diff --git a/.github/workflows/graalwasm-micronaut-excelize.yml b/.github/workflows/graalwasm-micronaut-excelize.yml new file mode 100644 index 00000000..de3eb604 --- /dev/null +++ b/.github/workflows/graalwasm-micronaut-excelize.yml @@ -0,0 +1,42 @@ +name: Test GraalWasm Micronaut Excelize Demo + +on: + push: + paths: + - 'graalwasm/graalwasm-micronaut-excelice/**' + - '.github/workflows/graalwasm-micronaut-excelice.yml' + pull_request: + paths: + - 'graalwasm/graalwasm-micronaut-excelice/**' + - '.github/workflows/graalwasm-micronaut-excelice.yml' + workflow_dispatch: + +permissions: + contents: read + +jobs: + run: + name: 'graalwasm-micronaut-excelice' + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + + - uses: graalvm/setup-graalvm@v1 + with: + java-version: '24.0.0' + distribution: 'graalvm' + github-token: ${{ secrets.GITHUB_TOKEN }} + cache: 'maven' + + - name: Package 'graalwasm-micronaut-excelice' + run: | + cd graalwasm/graalwasm-micronaut-excelice + ./mvnw --no-transfer-progress clean package + + - name: Run and Test Excelize App + run: | + cd graalwasm/graalwasm-micronaut-excelice + ./mvnw test & + sleep 10 + curl --fail-with-body --silent --dump-header - -o /dev/null http://localhost:8080 diff --git a/graalwasm/graalwasm-onnx-runtime/.gitignore b/graalwasm/graalwasm-onnx-runtime/.gitignore new file mode 100644 index 00000000..5ff6309b --- /dev/null +++ b/graalwasm/graalwasm-onnx-runtime/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/graalwasm/graalwasm-onnx-runtime/README.md b/graalwasm/graalwasm-onnx-runtime/README.md new file mode 100644 index 00000000..17d9720f --- /dev/null +++ b/graalwasm/graalwasm-onnx-runtime/README.md @@ -0,0 +1,21 @@ +### ONNX-WASM on GraalVM + +This project is a GraalVM-based reimplementation of the [ONNX Runtime Web Quick Start Demo](https://github.com/microsoft/onnxruntime-inference-examples/blob/main/js/quick-start_onnxruntime-web-script-tag/index.html) +provided by Microsoft. + +It demonstrates how to run ONNX models using the onnxruntime-web package inside a Java application via GraalVM Polyglot features. The core idea is to evaluate ONNX models entirely in the browser or on the JVM using WebAssembly (WASM) and JavaScript, tightly integrated with Java code. + + +### Technologies Used + +GraalVM (Java + JavaScript + WASM support) +onnxruntime-web (ONNX Runtime WASM backend) +Java (with Maven or Gradle) +Polyglot Context (GraalVM) +WASM + JavaScript bridge + +### How It Works + +Java loads a JavaScript wrapper (ort.js) that utilizes onnxruntime-web. +ONNX model is passed as a buffer or loaded inside JS using polyglot exports. +Inference is triggered through JavaScript and results returned to Java via Polyglot. diff --git a/graalwasm/graalwasm-onnx-runtime/dependency-reduced-pom.xml b/graalwasm/graalwasm-onnx-runtime/dependency-reduced-pom.xml new file mode 100644 index 00000000..1fc8b99d --- /dev/null +++ b/graalwasm/graalwasm-onnx-runtime/dependency-reduced-pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + org.example + onnx + 1.0-SNAPSHOT + + + + maven-compiler-plugin + 3.13.0 + + 17 + 17 + + + org.openjdk.jmh + jmh-generator-annprocess + 1.37 + + + + + + maven-shade-plugin + 3.5.1 + + + package + + shade + + + + + org.openjdk.jmh.Main + + + + + + + + + + + org.graalvm.polyglot + wasm + 24.2.0 + pom + compile + + + wasm + org.graalvm.wasm + + + + + + 23 + 23 + UTF-8 + + diff --git a/graalwasm/graalwasm-onnx-runtime/pom.xml b/graalwasm/graalwasm-onnx-runtime/pom.xml new file mode 100644 index 00000000..823d2f2e --- /dev/null +++ b/graalwasm/graalwasm-onnx-runtime/pom.xml @@ -0,0 +1,87 @@ + + + 4.0.0 + + org.example + onnx + 1.0-SNAPSHOT + + + 25 + 25 + UTF-8 + 25.0.0-SNAPSHOT + + + + org.graalvm.polyglot + polyglot + ${graal.languages.version} + + + org.graalvm.polyglot + js + ${graal.languages.version} + pom + + + org.graalvm.polyglot + wasm + ${graal.languages.version} + pom + + + org.openjdk.jmh + jmh-core + 1.37 + + + org.openjdk.jmh + jmh-generator-annprocess + 1.37 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + 17 + 17 + + + org.openjdk.jmh + jmh-generator-annprocess + 1.37 + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.5.1 + + + package + shade + + + + org.openjdk.jmh.Main + + + + + + + + + + + + \ No newline at end of file diff --git a/graalwasm/graalwasm-onnx-runtime/src/main/java/org/example/Main.java b/graalwasm/graalwasm-onnx-runtime/src/main/java/org/example/Main.java new file mode 100644 index 00000000..88ba3d33 --- /dev/null +++ b/graalwasm/graalwasm-onnx-runtime/src/main/java/org/example/Main.java @@ -0,0 +1,67 @@ +package org.example; + +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Source; +import org.graalvm.polyglot.Value; +import org.graalvm.polyglot.proxy.ProxyExecutable; + + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; + +import java.util.Map; +import java.util.Objects; + + +public class Main { + public static Map getLanguageOptions() { + Map options = new HashMap<>(); + options.put("engine.CompilationFailureAction", "Diagnose"); + options.put("js.webassembly", "true"); + options.put("js.commonjs-require", "true"); + return options; + } + public static void main(String[] args) throws IOException { + Context context = Context.newBuilder("js","wasm") + .options(getLanguageOptions()) + .allowAllAccess(true) + .build(); + byte[] wasmBinary = Files.readAllBytes(Paths.get("src/main/resources/ort-wasm.wasm")); + context.getBindings("js").putMember("modelWasmBuffer",wasmBinary); + context.eval("js",""" + if (typeof performance === 'undefined') { + globalThis.performance = { + now: () => Date.now() + }; + } + globalThis.self = globalThis; + """); + context.eval(Source.newBuilder("js", Objects.requireNonNull(Main.class.getResource("/ort.js"))) + .build()); + byte[] modelData = Files.readAllBytes(Paths.get("src/main/resources/modeel.onnx")); + + context.eval(Source.newBuilder("js", Objects.requireNonNull(Main.class.getResource("/script.js"))) + .build()); + int [] DataX = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + int [] DataY = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120}; + + GenerateFunction genratedFunction = context.getBindings("js").getMember("predict").as(GenerateFunction.class); + Prediction prediction = genratedFunction.apply(modelData, DataX , DataY); + prediction.then(result -> { + + System.out.println("results from java side : "+result[0].getArrayElement(0).asInt()); + return null; + }); + } + + @FunctionalInterface + public interface GenerateFunction { + Prediction apply(byte[] model , int [] DataX , int [] DataY); + } + + public interface Prediction { + void then(ProxyExecutable callback); + } +} \ No newline at end of file diff --git a/graalwasm/graalwasm-onnx-runtime/src/main/java/org/example/MainBenchmark.java b/graalwasm/graalwasm-onnx-runtime/src/main/java/org/example/MainBenchmark.java new file mode 100644 index 00000000..747b165d --- /dev/null +++ b/graalwasm/graalwasm-onnx-runtime/src/main/java/org/example/MainBenchmark.java @@ -0,0 +1,7 @@ +package org.example; + +public class MainBenchmark { + public static void main(String[] args) throws Exception { + org.openjdk.jmh.Main.main(args); + } +} diff --git a/graalwasm/graalwasm-onnx-runtime/src/main/java/org/example/OnnxBenchmark.java b/graalwasm/graalwasm-onnx-runtime/src/main/java/org/example/OnnxBenchmark.java new file mode 100644 index 00000000..e429a527 --- /dev/null +++ b/graalwasm/graalwasm-onnx-runtime/src/main/java/org/example/OnnxBenchmark.java @@ -0,0 +1,31 @@ +package org.example; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.concurrent.TimeUnit; + +@Warmup(iterations = 6, time = 10) +@Measurement(iterations = 6, time = 30) +@Fork(1) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Benchmark) +public class OnnxBenchmark { + + private OnnxRunner runner; + private byte[] modelData; + + @Setup(Level.Trial) + public void setup() throws Exception { + runner = new OnnxRunner(); + modelData = Files.readAllBytes(Paths.get("src/main/resources/modeel.onnx")); + } + + @Benchmark + public void benchmarkPredict(Blackhole blackhole) { + runner.predict(modelData,blackhole); + } +} diff --git a/graalwasm/graalwasm-onnx-runtime/src/main/java/org/example/OnnxRunner.java b/graalwasm/graalwasm-onnx-runtime/src/main/java/org/example/OnnxRunner.java new file mode 100644 index 00000000..d4a08ca8 --- /dev/null +++ b/graalwasm/graalwasm-onnx-runtime/src/main/java/org/example/OnnxRunner.java @@ -0,0 +1,52 @@ +package org.example; + +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Source; +import org.graalvm.polyglot.Value; +import org.graalvm.polyglot.proxy.ProxyExecutable; +import org.openjdk.jmh.infra.Blackhole; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class OnnxRunner { + private final Context context; + + public OnnxRunner() throws IOException { + + context = Context.newBuilder("js", "wasm") + .options(Main.getLanguageOptions()) + .allowAllAccess(true) + .build(); + + byte[] wasmBinary = Files.readAllBytes(Paths.get("src/main/resources/ort-wasm.wasm")); + context.getBindings("js").putMember("modelWasmBuffer", wasmBinary); + + context.eval("js", """ + if (typeof performance === 'undefined') { + globalThis.performance = { + now: () => Date.now() + }; + } + globalThis.self = globalThis; + """); + + context.eval(Source.newBuilder("js", Objects.requireNonNull(Main.class.getResource("/ort.js"))).build()); + context.eval(Source.newBuilder("js", Objects.requireNonNull(Main.class.getResource("/script.js"))).build()); + } + + int [] DataX = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; + int [] DataY = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120}; + + public void predict(byte[] modelData, Blackhole blackhole) { + Main.GenerateFunction genratedFunction = context.getBindings("js").getMember("predict").as(Main.GenerateFunction.class); + Main.Prediction prediction = genratedFunction.apply(modelData,DataX,DataY); + prediction.then(result -> { + blackhole.consume(result[0].getArrayElement(0).asInt()); + return null; + });} +} diff --git a/graalwasm/graalwasm-onnx-runtime/src/main/resources/house_price_model.onnx b/graalwasm/graalwasm-onnx-runtime/src/main/resources/house_price_model.onnx new file mode 100644 index 00000000..6bd90fa1 Binary files /dev/null and b/graalwasm/graalwasm-onnx-runtime/src/main/resources/house_price_model.onnx differ diff --git a/graalwasm/graalwasm-onnx-runtime/src/main/resources/img.png b/graalwasm/graalwasm-onnx-runtime/src/main/resources/img.png new file mode 100644 index 00000000..2deef834 Binary files /dev/null and b/graalwasm/graalwasm-onnx-runtime/src/main/resources/img.png differ diff --git a/graalwasm/graalwasm-onnx-runtime/src/main/resources/modeel.onnx b/graalwasm/graalwasm-onnx-runtime/src/main/resources/modeel.onnx new file mode 100644 index 00000000..088124bd --- /dev/null +++ b/graalwasm/graalwasm-onnx-runtime/src/main/resources/modeel.onnx @@ -0,0 +1,16 @@ + backend-test:b + +a +bc"MatMultest_matmul_2dZ +a +  + +Z +b +  + +b +c +  + +B \ No newline at end of file diff --git a/graalwasm/graalwasm-onnx-runtime/src/main/resources/ort-wasm.wasm b/graalwasm/graalwasm-onnx-runtime/src/main/resources/ort-wasm.wasm new file mode 100644 index 00000000..d1857ece Binary files /dev/null and b/graalwasm/graalwasm-onnx-runtime/src/main/resources/ort-wasm.wasm differ diff --git a/graalwasm/graalwasm-onnx-runtime/src/main/resources/ort.js b/graalwasm/graalwasm-onnx-runtime/src/main/resources/ort.js new file mode 100644 index 00000000..d89bf771 --- /dev/null +++ b/graalwasm/graalwasm-onnx-runtime/src/main/resources/ort.js @@ -0,0 +1,33277 @@ +/*! +* ONNX Runtime Web v1.15.1 +* 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.webgpu = {}; + 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) { + 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. +// 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'], +]); +// the following code allows delaying execution of BigInt checking. This allows lazy initialization for +// NUMERIC_TENSOR_TYPE_TO_TYPEDARRAY_MAP and NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP, which allows BigInt polyfill +// if available. +let isBigIntChecked = false; +const checkBigInt = () => { + if (!isBigIntChecked) { + isBigIntChecked = true; + const isBigInt64ArrayAvailable = typeof BigInt64Array !== 'undefined' && typeof BigInt64Array.from === 'function'; + const isBigUint64ArrayAvailable = typeof BigUint64Array !== 'undefined' && typeof BigUint64Array.from === 'function'; + 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) { + checkBigInt(); + 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'); + } + if (options.tensorLayout === 'NHWC') { + throw new Error('NHWC Tensor layout is not supported yet'); + } + const { height, width } = options; + const norm = options.norm ?? { mean: 255, bias: 0 }; + let normMean; + let normBias; + if (typeof (norm.mean) === 'number') { + normMean = [norm.mean, norm.mean, norm.mean, norm.mean]; + } + else { + normMean = [norm.mean[0], norm.mean[1], norm.mean[2], norm.mean[3] ?? 255]; + } + if (typeof (norm.bias) === 'number') { + normBias = [norm.bias, norm.bias, norm.bias, norm.bias]; + } + else { + normBias = [norm.bias[0], norm.bias[1], norm.bias[2], norm.bias[3] ?? 0]; + } + 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 stride = height * width; + const float32Data = outputformat === 'RGBA' ? new Float32Array(stride * 4) : new Float32Array(stride * 3); + // Default pointer assignments + let step = 4, rImagePointer = 0, gImagePointer = 1, bImagePointer = 2, aImagePointer = 3; + let rTensorPointer = 0, gTensorPointer = stride, bTensorPointer = stride * 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 = stride * 3; + } + else if (outputformat === 'RBG') { + rTensorPointer = 0; + bTensorPointer = stride; + gTensorPointer = stride * 2; + } + else if (outputformat === 'BGR') { + bTensorPointer = 0; + gTensorPointer = stride; + rTensorPointer = stride * 2; + } + for (let i = 0; i < stride; i++, rImagePointer += step, bImagePointer += step, gImagePointer += step, aImagePointer += step) { + float32Data[rTensorPointer++] = (buffer[rImagePointer] + normBias[0]) / normMean[0]; + float32Data[gTensorPointer++] = (buffer[gImagePointer] + normBias[1]) / normMean[1]; + float32Data[bTensorPointer++] = (buffer[bImagePointer] + normBias[2]) / normMean[2]; + if (aTensorPointer !== -1 && aImagePointer !== -1) { + float32Data[aTensorPointer++] = (buffer[aImagePointer] + normBias[3]) / normMean[3]; + } + } + // 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 isString = typeof image === 'string'; + let data; + let tensorConfig = options ?? {}; + // filling and checking image configuration options + if (isHTMLImageEle) { + // HTMLImageElement - image object - format is RGBA by default + const canvas = document.createElement('canvas'); + canvas.width = image.width; + canvas.height = image.height; + const pixels2DContext = canvas.getContext('2d'); + if (pixels2DContext != null) { + let height = image.height; + let width = image.width; + 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; + } + pixels2DContext.drawImage(image, 0, 0); + 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 (isString) { + 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) { + if (options.height !== undefined && options.height !== canvas.height) { + throw new Error('Image input config height doesn\'t match height'); + } + else { + tensorConfig.height = canvas.height; + } + if (options.width !== undefined && options.width !== canvas.width) { + throw new Error('Image input config width doesn\'t match 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'); + } + } + toDataURL(options) { + const canvas = document.createElement('canvas'); + canvas.width = this.dims[3]; + canvas.height = this.dims[2]; + const pixels2DContext = canvas.getContext('2d'); + if (pixels2DContext != null) { + // Default values for height and width & format + let width; + let height; + if (options?.tensorLayout !== undefined && options.tensorLayout === 'NHWC') { + width = this.dims[2]; + height = this.dims[3]; + } + else { // Default layout is NCWH + width = this.dims[3]; + height = this.dims[2]; + } + const inputformat = options?.format !== undefined ? options.format : 'RGB'; + const norm = options?.norm; + let normMean; + let normBias; + if (norm === undefined || norm.mean === undefined) { + normMean = [255, 255, 255, 255]; + } + else { + if (typeof (norm.mean) === 'number') { + normMean = [norm.mean, norm.mean, norm.mean, norm.mean]; + } + else { + normMean = [norm.mean[0], norm.mean[1], norm.mean[2], 0]; + if (norm.mean[3] !== undefined) { + normMean[3] = norm.mean[3]; + } + } + } + if (norm === undefined || norm.bias === undefined) { + normBias = [0, 0, 0, 0]; + } + else { + if (typeof (norm.bias) === 'number') { + normBias = [norm.bias, norm.bias, norm.bias, norm.bias]; + } + else { + normBias = [norm.bias[0], norm.bias[1], norm.bias[2], 0]; + if (norm.bias[3] !== undefined) { + normBias[3] = norm.bias[3]; + } + } + } + const stride = height * width; + // Default pointer assignments + let rTensorPointer = 0, gTensorPointer = stride, bTensorPointer = stride * 2, aTensorPointer = -1; + // Updating the pointer assignments based on the input image format + if (inputformat === 'RGBA') { + rTensorPointer = 0; + gTensorPointer = stride; + bTensorPointer = stride * 2; + aTensorPointer = stride * 3; + } + else if (inputformat === 'RGB') { + rTensorPointer = 0; + gTensorPointer = stride; + bTensorPointer = stride * 2; + } + else if (inputformat === 'RBG') { + rTensorPointer = 0; + bTensorPointer = stride; + gTensorPointer = stride * 2; + } + for (let i = 0; i < height; i++) { + for (let j = 0; j < width; j++) { + const R = (this.data[rTensorPointer++] - normBias[0]) * normMean[0]; // R value + const G = (this.data[gTensorPointer++] - normBias[1]) * normMean[1]; // G value + const B = (this.data[bTensorPointer++] - normBias[2]) * normMean[2]; // B value + const A = aTensorPointer === -1 ? + 255 : + (this.data[aTensorPointer++] - normBias[3]) * normMean[3]; // A value + // eslint-disable-next-line @typescript-eslint/restrict-plus-operands + pixels2DContext.fillStyle = 'rgba(' + R + ',' + G + ',' + B + ',' + A + ')'; + pixels2DContext.fillRect(j, i, 1, 1); + } + } + return canvas.toDataURL(); + } + else { + throw new Error('Can not access image data'); + } + } + toImageData(options) { + const pixels2DContext = document.createElement('canvas').getContext('2d'); + let image; + if (pixels2DContext != null) { + // Default values for height and width & format + let width; + let height; + let channels; + if (options?.tensorLayout !== undefined && options.tensorLayout === 'NHWC') { + width = this.dims[2]; + height = this.dims[1]; + channels = this.dims[3]; + } + else { // Default layout is NCWH + width = this.dims[3]; + height = this.dims[2]; + channels = this.dims[1]; + } + const inputformat = options !== undefined ? (options.format !== undefined ? options.format : 'RGB') : 'RGB'; + const norm = options?.norm; + let normMean; + let normBias; + if (norm === undefined || norm.mean === undefined) { + normMean = [255, 255, 255, 255]; + } + else { + if (typeof (norm.mean) === 'number') { + normMean = [norm.mean, norm.mean, norm.mean, norm.mean]; + } + else { + normMean = [norm.mean[0], norm.mean[1], norm.mean[2], 255]; + if (norm.mean[3] !== undefined) { + normMean[3] = norm.mean[3]; + } + } + } + if (norm === undefined || norm.bias === undefined) { + normBias = [0, 0, 0, 0]; + } + else { + if (typeof (norm.bias) === 'number') { + normBias = [norm.bias, norm.bias, norm.bias, norm.bias]; + } + else { + normBias = [norm.bias[0], norm.bias[1], norm.bias[2], 0]; + if (norm.bias[3] !== undefined) { + normBias[3] = norm.bias[3]; + } + } + } + const stride = 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 = stride, bTensorPointer = stride * 2, aTensorPointer = -1; + // Updating the pointer assignments based on the input image format + if (inputformat === 'RGBA') { + rTensorPointer = 0; + gTensorPointer = stride; + bTensorPointer = stride * 2; + aTensorPointer = stride * 3; + } + else if (inputformat === 'RGB') { + rTensorPointer = 0; + gTensorPointer = stride; + bTensorPointer = stride * 2; + } + else if (inputformat === 'RBG') { + rTensorPointer = 0; + bTensorPointer = stride; + gTensorPointer = stride * 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[0]) * normMean[0]; // R value + image.data[gImagePointer] = (this.data[gTensorPointer++] - normBias[1]) * normMean[1]; // G value + image.data[bImagePointer] = (this.data[bTensorPointer++] - normBias[2]) * normMean[2]; // B value + image.data[aImagePointer] = aTensorPointer === -1 ? + 255 : + (this.data[aTensorPointer++] - normBias[3]) * normMean[3]; // 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/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(); + //console.log(new Uint8Array(globalThis.modelBuffer).length) + 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); + if (false) {} + (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 lrn_1 = __webpack_require__(/*! ./ops/lrn */ "./lib/onnxjs/backends/webgl/ops/lrn.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], + ['LRN', '', '1+', lrn_1.lrn, lrn_1.parseLrnAttributes], + ['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/lrn.ts": +/*!**********************************************!*\ + !*** ./lib/onnxjs/backends/webgl/ops/lrn.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.createLrnProgramInfoLoader = exports.parseLrnAttributes = exports.lrn = 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 lrn = (inferenceHandler, inputs, attributes) => { + validateInputs(inputs); + // if (inferenceHandler.session.pack) { + // return [inferenceHandler.run(createPackedLrnProgramInfoLoader(inferenceHandler, inputs, attributes), + // inputs)]; + // } else { + return [inferenceHandler.run(createLrnProgramInfoLoader(inputs, attributes), inputs)]; + //} +}; +exports.lrn = lrn; +const parseLrnAttributes = (node) => { + const alpha = node.attributes.getFloat('alpha', 0.0001); + const beta = node.attributes.getFloat('beta', 0.75); + const bias = node.attributes.getFloat('bias', 1.0); + const size = node.attributes.getInt('size'); + return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ alpha, beta, bias, size }); +}; +exports.parseLrnAttributes = parseLrnAttributes; +const lrnProgramMetadata = { + name: 'LRN', + inputNames: ['X'], + inputTypes: [types_1.TextureType.unpacked] +}; +function createLrnProgramInfo(inputs, attributes) { + const C = inputs[0].dims[1]; + const rank = inputs[0].dims.length; + const from = -Math.floor((attributes.size - 1) / 2); + const to = Math.ceil((attributes.size - 1) / 2); + const alpha = `float(${attributes.alpha}) / float(${attributes.size})`; + const bias = `float(${attributes.bias})`; + const beta = `float(${attributes.beta})`; + const shaderSource = ` + float process(int indices[${rank}]) { + int c = indices[1]; + float x = _X(indices); + float square_sum = 0.0; + + for (int i = ${from}; i <= ${to}; i++) { + int idx = c + i; + if (c >= 0 && c < ${C}) { + indices[1] = idx; + float j = _X(indices); + square_sum += j * j; + } + } + return x / pow(${bias} + ${alpha} * square_sum, ${beta}); + }`; + return Object.assign(Object.assign({}, lrnProgramMetadata), { cacheHint: attributes.cacheKey, output: { dims: inputs[0].dims, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource }); +} +function createLrnProgramInfoLoader(inputs, attributes) { + return Object.assign(Object.assign({}, lrnProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createLrnProgramInfo(inputs, attributes) }); +} +exports.createLrnProgramInfoLoader = createLrnProgramInfoLoader; +const validateInputs = (inputs) => { + if (!inputs || inputs.length !== 1) { + throw new Error('LRN requires 1 input.'); + } + if (inputs[0].dims.length !== 4) { + throw new Error('currently only support LRN for input with "NCHW" format'); + } + if (inputs[0].type !== 'float32') { + throw new Error('input should be float type'); + } +}; + + +/***/ }), + +/***/ "./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) => { + // TODO: support Reduce* operators with 2 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 + // The graph is represented using these two arrays + // this._nodes - Array holding the kernels to execute - each entry is a kernel pointing to this._allData + // this._allData - hold 2 fields - to [] & from - these feileds hold the graph map for inputs and outputs per node + // newIndices - remapping the graph after reading the flag 'executeNode' + const newIndices = new Array(this._nodes.length, 0); + let nodePossition = 0; + for (let i = 0; i < this._nodes.length; i++) { + // giving new indexes to the nodes based on execution flag + newIndices[i] = nodePossition; + if (this._nodes[i].executeNode) { + if (nodePossition !== i) { + this._nodes[nodePossition] = this._nodes[i]; + } + nodePossition++; + } + else { + // delete all output values + this._nodes[i].outputs.forEach(ind => { + this._allData[ind]._from = -2; + }); + } + } + // removing the unused nodes + this._nodes.splice(nodePossition, this._nodes.length - nodePossition); + // Updating this._allData according to the new this._nodes + for (let i = 0; i < this._allData.length; i++) { + const currentData = this._allData[i]; + if (currentData._from !== undefined && currentData._from !== -1 && currentData._from !== -2) { + currentData._from = newIndices[currentData._from]; + } + for (let j = 0; j < currentData._to.length; j++) { + if (currentData._to[j] >= 0) { + currentData._to[j] = newIndices[currentData._to[j]]; + } + else { + throw new Error('Trying to update a removed node'); + } + } + } + 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 + for (let i = 0; i < node.inputs.length; i++) { + const delIndex = this._allData[node.inputs[i]].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[node.inputs[i]].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; + } + async 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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 + 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/jsep/backend-webgpu.ts": +/*!*****************************************!*\ + !*** ./lib/wasm/jsep/backend-webgpu.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.WebGpuBackend = void 0; +const onnxruntime_common_1 = __webpack_require__(/*! onnxruntime-common */ "../common/dist/lib/index.js"); +const log_1 = __webpack_require__(/*! ./log */ "./lib/wasm/jsep/log.ts"); +const gpu_data_manager_1 = __webpack_require__(/*! ./webgpu/gpu-data-manager */ "./lib/wasm/jsep/webgpu/gpu-data-manager.ts"); +const op_resolve_rules_1 = __webpack_require__(/*! ./webgpu/op-resolve-rules */ "./lib/wasm/jsep/webgpu/op-resolve-rules.ts"); +const program_manager_1 = __webpack_require__(/*! ./webgpu/program-manager */ "./lib/wasm/jsep/webgpu/program-manager.ts"); +/** + * get a unique key representing the program from the program info,input shapes and types. + * + * @returns a unique key is a shorter string than the shader source, which contains all the information to identify a + * program. if the key is the same, the program shader source should be the same, so we can reuse the program. + * + */ +const getProgramInfoUniqueKey = (programInfo, inputTensorShapes, inputGpuDataTypes) => { + const inputTensorShapesToString = inputTensorShapes.map(d => `${d.join(',')}`).join('_'); + const inputGpuDataTypesToString = inputGpuDataTypes.join('_'); + let key = programInfo.name; + if (programInfo.cacheHint) { + key += '[' + programInfo.cacheHint + ']'; + } + key += ':' + inputTensorShapesToString + ';' + inputGpuDataTypesToString; + return key; +}; +/** + * this class is designed to store status and being used as a singleton for JSEP. It will be passed to jsepInit() as + * the first parameter so that it is stored for future use. + */ +class WebGpuBackend { + constructor() { + /** + * representing the kernel ID of which is currently being computed (CPU code perspective). + * `null` means no kernel is being computed. + * only one kernel can be computed at a moment. + */ + this.currentKernelId = null; + this.commandEncoder = null; + this.computePassEncoder = null; + this.pendingDispatchNumber = 0; + this.profilingEnabled = false; + } + /** + * get the custom data of the current kernel + */ + get currentKernelCustomData() { + if (this.currentKernelId === null) { + throw new Error('currentKernelCustomData(): currentKernelId is null. (should not happen)'); + } + let data = this.kernelCustomData.get(this.currentKernelId); + if (!data) { + data = {}; + this.kernelCustomData.set(this.currentKernelId, data); + } + return data; + } + async initialize() { + if (!navigator.gpu) { + // WebGPU is not available. + throw new Error('WebGpuBackend: WebGPU is not available.'); + } + const adapter = await navigator.gpu.requestAdapter(); + if (!adapter) { + throw new Error('WebGpuBackend: Failed to get GPU adapter.'); + } + const deviceDescriptor = { + requiredLimits: { + maxComputeWorkgroupStorageSize: adapter.limits.maxComputeWorkgroupStorageSize, + maxComputeWorkgroupsPerDimension: adapter.limits.maxComputeWorkgroupsPerDimension, + maxStorageBufferBindingSize: adapter.limits.maxStorageBufferBindingSize, + } + }; + // WebGPU Spec: Timestamp Queries Inside Passes + // https://github.com/gpuweb/gpuweb/blob/main/proposals/timestamp-query-inside-passes.md + if (adapter.features.has('timestamp-query-inside-passes') && onnxruntime_common_1.env.webgpu.profilingMode === 'default') { + this.profilingEnabled = true; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + deviceDescriptor.requiredFeatures = ['timestamp-query-inside-passes']; + } + this.device = await adapter.requestDevice(deviceDescriptor); + this.gpuDataManager = (0, gpu_data_manager_1.createGpuDataManager)(this); + this.programManager = new program_manager_1.ProgramManager(this); + this.kernels = new Map(); + this.kernelPersistentData = new Map(); + this.kernelCustomData = new Map(); + // TODO: set up flags + this.device.onuncapturederror = ev => { + if (ev.error instanceof GPUValidationError) { + // eslint-disable-next-line no-console + console.error(`An uncaught WebGPU validation error was raised: ${ev.error.message}`); + } + }; + if (this.profilingEnabled) { + this.profilingQuerySet = this.device.createQuerySet({ + type: 'timestamp', + count: 2, + }); + } + } + dispose() { + // currently, we do not do anything in this function. In all known use cases, we don't have the requirement to + // actually dispose the WebGpuBackend instance, because it's always used as a singleton. + // + // revisit this place if we get real requirement to dispose the instance. + } + getCommandEncoder() { + if (!this.commandEncoder) { + this.commandEncoder = this.device.createCommandEncoder(); + } + return this.commandEncoder; + } + getComputePassEncoder() { + if (!this.computePassEncoder) { + this.computePassEncoder = this.getCommandEncoder().beginComputePass(); + } + return this.computePassEncoder; + } + endComputePass() { + if (this.computePassEncoder) { + this.computePassEncoder.end(); + this.computePassEncoder = null; + } + } + flush() { + this.endComputePass(); + this.device.queue.submit([this.getCommandEncoder().finish()]); + this.gpuDataManager.refreshPendingBuffers(); + this.commandEncoder = null; + this.pendingDispatchNumber = 0; + } + /** + * run a WebGPU program. + * @param program either a ProgramInfo instance containing metadata including the shader code, or a function that + * can be called and return a ProgramInfo instance + * @param inputs a TensorView array. each element represents a value already exists in GPU. + * @param outputIndices an indices array. each element can be either -1 (temporary data), -2 (persistent data) or an + * index to the kernel's output. + * @param createKernelOutput a callback function that create a value to kernel's output with the given index + * @param createIntermediateOutput a callback function that create a value as a intermediate value, either temporary + * or persistent (owned by the current kernel) + * @returns a TensorView array representing the result. + */ + run(program, inputs, outputIndices, createKernelOutput, createIntermediateOutput) { + if (inputs.length !== program.inputTypes.length) { + throw new Error(`Input size must be equal to ${program.inputTypes.length}.`); + } + // create info for inputs + const inputDatas = []; + for (let i = 0; i < inputs.length; ++i) { + const gpuData = this.gpuDataManager.get(inputs[i].data); + if (!gpuData) { + throw new Error(`no GPU data for input: ${inputs[i].data}`); + } + inputDatas[i] = gpuData; + } + const key = getProgramInfoUniqueKey(program, inputs.map(i => i.dims), inputDatas.map(i => i.type)); + let artifact = this.programManager.getArtifact(key); + const programInfo = artifact ? + artifact.programInfo : + (typeof program.get === 'function' ? program.get() : + program); + // check output indices + const validatedOutputIndices = outputIndices.length === 0 ? programInfo.outputs.map((_, i) => i) : outputIndices; + if (validatedOutputIndices.length !== programInfo.outputs.length) { + throw new Error(`Output size ${validatedOutputIndices.length} must be equal to ${programInfo.outputs.length}.`); + } + // create info for outputs + const outputTensorViews = []; + const outputDatas = []; + for (let i = 0; i < programInfo.outputs.length; ++i) { + // value -1 and -2 are used for creating temporary and persistent outputs. so -2, -1 and 0, 1, 2, ... are valid + // output indices. see type definition of ComputeContextInputsOutputsMapping for more details. + if (!Number.isInteger(validatedOutputIndices[i]) || validatedOutputIndices[i] < -2 || + validatedOutputIndices[i] >= programInfo.outputs.length) { + throw new Error(`Invalid output index: ${validatedOutputIndices[i]}`); + } + const isTemporary = validatedOutputIndices[i] === -1; + const isPersistent = validatedOutputIndices[i] === -2; + const tensorView = (isTemporary || isPersistent) ? + createIntermediateOutput(programInfo.outputs[i].dataType, programInfo.outputs[i].dims) : + createKernelOutput(validatedOutputIndices[i], programInfo.outputs[i].dataType, programInfo.outputs[i].dims); + const gpuData = this.gpuDataManager.get(tensorView.data); + if (!gpuData) { + throw new Error(`no GPU data for output: ${tensorView.data}`); + } + if (isTemporary) { + this.temporaryData.push(gpuData); + } + if (isPersistent) { + let persistentData = this.kernelPersistentData.get(this.currentKernelId); + if (!persistentData) { + persistentData = []; + this.kernelPersistentData.set(this.currentKernelId, persistentData); + } + persistentData.push(gpuData); + } + outputTensorViews.push(tensorView); + outputDatas.push(gpuData); + } + const normalizedDispatchGroup = this.programManager.normalizeDispatchGroupSize(programInfo.dispatchGroup(inputs)); + if (!artifact) { + artifact = this.programManager.build(programInfo, normalizedDispatchGroup); + this.programManager.setArtifact(key, artifact); + } + (0, log_1.LOG_DEBUG)('info', () => `[ProgramManager] run "${programInfo.name}" (key=${key}) with ${normalizedDispatchGroup[0]}x${normalizedDispatchGroup[1]}x${normalizedDispatchGroup[2]}`); + this.programManager.run(artifact, inputDatas, outputDatas, normalizedDispatchGroup); + return outputTensorViews; + } + upload(gpuDataId, data) { + this.gpuDataManager.upload(gpuDataId, data); + } + memcpy(src, dst) { + this.gpuDataManager.memcpy(src, dst); + } + async download(gpuDataId, getTargetBuffer) { + const arrayBuffer = await this.gpuDataManager.download(gpuDataId); + // the underlying buffer may be changed after the async function is called. so we use a getter function to make sure + // the buffer is up-to-date. + const data = getTargetBuffer(); + data.set(new Uint8Array(arrayBuffer)); + } + alloc(size) { + return this.gpuDataManager.create(size).id; + } + free(ptr) { + return this.gpuDataManager.release(ptr); + } + createKernel(name, kernelId, attribute) { + const op = op_resolve_rules_1.WEBGPU_OP_RESOLVE_RULES.get(name); + if (!op) { + throw new Error(`kernel not implemented: ${name}`); + } + this.kernels.set(kernelId, [name, op[0], [op[1], attribute]]); + } + releaseKernel(kernelId) { + const persistentData = this.kernelPersistentData.get(kernelId); + if (persistentData) { + for (const data of persistentData) { + this.gpuDataManager.release(data.id); + } + this.kernelPersistentData.delete(kernelId); + } + this.kernelCustomData.delete(kernelId); + this.kernels.delete(kernelId); + } + computeKernel(kernelId, context) { + const kernel = this.kernels.get(kernelId); + if (!kernel) { + throw new Error(`kernel not created: ${kernelId}`); + } + const [name, kernelEntry, attributes] = kernel; + if (this.currentKernelId !== null) { + throw new Error(`kernel "${name}" is not allowed to be called recursively`); + } + this.currentKernelId = kernelId; + // parse attributes if necessary + if (attributes[0]) { + attributes[1] = attributes[0](attributes[1]); + attributes[0] = undefined; + } + (0, log_1.LOG_DEBUG)('info', () => `[WebGPU] Start to run kernel "${name}"...`); + this.temporaryData = []; + try { + kernelEntry(context, attributes[1]); + return 0; // ORT_OK + } + catch (e) { + (0, log_1.LOG_DEBUG)('warning', `[WebGPU] Kernel "${name}" failed. Error: ${e}`); + return 1; // ORT_FAIL + } + finally { + for (const data of this.temporaryData) { + this.gpuDataManager.release(data.id); + } + this.temporaryData = []; + this.currentKernelId = null; + } + } +} +exports.WebGpuBackend = WebGpuBackend; + + +/***/ }), + +/***/ "./lib/wasm/jsep/init.ts": +/*!*******************************!*\ + !*** ./lib/wasm/jsep/init.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.init = void 0; +const wasm_common_1 = __webpack_require__(/*! ../wasm-common */ "./lib/wasm/wasm-common.ts"); +const backend_webgpu_1 = __webpack_require__(/*! ./backend-webgpu */ "./lib/wasm/jsep/backend-webgpu.ts"); +const log_1 = __webpack_require__(/*! ./log */ "./lib/wasm/jsep/log.ts"); +const util_1 = __webpack_require__(/*! ./util */ "./lib/wasm/jsep/util.ts"); +/* eslint-disable no-bitwise */ +class TensorViewImpl { + constructor(module, dataType, data, dims) { + this.module = module; + this.dataType = dataType; + this.data = data; + this.dims = dims; + } + getFloat32Array() { + return new Float32Array(this.module.HEAP8.buffer, this.data, util_1.ShapeUtil.size(this.dims)); + } + reshape(newDims) { + if (util_1.ShapeUtil.size(newDims) !== util_1.ShapeUtil.size(this.dims)) { + throw new Error('Invalid new shape'); + } + return new TensorViewImpl(this.module, this.dataType, this.data, newDims); + } +} +class ComputeContextImpl { + get customData() { + return this.backend.currentKernelCustomData; + } + constructor(module, backend, contextDataOffset) { + this.module = module; + this.backend = backend; + const heapU32 = module.HEAPU32; + // extract context data + let dataIndex = (contextDataOffset >> 2); + this.opKernelContext = heapU32[dataIndex++]; + const inputCount = heapU32[dataIndex++]; + const inputs = []; + for (let i = 0; i < inputCount; i++) { + const dataType = heapU32[dataIndex++]; + const data = heapU32[dataIndex++]; + const dim = heapU32[dataIndex++]; + const dims = []; + for (let d = 0; d < dim; d++) { + dims.push(heapU32[dataIndex++]); + } + inputs.push(new TensorViewImpl(module, dataType, data, dims)); + } + this.inputs = inputs; + } + compute(program, inputsOutputsMapping) { + var _a, _b, _c; + // prepare inputs. inputs should always be valid data. + const mappedInputs = (_b = (_a = inputsOutputsMapping === null || inputsOutputsMapping === void 0 ? void 0 : inputsOutputsMapping.inputs) === null || _a === void 0 ? void 0 : _a.map(i => typeof i === 'number' ? this.inputs[i] : i)) !== null && _b !== void 0 ? _b : this.inputs; + // prepare outputs. + const outputIndices = (_c = inputsOutputsMapping === null || inputsOutputsMapping === void 0 ? void 0 : inputsOutputsMapping.outputs) !== null && _c !== void 0 ? _c : []; + const createKernelOutput = (index, dataType, dims) => new TensorViewImpl(this.module, dataType, this.output(index, dims), dims); + const createTemporaryOutput = (dataType, dims) => { + const elementSize = (0, wasm_common_1.getTensorElementSize)(dataType); + if (!elementSize) { + throw new Error(`Unsupported data type: ${dataType}`); + } + const bufferSize = elementSize * util_1.ShapeUtil.size(dims); + return new TensorViewImpl(this.module, dataType, this.backend.gpuDataManager.create(bufferSize).id, dims); + }; + return this.backend.run(program, mappedInputs, outputIndices, createKernelOutput, createTemporaryOutput); + } + output(index, dims) { + const stack = this.module.stackSave(); + try { + const data = this.module.stackAlloc((1 + dims.length) * 4 /* sizeof(size_t) */); + let offset = data >> 2; + this.module.HEAPU32[offset++] = dims.length; + for (let i = 0; i < dims.length; i++) { + this.module.HEAPU32[offset++] = dims[i]; + } + return this.module._JsepOutput(this.opKernelContext, index, data); + } + finally { + this.module.stackRestore(stack); + } + } +} +const init = async (module) => { + const init = module.jsepInit; + if (init && navigator.gpu) { + const backend = new backend_webgpu_1.WebGpuBackend(); + await backend.initialize(); + init( + // backend + { backend }, + // jsepAlloc() + (size) => backend.alloc(size), + // jsepFree() + (ptr) => backend.free(ptr), + // jsepCopy(src, dst, size, isSourceGpu) + (src, dst, size, isSourceGpu = false) => { + if (isSourceGpu) { + (0, log_1.LOG_DEBUG)('verbose', () => `[WebGPU] jsepCopyGpuToGpu: src=${src}, dst=${dst}, size=${size}`); + backend.memcpy(src, dst); + } + else { + (0, log_1.LOG_DEBUG)('verbose', () => `[WebGPU] jsepCopyCpuToGpu: dataOffset=${src}, gpuDataId=${dst}, size=${size}`); + const data = module.HEAPU8.subarray(src, src + size); + backend.upload(dst, data); + } + }, + // jsepCopyAsync(src, dst, size) + async (gpuDataId, dataOffset, size) => { + (0, log_1.LOG_DEBUG)('verbose', () => `[WebGPU] jsepCopyGpuToCpu: gpuDataId=${gpuDataId}, dataOffset=${dataOffset}, size=${size}`); + await backend.download(gpuDataId, () => module.HEAPU8.subarray(dataOffset, dataOffset + size)); + }, + // jsepCreateKernel + (name, kernel, attribute) => backend.createKernel(name, kernel, attribute), + // jsepReleaseKernel + (kernel) => backend.releaseKernel(kernel), + // jsepRun + (kernel, contextDataOffset) => { + (0, log_1.LOG_DEBUG)('verbose', () => `[WebGPU] jsepRun: kernel=${kernel}, contextDataOffset=${contextDataOffset}`); + const context = new ComputeContextImpl(module, backend, contextDataOffset); + return backend.computeKernel(kernel, context); + }); + } +}; +exports.init = init; + + +/***/ }), + +/***/ "./lib/wasm/jsep/log.ts": +/*!******************************!*\ + !*** ./lib/wasm/jsep/log.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.LOG_DEBUG = exports.LOG = void 0; +const onnxruntime_common_1 = __webpack_require__(/*! onnxruntime-common */ "../common/dist/lib/index.js"); +const wasm_common_1 = __webpack_require__(/*! ../wasm-common */ "./lib/wasm/wasm-common.ts"); +const logLevelPrefix = ['V', 'I', 'W', 'E', 'F']; +const doLog = (level, message) => { + // eslint-disable-next-line no-console + console.log(`[${logLevelPrefix[level]},${new Date().toISOString()}]${message}`); +}; +/** + * A simple logging utility to log messages to the console. + */ +const LOG = (logLevel, msg) => { + const messageLevel = (0, wasm_common_1.logLevelStringToEnum)(logLevel); + const configLevel = (0, wasm_common_1.logLevelStringToEnum)(onnxruntime_common_1.env.logLevel); + if (messageLevel >= configLevel) { + doLog(messageLevel, typeof msg === 'function' ? msg() : msg); + } +}; +exports.LOG = LOG; +/** + * A simple logging utility to log messages to the console. Only logs when debug is enabled. + */ +const LOG_DEBUG = (...args) => { + if (onnxruntime_common_1.env.debug) { + (0, exports.LOG)(...args); + } +}; +exports.LOG_DEBUG = LOG_DEBUG; + + +/***/ }), + +/***/ "./lib/wasm/jsep/util.ts": +/*!*******************************!*\ + !*** ./lib/wasm/jsep/util.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.MAX_CLIP = exports.MIN_CLIP = exports.GemmUtil = exports.PoolConvUtil = exports.ShapeUtil = exports.BroadcastUtil = exports.MatMulUtil = void 0; +/* eslint-disable no-param-reassign */ +class MatMulUtil { + /** + * 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; + } + /** + * 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; + } +} +exports.BroadcastUtil = BroadcastUtil; +class ShapeUtil { + /** + * calculate the size (number of elements) + */ + static size(dims) { + return ShapeUtil.getSizeFromDimensionRange(dims, 0, dims.length); + } + /** + * calculate the size (number of elements) from the given 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); + } + /** + * calculate the size (number of elements) to the given 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); + } + /** + * calculate the size (number of elements) from and to the given axis [start, end) + */ + 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; + } + /** + * 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 !== null && tensorRank !== void 0 ? tensorRank : axes.length)); + } + /** + * 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]); + } +} +exports.ShapeUtil = ShapeUtil; +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, isChannelLast, 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 + (isChannelLast ? 1 : 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; +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; +exports.MIN_CLIP = -3.4028234663852886e+38; +exports.MAX_CLIP = 3.4028234663852886e+38; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/attribute-with-cache-key.ts": +/*!**********************************************************!*\ + !*** ./lib/wasm/jsep/webgpu/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; + } +} +/** + * create a new object from the given attribute, and add a cacheKey property to it + */ +const createAttributeWithCacheKey = (attribute) => new AttributeWithCacheKeyImpl(attribute); +exports.createAttributeWithCacheKey = createAttributeWithCacheKey; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/gpu-data-manager.ts": +/*!**************************************************!*\ + !*** ./lib/wasm/jsep/webgpu/gpu-data-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.createGpuDataManager = void 0; +const log_1 = __webpack_require__(/*! ../log */ "./lib/wasm/jsep/log.ts"); +const types_1 = __webpack_require__(/*! ./types */ "./lib/wasm/jsep/webgpu/types.ts"); +/** + * normalize the buffer size so that it fits the 128-bits (16 bytes) alignment. + */ +const calcNormalizedBufferSize = (size) => Math.ceil(size / 16) * 16; +let guid = 0; +const createNewGpuDataId = () => guid++; +class GpuDataManagerImpl { + constructor(backend /* , private reuseBuffer: boolean */) { + this.backend = backend; + this.storageCache = new Map(); + this.downloadCache = new Map(); + this.buffersForUploadingPending = []; + this.buffersPending = []; + } + upload(id, data) { + const srcArrayBuffer = data.buffer; + const srcOffset = data.byteOffset; + const srcLength = data.byteLength; + const size = calcNormalizedBufferSize(srcLength); + // get destination gpu buffer + const gpuDataCache = this.storageCache.get(id); + if (!gpuDataCache) { + throw new Error('gpu data for uploading does not exist'); + } + if (gpuDataCache.originalSize !== srcLength) { + throw new Error(`inconsistent data size. gpu data size=${gpuDataCache.originalSize}, data size=${srcLength}`); + } + // create gpu buffer + const gpuBufferForUploading = this.backend.device.createBuffer( + // eslint-disable-next-line no-bitwise + { mappedAtCreation: true, size, usage: GPUBufferUsage.MAP_WRITE | GPUBufferUsage.COPY_SRC }); + // copy (upload) data + const arrayBuffer = gpuBufferForUploading.getMappedRange(); + new Uint8Array(arrayBuffer).set(new Uint8Array(srcArrayBuffer, srcOffset, srcLength)); + gpuBufferForUploading.unmap(); + // GPU copy + const commandEncoder = this.backend.getCommandEncoder(); + this.backend.endComputePass(); + commandEncoder.copyBufferToBuffer(gpuBufferForUploading, 0, gpuDataCache.gpuData.buffer, 0, size); + (0, log_1.LOG_DEBUG)('verbose', () => `[WebGPU] GpuDataManager.upload(id=${id})`); + this.buffersForUploadingPending.push(gpuBufferForUploading); + } + memcpy(sourceId, destinationId) { + // get source gpu buffer + const sourceGpuDataCache = this.storageCache.get(sourceId); + if (!sourceGpuDataCache) { + throw new Error('source gpu data for memcpy does not exist'); + } + // get destination gpu buffer + const destinationGpuDataCache = this.storageCache.get(destinationId); + if (!destinationGpuDataCache) { + throw new Error('destination gpu data for memcpy does not exist'); + } + if (sourceGpuDataCache.originalSize !== destinationGpuDataCache.originalSize) { + throw new Error('inconsistent source and destination gpu data size'); + } + const size = calcNormalizedBufferSize(sourceGpuDataCache.originalSize); + // GPU copy + this.backend.getCommandEncoder().copyBufferToBuffer(sourceGpuDataCache.gpuData.buffer, 0, destinationGpuDataCache.gpuData.buffer, 0, size); + } + // eslint-disable-next-line no-bitwise + create(size, usage = GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST) { + // !!! + // !!! IMPORTANT: TODO: whether we should keep the storage buffer every time, or always create new ones. + // !!! This need to be figured out by performance test results. + // !!! + const bufferSize = calcNormalizedBufferSize(size); + // create gpu buffer + const gpuBuffer = this.backend.device.createBuffer({ size: bufferSize, usage }); + const gpuData = { id: createNewGpuDataId(), type: types_1.GpuDataType.default, buffer: gpuBuffer }; + this.storageCache.set(gpuData.id, { gpuData, originalSize: size }); + (0, log_1.LOG_DEBUG)('verbose', () => `[WebGPU] GpuDataManager.create(size=${size}) => id=${gpuData.id}`); + return gpuData; + } + get(id) { + var _a; + return (_a = this.storageCache.get(id)) === null || _a === void 0 ? void 0 : _a.gpuData; + } + release(id) { + const cachedData = this.storageCache.get(id); + if (!cachedData) { + throw new Error('releasing data does not exist'); + } + (0, log_1.LOG_DEBUG)('verbose', () => `[WebGPU] GpuDataManager.release(id=${id}), gpuDataId=${cachedData.gpuData.id}`); + this.storageCache.delete(id); + this.buffersPending.push(cachedData.gpuData.buffer); + // cachedData.gpuData.buffer.destroy(); + const downloadingData = this.downloadCache.get(id); + if (downloadingData) { + this.downloadCache.delete(id); + } + return cachedData.originalSize; + } + async download(id) { + const downloadData = this.downloadCache.get(id); + if (downloadData) { + return downloadData.data; + } + const cachedData = this.storageCache.get(id); + if (!cachedData) { + throw new Error('data does not exist'); + } + const commandEncoder = this.backend.getCommandEncoder(); + this.backend.endComputePass(); + const gpuReadBuffer = this.backend.device.createBuffer( + // eslint-disable-next-line no-bitwise + { size: cachedData.originalSize, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ }); + commandEncoder.copyBufferToBuffer(cachedData.gpuData.buffer /* source buffer */, 0 /* source offset */, gpuReadBuffer /* destination buffer */, 0 /* destination offset */, cachedData.originalSize /* size */); + this.backend.flush(); + const readDataPromise = new Promise((resolve) => { + gpuReadBuffer.mapAsync(GPUMapMode.READ).then(() => { + const data = gpuReadBuffer.getMappedRange().slice(0); + gpuReadBuffer.destroy(); + resolve(data); + }); + }); + this.downloadCache.set(id, { data: readDataPromise }); + return readDataPromise; + } + refreshPendingBuffers() { + for (const buffer of this.buffersForUploadingPending) { + buffer.destroy(); + } + for (const buffer of this.buffersPending) { + buffer.destroy(); + } + } +} +const createGpuDataManager = (...args) => new GpuDataManagerImpl(...args); +exports.createGpuDataManager = createGpuDataManager; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/op-resolve-rules.ts": +/*!**************************************************!*\ + !*** ./lib/wasm/jsep/webgpu/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.WEBGPU_OP_RESOLVE_RULES = void 0; +const binaryOps = __importStar(__webpack_require__(/*! ./ops/binary-op */ "./lib/wasm/jsep/webgpu/ops/binary-op.ts")); +const conv_1 = __webpack_require__(/*! ./ops/conv */ "./lib/wasm/jsep/webgpu/ops/conv.ts"); +const gemm_1 = __webpack_require__(/*! ./ops/gemm */ "./lib/wasm/jsep/webgpu/ops/gemm.ts"); +const matmul_1 = __webpack_require__(/*! ./ops/matmul */ "./lib/wasm/jsep/webgpu/ops/matmul.ts"); +const pool = __importStar(__webpack_require__(/*! ./ops/pool */ "./lib/wasm/jsep/webgpu/ops/pool.ts")); +const transpose_1 = __webpack_require__(/*! ./ops/transpose */ "./lib/wasm/jsep/webgpu/ops/transpose.ts"); +const unaryOps = __importStar(__webpack_require__(/*! ./ops/unary-op */ "./lib/wasm/jsep/webgpu/ops/unary-op.ts")); +exports.WEBGPU_OP_RESOLVE_RULES = new Map([ + ['Abs', [unaryOps.abs]], + ['Acos', [unaryOps.acos]], + ['Acosh', [unaryOps.acosh]], + ['Add', [binaryOps.add]], + ['Asin', [unaryOps.asin]], + ['Asinh', [unaryOps.asinh]], + ['Atan', [unaryOps.atan]], + ['Atanh', [unaryOps.atanh]], + // TODO: support new attributes for AveragePool-10 + ['AveragePool', [pool.averagePool, pool.parseAveragePoolAttributes]], + ['Ceil', [unaryOps.ceil]], + ['ClipV10', [unaryOps.clipV10]], + ['Clip', [unaryOps.clip]], + ['Conv', [conv_1.conv, conv_1.parseConvAttributes]], + ['Cos', [unaryOps.cos]], + ['Cosh', [unaryOps.cosh]], + ['Div', [binaryOps.div]], + ['Elu', [unaryOps.elu, unaryOps.parseAlphaAttributes]], + ['Erf', [unaryOps.erf]], + ['Exp', [unaryOps.exp]], + ['Floor', [unaryOps.floor]], + ['Gemm', [gemm_1.gemm, gemm_1.parseGemmAttributes]], + ['GlobalAveragePool', [pool.globalAveragePool, pool.parseGlobalAveragePoolAttributes]], + ['GlobalMaxPool', [pool.globalMaxPool, pool.parseGlobalMaxPoolAttributes]], + ['LeakyRelu', [unaryOps.leakyRelu, unaryOps.parseAlphaAttributes]], + ['MatMul', [matmul_1.matMul]], + // TODO: support new attributes for MaxPool-8 and MaxPool-10 + ['MaxPool', [pool.maxPool, pool.parseMaxPoolAttributes]], + ['Mul', [binaryOps.mul]], + ['Neg', [unaryOps.neg]], + ['Pow', [binaryOps.pow]], + ['Reciprocal', [unaryOps.reciprocal]], + ['Relu', [unaryOps.relu]], + ['Sigmoid', [unaryOps.sigmoid]], + ['Sin', [unaryOps.sin]], + ['Sinh', [unaryOps.sinh]], + ['Sqrt', [unaryOps.sqrt]], + ['Sub', [binaryOps.sub]], + ['Tan', [unaryOps.tan]], + ['Tanh', [unaryOps.tanh]], + ['ThresholdedRelu', [unaryOps.thresholdedRelu, unaryOps.parseAlphaAttributes]], + ['Transpose', [transpose_1.transpose, transpose_1.parseTransposeAttributes]], +]); + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/ops/3rd-party/activation_util.ts": +/*!***************************************************************!*\ + !*** ./lib/wasm/jsep/webgpu/ops/3rd-party/activation_util.ts ***! + \***************************************************************/ +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +/** + * @license + * Copyright 2021 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.biasActivationSnippet = exports.activationFnSnippet = exports.typeSnippet = void 0; +const typeSnippet = (component) => { + switch (component) { + case 1: + return 'f32'; + case 2: + return 'vec2'; + case 3: + return 'vec3'; + case 4: + return 'vec4'; + default: + throw new Error(`${component}-component is not supported.`); + } +}; +exports.typeSnippet = typeSnippet; +const activationFnSnippet = (activation, _hasPreluActivationWeights = false, _packed = false, _coordsLength = 3) => { + if (!activation) { + return ''; + } + // TODO: add implementations + return ''; +}; +exports.activationFnSnippet = activationFnSnippet; +const biasActivationSnippet = (hasBias, activation) => ` + ${hasBias ? 'value = value + getBiasByOutputCoords(coords);' : ''} + ${activation ? 'value = activation(value, coords);' : ''} + `; +exports.biasActivationSnippet = biasActivationSnippet; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/ops/3rd-party/conv2d_mm_webgpu.ts": +/*!****************************************************************!*\ + !*** ./lib/wasm/jsep/webgpu/ops/3rd-party/conv2d_mm_webgpu.ts ***! + \****************************************************************/ +/***/ ((__unused_webpack_module, exports, __webpack_require__) => { + +"use strict"; + +/** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.createConv2DMatMulProgramInfo = void 0; +// sampled from [@tensorflow/tfjs] tfjs-backend-webgpu/src/conv2d_mm_webgpu.ts +// +// modified to fit the needs of the project +const log_1 = __webpack_require__(/*! ../../../log */ "./lib/wasm/jsep/log.ts"); +const util_1 = __webpack_require__(/*! ../../../util */ "./lib/wasm/jsep/util.ts"); +const types_1 = __webpack_require__(/*! ../../types */ "./lib/wasm/jsep/webgpu/types.ts"); +const activation_util_1 = __webpack_require__(/*! ./activation_util */ "./lib/wasm/jsep/webgpu/ops/3rd-party/activation_util.ts"); +const conv_util_1 = __webpack_require__(/*! ./conv_util */ "./lib/wasm/jsep/webgpu/ops/3rd-party/conv_util.ts"); +const matmul_packed_webgpu_1 = __webpack_require__(/*! ./matmul_packed_webgpu */ "./lib/wasm/jsep/webgpu/ops/3rd-party/matmul_packed_webgpu.ts"); +const conv2dCommonSnippet = (isChannelsLast, fitAOuter, fitBOuter, fitInner, addBias = false, activation, hasPreluActivationWeights = false, innerElementSizeX = 4, innerElementSizeW = 4, innerElementSize = 4) => { + const getXSnippet = (innerElementSize) => { + switch (innerElementSize) { + case 1: + return 'resData = x[xIndex];'; + case 3: + return 'resData = vec3(x[xIndex], x[xIndex + 1], x[xIndex + 2]);'; + case 4: + return 'resData = x[xIndex / 4];'; + default: + throw new Error(`innerElementSize ${innerElementSize} is not supported.`); + } + }; + const getWSnippet = (innerElementSize) => { + switch (innerElementSize) { + case 1: + return 'return w[row * wShape[3] + colIn];'; + case 4: + return 'return w[row * wShape[3] / 4 + colIn];'; + default: + throw new Error(`innerElementSize ${innerElementSize} is not supported.`); + } + }; + const coordASnippet = isChannelsLast ? ` + let coord = vec4(batch, xRow, xCol, xCh); + ` : + ` + let coord = vec4(batch, xCh, xRow, xCol); + `; + const coordResSnippet = isChannelsLast ? ` + let coords = vec4( + batch, + row / outWidth, + row % outWidth, + col); + ` : + ` + let coords = vec4( + batch, + row, + col / outWidth, + col % outWidth); + `; + const xHeight = isChannelsLast ? 'xShape[1]' : 'xShape[2]'; + const xWidth = isChannelsLast ? 'xShape[2]' : 'xShape[3]'; + const row = isChannelsLast ? 'row' : 'col'; + const col = isChannelsLast ? 'col' : 'row'; + const readXSnippet = ` + let inChannels = wShape[2]; + let outWidth = ${isChannelsLast ? 'outShape[2]' : 'outShape[3]'}; + let outRow = ${row} / outWidth; + let outCol = ${row} % outWidth; + + let WRow = ${col} / (filterDims[1] * inChannels); + let WCol = ${col} / inChannels % filterDims[1]; + let xRow = outRow * stride[0] + dilation[0] * WRow - pad[0]; + let xCol = outCol * stride[1] + dilation[1] * WCol - pad[1]; + let xCh = ${col} % inChannels; + var resData = ${(0, activation_util_1.typeSnippet)(innerElementSizeX)}(0.0); + // The bounds checking is always needed since we use it to pad zero for + // the 'same' padding type. + if (xRow >= 0 && xRow < ${xHeight} && xCol >= 0 && xCol < ${xWidth}) { + ${coordASnippet} + let xIndex = getIndexFromCoords4D(coord, xShape); + ${getXSnippet(innerElementSizeX)} + } + return resData;`; + const sampleX = isChannelsLast ? (fitAOuter && fitInner ? ` + let col = colIn * ${innerElementSizeX}; + ${readXSnippet}` : + ` + let col = colIn * ${innerElementSizeX}; + if (row < dimAOuter && col < dimInner) { + ${readXSnippet} + } + return ${(0, activation_util_1.typeSnippet)(innerElementSizeX)}(0.0);`) : + (fitInner && fitBOuter ? ` + let col = colIn * ${innerElementSizeX}; + ${readXSnippet}` : + ` + let col = colIn * ${innerElementSizeX}; + if (row < dimInner && col < dimBOuter) { + ${readXSnippet} + } + return ${(0, activation_util_1.typeSnippet)(innerElementSizeX)}(0.0);`); + const sampleW = `${getWSnippet(innerElementSizeW)}`; + const resType = (0, activation_util_1.typeSnippet)(innerElementSize); + const aType = isChannelsLast ? (0, activation_util_1.typeSnippet)(innerElementSizeX) : (0, activation_util_1.typeSnippet)(innerElementSizeW); + const bType = isChannelsLast ? (0, activation_util_1.typeSnippet)(innerElementSizeW) : (0, activation_util_1.typeSnippet)(innerElementSizeX); + const userCode = ` + ${(0, activation_util_1.activationFnSnippet)(activation, hasPreluActivationWeights, innerElementSize === 4, 4)} + fn mm_readA(batch: i32, row : i32, colIn : i32) -> ${aType} { + ${isChannelsLast ? sampleX : sampleW} + } + + fn mm_readB(batch: i32, row : i32, colIn : i32) -> ${bType} { + ${isChannelsLast ? sampleW : sampleX} + } + + fn mm_write(batch: i32, row : i32, colIn : i32, valueIn : ${resType}) { + let col = colIn * ${innerElementSize}; + if (row < dimAOuter && col < dimBOuter) + { + var value = valueIn; + let outWidth = ${isChannelsLast ? 'outShape[2]' : 'outShape[3]'}; + ${coordResSnippet} + ${(0, activation_util_1.biasActivationSnippet)(addBias, activation)} + setOutputAtCoords(coords[0], coords[1], coords[2], coords[3], value); + } + }`; + return userCode; +}; +const createConv2DMatMulProgramInfo = (inputs, metadata, attributes, outputShape, dimAOuter, dimBOuter, dimInner, hasBias, sequentialAccessByThreads) => { + const isChannelsLast = attributes.format === 'NHWC'; + const inChannels = isChannelsLast ? inputs[0].dims[3] : inputs[0].dims[1]; + const batchSize = outputShape[0]; + const outWidth = isChannelsLast ? outputShape[2] : outputShape[3]; + const outHeight = isChannelsLast ? outputShape[1] : outputShape[2]; + const outChannels = isChannelsLast ? outputShape[3] : outputShape[1]; + const isVec4 = (((inChannels % 4 === 0 || inChannels % 3 === 0) && isChannelsLast) || + (outWidth % 4 === 0 && !isChannelsLast)) && + outChannels % 4 === 0; + // TODO: fine tune size + const dispatchX = isChannelsLast ? outChannels : outWidth * outHeight; + const dispatchY = isChannelsLast ? outWidth * outHeight : outChannels; + const workGroupSize = isVec4 ? [8, 8, 1] : [dispatchX <= 4 ? 4 : 16, dispatchX > 4 && dispatchY <= 4 ? 4 : 16, 1]; + const elementsPerThread = isVec4 ? [4, 4, 1] : [dispatchX <= 4 ? 1 : 2, dispatchX > 4 && dispatchY <= 4 ? 1 : 2, 1]; + const dispatch = [ + Math.ceil(dispatchX / workGroupSize[0] / elementsPerThread[0]), + Math.ceil(dispatchY / workGroupSize[1] / elementsPerThread[1]), + Math.ceil(batchSize / workGroupSize[2] / elementsPerThread[1]) + ]; + (0, log_1.LOG_DEBUG)('verbose', () => `[conv2d_mm_webgpu] dispatch = ${dispatch}`); + const innerElementSize = isVec4 ? (isChannelsLast && inChannels % 4 !== 0 ? 3 : 4) : elementsPerThread[0]; + const tileAOuter = workGroupSize[1] * elementsPerThread[1]; + const tileBOuter = workGroupSize[0] * elementsPerThread[0]; + const tileInner = Math.max(workGroupSize[0] * innerElementSize, workGroupSize[1]); + const fitAOuter = dimAOuter % tileAOuter === 0; + const fitBOuter = dimBOuter % tileBOuter === 0; + const fitInner = dimInner % tileInner === 0; + const elementsSize = isVec4 ? [innerElementSize, 4, 4] : [1, 1, 1]; + const declareInputs = [ + `@group(0) @binding(0) var x: array<${isVec4 && innerElementSize === 4 ? 'vec4' : 'f32'}>;`, + `@group(0) @binding(1) var w: array<${isVec4 ? 'vec4' : 'f32'}>;` + ]; + let declareFunctions = ` + fn setOutputAtIndex(flatIndex : i32, value : ${isVec4 ? 'vec4' : 'f32'}) { + result[flatIndex] = ${isVec4 ? 'vec4' : 'f32'}(value); + } + fn setOutputAtCoords(d0 : i32, d1 : i32, d2 : i32, d3 : i32, value : ${isVec4 ? 'vec4' : 'f32'}) { + let flatIndex = getOutputIndexFromCoords(vec4(d0, d1, d2, d3)); + setOutputAtIndex(flatIndex ${isVec4 ? '/ 4' : ''}, value); + }`; + if (hasBias) { + declareInputs.push(`@group(0) @binding(2) var bias: array<${isVec4 ? 'vec4' : 'f32'}>;`); + declareFunctions += ` + fn getBiasByOutputCoords(coords : vec4) -> ${isVec4 ? 'vec4' : 'f32'} { + return bias[coords.${isChannelsLast ? 'w' : 'y'}${isVec4 ? '/ 4' : ''}]; + }`; + } + return Object.assign(Object.assign({}, metadata), { outputs: [{ dims: outputShape, dataType: inputs[0].dataType, gpuDataType: types_1.GpuDataType.default }], dispatchGroup: () => ({ x: dispatch[0], y: dispatch[1], z: dispatch[2] }), getShaderSource: () => ` + ${conv_util_1.utilFunctions} + //struct Uniforms { xShape : vec4, wShape : vec4, outShape : vec4, + // outShapeStrides: vec3, filterDims : vec2, pad : vec2, stride : vec2, + // dilation : vec2, dimAOuter : i32, dimBOuter : i32, dimInner : i32 }; + ${declareInputs.join('')} + @group(0) @binding(${declareInputs.length}) var result: array<${isVec4 ? 'vec4' : 'f32'}>; + //@group(0) @binding(${declareInputs.length + 1}) var uniforms: Uniforms; + + const xShape : vec4 = vec4(${inputs[0].dims.join(',')}); + const wShape : vec4 = vec4(${inputs[1].dims.join(',')}); + const outShape : vec4 = vec4(${outputShape.join(',')}); + const outShapeStrides : vec3 = vec3(${util_1.ShapeUtil.computeStrides(outputShape).slice(0, 3).join(',')}); + const filterDims : vec2 = vec2(${attributes.kernelShape[0]}, ${attributes.kernelShape[1]}); + const pad : vec2 = vec2(${attributes.pads[0]}, ${attributes.pads[1]}); + const stride : vec2 = vec2(${attributes.strides[0]}, ${attributes.strides[1]}); + const dilation : vec2 = vec2(${attributes.dilations[0]}, ${attributes.dilations[1]}); + const dimAOuter : i32 = ${dimAOuter}; + const dimBOuter : i32 = ${dimBOuter}; + const dimInner : i32 = ${dimInner}; + ${declareFunctions} + ${conv2dCommonSnippet(isChannelsLast, fitAOuter, fitBOuter, fitInner, hasBias, undefined, false, elementsSize[0], elementsSize[1], elementsSize[2])} + ${isVec4 ? (0, matmul_packed_webgpu_1.makeMatMulPackedVec4Source)(elementsPerThread, workGroupSize, !isChannelsLast, tileInner) : + (0, matmul_packed_webgpu_1.makeMatMulPackedSource)(elementsPerThread, workGroupSize, !isChannelsLast, tileInner, false, undefined, sequentialAccessByThreads)}` }); +}; +exports.createConv2DMatMulProgramInfo = createConv2DMatMulProgramInfo; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/ops/3rd-party/conv_util.ts": +/*!*********************************************************!*\ + !*** ./lib/wasm/jsep/webgpu/ops/3rd-party/conv_util.ts ***! + \*********************************************************/ +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +/** + * @license + * Copyright 2020 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.utilFunctions = void 0; +// sampled from [@tensorflow/tfjs] tfjs-core/src/ops/conv_util.ts +// +// modified to fit the needs of the project +exports.utilFunctions = ` +fn getIndexFromCoords4D(coords : vec4, shape : vec4) -> i32 { + return dot(coords, vec4( + shape.y * shape.z * shape.w, shape.z * shape.w, shape.w, 1)); +} +fn getOutputIndexFromCoords(coords : vec4) -> i32 { + return dot(coords, vec4( + outShapeStrides.x, outShapeStrides.y, outShapeStrides.z, 1)); +} +`; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/ops/3rd-party/matmul_packed_webgpu.ts": +/*!********************************************************************!*\ + !*** ./lib/wasm/jsep/webgpu/ops/3rd-party/matmul_packed_webgpu.ts ***! + \********************************************************************/ +/***/ ((__unused_webpack_module, exports) => { + +"use strict"; + +/** + * @license + * Copyright 2019 Google LLC. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============================================================================= + */ +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.makeMatMulPackedSource = exports.makeMatMulPackedVec4Source = void 0; +// sampled from [@tensorflow/tfjs] tfjs-backend-webgpu/src/matmul_packed_webgpu.ts +// +// modified to fit the needs of the project +const writeDataToSubAVec4Snippet = (transpose) => { + if (transpose) { + return ` + mm_Asub[inputRow][inputCol] = mm_readA(batch, + kStart + inputRow, + globalRowStart / innerElementSize + inputCol); + `; + } + else { + return ` + mm_Asub[inputRow][inputCol] = mm_readA(batch, + globalRow + innerRow, + kStart / innerElementSize + inputCol); + `; + } +}; +const calculateResultSnippet = (transposeA, innerElementSize) => { + if (transposeA) { + return ` + let ACached0 = mm_Asub[k * innerElementSize][localRow]; + let ACached1 = mm_Asub[k * innerElementSize + 1][localRow]; + let ACached2 = mm_Asub[k * innerElementSize + 2][localRow]; + ${innerElementSize === 3 ? '' : 'let ACached3 = mm_Asub[k * innerElementSize + 3][localRow];'} + for (var i = 0; i < rowPerThread; i = i + 1) { + acc[i] = BCached0 * ACached0[i] + acc[i]; + acc[i] = BCached1 * ACached1[i] + acc[i]; + acc[i] = BCached2 * ACached2[i] + acc[i]; + ${innerElementSize === 3 ? '' : 'acc[i] = BCached3 * ACached3[i] + acc[i];'} + }`; + } + else { + return ` + for (var i = 0; i < rowPerThread; i = i + 1) { + let ACached = mm_Asub[tileRow + i][k]; + acc[i] = BCached0 * ACached.x + acc[i]; + acc[i] = BCached1 * ACached.y + acc[i]; + acc[i] = BCached2 * ACached.z + acc[i]; + ${innerElementSize === 3 ? '' : 'acc[i] = BCached3 * ACached.w + acc[i];'} + }`; + } +}; +const makeMatMulPackedVec4Source = (workPerThread, workgroupSize, transposeA = false, tileInner = 32, splitK = false, splitedDimInner = 32, isVectorA = false) => { + const tileAOuter = workgroupSize[1] * workPerThread[1]; + const tileBOuter = workgroupSize[0] * workPerThread[0]; + const tileAWidth = transposeA ? tileAOuter : tileInner; + const tileAHight = transposeA ? tileInner : tileAOuter; + const innerElementSize = tileAWidth / workgroupSize[0]; + const rowPerThreadB = tileInner / workgroupSize[1]; + if (!(((transposeA && innerElementSize === 4 && workPerThread[1] === 4) || + (!transposeA && (innerElementSize === 3 || innerElementSize === 4))) && + tileAWidth % workgroupSize[0] === 0 && tileInner % workgroupSize[1] === 0 && workPerThread[0] === 4)) { + throw new Error(`If transposeA ${transposeA} is true, innerElementSize ${innerElementSize} and workPerThread[1] ${workPerThread[1]} must be 4. + Otherwise, innerElementSize ${innerElementSize} must be 3 or 4. + tileAWidth ${tileAWidth} must be divisible by workgroupSize[0]${workgroupSize[0]}. tileInner ${tileInner} must be divisible by workgroupSize[1] ${workgroupSize[1]}. colPerThread ${workPerThread[0]} must be 4.`); + } + return ` +var mm_Asub : array, ${tileAWidth / innerElementSize}>, ${tileAHight}>; +var mm_Bsub : array, ${tileBOuter / workPerThread[0]}>, ${tileInner}>; + +const rowPerThread = ${workPerThread[1]}; +const colPerThread = ${workPerThread[0]}; +const innerElementSize = ${innerElementSize}; +const tileInner = ${tileInner}; + +@compute @workgroup_size(${workgroupSize[0]}, ${workgroupSize[1]}, ${workgroupSize[2]}) +fn main(@builtin(local_invocation_id) localId : vec3, + @builtin(global_invocation_id) globalId : vec3, + @builtin(workgroup_id) workgroupId : vec3) { + let localRow = i32(localId.y); + let tileRow = ${isVectorA ? '0' : 'localRow * rowPerThread'}; + let tileCol = i32(localId.x); + + let globalRow = ${isVectorA ? '0' : 'i32(globalId.y) * rowPerThread'}; + let globalCol = i32(globalId.x); + let batch = ${splitK ? '0' : 'i32(globalId.z)'}; + let globalRowStart = i32(workgroupId.y) * ${tileAOuter}; + + let numTiles = ${splitK ? `${Math.ceil(splitedDimInner / tileInner)}` : '(dimInner - 1) / tileInner + 1'}; + var kStart = ${splitK ? `i32(globalId.z) * ${splitedDimInner}` : '0'}; + + var acc: array, rowPerThread>; + + // Loop over shared dimension. + let tileRowB = localRow * ${rowPerThreadB}; + for (var t = 0; t < numTiles; t = t + 1) { + // Load one tile of A into local memory. + for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { + let inputRow = tileRow + innerRow; + let inputCol = tileCol; + ${writeDataToSubAVec4Snippet(transposeA)} + } + + // Load one tile of B into local memory. + for (var innerRow = 0; innerRow < ${rowPerThreadB}; innerRow = innerRow + 1) { + let inputRow = tileRowB + innerRow; + let inputCol = tileCol; + mm_Bsub[inputRow][inputCol] = mm_readB(batch, kStart + inputRow, globalCol); + } + kStart = kStart + tileInner; + workgroupBarrier(); + + // Compute acc values for a single thread. + for (var k = 0; k < tileInner / innerElementSize; k = k + 1) { + let BCached0 = mm_Bsub[k * innerElementSize][tileCol]; + let BCached1 = mm_Bsub[k * innerElementSize + 1][tileCol]; + let BCached2 = mm_Bsub[k * innerElementSize + 2][tileCol]; + ${innerElementSize === 3 ? '' : 'let BCached3 = mm_Bsub[k * innerElementSize + 3][tileCol];'} + + ${calculateResultSnippet(transposeA, innerElementSize)} + } + + workgroupBarrier(); + } + + for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { + mm_write(batch, globalRow + innerRow, globalCol, acc[innerRow]); + } +}`; +}; +exports.makeMatMulPackedVec4Source = makeMatMulPackedVec4Source; +const writeDataToSubASnippet = (transpose) => { + if (transpose) { + return ` + mm_Asub[inputRow][inputCol] = mm_readA(batch, + kStart + inputRow, + globalRowStart + inputCol); + `; + } + else { + return ` + mm_Asub[inputRow][inputCol] = mm_readA(batch, + globalRowStart + inputRow, + kStart + inputCol); + `; + } +}; +const readDataFromSubASnippet = (transposeA) => transposeA ? 'let ACached = mm_Asub[k][tileRow + innerRow];' : 'let ACached = mm_Asub[tileRow + innerRow][k];'; +// sequentialAccessByThreads means sequential data in memory is accessed by +// threads, instead of a single thread (default behavior). +const makeMatMulPackedSource = (workPerThread, workgroupSize, transposeA = false, tileInner = 32, splitK = false, splitedDimInner = 32, sequentialAccessByThreads = false) => { + const tileAOuter = workPerThread[1] * workgroupSize[1]; + const tileBOuter = workPerThread[0] * workgroupSize[0]; + const tileAWidth = transposeA ? tileAOuter : tileInner; + const tileAHight = transposeA ? tileInner : tileAOuter; + if (!(tileAHight % workgroupSize[1] === 0 && tileAWidth % workgroupSize[0] === 0 && + tileInner % workgroupSize[1] === 0)) { + throw new Error(`tileAHight ${tileAHight} must be divisible by workgroupSize[1]${workgroupSize[1]}, tileAWidth ${tileAWidth} must be divisible by workgroupSize[0]${workgroupSize[0]}, tileInner ${tileInner} must be divisible by workgroupSize[1]${workgroupSize[1]}`); + } + const rowPerThreadA = tileAHight / workgroupSize[1]; + const colPerThreadA = tileAWidth / workgroupSize[0]; + const rowPerThreadB = tileInner / workgroupSize[1]; + const matmulSnippet = sequentialAccessByThreads ? + ` + let localRow = i32(localId.y); + let localCol = i32(localId.x); + let globalRowStart = i32(workgroupId.y) * ${tileAOuter}; + let globalColStart = i32(workgroupId.x) * ${tileBOuter}; + + // Loop over shared dimension. + for (var t = 0; t < numTiles; t = t + 1) { + // Load one tile of A into local memory. + for (var inputRow = localRow; inputRow < ${tileAHight}; inputRow = inputRow + ${workgroupSize[1]}) { + for (var inputCol = localCol; inputCol < ${tileAWidth}; inputCol = inputCol + ${workgroupSize[0]}) { + ${writeDataToSubASnippet(transposeA)} + } + } + // Load one tile of B into local memory. + for (var inputRow = localRow; inputRow < ${tileInner}; inputRow = inputRow + ${workgroupSize[1]}) { + for (var inputCol = localCol; inputCol < ${tileBOuter}; inputCol = inputCol + ${workgroupSize[0]}) { + mm_Bsub[inputRow][inputCol] = mm_readB(batch, + kStart + inputRow, + globalColStart + inputCol); + } + } + kStart = kStart + tileInner; + workgroupBarrier(); + + // Compute acc values for a single thread. + var BCached : array; + for (var k = 0; k < tileInner; k = k + 1) { + for (var inner = 0; inner < colPerThread; inner = inner + 1) { + BCached[inner] = mm_Bsub[k][localCol + inner * ${workgroupSize[0]}]; + } + for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { + let ACached = ${transposeA ? `mm_Asub[k][localRow + innerRow * ${workgroupSize[1]}];` : + `mm_Asub[localRow + innerRow * ${workgroupSize[1]}][k];`} + for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { + acc[innerRow][innerCol] = acc[innerRow][innerCol] + + ACached * BCached[innerCol]; + } + } + } + workgroupBarrier(); + } + for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { + let gRow = globalRowStart + localRow + innerRow * ${workgroupSize[1]}; + for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { + let gCol = globalColStart + localCol + innerCol * ${workgroupSize[0]}; + mm_write(batch, gRow, gCol, acc[innerRow][innerCol]); + } + } + ` : + ` +let tileRow = i32(localId.y) * rowPerThread; +let tileCol = i32(localId.x) * colPerThread; + +let globalRow = i32(globalId.y) * rowPerThread; +let globalCol = i32(globalId.x) * colPerThread; +let globalRowStart = i32(workgroupId.y) * ${tileAOuter}; + +let tileRowA = i32(localId.y) * ${rowPerThreadA}; +let tileColA = i32(localId.x) * ${colPerThreadA}; +let tileRowB = i32(localId.y) * ${rowPerThreadB}; +// Loop over shared dimension. +for (var t = 0; t < numTiles; t = t + 1) { + // Load one tile of A into local memory. + for (var innerRow = 0; innerRow < ${rowPerThreadA}; innerRow = innerRow + 1) { + for (var innerCol = 0; innerCol < ${colPerThreadA}; innerCol = innerCol + 1) { + let inputRow = tileRowA + innerRow; + let inputCol = tileColA + innerCol; + ${writeDataToSubASnippet(transposeA)} + } + } + + // Load one tile of B into local memory. + for (var innerRow = 0; innerRow < ${rowPerThreadB}; innerRow = innerRow + 1) { + for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { + let inputRow = tileRowB + innerRow; + let inputCol = tileCol + innerCol; + mm_Bsub[inputRow][inputCol] = mm_readB(batch, + kStart + inputRow, + globalCol + innerCol); + } + } + kStart = kStart + tileInner; + workgroupBarrier(); + + // Compute acc values for a single thread. + var BCached : array; + for (var k = 0; k < tileInner; k = k + 1) { + for (var inner = 0; inner < colPerThread; inner = inner + 1) { + BCached[inner] = mm_Bsub[k][tileCol + inner]; + } + + for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { + ${readDataFromSubASnippet(transposeA)} + for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { + acc[innerRow][innerCol] = acc[innerRow][innerCol] + ACached * BCached[innerCol]; + } + } + } + + workgroupBarrier(); +} + +for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { + for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { + mm_write(batch, globalRow + innerRow, globalCol + innerCol, + acc[innerRow][innerCol]); + } +} +`; + return ` + var mm_Asub : array, ${tileAHight}>; + var mm_Bsub : array, ${tileInner}>; + const rowPerThread = ${workPerThread[1]}; + const colPerThread = ${workPerThread[0]}; + const tileInner = ${tileInner}; + +@compute @workgroup_size(${workgroupSize[0]}, ${workgroupSize[1]}, ${workgroupSize[2]}) +fn main(@builtin(local_invocation_id) localId : vec3, + @builtin(global_invocation_id) globalId : vec3, + @builtin(workgroup_id) workgroupId : vec3) { + let batch = ${splitK ? '0' : 'i32(globalId.z)'}; + let numTiles = ${splitK ? `${Math.ceil(splitedDimInner / tileInner)}` : '(dimInner - 1) / tileInner + 1'}; + var kStart = ${splitK ? `i32(globalId.z) * ${splitedDimInner}` : '0'}; + + var acc : array, rowPerThread>; + + // Without this initialization strange values show up in acc. + for (var innerRow = 0; innerRow < rowPerThread; innerRow = innerRow + 1) { + for (var innerCol = 0; innerCol < colPerThread; innerCol = innerCol + 1) { + acc[innerRow][innerCol] = 0.0; + } + } + ${matmulSnippet} + } +`; +}; +exports.makeMatMulPackedSource = makeMatMulPackedSource; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/ops/binary-op.ts": +/*!***********************************************!*\ + !*** ./lib/wasm/jsep/webgpu/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.sub = exports.pow = exports.mul = exports.div = exports.add = void 0; +const util_1 = __webpack_require__(/*! ../../util */ "./lib/wasm/jsep/util.ts"); +const types_1 = __webpack_require__(/*! ../types */ "./lib/wasm/jsep/webgpu/types.ts"); +const common_1 = __webpack_require__(/*! ./common */ "./lib/wasm/jsep/webgpu/ops/common.ts"); +const createBinaryOpProgramShader = (shaderHelper, dimsA, dimsB, dimsOutput, vectorize, doBroadcast, funcCall, additionalImplementation, typeA = 'f32', typeB = 'f32', typeOutput = 'f32') => { + const outputSize = util_1.ShapeUtil.size(dimsOutput); + const vecSize = Math.ceil(outputSize / 4); + let expressionScalar; + let expressionVector; + if (typeof funcCall === 'string') { + expressionScalar = expressionVector = (a, b) => `${funcCall}((${a}),(${b}))`; + } + else if (typeof funcCall === 'function') { + expressionScalar = expressionVector = funcCall; + } + else { + expressionScalar = funcCall.scalar; + expressionVector = funcCall.vector; + } + let broadcastImpl = ''; + const outputIndicesHelper = (0, common_1.createIndicesHelper)('output', dimsOutput); + if (doBroadcast) { + const calcOffsetImpl = (dims) => { + const strides = util_1.ShapeUtil.computeStrides(dims); + const offsets = []; + for (let i = dims.length - 1; i >= 0; i--) { + const idx = dimsOutput.length === 0 ? '0u' : + (dimsOutput.length === 1) ? '(*outputIndices)' : + `(*outputIndices)[${i + dimsOutput.length - dims.length}]`; + offsets.push(`${strides[i]}u * (${idx} % ${dims[i]}u)`); + } + return offsets.length > 0 ? offsets.join('+') : '0u'; + }; + broadcastImpl = ` + ${outputIndicesHelper.o2iImpl} + + fn calcOffsetA(outputIndices: ptr) -> u32 { + return ${calcOffsetImpl(dimsA)}; + } + + fn calcOffsetB(outputIndices: ptr) -> u32 { + return ${calcOffsetImpl(dimsB)}; + } + `; + } + let assignment; + if (vectorize) { + if (doBroadcast) { + assignment = ` + ${outputIndicesHelper.indicesVariableDeclaration('outputIndices')} + ${outputIndicesHelper.o2iCall('global_idx * 4u', 'outputIndices')} + let offsetA = calcOffsetA(&outputIndices); + let offsetB = calcOffsetB(&outputIndices); + outputData[global_idx] = ${expressionVector('aData[offsetA / 4u]', 'bData[offsetB / 4u]')};`; + } + else { + assignment = `outputData[global_idx] = ${expressionVector('aData[global_idx]', 'bData[global_idx]')};`; + } + } + else { + if (!doBroadcast) { + throw new Error('no necessary to use scalar implementation for element-wise binary op implementation.'); + } + const singleAssignment = (x) => { + const expressionA = `aData[indexA${x}][componentA${x}]`; + const expressionB = `bData[indexB${x}][componentB${x}]`; + return ` + ${outputIndicesHelper.o2iCall(`global_idx * 4u + ${x}u`, 'outputIndices')} + let offsetA${x} = calcOffsetA(&outputIndices); + let offsetB${x} = calcOffsetB(&outputIndices); + let indexA${x} = offsetA${x} / 4u; + let indexB${x} = offsetB${x} / 4u; + let componentA${x} = offsetA${x} % 4u; + let componentB${x} = offsetB${x} % 4u; + outputData[global_idx][${x}] = ${expressionScalar(expressionA, expressionB)};`; + }; + assignment = ` + ${outputIndicesHelper.indicesVariableDeclaration('outputIndices')} + ${singleAssignment(0)} + ${singleAssignment(1)} + ${singleAssignment(2)} + ${singleAssignment(3)}`; + } + return ` + @group(0) @binding(0) var aData : array>; + @group(0) @binding(1) var bData : array>; + @group(0) @binding(2) var outputData : array>; + + ${additionalImplementation !== null && additionalImplementation !== void 0 ? additionalImplementation : ''} + ${broadcastImpl} + + ${shaderHelper.mainStart()} + ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes(vecSize)} + ${assignment} + }`; +}; +const createBinaryOpProgramInfo = (metadata, a, b, funcCall, additionalImplementation, outputDataType = a.dataType) => { + var _a, _b; + const isBroadcast = !util_1.ShapeUtil.areEqual(a.dims, b.dims); + let outputShape = a.dims; + let outputSize = util_1.ShapeUtil.size(a.dims); + let vectorize = false; + // TODO: deal with zero-sized tensors (eg. dims=[1,0]) + if (isBroadcast) { + const calculatedShape = util_1.BroadcastUtil.calcShape(a.dims, b.dims, false); + if (!calculatedShape) { + throw new Error('Can\'t perform binary op on the given tensors'); + } + outputShape = calculatedShape; + outputSize = util_1.ShapeUtil.size(outputShape); + // check whether vectorize can be enabled + let sharedDimension = 1; + for (let i = 0; i < outputShape.length; i++) { + const dimA = (_a = a.dims[a.dims.length - i]) !== null && _a !== void 0 ? _a : 1; + const dimB = (_b = b.dims[b.dims.length - i]) !== null && _b !== void 0 ? _b : 1; + if (dimA === dimB) { + sharedDimension *= dimA; + } + else { + break; + } + } + if (sharedDimension % 4 === 0) { + vectorize = true; + } + } + else { + // element-wise + vectorize = true; + } + return Object.assign(Object.assign({}, metadata), { getShaderSource: (shaderHelper) => createBinaryOpProgramShader(shaderHelper, a.dims, b.dims, outputShape, vectorize, isBroadcast, funcCall, additionalImplementation), outputs: [{ dims: outputShape, dataType: outputDataType, gpuDataType: types_1.GpuDataType.default }], dispatchGroup: () => ({ x: Math.ceil(outputSize / 64 /* workgroup size */ / (vectorize ? 4 : 1) /* vec size */) }) }); +}; +const createBinaryOpProgramInfoLoader = (inputs, name, funcCall, additionalImplementation, cacheKey) => { + const metadata = { name, inputTypes: [types_1.GpuDataType.default, types_1.GpuDataType.default], cacheHint: cacheKey }; + return Object.assign(Object.assign({}, metadata), { get: () => createBinaryOpProgramInfo(metadata, inputs[0], inputs[1], funcCall, additionalImplementation) }); +}; +const add = (context) => { + context.compute(createBinaryOpProgramInfoLoader(context.inputs, 'Add', (a, b) => `${a}+${b}`)); +}; +exports.add = add; +const div = (context) => { + context.compute(createBinaryOpProgramInfoLoader(context.inputs, 'Div', (a, b) => `${a}/${b}`)); +}; +exports.div = div; +const mul = (context) => { + context.compute(createBinaryOpProgramInfoLoader(context.inputs, 'Mul', (a, b) => `${a}*${b}`)); +}; +exports.mul = mul; +const pow = (context) => { + context.compute(createBinaryOpProgramInfoLoader(context.inputs, 'Pow', ({ scalar: (a, b) => `pow_f32(${a},${b})`, vector: (a, b) => `pow_vf32(${a},${b})` }), ` + fn pow_f32(a : f32, b : f32) -> f32 { + if (b == 0.0) { + return 1.0; + } else if (a < 0.0 && b != floor(b)) { + return pow(a, b); // NaN + } + return select(sign(a), 1.0, round(abs(b) % 2.0) != 1.0) * pow(abs(a), b); + } + fn pow_vf32(a : vec4, b : vec4) -> vec4 { + // TODO: implement vectorized pow + return vec4(pow_f32(a.x, b.x), pow_f32(a.y, b.y), pow_f32(a.z, b.z), pow_f32(a.w, b.w)); + } + `)); +}; +exports.pow = pow; +const sub = (context) => { + context.compute(createBinaryOpProgramInfoLoader(context.inputs, 'Sub', (a, b) => `${a}-${b}`)); +}; +exports.sub = sub; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/ops/common.ts": +/*!********************************************!*\ + !*** ./lib/wasm/jsep/webgpu/ops/common.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.createShaderHelper = exports.createIndicesHelper = exports.WORKGROUP_SIZE = void 0; +const util_1 = __webpack_require__(/*! ../../util */ "./lib/wasm/jsep/util.ts"); +/** + * constant value for a workgroup size. + * + * We definitely can do further optimization in future, but for now we use 64. + * + * rule of thumb: Use [a workgroup size of] 64 unless you know what GPU you are targeting or that your workload + * needs something different. + * + * from: https://surma.dev/things/webgpu/ + **/ +exports.WORKGROUP_SIZE = 64; +const createIndicesHelper = (name, shape) => { + const iType = shape.length < 2 ? 'u32' : `array`; + const strides = util_1.ShapeUtil.computeStrides(shape); + let o2iSnippet = ''; + for (let i = 0; i < shape.length - 1; i++) { + o2iSnippet += ` + let dim${i} = current / ${strides[i]}u; + let rest${i} = current % ${strides[i]}u; + (*indices)[${i}] = dim${i}; + current = rest${i}; + `; + } + o2iSnippet += `(*indices)[${shape.length - 1}] = current;`; + const o2iImpl = shape.length < 2 ? '' : ` + fn ih_o2i_${name}(offset: u32, indices: ptr) { + var current = offset; + ${o2iSnippet} + }`; + const o2iCall = (varOffset, varIndices) => shape.length < 2 ? `${varIndices}=${varOffset};` : `ih_o2i_${name}(${varOffset}, &${varIndices});`; + const offsets = []; + if (shape.length === 0) { + offsets.push('0u'); + } + else if (shape.length < 2) { + offsets.push('(*indices)'); + } + else { + for (let i = shape.length - 1; i >= 0; i--) { + offsets.push(`${strides[i]}u * ((*indices)[${i}])`); + } + } + const i2oImpl = shape.length < 2 ? '' : ` + fn ih_i2o_${name}(indices: ptr) -> u32 { + return ${offsets.join('+')}; + }`; + const i2oExpression = (varIndices, isPtr) => shape.length < 2 ? `(${isPtr ? '*' : ''}${varIndices})` : `ih_i2o_${name}(${isPtr ? '' : '&'}${varIndices})`; + const indicesVariableDeclaration = (v, init) => `var ${v}:${iType}${init ? `=${iType}(${init.join(',')})` : ''};`; + return { o2iImpl, o2iCall, i2oImpl, i2oExpression, indicesVariableDeclaration, iType }; +}; +exports.createIndicesHelper = createIndicesHelper; +class ShaderHelperImpl { + constructor(normalizedDispatchGroup) { + this.normalizedDispatchGroup = normalizedDispatchGroup; + } + guardAgainstOutOfBoundsWorkgroupSizes(size) { + // Guard against out-of-bounds work group sizes + const sizeInCode = typeof size === 'number' ? `${size}u` : size; + return `if (global_idx >= ${sizeInCode}) { return; }`; + } + mainStart(workgroupSize = exports.WORKGROUP_SIZE) { + const workgroupSizeX = typeof workgroupSize === 'number' ? workgroupSize : workgroupSize[0]; + const workgroupSizeY = typeof workgroupSize === 'number' ? 1 : workgroupSize[1]; + const workgroupSizeZ = typeof workgroupSize === 'number' ? 1 : workgroupSize[2]; + const is1DimensionDispatch = this.normalizedDispatchGroup[1] === 1 && this.normalizedDispatchGroup[2] === 1; + const paramList = is1DimensionDispatch ? '@builtin(global_invocation_id) global_id : vec3' : + `@builtin(local_invocation_index) local_index : u32, + @builtin(workgroup_id) workgroup_id : vec3`; + const globalIdxDefinition = is1DimensionDispatch ? + 'let global_idx = global_id.x;' : + `let global_idx = (workgroup_id.z * ${this.normalizedDispatchGroup[0] * this.normalizedDispatchGroup[1]}u + + workgroup_id.y * ${this.normalizedDispatchGroup[0]}u + workgroup_id.x) * ${workgroupSizeX * workgroupSizeY * workgroupSizeZ}u + local_index;`; + return `@compute @workgroup_size(${workgroupSizeX}, ${workgroupSizeY}, ${workgroupSizeZ}) + fn main(${paramList}) { + ${globalIdxDefinition} + `; + } +} +const createShaderHelper = (dispatchGroup) => new ShaderHelperImpl(dispatchGroup); +exports.createShaderHelper = createShaderHelper; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/ops/conv-grouped.ts": +/*!**************************************************!*\ + !*** ./lib/wasm/jsep/webgpu/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.createGroupedConvProgramInfoLoader = void 0; +const util_1 = __webpack_require__(/*! ../../util */ "./lib/wasm/jsep/util.ts"); +const types_1 = __webpack_require__(/*! ../types */ "./lib/wasm/jsep/webgpu/types.ts"); +const common_1 = __webpack_require__(/*! ./common */ "./lib/wasm/jsep/webgpu/ops/common.ts"); +const conv_1 = __webpack_require__(/*! ./conv */ "./lib/wasm/jsep/webgpu/ops/conv.ts"); +const fuse_utils_1 = __webpack_require__(/*! ./fuse-utils */ "./lib/wasm/jsep/webgpu/ops/fuse-utils.ts"); +const createGroupedConvProgramMetadata = (hasBias, cacheHint) => ({ + name: 'GroupedConv', + inputTypes: hasBias ? [types_1.GpuDataType.default, types_1.GpuDataType.default, types_1.GpuDataType.default] : + [types_1.GpuDataType.default, types_1.GpuDataType.default], + cacheHint +}); +const createGroupedConvProgramInfo = (inputs, metadata, attributes, squeezeOutputShapeFunction) => { + const hasBias = inputs.length > 2; + const processBias = hasBias ? 'value += b[output_channel];' : ''; + const xShape = inputs[0].dims; + const wShape = inputs[1].dims; + const outputChannelsPerGroup = wShape[0] / attributes.group; + const dataType = 'f32'; // TODO: support other data type + const { activationFunction, applyActivation } = (0, fuse_utils_1.getActicationSnippet)(attributes); + const inputStorageBuffersDeclarations = [ + `@group(0) @binding(0) var x : array<${dataType}>;`, + `@group(0) @binding(1) var w : array<${dataType}>;` + ]; + if (hasBias) { + inputStorageBuffersDeclarations.push(`@group(0) @binding(2) var b : array<${dataType}>;`); + } + const isChannelLast = attributes.format === 'NHWC'; + const outputShape = (0, conv_1.calculateOutputShape)(xShape, wShape, attributes.dilations, attributes.pads, attributes.strides, isChannelLast); + const outputSize = util_1.ShapeUtil.size(outputShape); + const outputIndicesHelper = (0, common_1.createIndicesHelper)('output', outputShape); + const xIndicesHelper = (0, common_1.createIndicesHelper)('x', xShape); + const wIndicesHelper = (0, common_1.createIndicesHelper)('w', wShape); + const getShaderSource = (shaderHelper) => ` + const strides: vec2 = vec2(${attributes.strides[0]}u, ${attributes.strides[1]}u); + const pads: vec2 = vec2(${attributes.pads[0]}u, ${attributes.pads[1]}u); + + ${inputStorageBuffersDeclarations.join('\n')} + @group(0) @binding(${inputStorageBuffersDeclarations.length}) var output : array<${dataType}>; + + ${activationFunction} + ${outputIndicesHelper.o2iImpl} + ${xIndicesHelper.i2oImpl} + ${wIndicesHelper.i2oImpl} + + ${shaderHelper.mainStart()} + ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes(outputSize)} + + ${outputIndicesHelper.indicesVariableDeclaration('outputIndices')} + ${outputIndicesHelper.o2iCall('global_idx', 'outputIndices')} + let batch: u32 = outputIndices[0]; + let output_channel: u32 = outputIndices[${isChannelLast ? 3 : 1}]; + let xRCCorner: vec2 = vec2(outputIndices[${isChannelLast ? 1 : 2}], outputIndices[${isChannelLast ? 2 : 3}]) * strides - pads; + let group_id: u32 = output_channel / ${outputChannelsPerGroup}u; + + var value: ${dataType} = ${dataType}(0); + for (var wInChannel: u32 = 0u; wInChannel < ${wShape[1]}u; wInChannel++) { + let input_channel = group_id * ${wShape[1]}u + wInChannel; + for (var wHeight: u32 = 0u; wHeight < ${wShape[2]}u; wHeight++) { + let xHeight = xRCCorner.x + wHeight * ${attributes.dilations[0]}u; + + if (xHeight < 0u || xHeight >= ${xShape[isChannelLast ? 1 : 2]}u) { + continue; + } + + for (var wWidth: u32 = 0u; wWidth < ${wShape[3]}u; wWidth++) { + let xWidth = xRCCorner.y + wWidth * ${attributes.dilations[1]}u; + if (xWidth < 0u || xWidth >= ${xShape[isChannelLast ? 2 : 3]}u) { + continue; + } + + ${xIndicesHelper.indicesVariableDeclaration('xIndices', isChannelLast ? ['batch', 'xHeight', 'xWidth', 'input_channel'] : + [ + 'batch', 'input_channel', 'xHeight', 'xWidth' + ])} + let xVal = x[${xIndicesHelper.i2oExpression('xIndices')}]; + ${wIndicesHelper.indicesVariableDeclaration('wIndices', [ + 'output_channel', 'wInChannel', 'wHeight', 'wWidth' + ])} + let wVal = w[${wIndicesHelper.i2oExpression('wIndices')}]; + value += xVal*wVal; + } + } + } + ${processBias} + ${applyActivation} + output[global_idx] = value; + }`; + return Object.assign(Object.assign({}, metadata), { outputs: [{ + dims: squeezeOutputShapeFunction ? squeezeOutputShapeFunction(outputShape) : outputShape, + dataType: inputs[0].dataType, + gpuDataType: types_1.GpuDataType.default + }], getShaderSource, dispatchGroup: () => ({ x: Math.ceil(outputSize / 64 /* workgroup size */) }) }); +}; +/** + * naive grouped conv implementation, supports 1d/2d conv + * @param squeezeOutputShapeFunction - an optional function to squeeze the output shape, only used in conv1d + */ +const createGroupedConvProgramInfoLoader = (inputs, attributes, squeezeOutputShapeFunction) => { + const metadata = createGroupedConvProgramMetadata(inputs.length > 2, attributes.cacheKey); + return Object.assign(Object.assign({}, metadata), { get: () => createGroupedConvProgramInfo(inputs, metadata, attributes, squeezeOutputShapeFunction) }); +}; +exports.createGroupedConvProgramInfoLoader = createGroupedConvProgramInfoLoader; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/ops/conv.ts": +/*!******************************************!*\ + !*** ./lib/wasm/jsep/webgpu/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.conv = exports.parseConvAttributes = exports.calculateOutputShape = void 0; +const util_1 = __webpack_require__(/*! ../../util */ "./lib/wasm/jsep/util.ts"); +const attribute_with_cache_key_1 = __webpack_require__(/*! ../attribute-with-cache-key */ "./lib/wasm/jsep/webgpu/attribute-with-cache-key.ts"); +const conv_grouped_1 = __webpack_require__(/*! ./conv-grouped */ "./lib/wasm/jsep/webgpu/ops/conv-grouped.ts"); +const conv2d_mm_1 = __webpack_require__(/*! ./conv2d-mm */ "./lib/wasm/jsep/webgpu/ops/conv2d-mm.ts"); +const fuse_utils_1 = __webpack_require__(/*! ./fuse-utils */ "./lib/wasm/jsep/webgpu/ops/fuse-utils.ts"); +const transpose_1 = __webpack_require__(/*! ./transpose */ "./lib/wasm/jsep/webgpu/ops/transpose.ts"); +const calculateOutputShape = (inputShape, kernelShape, dilations, adjustPads, strides, isChannelLast) => { + const batchSize = inputShape[0]; + const inputSpatialShape = inputShape.slice(isChannelLast ? 1 : 2, isChannelLast ? 3 : 4); + 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 outputShape = inputSpatialShapeWithPad.map((v, i) => Math.floor((v - dilatedKernelShape[i] + strides[i]) / strides[i])); + outputShape.splice(0, 0, batchSize); + outputShape.splice(isChannelLast ? 3 : 1, 0, outChannels); + return outputShape; +}; +exports.calculateOutputShape = calculateOutputShape; +// for transposing weight tensor from [M, C/group, KH, KW] to [KH, KW, C/group, M] +const weightTransposeAttribute = (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ perm: [2, 3, 1, 0] }); +const validateInputs = (inputs, attributes) => { + // Refer to the below link for all input checks + // https://github.com/onnx/onnx/blob/master/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[0].dims.length !== 3) { + throw new Error('currently only support conv 1D and 2D'); + } + if (inputs[0].dims.length !== inputs[1].dims.length) { + throw new Error('filter does not have same dimension as input'); + } + // FILTER_IN_CHANNEL should be equal to DATA_CHANNEL + const dataChannel = inputs[0].dims[attributes.format === 'NHWC' ? inputs[0].dims.length - 1 : 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].dataType !== 1 /* DataType.float */ || inputs[1].dataType !== 1 /* DataType.float */) { + throw new Error('Conv input(X,W) should be float tensor'); + } + if (inputs.length === 3 && inputs[2].dataType !== 1 /* DataType.float */) { + throw new Error('Conv input(bias) should be float tensor'); + } +}; +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 + for (let i = 2; i < inputs[1].dims.length; ++i) { + if (kernelShape[i - 2] === 0) { + kernelShape[i - 2] = inputs[1].dims[i]; + } + } + const pads = attributes.pads.slice(); + util_1.PoolConvUtil.adjustPadsBasedOnAutoPad(inputs[0].dims, attributes.strides, attributes.dilations, kernelShape, pads, attributes.format === 'NHWC', 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 = (attributes) => { + const activationAttributes = (0, fuse_utils_1.parseInternalActivationAttributes)(attributes); + // TODO : Make this generic enough to compute default attributes for multi-dimensional conv + const format = attributes.format; + const autoPad = ['NOTSET', 'VALID', 'SAME_UPPER', 'SAME_LOWER'][attributes.auto_pad]; + const dilations = attributes.dilations; + const group = attributes.group; + const kernelShape = attributes.kernel_shape; + const pads = attributes.pads; + const strides = attributes.strides; + const wIsConst = attributes.w_is_const(); + return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)(Object.assign({ autoPad, format, dilations, group, kernelShape, pads, strides, wIsConst }, activationAttributes)); +}; +exports.parseConvAttributes = parseConvAttributes; +const conv2d = (context, inputs, attributes) => { + var _a; + const adjustedAttributes = getAdjustedConvAttributes(attributes, inputs); + // check attributes + const hasBias = inputs.length === 3; + // const hasPreluActivationWeights = false; /* TODO: add support for prelu activation weights */ + const isChannelsLast = attributes.format === 'NHWC'; + // const batchSize = context.inputs[0].dims[0]; + const inputHeight = inputs[0].dims[isChannelsLast ? 1 : 2]; + const inputWidth = inputs[0].dims[isChannelsLast ? 2 : 3]; + const inputChannels = inputs[0].dims[isChannelsLast ? 3 : 1]; + const weightHeight = inputs[1].dims[2]; + const weightWidth = inputs[1].dims[3]; + const outputShape = (0, exports.calculateOutputShape)(inputs[0].dims, inputs[1].dims, attributes.dilations, adjustedAttributes.pads, attributes.strides, isChannelsLast); + const outHeight = outputShape[isChannelsLast ? 1 : 2]; + const outWidth = outputShape[isChannelsLast ? 2 : 3]; + const outChannels = outputShape[isChannelsLast ? 3 : 1]; + const sameSize = isChannelsLast && weightHeight === inputHeight && weightWidth === inputWidth && attributes.autoPad === 'VALID'; + if (sameSize || + (weightHeight === 1 && weightWidth === 1 && attributes.dilations[0] === 1 && attributes.dilations[1] === 1 && + attributes.strides[0] === 1 && attributes.strides[1] === 1 && + (attributes.autoPad === 'SAME_UPPER' || attributes.autoPad === 'SAME_LOWER' || + attributes.autoPad === 'VALID'))) { + // TODO: implement conv2dByMatMul() + context.compute((0, conv_grouped_1.createGroupedConvProgramInfoLoader)(inputs, adjustedAttributes)); + return; + } + if (!isChannelsLast || attributes.group !== 1) { + context.compute((0, conv_grouped_1.createGroupedConvProgramInfoLoader)(inputs, adjustedAttributes)); + return; + } + // TODO: implement conv2dWithIm2Col() + const dimAOuter = isChannelsLast ? outHeight * outWidth : outChannels; + const dimBOuter = isChannelsLast ? outChannels : outHeight * outWidth; + const dimInner = weightHeight * weightWidth * inputChannels; + const sequentialAccessByThreads = /* backend.adapterInfo.isIntel() */ true; + // STEP.1: transpose weight + const transposedWeight = (_a = context.customData.wT) !== null && _a !== void 0 ? _a : context.compute(Object.assign(Object.assign({}, transpose_1.transposeProgramMetadata), { cacheHint: weightTransposeAttribute.cacheKey, get: () => (0, transpose_1.createTransposeProgramInfo)(inputs[1], weightTransposeAttribute.perm) }), { inputs: [1], outputs: [attributes.wIsConst ? -2 : -1] })[0]; + if (attributes.wIsConst && !context.customData.wT) { + context.customData.wT = transposedWeight; + } + // STEP.2: prepare reshaped inputs + const convInputs = [inputs[0], transposedWeight]; + if (hasBias) { + if (!isChannelsLast && inputs[2].dims.length === 1) { + convInputs.push(inputs[2].reshape([inputs[2].dims[0], 1, 1])); + } + else { + convInputs.push(inputs[2]); + } + } + // STEP.3: compute matmul + context.compute((0, conv2d_mm_1.createConv2DMatMulProgramInfoLoader)(convInputs, adjustedAttributes, outputShape, dimAOuter, dimBOuter, dimInner, hasBias, sequentialAccessByThreads), { inputs: convInputs }); +}; +const conv1d = (context, attributes) => { + // extend the input to 2D by adding H dimension + const isChannelLast = attributes.format === 'NHWC'; + const inputs = [ + context.inputs[0].reshape(isChannelLast ? + // [N, W, C] -> [N, H=1, W, C] + [context.inputs[0].dims[0], 1, context.inputs[0].dims[1], context.inputs[0].dims[2]] : + // [N, C, W] -> [N, C, H=1, W] + [context.inputs[0].dims[0], context.inputs[0].dims[1], 1, context.inputs[0].dims[2]]), + //[FILTER_OUT_CHANNEL, FILTER_IN_CHANNEL, kW] -> [FILTER_OUT_CHANNEL, FILTER_IN_CHANNEL, kH=1, kW] + context.inputs[1].reshape([context.inputs[1].dims[0], context.inputs[1].dims[1], 1, context.inputs[1].dims[2]]) + ]; + if (context.inputs.length === 3) { + inputs.push(context.inputs[2]); + } + const pads = [0, attributes.pads[0], 0, attributes.pads[1]]; + const strides = [1].concat(attributes.strides); + const dilations = [1].concat(attributes.dilations); + const kernelShape = [1].concat(attributes.kernelShape); + const adjustedAttributes = getAdjustedConvAttributes(Object.assign(Object.assign({}, attributes), { pads, strides, dilations, kernelShape }), inputs); + context.compute((0, conv_grouped_1.createGroupedConvProgramInfoLoader)(inputs, adjustedAttributes, outputShape => isChannelLast ? [outputShape[0], outputShape[2], outputShape[3]] : [])); +}; +const conv = (context, attributes) => { + validateInputs(context.inputs, attributes); // currently will fail if not conv1D/2D + if (context.inputs[0].dims.length === 3) { + conv1d(context, attributes); + } + else { + conv2d(context, context.inputs, attributes); + } +}; +exports.conv = conv; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/ops/conv2d-mm.ts": +/*!***********************************************!*\ + !*** ./lib/wasm/jsep/webgpu/ops/conv2d-mm.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.createConv2DMatMulProgramInfoLoader = void 0; +const types_1 = __webpack_require__(/*! ../types */ "./lib/wasm/jsep/webgpu/types.ts"); +const conv2d_mm_webgpu_1 = __webpack_require__(/*! ./3rd-party/conv2d_mm_webgpu */ "./lib/wasm/jsep/webgpu/ops/3rd-party/conv2d_mm_webgpu.ts"); +const createConv2DMatMulProgramMetadata = (hasBias, cacheHint) => ({ + name: 'Conv2DMatMul', + inputTypes: hasBias ? [types_1.GpuDataType.default, types_1.GpuDataType.default, types_1.GpuDataType.default] : + [types_1.GpuDataType.default, types_1.GpuDataType.default], + cacheHint +}); +const createConv2DMatMulProgramInfoLoader = (inputs, attributes, outputShape, dimAOuter, dimBOuter, dimInner, hasBias, sequentialAccessByThreads) => { + const metadata = createConv2DMatMulProgramMetadata(hasBias, attributes.cacheKey); + return Object.assign(Object.assign({}, metadata), { get: () => (0, conv2d_mm_webgpu_1.createConv2DMatMulProgramInfo)(inputs, metadata, attributes, outputShape, dimAOuter, dimBOuter, dimInner, hasBias, sequentialAccessByThreads) }); +}; +exports.createConv2DMatMulProgramInfoLoader = createConv2DMatMulProgramInfoLoader; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/ops/fuse-utils.ts": +/*!************************************************!*\ + !*** ./lib/wasm/jsep/webgpu/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.getActicationSnippet = void 0; +const util_1 = __webpack_require__(/*! ../../util */ "./lib/wasm/jsep/util.ts"); +const getActicationSnippet = (attributes) => { + switch (attributes.activation) { + case 'Relu': + return { activationFunction: '', applyActivation: 'value = max(value, 0.0);' }; + case 'Sigmoid': + return { activationFunction: '', applyActivation: 'value = (1.0 / (1.0 + exp(-value)));' }; + case 'Clip': + return { + activationFunction: `const clip_min_=f32(${attributes.clipMin});const clip_max_=f32(${attributes.clipMax});`, + applyActivation: 'value = clamp(value, clip_min_, clip_max_);' + }; + // TODO: adding other activations that can be fused. + default: + return { activationFunction: '', applyActivation: '' }; + } +}; +exports.getActicationSnippet = getActicationSnippet; +const parseInternalActivationAttributes = (attributes) => { + const activation = (attributes === null || attributes === void 0 ? void 0 : attributes.activation) || ''; + if (activation === 'Clip') { + const [clipMin, clipMax] = (attributes === null || attributes === void 0 ? void 0 : attributes.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/wasm/jsep/webgpu/ops/gemm.ts": +/*!******************************************!*\ + !*** ./lib/wasm/jsep/webgpu/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.parseGemmAttributes = exports.gemm = void 0; +const util_1 = __webpack_require__(/*! ../../util */ "./lib/wasm/jsep/util.ts"); +const attribute_with_cache_key_1 = __webpack_require__(/*! ../attribute-with-cache-key */ "./lib/wasm/jsep/webgpu/attribute-with-cache-key.ts"); +const types_1 = __webpack_require__(/*! ../types */ "./lib/wasm/jsep/webgpu/types.ts"); +const validateInputs = (inputs) => { + if (!inputs) { + throw new Error('Input is missing'); + } + if (inputs.length < 2 || inputs.length > 3) { + throw new Error('Invaid input number.'); + } + // 'C' can be of dimensionality 0, 1 or 2 only + if (inputs.length === 3 && inputs[2].dims.length > 2) { + throw new Error('Invalid input shape of C'); + } + if ((inputs[0].dataType !== 1 /* DataType.float */) || (inputs[1].dataType !== 1 /* DataType.float */) || + (inputs.length === 3 && inputs[2].dataType !== 1 /* DataType.float */)) { + throw new Error('Invalid input type.'); + } + if ((inputs[0].dataType !== inputs[1].dataType) || + (inputs.length === 3 && inputs[0].dataType !== inputs[2].dataType)) { + throw new Error('Input types are mismatched'); + } +}; +const offsetC = (m, n, dims) => { + if (dims.length === 0) { + return '0u'; + } + const broadcastM = (dims.length === 1 && m !== 1) || (dims.length === 2 && dims[0] !== m); + const broadcastN = dims[dims.length - 1] !== n; + let offset = '0u'; + if (!broadcastM) { + offset += `+ m * ${dims[dims.length - 1]}u`; + } + if (!broadcastN) { + offset += '+n'; + } + return offset; +}; +const createGemmProgramInfo = (metadata, inputs, attributes) => { + const aShape = inputs[0].dims.slice(); + const bShape = inputs[1].dims.slice(); + const [M, N, K] = 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'); + } + const outputSize = util_1.ShapeUtil.size(outputShape); + let line = ''; + if (attributes.transA && attributes.transB) { + line = 'value += a[k * M + m] * b[n * K + k];'; + } + else if (attributes.transA && !attributes.transB) { + line = 'value += a[k * M + m] * b[k * N + n];'; + } + else if (!attributes.transA && attributes.transB) { + line = 'value += a[m * K + k] * b[n * K + k];'; + } + else if (!attributes.transA && !attributes.transB) { + line = 'value += a[m * K + k] * b[k * N + n];'; + } + const dataType = 'f32'; // TODO: support other data type + const calculateAlpha = attributes.alpha === 1 ? '' : 'value *= alpha;'; + const calculateC = inputs.length === 3 ? `value += beta * c[${offsetC(M, N, inputs[2].dims)}];` : ''; + const inputStorageBuffersDeclarations = [ + `@group(0) @binding(0) var a : array<${dataType}>;`, + `@group(0) @binding(1) var b : array<${dataType}>;` + ]; + if (inputs.length === 3) { + inputStorageBuffersDeclarations.push(`@group(0) @binding(2) var c : array<${dataType}>;`); + } + const getShaderSource = (shaderHelper) => ` + const M: u32 = ${M}u; + const N: u32 = ${N}u; + const K: u32 = ${K}u; + const alpha = ${dataType}(${attributes.alpha}); + const beta = ${dataType}(${attributes.beta}); + + ${inputStorageBuffersDeclarations.join('\n')} + @group(0) @binding(${inputs.length}) var output : array<${dataType}>; + + ${shaderHelper.mainStart()} + ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes(outputSize)} + + let m = global_id.x / N; + let n = global_id.x % N; + + var value = ${dataType}(0); + for (var k: u32 = 0u; k<${K}u; k++) { + ${line} + } + + ${calculateAlpha} + ${calculateC} + output[global_id.x] = value; + + }`; + return Object.assign(Object.assign({}, metadata), { outputs: [{ dims: outputShape, dataType: inputs[0].dataType, gpuDataType: types_1.GpuDataType.default }], getShaderSource, dispatchGroup: () => ({ x: Math.ceil(outputSize / 64 /* workgroup size */) }) }); +}; +const createGemmProgramInfoLoader = (inputs, attributes) => { + const metadata = { + name: 'Gemm', + inputTypes: inputs.length === 3 ? [types_1.GpuDataType.default, types_1.GpuDataType.default, types_1.GpuDataType.default] : + [types_1.GpuDataType.default, types_1.GpuDataType.default], + cacheHint: attributes.cacheKey + }; + return Object.assign(Object.assign({}, metadata), { get: () => createGemmProgramInfo(metadata, inputs, attributes) }); +}; +const gemm = (context, attributes) => { + validateInputs(context.inputs); + context.compute(createGemmProgramInfoLoader(context.inputs, attributes)); +}; +exports.gemm = gemm; +const parseGemmAttributes = (attributes) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)(attributes); +exports.parseGemmAttributes = parseGemmAttributes; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/ops/matmul.ts": +/*!********************************************!*\ + !*** ./lib/wasm/jsep/webgpu/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.matMul = exports.createMatmulProgramInfoLoader = void 0; +const util_1 = __webpack_require__(/*! ../../util */ "./lib/wasm/jsep/util.ts"); +const types_1 = __webpack_require__(/*! ../types */ "./lib/wasm/jsep/webgpu/types.ts"); +const fuse_utils_1 = __webpack_require__(/*! ./fuse-utils */ "./lib/wasm/jsep/webgpu/ops/fuse-utils.ts"); +const createMatmulProgramMetadata = (hasBias, cacheHint) => ({ + name: 'MatMul', + inputTypes: hasBias ? [types_1.GpuDataType.default, types_1.GpuDataType.default, types_1.GpuDataType.default] : + [types_1.GpuDataType.default, types_1.GpuDataType.default], + cacheHint +}); +const 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 outputSize = util_1.ShapeUtil.size(outputShape); + // TODO: support broadcasting + const dataType = 'f32'; // TODO: support other data type + const { activationFunction, applyActivation } = (0, fuse_utils_1.getActicationSnippet)(activationAttributes); + const M = outputShape[outputShape.length - 2]; + const K = aShape[aShape.length - 1]; + const N = outputShape[outputShape.length - 1]; + const getShaderSource = (shaderHelper) => ` + const M: u32 = ${M}u; + const N: u32 = ${N}u; + const K: u32 = ${K}u; + + @group(0) @binding(0) var a : array<${dataType}>; + @group(0) @binding(1) var b : array<${dataType}>; + @group(0) @binding(2) var output : array<${dataType}>; + + ${activationFunction} + + ${shaderHelper.mainStart()} + ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes(outputSize)} + + let stack = global_idx / (M * N); + let mn = global_idx % (M * N); + let n = global_idx % N; + let m = mn / N; + + let offsetA = stack * (M * K); + let offsetB = stack * (K * N); + + var value = ${dataType}(0); + for (var k: u32 = 0u; k<${K}u; k++) { + value += a[offsetA + m * K + k] * b[offsetB + k * N + n]; + } + ${applyActivation} + output[global_idx] = value; + }`; + return Object.assign(Object.assign({}, metadata), { outputs: [{ dims: outputShape, dataType: inputs[0].dataType, gpuDataType: types_1.GpuDataType.default }], getShaderSource, dispatchGroup: () => ({ x: Math.ceil(outputSize / 64 /* workgroup size */) }) }); +}; +const 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].dataType !== 1 /* DataType.float */ || inputs[1].dataType !== 1 /* DataType.float */) { + throw new Error('inputs should be float type'); + } +}; +const matMul = (context) => { + validateInputs(context.inputs); + context.compute((0, exports.createMatmulProgramInfoLoader)(context.inputs, { activation: '', activationCacheKey: '' })); +}; +exports.matMul = matMul; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/ops/pool.ts": +/*!******************************************!*\ + !*** ./lib/wasm/jsep/webgpu/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.parseGlobalMaxPoolAttributes = exports.parseMaxPoolAttributes = exports.maxPool = exports.globalAveragePool = exports.parseGlobalAveragePoolAttributes = exports.averagePool = exports.parseAveragePoolAttributes = void 0; +const util_1 = __webpack_require__(/*! ../../util */ "./lib/wasm/jsep/util.ts"); +const attribute_with_cache_key_1 = __webpack_require__(/*! ../attribute-with-cache-key */ "./lib/wasm/jsep/webgpu/attribute-with-cache-key.ts"); +const types_1 = __webpack_require__(/*! ../types */ "./lib/wasm/jsep/webgpu/types.ts"); +const common_1 = __webpack_require__(/*! ./common */ "./lib/wasm/jsep/webgpu/ops/common.ts"); +// TODO: support: +// - ceil_mode "test_maxpool_2d_ceil" +// - storage_order "test_maxpool_with_argmax_2d_precomputed_strides" +// - [MaxPool] dilations "test_maxpool_2d_dilations" +// - [MaxPool] output[1] "test_maxpool_with_argmax_2d_precomputed_pads" +const validateInputs = (inputs) => { + if (!inputs || inputs.length !== 1) { + throw new Error('Pool ops requires 1 input.'); + } + if (inputs[0].dims.length !== 4) { + throw new Error('Pool ops supports 2-D inputs only for now.'); + } + if (inputs[0].dataType !== 1 /* DataType.float */) { + throw new Error('Invalid input type.'); + } +}; +const getAdjustedPoolAttributesAndOutputShape = (inputs, attributes, isGlobalOperator) => { + const isChannelsLast = attributes.format === 'NHWC'; + const inputShapeAsChannelFirst = isChannelsLast ? + [inputs[0].dims[0], inputs[0].dims[3], inputs[0].dims[1], inputs[0].dims[2]] : + 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, inputShapeAsChannelFirst, kernelShape, strides, dilations, pads); + const outputShapeAsChannelFirst = util_1.PoolConvUtil.computePoolOutputShape(isGlobalOperator, inputShapeAsChannelFirst, 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, + isChannelsLast ? + [ + outputShapeAsChannelFirst[0], outputShapeAsChannelFirst[2], outputShapeAsChannelFirst[3], + outputShapeAsChannelFirst[1] + ] : + outputShapeAsChannelFirst + ]; +}; +const generatePoolingCode = (shaderHelper, inputDims, outputShape, attributes, op1, op2, dataType, start) => { + const isChannelsLast = attributes.format === 'NHWC'; + const rank = inputDims.length; + const outputSize = util_1.ShapeUtil.size(outputShape); + const outputIndicesHelper = (0, common_1.createIndicesHelper)('output', outputShape); + const xIndicesHelper = (0, common_1.createIndicesHelper)('x', inputDims); + 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 dimIdxW = rank - (isChannelsLast ? 2 : 1); + let codeW = ''; + let codeH = ''; + let codeHEnd = ''; + if (pwStart + pwEnd !== 0) { + codeW = ` + for (var i: u32 = 0u; i < ${kw}u; i++) { + xIndices[${dimIdxW}] = indices[${dimIdxW}] * ${sw} - ${pwStart} + i; + if (xIndices[${dimIdxW}] < 0 || xIndices[${dimIdxW}] >= ${inputDims[dimIdxW]}) { + pad++; + continue; + } + let x_val = x[${xIndicesHelper.i2oExpression('xIndices')}]; + ${op1} + }`; + } + else { + codeW = ` + for (var i: u32 = 0u; i < ${kw}u; i++) { + xIndices[${dimIdxW}] = indices[${dimIdxW}] * ${sw} - ${pwStart} + i; + let x_val = x[${xIndicesHelper.i2oExpression('xIndices')}]; + ${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 dimIdxH = rank - (isChannelsLast ? 3 : 2); + const dimH = inputDims[dimIdxH]; + if (phStart + phEnd !== 0) { + codeH = ` + for (var j: u32 = 0u; j < ${kh}u; j++) { + xIndices[${dimIdxH}] = indices[${dimIdxH}] * ${sh} - ${phStart} + j; + if (xIndices[${dimIdxH}] < 0 || xIndices[${dimIdxH}] >= ${dimH}) { + pad+= ${kw}; + continue; + } + `; + } + else { + codeH = ` + for (var j: u32 = 0u; j < ${kh}u; j++) { + xIndices[${dimIdxH}] = indices[${dimIdxH}] * ${sh} - ${phStart} + j; + `; + } + codeHEnd = ` + } + `; + } + const poolingCode = ` + @group(0) @binding(0) var x : array<${dataType}>; + @group(0) @binding(1) var output : array<${dataType}>; + + ${outputIndicesHelper.o2iImpl} + ${xIndicesHelper.i2oImpl} + + ${shaderHelper.mainStart()} + ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes(outputSize)} + + ${outputIndicesHelper.indicesVariableDeclaration('indices')} + ${outputIndicesHelper.o2iCall('global_idx', 'indices')} + ${outputIndicesHelper.indicesVariableDeclaration('xIndices')} + ${outputIndicesHelper.o2iCall('global_idx', 'xIndices')} + + var value: ${dataType} = ${dataType}(${start}); + var pad = 0; + ${codeH} + ${codeW} + ${codeHEnd} + ${op2} + + output[global_idx] = value; + }`; + return poolingCode; + } + else { + if (isChannelsLast) { + throw new Error('Pooling with kernelShape.length > 2 is not supported for NHWC format.'); + } + 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 hasPads = attributes.pads.reduce((sum, cur) => sum + cur); + let padCode = ''; + if (hasPads) { + padCode = ` + if (xIndices[j] >= inputDims[j]) { + pad++; + isPad = true; + break; + } + } + if (!isPad) { + let x_val = x[${xIndicesHelper.i2oExpression('xIndices')}]; + ${op1} + }`; + } + else { + padCode = ` + } + let x_val = x[${xIndicesHelper.i2oExpression('xIndices')}]; + ${op1} + `; + } + const poolingCode = ` + @group(0) @binding(0) var x : array<${dataType}>; + @group(0) @binding(1) var output : array<${dataType}>; + + ${outputIndicesHelper.o2iImpl} + ${xIndicesHelper.i2oImpl} + + const pads = array(${attributes.pads.map(i => `${i}u`).join(',')}); + const inputDims = array(${inputDims.map(i => `${i}u`).join(',')}); + const kernelStrides = array(${kernelStrides.map(i => `${i}u`).join(',')}); + const strides = array(${attributes.strides.map(i => `${i}u`).join(',')}); + + ${shaderHelper.mainStart()} + ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes(outputSize)} + + ${outputIndicesHelper.indicesVariableDeclaration('indices')} + ${outputIndicesHelper.o2iCall('global_idx', 'indices')} + ${outputIndicesHelper.indicesVariableDeclaration('xIndices')} + ${outputIndicesHelper.o2iCall('global_idx', 'xIndices')} + + var offsets: array; + + var value = ${dataType}(${start}); + var pad = 0; + var isPad = false; + + for (var i: u32 = 0u; i < ${kernelSize}u; i++) { + var offset = i; + for (var j = 0u; j < ${stridesRank - 1}u; j++) { + offsets[j] = offset / kernelStrides[j]; + offset -= offsets[j] * kernelStrides[j]; + } + offsets[${stridesRank - 1}] = offset; + + isPad = false; + for (var j = ${rank - stridesRank}u; j < ${rank}u; j++) { + xIndices[j] = indices[j] * strides[j - ${rank - stridesRank}u] + + offsets[j - ${rank - stridesRank}u] - pads[j - 2u]; + ${padCode} + } + ${op2} + + output[global_idx] = value; + }`; + return poolingCode; + } +}; +const parsePoolCommonAttributes = (attributes) => ({ + format: attributes.format, + autoPad: ['NOTSET', 'VALID', 'SAME_UPPER', 'SAME_LOWER'][attributes.auto_pad], + ceilMode: attributes.ceil_mode, + kernelShape: attributes.kernel_shape, + strides: attributes.strides, + pads: attributes.pads +}); +const createAveragePoolProgramInfo = (inputs, metadata, isGlobalOperator, attributes) => { + const [adjustedAttributes, outputShape] = getAdjustedPoolAttributesAndOutputShape(inputs, attributes, isGlobalOperator); + const kernelSize = util_1.ShapeUtil.size(adjustedAttributes.kernelShape); + const dataType = 'f32'; + const op1 = 'value += x_val;'; + let op2 = ''; + if (adjustedAttributes.countIncludePad) { + op2 += `value /= ${dataType}(${kernelSize});`; + } + else { + op2 += `value /= ${dataType}(${kernelSize} - pad);`; + } + return Object.assign(Object.assign({}, metadata), { outputs: [{ dims: outputShape, dataType: inputs[0].dataType, gpuDataType: types_1.GpuDataType.default }], getShaderSource: shaderHelper => generatePoolingCode(shaderHelper, inputs[0].dims, outputShape, adjustedAttributes, op1, op2, dataType, '0.0'), dispatchGroup: () => ({ x: Math.ceil(util_1.ShapeUtil.size(outputShape) / 64 /* workgroup size */) }) }); +}; +const parseAveragePoolAttributes = (attributes) => { + const countIncludePad = attributes.count_include_pad === 0 ? false : true; + const attr = parsePoolCommonAttributes(attributes); + // TODO: support attribute 'ceil_mode' + if (attr.ceilMode !== 0) { + throw new Error('using ceil() in shape computation is not yet supported for AveragePool'); + } + return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)(Object.assign({ countIncludePad }, attr)); +}; +exports.parseAveragePoolAttributes = parseAveragePoolAttributes; +const averagePool = (context, attributes) => { + validateInputs(context.inputs); + const metadata = { name: 'AveragePool', inputTypes: [types_1.GpuDataType.default], cacheHint: attributes.cacheKey }; + context.compute(Object.assign(Object.assign({}, metadata), { get: () => createAveragePoolProgramInfo(context.inputs, metadata, false, attributes) })); +}; +exports.averagePool = averagePool; +const globalPoolAttributes = { + autoPad: '', + ceilMode: 0, + countIncludePad: false, + kernelShape: [], + strides: [], + pads: [], + storageOrder: 0, + dilations: [], + cacheKey: '' +}; +const parseGlobalAveragePoolAttributes = (attributes) => { + const format = attributes.format; + return Object.assign(Object.assign({ format }, globalPoolAttributes), { cacheKey: format }); +}; +exports.parseGlobalAveragePoolAttributes = parseGlobalAveragePoolAttributes; +const globalAveragePool = (context, attributes) => { + validateInputs(context.inputs); + const metadata = { name: 'GlobalAveragePool', inputTypes: [types_1.GpuDataType.default], cacheHint: attributes.cacheKey }; + context.compute(Object.assign(Object.assign({}, metadata), { get: () => createAveragePoolProgramInfo(context.inputs, metadata, true, attributes) })); +}; +exports.globalAveragePool = globalAveragePool; +const createMaxPoolProgramInfo = (inputs, metadata, isGlobalOperator, attributes) => { + const [adjustedAttributes, outputShape] = getAdjustedPoolAttributesAndOutputShape(inputs, attributes, isGlobalOperator); + const op1 = ` + value = max(x_val, value); + `; + const op2 = ''; + return Object.assign(Object.assign({}, metadata), { outputs: [{ dims: outputShape, dataType: inputs[0].dataType, gpuDataType: types_1.GpuDataType.default }], getShaderSource: shaderHelper => generatePoolingCode(shaderHelper, inputs[0].dims, outputShape, adjustedAttributes, op1, op2, 'f32', '-1e5'), dispatchGroup: () => ({ x: Math.ceil(util_1.ShapeUtil.size(outputShape) / 64 /* workgroup size */) }) }); +}; +const maxPool = (context, attributes) => { + validateInputs(context.inputs); + const metadata = { name: 'MaxPool', inputTypes: [types_1.GpuDataType.default], cacheHint: attributes.cacheKey }; + context.compute(Object.assign(Object.assign({}, metadata), { get: () => createMaxPoolProgramInfo(context.inputs, metadata, false, attributes) })); +}; +exports.maxPool = maxPool; +const parseMaxPoolAttributes = (attributes) => { + const storageOrder = attributes.storage_order; + const dilations = attributes.dilations; + const attr = parsePoolCommonAttributes(attributes); + // 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 (attr.ceilMode !== 0) { + throw new Error('using ceil() in shape computation is not yet supported for MaxPool'); + } + return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)(Object.assign({ storageOrder, dilations }, attr)); +}; +exports.parseMaxPoolAttributes = parseMaxPoolAttributes; +const parseGlobalMaxPoolAttributes = (attributes) => { + const format = attributes.format; + return Object.assign(Object.assign({ format }, globalPoolAttributes), { cacheKey: format }); +}; +exports.parseGlobalMaxPoolAttributes = parseGlobalMaxPoolAttributes; +const globalMaxPool = (context, attributes) => { + validateInputs(context.inputs); + const metadata = { name: 'GlobalMaxPool', inputTypes: [types_1.GpuDataType.default], cacheHint: attributes.cacheKey }; + context.compute(Object.assign(Object.assign({}, metadata), { get: () => createMaxPoolProgramInfo(context.inputs, metadata, true, attributes) })); +}; +exports.globalMaxPool = globalMaxPool; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/ops/transpose.ts": +/*!***********************************************!*\ + !*** ./lib/wasm/jsep/webgpu/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 = exports.createTransposeProgramInfo = exports.transposeProgramMetadata = void 0; +const util_1 = __webpack_require__(/*! ../../util */ "./lib/wasm/jsep/util.ts"); +const attribute_with_cache_key_1 = __webpack_require__(/*! ../attribute-with-cache-key */ "./lib/wasm/jsep/webgpu/attribute-with-cache-key.ts"); +const types_1 = __webpack_require__(/*! ../types */ "./lib/wasm/jsep/webgpu/types.ts"); +const common_1 = __webpack_require__(/*! ./common */ "./lib/wasm/jsep/webgpu/ops/common.ts"); +exports.transposeProgramMetadata = { + name: 'Transpose', + inputTypes: [types_1.GpuDataType.default] +}; +const validateInputs = (inputs) => { + if (!inputs || inputs.length !== 1) { + throw new Error('Transpose requires 1 input.'); + } + if (inputs[0].dataType !== 1 /* DataType.float */) { + throw new Error('input should be float tensor'); + } +}; +const getAdjustedPerm = (inputShape, perm) => (perm && perm.length !== inputShape.length) ? [...(inputShape.keys())].reverse() : perm; +const getOutputShape = (inputShape, perm) => util_1.ShapeUtil.sortBasedOnPerm(inputShape, getAdjustedPerm(inputShape, perm)); +const permFunctionBody = (perm, rank) => { + const reverseFunc = []; + reverseFunc.push(`fn perm(a: ptr>, i: ptr>) {`); + for (let i = 0; i < rank; ++i) { + reverseFunc.push(`\t(*a)[${perm[i]}]=(*i)[${i}];`); + } + reverseFunc.push('\t}'); + return reverseFunc.join('\n'); +}; +const createTransposeProgramInfo = (input, permAttr) => { + const dataType = 'f32'; // TODO: support other data type + const inputShape = input.dims; + const perm = getAdjustedPerm(inputShape, permAttr); + const outputShape = getOutputShape(inputShape, perm); + const rank = inputShape.length; + const outputSize = util_1.ShapeUtil.size(outputShape); + // A dims=[${inputs[0].dims.toString()}] + // out Dims=[${unpackedOutputShape.toString()}] + // based on perm=[${perm.toString()}] + const outputIndicesHelper = (0, common_1.createIndicesHelper)('output', outputShape); + const inputIndicesHelper = (0, common_1.createIndicesHelper)('a', inputShape); + const getShaderSource = (shaderHelper) => ` + @group(0) @binding(0) var a : array<${dataType}>; + @group(0) @binding(1) var output : array<${dataType}>; + + ${permFunctionBody(perm, rank)} + ${outputIndicesHelper.o2iImpl} + ${inputIndicesHelper.i2oImpl} + + ${shaderHelper.mainStart()} + ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes(outputSize)} + + ${outputIndicesHelper.indicesVariableDeclaration('indices')} + ${outputIndicesHelper.o2iCall('global_idx', 'indices')} + ${inputIndicesHelper.indicesVariableDeclaration('aIndices')} + perm(&aIndices, &indices); + + output[global_idx] = a[${inputIndicesHelper.i2oExpression('aIndices')}]; + }`; + return Object.assign(Object.assign({}, exports.transposeProgramMetadata), { outputs: [{ dims: outputShape, dataType: input.dataType, gpuDataType: types_1.GpuDataType.default }], getShaderSource, dispatchGroup: () => ({ x: Math.ceil(outputSize / 64 /* workgroup size */) }) }); +}; +exports.createTransposeProgramInfo = createTransposeProgramInfo; +const transpose = (context, attributes) => { + validateInputs(context.inputs); + context.compute(Object.assign(Object.assign({}, exports.transposeProgramMetadata), { cacheHint: attributes.cacheKey, get: () => (0, exports.createTransposeProgramInfo)(context.inputs[0], attributes.perm) })); +}; +exports.transpose = transpose; +const parseTransposeAttributes = (attributes) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ perm: attributes.perm }); +exports.parseTransposeAttributes = parseTransposeAttributes; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/ops/unary-op.ts": +/*!**********************************************!*\ + !*** ./lib/wasm/jsep/webgpu/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.thresholdedRelu = exports.tanh = exports.tan = exports.sqrt = exports.sinh = exports.sin = exports.sigmoid = exports.relu = exports.reciprocal = exports.neg = exports.leakyRelu = exports.floor = exports.exp = exports.erf = exports.elu = exports.parseAlphaAttributes = exports.cosh = exports.cos = exports.ceil = exports.clip = exports.clipV10 = exports.atanh = exports.atan = exports.asinh = exports.asin = exports.acosh = exports.acos = exports.abs = void 0; +const util_1 = __webpack_require__(/*! ../../util */ "./lib/wasm/jsep/util.ts"); +const attribute_with_cache_key_1 = __webpack_require__(/*! ../attribute-with-cache-key */ "./lib/wasm/jsep/webgpu/attribute-with-cache-key.ts"); +const types_1 = __webpack_require__(/*! ../types */ "./lib/wasm/jsep/webgpu/types.ts"); +const createElementwiseProgramShader = (shaderHelper, datasize, funcCall, additionalImplementation) => { + const vecSize = Math.ceil(datasize / 4); + let expression = ''; + if (typeof funcCall === 'string') { + expression = `${funcCall}(a)`; + } + else { + expression = funcCall('a'); + } + return ` + @group(0) @binding(0) var inputData : array>; + @group(0) @binding(1) var outputData : array>; + + ${additionalImplementation !== null && additionalImplementation !== void 0 ? additionalImplementation : ''} + + ${shaderHelper.mainStart()} + ${shaderHelper.guardAgainstOutOfBoundsWorkgroupSizes(vecSize)} + + let a = inputData[global_idx]; + outputData[global_idx] = ${expression}; + }`; +}; +const createElementwiseProgramInfo = (metadata, input, funcCall, additionalImplementation) => (Object.assign(Object.assign({}, metadata), { getShaderSource: shaderHelper => createElementwiseProgramShader(shaderHelper, util_1.ShapeUtil.size(input.dims), funcCall, additionalImplementation), outputs: [{ dims: input.dims, dataType: input.dataType, gpuDataType: types_1.GpuDataType.default }], dispatchGroup: (inputTensors) => ({ x: Math.ceil(util_1.ShapeUtil.size(inputTensors[0].dims) / 64 /* workgroup size */ / 4 /* vec size */) }) })); +const createElementwiseProgramInfoLoader = (input, name, funcCall, additionalImplementation, cacheKey) => { + const metadata = { name, inputTypes: [types_1.GpuDataType.default], cacheHint: cacheKey }; + return Object.assign(Object.assign({}, metadata), { get: () => createElementwiseProgramInfo(metadata, input, funcCall, additionalImplementation) }); +}; +const abs = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Abs', 'abs')); +}; +exports.abs = abs; +const acos = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Acos', 'acos')); +}; +exports.acos = acos; +const acosh = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Acosh', 'acosh')); +}; +exports.acosh = acosh; +const asin = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Asin', 'asin')); +}; +exports.asin = asin; +const asinh = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Asinh', 'asinh')); +}; +exports.asinh = asinh; +const atan = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Atan', 'atan')); +}; +exports.atan = atan; +const atanh = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Atanh', 'atanh')); +}; +exports.atanh = atanh; +const clipV10 = (context, attributes) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Clip', a => `clamp(${a}, clip_min_, clip_max_)`, ` + const clip_min_: vec4 = vec4(f32(${attributes.min})); + const clip_max_: vec4 = vec4(f32(${attributes.max})); +`, attributes.cacheKey), { inputs: [0] }); +}; +exports.clipV10 = clipV10; +const generateClipAttributesFromInputs = (inputs) => { + const min = (inputs.length >= 2) ? inputs[1].getFloat32Array()[0] : util_1.MIN_CLIP; + const max = (inputs.length >= 3) ? inputs[2].getFloat32Array()[0] : util_1.MAX_CLIP; + return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ min, max }); +}; +const clip = (context) => { + const attributes = generateClipAttributesFromInputs(context.inputs); + (0, exports.clipV10)(context, attributes); +}; +exports.clip = clip; +const ceil = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Ceil', 'ceil')); +}; +exports.ceil = ceil; +const cos = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Cos', 'cos')); +}; +exports.cos = cos; +const cosh = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Cosh', 'cosh')); +}; +exports.cosh = cosh; +const parseAlphaAttributes = (attributes) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)(attributes); +exports.parseAlphaAttributes = parseAlphaAttributes; +const elu = (context, attributes) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Elu', a => `elu_vf32(${a})`, ` + const elu_alpha_: f32 = f32(${attributes.alpha}); + + fn elu_f32(a: f32) -> f32 { + return select((exp(a) - 1.0) * elu_alpha_, a, a >= 0.0); + } + + fn elu_vf32(v: vec4) -> vec4 { + return vec4(elu_f32(v.x), elu_f32(v.y), elu_f32(v.z), elu_f32(v.w)); + }`, attributes.cacheKey)); +}; +exports.elu = elu; +const erf = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Erf', a => `erf_vf32(${a})`, ` + const r0: f32 = 0.3275911; + const r1: f32 = 0.254829592; + const r2: f32 = -0.284496736; + const r3: f32 = 1.421413741; + const r4: f32 = -1.453152027; + const r5: f32 = 1.061405429; + + fn erf_vf32(v: vec4) -> vec4 { + let absv = abs(v); + let x = 1.0 / (1.0 + r0 * absv); + return sign(v) * (1.0 - ((((r5 * x + r4) * x + r3) * x + r2) * x + r1) * x * exp(-absv * absv)); + }`)); +}; +exports.erf = erf; +const exp = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Exp', 'exp')); +}; +exports.exp = exp; +const floor = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Floor', 'floor')); +}; +exports.floor = floor; +const leakyRelu = (context, attributes) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'LeakyRelu', a => `select(leaky_relu_alpha_ * ${a}, ${a}, ${a} >= vec4(0.0))`, `const leaky_relu_alpha_: f32 = f32(${attributes.alpha});`, attributes.cacheKey)); +}; +exports.leakyRelu = leakyRelu; +const neg = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Neg', a => `-${a}`)); +}; +exports.neg = neg; +const reciprocal = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Reciprocal', a => `1.0/${a}`)); +}; +exports.reciprocal = reciprocal; +const relu = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Relu', a => `select(vec4(0.0), ${a}, ${a} > vec4(0.0))`)); +}; +exports.relu = relu; +const sigmoid = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Sigmoid', a => `(1.0 / (1.0 + exp(-${a})))`)); +}; +exports.sigmoid = sigmoid; +const sin = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Sin', 'sin')); +}; +exports.sin = sin; +const sinh = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Sinh', 'sinh')); +}; +exports.sinh = sinh; +const sqrt = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Sqrt', 'sqrt')); +}; +exports.sqrt = sqrt; +const tan = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Tan', 'tan')); +}; +exports.tan = tan; +const tanh = (context) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'Tanh', 'tanh')); +}; +exports.tanh = tanh; +const thresholdedRelu = (context, attributes) => { + context.compute(createElementwiseProgramInfoLoader(context.inputs[0], 'ThresholdedRelu', a => `select(vec4(0.0), ${a}, ${a} > thresholded_relu_alpha_)`, `const thresholded_relu_alpha_: vec4 = vec4(${attributes.alpha});`, attributes.cacheKey)); + return 0; +}; +exports.thresholdedRelu = thresholdedRelu; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/program-manager.ts": +/*!*************************************************!*\ + !*** ./lib/wasm/jsep/webgpu/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 log_1 = __webpack_require__(/*! ../log */ "./lib/wasm/jsep/log.ts"); +const common_1 = __webpack_require__(/*! ./ops/common */ "./lib/wasm/jsep/webgpu/ops/common.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(backend) { + this.backend = backend; + 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, outputs, dispatchGroup) { + const device = this.backend.device; + const computePassEncoder = this.backend.getComputePassEncoder(); + if (this.backend.profilingEnabled) { + // profiling write start timestamp + // eslint-disable-next-line @typescript-eslint/no-explicit-any + computePassEncoder.writeTimestamp(this.backend.profilingQuerySet, 0); + } + computePassEncoder.setPipeline(buildArtifact.computePipeline); + const entries = []; + for (const input of inputs) { + entries.push({ binding: entries.length, resource: { buffer: input.buffer } }); + } + for (const output of outputs) { + entries.push({ binding: entries.length, resource: { buffer: output.buffer } }); + } + const bindGroup = device.createBindGroup({ layout: buildArtifact.computePipeline.getBindGroupLayout(0), entries }); + computePassEncoder.setBindGroup(0, bindGroup); + computePassEncoder.dispatchWorkgroups(...dispatchGroup); + this.backend.pendingDispatchNumber++; + if (this.backend.profilingEnabled) { + // profiling write end timestamp + // eslint-disable-next-line @typescript-eslint/no-explicit-any + computePassEncoder.writeTimestamp(this.backend.profilingQuerySet, 1); + // eslint-disable-next-line no-bitwise + const queryData = this.backend.gpuDataManager.create(16, GPUBufferUsage.COPY_SRC | GPUBufferUsage.QUERY_RESOLVE); + // eslint-disable-next-line no-bitwise + const syncData = this.backend.gpuDataManager.create(16, GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST); + this.backend.endComputePass(); + this.backend.getCommandEncoder().resolveQuerySet(this.backend.profilingQuerySet, 0, 2, queryData.buffer, 0); + this.backend.getCommandEncoder().copyBufferToBuffer(queryData.buffer, 0, syncData.buffer, 0, 16); + this.backend.flush(); + const kernelId = this.backend.currentKernelId; + const kernelName = this.backend.kernels.get(kernelId)[0]; + syncData.buffer.mapAsync(GPUMapMode.READ).then(() => { + const mappedData = new BigUint64Array(syncData.buffer.getMappedRange()); + const startTimeU64 = mappedData[0]; + const endTimeU64 = mappedData[1]; + syncData.buffer.unmap(); + if (typeof this.backend.profilingTimeBase === 'undefined') { + this.backend.profilingTimeBase = startTimeU64; + } + const startTime = Number(startTimeU64 - this.backend.profilingTimeBase); + const endTime = Number(endTimeU64 - this.backend.profilingTimeBase); + if (!Number.isSafeInteger(startTime) || !Number.isSafeInteger(endTime)) { + throw new RangeError('incorrect timestamp range'); + } + this.backend.gpuDataManager.release(queryData.id); + this.backend.gpuDataManager.release(syncData.id); + // eslint-disable-next-line no-console + console.log(`[profiling] kernel "${kernelId}|${kernelName}" execution time: ${endTime - startTime} ns`); + }); + } + if (this.backend.pendingDispatchNumber >= 16) { + this.backend.flush(); + } + } + dispose() { + // this.repo.forEach(a => this.glContext.deleteProgram(a.program)); + } + build(programInfo, normalizedDispatchGroupSize) { + const device = this.backend.device; + const code = programInfo.getShaderSource((0, common_1.createShaderHelper)(normalizedDispatchGroupSize)); + const shaderModule = device.createShaderModule({ code }); + (0, log_1.LOG_DEBUG)('verbose', () => `[WebGPU] shader code: ${code}`); + const computePipeline = device.createComputePipeline({ compute: { module: shaderModule, entryPoint: 'main' }, layout: 'auto' }); + return { programInfo, computePipeline }; + } + normalizeDispatchGroupSize(dispatchGroup) { + const x = typeof dispatchGroup === 'number' ? dispatchGroup : dispatchGroup.x; + const y = typeof dispatchGroup === 'number' ? 1 : (dispatchGroup.y || 1); + const z = typeof dispatchGroup === 'number' ? 1 : (dispatchGroup.z || 1); + const limitPerDimension = this.backend.device.limits.maxComputeWorkgroupsPerDimension; + if (x <= limitPerDimension && y <= limitPerDimension && z <= limitPerDimension) { + return [x, y, z]; + } + const size = x * y * z; + let dispatchAverage = Math.ceil(Math.sqrt(size)); + if (dispatchAverage > limitPerDimension) { + dispatchAverage = Math.ceil(Math.cbrt(size)); + if (dispatchAverage > limitPerDimension) { + throw new Error('Total dispatch size exceeds WebGPU maximum.'); + } + return [dispatchAverage, dispatchAverage, dispatchAverage]; + } + else { + return [dispatchAverage, dispatchAverage, 1]; + } + } +} +exports.ProgramManager = ProgramManager; + + +/***/ }), + +/***/ "./lib/wasm/jsep/webgpu/types.ts": +/*!***************************************!*\ + !*** ./lib/wasm/jsep/webgpu/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.GpuDataType = void 0; +var GpuDataType; +(function (GpuDataType) { + GpuDataType[GpuDataType["default"] = 0] = "default"; + GpuDataType[GpuDataType["upload"] = 1] = "upload"; + GpuDataType[GpuDataType["profile"] = 2] = "profile"; +})(GpuDataType = exports.GpuDataType || (exports.GpuDataType = {})); + + +/***/ }), + +/***/ "./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 init_1 = __webpack_require__(/*! ./jsep/init */ "./lib/wasm/jsep/init.ts"); +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); + // TODO: support JSEP in worker + }); + } + else { + core.initOrt(numThreads, loggingLevel); + // init JSEP if available + await (0, init_1.init)((0, wasm_factory_1.getInstance)()); + } +}; +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"); +const wasm_common_1 = __webpack_require__(/*! ./wasm-common */ "./lib/wasm/wasm-common.ts"); +let ortInit; +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, (0, wasm_common_1.logLevelStringToEnum)(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'; + } + // if using JSEP with WebGPU, always disable memory pattern + if (options.executionProviders && + options.executionProviders.some(ep => (typeof ep === 'string' ? ep : ep.name) === 'webgpu')) { + options.enableMemPattern = false; + } +}; +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 'webgpu': + epName = 'JS'; + 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) => { + var _a, _b, _c, _d; + const wasm = (0, wasm_factory_1.getInstance)(); + let sessionOptionsHandle = 0; + const allocs = []; + const sessionOptions = options || {}; + appendDefaultOptions(sessionOptions); + try { + const graphOptimizationLevel = getGraphOptimzationLevel((_a = sessionOptions.graphOptimizationLevel) !== null && _a !== void 0 ? _a : 'all'); + const executionMode = getExecutionMode((_b = sessionOptions.executionMode) !== null && _b !== void 0 ? _b : 'sequential'); + const logIdDataOffset = typeof sessionOptions.logId === 'string' ? (0, string_utils_1.allocWasmString)(sessionOptions.logId, allocs) : 0; + const logSeverityLevel = (_c = sessionOptions.logSeverityLevel) !== null && _c !== void 0 ? _c : 2; // Default to 2 - warning + if (!Number.isInteger(logSeverityLevel) || logSeverityLevel < 0 || logSeverityLevel > 4) { + throw new Error(`log serverity level is not valid: ${logSeverityLevel}`); + } + const logVerbosityLevel = (_d = sessionOptions.logVerbosityLevel) !== null && _d !== void 0 ? _d : 0; // Default to 0 - verbose + if (!Number.isInteger(logVerbosityLevel) || logVerbosityLevel < 0 || logVerbosityLevel > 4) { + throw new Error(`log verbosity level is not valid: ${logVerbosityLevel}`); + } + const optimizedModelFilePathOffset = typeof sessionOptions.optimizedModelFilePath === 'string' ? + (0, string_utils_1.allocWasmString)(sessionOptions.optimizedModelFilePath, allocs) : + 0; + sessionOptionsHandle = wasm._OrtCreateSessionOptions(graphOptimizationLevel, !!sessionOptions.enableCpuMemArena, !!sessionOptions.enableMemPattern, executionMode, !!sessionOptions.enableProfiling, 0, logIdDataOffset, logSeverityLevel, logVerbosityLevel, optimizedModelFilePathOffset); + if (sessionOptionsHandle === 0) { + throw new Error('Can\'t create session options'); + } + if (sessionOptions.executionProviders) { + setExecutionProviders(sessionOptionsHandle, sessionOptions.executionProviders, allocs); + } + if (sessionOptions.extra !== undefined) { + (0, options_utils_1.iterateExtraOptions)(sessionOptions.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-common.ts": +/*!*********************************!*\ + !*** ./lib/wasm/wasm-common.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.logLevelStringToEnum = exports.tensorTypeToTypedArrayConstructor = exports.getTensorElementSize = exports.tensorDataTypeEnumToString = exports.tensorDataTypeStringToEnum = void 0; +/** + * Map string tensor data to enum value + */ +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}`); + } +}; +exports.tensorDataTypeStringToEnum = tensorDataTypeStringToEnum; +/** + * Map enum value to string tensor data + */ +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}`); + } +}; +exports.tensorDataTypeEnumToString = tensorDataTypeEnumToString; +/** + * get tensor element size in bytes by the given data type + * @returns size in integer or undefined if the data type is not supported + */ +const getTensorElementSize = (dateType) => [undefined, 4, 1, 1, 2, 2, 4, 8, undefined, 1, 2, 8, 4, 8, undefined, undefined, undefined][dateType]; +exports.getTensorElementSize = getTensorElementSize; +/** + * get typed array constructor by the given tensor type + */ +const tensorTypeToTypedArrayConstructor = (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}`); + } +}; +exports.tensorTypeToTypedArrayConstructor = tensorTypeToTypedArrayConstructor; +/** + * Map string log level to integer value + */ +const logLevelStringToEnum = (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}`); + } +}; +exports.logLevelStringToEnum = logLevelStringToEnum; + + +/***/ }), + +/***/ "./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_common_1 = __webpack_require__(/*! ./wasm-common */ "./lib/wasm/wasm-common.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(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]); + if (sessionOptionsHandle !== 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; +/** + * perform inference run + */ +const run = async (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((0, wasm_common_1.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); + // eslint-disable-next-line @typescript-eslint/naming-convention + const runPromise = wasm.jsepRunPromise; + if (runPromise && typeof runPromise.then !== 'undefined') { + errorCode = await runPromise; + } + 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 = (0, wasm_common_1.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 = (0, wasm_common_1.tensorTypeToTypedArrayConstructor)(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; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +exports.dispose = exports.getInstance = exports.initializeWebAssembly = void 0; +const path = __importStar(__webpack_require__(/*! path */ "?7aa5")); +/* eslint-disable @typescript-eslint/no-require-imports */ +const ortWasmFactory = true ? __webpack_require__(/*! ./binding/ort-wasm.js */ "./lib/wasm/binding/ort-wasm.js") : 0; +const ortWasmFactoryThreaded = true ? + ( true ? __webpack_require__(/*! ./binding/ort-wasm-threaded.js */ "./lib/wasm/binding/ort-wasm-threaded.js") : + 0) : + 0; +/* eslint-enable @typescript-eslint/no-require-imports */ +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 wasmPaths = flags.wasmPaths; + const wasmPrefixOverride = typeof wasmPaths === 'string' ? wasmPaths : undefined; + const wasmFileName = getWasmFileName(useSimd, useThreads); + const wasmPathOverride = typeof wasmPaths === 'object' ? wasmPaths[wasmFileName] : 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 : ortWasmFactory; +const config = { + locateFile: (fileName, scriptDirectory) => { + if (fileName.endsWith('.wasm') && typeof modelWasmBuffer !== 'undefined') { + // Return empty string to stop Emscripten from trying to fetch + return ''; + } + + // fallback + if (fileName.endsWith('.wasm')) { + if (wasmPathOverride) { + return wasmPathOverride; + } + const prefix = wasmPrefixOverride ?? scriptDirectory; + return prefix + wasmFileName; + } + return scriptDirectory + fileName; + }, + + // 👇 Inject custom instantiateWasm function + instantiateWasm: (info, receiveInstance) => { + if (typeof modelWasmBuffer === 'undefined') { + throw new Error('modelWasmBuffer not set'); + } + WebAssembly.instantiate(new Uint8Array(modelWasmBuffer), info) + .then(result => receiveInstance(result.instance)) + .catch(err => { + console.error("Failed to instantiate custom WASM:", err); + throw err; + }); + // Required by Emscripten + return {}; + } +}; + + 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.15.1\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/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 // if using JSEP with WebGPU, always disable memory pattern\n if (options.executionProviders &&\n options.executionProviders.some(ep => (typeof ep === 'string' ? ep : ep.name) === 'webgpu')) {\n options.enableMemPattern = false;\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 'webgpu':\n epName = 'JS';\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 var _a, _b, _c, _d;\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 const graphOptimizationLevel = getGraphOptimzationLevel((_a = sessionOptions.graphOptimizationLevel) !== null && _a !== void 0 ? _a : 'all');\n const executionMode = getExecutionMode((_b = sessionOptions.executionMode) !== null && _b !== void 0 ? _b : 'sequential');\n const logIdDataOffset = typeof sessionOptions.logId === 'string' ? (0, string_utils_1.allocWasmString)(sessionOptions.logId, allocs) : 0;\n const logSeverityLevel = (_c = sessionOptions.logSeverityLevel) !== null && _c !== void 0 ? _c : 2; // Default to 2 - warning\n if (!Number.isInteger(logSeverityLevel) || logSeverityLevel < 0 || logSeverityLevel > 4) {\n throw new Error(`log serverity level is not valid: ${logSeverityLevel}`);\n }\n const logVerbosityLevel = (_d = sessionOptions.logVerbosityLevel) !== null && _d !== void 0 ? _d : 0; // Default to 0 - verbose\n if (!Number.isInteger(logVerbosityLevel) || logVerbosityLevel < 0 || logVerbosityLevel > 4) {\n throw new Error(`log verbosity level is not valid: ${logVerbosityLevel}`);\n }\n const optimizedModelFilePathOffset = typeof sessionOptions.optimizedModelFilePath === 'string' ?\n (0, string_utils_1.allocWasmString)(sessionOptions.optimizedModelFilePath, allocs) :\n 0;\n sessionOptionsHandle = wasm._OrtCreateSessionOptions(graphOptimizationLevel, !!sessionOptions.enableCpuMemArena, !!sessionOptions.enableMemPattern, executionMode, !!sessionOptions.enableProfiling, 0, logIdDataOffset, logSeverityLevel, logVerbosityLevel, optimizedModelFilePathOffset);\n if (sessionOptionsHandle === 0) {\n throw new Error('Can\\'t create session options');\n }\n if (sessionOptions.executionProviders) {\n setExecutionProviders(sessionOptionsHandle, sessionOptions.executionProviders, allocs);\n }\n if (sessionOptions.extra !== undefined) {\n (0, options_utils_1.iterateExtraOptions)(sessionOptions.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-common.ts\":\n/*!*********************************!*\\\n !*** ./lib/wasm/wasm-common.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.logLevelStringToEnum = exports.tensorTypeToTypedArrayConstructor = exports.getTensorElementSize = exports.tensorDataTypeEnumToString = exports.tensorDataTypeStringToEnum = void 0;\n/**\n * Map string tensor data to enum value\n */\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};\nexports.tensorDataTypeStringToEnum = tensorDataTypeStringToEnum;\n/**\n * Map enum value to string tensor data\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};\nexports.tensorDataTypeEnumToString = tensorDataTypeEnumToString;\n/**\n * get tensor element size in bytes by the given data type\n * @returns size in integer or undefined if the data type is not supported\n */\nconst getTensorElementSize = (dateType) => [undefined, 4, 1, 1, 2, 2, 4, 8, undefined, 1, 2, 8, 4, 8, undefined, undefined, undefined][dateType];\nexports.getTensorElementSize = getTensorElementSize;\n/**\n * get typed array constructor by the given tensor type\n */\nconst tensorTypeToTypedArrayConstructor = (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};\nexports.tensorTypeToTypedArrayConstructor = tensorTypeToTypedArrayConstructor;\n/**\n * Map string log level to integer value\n */\nconst logLevelStringToEnum = (logLevel) => {\n switch (logLevel) {\n case 'verbose':\n return 0;\n case 'info':\n return 1;\n case 'warning':\n return 2;\n case 'error':\n return 3;\n case 'fatal':\n return 4;\n default:\n throw new Error(`unsupported logging level: ${logLevel}`);\n }\n};\nexports.logLevelStringToEnum = logLevelStringToEnum;\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_common_1 = __webpack_require__(/*! ./wasm-common */ \"./lib/wasm/wasm-common.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(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 if (sessionOptionsHandle !== 0) {\n wasm._OrtReleaseSessionOptions(sessionOptionsHandle);\n }\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;\n/**\n * perform inference run\n */\nconst run = async (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((0, wasm_common_1.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 // eslint-disable-next-line @typescript-eslint/naming-convention\n const runPromise = wasm.jsepRunPromise;\n if (runPromise && typeof runPromise.then !== 'undefined') {\n errorCode = await runPromise;\n }\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 = (0, wasm_common_1.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 = (0, wasm_common_1.tensorTypeToTypedArrayConstructor)(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};\nObject.defineProperty(exports, \"__esModule\", ({ value: true }));\nexports.dispose = exports.getInstance = exports.initializeWebAssembly = void 0;\nconst path = __importStar(__webpack_require__(/*! path */ \"?7aa5\"));\n/* eslint-disable @typescript-eslint/no-require-imports */\nconst ortWasmFactory = true ? __webpack_require__(/*! ./binding/ort-wasm.js */ \"./lib/wasm/binding/ort-wasm.js\") : 0;\nconst ortWasmFactoryThreaded = true ?\n ( true ? __webpack_require__(/*! ./binding/ort-wasm-threaded.js */ \"./lib/wasm/binding/ort-wasm-threaded.js\") :\n 0) :\n 0;\n/* eslint-enable @typescript-eslint/no-require-imports */\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 wasmPaths = flags.wasmPaths;\n const wasmPrefixOverride = typeof wasmPaths === 'string' ? wasmPaths : undefined;\n const wasmFileName = getWasmFileName(useSimd, useThreads);\n const wasmPathOverride = typeof wasmPaths === 'object' ? wasmPaths[wasmFileName] : 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 : ortWasmFactory;\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.endsWith('.wasm')) {\n if (wasmPathOverride) {\n return wasmPathOverride;\n }\n const prefix = wasmPrefixOverride !== null && wasmPrefixOverride !== void 0 ? wasmPrefixOverride : scriptDirectory;\n if (false) {}\n return prefix + wasmFileName;\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.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 c(){k.buffer!=l&&m(k.buffer);return aa}function q(){k.buffer!=l&&m(k.buffer);return ba}function t(){k.buffer!=l&&m(k.buffer);return ca}function w(){k.buffer!=l&&m(k.buffer);return da}function ea(){k.buffer!=l&&m(k.buffer);return fa}null;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\",z=(a,b)=>{throw b;},la=\"object\"==typeof window,A=\"function\"==typeof importScripts,B=\"object\"==typeof process&&\"object\"==typeof process.versions&&\"string\"==typeof process.versions.node,C=x.ENVIRONMENT_IS_PTHREAD||!1,D=\"\";function ma(a){return x.locateFile?x.locateFile(a,D):D+a}var na,F,G,fs,H,I;\r\nif(B){D=A?(__webpack_require__(/*! path */ \"?75c6\").dirname)(D)+\"/\":__dirname+\"/\";I=()=>{H||(fs=__webpack_require__(/*! fs */ \"?63c8\"),H=__webpack_require__(/*! path */ \"?75c6\"))};na=function(b,d){I();b=H.normalize(b);return fs.readFileSync(b,d?void 0:\"utf8\")};G=b=>{b=na(b,!0);b.buffer||(b=new Uint8Array(b));return b};F=(b,d,e)=>{I();b=H.normalize(b);fs.readFile(b,function(g,h){g?e(g):d(h.buffer)})};1{if(noExitRuntime)throw process.exitCode=b,d;d instanceof K||L(\"exiting due to exception: \"+d);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(la||A)A?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||(na=a=>{var b=new XMLHttpRequest;b.open(\"GET\",a,!1);b.send(null);return b.responseText},A&&(G=a=>{var b=new XMLHttpRequest;b.open(\"GET\",a,!1);b.responseType=\"arraybuffer\";b.send(null);return new Uint8Array(b.response)}),F=(a,b,d)=>{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):d()};e.onerror=\r\nd;e.send(null)});B&&\"undefined\"==typeof performance&&(__webpack_require__.g.performance=(__webpack_require__(/*! perf_hooks */ \"?674f\").performance));var oa=console.log.bind(console),pa=console.warn.bind(console);B&&(I(),oa=a=>fs.writeSync(1,a+\"\\n\"),pa=a=>fs.writeSync(2,a+\"\\n\"));var qa=x.print||oa,L=x.printErr||pa;Object.assign(x,ja);ja=null;x.thisProgram&&(ka=x.thisProgram);x.quit&&(z=x.quit);var M;x.wasmBinary&&(M=x.wasmBinary);var noExitRuntime=x.noExitRuntime||!0;\"object\"!=typeof WebAssembly&&N(\"no native wasm support detected\");\r\nvar k,ra,sa=!1,ta=\"undefined\"!=typeof TextDecoder?new TextDecoder(\"utf8\"):void 0;\r\nfunction ua(a,b,d){b>>>=0;var e=b+d;for(d=b;a[d]&&!(d>=e);)++d;if(16g?e+=String.fromCharCode(g):(g-=65536,e+=String.fromCharCode(55296|g>>10,56320|g&1023))}}else e+=String.fromCharCode(g)}return e}\r\nfunction va(a,b){return(a>>>=0)?ua(q(),a,b):\"\"}\r\nfunction wa(a,b,d,e){d>>>=0;if(!(0=n){var u=a.charCodeAt(++h);n=65536+((n&1023)<<10)|u&1023}if(127>=n){if(d>=e)break;b[d++>>>0]=n}else{if(2047>=n){if(d+1>=e)break;b[d++>>>0]=192|n>>6}else{if(65535>=n){if(d+2>=e)break;b[d++>>>0]=224|n>>12}else{if(d+3>=e)break;b[d++>>>0]=240|n>>18;b[d++>>>0]=128|n>>12&63}b[d++>>>0]=128|n>>6&63}b[d++>>>0]=128|n&63}}b[d>>>0]=0;return d-g}\r\nfunction xa(a){for(var b=0,d=0;d=e?b++:2047>=e?b+=2:55296<=e&&57343>=e?(b+=4,++d):b+=3}return b}var l,aa,ba,ca,da,fa;C&&(l=x.buffer);function m(a){l=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 ya=x.INITIAL_MEMORY||16777216;\r\nif(C)k=x.wasmMemory,l=x.buffer;else if(x.wasmMemory)k=x.wasmMemory;else if(k=new WebAssembly.Memory({initial:ya/65536,maximum:65536,shared:!0}),!(k.buffer instanceof SharedArrayBuffer))throw L(\"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\");k&&(l=k.buffer);ya=l.byteLength;m(l);var za,Aa=[],Ba=[],Ca=[];function Da(){var a=x.preRun.shift();Aa.unshift(a)}var O=0,Ea=null,P=null;function N(a){if(C)postMessage({cmd:\"onAbort\",arg:a});else if(x.onAbort)x.onAbort(a);a=\"Aborted(\"+a+\")\";L(a);sa=!0;a=new WebAssembly.RuntimeError(a+\". Build with -sASSERTIONS for more info.\");ia(a);throw a;}function Fa(){return Q.startsWith(\"data:application/octet-stream;base64,\")}var Q;Q=\"ort-wasm-threaded.wasm\";Fa()||(Q=ma(Q));\r\nfunction Ga(){var a=Q;try{if(a==Q&&M)return new Uint8Array(M);if(G)return G(a);throw\"both async and sync fetching of the wasm failed\";}catch(b){N(b)}}\r\nfunction Ha(){if(!M&&(la||A)){if(\"function\"==typeof fetch&&!Q.startsWith(\"file://\"))return fetch(Q,{credentials:\"same-origin\"}).then(function(a){if(!a.ok)throw\"failed to load wasm binary file at '\"+Q+\"'\";return a.arrayBuffer()}).catch(function(){return Ga()});if(F)return new Promise(function(a,b){F(Q,function(d){a(new Uint8Array(d))},b)})}return Promise.resolve().then(function(){return Ga()})}var Ia={};\r\nfunction K(a){this.name=\"ExitStatus\";this.message=\"Program terminated with exit(\"+a+\")\";this.status=a}function Ja(a){(a=R.La[a])||N();R.Xa(a)}function Ka(a){var b=R.lb();if(!b)return 6;R.Ra.push(b);R.La[a.Ka]=b;b.Ka=a.Ka;var d={cmd:\"run\",start_routine:a.pb,arg:a.ib,pthread_ptr:a.Ka};b.Qa=()=>{d.time=performance.now();b.postMessage(d,a.vb)};b.loaded&&(b.Qa(),delete b.Qa);return 0}function La(a){if(C)return S(1,1,a);if(!noExitRuntime){R.qb();if(x.onExit)x.onExit(a);sa=!0}z(a,new K(a))}\r\nfunction Ma(a,b){if(!b&&C)throw Na(a),\"unwind\";La(a)}\r\nvar R={Oa:[],Ra:[],$a:[],La:{},Ua:function(){C&&R.mb()},xb:function(){},mb:function(){R.receiveObjectTransfer=R.ob;R.threadInitTLS=R.Za;R.setExitStatus=R.Ya;noExitRuntime=!1},Ya:function(){},qb:function(){for(var a of Object.values(R.La))R.Xa(a);for(a of R.Oa)a.terminate();R.Oa=[]},Xa:function(a){var b=a.Ka;delete R.La[b];R.Oa.push(a);R.Ra.splice(R.Ra.indexOf(a),1);a.Ka=0;Oa(b)},ob:function(){},Za:function(){R.$a.forEach(a=>a())},nb:function(a,b){a.onmessage=d=>{d=d.data;var e=d.cmd;a.Ka&&(R.kb=a.Ka);\r\nif(d.targetThread&&d.targetThread!=T()){var g=R.La[d.yb];g?g.postMessage(d,d.transferList):L('Internal error! Worker sent a message \"'+e+'\" to target pthread '+d.targetThread+\", but that thread no longer exists!\")}else if(\"processProxyingQueue\"===e)Pa(d.queue);else if(\"spawnThread\"===e)Ka(d);else if(\"cleanupThread\"===e)Ja(d.thread);else if(\"killThread\"===e)d=d.thread,e=R.La[d],delete R.La[d],e.terminate(),Oa(d),R.Ra.splice(R.Ra.indexOf(e),1),e.Ka=0;else if(\"cancelThread\"===e)R.La[d.thread].postMessage({cmd:\"cancel\"});\r\nelse if(\"loaded\"===e)a.loaded=!0,b&&b(a),a.Qa&&(a.Qa(),delete a.Qa);else if(\"print\"===e)qa(\"Thread \"+d.threadId+\": \"+d.text);else if(\"printErr\"===e)L(\"Thread \"+d.threadId+\": \"+d.text);else if(\"alert\"===e)alert(\"Thread \"+d.threadId+\": \"+d.text);else if(\"setimmediate\"===d.target)a.postMessage(d);else if(\"onAbort\"===e){if(x.onAbort)x.onAbort(d.arg)}else e&&L(\"worker sent an unknown command \"+e);R.kb=void 0};a.onerror=d=>{L(\"worker sent an error! \"+d.filename+\":\"+d.lineno+\": \"+d.message);throw d;};B&&\r\n(a.on(\"message\",function(d){a.onmessage({data:d})}),a.on(\"error\",function(d){a.onerror(d)}),a.on(\"detachedExit\",function(){}));a.postMessage({cmd:\"load\",urlOrBlob:x.mainScriptUrlOrBlob||_scriptDir,wasmMemory:k,wasmModule:ra})},hb:function(){var a=ma(\"ort-wasm-threaded.worker.js\");R.Oa.push(new Worker(a))},lb:function(){0==R.Oa.length&&(R.hb(),R.nb(R.Oa[0]));return R.Oa.pop()}};x.PThread=R;function U(a){for(;0>2>>>0];a=t()[a+48>>2>>>0];Sa(b,b-a);V(b)};function Na(a){if(C)return S(2,0,a);try{Ma(a)}catch(b){b instanceof K||\"unwind\"==b||z(1,b)}}var W=[];x.invokeEntryPoint=function(a,b){var d=W[a];d||(a>=W.length&&(W.length=a+1),W[a]=d=za.get(a));a=d(b);noExitRuntime?R.Ya(a):Ta(a)};function Ua(a,b){c().set(a,b>>>0)}\r\nfunction Va(a){this.Pa=a-24;this.gb=function(b){w()[this.Pa+4>>2>>>0]=b};this.cb=function(b){w()[this.Pa+8>>2>>>0]=b};this.eb=function(){t()[this.Pa>>2>>>0]=0};this.bb=function(){var b=0;c()[this.Pa+12>>0>>>0]=b};this.fb=function(){var b=0;c()[this.Pa+13>>0>>>0]=b};this.Ua=function(b,d){this.ab();this.gb(b);this.cb(d);this.eb();this.bb();this.fb()};this.ab=function(){w()[this.Pa+16>>2>>>0]=0}}var Wa=0;function Xa(a,b,d,e){return C?S(3,1,a,b,d,e):Ya(a,b,d,e)}\r\nfunction Ya(a,b,d,e){if(\"undefined\"==typeof SharedArrayBuffer)return L(\"Current environment does not support SharedArrayBuffer, pthreads are not available!\"),6;var g=[];if(C&&0===g.length)return Xa(a,b,d,e);a={pb:d,Ka:a,ib:e,vb:g};return C?(a.wb=\"spawnThread\",postMessage(a,g),0):Ka(a)}function Za(a,b,d){return C?S(4,1,a,b,d):0}function $a(a,b){if(C)return S(5,1,a,b)}function ab(a,b){if(C)return S(6,1,a,b)}function bb(a,b,d){if(C)return S(7,1,a,b,d)}function cb(a,b,d){return C?S(8,1,a,b,d):0}\r\nfunction db(a,b){if(C)return S(9,1,a,b)}function eb(a,b,d){if(C)return S(10,1,a,b,d)}function fb(a,b,d,e){if(C)return S(11,1,a,b,d,e)}function gb(a,b,d,e){if(C)return S(12,1,a,b,d,e)}function hb(a,b,d,e){if(C)return S(13,1,a,b,d,e)}function ib(a){if(C)return S(14,1,a)}function jb(a,b){if(C)return S(15,1,a,b)}function kb(a,b,d){if(C)return S(16,1,a,b,d)}function Pa(a){Atomics.store(t(),a>>2,1);T()&&lb(a);Atomics.compareExchange(t(),a>>2,1,0)}x.executeNotifiedProxyingQueue=Pa;\r\nfunction mb(a){return w()[a>>>2]+4294967296*t()[a+4>>>2]}function nb(a,b,d,e,g,h){return C?S(17,1,a,b,d,e,g,h):-52}function ob(a,b,d,e,g,h){if(C)return S(18,1,a,b,d,e,g,h)}function pb(a){var b=xa(a)+1,d=qb(b);d&&wa(a,c(),d,b);return d}\r\nfunction rb(a,b,d){function e(v){return(v=v.toTimeString().match(/\\(([A-Za-z ]+)\\)$/))?v[1]:\"GMT\"}if(C)return S(19,1,a,b,d);var g=(new Date).getFullYear(),h=new Date(g,0,1),n=new Date(g,6,1);g=h.getTimezoneOffset();var u=n.getTimezoneOffset(),E=Math.max(g,u);t()[a>>2>>>0]=60*E;t()[b>>2>>>0]=Number(g!=u);a=e(h);b=e(n);a=pb(a);b=pb(b);u>2>>>0]=a,w()[d+4>>2>>>0]=b):(w()[d>>2>>>0]=b,w()[d+4>>2>>>0]=a)}function sb(a,b,d){sb.jb||(sb.jb=!0,rb(a,b,d))}var X,tb;\r\ntb=B?()=>{var a=process.hrtime();return 1E3*a[0]+a[1]/1E6}:C?()=>performance.now()-x.__performance_now_clock_drift:()=>performance.now();function S(a,b){var d=arguments.length-2,e=arguments;return Qa(()=>{for(var g=ub(8*d),h=g>>3,n=0;n>>0]=u}return vb(a,d,g,b)})}var wb=[],xb={};\r\nfunction yb(){if(!zb){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 xb)void 0===xb[b]?delete a[b]:a[b]=xb[b];var d=[];for(b in a)d.push(b+\"=\"+a[b]);zb=d}return zb}var zb;\r\nfunction Ab(a,b){if(C)return S(20,1,a,b);var d=0;yb().forEach(function(e,g){var h=b+d;g=w()[a+4*g>>2>>>0]=h;for(h=0;h>0>>>0]=e.charCodeAt(h);c()[g>>0>>>0]=0;d+=e.length+1});return 0}function Bb(a,b){if(C)return S(21,1,a,b);var d=yb();w()[a>>2>>>0]=d.length;var e=0;d.forEach(function(g){e+=g.length+1});w()[b>>2>>>0]=e;return 0}function Cb(a){return C?S(22,1,a):52}function Gb(a,b,d,e){return C?S(23,1,a,b,d,e):52}function Hb(a,b,d,e,g){return C?S(24,1,a,b,d,e,g):70}\r\nvar Ib=[null,[],[]];function Jb(a,b,d,e){if(C)return S(25,1,a,b,d,e);for(var g=0,h=0;h>2>>>0],u=w()[b+4>>2>>>0];b+=8;for(var E=0;E>>0],y=Ib[a];0===v||10===v?((1===a?qa:L)(ua(y,0)),y.length=0):y.push(v)}g+=u}w()[e>>2>>>0]=g;return 0}\r\nfunction Kb(){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__(/*! crypto */ \"?892d\");return()=>b.randomBytes(1)[0]}catch(d){}return()=>N(\"randomDevice\")}function Y(a,b){Y.Wa||(Y.Wa=Kb());for(var d=0;d>0>>>0]=Y.Wa();return 0}function Z(a){return 0===a%4&&(0!==a%100||0===a%400)}var Lb=[31,29,31,30,31,30,31,31,30,31,30,31],Mb=[31,28,31,30,31,30,31,31,30,31,30,31];\r\nfunction Nb(a){var b=Array(xa(a)+1);wa(a,b,0,b.length);return b}\r\nfunction Ob(a,b,d,e){function g(f,p,r){for(f=\"number\"==typeof f?f.toString():f||\"\";f.lengthDb?-1:0J-f.getDate())p-=J-f.getDate()+1,f.setDate(1),11>r?f.setMonth(r+1):(f.setMonth(0),f.setFullYear(f.getFullYear()+1));else{f.setDate(f.getDate()+p);break}}r=new Date(f.getFullYear()+1,0,4);p=u(new Date(f.getFullYear(),\r\n0,4));r=u(r);return 0>=n(p,f)?0>=n(r,f)?f.getFullYear()+1:f.getFullYear():f.getFullYear()-1}var v=t()[e+40>>2>>>0];e={tb:t()[e>>2>>>0],sb:t()[e+4>>2>>>0],Sa:t()[e+8>>2>>>0],Va:t()[e+12>>2>>>0],Ta:t()[e+16>>2>>>0],Na:t()[e+20>>2>>>0],Ja:t()[e+24>>2>>>0],Ma:t()[e+28>>2>>>0],zb:t()[e+32>>2>>>0],rb:t()[e+36>>2>>>0],ub:v?va(v):\"\"};d=va(d);v={\"%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 y in v)d=d.replace(new RegExp(y,\"g\"),v[y]);var Eb=\"Sunday Monday Tuesday Wednesday Thursday Friday Saturday\".split(\" \"),Fb=\"January February March April May June July August September October November December\".split(\" \");v={\"%a\":function(f){return Eb[f.Ja].substring(0,3)},\"%A\":function(f){return Eb[f.Ja]},\r\n\"%b\":function(f){return Fb[f.Ta].substring(0,3)},\"%B\":function(f){return Fb[f.Ta]},\"%C\":function(f){return h((f.Na+1900)/100|0,2)},\"%d\":function(f){return h(f.Va,2)},\"%e\":function(f){return g(f.Va,2,\" \")},\"%g\":function(f){return E(f).toString().substring(2)},\"%G\":function(f){return E(f)},\"%H\":function(f){return h(f.Sa,2)},\"%I\":function(f){f=f.Sa;0==f?f=12:12f.Sa?\"AM\":\"PM\"},\"%S\":function(f){return h(f.tb,2)},\"%t\":function(){return\"\\t\"},\"%u\":function(f){return f.Ja||7},\"%U\":function(f){return h(Math.floor((f.Ma+7-f.Ja)/7),2)},\"%V\":function(f){var p=Math.floor((f.Ma+7-(f.Ja+6)%7)/7);2>=(f.Ja+371-f.Ma-2)%7&&p++;if(p)53==p&&(r=(f.Ja+371-f.Ma)%7,4==r||3==r&&Z(f.Na)||(p=1));else{p=52;var r=(f.Ja+7-f.Ma-1)%7;(4==r||5==r&&Z(f.Na%400-1))&&p++}return h(p,2)},\r\n\"%w\":function(f){return f.Ja},\"%W\":function(f){return h(Math.floor((f.Ma+7-(f.Ja+6)%7)/7),2)},\"%y\":function(f){return(f.Na+1900).toString().substring(2)},\"%Y\":function(f){return f.Na+1900},\"%z\":function(f){f=f.rb;var p=0<=f;f=Math.abs(f)/60;return(p?\"+\":\"-\")+String(\"0000\"+(f/60*100+f%60)).slice(-4)},\"%Z\":function(f){return f.ub},\"%%\":function(){return\"%\"}};d=d.replace(/%%/g,\"\\x00\\x00\");for(y in v)d.includes(y)&&(d=d.replace(new RegExp(y,\"g\"),v[y](e)));d=d.replace(/\\0\\0/g,\"%\");y=Nb(d);if(y.length>\r\nb)return 0;Ua(y,a);return y.length-1}R.Ua();\r\nvar Pb=[null,La,Na,Xa,Za,$a,ab,bb,cb,db,eb,fb,gb,hb,ib,jb,kb,nb,ob,rb,Ab,Bb,Cb,Gb,Hb,Jb],Rb={b:function(a){return qb(a+24)+24},c:function(a,b,d){(new Va(a)).Ua(b,d);Wa++;throw a;},L:function(a){Qb(a,!A,1,!la);R.Za()},l:function(a){C?postMessage({cmd:\"cleanupThread\",thread:a}):Ja(a)},D:Ya,i:Za,R:$a,z:ab,B:bb,T:cb,P:db,I:eb,O:fb,p:gb,A:hb,x:ib,Q:jb,y:kb,r:function(){},j:function(){N(\"To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking\")},s:function(){N(\"To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking\")},\r\nq:function(){return Date.now()},E:function(){return 2097152},V:function(){return!0},F:function(a,b,d,e){if(a==b)setTimeout(()=>Pa(e));else if(C)postMessage({targetThread:a,cmd:\"processProxyingQueue\",queue:e});else{a=R.La[a];if(!a)return;a.postMessage({cmd:\"processProxyingQueue\",queue:e})}return 1},K:function(){return-1},W:function(a,b){a=new Date(1E3*mb(a));t()[b>>2>>>0]=a.getUTCSeconds();t()[b+4>>2>>>0]=a.getUTCMinutes();t()[b+8>>2>>>0]=a.getUTCHours();t()[b+12>>2>>>0]=a.getUTCDate();t()[b+16>>2>>>\r\n0]=a.getUTCMonth();t()[b+20>>2>>>0]=a.getUTCFullYear()-1900;t()[b+24>>2>>>0]=a.getUTCDay();a=(a.getTime()-Date.UTC(a.getUTCFullYear(),0,1,0,0,0,0))/864E5|0;t()[b+28>>2>>>0]=a},X:function(a,b){a=new Date(1E3*mb(a));t()[b>>2>>>0]=a.getSeconds();t()[b+4>>2>>>0]=a.getMinutes();t()[b+8>>2>>>0]=a.getHours();t()[b+12>>2>>>0]=a.getDate();t()[b+16>>2>>>0]=a.getMonth();t()[b+20>>2>>>0]=a.getFullYear()-1900;t()[b+24>>2>>>0]=a.getDay();var d=new Date(a.getFullYear(),0,1),e=(a.getTime()-d.getTime())/864E5|0;t()[b+\r\n28>>2>>>0]=e;t()[b+36>>2>>>0]=-(60*a.getTimezoneOffset());e=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();d=d.getTimezoneOffset();a=(e!=d&&a.getTimezoneOffset()==Math.min(d,e))|0;t()[b+32>>2>>>0]=a},Y:function(a){var b=new Date(t()[a+20>>2>>>0]+1900,t()[a+16>>2>>>0],t()[a+12>>2>>>0],t()[a+8>>2>>>0],t()[a+4>>2>>>0],t()[a>>2>>>0],0),d=t()[a+32>>2>>>0],e=b.getTimezoneOffset(),g=new Date(b.getFullYear(),0,1),h=(new Date(b.getFullYear(),6,1)).getTimezoneOffset(),n=g.getTimezoneOffset(),u=Math.min(n,\r\nh);0>d?t()[a+32>>2>>>0]=Number(h!=n&&u==e):0>2>>>0]=b.getDay();d=(b.getTime()-g.getTime())/864E5|0;t()[a+28>>2>>>0]=d;t()[a>>2>>>0]=b.getSeconds();t()[a+4>>2>>>0]=b.getMinutes();t()[a+8>>2>>>0]=b.getHours();t()[a+12>>2>>>0]=b.getDate();t()[a+16>>2>>>0]=b.getMonth();return b.getTime()/1E3|0},G:nb,H:ob,Z:sb,d:function(){N(\"\")},m:function(){if(!B&&!A){var a=\"Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread\";\r\nX||(X={});X[a]||(X[a]=1,B&&(a=\"warning: \"+a),L(a))}},w:function(){return 4294901760},f:tb,S:function(a,b,d){q().copyWithin(a>>>0,b>>>0,b+d>>>0)},g:function(){return B?(__webpack_require__(/*! os */ \"?aedb\").cpus)().length:navigator.hardwareConcurrency},J:function(a,b,d){wb.length=b;d>>=3;for(var e=0;e>>0];return(0>a?Ia[-a-1]:Pb[a]).apply(null,wb)},v:function(a){var b=q().length;a>>>=0;if(a<=b||4294901760=d;d*=2){var e=b*(1+.2/d);e=Math.min(e,a+100663296);var g=Math;e=Math.max(a,\r\ne);g=g.min.call(g,4294901760,e+(65536-e%65536)%65536);a:{try{k.grow(g-l.byteLength+65535>>>16);m(k.buffer);var h=1;break a}catch(n){}h=void 0}if(h)return!0}return!1},U:function(){throw\"unwind\";},M:Ab,N:Bb,k:Ma,h:Cb,o:Gb,t:Hb,n:Jb,u:Y,a:k||x.wasmMemory,C:Ob,e:function(a,b,d,e){return Ob(a,b,d,e)}};\r\n(function(){function a(g,h){x.asm=g.exports;R.$a.push(x.asm.wa);za=x.asm.za;Ba.unshift(x.asm._);ra=h;C||(O--,x.monitorRunDependencies&&x.monitorRunDependencies(O),0==O&&(null!==Ea&&(clearInterval(Ea),Ea=null),P&&(g=P,P=null,g())))}function b(g){a(g.instance,g.module)}function d(g){return Ha().then(function(h){return WebAssembly.instantiate(h,e)}).then(function(h){return h}).then(g,function(h){L(\"failed to asynchronously prepare wasm: \"+h);N(h)})}var e={a:Rb};C||(O++,x.monitorRunDependencies&&x.monitorRunDependencies(O));\r\nif(x.instantiateWasm)try{return x.instantiateWasm(e,a)}catch(g){return L(\"Module.instantiateWasm callback failed with error: \"+g),!1}(function(){return M||\"function\"!=typeof WebAssembly.instantiateStreaming||Fa()||Q.startsWith(\"file://\")||B||\"function\"!=typeof fetch?d(b):fetch(Q,{credentials:\"same-origin\"}).then(function(g){return WebAssembly.instantiateStreaming(g,e).then(b,function(h){L(\"wasm streaming compile failed: \"+h);L(\"falling back to ArrayBuffer instantiation\");return d(b)})})})().catch(ia);\r\nreturn{}})();x.___wasm_call_ctors=function(){return(x.___wasm_call_ctors=x.asm._).apply(null,arguments)};x._OrtInit=function(){return(x._OrtInit=x.asm.$).apply(null,arguments)};x._OrtCreateSessionOptions=function(){return(x._OrtCreateSessionOptions=x.asm.aa).apply(null,arguments)};x._OrtAppendExecutionProvider=function(){return(x._OrtAppendExecutionProvider=x.asm.ba).apply(null,arguments)};x._OrtAddSessionConfigEntry=function(){return(x._OrtAddSessionConfigEntry=x.asm.ca).apply(null,arguments)};\r\nx._OrtReleaseSessionOptions=function(){return(x._OrtReleaseSessionOptions=x.asm.da).apply(null,arguments)};x._OrtCreateSession=function(){return(x._OrtCreateSession=x.asm.ea).apply(null,arguments)};x._OrtReleaseSession=function(){return(x._OrtReleaseSession=x.asm.fa).apply(null,arguments)};x._OrtGetInputCount=function(){return(x._OrtGetInputCount=x.asm.ga).apply(null,arguments)};x._OrtGetOutputCount=function(){return(x._OrtGetOutputCount=x.asm.ha).apply(null,arguments)};\r\nx._OrtGetInputName=function(){return(x._OrtGetInputName=x.asm.ia).apply(null,arguments)};x._OrtGetOutputName=function(){return(x._OrtGetOutputName=x.asm.ja).apply(null,arguments)};x._OrtFree=function(){return(x._OrtFree=x.asm.ka).apply(null,arguments)};x._OrtCreateTensor=function(){return(x._OrtCreateTensor=x.asm.la).apply(null,arguments)};x._OrtGetTensorData=function(){return(x._OrtGetTensorData=x.asm.ma).apply(null,arguments)};\r\nx._OrtReleaseTensor=function(){return(x._OrtReleaseTensor=x.asm.na).apply(null,arguments)};x._OrtCreateRunOptions=function(){return(x._OrtCreateRunOptions=x.asm.oa).apply(null,arguments)};x._OrtAddRunConfigEntry=function(){return(x._OrtAddRunConfigEntry=x.asm.pa).apply(null,arguments)};x._OrtReleaseRunOptions=function(){return(x._OrtReleaseRunOptions=x.asm.qa).apply(null,arguments)};x._OrtRun=function(){return(x._OrtRun=x.asm.ra).apply(null,arguments)};\r\nx._OrtEndProfiling=function(){return(x._OrtEndProfiling=x.asm.sa).apply(null,arguments)};var T=x._pthread_self=function(){return(T=x._pthread_self=x.asm.ta).apply(null,arguments)},qb=x._malloc=function(){return(qb=x._malloc=x.asm.ua).apply(null,arguments)};x._free=function(){return(x._free=x.asm.va).apply(null,arguments)};x.__emscripten_tls_init=function(){return(x.__emscripten_tls_init=x.asm.wa).apply(null,arguments)};\r\nvar Qb=x.__emscripten_thread_init=function(){return(Qb=x.__emscripten_thread_init=x.asm.xa).apply(null,arguments)};x.__emscripten_thread_crashed=function(){return(x.__emscripten_thread_crashed=x.asm.ya).apply(null,arguments)};\r\nvar vb=x._emscripten_run_in_main_runtime_thread_js=function(){return(vb=x._emscripten_run_in_main_runtime_thread_js=x.asm.Aa).apply(null,arguments)},lb=x.__emscripten_proxy_execute_task_queue=function(){return(lb=x.__emscripten_proxy_execute_task_queue=x.asm.Ba).apply(null,arguments)},Oa=x.__emscripten_thread_free_data=function(){return(Oa=x.__emscripten_thread_free_data=x.asm.Ca).apply(null,arguments)},Ta=x.__emscripten_thread_exit=function(){return(Ta=x.__emscripten_thread_exit=x.asm.Da).apply(null,\r\narguments)},Sa=x._emscripten_stack_set_limits=function(){return(Sa=x._emscripten_stack_set_limits=x.asm.Ea).apply(null,arguments)},Ra=x.stackSave=function(){return(Ra=x.stackSave=x.asm.Fa).apply(null,arguments)},V=x.stackRestore=function(){return(V=x.stackRestore=x.asm.Ga).apply(null,arguments)},ub=x.stackAlloc=function(){return(ub=x.stackAlloc=x.asm.Ha).apply(null,arguments)};x.___cxa_is_pointer_type=function(){return(x.___cxa_is_pointer_type=x.asm.Ia).apply(null,arguments)};x.UTF8ToString=va;\r\nx.stringToUTF8=function(a,b,d){return wa(a,q(),b,d)};x.lengthBytesUTF8=xa;x.keepRuntimeAlive=function(){return noExitRuntime};x.wasmMemory=k;x.stackSave=Ra;x.stackRestore=V;x.stackAlloc=ub;x.ExitStatus=K;x.PThread=R;var Sb;P=function Tb(){Sb||Ub();Sb||(P=Tb)};\r\nfunction Ub(){function a(){if(!Sb&&(Sb=!0,x.calledRun=!0,!sa)){C||U(Ba);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();Ca.unshift(b)}U(Ca)}}}if(!(0 {\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\nnull;var b;b||(b=typeof ortWasm !== 'undefined' ? ortWasm : {});var aa,k;b.ready=new Promise(function(a,c){aa=a;k=c});var ba=Object.assign({},b),p=\"./this.program\",t=(a,c)=>{throw c;},ca=\"object\"==typeof window,u=\"function\"==typeof importScripts,x=\"object\"==typeof process&&\"object\"==typeof process.versions&&\"string\"==typeof process.versions.node,y=\"\",z,A,C,fs,D,E;\r\nif(x)y=u?(__webpack_require__(/*! path */ \"?75c6\").dirname)(y)+\"/\":__dirname+\"/\",E=()=>{D||(fs=__webpack_require__(/*! fs */ \"?63c8\"),D=__webpack_require__(/*! path */ \"?75c6\"))},z=function(a,c){E();a=D.normalize(a);return fs.readFileSync(a,c?void 0:\"utf8\")},C=a=>{a=z(a,!0);a.buffer||(a=new Uint8Array(a));return a},A=(a,c,e)=>{E();a=D.normalize(a);fs.readFile(a,function(f,g){f?e(f):c(g.buffer)})},1{if(noExitRuntime)throw process.exitCode=a,c;c instanceof F||G(\"exiting due to exception: \"+c);process.exit(a)},b.inspect=function(){return\"[Emscripten Module object]\"};else if(ca||u)u?y=self.location.href:\"undefined\"!=typeof document&&document.currentScript&&(y=document.currentScript.src),_scriptDir&&(y=_scriptDir),0!==y.indexOf(\"blob:\")?y=y.substr(0,y.replace(/[?#].*/,\"\").lastIndexOf(\"/\")+1):y=\"\",z=a=>{var c=new XMLHttpRequest;c.open(\"GET\",a,!1);c.send(null);return c.responseText},\r\nu&&(C=a=>{var c=new XMLHttpRequest;c.open(\"GET\",a,!1);c.responseType=\"arraybuffer\";c.send(null);return new Uint8Array(c.response)}),A=(a,c,e)=>{var f=new XMLHttpRequest;f.open(\"GET\",a,!0);f.responseType=\"arraybuffer\";f.onload=()=>{200==f.status||0==f.status&&f.response?c(f.response):e()};f.onerror=e;f.send(null)};var da=b.print||console.log.bind(console),G=b.printErr||console.warn.bind(console);Object.assign(b,ba);ba=null;b.thisProgram&&(p=b.thisProgram);b.quit&&(t=b.quit);var H;\r\nb.wasmBinary&&(H=b.wasmBinary);var noExitRuntime=b.noExitRuntime||!0;\"object\"!=typeof WebAssembly&&I(\"no native wasm support detected\");var J,K=!1,ea=\"undefined\"!=typeof TextDecoder?new TextDecoder(\"utf8\"):void 0;\r\nfunction fa(a,c,e){c>>>=0;var f=c+e;for(e=c;a[e]&&!(e>=f);)++e;if(16g?f+=String.fromCharCode(g):(g-=65536,f+=String.fromCharCode(55296|g>>10,56320|g&1023))}}else f+=String.fromCharCode(g)}return f}function L(a,c){return(a>>>=0)?fa(M,a,c):\"\"}\r\nfunction N(a,c,e,f){e>>>=0;if(!(0=l){var q=a.charCodeAt(++h);l=65536+((l&1023)<<10)|q&1023}if(127>=l){if(e>=f)break;c[e++>>>0]=l}else{if(2047>=l){if(e+1>=f)break;c[e++>>>0]=192|l>>6}else{if(65535>=l){if(e+2>=f)break;c[e++>>>0]=224|l>>12}else{if(e+3>=f)break;c[e++>>>0]=240|l>>18;c[e++>>>0]=128|l>>12&63}c[e++>>>0]=128|l>>6&63}c[e++>>>0]=128|l&63}}c[e>>>0]=0;return e-g}\r\nfunction O(a){for(var c=0,e=0;e=f?c++:2047>=f?c+=2:55296<=f&&57343>=f?(c+=4,++e):c+=3}return c}var ha,P,M,Q,R;function ia(){var a=J.buffer;ha=a;b.HEAP8=P=new Int8Array(a);b.HEAP16=new Int16Array(a);b.HEAP32=Q=new Int32Array(a);b.HEAPU8=M=new Uint8Array(a);b.HEAPU16=new Uint16Array(a);b.HEAPU32=R=new Uint32Array(a);b.HEAPF32=new Float32Array(a);b.HEAPF64=new Float64Array(a)}var ja=[],ka=[],la=[];function ma(){var a=b.preRun.shift();ja.unshift(a)}\r\nvar S=0,T=null,U=null;function I(a){if(b.onAbort)b.onAbort(a);a=\"Aborted(\"+a+\")\";G(a);K=!0;a=new WebAssembly.RuntimeError(a+\". Build with -sASSERTIONS for more info.\");k(a);throw a;}function na(){return V.startsWith(\"data:application/octet-stream;base64,\")}var V;V=\"ort-wasm.wasm\";if(!na()){var oa=V;V=b.locateFile?b.locateFile(oa,y):y+oa}function pa(){var a=V;try{if(a==V&&H)return new Uint8Array(H);if(C)return C(a);throw\"both async and sync fetching of the wasm failed\";}catch(c){I(c)}}\r\nfunction qa(){if(!H&&(ca||u)){if(\"function\"==typeof fetch&&!V.startsWith(\"file://\"))return fetch(V,{credentials:\"same-origin\"}).then(function(a){if(!a.ok)throw\"failed to load wasm binary file at '\"+V+\"'\";return a.arrayBuffer()}).catch(function(){return pa()});if(A)return new Promise(function(a,c){A(V,function(e){a(new Uint8Array(e))},c)})}return Promise.resolve().then(function(){return pa()})}function F(a){this.name=\"ExitStatus\";this.message=\"Program terminated with exit(\"+a+\")\";this.status=a}\r\nfunction W(a){for(;0>2>>>0]=c};this.Ba=function(c){R[this.sa+8>>2>>>0]=c};this.Ga=function(){Q[this.sa>>2>>>0]=0};this.Aa=function(){P[this.sa+12>>0>>>0]=0};this.Ha=function(){P[this.sa+13>>0>>>0]=0};this.ya=function(c,e){this.za();this.Ia(c);this.Ba(e);this.Ga();this.Aa();this.Ha()};this.za=function(){R[this.sa+16>>2>>>0]=0}}var sa=0;function ta(a){var c=O(a)+1,e=ua(c);e&&N(a,P,e,c);return e}\r\nfunction va(a,c,e){function f(w){return(w=w.toTimeString().match(/\\(([A-Za-z ]+)\\)$/))?w[1]:\"GMT\"}var g=(new Date).getFullYear(),h=new Date(g,0,1),l=new Date(g,6,1);g=h.getTimezoneOffset();var q=l.getTimezoneOffset();Q[a>>2>>>0]=60*Math.max(g,q);Q[c>>2>>>0]=Number(g!=q);a=f(h);c=f(l);a=ta(a);c=ta(c);q>2>>>0]=a,R[e+4>>2>>>0]=c):(R[e>>2>>>0]=c,R[e+4>>2>>>0]=a)}function wa(a,c,e){wa.xa||(wa.xa=!0,va(a,c,e))}var Aa={};\r\nfunction Ba(){if(!Ca){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\",_:p||\"./this.program\"},c;for(c in Aa)void 0===Aa[c]?delete a[c]:a[c]=Aa[c];var e=[];for(c in a)e.push(c+\"=\"+a[c]);Ca=e}return Ca}var Ca,Da=[null,[],[]];\r\nfunction Ea(){if(\"object\"==typeof crypto&&\"function\"==typeof crypto.getRandomValues){var a=new Uint8Array(1);return()=>{crypto.getRandomValues(a);return a[0]}}if(x)try{var c=__webpack_require__(/*! crypto */ \"?892d\");return()=>c.randomBytes(1)[0]}catch(e){}return()=>I(\"randomDevice\")}function X(a,c){X.wa||(X.wa=Ea());for(var e=0;e>0>>>0]=X.wa();return 0}function Y(a){return 0===a%4&&(0!==a%100||0===a%400)}var Fa=[31,29,31,30,31,30,31,31,30,31,30,31],Ga=[31,28,31,30,31,30,31,31,30,31,30,31];\r\nfunction Ha(a){var c=Array(O(a)+1);N(a,c,0,c.length);return c}\r\nfunction Ia(a,c,e,f){function g(d,m,n){for(d=\"number\"==typeof d?d.toString():d||\"\";d.lengthxa?-1:0B-d.getDate())m-=B-d.getDate()+1,d.setDate(1),11>n?d.setMonth(n+1):(d.setMonth(0),d.setFullYear(d.getFullYear()+1));else{d.setDate(d.getDate()+m);break}}n=new Date(d.getFullYear()+1,0,4);m=q(new Date(d.getFullYear(),\r\n0,4));n=q(n);return 0>=l(m,d)?0>=l(n,d)?d.getFullYear()+1:d.getFullYear():d.getFullYear()-1}var v=Q[f+40>>2>>>0];f={Ea:Q[f>>2>>>0],Da:Q[f+4>>2>>>0],ta:Q[f+8>>2>>>0],va:Q[f+12>>2>>>0],ua:Q[f+16>>2>>>0],ra:Q[f+20>>2>>>0],la:Q[f+24>>2>>>0],qa:Q[f+28>>2>>>0],Ja:Q[f+32>>2>>>0],Ca:Q[f+36>>2>>>0],Fa:v?L(v):\"\"};e=L(e);v={\"%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 r in v)e=e.replace(new RegExp(r,\"g\"),v[r]);var ya=\"Sunday Monday Tuesday Wednesday Thursday Friday Saturday\".split(\" \"),za=\"January February March April May June July August September October November December\".split(\" \");v={\"%a\":function(d){return ya[d.la].substring(0,3)},\"%A\":function(d){return ya[d.la]},\"%b\":function(d){return za[d.ua].substring(0,\r\n3)},\"%B\":function(d){return za[d.ua]},\"%C\":function(d){return h((d.ra+1900)/100|0,2)},\"%d\":function(d){return h(d.va,2)},\"%e\":function(d){return g(d.va,2,\" \")},\"%g\":function(d){return w(d).toString().substring(2)},\"%G\":function(d){return w(d)},\"%H\":function(d){return h(d.ta,2)},\"%I\":function(d){d=d.ta;0==d?d=12:12d.ta?\"AM\":\"PM\"},\"%S\":function(d){return h(d.Ea,2)},\"%t\":function(){return\"\\t\"},\"%u\":function(d){return d.la||7},\"%U\":function(d){return h(Math.floor((d.qa+7-d.la)/7),2)},\"%V\":function(d){var m=Math.floor((d.qa+7-(d.la+6)%7)/7);2>=(d.la+371-d.qa-2)%7&&m++;if(m)53==m&&(n=(d.la+371-d.qa)%7,4==n||3==n&&Y(d.ra)||(m=1));else{m=52;var n=(d.la+7-d.qa-1)%7;(4==n||5==n&&Y(d.ra%400-1))&&m++}return h(m,2)},\"%w\":function(d){return d.la},\"%W\":function(d){return h(Math.floor((d.qa+\r\n7-(d.la+6)%7)/7),2)},\"%y\":function(d){return(d.ra+1900).toString().substring(2)},\"%Y\":function(d){return d.ra+1900},\"%z\":function(d){d=d.Ca;var m=0<=d;d=Math.abs(d)/60;return(m?\"+\":\"-\")+String(\"0000\"+(d/60*100+d%60)).slice(-4)},\"%Z\":function(d){return d.Fa},\"%%\":function(){return\"%\"}};e=e.replace(/%%/g,\"\\x00\\x00\");for(r in v)e.includes(r)&&(e=e.replace(new RegExp(r,\"g\"),v[r](f)));e=e.replace(/\\0\\0/g,\"%\");r=Ha(e);if(r.length>c)return 0;P.set(r,a>>>0);return r.length-1}\r\nvar Ja={a:function(a){return ua(a+24)+24},b:function(a,c,e){(new ra(a)).ya(c,e);sa++;throw a;},g:function(){return 0},I:function(){},w:function(){},y:function(){},K:function(){return 0},G:function(){},C:function(){},F:function(){},k:function(){},x:function(){},u:function(){},H:function(){},v:function(){},n:function(){},p:function(){I(\"To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking\")},o:function(){I(\"To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking\")},\r\nl:function(){return Date.now()},L:function(){return!0},M:function(a,c){a=new Date(1E3*(R[a>>>2]+4294967296*Q[a+4>>>2]));Q[c>>2>>>0]=a.getUTCSeconds();Q[c+4>>2>>>0]=a.getUTCMinutes();Q[c+8>>2>>>0]=a.getUTCHours();Q[c+12>>2>>>0]=a.getUTCDate();Q[c+16>>2>>>0]=a.getUTCMonth();Q[c+20>>2>>>0]=a.getUTCFullYear()-1900;Q[c+24>>2>>>0]=a.getUTCDay();Q[c+28>>2>>>0]=(a.getTime()-Date.UTC(a.getUTCFullYear(),0,1,0,0,0,0))/864E5|0},N:function(a,c){a=new Date(1E3*(R[a>>>2]+4294967296*Q[a+4>>>2]));Q[c>>2>>>0]=a.getSeconds();\r\nQ[c+4>>2>>>0]=a.getMinutes();Q[c+8>>2>>>0]=a.getHours();Q[c+12>>2>>>0]=a.getDate();Q[c+16>>2>>>0]=a.getMonth();Q[c+20>>2>>>0]=a.getFullYear()-1900;Q[c+24>>2>>>0]=a.getDay();var e=new Date(a.getFullYear(),0,1);Q[c+28>>2>>>0]=(a.getTime()-e.getTime())/864E5|0;Q[c+36>>2>>>0]=-(60*a.getTimezoneOffset());var f=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();e=e.getTimezoneOffset();Q[c+32>>2>>>0]=(f!=e&&a.getTimezoneOffset()==Math.min(e,f))|0},O:function(a){var c=new Date(Q[a+20>>2>>>0]+1900,Q[a+16>>\r\n2>>>0],Q[a+12>>2>>>0],Q[a+8>>2>>>0],Q[a+4>>2>>>0],Q[a>>2>>>0],0),e=Q[a+32>>2>>>0],f=c.getTimezoneOffset(),g=new Date(c.getFullYear(),0,1),h=(new Date(c.getFullYear(),6,1)).getTimezoneOffset(),l=g.getTimezoneOffset(),q=Math.min(l,h);0>e?Q[a+32>>2>>>0]=Number(h!=l&&q==f):0>2>>>0]=c.getDay();Q[a+28>>2>>>0]=(c.getTime()-g.getTime())/864E5|0;Q[a>>2>>>0]=c.getSeconds();Q[a+4>>2>>>0]=c.getMinutes();Q[a+8>>2>>>0]=c.getHours();Q[a+\r\n12>>2>>>0]=c.getDate();Q[a+16>>2>>>0]=c.getMonth();return c.getTime()/1E3|0},z:function(){return-52},B:function(){},m:wa,d:function(){I(\"\")},t:function(){return 4294901760},h:x?()=>{var a=process.hrtime();return 1E3*a[0]+a[1]/1E6}:()=>performance.now(),J:function(a,c,e){M.copyWithin(a>>>0,c>>>0,c+e>>>0)},f:function(a){var c=M.length;a>>>=0;if(4294901760=e;e*=2){var f=c*(1+.2/e);f=Math.min(f,a+100663296);var g=Math;f=Math.max(a,f);g=g.min.call(g,4294901760,f+(65536-f%65536)%\r\n65536);a:{try{J.grow(g-ha.byteLength+65535>>>16);ia();var h=1;break a}catch(l){}h=void 0}if(h)return!0}return!1},D:function(a,c){var e=0;Ba().forEach(function(f,g){var h=c+e;g=R[a+4*g>>2>>>0]=h;for(h=0;h>0>>>0]=f.charCodeAt(h);P[g>>0>>>0]=0;e+=f.length+1});return 0},E:function(a,c){var e=Ba();R[a>>2>>>0]=e.length;var f=0;e.forEach(function(g){f+=g.length+1});R[c>>2>>>0]=f;return 0},r:function(a){if(!noExitRuntime){if(b.onExit)b.onExit(a);K=!0}t(a,new F(a))},e:function(){return 52},\r\nj:function(){return 52},q:function(){return 70},i:function(a,c,e,f){for(var g=0,h=0;h>2>>>0],q=R[c+4>>2>>>0];c+=8;for(var w=0;w>>0],r=Da[a];0===v||10===v?((1===a?da:G)(fa(r,0)),r.length=0):r.push(v)}g+=q}R[f>>2>>>0]=g;return 0},s:X,A:Ia,c:function(a,c,e,f){return Ia(a,c,e,f)}};\r\n(function(){function a(g){b.asm=g.exports;J=b.asm.P;ia();ka.unshift(b.asm.Q);S--;b.monitorRunDependencies&&b.monitorRunDependencies(S);0==S&&(null!==T&&(clearInterval(T),T=null),U&&(g=U,U=null,g()))}function c(g){a(g.instance)}function e(g){return qa().then(function(h){return WebAssembly.instantiate(h,f)}).then(function(h){return h}).then(g,function(h){G(\"failed to asynchronously prepare wasm: \"+h);I(h)})}var f={a:Ja};S++;b.monitorRunDependencies&&b.monitorRunDependencies(S);if(b.instantiateWasm)try{return b.instantiateWasm(f,\r\na)}catch(g){return G(\"Module.instantiateWasm callback failed with error: \"+g),!1}(function(){return H||\"function\"!=typeof WebAssembly.instantiateStreaming||na()||V.startsWith(\"file://\")||x||\"function\"!=typeof fetch?e(c):fetch(V,{credentials:\"same-origin\"}).then(function(g){return WebAssembly.instantiateStreaming(g,f).then(c,function(h){G(\"wasm streaming compile failed: \"+h);G(\"falling back to ArrayBuffer instantiation\");return e(c)})})})().catch(k);return{}})();\r\nb.___wasm_call_ctors=function(){return(b.___wasm_call_ctors=b.asm.Q).apply(null,arguments)};b._OrtInit=function(){return(b._OrtInit=b.asm.R).apply(null,arguments)};b._OrtCreateSessionOptions=function(){return(b._OrtCreateSessionOptions=b.asm.S).apply(null,arguments)};b._OrtAppendExecutionProvider=function(){return(b._OrtAppendExecutionProvider=b.asm.T).apply(null,arguments)};b._OrtAddSessionConfigEntry=function(){return(b._OrtAddSessionConfigEntry=b.asm.U).apply(null,arguments)};\r\nb._OrtReleaseSessionOptions=function(){return(b._OrtReleaseSessionOptions=b.asm.V).apply(null,arguments)};b._OrtCreateSession=function(){return(b._OrtCreateSession=b.asm.W).apply(null,arguments)};b._OrtReleaseSession=function(){return(b._OrtReleaseSession=b.asm.X).apply(null,arguments)};b._OrtGetInputCount=function(){return(b._OrtGetInputCount=b.asm.Y).apply(null,arguments)};b._OrtGetOutputCount=function(){return(b._OrtGetOutputCount=b.asm.Z).apply(null,arguments)};\r\nb._OrtGetInputName=function(){return(b._OrtGetInputName=b.asm._).apply(null,arguments)};b._OrtGetOutputName=function(){return(b._OrtGetOutputName=b.asm.$).apply(null,arguments)};b._OrtFree=function(){return(b._OrtFree=b.asm.aa).apply(null,arguments)};b._OrtCreateTensor=function(){return(b._OrtCreateTensor=b.asm.ba).apply(null,arguments)};b._OrtGetTensorData=function(){return(b._OrtGetTensorData=b.asm.ca).apply(null,arguments)};\r\nb._OrtReleaseTensor=function(){return(b._OrtReleaseTensor=b.asm.da).apply(null,arguments)};b._OrtCreateRunOptions=function(){return(b._OrtCreateRunOptions=b.asm.ea).apply(null,arguments)};b._OrtAddRunConfigEntry=function(){return(b._OrtAddRunConfigEntry=b.asm.fa).apply(null,arguments)};b._OrtReleaseRunOptions=function(){return(b._OrtReleaseRunOptions=b.asm.ga).apply(null,arguments)};b._OrtRun=function(){return(b._OrtRun=b.asm.ha).apply(null,arguments)};\r\nb._OrtEndProfiling=function(){return(b._OrtEndProfiling=b.asm.ia).apply(null,arguments)};var ua=b._malloc=function(){return(ua=b._malloc=b.asm.ja).apply(null,arguments)};b._free=function(){return(b._free=b.asm.ka).apply(null,arguments)};var Ka=b.stackSave=function(){return(Ka=b.stackSave=b.asm.ma).apply(null,arguments)},La=b.stackRestore=function(){return(La=b.stackRestore=b.asm.na).apply(null,arguments)},Ma=b.stackAlloc=function(){return(Ma=b.stackAlloc=b.asm.oa).apply(null,arguments)};\r\nb.___cxa_is_pointer_type=function(){return(b.___cxa_is_pointer_type=b.asm.pa).apply(null,arguments)};b.UTF8ToString=L;b.stringToUTF8=function(a,c,e){return N(a,M,c,e)};b.lengthBytesUTF8=O;b.stackSave=Ka;b.stackRestore=La;b.stackAlloc=Ma;var Z;U=function Na(){Z||Oa();Z||(U=Na)};\r\nfunction Oa(){function a(){if(!Z&&(Z=!0,b.calledRun=!0,!K)){W(ka);aa(b);if(b.onRuntimeInitialized)b.onRuntimeInitialized();if(b.postRun)for(\"function\"==typeof b.postRun&&(b.postRun=[b.postRun]);b.postRun.length;){var c=b.postRun.shift();la.unshift(c)}W(la)}}if(!(0 {\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/***/ \"?892d\":\n/*!************************!*\\\n !*** crypto (ignored) ***!\n \\************************/\n/***/ (() => {\n\n/* (ignored) */\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 (0, wasm_core_impl_1.run)(sessionId, inputIndices, inputs, outputIndices, options)\n .then(outputs => {\n postMessage({ type: 'run', out: outputs }, (0, wasm_core_impl_1.extractTransferableBuffers)(outputs));\n }, err => {\n postMessage({ type: 'run', err });\n });\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.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 c(){k.buffer!=l&&m(k.buffer);return aa}function q(){k.buffer!=l&&m(k.buffer);return ba}function t(){k.buffer!=l&&m(k.buffer);return ca}function w(){k.buffer!=l&&m(k.buffer);return da}function ea(){k.buffer!=l&&m(k.buffer);return fa}null;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",z=(a,b)=>{throw b;},la="object"==typeof window,A="function"==typeof importScripts,B="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node,C=x.ENVIRONMENT_IS_PTHREAD||!1,D="";function ma(a){return x.locateFile?x.locateFile(a,D):D+a}var na,F,G,fs,H,I; +if(B){D=A?(__webpack_require__(/*! path */ "?75c6").dirname)(D)+"/":__dirname+"/";I=()=>{H||(fs=__webpack_require__(/*! fs */ "?63c8"),H=__webpack_require__(/*! path */ "?75c6"))};na=function(b,d){I();b=H.normalize(b);return fs.readFileSync(b,d?void 0:"utf8")};G=b=>{b=na(b,!0);b.buffer||(b=new Uint8Array(b));return b};F=(b,d,e)=>{I();b=H.normalize(b);fs.readFile(b,function(g,h){g?e(g):d(h.buffer)})};1{if(noExitRuntime)throw process.exitCode=b,d;d instanceof K||L("exiting due to exception: "+d);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(la||A)A?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||(na=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.send(null);return b.responseText},A&&(G=a=>{var b=new XMLHttpRequest;b.open("GET",a,!1);b.responseType="arraybuffer";b.send(null);return new Uint8Array(b.response)}),F=(a,b,d)=>{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):d()};e.onerror= +d;e.send(null)});B&&"undefined"==typeof performance&&(__webpack_require__.g.performance=(__webpack_require__(/*! perf_hooks */ "?674f").performance));var oa=console.log.bind(console),pa=console.warn.bind(console);B&&(I(),oa=a=>fs.writeSync(1,a+"\n"),pa=a=>fs.writeSync(2,a+"\n"));var qa=x.print||oa,L=x.printErr||pa;Object.assign(x,ja);ja=null;x.thisProgram&&(ka=x.thisProgram);x.quit&&(z=x.quit);var M;x.wasmBinary&&(M=x.wasmBinary);var noExitRuntime=x.noExitRuntime||!0;"object"!=typeof WebAssembly&&N("no native wasm support detected"); +var k,ra,sa=!1,ta="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0; +function ua(a,b,d){b>>>=0;var e=b+d;for(d=b;a[d]&&!(d>=e);)++d;if(16g?e+=String.fromCharCode(g):(g-=65536,e+=String.fromCharCode(55296|g>>10,56320|g&1023))}}else e+=String.fromCharCode(g)}return e} +function va(a,b){return(a>>>=0)?ua(q(),a,b):""} +function wa(a,b,d,e){d>>>=0;if(!(0=n){var u=a.charCodeAt(++h);n=65536+((n&1023)<<10)|u&1023}if(127>=n){if(d>=e)break;b[d++>>>0]=n}else{if(2047>=n){if(d+1>=e)break;b[d++>>>0]=192|n>>6}else{if(65535>=n){if(d+2>=e)break;b[d++>>>0]=224|n>>12}else{if(d+3>=e)break;b[d++>>>0]=240|n>>18;b[d++>>>0]=128|n>>12&63}b[d++>>>0]=128|n>>6&63}b[d++>>>0]=128|n&63}}b[d>>>0]=0;return d-g} +function xa(a){for(var b=0,d=0;d=e?b++:2047>=e?b+=2:55296<=e&&57343>=e?(b+=4,++d):b+=3}return b}var l,aa,ba,ca,da,fa;C&&(l=x.buffer);function m(a){l=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 ya=x.INITIAL_MEMORY||16777216; +if(C)k=x.wasmMemory,l=x.buffer;else if(x.wasmMemory)k=x.wasmMemory;else if(k=new WebAssembly.Memory({initial:ya/65536,maximum:65536,shared:!0}),!(k.buffer instanceof SharedArrayBuffer))throw L("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");k&&(l=k.buffer);ya=l.byteLength;m(l);var za,Aa=[],Ba=[],Ca=[];function Da(){var a=x.preRun.shift();Aa.unshift(a)}var O=0,Ea=null,P=null;function N(a){if(C)postMessage({cmd:"onAbort",arg:a});else if(x.onAbort)x.onAbort(a);a="Aborted("+a+")";L(a);sa=!0;a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");ia(a);throw a;}function Fa(){return Q.startsWith("data:application/octet-stream;base64,")}var Q;Q="ort-wasm-threaded.wasm";Fa()||(Q=ma(Q)); +function Ga(){var a=Q;try{if(a==Q&&M)return new Uint8Array(M);if(G)return G(a);throw"both async and sync fetching of the wasm failed";}catch(b){N(b)}} +function Ha(){if(!M&&(la||A)){if("function"==typeof fetch&&!Q.startsWith("file://"))return fetch(Q,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+Q+"'";return a.arrayBuffer()}).catch(function(){return Ga()});if(F)return new Promise(function(a,b){F(Q,function(d){a(new Uint8Array(d))},b)})}return Promise.resolve().then(function(){return Ga()})}var Ia={}; +function K(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a}function Ja(a){(a=R.La[a])||N();R.Xa(a)}function Ka(a){var b=R.lb();if(!b)return 6;R.Ra.push(b);R.La[a.Ka]=b;b.Ka=a.Ka;var d={cmd:"run",start_routine:a.pb,arg:a.ib,pthread_ptr:a.Ka};b.Qa=()=>{d.time=performance.now();b.postMessage(d,a.vb)};b.loaded&&(b.Qa(),delete b.Qa);return 0}function La(a){if(C)return S(1,1,a);if(!noExitRuntime){R.qb();if(x.onExit)x.onExit(a);sa=!0}z(a,new K(a))} +function Ma(a,b){if(!b&&C)throw Na(a),"unwind";La(a)} +var R={Oa:[],Ra:[],$a:[],La:{},Ua:function(){C&&R.mb()},xb:function(){},mb:function(){R.receiveObjectTransfer=R.ob;R.threadInitTLS=R.Za;R.setExitStatus=R.Ya;noExitRuntime=!1},Ya:function(){},qb:function(){for(var a of Object.values(R.La))R.Xa(a);for(a of R.Oa)a.terminate();R.Oa=[]},Xa:function(a){var b=a.Ka;delete R.La[b];R.Oa.push(a);R.Ra.splice(R.Ra.indexOf(a),1);a.Ka=0;Oa(b)},ob:function(){},Za:function(){R.$a.forEach(a=>a())},nb:function(a,b){a.onmessage=d=>{d=d.data;var e=d.cmd;a.Ka&&(R.kb=a.Ka); +if(d.targetThread&&d.targetThread!=T()){var g=R.La[d.yb];g?g.postMessage(d,d.transferList):L('Internal error! Worker sent a message "'+e+'" to target pthread '+d.targetThread+", but that thread no longer exists!")}else if("processProxyingQueue"===e)Pa(d.queue);else if("spawnThread"===e)Ka(d);else if("cleanupThread"===e)Ja(d.thread);else if("killThread"===e)d=d.thread,e=R.La[d],delete R.La[d],e.terminate(),Oa(d),R.Ra.splice(R.Ra.indexOf(e),1),e.Ka=0;else if("cancelThread"===e)R.La[d.thread].postMessage({cmd:"cancel"}); +else if("loaded"===e)a.loaded=!0,b&&b(a),a.Qa&&(a.Qa(),delete a.Qa);else if("print"===e)qa("Thread "+d.threadId+": "+d.text);else if("printErr"===e)L("Thread "+d.threadId+": "+d.text);else if("alert"===e)alert("Thread "+d.threadId+": "+d.text);else if("setimmediate"===d.target)a.postMessage(d);else if("onAbort"===e){if(x.onAbort)x.onAbort(d.arg)}else e&&L("worker sent an unknown command "+e);R.kb=void 0};a.onerror=d=>{L("worker sent an error! "+d.filename+":"+d.lineno+": "+d.message);throw d;};B&& +(a.on("message",function(d){a.onmessage({data:d})}),a.on("error",function(d){a.onerror(d)}),a.on("detachedExit",function(){}));a.postMessage({cmd:"load",urlOrBlob:x.mainScriptUrlOrBlob||_scriptDir,wasmMemory:k,wasmModule:ra})},hb:function(){var a=ma("ort-wasm-threaded.worker.js");R.Oa.push(new Worker(a))},lb:function(){0==R.Oa.length&&(R.hb(),R.nb(R.Oa[0]));return R.Oa.pop()}};x.PThread=R;function U(a){for(;0>2>>>0];a=t()[a+48>>2>>>0];Sa(b,b-a);V(b)};function Na(a){if(C)return S(2,0,a);try{Ma(a)}catch(b){b instanceof K||"unwind"==b||z(1,b)}}var W=[];x.invokeEntryPoint=function(a,b){var d=W[a];d||(a>=W.length&&(W.length=a+1),W[a]=d=za.get(a));a=d(b);noExitRuntime?R.Ya(a):Ta(a)};function Ua(a,b){c().set(a,b>>>0)} +function Va(a){this.Pa=a-24;this.gb=function(b){w()[this.Pa+4>>2>>>0]=b};this.cb=function(b){w()[this.Pa+8>>2>>>0]=b};this.eb=function(){t()[this.Pa>>2>>>0]=0};this.bb=function(){var b=0;c()[this.Pa+12>>0>>>0]=b};this.fb=function(){var b=0;c()[this.Pa+13>>0>>>0]=b};this.Ua=function(b,d){this.ab();this.gb(b);this.cb(d);this.eb();this.bb();this.fb()};this.ab=function(){w()[this.Pa+16>>2>>>0]=0}}var Wa=0;function Xa(a,b,d,e){return C?S(3,1,a,b,d,e):Ya(a,b,d,e)} +function Ya(a,b,d,e){if("undefined"==typeof SharedArrayBuffer)return L("Current environment does not support SharedArrayBuffer, pthreads are not available!"),6;var g=[];if(C&&0===g.length)return Xa(a,b,d,e);a={pb:d,Ka:a,ib:e,vb:g};return C?(a.wb="spawnThread",postMessage(a,g),0):Ka(a)}function Za(a,b,d){return C?S(4,1,a,b,d):0}function $a(a,b){if(C)return S(5,1,a,b)}function ab(a,b){if(C)return S(6,1,a,b)}function bb(a,b,d){if(C)return S(7,1,a,b,d)}function cb(a,b,d){return C?S(8,1,a,b,d):0} +function db(a,b){if(C)return S(9,1,a,b)}function eb(a,b,d){if(C)return S(10,1,a,b,d)}function fb(a,b,d,e){if(C)return S(11,1,a,b,d,e)}function gb(a,b,d,e){if(C)return S(12,1,a,b,d,e)}function hb(a,b,d,e){if(C)return S(13,1,a,b,d,e)}function ib(a){if(C)return S(14,1,a)}function jb(a,b){if(C)return S(15,1,a,b)}function kb(a,b,d){if(C)return S(16,1,a,b,d)}function Pa(a){Atomics.store(t(),a>>2,1);T()&&lb(a);Atomics.compareExchange(t(),a>>2,1,0)}x.executeNotifiedProxyingQueue=Pa; +function mb(a){return w()[a>>>2]+4294967296*t()[a+4>>>2]}function nb(a,b,d,e,g,h){return C?S(17,1,a,b,d,e,g,h):-52}function ob(a,b,d,e,g,h){if(C)return S(18,1,a,b,d,e,g,h)}function pb(a){var b=xa(a)+1,d=qb(b);d&&wa(a,c(),d,b);return d} +function rb(a,b,d){function e(v){return(v=v.toTimeString().match(/\(([A-Za-z ]+)\)$/))?v[1]:"GMT"}if(C)return S(19,1,a,b,d);var g=(new Date).getFullYear(),h=new Date(g,0,1),n=new Date(g,6,1);g=h.getTimezoneOffset();var u=n.getTimezoneOffset(),E=Math.max(g,u);t()[a>>2>>>0]=60*E;t()[b>>2>>>0]=Number(g!=u);a=e(h);b=e(n);a=pb(a);b=pb(b);u>2>>>0]=a,w()[d+4>>2>>>0]=b):(w()[d>>2>>>0]=b,w()[d+4>>2>>>0]=a)}function sb(a,b,d){sb.jb||(sb.jb=!0,rb(a,b,d))}var X,tb; +tb=B?()=>{var a=process.hrtime();return 1E3*a[0]+a[1]/1E6}:C?()=>performance.now()-x.__performance_now_clock_drift:()=>performance.now();function S(a,b){var d=arguments.length-2,e=arguments;return Qa(()=>{for(var g=ub(8*d),h=g>>3,n=0;n>>0]=u}return vb(a,d,g,b)})}var wb=[],xb={}; +function yb(){if(!zb){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 xb)void 0===xb[b]?delete a[b]:a[b]=xb[b];var d=[];for(b in a)d.push(b+"="+a[b]);zb=d}return zb}var zb; +function Ab(a,b){if(C)return S(20,1,a,b);var d=0;yb().forEach(function(e,g){var h=b+d;g=w()[a+4*g>>2>>>0]=h;for(h=0;h>0>>>0]=e.charCodeAt(h);c()[g>>0>>>0]=0;d+=e.length+1});return 0}function Bb(a,b){if(C)return S(21,1,a,b);var d=yb();w()[a>>2>>>0]=d.length;var e=0;d.forEach(function(g){e+=g.length+1});w()[b>>2>>>0]=e;return 0}function Cb(a){return C?S(22,1,a):52}function Gb(a,b,d,e){return C?S(23,1,a,b,d,e):52}function Hb(a,b,d,e,g){return C?S(24,1,a,b,d,e,g):70} +var Ib=[null,[],[]];function Jb(a,b,d,e){if(C)return S(25,1,a,b,d,e);for(var g=0,h=0;h>2>>>0],u=w()[b+4>>2>>>0];b+=8;for(var E=0;E>>0],y=Ib[a];0===v||10===v?((1===a?qa:L)(ua(y,0)),y.length=0):y.push(v)}g+=u}w()[e>>2>>>0]=g;return 0} +function Kb(){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__(/*! crypto */ "?892d");return()=>b.randomBytes(1)[0]}catch(d){}return()=>N("randomDevice")}function Y(a,b){Y.Wa||(Y.Wa=Kb());for(var d=0;d>0>>>0]=Y.Wa();return 0}function Z(a){return 0===a%4&&(0!==a%100||0===a%400)}var Lb=[31,29,31,30,31,30,31,31,30,31,30,31],Mb=[31,28,31,30,31,30,31,31,30,31,30,31]; +function Nb(a){var b=Array(xa(a)+1);wa(a,b,0,b.length);return b} +function Ob(a,b,d,e){function g(f,p,r){for(f="number"==typeof f?f.toString():f||"";f.lengthDb?-1:0J-f.getDate())p-=J-f.getDate()+1,f.setDate(1),11>r?f.setMonth(r+1):(f.setMonth(0),f.setFullYear(f.getFullYear()+1));else{f.setDate(f.getDate()+p);break}}r=new Date(f.getFullYear()+1,0,4);p=u(new Date(f.getFullYear(), +0,4));r=u(r);return 0>=n(p,f)?0>=n(r,f)?f.getFullYear()+1:f.getFullYear():f.getFullYear()-1}var v=t()[e+40>>2>>>0];e={tb:t()[e>>2>>>0],sb:t()[e+4>>2>>>0],Sa:t()[e+8>>2>>>0],Va:t()[e+12>>2>>>0],Ta:t()[e+16>>2>>>0],Na:t()[e+20>>2>>>0],Ja:t()[e+24>>2>>>0],Ma:t()[e+28>>2>>>0],zb:t()[e+32>>2>>>0],rb:t()[e+36>>2>>>0],ub:v?va(v):""};d=va(d);v={"%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 y in v)d=d.replace(new RegExp(y,"g"),v[y]);var Eb="Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),Fb="January February March April May June July August September October November December".split(" ");v={"%a":function(f){return Eb[f.Ja].substring(0,3)},"%A":function(f){return Eb[f.Ja]}, +"%b":function(f){return Fb[f.Ta].substring(0,3)},"%B":function(f){return Fb[f.Ta]},"%C":function(f){return h((f.Na+1900)/100|0,2)},"%d":function(f){return h(f.Va,2)},"%e":function(f){return g(f.Va,2," ")},"%g":function(f){return E(f).toString().substring(2)},"%G":function(f){return E(f)},"%H":function(f){return h(f.Sa,2)},"%I":function(f){f=f.Sa;0==f?f=12:12f.Sa?"AM":"PM"},"%S":function(f){return h(f.tb,2)},"%t":function(){return"\t"},"%u":function(f){return f.Ja||7},"%U":function(f){return h(Math.floor((f.Ma+7-f.Ja)/7),2)},"%V":function(f){var p=Math.floor((f.Ma+7-(f.Ja+6)%7)/7);2>=(f.Ja+371-f.Ma-2)%7&&p++;if(p)53==p&&(r=(f.Ja+371-f.Ma)%7,4==r||3==r&&Z(f.Na)||(p=1));else{p=52;var r=(f.Ja+7-f.Ma-1)%7;(4==r||5==r&&Z(f.Na%400-1))&&p++}return h(p,2)}, +"%w":function(f){return f.Ja},"%W":function(f){return h(Math.floor((f.Ma+7-(f.Ja+6)%7)/7),2)},"%y":function(f){return(f.Na+1900).toString().substring(2)},"%Y":function(f){return f.Na+1900},"%z":function(f){f=f.rb;var p=0<=f;f=Math.abs(f)/60;return(p?"+":"-")+String("0000"+(f/60*100+f%60)).slice(-4)},"%Z":function(f){return f.ub},"%%":function(){return"%"}};d=d.replace(/%%/g,"\x00\x00");for(y in v)d.includes(y)&&(d=d.replace(new RegExp(y,"g"),v[y](e)));d=d.replace(/\0\0/g,"%");y=Nb(d);if(y.length> +b)return 0;Ua(y,a);return y.length-1}R.Ua(); +var Pb=[null,La,Na,Xa,Za,$a,ab,bb,cb,db,eb,fb,gb,hb,ib,jb,kb,nb,ob,rb,Ab,Bb,Cb,Gb,Hb,Jb],Rb={b:function(a){return qb(a+24)+24},c:function(a,b,d){(new Va(a)).Ua(b,d);Wa++;throw a;},L:function(a){Qb(a,!A,1,!la);R.Za()},l:function(a){C?postMessage({cmd:"cleanupThread",thread:a}):Ja(a)},D:Ya,i:Za,R:$a,z:ab,B:bb,T:cb,P:db,I:eb,O:fb,p:gb,A:hb,x:ib,Q:jb,y:kb,r:function(){},j:function(){N("To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking")},s:function(){N("To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking")}, +q:function(){return Date.now()},E:function(){return 2097152},V:function(){return!0},F:function(a,b,d,e){if(a==b)setTimeout(()=>Pa(e));else if(C)postMessage({targetThread:a,cmd:"processProxyingQueue",queue:e});else{a=R.La[a];if(!a)return;a.postMessage({cmd:"processProxyingQueue",queue:e})}return 1},K:function(){return-1},W:function(a,b){a=new Date(1E3*mb(a));t()[b>>2>>>0]=a.getUTCSeconds();t()[b+4>>2>>>0]=a.getUTCMinutes();t()[b+8>>2>>>0]=a.getUTCHours();t()[b+12>>2>>>0]=a.getUTCDate();t()[b+16>>2>>> +0]=a.getUTCMonth();t()[b+20>>2>>>0]=a.getUTCFullYear()-1900;t()[b+24>>2>>>0]=a.getUTCDay();a=(a.getTime()-Date.UTC(a.getUTCFullYear(),0,1,0,0,0,0))/864E5|0;t()[b+28>>2>>>0]=a},X:function(a,b){a=new Date(1E3*mb(a));t()[b>>2>>>0]=a.getSeconds();t()[b+4>>2>>>0]=a.getMinutes();t()[b+8>>2>>>0]=a.getHours();t()[b+12>>2>>>0]=a.getDate();t()[b+16>>2>>>0]=a.getMonth();t()[b+20>>2>>>0]=a.getFullYear()-1900;t()[b+24>>2>>>0]=a.getDay();var d=new Date(a.getFullYear(),0,1),e=(a.getTime()-d.getTime())/864E5|0;t()[b+ +28>>2>>>0]=e;t()[b+36>>2>>>0]=-(60*a.getTimezoneOffset());e=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();d=d.getTimezoneOffset();a=(e!=d&&a.getTimezoneOffset()==Math.min(d,e))|0;t()[b+32>>2>>>0]=a},Y:function(a){var b=new Date(t()[a+20>>2>>>0]+1900,t()[a+16>>2>>>0],t()[a+12>>2>>>0],t()[a+8>>2>>>0],t()[a+4>>2>>>0],t()[a>>2>>>0],0),d=t()[a+32>>2>>>0],e=b.getTimezoneOffset(),g=new Date(b.getFullYear(),0,1),h=(new Date(b.getFullYear(),6,1)).getTimezoneOffset(),n=g.getTimezoneOffset(),u=Math.min(n, +h);0>d?t()[a+32>>2>>>0]=Number(h!=n&&u==e):0>2>>>0]=b.getDay();d=(b.getTime()-g.getTime())/864E5|0;t()[a+28>>2>>>0]=d;t()[a>>2>>>0]=b.getSeconds();t()[a+4>>2>>>0]=b.getMinutes();t()[a+8>>2>>>0]=b.getHours();t()[a+12>>2>>>0]=b.getDate();t()[a+16>>2>>>0]=b.getMonth();return b.getTime()/1E3|0},G:nb,H:ob,Z:sb,d:function(){N("")},m:function(){if(!B&&!A){var a="Blocking on the main thread is very dangerous, see https://emscripten.org/docs/porting/pthreads.html#blocking-on-the-main-browser-thread"; +X||(X={});X[a]||(X[a]=1,B&&(a="warning: "+a),L(a))}},w:function(){return 4294901760},f:tb,S:function(a,b,d){q().copyWithin(a>>>0,b>>>0,b+d>>>0)},g:function(){return B?(__webpack_require__(/*! os */ "?aedb").cpus)().length:navigator.hardwareConcurrency},J:function(a,b,d){wb.length=b;d>>=3;for(var e=0;e>>0];return(0>a?Ia[-a-1]:Pb[a]).apply(null,wb)},v:function(a){var b=q().length;a>>>=0;if(a<=b||4294901760=d;d*=2){var e=b*(1+.2/d);e=Math.min(e,a+100663296);var g=Math;e=Math.max(a, +e);g=g.min.call(g,4294901760,e+(65536-e%65536)%65536);a:{try{k.grow(g-l.byteLength+65535>>>16);m(k.buffer);var h=1;break a}catch(n){}h=void 0}if(h)return!0}return!1},U:function(){throw"unwind";},M:Ab,N:Bb,k:Ma,h:Cb,o:Gb,t:Hb,n:Jb,u:Y,a:k||x.wasmMemory,C:Ob,e:function(a,b,d,e){return Ob(a,b,d,e)}}; +(function(){function a(g,h){x.asm=g.exports;R.$a.push(x.asm.wa);za=x.asm.za;Ba.unshift(x.asm._);ra=h;C||(O--,x.monitorRunDependencies&&x.monitorRunDependencies(O),0==O&&(null!==Ea&&(clearInterval(Ea),Ea=null),P&&(g=P,P=null,g())))}function b(g){a(g.instance,g.module)}function d(g){return Ha().then(function(h){return WebAssembly.instantiate(h,e)}).then(function(h){return h}).then(g,function(h){L("failed to asynchronously prepare wasm: "+h);N(h)})}var e={a:Rb};C||(O++,x.monitorRunDependencies&&x.monitorRunDependencies(O)); +if(x.instantiateWasm)try{return x.instantiateWasm(e,a)}catch(g){return L("Module.instantiateWasm callback failed with error: "+g),!1}(function(){return M||"function"!=typeof WebAssembly.instantiateStreaming||Fa()||Q.startsWith("file://")||B||"function"!=typeof fetch?d(b):fetch(Q,{credentials:"same-origin"}).then(function(g){return WebAssembly.instantiateStreaming(g,e).then(b,function(h){L("wasm streaming compile failed: "+h);L("falling back to ArrayBuffer instantiation");return d(b)})})})().catch(ia); +return{}})();x.___wasm_call_ctors=function(){return(x.___wasm_call_ctors=x.asm._).apply(null,arguments)};x._OrtInit=function(){return(x._OrtInit=x.asm.$).apply(null,arguments)};x._OrtCreateSessionOptions=function(){return(x._OrtCreateSessionOptions=x.asm.aa).apply(null,arguments)};x._OrtAppendExecutionProvider=function(){return(x._OrtAppendExecutionProvider=x.asm.ba).apply(null,arguments)};x._OrtAddSessionConfigEntry=function(){return(x._OrtAddSessionConfigEntry=x.asm.ca).apply(null,arguments)}; +x._OrtReleaseSessionOptions=function(){return(x._OrtReleaseSessionOptions=x.asm.da).apply(null,arguments)};x._OrtCreateSession=function(){return(x._OrtCreateSession=x.asm.ea).apply(null,arguments)};x._OrtReleaseSession=function(){return(x._OrtReleaseSession=x.asm.fa).apply(null,arguments)};x._OrtGetInputCount=function(){return(x._OrtGetInputCount=x.asm.ga).apply(null,arguments)};x._OrtGetOutputCount=function(){return(x._OrtGetOutputCount=x.asm.ha).apply(null,arguments)}; +x._OrtGetInputName=function(){return(x._OrtGetInputName=x.asm.ia).apply(null,arguments)};x._OrtGetOutputName=function(){return(x._OrtGetOutputName=x.asm.ja).apply(null,arguments)};x._OrtFree=function(){return(x._OrtFree=x.asm.ka).apply(null,arguments)};x._OrtCreateTensor=function(){return(x._OrtCreateTensor=x.asm.la).apply(null,arguments)};x._OrtGetTensorData=function(){return(x._OrtGetTensorData=x.asm.ma).apply(null,arguments)}; +x._OrtReleaseTensor=function(){return(x._OrtReleaseTensor=x.asm.na).apply(null,arguments)};x._OrtCreateRunOptions=function(){return(x._OrtCreateRunOptions=x.asm.oa).apply(null,arguments)};x._OrtAddRunConfigEntry=function(){return(x._OrtAddRunConfigEntry=x.asm.pa).apply(null,arguments)};x._OrtReleaseRunOptions=function(){return(x._OrtReleaseRunOptions=x.asm.qa).apply(null,arguments)};x._OrtRun=function(){return(x._OrtRun=x.asm.ra).apply(null,arguments)}; +x._OrtEndProfiling=function(){return(x._OrtEndProfiling=x.asm.sa).apply(null,arguments)};var T=x._pthread_self=function(){return(T=x._pthread_self=x.asm.ta).apply(null,arguments)},qb=x._malloc=function(){return(qb=x._malloc=x.asm.ua).apply(null,arguments)};x._free=function(){return(x._free=x.asm.va).apply(null,arguments)};x.__emscripten_tls_init=function(){return(x.__emscripten_tls_init=x.asm.wa).apply(null,arguments)}; +var Qb=x.__emscripten_thread_init=function(){return(Qb=x.__emscripten_thread_init=x.asm.xa).apply(null,arguments)};x.__emscripten_thread_crashed=function(){return(x.__emscripten_thread_crashed=x.asm.ya).apply(null,arguments)}; +var vb=x._emscripten_run_in_main_runtime_thread_js=function(){return(vb=x._emscripten_run_in_main_runtime_thread_js=x.asm.Aa).apply(null,arguments)},lb=x.__emscripten_proxy_execute_task_queue=function(){return(lb=x.__emscripten_proxy_execute_task_queue=x.asm.Ba).apply(null,arguments)},Oa=x.__emscripten_thread_free_data=function(){return(Oa=x.__emscripten_thread_free_data=x.asm.Ca).apply(null,arguments)},Ta=x.__emscripten_thread_exit=function(){return(Ta=x.__emscripten_thread_exit=x.asm.Da).apply(null, +arguments)},Sa=x._emscripten_stack_set_limits=function(){return(Sa=x._emscripten_stack_set_limits=x.asm.Ea).apply(null,arguments)},Ra=x.stackSave=function(){return(Ra=x.stackSave=x.asm.Fa).apply(null,arguments)},V=x.stackRestore=function(){return(V=x.stackRestore=x.asm.Ga).apply(null,arguments)},ub=x.stackAlloc=function(){return(ub=x.stackAlloc=x.asm.Ha).apply(null,arguments)};x.___cxa_is_pointer_type=function(){return(x.___cxa_is_pointer_type=x.asm.Ia).apply(null,arguments)};x.UTF8ToString=va; +x.stringToUTF8=function(a,b,d){return wa(a,q(),b,d)};x.lengthBytesUTF8=xa;x.keepRuntimeAlive=function(){return noExitRuntime};x.wasmMemory=k;x.stackSave=Ra;x.stackRestore=V;x.stackAlloc=ub;x.ExitStatus=K;x.PThread=R;var Sb;P=function Tb(){Sb||Ub();Sb||(P=Tb)}; +function Ub(){function a(){if(!Sb&&(Sb=!0,x.calledRun=!0,!sa)){C||U(Ba);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();Ca.unshift(b)}U(Ca)}}}if(!(0 { + +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 || {}; + + +null;var b;b||(b=typeof ortWasm !== 'undefined' ? ortWasm : {});var aa,k;b.ready=new Promise(function(a,c){aa=a;k=c});var ba=Object.assign({},b),p="./this.program",t=(a,c)=>{throw c;},ca="object"==typeof window,u="function"==typeof importScripts,x="object"==typeof process&&"object"==typeof process.versions&&"string"==typeof process.versions.node,y="",z,A,C,fs,D,E; +if(x)y=u?(__webpack_require__(/*! path */ "?75c6").dirname)(y)+"/":__dirname+"/",E=()=>{D||(fs=__webpack_require__(/*! fs */ "?63c8"),D=__webpack_require__(/*! path */ "?75c6"))},z=function(a,c){E();a=D.normalize(a);return fs.readFileSync(a,c?void 0:"utf8")},C=a=>{a=z(a,!0);a.buffer||(a=new Uint8Array(a));return a},A=(a,c,e)=>{E();a=D.normalize(a);fs.readFile(a,function(f,g){f?e(f):c(g.buffer)})},1{if(noExitRuntime)throw process.exitCode=a,c;c instanceof F||G("exiting due to exception: "+c);process.exit(a)},b.inspect=function(){return"[Emscripten Module object]"};else if(ca||u)u?y=self.location.href:"undefined"!=typeof document&&document.currentScript&&(y=document.currentScript.src),_scriptDir&&(y=_scriptDir),0!==y.indexOf("blob:")?y=y.substr(0,y.replace(/[?#].*/,"").lastIndexOf("/")+1):y="",z=a=>{var c=new XMLHttpRequest;c.open("GET",a,!1);c.send(null);return c.responseText}, +u&&(C=a=>{var c=new XMLHttpRequest;c.open("GET",a,!1);c.responseType="arraybuffer";c.send(null);return new Uint8Array(c.response)}),A=(a,c,e)=>{var f=new XMLHttpRequest;f.open("GET",a,!0);f.responseType="arraybuffer";f.onload=()=>{200==f.status||0==f.status&&f.response?c(f.response):e()};f.onerror=e;f.send(null)};var da=b.print||console.log.bind(console),G=b.printErr||console.warn.bind(console);Object.assign(b,ba);ba=null;b.thisProgram&&(p=b.thisProgram);b.quit&&(t=b.quit);var H; +b.wasmBinary&&(H=b.wasmBinary);var noExitRuntime=b.noExitRuntime||!0;"object"!=typeof WebAssembly&&I("no native wasm support detected");var J,K=!1,ea="undefined"!=typeof TextDecoder?new TextDecoder("utf8"):void 0; +function fa(a,c,e){c>>>=0;var f=c+e;for(e=c;a[e]&&!(e>=f);)++e;if(16g?f+=String.fromCharCode(g):(g-=65536,f+=String.fromCharCode(55296|g>>10,56320|g&1023))}}else f+=String.fromCharCode(g)}return f}function L(a,c){return(a>>>=0)?fa(M,a,c):""} +function N(a,c,e,f){e>>>=0;if(!(0=l){var q=a.charCodeAt(++h);l=65536+((l&1023)<<10)|q&1023}if(127>=l){if(e>=f)break;c[e++>>>0]=l}else{if(2047>=l){if(e+1>=f)break;c[e++>>>0]=192|l>>6}else{if(65535>=l){if(e+2>=f)break;c[e++>>>0]=224|l>>12}else{if(e+3>=f)break;c[e++>>>0]=240|l>>18;c[e++>>>0]=128|l>>12&63}c[e++>>>0]=128|l>>6&63}c[e++>>>0]=128|l&63}}c[e>>>0]=0;return e-g} +function O(a){for(var c=0,e=0;e=f?c++:2047>=f?c+=2:55296<=f&&57343>=f?(c+=4,++e):c+=3}return c}var ha,P,M,Q,R;function ia(){var a=J.buffer;ha=a;b.HEAP8=P=new Int8Array(a);b.HEAP16=new Int16Array(a);b.HEAP32=Q=new Int32Array(a);b.HEAPU8=M=new Uint8Array(a);b.HEAPU16=new Uint16Array(a);b.HEAPU32=R=new Uint32Array(a);b.HEAPF32=new Float32Array(a);b.HEAPF64=new Float64Array(a)}var ja=[],ka=[],la=[];function ma(){var a=b.preRun.shift();ja.unshift(a)} +var S=0,T=null,U=null;function I(a){if(b.onAbort)b.onAbort(a);a="Aborted("+a+")";G(a);K=!0;a=new WebAssembly.RuntimeError(a+". Build with -sASSERTIONS for more info.");k(a);throw a;}function na(){return V.startsWith("data:application/octet-stream;base64,")}var V;V="ort-wasm.wasm";if(!na()){var oa=V;V=b.locateFile?b.locateFile(oa,y):y+oa}function pa(){var a=V;try{if(a==V&&H)return new Uint8Array(H);if(C)return C(a);throw"both async and sync fetching of the wasm failed";}catch(c){I(c)}} +function qa(){if(!H&&(ca||u)){if("function"==typeof fetch&&!V.startsWith("file://"))return fetch(V,{credentials:"same-origin"}).then(function(a){if(!a.ok)throw"failed to load wasm binary file at '"+V+"'";return a.arrayBuffer()}).catch(function(){return pa()});if(A)return new Promise(function(a,c){A(V,function(e){a(new Uint8Array(e))},c)})}return Promise.resolve().then(function(){return pa()})}function F(a){this.name="ExitStatus";this.message="Program terminated with exit("+a+")";this.status=a} +function W(a){for(;0>2>>>0]=c};this.Ba=function(c){R[this.sa+8>>2>>>0]=c};this.Ga=function(){Q[this.sa>>2>>>0]=0};this.Aa=function(){P[this.sa+12>>0>>>0]=0};this.Ha=function(){P[this.sa+13>>0>>>0]=0};this.ya=function(c,e){this.za();this.Ia(c);this.Ba(e);this.Ga();this.Aa();this.Ha()};this.za=function(){R[this.sa+16>>2>>>0]=0}}var sa=0;function ta(a){var c=O(a)+1,e=ua(c);e&&N(a,P,e,c);return e} +function va(a,c,e){function f(w){return(w=w.toTimeString().match(/\(([A-Za-z ]+)\)$/))?w[1]:"GMT"}var g=(new Date).getFullYear(),h=new Date(g,0,1),l=new Date(g,6,1);g=h.getTimezoneOffset();var q=l.getTimezoneOffset();Q[a>>2>>>0]=60*Math.max(g,q);Q[c>>2>>>0]=Number(g!=q);a=f(h);c=f(l);a=ta(a);c=ta(c);q>2>>>0]=a,R[e+4>>2>>>0]=c):(R[e>>2>>>0]=c,R[e+4>>2>>>0]=a)}function wa(a,c,e){wa.xa||(wa.xa=!0,va(a,c,e))}var Aa={}; +function Ba(){if(!Ca){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",_:p||"./this.program"},c;for(c in Aa)void 0===Aa[c]?delete a[c]:a[c]=Aa[c];var e=[];for(c in a)e.push(c+"="+a[c]);Ca=e}return Ca}var Ca,Da=[null,[],[]]; +function Ea(){if("object"==typeof crypto&&"function"==typeof crypto.getRandomValues){var a=new Uint8Array(1);return()=>{crypto.getRandomValues(a);return a[0]}}if(x)try{var c=__webpack_require__(/*! crypto */ "?892d");return()=>c.randomBytes(1)[0]}catch(e){}return()=>I("randomDevice")}function X(a,c){X.wa||(X.wa=Ea());for(var e=0;e>0>>>0]=X.wa();return 0}function Y(a){return 0===a%4&&(0!==a%100||0===a%400)}var Fa=[31,29,31,30,31,30,31,31,30,31,30,31],Ga=[31,28,31,30,31,30,31,31,30,31,30,31]; +function Ha(a){var c=Array(O(a)+1);N(a,c,0,c.length);return c} +function Ia(a,c,e,f){function g(d,m,n){for(d="number"==typeof d?d.toString():d||"";d.lengthxa?-1:0B-d.getDate())m-=B-d.getDate()+1,d.setDate(1),11>n?d.setMonth(n+1):(d.setMonth(0),d.setFullYear(d.getFullYear()+1));else{d.setDate(d.getDate()+m);break}}n=new Date(d.getFullYear()+1,0,4);m=q(new Date(d.getFullYear(), +0,4));n=q(n);return 0>=l(m,d)?0>=l(n,d)?d.getFullYear()+1:d.getFullYear():d.getFullYear()-1}var v=Q[f+40>>2>>>0];f={Ea:Q[f>>2>>>0],Da:Q[f+4>>2>>>0],ta:Q[f+8>>2>>>0],va:Q[f+12>>2>>>0],ua:Q[f+16>>2>>>0],ra:Q[f+20>>2>>>0],la:Q[f+24>>2>>>0],qa:Q[f+28>>2>>>0],Ja:Q[f+32>>2>>>0],Ca:Q[f+36>>2>>>0],Fa:v?L(v):""};e=L(e);v={"%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 r in v)e=e.replace(new RegExp(r,"g"),v[r]);var ya="Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),za="January February March April May June July August September October November December".split(" ");v={"%a":function(d){return ya[d.la].substring(0,3)},"%A":function(d){return ya[d.la]},"%b":function(d){return za[d.ua].substring(0, +3)},"%B":function(d){return za[d.ua]},"%C":function(d){return h((d.ra+1900)/100|0,2)},"%d":function(d){return h(d.va,2)},"%e":function(d){return g(d.va,2," ")},"%g":function(d){return w(d).toString().substring(2)},"%G":function(d){return w(d)},"%H":function(d){return h(d.ta,2)},"%I":function(d){d=d.ta;0==d?d=12:12d.ta?"AM":"PM"},"%S":function(d){return h(d.Ea,2)},"%t":function(){return"\t"},"%u":function(d){return d.la||7},"%U":function(d){return h(Math.floor((d.qa+7-d.la)/7),2)},"%V":function(d){var m=Math.floor((d.qa+7-(d.la+6)%7)/7);2>=(d.la+371-d.qa-2)%7&&m++;if(m)53==m&&(n=(d.la+371-d.qa)%7,4==n||3==n&&Y(d.ra)||(m=1));else{m=52;var n=(d.la+7-d.qa-1)%7;(4==n||5==n&&Y(d.ra%400-1))&&m++}return h(m,2)},"%w":function(d){return d.la},"%W":function(d){return h(Math.floor((d.qa+ +7-(d.la+6)%7)/7),2)},"%y":function(d){return(d.ra+1900).toString().substring(2)},"%Y":function(d){return d.ra+1900},"%z":function(d){d=d.Ca;var m=0<=d;d=Math.abs(d)/60;return(m?"+":"-")+String("0000"+(d/60*100+d%60)).slice(-4)},"%Z":function(d){return d.Fa},"%%":function(){return"%"}};e=e.replace(/%%/g,"\x00\x00");for(r in v)e.includes(r)&&(e=e.replace(new RegExp(r,"g"),v[r](f)));e=e.replace(/\0\0/g,"%");r=Ha(e);if(r.length>c)return 0;P.set(r,a>>>0);return r.length-1} +var Ja={a:function(a){return ua(a+24)+24},b:function(a,c,e){(new ra(a)).ya(c,e);sa++;throw a;},g:function(){return 0},I:function(){},w:function(){},y:function(){},K:function(){return 0},G:function(){},C:function(){},F:function(){},k:function(){},x:function(){},u:function(){},H:function(){},v:function(){},n:function(){},p:function(){I("To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking")},o:function(){I("To use dlopen, you need enable dynamic linking, see https://github.com/emscripten-core/emscripten/wiki/Linking")}, +l:function(){return Date.now()},L:function(){return!0},M:function(a,c){a=new Date(1E3*(R[a>>>2]+4294967296*Q[a+4>>>2]));Q[c>>2>>>0]=a.getUTCSeconds();Q[c+4>>2>>>0]=a.getUTCMinutes();Q[c+8>>2>>>0]=a.getUTCHours();Q[c+12>>2>>>0]=a.getUTCDate();Q[c+16>>2>>>0]=a.getUTCMonth();Q[c+20>>2>>>0]=a.getUTCFullYear()-1900;Q[c+24>>2>>>0]=a.getUTCDay();Q[c+28>>2>>>0]=(a.getTime()-Date.UTC(a.getUTCFullYear(),0,1,0,0,0,0))/864E5|0},N:function(a,c){a=new Date(1E3*(R[a>>>2]+4294967296*Q[a+4>>>2]));Q[c>>2>>>0]=a.getSeconds(); +Q[c+4>>2>>>0]=a.getMinutes();Q[c+8>>2>>>0]=a.getHours();Q[c+12>>2>>>0]=a.getDate();Q[c+16>>2>>>0]=a.getMonth();Q[c+20>>2>>>0]=a.getFullYear()-1900;Q[c+24>>2>>>0]=a.getDay();var e=new Date(a.getFullYear(),0,1);Q[c+28>>2>>>0]=(a.getTime()-e.getTime())/864E5|0;Q[c+36>>2>>>0]=-(60*a.getTimezoneOffset());var f=(new Date(a.getFullYear(),6,1)).getTimezoneOffset();e=e.getTimezoneOffset();Q[c+32>>2>>>0]=(f!=e&&a.getTimezoneOffset()==Math.min(e,f))|0},O:function(a){var c=new Date(Q[a+20>>2>>>0]+1900,Q[a+16>> +2>>>0],Q[a+12>>2>>>0],Q[a+8>>2>>>0],Q[a+4>>2>>>0],Q[a>>2>>>0],0),e=Q[a+32>>2>>>0],f=c.getTimezoneOffset(),g=new Date(c.getFullYear(),0,1),h=(new Date(c.getFullYear(),6,1)).getTimezoneOffset(),l=g.getTimezoneOffset(),q=Math.min(l,h);0>e?Q[a+32>>2>>>0]=Number(h!=l&&q==f):0>2>>>0]=c.getDay();Q[a+28>>2>>>0]=(c.getTime()-g.getTime())/864E5|0;Q[a>>2>>>0]=c.getSeconds();Q[a+4>>2>>>0]=c.getMinutes();Q[a+8>>2>>>0]=c.getHours();Q[a+ +12>>2>>>0]=c.getDate();Q[a+16>>2>>>0]=c.getMonth();return c.getTime()/1E3|0},z:function(){return-52},B:function(){},m:wa,d:function(){I("")},t:function(){return 4294901760},h:x?()=>{var a=process.hrtime();return 1E3*a[0]+a[1]/1E6}:()=>performance.now(),J:function(a,c,e){M.copyWithin(a>>>0,c>>>0,c+e>>>0)},f:function(a){var c=M.length;a>>>=0;if(4294901760=e;e*=2){var f=c*(1+.2/e);f=Math.min(f,a+100663296);var g=Math;f=Math.max(a,f);g=g.min.call(g,4294901760,f+(65536-f%65536)% +65536);a:{try{J.grow(g-ha.byteLength+65535>>>16);ia();var h=1;break a}catch(l){}h=void 0}if(h)return!0}return!1},D:function(a,c){var e=0;Ba().forEach(function(f,g){var h=c+e;g=R[a+4*g>>2>>>0]=h;for(h=0;h>0>>>0]=f.charCodeAt(h);P[g>>0>>>0]=0;e+=f.length+1});return 0},E:function(a,c){var e=Ba();R[a>>2>>>0]=e.length;var f=0;e.forEach(function(g){f+=g.length+1});R[c>>2>>>0]=f;return 0},r:function(a){if(!noExitRuntime){if(b.onExit)b.onExit(a);K=!0}t(a,new F(a))},e:function(){return 52}, +j:function(){return 52},q:function(){return 70},i:function(a,c,e,f){for(var g=0,h=0;h>2>>>0],q=R[c+4>>2>>>0];c+=8;for(var w=0;w>>0],r=Da[a];0===v||10===v?((1===a?da:G)(fa(r,0)),r.length=0):r.push(v)}g+=q}R[f>>2>>>0]=g;return 0},s:X,A:Ia,c:function(a,c,e,f){return Ia(a,c,e,f)}}; +(function(){function a(g){b.asm=g.exports;J=b.asm.P;ia();ka.unshift(b.asm.Q);S--;b.monitorRunDependencies&&b.monitorRunDependencies(S);0==S&&(null!==T&&(clearInterval(T),T=null),U&&(g=U,U=null,g()))}function c(g){a(g.instance)}function e(g){return qa().then(function(h){return WebAssembly.instantiate(h,f)}).then(function(h){return h}).then(g,function(h){G("failed to asynchronously prepare wasm: "+h);I(h)})}var f={a:Ja};S++;b.monitorRunDependencies&&b.monitorRunDependencies(S);if(b.instantiateWasm)try{return b.instantiateWasm(f, +a)}catch(g){return G("Module.instantiateWasm callback failed with error: "+g),!1}(function(){return H||"function"!=typeof WebAssembly.instantiateStreaming||na()||V.startsWith("file://")||x||"function"!=typeof fetch?e(c):fetch(V,{credentials:"same-origin"}).then(function(g){return WebAssembly.instantiateStreaming(g,f).then(c,function(h){G("wasm streaming compile failed: "+h);G("falling back to ArrayBuffer instantiation");return e(c)})})})().catch(k);return{}})(); +b.___wasm_call_ctors=function(){return(b.___wasm_call_ctors=b.asm.Q).apply(null,arguments)};b._OrtInit=function(){return(b._OrtInit=b.asm.R).apply(null,arguments)};b._OrtCreateSessionOptions=function(){return(b._OrtCreateSessionOptions=b.asm.S).apply(null,arguments)};b._OrtAppendExecutionProvider=function(){return(b._OrtAppendExecutionProvider=b.asm.T).apply(null,arguments)};b._OrtAddSessionConfigEntry=function(){return(b._OrtAddSessionConfigEntry=b.asm.U).apply(null,arguments)}; +b._OrtReleaseSessionOptions=function(){return(b._OrtReleaseSessionOptions=b.asm.V).apply(null,arguments)};b._OrtCreateSession=function(){return(b._OrtCreateSession=b.asm.W).apply(null,arguments)};b._OrtReleaseSession=function(){return(b._OrtReleaseSession=b.asm.X).apply(null,arguments)};b._OrtGetInputCount=function(){return(b._OrtGetInputCount=b.asm.Y).apply(null,arguments)};b._OrtGetOutputCount=function(){return(b._OrtGetOutputCount=b.asm.Z).apply(null,arguments)}; +b._OrtGetInputName=function(){return(b._OrtGetInputName=b.asm._).apply(null,arguments)};b._OrtGetOutputName=function(){return(b._OrtGetOutputName=b.asm.$).apply(null,arguments)};b._OrtFree=function(){return(b._OrtFree=b.asm.aa).apply(null,arguments)};b._OrtCreateTensor=function(){return(b._OrtCreateTensor=b.asm.ba).apply(null,arguments)};b._OrtGetTensorData=function(){return(b._OrtGetTensorData=b.asm.ca).apply(null,arguments)}; +b._OrtReleaseTensor=function(){return(b._OrtReleaseTensor=b.asm.da).apply(null,arguments)};b._OrtCreateRunOptions=function(){return(b._OrtCreateRunOptions=b.asm.ea).apply(null,arguments)};b._OrtAddRunConfigEntry=function(){return(b._OrtAddRunConfigEntry=b.asm.fa).apply(null,arguments)};b._OrtReleaseRunOptions=function(){return(b._OrtReleaseRunOptions=b.asm.ga).apply(null,arguments)};b._OrtRun=function(){return(b._OrtRun=b.asm.ha).apply(null,arguments)}; +b._OrtEndProfiling=function(){return(b._OrtEndProfiling=b.asm.ia).apply(null,arguments)};var ua=b._malloc=function(){return(ua=b._malloc=b.asm.ja).apply(null,arguments)};b._free=function(){return(b._free=b.asm.ka).apply(null,arguments)};var Ka=b.stackSave=function(){return(Ka=b.stackSave=b.asm.ma).apply(null,arguments)},La=b.stackRestore=function(){return(La=b.stackRestore=b.asm.na).apply(null,arguments)},Ma=b.stackAlloc=function(){return(Ma=b.stackAlloc=b.asm.oa).apply(null,arguments)}; +b.___cxa_is_pointer_type=function(){return(b.___cxa_is_pointer_type=b.asm.pa).apply(null,arguments)};b.UTF8ToString=L;b.stringToUTF8=function(a,c,e){return N(a,M,c,e)};b.lengthBytesUTF8=O;b.stackSave=Ka;b.stackRestore=La;b.stackAlloc=Ma;var Z;U=function Na(){Z||Oa();Z||(U=Na)}; +function Oa(){function a(){if(!Z&&(Z=!0,b.calledRun=!0,!K)){W(ka);aa(b);if(b.onRuntimeInitialized)b.onRuntimeInitialized();if(b.postRun)for("function"==typeof b.postRun&&(b.postRun=[b.postRun]);b.postRun.length;){var c=b.postRun.shift();la.unshift(c)}W(la)}}if(!(0 { + +"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.} + * @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) { + try { + var mod = eval("quire".replace(/^/,"re"))(moduleName); // eslint-disable-line no-eval + if (mod && (mod.length || Object.keys(mod).length)) + return mod; + } catch (e) {} // eslint-disable-line no-empty + 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.} Byte representation + */ +LongPrototype.toBytes = function toBytes(le) { + return le ? this.toBytesLE() : this.toBytesBE(); +}; + +/** + * Converts this Long to its little endian byte representation. + * @returns {!Array.} 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.} 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.} 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.} 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.} 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.|null} [floats] AttributeProto floats + * @property {Array.|null} [ints] AttributeProto ints + * @property {Array.|null} [strings] AttributeProto strings + * @property {Array.|null} [tensors] AttributeProto tensors + * @property {Array.|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.} floats + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.floats = $util.emptyArray; + + /** + * AttributeProto ints. + * @member {Array.} ints + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.ints = $util.emptyArray; + + /** + * AttributeProto strings. + * @member {Array.} strings + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.strings = $util.emptyArray; + + /** + * AttributeProto tensors. + * @member {Array.} tensors + * @memberof onnx.AttributeProto + * @instance + */ + AttributeProto.prototype.tensors = $util.emptyArray; + + /** + * AttributeProto graphs. + * @member {Array.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.|null} [input] NodeProto input + * @property {Array.|null} [output] NodeProto output + * @property {string|null} [name] NodeProto name + * @property {string|null} [opType] NodeProto opType + * @property {string|null} [domain] NodeProto domain + * @property {Array.|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.} input + * @memberof onnx.NodeProto + * @instance + */ + NodeProto.prototype.input = $util.emptyArray; + + /** + * NodeProto output. + * @member {Array.} 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.} 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.} 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.} 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.} 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.} 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.|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.|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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.|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.} 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.} 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.} 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.} 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.} 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.|null} [node] GraphProto node + * @property {string|null} [name] GraphProto name + * @property {Array.|null} [initializer] GraphProto initializer + * @property {string|null} [docString] GraphProto docString + * @property {Array.|null} [input] GraphProto input + * @property {Array.|null} [output] GraphProto output + * @property {Array.|null} [valueInfo] GraphProto valueInfo + * @property {Array.|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.} 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.} 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.} input + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.input = $util.emptyArray; + + /** + * GraphProto output. + * @member {Array.} output + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.output = $util.emptyArray; + + /** + * GraphProto valueInfo. + * @member {Array.} valueInfo + * @memberof onnx.GraphProto + * @instance + */ + GraphProto.prototype.valueInfo = $util.emptyArray; + + /** + * GraphProto quantizationAnnotation. + * @member {Array.} 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.} 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.} 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.} 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.} 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.|null} [dims] TensorProto dims + * @property {number|null} [dataType] TensorProto dataType + * @property {onnx.TensorProto.ISegment|null} [segment] TensorProto segment + * @property {Array.|null} [floatData] TensorProto floatData + * @property {Array.|null} [int32Data] TensorProto int32Data + * @property {Array.|null} [stringData] TensorProto stringData + * @property {Array.|null} [int64Data] TensorProto int64Data + * @property {string|null} [name] TensorProto name + * @property {string|null} [docString] TensorProto docString + * @property {Uint8Array|null} [rawData] TensorProto rawData + * @property {Array.|null} [externalData] TensorProto externalData + * @property {onnx.TensorProto.DataLocation|null} [dataLocation] TensorProto dataLocation + * @property {Array.|null} [doubleData] TensorProto doubleData + * @property {Array.|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.} 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.} floatData + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.floatData = $util.emptyArray; + + /** + * TensorProto int32Data. + * @member {Array.} int32Data + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.int32Data = $util.emptyArray; + + /** + * TensorProto stringData. + * @member {Array.} stringData + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.stringData = $util.emptyArray; + + /** + * TensorProto int64Data. + * @member {Array.} 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.} 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.} doubleData + * @memberof onnx.TensorProto + * @instance + */ + TensorProto.prototype.doubleData = $util.emptyArray; + + /** + * TensorProto uint64Data. + * @member {Array.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.|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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} 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.} + * @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<{}>>} 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 + * @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 + * @template TRes extends Message + * @type {function} + * @param {TReq|Properties} request Request message or plain object + * @param {rpc.ServiceMethodCallback} [callback] Node-style callback called with the error, if any, and the response message + * @returns {Promise>} 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} method Reflected or static method + * @param {Constructor} requestCtor Request constructor + * @param {Constructor} responseCtor Response constructor + * @param {TReq|Properties} request Request message or plain object + * @param {rpc.ServiceMethodCallback} callback Service callback + * @returns {undefined} + * @template TReq extends Message + * @template TRes extends Message + */ +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} + */ +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} + */ +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} + */ +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.} dst Destination object + * @param {Object.} src Source object + * @param {boolean} [ifNotSet=false] Merges only if the key is not already set + * @returns {Object.} 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} 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 + * @constructor + * @param {string} message Error message + * @param {Object.} [properties] Additional properties + * @example + * try { + * MyMessage.decode(someBuffer); // throws if required fields are missing + * } catch (e) { + * if (e instanceof ProtocolError && e.instance) + * Failed to run model("decoded so far: " + JSON.stringify(e.instance)); + * } + */ +util.ProtocolError = newError("ProtocolError"); + +/** + * So far decoded message instance. + * @name util.ProtocolError#instance + * @type {Message} + */ + +/** + * 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/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) */ + +/***/ }), + +/***/ "?892d": +/*!************************!*\ + !*** crypto (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.} + * @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.} + * @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|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,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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QU0sSUFBSSxHQUFHLE1BQU0sQ0FBQztJQUNwQixNQUFNLElBQUksR0FBRztVQUNMLElBQUk7OztTQUdMLElBQUk7OztHQUdWLENBQUM7SUFDRixPQUFPLEVBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsK0JBQVksQ0FBQyxVQUFVLEVBQUMsQ0FBQztBQUNyRCxDQUFDO0FBWEQsMEJBV0M7QUFDRCxTQUFnQixPQUFPO0lBQ3JCLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQztJQUNwQixNQUFNLElBQUksR0FBRztVQUNMLElBQUk7OztTQUdMLElBQUk7OztHQUdWLENBQUM7SUFDRixPQUFPLEVBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsK0JBQVksQ0FBQyxVQUFVLEVBQUMsQ0FBQztBQUNyRCxDQUFDO0FBWEQsMEJBV0M7QUFDRCxTQUFnQixPQUFPO0lBQ3JCLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQztJQUNwQixNQUFNLElBQUksR0FBRztVQUNMLElBQUk7OztTQUdMLElBQUk7OztHQUdWLENBQUM7SUFDRixPQUFPLEVBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsK0JBQVksQ0FBQyxVQUFVLEVBQUMsQ0FBQztBQUNyRCxDQUFDO0FBWEQsMEJBV0M7QUFDRCxTQUFnQixTQUFTO0lBQ3ZCLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQztJQUN0QixNQUFNLElBQUksR0FBRztVQUNMLElBQUk7OztTQUdMLElBQUk7OztHQUdWLENBQUM7SUFDRixPQUFPLEVBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsK0JBQVksQ0FBQyxVQUFVLEVBQUMsQ0FBQztBQUNyRCxDQUFDO0FBWEQsOEJBV0M7QUFDRCxTQUFnQixXQUFXO0lBQ3pCLE1BQU0sSUFBSSxHQUFHLFVBQVUsQ0FBQztJQUN4QixNQUFNLElBQUksR0FBRztVQUNMLElBQUk7OztTQUdMLElBQUk7Ozs7OztHQU1WLENBQUM7SUFDRixPQUFPLEVBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJ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QUFDLENBQUM7b0JBQ2hELE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2xFLENBQUM7Z0JBU0QsTUFBTSxDQUFDLEtBQWEsRUFBRSxnQkFBc0I7b0JBQzFDLElBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxFQUFHLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7b0JBQ2hELE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxHQUFHLEtBQUssR0FBRyxDQUFDLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUNsSCxDQUFDO2dCQUVEOzttQkFFRztnQkFDSCxZQUFZO29CQUNWLElBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxFQUFHLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7b0JBQ2hELE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2xFLENBQUM7Z0JBU0QsT0FBTyxDQUFDLEtBQWEsRUFBRSxnQkFBc0I7b0JBQzNDLElBQUksTUFBTSxHQUFHLElBQUksQ0FBQyxFQUFHLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7b0JBQ2hELE9BQU8sTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRyxDQUFDLFFBQVEs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QUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsWUFBWTtBQUN2QixXQUFXLFFBQVE7QUFDbkIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSyxLQUFLO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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QVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEIsYUFBYTtBQUNiO0FBQ0EsWUFBWSxZQUFZO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxRQUFRO0FB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Ozs7OztBQ3BGQTs7Ozs7Ozs7OztBQ0FBOzs7Ozs7Ozs7O0FDQUE7Ozs7Ozs7Ozs7QUNBQTs7Ozs7Ozs7OztBQ0FBOzs7Ozs7Ozs7O0FDQUE7Ozs7Ozs7Ozs7QUNBQTs7Ozs7Ozs7OztBQ0FBOzs7Ozs7Ozs7O0FDQUE7Ozs7Ozs7Ozs7QUNBQTs7Ozs7Ozs7OztBQ0FBOzs7Ozs7Ozs7O0FDQUE7Ozs7Ozs7Ozs7Ozs7OztBQ0FBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGFBQWE7QUFDYjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBOztBQUVBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUTtBQUNuQixhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVcsa0JBQWtCO0FBQzdCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFVBQVU7QUFDVjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0Esa0JBQWtCLGVBQWU7QUFDakM7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVyxrQkFBa0I7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxrQkFBa0I7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkI7QUFDQTtB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QWlCO1dBQ3hFO1dBQ0EsZ0RBQWdELGFBQWE7V0FDN0Q7Ozs7O1VFTkE7VUFDQTtVQUNBO1VBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9vcnQvd2VicGFjay91bml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uIiwid2VicGFjazovL29ydC8uLi9jb21tb24vZGlzdC9saWIvYmFja2VuZC1pbXBsLmpzIiwid2VicGFjazovL29ydC8uLi9jb21tb24vZGlzdC9saWIvYmFja2VuZC5qcyIsIndlYnBhY2s6Ly9vcnQvLi4vY29tbW9uL2Rpc3QvbGliL2Vudi1pbXBsLmpzIiwid2VicGFjazovL29ydC8uLi9jb21tb24vZGlzdC9saWIvZW52LmpzIiwid2VicGFjazovL29ydC8uLi9jb21tb24vZGlzdC9saWIvaW5kZXguanMiLCJ3ZWJwYWNrOi8vb3J0Ly4uL2NvbW1vbi9kaXN0L2xpYi9pbmZlcmVuY2Utc2Vzc2lvbi1pbXBsLmpzIiwid2VicGFjazovL29ydC8uLi9jb21tb24vZGlzdC9saWIvaW5mZXJlbmNlLXNlc3Npb24uanMiLCJ3ZWJwYWNrOi8vb3J0Ly4uL2NvbW1vbi9kaXN0L2xpYi9vbm54LXZhbHVlLmpzIiwid2VicGFjazovL29ydC8uLi9jb21tb24vZGlzdC9saWIvdGVuc29yLWltcGwuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4uL2NvbW1vbi9kaXN0L2xpYi90ZW5zb3IuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL2JhY2tlbmQtb25ueGpzLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9iYWNrZW5kLXdhc20udHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL2luZGV4LnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5LnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYXR0cmlidXRlLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL2JhY2tlbmQtd2ViZ2wudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9nbHNsLWNvb3JkaW5hdGUtbGliLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvZ2xzbC1kZWZpbml0aW9ucy50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL2dsc2wtZW5jb2RpbmctbGliLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvZ2xzbC1mcmFnY29sb3ItbGliLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvZ2xzbC1mdW5jdGlvbi1pbmxpbmVyLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvZ2xzbC1wcmVwcm9jZXNzb3IudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9nbHNsLXJlZ2lzdGVyZWQtbGlicy50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL2dsc2wtc2hhcGUtdXRpbHMtbGliLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvZ2xzbC1zb3VyY2UudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9nbHNsLXZlYy1saWIudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9pbmZlcmVuY2UtaGFuZGxlci50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wLXJlc29sdmUtcnVsZXMudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvYmF0Y2gtbm9ybWFsaXphdGlvbi50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9iaW5hcnktb3AudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvY2FzdC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9jb25jYXQtcGFja2VkLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL2NvbmNhdC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9jb252LWdyb3VwZWQudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvY29udi1wYWNrLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL2NvbnYtdHJhbnNwb3NlLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL2NvbnYudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvZGVwdGgtdG8tc3BhY2UudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvZG90LXByb2R1Y3QudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvZmxhdHRlbi50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9mdXNlLXV0aWxzLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL2dhdGhlci50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9nZW1tLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL2ltMmNvbC1wYWNrLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL2ltMmNvbC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9pbWFnZS1zY2FsZXIudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvaW5zdGFuY2Utbm9ybWFsaXphdGlvbi50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9scm4udHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvbWF0bXVsLXBhY2sudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvbWF0bXVsLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3BhY2sudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvcGFja2luZy11dGlscy50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9wYWQudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvcG9vbC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9yZWR1Y2UudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvcmVzaGFwZS1wYWNrZWQudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvcmVzaGFwZS50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9yZXNpemUtcGFja2VkLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3NoYXBlLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3NsaWNlLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3NvZnRtYXgudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvc3BsaXQudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvc3F1ZWV6ZS50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy9zdW0udHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvdGlsZS50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy90cmFuc3Bvc2UudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvdWludDgtZW5jb2RlLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3VuYXJ5LW9wLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvb3BzL3VucGFjay50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL29wcy91bnNxdWVlemUudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9vcHMvdXBzYW1wbGUudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9wcm9ncmFtLW1hbmFnZXIudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC9zZXNzaW9uLWhhbmRsZXIudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC90ZXh0dXJlLWRhdGEtZW5jb2Rlci50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL3RleHR1cmUtbGF5b3V0LXN0cmF0ZWd5LnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvdGV4dHVyZS1sYXlvdXQudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC90ZXh0dXJlLW1hbmFnZXIudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9iYWNrZW5kcy93ZWJnbC90eXBlcy50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2JhY2tlbmRzL3dlYmdsL3V0aWxzLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvd2ViZ2wtY29udGV4dC1mYWN0b3J5LnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvYmFja2VuZHMvd2ViZ2wvd2ViZ2wtY29udGV4dC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL2V4ZWN1dGlvbi1wbGFuLnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvZ3JhcGgudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9pbnN0cnVtZW50LnRzIiwid2VicGFjazovL29ydC8uL2xpYi9vbm54anMvbW9kZWwudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9vcGVyYXRvcnMudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy9vcHNldC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL29ydC1zY2hlbWEvb3J0LWdlbmVyYXRlZC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL3Nlc3Npb24taGFuZGxlci50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvb25ueGpzL3Nlc3Npb24udHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy90ZW5zb3IudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL29ubnhqcy91dGlsLnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL2pzZXAvYmFja2VuZC13ZWJncHUudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL3dhc20vanNlcC9pbml0LnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL2pzZXAvbG9nLnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL2pzZXAvdXRpbC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXkudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL3dhc20vanNlcC93ZWJncHUvZ3B1LWRhdGEtbWFuYWdlci50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcC1yZXNvbHZlLXJ1bGVzLnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy8zcmQtcGFydHkvYWN0aXZhdGlvbl91dGlsLnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy8zcmQtcGFydHkvY29udjJkX21tX3dlYmdwdS50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvM3JkLXBhcnR5L2NvbnZfdXRpbC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvM3JkLXBhcnR5L21hdG11bF9wYWNrZWRfd2ViZ3B1LnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9iaW5hcnktb3AudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2NvbW1vbi50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvY29udi1ncm91cGVkLnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9jb252LnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy9jb252MmQtbW0udHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2Z1c2UtdXRpbHMudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL2dlbW0udHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL3dhc20vanNlcC93ZWJncHUvb3BzL21hdG11bC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvcG9vbC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9vcHMvdHJhbnNwb3NlLnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL2pzZXAvd2ViZ3B1L29wcy91bmFyeS1vcC50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9qc2VwL3dlYmdwdS9wcm9ncmFtLW1hbmFnZXIudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL3dhc20vanNlcC93ZWJncHUvdHlwZXMudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL3dhc20vb3B0aW9ucy11dGlscy50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9wcm94eS13cmFwcGVyLnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL3J1bi1vcHRpb25zLnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL3Nlc3Npb24taGFuZGxlci50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9zZXNzaW9uLW9wdGlvbnMudHMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbGliL3dhc20vc3RyaW5nLXV0aWxzLnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL3dhc20tY29tbW9uLnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL3dhc20tY29yZS1pbXBsLnRzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL3dhc20tZmFjdG9yeS50cyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9wcm94eS13b3JrZXIvbWFpbi50cyIsIndlYnBhY2s6Ly9vcnQvLi4vbm9kZV9tb2R1bGVzL3dvcmtlci1sb2FkZXIvZGlzdC9ydW50aW1lL2lubGluZS5qcyIsIndlYnBhY2s6Ly9vcnQvLi9saWIvd2FzbS9iaW5kaW5nL29ydC13YXNtLXRocmVhZGVkLmpzIiwid2VicGFjazovL29ydC8uL2xpYi93YXNtL2JpbmRpbmcvb3J0LXdhc20uanMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbm9kZV9tb2R1bGVzL0Bwcm90b2J1ZmpzL2FzcHJvbWlzZS9pbmRleC5qcyIsIndlYnBhY2s6Ly9vcnQvLi9ub2RlX21vZHVsZXMvQHByb3RvYnVmanMvYmFzZTY0L2luZGV4LmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9AcHJvdG9idWZqcy9ldmVudGVtaXR0ZXIvaW5kZXguanMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbm9kZV9tb2R1bGVzL0Bwcm90b2J1ZmpzL2Zsb2F0L2luZGV4LmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9AcHJvdG9idWZqcy9pbnF1aXJlL2luZGV4LmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9AcHJvdG9idWZqcy9wb29sL2luZGV4LmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9AcHJvdG9idWZqcy91dGY4L2luZGV4LmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9ndWlkLXR5cGVzY3JpcHQvZGlzdC9ndWlkLmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9sb25nL3NyYy9sb25nLmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9vbm54LXByb3RvL2Rpc3Qvb25ueC5qcyIsIndlYnBhY2s6Ly9vcnQvLi9ub2RlX21vZHVsZXMvcHJvdG9idWZqcy9taW5pbWFsLmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9wcm90b2J1ZmpzL3NyYy9pbmRleC1taW5pbWFsLmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9wcm90b2J1ZmpzL3NyYy9yZWFkZXIuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbm9kZV9tb2R1bGVzL3Byb3RvYnVmanMvc3JjL3JlYWRlcl9idWZmZXIuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbm9kZV9tb2R1bGVzL3Byb3RvYnVmanMvc3JjL3Jvb3RzLmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9wcm90b2J1ZmpzL3NyYy9ycGMuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbm9kZV9tb2R1bGVzL3Byb3RvYnVmanMvc3JjL3JwYy9zZXJ2aWNlLmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9wcm90b2J1ZmpzL3NyYy91dGlsL2xvbmdiaXRzLmpzIiwid2VicGFjazovL29ydC8uL25vZGVfbW9kdWxlcy9wcm90b2J1ZmpzL3NyYy91dGlsL21pbmltYWwuanMiLCJ3ZWJwYWNrOi8vb3J0Ly4vbm9kZV9tb2R1bGVzL3Byb3RvYnVmanMvc3JjL3dyaXRlci5qcyIsIndlYnBhY2s6Ly9vcnQvLi9ub2RlX21vZHVsZXMvcHJvdG9idWZqcy9zcmMvd3JpdGVyX2J1ZmZlci5qcyIsIndlYnBhY2s6Ly9vcnQvaWdub3JlZHxEOlxcYVxcX3dvcmtcXDFcXHNcXGpzXFx3ZWJcXGxpYlxcb25ueGpzfGZzIiwid2VicGFjazovL29ydC9pZ25vcmVkfEQ6XFxhXFxfd29ya1xcMVxcc1xcanNcXHdlYlxcbGliXFxvbm54anN8dXRpbCIsIndlYnBhY2s6Ly9vcnQvaWdub3JlZHxEOlxcYVxcX3dvcmtcXDFcXHNcXGpzXFx3ZWJcXGxpYlxcd2FzbVxcYmluZGluZ3xjcnlwdG8iLCJ3ZWJwYWNrOi8vb3J0L2lnbm9yZWR8RDpcXGFcXF93b3JrXFwxXFxzXFxqc1xcd2ViXFxsaWJcXHdhc21cXGJpbmRpbmd8ZnMiLCJ3ZWJwYWNrOi8vb3J0L2lnbm9yZWR8RDpcXGFcXF93b3JrXFwxXFxzXFxqc1xcd2ViXFxsaWJcXHdhc21cXGJpbmRpbmd8b3MiLCJ3ZWJwYWNrOi8vb3J0L2lnbm9yZWR8RDpcXGFcXF93b3JrXFwxXFxzXFxqc1xcd2ViXFxsaWJcXHdhc21cXGJpbmRpbmd8cGF0aCIsIndlYnBhY2s6Ly9vcnQvaWdub3JlZHxEOlxcYVxcX3dvcmtcXDFcXHNcXGpzXFx3ZWJcXGxpYlxcd2FzbVxcYmluZGluZ3xwZXJmX2hvb2tzIiwid2VicGFjazovL29ydC9pZ25vcmVkfEQ6XFxhXFxfd29ya1xcMVxcc1xcanNcXHdlYlxcbGliXFx3YXNtXFxiaW5kaW5nfHdvcmtlcl90aHJlYWRzIiwid2VicGFjazovL29ydC9pZ25vcmVkfEQ6XFxhXFxfd29ya1xcMVxcc1xcanNcXHdlYlxcbGliXFx3YXNtfGZzIiwid2VicGFjazovL29ydC9pZ25vcmVkfEQ6XFxhXFxfd29ya1xcMVxcc1xcanNcXHdlYlxcbGliXFx3YXNtfHBhdGgiLCJ3ZWJwYWNrOi8vb3J0L2lnbm9yZWR8RDpcXGFcXF93b3JrXFwxXFxzXFxqc1xcd2ViXFxsaWJcXHdhc218dXRpbCIsIndlYnBhY2s6Ly9vcnQvaWdub3JlZHxEOlxcYVxcX3dvcmtcXDFcXHNcXGpzXFx3ZWJcXGxpYnxvcyIsIndlYnBhY2s6Ly9vcnQvLi9ub2RlX21vZHVsZXMvZmxhdGJ1ZmZlcnMvanMvZmxhdGJ1ZmZlcnMubWpzIiwid2VicGFjazovL29ydC93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly9vcnQvd2VicGFjay9ydW50aW1lL2NvbXBhdCBnZXQgZGVmYXVsdCBleHBvcnQiLCJ3ZWJwYWNrOi8vb3J0L3dlYnBhY2svcnVudGltZS9kZWZpbmUgcHJvcGVydHkgZ2V0dGVycyIsIndlYnBhY2s6Ly9vcnQvd2VicGFjay9ydW50aW1lL2dsb2JhbCIsIndlYnBhY2s6Ly9vcnQvd2VicGFjay9ydW50aW1lL2hhc093blByb3BlcnR5IHNob3J0aGFuZCIsIndlYnBhY2s6Ly9vcnQvd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly9vcnQvd2VicGFjay9iZWZvcmUtc3RhcnR1cCIsIndlYnBhY2s6Ly9vcnQvd2VicGFjay9zdGFydHVwIiwid2VicGFjazovL29ydC93ZWJwYWNrL2FmdGVyLXN0YXJ0dXAiXSwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIHdlYnBhY2tVbml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uKHJvb3QsIGZhY3RvcnkpIHtcblx0aWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnKVxuXHRcdG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpO1xuXHRlbHNlIGlmKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZClcblx0XHRkZWZpbmUoW10sIGZhY3RvcnkpO1xuXHRlbHNlIGlmKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0Jylcblx0XHRleHBvcnRzW1wib3J0XCJdID0gZmFjdG9yeSgpO1xuXHRlbHNlXG5cdFx0cm9vdFtcIm9ydFwiXSA9IGZhY3RvcnkoKTtcbn0pKHNlbGYsICgpID0+IHtcbnJldHVybiAiLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cbmNvbnN0IGJhY2tlbmRzID0ge307XG5jb25zdCBiYWNrZW5kc1NvcnRlZEJ5UHJpb3JpdHkgPSBbXTtcbi8qKlxuICogUmVnaXN0ZXIgYSBiYWNrZW5kLlxuICpcbiAqIEBwYXJhbSBuYW1lIC0gdGhlIG5hbWUgYXMgYSBrZXkgdG8gbG9va3VwIGFzIGFuIGV4ZWN1dGlvbiBwcm92aWRlci5cbiAqIEBwYXJhbSBiYWNrZW5kIC0gdGhlIGJhY2tlbmQgb2JqZWN0LlxuICogQHBhcmFtIHByaW9yaXR5IC0gYW4gaW50ZWdlciBpbmRpY2F0aW5nIHRoZSBwcmlvcml0eSBvZiB0aGUgYmFja2VuZC4gSGlnaGVyIG51bWJlciBtZWFucyBoaWdoZXIgcHJpb3JpdHkuIGlmIHByaW9yaXR5XG4gKiA8IDAsIGl0IHdpbGwgYmUgY29uc2lkZXJlZCBhcyBhICdiZXRhJyB2ZXJzaW9uIGFuZCB3aWxsIG5vdCBiZSB1c2VkIGFzIGEgZmFsbGJhY2sgYmFja2VuZCBieSBkZWZhdWx0LlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgY29uc3QgcmVnaXN0ZXJCYWNrZW5kID0gKG5hbWUsIGJhY2tlbmQsIHByaW9yaXR5KSA9PiB7XG4gICAgaWYgKGJhY2tlbmQgJiYgdHlwZW9mIGJhY2tlbmQuaW5pdCA9PT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgYmFja2VuZC5jcmVhdGVTZXNzaW9uSGFuZGxlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBjb25zdCBjdXJyZW50QmFja2VuZCA9IGJhY2tlbmRzW25hbWVdO1xuICAgICAgICBpZiAoY3VycmVudEJhY2tlbmQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgYmFja2VuZHNbbmFtZV0gPSB7IGJhY2tlbmQsIHByaW9yaXR5IH07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY3VycmVudEJhY2tlbmQucHJpb3JpdHkgPiBwcmlvcml0eSkge1xuICAgICAgICAgICAgLy8gc2FtZSBuYW1lIGlzIGFscmVhZHkgcmVnaXN0ZXJlZCB3aXRoIGEgaGlnaGVyIHByaW9yaXR5LiBza2lwIHJlZ2lzdGVyYXRpb24uXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY3VycmVudEJhY2tlbmQucHJpb3JpdHkgPT09IHByaW9yaXR5KSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudEJhY2tlbmQuYmFja2VuZCAhPT0gYmFja2VuZCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgY2Fubm90IHJlZ2lzdGVyIGJhY2tlbmQgXCIke25hbWV9XCIgdXNpbmcgcHJpb3JpdHkgJHtwcmlvcml0eX1gKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAocHJpb3JpdHkgPj0gMCkge1xuICAgICAgICAgICAgY29uc3QgaSA9IGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eS5pbmRleE9mKG5hbWUpO1xuICAgICAgICAgICAgaWYgKGkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgYmFja2VuZHNTb3J0ZWRCeVByaW9yaXR5LnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYmFja2VuZHNTb3J0ZWRCeVByaW9yaXR5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGJhY2tlbmRzW2JhY2tlbmRzU29ydGVkQnlQcmlvcml0eVtpXV0ucHJpb3JpdHkgPD0gcHJpb3JpdHkpIHtcbiAgICAgICAgICAgICAgICAgICAgYmFja2VuZHNTb3J0ZWRCeVByaW9yaXR5LnNwbGljZShpLCAwLCBuYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eS5wdXNoKG5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbm90IGEgdmFsaWQgYmFja2VuZCcpO1xufTtcbi8qKlxuICogUmVzb2x2ZSBiYWNrZW5kIGJ5IHNwZWNpZmllZCBoaW50cy5cbiAqXG4gKiBAcGFyYW0gYmFja2VuZEhpbnRzIC0gYSBsaXN0IG9mIGV4ZWN1dGlvbiBwcm92aWRlciBuYW1lcyB0byBsb29rdXAuIElmIG9taXR0ZWQgdXNlIHJlZ2lzdGVyZWQgYmFja2VuZHMgYXMgbGlzdC5cbiAqIEByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIHRoZSBiYWNrZW5kLlxuICpcbiAqIEBpbnRlcm5hbFxuICovXG5leHBvcnQgY29uc3QgcmVzb2x2ZUJhY2tlbmQgPSBhc3luYyAoYmFja2VuZEhpbnRzKSA9PiB7XG4gICAgY29uc3QgYmFja2VuZE5hbWVzID0gYmFja2VuZEhpbnRzLmxlbmd0aCA9PT0gMCA/IGJhY2tlbmRzU29ydGVkQnlQcmlvcml0eSA6IGJhY2tlbmRIaW50cztcbiAgICBjb25zdCBlcnJvcnMgPSBbXTtcbiAgICBmb3IgKGNvbnN0IGJhY2tlbmROYW1lIG9mIGJhY2tlbmROYW1lcykge1xuICAgICAgICBjb25zdCBiYWNrZW5kSW5mbyA9IGJhY2tlbmRzW2JhY2tlbmROYW1lXTtcbiAgICAgICAgaWYgKGJhY2tlbmRJbmZvKSB7XG4gICAgICAgICAgICBpZiAoYmFja2VuZEluZm8uaW5pdGlhbGl6ZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYmFja2VuZEluZm8uYmFja2VuZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGJhY2tlbmRJbmZvLmFib3J0ZWQpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTsgLy8gY3VycmVudCBiYWNrZW5kIGlzIHVuYXZhaWxhYmxlOyB0cnkgbmV4dFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgaXNJbml0aWFsaXppbmcgPSAhIWJhY2tlbmRJbmZvLmluaXRQcm9taXNlO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBpZiAoIWlzSW5pdGlhbGl6aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGJhY2tlbmRJbmZvLmluaXRQcm9taXNlID0gYmFja2VuZEluZm8uYmFja2VuZC5pbml0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGF3YWl0IGJhY2tlbmRJbmZvLmluaXRQcm9taXNlO1xuICAgICAgICAgICAgICAgIGJhY2tlbmRJbmZvLmluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZXR1cm4gYmFja2VuZEluZm8uYmFja2VuZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpc0luaXRpYWxpemluZykge1xuICAgICAgICAgICAgICAgICAgICBlcnJvcnMucHVzaCh7IG5hbWU6IGJhY2tlbmROYW1lLCBlcnI6IGUgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJhY2tlbmRJbmZvLmFib3J0ZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZmluYWxseSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIGJhY2tlbmRJbmZvLmluaXRQcm9taXNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgbm8gYXZhaWxhYmxlIGJhY2tlbmQgZm91bmQuIEVSUjogJHtlcnJvcnMubWFwKGUgPT4gYFske2UubmFtZX1dICR7ZS5lcnJ9YCkuam9pbignLCAnKX1gKTtcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1iYWNrZW5kLWltcGwuanMubWFwIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5leHBvcnQgeyByZWdpc3RlckJhY2tlbmQgfSBmcm9tICcuL2JhY2tlbmQtaW1wbCc7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1iYWNrZW5kLmpzLm1hcCIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuZXhwb3J0IGNsYXNzIEVudkltcGwge1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLndhc20gPSB7fTtcbiAgICAgICAgdGhpcy53ZWJnbCA9IHt9O1xuICAgICAgICB0aGlzLndlYmdwdSA9IHt9O1xuICAgICAgICB0aGlzLmxvZ0xldmVsSW50ZXJuYWwgPSAnd2FybmluZyc7XG4gICAgfVxuICAgIC8vIFRPRE8gc3RhbmRhZGl6ZSB0aGUgZ2V0dGVyIGFuZCBzZXR0ZXIgY29udmVudGlvbiBpbiBlbnYgZm9yIG90aGVyIGZpZWxkcy5cbiAgICBzZXQgbG9nTGV2ZWwodmFsdWUpIHtcbiAgICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJyB8fCBbJ3ZlcmJvc2UnLCAnaW5mbycsICd3YXJuaW5nJywgJ2Vycm9yJywgJ2ZhdGFsJ10uaW5kZXhPZih2YWx1ZSkgPT09IC0xKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIGxvZ2dpbmcgbGV2ZWw6ICR7dmFsdWV9YCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sb2dMZXZlbEludGVybmFsID0gdmFsdWU7XG4gICAgfVxuICAgIGdldCBsb2dMZXZlbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9nTGV2ZWxJbnRlcm5hbDtcbiAgICB9XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1lbnYtaW1wbC5qcy5tYXAiLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cbmltcG9ydCB7IEVudkltcGwgfSBmcm9tICcuL2Vudi1pbXBsJztcbi8qKlxuICogUmVwcmVzZW50IGEgc2V0IG9mIGZsYWdzIGFzIGEgZ2xvYmFsIHNpbmdsZXRvbi5cbiAqL1xuZXhwb3J0IGNvbnN0IGVudiA9IG5ldyBFbnZJbXBsKCk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1lbnYuanMubWFwIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG4vKipcbiAqICMgT05OWCBSdW50aW1lIEphdmFTY3JpcHQgQVBJXG4gKlxuICogT05OWCBSdW50aW1lIEphdmFTY3JpcHQgQVBJIGlzIGEgdW5pZmllZCBBUEkgZm9yIGFsbCBKYXZhU2NyaXB0IHVzYWdlcywgaW5jbHVkaW5nIHRoZSBmb2xsb3dpbmcgTlBNIHBhY2thZ2VzOlxuICpcbiAqIC0gW29ubnhydW50aW1lLW5vZGVdKGh0dHBzOi8vd3d3Lm5wbWpzLmNvbS9wYWNrYWdlL29ubnhydW50aW1lLW5vZGUpXG4gKiAtIFtvbm54cnVudGltZS13ZWJdKGh0dHBzOi8vd3d3Lm5wbWpzLmNvbS9wYWNrYWdlL29ubnhydW50aW1lLXdlYilcbiAqIC0gW29ubnhydW50aW1lLXJlYWN0LW5hdGl2ZV0oaHR0cHM6Ly93d3cubnBtanMuY29tL3BhY2thZ2Uvb25ueHJ1bnRpbWUtcmVhY3QtbmF0aXZlKVxuICpcbiAqIFNlZSBhbHNvOlxuICogLSBbR2V0IFN0YXJ0ZWRdKGh0dHBzOi8vb25ueHJ1bnRpbWUuYWkvZG9jcy9nZXQtc3RhcnRlZC93aXRoLWphdmFzY3JpcHQuaHRtbClcbiAqIC0gW0luZmVyZW5jZSBleGFtcGxlc10oaHR0cHM6Ly9naXRodWIuY29tL21pY3Jvc29mdC9vbm54cnVudGltZS1pbmZlcmVuY2UtZXhhbXBsZXMvdHJlZS9tYWluL2pzKVxuICpcbiAqIEBwYWNrYWdlRG9jdW1lbnRhdGlvblxuICovXG5leHBvcnQgKiBmcm9tICcuL2JhY2tlbmQnO1xuZXhwb3J0ICogZnJvbSAnLi9lbnYnO1xuZXhwb3J0ICogZnJvbSAnLi9pbmZlcmVuY2Utc2Vzc2lvbic7XG5leHBvcnQgKiBmcm9tICcuL3RlbnNvcic7XG5leHBvcnQgKiBmcm9tICcuL29ubngtdmFsdWUnO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5kZXguanMubWFwIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5pbXBvcnQgeyByZXNvbHZlQmFja2VuZCB9IGZyb20gJy4vYmFja2VuZC1pbXBsJztcbmltcG9ydCB7IFRlbnNvciB9IGZyb20gJy4vdGVuc29yJztcbmV4cG9ydCBjbGFzcyBJbmZlcmVuY2VTZXNzaW9uIHtcbiAgICBjb25zdHJ1Y3RvcihoYW5kbGVyKSB7XG4gICAgICAgIHRoaXMuaGFuZGxlciA9IGhhbmRsZXI7XG4gICAgfVxuICAgIGFzeW5jIHJ1bihmZWVkcywgYXJnMSwgYXJnMikge1xuICAgICAgICBjb25zdCBmZXRjaGVzID0ge307XG4gICAgICAgIGxldCBvcHRpb25zID0ge307XG4gICAgICAgIC8vIGNoZWNrIGlucHV0c1xuICAgICAgICBpZiAodHlwZW9mIGZlZWRzICE9PSAnb2JqZWN0JyB8fCBmZWVkcyA9PT0gbnVsbCB8fCBmZWVkcyBpbnN0YW5jZW9mIFRlbnNvciB8fCBBcnJheS5pc0FycmF5KGZlZWRzKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXFwnZmVlZHNcXCcgbXVzdCBiZSBhbiBvYmplY3QgdGhhdCB1c2UgaW5wdXQgbmFtZXMgYXMga2V5cyBhbmQgT25ueFZhbHVlIGFzIGNvcnJlc3BvbmRpbmcgdmFsdWVzLicpO1xuICAgICAgICB9XG4gICAgICAgIGxldCBpc0ZldGNoZXNFbXB0eSA9IHRydWU7XG4gICAgICAgIC8vIGRldGVybWluZSB3aGljaCBvdmVycmlkZSBpcyBiZWluZyB1c2VkXG4gICAgICAgIGlmICh0eXBlb2YgYXJnMSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGlmIChhcmcxID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5leHBlY3RlZCBhcmd1bWVudFsxXTogY2Fubm90IGJlIG51bGwuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYXJnMSBpbnN0YW5jZW9mIFRlbnNvcikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1xcJ2ZldGNoZXNcXCcgY2Fubm90IGJlIGEgVGVuc29yJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShhcmcxKSkge1xuICAgICAgICAgICAgICAgIGlmIChhcmcxLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcXCdmZXRjaGVzXFwnIGNhbm5vdCBiZSBhbiBlbXB0eSBhcnJheS4nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaXNGZXRjaGVzRW1wdHkgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAvLyBvdXRwdXQgbmFtZXNcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgYXJnMSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcXCdmZXRjaGVzXFwnIG11c3QgYmUgYSBzdHJpbmcgYXJyYXkgb3IgYW4gb2JqZWN0LicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLm91dHB1dE5hbWVzLmluZGV4T2YobmFtZSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgJ2ZldGNoZXMnIGNvbnRhaW5zIGludmFsaWQgb3V0cHV0IG5hbWU6ICR7bmFtZX0uYCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZmV0Y2hlc1tuYW1lXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYXJnMiA9PT0gJ29iamVjdCcgJiYgYXJnMiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0gYXJnMjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGFyZzIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1xcJ29wdGlvbnNcXCcgbXVzdCBiZSBhbiBvYmplY3QuJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gZGVjaWRlIHdoZXRoZXIgYXJnMSBpcyBmZXRjaGVzIG9yIG9wdGlvbnNcbiAgICAgICAgICAgICAgICAvLyBpZiBhbnkgb3V0cHV0IG5hbWUgaXMgcHJlc2VudCBhbmQgaXRzIHZhbHVlIGlzIHZhbGlkIE9ubnhWYWx1ZSwgd2UgY29uc2lkZXIgaXQgZmV0Y2hlc1xuICAgICAgICAgICAgICAgIGxldCBpc0ZldGNoZXMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBjb25zdCBhcmcxS2V5cyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGFyZzEpO1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgbmFtZSBvZiB0aGlzLm91dHB1dE5hbWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhcmcxS2V5cy5pbmRleE9mKG5hbWUpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdiA9IGFyZzFbbmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodiA9PT0gbnVsbCB8fCB2IGluc3RhbmNlb2YgVGVuc29yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXNGZXRjaGVzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc0ZldGNoZXNFbXB0eSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZldGNoZXNbbmFtZV0gPSB2O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChpc0ZldGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBhcmcyID09PSAnb2JqZWN0JyAmJiBhcmcyICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zID0gYXJnMjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2YgYXJnMiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1xcJ29wdGlvbnNcXCcgbXVzdCBiZSBhbiBvYmplY3QuJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBhcmcxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgYXJnMSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1VuZXhwZWN0ZWQgYXJndW1lbnRbMV06IG11c3QgYmUgXFwnZmV0Y2hlc1xcJyBvciBcXCdvcHRpb25zXFwnLicpO1xuICAgICAgICB9XG4gICAgICAgIC8vIGNoZWNrIGlmIGFsbCBpbnB1dHMgYXJlIGluIGZlZWRcbiAgICAgICAgZm9yIChjb25zdCBuYW1lIG9mIHRoaXMuaW5wdXROYW1lcykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBmZWVkc1tuYW1lXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGlucHV0ICcke25hbWV9JyBpcyBtaXNzaW5nIGluICdmZWVkcycuYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gaWYgbm8gZmV0Y2hlcyBpcyBzcGVjaWZpZWQsIHdlIHVzZSB0aGUgZnVsbCBvdXRwdXQgbmFtZXMgbGlzdFxuICAgICAgICBpZiAoaXNGZXRjaGVzRW1wdHkpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgbmFtZSBvZiB0aGlzLm91dHB1dE5hbWVzKSB7XG4gICAgICAgICAgICAgICAgZmV0Y2hlc1tuYW1lXSA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gZmVlZHMsIGZldGNoZXMgYW5kIG9wdGlvbnMgYXJlIHByZXBhcmVkXG4gICAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCB0aGlzLmhhbmRsZXIucnVuKGZlZWRzLCBmZXRjaGVzLCBvcHRpb25zKTtcbiAgICAgICAgY29uc3QgcmV0dXJuVmFsdWUgPSB7fTtcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gcmVzdWx0cykge1xuICAgICAgICAgICAgaWYgKE9iamVjdC5oYXNPd25Qcm9wZXJ0eS5jYWxsKHJlc3VsdHMsIGtleSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm5WYWx1ZVtrZXldID0gbmV3IFRlbnNvcihyZXN1bHRzW2tleV0udHlwZSwgcmVzdWx0c1trZXldLmRhdGEsIHJlc3VsdHNba2V5XS5kaW1zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgfVxuICAgIHN0YXRpYyBhc3luYyBjcmVhdGUoYXJnMCwgYXJnMSwgYXJnMiwgYXJnMykge1xuICAgICAgICAvLyBlaXRoZXIgbG9hZCBmcm9tIGEgZmlsZSBvciBidWZmZXJcbiAgICAgICAgbGV0IGZpbGVQYXRoT3JVaW50OEFycmF5O1xuICAgICAgICBsZXQgb3B0aW9ucyA9IHt9O1xuICAgICAgICBpZiAodHlwZW9mIGFyZzAgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBmaWxlUGF0aE9yVWludDhBcnJheSA9IGFyZzA7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGFyZzEgPT09ICdvYmplY3QnICYmIGFyZzEgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBvcHRpb25zID0gYXJnMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBhcmcxICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1xcJ29wdGlvbnNcXCcgbXVzdCBiZSBhbiBvYmplY3QuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoYXJnMCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpIHtcbiAgICAgICAgICAgIGZpbGVQYXRoT3JVaW50OEFycmF5ID0gYXJnMDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgYXJnMSA9PT0gJ29iamVjdCcgJiYgYXJnMSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBhcmcxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGFyZzEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXFwnb3B0aW9uc1xcJyBtdXN0IGJlIGFuIG9iamVjdC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChhcmcwIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIgfHxcbiAgICAgICAgICAgICh0eXBlb2YgU2hhcmVkQXJyYXlCdWZmZXIgIT09ICd1bmRlZmluZWQnICYmIGFyZzAgaW5zdGFuY2VvZiBTaGFyZWRBcnJheUJ1ZmZlcikpIHtcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlciA9IGFyZzA7XG4gICAgICAgICAgICBsZXQgYnl0ZU9mZnNldCA9IDA7XG4gICAgICAgICAgICBsZXQgYnl0ZUxlbmd0aCA9IGFyZzAuYnl0ZUxlbmd0aDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgYXJnMSA9PT0gJ29iamVjdCcgJiYgYXJnMSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSBhcmcxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGFyZzEgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgICAgYnl0ZU9mZnNldCA9IGFyZzE7XG4gICAgICAgICAgICAgICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcihieXRlT2Zmc2V0KSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignXFwnYnl0ZU9mZnNldFxcJyBtdXN0IGJlIGFuIGludGVnZXIuJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChieXRlT2Zmc2V0IDwgMCB8fCBieXRlT2Zmc2V0ID49IGJ1ZmZlci5ieXRlTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKGAnYnl0ZU9mZnNldCcgaXMgb3V0IG9mIHJhbmdlIFswLCAke2J1ZmZlci5ieXRlTGVuZ3RofSkuYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGJ5dGVMZW5ndGggPSBhcmcwLmJ5dGVMZW5ndGggLSBieXRlT2Zmc2V0O1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYXJnMiA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgYnl0ZUxlbmd0aCA9IGFyZzI7XG4gICAgICAgICAgICAgICAgICAgIGlmICghTnVtYmVyLmlzU2FmZUludGVnZXIoYnl0ZUxlbmd0aCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdcXCdieXRlTGVuZ3RoXFwnIG11c3QgYmUgYW4gaW50ZWdlci4nKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoYnl0ZUxlbmd0aCA8PSAwIHx8IGJ5dGVPZmZzZXQgKyBieXRlTGVuZ3RoID4gYnVmZmVyLmJ5dGVMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKGAnYnl0ZUxlbmd0aCcgaXMgb3V0IG9mIHJhbmdlICgwLCAke2J1ZmZlci5ieXRlTGVuZ3RoIC0gYnl0ZU9mZnNldH1dLmApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYXJnMyA9PT0gJ29iamVjdCcgJiYgYXJnMyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IGFyZzM7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGFyZzMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcXCdvcHRpb25zXFwnIG11c3QgYmUgYW4gb2JqZWN0LicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBhcmcyICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcXCdieXRlTGVuZ3RoXFwnIG11c3QgYmUgYSBudW1iZXIuJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIGFyZzEgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXFwnb3B0aW9uc1xcJyBtdXN0IGJlIGFuIG9iamVjdC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZpbGVQYXRoT3JVaW50OEFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoYnVmZmVyLCBieXRlT2Zmc2V0LCBieXRlTGVuZ3RoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1VuZXhwZWN0ZWQgYXJndW1lbnRbMF06IG11c3QgYmUgXFwncGF0aFxcJyBvciBcXCdidWZmZXJcXCcuJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gZ2V0IGJhY2tlbmQgaGludHNcbiAgICAgICAgY29uc3QgZXBzID0gb3B0aW9ucy5leGVjdXRpb25Qcm92aWRlcnMgfHwgW107XG4gICAgICAgIGNvbnN0IGJhY2tlbmRIaW50cyA9IGVwcy5tYXAoaSA9PiB0eXBlb2YgaSA9PT0gJ3N0cmluZycgPyBpIDogaS5uYW1lKTtcbiAgICAgICAgY29uc3QgYmFja2VuZCA9IGF3YWl0IHJlc29sdmVCYWNrZW5kKGJhY2tlbmRIaW50cyk7XG4gICAgICAgIGNvbnN0IGhhbmRsZXIgPSBhd2FpdCBiYWNrZW5kLmNyZWF0ZVNlc3Npb25IYW5kbGVyKGZpbGVQYXRoT3JVaW50OEFycmF5LCBvcHRpb25zKTtcbiAgICAgICAgcmV0dXJuIG5ldyBJbmZlcmVuY2VTZXNzaW9uKGhhbmRsZXIpO1xuICAgIH1cbiAgICBzdGFydFByb2ZpbGluZygpIHtcbiAgICAgICAgdGhpcy5oYW5kbGVyLnN0YXJ0UHJvZmlsaW5nKCk7XG4gICAgfVxuICAgIGVuZFByb2ZpbGluZygpIHtcbiAgICAgICAgdGhpcy5oYW5kbGVyLmVuZFByb2ZpbGluZygpO1xuICAgIH1cbiAgICBnZXQgaW5wdXROYW1lcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlci5pbnB1dE5hbWVzO1xuICAgIH1cbiAgICBnZXQgb3V0cHV0TmFtZXMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmhhbmRsZXIub3V0cHV0TmFtZXM7XG4gICAgfVxufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW5mZXJlbmNlLXNlc3Npb24taW1wbC5qcy5tYXAiLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cbmltcG9ydCB7IEluZmVyZW5jZVNlc3Npb24gYXMgSW5mZXJlbmNlU2Vzc2lvbkltcGwgfSBmcm9tICcuL2luZmVyZW5jZS1zZXNzaW9uLWltcGwnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxuZXhwb3J0IGNvbnN0IEluZmVyZW5jZVNlc3Npb24gPSBJbmZlcmVuY2VTZXNzaW9uSW1wbDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWluZmVyZW5jZS1zZXNzaW9uLmpzLm1hcCIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuZXhwb3J0IHt9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9b25ueC12YWx1ZS5qcy5tYXAiLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cbi8vIGEgcnVudGltZSBtYXAgdGhhdCBtYXBzIHR5cGUgc3RyaW5nIHRvIFR5cGVkQXJyYXkgY29uc3RydWN0b3IuIFNob3VsZCBtYXRjaCBUZW5zb3IuRGF0YVR5cGVNYXAuXG5jb25zdCBOVU1FUklDX1RFTlNPUl9UWVBFX1RPX1RZUEVEQVJSQVlfTUFQID0gbmV3IE1hcChbXG4gICAgWydmbG9hdDMyJywgRmxvYXQzMkFycmF5XSxcbiAgICBbJ3VpbnQ4JywgVWludDhBcnJheV0sXG4gICAgWydpbnQ4JywgSW50OEFycmF5XSxcbiAgICBbJ3VpbnQxNicsIFVpbnQxNkFycmF5XSxcbiAgICBbJ2ludDE2JywgSW50MTZBcnJheV0sXG4gICAgWydpbnQzMicsIEludDMyQXJyYXldLFxuICAgIFsnYm9vbCcsIFVpbnQ4QXJyYXldLFxuICAgIFsnZmxvYXQ2NCcsIEZsb2F0NjRBcnJheV0sXG4gICAgWyd1aW50MzInLCBVaW50MzJBcnJheV0sXG5dKTtcbi8vIGEgcnVudGltZSBtYXAgdGhhdCBtYXBzIHR5cGUgc3RyaW5nIHRvIFR5cGVkQXJyYXkgY29uc3RydWN0b3IuIFNob3VsZCBtYXRjaCBUZW5zb3IuRGF0YVR5cGVNYXAuXG5jb25zdCBOVU1FUklDX1RFTlNPUl9UWVBFREFSUkFZX1RPX1RZUEVfTUFQID0gbmV3IE1hcChbXG4gICAgW0Zsb2F0MzJBcnJheSwgJ2Zsb2F0MzInXSxcbiAgICBbVWludDhBcnJheSwgJ3VpbnQ4J10sXG4gICAgW0ludDhBcnJheSwgJ2ludDgnXSxcbiAgICBbVWludDE2QXJyYXksICd1aW50MTYnXSxcbiAgICBbSW50MTZBcnJheSwgJ2ludDE2J10sXG4gICAgW0ludDMyQXJyYXksICdpbnQzMiddLFxuICAgIFtGbG9hdDY0QXJyYXksICdmbG9hdDY0J10sXG4gICAgW1VpbnQzMkFycmF5LCAndWludDMyJ10sXG5dKTtcbi8vIHRoZSBmb2xsb3dpbmcgY29kZSBhbGxvd3MgZGVsYXlpbmcgZXhlY3V0aW9uIG9mIEJpZ0ludCBjaGVja2luZy4gVGhpcyBhbGxvd3MgbGF6eSBpbml0aWFsaXphdGlvbiBmb3Jcbi8vIE5VTUVSSUNfVEVOU09SX1RZUEVfVE9fVFlQRURBUlJBWV9NQVAgYW5kIE5VTUVSSUNfVEVOU09SX1RZUEVEQVJSQVlfVE9fVFlQRV9NQVAsIHdoaWNoIGFsbG93cyBCaWdJbnQgcG9seWZpbGxcbi8vIGlmIGF2YWlsYWJsZS5cbmxldCBpc0JpZ0ludENoZWNrZWQgPSBmYWxzZTtcbmNvbnN0IGNoZWNrQmlnSW50ID0gKCkgPT4ge1xuICAgIGlmICghaXNCaWdJbnRDaGVja2VkKSB7XG4gICAgICAgIGlzQmlnSW50Q2hlY2tlZCA9IHRydWU7XG4gICAgICAgIGNvbnN0IGlzQmlnSW50NjRBcnJheUF2YWlsYWJsZSA9IHR5cGVvZiBCaWdJbnQ2NEFycmF5ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgQmlnSW50NjRBcnJheS5mcm9tID09PSAnZnVuY3Rpb24nO1xuICAgICAgICBjb25zdCBpc0JpZ1VpbnQ2NEFycmF5QXZhaWxhYmxlID0gdHlwZW9mIEJpZ1VpbnQ2NEFycmF5ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgQmlnVWludDY0QXJyYXkuZnJvbSA9PT0gJ2Z1bmN0aW9uJztcbiAgICAgICAgaWYgKGlzQmlnSW50NjRBcnJheUF2YWlsYWJsZSkge1xuICAgICAgICAgICAgTlVNRVJJQ19URU5TT1JfVFlQRV9UT19UWVBFREFSUkFZX01BUC5zZXQoJ2ludDY0JywgQmlnSW50NjRBcnJheSk7XG4gICAgICAgICAgICBOVU1FUklDX1RFTlNPUl9UWVBFREFSUkFZX1RPX1RZUEVfTUFQLnNldChCaWdJbnQ2NEFycmF5LCAnaW50NjQnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNCaWdVaW50NjRBcnJheUF2YWlsYWJsZSkge1xuICAgICAgICAgICAgTlVNRVJJQ19URU5TT1JfVFlQRV9UT19UWVBFREFSUkFZX01BUC5zZXQoJ3VpbnQ2NCcsIEJpZ1VpbnQ2NEFycmF5KTtcbiAgICAgICAgICAgIE5VTUVSSUNfVEVOU09SX1RZUEVEQVJSQVlfVE9fVFlQRV9NQVAuc2V0KEJpZ1VpbnQ2NEFycmF5LCAndWludDY0Jyk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuLyoqXG4gKiBjYWxjdWxhdGUgc2l6ZSBmcm9tIGRpbXMuXG4gKlxuICogQHBhcmFtIGRpbXMgdGhlIGRpbXMgYXJyYXkuIE1heSBiZSBhbiBpbGxlZ2FsIGlucHV0LlxuICovXG5jb25zdCBjYWxjdWxhdGVTaXplID0gKGRpbXMpID0+IHtcbiAgICBsZXQgc2l6ZSA9IDE7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkaW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGRpbSA9IGRpbXNbaV07XG4gICAgICAgIGlmICh0eXBlb2YgZGltICE9PSAnbnVtYmVyJyB8fCAhTnVtYmVyLmlzU2FmZUludGVnZXIoZGltKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgZGltc1ske2l9XSBtdXN0IGJlIGFuIGludGVnZXIsIGdvdDogJHtkaW19YCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRpbSA8IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKGBkaW1zWyR7aX1dIG11c3QgYmUgYSBub24tbmVnYXRpdmUgaW50ZWdlciwgZ290OiAke2RpbX1gKTtcbiAgICAgICAgfVxuICAgICAgICBzaXplICo9IGRpbTtcbiAgICB9XG4gICAgcmV0dXJuIHNpemU7XG59O1xuZXhwb3J0IGNsYXNzIFRlbnNvciB7XG4gICAgY29uc3RydWN0b3IoYXJnMCwgYXJnMSwgYXJnMikge1xuICAgICAgICBjaGVja0JpZ0ludCgpO1xuICAgICAgICBsZXQgdHlwZTtcbiAgICAgICAgbGV0IGRhdGE7XG4gICAgICAgIGxldCBkaW1zO1xuICAgICAgICAvLyBjaGVjayB3aGV0aGVyIGFyZzAgaXMgdHlwZSBvciBkYXRhXG4gICAgICAgIGlmICh0eXBlb2YgYXJnMCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyBPdmVycmlkZTogY29uc3RydWN0b3IodHlwZSwgZGF0YSwgLi4uKVxuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIHR5cGUgPSBhcmcwO1xuICAgICAgICAgICAgZGltcyA9IGFyZzI7XG4gICAgICAgICAgICBpZiAoYXJnMCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAvLyBzdHJpbmcgdGVuc29yXG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGFyZzEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Egc3RyaW5nIHRlbnNvclxcJ3MgZGF0YSBtdXN0IGJlIGEgc3RyaW5nIGFycmF5LicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyB3ZSBkb24ndCBjaGVjayB3aGV0aGVyIGV2ZXJ5IGVsZW1lbnQgaW4gdGhlIGFycmF5IGlzIHN0cmluZzsgdGhpcyBpcyB0b28gc2xvdy4gd2UgYXNzdW1lIGl0J3MgY29ycmVjdCBhbmRcbiAgICAgICAgICAgICAgICAvLyBlcnJvciB3aWxsIGJlIHBvcHVsYXRlZCBhdCBpbmZlcmVuY2VcbiAgICAgICAgICAgICAgICBkYXRhID0gYXJnMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIG51bWVyaWMgdGVuc29yXG4gICAgICAgICAgICAgICAgY29uc3QgdHlwZWRBcnJheUNvbnN0cnVjdG9yID0gTlVNRVJJQ19URU5TT1JfVFlQRV9UT19UWVBFREFSUkFZX01BUC5nZXQoYXJnMCk7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYFVuc3VwcG9ydGVkIHRlbnNvciB0eXBlOiAke2FyZzB9LmApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShhcmcxKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyB1c2UgJ2FzIGFueScgaGVyZSBiZWNhdXNlIFR5cGVTY3JpcHQncyBjaGVjayBvbiB0eXBlIG9mICdTdXBwb3J0ZWRUeXBlZEFycmF5Q29uc3RydWN0b3JzLmZyb20oKScgcHJvZHVjZXNcbiAgICAgICAgICAgICAgICAgICAgLy8gaW5jb3JyZWN0IHJlc3VsdHMuXG4gICAgICAgICAgICAgICAgICAgIC8vICd0eXBlZEFycmF5Q29uc3RydWN0b3InIHNob3VsZCBiZSBvbmUgb2YgdGhlIHR5cGVkIGFycmF5IHByb3RvdHlwZSBvYmplY3RzLlxuICAgICAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuICAgICAgICAgICAgICAgICAgICBkYXRhID0gdHlwZWRBcnJheUNvbnN0cnVjdG9yLmZyb20oYXJnMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGFyZzEgaW5zdGFuY2VvZiB0eXBlZEFycmF5Q29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YSA9IGFyZzE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBBICR7dHlwZX0gdGVuc29yJ3MgZGF0YSBtdXN0IGJlIHR5cGUgb2YgJHt0eXBlZEFycmF5Q29uc3RydWN0b3J9YCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIC8vIE92ZXJyaWRlOiBjb25zdHJ1Y3RvcihkYXRhLCAuLi4pXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgZGltcyA9IGFyZzE7XG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShhcmcwKSkge1xuICAgICAgICAgICAgICAgIC8vIG9ubHkgYm9vbGVhbltdIGFuZCBzdHJpbmdbXSBpcyBzdXBwb3J0ZWRcbiAgICAgICAgICAgICAgICBpZiAoYXJnMC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVGVuc29yIHR5cGUgY2Fubm90IGJlIGluZmVycmVkIGZyb20gYW4gZW1wdHkgYXJyYXkuJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGZpcnN0RWxlbWVudFR5cGUgPSB0eXBlb2YgYXJnMFswXTtcbiAgICAgICAgICAgICAgICBpZiAoZmlyc3RFbGVtZW50VHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9ICdzdHJpbmcnO1xuICAgICAgICAgICAgICAgICAgICBkYXRhID0gYXJnMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZmlyc3RFbGVtZW50VHlwZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSAnYm9vbCc7XG4gICAgICAgICAgICAgICAgICAgIC8vICdhcmcwJyBpcyBvZiB0eXBlICdib29sZWFuW10nLiBVaW50OEFycmF5LmZyb20oYm9vbGVhbltdKSBhY3R1YWxseSB3b3JrcywgYnV0IHR5cGVzY3JpcHQgdGhpbmtzIHRoaXMgaXNcbiAgICAgICAgICAgICAgICAgICAgLy8gd3JvbmcgdHlwZS4gV2UgdXNlICdhcyBhbnknIHRvIG1ha2UgaXQgaGFwcHkuXG4gICAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAgICAgICAgICAgICAgIGRhdGEgPSBVaW50OEFycmF5LmZyb20oYXJnMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBJbnZhbGlkIGVsZW1lbnQgdHlwZSBvZiBkYXRhIGFycmF5OiAke2ZpcnN0RWxlbWVudFR5cGV9LmApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIGdldCB0ZW5zb3IgdHlwZSBmcm9tIFR5cGVkQXJyYXlcbiAgICAgICAgICAgICAgICBjb25zdCBtYXBwZWRUeXBlID0gTlVNRVJJQ19URU5TT1JfVFlQRURBUlJBWV9UT19UWVBFX01BUC5nZXQoYXJnMC5jb25zdHJ1Y3Rvcik7XG4gICAgICAgICAgICAgICAgaWYgKG1hcHBlZFR5cGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBVbnN1cHBvcnRlZCB0eXBlIGZvciB0ZW5zb3IgZGF0YTogJHthcmcwLmNvbnN0cnVjdG9yfS5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdHlwZSA9IG1hcHBlZFR5cGU7XG4gICAgICAgICAgICAgICAgZGF0YSA9IGFyZzA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gdHlwZSBhbmQgZGF0YSBpcyBwcm9jZXNzZWQsIG5vdyBwcm9jZXNzaW5nIGRpbXNcbiAgICAgICAgaWYgKGRpbXMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgLy8gYXNzdW1lIDEtRCB0ZW5zb3IgaWYgZGltcyBvbWl0dGVkXG4gICAgICAgICAgICBkaW1zID0gW2RhdGEubGVuZ3RoXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghQXJyYXkuaXNBcnJheShkaW1zKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQSB0ZW5zb3JcXCdzIGRpbXMgbXVzdCBiZSBhIG51bWJlciBhcnJheScpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHBlcmZvcm0gY2hlY2tcbiAgICAgICAgY29uc3Qgc2l6ZSA9IGNhbGN1bGF0ZVNpemUoZGltcyk7XG4gICAgICAgIGlmIChzaXplICE9PSBkYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUZW5zb3IncyBzaXplKCR7c2l6ZX0pIGRvZXMgbm90IG1hdGNoIGRhdGEgbGVuZ3RoKCR7ZGF0YS5sZW5ndGh9KS5gKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmRpbXMgPSBkaW1zO1xuICAgICAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgICAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgICAgICB0aGlzLnNpemUgPSBzaXplO1xuICAgIH1cbiAgICAvLyAjZW5kcmVnaW9uXG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgbmV3IHRlbnNvciBvYmplY3QgZnJvbSBpbWFnZSBvYmplY3RcbiAgICAgKlxuICAgICAqIEBwYXJhbSBidWZmZXIgLSBFeHRyYWN0ZWQgaW1hZ2UgYnVmZmVyIGRhdGEgLSBhc3N1bWluZyBSR0JBIGZvcm1hdFxuICAgICAqIEBwYXJhbSBpbWFnZUZvcm1hdCAtIGlucHV0IGltYWdlIGNvbmZpZ3VyYXRpb24gLSByZXF1aXJlZCBjb25maWd1cmF0aW9ucyBoZWlnaHQsIHdpZHRoLCBmb3JtYXRcbiAgICAgKiBAcGFyYW0gdGVuc29yRm9ybWF0IC0gb3V0cHV0IHRlbnNvciBjb25maWd1cmF0aW9uIC0gRGVmYXVsdCBpcyBSR0IgZm9ybWF0XG4gICAgICovXG4gICAgc3RhdGljIGJ1ZmZlclRvVGVuc29yKGJ1ZmZlciwgb3B0aW9ucykge1xuICAgICAgICBpZiAoYnVmZmVyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2UgYnVmZmVyIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLmhlaWdodCA9PT0gdW5kZWZpbmVkIHx8IG9wdGlvbnMud2lkdGggPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbWFnZSBoZWlnaHQgYW5kIHdpZHRoIG11c3QgYmUgZGVmaW5lZCcpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvcHRpb25zLnRlbnNvckxheW91dCA9PT0gJ05IV0MnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05IV0MgVGVuc29yIGxheW91dCBpcyBub3Qgc3VwcG9ydGVkIHlldCcpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHsgaGVpZ2h0LCB3aWR0aCB9ID0gb3B0aW9ucztcbiAgICAgICAgY29uc3Qgbm9ybSA9IG9wdGlvbnMubm9ybSA/PyB7IG1lYW46IDI1NSwgYmlhczogMCB9O1xuICAgICAgICBsZXQgbm9ybU1lYW47XG4gICAgICAgIGxldCBub3JtQmlhcztcbiAgICAgICAgaWYgKHR5cGVvZiAobm9ybS5tZWFuKSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIG5vcm1NZWFuID0gW25vcm0ubWVhbiwgbm9ybS5tZWFuLCBub3JtLm1lYW4sIG5vcm0ubWVhbl07XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBub3JtTWVhbiA9IFtub3JtLm1lYW5bMF0sIG5vcm0ubWVhblsxXSwgbm9ybS5tZWFuWzJdLCBub3JtLm1lYW5bM10gPz8gMjU1XTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIChub3JtLmJpYXMpID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgbm9ybUJpYXMgPSBbbm9ybS5iaWFzLCBub3JtLmJpYXMsIG5vcm0uYmlhcywgbm9ybS5iaWFzXTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG5vcm1CaWFzID0gW25vcm0uYmlhc1swXSwgbm9ybS5iaWFzWzFdLCBub3JtLmJpYXNbMl0sIG5vcm0uYmlhc1szXSA/PyAwXTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBpbnB1dGZvcm1hdCA9IG9wdGlvbnMuYml0bWFwRm9ybWF0ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmJpdG1hcEZvcm1hdCA6ICdSR0JBJztcbiAgICAgICAgLy8gZGVmYXVsdCB2YWx1ZSBpcyBSR0JBIHNpbmNlIGltYWdlZGF0YSBhbmQgSFRNTEltYWdlRWxlbWVudCB1c2VzIGl0XG4gICAgICAgIGNvbnN0IG91dHB1dGZvcm1hdCA9IG9wdGlvbnMudGVuc29yRm9ybWF0ICE9PSB1bmRlZmluZWQgP1xuICAgICAgICAgICAgKG9wdGlvbnMudGVuc29yRm9ybWF0ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLnRlbnNvckZvcm1hdCA6ICdSR0InKSA6XG4gICAgICAgICAgICAnUkdCJztcbiAgICAgICAgY29uc3Qgc3RyaWRlID0gaGVpZ2h0ICogd2lkdGg7XG4gICAgICAgIGNvbnN0IGZsb2F0MzJEYXRhID0gb3V0cHV0Zm9ybWF0ID09PSAnUkdCQScgPyBuZXcgRmxvYXQzMkFycmF5KHN0cmlkZSAqIDQpIDogbmV3IEZsb2F0MzJBcnJheShzdHJpZGUgKiAzKTtcbiAgICAgICAgLy8gRGVmYXVsdCBwb2ludGVyIGFzc2lnbm1lbnRzXG4gICAgICAgIGxldCBzdGVwID0gNCwgckltYWdlUG9pbnRlciA9IDAsIGdJbWFnZVBvaW50ZXIgPSAxLCBiSW1hZ2VQb2ludGVyID0gMiwgYUltYWdlUG9pbnRlciA9IDM7XG4gICAgICAgIGxldCByVGVuc29yUG9pbnRlciA9IDAsIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlLCBiVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDIsIGFUZW5zb3JQb2ludGVyID0gLTE7XG4gICAgICAgIC8vIFVwZGF0aW5nIHRoZSBwb2ludGVyIGFzc2lnbm1lbnRzIGJhc2VkIG9uIHRoZSBpbnB1dCBpbWFnZSBmb3JtYXRcbiAgICAgICAgaWYgKGlucHV0Zm9ybWF0ID09PSAnUkdCJykge1xuICAgICAgICAgICAgc3RlcCA9IDM7XG4gICAgICAgICAgICBySW1hZ2VQb2ludGVyID0gMDtcbiAgICAgICAgICAgIGdJbWFnZVBvaW50ZXIgPSAxO1xuICAgICAgICAgICAgYkltYWdlUG9pbnRlciA9IDI7XG4gICAgICAgICAgICBhSW1hZ2VQb2ludGVyID0gLTE7XG4gICAgICAgIH1cbiAgICAgICAgLy8gVXBkYXRpbmcgdGhlIHBvaW50ZXIgYXNzaWdubWVudHMgYmFzZWQgb24gdGhlIG91dHB1dCB0ZW5zb3IgZm9ybWF0XG4gICAgICAgIGlmIChvdXRwdXRmb3JtYXQgPT09ICdSR0JBJykge1xuICAgICAgICAgICAgYVRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAzO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG91dHB1dGZvcm1hdCA9PT0gJ1JCRycpIHtcbiAgICAgICAgICAgIHJUZW5zb3JQb2ludGVyID0gMDtcbiAgICAgICAgICAgIGJUZW5zb3JQb2ludGVyID0gc3RyaWRlO1xuICAgICAgICAgICAgZ1RlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG91dHB1dGZvcm1hdCA9PT0gJ0JHUicpIHtcbiAgICAgICAgICAgIGJUZW5zb3JQb2ludGVyID0gMDtcbiAgICAgICAgICAgIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlO1xuICAgICAgICAgICAgclRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaWRlOyBpKyssIHJJbWFnZVBvaW50ZXIgKz0gc3RlcCwgYkltYWdlUG9pbnRlciArPSBzdGVwLCBnSW1hZ2VQb2ludGVyICs9IHN0ZXAsIGFJbWFnZVBvaW50ZXIgKz0gc3RlcCkge1xuICAgICAgICAgICAgZmxvYXQzMkRhdGFbclRlbnNvclBvaW50ZXIrK10gPSAoYnVmZmVyW3JJbWFnZVBvaW50ZXJdICsgbm9ybUJpYXNbMF0pIC8gbm9ybU1lYW5bMF07XG4gICAgICAgICAgICBmbG9hdDMyRGF0YVtnVGVuc29yUG9pbnRlcisrXSA9IChidWZmZXJbZ0ltYWdlUG9pbnRlcl0gKyBub3JtQmlhc1sxXSkgLyBub3JtTWVhblsxXTtcbiAgICAgICAgICAgIGZsb2F0MzJEYXRhW2JUZW5zb3JQb2ludGVyKytdID0gKGJ1ZmZlcltiSW1hZ2VQb2ludGVyXSArIG5vcm1CaWFzWzJdKSAvIG5vcm1NZWFuWzJdO1xuICAgICAgICAgICAgaWYgKGFUZW5zb3JQb2ludGVyICE9PSAtMSAmJiBhSW1hZ2VQb2ludGVyICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIGZsb2F0MzJEYXRhW2FUZW5zb3JQb2ludGVyKytdID0gKGJ1ZmZlclthSW1hZ2VQb2ludGVyXSArIG5vcm1CaWFzWzNdKSAvIG5vcm1NZWFuWzNdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIEZsb2F0MzJBcnJheSAtPiBvcnQuVGVuc29yXG4gICAgICAgIGNvbnN0IG91dHB1dFRlbnNvciA9IG91dHB1dGZvcm1hdCA9PT0gJ1JHQkEnID8gbmV3IFRlbnNvcignZmxvYXQzMicsIGZsb2F0MzJEYXRhLCBbMSwgNCwgaGVpZ2h0LCB3aWR0aF0pIDpcbiAgICAgICAgICAgIG5ldyBUZW5zb3IoJ2Zsb2F0MzInLCBmbG9hdDMyRGF0YSwgWzEsIDMsIGhlaWdodCwgd2lkdGhdKTtcbiAgICAgICAgcmV0dXJuIG91dHB1dFRlbnNvcjtcbiAgICB9XG4gICAgc3RhdGljIGFzeW5jIGZyb21JbWFnZShpbWFnZSwgb3B0aW9ucykge1xuICAgICAgICAvLyBjaGVja2luZyB0aGUgdHlwZSBvZiBpbWFnZSBvYmplY3RcbiAgICAgICAgY29uc3QgaXNIVE1MSW1hZ2VFbGUgPSB0eXBlb2YgKEhUTUxJbWFnZUVsZW1lbnQpICE9PSAndW5kZWZpbmVkJyAmJiBpbWFnZSBpbnN0YW5jZW9mIEhUTUxJbWFnZUVsZW1lbnQ7XG4gICAgICAgIGNvbnN0IGlzSW1hZ2VEYXRhRWxlID0gdHlwZW9mIChJbWFnZURhdGEpICE9PSAndW5kZWZpbmVkJyAmJiBpbWFnZSBpbnN0YW5jZW9mIEltYWdlRGF0YTtcbiAgICAgICAgY29uc3QgaXNJbWFnZUJpdG1hcCA9IHR5cGVvZiAoSW1hZ2VCaXRtYXApICE9PSAndW5kZWZpbmVkJyAmJiBpbWFnZSBpbnN0YW5jZW9mIEltYWdlQml0bWFwO1xuICAgICAgICBjb25zdCBpc1N0cmluZyA9IHR5cGVvZiBpbWFnZSA9PT0gJ3N0cmluZyc7XG4gICAgICAgIGxldCBkYXRhO1xuICAgICAgICBsZXQgdGVuc29yQ29uZmlnID0gb3B0aW9ucyA/PyB7fTtcbiAgICAgICAgLy8gZmlsbGluZyBhbmQgY2hlY2tpbmcgaW1hZ2UgY29uZmlndXJhdGlvbiBvcHRpb25zXG4gICAgICAgIGlmIChpc0hUTUxJbWFnZUVsZSkge1xuICAgICAgICAgICAgLy8gSFRNTEltYWdlRWxlbWVudCAtIGltYWdlIG9iamVjdCAtIGZvcm1hdCBpcyBSR0JBIGJ5IGRlZmF1bHRcbiAgICAgICAgICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICAgICAgY2FudmFzLndpZHRoID0gaW1hZ2Uud2lkdGg7XG4gICAgICAgICAgICBjYW52YXMuaGVpZ2h0ID0gaW1hZ2UuaGVpZ2h0O1xuICAgICAgICAgICAgY29uc3QgcGl4ZWxzMkRDb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgICAgICBpZiAocGl4ZWxzMkRDb250ZXh0ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBsZXQgaGVpZ2h0ID0gaW1hZ2UuaGVpZ2h0O1xuICAgICAgICAgICAgICAgIGxldCB3aWR0aCA9IGltYWdlLndpZHRoO1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5yZXNpemVkSGVpZ2h0ICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5yZXNpemVkV2lkdGggIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICBoZWlnaHQgPSBvcHRpb25zLnJlc2l6ZWRIZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIHdpZHRoID0gb3B0aW9ucy5yZXNpemVkV2lkdGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGVuc29yQ29uZmlnID0gb3B0aW9ucztcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMudGVuc29yRm9ybWF0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2UgaW5wdXQgY29uZmlnIGZvcm1hdCBtdXN0IGJlIFJHQkEgZm9yIEhUTUxJbWFnZUVsZW1lbnQnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy50ZW5zb3JGb3JtYXQgPSAnUkdCQSc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuaGVpZ2h0ICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5oZWlnaHQgIT09IGhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbWFnZSBpbnB1dCBjb25maWcgaGVpZ2h0IGRvZXNuXFwndCBtYXRjaCBIVE1MSW1hZ2VFbGVtZW50IGhlaWdodCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGVuc29yQ29uZmlnLmhlaWdodCA9IGhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy53aWR0aCAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMud2lkdGggIT09IHdpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltYWdlIGlucHV0IGNvbmZpZyB3aWR0aCBkb2VzblxcJ3QgbWF0Y2ggSFRNTEltYWdlRWxlbWVudCB3aWR0aCcpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGVuc29yQ29uZmlnLndpZHRoID0gd2lkdGg7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy50ZW5zb3JGb3JtYXQgPSAnUkdCQSc7XG4gICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy53aWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwaXhlbHMyRENvbnRleHQuZHJhd0ltYWdlKGltYWdlLCAwLCAwKTtcbiAgICAgICAgICAgICAgICBkYXRhID0gcGl4ZWxzMkRDb250ZXh0LmdldEltYWdlRGF0YSgwLCAwLCB3aWR0aCwgaGVpZ2h0KS5kYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNJbWFnZURhdGFFbGUpIHtcbiAgICAgICAgICAgIC8vIEltYWdlRGF0YSAtIGltYWdlIG9iamVjdCAtIGZvcm1hdCBpcyBSR0JBIGJ5IGRlZmF1bHRcbiAgICAgICAgICAgIGNvbnN0IGZvcm1hdCA9ICdSR0JBJztcbiAgICAgICAgICAgIGxldCBoZWlnaHQ7XG4gICAgICAgICAgICBsZXQgd2lkdGg7XG4gICAgICAgICAgICBpZiAob3B0aW9ucyAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMucmVzaXplZFdpZHRoICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5yZXNpemVkSGVpZ2h0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBoZWlnaHQgPSBvcHRpb25zLnJlc2l6ZWRIZWlnaHQ7XG4gICAgICAgICAgICAgICAgd2lkdGggPSBvcHRpb25zLnJlc2l6ZWRXaWR0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGhlaWdodCA9IGltYWdlLmhlaWdodDtcbiAgICAgICAgICAgICAgICB3aWR0aCA9IGltYWdlLndpZHRoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdGlvbnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZyA9IG9wdGlvbnM7XG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuYml0bWFwRm9ybWF0ICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5iaXRtYXBGb3JtYXQgIT09IGZvcm1hdCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltYWdlIGlucHV0IGNvbmZpZyBmb3JtYXQgbXVzdCBiZSBSR0JBIGZvciBJbWFnZURhdGEnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy5iaXRtYXBGb3JtYXQgPSAnUkdCQSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGVuc29yQ29uZmlnLmJpdG1hcEZvcm1hdCA9ICdSR0JBJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRlbnNvckNvbmZpZy5oZWlnaHQgPSBoZWlnaHQ7XG4gICAgICAgICAgICB0ZW5zb3JDb25maWcud2lkdGggPSB3aWR0aDtcbiAgICAgICAgICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB0ZW1wQ2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgICAgICAgICAgICAgdGVtcENhbnZhcy53aWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgICAgIHRlbXBDYW52YXMuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICAgICAgICAgIGNvbnN0IHBpeGVsczJEQ29udGV4dCA9IHRlbXBDYW52YXMuZ2V0Q29udGV4dCgnMmQnKTtcbiAgICAgICAgICAgICAgICBpZiAocGl4ZWxzMkRDb250ZXh0ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcGl4ZWxzMkRDb250ZXh0LnB1dEltYWdlRGF0YShpbWFnZSwgMCwgMCk7XG4gICAgICAgICAgICAgICAgICAgIGRhdGEgPSBwaXhlbHMyRENvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIHdpZHRoLCBoZWlnaHQpLmRhdGE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkYXRhID0gaW1hZ2UuZGF0YTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChpc0ltYWdlQml0bWFwKSB7XG4gICAgICAgICAgICAvLyBJbWFnZUJpdG1hcCAtIGltYWdlIG9iamVjdCAtIGZvcm1hdCBtdXN0IGJlIHByb3ZpZGVkIGJ5IHVzZXJcbiAgICAgICAgICAgIGlmIChvcHRpb25zID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BsZWFzZSBwcm92aWRlIGltYWdlIGNvbmZpZyB3aXRoIGZvcm1hdCBmb3IgSW1hZ2ViaXRtYXAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvcHRpb25zLmJpdG1hcEZvcm1hdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbWFnZSBpbnB1dCBjb25maWcgZm9ybWF0IG11c3QgYmUgZGVmaW5lZCBmb3IgSW1hZ2VCaXRtYXAnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHBpeGVsczJEQ29udGV4dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgICAgICBpZiAocGl4ZWxzMkRDb250ZXh0ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBoZWlnaHQgPSBpbWFnZS5oZWlnaHQ7XG4gICAgICAgICAgICAgICAgY29uc3Qgd2lkdGggPSBpbWFnZS53aWR0aDtcbiAgICAgICAgICAgICAgICBwaXhlbHMyRENvbnRleHQuZHJhd0ltYWdlKGltYWdlLCAwLCAwLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICBkYXRhID0gcGl4ZWxzMkRDb250ZXh0LmdldEltYWdlRGF0YSgwLCAwLCB3aWR0aCwgaGVpZ2h0KS5kYXRhO1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gdXNpbmcgc3F1YXJlIGJyYWNrZXRzIHRvIGF2b2lkIFRTIGVycm9yIC0gdHlwZSAnbmV2ZXInXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmhlaWdodCAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMuaGVpZ2h0ICE9PSBoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2UgaW5wdXQgY29uZmlnIGhlaWdodCBkb2VzblxcJ3QgbWF0Y2ggSW1hZ2VCaXRtYXAgaGVpZ2h0Jyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0ZW5zb3JDb25maWcuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIHVzaW5nIHNxdWFyZSBicmFja2V0cyB0byBhdm9pZCBUUyBlcnJvciAtIHR5cGUgJ25ldmVyJ1xuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy53aWR0aCAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMud2lkdGggIT09IHdpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltYWdlIGlucHV0IGNvbmZpZyB3aWR0aCBkb2VzblxcJ3QgbWF0Y2ggSW1hZ2VCaXRtYXAgd2lkdGgnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy53aWR0aCA9IHdpZHRoO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0ZW5zb3JDb25maWcuaGVpZ2h0ID0gaGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB0ZW5zb3JDb25maWcud2lkdGggPSB3aWR0aDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIFRlbnNvci5idWZmZXJUb1RlbnNvcihkYXRhLCB0ZW5zb3JDb25maWcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW4gbm90IGFjY2VzcyBpbWFnZSBkYXRhJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXNTdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgICAgICAgICAgICAgY29uc3QgY29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICAgICAgICAgIGlmICghaW1hZ2UgfHwgIWNvbnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBuZXdJbWFnZSA9IG5ldyBJbWFnZSgpO1xuICAgICAgICAgICAgICAgIG5ld0ltYWdlLmNyb3NzT3JpZ2luID0gJ0Fub255bW91cyc7XG4gICAgICAgICAgICAgICAgbmV3SW1hZ2Uuc3JjID0gaW1hZ2U7XG4gICAgICAgICAgICAgICAgbmV3SW1hZ2Uub25sb2FkID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjYW52YXMud2lkdGggPSBuZXdJbWFnZS53aWR0aDtcbiAgICAgICAgICAgICAgICAgICAgY2FudmFzLmhlaWdodCA9IG5ld0ltYWdlLmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dC5kcmF3SW1hZ2UobmV3SW1hZ2UsIDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGltZyA9IGNvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIGNhbnZhcy53aWR0aCwgY2FudmFzLmhlaWdodCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmhlaWdodCAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMuaGVpZ2h0ICE9PSBjYW52YXMuaGVpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbWFnZSBpbnB1dCBjb25maWcgaGVpZ2h0IGRvZXNuXFwndCBtYXRjaCBoZWlnaHQnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy5oZWlnaHQgPSBjYW52YXMuaGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMud2lkdGggIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLndpZHRoICE9PSBjYW52YXMud2lkdGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ltYWdlIGlucHV0IGNvbmZpZyB3aWR0aCBkb2VzblxcJ3QgbWF0Y2ggd2lkdGgnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy53aWR0aCA9IGNhbnZhcy53aWR0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRlbnNvckNvbmZpZy5oZWlnaHQgPSBjYW52YXMuaGVpZ2h0O1xuICAgICAgICAgICAgICAgICAgICAgICAgdGVuc29yQ29uZmlnLndpZHRoID0gY2FudmFzLndpZHRoO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoVGVuc29yLmJ1ZmZlclRvVGVuc29yKGltZy5kYXRhLCB0ZW5zb3JDb25maWcpKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0lucHV0IGRhdGEgcHJvdmlkZWQgaXMgbm90IHN1cHBvcnRlZCAtIGFib3J0ZWQgdGVuc29yIGNyZWF0aW9uJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRhdGEgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIFRlbnNvci5idWZmZXJUb1RlbnNvcihkYXRhLCB0ZW5zb3JDb25maWcpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBkYXRhIHByb3ZpZGVkIGlzIG5vdCBzdXBwb3J0ZWQgLSBhYm9ydGVkIHRlbnNvciBjcmVhdGlvbicpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHRvRGF0YVVSTChvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICBjYW52YXMud2lkdGggPSB0aGlzLmRpbXNbM107XG4gICAgICAgIGNhbnZhcy5oZWlnaHQgPSB0aGlzLmRpbXNbMl07XG4gICAgICAgIGNvbnN0IHBpeGVsczJEQ29udGV4dCA9IGNhbnZhcy5nZXRDb250ZXh0KCcyZCcpO1xuICAgICAgICBpZiAocGl4ZWxzMkRDb250ZXh0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIC8vIERlZmF1bHQgdmFsdWVzIGZvciBoZWlnaHQgYW5kIHdpZHRoICYgZm9ybWF0XG4gICAgICAgICAgICBsZXQgd2lkdGg7XG4gICAgICAgICAgICBsZXQgaGVpZ2h0O1xuICAgICAgICAgICAgaWYgKG9wdGlvbnM/LnRlbnNvckxheW91dCAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMudGVuc29yTGF5b3V0ID09PSAnTkhXQycpIHtcbiAgICAgICAgICAgICAgICB3aWR0aCA9IHRoaXMuZGltc1syXTtcbiAgICAgICAgICAgICAgICBoZWlnaHQgPSB0aGlzLmRpbXNbM107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHsgLy8gRGVmYXVsdCBsYXlvdXQgaXMgTkNXSFxuICAgICAgICAgICAgICAgIHdpZHRoID0gdGhpcy5kaW1zWzNdO1xuICAgICAgICAgICAgICAgIGhlaWdodCA9IHRoaXMuZGltc1syXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGlucHV0Zm9ybWF0ID0gb3B0aW9ucz8uZm9ybWF0ICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLmZvcm1hdCA6ICdSR0InO1xuICAgICAgICAgICAgY29uc3Qgbm9ybSA9IG9wdGlvbnM/Lm5vcm07XG4gICAgICAgICAgICBsZXQgbm9ybU1lYW47XG4gICAgICAgICAgICBsZXQgbm9ybUJpYXM7XG4gICAgICAgICAgICBpZiAobm9ybSA9PT0gdW5kZWZpbmVkIHx8IG5vcm0ubWVhbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbm9ybU1lYW4gPSBbMjU1LCAyNTUsIDI1NSwgMjU1XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgKG5vcm0ubWVhbikgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vcm1NZWFuID0gW25vcm0ubWVhbiwgbm9ybS5tZWFuLCBub3JtLm1lYW4sIG5vcm0ubWVhbl07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBub3JtTWVhbiA9IFtub3JtLm1lYW5bMF0sIG5vcm0ubWVhblsxXSwgbm9ybS5tZWFuWzJdLCAwXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5vcm0ubWVhblszXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub3JtTWVhblszXSA9IG5vcm0ubWVhblszXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChub3JtID09PSB1bmRlZmluZWQgfHwgbm9ybS5iaWFzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBub3JtQmlhcyA9IFswLCAwLCAwLCAwXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgKG5vcm0uYmlhcykgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vcm1CaWFzID0gW25vcm0uYmlhcywgbm9ybS5iaWFzLCBub3JtLmJpYXMsIG5vcm0uYmlhc107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBub3JtQmlhcyA9IFtub3JtLmJpYXNbMF0sIG5vcm0uYmlhc1sxXSwgbm9ybS5iaWFzWzJdLCAwXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5vcm0uYmlhc1szXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub3JtQmlhc1szXSA9IG5vcm0uYmlhc1szXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHN0cmlkZSA9IGhlaWdodCAqIHdpZHRoO1xuICAgICAgICAgICAgLy8gRGVmYXVsdCBwb2ludGVyIGFzc2lnbm1lbnRzXG4gICAgICAgICAgICBsZXQgclRlbnNvclBvaW50ZXIgPSAwLCBnVGVuc29yUG9pbnRlciA9IHN0cmlkZSwgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyLCBhVGVuc29yUG9pbnRlciA9IC0xO1xuICAgICAgICAgICAgLy8gVXBkYXRpbmcgdGhlIHBvaW50ZXIgYXNzaWdubWVudHMgYmFzZWQgb24gdGhlIGlucHV0IGltYWdlIGZvcm1hdFxuICAgICAgICAgICAgaWYgKGlucHV0Zm9ybWF0ID09PSAnUkdCQScpIHtcbiAgICAgICAgICAgICAgICByVGVuc29yUG9pbnRlciA9IDA7XG4gICAgICAgICAgICAgICAgZ1RlbnNvclBvaW50ZXIgPSBzdHJpZGU7XG4gICAgICAgICAgICAgICAgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyO1xuICAgICAgICAgICAgICAgIGFUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGlucHV0Zm9ybWF0ID09PSAnUkdCJykge1xuICAgICAgICAgICAgICAgIHJUZW5zb3JQb2ludGVyID0gMDtcbiAgICAgICAgICAgICAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZTtcbiAgICAgICAgICAgICAgICBiVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChpbnB1dGZvcm1hdCA9PT0gJ1JCRycpIHtcbiAgICAgICAgICAgICAgICByVGVuc29yUG9pbnRlciA9IDA7XG4gICAgICAgICAgICAgICAgYlRlbnNvclBvaW50ZXIgPSBzdHJpZGU7XG4gICAgICAgICAgICAgICAgZ1RlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoZWlnaHQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgd2lkdGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBSID0gKHRoaXMuZGF0YVtyVGVuc29yUG9pbnRlcisrXSAtIG5vcm1CaWFzWzBdKSAqIG5vcm1NZWFuWzBdOyAvLyBSIHZhbHVlXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IEcgPSAodGhpcy5kYXRhW2dUZW5zb3JQb2ludGVyKytdIC0gbm9ybUJpYXNbMV0pICogbm9ybU1lYW5bMV07IC8vIEcgdmFsdWVcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgQiA9ICh0aGlzLmRhdGFbYlRlbnNvclBvaW50ZXIrK10gLSBub3JtQmlhc1syXSkgKiBub3JtTWVhblsyXTsgLy8gQiB2YWx1ZVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBBID0gYVRlbnNvclBvaW50ZXIgPT09IC0xID9cbiAgICAgICAgICAgICAgICAgICAgICAgIDI1NSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAodGhpcy5kYXRhW2FUZW5zb3JQb2ludGVyKytdIC0gbm9ybUJpYXNbM10pICogbm9ybU1lYW5bM107IC8vIEEgdmFsdWVcbiAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9yZXN0cmljdC1wbHVzLW9wZXJhbmRzXG4gICAgICAgICAgICAgICAgICAgIHBpeGVsczJEQ29udGV4dC5maWxsU3R5bGUgPSAncmdiYSgnICsgUiArICcsJyArIEcgKyAnLCcgKyBCICsgJywnICsgQSArICcpJztcbiAgICAgICAgICAgICAgICAgICAgcGl4ZWxzMkRDb250ZXh0LmZpbGxSZWN0KGosIGksIDEsIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBjYW52YXMudG9EYXRhVVJMKCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBub3QgYWNjZXNzIGltYWdlIGRhdGEnKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB0b0ltYWdlRGF0YShvcHRpb25zKSB7XG4gICAgICAgIGNvbnN0IHBpeGVsczJEQ29udGV4dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgIGxldCBpbWFnZTtcbiAgICAgICAgaWYgKHBpeGVsczJEQ29udGV4dCAhPSBudWxsKSB7XG4gICAgICAgICAgICAvLyBEZWZhdWx0IHZhbHVlcyBmb3IgaGVpZ2h0IGFuZCB3aWR0aCAmIGZvcm1hdFxuICAgICAgICAgICAgbGV0IHdpZHRoO1xuICAgICAgICAgICAgbGV0IGhlaWdodDtcbiAgICAgICAgICAgIGxldCBjaGFubmVscztcbiAgICAgICAgICAgIGlmIChvcHRpb25zPy50ZW5zb3JMYXlvdXQgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLnRlbnNvckxheW91dCA9PT0gJ05IV0MnKSB7XG4gICAgICAgICAgICAgICAgd2lkdGggPSB0aGlzLmRpbXNbMl07XG4gICAgICAgICAgICAgICAgaGVpZ2h0ID0gdGhpcy5kaW1zWzFdO1xuICAgICAgICAgICAgICAgIGNoYW5uZWxzID0gdGhpcy5kaW1zWzNdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7IC8vIERlZmF1bHQgbGF5b3V0IGlzIE5DV0hcbiAgICAgICAgICAgICAgICB3aWR0aCA9IHRoaXMuZGltc1szXTtcbiAgICAgICAgICAgICAgICBoZWlnaHQgPSB0aGlzLmRpbXNbMl07XG4gICAgICAgICAgICAgICAgY2hhbm5lbHMgPSB0aGlzLmRpbXNbMV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBpbnB1dGZvcm1hdCA9IG9wdGlvbnMgIT09IHVuZGVmaW5lZCA/IChvcHRpb25zLmZvcm1hdCAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5mb3JtYXQgOiAnUkdCJykgOiAnUkdCJztcbiAgICAgICAgICAgIGNvbnN0IG5vcm0gPSBvcHRpb25zPy5ub3JtO1xuICAgICAgICAgICAgbGV0IG5vcm1NZWFuO1xuICAgICAgICAgICAgbGV0IG5vcm1CaWFzO1xuICAgICAgICAgICAgaWYgKG5vcm0gPT09IHVuZGVmaW5lZCB8fCBub3JtLm1lYW4gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIG5vcm1NZWFuID0gWzI1NSwgMjU1LCAyNTUsIDI1NV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIChub3JtLm1lYW4pID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgICAgICAgICBub3JtTWVhbiA9IFtub3JtLm1lYW4sIG5vcm0ubWVhbiwgbm9ybS5tZWFuLCBub3JtLm1lYW5dO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbm9ybU1lYW4gPSBbbm9ybS5tZWFuWzBdLCBub3JtLm1lYW5bMV0sIG5vcm0ubWVhblsyXSwgMjU1XTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5vcm0ubWVhblszXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub3JtTWVhblszXSA9IG5vcm0ubWVhblszXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChub3JtID09PSB1bmRlZmluZWQgfHwgbm9ybS5iaWFzID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBub3JtQmlhcyA9IFswLCAwLCAwLCAwXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgKG5vcm0uYmlhcykgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vcm1CaWFzID0gW25vcm0uYmlhcywgbm9ybS5iaWFzLCBub3JtLmJpYXMsIG5vcm0uYmlhc107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBub3JtQmlhcyA9IFtub3JtLmJpYXNbMF0sIG5vcm0uYmlhc1sxXSwgbm9ybS5iaWFzWzJdLCAwXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5vcm0uYmlhc1szXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub3JtQmlhc1szXSA9IG5vcm0uYmlhc1szXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHN0cmlkZSA9IGhlaWdodCAqIHdpZHRoO1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmhlaWdodCAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMuaGVpZ2h0ICE9PSBoZWlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbWFnZSBvdXRwdXQgY29uZmlnIGhlaWdodCBkb2VzblxcJ3QgbWF0Y2ggdGVuc29yIGhlaWdodCcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy53aWR0aCAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMud2lkdGggIT09IHdpZHRoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2Ugb3V0cHV0IGNvbmZpZyB3aWR0aCBkb2VzblxcJ3QgbWF0Y2ggdGVuc29yIHdpZHRoJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmZvcm1hdCAhPT0gdW5kZWZpbmVkICYmIChjaGFubmVscyA9PT0gNCAmJiBvcHRpb25zLmZvcm1hdCAhPT0gJ1JHQkEnKSB8fFxuICAgICAgICAgICAgICAgICAgICAoY2hhbm5lbHMgPT09IDMgJiYgKG9wdGlvbnMuZm9ybWF0ICE9PSAnUkdCJyAmJiBvcHRpb25zLmZvcm1hdCAhPT0gJ0JHUicpKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RlbnNvciBmb3JtYXQgZG9lc25cXCd0IG1hdGNoIGlucHV0IHRlbnNvciBkaW1zJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRGVmYXVsdCBwb2ludGVyIGFzc2lnbm1lbnRzXG4gICAgICAgICAgICBjb25zdCBzdGVwID0gNDtcbiAgICAgICAgICAgIGxldCBySW1hZ2VQb2ludGVyID0gMCwgZ0ltYWdlUG9pbnRlciA9IDEsIGJJbWFnZVBvaW50ZXIgPSAyLCBhSW1hZ2VQb2ludGVyID0gMztcbiAgICAgICAgICAgIGxldCByVGVuc29yUG9pbnRlciA9IDAsIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlLCBiVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDIsIGFUZW5zb3JQb2ludGVyID0gLTE7XG4gICAgICAgICAgICAvLyBVcGRhdGluZyB0aGUgcG9pbnRlciBhc3NpZ25tZW50cyBiYXNlZCBvbiB0aGUgaW5wdXQgaW1hZ2UgZm9ybWF0XG4gICAgICAgICAgICBpZiAoaW5wdXRmb3JtYXQgPT09ICdSR0JBJykge1xuICAgICAgICAgICAgICAgIHJUZW5zb3JQb2ludGVyID0gMDtcbiAgICAgICAgICAgICAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZTtcbiAgICAgICAgICAgICAgICBiVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDI7XG4gICAgICAgICAgICAgICAgYVRlbnNvclBvaW50ZXIgPSBzdHJpZGUgKiAzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoaW5wdXRmb3JtYXQgPT09ICdSR0InKSB7XG4gICAgICAgICAgICAgICAgclRlbnNvclBvaW50ZXIgPSAwO1xuICAgICAgICAgICAgICAgIGdUZW5zb3JQb2ludGVyID0gc3RyaWRlO1xuICAgICAgICAgICAgICAgIGJUZW5zb3JQb2ludGVyID0gc3RyaWRlICogMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGlucHV0Zm9ybWF0ID09PSAnUkJHJykge1xuICAgICAgICAgICAgICAgIHJUZW5zb3JQb2ludGVyID0gMDtcbiAgICAgICAgICAgICAgICBiVGVuc29yUG9pbnRlciA9IHN0cmlkZTtcbiAgICAgICAgICAgICAgICBnVGVuc29yUG9pbnRlciA9IHN0cmlkZSAqIDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpbWFnZSA9IHBpeGVsczJEQ29udGV4dC5jcmVhdGVJbWFnZURhdGEod2lkdGgsIGhlaWdodCk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGhlaWdodCAqIHdpZHRoOyBySW1hZ2VQb2ludGVyICs9IHN0ZXAsIGdJbWFnZVBvaW50ZXIgKz0gc3RlcCwgYkltYWdlUG9pbnRlciArPSBzdGVwLCBhSW1hZ2VQb2ludGVyICs9IHN0ZXAsIGkrKykge1xuICAgICAgICAgICAgICAgIGltYWdlLmRhdGFbckltYWdlUG9pbnRlcl0gPSAodGhpcy5kYXRhW3JUZW5zb3JQb2ludGVyKytdIC0gbm9ybUJpYXNbMF0pICogbm9ybU1lYW5bMF07IC8vIFIgdmFsdWVcbiAgICAgICAgICAgICAgICBpbWFnZS5kYXRhW2dJbWFnZVBvaW50ZXJdID0gKHRoaXMuZGF0YVtnVGVuc29yUG9pbnRlcisrXSAtIG5vcm1CaWFzWzFdKSAqIG5vcm1NZWFuWzFdOyAvLyBHIHZhbHVlXG4gICAgICAgICAgICAgICAgaW1hZ2UuZGF0YVtiSW1hZ2VQb2ludGVyXSA9ICh0aGlzLmRhdGFbYlRlbnNvclBvaW50ZXIrK10gLSBub3JtQmlhc1syXSkgKiBub3JtTWVhblsyXTsgLy8gQiB2YWx1ZVxuICAgICAgICAgICAgICAgIGltYWdlLmRhdGFbYUltYWdlUG9pbnRlcl0gPSBhVGVuc29yUG9pbnRlciA9PT0gLTEgP1xuICAgICAgICAgICAgICAgICAgICAyNTUgOlxuICAgICAgICAgICAgICAgICAgICAodGhpcy5kYXRhW2FUZW5zb3JQb2ludGVyKytdIC0gbm9ybUJpYXNbM10pICogbm9ybU1lYW5bM107IC8vIEEgdmFsdWVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuIG5vdCBhY2Nlc3MgaW1hZ2UgZGF0YScpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpbWFnZTtcbiAgICB9XG4gICAgLy8gI2VuZHJlZ2lvblxuICAgIC8vICNyZWdpb24gdGVuc29yIHV0aWxpdGllc1xuICAgIHJlc2hhcGUoZGltcykge1xuICAgICAgICByZXR1cm4gbmV3IFRlbnNvcih0aGlzLnR5cGUsIHRoaXMuZGF0YSwgZGltcyk7XG4gICAgfVxufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dGVuc29yLWltcGwuanMubWFwIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5pbXBvcnQgeyBUZW5zb3IgYXMgVGVuc29ySW1wbCB9IGZyb20gJy4vdGVuc29yLWltcGwnO1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxuZXhwb3J0IGNvbnN0IFRlbnNvciA9IFRlbnNvckltcGw7XG4vLyMgc291cmNlTWFwcGluZ1VSTD10ZW5zb3IuanMubWFwIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbi8qIGVzbGludC1kaXNhYmxlIGltcG9ydC9uby1pbnRlcm5hbC1tb2R1bGVzICovXG5pbXBvcnQge0JhY2tlbmQsIEluZmVyZW5jZVNlc3Npb24sIFNlc3Npb25IYW5kbGVyfSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQge1Nlc3Npb259IGZyb20gJy4vb25ueGpzL3Nlc3Npb24nO1xuaW1wb3J0IHtPbm54anNTZXNzaW9uSGFuZGxlcn0gZnJvbSAnLi9vbm54anMvc2Vzc2lvbi1oYW5kbGVyJztcblxuY2xhc3MgT25ueGpzQmFja2VuZCBpbXBsZW1lbnRzIEJhY2tlbmQge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWVtcHR5LWZ1bmN0aW9uXG4gIGFzeW5jIGluaXQoKTogUHJvbWlzZTx2b2lkPiB7fVxuXG4gIGFzeW5jIGNyZWF0ZVNlc3Npb25IYW5kbGVyKHBhdGhPckJ1ZmZlcjogc3RyaW5nfFVpbnQ4QXJyYXksIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zKTpcbiAgICAgIFByb21pc2U8U2Vzc2lvbkhhbmRsZXI+IHtcbiAgICAvLyBOT1RFOiBTZXNzaW9uLkNvbmZpZyhmcm9tIG9ubnguanMpIGlzIG5vdCBjb21wYXRpYmxlIHdpdGggSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyhmcm9tXG4gICAgLy8gb25ueHJ1bnRpbWUtY29tbW9uKS5cbiAgICAvLyAgICAgICBJbiBmdXR1cmUgd2Ugc2hvdWxkIHJlbW92ZSBTZXNzaW9uLkNvbmZpZyBhbmQgdXNlIEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMuXG4gICAgLy8gICAgICAgQ3VycmVudGx5IHdlIGFsbG93IHRoaXMgdG8gaGFwcGVuIHRvIG1ha2UgdGVzdCBydW5uZXIgd29yay5cbiAgICBjb25zdCBzZXNzaW9uID0gbmV3IFNlc3Npb24ob3B0aW9ucyBhcyB1bmtub3duIGFzIFNlc3Npb24uQ29uZmlnKTtcblxuICAgIC8vIHR5cGVzY3JpcHQgY2Fubm90IG1lcmdlIG1ldGhvZCBvdmVycmlkZSBjb3JyZWN0bHkgKHNvIGZhciBpbiA0LjIuMykuIG5lZWQgaWYtZWxzZSB0byBjYWxsIHRoZSBtZXRob2QuXG4gICAgaWYgKHR5cGVvZiBwYXRoT3JCdWZmZXIgPT09ICdzdHJpbmcnKSB7XG4gICAgICBhd2FpdCBzZXNzaW9uLmxvYWRNb2RlbChwYXRoT3JCdWZmZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCBzZXNzaW9uLmxvYWRNb2RlbChwYXRoT3JCdWZmZXIpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgT25ueGpzU2Vzc2lvbkhhbmRsZXIoc2Vzc2lvbik7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IG9ubnhqc0JhY2tlbmQgPSBuZXcgT25ueGpzQmFja2VuZCgpO1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7QmFja2VuZCwgZW52LCBJbmZlcmVuY2VTZXNzaW9uLCBTZXNzaW9uSGFuZGxlcn0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcbmltcG9ydCB7Y3B1c30gZnJvbSAnb3MnO1xuXG5pbXBvcnQge2luaXRXYXNtfSBmcm9tICcuL3dhc20vcHJveHktd3JhcHBlcic7XG5pbXBvcnQge09ubnhydW50aW1lV2ViQXNzZW1ibHlTZXNzaW9uSGFuZGxlcn0gZnJvbSAnLi93YXNtL3Nlc3Npb24taGFuZGxlcic7XG5cbi8qKlxuICogVGhpcyBmdW5jdGlvbiBpbml0aWFsaXplcyBhbGwgZmxhZ3MgZm9yIFdlYkFzc2VtYmx5LlxuICpcbiAqIFRob3NlIGZsYWdzIGFyZSBhY2Nlc3NpYmxlIGZyb20gYG9ydC5lbnYud2FzbWAuIFVzZXJzIGFyZSBhbGxvdyB0byBzZXQgdGhvc2UgZmxhZ3MgYmVmb3JlIHRoZSBmaXJzdCBpbmZlcmVuY2Ugc2Vzc2lvblxuICogYmVpbmcgY3JlYXRlZCwgdG8gb3ZlcnJpZGUgZGVmYXVsdCB2YWx1ZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGluaXRpYWxpemVGbGFncyA9ICgpOiB2b2lkID0+IHtcbiAgaWYgKHR5cGVvZiBlbnYud2FzbS5pbml0VGltZW91dCAhPT0gJ251bWJlcicgfHwgZW52Lndhc20uaW5pdFRpbWVvdXQgPCAwKSB7XG4gICAgZW52Lndhc20uaW5pdFRpbWVvdXQgPSAwO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBlbnYud2FzbS5zaW1kICE9PSAnYm9vbGVhbicpIHtcbiAgICBlbnYud2FzbS5zaW1kID0gdHJ1ZTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgZW52Lndhc20ucHJveHkgIT09ICdib29sZWFuJykge1xuICAgIGVudi53YXNtLnByb3h5ID0gZmFsc2U7XG4gIH1cblxuICBpZiAodHlwZW9mIGVudi53YXNtLm51bVRocmVhZHMgIT09ICdudW1iZXInIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKGVudi53YXNtLm51bVRocmVhZHMpIHx8IGVudi53YXNtLm51bVRocmVhZHMgPD0gMCkge1xuICAgIGNvbnN0IG51bUNwdUxvZ2ljYWxDb3JlcyA9IHR5cGVvZiBuYXZpZ2F0b3IgPT09ICd1bmRlZmluZWQnID8gY3B1cygpLmxlbmd0aCA6IG5hdmlnYXRvci5oYXJkd2FyZUNvbmN1cnJlbmN5O1xuICAgIGVudi53YXNtLm51bVRocmVhZHMgPSBNYXRoLm1pbig0LCBNYXRoLmNlaWwoKG51bUNwdUxvZ2ljYWxDb3JlcyB8fCAxKSAvIDIpKTtcbiAgfVxufTtcblxuY2xhc3MgT25ueHJ1bnRpbWVXZWJBc3NlbWJseUJhY2tlbmQgaW1wbGVtZW50cyBCYWNrZW5kIHtcbiAgYXN5bmMgaW5pdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBwb3B1bGF0ZSB3YXNtIGZsYWdzXG4gICAgaW5pdGlhbGl6ZUZsYWdzKCk7XG5cbiAgICAvLyBpbml0IHdhc21cbiAgICBhd2FpdCBpbml0V2FzbSgpO1xuICB9XG4gIGNyZWF0ZVNlc3Npb25IYW5kbGVyKHBhdGg6IHN0cmluZywgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMpOiBQcm9taXNlPFNlc3Npb25IYW5kbGVyPjtcbiAgY3JlYXRlU2Vzc2lvbkhhbmRsZXIoYnVmZmVyOiBVaW50OEFycmF5LCBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyk6IFByb21pc2U8U2Vzc2lvbkhhbmRsZXI+O1xuICBhc3luYyBjcmVhdGVTZXNzaW9uSGFuZGxlcihwYXRoT3JCdWZmZXI6IHN0cmluZ3xVaW50OEFycmF5LCBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyk6XG4gICAgICBQcm9taXNlPFNlc3Npb25IYW5kbGVyPiB7XG4gICAgY29uc3QgaGFuZGxlciA9IG5ldyBPbm54cnVudGltZVdlYkFzc2VtYmx5U2Vzc2lvbkhhbmRsZXIoKTtcbiAgICBhd2FpdCBoYW5kbGVyLmxvYWRNb2RlbChwYXRoT3JCdWZmZXIsIG9wdGlvbnMpO1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoaGFuZGxlcik7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IHdhc21CYWNrZW5kID0gbmV3IE9ubnhydW50aW1lV2ViQXNzZW1ibHlCYWNrZW5kKCk7XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlcywgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cyAqL1xuLy8gV2UgdXNlIFwicmVxdWlyZVwiIGluc3RlYWQgb2YgXCJpbXBvcnRcIiBoZXJlIGJlY2F1c2UgaW1wb3J0IHN0YXRlbWVudCBtdXN0IGJlIHB1dCBpbiB0b3AgbGV2ZWwuIE91ciBjdXJyZW50IGNvZGUgZG9lc1xuLy8gbm90IGFsbG93IHRlcnNlciB0byB0cmVlLXNoYWtpbmcgY29kZSBhcyBleHBlY3RlZCBiZWNhdXNlIHNvbWUgY29kZXMgYXJlIHRyZWF0ZWQgYXMgaGF2aW5nIHNpZGUgZWZmZWN0cy5cbi8vIFNvIHdlIGltcG9ydCBjb2RlIGluc2lkZSB0aGUgaWYtY2xhdXNlIHRvIGFsbG93IHRlcnNlciByZW1vdmUgdGhlIGNvZGUgc2FmZWx5LlxuXG5leHBvcnQgKiBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuaW1wb3J0IHtyZWdpc3RlckJhY2tlbmR9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmlmICghQlVJTERfREVGUy5ESVNBQkxFX1dFQkdMKSB7XG4gIGNvbnN0IG9ubnhqc0JhY2tlbmQgPSByZXF1aXJlKCcuL2JhY2tlbmQtb25ueGpzJykub25ueGpzQmFja2VuZDtcbiAgcmVnaXN0ZXJCYWNrZW5kKCd3ZWJnbCcsIG9ubnhqc0JhY2tlbmQsIC0xMCk7XG59XG5cbmlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU00pIHtcbiAgY29uc3Qgd2FzbUJhY2tlbmQgPSByZXF1aXJlKCcuL2JhY2tlbmQtd2FzbScpLndhc21CYWNrZW5kO1xuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XRUJHUFUpIHtcbiAgICByZWdpc3RlckJhY2tlbmQoJ3dlYmdwdScsIHdhc21CYWNrZW5kLCA1KTtcbiAgfVxuICByZWdpc3RlckJhY2tlbmQoJ2NwdScsIHdhc21CYWNrZW5kLCAxMCk7XG4gIHJlZ2lzdGVyQmFja2VuZCgnd2FzbScsIHdhc21CYWNrZW5kLCAxMCk7XG4gIHJlZ2lzdGVyQmFja2VuZCgneG5ucGFjaycsIHdhc21CYWNrZW5kLCA5KTtcbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5jbGFzcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXlJbXBsIHtcbiAgY29uc3RydWN0b3IoYXR0cmlidXRlOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikge1xuICAgIE9iamVjdC5hc3NpZ24odGhpcywgYXR0cmlidXRlKTtcbiAgfVxuXG4gIHByaXZhdGUgX2NhY2hlS2V5OiBzdHJpbmc7XG4gIHB1YmxpYyBnZXQgY2FjaGVLZXkoKTogc3RyaW5nIHtcbiAgICBpZiAoIXRoaXMuX2NhY2hlS2V5KSB7XG4gICAgICB0aGlzLl9jYWNoZUtleSA9XG4gICAgICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGhpcykuc29ydCgpLm1hcChuYW1lID0+IGAkeyh0aGlzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVtuYW1lXX1gKS5qb2luKCc7Jyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9jYWNoZUtleTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IGNhY2hlS2V5OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgPSA8VCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+PihhdHRyaWJ1dGU6IFQpOiBUJkF0dHJpYnV0ZVdpdGhDYWNoZUtleSA9PlxuICAgIG5ldyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXlJbXBsKGF0dHJpYnV0ZSkgYXMgdW5rbm93biBhcyBUICYgQXR0cmlidXRlV2l0aENhY2hlS2V5O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCBMb25nIGZyb20gJ2xvbmcnO1xuaW1wb3J0IHtvbm54fSBmcm9tICdvbm54LXByb3RvJztcblxuaW1wb3J0IHtvbm54cnVudGltZX0gZnJvbSAnLi9vcnQtc2NoZW1hL29ydC1nZW5lcmF0ZWQnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4vdGVuc29yJztcbmltcG9ydCB7ZGVjb2RlVXRmOFN0cmluZywgTG9uZ1V0aWx9IGZyb20gJy4vdXRpbCc7XG5cbmltcG9ydCBvcnRGYnMgPSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzO1xuXG5leHBvcnQgZGVjbGFyZSBuYW1lc3BhY2UgQXR0cmlidXRlIHtcbiAgZXhwb3J0IGludGVyZmFjZSBEYXRhVHlwZU1hcCB7XG4gICAgZmxvYXQ6IG51bWJlcjtcbiAgICBpbnQ6IG51bWJlcjtcbiAgICBzdHJpbmc6IHN0cmluZztcbiAgICB0ZW5zb3I6IFRlbnNvcjtcbiAgICBmbG9hdHM6IG51bWJlcltdO1xuICAgIGludHM6IG51bWJlcltdO1xuICAgIHN0cmluZ3M6IHN0cmluZ1tdO1xuICAgIHRlbnNvcnM6IFRlbnNvcltdO1xuICB9XG5cbiAgZXhwb3J0IHR5cGUgRGF0YVR5cGUgPSBrZXlvZiBEYXRhVHlwZU1hcDtcbn1cblxudHlwZSBWYWx1ZVR5cGVzID0gQXR0cmlidXRlLkRhdGFUeXBlTWFwW0F0dHJpYnV0ZS5EYXRhVHlwZV07XG5cbnR5cGUgVmFsdWUgPSBbVmFsdWVUeXBlcywgQXR0cmlidXRlLkRhdGFUeXBlXTtcblxuZXhwb3J0IGNsYXNzIEF0dHJpYnV0ZSB7XG4gIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXM6IG9ubnguSUF0dHJpYnV0ZVByb3RvW118b3J0RmJzLkF0dHJpYnV0ZVtdfG51bGx8dW5kZWZpbmVkKSB7XG4gICAgdGhpcy5fYXR0cmlidXRlcyA9IG5ldyBNYXAoKTtcbiAgICBpZiAoYXR0cmlidXRlcyAhPT0gbnVsbCAmJiBhdHRyaWJ1dGVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGZvciAoY29uc3QgYXR0ciBvZiBhdHRyaWJ1dGVzKSB7XG4gICAgICAgIGlmIChhdHRyIGluc3RhbmNlb2Ygb25ueC5BdHRyaWJ1dGVQcm90bykge1xuICAgICAgICAgIHRoaXMuX2F0dHJpYnV0ZXMuc2V0KGF0dHIubmFtZSwgW0F0dHJpYnV0ZS5nZXRWYWx1ZShhdHRyKSwgQXR0cmlidXRlLmdldFR5cGUoYXR0cildKTtcbiAgICAgICAgfSBlbHNlIGlmIChhdHRyIGluc3RhbmNlb2Ygb3J0RmJzLkF0dHJpYnV0ZSkge1xuICAgICAgICAgIHRoaXMuX2F0dHJpYnV0ZXMuc2V0KGF0dHIubmFtZSgpISwgW0F0dHJpYnV0ZS5nZXRWYWx1ZShhdHRyKSwgQXR0cmlidXRlLmdldFR5cGUoYXR0cildKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHRoaXMuX2F0dHJpYnV0ZXMuc2l6ZSA8IGF0dHJpYnV0ZXMubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZHVwbGljYXRlZCBhdHRyaWJ1dGUgbmFtZXMnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBzZXQoa2V5OiBzdHJpbmcsIHR5cGU6IEF0dHJpYnV0ZS5EYXRhVHlwZSwgdmFsdWU6IFZhbHVlVHlwZXMpOiB2b2lkIHtcbiAgICB0aGlzLl9hdHRyaWJ1dGVzLnNldChrZXksIFt2YWx1ZSwgdHlwZV0pO1xuICB9XG4gIGRlbGV0ZShrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuX2F0dHJpYnV0ZXMuZGVsZXRlKGtleSk7XG4gIH1cbiAgZ2V0RmxvYXQoa2V5OiBzdHJpbmcsIGRlZmF1bHRWYWx1ZT86IEF0dHJpYnV0ZS5EYXRhVHlwZU1hcFsnZmxvYXQnXSkge1xuICAgIHJldHVybiB0aGlzLmdldChrZXksICdmbG9hdCcsIGRlZmF1bHRWYWx1ZSk7XG4gIH1cblxuICBnZXRJbnQoa2V5OiBzdHJpbmcsIGRlZmF1bHRWYWx1ZT86IEF0dHJpYnV0ZS5EYXRhVHlwZU1hcFsnaW50J10pIHtcbiAgICByZXR1cm4gdGhpcy5nZXQoa2V5LCAnaW50JywgZGVmYXVsdFZhbHVlKTtcbiAgfVxuXG4gIGdldFN0cmluZyhrZXk6IHN0cmluZywgZGVmYXVsdFZhbHVlPzogQXR0cmlidXRlLkRhdGFUeXBlTWFwWydzdHJpbmcnXSkge1xuICAgIHJldHVybiB0aGlzLmdldChrZXksICdzdHJpbmcnLCBkZWZhdWx0VmFsdWUpO1xuICB9XG5cbiAgZ2V0VGVuc29yKGtleTogc3RyaW5nLCBkZWZhdWx0VmFsdWU/OiBBdHRyaWJ1dGUuRGF0YVR5cGVNYXBbJ3RlbnNvciddKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KGtleSwgJ3RlbnNvcicsIGRlZmF1bHRWYWx1ZSk7XG4gIH1cblxuICBnZXRGbG9hdHMoa2V5OiBzdHJpbmcsIGRlZmF1bHRWYWx1ZT86IEF0dHJpYnV0ZS5EYXRhVHlwZU1hcFsnZmxvYXRzJ10pIHtcbiAgICByZXR1cm4gdGhpcy5nZXQoa2V5LCAnZmxvYXRzJywgZGVmYXVsdFZhbHVlKTtcbiAgfVxuXG4gIGdldEludHMoa2V5OiBzdHJpbmcsIGRlZmF1bHRWYWx1ZT86IEF0dHJpYnV0ZS5EYXRhVHlwZU1hcFsnaW50cyddKSB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0KGtleSwgJ2ludHMnLCBkZWZhdWx0VmFsdWUpO1xuICB9XG5cbiAgZ2V0U3RyaW5ncyhrZXk6IHN0cmluZywgZGVmYXVsdFZhbHVlPzogQXR0cmlidXRlLkRhdGFUeXBlTWFwWydzdHJpbmdzJ10pIHtcbiAgICByZXR1cm4gdGhpcy5nZXQoa2V5LCAnc3RyaW5ncycsIGRlZmF1bHRWYWx1ZSk7XG4gIH1cblxuICBnZXRUZW5zb3JzKGtleTogc3RyaW5nLCBkZWZhdWx0VmFsdWU/OiBBdHRyaWJ1dGUuRGF0YVR5cGVNYXBbJ3RlbnNvcnMnXSkge1xuICAgIHJldHVybiB0aGlzLmdldChrZXksICd0ZW5zb3JzJywgZGVmYXVsdFZhbHVlKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0PFYgZXh0ZW5kcyBBdHRyaWJ1dGUuRGF0YVR5cGVNYXBbQXR0cmlidXRlLkRhdGFUeXBlXT4oXG4gICAgICBrZXk6IHN0cmluZywgdHlwZTogQXR0cmlidXRlLkRhdGFUeXBlLCBkZWZhdWx0VmFsdWU/OiBWKTogViB7XG4gICAgY29uc3QgdmFsdWVBbmRUeXBlID0gdGhpcy5fYXR0cmlidXRlcy5nZXQoa2V5KTtcbiAgICBpZiAodmFsdWVBbmRUeXBlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChkZWZhdWx0VmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKGByZXF1aXJlZCBhdHRyaWJ1dGUgbm90IGZvdW5kOiAke2tleX1gKTtcbiAgICB9XG4gICAgaWYgKHZhbHVlQW5kVHlwZVsxXSAhPT0gdHlwZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGB0eXBlIG1pc21hdGNoOiBleHBlY3RlZCAke3R5cGV9IGJ1dCBnb3QgJHt2YWx1ZUFuZFR5cGVbMV19YCk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZUFuZFR5cGVbMF0gYXMgVjtcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGdldFR5cGUoYXR0cjogb25ueC5JQXR0cmlidXRlUHJvdG98b3J0RmJzLkF0dHJpYnV0ZSk6IEF0dHJpYnV0ZS5EYXRhVHlwZSB7XG4gICAgY29uc3QgdHlwZSA9IGF0dHIgaW5zdGFuY2VvZiBvbm54LkF0dHJpYnV0ZVByb3RvID8gKGF0dHIpLnR5cGUgOiAoYXR0ciBhcyBvcnRGYnMuQXR0cmlidXRlKS50eXBlKCk7XG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICBjYXNlIG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5GTE9BVDpcbiAgICAgICAgcmV0dXJuICdmbG9hdCc7XG4gICAgICBjYXNlIG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5JTlQ6XG4gICAgICAgIHJldHVybiAnaW50JztcbiAgICAgIGNhc2Ugb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlLlNUUklORzpcbiAgICAgICAgcmV0dXJuICdzdHJpbmcnO1xuICAgICAgY2FzZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuVEVOU09SOlxuICAgICAgICByZXR1cm4gJ3RlbnNvcic7XG4gICAgICBjYXNlIG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5GTE9BVFM6XG4gICAgICAgIHJldHVybiAnZmxvYXRzJztcbiAgICAgIGNhc2Ugb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlLklOVFM6XG4gICAgICAgIHJldHVybiAnaW50cyc7XG4gICAgICBjYXNlIG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5TVFJJTkdTOlxuICAgICAgICByZXR1cm4gJ3N0cmluZ3MnO1xuICAgICAgY2FzZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuVEVOU09SUzpcbiAgICAgICAgcmV0dXJuICd0ZW5zb3JzJztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgYXR0cmlidXRlIHR5cGUgaXMgbm90IHN1cHBvcnRlZCB5ZXQ6ICR7b25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlW3R5cGVdfWApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGdldFZhbHVlKGF0dHI6IG9ubnguSUF0dHJpYnV0ZVByb3RvfG9ydEZicy5BdHRyaWJ1dGUpIHtcbiAgICBjb25zdCBhdHRyVHlwZSA9IGF0dHIgaW5zdGFuY2VvZiBvbm54LkF0dHJpYnV0ZVByb3RvID8gYXR0ci50eXBlIDogKGF0dHIgYXMgb3J0RmJzLkF0dHJpYnV0ZSkudHlwZSgpO1xuICAgIGlmIChhdHRyVHlwZSA9PT0gb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlLkdSQVBIIHx8IGF0dHJUeXBlID09PSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuR1JBUEhTKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2dyYXBoIGF0dHJpYnV0ZSBpcyBub3Qgc3VwcG9ydGVkIHlldCcpO1xuICAgIH1cblxuICAgIGNvbnN0IHZhbHVlID0gdGhpcy5nZXRWYWx1ZU5vQ2hlY2soYXR0cik7XG5cbiAgICAvLyBjYXN0IExPTkcgdG8gbnVtYmVyXG4gICAgaWYgKGF0dHJUeXBlID09PSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuSU5UICYmIExvbmdVdGlsLmlzTG9uZyh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBMb25nVXRpbC5sb25nVG9OdW1iZXIodmFsdWUgYXMgTG9uZyB8IGZsYXRidWZmZXJzLkxvbmcpO1xuICAgIH1cblxuICAgIC8vIGNhc3QgTE9OR1tdIHRvIG51bWJlcltdXG4gICAgaWYgKGF0dHJUeXBlID09PSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuSU5UUykge1xuICAgICAgY29uc3QgYXJyID0gKHZhbHVlIGFzIEFycmF5PG51bWJlcnxMb25nfGZsYXRidWZmZXJzLkxvbmc+KTtcbiAgICAgIGNvbnN0IG51bWJlclZhbHVlOiBudW1iZXJbXSA9IG5ldyBBcnJheTxudW1iZXI+KGFyci5sZW5ndGgpO1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBtYXliZUxvbmcgPSBhcnJbaV07XG4gICAgICAgIG51bWJlclZhbHVlW2ldID0gTG9uZ1V0aWwubG9uZ1RvTnVtYmVyKG1heWJlTG9uZyk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBudW1iZXJWYWx1ZTtcbiAgICB9XG5cbiAgICAvLyBjYXN0IG9ubnguVGVuc29yUHJvdG8gdG8gb25ueGpzLlRlbnNvclxuICAgIGlmIChhdHRyVHlwZSA9PT0gb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlLlRFTlNPUikge1xuICAgICAgcmV0dXJuIGF0dHIgaW5zdGFuY2VvZiBvbm54LkF0dHJpYnV0ZVByb3RvID8gVGVuc29yLmZyb21Qcm90byh2YWx1ZSBhcyBvbm54LklUZW5zb3JQcm90bykgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVGVuc29yLmZyb21PcnRUZW5zb3IodmFsdWUgYXMgb3J0RmJzLlRlbnNvcik7XG4gICAgfVxuXG4gICAgLy8gY2FzdCBvbm54LlRlbnNvclByb3RvW10gdG8gb25ueGpzLlRlbnNvcltdXG4gICAgaWYgKGF0dHJUeXBlID09PSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuVEVOU09SUykge1xuICAgICAgaWYgKGF0dHIgaW5zdGFuY2VvZiBvbm54LkF0dHJpYnV0ZVByb3RvKSB7XG4gICAgICAgIGNvbnN0IHRlbnNvclByb3RvcyA9IHZhbHVlIGFzIG9ubnguSVRlbnNvclByb3RvW107XG4gICAgICAgIHJldHVybiB0ZW5zb3JQcm90b3MubWFwKHZhbHVlID0+IFRlbnNvci5mcm9tUHJvdG8odmFsdWUpKTtcbiAgICAgIH0gZWxzZSBpZiAoYXR0ciBpbnN0YW5jZW9mIG9ydEZicy5BdHRyaWJ1dGUpIHtcbiAgICAgICAgY29uc3QgdGVuc29yUHJvdG9zID0gdmFsdWUgYXMgb3J0RmJzLlRlbnNvcltdO1xuICAgICAgICByZXR1cm4gdGVuc29yUHJvdG9zLm1hcCh2YWx1ZSA9PiBUZW5zb3IuZnJvbU9ydFRlbnNvcih2YWx1ZSkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNhc3QgVWludDhBcnJheSB0byBzdHJpbmdcbiAgICBpZiAoYXR0clR5cGUgPT09IG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5TVFJJTkcpIHtcbiAgICAgIC8vIHN0cmluZyBpbiBvbm54IGF0dHJpYnV0ZSBpcyBvZiB1aW50OGFycmF5IHR5cGUsIHNvIHdlIG5lZWQgdG8gY29udmVydCBpdCB0byBzdHJpbmcgYmVsb3cuIFdoaWxlIGluIG9ydCBmb3JtYXQsXG4gICAgICAvLyBzdHJpbmcgYXR0cmlidXRlcyBhcmUgcmV0dXJuZWQgYXMgc3RyaW5nLCBzbyBubyBjb252ZXJzaW9uIGlzIG5lZWRlZC5cbiAgICAgIGlmIChhdHRyIGluc3RhbmNlb2Ygb25ueC5BdHRyaWJ1dGVQcm90bykge1xuICAgICAgICBjb25zdCB1dGY4U3RyaW5nID0gdmFsdWUgYXMgVWludDhBcnJheTtcbiAgICAgICAgcmV0dXJuIGRlY29kZVV0ZjhTdHJpbmcodXRmOFN0cmluZyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gY2FzdCBVaW50OEFycmF5W10gdG8gc3RyaW5nW11cbiAgICBpZiAoYXR0clR5cGUgPT09IG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5TVFJJTkdTKSB7XG4gICAgICAvLyBzdHJpbmdzIGluIG9ubnggYXR0cmlidXRlIGlzIHJldHVybmVkIGFzIHVpbnQ4YXJyYXlbXSwgc28gd2UgbmVlZCB0byBjb252ZXJ0IGl0IHRvIHN0cmluZ1tdIGJlbG93LiBXaGlsZSBpbiBvcnRcbiAgICAgIC8vIGZvcm1hdCBzdHJpbmdzIGF0dHJpYnV0ZXMgYXJlIHJldHVybmVkIGFzIHN0cmluZ1tdLCBzbyBubyBjb252ZXJzaW9uIGlzIG5lZWRlZC5cbiAgICAgIGlmIChhdHRyIGluc3RhbmNlb2Ygb25ueC5BdHRyaWJ1dGVQcm90bykge1xuICAgICAgICBjb25zdCB1dGY4U3RyaW5ncyA9IHZhbHVlIGFzIFVpbnQ4QXJyYXlbXTtcbiAgICAgICAgcmV0dXJuIHV0ZjhTdHJpbmdzLm1hcChkZWNvZGVVdGY4U3RyaW5nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUgYXMgVmFsdWVUeXBlcztcbiAgfVxuXG4gIHByaXZhdGUgc3RhdGljIGdldFZhbHVlTm9DaGVjayhhdHRyOiBvbm54LklBdHRyaWJ1dGVQcm90b3xvcnRGYnMuQXR0cmlidXRlKSB7XG4gICAgcmV0dXJuIGF0dHIgaW5zdGFuY2VvZiAob25ueC5BdHRyaWJ1dGVQcm90bykgPyB0aGlzLmdldFZhbHVlTm9DaGVja0Zyb21Pbm54Rm9ybWF0KGF0dHIpIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ2V0VmFsdWVOb0NoZWNrRnJvbU9ydEZvcm1hdChhdHRyIGFzIG9ydEZicy5BdHRyaWJ1dGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0VmFsdWVOb0NoZWNrRnJvbU9ubnhGb3JtYXQoYXR0cjogb25ueC5JQXR0cmlidXRlUHJvdG8pIHtcbiAgICBzd2l0Y2ggKGF0dHIudHlwZSEpIHtcbiAgICAgIGNhc2Ugb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlLkZMT0FUOlxuICAgICAgICByZXR1cm4gYXR0ci5mO1xuICAgICAgY2FzZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuSU5UOlxuICAgICAgICByZXR1cm4gYXR0ci5pO1xuICAgICAgY2FzZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuU1RSSU5HOlxuICAgICAgICByZXR1cm4gYXR0ci5zO1xuICAgICAgY2FzZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuVEVOU09SOlxuICAgICAgICByZXR1cm4gYXR0ci50O1xuICAgICAgY2FzZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuR1JBUEg6XG4gICAgICAgIHJldHVybiBhdHRyLmc7XG4gICAgICBjYXNlIG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5GTE9BVFM6XG4gICAgICAgIHJldHVybiBhdHRyLmZsb2F0cztcbiAgICAgIGNhc2Ugb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlLklOVFM6XG4gICAgICAgIHJldHVybiBhdHRyLmludHM7XG4gICAgICBjYXNlIG9ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZS5TVFJJTkdTOlxuICAgICAgICByZXR1cm4gYXR0ci5zdHJpbmdzO1xuICAgICAgY2FzZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGUuVEVOU09SUzpcbiAgICAgICAgcmV0dXJuIGF0dHIudGVuc29ycztcbiAgICAgIGNhc2Ugb25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlLkdSQVBIUzpcbiAgICAgICAgcmV0dXJuIGF0dHIuZ3JhcGhzO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBhdHRyaWJ1dGUgdHlwZTogJHtvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGVbYXR0ci50eXBlIV19YCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgZ2V0VmFsdWVOb0NoZWNrRnJvbU9ydEZvcm1hdChhdHRyOiBvcnRGYnMuQXR0cmlidXRlKSB7XG4gICAgc3dpdGNoIChhdHRyLnR5cGUoKSkge1xuICAgICAgY2FzZSBvcnRGYnMuQXR0cmlidXRlVHlwZS5GTE9BVDpcbiAgICAgICAgcmV0dXJuIGF0dHIuZigpO1xuICAgICAgY2FzZSBvcnRGYnMuQXR0cmlidXRlVHlwZS5JTlQ6XG4gICAgICAgIHJldHVybiBhdHRyLmkoKTtcbiAgICAgIGNhc2Ugb3J0RmJzLkF0dHJpYnV0ZVR5cGUuU1RSSU5HOlxuICAgICAgICByZXR1cm4gYXR0ci5zKCk7XG4gICAgICBjYXNlIG9ydEZicy5BdHRyaWJ1dGVUeXBlLlRFTlNPUjpcbiAgICAgICAgcmV0dXJuIGF0dHIudCgpO1xuICAgICAgY2FzZSBvcnRGYnMuQXR0cmlidXRlVHlwZS5HUkFQSDpcbiAgICAgICAgcmV0dXJuIGF0dHIuZygpO1xuICAgICAgY2FzZSBvcnRGYnMuQXR0cmlidXRlVHlwZS5GTE9BVFM6XG4gICAgICAgIHJldHVybiBhdHRyLmZsb2F0c0FycmF5KCk7XG4gICAgICBjYXNlIG9ydEZicy5BdHRyaWJ1dGVUeXBlLklOVFM6IHtcbiAgICAgICAgY29uc3QgaW50cyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF0dHIuaW50c0xlbmd0aCgpOyBpKyspIHtcbiAgICAgICAgICBpbnRzLnB1c2goYXR0ci5pbnRzKGkpISk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGludHM7XG4gICAgICB9XG4gICAgICBjYXNlIG9ydEZicy5BdHRyaWJ1dGVUeXBlLlNUUklOR1M6IHtcbiAgICAgICAgY29uc3Qgc3RyaW5ncyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGF0dHIuc3RyaW5nc0xlbmd0aCgpOyBpKyspIHtcbiAgICAgICAgICBzdHJpbmdzLnB1c2goYXR0ci5zdHJpbmdzKGkpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyaW5ncztcbiAgICAgIH1cbiAgICAgIGNhc2Ugb3J0RmJzLkF0dHJpYnV0ZVR5cGUuVEVOU09SUzoge1xuICAgICAgICBjb25zdCB0ZW5zb3JzID0gW107XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXR0ci50ZW5zb3JzTGVuZ3RoKCk7IGkrKykge1xuICAgICAgICAgIHRlbnNvcnMucHVzaChhdHRyLnRlbnNvcnMoaSkhKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGVuc29ycztcbiAgICAgIH1cbiAgICAgIC8vIGNhc2Ugb3J0RmJzLkF0dHJpYnV0ZVR5cGUuR1JBUEhTOlxuICAgICAgLy8gVE9ETzogU3ViZ3JhcGggbm90IHN1cHBvcnRlZCB5ZXQuXG4gICAgICAvLyBjb25zdCBncmFwaHMgPSBbXTtcbiAgICAgIC8vIGZvciAobGV0IGkgPSAwOyBpIDwgYXR0ci5ncmFwaHNMZW5ndGgoKTsgaSsrKSB7XG4gICAgICAvLyAgIGdyYXBocy5wdXNoKGF0dHIuZ3JhcGhzKGkpISk7XG4gICAgICAvLyB9XG4gICAgICAvLyByZXR1cm4gZ3JhcGhzO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBhdHRyaWJ1dGUgdHlwZTogJHtvcnRGYnMuQXR0cmlidXRlVHlwZVthdHRyLnR5cGUoKV19YCk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIF9hdHRyaWJ1dGVzOiBNYXA8c3RyaW5nLCBWYWx1ZT47XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtXZWJHTEJhY2tlbmR9IGZyb20gJy4vYmFja2VuZHMvYmFja2VuZC13ZWJnbCc7XG5pbXBvcnQge0dyYXBofSBmcm9tICcuL2dyYXBoJztcbmltcG9ydCB7T3BlcmF0b3J9IGZyb20gJy4vb3BlcmF0b3JzJztcbmltcG9ydCB7T3BTZXR9IGZyb20gJy4vb3BzZXQnO1xuaW1wb3J0IHtTZXNzaW9ufSBmcm9tICcuL3Nlc3Npb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIEluZmVyZW5jZUhhbmRsZXIge1xuICAvKipcbiAgICogZGlzcG9zZSB0aGUgaW5mZXJlbmNlIGhhbmRsZXIuIGl0IHdpbGwgYmUgY2FsbGVkIGFzIHRoZSBsYXN0IHN0ZXAgaW4gU2Vzc2lvbi5ydW4oKVxuICAgKi9cbiAgZGlzcG9zZSgpOiB2b2lkO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNlc3Npb25IYW5kbGVyIHtcbiAgLyoqXG4gICAqIHRyYW5zZm9ybSB0aGUgZ3JhcGggYXQgaW5pdGlhbGl6YXRpb24gdGltZVxuICAgKiBAcGFyYW0gZ3JhcGhUcmFuc2Zvcm1lciB0aGUgZ3JhcGggdHJhbnNmb3JtZXIgdG8gbWFuaXB1bGF0ZSB0aGUgbW9kZWwgZ3JhcGhcbiAgICovXG4gIHRyYW5zZm9ybUdyYXBoPyhncmFwaFRyYW5zZm9ybWVyOiBHcmFwaC5UcmFuc2Zvcm1lcik6IHZvaWQ7XG5cbiAgLyoqXG4gICAqIGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiBJbmZlcmVuY2VIYW5kbGVyIHRvIHVzZSBpbiBhIFNlc3Npb24ucnVuKCkgY2FsbFxuICAgKi9cbiAgY3JlYXRlSW5mZXJlbmNlSGFuZGxlcigpOiBJbmZlcmVuY2VIYW5kbGVyO1xuXG4gIC8qKlxuICAgKiBkaXNwb3NlIHRoZSBzZXNzaW9uIGhhbmRsZXIuIGl0IHdpbGwgYmUgY2FsbGVkIHdoZW4gYSBzZXNzaW9uIGlzIGJlaW5nIGRpc3Bvc2VkIGV4cGxpY2l0bHlcbiAgICovXG4gIGRpc3Bvc2UoKTogdm9pZDtcblxuICAvKipcbiAgICogUmVzb2x2ZXMgdGhlIG9wZXJhdG9yIGZyb20gdGhlIG5hbWUgYW5kIG9wc2V0IHZlcnNpb247IGJhY2tlbmQgc3BlY2lmaWNcbiAgICogQHBhcmFtIG5vZGUgdGhlIG5vZGUgdG8gcmVzb2x2ZVxuICAgKiBAcGFyYW0gb3BzZXRzIGEgbGlzdCBvZiBvcHNldHMgdGhhdCBleHBvcnRlZCBmcm9tIHRoZSBtb2RlbFxuICAgKiBAcGFyYW0gZ3JhcGggdGhlIGNvbXBsZXRlbHkgaW5pdGlhbGl6ZWQgZ3JhcGhcbiAgICovXG4gIHJlc29sdmUobm9kZTogR3JhcGguTm9kZSwgb3BzZXRzOiByZWFkb25seSBPcFNldFtdLCBncmFwaDogR3JhcGgpOiBPcGVyYXRvcjtcblxuICAvKipcbiAgICogVGhpcyBtZXRob2QgbGV0J3MgdGhlIHNlc3Npb25IYW5kbGVyIGtub3cgdGhhdCB0aGUgZ3JhcGggaW5pdGlhbGl6YXRpb24gaXMgY29tcGxldGVcbiAgICogQHBhcmFtIGdyYXBoIHRoZSBjb21wbGV0ZWx5IGluaXRpYWxpemVkIGdyYXBoXG4gICAqL1xuICBvbkdyYXBoSW5pdGlhbGl6ZWQ/KGdyYXBoOiBHcmFwaCk6IHZvaWQ7XG5cbiAgLyoqXG4gICAqIGEgcmVmZXJlbmNlIHRvIHRoZSBjb3JyZXNwb25kaW5nIGJhY2tlbmRcbiAgICovXG4gIHJlYWRvbmx5IGJhY2tlbmQ6IEJhY2tlbmQ7XG5cbiAgLyoqXG4gICAqIGEgcmVmZXJlbmNlIHRvIHRoZSBzZXNzaW9uIGNvbnRleHRcbiAgICovXG4gIHJlYWRvbmx5IGNvbnRleHQ6IFNlc3Npb24uQ29udGV4dDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCYWNrZW5kIHtcbiAgLyoqXG4gICAqIGluaXRpYWxpemUgdGhlIGJhY2tlbmQuIHdpbGwgYmUgY2FsbGVkIG9ubHkgb25jZSwgd2hlbiB0aGUgZmlyc3QgdGltZSB0aGVcbiAgICogYmFja2VuZCBpdCB0byBiZSB1c2VkXG4gICAqL1xuICBpbml0aWFsaXplKCk6IGJvb2xlYW58UHJvbWlzZTxib29sZWFuPjtcblxuICAvKipcbiAgICogY3JlYXRlIGFuIGluc3RhbmNlIG9mIFNlc3Npb25IYW5kbGVyIHRvIHVzZSBpbiBhIFNlc3Npb24gb2JqZWN0J3MgbGlmZWN5Y2xlXG4gICAqL1xuICBjcmVhdGVTZXNzaW9uSGFuZGxlcihjb250ZXh0OiBTZXNzaW9uLkNvbnRleHQpOiBTZXNzaW9uSGFuZGxlcjtcblxuICAvKipcbiAgICogZGlzcG9zZSB0aGUgYmFja2VuZC4gY3VycmVudGx5IHRoaXMgd2lsbCBub3QgYmUgY2FsbGVkXG4gICAqL1xuICBkaXNwb3NlKCk6IHZvaWQ7XG59XG5cbi8vIGNhY2hlcyBhbGwgaW5pdGlhbGl6ZWQgYmFja2VuZCBpbnN0YW5jZXNcbmNvbnN0IGJhY2tlbmRzQ2FjaGU6IE1hcDxzdHJpbmcsIEJhY2tlbmQ+ID0gbmV3IE1hcCgpO1xuXG5leHBvcnQgY29uc3QgYmFja2VuZDoge1tuYW1lOiBzdHJpbmddOiBCYWNrZW5kfSA9IHtcbiAgd2ViZ2w6IG5ldyBXZWJHTEJhY2tlbmQoKVxufTtcblxuLyoqXG4gKiBSZXNvbHZlIGEgcmVmZXJlbmNlIHRvIHRoZSBiYWNrZW5kLiBJZiBhIGhpbnQgaXMgc3BlY2lmaWVkLCB0aGUgY29ycmVzcG9uZGluZ1xuICogYmFja2VuZCB3aWxsIGJlIHVzZWQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlQmFja2VuZChoaW50Pzogc3RyaW5nfHJlYWRvbmx5IHN0cmluZ1tdKTogUHJvbWlzZTxCYWNrZW5kPiB7XG4gIGlmICghaGludCkge1xuICAgIHJldHVybiByZXNvbHZlQmFja2VuZChbJ3dlYmdsJ10pO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IGhpbnRzID0gdHlwZW9mIGhpbnQgPT09ICdzdHJpbmcnID8gW2hpbnRdIDogaGludDtcblxuICAgIGZvciAoY29uc3QgYmFja2VuZEhpbnQgb2YgaGludHMpIHtcbiAgICAgIGNvbnN0IGNhY2hlID0gYmFja2VuZHNDYWNoZS5nZXQoYmFja2VuZEhpbnQpO1xuICAgICAgaWYgKGNhY2hlKSB7XG4gICAgICAgIHJldHVybiBjYWNoZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgYmFja2VuZCA9IGF3YWl0IHRyeUxvYWRCYWNrZW5kKGJhY2tlbmRIaW50KTtcbiAgICAgIGlmIChiYWNrZW5kKSB7XG4gICAgICAgIHJldHVybiBiYWNrZW5kO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignbm8gYXZhaWxhYmxlIGJhY2tlbmQgdG8gdXNlJyk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHRyeUxvYWRCYWNrZW5kKGJhY2tlbmRIaW50OiBzdHJpbmcpOiBQcm9taXNlPEJhY2tlbmR8dW5kZWZpbmVkPiB7XG4gIGNvbnN0IGJhY2tlbmRPYmogPSBiYWNrZW5kO1xuXG4gIGlmICh0eXBlb2YgYmFja2VuZE9ialtiYWNrZW5kSGludF0gIT09ICd1bmRlZmluZWQnICYmIGlzQmFja2VuZChiYWNrZW5kT2JqW2JhY2tlbmRIaW50XSkpIHtcbiAgICBjb25zdCBiYWNrZW5kID0gYmFja2VuZE9ialtiYWNrZW5kSGludF07XG4gICAgbGV0IGluaXQgPSBiYWNrZW5kLmluaXRpYWxpemUoKTtcbiAgICBpZiAodHlwZW9mIGluaXQgPT09ICdvYmplY3QnICYmICd0aGVuJyBpbiBpbml0KSB7XG4gICAgICBpbml0ID0gYXdhaXQgaW5pdDtcbiAgICB9XG4gICAgaWYgKGluaXQpIHtcbiAgICAgIGJhY2tlbmRzQ2FjaGUuc2V0KGJhY2tlbmRIaW50LCBiYWNrZW5kKTtcbiAgICAgIHJldHVybiBiYWNrZW5kO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIGlzQmFja2VuZChvYmo6IHVua25vd24pIHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgY29uc3QgbyA9IG9iaiBhcyBhbnk7XG5cbiAgLy8gY2hlY2sgaWYgYW4gb2JqZWN0IGlzIGEgQmFja2VuZCBpbnN0YW5jZVxuICBpZiAoXG4gICAgICAnaW5pdGlhbGl6ZScgaW4gbyAmJiB0eXBlb2Ygby5pbml0aWFsaXplID09PSAnZnVuY3Rpb24nICYmICAgICAgICAgICAgICAgICAgICAgIC8vIGluaXRpYWxpemUoKVxuICAgICAgJ2NyZWF0ZVNlc3Npb25IYW5kbGVyJyBpbiBvICYmIHR5cGVvZiBvLmNyZWF0ZVNlc3Npb25IYW5kbGVyID09PSAnZnVuY3Rpb24nICYmICAvLyBjcmVhdGVTZXNzaW9uSGFuZGxlcigpXG4gICAgICAnZGlzcG9zZScgaW4gbyAmJiB0eXBlb2Ygby5kaXNwb3NlID09PSAnZnVuY3Rpb24nICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGRpc3Bvc2UoKVxuICApIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZXhwb3J0IHR5cGUgQmFja2VuZFR5cGUgPSBCYWNrZW5kO1xuZXhwb3J0IHR5cGUgU2Vzc2lvbkhhbmRsZXJUeXBlID0gUmV0dXJuVHlwZTxCYWNrZW5kVHlwZVsnY3JlYXRlU2Vzc2lvbkhhbmRsZXInXT47XG5leHBvcnQgdHlwZSBJbmZlcmVuY2VIYW5kbGVyVHlwZSA9IFJldHVyblR5cGU8U2Vzc2lvbkhhbmRsZXJUeXBlWydjcmVhdGVJbmZlcmVuY2VIYW5kbGVyJ10+O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7ZW52fSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQge0JhY2tlbmQsIFNlc3Npb25IYW5kbGVyfSBmcm9tICcuLi9iYWNrZW5kJztcbmltcG9ydCB7TG9nZ2VyfSBmcm9tICcuLi9pbnN0cnVtZW50JztcbmltcG9ydCB7U2Vzc2lvbn0gZnJvbSAnLi4vc2Vzc2lvbic7XG5cbmltcG9ydCB7V2ViR0xTZXNzaW9uSGFuZGxlcn0gZnJvbSAnLi93ZWJnbC9zZXNzaW9uLWhhbmRsZXInO1xuaW1wb3J0IHtXZWJHTENvbnRleHR9IGZyb20gJy4vd2ViZ2wvd2ViZ2wtY29udGV4dCc7XG5pbXBvcnQge2NyZWF0ZVdlYkdMQ29udGV4dH0gZnJvbSAnLi93ZWJnbC93ZWJnbC1jb250ZXh0LWZhY3RvcnknO1xuXG4vKipcbiAqIFdlYkdMQmFja2VuZCBpcyB0aGUgZW50cnkgcG9pbnQgZm9yIGFsbCBXZWJHTCBvcGVhcnRpb25zXG4gKiBXaGVuIGl0IHN0YXJ0cyBpdCBjcmVhdGVkIHRoZSBXZWJHTFJlbmRlcmluZ0NvbnRleHRcbiAqIGFuZCBvdGhlciBtYWluIGZyYW1ld29yayBjb21wb25lbnRzIHN1Y2ggYXMgUHJvZ3JhbSBhbmQgVGV4dHVyZSBNYW5hZ2Vyc1xuICovXG5leHBvcnQgY2xhc3MgV2ViR0xCYWNrZW5kIGltcGxlbWVudHMgQmFja2VuZCB7XG4gIGdsQ29udGV4dDogV2ViR0xDb250ZXh0O1xuXG4gIGdldCBjb250ZXh0SWQoKTogJ3dlYmdsJ3wnd2ViZ2wyJ3x1bmRlZmluZWQge1xuICAgIHJldHVybiBlbnYud2ViZ2wuY29udGV4dElkO1xuICB9XG4gIHNldCBjb250ZXh0SWQodmFsdWU6ICd3ZWJnbCd8J3dlYmdsMid8dW5kZWZpbmVkKSB7XG4gICAgZW52LndlYmdsLmNvbnRleHRJZCA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0IG1hdG11bE1heEJhdGNoU2l6ZSgpOiBudW1iZXJ8dW5kZWZpbmVkIHtcbiAgICByZXR1cm4gZW52LndlYmdsLm1hdG11bE1heEJhdGNoU2l6ZTtcbiAgfVxuICBzZXQgbWF0bXVsTWF4QmF0Y2hTaXplKHZhbHVlOiBudW1iZXJ8dW5kZWZpbmVkKSB7XG4gICAgZW52LndlYmdsLm1hdG11bE1heEJhdGNoU2l6ZSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0IHRleHR1cmVDYWNoZU1vZGUoKTogJ2luaXRpYWxpemVyT25seSd8J2Z1bGwnfHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIGVudi53ZWJnbC50ZXh0dXJlQ2FjaGVNb2RlO1xuICB9XG4gIHNldCB0ZXh0dXJlQ2FjaGVNb2RlKHZhbHVlOiAnaW5pdGlhbGl6ZXJPbmx5J3wnZnVsbCd8dW5kZWZpbmVkKSB7XG4gICAgZW52LndlYmdsLnRleHR1cmVDYWNoZU1vZGUgPSB2YWx1ZTtcbiAgfVxuXG4gIGdldCBwYWNrKCk6IGJvb2xlYW58dW5kZWZpbmVkIHtcbiAgICByZXR1cm4gZW52LndlYmdsLnBhY2s7XG4gIH1cbiAgc2V0IHBhY2sodmFsdWU6IGJvb2xlYW58dW5kZWZpbmVkKSB7XG4gICAgZW52LndlYmdsLnBhY2sgPSB2YWx1ZTtcbiAgfVxuXG4gIGdldCBhc3luYygpOiBib29sZWFufHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIGVudi53ZWJnbC5hc3luYztcbiAgfVxuICBzZXQgYXN5bmModmFsdWU6IGJvb2xlYW58dW5kZWZpbmVkKSB7XG4gICAgZW52LndlYmdsLmFzeW5jID0gdmFsdWU7XG4gIH1cblxuICBpbml0aWFsaXplKCk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICB0aGlzLmdsQ29udGV4dCA9IGNyZWF0ZVdlYkdMQ29udGV4dCh0aGlzLmNvbnRleHRJZCk7XG4gICAgICBpZiAodHlwZW9mIHRoaXMubWF0bXVsTWF4QmF0Y2hTaXplICE9PSAnbnVtYmVyJykge1xuICAgICAgICB0aGlzLm1hdG11bE1heEJhdGNoU2l6ZSA9IDE2O1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiB0aGlzLnRleHR1cmVDYWNoZU1vZGUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRoaXMudGV4dHVyZUNhY2hlTW9kZSA9ICdmdWxsJztcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgdGhpcy5wYWNrICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgdGhpcy5wYWNrID0gZmFsc2U7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHRoaXMuYXN5bmMgIT09ICdib29sZWFuJykge1xuICAgICAgICB0aGlzLmFzeW5jID0gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIExvZ2dlci5zZXRXaXRoRW52KGVudik7XG5cbiAgICAgIExvZ2dlci52ZXJib3NlKFxuICAgICAgICAgICdXZWJHTEJhY2tlbmQnLFxuICAgICAgICAgIGBDcmVhdGVkIFdlYkdMQ29udGV4dDogJHt0eXBlb2YgdGhpcy5nbENvbnRleHR9IHdpdGggbWF0bXVsTWF4QmF0Y2hTaXplOiAke1xuICAgICAgICAgICAgICB0aGlzLm1hdG11bE1heEJhdGNoU2l6ZX07IHRleHR1cmVDYWNoZU1vZGU6ICR7dGhpcy50ZXh0dXJlQ2FjaGVNb2RlfTsgcGFjazogJHt0aGlzLnBhY2t9OyBhc3luYzogJHtcbiAgICAgICAgICAgICAgdGhpcy5hc3luY30uYCk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBMb2dnZXIud2FybmluZygnV2ViR0xCYWNrZW5kJywgYFVuYWJsZSB0byBpbml0aWFsaXplIFdlYkdMQmFja2VuZC4gJHtlfWApO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICBjcmVhdGVTZXNzaW9uSGFuZGxlcihjb250ZXh0OiBTZXNzaW9uLkNvbnRleHQpOiBTZXNzaW9uSGFuZGxlciB7XG4gICAgcmV0dXJuIG5ldyBXZWJHTFNlc3Npb25IYW5kbGVyKHRoaXMsIGNvbnRleHQpO1xuICB9XG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgdGhpcy5nbENvbnRleHQuZGlzcG9zZSgpO1xuICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtBcnJheVV0aWwsIEJyb2FkY2FzdFV0aWwsIFNoYXBlVXRpbH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5cbmltcG9ydCB7R2xzbENvbnRleHQsIEdsc2xMaWIsIEdsc2xMaWJSb3V0aW5lfSBmcm9tICcuL2dsc2wtZGVmaW5pdGlvbnMnO1xuaW1wb3J0IHtnZXRHbHNsfSBmcm9tICcuL2dsc2wtc291cmNlJztcbmltcG9ydCB7c3F1ZWV6ZVNoYXBlfSBmcm9tICcuL3RleHR1cmUtbGF5b3V0LXN0cmF0ZWd5JztcbmltcG9ydCB7VGV4dHVyZUxheW91dH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQge2dlbmVyYXRlU2hhZGVyRnVuY05hbWVGcm9tSW5wdXRTYW1wbGVyTmFtZSwgZ2VuZXJhdGVTaGFkZXJGdW5jTmFtZUZyb21JbnB1dFNhbXBsZXJOYW1lQXRPdXRDb29yZHMsIGdldENvb3Jkc0RhdGFUeXBlLCBnZXRHbENoYW5uZWxzLCBnZXRTcXVlZXplZFBhcmFtcywgc3F1ZWV6ZUlucHV0U2hhcGV9IGZyb20gJy4vdXRpbHMnO1xuXG4vKipcbiAqIEdMU0wgTGlicmFyeSByZXNwb25zaWJsZSBmb3IgZGF0YSB0eXBlcyBhbmQgcm91dGluZXMgZm9yIG1hbmlwdWxhdGluZ1xuICogY29vcmRpbmF0ZXMgYW5kIG1hcHBpbmcgdG8vZnJvbSB0ZW5zb3IgaW5kaWNlc1xuICovXG5leHBvcnQgY2xhc3MgQ29vcmRzR2xzbExpYiBleHRlbmRzIEdsc2xMaWIge1xuICByZXR1cm5UeXBlOiBzdHJpbmc7XG5cbiAgY29uc3RydWN0b3IoY29udGV4dDogR2xzbENvbnRleHQpIHtcbiAgICBzdXBlcihjb250ZXh0KTtcbiAgfVxuICBnZXRGdW5jdGlvbnMoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIHJldHVybiB7XG4gICAgICAuLi50aGlzLm9mZnNldFRvQ29vcmRzKCksXG4gICAgICAuLi50aGlzLmNvb3Jkc1RvT2Zmc2V0KCksXG4gICAgICAuLi50aGlzLnRvVmVjKCksXG4gICAgICAuLi50aGlzLnZhbHVlRnJvbSgpLFxuICAgICAgLy8gVE9ETyByZXR1cm4gdGhlc2Ugb25seSB3aGVuIHBhY2tpbmcgaXMgZW5hYmxlZC5cbiAgICAgIC4uLnRoaXMuZ2V0Q29tbW9uVXRpbEZ1bmNzKCksXG4gICAgICAuLi50aGlzLmdldElucHV0c1NhbXBsaW5nU25pcHBldHMoKSxcbiAgICAgIC4uLnRoaXMuZ2V0T3V0cHV0U2FtcGxpbmdTbmlwcGV0KClcbiAgICB9O1xuICB9XG4gIGdldEN1c3RvbVR5cGVzKCkge1xuICAgIHJldHVybiB7fTtcbiAgfVxuICAvKipcbiAgICogUHJvZHVjZXMgYSBmdW5jdGlvbiB0aGF0IGNhbiBtYXAgZnJvbVxuICAgKiAyRCBub3JtYWx6aWVkIGNvb3JkaW5hdGVzIChzLHQpIHRvIGEgZmxhdCBvZmZzZXRcbiAgICovXG4gIHByb3RlY3RlZCBvZmZzZXRUb0Nvb3JkcygpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgY29uc3QgZnVuY05hbWUgPSAnb2Zmc2V0VG9Db29yZHMnO1xuICAgIHJldHVybiB7XG4gICAgICBvZmZzZXRUb0Nvb3JkczogbmV3IEdsc2xMaWJSb3V0aW5lKGBcbiAgICAgIHZlYzIgJHtmdW5jTmFtZX0oaW50IG9mZnNldCwgaW50IHdpZHRoLCBpbnQgaGVpZ2h0KSB7XG4gICAgICAgIGludCB0ID0gb2Zmc2V0IC8gd2lkdGg7XG4gICAgICAgIGludCBzID0gb2Zmc2V0IC0gdCp3aWR0aDtcbiAgICAgICAgdmVjMiBjb29yZHMgPSAodmVjMihzLHQpICsgdmVjMigwLjUsMC41KSkgLyB2ZWMyKHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICByZXR1cm4gY29vcmRzO1xuICAgICAgfVxuICAgICAgYClcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFByb2R1Y2VzIGEgZnVuY3Rpb24gdGhhdCBjYW4gbWFwIGZyb21cbiAgICogMkQgbm9ybWFsemllZCBjb29yZGluYXRlcyAocyx0KSB0byBhIGZsYXQgb2Zmc2V0XG4gICAqL1xuICBwcm90ZWN0ZWQgY29vcmRzVG9PZmZzZXQoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IGZ1bmNOYW1lID0gJ2Nvb3Jkc1RvT2Zmc2V0JztcbiAgICByZXR1cm4ge1xuICAgICAgY29vcmRzVG9PZmZzZXQ6IG5ldyBHbHNsTGliUm91dGluZShgXG4gICAgICBpbnQgJHtmdW5jTmFtZX0odmVjMiBjb29yZHMsIGludCB3aWR0aCwgaW50IGhlaWdodCkge1xuICAgICAgICBmbG9hdCBzID0gY29vcmRzLnMgKiBmbG9hdCh3aWR0aCk7XG4gICAgICAgIGZsb2F0IHQgPSBjb29yZHMudCAqIGZsb2F0KGhlaWdodCk7XG4gICAgICAgIGludCBvZmZzZXQgPSBpbnQodCkgKiB3aWR0aCArIGludChzKTtcbiAgICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICAgIH1cbiAgICAgIGApXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgY29kZSBmb3Igb3V0cHV0IHNhbXBsZXIuXG4gICAqL1xuXG4gIHByb3RlY3RlZCBnZXRPdXRwdXRTYW1wbGluZ1NuaXBwZXQoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IG91dHB1dExheW91dCA9IHRoaXMuY29udGV4dC5vdXRwdXRUZXh0dXJlTGF5b3V0O1xuICAgIGlmIChvdXRwdXRMYXlvdXQuaXNQYWNrZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLmdldFBhY2tlZE91dHB1dFNhbXBsaW5nU25pcHBldChvdXRwdXRMYXlvdXQpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRVbnBhY2tlZE91dHB1dFNhbXBsaW5nU25pcHBldChvdXRwdXRMYXlvdXQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZXMgY29kZSBmb3IgcGFja2VkIG91dHB1dCBzYW1wbGVyLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFBhY2tlZE91dHB1dFNhbXBsaW5nU25pcHBldChvdXRwdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgY29uc3Qgb3V0U2hhcGUgPSBvdXRwdXRMYXlvdXQudW5wYWNrZWRTaGFwZTtcbiAgICBjb25zdCBvdXRUZXhTaGFwZSA9IFtvdXRwdXRMYXlvdXQud2lkdGgsIG91dHB1dExheW91dC5oZWlnaHRdO1xuICAgIGNvbnN0IHJlc3VsdDoge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0gPSB7fTtcbiAgICBjb25zdCBmdW5jTmFtZSA9ICdnZXRPdXRwdXRDb29yZHMnO1xuICAgIHN3aXRjaCAob3V0U2hhcGUubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPSB0aGlzLmdldE91dHB1dFNjYWxhckNvb3JkcygpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMTpcbiAgICAgICAgcmVzdWx0W2Z1bmNOYW1lXSA9IHRoaXMuZ2V0T3V0cHV0UGFja2VkMURDb29yZHMob3V0U2hhcGUgYXMgW251bWJlcl0sIG91dFRleFNoYXBlIGFzIFtudW1iZXIsIG51bWJlcl0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMjpcbiAgICAgICAgcmVzdWx0W2Z1bmNOYW1lXSA9IHRoaXMuZ2V0T3V0cHV0UGFja2VkMkRDb29yZHMob3V0U2hhcGUgYXMgW251bWJlciwgbnVtYmVyXSwgb3V0VGV4U2hhcGUgYXMgW251bWJlciwgbnVtYmVyXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzOlxuICAgICAgICByZXN1bHRbZnVuY05hbWVdID1cbiAgICAgICAgICAgIHRoaXMuZ2V0T3V0cHV0UGFja2VkM0RDb29yZHMob3V0U2hhcGUgYXMgW251bWJlciwgbnVtYmVyLCBudW1iZXJdLCBvdXRUZXhTaGFwZSBhcyBbbnVtYmVyLCBudW1iZXJdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXN1bHRbZnVuY05hbWVdID0gdGhpcy5nZXRPdXRwdXRQYWNrZWRORENvb3JkcyhvdXRTaGFwZSwgb3V0VGV4U2hhcGUgYXMgW251bWJlciwgbnVtYmVyXSk7XG4gICAgfVxuICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKHRoaXMuY29udGV4dC5nbENvbnRleHQudmVyc2lvbik7XG4gICAgLy8gVE9ETyB3ZSBuZWVkIHRoaXMgdG8gcHJvcGVybHkgcmV0dXJuIGEgcGFja2VkIHZlYzQgZnJvbSBrZXJuZWxzLlxuICAgIC8vIFJlcGxhY2UgYWxsICd7Z2xzbC5vdXRwdXR9ID0gcmVzdWx0JyB3aXRoICdzZXRPdXRwdXQocmVzdWx0KScgaW4gYWxsIGtlcm5lbHMuXG4gICAgY29uc3QgZmxvYXRUZXh0dXJlU2V0UkdCQVNvdXJjZSA9IGBcbiAgICAgIHZvaWQgc2V0T3V0cHV0KHZlYzQgdmFsKSB7XG4gICAgICAgICR7Z2xzbC5vdXRwdXR9ID0gdmFsO1xuICAgICAgfVxuICAgIGA7XG4gICAgY29uc3QgZmxvYXRUZXh0dXJlU2V0UkdCQUZ1bmNOYW1lID0gJ2Zsb2F0VGV4dHVyZVNldFJHQkEnO1xuICAgIHJlc3VsdFtmbG9hdFRleHR1cmVTZXRSR0JBRnVuY05hbWVdID0gbmV3IEdsc2xMaWJSb3V0aW5lKGZsb2F0VGV4dHVyZVNldFJHQkFTb3VyY2UpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGNvZGUgZm9yIHVucGFja2VkIG91dHB1dCBzYW1wbGVyLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFVucGFja2VkT3V0cHV0U2FtcGxpbmdTbmlwcGV0KG91dHB1dExheW91dDogVGV4dHVyZUxheW91dCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICBjb25zdCBvdXRTaGFwZSA9IG91dHB1dExheW91dC51bnBhY2tlZFNoYXBlO1xuICAgIGNvbnN0IG91dFRleFNoYXBlID0gW291dHB1dExheW91dC53aWR0aCwgb3V0cHV0TGF5b3V0LmhlaWdodF07XG4gICAgY29uc3QgcmVzdWx0OiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSA9IHt9O1xuICAgIGNvbnN0IGZ1bmNOYW1lID0gJ2dldE91dHB1dENvb3Jkcyc7XG4gICAgc3dpdGNoIChvdXRTaGFwZS5sZW5ndGgpIHtcbiAgICAgIGNhc2UgMDpcbiAgICAgICAgcmVzdWx0W2Z1bmNOYW1lXSA9IHRoaXMuZ2V0T3V0cHV0U2NhbGFyQ29vcmRzKCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXN1bHRbZnVuY05hbWVdID0gdGhpcy5nZXRPdXRwdXRVbnBhY2tlZDFEQ29vcmRzKG91dFNoYXBlIGFzIFtudW1iZXJdLCBvdXRUZXhTaGFwZSBhcyBbbnVtYmVyLCBudW1iZXJdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDI6XG4gICAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPVxuICAgICAgICAgICAgdGhpcy5nZXRPdXRwdXRVbnBhY2tlZDJEQ29vcmRzKG91dFNoYXBlIGFzIFtudW1iZXIsIG51bWJlcl0sIG91dFRleFNoYXBlIGFzIFtudW1iZXIsIG51bWJlcl0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMzpcbiAgICAgICAgcmVzdWx0W2Z1bmNOYW1lXSA9XG4gICAgICAgICAgICB0aGlzLmdldE91dHB1dFVucGFja2VkM0RDb29yZHMob3V0U2hhcGUgYXMgW251bWJlciwgbnVtYmVyLCBudW1iZXJdLCBvdXRUZXhTaGFwZSBhcyBbbnVtYmVyLCBudW1iZXJdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDQ6XG4gICAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPSB0aGlzLmdldE91dHB1dFVucGFja2VkNERDb29yZHMoXG4gICAgICAgICAgICBvdXRTaGFwZSBhcyBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSwgb3V0VGV4U2hhcGUgYXMgW251bWJlciwgbnVtYmVyXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA1OlxuICAgICAgICByZXN1bHRbZnVuY05hbWVdID0gdGhpcy5nZXRPdXRwdXRVbnBhY2tlZDVEQ29vcmRzKFxuICAgICAgICAgICAgb3V0U2hhcGUgYXMgW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSwgb3V0VGV4U2hhcGUgYXMgW251bWJlciwgbnVtYmVyXSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA2OlxuICAgICAgICByZXN1bHRbZnVuY05hbWVdID0gdGhpcy5nZXRPdXRwdXRVbnBhY2tlZDZEQ29vcmRzKFxuICAgICAgICAgICAgb3V0U2hhcGUgYXMgW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdLCBvdXRUZXhTaGFwZSBhcyBbbnVtYmVyLCBudW1iZXJdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuc3VwcG9ydGVkIG91dHB1dCBkaW1lbnNpb25hbGl0eTogJHtvdXRTaGFwZS5sZW5ndGh9YCk7XG4gICAgfVxuICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKHRoaXMuY29udGV4dC5nbENvbnRleHQudmVyc2lvbik7XG4gICAgLy8gVE9ETyB3ZSBuZWVkIHRoaXMgdG8gcHJvcGVybHkgcmV0dXJuIGEgcGFja2VkIHZlYzQgZnJvbSBrZXJuZWxzLlxuICAgIC8vIFJlcGxhY2UgYWxsICd7Z2xzbC5vdXRwdXR9ID0gcmVzdWx0JyB3aXRoICdzZXRPdXRwdXQocmVzdWx0KScgaW4gYWxsIGtlcm5lbHMuXG4gICAgY29uc3QgZmxvYXRUZXh0dXJlU2V0UlNvdXJjZSA9IGBcbiAgICAgICAgdm9pZCBzZXRPdXRwdXQoZmxvYXQgdmFsKSB7XG4gICAgICAgICAgJHtnbHNsLm91dHB1dH0gPSB2ZWM0KHZhbCwgMCwgMCwgMCk7XG4gICAgICAgIH1cbiAgICBgO1xuICAgIGNvbnN0IGZsb2F0VGV4dHVyZVNldFJGdW5jTmFtZSA9ICdmbG9hdFRleHR1cmVTZXRSJztcbiAgICByZXN1bHRbZmxvYXRUZXh0dXJlU2V0UkZ1bmNOYW1lXSA9IG5ldyBHbHNsTGliUm91dGluZShmbG9hdFRleHR1cmVTZXRSU291cmNlKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIFNjYWxhciBvdXRwdXQgY29vcmRpbmF0ZXMuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0T3V0cHV0U2NhbGFyQ29vcmRzKCk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKGBcbiAgICAgIGludCBnZXRPdXRwdXRDb29yZHMoKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgICAgfVxuICAgIGApO1xuICB9XG5cbiAgLyoqXG4gICAqIDFEIHBhY2tlZCBvdXRwdXQgY29vcmRpbmF0ZXMuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0T3V0cHV0UGFja2VkMURDb29yZHMoc2hhcGU6IFtudW1iZXJdLCB0ZXhTaGFwZTogW251bWJlciwgbnVtYmVyXSk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBjb25zdCBwYWNrZWRUZXhTaGFwZSA9IHRleFNoYXBlO1xuICAgIGxldCBzb3VyY2UgPSAnJztcbiAgICBpZiAocGFja2VkVGV4U2hhcGVbMF0gPT09IDEpIHtcbiAgICAgIHNvdXJjZSA9IGBcbiAgICAgICAgICBpbnQgZ2V0T3V0cHV0Q29vcmRzKCkge1xuICAgICAgICAgICAgcmV0dXJuIDIgKiBpbnQoVGV4Q29vcmRzLnkgKiAke3BhY2tlZFRleFNoYXBlWzFdfS4wKTtcbiAgICAgICAgICB9XG4gICAgICAgIGA7XG4gICAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSk7XG4gICAgfVxuXG4gICAgaWYgKHBhY2tlZFRleFNoYXBlWzFdID09PSAxKSB7XG4gICAgICBzb3VyY2UgPSBgXG4gICAgICAgICAgaW50IGdldE91dHB1dENvb3JkcygpIHtcbiAgICAgICAgICAgIHJldHVybiAyICogaW50KFRleENvb3Jkcy54ICogJHtwYWNrZWRUZXhTaGFwZVswXX0uMCk7XG4gICAgICAgICAgfVxuICAgICAgICBgO1xuICAgICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UpO1xuICAgIH1cblxuICAgIHNvdXJjZSA9IGBcbiAgICAgICAgaW50IGdldE91dHB1dENvb3JkcygpIHtcbiAgICAgICAgICBpdmVjMiByZXNUZXhSQyA9IGl2ZWMyKFRleENvb3Jkcy54eSAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZWMyKCR7cGFja2VkVGV4U2hhcGVbMF19LCAke3BhY2tlZFRleFNoYXBlWzFdfSkpO1xuICAgICAgICAgIHJldHVybiAyICogKHJlc1RleFJDLnkgKiAke3BhY2tlZFRleFNoYXBlWzBdfSArIHJlc1RleFJDLngpO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiAyRCBwYWNrZWQgb3V0cHV0IGNvb3JkaW5hdGVzLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldE91dHB1dFBhY2tlZDJEQ29vcmRzKHNoYXBlOiBbbnVtYmVyLCBudW1iZXJdLCB0ZXhTaGFwZTogW251bWJlciwgbnVtYmVyXSk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBsZXQgc291cmNlID0gJyc7XG4gICAgaWYgKEFycmF5VXRpbC5hcnJheXNFcXVhbChzaGFwZSwgdGV4U2hhcGUpKSB7XG4gICAgICBzb3VyY2UgPSBgXG4gICAgICAgIGl2ZWMyIGdldE91dHB1dENvb3JkcygpIHtcbiAgICAgICAgICByZXR1cm4gMiAqIGl2ZWMyKFRleENvb3Jkcy54eSAqIHZlYzIoJHt0ZXhTaGFwZVswXX0sICR7dGV4U2hhcGVbMV19KSk7XG4gICAgICAgIH1cbiAgICAgIGA7XG4gICAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSk7XG4gICAgfVxuXG4gICAgY29uc3QgcGFja2VkVGV4U2hhcGUgPSB0ZXhTaGFwZTtcbiAgICAvLyB0ZXhlbHMgbmVlZGVkIHRvIGFjY29tbW9kYXRlIGEgbG9naWNhbCByb3dcbiAgICBjb25zdCB0ZXhlbHNJbkxvZ2ljYWxSb3cgPSBNYXRoLmNlaWwoc2hhcGVbMV0gLyAyKTtcblxuICAgIC8qKlxuICAgICAqIGdldE91dHB1dENvb3Jkc1xuICAgICAqXG4gICAgICogcmVzVGV4UkM6IFRoZSByb3dzIGFuZCBjb2x1bW5zIG9mIHRoZSB0ZXhlbHMuIElmIHlvdSBtb3ZlIG92ZXIgb25lXG4gICAgICogdGV4ZWwgdG8gdGhlIHJpZ2h0IGluIHRoZSBwYWNrZWQgdGV4dHVyZSwgeW91IGFyZSBtb3Zpbmcgb3ZlciBvbmUgY29sdW1uXG4gICAgICogKG5vdCB0d28pLlxuICAgICAqXG4gICAgICogaW5kZXg6IFRoZSB0ZXhlbCBpbmRleFxuICAgICAqL1xuICAgIHNvdXJjZSA9IGBcbiAgICAgICAgaXZlYzIgZ2V0T3V0cHV0Q29vcmRzKCkge1xuICAgICAgICAgIGl2ZWMyIHJlc1RleFJDID0gaXZlYzIoVGV4Q29vcmRzLnh5ICpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVjMigke3BhY2tlZFRleFNoYXBlWzBdfSwgJHtwYWNrZWRUZXhTaGFwZVsxXX0pKTtcblxuICAgICAgICAgIGludCBpbmRleCA9IHJlc1RleFJDLnkgKiAke3BhY2tlZFRleFNoYXBlWzBdfSArIHJlc1RleFJDLng7XG5cbiAgICAgICAgICAvLyByZXZlcnNlIHIgYW5kIGMgb3JkZXIgZm9yIHBhY2tlZCB0ZXh0dXJlXG4gICAgICAgICAgaW50IHIgPSBpbW9kKGluZGV4LCAke3RleGVsc0luTG9naWNhbFJvd30pICogMjtcbiAgICAgICAgICBpbnQgYyA9IDIgKiAoaW5kZXggLyAke3RleGVsc0luTG9naWNhbFJvd30pO1xuXG4gICAgICAgICAgcmV0dXJuIGl2ZWMyKHIsIGMpO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiAzRCBwYWNrZWQgb3V0cHV0IGNvb3JkaW5hdGVzLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldE91dHB1dFBhY2tlZDNEQ29vcmRzKHNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sIHRleFNoYXBlOiBbbnVtYmVyLCBudW1iZXJdKTogR2xzbExpYlJvdXRpbmUge1xuICAgIGNvbnN0IHBhY2tlZFRleFNoYXBlID0gW3RleFNoYXBlWzBdLCB0ZXhTaGFwZVsxXV07XG4gICAgY29uc3QgdGV4ZWxzSW5Mb2dpY2FsUm93ID0gTWF0aC5jZWlsKHNoYXBlWzJdIC8gMik7XG4gICAgY29uc3QgdGV4ZWxzSW5CYXRjaCA9IHRleGVsc0luTG9naWNhbFJvdyAqIE1hdGguY2VpbChzaGFwZVsxXSAvIDIpO1xuICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgaXZlYzMgZ2V0T3V0cHV0Q29vcmRzKCkge1xuICAgICAgICAgIGl2ZWMyIHJlc1RleFJDID0gaXZlYzIoVGV4Q29vcmRzLnh5ICpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVjMigke3BhY2tlZFRleFNoYXBlWzBdfSwgJHtwYWNrZWRUZXhTaGFwZVsxXX0pKTtcbiAgICAgICAgICBpbnQgaW5kZXggPSByZXNUZXhSQy55ICogJHtwYWNrZWRUZXhTaGFwZVswXX0gKyByZXNUZXhSQy54O1xuXG4gICAgICAgICAgaW50IGIgPSBpbmRleCAvICR7dGV4ZWxzSW5CYXRjaH07XG4gICAgICAgICAgaW5kZXggLT0gYiAqICR7dGV4ZWxzSW5CYXRjaH07XG5cbiAgICAgICAgICAvLyByZXZlcnNlIHIgYW5kIGMgb3JkZXIgZm9yIHBhY2tlZCB0ZXh0dXJlXG4gICAgICAgICAgaW50IHIgPSBpbW9kKGluZGV4LCAke3RleGVsc0luTG9naWNhbFJvd30pICogMjtcbiAgICAgICAgICBpbnQgYyA9IDIgKiAoaW5kZXggLyAke3RleGVsc0luTG9naWNhbFJvd30pO1xuXG4gICAgICAgICAgcmV0dXJuIGl2ZWMzKGIsIHIsIGMpO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBORCBwYWNrZWQgb3V0cHV0IGNvb3JkaW5hdGVzLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldE91dHB1dFBhY2tlZE5EQ29vcmRzKHNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgdGV4U2hhcGU6IFtudW1iZXIsIG51bWJlcl0pOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3QgcGFja2VkVGV4U2hhcGUgPSBbdGV4U2hhcGVbMF0sIHRleFNoYXBlWzFdXTtcblxuICAgIGNvbnN0IHRleGVsc0luTG9naWNhbFJvdyA9IE1hdGguY2VpbChzaGFwZVtzaGFwZS5sZW5ndGggLSAxXSAvIDIpO1xuICAgIGNvbnN0IHRleGVsc0luQmF0Y2ggPSB0ZXhlbHNJbkxvZ2ljYWxSb3cgKiBNYXRoLmNlaWwoc2hhcGVbc2hhcGUubGVuZ3RoIC0gMl0gLyAyKTtcbiAgICBsZXQgdGV4ZWxzSW5CYXRjaE4gPSB0ZXhlbHNJbkJhdGNoO1xuICAgIGxldCBiYXRjaGVzID0gJyc7XG4gICAgbGV0IGNvb3JkcyA9ICdiLCByLCBjJztcblxuICAgIGZvciAobGV0IGIgPSAyOyBiIDwgc2hhcGUubGVuZ3RoIC0gMTsgYisrKSB7XG4gICAgICB0ZXhlbHNJbkJhdGNoTiAqPSBzaGFwZVtzaGFwZS5sZW5ndGggLSBiIC0gMV07XG4gICAgICBiYXRjaGVzID0gYFxuICAgICAgaW50IGIke2J9ID0gaW5kZXggLyAke3RleGVsc0luQmF0Y2hOfTtcbiAgICAgIGluZGV4IC09IGIke2J9ICogJHt0ZXhlbHNJbkJhdGNoTn07XG4gICAgYCArIGJhdGNoZXM7XG4gICAgICBjb29yZHMgPSBgYiR7Yn0sIGAgKyBjb29yZHM7XG4gICAgfVxuICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgIGl2ZWMke3NoYXBlLmxlbmd0aH0gZ2V0T3V0cHV0Q29vcmRzKCkge1xuICAgICAgICBpdmVjMiByZXNUZXhSQyA9IGl2ZWMyKFRleENvb3Jkcy54eSAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZWMyKCR7cGFja2VkVGV4U2hhcGVbMF19LCAke3BhY2tlZFRleFNoYXBlWzFdfSkpO1xuICAgICAgICBpbnQgaW5kZXggPSByZXNUZXhSQy55ICogJHtwYWNrZWRUZXhTaGFwZVswXX0gKyByZXNUZXhSQy54O1xuXG4gICAgICAgICR7YmF0Y2hlc31cblxuICAgICAgICBpbnQgYiA9IGluZGV4IC8gJHt0ZXhlbHNJbkJhdGNofTtcbiAgICAgICAgaW5kZXggLT0gYiAqICR7dGV4ZWxzSW5CYXRjaH07XG5cbiAgICAgICAgLy8gcmV2ZXJzZSByIGFuZCBjIG9yZGVyIGZvciBwYWNrZWQgdGV4dHVyZVxuICAgICAgICBpbnQgciA9IGltb2QoaW5kZXgsICR7dGV4ZWxzSW5Mb2dpY2FsUm93fSkgKiAyO1xuICAgICAgICBpbnQgYyA9IDIgKiAoaW5kZXggLyAke3RleGVsc0luTG9naWNhbFJvd30pO1xuXG4gICAgICAgIHJldHVybiBpdmVjJHtzaGFwZS5sZW5ndGh9KCR7Y29vcmRzfSk7XG4gICAgICB9XG4gICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSk7XG4gIH1cblxuICAvKipcbiAgICogVW5wYWNrZWQgMUQgb3V0cHV0IGNvb3JkaW5hdGVzLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldE91dHB1dFVucGFja2VkMURDb29yZHMoc2hhcGU6IFtudW1iZXJdLCB0ZXhTaGFwZTogW251bWJlciwgbnVtYmVyXSk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgIGludCBnZXRPdXRwdXRDb29yZHMoKSB7XG4gICAgICAgICAgaXZlYzIgcmVzVGV4UkMgPSBpdmVjMihUZXhDb29yZHMueHkgKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZWMyKCR7dGV4U2hhcGVbMF19LCAke3RleFNoYXBlWzFdfSkpO1xuICAgICAgICAgIHJldHVybiByZXNUZXhSQy55ICogJHt0ZXhTaGFwZVswXX0gKyByZXNUZXhSQy54O1xuICAgICAgICB9XG4gICAgICBgO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnBhY2tlZCAyRCBvdXRwdXQgY29vcmRpbmF0ZXMuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0T3V0cHV0VW5wYWNrZWQyRENvb3JkcyhzaGFwZTogW251bWJlciwgbnVtYmVyXSwgdGV4U2hhcGU6IFtudW1iZXIsIG51bWJlcl0pOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICBpdmVjMiBnZXRPdXRwdXRDb29yZHMoKSB7XG4gICAgICAgICAgaXZlYzIgcmVzVGV4UkMgPSBpdmVjMihUZXhDb29yZHMueHkgKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZWMyKCR7dGV4U2hhcGVbMF19LCAke3RleFNoYXBlWzFdfSkpO1xuICAgICAgICAgIGludCBpbmRleCA9IHJlc1RleFJDLnkgKiAke3RleFNoYXBlWzBdfSArIHJlc1RleFJDLng7XG4gICAgICAgICAgaW50IHIgPSBpbmRleCAvICR7c2hhcGVbMV19O1xuICAgICAgICAgIGludCBjID0gaW5kZXggLSByICogJHtzaGFwZVsxXX07XG4gICAgICAgICAgcmV0dXJuIGl2ZWMyKHIsIGMpO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnBhY2tlZCAzRCBvdXRwdXQgY29vcmRpbmF0ZXMuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0T3V0cHV0VW5wYWNrZWQzRENvb3JkcyhzaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXJdLCB0ZXhTaGFwZTogW251bWJlciwgbnVtYmVyXSk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBsZXQgc291cmNlID0gJyc7XG4gICAgY29uc3QgcmFuayA9IHNoYXBlLmxlbmd0aDtcblxuICAgIGxldCBzdHJpZGVzID0gbnVsbDtcbiAgICBpZiAocmFuayA8IDIpIHtcbiAgICAgIHN0cmlkZXMgPSBbXTtcbiAgICB9XG5cbiAgICBzdHJpZGVzID0gbmV3IEFycmF5KHJhbmsgLSAxKTtcbiAgICBzdHJpZGVzW3JhbmsgLSAyXSA9IHNoYXBlW3JhbmsgLSAxXTtcbiAgICBmb3IgKGxldCBpID0gcmFuayAtIDM7IGkgPj0gMDsgLS1pKSB7XG4gICAgICBzdHJpZGVzW2ldID0gc3RyaWRlc1tpICsgMV0gKiBzaGFwZVtpICsgMV07XG4gICAgfVxuICAgIGNvbnN0IGNvb3Jkc1RvQ29tcHV0ZSA9IFsncicsICdjJywgJ2QnXTtcbiAgICBjb25zdCBjb29yZHNGcm9tSW5kZXhTbmlwcGV0ID1cbiAgICAgICAgc3RyaWRlc1xuICAgICAgICAgICAgLm1hcCgoc3RyaWRlLCBpKSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IGxpbmUxID0gYGludCAke2Nvb3Jkc1RvQ29tcHV0ZVtpXX0gPSBpbmRleCAvICR7c3RyaWRlfWA7XG4gICAgICAgICAgICAgIGNvbnN0IGxpbmUyID0gaSA9PT0gc3RyaWRlcy5sZW5ndGggLSAxID9cbiAgICAgICAgICAgICAgICAgIGBpbnQgJHtjb29yZHNUb0NvbXB1dGVbaSArIDFdfSA9IGluZGV4IC0gJHtjb29yZHNUb0NvbXB1dGVbaV19ICogJHtzdHJpZGV9YCA6XG4gICAgICAgICAgICAgICAgICBgaW5kZXggLT0gJHtjb29yZHNUb0NvbXB1dGVbaV19ICogJHtzdHJpZGV9YDtcbiAgICAgICAgICAgICAgcmV0dXJuIGAke2xpbmUxfTsgJHtsaW5lMn07YDtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuam9pbignJyk7XG5cbiAgICBzb3VyY2UgPSBgXG4gICAgICAgIGl2ZWMzIGdldE91dHB1dENvb3JkcygpIHtcbiAgICAgICAgICBpdmVjMiByZXNUZXhSQyA9IGl2ZWMyKFRleENvb3Jkcy54eSAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlYzIoJHt0ZXhTaGFwZVswXX0sICR7dGV4U2hhcGVbMV19KSk7XG4gICAgICAgICAgaW50IGluZGV4ID0gcmVzVGV4UkMueSAqICR7dGV4U2hhcGVbMF19ICsgcmVzVGV4UkMueDtcbiAgICAgICAgICAke2Nvb3Jkc0Zyb21JbmRleFNuaXBwZXR9XG4gICAgICAgICAgcmV0dXJuIGl2ZWMzKHIsIGMsIGQpO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnBhY2tlZCA0RCBvdXRwdXQgY29vcmRpbmF0ZXMuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0T3V0cHV0VW5wYWNrZWQ0RENvb3JkcyhzaGFwZTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sIHRleFNoYXBlOiBbbnVtYmVyLCBudW1iZXJdKTpcbiAgICAgIEdsc2xMaWJSb3V0aW5lIHtcbiAgICBsZXQgc291cmNlID0gJyc7XG4gICAgY29uc3QgcmFuayA9IHNoYXBlLmxlbmd0aDtcblxuICAgIGxldCBzdHJpZGVzID0gbnVsbDtcbiAgICBpZiAocmFuayA8IDIpIHtcbiAgICAgIHN0cmlkZXMgPSBbXTtcbiAgICB9XG5cbiAgICBzdHJpZGVzID0gbmV3IEFycmF5KHJhbmsgLSAxKTtcbiAgICBzdHJpZGVzW3JhbmsgLSAyXSA9IHNoYXBlW3JhbmsgLSAxXTtcbiAgICBmb3IgKGxldCBpID0gcmFuayAtIDM7IGkgPj0gMDsgLS1pKSB7XG4gICAgICBzdHJpZGVzW2ldID0gc3RyaWRlc1tpICsgMV0gKiBzaGFwZVtpICsgMV07XG4gICAgfVxuICAgIGNvbnN0IGNvb3Jkc1RvQ29tcHV0ZSA9IFsncicsICdjJywgJ2QnLCAnZDInXTtcbiAgICBjb25zdCBjb29yZHNGcm9tSW5kZXhTbmlwcGV0ID1cbiAgICAgICAgc3RyaWRlc1xuICAgICAgICAgICAgLm1hcCgoc3RyaWRlLCBpKSA9PiB7XG4gICAgICAgICAgICAgIGNvbnN0IGxpbmUxID0gYGludCAke2Nvb3Jkc1RvQ29tcHV0ZVtpXX0gPSBpbmRleCAvICR7c3RyaWRlfWA7XG4gICAgICAgICAgICAgIGNvbnN0IGxpbmUyID0gaSA9PT0gc3RyaWRlcy5sZW5ndGggLSAxID9cbiAgICAgICAgICAgICAgICAgIGBpbnQgJHtjb29yZHNUb0NvbXB1dGVbaSArIDFdfSA9IGluZGV4IC0gJHtjb29yZHNUb0NvbXB1dGVbaV19ICogJHtzdHJpZGV9YCA6XG4gICAgICAgICAgICAgICAgICBgaW5kZXggLT0gJHtjb29yZHNUb0NvbXB1dGVbaV19ICogJHtzdHJpZGV9YDtcbiAgICAgICAgICAgICAgcmV0dXJuIGAke2xpbmUxfTsgJHtsaW5lMn07YDtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuam9pbignJyk7XG5cbiAgICBzb3VyY2UgPSBgXG4gICAgICBpdmVjNCBnZXRPdXRwdXRDb29yZHMoKSB7XG4gICAgICAgICAgaXZlYzIgcmVzVGV4UkMgPSBpdmVjMihUZXhDb29yZHMueHkgKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZWMyKCR7dGV4U2hhcGVbMF19LCAke3RleFNoYXBlWzFdfSkpO1xuICAgICAgICAgIGludCBpbmRleCA9IHJlc1RleFJDLnkgKiAke3RleFNoYXBlWzBdfSArIHJlc1RleFJDLng7XG4gICAgICAgICAgJHtjb29yZHNGcm9tSW5kZXhTbmlwcGV0fVxuICAgICAgICAgIHJldHVybiBpdmVjNChyLCBjLCBkLCBkMik7XG4gICAgICAgIH1cbiAgICAgIGA7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVucGFja2VkIDVEIG91dHB1dCBjb29yZGluYXRlcy5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRPdXRwdXRVbnBhY2tlZDVEQ29vcmRzKHNoYXBlOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdLCB0ZXhTaGFwZTogW251bWJlciwgbnVtYmVyXSk6XG4gICAgICBHbHNsTGliUm91dGluZSB7XG4gICAgbGV0IHNvdXJjZSA9ICcnO1xuICAgIGNvbnN0IHJhbmsgPSBzaGFwZS5sZW5ndGg7XG5cbiAgICBsZXQgc3RyaWRlcyA9IG51bGw7XG4gICAgaWYgKHJhbmsgPCAyKSB7XG4gICAgICBzdHJpZGVzID0gW107XG4gICAgfVxuXG4gICAgc3RyaWRlcyA9IG5ldyBBcnJheShyYW5rIC0gMSk7XG4gICAgc3RyaWRlc1tyYW5rIC0gMl0gPSBzaGFwZVtyYW5rIC0gMV07XG4gICAgZm9yIChsZXQgaSA9IHJhbmsgLSAzOyBpID49IDA7IC0taSkge1xuICAgICAgc3RyaWRlc1tpXSA9IHN0cmlkZXNbaSArIDFdICogc2hhcGVbaSArIDFdO1xuICAgIH1cbiAgICBjb25zdCBjb29yZHNUb0NvbXB1dGUgPSBbJ3InLCAnYycsICdkJywgJ2QyJywgJ2QzJ107XG4gICAgY29uc3QgY29vcmRzRnJvbUluZGV4U25pcHBldCA9XG4gICAgICAgIHN0cmlkZXNcbiAgICAgICAgICAgIC5tYXAoKHN0cmlkZSwgaSkgPT4ge1xuICAgICAgICAgICAgICBjb25zdCBsaW5lMSA9IGBpbnQgJHtjb29yZHNUb0NvbXB1dGVbaV19ID0gaW5kZXggLyAke3N0cmlkZX1gO1xuICAgICAgICAgICAgICBjb25zdCBsaW5lMiA9IGkgPT09IHN0cmlkZXMubGVuZ3RoIC0gMSA/XG4gICAgICAgICAgICAgICAgICBgaW50ICR7Y29vcmRzVG9Db21wdXRlW2kgKyAxXX0gPSBpbmRleCAtICR7Y29vcmRzVG9Db21wdXRlW2ldfSAqICR7c3RyaWRlfWAgOlxuICAgICAgICAgICAgICAgICAgYGluZGV4IC09ICR7Y29vcmRzVG9Db21wdXRlW2ldfSAqICR7c3RyaWRlfWA7XG4gICAgICAgICAgICAgIHJldHVybiBgJHtsaW5lMX07ICR7bGluZTJ9O2A7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmpvaW4oJycpO1xuXG4gICAgc291cmNlID0gYFxuICAgICAgaXZlYzUgZ2V0T3V0cHV0Q29vcmRzKCkge1xuICAgICAgICAgIGl2ZWMyIHJlc1RleFJDID0gaXZlYzIoVGV4Q29vcmRzLnh5ICpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVjMigke3RleFNoYXBlWzBdfSwgJHt0ZXhTaGFwZVsxXX0pKTtcbiAgICAgICAgICBpbnQgaW5kZXggPSByZXNUZXhSQy55ICogJHt0ZXhTaGFwZVswXX0gKyByZXNUZXhSQy54O1xuICAgICAgICAgICR7Y29vcmRzRnJvbUluZGV4U25pcHBldH1cbiAgICAgICAgICByZXR1cm4gaXZlYzUociwgYywgZCwgZDIsIGQzKTtcbiAgICAgICAgfVxuICAgICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSk7XG4gIH1cblxuICAvKipcbiAgICogVW5wYWNrZWQgNkQgb3V0cHV0IGNvb3JkaW5hdGVzLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldE91dHB1dFVucGFja2VkNkRDb29yZHMoc2hhcGU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXSwgdGV4U2hhcGU6IFtcbiAgICBudW1iZXIsIG51bWJlclxuICBdKTogR2xzbExpYlJvdXRpbmUge1xuICAgIGxldCBzb3VyY2UgPSAnJztcbiAgICBjb25zdCByYW5rID0gc2hhcGUubGVuZ3RoO1xuXG4gICAgbGV0IHN0cmlkZXMgPSBudWxsO1xuICAgIGlmIChyYW5rIDwgMikge1xuICAgICAgc3RyaWRlcyA9IFtdO1xuICAgIH1cblxuICAgIHN0cmlkZXMgPSBuZXcgQXJyYXkocmFuayAtIDEpO1xuICAgIHN0cmlkZXNbcmFuayAtIDJdID0gc2hhcGVbcmFuayAtIDFdO1xuICAgIGZvciAobGV0IGkgPSByYW5rIC0gMzsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIHN0cmlkZXNbaV0gPSBzdHJpZGVzW2kgKyAxXSAqIHNoYXBlW2kgKyAxXTtcbiAgICB9XG4gICAgY29uc3QgY29vcmRzVG9Db21wdXRlID0gWydyJywgJ2MnLCAnZCcsICdkMicsICdkMycsICdkNCddO1xuICAgIGNvbnN0IGNvb3Jkc0Zyb21JbmRleFNuaXBwZXQgPVxuICAgICAgICBzdHJpZGVzXG4gICAgICAgICAgICAubWFwKChzdHJpZGUsIGkpID0+IHtcbiAgICAgICAgICAgICAgY29uc3QgbGluZTEgPSBgaW50ICR7Y29vcmRzVG9Db21wdXRlW2ldfSA9IGluZGV4IC8gJHtzdHJpZGV9YDtcbiAgICAgICAgICAgICAgY29uc3QgbGluZTIgPSBpID09PSBzdHJpZGVzLmxlbmd0aCAtIDEgP1xuICAgICAgICAgICAgICAgICAgYGludCAke2Nvb3Jkc1RvQ29tcHV0ZVtpICsgMV19ID0gaW5kZXggLSAke2Nvb3Jkc1RvQ29tcHV0ZVtpXX0gKiAke3N0cmlkZX1gIDpcbiAgICAgICAgICAgICAgICAgIGBpbmRleCAtPSAke2Nvb3Jkc1RvQ29tcHV0ZVtpXX0gKiAke3N0cmlkZX1gO1xuICAgICAgICAgICAgICByZXR1cm4gYCR7bGluZTF9OyAke2xpbmUyfTtgO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5qb2luKCcnKTtcblxuICAgIHNvdXJjZSA9IGBcbiAgICAgaXZlYzYgZ2V0T3V0cHV0Q29vcmRzKCkge1xuICAgICAgICAgaXZlYzIgcmVzVGV4UkMgPSBpdmVjMihUZXhDb29yZHMueHkgKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlYzIoJHt0ZXhTaGFwZVswXX0sICR7dGV4U2hhcGVbMV19KSk7XG4gICAgICAgICBpbnQgaW5kZXggPSByZXNUZXhSQy55ICogJHt0ZXhTaGFwZVswXX0gKyByZXNUZXhSQy54O1xuICAgICAgICAgJHtjb29yZHNGcm9tSW5kZXhTbmlwcGV0fVxuICAgICAgICAgcmV0dXJuIGl2ZWM2KHIsIGMsIGQsIGQyLCBkMywgZDQpO1xuICAgICAgIH1cbiAgICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSk7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGVzIGNvZGUgZm9yIGNvbW1vbiBVViBjb29yZHMgY29tcHV0YXRpb24gdXRpbGl0eSBmdW5jdGlvbnMuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0Q29tbW9uVXRpbEZ1bmNzKCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICBjb25zdCByZXN1bHQ6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9ID0ge307XG4gICAgbGV0IGZ1bmNOYW1lID0gJ3V2RnJvbUZsYXQnO1xuICAgIHJlc3VsdFtmdW5jTmFtZV0gPSBuZXcgR2xzbExpYlJvdXRpbmUoYFxuICAgIHZlYzIgdXZGcm9tRmxhdChpbnQgdGV4TnVtUiwgaW50IHRleE51bUMsIGludCBpbmRleCkge1xuICAgICAgaW50IHRleEMgPSBpbmRleCAvIHRleE51bVI7XG4gICAgICBpbnQgdGV4UiA9IGluZGV4IC0gdGV4QyAqIHRleE51bVI7XG4gICAgICAvLyBUT0RPOiBzd2FwIHRleFIsIHRleEMgb3JkZXIgaW4gZm9sbG93aW5nIGZ1bmN0aW9uIHNvIHJvdyBpcyBjb3JyZXNwb25kaW5nIHRvIHUgYW5kIGNvbHVtbiBpcyBjb3JyZXNwb25kaW5nIHRvXG4gICAgICAvLyAgICAgICB2LlxuICAgICAgcmV0dXJuICh2ZWMyKHRleFIsIHRleEMpICsgaGFsZkNSKSAvIHZlYzIodGV4TnVtUiwgdGV4TnVtQyk7XG4gICAgfVxuICAgIGApO1xuICAgIGZ1bmNOYW1lID0gJ3BhY2tlZFVWZnJvbTFEJztcbiAgICByZXN1bHRbZnVuY05hbWVdID0gbmV3IEdsc2xMaWJSb3V0aW5lKGBcbiAgICAgIHZlYzIgcGFja2VkVVZmcm9tMUQoaW50IHRleE51bVIsIGludCB0ZXhOdW1DLCBpbnQgaW5kZXgpIHtcbiAgICAgICAgaW50IHRleGVsSW5kZXggPSBpbmRleCAvIDI7XG4gICAgICAgIGludCB0ZXhSID0gdGV4ZWxJbmRleCAvIHRleE51bUM7XG4gICAgICAgIGludCB0ZXhDID0gdGV4ZWxJbmRleCAtIHRleFIgKiB0ZXhOdW1DO1xuICAgICAgICByZXR1cm4gKHZlYzIodGV4QywgdGV4UikgKyBoYWxmQ1IpIC8gdmVjMih0ZXhOdW1DLCB0ZXhOdW1SKTtcbiAgICAgIH1cbiAgICAgIGApO1xuICAgIGZ1bmNOYW1lID0gJ3BhY2tlZFVWZnJvbTJEJztcbiAgICByZXN1bHRbZnVuY05hbWVdID0gbmV3IEdsc2xMaWJSb3V0aW5lKGBcbiAgICAgIHZlYzIgcGFja2VkVVZmcm9tMkQoaW50IHRleE51bVIsIGludCB0ZXhOdW1DLCBpbnQgdGV4ZWxzSW5Mb2dpY2FsUm93LCBpbnQgcm93LCBpbnQgY29sKSB7XG4gICAgICAgIGludCB0ZXhlbEluZGV4ID0gKHJvdyAvIDIpICogdGV4ZWxzSW5Mb2dpY2FsUm93ICsgKGNvbCAvIDIpO1xuICAgICAgICBpbnQgdGV4UiA9IHRleGVsSW5kZXggLyB0ZXhOdW1DO1xuICAgICAgICBpbnQgdGV4QyA9IHRleGVsSW5kZXggLSB0ZXhSICogdGV4TnVtQztcbiAgICAgICAgcmV0dXJuICh2ZWMyKHRleEMsIHRleFIpICsgaGFsZkNSKSAvIHZlYzIodGV4TnVtQywgdGV4TnVtUik7XG4gICAgICB9XG4gICAgICBgKTtcbiAgICBmdW5jTmFtZSA9ICdwYWNrZWRVVmZyb20zRCc7XG4gICAgcmVzdWx0W2Z1bmNOYW1lXSA9IG5ldyBHbHNsTGliUm91dGluZShgXG4gICAgICB2ZWMyIHBhY2tlZFVWZnJvbTNEKGludCB0ZXhOdW1SLCBpbnQgdGV4TnVtQyxcbiAgICAgICAgICBpbnQgdGV4ZWxzSW5CYXRjaCwgaW50IHRleGVsc0luTG9naWNhbFJvdywgaW50IGIsXG4gICAgICAgICAgaW50IHJvdywgaW50IGNvbCkge1xuICAgICAgICBpbnQgaW5kZXggPSBiICogdGV4ZWxzSW5CYXRjaCArIChyb3cgLyAyKSAqIHRleGVsc0luTG9naWNhbFJvdyArIChjb2wgLyAyKTtcbiAgICAgICAgaW50IHRleFIgPSBpbmRleCAvIHRleE51bUM7XG4gICAgICAgIGludCB0ZXhDID0gaW5kZXggLSB0ZXhSICogdGV4TnVtQztcbiAgICAgICAgcmV0dXJuICh2ZWMyKHRleEMsIHRleFIpICsgaGFsZkNSKSAvIHZlYzIodGV4TnVtQywgdGV4TnVtUik7XG4gICAgICB9XG4gICAgICBgKTtcbiAgICBmdW5jTmFtZSA9ICdzYW1wbGVUZXh0dXJlJztcbiAgICBjb25zdCBnbHNsID0gZ2V0R2xzbCh0aGlzLmNvbnRleHQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgIHJlc3VsdFtmdW5jTmFtZV0gPSBuZXcgR2xzbExpYlJvdXRpbmUoYFxuICAgICAgICBmbG9hdCBzYW1wbGVUZXh0dXJlKHNhbXBsZXIyRCB0ZXh0dXJlU2FtcGxlciwgdmVjMiB1dikge1xuICAgICAgICAgICAgcmV0dXJuICR7Z2xzbC50ZXh0dXJlMkR9KHRleHR1cmVTYW1wbGVyLCB1dikucjtcbiAgICAgICAgfWApO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICAvKipcbiAgICogQ29uc3RydWN0aW5nIHNuaXBwZXRzIGZvciBpbnB1dHNcbiAgICovXG4gIHByb3RlY3RlZCBnZXRJbnB1dHNTYW1wbGluZ1NuaXBwZXRzKCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICBjb25zdCByZXN1bHQ6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9ID0ge307XG4gICAgY29uc3Qgb3V0cHV0TGF5b3V0ID0gdGhpcy5jb250ZXh0Lm91dHB1dFRleHR1cmVMYXlvdXQ7XG4gICAgdGhpcy5jb250ZXh0LnByb2dyYW1JbmZvLmlucHV0TmFtZXMuZm9yRWFjaCgoc2FtcGxlck5hbWUsIGkpID0+IHtcbiAgICAgIGNvbnN0IGlucHV0TGF5b3V0ID0gdGhpcy5jb250ZXh0LmlucHV0VGV4dHVyZUxheW91dHNbaV07XG4gICAgICBjb25zdCBmdW5jTmFtZSA9IGdlbmVyYXRlU2hhZGVyRnVuY05hbWVGcm9tSW5wdXRTYW1wbGVyTmFtZShzYW1wbGVyTmFtZSk7XG4gICAgICBpZiAoaW5wdXRMYXlvdXQuaXNQYWNrZWQpIHtcbiAgICAgICAgcmVzdWx0W2Z1bmNOYW1lXSA9IHRoaXMuZ2V0UGFja2VkU2FtcGxlckZyb21JbnB1dChmdW5jTmFtZSwgc2FtcGxlck5hbWUsIGlucHV0TGF5b3V0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPSB0aGlzLmdldFVucGFja2VkU2FtcGxlckZyb21JbnB1dChmdW5jTmFtZSwgc2FtcGxlck5hbWUsIGlucHV0TGF5b3V0KTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb3V0Q29vcmRGdW5jTmFtZSA9IGdlbmVyYXRlU2hhZGVyRnVuY05hbWVGcm9tSW5wdXRTYW1wbGVyTmFtZUF0T3V0Q29vcmRzKHNhbXBsZXJOYW1lKTtcbiAgICAgIGlmIChpbnB1dExheW91dC51bnBhY2tlZFNoYXBlLmxlbmd0aCA8PSBvdXRwdXRMYXlvdXQudW5wYWNrZWRTaGFwZS5sZW5ndGgpIHtcbiAgICAgICAgaWYgKGlucHV0TGF5b3V0LmlzUGFja2VkKSB7XG4gICAgICAgICAgcmVzdWx0W291dENvb3JkRnVuY05hbWVdID1cbiAgICAgICAgICAgICAgdGhpcy5nZXRQYWNrZWRTYW1wbGVyQXRPdXRwdXRDb29yZHMob3V0Q29vcmRGdW5jTmFtZSwgaW5wdXRMYXlvdXQsIG91dHB1dExheW91dCwgc2FtcGxlck5hbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc3VsdFtvdXRDb29yZEZ1bmNOYW1lXSA9XG4gICAgICAgICAgICAgIHRoaXMuZ2V0VW5wYWNrZWRTYW1wbGVyQXRPdXRwdXRDb29yZHMob3V0Q29vcmRGdW5jTmFtZSwgaW5wdXRMYXlvdXQsIG91dHB1dExheW91dCwgc2FtcGxlck5hbWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdGluZyBzbmlwcGV0cyBmb3Igb3V0cHV0IGNvb3JkaW5hdGVzIG9mIHNhbXBsZXJzXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0UGFja2VkU2FtcGxlckF0T3V0cHV0Q29vcmRzKFxuICAgICAgZnVuY05hbWU6IHN0cmluZywgaW5wdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQsIG91dHB1dExheW91dDogVGV4dHVyZUxheW91dCwgbmFtZTogc3RyaW5nKTogR2xzbExpYlJvdXRpbmUge1xuICAgIGNvbnN0IGluU2hhcGUgPSBpbnB1dExheW91dC51bnBhY2tlZFNoYXBlO1xuICAgIGNvbnN0IG91dFNoYXBlID0gb3V0cHV0TGF5b3V0LnVucGFja2VkU2hhcGU7XG4gICAgY29uc3QgdGV4TmFtZSA9IG5hbWU7XG4gICAgY29uc3QgdGV4RnVuY1NuaXBwZXQgPSBnZW5lcmF0ZVNoYWRlckZ1bmNOYW1lRnJvbUlucHV0U2FtcGxlck5hbWUodGV4TmFtZSk7XG5cbiAgICBjb25zdCBpblJhbmsgPSBpblNoYXBlLmxlbmd0aDtcbiAgICBjb25zdCBvdXRSYW5rID0gb3V0U2hhcGUubGVuZ3RoO1xuXG4gICAgY29uc3QgYnJvYWRjYXN0RGltcyA9IEJyb2FkY2FzdFV0aWwuZ2V0QnJvYWRjYXN0RGltcyhpblNoYXBlLCBvdXRTaGFwZSk7XG5cbiAgICBjb25zdCB0eXBlID0gZ2V0Q29vcmRzRGF0YVR5cGUob3V0UmFuayk7XG4gICAgY29uc3QgcmFua0RpZmYgPSBvdXRSYW5rIC0gaW5SYW5rO1xuICAgIGxldCBjb29yZHNTbmlwcGV0OiBzdHJpbmc7XG4gICAgY29uc3QgZmllbGRzID0gZ2V0R2xDaGFubmVscygpO1xuXG4gICAgaWYgKGluUmFuayA9PT0gMCkge1xuICAgICAgY29vcmRzU25pcHBldCA9ICcnO1xuICAgIH0gZWxzZSBpZiAob3V0UmFuayA8IDIgJiYgYnJvYWRjYXN0RGltcy5sZW5ndGggPj0gMSkge1xuICAgICAgY29vcmRzU25pcHBldCA9ICdjb29yZHMgPSAwOyc7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvb3Jkc1NuaXBwZXQgPSBicm9hZGNhc3REaW1zLm1hcChkID0+IGBjb29yZHMuJHtmaWVsZHNbZCArIHJhbmtEaWZmXX0gPSAwO2ApLmpvaW4oJ1xcbicpO1xuICAgIH1cbiAgICBsZXQgdW5wYWNrZWRDb29yZHNTbmlwcGV0ID0gJyc7XG4gICAgaWYgKG91dFJhbmsgPCAyICYmIGluUmFuayA+IDApIHtcbiAgICAgIHVucGFja2VkQ29vcmRzU25pcHBldCA9ICdjb29yZHMnO1xuICAgIH0gZWxzZSB7XG4gICAgICB1bnBhY2tlZENvb3Jkc1NuaXBwZXQgPSBpblNoYXBlLm1hcCgocywgaSkgPT4gYGNvb3Jkcy4ke2ZpZWxkc1tpICsgcmFua0RpZmZdfWApLmpvaW4oJywgJyk7XG4gICAgfVxuXG4gICAgbGV0IG91dHB1dCA9ICdyZXR1cm4gb3V0cHV0VmFsdWU7JztcbiAgICBjb25zdCBpblNpemUgPSBTaGFwZVV0aWwuc2l6ZShpblNoYXBlKTtcbiAgICBjb25zdCBpc0lucHV0U2NhbGFyID0gaW5TaXplID09PSAxO1xuICAgIGNvbnN0IG91dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRTaGFwZSk7XG4gICAgY29uc3QgaXNPdXRwdXRTY2FsYXIgPSBvdXRTaXplID09PSAxO1xuXG4gICAgaWYgKGluUmFuayA9PT0gMSAmJiAhaXNJbnB1dFNjYWxhciAmJiAhaXNPdXRwdXRTY2FsYXIpIHtcbiAgICAgIG91dHB1dCA9IGBcbiAgICAgICAgcmV0dXJuIHZlYzQob3V0cHV0VmFsdWUueHksIG91dHB1dFZhbHVlLnh5KTtcbiAgICAgIGA7XG4gICAgfSBlbHNlIGlmIChpc0lucHV0U2NhbGFyICYmICFpc091dHB1dFNjYWxhcikge1xuICAgICAgaWYgKG91dFJhbmsgPT09IDEpIHtcbiAgICAgICAgb3V0cHV0ID0gYFxuICAgICAgICAgIHJldHVybiB2ZWM0KG91dHB1dFZhbHVlLngsIG91dHB1dFZhbHVlLngsIDAuLCAwLik7XG4gICAgICAgIGA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvdXRwdXQgPSBgXG4gICAgICAgICAgcmV0dXJuIHZlYzQob3V0cHV0VmFsdWUueCk7XG4gICAgICAgIGA7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChicm9hZGNhc3REaW1zLmxlbmd0aCkge1xuICAgICAgY29uc3Qgcm93cyA9IGluUmFuayAtIDI7XG4gICAgICBjb25zdCBjb2xzID0gaW5SYW5rIC0gMTtcblxuICAgICAgaWYgKGJyb2FkY2FzdERpbXMuaW5kZXhPZihyb3dzKSA+IC0xICYmIGJyb2FkY2FzdERpbXMuaW5kZXhPZihjb2xzKSA+IC0xKSB7XG4gICAgICAgIG91dHB1dCA9ICdyZXR1cm4gdmVjNChvdXRwdXRWYWx1ZS54KTsnO1xuICAgICAgfSBlbHNlIGlmIChicm9hZGNhc3REaW1zLmluZGV4T2Yocm93cykgPiAtMSkge1xuICAgICAgICBvdXRwdXQgPSAncmV0dXJuIHZlYzQob3V0cHV0VmFsdWUueCwgb3V0cHV0VmFsdWUueSwgJyArXG4gICAgICAgICAgICAnb3V0cHV0VmFsdWUueCwgb3V0cHV0VmFsdWUueSk7JztcbiAgICAgIH0gZWxzZSBpZiAoYnJvYWRjYXN0RGltcy5pbmRleE9mKGNvbHMpID4gLTEpIHtcbiAgICAgICAgb3V0cHV0ID0gJ3JldHVybiB2ZWM0KG91dHB1dFZhbHVlLnh4LCBvdXRwdXRWYWx1ZS56eik7JztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBzd2FwTGFzdERpbXNTbmlwcGV0ID0gYFxuICAgICAgICBpbnQgbGFzdERpbSA9IGNvb3Jkcy4ke2ZpZWxkc1tvdXRSYW5rIC0gMV19O1xuICAgICAgICBjb29yZHMuJHtmaWVsZHNbb3V0UmFuayAtIDFdfSA9IGNvb3Jkcy4ke2ZpZWxkc1tvdXRSYW5rIC0gMl19O1xuICAgICAgICBjb29yZHMuJHtmaWVsZHNbb3V0UmFuayAtIDJdfSA9IGxhc3REaW07XG4gICAgICBgO1xuICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgIHZlYzQgJHtmdW5jTmFtZX0oKSB7XG4gICAgICAgICR7dHlwZX0gY29vcmRzID0gZ2V0T3V0cHV0Q29vcmRzKCk7XG4gICAgICAgICR7c3dhcExhc3REaW1zU25pcHBldH1cbiAgICAgICAgJHtjb29yZHNTbmlwcGV0fVxuICAgICAgICB2ZWM0IG91dHB1dFZhbHVlID0gJHt0ZXhGdW5jU25pcHBldH0oJHt1bnBhY2tlZENvb3Jkc1NuaXBwZXR9KTtcbiAgICAgICAgJHtvdXRwdXR9XG4gICAgICB9XG4gICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSwgWydjb29yZGluYXRlcy5nZXRPdXRwdXRDb29yZHMnXSk7XG4gIH1cblxuICAvKipcbiAgICogQ29uc3RydWN0aW5nIHNuaXBwZXRzIGZvciB1bnBhY2tlZCBvdXRwdXQgY29vcmRpbmF0ZXMgb2Ygc2FtcGxlcnNcbiAgICovXG4gIHByb3RlY3RlZCBnZXRVbnBhY2tlZFNhbXBsZXJBdE91dHB1dENvb3JkcyhcbiAgICAgIGZ1bmNOYW1lOiBzdHJpbmcsIGlucHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0LCBvdXRwdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQsIG5hbWU6IHN0cmluZyk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBjb25zdCBvdXRUZXhTaGFwZSA9IFtvdXRwdXRMYXlvdXQud2lkdGgsIG91dHB1dExheW91dC5oZWlnaHRdO1xuICAgIGNvbnN0IGluVGV4U2hhcGUgPSBbaW5wdXRMYXlvdXQud2lkdGgsIGlucHV0TGF5b3V0LmhlaWdodF07XG4gICAgY29uc3QgaW5SYW5rID0gaW5wdXRMYXlvdXQudW5wYWNrZWRTaGFwZS5sZW5ndGg7XG4gICAgY29uc3Qgb3V0UmFuayA9IG91dHB1dExheW91dC51bnBhY2tlZFNoYXBlLmxlbmd0aDtcbiAgICBjb25zdCBpblNoYXBlID0gaW5wdXRMYXlvdXQudW5wYWNrZWRTaGFwZTtcbiAgICBjb25zdCBvdXRTaGFwZSA9IG91dHB1dExheW91dC51bnBhY2tlZFNoYXBlO1xuICAgIGNvbnN0IHRleEZ1bmNTbmlwcGV0ID0gZ2VuZXJhdGVTaGFkZXJGdW5jTmFtZUZyb21JbnB1dFNhbXBsZXJOYW1lKG5hbWUpO1xuXG4gICAgaWYgKGluUmFuayA9PT0gb3V0UmFuayAmJiBBcnJheVV0aWwuYXJyYXlzRXF1YWwoaW5UZXhTaGFwZSwgb3V0VGV4U2hhcGUpKSB7XG4gICAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgICAgZmxvYXQgJHtmdW5jTmFtZX0oKSB7XG4gICAgICAgICAgICByZXR1cm4gc2FtcGxlVGV4dHVyZSgke25hbWV9LCBUZXhDb29yZHMpO1xuICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnNhbXBsZVRleHR1cmUnXSk7XG4gICAgfVxuXG4gICAgY29uc3QgdHlwZSA9IGdldENvb3Jkc0RhdGFUeXBlKG91dFJhbmspO1xuICAgIGNvbnN0IGJyb2FkY2FzdERpbXMgPSBCcm9hZGNhc3RVdGlsLmdldEJyb2FkY2FzdERpbXMoaW5TaGFwZSwgb3V0U2hhcGUpO1xuICAgIGNvbnN0IHJhbmtEaWZmID0gb3V0UmFuayAtIGluUmFuaztcbiAgICBsZXQgY29vcmRzU25pcHBldDogc3RyaW5nO1xuICAgIGNvbnN0IGZpZWxkcyA9IGdldEdsQ2hhbm5lbHMoKTtcblxuICAgIGlmIChpblJhbmsgPT09IDApIHtcbiAgICAgIGNvb3Jkc1NuaXBwZXQgPSAnJztcbiAgICB9IGVsc2UgaWYgKG91dFJhbmsgPCAyICYmIGJyb2FkY2FzdERpbXMubGVuZ3RoID49IDEpIHtcbiAgICAgIGNvb3Jkc1NuaXBwZXQgPSAnY29vcmRzID0gMDsnO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb29yZHNTbmlwcGV0ID0gYnJvYWRjYXN0RGltcy5tYXAoZCA9PiBgY29vcmRzLiR7ZmllbGRzW2QgKyByYW5rRGlmZl19ID0gMDtgKS5qb2luKCdcXG4nKTtcbiAgICB9XG4gICAgbGV0IHVucGFja2VkQ29vcmRzU25pcHBldCA9ICcnO1xuICAgIGlmIChvdXRSYW5rIDwgMiAmJiBpblJhbmsgPiAwKSB7XG4gICAgICB1bnBhY2tlZENvb3Jkc1NuaXBwZXQgPSAnY29vcmRzJztcbiAgICB9IGVsc2Uge1xuICAgICAgdW5wYWNrZWRDb29yZHNTbmlwcGV0ID0gaW5wdXRMYXlvdXQudW5wYWNrZWRTaGFwZS5tYXAoKHMsIGkpID0+IGBjb29yZHMuJHtmaWVsZHNbaSArIHJhbmtEaWZmXX1gKS5qb2luKCcsICcpO1xuICAgIH1cbiAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KCkge1xuICAgICAgICAgICR7dHlwZX0gY29vcmRzID0gZ2V0T3V0cHV0Q29vcmRzKCk7XG4gICAgICAgICAgJHtjb29yZHNTbmlwcGV0fVxuICAgICAgICAgIHJldHVybiAke3RleEZ1bmNTbmlwcGV0fSgke3VucGFja2VkQ29vcmRzU25pcHBldH0pO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCBbJ2Nvb3JkaW5hdGVzLmdldE91dHB1dENvb3JkcyddKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3Rpbmcgc25pcHBldHMgZm9yIHBhY2tlZCBvcGVyYXRpb25zLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFBhY2tlZFNhbXBsZXJGcm9tSW5wdXQoZnVuY05hbWU6IHN0cmluZywgbmFtZTogc3RyaW5nLCBpbnB1dExheW91dDogVGV4dHVyZUxheW91dCk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBzd2l0Y2ggKGlucHV0TGF5b3V0LnVucGFja2VkU2hhcGUubGVuZ3RoKSB7XG4gICAgICBjYXNlIDA6XG4gICAgICAgIHJldHVybiB0aGlzLmdldFBhY2tlZFNhbXBsZXJTY2FsYXIoZnVuY05hbWUsIG5hbWUpO1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gdGhpcy5nZXRQYWNrZWRTYW1wbGVyMUQoZnVuY05hbWUsIG5hbWUsIGlucHV0TGF5b3V0KTtcbiAgICAgIGNhc2UgMjpcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UGFja2VkU2FtcGxlcjJEKGZ1bmNOYW1lLCBuYW1lLCBpbnB1dExheW91dCk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmdldFBhY2tlZFNhbXBsZXIzRChmdW5jTmFtZSwgbmFtZSwgaW5wdXRMYXlvdXQpO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UGFja2VkU2FtcGxlck5EKGZ1bmNOYW1lLCBuYW1lLCBpbnB1dExheW91dCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdGluZyBzbmlwcGV0cyBmb3IgdW5wYWNrZWQgb3BlcmF0aW9ucy5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRVbnBhY2tlZFNhbXBsZXJGcm9tSW5wdXQoZnVuY05hbWU6IHN0cmluZywgbmFtZTogc3RyaW5nLCBpbnB1dExheW91dDogVGV4dHVyZUxheW91dCk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBjb25zdCBzaGFwZSA9IGlucHV0TGF5b3V0LnVucGFja2VkU2hhcGU7XG4gICAgc3dpdGNoIChzaGFwZS5sZW5ndGgpIHtcbiAgICAgIGNhc2UgMDpcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0VW5wYWNrZWRTYW1wbGVyU2NhbGFyKGZ1bmNOYW1lLCBuYW1lLCBpbnB1dExheW91dCk7XG4gICAgICBjYXNlIDE6XG4gICAgICAgIHJldHVybiB0aGlzLmdldFVucGFja2VkU2FtcGxlcjFEKGZ1bmNOYW1lLCBuYW1lLCBpbnB1dExheW91dCk7XG4gICAgICBjYXNlIDI6XG4gICAgICAgIHJldHVybiB0aGlzLmdldFVucGFja2VkU2FtcGxlcjJEKGZ1bmNOYW1lLCBuYW1lLCBpbnB1dExheW91dCk7XG4gICAgICBjYXNlIDM6XG4gICAgICAgIHJldHVybiB0aGlzLmdldFVucGFja2VkU2FtcGxlcjNEKGZ1bmNOYW1lLCBuYW1lLCBpbnB1dExheW91dCk7XG4gICAgICBjYXNlIDQ6XG4gICAgICAgIHJldHVybiB0aGlzLmdldFVucGFja2VkU2FtcGxlcjREKGZ1bmNOYW1lLCBuYW1lLCBpbnB1dExheW91dCk7XG4gICAgICBjYXNlIDU6XG4gICAgICAgIHJldHVybiB0aGlzLmdldFVucGFja2VkU2FtcGxlcjVEKGZ1bmNOYW1lLCBuYW1lLCBpbnB1dExheW91dCk7XG4gICAgICBjYXNlIDY6XG4gICAgICAgIHJldHVybiB0aGlzLmdldFVucGFja2VkU2FtcGxlcjZEKGZ1bmNOYW1lLCBuYW1lLCBpbnB1dExheW91dCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICAvLyBUT0RPIHN1cHBvcnQgbW9yZSBkaW1lbnNpb25hbGl0aWVzXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgZGltZW5zaW9uICR7c2hhcGUubGVuZ3RofS1EYCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBhY2tlZCBzY2FsYXIgc25pcHBldC5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRQYWNrZWRTYW1wbGVyU2NhbGFyKGZ1bmNOYW1lOiBzdHJpbmcsIG5hbWU6IHN0cmluZyk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBjb25zdCBnbHNsID0gZ2V0R2xzbCh0aGlzLmNvbnRleHQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgICB2ZWM0ICR7ZnVuY05hbWV9KCkge1xuICAgICAgICAgICAgcmV0dXJuICR7Z2xzbC50ZXh0dXJlMkR9KCR7bmFtZX0sIGhhbGZDUik7XG4gICAgICAgICAgfVxuICAgICAgICBgO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYWNrZWQgMUQgc25pcHBldC5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRQYWNrZWRTYW1wbGVyMUQoZnVuY05hbWU6IHN0cmluZywgbmFtZTogc3RyaW5nLCBpbnB1dExheW91dDogVGV4dHVyZUxheW91dCk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBjb25zdCB0ZXhTaGFwZSA9IFtpbnB1dExheW91dC53aWR0aCwgaW5wdXRMYXlvdXQuaGVpZ2h0XTtcbiAgICBjb25zdCBwYWNrZWRUZXhTaGFwZSA9IFt0ZXhTaGFwZVsxXSwgdGV4U2hhcGVbMF1dO1xuICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKHRoaXMuY29udGV4dC5nbENvbnRleHQudmVyc2lvbik7XG5cbiAgICBjb25zdCBwYWNrZWRTYW1wbGVyID0gYHZlYzQgJHtmdW5jTmFtZX0oaW50IGluZGV4KSB7XG4gICAgICB2ZWMyIHV2ID0gcGFja2VkVVZmcm9tMUQoXG4gICAgICAke3BhY2tlZFRleFNoYXBlWzBdfSwgJHtwYWNrZWRUZXhTaGFwZVsxXX0sIGluZGV4KTtcbiAgICAgIHJldHVybiAke2dsc2wudGV4dHVyZTJEfSgke25hbWV9LCB1dik7XG4gICAgfWA7XG4gICAgY29uc3Qgc291cmNlID0gcGFja2VkU2FtcGxlcjtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSwgWydjb29yZGluYXRlcy5wYWNrZWRVVmZyb20xRCddKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQYWNrZWQgMkQgc25pcHBldC5cbiAgICovXG4gIHByb3RlY3RlZCBnZXRQYWNrZWRTYW1wbGVyMkQoZnVuY05hbWU6IHN0cmluZywgbmFtZTogc3RyaW5nLCBpbnB1dExheW91dDogVGV4dHVyZUxheW91dCk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBjb25zdCBzaGFwZSA9IGlucHV0TGF5b3V0LnVucGFja2VkU2hhcGU7XG4gICAgY29uc3QgdGV4U2hhcGUgPSBbaW5wdXRMYXlvdXQud2lkdGgsIGlucHV0TGF5b3V0LmhlaWdodF07XG4gICAgY29uc3QgZ2xzbCA9IGdldEdsc2wodGhpcy5jb250ZXh0LmdsQ29udGV4dC52ZXJzaW9uKTtcbiAgICBjb25zdCB0ZXhOdW1SID0gdGV4U2hhcGVbMF07XG4gICAgY29uc3QgdGV4TnVtQyA9IHRleFNoYXBlWzFdO1xuXG4gICAgaWYgKHRleFNoYXBlICE9IG51bGwgJiYgQXJyYXlVdGlsLmFycmF5c0VxdWFsKHNoYXBlLCB0ZXhTaGFwZSkpIHtcbiAgICAgIGNvbnN0IHBhY2tlZFNhbXBsZXIgPSBgdmVjNCAke2Z1bmNOYW1lfShpbnQgcm93LCBpbnQgY29sKSB7XG4gICAgICAgIHZlYzIgdXYgPSAodmVjMihjb2wsIHJvdykgKyBoYWxmQ1IpIC8gdmVjMigke3RleE51bUN9LjAsICR7dGV4TnVtUn0uMCk7XG4gICAgICAgIHJldHVybiAke2dsc2wudGV4dHVyZTJEfSgke25hbWV9LCB1dik7XG4gICAgICB9YDtcblxuICAgICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShwYWNrZWRTYW1wbGVyKTtcbiAgICB9XG4gICAgY29uc3QgcGFja2VkVGV4U2hhcGUgPSB0ZXhTaGFwZTtcbiAgICBjb25zdCB2YWx1ZXNQZXJSb3cgPSBNYXRoLmNlaWwoc2hhcGVbMV0gLyAyKTtcbiAgICBjb25zdCBwYWNrZWRTYW1wbGVyID0gYHZlYzQgJHtmdW5jTmFtZX0oaW50IHJvdywgaW50IGNvbCkge1xuICAgICAgdmVjMiB1diA9IHBhY2tlZFVWZnJvbTJEKCR7cGFja2VkVGV4U2hhcGVbMV19LCAke3BhY2tlZFRleFNoYXBlWzBdfSwgJHt2YWx1ZXNQZXJSb3d9LCByb3csIGNvbCk7XG4gICAgICByZXR1cm4gJHtnbHNsLnRleHR1cmUyRH0oJHtuYW1lfSwgdXYpO1xuICAgIH1gO1xuICAgIGNvbnN0IHNvdXJjZSA9IHBhY2tlZFNhbXBsZXI7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UsIFsnY29vcmRpbmF0ZXMucGFja2VkVVZmcm9tMkQnXSk7XG4gIH1cblxuICAvKipcbiAgICogUGFja2VkIDNEIHNuaXBwZXQuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0UGFja2VkU2FtcGxlcjNEKGZ1bmNOYW1lOiBzdHJpbmcsIG5hbWU6IHN0cmluZywgaW5wdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQpOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3Qgc2hhcGUgPSBpbnB1dExheW91dC51bnBhY2tlZFNoYXBlO1xuICAgIGNvbnN0IHRleFNoYXBlID0gW2lucHV0TGF5b3V0LndpZHRoLCBpbnB1dExheW91dC5oZWlnaHRdO1xuICAgIGNvbnN0IHBhY2tlZFRleFNoYXBlID0gW3RleFNoYXBlWzBdLCB0ZXhTaGFwZVsxXV07XG4gICAgY29uc3QgZ2xzbCA9IGdldEdsc2wodGhpcy5jb250ZXh0LmdsQ29udGV4dC52ZXJzaW9uKTtcblxuICAgIGlmIChzaGFwZVswXSA9PT0gMSkge1xuICAgICAgY29uc3Qgc3F1ZWV6ZWRTaGFwZSA9IHNoYXBlLnNsaWNlKDEpO1xuICAgICAgY29uc3Qga2VwdERpbXMgPSBbMSwgMl07XG4gICAgICBjb25zdCBuZXdJbnB1dFNoYXBlID0gc3F1ZWV6ZUlucHV0U2hhcGUoc2hhcGUsIHNxdWVlemVkU2hhcGUpO1xuICAgICAgY29uc3QgcGFyYW1zID0gWydiJywgJ3JvdycsICdjb2wnXTtcbiAgICAgIC8vIERlZXAgY29weSBvZiBpbnB1dCB0ZXh0dXJlIGxheW91dC5cbiAgICAgIGNvbnN0IG5ld0lucHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0ID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShpbnB1dExheW91dCkpO1xuICAgICAgbmV3SW5wdXRMYXlvdXQudW5wYWNrZWRTaGFwZSA9IG5ld0lucHV0U2hhcGU7XG4gICAgICBjb25zdCBzYW1wbGVyUm91dGluZSA9IHRoaXMuZ2V0UGFja2VkU2FtcGxlckZyb21JbnB1dChmdW5jTmFtZSwgbmFtZSwgbmV3SW5wdXRMYXlvdXQpO1xuICAgICAgY29uc3QgcGFja2VkU2FtcGxlciA9IGAke3NhbXBsZXJSb3V0aW5lLnJvdXRpbmVCb2R5fVxuICAgICAgdmVjNCAke2Z1bmNOYW1lfShpbnQgYiwgaW50IHJvdywgaW50IGNvbCkge1xuICAgICAgICByZXR1cm4gJHtmdW5jTmFtZX0oJHtnZXRTcXVlZXplZFBhcmFtcyhwYXJhbXMsIGtlcHREaW1zKX0pO1xuICAgICAgfSBgO1xuICAgICAgY29uc3Qgc291cmNlID0gcGFja2VkU2FtcGxlcjtcbiAgICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCBzYW1wbGVyUm91dGluZS5kZXBlbmRlbmNpZXMpO1xuICAgIH1cbiAgICBjb25zdCB0ZXhOdW1SID0gcGFja2VkVGV4U2hhcGVbMF07XG4gICAgY29uc3QgdGV4TnVtQyA9IHBhY2tlZFRleFNoYXBlWzFdO1xuXG4gICAgY29uc3QgdmFsdWVzUGVyUm93ID0gTWF0aC5jZWlsKHNoYXBlWzJdIC8gMik7XG4gICAgY29uc3QgdGV4ZWxzSW5CYXRjaCA9IHZhbHVlc1BlclJvdyAqIE1hdGguY2VpbChzaGFwZVsxXSAvIDIpO1xuXG4gICAgY29uc3QgcGFja2VkU2FtcGxlciA9IGB2ZWM0ICR7ZnVuY05hbWV9KGludCBiLCBpbnQgcm93LCBpbnQgY29sKSB7XG4gICAgICB2ZWMyIHV2ID0gcGFja2VkVVZmcm9tM0QoXG4gICAgICAgICR7dGV4TnVtQ30sICR7dGV4TnVtUn0sICR7dGV4ZWxzSW5CYXRjaH0sICR7dmFsdWVzUGVyUm93fSwgYiwgcm93LCBjb2wpO1xuICAgICAgcmV0dXJuICR7Z2xzbC50ZXh0dXJlMkR9KCR7bmFtZX0sIHV2KTt9YDtcbiAgICBjb25zdCBzb3VyY2UgPSBwYWNrZWRTYW1wbGVyO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnBhY2tlZFVWZnJvbTNEJ10pO1xuICB9XG4gIC8qXG4gICAqIFBhY2tlZCBORCBzbmlwcGV0LlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFBhY2tlZFNhbXBsZXJORChmdW5jTmFtZTogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIGlucHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0KTogR2xzbExpYlJvdXRpbmUge1xuICAgIGNvbnN0IHNoYXBlID0gaW5wdXRMYXlvdXQudW5wYWNrZWRTaGFwZTtcbiAgICBjb25zdCByYW5rID0gc2hhcGUubGVuZ3RoO1xuICAgIGNvbnN0IHRleFNoYXBlID0gW2lucHV0TGF5b3V0LndpZHRoLCBpbnB1dExheW91dC5oZWlnaHRdO1xuICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKHRoaXMuY29udGV4dC5nbENvbnRleHQudmVyc2lvbik7XG5cbiAgICBjb25zdCBwYWNrZWRUZXhTaGFwZSA9IFt0ZXhTaGFwZVswXSwgdGV4U2hhcGVbMV1dO1xuICAgIGNvbnN0IHRleE51bVIgPSBwYWNrZWRUZXhTaGFwZVsxXTtcbiAgICBjb25zdCB0ZXhOdW1DID0gcGFja2VkVGV4U2hhcGVbMF07XG4gICAgY29uc3QgdmFsdWVzUGVyUm93ID0gTWF0aC5jZWlsKHNoYXBlW3JhbmsgLSAxXSAvIDIpO1xuICAgIGxldCB0ZXhlbHNJbkJhdGNoID0gdmFsdWVzUGVyUm93ICogTWF0aC5jZWlsKHNoYXBlW3JhbmsgLSAyXSAvIDIpO1xuICAgIGxldCBwYXJhbXMgPSAnaW50IGIsIGludCByb3csIGludCBjb2wnO1xuICAgIGxldCBpbmRleCA9IGBiICogJHt0ZXhlbHNJbkJhdGNofSArIChyb3cgLyAyKSAqICR7dmFsdWVzUGVyUm93fSArIChjb2wgLyAyKWA7XG4gICAgZm9yIChsZXQgYiA9IDI7IGIgPCByYW5rIC0gMTsgYisrKSB7XG4gICAgICBwYXJhbXMgPSBgaW50IGIke2J9LCBgICsgcGFyYW1zO1xuICAgICAgdGV4ZWxzSW5CYXRjaCAqPSBzaGFwZVtyYW5rIC0gYiAtIDFdO1xuICAgICAgaW5kZXggPSBgYiR7Yn0gKiAke3RleGVsc0luQmF0Y2h9ICsgYCArIGluZGV4O1xuICAgIH1cbiAgICBjb25zdCBwYWNrZWRTYW1wbGVyID0gYHZlYzQgJHtmdW5jTmFtZX0oJHtwYXJhbXN9KSB7XG4gICAgICBpbnQgaW5kZXggPSAke2luZGV4fTtcbiAgICAgIGludCB0ZXhSID0gaW5kZXggLyAke3RleE51bUN9O1xuICAgICAgaW50IHRleEMgPSBpbmRleCAtIHRleFIgKiAke3RleE51bUN9O1xuICAgICAgdmVjMiB1diA9ICh2ZWMyKHRleEMsIHRleFIpICsgaGFsZkNSKSAvIHZlYzIoJHt0ZXhOdW1DfSwgJHt0ZXhOdW1SfSk7XG4gICAgICByZXR1cm4gJHtnbHNsLnRleHR1cmUyRH0oJHtuYW1lfSwgdXYpO1xuICAgIH1gO1xuICAgIGNvbnN0IHNvdXJjZSA9IHBhY2tlZFNhbXBsZXI7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVucGFja2VkIHNjYWxhciBzbmlwcGV0LlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFVucGFja2VkU2FtcGxlclNjYWxhcihmdW5jTmFtZTogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIGlucHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0KTogR2xzbExpYlJvdXRpbmUge1xuICAgIGNvbnN0IFt0ZXhOdW1SLCB0ZXhOdW1DXSA9IFtpbnB1dExheW91dC53aWR0aCwgaW5wdXRMYXlvdXQuaGVpZ2h0XTtcbiAgICBpZiAodGV4TnVtUiA9PT0gMSAmJiB0ZXhOdW1DID09PSAxKSB7XG4gICAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgICAgZmxvYXQgJHtmdW5jTmFtZX0oKSB7XG4gICAgICAgICAgICByZXR1cm4gc2FtcGxlVGV4dHVyZSgke25hbWV9LCBoYWxmQ1IpO1xuICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnNhbXBsZVRleHR1cmUnXSk7XG4gICAgfVxuXG4gICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfSgpIHtcbiAgICAgICAgICBpbnQgb2Zmc2V0XyR7bmFtZX0gPSBjb29yZHNUb09mZnNldChUZXhDb29yZHMsICR7dGV4TnVtUn0sICR7dGV4TnVtQ30pO1xuICAgICAgICAgIHZlYzIgdXYgPSB1dkZyb21GbGF0KCR7dGV4TnVtUn0sICR7dGV4TnVtQ30sIG9mZnNldF8ke25hbWV9KTtcbiAgICAgICAgICByZXR1cm4gc2FtcGxlVGV4dHVyZSgke25hbWV9LCB1dik7XG4gICAgICAgIH1cbiAgICAgIGA7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShcbiAgICAgICAgc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnV2RnJvbUZsYXQnLCAnY29vcmRpbmF0ZXMuc2FtcGxlVGV4dHVyZScsICdjb29yZGluYXRlcy5jb29yZHNUb09mZnNldCddKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnBhY2tlZCAxRCBzbmlwcGV0LlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFVucGFja2VkU2FtcGxlcjFEKGZ1bmNOYW1lOiBzdHJpbmcsIG5hbWU6IHN0cmluZywgaW5wdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQpOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3QgdE51bVIgPSBpbnB1dExheW91dC53aWR0aDtcbiAgICBjb25zdCB0TnVtQyA9IGlucHV0TGF5b3V0LmhlaWdodDtcblxuICAgIGlmICh0TnVtQyA9PT0gMSAmJiB0TnVtUiA9PT0gMSkge1xuICAgICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfShpbnQgaW5kZXgpIHtcbiAgICAgICAgICByZXR1cm4gc2FtcGxlVGV4dHVyZSgke25hbWV9LCBoYWxmQ1IpO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UsIFsnY29vcmRpbmF0ZXMuc2FtcGxlVGV4dHVyZSddKTtcbiAgICB9XG5cbiAgICBpZiAodE51bUMgPT09IDEpIHtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfShpbnQgaW5kZXgpIHtcbiAgICAgICAgICAgIHZlYzIgdXYgPSB2ZWMyKChmbG9hdChpbmRleCkgKyAwLjUpIC8gJHt0TnVtUn0uMCwgMC41KTtcbiAgICAgICAgICAgIHJldHVybiBzYW1wbGVUZXh0dXJlKCR7bmFtZX0sIHV2KTtcbiAgICAgICAgICB9XG4gICAgICAgIGA7XG4gICAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSwgWydjb29yZGluYXRlcy5zYW1wbGVUZXh0dXJlJ10pO1xuICAgIH1cbiAgICBpZiAodE51bVIgPT09IDEpIHtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfShpbnQgaW5kZXgpIHtcbiAgICAgICAgICAgIHZlYzIgdXYgPSB2ZWMyKDAuNSwgKGZsb2F0KGluZGV4KSArIDAuNSkgLyAke3ROdW1DfS4wKTtcbiAgICAgICAgICAgIHJldHVybiBzYW1wbGVUZXh0dXJlKCR7bmFtZX0sIHV2KTtcbiAgICAgICAgICB9XG4gICAgICAgIGA7XG4gICAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSwgWydjb29yZGluYXRlcy5zYW1wbGVUZXh0dXJlJ10pO1xuICAgIH1cbiAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KGludCBpbmRleCkge1xuICAgICAgICAgIHZlYzIgdXYgPSB1dkZyb21GbGF0KCR7dE51bVJ9LCAke3ROdW1DfSwgaW5kZXgpO1xuICAgICAgICAgIHJldHVybiBzYW1wbGVUZXh0dXJlKCR7bmFtZX0sIHV2KTtcbiAgICAgICAgfVxuICAgICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSwgWydjb29yZGluYXRlcy51dkZyb21GbGF0JywgJ2Nvb3JkaW5hdGVzLnNhbXBsZVRleHR1cmUnXSk7XG4gIH1cblxuICAvKipcbiAgICogVW5wYWNrZWQgMkQgc25pcHBldC5cbiAgICovXG5cbiAgcHJvdGVjdGVkIGdldFVucGFja2VkU2FtcGxlcjJEKGZ1bmNOYW1lOiBzdHJpbmcsIG5hbWU6IHN0cmluZywgaW5wdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQpOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3Qgc2hhcGUgPSBpbnB1dExheW91dC51bnBhY2tlZFNoYXBlO1xuXG4gICAgLy8gVE9ETzogbW9kaWZ5IHJvdy9jb2wgb3JkZXIgZm9yIG90aGVyIGRpbWVuc2lvbnMuXG4gICAgY29uc3QgdGV4U2hhcGUgPSBbaW5wdXRMYXlvdXQuaGVpZ2h0LCBpbnB1dExheW91dC53aWR0aF07XG5cbiAgICBpZiAodGV4U2hhcGUgIT0gbnVsbCAmJiBBcnJheVV0aWwuYXJyYXlzRXF1YWwoc2hhcGUsIHRleFNoYXBlKSkge1xuICAgICAgY29uc3QgdGV4TnVtUiA9IHRleFNoYXBlWzFdO1xuICAgICAgY29uc3QgdGV4TnVtQyA9IHRleFNoYXBlWzBdO1xuICAgICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KGludCByb3csIGludCBjb2wpIHtcbiAgICAgICAgICAgIHZlYzIgdXYgPSAodmVjMihyb3csIGNvbCkgKyBoYWxmQ1IpIC8gdmVjMigke3RleE51bVJ9LjAsICR7dGV4TnVtQ30uMCk7XG4gICAgICAgICAgICByZXR1cm4gc2FtcGxlVGV4dHVyZSgke25hbWV9LCB1dik7XG4gICAgICAgICAgfVxuICAgICAgICBgO1xuICAgICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UsIFsnY29vcmRpbmF0ZXMuc2FtcGxlVGV4dHVyZSddKTtcbiAgICB9XG5cbiAgICBjb25zdCB7bmV3U2hhcGUsIGtlcHREaW1zfSA9IHNxdWVlemVTaGFwZShzaGFwZSBhcyBudW1iZXJbXSk7XG4gICAgY29uc3Qgc3F1ZWV6ZWRTaGFwZSA9IG5ld1NoYXBlO1xuICAgIGlmIChzcXVlZXplZFNoYXBlLmxlbmd0aCA8IHNoYXBlLmxlbmd0aCkge1xuICAgICAgY29uc3QgbmV3SW5wdXRTaGFwZSA9IHNxdWVlemVJbnB1dFNoYXBlKHNoYXBlLCBzcXVlZXplZFNoYXBlKTtcbiAgICAgIC8vIERlZXAgY29weSBvZiBpbnB1dCB0ZXh0dXJlIGxheW91dC5cbiAgICAgIGNvbnN0IG5ld0lucHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0ID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShpbnB1dExheW91dCkpO1xuICAgICAgbmV3SW5wdXRMYXlvdXQudW5wYWNrZWRTaGFwZSA9IG5ld0lucHV0U2hhcGU7XG5cbiAgICAgIGNvbnN0IHBhcmFtcyA9IFsnY29sJywgJ3JvdyddO1xuICAgICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICAgICR7dGhpcy5nZXRVbnBhY2tlZFNhbXBsZXJGcm9tSW5wdXQoZnVuY05hbWUsIG5hbWUsIG5ld0lucHV0TGF5b3V0KS5yb3V0aW5lQm9keX1cbiAgICAgICAgICBmbG9hdCAke2Z1bmNOYW1lfShpbnQgcm93LCBpbnQgY29sKSB7XG4gICAgICAgICAgICByZXR1cm4gJHtmdW5jTmFtZX0oJHtnZXRTcXVlZXplZFBhcmFtcyhwYXJhbXMsIGtlcHREaW1zKX0pO1xuICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnNhbXBsZVRleHR1cmUnXSk7XG4gICAgfVxuXG4gICAgY29uc3QgdGV4TnVtUiA9IHRleFNoYXBlWzFdO1xuICAgIGNvbnN0IHRleE51bUMgPSB0ZXhTaGFwZVswXTtcbiAgICBpZiAodGV4TnVtQyA9PT0gMSkge1xuICAgICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KGludCByb3csIGludCBjb2wpIHtcbiAgICAgICAgICAgIGludCBvZmZzZXRfJHtuYW1lfSA9IGNvb3Jkc1RvT2Zmc2V0KFRleENvb3JkcywgJHt0ZXhOdW1SfSwgJHt0ZXhOdW1DfSk7XG4gICAgICAgICAgICBmbG9hdCBpbmRleCA9IGRvdCh2ZWMzKHJvdywgY29sLCBvZmZzZXRfJHtuYW1lfSksIHZlYzMoJHtzaGFwZVsxXX0sIDEsIDEpKTtcbiAgICAgICAgICAgIHZlYzIgdXYgPSB2ZWMyKDAuNSwgKGluZGV4ICsgMC41KSAvICR7dGV4TnVtUn0uMCk7XG4gICAgICAgICAgICByZXR1cm4gc2FtcGxlVGV4dHVyZSgke25hbWV9LCB1dik7XG4gICAgICAgICAgfVxuICAgICAgICBgO1xuICAgICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UsIFsnY29vcmRpbmF0ZXMuc2FtcGxlVGV4dHVyZScsICdjb29yZGluYXRlcy5jb29yZHNUb09mZnNldCddKTtcbiAgICB9XG5cbiAgICBpZiAodGV4TnVtUiA9PT0gMSkge1xuICAgICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KGludCByb3csIGludCBjb2wpIHtcbiAgICAgICAgICAgIGludCBvZmZzZXRfJHtuYW1lfSA9IGNvb3Jkc1RvT2Zmc2V0KFRleENvb3JkcywgJHt0ZXhOdW1SfSwgJHt0ZXhOdW1DfSk7XG4gICAgICAgICAgICBmbG9hdCBpbmRleCA9IGRvdCh2ZWMzKHJvdywgY29sLCBvZmZzZXRfJHtuYW1lfSksIHZlYzMoJHtzaGFwZVsxXX0sIDEsIDEpKTtcbiAgICAgICAgICAgIHZlYzIgdXYgPSB2ZWMyKChpbmRleCArIDAuNSkgLyAke3RleE51bUN9LjAsIDAuNSk7XG4gICAgICAgICAgICByZXR1cm4gc2FtcGxlVGV4dHVyZSgke25hbWV9LCB1dik7XG4gICAgICAgICAgfVxuICAgICAgICBgO1xuICAgICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UsIFsnY29vcmRpbmF0ZXMuc2FtcGxlVGV4dHVyZScsICdjb29yZGluYXRlcy5jb29yZHNUb09mZnNldCddKTtcbiAgICB9XG5cbiAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KGludCByb3csIGludCBjb2wpIHtcbiAgICAgICAgICBpbnQgaW5kZXggPSBjb2wgKiAke3NoYXBlWzFdfSArIHJvdztcbiAgICAgICAgICB2ZWMyIHV2ID0gdXZGcm9tRmxhdCgke3RleE51bVJ9LCAke3RleE51bUN9LCBpbmRleCk7XG4gICAgICAgICAgcmV0dXJuIHNhbXBsZVRleHR1cmUoJHtuYW1lfSwgdXYpO1xuICAgICAgICB9XG4gICAgICBgO1xuICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoXG4gICAgICAgIHNvdXJjZSwgWydjb29yZGluYXRlcy51dkZyb21GbGF0JywgJ2Nvb3JkaW5hdGVzLnNhbXBsZVRleHR1cmUnLCAnY29vcmRpbmF0ZXMuY29vcmRzVG9PZmZzZXQnXSk7XG4gIH1cblxuICAvKipcbiAgICogVW5wYWNrZWQgM0Qgc25pcHBldC5cbiAgICovXG5cbiAgcHJvdGVjdGVkIGdldFVucGFja2VkU2FtcGxlcjNEKGZ1bmNOYW1lOiBzdHJpbmcsIG5hbWU6IHN0cmluZywgaW5wdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQpOiBHbHNsTGliUm91dGluZSB7XG4gICAgY29uc3Qgc2hhcGUgPSBpbnB1dExheW91dC51bnBhY2tlZFNoYXBlO1xuICAgIGNvbnN0IHN0cmlkZTAgPSBzaGFwZVsxXSAqIHNoYXBlWzJdO1xuICAgIGNvbnN0IHN0cmlkZTEgPSBzaGFwZVsyXTtcblxuICAgIGNvbnN0IHtuZXdTaGFwZSwga2VwdERpbXN9ID0gc3F1ZWV6ZVNoYXBlKHNoYXBlIGFzIG51bWJlcltdKTtcbiAgICBjb25zdCBzcXVlZXplZFNoYXBlID0gbmV3U2hhcGU7XG4gICAgaWYgKHNxdWVlemVkU2hhcGUubGVuZ3RoIDwgc2hhcGUubGVuZ3RoKSB7XG4gICAgICBjb25zdCBuZXdJbnB1dFNoYXBlID0gc3F1ZWV6ZUlucHV0U2hhcGUoc2hhcGUsIHNxdWVlemVkU2hhcGUpO1xuICAgICAgY29uc3QgcGFyYW1zID0gWydiYXRjaCcsICdjb2wnLCAncm93J107XG4gICAgICAvLyBEZWVwIGNvcHkgb2YgaW5wdXQgdGV4dHVyZSBsYXlvdXQuXG4gICAgICBjb25zdCBuZXdJbnB1dExheW91dDogVGV4dHVyZUxheW91dCA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoaW5wdXRMYXlvdXQpKTtcbiAgICAgIG5ld0lucHV0TGF5b3V0LnVucGFja2VkU2hhcGUgPSBuZXdJbnB1dFNoYXBlO1xuICAgICAgY29uc3Qgcm91dGluZSA9IHRoaXMuZ2V0VW5wYWNrZWRTYW1wbGVyRnJvbUlucHV0KGZ1bmNOYW1lLCBuYW1lLCBuZXdJbnB1dExheW91dCk7XG4gICAgICAvLyBUT0RPOiByZXZpc2l0IHRoZSBsb2dpYyBoZXJlIHRvIG1ha2UgaXQgc2ltcGxlclxuICAgICAgY29uc3QgcmV2RGltcyA9IGtlcHREaW1zLnJldmVyc2UoKTtcbiAgICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgICAke3JvdXRpbmUucm91dGluZUJvZHl9XG4gICAgICAgICAgZmxvYXQgJHtmdW5jTmFtZX0oaW50IGJhdGNoLCBpbnQgcm93LCBpbnQgY29sKSB7XG4gICAgICAgICAgICByZXR1cm4gJHtmdW5jTmFtZX0oJHtnZXRTcXVlZXplZFBhcmFtcyhwYXJhbXMsIHJldkRpbXMpfSk7XG4gICAgICAgICAgfVxuICAgICAgICBgO1xuICAgICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UsIHJvdXRpbmUuZGVwZW5kZW5jaWVzKTtcbiAgICB9XG5cbiAgICBjb25zdCB0ZXhOdW1SID0gaW5wdXRMYXlvdXQud2lkdGg7XG4gICAgY29uc3QgdGV4TnVtQyA9IGlucHV0TGF5b3V0LmhlaWdodDtcbiAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgICAgZmxvYXQgJHtmdW5jTmFtZX0oaW50IGRlcHRoLCBpbnQgcm93LCBpbnQgY29sKSB7XG4gICAgICAgICAgICAvLyBFeHBsaWNpdGx5IHVzZSBpbnRlZ2VyIG9wZXJhdGlvbnMgYXMgZG90KCkgb25seSB3b3JrcyBvbiBmbG9hdHMuXG4gICAgICAgICAgICBpbnQgaW5kZXggPSBkZXB0aCAqICR7c3RyaWRlMH0gKyBjb2wgKiAke3N0cmlkZTF9ICsgcm93O1xuICAgICAgICAgICAgdmVjMiB1diA9IHV2RnJvbUZsYXQoJHt0ZXhOdW1SfSwgJHt0ZXhOdW1DfSwgaW5kZXgpO1xuICAgICAgICAgICAgcmV0dXJuIHNhbXBsZVRleHR1cmUoJHtuYW1lfSwgdXYpO1xuICAgICAgICAgIH1cbiAgICAgIGA7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShcbiAgICAgICAgc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnV2RnJvbUZsYXQnLCAnY29vcmRpbmF0ZXMuc2FtcGxlVGV4dHVyZScsICdjb29yZGluYXRlcy5jb29yZHNUb09mZnNldCddKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVbnBhY2tlZCA0RCBzbmlwcGV0LlxuICAgKi9cblxuICBwcm90ZWN0ZWQgZ2V0VW5wYWNrZWRTYW1wbGVyNEQoZnVuY05hbWU6IHN0cmluZywgbmFtZTogc3RyaW5nLCBpbnB1dExheW91dDogVGV4dHVyZUxheW91dCk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBjb25zdCBzaGFwZSA9IGlucHV0TGF5b3V0LnVucGFja2VkU2hhcGU7XG4gICAgY29uc3Qgc3RyaWRlMiA9IHNoYXBlWzNdO1xuICAgIGNvbnN0IHN0cmlkZTEgPSBzaGFwZVsyXSAqIHN0cmlkZTI7XG4gICAgY29uc3Qgc3RyaWRlMCA9IHNoYXBlWzFdICogc3RyaWRlMTtcblxuICAgIC8vXG4gICAgLy8gVE9ETzogcmUtZW5hYmxlIHRoaXMgc2hvcnRjdXQgb25jZSB0aGUgaW5kZXggY2FsY3VsYXRpb24gYnVnIGlzIGZpeGVkLlxuICAgIC8vXG4gICAgLy8gY29uc3Qge25ld1NoYXBlLCBrZXB0RGltc30gPSBzcXVlZXplU2hhcGUoc2hhcGUgYXMgbnVtYmVyW10pO1xuICAgIC8vIGlmIChuZXdTaGFwZS5sZW5ndGggPCBzaGFwZS5sZW5ndGgpIHtcbiAgICAvLyAgIGNvbnN0IG5ld0lucHV0U2hhcGUgPSBzcXVlZXplSW5wdXRTaGFwZShzaGFwZSwgbmV3U2hhcGUpO1xuICAgIC8vICAgY29uc3QgcGFyYW1zID0gWydyb3cnLCAnY29sJywgJ2RlcHRoJywgJ2RlcHRoMiddO1xuICAgIC8vICAgLy8gRGVlcCBjb3B5IG9mIGlucHV0IHRleHR1cmUgbGF5b3V0LlxuICAgIC8vICAgY29uc3QgbmV3SW5wdXRMYXlvdXQ6IFRleHR1cmVMYXlvdXQgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KGlucHV0TGF5b3V0KSk7XG4gICAgLy8gICBuZXdJbnB1dExheW91dC51bnBhY2tlZFNoYXBlID0gbmV3SW5wdXRTaGFwZTtcbiAgICAvLyAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAvLyAgICAgICAke3RoaXMuZ2V0VW5wYWNrZWRTYW1wbGVyRnJvbUlucHV0KGZ1bmNOYW1lLCBuYW1lLCBuZXdJbnB1dExheW91dCkucm91dGluZUJvZHl9XG4gICAgLy8gICAgICAgZmxvYXQgJHtmdW5jTmFtZX0oaW50IHJvdywgaW50IGNvbCwgaW50IGRlcHRoLCBpbnQgZGVwdGgyKSB7XG4gICAgLy8gICAgICAgICByZXR1cm4gJHtmdW5jTmFtZX0oJHtnZXRTcXVlZXplZFBhcmFtcyhwYXJhbXMsIGtlcHREaW1zKX0pO1xuICAgIC8vICAgICAgIH1cbiAgICAvLyAgICAgYDtcbiAgICAvLyAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoXG4gICAgLy8gICAgICAgc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnV2RnJvbUZsYXQnLCAnY29vcmRpbmF0ZXMuc2FtcGxlVGV4dHVyZScsICdjb29yZGluYXRlcy5jb29yZHNUb09mZnNldCddKTtcbiAgICAvLyB9XG5cbiAgICBjb25zdCB0ZXhOdW1SID0gaW5wdXRMYXlvdXQud2lkdGg7XG4gICAgY29uc3QgdGV4TnVtQyA9IGlucHV0TGF5b3V0LmhlaWdodDtcbiAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KGludCByb3csIGludCBjb2wsIGludCBkZXB0aCwgaW50IGRlcHRoMikge1xuICAgICAgICAgIGludCBpbmRleCA9IHJvdyAqICR7c3RyaWRlMH0gKyBjb2wgKiAke3N0cmlkZTF9ICtcbiAgICAgICAgICAgICAgZGVwdGgyICogJHtzdHJpZGUyfSArIGRlcHRoO1xuICAgICAgICAgIHZlYzIgdXYgPSB1dkZyb21GbGF0KCR7dGV4TnVtUn0sICR7dGV4TnVtQ30sIGluZGV4KTtcbiAgICAgICAgICByZXR1cm4gc2FtcGxlVGV4dHVyZSgke25hbWV9LCB1dik7XG4gICAgICAgIH1cbiAgICAgIGA7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UsIFsnY29vcmRpbmF0ZXMudXZGcm9tRmxhdCcsICdjb29yZGluYXRlcy5zYW1wbGVUZXh0dXJlJ10pO1xuICB9XG5cbiAgLyoqXG4gICAqIFVucGFja2VkIDVEIHNuaXBwZXQuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0VW5wYWNrZWRTYW1wbGVyNUQoZnVuY05hbWU6IHN0cmluZywgbmFtZTogc3RyaW5nLCBpbnB1dExheW91dDogVGV4dHVyZUxheW91dCk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBjb25zdCBzaGFwZSA9IGlucHV0TGF5b3V0LnVucGFja2VkU2hhcGU7XG4gICAgY29uc3Qgc3RyaWRlMyA9IHNoYXBlWzRdO1xuICAgIGNvbnN0IHN0cmlkZTIgPSBzaGFwZVszXSAqIHN0cmlkZTM7XG4gICAgY29uc3Qgc3RyaWRlMSA9IHNoYXBlWzJdICogc3RyaWRlMjtcbiAgICBjb25zdCBzdHJpZGUwID0gc2hhcGVbMV0gKiBzdHJpZGUxO1xuXG4gICAgY29uc3Qge25ld1NoYXBlLCBrZXB0RGltc30gPSBzcXVlZXplU2hhcGUoc2hhcGUgYXMgbnVtYmVyW10pO1xuICAgIGlmIChuZXdTaGFwZS5sZW5ndGggPCBzaGFwZS5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IG5ld0lucHV0U2hhcGUgPSBzcXVlZXplSW5wdXRTaGFwZShzaGFwZSwgbmV3U2hhcGUpO1xuICAgICAgY29uc3QgcGFyYW1zID0gWydyb3cnLCAnY29sJywgJ2RlcHRoJywgJ2RlcHRoMicsICdkZXB0aDMnXTtcbiAgICAgIC8vIERlZXAgY29weSBvZiBpbnB1dCB0ZXh0dXJlIGxheW91dC5cbiAgICAgIGNvbnN0IG5ld0lucHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0ID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShpbnB1dExheW91dCkpO1xuICAgICAgbmV3SW5wdXRMYXlvdXQudW5wYWNrZWRTaGFwZSA9IG5ld0lucHV0U2hhcGU7XG5cbiAgICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgICAke3RoaXMuZ2V0VW5wYWNrZWRTYW1wbGVyRnJvbUlucHV0KGZ1bmNOYW1lLCBuYW1lLCBuZXdJbnB1dExheW91dCkucm91dGluZUJvZHl9XG4gICAgICAgICAgZmxvYXQgJHtmdW5jTmFtZX0oaW50IHJvdywgaW50IGNvbCwgaW50IGRlcHRoLCBpbnQgZGVwdGgyLCBpbnQgZGVwdGgzKSB7XG4gICAgICAgICAgICByZXR1cm4gJHtmdW5jTmFtZX0oJHtnZXRTcXVlZXplZFBhcmFtcyhwYXJhbXMsIGtlcHREaW1zKX0pO1xuICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIHJldHVybiBuZXcgR2xzbExpYlJvdXRpbmUoc291cmNlLCBbJ2Nvb3JkaW5hdGVzLnNhbXBsZVRleHR1cmUnLCAnY29vcmRpbmF0ZXMudXZGcm9tRmxhdCddKTtcbiAgICB9XG5cbiAgICBjb25zdCB0ZXhOdW1SID0gaW5wdXRMYXlvdXQud2lkdGg7XG4gICAgY29uc3QgdGV4TnVtQyA9IGlucHV0TGF5b3V0LmhlaWdodDtcbiAgICBjb25zdCBzb3VyY2UgPSBgXG4gICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KGludCByb3csIGludCBjb2wsIGludCBkZXB0aCwgaW50IGRlcHRoMiwgaW50IGRlcHRoMykge1xuICAgICAgICAgIGludCBpbmRleCA9IHJvdyAqICR7c3RyaWRlMH0gKyBjb2wgKiAke3N0cmlkZTF9ICsgZGVwdGggKiAke3N0cmlkZTJ9ICtcbiAgICAgICAgICBkZXB0aDMgKiAke3N0cmlkZTN9ICsgZGVwdGgyO1xuICAgICAgICAgIHZlYzIgdXYgPSB1dkZyb21GbGF0KCR7dGV4TnVtUn0sICR7dGV4TnVtQ30sIGluZGV4KTtcbiAgICAgICAgICByZXR1cm4gc2FtcGxlVGV4dHVyZSgke25hbWV9LCB1dik7XG4gICAgICAgIH1cbiAgICAgIGA7XG4gICAgcmV0dXJuIG5ldyBHbHNsTGliUm91dGluZShzb3VyY2UsIFsnY29vcmRpbmF0ZXMuc2FtcGxlVGV4dHVyZScsICdjb29yZGluYXRlcy51dkZyb21GbGF0J10pO1xuICB9XG5cbiAgLyoqXG4gICAqIFVucGFja2VkIDZEIHNuaXBwZXQuXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0VW5wYWNrZWRTYW1wbGVyNkQoZnVuY05hbWU6IHN0cmluZywgbmFtZTogc3RyaW5nLCBpbnB1dExheW91dDogVGV4dHVyZUxheW91dCk6IEdsc2xMaWJSb3V0aW5lIHtcbiAgICBjb25zdCBzaGFwZSA9IGlucHV0TGF5b3V0LnVucGFja2VkU2hhcGU7XG4gICAgY29uc3Qgc3RyaWRlNCA9IHNoYXBlWzVdO1xuICAgIGNvbnN0IHN0cmlkZTMgPSBzaGFwZVs0XSAqIHN0cmlkZTQ7XG4gICAgY29uc3Qgc3RyaWRlMiA9IHNoYXBlWzNdICogc3RyaWRlMztcbiAgICBjb25zdCBzdHJpZGUxID0gc2hhcGVbMl0gKiBzdHJpZGUyO1xuICAgIGNvbnN0IHN0cmlkZTAgPSBzaGFwZVsxXSAqIHN0cmlkZTE7XG5cbiAgICBjb25zdCB7bmV3U2hhcGUsIGtlcHREaW1zfSA9IHNxdWVlemVTaGFwZShzaGFwZSBhcyBudW1iZXJbXSk7XG4gICAgaWYgKG5ld1NoYXBlLmxlbmd0aCA8IHNoYXBlLmxlbmd0aCkge1xuICAgICAgY29uc3QgbmV3SW5wdXRTaGFwZSA9IHNxdWVlemVJbnB1dFNoYXBlKHNoYXBlLCBuZXdTaGFwZSk7XG4gICAgICBjb25zdCBwYXJhbXMgPSBbJ3JvdycsICdjb2wnLCAnZGVwdGgnLCAnZGVwdGgyJywgJ2RlcHRoMycsICdkZXB0aDQnXTtcbiAgICAgIC8vIERlZXAgY29weSBvZiBpbnB1dCB0ZXh0dXJlIGxheW91dC5cbiAgICAgIGNvbnN0IG5ld0lucHV0TGF5b3V0OiBUZXh0dXJlTGF5b3V0ID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShpbnB1dExheW91dCkpO1xuICAgICAgbmV3SW5wdXRMYXlvdXQudW5wYWNrZWRTaGFwZSA9IG5ld0lucHV0U2hhcGU7XG5cbiAgICAgIGNvbnN0IHNvdXJjZSA9IGBcbiAgICAgICAgICAgICR7dGhpcy5nZXRVbnBhY2tlZFNhbXBsZXJGcm9tSW5wdXQoZnVuY05hbWUsIG5hbWUsIG5ld0lucHV0TGF5b3V0KS5yb3V0aW5lQm9keX1cbiAgICAgICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KGludCByb3csIGludCBjb2wsIGludCBkZXB0aCxcbiAgICAgICAgICAgICAgaW50IGRlcHRoMiwgaW50IGRlcHRoMywgaW50IGRlcHRoNCkge1xuICAgICAgICAgICAgICByZXR1cm4gJHtmdW5jTmFtZX0oJHtnZXRTcXVlZXplZFBhcmFtcyhwYXJhbXMsIGtlcHREaW1zKX0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIGA7XG4gICAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKHNvdXJjZSwgWydjb29yZGluYXRlcy5zYW1wbGVUZXh0dXJlJywgJ2Nvb3JkaW5hdGVzLnV2RnJvbUZsYXQnXSk7XG4gICAgfVxuXG4gICAgY29uc3QgdGV4TnVtUiA9IGlucHV0TGF5b3V0LndpZHRoO1xuICAgIGNvbnN0IHRleE51bUMgPSBpbnB1dExheW91dC5oZWlnaHQ7XG4gICAgY29uc3Qgc291cmNlID0gYFxuICAgICAgICAgIGZsb2F0ICR7ZnVuY05hbWV9KGludCByb3csIGludCBjb2wsIGludCBkZXB0aCxcbiAgICAgICAgICAgIGludCBkZXB0aDIsIGludCBkZXB0aDMsIGludCBkZXB0aDQpIHtcbiAgICAgICAgICAgIGludCBpbmRleCA9IHJvdyAqICR7c3RyaWRlMH0gKyBjb2wgKiAke3N0cmlkZTF9ICsgZGVwdGggKiAke3N0cmlkZTJ9ICtcbiAgICAgICAgICAgIGRlcHRoMiAqICR7c3RyaWRlM30gKyBkZXB0aDMgKiAke3N0cmlkZTR9ICsgZGVwdGg0O1xuICAgICAgICAgICAgdmVjMiB1diA9IHV2RnJvbUZsYXQoJHt0ZXhOdW1SfSwgJHt0ZXhOdW1DfSwgaW5kZXgpO1xuICAgICAgICAgICAgcmV0dXJuIHNhbXBsZVRleHR1cmUoJHtuYW1lfSwgdXYpO1xuICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICByZXR1cm4gbmV3IEdsc2xMaWJSb3V0aW5lKFxuICAgICAgICBzb3VyY2UsIFsnY29vcmRpbmF0ZXMudXZGcm9tRmxhdCcsICdjb29yZGluYXRlcy5zYW1wbGVUZXh0dXJlJywgJ2Nvb3JkaW5hdGVzLmNvb3Jkc1RvT2Zmc2V0J10pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoaXMgaXMgdGhlIG1haW4gZnVuY3Rpb24gdG8gbWFwIGZyb20gdGhlIGdpdmVuIHRleHR1cmUgY29vcmRpYW50ZXMgKHMsdClcbiAgICogdG8gbG9naWNhbCBpbmRpY2VzIGZvciB0aGUgb3V0cHV0XG4gICAqIFRoZXJlIHdpbGwgb25seSBiZSBvbmUgc2luZ2xlIHZhcmlhdGlvbiBvZiB0aGlzXG4gICAqIEFsc28gc2VlIGNvb3Jkc1RvT2Zmc2V0IGFuZCBvZmZzZXRUb0luZGljZXMgZm9yIGlucHV0LXNwZWNpZmljIHZlcnNpb25zXG4gICAqL1xuICBwcm90ZWN0ZWQgdG9WZWMoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IG91dHB1dCA9IHRoaXMuY29udGV4dC5vdXRwdXRUZXh0dXJlTGF5b3V0O1xuICAgIGNvbnN0IHJhbmsgPSBvdXRwdXQuc2hhcGUubGVuZ3RoO1xuICAgIGNvbnN0IHN0cmlkZXMgPSBvdXRwdXQuc3RyaWRlcztcbiAgICBjb25zdCB4U2NhbGUgPSBvdXRwdXQud2lkdGg7XG4gICAgY29uc3QgeVNjYWxlID0gb3V0cHV0LmhlaWdodDtcblxuICAgIGNvbnN0IHN0cmlkZXNCbG9jayA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmFuayAtIDE7ICsraSkge1xuICAgICAgc3RyaWRlc0Jsb2NrLnB1c2goYFxuICAgICAgICBjWyR7aX1dID0gb2Zmc2V0IC8gJHtzdHJpZGVzW2ldfTtgKTtcbiAgICAgIHN0cmlkZXNCbG9jay5wdXNoKGBcbiAgICAgICAgb2Zmc2V0IC09IGNbJHtpfV0gKiAke3N0cmlkZXNbaV19O2ApO1xuICAgIH1cbiAgICBzdHJpZGVzQmxvY2sucHVzaChgXG4gICAgICAgIGNbJHtyYW5rIC0gMX1dID0gb2Zmc2V0O2ApO1xuICAgIGNvbnN0IGJvZHkgPSBgXG4gICAgICB2b2lkIHRvVmVjKHZlYzIgdGV4Q29vcmRzLCBvdXQgaW50IGNbJHtyYW5rfV0pIHtcbiAgICAgICAgaW50IG9mZnNldCA9IGNvb3Jkc1RvT2Zmc2V0KHRleENvb3JkcywgJHt4U2NhbGV9LCAke3lTY2FsZX0pO1xuICAgICAgICAke3N0cmlkZXNCbG9jay5qb2luKCcnKX1cbiAgICAgIH1cbiAgICAgIHZvaWQgdG9WZWMoaW50IG9mZnNldCwgb3V0IGludCBjWyR7cmFua31dKSB7XG4gICAgICAgICR7c3RyaWRlc0Jsb2NrLmpvaW4oJycpfVxuICAgICAgfVxuICAgIGA7XG4gICAgcmV0dXJuIHt0b1ZlYzogbmV3IEdsc2xMaWJSb3V0aW5lKGJvZHksIFsnY29vcmRpbmF0ZXMuY29vcmRzVG9PZmZzZXQnXSl9O1xuICB9XG4gIC8qKlxuICAgKiBUaGVzZSBhcmUgdmFsdWUgZ2V0dGVyIGZ1bmN0aW9ucyBnZW5lcmF0ZWQgZm9yIGVhY2ggaW5wdXRcbiAgICogRWFjaCBmdW5jdGlvbiBpcyBoYXJkd2lyZWQgdG8gdGhlIG5hbWUgYW5kIGRpbWVuc2lvbnMgb2YgdGhlIGlucHV0XG4gICAqIEFuICdfVCcgdmFyaWF0aW9uIGlzIGFsc28gcHJvZHVjZWQgd2hpY2ggYWNjZXNzZXMgdmFsdWVzIGFzIGlmIHRoZVxuICAgKiBpbnB1dCB3YXMgdHJhbnNwb3NlZFxuICAgKi9cbiAgcHJvdGVjdGVkIHZhbHVlRnJvbSgpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgY29uc3QgcmVzdWx0OiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSA9IHt9O1xuICAgIHRoaXMuY29udGV4dC5wcm9ncmFtSW5mby5pbnB1dE5hbWVzLmZvckVhY2goKG5hbWUsIGkpID0+IHtcbiAgICAgIGNvbnN0IGxheW91dCA9IHRoaXMuY29udGV4dC5pbnB1dFRleHR1cmVMYXlvdXRzW2ldO1xuICAgICAgY29uc3Qgc2hhcGUgPSBsYXlvdXQudW5wYWNrZWRTaGFwZS5sZW5ndGggPiAwID8gbGF5b3V0LnVucGFja2VkU2hhcGUgOiBsYXlvdXQuc2hhcGU7XG4gICAgICBjb25zdCByYW5rID0gc2hhcGUubGVuZ3RoO1xuICAgICAgbGV0IGZ1bmNOYW1lID0gYF8ke25hbWV9YDtcbiAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPSBuZXcgR2xzbExpYlJvdXRpbmUoXG4gICAgICAgICAgdGhpcy5nZXRWYWx1ZUZyb21TaW5nbGUobmFtZSwgcmFuaywgbGF5b3V0LndpZHRoLCBsYXlvdXQuaGVpZ2h0LCBmYWxzZSksXG4gICAgICAgICAgW2BzaGFwZVV0aWxzLmluZGljZXNUb09mZnNldCR7ZnVuY05hbWV9YCwgJ2Nvb3JkaW5hdGVzLm9mZnNldFRvQ29vcmRzJywgJ2ZyYWdjb2xvci5nZXRDb2xvckFzRmxvYXQnXSk7XG4gICAgICBmdW5jTmFtZSA9IGZ1bmNOYW1lICsgJ19UJztcbiAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPSBuZXcgR2xzbExpYlJvdXRpbmUoXG4gICAgICAgICAgdGhpcy5nZXRWYWx1ZUZyb21TaW5nbGUobmFtZSwgcmFuaywgbGF5b3V0LndpZHRoLCBsYXlvdXQuaGVpZ2h0LCB0cnVlKSxcbiAgICAgICAgICBbYHNoYXBlVXRpbHMuaW5kaWNlc1RvT2Zmc2V0JHtmdW5jTmFtZX1gLCAnY29vcmRpbmF0ZXMub2Zmc2V0VG9Db29yZHMnLCAnZnJhZ2NvbG9yLmdldENvbG9yQXNGbG9hdCddKTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIC8qKlxuICAgKiBQcm9kdWNlcyBvbmUgdmFsdWUgZ2V0dGVyIGZ1bmN0aW9uIGZvciB0aGUgbmFtZSBhbmQgcmFuayBnaXZlblxuICAgKiBJZiBhIHRyYW5zcG9zZSBpcyBzZXQgcHJvcGVyIG9mZnNldFRvQ29vcmRzIG1hcHBpbmcgd2lsbCBiZSB1c2VkXG4gICAqIEBwYXJhbSBuYW1lIG5hbWUgb2YgdGhlIGZ1bmN0aW9uXG4gICAqIEBwYXJhbSByYW5rIHJhbmsgb2YgdGhlIGlucHV0XG4gICAqIEBwYXJhbSB0cmFuc3Bvc2Ugd2hldGhlciBvciBub3Qgc2hvdWxkIGdlbmVyYXRlIGEgdHJhbnNwb3NlIHZhcmlhdGlvblxuICAgKi9cbiAgcHJvdGVjdGVkIGdldFZhbHVlRnJvbVNpbmdsZSh2YXJOYW1lOiBzdHJpbmcsIHJhbms6IG51bWJlciwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIsIHRyYW5zcG9zZTogYm9vbGVhbik6XG4gICAgICBzdHJpbmcge1xuICAgIGxldCBuYW1lID0gYF8ke3Zhck5hbWV9YDtcbiAgICBpZiAodHJhbnNwb3NlKSB7XG4gICAgICBuYW1lID0gbmFtZSArICdfVCc7XG4gICAgfVxuICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKHRoaXMuY29udGV4dC5nbENvbnRleHQudmVyc2lvbik7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgZmxvYXQgJHtuYW1lfShpbnQgbVske3Jhbmt9XSkge1xuICAgICAgICAgIGludCBvZmZzZXQgPSBpbmRpY2VzVG9PZmZzZXQke25hbWV9KG0pO1xuICAgICAgICAgIHZlYzIgY29vcmRzID0gb2Zmc2V0VG9Db29yZHMob2Zmc2V0LCAke3dpZHRofSwgJHtoZWlnaHR9KTtcbiAgICAgICAgICBmbG9hdCB2YWx1ZSA9IGdldENvbG9yQXNGbG9hdCgke2dsc2wudGV4dHVyZTJEfSgke3Zhck5hbWV9LCBjb29yZHMpKTtcbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgYDtcbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9kdWNlcyBhIHBhY2tlZCB2YWx1ZSBnZXR0ZXIgZnVuY3Rpb24gZm9yIHRoZSBuYW1lIGFuZCByYW5rIGdpdmVuXG4gICAqIElmIGEgdHJhbnNwb3NlIGlzIHNldCBwcm9wZXIgb2Zmc2V0VG9Db29yZHMgbWFwcGluZyB3aWxsIGJlIHVzZWRcbiAgICogQHBhcmFtIG5hbWUgbmFtZSBvZiB0aGUgZnVuY3Rpb25cbiAgICogQHBhcmFtIHJhbmsgcmFuayBvZiB0aGUgaW5wdXRcbiAgICogQHBhcmFtIHRyYW5zcG9zZSB3aGV0aGVyIG9yIG5vdCBzaG91bGQgZ2VuZXJhdGUgYSB0cmFuc3Bvc2UgdmFyaWF0aW9uXG4gICAqL1xuICBwcm90ZWN0ZWQgZ2V0UGFja2VkVmFsdWVGcm9tKHZhck5hbWU6IHN0cmluZywgcmFuazogbnVtYmVyLCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciwgdHJhbnNwb3NlOiBib29sZWFuKTpcbiAgICAgIHN0cmluZyB7XG4gICAgbGV0IG5hbWUgPSBgXyR7dmFyTmFtZX1fUGFja2A7XG4gICAgaWYgKHRyYW5zcG9zZSkge1xuICAgICAgbmFtZSA9IG5hbWUgKyAnX1QnO1xuICAgIH1cbiAgICBjb25zdCBnbHNsID0gZ2V0R2xzbCh0aGlzLmNvbnRleHQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgIHJldHVybiBgXG4gICAgICAgIHZlYzQgJHtuYW1lfShpbnQgbVske3Jhbmt9XSkge1xuICAgICAgICAgIGludCBvZmZzZXQgPSBpbmRpY2VzVG9PZmZzZXRfJHt2YXJOYW1lfShtKTtcbiAgICAgICAgICB2ZWMyIGNvb3JkcyA9IG9mZnNldFRvQ29vcmRzKG9mZnNldCwgJHt3aWR0aH0sICR7aGVpZ2h0fSk7XG4gICAgICAgICAgcmV0dXJuICR7Z2xzbC50ZXh0dXJlMkR9KCR7dmFyTmFtZX0sIGNvb3Jkcyk7XG4gICAgICAgIH1cbiAgICAgICAgYDtcbiAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7UHJvZ3JhbUluZm8sIFRleHR1cmVMYXlvdXR9IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHtXZWJHTENvbnRleHR9IGZyb20gJy4vd2ViZ2wtY29udGV4dCc7XG5cbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvbiAqL1xuZXhwb3J0IGVudW0gRnVuY3Rpb25UeXBlIHtcbiAgVmFsdWVCYXNlZCxcbiAgUG9zaXRpb25hbFxufVxuZXhwb3J0IGludGVyZmFjZSBHbHNsRnVuY3Rpb248VCBleHRlbmRzIEZ1bmN0aW9uVHlwZT4ge1xuICBib2R5OiBzdHJpbmc7XG4gIG5hbWU6IHN0cmluZztcbiAgdHlwZTogVDtcbn1cbmV4cG9ydCB0eXBlIEdsc2xWYWx1ZUZ1bmN0aW9uID0gR2xzbEZ1bmN0aW9uPEZ1bmN0aW9uVHlwZS5WYWx1ZUJhc2VkPjtcbmV4cG9ydCBpbnRlcmZhY2UgR2xzbFBvc2l0aW9uYWxGdW5jdGlvbiBleHRlbmRzIEdsc2xGdW5jdGlvbjxGdW5jdGlvblR5cGUuUG9zaXRpb25hbD4ge1xuICBpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXTtcbiAgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdO1xufVxuXG5leHBvcnQgY2xhc3MgR2xzbENvbnRleHQge1xuICBjb25zdHJ1Y3RvcihcbiAgICAgIHB1YmxpYyBnbENvbnRleHQ6IFdlYkdMQ29udGV4dCwgcHVibGljIHByb2dyYW1JbmZvOiBQcm9ncmFtSW5mbywgcHVibGljIGlucHV0VGV4dHVyZUxheW91dHM6IFRleHR1cmVMYXlvdXRbXSxcbiAgICAgIHB1YmxpYyBvdXRwdXRUZXh0dXJlTGF5b3V0OiBUZXh0dXJlTGF5b3V0KSB7fVxufVxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIEdsc2xMaWIge1xuICBjb25zdHJ1Y3RvcihwdWJsaWMgY29udGV4dDogR2xzbENvbnRleHQpIHt9XG4gIGFic3RyYWN0IGdldEZ1bmN0aW9ucygpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfTtcbiAgYWJzdHJhY3QgZ2V0Q3VzdG9tVHlwZXMoKToge1tuYW1lOiBzdHJpbmddOiBzdHJpbmd9O1xufVxuXG4vLyBhYnN0cmFjdGlvbiB0byByZXByZXNlbnQgYSBHTFNMIGxpYnJhcnkgcm91dGluZSBhbmQgaXQncyBkZXBlbmRlbmNpZXNcbmV4cG9ydCBjbGFzcyBHbHNsTGliUm91dGluZSB7XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyByb3V0aW5lQm9keTogc3RyaW5nLCBwdWJsaWMgZGVwZW5kZW5jaWVzPzogc3RyaW5nW10pIHt9XG59XG5cbi8vIGFic3RyYWN0aW9uIHRvIHJlcHJlc2VudCBhIEdMU0wgbGlicmFyeSByb3V0aW5lIGFuZCBpdCdzIGRlcGVuZGVuY2llcyBBUyBHUkFQSCBOb2Rlc1xuLy8gdGhpcyBsZXZlbCBvZiBhYnN0cmFjdGlvbiBpcyB1c2VkIHRvIHRvcG9sb2dpY2FsbHkgc29ydCByb3V0aW5lcyBiZWZvcmUgZnJhZ21lbnQgc2hhZGUgaW5jbHVzaW9uXG5leHBvcnQgY2xhc3MgR2xzbExpYlJvdXRpbmVOb2RlIHtcbiAgZGVwZW5kZW5jaWVzOiBHbHNsTGliUm91dGluZU5vZGVbXTtcbiAgcm91dGluZUJvZHk6IHN0cmluZztcbiAgY29uc3RydWN0b3IocHVibGljIG5hbWU6IHN0cmluZywgcm91dGluZUJvZHk/OiBzdHJpbmcsIGRlcGVuZGVuY2llcz86IEdsc2xMaWJSb3V0aW5lTm9kZVtdKSB7XG4gICAgaWYgKGRlcGVuZGVuY2llcykge1xuICAgICAgdGhpcy5kZXBlbmRlbmNpZXMgPSBkZXBlbmRlbmNpZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZGVwZW5kZW5jaWVzID0gW107XG4gICAgfVxuXG4gICAgaWYgKHJvdXRpbmVCb2R5KSB7XG4gICAgICB0aGlzLnJvdXRpbmVCb2R5ID0gcm91dGluZUJvZHk7XG4gICAgfVxuICB9XG4gIGFkZERlcGVuZGVuY3kobm9kZTogR2xzbExpYlJvdXRpbmVOb2RlKSB7XG4gICAgaWYgKG5vZGUpIHtcbiAgICAgIHRoaXMuZGVwZW5kZW5jaWVzLnB1c2gobm9kZSk7XG4gICAgfVxuICB9XG59XG5cbi8vIHRvcG9sb2dpY2FsbHkgc29ydCBHTFNMIGxpYnJhcnkgcm91dGluZXMgKGdyYXBoIG5vZGVzIGFic3RyYWN0aW9uKSBiZWZvcmUgc2hhZGVyIHNjcmlwdCBpbmNsdXNpb25cbmV4cG9ydCBjbGFzcyBUb3BvbG9naWNhbFNvcnRHbHNsUm91dGluZXMge1xuICBzdGF0aWMgcmV0dXJuT3JkZXJlZE5vZGVzKG5vZGVzOiBHbHNsTGliUm91dGluZU5vZGVbXSk6IEdsc2xMaWJSb3V0aW5lTm9kZVtdIHtcbiAgICBpZiAoIW5vZGVzIHx8IG5vZGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGlmIChub2Rlcy5sZW5ndGggPT09IDEpIHtcbiAgICAgIHJldHVybiBub2RlcztcbiAgICB9XG5cbiAgICBjb25zdCBjeWNsZUNoZWNrID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgY29uc3QgYWxyZWFkeVRyYXZlcnNlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIGNvbnN0IHJlc3VsdCA9IG5ldyBBcnJheTxHbHNsTGliUm91dGluZU5vZGU+KCk7XG5cbiAgICB0aGlzLmNyZWF0ZU9yZGVyZWROb2Rlcyhub2RlcywgY3ljbGVDaGVjaywgYWxyZWFkeVRyYXZlcnNlZCwgcmVzdWx0KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcHJpdmF0ZSBzdGF0aWMgY3JlYXRlT3JkZXJlZE5vZGVzKFxuICAgICAgZ3JhcGhOb2RlczogR2xzbExpYlJvdXRpbmVOb2RlW10sIGN5Y2xlQ2hlY2s6IFNldDxzdHJpbmc+LCBhbHJlYWR5VHJhdmVyc2VkOiBTZXQ8c3RyaW5nPixcbiAgICAgIHJlc3VsdDogR2xzbExpYlJvdXRpbmVOb2RlW10pIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGdyYXBoTm9kZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHRoaXMuZGZzVHJhdmVyc2UoZ3JhcGhOb2Rlc1tpXSwgY3ljbGVDaGVjaywgYWxyZWFkeVRyYXZlcnNlZCwgcmVzdWx0KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBkZnNUcmF2ZXJzZShcbiAgICAgIHJvb3Q6IEdsc2xMaWJSb3V0aW5lTm9kZSwgY3ljbGVDaGVjazogU2V0PHN0cmluZz4sIGFscmVhZHlUcmF2ZXJzZWQ6IFNldDxzdHJpbmc+LCByZXN1bHQ6IEdsc2xMaWJSb3V0aW5lTm9kZVtdKSB7XG4gICAgLy8gaWYgdGhpcyByb290IGhhcyBhbHJlYWR5IGJlZW4gdHJhdmVyc2VkIHJldHVyblxuICAgIGlmICghcm9vdCB8fCBhbHJlYWR5VHJhdmVyc2VkLmhhcyhyb290Lm5hbWUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gY3ljbGljIGRlcGVuZGVuY3kgaGFzIGJlZW4gZGV0ZWN0ZWRcbiAgICBpZiAoY3ljbGVDaGVjay5oYXMocm9vdC5uYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDeWNsaWMgZGVwZW5kZW5jeSBkZXRlY3RlZC4gQ2FuXFwndCB0b3BvbG9naWNhbGx5IHNvcnQgcm91dGluZXMgbmVlZGVkIGZvciBzaGFkZXIuJyk7XG4gICAgfVxuXG4gICAgLy8gaG9sZCB0aGlzIG5vZGUgdG8gZGV0ZWN0IGN5Y2xlcyBpZiBhbnlcbiAgICBjeWNsZUNoZWNrLmFkZChyb290Lm5hbWUpO1xuXG4gICAgLy8gdHJhdmVyc2UgY2hpbGRyZW4gaW4gYSBkZnMgZmFzaGlvblxuICAgIGNvbnN0IGRlcGVuZGVuY2llcyA9IHJvb3QuZGVwZW5kZW5jaWVzO1xuICAgIGlmIChkZXBlbmRlbmNpZXMgJiYgZGVwZW5kZW5jaWVzLmxlbmd0aCA+IDApIHtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGVwZW5kZW5jaWVzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHRoaXMuZGZzVHJhdmVyc2UoZGVwZW5kZW5jaWVzW2ldLCBjeWNsZUNoZWNrLCBhbHJlYWR5VHJhdmVyc2VkLCByZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGFkZCB0byByZXN1bHQgaG9sZGVyXG4gICAgcmVzdWx0LnB1c2gocm9vdCk7XG5cbiAgICAvLyBtYXJrIHRoaXMgbm9kZSBhcyB0cmF2ZXJzZWQgc28gdGhhdCB3ZSBkb24ndCB0cmF2ZXJzZSBmcm9tIHRoaXMgYWdhaW5cbiAgICBhbHJlYWR5VHJhdmVyc2VkLmFkZChyb290Lm5hbWUpO1xuXG4gICAgLy8gcmVsZWFzZSB0aGUgaG9sZFxuICAgIGN5Y2xlQ2hlY2suZGVsZXRlKHJvb3QubmFtZSk7XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0dsc2xDb250ZXh0LCBHbHNsTGliLCBHbHNsTGliUm91dGluZX0gZnJvbSAnLi9nbHNsLWRlZmluaXRpb25zJztcblxuLyoqXG4gKiBUaGlzIEdMU0wgbGlicmFyeSBoYW5kbGVzIHJvdXRpbmVzIGNvbnZlcnRpbmdcbiAqIGZsb2F0MzIgdG8vZnJvbSBVbnNpZ25lZCBieXRlIG9yIGZsb2F0IDE2XG4gKi9cbmV4cG9ydCBjbGFzcyBFbmNvZGluZ0dsc2xMaWIgZXh0ZW5kcyBHbHNsTGliIHtcbiAgY29uc3RydWN0b3IoY29udGV4dDogR2xzbENvbnRleHQpIHtcbiAgICBzdXBlcihjb250ZXh0KTtcbiAgfVxuICBnZXRGdW5jdGlvbnMoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIHJldHVybiB7Li4udGhpcy5lbmNvZGVGbG9hdDMyKCksIC4uLnRoaXMuZGVjb2RlRmxvYXQzMigpfTtcbiAgfVxuICBnZXRDdXN0b21UeXBlcygpOiB7W25hbWU6IHN0cmluZ106IHN0cmluZ30ge1xuICAgIHJldHVybiB7fTtcbiAgfVxuICBwcm90ZWN0ZWQgZW5jb2RlRmxvYXQzMigpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGVuY29kZTogbmV3IEdsc2xMaWJSb3V0aW5lKGBoaWdocCB2ZWM0IGVuY29kZShoaWdocCBmbG9hdCBmKSB7XG4gICAgICAgIHJldHVybiB2ZWM0KGYsIDAuMCwgMC4wLCAwLjApO1xuICAgICAgfVxuICAgICAgICBgKVxuICAgIH07XG4gIH1cbiAgcHJvdGVjdGVkIGRlY29kZUZsb2F0MzIoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIHJldHVybiB7XG4gICAgICBkZWNvZGU6IG5ldyBHbHNsTGliUm91dGluZShgaGlnaHAgZmxvYXQgZGVjb2RlKGhpZ2hwIHZlYzQgcmdiYSkge1xuICAgICAgICByZXR1cm4gcmdiYS5yO1xuICAgICAgfVxuICAgICAgICBgKVxuICAgIH07XG4gIH1cbiAgLyoqXG4gICAqIHJldHVybnMgdGhlIHJvdXRpbmUgdG8gZW5jb2RlIGVuY29kZSBhIDMyYml0IGZsb2F0IHRvIGEgdmVjNCAob2YgdW5zaWduZWQgYnl0ZXMpXG4gICAqIEBjcmVkaXQ6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzcwNTk5NjIvaG93LWRvLWktY29udmVydC1hLXZlYzQtcmdiYS12YWx1ZS10by1hLWZsb2F0XG4gICAqL1xuICBwcm90ZWN0ZWQgZW5jb2RlVWludDgoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IGVuZGlhbm5lc3MgPSBFbmNvZGluZ0dsc2xMaWIuaXNMaXR0bGVFbmRpYW4oKSA/ICdyZ2JhLnJnYmE9cmdiYS5hYmdyOycgOiAnJztcbiAgICByZXR1cm4ge1xuICAgICAgZW5jb2RlOiBuZXcgR2xzbExpYlJvdXRpbmUoYFxuICAgICAgaGlnaHAgdmVjNCBlbmNvZGUoaGlnaHAgZmxvYXQgZikge1xuICAgICAgICBoaWdocCBmbG9hdCBGID0gYWJzKGYpO1xuICAgICAgICBoaWdocCBmbG9hdCBTaWduID0gc3RlcCgwLjAsLWYpO1xuICAgICAgICBoaWdocCBmbG9hdCBFeHBvbmVudCA9IGZsb29yKGxvZzIoRikpO1xuICAgICAgICBoaWdocCBmbG9hdCBNYW50aXNzYSA9IChleHAyKC0gRXhwb25lbnQpICogRik7XG4gICAgICAgIEV4cG9uZW50ID0gZmxvb3IobG9nMihGKSArIDEyNy4wKSArIGZsb29yKGxvZzIoTWFudGlzc2EpKTtcbiAgICAgICAgaGlnaHAgdmVjNCByZ2JhO1xuICAgICAgICByZ2JhWzBdID0gMTI4LjAgKiBTaWduICArIGZsb29yKEV4cG9uZW50KmV4cDIoLTEuMCkpO1xuICAgICAgICByZ2JhWzFdID0gMTI4LjAgKiBtb2QoRXhwb25lbnQsMi4wKSArIG1vZChmbG9vcihNYW50aXNzYSoxMjguMCksMTI4LjApO1xuICAgICAgICByZ2JhWzJdID0gZmxvb3IobW9kKGZsb29yKE1hbnRpc3NhKmV4cDIoMjMuMCAtOC4wKSksZXhwMig4LjApKSk7XG4gICAgICAgIHJnYmFbM10gPSBmbG9vcihleHAyKDIzLjApKm1vZChNYW50aXNzYSxleHAyKC0xNS4wKSkpO1xuICAgICAgICAke2VuZGlhbm5lc3N9XG4gICAgICAgIHJnYmEgPSByZ2JhIC8gMjU1LjA7IC8vIHZhbHVlcyBuZWVkIHRvIGJlIG5vcm1hbGl6ZWQgdG8gWzAsMV1cbiAgICAgICAgcmV0dXJuIHJnYmE7XG4gICAgfVxuICAgICAgICBgKVxuICAgIH07XG4gIH1cbiAgLyoqXG4gICAqIHJldHVybnMgdGhlIHJvdXRpbmUgdG8gZW5jb2RlIGEgdmVjNCBvZiB1bnNpZ25lZCBieXRlcyB0byBmbG9hdDMyXG4gICAqIEBjcmVkaXQ6IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzcwNTk5NjIvaG93LWRvLWktY29udmVydC1hLXZlYzQtcmdiYS12YWx1ZS10by1hLWZsb2F0XG4gICAqL1xuICBwcm90ZWN0ZWQgZGVjb2RlVWludDgoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IGVuZGlhbm5lc3MgPSBFbmNvZGluZ0dsc2xMaWIuaXNMaXR0bGVFbmRpYW4oKSA/ICdyZ2JhLnJnYmE9cmdiYS5hYmdyOycgOiAnJztcbiAgICByZXR1cm4ge1xuICAgICAgZGVjb2RlOiBuZXcgR2xzbExpYlJvdXRpbmUoYFxuICAgICAgICBoaWdocCBmbG9hdCBkZWNvZGUoaGlnaHAgdmVjNCByZ2JhKSB7XG4gICAgICAgICAgcmdiYSA9IHJnYmEgKiAyNTUuMDsgLy8gdmFsdWVzIG5lZWQgdG8gYmUgZGUtbm9ybWFsaXplZCBmcm9tIFswLDFdIHRvIFswLDI1NV1cbiAgICAgICAgICAke2VuZGlhbm5lc3N9XG4gICAgICAgICAgaGlnaHAgZmxvYXQgU2lnbiA9IDEuMCAtIHN0ZXAoMTI4LjAscmdiYVswXSkqMi4wO1xuICAgICAgICAgIGhpZ2hwIGZsb2F0IEV4cG9uZW50ID0gMi4wICogbW9kKHJnYmFbMF0sMTI4LjApICsgc3RlcCgxMjguMCxyZ2JhWzFdKSAtIDEyNy4wO1xuICAgICAgICAgIGhpZ2hwIGZsb2F0IE1hbnRpc3NhID0gbW9kKHJnYmFbMV0sMTI4LjApKjY1NTM2LjAgKyByZ2JhWzJdKjI1Ni4wICtyZ2JhWzNdICsgZmxvYXQoMHg4MDAwMDApO1xuICAgICAgICAgIGhpZ2hwIGZsb2F0IFJlc3VsdCA9ICBTaWduICogZXhwMihFeHBvbmVudCkgKiAoTWFudGlzc2EgKiBleHAyKC0yMy4wICkpO1xuICAgICAgICAgIHJldHVybiBSZXN1bHQ7XG4gICAgICB9XG4gICAgICAgIGApXG4gICAgfTtcbiAgfVxuICAvKipcbiAgICogRGV0ZXJtaW5lcyBpZiB0aGUgbWFjaGluZSBpcyBsaXR0bGUgZW5kaWFuIG9yIG5vdFxuICAgKiBAY3JlZGl0OiBodHRwczovL2dpc3QuZ2l0aHViLmNvbS9Ub29UYWxsTmF0ZS80NzUwOTUzXG4gICAqL1xuICBzdGF0aWMgaXNMaXR0bGVFbmRpYW4oKTogYm9vbGVhbiB7XG4gICAgY29uc3QgYiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBjb25zdCBhID0gbmV3IFVpbnQzMkFycmF5KGIpO1xuICAgIGNvbnN0IGMgPSBuZXcgVWludDhBcnJheShiKTtcbiAgICBhWzBdID0gMHhkZWFkYmVlZjtcbiAgICBpZiAoY1swXSA9PT0gMHhlZikge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmIChjWzBdID09PSAweGRlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcigndW5rbm93biBlbmRpYW5uZXNzJyk7XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0dsc2xDb250ZXh0LCBHbHNsTGliLCBHbHNsTGliUm91dGluZX0gZnJvbSAnLi9nbHNsLWRlZmluaXRpb25zJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi9nbHNsLXNvdXJjZSc7XG5cbi8qKlxuICogVGhpcyBHTFNMIGxpYnJhcnkgaGFuZGxlcyByb3V0aW5lcyBhcm91bmQgcmVhZGluZyBhIHRleGxldCBhbmQgd3JpdGluZyB0byBpdFxuICogUmVhZGluZyBhbmQgd3JpdGluZyBjb3VsZCBiZSBtb3JlIHRoYW4ganVzdCBkZWFsaW5nIHdpdGggb25lIGNoYW5uZWxcbiAqIEl0IG1heSByZXF1aXJlIGVuY29kaW5nL2RlY29kaW5nIHRvL2Zyb20gNCBjaGFubmVscyBpbnRvIG9uZVxuICovXG5leHBvcnQgY2xhc3MgRnJhZ0NvbG9yR2xzbExpYiBleHRlbmRzIEdsc2xMaWIge1xuICBjb25zdHJ1Y3Rvcihjb250ZXh0OiBHbHNsQ29udGV4dCkge1xuICAgIHN1cGVyKGNvbnRleHQpO1xuICB9XG4gIGdldEZ1bmN0aW9ucygpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgcmV0dXJuIHsuLi50aGlzLnNldEZyYWdDb2xvcigpLCAuLi50aGlzLmdldENvbG9yQXNGbG9hdCgpfTtcbiAgfVxuICBnZXRDdXN0b21UeXBlcygpOiB7W25hbWU6IHN0cmluZ106IHN0cmluZ30ge1xuICAgIHJldHVybiB7fTtcbiAgfVxuICBwcm90ZWN0ZWQgc2V0RnJhZ0NvbG9yKCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICBjb25zdCBnbHNsID0gZ2V0R2xzbCh0aGlzLmNvbnRleHQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgIHJldHVybiB7XG4gICAgICBzZXRGcmFnQ29sb3I6IG5ldyBHbHNsTGliUm91dGluZShcbiAgICAgICAgICBgXG4gICAgICAgIHZvaWQgc2V0RnJhZ0NvbG9yKGZsb2F0IHZhbHVlKSB7XG4gICAgICAgICAgICAke2dsc2wub3V0cHV0fSA9IGVuY29kZSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgYCxcbiAgICAgICAgICBbJ2VuY29kaW5nLmVuY29kZSddKVxuICAgIH07XG4gIH1cbiAgcHJvdGVjdGVkIGdldENvbG9yQXNGbG9hdCgpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGdldENvbG9yQXNGbG9hdDogbmV3IEdsc2xMaWJSb3V0aW5lKFxuICAgICAgICAgIGBcbiAgICAgICAgZmxvYXQgZ2V0Q29sb3JBc0Zsb2F0KHZlYzQgY29sb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBkZWNvZGUoY29sb3IpO1xuICAgICAgICB9XG4gICAgICAgIGAsXG4gICAgICAgICAgWydlbmNvZGluZy5kZWNvZGUnXSlcbiAgICB9O1xuICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuY29uc3QgSU5MSU5FX0ZVTkNfREVGX1JFR0VYID0gL0BpbmxpbmVbXFxzXFxuXFxyXSsoXFx3KylbXFxzXFxuXFxyXSsoWzAtOWEtekEtWl9dKylcXHMqXFwoKFteKV0qKVxcKVxccyp7KChbXn1dfFtcXG5cXHJdKSopfS9nbTtcbmNvbnN0IEZVTkNfQ0FMTF9SRUdFWCA9ICcoXFxcXHcrKT9cXFxccysoW18wLTlhLXpBLVpdKylcXFxccys9XFxcXHMrX19GVU5DX19cXFxcKCguKilcXFxcKVxcXFxzKjsnO1xuLyoqXG4gKiBHTFNMIHByZXByb2Nlc3NvciByZXNwb25zaWJsZSBmb3IgcmVzb2x2aW5nIEBpbmxpbmUgZGlyZWN0aXZlc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcmVwbGFjZUlubGluZXMoc2NyaXB0OiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBpbmxpbmVEZWZzOiB7W25hbWU6IHN0cmluZ106IHtwYXJhbXM6IEFycmF5PHt0eXBlOiBzdHJpbmc7IG5hbWU6IHN0cmluZ318bnVsbD47IGJvZHk6IHN0cmluZ319ID0ge307XG4gIGxldCBtYXRjaDtcbiAgd2hpbGUgKChtYXRjaCA9IElOTElORV9GVU5DX0RFRl9SRUdFWC5leGVjKHNjcmlwdCkpICE9PSBudWxsKSB7XG4gICAgY29uc3QgcGFyYW1zID0gbWF0Y2hbM11cbiAgICAgICAgICAgICAgICAgICAgICAgLnNwbGl0KCcsJylcbiAgICAgICAgICAgICAgICAgICAgICAgLm1hcChzID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0b2tlbnMgPSBzLnRyaW0oKS5zcGxpdCgnICcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0b2tlbnMgJiYgdG9rZW5zLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt0eXBlOiB0b2tlbnNbMF0sIG5hbWU6IHRva2Vuc1sxXX07XG4gICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKHYgPT4gdiAhPT0gbnVsbCk7XG4gICAgaW5saW5lRGVmc1ttYXRjaFsyXV0gPSB7cGFyYW1zLCBib2R5OiBtYXRjaFs0XX07XG4gIH1cbiAgZm9yIChjb25zdCBuYW1lIGluIGlubGluZURlZnMpIHtcbiAgICBjb25zdCByZWdleFN0cmluZyA9IEZVTkNfQ0FMTF9SRUdFWC5yZXBsYWNlKCdfX0ZVTkNfXycsIG5hbWUpO1xuICAgIGNvbnN0IHJlZ2V4ID0gbmV3IFJlZ0V4cChyZWdleFN0cmluZywgJ2dtJyk7XG4gICAgd2hpbGUgKChtYXRjaCA9IHJlZ2V4LmV4ZWMoc2NyaXB0KSkgIT09IG51bGwpIHtcbiAgICAgIGNvbnN0IHR5cGUgPSBtYXRjaFsxXTtcbiAgICAgIGNvbnN0IHZhcmlhYmxlID0gbWF0Y2hbMl07XG4gICAgICBjb25zdCBwYXJhbXMgPSBtYXRjaFszXS5zcGxpdCgnLCcpO1xuICAgICAgY29uc3QgZGVjbExpbmUgPSAodHlwZSkgPyBgJHt0eXBlfSAke3ZhcmlhYmxlfTtgIDogJyc7XG4gICAgICBsZXQgbmV3Qm9keTogc3RyaW5nID0gaW5saW5lRGVmc1tuYW1lXS5ib2R5O1xuICAgICAgbGV0IHBhcmFtUmVkZWNMaW5lID0gJyc7XG4gICAgICBpbmxpbmVEZWZzW25hbWVdLnBhcmFtcy5mb3JFYWNoKCh2LCBpKSA9PiB7XG4gICAgICAgIGlmICh2KSB7XG4gICAgICAgICAgcGFyYW1SZWRlY0xpbmUgKz0gYCR7di50eXBlfSAke3YubmFtZX0gPSAke3BhcmFtc1tpXX07XFxuYDtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICBuZXdCb2R5ID0gYCR7cGFyYW1SZWRlY0xpbmV9XFxuICR7bmV3Qm9keX1gO1xuICAgICAgbmV3Qm9keSA9IG5ld0JvZHkucmVwbGFjZSgncmV0dXJuJywgYCR7dmFyaWFibGV9ID0gYCk7XG4gICAgICBjb25zdCByZXBsYWNlbWVudCA9IGBcbiAgICAgICR7ZGVjbExpbmV9XG4gICAgICB7XG4gICAgICAgICR7bmV3Qm9keX1cbiAgICAgIH1cbiAgICAgIGA7XG4gICAgICBzY3JpcHQgPSBzY3JpcHQucmVwbGFjZShtYXRjaFswXSwgcmVwbGFjZW1lbnQpO1xuICAgIH1cbiAgfVxuICBzY3JpcHQgPSBzY3JpcHQucmVwbGFjZShJTkxJTkVfRlVOQ19ERUZfUkVHRVgsICcnKTtcbiAgcmV0dXJuIHNjcmlwdDtcbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0dsc2xDb250ZXh0LCBHbHNsTGliLCBHbHNsTGliUm91dGluZU5vZGUsIFRvcG9sb2dpY2FsU29ydEdsc2xSb3V0aW5lc30gZnJvbSAnLi9nbHNsLWRlZmluaXRpb25zJztcbmltcG9ydCB7cmVwbGFjZUlubGluZXN9IGZyb20gJy4vZ2xzbC1mdW5jdGlvbi1pbmxpbmVyJztcbmltcG9ydCB7Z2xzbFJlZ2lzdHJ5fSBmcm9tICcuL2dsc2wtcmVnaXN0ZXJlZC1saWJzJztcbmltcG9ydCB7Z2V0RGVmYXVsdEZyYWdTaGFkZXJNYWluLCBnZXRGcmFnU2hhZGVyUHJlYW1ibGV9IGZyb20gJy4vZ2xzbC1zb3VyY2UnO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgVGV4dHVyZUxheW91dCwgVmFyaWFibGVJbmZvfSBmcm9tICcuL3R5cGVzJztcbmltcG9ydCB7V2ViR0xDb250ZXh0fSBmcm9tICcuL3dlYmdsLWNvbnRleHQnO1xuXG4vKipcbiAqIFByZXByb2Nlc3NvciBmb3IgdGhlIGFkZGl0aW9ucyB0byB0aGUgR0xTTCBsYW5ndWFnZVxuICogSXQgZGVhbHMgd2l0aDpcbiAqICBAaW5jbHVkZSBkaXJlY3RpdmVzXG4gKiAgQGlubGluZVxuICogIExvb3AgdW5yb2xsaW5nIChub3QgaW1wbGVtZW50ZWQpXG4gKiAgTWFjcm8gcmVzb2x1dGlvbiAobm90IGltcGxlbWVudGVkKVxuICovXG5leHBvcnQgY2xhc3MgR2xzbFByZXByb2Nlc3NvciB7XG4gIHJlYWRvbmx5IGNvbnRleHQ6IEdsc2xDb250ZXh0O1xuICByZWFkb25seSBsaWJzOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJ9ID0ge307XG4gIHJlYWRvbmx5IGdsc2xMaWJSb3V0aW5lRGVwZW5kZW5jeUdyYXBoOiB7W3JvdXRpbmVOYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZU5vZGV9ID0ge307XG5cbiAgY29uc3RydWN0b3IoXG4gICAgICBnbENvbnRleHQ6IFdlYkdMQ29udGV4dCwgcHJvZ3JhbUluZm86IFByb2dyYW1JbmZvLCBpbnB1dFRleHR1cmVMYXlvdXRzOiBUZXh0dXJlTGF5b3V0W10sXG4gICAgICBvdXRwdXRUZXh0dXJlTGF5b3V0OiBUZXh0dXJlTGF5b3V0KSB7XG4gICAgdGhpcy5jb250ZXh0ID0gbmV3IEdsc2xDb250ZXh0KGdsQ29udGV4dCwgcHJvZ3JhbUluZm8sIGlucHV0VGV4dHVyZUxheW91dHMsIG91dHB1dFRleHR1cmVMYXlvdXQpO1xuXG4gICAgLy8gY29uc3RydWN0IEdsc2xMaWJzXG4gICAgT2JqZWN0LmtleXMoZ2xzbFJlZ2lzdHJ5KS5mb3JFYWNoKChuYW1lOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IGxpYiA9IG5ldyBnbHNsUmVnaXN0cnlbbmFtZV0odGhpcy5jb250ZXh0KTtcbiAgICAgIHRoaXMubGlic1tuYW1lXSA9IGxpYjtcbiAgICB9KTtcblxuICAgIC8vIGNvbnN0cnVjdCBHbHNsUm91dGluZURlcGVuZGVuY3lHcmFwaFxuICAgIGNvbnN0IG1hcCA9IHRoaXMuZ2xzbExpYlJvdXRpbmVEZXBlbmRlbmN5R3JhcGg7XG4gICAgZm9yIChjb25zdCBsaWJOYW1lIGluIHRoaXMubGlicykge1xuICAgICAgY29uc3QgbGliID0gdGhpcy5saWJzW2xpYk5hbWVdO1xuICAgICAgY29uc3Qgcm91dGluZXNJbkxpYiA9IGxpYi5nZXRGdW5jdGlvbnMoKTtcbiAgICAgIGZvciAoY29uc3Qgcm91dGluZSBpbiByb3V0aW5lc0luTGliKSB7XG4gICAgICAgIGNvbnN0IGtleSA9IGxpYk5hbWUgKyAnLicgKyByb3V0aW5lO1xuICAgICAgICBsZXQgY3VycmVudE5vZGU6IEdsc2xMaWJSb3V0aW5lTm9kZTtcbiAgICAgICAgaWYgKG1hcFtrZXldKSB7XG4gICAgICAgICAgY3VycmVudE5vZGUgPSBtYXBba2V5XTtcbiAgICAgICAgICBjdXJyZW50Tm9kZS5yb3V0aW5lQm9keSA9IHJvdXRpbmVzSW5MaWJbcm91dGluZV0ucm91dGluZUJvZHk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY3VycmVudE5vZGUgPSBuZXcgR2xzbExpYlJvdXRpbmVOb2RlKGtleSwgcm91dGluZXNJbkxpYltyb3V0aW5lXS5yb3V0aW5lQm9keSk7XG4gICAgICAgICAgbWFwW2tleV0gPSBjdXJyZW50Tm9kZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBkZXBlbmRlbmNpZXMgPSByb3V0aW5lc0luTGliW3JvdXRpbmVdLmRlcGVuZGVuY2llcztcbiAgICAgICAgaWYgKGRlcGVuZGVuY2llcykge1xuICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGVwZW5kZW5jaWVzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICBpZiAoIW1hcFtkZXBlbmRlbmNpZXNbaV1dKSB7XG4gICAgICAgICAgICAgIGNvbnN0IG5vZGUgPSBuZXcgR2xzbExpYlJvdXRpbmVOb2RlKGRlcGVuZGVuY2llc1tpXSk7XG4gICAgICAgICAgICAgIG1hcFtkZXBlbmRlbmNpZXNbaV1dID0gbm9kZTtcbiAgICAgICAgICAgICAgY3VycmVudE5vZGUuYWRkRGVwZW5kZW5jeShub2RlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGN1cnJlbnROb2RlLmFkZERlcGVuZGVuY3kobWFwW2RlcGVuZGVuY2llc1tpXV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByZXByb2Nlc3MoKTogc3RyaW5nIHtcbiAgICBjb25zdCBwcm9ncmFtSW5mbyA9IHRoaXMuY29udGV4dC5wcm9ncmFtSW5mbztcbiAgICBsZXQgc291cmNlID0gcHJvZ3JhbUluZm8uc2hhZGVyU291cmNlO1xuXG4gICAgLy8gYXBwZW5kIG1haW4oKSBmdW5jdGlvblxuICAgIGlmICghdGhpcy5jb250ZXh0LnByb2dyYW1JbmZvLmhhc01haW4pIHtcbiAgICAgIHNvdXJjZSA9IGAke3NvdXJjZX1cbiAgICAgICR7Z2V0RGVmYXVsdEZyYWdTaGFkZXJNYWluKHRoaXMuY29udGV4dC5nbENvbnRleHQudmVyc2lvbiwgdGhpcy5jb250ZXh0Lm91dHB1dFRleHR1cmVMYXlvdXQuc2hhcGUubGVuZ3RoKX1gO1xuICAgIH1cbiAgICAvLyByZXBsYWNlIGlubGluZXNcbiAgICBzb3VyY2UgPSByZXBsYWNlSW5saW5lcyhzb3VyY2UpO1xuXG4gICAgLy8gY29uY2F0IGZpbmFsIHNvdXJjZSBzdHJpbmdcbiAgICByZXR1cm4gYCR7Z2V0RnJhZ1NoYWRlclByZWFtYmxlKHRoaXMuY29udGV4dC5nbENvbnRleHQudmVyc2lvbil9XG4gICAgJHt0aGlzLmdldFVuaWZvcm1zKHByb2dyYW1JbmZvLmlucHV0TmFtZXMsIHByb2dyYW1JbmZvLnZhcmlhYmxlcyl9XG4gICAgJHt0aGlzLmdldEltcG9ydHMoc291cmNlKX1cbiAgICAke3NvdXJjZX1gO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldEltcG9ydHMoc2NyaXB0OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IHJvdXRpbmVzSW5jbHVkZWQgPSB0aGlzLnNlbGVjdEdsc2xMaWJSb3V0aW5lc1RvQmVJbmNsdWRlZChzY3JpcHQpO1xuXG4gICAgaWYgKHJvdXRpbmVzSW5jbHVkZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgbGV0IHJvdXRpbmVzID0gJyc7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCByb3V0aW5lc0luY2x1ZGVkLmxlbmd0aDsgKytpKSB7XG4gICAgICBpZiAocm91dGluZXNJbmNsdWRlZFtpXS5yb3V0aW5lQm9keSkge1xuICAgICAgICByb3V0aW5lcyArPSByb3V0aW5lc0luY2x1ZGVkW2ldLnJvdXRpbmVCb2R5ICsgJ1xcbic7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE1pc3NpbmcgYm9keSBmb3IgdGhlIEdsc2wgTGlicmFyeSByb3V0aW5lOiAke3JvdXRpbmVzSW5jbHVkZWRbaV0ubmFtZX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcm91dGluZXM7XG4gIH1cbiAgcHJpdmF0ZSBzZWxlY3RHbHNsTGliUm91dGluZXNUb0JlSW5jbHVkZWQoc2NyaXB0OiBzdHJpbmcpOiBHbHNsTGliUm91dGluZU5vZGVbXSB7XG4gICAgY29uc3Qgbm9kZXM6IEdsc2xMaWJSb3V0aW5lTm9kZVtdID0gW107XG5cbiAgICBPYmplY3Qua2V5cyh0aGlzLmdsc2xMaWJSb3V0aW5lRGVwZW5kZW5jeUdyYXBoKS5mb3JFYWNoKGNsYXNzQW5kUm91dGluZSA9PiB7XG4gICAgICBjb25zdCByb3V0aW5lID0gY2xhc3NBbmRSb3V0aW5lLnNwbGl0KCcuJylbMV07XG4gICAgICBpZiAoc2NyaXB0LmluZGV4T2Yocm91dGluZSkgIT09IC0xKSB7XG4gICAgICAgIG5vZGVzLnB1c2godGhpcy5nbHNsTGliUm91dGluZURlcGVuZGVuY3lHcmFwaFtjbGFzc0FuZFJvdXRpbmVdKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBUb3BvbG9naWNhbFNvcnRHbHNsUm91dGluZXMucmV0dXJuT3JkZXJlZE5vZGVzKG5vZGVzKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRVbmlmb3JtcyhzYW1wbGVycz86IHN0cmluZ1tdLCB2YXJpYWJsZXM/OiBWYXJpYWJsZUluZm9bXSk6IHN0cmluZyB7XG4gICAgY29uc3QgdW5pZm9ybUxpbmVzOiBzdHJpbmdbXSA9IFtdO1xuICAgIGlmIChzYW1wbGVycykge1xuICAgICAgZm9yIChjb25zdCBzYW1wbGVyIG9mIHNhbXBsZXJzKSB7XG4gICAgICAgIHVuaWZvcm1MaW5lcy5wdXNoKGB1bmlmb3JtIHNhbXBsZXIyRCAke3NhbXBsZXJ9O2ApO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAodmFyaWFibGVzKSB7XG4gICAgICBmb3IgKGNvbnN0IHZhcmlhYmxlIG9mIHZhcmlhYmxlcykge1xuICAgICAgICB1bmlmb3JtTGluZXMucHVzaChcbiAgICAgICAgICAgIGB1bmlmb3JtICR7dmFyaWFibGUudHlwZX0gJHt2YXJpYWJsZS5uYW1lfSR7dmFyaWFibGUuYXJyYXlMZW5ndGggPyBgWyR7dmFyaWFibGUuYXJyYXlMZW5ndGh9XWAgOiAnJ307YCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1bmlmb3JtTGluZXMuam9pbignXFxuJyk7XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0Nvb3Jkc0dsc2xMaWJ9IGZyb20gJy4vZ2xzbC1jb29yZGluYXRlLWxpYic7XG5pbXBvcnQge0dsc2xDb250ZXh0LCBHbHNsTGlifSBmcm9tICcuL2dsc2wtZGVmaW5pdGlvbnMnO1xuaW1wb3J0IHtFbmNvZGluZ0dsc2xMaWJ9IGZyb20gJy4vZ2xzbC1lbmNvZGluZy1saWInO1xuaW1wb3J0IHtGcmFnQ29sb3JHbHNsTGlifSBmcm9tICcuL2dsc2wtZnJhZ2NvbG9yLWxpYic7XG5pbXBvcnQge1NoYXBlVXRpbHNHbHNsTGlifSBmcm9tICcuL2dsc2wtc2hhcGUtdXRpbHMtbGliJztcbmltcG9ydCB7VmVjR2xzbExpYn0gZnJvbSAnLi9nbHNsLXZlYy1saWInO1xuXG5leHBvcnQgY29uc3QgZ2xzbFJlZ2lzdHJ5OiB7W25hbWU6IHN0cmluZ106IG5ldyAoY29udGV4dDogR2xzbENvbnRleHQpID0+IEdsc2xMaWJ9ID0ge1xuICAnZW5jb2RpbmcnOiBFbmNvZGluZ0dsc2xMaWIsXG4gICdmcmFnY29sb3InOiBGcmFnQ29sb3JHbHNsTGliLFxuICAndmVjJzogVmVjR2xzbExpYixcbiAgJ3NoYXBlVXRpbHMnOiBTaGFwZVV0aWxzR2xzbExpYixcbiAgJ2Nvb3JkaW5hdGVzJzogQ29vcmRzR2xzbExpYixcbiAgLy8gICdhcnJheXMnOiBBcnJheUdsc2xTTGliXG59O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7R2xzbENvbnRleHQsIEdsc2xMaWIsIEdsc2xMaWJSb3V0aW5lfSBmcm9tICcuL2dsc2wtZGVmaW5pdGlvbnMnO1xuXG4vKipcbiAqIEdMU0wgTGlicmFyeSByZXNwb25zaWJsZSBmb3IgZGF0YSB0eXBlcyBhbmQgcm91dGluZXMgZm9yIG1hbmlwdWxhdGluZ1xuICogY29vcmRpbmF0ZXMgYW5kIG1hcHBpbmcgdG8vZnJvbSB0ZW5zb3IgaW5kaWNlc1xuICovXG5leHBvcnQgY2xhc3MgU2hhcGVVdGlsc0dsc2xMaWIgZXh0ZW5kcyBHbHNsTGliIHtcbiAgY29uc3RydWN0b3IoY29udGV4dDogR2xzbENvbnRleHQpIHtcbiAgICBzdXBlcihjb250ZXh0KTtcbiAgfVxuICBnZXRGdW5jdGlvbnMoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIHJldHVybiB7XG4gICAgICAuLi50aGlzLmJjYXN0SW5kZXgoKSxcbiAgICAgIC4uLnRoaXMuYmNhc3RNYXRtdWxJbmRleCgpLFxuICAgICAgLi4udGhpcy5vZmZzZXRUb0luZGljZXMoKSxcbiAgICAgIC4uLnRoaXMuaW5kaWNlc1RvT2Zmc2V0KCksXG4gICAgICAuLi50aGlzLmluY3JlbWVudEluZGljZXMoKVxuICAgIH07XG4gIH1cbiAgZ2V0Q3VzdG9tVHlwZXMoKSB7XG4gICAgcmV0dXJuIHt9O1xuICB9XG4gIHByb3RlY3RlZCBiY2FzdEluZGV4KCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICBjb25zdCBvdXRwdXRSYW5rID0gdGhpcy5jb250ZXh0Lm91dHB1dFRleHR1cmVMYXlvdXQuc2hhcGUubGVuZ3RoO1xuICAgIGNvbnN0IHJlc3VsdDoge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0gPSB7fTtcbiAgICB0aGlzLmNvbnRleHQucHJvZ3JhbUluZm8uaW5wdXROYW1lcy5mb3JFYWNoKChuYW1lLCBpKSA9PiB7XG4gICAgICBjb25zdCBzaGFwZSA9IHRoaXMuY29udGV4dC5pbnB1dFRleHR1cmVMYXlvdXRzW2ldLnVucGFja2VkU2hhcGU7XG4gICAgICBpZiAoc2hhcGUubGVuZ3RoIDw9IG91dHB1dFJhbmspIHtcbiAgICAgICAgY29uc3QgcmFuayA9IHNoYXBlLmxlbmd0aDtcbiAgICAgICAgY29uc3QgZGltT2Zmc2V0ID0gb3V0cHV0UmFuayAtIHJhbms7XG4gICAgICAgIGNvbnN0IGZ1bmNOYW1lID0gYGJjYXN0SW5kaWNlc18ke25hbWV9YDtcbiAgICAgICAgbGV0IGJsb2NrID0gJyc7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmFuazsgKytpKSB7XG4gICAgICAgICAgYmxvY2sgKz0gYFxuICAgICAgICAgIHJlYWxJbmRpY2VzWyR7aX1dID0gaW50KCBtb2QoZmxvYXQoYmNhc3RlZEluZGljZXNbJHtkaW1PZmZzZXQgKyBpfV0pLCAke3NoYXBlW2ldfS4wKSApO1xuICAgICAgICAgIGA7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYm9keSA9IGBcbiAgICAgICAgdm9pZCAke2Z1bmNOYW1lfSAoaW50IGJjYXN0ZWRJbmRpY2VzWyR7b3V0cHV0UmFua31dLCBvdXQgaW50IHJlYWxJbmRpY2VzWyR7cmFua31dKSB7XG4gICAgICAgICAgJHtibG9ja31cbiAgICAgICAgfVxuICAgICAgICBgO1xuICAgICAgICByZXN1bHRbZnVuY05hbWVdID0gbmV3IEdsc2xMaWJSb3V0aW5lKGJvZHkpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgcHJvdGVjdGVkIGJjYXN0TWF0bXVsSW5kZXgoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IG91dHB1dFJhbmsgPSB0aGlzLmNvbnRleHQub3V0cHV0VGV4dHVyZUxheW91dC5zaGFwZS5sZW5ndGg7XG4gICAgY29uc3QgcmVzdWx0OiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSA9IHt9O1xuICAgIHRoaXMuY29udGV4dC5wcm9ncmFtSW5mby5pbnB1dE5hbWVzLmZvckVhY2goKG5hbWUsIGkpID0+IHtcbiAgICAgIGNvbnN0IHNoYXBlID0gdGhpcy5jb250ZXh0LmlucHV0VGV4dHVyZUxheW91dHNbaV0uc2hhcGU7XG4gICAgICBpZiAoIShzaGFwZS5sZW5ndGggPCAyIHx8IHNoYXBlLmxlbmd0aCA+IG91dHB1dFJhbmspKSB7XG4gICAgICAgIGNvbnN0IHJhbmsgPSBzaGFwZS5sZW5ndGg7XG4gICAgICAgIGNvbnN0IGRpbU9mZnNldCA9IG91dHB1dFJhbmsgLSByYW5rO1xuICAgICAgICBjb25zdCBmdW5jTmFtZSA9IGBiY2FzdE1hdG11bEluZGljZXNfJHtuYW1lfWA7XG4gICAgICAgIGxldCBibG9jayA9ICcnO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbmsgLSAyOyArK2kpIHtcbiAgICAgICAgICBibG9jayArPSBgXG4gICAgICAgICAgcmVhbEluZGljZXNbJHtpfV0gPSBpbnQoIG1vZChmbG9hdChiY2FzdGVkSW5kaWNlc1ske2RpbU9mZnNldCArIGl9XSksICR7c2hhcGVbaV19LjApICk7XG4gICAgICAgICAgYDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBib2R5ID0gYFxuICAgICAgICB2b2lkICR7ZnVuY05hbWV9KGludCBiY2FzdGVkSW5kaWNlc1ske291dHB1dFJhbmt9XSwgb3V0IGludCByZWFsSW5kaWNlc1ske3Jhbmt9XSkge1xuICAgICAgICAgICR7YmxvY2t9XG4gICAgICAgICAgcmVhbEluZGljZXNbJHtyYW5rIC0gMX1dID0gYmNhc3RlZEluZGljZXNbJHtvdXRwdXRSYW5rIC0gMX1dO1xuICAgICAgICAgIHJlYWxJbmRpY2VzWyR7cmFuayAtIDJ9XSA9IGJjYXN0ZWRJbmRpY2VzWyR7b3V0cHV0UmFuayAtIDJ9XTtcbiAgICAgICAgfVxuICAgICAgICBgO1xuICAgICAgICByZXN1bHRbZnVuY05hbWVdID0gbmV3IEdsc2xMaWJSb3V0aW5lKGJvZHkpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgcHJvdGVjdGVkIGluZGljZXNUb09mZnNldCgpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgY29uc3QgcmVzdWx0OiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSA9IHt9O1xuICAgIHRoaXMuY29udGV4dC5wcm9ncmFtSW5mby5pbnB1dE5hbWVzLmZvckVhY2goKG5hbWUsIGkpID0+IHtcbiAgICAgIGNvbnN0IHNoYXBlID0gdGhpcy5jb250ZXh0LmlucHV0VGV4dHVyZUxheW91dHNbaV0uc2hhcGU7XG4gICAgICBjb25zdCBzdHJpZGVzID0gdGhpcy5jb250ZXh0LmlucHV0VGV4dHVyZUxheW91dHNbaV0uc3RyaWRlcztcbiAgICAgIGNvbnN0IHJhbmsgPSBzaGFwZS5sZW5ndGg7XG4gICAgICBsZXQgZnVuY05hbWUgPSBgaW5kaWNlc1RvT2Zmc2V0XyR7bmFtZX1gO1xuICAgICAgcmVzdWx0W2Z1bmNOYW1lXSA9IG5ldyBHbHNsTGliUm91dGluZShTaGFwZVV0aWxzR2xzbExpYi5pbmRleFRvT2Zmc2V0U2luZ2xlKGZ1bmNOYW1lLCByYW5rLCBzdHJpZGVzKSk7XG4gICAgICBmdW5jTmFtZSA9IGBpbmRpY2VzVG9PZmZzZXRfJHtuYW1lfV9UYDtcbiAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPVxuICAgICAgICAgIG5ldyBHbHNsTGliUm91dGluZShTaGFwZVV0aWxzR2xzbExpYi5pbmRleFRvT2Zmc2V0U2luZ2xlKGZ1bmNOYW1lLCByYW5rLCBzdHJpZGVzLnNsaWNlKCkucmV2ZXJzZSgpKSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICBzdGF0aWMgaW5kZXhUb09mZnNldFNpbmdsZShuYW1lOiBzdHJpbmcsIHJhbms6IG51bWJlciwgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW10pOiBzdHJpbmcge1xuICAgIGxldCBibG9jayA9ICcnO1xuICAgIGZvciAobGV0IGkgPSByYW5rIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgIGJsb2NrICs9IGBcbiAgICAgICAgb2Zmc2V0ICs9IGluZGljZXNbJHtpfV0gKiAke3N0cmlkZXNbaV19O1xuICAgICAgICBgO1xuICAgIH1cbiAgICByZXR1cm4gYFxuICAgICAgaW50ICR7bmFtZX0oaW50IGluZGljZXNbJHtyYW5rfV0pIHtcbiAgICAgICAgaW50IG9mZnNldCA9IDA7XG4gICAgICAgICR7YmxvY2t9XG4gICAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgICB9XG4gICAgICBgO1xuICB9XG4gIHByb3RlY3RlZCBvZmZzZXRUb0luZGljZXMoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IHJlc3VsdDoge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0gPSB7fTtcbiAgICB0aGlzLmNvbnRleHQucHJvZ3JhbUluZm8uaW5wdXROYW1lcy5mb3JFYWNoKChuYW1lLCBpKSA9PiB7XG4gICAgICBjb25zdCBzaGFwZSA9IHRoaXMuY29udGV4dC5pbnB1dFRleHR1cmVMYXlvdXRzW2ldLnNoYXBlO1xuICAgICAgY29uc3Qgc3RyaWRlcyA9IHRoaXMuY29udGV4dC5pbnB1dFRleHR1cmVMYXlvdXRzW2ldLnN0cmlkZXM7XG4gICAgICBjb25zdCByYW5rID0gc2hhcGUubGVuZ3RoO1xuICAgICAgbGV0IGZ1bmNOYW1lID0gYG9mZnNldFRvSW5kaWNlc18ke25hbWV9YDtcbiAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPSBuZXcgR2xzbExpYlJvdXRpbmUoU2hhcGVVdGlsc0dsc2xMaWIub2Zmc2V0VG9JbmRpY2VzU2luZ2xlKGZ1bmNOYW1lLCByYW5rLCBzdHJpZGVzKSk7XG4gICAgICBmdW5jTmFtZSA9IGBvZmZzZXRUb0luZGljZXNfJHtuYW1lfV9UYDtcbiAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPVxuICAgICAgICAgIG5ldyBHbHNsTGliUm91dGluZShTaGFwZVV0aWxzR2xzbExpYi5vZmZzZXRUb0luZGljZXNTaW5nbGUoZnVuY05hbWUsIHJhbmssIHN0cmlkZXMuc2xpY2UoKS5yZXZlcnNlKCkpKTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIHN0YXRpYyBvZmZzZXRUb0luZGljZXNTaW5nbGUobmFtZTogc3RyaW5nLCByYW5rOiBudW1iZXIsIHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdKTogc3RyaW5nIHtcbiAgICBjb25zdCBzdHJpZGVzQmxvY2sgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbmsgLSAxOyArK2kpIHtcbiAgICAgIHN0cmlkZXNCbG9jay5wdXNoKGBcbiAgICAgIGluZGljZXNbJHtpfV0gPSBvZmZzZXQgLyAke3N0cmlkZXNbaV19O2ApO1xuICAgICAgc3RyaWRlc0Jsb2NrLnB1c2goYFxuICAgICAgICBvZmZzZXQgLT0gaW5kaWNlc1ske2l9XSAqICR7c3RyaWRlc1tpXX07YCk7XG4gICAgfVxuICAgIHN0cmlkZXNCbG9jay5wdXNoKGBcbiAgICAgIGluZGljZXNbJHtyYW5rIC0gMX1dID0gb2Zmc2V0O2ApO1xuICAgIHJldHVybiBgXG4gICAgICB2b2lkICR7bmFtZX0oaW50IG9mZnNldCwgb3V0IGludCBpbmRpY2VzWyR7cmFua31dKSB7XG4gICAgICAgICR7c3RyaWRlc0Jsb2NrLmpvaW4oJycpfVxuICAgICAgfVxuICAgICAgYDtcbiAgfVxuICBwcm90ZWN0ZWQgaW5jcmVtZW50SW5kaWNlcygpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgY29uc3QgcmVzdWx0OiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSA9IHt9O1xuICAgIHRoaXMuY29udGV4dC5wcm9ncmFtSW5mby5pbnB1dE5hbWVzLmZvckVhY2goKG5hbWUsIGkpID0+IHtcbiAgICAgIGNvbnN0IHNoYXBlID0gdGhpcy5jb250ZXh0LmlucHV0VGV4dHVyZUxheW91dHNbaV0uc2hhcGU7XG4gICAgICBjb25zdCByYW5rID0gc2hhcGUubGVuZ3RoO1xuICAgICAgY29uc3QgZnVuY05hbWUgPSBgaW5jcmVtZW50SW5kaWNlc18ke25hbWV9YDtcbiAgICAgIGxldCBzaGFwZUluaXQgPSAnJztcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmFuazsgKytpKSB7XG4gICAgICAgIHNoYXBlSW5pdCArPSBgXG4gICAgICAgIHNoYXBlWyR7aX1dID0gJHtzaGFwZVtpXX07YDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGJvZHkgPSBgXG4gICAgICAgIHZvaWQgJHtmdW5jTmFtZX0oaW50IGF4aXMsIG91dCBpbnQgaW5kaWNlc1ske3Jhbmt9XSkge1xuICAgICAgICAgIGludCBzaGFwZVske3Jhbmt9XTtcbiAgICAgICAgICAke3NoYXBlSW5pdH07XG4gICAgICAgICAgZm9yKGludCBpID0gJHtyYW5rfSAtMSA7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBpZihpID4gYXhpcykgY29udGludWU7XG4gICAgICAgICAgICBpbmRpY2VzW2ldICs9IDE7XG4gICAgICAgICAgICBpZihpbmRpY2VzW2ldIDwgc2hhcGVbaV0pIHtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpbmRpY2VzW2ldID0gMDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgIHJlc3VsdFtmdW5jTmFtZV0gPSBuZXcgR2xzbExpYlJvdXRpbmUoYm9keSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbi8qKlxuICogcmVwcmVzZW50IGEgdmVyc2lvbiBpcnJlbGV2YW50IGFic3RyYWN0aW9uIG9mIGZvciBHTFNMIHNvdXJjZSBjb2RlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2xzbCB7XG4gIHJlYWRvbmx5IHZlcnNpb246IHN0cmluZztcbiAgcmVhZG9ubHkgYXR0cmlidXRlOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHZhcnlpbmdWZXJ0ZXg6IHN0cmluZztcbiAgcmVhZG9ubHkgdmFyeWluZ0ZyYWc6IHN0cmluZztcbiAgcmVhZG9ubHkgdGV4dHVyZTJEOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG91dHB1dDogc3RyaW5nO1xuICByZWFkb25seSBvdXRwdXREZWNsYXJhdGlvbjogc3RyaW5nO1xufVxuXG5jb25zdCBHTFNMX0VTXzJfMDogR2xzbCA9IHtcbiAgdmVyc2lvbjogJycsXG4gIGF0dHJpYnV0ZTogJ2F0dHJpYnV0ZScsXG4gIHZhcnlpbmdWZXJ0ZXg6ICd2YXJ5aW5nJyxcbiAgdmFyeWluZ0ZyYWc6ICd2YXJ5aW5nJyxcbiAgdGV4dHVyZTJEOiAndGV4dHVyZTJEJyxcbiAgb3V0cHV0OiAnZ2xfRnJhZ0NvbG9yJyxcbiAgb3V0cHV0RGVjbGFyYXRpb246ICcnLFxufTtcbmNvbnN0IEdMU0xfRVNfM18wOiBHbHNsID0ge1xuICB2ZXJzaW9uOiAnI3ZlcnNpb24gMzAwIGVzJyxcbiAgYXR0cmlidXRlOiAnaW4nLFxuICB2YXJ5aW5nVmVydGV4OiAnb3V0JyxcbiAgdmFyeWluZ0ZyYWc6ICdpbicsXG4gIHRleHR1cmUyRDogJ3RleHR1cmUnLFxuICBvdXRwdXQ6ICdvdXRwdXRDb2xvcicsXG4gIG91dHB1dERlY2xhcmF0aW9uOiAnb3V0IHZlYzQgb3V0cHV0Q29sb3I7Jyxcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRHbHNsKHZlcnNpb246IDF8Mikge1xuICByZXR1cm4gdmVyc2lvbiA9PT0gMSA/IEdMU0xfRVNfMl8wIDogR0xTTF9FU18zXzA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRWZXJ0ZXhTaGFkZXJTb3VyY2UodmVyc2lvbjogMXwyKTogc3RyaW5nIHtcbiAgY29uc3QgZ2xzbCA9IGdldEdsc2wodmVyc2lvbik7XG4gIHJldHVybiBgJHtnbHNsLnZlcnNpb259XG4gICAgICBwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XG4gICAgICAke2dsc2wuYXR0cmlidXRlfSB2ZWMzIHBvc2l0aW9uO1xuICAgICAgJHtnbHNsLmF0dHJpYnV0ZX0gdmVjMiB0ZXh0dXJlQ29vcmQ7XG5cbiAgICAgICR7Z2xzbC52YXJ5aW5nVmVydGV4fSB2ZWMyIFRleENvb3JkcztcblxuICAgICAgdm9pZCBtYWluKClcbiAgICAgIHtcbiAgICAgICAgICBnbF9Qb3NpdGlvbiA9IHZlYzQocG9zaXRpb24sIDEuMCk7XG4gICAgICAgICAgVGV4Q29vcmRzID0gdGV4dHVyZUNvb3JkO1xuICAgICAgfWA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRGcmFnU2hhZGVyUHJlYW1ibGUodmVyc2lvbjogMXwyKTogc3RyaW5nIHtcbiAgY29uc3QgZ2xzbCA9IGdldEdsc2wodmVyc2lvbik7XG4gIHJldHVybiBgJHtnbHNsLnZlcnNpb259XG4gICAgcHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1xuICAgIHByZWNpc2lvbiBoaWdocCBpbnQ7XG4gICAgcHJlY2lzaW9uIGhpZ2hwIHNhbXBsZXIyRDtcbiAgICAke2dsc2wudmFyeWluZ0ZyYWd9IHZlYzIgVGV4Q29vcmRzO1xuICAgICR7Z2xzbC5vdXRwdXREZWNsYXJhdGlvbn1cbiAgICBjb25zdCB2ZWMyIGhhbGZDUiA9IHZlYzIoMC41LCAwLjUpO1xuXG4gICAgLy8gQ3VzdG9tIHZlY3RvciB0eXBlcyB0byBoYW5kbGUgaGlnaGVyIGRpbWVuYWxpdGllcy5cbiAgICBzdHJ1Y3QgaXZlYzVcbiAgICB7XG4gICAgICBpbnQgeDtcbiAgICAgIGludCB5O1xuICAgICAgaW50IHo7XG4gICAgICBpbnQgdztcbiAgICAgIGludCB1O1xuICAgIH07XG5cbiAgICBzdHJ1Y3QgaXZlYzZcbiAgICB7XG4gICAgICBpbnQgeDtcbiAgICAgIGludCB5O1xuICAgICAgaW50IHo7XG4gICAgICBpbnQgdztcbiAgICAgIGludCB1O1xuICAgICAgaW50IHY7XG4gICAgfTtcblxuICAgIGludCBpbW9kKGludCB4LCBpbnQgeSkge1xuICAgICAgcmV0dXJuIHggLSB5ICogKHggLyB5KTtcbiAgICB9XG5cbiAgICBgO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0RGVmYXVsdEZyYWdTaGFkZXJNYWluKHZlcnNpb246IDF8Miwgb3V0cHV0U2hhcGVMZW5ndGg6IG51bWJlcik6IHN0cmluZyB7XG4gIGNvbnN0IGdsc2wgPSBnZXRHbHNsKHZlcnNpb24pO1xuICByZXR1cm4gYFxuICB2b2lkIG1haW4oKSB7XG4gICAgaW50IGluZGljZXNbJHtvdXRwdXRTaGFwZUxlbmd0aH1dO1xuICAgIHRvVmVjKFRleENvb3JkcywgaW5kaWNlcyk7XG4gICAgdmVjNCByZXN1bHQgPSB2ZWM0KHByb2Nlc3MoaW5kaWNlcykpO1xuICAgICR7Z2xzbC5vdXRwdXR9ID0gcmVzdWx0O1xuICB9XG4gIGA7XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtHbHNsQ29udGV4dCwgR2xzbExpYiwgR2xzbExpYlJvdXRpbmV9IGZyb20gJy4vZ2xzbC1kZWZpbml0aW9ucyc7XG5cbi8qKlxuICogR0xTTCBMaWJyYXJ5IHJlc3BvbnNpYmxlIGZvciB2ZWMgcm91dGluZXNcbiAqIFZlYyBpcyBhbiB2YXJpYmxlIGxlbmd0aCBpbnQgYXJyYXkuIFRoZSBsZW5ndGggaXMgZml4ZWQgYXQgdGhlIHRpbWUgb2ZcbiAqIGdlbmVyYXRpbmcgdGhlIGxpYnJhcnkgZnVuY3Rpb25zIGZyb20gdGhlIGRpbWVuc2lvbnMgb2YgdGhlIG91dHB1dC5cbiAqL1xuZXhwb3J0IGNsYXNzIFZlY0dsc2xMaWIgZXh0ZW5kcyBHbHNsTGliIHtcbiAgY29uc3RydWN0b3IoY29udGV4dDogR2xzbENvbnRleHQpIHtcbiAgICBzdXBlcihjb250ZXh0KTtcbiAgfVxuICBnZXRDdXN0b21UeXBlcygpOiB7W25hbWU6IHN0cmluZ106IHN0cmluZ30ge1xuICAgIHJldHVybiB7fTtcbiAgfVxuICBnZXRGdW5jdGlvbnMoKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIHJldHVybiB7Li4udGhpcy5iaW5hcnlWZWNGdW5jdGlvbnMoKSwgLi4udGhpcy5jb3B5VmVjKCksIC4uLnRoaXMuc2V0VmVjSXRlbSgpLCAuLi50aGlzLmdldFZlY0l0ZW0oKX07XG4gIH1cbiAgcHJvdGVjdGVkIGJpbmFyeVZlY0Z1bmN0aW9ucygpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgY29uc3Qgb3V0cHV0TGF5b3V0ID0gdGhpcy5jb250ZXh0Lm91dHB1dFRleHR1cmVMYXlvdXQ7XG4gICAgY29uc3QgcmFuayA9IG91dHB1dExheW91dC5zaGFwZS5sZW5ndGg7XG4gICAgY29uc3QgbmFtZU9wOiB7W25hbWU6IHN0cmluZ106IHN0cmluZ30gPSB7YWRkOiAnKz0nLCBzdWI6ICctPScsIG11bDogJyo9JywgZGl2OiAnLz0nfTtcbiAgICBjb25zdCByZXN1bHQ6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9ID0ge307XG4gICAgZm9yIChjb25zdCBuYW1lIGluIG5hbWVPcCkge1xuICAgICAgY29uc3QgZm5hbWUgPSBgJHtuYW1lfVZlY2A7XG4gICAgICBsZXQgYXNzaWdubWVudEJsb2NrID0gJyc7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHJhbms7ICsraSkge1xuICAgICAgICBhc3NpZ25tZW50QmxvY2sgKz0gYFxuICAgICAgICAgIGRlc3RbJHtpfV0gJHtuYW1lT3BbbmFtZV19IHNyY1ske2l9XTtcbiAgICAgICAgICBgO1xuICAgICAgfVxuICAgICAgY29uc3QgYm9keSA9IGBcbiAgICAgICAgdm9pZCAke2ZuYW1lfShpbnQgc3JjWyR7cmFua31dLCBvdXQgaW50IGRlc3RbJHtyYW5rfV0pIHtcbiAgICAgICAgICAke2Fzc2lnbm1lbnRCbG9ja31cbiAgICAgICAgfVxuICAgICAgICBgO1xuICAgICAgcmVzdWx0W2ZuYW1lXSA9IG5ldyBHbHNsTGliUm91dGluZShib2R5KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIHByb3RlY3RlZCBjb3B5VmVjKCk6IHtbbmFtZTogc3RyaW5nXTogR2xzbExpYlJvdXRpbmV9IHtcbiAgICBjb25zdCBvdXRwdXRMYXlvdXQgPSB0aGlzLmNvbnRleHQub3V0cHV0VGV4dHVyZUxheW91dDtcbiAgICBjb25zdCByYW5rID0gb3V0cHV0TGF5b3V0LnNoYXBlLmxlbmd0aDtcbiAgICBsZXQgYXNzaWdubWVudEJsb2NrID0gJyc7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCByYW5rOyArK2kpIHtcbiAgICAgIGFzc2lnbm1lbnRCbG9jayArPSBgXG4gICAgICAgIGRlc3RbJHtpfV0gPSBzcmNbJHtpfV07XG4gICAgICAgIGA7XG4gICAgfVxuICAgIGNvbnN0IGJvZHkgPSBgXG4gICAgICB2b2lkIGNvcHlWZWMoaW50IHNyY1ske3Jhbmt9XSwgb3V0IGludCBkZXN0WyR7cmFua31dKSB7XG4gICAgICAgICR7YXNzaWdubWVudEJsb2NrfVxuICAgICAgfVxuICAgICAgYDtcbiAgICByZXR1cm4ge2NvcHlWZWM6IG5ldyBHbHNsTGliUm91dGluZShib2R5KX07XG4gIH1cblxuICBwcm90ZWN0ZWQgc2V0VmVjSXRlbSgpOiB7W25hbWU6IHN0cmluZ106IEdsc2xMaWJSb3V0aW5lfSB7XG4gICAgY29uc3Qgb3V0cHV0TGF5b3V0ID0gdGhpcy5jb250ZXh0Lm91dHB1dFRleHR1cmVMYXlvdXQ7XG4gICAgY29uc3QgcmFuayA9IG91dHB1dExheW91dC5zaGFwZS5sZW5ndGg7XG4gICAgbGV0IGJsb2NrID0gYFxuICAgICAgICBpZihpbmRleCA8IDApXG4gICAgICAgICAgICBpbmRleCA9JHtyYW5rfSArIGluZGV4O1xuICAgICAgICBpZiAoaW5kZXggPT0gMClcbiAgICAgICAgICAgIG1bMF0gPSB2YWx1ZTtcbiAgICAgICAgYDtcbiAgICBmb3IgKGxldCBpID0gMTsgaSA8IHJhbmsgLSAxOyArK2kpIHtcbiAgICAgIGJsb2NrICs9IGBcbiAgICAgICAgZWxzZSBpZiAoaW5kZXggPT0gJHtpfSlcbiAgICAgICAgICAgIG1bJHtpfV0gPSB2YWx1ZTtcbiAgICAgICAgICAgIGA7XG4gICAgfVxuICAgIGJsb2NrICs9IGBcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgbVske3JhbmsgLSAxfV0gPSB2YWx1ZTtcbiAgICAgICAgYDtcbiAgICBjb25zdCBib2R5ID0gYFxuICAgICAgdm9pZCBzZXRWZWNJdGVtKG91dCBpbnQgbVske3Jhbmt9XSwgaW50IGluZGV4LCBpbnQgdmFsdWUpIHtcbiAgICAgICAgJHtibG9ja31cbiAgICAgIH1cbiAgICAgICAgYDtcbiAgICByZXR1cm4ge3NldFZlY0l0ZW06IG5ldyBHbHNsTGliUm91dGluZShib2R5KX07XG4gIH1cbiAgcHJvdGVjdGVkIGdldFZlY0l0ZW0oKToge1tuYW1lOiBzdHJpbmddOiBHbHNsTGliUm91dGluZX0ge1xuICAgIGNvbnN0IG91dHB1dExheW91dCA9IHRoaXMuY29udGV4dC5vdXRwdXRUZXh0dXJlTGF5b3V0O1xuICAgIGNvbnN0IHJhbmsgPSBvdXRwdXRMYXlvdXQuc2hhcGUubGVuZ3RoO1xuICAgIGxldCBibG9jayA9IGBcbiAgICAgICAgaWYoaW5kZXggPCAwKVxuICAgICAgICAgICAgaW5kZXggPSAke3Jhbmt9ICsgaW5kZXg7XG4gICAgICAgIGlmIChpbmRleCA9PSAwKVxuICAgICAgICAgICAgcmV0dXJuIG1bMF07XG4gICAgICBgO1xuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgcmFuayAtIDE7ICsraSkge1xuICAgICAgYmxvY2sgKz0gYFxuICAgICAgICBlbHNlIGlmIChpbmRleCA9PSAke2l9KVxuICAgICAgICAgICAgcmV0dXJuIG1bJHtpfV07XG4gICAgICBgO1xuICAgIH1cbiAgICBibG9jayArPSBgXG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHJldHVybiBtWyR7cmFuayAtIDF9XTtcbiAgICAgICAgYDtcbiAgICBjb25zdCBib2R5ID0gYFxuICAgICAgaW50IGdldFZlY0l0ZW0oaW50IG1bJHtyYW5rfV0sIGludCBpbmRleCkge1xuICAgICAgICAke2Jsb2NrfVxuICAgICAgfVxuICAgIGA7XG4gICAgcmV0dXJuIHtnZXRWZWNJdGVtOiBuZXcgR2xzbExpYlJvdXRpbmUoYm9keSl9O1xuICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi8uLi9iYWNrZW5kJztcbmltcG9ydCB7TG9nZ2VyfSBmcm9tICcuLi8uLi9pbnN0cnVtZW50JztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtTaGFwZVV0aWx9IGZyb20gJy4uLy4uL3V0aWwnO1xuXG5pbXBvcnQge2NyZWF0ZVBhY2tQcm9ncmFtSW5mb0xvYWRlcn0gZnJvbSAnLi9vcHMvcGFjayc7XG5pbXBvcnQge2NyZWF0ZVBhY2tlZFJlc2hhcGUzRFByb2dyYW1JbmZvTG9hZGVyLCBpc1Jlc2hhcGVDaGVhcCwgcHJvY2Vzc0RpbXMzRH0gZnJvbSAnLi9vcHMvcmVzaGFwZS1wYWNrZWQnO1xuaW1wb3J0IHtlbmNvZGVBc1VpbnQ4fSBmcm9tICcuL29wcy91aW50OC1lbmNvZGUnO1xuaW1wb3J0IHtjcmVhdGVVbnBhY2tQcm9ncmFtSW5mb0xvYWRlcn0gZnJvbSAnLi9vcHMvdW5wYWNrJztcbmltcG9ydCB7V2ViR0xTZXNzaW9uSGFuZGxlcn0gZnJvbSAnLi9zZXNzaW9uLWhhbmRsZXInO1xuaW1wb3J0IHtFbmNvZGVyfSBmcm9tICcuL3RleHR1cmUtZGF0YS1lbmNvZGVyJztcbmltcG9ydCB7Y2FsY3VsYXRlVGV4dHVyZVdpZHRoQW5kSGVpZ2h0LCBjcmVhdGVUZXh0dXJlTGF5b3V0RnJvbVNoYXBlLCBjcmVhdGVUZXh0dXJlTGF5b3V0RnJvbVRleHR1cmVUeXBlfSBmcm9tICcuL3RleHR1cmUtbGF5b3V0JztcbmltcG9ydCB7QXJ0aWZhY3QsIFByb2dyYW1JbmZvLCBQcm9ncmFtSW5mb0xvYWRlciwgVGV4dHVyZURhdGEsIFRleHR1cmVMYXlvdXQsIFRleHR1cmVUeXBlfSBmcm9tICcuL3R5cGVzJztcblxuY29uc3QgZ2V0UHJvZ3JhbUluZm9VbmlxdWVLZXkgPVxuICAgIChwcm9ncmFtSW5mbzogUHJvZ3JhbUluZm98UHJvZ3JhbUluZm9Mb2FkZXIsIGlucHV0VGV4dHVyZURhdGFzOiBUZXh0dXJlRGF0YVtdKTogc3RyaW5nID0+IHtcbiAgICAgIGNvbnN0IGlucHV0cyA9XG4gICAgICAgICAgaW5wdXRUZXh0dXJlRGF0YXMubWFwKHRleHR1cmUgPT4gYCR7dGV4dHVyZS51bnBhY2tlZFNoYXBlLmpvaW4oJywnKX07JHt0ZXh0dXJlLndpZHRofXgke3RleHR1cmUuaGVpZ2h0fWApXG4gICAgICAgICAgICAgIC5qb2luKCdfJyk7XG4gICAgICBsZXQga2V5ID0gcHJvZ3JhbUluZm8ubmFtZTtcbiAgICAgIGlmIChwcm9ncmFtSW5mby5jYWNoZUhpbnQpIHtcbiAgICAgICAga2V5ICs9ICdbJyArIHByb2dyYW1JbmZvLmNhY2hlSGludCArICddJztcbiAgICAgIH1cbiAgICAgIGtleSArPSAnOicgKyBpbnB1dHM7XG4gICAgICByZXR1cm4ga2V5O1xuICAgIH07XG5cbmV4cG9ydCBjbGFzcyBXZWJHTEluZmVyZW5jZUhhbmRsZXIgaW1wbGVtZW50cyBJbmZlcmVuY2VIYW5kbGVyIHtcbiAgcHJpdmF0ZSBwYWNrZWRUZXh0dXJlRGF0YUNhY2hlOiBNYXA8VGVuc29yLklkLCBUZXh0dXJlRGF0YT47XG4gIHByaXZhdGUgdW5wYWNrZWRUZXh0dXJlRGF0YUNhY2hlOiBNYXA8VGVuc29yLklkLCBUZXh0dXJlRGF0YT47XG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBzZXNzaW9uOiBXZWJHTFNlc3Npb25IYW5kbGVyKSB7XG4gICAgdGhpcy5wYWNrZWRUZXh0dXJlRGF0YUNhY2hlID0gbmV3IE1hcCgpO1xuICAgIHRoaXMudW5wYWNrZWRUZXh0dXJlRGF0YUNhY2hlID0gbmV3IE1hcCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIFt3aWR0aCwgaGVpZ2h0XVxuICAgKi9cbiAgY2FsY3VsYXRlVGV4dHVyZVdpZHRoQW5kSGVpZ2h0KHNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlKTogW251bWJlciwgbnVtYmVyXSB7XG4gICAgcmV0dXJuIGNhbGN1bGF0ZVRleHR1cmVXaWR0aEFuZEhlaWdodCh0aGlzLnNlc3Npb24ubGF5b3V0U3RyYXRlZ3ksIHNoYXBlLCB0ZXh0dXJlVHlwZSk7XG4gIH1cblxuICBleGVjdXRlUHJvZ3JhbShwcm9ncmFtOiBQcm9ncmFtSW5mb3xQcm9ncmFtSW5mb0xvYWRlciwgaW5wdXRzOiByZWFkb25seSBUZW5zb3JbXSk6IFRleHR1cmVEYXRhIHtcbiAgICBpZiAoaW5wdXRzLmxlbmd0aCA8IHByb2dyYW0uaW5wdXROYW1lcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW5wdXQgc2l6ZSBtdXN0bid0IGJlIGxlc3MgdGhhbiAke3Byb2dyYW0uaW5wdXROYW1lcy5sZW5ndGh9LmApO1xuICAgIH1cbiAgICBpZiAocHJvZ3JhbS5pbnB1dE5hbWVzLmxlbmd0aCAhPT0gcHJvZ3JhbS5pbnB1dFR5cGVzLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dCBuYW1lcyBzaXplIGRvZXMgbm90IG1hdGNoIGlucHV0IHR5cGVzJyk7XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIHRleHR1cmUgaW5mbyBmb3IgaW5wdXRcbiAgICBjb25zdCBpbnB1dFRleHR1cmVEYXRhczogVGV4dHVyZURhdGFbXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcHJvZ3JhbS5pbnB1dE5hbWVzLmxlbmd0aDsgKytpKSB7XG4gICAgICBpbnB1dFRleHR1cmVEYXRhc1tpXSA9IHRoaXMuZ2V0T3JDcmVhdGVUZXh0dXJlRGF0YShpbnB1dHNbaV0sIHByb2dyYW0uaW5wdXRUeXBlc1tpXSk7XG4gICAgfVxuXG4gICAgY29uc3Qga2V5ID0gZ2V0UHJvZ3JhbUluZm9VbmlxdWVLZXkocHJvZ3JhbSwgaW5wdXRUZXh0dXJlRGF0YXMpO1xuICAgIGxldCBhcnRpZmFjdCA9IHRoaXMuc2Vzc2lvbi5wcm9ncmFtTWFuYWdlci5nZXRBcnRpZmFjdChrZXkpO1xuICAgIGNvbnN0IHByb2dyYW1JbmZvID0gYXJ0aWZhY3QgP1xuICAgICAgICBhcnRpZmFjdC5wcm9ncmFtSW5mbyA6XG4gICAgICAgICh0eXBlb2YgKHByb2dyYW0gYXMgUHJvZ3JhbUluZm9Mb2FkZXIpLmdldCA9PT0gJ2Z1bmN0aW9uJyA/IChwcm9ncmFtIGFzIFByb2dyYW1JbmZvTG9hZGVyKS5nZXQoKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwcm9ncmFtIGFzIFByb2dyYW1JbmZvKSk7XG5cbiAgICAvLyBjcmVhdGUgdGV4dHVyZSBpbmZvIGZvciBvdXRwdXRcbiAgICBjb25zdCBvdXRwdXRUZXh0dXJlTGF5b3V0ID0gY3JlYXRlVGV4dHVyZUxheW91dEZyb21UZXh0dXJlVHlwZShcbiAgICAgICAgdGhpcy5zZXNzaW9uLmxheW91dFN0cmF0ZWd5LCBwcm9ncmFtSW5mby5vdXRwdXQuZGltcywgcHJvZ3JhbUluZm8ub3V0cHV0LnRleHR1cmVUeXBlKTtcbiAgICBjb25zdCBvdXRwdXRUZXh0dXJlRGF0YSA9IHRoaXMuY3JlYXRlVGV4dHVyZURhdGEob3V0cHV0VGV4dHVyZUxheW91dCwgcHJvZ3JhbUluZm8ub3V0cHV0LnR5cGUpO1xuXG4gICAgaWYgKCFhcnRpZmFjdCkge1xuICAgICAgYXJ0aWZhY3QgPSB0aGlzLnNlc3Npb24ucHJvZ3JhbU1hbmFnZXIuYnVpbGQocHJvZ3JhbUluZm8sIGlucHV0VGV4dHVyZURhdGFzLCBvdXRwdXRUZXh0dXJlRGF0YSk7XG4gICAgICB0aGlzLnNlc3Npb24ucHJvZ3JhbU1hbmFnZXIuc2V0QXJ0aWZhY3Qoa2V5LCBhcnRpZmFjdCk7XG4gICAgfVxuXG4gICAgdGhpcy5ydW5Qcm9ncmFtKGFydGlmYWN0LCBpbnB1dFRleHR1cmVEYXRhcywgb3V0cHV0VGV4dHVyZURhdGEpO1xuICAgIHJldHVybiBvdXRwdXRUZXh0dXJlRGF0YTtcbiAgfVxuXG4gIHJ1bihwcm9ncmFtOiBQcm9ncmFtSW5mb0xvYWRlciwgaW5wdXRzOiByZWFkb25seSBUZW5zb3JbXSk6IFRlbnNvciB7XG4gICAgY29uc3Qgb3V0cHV0VGV4dHVyZURhdGEgPSB0aGlzLmV4ZWN1dGVQcm9ncmFtKHByb2dyYW0sIGlucHV0cyk7XG4gICAgcmV0dXJuIG91dHB1dFRleHR1cmVEYXRhLnRlbnNvcjtcbiAgfVxuXG4gIHByaXZhdGUgcnVuUHJvZ3JhbShhcnRpZmFjdDogQXJ0aWZhY3QsIGlucHV0czogVGV4dHVyZURhdGFbXSwgb3V0cHV0OiBUZXh0dXJlRGF0YSk6IHZvaWQge1xuICAgIC8vIGlucHV0IHNob3VsZCBtYXRjaFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRzLmxlbmd0aDsgKytpKSB7XG4gICAgICBpZiAoISFpbnB1dHNbaV0uaXNQYWNrZWQgIT09IChhcnRpZmFjdC5wcm9ncmFtSW5mby5pbnB1dFR5cGVzW2ldID09PSBUZXh0dXJlVHlwZS5wYWNrZWQpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaW5wdXRbJHtpfV0gcHJvcGVydHkgcGFja2VkIGluY29uc2lzdGVudGApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIG91dHB1dCBzaG91bGQgbWF0Y2hcbiAgICBpZiAoISFvdXRwdXQuaXNQYWNrZWQgIT09IChhcnRpZmFjdC5wcm9ncmFtSW5mby5vdXRwdXQudGV4dHVyZVR5cGUgPT09IFRleHR1cmVUeXBlLnBhY2tlZCkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignb3V0cHV0IHByb3BlcnR5IHBhY2tlZCBpbmNvbnNpc3RlbnQnKTtcbiAgICB9XG5cbiAgICB0aGlzLnNlc3Npb24ucHJvZ3JhbU1hbmFnZXIucnVuKGFydGlmYWN0LCBpbnB1dHMsIG91dHB1dCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgVGV4dHVyZURhdGEgb2JqZWN0IGZyb20gYSB0ZW5zb3IuXG4gICAqIFVzYWdlID0gRW5jb2Rlci5Vc2FnZS5VcGxvYWRPbmx5LlxuICAgKiBJZiBhIHJlbGF0ZWQgdGV4dHVyZSBkYXRhIGlzIGZvdW5kIGluIGNhY2hlLCByZXR1cm5zIGl0O1xuICAgKiBPdGhlcndpc2U6XG4gICAqICAgQ3JlYXRlcyBhIG5ldyB0ZXh0dXJlIGxheW91dCBpZiBub3QgcHJvdmlkZWQ7XG4gICAqICAgQ3JlYXRlcyBXZWJHTFRleHR1cmUgd2l0aCB0aGUgbGF5b3V0O1xuICAgKiAgIFVwbG9hZCB0ZW5zb3IgZGF0YSB0byB0aGUgdGV4dHVyZTtcbiAgICogICBDcmVhdGVzIGEgdGV4dHVyZSBkYXRhIG9iamVjdCBhc3NvY2lhdGVkIHdpdGggdGhlIGdpdmVuIHRlbnNvci5cbiAgICogQHBhcmFtIHRlbnNvciB0aGUgdGVuc29yIHdpdGggZGF0YSB0byB1cGxvYWRcbiAgICovXG4gIHByaXZhdGUgZ2V0T3JDcmVhdGVUZXh0dXJlRGF0YSh0ZW5zb3I6IFRlbnNvciwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlKSB7XG4gICAgbGV0IHRkID0gdGhpcy5nZXRUZXh0dXJlRGF0YSh0ZW5zb3IuZGF0YUlkLCB0ZXh0dXJlVHlwZSA9PT0gVGV4dHVyZVR5cGUucGFja2VkKTtcblxuICAgIGlmICghdGQpIHtcbiAgICAgIC8vIGNoZWNrIGlmIHdlIGhhdmUgdGV4dHVyZSBkYXRhIGluIGRpZmZlcmVudCB0eXBlXG4gICAgICB0ZCA9IHRoaXMuZ2V0VGV4dHVyZURhdGEodGVuc29yLmRhdGFJZCwgdGV4dHVyZVR5cGUgIT09IFRleHR1cmVUeXBlLnBhY2tlZCk7XG4gICAgICBpZiAodGQpIHtcbiAgICAgICAgaWYgKHRleHR1cmVUeXBlID09PSBUZXh0dXJlVHlwZS5wYWNrZWQpIHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5wYWNrKHRkKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gdGhpcy51bnBhY2sodGQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCF0ZCkge1xuICAgICAgY29uc3QgbGF5b3V0ID0gY3JlYXRlVGV4dHVyZUxheW91dEZyb21UZXh0dXJlVHlwZSh0aGlzLnNlc3Npb24ubGF5b3V0U3RyYXRlZ3ksIHRlbnNvci5kaW1zLCB0ZXh0dXJlVHlwZSk7XG5cbiAgICAgIGlmICh0ZXh0dXJlVHlwZSA9PT0gVGV4dHVyZVR5cGUucGFja2VkTGFzdERpbWVuc2lvbikge1xuICAgICAgICBjb25zdCBncm91cCA9IDE7XG4gICAgICAgIGNvbnN0IGNoYW5uZWxzID0gNDtcbiAgICAgICAgY29uc3Qgc2hhcGUgPSB0ZW5zb3IuZGltcztcbiAgICAgICAgaWYgKHNoYXBlLmxlbmd0aCA9PT0gNCkge1xuICAgICAgICAgIC8vIHByZS1wcm9jZXNzaW5nIGZvciBrZXJuZWwgZGF0YSBvZiBDb252LlxuICAgICAgICAgIC8vXG4gICAgICAgICAgLy8gVE9ETzogY3VycmVudGx5IHRoaXMgaXMgYSBoYWNraW5nIHRvIG92ZXJ3cml0ZSBDb252J3Mgd2VpZ2h0LiBUaGUgY29ycmVjdCB3YXkgdG8gZG8gdGhpcyBzaG91bGQgYmU6XG4gICAgICAgICAgLy8gMS4gaW1wbGVtZW50IHRleHR1cmUgYmFzZWQgY29uc3QtZm9sZGluZ1xuICAgICAgICAgIC8vIDIuIGNyZWF0ZSBhIFdlYkdMIHByb2dyYW0gXCJwcmVwcm9jZXNzQ29udldlaWdodFwiIHRvIGRvIHRoZSBzYW1lIHdvcmsgYXMgYmVsb3dcbiAgICAgICAgICAvLyAzLiBydW4gdGhlIHByb2dyYW0gYmVmb3JlIGRvdFByb2R1Y3QuXG4gICAgICAgICAgLy9cbiAgICAgICAgICBjb25zdCBhZGp1c3RlZEtlcm5lbFNoYXBlID0gW3NoYXBlWzBdLCBNYXRoLmNlaWwoKHNoYXBlWzFdICogc2hhcGVbMl0gKiBzaGFwZVszXSkgLyBjaGFubmVscyldO1xuICAgICAgICAgIGNvbnN0IGFkanVzdGVkTGF5b3V0ID1cbiAgICAgICAgICAgICAgY3JlYXRlVGV4dHVyZUxheW91dEZyb21UZXh0dXJlVHlwZSh0aGlzLnNlc3Npb24ubGF5b3V0U3RyYXRlZ3ksIGFkanVzdGVkS2VybmVsU2hhcGUsIHRleHR1cmVUeXBlKTtcbiAgICAgICAgICBsZXQgYnVmZmVyID0gdGVuc29yLm51bWJlckRhdGE7XG4gICAgICAgICAgaWYgKHNoYXBlWzFdICogc2hhcGVbMl0gKiBzaGFwZVszXSAlIGNoYW5uZWxzICE9PSAwKSB7XG4gICAgICAgICAgICBjb25zdCBudW1GZWF0dXJlTWFwcyA9IHNoYXBlWzBdO1xuICAgICAgICAgICAgY29uc3Qgb2xkUm93U2l6ZSA9IHNoYXBlWzFdICogc2hhcGVbMl0gKiBzaGFwZVszXTtcbiAgICAgICAgICAgIGNvbnN0IG5ld1Jvd1NpemUgPSBNYXRoLmNlaWwob2xkUm93U2l6ZSAqIGdyb3VwIC8gY2hhbm5lbHMpICogY2hhbm5lbHM7XG4gICAgICAgICAgICBjb25zdCBuZXdTaXplID0gbnVtRmVhdHVyZU1hcHMgKiBuZXdSb3dTaXplO1xuICAgICAgICAgICAgYnVmZmVyID0gbmV3IEZsb2F0MzJBcnJheShuZXdTaXplKTtcbiAgICAgICAgICAgIGZvciAobGV0IGYgPSAwOyBmIDwgbnVtRmVhdHVyZU1hcHM7ICsrZikge1xuICAgICAgICAgICAgICBjb25zdCBvbGRPZmZzZXQgPSBmICogb2xkUm93U2l6ZTtcbiAgICAgICAgICAgICAgY29uc3QgbmV3T2Zmc2V0ID0gZiAqIG5ld1Jvd1NpemUgKyBmICUgZ3JvdXAgKiBvbGRSb3dTaXplO1xuICAgICAgICAgICAgICBidWZmZXIuc2V0KHRlbnNvci5udW1iZXJEYXRhLnN1YmFycmF5KG9sZE9mZnNldCwgb2xkT2Zmc2V0ICsgb2xkUm93U2l6ZSksIG5ld09mZnNldCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZVRleHR1cmVEYXRhKGFkanVzdGVkTGF5b3V0LCB0ZW5zb3IudHlwZSwgYnVmZmVyLCB0ZW5zb3IsIEVuY29kZXIuVXNhZ2UuVXBsb2FkT25seSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKHRleHR1cmVUeXBlID09PSBUZXh0dXJlVHlwZS5wYWNrZWQpIHtcbiAgICAgICAgY29uc3QgdW5wYWNrZWRUZXh0dXJlTGF5b3V0ID1cbiAgICAgICAgICAgIGNyZWF0ZVRleHR1cmVMYXlvdXRGcm9tU2hhcGUodGhpcy5zZXNzaW9uLmxheW91dFN0cmF0ZWd5LCB0ZW5zb3IuZGltcywgMSwgW10sIHtyZXZlcnNlV0g6IHRydWV9KTtcbiAgICAgICAgY29uc3QgdW5wYWNrZWRUZXh0dXJlRGF0YSA9IHRoaXMuY3JlYXRlVGV4dHVyZURhdGEoXG4gICAgICAgICAgICB1bnBhY2tlZFRleHR1cmVMYXlvdXQsIHRlbnNvci50eXBlLCB0ZW5zb3IubnVtYmVyRGF0YSwgdGVuc29yLCBFbmNvZGVyLlVzYWdlLlVwbG9hZE9ubHkpO1xuICAgICAgICB0ZCA9IHRoaXMucGFjayh1bnBhY2tlZFRleHR1cmVEYXRhKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRkID0gdGhpcy5jcmVhdGVUZXh0dXJlRGF0YShsYXlvdXQsIHRlbnNvci50eXBlLCB0ZW5zb3IubnVtYmVyRGF0YSwgdGVuc29yLCBFbmNvZGVyLlVzYWdlLlVwbG9hZE9ubHkpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGQ7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgVGV4dHVyZURhdGEgb2JqZWN0IHVzaW5nIHRoZSBnaXZlbiBkYXRhIGFuZCBiaW5kIHRvIHRoZSBnaXZlbiB0ZW5zb3IuXG4gICAqIFVzYWdlID0gRW5jb2Rlci5Vc2FnZS5VcGxvYWRPbmx5LlxuICAgKiBOT1RFOiB0aGlzIGZ1bmN0aW9uIGlzIGEgaGFjayBmb3IgQ29udiBpbXBsZW1lbnRhdGlvbi4gc2hvdWxkIHJlbW92ZSB0aGlzIGZ1bmN0aW9uLCBhZnRlciByZXdyaXRpbmcgQ29udlxuICAgKiBpbXBsZW1lbnRhdGlvbiBieSBHcmFwaC5UcmFuc2Zvcm1lclxuICAgKiBAcGFyYW0gZGF0YVR5cGUgdGhlIHRlbnNvciBkYXRhIHR5cGVcbiAgICogQHBhcmFtIGRhdGEgdGhlIGFjdHVhbCBkYXRhIHRvIHVwbG9hZFxuICAgKiBAcGFyYW0gdGVuc29yIHRoZSB0ZW5zb3IgdG8gYmluZC4gdGVuc29yJ3MgZGF0YSBpcyBpZ25vcmVkLlxuICAgKi9cbiAgY3JlYXRlVGV4dHVyZURhdGFGcm9tTGF5b3V0QmluZFRlbnNvcihcbiAgICAgIGxheW91dDogVGV4dHVyZUxheW91dCwgZGF0YVR5cGU6IFRlbnNvci5EYXRhVHlwZSwgZGF0YTogVGVuc29yLk51bWJlclR5cGUsIHRlbnNvcjogVGVuc29yKTogVGV4dHVyZURhdGEge1xuICAgIHJldHVybiB0aGlzLmNyZWF0ZVRleHR1cmVEYXRhKGxheW91dCwgZGF0YVR5cGUsIGRhdGEsIHRlbnNvciwgRW5jb2Rlci5Vc2FnZS5VcGxvYWRPbmx5KTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlVGV4dHVyZURhdGEoXG4gICAgICBsYXlvdXQ6IFRleHR1cmVMYXlvdXQsIGRhdGFUeXBlOiBUZW5zb3IuRGF0YVR5cGUsIGRhdGE/OiBUZW5zb3IuTnVtYmVyVHlwZSwgdGVuc29yPzogVGVuc29yLFxuICAgICAgdXNhZ2U/OiBFbmNvZGVyLlVzYWdlKTogVGV4dHVyZURhdGEge1xuICAgIExvZ2dlci52ZXJib3NlKCdJbmZlcmVuY2VIYW5kbGVyJywgYENyZWF0aW5nIFRleHR1cmVEYXRhOiBsYXlvdXQ6WyR7SlNPTi5zdHJpbmdpZnkobGF5b3V0KX1dYCk7XG4gICAgY29uc3QgdGV4dHVyZSA9IHRoaXMuc2Vzc2lvbi50ZXh0dXJlTWFuYWdlci5jcmVhdGVUZXh0dXJlRnJvbUxheW91dChkYXRhVHlwZSwgbGF5b3V0LCBkYXRhLCB1c2FnZSk7XG4gICAgcmV0dXJuIHRoaXMuY3JlYXRlVGV4dHVyZURhdGFGcm9tVGV4dHVyZShsYXlvdXQsIGRhdGFUeXBlLCB0ZXh0dXJlLCB0ZW5zb3IpO1xuICB9XG5cbiAgcmVzaGFwZVVucGFja2VkKGlucHV0OiBUZW5zb3IsIHJlc2hhcGVkRGltczogcmVhZG9ubHkgbnVtYmVyW10pOiBUZW5zb3Ige1xuICAgIGNvbnN0IGlucHV0VEQgPSB0aGlzLmdldE9yQ3JlYXRlVGV4dHVyZURhdGEoaW5wdXQsIFRleHR1cmVUeXBlLnVucGFja2VkKTtcbiAgICBjb25zdCBuZXdUZXh0dXJlTGF5b3V0OiBUZXh0dXJlTGF5b3V0ID0ge1xuICAgICAgY2hhbm5lbHM6IGlucHV0VEQuY2hhbm5lbHMsXG4gICAgICBoZWlnaHQ6IGlucHV0VEQuaGVpZ2h0LFxuICAgICAgd2lkdGg6IGlucHV0VEQud2lkdGgsXG4gICAgICAvLyBoYW5kbGUgcmVzaGFwaW5nIGludG8gc2NhbGFyIFRlbnNvcnNcbiAgICAgIHNoYXBlOiByZXNoYXBlZERpbXMubGVuZ3RoICE9PSAwID8gcmVzaGFwZWREaW1zIDogWzFdLFxuICAgICAgc3RyaWRlczogU2hhcGVVdGlsLmNvbXB1dGVTdHJpZGVzKHJlc2hhcGVkRGltcyksXG4gICAgICB1bnBhY2tlZFNoYXBlOiByZXNoYXBlZERpbXMsXG4gICAgfTtcbiAgICBjb25zdCBuZXdUZXh0dXJlRGF0YSA9IHRoaXMuY3JlYXRlVGV4dHVyZURhdGFGcm9tVGV4dHVyZShuZXdUZXh0dXJlTGF5b3V0LCBpbnB1dC50eXBlLCBpbnB1dFRELnRleHR1cmUpO1xuICAgIHJldHVybiBuZXdUZXh0dXJlRGF0YS50ZW5zb3I7XG4gIH1cblxuICByZXNoYXBlUGFja2VkKGlucHV0OiBUZW5zb3IsIHJlc2hhcGVkRGltczogcmVhZG9ubHkgbnVtYmVyW10pOiBUZW5zb3Ige1xuICAgIGNvbnN0IGlucHV0VEQgPSB0aGlzLmdldE9yQ3JlYXRlVGV4dHVyZURhdGEoaW5wdXQsIFRleHR1cmVUeXBlLnBhY2tlZCk7XG5cbiAgICAvLyBjaGVjayBpZiB0aGUgcmVzaGFwZSBpcyAnY2hlYXAnXG4gICAgaWYgKGlzUmVzaGFwZUNoZWFwKGlucHV0LmRpbXMsIHJlc2hhcGVkRGltcykpIHtcbiAgICAgIGNvbnN0IG5ld1RleHR1cmVMYXlvdXQ6IFRleHR1cmVMYXlvdXQgPSB7XG4gICAgICAgIGNoYW5uZWxzOiBpbnB1dFRELmNoYW5uZWxzLFxuICAgICAgICBoZWlnaHQ6IGlucHV0VEQuaGVpZ2h0LFxuICAgICAgICB3aWR0aDogaW5wdXRURC53aWR0aCxcbiAgICAgICAgLy8gaGFuZGxlIHJlc2hhcGluZyBpbnRvIHNjYWxhciBUZW5zb3JzXG4gICAgICAgIHNoYXBlOiByZXNoYXBlZERpbXMubGVuZ3RoICE9PSAwID8gcmVzaGFwZWREaW1zIDogWzFdLFxuICAgICAgICBzdHJpZGVzOiBTaGFwZVV0aWwuY29tcHV0ZVN0cmlkZXMocmVzaGFwZWREaW1zKSxcbiAgICAgICAgdW5wYWNrZWRTaGFwZTogcmVzaGFwZWREaW1zLFxuICAgICAgICBpc1BhY2tlZDogdHJ1ZVxuICAgICAgfTtcbiAgICAgIGNvbnN0IG5ld1RleHR1cmVEYXRhID0gdGhpcy5jcmVhdGVUZXh0dXJlRGF0YUZyb21UZXh0dXJlKG5ld1RleHR1cmVMYXlvdXQsIGlucHV0LnR5cGUsIGlucHV0VEQudGV4dHVyZSk7XG4gICAgICByZXR1cm4gbmV3VGV4dHVyZURhdGEudGVuc29yO1xuICAgIH1cblxuICAgIGNvbnN0IHNxdWVlemVkSW5wdXRTaGFwZSA9IHByb2Nlc3NEaW1zM0QoaW5wdXQuZGltcyk7XG4gICAgY29uc3Qgc3F1ZWV6ZWRPdXRwdXRTaGFwZSA9IHByb2Nlc3NEaW1zM0QocmVzaGFwZWREaW1zKTtcblxuICAgIGNvbnN0IHNxdWVlemVkSW5wdXRUZW5zb3IgPSB0aGlzLnJlc2hhcGVQYWNrZWQoaW5wdXQsIHNxdWVlemVkSW5wdXRTaGFwZSk7XG4gICAgY29uc3Qgc3F1ZWV6ZWRPdXRwdXRUZW5zb3IgPSB0aGlzLnJ1bihcbiAgICAgICAgY3JlYXRlUGFja2VkUmVzaGFwZTNEUHJvZ3JhbUluZm9Mb2FkZXIodGhpcywgc3F1ZWV6ZWRJbnB1dFRlbnNvciwgc3F1ZWV6ZWRPdXRwdXRTaGFwZSksIFtzcXVlZXplZElucHV0VGVuc29yXSk7XG4gICAgY29uc3Qgb3V0cHV0VGVuc29yID0gdGhpcy5yZXNoYXBlUGFja2VkKHNxdWVlemVkT3V0cHV0VGVuc29yLCByZXNoYXBlZERpbXMpO1xuICAgIHJldHVybiBvdXRwdXRUZW5zb3I7XG4gIH1cblxuICBjYXN0KGlucHV0OiBUZW5zb3IsIHR5cGU6IFRlbnNvci5EYXRhVHlwZSk6IFRlbnNvciB7XG4gICAgY29uc3QgaW5wdXRURCA9IHRoaXMuZ2V0T3JDcmVhdGVUZXh0dXJlRGF0YShpbnB1dCwgVGV4dHVyZVR5cGUudW5wYWNrZWQpO1xuICAgIGNvbnN0IG5ld1RleHR1cmVEYXRhID0gdGhpcy5jcmVhdGVUZXh0dXJlRGF0YUZyb21UZXh0dXJlKGlucHV0VEQgYXMgVGV4dHVyZUxheW91dCwgdHlwZSwgaW5wdXRURC50ZXh0dXJlKTtcbiAgICByZXR1cm4gbmV3VGV4dHVyZURhdGEudGVuc29yO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVUZXh0dXJlRGF0YUZyb21UZXh0dXJlKFxuICAgICAgbGF5b3V0OiBUZXh0dXJlTGF5b3V0LCBkYXRhVHlwZTogVGVuc29yLkRhdGFUeXBlLCB0ZXh0dXJlOiBXZWJHTFRleHR1cmUsIHRlbnNvcj86IFRlbnNvciwgdGVuc29ySWQ/OiBUZW5zb3IuSWQpIHtcbiAgICBjb25zdCB0ZXh0dXJlRGF0YTogVGV4dHVyZURhdGEgPSB7XG4gICAgICAuLi5sYXlvdXQsXG4gICAgICB0ZW5zb3I6IHRlbnNvciB8fFxuICAgICAgICAgIG5ldyBUZW5zb3IoXG4gICAgICAgICAgICAgICAgICBsYXlvdXQudW5wYWNrZWRTaGFwZSwgZGF0YVR5cGUsIChfaWQ6IFRlbnNvci5JZCkgPT4gdGhpcy5yZWFkVGV4dHVyZSh0ZXh0dXJlRGF0YSksXG4gICAgICAgICAgICAgICAgICBhc3luYyAoX2lkOiBUZW5zb3IuSWQpID0+IHRoaXMucmVhZFRleHR1cmVBc3luYyh0ZXh0dXJlRGF0YSksIHVuZGVmaW5lZCwgdGVuc29ySWQpLFxuICAgICAgdGV4dHVyZVxuICAgIH07XG4gICAgdGhpcy5zZXRUZXh0dXJlRGF0YSh0ZXh0dXJlRGF0YS50ZW5zb3IuZGF0YUlkLCB0ZXh0dXJlRGF0YSwgbGF5b3V0LmlzUGFja2VkKTtcbiAgICByZXR1cm4gdGV4dHVyZURhdGE7XG4gIH1cblxuICBwcml2YXRlIGdldFRleHR1cmVEYXRhKHRlbnNvcklkOiBUZW5zb3IuSWQsIGlzUGFja2VkID0gZmFsc2UpOiBUZXh0dXJlRGF0YXx1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnNlc3Npb24uaXNJbml0aWFsaXplcih0ZW5zb3JJZCkgPyB0aGlzLnNlc3Npb24uZ2V0VGV4dHVyZURhdGEodGVuc29ySWQsIGlzUGFja2VkKSA6XG4gICAgICAgIGlzUGFja2VkICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IHRoaXMucGFja2VkVGV4dHVyZURhdGFDYWNoZS5nZXQodGVuc29ySWQpIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy51bnBhY2tlZFRleHR1cmVEYXRhQ2FjaGUuZ2V0KHRlbnNvcklkKTtcbiAgfVxuICBzZXRUZXh0dXJlRGF0YSh0ZW5zb3JJZDogVGVuc29yLklkLCB0ZDogVGV4dHVyZURhdGEsIGlzUGFja2VkID0gZmFsc2UpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zZXNzaW9uLmlzSW5pdGlhbGl6ZXIodGVuc29ySWQpKSB7XG4gICAgICB0aGlzLnNlc3Npb24uc2V0VGV4dHVyZURhdGEodGVuc29ySWQsIHRkLCBpc1BhY2tlZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIChpc1BhY2tlZCA/IHRoaXMucGFja2VkVGV4dHVyZURhdGFDYWNoZSA6IHRoaXMudW5wYWNrZWRUZXh0dXJlRGF0YUNhY2hlKS5zZXQodGVuc29ySWQsIHRkKTtcbiAgICB9XG4gIH1cbiAgaXNUZXh0dXJlTGF5b3V0Q2FjaGVkKHRlbnNvcjogVGVuc29yLCBpc1BhY2tlZCA9IGZhbHNlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5nZXRUZXh0dXJlRGF0YSh0ZW5zb3IuZGF0YUlkLCBpc1BhY2tlZCk7XG4gIH1cblxuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIHRoaXMuc2Vzc2lvbi50ZXh0dXJlTWFuYWdlci5jbGVhckFjdGl2ZVRleHR1cmVzKCk7XG4gICAgdGhpcy5wYWNrZWRUZXh0dXJlRGF0YUNhY2hlLmZvckVhY2godGQgPT4gdGhpcy5zZXNzaW9uLnRleHR1cmVNYW5hZ2VyLnJlbGVhc2VUZXh0dXJlKHRkKSk7XG4gICAgdGhpcy5wYWNrZWRUZXh0dXJlRGF0YUNhY2hlID0gbmV3IE1hcCgpO1xuICAgIHRoaXMudW5wYWNrZWRUZXh0dXJlRGF0YUNhY2hlLmZvckVhY2godGQgPT4gdGhpcy5zZXNzaW9uLnRleHR1cmVNYW5hZ2VyLnJlbGVhc2VUZXh0dXJlKHRkKSk7XG4gICAgdGhpcy51bnBhY2tlZFRleHR1cmVEYXRhQ2FjaGUgPSBuZXcgTWFwKCk7XG4gIH1cblxuICByZWFkVGV4dHVyZSh0ZXh0dXJlRGF0YTogVGV4dHVyZURhdGEpOiBUZW5zb3IuTnVtYmVyVHlwZSB7XG4gICAgaWYgKHRleHR1cmVEYXRhLmlzUGFja2VkKSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWFkVGV4dHVyZSh0aGlzLnVucGFjayh0ZXh0dXJlRGF0YSkpO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuc2Vzc2lvbi5iYWNrZW5kLmdsQ29udGV4dC5pc0Zsb2F0MzJEb3dubG9hZFN1cHBvcnRlZCkge1xuICAgICAgcmV0dXJuIHRoaXMuc2Vzc2lvbi50ZXh0dXJlTWFuYWdlci5yZWFkVWludDhUZXh0dXJlQXNGbG9hdChlbmNvZGVBc1VpbnQ4KHRoaXMsIHRleHR1cmVEYXRhKSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnNlc3Npb24udGV4dHVyZU1hbmFnZXIucmVhZFRleHR1cmUodGV4dHVyZURhdGEsIHRleHR1cmVEYXRhLnRlbnNvci50eXBlLCB0ZXh0dXJlRGF0YS5jaGFubmVscyk7XG4gIH1cblxuICBhc3luYyByZWFkVGV4dHVyZUFzeW5jKHRleHR1cmVEYXRhOiBUZXh0dXJlRGF0YSk6IFByb21pc2U8VGVuc29yLk51bWJlclR5cGU+IHtcbiAgICBpZiAodGV4dHVyZURhdGEuaXNQYWNrZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLnJlYWRUZXh0dXJlQXN5bmModGhpcy51bnBhY2sodGV4dHVyZURhdGEpKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQuaXNGbG9hdDMyRG93bmxvYWRTdXBwb3J0ZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLnNlc3Npb24udGV4dHVyZU1hbmFnZXIucmVhZFVpbnQ4VGV4dHVyZUFzRmxvYXQoZW5jb2RlQXNVaW50OCh0aGlzLCB0ZXh0dXJlRGF0YSkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uLnRleHR1cmVNYW5hZ2VyLnJlYWRUZXh0dXJlQXN5bmModGV4dHVyZURhdGEsIHRleHR1cmVEYXRhLnRlbnNvci50eXBlLCB0ZXh0dXJlRGF0YS5jaGFubmVscyk7XG4gIH1cblxuICBwYWNrKGlucHV0OiBUZXh0dXJlRGF0YSk6IFRleHR1cmVEYXRhIHtcbiAgICBjb25zdCBvdXRwdXRUZXh0dXJlRGF0YSA9IHRoaXMuZXhlY3V0ZVByb2dyYW0oY3JlYXRlUGFja1Byb2dyYW1JbmZvTG9hZGVyKHRoaXMsIGlucHV0LnRlbnNvciksIFtpbnB1dC50ZW5zb3JdKTtcbiAgICByZXR1cm4gb3V0cHV0VGV4dHVyZURhdGE7XG4gIH1cblxuICB1bnBhY2soaW5wdXQ6IFRleHR1cmVEYXRhKTogVGV4dHVyZURhdGEge1xuICAgIGNvbnN0IG91dHB1dFRleHR1cmVEYXRhID0gdGhpcy5leGVjdXRlUHJvZ3JhbShjcmVhdGVVbnBhY2tQcm9ncmFtSW5mb0xvYWRlcih0aGlzLCBpbnB1dC50ZW5zb3IpLCBbaW5wdXQudGVuc29yXSk7XG4gICAgcmV0dXJuIG91dHB1dFRleHR1cmVEYXRhO1xuICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtPcFNldH0gZnJvbSAnLi4vLi4vb3BzZXQnO1xuXG5pbXBvcnQge2JhdGNoTm9ybWFsaXphdGlvbiwgcGFyc2VCYXRjaE5vcm1hbGl6YXRpb25BdHRyaWJ1dGVzfSBmcm9tICcuL29wcy9iYXRjaC1ub3JtYWxpemF0aW9uJztcbmltcG9ydCAqIGFzIGJpbmFyeU9wcyBmcm9tICcuL29wcy9iaW5hcnktb3AnO1xuaW1wb3J0IHtjYXN0LCBwYXJzZUNhc3RBdHRyaWJ1dGVzfSBmcm9tICcuL29wcy9jYXN0JztcbmltcG9ydCB7Y29uY2F0LCBwYXJzZUNvbmNhdEF0dHJpYnV0ZXN9IGZyb20gJy4vb3BzL2NvbmNhdCc7XG5pbXBvcnQge2NvbnYsIHBhcnNlQ29udkF0dHJpYnV0ZXN9IGZyb20gJy4vb3BzL2NvbnYnO1xuaW1wb3J0IHtjb252VHJhbnNwb3NlLCBwYXJzZUNvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzfSBmcm9tICcuL29wcy9jb252LXRyYW5zcG9zZSc7XG5pbXBvcnQge2RlcHRoVG9TcGFjZSwgcGFyc2VEZXB0aFRvU3BhY2VBdHRyaWJ1dGVzfSBmcm9tICcuL29wcy9kZXB0aC10by1zcGFjZSc7XG5pbXBvcnQge2ZsYXR0ZW4sIHBhcnNlRmxhdHRlbkF0dHJpYnV0ZXN9IGZyb20gJy4vb3BzL2ZsYXR0ZW4nO1xuaW1wb3J0IHtnYXRoZXIsIHBhcnNlR2F0aGVyQXR0cmlidXRlc30gZnJvbSAnLi9vcHMvZ2F0aGVyJztcbmltcG9ydCB7Z2VtbSwgcGFyc2VHZW1tQXR0cmlidXRlc1YxMSwgcGFyc2VHZW1tQXR0cmlidXRlc1Y3fSBmcm9tICcuL29wcy9nZW1tJztcbmltcG9ydCB7aW1hZ2VTY2FsZXIsIHBhcnNlSW1hZ2VTY2FsZXJBdHRyaWJ1dGVzfSBmcm9tICcuL29wcy9pbWFnZS1zY2FsZXInO1xuaW1wb3J0IHtpbnN0YW5jZU5vcm1hbGl6YXRpb24sIHBhcnNlSW5zdGFuY2VOb3JtYWxpemF0aW9uQXR0cmlidXRlc30gZnJvbSAnLi9vcHMvaW5zdGFuY2Utbm9ybWFsaXphdGlvbic7XG5pbXBvcnQge2xybiwgcGFyc2VMcm5BdHRyaWJ1dGVzfSBmcm9tICcuL29wcy9scm4nO1xuaW1wb3J0IHttYXRNdWwsIHBhcnNlTWF0TXVsQXR0cmlidXRlc30gZnJvbSAnLi9vcHMvbWF0bXVsJztcbmltcG9ydCB7cGFkVjExLCBwYWRWMiwgcGFyc2VQYWRBdHRyaWJ1dGVzVjExLCBwYXJzZVBhZEF0dHJpYnV0ZXNWMn0gZnJvbSAnLi9vcHMvcGFkJztcbmltcG9ydCB7YXZlcmFnZVBvb2wsIGdsb2JhbEF2ZXJhZ2VQb29sLCBnbG9iYWxNYXhQb29sLCBtYXhQb29sLCBwYXJzZUF2ZXJhZ2VQb29sQXR0cmlidXRlcywgcGFyc2VHbG9iYWxBdmVyYWdlUG9vbEF0dHJpYnV0ZXMsIHBhcnNlTWF4UG9vbEF0dHJpYnV0ZXN9IGZyb20gJy4vb3BzL3Bvb2wnO1xuaW1wb3J0IHtwYXJzZVJlZHVjZUF0dHJpYnV0ZXMsIHJlZHVjZUxvZ1N1bSwgcmVkdWNlTG9nU3VtU3F1YXJlLCByZWR1Y2VNYXgsIHJlZHVjZU1lYW4sIHJlZHVjZU1pbiwgcmVkdWNlUHJvZCwgcmVkdWNlU3VtfSBmcm9tICcuL29wcy9yZWR1Y2UnO1xuaW1wb3J0IHtyZXNoYXBlfSBmcm9tICcuL29wcy9yZXNoYXBlJztcbmltcG9ydCB7cGFyc2VSZXNpemVBdHRyaWJ1dGVzVjEwLCBwYXJzZVJlc2l6ZUF0dHJpYnV0ZXNWMTEsIHJlc2l6ZX0gZnJvbSAnLi9vcHMvcmVzaXplLXBhY2tlZCc7XG5pbXBvcnQge3NoYXBlfSBmcm9tICcuL29wcy9zaGFwZSc7XG5pbXBvcnQge3BhcnNlU2xpY2VBdHRyaWJ1dGVzLCBzbGljZSwgc2xpY2VWMTB9IGZyb20gJy4vb3BzL3NsaWNlJztcbmltcG9ydCB7cGFyc2VTb2Z0bWF4QXR0cmlidXRlcywgcGFyc2VTb2Z0bWF4QXR0cmlidXRlc1YxMywgc29mdG1heCwgc29mdG1heFYxM30gZnJvbSAnLi9vcHMvc29mdG1heCc7XG5pbXBvcnQge3BhcnNlU3BsaXRBdHRyaWJ1dGVzLCBzcGxpdH0gZnJvbSAnLi9vcHMvc3BsaXQnO1xuaW1wb3J0IHtwYXJzZVNxdWVlemVBdHRyaWJ1dGVzLCBzcXVlZXplLCBzcXVlZXplVjEzfSBmcm9tICcuL29wcy9zcXVlZXplJztcbmltcG9ydCB7c3VtfSBmcm9tICcuL29wcy9zdW0nO1xuaW1wb3J0IHt0aWxlfSBmcm9tICcuL29wcy90aWxlJztcbmltcG9ydCB7cGFyc2VUcmFuc3Bvc2VBdHRyaWJ1dGVzLCB0cmFuc3Bvc2V9IGZyb20gJy4vb3BzL3RyYW5zcG9zZSc7XG5pbXBvcnQgKiBhcyB1bmFyeU9wcyBmcm9tICcuL29wcy91bmFyeS1vcCc7XG5pbXBvcnQge3BhcnNlVW5zcXVlZXplQXR0cmlidXRlcywgdW5zcXVlZXplLCB1bnNxdWVlemVWMTN9IGZyb20gJy4vb3BzL3Vuc3F1ZWV6ZSc7XG5pbXBvcnQge3BhcnNlVXBzYW1wbGVBdHRyaWJ1dGVzVjcsIHBhcnNlVXBzYW1wbGVBdHRyaWJ1dGVzVjksIHVwc2FtcGxlfSBmcm9tICcuL29wcy91cHNhbXBsZSc7XG5cbmV4cG9ydCBjb25zdCBXRUJHTF9PUF9SRVNPTFZFX1JVTEVTOiByZWFkb25seSBPcFNldC5SZXNvbHZlUnVsZVtdID0gW1xuICBbJ0FicycsICcnLCAnNisnLCB1bmFyeU9wcy5hYnNdLFxuICBbJ0Fjb3MnLCAnJywgJzcrJywgdW5hcnlPcHMuYWNvc10sXG4gIFsnQWRkJywgJycsICc3KycsIGJpbmFyeU9wcy5hZGRdLFxuICBbJ0FuZCcsICcnLCAnNysnLCBiaW5hcnlPcHMuYW5kXSxcbiAgWydBc2luJywgJycsICc3KycsIHVuYXJ5T3BzLmFzaW5dLFxuICBbJ0F0YW4nLCAnJywgJzcrJywgdW5hcnlPcHMuYXRhbl0sXG4gIC8vIFRPRE86IHN1cHBvcnQgbmV3IGF0dHJpYnV0ZXMgZm9yIEF2ZXJhZ2VQb29sLTEwXG4gIFsnQXZlcmFnZVBvb2wnLCAnJywgJzcrJywgYXZlcmFnZVBvb2wsIHBhcnNlQXZlcmFnZVBvb2xBdHRyaWJ1dGVzXSxcbiAgWydCYXRjaE5vcm1hbGl6YXRpb24nLCAnJywgJzcrJywgYmF0Y2hOb3JtYWxpemF0aW9uLCBwYXJzZUJhdGNoTm9ybWFsaXphdGlvbkF0dHJpYnV0ZXNdLFxuICBbJ0Nhc3QnLCAnJywgJzYrJywgY2FzdCwgcGFyc2VDYXN0QXR0cmlidXRlc10sXG4gIFsnQ2VpbCcsICcnLCAnNisnLCB1bmFyeU9wcy5jZWlsXSxcbiAgWydDbGlwJywgJycsICc2LTEwJywgdW5hcnlPcHMuY2xpcCwgdW5hcnlPcHMucGFyc2VDbGlwQXR0cmlidXRlc10sXG4gIFsnQ2xpcCcsICcnLCAnMTErJywgdW5hcnlPcHMuY2xpcFYxMV0sXG4gIFsnQ29uY2F0JywgJycsICc0KycsIGNvbmNhdCwgcGFyc2VDb25jYXRBdHRyaWJ1dGVzXSxcbiAgWydDb252JywgJycsICcxKycsIGNvbnYsIHBhcnNlQ29udkF0dHJpYnV0ZXNdLFxuICBbJ0NvbnZUcmFuc3Bvc2UnLCAnJywgJzErJywgY29udlRyYW5zcG9zZSwgcGFyc2VDb252VHJhbnNwb3NlQXR0cmlidXRlc10sXG4gIFsnQ29zJywgJycsICc3KycsIHVuYXJ5T3BzLmNvc10sXG4gIFsnRGl2JywgJycsICc3KycsIGJpbmFyeU9wcy5kaXZdLFxuICBbJ0Ryb3BvdXQnLCAnJywgJzcrJywgdW5hcnlPcHMuaWRlbnRpdHldLFxuICBbJ0RlcHRoVG9TcGFjZScsICcnLCAnMSsnLCBkZXB0aFRvU3BhY2UsIHBhcnNlRGVwdGhUb1NwYWNlQXR0cmlidXRlc10sXG4gIFsnRXF1YWwnLCAnJywgJzcrJywgYmluYXJ5T3BzLmVxdWFsXSxcbiAgWydFbHUnLCAnJywgJzYrJywgdW5hcnlPcHMuZWx1LCB1bmFyeU9wcy5wYXJzZUVsdUF0dHJpYnV0ZXNdLFxuICBbJ0V4cCcsICcnLCAnNisnLCB1bmFyeU9wcy5leHBdLFxuICBbJ0ZsYXR0ZW4nLCAnJywgJzErJywgZmxhdHRlbiwgcGFyc2VGbGF0dGVuQXR0cmlidXRlc10sXG4gIFsnRmxvb3InLCAnJywgJzYrJywgdW5hcnlPcHMuZmxvb3JdLFxuICBbJ0Z1c2VkQ29udicsICdjb20ubWljcm9zb2Z0JywgJzErJywgY29udiwgcGFyc2VDb252QXR0cmlidXRlc10sXG4gIFsnR2F0aGVyJywgJycsICcxKycsIGdhdGhlciwgcGFyc2VHYXRoZXJBdHRyaWJ1dGVzXSxcbiAgWydHZW1tJywgJycsICc3LTEwJywgZ2VtbSwgcGFyc2VHZW1tQXR0cmlidXRlc1Y3XSxcbiAgWydHZW1tJywgJycsICcxMSsnLCBnZW1tLCBwYXJzZUdlbW1BdHRyaWJ1dGVzVjExXSxcbiAgWydHbG9iYWxBdmVyYWdlUG9vbCcsICcnLCAnMSsnLCBnbG9iYWxBdmVyYWdlUG9vbCwgcGFyc2VHbG9iYWxBdmVyYWdlUG9vbEF0dHJpYnV0ZXNdLFxuICBbJ0dsb2JhbE1heFBvb2wnLCAnJywgJzErJywgZ2xvYmFsTWF4UG9vbF0sXG4gIFsnR3JlYXRlcicsICcnLCAnNysnLCBiaW5hcnlPcHMuZ3JlYXRlcl0sXG4gIFsnSWRlbnRpdHknLCAnJywgJzErJywgdW5hcnlPcHMuaWRlbnRpdHldLFxuICBbJ0ltYWdlU2NhbGVyJywgJycsICcxKycsIGltYWdlU2NhbGVyLCBwYXJzZUltYWdlU2NhbGVyQXR0cmlidXRlc10sXG4gIFsnSW5zdGFuY2VOb3JtYWxpemF0aW9uJywgJycsICc2KycsIGluc3RhbmNlTm9ybWFsaXphdGlvbiwgcGFyc2VJbnN0YW5jZU5vcm1hbGl6YXRpb25BdHRyaWJ1dGVzXSxcbiAgWydMZWFreVJlbHUnLCAnJywgJzYrJywgdW5hcnlPcHMubGVha3lSZWx1LCB1bmFyeU9wcy5wYXJzZUxlYWt5UmVsdUF0dHJpYnV0ZXNdLFxuICBbJ0xlc3MnLCAnJywgJzcrJywgYmluYXJ5T3BzLmxlc3NdLFxuICBbJ0xSTicsICcnLCAnMSsnLCBscm4sIHBhcnNlTHJuQXR0cmlidXRlc10sXG4gIFsnTG9nJywgJycsICc2KycsIHVuYXJ5T3BzLmxvZ10sXG4gIFsnTWF0TXVsJywgJycsICcxKycsIG1hdE11bCwgcGFyc2VNYXRNdWxBdHRyaWJ1dGVzXSxcbiAgLy8gVE9ETzogc3VwcG9ydCBuZXcgYXR0cmlidXRlcyBmb3IgTWF4UG9vbC04IGFuZCBNYXhQb29sLTEwXG4gIFsnTWF4UG9vbCcsICcnLCAnMSsnLCBtYXhQb29sLCBwYXJzZU1heFBvb2xBdHRyaWJ1dGVzXSxcbiAgWydNdWwnLCAnJywgJzcrJywgYmluYXJ5T3BzLm11bF0sXG4gIFsnTmVnJywgJycsICc2KycsIHVuYXJ5T3BzLm5lZ10sXG4gIFsnTm90JywgJycsICcxKycsIHVuYXJ5T3BzLm5vdF0sXG4gIFsnT3InLCAnJywgJzcrJywgYmluYXJ5T3BzLm9yXSxcbiAgWydQYWQnLCAnJywgJzItMTAnLCBwYWRWMiwgcGFyc2VQYWRBdHRyaWJ1dGVzVjJdLFxuICBbJ1BhZCcsICcnLCAnMTErJywgcGFkVjExLCBwYXJzZVBhZEF0dHJpYnV0ZXNWMTFdLFxuICBbJ1BvdycsICcnLCAnNysnLCBiaW5hcnlPcHMucG93XSxcbiAgWydQUmVsdScsICcnLCAnNysnLCBiaW5hcnlPcHMucFJlbHVdLFxuICBbJ1JlZHVjZUxvZ1N1bScsICcnLCAnMSsnLCByZWR1Y2VMb2dTdW0sIHBhcnNlUmVkdWNlQXR0cmlidXRlc10sXG4gIFsnUmVkdWNlTWF4JywgJycsICcxKycsIHJlZHVjZU1heCwgcGFyc2VSZWR1Y2VBdHRyaWJ1dGVzXSxcbiAgWydSZWR1Y2VNZWFuJywgJycsICcxKycsIHJlZHVjZU1lYW4sIHBhcnNlUmVkdWNlQXR0cmlidXRlc10sXG4gIFsnUmVkdWNlTWluJywgJycsICcxKycsIHJlZHVjZU1pbiwgcGFyc2VSZWR1Y2VBdHRyaWJ1dGVzXSxcbiAgWydSZWR1Y2VQcm9kJywgJycsICcxKycsIHJlZHVjZVByb2QsIHBhcnNlUmVkdWNlQXR0cmlidXRlc10sXG4gIFsnUmVkdWNlU3VtJywgJycsICcxLTEyJywgcmVkdWNlU3VtLCBwYXJzZVJlZHVjZUF0dHJpYnV0ZXNdLFxuICBbJ1JlZHVjZVN1bVNxdWFyZScsICcnLCAnMSsnLCByZWR1Y2VMb2dTdW1TcXVhcmUsIHBhcnNlUmVkdWNlQXR0cmlidXRlc10sXG4gIFsnUmVsdScsICcnLCAnNisnLCB1bmFyeU9wcy5yZWx1XSxcbiAgWydSZXNoYXBlJywgJycsICc1KycsIHJlc2hhcGVdLFxuICBbJ1Jlc2l6ZScsICcnLCAnMTAnLCByZXNpemUsIHBhcnNlUmVzaXplQXR0cmlidXRlc1YxMF0sXG4gIFsnUmVzaXplJywgJycsICcxMSsnLCByZXNpemUsIHBhcnNlUmVzaXplQXR0cmlidXRlc1YxMV0sXG4gIFsnU2hhcGUnLCAnJywgJzErJywgc2hhcGVdLFxuICBbJ1NpZ21vaWQnLCAnJywgJzYrJywgdW5hcnlPcHMuc2lnbW9pZF0sXG4gIFsnU2luJywgJycsICc3KycsIHVuYXJ5T3BzLnNpbl0sXG4gIFsnU2xpY2UnLCAnJywgJzEwKycsIHNsaWNlVjEwXSwgIC8vIFRPRE86IHN1cHBvcnQgJ3N0ZXBzJyBmb3IgU2xpY2UtMTBcbiAgWydTbGljZScsICcnLCAnMS05Jywgc2xpY2UsIHBhcnNlU2xpY2VBdHRyaWJ1dGVzXSxcbiAgLy8gVGhlIFwic2VtYW50aWNcIiBtZWFuaW5nIG9mIGF4aXMgaGFzIGNoYW5nZWQgaW4gb3BzZXQtMTMuXG4gIFsnU29mdG1heCcsICcnLCAnMS0xMicsIHNvZnRtYXgsIHBhcnNlU29mdG1heEF0dHJpYnV0ZXNdLFxuICBbJ1NvZnRtYXgnLCAnJywgJzEzKycsIHNvZnRtYXhWMTMsIHBhcnNlU29mdG1heEF0dHJpYnV0ZXNWMTNdLFxuICAvLyAnU3BsaXQnIG9wZXJhdG9yIGhhcyBhbiBvcHRpb25hbCBhdHRyaWJ1dGUgJ3NwbGl0J1xuICAvLyB0aGlzIGF0dHJpYnV0ZSBkZXRlcm1pbmVzIGhvdyB0aGUgc3BlY2lmaWVkIGF4aXMgb2YgaW5wdXQgZGF0YSBpcyBzcGxpdC5cbiAgLy8gV2hlbiB0aGUgYXR0cmlidXRlIGlzIG1pc3NpbmcsIHdlIG5lZWQgdGhlIGNvdW50IG9mIG51bWJlciBvZiBvdXRwdXRzXG4gIC8vIHNvIHRoYXQgd2UgY2FuIGRldGVybWluZSB0aGUgJ3NwbGl0JyBhdHRyaWJ1dGUgZnJvbSB0aGUgcnVudGltZSBpbnB1dCB0byB0aGUgT3BlcmF0b3JcbiAgWydTcGxpdCcsICcnLCAnMi0xMicsIHNwbGl0LCBwYXJzZVNwbGl0QXR0cmlidXRlc10sXG4gIFsnU3FydCcsICcnLCAnNisnLCB1bmFyeU9wcy5zcXJ0XSxcbiAgWydTcXVlZXplJywgJycsICcxLTEyJywgc3F1ZWV6ZSwgcGFyc2VTcXVlZXplQXR0cmlidXRlc10sXG4gIFsnU3F1ZWV6ZScsICcnLCAnMTMrJywgc3F1ZWV6ZVYxM10sXG4gIFsnU3ViJywgJycsICc3KycsIGJpbmFyeU9wcy5zdWJdLFxuICBbJ1N1bScsICcnLCAnNisnLCBzdW1dLFxuICBbJ1RhbicsICcnLCAnNysnLCB1bmFyeU9wcy50YW5dLFxuICBbJ1RhbmgnLCAnJywgJzYrJywgdW5hcnlPcHMudGFuaF0sXG4gIFsnVGlsZScsICcnLCAnNisnLCB0aWxlXSxcbiAgWydUcmFuc3Bvc2UnLCAnJywgJzErJywgdHJhbnNwb3NlLCBwYXJzZVRyYW5zcG9zZUF0dHJpYnV0ZXNdLFxuICBbJ1Vwc2FtcGxlJywgJycsICc3LTgnLCB1cHNhbXBsZSwgcGFyc2VVcHNhbXBsZUF0dHJpYnV0ZXNWN10sXG4gIFsnVXBzYW1wbGUnLCAnJywgJzknLCB1cHNhbXBsZSwgcGFyc2VVcHNhbXBsZUF0dHJpYnV0ZXNWOV0sXG4gIFsnVW5zcXVlZXplJywgJycsICcxLTEyJywgdW5zcXVlZXplLCBwYXJzZVVuc3F1ZWV6ZUF0dHJpYnV0ZXNdLFxuICBbJ1Vuc3F1ZWV6ZScsICcnLCAnMTMrJywgdW5zcXVlZXplVjEzXSxcbiAgWydYb3InLCAnJywgJzcrJywgYmluYXJ5T3BzLnhvcl0sXG5dO1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7QXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXl9IGZyb20gJy4uLy4uLy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQge0dyYXBofSBmcm9tICcuLi8uLi8uLi9ncmFwaCc7XG5pbXBvcnQge09wZXJhdG9ySW1wbGVtZW50YXRpb24sIE9wZXJhdG9ySW5pdGlhbGl6YXRpb259IGZyb20gJy4uLy4uLy4uL29wZXJhdG9ycyc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi4vZ2xzbC1zb3VyY2UnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQmF0Y2hOb3JtYWxpemF0aW9uQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIGVwc2lsb246IG51bWJlcjtcbiAgbW9tZW50dW06IG51bWJlcjtcbiAgc3BhdGlhbDogbnVtYmVyO1xufVxuXG5jb25zdCBiYXRjaE5vcm1hbGl6YXRpb25Qcm9ncmFtTWV0YWRhdGEgPSB7XG4gIG5hbWU6ICdCYXRjaE5vcm1hbGl6YXRpb24nLFxuICBpbnB1dE5hbWVzOiBbJ0EnLCAnU2NhbGUnLCAnQicsICdNZWFuJywgJ1ZhcmlhbmNlJ10sXG4gIGlucHV0VHlwZXM6XG4gICAgICBbVGV4dHVyZVR5cGUudW5wYWNrZWQsIFRleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWQsIFRleHR1cmVUeXBlLnVucGFja2VkXVxufTtcblxuZXhwb3J0IGNvbnN0IGJhdGNoTm9ybWFsaXphdGlvbjogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxCYXRjaE5vcm1hbGl6YXRpb25BdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogQmF0Y2hOb3JtYWxpemF0aW9uQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cyk7XG4gICAgICBjb25zdCBvdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgICAgICB7XG4gICAgICAgICAgICAuLi5iYXRjaE5vcm1hbGl6YXRpb25Qcm9ncmFtTWV0YWRhdGEsXG4gICAgICAgICAgICBjYWNoZUhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXksXG4gICAgICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZUJhdGNoTm9ybWFsaXphdGlvblByb2dyYW1JbmZvKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYXR0cmlidXRlcylcbiAgICAgICAgICB9LFxuICAgICAgICAgIGlucHV0cyk7XG4gICAgICByZXR1cm4gW291dHB1dF07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlQmF0Y2hOb3JtYWxpemF0aW9uQXR0cmlidXRlczogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxCYXRjaE5vcm1hbGl6YXRpb25BdHRyaWJ1dGVzPiA9XG4gICAgKG5vZGU6IEdyYXBoLk5vZGUpOiBCYXRjaE5vcm1hbGl6YXRpb25BdHRyaWJ1dGVzID0+IHtcbiAgICAgIGNvbnN0IGVwc2lsb24gPSBub2RlLmF0dHJpYnV0ZXMuZ2V0RmxvYXQoJ2Vwc2lsb24nLCAxZS01KTtcbiAgICAgIGNvbnN0IG1vbWVudHVtID0gbm9kZS5hdHRyaWJ1dGVzLmdldEZsb2F0KCdtb21lbnR1bScsIDAuOSk7XG4gICAgICBjb25zdCBzcGF0aWFsID0gbm9kZS5hdHRyaWJ1dGVzLmdldEludCgnc3BhdGlhbCcsIDEpO1xuICAgICAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7ZXBzaWxvbiwgbW9tZW50dW0sIHNwYXRpYWx9KTtcbiAgICB9O1xuXG5jb25zdCBjcmVhdGVCYXRjaE5vcm1hbGl6YXRpb25Qcm9ncmFtSW5mbyA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogQmF0Y2hOb3JtYWxpemF0aW9uQXR0cmlidXRlcyk6XG4gICAgICAgIFByb2dyYW1JbmZvID0+IHtcbiAgICAgICAgICBjb25zdCBnbHNsID0gZ2V0R2xzbChpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQudmVyc2lvbik7XG4gICAgICAgICAgY29uc3QgcmFuayA9IGlucHV0c1swXS5kaW1zLmxlbmd0aDtcbiAgICAgICAgICBjb25zdCBbc2NhbGVXaWR0aCwgc2NhbGVIZWlnaHRdID1cbiAgICAgICAgICAgICAgaW5mZXJlbmNlSGFuZGxlci5jYWxjdWxhdGVUZXh0dXJlV2lkdGhBbmRIZWlnaHQoaW5wdXRzWzFdLmRpbXMsIFRleHR1cmVUeXBlLnVucGFja2VkKTtcbiAgICAgICAgICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gIGZsb2F0IHByb2Nlc3MoaW50WyR7cmFua31dIGluZGljZXMpIHtcbiAgICB2ZWMyIHBvc2l0aW9uID0gb2Zmc2V0VG9Db29yZHMoaW5kaWNlc1sxXSwgJHtzY2FsZVdpZHRofSwgJHtzY2FsZUhlaWdodH0pO1xuICAgIGZsb2F0IHNjYWxlID0gZ2V0Q29sb3JBc0Zsb2F0KCR7Z2xzbC50ZXh0dXJlMkR9KFNjYWxlLCBwb3NpdGlvbikpO1xuICAgIGZsb2F0IG1lYW4gPSBnZXRDb2xvckFzRmxvYXQoJHtnbHNsLnRleHR1cmUyRH0oTWVhbiwgcG9zaXRpb24pKTtcbiAgICBmbG9hdCB2YXJpYW5jZSA9IGdldENvbG9yQXNGbG9hdCgke2dsc2wudGV4dHVyZTJEfShWYXJpYW5jZSwgcG9zaXRpb24pKTtcbiAgICBmbG9hdCBiID0gZ2V0Q29sb3JBc0Zsb2F0KCR7Z2xzbC50ZXh0dXJlMkR9KEIsIHBvc2l0aW9uKSk7XG5cbiAgICByZXR1cm4gc2NhbGUgKiAoIChfQShpbmRpY2VzKSAtIG1lYW4pIC8gc3FydCh2YXJpYW5jZSArIGZsb2F0KCR7YXR0cmlidXRlcy5lcHNpbG9ufSkpICkgKyBiO1xuICB9YDtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4uYmF0Y2hOb3JtYWxpemF0aW9uUHJvZ3JhbU1ldGFkYXRhLFxuICAgICAgICAgICAgb3V0cHV0OiB7ZGltczogaW5wdXRzWzBdLmRpbXMsIHR5cGU6IGlucHV0c1swXS50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUudW5wYWNrZWR9LFxuICAgICAgICAgICAgc2hhZGVyU291cmNlXG4gICAgICAgICAgfTtcbiAgICAgICAgfTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiBUZW5zb3JbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSA1KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdCYXRjaE5vcm1hbGl6YXRpb24gcmVxdWlyZXMgNSBpbnB1dHMuJyk7XG4gIH1cblxuICBjb25zdCBYID0gaW5wdXRzWzBdO1xuICBjb25zdCBzY2FsZSA9IGlucHV0c1sxXTtcbiAgY29uc3QgQiA9IGlucHV0c1syXTtcbiAgY29uc3QgbWVhbiA9IGlucHV0c1szXTtcbiAgY29uc3QgdmFyXyA9IGlucHV0c1s0XTtcblxuICAvLyBpbnB1dCBzaG91bGQgYXRsZWFzdCBoYXZlIHRocmVlIGRpbWVuc2lvbnMgLSBOLEMsZGltMSwuLi4sZGltblxuICAvLyBvdGhlciBpbnB1dHMgY2FuIGhhdmUgb25seSBvbmUgZGltZW5zaW9uc1xuICBpZiAoWC5kaW1zLmxlbmd0aCA8IDMgfHwgc2NhbGUuZGltcy5sZW5ndGggIT09IDEgfHwgQi5kaW1zLmxlbmd0aCAhPT0gMSB8fCBtZWFuLmRpbXMubGVuZ3RoICE9PSAxIHx8XG4gICAgICB2YXJfLmRpbXMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGlucHV0IHNoYXBlLicpO1xuICB9XG4gIGlmIChzY2FsZS5kaW1zWzBdICE9PSBYLmRpbXNbMV0gfHwgQi5kaW1zWzBdICE9PSBYLmRpbXNbMV0gfHwgbWVhbi5kaW1zWzBdICE9PSBYLmRpbXNbMV0gfHxcbiAgICAgIHZhcl8uZGltc1swXSAhPT0gWC5kaW1zWzFdKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGlucHV0IHNoYXBlLicpO1xuICB9XG4gIGlmICgoWC50eXBlICE9PSAnZmxvYXQzMicgJiYgWC50eXBlICE9PSAnZmxvYXQ2NCcpIHx8IChzY2FsZS50eXBlICE9PSAnZmxvYXQzMicgJiYgc2NhbGUudHlwZSAhPT0gJ2Zsb2F0NjQnKSB8fFxuICAgICAgKEIudHlwZSAhPT0gJ2Zsb2F0MzInICYmIEIudHlwZSAhPT0gJ2Zsb2F0NjQnKSB8fCAobWVhbi50eXBlICE9PSAnZmxvYXQzMicgJiYgbWVhbi50eXBlICE9PSAnZmxvYXQ2NCcpIHx8XG4gICAgICAodmFyXy50eXBlICE9PSAnZmxvYXQzMicgJiYgdmFyXy50eXBlICE9PSAnZmxvYXQ2NCcpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGlucHV0IHRlbnNvciB0eXBlcy4nKTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7QnJvYWRjYXN0VXRpbCwgU2hhcGVVdGlsfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7RnVuY3Rpb25UeXBlLCBHbHNsVmFsdWVGdW5jdGlvbn0gZnJvbSAnLi4vZ2xzbC1kZWZpbml0aW9ucyc7XG5pbXBvcnQge2dldEdsc2x9IGZyb20gJy4uL2dsc2wtc291cmNlJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBQcm9ncmFtSW5mb0xvYWRlciwgVGV4dHVyZVR5cGV9IGZyb20gJy4uL3R5cGVzJztcblxuZXhwb3J0IGZ1bmN0aW9uIGdsc2xBZGQoKTogR2xzbFZhbHVlRnVuY3Rpb24ge1xuICBjb25zdCBuYW1lID0gJ2FkZF8nO1xuICBjb25zdCBib2R5ID0gYFxuICBmbG9hdCAke25hbWV9KGZsb2F0IGEsIGZsb2F0IGIpIHtcbiAgICByZXR1cm4gYSArIGI7XG4gIH1cbiAgdmVjNCAke25hbWV9KHZlYzQgdjEsIHZlYzQgdjIpIHtcbiAgICByZXR1cm4gdjEgKyB2MjtcbiAgfVxuICBgO1xuICByZXR1cm4ge2JvZHksIG5hbWUsIHR5cGU6IEZ1bmN0aW9uVHlwZS5WYWx1ZUJhc2VkfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsRGl2KCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9ICdkaXZfJztcbiAgY29uc3QgYm9keSA9IGBcbiAgZmxvYXQgJHtuYW1lfShmbG9hdCBhLCBmbG9hdCBiKSB7XG4gICAgcmV0dXJuIGEgLyBiO1xuICB9XG4gIHZlYzQgJHtuYW1lfSh2ZWM0IHYxLCB2ZWM0IHYyKSB7XG4gICAgcmV0dXJuIHYxIC8gdjI7XG4gIH1cbiAgYDtcbiAgcmV0dXJuIHtib2R5LCBuYW1lLCB0eXBlOiBGdW5jdGlvblR5cGUuVmFsdWVCYXNlZH07XG59XG5leHBvcnQgZnVuY3Rpb24gZ2xzbE11bCgpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIGNvbnN0IG5hbWUgPSAnbXVsXyc7XG4gIGNvbnN0IGJvZHkgPSBgXG4gIGZsb2F0ICR7bmFtZX0oZmxvYXQgYSwgZmxvYXQgYikge1xuICAgIHJldHVybiBhICogYjtcbiAgfVxuICB2ZWM0ICR7bmFtZX0odmVjNCB2MSwgdmVjNCB2Mikge1xuICAgIHJldHVybiB2MSAqIHYyO1xuICB9XG4gIGA7XG4gIHJldHVybiB7Ym9keSwgbmFtZSwgdHlwZTogRnVuY3Rpb25UeXBlLlZhbHVlQmFzZWR9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdsc2xTdWIoKTogR2xzbFZhbHVlRnVuY3Rpb24ge1xuICBjb25zdCBuYW1lID0gJ3N1Yl8nO1xuICBjb25zdCBib2R5ID0gYFxuICBmbG9hdCAke25hbWV9KGZsb2F0IGEsIGZsb2F0IGIpIHtcbiAgICByZXR1cm4gYSAtIGI7XG4gIH1cbiAgdmVjNCAke25hbWV9KHZlYzQgdjEsIHZlYzQgdjIpIHtcbiAgICByZXR1cm4gdjEgLSB2MjtcbiAgfVxuICBgO1xuICByZXR1cm4ge2JvZHksIG5hbWUsIHR5cGU6IEZ1bmN0aW9uVHlwZS5WYWx1ZUJhc2VkfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsRXF1YWwoKTogR2xzbFZhbHVlRnVuY3Rpb24ge1xuICBjb25zdCBuYW1lID0gJ2VxdWFsXyc7XG4gIGNvbnN0IGJvZHkgPSBgXG4gIGZsb2F0ICR7bmFtZX0oZmxvYXQgYSwgZmxvYXQgYikge1xuICAgIHJldHVybiBmbG9hdChhID09IGIpO1xuICB9XG4gIHZlYzQgJHtuYW1lfSh2ZWM0IHYxLCB2ZWM0IHYyKSB7XG4gICAgcmV0dXJuIHZlYzQoZXF1YWwodjEsIHYyKSk7XG4gIH1cbiAgYDtcbiAgcmV0dXJuIHtib2R5LCBuYW1lLCB0eXBlOiBGdW5jdGlvblR5cGUuVmFsdWVCYXNlZH07XG59XG5leHBvcnQgZnVuY3Rpb24gZ2xzbEdyZWF0ZXIoKTogR2xzbFZhbHVlRnVuY3Rpb24ge1xuICBjb25zdCBuYW1lID0gJ2dyZWF0ZXJfJztcbiAgY29uc3QgYm9keSA9IGBcbiAgZmxvYXQgJHtuYW1lfShmbG9hdCBhLCBmbG9hdCBiKSB7XG4gICAgcmV0dXJuIGZsb2F0KGEgPiBiKTtcbiAgfVxuICB2ZWM0ICR7bmFtZX0odmVjNCB2MSwgdmVjNCB2Mikge1xuICAgIHJldHVybiB2ZWM0KCB2MS5yID4gdjIuciAsXG4gICAgICB2MS5nID4gdjIuZyxcbiAgICAgIHYxLmIgPiB2Mi5iLFxuICAgICAgdjEuYSA+IHYyLmEgKTtcbiAgfVxuICBgO1xuICByZXR1cm4ge2JvZHksIG5hbWUsIHR5cGU6IEZ1bmN0aW9uVHlwZS5WYWx1ZUJhc2VkfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsTGVzcygpOiBHbHNsVmFsdWVGdW5jdGlvbiB7XG4gIGNvbnN0IG5hbWUgPSAnbGVzc18nO1xuICBjb25zdCBib2R5ID0gYFxuICBmbG9hdCAke25hbWV9KGZsb2F0IGEsIGZsb2F0IGIpIHtcbiAgICByZXR1cm4gZmxvYXQoYSA8IGIpO1xuICB9XG4gIHZlYzQgJHtuYW1lfSh2ZWM0IHYxLCB2ZWM0IHYyKSB7XG4gICAgcmV0dXJuIHZlYzQoIHYxLnIgPCB2Mi5yICxcbiAgICAgICAgICAgICAgICB2MS5nIDwgdjIuZyxcbiAgICAgICAgICAgICAgICB2MS5iIDwgdjIuYixcbiAgICAgICAgICAgICAgICB2MS5hIDwgdjIuYSApO1xuICB9XG4gIGA7XG4gIHJldHVybiB7Ym9keSwgbmFtZSwgdHlwZTogRnVuY3Rpb25UeXBlLlZhbHVlQmFzZWR9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdsc2xBbmQoKTogR2xzbFZhbHVlRnVuY3Rpb24ge1xuICBjb25zdCBuYW1lID0gJ2FuZF8nO1xuICBjb25zdCBib2R5ID0gYFxuICBmbG9hdCAke25hbWV9KGZsb2F0IGEsIGZsb2F0IGIpIHtcbiAgICByZXR1cm4gZmxvYXQoIGJvb2woYSkgJiYgYm9vbChiKSApO1xuICB9XG4gIHZlYzQgJHtuYW1lfSh2ZWM0IHYxLCB2ZWM0IHYyKSB7XG4gICAgYnZlYzQgYjEgPSBidmVjNCh2MSk7XG4gICAgYnZlYzQgYjIgPSBidmVjNCh2Mik7XG4gICAgcmV0dXJuIHZlYzQoIGIxLnIgJiYgYjIuciAsXG4gICAgICAgICAgICAgICAgYjEuZyAmJiBiMi5nLFxuICAgICAgICAgICAgICAgIGIxLmIgJiYgYjIuYixcbiAgICAgICAgICAgICAgICBiMS5hICYmIGIyLmEgKTtcbiAgfVxuICBgO1xuICByZXR1cm4ge2JvZHksIG5hbWUsIHR5cGU6IEZ1bmN0aW9uVHlwZS5WYWx1ZUJhc2VkfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsT3IoKTogR2xzbFZhbHVlRnVuY3Rpb24ge1xuICBjb25zdCBuYW1lID0gJ29yXyc7XG4gIGNvbnN0IGJvZHkgPSBgXG4gIGZsb2F0ICR7bmFtZX0oZmxvYXQgYSwgZmxvYXQgYikge1xuICAgIHJldHVybiBmbG9hdCggYm9vbChhKSB8fCBib29sKGIpICk7XG4gIH1cbiAgdmVjNCAke25hbWV9KHZlYzQgdjEsIHZlYzQgdjIpIHtcbiAgICBidmVjNCBiMSA9IGJ2ZWM0KHYxKTtcbiAgICBidmVjNCBiMiA9IGJ2ZWM0KHYyKTtcbiAgICByZXR1cm4gdmVjNCggYjEuciB8fCBiMi5yICxcbiAgICAgICAgICAgICAgICBiMS5nIHx8IGIyLmcsXG4gICAgICAgICAgICAgICAgYjEuYiB8fCBiMi5iLFxuICAgICAgICAgICAgICAgIGIxLmEgfHwgYjIuYSApO1xuICB9XG4gIGA7XG4gIHJldHVybiB7Ym9keSwgbmFtZSwgdHlwZTogRnVuY3Rpb25UeXBlLlZhbHVlQmFzZWR9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGdsc2xYb3IoKTogR2xzbFZhbHVlRnVuY3Rpb24ge1xuICBjb25zdCBuYW1lID0gJ3hvcl8nO1xuICBjb25zdCBib2R5ID0gYFxuICBmbG9hdCAke25hbWV9KGZsb2F0IGEsIGZsb2F0IGIpIHtcbiAgICByZXR1cm4gZmxvYXQoIGJvb2woYSkgXl4gYm9vbChiKSApO1xuICB9XG4gIHZlYzQgJHtuYW1lfSh2ZWM0IHYxLCB2ZWM0IHYyKSB7XG4gICAgYnZlYzQgYjEgPSBidmVjNCh2MSk7XG4gICAgYnZlYzQgYjIgPSBidmVjNCh2Mik7XG4gICAgcmV0dXJuIHZlYzQoIGIxLnIgXl4gYjIuciAsXG4gICAgICAgICAgICAgICAgYjEuZyBeXiBiMi5nLFxuICAgICAgICAgICAgICAgIGIxLmIgXl4gYjIuYixcbiAgICAgICAgICAgICAgICBiMS5hIF5eIGIyLmEgKTtcbiAgfVxuICBgO1xuICByZXR1cm4ge2JvZHksIG5hbWUsIHR5cGU6IEZ1bmN0aW9uVHlwZS5WYWx1ZUJhc2VkfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsUG93KCk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgcmV0dXJuIGdsc2xCdWlsdGluQmluYXJ5KCdwb3cnKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBnbHNsUFJlbHUoKTogR2xzbFZhbHVlRnVuY3Rpb24ge1xuICBjb25zdCBuYW1lID0gJ3ByZWx1Xyc7XG4gIGNvbnN0IGJvZHkgPSBgXG4gIGZsb2F0ICR7bmFtZX0oZmxvYXQgYSwgZmxvYXQgYikge1xuICAgIHJldHVybiBhIDwgMC4wID8gYSAqIGI6IGE7XG4gIH1cbiAgdmVjNCAke25hbWV9KHZlYzQgdjEsIHZlYzQgdjIpIHtcbiAgICByZXR1cm4gdmVjNChcbiAgICAgIHYxLnIgPCAwLjAgPyB2MS5yICogdjIucjogdjEucixcbiAgICAgIHYxLmcgPCAwLjAgPyB2MS5nICogdjIuZzogdjEuZyxcbiAgICAgIHYxLmIgPCAwLjAgPyB2MS5iICogdjIuYjogdjEuYixcbiAgICAgIHYxLmEgPCAwLjAgPyB2MS5hICogdjIuYTogdjEuYVxuICAgICAgKTtcbiAgfVxuICBgO1xuICByZXR1cm4ge2JvZHksIG5hbWUsIHR5cGU6IEZ1bmN0aW9uVHlwZS5WYWx1ZUJhc2VkfTtcbn1cblxuZnVuY3Rpb24gZ2xzbEJ1aWx0aW5CaW5hcnkoZm5hbWU6IHN0cmluZyk6IEdsc2xWYWx1ZUZ1bmN0aW9uIHtcbiAgY29uc3QgbmFtZSA9IGAke2ZuYW1lfV9gO1xuICBjb25zdCBib2R5ID0gYFxuICBmbG9hdCAke25hbWV9KGZsb2F0IGEsIGZsb2F0IGIpIHtcbiAgICByZXR1cm4gJHtmbmFtZX0oYSwgYik7XG4gIH1cbiAgdmVjNCAke25hbWV9KHZlYzQgdjEsIHZlYzQgdjIpIHtcbiAgICByZXR1cm4gJHtmbmFtZX0odjEsIHYyKTtcbiAgfVxuICBgO1xuICByZXR1cm4ge2JvZHksIG5hbWUsIHR5cGU6IEZ1bmN0aW9uVHlwZS5WYWx1ZUJhc2VkfTtcbn1cblxuY29uc3QgY3JlYXRlQmluYXJ5UHJvZ3JhbUluZm9Mb2FkZXIgPVxuICAgIChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGdsc2xGdW5jOiBHbHNsVmFsdWVGdW5jdGlvbixcbiAgICAgb3V0cHV0VGVuc29yVHlwZTogVGVuc29yLkRhdGFUeXBlID0gaW5wdXRzWzBdLnR5cGUsIGNhY2hlS2V5Pzogc3RyaW5nKTogUHJvZ3JhbUluZm9Mb2FkZXIgPT4ge1xuICAgICAgY29uc3QgdGV4dHVyZVR5cGUgPSBoYW5kbGVyLnNlc3Npb24ucGFjayA/IFRleHR1cmVUeXBlLnBhY2tlZCA6IFRleHR1cmVUeXBlLnVucGFja2VkO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbmFtZTogZ2xzbEZ1bmMubmFtZSxcbiAgICAgICAgaW5wdXROYW1lczogWydBJywgJ0InXSxcbiAgICAgICAgaW5wdXRUeXBlczogW3RleHR1cmVUeXBlLCB0ZXh0dXJlVHlwZV0sXG4gICAgICAgIGNhY2hlSGludDogY2FjaGVLZXksXG4gICAgICAgIGdldDogKCkgPT4gY3JlYXRlQmluYXJ5UHJvZ3JhbUluZm8oaGFuZGxlciwgaW5wdXRzLCBnbHNsRnVuYywgb3V0cHV0VGVuc29yVHlwZSlcbiAgICAgIH07XG4gICAgfTtcblxuY29uc3QgY3JlYXRlQmluYXJ5UHJvZ3JhbUluZm8gPVxuICAgIChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGdsc2xGdW5jOiBHbHNsVmFsdWVGdW5jdGlvbixcbiAgICAgb3V0cHV0VGVuc29yVHlwZTogVGVuc29yLkRhdGFUeXBlID0gaW5wdXRzWzBdLnR5cGUpOiBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICBjb25zdCB0ZXh0dXJlVHlwZSA9IGhhbmRsZXIuc2Vzc2lvbi5wYWNrID8gVGV4dHVyZVR5cGUucGFja2VkIDogVGV4dHVyZVR5cGUudW5wYWNrZWQ7XG4gICAgICBjb25zdCBpc0Jyb2FkY2FzdCA9ICFTaGFwZVV0aWwuYXJlRXF1YWwoaW5wdXRzWzBdLmRpbXMsIGlucHV0c1sxXS5kaW1zKTtcbiAgICAgIGxldCBvdXRwdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuXG4gICAgICBjb25zdCB1c2VQYWNrZWRUZXh0dXJlID0gaGFuZGxlci5zZXNzaW9uLnBhY2s7XG5cbiAgICAgIGlmIChpc0Jyb2FkY2FzdCkge1xuICAgICAgICBjb25zdCBjYWxjdWxhdGVkU2hhcGUgPSBCcm9hZGNhc3RVdGlsLmNhbGNTaGFwZShpbnB1dHNbMF0uZGltcywgaW5wdXRzWzFdLmRpbXMsIGZhbHNlKTtcbiAgICAgICAgaWYgKCFjYWxjdWxhdGVkU2hhcGUpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcJ3QgcGVyZm9ybSBiaW5hcnkgb3Agb24gdGhlIGdpdmVuIHRlbnNvcnMnKTtcbiAgICAgICAgfVxuICAgICAgICBvdXRwdXRTaGFwZSA9IGNhbGN1bGF0ZWRTaGFwZTtcbiAgICAgICAgY29uc3Qgb3V0cHV0UmFuayA9IG91dHB1dFNoYXBlLmxlbmd0aDtcbiAgICAgICAgY29uc3QgYVJhbmsgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IDAgPyBpbnB1dHNbMF0uZGltcy5sZW5ndGggOiAxO1xuICAgICAgICBjb25zdCBiUmFuayA9IGlucHV0c1sxXS5kaW1zLmxlbmd0aCAhPT0gMCA/IGlucHV0c1sxXS5kaW1zLmxlbmd0aCA6IDE7XG4gICAgICAgIGNvbnN0IGFCY2FzdCA9IGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gMCA/ICdiY2FzdEluZGljZXNfQShpbmRpY2VzLCBhaW5kaWNlcyk7JyA6ICdhaW5kaWNlc1swXSA9IDA7JztcbiAgICAgICAgY29uc3QgYkJjYXN0ID0gaW5wdXRzWzFdLmRpbXMubGVuZ3RoICE9PSAwID8gJ2JjYXN0SW5kaWNlc19CKGluZGljZXMsIGJpbmRpY2VzKTsnIDogJ2JpbmRpY2VzWzBdID0gMDsnO1xuXG4gICAgICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKGhhbmRsZXIuc2Vzc2lvbi5iYWNrZW5kLmdsQ29udGV4dC52ZXJzaW9uKTtcbiAgICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gdXNlUGFja2VkVGV4dHVyZSA/IGBcbiAgICAgICR7Z2xzbEZ1bmMuYm9keX1cbiAgICAgIHZvaWQgbWFpbigpIHtcbiAgICAgICAgdmVjNCBhID0gZ2V0QUF0T3V0Q29vcmRzKCk7XG4gICAgICAgIHZlYzQgYiA9IGdldEJBdE91dENvb3JkcygpO1xuICAgICAgICB2ZWM0IHJlc3VsdCA9ICR7Z2xzbEZ1bmMubmFtZX0oYSwgYik7XG4gICAgICAgICR7Z2xzbC5vdXRwdXR9ID0gcmVzdWx0O1xuICAgICAgfWAgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYFxuICAgICAgJHtnbHNsRnVuYy5ib2R5fVxuICAgICAgZmxvYXQgcHJvY2VzcyhpbnQgaW5kaWNlc1ske291dHB1dFJhbmt9XSkge1xuICAgICAgICBpbnQgYWluZGljZXNbJHthUmFua31dO1xuICAgICAgICBpbnQgYmluZGljZXNbJHtiUmFua31dO1xuICAgICAgICAke2FCY2FzdH1cbiAgICAgICAgJHtiQmNhc3R9XG4gICAgICAgIHJldHVybiAke2dsc2xGdW5jLm5hbWV9KF9BKGFpbmRpY2VzKSwgX0IoYmluZGljZXMpKTtcbiAgICAgIH1gO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbmFtZTogZ2xzbEZ1bmMubmFtZSxcbiAgICAgICAgICBpbnB1dE5hbWVzOiBbJ0EnLCAnQiddLFxuICAgICAgICAgIGlucHV0VHlwZXM6IFt0ZXh0dXJlVHlwZSwgdGV4dHVyZVR5cGVdLFxuICAgICAgICAgIG91dHB1dDoge2RpbXM6IG91dHB1dFNoYXBlLCB0eXBlOiBvdXRwdXRUZW5zb3JUeXBlLCB0ZXh0dXJlVHlwZX0sXG4gICAgICAgICAgc2hhZGVyU291cmNlLFxuICAgICAgICAgIGhhc01haW46IHVzZVBhY2tlZFRleHR1cmVcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKGhhbmRsZXIuc2Vzc2lvbi5iYWNrZW5kLmdsQ29udGV4dC52ZXJzaW9uKTtcbiAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAke2dsc2xGdW5jLmJvZHl9XG4gICAgdm9pZCBtYWluKCkge1xuICAgICAgdmVjNCB2MSA9ICR7Z2xzbC50ZXh0dXJlMkR9KEEsIFRleENvb3Jkcyk7XG4gICAgICB2ZWM0IHYyID0gJHtnbHNsLnRleHR1cmUyRH0oQiwgVGV4Q29vcmRzKTtcbiAgICAgIHZlYzQgcmVzdWx0ID0gJHtnbHNsRnVuYy5uYW1lfSh2MSwgdjIpO1xuICAgICAgJHtnbHNsLm91dHB1dH0gPSByZXN1bHQ7XG4gICAgfVxuICAgIGA7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIG5hbWU6IGdsc2xGdW5jLm5hbWUsXG4gICAgICAgIGlucHV0TmFtZXM6IFsnQScsICdCJ10sXG4gICAgICAgIGlucHV0VHlwZXM6IFt0ZXh0dXJlVHlwZSwgdGV4dHVyZVR5cGVdLFxuICAgICAgICBvdXRwdXQ6IHtkaW1zOiBpbnB1dHNbMF0uZGltcywgdHlwZTogb3V0cHV0VGVuc29yVHlwZSwgdGV4dHVyZVR5cGV9LFxuICAgICAgICBzaGFkZXJTb3VyY2UsXG4gICAgICAgIGhhc01haW46IHRydWVcbiAgICAgIH07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IGFkZCA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOlxuICAgIFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihjcmVhdGVCaW5hcnlQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHMsIGdsc2xBZGQoKSksIGlucHV0cyldO1xuXG5leHBvcnQgY29uc3QgYW5kID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUJpbmFyeVByb2dyYW1JbmZvTG9hZGVyKGhhbmRsZXIsIGlucHV0cywgZ2xzbEFuZCgpLCAnYm9vbCcpLCBpbnB1dHMpXTtcblxuZXhwb3J0IGNvbnN0IGRpdiA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOlxuICAgIFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihjcmVhdGVCaW5hcnlQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHMsIGdsc2xEaXYoKSksIGlucHV0cyldO1xuXG5leHBvcnQgY29uc3QgZXF1YWwgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTpcbiAgICBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oY3JlYXRlQmluYXJ5UHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzLCBnbHNsRXF1YWwoKSwgJ2Jvb2wnKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCBncmVhdGVyID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUJpbmFyeVByb2dyYW1JbmZvTG9hZGVyKGhhbmRsZXIsIGlucHV0cywgZ2xzbEdyZWF0ZXIoKSwgJ2Jvb2wnKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCBsZXNzID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUJpbmFyeVByb2dyYW1JbmZvTG9hZGVyKGhhbmRsZXIsIGlucHV0cywgZ2xzbExlc3MoKSwgJ2Jvb2wnKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCBtdWwgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTpcbiAgICBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oY3JlYXRlQmluYXJ5UHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzLCBnbHNsTXVsKCkpLCBpbnB1dHMpXTtcblxuZXhwb3J0IGNvbnN0IG9yID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUJpbmFyeVByb2dyYW1JbmZvTG9hZGVyKGhhbmRsZXIsIGlucHV0cywgZ2xzbE9yKCksICdib29sJyksIGlucHV0cyldO1xuXG5leHBvcnQgY29uc3QgcG93ID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSk6XG4gICAgVGVuc29yW10gPT4gW2hhbmRsZXIucnVuKGNyZWF0ZUJpbmFyeVByb2dyYW1JbmZvTG9hZGVyKGhhbmRsZXIsIGlucHV0cywgZ2xzbFBvdygpKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCBwUmVsdSA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOlxuICAgIFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihjcmVhdGVCaW5hcnlQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHMsIGdsc2xQUmVsdSgpKSwgaW5wdXRzKV07XG5cbmV4cG9ydCBjb25zdCBzdWIgPSAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTpcbiAgICBUZW5zb3JbXSA9PiBbaGFuZGxlci5ydW4oY3JlYXRlQmluYXJ5UHJvZ3JhbUluZm9Mb2FkZXIoaGFuZGxlciwgaW5wdXRzLCBnbHNsU3ViKCkpLCBpbnB1dHMpXTtcblxuZXhwb3J0IGNvbnN0IHhvciA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10pOlxuICAgIFRlbnNvcltdID0+IFtoYW5kbGVyLnJ1bihjcmVhdGVCaW5hcnlQcm9ncmFtSW5mb0xvYWRlcihoYW5kbGVyLCBpbnB1dHMsIGdsc2xYb3IoKSwgJ2Jvb2wnKSwgaW5wdXRzKV07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1Byb3RvVXRpbH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuXG5leHBvcnQgY29uc3QgY2FzdDogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxUZW5zb3IuRGF0YVR5cGU+ID1cbiAgICAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCB0bzogVGVuc29yLkRhdGFUeXBlKTogVGVuc29yW10gPT4ge1xuICAgICAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzKTtcbiAgICAgIHJldHVybiBbaGFuZGxlci5jYXN0KGlucHV0c1swXSwgdG8pXTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcGFyc2VDYXN0QXR0cmlidXRlczogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxUZW5zb3IuRGF0YVR5cGU+ID0gKG5vZGU6IEdyYXBoLk5vZGUpOiBUZW5zb3IuRGF0YVR5cGUgPT5cbiAgICBQcm90b1V0aWwudGVuc29yRGF0YVR5cGVGcm9tUHJvdG8obm9kZS5hdHRyaWJ1dGVzLmdldEludCgndG8nKSk7XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogVGVuc29yW10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2FzdCByZXF1aXJlcyAxIGlucHV0LicpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS50eXBlID09PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCB0eXBlLicpO1xuICB9XG59OyIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi4vZ2xzbC1zb3VyY2UnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGEsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQge2dldENvb3Jkc0RhdGFUeXBlLCBnZXRHbENoYW5uZWxzfSBmcm9tICcuLi91dGlscyc7XG5cbmltcG9ydCB7Q29uY2F0QXR0cmlidXRlc30gZnJvbSAnLi9jb25jYXQnO1xuaW1wb3J0IHtnZXRDaGFubmVscywgdW5wYWNrRnJvbUNoYW5uZWx9IGZyb20gJy4vcGFja2luZy11dGlscyc7XG5cbmNvbnN0IGNyZWF0ZVBhY2tlZENvbmNhdFByb2dyYW1NZXRhZGF0YSA9IChpbnB1dENvdW50OiBudW1iZXIsIGNhY2hlSGludDogc3RyaW5nKSA9PiAoe1xuICBuYW1lOiAnQ29uY2F0IChwYWNrZWQpJyxcbiAgaW5wdXROYW1lczogQXJyYXkuZnJvbSh7bGVuZ3RoOiBpbnB1dENvdW50fSwgKHYsIGkpID0+IGBYJHtpfWApLFxuICBpbnB1dFR5cGVzOiBBcnJheShpbnB1dENvdW50KS5maWxsKFRleHR1cmVUeXBlLnBhY2tlZCksXG4gIGNhY2hlSGludFxufSk7XG5cbmNvbnN0IGNyZWF0ZVBhY2tlZENvbmNhdFByb2dyYW1JbmZvID1cbiAgICAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhLCBpbnB1dHM6IFRlbnNvcltdLCBheGlzOiBudW1iZXIpOiBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXRzWzBdLmRpbXMuc2xpY2UoKTtcbiAgICAgIGlmIChheGlzID49IGlucHV0U2hhcGUubGVuZ3RoIHx8IGF4aXMgPCAoLTEgKiBpbnB1dFNoYXBlLmxlbmd0aCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdheGlzIHNwZWNpZmllZCBmb3IgY29uY2F0IGRvZXNuXFwndCBtYXRjaCBpbnB1dCBkaW1lbnNpb25hbGl0eScpO1xuICAgICAgfVxuICAgICAgaWYgKGF4aXMgPCAwKSB7XG4gICAgICAgIGF4aXMgPSBpbnB1dFNoYXBlLmxlbmd0aCArIGF4aXM7XG4gICAgICB9XG4gICAgICAvLyBlbnN1cmUgYWxsIG9mIHRoZSBub24tY29uY2F0ZW5hdGVkIGF4ZXMgbWF0Y2ggZWFjaCBvdGhlclxuICAgICAgLy8gY2FsY3VsYXRlIHRoZSBzaGFwZSBvZiB0aGUgb3V0cHV0IHRlbnNvciB3aGlsZSB3ZSBkbyB0aGF0XG4gICAgICBjb25zdCBvdXRwdXRTaGFwZSA9IGlucHV0U2hhcGUuc2xpY2UoMCk7XG4gICAgICBmb3IgKGxldCBpID0gMTsgaSA8IGlucHV0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBkYXRhTlNoYXBlID0gaW5wdXRzW2ldLmRpbXMuc2xpY2UoKTtcbiAgICAgICAgZm9yIChsZXQgYXhpc0luZGV4ID0gMDsgYXhpc0luZGV4IDwgaW5wdXRTaGFwZS5sZW5ndGg7IGF4aXNJbmRleCsrKSB7XG4gICAgICAgICAgLy8gYWRkIHRvIHRoZSBwbGFjZWhvbGRlciBmb3IgY29tcHV0aW5nIG91dHB1dCBzaGFwZVxuICAgICAgICAgIGlmIChheGlzSW5kZXggPT09IGF4aXMpIHtcbiAgICAgICAgICAgIG91dHB1dFNoYXBlW2F4aXNdICs9IGRhdGFOU2hhcGVbYXhpc0luZGV4XTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gZW5zdXJlIGFsbCBub24tY2FuY2F0ZW5hdGVkIGF4ZXMgbWF0Y2ggZWFjaCBvdGhlclxuICAgICAgICAgIGVsc2UgaWYgKGlucHV0U2hhcGVbYXhpc0luZGV4XSAhPT0gZGF0YU5TaGFwZVtheGlzSW5kZXhdKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vbiBjb25jYXQgZGltZW5zaW9ucyBtdXN0IG1hdGNoJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJhbmsgPSBvdXRwdXRTaGFwZS5sZW5ndGg7XG4gICAgICBjb25zdCBjb29yZHMgPSBnZXRDaGFubmVscygnY29vcmRzJywgcmFuayk7XG4gICAgICBjb25zdCBkdHlwZSA9IGdldENvb3Jkc0RhdGFUeXBlKHJhbmspO1xuICAgICAgY29uc3QgdW5wYWNrQ2hhbm5lbCA9IHVucGFja0Zyb21DaGFubmVsKCk7XG5cbiAgICAgIGNvbnN0IHNoYXBlcyA9IGlucHV0cy5tYXAoaSA9PiBpLmRpbXMpO1xuICAgICAgY29uc3QgY2hhbm5lbHMgPSBnZXRHbENoYW5uZWxzKHJhbmspO1xuICAgICAgY29uc3Qgb2Zmc2V0czogbnVtYmVyW10gPSBuZXcgQXJyYXkoc2hhcGVzLmxlbmd0aCAtIDEpO1xuXG4gICAgICBvZmZzZXRzWzBdID0gc2hhcGVzWzBdW2F4aXNdO1xuICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBvZmZzZXRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIG9mZnNldHNbaV0gPSBvZmZzZXRzW2kgLSAxXSArIHNoYXBlc1tpXVtheGlzXTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2hhbm5lbCA9IGNoYW5uZWxzW2F4aXNdO1xuICAgICAgY29uc3QgbGFzdENoYW5uZWxzID0gY2hhbm5lbHMuc2xpY2UoLTIpO1xuICAgICAgY29uc3QgYWxsQ2hhbm5lbHMgPSBjaGFubmVscy5qb2luKCk7XG5cbiAgICAgIGxldCBnZXRWYWx1ZVNuaXBwZXQgPSBgaWYgKCR7Y2hhbm5lbH0gPCAke29mZnNldHNbMF19KSB7XG4gICAgICAgIHJldHVybiBnZXRDaGFubmVsKFxuICAgICAgICAgICAgZ2V0WDAoJHthbGxDaGFubmVsc30pLCB2ZWMyKCR7bGFzdENoYW5uZWxzLmpvaW4oKX0pKTtcbiAgICAgICAgfWA7XG4gICAgICBmb3IgKGxldCBpID0gMTsgaSA8IG9mZnNldHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3Qgc2hpZnQgPSBvZmZzZXRzW2kgLSAxXTtcbiAgICAgICAgZ2V0VmFsdWVTbmlwcGV0ICs9IGBcbiAgICAgICAgICAgIGlmICgke2NoYW5uZWx9IDwgJHtvZmZzZXRzW2ldfSAgJiYgJHtjaGFubmVsfSA+PSAke29mZnNldHNbaSAtIDFdfSkge1xuICAgICAgICAgICAgICByZXR1cm4gZ2V0Q2hhbm5lbChcbiAgICAgICAgICAgICAgICBnZXRYJHtpfSgke2dldFNoaWZ0ZWRDaGFubmVsc1NuaXBwZXQoY2hhbm5lbHMsIGNoYW5uZWwsIHNoaWZ0KX0pLFxuICAgICAgICAgICAgICAgIHZlYzIoJHtnZXRTaGlmdGVkQ2hhbm5lbHNTbmlwcGV0KGxhc3RDaGFubmVscywgY2hhbm5lbCwgc2hpZnQpfSkpO1xuICAgICAgICAgICAgfWA7XG4gICAgICB9XG4gICAgICBjb25zdCBsYXN0SW5kZXggPSBvZmZzZXRzLmxlbmd0aDtcbiAgICAgIGNvbnN0IHNoaWZ0ID0gb2Zmc2V0c1tvZmZzZXRzLmxlbmd0aCAtIDFdO1xuICAgICAgZ2V0VmFsdWVTbmlwcGV0ICs9IGBcbiAgICAgICAgICAgIHJldHVybiBnZXRDaGFubmVsKFxuICAgICAgICAgICAgICBnZXRYJHtsYXN0SW5kZXh9KCR7Z2V0U2hpZnRlZENoYW5uZWxzU25pcHBldChjaGFubmVscywgY2hhbm5lbCwgc2hpZnQpfSksXG4gICAgICAgICAgICAgIHZlYzIoJHtnZXRTaGlmdGVkQ2hhbm5lbHNTbmlwcGV0KGxhc3RDaGFubmVscywgY2hhbm5lbCwgc2hpZnQpfSkpO2A7XG5cbiAgICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKGhhbmRsZXIuc2Vzc2lvbi5iYWNrZW5kLmdsQ29udGV4dC52ZXJzaW9uKTtcblxuICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICAgICAgICR7dW5wYWNrQ2hhbm5lbH1cbiAgICAgICAgICBmbG9hdCBnZXRWYWx1ZSgke2NoYW5uZWxzLm1hcCh4ID0+ICdpbnQgJyArIHgpfSkge1xuICAgICAgICAgICAgJHtnZXRWYWx1ZVNuaXBwZXR9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdm9pZCBtYWluKCkge1xuICAgICAgICAgICAgJHtkdHlwZX0gY29vcmRzID0gZ2V0T3V0cHV0Q29vcmRzKCk7XG4gICAgICAgICAgICBpbnQgbGFzdERpbSA9IGNvb3Jkcy4ke2NoYW5uZWxzW3JhbmsgLSAxXX07XG4gICAgICAgICAgICBjb29yZHMuJHtjaGFubmVsc1tyYW5rIC0gMV19ID0gY29vcmRzLiR7Y2hhbm5lbHNbcmFuayAtIDJdfTtcbiAgICAgICAgICAgIGNvb3Jkcy4ke2NoYW5uZWxzW3JhbmsgLSAyXX0gPSBsYXN0RGltO1xuXG4gICAgICAgICAgICB2ZWM0IHJlc3VsdCA9IHZlYzQoZ2V0VmFsdWUoJHtjb29yZHN9KSwgMC4sIDAuLCAwLik7XG5cbiAgICAgICAgICAgICR7Y29vcmRzW3JhbmsgLSAxXX0gPSAke2Nvb3Jkc1tyYW5rIC0gMV19ICsgMTtcbiAgICAgICAgICAgIGlmICgke2Nvb3Jkc1tyYW5rIC0gMV19IDwgJHtvdXRwdXRTaGFwZVtyYW5rIC0gMV19KSB7XG4gICAgICAgICAgICAgIHJlc3VsdC5nID0gZ2V0VmFsdWUoJHtjb29yZHN9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgJHtjb29yZHNbcmFuayAtIDJdfSA9ICR7Y29vcmRzW3JhbmsgLSAyXX0gKyAxO1xuICAgICAgICAgICAgaWYgKCR7Y29vcmRzW3JhbmsgLSAyXX0gPCAke291dHB1dFNoYXBlW3JhbmsgLSAyXX0pIHtcbiAgICAgICAgICAgICAgcmVzdWx0LmEgPSBnZXRWYWx1ZSgke2Nvb3Jkc30pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAke2Nvb3Jkc1tyYW5rIC0gMV19ID0gJHtjb29yZHNbcmFuayAtIDFdfSAtIDE7XG4gICAgICAgICAgICBpZiAoJHtjb29yZHNbcmFuayAtIDJdfSA8ICR7b3V0cHV0U2hhcGVbcmFuayAtIDJdfSAmJlxuICAgICAgICAgICAgICAgICR7Y29vcmRzW3JhbmsgLSAxXX0gPCAke291dHB1dFNoYXBlW3JhbmsgLSAxXX0pIHtcbiAgICAgICAgICAgICAgcmVzdWx0LmIgPSBnZXRWYWx1ZSgke2Nvb3Jkc30pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJHtnbHNsLm91dHB1dH0gPSByZXN1bHQ7XG4gICAgICAgICAgfVxuICAgICAgICBgO1xuXG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgb3V0cHV0OiB7ZGltczogb3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0c1swXS50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUucGFja2VkfSxcbiAgICAgICAgc2hhZGVyU291cmNlLFxuICAgICAgICBoYXNNYWluOiB0cnVlLFxuICAgICAgfTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlUGFja2VkQ29uY2F0UHJvZ3JhbUluZm9Mb2FkZXIgPVxuICAgIChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IENvbmNhdEF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mb0xvYWRlciA9PiB7XG4gICAgICBjb25zdCBtZXRhZGF0YSA9IGNyZWF0ZVBhY2tlZENvbmNhdFByb2dyYW1NZXRhZGF0YShpbnB1dHMubGVuZ3RoLCBhdHRyaWJ1dGVzLmNhY2hlS2V5KTtcbiAgICAgIHJldHVybiB7Li4ubWV0YWRhdGEsIGdldDogKCkgPT4gY3JlYXRlUGFja2VkQ29uY2F0UHJvZ3JhbUluZm8oaGFuZGxlciwgbWV0YWRhdGEsIGlucHV0cywgYXR0cmlidXRlcy5heGlzKX07XG4gICAgfTtcblxuY29uc3QgZ2V0U2hpZnRlZENoYW5uZWxzU25pcHBldCA9IChjaGFubmVsczogc3RyaW5nW10sIGNoYW5uZWw6IHN0cmluZywgc2hpZnQ6IG51bWJlcik6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGNoYW5uZWxJZHggPSBjaGFubmVscy5pbmRleE9mKGNoYW5uZWwpO1xuICBjb25zdCByZXMgPSBjaGFubmVscy5tYXAoKGMsIGlkeCkgPT4ge1xuICAgIGlmIChpZHggPT09IGNoYW5uZWxJZHgpIHtcbiAgICAgIHJldHVybiBgJHtjfSAtICR7c2hpZnR9YDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGM7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIHJlcy5qb2luKCk7XG59O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7QXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXl9IGZyb20gJy4uLy4uLy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQge0dyYXBofSBmcm9tICcuLi8uLi8uLi9ncmFwaCc7XG5pbXBvcnQge09wZXJhdG9ySW1wbGVtZW50YXRpb24sIE9wZXJhdG9ySW5pdGlhbGl6YXRpb259IGZyb20gJy4uLy4uLy4uL29wZXJhdG9ycyc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBQcm9ncmFtSW5mb0xvYWRlciwgUHJvZ3JhbU1ldGFkYXRhLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge2NyZWF0ZVBhY2tlZENvbmNhdFByb2dyYW1JbmZvTG9hZGVyfSBmcm9tICcuL2NvbmNhdC1wYWNrZWQnO1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbmNhdEF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBheGlzOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCBjb25jYXQ6IE9wZXJhdG9ySW1wbGVtZW50YXRpb248Q29uY2F0QXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IENvbmNhdEF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuICAgICAgaWYgKGluZmVyZW5jZUhhbmRsZXIuc2Vzc2lvbi5wYWNrICYmIGlucHV0c1swXS5kaW1zLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgY29uc3Qgb3V0cHV0ID1cbiAgICAgICAgICAgIGluZmVyZW5jZUhhbmRsZXIucnVuKGNyZWF0ZVBhY2tlZENvbmNhdFByb2dyYW1JbmZvTG9hZGVyKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYXR0cmlidXRlcyksIGlucHV0cyk7XG4gICAgICAgIHJldHVybiBbb3V0cHV0XTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IG91dHB1dCA9XG4gICAgICAgICAgICBpbmZlcmVuY2VIYW5kbGVyLnJ1bihjcmVhdGVVbnBhY2tlZENvbmNhdFByb2dyYW1JbmZvTG9hZGVyKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYXR0cmlidXRlcyksIGlucHV0cyk7XG4gICAgICAgIHJldHVybiBbb3V0cHV0XTtcbiAgICAgIH1cbiAgICB9O1xuXG5jb25zdCBjcmVhdGVVbnBhY2tlZENvbmNhdFByb2dyYW1NZXRhZGF0YSA9IChpbnB1dENvdW50OiBudW1iZXIsIGNhY2hlSGludDogc3RyaW5nKSA9PiAoe1xuICBuYW1lOiAnQ29uY2F0JyxcbiAgaW5wdXROYW1lczogQXJyYXkuZnJvbSh7bGVuZ3RoOiBpbnB1dENvdW50fSwgKHYsIGkpID0+IGBYJHtpfWApLFxuICBpbnB1dFR5cGVzOiBBcnJheShpbnB1dENvdW50KS5maWxsKFRleHR1cmVUeXBlLnVucGFja2VkKSxcbiAgY2FjaGVIaW50XG59KTtcblxuY29uc3QgY3JlYXRlVW5wYWNrZWRDb25jYXRQcm9ncmFtSW5mbyA9XG4gICAgKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgbWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSwgaW5wdXRzOiBUZW5zb3JbXSwgYXhpczogbnVtYmVyKTogUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zLnNsaWNlKCk7XG4gICAgICBpZiAoYXhpcyA+PSBpbnB1dFNoYXBlLmxlbmd0aCB8fCBheGlzIDwgKC0xICogaW5wdXRTaGFwZS5sZW5ndGgpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYXhpcyBzcGVjaWZpZWQgZm9yIGNvbmNhdCBkb2VzblxcJ3QgbWF0Y2ggaW5wdXQgZGltZW5zaW9uYWxpdHknKTtcbiAgICAgIH1cbiAgICAgIGlmIChheGlzIDwgMCkge1xuICAgICAgICBheGlzID0gaW5wdXRTaGFwZS5sZW5ndGggKyBheGlzO1xuICAgICAgfVxuICAgICAgLy8gZW5zdXJlIGFsbCBvZiB0aGUgbm9uLWNvbmNhdGVuYXRlZCBheGVzIG1hdGNoIGVhY2ggb3RoZXJcbiAgICAgIC8vIGNhbGN1bGF0ZSB0aGUgc2hhcGUgb2YgdGhlIG91dHB1dCB0ZW5zb3Igd2hpbGUgd2UgZG8gdGhhdFxuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dFNoYXBlLnNsaWNlKDApO1xuICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBpbnB1dHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgZGF0YU5TaGFwZSA9IGlucHV0c1tpXS5kaW1zLnNsaWNlKCk7XG4gICAgICAgIGZvciAobGV0IGF4aXNJbmRleCA9IDA7IGF4aXNJbmRleCA8IGlucHV0U2hhcGUubGVuZ3RoOyBheGlzSW5kZXgrKykge1xuICAgICAgICAgIC8vIGFkZCB0byB0aGUgcGxhY2Vob2xkZXIgZm9yIGNvbXB1dGluZyBvdXRwdXQgc2hhcGVcbiAgICAgICAgICBpZiAoYXhpc0luZGV4ID09PSBheGlzKSB7XG4gICAgICAgICAgICBvdXRwdXRTaGFwZVtheGlzXSArPSBkYXRhTlNoYXBlW2F4aXNJbmRleF07XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIGVuc3VyZSBhbGwgbm9uLWNhbmNhdGVuYXRlZCBheGVzIG1hdGNoIGVhY2ggb3RoZXJcbiAgICAgICAgICBlbHNlIGlmIChpbnB1dFNoYXBlW2F4aXNJbmRleF0gIT09IGRhdGFOU2hhcGVbYXhpc0luZGV4XSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdub24gY29uY2F0IGRpbWVuc2lvbnMgbXVzdCBtYXRjaCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCByYW5rID0gb3V0cHV0U2hhcGUubGVuZ3RoO1xuXG4gICAgICBjb25zdCBzaXplSW5Db25jYXRBeGlzID0gbmV3IEFycmF5PG51bWJlcj4oaW5wdXRzLmxlbmd0aCk7XG4gICAgICBsZXQgcHJldmlvdXNTdW0gPSAwO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplSW5Db25jYXRBeGlzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHByZXZpb3VzU3VtICs9IGlucHV0c1tpXS5kaW1zW2F4aXNdO1xuICAgICAgICBzaXplSW5Db25jYXRBeGlzW2ldID0gcHJldmlvdXNTdW07XG4gICAgICB9XG5cbiAgICAgIGxldCBnZXRUZXh0dXJlSW5kZXhXaGVyZURhdGFSZXNpZGVzTWV0aG9kID0gJyc7XG4gICAgICAvLyBpbiBtb3N0IGNhc2VzIGxpbmVhciBzZWFyY2ggaXMgc3VmZmljaWVudCwgYXMgaW4gbW9zdCBzY2VuYXJpb3MsIG9ubHkgMiB0ZW5zb3JzIGFyZSBjb25jYXRlbmF0ZWRcbiAgICAgIGlmIChpbnB1dHMubGVuZ3RoIDwgNSkge1xuICAgICAgICBnZXRUZXh0dXJlSW5kZXhXaGVyZURhdGFSZXNpZGVzTWV0aG9kID0gZ2V0VGV4dHVyZUluZGV4V2hlcmVEYXRhUmVzaWRlc0xpbmVhclNlYXJjaChzaXplSW5Db25jYXRBeGlzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGdldFRleHR1cmVJbmRleFdoZXJlRGF0YVJlc2lkZXNNZXRob2QgPSBnZXRUZXh0dXJlSW5kZXhXaGVyZURhdGFSZXNpZGVzQmluYXJ5U2VhcmNoKHNpemVJbkNvbmNhdEF4aXMpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBmZXRjaERhdGFGcm9tQ29ycmVjdFRleHR1cmVNZXRob2QgPSBnZXRGZXRjaERhdGFGcm9tQ29ycmVjdFRleHR1cmVNZXRob2QoaW5wdXRzLmxlbmd0aCwgcmFuayk7XG4gICAgICBjb25zdCBnZXRTaXplSW5Db25jYXRBeGlzVmFsdWVGcm9tSW5kZXhNZXRob2QgPSBnZXRHZXRTaXplSW5Db25jYXRBeGlzVmFsdWVGcm9tSW5kZXhNZXRob2Qoc2l6ZUluQ29uY2F0QXhpcyk7XG4gICAgICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gICAgICAgICR7ZmV0Y2hEYXRhRnJvbUNvcnJlY3RUZXh0dXJlTWV0aG9kfVxuICAgICAgICAke2dldFNpemVJbkNvbmNhdEF4aXNWYWx1ZUZyb21JbmRleE1ldGhvZH1cbiAgICAgICAgJHtnZXRUZXh0dXJlSW5kZXhXaGVyZURhdGFSZXNpZGVzTWV0aG9kfVxuICAgICAgICBmbG9hdCBwcm9jZXNzKGludCBpbmRpY2VzWyR7cmFua31dKSB7XG4gICAgICAgICAgaW50IHRleHR1cmVJbmRleCA9IGdldFRleHR1cmVXaGVyZURhdGFSZXNpZGVzIChpbmRpY2VzWyR7YXhpc31dKTtcblxuICAgICAgICAgIGlmKHRleHR1cmVJbmRleCAhPSAwKSB7XG4gICAgICAgICAgICBpbmRpY2VzWyR7YXhpc31dID0gaW5kaWNlc1ske2F4aXN9XSAtIGludChnZXRTaXplSW5Db25jYXRBeGlzVmFsdWVGcm9tSW5kZXgodGV4dHVyZUluZGV4LWludCgxKSkpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBmZXRjaERhdGFGcm9tQ29ycmVjdFRleHR1cmUodGV4dHVyZUluZGV4LCBpbmRpY2VzKTtcbiAgICAgICAgfWA7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgb3V0cHV0OiB7ZGltczogb3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0c1swXS50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUudW5wYWNrZWR9LFxuICAgICAgICBzaGFkZXJTb3VyY2UsXG4gICAgICB9O1xuICAgIH07XG5cbmNvbnN0IGNyZWF0ZVVucGFja2VkQ29uY2F0UHJvZ3JhbUluZm9Mb2FkZXIgPVxuICAgIChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IENvbmNhdEF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mb0xvYWRlciA9PiB7XG4gICAgICBjb25zdCBtZXRhZGF0YSA9IGNyZWF0ZVVucGFja2VkQ29uY2F0UHJvZ3JhbU1ldGFkYXRhKGlucHV0cy5sZW5ndGgsIGF0dHJpYnV0ZXMuY2FjaGVLZXkpO1xuICAgICAgcmV0dXJuIHsuLi5tZXRhZGF0YSwgZ2V0OiAoKSA9PiBjcmVhdGVVbnBhY2tlZENvbmNhdFByb2dyYW1JbmZvKGhhbmRsZXIsIG1ldGFkYXRhLCBpbnB1dHMsIGF0dHJpYnV0ZXMuYXhpcyl9O1xuICAgIH07XG5cbmNvbnN0IGdldFRleHR1cmVJbmRleFdoZXJlRGF0YVJlc2lkZXNMaW5lYXJTZWFyY2ggPSAoc2l6ZUluQ29uY2F0QXhpczogbnVtYmVyW10pOiBzdHJpbmcgPT4ge1xuICBjb25zdCBzZWFyY2hBeGlzID0gc2l6ZUluQ29uY2F0QXhpcy5tYXAoKHNpemUsIGkpID0+IGBpZihpbmRleDwke3NpemV9KSB7cmV0dXJuICR7aX07fVxuYCk7XG4gIHJldHVybiBgaW50IGdldFRleHR1cmVXaGVyZURhdGFSZXNpZGVzKGludCBpbmRleCkge1xuICAgICAgJHtzZWFyY2hBeGlzLmpvaW4oJycpfVxuICAgIH1gO1xufTtcblxuLy8gVE9ETzogSW1wbGVtZW50IEJpbmFyeVNlYXJjaCBpbiBHTFNMXG5jb25zdCBnZXRUZXh0dXJlSW5kZXhXaGVyZURhdGFSZXNpZGVzQmluYXJ5U2VhcmNoID0gKHNpemVJbkNvbmNhdEF4aXM6IG51bWJlcltdKTogc3RyaW5nID0+XG4gICAgZ2V0VGV4dHVyZUluZGV4V2hlcmVEYXRhUmVzaWRlc0xpbmVhclNlYXJjaChzaXplSW5Db25jYXRBeGlzKTtcblxuY29uc3QgZ2V0RmV0Y2hEYXRhRnJvbUNvcnJlY3RUZXh0dXJlTWV0aG9kID0gKG51bWJlck9mVGVuc29yczogbnVtYmVyLCB0ZW5zb3JSYW5rOiBudW1iZXIpID0+IHtcbiAgY29uc3QgY29kZUxpbmVzOiBzdHJpbmdbXSA9IFtgZmxvYXQgZmV0Y2hEYXRhRnJvbUNvcnJlY3RUZXh0dXJlKGludCB0ZXh0dXJlSW5kZXgsIGludCBpbmRpY2VzWyR7dGVuc29yUmFua31dKSB7YF07XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZUZW5zb3JzOyArK2kpIHtcbiAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgY29kZUxpbmVzLnB1c2goXG4gICAgICAgICAgJ1xcdCcgK1xuICAgICAgICAgIGBpZiAodGV4dHVyZUluZGV4ID09ICR7aX0pIHsgcmV0dXJuIF9YJHtpfShpbmRpY2VzKTsgfWApO1xuICAgIH0gZWxzZSBpZiAoaSA9PT0gbnVtYmVyT2ZUZW5zb3JzIC0gMSkge1xuICAgICAgY29kZUxpbmVzLnB1c2goXG4gICAgICAgICAgJ1xcdCcgK1xuICAgICAgICAgIGBlbHNlIHsgcmV0dXJuIF9YJHtpfShpbmRpY2VzKTsgfWApO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb2RlTGluZXMucHVzaChcbiAgICAgICAgICAnXFx0JyArXG4gICAgICAgICAgYGVsc2UgaWYgKHRleHR1cmVJbmRleCA9PSAke2l9KSB7IHJldHVybiBfWCR7aX0oaW5kaWNlcyk7IH1gKTtcbiAgICB9XG4gIH1cbiAgY29kZUxpbmVzLnB1c2goXG4gICAgICAnXFx0JyArXG4gICAgICAnfScpO1xuICByZXR1cm4gY29kZUxpbmVzLmpvaW4oJ1xcbicpO1xufTtcblxuY29uc3QgZ2V0R2V0U2l6ZUluQ29uY2F0QXhpc1ZhbHVlRnJvbUluZGV4TWV0aG9kID0gKHNpemVJbkNvbmNhdEF4aXM6IG51bWJlcltdKTogc3RyaW5nID0+IHtcbiAgY29uc3QgY29kZUxpbmVzOiBzdHJpbmdbXSA9IFsnaW50IGdldFNpemVJbkNvbmNhdEF4aXNWYWx1ZUZyb21JbmRleChpbnQgaW5kZXgpIHsnXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplSW5Db25jYXRBeGlzLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKFxuICAgICAgICAgICdcXHQnICtcbiAgICAgICAgICBgaWYgKGluZGV4ID09ICR7aX0pIHsgcmV0dXJuICR7c2l6ZUluQ29uY2F0QXhpc1tpXX07IH1gKTtcbiAgICB9IGVsc2UgaWYgKGkgPT09IHNpemVJbkNvbmNhdEF4aXMubGVuZ3RoIC0gMSkge1xuICAgICAgY29kZUxpbmVzLnB1c2goXG4gICAgICAgICAgJ1xcdCcgK1xuICAgICAgICAgIGBlbHNlIHsgcmV0dXJuICR7c2l6ZUluQ29uY2F0QXhpc1tpXX07IH1gKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29kZUxpbmVzLnB1c2goXG4gICAgICAgICAgJ1xcdCcgK1xuICAgICAgICAgIGBlbHNlIGlmIChpbmRleCA9PSAke2l9KSB7IHJldHVybiAke3NpemVJbkNvbmNhdEF4aXNbaV19OyB9YCk7XG4gICAgfVxuICB9XG4gIGNvZGVMaW5lcy5wdXNoKFxuICAgICAgJ1xcdCcgK1xuICAgICAgJ30nKTtcblxuICByZXR1cm4gY29kZUxpbmVzLmpvaW4oJ1xcbicpO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlQ29uY2F0QXR0cmlidXRlczogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxDb25jYXRBdHRyaWJ1dGVzPiA9IChub2RlOiBHcmFwaC5Ob2RlKTogQ29uY2F0QXR0cmlidXRlcyA9PlxuICAgIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7YXhpczogbm9kZS5hdHRyaWJ1dGVzLmdldEludCgnYXhpcycpfSk7XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogVGVuc29yW10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCA8IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3RvbyBmZXcgaW5wdXRzJyk7XG4gIH1cblxuICBjb25zdCBpbnB1dFR5cGUgPSBpbnB1dHNbMF0udHlwZTtcbiAgY29uc3QgaW5wdXREaW1lbnNpb25hbGl0eSA9IGlucHV0c1swXS5kaW1zLmxlbmd0aDtcblxuICAvLyBUT0RPOiBTdXBwb3J0IHN0cmluZyBjb25jYXRcbiAgaWYgKGlucHV0VHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3N0cmluZyB0ZW5zb3IgaXMgbm90IHN1cHBvcnRlZCB5ZXQnKTtcbiAgfVxuXG4gIGZvciAoY29uc3QgaW5wdXQgb2YgaW5wdXRzKSB7XG4gICAgLy8gbWFrZSBzdXJlIHR5cGVzIG9mIGFsbCBpbnB1dHMgbWF0Y2hcbiAgICBpZiAoaW5wdXQudHlwZSAhPT0gaW5wdXRUeXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2lucHV0IHRlbnNvcnMgc2hvdWxkIGJlIG9uZSB0eXBlJyk7XG4gICAgfVxuXG4gICAgLy8gbWFrZSBzdXJlIHRoZSBkaW1lbnNpb25hbGl0eSBvZiBhbGwgaW5wdXRzIGFyZSB0aGUgc2FtZVxuICAgIGlmIChpbnB1dC5kaW1zLmxlbmd0aCAhPT0gaW5wdXREaW1lbnNpb25hbGl0eSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dCB0ZW5zb3JzIHNob3VsZCBoYXZlIHRoZSBzYW1lIHNoYXBlJyk7XG4gICAgfVxuICB9XG59O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7TG9nZ2VyfSBmcm9tICcuLi8uLi8uLi9pbnN0cnVtZW50JztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtnZXRHbHNsfSBmcm9tICcuLi9nbHNsLXNvdXJjZSc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgUHJvZ3JhbUluZm9Mb2FkZXIsIFByb2dyYW1NZXRhZGF0YSwgVGV4dHVyZVR5cGV9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtjYWxjdWxhdGVPdXRwdXRTaGFwZSwgQ29udkF0dHJpYnV0ZXN9IGZyb20gJy4vY29udic7XG5pbXBvcnQge2dldEFjdGl2YXRpb25TbmlwcGV0fSBmcm9tICcuL2Z1c2UtdXRpbHMnO1xuXG5jb25zdCBjcmVhdGVVbnBhY2tlZEdyb3VwZWRDb252UHJvZ3JhbU1ldGFkYXRhID0gKGhhc0JpYXM6IGJvb2xlYW4sIGNhY2hlSGludDogc3RyaW5nKTogUHJvZ3JhbU1ldGFkYXRhID0+ICh7XG4gIG5hbWU6ICdHcm91cGVkQ29udicsXG4gIGlucHV0TmFtZXM6IGhhc0JpYXMgPyBbJ1gnLCAnVycsICdCaWFzJ10gOiBbJ1gnLCAnVyddLFxuICBpbnB1dFR5cGVzOiBoYXNCaWFzID8gW1RleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWRdIDpcbiAgICAgICAgICAgICAgICAgICAgICAgIFtUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWRdLFxuICBjYWNoZUhpbnRcbn0pO1xuXG5jb25zdCBjcmVhdGVVbnBhY2tlZEdyb3VwZWRDb252UHJvZ3JhbUluZm8gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogcmVhZG9ubHkgVGVuc29yW10sIG1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEsXG4gICAgIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgY29uc3QgaGFzQmlhcyA9IGlucHV0cy5sZW5ndGggPiAyO1xuICAgICAgY29uc3QgcHJvY2Vzc0JpYXMgPSBoYXNCaWFzID8gJ3ZhbHVlICs9IGdldEJpYXMob3V0cHV0X2NoYW5uZWwpOycgOiAnJztcbiAgICAgIGNvbnN0IHhTaGFwZSA9IGlucHV0c1swXS5kaW1zLnNsaWNlKCk7XG4gICAgICBjb25zdCB3U2hhcGUgPSBpbnB1dHNbMV0uZGltcy5zbGljZSgpO1xuICAgICAgY29uc3Qgb3V0cHV0Q2hhbm5lbHNQZXJHcm91cCA9IHdTaGFwZVswXSAvIGF0dHJpYnV0ZXMuZ3JvdXA7XG4gICAgICBMb2dnZXIudmVyYm9zZShcbiAgICAgICAgICAnR3JvdXBlZENvbnYnLFxuICAgICAgICAgIGBhdXRwUGFkOiR7YXR0cmlidXRlcy5hdXRvUGFkfSwgZGlsYXRpb25zOiR7YXR0cmlidXRlcy5kaWxhdGlvbnN9LCBncm91cDoke2F0dHJpYnV0ZXMuZ3JvdXB9LCBrZXJuZWxTaGFwZToke1xuICAgICAgICAgICAgICBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlfSwgcGFkczoke2F0dHJpYnV0ZXMucGFkc30sIHN0cmlkZXM6JHthdHRyaWJ1dGVzLnN0cmlkZXN9YCk7XG4gICAgICBjb25zdCBvdXRwdXRTaGFwZSA9XG4gICAgICAgICAgY2FsY3VsYXRlT3V0cHV0U2hhcGUoeFNoYXBlLCB3U2hhcGUsIGF0dHJpYnV0ZXMuZGlsYXRpb25zLCBhdHRyaWJ1dGVzLnBhZHMsIGF0dHJpYnV0ZXMuc3RyaWRlcyk7XG4gICAgICBjb25zdCBnbHNsID0gZ2V0R2xzbChpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQudmVyc2lvbik7XG4gICAgICBjb25zdCB7YWN0aXZhdGlvbkZ1bmN0aW9uLCBhcHBseUFjdGl2YXRpb259ID0gZ2V0QWN0aXZhdGlvblNuaXBwZXQoYXR0cmlidXRlcyk7XG5cbiAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgY29uc3QgaXZlYzIgc3RyaWRlcyA9IGl2ZWMyKCR7YXR0cmlidXRlcy5zdHJpZGVzWzBdfSwgJHthdHRyaWJ1dGVzLnN0cmlkZXNbMV19KTtcbiAgY29uc3QgaXZlYzIgcGFkcyA9IGl2ZWMyKCR7YXR0cmlidXRlcy5wYWRzWzBdfSwgJHthdHRyaWJ1dGVzLnBhZHNbMV19KTtcbiAgJHthY3RpdmF0aW9uRnVuY3Rpb259XG4gIHZvaWQgbWFpbigpIHtcbiAgICBpdmVjNCBjb29yZHMgPSBnZXRPdXRwdXRDb29yZHMoKTtcbiAgICBpbnQgYmF0Y2ggPSBjb29yZHMueDtcbiAgICBpbnQgb3V0cHV0X2NoYW5uZWwgPSBjb29yZHMueTtcbiAgICBpdmVjMiB4UkNDb3JuZXIgPSBjb29yZHMuencgKiBzdHJpZGVzIC0gcGFkcztcbiAgICBpbnQgZ3JvdXBfaWQgPSBvdXRwdXRfY2hhbm5lbCAvICR7b3V0cHV0Q2hhbm5lbHNQZXJHcm91cH07XG5cbiAgICBmbG9hdCB2YWx1ZSA9IDAuMDtcbiAgICBmb3IgKGludCB3SW5DaGFubmVsID0gMDsgd0luQ2hhbm5lbCA8ICR7d1NoYXBlWzFdfTsgd0luQ2hhbm5lbCsrKSB7XG4gICAgICBpbnQgaW5wdXRfY2hhbm5lbCA9IGdyb3VwX2lkICogJHt3U2hhcGVbMV19ICsgd0luQ2hhbm5lbDtcbiAgICAgIGZvciAoaW50IHdIZWlnaHQgPSAwOyB3SGVpZ2h0IDwgJHt3U2hhcGVbMl19OyB3SGVpZ2h0KyspIHtcbiAgICAgICAgaW50IHhIZWlnaHQgPSB4UkNDb3JuZXIueCArIHdIZWlnaHQgKiAke2F0dHJpYnV0ZXMuZGlsYXRpb25zWzBdfTtcblxuICAgICAgICBpZiAoeEhlaWdodCA8IDAgfHwgeEhlaWdodCA+PSAke3hTaGFwZVsyXX0pIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoaW50IHdXaWR0aCA9IDA7IHdXaWR0aCA8ICR7d1NoYXBlWzNdfTsgd1dpZHRoKyspIHtcbiAgICAgICAgICBpbnQgeFdpZHRoID0geFJDQ29ybmVyLnkgKyB3V2lkdGggKiAke2F0dHJpYnV0ZXMuZGlsYXRpb25zWzFdfTtcbiAgICAgICAgICBpZiAoeFdpZHRoIDwgMCB8fCB4V2lkdGggPj0gJHt4U2hhcGVbM119KSB7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmbG9hdCB4VmFsID0gZ2V0WChiYXRjaCwgaW5wdXRfY2hhbm5lbCwgeFdpZHRoLCB4SGVpZ2h0KTtcbiAgICAgICAgICBmbG9hdCB3VmFsID0gZ2V0VyhvdXRwdXRfY2hhbm5lbCwgd0luQ2hhbm5lbCwgd1dpZHRoLCB3SGVpZ2h0KTtcbiAgICAgICAgICB2YWx1ZSArPSB4VmFsKndWYWw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgJHtwcm9jZXNzQmlhc31cbiAgICAke2FwcGx5QWN0aXZhdGlvbn1cbiAgICAke2dsc2wub3V0cHV0fSA9IHZlYzQodmFsdWUsIC4wLCAuMCwgLjApO1xuICB9XG5gO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgIG91dHB1dDoge2RpbXM6IG91dHB1dFNoYXBlLCB0eXBlOiBpbnB1dHNbMF0udHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgc2hhZGVyU291cmNlLFxuICAgICAgICBoYXNNYWluOiB0cnVlLFxuICAgICAgfTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlVW5wYWNrZWRHcm91cGVkQ29udlByb2dyYW1JbmZvTG9hZGVyID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6XG4gICAgICAgIFByb2dyYW1JbmZvTG9hZGVyID0+IHtcbiAgICAgICAgICBjb25zdCBtZXRhZGF0YSA9IGNyZWF0ZVVucGFja2VkR3JvdXBlZENvbnZQcm9ncmFtTWV0YWRhdGEoaW5wdXRzLmxlbmd0aCA+IDIsIGF0dHJpYnV0ZXMuY2FjaGVLZXkpO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgICAgIGdldDogKCkgPT4gY3JlYXRlVW5wYWNrZWRHcm91cGVkQ29udlByb2dyYW1JbmZvKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgbWV0YWRhdGEsIGF0dHJpYnV0ZXMpXG4gICAgICAgICAgfTtcbiAgICAgICAgfTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5cbmltcG9ydCB7Y2FsY3VsYXRlT3V0cHV0U2hhcGUsIENvbnZBdHRyaWJ1dGVzfSBmcm9tICcuL2NvbnYnO1xuaW1wb3J0IHtjcmVhdGVQYWNrZWRJbTJDb2xQcm9ncmFtSW5mb0xvYWRlcn0gZnJvbSAnLi9pbTJjb2wtcGFjayc7XG5pbXBvcnQge2NyZWF0ZVBhY2tlZE1hdG11bFByb2dyYW1JbmZvTG9hZGVyfSBmcm9tICcuL21hdG11bC1wYWNrJztcblxuZXhwb3J0IGNvbnN0IGNvbnYyRFBhY2tlZFBvaW50d2lzZSA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiByZWFkb25seSBUZW5zb3JbXSwgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMpOiBUZW5zb3IgPT4ge1xuICAgICAgY29uc3QgeHNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gICAgICBjb25zdCBrc2hhcGUgPSBpbnB1dHNbMV0uZGltcztcbiAgICAgIGNvbnN0IG91dHB1dFNoYXBlID1cbiAgICAgICAgICBjYWxjdWxhdGVPdXRwdXRTaGFwZSh4c2hhcGUsIGtzaGFwZSwgYXR0cmlidXRlcy5kaWxhdGlvbnMsIGF0dHJpYnV0ZXMucGFkcywgYXR0cmlidXRlcy5zdHJpZGVzKTtcbiAgICAgIGNvbnN0IHJlc2hhcGVkWCA9IGluZmVyZW5jZUhhbmRsZXIucmVzaGFwZVBhY2tlZChpbnB1dHNbMF0sIFt4c2hhcGVbMV0sIHhzaGFwZVsyXSAqIHhzaGFwZVszXV0pO1xuICAgICAgY29uc3QgcmVzaGFwZWRLID0gaW5mZXJlbmNlSGFuZGxlci5yZXNoYXBlUGFja2VkKGlucHV0c1sxXSwgW2tzaGFwZVswXSwga3NoYXBlWzFdXSk7XG5cbiAgICAgIGNvbnN0IG1hdG11bElucHV0cyA9IGlucHV0cy5sZW5ndGggPiAyID8gW3Jlc2hhcGVkSywgcmVzaGFwZWRYLCBpbnB1dHNbMl1dIDogW3Jlc2hhcGVkSywgcmVzaGFwZWRYXTtcbiAgICAgIGNvbnN0IG1hdG11bE91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgIGNyZWF0ZVBhY2tlZE1hdG11bFByb2dyYW1JbmZvTG9hZGVyKGluZmVyZW5jZUhhbmRsZXIsIG1hdG11bElucHV0cywgYXR0cmlidXRlcyksIG1hdG11bElucHV0cyk7XG4gICAgICByZXR1cm4gaW5mZXJlbmNlSGFuZGxlci5yZXNoYXBlUGFja2VkKG1hdG11bE91dHB1dCwgb3V0cHV0U2hhcGUpO1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBjb252MkRQYWNrZWQgPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogcmVhZG9ubHkgVGVuc29yW10sIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzKTogVGVuc29yID0+IHtcbiAgICAgIGNvbnN0IHhzaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICAgICAgY29uc3Qga3NoYXBlID0gaW5wdXRzWzFdLmRpbXM7XG4gICAgICBjb25zdCBvdXRwdXRTaGFwZSA9XG4gICAgICAgICAgY2FsY3VsYXRlT3V0cHV0U2hhcGUoeHNoYXBlLCBrc2hhcGUsIGF0dHJpYnV0ZXMuZGlsYXRpb25zLCBhdHRyaWJ1dGVzLnBhZHMsIGF0dHJpYnV0ZXMuc3RyaWRlcyk7XG5cbiAgICAgIC8vIHJ1biBpbTJjb2xcbiAgICAgIGNvbnN0IGltMmNvbE91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgIGNyZWF0ZVBhY2tlZEltMkNvbFByb2dyYW1JbmZvTG9hZGVyKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0c1swXSwgaW5wdXRzWzFdLCBvdXRwdXRTaGFwZSwgYXR0cmlidXRlcyksXG4gICAgICAgICAgW2lucHV0c1swXV0pO1xuXG4gICAgICAvLyByZXNoYXBlIGtlcm5lbFxuICAgICAgY29uc3Qga2VybmVsUmVzaGFwZWQgPSBpbmZlcmVuY2VIYW5kbGVyLnJlc2hhcGVQYWNrZWQoaW5wdXRzWzFdLCBba3NoYXBlWzBdLCBrc2hhcGVbMV0gKiBrc2hhcGVbMl0gKiBrc2hhcGVbM11dKTtcblxuICAgICAgLy8gcnVuIG1hdG11bFxuICAgICAgY29uc3QgbWF0bXVsSW5wdXRzID1cbiAgICAgICAgICAoaW5wdXRzLmxlbmd0aCA9PT0gMykgPyBba2VybmVsUmVzaGFwZWQsIGltMmNvbE91dHB1dCwgaW5wdXRzWzJdXSA6IFtrZXJuZWxSZXNoYXBlZCwgaW0yY29sT3V0cHV0XTtcbiAgICAgIGNvbnN0IG1hdG11bE91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgIGNyZWF0ZVBhY2tlZE1hdG11bFByb2dyYW1JbmZvTG9hZGVyKGluZmVyZW5jZUhhbmRsZXIsIG1hdG11bElucHV0cywgYXR0cmlidXRlcyksIG1hdG11bElucHV0cyk7XG5cbiAgICAgIC8vIHJlc2hhcGUgb3V0cHV0XG4gICAgICBjb25zdCBvdXRwdXRSZXNoYXBlZCA9IGluZmVyZW5jZUhhbmRsZXIucmVzaGFwZVBhY2tlZChtYXRtdWxPdXRwdXQsIG91dHB1dFNoYXBlKTtcbiAgICAgIHJldHVybiBvdXRwdXRSZXNoYXBlZDtcbiAgICB9O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7Y3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi8uLi8uLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi8uLi8uLi9iYWNrZW5kJztcbmltcG9ydCB7R3JhcGh9IGZyb20gJy4uLy4uLy4uL2dyYXBoJztcbmltcG9ydCB7T3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi4vLi4vLi4vb3BlcmF0b3JzJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtnZXRHbHNsfSBmcm9tICcuLi9nbHNsLXNvdXJjZSc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgUHJvZ3JhbUluZm9Mb2FkZXIsIFByb2dyYW1NZXRhZGF0YSwgVGV4dHVyZVR5cGV9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtDb252QXR0cmlidXRlc30gZnJvbSAnLi9jb252JztcbmltcG9ydCB7Z2V0QWN0aXZhdGlvblNuaXBwZXQsIHBhcnNlSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlc30gZnJvbSAnLi9mdXNlLXV0aWxzJztcblxuY29uc3QgY29tcHV0ZVRvdGFsUGFkID1cbiAgICAoaW5EaW06IG51bWJlciwgc3RyaWRlOiBudW1iZXIsIGFkajogbnVtYmVyLCBrZXJuZWw6IG51bWJlciwgZGlsYXRpb246IG51bWJlciwgb3V0U2l6ZTogbnVtYmVyKSA9PlxuICAgICAgICAoaW5EaW0gLSAxKSAqIHN0cmlkZSArIGFkaiArIChrZXJuZWwgLSAxKSAqIGRpbGF0aW9uICsgMSAtIG91dFNpemU7XG5cbmNvbnN0IGRpc3RyaWJ1dGVQYWRkaW5nID0gKHRvdGFsUGFkOiBudW1iZXIsIGF1dG9QYWQ6IHN0cmluZywgcGFkczogbnVtYmVyW10sIGhlYWQ6IG51bWJlciwgdGFpbDogbnVtYmVyKSA9PiB7XG4gIGNvbnN0IHNtYWxsUGFkID0gTWF0aC5mbG9vcih0b3RhbFBhZCAvIDIpO1xuICBpZiAoYXV0b1BhZCA9PT0gJ1NBTUVfVVBQRVInKSB7XG4gICAgcGFkc1toZWFkXSA9IHNtYWxsUGFkO1xuICAgIHBhZHNbdGFpbF0gPSB0b3RhbFBhZCAtIHNtYWxsUGFkO1xuICB9IGVsc2UgaWYgKGF1dG9QYWQgPT09ICdTQU1FX0xPV0VSJykge1xuICAgIHBhZHNbaGVhZF0gPSB0b3RhbFBhZCAtIHNtYWxsUGFkO1xuICAgIHBhZHNbdGFpbF0gPSBzbWFsbFBhZDtcbiAgfVxufTtcblxuY29uc3QgY2FsY3VsYXRlT3V0cHV0U2hhcGVBbmRQYWRzID1cbiAgICAoaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIGtlcm5lbFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgZGlsYXRpb25zOiByZWFkb25seSBudW1iZXJbXSwgYXV0b1BhZDogc3RyaW5nLFxuICAgICBwYWRzOiBudW1iZXJbXSwgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW10sIG91dHB1dFBhZGRpbmc6IHJlYWRvbmx5IG51bWJlcltdLCBvdXRwdXRTaGFwZTogbnVtYmVyW10pID0+IHtcbiAgICAgIGNvbnN0IHNwYXRpYWxSYW5rID0gaW5wdXRTaGFwZS5sZW5ndGggLSAyO1xuICAgICAgY29uc3QgdXBkYXRlU2hhcGUgPSBvdXRwdXRTaGFwZS5sZW5ndGggPT09IDA7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNwYXRpYWxSYW5rOyArK2kpIHtcbiAgICAgICAgY29uc3Qgb3V0U2l6ZSA9IHVwZGF0ZVNoYXBlID8gaW5wdXRTaGFwZVtpICsgMl0gKiBzdHJpZGVzW2ldIDogb3V0cHV0U2hhcGVbaV07XG4gICAgICAgIGNvbnN0IHRvdGFsUGFkID0gY29tcHV0ZVRvdGFsUGFkKGlucHV0U2hhcGVbaSArIDJdLCBzdHJpZGVzW2ldLCBwYWRzW2ldLCBrZXJuZWxTaGFwZVtpXSwgZGlsYXRpb25zW2ldLCBvdXRTaXplKTtcbiAgICAgICAgZGlzdHJpYnV0ZVBhZGRpbmcodG90YWxQYWQsIGF1dG9QYWQsIHBhZHMsIGksIGkgKyBzcGF0aWFsUmFuayk7XG4gICAgICAgIGlmICh1cGRhdGVTaGFwZSkge1xuICAgICAgICAgIG91dHB1dFNoYXBlLnB1c2goXG4gICAgICAgICAgICAgIHN0cmlkZXNbaV0gKiAoaW5wdXRTaGFwZVtpICsgMl0gLSAxKSArIG91dHB1dFBhZGRpbmdbaV0gKyAoa2VybmVsU2hhcGVbaV0gLSAxKSAqIGRpbGF0aW9uc1tpXSArIDEgLVxuICAgICAgICAgICAgICBwYWRzW2ldIC0gcGFkc1tpICsgc3BhdGlhbFJhbmtdKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMgZXh0ZW5kcyBDb252QXR0cmlidXRlcyB7XG4gIHJlYWRvbmx5IG91dHB1dFBhZGRpbmc6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW107XG59XG5cbmV4cG9ydCBjb25zdCBjb252VHJhbnNwb3NlOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzLCBhdHRyaWJ1dGVzKTsgIC8vIGN1cnJlbnRseSB3aWxsIGZhaWwgaWYgbm90IGNvbnZUcmFuc3Bvc2UyRFxuICAgICAgcmV0dXJuIGNvbnZUcmFuc3Bvc2UyZChpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICAgIH07XG5cbmNvbnN0IGNvbnZUcmFuc3Bvc2UyZDogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxDb252VHJhbnNwb3NlQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IENvbnZUcmFuc3Bvc2VBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgY29uc3QgYWRqdXN0ZWRBdHRyaWJ1dGVzID0gZ2V0QWRqdXN0ZWRDb252VHJhbnNwb3NlQXR0cmlidXRlcyhhdHRyaWJ1dGVzLCBpbnB1dHMpO1xuICAgICAgcmV0dXJuIFtjb252VHJhbnNwb3NlMkRVbnBhY2tlZChpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIGFkanVzdGVkQXR0cmlidXRlcyldO1xuICAgIH07XG5cbmNvbnN0IGNyZWF0ZUNvbnZUcmFuc3Bvc2VQcm9ncmFtTWV0YWRhdGEgPSAoaGFzQmlhczogYm9vbGVhbiwgY2FjaGVIaW50OiBzdHJpbmcpID0+ICh7XG4gIG5hbWU6ICdDb252VHJhbnNwb3NlJyxcbiAgaW5wdXROYW1lczogaGFzQmlhcyA/IFsnWCcsICdXJywgJ0InXSA6IFsnWCcsICdXJ10sXG4gIGlucHV0VHlwZXM6IGhhc0JpYXMgPyBbVGV4dHVyZVR5cGUudW5wYWNrZWQsIFRleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS51bnBhY2tlZF0gOlxuICAgICAgICAgICAgICAgICAgICAgICAgW1RleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS51bnBhY2tlZF0sXG4gIGNhY2hlSGludFxufSk7XG5cbmNvbnN0IGNyZWF0ZVVucGFja2VkQ29udlRyYW5zcG9zZVByb2dyYW1JbmZvID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvcltdLCBtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhLFxuICAgICBhdHRyaWJ1dGVzOiBDb252VHJhbnNwb3NlQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IGhhc0JpYXMgPSBpbnB1dHMubGVuZ3RoID4gMjtcbiAgICAgIGNvbnN0IHZhbHVlSW5pdCA9IGhhc0JpYXMgPyAnZ2V0QihvdXRwdXRfY2hhbm5lbCknIDogJzAuMCc7XG4gICAgICBjb25zdCB4U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgICAgIGNvbnN0IHdTaGFwZSA9IGlucHV0c1sxXS5kaW1zO1xuICAgICAgY29uc3Qgb3V0cHV0Q2hhbm5lbHNQZXJHcm91cCA9IHdTaGFwZVsxXTtcbiAgICAgIGNvbnN0IGlucHV0Q2hhbm5lbHNQZXJHcm91cCA9IHdTaGFwZVswXSAvIGF0dHJpYnV0ZXMuZ3JvdXA7XG4gICAgICBjb25zdCBvdXRwdXRTaGFwZSA9IFtpbnB1dHNbMF0uZGltc1swXSwgaW5wdXRzWzFdLmRpbXNbMV0gKiBhdHRyaWJ1dGVzLmdyb3VwLCAuLi5hdHRyaWJ1dGVzLm91dHB1dFNoYXBlXTtcbiAgICAgIGNvbnN0IGdsc2wgPSBnZXRHbHNsKGluZmVyZW5jZUhhbmRsZXIuc2Vzc2lvbi5iYWNrZW5kLmdsQ29udGV4dC52ZXJzaW9uKTtcbiAgICAgIGNvbnN0IHthY3RpdmF0aW9uRnVuY3Rpb24sIGFwcGx5QWN0aXZhdGlvbn0gPSBnZXRBY3RpdmF0aW9uU25pcHBldChhdHRyaWJ1dGVzKTtcblxuICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICBjb25zdCBpdmVjMiBzdHJpZGVzID0gaXZlYzIoJHthdHRyaWJ1dGVzLnN0cmlkZXNbMF19LCAke2F0dHJpYnV0ZXMuc3RyaWRlc1sxXX0pO1xuICBjb25zdCBpdmVjMiBwYWRzID0gaXZlYzIoJHthdHRyaWJ1dGVzLnBhZHNbMF19LCAke2F0dHJpYnV0ZXMucGFkc1sxXX0pO1xuICAke2FjdGl2YXRpb25GdW5jdGlvbn1cbiAgdm9pZCBtYWluKCkge1xuICAgIGl2ZWM0IGNvb3JkcyA9IGdldE91dHB1dENvb3JkcygpO1xuICAgIGludCBiYXRjaCA9IGNvb3Jkcy54O1xuICAgIGludCBvdXRwdXRfY2hhbm5lbCA9IGNvb3Jkcy55O1xuXG4gICAgaXZlYzIgbG9jID0gY29vcmRzLnp3ICsgcGFkcztcblxuICAgIGludCBncm91cF9pZCA9IG91dHB1dF9jaGFubmVsIC8gJHtvdXRwdXRDaGFubmVsc1Blckdyb3VwfTtcbiAgICBpbnQgd091dENoYW5uZWwgPSBvdXRwdXRfY2hhbm5lbCAtIGdyb3VwX2lkICogJHtvdXRwdXRDaGFubmVsc1Blckdyb3VwfTtcblxuICAgIGZsb2F0IHZhbHVlID0gJHt2YWx1ZUluaXR9O1xuICAgIGZvciAoaW50IGluQ2hhbm5lbE9mZnNldCA9IDA7IGluQ2hhbm5lbE9mZnNldCA8ICR7aW5wdXRDaGFubmVsc1Blckdyb3VwfTsgaW5DaGFubmVsT2Zmc2V0KyspIHtcbiAgICAgIGludCBpbnB1dF9jaGFubmVsID0gZ3JvdXBfaWQgKiAke2lucHV0Q2hhbm5lbHNQZXJHcm91cH0gKyBpbkNoYW5uZWxPZmZzZXQ7XG4gICAgICBmb3IgKGludCB3V09mZiA9IDA7IHdXT2ZmIDwgJHt3U2hhcGVbMl19OyB3V09mZisrKSB7XG4gICAgICAgIGZvciAoaW50IHdIT2ZmID0gMDsgd0hPZmYgPCAke3dTaGFwZVszXX07IHdIT2ZmKyspIHtcbiAgICAgICAgICBpdmVjMiB3T2ZmID0gaXZlYzIod1dPZmYgKiAke2F0dHJpYnV0ZXMuZGlsYXRpb25zWzBdfSwgd0hPZmYgKiAke2F0dHJpYnV0ZXMuZGlsYXRpb25zWzFdfSk7XG4gICAgICAgICAgaXZlYzIgd0xvYyA9IGxvYyAtIHdPZmY7XG4gICAgICAgICAgaXZlYzIgd0xvY0luID0gd0xvYyAvIHN0cmlkZXM7XG4gICAgICAgICAgaWYgKFxuICAgICAgICAgICAgd0xvY0luICogc3RyaWRlcyA9PSB3TG9jICYmXG4gICAgICAgICAgICB3TG9jSW4ueCA+PSAwICYmIHdMb2NJbi54IDwgJHt4U2hhcGVbMl19ICYmXG4gICAgICAgICAgICB3TG9jSW4ueSA+PSAwICYmIHdMb2NJbi55IDwgJHt4U2hhcGVbM119XG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBmbG9hdCB4VmFsID0gZ2V0WChiYXRjaCwgaW5wdXRfY2hhbm5lbCwgd0xvY0luLnksIHdMb2NJbi54KTtcbiAgICAgICAgICAgIGZsb2F0IHdWYWwgPSBnZXRXKGlucHV0X2NoYW5uZWwsIHdPdXRDaGFubmVsLCB3SE9mZiwgd1dPZmYpO1xuICAgICAgICAgICAgdmFsdWUgKz0geFZhbCAqIHdWYWw7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgICR7YXBwbHlBY3RpdmF0aW9ufVxuICAgICR7Z2xzbC5vdXRwdXR9ID0gdmVjNCh2YWx1ZSwgLjAsIC4wLCAuMCk7XG4gIH1cbmA7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgb3V0cHV0OiB7ZGltczogb3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0c1swXS50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUudW5wYWNrZWR9LFxuICAgICAgICBzaGFkZXJTb3VyY2UsXG4gICAgICAgIGhhc01haW46IHRydWUsXG4gICAgICB9O1xuICAgIH07XG5cbmNvbnN0IGNyZWF0ZVVucGFja2VkQ29udlRyYW5zcG9zZVByb2dyYW1JbmZvTG9hZGVyID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBDb252VHJhbnNwb3NlQXR0cmlidXRlcyk6XG4gICAgICAgIFByb2dyYW1JbmZvTG9hZGVyID0+IHtcbiAgICAgICAgICBjb25zdCBtZXRhZGF0YSA9IGNyZWF0ZUNvbnZUcmFuc3Bvc2VQcm9ncmFtTWV0YWRhdGEoaW5wdXRzLmxlbmd0aCA+IDIsIGF0dHJpYnV0ZXMuY2FjaGVLZXkpO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgICAgIGdldDogKCkgPT4gY3JlYXRlVW5wYWNrZWRDb252VHJhbnNwb3NlUHJvZ3JhbUluZm8oaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBtZXRhZGF0YSwgYXR0cmlidXRlcylcbiAgICAgICAgICB9O1xuICAgICAgICB9O1xuXG5cbmNvbnN0IGNvbnZUcmFuc3Bvc2UyRFVucGFja2VkID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBDb252VHJhbnNwb3NlQXR0cmlidXRlcyk6XG4gICAgICAgIFRlbnNvciA9PiB7XG4gICAgICAgICAgY29uc3QgcmVzdWx0ID0gaW5mZXJlbmNlSGFuZGxlci5ydW4oXG4gICAgICAgICAgICAgIGNyZWF0ZVVucGFja2VkQ29udlRyYW5zcG9zZVByb2dyYW1JbmZvTG9hZGVyKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYXR0cmlidXRlcyksIGlucHV0cyk7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfTtcblxuY29uc3QgZ2V0QWRqdXN0ZWRDb252VHJhbnNwb3NlQXR0cmlidXRlcyA9IDxUIGV4dGVuZHMgQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXM+KGF0dHJpYnV0ZXM6IFQsIGlucHV0czogVGVuc29yW10pOiBUID0+IHtcbiAgY29uc3Qga2VybmVsU2hhcGUgPSBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLnNsaWNlKCk7XG4gIC8vIGlmIGtlcm5lbFNoYXBlIGlzIG5vdCBzcGVjaWZpZWQgaW4gdGhlIGF0dHJpYnV0ZXMgb2YgdGhpcyBvcCwgaW5mZXIgaXQgZnJvbSB0aGUgd2VpZ2h0IHRlbnNvciBkaW1zXG4gIGlmIChhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCA9PT0gMCkge1xuICAgIGZvciAobGV0IGkgPSAyOyBpIDwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIGtlcm5lbFNoYXBlLnB1c2goaW5wdXRzWzFdLmRpbXNbaV0pO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHBhZHMgPSBhdHRyaWJ1dGVzLnBhZHMuc2xpY2UoKTtcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBhdHRyaWJ1dGVzLm91dHB1dFNoYXBlLnNsaWNlKCk7XG4gIGNvbnN0IGlucHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgLy8gSWYgb3V0cHV0U2hhcGUgaXMgbm90IHNwZWNpZmllZCBpbiB0aGUgYXR0cmlidXRlcyBvZiB0aGlzIG9wLCBpbmZlciBpdCBmcm9tIHRoZSBwYXJhbWV0ZXJzXG4gIC8vIFNpbWlsYXJseSwgYXV0b21hdGljYWxseSBpbmZlciBwYWRzIGlmIG5vdCBzcGVjaWZpZWRcbiAgY2FsY3VsYXRlT3V0cHV0U2hhcGVBbmRQYWRzKFxuICAgICAgaW5wdXRTaGFwZSwga2VybmVsU2hhcGUsIGF0dHJpYnV0ZXMuZGlsYXRpb25zLCBhdHRyaWJ1dGVzLmF1dG9QYWQsIHBhZHMsIGF0dHJpYnV0ZXMuc3RyaWRlcyxcbiAgICAgIGF0dHJpYnV0ZXMub3V0cHV0UGFkZGluZywgb3V0cHV0U2hhcGUpO1xuXG4gIC8vIGFsd2F5cyByZXR1cm4gYSBuZXcgb2JqZWN0IHNvIGRvZXMgbm90IG1vZGlmeSB0aGUgb3JpZ2luYWwgYXR0cmlidXRlc1xuICBjb25zdCBuZXdBdHRyaWJ1dGVzOiBUID0gT2JqZWN0LmFzc2lnbih7fSwgYXR0cmlidXRlcyk7XG4gIE9iamVjdC5hc3NpZ24obmV3QXR0cmlidXRlcywge2tlcm5lbFNoYXBlLCBwYWRzLCBvdXRwdXRTaGFwZSwgY2FjaGVLZXk6IGF0dHJpYnV0ZXMuY2FjaGVLZXl9KTtcbiAgcmV0dXJuIG5ld0F0dHJpYnV0ZXM7XG59O1xuXG5leHBvcnQgY29uc3QgcGFyc2VDb252VHJhbnNwb3NlQXR0cmlidXRlczogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxDb252VHJhbnNwb3NlQXR0cmlidXRlcz4gPVxuICAgIChub2RlOiBHcmFwaC5Ob2RlKTogQ29udlRyYW5zcG9zZUF0dHJpYnV0ZXMgPT4ge1xuICAgICAgY29uc3QgYXR0cmlidXRlcyA9IG5vZGUuYXR0cmlidXRlcztcbiAgICAgIGNvbnN0IGFjdGl2YXRpb25BdHRyaWJ1dGVzID0gcGFyc2VJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzKGF0dHJpYnV0ZXMpO1xuICAgICAgLy8gVE9ETyA6IE1ha2UgdGhpcyBnZW5lcmljIGVub3VnaCB0byBjb21wdXRlIGRlZmF1bHQgYXR0cmlidXRlcyBmb3IgbXVsdGktZGltZW5zaW9uYWwgY29udlxuICAgICAgY29uc3QgYXV0b1BhZCA9IGF0dHJpYnV0ZXMuZ2V0U3RyaW5nKCdhdXRvX3BhZCcsICdOT1RTRVQnKTtcbiAgICAgIGNvbnN0IGRpbGF0aW9ucyA9IGF0dHJpYnV0ZXMuZ2V0SW50cygnZGlsYXRpb25zJywgWzEsIDFdKTtcbiAgICAgIGNvbnN0IGdyb3VwID0gYXR0cmlidXRlcy5nZXRJbnQoJ2dyb3VwJywgMSk7XG4gICAgICBjb25zdCBrZXJuZWxTaGFwZSA9IGF0dHJpYnV0ZXMuZ2V0SW50cygna2VybmVsX3NoYXBlJywgW10pO1xuICAgICAgY29uc3Qgb3V0cHV0UGFkZGluZyA9IGF0dHJpYnV0ZXMuZ2V0SW50cygnb3V0cHV0X3BhZGRpbmcnLCBbMCwgMF0pO1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBhdHRyaWJ1dGVzLmdldEludHMoJ291dHB1dF9zaGFwZScsIFtdKTtcbiAgICAgIGNvbnN0IHBhZHMgPSBhdHRyaWJ1dGVzLmdldEludHMoJ3BhZHMnLCBbMCwgMCwgMCwgMF0pO1xuICAgICAgY29uc3Qgc3RyaWRlcyA9IGF0dHJpYnV0ZXMuZ2V0SW50cygnc3RyaWRlcycsIFsxLCAxXSk7XG5cbiAgICAgIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoXG4gICAgICAgICAge2F1dG9QYWQsIGRpbGF0aW9ucywgZ3JvdXAsIGtlcm5lbFNoYXBlLCBvdXRwdXRQYWRkaW5nLCBvdXRwdXRTaGFwZSwgcGFkcywgc3RyaWRlcywgLi4uYWN0aXZhdGlvbkF0dHJpYnV0ZXN9KTtcbiAgICB9O1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBDb252VHJhbnNwb3NlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICAvLyBSZWZlciB0byB0aGUgYmVsb3cgbGluayBmb3IgYWxsIGlucHV0IGNoZWNrc1xuICAvLyBodHRwczovL2dpdGh1Yi5jb20vb25ueC9vbm54L2Jsb2IvbWFpbi9kb2NzL09wZXJhdG9ycy5tZCNDb252XG4gIGlmICghaW5wdXRzIHx8IChpbnB1dHMubGVuZ3RoICE9PSAyICYmIGlucHV0cy5sZW5ndGggIT09IDMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDb252IHJlcXVpcmVzIDIgb3IgMyBpbnB1dHMnKTtcbiAgfVxuXG4gIC8vIFRPRE8gOiBOZWVkIHRvIGFkZCBzdXBwb3J0IGZvciBtdWx0aS1kaW1lbnNpb25hbCBjb252XG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IDQgfHwgaW5wdXRzWzFdLmRpbXMubGVuZ3RoICE9PSA0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjdXJyZW50bHkgb25seSBzdXBwb3J0IDItZGltZW5zaW9uYWwgY29udicpO1xuICB9XG5cbiAgLy8gRklMVEVSX0lOX0NIQU5ORUwgc2hvdWxkIGJlIGVxdWFsIHRvIERBVEFfQ0hBTk5FTFxuICBjb25zdCBkYXRhQ2hhbm5lbCA9IGlucHV0c1swXS5kaW1zWzFdO1xuICBjb25zdCBmaWx0ZXJJbkNoYW5uZWwgPSBpbnB1dHNbMV0uZGltc1swXTtcbiAgaWYgKGRhdGFDaGFubmVsICE9PSBmaWx0ZXJJbkNoYW5uZWwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZJTFRFUl9JTl9DSEFOTkVMIHNob3VsZCBiZSBlcXVhbCB0byBEQVRBX0NIQU5ORUwnKTtcbiAgfVxuXG4gIGNvbnN0IGZlYXR1cmVNYXBzID0gaW5wdXRzWzFdLmRpbXNbMV0gKiBhdHRyaWJ1dGVzLmdyb3VwO1xuXG4gIC8vIGlmIGJpYXMgaXMgcHJvdmlkZWQgaXQgc2hvdWxkIGJlIDFEIGFuZCB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIHNob3VsZCBiZSBlcXVhbCB0byB0aGUgbnVtYmVyIG9mIGZlYXR1cmUgbWFwc1xuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiAoaW5wdXRzWzJdLmRpbXMubGVuZ3RoICE9PSAxIHx8IGlucHV0c1syXS5kaW1zWzBdICE9PSBmZWF0dXJlTWFwcykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgYmlhcycpO1xuICB9XG5cbiAgY29uc3Qgc3BhdGlhbFJhbmsgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAyO1xuICAvLyB3cm9uZyBkaWxhdGlvbnMgZGltZW5zaW9uXG4gIGlmIChhdHRyaWJ1dGVzLmRpbGF0aW9ucy5sZW5ndGggIT09IHNwYXRpYWxSYW5rKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBkaWxhdGlvbnMgc2hvdWxkIGJlICR7c3BhdGlhbFJhbmt9RGApO1xuICB9XG5cbiAgLy8gV3Jvbmcgc3RyaWRlcyBkaW1lbnNpb25cbiAgaWYgKGF0dHJpYnV0ZXMuc3RyaWRlcy5sZW5ndGggIT09IHNwYXRpYWxSYW5rKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBzdHJpZGVzIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rfURgKTtcbiAgfVxuXG4gIC8vIFdyb25nIHBhZHMgZGltZW5zaW9uXG4gIGlmIChhdHRyaWJ1dGVzLnBhZHMubGVuZ3RoICE9PSBzcGF0aWFsUmFuayAqIDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHBhZHMgc2hvdWxkIGJlICR7c3BhdGlhbFJhbmsgKiAyfURgKTtcbiAgfVxuXG4gIC8vIFdyb25nIG91dHB1dCBwYWRkaW5nIGRpbWVuc2lvblxuICBpZiAoYXR0cmlidXRlcy5vdXRwdXRQYWRkaW5nLmxlbmd0aCAhPT0gc3BhdGlhbFJhbmspIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYG91dHB1dF9wYWRkaW5nIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rfURgKTtcbiAgfVxuXG4gIC8vIGlmIGtlcm5lbFNoYXBlIGlzIHNwZWNpZmllZCwgaXQncyBkYXRhIGxlbmd0aCBtdXN0IGJlIDIgbGVzcyB0aGFuIGRpbXMgbGVuZ3RoIG9mIHRoZSB3ZWlnaHRzIHRlbnNvclxuICAvLyAodGhlIGZpcnN0IDIgZGltcyBhcmUgYmF0Y2hfc2l6ZSBhbmQgY2hhbm5lbHMpXG4gIGlmIChhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCAhPT0gMCAmJiBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCAhPT0gaW5wdXRzWzFdLmRpbXMubGVuZ3RoIC0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBrZXJuZWwgc2hhcGUnKTtcbiAgfVxuXG4gIC8vIGFzIHdpdGgga2VybmVsU2hhcGUsIG11c3QgaGF2ZSBzYW1lIG51bWJlciBvZiBzcGF0aWFsIGRpbXMgYXMgaW5wdXRcbiAgaWYgKGF0dHJpYnV0ZXMub3V0cHV0U2hhcGUubGVuZ3RoICE9PSAwICYmIGF0dHJpYnV0ZXMub3V0cHV0U2hhcGUubGVuZ3RoICE9PSBpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIG91dHB1dCBzaGFwZScpO1xuICB9XG5cbiAgLy8gVE9ETyA6IE5lZWQgdG8gYWRkIHN1cHBvcnQgZm9yIGZsb2F0NjRcbiAgaWYgKGlucHV0c1swXS50eXBlICE9PSAnZmxvYXQzMicgfHwgaW5wdXRzWzFdLnR5cGUgIT09ICdmbG9hdDMyJykge1xuICAgIHRocm93IG5ldyBFcnJvcignQ29udlRyYW5zcG9zZSBpbnB1dChYLFcpIHNob3VsZCBiZSBmbG9hdCB0ZW5zb3InKTtcbiAgfVxuXG4gIGlmIChpbnB1dHMubGVuZ3RoID09PSAzICYmIGlucHV0c1syXS50eXBlICE9PSAnZmxvYXQzMicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbnZUcmFuc3Bvc2UgaW5wdXQoYmlhcykgc2hvdWxkIGJlIGZsb2F0IHRlbnNvcicpO1xuICB9XG59O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7QXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXl9IGZyb20gJy4uLy4uLy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQge0luZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uLy4uLy4uL2JhY2tlbmQnO1xuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1Bvb2xDb252VXRpbH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuXG5pbXBvcnQge2NyZWF0ZVVucGFja2VkR3JvdXBlZENvbnZQcm9ncmFtSW5mb0xvYWRlcn0gZnJvbSAnLi9jb252LWdyb3VwZWQnO1xuaW1wb3J0IHtjb252MkRQYWNrZWR9IGZyb20gJy4vY29udi1wYWNrJztcbmltcG9ydCB7Y3JlYXRlRG90UHJvZHVjdFByb2dyYW1JbmZvTG9hZGVyfSBmcm9tICcuL2RvdC1wcm9kdWN0JztcbmltcG9ydCB7SW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcywgcGFyc2VJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzfSBmcm9tICcuL2Z1c2UtdXRpbHMnO1xuaW1wb3J0IHtjcmVhdGVJbTJDb2xQcm9ncmFtSW5mb0xvYWRlcn0gZnJvbSAnLi9pbTJjb2wnO1xuaW1wb3J0IHtjcmVhdGVNYXRtdWxQcm9ncmFtSW5mb0xvYWRlcn0gZnJvbSAnLi9tYXRtdWwnO1xuXG5cbmV4cG9ydCBjb25zdCBjYWxjdWxhdGVPdXRwdXRTaGFwZSA9XG4gICAgKGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIGRpbGF0aW9uczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgIGFkanVzdFBhZHM6IHJlYWRvbmx5IG51bWJlcltdLCBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXSk6IG51bWJlcltdID0+IHtcbiAgICAgIGNvbnN0IGJhdGNoU2l6ZSA9IGlucHV0U2hhcGVbMF07XG4gICAgICBjb25zdCBpbnB1dFNwYXRpYWxTaGFwZSA9IGlucHV0U2hhcGUuc2xpY2UoMik7XG4gICAgICBjb25zdCBzcGF0aWFsUmFuayA9IGlucHV0U3BhdGlhbFNoYXBlLmxlbmd0aDtcbiAgICAgIGNvbnN0IG91dENoYW5uZWxzID0ga2VybmVsU2hhcGVbMF07XG4gICAgICBjb25zdCBrZXJuZWxTcGF0aWFsU2hhcGUgPSBrZXJuZWxTaGFwZS5zbGljZSgyKTtcbiAgICAgIGNvbnN0IGRpbGF0ZWRLZXJuZWxTaGFwZSA9IGtlcm5lbFNwYXRpYWxTaGFwZS5tYXAoKHYsIGkpID0+IHYgKyAodiAtIDEpICogKGRpbGF0aW9uc1tpXSAtIDEpKTtcbiAgICAgIGNvbnN0IGlucHV0U3BhdGlhbFNoYXBlV2l0aFBhZCA9IGlucHV0U3BhdGlhbFNoYXBlLm1hcCgodiwgaSkgPT4gdiArIGFkanVzdFBhZHNbaV0gKyBhZGp1c3RQYWRzW2kgKyBzcGF0aWFsUmFua10pO1xuICAgICAgY29uc3Qgb3V0cHV0U3BhdGlhbFNoYXBlID1cbiAgICAgICAgICBpbnB1dFNwYXRpYWxTaGFwZVdpdGhQYWQubWFwKCh2LCBpKSA9PiBNYXRoLmZsb29yKCh2IC0gZGlsYXRlZEtlcm5lbFNoYXBlW2ldICsgc3RyaWRlc1tpXSkgLyBzdHJpZGVzW2ldKSk7XG4gICAgICBjb25zdCBvdXRwdXRTaGFwZSA9IFtiYXRjaFNpemUsIG91dENoYW5uZWxzXS5jb25jYXQoLi4ub3V0cHV0U3BhdGlhbFNoYXBlKTtcbiAgICAgIHJldHVybiBvdXRwdXRTaGFwZTtcbiAgICB9O1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbnZBdHRyaWJ1dGVzIGV4dGVuZHMgSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcywgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgYXV0b1BhZDogc3RyaW5nO1xuICByZWFkb25seSBkaWxhdGlvbnM6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSBncm91cDogbnVtYmVyO1xuICByZWFkb25seSBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW107XG4gIHJlYWRvbmx5IHBhZHM6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXTtcbn1cblxuZXhwb3J0IGNvbnN0IGNvbnY6IE9wZXJhdG9ySW1wbGVtZW50YXRpb248Q29udkF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMsIGF0dHJpYnV0ZXMpOyAgLy8gY3VycmVudGx5IHdpbGwgZmFpbCBpZiBub3QgY29udjJEXG4gICAgICByZXR1cm4gY29udjJkKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYXR0cmlidXRlcyk7XG4gICAgfTtcblxuY29uc3QgY29udjJkOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPENvbnZBdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICBjb25zdCBhZGp1c3RlZEF0dHJpYnV0ZXMgPSBnZXRBZGp1c3RlZENvbnZBdHRyaWJ1dGVzKGF0dHJpYnV0ZXMsIGlucHV0cyk7XG4gICAgICBjb25zdCBwYWNrTW9kZSA9IGluZmVyZW5jZUhhbmRsZXIuc2Vzc2lvbi5wYWNrO1xuICAgICAgY29uc3QgaXNQb2ludHdpc2UgPSBhZGp1c3RlZEF0dHJpYnV0ZXMua2VybmVsU2hhcGVbMF0gPT09IDEgJiYgYWRqdXN0ZWRBdHRyaWJ1dGVzLmtlcm5lbFNoYXBlWzFdID09PSAxO1xuICAgICAgaWYgKGFkanVzdGVkQXR0cmlidXRlcy5ncm91cCA+IDEpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gaW5mZXJlbmNlSGFuZGxlci5ydW4oXG4gICAgICAgICAgICBjcmVhdGVVbnBhY2tlZEdyb3VwZWRDb252UHJvZ3JhbUluZm9Mb2FkZXIoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhZGp1c3RlZEF0dHJpYnV0ZXMpLCBpbnB1dHMpO1xuICAgICAgICByZXR1cm4gW3Jlc3VsdF07XG4gICAgICB9IGVsc2UgaWYgKGlzUG9pbnR3aXNlICYmIHBhY2tNb2RlKSB7XG4gICAgICAgIHJldHVybiBbY29udjJEVW5wYWNrZWRQb2ludHdpc2UoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhZGp1c3RlZEF0dHJpYnV0ZXMpXTtcbiAgICAgIH0gZWxzZSBpZiAocGFja01vZGUgJiYgaW5wdXRzWzBdLmRpbXMubGVuZ3RoID09PSA0ICYmIGlucHV0c1swXS5kaW1zWzBdID09PSAxICYmICFpc1BvaW50d2lzZSkge1xuICAgICAgICByZXR1cm4gW2NvbnYyRFBhY2tlZChpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIGFkanVzdGVkQXR0cmlidXRlcyldO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFtjb252MkRVbnBhY2tlZChpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIGFkanVzdGVkQXR0cmlidXRlcyldO1xuICAgICAgfVxuICAgIH07XG5cbmNvbnN0IGNvbnYyRFVucGFja2VkUG9pbnR3aXNlID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6IFRlbnNvciA9PiB7XG4gICAgICBjb25zdCB4c2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgICAgIGNvbnN0IGtzaGFwZSA9IGlucHV0c1sxXS5kaW1zO1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPVxuICAgICAgICAgIGNhbGN1bGF0ZU91dHB1dFNoYXBlKHhzaGFwZSwga3NoYXBlLCBhdHRyaWJ1dGVzLmRpbGF0aW9ucywgYXR0cmlidXRlcy5wYWRzLCBhdHRyaWJ1dGVzLnN0cmlkZXMpO1xuICAgICAgY29uc3QgcmVzaGFwZWRYID0gaW5mZXJlbmNlSGFuZGxlci5yZXNoYXBlVW5wYWNrZWQoaW5wdXRzWzBdLCBbeHNoYXBlWzFdLCB4c2hhcGVbMl0gKiB4c2hhcGVbM11dKTtcbiAgICAgIGNvbnN0IHJlc2hhcGVkSyA9IGluZmVyZW5jZUhhbmRsZXIucmVzaGFwZVVucGFja2VkKGlucHV0c1sxXSwgW2tzaGFwZVswXSwga3NoYXBlWzFdXSk7XG5cbiAgICAgIGNvbnN0IG1hdG11bElucHV0cyA9IGlucHV0cy5sZW5ndGggPiAyID8gW3Jlc2hhcGVkSywgcmVzaGFwZWRYLCBpbnB1dHNbMl1dIDogW3Jlc2hhcGVkSywgcmVzaGFwZWRYXTtcbiAgICAgIGNvbnN0IG1hdG11bE91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKGNyZWF0ZU1hdG11bFByb2dyYW1JbmZvTG9hZGVyKG1hdG11bElucHV0cywgYXR0cmlidXRlcyksIG1hdG11bElucHV0cyk7XG4gICAgICByZXR1cm4gaW5mZXJlbmNlSGFuZGxlci5yZXNoYXBlVW5wYWNrZWQobWF0bXVsT3V0cHV0LCBvdXRwdXRTaGFwZSk7XG4gICAgfTtcblxuY29uc3QgY29udjJEVW5wYWNrZWQgPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogcmVhZG9ubHkgVGVuc29yW10sIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzKTogVGVuc29yID0+IHtcbiAgICAgIGNvbnN0IHhzaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICAgICAgY29uc3Qga3NoYXBlID0gaW5wdXRzWzFdLmRpbXM7XG4gICAgICBjb25zdCBvdXRwdXRTaGFwZSA9XG4gICAgICAgICAgY2FsY3VsYXRlT3V0cHV0U2hhcGUoeHNoYXBlLCBrc2hhcGUsIGF0dHJpYnV0ZXMuZGlsYXRpb25zLCBhdHRyaWJ1dGVzLnBhZHMsIGF0dHJpYnV0ZXMuc3RyaWRlcyk7XG4gICAgICBjb25zdCB4SW0yQ29sID0gaW5mZXJlbmNlSGFuZGxlci5ydW4oXG4gICAgICAgICAgY3JlYXRlSW0yQ29sUHJvZ3JhbUluZm9Mb2FkZXIoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzWzBdLCBpbnB1dHNbMV0sIG91dHB1dFNoYXBlLCBhdHRyaWJ1dGVzKSwgW2lucHV0c1swXV0pO1xuXG4gICAgICBjb25zdCBkb3RQcm9kdWN0SW5wdXRzID0gaW5wdXRzLmxlbmd0aCA9PT0gMyA/IFt4SW0yQ29sLCBpbnB1dHNbMV0sIGlucHV0c1syXV0gOiBbeEltMkNvbCwgaW5wdXRzWzFdXTtcbiAgICAgIGNvbnN0IG91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgIGNyZWF0ZURvdFByb2R1Y3RQcm9ncmFtSW5mb0xvYWRlcihpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIG91dHB1dFNoYXBlLCBhdHRyaWJ1dGVzKSwgZG90UHJvZHVjdElucHV0cyk7XG4gICAgICByZXR1cm4gb3V0cHV0O1xuICAgIH07XG5cbmNvbnN0IGdldEFkanVzdGVkQ29udkF0dHJpYnV0ZXMgPSA8VCBleHRlbmRzIENvbnZBdHRyaWJ1dGVzPihhdHRyaWJ1dGVzOiBULCBpbnB1dHM6IFRlbnNvcltdKTogVCA9PiB7XG4gIGNvbnN0IGtlcm5lbFNoYXBlID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5zbGljZSgpO1xuICAvLyBpZiBrZXJuZWxTaGFwZSBpcyBub3Qgc3BlY2lmaWVkIGluIHRoZSBhdHRyaWJ1dGVzIG9mIHRoaXMgb3AsIGluZmVyIGl0IGZyb20gdGhlIHdlaWdodCB0ZW5zb3IgZGltc1xuICBpZiAoYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggPT09IDApIHtcbiAgICBmb3IgKGxldCBpID0gMjsgaSA8IGlucHV0c1sxXS5kaW1zLmxlbmd0aDsgKytpKSB7XG4gICAgICBrZXJuZWxTaGFwZS5wdXNoKGlucHV0c1sxXS5kaW1zW2ldKTtcbiAgICB9XG4gIH1cbiAgY29uc3QgcGFkcyA9IGF0dHJpYnV0ZXMucGFkcy5zbGljZSgpO1xuICBQb29sQ29udlV0aWwuYWRqdXN0UGFkc0Jhc2VkT25BdXRvUGFkKFxuICAgICAgaW5wdXRzWzBdLmRpbXMsIGF0dHJpYnV0ZXMuc3RyaWRlcywgYXR0cmlidXRlcy5kaWxhdGlvbnMsIGtlcm5lbFNoYXBlLCBwYWRzLCBhdHRyaWJ1dGVzLmF1dG9QYWQpO1xuXG4gIC8vIGFsd2F5cyByZXR1cm4gYSBuZXcgb2JqZWN0IHNvIGRvZXMgbm90IG1vZGlmeSB0aGUgb3JpZ2luYWwgYXR0cmlidXRlc1xuICBjb25zdCBuZXdBdHRyaWJ1dGVzOiBUID0gT2JqZWN0LmFzc2lnbih7fSwgYXR0cmlidXRlcyk7XG4gIE9iamVjdC5hc3NpZ24obmV3QXR0cmlidXRlcywge2tlcm5lbFNoYXBlLCBwYWRzLCBjYWNoZUtleTogYXR0cmlidXRlcy5jYWNoZUtleX0pO1xuICByZXR1cm4gbmV3QXR0cmlidXRlcztcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUNvbnZBdHRyaWJ1dGVzOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPENvbnZBdHRyaWJ1dGVzPiA9IChub2RlOiBHcmFwaC5Ob2RlKTogQ29udkF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBhdHRyaWJ1dGVzID0gbm9kZS5hdHRyaWJ1dGVzO1xuICBjb25zdCBhY3RpdmF0aW9uQXR0cmlidXRlcyA9IHBhcnNlSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyhhdHRyaWJ1dGVzKTtcbiAgLy8gVE9ETyA6IE1ha2UgdGhpcyBnZW5lcmljIGVub3VnaCB0byBjb21wdXRlIGRlZmF1bHQgYXR0cmlidXRlcyBmb3IgbXVsdGktZGltZW5zaW9uYWwgY29udlxuICBjb25zdCBhdXRvUGFkID0gYXR0cmlidXRlcy5nZXRTdHJpbmcoJ2F1dG9fcGFkJywgJ05PVFNFVCcpO1xuICBjb25zdCBkaWxhdGlvbnMgPSBhdHRyaWJ1dGVzLmdldEludHMoJ2RpbGF0aW9ucycsIFsxLCAxXSk7XG4gIGNvbnN0IGdyb3VwID0gYXR0cmlidXRlcy5nZXRJbnQoJ2dyb3VwJywgMSk7XG4gIGNvbnN0IGtlcm5lbFNoYXBlID0gYXR0cmlidXRlcy5nZXRJbnRzKCdrZXJuZWxfc2hhcGUnLCBbXSk7XG4gIGNvbnN0IHBhZHMgPSBhdHRyaWJ1dGVzLmdldEludHMoJ3BhZHMnLCBbMCwgMCwgMCwgMF0pO1xuICBjb25zdCBzdHJpZGVzID0gYXR0cmlidXRlcy5nZXRJbnRzKCdzdHJpZGVzJywgWzEsIDFdKTtcblxuICByZXR1cm4gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHthdXRvUGFkLCBkaWxhdGlvbnMsIGdyb3VwLCBrZXJuZWxTaGFwZSwgcGFkcywgc3RyaWRlcywgLi4uYWN0aXZhdGlvbkF0dHJpYnV0ZXN9KTtcbn07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIC8vIFJlZmVyIHRvIHRoZSBiZWxvdyBsaW5rIGZvciBhbGwgaW5wdXQgY2hlY2tzXG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9vbm54L29ubngvYmxvYi9tYWluL2RvY3MvT3BlcmF0b3JzLm1kI0NvbnZcbiAgaWYgKCFpbnB1dHMgfHwgKGlucHV0cy5sZW5ndGggIT09IDIgJiYgaW5wdXRzLmxlbmd0aCAhPT0gMykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbnYgcmVxdWlyZXMgMiBvciAzIGlucHV0cycpO1xuICB9XG5cbiAgLy8gVE9ETyA6IE5lZWQgdG8gYWRkIHN1cHBvcnQgZm9yIG11bHRpLWRpbWVuc2lvbmFsIGNvbnZcbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gNCB8fCBpbnB1dHNbMV0uZGltcy5sZW5ndGggIT09IDQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2N1cnJlbnRseSBvbmx5IHN1cHBvcnQgMi1kaW1lbnNpb25hbCBjb252Jyk7XG4gIH1cblxuICAvLyBGSUxURVJfSU5fQ0hBTk5FTCBzaG91bGQgYmUgZXF1YWwgdG8gREFUQV9DSEFOTkVMXG4gIGNvbnN0IGRhdGFDaGFubmVsID0gaW5wdXRzWzBdLmRpbXNbMV07XG4gIGNvbnN0IGZpbHRlckluQ2hhbm5lbCA9IGlucHV0c1sxXS5kaW1zWzFdICogYXR0cmlidXRlcy5ncm91cDtcbiAgaWYgKGRhdGFDaGFubmVsICE9PSBmaWx0ZXJJbkNoYW5uZWwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZJTFRFUl9JTl9DSEFOTkVMIHNob3VsZCBiZSBlcXVhbCB0byBEQVRBX0NIQU5ORUwnKTtcbiAgfVxuXG4gIC8vIGlmIGJpYXMgaXMgcHJvdmlkZWQgaXQgc2hvdWxkIGJlIDFEIGFuZCB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIHNob3VsZCBiZSBlcXVhbCB0byB0aGUgbnVtYmVyIG9mIGZlYXR1cmUgbWFwc1xuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiAoaW5wdXRzWzJdLmRpbXMubGVuZ3RoICE9PSAxIHx8IGlucHV0c1sxXS5kaW1zWzBdICE9PSBpbnB1dHNbMl0uZGltc1swXSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgYmlhcycpO1xuICB9XG5cbiAgY29uc3Qgc3BhdGlhbFJhbmsgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAyO1xuICAvLyB3cm9uZyBkaWxhdGlvbnMgZGltZW5zaW9uXG4gIGlmIChhdHRyaWJ1dGVzLmRpbGF0aW9ucy5sZW5ndGggIT09IHNwYXRpYWxSYW5rKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBkaWxhdGlvbnMgc2hvdWxkIGJlICR7c3BhdGlhbFJhbmt9RGApO1xuICB9XG5cbiAgLy8gV3Jvbmcgc3RyaWRlcyBkaW1lbnNpb25cbiAgaWYgKGF0dHJpYnV0ZXMuc3RyaWRlcy5sZW5ndGggIT09IHNwYXRpYWxSYW5rKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBzdHJpZGVzIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rfURgKTtcbiAgfVxuXG4gIC8vIFdyb25nIHBhZHMgZGltZW5zaW9uXG4gIGlmIChhdHRyaWJ1dGVzLnBhZHMubGVuZ3RoICE9PSBzcGF0aWFsUmFuayAqIDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHBhZHMgc2hvdWxkIGJlICR7c3BhdGlhbFJhbmsgKiAyfURgKTtcbiAgfVxuXG4gIC8vIGlmIGtlcm5lbFNoYXBlIGlzIHNwZWNpZmllZCwgaXQncyBkYXRhIGxlbmd0aCBtdXN0IGJlIDIgbGVzcyB0aGFuIGRpbXMgbGVuZ3RoIG9mIHRoZSB3ZWlnaHRzIHRlbnNvclxuICAvLyAodGhlIGZpcnN0IDIgZGltcyBhcmUgYmF0Y2hfc2l6ZSBhbmQgY2hhbm5lbHMpXG4gIGlmIChhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCAhPT0gMCAmJiBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCAhPT0gaW5wdXRzWzFdLmRpbXMubGVuZ3RoIC0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBrZXJuZWwgc2hhcGUnKTtcbiAgfVxuXG4gIC8vIFRPRE8gOiBOZWVkIHRvIGFkZCBzdXBwb3J0IGZvciBmbG9hdDY0XG4gIGlmIChpbnB1dHNbMF0udHlwZSAhPT0gJ2Zsb2F0MzInIHx8IGlucHV0c1sxXS50eXBlICE9PSAnZmxvYXQzMicpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbnYgaW5wdXQoWCxXKSBzaG91bGQgYmUgZmxvYXQgdGVuc29yJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiBpbnB1dHNbMl0udHlwZSAhPT0gJ2Zsb2F0MzInKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDb252IGlucHV0KGJpYXMpIHNob3VsZCBiZSBmbG9hdCB0ZW5zb3InKTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0dyYXBofSBmcm9tICcuLi8uLi8uLi9ncmFwaCc7XG5pbXBvcnQge09wZXJhdG9ySW1wbGVtZW50YXRpb24sIE9wZXJhdG9ySW5pdGlhbGl6YXRpb259IGZyb20gJy4uLy4uLy4uL29wZXJhdG9ycyc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5cbmltcG9ydCB7dHJhbnNwb3NlLCBUcmFuc3Bvc2VBdHRyaWJ1dGVzfSBmcm9tICcuL3RyYW5zcG9zZSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVwdGhUb1NwYWNlQXR0cmlidXRlcyB7XG4gIG1vZGU6ICdEQ1InfCdDUkQnO1xuICBibG9ja3NpemU6IG51bWJlcjtcbn1cblxuZXhwb3J0IGNvbnN0IGRlcHRoVG9TcGFjZTogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxEZXB0aFRvU3BhY2VBdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogRGVwdGhUb1NwYWNlQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cyk7XG4gICAgICBjb25zdCBibG9ja3NpemUgPSBhdHRyaWJ1dGVzLmJsb2Nrc2l6ZTtcbiAgICAgIGNvbnN0IGJsb2Nrc2l6ZVNxciA9IGJsb2Nrc2l6ZSAqIGJsb2Nrc2l6ZTtcbiAgICAgIGNvbnN0IHRyYW5zcG9zZVBlcm0gPSBhdHRyaWJ1dGVzLm1vZGUgPT09ICdEQ1InID8gWzAsIDMsIDQsIDEsIDUsIDJdIDogWzAsIDEsIDQsIDIsIDUsIDNdO1xuICAgICAgY29uc3QgZmlyc3RSZXNoYXBlU2hhcGUgPSBhdHRyaWJ1dGVzLm1vZGUgPT09ICdEQ1InID9cbiAgICAgICAgICBbXG4gICAgICAgICAgICBpbnB1dHNbMF0uZGltc1swXSwgYmxvY2tzaXplLCBibG9ja3NpemUsIGlucHV0c1swXS5kaW1zWzFdIC8gYmxvY2tzaXplU3FyLCBpbnB1dHNbMF0uZGltc1syXSxcbiAgICAgICAgICAgIGlucHV0c1swXS5kaW1zWzNdXG4gICAgICAgICAgXSA6XG4gICAgICAgICAgW1xuICAgICAgICAgICAgaW5wdXRzWzBdLmRpbXNbMF0sIGlucHV0c1swXS5kaW1zWzFdIC8gYmxvY2tzaXplU3FyLCBibG9ja3NpemUsIGJsb2Nrc2l6ZSwgaW5wdXRzWzBdLmRpbXNbMl0sXG4gICAgICAgICAgICBpbnB1dHNbMF0uZGltc1szXVxuICAgICAgICAgIF07XG5cbiAgICAgIC8vIGNvbnN0IHRyYW5zcG9zZSA9IG5ldyBXZWJHTFRyYW5zcG9zZSgpO1xuICAgICAgLy8gY29uc3QgYXR0cmlidXRlcyA9IG5ldyBBdHRyaWJ1dGUodW5kZWZpbmVkKTtcbiAgICAgIC8vIGF0dHJpYnV0ZXMuc2V0KCdwZXJtJywgJ2ludHMnLCB0cmFuc3Bvc2VQZXJtKTtcbiAgICAgIC8vIHRyYW5zcG9zZS5pbml0aWFsaXplKGF0dHJpYnV0ZXMpO1xuXG4gICAgICAvLyBGaXJzdCByZXNoYXBlXG4gICAgICBjb25zdCBmaXJzdFJlc2hhcGVkVGVuc29yID0gaW5mZXJlbmNlSGFuZGxlci5yZXNoYXBlVW5wYWNrZWQoaW5wdXRzWzBdLCBmaXJzdFJlc2hhcGVTaGFwZSk7XG5cbiAgICAgIC8vIHRyYW5zcG9zZVxuICAgICAgY29uc3QgdHJhbnNwb3NlQXR0cmlidXRlczogVHJhbnNwb3NlQXR0cmlidXRlcyA9IHtwZXJtOiB0cmFuc3Bvc2VQZXJtLCBjYWNoZUtleTogYCR7dHJhbnNwb3NlUGVybX1gfTtcbiAgICAgIGNvbnN0IFt0cmFuc3Bvc2VPdXRwdXRdID0gdHJhbnNwb3NlKGluZmVyZW5jZUhhbmRsZXIsIFtmaXJzdFJlc2hhcGVkVGVuc29yXSwgdHJhbnNwb3NlQXR0cmlidXRlcyk7XG5cbiAgICAgIC8vIFNlY29uZCByZXNoYXBlXG4gICAgICBjb25zdCBzZWNvbmRSZXNoYXBlU2hhcGUgPSBbXG4gICAgICAgIGlucHV0c1swXS5kaW1zWzBdLCBpbnB1dHNbMF0uZGltc1sxXSAvIGJsb2Nrc2l6ZVNxciwgaW5wdXRzWzBdLmRpbXNbMl0gKiBibG9ja3NpemUsXG4gICAgICAgIGlucHV0c1swXS5kaW1zWzNdICogYmxvY2tzaXplXG4gICAgICBdO1xuICAgICAgY29uc3QgcmVzdWx0ID0gaW5mZXJlbmNlSGFuZGxlci5yZXNoYXBlVW5wYWNrZWQodHJhbnNwb3NlT3V0cHV0LCBzZWNvbmRSZXNoYXBlU2hhcGUpO1xuICAgICAgcmV0dXJuIFtyZXN1bHRdO1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBwYXJzZURlcHRoVG9TcGFjZUF0dHJpYnV0ZXM6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248RGVwdGhUb1NwYWNlQXR0cmlidXRlcz4gPVxuICAgIChub2RlOiBHcmFwaC5Ob2RlKTogRGVwdGhUb1NwYWNlQXR0cmlidXRlcyA9PiB7XG4gICAgICAvLyBwcm9jZXNzaW5nIG5vZGUgYXR0cmlidXRlc1xuICAgICAgY29uc3QgYmxvY2tzaXplID0gbm9kZS5hdHRyaWJ1dGVzLmdldEludCgnYmxvY2tzaXplJyk7XG4gICAgICBpZiAoYmxvY2tzaXplIDwgMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGJsb2Nrc2l6ZSBtdXN0IGJlID49IDEsIGJ1dCBnb3QgOiAke2Jsb2Nrc2l6ZX0gZm9yIERlcHRoVG9TcGFjZWApO1xuICAgICAgfVxuICAgICAgY29uc3QgbW9kZSA9IG5vZGUuYXR0cmlidXRlcy5nZXRTdHJpbmcoJ21vZGUnLCAnRENSJyk7XG4gICAgICBpZiAobW9kZSAhPT0gJ0RDUicgJiYgbW9kZSAhPT0gJ0NSRCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnJlY29nbml6ZWQgbW9kZTogJHttb2RlfSBmb3IgRGVwdGhUb1NwYWNlYCk7XG4gICAgICB9XG4gICAgICByZXR1cm4ge21vZGUsIGJsb2Nrc2l6ZX07XG4gICAgfTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiBUZW5zb3JbXSk6IHZvaWQgPT4ge1xuICBpZiAoaW5wdXRzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgRGVwdGhUb1NwYWNlIGV4cGVjdCAxIGlucHV0cywgYnV0IGdvdCAke2lucHV0cy5sZW5ndGh9YCk7XG4gIH1cblxuICAvLyBJbnB1dCBoYXMgdG8gYmUgYSA0LUQgdGVuc29yXG4gIC8vIFRPRE86IFN1cHBvcnQgc3RyaW5nIGRlcHRoLXRvLXNwYWNlLlxuICBpZiAoaW5wdXRzWzBdLnR5cGUgPT09ICdzdHJpbmcnIHx8IGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gNCkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0RlcHRoVG9TcGFjZSBpbnB1dCBzaG91bGQgYmUgYSA0LUQgbnVtZXJpYyB0ZW5zb3InKTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7U2hhcGVVdGlsfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi4vZ2xzbC1zb3VyY2UnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGEsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7Z2V0QWN0aXZhdGlvblNuaXBwZXQsIEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXN9IGZyb20gJy4vZnVzZS11dGlscyc7XG5pbXBvcnQge2NhbGN1bGF0ZUltMkNvbERpbXN9IGZyb20gJy4vaW0yY29sJztcblxuY29uc3QgY3JlYXRlRG90UHJvZHVjdFByb2dyYW1NZXRhZGF0YSA9IChoYXNCaWFzOiBib29sZWFuLCBhdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzKSA9PiAoe1xuICBuYW1lOiAnQ29udkRvdFByb2R1Y3QnLFxuICBpbnB1dE5hbWVzOiBoYXNCaWFzID8gWydJbTJDb2wnLCAnSycsICdCJ10gOiBbJ0ltMkNvbCcsICdLJ10sXG4gIGlucHV0VHlwZXM6IGhhc0JpYXMgPyBbVGV4dHVyZVR5cGUudW5wYWNrZWQsIFRleHR1cmVUeXBlLnBhY2tlZExhc3REaW1lbnNpb24sIFRleHR1cmVUeXBlLnVucGFja2VkXSA6XG4gICAgICAgICAgICAgICAgICAgICAgICBbVGV4dHVyZVR5cGUudW5wYWNrZWQsIFRleHR1cmVUeXBlLnBhY2tlZExhc3REaW1lbnNpb25dLFxuICBjYWNoZUtleTogYXR0cmlidXRlcy5hY3RpdmF0aW9uQ2FjaGVLZXlcbn0pO1xuXG5jb25zdCBjcmVhdGVEb3RQcm9kdWN0UHJvZ3JhbUluZm8gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIG1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEsIGlucHV0czogcmVhZG9ubHkgVGVuc29yW10sXG4gICAgIG91dHB1dFNoYXBlOiBudW1iZXJbXSwgYXR0cmlidXRlczogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IHhzaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICAgICAgY29uc3Qga3NoYXBlID0gaW5wdXRzWzFdLmRpbXM7XG4gICAgICBjb25zdCBhZGp1c3RlZEtlcm5lbFNoYXBlID0gW2tzaGFwZVswXSwgTWF0aC5jZWlsKCh4c2hhcGVbMV0gKiBrc2hhcGVbMl0gKiBrc2hhcGVbM10pIC8gNCldO1xuICAgICAgY29uc3QgaW0yY29sU2hhcGUgPSBjYWxjdWxhdGVJbTJDb2xEaW1zKHhzaGFwZSwga3NoYXBlLCBvdXRwdXRTaGFwZSk7XG4gICAgICBjb25zdCBba1dpZHRoLCBrSGVpZ2h0XSA9XG4gICAgICAgICAgaW5mZXJlbmNlSGFuZGxlci5jYWxjdWxhdGVUZXh0dXJlV2lkdGhBbmRIZWlnaHQoYWRqdXN0ZWRLZXJuZWxTaGFwZSwgVGV4dHVyZVR5cGUucGFja2VkTGFzdERpbWVuc2lvbik7XG5cbiAgICAgIGNvbnN0IGltMmNvbFN0cmlkZXMgPSBTaGFwZVV0aWwuY29tcHV0ZVN0cmlkZXMoaW0yY29sU2hhcGUpO1xuICAgICAgY29uc3QgW2ltMmNvbFdpZHRoLCBpbTJjb2xIZWlnaHRdID1cbiAgICAgICAgICBpbmZlcmVuY2VIYW5kbGVyLmNhbGN1bGF0ZVRleHR1cmVXaWR0aEFuZEhlaWdodChpbTJjb2xTaGFwZSwgVGV4dHVyZVR5cGUucGFja2VkTGFzdERpbWVuc2lvbik7XG4gICAgICBjb25zdCByYW5rID0gb3V0cHV0U2hhcGUubGVuZ3RoO1xuXG4gICAgICBjb25zdCBpbml0VmFsdWUgPSAoaW5wdXRzLmxlbmd0aCA8IDMpID8gJzAuMCcgOiAnX0IoYiknO1xuICAgICAgY29uc3Qgc2hhcmVkRGltID0gTWF0aC5jZWlsKHhzaGFwZVsxXSAqIGtzaGFwZVsyXSAqIGtzaGFwZVszXSAvIDQpO1xuICAgICAgY29uc3Qge2FjdGl2YXRpb25GdW5jdGlvbiwgYXBwbHlBY3RpdmF0aW9ufSA9IGdldEFjdGl2YXRpb25TbmlwcGV0KGF0dHJpYnV0ZXMpO1xuICAgICAgY29uc3QgZ2xzbCA9IGdldEdsc2woaW5mZXJlbmNlSGFuZGxlci5zZXNzaW9uLmJhY2tlbmQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuJHthY3RpdmF0aW9uRnVuY3Rpb259XG5mbG9hdCBwcm9jZXNzKGludCBpbmRpY2VzWyR7cmFua31dKSB7XG4gIGludCBiWzFdO1xuICBiWzBdID0gaW5kaWNlc1sxXTtcbiAgaW50IGltMmNvbFs0XTtcbiAgaW0yY29sWzBdID0gaW5kaWNlc1swXTtcbiAgaW0yY29sWzFdID0gaW5kaWNlc1syXTtcbiAgaW0yY29sWzJdID0gaW5kaWNlc1szXTtcbiAgaW50IGltMmNvbE9mZnNldCA9IGltMmNvbFswXSAqICR7aW0yY29sU3RyaWRlc1swXX0gKyBpbTJjb2xbMV0gKiAke2ltMmNvbFN0cmlkZXNbMV19ICsgaW0yY29sWzJdICogJHtcbiAgICAgICAgICBpbTJjb2xTdHJpZGVzWzJdfTtcbiAgaW50IGtlcm5lbE9mZnNldCA9IGluZGljZXNbMV0gKiAke2FkanVzdGVkS2VybmVsU2hhcGVbMV19O1xuICBmbG9hdCB2YWx1ZSA9ICR7aW5pdFZhbHVlfTtcbiAgZm9yIChpbnQgaSA9IDA7IGkgPCAke3NoYXJlZERpbX07ICsraSkge1xuICAgIHZlYzIgaW0yY29sQ29vcmRzID0gb2Zmc2V0VG9Db29yZHMoaW0yY29sT2Zmc2V0LCAke2ltMmNvbFdpZHRofSwgJHtpbTJjb2xIZWlnaHR9KTtcbiAgICB2ZWMyIGtlcm5lbENvb3JkcyA9IG9mZnNldFRvQ29vcmRzKGtlcm5lbE9mZnNldCwgJHtrV2lkdGh9LCAke2tIZWlnaHR9KTtcbiAgICB2YWx1ZSArPSBkb3QoJHtnbHNsLnRleHR1cmUyRH0oSW0yQ29sLCBpbTJjb2xDb29yZHMpLCAke2dsc2wudGV4dHVyZTJEfShLLCBrZXJuZWxDb29yZHMpKTtcbiAgICArK2ltMmNvbE9mZnNldDtcbiAgICArK2tlcm5lbE9mZnNldDtcbiAgfVxuICAke2FwcGx5QWN0aXZhdGlvbn1cbiAgcmV0dXJuIHZhbHVlO1xufWA7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgb3V0cHV0OiB7ZGltczogb3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0c1swXS50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUudW5wYWNrZWR9LFxuICAgICAgICBzaGFkZXJTb3VyY2VcbiAgICAgIH07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZURvdFByb2R1Y3RQcm9ncmFtSW5mb0xvYWRlciA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiByZWFkb25seSBUZW5zb3JbXSwgb3V0cHV0U2hhcGU6IG51bWJlcltdLFxuICAgICBhdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm9Mb2FkZXIgPT4ge1xuICAgICAgY29uc3QgbWV0YWRhdGEgPSBjcmVhdGVEb3RQcm9kdWN0UHJvZ3JhbU1ldGFkYXRhKGlucHV0cy5sZW5ndGggPiAyLCBhdHRyaWJ1dGVzKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZURvdFByb2R1Y3RQcm9ncmFtSW5mbyhpbmZlcmVuY2VIYW5kbGVyLCBtZXRhZGF0YSwgaW5wdXRzLCBvdXRwdXRTaGFwZSwgYXR0cmlidXRlcylcbiAgICAgIH07XG4gICAgfTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0dyYXBofSBmcm9tICcuLi8uLi8uLi9ncmFwaCc7XG5pbXBvcnQge09wZXJhdG9ySW1wbGVtZW50YXRpb24sIE9wZXJhdG9ySW5pdGlhbGl6YXRpb259IGZyb20gJy4uLy4uLy4uL29wZXJhdG9ycyc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7U2hhcGVVdGlsfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5cbmV4cG9ydCBjb25zdCBmbGF0dGVuOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPG51bWJlcj4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF4aXM6IG51bWJlcik6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cywgYXhpcyk7XG5cbiAgICAgIGNvbnN0IG91dHB1dERpbXMgPSBTaGFwZVV0aWwuZmxhdHRlblNoYXBlKGlucHV0c1swXS5kaW1zLCBheGlzKTtcbiAgICAgIHJldHVybiBbaW5mZXJlbmNlSGFuZGxlci5yZXNoYXBlVW5wYWNrZWQoaW5wdXRzWzBdLCBvdXRwdXREaW1zKV07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlRmxhdHRlbkF0dHJpYnV0ZXM6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248bnVtYmVyPiA9IChub2RlOiBHcmFwaC5Ob2RlKTogbnVtYmVyID0+XG4gICAgbm9kZS5hdHRyaWJ1dGVzLmdldEludCgnYXhpcycsIDEpOyAgLy8gZGVmYXVsdCBheGlzIGlzIDFcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiBUZW5zb3JbXSwgYXhpczogbnVtYmVyKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZsYXR0ZW4gcmVxdWlyZXMgMSBpbnB1dC4nKTtcbiAgfVxuXG4gIGNvbnN0IHIgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGg7XG4gIGlmIChyID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzY2FsYXIgdGVuc29yIGlzIG5vdCBzdXBwb3J0ZWQuJyk7XG4gIH1cblxuICBpZiAoYXhpcyA8IC1yIHx8IGF4aXMgPiByKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGF4aXMnKTtcbiAgfVxuXG4gIC8vIFRPRE86IFN1cHBvcnQgc3RyaW5nIHR5cGVcbiAgaWYgKGlucHV0c1swXS50eXBlID09PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBFcnJvcignc3RyaW5nIHRlbnNvciBpcyBub3Qgc3VwcG9ydGVkLicpO1xuICB9XG59OyIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0F0dHJpYnV0ZX0gZnJvbSAnLi4vLi4vLi4vYXR0cmlidXRlJztcbmltcG9ydCB7TUFYX0NMSVAsIE1JTl9DTElQfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7R2xzbFZhbHVlRnVuY3Rpb259IGZyb20gJy4uL2dsc2wtZGVmaW5pdGlvbnMnO1xuXG5pbXBvcnQge2dsc2xDbGlwLCBnbHNsUmVsdSwgZ2xzbFNpZ21vaWR9IGZyb20gJy4vdW5hcnktb3AnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMge1xuICByZWFkb25seSBhY3RpdmF0aW9uOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNsaXBNaW4/OiBudW1iZXI7XG4gIHJlYWRvbmx5IGNsaXBNYXg/OiBudW1iZXI7XG4gIHJlYWRvbmx5IGFjdGl2YXRpb25DYWNoZUtleTogc3RyaW5nO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWN0aXZhdGlvblNuaXBwZXQoYXR0cmlidXRlczogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcykge1xuICBsZXQgZnVuYzogR2xzbFZhbHVlRnVuY3Rpb247XG4gIHN3aXRjaCAoYXR0cmlidXRlcy5hY3RpdmF0aW9uKSB7XG4gICAgY2FzZSAnUmVsdSc6XG4gICAgICBmdW5jID0gZ2xzbFJlbHUoKTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ1NpZ21vaWQnOlxuICAgICAgZnVuYyA9IGdsc2xTaWdtb2lkKCk7XG4gICAgICBicmVhaztcbiAgICBjYXNlICdDbGlwJzpcbiAgICAgIGZ1bmMgPSBnbHNsQ2xpcChhdHRyaWJ1dGVzLmNsaXBNaW4hLCBhdHRyaWJ1dGVzLmNsaXBNYXghKTtcbiAgICAgIGJyZWFrO1xuICAgIC8vIFRPRE86IGFkZGluZyBvdGhlciBhY3RpdmF0aW9ucyB0aGF0IGNhbiBiZSBmdXNlZC5cbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHthY3RpdmF0aW9uRnVuY3Rpb246ICcnLCBhcHBseUFjdGl2YXRpb246ICcnfTtcbiAgfVxuXG4gIGNvbnN0IGFjdGl2YXRpb25OYW1lID0gZnVuYy5uYW1lO1xuICBjb25zdCBhY3RpdmF0aW9uRnVuY3Rpb24gPSBmdW5jLmJvZHk7XG4gIGNvbnN0IGFwcGx5QWN0aXZhdGlvbiA9IGB2YWx1ZSA9ICR7YWN0aXZhdGlvbk5hbWV9Xyh2YWx1ZSk7YDtcbiAgcmV0dXJuIHthY3RpdmF0aW9uRnVuY3Rpb24sIGFwcGx5QWN0aXZhdGlvbn07XG59XG5cbmV4cG9ydCBjb25zdCBwYXJzZUludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogQXR0cmlidXRlKTogSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGFjdGl2YXRpb24gPSBhdHRyaWJ1dGVzLmdldFN0cmluZygnYWN0aXZhdGlvbicsICcnKTtcblxuICBpZiAoYWN0aXZhdGlvbiA9PT0gJ0NsaXAnKSB7XG4gICAgY29uc3QgW2NsaXBNaW4sIGNsaXBNYXhdID0gYXR0cmlidXRlcy5nZXRGbG9hdHMoJ2FjdGl2YXRpb25fcGFyYW1zJywgW01JTl9DTElQLCBNQVhfQ0xJUF0pO1xuICAgIHJldHVybiB7YWN0aXZhdGlvbiwgY2xpcE1heCwgY2xpcE1pbiwgYWN0aXZhdGlvbkNhY2hlS2V5OiBgJHthY3RpdmF0aW9ufToke2NsaXBNaW59LCR7Y2xpcE1heH1gfTtcbiAgfVxuICByZXR1cm4ge2FjdGl2YXRpb24sIGFjdGl2YXRpb25DYWNoZUtleTogYWN0aXZhdGlvbn07XG59O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7QXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXl9IGZyb20gJy4uLy4uLy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQge0dyYXBofSBmcm9tICcuLi8uLi8uLi9ncmFwaCc7XG5pbXBvcnQge05VTUJFUl9UWVBFUywgT3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi4vLi4vLi4vb3BlcmF0b3JzJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtTaGFwZVV0aWx9IGZyb20gJy4uLy4uLy4uL3V0aWwnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGEsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmludGVyZmFjZSBHYXRoZXJBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgYXhpczogbnVtYmVyO1xufVxuXG5leHBvcnQgY29uc3QgZ2F0aGVyOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPEdhdGhlckF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBHYXRoZXJBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzLCBhdHRyaWJ1dGVzLmF4aXMpO1xuICAgICAgY29uc3Qgb3V0cHV0ID0gaW5mZXJlbmNlSGFuZGxlci5ydW4oY3JlYXRlR2F0aGVyUHJvZ3JhbUluZm9Mb2FkZXIoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhdHRyaWJ1dGVzKSwgaW5wdXRzKTtcbiAgICAgIHJldHVybiBbb3V0cHV0XTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcGFyc2VHYXRoZXJBdHRyaWJ1dGVzOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPEdhdGhlckF0dHJpYnV0ZXM+ID0gKG5vZGU6IEdyYXBoLk5vZGUpOiBHYXRoZXJBdHRyaWJ1dGVzID0+XG4gICAgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtheGlzOiBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50KCdheGlzJywgMCl9KTtcblxuY29uc3QgZ2F0aGVyUHJvZ3JhbU1ldGFkYXRhID0ge1xuICBuYW1lOiAnR2F0aGVyJyxcbiAgaW5wdXROYW1lczogWydBJywgJ0InXSxcbiAgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS51bnBhY2tlZF0sXG59O1xuXG5jb25zdCBjcmVhdGVHYXRoZXJQcm9ncmFtSW5mbyA9XG4gICAgKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgbWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSwgaW5wdXRzOiBUZW5zb3JbXSwgYXhpczogbnVtYmVyKTogUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zLnNsaWNlKCk7XG4gICAgICBjb25zdCBpbmRleERhdGFTaGFwZSA9IGlucHV0c1sxXS5kaW1zLnNsaWNlKCk7XG4gICAgICBjb25zdCBvdXRwdXRTaGFwZSA9IG5ldyBBcnJheShpbnB1dFNoYXBlLmxlbmd0aCArIGluZGV4RGF0YVNoYXBlLmxlbmd0aCAtIDEpO1xuXG4gICAgICBheGlzID0gU2hhcGVVdGlsLm5vcm1hbGl6ZUF4aXMoYXhpcywgaW5wdXRTaGFwZS5sZW5ndGgpO1xuICAgICAgY29uc3QgaW5kZXhDb3B5T3BzOiBzdHJpbmdbXSA9IFtdO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXRTaGFwZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAvLyBvdXRwdXRTaGFwZSBpcyBkaXZpZGVkIGludG8gdGhyZWUgcGFydHM6IEEsIEIsIENcbiAgICAgICAgLy8gfDAgICAgICAgIGF4aXN8ICBheGlzICsgaW5kZXhEYXRhU2hhcGUubGVuZ3RoIHwgICAgICAgICAgZW5kfFxuICAgICAgICAvLyB8ICAgICBBICAgICAgIHwgICAgICAgICAgICAgQiAgICAgICAgICAgICAgICAgfCAgICAgIEMgICAgICB8XG4gICAgICAgIC8vXG4gICAgICAgIC8vIGlucHV0SWR4OiBbQSwgaW5wdXRzWzFdW0JdLCBDXVxuICAgICAgICBpZiAoaSA8IGF4aXMpIHsgIC8vIEFcbiAgICAgICAgICBvdXRwdXRTaGFwZVtpXSA9IGlucHV0U2hhcGVbaV07XG4gICAgICAgICAgaW5kZXhDb3B5T3BzLnB1c2goYGlucHV0SWR4WyR7aX1dID0gb3V0cHV0SWR4WyR7aX1dO2ApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChpIDwgYXhpcyArIGluZGV4RGF0YVNoYXBlLmxlbmd0aCkgeyAgLy8gQlxuICAgICAgICAgICAgb3V0cHV0U2hhcGVbaV0gPSBpbmRleERhdGFTaGFwZVtpIC0gYXhpc107XG4gICAgICAgICAgICBpbmRleENvcHlPcHMucHVzaChgaW5kZXhEYXRhSWR4WyR7aSAtIGF4aXN9XSA9IG91dHB1dElkeFske2l9XTtgKTtcbiAgICAgICAgICB9IGVsc2UgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDXG4gICAgICAgICAgICBvdXRwdXRTaGFwZVtpXSA9IGlucHV0U2hhcGVbaSAtIGluZGV4RGF0YVNoYXBlLmxlbmd0aCArIDFdOyAgLy8gc2tpcCAxIGZvciBheGlzXG4gICAgICAgICAgICBpbmRleENvcHlPcHMucHVzaChgaW5wdXRJZHhbJHtpIC0gaW5kZXhEYXRhU2hhcGUubGVuZ3RoICsgMX1dID0gb3V0cHV0SWR4WyR7aX1dO2ApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBvcmFuayA9IG91dHB1dFNoYXBlLmxlbmd0aCB8fCAxO1xuICAgICAgY29uc3QgaXJhbmsgPSBpbnB1dFNoYXBlLmxlbmd0aDtcbiAgICAgIGNvbnN0IGlEcmFuayA9IGluZGV4RGF0YVNoYXBlLmxlbmd0aCB8fCAxO1xuICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICAgZmxvYXQgcHJvY2VzcyhpbnQgb3V0cHV0SWR4WyR7b3Jhbmt9XSkge1xuICAgICAgICBpbnQgaW5wdXRJZHhbJHtpcmFua31dO1xuICAgICAgICBpbnQgaW5kZXhEYXRhSWR4WyR7aURyYW5rfV07XG4gICAgICAgIGluZGV4RGF0YUlkeFswXSA9IDA7XG4gICAgICAgICR7aW5kZXhDb3B5T3BzLmpvaW4oJ1xcbiAgICAgICAgJyl9XG4gICAgICAgIGludCBpZHggPSBpbnQoX0IoaW5kZXhEYXRhSWR4KSk7XG4gICAgICAgIGlucHV0SWR4WyR7YXhpc31dID0gaWR4IDwgMCA/IGlkeCArICR7aW5wdXRTaGFwZVtheGlzXX0gOiBpZHg7XG4gICAgICAgIHJldHVybiBfQShpbnB1dElkeCk7XG4gICAgICB9YDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICBvdXRwdXQ6IHtkaW1zOiBvdXRwdXRTaGFwZSwgdHlwZTogaW5wdXRzWzBdLnR5cGUsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZS51bnBhY2tlZH0sXG4gICAgICAgIHNoYWRlclNvdXJjZVxuICAgICAgfTtcbiAgICB9O1xuXG5jb25zdCBjcmVhdGVHYXRoZXJQcm9ncmFtSW5mb0xvYWRlciA9XG4gICAgKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogR2F0aGVyQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvTG9hZGVyID0+IHtcbiAgICAgIGNvbnN0IG1ldGFkYXRhID0gey4uLmdhdGhlclByb2dyYW1NZXRhZGF0YSwgY2FjaGVIaW50OiBhdHRyaWJ1dGVzLmNhY2hlS2V5fTtcbiAgICAgIHJldHVybiB7Li4ubWV0YWRhdGEsIGdldDogKCkgPT4gY3JlYXRlR2F0aGVyUHJvZ3JhbUluZm8oaGFuZGxlciwgbWV0YWRhdGEsIGlucHV0cywgYXR0cmlidXRlcy5heGlzKX07XG4gICAgfTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiBUZW5zb3JbXSwgYXhpczogbnVtYmVyKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0dhdGhlciByZXF1aXJlcyAyIGlucHV0cy4nKTtcbiAgfVxuICBjb25zdCB0ZW5zb3JSYW5rID0gaW5wdXRzWzBdLmRpbXMubGVuZ3RoO1xuICBpZiAodGVuc29yUmFuayA8IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaW5wdXQgc2hhcGUuJyk7XG4gIH1cbiAgaWYgKGF4aXMgPCAtdGVuc29yUmFuayB8fCBheGlzID4gdGVuc29yUmFuayAtIDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgYXhpcy4nKTtcbiAgfVxuICBpZiAoTlVNQkVSX1RZUEVTLmluZGV4T2YoaW5wdXRzWzBdLnR5cGUpID09PSAtMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWlkIGlucHV0IHR5cGUuJyk7XG4gIH1cbiAgaWYgKGlucHV0c1sxXS50eXBlICE9PSAnaW50MzInICYmIGlucHV0c1sxXS50eXBlICE9PSAnaW50MTYnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhaWQgaW5wdXQgdHlwZS4nKTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0F0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi8uLi8uLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge0dlbW1VdGlsfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBQcm9ncmFtSW5mb0xvYWRlciwgUHJvZ3JhbU1ldGFkYXRhLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEdlbW1BdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgdHJhbnNBOiBib29sZWFuO1xuICB0cmFuc0I6IGJvb2xlYW47XG4gIGFscGhhOiBudW1iZXI7XG4gIGJldGE6IG51bWJlcjtcbiAgaXNPcHRpb25hbEM6IGJvb2xlYW47ICAvLyBpbiBvcHNldCAxMSwgQyBiZWNvbWVzIG9wdGlvbmFsXG59XG5cbmV4cG9ydCBjb25zdCBnZW1tOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPEdlbW1BdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogR2VtbUF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICAgICAgY29uc3Qgb3V0cHV0ID0gaW5mZXJlbmNlSGFuZGxlci5ydW4oY3JlYXRlR2VtbVByb2dyYW1JbmZvTG9hZGVyKGlucHV0cywgYXR0cmlidXRlcyksIGlucHV0cyk7XG4gICAgICByZXR1cm4gW291dHB1dF07XG4gICAgfTtcblxuY29uc3QgcGFyc2VHZW1tQXR0cmlidXRlcyA9IChub2RlOiBHcmFwaC5Ob2RlLCBpc09wdGlvbmFsQzogYm9vbGVhbik6IEdlbW1BdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgdHJhbnNBID0gbm9kZS5hdHRyaWJ1dGVzLmdldEludCgndHJhbnNBJywgMCkgIT09IDA7XG4gIGNvbnN0IHRyYW5zQiA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnQoJ3RyYW5zQicsIDApICE9PSAwO1xuICBjb25zdCBhbHBoYSA9IG5vZGUuYXR0cmlidXRlcy5nZXRGbG9hdCgnYWxwaGEnLCAxLjApO1xuICBjb25zdCBiZXRhID0gbm9kZS5hdHRyaWJ1dGVzLmdldEZsb2F0KCdiZXRhJywgMS4wKTtcbiAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7dHJhbnNBLCB0cmFuc0IsIGFscGhhLCBiZXRhLCBpc09wdGlvbmFsQ30pO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlR2VtbUF0dHJpYnV0ZXNWNzogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxHZW1tQXR0cmlidXRlcz4gPSAobm9kZTogR3JhcGguTm9kZSk6IEdlbW1BdHRyaWJ1dGVzID0+XG4gICAgcGFyc2VHZW1tQXR0cmlidXRlcyhub2RlLCBmYWxzZSk7XG5cbmV4cG9ydCBjb25zdCBwYXJzZUdlbW1BdHRyaWJ1dGVzVjExOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPEdlbW1BdHRyaWJ1dGVzPiA9IChub2RlOiBHcmFwaC5Ob2RlKTogR2VtbUF0dHJpYnV0ZXMgPT5cbiAgICBwYXJzZUdlbW1BdHRyaWJ1dGVzKG5vZGUsIHRydWUpO1xuXG5jb25zdCBjcmVhdGVHZW1tUHJvZ3JhbUluZm9Mb2FkZXIgPSAoaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogR2VtbUF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mb0xvYWRlciA9PiB7XG4gIGNvbnN0IG1ldGFkYXRhID0ge1xuICAgIG5hbWU6ICdHZW1tJyxcbiAgICBpbnB1dE5hbWVzOiBpbnB1dHMubGVuZ3RoID09PSAzID8gWydBJywgJ0InLCAnQyddIDogWydBJywgJ0InXSxcbiAgICBpbnB1dFR5cGVzOiBpbnB1dHMubGVuZ3RoID09PSAzID8gW1RleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWRdIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW1RleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS51bnBhY2tlZF0sXG4gICAga2V5OiBhdHRyaWJ1dGVzLmNhY2hlS2V5XG4gIH07XG5cbiAgcmV0dXJuIHsuLi5tZXRhZGF0YSwgZ2V0OiAoKSA9PiBjcmVhdGVHZW1tUHJvZ3JhbUluZm8obWV0YWRhdGEsIGlucHV0cywgYXR0cmlidXRlcyl9O1xufTtcblxuY29uc3QgY3JlYXRlR2VtbVByb2dyYW1JbmZvID1cbiAgICAobWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogR2VtbUF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICBjb25zdCBhU2hhcGUgPSBpbnB1dHNbMF0uZGltcy5zbGljZSgpO1xuICAgICAgY29uc3QgYlNoYXBlID0gaW5wdXRzWzFdLmRpbXMuc2xpY2UoKTtcbiAgICAgIGNvbnN0IFtNLCBOXSA9IEdlbW1VdGlsLmdldFNoYXBlT2ZHZW1tUmVzdWx0KFxuICAgICAgICAgIGFTaGFwZSwgYXR0cmlidXRlcy50cmFuc0EsIGJTaGFwZSwgYXR0cmlidXRlcy50cmFuc0IsIGlucHV0cy5sZW5ndGggPT09IDMgPyBpbnB1dHNbMl0uZGltcyA6IHVuZGVmaW5lZCk7XG4gICAgICBjb25zdCBvdXRwdXRTaGFwZSA9IFtNLCBOXTtcbiAgICAgIGlmICghb3V0cHV0U2hhcGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXCd0IHVzZSBnZW1tIG9uIHRoZSBnaXZlbiB0ZW5zb3JzJyk7XG4gICAgICB9XG4gICAgICBsZXQgc2hhcmVkRGltID0gYVNoYXBlW2FTaGFwZS5sZW5ndGggLSAxXTtcbiAgICAgIGxldCBsaW5lID0gJyc7XG4gICAgICBpZiAoYXR0cmlidXRlcy50cmFuc0EpIHtcbiAgICAgICAgc2hhcmVkRGltID0gYVNoYXBlWzBdO1xuICAgICAgfVxuICAgICAgaWYgKGF0dHJpYnV0ZXMudHJhbnNBICYmIGF0dHJpYnV0ZXMudHJhbnNCKSB7XG4gICAgICAgIGxpbmUgPSAndmFsdWUgKz0gX0FfVChhKSAqIF9CX1QoYik7JztcbiAgICAgIH0gZWxzZSBpZiAoYXR0cmlidXRlcy50cmFuc0EgJiYgIWF0dHJpYnV0ZXMudHJhbnNCKSB7XG4gICAgICAgIGxpbmUgPSAndmFsdWUgKz0gX0FfVChhKSAqIF9CKGIpOyc7XG4gICAgICB9IGVsc2UgaWYgKCFhdHRyaWJ1dGVzLnRyYW5zQSAmJiBhdHRyaWJ1dGVzLnRyYW5zQikge1xuICAgICAgICBsaW5lID0gJ3ZhbHVlICs9IF9BKGEpICogX0JfVChiKTsnO1xuICAgICAgfSBlbHNlIGlmICghYXR0cmlidXRlcy50cmFuc0EgJiYgIWF0dHJpYnV0ZXMudHJhbnNCKSB7XG4gICAgICAgIGxpbmUgPSAndmFsdWUgKz0gX0EoYSkgKiBfQihiKTsnO1xuICAgICAgfVxuICAgICAgY29uc3QgcmFuayA9IG91dHB1dFNoYXBlLmxlbmd0aDtcbiAgICAgIGNvbnN0IGRlY2xhcmVDID0gaW5wdXRzLmxlbmd0aCA9PT0gMyA/IGBpbnQgY1ske2lucHV0c1syXS5kaW1zLmxlbmd0aH1dO2AgOiAnJztcbiAgICAgIGNvbnN0IGJyb2FkY2FzdEMgPSBpbnB1dHMubGVuZ3RoID09PSAzID8gJ2JjYXN0SW5kaWNlc19DKGluZGljZXMsIGMpOycgOiAnJztcbiAgICAgIGNvbnN0IGNhbGN1bGF0ZUMgPSBpbnB1dHMubGVuZ3RoID09PSAzID8gJ3ZhbHVlICs9IGJldGEgKiBfQyhjKTsnIDogJyc7XG4gICAgICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gICAgICBmbG9hdCBwcm9jZXNzKGludCBpbmRpY2VzWyR7cmFua31dKSB7XG4gICAgICAgICAgaW50IGFbJHtyYW5rfV07XG4gICAgICAgICAgaW50IGJbJHtyYW5rfV07XG4gICAgICAgICAgJHtkZWNsYXJlQ31cblxuICAgICAgICAgIGNvcHlWZWMoaW5kaWNlcywgYSk7XG4gICAgICAgICAgY29weVZlYyhpbmRpY2VzLCBiKTtcbiAgICAgICAgICAke2Jyb2FkY2FzdEN9XG5cbiAgICAgICAgICBmbG9hdCB2YWx1ZSA9IDAuMDtcbiAgICAgICAgICBmb3IgKGludCBrPTA7IGs8JHtzaGFyZWREaW19OyArK2spIHtcbiAgICAgICAgICAgICAgYVske3JhbmsgLSAxfV0gPSBrO1xuICAgICAgICAgICAgICBiWyR7cmFuayAtIDJ9XSA9IGs7XG4gICAgICAgICAgICAgICR7bGluZX1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YWx1ZSA9IHZhbHVlICogYWxwaGE7XG4gICAgICAgICAgJHtjYWxjdWxhdGVDfVxuICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1gO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgIG91dHB1dDoge2RpbXM6IG91dHB1dFNoYXBlLCB0eXBlOiBpbnB1dHNbMF0udHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgdmFyaWFibGVzOiBbXG4gICAgICAgICAge25hbWU6ICdhbHBoYScsIHR5cGU6ICdmbG9hdCcsIGRhdGE6IGF0dHJpYnV0ZXMuYWxwaGF9LCB7bmFtZTogJ2JldGEnLCB0eXBlOiAnZmxvYXQnLCBkYXRhOiBhdHRyaWJ1dGVzLmJldGF9XG4gICAgICAgIF0sXG4gICAgICAgIHNoYWRlclNvdXJjZVxuICAgICAgfTtcbiAgICB9O1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBHZW1tQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cykge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgaXMgbWlzc2luZycpO1xuICB9XG4gIGlmIChhdHRyaWJ1dGVzLmlzT3B0aW9uYWxDICYmIChpbnB1dHMubGVuZ3RoIDwgMiB8fCBpbnB1dHMubGVuZ3RoID4gMykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFpZCBpbnB1dCBzaGFwZS4nKTtcbiAgfVxuICBpZiAoIWF0dHJpYnV0ZXMuaXNPcHRpb25hbEMgJiYgaW5wdXRzLmxlbmd0aCAhPT0gMykge1xuICAgIHRocm93IG5ldyBFcnJvcignR2VtbSByZXF1aXJlcyAzIGlucHV0cycpO1xuICB9XG5cbiAgLy8gJ0MnIGNhbiBiZSBvZiBkaW1lbnNpb25hbGl0eSAxIG9yIDIgb25seVxuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiBpbnB1dHNbMl0uZGltcy5sZW5ndGggIT09IDEgJiYgaW5wdXRzWzJdLmRpbXMubGVuZ3RoICE9PSAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHNoYXBlIG9mIEMnKTtcbiAgfVxuXG4gIGlmICgoaW5wdXRzWzBdLnR5cGUgIT09ICdmbG9hdDMyJyAmJiBpbnB1dHNbMF0udHlwZSAhPT0gJ2Zsb2F0NjQnKSB8fFxuICAgICAgKGlucHV0c1sxXS50eXBlICE9PSAnZmxvYXQzMicgJiYgaW5wdXRzWzFdLnR5cGUgIT09ICdmbG9hdDY0JykgfHxcbiAgICAgIChpbnB1dHMubGVuZ3RoID09PSAzICYmIGlucHV0c1syXS50eXBlICE9PSAnZmxvYXQzMicgJiYgaW5wdXRzWzJdLnR5cGUgIT09ICdmbG9hdDY0JykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaW5wdXQgdHlwZS4nKTtcbiAgfVxuXG4gIGlmICgoaW5wdXRzWzBdLnR5cGUgIT09IGlucHV0c1sxXS50eXBlKSB8fCAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiBpbnB1dHNbMF0udHlwZSAhPT0gaW5wdXRzWzJdLnR5cGUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCB0eXBlcyBhcmUgbWlzbWF0Y2hlZCcpO1xuICB9XG59O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtnZXRHbHNsfSBmcm9tICcuLi9nbHNsLXNvdXJjZSc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgUHJvZ3JhbUluZm9Mb2FkZXIsIFByb2dyYW1NZXRhZGF0YSwgVGV4dHVyZVR5cGV9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtDb252QXR0cmlidXRlc30gZnJvbSAnLi9jb252JztcbmltcG9ydCB7dW5wYWNrRnJvbUNoYW5uZWx9IGZyb20gJy4vcGFja2luZy11dGlscyc7XG5cbmNvbnN0IGNyZWF0ZVBhY2tlZEltMkNvbFByb2dyYW1NZXRhZGF0YSA9IChjYWNoZUhpbnQ6IHN0cmluZykgPT4gKHtcbiAgbmFtZTogJ0ltMkNvbCAocGFja2VkKScsXG4gIGlucHV0TmFtZXM6IFsnQSddLFxuICBpbnB1dFR5cGVzOiBbVGV4dHVyZVR5cGUucGFja2VkXSxcbiAgY2FjaGVIaW50LFxufSk7XG5cbmNvbnN0IGNyZWF0ZVBhY2tlZEltMkNvbFByb2dyYW1JbmZvID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhLCB4OiBUZW5zb3IsIHc6IFRlbnNvcixcbiAgICAgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IHhzaGFwZSA9IHguZGltcztcbiAgICAgIGNvbnN0IHdzaGFwZSA9IHcuZGltcztcbiAgICAgIGNvbnN0IHJvd0RpbSA9IDI7XG4gICAgICBjb25zdCBjb2xEaW0gPSAzO1xuICAgICAgY29uc3QgcmFuayA9IG91dHB1dFNoYXBlLmxlbmd0aDtcbiAgICAgIGNvbnN0IGltMmNvbFNoYXBlID0gW3dzaGFwZVsxXSAqIHdzaGFwZVsyXSAqIHdzaGFwZVszXSwgb3V0cHV0U2hhcGVbMl0gKiBvdXRwdXRTaGFwZVszXV07XG4gICAgICBjb25zdCBrZXJuZWxTaXplID0gd3NoYXBlWzJdICogd3NoYXBlWzNdO1xuICAgICAgY29uc3QgdW5wYWNrQ2hhbm5lbCA9IHVucGFja0Zyb21DaGFubmVsKCk7XG4gICAgICBjb25zdCBnbHNsID0gZ2V0R2xzbChpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQudmVyc2lvbik7XG4gICAgICBsZXQgdW5yb2xsZWQgPSAnJztcblxuICAgICAgZm9yIChsZXQgcm93ID0gMDsgcm93IDw9IDE7IHJvdysrKSB7XG4gICAgICAgIGZvciAobGV0IGNvbCA9IDA7IGNvbCA8PSAxOyBjb2wrKykge1xuICAgICAgICAgIHVucm9sbGVkICs9IGBcbiAgICAgICAgICAgIGJsb2NrSW5kZXggPSByYy54ICsgJHtjb2x9O1xuICAgICAgICAgICAgcG9zID0gcmMueSArICR7cm93fTtcblxuICAgICAgICAgICAgaWYoYmxvY2tJbmRleCA8ICR7aW0yY29sU2hhcGVbMV19ICYmIHBvcyA8ICR7aW0yY29sU2hhcGVbMF19KSB7XG4gICAgICAgICAgICAgIG9mZnNldFkgPSBpbnQoYmxvY2tJbmRleCAvICgke291dHB1dFNoYXBlW3JhbmsgLSAxXX0pKSAqICR7YXR0cmlidXRlcy5zdHJpZGVzWzBdfSAtXG4gICAgICAgICAgICAgICAgJHthdHRyaWJ1dGVzLnBhZHNbMF19O1xuICAgICAgICAgICAgICBkMCA9IG9mZnNldFkgKyAke2F0dHJpYnV0ZXMuZGlsYXRpb25zWzBdfSAqIChpbW9kKHBvcywgJHtrZXJuZWxTaXplfSkgLyAke3dzaGFwZVsyXX0pO1xuXG4gICAgICAgICAgICAgIGlmKGQwIDwgJHt4c2hhcGVbcm93RGltXX0gJiYgZDAgPj0gMCkge1xuICAgICAgICAgICAgICAgIG9mZnNldFggPSBpbW9kKGJsb2NrSW5kZXgsICR7b3V0cHV0U2hhcGVbcmFuayAtIDFdfSkgKiAke2F0dHJpYnV0ZXMuc3RyaWRlc1sxXX0gLVxuICAgICAgICAgICAgICAgICAgJHthdHRyaWJ1dGVzLnBhZHNbMV19O1xuICAgICAgICAgICAgICAgIGQxID0gb2Zmc2V0WCArICR7YXR0cmlidXRlcy5kaWxhdGlvbnNbMV19ICogaW1vZChpbW9kKHBvcywgJHtrZXJuZWxTaXplfSksICR7d3NoYXBlWzJdfSk7XG5cbiAgICAgICAgICAgICAgICBpZihkMSA8ICR7eHNoYXBlW2NvbERpbV19ICYmIGQxID49IDApIHtcblxuICAgICAgICAgICAgICAgICAgY2ggPSBpbnQoZmxvYXQocG9zKS8gJHtrZXJuZWxTaXplfS4pO1xuICAgICAgICAgICAgICAgICAgICBpbm5lckRpbXMgPSB2ZWMyKGQwLCBkMSk7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFske3JvdyAqIDIgKyBjb2x9XSA9IGdldENoYW5uZWwoXG4gICAgICAgICAgICAgICAgICAgICAgZ2V0QSgwLCBjaCwgaW50KGlubmVyRGltcy54KSxcbiAgICAgICAgICAgICAgICAgICAgICBpbnQoaW5uZXJEaW1zLnkpKSwgaW5uZXJEaW1zKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgIGA7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICAgJHt1bnBhY2tDaGFubmVsfVxuXG4gICAgICB2b2lkIG1haW4oKSB7XG4gICAgICAgIGl2ZWMyIHJjID0gZ2V0T3V0cHV0Q29vcmRzKCk7XG4gICAgICAgICAgdmVjNCByZXN1bHQgPSB2ZWM0KDAuMCk7XG4gICAgICAgICAgaW50IGJsb2NrSW5kZXgsIHBvcywgb2Zmc2V0WSwgZDAsIG9mZnNldFgsIGQxLCBjaDtcbiAgICAgICAgICB2ZWMyIGlubmVyRGltcztcbiAgICAgICAgICAke3Vucm9sbGVkfVxuICAgICAgICAgICR7Z2xzbC5vdXRwdXR9ID0gcmVzdWx0O1xuICAgICAgfVxuICAgICAgICAgICAgYDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICBvdXRwdXQ6IHtkaW1zOiBpbTJjb2xTaGFwZSwgdHlwZTogeC50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUucGFja2VkfSxcbiAgICAgICAgc2hhZGVyU291cmNlLFxuICAgICAgICBoYXNNYWluOiB0cnVlXG4gICAgICB9O1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVQYWNrZWRJbTJDb2xQcm9ncmFtSW5mb0xvYWRlciA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgeDogVGVuc29yLCB3OiBUZW5zb3IsIG91dHB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSxcbiAgICAgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mb0xvYWRlciA9PiB7XG4gICAgICBjb25zdCBtZXRhZGF0YSA9IGNyZWF0ZVBhY2tlZEltMkNvbFByb2dyYW1NZXRhZGF0YShhdHRyaWJ1dGVzLmNhY2hlS2V5KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZVBhY2tlZEltMkNvbFByb2dyYW1JbmZvKGluZmVyZW5jZUhhbmRsZXIsIG1ldGFkYXRhLCB4LCB3LCBvdXRwdXRTaGFwZSwgYXR0cmlidXRlcylcbiAgICAgIH07XG4gICAgfTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBQcm9ncmFtSW5mb0xvYWRlciwgUHJvZ3JhbU1ldGFkYXRhLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge0NvbnZBdHRyaWJ1dGVzfSBmcm9tICcuL2NvbnYnO1xuXG5jb25zdCBjcmVhdGVJbTJDb2xQcm9ncmFtTWV0YWRhdGEgPSAoY2FjaGVIaW50OiBzdHJpbmcpID0+ICh7XG4gIG5hbWU6ICdJbTJDb2wnLFxuICBpbnB1dE5hbWVzOiBbJ1gnXSxcbiAgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnVucGFja2VkXSxcbiAgY2FjaGVIaW50LFxufSk7XG5cbmNvbnN0IGNyZWF0ZUltMkNvbFByb2dyYW1JbmZvID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhLCB4OiBUZW5zb3IsIHc6IFRlbnNvcixcbiAgICAgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IHhzaGFwZSA9IHguZGltcztcbiAgICAgIGNvbnN0IHdzaGFwZSA9IHcuZGltcztcblxuICAgICAgY29uc3QgcmFuayA9IG91dHB1dFNoYXBlLmxlbmd0aDtcbiAgICAgIGNvbnN0IGltMmNvbERpbXMgPSBjYWxjdWxhdGVJbTJDb2xEaW1zKHhzaGFwZSwgd3NoYXBlLCBvdXRwdXRTaGFwZSwgNCk7XG5cbiAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAgICAgY29uc3QgaW50IFhDID0gJHt4c2hhcGVbMV19O1xuICAgICAgICBjb25zdCBpbnQgWEggPSAke3hzaGFwZVsyXX07XG4gICAgICAgIGNvbnN0IGludCBYVyA9ICR7eHNoYXBlWzNdfTtcbiAgICAgICAgY29uc3QgaW50IEtIID0gJHthdHRyaWJ1dGVzLmtlcm5lbFNoYXBlWzBdfTtcbiAgICAgICAgY29uc3QgaW50IEtXID0gJHthdHRyaWJ1dGVzLmtlcm5lbFNoYXBlWzFdfTtcbiAgICAgICAgY29uc3QgaW50IGRpbGF0aW9uSCA9ICR7YXR0cmlidXRlcy5kaWxhdGlvbnNbMF19O1xuICAgICAgICBjb25zdCBpbnQgZGlsYXRpb25XID0gJHthdHRyaWJ1dGVzLmRpbGF0aW9uc1sxXX07XG4gICAgICAgIGNvbnN0IGludCBzdHJpZGVIID0gJHthdHRyaWJ1dGVzLnN0cmlkZXNbMF19O1xuICAgICAgICBjb25zdCBpbnQgc3RyaWRlVyA9ICR7YXR0cmlidXRlcy5zdHJpZGVzWzFdfTtcbiAgICAgICAgY29uc3QgaW50IHBhZEggPSAke2F0dHJpYnV0ZXMucGFkc1swXX07XG4gICAgICAgIGNvbnN0IGludCBwYWRXID0gJHthdHRyaWJ1dGVzLnBhZHNbMV19O1xuICAgICAgICBjb25zdCBpbnQgS0hLVyA9IEtIKktXO1xuICAgICAgICBjb25zdCBpbnQgWENLSEtXID0gWEMgKiBLSEtXO1xuICAgICAgICBjb25zdCBpbnQgb3V0cHV0Q2hhbm5lbHMgPSA0O1xuICAgICAgICB2ZWM0IHByb2Nlc3MoaW50IGluZGljZXNbJHtyYW5rfV0pIHtcbiAgICAgICAgICBpbnQgYiAgPSBpbmRpY2VzWzBdOyAvLyBiYXRjaCBzaXplXG4gICAgICAgICAgaW50IG9oID0gaW5kaWNlc1sxXSAqIHN0cmlkZUggLSBwYWRIOyAvL291dHB1dCBoZWlnaHRcbiAgICAgICAgICBpbnQgb3cgPSBpbmRpY2VzWzJdICogc3RyaWRlVyAtIHBhZFc7IC8vb3V0cHV0IHdpZHRoXG4gICAgICAgICAgaW50IHAgPSBpbmRpY2VzWzNdICogb3V0cHV0Q2hhbm5lbHM7IC8vcGF0Y2hcbiAgICAgICAgICB2ZWM0IHZhbHVlID0gdmVjNCgwLjApO1xuICAgICAgICAgIGZvcihpbnQgaT0wOyBpIDwgb3V0cHV0Q2hhbm5lbHM7ICsraSkge1xuICAgICAgICAgICAgaWYocCA8IFhDS0hLVykge1xuICAgICAgICAgICAgICBpbnQgcGF0Y2hDID0gcCAvIEtIS1c7XG4gICAgICAgICAgICAgIGludCBwYXRjaEggPSAocCAtIHBhdGNoQypLSEtXKSAvIEtXO1xuICAgICAgICAgICAgICBpbnQgcGF0Y2hXID0gKHAgLSBwYXRjaEMqS0hLVykgLSBwYXRjaEggKiBLVztcbiAgICAgICAgICAgICAgaW50IHhoMiA9IG9oICsgcGF0Y2hIICogZGlsYXRpb25IO1xuICAgICAgICAgICAgICBpbnQgeHcyID0gb3cgKyBwYXRjaFcgKiBkaWxhdGlvblc7XG4gICAgICAgICAgICAgIGludCB4WyR7eHNoYXBlLmxlbmd0aH1dO1xuICAgICAgICAgICAgICB4WzBdID0gYjtcbiAgICAgICAgICAgICAgeFsxXSA9IHBhdGNoQztcbiAgICAgICAgICAgICAgeFsyXSA9IHhoMjtcbiAgICAgICAgICAgICAgeFszXSA9IHh3MjtcbiAgICAgICAgICAgICAgaWYoeGgyID49IDAgJiZcbiAgICAgICAgICAgICAgICAgIHhoMiA8IFhIICYmXG4gICAgICAgICAgICAgICAgICB4dzIgPj0gMCAmJlxuICAgICAgICAgICAgICAgICAgeHcyIDwgWFcpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZVtpXSA9IF9YKHgpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICArK3A7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBgO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgIG91dHB1dDoge2RpbXM6IGltMmNvbERpbXMsIHR5cGU6IHgudHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnBhY2tlZExhc3REaW1lbnNpb259LFxuICAgICAgICBzaGFkZXJTb3VyY2VcbiAgICAgIH07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZUltMkNvbFByb2dyYW1JbmZvTG9hZGVyID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCB4OiBUZW5zb3IsIHc6IFRlbnNvciwgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgICBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6IFByb2dyYW1JbmZvTG9hZGVyID0+IHtcbiAgICAgIGNvbnN0IG1ldGFkYXRhID0gY3JlYXRlSW0yQ29sUHJvZ3JhbU1ldGFkYXRhKGF0dHJpYnV0ZXMuY2FjaGVLZXkpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgIGdldDogKCkgPT4gY3JlYXRlSW0yQ29sUHJvZ3JhbUluZm8oaW5mZXJlbmNlSGFuZGxlciwgbWV0YWRhdGEsIHgsIHcsIG91dHB1dFNoYXBlLCBhdHRyaWJ1dGVzKVxuICAgICAgfTtcbiAgICB9O1xuXG5cbmV4cG9ydCBjb25zdCBjYWxjdWxhdGVJbTJDb2xEaW1zID1cbiAgICAoaW5wdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIGtlcm5lbFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBjaGFubmVscyA9IDQpOlxuICAgICAgICBudW1iZXJbXSA9PlxuICAgICAgICAgICAgW291dHB1dFNoYXBlWzBdLCBvdXRwdXRTaGFwZVsyXSwgb3V0cHV0U2hhcGVbM10sXG4gICAgICAgICAgICAgTWF0aC5jZWlsKGlucHV0U2hhcGVbMV0gKiBrZXJuZWxTaGFwZVsyXSAqIGtlcm5lbFNoYXBlWzNdIC8gY2hhbm5lbHMpXTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0F0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi8uLi8uLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgUHJvZ3JhbUluZm9Mb2FkZXIsIFByb2dyYW1NZXRhZGF0YSwgVGV4dHVyZVR5cGV9IGZyb20gJy4uL3R5cGVzJztcblxuZXhwb3J0IGludGVyZmFjZSBJbWFnZVNjYWxlckF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICBzY2FsZTogbnVtYmVyO1xuICBiaWFzOiBudW1iZXJbXTtcbn1cblxuZXhwb3J0IGNvbnN0IGltYWdlU2NhbGVyOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPEltYWdlU2NhbGVyQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IEltYWdlU2NhbGVyQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cyk7XG4gICAgICBjb25zdCBvdXRwdXQgPVxuICAgICAgICAgIGluZmVyZW5jZUhhbmRsZXIucnVuKGNyZWF0ZUltYWdlU2NhbGVyUHJvZ3JhbUluZm9Mb2FkZXIoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhdHRyaWJ1dGVzKSwgaW5wdXRzKTtcbiAgICAgIHJldHVybiBbb3V0cHV0XTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcGFyc2VJbWFnZVNjYWxlckF0dHJpYnV0ZXM6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248SW1hZ2VTY2FsZXJBdHRyaWJ1dGVzPiA9XG4gICAgKG5vZGU6IEdyYXBoLk5vZGUpOiBJbWFnZVNjYWxlckF0dHJpYnV0ZXMgPT4ge1xuICAgICAgY29uc3Qgc2NhbGUgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0RmxvYXQoJ3NjYWxlJyk7XG4gICAgICBjb25zdCBiaWFzID0gbm9kZS5hdHRyaWJ1dGVzLmdldEZsb2F0cygnYmlhcycpO1xuICAgICAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7c2NhbGUsIGJpYXN9KTtcbiAgICB9O1xuXG5jb25zdCBpbWFnZVNjYWxlclByb2dyYW1NZXRhZGF0YSA9IHtcbiAgbmFtZTogJ0ltYWdlU2NhbGVyJyxcbiAgaW5wdXROYW1lczogWydYJ10sXG4gIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS51bnBhY2tlZF0sXG59O1xuXG5jb25zdCBjcmVhdGVJbWFnZVNjYWxlclByb2dyYW1JbmZvID1cbiAgICAoaGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBJbWFnZVNjYWxlckF0dHJpYnV0ZXMpOlxuICAgICAgICBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBpbnB1dHNbMF0uZGltcy5zbGljZSgpO1xuICAgICAgICAgIGNvbnN0IHJhbmsgPSBvdXRwdXRTaGFwZS5sZW5ndGg7XG4gICAgICAgICAgY29uc3QgZ2V0Qmlhc01ldGhvZCA9IGNyZWF0ZUdldEJpYXNNZXRob2QoYXR0cmlidXRlcy5iaWFzLmxlbmd0aCk7XG4gICAgICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICAgJHtnZXRCaWFzTWV0aG9kfVxuICAgICAgZmxvYXQgcHJvY2VzcyhpbnQgaW5kaWNlc1ske3Jhbmt9XSkge1xuICAgICAgICByZXR1cm4gX1goaW5kaWNlcykgKiBzY2FsZSArIGdldEJpYXMoYmlhcywgaW5kaWNlc1sxXSk7XG4gICAgICB9YDtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgICAgICBvdXRwdXQ6IHtkaW1zOiBvdXRwdXRTaGFwZSwgdHlwZTogaW5wdXRzWzBdLnR5cGUsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZS51bnBhY2tlZH0sXG4gICAgICAgICAgICB2YXJpYWJsZXM6IFtcbiAgICAgICAgICAgICAge25hbWU6ICdiaWFzJywgdHlwZTogJ2Zsb2F0JywgYXJyYXlMZW5ndGg6IGF0dHJpYnV0ZXMuYmlhcy5sZW5ndGgsIGRhdGE6IGF0dHJpYnV0ZXMuYmlhc30sXG4gICAgICAgICAgICAgIHtuYW1lOiAnc2NhbGUnLCB0eXBlOiAnZmxvYXQnLCBkYXRhOiBhdHRyaWJ1dGVzLnNjYWxlfVxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIHNoYWRlclNvdXJjZVxuICAgICAgICAgIH07XG4gICAgICAgIH07XG5cbmNvbnN0IGNyZWF0ZUltYWdlU2NhbGVyUHJvZ3JhbUluZm9Mb2FkZXIgPVxuICAgIChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IEltYWdlU2NhbGVyQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvTG9hZGVyID0+IHtcbiAgICAgIGNvbnN0IG1ldGFkYXRhID0gey4uLmltYWdlU2NhbGVyUHJvZ3JhbU1ldGFkYXRhLCBjYWNoZUhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXl9O1xuICAgICAgcmV0dXJuIHsuLi5tZXRhZGF0YSwgZ2V0OiAoKSA9PiBjcmVhdGVJbWFnZVNjYWxlclByb2dyYW1JbmZvKGhhbmRsZXIsIG1ldGFkYXRhLCBpbnB1dHMsIGF0dHJpYnV0ZXMpfTtcbiAgICB9O1xuXG5jb25zdCBjcmVhdGVHZXRCaWFzTWV0aG9kID0gKG51bUNoYW5uZWxzOiBudW1iZXIpOiBzdHJpbmcgPT4ge1xuICBjb25zdCBjb2RlTGluZXM6IHN0cmluZ1tdID0gW2BmbG9hdCBnZXRCaWFzKGZsb2F0IGJpYXNbJHtudW1DaGFubmVsc31dLCBpbnQgY2hhbm5lbCkge2BdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUNoYW5uZWxzOyArK2kpIHtcbiAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgY29kZUxpbmVzLnB1c2goXG4gICAgICAgICAgJ1xcdCcgK1xuICAgICAgICAgIGBpZiAoY2hhbm5lbCA9PSAke2l9KSB7IHJldHVybiBiaWFzWyR7aX1dOyB9YCk7XG4gICAgfSBlbHNlIGlmIChpID09PSBudW1DaGFubmVscyAtIDEpIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKFxuICAgICAgICAgICdcXHQnICtcbiAgICAgICAgICBgZWxzZSB7IHJldHVybiBiaWFzWyR7aX1dOyB9YCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvZGVMaW5lcy5wdXNoKFxuICAgICAgICAgICdcXHQnICtcbiAgICAgICAgICBgZWxzZSBpZiAoY2hhbm5lbCA9PSAke2l9KSB7IHJldHVybiBiaWFzWyR7aX1dOyB9YCk7XG4gICAgfVxuICB9XG4gIGNvZGVMaW5lcy5wdXNoKFxuICAgICAgJ1xcdCcgK1xuICAgICAgJ30nKTtcbiAgcmV0dXJuIGNvZGVMaW5lcy5qb2luKCdcXG4nKTtcbn07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogVGVuc29yW10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW1hZ2VTY2FsZXIgcmVxdWlyZXMgMSBpbnB1dC4nKTtcbiAgfVxuICBpZiAoaW5wdXRzWzBdLmRpbXMubGVuZ3RoICE9PSA0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHNoYXBlLicpO1xuICB9XG4gIGlmIChpbnB1dHNbMF0udHlwZSAhPT0gJ2Zsb2F0MzInICYmIGlucHV0c1swXS50eXBlICE9PSAnZmxvYXQ2NCcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaW5wdXQgdHlwZS4nKTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0dyYXBofSBmcm9tICcuLi8uLi8uLi9ncmFwaCc7XG5pbXBvcnQge09wZXJhdG9ySW1wbGVtZW50YXRpb24sIE9wZXJhdG9ySW5pdGlhbGl6YXRpb259IGZyb20gJy4uLy4uLy4uL29wZXJhdG9ycyc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi4vZ2xzbC1zb3VyY2UnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGEsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmV4cG9ydCBjb25zdCBpbnN0YW5jZU5vcm1hbGl6YXRpb246IE9wZXJhdG9ySW1wbGVtZW50YXRpb248bnVtYmVyPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgZXBzaWxvbjogbnVtYmVyKTogVGVuc29yW10gPT4ge1xuICAgICAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzKTtcblxuICAgICAgY29uc3QgbWVhbkFuZFZhcmlhbmNlID0gaW5mZXJlbmNlSGFuZGxlci5ydW4oY3JlYXRlTWVhbkFuZFZhcmlhbmNlUHJvZ3JhbUluZm9Mb2FkZXIoaW5wdXRzWzBdKSwgaW5wdXRzKTtcbiAgICAgIGNvbnN0IG91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgIGNyZWF0ZUNvbXB1dGVPdXRwdXRQcm9ncmFtSW5mb0xvYWRlcihpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHNbMF0sIGVwc2lsb24sIG1lYW5BbmRWYXJpYW5jZS5kaW1zKSxcbiAgICAgICAgICBbaW5wdXRzWzBdLCBtZWFuQW5kVmFyaWFuY2UsIGlucHV0c1sxXSwgaW5wdXRzWzJdXSk7XG4gICAgICByZXR1cm4gW291dHB1dF07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlSW5zdGFuY2VOb3JtYWxpemF0aW9uQXR0cmlidXRlczogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxudW1iZXI+ID0gKG5vZGU6IEdyYXBoLk5vZGUpOiBudW1iZXIgPT5cbiAgICBub2RlLmF0dHJpYnV0ZXMuZ2V0RmxvYXQoJ2Vwc2lsb24nLCAxZS01KTtcblxuY29uc3QgbWVhbkFuZFZhcmlhbmNlUHJvZ3JhbU1ldGFkYXRhID0ge1xuICBuYW1lOiAnSW5zdGFuY2VOb3JtYWxpemF0aW9uX01lYW5BbmRWYXJpYW5jZScsXG4gIGlucHV0TmFtZXM6IFsnWCddLFxuICBpbnB1dFR5cGVzOiBbVGV4dHVyZVR5cGUudW5wYWNrZWRdLFxufTtcblxuY29uc3QgY3JlYXRlTWVhbkFuZFZhcmlhbmNlUHJvZ3JhbUluZm8gPSAobWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSwgaW5wdXQ6IFRlbnNvcik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgeERpbXMgPSBpbnB1dC5kaW1zLnNsaWNlKCk7XG4gIGNvbnN0IGNoYW5uZWwgPSB4RGltc1sxXTtcbiAgY29uc3QgY2hhbm5lbFNpemUgPSB4RGltc1syXSAqIHhEaW1zWzNdO1xuICBjb25zdCBvdXRwdXRTaGFwZSA9IFt4RGltc1swXSwgY2hhbm5lbF07XG5cbiAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICAgdmVjNCBwcm9jZXNzKGludFsyXSBpbmRpY2VzKSB7XG4gICAgICAgIHZlYzQgdiA9IHZlYzQoMC4wKTtcbiAgICAgICAgaW50IGFbNF07XG4gICAgICAgIGFbMF0gPSBpbmRpY2VzWzBdO1xuICAgICAgICBhWzFdID0gaW5kaWNlc1sxXTtcbiAgICAgICAgZmxvYXQgdGVtcCA9IDAuMDtcbiAgICAgICAgZm9yKGludCBhMj0wOyBhMjwke3hEaW1zWzJdfTsgYTIrKykge1xuICAgICAgICAgIGFbMl0gPSBhMjtcbiAgICAgICAgICBmb3IoaW50IGEzPTA7IGEzPCR7eERpbXNbM119OyBhMysrKSB7XG4gICAgICAgICAgICBhWzNdID0gYTM7XG4gICAgICAgICAgICBmbG9hdCB4ID0gX1goYSk7XG4gICAgICAgICAgICB0ZW1wICs9IHg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZsb2F0IG1lYW4gPSB0ZW1wIC8gZmxvYXQoJHtjaGFubmVsU2l6ZX0pO1xuICAgICAgICB0ZW1wID0gMC4wO1xuICAgICAgICBmb3IoaW50IGEyPTA7IGEyPCR7eERpbXNbMl19OyBhMisrKSB7XG4gICAgICAgICAgYVsyXSA9IGEyO1xuICAgICAgICAgIGZvcihpbnQgYTM9MDsgYTM8JHt4RGltc1szXX07IGEzKyspIHtcbiAgICAgICAgICAgIGFbM10gPSBhMztcbiAgICAgICAgICAgIGZsb2F0IHggPSBfWChhKTtcbiAgICAgICAgICAgIHRlbXAgKz0gKHggLSBtZWFuKSAqICh4IC0gbWVhbik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHYuciA9IG1lYW47XG4gICAgICAgIHYuZyA9IHRlbXAgLyBmbG9hdCgke2NoYW5uZWxTaXplfSk7XG5cbiAgICAgICAgcmV0dXJuIHY7XG4gICAgICB9YDtcbiAgcmV0dXJuIHtcbiAgICAuLi5tZXRhZGF0YSxcbiAgICBvdXRwdXQ6IHtkaW1zOiBvdXRwdXRTaGFwZSwgdHlwZTogaW5wdXQudHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnBhY2tlZExhc3REaW1lbnNpb259LFxuICAgIHNoYWRlclNvdXJjZVxuICB9O1xufTtcblxuY29uc3QgY3JlYXRlTWVhbkFuZFZhcmlhbmNlUHJvZ3JhbUluZm9Mb2FkZXIgPSAoaW5wdXQ6IFRlbnNvcik6IFByb2dyYW1JbmZvTG9hZGVyID0+ICh7XG4gIC4uLm1lYW5BbmRWYXJpYW5jZVByb2dyYW1NZXRhZGF0YSxcbiAgZ2V0OiAoKSA9PiBjcmVhdGVNZWFuQW5kVmFyaWFuY2VQcm9ncmFtSW5mbyhtZWFuQW5kVmFyaWFuY2VQcm9ncmFtTWV0YWRhdGEsIGlucHV0KVxufSk7XG5cbmNvbnN0IGNvbXB1dGVPdXRwdXRQcm9ncmFtTWV0YWRhdGEgPSB7XG4gIG5hbWU6ICdJbnN0YW5jZU5vcm1hbGl6YXRpb25fQ29tcHV0ZU91dHB1dCcsXG4gIGlucHV0TmFtZXM6IFsnWCcsICdNZWFuQW5kVmFyaWFuY2UnLCAnU2NhbGUnLCAnQiddLFxuICBpbnB1dFR5cGVzOiBbVGV4dHVyZVR5cGUudW5wYWNrZWQsIFRleHR1cmVUeXBlLnBhY2tlZExhc3REaW1lbnNpb24sIFRleHR1cmVUeXBlLnVucGFja2VkLCBUZXh0dXJlVHlwZS51bnBhY2tlZF0sXG59O1xuXG5jb25zdCBjcmVhdGVDb21wdXRlT3V0cHV0UHJvZ3JhbUluZm8gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIG1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEsIGlucHV0OiBUZW5zb3IsIGVwc2lsb246IG51bWJlcixcbiAgICAgbWVhbkFuZFZhcmlhbmNlU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKTogUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgY29uc3QgZ2xzbCA9IGdldEdsc2woaW5mZXJlbmNlSGFuZGxlci5zZXNzaW9uLmJhY2tlbmQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICAgICAgY29uc3QgW3RleHR1cmVXaWR0aCwgdGV4dHVyZUhlaWdodF0gPVxuICAgICAgICAgIGluZmVyZW5jZUhhbmRsZXIuY2FsY3VsYXRlVGV4dHVyZVdpZHRoQW5kSGVpZ2h0KG1lYW5BbmRWYXJpYW5jZVNoYXBlLCBUZXh0dXJlVHlwZS5wYWNrZWRMYXN0RGltZW5zaW9uKTtcbiAgICAgIGNvbnN0IFttZWFuQW5kVmFyaWFuY2VXaWR0aCwgbWVhbkFuZFZhcmlhbmNlSGVpZ2h0XSA9IFt0ZXh0dXJlV2lkdGggLyA0LCB0ZXh0dXJlSGVpZ2h0XTtcbiAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAgIHZlYzQgZ2V0X01lYW5BbmRWYXJpYW5jZShpbnRbMl0gbXYpIHtcbiAgICAgICAgaW50IG9mZnNldCA9IGluZGljZXNUb09mZnNldF9NZWFuQW5kVmFyaWFuY2UobXYpO1xuICAgICAgICB2ZWMyIGNvb3JkcyA9IG9mZnNldFRvQ29vcmRzKG9mZnNldCwgJHttZWFuQW5kVmFyaWFuY2VXaWR0aH0sICR7bWVhbkFuZFZhcmlhbmNlSGVpZ2h0fSk7XG4gICAgICAgIHJldHVybiAke2dsc2wudGV4dHVyZTJEfShNZWFuQW5kVmFyaWFuY2UsIGNvb3Jkcyk7XG4gICAgICB9XG5cbiAgICAgIGZsb2F0IHByb2Nlc3MoaW50WzRdIGluZGljZXMpIHtcbiAgICAgICAgaW50IG12WzJdO1xuICAgICAgICBtdlswXSA9IGluZGljZXNbMF07XG4gICAgICAgIG12WzFdID0gaW5kaWNlc1sxXTtcbiAgICAgICAgdmVjNCBtZWFuX2FuZF92YXJpYW5jZSA9IGdldF9NZWFuQW5kVmFyaWFuY2UobXYpO1xuICAgICAgICBmbG9hdCBtZWFuID0gbWVhbl9hbmRfdmFyaWFuY2UucjtcbiAgICAgICAgZmxvYXQgdmFyaWFuY2UgPSBtZWFuX2FuZF92YXJpYW5jZS5nO1xuXG4gICAgICAgIGludCBzYlsxXTtcbiAgICAgICAgc2JbMF0gPSBpbmRpY2VzWzFdO1xuICAgICAgICBmbG9hdCBzY2FsZSA9IF9TY2FsZShzYik7XG4gICAgICAgIGZsb2F0IGIgPSBfQihzYik7XG5cbiAgICAgICAgcmV0dXJuIHNjYWxlICogKF9YKGluZGljZXMpIC0gbWVhbikgLyBzcXJ0KHZhcmlhbmNlICsgZXBzaWxvbikgKyBiO1xuICAgICAgfWA7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgb3V0cHV0OiB7ZGltczogaW5wdXQuZGltcywgdHlwZTogaW5wdXQudHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgdmFyaWFibGVzOiBbe25hbWU6ICdlcHNpbG9uJywgdHlwZTogJ2Zsb2F0JywgZGF0YTogZXBzaWxvbn1dLFxuICAgICAgICBzaGFkZXJTb3VyY2VcbiAgICAgIH07XG4gICAgfTtcblxuY29uc3QgY3JlYXRlQ29tcHV0ZU91dHB1dFByb2dyYW1JbmZvTG9hZGVyID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dDogVGVuc29yLCBlcHNpbG9uOiBudW1iZXIsIG1lYW5BbmRWYXJpYW5jZVNoYXBlOiByZWFkb25seSBudW1iZXJbXSk6XG4gICAgICAgIFByb2dyYW1JbmZvTG9hZGVyID0+IHtcbiAgICAgICAgICBjb25zdCBtZXRhZGF0YSA9IHsuLi5jb21wdXRlT3V0cHV0UHJvZ3JhbU1ldGFkYXRhLCBjYWNoZUhpbnQ6IGAke2Vwc2lsb259YH07XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICAgICAgZ2V0OiAoKSA9PiBjcmVhdGVDb21wdXRlT3V0cHV0UHJvZ3JhbUluZm8oaW5mZXJlbmNlSGFuZGxlciwgbWV0YWRhdGEsIGlucHV0LCBlcHNpbG9uLCBtZWFuQW5kVmFyaWFuY2VTaGFwZSlcbiAgICAgICAgICB9O1xuICAgICAgICB9O1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IFRlbnNvcltdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0luc3RhbmNlTm9ybWFsaXphdGlvbiByZXF1aXJlcyAzIGlucHV0cy4nKTtcbiAgfVxuXG4gIGNvbnN0IFggPSBpbnB1dHNbMF07XG4gIGNvbnN0IHNjYWxlID0gaW5wdXRzWzFdO1xuICBjb25zdCBCID0gaW5wdXRzWzJdO1xuXG4gIC8vIGlucHV0IHNob3VsZCBhdCBsZWFzdCBoYXZlIHRocmVlIGRpbWVuc2lvbnMgLSBOLEMsZGltMSwuLi4sZGltblxuICAvLyBvdGhlciBpbnB1dHMgY2FuIGhhdmUgb25seSBvbmUgZGltZW5zaW9uc1xuICBpZiAoWC5kaW1zLmxlbmd0aCA8IDMgfHwgc2NhbGUuZGltcy5sZW5ndGggIT09IDEgfHwgQi5kaW1zLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCBzaGFwZS4nKTtcbiAgfVxuICBpZiAoc2NhbGUuZGltc1swXSAhPT0gWC5kaW1zWzFdIHx8IEIuZGltc1swXSAhPT0gWC5kaW1zWzFdKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBzaGFwZXMgYXJlIG1pc21hdGNoZWQuJyk7XG4gIH1cbiAgaWYgKChYLnR5cGUgIT09ICdmbG9hdDMyJyAmJiBYLnR5cGUgIT09ICdmbG9hdDY0JykgfHwgKHNjYWxlLnR5cGUgIT09ICdmbG9hdDMyJyAmJiBzY2FsZS50eXBlICE9PSAnZmxvYXQ2NCcpIHx8XG4gICAgICAoQi50eXBlICE9PSAnZmxvYXQzMicgJiYgQi50eXBlICE9PSAnZmxvYXQ2NCcpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHR5cGUuJyk7XG4gIH1cbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gNCkge1xuICAgIHRocm93IG5ldyBFcnJvcignT25seSBzdXBwb3J0IDQtRCBpbnB1dCBzaGFwZS4nKTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0F0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi8uLi8uLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgUHJvZ3JhbUluZm9Mb2FkZXIsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgTHJuQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIGFscGhhOiBudW1iZXI7XG4gIGJldGE6IG51bWJlcjtcbiAgYmlhczogbnVtYmVyO1xuICBzaXplOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCBscm46IE9wZXJhdG9ySW1wbGVtZW50YXRpb248THJuQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IExybkF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuXG4gICAgICAvLyBpZiAoaW5mZXJlbmNlSGFuZGxlci5zZXNzaW9uLnBhY2spIHtcbiAgICAgIC8vICAgcmV0dXJuIFtpbmZlcmVuY2VIYW5kbGVyLnJ1bihjcmVhdGVQYWNrZWRMcm5Qcm9ncmFtSW5mb0xvYWRlcihpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIGF0dHJpYnV0ZXMpLFxuICAgICAgLy8gICBpbnB1dHMpXTtcbiAgICAgIC8vIH0gZWxzZSB7XG4gICAgICByZXR1cm4gW2luZmVyZW5jZUhhbmRsZXIucnVuKGNyZWF0ZUxyblByb2dyYW1JbmZvTG9hZGVyKGlucHV0cywgYXR0cmlidXRlcyksIGlucHV0cyldO1xuICAgICAgLy99XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlTHJuQXR0cmlidXRlczogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxMcm5BdHRyaWJ1dGVzPiA9IChub2RlOiBHcmFwaC5Ob2RlKTogTHJuQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGFscGhhID0gbm9kZS5hdHRyaWJ1dGVzLmdldEZsb2F0KCdhbHBoYScsIDAuMDAwMSk7XG4gIGNvbnN0IGJldGEgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0RmxvYXQoJ2JldGEnLCAwLjc1KTtcbiAgY29uc3QgYmlhcyA9IG5vZGUuYXR0cmlidXRlcy5nZXRGbG9hdCgnYmlhcycsIDEuMCk7XG4gIGNvbnN0IHNpemUgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50KCdzaXplJyk7XG5cbiAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7YWxwaGEsIGJldGEsIGJpYXMsIHNpemV9KTtcbn07XG5cbmNvbnN0IGxyblByb2dyYW1NZXRhZGF0YSA9IHtcbiAgbmFtZTogJ0xSTicsXG4gIGlucHV0TmFtZXM6IFsnWCddLFxuICBpbnB1dFR5cGVzOiBbVGV4dHVyZVR5cGUudW5wYWNrZWRdXG59O1xuXG5mdW5jdGlvbiBjcmVhdGVMcm5Qcm9ncmFtSW5mbyhpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBMcm5BdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm8ge1xuICBjb25zdCBDID0gaW5wdXRzWzBdLmRpbXNbMV07XG4gIGNvbnN0IHJhbmsgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGg7XG4gIGNvbnN0IGZyb20gPSAtTWF0aC5mbG9vcigoYXR0cmlidXRlcy5zaXplIC0gMSkgLyAyKTtcbiAgY29uc3QgdG8gPSBNYXRoLmNlaWwoKGF0dHJpYnV0ZXMuc2l6ZSAtIDEpIC8gMik7XG4gIGNvbnN0IGFscGhhID0gYGZsb2F0KCR7YXR0cmlidXRlcy5hbHBoYX0pIC8gZmxvYXQoJHthdHRyaWJ1dGVzLnNpemV9KWA7XG4gIGNvbnN0IGJpYXMgPSBgZmxvYXQoJHthdHRyaWJ1dGVzLmJpYXN9KWA7XG4gIGNvbnN0IGJldGEgPSBgZmxvYXQoJHthdHRyaWJ1dGVzLmJldGF9KWA7XG5cbiAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgIGZsb2F0IHByb2Nlc3MoaW50IGluZGljZXNbJHtyYW5rfV0pIHtcbiAgICAgICAgaW50IGMgPSBpbmRpY2VzWzFdO1xuICAgICAgICBmbG9hdCB4ID0gX1goaW5kaWNlcyk7XG4gICAgICAgIGZsb2F0IHNxdWFyZV9zdW0gPSAwLjA7XG5cbiAgICAgICAgZm9yIChpbnQgaSA9ICR7ZnJvbX07IGkgPD0gJHt0b307IGkrKykge1xuICAgICAgICAgIGludCBpZHggPSBjICsgaTtcbiAgICAgICAgICBpZiAoYyA+PSAwICYmIGMgPCAke0N9KSB7XG4gICAgICAgICAgICBpbmRpY2VzWzFdID0gaWR4O1xuICAgICAgICAgICAgZmxvYXQgaiA9IF9YKGluZGljZXMpO1xuICAgICAgICAgICAgc3F1YXJlX3N1bSArPSBqICogajtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHggLyBwb3coJHtiaWFzfSArICR7YWxwaGF9ICogc3F1YXJlX3N1bSwgJHtiZXRhfSk7XG4gICAgfWA7XG4gIHJldHVybiB7XG4gICAgLi4ubHJuUHJvZ3JhbU1ldGFkYXRhLFxuICAgIGNhY2hlSGludDogYXR0cmlidXRlcy5jYWNoZUtleSxcbiAgICBvdXRwdXQ6IHtkaW1zOiBpbnB1dHNbMF0uZGltcywgdHlwZTogaW5wdXRzWzBdLnR5cGUsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZS51bnBhY2tlZH0sXG4gICAgc2hhZGVyU291cmNlLFxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTHJuUHJvZ3JhbUluZm9Mb2FkZXIoaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogTHJuQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvTG9hZGVyIHtcbiAgcmV0dXJuIHsuLi5scm5Qcm9ncmFtTWV0YWRhdGEsIGNhY2hlSGludDogYXR0cmlidXRlcy5jYWNoZUtleSwgZ2V0OiAoKSA9PiBjcmVhdGVMcm5Qcm9ncmFtSW5mbyhpbnB1dHMsIGF0dHJpYnV0ZXMpfTtcbn1cblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiBUZW5zb3JbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdMUk4gcmVxdWlyZXMgMSBpbnB1dC4nKTtcbiAgfVxuICBpZiAoaW5wdXRzWzBdLmRpbXMubGVuZ3RoICE9PSA0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjdXJyZW50bHkgb25seSBzdXBwb3J0IExSTiBmb3IgaW5wdXQgd2l0aCBcIk5DSFdcIiBmb3JtYXQnKTtcbiAgfVxuICBpZiAoaW5wdXRzWzBdLnR5cGUgIT09ICdmbG9hdDMyJykge1xuICAgIHRocm93IG5ldyBFcnJvcignaW5wdXQgc2hvdWxkIGJlIGZsb2F0IHR5cGUnKTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7QnJvYWRjYXN0VXRpbCwgU2hhcGVVdGlsfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi4vZ2xzbC1zb3VyY2UnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGEsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQge2dldENvb3Jkc0RhdGFUeXBlLCBnZXRHbENoYW5uZWxzfSBmcm9tICcuLi91dGlscyc7XG5cbmltcG9ydCB7Z2V0QWN0aXZhdGlvblNuaXBwZXQsIEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXN9IGZyb20gJy4vZnVzZS11dGlscyc7XG5pbXBvcnQge2dldEJpYXNGb3JNYXRtdWx9IGZyb20gJy4vbWF0bXVsJztcblxuY29uc3QgY3JlYXRlUGFja2VkTWF0bXVsUHJvZ3JhbU1ldGFkYXRhID0gKGhhc0JpYXM6IGJvb2xlYW4sIGNhY2hlSGludDogc3RyaW5nKSA9PiAoe1xuICBuYW1lOiAnTWF0TXVsIChwYWNrZWQpJyxcbiAgaW5wdXROYW1lczogaGFzQmlhcyA/IFsnQScsICdCJywgJ0JpYXMnXSA6IFsnQScsICdCJ10sXG4gIGlucHV0VHlwZXM6IGhhc0JpYXMgPyBbVGV4dHVyZVR5cGUucGFja2VkLCBUZXh0dXJlVHlwZS5wYWNrZWQsIFRleHR1cmVUeXBlLnBhY2tlZF0gOlxuICAgICAgICAgICAgICAgICAgICAgICAgW1RleHR1cmVUeXBlLnBhY2tlZCwgVGV4dHVyZVR5cGUucGFja2VkXSxcbiAgY2FjaGVIaW50XG59KTtcblxuY29uc3QgY3JlYXRlUGFja2VkTWF0bXVsUHJvZ3JhbUluZm8gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIG1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEsIGlucHV0czogVGVuc29yW10sXG4gICAgIGFjdGl2YXRpb25BdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgY29uc3QgaGFzQmlhcyA9IGlucHV0cy5sZW5ndGggPiAyO1xuICAgICAgY29uc3QgcHJvY2Vzc0JpYXMgPSBoYXNCaWFzID8gJ3ZhbHVlICs9IGdldEJpYXNGb3JNYXRtdWwoKTsnIDogJyc7XG4gICAgICBjb25zdCBhU2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgICAgIGNvbnN0IGJTaGFwZSA9IGlucHV0c1sxXS5kaW1zO1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBCcm9hZGNhc3RVdGlsLmNhbGNTaGFwZShhU2hhcGUsIGJTaGFwZSwgdHJ1ZSk7XG4gICAgICBjb25zdCBpc0Jyb2FkY2FzdCA9ICFTaGFwZVV0aWwuYXJlRXF1YWwoaW5wdXRzWzBdLmRpbXMsIGlucHV0c1sxXS5kaW1zKTtcblxuICAgICAgaWYgKCFvdXRwdXRTaGFwZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcJ3QgdXNlIG1hdG11bCBvbiB0aGUgZ2l2ZW4gdGVuc29ycycpO1xuICAgICAgfVxuICAgICAgY29uc3Qgc2hhcmVkRGltID0gYVNoYXBlW2FTaGFwZS5sZW5ndGggLSAxXTtcbiAgICAgIGNvbnN0IHNoYXJlZERpbUluZGV4ID0gTWF0aC5jZWlsKHNoYXJlZERpbSAvIDIpO1xuICAgICAgY29uc3QgYVJhbmsgPSBhU2hhcGUubGVuZ3RoO1xuICAgICAgY29uc3QgYlJhbmsgPSBiU2hhcGUubGVuZ3RoO1xuXG4gICAgICBjb25zdCBnbHNsID0gZ2V0R2xzbChpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24uYmFja2VuZC5nbENvbnRleHQudmVyc2lvbik7XG4gICAgICBjb25zdCBjb29yZHNEYXRhVHlwZSA9IGdldENvb3Jkc0RhdGFUeXBlKG91dHB1dFNoYXBlLmxlbmd0aCk7XG4gICAgICBjb25zdCBvdXRSYW5rID0gb3V0cHV0U2hhcGUubGVuZ3RoO1xuICAgICAgY29uc3QgYWxsR2xDaGFubmVscyA9IGdldEdsQ2hhbm5lbHMoKTtcbiAgICAgIGNvbnN0IHthY3RpdmF0aW9uRnVuY3Rpb24sIGFwcGx5QWN0aXZhdGlvbn0gPSBnZXRBY3RpdmF0aW9uU25pcHBldChhY3RpdmF0aW9uQXR0cmlidXRlcyk7XG5cbiAgICAgIGNvbnN0IGdldEJpYXNGb3JNYXRtdWxTbmlwcGV0ID1cbiAgICAgICAgICBoYXNCaWFzID8gYCR7Z2V0Qmlhc0Zvck1hdG11bChjb29yZHNEYXRhVHlwZSwgYWxsR2xDaGFubmVscywgaW5wdXRzWzJdLmRpbXMsIG91dHB1dFNoYXBlLCB0cnVlKX1gIDogJyc7XG5cbiAgICAgIGNvbnN0IGdldEJjYXN0ZWRTYW1wbGVyRm9yTWF0bXVsU25pcHBldCA9XG4gICAgICAgICAgaXNCcm9hZGNhc3QgPyBgJHtnZXRCY2FzdFNhbXBsZXJGb3JNYXRtdWwoY29vcmRzRGF0YVR5cGUsIGFsbEdsQ2hhbm5lbHMsIGlucHV0cywgb3V0cHV0U2hhcGUpfWAgOiAnJztcblxuICAgICAgY29uc3QgZ2V0U2FtcGxlckFJbkxvb3BTbmlwcGV0ID0gaXNCcm9hZGNhc3QgPyAnZ2V0QUF0T3V0Q29vcmRzTWF0bXVsKGkpJyA6IGBnZXRBKCR7Z2V0QShhbGxHbENoYW5uZWxzLCBhUmFuayl9KWA7XG4gICAgICBjb25zdCBnZXRTYW1wbGVyQkluTG9vcFNuaXBwZXQgPSBpc0Jyb2FkY2FzdCA/ICdnZXRCQXRPdXRDb29yZHNNYXRtdWwoaSknIDogYGdldEIoJHtnZXRCKGFsbEdsQ2hhbm5lbHMsIGJSYW5rKX0pYDtcbiAgICAgIGNvbnN0IGdldE91dHB1dENvb3Jkc1NuaXBwZXQgPSBpc0Jyb2FkY2FzdCA/ICcnIDogYCR7Y29vcmRzRGF0YVR5cGV9IHJjID1cbiAgICAgICAgICBnZXRPdXRwdXRDb29yZHMoKTsgaW50IGxhc3REaW0gPSByYy4ke2FsbEdsQ2hhbm5lbHNbb3V0UmFuayAtIDFdfTsgcmMuJHthbGxHbENoYW5uZWxzW291dFJhbmsgLSAxXX0gPVxuICAgICAgICAgIHJjLiR7YWxsR2xDaGFubmVsc1tvdXRSYW5rIC0gMl19OyByYy4ke2FsbEdsQ2hhbm5lbHNbb3V0UmFuayAtIDJdfSA9IGxhc3REaW07XG4gICAgICBgO1xuICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICAgICAgICAgJHtnZXRCY2FzdGVkU2FtcGxlckZvck1hdG11bFNuaXBwZXR9XG4gICAgICAgICAgICAke2dldEJpYXNGb3JNYXRtdWxTbmlwcGV0fVxuICAgICAgICAgICAgJHthY3RpdmF0aW9uRnVuY3Rpb259XG4gICAgICAgICAgICB2b2lkIG1haW4oKSB7XG4gICAgICAgICAgICAgICR7Z2V0T3V0cHV0Q29vcmRzU25pcHBldH1cblxuICAgICAgICAgICAgICB2ZWM0IHZhbHVlID0gdmVjNCgwKTtcbiAgICAgICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCAke3NoYXJlZERpbUluZGV4fTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmVjNCBhID0gJHtnZXRTYW1wbGVyQUluTG9vcFNuaXBwZXR9O1xuICAgICAgICAgICAgICAgIHZlYzQgYiA9ICR7Z2V0U2FtcGxlckJJbkxvb3BTbmlwcGV0fTtcblxuICAgICAgICAgICAgICAgIHZhbHVlICs9IChhLnJyYmIgKiBiLnJncmcpO1xuICAgICAgICAgICAgICAgIHZhbHVlICs9IChhLmdnYWEgKiBiLmJhYmEpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICR7cHJvY2Vzc0JpYXN9XG4gICAgICAgICAgICAgICR7YXBwbHlBY3RpdmF0aW9ufVxuICAgICAgICAgICAgICAke2dsc2wub3V0cHV0fSA9IHZhbHVlO1xuICAgICAgICAgICAgfWA7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgb3V0cHV0OiB7ZGltczogb3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0c1swXS50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUucGFja2VkfSxcbiAgICAgICAgc2hhZGVyU291cmNlLFxuICAgICAgICBoYXNNYWluOiB0cnVlXG4gICAgICB9O1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVQYWNrZWRNYXRtdWxQcm9ncmFtSW5mb0xvYWRlciA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSxcbiAgICAgYWN0aXZhdGlvbkF0dHJpYnV0ZXM6IEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mb0xvYWRlciA9PiB7XG4gICAgICBjb25zdCBtZXRhZGF0YSA9IGNyZWF0ZVBhY2tlZE1hdG11bFByb2dyYW1NZXRhZGF0YShpbnB1dHMubGVuZ3RoID4gMiwgYWN0aXZhdGlvbkF0dHJpYnV0ZXMuYWN0aXZhdGlvbkNhY2hlS2V5KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZVBhY2tlZE1hdG11bFByb2dyYW1JbmZvKGluZmVyZW5jZUhhbmRsZXIsIG1ldGFkYXRhLCBpbnB1dHMsIGFjdGl2YXRpb25BdHRyaWJ1dGVzKVxuICAgICAgfTtcbiAgICB9O1xuXG5mdW5jdGlvbiBnZXRCY2FzdFNhbXBsZXJGb3JNYXRtdWwoXG4gICAgY29vcmRzRGF0YVR5cGU6IHN0cmluZywgYWxsR2xDaGFubmVsczogcmVhZG9ubHkgc3RyaW5nW10sIGlucHV0czogVGVuc29yW10sIG91dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSk6IHN0cmluZyB7XG4gIGxldCB1bnBhY2tlZEFDb29yZHNTbmlwcGV0ID0gW107XG4gIGxldCB1bnBhY2tlZEJDb29yZHNTbmlwcGV0ID0gW107XG5cbiAgY29uc3QgaW5BU2hhcGUgPSBpbnB1dHNbMF0uZGltcztcbiAgY29uc3QgaW5CU2hhcGUgPSBpbnB1dHNbMV0uZGltcztcblxuICBjb25zdCBpbkFSYW5rID0gaW5BU2hhcGUubGVuZ3RoO1xuICBjb25zdCBpbkJSYW5rID0gaW5CU2hhcGUubGVuZ3RoO1xuXG4gIGNvbnN0IG91dFJhbmsgPSBvdXRTaGFwZS5sZW5ndGg7XG4gIGNvbnN0IHJhbmtBRGlmZiA9IG91dFJhbmsgLSBpbkFSYW5rO1xuICBjb25zdCByYW5rQkRpZmYgPSBvdXRSYW5rIC0gaW5CUmFuaztcblxuICB1bnBhY2tlZEFDb29yZHNTbmlwcGV0ID0gaW5BU2hhcGUubWFwKChzLCBpKSA9PiBgY29vcmRzLiR7YWxsR2xDaGFubmVsc1tpICsgcmFua0FEaWZmXX1gKTtcbiAgdW5wYWNrZWRBQ29vcmRzU25pcHBldFtpbkFSYW5rIC0gMV0gPSAnaSoyJztcbiAgdW5wYWNrZWRBQ29vcmRzU25pcHBldC5qb2luKCcsICcpO1xuICB1bnBhY2tlZEJDb29yZHNTbmlwcGV0ID0gaW5CU2hhcGUubWFwKChzLCBpKSA9PiBgY29vcmRzLiR7YWxsR2xDaGFubmVsc1tpICsgcmFua0JEaWZmXX1gKTtcbiAgdW5wYWNrZWRCQ29vcmRzU25pcHBldFtpbkJSYW5rIC0gMl0gPSAnaSoyJztcbiAgdW5wYWNrZWRCQ29vcmRzU25pcHBldC5qb2luKCcsICcpO1xuXG4gIGNvbnN0IGJyb2FkY2FzdEFEaW1zID0gQnJvYWRjYXN0VXRpbC5nZXRCcm9hZGNhc3REaW1zKGluQVNoYXBlLCBvdXRTaGFwZSk7XG4gIGNvbnN0IGJyb2FkY2FzdEJEaW1zID0gQnJvYWRjYXN0VXRpbC5nZXRCcm9hZGNhc3REaW1zKGluQlNoYXBlLCBvdXRTaGFwZSk7XG5cbiAgY29uc3QgY29vcmRzQVNuaXBwZXQgPSBicm9hZGNhc3RBRGltcy5tYXAoZCA9PiBgY29vcmRzLiR7YWxsR2xDaGFubmVsc1tkICsgcmFua0FEaWZmXX0gPSAwO2ApLmpvaW4oJ1xcbicpO1xuICBjb25zdCBjb29yZHNCU25pcHBldCA9IGJyb2FkY2FzdEJEaW1zLm1hcChkID0+IGBjb29yZHMuJHthbGxHbENoYW5uZWxzW2QgKyByYW5rQkRpZmZdfSA9IDA7YCkuam9pbignXFxuJyk7XG4gIGNvbnN0IHN3YXBEaW1TbmlwcGV0ID0gYGludCBsYXN0RGltID0gY29vcmRzLiR7YWxsR2xDaGFubmVsc1tvdXRSYW5rIC0gMV19O1xuICBjb29yZHMuJHthbGxHbENoYW5uZWxzW291dFJhbmsgLSAxXX0gPSBjb29yZHMuJHthbGxHbENoYW5uZWxzW291dFJhbmsgLSAyXX07XG4gIGNvb3Jkcy4ke2FsbEdsQ2hhbm5lbHNbb3V0UmFuayAtIDJdfSA9IGxhc3REaW07YDtcblxuICBjb25zdCBnZXRCY2FzdFNhbXBsZXJNYXRtdWxTb3VyY2UgPSBgXG52ZWM0IGdldEFBdE91dENvb3Jkc01hdG11bChpbnQgaSkge1xuICAke2Nvb3Jkc0RhdGFUeXBlfSBjb29yZHMgPSBnZXRPdXRwdXRDb29yZHMoKTtcbiAgJHtzd2FwRGltU25pcHBldH1cbiAgJHtjb29yZHNBU25pcHBldH1cbiAgdmVjNCBvdXRwdXRWYWx1ZSA9IGdldEEoJHt1bnBhY2tlZEFDb29yZHNTbmlwcGV0fSk7XG4gIHJldHVybiBvdXRwdXRWYWx1ZTtcbn1cblxudmVjNCBnZXRCQXRPdXRDb29yZHNNYXRtdWwoaW50IGkpIHtcbiAgJHtjb29yZHNEYXRhVHlwZX0gY29vcmRzID0gZ2V0T3V0cHV0Q29vcmRzKCk7XG4gICR7c3dhcERpbVNuaXBwZXR9XG4gICR7Y29vcmRzQlNuaXBwZXR9XG4gIHZlYzQgb3V0cHV0VmFsdWUgPSBnZXRCKCR7dW5wYWNrZWRCQ29vcmRzU25pcHBldH0pO1xuICByZXR1cm4gb3V0cHV0VmFsdWU7XG59YDtcblxuICByZXR1cm4gZ2V0QmNhc3RTYW1wbGVyTWF0bXVsU291cmNlO1xufVxuXG5mdW5jdGlvbiBnZXRBKGFsbEdsQ2hhbm5lbHM6IHN0cmluZ1tdLCByYW5rOiBudW1iZXIpOiBzdHJpbmcge1xuICBsZXQgcmVzID0gJyc7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcmFuayAtIDI7IGkrKykge1xuICAgIHJlcyArPSBgcmMuJHthbGxHbENoYW5uZWxzW2ldfSwgYDtcbiAgfVxuICByZXMgKz0gYHJjLiR7YWxsR2xDaGFubmVsc1tyYW5rIC0gMl19LCBgICtcbiAgICAgICdpKjInO1xuICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiBnZXRCKGFsbEdsQ2hhbm5lbHM6IHN0cmluZ1tdLCByYW5rOiBudW1iZXIpOiBzdHJpbmcge1xuICBsZXQgcmVzID0gJyc7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcmFuayAtIDI7IGkrKykge1xuICAgIHJlcyArPSBgcmMuJHthbGxHbENoYW5uZWxzW2ldfSwgYDtcbiAgfVxuICByZXMgKz0gJ2kqMiwgJyArXG4gICAgICBgcmMuJHthbGxHbENoYW5uZWxzW3JhbmsgLSAxXX1gO1xuICByZXR1cm4gcmVzO1xufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7R3JhcGh9IGZyb20gJy4uLy4uLy4uL2dyYXBoJztcbmltcG9ydCB7T3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi4vLi4vLi4vb3BlcmF0b3JzJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtCcm9hZGNhc3RVdGlsLCBTaGFwZVV0aWx9IGZyb20gJy4uLy4uLy4uL3V0aWwnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGEsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQge2dldENvb3Jkc0RhdGFUeXBlLCBnZXRHbENoYW5uZWxzfSBmcm9tICcuLi91dGlscyc7XG5cbmltcG9ydCB7Z2V0QWN0aXZhdGlvblNuaXBwZXQsIEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMsIHBhcnNlSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlc30gZnJvbSAnLi9mdXNlLXV0aWxzJztcbmltcG9ydCB7Y3JlYXRlUGFja2VkTWF0bXVsUHJvZ3JhbUluZm9Mb2FkZXJ9IGZyb20gJy4vbWF0bXVsLXBhY2snO1xuXG5leHBvcnQgY29uc3QgbWF0TXVsOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzKTtcblxuICAgICAgaWYgKGluZmVyZW5jZUhhbmRsZXIuc2Vzc2lvbi5wYWNrKSB7XG4gICAgICAgIHJldHVybiBbaW5mZXJlbmNlSGFuZGxlci5ydW4oXG4gICAgICAgICAgICBjcmVhdGVQYWNrZWRNYXRtdWxQcm9ncmFtSW5mb0xvYWRlcihpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIGF0dHJpYnV0ZXMpLCBpbnB1dHMpXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBbaW5mZXJlbmNlSGFuZGxlci5ydW4oY3JlYXRlTWF0bXVsUHJvZ3JhbUluZm9Mb2FkZXIoaW5wdXRzLCBhdHRyaWJ1dGVzKSwgaW5wdXRzKV07XG4gICAgICB9XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlTWF0TXVsQXR0cmlidXRlczogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzPiA9XG4gICAgKG5vZGU6IEdyYXBoLk5vZGUpOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzID0+IHBhcnNlSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyhub2RlLmF0dHJpYnV0ZXMpO1xuXG5jb25zdCBjcmVhdGVNYXRtdWxQcm9ncmFtTWV0YWRhdGEgPSAoaGFzQmlhczogYm9vbGVhbiwgY2FjaGVIaW50OiBzdHJpbmcpID0+ICh7XG4gIG5hbWU6ICdNYXRNdWwnLFxuICBpbnB1dE5hbWVzOiBoYXNCaWFzID8gWydBJywgJ0InLCAnQmlhcyddIDogWydBJywgJ0InXSxcbiAgaW5wdXRUeXBlczogaGFzQmlhcyA/IFtUZXh0dXJlVHlwZS51bnBhY2tlZCwgVGV4dHVyZVR5cGUudW5wYWNrZWQsIFRleHR1cmVUeXBlLnVucGFja2VkXSA6XG4gICAgICAgICAgICAgICAgICAgICAgICBbVGV4dHVyZVR5cGUudW5wYWNrZWQsIFRleHR1cmVUeXBlLnVucGFja2VkXSxcbiAgY2FjaGVIaW50XG59KTtcblxuZnVuY3Rpb24gY3JlYXRlTWF0bXVsUHJvZ3JhbUluZm8oXG4gICAgbWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSwgaW5wdXRzOiBUZW5zb3JbXSwgYWN0aXZhdGlvbkF0dHJpYnV0ZXM6IEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyB7XG4gIGNvbnN0IGFTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICBjb25zdCBiU2hhcGUgPSBpbnB1dHNbMV0uZGltcztcbiAgY29uc3Qgb3V0cHV0U2hhcGUgPSBCcm9hZGNhc3RVdGlsLmNhbGNTaGFwZShhU2hhcGUsIGJTaGFwZSwgdHJ1ZSk7XG4gIGlmICghb3V0cHV0U2hhcGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcJ3QgdXNlIG1hdG11bCBvbiB0aGUgZ2l2ZW4gdGVuc29ycycpO1xuICB9XG4gIGNvbnN0IGNvb3Jkc0RhdGFUeXBlID0gZ2V0Q29vcmRzRGF0YVR5cGUob3V0cHV0U2hhcGUubGVuZ3RoKTtcbiAgY29uc3QgYWxsR2xDaGFubmVscyA9IGdldEdsQ2hhbm5lbHMoKTtcbiAgY29uc3Qge2FjdGl2YXRpb25GdW5jdGlvbiwgYXBwbHlBY3RpdmF0aW9ufSA9IGdldEFjdGl2YXRpb25TbmlwcGV0KGFjdGl2YXRpb25BdHRyaWJ1dGVzKTtcblxuICBjb25zdCBoYXNCaWFzID0gaW5wdXRzLmxlbmd0aCA+IDI7XG4gIGNvbnN0IHByb2Nlc3NCaWFzID0gaGFzQmlhcyA/ICd2YWx1ZSArPSBnZXRCaWFzRm9yTWF0bXVsKCk7JyA6ICcnO1xuICBjb25zdCBnZXRCaWFzRm9yTWF0bXVsU25pcHBldCA9XG4gICAgICBoYXNCaWFzID8gYCR7Z2V0Qmlhc0Zvck1hdG11bChjb29yZHNEYXRhVHlwZSwgYWxsR2xDaGFubmVscywgaW5wdXRzWzJdLmRpbXMsIG91dHB1dFNoYXBlLCBmYWxzZSl9YCA6ICcnO1xuXG4gIGNvbnN0IHJhbmsgPSBvdXRwdXRTaGFwZS5sZW5ndGg7XG4gIGNvbnN0IGFyYW5rID0gYVNoYXBlLmxlbmd0aDtcbiAgY29uc3QgYnJhbmsgPSBiU2hhcGUubGVuZ3RoO1xuICBjb25zdCBzaGFyZWREaW0gPSBhU2hhcGVbYVNoYXBlLmxlbmd0aCAtIDFdO1xuICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gICAgJHthY3RpdmF0aW9uRnVuY3Rpb259XG4gICAgJHtnZXRCaWFzRm9yTWF0bXVsU25pcHBldH1cbiAgICBmbG9hdCBwcm9jZXNzKGludCBpbmRpY2VzWyR7cmFua31dKSB7XG4gICAgICAgIGludCBhWyR7YXJhbmt9XTtcbiAgICAgICAgaW50IGJbJHticmFua31dO1xuICAgICAgICBiY2FzdE1hdG11bEluZGljZXNfQShpbmRpY2VzLCBhKTtcbiAgICAgICAgYmNhc3RNYXRtdWxJbmRpY2VzX0IoaW5kaWNlcywgYik7XG5cbiAgICAgICAgZmxvYXQgdmFsdWU7XG4gICAgICAgIGZvciAoaW50IGs9MDsgazwke3NoYXJlZERpbX07ICsraykge1xuICAgICAgICAgICAgYVske2FyYW5rIC0gMX1dID0gaztcbiAgICAgICAgICAgIGJbJHticmFuayAtIDJ9XSA9IGs7XG4gICAgICAgICAgICB2YWx1ZSArPSBfQShhKSAqIF9CKGIpO1xuICAgICAgICB9XG4gICAgICAgICR7cHJvY2Vzc0JpYXN9XG4gICAgICAgICR7YXBwbHlBY3RpdmF0aW9ufVxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfWA7XG4gIHJldHVybiB7XG4gICAgLi4ubWV0YWRhdGEsXG4gICAgb3V0cHV0OiB7ZGltczogb3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0c1swXS50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUudW5wYWNrZWR9LFxuICAgIHNoYWRlclNvdXJjZSxcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZU1hdG11bFByb2dyYW1JbmZvTG9hZGVyKFxuICAgIGlucHV0czogVGVuc29yW10sIGFjdGl2YXRpb25BdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm9Mb2FkZXIge1xuICBjb25zdCBtZXRhZGF0YSA9IGNyZWF0ZU1hdG11bFByb2dyYW1NZXRhZGF0YShpbnB1dHMubGVuZ3RoID4gMiwgYWN0aXZhdGlvbkF0dHJpYnV0ZXMuYWN0aXZhdGlvbkNhY2hlS2V5KTtcbiAgcmV0dXJuIHsuLi5tZXRhZGF0YSwgZ2V0OiAoKSA9PiBjcmVhdGVNYXRtdWxQcm9ncmFtSW5mbyhtZXRhZGF0YSwgaW5wdXRzLCBhY3RpdmF0aW9uQXR0cmlidXRlcyl9O1xufVxuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IFRlbnNvcltdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ01hdE11bCByZXF1aXJlcyAyIGlucHV0cy4nKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0uZGltc1tpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAxXSAhPT0gaW5wdXRzWzFdLmRpbXNbaW5wdXRzWzFdLmRpbXMubGVuZ3RoIC0gMl0pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NoYXJlZCBkaW1lbnNpb24gZG9lcyBub3QgbWF0Y2guJyk7XG4gIH1cblxuICBpZiAoKGlucHV0c1swXS50eXBlICE9PSAnZmxvYXQzMicgJiYgaW5wdXRzWzBdLnR5cGUgIT09ICdmbG9hdDY0JykgfHxcbiAgICAgIChpbnB1dHNbMV0udHlwZSAhPT0gJ2Zsb2F0MzInICYmIGlucHV0c1sxXS50eXBlICE9PSAnZmxvYXQ2NCcpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dHMgc2hvdWxkIGJlIGZsb2F0IHR5cGUnKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0udHlwZSAhPT0gaW5wdXRzWzFdLnR5cGUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2lucHV0cyB0eXBlcyBzaG91bGQgbWF0Y2gnKTtcbiAgfVxufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldEJpYXNGb3JNYXRtdWwoXG4gICAgY29vcmRzRGF0YVR5cGU6IHN0cmluZywgYWxsR2xDaGFubmVsczogcmVhZG9ubHkgc3RyaW5nW10sIGluU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBvdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgaXNQYWNrZWQ6IGJvb2xlYW4pOiBzdHJpbmcge1xuICBsZXQgdW5wYWNrZWRDb29yZHNTbmlwcGV0ID0gJyc7XG4gIGNvbnN0IGluUmFuayA9IGluU2hhcGUubGVuZ3RoO1xuICBjb25zdCBvdXRSYW5rID0gb3V0U2hhcGUubGVuZ3RoO1xuICBjb25zdCByYW5rRGlmZiA9IG91dFJhbmsgLSBpblJhbms7XG4gIGlmIChvdXRSYW5rIDwgMiAmJiBpblJhbmsgPiAwKSB7XG4gICAgdW5wYWNrZWRDb29yZHNTbmlwcGV0ID0gJ2Nvb3Jkcyc7XG4gIH0gZWxzZSB7XG4gICAgdW5wYWNrZWRDb29yZHNTbmlwcGV0ID0gaW5TaGFwZS5tYXAoKHMsIGkpID0+IGBjb29yZHMuJHthbGxHbENoYW5uZWxzW2kgKyByYW5rRGlmZl19YCkuam9pbignLCAnKTtcbiAgfVxuICBjb25zdCBicm9hZGNhc3REaW1zID0gQnJvYWRjYXN0VXRpbC5nZXRCcm9hZGNhc3REaW1zKGluU2hhcGUsIG91dFNoYXBlKTtcbiAgY29uc3QgY29vcmRzU25pcHBldCA9IGJyb2FkY2FzdERpbXMubWFwKGQgPT4gYGNvb3Jkcy4ke2FsbEdsQ2hhbm5lbHNbZCArIHJhbmtEaWZmXX0gPSAwO2ApLmpvaW4oJ1xcbicpO1xuICBjb25zdCBpblNpemUgPSBTaGFwZVV0aWwuc2l6ZShpblNoYXBlKTtcbiAgY29uc3QgaXNJbnB1dFNjYWxhciA9IGluU2l6ZSA9PT0gMTtcbiAgbGV0IG91dHB1dCA9ICd2ZWM0KG91dHB1dFZhbHVlLnh4LCBvdXRwdXRWYWx1ZS55eSknO1xuICBpZiAoaXNJbnB1dFNjYWxhcikge1xuICAgIG91dHB1dCA9ICd2ZWM0KG91dHB1dFZhbHVlLngpJztcbiAgfVxuICBjb25zdCBnZXRCaWFzRm9yTWF0bXVsU291cmNlID0gaXNQYWNrZWQgPyBgXG52ZWM0IGdldEJpYXNGb3JNYXRtdWwoKSB7XG4gICR7Y29vcmRzRGF0YVR5cGV9IGNvb3JkcyA9IGdldE91dHB1dENvb3JkcygpO1xuICAke2Nvb3Jkc1NuaXBwZXR9XG4gIHZlYzQgb3V0cHV0VmFsdWUgPSBnZXRCaWFzKCR7dW5wYWNrZWRDb29yZHNTbmlwcGV0fSk7XG4gIHJldHVybiAke291dHB1dH07XG59YCA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBcbmZsb2F0IGdldEJpYXNGb3JNYXRtdWwoKSB7XG4gICR7Y29vcmRzRGF0YVR5cGV9IGNvb3JkcyA9IGdldE91dHB1dENvb3JkcygpO1xuICAke2Nvb3Jkc1NuaXBwZXR9XG4gIHJldHVybiBnZXRCaWFzKGNvb3Jkcy54KTtcbn1gO1xuXG4gIHJldHVybiBnZXRCaWFzRm9yTWF0bXVsU291cmNlO1xufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtnZXRHbHNsfSBmcm9tICcuLi9nbHNsLXNvdXJjZSc7XG5pbXBvcnQge1dlYkdMSW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi4vaW5mZXJlbmNlLWhhbmRsZXInO1xuaW1wb3J0IHtQcm9ncmFtSW5mbywgUHJvZ3JhbUluZm9Mb2FkZXIsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5pbXBvcnQge2dldENvb3Jkc0RhdGFUeXBlfSBmcm9tICcuLi91dGlscyc7XG5cbmltcG9ydCB7Z2V0Q2hhbm5lbHN9IGZyb20gJy4vcGFja2luZy11dGlscyc7XG5cbmNvbnN0IHBhY2tQcm9ncmFtTWV0YWRhdGEgPSB7XG4gIG5hbWU6ICdwYWNrJyxcbiAgaW5wdXROYW1lczogWydBJ10sXG4gIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS51bnBhY2tlZFJldmVyc2VkXVxufTtcblxuY29uc3QgY3JlYXRlUGFja1Byb2dyYW1JbmZvID0gKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXQ6IFRlbnNvcik6IFByb2dyYW1JbmZvID0+IHtcbiAgY29uc3QgZ2xzbCA9IGdldEdsc2woaGFuZGxlci5zZXNzaW9uLmJhY2tlbmQuZ2xDb250ZXh0LnZlcnNpb24pO1xuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXQuZGltcztcblxuICBjb25zdCBpbnB1dFJhbmsgPSBpbnB1dFNoYXBlLmxlbmd0aDtcbiAgLy8gY3JlYXRlVGV4dHVyZUxheW91dEZyb21TaGFwZSB3b24ndCBjaGFuZ2Ugb3V0cHV0IHJhbmsuIE5lZWQgdG8gdmVyaWZ5IGJ5IHJ1bm5pbmcgdGVzdHNcbiAgY29uc3Qgb3V0cHV0UmFuayA9IGlucHV0LmRpbXMubGVuZ3RoO1xuXG4gIGNvbnN0IGNvb3Jkc0RhdGFUeXBlID0gZ2V0Q29vcmRzRGF0YVR5cGUob3V0cHV0UmFuayk7XG4gIGNvbnN0IGNoYW5uZWxzID0gZ2V0Q2hhbm5lbHMoJ3JjJywgb3V0cHV0UmFuayk7XG4gIGNvbnN0IHNldHVwID0gZ2V0U2V0dXAob3V0cHV0UmFuaywgY2hhbm5lbHMsIGlucHV0U2hhcGVbaW5wdXRTaGFwZS5sZW5ndGggLSAyXSwgaW5wdXRTaGFwZVtpbnB1dFNoYXBlLmxlbmd0aCAtIDFdKTtcblxuICBsZXQgcmV2ZXJzZWRJbnB1dFdIO1xuICBpZiAoaW5wdXRSYW5rID09PSAwKSB7XG4gICAgcmV2ZXJzZWRJbnB1dFdIID0gWzEsIDFdO1xuICB9IGVsc2UgaWYgKGlucHV0UmFuayA9PT0gMSkge1xuICAgIHJldmVyc2VkSW5wdXRXSCA9IFtpbnB1dFNoYXBlWzBdLCAxXTtcbiAgfSBlbHNlIHtcbiAgICByZXZlcnNlZElucHV0V0ggPSBbaW5wdXRTaGFwZVtvdXRwdXRSYW5rIC0gMV0sIGlucHV0U2hhcGVbb3V0cHV0UmFuayAtIDJdXTtcbiAgfVxuICBjb25zdCBvdXRPZkJvdW5kc0NvbmRpdGlvbiA9IGdldE91dE9mQm91bmRzQ29uZGl0aW9uKG91dHB1dFJhbmssIHJldmVyc2VkSW5wdXRXSCwgY2hhbm5lbHMpO1xuICBjb25zdCBvdXRwdXQgPSBnZXRPdXRwdXQoaW5wdXRTaGFwZSwgY2hhbm5lbHMpO1xuXG4gIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAgICAgdm9pZCBtYWluKCkge1xuICAgICAgICAgICR7Y29vcmRzRGF0YVR5cGV9IHJjID0gZ2V0T3V0cHV0Q29vcmRzKCk7XG5cbiAgICAgICAgICBpZigke291dE9mQm91bmRzQ29uZGl0aW9ufSkge1xuICAgICAgICAgICAgJHtnbHNsLm91dHB1dH0gPSB2ZWM0KDApO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAke3NldHVwfVxuXG4gICAgICAgICAgICAke2dsc2wub3V0cHV0fSA9IHZlYzQoJHtvdXRwdXR9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIGA7XG4gIHJldHVybiB7XG4gICAgLi4ucGFja1Byb2dyYW1NZXRhZGF0YSxcbiAgICBoYXNNYWluOiB0cnVlLFxuICAgIG91dHB1dDoge2RpbXM6IGlucHV0LmRpbXMsIHR5cGU6IGlucHV0LnR5cGUsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZS5wYWNrZWR9LFxuICAgIHNoYWRlclNvdXJjZVxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVBhY2tQcm9ncmFtSW5mb0xvYWRlciA9IChoYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0OiBUZW5zb3IpOiBQcm9ncmFtSW5mb0xvYWRlciA9PlxuICAgICh7Li4ucGFja1Byb2dyYW1NZXRhZGF0YSwgZ2V0OiAoKSA9PiBjcmVhdGVQYWNrUHJvZ3JhbUluZm8oaGFuZGxlciwgaW5wdXQpfSk7XG5cbi8qKlxuICogY2hlY2sgb3V0cHV0IGNvb3JkaW5hdGUgbG9jYXRpb24gYW5kIHJldHVybiBmYWxzZSBpZiBpdCBpcyBvdXRzaWRlIGlucHV0J3Mgd2lkdGgvaGVpZ2h0IGJvdW5kYXJ5XG4gKi9cbmZ1bmN0aW9uIGdldE91dE9mQm91bmRzQ29uZGl0aW9uKHJhbms6IG51bWJlciwgc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBkaW1zOiBzdHJpbmdbXSk6IHN0cmluZyB7XG4gIGlmIChyYW5rID09PSAwKSB7XG4gICAgcmV0dXJuICdmYWxzZSc7XG4gIH1cbiAgaWYgKHJhbmsgPT09IDEpIHtcbiAgICByZXR1cm4gYHJjID4gJHtzaGFwZVswXX1gO1xuICB9XG5cbiAgbGV0IGNvbmQgPSAnJztcbiAgZm9yIChsZXQgaSA9IHJhbmsgLSAyOyBpIDwgcmFuazsgaSsrKSB7XG4gICAgY29uZCArPSBgJHtkaW1zW2ldfSA+PSAke3NoYXBlW2kgLSByYW5rICsgMl19YDtcbiAgICBpZiAoaSA8IHJhbmsgLSAxKSB7XG4gICAgICBjb25kICs9ICd8fCc7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGNvbmQ7XG59XG5cbi8qKlxuICogY29kZSBzbmlwcGV0IHRvIHNhbXBsZSBpbnB1dCB0ZXh0dXJlIHdpdGggb3V0cHV0IGNvb3JkaWFudGVzXG4gKi9cbmZ1bmN0aW9uIGdldE91dHB1dChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIGRpbXM6IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgY29uc3QgcmFuayA9IHNoYXBlLmxlbmd0aDtcblxuICBpZiAocmFuayA9PT0gMCkge1xuICAgIHJldHVybiAnZ2V0QSgpLCAwLCAwLCAwJztcbiAgfVxuXG4gIGlmIChyYW5rID09PSAxKSB7XG4gICAgcmV0dXJuIGBnZXRBKHJjKSxcbiAgICAgICAgICAgIHJjICsgMSA+PSAke3NoYXBlWzBdfSA/IDAuIDogZ2V0QShyYyArIDEpLFxuICAgICAgICAgICAgMCwgMGA7XG4gIH1cblxuICBjb25zdCBjb29yZDAwID0gJ3IsIGMnO1xuICBjb25zdCBjb29yZDAxID0gJ3IsIGNwMSc7XG4gIGNvbnN0IGNvb3JkMTAgPSAncnAxLCBjJztcbiAgY29uc3QgY29vcmQxMSA9ICdycDEsIGNwMSc7XG4gIGxldCBEID0gJyc7XG4gIGlmIChyYW5rID4gMikge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcmFuayAtIDI7ICsraSkge1xuICAgICAgRCA9IEQgKyBgJHtkaW1zW2ldfSxgO1xuICAgIH1cbiAgfVxuICByZXR1cm4gYGdldEEoJHtEfSR7Y29vcmQwMH0pLFxuICAgICAgICAgIHJFZGdlID8gMC4gOiBnZXRBKCR7RH0ke2Nvb3JkMTB9KSxcbiAgICAgICAgICBjRWRnZSA/IDAuIDogZ2V0QSgke0R9JHtjb29yZDAxfSksXG4gICAgICAgICAgckVkZ2UgfHwgY0VkZ2UgPyAwLiA6IGdldEEoJHtEfSR7Y29vcmQxMX0pYDtcbn1cblxuLyoqXG4gKiBjb2RlIHNuaXBwZXQgdG8gc2V0dXAgNCBjb29yZGluYXRlcyBhbmQgZWRnZSBjb25kaXRpb25zXG4gKi9cbmZ1bmN0aW9uIGdldFNldHVwKHJhbms6IG51bWJlciwgZGltczogc3RyaW5nW10sIHJvd3M6IG51bWJlciwgY29sczogbnVtYmVyKTogc3RyaW5nIHtcbiAgaWYgKHJhbmsgPT09IDAgfHwgcmFuayA9PT0gMSkge1xuICAgIHJldHVybiAnJztcbiAgfVxuICAvLyByYW5rID49IDIgZm9yIHdpZHRoK2hlaWdodCBwYWNrLlxuICBlbHNlIHtcbiAgICBjb25zdCBzZXR1cCA9IGBcbiAgICBpbnQgciA9ICR7ZGltc1tyYW5rIC0gMl19O1xuICAgIGludCBjID0gJHtkaW1zW3JhbmsgLSAxXX07XG4gICAgaW50IHJwMSA9ICR7ZGltc1tyYW5rIC0gMl19ICsgMTtcbiAgICBpbnQgY3AxID0gJHtkaW1zW3JhbmsgLSAxXX0gKyAxO1xuICAgIGJvb2wgckVkZ2UgPSBycDEgPj0gJHtjb2xzfTtcbiAgICBib29sIGNFZGdlID0gY3AxID49ICR7cm93c307XG4gICAgYDtcbiAgICByZXR1cm4gc2V0dXA7XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge2dldEdsQ2hhbm5lbHN9IGZyb20gJy4uL3V0aWxzJztcblxuZXhwb3J0IGZ1bmN0aW9uIGdldFZlY0NoYW5uZWxzKG5hbWU6IHN0cmluZywgcmFuazogbnVtYmVyKTogc3RyaW5nW10ge1xuICByZXR1cm4gZ2V0R2xDaGFubmVscyhyYW5rKS5tYXAoZCA9PiBgJHtuYW1lfS4ke2R9YCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDaGFubmVscyhuYW1lOiBzdHJpbmcsIHJhbms6IG51bWJlcik6IHN0cmluZ1tdIHtcbiAgaWYgKHJhbmsgPT09IDEpIHtcbiAgICByZXR1cm4gW25hbWVdO1xuICB9XG4gIHJldHVybiBnZXRWZWNDaGFubmVscyhuYW1lLCByYW5rKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHVucGFja0Zyb21DaGFubmVsKCk6IHN0cmluZyB7XG4gIHJldHVybiBgXG4gICAgZmxvYXQgZ2V0Q2hhbm5lbCh2ZWM0IGZyYWcsIGludCBkaW0pIHtcbiAgICAgIGludCBtb2RDb29yZCA9IGltb2QoZGltLCAyKTtcbiAgICAgIHJldHVybiBtb2RDb29yZCA9PSAwID8gZnJhZy5yIDogZnJhZy5nO1xuICAgIH1cblxuICAgIGZsb2F0IGdldENoYW5uZWwodmVjNCBmcmFnLCB2ZWMyIGlubmVyRGltcykge1xuICAgICAgdmVjMiBtb2RDb29yZCA9IG1vZChpbm5lckRpbXMsIDIuKTtcbiAgICAgIHJldHVybiBtb2RDb29yZC54ID09IDAuID9cbiAgICAgICAgKG1vZENvb3JkLnkgPT0gMC4gPyBmcmFnLnIgOiBmcmFnLmcpIDpcbiAgICAgICAgKG1vZENvb3JkLnkgPT0gMC4gPyBmcmFnLmIgOiBmcmFnLmEpO1xuICAgIH1cbiAgYDtcbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0F0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi8uLi8uLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi4vLi4vLi4vZ3JhcGgnO1xuaW1wb3J0IHtPcGVyYXRvckltcGxlbWVudGF0aW9uLCBPcGVyYXRvckluaXRpYWxpemF0aW9ufSBmcm9tICcuLi8uLi8uLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1NoYXBlVXRpbH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQge2dldEdsc2wsIEdsc2x9IGZyb20gJy4uL2dsc2wtc291cmNlJztcbmltcG9ydCB7V2ViR0xJbmZlcmVuY2VIYW5kbGVyfSBmcm9tICcuLi9pbmZlcmVuY2UtaGFuZGxlcic7XG5pbXBvcnQge1Byb2dyYW1JbmZvLCBUZXh0dXJlVHlwZX0gZnJvbSAnLi4vdHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFBhZEF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBtb2RlOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHBhZHM6IG51bWJlcltdO1xuICByZWFkb25seSB2YWx1ZTogbnVtYmVyO1xufVxuXG5jb25zdCBwYWRQcm9ncmFtTWV0YWRhdGEgPSB7XG4gIG5hbWU6ICdQYWQnLFxuICBpbnB1dE5hbWVzOiBbJ0EnXSxcbiAgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnVucGFja2VkXSxcbn07XG5cbmV4cG9ydCBjb25zdCBwYWRWMjogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxQYWRBdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogUGFkQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzVjIoaW5wdXRzKTtcbiAgICAgIGNvbnN0IG91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIC4uLnBhZFByb2dyYW1NZXRhZGF0YSxcbiAgICAgICAgICAgIGNhY2hlSGludDogYXR0cmlidXRlcy5jYWNoZUtleSxcbiAgICAgICAgICAgIGdldDogKCkgPT4gY3JlYXRlUGFkUHJvZ3JhbUluZm8oaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzWzBdLCBhdHRyaWJ1dGVzKVxuICAgICAgICAgIH0sXG4gICAgICAgICAgaW5wdXRzKTtcbiAgICAgIHJldHVybiBbb3V0cHV0XTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcGFyc2VQYWRBdHRyaWJ1dGVzVjI6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248UGFkQXR0cmlidXRlcz4gPSAobm9kZTogR3JhcGguTm9kZSk6IFBhZEF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBtb2RlID0gbm9kZS5hdHRyaWJ1dGVzLmdldFN0cmluZygnbW9kZScsICdjb25zdGFudCcpO1xuICBjb25zdCB2YWx1ZSA9IG5vZGUuYXR0cmlidXRlcy5nZXRGbG9hdCgndmFsdWUnLCAwLjApO1xuICBjb25zdCBwYWRzID0gbm9kZS5hdHRyaWJ1dGVzLmdldEludHMoJ3BhZHMnKTtcbiAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7bW9kZSwgdmFsdWUsIHBhZHN9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYWRWMTE6IE9wZXJhdG9ySW1wbGVtZW50YXRpb248c3RyaW5nPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgbW9kZTogc3RyaW5nKTogVGVuc29yW10gPT4ge1xuICAgICAgdmFsaWRhdGVJbnB1dHNWMTEoaW5wdXRzKTtcbiAgICAgIGNvbnN0IGF0dHJ1YnV0ZXMgPSBnZW5lcmF0ZVBhZEF0dHJpYnV0ZXNGcm9tSW5wdXRzKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgbW9kZSk7XG4gICAgICByZXR1cm4gcGFkVjIoaW5mZXJlbmNlSGFuZGxlciwgW2lucHV0c1swXV0sIGF0dHJ1YnV0ZXMpO1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBwYXJzZVBhZEF0dHJpYnV0ZXNWMTE6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248c3RyaW5nPiA9IChub2RlOiBHcmFwaC5Ob2RlKTogc3RyaW5nID0+XG4gICAgbm9kZS5hdHRyaWJ1dGVzLmdldFN0cmluZygnbW9kZScsICdjb25zdGFudCcpO1xuXG5jb25zdCBnZW5lcmF0ZVBhZEF0dHJpYnV0ZXNGcm9tSW5wdXRzID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBtb2RlOiBzdHJpbmcpOiBQYWRBdHRyaWJ1dGVzID0+IHtcbiAgICAgIGlmICghaW5mZXJlbmNlSGFuZGxlci5zZXNzaW9uLmlzSW5pdGlhbGl6ZXIoaW5wdXRzWzFdLmRhdGFJZCkgfHxcbiAgICAgICAgICAoaW5wdXRzLmxlbmd0aCA+PSAzICYmICFpbmZlcmVuY2VIYW5kbGVyLnNlc3Npb24uaXNJbml0aWFsaXplcihpbnB1dHNbMl0uZGF0YUlkKSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkeW5hbWljIHBhZCBhdHRyaWJ1dGVzIGFyZSBub3QgYWxsb3dlZCcpO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwYWRzID0gQXJyYXkuZnJvbShpbnB1dHNbMV0uaW50ZWdlckRhdGEpO1xuICAgICAgY29uc3QgdmFsdWUgPSAoaW5wdXRzLmxlbmd0aCA+PSAzKSA/IGlucHV0c1syXS5mbG9hdERhdGFbMF0gOiAwLjA7XG5cbiAgICAgIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe21vZGUsIHBhZHMsIHZhbHVlfSk7XG4gICAgfTtcblxuY29uc3QgY3JlYXRlUGFkUHJvZ3JhbUluZm8gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0OiBUZW5zb3IsIGF0dHJpYnV0ZXM6IFBhZEF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICBjb25zdCBvdXRwdXRTaGFwZSA9IFNoYXBlVXRpbC5wYWRTaGFwZShpbnB1dC5kaW1zLnNsaWNlKCksIGF0dHJpYnV0ZXMucGFkcyk7XG4gICAgICBjb25zdCByYW5rID0gb3V0cHV0U2hhcGUubGVuZ3RoO1xuICAgICAgY29uc3QgcGFkRnVuY3Rpb24gPSBnZXRQYWRGdW5jdGlvbihpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dCwgYXR0cmlidXRlcyk7XG4gICAgICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gICAgICAke3BhZEZ1bmN0aW9ufVxuICAgICAgZmxvYXQgcHJvY2VzcyhpbnRbJHtyYW5rfV0gaW5kaWNlcykge1xuICAgICAgICAgIHJldHVybiBwYWRBKGluZGljZXMpO1xuICAgICAgfWA7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBuYW1lOiAnUGFkJyxcbiAgICAgICAgaW5wdXROYW1lczogWydBJ10sXG4gICAgICAgIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS51bnBhY2tlZF0sXG4gICAgICAgIG91dHB1dDoge2RpbXM6IG91dHB1dFNoYXBlLCB0eXBlOiBpbnB1dC50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUudW5wYWNrZWR9LFxuICAgICAgICBzaGFkZXJTb3VyY2VcbiAgICAgIH07XG4gICAgfTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHNWMiA9IChpbnB1dHM6IFRlbnNvcltdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1BhZCByZXF1aXJlcyAxIGlucHV0Jyk7XG4gIH1cbiAgaWYgKGlucHV0c1swXS50eXBlICE9PSAnZmxvYXQzMicgJiYgaW5wdXRzWzBdLnR5cGUgIT09ICdmbG9hdDY0Jykge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCB0eXBlLicpO1xuICB9XG59O1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0c1YxMSA9IChpbnB1dHM6IFRlbnNvcltdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IChpbnB1dHMubGVuZ3RoICE9PSAyICYmIGlucHV0cy5sZW5ndGggIT09IDMpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQYWQgcmVxdWlyZXMgMiBvciAzIGlucHV0cycpO1xuICB9XG4gIGlmIChpbnB1dHNbMV0udHlwZSAhPT0gJ2ludDMyJykge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCB0eXBlLicpO1xuICB9XG4gIGlmIChpbnB1dHMubGVuZ3RoID49IDMgJiYgaW5wdXRzWzJdLnR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHR5cGUuJyk7XG4gIH1cbn07XG5cbmNvbnN0IGdldFBhZEZ1bmN0aW9uID0gKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXQ6IFRlbnNvciwgYXR0cmlidXRlczogUGFkQXR0cmlidXRlcyk6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGdsc2wgPSBnZXRHbHNsKGluZmVyZW5jZUhhbmRsZXIuc2Vzc2lvbi5iYWNrZW5kLmdsQ29udGV4dC52ZXJzaW9uKTtcbiAgY29uc3QgW3dpZHRoLCBoZWlnaHRdID0gaW5mZXJlbmNlSGFuZGxlci5jYWxjdWxhdGVUZXh0dXJlV2lkdGhBbmRIZWlnaHQoaW5wdXQuZGltcywgVGV4dHVyZVR5cGUudW5wYWNrZWQpO1xuICBjb25zdCBzdHJpZGVzID0gU2hhcGVVdGlsLmNvbXB1dGVTdHJpZGVzKGlucHV0LmRpbXMpO1xuXG4gIHN3aXRjaCAoYXR0cmlidXRlcy5tb2RlKSB7XG4gICAgY2FzZSAnY29uc3RhbnQnOlxuICAgICAgcmV0dXJuIGdldFBhZENvbnN0YW50KGdsc2wsIGlucHV0LmRpbXMsIHN0cmlkZXMsIHdpZHRoLCBoZWlnaHQsIGF0dHJpYnV0ZXMucGFkcywgYXR0cmlidXRlcy52YWx1ZSk7XG4gICAgY2FzZSAncmVmbGVjdCc6XG4gICAgICByZXR1cm4gZ2V0UGFkUmVmbGVjdChnbHNsLCBpbnB1dC5kaW1zLCBzdHJpZGVzLCB3aWR0aCwgaGVpZ2h0LCBhdHRyaWJ1dGVzLnBhZHMpO1xuICAgIGNhc2UgJ2VkZ2UnOlxuICAgICAgcmV0dXJuIGdldFBhZEVkZ2UoZ2xzbCwgaW5wdXQuZGltcywgc3RyaWRlcywgd2lkdGgsIGhlaWdodCwgYXR0cmlidXRlcy5wYWRzKTtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG1vZGUnKTtcbiAgfVxufTtcblxuY29uc3QgZ2V0UGFkQ29uc3RhbnQgPVxuICAgIChnbHNsOiBHbHNsLCBzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdLCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciwgcGFkczogbnVtYmVyW10sXG4gICAgIHZhbHVlOiBudW1iZXIpOiBzdHJpbmcgPT4ge1xuICAgICAgY29uc3QgcmFuayA9IHNoYXBlLmxlbmd0aDtcbiAgICAgIGxldCBibG9jayA9ICcnO1xuICAgICAgZm9yIChsZXQgaSA9IHJhbmsgLSAxOyBpID49IDA7IC0taSkge1xuICAgICAgICBibG9jayArPSBgXG4gICAgICAgIGsgPSBtWyR7aX1dIC0gJHtwYWRzW2ldfTtcbiAgICAgICAgaWYgKGsgPCAwKSAgcmV0dXJuIGNvbnN0YW50O1xuICAgICAgICBpZiAoayA+PSAke3NoYXBlW2ldfSkgcmV0dXJuIGNvbnN0YW50O1xuICAgICAgICBvZmZzZXQgKz0gayAqICR7c3RyaWRlc1tpXX07XG4gICAgICAgIGA7XG4gICAgICB9XG4gICAgICByZXR1cm4gYFxuICAgICAgZmxvYXQgcGFkQShpbnQgbVske3Jhbmt9XSkge1xuICAgICAgICBjb25zdCBmbG9hdCBjb25zdGFudCA9IGZsb2F0KCR7dmFsdWV9KTtcbiAgICAgICAgaW50IG9mZnNldCA9IDA7XG4gICAgICAgIGludCBrID0gMDtcbiAgICAgICAgJHtibG9ja31cbiAgICAgICAgdmVjMiBjb29yZHMgPSBvZmZzZXRUb0Nvb3JkcyhvZmZzZXQsICR7d2lkdGh9LCAke2hlaWdodH0pO1xuICAgICAgICBmbG9hdCB2YWx1ZSA9IGdldENvbG9yQXNGbG9hdCgke2dsc2wudGV4dHVyZTJEfShBLCBjb29yZHMpKTtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgfVxuICAgICAgYDtcbiAgICB9O1xuXG5jb25zdCBnZXRQYWRSZWZsZWN0ID1cbiAgICAoZ2xzbDogR2xzbCwgc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXSwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIsIHBhZHM6IG51bWJlcltdKTpcbiAgICAgICAgc3RyaW5nID0+IHtcbiAgICAgICAgICBjb25zdCByYW5rID0gc2hhcGUubGVuZ3RoO1xuXG4gICAgICAgICAgbGV0IGJsb2NrID0gJyc7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IHJhbmsgLSAxOyBpID49IDA7IC0taSkge1xuICAgICAgICAgICAgYmxvY2sgKz0gYFxuICAgICAgICBrID0gbVske2l9XSAtICR7cGFkc1tpXX07XG4gICAgICAgIGlmIChrIDwgMCkgeyBrID0gLWs7IH1cbiAgICAgICAge1xuICAgICAgICAgIGNvbnN0IGludCBfMm5fMSA9ICR7MiAqIChzaGFwZVtpXSAtIDEpfTtcbiAgICAgICAgICBrID0gaW50KCBtb2QoIGZsb2F0KGspLCBmbG9hdChfMm5fMSkgKSApIDtcbiAgICAgICAgICBpZihrID49ICR7c2hhcGVbaV19KSB7IGsgPSBfMm5fMSAtIGs7IH1cbiAgICAgICAgfVxuICAgICAgICBvZmZzZXQgKz0gayAqICR7c3RyaWRlc1tpXX07XG4gICAgICAgIGA7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBgXG4gICAgICBmbG9hdCBwYWRBKGludCBtWyR7cmFua31dKSB7XG4gICAgICAgIGludCBvZmZzZXQgPSAwO1xuICAgICAgICBpbnQgayA9IDA7XG4gICAgICAgICR7YmxvY2t9XG4gICAgICAgIHZlYzIgY29vcmRzID0gb2Zmc2V0VG9Db29yZHMob2Zmc2V0LCAke3dpZHRofSwgJHtoZWlnaHR9KTtcbiAgICAgICAgZmxvYXQgdmFsdWUgPSBnZXRDb2xvckFzRmxvYXQoJHtnbHNsLnRleHR1cmUyRH0oQSwgY29vcmRzKSk7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIGA7XG4gICAgICAgIH07XG5cbmNvbnN0IGdldFBhZEVkZ2UgPVxuICAgIChnbHNsOiBHbHNsLCBzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdLCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlciwgcGFkczogbnVtYmVyW10pOlxuICAgICAgICBzdHJpbmcgPT4ge1xuICAgICAgICAgIGNvbnN0IHJhbmsgPSBzaGFwZS5sZW5ndGg7XG5cbiAgICAgICAgICBsZXQgYmxvY2sgPSAnJztcbiAgICAgICAgICBmb3IgKGxldCBpID0gcmFuayAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgICAgICBibG9jayArPSBgXG4gICAgICAgIGsgPSBtWyR7aX1dIC0gJHtwYWRzW2ldfTtcbiAgICAgICAgaWYgKGsgPCAwKSAgayA9IDA7XG4gICAgICAgIGlmIChrID49ICR7c2hhcGVbaV19KSBrID0gJHtzaGFwZVtpXSAtIDF9O1xuICAgICAgICBvZmZzZXQgKz0gayAqICR7c3RyaWRlc1tpXX07XG4gICAgICBgO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gYFxuICAgICAgZmxvYXQgcGFkQShpbnQgbVske3Jhbmt9XSkge1xuICAgICAgICBpbnQgb2Zmc2V0ID0gMDtcbiAgICAgICAgaW50IGsgPSAwO1xuICAgICAgICAke2Jsb2NrfVxuICAgICAgICB2ZWMyIGNvb3JkcyA9IG9mZnNldFRvQ29vcmRzKG9mZnNldCwgJHt3aWR0aH0sICR7aGVpZ2h0fSk7XG4gICAgICAgIGZsb2F0IHZhbHVlID0gZ2V0Q29sb3JBc0Zsb2F0KCR7Z2xzbC50ZXh0dXJlMkR9KEEsIGNvb3JkcykpO1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9XG4gICAgICBgO1xuICAgICAgICB9O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7QXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXl9IGZyb20gJy4uLy4uLy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQge0dyYXBofSBmcm9tICcuLi8uLi8uLi9ncmFwaCc7XG5pbXBvcnQge09wZXJhdG9ySW1wbGVtZW50YXRpb24sIE9wZXJhdG9ySW5pdGlhbGl6YXRpb259IGZyb20gJy4uLy4uLy4uL29wZXJhdG9ycyc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7UG9vbENvbnZVdGlsLCBTaGFwZVV0aWx9IGZyb20gJy4uLy4uLy4uL3V0aWwnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1NZXRhZGF0YSwgVGV4dHVyZVR5cGV9IGZyb20gJy4uL3R5cGVzJztcblxuZXhwb3J0IGludGVyZmFjZSBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBhdXRvUGFkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNlaWxNb2RlOiBudW1iZXI7XG4gIHJlYWRvbmx5IGNvdW50SW5jbHVkZVBhZDogYm9vbGVhbjtcbiAgcmVhZG9ubHkga2VybmVsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgcGFkczogcmVhZG9ubHkgbnVtYmVyW107XG59XG5cbmV4cG9ydCBjb25zdCBhdmVyYWdlUG9vbDogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxBdmVyYWdlUG9vbEF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuICAgICAgY29uc3QgbWV0YWRhdGEgPVxuICAgICAgICAgIHtuYW1lOiAnQXZlcmFnZVBvb2wnLCBpbnB1dE5hbWVzOiBbJ1gnXSwgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnVucGFja2VkXSwgY2FjaGVIaW50OiBhdHRyaWJ1dGVzLmNhY2hlS2V5fTtcbiAgICAgIGNvbnN0IG91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgIHsuLi5tZXRhZGF0YSwgZ2V0OiAoKSA9PiBjcmVhdGVBdmVyYWdlUG9vbFByb2dyYW1JbmZvKGlucHV0cywgbWV0YWRhdGEsIGZhbHNlLCBhdHRyaWJ1dGVzKX0sIGlucHV0cyk7XG4gICAgICByZXR1cm4gW291dHB1dF07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlQXZlcmFnZVBvb2xBdHRyaWJ1dGVzOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPEF2ZXJhZ2VQb29sQXR0cmlidXRlcz4gPVxuICAgIChub2RlOiBHcmFwaC5Ob2RlKTogQXZlcmFnZVBvb2xBdHRyaWJ1dGVzID0+IHtcbiAgICAgIGNvbnN0IGF1dG9QYWQgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0U3RyaW5nKCdhdXRvX3BhZCcsICdOT1RTRVQnKTtcbiAgICAgIGNvbnN0IGNlaWxNb2RlID0gbm9kZS5hdHRyaWJ1dGVzLmdldEludCgnY2VpbF9tb2RlJywgMCk7XG4gICAgICBjb25zdCBjb3VudEluY2x1ZGVQYWQgPSAobm9kZS5hdHRyaWJ1dGVzLmdldEludCgnY291bnRfaW5jbHVkZV9wYWQnLCAwKSA9PT0gMCA/IGZhbHNlIDogdHJ1ZSk7XG4gICAgICBjb25zdCBrZXJuZWxTaGFwZSA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnRzKCdrZXJuZWxfc2hhcGUnKTtcbiAgICAgIGNvbnN0IHN0cmlkZXMgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50cygnc3RyaWRlcycsIFtdKTtcbiAgICAgIGNvbnN0IHBhZHMgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50cygncGFkcycsIFtdKTtcblxuICAgICAgLy8gVE9ETzogc3VwcG9ydCBhdHRyaWJ1dGUgJ2NlaWxfbW9kZSdcbiAgICAgIGlmIChjZWlsTW9kZSAhPT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3VzaW5nIGNlaWwoKSBpbiBzaGFwZSBjb21wdXRhdGlvbiBpcyBub3QgeWV0IHN1cHBvcnRlZCBmb3IgQXZlcmFnZVBvb2wnKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7YXV0b1BhZCwgY2VpbE1vZGUsIGNvdW50SW5jbHVkZVBhZCwga2VybmVsU2hhcGUsIHN0cmlkZXMsIHBhZHN9KTtcbiAgICB9O1xuXG5jb25zdCBjcmVhdGVBdmVyYWdlUG9vbFByb2dyYW1JbmZvID1cbiAgICAoaW5wdXRzOiBUZW5zb3JbXSwgbWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSwgaXNHbG9iYWxPcGVyYXRvcjogYm9vbGVhbiwgYXR0cmlidXRlczogQXZlcmFnZVBvb2xBdHRyaWJ1dGVzKTpcbiAgICAgICAgUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgICAgIGNvbnN0IFthZGp1c3RlZEF0dHJpYnV0ZXMsIG91dHB1dFNoYXBlXSA9XG4gICAgICAgICAgICAgIGdldEFkanVzdGVkUG9vbEF0dHJpYnV0ZXNBbmRPdXRwdXRTaGFwZShpbnB1dHMsIGF0dHJpYnV0ZXMsIGlzR2xvYmFsT3BlcmF0b3IpO1xuICAgICAgICAgIGNvbnN0IGtlcm5lbFNpemUgPSBTaGFwZVV0aWwuc2l6ZShhZGp1c3RlZEF0dHJpYnV0ZXMua2VybmVsU2hhcGUpO1xuICAgICAgICAgIGNvbnN0IG9wMSA9ICd2YWx1ZSArPSBfWCh4KTsnO1xuICAgICAgICAgIGxldCBvcDIgPSAnJztcbiAgICAgICAgICBpZiAoYWRqdXN0ZWRBdHRyaWJ1dGVzLmNvdW50SW5jbHVkZVBhZCkge1xuICAgICAgICAgICAgb3AyICs9IGB2YWx1ZSAvPSBmbG9hdCgke2tlcm5lbFNpemV9KTtgO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvcDIgKz0gYHZhbHVlIC89IGZsb2F0KCR7a2VybmVsU2l6ZX0gLSBwYWQpO2A7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IHBvb2xpbmdDb2RlID0gZ2VuZXJhdGVQb29saW5nQ29kZShpbnB1dHNbMF0uZGltcywgYWRqdXN0ZWRBdHRyaWJ1dGVzLCBvcDEsIG9wMiwgJzAuMCcpO1xuICAgICAgICAgIGNvbnN0IHNoYWRlclNvdXJjZSA9IGBcbiAgICAgICAgJHtwb29saW5nQ29kZX1cbiAgICAgIGA7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICAgICAgb3V0cHV0OiB7ZGltczogb3V0cHV0U2hhcGUsIHR5cGU6IGlucHV0c1swXS50eXBlLCB0ZXh0dXJlVHlwZTogVGV4dHVyZVR5cGUudW5wYWNrZWR9LFxuICAgICAgICAgICAgc2hhZGVyU291cmNlXG4gICAgICAgICAgfTtcbiAgICAgICAgfTtcblxuZXhwb3J0IGNvbnN0IGdsb2JhbEF2ZXJhZ2VQb29sOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPEF2ZXJhZ2VQb29sQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IEF2ZXJhZ2VQb29sQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cyk7XG4gICAgICBjb25zdCBtZXRhZGF0YSA9IHtcbiAgICAgICAgbmFtZTogJ0dsb2JhbEF2ZXJhZ2VQb29sJyxcbiAgICAgICAgaW5wdXROYW1lczogWydYJ10sXG4gICAgICAgIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS51bnBhY2tlZF0sXG4gICAgICAgIGNhY2hlSGludDogYCR7YXR0cmlidXRlcy5jb3VudEluY2x1ZGVQYWR9YFxuICAgICAgfTtcbiAgICAgIGNvbnN0IG91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgIHsuLi5tZXRhZGF0YSwgZ2V0OiAoKSA9PiBjcmVhdGVBdmVyYWdlUG9vbFByb2dyYW1JbmZvKGlucHV0cywgbWV0YWRhdGEsIHRydWUsIGF0dHJpYnV0ZXMpfSwgaW5wdXRzKTtcbiAgICAgIHJldHVybiBbb3V0cHV0XTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcGFyc2VHbG9iYWxBdmVyYWdlUG9vbEF0dHJpYnV0ZXM6IE9wZXJhdG9ySW5pdGlhbGl6YXRpb248QXZlcmFnZVBvb2xBdHRyaWJ1dGVzPiA9XG4gICAgKG5vZGU6IEdyYXBoLk5vZGUpOiBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMgPT4ge1xuICAgICAgY29uc3QgY291bnRJbmNsdWRlUGFkID0gKG5vZGUuYXR0cmlidXRlcy5nZXRJbnQoJ2NvdW50X2luY2x1ZGVfcGFkJywgMCkgPT09IDAgPyBmYWxzZSA6IHRydWUpO1xuICAgICAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleShcbiAgICAgICAgICB7YXV0b1BhZDogJycsIGNlaWxNb2RlOiAwLCBjb3VudEluY2x1ZGVQYWQsIGtlcm5lbFNoYXBlOiBbXSwgc3RyaWRlczogW10sIHBhZHM6IFtdfSk7XG4gICAgfTtcblxuZXhwb3J0IGludGVyZmFjZSBNYXhQb29sQXR0cmlidXRlcyBleHRlbmRzIEF2ZXJhZ2VQb29sQXR0cmlidXRlcyB7XG4gIHJlYWRvbmx5IHN0b3JhZ2VPcmRlcjogbnVtYmVyO1xuICByZWFkb25seSBkaWxhdGlvbnM6IG51bWJlcltdO1xufVxuXG5leHBvcnQgY29uc3QgbWF4UG9vbDogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxNYXhQb29sQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IE1heFBvb2xBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgdmFsaWRhdGVJbnB1dHMoaW5wdXRzKTtcbiAgICAgIGNvbnN0IG1ldGFkYXRhID1cbiAgICAgICAgICB7bmFtZTogJ01heFBvb2wnLCBpbnB1dE5hbWVzOiBbJ1gnXSwgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnVucGFja2VkXSwgY2FjaGVIaW50OiBhdHRyaWJ1dGVzLmNhY2hlS2V5fTtcbiAgICAgIGNvbnN0IG91dHB1dCA9IGluZmVyZW5jZUhhbmRsZXIucnVuKFxuICAgICAgICAgIHsuLi5tZXRhZGF0YSwgZ2V0OiAoKSA9PiBjcmVhdGVNYXhQb29sUHJvZ3JhbUluZm8oaW5wdXRzLCBtZXRhZGF0YSwgZmFsc2UsIGF0dHJpYnV0ZXMpfSwgaW5wdXRzKTtcbiAgICAgIHJldHVybiBbb3V0cHV0XTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcGFyc2VNYXhQb29sQXR0cmlidXRlczogT3BlcmF0b3JJbml0aWFsaXphdGlvbjxNYXhQb29sQXR0cmlidXRlcz4gPVxuICAgIChub2RlOiBHcmFwaC5Ob2RlKTogTWF4UG9vbEF0dHJpYnV0ZXMgPT4ge1xuICAgICAgY29uc3QgYXV0b1BhZCA9IG5vZGUuYXR0cmlidXRlcy5nZXRTdHJpbmcoJ2F1dG9fcGFkJywgJ05PVFNFVCcpO1xuICAgICAgY29uc3QgY2VpbE1vZGUgPSBub2RlLmF0dHJpYnV0ZXMuZ2V0SW50KCdjZWlsX21vZGUnLCAwKTtcbiAgICAgIGNvbnN0IGtlcm5lbFNoYXBlID0gbm9kZS5hdHRyaWJ1dGVzLmdldEludHMoJ2tlcm5lbF9zaGFwZScpO1xuICAgICAgY29uc3Qgc3RyaWRlcyA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnRzKCdzdHJpZGVzJywgW10pO1xuICAgICAgY29uc3QgcGFkcyA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnRzKCdwYWRzJywgW10pO1xuICAgICAgY29uc3Qgc3RvcmFnZU9yZGVyID0gbm9kZS5hdHRyaWJ1dGVzLmdldEludCgnc3RvcmFnZV9vcmRlcicsIDApO1xuICAgICAgY29uc3QgZGlsYXRpb25zID0gbm9kZS5hdHRyaWJ1dGVzLmdldEludHMoJ2RpbGF0aW9ucycsIFtdKTtcblxuICAgICAgLy8gVE9ETzogc3VwcG9ydCBhdHRyaWJ1dGUgJ2NlaWxfbW9kZScgYW5kICdzdG9yYWdlX29yZGVyJ1xuICAgICAgaWYgKHN0b3JhZ2VPcmRlciAhPT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvbHVtbiBtYWpvciBzdG9yYWdlIG9yZGVyIGlzIG5vdCB5ZXQgc3VwcG9ydGVkIGZvciBNYXhQb29sJyk7XG4gICAgICB9XG4gICAgICBpZiAoY2VpbE1vZGUgIT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd1c2luZyBjZWlsKCkgaW4gc2hhcGUgY29tcHV0YXRpb24gaXMgbm90IHlldCBzdXBwb3J0ZWQgZm9yIE1heFBvb2wnKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleShcbiAgICAgICAgICB7YXV0b1BhZCwgY2VpbE1vZGUsIGNvdW50SW5jbHVkZVBhZDogZmFsc2UsIGtlcm5lbFNoYXBlLCBzdHJpZGVzLCBwYWRzLCBzdG9yYWdlT3JkZXIsIGRpbGF0aW9uc30pO1xuICAgIH07XG5cbmNvbnN0IGNyZWF0ZU1heFBvb2xQcm9ncmFtSW5mbyA9XG4gICAgKGlucHV0czogVGVuc29yW10sIG1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEsIGlzR2xvYmFsT3BlcmF0b3I6IGJvb2xlYW4sIGF0dHJpYnV0ZXM6IE1heFBvb2xBdHRyaWJ1dGVzKTpcbiAgICAgICAgUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgICAgIGNvbnN0IFthZGp1c3RlZEF0dHJpYnV0ZXMsIG91dHB1dFNoYXBlXSA9XG4gICAgICAgICAgICAgIGdldEFkanVzdGVkUG9vbEF0dHJpYnV0ZXNBbmRPdXRwdXRTaGFwZShpbnB1dHMsIGF0dHJpYnV0ZXMsIGlzR2xvYmFsT3BlcmF0b3IpO1xuICAgICAgICAgIGNvbnN0IG9wMSA9IGBcbiAgICAgIHZhbHVlID0gbWF4KF9YKHgpLCB2YWx1ZSk7XG4gICAgYDtcbiAgICAgICAgICBjb25zdCBvcDIgPSAnJztcbiAgICAgICAgICBjb25zdCBwb29saW5nQ29kZSA9IGdlbmVyYXRlUG9vbGluZ0NvZGUoaW5wdXRzWzBdLmRpbXMsIGFkanVzdGVkQXR0cmlidXRlcywgb3AxLCBvcDIsICctMWU1Jyk7XG4gICAgICAgICAgY29uc3Qgc2hhZGVyU291cmNlID0gYFxuICAgICAgJHtwb29saW5nQ29kZX1cbiAgICBgO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgICAgIG91dHB1dDoge2RpbXM6IG91dHB1dFNoYXBlLCB0eXBlOiBpbnB1dHNbMF0udHlwZSwgdGV4dHVyZVR5cGU6IFRleHR1cmVUeXBlLnVucGFja2VkfSxcbiAgICAgICAgICAgIHNoYWRlclNvdXJjZVxuICAgICAgICAgIH07XG4gICAgICAgIH07XG5cbmNvbnN0IGdldEFkanVzdGVkUG9vbEF0dHJpYnV0ZXNBbmRPdXRwdXRTaGFwZSA9XG4gICAgKGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IEF2ZXJhZ2VQb29sQXR0cmlidXRlc3xNYXhQb29sQXR0cmlidXRlcywgaXNHbG9iYWxPcGVyYXRvcjogYm9vbGVhbik6XG4gICAgICAgIFtBdmVyYWdlUG9vbEF0dHJpYnV0ZXN8TWF4UG9vbEF0dHJpYnV0ZXMsIG51bWJlcltdXSA9PiB7XG4gICAgICAgICAgY29uc3QgaW5wdXRTaGFwZSA9IGlucHV0c1swXS5kaW1zLnNsaWNlKCk7XG4gICAgICAgICAgY29uc3QgaGFzRGlsYXRpb25zID0gT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwoYXR0cmlidXRlcywgJ2RpbGF0aW9ucycpO1xuICAgICAgICAgIGNvbnN0IGtlcm5lbFNoYXBlID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5zbGljZSgpO1xuICAgICAgICAgIGNvbnN0IHN0cmlkZXMgPSBhdHRyaWJ1dGVzLnN0cmlkZXMuc2xpY2UoKTtcbiAgICAgICAgICBjb25zdCBkaWxhdGlvbnM6IG51bWJlcltdID0gaGFzRGlsYXRpb25zID8gKGF0dHJpYnV0ZXMgYXMgTWF4UG9vbEF0dHJpYnV0ZXMpLmRpbGF0aW9ucy5zbGljZSgpIDogW107XG4gICAgICAgICAgY29uc3QgcGFkcyA9IGF0dHJpYnV0ZXMucGFkcy5zbGljZSgpO1xuICAgICAgICAgIFBvb2xDb252VXRpbC5hZGp1c3RQb29sQXR0cmlidXRlcyhpc0dsb2JhbE9wZXJhdG9yLCBpbnB1dFNoYXBlLCBrZXJuZWxTaGFwZSwgc3RyaWRlcywgZGlsYXRpb25zLCBwYWRzKTtcblxuICAgICAgICAgIGNvbnN0IG91dHB1dFNoYXBlID0gUG9vbENvbnZVdGlsLmNvbXB1dGVQb29sT3V0cHV0U2hhcGUoXG4gICAgICAgICAgICAgIGlzR2xvYmFsT3BlcmF0b3IsIGlucHV0U2hhcGUsIHN0cmlkZXMsIGRpbGF0aW9ucywga2VybmVsU2hhcGUsIHBhZHMsIGF0dHJpYnV0ZXMuYXV0b1BhZCk7XG5cbiAgICAgICAgICBjb25zdCBuZXdBdHRyaWJ1dGVzID0gT2JqZWN0LmFzc2lnbih7fSwgYXR0cmlidXRlcyk7XG4gICAgICAgICAgaWYgKGhhc0RpbGF0aW9ucykge1xuICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihuZXdBdHRyaWJ1dGVzLCB7a2VybmVsU2hhcGUsIHN0cmlkZXMsIHBhZHMsIGRpbGF0aW9ucywgY2FjaGVLZXk6IGF0dHJpYnV0ZXMuY2FjaGVLZXl9KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihuZXdBdHRyaWJ1dGVzLCB7a2VybmVsU2hhcGUsIHN0cmlkZXMsIHBhZHMsIGNhY2hlS2V5OiBhdHRyaWJ1dGVzLmNhY2hlS2V5fSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBbbmV3QXR0cmlidXRlcywgb3V0cHV0U2hhcGVdO1xuICAgICAgICB9O1xuXG5jb25zdCBnbG9iYWxNYXhQb29sQXR0cmlidXRlcyA9IHtcbiAgYXV0b1BhZDogJycsXG4gIGNlaWxNb2RlOiAwLFxuICBjb3VudEluY2x1ZGVQYWQ6IGZhbHNlLFxuICBrZXJuZWxTaGFwZTogW10sXG4gIHN0cmlkZXM6IFtdLFxuICBwYWRzOiBbXSxcbiAgc3RvcmFnZU9yZGVyOiAwLFxuICBkaWxhdGlvbnM6IFtdLFxuICBjYWNoZUtleTogJydcbn07XG5cbmNvbnN0IGdsb2JhbE1heFBvb2xNZXRhZGF0YSA9IHtcbiAgbmFtZTogJ0dsb2JhbE1heFBvb2wnLFxuICBpbnB1dE5hbWVzOiBbJ1gnXSxcbiAgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnVucGFja2VkXVxufTtcblxuZXhwb3J0IGNvbnN0IGdsb2JhbE1heFBvb2wgPSAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdKTogVGVuc29yW10gPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuICBjb25zdCBvdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgIHtcbiAgICAgICAgLi4uZ2xvYmFsTWF4UG9vbE1ldGFkYXRhLFxuICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZU1heFBvb2xQcm9ncmFtSW5mbyhpbnB1dHMsIGdsb2JhbE1heFBvb2xNZXRhZGF0YSwgdHJ1ZSwgZ2xvYmFsTWF4UG9vbEF0dHJpYnV0ZXMpXG4gICAgICB9LFxuICAgICAgaW5wdXRzKTtcbiAgcmV0dXJuIFtvdXRwdXRdO1xufTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiBUZW5zb3JbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQb29sIG9wcyByZXF1aXJlcyAxIGlucHV0LicpO1xuICB9XG4gIGlmIChpbnB1dHNbMF0udHlwZSAhPT0gJ2Zsb2F0MzInICYmIGlucHV0c1swXS50eXBlICE9PSAnZmxvYXQ2NCcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgaW5wdXQgdHlwZS4nKTtcbiAgfVxufTtcblxuY29uc3QgZ2VuZXJhdGVQb29saW5nQ29kZSA9XG4gICAgKGlucHV0RGltczogcmVhZG9ubHkgbnVtYmVyW10sIGF0dHJpYnV0ZXM6IEF2ZXJhZ2VQb29sQXR0cmlidXRlcywgb3AxOiBzdHJpbmcsIG9wMjogc3RyaW5nLCBzdGFydDogc3RyaW5nKTpcbiAgICAgICAgc3RyaW5nID0+IHtcbiAgICAgICAgICBjb25zdCByYW5rID0gaW5wdXREaW1zLmxlbmd0aDtcbiAgICAgICAgICBpZiAoYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggPD0gMikge1xuICAgICAgICAgICAgY29uc3Qga3cgPSBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlW2F0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICBjb25zdCBzdyA9IGF0dHJpYnV0ZXMuc3RyaWRlc1thdHRyaWJ1dGVzLnN0cmlkZXMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICBjb25zdCBwd1N0YXJ0ID0gYXR0cmlidXRlcy5wYWRzW2F0dHJpYnV0ZXMucGFkcy5sZW5ndGggLyAyIC0gMV07XG4gICAgICAgICAgICBjb25zdCBwd0VuZCA9IGF0dHJpYnV0ZXMucGFkc1thdHRyaWJ1dGVzLnBhZHMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICBjb25zdCBkaW1XID0gaW5wdXREaW1zW3JhbmsgLSAxXTtcbiAgICAgICAgICAgIGxldCBjb2RlVyA9ICcnO1xuICAgICAgICAgICAgbGV0IGNvZGVIID0gJyc7XG4gICAgICAgICAgICBsZXQgY29kZUhFbmQgPSAnJztcbiAgICAgICAgICAgIGlmIChwd1N0YXJ0ICsgcHdFbmQgIT09IDApIHtcbiAgICAgICAgICAgICAgY29kZVcgPSBgXG4gICAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCAke2t3fTsgaSsrKSB7XG4gICAgICAgICAgICB4WyR7cmFua30gLSAxXSA9IGluZGljZXNbJHtyYW5rfSAtIDFdICogJHtzd30gLSAke3B3U3RhcnR9ICsgaTtcbiAgICAgICAgICAgIGlmICh4WyR7cmFua30gLSAxXSA8IDAgfHwgeFske3Jhbmt9IC0gMV0gPj0gJHtkaW1XfSkge1xuICAgICAgICAgICAgICBwYWQrKztcbiAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAke29wMX1cbiAgICAgICAgICB9YDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGNvZGVXID0gYFxuICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgJHtrd307IGkrKykge1xuICAgICAgICAgICAgeFske3Jhbmt9IC0gMV0gPSBpbmRpY2VzWyR7cmFua30gLSAxXSAqICR7c3d9IC0gJHtwd1N0YXJ0fSArIGk7XG4gICAgICAgICAgICAke29wMX1cbiAgICAgICAgICB9YDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoID09PSAyKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGtoID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZVthdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCAtIDJdO1xuICAgICAgICAgICAgICBjb25zdCBzaCA9IGF0dHJpYnV0ZXMuc3RyaWRlc1thdHRyaWJ1dGVzLnN0cmlkZXMubGVuZ3RoIC0gMl07XG4gICAgICAgICAgICAgIGNvbnN0IHBoU3RhcnQgPSBhdHRyaWJ1dGVzLnBhZHNbYXR0cmlidXRlcy5wYWRzLmxlbmd0aCAvIDIgLSAyXTtcbiAgICAgICAgICAgICAgY29uc3QgcGhFbmQgPSBhdHRyaWJ1dGVzLnBhZHNbYXR0cmlidXRlcy5wYWRzLmxlbmd0aCAtIDJdO1xuICAgICAgICAgICAgICBjb25zdCBkaW1IID0gaW5wdXREaW1zW3JhbmsgLSAyXTtcbiAgICAgICAgICAgICAgaWYgKHBoU3RhcnQgKyBwaEVuZCAhPT0gMCkge1xuICAgICAgICAgICAgICAgIGNvZGVIID0gYFxuICAgICAgICAgICAgZm9yIChpbnQgaiA9IDA7IGogPCAke2tofTsgaisrKSB7XG4gICAgICAgICAgICAgIHhbJHtyYW5rfSAtIDJdID0gaW5kaWNlc1ske3Jhbmt9IC0gMl0gKiAke3NofSAtICR7cGhTdGFydH0gKyBqO1xuICAgICAgICAgICAgICBpZiAoeFske3Jhbmt9IC0gMl0gPCAwIHx8IHhbJHtyYW5rfSAtIDJdID49ICR7ZGltSH0pIHtcbiAgICAgICAgICAgICAgICBwYWQrPSAke2t3fTtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgIGA7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29kZUggPSBgXG4gICAgICAgICAgICBmb3IgKGludCBqID0gMDsgaiA8ICR7a2h9OyBqKyspIHtcbiAgICAgICAgICAgICAgeFske3Jhbmt9IC0gMl0gPSBpbmRpY2VzWyR7cmFua30gLSAyXSAqICR7c2h9IC0gJHtwaFN0YXJ0fSArIGo7XG4gICAgICAgICAgICBgO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGNvZGVIRW5kID0gYFxuICAgICAgICAgIH1cbiAgICAgICAgYDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgcG9vbGluZ0NvZGUgPSBgXG4gICAgICAgIGZsb2F0IHByb2Nlc3MoaW50IGluZGljZXNbJHtyYW5rfV0pIHtcbiAgICAgICAgICBpbnQgeFske3Jhbmt9XTtcbiAgICAgICAgICBjb3B5VmVjKGluZGljZXMsIHgpO1xuXG4gICAgICAgICAgZmxvYXQgdmFsdWUgPSAke3N0YXJ0fTtcbiAgICAgICAgICBpbnQgcGFkID0gMDtcbiAgICAgICAgICAke2NvZGVIfVxuICAgICAgICAgICR7Y29kZVd9XG4gICAgICAgICAgJHtjb2RlSEVuZH1cbiAgICAgICAgICAke29wMn1cbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIGA7XG4gICAgICAgICAgICByZXR1cm4gcG9vbGluZ0NvZGU7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGtlcm5lbFNpemUgPSBTaGFwZVV0aWwuc2l6ZShhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlKTtcbiAgICAgICAgICAgIGNvbnN0IGtlcm5lbFN0cmlkZXMgPSBTaGFwZVV0aWwuY29tcHV0ZVN0cmlkZXMoYXR0cmlidXRlcy5rZXJuZWxTaGFwZSk7XG4gICAgICAgICAgICBjb25zdCBzdHJpZGVzUmFuayA9IGtlcm5lbFN0cmlkZXMubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgcGFkc1JhbmsgPSBhdHRyaWJ1dGVzLnBhZHMubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0VG9JbmRpY2VzRnVuY3Rpb24gPSBvZmZzZXRUb0luZGljZXMoc3RyaWRlc1JhbmspO1xuICAgICAgICAgICAgY29uc3QgY29weUlucHV0RGltcyA9IGNvcHlBcnJheShpbnB1dERpbXMsICdpbnB1dERpbXMnKTtcbiAgICAgICAgICAgIGNvbnN0IGNvcHlQYWRzID0gY29weUFycmF5KGF0dHJpYnV0ZXMucGFkcywgJ3BhZHMnKTtcbiAgICAgICAgICAgIGNvbnN0IGNvcHlLZXJuZWxTdHJpZGVzID0gY29weUFycmF5KGtlcm5lbFN0cmlkZXMsICdrZXJuZWxTdHJpZGVzJyk7XG4gICAgICAgICAgICBjb25zdCBjb3B5U3RyaWRlcyA9IGNvcHlBcnJheShhdHRyaWJ1dGVzLnN0cmlkZXMsICdzdHJpZGVzJyk7XG4gICAgICAgICAgICBjb25zdCBoYXNQYWRzID0gYXR0cmlidXRlcy5wYWRzLnJlZHVjZSgoc3VtLCBjdXIpID0+IHN1bSArIGN1cik7XG4gICAgICAgICAgICBsZXQgcGFkQ29kZSA9ICcnO1xuICAgICAgICAgICAgaWYgKGhhc1BhZHMpIHtcbiAgICAgICAgICAgICAgcGFkQ29kZSA9IGBcbiAgICAgICAgICAgIGlmICh4W2pdID49IGlucHV0RGltc1tqXSB8fCB4W2pdIDwgMCkge1xuICAgICAgICAgICAgICBwYWQrKztcbiAgICAgICAgICAgICAgaXNQYWQgPSB0cnVlO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFpc1BhZCkge1xuICAgICAgICAgICAgJHtvcDF9XG4gICAgICAgICAgfWA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBwYWRDb2RlID0gYFxuICAgICAgICAgIH1cbiAgICAgICAgICAke29wMX1cbiAgICAgICAgYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHBvb2xpbmdDb2RlID0gYFxuICAgICAgICAke29mZnNldFRvSW5kaWNlc0Z1bmN0aW9ufVxuICAgICAgICBmbG9hdCBwcm9jZXNzKGludCBpbmRpY2VzWyR7cmFua31dKSB7XG4gICAgICAgICAgaW50IHhbJHtyYW5rfV07XG4gICAgICAgICAgY29weVZlYyhpbmRpY2VzLCB4KTtcbiAgICAgICAgICBpbnQgb2Zmc2V0WyR7c3RyaWRlc1Jhbmt9XTtcbiAgICAgICAgICBpbnQgcGFkc1ske3BhZHNSYW5rfV07XG4gICAgICAgICAgaW50IGlucHV0RGltc1ske3Jhbmt9XTtcbiAgICAgICAgICBpbnQga2VybmVsU3RyaWRlc1ske3N0cmlkZXNSYW5rfV07XG4gICAgICAgICAgaW50IHN0cmlkZXNbJHtzdHJpZGVzUmFua31dO1xuICAgICAgICAgICR7Y29weVBhZHN9XG4gICAgICAgICAgJHtjb3B5SW5wdXREaW1zfVxuICAgICAgICAgICR7Y29weVN0cmlkZXN9XG4gICAgICAgICAgJHtjb3B5S2VybmVsU3RyaWRlc31cblxuICAgICAgICAgIGZsb2F0IHZhbHVlID0gJHtzdGFydH07XG4gICAgICAgICAgaW50IHBhZCA9IDA7XG4gICAgICAgICAgYm9vbCBpc1BhZCA9IGZhbHNlO1xuICAgICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgJHtrZXJuZWxTaXplfTsgaSsrKSB7XG4gICAgICAgICAgICBvZmZzZXRUb0luZGljZXMoaSwga2VybmVsU3RyaWRlcywgb2Zmc2V0KTtcbiAgICAgICAgICAgIGlzUGFkID0gZmFsc2U7XG4gICAgICAgICAgICBmb3IgKGludCBqID0gJHtyYW5rfSAtICR7c3RyaWRlc1Jhbmt9OyBqIDwgJHtyYW5rfTsgaisrKSB7XG4gICAgICAgICAgICAgIHhbal0gPSBpbmRpY2VzW2pdICogc3RyaWRlc1tqIC0gJHtyYW5rfSArICR7c3RyaWRlc1Jhbmt9XVxuICAgICAgICAgICAgICAgICsgb2Zmc2V0W2ogLSAke3Jhbmt9ICsgJHtzdHJpZGVzUmFua31dIC0gcGFkc1tqIC0gMl07XG4gICAgICAgICAgICAgICR7cGFkQ29kZX1cbiAgICAgICAgICB9XG4gICAgICAgICAgJHtvcDJ9XG5cbiAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIGA7XG4gICAgICAgICAgICByZXR1cm4gcG9vbGluZ0NvZGU7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuXG5jb25zdCBjb3B5QXJyYXkgPSAoYXJyYXk6IHJlYWRvbmx5IG51bWJlcltdLCBhcnJheU5hbWU6IHN0cmluZyk6IHN0cmluZyA9PiB7XG4gIGxldCBibG9jayA9ICcnO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgYmxvY2sgKz0gYFxuICAgICAgJHthcnJheU5hbWV9WyR7aX1dID0gJHthcnJheVtpXX07XG4gICAgYDtcbiAgfVxuICByZXR1cm4gYmxvY2s7XG59O1xuXG5jb25zdCBvZmZzZXRUb0luZGljZXMgPSAocmFuazogbnVtYmVyKTogc3RyaW5nID0+IGBcbiAgdm9pZCBvZmZzZXRUb0luZGljZXMoaW50IG9mZnNldCwgaW50WyR7cmFua31dIHN0cmlkZXMsIG91dCBpbnRbJHtyYW5rfV0gaW5kaWNlcykge1xuICAgIGlmICgke3Jhbmt9ID09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yIChpbnQgaSA9IDA7IGkgPCAke3Jhbmt9IC0gMTsgKytpKSB7XG4gICAgICBpbmRpY2VzW2ldID0gb2Zmc2V0IC8gc3RyaWRlc1tpXTtcbiAgICAgIG9mZnNldCAtPSBpbmRpY2VzW2ldICogc3RyaWRlc1tpXTtcbiAgICB9XG4gICAgaW5kaWNlc1ske3Jhbmt9IC0gMV0gPSBvZmZzZXQ7XG4gIH1gO1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7QXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXl9IGZyb20gJy4uLy4uLy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQge0dyYXBofSBmcm9tICcuLi8uLi8uLi9ncmFwaCc7XG5pbXBvcnQge05VTUJFUl9UWVBFUywgT3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi4vLi4vLi4vb3BlcmF0b3JzJztcbmltcG9ydCB7VGVuc29yfSBmcm9tICcuLi8uLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtTaGFwZVV0aWx9IGZyb20gJy4uLy4uLy4uL3V0aWwnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1NZXRhZGF0YSwgVGV4dHVyZVR5cGV9IGZyb20gJy4uL3R5cGVzJztcblxuZXhwb3J0IGludGVyZmFjZSBSZWR1Y2VBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgYXhlczogbnVtYmVyW107XG4gIHJlYWRvbmx5IGtlZXBEaW1zOiBib29sZWFuO1xufVxuXG4vLyByZXR1cm4gW2luaXQgb3BzLCByZWR1Y2Ugb3BzLCBmaW5hbCBvcHNdXG50eXBlIFJlZHVjZU9wID0gKGlucHV0czogVGVuc29yW10sIGF4ZXM6IG51bWJlcltdKSA9PiBzdHJpbmdbXTtcblxuY29uc3QgcmVkdWNlID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzLCBuYW1lOiBzdHJpbmcsXG4gICAgIHJlZHVjZU9wOiBSZWR1Y2VPcCk6IFRlbnNvcltdID0+IHtcbiAgICAgIHZhbGlkYXRlSW5wdXRzKGlucHV0cyk7XG5cbiAgICAgIGNvbnN0IHJlZHVjZVByb2dyYW1NZXRhZGF0YSA9IHtcbiAgICAgICAgbmFtZSxcbiAgICAgICAgaW5wdXROYW1lczogWydBJ10sXG4gICAgICAgIGlucHV0VHlwZXM6IFtUZXh0dXJlVHlwZS51bnBhY2tlZF0sXG4gICAgICB9O1xuXG4gICAgICBjb25zdCBvdXRwdXQgPSBpbmZlcmVuY2VIYW5kbGVyLnJ1bihcbiAgICAgICAgICB7XG4gICAgICAgICAgICAuLi5yZWR1Y2VQcm9ncmFtTWV0YWRhdGEsXG4gICAgICAgICAgICBjYWNoZUhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXksXG4gICAgICAgICAgICBnZXQ6ICgpID0+XG4gICAgICAgICAgICAgICAgY3JlYXRlUmVkdWNlUHJvZ3JhbUluZm8oaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhdHRyaWJ1dGVzLCBuYW1lLCByZWR1Y2VPcCwgcmVkdWNlUHJvZ3JhbU1ldGFkYXRhKVxuICAgICAgICAgIH0sXG4gICAgICAgICAgaW5wdXRzKTtcbiAgICAgIHJldHVybiBbb3V0cHV0XTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcGFyc2VSZWR1Y2VBdHRyaWJ1dGVzOiBPcGVyYXRvckluaXRpYWxpemF0aW9uPFJlZHVjZUF0dHJpYnV0ZXM+ID0gKG5vZGU6IEdyYXBoLk5vZGUpOiBSZWR1Y2VBdHRyaWJ1dGVzID0+IHtcbiAgY29uc3QgYXhlcyA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnRzKCdheGVzJywgW10pO1xuICBjb25zdCBrZWVwRGltcyA9IG5vZGUuYXR0cmlidXRlcy5nZXRJbnQoJ2tlZXBkaW1zJywgMSkgPT09IDE7XG4gIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe2F4ZXMsIGtlZXBEaW1zfSk7XG59O1xuXG5jb25zdCBjcmVhdGVSZWR1Y2VQcm9ncmFtSW5mbyA9XG4gICAgKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcywgbmFtZTogc3RyaW5nLCByZWR1Y2VPcDogUmVkdWNlT3AsXG4gICAgIHJlZHVjZVByb2dyYW1NZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhKTogUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGU6IG51bWJlcltdID0gW107XG4gICAgICBjb25zdCBpUmFuayA9IGlucHV0c1swXS5kaW1zLmxlbmd0aCB8fCAxO1xuXG4gICAgICBjb25zdCBpZHhDb3B5ID0gW107ICAvLyBjb3B5IG91dHB1dCBpbmRleGVzIHRvIGlucHV0IGluZGV4ZXNcblxuICAgICAgY29uc3QgYXhlcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGVzKGF0dHJpYnV0ZXMuYXhlcywgaW5wdXRzWzBdLmRpbXMubGVuZ3RoKTtcbiAgICAgIGNvbnN0IG9wcyA9IHJlZHVjZU9wKGlucHV0cywgYXhlcyk7XG4gICAgICBsZXQgcmVkdWNlT3BzID0gb3BzWzFdO1xuXG4gICAgICBmb3IgKGxldCBrID0gMDsgayA8IGlucHV0c1swXS5kaW1zLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIC8vIGlmIHRoaXMgYXhpcyBpcyByZWR1Y2VkXG4gICAgICAgIGlmIChheGVzLmluZGV4T2YoaykgPj0gMCB8fCBheGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmIChhdHRyaWJ1dGVzLmtlZXBEaW1zKSB7XG4gICAgICAgICAgICBvdXRwdXRTaGFwZS5wdXNoKDEpO1xuICAgICAgICAgIH0gIC8vIGVsc2UgeyByZW1vdmUgdGhlIGF4aXMgZnJvbSBvdXRwdXRTaGFwZTsgfVxuXG4gICAgICAgICAgLy8gbG9vcCBvdmVyIHRoZSBkLXRoIGF4aXNcbiAgICAgICAgICByZWR1Y2VPcHMgPSBgXG4gICAgICAgICAgZm9yKGludCBqJHtrfSA9IDA7IGoke2t9IDwgJHtpbnB1dHNbMF0uZGltc1trXX07IGoke2t9KyspIHtcbiAgICAgICAgICAgIGlucHV0SWR4WyR7a31dID0gaiR7a307XG4gICAgICAgICAgICAke3JlZHVjZU9wc31cbiAgICAgICAgICB9YDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBpZHhDb3B5LnB1c2goYGlucHV0SWR4WyR7a31dID0gb3V0cHV0SWR4WyR7b3V0cHV0U2hhcGUubGVuZ3RofV07YCk7XG5cbiAgICAgICAgICBvdXRwdXRTaGFwZS5wdXNoKGlucHV0c1swXS5kaW1zW2tdKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBjb25zdCBvUmFuayA9IG91dHB1dFNoYXBlLmxlbmd0aCB8fCAxO1xuXG4gICAgICBjb25zdCBzaGFkZXJTb3VyY2UgPSBgXG4gICAgICBmbG9hdCBwcm9jZXNzKGludCBvdXRwdXRJZHhbJHtvUmFua31dKSB7XG4gICAgICAgIGZsb2F0IHZhbHVlOyAgICAgICAgICAgICAgICAgLy8gZmluYWwgcmVzdWx0XG4gICAgICAgIGludCBpbnB1dElkeFske2lSYW5rfV07ICAgICAgLy8gYWRkcmVzc2luZyBpbnB1dCBkYXRhXG4gICAgICAgICR7aWR4Q29weS5qb2luKCdcXG4nKX1cbiAgICAgICAgJHtvcHNbMF19ICAgICAgIC8vIGluaXQgb3BzIGZvciByZWR1Y2UgbWF4L21pblxuICAgICAgICAke3JlZHVjZU9wc31cbiAgICAgICAgJHtvcHNbMl19ICAgICAgIC8vIGZpbmFsIGNvbXB1dGF0aW9uIGZvciByZWR1Y2UgbWVhblxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9YDtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ucmVkdWNlUHJvZ3JhbU1ldGFkYXRhLFxuICAgICAgICBvdXRwdXQ6IHtkaW1zOiBvdXRwdXRTaGFwZSwgdHlwZTogaW5wdXRzWzBdLnR5cGUsIHRleHR1cmVUeXBlOiBUZXh0dXJlVHlwZS51bnBhY2tlZH0sXG4gICAgICAgIHNoYWRlclNvdXJjZVxuICAgICAgfTtcbiAgICB9O1xuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IFRlbnNvcltdKTogdm9pZCA9PiB7XG4gIC8vIFRPRE86IHN1cHBvcnQgUmVkdWNlKiBvcGVyYXRvcnMgd2l0aCAyIGlucHV0cy5cbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignUmVkdWNlIG9wIHJlcXVpcmVzIDEgaW5wdXQuJyk7XG4gIH1cblxuICBpZiAoTlVNQkVSX1RZUEVTLmluZGV4T2YoaW5wdXRzWzBdLnR5cGUpID09PSAtMSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCB0eXBlLicpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlU3VtOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPFJlZHVjZUF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgY29uc3QgcmVkdWNlT3A6IFJlZHVjZU9wID0gKCk6IHN0cmluZ1tdID0+IFsndmFsdWUgPSAwLjA7JywgJ3ZhbHVlICs9IF9BKGlucHV0SWR4KTsnLCAnJ107XG4gICAgICByZXR1cm4gcmVkdWNlKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYXR0cmlidXRlcywgJ1JlZHVjZVN1bScsIHJlZHVjZU9wKTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTWVhbjogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxSZWR1Y2VBdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIGNvbnN0IHJlZHVjZU9wOiBSZWR1Y2VPcCA9IChpbnB1dHM6IFRlbnNvcltdLCBheGVzOiBudW1iZXJbXSk6IHN0cmluZ1tdID0+IHtcbiAgICAgICAgbGV0IHNpemUgPSAxLjA7XG4gICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgaW5wdXRzWzBdLmRpbXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICBpZiAoYXhlcy5pbmRleE9mKGspID49IDAgfHwgYXhlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHNpemUgKj0gaW5wdXRzWzBdLmRpbXNba107XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFsndmFsdWUgPSAwLjA7JywgJ3ZhbHVlICs9IF9BKGlucHV0SWR4KTsnLCBgdmFsdWUgLz0gJHtzaXplfS47YF07ICAvLyBlbnN1cmUgcmVhbCBudW1iZXIgd2l0aCBgLmBcbiAgICAgIH07XG4gICAgICByZXR1cm4gcmVkdWNlKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYXR0cmlidXRlcywgJ1JlZHVjZU1lYW4nLCByZWR1Y2VPcCk7XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHJlZHVjZU1heDogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxSZWR1Y2VBdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIGNvbnN0IHJlZHVjZU9wOiBSZWR1Y2VPcCA9IChpbnB1dHM6IFRlbnNvcltdLCBheGVzOiBudW1iZXJbXSk6IHN0cmluZ1tdID0+IHtcbiAgICAgICAgY29uc3QgaWR4WmVybyA9IFtdO1xuICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IGlucHV0c1swXS5kaW1zLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgaWYgKGF4ZXMuaW5kZXhPZihrKSA+PSAwIHx8IGF4ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBpZHhaZXJvLnB1c2goYGlucHV0SWR4WyR7a31dID0gMDtgKTsgIC8vIGZpcnN0IGVsZW1lbnRcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW2Ake2lkeFplcm8uam9pbignXFxuJyl9XFxudmFsdWUgPSBfQShpbnB1dElkeCk7YCwgJ3ZhbHVlID0gbWF4KHZhbHVlLCBfQShpbnB1dElkeCkpOycsICcnXTtcbiAgICAgIH07XG4gICAgICByZXR1cm4gcmVkdWNlKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYXR0cmlidXRlcywgJ1JlZHVjZU1heCcsIHJlZHVjZU9wKTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcmVkdWNlTWluOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPFJlZHVjZUF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgY29uc3QgcmVkdWNlT3A6IFJlZHVjZU9wID0gKGlucHV0czogVGVuc29yW10sIGF4ZXM6IG51bWJlcltdKTogc3RyaW5nW10gPT4ge1xuICAgICAgICBjb25zdCBpZHhaZXJvID0gW107XG4gICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgaW5wdXRzWzBdLmRpbXMubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICBpZiAoYXhlcy5pbmRleE9mKGspID49IDAgfHwgYXhlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGlkeFplcm8ucHVzaChgaW5wdXRJZHhbJHtrfV0gPSAwO2ApOyAgLy8gZmlyc3QgZWxlbWVudFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBbYCR7aWR4WmVyby5qb2luKCdcXG4nKX1cXG52YWx1ZSA9IF9BKGlucHV0SWR4KTtgLCAndmFsdWUgPSBtaW4odmFsdWUsIF9BKGlucHV0SWR4KSk7JywgJyddO1xuICAgICAgfTtcbiAgICAgIHJldHVybiByZWR1Y2UoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhdHRyaWJ1dGVzLCAnUmVkdWNlTWluJywgcmVkdWNlT3ApO1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VQcm9kOiBPcGVyYXRvckltcGxlbWVudGF0aW9uPFJlZHVjZUF0dHJpYnV0ZXM+ID1cbiAgICAoaW5mZXJlbmNlSGFuZGxlcjogV2ViR0xJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBhdHRyaWJ1dGVzOiBSZWR1Y2VBdHRyaWJ1dGVzKTogVGVuc29yW10gPT4ge1xuICAgICAgY29uc3QgcmVkdWNlT3A6IFJlZHVjZU9wID0gKCk6IHN0cmluZ1tdID0+IFsndmFsdWUgPSAxLjA7JywgJ3ZhbHVlICo9IF9BKGlucHV0SWR4KTsnLCAnJ107XG4gICAgICByZXR1cm4gcmVkdWNlKGluZmVyZW5jZUhhbmRsZXIsIGlucHV0cywgYXR0cmlidXRlcywgJ1JlZHVjZVByb2QnLCByZWR1Y2VPcCk7XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHJlZHVjZUxvZ1N1bTogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxSZWR1Y2VBdHRyaWJ1dGVzPiA9XG4gICAgKGluZmVyZW5jZUhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzOiBUZW5zb3JbXSwgYXR0cmlidXRlczogUmVkdWNlQXR0cmlidXRlcyk6IFRlbnNvcltdID0+IHtcbiAgICAgIGNvbnN0IHJlZHVjZU9wOiBSZWR1Y2VPcCA9ICgpOiBzdHJpbmdbXSA9PiBbJ3ZhbHVlID0gMC4wOycsICd2YWx1ZSArPSBfQShpbnB1dElkeCk7JywgJ3ZhbHVlID0gbG9nKHZhbHVlKTsnXTtcbiAgICAgIHJldHVybiByZWR1Y2UoaW5mZXJlbmNlSGFuZGxlciwgaW5wdXRzLCBhdHRyaWJ1dGVzLCAnUmVkdWNlTG9nU3VtJywgcmVkdWNlT3ApO1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCByZWR1Y2VMb2dTdW1TcXVhcmU6IE9wZXJhdG9ySW1wbGVtZW50YXRpb248UmVkdWNlQXR0cmlidXRlcz4gPVxuICAgIChpbmZlcmVuY2VIYW5kbGVyOiBXZWJHTEluZmVyZW5jZUhhbmRsZXIsIGlucHV0czogVGVuc29yW10sIGF0dHJpYnV0ZXM6IFJlZHVjZUF0dHJpYnV0ZXMpOiBUZW5zb3JbXSA9PiB7XG4gICAgICBjb25zdCByZWR1Y2VPcDogUmVkdWNlT3AgPSAoKTogc3RyaW5nW10gPT4gWydmbG9hdCB0OyB2YWx1ZSA9IDAuMDsnLCAndCA9IF9BKGlucHV0SWR4KTsgdmFsdWUgKz0gdCAqIHQ7JywgJyddO1xuICAgICAgcmV0dXJuIHJlZHVjZShpbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHMsIGF0dHJpYnV0ZXMsICdSZWR1Y2VMb2dTdW1TcXVhcmUnLCByZWR1Y2VPcCk7XG4gICAgfTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi4vLi4vLi4vdGVuc29yJztcbmltcG9ydCB7U2hhcGVVdGlsfSBmcm9tICcuLi8uLi8uLi91dGlsJztcbmltcG9ydCB7Z2V0R2xzbH0gZnJvbSAnLi4vZ2xzbC1zb3VyY2UnO1xuaW1wb3J0IHtXZWJHTEluZmVyZW5jZUhhbmRsZXJ9IGZyb20gJy4uL2luZmVyZW5jZS1oYW5kbGVyJztcbmltcG9ydCB7UHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGEsIFRleHR1cmVUeXBlfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7dW5wYWNrRnJvbUNoYW5uZWx9IGZyb20gJy4vcGFja2luZy11dGlscyc7XG5cbmNvbnN0IGNyZWF0ZVBhY2tlZFJlc2hhcGUzRFByb2dyYW1NZXRhZGF0YSA9IChvdXRwdXRTaGFwZTNEOiByZWFkb25seSBudW1iZXJbXSkgPT5cbiAgICAoe25hbWU6ICdSZXNoYXBlIChwYWNrZWQpJywgaW5wdXRUeXBlczogW1RleHR1cmVUeXBlLnBhY2tlZF0sIGlucHV0TmFtZXM6IFsnQSddLCBjYWNoZUhpbnQ6IGAke291dHB1dFNoYXBlM0R9YH0pO1xuXG5jb25zdCBjcmVhdGVQYWNrZWRSZXNoYXBlM0RQcm9ncmFtSW5mbyA9XG4gICAgKGhhbmRsZXI6IFdlYkdMSW5mZXJlbmNlSGFuZGxlciwgaW5wdXQzRDogVGVuc29yLCBtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhLCBvdXRwdXRTaGFwZTNEOiByZWFkb25seSBudW1iZXJbXSk6XG4gICAgICAgIFByb2dyYW1JbmZvID0+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+KCk7XG4gICAgdGhpcy5fYWxsSW5wdXRJbmRpY2VzLmZvckVhY2goaSA9PiB7XG4gICAgICBjb25zdCBkYXRhID0gdGhpcy5fYWxsRGF0YVtpXTtcbiAgICAgIGRhdGEuX3RvLmZvckVhY2goaiA9PiB7XG4gICAgICAgIHN0YXJ0ZXJzLmFkZChqKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gSXRlcmF0aXZlIERGUyB0byBjaGVjayBmb3IgY3ljbGVzXG4gICAgY29uc3Qgbm9kZXNTdGFjayA9IEFycmF5LmZyb20oc3RhcnRlcnMpO1xuICAgIGNvbnN0IG5vZGVzU3RhdGUgPSBuZXcgQXJyYXk8c3RyaW5nPih0aGlzLl9ub2Rlcy5sZW5ndGgpLmZpbGwoJ3doaXRlJyk7XG5cbiAgICB3aGlsZSAobm9kZXNTdGFjay5sZW5ndGggPiAwKSB7XG4gICAgICBjb25zdCBub2RlSW5kZXggPSBub2Rlc1N0YWNrLnBvcCgpITtcbiAgICAgIC8vIHRoaXMgbm9kZSBoYXMgbm93IGJlZW4gcHJvY2Vzc2VkIGNvbXBsZXRlbHkuIE1hcmsgdGhpcyBub2RlICdibGFjaycgdG8gZGVub3RlIHRoaXMuXG4gICAgICBpZiAobm9kZXNTdGF0ZVtub2RlSW5kZXhdID09PSAnZ3JheScpIHtcbiAgICAgICAgbm9kZXNTdGF0ZVtub2RlSW5kZXhdID0gJ2JsYWNrJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHRoaXMgbm9kZSBpcyB1bmRlciBwcm9jZXNzaW5nIHN0YWdlLiBtYXJrIHRoaXMgbm9kZSAnZ3JheScgdG8gZGVub3RlIHRoaXMuXG4gICAgICAgIG5vZGVzU3RhY2sucHVzaChub2RlSW5kZXgpO1xuICAgICAgICBub2Rlc1N0YXRlW25vZGVJbmRleF0gPSAnZ3JheSc7XG5cbiAgICAgICAgdGhpcy5fbm9kZXNbbm9kZUluZGV4XS5vdXRwdXRzLmZvckVhY2goKG91dGdvaW5nRWRnZUluZGV4KSA9PiB7XG4gICAgICAgICAgY29uc3QgZGF0YSA9IHRoaXMuX2FsbERhdGFbb3V0Z29pbmdFZGdlSW5kZXhdO1xuICAgICAgICAgIGlmICh0eXBlb2YgZGF0YS50ZW5zb3IgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vZGUgb3V0cHV0cyBzaG91bGQgbm90IGJlIGluaXRpYWxpemVkJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChkYXRhLl9mcm9tICE9PSBub2RlSW5kZXgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignZnJvbSBwcm9wZXJ0eSBvZiB0aGUgVmFsdWUgb2JqZWN0IGRvZXNuXFwndCBtYXRjaCBpbmRleCBvZiBOb2RlIGJlaW5nIHByb2Nlc3NlZCcpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBkYXRhLl90by5mb3JFYWNoKChkb3duc3RyZWFtTm9kZUluZGV4KSA9PiB7XG4gICAgICAgICAgICAvLyBiYWNrIGVkZ2UgZm91bmQgLSBjeWNsaWNcbiAgICAgICAgICAgIGlmIChub2Rlc1N0YXRlW2Rvd25zdHJlYW1Ob2RlSW5kZXhdID09PSAnZ3JheScpIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtb2RlbCBncmFwaCBpcyBjeWNsaWMnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHRyZWUgZWRnZSBmb3VuZCAtIGNvbnRpbnVlIHByb2Nlc3NpbmcgYnkgYWRkaW5nIGl0IHRvIHN0YWNrXG4gICAgICAgICAgICBlbHNlIGlmIChub2Rlc1N0YXRlW2Rvd25zdHJlYW1Ob2RlSW5kZXhdID09PSAnd2hpdGUnKSB7XG4gICAgICAgICAgICAgIG5vZGVzU3RhY2sucHVzaChkb3duc3RyZWFtTm9kZUluZGV4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB0cmFuc2Zvcm1HcmFwaChncmFwaEluaXRpYWxpemVyPzogR3JhcGguSW5pdGlhbGl6ZXIpOiB2b2lkIHtcbiAgICAvLyBhcHBseSBjb21tb24gdHJhbnNmb3JtXG4gICAgdGhpcy5yZW1vdmVBbGxJZGVudGl0eU5vZGVzKCk7XG4gICAgdGhpcy5yZW1vdmVBbGxEcm9wb3V0Tm9kZXMoKTtcbiAgICB0aGlzLmZ1c2VDb252QWN0aXZhdGlvbk5vZGVzKCk7XG4gICAgLy8gYXBwbHkgaW5pdGlhbGl6ZXIgc3BlY2lmaWMgdHJhbnNmb3JtXG4gICAgaWYgKGdyYXBoSW5pdGlhbGl6ZXIpIHtcbiAgICAgIGdyYXBoSW5pdGlhbGl6ZXIudHJhbnNmb3JtR3JhcGgodGhpcyk7XG4gICAgfVxuXG4gICAgLy8gZmluYWxpemUgZ3JhcGhcbiAgICB0aGlzLmZpbmFsaXplR3JhcGgoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBmaW5hbGl6ZSB0aGUgZ3JhcGguXG4gICAqXG4gICAqIHRoaXMgZnVuY3Rpb24gc2hvdWxkIGJlIGNhbGxlZCBhZnRlciBhbGwgdGhlIHRyYW5zZm9ybWF0aW9uIGNvbXBsZXRlZC5cbiAgICogdGhpcyBmdW5jdGlvbiByZW1vdmVzIGFsbCB1bm5lY2Vzc2FyeSBub2RlcyBhbmQgdmFsdWVzIGZyb20gdGhlIGdyYXBoXG4gICAqL1xuICBmaW5hbGl6ZUdyYXBoKCkge1xuICAgIGxldCBvZmZzZXQgPSAwO1xuICAgIC8vIGRlbGV0ZSBhbGwgbm9kZXMgdGhhdCBhcmUgbm90IGJlaW5nIGV4ZWN1dGVkXG4gICAgLy8gVGhlIGdyYXBoIGlzIHJlcHJlc2VudGVkIHVzaW5nIHRoZXNlIHR3byBhcnJheXNcbiAgICAvLyB0aGlzLl9ub2RlcyAtIEFycmF5IGhvbGRpbmcgdGhlIGtlcm5lbHMgdG8gZXhlY3V0ZSAtIGVhY2ggZW50cnkgaXMgYSBrZXJuZWwgcG9pbnRpbmcgdG8gdGhpcy5fYWxsRGF0YVxuICAgIC8vIHRoaXMuX2FsbERhdGEgLSBob2xkIDIgZmllbGRzIC0gdG8gW10gJiBmcm9tIC0gdGhlc2UgZmVpbGVkcyBob2xkIHRoZSBncmFwaCBtYXAgZm9yIGlucHV0cyBhbmQgb3V0cHV0cyBwZXIgbm9kZVxuICAgIC8vIG5ld0luZGljZXMgLSByZW1hcHBpbmcgdGhlIGdyYXBoIGFmdGVyIHJlYWRpbmcgdGhlIGZsYWcgJ2V4ZWN1dGVOb2RlJ1xuICAgIGNvbnN0IG5ld0luZGljZXMgPSBuZXcgQXJyYXk8bnVtYmVyPih0aGlzLl9ub2Rlcy5sZW5ndGgsIDApO1xuICAgIGxldCBub2RlUG9zc2l0aW9uID0gMDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIC8vIGdpdmluZyBuZXcgaW5kZXhlcyB0byB0aGUgbm9kZXMgYmFzZWQgb24gZXhlY3V0aW9uIGZsYWdcbiAgICAgIG5ld0luZGljZXNbaV0gPSBub2RlUG9zc2l0aW9uO1xuICAgICAgaWYgKHRoaXMuX25vZGVzW2ldLmV4ZWN1dGVOb2RlKSB7XG4gICAgICAgIGlmIChub2RlUG9zc2l0aW9uICE9PSBpKSB7XG4gICAgICAgICAgdGhpcy5fbm9kZXNbbm9kZVBvc3NpdGlvbl0gPSB0aGlzLl9ub2Rlc1tpXTtcbiAgICAgICAgfVxuICAgICAgICBub2RlUG9zc2l0aW9uKys7XG5cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGRlbGV0ZSBhbGwgb3V0cHV0IHZhbHVlc1xuICAgICAgICB0aGlzLl9ub2Rlc1tpXS5vdXRwdXRzLmZvckVhY2goaW5kID0+IHtcbiAgICAgICAgICB0aGlzLl9hbGxEYXRhW2luZF0uX2Zyb20gPSAtMjtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gcmVtb3ZpbmcgdGhlIHVudXNlZCBub2Rlc1xuICAgIHRoaXMuX25vZGVzLnNwbGljZShub2RlUG9zc2l0aW9uLCB0aGlzLl9ub2Rlcy5sZW5ndGggLSBub2RlUG9zc2l0aW9uKTtcblxuICAgIC8vIFVwZGF0aW5nIHRoaXMuX2FsbERhdGEgYWNjb3JkaW5nIHRvIHRoZSBuZXcgdGhpcy5fbm9kZXNcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX2FsbERhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGN1cnJlbnREYXRhID0gdGhpcy5fYWxsRGF0YVtpXTtcbiAgICAgIGlmIChjdXJyZW50RGF0YS5fZnJvbSAhPT0gdW5kZWZpbmVkICYmIGN1cnJlbnREYXRhLl9mcm9tICE9PSAtMSAmJiBjdXJyZW50RGF0YS5fZnJvbSAhPT0gLTIpIHtcbiAgICAgICAgY3VycmVudERhdGEuX2Zyb20gPSBuZXdJbmRpY2VzW2N1cnJlbnREYXRhLl9mcm9tXTtcbiAgICAgIH1cblxuICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBjdXJyZW50RGF0YS5fdG8ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgaWYgKGN1cnJlbnREYXRhLl90b1tqXSA+PSAwKSB7XG4gICAgICAgICAgY3VycmVudERhdGEuX3RvW2pdID0gbmV3SW5kaWNlc1tjdXJyZW50RGF0YS5fdG9bal1dO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVHJ5aW5nIHRvIHVwZGF0ZSBhIHJlbW92ZWQgbm9kZScpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgb2Zmc2V0ID0gMDtcbiAgICAvLyBkZWxldGUgYWxsIHZhbHVlcyB0aGF0IGFyZSBub3QgYmVpbmcgcmVmZXJlbmNlZFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fYWxsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgLy8gaWYgY3VycmVudCB2YWx1ZSBpcyBuZWl0aGVyIGxpbmtlZCB0byBuZXh0IG5vZGUsIG5vciBhbiBvdXRwdXQgdmFsdWUsIHJlbW92ZSBpdC5cbiAgICAgIGlmICh0aGlzLl9hbGxEYXRhW2ldLmZyb20gPT09IC0yICYmIHRoaXMuX2FsbE91dHB1dEluZGljZXMuaW5kZXhPZihpICsgb2Zmc2V0KSA9PT0gLTEpIHtcbiAgICAgICAgb2Zmc2V0Kys7XG4gICAgICAgIHRoaXMuX2FsbERhdGEuc3BsaWNlKGksIDEpO1xuICAgICAgICBpLS07XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgaWYgKG9mZnNldCA+IDApIHtcbiAgICAgICAgbGV0IGluZCA9IC0xO1xuICAgICAgICAvLyBpZiBjdXJyZW50IHZhbHVlIGlzIG5laXRoZXIgYW4gaW5wdXQgdmFsdWUgbm9yIGFuIGluaXRpYWxpemVyLCBmaW5kIHRoZSBub2RlIGl0J3NcbiAgICAgICAgLy8gY29taW5nIGZyb20gYW5kIHVwZGF0ZSB0aGUgY29ycmVzcG9uZGluZyBub2RlIG91dHB1dFxuICAgICAgICBpZiAodGhpcy5fYWxsRGF0YVtpXS5mcm9tICE9PSB1bmRlZmluZWQgJiYgdGhpcy5fYWxsRGF0YVtpXS5mcm9tICE9PSAtMSkge1xuICAgICAgICAgIGluZCA9IHRoaXMuX25vZGVzW3RoaXMuX2FsbERhdGFbaV0uZnJvbV0ub3V0cHV0cy5pbmRleE9mKGkgKyBvZmZzZXQpO1xuICAgICAgICAgIGlmIChpbmQgIT09IC0xKSB7XG4gICAgICAgICAgICB0aGlzLl9ub2Rlc1t0aGlzLl9hbGxEYXRhW2ldLmZyb21dLm91dHB1dHNbaW5kXSA9IGk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGlmIGN1cnJlbnQgdmFsdWUgaXMgYW4gaW5wdXQgdmFsdWUsIHVwZGF0ZSBpdHMgcmVmZXJlbmNlIGluIGlucHV0SW5kaWNlc1xuICAgICAgICAgIGluZCA9IHRoaXMuX2FsbElucHV0SW5kaWNlcy5pbmRleE9mKGkgKyBvZmZzZXQpO1xuICAgICAgICAgIGlmIChpbmQgIT09IC0xKSB7XG4gICAgICAgICAgICB0aGlzLl9hbGxJbnB1dEluZGljZXNbaW5kXSA9IGk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gZmluZCB0aGUgbm9kZSB0aGF0IHRoZSBjdXJyZW50IHZhbHVlIGlzIGxpbmtpbmcgdG8gYW5kIHVwZGF0ZSBpdHMgaW5wdXQgcmVmZXJlbmNlXG4gICAgICAgIHRoaXMuX2FsbERhdGFbaV0udG8uZm9yRWFjaChub2RlID0+IHtcbiAgICAgICAgICBpbmQgPSB0aGlzLl9ub2Rlc1tub2RlXS5pbnB1dHMuaW5kZXhPZihpICsgb2Zmc2V0KTtcbiAgICAgICAgICBpZiAoaW5kICE9PSAtMSkge1xuICAgICAgICAgICAgdGhpcy5fbm9kZXNbbm9kZV0uaW5wdXRzW2luZF0gPSBpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIGlmICh0aGlzLl9hbGxEYXRhW2ldLnRvLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIC8vIGlmIGN1cnJlbnQgdmFsdWUgaXMgYSBncmFwaCBvdXRwdXQsIHVwZGF0ZSBpdHMgcmVmZXJlbmNlIGluIG91dHB1dEluZGljZXNcbiAgICAgICAgICBpbmQgPSB0aGlzLl9hbGxPdXRwdXRJbmRpY2VzLmluZGV4T2YoaSArIG9mZnNldCk7XG4gICAgICAgICAgaWYgKGluZCAhPT0gLTEpIHtcbiAgICAgICAgICAgIHRoaXMuX2FsbE91dHB1dEluZGljZXNbaW5kXSA9IGk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZSB0aGUgc3BlY2lmZWQgbm9kZS4gQXNzdW1lIHRoZSBub2RlIGhhcyBvbmUgaW5jb21pbmcgaW5wdXQgYW5kIHRoZSBmaXJzdCBvdXRwdXQgY29ubmVjdGVkIHRvIG90aGVyIG5vZGVzLlxuICAgKiBBbiBpbnB1dCB2YWxpZGF0aW9uIG11c3QgYmUgZG9uZSBiZWZvcmUgY2FsbGluZyB0aGlzIGZ1bmN0aW9uLlxuICAgKiBAcGFyYW0gbm9kZUluZGV4IFRoZSBpbmRleCBvZiBub2RlIHRvIGJlIGRlbGV0ZWRcbiAgICovXG4gIHByaXZhdGUgZGVsZXRlTm9kZShub2RlSW5kZXg6IG51bWJlcikge1xuICAgIGNvbnN0IG5vZGUgPSB0aGlzLl9ub2Rlc1tub2RlSW5kZXhdO1xuICAgIGlmIChub2RlLm91dHB1dHMubGVuZ3RoID4gMSkge1xuICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBub2RlLm91dHB1dHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKHRoaXMuX2FsbERhdGFbbm9kZS5vdXRwdXRzW2ldXS50by5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdOb2RlIGRlbGV0aW9uIHdpdGggbW9yZSB0aGFuIG9uZSBvdXRwdXQgY29ubmVjdGVkIHRvIG90aGVyIG5vZGVzIGlzIG5vdCBzdXBwb3J0ZWQuICcpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gdGhpcyBub2RlIHdpbCBub3QgYmUgZXhlY3V0ZWRcbiAgICBub2RlLmV4ZWN1dGVOb2RlID0gZmFsc2U7XG4gICAgY29uc3QgaW5wdXRWYWx1ZUluZGV4ID0gbm9kZS5pbnB1dHNbMF07XG4gICAgY29uc3Qgb3V0cHV0VmFsdWVJbmRleCA9IG5vZGUub3V0cHV0c1swXTtcbiAgICBjb25zdCBub2Rlc0NvbnN1bWluZ091dHB1dCA9IHRoaXMuX2FsbERhdGFbb3V0cHV0VmFsdWVJbmRleF0udG87XG5cbiAgICAvLyByZW1vdmUgdGhpcyBub2RlIGZyb20gdGhlIHRvIHByb3BlcnR5IG9mIHRoZSBpbnB1dCBWYWx1ZVxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbm9kZS5pbnB1dHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGRlbEluZGV4ID0gdGhpcy5fYWxsRGF0YVtub2RlLmlucHV0c1tpXV0udG8uaW5kZXhPZihub2RlSW5kZXgpO1xuICAgICAgLy8gc2hvdWxkIG5vdCBoYXBwZW5cbiAgICAgIGlmIChkZWxJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgVmFsdWUgb2JqZWN0IGRvZXNuXFwndCBoYXZlIHRoZSBjdXJyZW50IE5vZGUgaW4gaXRcXCdzIFxcJ3RvXFwnIHByb3BlcnR5ICcpO1xuICAgICAgfVxuICAgICAgdGhpcy5fYWxsRGF0YVtub2RlLmlucHV0c1tpXV0udG8uc3BsaWNlKGRlbEluZGV4LCAxKTtcbiAgICB9XG5cbiAgICAvLyBjbGVhciBub2RlIGluZGljZXMgY29uc3VtaW5nIHRoaXMgb3V0cHV0IFZhbHVlXG4gICAgdGhpcy5fYWxsRGF0YVtvdXRwdXRWYWx1ZUluZGV4XS5fdG8gPSBbXTtcblxuICAgIC8vIGlmIHRoZSBvdXRwdXQgb2YgdGhpcyBub2RlIGlzIGEgZ3JhcGggb3V0cHV0LCBhZGp1c3QgdGhlIGluZGV4IGFwcHJvcHJpYXRlbHlcbiAgICBjb25zdCBpbmRleCA9IHRoaXMuX2FsbE91dHB1dEluZGljZXMuaW5kZXhPZihvdXRwdXRWYWx1ZUluZGV4KTtcbiAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICB0aGlzLl9hbGxPdXRwdXRJbmRpY2VzW2luZGV4XSA9IGlucHV0VmFsdWVJbmRleDtcbiAgICB9XG5cbiAgICAvLyBvdmVycmlkZSB0aGUgaW5wdXRzIGZvciBub2RlcyBjb25zdW1pbmcgdGhpcyBub2RlJ3Mgb3V0cHV0IHdpdGggdGhlIGlucHV0IHRvIHRoaXMgbm9kZVxuICAgIGlmIChub2Rlc0NvbnN1bWluZ091dHB1dCAmJiBub2Rlc0NvbnN1bWluZ091dHB1dC5sZW5ndGggPiAwKSB7XG4gICAgICBmb3IgKGNvbnN0IG5vZGVJbmRleCBvZiBub2Rlc0NvbnN1bWluZ091dHB1dCkge1xuICAgICAgICBjb25zdCByZXBsYWNlSW5kZXggPSB0aGlzLl9ub2Rlc1tub2RlSW5kZXhdLmlucHV0cy5pbmRleE9mKG91dHB1dFZhbHVlSW5kZXgpO1xuICAgICAgICAvLyBzaG91bGQgbm90IGhhcHBlblxuICAgICAgICBpZiAocmVwbGFjZUluZGV4ID09PSAtMSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIE5vZGUgb2JqZWN0IGRvZXNuXFwndCBoYXZlIHRoZSBvdXRwdXQgVmFsdWUgaW4gaXRcXCdzIFxcJ2lucHV0c1xcJyBwcm9wZXJ0eSAnKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9ub2Rlc1tub2RlSW5kZXhdLmlucHV0c1tyZXBsYWNlSW5kZXhdID0gaW5wdXRWYWx1ZUluZGV4O1xuICAgICAgICB0aGlzLl9hbGxEYXRhW2lucHV0VmFsdWVJbmRleF0udG8ucHVzaChub2RlSW5kZXgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJlbW92ZUFsbERyb3BvdXROb2RlcygpIHtcbiAgICBsZXQgbm9kZUluZGV4ID0gMDtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2YgdGhpcy5fbm9kZXMpIHtcbiAgICAgIC8vIHdlZWQgb3V0ICdEcm9wb3V0JyBub2RlcyBzbyB0aGF0IG5vIHRpbWUgaXMgd2FzdGVkIGluIGV4ZWN1dGlvblxuICAgICAgaWYgKG5vZGUub3BUeXBlID09PSAnRHJvcG91dCcpIHtcbiAgICAgICAgLy8gdGhlIG5vZGUgc2hvdWxkIGhhdmUgZXhhY3RseSAxIGlucHV0IGFuZCAxIG9yIDIgb3V0cHV0c1xuICAgICAgICBpZiAobm9kZS5pbnB1dHMubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEcm9wb3V0IG5vZGVzIHNob3VsZCBvbmx5IGNvbnRhaW4gb25lIGlucHV0LiAnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobm9kZS5vdXRwdXRzLmxlbmd0aCAhPT0gMSAmJiBub2RlLm91dHB1dHMubGVuZ3RoICE9PSAyKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEcm9wb3V0IG5vZGVzIHNob3VsZCBjb250YWluIGVpdGhlciAxIG9yIDIgb3V0cHV0KHMpJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gdGhlIHNlY29uZCBvdXRwdXQgc2hvdWxkIG5vdCBiZSByZWZlcmVuY2VkIGJ5IGFueSBvdGhlciBub2RlXG4gICAgICAgIGlmIChub2RlLm91dHB1dHMubGVuZ3RoID09PSAyICYmIHRoaXMuX2FsbERhdGFbbm9kZS5vdXRwdXRzWzFdXS5fdG8ubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEcm9wb3V0IG5vZGVzXFwncyBzZWNvbmQgb3V0cHV0IHNob3VsZCBub3QgYmUgcmVmZXJlbmNlZCBieSBvdGhlciBub2RlcycpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZGVsZXRlTm9kZShub2RlSW5kZXgpO1xuICAgICAgfVxuICAgICAgbm9kZUluZGV4Kys7XG4gICAgfVxuICB9XG5cbiAgcmVtb3ZlQWxsSWRlbnRpdHlOb2RlcygpIHtcbiAgICBsZXQgbm9kZUluZGV4ID0gMDtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2YgdGhpcy5fbm9kZXMpIHtcbiAgICAgIC8vIHdlZWQgb3V0ICdJZGVudGl0eScgbm9kZXMgc28gdGhhdCBubyB0aW1lIGlzIHdhc3RlZCBpbiBleGVjdXRpb25cbiAgICAgIGlmIChub2RlLm9wVHlwZSA9PT0gJ0lkZW50aXR5Jykge1xuICAgICAgICB0aGlzLmRlbGV0ZU5vZGUobm9kZUluZGV4KTtcbiAgICAgIH1cbiAgICAgIG5vZGVJbmRleCsrO1xuICAgIH1cbiAgfVxuXG4gIGlzQWN0aXZhdGlvbihuOiBOb2RlKTogYm9vbGVhbiB7XG4gICAgc3dpdGNoIChuLm9wVHlwZSkge1xuICAgICAgLy8gVE9ETzogYWRkIG90aGVyIGFjdGl2YXRpb24gbWV0aG9kc1xuICAgICAgY2FzZSAnUmVsdSc6XG4gICAgICBjYXNlICdTaWdtb2lkJzpcbiAgICAgIGNhc2UgJ0NsaXAnOlxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBmdXNlQ29udkFjdGl2YXRpb25Ob2RlcygpIHtcbiAgICBmb3IgKGNvbnN0IG5vZGUgb2YgdGhpcy5fbm9kZXMpIHtcbiAgICAgIGlmIChub2RlLm9wVHlwZSA9PT0gJ0NvbnYnKSB7XG4gICAgICAgIGNvbnN0IG5leHQgPSB0aGlzLl9hbGxEYXRhW25vZGUub3V0cHV0c1swXV0uX3RvO1xuICAgICAgICBpZiAobmV4dC5sZW5ndGggPT09IDEgJiYgdGhpcy5pc0FjdGl2YXRpb24odGhpcy5fbm9kZXNbbmV4dFswXV0pKSB7XG4gICAgICAgICAgY29uc3QgY2hpbGQgPSB0aGlzLl9ub2Rlc1tuZXh0WzBdXTtcbiAgICAgICAgICBpZiAoY2hpbGQub3BUeXBlID09PSAnQ2xpcCcpIHtcbiAgICAgICAgICAgIGlmIChjaGlsZC5pbnB1dHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgbm9kZS5hdHRyaWJ1dGVzLnNldChcbiAgICAgICAgICAgICAgICAgICAgJ2FjdGl2YXRpb25fcGFyYW1zJywgJ2Zsb2F0cycsXG4gICAgICAgICAgICAgICAgICAgIFtjaGlsZC5hdHRyaWJ1dGVzLmdldEZsb2F0KCdtaW4nKSwgY2hpbGQuYXR0cmlidXRlcy5nZXRGbG9hdCgnbWF4JyldKTtcbiAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIG5vZGUuYXR0cmlidXRlcy5zZXQoJ2FjdGl2YXRpb25fcGFyYW1zJywgJ2Zsb2F0cycsIFtNSU5fQ0xJUCwgTUFYX0NMSVBdKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgICBjaGlsZC5pbnB1dHMubGVuZ3RoID49IDMgJiYgdGhpcy5fYWxsRGF0YVtjaGlsZC5pbnB1dHNbMV1dLnRlbnNvciAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAgICAgICAgICAgdGhpcy5fYWxsRGF0YVtjaGlsZC5pbnB1dHNbMl1dLnRlbnNvciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgIG5vZGUuYXR0cmlidXRlcy5zZXQoJ2FjdGl2YXRpb25fcGFyYW1zJywgJ2Zsb2F0cycsIFtcbiAgICAgICAgICAgICAgICB0aGlzLl9hbGxEYXRhW2NoaWxkLmlucHV0c1sxXV0udGVuc29yIS5mbG9hdERhdGFbMF0sIHRoaXMuX2FsbERhdGFbY2hpbGQuaW5wdXRzWzJdXS50ZW5zb3IhLmZsb2F0RGF0YVswXVxuICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIC8vIFNraXAgZnVzaW9uIHdpdGggY2xpcCBub2RlIHNpbmNlIGNsaXAgbWluIGFuZCBjbGlwIG1heCBhcmUgbm90IGNvbWluZyBmcm9tIGluaXRpYWxpemVyXG4gICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBub2RlLmF0dHJpYnV0ZXMuc2V0KCdhY3RpdmF0aW9uJywgJ3N0cmluZycsIChjaGlsZC5vcFR5cGUpKTtcbiAgICAgICAgICB0aGlzLmRlbGV0ZU5vZGUobmV4dFswXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0Vudn0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHtXZWJHTENvbnRleHR9IGZyb20gJy4vYmFja2VuZHMvd2ViZ2wvd2ViZ2wtY29udGV4dCc7XG5cbmV4cG9ydCBkZWNsYXJlIG5hbWVzcGFjZSBMb2dnZXIge1xuICBleHBvcnQgaW50ZXJmYWNlIFNldmVyaXR5VHlwZU1hcCB7XG4gICAgdmVyYm9zZTogJ3YnO1xuICAgIGluZm86ICdpJztcbiAgICB3YXJuaW5nOiAndyc7XG4gICAgZXJyb3I6ICdlJztcbiAgICBmYXRhbDogJ2YnO1xuICB9XG5cbiAgZXhwb3J0IHR5cGUgU2V2ZXJpdHkgPSBrZXlvZiBTZXZlcml0eVR5cGVNYXA7XG5cbiAgZXhwb3J0IHR5cGUgUHJvdmlkZXIgPSAnbm9uZSd8J2NvbnNvbGUnO1xuXG4gIC8qKlxuICAgKiBMb2dnaW5nIGNvbmZpZyB0aGF0IHVzZWQgdG8gY29udHJvbCB0aGUgYmVoYXZpb3Igb2YgbG9nZ2VyXG4gICAqL1xuICBleHBvcnQgaW50ZXJmYWNlIENvbmZpZyB7XG4gICAgLyoqXG4gICAgICogU3BlY2lmeSB0aGUgbG9nZ2luZyBwcm92aWRlci4gJ2NvbnNvbGUnIGJ5IGRlZmF1bHRcbiAgICAgKi9cbiAgICBwcm92aWRlcj86IFByb3ZpZGVyO1xuICAgIC8qKlxuICAgICAqIFNwZWNpZnkgdGhlIG1pbmltYWwgbG9nZ2VyIHNlcnZlcml0eS4gJ3dhcm5pbmcnIGJ5IGRlZmF1bHRcbiAgICAgKi9cbiAgICBtaW5pbWFsU2V2ZXJpdHk/OiBMb2dnZXIuU2V2ZXJpdHk7XG4gICAgLyoqXG4gICAgICogV2hldGhlciB0byBvdXRwdXQgZGF0ZSB0aW1lIGluIGxvZy4gdHJ1ZSBieSBkZWZhdWx0XG4gICAgICovXG4gICAgbG9nRGF0ZVRpbWU/OiBib29sZWFuO1xuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgdG8gb3V0cHV0IHNvdXJjZSBpbmZvcm1hdGlvbiAoTm90IHlldCBzdXBwb3J0ZWQpLiBmYWxzZSBieSBkZWZhdWx0XG4gICAgICovXG4gICAgbG9nU291cmNlTG9jYXRpb24/OiBib29sZWFuO1xuICB9XG5cbiAgZXhwb3J0IGludGVyZmFjZSBDYXRlZ29yaXplZExvZ2dlciB7XG4gICAgdmVyYm9zZShjb250ZW50OiBzdHJpbmcpOiB2b2lkO1xuICAgIGluZm8oY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgICB3YXJuaW5nKGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gICAgZXJyb3IoY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgICBmYXRhbChjb250ZW50OiBzdHJpbmcpOiB2b2lkO1xuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVkZWNsYXJlXG5leHBvcnQgaW50ZXJmYWNlIExvZ2dlciB7XG4gIChjYXRlZ29yeTogc3RyaW5nKTogTG9nZ2VyLkNhdGVnb3JpemVkTG9nZ2VyO1xuXG4gIHZlcmJvc2UoY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgdmVyYm9zZShjYXRlZ29yeTogc3RyaW5nLCBjb250ZW50OiBzdHJpbmcpOiB2b2lkO1xuICBpbmZvKGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gIGluZm8oY2F0ZWdvcnk6IHN0cmluZywgY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgd2FybmluZyhjb250ZW50OiBzdHJpbmcpOiB2b2lkO1xuICB3YXJuaW5nKGNhdGVnb3J5OiBzdHJpbmcsIGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gIGVycm9yKGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gIGVycm9yKGNhdGVnb3J5OiBzdHJpbmcsIGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gIGZhdGFsKGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gIGZhdGFsKGNhdGVnb3J5OiBzdHJpbmcsIGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG5cbiAgLyoqXG4gICAqIFJlc2V0IHRoZSBsb2dnZXIgY29uZmlndXJhdGlvbi5cbiAgICogQHBhcmFtIGNvbmZpZyBzcGVjaWZ5IGFuIG9wdGlvbmFsIGRlZmF1bHQgY29uZmlnXG4gICAqL1xuICByZXNldChjb25maWc/OiBMb2dnZXIuQ29uZmlnKTogdm9pZDtcbiAgLyoqXG4gICAqIFNldCB0aGUgbG9nZ2VyJ3MgYmVoYXZpb3Igb24gdGhlIGdpdmVuIGNhdGVnb3J5XG4gICAqIEBwYXJhbSBjYXRlZ29yeSBzcGVjaWZ5IGEgY2F0ZWdvcnkgc3RyaW5nLiBJZiAnKicgaXMgc3BlY2lmaWVkLCBhbGwgcHJldmlvdXMgY29uZmlndXJhdGlvbiB3aWxsIGJlIG92ZXJ3cml0dGVuLiBJZlxuICAgKiAnJyBpcyBzcGVjaWZpZWQsIHRoZSBkZWZhdWx0IGJlaGF2aW9yIHdpbGwgYmUgdXBkYXRlZC5cbiAgICogQHBhcmFtIGNvbmZpZyB0aGUgY29uZmlnIG9iamVjdCB0byBpbmRpY2F0ZSB0aGUgbG9nZ2VyJ3MgYmVoYXZpb3JcbiAgICovXG4gIHNldChjYXRlZ29yeTogc3RyaW5nLCBjb25maWc6IExvZ2dlci5Db25maWcpOiB2b2lkO1xuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGxvZ2dlcidzIGJlaGF2aW9yIGZyb20gb3J0LWNvbW1vbiBlbnZcbiAgICogQHBhcmFtIGVudiB0aGUgZW52IHVzZWQgdG8gc2V0IGxvZ2dlci4gQ3VycmVudGx5IG9ubHkgc2V0dGluZyBsb2dsZXZlbCBpcyBzdXBwb3J0ZWQgdGhyb3VnaCBFbnYuXG4gICAqL1xuICBzZXRXaXRoRW52KGVudjogRW52KTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIExvZ2dlclByb3ZpZGVyIHtcbiAgbG9nKHNldmVyaXR5OiBMb2dnZXIuU2V2ZXJpdHksIGNvbnRlbnQ6IHN0cmluZywgY2F0ZWdvcnk/OiBzdHJpbmcpOiB2b2lkO1xufVxuY2xhc3MgTm9PcExvZ2dlclByb3ZpZGVyIGltcGxlbWVudHMgTG9nZ2VyUHJvdmlkZXIge1xuICBsb2coX3NldmVyaXR5OiBMb2dnZXIuU2V2ZXJpdHksIF9jb250ZW50OiBzdHJpbmcsIF9jYXRlZ29yeT86IHN0cmluZykge1xuICAgIC8vIGRvIG5vdGhpbmdcbiAgfVxufVxuY2xhc3MgQ29uc29sZUxvZ2dlclByb3ZpZGVyIGltcGxlbWVudHMgTG9nZ2VyUHJvdmlkZXIge1xuICBsb2coc2V2ZXJpdHk6IExvZ2dlci5TZXZlcml0eSwgY29udGVudDogc3RyaW5nLCBjYXRlZ29yeT86IHN0cmluZykge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgY29uc29sZS5sb2coYCR7dGhpcy5jb2xvcihzZXZlcml0eSl9ICR7Y2F0ZWdvcnkgPyAnXFx4MWJbMzVtJyArIGNhdGVnb3J5ICsgJ1xceDFiWzBtICcgOiAnJ30ke2NvbnRlbnR9YCk7XG4gIH1cblxuICBwcml2YXRlIGNvbG9yKHNldmVyaXR5OiBMb2dnZXIuU2V2ZXJpdHkpIHtcbiAgICBzd2l0Y2ggKHNldmVyaXR5KSB7XG4gICAgICBjYXNlICd2ZXJib3NlJzpcbiAgICAgICAgcmV0dXJuICdcXHgxYlszNDs0MG12XFx4MWJbMG0nO1xuICAgICAgY2FzZSAnaW5mbyc6XG4gICAgICAgIHJldHVybiAnXFx4MWJbMzJtaVxceDFiWzBtJztcbiAgICAgIGNhc2UgJ3dhcm5pbmcnOlxuICAgICAgICByZXR1cm4gJ1xceDFiWzMwOzQzbXdcXHgxYlswbSc7XG4gICAgICBjYXNlICdlcnJvcic6XG4gICAgICAgIHJldHVybiAnXFx4MWJbMzE7NDBtZVxceDFiWzBtJztcbiAgICAgIGNhc2UgJ2ZhdGFsJzpcbiAgICAgICAgcmV0dXJuICdcXHgxYlsxMDFtZlxceDFiWzBtJztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgc2V2ZXJpdHk6ICR7c2V2ZXJpdHl9YCk7XG4gICAgfVxuICB9XG59XG5cbmNvbnN0IFNFVkVSSVRZX1ZBTFVFID0ge1xuICB2ZXJib3NlOiAxMDAwLFxuICBpbmZvOiAyMDAwLFxuICB3YXJuaW5nOiA0MDAwLFxuICBlcnJvcjogNTAwMCxcbiAgZmF0YWw6IDYwMDBcbn07XG5cbmNvbnN0IExPR0dFUl9QUk9WSURFUl9NQVA6IHtyZWFkb25seSBbcHJvdmlkZXI6IHN0cmluZ106IFJlYWRvbmx5PExvZ2dlclByb3ZpZGVyPn0gPSB7XG4gIFsnbm9uZSddOiBuZXcgTm9PcExvZ2dlclByb3ZpZGVyKCksXG4gIFsnY29uc29sZSddOiBuZXcgQ29uc29sZUxvZ2dlclByb3ZpZGVyKClcbn07XG5jb25zdCBMT0dHRVJfREVGQVVMVF9DT05GSUcgPSB7XG4gIHByb3ZpZGVyOiAnY29uc29sZScsXG4gIG1pbmltYWxTZXZlcml0eTogJ3dhcm5pbmcnLFxuICBsb2dEYXRlVGltZTogdHJ1ZSxcbiAgbG9nU291cmNlTG9jYXRpb246IGZhbHNlXG59O1xubGV0IExPR0dFUl9DT05GSUdfTUFQOlxuICAgIHtbY2F0ZWdvcnk6IHN0cmluZ106IFJlYWRvbmx5PFJlcXVpcmVkPExvZ2dlci5Db25maWc+Pn0gPSB7WycnXTogTE9HR0VSX0RFRkFVTFRfQ09ORklHIGFzIFJlcXVpcmVkPExvZ2dlci5Db25maWc+fTtcblxuZnVuY3Rpb24gbG9nKGNhdGVnb3J5OiBzdHJpbmcpOiBMb2dnZXIuQ2F0ZWdvcml6ZWRMb2dnZXI7XG5mdW5jdGlvbiBsb2coc2V2ZXJpdHk6IExvZ2dlci5TZXZlcml0eSwgY29udGVudDogc3RyaW5nKTogdm9pZDtcbmZ1bmN0aW9uIGxvZyhzZXZlcml0eTogTG9nZ2VyLlNldmVyaXR5LCBjYXRlZ29yeTogc3RyaW5nLCBjb250ZW50OiBzdHJpbmcpOiB2b2lkO1xuZnVuY3Rpb24gbG9nKHNldmVyaXR5OiBMb2dnZXIuU2V2ZXJpdHksIGFyZzE6IHN0cmluZywgYXJnMj86IHN0cmluZyk6IHZvaWQ7XG5mdW5jdGlvbiBsb2coXG4gICAgYXJnMDogc3RyaW5nfExvZ2dlci5TZXZlcml0eSwgYXJnMT86IHN0cmluZywgYXJnMj86IHN0cmluZ3xudW1iZXIsIGFyZzM/OiBudW1iZXIpOiBMb2dnZXIuQ2F0ZWdvcml6ZWRMb2dnZXJ8dm9pZCB7XG4gIGlmIChhcmcxID09PSB1bmRlZmluZWQpIHtcbiAgICAvLyBsb2coY2F0ZWdvcnk6IHN0cmluZyk6IExvZ2dlci5DYXRlZ29yaXplZExvZ2dlcjtcbiAgICByZXR1cm4gY3JlYXRlQ2F0ZWdvcml6ZWRMb2dnZXIoYXJnMCk7XG4gIH0gZWxzZSBpZiAoYXJnMiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgLy8gbG9nKHNldmVyaXR5LCBjb250ZW50KTtcbiAgICBsb2dJbnRlcm5hbChhcmcwIGFzIExvZ2dlci5TZXZlcml0eSwgYXJnMSwgMSk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGFyZzIgPT09ICdudW1iZXInICYmIGFyZzMgPT09IHVuZGVmaW5lZCkge1xuICAgIC8vIGxvZyhzZXZlcml0eSwgY29udGVudCwgc3RhY2spXG4gICAgbG9nSW50ZXJuYWwoYXJnMCBhcyBMb2dnZXIuU2V2ZXJpdHksIGFyZzEsIGFyZzIpO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBhcmcyID09PSAnc3RyaW5nJyAmJiBhcmczID09PSB1bmRlZmluZWQpIHtcbiAgICAvLyBsb2coc2V2ZXJpdHksIGNhdGVnb3J5LCBjb250ZW50KVxuICAgIGxvZ0ludGVybmFsKGFyZzAgYXMgTG9nZ2VyLlNldmVyaXR5LCBhcmcyLCAxLCBhcmcxKTtcbiAgfSBlbHNlIGlmICh0eXBlb2YgYXJnMiA9PT0gJ3N0cmluZycgJiYgdHlwZW9mIGFyZzMgPT09ICdudW1iZXInKSB7XG4gICAgLy8gbG9nKHNldmVyaXR5LCBjYXRlZ29yeSwgY29udGVudCwgc3RhY2spXG4gICAgbG9nSW50ZXJuYWwoYXJnMCBhcyBMb2dnZXIuU2V2ZXJpdHksIGFyZzIsIGFyZzMsIGFyZzEpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2lucHV0IGlzIHZhbGlkJyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlQ2F0ZWdvcml6ZWRMb2dnZXIoY2F0ZWdvcnk6IHN0cmluZyk6IExvZ2dlci5DYXRlZ29yaXplZExvZ2dlciB7XG4gIHJldHVybiB7XG4gICAgdmVyYm9zZTogbG9nLnZlcmJvc2UuYmluZChudWxsLCBjYXRlZ29yeSksXG4gICAgaW5mbzogbG9nLmluZm8uYmluZChudWxsLCBjYXRlZ29yeSksXG4gICAgd2FybmluZzogbG9nLndhcm5pbmcuYmluZChudWxsLCBjYXRlZ29yeSksXG4gICAgZXJyb3I6IGxvZy5lcnJvci5iaW5kKG51bGwsIGNhdGVnb3J5KSxcbiAgICBmYXRhbDogbG9nLmZhdGFsLmJpbmQobnVsbCwgY2F0ZWdvcnkpXG4gIH07XG59XG5cbi8vIE5PVEU6IGFyZ3VtZW50ICdjYXRlZ29yeScgaXMgcHV0IHRoZSBsYXN0IHBhcmFtZXRlciBiZWFjYXVzZSB0eXBlc2NyaXB0XG4vLyBkb2Vzbid0IGFsbG93IG9wdGlvbmFsIGFyZ3VtZW50IHB1dCBpbiBmcm9udCBvZiByZXF1aXJlZCBhcmd1bWVudC4gVGhpc1xuLy8gb3JkZXIgaXMgZGlmZmVyZW50IGZyb20gYSB1c3VhbCBsb2dnaW5nIEFQSS5cbmZ1bmN0aW9uIGxvZ0ludGVybmFsKHNldmVyaXR5OiBMb2dnZXIuU2V2ZXJpdHksIGNvbnRlbnQ6IHN0cmluZywgc3RhY2s6IG51bWJlciwgY2F0ZWdvcnk/OiBzdHJpbmcpIHtcbiAgY29uc3QgY29uZmlnID0gTE9HR0VSX0NPTkZJR19NQVBbY2F0ZWdvcnkgfHwgJyddIHx8IExPR0dFUl9DT05GSUdfTUFQWycnXTtcbiAgaWYgKFNFVkVSSVRZX1ZBTFVFW3NldmVyaXR5XSA8IFNFVkVSSVRZX1ZBTFVFW2NvbmZpZy5taW5pbWFsU2V2ZXJpdHldKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKGNvbmZpZy5sb2dEYXRlVGltZSkge1xuICAgIGNvbnRlbnQgPSBgJHtuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCl9fCR7Y29udGVudH1gO1xuICB9XG5cbiAgaWYgKGNvbmZpZy5sb2dTb3VyY2VMb2NhdGlvbikge1xuICAgIC8vIFRPRE86IGNhbGN1bGF0ZSBzb3VyY2UgbG9jYXRpb24gZnJvbSAnc3RhY2snXG4gIH1cblxuICBMT0dHRVJfUFJPVklERVJfTUFQW2NvbmZpZy5wcm92aWRlcl0ubG9nKHNldmVyaXR5LCBjb250ZW50LCBjYXRlZ29yeSk7XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbmFtZXNwYWNlXG5uYW1lc3BhY2UgbG9nIHtcbiAgZXhwb3J0IGZ1bmN0aW9uIHZlcmJvc2UoY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgZXhwb3J0IGZ1bmN0aW9uIHZlcmJvc2UoY2F0ZWdvcnk6IHN0cmluZywgY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgZXhwb3J0IGZ1bmN0aW9uIHZlcmJvc2UoYXJnMDogc3RyaW5nLCBhcmcxPzogc3RyaW5nKSB7XG4gICAgbG9nKCd2ZXJib3NlJywgYXJnMCwgYXJnMSk7XG4gIH1cbiAgZXhwb3J0IGZ1bmN0aW9uIGluZm8oY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgZXhwb3J0IGZ1bmN0aW9uIGluZm8oY2F0ZWdvcnk6IHN0cmluZywgY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgZXhwb3J0IGZ1bmN0aW9uIGluZm8oYXJnMDogc3RyaW5nLCBhcmcxPzogc3RyaW5nKSB7XG4gICAgbG9nKCdpbmZvJywgYXJnMCwgYXJnMSk7XG4gIH1cbiAgZXhwb3J0IGZ1bmN0aW9uIHdhcm5pbmcoY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgZXhwb3J0IGZ1bmN0aW9uIHdhcm5pbmcoY2F0ZWdvcnk6IHN0cmluZywgY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgZXhwb3J0IGZ1bmN0aW9uIHdhcm5pbmcoYXJnMDogc3RyaW5nLCBhcmcxPzogc3RyaW5nKSB7XG4gICAgbG9nKCd3YXJuaW5nJywgYXJnMCwgYXJnMSk7XG4gIH1cbiAgZXhwb3J0IGZ1bmN0aW9uIGVycm9yKGNvbnRlbnQ6IHN0cmluZyk6IHZvaWQ7XG4gIGV4cG9ydCBmdW5jdGlvbiBlcnJvcihjYXRlZ29yeTogc3RyaW5nLCBjb250ZW50OiBzdHJpbmcpOiB2b2lkO1xuICBleHBvcnQgZnVuY3Rpb24gZXJyb3IoYXJnMDogc3RyaW5nLCBhcmcxPzogc3RyaW5nKSB7XG4gICAgbG9nKCdlcnJvcicsIGFyZzAsIGFyZzEpO1xuICB9XG4gIGV4cG9ydCBmdW5jdGlvbiBmYXRhbChjb250ZW50OiBzdHJpbmcpOiB2b2lkO1xuICBleHBvcnQgZnVuY3Rpb24gZmF0YWwoY2F0ZWdvcnk6IHN0cmluZywgY29udGVudDogc3RyaW5nKTogdm9pZDtcbiAgZXhwb3J0IGZ1bmN0aW9uIGZhdGFsKGFyZzA6IHN0cmluZywgYXJnMT86IHN0cmluZykge1xuICAgIGxvZygnZmF0YWwnLCBhcmcwLCBhcmcxKTtcbiAgfVxuXG4gIGV4cG9ydCBmdW5jdGlvbiByZXNldChjb25maWc/OiBMb2dnZXIuQ29uZmlnKTogdm9pZCB7XG4gICAgTE9HR0VSX0NPTkZJR19NQVAgPSB7fTtcbiAgICBzZXQoJycsIGNvbmZpZyB8fCB7fSk7XG4gIH1cbiAgZXhwb3J0IGZ1bmN0aW9uIHNldChjYXRlZ29yeTogc3RyaW5nLCBjb25maWc6IExvZ2dlci5Db25maWcpOiB2b2lkIHtcbiAgICBpZiAoY2F0ZWdvcnkgPT09ICcqJykge1xuICAgICAgcmVzZXQoY29uZmlnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcHJldmlvdXNDb25maWcgPSBMT0dHRVJfQ09ORklHX01BUFtjYXRlZ29yeV0gfHwgTE9HR0VSX0RFRkFVTFRfQ09ORklHO1xuICAgICAgTE9HR0VSX0NPTkZJR19NQVBbY2F0ZWdvcnldID0ge1xuICAgICAgICBwcm92aWRlcjogY29uZmlnLnByb3ZpZGVyIHx8IHByZXZpb3VzQ29uZmlnLnByb3ZpZGVyLFxuICAgICAgICBtaW5pbWFsU2V2ZXJpdHk6IGNvbmZpZy5taW5pbWFsU2V2ZXJpdHkgfHwgcHJldmlvdXNDb25maWcubWluaW1hbFNldmVyaXR5LFxuICAgICAgICBsb2dEYXRlVGltZTogKGNvbmZpZy5sb2dEYXRlVGltZSA9PT0gdW5kZWZpbmVkKSA/IHByZXZpb3VzQ29uZmlnLmxvZ0RhdGVUaW1lIDogY29uZmlnLmxvZ0RhdGVUaW1lLFxuICAgICAgICBsb2dTb3VyY2VMb2NhdGlvbjogKGNvbmZpZy5sb2dTb3VyY2VMb2NhdGlvbiA9PT0gdW5kZWZpbmVkKSA/IHByZXZpb3VzQ29uZmlnLmxvZ1NvdXJjZUxvY2F0aW9uIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maWcubG9nU291cmNlTG9jYXRpb25cbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gVE9ETzogd2Ugd2FudCB0byBzdXBwb3J0IHdpbGRjYXJkIG9yIHJlZ2V4P1xuICB9XG5cbiAgZXhwb3J0IGZ1bmN0aW9uIHNldFdpdGhFbnYoZW52OiBFbnYpOiB2b2lkIHtcbiAgICBjb25zdCBjb25maWc6IExvZ2dlci5Db25maWcgPSB7fTtcbiAgICBpZiAoZW52LmxvZ0xldmVsKSB7XG4gICAgICBjb25maWcubWluaW1hbFNldmVyaXR5ID0gZW52LmxvZ0xldmVsIGFzIExvZ2dlci5TZXZlcml0eTtcbiAgICB9XG4gICAgc2V0KCcnLCBjb25maWcpO1xuICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVkZWNsYXJlLCBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cbmV4cG9ydCBjb25zdCBMb2dnZXI6IExvZ2dlciA9IGxvZztcblxuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIFByb2ZpbGVyIHtcbiAgZXhwb3J0IGludGVyZmFjZSBDb25maWcge1xuICAgIG1heE51bWJlckV2ZW50cz86IG51bWJlcjtcbiAgICBmbHVzaEJhdGNoU2l6ZT86IG51bWJlcjtcbiAgICBmbHVzaEludGVydmFsSW5NaWxsaXNlY29uZHM/OiBudW1iZXI7XG4gIH1cblxuICBleHBvcnQgdHlwZSBFdmVudENhdGVnb3J5ID0gJ3Nlc3Npb24nfCdub2RlJ3wnb3AnfCdiYWNrZW5kJztcblxuICBleHBvcnQgaW50ZXJmYWNlIEV2ZW50IHtcbiAgICBlbmQoKTogdm9pZHxQcm9taXNlPHZvaWQ+O1xuICB9XG59XG4vLyBUT0RPXG4vLyBjbGFzcyBXZWJHTEV2ZW50IGltcGxlbWVudHMgUHJvZmlsZXIuRXZlbnQge31cblxuY2xhc3MgRXZlbnQgaW1wbGVtZW50cyBQcm9maWxlci5FdmVudCB7XG4gIGNvbnN0cnVjdG9yKFxuICAgICAgcHVibGljIGNhdGVnb3J5OiBQcm9maWxlci5FdmVudENhdGVnb3J5LCBwdWJsaWMgbmFtZTogc3RyaW5nLCBwdWJsaWMgc3RhcnRUaW1lOiBudW1iZXIsXG4gICAgICBwcml2YXRlIGVuZENhbGxiYWNrOiAoZTogRXZlbnQpID0+IHZvaWR8UHJvbWlzZTx2b2lkPiwgcHVibGljIHRpbWVyPzogV2ViR0xRdWVyeSwgcHVibGljIGN0eD86IFdlYkdMQ29udGV4dCkge31cblxuICBhc3luYyBlbmQoKSB7XG4gICAgcmV0dXJuIHRoaXMuZW5kQ2FsbGJhY2sodGhpcyk7XG4gIH1cblxuICBhc3luYyBjaGVja1RpbWVyKCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgaWYgKHRoaXMuY3R4ID09PSB1bmRlZmluZWQgfHwgdGhpcy50aW1lciA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHdlYmdsIHRpbWVyIGZvdW5kJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY3R4LmVuZFRpbWVyKCk7XG4gICAgICByZXR1cm4gdGhpcy5jdHgud2FpdEZvclF1ZXJ5QW5kR2V0VGltZSh0aGlzLnRpbWVyKTtcbiAgICB9XG4gIH1cbn1cblxuY2xhc3MgRXZlbnRSZWNvcmQge1xuICBjb25zdHJ1Y3RvcihcbiAgICAgIHB1YmxpYyBjYXRlZ29yeTogUHJvZmlsZXIuRXZlbnRDYXRlZ29yeSwgcHVibGljIG5hbWU6IHN0cmluZywgcHVibGljIHN0YXJ0VGltZTogbnVtYmVyLCBwdWJsaWMgZW5kVGltZTogbnVtYmVyKSB7fVxufVxuXG5leHBvcnQgY2xhc3MgUHJvZmlsZXIge1xuICBzdGF0aWMgY3JlYXRlKGNvbmZpZz86IFByb2ZpbGVyLkNvbmZpZyk6IFByb2ZpbGVyIHtcbiAgICBpZiAoY29uZmlnID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBuZXcgdGhpcygpO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IHRoaXMoY29uZmlnLm1heE51bWJlckV2ZW50cywgY29uZmlnLmZsdXNoQmF0Y2hTaXplLCBjb25maWcuZmx1c2hJbnRlcnZhbEluTWlsbGlzZWNvbmRzKTtcbiAgfVxuXG4gIHByaXZhdGUgY29uc3RydWN0b3IobWF4TnVtYmVyRXZlbnRzPzogbnVtYmVyLCBmbHVzaEJhdGNoU2l6ZT86IG51bWJlciwgZmx1c2hJbnRlcnZhbEluTWlsbGlzZWNvbmRzPzogbnVtYmVyKSB7XG4gICAgdGhpcy5fc3RhcnRlZCA9IGZhbHNlO1xuICAgIHRoaXMuX21heE51bWJlckV2ZW50cyA9IG1heE51bWJlckV2ZW50cyA9PT0gdW5kZWZpbmVkID8gMTAwMDAgOiBtYXhOdW1iZXJFdmVudHM7XG4gICAgdGhpcy5fZmx1c2hCYXRjaFNpemUgPSBmbHVzaEJhdGNoU2l6ZSA9PT0gdW5kZWZpbmVkID8gMTAgOiBmbHVzaEJhdGNoU2l6ZTtcbiAgICB0aGlzLl9mbHVzaEludGVydmFsSW5NaWxsaXNlY29uZHMgPSBmbHVzaEludGVydmFsSW5NaWxsaXNlY29uZHMgPT09IHVuZGVmaW5lZCA/IDUwMDAgOiBmbHVzaEludGVydmFsSW5NaWxsaXNlY29uZHM7XG4gIH1cblxuICAvLyBzdGFydCBwcm9maWxpbmdcbiAgc3RhcnQoKSB7XG4gICAgdGhpcy5fc3RhcnRlZCA9IHRydWU7XG4gICAgdGhpcy5fdGltaW5nRXZlbnRzID0gW107XG4gICAgdGhpcy5fZmx1c2hUaW1lID0gbm93KCk7XG4gICAgdGhpcy5fZmx1c2hQb2ludGVyID0gMDtcbiAgfVxuXG4gIC8vIHN0b3AgcHJvZmlsaW5nXG4gIHN0b3AoKSB7XG4gICAgdGhpcy5fc3RhcnRlZCA9IGZhbHNlO1xuICAgIGZvciAoOyB0aGlzLl9mbHVzaFBvaW50ZXIgPCB0aGlzLl90aW1pbmdFdmVudHMubGVuZ3RoOyB0aGlzLl9mbHVzaFBvaW50ZXIrKykge1xuICAgICAgdGhpcy5sb2dPbmVFdmVudCh0aGlzLl90aW1pbmdFdmVudHNbdGhpcy5fZmx1c2hQb2ludGVyXSk7XG4gICAgfVxuICB9XG5cbiAgLy8gY3JlYXRlIGFuIGV2ZW50IHNjb3BlIGZvciB0aGUgc3BlY2lmaWMgZnVuY3Rpb25cbiAgZXZlbnQ8VD4oY2F0ZWdvcnk6IFByb2ZpbGVyLkV2ZW50Q2F0ZWdvcnksIG5hbWU6IHN0cmluZywgZnVuYzogKCkgPT4gVCwgY3R4PzogV2ViR0xDb250ZXh0KTogVDtcbiAgZXZlbnQ8VD4oY2F0ZWdvcnk6IFByb2ZpbGVyLkV2ZW50Q2F0ZWdvcnksIG5hbWU6IHN0cmluZywgZnVuYzogKCkgPT4gUHJvbWlzZTxUPiwgY3R4PzogV2ViR0xDb250ZXh0KTogUHJvbWlzZTxUPjtcblxuICBldmVudDxUPihjYXRlZ29yeTogUHJvZmlsZXIuRXZlbnRDYXRlZ29yeSwgbmFtZTogc3RyaW5nLCBmdW5jOiAoKSA9PiBUIHwgUHJvbWlzZTxUPiwgY3R4PzogV2ViR0xDb250ZXh0KTogVFxuICAgICAgfFByb21pc2U8VD4ge1xuICAgIGNvbnN0IGV2ZW50ID0gdGhpcy5fc3RhcnRlZCA/IHRoaXMuYmVnaW4oY2F0ZWdvcnksIG5hbWUsIGN0eCkgOiB1bmRlZmluZWQ7XG4gICAgbGV0IGlzUHJvbWlzZSA9IGZhbHNlO1xuXG4gICAgY29uc3QgcmVzID0gZnVuYygpO1xuXG4gICAgLy8gd2UgY29uc2lkZXIgYSB0aGVuLWFibGUgb2JqZWN0IGlzIGEgcHJvbWlzZVxuICAgIGlmIChyZXMgJiYgdHlwZW9mIChyZXMgYXMgUHJvbWlzZTxUPikudGhlbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgaXNQcm9taXNlID0gdHJ1ZTtcbiAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxUPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgIChyZXMgYXMgUHJvbWlzZTxUPilcbiAgICAgICAgICAgIC50aGVuKFxuICAgICAgICAgICAgICAgIGFzeW5jIHZhbHVlID0+IHsgIC8vIGZ1bGZpbGxlZFxuICAgICAgICAgICAgICAgICAgaWYgKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IGV2ZW50LmVuZCgpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBhc3luYyByZWFzb24gPT4geyAgLy8gcmVqZWN0ZWRcbiAgICAgICAgICAgICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgICAgICAgICAgICBhd2FpdCBldmVudC5lbmQoKTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIHJlamVjdChyZWFzb24pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICAgIGlmICghaXNQcm9taXNlICYmIGV2ZW50KSB7XG4gICAgICBjb25zdCBldmVudFJlcyA9IGV2ZW50LmVuZCgpO1xuICAgICAgaWYgKGV2ZW50UmVzICYmIHR5cGVvZiBldmVudFJlcy50aGVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxUPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgKGV2ZW50UmVzKS50aGVuKFxuICAgICAgICAgICAgICAoKSA9PiB7ICAvLyBmdWxmaWxsZWRcbiAgICAgICAgICAgICAgICByZXNvbHZlKHJlcyk7XG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIChyZWFzb24pID0+IHsgIC8vIHJlamVjdGVkXG4gICAgICAgICAgICAgICAgcmVqZWN0KHJlYXNvbik7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbiAgfVxuXG4gIC8vIGJlZ2luIGFuIGV2ZW50XG4gIGJlZ2luKGNhdGVnb3J5OiBQcm9maWxlci5FdmVudENhdGVnb3J5LCBuYW1lOiBzdHJpbmcsIGN0eD86IFdlYkdMQ29udGV4dCk6IEV2ZW50IHtcbiAgICBpZiAoIXRoaXMuX3N0YXJ0ZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigncHJvZmlsZXIgaXMgbm90IHN0YXJ0ZWQgeWV0Jyk7XG4gICAgfVxuICAgIGlmIChjdHggPT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3Qgc3RhcnRUaW1lID0gbm93KCk7XG4gICAgICB0aGlzLmZsdXNoKHN0YXJ0VGltZSk7XG4gICAgICByZXR1cm4gbmV3IEV2ZW50KGNhdGVnb3J5LCBuYW1lLCBzdGFydFRpbWUsIGUgPT4gdGhpcy5lbmRTeW5jKGUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgdGltZXI6IFdlYkdMUXVlcnkgPSBjdHguYmVnaW5UaW1lcigpO1xuICAgICAgcmV0dXJuIG5ldyBFdmVudChjYXRlZ29yeSwgbmFtZSwgMCwgYXN5bmMgZSA9PiB0aGlzLmVuZChlKSwgdGltZXIsIGN0eCk7XG4gICAgfVxuICB9XG5cbiAgLy8gZW5kIHRoZSBzcGVjaWZpYyBldmVudFxuICBwcml2YXRlIGFzeW5jIGVuZChldmVudDogRXZlbnQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBlbmRUaW1lOiBudW1iZXIgPSBhd2FpdCBldmVudC5jaGVja1RpbWVyKCk7XG4gICAgaWYgKHRoaXMuX3RpbWluZ0V2ZW50cy5sZW5ndGggPCB0aGlzLl9tYXhOdW1iZXJFdmVudHMpIHtcbiAgICAgIHRoaXMuX3RpbWluZ0V2ZW50cy5wdXNoKG5ldyBFdmVudFJlY29yZChldmVudC5jYXRlZ29yeSwgZXZlbnQubmFtZSwgZXZlbnQuc3RhcnRUaW1lLCBlbmRUaW1lKSk7XG4gICAgICB0aGlzLmZsdXNoKGVuZFRpbWUpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZW5kU3luYyhldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBlbmRUaW1lOiBudW1iZXIgPSBub3coKTtcbiAgICBpZiAodGhpcy5fdGltaW5nRXZlbnRzLmxlbmd0aCA8IHRoaXMuX21heE51bWJlckV2ZW50cykge1xuICAgICAgdGhpcy5fdGltaW5nRXZlbnRzLnB1c2gobmV3IEV2ZW50UmVjb3JkKGV2ZW50LmNhdGVnb3J5LCBldmVudC5uYW1lLCBldmVudC5zdGFydFRpbWUsIGVuZFRpbWUpKTtcbiAgICAgIHRoaXMuZmx1c2goZW5kVGltZSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBsb2dPbmVFdmVudChldmVudDogRXZlbnRSZWNvcmQpIHtcbiAgICBMb2dnZXIudmVyYm9zZShcbiAgICAgICAgYFByb2ZpbGVyLiR7ZXZlbnQuY2F0ZWdvcnl9YCxcbiAgICAgICAgYCR7KGV2ZW50LmVuZFRpbWUgLSBldmVudC5zdGFydFRpbWUpLnRvRml4ZWQoMil9bXMgb24gZXZlbnQgJyR7ZXZlbnQubmFtZX0nIGF0ICR7ZXZlbnQuZW5kVGltZS50b0ZpeGVkKDIpfWApO1xuICB9XG5cbiAgcHJpdmF0ZSBmbHVzaChjdXJyZW50VGltZTogbnVtYmVyKSB7XG4gICAgaWYgKHRoaXMuX3RpbWluZ0V2ZW50cy5sZW5ndGggLSB0aGlzLl9mbHVzaFBvaW50ZXIgPj0gdGhpcy5fZmx1c2hCYXRjaFNpemUgfHxcbiAgICAgICAgY3VycmVudFRpbWUgLSB0aGlzLl9mbHVzaFRpbWUgPj0gdGhpcy5fZmx1c2hJbnRlcnZhbEluTWlsbGlzZWNvbmRzKSB7XG4gICAgICAvLyBzaG91bGQgZmx1c2ggd2hlbiBlaXRoZXIgYmF0Y2ggc2l6ZSBhY2N1bWxhdGVkIG9yIGludGVydmFsIGVsZXBzZWRcblxuICAgICAgZm9yIChjb25zdCBwcmV2aW91c1BvaW50ZXIgPSB0aGlzLl9mbHVzaFBvaW50ZXI7IHRoaXMuX2ZsdXNoUG9pbnRlciA8IHByZXZpb3VzUG9pbnRlciArIHRoaXMuX2ZsdXNoQmF0Y2hTaXplICYmXG4gICAgICAgICAgIHRoaXMuX2ZsdXNoUG9pbnRlciA8IHRoaXMuX3RpbWluZ0V2ZW50cy5sZW5ndGg7XG4gICAgICAgICAgIHRoaXMuX2ZsdXNoUG9pbnRlcisrKSB7XG4gICAgICAgIHRoaXMubG9nT25lRXZlbnQodGhpcy5fdGltaW5nRXZlbnRzW3RoaXMuX2ZsdXNoUG9pbnRlcl0pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9mbHVzaFRpbWUgPSBub3coKTtcbiAgICB9XG4gIH1cblxuICBnZXQgc3RhcnRlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhcnRlZDtcbiAgfVxuICBwcml2YXRlIF9zdGFydGVkID0gZmFsc2U7XG4gIHByaXZhdGUgX3RpbWluZ0V2ZW50czogRXZlbnRSZWNvcmRbXTtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9tYXhOdW1iZXJFdmVudHM6IG51bWJlcjtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9mbHVzaEJhdGNoU2l6ZTogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IF9mbHVzaEludGVydmFsSW5NaWxsaXNlY29uZHM6IG51bWJlcjtcblxuICBwcml2YXRlIF9mbHVzaFRpbWU6IG51bWJlcjtcbiAgcHJpdmF0ZSBfZmx1c2hQb2ludGVyID0gMDtcbn1cblxuLyoqXG4gKiByZXR1cm5zIGEgbnVtYmVyIHRvIHJlcHJlc2VudCB0aGUgY3VycmVudCB0aW1lc3RhbXAgaW4gYSByZXNvbHV0aW9uIGFzIGhpZ2ggYXMgcG9zc2libGUuXG4gKi9cbmV4cG9ydCBjb25zdCBub3cgPSAodHlwZW9mIHBlcmZvcm1hbmNlICE9PSAndW5kZWZpbmVkJyAmJiBwZXJmb3JtYW5jZS5ub3cpID8gKCkgPT4gcGVyZm9ybWFuY2Uubm93KCkgOiBEYXRlLm5vdztcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge2ZsYXRidWZmZXJzfSBmcm9tICdmbGF0YnVmZmVycyc7XG5pbXBvcnQge29ubnh9IGZyb20gJ29ubngtcHJvdG8nO1xuXG5pbXBvcnQge0dyYXBofSBmcm9tICcuL2dyYXBoJztcbmltcG9ydCB7T3BTZXR9IGZyb20gJy4vb3BzZXQnO1xuaW1wb3J0IHtvbm54cnVudGltZX0gZnJvbSAnLi9vcnQtc2NoZW1hL29ydC1nZW5lcmF0ZWQnO1xuaW1wb3J0IHtMb25nVXRpbH0gZnJvbSAnLi91dGlsJztcblxuaW1wb3J0IG9ydEZicyA9IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnM7XG5cbmV4cG9ydCBjbGFzcyBNb2RlbCB7XG4gIC8vIGVtcHR5IG1vZGVsXG4gIGNvbnN0cnVjdG9yKCkge31cblxuICBsb2FkKGJ1ZjogVWludDhBcnJheSwgZ3JhcGhJbml0aWFsaXplcj86IEdyYXBoLkluaXRpYWxpemVyLCBpc09ydEZvcm1hdD86IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAoIWlzT3J0Rm9ybWF0KSB7XG4gICAgICAvLyBpc09ydEZvcm1hdCA9PT0gZmFsc2UgfHwgaXNPcnRGb3JtYXQgPT09IHVuZGVmaW5lZFxuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5sb2FkRnJvbU9ubnhGb3JtYXQoYnVmLCBncmFwaEluaXRpYWxpemVyKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoaXNPcnRGb3JtYXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IGU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLmxvYWRGcm9tT3J0Rm9ybWF0KGJ1ZiwgZ3JhcGhJbml0aWFsaXplcik7XG4gIH1cblxuICBwcml2YXRlIGxvYWRGcm9tT25ueEZvcm1hdChidWY6IFVpbnQ4QXJyYXksIGdyYXBoSW5pdGlhbGl6ZXI/OiBHcmFwaC5Jbml0aWFsaXplcik6IHZvaWQge1xuICAgIGNvbnN0IG1vZGVsUHJvdG8gPSBvbm54Lk1vZGVsUHJvdG8uZGVjb2RlKGJ1Zik7XG4gICAgY29uc3QgaXJWZXJzaW9uID0gTG9uZ1V0aWwubG9uZ1RvTnVtYmVyKG1vZGVsUHJvdG8uaXJWZXJzaW9uKTtcbiAgICBpZiAoaXJWZXJzaW9uIDwgMykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdvbmx5IHN1cHBvcnQgT05OWCBtb2RlbCB3aXRoIElSX1ZFUlNJT04+PTMnKTtcbiAgICB9XG5cbiAgICB0aGlzLl9vcHNldHMgPVxuICAgICAgICBtb2RlbFByb3RvLm9wc2V0SW1wb3J0Lm1hcChpID0+ICh7ZG9tYWluOiBpLmRvbWFpbiBhcyBzdHJpbmcsIHZlcnNpb246IExvbmdVdGlsLmxvbmdUb051bWJlcihpLnZlcnNpb24hKX0pKTtcblxuICAgIHRoaXMuX2dyYXBoID0gR3JhcGguZnJvbShtb2RlbFByb3RvLmdyYXBoISwgZ3JhcGhJbml0aWFsaXplcik7XG4gIH1cblxuICBwcml2YXRlIGxvYWRGcm9tT3J0Rm9ybWF0KGJ1ZjogVWludDhBcnJheSwgZ3JhcGhJbml0aWFsaXplcj86IEdyYXBoLkluaXRpYWxpemVyKTogdm9pZCB7XG4gICAgY29uc3QgZmIgPSBuZXcgZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcihidWYpO1xuICAgIGNvbnN0IG9ydE1vZGVsID0gb3J0RmJzLkluZmVyZW5jZVNlc3Npb24uZ2V0Um9vdEFzSW5mZXJlbmNlU2Vzc2lvbihmYikubW9kZWwoKSE7XG4gICAgY29uc3QgaXJWZXJzaW9uID0gTG9uZ1V0aWwubG9uZ1RvTnVtYmVyKG9ydE1vZGVsLmlyVmVyc2lvbigpKTtcbiAgICBpZiAoaXJWZXJzaW9uIDwgMykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdvbmx5IHN1cHBvcnQgT05OWCBtb2RlbCB3aXRoIElSX1ZFUlNJT04+PTMnKTtcbiAgICB9XG4gICAgdGhpcy5fb3BzZXRzID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvcnRNb2RlbC5vcHNldEltcG9ydExlbmd0aCgpOyBpKyspIHtcbiAgICAgIGNvbnN0IG9wc2V0SWQgPSBvcnRNb2RlbC5vcHNldEltcG9ydChpKSE7XG4gICAgICB0aGlzLl9vcHNldHMucHVzaCh7ZG9tYWluOiBvcHNldElkPy5kb21haW4oKSBhcyBzdHJpbmcsIHZlcnNpb246IExvbmdVdGlsLmxvbmdUb051bWJlcihvcHNldElkLnZlcnNpb24oKSEpfSk7XG4gICAgfVxuXG4gICAgdGhpcy5fZ3JhcGggPSBHcmFwaC5mcm9tKG9ydE1vZGVsLmdyYXBoKCkhLCBncmFwaEluaXRpYWxpemVyKTtcbiAgfVxuXG4gIHByaXZhdGUgX2dyYXBoOiBHcmFwaDtcbiAgZ2V0IGdyYXBoKCk6IEdyYXBoIHtcbiAgICByZXR1cm4gdGhpcy5fZ3JhcGg7XG4gIH1cblxuICBwcml2YXRlIF9vcHNldHM6IE9wU2V0W107XG4gIGdldCBvcHNldHMoKTogcmVhZG9ubHkgT3BTZXRbXSB7XG4gICAgcmV0dXJuIHRoaXMuX29wc2V0cztcbiAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7SW5mZXJlbmNlSGFuZGxlcn0gZnJvbSAnLi9iYWNrZW5kJztcbmltcG9ydCB7R3JhcGh9IGZyb20gJy4vZ3JhcGgnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4vdGVuc29yJztcblxuZXhwb3J0IHR5cGUgT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjxUPiA9IChpbmZlcmVuY2VIYW5kbGVyOiBJbmZlcmVuY2VIYW5kbGVyLCBpbnB1dHM6IFRlbnNvcltdLCBjb250ZXh0OiBUKSA9PiBUZW5zb3JbXTtcbmV4cG9ydCB0eXBlIE9wZXJhdG9ySW5pdGlhbGl6YXRpb248VD4gPSAobm9kZTogR3JhcGguTm9kZSwgZ3JhcGg6IEdyYXBoKSA9PiBUO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9wZXJhdG9yIHtcbiAgcmVhZG9ubHkgaW1wbDogT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjx1bmtub3duPjtcbiAgcmVhZG9ubHkgY29udGV4dDogR3JhcGguTm9kZXx1bmtub3duO1xufVxuXG5leHBvcnQgY29uc3QgTlVNQkVSX1RZUEVTOiByZWFkb25seSBUZW5zb3IuRGF0YVR5cGVbXSA9XG4gICAgWydmbG9hdDMyJywgJ2Zsb2F0NjQnLCAnaW50MzInLCAnaW50MTYnLCAnaW50OCcsICd1aW50MTYnLCAndWludDMyJywgJ3VpbnQ4J107XG5leHBvcnQgY29uc3QgSU5UX1RZUEVTOiByZWFkb25seSBUZW5zb3IuRGF0YVR5cGVbXSA9IFsnaW50MzInLCAnaW50MTYnLCAnaW50OCcsICd1aW50MTYnLCAndWludDMyJywgJ3VpbnQ4J107XG5leHBvcnQgY29uc3QgRkxPQVRfVFlQRVM6IHJlYWRvbmx5IFRlbnNvci5EYXRhVHlwZVtdID0gWydmbG9hdDMyJywgJ2Zsb2F0NjQnXTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0dyYXBofSBmcm9tICcuL2dyYXBoJztcbmltcG9ydCB7T3BlcmF0b3JJbXBsZW1lbnRhdGlvbiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbn0gZnJvbSAnLi9vcGVyYXRvcnMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9wU2V0IHtcbiAgZG9tYWluOiBzdHJpbmc7XG4gIHZlcnNpb246IG51bWJlcjtcbn1cbmV4cG9ydCBkZWNsYXJlIG5hbWVzcGFjZSBPcFNldCB7XG4gIC8qKlxuICAgKiBEb21haW4gb2YgYW4gb3BzZXQsIGl0IGNhbiBiZSBhbiBlbXB0eSBzdHJpbmcoZGVmYXVsdCB2YWx1ZSwgcmVwcmVzZW50IGZvciBhaS5vbm54KSwgb3IgJ2FpLm9ubngubWwnXG4gICAqL1xuICB0eXBlIERvbWFpbiA9ICcnfCdhaS5vbm54Lm1sJ3wnY29tLm1pY3Jvc29mdCc7XG4gIC8qKlxuICAgKiBBIHJlc29sdmUgcnVsZSBjb25zaXN0cyBvZiA0IG9yIDUgaXRlbXM6IG9wVHlwZSwgb3BTZXREb21haW4sIHZlcnNpb25TZWxlY3Rvciwgb3BlcmF0b3JJbXBsZW1lbnRhdGlvbiBhbmRcbiAgICogb3BlcmF0b3JJbml0aWFsaXphdGlvbiAob3B0aW9uYWwpXG4gICAqL1xuICB0eXBlIFJlc29sdmVSdWxlID0gW1xuICAgIHN0cmluZywgRG9tYWluLCBzdHJpbmcsIE9wZXJhdG9ySW1wbGVtZW50YXRpb248R3JhcGguTm9kZT5cbiAgXXxbc3RyaW5nLCBEb21haW4sIHN0cmluZywgT3BlcmF0b3JJbXBsZW1lbnRhdGlvbjx1bmtub3duPiwgT3BlcmF0b3JJbml0aWFsaXphdGlvbjx1bmtub3duPl07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlT3BlcmF0b3Iobm9kZTogR3JhcGguTm9kZSwgb3BzZXRzOiByZWFkb25seSBPcFNldFtdLCBydWxlczogcmVhZG9ubHkgT3BTZXQuUmVzb2x2ZVJ1bGVbXSkge1xuICBmb3IgKGNvbnN0IHJ1bGUgb2YgcnVsZXMpIHtcbiAgICBjb25zdCBvcFR5cGUgPSBydWxlWzBdO1xuICAgIGNvbnN0IGRvbWFpbiA9IHJ1bGVbMV07XG4gICAgY29uc3QgdmVyc2lvblNlbGVjdG9yID0gcnVsZVsyXTtcbiAgICBjb25zdCBvcEltcGwgPSBydWxlWzNdO1xuICAgIGNvbnN0IG9wSW5pdCA9IHJ1bGVbNF07XG5cbiAgICBpZiAobm9kZS5vcFR5cGUgPT09IG9wVHlwZSkgeyAgLy8gb3BlcmF0b3IgdHlwZSBtYXRjaGVzXG4gICAgICBmb3IgKGNvbnN0IG9wc2V0IG9mIG9wc2V0cykge1xuICAgICAgICAvLyBvcHNldCAnJyBhbmQgJ2FpLm9ubngnIGFyZSBjb25zaWRlcmVkIHRoZSBzYW1lLlxuICAgICAgICBpZiAob3BzZXQuZG9tYWluID09PSBkb21haW4gfHwgKG9wc2V0LmRvbWFpbiA9PT0gJ2FpLm9ubngnICYmIGRvbWFpbiA9PT0gJycpKSB7ICAvLyBvcHNldCBkb21haW4gZm91bmRcbiAgICAgICAgICBpZiAobWF0Y2hTZWxlY3RvcihvcHNldC52ZXJzaW9uLCB2ZXJzaW9uU2VsZWN0b3IpKSB7XG4gICAgICAgICAgICByZXR1cm4ge29wSW1wbCwgb3BJbml0fTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZUVycm9yKGBjYW5ub3QgcmVzb2x2ZSBvcGVyYXRvciAnJHtub2RlLm9wVHlwZX0nIHdpdGggb3BzZXRzOiAke1xuICAgICAgb3BzZXRzLm1hcChzZXQgPT4gYCR7c2V0LmRvbWFpbiB8fCAnYWkub25ueCd9IHYke3NldC52ZXJzaW9ufWApLmpvaW4oJywgJyl9YCk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoU2VsZWN0b3IodmVyc2lvbjogbnVtYmVyLCBzZWxlY3Rvcjogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGlmIChzZWxlY3Rvci5lbmRzV2l0aCgnKycpKSB7XG4gICAgLy8gbWluaW11bSB2ZXJzaW9uIG1hdGNoICgnNysnIGV4cGVjdHMgdmVyc2lvbj49NylcbiAgICBjb25zdCByYW5nZVN0YXJ0ID0gTnVtYmVyLnBhcnNlSW50KHNlbGVjdG9yLnN1YnN0cmluZygwLCBzZWxlY3Rvci5sZW5ndGggLSAxKSwgMTApO1xuICAgIHJldHVybiAhaXNOYU4ocmFuZ2VTdGFydCkgJiYgcmFuZ2VTdGFydCA8PSB2ZXJzaW9uO1xuICB9IGVsc2UgaWYgKHNlbGVjdG9yLnNwbGl0KCctJykubGVuZ3RoID09PSAyKSB7XG4gICAgLy8gcmFuZ2UgbWF0Y2ggKCc2LTgnIGV4cGVjdHMgNjw9dmVyc2lvbjw9OClcbiAgICBjb25zdCBwYWlyID0gc2VsZWN0b3Iuc3BsaXQoJy0nKTtcbiAgICBjb25zdCByYW5nZVN0YXJ0ID0gTnVtYmVyLnBhcnNlSW50KHBhaXJbMF0sIDEwKTtcbiAgICBjb25zdCByYW5nZUVuZCA9IE51bWJlci5wYXJzZUludChwYWlyWzFdLCAxMCk7XG4gICAgcmV0dXJuICFpc05hTihyYW5nZVN0YXJ0KSAmJiAhaXNOYU4ocmFuZ2VFbmQpICYmIHJhbmdlU3RhcnQgPD0gdmVyc2lvbiAmJiB2ZXJzaW9uIDw9IHJhbmdlRW5kO1xuICB9IGVsc2Uge1xuICAgIC8vIGV4YWN0IG1hdGNoICgnNycgZXhwZWN0cyB2ZXJzaW9uPT09NylcbiAgICByZXR1cm4gTnVtYmVyLnBhcnNlSW50KHNlbGVjdG9yLCAxMCkgPT09IHZlcnNpb247XG4gIH1cbn1cbiIsIi8vIGF1dG9tYXRpY2FsbHkgZ2VuZXJhdGVkIGJ5IHRoZSBGbGF0QnVmZmVycyBjb21waWxlciwgZG8gbm90IG1vZGlmeVxuLyogZXNsaW50LWRpc2FibGUgKi9cblxuaW1wb3J0IHtmbGF0YnVmZmVyc30gZnJvbSAnZmxhdGJ1ZmZlcnMnO1xuXG4vKipcbiAqIEBlbnVtIHtudW1iZXJ9XG4gKi9cbmV4cG9ydCBuYW1lc3BhY2Ugb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicyB7XG4gIGV4cG9ydCBlbnVtIEF0dHJpYnV0ZVR5cGUge1xuICAgIFVOREVGSU5FRCA9IDAsXG4gICAgRkxPQVQgPSAxLFxuICAgIElOVCA9IDIsXG4gICAgU1RSSU5HID0gMyxcbiAgICBURU5TT1IgPSA0LFxuICAgIEdSQVBIID0gNSxcbiAgICBGTE9BVFMgPSA2LFxuICAgIElOVFMgPSA3LFxuICAgIFNUUklOR1MgPSA4LFxuICAgIFRFTlNPUlMgPSA5LFxuICAgIEdSQVBIUyA9IDEwLFxuICAgIFNQQVJTRV9URU5TT1IgPSAxMSxcbiAgICBTUEFSU0VfVEVOU09SUyA9IDEyXG4gIH1cbn1cblxuLyoqXG4gKiBAZW51bSB7bnVtYmVyfVxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgZW51bSBEaW1lbnNpb25WYWx1ZVR5cGUge1VOS05PV04gPSAwLCBWQUxVRSA9IDEsIFBBUkFNID0gMn1cbn1cblxuLyoqXG4gKiBAZW51bSB7bnVtYmVyfVxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgZW51bSBUZW5zb3JEYXRhVHlwZSB7XG4gICAgVU5ERUZJTkVEID0gMCxcbiAgICBGTE9BVCA9IDEsXG4gICAgVUlOVDggPSAyLFxuICAgIElOVDggPSAzLFxuICAgIFVJTlQxNiA9IDQsXG4gICAgSU5UMTYgPSA1LFxuICAgIElOVDMyID0gNixcbiAgICBJTlQ2NCA9IDcsXG4gICAgU1RSSU5HID0gOCxcbiAgICBCT09MID0gOSxcbiAgICBGTE9BVDE2ID0gMTAsXG4gICAgRE9VQkxFID0gMTEsXG4gICAgVUlOVDMyID0gMTIsXG4gICAgVUlOVDY0ID0gMTMsXG4gICAgQ09NUExFWDY0ID0gMTQsXG4gICAgQ09NUExFWDEyOCA9IDE1LFxuICAgIEJGTE9BVDE2ID0gMTZcbiAgfVxufVxuXG4vKipcbiAqIEBlbnVtIHtudW1iZXJ9XG4gKi9cbmV4cG9ydCBuYW1lc3BhY2Ugb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicyB7XG4gIGV4cG9ydCBlbnVtIE5vZGVUeXBlIHtQcmltaXRpdmUgPSAwLCBGdXNlZCA9IDF9XG59XG5cbi8qKlxuICogQGVudW0ge251bWJlcn1cbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGVudW0gVHlwZUluZm9WYWx1ZSB7Tk9ORSA9IDAsIHRlbnNvcl90eXBlID0gMSwgc2VxdWVuY2VfdHlwZSA9IDIsIG1hcF90eXBlID0gM31cbn1cblxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIFNoYXBlIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBTaGFwZVxuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogU2hhcGUge1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gU2hhcGU9IG9ialxuICAgICAqIEByZXR1cm5zIFNoYXBlXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc1NoYXBlKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBTaGFwZSk6IFNoYXBlIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBTaGFwZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIFNoYXBlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBTaGFwZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNTaGFwZShiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogU2hhcGUpOiBTaGFwZSB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBTaGFwZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5EaW1lbnNpb249IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRGltZW5zaW9uXG4gICAgICovXG4gICAgZGltKGluZGV4OiBudW1iZXIsIG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRGltZW5zaW9uKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5EaW1lbnNpb258bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRGltZW5zaW9uKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgZGltTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRTaGFwZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGRpbU9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGREaW0oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGltT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMCwgZGltT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIEFycmF5LjxmbGF0YnVmZmVycy5PZmZzZXQ+IGRhdGFcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlRGltVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLk9mZnNldFtdKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgZGF0YS5sZW5ndGgsIDQpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRPZmZzZXQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydERpbVZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGVuZFNoYXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVTaGFwZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkaW1PZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBTaGFwZS5zdGFydFNoYXBlKGJ1aWxkZXIpO1xuICAgICAgU2hhcGUuYWRkRGltKGJ1aWxkZXIsIGRpbU9mZnNldCk7XG4gICAgICByZXR1cm4gU2hhcGUuZW5kU2hhcGUoYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgRGltZW5zaW9uIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBEaW1lbnNpb25cbiAgICAgKi9cbiAgICBfX2luaXQoaTogbnVtYmVyLCBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcik6IERpbWVuc2lvbiB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBEaW1lbnNpb249IG9ialxuICAgICAqIEByZXR1cm5zIERpbWVuc2lvblxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRSb290QXNEaW1lbnNpb24oYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IERpbWVuc2lvbik6IERpbWVuc2lvbiB7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgRGltZW5zaW9uKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gRGltZW5zaW9uPSBvYmpcbiAgICAgKiBAcmV0dXJucyBEaW1lbnNpb25cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzRGltZW5zaW9uKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBEaW1lbnNpb24pOiBEaW1lbnNpb24ge1xuICAgICAgYmIuc2V0UG9zaXRpb24oYmIucG9zaXRpb24oKSArIGZsYXRidWZmZXJzLlNJWkVfUFJFRklYX0xFTkdUSCk7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgRGltZW5zaW9uKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRGltZW5zaW9uVmFsdWU9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRGltZW5zaW9uVmFsdWV8bnVsbFxuICAgICAqL1xuICAgIHZhbHVlKG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRGltZW5zaW9uVmFsdWUpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkRpbWVuc2lvblZhbHVlfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkRpbWVuc2lvblZhbHVlKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiX3BvcyArIG9mZnNldCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheXxudWxsXG4gICAgICovXG4gICAgZGVub3RhdGlvbigpOiBzdHJpbmd8bnVsbDtcbiAgICBkZW5vdGF0aW9uKG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbDtcbiAgICBkZW5vdGF0aW9uKG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYl9wb3MgKyBvZmZzZXQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0RGltZW5zaW9uKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRPYmplY3QoMik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgdmFsdWVPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkVmFsdWUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgdmFsdWVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgwLCB2YWx1ZU9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZGVub3RhdGlvbk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGREZW5vdGF0aW9uKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRlbm90YXRpb25PZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxLCBkZW5vdGF0aW9uT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGVuZERpbWVuc2lvbihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGxldCBvZmZzZXQgPSBidWlsZGVyLmVuZE9iamVjdCgpO1xuICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlRGltZW5zaW9uKFxuICAgICAgICBidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCB2YWx1ZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICBkZW5vdGF0aW9uT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgRGltZW5zaW9uLnN0YXJ0RGltZW5zaW9uKGJ1aWxkZXIpO1xuICAgICAgRGltZW5zaW9uLmFkZFZhbHVlKGJ1aWxkZXIsIHZhbHVlT2Zmc2V0KTtcbiAgICAgIERpbWVuc2lvbi5hZGREZW5vdGF0aW9uKGJ1aWxkZXIsIGRlbm90YXRpb25PZmZzZXQpO1xuICAgICAgcmV0dXJuIERpbWVuc2lvbi5lbmREaW1lbnNpb24oYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgRGltZW5zaW9uVmFsdWUge1xuICAgIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyfG51bGwgPSBudWxsO1xuXG4gICAgYmJfcG9zID0gMDtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGlcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEByZXR1cm5zIERpbWVuc2lvblZhbHVlXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBEaW1lbnNpb25WYWx1ZSB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBEaW1lbnNpb25WYWx1ZT0gb2JqXG4gICAgICogQHJldHVybnMgRGltZW5zaW9uVmFsdWVcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0Um9vdEFzRGltZW5zaW9uVmFsdWUoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IERpbWVuc2lvblZhbHVlKTogRGltZW5zaW9uVmFsdWUge1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IERpbWVuc2lvblZhbHVlKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gRGltZW5zaW9uVmFsdWU9IG9ialxuICAgICAqIEByZXR1cm5zIERpbWVuc2lvblZhbHVlXG4gICAgICovXG4gICAgc3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0RpbWVuc2lvblZhbHVlKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBEaW1lbnNpb25WYWx1ZSk6IERpbWVuc2lvblZhbHVlIHtcbiAgICAgIGJiLnNldFBvc2l0aW9uKGJiLnBvc2l0aW9uKCkgKyBmbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEgpO1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IERpbWVuc2lvblZhbHVlKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5EaW1lbnNpb25WYWx1ZVR5cGVcbiAgICAgKi9cbiAgICBkaW1UeXBlKCk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRGltZW5zaW9uVmFsdWVUeXBlIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gLyoqICAqLyAodGhpcy5iYiEucmVhZEludDgodGhpcy5iYl9wb3MgKyBvZmZzZXQpKSA6XG4gICAgICAgICAgICAgICAgICAgICAgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5EaW1lbnNpb25WYWx1ZVR5cGUuVU5LTk9XTjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5Mb25nXG4gICAgICovXG4gICAgZGltVmFsdWUoKTogZmxhdGJ1ZmZlcnMuTG9uZyB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLnJlYWRJbnQ2NCh0aGlzLmJiX3BvcyArIG9mZnNldCkgOiB0aGlzLmJiIS5jcmVhdGVMb25nKDAsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBkaW1QYXJhbSgpOiBzdHJpbmd8bnVsbDtcbiAgICBkaW1QYXJhbShvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgZGltUGFyYW0ob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnREaW1lbnNpb25WYWx1ZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5EaW1lbnNpb25WYWx1ZVR5cGUgZGltVHlwZVxuICAgICAqL1xuICAgIHN0YXRpYyBhZGREaW1UeXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRpbVR5cGU6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRGltZW5zaW9uVmFsdWVUeXBlKSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkSW50OCgwLCBkaW1UeXBlLCBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkRpbWVuc2lvblZhbHVlVHlwZS5VTktOT1dOKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkxvbmcgZGltVmFsdWVcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRGltVmFsdWUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGltVmFsdWU6IGZsYXRidWZmZXJzLkxvbmcpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRJbnQ2NCgxLCBkaW1WYWx1ZSwgYnVpbGRlci5jcmVhdGVMb25nKDAsIDApKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBkaW1QYXJhbU9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGREaW1QYXJhbShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkaW1QYXJhbU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDIsIGRpbVBhcmFtT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGVuZERpbWVuc2lvblZhbHVlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVEaW1lbnNpb25WYWx1ZShcbiAgICAgICAgYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGltVHlwZTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5EaW1lbnNpb25WYWx1ZVR5cGUsXG4gICAgICAgIGRpbVZhbHVlOiBmbGF0YnVmZmVycy5Mb25nLCBkaW1QYXJhbU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIERpbWVuc2lvblZhbHVlLnN0YXJ0RGltZW5zaW9uVmFsdWUoYnVpbGRlcik7XG4gICAgICBEaW1lbnNpb25WYWx1ZS5hZGREaW1UeXBlKGJ1aWxkZXIsIGRpbVR5cGUpO1xuICAgICAgRGltZW5zaW9uVmFsdWUuYWRkRGltVmFsdWUoYnVpbGRlciwgZGltVmFsdWUpO1xuICAgICAgRGltZW5zaW9uVmFsdWUuYWRkRGltUGFyYW0oYnVpbGRlciwgZGltUGFyYW1PZmZzZXQpO1xuICAgICAgcmV0dXJuIERpbWVuc2lvblZhbHVlLmVuZERpbWVuc2lvblZhbHVlKGJ1aWxkZXIpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIFRlbnNvclR5cGVBbmRTaGFwZSB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgVGVuc29yVHlwZUFuZFNoYXBlXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBUZW5zb3JUeXBlQW5kU2hhcGUge1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gVGVuc29yVHlwZUFuZFNoYXBlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBUZW5zb3JUeXBlQW5kU2hhcGVcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0Um9vdEFzVGVuc29yVHlwZUFuZFNoYXBlKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBUZW5zb3JUeXBlQW5kU2hhcGUpOiBUZW5zb3JUeXBlQW5kU2hhcGUge1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFRlbnNvclR5cGVBbmRTaGFwZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIFRlbnNvclR5cGVBbmRTaGFwZT0gb2JqXG4gICAgICogQHJldHVybnMgVGVuc29yVHlwZUFuZFNoYXBlXG4gICAgICovXG4gICAgc3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1RlbnNvclR5cGVBbmRTaGFwZShiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogVGVuc29yVHlwZUFuZFNoYXBlKTpcbiAgICAgICAgVGVuc29yVHlwZUFuZFNoYXBlIHtcbiAgICAgIGJiLnNldFBvc2l0aW9uKGJiLnBvc2l0aW9uKCkgKyBmbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEgpO1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFRlbnNvclR5cGVBbmRTaGFwZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGVcbiAgICAgKi9cbiAgICBlbGVtVHlwZSgpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvckRhdGFUeXBlIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gLyoqICAqLyAodGhpcy5iYiEucmVhZEludDMyKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSkgOlxuICAgICAgICAgICAgICAgICAgICAgIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGUuVU5ERUZJTkVEO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlNoYXBlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlNoYXBlfG51bGxcbiAgICAgKi9cbiAgICBzaGFwZShvYmo/OiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlNoYXBlKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TaGFwZXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TaGFwZSgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYl9wb3MgKyBvZmZzZXQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydFRlbnNvclR5cGVBbmRTaGFwZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZSBlbGVtVHlwZVxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRFbGVtVHlwZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBlbGVtVHlwZTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZSkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZEludDMyKDAsIGVsZW1UeXBlLCBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvckRhdGFUeXBlLlVOREVGSU5FRCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgc2hhcGVPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkU2hhcGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgc2hhcGVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxLCBzaGFwZU9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBlbmRUZW5zb3JUeXBlQW5kU2hhcGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcik6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gYnVpbGRlci5lbmRPYmplY3QoKTtcbiAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZVRlbnNvclR5cGVBbmRTaGFwZShcbiAgICAgICAgYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZWxlbVR5cGU6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGUsXG4gICAgICAgIHNoYXBlT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgVGVuc29yVHlwZUFuZFNoYXBlLnN0YXJ0VGVuc29yVHlwZUFuZFNoYXBlKGJ1aWxkZXIpO1xuICAgICAgVGVuc29yVHlwZUFuZFNoYXBlLmFkZEVsZW1UeXBlKGJ1aWxkZXIsIGVsZW1UeXBlKTtcbiAgICAgIFRlbnNvclR5cGVBbmRTaGFwZS5hZGRTaGFwZShidWlsZGVyLCBzaGFwZU9mZnNldCk7XG4gICAgICByZXR1cm4gVGVuc29yVHlwZUFuZFNoYXBlLmVuZFRlbnNvclR5cGVBbmRTaGFwZShidWlsZGVyKTtcbiAgICB9XG4gIH1cbn1cbi8qKlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBuYW1lc3BhY2Ugb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicyB7XG4gIGV4cG9ydCBjbGFzcyBNYXBUeXBlIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBNYXBUeXBlXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBNYXBUeXBlIHtcbiAgICAgIHRoaXMuYmJfcG9zID0gaTtcbiAgICAgIHRoaXMuYmIgPSBiYjtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIE1hcFR5cGU9IG9ialxuICAgICAqIEByZXR1cm5zIE1hcFR5cGVcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0Um9vdEFzTWFwVHlwZShiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogTWFwVHlwZSk6IE1hcFR5cGUge1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IE1hcFR5cGUoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBNYXBUeXBlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBNYXBUeXBlXG4gICAgICovXG4gICAgc3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc01hcFR5cGUoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IE1hcFR5cGUpOiBNYXBUeXBlIHtcbiAgICAgIGJiLnNldFBvc2l0aW9uKGJiLnBvc2l0aW9uKCkgKyBmbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEgpO1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IE1hcFR5cGUoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvckRhdGFUeXBlXG4gICAgICovXG4gICAga2V5VHlwZSgpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvckRhdGFUeXBlIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gLyoqICAqLyAodGhpcy5iYiEucmVhZEludDMyKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSkgOlxuICAgICAgICAgICAgICAgICAgICAgIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGUuVU5ERUZJTkVEO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvfG51bGxcbiAgICAgKi9cbiAgICB2YWx1ZVR5cGUob2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UeXBlSW5mbyk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm98bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm8oKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLl9faW5pdCh0aGlzLmJiIS5fX2luZGlyZWN0KHRoaXMuYmJfcG9zICsgb2Zmc2V0KSwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRNYXBUeXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRPYmplY3QoMik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvckRhdGFUeXBlIGtleVR5cGVcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkS2V5VHlwZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBrZXlUeXBlOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvckRhdGFUeXBlKSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkSW50MzIoMCwga2V5VHlwZSwgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZS5VTkRFRklORUQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IHZhbHVlVHlwZU9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRWYWx1ZVR5cGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgdmFsdWVUeXBlT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMSwgdmFsdWVUeXBlT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGVuZE1hcFR5cGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcik6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gYnVpbGRlci5lbmRPYmplY3QoKTtcbiAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZU1hcFR5cGUoXG4gICAgICAgIGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGtleVR5cGU6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGUsXG4gICAgICAgIHZhbHVlVHlwZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIE1hcFR5cGUuc3RhcnRNYXBUeXBlKGJ1aWxkZXIpO1xuICAgICAgTWFwVHlwZS5hZGRLZXlUeXBlKGJ1aWxkZXIsIGtleVR5cGUpO1xuICAgICAgTWFwVHlwZS5hZGRWYWx1ZVR5cGUoYnVpbGRlciwgdmFsdWVUeXBlT2Zmc2V0KTtcbiAgICAgIHJldHVybiBNYXBUeXBlLmVuZE1hcFR5cGUoYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgU2VxdWVuY2VUeXBlIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBTZXF1ZW5jZVR5cGVcbiAgICAgKi9cbiAgICBfX2luaXQoaTogbnVtYmVyLCBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcik6IFNlcXVlbmNlVHlwZSB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBTZXF1ZW5jZVR5cGU9IG9ialxuICAgICAqIEByZXR1cm5zIFNlcXVlbmNlVHlwZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRSb290QXNTZXF1ZW5jZVR5cGUoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IFNlcXVlbmNlVHlwZSk6IFNlcXVlbmNlVHlwZSB7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgU2VxdWVuY2VUeXBlKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gU2VxdWVuY2VUeXBlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBTZXF1ZW5jZVR5cGVcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzU2VxdWVuY2VUeXBlKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBTZXF1ZW5jZVR5cGUpOiBTZXF1ZW5jZVR5cGUge1xuICAgICAgYmIuc2V0UG9zaXRpb24oYmIucG9zaXRpb24oKSArIGZsYXRidWZmZXJzLlNJWkVfUFJFRklYX0xFTkdUSCk7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgU2VxdWVuY2VUeXBlKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm89IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm98bnVsbFxuICAgICAqL1xuICAgIGVsZW1UeXBlKG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm8pOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiX3BvcyArIG9mZnNldCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0U2VxdWVuY2VUeXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRPYmplY3QoMSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZWxlbVR5cGVPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRWxlbVR5cGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZWxlbVR5cGVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgwLCBlbGVtVHlwZU9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBlbmRTZXF1ZW5jZVR5cGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcik6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gYnVpbGRlci5lbmRPYmplY3QoKTtcbiAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZVNlcXVlbmNlVHlwZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBlbGVtVHlwZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIFNlcXVlbmNlVHlwZS5zdGFydFNlcXVlbmNlVHlwZShidWlsZGVyKTtcbiAgICAgIFNlcXVlbmNlVHlwZS5hZGRFbGVtVHlwZShidWlsZGVyLCBlbGVtVHlwZU9mZnNldCk7XG4gICAgICByZXR1cm4gU2VxdWVuY2VUeXBlLmVuZFNlcXVlbmNlVHlwZShidWlsZGVyKTtcbiAgICB9XG4gIH1cbn1cbi8qKlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBuYW1lc3BhY2Ugb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicyB7XG4gIGV4cG9ydCBjbGFzcyBFZGdlRW5kIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBFZGdlRW5kXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBFZGdlRW5kIHtcbiAgICAgIHRoaXMuYmJfcG9zID0gaTtcbiAgICAgIHRoaXMuYmIgPSBiYjtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIG5vZGVJbmRleCgpOiBudW1iZXIge1xuICAgICAgcmV0dXJuIHRoaXMuYmIhLnJlYWRVaW50MzIodGhpcy5iYl9wb3MpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIHNyY0FyZ0luZGV4KCk6IG51bWJlciB7XG4gICAgICByZXR1cm4gdGhpcy5iYiEucmVhZEludDMyKHRoaXMuYmJfcG9zICsgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgZHN0QXJnSW5kZXgoKTogbnVtYmVyIHtcbiAgICAgIHJldHVybiB0aGlzLmJiIS5yZWFkSW50MzIodGhpcy5iYl9wb3MgKyA4KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBub2RlX2luZGV4XG4gICAgICogQHBhcmFtIG51bWJlciBzcmNfYXJnX2luZGV4XG4gICAgICogQHBhcmFtIG51bWJlciBkc3RfYXJnX2luZGV4XG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZUVkZ2VFbmQoXG4gICAgICAgIGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG5vZGVfaW5kZXg6IG51bWJlciwgc3JjX2FyZ19pbmRleDogbnVtYmVyLFxuICAgICAgICBkc3RfYXJnX2luZGV4OiBudW1iZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5wcmVwKDQsIDEyKTtcbiAgICAgIGJ1aWxkZXIud3JpdGVJbnQzMihkc3RfYXJnX2luZGV4KTtcbiAgICAgIGJ1aWxkZXIud3JpdGVJbnQzMihzcmNfYXJnX2luZGV4KTtcbiAgICAgIGJ1aWxkZXIud3JpdGVJbnQzMihub2RlX2luZGV4KTtcbiAgICAgIHJldHVybiBidWlsZGVyLm9mZnNldCgpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIE5vZGVFZGdlIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBOb2RlRWRnZVxuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogTm9kZUVkZ2Uge1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gTm9kZUVkZ2U9IG9ialxuICAgICAqIEByZXR1cm5zIE5vZGVFZGdlXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc05vZGVFZGdlKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBOb2RlRWRnZSk6IE5vZGVFZGdlIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBOb2RlRWRnZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIE5vZGVFZGdlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBOb2RlRWRnZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNOb2RlRWRnZShiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogTm9kZUVkZ2UpOiBOb2RlRWRnZSB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBOb2RlRWRnZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIG5vZGVJbmRleCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkVWludDMyKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkVkZ2VFbmQ9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRWRnZUVuZFxuICAgICAqL1xuICAgIGlucHV0RWRnZXMoaW5kZXg6IG51bWJlciwgb2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5FZGdlRW5kKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5FZGdlRW5kfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkVkZ2VFbmQoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLl9faW5pdCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDEyLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgaW5wdXRFZGdlc0xlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuRWRnZUVuZD0gb2JqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5FZGdlRW5kXG4gICAgICovXG4gICAgb3V0cHV0RWRnZXMoaW5kZXg6IG51bWJlciwgb2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5FZGdlRW5kKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5FZGdlRW5kfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkVkZ2VFbmQoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLl9faW5pdCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDEyLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgb3V0cHV0RWRnZXNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydE5vZGVFZGdlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRPYmplY3QoMyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbm9kZUluZGV4XG4gICAgICovXG4gICAgc3RhdGljIGFkZE5vZGVJbmRleChidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBub2RlSW5kZXg6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZEludDMyKDAsIG5vZGVJbmRleCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgaW5wdXRFZGdlc09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRJbnB1dEVkZ2VzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGlucHV0RWRnZXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxLCBpbnB1dEVkZ2VzT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydElucHV0RWRnZXNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3RvcigxMiwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IG91dHB1dEVkZ2VzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZE91dHB1dEVkZ2VzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG91dHB1dEVkZ2VzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMiwgb3V0cHV0RWRnZXNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0T3V0cHV0RWRnZXNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3RvcigxMiwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgZW5kTm9kZUVkZ2UoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcik6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gYnVpbGRlci5lbmRPYmplY3QoKTtcbiAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZU5vZGVFZGdlKFxuICAgICAgICBidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBub2RlSW5kZXg6IG51bWJlciwgaW5wdXRFZGdlc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICBvdXRwdXRFZGdlc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIE5vZGVFZGdlLnN0YXJ0Tm9kZUVkZ2UoYnVpbGRlcik7XG4gICAgICBOb2RlRWRnZS5hZGROb2RlSW5kZXgoYnVpbGRlciwgbm9kZUluZGV4KTtcbiAgICAgIE5vZGVFZGdlLmFkZElucHV0RWRnZXMoYnVpbGRlciwgaW5wdXRFZGdlc09mZnNldCk7XG4gICAgICBOb2RlRWRnZS5hZGRPdXRwdXRFZGdlcyhidWlsZGVyLCBvdXRwdXRFZGdlc09mZnNldCk7XG4gICAgICByZXR1cm4gTm9kZUVkZ2UuZW5kTm9kZUVkZ2UoYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgTm9kZSB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgTm9kZVxuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogTm9kZSB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBOb2RlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBOb2RlXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc05vZGUoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IE5vZGUpOiBOb2RlIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBOb2RlKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gTm9kZT0gb2JqXG4gICAgICogQHJldHVybnMgTm9kZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNOb2RlKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBOb2RlKTogTm9kZSB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBOb2RlKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIG5hbWUoKTogc3RyaW5nfG51bGw7XG4gICAgbmFtZShvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgbmFtZShvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIGRvY1N0cmluZygpOiBzdHJpbmd8bnVsbDtcbiAgICBkb2NTdHJpbmcob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIGRvY1N0cmluZyhvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIGRvbWFpbigpOiBzdHJpbmd8bnVsbDtcbiAgICBkb21haW4ob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIGRvbWFpbihvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDgpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgc2luY2VWZXJzaW9uKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDEwKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkSW50MzIodGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBpbmRleCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxMik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEucmVhZFVpbnQzMih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBvcFR5cGUoKTogc3RyaW5nfG51bGw7XG4gICAgb3BUeXBlKG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbDtcbiAgICBvcFR5cGUob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYl9wb3MgKyBvZmZzZXQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk5vZGVUeXBlXG4gICAgICovXG4gICAgdHlwZSgpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk5vZGVUeXBlIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IC8qKiAgKi8gKHRoaXMuYmIhLnJlYWRJbnQzMih0aGlzLmJiX3BvcyArIG9mZnNldCkpIDpcbiAgICAgICAgICAgICAgICAgICAgICBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk5vZGVUeXBlLlByaW1pdGl2ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheXxudWxsXG4gICAgICovXG4gICAgZXhlY3V0aW9uUHJvdmlkZXJUeXBlKCk6IHN0cmluZ3xudWxsO1xuICAgIGV4ZWN1dGlvblByb3ZpZGVyVHlwZShvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgZXhlY3V0aW9uUHJvdmlkZXJUeXBlKG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTgpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5XG4gICAgICovXG4gICAgaW5wdXRzKGluZGV4OiBudW1iZXIpOiBzdHJpbmc7XG4gICAgaW5wdXRzKGluZGV4OiBudW1iZXIsIG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXk7XG4gICAgaW5wdXRzKGluZGV4OiBudW1iZXIsIG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjApO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogNCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGlucHV0c0xlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAyMCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5XG4gICAgICovXG4gICAgb3V0cHV0cyhpbmRleDogbnVtYmVyKTogc3RyaW5nO1xuICAgIG91dHB1dHMoaW5kZXg6IG51bWJlciwgb3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheTtcbiAgICBvdXRwdXRzKGluZGV4OiBudW1iZXIsIG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjIpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogNCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIG91dHB1dHNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjIpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5BdHRyaWJ1dGU9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuQXR0cmlidXRlXG4gICAgICovXG4gICAgYXR0cmlidXRlcyhpbmRleDogbnVtYmVyLCBvYmo/OiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkF0dHJpYnV0ZSk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuQXR0cmlidXRlXG4gICAgICAgIHxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuQXR0cmlidXRlKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgYXR0cmlidXRlc0xlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAyNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGlucHV0QXJnQ291bnRzKGluZGV4OiBudW1iZXIpOiBudW1iZXJ8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDI2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkSW50MzIodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgaW5wdXRBcmdDb3VudHNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIEludDMyQXJyYXlcbiAgICAgKi9cbiAgICBpbnB1dEFyZ0NvdW50c0FycmF5KCk6IEludDMyQXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDI2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgP1xuICAgICAgICAgIG5ldyBJbnQzMkFycmF5KFxuICAgICAgICAgICAgICB0aGlzLmJiIS5ieXRlcygpLmJ1ZmZlciwgdGhpcy5iYiEuYnl0ZXMoKS5ieXRlT2Zmc2V0ICsgdGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpLFxuICAgICAgICAgICAgICB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpKSA6XG4gICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXlcbiAgICAgKi9cbiAgICBpbXBsaWNpdElucHV0cyhpbmRleDogbnVtYmVyKTogc3RyaW5nO1xuICAgIGltcGxpY2l0SW5wdXRzKGluZGV4OiBudW1iZXIsIG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXk7XG4gICAgaW1wbGljaXRJbnB1dHMoaW5kZXg6IG51bWJlciwgb3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAyOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgaW1wbGljaXRJbnB1dHNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjgpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnROb2RlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRPYmplY3QoMTMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IG5hbWVPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkTmFtZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBuYW1lT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMCwgbmFtZU9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZG9jU3RyaW5nT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZERvY1N0cmluZyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkb2NTdHJpbmdPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxLCBkb2NTdHJpbmdPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGRvbWFpbk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGREb21haW4oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZG9tYWluT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMiwgZG9tYWluT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBzaW5jZVZlcnNpb25cbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkU2luY2VWZXJzaW9uKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHNpbmNlVmVyc2lvbjogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkSW50MzIoMywgc2luY2VWZXJzaW9uLCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRJbmRleChidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBpbmRleDogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkSW50MzIoNCwgaW5kZXgsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IG9wVHlwZU9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRPcFR5cGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgb3BUeXBlT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoNSwgb3BUeXBlT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTm9kZVR5cGUgdHlwZVxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRUeXBlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHR5cGU6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTm9kZVR5cGUpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRJbnQzMig2LCB0eXBlLCBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk5vZGVUeXBlLlByaW1pdGl2ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZXhlY3V0aW9uUHJvdmlkZXJUeXBlT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZEV4ZWN1dGlvblByb3ZpZGVyVHlwZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBleGVjdXRpb25Qcm92aWRlclR5cGVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCg3LCBleGVjdXRpb25Qcm92aWRlclR5cGVPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGlucHV0c09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRJbnB1dHMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgaW5wdXRzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoOCwgaW5wdXRzT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIEFycmF5LjxmbGF0YnVmZmVycy5PZmZzZXQ+IGRhdGFcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlSW5wdXRzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLk9mZnNldFtdKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgZGF0YS5sZW5ndGgsIDQpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRPZmZzZXQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydElucHV0c1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBvdXRwdXRzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZE91dHB1dHMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgb3V0cHV0c09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDksIG91dHB1dHNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLk9mZnNldD4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVPdXRwdXRzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLk9mZnNldFtdKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgZGF0YS5sZW5ndGgsIDQpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRPZmZzZXQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydE91dHB1dHNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgYXR0cmlidXRlc09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRBdHRyaWJ1dGVzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGF0dHJpYnV0ZXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxMCwgYXR0cmlidXRlc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuT2Zmc2V0PiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZUF0dHJpYnV0ZXNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogZmxhdGJ1ZmZlcnMuT2Zmc2V0W10pOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZE9mZnNldChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0QXR0cmlidXRlc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBpbnB1dEFyZ0NvdW50c09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRJbnB1dEFyZ0NvdW50cyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBpbnB1dEFyZ0NvdW50c09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDExLCBpbnB1dEFyZ0NvdW50c09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48bnVtYmVyPiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZUlucHV0QXJnQ291bnRzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IG51bWJlcltdfFVpbnQ4QXJyYXkpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZEludDMyKGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRJbnB1dEFyZ0NvdW50c1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBpbXBsaWNpdElucHV0c09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRJbXBsaWNpdElucHV0cyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBpbXBsaWNpdElucHV0c09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDEyLCBpbXBsaWNpdElucHV0c09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuT2Zmc2V0PiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZUltcGxpY2l0SW5wdXRzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLk9mZnNldFtdKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgZGF0YS5sZW5ndGgsIDQpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRPZmZzZXQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydEltcGxpY2l0SW5wdXRzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgZW5kTm9kZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGxldCBvZmZzZXQgPSBidWlsZGVyLmVuZE9iamVjdCgpO1xuICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlTm9kZShcbiAgICAgICAgYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbmFtZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBkb2NTdHJpbmdPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgZG9tYWluT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsIHNpbmNlVmVyc2lvbjogbnVtYmVyLCBpbmRleDogbnVtYmVyLCBvcFR5cGVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgdHlwZTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Ob2RlVHlwZSwgZXhlY3V0aW9uUHJvdmlkZXJUeXBlT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIGlucHV0c09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBvdXRwdXRzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsIGF0dHJpYnV0ZXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgaW5wdXRBcmdDb3VudHNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgaW1wbGljaXRJbnB1dHNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBOb2RlLnN0YXJ0Tm9kZShidWlsZGVyKTtcbiAgICAgIE5vZGUuYWRkTmFtZShidWlsZGVyLCBuYW1lT2Zmc2V0KTtcbiAgICAgIE5vZGUuYWRkRG9jU3RyaW5nKGJ1aWxkZXIsIGRvY1N0cmluZ09mZnNldCk7XG4gICAgICBOb2RlLmFkZERvbWFpbihidWlsZGVyLCBkb21haW5PZmZzZXQpO1xuICAgICAgTm9kZS5hZGRTaW5jZVZlcnNpb24oYnVpbGRlciwgc2luY2VWZXJzaW9uKTtcbiAgICAgIE5vZGUuYWRkSW5kZXgoYnVpbGRlciwgaW5kZXgpO1xuICAgICAgTm9kZS5hZGRPcFR5cGUoYnVpbGRlciwgb3BUeXBlT2Zmc2V0KTtcbiAgICAgIE5vZGUuYWRkVHlwZShidWlsZGVyLCB0eXBlKTtcbiAgICAgIE5vZGUuYWRkRXhlY3V0aW9uUHJvdmlkZXJUeXBlKGJ1aWxkZXIsIGV4ZWN1dGlvblByb3ZpZGVyVHlwZU9mZnNldCk7XG4gICAgICBOb2RlLmFkZElucHV0cyhidWlsZGVyLCBpbnB1dHNPZmZzZXQpO1xuICAgICAgTm9kZS5hZGRPdXRwdXRzKGJ1aWxkZXIsIG91dHB1dHNPZmZzZXQpO1xuICAgICAgTm9kZS5hZGRBdHRyaWJ1dGVzKGJ1aWxkZXIsIGF0dHJpYnV0ZXNPZmZzZXQpO1xuICAgICAgTm9kZS5hZGRJbnB1dEFyZ0NvdW50cyhidWlsZGVyLCBpbnB1dEFyZ0NvdW50c09mZnNldCk7XG4gICAgICBOb2RlLmFkZEltcGxpY2l0SW5wdXRzKGJ1aWxkZXIsIGltcGxpY2l0SW5wdXRzT2Zmc2V0KTtcbiAgICAgIHJldHVybiBOb2RlLmVuZE5vZGUoYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgVmFsdWVJbmZvIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBWYWx1ZUluZm9cbiAgICAgKi9cbiAgICBfX2luaXQoaTogbnVtYmVyLCBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcik6IFZhbHVlSW5mbyB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBWYWx1ZUluZm89IG9ialxuICAgICAqIEByZXR1cm5zIFZhbHVlSW5mb1xuICAgICAqL1xuICAgIHN0YXRpYyBnZXRSb290QXNWYWx1ZUluZm8oYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IFZhbHVlSW5mbyk6IFZhbHVlSW5mbyB7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgVmFsdWVJbmZvKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gVmFsdWVJbmZvPSBvYmpcbiAgICAgKiBAcmV0dXJucyBWYWx1ZUluZm9cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzVmFsdWVJbmZvKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBWYWx1ZUluZm8pOiBWYWx1ZUluZm8ge1xuICAgICAgYmIuc2V0UG9zaXRpb24oYmIucG9zaXRpb24oKSArIGZsYXRidWZmZXJzLlNJWkVfUFJFRklYX0xFTkdUSCk7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgVmFsdWVJbmZvKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIG5hbWUoKTogc3RyaW5nfG51bGw7XG4gICAgbmFtZShvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgbmFtZShvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIGRvY1N0cmluZygpOiBzdHJpbmd8bnVsbDtcbiAgICBkb2NTdHJpbmcob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIGRvY1N0cmluZyhvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm89IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm98bnVsbFxuICAgICAqL1xuICAgIHR5cGUob2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UeXBlSW5mbyk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm98bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDgpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm8oKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLl9faW5pdCh0aGlzLmJiIS5fX2luZGlyZWN0KHRoaXMuYmJfcG9zICsgb2Zmc2V0KSwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRWYWx1ZUluZm8oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcikge1xuICAgICAgYnVpbGRlci5zdGFydE9iamVjdCgzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBuYW1lT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZE5hbWUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbmFtZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDAsIG5hbWVPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGRvY1N0cmluZ09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGREb2NTdHJpbmcoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZG9jU3RyaW5nT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMSwgZG9jU3RyaW5nT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCB0eXBlT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZFR5cGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgdHlwZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDIsIHR5cGVPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgZW5kVmFsdWVJbmZvKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVWYWx1ZUluZm8oXG4gICAgICAgIGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG5hbWVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgZG9jU3RyaW5nT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIHR5cGVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBWYWx1ZUluZm8uc3RhcnRWYWx1ZUluZm8oYnVpbGRlcik7XG4gICAgICBWYWx1ZUluZm8uYWRkTmFtZShidWlsZGVyLCBuYW1lT2Zmc2V0KTtcbiAgICAgIFZhbHVlSW5mby5hZGREb2NTdHJpbmcoYnVpbGRlciwgZG9jU3RyaW5nT2Zmc2V0KTtcbiAgICAgIFZhbHVlSW5mby5hZGRUeXBlKGJ1aWxkZXIsIHR5cGVPZmZzZXQpO1xuICAgICAgcmV0dXJuIFZhbHVlSW5mby5lbmRWYWx1ZUluZm8oYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgVHlwZUluZm8ge1xuICAgIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyfG51bGwgPSBudWxsO1xuXG4gICAgYmJfcG9zID0gMDtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGlcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEByZXR1cm5zIFR5cGVJbmZvXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBUeXBlSW5mbyB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBUeXBlSW5mbz0gb2JqXG4gICAgICogQHJldHVybnMgVHlwZUluZm9cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0Um9vdEFzVHlwZUluZm8oYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IFR5cGVJbmZvKTogVHlwZUluZm8ge1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFR5cGVJbmZvKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gVHlwZUluZm89IG9ialxuICAgICAqIEByZXR1cm5zIFR5cGVJbmZvXG4gICAgICovXG4gICAgc3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1R5cGVJbmZvKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBUeXBlSW5mbyk6IFR5cGVJbmZvIHtcbiAgICAgIGJiLnNldFBvc2l0aW9uKGJiLnBvc2l0aW9uKCkgKyBmbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEgpO1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFR5cGVJbmZvKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIGRlbm90YXRpb24oKTogc3RyaW5nfG51bGw7XG4gICAgZGVub3RhdGlvbihvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgZGVub3RhdGlvbihvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UeXBlSW5mb1ZhbHVlXG4gICAgICovXG4gICAgdmFsdWVUeXBlKCk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVHlwZUluZm9WYWx1ZSB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IC8qKiAgKi8gKHRoaXMuYmIhLnJlYWRVaW50OCh0aGlzLmJiX3BvcyArIG9mZnNldCkpIDpcbiAgICAgICAgICAgICAgICAgICAgICBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvVmFsdWUuTk9ORTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuVGFibGUgb2JqXG4gICAgICogQHJldHVybnMgP2ZsYXRidWZmZXJzLlRhYmxlXG4gICAgICovXG4gICAgdmFsdWU8VCBleHRlbmRzIGZsYXRidWZmZXJzLlRhYmxlPihvYmo6IFQpOiBUfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3VuaW9uKG9iaiwgdGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0VHlwZUluZm8oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcikge1xuICAgICAgYnVpbGRlci5zdGFydE9iamVjdCgzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBkZW5vdGF0aW9uT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZERlbm90YXRpb24oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGVub3RhdGlvbk9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDAsIGRlbm90YXRpb25PZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UeXBlSW5mb1ZhbHVlIHZhbHVlVHlwZVxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRWYWx1ZVR5cGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgdmFsdWVUeXBlOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlR5cGVJbmZvVmFsdWUpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRJbnQ4KDEsIHZhbHVlVHlwZSwgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UeXBlSW5mb1ZhbHVlLk5PTkUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IHZhbHVlT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZFZhbHVlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHZhbHVlT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMiwgdmFsdWVPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgZW5kVHlwZUluZm8oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcik6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gYnVpbGRlci5lbmRPYmplY3QoKTtcbiAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZVR5cGVJbmZvKFxuICAgICAgICBidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkZW5vdGF0aW9uT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIHZhbHVlVHlwZTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UeXBlSW5mb1ZhbHVlLCB2YWx1ZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIFR5cGVJbmZvLnN0YXJ0VHlwZUluZm8oYnVpbGRlcik7XG4gICAgICBUeXBlSW5mby5hZGREZW5vdGF0aW9uKGJ1aWxkZXIsIGRlbm90YXRpb25PZmZzZXQpO1xuICAgICAgVHlwZUluZm8uYWRkVmFsdWVUeXBlKGJ1aWxkZXIsIHZhbHVlVHlwZSk7XG4gICAgICBUeXBlSW5mby5hZGRWYWx1ZShidWlsZGVyLCB2YWx1ZU9mZnNldCk7XG4gICAgICByZXR1cm4gVHlwZUluZm8uZW5kVHlwZUluZm8oYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgT3BlcmF0b3JTZXRJZCB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgT3BlcmF0b3JTZXRJZFxuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogT3BlcmF0b3JTZXRJZCB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBPcGVyYXRvclNldElkPSBvYmpcbiAgICAgKiBAcmV0dXJucyBPcGVyYXRvclNldElkXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc09wZXJhdG9yU2V0SWQoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IE9wZXJhdG9yU2V0SWQpOiBPcGVyYXRvclNldElkIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBPcGVyYXRvclNldElkKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gT3BlcmF0b3JTZXRJZD0gb2JqXG4gICAgICogQHJldHVybnMgT3BlcmF0b3JTZXRJZFxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNPcGVyYXRvclNldElkKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBPcGVyYXRvclNldElkKTogT3BlcmF0b3JTZXRJZCB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBPcGVyYXRvclNldElkKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIGRvbWFpbigpOiBzdHJpbmd8bnVsbDtcbiAgICBkb21haW4ob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIGRvbWFpbihvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuTG9uZ1xuICAgICAqL1xuICAgIHZlcnNpb24oKTogZmxhdGJ1ZmZlcnMuTG9uZyB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLnJlYWRJbnQ2NCh0aGlzLmJiX3BvcyArIG9mZnNldCkgOiB0aGlzLmJiIS5jcmVhdGVMb25nKDAsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRPcGVyYXRvclNldElkKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRPYmplY3QoMik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZG9tYWluT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZERvbWFpbihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkb21haW5PZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgwLCBkb21haW5PZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuTG9uZyB2ZXJzaW9uXG4gICAgICovXG4gICAgc3RhdGljIGFkZFZlcnNpb24oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgdmVyc2lvbjogZmxhdGJ1ZmZlcnMuTG9uZykge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZEludDY0KDEsIHZlcnNpb24sIGJ1aWxkZXIuY3JlYXRlTG9uZygwLCAwKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBlbmRPcGVyYXRvclNldElkKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVPcGVyYXRvclNldElkKFxuICAgICAgICBidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkb21haW5PZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgdmVyc2lvbjogZmxhdGJ1ZmZlcnMuTG9uZyk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBPcGVyYXRvclNldElkLnN0YXJ0T3BlcmF0b3JTZXRJZChidWlsZGVyKTtcbiAgICAgIE9wZXJhdG9yU2V0SWQuYWRkRG9tYWluKGJ1aWxkZXIsIGRvbWFpbk9mZnNldCk7XG4gICAgICBPcGVyYXRvclNldElkLmFkZFZlcnNpb24oYnVpbGRlciwgdmVyc2lvbik7XG4gICAgICByZXR1cm4gT3BlcmF0b3JTZXRJZC5lbmRPcGVyYXRvclNldElkKGJ1aWxkZXIpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIFRlbnNvciB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgVGVuc29yXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBUZW5zb3Ige1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gVGVuc29yPSBvYmpcbiAgICAgKiBAcmV0dXJucyBUZW5zb3JcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0Um9vdEFzVGVuc29yKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBUZW5zb3IpOiBUZW5zb3Ige1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFRlbnNvcigpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIFRlbnNvcj0gb2JqXG4gICAgICogQHJldHVybnMgVGVuc29yXG4gICAgICovXG4gICAgc3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1RlbnNvcihiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogVGVuc29yKTogVGVuc29yIHtcbiAgICAgIGJiLnNldFBvc2l0aW9uKGJiLnBvc2l0aW9uKCkgKyBmbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEgpO1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFRlbnNvcigpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBuYW1lKCk6IHN0cmluZ3xudWxsO1xuICAgIG5hbWUob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIG5hbWUob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBkb2NTdHJpbmcoKTogc3RyaW5nfG51bGw7XG4gICAgZG9jU3RyaW5nKG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbDtcbiAgICBkb2NTdHJpbmcob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5Mb25nXG4gICAgICovXG4gICAgZGltcyhpbmRleDogbnVtYmVyKTogZmxhdGJ1ZmZlcnMuTG9uZ3xudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEucmVhZEludDY0KHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogOCkgOlxuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmIhLmNyZWF0ZUxvbmcoMCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgZGltc0xlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvckRhdGFUeXBlXG4gICAgICovXG4gICAgZGF0YVR5cGUoKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZSB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDEwKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAvKiogICovICh0aGlzLmJiIS5yZWFkSW50MzIodGhpcy5iYl9wb3MgKyBvZmZzZXQpKSA6XG4gICAgICAgICAgICAgICAgICAgICAgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZS5VTkRFRklORUQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIHJhd0RhdGEoaW5kZXg6IG51bWJlcik6IG51bWJlcnxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTIpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLnJlYWRVaW50OCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIHJhd0RhdGFMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTIpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIFVpbnQ4QXJyYXlcbiAgICAgKi9cbiAgICByYXdEYXRhQXJyYXkoKTogVWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTIpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/XG4gICAgICAgICAgbmV3IFVpbnQ4QXJyYXkoXG4gICAgICAgICAgICAgIHRoaXMuYmIhLmJ5dGVzKCkuYnVmZmVyLCB0aGlzLmJiIS5ieXRlcygpLmJ5dGVPZmZzZXQgKyB0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCksXG4gICAgICAgICAgICAgIHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkpIDpcbiAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheVxuICAgICAqL1xuICAgIHN0cmluZ0RhdGEoaW5kZXg6IG51bWJlcik6IHN0cmluZztcbiAgICBzdHJpbmdEYXRhKGluZGV4OiBudW1iZXIsIG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXk7XG4gICAgc3RyaW5nRGF0YShpbmRleDogbnVtYmVyLCBvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDE0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBzdHJpbmdEYXRhTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDE0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0VGVuc29yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRPYmplY3QoNik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgbmFtZU9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGROYW1lKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG5hbWVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgwLCBuYW1lT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBkb2NTdHJpbmdPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRG9jU3RyaW5nKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRvY1N0cmluZ09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDEsIGRvY1N0cmluZ09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZGltc09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGREaW1zKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRpbXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgyLCBkaW1zT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIEFycmF5LjxmbGF0YnVmZmVycy5Mb25nPiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZURpbXNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogZmxhdGJ1ZmZlcnMuTG9uZ1tdKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoOCwgZGF0YS5sZW5ndGgsIDgpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRJbnQ2NChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0RGltc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDgsIG51bUVsZW1zLCA4KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGUgZGF0YVR5cGVcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRGF0YVR5cGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YVR5cGU6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yRGF0YVR5cGUpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRJbnQzMigzLCBkYXRhVHlwZSwgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZS5VTkRFRklORUQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IHJhd0RhdGFPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkUmF3RGF0YShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCByYXdEYXRhT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoNCwgcmF3RGF0YU9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48bnVtYmVyPiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZVJhd0RhdGFWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogbnVtYmVyW118VWludDhBcnJheSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDEsIGRhdGEubGVuZ3RoLCAxKTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkSW50OChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0UmF3RGF0YVZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDEsIG51bUVsZW1zLCAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBzdHJpbmdEYXRhT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZFN0cmluZ0RhdGEoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgc3RyaW5nRGF0YU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDUsIHN0cmluZ0RhdGFPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLk9mZnNldD4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVTdHJpbmdEYXRhVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLk9mZnNldFtdKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgZGF0YS5sZW5ndGgsIDQpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRPZmZzZXQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydFN0cmluZ0RhdGFWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBlbmRUZW5zb3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcik6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gYnVpbGRlci5lbmRPYmplY3QoKTtcbiAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZVRlbnNvcihcbiAgICAgICAgYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbmFtZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBkb2NTdHJpbmdPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgZGltc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBkYXRhVHlwZTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZSxcbiAgICAgICAgcmF3RGF0YU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBzdHJpbmdEYXRhT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgVGVuc29yLnN0YXJ0VGVuc29yKGJ1aWxkZXIpO1xuICAgICAgVGVuc29yLmFkZE5hbWUoYnVpbGRlciwgbmFtZU9mZnNldCk7XG4gICAgICBUZW5zb3IuYWRkRG9jU3RyaW5nKGJ1aWxkZXIsIGRvY1N0cmluZ09mZnNldCk7XG4gICAgICBUZW5zb3IuYWRkRGltcyhidWlsZGVyLCBkaW1zT2Zmc2V0KTtcbiAgICAgIFRlbnNvci5hZGREYXRhVHlwZShidWlsZGVyLCBkYXRhVHlwZSk7XG4gICAgICBUZW5zb3IuYWRkUmF3RGF0YShidWlsZGVyLCByYXdEYXRhT2Zmc2V0KTtcbiAgICAgIFRlbnNvci5hZGRTdHJpbmdEYXRhKGJ1aWxkZXIsIHN0cmluZ0RhdGFPZmZzZXQpO1xuICAgICAgcmV0dXJuIFRlbnNvci5lbmRUZW5zb3IoYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgU3BhcnNlVGVuc29yIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBTcGFyc2VUZW5zb3JcbiAgICAgKi9cbiAgICBfX2luaXQoaTogbnVtYmVyLCBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcik6IFNwYXJzZVRlbnNvciB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBTcGFyc2VUZW5zb3I9IG9ialxuICAgICAqIEByZXR1cm5zIFNwYXJzZVRlbnNvclxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRSb290QXNTcGFyc2VUZW5zb3IoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IFNwYXJzZVRlbnNvcik6IFNwYXJzZVRlbnNvciB7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgU3BhcnNlVGVuc29yKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gU3BhcnNlVGVuc29yPSBvYmpcbiAgICAgKiBAcmV0dXJucyBTcGFyc2VUZW5zb3JcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzU3BhcnNlVGVuc29yKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBTcGFyc2VUZW5zb3IpOiBTcGFyc2VUZW5zb3Ige1xuICAgICAgYmIuc2V0UG9zaXRpb24oYmIucG9zaXRpb24oKSArIGZsYXRidWZmZXJzLlNJWkVfUFJFRklYX0xFTkdUSCk7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgU3BhcnNlVGVuc29yKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcnxudWxsXG4gICAgICovXG4gICAgdmFsdWVzKG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3J8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiX3BvcyArIG9mZnNldCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3I9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yfG51bGxcbiAgICAgKi9cbiAgICBpbmRpY2VzKG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3J8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiX3BvcyArIG9mZnNldCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuTG9uZ1xuICAgICAqL1xuICAgIGRpbXMoaW5kZXg6IG51bWJlcik6IGZsYXRidWZmZXJzLkxvbmd8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDgpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLnJlYWRJbnQ2NCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDgpIDpcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLmJiIS5jcmVhdGVMb25nKDAsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGRpbXNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydFNwYXJzZVRlbnNvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IHZhbHVlc09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRWYWx1ZXMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgdmFsdWVzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMCwgdmFsdWVzT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBpbmRpY2VzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZEluZGljZXMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgaW5kaWNlc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDEsIGluZGljZXNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGRpbXNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRGltcyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkaW1zT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMiwgZGltc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuTG9uZz4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVEaW1zVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLkxvbmdbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDgsIGRhdGEubGVuZ3RoLCA4KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkSW50NjQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydERpbXNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig4LCBudW1FbGVtcywgOCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBlbmRTcGFyc2VUZW5zb3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcik6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gYnVpbGRlci5lbmRPYmplY3QoKTtcbiAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZVNwYXJzZVRlbnNvcihcbiAgICAgICAgYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgdmFsdWVzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsIGluZGljZXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgZGltc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIFNwYXJzZVRlbnNvci5zdGFydFNwYXJzZVRlbnNvcihidWlsZGVyKTtcbiAgICAgIFNwYXJzZVRlbnNvci5hZGRWYWx1ZXMoYnVpbGRlciwgdmFsdWVzT2Zmc2V0KTtcbiAgICAgIFNwYXJzZVRlbnNvci5hZGRJbmRpY2VzKGJ1aWxkZXIsIGluZGljZXNPZmZzZXQpO1xuICAgICAgU3BhcnNlVGVuc29yLmFkZERpbXMoYnVpbGRlciwgZGltc09mZnNldCk7XG4gICAgICByZXR1cm4gU3BhcnNlVGVuc29yLmVuZFNwYXJzZVRlbnNvcihidWlsZGVyKTtcbiAgICB9XG4gIH1cbn1cbi8qKlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBuYW1lc3BhY2Ugb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicyB7XG4gIGV4cG9ydCBjbGFzcyBBdHRyaWJ1dGUge1xuICAgIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyfG51bGwgPSBudWxsO1xuXG4gICAgYmJfcG9zID0gMDtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGlcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEByZXR1cm5zIEF0dHJpYnV0ZVxuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogQXR0cmlidXRlIHtcbiAgICAgIHRoaXMuYmJfcG9zID0gaTtcbiAgICAgIHRoaXMuYmIgPSBiYjtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIEF0dHJpYnV0ZT0gb2JqXG4gICAgICogQHJldHVybnMgQXR0cmlidXRlXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc0F0dHJpYnV0ZShiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogQXR0cmlidXRlKTogQXR0cmlidXRlIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBBdHRyaWJ1dGUoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBBdHRyaWJ1dGU9IG9ialxuICAgICAqIEByZXR1cm5zIEF0dHJpYnV0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNBdHRyaWJ1dGUoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IEF0dHJpYnV0ZSk6IEF0dHJpYnV0ZSB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBBdHRyaWJ1dGUoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheXxudWxsXG4gICAgICovXG4gICAgbmFtZSgpOiBzdHJpbmd8bnVsbDtcbiAgICBuYW1lKG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbDtcbiAgICBuYW1lKG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYl9wb3MgKyBvZmZzZXQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheXxudWxsXG4gICAgICovXG4gICAgZG9jU3RyaW5nKCk6IHN0cmluZ3xudWxsO1xuICAgIGRvY1N0cmluZyhvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgZG9jU3RyaW5nKG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYl9wb3MgKyBvZmZzZXQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkF0dHJpYnV0ZVR5cGVcbiAgICAgKi9cbiAgICB0eXBlKCk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuQXR0cmlidXRlVHlwZSB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDgpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IC8qKiAgKi8gKHRoaXMuYmIhLnJlYWRJbnQzMih0aGlzLmJiX3BvcyArIG9mZnNldCkpIDpcbiAgICAgICAgICAgICAgICAgICAgICBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkF0dHJpYnV0ZVR5cGUuVU5ERUZJTkVEO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIGYoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTApO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLnJlYWRGbG9hdDMyKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDAuMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5Mb25nXG4gICAgICovXG4gICAgaSgpOiBmbGF0YnVmZmVycy5Mb25nIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTIpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLnJlYWRJbnQ2NCh0aGlzLmJiX3BvcyArIG9mZnNldCkgOiB0aGlzLmJiIS5jcmVhdGVMb25nKDAsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5fG51bGxcbiAgICAgKi9cbiAgICBzKCk6IHN0cmluZ3xudWxsO1xuICAgIHMob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIHMob3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYl9wb3MgKyBvZmZzZXQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3I9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yfG51bGxcbiAgICAgKi9cbiAgICB0KG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3J8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDE2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcigpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYl9wb3MgKyBvZmZzZXQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuR3JhcGg9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuR3JhcGh8bnVsbFxuICAgICAqL1xuICAgIGcob2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5HcmFwaCk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuR3JhcGh8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDE4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkdyYXBoKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiX3BvcyArIG9mZnNldCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgZmxvYXRzKGluZGV4OiBudW1iZXIpOiBudW1iZXJ8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDIwKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkRmxvYXQzMih0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBmbG9hdHNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjApO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIEZsb2F0MzJBcnJheVxuICAgICAqL1xuICAgIGZsb2F0c0FycmF5KCk6IEZsb2F0MzJBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjApO1xuICAgICAgcmV0dXJuIG9mZnNldCA/XG4gICAgICAgICAgbmV3IEZsb2F0MzJBcnJheShcbiAgICAgICAgICAgICAgdGhpcy5iYiEuYnl0ZXMoKS5idWZmZXIsIHRoaXMuYmIhLmJ5dGVzKCkuYnl0ZU9mZnNldCArIHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSxcbiAgICAgICAgICAgICAgdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSkgOlxuICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLkxvbmdcbiAgICAgKi9cbiAgICBpbnRzKGluZGV4OiBudW1iZXIpOiBmbGF0YnVmZmVycy5Mb25nfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAyMik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEucmVhZEludDY0KHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogOCkgOlxuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYmIhLmNyZWF0ZUxvbmcoMCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgaW50c0xlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAyMik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5FbmNvZGluZz0gb3B0aW9uYWxFbmNvZGluZ1xuICAgICAqIEByZXR1cm5zIHN0cmluZ3xVaW50OEFycmF5XG4gICAgICovXG4gICAgc3RyaW5ncyhpbmRleDogbnVtYmVyKTogc3RyaW5nO1xuICAgIHN0cmluZ3MoaW5kZXg6IG51bWJlciwgb3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheTtcbiAgICBzdHJpbmdzKGluZGV4OiBudW1iZXIsIG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogNCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIHN0cmluZ3NMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMjQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3I9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yXG4gICAgICovXG4gICAgdGVuc29ycyhpbmRleDogbnVtYmVyLCBvYmo/OiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcik6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAyNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3IoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLl9faW5pdCh0aGlzLmJiIS5fX2luZGlyZWN0KHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogNCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICB0ZW5zb3JzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDI2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuR3JhcGg9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuR3JhcGhcbiAgICAgKi9cbiAgICBncmFwaHMoaW5kZXg6IG51bWJlciwgb2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5HcmFwaCk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuR3JhcGh8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDI4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkdyYXBoKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgZ3JhcGhzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDI4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0QXR0cmlidXRlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRPYmplY3QoMTMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IG5hbWVPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkTmFtZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBuYW1lT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMCwgbmFtZU9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZG9jU3RyaW5nT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZERvY1N0cmluZyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkb2NTdHJpbmdPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxLCBkb2NTdHJpbmdPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5BdHRyaWJ1dGVUeXBlIHR5cGVcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkVHlwZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCB0eXBlOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkF0dHJpYnV0ZVR5cGUpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRJbnQzMigyLCB0eXBlLCBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkF0dHJpYnV0ZVR5cGUuVU5ERUZJTkVEKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBmXG4gICAgICovXG4gICAgc3RhdGljIGFkZEYoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZjogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkRmxvYXQzMigzLCBmLCAwLjApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuTG9uZyBpXG4gICAgICovXG4gICAgc3RhdGljIGFkZEkoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgaTogZmxhdGJ1ZmZlcnMuTG9uZykge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZEludDY0KDQsIGksIGJ1aWxkZXIuY3JlYXRlTG9uZygwLCAwKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgc09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRTKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCg1LCBzT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCB0T2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZFQoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgdE9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDYsIHRPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGdPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBnT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoNywgZ09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgZmxvYXRzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZEZsb2F0cyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBmbG9hdHNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCg4LCBmbG9hdHNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPG51bWJlcj4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVGbG9hdHNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogbnVtYmVyW118VWludDhBcnJheSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIGRhdGEubGVuZ3RoLCA0KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkRmxvYXQzMihkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0RmxvYXRzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGludHNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkSW50cyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBpbnRzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoOSwgaW50c09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuTG9uZz4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVJbnRzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLkxvbmdbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDgsIGRhdGEubGVuZ3RoLCA4KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkSW50NjQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydEludHNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig4LCBudW1FbGVtcywgOCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgc3RyaW5nc09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRTdHJpbmdzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHN0cmluZ3NPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxMCwgc3RyaW5nc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuT2Zmc2V0PiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZVN0cmluZ3NWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogZmxhdGJ1ZmZlcnMuT2Zmc2V0W10pOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZE9mZnNldChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0U3RyaW5nc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCB0ZW5zb3JzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZFRlbnNvcnMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgdGVuc29yc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDExLCB0ZW5zb3JzT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIEFycmF5LjxmbGF0YnVmZmVycy5PZmZzZXQ+IGRhdGFcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlVGVuc29yc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBmbGF0YnVmZmVycy5PZmZzZXRbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIGRhdGEubGVuZ3RoLCA0KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkT2Zmc2V0KGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRUZW5zb3JzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGdyYXBoc09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRHcmFwaHMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZ3JhcGhzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMTIsIGdyYXBoc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuT2Zmc2V0PiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZUdyYXBoc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBmbGF0YnVmZmVycy5PZmZzZXRbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIGRhdGEubGVuZ3RoLCA0KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkT2Zmc2V0KGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRHcmFwaHNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBlbmRBdHRyaWJ1dGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcik6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gYnVpbGRlci5lbmRPYmplY3QoKTtcbiAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZUF0dHJpYnV0ZShcbiAgICAgICAgYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbmFtZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBkb2NTdHJpbmdPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgdHlwZTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5BdHRyaWJ1dGVUeXBlLCBmOiBudW1iZXIsIGk6IGZsYXRidWZmZXJzLkxvbmcsIHNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgdE9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBnT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsIGZsb2F0c09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICBpbnRzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsIHN0cmluZ3NPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgdGVuc29yc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICBncmFwaHNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBBdHRyaWJ1dGUuc3RhcnRBdHRyaWJ1dGUoYnVpbGRlcik7XG4gICAgICBBdHRyaWJ1dGUuYWRkTmFtZShidWlsZGVyLCBuYW1lT2Zmc2V0KTtcbiAgICAgIEF0dHJpYnV0ZS5hZGREb2NTdHJpbmcoYnVpbGRlciwgZG9jU3RyaW5nT2Zmc2V0KTtcbiAgICAgIEF0dHJpYnV0ZS5hZGRUeXBlKGJ1aWxkZXIsIHR5cGUpO1xuICAgICAgQXR0cmlidXRlLmFkZEYoYnVpbGRlciwgZik7XG4gICAgICBBdHRyaWJ1dGUuYWRkSShidWlsZGVyLCBpKTtcbiAgICAgIEF0dHJpYnV0ZS5hZGRTKGJ1aWxkZXIsIHNPZmZzZXQpO1xuICAgICAgQXR0cmlidXRlLmFkZFQoYnVpbGRlciwgdE9mZnNldCk7XG4gICAgICBBdHRyaWJ1dGUuYWRkRyhidWlsZGVyLCBnT2Zmc2V0KTtcbiAgICAgIEF0dHJpYnV0ZS5hZGRGbG9hdHMoYnVpbGRlciwgZmxvYXRzT2Zmc2V0KTtcbiAgICAgIEF0dHJpYnV0ZS5hZGRJbnRzKGJ1aWxkZXIsIGludHNPZmZzZXQpO1xuICAgICAgQXR0cmlidXRlLmFkZFN0cmluZ3MoYnVpbGRlciwgc3RyaW5nc09mZnNldCk7XG4gICAgICBBdHRyaWJ1dGUuYWRkVGVuc29ycyhidWlsZGVyLCB0ZW5zb3JzT2Zmc2V0KTtcbiAgICAgIEF0dHJpYnV0ZS5hZGRHcmFwaHMoYnVpbGRlciwgZ3JhcGhzT2Zmc2V0KTtcbiAgICAgIHJldHVybiBBdHRyaWJ1dGUuZW5kQXR0cmlidXRlKGJ1aWxkZXIpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIEdyYXBoIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBHcmFwaFxuICAgICAqL1xuICAgIF9faW5pdChpOiBudW1iZXIsIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyKTogR3JhcGgge1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gR3JhcGg9IG9ialxuICAgICAqIEByZXR1cm5zIEdyYXBoXG4gICAgICovXG4gICAgc3RhdGljIGdldFJvb3RBc0dyYXBoKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBHcmFwaCk6IEdyYXBoIHtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBHcmFwaCgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIEdyYXBoPSBvYmpcbiAgICAgKiBAcmV0dXJucyBHcmFwaFxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRTaXplUHJlZml4ZWRSb290QXNHcmFwaChiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogR3JhcGgpOiBHcmFwaCB7XG4gICAgICBiYi5zZXRQb3NpdGlvbihiYi5wb3NpdGlvbigpICsgZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIKTtcbiAgICAgIHJldHVybiAob2JqIHx8IG5ldyBHcmFwaCgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3I9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZXJzKGluZGV4OiBudW1iZXIsIG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3J8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVGVuc29yKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgaW5pdGlhbGl6ZXJzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fdmVjdG9yX2xlbih0aGlzLmJiX3BvcyArIG9mZnNldCkgOiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaW5kZXhcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5WYWx1ZUluZm89IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuVmFsdWVJbmZvXG4gICAgICovXG4gICAgbm9kZUFyZ3MoaW5kZXg6IG51bWJlciwgb2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5WYWx1ZUluZm8pOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlZhbHVlSW5mb3xudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5WYWx1ZUluZm8oKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLl9faW5pdCh0aGlzLmJiIS5fX2luZGlyZWN0KHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogNCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBub2RlQXJnc0xlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTm9kZT0gb2JqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Ob2RlXG4gICAgICovXG4gICAgbm9kZXMoaW5kZXg6IG51bWJlciwgb2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Ob2RlKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Ob2RlfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk5vZGUoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLl9faW5pdCh0aGlzLmJiIS5fX2luZGlyZWN0KHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogNCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBub2Rlc0xlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBtYXhOb2RlSW5kZXgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTApO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLnJlYWRVaW50MzIodGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTm9kZUVkZ2U9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTm9kZUVkZ2VcbiAgICAgKi9cbiAgICBub2RlRWRnZXMoaW5kZXg6IG51bWJlciwgb2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Ob2RlRWRnZSk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTm9kZUVkZ2V8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDEyKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk5vZGVFZGdlKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgbm9kZUVkZ2VzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDEyKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXlcbiAgICAgKi9cbiAgICBpbnB1dHMoaW5kZXg6IG51bWJlcik6IHN0cmluZztcbiAgICBpbnB1dHMoaW5kZXg6IG51bWJlciwgb3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheTtcbiAgICBpbnB1dHMoaW5kZXg6IG51bWJlciwgb3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgaW5wdXRzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDE0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXlcbiAgICAgKi9cbiAgICBvdXRwdXRzKGluZGV4OiBudW1iZXIpOiBzdHJpbmc7XG4gICAgb3V0cHV0cyhpbmRleDogbnVtYmVyLCBvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5O1xuICAgIG91dHB1dHMoaW5kZXg6IG51bWJlciwgb3B0aW9uYWxFbmNvZGluZz86IGFueSk6IHN0cmluZ3xVaW50OEFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgb3V0cHV0c0xlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlNwYXJzZVRlbnNvcj0gb2JqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TcGFyc2VUZW5zb3JcbiAgICAgKi9cbiAgICBzcGFyc2VJbml0aWFsaXplcnMoaW5kZXg6IG51bWJlciwgb2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TcGFyc2VUZW5zb3IpOlxuICAgICAgICBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlNwYXJzZVRlbnNvcnxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTgpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU3BhcnNlVGVuc29yKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiIS5fX3ZlY3Rvcih0aGlzLmJiX3BvcyArIG9mZnNldCkgKyBpbmRleCAqIDQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgc3BhcnNlSW5pdGlhbGl6ZXJzTGVuZ3RoKCk6IG51bWJlciB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDE4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0R3JhcGgoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcikge1xuICAgICAgYnVpbGRlci5zdGFydE9iamVjdCg4KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBpbml0aWFsaXplcnNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkSW5pdGlhbGl6ZXJzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGluaXRpYWxpemVyc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDAsIGluaXRpYWxpemVyc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuT2Zmc2V0PiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZUluaXRpYWxpemVyc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBmbGF0YnVmZmVycy5PZmZzZXRbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIGRhdGEubGVuZ3RoLCA0KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkT2Zmc2V0KGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRJbml0aWFsaXplcnNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgbm9kZUFyZ3NPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkTm9kZUFyZ3MoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbm9kZUFyZ3NPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxLCBub2RlQXJnc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuT2Zmc2V0PiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZU5vZGVBcmdzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IGZsYXRidWZmZXJzLk9mZnNldFtdKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgZGF0YS5sZW5ndGgsIDQpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRPZmZzZXQoZGF0YVtpXSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYnVpbGRlci5lbmRWZWN0b3IoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBudW1FbGVtc1xuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydE5vZGVBcmdzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IG5vZGVzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZE5vZGVzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG5vZGVzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMiwgbm9kZXNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLk9mZnNldD4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVOb2Rlc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBmbGF0YnVmZmVycy5PZmZzZXRbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIGRhdGEubGVuZ3RoLCA0KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkT2Zmc2V0KGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnROb2Rlc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIG51bWJlciBtYXhOb2RlSW5kZXhcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkTWF4Tm9kZUluZGV4KGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG1heE5vZGVJbmRleDogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkSW50MzIoMywgbWF4Tm9kZUluZGV4LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBub2RlRWRnZXNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkTm9kZUVkZ2VzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG5vZGVFZGdlc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDQsIG5vZGVFZGdlc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuT2Zmc2V0PiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZU5vZGVFZGdlc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBmbGF0YnVmZmVycy5PZmZzZXRbXSk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIGRhdGEubGVuZ3RoLCA0KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkT2Zmc2V0KGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnROb2RlRWRnZXNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgaW5wdXRzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZElucHV0cyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBpbnB1dHNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCg1LCBpbnB1dHNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLk9mZnNldD4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVJbnB1dHNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogZmxhdGJ1ZmZlcnMuT2Zmc2V0W10pOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZE9mZnNldChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0SW5wdXRzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IG91dHB1dHNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkT3V0cHV0cyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBvdXRwdXRzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoNiwgb3V0cHV0c09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuT2Zmc2V0PiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZU91dHB1dHNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogZmxhdGJ1ZmZlcnMuT2Zmc2V0W10pOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZE9mZnNldChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0T3V0cHV0c1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBzcGFyc2VJbml0aWFsaXplcnNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkU3BhcnNlSW5pdGlhbGl6ZXJzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIHNwYXJzZUluaXRpYWxpemVyc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDcsIHNwYXJzZUluaXRpYWxpemVyc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuT2Zmc2V0PiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZVNwYXJzZUluaXRpYWxpemVyc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBkYXRhOiBmbGF0YnVmZmVycy5PZmZzZXRbXSk6XG4gICAgICAgIGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIGRhdGEubGVuZ3RoLCA0KTtcbiAgICAgIGZvciAobGV0IGkgPSBkYXRhLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkT2Zmc2V0KGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRTcGFyc2VJbml0aWFsaXplcnNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBlbmRHcmFwaChidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGxldCBvZmZzZXQgPSBidWlsZGVyLmVuZE9iamVjdCgpO1xuICAgICAgcmV0dXJuIG9mZnNldDtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlR3JhcGgoXG4gICAgICAgIGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGluaXRpYWxpemVyc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBub2RlQXJnc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICBub2Rlc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBtYXhOb2RlSW5kZXg6IG51bWJlciwgbm9kZUVkZ2VzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIGlucHV0c09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBvdXRwdXRzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIHNwYXJzZUluaXRpYWxpemVyc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIEdyYXBoLnN0YXJ0R3JhcGgoYnVpbGRlcik7XG4gICAgICBHcmFwaC5hZGRJbml0aWFsaXplcnMoYnVpbGRlciwgaW5pdGlhbGl6ZXJzT2Zmc2V0KTtcbiAgICAgIEdyYXBoLmFkZE5vZGVBcmdzKGJ1aWxkZXIsIG5vZGVBcmdzT2Zmc2V0KTtcbiAgICAgIEdyYXBoLmFkZE5vZGVzKGJ1aWxkZXIsIG5vZGVzT2Zmc2V0KTtcbiAgICAgIEdyYXBoLmFkZE1heE5vZGVJbmRleChidWlsZGVyLCBtYXhOb2RlSW5kZXgpO1xuICAgICAgR3JhcGguYWRkTm9kZUVkZ2VzKGJ1aWxkZXIsIG5vZGVFZGdlc09mZnNldCk7XG4gICAgICBHcmFwaC5hZGRJbnB1dHMoYnVpbGRlciwgaW5wdXRzT2Zmc2V0KTtcbiAgICAgIEdyYXBoLmFkZE91dHB1dHMoYnVpbGRlciwgb3V0cHV0c09mZnNldCk7XG4gICAgICBHcmFwaC5hZGRTcGFyc2VJbml0aWFsaXplcnMoYnVpbGRlciwgc3BhcnNlSW5pdGlhbGl6ZXJzT2Zmc2V0KTtcbiAgICAgIHJldHVybiBHcmFwaC5lbmRHcmFwaChidWlsZGVyKTtcbiAgICB9XG4gIH1cbn1cbi8qKlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBuYW1lc3BhY2Ugb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicyB7XG4gIGV4cG9ydCBjbGFzcyBNb2RlbCB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgTW9kZWxcbiAgICAgKi9cbiAgICBfX2luaXQoaTogbnVtYmVyLCBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcik6IE1vZGVsIHtcbiAgICAgIHRoaXMuYmJfcG9zID0gaTtcbiAgICAgIHRoaXMuYmIgPSBiYjtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIE1vZGVsPSBvYmpcbiAgICAgKiBAcmV0dXJucyBNb2RlbFxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRSb290QXNNb2RlbChiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogTW9kZWwpOiBNb2RlbCB7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgTW9kZWwoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBNb2RlbD0gb2JqXG4gICAgICogQHJldHVybnMgTW9kZWxcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0U2l6ZVByZWZpeGVkUm9vdEFzTW9kZWwoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IE1vZGVsKTogTW9kZWwge1xuICAgICAgYmIuc2V0UG9zaXRpb24oYmIucG9zaXRpb24oKSArIGZsYXRidWZmZXJzLlNJWkVfUFJFRklYX0xFTkdUSCk7XG4gICAgICByZXR1cm4gKG9iaiB8fCBuZXcgTW9kZWwoKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5Mb25nXG4gICAgICovXG4gICAgaXJWZXJzaW9uKCk6IGZsYXRidWZmZXJzLkxvbmcge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkSW50NjQodGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogdGhpcy5iYiEuY3JlYXRlTG9uZygwLCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuT3BlcmF0b3JTZXRJZD0gb2JqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5PcGVyYXRvclNldElkXG4gICAgICovXG4gICAgb3BzZXRJbXBvcnQoaW5kZXg6IG51bWJlciwgb2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5PcGVyYXRvclNldElkKTpcbiAgICAgICAgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5PcGVyYXRvclNldElkfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLk9wZXJhdG9yU2V0SWQoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLl9faW5pdCh0aGlzLmJiIS5fX2luZGlyZWN0KHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogNCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBvcHNldEltcG9ydExlbmd0aCgpOiBudW1iZXIge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA2KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3ZlY3Rvcl9sZW4odGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheXxudWxsXG4gICAgICovXG4gICAgcHJvZHVjZXJOYW1lKCk6IHN0cmluZ3xudWxsO1xuICAgIHByb2R1Y2VyTmFtZShvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgcHJvZHVjZXJOYW1lKG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYl9wb3MgKyBvZmZzZXQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheXxudWxsXG4gICAgICovXG4gICAgcHJvZHVjZXJWZXJzaW9uKCk6IHN0cmluZ3xudWxsO1xuICAgIHByb2R1Y2VyVmVyc2lvbihvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgcHJvZHVjZXJWZXJzaW9uKG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTApO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIGRvbWFpbigpOiBzdHJpbmd8bnVsbDtcbiAgICBkb21haW4ob3B0aW9uYWxFbmNvZGluZzogZmxhdGJ1ZmZlcnMuRW5jb2RpbmcpOiBzdHJpbmd8VWludDhBcnJheXxudWxsO1xuICAgIGRvbWFpbihvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDEyKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLkxvbmdcbiAgICAgKi9cbiAgICBtb2RlbFZlcnNpb24oKTogZmxhdGJ1ZmZlcnMuTG9uZyB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDE0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5yZWFkSW50NjQodGhpcy5iYl9wb3MgKyBvZmZzZXQpIDogdGhpcy5iYiEuY3JlYXRlTG9uZygwLCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheXxudWxsXG4gICAgICovXG4gICAgZG9jU3RyaW5nKCk6IHN0cmluZ3xudWxsO1xuICAgIGRvY1N0cmluZyhvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgZG9jU3RyaW5nKG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgMTYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuR3JhcGg9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuR3JhcGh8bnVsbFxuICAgICAqL1xuICAgIGdyYXBoKG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuR3JhcGgpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLkdyYXBofG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCAxOCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gKG9iaiB8fCBuZXcgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5HcmFwaCgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYl9wb3MgKyBvZmZzZXQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIGdyYXBoRG9jU3RyaW5nKCk6IHN0cmluZ3xudWxsO1xuICAgIGdyYXBoRG9jU3RyaW5nKG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbDtcbiAgICBncmFwaERvY1N0cmluZyhvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDIwKTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyB0aGlzLmJiIS5fX3N0cmluZyh0aGlzLmJiX3BvcyArIG9mZnNldCwgb3B0aW9uYWxFbmNvZGluZykgOiBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnRNb2RlbChidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuTG9uZyBpclZlcnNpb25cbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkSXJWZXJzaW9uKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGlyVmVyc2lvbjogZmxhdGJ1ZmZlcnMuTG9uZykge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZEludDY0KDAsIGlyVmVyc2lvbiwgYnVpbGRlci5jcmVhdGVMb25nKDAsIDApKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBvcHNldEltcG9ydE9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRPcHNldEltcG9ydChidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBvcHNldEltcG9ydE9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDEsIG9wc2V0SW1wb3J0T2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIEFycmF5LjxmbGF0YnVmZmVycy5PZmZzZXQ+IGRhdGFcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgY3JlYXRlT3BzZXRJbXBvcnRWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogZmxhdGJ1ZmZlcnMuT2Zmc2V0W10pOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZE9mZnNldChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0T3BzZXRJbXBvcnRWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbnVtRWxlbXM6IG51bWJlcikge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBudW1FbGVtcywgNCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgcHJvZHVjZXJOYW1lT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZFByb2R1Y2VyTmFtZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBwcm9kdWNlck5hbWVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgyLCBwcm9kdWNlck5hbWVPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IHByb2R1Y2VyVmVyc2lvbk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRQcm9kdWNlclZlcnNpb24oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgcHJvZHVjZXJWZXJzaW9uT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMywgcHJvZHVjZXJWZXJzaW9uT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBkb21haW5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkRG9tYWluKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRvbWFpbk9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDQsIGRvbWFpbk9mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5Mb25nIG1vZGVsVmVyc2lvblxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRNb2RlbFZlcnNpb24oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbW9kZWxWZXJzaW9uOiBmbGF0YnVmZmVycy5Mb25nKSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkSW50NjQoNSwgbW9kZWxWZXJzaW9uLCBidWlsZGVyLmNyZWF0ZUxvbmcoMCwgMCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGRvY1N0cmluZ09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGREb2NTdHJpbmcoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZG9jU3RyaW5nT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoNiwgZG9jU3RyaW5nT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBncmFwaE9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRHcmFwaChidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBncmFwaE9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDcsIGdyYXBoT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBncmFwaERvY1N0cmluZ09mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRHcmFwaERvY1N0cmluZyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBncmFwaERvY1N0cmluZ09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDgsIGdyYXBoRG9jU3RyaW5nT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGVuZE1vZGVsKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVNb2RlbChcbiAgICAgICAgYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgaXJWZXJzaW9uOiBmbGF0YnVmZmVycy5Mb25nLCBvcHNldEltcG9ydE9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICBwcm9kdWNlck5hbWVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCwgcHJvZHVjZXJWZXJzaW9uT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIGRvbWFpbk9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBtb2RlbFZlcnNpb246IGZsYXRidWZmZXJzLkxvbmcsIGRvY1N0cmluZ09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICBncmFwaE9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LCBncmFwaERvY1N0cmluZ09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIE1vZGVsLnN0YXJ0TW9kZWwoYnVpbGRlcik7XG4gICAgICBNb2RlbC5hZGRJclZlcnNpb24oYnVpbGRlciwgaXJWZXJzaW9uKTtcbiAgICAgIE1vZGVsLmFkZE9wc2V0SW1wb3J0KGJ1aWxkZXIsIG9wc2V0SW1wb3J0T2Zmc2V0KTtcbiAgICAgIE1vZGVsLmFkZFByb2R1Y2VyTmFtZShidWlsZGVyLCBwcm9kdWNlck5hbWVPZmZzZXQpO1xuICAgICAgTW9kZWwuYWRkUHJvZHVjZXJWZXJzaW9uKGJ1aWxkZXIsIHByb2R1Y2VyVmVyc2lvbk9mZnNldCk7XG4gICAgICBNb2RlbC5hZGREb21haW4oYnVpbGRlciwgZG9tYWluT2Zmc2V0KTtcbiAgICAgIE1vZGVsLmFkZE1vZGVsVmVyc2lvbihidWlsZGVyLCBtb2RlbFZlcnNpb24pO1xuICAgICAgTW9kZWwuYWRkRG9jU3RyaW5nKGJ1aWxkZXIsIGRvY1N0cmluZ09mZnNldCk7XG4gICAgICBNb2RlbC5hZGRHcmFwaChidWlsZGVyLCBncmFwaE9mZnNldCk7XG4gICAgICBNb2RlbC5hZGRHcmFwaERvY1N0cmluZyhidWlsZGVyLCBncmFwaERvY1N0cmluZ09mZnNldCk7XG4gICAgICByZXR1cm4gTW9kZWwuZW5kTW9kZWwoYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgS2VybmVsQ3JlYXRlSW5mb3Mge1xuICAgIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyfG51bGwgPSBudWxsO1xuXG4gICAgYmJfcG9zID0gMDtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGlcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEByZXR1cm5zIEtlcm5lbENyZWF0ZUluZm9zXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBLZXJuZWxDcmVhdGVJbmZvcyB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBLZXJuZWxDcmVhdGVJbmZvcz0gb2JqXG4gICAgICogQHJldHVybnMgS2VybmVsQ3JlYXRlSW5mb3NcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0Um9vdEFzS2VybmVsQ3JlYXRlSW5mb3MoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IEtlcm5lbENyZWF0ZUluZm9zKTogS2VybmVsQ3JlYXRlSW5mb3Mge1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IEtlcm5lbENyZWF0ZUluZm9zKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gS2VybmVsQ3JlYXRlSW5mb3M9IG9ialxuICAgICAqIEByZXR1cm5zIEtlcm5lbENyZWF0ZUluZm9zXG4gICAgICovXG4gICAgc3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0tlcm5lbENyZWF0ZUluZm9zKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBLZXJuZWxDcmVhdGVJbmZvcyk6XG4gICAgICAgIEtlcm5lbENyZWF0ZUluZm9zIHtcbiAgICAgIGJiLnNldFBvc2l0aW9uKGJiLnBvc2l0aW9uKCkgKyBmbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEgpO1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IEtlcm5lbENyZWF0ZUluZm9zKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEByZXR1cm5zIG51bWJlclxuICAgICAqL1xuICAgIG5vZGVJbmRpY2VzKGluZGV4OiBudW1iZXIpOiBudW1iZXJ8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLnJlYWRVaW50MzIodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgbnVtYmVyXG4gICAgICovXG4gICAgbm9kZUluZGljZXNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgVWludDMyQXJyYXlcbiAgICAgKi9cbiAgICBub2RlSW5kaWNlc0FycmF5KCk6IFVpbnQzMkFycmF5fG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgP1xuICAgICAgICAgIG5ldyBVaW50MzJBcnJheShcbiAgICAgICAgICAgICAgdGhpcy5iYiEuYnl0ZXMoKS5idWZmZXIsIHRoaXMuYmIhLmJ5dGVzKCkuYnl0ZU9mZnNldCArIHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSxcbiAgICAgICAgICAgICAgdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSkgOlxuICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpbmRleFxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLkxvbmdcbiAgICAgKi9cbiAgICBrZXJuZWxEZWZIYXNoZXMoaW5kZXg6IG51bWJlcik6IGZsYXRidWZmZXJzLkxvbmd8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLnJlYWRVaW50NjQodGhpcy5iYiEuX192ZWN0b3IodGhpcy5iYl9wb3MgKyBvZmZzZXQpICsgaW5kZXggKiA4KSA6XG4gICAgICAgICAgICAgICAgICAgICAgdGhpcy5iYiEuY3JlYXRlTG9uZygwLCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBrZXJuZWxEZWZIYXNoZXNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydEtlcm5lbENyZWF0ZUluZm9zKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRPYmplY3QoMik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgbm9kZUluZGljZXNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkTm9kZUluZGljZXMoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgbm9kZUluZGljZXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgwLCBub2RlSW5kaWNlc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48bnVtYmVyPiBkYXRhXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGNyZWF0ZU5vZGVJbmRpY2VzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGRhdGE6IG51bWJlcltdfFVpbnQ4QXJyYXkpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZEludDMyKGRhdGFbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1aWxkZXIuZW5kVmVjdG9yKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBudW1iZXIgbnVtRWxlbXNcbiAgICAgKi9cbiAgICBzdGF0aWMgc3RhcnROb2RlSW5kaWNlc1ZlY3RvcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBudW1FbGVtczogbnVtYmVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0VmVjdG9yKDQsIG51bUVsZW1zLCA0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBrZXJuZWxEZWZIYXNoZXNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkS2VybmVsRGVmSGFzaGVzKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGtlcm5lbERlZkhhc2hlc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDEsIGtlcm5lbERlZkhhc2hlc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBBcnJheS48ZmxhdGJ1ZmZlcnMuTG9uZz4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVLZXJuZWxEZWZIYXNoZXNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogZmxhdGJ1ZmZlcnMuTG9uZ1tdKTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoOCwgZGF0YS5sZW5ndGgsIDgpO1xuICAgICAgZm9yIChsZXQgaSA9IGRhdGEubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYnVpbGRlci5hZGRJbnQ2NChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0S2VybmVsRGVmSGFzaGVzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoOCwgbnVtRWxlbXMsIDgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgZW5kS2VybmVsQ3JlYXRlSW5mb3MoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcik6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gYnVpbGRlci5lbmRPYmplY3QoKTtcbiAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZUtlcm5lbENyZWF0ZUluZm9zKFxuICAgICAgICBidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBub2RlSW5kaWNlc09mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICBrZXJuZWxEZWZIYXNoZXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBLZXJuZWxDcmVhdGVJbmZvcy5zdGFydEtlcm5lbENyZWF0ZUluZm9zKGJ1aWxkZXIpO1xuICAgICAgS2VybmVsQ3JlYXRlSW5mb3MuYWRkTm9kZUluZGljZXMoYnVpbGRlciwgbm9kZUluZGljZXNPZmZzZXQpO1xuICAgICAgS2VybmVsQ3JlYXRlSW5mb3MuYWRkS2VybmVsRGVmSGFzaGVzKGJ1aWxkZXIsIGtlcm5lbERlZkhhc2hlc09mZnNldCk7XG4gICAgICByZXR1cm4gS2VybmVsQ3JlYXRlSW5mb3MuZW5kS2VybmVsQ3JlYXRlSW5mb3MoYnVpbGRlcik7XG4gICAgfVxuICB9XG59XG4vKipcbiAqIEBjb25zdHJ1Y3RvclxuICovXG5leHBvcnQgbmFtZXNwYWNlIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMge1xuICBleHBvcnQgY2xhc3MgU3ViR3JhcGhTZXNzaW9uU3RhdGUge1xuICAgIGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyfG51bGwgPSBudWxsO1xuXG4gICAgYmJfcG9zID0gMDtcbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGlcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEByZXR1cm5zIFN1YkdyYXBoU2Vzc2lvblN0YXRlXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBTdWJHcmFwaFNlc3Npb25TdGF0ZSB7XG4gICAgICB0aGlzLmJiX3BvcyA9IGk7XG4gICAgICB0aGlzLmJiID0gYmI7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBTdWJHcmFwaFNlc3Npb25TdGF0ZT0gb2JqXG4gICAgICogQHJldHVybnMgU3ViR3JhcGhTZXNzaW9uU3RhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0Um9vdEFzU3ViR3JhcGhTZXNzaW9uU3RhdGUoYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IFN1YkdyYXBoU2Vzc2lvblN0YXRlKTogU3ViR3JhcGhTZXNzaW9uU3RhdGUge1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFN1YkdyYXBoU2Vzc2lvblN0YXRlKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gU3ViR3JhcGhTZXNzaW9uU3RhdGU9IG9ialxuICAgICAqIEByZXR1cm5zIFN1YkdyYXBoU2Vzc2lvblN0YXRlXG4gICAgICovXG4gICAgc3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1N1YkdyYXBoU2Vzc2lvblN0YXRlKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBTdWJHcmFwaFNlc3Npb25TdGF0ZSk6XG4gICAgICAgIFN1YkdyYXBoU2Vzc2lvblN0YXRlIHtcbiAgICAgIGJiLnNldFBvc2l0aW9uKGJiLnBvc2l0aW9uKCkgKyBmbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEgpO1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFN1YkdyYXBoU2Vzc2lvblN0YXRlKCkpLl9faW5pdChiYi5yZWFkSW50MzIoYmIucG9zaXRpb24oKSkgKyBiYi5wb3NpdGlvbigpLCBiYik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkVuY29kaW5nPSBvcHRpb25hbEVuY29kaW5nXG4gICAgICogQHJldHVybnMgc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbFxuICAgICAqL1xuICAgIGdyYXBoSWQoKTogc3RyaW5nfG51bGw7XG4gICAgZ3JhcGhJZChvcHRpb25hbEVuY29kaW5nOiBmbGF0YnVmZmVycy5FbmNvZGluZyk6IHN0cmluZ3xVaW50OEFycmF5fG51bGw7XG4gICAgZ3JhcGhJZChvcHRpb25hbEVuY29kaW5nPzogYW55KTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDQpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IHRoaXMuYmIhLl9fc3RyaW5nKHRoaXMuYmJfcG9zICsgb2Zmc2V0LCBvcHRpb25hbEVuY29kaW5nKSA6IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU2Vzc2lvblN0YXRlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlNlc3Npb25TdGF0ZXxudWxsXG4gICAgICovXG4gICAgc2Vzc2lvblN0YXRlKG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU2Vzc2lvblN0YXRlKTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TZXNzaW9uU3RhdGV8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU2Vzc2lvblN0YXRlKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiX3BvcyArIG9mZnNldCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0U3ViR3JhcGhTZXNzaW9uU3RhdGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcikge1xuICAgICAgYnVpbGRlci5zdGFydE9iamVjdCgyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBncmFwaElkT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZEdyYXBoSWQoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZ3JhcGhJZE9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDAsIGdyYXBoSWRPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IHNlc3Npb25TdGF0ZU9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRTZXNzaW9uU3RhdGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgc2Vzc2lvblN0YXRlT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMSwgc2Vzc2lvblN0YXRlT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGVuZFN1YkdyYXBoU2Vzc2lvblN0YXRlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICBidWlsZGVyLnJlcXVpcmVkRmllbGQob2Zmc2V0LCA0KTsgIC8vIGdyYXBoX2lkXG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVTdWJHcmFwaFNlc3Npb25TdGF0ZShcbiAgICAgICAgYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZ3JhcGhJZE9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0LFxuICAgICAgICBzZXNzaW9uU3RhdGVPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCk6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBTdWJHcmFwaFNlc3Npb25TdGF0ZS5zdGFydFN1YkdyYXBoU2Vzc2lvblN0YXRlKGJ1aWxkZXIpO1xuICAgICAgU3ViR3JhcGhTZXNzaW9uU3RhdGUuYWRkR3JhcGhJZChidWlsZGVyLCBncmFwaElkT2Zmc2V0KTtcbiAgICAgIFN1YkdyYXBoU2Vzc2lvblN0YXRlLmFkZFNlc3Npb25TdGF0ZShidWlsZGVyLCBzZXNzaW9uU3RhdGVPZmZzZXQpO1xuICAgICAgcmV0dXJuIFN1YkdyYXBoU2Vzc2lvblN0YXRlLmVuZFN1YkdyYXBoU2Vzc2lvblN0YXRlKGJ1aWxkZXIpO1xuICAgIH1cbiAgfVxufVxuLyoqXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZXhwb3J0IG5hbWVzcGFjZSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzIHtcbiAgZXhwb3J0IGNsYXNzIFNlc3Npb25TdGF0ZSB7XG4gICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ8bnVsbCA9IG51bGw7XG5cbiAgICBiYl9wb3MgPSAwO1xuICAgIC8qKlxuICAgICAqIEBwYXJhbSBudW1iZXIgaVxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHJldHVybnMgU2Vzc2lvblN0YXRlXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBTZXNzaW9uU3RhdGUge1xuICAgICAgdGhpcy5iYl9wb3MgPSBpO1xuICAgICAgdGhpcy5iYiA9IGJiO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcGFyYW0gU2Vzc2lvblN0YXRlPSBvYmpcbiAgICAgKiBAcmV0dXJucyBTZXNzaW9uU3RhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0Um9vdEFzU2Vzc2lvblN0YXRlKGJiOiBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLCBvYmo/OiBTZXNzaW9uU3RhdGUpOiBTZXNzaW9uU3RhdGUge1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFNlc3Npb25TdGF0ZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIFNlc3Npb25TdGF0ZT0gb2JqXG4gICAgICogQHJldHVybnMgU2Vzc2lvblN0YXRlXG4gICAgICovXG4gICAgc3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc1Nlc3Npb25TdGF0ZShiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogU2Vzc2lvblN0YXRlKTogU2Vzc2lvblN0YXRlIHtcbiAgICAgIGJiLnNldFBvc2l0aW9uKGJiLnBvc2l0aW9uKCkgKyBmbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEgpO1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IFNlc3Npb25TdGF0ZSgpKS5fX2luaXQoYmIucmVhZEludDMyKGJiLnBvc2l0aW9uKCkpICsgYmIucG9zaXRpb24oKSwgYmIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLktlcm5lbENyZWF0ZUluZm9zPSBvYmpcbiAgICAgKiBAcmV0dXJucyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLktlcm5lbENyZWF0ZUluZm9zfG51bGxcbiAgICAgKi9cbiAgICBrZXJuZWxzKG9iaj86IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuS2VybmVsQ3JlYXRlSW5mb3MpOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLktlcm5lbENyZWF0ZUluZm9zfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA0KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLktlcm5lbENyZWF0ZUluZm9zKCkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIC5fX2luaXQodGhpcy5iYiEuX19pbmRpcmVjdCh0aGlzLmJiX3BvcyArIG9mZnNldCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gbnVtYmVyIGluZGV4XG4gICAgICogQHBhcmFtIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU3ViR3JhcGhTZXNzaW9uU3RhdGU9IG9ialxuICAgICAqIEByZXR1cm5zIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU3ViR3JhcGhTZXNzaW9uU3RhdGVcbiAgICAgKi9cbiAgICBzdWJHcmFwaFNlc3Npb25TdGF0ZXMoaW5kZXg6IG51bWJlciwgb2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TdWJHcmFwaFNlc3Npb25TdGF0ZSk6XG4gICAgICAgIG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU3ViR3JhcGhTZXNzaW9uU3RhdGV8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU3ViR3JhcGhTZXNzaW9uU3RhdGUoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLl9faW5pdCh0aGlzLmJiIS5fX2luZGlyZWN0KHRoaXMuYmIhLl9fdmVjdG9yKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSArIGluZGV4ICogNCksIHRoaXMuYmIhKSA6XG4gICAgICAgICAgICAgICAgICAgICAgbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBudW1iZXJcbiAgICAgKi9cbiAgICBzdWJHcmFwaFNlc3Npb25TdGF0ZXNMZW5ndGgoKTogbnVtYmVyIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNik7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX192ZWN0b3JfbGVuKHRoaXMuYmJfcG9zICsgb2Zmc2V0KSA6IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydFNlc3Npb25TdGF0ZShidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyKSB7XG4gICAgICBidWlsZGVyLnN0YXJ0T2JqZWN0KDIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IGtlcm5lbHNPZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkS2VybmVscyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBrZXJuZWxzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMCwga2VybmVsc09mZnNldCwgMCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgc3ViR3JhcGhTZXNzaW9uU3RhdGVzT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZFN1YkdyYXBoU2Vzc2lvblN0YXRlcyhidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBzdWJHcmFwaFNlc3Npb25TdGF0ZXNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5hZGRGaWVsZE9mZnNldCgxLCBzdWJHcmFwaFNlc3Npb25TdGF0ZXNPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gQXJyYXkuPGZsYXRidWZmZXJzLk9mZnNldD4gZGF0YVxuICAgICAqIEByZXR1cm5zIGZsYXRidWZmZXJzLk9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBjcmVhdGVTdWJHcmFwaFNlc3Npb25TdGF0ZXNWZWN0b3IoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgZGF0YTogZmxhdGJ1ZmZlcnMuT2Zmc2V0W10pOlxuICAgICAgICBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgYnVpbGRlci5zdGFydFZlY3Rvcig0LCBkYXRhLmxlbmd0aCwgNCk7XG4gICAgICBmb3IgKGxldCBpID0gZGF0YS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBidWlsZGVyLmFkZE9mZnNldChkYXRhW2ldKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBidWlsZGVyLmVuZFZlY3RvcigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gbnVtYmVyIG51bUVsZW1zXG4gICAgICovXG4gICAgc3RhdGljIHN0YXJ0U3ViR3JhcGhTZXNzaW9uU3RhdGVzVmVjdG9yKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG51bUVsZW1zOiBudW1iZXIpIHtcbiAgICAgIGJ1aWxkZXIuc3RhcnRWZWN0b3IoNCwgbnVtRWxlbXMsIDQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcmV0dXJucyBmbGF0YnVmZmVycy5PZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgZW5kU2Vzc2lvblN0YXRlKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgbGV0IG9mZnNldCA9IGJ1aWxkZXIuZW5kT2JqZWN0KCk7XG4gICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVTZXNzaW9uU3RhdGUoXG4gICAgICAgIGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIGtlcm5lbHNPZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCxcbiAgICAgICAgc3ViR3JhcGhTZXNzaW9uU3RhdGVzT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpOiBmbGF0YnVmZmVycy5PZmZzZXQge1xuICAgICAgU2Vzc2lvblN0YXRlLnN0YXJ0U2Vzc2lvblN0YXRlKGJ1aWxkZXIpO1xuICAgICAgU2Vzc2lvblN0YXRlLmFkZEtlcm5lbHMoYnVpbGRlciwga2VybmVsc09mZnNldCk7XG4gICAgICBTZXNzaW9uU3RhdGUuYWRkU3ViR3JhcGhTZXNzaW9uU3RhdGVzKGJ1aWxkZXIsIHN1YkdyYXBoU2Vzc2lvblN0YXRlc09mZnNldCk7XG4gICAgICByZXR1cm4gU2Vzc2lvblN0YXRlLmVuZFNlc3Npb25TdGF0ZShidWlsZGVyKTtcbiAgICB9XG4gIH1cbn1cbi8qKlxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBuYW1lc3BhY2Ugb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicyB7XG4gIGV4cG9ydCBjbGFzcyBJbmZlcmVuY2VTZXNzaW9uIHtcbiAgICBiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcnxudWxsID0gbnVsbDtcblxuICAgIGJiX3BvcyA9IDA7XG4gICAgLyoqXG4gICAgICogQHBhcmFtIG51bWJlciBpXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgYmJcbiAgICAgKiBAcmV0dXJucyBJbmZlcmVuY2VTZXNzaW9uXG4gICAgICovXG4gICAgX19pbml0KGk6IG51bWJlciwgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIpOiBJbmZlcmVuY2VTZXNzaW9uIHtcbiAgICAgIHRoaXMuYmJfcG9zID0gaTtcbiAgICAgIHRoaXMuYmIgPSBiYjtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyIGJiXG4gICAgICogQHBhcmFtIEluZmVyZW5jZVNlc3Npb249IG9ialxuICAgICAqIEByZXR1cm5zIEluZmVyZW5jZVNlc3Npb25cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0Um9vdEFzSW5mZXJlbmNlU2Vzc2lvbihiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciwgb2JqPzogSW5mZXJlbmNlU2Vzc2lvbik6IEluZmVyZW5jZVNlc3Npb24ge1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IEluZmVyZW5jZVNlc3Npb24oKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEBwYXJhbSBJbmZlcmVuY2VTZXNzaW9uPSBvYmpcbiAgICAgKiBAcmV0dXJucyBJbmZlcmVuY2VTZXNzaW9uXG4gICAgICovXG4gICAgc3RhdGljIGdldFNpemVQcmVmaXhlZFJvb3RBc0luZmVyZW5jZVNlc3Npb24oYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsIG9iaj86IEluZmVyZW5jZVNlc3Npb24pOiBJbmZlcmVuY2VTZXNzaW9uIHtcbiAgICAgIGJiLnNldFBvc2l0aW9uKGJiLnBvc2l0aW9uKCkgKyBmbGF0YnVmZmVycy5TSVpFX1BSRUZJWF9MRU5HVEgpO1xuICAgICAgcmV0dXJuIChvYmogfHwgbmV3IEluZmVyZW5jZVNlc3Npb24oKSkuX19pbml0KGJiLnJlYWRJbnQzMihiYi5wb3NpdGlvbigpKSArIGJiLnBvc2l0aW9uKCksIGJiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlciBiYlxuICAgICAqIEByZXR1cm5zIGJvb2xlYW5cbiAgICAgKi9cbiAgICBzdGF0aWMgYnVmZmVySGFzSWRlbnRpZmllcihiYjogZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcik6IGJvb2xlYW4ge1xuICAgICAgcmV0dXJuIGJiLl9faGFzX2lkZW50aWZpZXIoJ09SVE0nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuRW5jb2Rpbmc9IG9wdGlvbmFsRW5jb2RpbmdcbiAgICAgKiBAcmV0dXJucyBzdHJpbmd8VWludDhBcnJheXxudWxsXG4gICAgICovXG4gICAgb3J0VmVyc2lvbigpOiBzdHJpbmd8bnVsbDtcbiAgICBvcnRWZXJzaW9uKG9wdGlvbmFsRW5jb2Rpbmc6IGZsYXRidWZmZXJzLkVuY29kaW5nKTogc3RyaW5nfFVpbnQ4QXJyYXl8bnVsbDtcbiAgICBvcnRWZXJzaW9uKG9wdGlvbmFsRW5jb2Rpbmc/OiBhbnkpOiBzdHJpbmd8VWludDhBcnJheXxudWxsIHtcbiAgICAgIGxldCBvZmZzZXQgPSB0aGlzLmJiIS5fX29mZnNldCh0aGlzLmJiX3BvcywgNCk7XG4gICAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5iYiEuX19zdHJpbmcodGhpcy5iYl9wb3MgKyBvZmZzZXQsIG9wdGlvbmFsRW5jb2RpbmcpIDogbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Nb2RlbD0gb2JqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Nb2RlbHxudWxsXG4gICAgICovXG4gICAgbW9kZWwob2JqPzogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Nb2RlbCk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTW9kZWx8bnVsbCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gdGhpcy5iYiEuX19vZmZzZXQodGhpcy5iYl9wb3MsIDYpO1xuICAgICAgcmV0dXJuIG9mZnNldCA/IChvYmogfHwgbmV3IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuTW9kZWwoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgLl9faW5pdCh0aGlzLmJiIS5fX2luZGlyZWN0KHRoaXMuYmJfcG9zICsgb2Zmc2V0KSwgdGhpcy5iYiEpIDpcbiAgICAgICAgICAgICAgICAgICAgICBudWxsO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlNlc3Npb25TdGF0ZT0gb2JqXG4gICAgICogQHJldHVybnMgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5TZXNzaW9uU3RhdGV8bnVsbFxuICAgICAqL1xuICAgIHNlc3Npb25TdGF0ZShvYmo/OiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlNlc3Npb25TdGF0ZSk6IG9ubnhydW50aW1lLmV4cGVyaW1lbnRhbC5mYnMuU2Vzc2lvblN0YXRlfG51bGwge1xuICAgICAgbGV0IG9mZnNldCA9IHRoaXMuYmIhLl9fb2Zmc2V0KHRoaXMuYmJfcG9zLCA4KTtcbiAgICAgIHJldHVybiBvZmZzZXQgPyAob2JqIHx8IG5ldyBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlNlc3Npb25TdGF0ZSgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAuX19pbml0KHRoaXMuYmIhLl9faW5kaXJlY3QodGhpcy5iYl9wb3MgKyBvZmZzZXQpLCB0aGlzLmJiISkgOlxuICAgICAgICAgICAgICAgICAgICAgIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqL1xuICAgIHN0YXRpYyBzdGFydEluZmVyZW5jZVNlc3Npb24oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcikge1xuICAgICAgYnVpbGRlci5zdGFydE9iamVjdCgzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBvcnRWZXJzaW9uT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZE9ydFZlcnNpb24oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgb3J0VmVyc2lvbk9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KSB7XG4gICAgICBidWlsZGVyLmFkZEZpZWxkT2Zmc2V0KDAsIG9ydFZlcnNpb25PZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IG1vZGVsT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGFkZE1vZGVsKGJ1aWxkZXI6IGZsYXRidWZmZXJzLkJ1aWxkZXIsIG1vZGVsT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMSwgbW9kZWxPZmZzZXQsIDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5CdWlsZGVyIGJ1aWxkZXJcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuT2Zmc2V0IHNlc3Npb25TdGF0ZU9mZnNldFxuICAgICAqL1xuICAgIHN0YXRpYyBhZGRTZXNzaW9uU3RhdGUoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgc2Vzc2lvblN0YXRlT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuYWRkRmllbGRPZmZzZXQoMiwgc2Vzc2lvblN0YXRlT2Zmc2V0LCAwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHJldHVybnMgZmxhdGJ1ZmZlcnMuT2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGVuZEluZmVyZW5jZVNlc3Npb24oYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlcik6IGZsYXRidWZmZXJzLk9mZnNldCB7XG4gICAgICBsZXQgb2Zmc2V0ID0gYnVpbGRlci5lbmRPYmplY3QoKTtcbiAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLkJ1aWxkZXIgYnVpbGRlclxuICAgICAqIEBwYXJhbSBmbGF0YnVmZmVycy5PZmZzZXQgb2Zmc2V0XG4gICAgICovXG4gICAgc3RhdGljIGZpbmlzaEluZmVyZW5jZVNlc3Npb25CdWZmZXIoYnVpbGRlcjogZmxhdGJ1ZmZlcnMuQnVpbGRlciwgb2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQpIHtcbiAgICAgIGJ1aWxkZXIuZmluaXNoKG9mZnNldCwgJ09SVE0nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZmxhdGJ1ZmZlcnMuQnVpbGRlciBidWlsZGVyXG4gICAgICogQHBhcmFtIGZsYXRidWZmZXJzLk9mZnNldCBvZmZzZXRcbiAgICAgKi9cbiAgICBzdGF0aWMgZmluaXNoU2l6ZVByZWZpeGVkSW5mZXJlbmNlU2Vzc2lvbkJ1ZmZlcihidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBvZmZzZXQ6IGZsYXRidWZmZXJzLk9mZnNldCkge1xuICAgICAgYnVpbGRlci5maW5pc2gob2Zmc2V0LCAnT1JUTScsIHRydWUpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGVJbmZlcmVuY2VTZXNzaW9uKFxuICAgICAgICBidWlsZGVyOiBmbGF0YnVmZmVycy5CdWlsZGVyLCBvcnRWZXJzaW9uT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsIG1vZGVsT2Zmc2V0OiBmbGF0YnVmZmVycy5PZmZzZXQsXG4gICAgICAgIHNlc3Npb25TdGF0ZU9mZnNldDogZmxhdGJ1ZmZlcnMuT2Zmc2V0KTogZmxhdGJ1ZmZlcnMuT2Zmc2V0IHtcbiAgICAgIEluZmVyZW5jZVNlc3Npb24uc3RhcnRJbmZlcmVuY2VTZXNzaW9uKGJ1aWxkZXIpO1xuICAgICAgSW5mZXJlbmNlU2Vzc2lvbi5hZGRPcnRWZXJzaW9uKGJ1aWxkZXIsIG9ydFZlcnNpb25PZmZzZXQpO1xuICAgICAgSW5mZXJlbmNlU2Vzc2lvbi5hZGRNb2RlbChidWlsZGVyLCBtb2RlbE9mZnNldCk7XG4gICAgICBJbmZlcmVuY2VTZXNzaW9uLmFkZFNlc3Npb25TdGF0ZShidWlsZGVyLCBzZXNzaW9uU3RhdGVPZmZzZXQpO1xuICAgICAgcmV0dXJuIEluZmVyZW5jZVNlc3Npb24uZW5kSW5mZXJlbmNlU2Vzc2lvbihidWlsZGVyKTtcbiAgICB9XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0luZmVyZW5jZVNlc3Npb24sIFNlc3Npb25IYW5kbGVyLCBUZW5zb3J9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7U2Vzc2lvbn0gZnJvbSAnLi9zZXNzaW9uJztcbmltcG9ydCB7VGVuc29yIGFzIE9ubnhqc1RlbnNvcn0gZnJvbSAnLi90ZW5zb3InO1xuXG5leHBvcnQgY2xhc3MgT25ueGpzU2Vzc2lvbkhhbmRsZXIgaW1wbGVtZW50cyBTZXNzaW9uSGFuZGxlciB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgc2Vzc2lvbjogU2Vzc2lvbikge1xuICAgIHRoaXMuaW5wdXROYW1lcyA9IHRoaXMuc2Vzc2lvbi5pbnB1dE5hbWVzO1xuICAgIHRoaXMub3V0cHV0TmFtZXMgPSB0aGlzLnNlc3Npb24ub3V0cHV0TmFtZXM7XG4gIH1cblxuICBhc3luYyBkaXNwb3NlKCk6IFByb21pc2U8dm9pZD4ge31cbiAgaW5wdXROYW1lczogcmVhZG9ubHkgc3RyaW5nW107XG4gIG91dHB1dE5hbWVzOiByZWFkb25seSBzdHJpbmdbXTtcbiAgYXN5bmMgcnVuKFxuICAgICAgZmVlZHM6IFNlc3Npb25IYW5kbGVyLkZlZWRzVHlwZSwgX2ZldGNoZXM6IFNlc3Npb25IYW5kbGVyLkZldGNoZXNUeXBlLFxuICAgICAgX29wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uUnVuT3B0aW9ucyk6IFByb21pc2U8U2Vzc2lvbkhhbmRsZXIuUmV0dXJuVHlwZT4ge1xuICAgIGNvbnN0IGlucHV0TWFwID0gbmV3IE1hcDxzdHJpbmcsIE9ubnhqc1RlbnNvcj4oKTtcbiAgICBmb3IgKGNvbnN0IG5hbWUgaW4gZmVlZHMpIHtcbiAgICAgIGlmIChPYmplY3QuaGFzT3duUHJvcGVydHkuY2FsbChmZWVkcywgbmFtZSkpIHtcbiAgICAgICAgY29uc3QgZmVlZCA9IGZlZWRzW25hbWVdO1xuICAgICAgICBpbnB1dE1hcC5zZXQoXG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgbmV3IE9ubnhqc1RlbnNvcihcbiAgICAgICAgICAgICAgICBmZWVkLmRpbXMsIGZlZWQudHlwZSBhcyBPbm54anNUZW5zb3IuRGF0YVR5cGUsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgIGZlZWQuZGF0YSBhcyBPbm54anNUZW5zb3IuTnVtYmVyVHlwZSkpO1xuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBvdXRwdXRNYXAgPSBhd2FpdCB0aGlzLnNlc3Npb24ucnVuKGlucHV0TWFwKTtcbiAgICBjb25zdCBvdXRwdXQ6IFNlc3Npb25IYW5kbGVyLlJldHVyblR5cGUgPSB7fTtcbiAgICBvdXRwdXRNYXAuZm9yRWFjaCgodGVuc29yLCBuYW1lKSA9PiB7XG4gICAgICBvdXRwdXRbbmFtZV0gPSBuZXcgVGVuc29yKHRlbnNvci50eXBlLCB0ZW5zb3IuZGF0YSwgdGVuc29yLmRpbXMpO1xuICAgIH0pO1xuICAgIHJldHVybiBvdXRwdXQ7XG4gIH1cbiAgc3RhcnRQcm9maWxpbmcoKTogdm9pZCB7XG4gICAgdGhpcy5zZXNzaW9uLnN0YXJ0UHJvZmlsaW5nKCk7XG4gIH1cbiAgZW5kUHJvZmlsaW5nKCk6IHZvaWQge1xuICAgIHRoaXMuc2Vzc2lvbi5lbmRQcm9maWxpbmcoKTtcbiAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7cmVhZEZpbGV9IGZyb20gJ2ZzJztcbmltcG9ydCB7cHJvbWlzaWZ5fSBmcm9tICd1dGlsJztcblxuaW1wb3J0IHtyZXNvbHZlQmFja2VuZCwgU2Vzc2lvbkhhbmRsZXJUeXBlfSBmcm9tICcuL2JhY2tlbmQnO1xuaW1wb3J0IHtFeGVjdXRpb25QbGFufSBmcm9tICcuL2V4ZWN1dGlvbi1wbGFuJztcbmltcG9ydCB7R3JhcGh9IGZyb20gJy4vZ3JhcGgnO1xuaW1wb3J0IHtQcm9maWxlcn0gZnJvbSAnLi9pbnN0cnVtZW50JztcbmltcG9ydCB7TW9kZWx9IGZyb20gJy4vbW9kZWwnO1xuaW1wb3J0IHtPcGVyYXRvcn0gZnJvbSAnLi9vcGVyYXRvcnMnO1xuaW1wb3J0IHtUZW5zb3J9IGZyb20gJy4vdGVuc29yJztcblxuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIFNlc3Npb24ge1xuICBleHBvcnQgaW50ZXJmYWNlIENvbmZpZyB7XG4gICAgYmFja2VuZEhpbnQ/OiBzdHJpbmc7XG4gICAgcHJvZmlsZXI/OiBQcm9maWxlci5Db25maWc7XG4gIH1cblxuICBleHBvcnQgaW50ZXJmYWNlIENvbnRleHQge1xuICAgIHByb2ZpbGVyOiBSZWFkb25seTxQcm9maWxlcj47XG4gICAgZ3JhcGhJbnB1dFR5cGVzPzogVGVuc29yLkRhdGFUeXBlW107XG4gICAgZ3JhcGhJbnB1dERpbXM/OiBBcnJheTxyZWFkb25seSBudW1iZXJbXT47XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFNlc3Npb24ge1xuICBjb25zdHJ1Y3Rvcihjb25maWc6IFNlc3Npb24uQ29uZmlnID0ge30pIHtcbiAgICB0aGlzLl9pbml0aWFsaXplZCA9IGZhbHNlO1xuICAgIHRoaXMuYmFja2VuZEhpbnQgPSBjb25maWcuYmFja2VuZEhpbnQ7XG4gICAgdGhpcy5wcm9maWxlciA9IFByb2ZpbGVyLmNyZWF0ZShjb25maWcucHJvZmlsZXIpO1xuICAgIHRoaXMuY29udGV4dCA9IHtwcm9maWxlcjogdGhpcy5wcm9maWxlciwgZ3JhcGhJbnB1dFR5cGVzOiBbXSwgZ3JhcGhJbnB1dERpbXM6IFtdfTtcbiAgfVxuXG4gIGdldCBpbnB1dE5hbWVzKCk6IHJlYWRvbmx5IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gdGhpcy5fbW9kZWwuZ3JhcGguZ2V0SW5wdXROYW1lcygpO1xuICB9XG4gIGdldCBvdXRwdXROYW1lcygpOiByZWFkb25seSBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMuX21vZGVsLmdyYXBoLmdldE91dHB1dE5hbWVzKCk7XG4gIH1cblxuICBzdGFydFByb2ZpbGluZygpIHtcbiAgICB0aGlzLnByb2ZpbGVyLnN0YXJ0KCk7XG4gIH1cblxuICBlbmRQcm9maWxpbmcoKSB7XG4gICAgdGhpcy5wcm9maWxlci5zdG9wKCk7XG4gIH1cblxuICBhc3luYyBsb2FkTW9kZWwodXJpOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+O1xuICBhc3luYyBsb2FkTW9kZWwoYnVmZmVyOiBBcnJheUJ1ZmZlciwgYnl0ZU9mZnNldD86IG51bWJlciwgbGVuZ3RoPzogbnVtYmVyKTogUHJvbWlzZTx2b2lkPjtcbiAgYXN5bmMgbG9hZE1vZGVsKGJ1ZmZlcjogVWludDhBcnJheSk6IFByb21pc2U8dm9pZD47XG4gIGFzeW5jIGxvYWRNb2RlbChhcmc6IHN0cmluZ3xBcnJheUJ1ZmZlcnxVaW50OEFycmF5LCBieXRlT2Zmc2V0PzogbnVtYmVyLCBsZW5ndGg/OiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLnByb2ZpbGVyLmV2ZW50KCdzZXNzaW9uJywgJ1Nlc3Npb24ubG9hZE1vZGVsJywgYXN5bmMgKCkgPT4ge1xuICAgICAgLy8gcmVzb2x2ZSBiYWNrZW5kIGFuZCBzZXNzaW9uIGhhbmRsZXJcbiAgICAgIGNvbnN0IGJhY2tlbmQgPSBhd2FpdCByZXNvbHZlQmFja2VuZCh0aGlzLmJhY2tlbmRIaW50KTtcbiAgICAgIHRoaXMuc2Vzc2lvbkhhbmRsZXIgPSBiYWNrZW5kLmNyZWF0ZVNlc3Npb25IYW5kbGVyKHRoaXMuY29udGV4dCk7XG5cbiAgICAgIHRoaXMuX21vZGVsID0gbmV3IE1vZGVsKCk7XG4gICAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uc3QgaXNPcnRGb3JtYXQgPSBhcmcuZW5kc1dpdGgoJy5vcnQnKTtcbiAgICAgICAgaWYgKHR5cGVvZiBmZXRjaCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAvLyBub2RlXG4gICAgICAgICAgY29uc3QgYnVmID0gYXdhaXQgcHJvbWlzaWZ5KHJlYWRGaWxlKShhcmcpO1xuICAgICAgICAgIHRoaXMuaW5pdGlhbGl6ZShidWYsIGlzT3J0Rm9ybWF0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBicm93c2VyXG4gICAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaChhcmcpO1xuICAgICAgICAgIGNvbnN0IGJ1ZiA9IGF3YWl0IHJlc3BvbnNlLmFycmF5QnVmZmVyKCk7XG4gICAgICAgICAgdGhpcy5pbml0aWFsaXplKG5ldyBVaW50OEFycmF5KGJ1ZiksIGlzT3J0Rm9ybWF0KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICghQXJyYXlCdWZmZXIuaXNWaWV3KGFyZykpIHtcbiAgICAgICAgLy8gbG9hZCBtb2RlbCBmcm9tIEFycmF5QnVmZmVyXG4gICAgICAgIGNvbnN0IGFyciA9IG5ldyBVaW50OEFycmF5KGFyZywgYnl0ZU9mZnNldCB8fCAwLCBsZW5ndGggfHwgYXJnLmJ5dGVMZW5ndGgpO1xuICAgICAgICB0aGlzLmluaXRpYWxpemUoYXJyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGxvYWQgbW9kZWwgZnJvbSBVaW50OGFycmF5XG4gICAgICAgIHRoaXMuaW5pdGlhbGl6ZShhcmcpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBpbml0aWFsaXplKG1vZGVsUHJvdG9CbG9iOiBVaW50OEFycmF5LCBpc09ydEZvcm1hdD86IGJvb2xlYW4pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5faW5pdGlhbGl6ZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignYWxyZWFkeSBpbml0aWFsaXplZCcpO1xuICAgIH1cblxuICAgIHRoaXMucHJvZmlsZXIuZXZlbnQoJ3Nlc3Npb24nLCAnU2Vzc2lvbi5pbml0aWFsaXplJywgKCkgPT4ge1xuICAgICAgLy8gbG9hZCBncmFwaFxuICAgICAgY29uc3QgZ3JhcGhJbml0aWFsaXplciA9XG4gICAgICAgICAgdGhpcy5zZXNzaW9uSGFuZGxlci50cmFuc2Zvcm1HcmFwaCA/IHRoaXMuc2Vzc2lvbkhhbmRsZXIgYXMgR3JhcGguSW5pdGlhbGl6ZXIgOiB1bmRlZmluZWQ7XG4gICAgICB0aGlzLl9tb2RlbC5sb2FkKG1vZGVsUHJvdG9CbG9iLCBncmFwaEluaXRpYWxpemVyLCBpc09ydEZvcm1hdCk7XG5cbiAgICAgIC8vIGdyYXBoIGlzIGNvbXBsZXRlbHkgaW5pdGlhbHppZWQgYXQgdGhpcyBzdGFnZSAsIGxldCB0aGUgaW50ZXJlc3RlZCBoYW5kbGVycyBrbm93XG4gICAgICBpZiAodGhpcy5zZXNzaW9uSGFuZGxlci5vbkdyYXBoSW5pdGlhbGl6ZWQpIHtcbiAgICAgICAgdGhpcy5zZXNzaW9uSGFuZGxlci5vbkdyYXBoSW5pdGlhbGl6ZWQodGhpcy5fbW9kZWwuZ3JhcGgpO1xuICAgICAgfVxuICAgICAgLy8gaW5pdGlhbGl6ZSBlYWNoIG9wZXJhdG9yIGluIHRoZSBncmFwaFxuICAgICAgdGhpcy5pbml0aWFsaXplT3BzKHRoaXMuX21vZGVsLmdyYXBoKTtcblxuICAgICAgLy8gaW5zdGFudGlhdGUgYW4gRXhlY3V0aW9uUGxhbiBvYmplY3QgdG8gYmUgdXNlZCBieSB0aGUgU2Vzc2lvbiBvYmplY3RcbiAgICAgIHRoaXMuX2V4ZWN1dGlvblBsYW4gPSBuZXcgRXhlY3V0aW9uUGxhbih0aGlzLl9tb2RlbC5ncmFwaCwgdGhpcy5fb3BzLCB0aGlzLnByb2ZpbGVyKTtcbiAgICB9KTtcblxuICAgIHRoaXMuX2luaXRpYWxpemVkID0gdHJ1ZTtcbiAgfVxuXG4gIGFzeW5jIHJ1bihpbnB1dHM6IE1hcDxzdHJpbmcsIFRlbnNvcj58VGVuc29yW10pOiBQcm9taXNlPE1hcDxzdHJpbmcsIFRlbnNvcj4+IHtcbiAgICBpZiAoIXRoaXMuX2luaXRpYWxpemVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Nlc3Npb24gbm90IGluaXRpYWxpemVkIHlldCcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnByb2ZpbGVyLmV2ZW50KCdzZXNzaW9uJywgJ1Nlc3Npb24ucnVuJywgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgaW5wdXRUZW5zb3JzID0gdGhpcy5ub3JtYWxpemVBbmRWYWxpZGF0ZUlucHV0cyhpbnB1dHMpO1xuXG4gICAgICBjb25zdCBvdXRwdXRUZW5zb3JzID0gYXdhaXQgdGhpcy5fZXhlY3V0aW9uUGxhbi5leGVjdXRlKHRoaXMuc2Vzc2lvbkhhbmRsZXIsIGlucHV0VGVuc29ycyk7XG5cbiAgICAgIHJldHVybiB0aGlzLmNyZWF0ZU91dHB1dChvdXRwdXRUZW5zb3JzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgbm9ybWFsaXplQW5kVmFsaWRhdGVJbnB1dHMoaW5wdXRzOiBNYXA8c3RyaW5nLCBUZW5zb3I+fFRlbnNvcltdKTogVGVuc29yW10ge1xuICAgIGNvbnN0IG1vZGVsSW5wdXROYW1lcyA9IHRoaXMuX21vZGVsLmdyYXBoLmdldElucHV0TmFtZXMoKTtcblxuICAgIC8vIG5vcm1hbGl6ZSBpbnB1dHNcbiAgICAvLyBpbnB1dHM6IFRlbnNvcltdXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXRzKSkge1xuICAgICAgaWYgKGlucHV0cy5sZW5ndGggIT09IG1vZGVsSW5wdXROYW1lcy5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbmNvcnJlY3QgaW5wdXQgYXJyYXkgbGVuZ3RoOiBleHBlY3RlZCAke21vZGVsSW5wdXROYW1lcy5sZW5ndGh9IGJ1dCBnb3QgJHtpbnB1dHMubGVuZ3RofWApO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBjb252ZXJ0IG1hcCB0byBhcnJheVxuICAgIC8vIGlucHV0czogTWFwPHN0cmluZywgVGVuc29yPlxuICAgIGVsc2Uge1xuICAgICAgaWYgKGlucHV0cy5zaXplICE9PSBtb2RlbElucHV0TmFtZXMubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaW5jb3JyZWN0IGlucHV0IG1hcCBzaXplOiBleHBlY3RlZCAke21vZGVsSW5wdXROYW1lcy5sZW5ndGh9IGJ1dCBnb3QgJHtpbnB1dHMuc2l6ZX1gKTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc29ydGVkSW5wdXRzID0gbmV3IEFycmF5PFRlbnNvcj4oaW5wdXRzLnNpemUpO1xuICAgICAgbGV0IHNvcnRlZElucHV0c0luZGV4ID0gMDtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbW9kZWxJbnB1dE5hbWVzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGNvbnN0IHRlbnNvciA9IGlucHV0cy5nZXQobW9kZWxJbnB1dE5hbWVzW2ldKTtcbiAgICAgICAgaWYgKCF0ZW5zb3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG1pc3NpbmcgaW5wdXQgdGVuc29yIGZvcjogJyR7bmFtZX0nYCk7XG4gICAgICAgIH1cbiAgICAgICAgc29ydGVkSW5wdXRzW3NvcnRlZElucHV0c0luZGV4KytdID0gdGVuc29yO1xuICAgICAgfVxuXG4gICAgICBpbnB1dHMgPSBzb3J0ZWRJbnB1dHM7XG4gICAgfVxuXG4gICAgLy8gdmFsaWRhdGUgZGltcyByZXF1aXJlbWVudHNcbiAgICAvLyBGaXJzdCBzZXNzaW9uIHJ1biAtIGdyYXBoIGlucHV0IGRhdGEgaXMgbm90IGNhY2hlZCBmb3IgdGhlIHNlc3Npb25cbiAgICBpZiAoIXRoaXMuY29udGV4dC5ncmFwaElucHV0VHlwZXMgfHwgdGhpcy5jb250ZXh0LmdyYXBoSW5wdXRUeXBlcy5sZW5ndGggPT09IDAgfHwgIXRoaXMuY29udGV4dC5ncmFwaElucHV0RGltcyB8fFxuICAgICAgICB0aGlzLmNvbnRleHQuZ3JhcGhJbnB1dERpbXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBjb25zdCBtb2RlbElucHV0SW5kaWNlcyA9IHRoaXMuX21vZGVsLmdyYXBoLmdldElucHV0SW5kaWNlcygpO1xuICAgICAgY29uc3QgbW9kZWxWYWx1ZXMgPSB0aGlzLl9tb2RlbC5ncmFwaC5nZXRWYWx1ZXMoKTtcblxuICAgICAgY29uc3QgZ3JhcGhJbnB1dERpbXMgPSBuZXcgQXJyYXk8cmVhZG9ubHkgbnVtYmVyW10+KG1vZGVsSW5wdXRJbmRpY2VzLmxlbmd0aCk7XG5cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbW9kZWxJbnB1dEluZGljZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgY29uc3QgZ3JhcGhJbnB1dCA9IG1vZGVsVmFsdWVzW21vZGVsSW5wdXRJbmRpY2VzW2ldXTtcbiAgICAgICAgZ3JhcGhJbnB1dERpbXNbaV0gPSBncmFwaElucHV0LnR5cGUhLnNoYXBlLmRpbXM7XG5cbiAgICAgICAgLy8gY2FjaGVkIGZvciBzZWNvbmQgYW5kIHN1YnNlcXVlbnQgcnVucy5cbiAgICAgICAgLy8gU29tZSBwYXJ0cyBvZiB0aGUgZnJhbWV3b3JrIHdvcmtzIG9uIHRoZSBhc3N1bXB0aW9uIHRoYXQgdGhlIGdyYXBoIGFuZCB0eXBlcyBhbmQgc2hhcGVzIGFyZSBzdGF0aWNcbiAgICAgICAgdGhpcy5jb250ZXh0LmdyYXBoSW5wdXRUeXBlcyEucHVzaChncmFwaElucHV0LnR5cGUhLnRlbnNvclR5cGUpO1xuICAgICAgICB0aGlzLmNvbnRleHQuZ3JhcGhJbnB1dERpbXMhLnB1c2goaW5wdXRzW2ldLmRpbXMpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnZhbGlkYXRlSW5wdXRUZW5zb3JEaW1zKGdyYXBoSW5wdXREaW1zLCBpbnB1dHMsIHRydWUpO1xuICAgIH1cblxuICAgIC8vIFNlY29uZCBhbmQgc3Vic2VxdWVudCBzZXNzaW9uIHJ1bnMgLSBncmFwaCBpbnB1dCBkYXRhIGlzIGNhY2hlZCBmb3IgdGhlIHNlc3Npb25cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMudmFsaWRhdGVJbnB1dFRlbnNvckRpbXModGhpcy5jb250ZXh0LmdyYXBoSW5wdXREaW1zLCBpbnB1dHMsIGZhbHNlKTtcbiAgICB9XG5cbiAgICAvLyB2YWxpZGF0ZSB0eXBlcyByZXF1aXJlbWVudFxuICAgIHRoaXMudmFsaWRhdGVJbnB1dFRlbnNvclR5cGVzKHRoaXMuY29udGV4dC5ncmFwaElucHV0VHlwZXMhLCBpbnB1dHMpO1xuXG4gICAgcmV0dXJuIGlucHV0cztcbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVJbnB1dFRlbnNvclR5cGVzKGdyYXBoSW5wdXRUeXBlczogVGVuc29yLkRhdGFUeXBlW10sIGdpdmVuSW5wdXRzOiBUZW5zb3JbXSkge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZ2l2ZW5JbnB1dHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGV4cGVjdGVkVHlwZSA9IGdyYXBoSW5wdXRUeXBlc1tpXTtcbiAgICAgIGNvbnN0IGFjdHVhbFR5cGUgPSBnaXZlbklucHV0c1tpXS50eXBlO1xuICAgICAgaWYgKGV4cGVjdGVkVHlwZSAhPT0gYWN0dWFsVHlwZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGlucHV0IHRlbnNvclske2l9XSBjaGVjayBmYWlsZWQ6IGV4cGVjdGVkIHR5cGUgJyR7ZXhwZWN0ZWRUeXBlfScgYnV0IGdvdCAke2FjdHVhbFR5cGV9YCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZUlucHV0VGVuc29yRGltcyhcbiAgICAgIGdyYXBoSW5wdXREaW1zOiBBcnJheTxyZWFkb25seSBudW1iZXJbXT4sIGdpdmVuSW5wdXRzOiBUZW5zb3JbXSwgbm9uZURpbVN1cHBvcnRlZDogYm9vbGVhbikge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZ2l2ZW5JbnB1dHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGV4cGVjdGVkRGltcyA9IGdyYXBoSW5wdXREaW1zW2ldO1xuICAgICAgY29uc3QgYWN0dWFsRGltcyA9IGdpdmVuSW5wdXRzW2ldLmRpbXM7XG4gICAgICBpZiAoIXRoaXMuY29tcGFyZVRlbnNvckRpbXMoZXhwZWN0ZWREaW1zLCBhY3R1YWxEaW1zLCBub25lRGltU3VwcG9ydGVkKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGlucHV0IHRlbnNvclske2l9XSBjaGVjayBmYWlsZWQ6IGV4cGVjdGVkIHNoYXBlICdbJHtleHBlY3RlZERpbXMuam9pbignLCcpfV0nIGJ1dCBnb3QgWyR7XG4gICAgICAgICAgICBhY3R1YWxEaW1zLmpvaW4oJywnKX1dYCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjb21wYXJlVGVuc29yRGltcyhleHBlY3RlZERpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBhY3R1YWxEaW1zOiByZWFkb25seSBudW1iZXJbXSwgbm9uZURpbVN1cHBvcnRlZDogYm9vbGVhbik6XG4gICAgICBib29sZWFuIHtcbiAgICBpZiAoZXhwZWN0ZWREaW1zLmxlbmd0aCAhPT0gYWN0dWFsRGltcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGV4cGVjdGVkRGltcy5sZW5ndGg7ICsraSkge1xuICAgICAgaWYgKGV4cGVjdGVkRGltc1tpXSAhPT0gYWN0dWFsRGltc1tpXSAmJiAoIW5vbmVEaW1TdXBwb3J0ZWQgfHwgZXhwZWN0ZWREaW1zW2ldICE9PSAwKSkge1xuICAgICAgICAvLyBkYXRhIHNoYXBlIG1pcy1tYXRjaCBBTkQgbm90IGEgJ05vbmUnIGRpbWVuc2lvbi5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVPdXRwdXQob3V0cHV0VGVuc29yczogVGVuc29yW10pOiBNYXA8c3RyaW5nLCBUZW5zb3I+IHtcbiAgICBjb25zdCBtb2RlbE91dHB1dE5hbWVzID0gdGhpcy5fbW9kZWwuZ3JhcGguZ2V0T3V0cHV0TmFtZXMoKTtcbiAgICBpZiAob3V0cHV0VGVuc29ycy5sZW5ndGggIT09IG1vZGVsT3V0cHV0TmFtZXMubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4cGVjdGVkIG51bWJlciBvZiBvdXRwdXRzIGRvIG5vdCBtYXRjaCBudW1iZXIgb2YgZ2VuZXJhdGVkIG91dHB1dHMnKTtcbiAgICB9XG5cbiAgICBjb25zdCBvdXRwdXQgPSBuZXcgTWFwPHN0cmluZywgVGVuc29yPigpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbW9kZWxPdXRwdXROYW1lcy5sZW5ndGg7ICsraSkge1xuICAgICAgb3V0cHV0LnNldChtb2RlbE91dHB1dE5hbWVzW2ldLCBvdXRwdXRUZW5zb3JzW2ldKTtcbiAgICB9XG5cbiAgICByZXR1cm4gb3V0cHV0O1xuICB9XG5cbiAgcHJpdmF0ZSBpbml0aWFsaXplT3BzKGdyYXBoOiBHcmFwaCk6IHZvaWQge1xuICAgIGNvbnN0IG5vZGVzID0gZ3JhcGguZ2V0Tm9kZXMoKTtcbiAgICB0aGlzLl9vcHMgPSBuZXcgQXJyYXkobm9kZXMubGVuZ3RoKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuX29wc1tpXSA9IHRoaXMuc2Vzc2lvbkhhbmRsZXIucmVzb2x2ZShub2Rlc1tpXSwgdGhpcy5fbW9kZWwub3BzZXRzLCBncmFwaCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfbW9kZWw6IE1vZGVsO1xuICBwcml2YXRlIF9pbml0aWFsaXplZDogYm9vbGVhbjtcblxuICBwcml2YXRlIF9vcHM6IE9wZXJhdG9yW107XG4gIHByaXZhdGUgX2V4ZWN1dGlvblBsYW46IEV4ZWN1dGlvblBsYW47XG5cbiAgcHJpdmF0ZSBiYWNrZW5kSGludD86IHN0cmluZztcblxuICBwcml2YXRlIHNlc3Npb25IYW5kbGVyOiBTZXNzaW9uSGFuZGxlclR5cGU7XG4gIHByaXZhdGUgY29udGV4dDogU2Vzc2lvbi5Db250ZXh0O1xuICBwcml2YXRlIHByb2ZpbGVyOiBSZWFkb25seTxQcm9maWxlcj47XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtHdWlkfSBmcm9tICdndWlkLXR5cGVzY3JpcHQnO1xuaW1wb3J0IExvbmcgZnJvbSAnbG9uZyc7XG5pbXBvcnQge29ubnh9IGZyb20gJ29ubngtcHJvdG8nO1xuXG5pbXBvcnQge29ubnhydW50aW1lfSBmcm9tICcuL29ydC1zY2hlbWEvb3J0LWdlbmVyYXRlZCc7XG5pbXBvcnQge2RlY29kZVV0ZjhTdHJpbmcsIFByb3RvVXRpbCwgU2hhcGVVdGlsfSBmcm9tICcuL3V0aWwnO1xuXG5pbXBvcnQgb3J0RmJzID0gb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicztcblxuZXhwb3J0IGRlY2xhcmUgbmFtZXNwYWNlIFRlbnNvciB7XG4gIGV4cG9ydCBpbnRlcmZhY2UgRGF0YVR5cGVNYXAge1xuICAgIGJvb2w6IFVpbnQ4QXJyYXk7XG4gICAgZmxvYXQzMjogRmxvYXQzMkFycmF5O1xuICAgIGZsb2F0NjQ6IEZsb2F0NjRBcnJheTtcbiAgICBzdHJpbmc6IHN0cmluZ1tdO1xuICAgIGludDg6IEludDhBcnJheTtcbiAgICB1aW50ODogVWludDhBcnJheTtcbiAgICBpbnQxNjogSW50MTZBcnJheTtcbiAgICB1aW50MTY6IFVpbnQxNkFycmF5O1xuICAgIGludDMyOiBJbnQzMkFycmF5O1xuICAgIHVpbnQzMjogVWludDMyQXJyYXk7XG4gIH1cblxuICBleHBvcnQgdHlwZSBEYXRhVHlwZSA9IGtleW9mIERhdGFUeXBlTWFwO1xuXG4gIGV4cG9ydCB0eXBlIFN0cmluZ1R5cGUgPSBUZW5zb3IuRGF0YVR5cGVNYXBbJ3N0cmluZyddO1xuICBleHBvcnQgdHlwZSBCb29sZWFuVHlwZSA9IFRlbnNvci5EYXRhVHlwZU1hcFsnYm9vbCddO1xuICBleHBvcnQgdHlwZSBJbnRlZ2VyVHlwZSA9IFRlbnNvci5EYXRhVHlwZU1hcFsnaW50OCddfFRlbnNvci5EYXRhVHlwZU1hcFsndWludDgnXXxUZW5zb3IuRGF0YVR5cGVNYXBbJ2ludDE2J118XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgVGVuc29yLkRhdGFUeXBlTWFwWyd1aW50MTYnXXxUZW5zb3IuRGF0YVR5cGVNYXBbJ2ludDMyJ118VGVuc29yLkRhdGFUeXBlTWFwWyd1aW50MzInXTtcbiAgZXhwb3J0IHR5cGUgRmxvYXRUeXBlID0gVGVuc29yLkRhdGFUeXBlTWFwWydmbG9hdDMyJ118VGVuc29yLkRhdGFUeXBlTWFwWydmbG9hdDY0J107XG4gIGV4cG9ydCB0eXBlIE51bWJlclR5cGUgPSBCb29sZWFuVHlwZXxJbnRlZ2VyVHlwZXxGbG9hdFR5cGU7XG5cbiAgZXhwb3J0IHR5cGUgSWQgPSBHdWlkO1xufVxuXG50eXBlIFRlbnNvckRhdGEgPSBUZW5zb3IuRGF0YVR5cGVNYXBbVGVuc29yLkRhdGFUeXBlXTtcblxudHlwZSBEYXRhUHJvdmlkZXIgPSAoaWQ6IFRlbnNvci5JZCkgPT4gVGVuc29yRGF0YTtcbnR5cGUgQXN5bmNEYXRhUHJvdmlkZXIgPSAoaWQ6IFRlbnNvci5JZCkgPT4gUHJvbWlzZTxUZW5zb3JEYXRhPjtcblxuZXhwb3J0IGNsYXNzIFRlbnNvciB7XG4gIC8qKlxuICAgKiBnZXQgdGhlIHVuZGVybHlpbmcgdGVuc29yIGRhdGFcbiAgICovXG4gIGdldCBkYXRhKCk6IFRlbnNvckRhdGEge1xuICAgIGlmICh0aGlzLmNhY2hlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLmRhdGFQcm92aWRlciEodGhpcy5kYXRhSWQpO1xuICAgICAgaWYgKGRhdGEubGVuZ3RoICE9PSB0aGlzLnNpemUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdMZW5ndGggb2YgZGF0YSBwcm92aWRlZCBieSB0aGUgRGF0YSBQcm92aWRlciBpcyBpbmNvbnNpc3RlbnQgd2l0aCB0aGUgZGltcyBvZiB0aGlzIFRlbnNvci4nKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuY2FjaGUgPSBkYXRhO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jYWNoZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBnZXQgdGhlIHVuZGVybHlpbmcgc3RyaW5nIHRlbnNvciBkYXRhLiBTaG91bGQgb25seSB1c2Ugd2hlbiB0eXBlIGlzIFNUUklOR1xuICAgKi9cbiAgZ2V0IHN0cmluZ0RhdGEoKSB7XG4gICAgaWYgKHRoaXMudHlwZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RhdGEgdHlwZSBpcyBub3Qgc3RyaW5nJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZGF0YSBhcyBUZW5zb3IuU3RyaW5nVHlwZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBnZXQgdGhlIHVuZGVybHlpbmcgaW50ZWdlciB0ZW5zb3IgZGF0YS4gU2hvdWxkIG9ubHkgdXNlIHdoZW4gdHlwZSBpcyBvbmUgb2YgdGhlIGZvbGxvd2luZzogKFVJTlQ4LCBJTlQ4LCBVSU5UMTYsXG4gICAqIElOVDE2LCBJTlQzMiwgVUlOVDMyLCBCT09MKVxuICAgKi9cbiAgZ2V0IGludGVnZXJEYXRhKCkge1xuICAgIHN3aXRjaCAodGhpcy50eXBlKSB7XG4gICAgICBjYXNlICd1aW50OCc6XG4gICAgICBjYXNlICdpbnQ4JzpcbiAgICAgIGNhc2UgJ3VpbnQxNic6XG4gICAgICBjYXNlICdpbnQxNic6XG4gICAgICBjYXNlICdpbnQzMic6XG4gICAgICBjYXNlICd1aW50MzInOlxuICAgICAgY2FzZSAnYm9vbCc6XG4gICAgICAgIHJldHVybiB0aGlzLmRhdGEgYXMgVGVuc29yLkludGVnZXJUeXBlO1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXRhIHR5cGUgaXMgbm90IGludGVnZXIgKHVpbnQ4LCBpbnQ4LCB1aW50MTYsIGludDE2LCBpbnQzMiwgdWludDMyLCBib29sKScpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBnZXQgdGhlIHVuZGVybHlpbmcgZmxvYXQgdGVuc29yIGRhdGEuIFNob3VsZCBvbmx5IHVzZSB3aGVuIHR5cGUgaXMgb25lIG9mIHRoZSBmb2xsb3dpbmc6IChGTE9BVCwgRE9VQkxFKVxuICAgKi9cbiAgZ2V0IGZsb2F0RGF0YSgpIHtcbiAgICBzd2l0Y2ggKHRoaXMudHlwZSkge1xuICAgICAgY2FzZSAnZmxvYXQzMic6XG4gICAgICBjYXNlICdmbG9hdDY0JzpcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF0YSBhcyBUZW5zb3IuRmxvYXRUeXBlO1xuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXRhIHR5cGUgaXMgbm90IGZsb2F0IChmbG9hdDMyLCBmbG9hdDY0KScpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBnZXQgdGhlIHVuZGVybHlpbmcgbnVtYmVyIHRlbnNvciBkYXRhLiBTaG91bGQgb25seSB1c2Ugd2hlbiB0eXBlIGlzIG9uZSBvZiB0aGUgZm9sbG93aW5nOiAoVUlOVDgsIElOVDgsIFVJTlQxNixcbiAgICogSU5UMTYsIElOVDMyLCBVSU5UMzIsIEJPT0wsIEZMT0FULCBET1VCTEUpXG4gICAqL1xuICBnZXQgbnVtYmVyRGF0YSgpIHtcbiAgICBpZiAodGhpcy50eXBlICE9PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIHRoaXMuZGF0YSBhcyBUZW5zb3IuTnVtYmVyVHlwZTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndHlwZSBjYW5ub3QgYmUgbm9uLW51bWJlciAoc3RyaW5nKScpO1xuICB9XG5cbiAgLyoqXG4gICAqIGdldCB2YWx1ZSBvZiBhbiBlbGVtZW50IGF0IHRoZSBnaXZlbiBpbmRpY2VzXG4gICAqL1xuICBnZXQoaW5kaWNlczogcmVhZG9ubHkgbnVtYmVyW10pOiBUZW5zb3IuRGF0YVR5cGVNYXBbVGVuc29yLkRhdGFUeXBlXVtudW1iZXJdIHtcbiAgICByZXR1cm4gdGhpcy5kYXRhW1NoYXBlVXRpbC5pbmRpY2VzVG9PZmZzZXQoaW5kaWNlcywgdGhpcy5zdHJpZGVzKV07XG4gIH1cblxuICAvKipcbiAgICogc2V0IHZhbHVlIG9mIGFuIGVsZW1lbnQgYXQgdGhlIGdpdmVuIGluZGljZXNcbiAgICovXG4gIHNldChpbmRpY2VzOiByZWFkb25seSBudW1iZXJbXSwgdmFsdWU6IFRlbnNvci5EYXRhVHlwZU1hcFtUZW5zb3IuRGF0YVR5cGVdW251bWJlcl0pIHtcbiAgICB0aGlzLmRhdGFbU2hhcGVVdGlsLmluZGljZXNUb09mZnNldChpbmRpY2VzLCB0aGlzLnN0cmlkZXMpXSA9IHZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIGdldCB0aGUgdW5kZXJseWluZyB0ZW5zb3IgZGF0YSBhc3luY2hyb25vdXNseVxuICAgKi9cbiAgYXN5bmMgZ2V0RGF0YSgpOiBQcm9taXNlPFRlbnNvckRhdGE+IHtcbiAgICBpZiAodGhpcy5jYWNoZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmNhY2hlID0gYXdhaXQgdGhpcy5hc3luY0RhdGFQcm92aWRlciEodGhpcy5kYXRhSWQpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jYWNoZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBnZXQgdGhlIG51bWJlciBvZiBlbGVtZW50cyBpbiB0aGUgdGVuc29yXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgc2l6ZTogbnVtYmVyO1xuXG4gIHByaXZhdGUgX3N0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdO1xuICAvKipcbiAgICogZ2V0IHRoZSBzdHJpZGVzIGZvciBlYWNoIGRpbWVuc2lvblxuICAgKi9cbiAgZ2V0IHN0cmlkZXMoKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIGlmICghdGhpcy5fc3RyaWRlcykge1xuICAgICAgdGhpcy5fc3RyaWRlcyA9IFNoYXBlVXRpbC5jb21wdXRlU3RyaWRlcyh0aGlzLmRpbXMpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fc3RyaWRlcztcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgICAgLyoqXG4gICAgICAgKiBnZXQgdGhlIGRpbWVuc2lvbnMgb2YgdGhlIHRlbnNvclxuICAgICAgICovXG4gICAgICBwdWJsaWMgcmVhZG9ubHkgZGltczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgICAvKipcbiAgICAgICAqIGdldCB0aGUgdHlwZSBvZiB0aGUgdGVuc29yXG4gICAgICAgKi9cbiAgICAgIHB1YmxpYyByZWFkb25seSB0eXBlOiBUZW5zb3IuRGF0YVR5cGUsIHByaXZhdGUgZGF0YVByb3ZpZGVyPzogRGF0YVByb3ZpZGVyLFxuICAgICAgcHJpdmF0ZSBhc3luY0RhdGFQcm92aWRlcj86IEFzeW5jRGF0YVByb3ZpZGVyLCBwcml2YXRlIGNhY2hlPzogVGVuc29yRGF0YSxcbiAgICAgIC8qKlxuICAgICAgICogZ2V0IHRoZSBkYXRhIElEIHRoYXQgdXNlZCB0byBtYXAgdG8gYSB0ZW5zb3IgZGF0YVxuICAgICAgICovXG4gICAgICBwdWJsaWMgcmVhZG9ubHkgZGF0YUlkOiBHdWlkID0gR3VpZC5jcmVhdGUoKSkge1xuICAgIHRoaXMuc2l6ZSA9IFNoYXBlVXRpbC52YWxpZGF0ZURpbXNBbmRDYWxjU2l6ZShkaW1zKTtcbiAgICBjb25zdCBzaXplID0gdGhpcy5zaXplO1xuICAgIGNvbnN0IGVtcHR5ID0gKGRhdGFQcm92aWRlciA9PT0gdW5kZWZpbmVkICYmIGFzeW5jRGF0YVByb3ZpZGVyID09PSB1bmRlZmluZWQgJiYgY2FjaGUgPT09IHVuZGVmaW5lZCk7XG5cbiAgICBpZiAoY2FjaGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKGNhY2hlLmxlbmd0aCAhPT0gc2l6ZSkge1xuICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW5wdXQgZGltcyBkb2VzblxcJ3QgbWF0Y2ggZGF0YSBsZW5ndGguJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICBpZiAoY2FjaGUgIT09IHVuZGVmaW5lZCAmJiAoIUFycmF5LmlzQXJyYXkoY2FjaGUpIHx8ICFjYWNoZS5ldmVyeShpID0+IHR5cGVvZiBpID09PSAnc3RyaW5nJykpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2NhY2hlIHNob3VsZCBiZSBhIHN0cmluZyBhcnJheScpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZW1wdHkpIHtcbiAgICAgICAgdGhpcy5jYWNoZSA9IG5ldyBBcnJheTxzdHJpbmc+KHNpemUpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoY2FjaGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBjb25zdCBjb25zdHJ1Y3RvciA9IGRhdGF2aWV3Q29uc3RydWN0b3IodHlwZSk7XG4gICAgICAgIGlmICghKGNhY2hlIGluc3RhbmNlb2YgY29uc3RydWN0b3IpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgY2FjaGUgc2hvdWxkIGJlIHR5cGUgJHtjb25zdHJ1Y3Rvci5uYW1lfWApO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChlbXB0eSkge1xuICAgICAgICBjb25zdCBidWYgPSBuZXcgQXJyYXlCdWZmZXIoc2l6ZSAqIHNpemVvZih0eXBlKSk7XG4gICAgICAgIHRoaXMuY2FjaGUgPSBjcmVhdGVWaWV3KGJ1ZiwgdHlwZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdCBuZXcgVGVuc29yIGZyb20gYSBPTk5YIFRlbnNvciBvYmplY3RcbiAgICogQHBhcmFtIHRlbnNvclByb3RvIHRoZSBPTk5YIFRlbnNvclxuICAgKi9cbiAgc3RhdGljIGZyb21Qcm90byh0ZW5zb3JQcm90bzogb25ueC5JVGVuc29yUHJvdG8pOiBUZW5zb3Ige1xuICAgIGlmICghdGVuc29yUHJvdG8pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY2Fubm90IGNvbnN0cnVjdCBWYWx1ZSBmcm9tIGFuIGVtcHR5IHRlbnNvcicpO1xuICAgIH1cbiAgICBjb25zdCB0eXBlID0gUHJvdG9VdGlsLnRlbnNvckRhdGFUeXBlRnJvbVByb3RvKHRlbnNvclByb3RvLmRhdGFUeXBlISk7XG4gICAgY29uc3QgZGltcyA9IFByb3RvVXRpbC50ZW5zb3JEaW1zRnJvbVByb3RvKHRlbnNvclByb3RvLmRpbXMhKTtcblxuICAgIGNvbnN0IHZhbHVlID0gbmV3IFRlbnNvcihkaW1zLCB0eXBlKTtcblxuICAgIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgLy8gV2hlbiBpdCdzIFNUUklORyB0eXBlLCB0aGUgdmFsdWUgc2hvdWxkIGFsd2F5cyBiZSBzdG9yZWQgaW4gZmllbGRcbiAgICAgIC8vICdzdHJpbmdEYXRhJ1xuICAgICAgdGVuc29yUHJvdG8uc3RyaW5nRGF0YSEuZm9yRWFjaCgoc3RyLCBpKSA9PiB7XG4gICAgICAgIHZhbHVlLmRhdGFbaV0gPSBkZWNvZGVVdGY4U3RyaW5nKHN0cik7XG4gICAgICB9KTtcblxuICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIHRlbnNvclByb3RvLnJhd0RhdGEgJiYgdHlwZW9mIHRlbnNvclByb3RvLnJhd0RhdGEuYnl0ZUxlbmd0aCA9PT0gJ251bWJlcicgJiZcbiAgICAgICAgdGVuc29yUHJvdG8ucmF3RGF0YS5ieXRlTGVuZ3RoID4gMCkge1xuICAgICAgLy8gTk9UIGNvbnNpZGVyaW5nIHNlZ21lbnQgZm9yIG5vdyAoSU1QT1JUQU5UKVxuXG4gICAgICAvLyBwb3B1bGF0ZSB2YWx1ZSBmcm9tIHJhd0RhdGFcbiAgICAgIGNvbnN0IGRhdGFEZXN0ID0gdmFsdWUuZGF0YTtcbiAgICAgIGNvbnN0IGRhdGFTb3VyY2UgPVxuICAgICAgICAgIG5ldyBEYXRhVmlldyh0ZW5zb3JQcm90by5yYXdEYXRhLmJ1ZmZlciwgdGVuc29yUHJvdG8ucmF3RGF0YS5ieXRlT2Zmc2V0LCB0ZW5zb3JQcm90by5yYXdEYXRhLmJ5dGVMZW5ndGgpO1xuICAgICAgY29uc3QgZWxlbWVudFNpemUgPSBzaXplb2ZQcm90byh0ZW5zb3JQcm90by5kYXRhVHlwZSEpO1xuICAgICAgY29uc3QgbGVuZ3RoID0gdGVuc29yUHJvdG8ucmF3RGF0YS5ieXRlTGVuZ3RoIC8gZWxlbWVudFNpemU7XG5cbiAgICAgIGlmICh0ZW5zb3JQcm90by5yYXdEYXRhLmJ5dGVMZW5ndGggJSBlbGVtZW50U2l6ZSAhPT0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgYnVmZmVyIGxlbmd0aCcpO1xuICAgICAgfVxuICAgICAgaWYgKGRhdGFEZXN0Lmxlbmd0aCAhPT0gbGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYnVmZmVyIGxlbmd0aCBtaXNtYXRjaCcpO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IG4gPSByZWFkUHJvdG8oZGF0YVNvdXJjZSwgdGVuc29yUHJvdG8uZGF0YVR5cGUhLCBpICogZWxlbWVudFNpemUpO1xuICAgICAgICBkYXRhRGVzdFtpXSA9IG47XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHBvcHVsYXRlIHZhbHVlIGZyb20gYXJyYXlcbiAgICAgIGxldCBhcnJheTogQXJyYXk8bnVtYmVyfExvbmc+O1xuICAgICAgc3dpdGNoICh0ZW5zb3JQcm90by5kYXRhVHlwZSkge1xuICAgICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuRkxPQVQ6XG4gICAgICAgICAgYXJyYXkgPSB0ZW5zb3JQcm90by5mbG9hdERhdGEhO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UMzI6XG4gICAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQxNjpcbiAgICAgICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLlVJTlQxNjpcbiAgICAgICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLklOVDg6XG4gICAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UODpcbiAgICAgICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLkJPT0w6XG4gICAgICAgICAgYXJyYXkgPSB0ZW5zb3JQcm90by5pbnQzMkRhdGEhO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UNjQ6XG4gICAgICAgICAgYXJyYXkgPSB0ZW5zb3JQcm90by5pbnQ2NERhdGEhO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuRE9VQkxFOlxuICAgICAgICAgIGFycmF5ID0gdGVuc29yUHJvdG8uZG91YmxlRGF0YSE7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UMzI6XG4gICAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UNjQ6XG4gICAgICAgICAgYXJyYXkgPSB0ZW5zb3JQcm90by51aW50NjREYXRhITtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAvLyBzaG91bGQgbmV2ZXIgcnVuIGhlcmVcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Vuc3BlY2lmaWMgZXJyb3InKTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFycmF5ID09PSBudWxsIHx8IGFycmF5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdmYWlsZWQgdG8gcG9wdWxhdGUgZGF0YSBmcm9tIGEgdGVuc29ycHJvdG8gdmFsdWUnKTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGF0YSA9IHZhbHVlLmRhdGE7XG4gICAgICBpZiAoZGF0YS5sZW5ndGggIT09IGFycmF5Lmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2FycmF5IGxlbmd0aCBtaXNtYXRjaCcpO1xuICAgICAgfVxuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnQgPSBhcnJheVtpXTtcbiAgICAgICAgaWYgKExvbmcuaXNMb25nKGVsZW1lbnQpKSB7XG4gICAgICAgICAgZGF0YVtpXSA9IGxvbmdUb051bWJlcihlbGVtZW50LCB0ZW5zb3JQcm90by5kYXRhVHlwZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZGF0YVtpXSA9IGVsZW1lbnQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogQ29uc3RydWN0IG5ldyBUZW5zb3IgZnJvbSByYXcgZGF0YVxuICAgKiBAcGFyYW0gZGF0YSB0aGUgcmF3IGRhdGEgb2JqZWN0LiBTaG91bGQgYmUgYSBzdHJpbmcgYXJyYXkgZm9yICdzdHJpbmcnIHRlbnNvciwgYW5kIHRoZSBjb3JyZXNwb25kaW5nIHR5cGVkIGFycmF5XG4gICAqIGZvciBvdGhlciB0eXBlcyBvZiB0ZW5zb3IuXG4gICAqIEBwYXJhbSBkaW1zIHRoZSBkaW1lbnNpb25zIG9mIHRoZSB0ZW5zb3JcbiAgICogQHBhcmFtIHR5cGUgdGhlIHR5cGUgb2YgdGhlIHRlbnNvclxuICAgKi9cbiAgc3RhdGljIGZyb21EYXRhKGRhdGE6IFRlbnNvci5EYXRhVHlwZU1hcFtUZW5zb3IuRGF0YVR5cGVdLCBkaW1zOiByZWFkb25seSBudW1iZXJbXSwgdHlwZTogVGVuc29yLkRhdGFUeXBlKSB7XG4gICAgcmV0dXJuIG5ldyBUZW5zb3IoZGltcywgdHlwZSwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIGRhdGEpO1xuICB9XG5cbiAgc3RhdGljIGZyb21PcnRUZW5zb3Iob3J0VGVuc29yOiBvcnRGYnMuVGVuc29yKSB7XG4gICAgaWYgKCFvcnRUZW5zb3IpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY2Fubm90IGNvbnN0cnVjdCBWYWx1ZSBmcm9tIGFuIGVtcHR5IHRlbnNvcicpO1xuICAgIH1cbiAgICBjb25zdCBkaW1zID0gUHJvdG9VdGlsLnRlbnNvckRpbXNGcm9tT1JURm9ybWF0KG9ydFRlbnNvcik7XG4gICAgY29uc3QgdHlwZSA9IFByb3RvVXRpbC50ZW5zb3JEYXRhVHlwZUZyb21Qcm90byhvcnRUZW5zb3IuZGF0YVR5cGUoKSk7XG5cbiAgICBjb25zdCB2YWx1ZSA9IG5ldyBUZW5zb3IoZGltcywgdHlwZSk7XG5cbiAgICBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIC8vIFdoZW4gaXQncyBTVFJJTkcgdHlwZSwgdGhlIHZhbHVlIHNob3VsZCBhbHdheXMgYmUgc3RvcmVkIGluIGZpZWxkXG4gICAgICAvLyAnc3RyaW5nRGF0YSdcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3J0VGVuc29yLnN0cmluZ0RhdGFMZW5ndGgoKTsgaSsrKSB7XG4gICAgICAgIHZhbHVlLmRhdGFbaV0gPSBvcnRUZW5zb3Iuc3RyaW5nRGF0YShpKTtcbiAgICAgIH1cblxuICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIG9ydFRlbnNvci5yYXdEYXRhQXJyYXkoKSAmJiB0eXBlb2Ygb3J0VGVuc29yLnJhd0RhdGFMZW5ndGgoKSA9PT0gJ251bWJlcicgJiYgb3J0VGVuc29yLnJhd0RhdGFMZW5ndGgoKSA+IDApIHtcbiAgICAgIC8vIE5PVCBjb25zaWRlcmluZyBzZWdtZW50IGZvciBub3cgKElNUE9SVEFOVClcblxuICAgICAgLy8gcG9wdWxhdGUgdmFsdWUgZnJvbSByYXdEYXRhXG4gICAgICBjb25zdCBkYXRhRGVzdCA9IHZhbHVlLmRhdGE7XG4gICAgICBjb25zdCBkYXRhU291cmNlID0gbmV3IERhdGFWaWV3KFxuICAgICAgICAgIG9ydFRlbnNvci5yYXdEYXRhQXJyYXkoKSEuYnVmZmVyLCBvcnRUZW5zb3IucmF3RGF0YUFycmF5KCkhLmJ5dGVPZmZzZXQsIG9ydFRlbnNvci5yYXdEYXRhTGVuZ3RoKCkpO1xuICAgICAgY29uc3QgZWxlbWVudFNpemUgPSBzaXplb2ZQcm90byhvcnRUZW5zb3IuZGF0YVR5cGUoKSk7XG4gICAgICBjb25zdCBsZW5ndGggPSBvcnRUZW5zb3IucmF3RGF0YUxlbmd0aCgpIC8gZWxlbWVudFNpemU7XG5cbiAgICAgIGlmIChvcnRUZW5zb3IucmF3RGF0YUxlbmd0aCgpICUgZWxlbWVudFNpemUgIT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGJ1ZmZlciBsZW5ndGgnKTtcbiAgICAgIH1cbiAgICAgIGlmIChkYXRhRGVzdC5sZW5ndGggIT09IGxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2J1ZmZlciBsZW5ndGggbWlzbWF0Y2gnKTtcbiAgICAgIH1cblxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBuID0gcmVhZFByb3RvKGRhdGFTb3VyY2UsIG9ydFRlbnNvci5kYXRhVHlwZSgpLCBpICogZWxlbWVudFNpemUpO1xuICAgICAgICBkYXRhRGVzdFtpXSA9IG47XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxufVxuXG5mdW5jdGlvbiBzaXplb2YodHlwZTogVGVuc29yLkRhdGFUeXBlKTogbnVtYmVyIHtcbiAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSAnYm9vbCc6XG4gICAgY2FzZSAnaW50OCc6XG4gICAgY2FzZSAndWludDgnOlxuICAgICAgcmV0dXJuIDE7XG4gICAgY2FzZSAnaW50MTYnOlxuICAgIGNhc2UgJ3VpbnQxNic6XG4gICAgICByZXR1cm4gMjtcbiAgICBjYXNlICdpbnQzMic6XG4gICAgY2FzZSAndWludDMyJzpcbiAgICBjYXNlICdmbG9hdDMyJzpcbiAgICAgIHJldHVybiA0O1xuICAgIGNhc2UgJ2Zsb2F0NjQnOlxuICAgICAgcmV0dXJuIDg7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgY2Fubm90IGNhbGN1bGF0ZSBzaXplb2YoKSBvbiB0eXBlICR7dHlwZX1gKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBzaXplb2ZQcm90byh0eXBlOiBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlfG9ydEZicy5UZW5zb3JEYXRhVHlwZSk6IG51bWJlciB7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UODpcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UODpcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuQk9PTDpcbiAgICAgIHJldHVybiAxO1xuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UMTY6XG4gICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLklOVDE2OlxuICAgICAgcmV0dXJuIDI7XG4gICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLkZMT0FUOlxuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQzMjpcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDMyOlxuICAgICAgcmV0dXJuIDQ7XG4gICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLklOVDY0OlxuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5ET1VCTEU6XG4gICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLlVJTlQ2NDpcbiAgICAgIHJldHVybiA4O1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGNhbm5vdCBjYWxjdWxhdGUgc2l6ZW9mKCkgb24gdHlwZSAke29ubnguVGVuc29yUHJvdG8uRGF0YVR5cGVbdHlwZV19YCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY3JlYXRlVmlldyhkYXRhQnVmZmVyOiBBcnJheUJ1ZmZlciwgdHlwZTogVGVuc29yLkRhdGFUeXBlKSB7XG4gIHJldHVybiBuZXcgKGRhdGF2aWV3Q29uc3RydWN0b3IodHlwZSkpKGRhdGFCdWZmZXIpO1xufVxuXG5mdW5jdGlvbiBkYXRhdmlld0NvbnN0cnVjdG9yKHR5cGU6IFRlbnNvci5EYXRhVHlwZSkge1xuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlICdib29sJzpcbiAgICBjYXNlICd1aW50OCc6XG4gICAgICByZXR1cm4gVWludDhBcnJheTtcbiAgICBjYXNlICdpbnQ4JzpcbiAgICAgIHJldHVybiBJbnQ4QXJyYXk7XG4gICAgY2FzZSAnaW50MTYnOlxuICAgICAgcmV0dXJuIEludDE2QXJyYXk7XG4gICAgY2FzZSAndWludDE2JzpcbiAgICAgIHJldHVybiBVaW50MTZBcnJheTtcbiAgICBjYXNlICdpbnQzMic6XG4gICAgICByZXR1cm4gSW50MzJBcnJheTtcbiAgICBjYXNlICd1aW50MzInOlxuICAgICAgcmV0dXJuIFVpbnQzMkFycmF5O1xuICAgIGNhc2UgJ2Zsb2F0MzInOlxuICAgICAgcmV0dXJuIEZsb2F0MzJBcnJheTtcbiAgICBjYXNlICdmbG9hdDY0JzpcbiAgICAgIHJldHVybiBGbG9hdDY0QXJyYXk7XG4gICAgZGVmYXVsdDpcbiAgICAgIC8vIHNob3VsZCBuZXZlciBydW4gdG8gaGVyZVxuICAgICAgdGhyb3cgbmV3IEVycm9yKCd1bnNwZWNpZmllZCBlcnJvcicpO1xuICB9XG59XG5cbi8vIGNvbnZlcnQgYSBsb25nIG51bWJlciB0byBhIDMyLWJpdCBpbnRlZ2VyIChjYXN0LWRvd24pXG5mdW5jdGlvbiBsb25nVG9OdW1iZXIoaTogTG9uZywgdHlwZTogb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZXxvcnRGYnMuVGVuc29yRGF0YVR5cGUpOiBudW1iZXIge1xuICAvLyBJTlQ2NCwgVUlOVDMyLCBVSU5UNjRcbiAgaWYgKHR5cGUgPT09IG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UNjQgfHwgdHlwZSA9PT0gb3J0RmJzLlRlbnNvckRhdGFUeXBlLklOVDY0KSB7XG4gICAgaWYgKGkuZ3JlYXRlclRoYW5PckVxdWFsKDIxNDc0ODM2NDgpIHx8IGkubGVzc1RoYW4oLTIxNDc0ODM2NDgpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpbnQ2NCBpcyBub3Qgc3VwcG9ydGVkJyk7XG4gICAgfVxuICB9IGVsc2UgaWYgKFxuICAgICAgdHlwZSA9PT0gb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UMzIgfHwgdHlwZSA9PT0gb3J0RmJzLlRlbnNvckRhdGFUeXBlLlVJTlQzMiB8fFxuICAgICAgdHlwZSA9PT0gb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UNjQgfHwgdHlwZSA9PT0gb3J0RmJzLlRlbnNvckRhdGFUeXBlLlVJTlQ2NCkge1xuICAgIGlmIChpLmdyZWF0ZXJUaGFuT3JFcXVhbCg0Mjk0OTY3Mjk2KSB8fCBpLmxlc3NUaGFuKDApKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd1aW50NjQgaXMgbm90IHN1cHBvcnRlZCcpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBub3QgYSBMT05HIHR5cGU6ICR7b25ueC5UZW5zb3JQcm90by5EYXRhVHlwZVt0eXBlXX1gKTtcbiAgfVxuXG4gIHJldHVybiBpLnRvTnVtYmVyKCk7XG59XG5cbi8vIHJlYWQgb25lIHZhbHVlIGZyb20gVGVuc29yUHJvdG9cbmZ1bmN0aW9uIHJlYWRQcm90byh2aWV3OiBEYXRhVmlldywgdHlwZTogb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZXxvcnRGYnMuVGVuc29yRGF0YVR5cGUsIGJ5dGVPZmZzZXQ6IG51bWJlcik6IG51bWJlciB7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5CT09MOlxuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UODpcbiAgICAgIHJldHVybiB2aWV3LmdldFVpbnQ4KGJ5dGVPZmZzZXQpO1xuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQ4OlxuICAgICAgcmV0dXJuIHZpZXcuZ2V0SW50OChieXRlT2Zmc2V0KTtcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDE2OlxuICAgICAgcmV0dXJuIHZpZXcuZ2V0VWludDE2KGJ5dGVPZmZzZXQsIHRydWUpO1xuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQxNjpcbiAgICAgIHJldHVybiB2aWV3LmdldEludDE2KGJ5dGVPZmZzZXQsIHRydWUpO1xuICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5GTE9BVDpcbiAgICAgIHJldHVybiB2aWV3LmdldEZsb2F0MzIoYnl0ZU9mZnNldCwgdHJ1ZSk7XG4gICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLklOVDMyOlxuICAgICAgcmV0dXJuIHZpZXcuZ2V0SW50MzIoYnl0ZU9mZnNldCwgdHJ1ZSk7XG4gICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLlVJTlQzMjpcbiAgICAgIHJldHVybiB2aWV3LmdldFVpbnQzMihieXRlT2Zmc2V0LCB0cnVlKTtcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UNjQ6XG4gICAgICByZXR1cm4gbG9uZ1RvTnVtYmVyKFxuICAgICAgICAgIExvbmcuZnJvbUJpdHModmlldy5nZXRVaW50MzIoYnl0ZU9mZnNldCwgdHJ1ZSksIHZpZXcuZ2V0VWludDMyKGJ5dGVPZmZzZXQgKyA0LCB0cnVlKSwgZmFsc2UpLCB0eXBlKTtcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuRE9VQkxFOlxuICAgICAgcmV0dXJuIHZpZXcuZ2V0RmxvYXQ2NChieXRlT2Zmc2V0LCB0cnVlKTtcbiAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDY0OlxuICAgICAgcmV0dXJuIGxvbmdUb051bWJlcihcbiAgICAgICAgICBMb25nLmZyb21CaXRzKHZpZXcuZ2V0VWludDMyKGJ5dGVPZmZzZXQsIHRydWUpLCB2aWV3LmdldFVpbnQzMihieXRlT2Zmc2V0ICsgNCwgdHJ1ZSksIHRydWUpLCB0eXBlKTtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBjYW5ub3QgcmVhZCBmcm9tIERhdGFWaWV3IGZvciB0eXBlICR7b25ueC5UZW5zb3JQcm90by5EYXRhVHlwZVt0eXBlXX1gKTtcbiAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7ZmxhdGJ1ZmZlcnN9IGZyb20gJ2ZsYXRidWZmZXJzJztcbmltcG9ydCBMb25nIGZyb20gJ2xvbmcnO1xuaW1wb3J0IHtvbm54fSBmcm9tICdvbm54LXByb3RvJztcblxuaW1wb3J0IHtHcmFwaH0gZnJvbSAnLi9ncmFwaCc7XG5pbXBvcnQge29ubnhydW50aW1lfSBmcm9tICcuL29ydC1zY2hlbWEvb3J0LWdlbmVyYXRlZCc7XG5pbXBvcnQge1RlbnNvcn0gZnJvbSAnLi90ZW5zb3InO1xuXG4vLyBjaGVjayB0aGUgaW5wdXRzIHNoYXBlIGJlZm9yZSBydW5uaW5nIGFuIE9QLlxuLy8gcmV0dXJuIHRydWUgd2hlbiB0aGUgaW5wdXRzIHBhc3MgdGhlIGNoZWNrXG4vLyByZXR1cm4gZmFsc2Ugd2hlbiB0aGUgaW5wdXRzIGRvIG5vdCBmaXQgdGhlIHJlcXVpcmVtZW50XG4vLyB0aHJvdyBleGNlcHRpb24gd2hlbiBmYXRhbCBlcnJvciBvciBub3QgaW1wbGVtZW50ZWRcbmV4cG9ydCBmdW5jdGlvbiBjaGVja0lucHV0c1NoYXBlKGlucHV0czogVGVuc29yW10sIC4uLmV4cGVjdGVkRGltZW5zaW9uczogbnVtYmVyW10pOiBib29sZWFuIHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gZXhwZWN0ZWREaW1lbnNpb25zLmxlbmd0aCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0cy5sZW5ndGg7IGkrKykge1xuICAgIGlmICghaW5wdXRzW2ldLmRpbXMgfHwgaW5wdXRzW2ldLmRpbXMubGVuZ3RoICE9PSBleHBlY3RlZERpbWVuc2lvbnNbaV0pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cbi8vIEV2YWx1YXRlcyB0aGUgZ2l2ZW4gZXhwcmVzc2lvbiBhbmQgYXNzZXJ0cyBlcnJvciBtZXNzYWdlIGlmIGNvbmRpdGlvbiBpcyB1bm1ldC5cbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnQoZXhwcjogYm9vbGVhbiwgbXNnOiAoKSA9PiBzdHJpbmcpIHtcbiAgaWYgKCFleHByKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKHR5cGVvZiBtc2cgPT09ICdzdHJpbmcnID8gbXNnIDogbXNnKCkpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBBcnJheVV0aWwge1xuICAvKipcbiAgICogVmVyaWZpZXMgaWYgMiBpbnB1dCBhcnJheXMgY29udGFpbiB0aGUgc2FtZSBlbGVtZW50cy5cbiAgICogQHBhcmFtIG4xIEFycmF5IDFcbiAgICogQHBhcmFtIG4yIEFycmF5IDJcbiAgICogQHJldHVybnMgV2hldGhlciB0aGVzZSAyIGFyZSBlcXVhbFxuICAgKi9cbiAgc3RhdGljIGFycmF5c0VxdWFsKFxuICAgICAgbjE6IHJlYWRvbmx5IG51bWJlcltdfEludDhBcnJheXxVaW50OEFycmF5fEludDE2QXJyYXl8VWludDE2QXJyYXl8SW50MzJBcnJheXxVaW50MzJBcnJheXxVaW50OENsYW1wZWRBcnJheXxcbiAgICAgIEZsb2F0MzJBcnJheXxGbG9hdDY0QXJyYXksXG4gICAgICBuMjogcmVhZG9ubHkgbnVtYmVyW118SW50OEFycmF5fFVpbnQ4QXJyYXl8SW50MTZBcnJheXxVaW50MTZBcnJheXxJbnQzMkFycmF5fFVpbnQzMkFycmF5fFVpbnQ4Q2xhbXBlZEFycmF5fFxuICAgICAgRmxvYXQzMkFycmF5fEZsb2F0NjRBcnJheSkge1xuICAgIGlmIChuMS5sZW5ndGggIT09IG4yLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG4xLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAobjFbaV0gIT09IG4yW2ldKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE1hdE11bFV0aWwge1xuICAvKipcbiAgICogRml4IHRoZSBpbnB1dCBzaGFwZXMgZm9yIE1hdE11bCBvcGVyYXRpb24gaWYgdGhleSBuZWVkIGZpeGluZ1xuICAgKiBAcGFyYW0gZGltc0EgVGhlIHNoYXBlIG9mIHRlbnNvciBBLiBTaG91bGQgYmUgYW4gYXJyYXkgb2YgcG9zaXRpdmUgaW50ZWdlcnNcbiAgICogQHBhcmFtIGRpbXNCIFRoZSBzaGFwZSBvZiB0ZW5zb3IgQi4gU2hvdWxkIGJlIGFuIGFycmF5IG9mIHBvc2l0aXZlIGludGVnZXJzXG4gICAqIEByZXR1cm5zIEEgdHVwbGUgY29udGFpbmluZyB0aGUgcHJlcHJvY2Vzc2VkIGlucHV0IHNoYXBlcyBhcyByZXF1aXJlZCBieSBPTk5YIHNwZWNpZmljYXRpb25zXG4gICAqL1xuICBzdGF0aWMgcHJlcHJvY2Vzc0lucHV0U2hhcGVzKGRpbXNBOiByZWFkb25seSBudW1iZXJbXSwgZGltc0I6IHJlYWRvbmx5IG51bWJlcltdKTpcbiAgICAgIFtyZWFkb25seSBudW1iZXJbXSwgcmVhZG9ubHkgbnVtYmVyW11dIHtcbiAgICAvLyBJZiB0aGUgZmlyc3QgYXJndW1lbnQgaXMgMS1ELCBpdCBpcyBwcm9tb3RlZCB0byBhIG1hdHJpeCBieSBwcmVwZW5kaW5nXG4gICAgLy8gYSAxIHRvIGl0cyBkaW1lbnNpb25zLiBBZnRlciBtYXRyaXggbXVsdGlwbGljYXRpb24gdGhlIHByZXBlbmRlZCAxIGlzXG4gICAgLy8gcmVtb3ZlZC5cbiAgICBjb25zdCBhID0gKGRpbXNBLmxlbmd0aCA9PT0gMSkgPyBbMSwgZGltc0FbMF1dIDogZGltc0E7XG5cbiAgICAvLyBJZiB0aGUgc2Vjb25kIGFyZ3VtZW50IGlzIDEtRCwgaXQgaXMgcHJvbW90ZWQgdG8gYSBtYXRyaXggYnkgYXBwZW5kaW5nXG4gICAgLy8gYSAxIHRvIGl0cyBkaW1lbnNpb25zLiBBZnRlciBtYXRyaXggbXVsdGlwbGljYXRpb24gdGhlIGFwcGVuZGVkIDEgaXNcbiAgICAvLyByZW1vdmVkLlxuICAgIGNvbnN0IGIgPSAoZGltc0IubGVuZ3RoID09PSAxKSA/IFtkaW1zQlswXSwgMV0gOiBkaW1zQjtcblxuICAgIHJldHVybiBbYSwgYl07XG4gIH1cblxuICAvKipcbiAgICogRml4IHRoZSBvdXRwdXQgc2hhcGUgY29tcHV0ZWQgZm9yIE1hdE11bCBvcGVyYXRpb24gaWYgaXQgbmVlZHMgZml4aW5nXG4gICAqIEBwYXJhbSBvdXRwdXRTaGFwZSBUaGUgY29tcHV0ZWQgb3V0cHV0U2hhcGUuIFNob3VsZCBiZSBhbiBhcnJheSAoYXRsZWFzdCBvZiBsZW5ndGggMikgb2YgcG9zaXRpdmUgaW50ZWdlcnMuXG4gICAqIFRoaXMgd2lsbCBiZSBtdXRhdGVkLlxuICAgKiBAcGFyYW0gYVJhbmsgVGhlIHJhbmsgb2YgdGVuc29yIEEuXG4gICAqIEBwYXJhbSBiUmFuayBUaGUgcmFuayBvZiB0ZW5zb3IgQi5cbiAgICovXG4gIHN0YXRpYyBwb3N0cHJvY2Vzc091dHB1dFNoYXBlKG91dHB1dFNoYXBlOiBudW1iZXJbXSwgYVJhbms6IG51bWJlciwgYlJhbms6IG51bWJlcikge1xuICAgIC8vIFJlbW92ZSBwcmVwZW5kZWQgZGltZW5zaW9uIGlmIGZpcnN0IGlucHV0IGlzIDFkXG4gICAgaWYgKGFSYW5rID09PSAxKSB7XG4gICAgICAvLyBvdXRwdXRTaGFwZSA9IG91dHB1dFNoYXBlLnNsaWNlKDAsIG91dHB1dFNoYXBlLmxlbmd0aCAtIDIpLmNvbmNhdChvdXRwdXRTaGFwZS5zbGljZShvdXRwdXRTaGFwZS5sZW5ndGggLSAxKSk7XG4gICAgICBvdXRwdXRTaGFwZS5zcGxpY2Uob3V0cHV0U2hhcGUubGVuZ3RoIC0gMiwgMSk7XG4gICAgfVxuICAgIC8vIFJlbW92ZSBhcHBlbmRlZCBkaW1lbnNpb24gaWYgc2Vjb25kIGlucHV0IGlzIDFkXG4gICAgaWYgKGJSYW5rID09PSAxKSB7XG4gICAgICBvdXRwdXRTaGFwZS5wb3AoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIHRoZSBleHBlY3RlZCBzaGFwZSB3aGVuIG1hdHJpeCBtdWx0aXBsaWNhdGlvblxuICAgKiBAcGFyYW0gYSBUaGUgc2hhcGUgb2YgdGVuc29yIEEuIFNob3VsZCBiZSBhIHR1cGxlIG9mIDIgcG9zaXRpdmUgaW50ZWdlcnNcbiAgICogQHBhcmFtIGIgVGhlIHNoYXBlIG9mIHRlbnNvciBCLiBTaG91bGQgYmUgYSB0dXBsZSBvZiAyIHBvc2l0aXZlIGludGVnZXJzXG4gICAqIEByZXR1cm5zIFRoZSBleHBlY3RlZCBzaGFwZSBvZiB0aGUgcmVzdWx0LCBvciB1bmRlZmluZWQgaWYgTi9BXG4gICAqL1xuICBzdGF0aWMgY2FsY01hdE11bFNoYXBlKGE6IFtudW1iZXIsIG51bWJlcl0sIGI6IFtudW1iZXIsIG51bWJlcl0pOiBbbnVtYmVyLCBudW1iZXJdfHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIChhWzFdICE9PSBiWzBdKSA/IHVuZGVmaW5lZCA6IFthWzBdLCBiWzFdXTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQnJvYWRjYXN0VXRpbCB7XG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgdGhlIGV4cGVjdGVkIHNoYXBlIHdoZW4gYnJvYWRjYXN0aW5nIDIgdGVuc29yc1xuICAgKiBAcGFyYW0gYSBUaGUgc2hhcGUgb2YgdGVuc29yIEEuIFNob3VsZCBiZSBhbiBhcnJheSBvZiBwb3NpdGl2ZSBpbnRlZ2Vyc1xuICAgKiBAcGFyYW0gYiBUaGUgc2hhcGUgb2YgdGVuc29yIEIuIFNob3VsZCBiZSBhbiBhcnJheSBvZiBwb3NpdGl2ZSBpbnRlZ2Vyc1xuICAgKiBAcGFyYW0gaXNNYXRNdWwgV2hldGhlciB0aGUgb3BlcmF0aW9uIGlzIE1hdE11bFxuICAgKiBAcmV0dXJucyBUaGUgZXhwZWN0ZWQgc2hhcGUgb2YgdGhlIHJlc3VsdCwgb3IgdW5kZWZpbmVkIGlmIE4vQVxuICAgKi9cbiAgc3RhdGljIGNhbGNTaGFwZShhZGltczogcmVhZG9ubHkgbnVtYmVyW10sIGJkaW1zOiByZWFkb25seSBudW1iZXJbXSwgaXNNYXRNdWwgPSBmYWxzZSk6IHJlYWRvbmx5IG51bWJlcltdfHVuZGVmaW5lZCB7XG4gICAgY29uc3QgYXJhbmsgPSBhZGltcy5sZW5ndGg7XG4gICAgY29uc3QgYnJhbmsgPSBiZGltcy5sZW5ndGg7XG4gICAgaWYgKGFyYW5rID09PSAwKSB7XG4gICAgICByZXR1cm4gYmRpbXM7XG4gICAgfVxuICAgIGlmIChicmFuayA9PT0gMCkge1xuICAgICAgcmV0dXJuIGFkaW1zO1xuICAgIH1cbiAgICBjb25zdCBjcmFuayA9IE1hdGgubWF4KGFkaW1zLmxlbmd0aCwgYmRpbXMubGVuZ3RoKTtcbiAgICBjb25zdCBjZGltcyA9IG5ldyBBcnJheTxudW1iZXI+KGNyYW5rKTtcblxuICAgIC8vIGNhbGN1bGF0ZSB0aGUgbGFzdCAyIGRpbWVuc2lvbiBpZiBpdCBpcyBNYXRNdWxcbiAgICBpZiAoaXNNYXRNdWwpIHtcbiAgICAgIGlmIChhcmFuayA8IDIgfHwgYnJhbmsgPCAyKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgICBjb25zdCBjU2hhcGVNYXRNdWwgPVxuICAgICAgICAgIE1hdE11bFV0aWwuY2FsY01hdE11bFNoYXBlKFthZGltc1thcmFuayAtIDJdLCBhZGltc1thcmFuayAtIDFdXSwgW2JkaW1zW2JyYW5rIC0gMl0sIGJkaW1zW2JyYW5rIC0gMV1dKTtcbiAgICAgIGlmIChjU2hhcGVNYXRNdWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgW2NkaW1zW2NyYW5rIC0gMl0sIGNkaW1zW2NyYW5rIC0gMV1dID0gY1NoYXBlTWF0TXVsO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSBpc01hdE11bCA/IDMgOiAxOyBpIDw9IGNyYW5rOyBpKyspIHtcbiAgICAgIGNvbnN0IGFMZW4gPSBhcmFuayAtIGkgPCAwID8gMSA6IGFkaW1zW2FyYW5rIC0gaV07XG4gICAgICBjb25zdCBiTGVuID0gYnJhbmsgLSBpIDwgMCA/IDEgOiBiZGltc1ticmFuayAtIGldO1xuXG4gICAgICBpZiAoYUxlbiAhPT0gYkxlbiAmJiBhTGVuID4gMSAmJiBiTGVuID4gMSkge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgY2RpbXNbY3JhbmsgLSBpXSA9IE1hdGgubWF4KGFMZW4sIGJMZW4pO1xuICAgIH1cblxuICAgIHJldHVybiBjZGltcztcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiB0aGUgaW5kaWNlcyBvZiBhIGJyb2FkY2FzdGVkIHRlbnNvciwgY2FsY3VsYXRlIHRoZSBvcmlnaW5hbCBpbmRpY2VzXG4gICAqIEBwYXJhbSBicm9hZGNhc3RlZEluZGljZXMgVGhlIGdpdmVuIGluZGljZXMgb2YgdGhlIGJyb2FkY2FzdGVkIHRlbnNvci5cbiAgICogQHBhcmFtIG9yaWdpbmFsU2hhcGUgVGhlIG9yaWdpbmFsIHNoYXBlIG9mIHRoZSB0ZW5zb3IgYmVmb3JlIGJyb2FkY2FzXG4gICAqIEByZXR1cm5zIFRoZSBjYWxjdWxhdGVkIGluZGljZXMgdGhhdCBtYXBzIHRvIHRoZSBvcmlnaW5hbCB0ZW5zb3IuXG4gICAqL1xuICBzdGF0aWMgaW5kZXgoYnJvYWRjYXN0ZWRJbmRpY2VzOiByZWFkb25seSBudW1iZXJbXSwgb3JpZ2luYWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pOiBudW1iZXJbXSB7XG4gICAgLy8gTk9URSAxOiB3ZSBhc3N1bWUgdGhlIHBhcmFtZXRlciBicm9hZGNhc3RlZEluZGljZXMgaXMgdmFsaWQuIGllLiBpdCBzaG91bGQgaGF2ZSB0aGUgc2FtZVxuICAgIC8vIGxlbmd0aCBhcyB0aGUgYnJvYWRjYXN0ZWQgc2hhcGUsIGFuZCBmb3IgZWFjaCBkaW1lbnNpb24gdGhlIGluZGV4IHNob3VsZFxuICAgIC8vIG5vdCBiZSBvdXQgb2YgcmFuZ2UuXG4gICAgY29uc3Qgb3JpZ2luYWxJbmRpY2VzID0gbmV3IEFycmF5KG9yaWdpbmFsU2hhcGUubGVuZ3RoKTtcbiAgICBCcm9hZGNhc3RVdGlsLmZpbGxJbmRleChicm9hZGNhc3RlZEluZGljZXMsIG9yaWdpbmFsU2hhcGUsIG9yaWdpbmFsSW5kaWNlcyk7XG4gICAgcmV0dXJuIG9yaWdpbmFsSW5kaWNlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiB0aGUgaW5kaWNlcyBvZiBhIGJyb2FkY2FzdGVkIHRlbnNvciwgY2FsY3VsYXRlIHRoZSBvcmlnaW5hbCBpbmRpY2VzXG4gICAqIEBwYXJhbSBicm9hZGNhc3RlZEluZGljZXMgVGhlIGdpdmVuIGluZGljZXMgb2YgdGhlIGJyb2FkY2FzdGVkIHRlbnNvci5cbiAgICogQHBhcmFtIG9yaWdpbmFsU2hhcGUgVGhlIG9yaWdpbmFsIHNoYXBlIG9mIHRoZSB0ZW5zb3IgYmVmb3JlIGJyb2FkY2FzdFxuICAgKiBAcGFyYW0gb3JpZ2luYWxJbmRpY2VzIFRoZSBtYXBwaW5nIG9mIGJyb2FkY2FzdGVkSW5kaWNlcyB0byB0aGUgb3JpZ2luYWxJbmRpY2VzIChvdXRwdXQgcGFyYW1ldGVyIC0gd2lsbCBiZVxuICAgKiAgICAgbXV0YXRlZCkuXG4gICAqL1xuICBzdGF0aWMgZmlsbEluZGV4KGJyb2FkY2FzdGVkSW5kaWNlczogcmVhZG9ubHkgbnVtYmVyW10sIG9yaWdpbmFsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBvcmlnaW5hbEluZGljZXM6IG51bWJlcltdKSB7XG4gICAgLy8gTk9URSAxOiB3ZSBhc3N1bWUgdGhlIHBhcmFtZXRlciBicm9hZGNhc3RlZEluZGljZXMgaXMgdmFsaWQuIGllLiBpdCBzaG91bGQgaGF2ZSB0aGUgc2FtZSBsZW5ndGggYXMgdGhlXG4gICAgLy8gYnJvYWRjYXN0ZWQgc2hhcGUsIGFuZCBmb3IgZWFjaCBkaW1lbnNpb24gdGhlIGluZGV4IHNob3VsZCBub3QgYmUgb3V0IG9mIHJhbmdlLlxuICAgIC8vIE5PVEUgMjogd2UgYXNzdW1lIHRoZSBwYXJhbWV0ZXIgb3JpZ2luYWxJbmRpY2VzIGhhcyB0aGUgc2FtZSBsZW5ndGggYXMgdGhlIG9yaWdpbmFsU2hhcGVcbiAgICBjb25zdCBkaW1PZmZzZXQgPSBicm9hZGNhc3RlZEluZGljZXMubGVuZ3RoIC0gb3JpZ2luYWxTaGFwZS5sZW5ndGg7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvcmlnaW5hbFNoYXBlLmxlbmd0aDsgaSsrKSB7XG4gICAgICBvcmlnaW5hbEluZGljZXNbaV0gPSBicm9hZGNhc3RlZEluZGljZXNbZGltT2Zmc2V0ICsgaV0gJSBvcmlnaW5hbFNoYXBlW2ldO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIHRoZSBicm9hZGNhc3Rpbmcgb3BlcmF0aW9uIG9uIHRoZSBzcGVjaWZpYyBvcGVyYXRvclxuICAgKiBAcGFyYW0gYSBUaGUgaW5wdXQgdGVuc29yIEFcbiAgICogQHBhcmFtIGIgVGhlIGlucHV0IHRlbnNvciBCXG4gICAqIEBwYXJhbSBvcCBUaGUgb3BlcmF0b3IgbGFtYmRhIGZ1bmN0aW9uXG4gICAqIEBwYXJhbSBpbnBsYWNlIFdoZXRoZXIgdG8gd3JpdGUgdGhlIHJlc3VsdCBiYWNrIHRvIEEuXG4gICAqIEByZXR1cm5zIFRoZSByZXN1bHQgdGVuc29yLCBvciB1bmRlZmluZWQgaWYgaW5wdXQgbm90IGJyb2FkY2FzdGFibGUuXG4gICAqL1xuICBzdGF0aWMgY2FsYyhcbiAgICAgIGE6IFRlbnNvciwgYjogVGVuc29yLCBvcDogKGE6IHN0cmluZ3xudW1iZXIsIGI6IHN0cmluZ3xudW1iZXIpID0+IChzdHJpbmcgfCBudW1iZXIpLCBpbnBsYWNlOiBib29sZWFuLFxuICAgICAgcmVzdWx0VHlwZT86IFRlbnNvci5EYXRhVHlwZSk6IFRlbnNvcnx1bmRlZmluZWQge1xuICAgIGNvbnN0IG91dHB1dFNoYXBlID0gQnJvYWRjYXN0VXRpbC5jYWxjU2hhcGUoYS5kaW1zLCBiLmRpbXMpO1xuXG4gICAgaWYgKG91dHB1dFNoYXBlKSB7XG4gICAgICBpZiAoaW5wbGFjZSAmJiAhU2hhcGVVdGlsLmFyZUVxdWFsKG91dHB1dFNoYXBlLCBhLmRpbXMpKSB7XG4gICAgICAgIC8vIEIgaXMgbm90IGJyb2FkY2FzdGFibGUgdG8gQSwgZmFpbGVkIHRvIGNhbGN1bGF0ZSBpbnBsYWNlLlxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICAgICAgY29uc3QgYyA9IGlucGxhY2UgPyBhIDogbmV3IFRlbnNvcihvdXRwdXRTaGFwZSwgcmVzdWx0VHlwZSB8fCBhLnR5cGUpO1xuXG4gICAgICAvLyBib3RoIGlucHV0cyBhcmUgc2NhbGFyc1xuICAgICAgaWYgKG91dHB1dFNoYXBlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBjLnNldChbXSwgb3AoYS5nZXQoW10pLCBiLmdldChbXSkpKTtcbiAgICAgIH1cblxuICAgICAgLy8gYXRsZWFzdCBvbmUgaW5wdXQgaXMgYSBub24tc2NhbGFyXG4gICAgICBlbHNlIHtcbiAgICAgICAgY29uc3Qgb3V0cHV0SW5kaWNlcyA9IG5ldyBBcnJheTxudW1iZXI+KG91dHB1dFNoYXBlLmxlbmd0aCk7XG4gICAgICAgIGNvbnN0IG9yaWdpbmFsSW5kaWNlc0EgPSBuZXcgQXJyYXkoYS5kaW1zLmxlbmd0aCk7XG4gICAgICAgIGNvbnN0IG9yaWdpbmFsSW5kaWNlc0IgPSBuZXcgQXJyYXkoYi5kaW1zLmxlbmd0aCk7XG4gICAgICAgIGxldCB2YWxBOiBzdHJpbmd8bnVtYmVyID0gMDtcbiAgICAgICAgbGV0IHZhbEI6IHN0cmluZ3xudW1iZXIgPSAwO1xuICAgICAgICBsZXQgaXNBU2NhbGFyID0gZmFsc2U7XG4gICAgICAgIGxldCBpc0JTY2FsYXIgPSBmYWxzZTtcbiAgICAgICAgaWYgKGEuZGltcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB2YWxBID0gYS5nZXQoW10pO1xuICAgICAgICAgIGlzQVNjYWxhciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGIuZGltcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICB2YWxCID0gYi5nZXQoW10pO1xuICAgICAgICAgIGlzQlNjYWxhciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHJlc3Q6IG51bWJlcjtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgICAvLyB0cmF2ZXJzYWwgaW5kaWNlc1xuICAgICAgICAgIHJlc3QgPSBpO1xuICAgICAgICAgIGZvciAobGV0IGogPSBvdXRwdXRTaGFwZS5sZW5ndGggLSAxOyBqID49IDA7IGotLSkge1xuICAgICAgICAgICAgb3V0cHV0SW5kaWNlc1tqXSA9IHJlc3QgJSBvdXRwdXRTaGFwZVtqXTtcbiAgICAgICAgICAgIHJlc3QgPSBNYXRoLmZsb29yKHJlc3QgLyBvdXRwdXRTaGFwZVtqXSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKCFpc0FTY2FsYXIpIHtcbiAgICAgICAgICAgIC8vIG1hcCBvdXRwdXRJbmRpY2VzICh3aGljaCBpcyBhY3R1YWxseSBicm9hZGNhc3RlZCkgdG8gdGhlIG9yaWdpbmFsSW5kaWNlc1xuICAgICAgICAgICAgQnJvYWRjYXN0VXRpbC5maWxsSW5kZXgob3V0cHV0SW5kaWNlcywgYS5kaW1zLCBvcmlnaW5hbEluZGljZXNBKTtcbiAgICAgICAgICAgIHZhbEEgPSBhLmdldChvcmlnaW5hbEluZGljZXNBKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKCFpc0JTY2FsYXIpIHtcbiAgICAgICAgICAgIEJyb2FkY2FzdFV0aWwuZmlsbEluZGV4KG91dHB1dEluZGljZXMsIGIuZGltcywgb3JpZ2luYWxJbmRpY2VzQik7XG4gICAgICAgICAgICB2YWxCID0gYi5nZXQob3JpZ2luYWxJbmRpY2VzQik7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgYy5zZXQob3V0cHV0SW5kaWNlcywgb3AodmFsQSwgdmFsQikpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjO1xuICAgIH1cblxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lIGlmIGEgc2hhcGUgaXMgdW5pZGlyZWN0aW9uYWwgYnJvYWRjYXN0YWJsZSB0byBhbm90aGVyIHNoYXBlXG4gICAqIEBwYXJhbSBzaGFwZSBUaGUgaW5wdXQgc2hhcGVcbiAgICogQHBhcmFtIGZpbmFsU2hhcGUgVGhlIGRlc2lyZWQgc2hhcGUgYWZ0ZXIgYnJvYWRjYXN0aW5nXG4gICAqL1xuICBzdGF0aWMgaXNWYWxpZEJyb2FkY2FzdChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIGZpbmFsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKTogYm9vbGVhbiB7XG4gICAgLy8gYWxpZ24gc2hhcGUgdG8gdGhlIHJpZ2h0XG4gICAgY29uc3QgaW5wdXRSYW5rID0gc2hhcGUubGVuZ3RoO1xuICAgIGNvbnN0IGZpbmFsUmFuayA9IGZpbmFsU2hhcGUubGVuZ3RoO1xuICAgIGlmIChpbnB1dFJhbmsgPiBmaW5hbFJhbmspIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPD0gaW5wdXRSYW5rOyBpKyspIHtcbiAgICAgIGlmIChzaGFwZVtpbnB1dFJhbmsgLSBpXSAhPT0gMSAmJiBzaGFwZVtpbnB1dFJhbmsgLSBpXSAhPT0gZmluYWxTaGFwZVtmaW5hbFJhbmsgLSBpXSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZSB0aGUgYnJvYWRjYXN0ZWQgZGltcyBpbiBpbnB1dCBzaGFwZSBiYXNlZCBvbiB0aGUgZ2l2ZW4gb3V0cHV0IHNoYXBlLlxuICAgKiBOb3RlIHRoYXQgdGhpcyBmdW5jdGlvbiBvbmx5IHJldHVybnMgdGhlIGJyb2FkY2FzdGVkIGRpbXMuXG4gICAqIEBwYXJhbSBpbnB1dFNoYXBlIFRoZSBpbnB1dCBzaGFwZVxuICAgKiBAcGFyYW0gb3V0cHV0U2hhcGUgVGhlIG91dHB1dCBzaGFwZVxuICAgKiBAcmV0dXJucyBUaGUgYnJvYWRjYXN0ZWQgZGltcyBpbiBpbnB1dCBzaGFwZS5cbiAgICovXG4gIHN0YXRpYyBnZXRCcm9hZGNhc3REaW1zKGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10pOiBudW1iZXJbXSB7XG4gICAgY29uc3QgaW5SYW5rID0gaW5wdXRTaGFwZS5sZW5ndGg7XG4gICAgY29uc3QgZGltczogbnVtYmVyW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGluUmFuazsgaSsrKSB7XG4gICAgICBjb25zdCBkaW0gPSBpblJhbmsgLSAxIC0gaTtcbiAgICAgIGNvbnN0IGEgPSBpbnB1dFNoYXBlW2RpbV0gfHwgMTtcbiAgICAgIGNvbnN0IGIgPSBvdXRwdXRTaGFwZVtvdXRwdXRTaGFwZS5sZW5ndGggLSAxIC0gaV0gfHwgMTtcbiAgICAgIGlmIChiID4gMSAmJiBhID09PSAxKSB7XG4gICAgICAgIGRpbXMudW5zaGlmdChkaW0pO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGltcztcbiAgfVxufVxuXG4vLyBjb3B5IGFycmF5IGhlbHBlclxuLy8gbWltaWNzIG1lbWNweSBhcyBtdWNoIGFzIHBvc3NpYmxlXG5leHBvcnQgZnVuY3Rpb24gYXJyYXlDb3B5SGVscGVyKFxuICAgIHRhcmdldDogbnVtYmVyW118VGVuc29yLk51bWJlclR5cGUsIHNvdXJjZTogbnVtYmVyW118VGVuc29yLk51bWJlclR5cGUsIHRhcmdldEluZGV4OiBudW1iZXIsIHNvdXJjZUluZGV4OiBudW1iZXIsXG4gICAgYmxvY2tTaXplOiBudW1iZXIpIHtcbiAgaWYgKHNvdXJjZUluZGV4IDwgMCB8fCBzb3VyY2VJbmRleCA+PSBzb3VyY2UubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzb3VyY2VJbmRleCBvdXQgb2YgYm91bmRzJyk7XG4gIH1cbiAgaWYgKHRhcmdldEluZGV4IDwgMCB8fCB0YXJnZXRJbmRleCA+PSB0YXJnZXQubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd0YXJnZXRJbmRleCBvdXQgb2YgYm91bmRzJyk7XG4gIH1cbiAgaWYgKHNvdXJjZUluZGV4ICsgYmxvY2tTaXplID4gc291cmNlLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignc291cmNlIGluZGljZXMgdG8gYmUgY29waWVkIGFyZSBvdXRzaWRlIGJvdW5kcycpO1xuICB9XG4gIGlmICh0YXJnZXRJbmRleCArIGJsb2NrU2l6ZSA+IHRhcmdldC5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3RhcmdldCBhcnJheSBpcyB0b28gc21hbGwgdG8gaG9sZCByZXN1bHQnKTtcbiAgfVxuXG4gIGZvciAobGV0IG9mZnNldCA9IDA7IG9mZnNldCA8IGJsb2NrU2l6ZTsgb2Zmc2V0KyspIHtcbiAgICB0YXJnZXRbdGFyZ2V0SW5kZXggKyBvZmZzZXRdID0gc291cmNlW3NvdXJjZUluZGV4ICsgb2Zmc2V0XTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgR2VtbVV0aWwge1xuICAvLyB3aWxsIG1ha2Ugc3VyZSBpbnB1dCBzaGFwZXMgYXJlIGNvbXBhdGlibGUgZm9yIHRoaXMgb3BcbiAgLy8gYW5kIHJldHVybiBiYWNrIHRoZSBzaGFwZSBvZiB0aGUgb3V0cHV0IGluIHRoZSBmb3JtIG9mIGEgdHVwbGVcbiAgLy8gd2lsbCB0aHJvdyBleGNlcHRpb24gaWYgdGhlIGlucHV0IHNoYXBlcyBhcmUgbm90IGNvbXBhdGlibGVcbiAgc3RhdGljIGdldFNoYXBlT2ZHZW1tUmVzdWx0KFxuICAgICAgbGVmdFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgdHJhbnNMZWZ0OiBib29sZWFuLCByaWdodFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgdHJhbnNSaWdodDogYm9vbGVhbixcbiAgICAgIGJpYXNTaGFwZT86IHJlYWRvbmx5IG51bWJlcltdKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIGlmIChsZWZ0U2hhcGUubGVuZ3RoICE9PSAyIHx8IHJpZ2h0U2hhcGUubGVuZ3RoICE9PSAyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NoYXBlIG5lZWQgdG8gYmUgb2Ygc2l6ZSAyJyk7XG4gICAgfVxuXG4gICAgbGV0IE06IG51bWJlcjtcbiAgICBsZXQgSzogbnVtYmVyO1xuICAgIGxldCBOOiBudW1iZXI7XG5cbiAgICBpZiAodHJhbnNMZWZ0KSB7XG4gICAgICBNID0gbGVmdFNoYXBlWzFdO1xuICAgICAgSyA9IGxlZnRTaGFwZVswXTtcbiAgICB9IGVsc2Uge1xuICAgICAgTSA9IGxlZnRTaGFwZVswXTtcbiAgICAgIEsgPSBsZWZ0U2hhcGVbMV07XG4gICAgfVxuXG4gICAgbGV0IGtEaW0gPSAtMTtcblxuICAgIGlmICh0cmFuc1JpZ2h0KSB7XG4gICAgICBOID0gcmlnaHRTaGFwZVswXTtcbiAgICAgIGtEaW0gPSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICBOID0gcmlnaHRTaGFwZVsxXTtcbiAgICAgIGtEaW0gPSAwO1xuICAgIH1cblxuICAgIGlmIChyaWdodFNoYXBlW2tEaW1dICE9PSBLKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RpbWVuc2lvbiBtaXNtYXRjaCcpO1xuICAgIH1cblxuICAgIGlmIChNIDw9IDAgfHwgTiA8PSAwIHx8IEsgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHNoYXBlIHNwZWNpZmllZCcpO1xuICAgIH1cblxuICAgIGlmIChiaWFzU2hhcGUgJiYgIUJyb2FkY2FzdFV0aWwuaXNWYWxpZEJyb2FkY2FzdChiaWFzU2hhcGUsIFtNLCBOXSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ2VtbTogaW52YWxpZCBiaWFzIHNoYXBlIGZvciBicm9hZGNhc3QnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gW00sIE4sIEtdO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBQcm90b1V0aWwge1xuICBzdGF0aWMgdGVuc29yRGF0YVR5cGVGcm9tUHJvdG8odHlwZVByb3RvOiBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlfFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5UZW5zb3JEYXRhVHlwZSk6IFRlbnNvci5EYXRhVHlwZSB7XG4gICAgc3dpdGNoICh0eXBlUHJvdG8pIHtcbiAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQ4OlxuICAgICAgICByZXR1cm4gJ2ludDgnO1xuICAgICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLlVJTlQ4OlxuICAgICAgICByZXR1cm4gJ3VpbnQ4JztcbiAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5CT09MOlxuICAgICAgICByZXR1cm4gJ2Jvb2wnO1xuICAgICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLklOVDE2OlxuICAgICAgICByZXR1cm4gJ2ludDE2JztcbiAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UMTY6XG4gICAgICAgIHJldHVybiAndWludDE2JztcbiAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQzMjpcbiAgICAgICAgcmV0dXJuICdpbnQzMic7XG4gICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuVUlOVDMyOlxuICAgICAgICByZXR1cm4gJ3VpbnQzMic7XG4gICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuRkxPQVQ6XG4gICAgICAgIHJldHVybiAnZmxvYXQzMic7XG4gICAgICBjYXNlIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuRE9VQkxFOlxuICAgICAgICByZXR1cm4gJ2Zsb2F0NjQnO1xuICAgICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLlNUUklORzpcbiAgICAgICAgcmV0dXJuICdzdHJpbmcnO1xuXG4gICAgICAvLyBGb3IgSU5UNjQvVUlOVDY0LCByZWR1Y2UgdGhlaXIgdmFsdWUgdG8gMzItYml0cy5cbiAgICAgIC8vIFNob3VsZCB0aHJvdyBleGNlcHRpb24gd2hlbiBvdmVyZmxvd1xuICAgICAgY2FzZSBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLklOVDY0OlxuICAgICAgICByZXR1cm4gJ2ludDMyJztcbiAgICAgIGNhc2Ugb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UNjQ6XG4gICAgICAgIHJldHVybiAndWludDMyJztcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7b25ueC5UZW5zb3JQcm90by5EYXRhVHlwZVt0eXBlUHJvdG9dfWApO1xuICAgIH1cbiAgfVxuXG4gIHN0YXRpYyB0ZW5zb3JEYXRhVHlwZVN0cmluZ1RvRW51bSh0eXBlOiBzdHJpbmcpOiBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlIHtcbiAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgIGNhc2UgJ2ludDgnOlxuICAgICAgICByZXR1cm4gb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQ4O1xuICAgICAgY2FzZSAndWludDgnOlxuICAgICAgICByZXR1cm4gb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UODtcbiAgICAgIGNhc2UgJ2Jvb2wnOlxuICAgICAgICByZXR1cm4gb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5CT09MO1xuICAgICAgY2FzZSAnaW50MTYnOlxuICAgICAgICByZXR1cm4gb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQxNjtcbiAgICAgIGNhc2UgJ3VpbnQxNic6XG4gICAgICAgIHJldHVybiBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLlVJTlQxNjtcbiAgICAgIGNhc2UgJ2ludDMyJzpcbiAgICAgICAgcmV0dXJuIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuSU5UMzI7XG4gICAgICBjYXNlICd1aW50MzInOlxuICAgICAgICByZXR1cm4gb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5VSU5UMzI7XG4gICAgICBjYXNlICdmbG9hdDMyJzpcbiAgICAgICAgcmV0dXJuIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuRkxPQVQ7XG4gICAgICBjYXNlICdmbG9hdDY0JzpcbiAgICAgICAgcmV0dXJuIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuRE9VQkxFO1xuICAgICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgICAgcmV0dXJuIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGUuU1RSSU5HO1xuICAgICAgY2FzZSAnaW50NjQnOlxuICAgICAgICByZXR1cm4gb25ueC5UZW5zb3JQcm90by5EYXRhVHlwZS5JTlQ2NDtcbiAgICAgIGNhc2UgJ3VpbnQ2NCc6XG4gICAgICAgIHJldHVybiBvbm54LlRlbnNvclByb3RvLkRhdGFUeXBlLlVJTlQ2NDtcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7dHlwZX1gKTtcbiAgICB9XG4gIH1cblxuICBzdGF0aWMgdGVuc29yRGltc0Zyb21Qcm90byhkaW1zOiBBcnJheTxudW1iZXJ8TG9uZz4pOiBudW1iZXJbXSB7XG4gICAgLy8gZ2V0IHJpZCBvZiBMb25nIHR5cGUgZm9yIGRpbXNcbiAgICByZXR1cm4gZGltcy5tYXAoZCA9PiBMb25nLmlzTG9uZyhkKSA/IGQudG9OdW1iZXIoKSA6IGQpO1xuICB9XG5cbiAgc3RhdGljIHRlbnNvclZhbHVlVHlwZUZyb21Qcm90byh2YWx1ZVR5cGU6IG9ubnguVHlwZVByb3RvLklUZW5zb3IpOiBHcmFwaC5WYWx1ZVR5cGUge1xuICAgIHJldHVybiB7XG4gICAgICB0ZW5zb3JUeXBlOiBQcm90b1V0aWwudGVuc29yRGF0YVR5cGVGcm9tUHJvdG8odmFsdWVUeXBlLmVsZW1UeXBlISksXG4gICAgICBzaGFwZToge2RpbXM6IFByb3RvVXRpbC50ZW5zb3JEaW1zRnJvbVByb3RvKHZhbHVlVHlwZS5zaGFwZSEuZGltIS5tYXAoZCA9PiBkLmRpbVZhbHVlISkpfVxuICAgIH07XG4gIH1cblxuICBzdGF0aWMgdGVuc29yRGltc0Zyb21PUlRGb3JtYXQodGVuc29yOiBvbm54cnVudGltZS5leHBlcmltZW50YWwuZmJzLlRlbnNvcikge1xuICAgIGNvbnN0IGRpbXMgPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRlbnNvci5kaW1zTGVuZ3RoKCk7IGkrKykge1xuICAgICAgZGltcy5wdXNoKExvbmdVdGlsLmxvbmdUb051bWJlcih0ZW5zb3IuZGltcyhpKSEpKTtcbiAgICB9XG4gICAgcmV0dXJuIGRpbXM7XG4gIH1cblxuICBzdGF0aWMgdGVuc29yQXR0cmlidXRlc0Zyb21PUlRGb3JtYXQobm9kZTogb25ueHJ1bnRpbWUuZXhwZXJpbWVudGFsLmZicy5Ob2RlKSB7XG4gICAgY29uc3QgYXR0cmlidXRlcyA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbm9kZS5hdHRyaWJ1dGVzTGVuZ3RoKCk7IGkrKykge1xuICAgICAgYXR0cmlidXRlcy5wdXNoKG5vZGUuYXR0cmlidXRlcyhpKSEpO1xuICAgIH1cbiAgICByZXR1cm4gYXR0cmlidXRlcztcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTG9uZ1V0aWwge1xuICAvLyBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB0byBnZXQgYSBudW1iZXIgZnJvbSBsb25nIHR5cGUgb2YgZGF0YSBmb3IgYXR0cmlidXRlLCBkaW0sIGFuZCBpciB2ZXJzaW9uLFxuICAvLyB3aGljaCB2YWx1ZXMgYXJlIHNpZ25lZCBpbnRlZ2Vycy5cbiAgLy8gVG8gbWFrZSBpdCBtb3JlIGdlbmVyaWMsIGFkZCBhbiBvcHRpb25hbCBwYXJhbXRlciB0byBjb252ZXJ0IHRvIGEgdW5zaWduZWQgbnVtYmVyLlxuICBzdGF0aWMgbG9uZ1RvTnVtYmVyKG46IExvbmd8ZmxhdGJ1ZmZlcnMuTG9uZ3xudW1iZXIsIHVuc2lnbmVkPzogYm9vbGVhbikge1xuICAgIGlmIChMb25nLmlzTG9uZyhuKSkge1xuICAgICAgcmV0dXJuIG4udG9OdW1iZXIoKTtcbiAgICB9IGVsc2UgaWYgKG4gaW5zdGFuY2VvZiBmbGF0YnVmZmVycy5Mb25nKSB7XG4gICAgICByZXR1cm4gTG9uZy5mcm9tVmFsdWUoe2xvdzogbi5sb3csIGhpZ2g6IG4uaGlnaCwgdW5zaWduZWQ6IHVuc2lnbmVkID8/IGZhbHNlfSkudG9OdW1iZXIoKTtcbiAgICB9XG4gICAgcmV0dXJuIG47XG4gIH1cbiAgc3RhdGljIGlzTG9uZyhuOiB1bmtub3duKSB7XG4gICAgcmV0dXJuIExvbmcuaXNMb25nKG4pIHx8IG4gaW5zdGFuY2VvZiBmbGF0YnVmZmVycy5Mb25nO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBTaGFwZVV0aWwge1xuICBzdGF0aWMgc2l6ZShkaW1zOiByZWFkb25seSBudW1iZXJbXSk6IG51bWJlciB7XG4gICAgcmV0dXJuIFNoYXBlVXRpbC5nZXRTaXplRnJvbURpbWVuc2lvblJhbmdlKGRpbXMsIDAsIGRpbXMubGVuZ3RoKTtcbiAgfVxuXG4gIC8vIGBheGlzYCBpbmNsdXNpdmVcbiAgc3RhdGljIHNpemVGcm9tRGltZW5zaW9uKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBheGlzOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGlmIChheGlzIDwgMCB8fCBheGlzID4gZGltcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBkaW1lbnNpb24gb2YgJHtheGlzfSBmb3Igc2l6ZUZyb21EaW1lbnNpb24gYXMgVGVuc29yIGhhcyAke2RpbXMubGVuZ3RofSBkaW1lbnNpb25zLmApO1xuICAgIH1cbiAgICByZXR1cm4gU2hhcGVVdGlsLmdldFNpemVGcm9tRGltZW5zaW9uUmFuZ2UoZGltcywgYXhpcywgZGltcy5sZW5ndGgpO1xuICB9XG5cbiAgLy8gYGF4aXNgIGV4Y2x1c2l2ZVxuICBzdGF0aWMgc2l6ZVRvRGltZW5zaW9uKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBheGlzOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGlmIChheGlzIDwgMCB8fCBheGlzID4gZGltcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBkaW1lbnNpb24gb2YgJHtheGlzfSBmb3Igc2l6ZVRvRGltZW5zaW9uIGFzIFRlbnNvciBoYXMgJHtkaW1zLmxlbmd0aH0gZGltZW5zaW9ucy5gKTtcbiAgICB9XG4gICAgcmV0dXJuIFNoYXBlVXRpbC5nZXRTaXplRnJvbURpbWVuc2lvblJhbmdlKGRpbXMsIDAsIGF4aXMpO1xuICB9XG5cbiAgc3RhdGljIGdldFNpemVGcm9tRGltZW5zaW9uUmFuZ2UoZGltczogcmVhZG9ubHkgbnVtYmVyW10sIHN0YXJ0OiBudW1iZXIsIGVuZDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBsZXQgc2l6ZSA9IDE7XG4gICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICAgIC8vIHNhZmV0eSBjaGVjayBhcyB0aGlzIG1ldGhvZCBpcyBjYWxsZWQgYnkgbXVsdGlwbGUgb3RoZXIgbWV0aG9kcyByZXF1aXJpbmcgc2l6ZS5cbiAgICAgIC8vIHNpemUgY2Fubm90IGJlIDAgb3IgbmVnYXRpdmUuXG4gICAgICBpZiAoZGltc1tpXSA8PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBtYXgtbGVuXG4gICAgICAgICAgICAnY2Fubm90IGdldCB2YWxpZCBzaXplIGZyb20gc3BlY2lmaWVkIGRpbWVuc2lvbiByYW5nZS4gTW9zdCBsaWtlbHkgdGhlIHJhbmdlIGNvbnRhaW5zIDAgb3IgbmVnYXRpdmUgdmFsdWVzIGluIHRoZW0uJyk7XG4gICAgICB9XG4gICAgICBzaXplICo9IGRpbXNbaV07XG4gICAgfVxuICAgIHJldHVybiBzaXplO1xuICB9XG5cbiAgc3RhdGljIGNvbXB1dGVTdHJpZGVzKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIGNvbnN0IHJhbmsgPSBkaW1zLmxlbmd0aDtcbiAgICBpZiAocmFuayA9PT0gMCkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH0gZWxzZSBpZiAocmFuayA9PT0gMSkge1xuICAgICAgcmV0dXJuIFsxXTtcbiAgICB9XG4gICAgY29uc3Qgc3RyaWRlcyA9IG5ldyBBcnJheShyYW5rKTtcbiAgICBzdHJpZGVzW3JhbmsgLSAxXSA9IDE7XG4gICAgc3RyaWRlc1tyYW5rIC0gMl0gPSBkaW1zW3JhbmsgLSAxXTtcbiAgICBmb3IgKGxldCBpID0gcmFuayAtIDM7IGkgPj0gMDsgLS1pKSB7XG4gICAgICBzdHJpZGVzW2ldID0gc3RyaWRlc1tpICsgMV0gKiBkaW1zW2kgKyAxXTtcbiAgICB9XG4gICAgcmV0dXJuIHN0cmlkZXM7XG4gIH1cblxuICBzdGF0aWMgdHJhbnNwb3NlKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIGNvbnN0IGNvcHkgPSBkaW1zLnNsaWNlKCk7XG4gICAgcmV0dXJuIGNvcHkucmV2ZXJzZSgpO1xuICB9XG5cbiAgc3RhdGljIGluZGljZXNUb09mZnNldChpbmRpY2VzOiByZWFkb25seSBudW1iZXJbXSwgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW10sIGF4aXM/OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGlmIChheGlzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGF4aXMgPSBpbmRpY2VzLmxlbmd0aDtcbiAgICB9XG4gICAgbGV0IG9mZnNldCA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBheGlzOyArK2kpIHtcbiAgICAgIG9mZnNldCArPSBzdHJpZGVzW2ldICogaW5kaWNlc1tpXTtcbiAgICB9XG4gICAgcmV0dXJuIG9mZnNldDtcbiAgfVxuXG4gIHN0YXRpYyBvZmZzZXRUb0luZGljZXMob2Zmc2V0OiBudW1iZXIsIHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIGNvbnN0IHJhbmsgPSBzdHJpZGVzLmxlbmd0aDtcbiAgICBpZiAocmFuayA9PT0gMCkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH0gZWxzZSBpZiAocmFuayA9PT0gMSkge1xuICAgICAgcmV0dXJuIFtvZmZzZXQgKiBzdHJpZGVzWzBdXTtcbiAgICB9XG4gICAgY29uc3QgaW5kaWNlczogbnVtYmVyW10gPSBuZXcgQXJyYXkoc3RyaWRlcy5sZW5ndGgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGggLSAxOyArK2kpIHtcbiAgICAgIGluZGljZXNbaV0gPSBNYXRoLmZsb29yKG9mZnNldCAvIHN0cmlkZXNbaV0pO1xuICAgICAgb2Zmc2V0IC09IGluZGljZXNbaV0gKiBzdHJpZGVzW2ldO1xuICAgIH1cbiAgICBpbmRpY2VzW2luZGljZXMubGVuZ3RoIC0gMV0gPSBvZmZzZXQ7XG4gICAgcmV0dXJuIGluZGljZXM7XG4gIH1cblxuICAvKipcbiAgICogbm9ybWFpbHplIGF4aXMgb2YgcmFuZ2UgWy1yLCByKSBpbnRvIFswLCByKS5cbiAgICovXG4gIHN0YXRpYyBub3JtYWxpemVBeGlzKGF4aXM6IG51bWJlciwgdGVuc29yUmFuazogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBpZiAoYXhpcyA8IC10ZW5zb3JSYW5rICYmIGF4aXMgPj0gdGVuc29yUmFuaykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd1bnN1cHBvcnRlZCBheGlzIGZvciB0aGlzIG9wZXJhdGlvbi4nKTtcbiAgICB9XG4gICAgcmV0dXJuIGF4aXMgPCAwID8gYXhpcyArIHRlbnNvclJhbmsgOiBheGlzO1xuICB9XG5cbiAgc3RhdGljIG5vcm1hbGl6ZUF4ZXMoYXhlczogcmVhZG9ubHkgbnVtYmVyW10sIHRlbnNvclJhbms6IG51bWJlcik6IG51bWJlcltdIHtcbiAgICByZXR1cm4gYXhlcy5tYXAoeCA9PiB0aGlzLm5vcm1hbGl6ZUF4aXMoeCwgdGVuc29yUmFuaykpO1xuICB9XG5cbiAgLy8gSW5jcmVtZW50IGFuIGluZGV4IGludG8gYSB0ZW5zb3IgKGluIGxleGljb2dyYXBoaWNcbiAgLy8gb3JkZXJpbmcpLCB3cmFwcGluZyBhcm91bmQgdGhlIHNwZWNpZmllZCB1cHBlcl9ib3VuZC5cbiAgLyoqXG4gICAqIEluY3JlbWVudCBhbiBpbmRleCBpbnRvIGEgdGVuc29yIChpbiBsZXhpY29ncmFwaGljIG9yZGVyaW5nKSwgd3JhcHBpbmcgYXJvdW5kIHRoZSBzcGVjaWZpZWQgdXBwZXJfYm91bmQuXG4gICAqIEBwYXJhbSBpbmRleCBHaXZlbiBpbmRleCB0byBpbmNyZW1lbnQgKFdpbGwgYmUgbXV0YXRlZClcbiAgICogQHBhcmFtIGRpbXMgVGhlIGRpbWVuc2lvbnMgb2YgdGhlIHRlbnNvciBmb3Igd2hpY2ggdGhlIGdpdmVuIGluZGV4IGNvcnJlc3BvbmRzIHRvXG4gICAqIEBwYXJhbSBheGlzVG9JbmNyZW1lbnRPbiBUaGUgMS1pbmRleGVkIGF4aXMgdG8gaW5jcmVtZW50IG9uLiBJZiB1bmRlZmluZWQsIGF4aXNUb0luY3JlbWVudE9uID09IHJhbmtcbiAgICovXG4gIHN0YXRpYyBpbmNyZW1lbnRJbmRleChpbmRleDogbnVtYmVyW10sIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBheGlzVG9JbmNyZW1lbnRPbj86IG51bWJlcikge1xuICAgIGlmIChkaW1zLmxlbmd0aCA9PT0gMCB8fCBpbmRleC5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW5kZXggaW5jcmVtZW50aW5nIHVuc3VwcG9ydGVkIGZvciBzY2FsYXIgVGVuc29yJyk7XG4gICAgfVxuICAgIGlmIChheGlzVG9JbmNyZW1lbnRPbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBheGlzVG9JbmNyZW1lbnRPbiA9IGRpbXMubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYXhpc1RvSW5jcmVtZW50T24gPD0gMCB8fCBheGlzVG9JbmNyZW1lbnRPbiA+IGRpbXMubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW5jb3JyZWN0IGF4aXMgdG8gaW5jcmVtZW50IG9uJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChsZXQgayA9IGF4aXNUb0luY3JlbWVudE9uIC0gMTsgayA+PSAwOyAtLWspIHtcbiAgICAgIGluZGV4W2tdKys7XG4gICAgICBpZiAoaW5kZXhba10gPCBkaW1zW2tdKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaW5kZXhba10gPSAwO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQcm9kdWNlcyBhIG5ldyBkaW1lbnNpb25zIGFycmF5IGJhc2VkIG9uIHRoZSB2YWx1ZXMgaW4gdGhlICdvcmlnaW5hbERpbWVuc2lvbnMnIGFuZCAnc2hhcGUnIGFycmF5XG4gICAqIFVzZWQgaW4gUmVzaGFwZVxuICAgKiBAcGFyYW0gb3JpZ2luYWxEaW1zIE9yaWdpbmFsIFNoYXBlIGFycmF5XG4gICAqIEBwYXJhbSBzaGFwZUhpbnRzIGFycmF5IGNvbnRhaW5pbmcgdmFsdWVzIHRvIGNvbXB1dGUgdGhlIG5ldyBkaW1lbnNpb25zXG4gICAqIEZvciBleGFtcGxlOlxuICAgKiBvcmlnaW5hbERpbXMgPSBbMiwyXSBhbmQgc2hhcGVIaW50cyA9IFswLC0xXSB3aWxsIHJldHVybiBbMiwyXVxuICAgKiBvcmlnaW5hbERpbXMgPSBbMiwyXSBhbmQgc2hhcGVIaW50cyA9IFs0XSB3aWxsIHJldHVybiBbNF1cbiAgICogb3JpZ2luYWxEaW1zID0gWzIsMl0gYW5kIHNoYXBlSGludHMgPSBbNV0gd2lsbCB0aHJvdyBhbiBleGNlcHRpb25cbiAgICogaHR0cHM6Ly9naXRodWIuY29tL29ubngvb25ueC9ibG9iL21haW4vZG9jcy9PcGVyYXRvcnMubWQjUmVzaGFwZVxuICAgKi9cblxuICBzdGF0aWMgY2FsY3VsYXRlUmVzaGFwZWREaW1zKG9yaWdpbmFsRGltczogcmVhZG9ubHkgbnVtYmVyW10sIHNoYXBlSGludHM6IEFycmF5TGlrZTxudW1iZXI+KTogbnVtYmVyW10ge1xuICAgIC8vIHJlc2hhcGUgdG8gYSBTY2FsYXIgVGVuc29yXG4gICAgaWYgKHNoYXBlSGludHMubGVuZ3RoID09PSAwKSB7XG4gICAgICBpZiAob3JpZ2luYWxEaW1zLmxlbmd0aCA9PT0gMCB8fCBTaGFwZVV0aWwuc2l6ZShvcmlnaW5hbERpbXMpID09PSAxKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignY2Fubm90IHJlc2hhcGUgdG8gYSBzY2FsYXIgVGVuc29yJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgbkRpbXMgPSBzaGFwZUhpbnRzLmxlbmd0aDtcbiAgICBjb25zdCByZXNoYXBlZERpbXMgPSBuZXcgQXJyYXk8bnVtYmVyPihuRGltcyk7XG4gICAgbGV0IHVua25vd25EaW1lbnNpb24gPSAtMTtcbiAgICBsZXQgbmV3VGVuc29yU2l6ZSA9IDE7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuRGltczsgaSsrKSB7XG4gICAgICBpZiAoc2hhcGVIaW50c1tpXSA8IC0xKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYSBkaW1lbnNpb24gaW4gc2hhcGUgaGludHMgY2Fubm90IGJlIGxlc3MgdGhhbiAtMScpO1xuICAgICAgfVxuICAgICAgaWYgKHNoYXBlSGludHNbaV0gPT09IC0xKSB7XG4gICAgICAgIGlmICh1bmtub3duRGltZW5zaW9uICE9PSAtMSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignYXQgbW9zdCBvbmUgZGltZW5zaW9uIGluIHNoYXBlIGhpbnRzIGNhbiBiZSAtMScpO1xuICAgICAgICB9XG4gICAgICAgIHVua25vd25EaW1lbnNpb24gPSBpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHNoYXBlSGludHNbaV0gPT09IDApIHtcbiAgICAgICAgICBpZiAoaSA+PSBvcmlnaW5hbERpbXMubGVuZ3RoKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RoZSBkaW1lbnNpb24gd2l0aCB2YWx1ZSB6ZXJvIGV4Y2VlZHMgdGhlIGRpbWVuc2lvbiBzaXplIG9mIHRoZSBpbnB1dCB0ZW5zb3InKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVzaGFwZWREaW1zW2ldID0gb3JpZ2luYWxEaW1zW2ldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJlc2hhcGVkRGltc1tpXSA9IHNoYXBlSGludHNbaV07XG4gICAgICAgIH1cbiAgICAgICAgbmV3VGVuc29yU2l6ZSAqPSByZXNoYXBlZERpbXNbaV07XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgb2xkVGVuc29yU2l6ZSA9IFNoYXBlVXRpbC5zaXplKG9yaWdpbmFsRGltcyk7XG4gICAgaWYgKHVua25vd25EaW1lbnNpb24gIT09IC0xKSB7XG4gICAgICBpZiAob2xkVGVuc29yU2l6ZSAlIG5ld1RlbnNvclNpemUgIT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB0aGUgaW5wdXQgdGVuc29yIGNhbm5vdCBiZSByZXNoYXBlZCB0byB0aGUgcmVxdWVzdGVkIHNoYXBlLiBJbnB1dCBzaGFwZTogWyR7XG4gICAgICAgICAgICBvcmlnaW5hbERpbXN9XSBPdXRwdXQgc2hhcGU6IFske3NoYXBlSGludHN9XWApO1xuICAgICAgfVxuICAgICAgcmVzaGFwZWREaW1zW3Vua25vd25EaW1lbnNpb25dID0gb2xkVGVuc29yU2l6ZSAvIG5ld1RlbnNvclNpemU7XG4gICAgfVxuICAgIC8vIHZhbGlkYXRlIHNpemVzIGZyb20gb3JpZ2luYWxEaW1zIGFuZCByZXNoYXBlZERpbXMgbWF0Y2hcbiAgICBlbHNlIHtcbiAgICAgIGlmIChuZXdUZW5zb3JTaXplICE9PSBvbGRUZW5zb3JTaXplKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigncmVzaGFwZWREaW1zIGFuZCBvcmlnaW5hbERpbXMgZG9uXFwndCBoYXZlIG1hdGNoaW5nIHNpemVzJyk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXNoYXBlZERpbXM7XG4gIH1cblxuICAvKipcbiAgICogU29ydHMgYSBnaXZlbiBhcnJheSBiYXNlZCBvbiB0aGUgaW5kaWNlcyBpbiB0aGUgUGVybSBhcnJheVxuICAgKiBVc2VkIGluIFRyYW5zcG9zZVxuICAgKiBAcGFyYW0gYSBBcnJheSB0byBiZSBzb3J0ZWQgc3VjaCBhcyBkaW1zIG9yIHN0cmlkZXNcbiAgICogQHBhcmFtIHBlcm0gUGVybSBnaXZlbjsgaWYgbnVsbCBhIHdpbGwgYmUgcmV2ZXJzZWRcbiAgICovXG4gIHN0YXRpYyBzb3J0QmFzZWRPblBlcm0oYTogcmVhZG9ubHkgbnVtYmVyW10sIHBlcm0/OiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBpZiAocGVybSkge1xuICAgICAgcmV0dXJuIHBlcm0ubWFwKCh2KSA9PiBhW3ZdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGEuc2xpY2UoKS5yZXZlcnNlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBhZHMgYSBnaXZlbiBzaGFwZSBhY2NvcmRpbmcgdG8gdGhlIHBhZGRpbmcgdmFsdWVzXG4gICAqIEBwYXJhbSBkaW1zIHNoYXBlIG9mIHRoZSBUZW5zb3IgdG8gYmUgcGFkZGVkXG4gICAqIEBwYXJhbSBwYWQgcGFkIHZhbHVlc1xuICAgKi9cbiAgc3RhdGljIHBhZFNoYXBlKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBwYWQ6IHJlYWRvbmx5IG51bWJlcltdKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIGNvbnN0IHJhbmsgPSBkaW1zLmxlbmd0aDtcbiAgICByZXR1cm4gZGltcy5tYXAoKHYsIGkpID0+IHYgKyBwYWRbaV0gKyBwYWRbaSArIHJhbmtdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIGlmIHRoZSB0d28gc2hhcGVzIGFyZSBpZGVudGljYWxcbiAgICogQHBhcmFtIHNoYXBlMVxuICAgKiBAcGFyYW0gc2hhcGUyXG4gICAqL1xuICBzdGF0aWMgYXJlRXF1YWwoc2hhcGUxOiByZWFkb25seSBudW1iZXJbXSwgc2hhcGUyOiByZWFkb25seSBudW1iZXJbXSk6IGJvb2xlYW4ge1xuICAgIGlmIChzaGFwZTEubGVuZ3RoICE9PSBzaGFwZTIubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBzaGFwZTEuZXZlcnkoKHYsIGkpID0+IHYgPT09IHNoYXBlMltpXSk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGVzIGlmIHRoZSBnaXZlbiBgZGltc2Agb3IgYHNoYXBlYCBpcyB2YWxpZCBpbiBPTk5YLmpzIGNvbnRleHQgYW5kIHJldHVybnMgZGF0YSBzaXplXG4gICAqIEBwYXJhbSBkaW1zIC0gaW5wdXQgYGRpbXNgIHRoYXQgbmVlZHMgdG8gYmUgY2hlY2tlZFxuICAgKi9cbiAgc3RhdGljIHZhbGlkYXRlRGltc0FuZENhbGNTaXplKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogbnVtYmVyIHtcbiAgICBpZiAoZGltcy5sZW5ndGggPiA2KSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdPbmx5IHJhbmsgMCB0byA2IGlzIHN1cHBvcnRlZCBmb3IgdGVuc29yIHNoYXBlLicpO1xuICAgIH1cbiAgICBsZXQgc2l6ZSA9IDE7XG4gICAgZm9yIChjb25zdCBuIG9mIGRpbXMpIHtcbiAgICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihuKSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBJbnZhbGlkIHNoYXBlOiAke259IGlzIG5vdCBhbiBpbnRlZ2VyYCk7XG4gICAgICB9XG4gICAgICBpZiAobiA8IDAgfHwgbiA+IDIxNDc0ODM2NDcpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCBzaGFwZTogbGVuZ3RoICR7bn0gaXMgbm90IGFsbG93ZWRgKTtcbiAgICAgIH1cbiAgICAgIHNpemUgKj0gbjtcbiAgICB9XG4gICAgcmV0dXJuIHNpemU7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB0aGUgc2hhcGUgb2Ygb3V0cHV0IHRlbnNvciB5ID0gZmxhdHRlbih4LCBheGlzKVxuICAgKiBAcGFyYW0gZGltcyAtIHNoYXBlIG9mIGlucHV0IHRlbnNvclxuICAgKiBAcGFyYW0gYXhpcyAtIGZsYXR0ZW4gYXhpcywgaW4gdGhlIHJhbmdlIFstciwgcl1cbiAgICovXG4gIHN0YXRpYyBmbGF0dGVuU2hhcGUoZGltczogcmVhZG9ubHkgbnVtYmVyW10sIGF4aXM6IG51bWJlcik6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBpZiAoYXhpcyA8IDApIHtcbiAgICAgIGF4aXMgKz0gZGltcy5sZW5ndGg7XG4gICAgfVxuICAgIGNvbnN0IHRvdGFsID0gZGltcy5yZWR1Y2UoKHgsIHkpID0+IHggKiB5LCAxKTtcbiAgICBjb25zdCByaWdodCA9IGRpbXMuc2xpY2UoYXhpcykucmVkdWNlKCh4LCB5KSA9PiB4ICogeSwgMSk7XG4gICAgY29uc3Qgb3V0cHV0RGltcyA9IFt0b3RhbCAvIHJpZ2h0LCByaWdodF07XG5cbiAgICByZXR1cm4gb3V0cHV0RGltcztcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIHRoZSBzaGFwZSBvZiBvdXRwdXQgdGVuc29yIHkgPSBzcXVlZXplKHgsIGF4ZXMpXG4gICAqIEBwYXJhbSBkaW1zIC0gc2hhcGUgb2YgaW5wdXQgdGVuc29yXG4gICAqIEBwYXJhbSBheGVzIC0gc3F1ZWV6ZSBheGVzXG4gICAqL1xuICBzdGF0aWMgc3F1ZWV6ZVNoYXBlKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBheGVzOiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBjb25zdCBvdXRwdXREaW1zID0gbmV3IEFycmF5PG51bWJlcj4oKTtcblxuICAgIC8vIHNhbml0eSBjaGVja1xuICAgIGF4ZXMgPSBTaGFwZVV0aWwubm9ybWFsaXplQXhlcyhheGVzLCBkaW1zLmxlbmd0aCk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRpbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGluU3F1ZWV6ZUxpc3QgPSBheGVzLmluZGV4T2YoaSkgPj0gMDtcbiAgICAgIGlmIChpblNxdWVlemVMaXN0ICYmIGRpbXNbaV0gIT09IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdzcXVlZXplIGFuIGF4aXMgb2Ygc2l6ZSBkaWZmZXJlbnQgdGhhbiAxJyk7XG4gICAgICB9XG5cbiAgICAgIGlmICgoYXhlcy5sZW5ndGggPT09IDAgJiYgZGltc1tpXSA+IDEpIHx8IChheGVzLmxlbmd0aCA+IDAgJiYgIWluU3F1ZWV6ZUxpc3QpKSB7XG4gICAgICAgIG91dHB1dERpbXMucHVzaChkaW1zW2ldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3V0cHV0RGltcztcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIHRoZSBzaGFwZSBvZiBvdXRwdXQgdGVuc29yIHkgPSB1bnNxdWVlemUoeCwgYXhlcylcbiAgICogQHBhcmFtIGRpbXMgLSBzaGFwZSBvZiBpbnB1dCB0ZW5zb3JcbiAgICogQHBhcmFtIGF4ZXMgLSB1bnNxdWVlemUgYXhlc1xuICAgKi9cbiAgc3RhdGljIHVuc3F1ZWV6ZVNoYXBlKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBheGVzOiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBjb25zdCBvdXRwdXREaW1zID0gbmV3IEFycmF5PG51bWJlcj4oZGltcy5sZW5ndGggKyBheGVzLmxlbmd0aCk7XG5cbiAgICAvLyBpbml0aWFsaXplIHRoZSBhcnJheSBlbGVtZW50cyB0byAwXG4gICAgb3V0cHV0RGltcy5maWxsKDApO1xuXG4gICAgLy8gc2V0IGFsbCBheGVzIGluZGljZXMgdG8gMSBpbiBvdXRwdXREaW1zIGFuZCBjaGVjayBmb3IgZHVwbGljYXRlc1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXhlcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgYXhpcyA9IFNoYXBlVXRpbC5ub3JtYWxpemVBeGlzKGF4ZXNbaV0sIG91dHB1dERpbXMubGVuZ3RoKTtcbiAgICAgIGlmIChheGlzID49IG91dHB1dERpbXMubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignXFwnYXhlc1xcJyBoYXMgYW4gb3V0IG9mIHJhbmdlIGF4aXMnKTtcbiAgICAgIH1cbiAgICAgIGlmIChvdXRwdXREaW1zW2F4aXNdICE9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignXFwnYXhlc1xcJyBoYXMgYSBkdXBsaWNhdGUgYXhpcycpO1xuICAgICAgfVxuXG4gICAgICBvdXRwdXREaW1zW2F4aXNdID0gMTtcbiAgICB9XG5cbiAgICAvLyBmaWxsIGluIHRoZSB6ZXJvIGVudHJpZXMgb2Ygb3V0cHV0RGltcyB3aXRoIHRoZSBpbnB1dCB0ZW5zb3IncyBzaGFwZVxuICAgIGxldCBpbnB1dERpbXNJdGVyYXRvciA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXREaW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAob3V0cHV0RGltc1tpXSA9PT0gMCkge1xuICAgICAgICBvdXRwdXREaW1zW2ldID0gZGltc1tpbnB1dERpbXNJdGVyYXRvcisrXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBzYW5pdHkgY2hlY2sgYXNzZXJ0aW9uLiAnaW5wdXREaW1zSXRlcmF0b3InXG4gICAgLy8gc2hvdWxkIGJlIGVxdWFsIHRvIHRoZSBsZW5ndGggb2YgJ2RpbXMnXG4gICAgaWYgKGlucHV0RGltc0l0ZXJhdG9yICE9PSBkaW1zLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd0aGUgdW5zcXVlZXplZCBkaW1lbnNpb24gY291bGQgbm90IGJlIGVzdGFibGlzaGVkJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dHB1dERpbXM7XG4gIH1cbn1cblxuLy8gYnVuY2ggb2YgaGVscGVyIG1ldGhvZHMgdGhhdCBkbyBhIHZhcmlldHkgb2YgbWF0aCBvcGVyYXRpb25zXG5leHBvcnQgY2xhc3MgTWF0aFV0aWwge1xuICAvLyB5ID0gKHgqeCkgKyB5XG4gIHN0YXRpYyBzcXIoXG4gICAgICB0YXJnZXQ6IG51bWJlcltdfFRlbnNvci5OdW1iZXJUeXBlLCBzb3VyY2U6IG51bWJlcltdfFRlbnNvci5OdW1iZXJUeXBlLCB0YXJnZXRJbmRleDogbnVtYmVyLCBzb3VyY2VJbmRleDogbnVtYmVyLFxuICAgICAgYmxvY2tTaXplOiBudW1iZXIpIHtcbiAgICBpZiAoc291cmNlSW5kZXggPCAwIHx8IHNvdXJjZUluZGV4ID49IHNvdXJjZS5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignc291cmNlSW5kZXggb3V0IG9mIGJvdW5kcycpO1xuICAgIH1cbiAgICBpZiAodGFyZ2V0SW5kZXggPCAwIHx8IHRhcmdldEluZGV4ID49IHRhcmdldC5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndGFyZ2V0SW5kZXggb3V0IG9mIGJvdW5kcycpO1xuICAgIH1cbiAgICBpZiAoc291cmNlSW5kZXggKyBibG9ja1NpemUgPiBzb3VyY2UubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NvdXJjZSBpbmRpY2VzIHRvIGJlIGNvcGllZCBhcmUgb3V0c2lkZSBib3VuZHMnKTtcbiAgICB9XG4gICAgaWYgKHRhcmdldEluZGV4ICsgYmxvY2tTaXplID4gdGFyZ2V0Lmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd0YXJnZXQgYXJyYXkgaXMgdG9vIHNtYWxsIHRvIGhvbGQgcmVzdWx0Jyk7XG4gICAgfVxuXG4gICAgZm9yIChsZXQgb2Zmc2V0ID0gMDsgb2Zmc2V0IDwgYmxvY2tTaXplOyBvZmZzZXQrKykge1xuICAgICAgdGFyZ2V0W3RhcmdldEluZGV4ICsgb2Zmc2V0XSArPSBNYXRoLnBvdyhzb3VyY2Vbc291cmNlSW5kZXggKyBvZmZzZXRdLCAyKTtcbiAgICB9XG4gIH1cblxuICAvLyB5ID0gYXggKyB5XG4gIHN0YXRpYyBheHB5KFxuICAgICAgdGFyZ2V0OiBudW1iZXJbXXxUZW5zb3IuTnVtYmVyVHlwZSwgc291cmNlOiBudW1iZXJbXXxUZW5zb3IuTnVtYmVyVHlwZSwgdGFyZ2V0SW5kZXg6IG51bWJlciwgc291cmNlSW5kZXg6IG51bWJlcixcbiAgICAgIGJsb2NrU2l6ZTogbnVtYmVyLCBhbHBoYTogbnVtYmVyKSB7XG4gICAgaWYgKHNvdXJjZUluZGV4IDwgMCB8fCBzb3VyY2VJbmRleCA+PSBzb3VyY2UubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NvdXJjZUluZGV4IG91dCBvZiBib3VuZHMnKTtcbiAgICB9XG4gICAgaWYgKHRhcmdldEluZGV4IDwgMCB8fCB0YXJnZXRJbmRleCA+PSB0YXJnZXQubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RhcmdldEluZGV4IG91dCBvZiBib3VuZHMnKTtcbiAgICB9XG4gICAgaWYgKHNvdXJjZUluZGV4ICsgYmxvY2tTaXplID4gc291cmNlLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzb3VyY2UgaW5kaWNlcyB0byBiZSBjb3BpZWQgYXJlIG91dHNpZGUgYm91bmRzJyk7XG4gICAgfVxuICAgIGlmICh0YXJnZXRJbmRleCArIGJsb2NrU2l6ZSA+IHRhcmdldC5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndGFyZ2V0IGFycmF5IGlzIHRvbyBzbWFsbCB0byBob2xkIHJlc3VsdCcpO1xuICAgIH1cblxuICAgIGZvciAobGV0IG9mZnNldCA9IDA7IG9mZnNldCA8IGJsb2NrU2l6ZTsgb2Zmc2V0KyspIHtcbiAgICAgIHRhcmdldFt0YXJnZXRJbmRleCArIG9mZnNldF0gKz0gKGFscGhhICogc291cmNlW3NvdXJjZUluZGV4ICsgb2Zmc2V0XSk7XG4gICAgfVxuICB9XG5cbiAgLy8geSA9IHBvdyh4LCBiKVxuICBzdGF0aWMgcG93eChcbiAgICAgIHRhcmdldDogbnVtYmVyW118VGVuc29yLk51bWJlclR5cGUsIHNvdXJjZTogbnVtYmVyW118VGVuc29yLk51bWJlclR5cGUsIHRhcmdldEluZGV4OiBudW1iZXIsIHNvdXJjZUluZGV4OiBudW1iZXIsXG4gICAgICBibG9ja1NpemU6IG51bWJlciwgYjogbnVtYmVyKSB7XG4gICAgaWYgKHNvdXJjZUluZGV4IDwgMCB8fCBzb3VyY2VJbmRleCA+PSBzb3VyY2UubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NvdXJjZUluZGV4IG91dCBvZiBib3VuZHMnKTtcbiAgICB9XG4gICAgaWYgKHRhcmdldEluZGV4IDwgMCB8fCB0YXJnZXRJbmRleCA+PSB0YXJnZXQubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RhcmdldEluZGV4IG91dCBvZiBib3VuZHMnKTtcbiAgICB9XG4gICAgaWYgKHNvdXJjZUluZGV4ICsgYmxvY2tTaXplID4gc291cmNlLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzb3VyY2UgaW5kaWNlcyB0byBiZSBjb3BpZWQgYXJlIG91dHNpZGUgYm91bmRzJyk7XG4gICAgfVxuICAgIGlmICh0YXJnZXRJbmRleCArIGJsb2NrU2l6ZSA+IHRhcmdldC5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndGFyZ2V0IGFycmF5IGlzIHRvbyBzbWFsbCB0byBob2xkIHJlc3VsdCcpO1xuICAgIH1cblxuICAgIGZvciAobGV0IG9mZnNldCA9IDA7IG9mZnNldCA8IGJsb2NrU2l6ZTsgb2Zmc2V0KyspIHtcbiAgICAgIHRhcmdldFt0YXJnZXRJbmRleCArIG9mZnNldF0gPSBNYXRoLnBvdyhzb3VyY2Vbc291cmNlSW5kZXggKyBvZmZzZXRdLCBiKTtcbiAgICB9XG4gIH1cblxuICAvLyB5ID0geCAqIHlcbiAgc3RhdGljIG11bChcbiAgICAgIHRhcmdldDogbnVtYmVyW118VGVuc29yLk51bWJlclR5cGUsIHNvdXJjZTogbnVtYmVyW118VGVuc29yLk51bWJlclR5cGUsIHRhcmdldEluZGV4OiBudW1iZXIsIHNvdXJjZUluZGV4OiBudW1iZXIsXG4gICAgICBibG9ja1NpemU6IG51bWJlcikge1xuICAgIGlmIChzb3VyY2VJbmRleCA8IDAgfHwgc291cmNlSW5kZXggPj0gc291cmNlLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzb3VyY2VJbmRleCBvdXQgb2YgYm91bmRzJyk7XG4gICAgfVxuICAgIGlmICh0YXJnZXRJbmRleCA8IDAgfHwgdGFyZ2V0SW5kZXggPj0gdGFyZ2V0Lmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd0YXJnZXRJbmRleCBvdXQgb2YgYm91bmRzJyk7XG4gICAgfVxuICAgIGlmIChzb3VyY2VJbmRleCArIGJsb2NrU2l6ZSA+IHNvdXJjZS5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignc291cmNlIGluZGljZXMgdG8gYmUgY29waWVkIGFyZSBvdXRzaWRlIGJvdW5kcycpO1xuICAgIH1cbiAgICBpZiAodGFyZ2V0SW5kZXggKyBibG9ja1NpemUgPiB0YXJnZXQubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RhcmdldCBhcnJheSBpcyB0b28gc21hbGwgdG8gaG9sZCByZXN1bHQnKTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBvZmZzZXQgPSAwOyBvZmZzZXQgPCBibG9ja1NpemU7IG9mZnNldCsrKSB7XG4gICAgICB0YXJnZXRbdGFyZ2V0SW5kZXggKyBvZmZzZXRdID0gKHNvdXJjZVtzb3VyY2VJbmRleCArIG9mZnNldF0gKiB0YXJnZXRbdGFyZ2V0SW5kZXggKyBvZmZzZXRdKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFNwbGl0VXRpbCB7XG4gIC8qKlxuICAgKiBDYWxjdWxhdGVzIG5ldyBTaGFwZXMgZnJvbSBleGlzdGluZyBvbmUgYW5kIHRoZSBzcGxpdHMgZ2l2ZW4gYWxvbmcgdGhlIGF4aXMgcHJvdmlkZXNcbiAgICogQHBhcmFtIGRpbXMgU2hhcGUgb2YgdGhlIFRlbnNvciB0byBiZSBzcGxpdHRlZCBpbnRvIHR3byBvciBtb3JlIFNoYXBlc1xuICAgKiBAcGFyYW0gYXhpcyBUaGUgZGltZW5zaW9uIGFsb25nIHdoaWNoIHRoZSBUZW5zb3Igd2lsbCBiZSBzcGxpdFxuICAgKiBAcGFyYW0gc3BsaXRzIE9mZnNldHMgZm9yIHRoZSBzdGFydCBvZiBlYWNoIHNwbGl0XG4gICAqL1xuICBzdGF0aWMgc3BsaXRTaGFwZShkaW1zOiByZWFkb25seSBudW1iZXJbXSwgYXhpczogbnVtYmVyLCBzcGxpdDogbnVtYmVyW10sIG51bU91dHB1dHM/OiBudW1iZXIpOlxuICAgICAgW251bWJlcltdW10sIG51bWJlcltdXSB7XG4gICAgaWYgKHNwbGl0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgaWYgKCFudW1PdXRwdXRzKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignbmVlZCB0byBrbm93IG51bWJlciBvZiBvdXRwdXRzIHdoZW4gdGhlIFxcJ3NwbGl0XFwnIGF0dHJpYnV0ZSBpcyBub3Qgc3BlY2lmaWVkJyk7XG4gICAgICB9XG4gICAgICBTcGxpdFV0aWwuZGV0ZXJtaW5lU3BsaXQoZGltc1theGlzXSwgbnVtT3V0cHV0cywgc3BsaXQpO1xuICAgIH1cblxuICAgIGNvbnN0IHNoYXBlczogbnVtYmVyW11bXSA9IFtdO1xuICAgIGNvbnN0IG9mZnNldHMgPSBbMF07XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzcGxpdC5sZW5ndGg7ICsraSkge1xuICAgICAgaWYgKGkgIT09IDApIHtcbiAgICAgICAgb2Zmc2V0cy5wdXNoKG9mZnNldHNbaSAtIDFdICsgc3BsaXRbaSAtIDFdKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHNoYXBlID0gZGltcy5zbGljZSgpO1xuICAgICAgc2hhcGVbYXhpc10gPSBzcGxpdFtpXTtcbiAgICAgIHNoYXBlcy5wdXNoKHNoYXBlKTtcbiAgICB9XG4gICAgcmV0dXJuIFtzaGFwZXMsIG9mZnNldHNdO1xuICB9XG5cbiAgc3RhdGljIGRldGVybWluZVNwbGl0KG51bUVsZW1lbnRzQWxvbmdBeGlzOiBudW1iZXIsIG51bU91dHB1dHM6IG51bWJlciwgc3BsaXQ6IG51bWJlcltdKSB7XG4gICAgLy8gSWYgJ3NwbGl0JyBpcyBub3Qgc3BlY2lmaWVkIGJ5IHRoZSB1c2VyLCB3ZSBuZWVkIHRvIHBhcnRpdGlvbiB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIGVxdWFsbHkgYW1vbmcgdGhlIG91dHB1dHNcbiAgICBpZiAobnVtRWxlbWVudHNBbG9uZ0F4aXMgJSBudW1PdXRwdXRzICE9PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Nhbm5vdCBzcGxpdCB0ZW5zb3IgdG8gZXF1YWwgc2l6ZWQgcGFydHMnKTtcbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1PdXRwdXRzOyArK2kpIHtcbiAgICAgIHNwbGl0LnB1c2gobnVtRWxlbWVudHNBbG9uZ0F4aXMgLyBudW1PdXRwdXRzKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFJlZHVjZVV0aWwge1xuICAvKipcbiAgICogUGVyZm9ybSByZWR1Y2Ugb3BlcmF0aW9ucyBvbiB0aGUgc3BlY2lmaWMgb3BlcmF0b3JcbiAgICogQHBhcmFtIGEgSW5wdXQgdGVuc29yIGRhdGFcbiAgICogQHBhcmFtIGF4ZXMgVGhlIGRpbWVuc2lvbnMgYWxvbmcgd2hpY2ggdGhlIFRlbnNvciB3aWxsIGJlIHJlZHVjZWRcbiAgICogQHBhcmFtIGtlZXBkaW1zIElmIHNldCB0byB0cnVlLCB0aGUgYXhlcyB3aGljaCBhcmUgcmVkdWNlZCBhcmUgbGVmdCBpbiB0aGVcbiAgICogICAgcmVzdWx0IGFzIGRpbWVuc2lvbnMgd2l0aCBzaXplIG9uZS5cbiAgICogQHBhcmFtIG9wMSBUaGUgb3BlcmF0aW9uIHRvIGJlIHBlcmZvcm1lZCBvbiBlYWNoIGVsZW1lbnQgaW4gdGhlIHRlbnNvclxuICAgKiBAcGFyYW0gb3AyIFRoZSBvcGVyYXRpb24gdG8gYmUgcGVyZm9ybWVkIGJldHdlZW4gZWxlbWVudHMgaW4gdGhlIHRlbnNvclxuICAgKi9cbiAgc3RhdGljIGNhbGNSZWR1Y2UoXG4gICAgICBhOiBUZW5zb3IsIGF4ZXM6IG51bWJlcltdLCBrZWVwZGltczogYm9vbGVhbiwgb3AxOiAoYjogbnVtYmVyKSA9PiBudW1iZXIsXG4gICAgICBvcDI6IChhOiBudW1iZXIsIGI6IG51bWJlcikgPT4gbnVtYmVyKTogVGVuc29yIHtcbiAgICBjb25zdCBkaW1zID0gYS5kaW1zLnNsaWNlKDApO1xuICAgIC8vIGlmIGF4ZXMgaXMgbm90IHNldCwgcGVyZm9ybSByZWR1Y2Ugb24gYWxsIGF4ZXNcbiAgICBpZiAoYXhlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIGRpbXMuZm9yRWFjaCgoZCwgaW5kKSA9PiBheGVzLnB1c2goaW5kKSk7XG4gICAgfVxuICAgIC8vIGdldCBhIHRlbXBvcmFyeSBicm9hZGNhc3RhYmxlIG91dHB1dCBzaGFwZVxuICAgIGNvbnN0IG91dHB1dERpbXMgPSBSZWR1Y2VVdGlsLmNhbGNSZWR1Y2VTaGFwZShkaW1zLCBheGVzLCB0cnVlKTtcblxuICAgIC8vIGxvb3AgdGhyb3VnaCB0aGUgb3V0cHV0IGFuZCBjYWxjdWxhdGUgcmVzdWx0IG9uZSBieSBvbmVcbiAgICBjb25zdCBzaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0RGltcyk7XG4gICAgY29uc3QgeSA9IG5ldyBUZW5zb3Iob3V0cHV0RGltcywgYS50eXBlKTtcbiAgICBjb25zdCBzdHJpZGVzID0gU2hhcGVVdGlsLmNvbXB1dGVTdHJpZGVzKG91dHB1dERpbXMpO1xuICAgIGNvbnN0IGlucHV0U3RyaWRlcyA9IFNoYXBlVXRpbC5jb21wdXRlU3RyaWRlcyhkaW1zKTtcbiAgICBjb25zdCBpbmRpY2VzWSA9IG5ldyBBcnJheShkaW1zLmxlbmd0aCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgIGNvbnN0IGluZGljZXMgPSBTaGFwZVV0aWwub2Zmc2V0VG9JbmRpY2VzKGksIHN0cmlkZXMpO1xuICAgICAgLy8gbWFwIGluZGV4XG4gICAgICBCcm9hZGNhc3RVdGlsLmZpbGxJbmRleChpbmRpY2VzLCBkaW1zLCBpbmRpY2VzWSk7XG4gICAgICB5LnNldChcbiAgICAgICAgICBpbmRpY2VzLFxuICAgICAgICAgIFJlZHVjZVV0aWwuY2FsY1JlZHVjZUJ5QXhpcyhcbiAgICAgICAgICAgICAgYS5udW1iZXJEYXRhLCBheGVzLCBkaW1zLCAwLCBTaGFwZVV0aWwuaW5kaWNlc1RvT2Zmc2V0KGluZGljZXNZLCBpbnB1dFN0cmlkZXMpLCBvcDEsIG9wMikpO1xuICAgIH1cblxuICAgIGlmIChrZWVwZGltcykge1xuICAgICAgcmV0dXJuIHk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGtlZXBkaW1zID09IDAsIGNhbGN1bGF0ZSB0aGUgZXhwZWN0ZWQgc2hhcGVcbiAgICAgIHJldHVybiBuZXcgVGVuc29yKFxuICAgICAgICAgIFJlZHVjZVV0aWwuY2FsY1JlZHVjZVNoYXBlKGRpbXMsIGF4ZXMsIGtlZXBkaW1zKSwgeS50eXBlLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgeS5kYXRhLCB5LmRhdGFJZCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBlcmZvcm0gcmVkdWNlIG9wZXJhdGlvbnMgb24gdGhlIHNwZWNpZmljIG9wZXJhdG9yIG9uIHNwZWNpZmljIGF4ZXNcbiAgICogQHBhcmFtIGEgSW5wdXQgdGVuc29yIGRhdGFcbiAgICogQHBhcmFtIGF4ZXMgVGhlIGRpbWVuc2lvbnMgYWxvbmcgd2hpY2ggdGhlIFRlbnNvciB3aWxsIGJlIHJlZHVjZWRcbiAgICogQHBhcmFtIGRpbXMgVGhlIGlucHV0IGRpbWVuc2lvbi5cbiAgICogQHBhcmFtIGN1ckF4aXNJbmQgSW5kZXggaW4gYXhlcyBzcGVjaWZ5aW5nIHRoZSBjdXJyZW50IGRpbWVuc2lvbiBhbG9uZ1xuICAgKiAgICAgIHdoaWNoIHRoZSB0ZW5zb3Igd2lsbCBiZSByZWR1Y2VkXG4gICAqIEBwYXJhbSBwb3MgVGhlIGN1cnJlbnQgaW5kZXggb2YgZWxlbWVudCB0byBwZXJmb3JtIG9wZXJhdGlvblxuICAgKiBAcGFyYW0gb3AxIFRoZSBvcGVyYXRpb24gdG8gYmUgcGVyZm9ybWVkIG9uIGVhY2ggZWxlbWVudCBpbiB0aGUgdGVuc29yXG4gICAqIEBwYXJhbSBvcDIgVGhlIG9wZXJhdGlvbiB0byBiZSBwZXJmb3JtZWQgYmV0d2VlbiBlbGVtZW50cyBpbiB0aGUgdGVuc29yXG4gICAqL1xuICBzdGF0aWMgY2FsY1JlZHVjZUJ5QXhpcyhcbiAgICAgIGlucHV0OiBUZW5zb3IuTnVtYmVyVHlwZSwgYXhlczogbnVtYmVyW10sIGRpbXM6IG51bWJlcltdLCBjdXJBeGlzSW5kOiBudW1iZXIsIHBvczogbnVtYmVyLFxuICAgICAgb3AxOiAoYjogbnVtYmVyKSA9PiBudW1iZXIsIG9wMjogKGE6IG51bWJlciwgYjogbnVtYmVyKSA9PiBudW1iZXIpOiBudW1iZXIge1xuICAgIGxldCByZXMgPSAwO1xuICAgIGlmIChjdXJBeGlzSW5kID49IGF4ZXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gb3AxKGlucHV0W3Bvc10pO1xuICAgIH1cbiAgICBjb25zdCBheGlzID0gYXhlc1tjdXJBeGlzSW5kXTtcbiAgICBjb25zdCBzdGVwID0gYXhpcyA+PSBkaW1zLmxlbmd0aCA/IDEgOiBTaGFwZVV0aWwuc2l6ZShkaW1zLnNsaWNlKGF4aXMgKyAxKSk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkaW1zW2F4aXNdOyBpKyspIHtcbiAgICAgIHJlcyA9IGkgPT09IDAgPyBSZWR1Y2VVdGlsLmNhbGNSZWR1Y2VCeUF4aXMoaW5wdXQsIGF4ZXMsIGRpbXMsIGN1ckF4aXNJbmQgKyAxLCBwb3MsIG9wMSwgb3AyKSA6XG4gICAgICAgICAgICAgICAgICAgICAgb3AyKHJlcywgUmVkdWNlVXRpbC5jYWxjUmVkdWNlQnlBeGlzKGlucHV0LCBheGVzLCBkaW1zLCBjdXJBeGlzSW5kICsgMSwgcG9zLCBvcDEsIG9wMikpO1xuICAgICAgcG9zICs9IHN0ZXA7XG4gICAgfVxuICAgIHJldHVybiByZXM7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIHRoZSBleHBlY3RlZCBzaGFwZSBvZiBhIHJlZHVjZSBvcGVyYXRpb25cbiAgICogQHBhcmFtIGRpbXMgVGhlIGlucHV0IHRlbnNvciBkaW1lbnNpb25cbiAgICogQHBhcmFtIGF4ZXMgVGhlIGRpbWVuc2lvbnMgYWxvbmcgd2hpY2ggdGhlIFRlbnNvciB3aWxsIGJlIHJlZHVjZWRcbiAgICogQHBhcmFtIGtlZXBkaW1zIElmIHNldCB0byB0cnVlLCB0aGUgYXhlcyB3aGljaCBhcmUgcmVkdWNlZCBhcmUgbGVmdCBpbiB0aGVcbiAgICogICAgcmVzdWx0IGFzIGRpbWVuc2lvbnMgd2l0aCBzaXplIG9uZS5cbiAgICovXG4gIHN0YXRpYyBjYWxjUmVkdWNlU2hhcGUoZGltczogcmVhZG9ubHkgbnVtYmVyW10sIGF4ZXM6IHJlYWRvbmx5IG51bWJlcltdLCBrZWVwRGltczogYm9vbGVhbik6IG51bWJlcltdIHtcbiAgICBjb25zdCBvdXRwdXREaW1zID0gZGltcy5zbGljZSgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXhlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGtlZXBEaW1zKSB7XG4gICAgICAgIG91dHB1dERpbXNbYXhlc1tpXV0gPSAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3V0cHV0RGltc1theGVzW2ldXSA9IDA7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBvdXRwdXREaW1zLmZpbHRlcihkaW0gPT4gZGltICE9PSAwKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgUG9vbENvbnZVdGlsIHtcbiAgLyoqXG4gICAqIEFkanVzdCB0aGUga2VybmVsLCBzdHJpZGVzLCBwYWRzIHRvIGNvcnJlY3QgcmFuay4gU2V0IHRvIGRlZmF1bHQgdmFsdWUgaWYgbm90IHByZXNlbnRcbiAgICogQHBhcmFtIGlzR2xvYmFsT3BlcmF0b3IgSWYgdHJ1ZSwgcGVyZm9ybSBnbG9iYWwgcG9vbGluZy5cbiAgICogQHBhcmFtIGlucHV0RGltcyBUaGUgaW5wdXQgdGVuc29yIGRpbWVuc2lvbi5cbiAgICogQHBhcmFtIGtlcm5lbFNoYXBlIFRoZSBzaXplIG9mIHRoZSBrZXJuZWwgYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0gc3RyaWRlcyBTdHJpZGUgYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0gZGlsYXRpb25zIERpbGF0aW9uIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIHBhZHMgUGFkZGluZyBmb3IgdGhlIGJlZ2lubmluZyBhbmQgZW5kaW5nIGFsb25nIGVhY2ggYXhpcy5cbiAgICovXG4gIHN0YXRpYyBhZGp1c3RQb29sQXR0cmlidXRlcyhcbiAgICAgIGlzR2xvYmFsT3BlcmF0b3I6IGJvb2xlYW4sIGlucHV0RGltczogcmVhZG9ubHkgbnVtYmVyW10sIGtlcm5lbFNoYXBlOiBudW1iZXJbXSwgc3RyaWRlczogbnVtYmVyW10sXG4gICAgICBkaWxhdGlvbnM6IG51bWJlcltdLCBwYWRzOiBudW1iZXJbXSkge1xuICAgIGlmICghaXNHbG9iYWxPcGVyYXRvciAmJiBrZXJuZWxTaGFwZS5sZW5ndGggIT09IGlucHV0RGltcy5sZW5ndGggLSAyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2xlbmd0aCBvZiBzcGVjaWZpZWQga2VybmVsIHNoYXBlcyBzaG91bGQgYmUgMiBsZXNzIHRoYW4gbGVuZ3RoIG9mIGlucHV0IGRpbWVuc2lvbnMnKTtcbiAgICB9XG5cbiAgICBpZiAoaXNHbG9iYWxPcGVyYXRvcikge1xuICAgICAgLy8gYWRqdXN0IGtlcm5lbCBzaGFwZSB0byBjb3ZlciB0aGUgaW5wdXQgZGltc1xuICAgICAgZm9yIChsZXQgZGltID0gMDsgZGltIDwgaW5wdXREaW1zLmxlbmd0aCAtIDI7IGRpbSsrKSB7XG4gICAgICAgIGlmIChkaW0gPj0ga2VybmVsU2hhcGUubGVuZ3RoKSB7XG4gICAgICAgICAga2VybmVsU2hhcGUucHVzaChpbnB1dERpbXNbZGltICsgMl0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGtlcm5lbFNoYXBlW2RpbV0gPSBpbnB1dERpbXNbZGltICsgMl07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBhZGp1c3Qgc3RyaWRlcyBsZW5ndGggdG8gbWF0Y2gga2VybmVsIHNoYXBlIGxlbmd0aFxuICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGtlcm5lbFNoYXBlLmxlbmd0aDsgZGltKyspIHtcbiAgICAgIGlmIChkaW0gPCBzdHJpZGVzLmxlbmd0aCkge1xuICAgICAgICBpZiAoc3RyaWRlc1tkaW1dIDwgMCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignc3RyaWRlcyBzaG91bGQgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDEnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RyaWRlcy5wdXNoKDEpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGFkanVzdCBkaWxhdGlvbiB2YWx1ZVxuICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGtlcm5lbFNoYXBlLmxlbmd0aDsgZGltKyspIHtcbiAgICAgIGlmIChkaW0gPCBkaWxhdGlvbnMubGVuZ3RoKSB7XG4gICAgICAgIGlmIChkaWxhdGlvbnNbZGltXSA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RpbGF0aW9ucyBzaG91bGQgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDEnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGlsYXRpb25zLnB1c2goMSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gYWRqdXN0IHBhZHMgbGVuZ3RoIHRvIG1hdGNoIDIgKiBrZXJuZWwgc2hhcGUgbGVuZ3RoXG4gICAgZm9yIChsZXQgZGltID0gMDsgZGltIDwga2VybmVsU2hhcGUubGVuZ3RoICogMjsgZGltKyspIHtcbiAgICAgIGlmIChkaW0gPCBwYWRzLmxlbmd0aCkge1xuICAgICAgICBpZiAocGFkc1tkaW1dIDwgMCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcigncGFkIHNob3VsZCBiZSBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gMScpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwYWRzLnB1c2goMCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gc2FuaXR5IGNoZWNrcyBmb3IgdmFsdWVzIGluIGtlcm5lbCBzaGFwZXMgYW5kIHBhZHNcbiAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBrZXJuZWxTaGFwZS5sZW5ndGg7IGRpbSsrKSB7XG4gICAgICBpZiAoa2VybmVsU2hhcGVbZGltXSA8PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcigna2VybmVsIHNoYXBlcyBuZWVkIHRvIGJlIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChwYWRzW2RpbV0gPj0ga2VybmVsU2hhcGVbZGltXSB8fCBwYWRzW2RpbSArIGtlcm5lbFNoYXBlLmxlbmd0aF0gPj0ga2VybmVsU2hhcGVbZGltXSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BhZHMgc2hvdWxkIGJlIHNtYWxsZXIgdGhhbiBrZXJuZWwnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBhZGp1c3QgcGFkIHZhbHVlcyBiYXNlZCBvbiAnYXV0b1BhZCcgYXR0cmlidXRlXG4gIHN0YXRpYyBhZGp1c3RQYWRzQmFzZWRPbkF1dG9QYWQoXG4gICAgICBpbnB1dERpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXSwgZGlsYXRpb25zOiByZWFkb25seSBudW1iZXJbXSxcbiAgICAgIGtlcm5lbFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgcGFkczogbnVtYmVyW10sIGF1dG9QYWQ/OiBzdHJpbmcpIHtcbiAgICBpZiAoIWF1dG9QYWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAocGFkcy5sZW5ndGggIT09IDIgKiAoaW5wdXREaW1zLmxlbmd0aCAtIDIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2xlbmd0aCBvZiBwYWRzIHNob3VsZCBiZSB0d2ljZSB0aGUgbGVuZ3RoIG9mIGRhdGEgZGltZW5zaW9ucycpO1xuICAgIH1cblxuICAgIGlmIChzdHJpZGVzLmxlbmd0aCAhPT0gKGlucHV0RGltcy5sZW5ndGggLSAyKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdsZW5ndGggb2Ygc3RyaWRlcyBzaG91bGQgYmUgdGhlIGxlbmd0aCBvZiBkYXRhIGRpbWVuc2lvbnMnKTtcbiAgICB9XG5cbiAgICBpZiAoa2VybmVsU2hhcGUubGVuZ3RoICE9PSAoaW5wdXREaW1zLmxlbmd0aCAtIDIpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2xlbmd0aCBvZiBrZXJuZWwgc2hhcGVzIHNob3VsZCBiZSB0aGUgbGVuZ3RoIG9mIGRhdGEgZGltZW5zaW9ucycpO1xuICAgIH1cblxuICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGlucHV0RGltcy5sZW5ndGggLSAyOyBkaW0rKykge1xuICAgICAgUG9vbENvbnZVdGlsLmFkanVzdFBhZEFuZFJldHVyblNoYXBlKFxuICAgICAgICAgIGlucHV0RGltc1tkaW0gKyAyXSwgc3RyaWRlc1tkaW1dLCBkaWxhdGlvbnNbZGltXSwga2VybmVsU2hhcGVbZGltXSwgcGFkcywgZGltLCBkaW0gKyBpbnB1dERpbXMubGVuZ3RoIC0gMixcbiAgICAgICAgICBhdXRvUGFkKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIHRoZSBvdXRwdXQgc2hhcGUgZm9yIFBvb2wgb3BzIGJhc2VkIG9uIGlucHV0IGF0dHJpYnV0ZXMuIChTaG91bGQgYmUgdXNlZCBvbmx5IGZvciBQb29sIG9wcylcbiAgICogQHBhcmFtIGlzR2xvYmFsT3BlcmF0b3IgSWYgdHJ1ZSwgcGVyZm9ybSBnbG9iYWwgcG9vbGluZy5cbiAgICogQHBhcmFtIGlucHV0RGltcyBUaGUgaW5wdXQgdGVuc29yIGRpbWVuc2lvbi4gKGlucHV0c1swXS5kaW1zKVxuICAgKiBAcGFyYW0gc3RyaWRlcyBTdHJpZGUgYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0gZGlsYXRpb25zIERpbGF0aW9uIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIGtlcm5lbFNoYXBlIFRoZSBzaXplIG9mIHRoZSBrZXJuZWwgYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0gcGFkcyBQYWRkaW5nIGZvciB0aGUgYmVnaW5uaW5nIGFuZCBlbmRpbmcgYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0gYXV0b1BhZCBERVBSRUNBVEVEIGF0dHJpYnV0ZSBzdXBwb3J0ZWQgZm9yIGxlZ2FjeSBtb2RlbHMuIFNwZWNpZmllcyBob3cgdG8gaW1wbGljaXRseSBjYWxjdWxhdGUgcGFkcyBpbiBlYWNoXG4gICAqICAgICBkaW1lbnNpb24uIENhbiB0YWtlIHZhbHVlcyBOT1RTRVQsIFNBTUVfVVBQRVIsIFNBTUVfTE9XRVIsIG9yIFZBTElELlxuICAgKi9cbiAgc3RhdGljIGNvbXB1dGVQb29sT3V0cHV0U2hhcGUoXG4gICAgICBpc0dsb2JhbE9wZXJhdG9yOiBib29sZWFuLCBpbnB1dERpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBzdHJpZGVzOiBudW1iZXJbXSwgZGlsYXRpb25zOiBudW1iZXJbXSxcbiAgICAgIGtlcm5lbFNoYXBlOiBudW1iZXJbXSwgcGFkczogbnVtYmVyW10sIGF1dG9QYWQ/OiBzdHJpbmcpOiBudW1iZXJbXSB7XG4gICAgaWYgKGlucHV0RGltcy5sZW5ndGggPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnB1dCBzaGFwZSBtdXN0IGJlIG9mIHNpemUgZ3JlYXRlciB0aGFuIDAnKTtcbiAgICB9XG5cbiAgICAvLyBBZGQgYmF0Y2ggc2l6ZSBhbmQgbnVtYmVyIG9mIGNoYW5uZWxzIG9mIG91dHB1dFxuICAgIGNvbnN0IG91dHB1dERpbXMgPSBbaW5wdXREaW1zWzBdLCBpbnB1dERpbXNbMV1dO1xuXG4gICAgUG9vbENvbnZVdGlsLmNvbXB1dGVTaGFwZUhlbHBlcihcbiAgICAgICAgaXNHbG9iYWxPcGVyYXRvciwgaW5wdXREaW1zLCBvdXRwdXREaW1zLCBzdHJpZGVzLCBkaWxhdGlvbnMsIGtlcm5lbFNoYXBlLCBwYWRzLCBhdXRvUGFkKTtcbiAgICByZXR1cm4gb3V0cHV0RGltcztcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgdGhlIG91dHB1dCBzaGFwZSBmb3IgQ29udiBvcCBiYXNlZCBvbiBpbnB1dCBhdHRyaWJ1dGVzLiAoU2hvdWxkIGJlIHVzZWQgb25seSBmb3IgQ29udiBvcClcbiAgICogQHBhcmFtIGlucHV0RGltcyBUaGUgaW5wdXQgdGVuc29yIGRpbWVuc2lvbi4gKGlucHV0c1swXS5kaW1zKVxuICAgKiBAcGFyYW0gZmlsdGVyRGltcyBUaGUgZmlsdGVyIHRlbnNvciBkaW1lbnNpb24uIChpbnB1dHNbMV0uZGltcylcbiAgICogQHBhcmFtIHN0cmlkZXMgU3RyaWRlIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIGtlcm5lbFNoYXBlIFRoZSBzaXplIG9mIHRoZSBrZXJuZWwgYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0gcGFkcyBQYWRkaW5nIGZvciB0aGUgYmVnaW5uaW5nIGFuZCBlbmRpbmcgYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0gYXV0b1BhZCBERVBSRUNBVEVEIGF0dHJpYnV0ZSBzdXBwb3J0ZWQgZm9yIGxlZ2FjeSBtb2RlbHMuIFNwZWNpZmllcyBob3cgdG8gaW1wbGljaXRseSBjYWxjdWxhdGUgcGFkcyBpbiBlYWNoXG4gICAqICAgICBkaW1lbnNpb24uIENhbiB0YWtlIHZhbHVlcyBOT1RTRVQsIFNBTUVfVVBQRVIsIFNBTUVfTE9XRVIsIG9yIFZBTElELlxuICAgKi9cbiAgc3RhdGljIGNvbXB1dGVDb252T3V0cHV0U2hhcGUoXG4gICAgICBpbnB1dERpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBmaWx0ZXJEaW1zOiByZWFkb25seSBudW1iZXJbXSwgc3RyaWRlczogbnVtYmVyW10sIGRpbGF0aW9uczogbnVtYmVyW10sXG4gICAgICBrZXJuZWxTaGFwZTogbnVtYmVyW10sIHBhZHM6IG51bWJlcltdLCBhdXRvUGFkPzogc3RyaW5nKTogbnVtYmVyW10ge1xuICAgIGlmIChpbnB1dERpbXMubGVuZ3RoIDw9IDAgfHwgZmlsdGVyRGltcy5sZW5ndGggPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGlucHV0IHRlbnNvciBkaW1zIG9yIGludmFsaWQgZmlsdGVyIHRlbnNvciBkaW1zJyk7XG4gICAgfVxuXG4gICAgLy8gQWRkIGJhdGNoIHNpemUgYW5kIG51bWJlciBvZiBjaGFubmVscyBvZiBvdXRwdXRcbiAgICBjb25zdCBvdXRwdXREaW1zID0gW2lucHV0RGltc1swXSwgZmlsdGVyRGltc1swXV07XG5cbiAgICBQb29sQ29udlV0aWwuY29tcHV0ZVNoYXBlSGVscGVyKGZhbHNlLCBpbnB1dERpbXMsIG91dHB1dERpbXMsIHN0cmlkZXMsIGRpbGF0aW9ucywga2VybmVsU2hhcGUsIHBhZHMsIGF1dG9QYWQpO1xuICAgIHJldHVybiBvdXRwdXREaW1zO1xuICB9XG5cbiAgLy8gd2lsbCBjb21wdXRlIG91dHB1dCBzaGFwZXMgZm9yIGRhdGEgZGltZW5zaW9ucyBPTkxZIChpLmUuKSBubyBiYXRjaCBzaXplIGFuZCBjaGFubmVsc1xuICAvLyBjYWxsZWQgYnkgY29tcHV0ZVBvb2xPdXRwdXRTaGFwZSgpIGFuZCBjb21wdXRlQ29udk91dHB1dFNoYXBlKClcbiAgLy8gYWRqdXN0IHBhZHMgYmFzZWQgb24gJ2F1dG9QYWQnIGF0dHJpYnV0ZSBwcmlvciB0byBzaGFwZSBjb21wdXRhdGlvblxuICBwcml2YXRlIHN0YXRpYyBjb21wdXRlU2hhcGVIZWxwZXIoXG4gICAgICBpc0dsb2JhbE9wZXJhdG9yOiBib29sZWFuLCBpbnB1dERpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBvdXRwdXREaW1zOiBudW1iZXJbXSwgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgICBkaWxhdGlvbnM6IHJlYWRvbmx5IG51bWJlcltdLCBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHBhZHM6IG51bWJlcltdLCBhdXRvUGFkPzogc3RyaW5nKSB7XG4gICAgaWYgKGlzR2xvYmFsT3BlcmF0b3IpIHtcbiAgICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGlucHV0RGltcy5sZW5ndGggLSAyOyBkaW0rKykge1xuICAgICAgICBvdXRwdXREaW1zLnB1c2goMSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGlucHV0RGltcy5sZW5ndGggLSAyOyBkaW0rKykge1xuICAgICAgICBvdXRwdXREaW1zLnB1c2goUG9vbENvbnZVdGlsLmFkanVzdFBhZEFuZFJldHVyblNoYXBlKFxuICAgICAgICAgICAgaW5wdXREaW1zW2RpbSArIDJdLCBzdHJpZGVzW2RpbV0sIGRpbGF0aW9uc1tkaW1dLCBrZXJuZWxTaGFwZVtkaW1dLCBwYWRzLCBkaW0sIGRpbSArIGlucHV0RGltcy5sZW5ndGggLSAyLFxuICAgICAgICAgICAgYXV0b1BhZCkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIGhlbHBlciBmb3IgY29tcHV0ZVNoYXBlSGVscGVyKCkgYW5kIGFkanVzdFBhZHNCYXNlZE9uQXV0b1BhZCgpXG4gIC8vIGFkanVzdHMgcGFkIHZhbHVlIGZvciBnaXZlbiAnYXV0b1BhZCcgc3RyaW5nIGFuZCBjb21wdXRlcyBvdXRwdXQgc2hhcGUgYWxvbmcgYSBwYXJ0aWN1bGFyIGRpbWVuc2lvblxuICBwcml2YXRlIHN0YXRpYyBhZGp1c3RQYWRBbmRSZXR1cm5TaGFwZShcbiAgICAgIGluU2l6ZTogbnVtYmVyLCBzdHJpZGU6IG51bWJlciwgZGlsYXRpb246IG51bWJlciwga2VybmVsOiBudW1iZXIsIHBhZHM6IG51bWJlcltdLCBwYWRIZWFkSW5kZXg6IG51bWJlcixcbiAgICAgIHBhZFRhaWxJbmRleDogbnVtYmVyLCBhdXRvUGFkPzogc3RyaW5nKTogbnVtYmVyIHtcbiAgICBjb25zdCBka2VybmVsID0gZGlsYXRpb24gKiAoa2VybmVsIC0gMSkgKyAxO1xuICAgIGlmIChhdXRvUGFkICYmIGF1dG9QYWQgIT09ICdOT1RTRVQnKSB7XG4gICAgICBzd2l0Y2ggKGF1dG9QYWQpIHtcbiAgICAgICAgY2FzZSAnVkFMSUQnOlxuICAgICAgICAgIHBhZHNbcGFkSGVhZEluZGV4XSA9IDA7XG4gICAgICAgICAgcGFkc1twYWRUYWlsSW5kZXhdID0gMDtcbiAgICAgICAgICByZXR1cm4gTWF0aC5mbG9vcigoKGluU2l6ZSAtIGRrZXJuZWwpIC8gc3RyaWRlKSArIDEpO1xuICAgICAgICBjYXNlICdTQU1FX0xPV0VSJzpcbiAgICAgICAgY2FzZSAnU0FNRV9VUFBFUic6XG4gICAgICAgICAgaWYgKGRpbGF0aW9uICE9PSAxKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RpbGF0aW9uIG5vdCBzdXBwb3J0ZWQgZm9yIFNBTUVfVVBQRVIgb3IgU0FNRV9MT1dFUicpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBsZWdhY3lUYXJnZXRTaXplID0gKGluU2l6ZSArIHN0cmlkZSAtIDEpIC8gc3RyaWRlO1xuICAgICAgICAgICAgY29uc3QgcGFkTmVlZGVkID0gKGxlZ2FjeVRhcmdldFNpemUgLSAxKSAqIHN0cmlkZSArIGtlcm5lbCAtIGluU2l6ZTtcbiAgICAgICAgICAgIHBhZHNbcGFkSGVhZEluZGV4XSA9XG4gICAgICAgICAgICAgICAgKGF1dG9QYWQgPT09ICdTQU1FX0xPV0VSJykgPyBNYXRoLmZsb29yKChwYWROZWVkZWQgKyAxKSAvIDIpIDogTWF0aC5mbG9vcihwYWROZWVkZWQgLyAyKTtcbiAgICAgICAgICAgIHBhZHNbcGFkVGFpbEluZGV4XSA9IHBhZE5lZWRlZCAtIHBhZHNbcGFkSGVhZEluZGV4XTtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKCgoaW5TaXplICsgcGFkTmVlZGVkIC0ga2VybmVsKSAvIHN0cmlkZSkgKyAxKTtcbiAgICAgICAgICB9XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBBdXRvUGFkIHR5cGUnKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKChpblNpemUgKyBwYWRzW3BhZEhlYWRJbmRleF0gKyBwYWRzW3BhZFRhaWxJbmRleF0gLSBka2VybmVsKSAvIHN0cmlkZSkgKyAxKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IE1JTl9DTElQID0gLTMuNDAyODIzNDY2Mzg1Mjg4NmUrMzg7XG5leHBvcnQgY29uc3QgTUFYX0NMSVAgPSAzLjQwMjgyMzQ2NjM4NTI4ODZlKzM4O1xuXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlVXRmOFN0cmluZyhidWZmZXI6IFVpbnQ4QXJyYXkpOiBzdHJpbmcge1xuICByZXR1cm4gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKGJ1ZmZlcik7XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtlbnZ9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7TE9HX0RFQlVHfSBmcm9tICcuL2xvZyc7XG5pbXBvcnQge1RlbnNvclZpZXd9IGZyb20gJy4vdGVuc29yJztcbmltcG9ydCB7Y3JlYXRlR3B1RGF0YU1hbmFnZXIsIEdwdURhdGFNYW5hZ2VyfSBmcm9tICcuL3dlYmdwdS9ncHUtZGF0YS1tYW5hZ2VyJztcbmltcG9ydCB7UnVuRnVuY3Rpb24sIFdFQkdQVV9PUF9SRVNPTFZFX1JVTEVTfSBmcm9tICcuL3dlYmdwdS9vcC1yZXNvbHZlLXJ1bGVzJztcbmltcG9ydCB7UHJvZ3JhbU1hbmFnZXJ9IGZyb20gJy4vd2ViZ3B1L3Byb2dyYW0tbWFuYWdlcic7XG5pbXBvcnQge0NvbXB1dGVDb250ZXh0LCBHcHVEYXRhLCBHcHVEYXRhVHlwZSwgUHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyfSBmcm9tICcuL3dlYmdwdS90eXBlcyc7XG5cbi8qKlxuICogZ2V0IGEgdW5pcXVlIGtleSByZXByZXNlbnRpbmcgdGhlIHByb2dyYW0gZnJvbSB0aGUgcHJvZ3JhbSBpbmZvLGlucHV0IHNoYXBlcyBhbmQgdHlwZXMuXG4gKlxuICogQHJldHVybnMgYSB1bmlxdWUga2V5IGlzIGEgc2hvcnRlciBzdHJpbmcgdGhhbiB0aGUgc2hhZGVyIHNvdXJjZSwgd2hpY2ggY29udGFpbnMgYWxsIHRoZSBpbmZvcm1hdGlvbiB0byBpZGVudGlmeSBhXG4gKiBwcm9ncmFtLiBpZiB0aGUga2V5IGlzIHRoZSBzYW1lLCB0aGUgcHJvZ3JhbSBzaGFkZXIgc291cmNlIHNob3VsZCBiZSB0aGUgc2FtZSwgc28gd2UgY2FuIHJldXNlIHRoZSBwcm9ncmFtLlxuICpcbiAqL1xuY29uc3QgZ2V0UHJvZ3JhbUluZm9VbmlxdWVLZXkgPVxuICAgIChwcm9ncmFtSW5mbzogUHJvZ3JhbUluZm98UHJvZ3JhbUluZm9Mb2FkZXIsIGlucHV0VGVuc29yU2hhcGVzOiBSZWFkb25seUFycmF5PFRlbnNvclZpZXdbJ2RpbXMnXT4sXG4gICAgIGlucHV0R3B1RGF0YVR5cGVzOiByZWFkb25seSBHcHVEYXRhVHlwZVtdKTogc3RyaW5nID0+IHtcbiAgICAgIGNvbnN0IGlucHV0VGVuc29yU2hhcGVzVG9TdHJpbmcgPSBpbnB1dFRlbnNvclNoYXBlcy5tYXAoZCA9PiBgJHtkLmpvaW4oJywnKX1gKS5qb2luKCdfJyk7XG4gICAgICBjb25zdCBpbnB1dEdwdURhdGFUeXBlc1RvU3RyaW5nID0gaW5wdXRHcHVEYXRhVHlwZXMuam9pbignXycpO1xuICAgICAgbGV0IGtleSA9IHByb2dyYW1JbmZvLm5hbWU7XG4gICAgICBpZiAocHJvZ3JhbUluZm8uY2FjaGVIaW50KSB7XG4gICAgICAgIGtleSArPSAnWycgKyBwcm9ncmFtSW5mby5jYWNoZUhpbnQgKyAnXSc7XG4gICAgICB9XG4gICAgICBrZXkgKz0gJzonICsgaW5wdXRUZW5zb3JTaGFwZXNUb1N0cmluZyArICc7JyArIGlucHV0R3B1RGF0YVR5cGVzVG9TdHJpbmc7XG4gICAgICByZXR1cm4ga2V5O1xuICAgIH07XG5cbi8qKlxuICogdGhpcyBjbGFzcyBpcyBkZXNpZ25lZCB0byBzdG9yZSBzdGF0dXMgYW5kIGJlaW5nIHVzZWQgYXMgYSBzaW5nbGV0b24gZm9yIEpTRVAuIEl0IHdpbGwgYmUgcGFzc2VkIHRvIGpzZXBJbml0KCkgYXNcbiAqIHRoZSBmaXJzdCBwYXJhbWV0ZXIgc28gdGhhdCBpdCBpcyBzdG9yZWQgZm9yIGZ1dHVyZSB1c2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJHcHVCYWNrZW5kIHtcbiAgZGV2aWNlOiBHUFVEZXZpY2U7XG4gIC8qKlxuICAgKiBhbiBpbnN0YW5jZSBvZiBHcHVEYXRhTWFuYWdlciB0byBtYW5hZ2UgYSBHcHVEYXRhSWQgLT4gR3B1QnVmZmVyIG1hcHBpbmdcbiAgICovXG4gIGdwdURhdGFNYW5hZ2VyOiBHcHVEYXRhTWFuYWdlcjtcbiAgLyoqXG4gICAqIGFuIGluc3RhbmNlIG9mIFByb2dyYW1NYW5hZ2VyIHRvIGJ1aWxkIGFuZCBydW4gV2ViR1BVIGNvbXB1dGUgc2hhZGVyIHByb2dyYW0sIGFuZCBtYW5hZ2UgYSBQcm9ncmFtS2V5IC0+IFByb2dyYW1cbiAgICogYXJ0aWZhY3RzIG1hcHBpbmdcbiAgICovXG4gIHByb2dyYW1NYW5hZ2VyOiBQcm9ncmFtTWFuYWdlcjtcblxuICAvKipcbiAgICogcmVwcmVzZW50aW5nIHRoZSBrZXJuZWwgSUQgb2Ygd2hpY2ggaXMgY3VycmVudGx5IGJlaW5nIGNvbXB1dGVkIChDUFUgY29kZSBwZXJzcGVjdGl2ZSkuXG4gICAqIGBudWxsYCBtZWFucyBubyBrZXJuZWwgaXMgYmVpbmcgY29tcHV0ZWQuXG4gICAqIG9ubHkgb25lIGtlcm5lbCBjYW4gYmUgY29tcHV0ZWQgYXQgYSBtb21lbnQuXG4gICAqL1xuICBjdXJyZW50S2VybmVsSWQ6IG51bWJlcnxudWxsID0gbnVsbDtcbiAgLyoqXG4gICAqIGEgbGlzdCBvZiB0ZW1wb3JhcnkgR1BVIGRhdGEgZm9yIHRoZSBjdXJyZW50IGtlcm5lbC4gc2hvdWxkIHJlbGVhc2Ugd2hlbiB0aGUga2VybmVsIGRvbmUgY29tcHV0YXRpb24uXG4gICAqL1xuICBwcml2YXRlIHRlbXBvcmFyeURhdGE6IEdwdURhdGFbXTtcbiAgLyoqXG4gICAqIGEgS2VybmVsSUQgLT4gYSBHUFUgZGF0YSBsaXN0LCB3aGljaCBzdG9yZXMgcGVyc2lzdGVudCBHUFUgZGF0YSBvd25lZCBieSB0aGUgc3BlY2lmaWMga2VybmVsLlxuICAgKi9cbiAgcHJpdmF0ZSBrZXJuZWxQZXJzaXN0ZW50RGF0YTogTWFwPG51bWJlciwgR3B1RGF0YVtdPjtcbiAgLyoqXG4gICAqIGEgS2VybmVsSUQgLT4gYSBjdXN0b20gZGF0YSwgd2hpY2ggc3RvcmVzIGN1c3RvbSBkYXRhIG93bmVkIGJ5IHRoZSBzcGVjaWZpYyBrZXJuZWwuXG4gICAqL1xuICBwcml2YXRlIGtlcm5lbEN1c3RvbURhdGE6IE1hcDxudW1iZXIsIHtba2V5OiBzdHJpbmddOiB1bmtub3dufT47XG4gIC8qKlxuICAgKiBnZXQgdGhlIGN1c3RvbSBkYXRhIG9mIHRoZSBjdXJyZW50IGtlcm5lbFxuICAgKi9cbiAgZ2V0IGN1cnJlbnRLZXJuZWxDdXN0b21EYXRhKCk6IHtba2V5OiBzdHJpbmddOiB1bmtub3dufSB7XG4gICAgaWYgKHRoaXMuY3VycmVudEtlcm5lbElkID09PSBudWxsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2N1cnJlbnRLZXJuZWxDdXN0b21EYXRhKCk6IGN1cnJlbnRLZXJuZWxJZCBpcyBudWxsLiAoc2hvdWxkIG5vdCBoYXBwZW4pJyk7XG4gICAgfVxuXG4gICAgbGV0IGRhdGEgPSB0aGlzLmtlcm5lbEN1c3RvbURhdGEuZ2V0KHRoaXMuY3VycmVudEtlcm5lbElkKTtcbiAgICBpZiAoIWRhdGEpIHtcbiAgICAgIGRhdGEgPSB7fTtcbiAgICAgIHRoaXMua2VybmVsQ3VzdG9tRGF0YS5zZXQodGhpcy5jdXJyZW50S2VybmVsSWQsIGRhdGEpO1xuICAgIH1cblxuICAgIHJldHVybiBkYXRhO1xuICB9XG5cbiAgLyoqXG4gICAqIGEgS2VybmVsSUQgLT4ga2VybmVsIGluZm8gbWFwcGluZy4gdmFsdWUgaXMgWyBuYW1lLCBydW4gZnVuY3Rpb24sIFtvcHRpb25hbF0gcHJlcHJvY2Vzc19hdHRyaWJ1dGVfb25jZSBmdW5jdGlvbiBdXG4gICAqL1xuICBrZXJuZWxzOiBNYXA8bnVtYmVyLCBbc3RyaW5nLCBSdW5GdW5jdGlvbiwgWygoYXR0cmlidXRlOiB1bmtub3duKSA9PiB1bmtub3duKSB8IHVuZGVmaW5lZCwgdW5rbm93bl1dPjtcblxuICBjb21tYW5kRW5jb2RlcjogR1BVQ29tbWFuZEVuY29kZXJ8bnVsbCA9IG51bGw7XG4gIGNvbXB1dGVQYXNzRW5jb2RlcjogR1BVQ29tcHV0ZVBhc3NFbmNvZGVyfG51bGwgPSBudWxsO1xuICBwZW5kaW5nRGlzcGF0Y2hOdW1iZXIgPSAwO1xuXG4gIHByb2ZpbGluZ0VuYWJsZWQgPSBmYWxzZTtcbiAgcHJvZmlsaW5nUXVlcnlTZXQ6IEdQVVF1ZXJ5U2V0O1xuICBwcm9maWxpbmdUaW1lQmFzZT86IGJpZ2ludDtcblxuICBhc3luYyBpbml0aWFsaXplKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghbmF2aWdhdG9yLmdwdSkge1xuICAgICAgLy8gV2ViR1BVIGlzIG5vdCBhdmFpbGFibGUuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dlYkdwdUJhY2tlbmQ6IFdlYkdQVSBpcyBub3QgYXZhaWxhYmxlLicpO1xuICAgIH1cblxuICAgIGNvbnN0IGFkYXB0ZXIgPSBhd2FpdCBuYXZpZ2F0b3IuZ3B1LnJlcXVlc3RBZGFwdGVyKCk7XG4gICAgaWYgKCFhZGFwdGVyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dlYkdwdUJhY2tlbmQ6IEZhaWxlZCB0byBnZXQgR1BVIGFkYXB0ZXIuJyk7XG4gICAgfVxuXG4gICAgY29uc3QgZGV2aWNlRGVzY3JpcHRvcjogR1BVRGV2aWNlRGVzY3JpcHRvciA9IHtcbiAgICAgIHJlcXVpcmVkTGltaXRzOiB7XG4gICAgICAgIG1heENvbXB1dGVXb3JrZ3JvdXBTdG9yYWdlU2l6ZTogYWRhcHRlci5saW1pdHMubWF4Q29tcHV0ZVdvcmtncm91cFN0b3JhZ2VTaXplLFxuICAgICAgICBtYXhDb21wdXRlV29ya2dyb3Vwc1BlckRpbWVuc2lvbjogYWRhcHRlci5saW1pdHMubWF4Q29tcHV0ZVdvcmtncm91cHNQZXJEaW1lbnNpb24sXG4gICAgICAgIG1heFN0b3JhZ2VCdWZmZXJCaW5kaW5nU2l6ZTogYWRhcHRlci5saW1pdHMubWF4U3RvcmFnZUJ1ZmZlckJpbmRpbmdTaXplLFxuICAgICAgfVxuICAgIH07XG4gICAgLy8gV2ViR1BVIFNwZWM6IFRpbWVzdGFtcCBRdWVyaWVzIEluc2lkZSBQYXNzZXNcbiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vZ3B1d2ViL2dwdXdlYi9ibG9iL21haW4vcHJvcG9zYWxzL3RpbWVzdGFtcC1xdWVyeS1pbnNpZGUtcGFzc2VzLm1kXG4gICAgaWYgKGFkYXB0ZXIuZmVhdHVyZXMuaGFzKCd0aW1lc3RhbXAtcXVlcnktaW5zaWRlLXBhc3NlcycpICYmIGVudi53ZWJncHUucHJvZmlsaW5nTW9kZSA9PT0gJ2RlZmF1bHQnKSB7XG4gICAgICB0aGlzLnByb2ZpbGluZ0VuYWJsZWQgPSB0cnVlO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgIGRldmljZURlc2NyaXB0b3IucmVxdWlyZWRGZWF0dXJlcyA9IFsndGltZXN0YW1wLXF1ZXJ5LWluc2lkZS1wYXNzZXMnIGFzIGFueV07XG4gICAgfVxuXG4gICAgdGhpcy5kZXZpY2UgPSBhd2FpdCBhZGFwdGVyLnJlcXVlc3REZXZpY2UoZGV2aWNlRGVzY3JpcHRvcik7XG4gICAgdGhpcy5ncHVEYXRhTWFuYWdlciA9IGNyZWF0ZUdwdURhdGFNYW5hZ2VyKHRoaXMpO1xuICAgIHRoaXMucHJvZ3JhbU1hbmFnZXIgPSBuZXcgUHJvZ3JhbU1hbmFnZXIodGhpcyk7XG4gICAgdGhpcy5rZXJuZWxzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMua2VybmVsUGVyc2lzdGVudERhdGEgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5rZXJuZWxDdXN0b21EYXRhID0gbmV3IE1hcCgpO1xuICAgIC8vIFRPRE86IHNldCB1cCBmbGFnc1xuXG4gICAgdGhpcy5kZXZpY2Uub251bmNhcHR1cmVkZXJyb3IgPSBldiA9PiB7XG4gICAgICBpZiAoZXYuZXJyb3IgaW5zdGFuY2VvZiBHUFVWYWxpZGF0aW9uRXJyb3IpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgY29uc29sZS5lcnJvcihgQW4gdW5jYXVnaHQgV2ViR1BVIHZhbGlkYXRpb24gZXJyb3Igd2FzIHJhaXNlZDogJHtldi5lcnJvci5tZXNzYWdlfWApO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAodGhpcy5wcm9maWxpbmdFbmFibGVkKSB7XG4gICAgICB0aGlzLnByb2ZpbGluZ1F1ZXJ5U2V0ID0gdGhpcy5kZXZpY2UuY3JlYXRlUXVlcnlTZXQoe1xuICAgICAgICB0eXBlOiAndGltZXN0YW1wJyxcbiAgICAgICAgY291bnQ6IDIsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBkaXNwb3NlKCk6IHZvaWQge1xuICAgIC8vIGN1cnJlbnRseSwgd2UgZG8gbm90IGRvIGFueXRoaW5nIGluIHRoaXMgZnVuY3Rpb24uIEluIGFsbCBrbm93biB1c2UgY2FzZXMsIHdlIGRvbid0IGhhdmUgdGhlIHJlcXVpcmVtZW50IHRvXG4gICAgLy8gYWN0dWFsbHkgZGlzcG9zZSB0aGUgV2ViR3B1QmFja2VuZCBpbnN0YW5jZSwgYmVjYXVzZSBpdCdzIGFsd2F5cyB1c2VkIGFzIGEgc2luZ2xldG9uLlxuICAgIC8vXG4gICAgLy8gcmV2aXNpdCB0aGlzIHBsYWNlIGlmIHdlIGdldCByZWFsIHJlcXVpcmVtZW50IHRvIGRpc3Bvc2UgdGhlIGluc3RhbmNlLlxuICB9XG5cbiAgZ2V0Q29tbWFuZEVuY29kZXIoKTogR1BVQ29tbWFuZEVuY29kZXIge1xuICAgIGlmICghdGhpcy5jb21tYW5kRW5jb2Rlcikge1xuICAgICAgdGhpcy5jb21tYW5kRW5jb2RlciA9IHRoaXMuZGV2aWNlLmNyZWF0ZUNvbW1hbmRFbmNvZGVyKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLmNvbW1hbmRFbmNvZGVyO1xuICB9XG5cbiAgZ2V0Q29tcHV0ZVBhc3NFbmNvZGVyKCk6IEdQVUNvbXB1dGVQYXNzRW5jb2RlciB7XG4gICAgaWYgKCF0aGlzLmNvbXB1dGVQYXNzRW5jb2Rlcikge1xuICAgICAgdGhpcy5jb21wdXRlUGFzc0VuY29kZXIgPSB0aGlzLmdldENvbW1hbmRFbmNvZGVyKCkuYmVnaW5Db21wdXRlUGFzcygpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5jb21wdXRlUGFzc0VuY29kZXI7XG4gIH1cblxuICBlbmRDb21wdXRlUGFzcygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jb21wdXRlUGFzc0VuY29kZXIpIHtcbiAgICAgIHRoaXMuY29tcHV0ZVBhc3NFbmNvZGVyLmVuZCgpO1xuICAgICAgdGhpcy5jb21wdXRlUGFzc0VuY29kZXIgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIGZsdXNoKCk6IHZvaWQge1xuICAgIHRoaXMuZW5kQ29tcHV0ZVBhc3MoKTtcbiAgICB0aGlzLmRldmljZS5xdWV1ZS5zdWJtaXQoW3RoaXMuZ2V0Q29tbWFuZEVuY29kZXIoKS5maW5pc2goKV0pO1xuICAgIHRoaXMuZ3B1RGF0YU1hbmFnZXIucmVmcmVzaFBlbmRpbmdCdWZmZXJzKCk7XG4gICAgdGhpcy5jb21tYW5kRW5jb2RlciA9IG51bGw7XG4gICAgdGhpcy5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIgPSAwO1xuICB9XG5cbiAgLyoqXG4gICAqIHJ1biBhIFdlYkdQVSBwcm9ncmFtLlxuICAgKiBAcGFyYW0gcHJvZ3JhbSBlaXRoZXIgYSBQcm9ncmFtSW5mbyBpbnN0YW5jZSBjb250YWluaW5nIG1ldGFkYXRhIGluY2x1ZGluZyB0aGUgc2hhZGVyIGNvZGUsIG9yIGEgZnVuY3Rpb24gdGhhdFxuICAgKiBjYW4gYmUgY2FsbGVkIGFuZCByZXR1cm4gYSBQcm9ncmFtSW5mbyBpbnN0YW5jZVxuICAgKiBAcGFyYW0gaW5wdXRzIGEgVGVuc29yVmlldyBhcnJheS4gZWFjaCBlbGVtZW50IHJlcHJlc2VudHMgYSB2YWx1ZSBhbHJlYWR5IGV4aXN0cyBpbiBHUFUuXG4gICAqIEBwYXJhbSBvdXRwdXRJbmRpY2VzIGFuIGluZGljZXMgYXJyYXkuIGVhY2ggZWxlbWVudCBjYW4gYmUgZWl0aGVyIC0xICh0ZW1wb3JhcnkgZGF0YSksIC0yIChwZXJzaXN0ZW50IGRhdGEpIG9yIGFuXG4gICAqIGluZGV4IHRvIHRoZSBrZXJuZWwncyBvdXRwdXQuXG4gICAqIEBwYXJhbSBjcmVhdGVLZXJuZWxPdXRwdXQgYSBjYWxsYmFjayBmdW5jdGlvbiB0aGF0IGNyZWF0ZSBhIHZhbHVlIHRvIGtlcm5lbCdzIG91dHB1dCB3aXRoIHRoZSBnaXZlbiBpbmRleFxuICAgKiBAcGFyYW0gY3JlYXRlSW50ZXJtZWRpYXRlT3V0cHV0IGEgY2FsbGJhY2sgZnVuY3Rpb24gdGhhdCBjcmVhdGUgYSB2YWx1ZSBhcyBhIGludGVybWVkaWF0ZSB2YWx1ZSwgZWl0aGVyIHRlbXBvcmFyeVxuICAgKiBvciBwZXJzaXN0ZW50IChvd25lZCBieSB0aGUgY3VycmVudCBrZXJuZWwpXG4gICAqIEByZXR1cm5zIGEgVGVuc29yVmlldyBhcnJheSByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC5cbiAgICovXG4gIHJ1bihwcm9ncmFtOiBQcm9ncmFtSW5mb0xvYWRlcnxQcm9ncmFtSW5mbywgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIG91dHB1dEluZGljZXM6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgICAgY3JlYXRlS2VybmVsT3V0cHV0OiAoaW5kZXg6IG51bWJlciwgZGF0YVR5cGU6IG51bWJlciwgZGltczogcmVhZG9ubHkgbnVtYmVyW10pID0+IFRlbnNvclZpZXcsXG4gICAgICBjcmVhdGVJbnRlcm1lZGlhdGVPdXRwdXQ6IChkYXRhVHlwZTogbnVtYmVyLCBkaW1zOiByZWFkb25seSBudW1iZXJbXSkgPT4gVGVuc29yVmlldyk6IFRlbnNvclZpZXdbXSB7XG4gICAgaWYgKGlucHV0cy5sZW5ndGggIT09IHByb2dyYW0uaW5wdXRUeXBlcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgSW5wdXQgc2l6ZSBtdXN0IGJlIGVxdWFsIHRvICR7cHJvZ3JhbS5pbnB1dFR5cGVzLmxlbmd0aH0uYCk7XG4gICAgfVxuXG4gICAgLy8gY3JlYXRlIGluZm8gZm9yIGlucHV0c1xuICAgIGNvbnN0IGlucHV0RGF0YXM6IEdwdURhdGFbXSA9IFtdO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRzLmxlbmd0aDsgKytpKSB7XG4gICAgICBjb25zdCBncHVEYXRhID0gdGhpcy5ncHVEYXRhTWFuYWdlci5nZXQoaW5wdXRzW2ldLmRhdGEpO1xuICAgICAgaWYgKCFncHVEYXRhKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgbm8gR1BVIGRhdGEgZm9yIGlucHV0OiAke2lucHV0c1tpXS5kYXRhfWApO1xuICAgICAgfVxuICAgICAgaW5wdXREYXRhc1tpXSA9IGdwdURhdGE7XG4gICAgfVxuXG4gICAgY29uc3Qga2V5ID0gZ2V0UHJvZ3JhbUluZm9VbmlxdWVLZXkocHJvZ3JhbSwgaW5wdXRzLm1hcChpID0+IGkuZGltcyksIGlucHV0RGF0YXMubWFwKGkgPT4gaS50eXBlKSk7XG4gICAgbGV0IGFydGlmYWN0ID0gdGhpcy5wcm9ncmFtTWFuYWdlci5nZXRBcnRpZmFjdChrZXkpO1xuICAgIGNvbnN0IHByb2dyYW1JbmZvID0gYXJ0aWZhY3QgP1xuICAgICAgICBhcnRpZmFjdC5wcm9ncmFtSW5mbyA6XG4gICAgICAgICh0eXBlb2YgKHByb2dyYW0gYXMgUHJvZ3JhbUluZm9Mb2FkZXIpLmdldCA9PT0gJ2Z1bmN0aW9uJyA/IChwcm9ncmFtIGFzIFByb2dyYW1JbmZvTG9hZGVyKS5nZXQoKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChwcm9ncmFtIGFzIFByb2dyYW1JbmZvKSk7XG5cbiAgICAvLyBjaGVjayBvdXRwdXQgaW5kaWNlc1xuICAgIGNvbnN0IHZhbGlkYXRlZE91dHB1dEluZGljZXMgPSBvdXRwdXRJbmRpY2VzLmxlbmd0aCA9PT0gMCA/IHByb2dyYW1JbmZvLm91dHB1dHMubWFwKChfLCBpKSA9PiBpKSA6IG91dHB1dEluZGljZXM7XG4gICAgaWYgKHZhbGlkYXRlZE91dHB1dEluZGljZXMubGVuZ3RoICE9PSBwcm9ncmFtSW5mby5vdXRwdXRzLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBPdXRwdXQgc2l6ZSAke3ZhbGlkYXRlZE91dHB1dEluZGljZXMubGVuZ3RofSBtdXN0IGJlIGVxdWFsIHRvICR7cHJvZ3JhbUluZm8ub3V0cHV0cy5sZW5ndGh9LmApO1xuICAgIH1cblxuICAgIC8vIGNyZWF0ZSBpbmZvIGZvciBvdXRwdXRzXG4gICAgY29uc3Qgb3V0cHV0VGVuc29yVmlld3M6IFRlbnNvclZpZXdbXSA9IFtdO1xuICAgIGNvbnN0IG91dHB1dERhdGFzOiBHcHVEYXRhW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHByb2dyYW1JbmZvLm91dHB1dHMubGVuZ3RoOyArK2kpIHtcbiAgICAgIC8vIHZhbHVlIC0xIGFuZCAtMiBhcmUgdXNlZCBmb3IgY3JlYXRpbmcgdGVtcG9yYXJ5IGFuZCBwZXJzaXN0ZW50IG91dHB1dHMuIHNvIC0yLCAtMSBhbmQgMCwgMSwgMiwgLi4uIGFyZSB2YWxpZFxuICAgICAgLy8gb3V0cHV0IGluZGljZXMuIHNlZSB0eXBlIGRlZmluaXRpb24gb2YgQ29tcHV0ZUNvbnRleHRJbnB1dHNPdXRwdXRzTWFwcGluZyBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKHZhbGlkYXRlZE91dHB1dEluZGljZXNbaV0pIHx8IHZhbGlkYXRlZE91dHB1dEluZGljZXNbaV0gPCAtMiB8fFxuICAgICAgICAgIHZhbGlkYXRlZE91dHB1dEluZGljZXNbaV0gPj0gcHJvZ3JhbUluZm8ub3V0cHV0cy5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIG91dHB1dCBpbmRleDogJHt2YWxpZGF0ZWRPdXRwdXRJbmRpY2VzW2ldfWApO1xuICAgICAgfVxuICAgICAgY29uc3QgaXNUZW1wb3JhcnkgPSB2YWxpZGF0ZWRPdXRwdXRJbmRpY2VzW2ldID09PSAtMTtcbiAgICAgIGNvbnN0IGlzUGVyc2lzdGVudCA9IHZhbGlkYXRlZE91dHB1dEluZGljZXNbaV0gPT09IC0yO1xuICAgICAgY29uc3QgdGVuc29yVmlldyA9IChpc1RlbXBvcmFyeSB8fCBpc1BlcnNpc3RlbnQpID9cbiAgICAgICAgICBjcmVhdGVJbnRlcm1lZGlhdGVPdXRwdXQocHJvZ3JhbUluZm8ub3V0cHV0c1tpXS5kYXRhVHlwZSwgcHJvZ3JhbUluZm8ub3V0cHV0c1tpXS5kaW1zKSA6XG4gICAgICAgICAgY3JlYXRlS2VybmVsT3V0cHV0KHZhbGlkYXRlZE91dHB1dEluZGljZXNbaV0sIHByb2dyYW1JbmZvLm91dHB1dHNbaV0uZGF0YVR5cGUsIHByb2dyYW1JbmZvLm91dHB1dHNbaV0uZGltcyk7XG4gICAgICBjb25zdCBncHVEYXRhID0gdGhpcy5ncHVEYXRhTWFuYWdlci5nZXQodGVuc29yVmlldy5kYXRhKTtcbiAgICAgIGlmICghZ3B1RGF0YSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYG5vIEdQVSBkYXRhIGZvciBvdXRwdXQ6ICR7dGVuc29yVmlldy5kYXRhfWApO1xuICAgICAgfVxuICAgICAgaWYgKGlzVGVtcG9yYXJ5KSB7XG4gICAgICAgIHRoaXMudGVtcG9yYXJ5RGF0YS5wdXNoKGdwdURhdGEpO1xuICAgICAgfVxuICAgICAgaWYgKGlzUGVyc2lzdGVudCkge1xuICAgICAgICBsZXQgcGVyc2lzdGVudERhdGEgPSB0aGlzLmtlcm5lbFBlcnNpc3RlbnREYXRhLmdldCh0aGlzLmN1cnJlbnRLZXJuZWxJZCEpO1xuICAgICAgICBpZiAoIXBlcnNpc3RlbnREYXRhKSB7XG4gICAgICAgICAgcGVyc2lzdGVudERhdGEgPSBbXTtcbiAgICAgICAgICB0aGlzLmtlcm5lbFBlcnNpc3RlbnREYXRhLnNldCh0aGlzLmN1cnJlbnRLZXJuZWxJZCEsIHBlcnNpc3RlbnREYXRhKTtcbiAgICAgICAgfVxuICAgICAgICBwZXJzaXN0ZW50RGF0YS5wdXNoKGdwdURhdGEpO1xuICAgICAgfVxuICAgICAgb3V0cHV0VGVuc29yVmlld3MucHVzaCh0ZW5zb3JWaWV3KTtcbiAgICAgIG91dHB1dERhdGFzLnB1c2goZ3B1RGF0YSk7XG4gICAgfVxuXG4gICAgY29uc3Qgbm9ybWFsaXplZERpc3BhdGNoR3JvdXAgPSB0aGlzLnByb2dyYW1NYW5hZ2VyLm5vcm1hbGl6ZURpc3BhdGNoR3JvdXBTaXplKHByb2dyYW1JbmZvLmRpc3BhdGNoR3JvdXAoaW5wdXRzKSk7XG5cbiAgICBpZiAoIWFydGlmYWN0KSB7XG4gICAgICBhcnRpZmFjdCA9IHRoaXMucHJvZ3JhbU1hbmFnZXIuYnVpbGQocHJvZ3JhbUluZm8sIG5vcm1hbGl6ZWREaXNwYXRjaEdyb3VwKTtcbiAgICAgIHRoaXMucHJvZ3JhbU1hbmFnZXIuc2V0QXJ0aWZhY3Qoa2V5LCBhcnRpZmFjdCk7XG4gICAgfVxuXG4gICAgTE9HX0RFQlVHKFxuICAgICAgICAnaW5mbycsXG4gICAgICAgICgpID0+IGBbUHJvZ3JhbU1hbmFnZXJdIHJ1biBcIiR7cHJvZ3JhbUluZm8ubmFtZX1cIiAoa2V5PSR7a2V5fSkgd2l0aCAke25vcm1hbGl6ZWREaXNwYXRjaEdyb3VwWzBdfXgke1xuICAgICAgICAgICAgbm9ybWFsaXplZERpc3BhdGNoR3JvdXBbMV19eCR7bm9ybWFsaXplZERpc3BhdGNoR3JvdXBbMl19YCk7XG4gICAgdGhpcy5wcm9ncmFtTWFuYWdlci5ydW4oYXJ0aWZhY3QsIGlucHV0RGF0YXMsIG91dHB1dERhdGFzLCBub3JtYWxpemVkRGlzcGF0Y2hHcm91cCk7XG5cbiAgICByZXR1cm4gb3V0cHV0VGVuc29yVmlld3M7XG4gIH1cblxuICB1cGxvYWQoZ3B1RGF0YUlkOiBudW1iZXIsIGRhdGE6IFVpbnQ4QXJyYXkpOiB2b2lkIHtcbiAgICB0aGlzLmdwdURhdGFNYW5hZ2VyLnVwbG9hZChncHVEYXRhSWQsIGRhdGEpO1xuICB9XG5cbiAgbWVtY3B5KHNyYzogbnVtYmVyLCBkc3Q6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuZ3B1RGF0YU1hbmFnZXIubWVtY3B5KHNyYywgZHN0KTtcbiAgfVxuXG4gIGFzeW5jIGRvd25sb2FkKGdwdURhdGFJZDogbnVtYmVyLCBnZXRUYXJnZXRCdWZmZXI6ICgpID0+IFVpbnQ4QXJyYXkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBhcnJheUJ1ZmZlciA9IGF3YWl0IHRoaXMuZ3B1RGF0YU1hbmFnZXIuZG93bmxvYWQoZ3B1RGF0YUlkKTtcblxuICAgIC8vIHRoZSB1bmRlcmx5aW5nIGJ1ZmZlciBtYXkgYmUgY2hhbmdlZCBhZnRlciB0aGUgYXN5bmMgZnVuY3Rpb24gaXMgY2FsbGVkLiBzbyB3ZSB1c2UgYSBnZXR0ZXIgZnVuY3Rpb24gdG8gbWFrZSBzdXJlXG4gICAgLy8gdGhlIGJ1ZmZlciBpcyB1cC10by1kYXRlLlxuICAgIGNvbnN0IGRhdGEgPSBnZXRUYXJnZXRCdWZmZXIoKTtcbiAgICBkYXRhLnNldChuZXcgVWludDhBcnJheShhcnJheUJ1ZmZlcikpO1xuICB9XG5cbiAgYWxsb2Moc2l6ZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5ncHVEYXRhTWFuYWdlci5jcmVhdGUoc2l6ZSkuaWQ7XG4gIH1cblxuICBmcmVlKHB0cjogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5ncHVEYXRhTWFuYWdlci5yZWxlYXNlKHB0cik7XG4gIH1cblxuICBjcmVhdGVLZXJuZWwobmFtZTogc3RyaW5nLCBrZXJuZWxJZDogbnVtYmVyLCBhdHRyaWJ1dGU6IHVua25vd24pOiB2b2lkIHtcbiAgICBjb25zdCBvcCA9IFdFQkdQVV9PUF9SRVNPTFZFX1JVTEVTLmdldChuYW1lKTtcbiAgICBpZiAoIW9wKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGtlcm5lbCBub3QgaW1wbGVtZW50ZWQ6ICR7bmFtZX1gKTtcbiAgICB9XG5cbiAgICB0aGlzLmtlcm5lbHMuc2V0KGtlcm5lbElkLCBbbmFtZSwgb3BbMF0sIFtvcFsxXSwgYXR0cmlidXRlXV0pO1xuICB9XG5cbiAgcmVsZWFzZUtlcm5lbChrZXJuZWxJZDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgcGVyc2lzdGVudERhdGEgPSB0aGlzLmtlcm5lbFBlcnNpc3RlbnREYXRhLmdldChrZXJuZWxJZCk7XG4gICAgaWYgKHBlcnNpc3RlbnREYXRhKSB7XG4gICAgICBmb3IgKGNvbnN0IGRhdGEgb2YgcGVyc2lzdGVudERhdGEpIHtcbiAgICAgICAgdGhpcy5ncHVEYXRhTWFuYWdlci5yZWxlYXNlKGRhdGEuaWQpO1xuICAgICAgfVxuICAgICAgdGhpcy5rZXJuZWxQZXJzaXN0ZW50RGF0YS5kZWxldGUoa2VybmVsSWQpO1xuICAgIH1cblxuICAgIHRoaXMua2VybmVsQ3VzdG9tRGF0YS5kZWxldGUoa2VybmVsSWQpO1xuICAgIHRoaXMua2VybmVscy5kZWxldGUoa2VybmVsSWQpO1xuICB9XG5cbiAgY29tcHV0ZUtlcm5lbChrZXJuZWxJZDogbnVtYmVyLCBjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IG51bWJlciB7XG4gICAgY29uc3Qga2VybmVsID0gdGhpcy5rZXJuZWxzLmdldChrZXJuZWxJZCk7XG4gICAgaWYgKCFrZXJuZWwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihga2VybmVsIG5vdCBjcmVhdGVkOiAke2tlcm5lbElkfWApO1xuICAgIH1cbiAgICBjb25zdCBbbmFtZSwga2VybmVsRW50cnksIGF0dHJpYnV0ZXNdID0ga2VybmVsO1xuICAgIGlmICh0aGlzLmN1cnJlbnRLZXJuZWxJZCAhPT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBrZXJuZWwgXCIke25hbWV9XCIgaXMgbm90IGFsbG93ZWQgdG8gYmUgY2FsbGVkIHJlY3Vyc2l2ZWx5YCk7XG4gICAgfVxuICAgIHRoaXMuY3VycmVudEtlcm5lbElkID0ga2VybmVsSWQ7XG5cbiAgICAvLyBwYXJzZSBhdHRyaWJ1dGVzIGlmIG5lY2Vzc2FyeVxuICAgIGlmIChhdHRyaWJ1dGVzWzBdKSB7XG4gICAgICBhdHRyaWJ1dGVzWzFdID0gYXR0cmlidXRlc1swXShhdHRyaWJ1dGVzWzFdKTtcbiAgICAgIGF0dHJpYnV0ZXNbMF0gPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgTE9HX0RFQlVHKCdpbmZvJywgKCkgPT4gYFtXZWJHUFVdIFN0YXJ0IHRvIHJ1biBrZXJuZWwgXCIke25hbWV9XCIuLi5gKTtcblxuICAgIHRoaXMudGVtcG9yYXJ5RGF0YSA9IFtdO1xuICAgIHRyeSB7XG4gICAgICBrZXJuZWxFbnRyeShjb250ZXh0LCBhdHRyaWJ1dGVzWzFdKTtcbiAgICAgIHJldHVybiAwOyAgLy8gT1JUX09LXG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgTE9HX0RFQlVHKCd3YXJuaW5nJywgYFtXZWJHUFVdIEtlcm5lbCBcIiR7bmFtZX1cIiBmYWlsZWQuIEVycm9yOiAke2V9YCk7XG4gICAgICByZXR1cm4gMTsgIC8vIE9SVF9GQUlMXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGZvciAoY29uc3QgZGF0YSBvZiB0aGlzLnRlbXBvcmFyeURhdGEpIHtcbiAgICAgICAgdGhpcy5ncHVEYXRhTWFuYWdlci5yZWxlYXNlKGRhdGEuaWQpO1xuICAgICAgfVxuICAgICAgdGhpcy50ZW1wb3JhcnlEYXRhID0gW107XG4gICAgICB0aGlzLmN1cnJlbnRLZXJuZWxJZCA9IG51bGw7XG4gICAgfVxuICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtPcnRXYXNtTW9kdWxlfSBmcm9tICcuLi9iaW5kaW5nL29ydC13YXNtJztcbmltcG9ydCB7Z2V0VGVuc29yRWxlbWVudFNpemV9IGZyb20gJy4uL3dhc20tY29tbW9uJztcblxuaW1wb3J0IHtXZWJHcHVCYWNrZW5kfSBmcm9tICcuL2JhY2tlbmQtd2ViZ3B1JztcbmltcG9ydCB7TE9HX0RFQlVHfSBmcm9tICcuL2xvZyc7XG5pbXBvcnQge1RlbnNvclZpZXd9IGZyb20gJy4vdGVuc29yJztcbmltcG9ydCB7U2hhcGVVdGlsfSBmcm9tICcuL3V0aWwnO1xuaW1wb3J0IHtDb21wdXRlQ29udGV4dCwgQ29tcHV0ZUNvbnRleHRJbnB1dHNPdXRwdXRzTWFwcGluZywgUHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyfSBmcm9tICcuL3dlYmdwdS90eXBlcyc7XG5cbi8qIGVzbGludC1kaXNhYmxlIG5vLWJpdHdpc2UgKi9cblxuY2xhc3MgVGVuc29yVmlld0ltcGwgaW1wbGVtZW50cyBUZW5zb3JWaWV3IHtcbiAgY29uc3RydWN0b3IoXG4gICAgICBwcml2YXRlIG1vZHVsZTogT3J0V2FzbU1vZHVsZSwgcHVibGljIHJlYWRvbmx5IGRhdGFUeXBlOiBudW1iZXIsIHB1YmxpYyByZWFkb25seSBkYXRhOiBudW1iZXIsXG4gICAgICBwdWJsaWMgcmVhZG9ubHkgZGltczogcmVhZG9ubHkgbnVtYmVyW10pIHt9XG5cbiAgZ2V0RmxvYXQzMkFycmF5KCk6IEZsb2F0MzJBcnJheSB7XG4gICAgcmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkodGhpcy5tb2R1bGUuSEVBUDguYnVmZmVyLCB0aGlzLmRhdGEsIFNoYXBlVXRpbC5zaXplKHRoaXMuZGltcykpO1xuICB9XG5cbiAgcmVzaGFwZShuZXdEaW1zOiByZWFkb25seSBudW1iZXJbXSk6IFRlbnNvclZpZXcge1xuICAgIGlmIChTaGFwZVV0aWwuc2l6ZShuZXdEaW1zKSAhPT0gU2hhcGVVdGlsLnNpemUodGhpcy5kaW1zKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG5ldyBzaGFwZScpO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IFRlbnNvclZpZXdJbXBsKHRoaXMubW9kdWxlLCB0aGlzLmRhdGFUeXBlLCB0aGlzLmRhdGEsIG5ld0RpbXMpO1xuICB9XG59XG5cbmNsYXNzIENvbXB1dGVDb250ZXh0SW1wbCBpbXBsZW1lbnRzIENvbXB1dGVDb250ZXh0IHtcbiAgcmVhZG9ubHkgb3BLZXJuZWxDb250ZXh0OiBudW1iZXI7XG4gIHJlYWRvbmx5IGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdO1xuICBnZXQgY3VzdG9tRGF0YSgpOiB7W2tleTogc3RyaW5nXTogdW5rbm93bn0ge1xuICAgIHJldHVybiB0aGlzLmJhY2tlbmQuY3VycmVudEtlcm5lbEN1c3RvbURhdGE7XG4gIH1cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBtb2R1bGU6IE9ydFdhc21Nb2R1bGUsIHByaXZhdGUgYmFja2VuZDogV2ViR3B1QmFja2VuZCwgY29udGV4dERhdGFPZmZzZXQ6IG51bWJlcikge1xuICAgIGNvbnN0IGhlYXBVMzIgPSBtb2R1bGUuSEVBUFUzMjtcblxuICAgIC8vIGV4dHJhY3QgY29udGV4dCBkYXRhXG4gICAgbGV0IGRhdGFJbmRleCA9IChjb250ZXh0RGF0YU9mZnNldCA+PiAyKTtcbiAgICB0aGlzLm9wS2VybmVsQ29udGV4dCA9IGhlYXBVMzJbZGF0YUluZGV4KytdO1xuICAgIGNvbnN0IGlucHV0Q291bnQgPSBoZWFwVTMyW2RhdGFJbmRleCsrXTtcblxuICAgIGNvbnN0IGlucHV0czogVGVuc29yVmlld1tdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dENvdW50OyBpKyspIHtcbiAgICAgIGNvbnN0IGRhdGFUeXBlID0gaGVhcFUzMltkYXRhSW5kZXgrK107XG4gICAgICBjb25zdCBkYXRhID0gaGVhcFUzMltkYXRhSW5kZXgrK107XG4gICAgICBjb25zdCBkaW0gPSBoZWFwVTMyW2RhdGFJbmRleCsrXTtcbiAgICAgIGNvbnN0IGRpbXM6IG51bWJlcltdID0gW107XG4gICAgICBmb3IgKGxldCBkID0gMDsgZCA8IGRpbTsgZCsrKSB7XG4gICAgICAgIGRpbXMucHVzaChoZWFwVTMyW2RhdGFJbmRleCsrXSk7XG4gICAgICB9XG4gICAgICBpbnB1dHMucHVzaChuZXcgVGVuc29yVmlld0ltcGwobW9kdWxlLCBkYXRhVHlwZSwgZGF0YSwgZGltcykpO1xuICAgIH1cbiAgICB0aGlzLmlucHV0cyA9IGlucHV0cztcbiAgfVxuXG4gIGNvbXB1dGUocHJvZ3JhbTogUHJvZ3JhbUluZm9Mb2FkZXJ8UHJvZ3JhbUluZm8sIGlucHV0c091dHB1dHNNYXBwaW5nPzogQ29tcHV0ZUNvbnRleHRJbnB1dHNPdXRwdXRzTWFwcGluZyk6XG4gICAgICBUZW5zb3JWaWV3W10ge1xuICAgIC8vIHByZXBhcmUgaW5wdXRzLiBpbnB1dHMgc2hvdWxkIGFsd2F5cyBiZSB2YWxpZCBkYXRhLlxuICAgIGNvbnN0IG1hcHBlZElucHV0cyA9XG4gICAgICAgIGlucHV0c091dHB1dHNNYXBwaW5nPy5pbnB1dHM/Lm1hcChpID0+IHR5cGVvZiBpID09PSAnbnVtYmVyJyA/IHRoaXMuaW5wdXRzW2ldIDogaSkgPz8gdGhpcy5pbnB1dHM7XG4gICAgLy8gcHJlcGFyZSBvdXRwdXRzLlxuICAgIGNvbnN0IG91dHB1dEluZGljZXMgPSBpbnB1dHNPdXRwdXRzTWFwcGluZz8ub3V0cHV0cyA/PyBbXTtcbiAgICBjb25zdCBjcmVhdGVLZXJuZWxPdXRwdXQgPSAoaW5kZXg6IG51bWJlciwgZGF0YVR5cGU6IG51bWJlciwgZGltczogcmVhZG9ubHkgbnVtYmVyW10pOiBUZW5zb3JWaWV3ID0+XG4gICAgICAgIG5ldyBUZW5zb3JWaWV3SW1wbCh0aGlzLm1vZHVsZSwgZGF0YVR5cGUsIHRoaXMub3V0cHV0KGluZGV4LCBkaW1zKSwgZGltcyk7XG4gICAgY29uc3QgY3JlYXRlVGVtcG9yYXJ5T3V0cHV0ID0gKGRhdGFUeXBlOiBudW1iZXIsIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogVGVuc29yVmlldyA9PiB7XG4gICAgICBjb25zdCBlbGVtZW50U2l6ZSA9IGdldFRlbnNvckVsZW1lbnRTaXplKGRhdGFUeXBlKTtcbiAgICAgIGlmICghZWxlbWVudFNpemUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7ZGF0YVR5cGV9YCk7XG4gICAgICB9XG4gICAgICBjb25zdCBidWZmZXJTaXplID0gZWxlbWVudFNpemUgKiBTaGFwZVV0aWwuc2l6ZShkaW1zKTtcbiAgICAgIHJldHVybiBuZXcgVGVuc29yVmlld0ltcGwodGhpcy5tb2R1bGUsIGRhdGFUeXBlLCB0aGlzLmJhY2tlbmQuZ3B1RGF0YU1hbmFnZXIuY3JlYXRlKGJ1ZmZlclNpemUpLmlkLCBkaW1zKTtcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLmJhY2tlbmQucnVuKHByb2dyYW0sIG1hcHBlZElucHV0cywgb3V0cHV0SW5kaWNlcywgY3JlYXRlS2VybmVsT3V0cHV0LCBjcmVhdGVUZW1wb3JhcnlPdXRwdXQpO1xuICB9XG5cbiAgb3V0cHV0KGluZGV4OiBudW1iZXIsIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogbnVtYmVyIHtcbiAgICBjb25zdCBzdGFjayA9IHRoaXMubW9kdWxlLnN0YWNrU2F2ZSgpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkYXRhID0gdGhpcy5tb2R1bGUuc3RhY2tBbGxvYygoMSArIGRpbXMubGVuZ3RoKSAqIDQgLyogc2l6ZW9mKHNpemVfdCkgKi8pO1xuICAgICAgbGV0IG9mZnNldCA9IGRhdGEgPj4gMjtcbiAgICAgIHRoaXMubW9kdWxlLkhFQVBVMzJbb2Zmc2V0KytdID0gZGltcy5sZW5ndGg7XG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRpbXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdGhpcy5tb2R1bGUuSEVBUFUzMltvZmZzZXQrK10gPSBkaW1zW2ldO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMubW9kdWxlLl9Kc2VwT3V0cHV0KHRoaXMub3BLZXJuZWxDb250ZXh0LCBpbmRleCwgZGF0YSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMubW9kdWxlLnN0YWNrUmVzdG9yZShzdGFjayk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBpbml0ID0gYXN5bmMobW9kdWxlOiBPcnRXYXNtTW9kdWxlKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gIGNvbnN0IGluaXQgPSBtb2R1bGUuanNlcEluaXQ7XG4gIGlmIChpbml0ICYmIG5hdmlnYXRvci5ncHUpIHtcbiAgICBjb25zdCBiYWNrZW5kID0gbmV3IFdlYkdwdUJhY2tlbmQoKTtcbiAgICBhd2FpdCBiYWNrZW5kLmluaXRpYWxpemUoKTtcblxuICAgIGluaXQoXG4gICAgICAgIC8vIGJhY2tlbmRcbiAgICAgICAge2JhY2tlbmR9LFxuXG4gICAgICAgIC8vIGpzZXBBbGxvYygpXG4gICAgICAgIChzaXplOiBudW1iZXIpID0+IGJhY2tlbmQuYWxsb2Moc2l6ZSksXG5cbiAgICAgICAgLy8ganNlcEZyZWUoKVxuICAgICAgICAocHRyOiBudW1iZXIpID0+IGJhY2tlbmQuZnJlZShwdHIpLFxuXG4gICAgICAgIC8vIGpzZXBDb3B5KHNyYywgZHN0LCBzaXplLCBpc1NvdXJjZUdwdSlcbiAgICAgICAgKHNyYzogbnVtYmVyLCBkc3Q6IG51bWJlciwgc2l6ZTogbnVtYmVyLCBpc1NvdXJjZUdwdSA9IGZhbHNlKSA9PiB7XG4gICAgICAgICAgaWYgKGlzU291cmNlR3B1KSB7XG4gICAgICAgICAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW1dlYkdQVV0ganNlcENvcHlHcHVUb0dwdTogc3JjPSR7c3JjfSwgZHN0PSR7ZHN0fSwgc2l6ZT0ke3NpemV9YCk7XG4gICAgICAgICAgICBiYWNrZW5kLm1lbWNweShzcmMsIGRzdCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbV2ViR1BVXSBqc2VwQ29weUNwdVRvR3B1OiBkYXRhT2Zmc2V0PSR7c3JjfSwgZ3B1RGF0YUlkPSR7ZHN0fSwgc2l6ZT0ke3NpemV9YCk7XG4gICAgICAgICAgICBjb25zdCBkYXRhID0gbW9kdWxlLkhFQVBVOC5zdWJhcnJheShzcmMsIHNyYyArIHNpemUpO1xuICAgICAgICAgICAgYmFja2VuZC51cGxvYWQoZHN0LCBkYXRhKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgLy8ganNlcENvcHlBc3luYyhzcmMsIGRzdCwgc2l6ZSlcbiAgICAgICAgYXN5bmMoZ3B1RGF0YUlkOiBudW1iZXIsIGRhdGFPZmZzZXQ6IG51bWJlciwgc2l6ZTogbnVtYmVyKTpcbiAgICAgICAgICAgIFByb21pc2U8dm9pZD4gPT4ge1xuICAgICAgICAgICAgICBMT0dfREVCVUcoXG4gICAgICAgICAgICAgICAgICAndmVyYm9zZScsXG4gICAgICAgICAgICAgICAgICAoKSA9PiBgW1dlYkdQVV0ganNlcENvcHlHcHVUb0NwdTogZ3B1RGF0YUlkPSR7Z3B1RGF0YUlkfSwgZGF0YU9mZnNldD0ke2RhdGFPZmZzZXR9LCBzaXplPSR7c2l6ZX1gKTtcblxuICAgICAgICAgICAgICBhd2FpdCBiYWNrZW5kLmRvd25sb2FkKGdwdURhdGFJZCwgKCkgPT4gbW9kdWxlLkhFQVBVOC5zdWJhcnJheShkYXRhT2Zmc2V0LCBkYXRhT2Zmc2V0ICsgc2l6ZSkpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAvLyBqc2VwQ3JlYXRlS2VybmVsXG4gICAgICAgIChuYW1lOiBzdHJpbmcsIGtlcm5lbDogbnVtYmVyLCBhdHRyaWJ1dGU6IHVua25vd24pID0+IGJhY2tlbmQuY3JlYXRlS2VybmVsKG5hbWUsIGtlcm5lbCwgYXR0cmlidXRlKSxcblxuICAgICAgICAvLyBqc2VwUmVsZWFzZUtlcm5lbFxuICAgICAgICAoa2VybmVsOiBudW1iZXIpID0+IGJhY2tlbmQucmVsZWFzZUtlcm5lbChrZXJuZWwpLFxuXG4gICAgICAgIC8vIGpzZXBSdW5cbiAgICAgICAgKGtlcm5lbDogbnVtYmVyLCBjb250ZXh0RGF0YU9mZnNldDogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgTE9HX0RFQlVHKCd2ZXJib3NlJywgKCkgPT4gYFtXZWJHUFVdIGpzZXBSdW46IGtlcm5lbD0ke2tlcm5lbH0sIGNvbnRleHREYXRhT2Zmc2V0PSR7Y29udGV4dERhdGFPZmZzZXR9YCk7XG4gICAgICAgICAgY29uc3QgY29udGV4dCA9IG5ldyBDb21wdXRlQ29udGV4dEltcGwobW9kdWxlLCBiYWNrZW5kLCBjb250ZXh0RGF0YU9mZnNldCk7XG4gICAgICAgICAgcmV0dXJuIGJhY2tlbmQuY29tcHV0ZUtlcm5lbChrZXJuZWwsIGNvbnRleHQpO1xuICAgICAgICB9KTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge2Vudn0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHtsb2dMZXZlbFN0cmluZ1RvRW51bX0gZnJvbSAnLi4vd2FzbS1jb21tb24nO1xuXG50eXBlIExvZ0xldmVsID0gTm9uTnVsbGFibGU8dHlwZW9mIGVudi5sb2dMZXZlbD47XG50eXBlIE1lc3NhZ2VTdHJpbmcgPSBzdHJpbmc7XG50eXBlIE1lc3NhZ2VGdW5jdGlvbiA9ICgpID0+IHN0cmluZztcbnR5cGUgTWVzc2FnZSA9IE1lc3NhZ2VTdHJpbmd8TWVzc2FnZUZ1bmN0aW9uO1xuXG5jb25zdCBsb2dMZXZlbFByZWZpeCA9IFsnVicsICdJJywgJ1cnLCAnRScsICdGJ107XG5cbmNvbnN0IGRvTG9nID0gKGxldmVsOiBudW1iZXIsIG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQgPT4ge1xuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICBjb25zb2xlLmxvZyhgWyR7bG9nTGV2ZWxQcmVmaXhbbGV2ZWxdfSwke25ldyBEYXRlKCkudG9JU09TdHJpbmcoKX1dJHttZXNzYWdlfWApO1xufTtcblxuLyoqXG4gKiBBIHNpbXBsZSBsb2dnaW5nIHV0aWxpdHkgdG8gbG9nIG1lc3NhZ2VzIHRvIHRoZSBjb25zb2xlLlxuICovXG5leHBvcnQgY29uc3QgTE9HID0gKGxvZ0xldmVsOiBMb2dMZXZlbCwgbXNnOiBNZXNzYWdlKTogdm9pZCA9PiB7XG4gIGNvbnN0IG1lc3NhZ2VMZXZlbCA9IGxvZ0xldmVsU3RyaW5nVG9FbnVtKGxvZ0xldmVsKTtcbiAgY29uc3QgY29uZmlnTGV2ZWwgPSBsb2dMZXZlbFN0cmluZ1RvRW51bShlbnYubG9nTGV2ZWwhKTtcbiAgaWYgKG1lc3NhZ2VMZXZlbCA+PSBjb25maWdMZXZlbCkge1xuICAgIGRvTG9nKG1lc3NhZ2VMZXZlbCwgdHlwZW9mIG1zZyA9PT0gJ2Z1bmN0aW9uJyA/IG1zZygpIDogbXNnKTtcbiAgfVxufTtcblxuLyoqXG4gKiBBIHNpbXBsZSBsb2dnaW5nIHV0aWxpdHkgdG8gbG9nIG1lc3NhZ2VzIHRvIHRoZSBjb25zb2xlLiBPbmx5IGxvZ3Mgd2hlbiBkZWJ1ZyBpcyBlbmFibGVkLlxuICovXG5leHBvcnQgY29uc3QgTE9HX0RFQlVHOiB0eXBlb2YgTE9HID0gKC4uLmFyZ3M6IFBhcmFtZXRlcnM8dHlwZW9mIExPRz4pID0+IHtcbiAgaWYgKGVudi5kZWJ1Zykge1xuICAgIExPRyguLi5hcmdzKTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG4vKiBlc2xpbnQtZGlzYWJsZSBuby1wYXJhbS1yZWFzc2lnbiAqL1xuXG5leHBvcnQgY2xhc3MgTWF0TXVsVXRpbCB7XG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgdGhlIGV4cGVjdGVkIHNoYXBlIHdoZW4gbWF0cml4IG11bHRpcGxpY2F0aW9uXG4gICAqIEBwYXJhbSBhIFRoZSBzaGFwZSBvZiB0ZW5zb3IgQS4gU2hvdWxkIGJlIGEgdHVwbGUgb2YgMiBwb3NpdGl2ZSBpbnRlZ2Vyc1xuICAgKiBAcGFyYW0gYiBUaGUgc2hhcGUgb2YgdGVuc29yIEIuIFNob3VsZCBiZSBhIHR1cGxlIG9mIDIgcG9zaXRpdmUgaW50ZWdlcnNcbiAgICogQHJldHVybnMgVGhlIGV4cGVjdGVkIHNoYXBlIG9mIHRoZSByZXN1bHQsIG9yIHVuZGVmaW5lZCBpZiBOL0FcbiAgICovXG4gIHN0YXRpYyBjYWxjTWF0TXVsU2hhcGUoYTogW251bWJlciwgbnVtYmVyXSwgYjogW251bWJlciwgbnVtYmVyXSk6IFtudW1iZXIsIG51bWJlcl18dW5kZWZpbmVkIHtcbiAgICByZXR1cm4gKGFbMV0gIT09IGJbMF0pID8gdW5kZWZpbmVkIDogW2FbMF0sIGJbMV1dO1xuICB9XG59XG5cblxuZXhwb3J0IGNsYXNzIEJyb2FkY2FzdFV0aWwge1xuICAvKipcbiAgICogQ2FsY3VsYXRlIHRoZSBleHBlY3RlZCBzaGFwZSB3aGVuIGJyb2FkY2FzdGluZyAyIHRlbnNvcnNcbiAgICogQHBhcmFtIGEgVGhlIHNoYXBlIG9mIHRlbnNvciBBLiBTaG91bGQgYmUgYW4gYXJyYXkgb2YgcG9zaXRpdmUgaW50ZWdlcnNcbiAgICogQHBhcmFtIGIgVGhlIHNoYXBlIG9mIHRlbnNvciBCLiBTaG91bGQgYmUgYW4gYXJyYXkgb2YgcG9zaXRpdmUgaW50ZWdlcnNcbiAgICogQHBhcmFtIGlzTWF0TXVsIFdoZXRoZXIgdGhlIG9wZXJhdGlvbiBpcyBNYXRNdWxcbiAgICogQHJldHVybnMgVGhlIGV4cGVjdGVkIHNoYXBlIG9mIHRoZSByZXN1bHQsIG9yIHVuZGVmaW5lZCBpZiBOL0FcbiAgICovXG4gIHN0YXRpYyBjYWxjU2hhcGUoYWRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBiZGltczogcmVhZG9ubHkgbnVtYmVyW10sIGlzTWF0TXVsID0gZmFsc2UpOiByZWFkb25seSBudW1iZXJbXXx1bmRlZmluZWQge1xuICAgIGNvbnN0IGFyYW5rID0gYWRpbXMubGVuZ3RoO1xuICAgIGNvbnN0IGJyYW5rID0gYmRpbXMubGVuZ3RoO1xuICAgIGlmIChhcmFuayA9PT0gMCkge1xuICAgICAgcmV0dXJuIGJkaW1zO1xuICAgIH1cbiAgICBpZiAoYnJhbmsgPT09IDApIHtcbiAgICAgIHJldHVybiBhZGltcztcbiAgICB9XG4gICAgY29uc3QgY3JhbmsgPSBNYXRoLm1heChhZGltcy5sZW5ndGgsIGJkaW1zLmxlbmd0aCk7XG4gICAgY29uc3QgY2RpbXMgPSBuZXcgQXJyYXk8bnVtYmVyPihjcmFuayk7XG5cbiAgICAvLyBjYWxjdWxhdGUgdGhlIGxhc3QgMiBkaW1lbnNpb24gaWYgaXQgaXMgTWF0TXVsXG4gICAgaWYgKGlzTWF0TXVsKSB7XG4gICAgICBpZiAoYXJhbmsgPCAyIHx8IGJyYW5rIDwgMikge1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgICAgY29uc3QgY1NoYXBlTWF0TXVsID1cbiAgICAgICAgICBNYXRNdWxVdGlsLmNhbGNNYXRNdWxTaGFwZShbYWRpbXNbYXJhbmsgLSAyXSwgYWRpbXNbYXJhbmsgLSAxXV0sIFtiZGltc1ticmFuayAtIDJdLCBiZGltc1ticmFuayAtIDFdXSk7XG4gICAgICBpZiAoY1NoYXBlTWF0TXVsID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIFtjZGltc1tjcmFuayAtIDJdLCBjZGltc1tjcmFuayAtIDFdXSA9IGNTaGFwZU1hdE11bDtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gaXNNYXRNdWwgPyAzIDogMTsgaSA8PSBjcmFuazsgaSsrKSB7XG4gICAgICBjb25zdCBhTGVuID0gYXJhbmsgLSBpIDwgMCA/IDEgOiBhZGltc1thcmFuayAtIGldO1xuICAgICAgY29uc3QgYkxlbiA9IGJyYW5rIC0gaSA8IDAgPyAxIDogYmRpbXNbYnJhbmsgLSBpXTtcblxuICAgICAgaWYgKGFMZW4gIT09IGJMZW4gJiYgYUxlbiA+IDEgJiYgYkxlbiA+IDEpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH1cbiAgICAgIGNkaW1zW2NyYW5rIC0gaV0gPSBNYXRoLm1heChhTGVuLCBiTGVuKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2RpbXM7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lIGlmIGEgc2hhcGUgaXMgdW5pZGlyZWN0aW9uYWwgYnJvYWRjYXN0YWJsZSB0byBhbm90aGVyIHNoYXBlXG4gICAqIEBwYXJhbSBzaGFwZSBUaGUgaW5wdXQgc2hhcGVcbiAgICogQHBhcmFtIGZpbmFsU2hhcGUgVGhlIGRlc2lyZWQgc2hhcGUgYWZ0ZXIgYnJvYWRjYXN0aW5nXG4gICAqL1xuICBzdGF0aWMgaXNWYWxpZEJyb2FkY2FzdChzaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIGZpbmFsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKTogYm9vbGVhbiB7XG4gICAgLy8gYWxpZ24gc2hhcGUgdG8gdGhlIHJpZ2h0XG4gICAgY29uc3QgaW5wdXRSYW5rID0gc2hhcGUubGVuZ3RoO1xuICAgIGNvbnN0IGZpbmFsUmFuayA9IGZpbmFsU2hhcGUubGVuZ3RoO1xuICAgIGlmIChpbnB1dFJhbmsgPiBmaW5hbFJhbmspIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPD0gaW5wdXRSYW5rOyBpKyspIHtcbiAgICAgIGlmIChzaGFwZVtpbnB1dFJhbmsgLSBpXSAhPT0gMSAmJiBzaGFwZVtpbnB1dFJhbmsgLSBpXSAhPT0gZmluYWxTaGFwZVtmaW5hbFJhbmsgLSBpXSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG5cblxuZXhwb3J0IGNsYXNzIFNoYXBlVXRpbCB7XG4gIC8qKlxuICAgKiBjYWxjdWxhdGUgdGhlIHNpemUgKG51bWJlciBvZiBlbGVtZW50cylcbiAgICovXG4gIHN0YXRpYyBzaXplKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogbnVtYmVyIHtcbiAgICByZXR1cm4gU2hhcGVVdGlsLmdldFNpemVGcm9tRGltZW5zaW9uUmFuZ2UoZGltcywgMCwgZGltcy5sZW5ndGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIGNhbGN1bGF0ZSB0aGUgc2l6ZSAobnVtYmVyIG9mIGVsZW1lbnRzKSBmcm9tIHRoZSBnaXZlbiBheGlzIChpbmNsdXNpdmUpXG4gICAqL1xuICBzdGF0aWMgc2l6ZUZyb21EaW1lbnNpb24oZGltczogcmVhZG9ubHkgbnVtYmVyW10sIGF4aXM6IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKGF4aXMgPCAwIHx8IGF4aXMgPiBkaW1zLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIGRpbWVuc2lvbiBvZiAke2F4aXN9IGZvciBzaXplRnJvbURpbWVuc2lvbiBhcyBUZW5zb3IgaGFzICR7ZGltcy5sZW5ndGh9IGRpbWVuc2lvbnMuYCk7XG4gICAgfVxuICAgIHJldHVybiBTaGFwZVV0aWwuZ2V0U2l6ZUZyb21EaW1lbnNpb25SYW5nZShkaW1zLCBheGlzLCBkaW1zLmxlbmd0aCk7XG4gIH1cblxuICAvKipcbiAgICogY2FsY3VsYXRlIHRoZSBzaXplIChudW1iZXIgb2YgZWxlbWVudHMpIHRvIHRoZSBnaXZlbiBheGlzIChleGNsdXNpdmUpXG4gICAqL1xuICBzdGF0aWMgc2l6ZVRvRGltZW5zaW9uKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBheGlzOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGlmIChheGlzIDwgMCB8fCBheGlzID4gZGltcy5sZW5ndGgpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgaW52YWxpZCBkaW1lbnNpb24gb2YgJHtheGlzfSBmb3Igc2l6ZVRvRGltZW5zaW9uIGFzIFRlbnNvciBoYXMgJHtkaW1zLmxlbmd0aH0gZGltZW5zaW9ucy5gKTtcbiAgICB9XG4gICAgcmV0dXJuIFNoYXBlVXRpbC5nZXRTaXplRnJvbURpbWVuc2lvblJhbmdlKGRpbXMsIDAsIGF4aXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIGNhbGN1bGF0ZSB0aGUgc2l6ZSAobnVtYmVyIG9mIGVsZW1lbnRzKSBmcm9tIGFuZCB0byB0aGUgZ2l2ZW4gYXhpcyBbc3RhcnQsIGVuZClcbiAgICovXG4gIHN0YXRpYyBnZXRTaXplRnJvbURpbWVuc2lvblJhbmdlKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBzdGFydDogbnVtYmVyLCBlbmQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgbGV0IHNpemUgPSAxO1xuICAgIGZvciAobGV0IGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICAvLyBzYWZldHkgY2hlY2sgYXMgdGhpcyBtZXRob2QgaXMgY2FsbGVkIGJ5IG11bHRpcGxlIG90aGVyIG1ldGhvZHMgcmVxdWlyaW5nIHNpemUuXG4gICAgICAvLyBzaXplIGNhbm5vdCBiZSAwIG9yIG5lZ2F0aXZlLlxuICAgICAgaWYgKGRpbXNbaV0gPD0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxlblxuICAgICAgICAgICAgJ2Nhbm5vdCBnZXQgdmFsaWQgc2l6ZSBmcm9tIHNwZWNpZmllZCBkaW1lbnNpb24gcmFuZ2UuIE1vc3QgbGlrZWx5IHRoZSByYW5nZSBjb250YWlucyAwIG9yIG5lZ2F0aXZlIHZhbHVlcyBpbiB0aGVtLicpO1xuICAgICAgfVxuICAgICAgc2l6ZSAqPSBkaW1zW2ldO1xuICAgIH1cbiAgICByZXR1cm4gc2l6ZTtcbiAgfVxuXG4gIHN0YXRpYyBjb21wdXRlU3RyaWRlcyhkaW1zOiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBjb25zdCByYW5rID0gZGltcy5sZW5ndGg7XG4gICAgaWYgKHJhbmsgPT09IDApIHtcbiAgICAgIHJldHVybiBbXTtcbiAgICB9IGVsc2UgaWYgKHJhbmsgPT09IDEpIHtcbiAgICAgIHJldHVybiBbMV07XG4gICAgfVxuICAgIGNvbnN0IHN0cmlkZXMgPSBuZXcgQXJyYXkocmFuayk7XG4gICAgc3RyaWRlc1tyYW5rIC0gMV0gPSAxO1xuICAgIHN0cmlkZXNbcmFuayAtIDJdID0gZGltc1tyYW5rIC0gMV07XG4gICAgZm9yIChsZXQgaSA9IHJhbmsgLSAzOyBpID49IDA7IC0taSkge1xuICAgICAgc3RyaWRlc1tpXSA9IHN0cmlkZXNbaSArIDFdICogZGltc1tpICsgMV07XG4gICAgfVxuICAgIHJldHVybiBzdHJpZGVzO1xuICB9XG5cbiAgLyoqXG4gICAqIG5vcm1haWx6ZSBheGlzIG9mIHJhbmdlIFstciwgcikgaW50byBbMCwgcikuXG4gICAqL1xuICBzdGF0aWMgbm9ybWFsaXplQXhpcyhheGlzOiBudW1iZXIsIHRlbnNvclJhbms6IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKGF4aXMgPCAtdGVuc29yUmFuayAmJiBheGlzID49IHRlbnNvclJhbmspIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndW5zdXBwb3J0ZWQgYXhpcyBmb3IgdGhpcyBvcGVyYXRpb24uJyk7XG4gICAgfVxuICAgIHJldHVybiBheGlzIDwgMCA/IGF4aXMgKyB0ZW5zb3JSYW5rIDogYXhpcztcbiAgfVxuXG4gIHN0YXRpYyBub3JtYWxpemVBeGVzKGF4ZXM6IHJlYWRvbmx5IG51bWJlcltdLCB0ZW5zb3JSYW5rPzogbnVtYmVyKTogbnVtYmVyW10ge1xuICAgIHJldHVybiBheGVzLm1hcCh4ID0+IHRoaXMubm9ybWFsaXplQXhpcyh4LCB0ZW5zb3JSYW5rID8/IGF4ZXMubGVuZ3RoKSk7XG4gIH1cblxuICAvKipcbiAgICogU29ydHMgYSBnaXZlbiBhcnJheSBiYXNlZCBvbiB0aGUgaW5kaWNlcyBpbiB0aGUgUGVybSBhcnJheVxuICAgKiBVc2VkIGluIFRyYW5zcG9zZVxuICAgKiBAcGFyYW0gYSBBcnJheSB0byBiZSBzb3J0ZWQgc3VjaCBhcyBkaW1zIG9yIHN0cmlkZXNcbiAgICogQHBhcmFtIHBlcm0gUGVybSBnaXZlbjsgaWYgbnVsbCBhIHdpbGwgYmUgcmV2ZXJzZWRcbiAgICovXG4gIHN0YXRpYyBzb3J0QmFzZWRPblBlcm0oYTogcmVhZG9ubHkgbnVtYmVyW10sIHBlcm0/OiByZWFkb25seSBudW1iZXJbXSk6IHJlYWRvbmx5IG51bWJlcltdIHtcbiAgICBpZiAocGVybSkge1xuICAgICAgcmV0dXJuIHBlcm0ubWFwKCh2KSA9PiBhW3ZdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGEuc2xpY2UoKS5yZXZlcnNlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFBhZHMgYSBnaXZlbiBzaGFwZSBhY2NvcmRpbmcgdG8gdGhlIHBhZGRpbmcgdmFsdWVzXG4gICAqIEBwYXJhbSBkaW1zIHNoYXBlIG9mIHRoZSBUZW5zb3IgdG8gYmUgcGFkZGVkXG4gICAqIEBwYXJhbSBwYWQgcGFkIHZhbHVlc1xuICAgKi9cbiAgc3RhdGljIHBhZFNoYXBlKGRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBwYWQ6IHJlYWRvbmx5IG51bWJlcltdKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIGNvbnN0IHJhbmsgPSBkaW1zLmxlbmd0aDtcbiAgICByZXR1cm4gZGltcy5tYXAoKHYsIGkpID0+IHYgKyBwYWRbaV0gKyBwYWRbaSArIHJhbmtdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIGlmIHRoZSB0d28gc2hhcGVzIGFyZSBpZGVudGljYWxcbiAgICogQHBhcmFtIHNoYXBlMVxuICAgKiBAcGFyYW0gc2hhcGUyXG4gICAqL1xuICBzdGF0aWMgYXJlRXF1YWwoc2hhcGUxOiByZWFkb25seSBudW1iZXJbXSwgc2hhcGUyOiByZWFkb25seSBudW1iZXJbXSk6IGJvb2xlYW4ge1xuICAgIGlmIChzaGFwZTEubGVuZ3RoICE9PSBzaGFwZTIubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBzaGFwZTEuZXZlcnkoKHYsIGkpID0+IHYgPT09IHNoYXBlMltpXSk7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFBvb2xDb252VXRpbCB7XG4gIC8qKlxuICAgKiBBZGp1c3QgdGhlIGtlcm5lbCwgc3RyaWRlcywgcGFkcyB0byBjb3JyZWN0IHJhbmsuIFNldCB0byBkZWZhdWx0IHZhbHVlIGlmIG5vdCBwcmVzZW50XG4gICAqIEBwYXJhbSBpc0dsb2JhbE9wZXJhdG9yIElmIHRydWUsIHBlcmZvcm0gZ2xvYmFsIHBvb2xpbmcuXG4gICAqIEBwYXJhbSBpbnB1dERpbXMgVGhlIGlucHV0IHRlbnNvciBkaW1lbnNpb24uXG4gICAqIEBwYXJhbSBrZXJuZWxTaGFwZSBUaGUgc2l6ZSBvZiB0aGUga2VybmVsIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIHN0cmlkZXMgU3RyaWRlIGFsb25nIGVhY2ggYXhpcy5cbiAgICogQHBhcmFtIGRpbGF0aW9ucyBEaWxhdGlvbiBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBwYWRzIFBhZGRpbmcgZm9yIHRoZSBiZWdpbm5pbmcgYW5kIGVuZGluZyBhbG9uZyBlYWNoIGF4aXMuXG4gICAqL1xuICBzdGF0aWMgYWRqdXN0UG9vbEF0dHJpYnV0ZXMoXG4gICAgICBpc0dsb2JhbE9wZXJhdG9yOiBib29sZWFuLCBpbnB1dERpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBrZXJuZWxTaGFwZTogbnVtYmVyW10sIHN0cmlkZXM6IG51bWJlcltdLFxuICAgICAgZGlsYXRpb25zOiBudW1iZXJbXSwgcGFkczogbnVtYmVyW10pOiB2b2lkIHtcbiAgICBpZiAoIWlzR2xvYmFsT3BlcmF0b3IgJiYga2VybmVsU2hhcGUubGVuZ3RoICE9PSBpbnB1dERpbXMubGVuZ3RoIC0gMikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdsZW5ndGggb2Ygc3BlY2lmaWVkIGtlcm5lbCBzaGFwZXMgc2hvdWxkIGJlIDIgbGVzcyB0aGFuIGxlbmd0aCBvZiBpbnB1dCBkaW1lbnNpb25zJyk7XG4gICAgfVxuXG4gICAgaWYgKGlzR2xvYmFsT3BlcmF0b3IpIHtcbiAgICAgIC8vIGFkanVzdCBrZXJuZWwgc2hhcGUgdG8gY292ZXIgdGhlIGlucHV0IGRpbXNcbiAgICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGlucHV0RGltcy5sZW5ndGggLSAyOyBkaW0rKykge1xuICAgICAgICBpZiAoZGltID49IGtlcm5lbFNoYXBlLmxlbmd0aCkge1xuICAgICAgICAgIGtlcm5lbFNoYXBlLnB1c2goaW5wdXREaW1zW2RpbSArIDJdKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBrZXJuZWxTaGFwZVtkaW1dID0gaW5wdXREaW1zW2RpbSArIDJdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gYWRqdXN0IHN0cmlkZXMgbGVuZ3RoIHRvIG1hdGNoIGtlcm5lbCBzaGFwZSBsZW5ndGhcbiAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBrZXJuZWxTaGFwZS5sZW5ndGg7IGRpbSsrKSB7XG4gICAgICBpZiAoZGltIDwgc3RyaWRlcy5sZW5ndGgpIHtcbiAgICAgICAgaWYgKHN0cmlkZXNbZGltXSA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3N0cmlkZXMgc2hvdWxkIGJlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAxJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0cmlkZXMucHVzaCgxKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBhZGp1c3QgZGlsYXRpb24gdmFsdWVcbiAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBrZXJuZWxTaGFwZS5sZW5ndGg7IGRpbSsrKSB7XG4gICAgICBpZiAoZGltIDwgZGlsYXRpb25zLmxlbmd0aCkge1xuICAgICAgICBpZiAoZGlsYXRpb25zW2RpbV0gPCAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkaWxhdGlvbnMgc2hvdWxkIGJlIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAxJyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRpbGF0aW9ucy5wdXNoKDEpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGFkanVzdCBwYWRzIGxlbmd0aCB0byBtYXRjaCAyICoga2VybmVsIHNoYXBlIGxlbmd0aFxuICAgIGZvciAobGV0IGRpbSA9IDA7IGRpbSA8IGtlcm5lbFNoYXBlLmxlbmd0aCAqIDI7IGRpbSsrKSB7XG4gICAgICBpZiAoZGltIDwgcGFkcy5sZW5ndGgpIHtcbiAgICAgICAgaWYgKHBhZHNbZGltXSA8IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BhZCBzaG91bGQgYmUgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRvIDEnKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGFkcy5wdXNoKDApO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIHNhbml0eSBjaGVja3MgZm9yIHZhbHVlcyBpbiBrZXJuZWwgc2hhcGVzIGFuZCBwYWRzXG4gICAgZm9yIChsZXQgZGltID0gMDsgZGltIDwga2VybmVsU2hhcGUubGVuZ3RoOyBkaW0rKykge1xuICAgICAgaWYgKGtlcm5lbFNoYXBlW2RpbV0gPD0gMCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2tlcm5lbCBzaGFwZXMgbmVlZCB0byBiZSBncmVhdGVyIHRoYW4gMCcpO1xuICAgICAgfVxuXG4gICAgICBpZiAocGFkc1tkaW1dID49IGtlcm5lbFNoYXBlW2RpbV0gfHwgcGFkc1tkaW0gKyBrZXJuZWxTaGFwZS5sZW5ndGhdID49IGtlcm5lbFNoYXBlW2RpbV0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdwYWRzIHNob3VsZCBiZSBzbWFsbGVyIHRoYW4ga2VybmVsJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gYWRqdXN0IHBhZCB2YWx1ZXMgYmFzZWQgb24gJ2F1dG9QYWQnIGF0dHJpYnV0ZVxuICBzdGF0aWMgYWRqdXN0UGFkc0Jhc2VkT25BdXRvUGFkKFxuICAgICAgaW5wdXREaW1zOiByZWFkb25seSBudW1iZXJbXSwgc3RyaWRlczogcmVhZG9ubHkgbnVtYmVyW10sIGRpbGF0aW9uczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgICBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIHBhZHM6IG51bWJlcltdLCBpc0NoYW5uZWxMYXN0OiBib29sZWFuLCBhdXRvUGFkPzogc3RyaW5nKTogdm9pZCB7XG4gICAgaWYgKCFhdXRvUGFkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHBhZHMubGVuZ3RoICE9PSAyICogKGlucHV0RGltcy5sZW5ndGggLSAyKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdsZW5ndGggb2YgcGFkcyBzaG91bGQgYmUgdHdpY2UgdGhlIGxlbmd0aCBvZiBkYXRhIGRpbWVuc2lvbnMnKTtcbiAgICB9XG5cbiAgICBpZiAoc3RyaWRlcy5sZW5ndGggIT09IChpbnB1dERpbXMubGVuZ3RoIC0gMikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbGVuZ3RoIG9mIHN0cmlkZXMgc2hvdWxkIGJlIHRoZSBsZW5ndGggb2YgZGF0YSBkaW1lbnNpb25zJyk7XG4gICAgfVxuXG4gICAgaWYgKGtlcm5lbFNoYXBlLmxlbmd0aCAhPT0gKGlucHV0RGltcy5sZW5ndGggLSAyKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdsZW5ndGggb2Yga2VybmVsIHNoYXBlcyBzaG91bGQgYmUgdGhlIGxlbmd0aCBvZiBkYXRhIGRpbWVuc2lvbnMnKTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBkaW0gPSAwOyBkaW0gPCBpbnB1dERpbXMubGVuZ3RoIC0gMjsgZGltKyspIHtcbiAgICAgIFBvb2xDb252VXRpbC5hZGp1c3RQYWRBbmRSZXR1cm5TaGFwZShcbiAgICAgICAgICBpbnB1dERpbXNbZGltICsgKGlzQ2hhbm5lbExhc3QgPyAxIDogMildLCBzdHJpZGVzW2RpbV0sIGRpbGF0aW9uc1tkaW1dLCBrZXJuZWxTaGFwZVtkaW1dLCBwYWRzLCBkaW0sXG4gICAgICAgICAgZGltICsgaW5wdXREaW1zLmxlbmd0aCAtIDIsIGF1dG9QYWQpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgdGhlIG91dHB1dCBzaGFwZSBmb3IgUG9vbCBvcHMgYmFzZWQgb24gaW5wdXQgYXR0cmlidXRlcy4gKFNob3VsZCBiZSB1c2VkIG9ubHkgZm9yIFBvb2wgb3BzKVxuICAgKiBAcGFyYW0gaXNHbG9iYWxPcGVyYXRvciBJZiB0cnVlLCBwZXJmb3JtIGdsb2JhbCBwb29saW5nLlxuICAgKiBAcGFyYW0gaW5wdXREaW1zIFRoZSBpbnB1dCB0ZW5zb3IgZGltZW5zaW9uLiAoaW5wdXRzWzBdLmRpbXMpXG4gICAqIEBwYXJhbSBzdHJpZGVzIFN0cmlkZSBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBkaWxhdGlvbnMgRGlsYXRpb24gYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0ga2VybmVsU2hhcGUgVGhlIHNpemUgb2YgdGhlIGtlcm5lbCBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBwYWRzIFBhZGRpbmcgZm9yIHRoZSBiZWdpbm5pbmcgYW5kIGVuZGluZyBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBhdXRvUGFkIERFUFJFQ0FURUQgYXR0cmlidXRlIHN1cHBvcnRlZCBmb3IgbGVnYWN5IG1vZGVscy4gU3BlY2lmaWVzIGhvdyB0byBpbXBsaWNpdGx5IGNhbGN1bGF0ZSBwYWRzIGluIGVhY2hcbiAgICogICAgIGRpbWVuc2lvbi4gQ2FuIHRha2UgdmFsdWVzIE5PVFNFVCwgU0FNRV9VUFBFUiwgU0FNRV9MT1dFUiwgb3IgVkFMSUQuXG4gICAqL1xuICBzdGF0aWMgY29tcHV0ZVBvb2xPdXRwdXRTaGFwZShcbiAgICAgIGlzR2xvYmFsT3BlcmF0b3I6IGJvb2xlYW4sIGlucHV0RGltczogcmVhZG9ubHkgbnVtYmVyW10sIHN0cmlkZXM6IG51bWJlcltdLCBkaWxhdGlvbnM6IG51bWJlcltdLFxuICAgICAga2VybmVsU2hhcGU6IG51bWJlcltdLCBwYWRzOiBudW1iZXJbXSwgYXV0b1BhZD86IHN0cmluZyk6IG51bWJlcltdIHtcbiAgICBpZiAoaW5wdXREaW1zLmxlbmd0aCA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2lucHV0IHNoYXBlIG11c3QgYmUgb2Ygc2l6ZSBncmVhdGVyIHRoYW4gMCcpO1xuICAgIH1cblxuICAgIC8vIEFkZCBiYXRjaCBzaXplIGFuZCBudW1iZXIgb2YgY2hhbm5lbHMgb2Ygb3V0cHV0XG4gICAgY29uc3Qgb3V0cHV0RGltcyA9IFtpbnB1dERpbXNbMF0sIGlucHV0RGltc1sxXV07XG5cbiAgICBQb29sQ29udlV0aWwuY29tcHV0ZVNoYXBlSGVscGVyKFxuICAgICAgICBpc0dsb2JhbE9wZXJhdG9yLCBpbnB1dERpbXMsIG91dHB1dERpbXMsIHN0cmlkZXMsIGRpbGF0aW9ucywga2VybmVsU2hhcGUsIHBhZHMsIGF1dG9QYWQpO1xuICAgIHJldHVybiBvdXRwdXREaW1zO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZSB0aGUgb3V0cHV0IHNoYXBlIGZvciBDb252IG9wIGJhc2VkIG9uIGlucHV0IGF0dHJpYnV0ZXMuIChTaG91bGQgYmUgdXNlZCBvbmx5IGZvciBDb252IG9wKVxuICAgKiBAcGFyYW0gaW5wdXREaW1zIFRoZSBpbnB1dCB0ZW5zb3IgZGltZW5zaW9uLiAoaW5wdXRzWzBdLmRpbXMpXG4gICAqIEBwYXJhbSBmaWx0ZXJEaW1zIFRoZSBmaWx0ZXIgdGVuc29yIGRpbWVuc2lvbi4gKGlucHV0c1sxXS5kaW1zKVxuICAgKiBAcGFyYW0gc3RyaWRlcyBTdHJpZGUgYWxvbmcgZWFjaCBheGlzLlxuICAgKiBAcGFyYW0ga2VybmVsU2hhcGUgVGhlIHNpemUgb2YgdGhlIGtlcm5lbCBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBwYWRzIFBhZGRpbmcgZm9yIHRoZSBiZWdpbm5pbmcgYW5kIGVuZGluZyBhbG9uZyBlYWNoIGF4aXMuXG4gICAqIEBwYXJhbSBhdXRvUGFkIERFUFJFQ0FURUQgYXR0cmlidXRlIHN1cHBvcnRlZCBmb3IgbGVnYWN5IG1vZGVscy4gU3BlY2lmaWVzIGhvdyB0byBpbXBsaWNpdGx5IGNhbGN1bGF0ZSBwYWRzIGluIGVhY2hcbiAgICogICAgIGRpbWVuc2lvbi4gQ2FuIHRha2UgdmFsdWVzIE5PVFNFVCwgU0FNRV9VUFBFUiwgU0FNRV9MT1dFUiwgb3IgVkFMSUQuXG4gICAqL1xuICBzdGF0aWMgY29tcHV0ZUNvbnZPdXRwdXRTaGFwZShcbiAgICAgIGlucHV0RGltczogcmVhZG9ubHkgbnVtYmVyW10sIGZpbHRlckRpbXM6IHJlYWRvbmx5IG51bWJlcltdLCBzdHJpZGVzOiBudW1iZXJbXSwgZGlsYXRpb25zOiBudW1iZXJbXSxcbiAgICAgIGtlcm5lbFNoYXBlOiBudW1iZXJbXSwgcGFkczogbnVtYmVyW10sIGF1dG9QYWQ/OiBzdHJpbmcpOiBudW1iZXJbXSB7XG4gICAgaWYgKGlucHV0RGltcy5sZW5ndGggPD0gMCB8fCBmaWx0ZXJEaW1zLmxlbmd0aCA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgaW5wdXQgdGVuc29yIGRpbXMgb3IgaW52YWxpZCBmaWx0ZXIgdGVuc29yIGRpbXMnKTtcbiAgICB9XG5cbiAgICAvLyBBZGQgYmF0Y2ggc2l6ZSBhbmQgbnVtYmVyIG9mIGNoYW5uZWxzIG9mIG91dHB1dFxuICAgIGNvbnN0IG91dHB1dERpbXMgPSBbaW5wdXREaW1zWzBdLCBmaWx0ZXJEaW1zWzBdXTtcblxuICAgIFBvb2xDb252VXRpbC5jb21wdXRlU2hhcGVIZWxwZXIoZmFsc2UsIGlucHV0RGltcywgb3V0cHV0RGltcywgc3RyaWRlcywgZGlsYXRpb25zLCBrZXJuZWxTaGFwZSwgcGFkcywgYXV0b1BhZCk7XG4gICAgcmV0dXJuIG91dHB1dERpbXM7XG4gIH1cblxuICAvLyB3aWxsIGNvbXB1dGUgb3V0cHV0IHNoYXBlcyBmb3IgZGF0YSBkaW1lbnNpb25zIE9OTFkgKGkuZS4pIG5vIGJhdGNoIHNpemUgYW5kIGNoYW5uZWxzXG4gIC8vIGNhbGxlZCBieSBjb21wdXRlUG9vbE91dHB1dFNoYXBlKCkgYW5kIGNvbXB1dGVDb252T3V0cHV0U2hhcGUoKVxuICAvLyBhZGp1c3QgcGFkcyBiYXNlZCBvbiAnYXV0b1BhZCcgYXR0cmlidXRlIHByaW9yIHRvIHNoYXBlIGNvbXB1dGF0aW9uXG4gIHByaXZhdGUgc3RhdGljIGNvbXB1dGVTaGFwZUhlbHBlcihcbiAgICAgIGlzR2xvYmFsT3BlcmF0b3I6IGJvb2xlYW4sIGlucHV0RGltczogcmVhZG9ubHkgbnVtYmVyW10sIG91dHB1dERpbXM6IG51bWJlcltdLCBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXSxcbiAgICAgIGRpbGF0aW9uczogcmVhZG9ubHkgbnVtYmVyW10sIGtlcm5lbFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgcGFkczogbnVtYmVyW10sIGF1dG9QYWQ/OiBzdHJpbmcpIHtcbiAgICBpZiAoaXNHbG9iYWxPcGVyYXRvcikge1xuICAgICAgZm9yIChsZXQgZGltID0gMDsgZGltIDwgaW5wdXREaW1zLmxlbmd0aCAtIDI7IGRpbSsrKSB7XG4gICAgICAgIG91dHB1dERpbXMucHVzaCgxKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZm9yIChsZXQgZGltID0gMDsgZGltIDwgaW5wdXREaW1zLmxlbmd0aCAtIDI7IGRpbSsrKSB7XG4gICAgICAgIG91dHB1dERpbXMucHVzaChQb29sQ29udlV0aWwuYWRqdXN0UGFkQW5kUmV0dXJuU2hhcGUoXG4gICAgICAgICAgICBpbnB1dERpbXNbZGltICsgMl0sIHN0cmlkZXNbZGltXSwgZGlsYXRpb25zW2RpbV0sIGtlcm5lbFNoYXBlW2RpbV0sIHBhZHMsIGRpbSwgZGltICsgaW5wdXREaW1zLmxlbmd0aCAtIDIsXG4gICAgICAgICAgICBhdXRvUGFkKSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gaGVscGVyIGZvciBjb21wdXRlU2hhcGVIZWxwZXIoKSBhbmQgYWRqdXN0UGFkc0Jhc2VkT25BdXRvUGFkKClcbiAgLy8gYWRqdXN0cyBwYWQgdmFsdWUgZm9yIGdpdmVuICdhdXRvUGFkJyBzdHJpbmcgYW5kIGNvbXB1dGVzIG91dHB1dCBzaGFwZSBhbG9uZyBhIHBhcnRpY3VsYXIgZGltZW5zaW9uXG4gIHByaXZhdGUgc3RhdGljIGFkanVzdFBhZEFuZFJldHVyblNoYXBlKFxuICAgICAgaW5TaXplOiBudW1iZXIsIHN0cmlkZTogbnVtYmVyLCBkaWxhdGlvbjogbnVtYmVyLCBrZXJuZWw6IG51bWJlciwgcGFkczogbnVtYmVyW10sIHBhZEhlYWRJbmRleDogbnVtYmVyLFxuICAgICAgcGFkVGFpbEluZGV4OiBudW1iZXIsIGF1dG9QYWQ/OiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGNvbnN0IGRrZXJuZWwgPSBkaWxhdGlvbiAqIChrZXJuZWwgLSAxKSArIDE7XG4gICAgaWYgKGF1dG9QYWQgJiYgYXV0b1BhZCAhPT0gJ05PVFNFVCcpIHtcbiAgICAgIHN3aXRjaCAoYXV0b1BhZCkge1xuICAgICAgICBjYXNlICdWQUxJRCc6XG4gICAgICAgICAgcGFkc1twYWRIZWFkSW5kZXhdID0gMDtcbiAgICAgICAgICBwYWRzW3BhZFRhaWxJbmRleF0gPSAwO1xuICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKCgoaW5TaXplIC0gZGtlcm5lbCkgLyBzdHJpZGUpICsgMSk7XG4gICAgICAgIGNhc2UgJ1NBTUVfTE9XRVInOlxuICAgICAgICBjYXNlICdTQU1FX1VQUEVSJzpcbiAgICAgICAgICBpZiAoZGlsYXRpb24gIT09IDEpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRGlsYXRpb24gbm90IHN1cHBvcnRlZCBmb3IgU0FNRV9VUFBFUiBvciBTQU1FX0xPV0VSJyk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGxlZ2FjeVRhcmdldFNpemUgPSAoaW5TaXplICsgc3RyaWRlIC0gMSkgLyBzdHJpZGU7XG4gICAgICAgICAgICBjb25zdCBwYWROZWVkZWQgPSAobGVnYWN5VGFyZ2V0U2l6ZSAtIDEpICogc3RyaWRlICsga2VybmVsIC0gaW5TaXplO1xuICAgICAgICAgICAgcGFkc1twYWRIZWFkSW5kZXhdID1cbiAgICAgICAgICAgICAgICAoYXV0b1BhZCA9PT0gJ1NBTUVfTE9XRVInKSA/IE1hdGguZmxvb3IoKHBhZE5lZWRlZCArIDEpIC8gMikgOiBNYXRoLmZsb29yKHBhZE5lZWRlZCAvIDIpO1xuICAgICAgICAgICAgcGFkc1twYWRUYWlsSW5kZXhdID0gcGFkTmVlZGVkIC0gcGFkc1twYWRIZWFkSW5kZXhdO1xuICAgICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoKChpblNpemUgKyBwYWROZWVkZWQgLSBrZXJuZWwpIC8gc3RyaWRlKSArIDEpO1xuICAgICAgICAgIH1cbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydGVkIEF1dG9QYWQgdHlwZScpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gTWF0aC5mbG9vcigoKGluU2l6ZSArIHBhZHNbcGFkSGVhZEluZGV4XSArIHBhZHNbcGFkVGFpbEluZGV4XSAtIGRrZXJuZWwpIC8gc3RyaWRlKSArIDEpO1xuICAgIH1cbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgR2VtbVV0aWwge1xuICAvLyB3aWxsIG1ha2Ugc3VyZSBpbnB1dCBzaGFwZXMgYXJlIGNvbXBhdGlibGUgZm9yIHRoaXMgb3BcbiAgLy8gYW5kIHJldHVybiBiYWNrIHRoZSBzaGFwZSBvZiB0aGUgb3V0cHV0IGluIHRoZSBmb3JtIG9mIGEgdHVwbGVcbiAgLy8gd2lsbCB0aHJvdyBleGNlcHRpb24gaWYgdGhlIGlucHV0IHNoYXBlcyBhcmUgbm90IGNvbXBhdGlibGVcbiAgc3RhdGljIGdldFNoYXBlT2ZHZW1tUmVzdWx0KFxuICAgICAgbGVmdFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgdHJhbnNMZWZ0OiBib29sZWFuLCByaWdodFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgdHJhbnNSaWdodDogYm9vbGVhbixcbiAgICAgIGJpYXNTaGFwZT86IHJlYWRvbmx5IG51bWJlcltdKTogcmVhZG9ubHkgbnVtYmVyW10ge1xuICAgIGlmIChsZWZ0U2hhcGUubGVuZ3RoICE9PSAyIHx8IHJpZ2h0U2hhcGUubGVuZ3RoICE9PSAyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3NoYXBlIG5lZWQgdG8gYmUgb2Ygc2l6ZSAyJyk7XG4gICAgfVxuXG4gICAgbGV0IE06IG51bWJlcjtcbiAgICBsZXQgSzogbnVtYmVyO1xuICAgIGxldCBOOiBudW1iZXI7XG5cbiAgICBpZiAodHJhbnNMZWZ0KSB7XG4gICAgICBNID0gbGVmdFNoYXBlWzFdO1xuICAgICAgSyA9IGxlZnRTaGFwZVswXTtcbiAgICB9IGVsc2Uge1xuICAgICAgTSA9IGxlZnRTaGFwZVswXTtcbiAgICAgIEsgPSBsZWZ0U2hhcGVbMV07XG4gICAgfVxuXG4gICAgbGV0IGtEaW0gPSAtMTtcblxuICAgIGlmICh0cmFuc1JpZ2h0KSB7XG4gICAgICBOID0gcmlnaHRTaGFwZVswXTtcbiAgICAgIGtEaW0gPSAxO1xuICAgIH0gZWxzZSB7XG4gICAgICBOID0gcmlnaHRTaGFwZVsxXTtcbiAgICAgIGtEaW0gPSAwO1xuICAgIH1cblxuICAgIGlmIChyaWdodFNoYXBlW2tEaW1dICE9PSBLKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RpbWVuc2lvbiBtaXNtYXRjaCcpO1xuICAgIH1cblxuICAgIGlmIChNIDw9IDAgfHwgTiA8PSAwIHx8IEsgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHNoYXBlIHNwZWNpZmllZCcpO1xuICAgIH1cblxuICAgIGlmIChiaWFzU2hhcGUgJiYgIUJyb2FkY2FzdFV0aWwuaXNWYWxpZEJyb2FkY2FzdChiaWFzU2hhcGUsIFtNLCBOXSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ2VtbTogaW52YWxpZCBiaWFzIHNoYXBlIGZvciBicm9hZGNhc3QnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gW00sIE4sIEtdO1xuICB9XG59XG5cblxuZXhwb3J0IGNvbnN0IE1JTl9DTElQID0gLTMuNDAyODIzNDY2Mzg1Mjg4NmUrMzg7XG5leHBvcnQgY29uc3QgTUFYX0NMSVAgPSAzLjQwMjgyMzQ2NjM4NTI4ODZlKzM4O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmNsYXNzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleUltcGwge1xuICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGU6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSB7XG4gICAgT2JqZWN0LmFzc2lnbih0aGlzLCBhdHRyaWJ1dGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBfY2FjaGVLZXk6IHN0cmluZztcbiAgcHVibGljIGdldCBjYWNoZUtleSgpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5fY2FjaGVLZXkpIHtcbiAgICAgIHRoaXMuX2NhY2hlS2V5ID1cbiAgICAgICAgICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKS5zb3J0KCkubWFwKG5hbWUgPT4gYCR7KHRoaXMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW25hbWVdfWApLmpvaW4oJzsnKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2NhY2hlS2V5O1xuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgY2FjaGVLZXk6IHN0cmluZztcbn1cblxuLyoqXG4gKiBjcmVhdGUgYSBuZXcgb2JqZWN0IGZyb20gdGhlIGdpdmVuIGF0dHJpYnV0ZSwgYW5kIGFkZCBhIGNhY2hlS2V5IHByb3BlcnR5IHRvIGl0XG4gKi9cbmV4cG9ydCBjb25zdCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkgPSA8VCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+PihhdHRyaWJ1dGU6IFQpOiBUJkF0dHJpYnV0ZVdpdGhDYWNoZUtleSA9PlxuICAgIG5ldyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXlJbXBsKGF0dHJpYnV0ZSkgYXMgdW5rbm93biBhcyBUICYgQXR0cmlidXRlV2l0aENhY2hlS2V5O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7V2ViR3B1QmFja2VuZH0gZnJvbSAnLi4vYmFja2VuZC13ZWJncHUnO1xuaW1wb3J0IHtMT0dfREVCVUd9IGZyb20gJy4uL2xvZyc7XG5cbmltcG9ydCB7R3B1RGF0YSwgR3B1RGF0YUlkLCBHcHVEYXRhVHlwZX0gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogbWFuYWdlcyBHcHVEYXRhSWQgLT4gR3B1QnVmZmVyXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR3B1RGF0YU1hbmFnZXIge1xuICAvKipcbiAgICogY29weSBkYXRhIGZyb20gQ1BVIHRvIEdQVS5cbiAgICovXG4gIHVwbG9hZChpZDogR3B1RGF0YUlkLCBkYXRhOiBVaW50OEFycmF5KTogdm9pZDtcbiAgLyoqXG4gICAqIGNvcHkgZGF0YSBmcm9tIEdQVSB0byBHUFUuXG4gICAqL1xuICBtZW1jcHkoc291cmNlSWQ6IEdwdURhdGFJZCwgZGVzdGluYXRpb25JZDogR3B1RGF0YUlkKTogdm9pZDtcbiAgLyoqXG4gICAqIGNyZWF0ZSBuZXcgZGF0YSBvbiBHUFUuXG4gICAqL1xuICBjcmVhdGUoc2l6ZTogbnVtYmVyLCB1c2FnZT86IG51bWJlcik6IEdwdURhdGE7XG4gIC8qKlxuICAgKiBnZXQgR1BVIGRhdGEgYnkgSUQuXG4gICAqL1xuICBnZXQoaWQ6IEdwdURhdGFJZCk6IEdwdURhdGF8dW5kZWZpbmVkO1xuICAvKipcbiAgICogcmVsZWFzZSB0aGUgZGF0YSBvbiBHUFUgYnkgSUQuXG4gICAqXG4gICAqIEByZXR1cm4gc2l6ZSBvZiB0aGUgZGF0YSByZWxlYXNlZFxuICAgKi9cbiAgcmVsZWFzZShpZDogR3B1RGF0YUlkKTogbnVtYmVyO1xuICAvKipcbiAgICogY29weSBkYXRhIGZyb20gR1BVIHRvIENQVS5cbiAgICovXG4gIGRvd25sb2FkKGlkOiBHcHVEYXRhSWQpOiBQcm9taXNlPEFycmF5QnVmZmVyTGlrZT47XG5cbiAgLyoqXG4gICAqIHJlZnJlc2ggdGhlIGJ1ZmZlcnMgdGhhdCBtYXJrZWQgZm9yIHJlbGVhc2UuXG4gICAqXG4gICAqIHdoZW4gcmVsZWFzZSgpIGlzIGNhbGxlZCwgdGhlIGJ1ZmZlciBpcyBub3QgcmVsZWFzZWQgaW1tZWRpYXRlbHkuIHRoaXMgaXMgYmVjYXVzZSB3ZSBuZWVkIHRvIHdhaXQgZm9yIHRoZSBjb21tYW5kc1xuICAgKiB0byBiZSBzdWJtaXR0ZWQgdG8gdGhlIEdQVS4gdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgYWZ0ZXIgdGhlIGNvbW1hbmRzIGFyZSBzdWJtaXR0ZWQgc28gdGhhdCB0aGUgYnVmZmVycyBjYW4gYmVcbiAgICogYWN0dWFsbHkgcmVsZWFzZWQuXG4gICAqL1xuICByZWZyZXNoUGVuZGluZ0J1ZmZlcnMoKTogdm9pZDtcbn1cblxuaW50ZXJmYWNlIFN0b3JhZ2VDYWNoZVZhbHVlIHtcbiAgZ3B1RGF0YTogR3B1RGF0YTtcbiAgb3JpZ2luYWxTaXplOiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBEb3dubG9hZENhY2hlVmFsdWUge1xuICBkYXRhOiBQcm9taXNlPEFycmF5QnVmZmVyTGlrZT47XG59XG5cbi8qKlxuICogbm9ybWFsaXplIHRoZSBidWZmZXIgc2l6ZSBzbyB0aGF0IGl0IGZpdHMgdGhlIDEyOC1iaXRzICgxNiBieXRlcykgYWxpZ25tZW50LlxuICovXG5jb25zdCBjYWxjTm9ybWFsaXplZEJ1ZmZlclNpemUgPSAoc2l6ZTogbnVtYmVyKSA9PiBNYXRoLmNlaWwoc2l6ZSAvIDE2KSAqIDE2O1xuXG5sZXQgZ3VpZCA9IDA7XG5jb25zdCBjcmVhdGVOZXdHcHVEYXRhSWQgPSAoKSA9PiBndWlkKys7XG5cbmNsYXNzIEdwdURhdGFNYW5hZ2VySW1wbCBpbXBsZW1lbnRzIEdwdURhdGFNYW5hZ2VyIHtcbiAgLy8gR1BVIERhdGEgSUQgPT4gR1BVIERhdGEgKCBzdG9yYWdlIGJ1ZmZlciApXG4gIHN0b3JhZ2VDYWNoZTogTWFwPEdwdURhdGFJZCwgU3RvcmFnZUNhY2hlVmFsdWU+O1xuXG4gIC8vIEdQVSBEYXRhIElEID0+IEdQVSBEYXRhICggcmVhZCBidWZmZXIgKVxuICBkb3dubG9hZENhY2hlOiBNYXA8R3B1RGF0YUlkLCBEb3dubG9hZENhY2hlVmFsdWU+O1xuXG4gIC8vIHBlbmRpbmcgYnVmZmVycyBmb3IgdXBsb2FkaW5nICggZGF0YSBpcyB1bm1hcHBlZCApXG4gIHByaXZhdGUgYnVmZmVyc0ZvclVwbG9hZGluZ1BlbmRpbmc6IEdQVUJ1ZmZlcltdO1xuICAvLyBwZW5kaW5nIGJ1ZmZlcnMgZm9yIGNvbXB1dGluZ1xuICBwcml2YXRlIGJ1ZmZlcnNQZW5kaW5nOiBHUFVCdWZmZXJbXTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGJhY2tlbmQ6IFdlYkdwdUJhY2tlbmQgLyogLCBwcml2YXRlIHJldXNlQnVmZmVyOiBib29sZWFuICovKSB7XG4gICAgdGhpcy5zdG9yYWdlQ2FjaGUgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5kb3dubG9hZENhY2hlID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuYnVmZmVyc0ZvclVwbG9hZGluZ1BlbmRpbmcgPSBbXTtcbiAgICB0aGlzLmJ1ZmZlcnNQZW5kaW5nID0gW107XG4gIH1cblxuICB1cGxvYWQoaWQ6IEdwdURhdGFJZCwgZGF0YTogVWludDhBcnJheSk6IHZvaWQge1xuICAgIGNvbnN0IHNyY0FycmF5QnVmZmVyID0gZGF0YS5idWZmZXI7XG4gICAgY29uc3Qgc3JjT2Zmc2V0ID0gZGF0YS5ieXRlT2Zmc2V0O1xuICAgIGNvbnN0IHNyY0xlbmd0aCA9IGRhdGEuYnl0ZUxlbmd0aDtcbiAgICBjb25zdCBzaXplID0gY2FsY05vcm1hbGl6ZWRCdWZmZXJTaXplKHNyY0xlbmd0aCk7XG5cbiAgICAvLyBnZXQgZGVzdGluYXRpb24gZ3B1IGJ1ZmZlclxuICAgIGNvbnN0IGdwdURhdGFDYWNoZSA9IHRoaXMuc3RvcmFnZUNhY2hlLmdldChpZCk7XG4gICAgaWYgKCFncHVEYXRhQ2FjaGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZ3B1IGRhdGEgZm9yIHVwbG9hZGluZyBkb2VzIG5vdCBleGlzdCcpO1xuICAgIH1cbiAgICBpZiAoZ3B1RGF0YUNhY2hlLm9yaWdpbmFsU2l6ZSAhPT0gc3JjTGVuZ3RoKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGluY29uc2lzdGVudCBkYXRhIHNpemUuIGdwdSBkYXRhIHNpemU9JHtncHVEYXRhQ2FjaGUub3JpZ2luYWxTaXplfSwgZGF0YSBzaXplPSR7c3JjTGVuZ3RofWApO1xuICAgIH1cblxuICAgIC8vIGNyZWF0ZSBncHUgYnVmZmVyXG4gICAgY29uc3QgZ3B1QnVmZmVyRm9yVXBsb2FkaW5nID0gdGhpcy5iYWNrZW5kLmRldmljZS5jcmVhdGVCdWZmZXIoXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlXG4gICAgICAgIHttYXBwZWRBdENyZWF0aW9uOiB0cnVlLCBzaXplLCB1c2FnZTogR1BVQnVmZmVyVXNhZ2UuTUFQX1dSSVRFIHwgR1BVQnVmZmVyVXNhZ2UuQ09QWV9TUkN9KTtcblxuICAgIC8vIGNvcHkgKHVwbG9hZCkgZGF0YVxuICAgIGNvbnN0IGFycmF5QnVmZmVyID0gZ3B1QnVmZmVyRm9yVXBsb2FkaW5nLmdldE1hcHBlZFJhbmdlKCk7XG4gICAgbmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWZmZXIpLnNldChuZXcgVWludDhBcnJheShzcmNBcnJheUJ1ZmZlciwgc3JjT2Zmc2V0LCBzcmNMZW5ndGgpKTtcbiAgICBncHVCdWZmZXJGb3JVcGxvYWRpbmcudW5tYXAoKTtcblxuXG4gICAgLy8gR1BVIGNvcHlcbiAgICBjb25zdCBjb21tYW5kRW5jb2RlciA9IHRoaXMuYmFja2VuZC5nZXRDb21tYW5kRW5jb2RlcigpO1xuICAgIHRoaXMuYmFja2VuZC5lbmRDb21wdXRlUGFzcygpO1xuICAgIGNvbW1hbmRFbmNvZGVyLmNvcHlCdWZmZXJUb0J1ZmZlcihncHVCdWZmZXJGb3JVcGxvYWRpbmcsIDAsIGdwdURhdGFDYWNoZS5ncHVEYXRhLmJ1ZmZlciwgMCwgc2l6ZSk7XG5cbiAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW1dlYkdQVV0gR3B1RGF0YU1hbmFnZXIudXBsb2FkKGlkPSR7aWR9KWApO1xuXG4gICAgdGhpcy5idWZmZXJzRm9yVXBsb2FkaW5nUGVuZGluZy5wdXNoKGdwdUJ1ZmZlckZvclVwbG9hZGluZyk7XG4gIH1cblxuICBtZW1jcHkoc291cmNlSWQ6IEdwdURhdGFJZCwgZGVzdGluYXRpb25JZDogR3B1RGF0YUlkKTogdm9pZCB7XG4gICAgLy8gZ2V0IHNvdXJjZSBncHUgYnVmZmVyXG4gICAgY29uc3Qgc291cmNlR3B1RGF0YUNhY2hlID0gdGhpcy5zdG9yYWdlQ2FjaGUuZ2V0KHNvdXJjZUlkKTtcbiAgICBpZiAoIXNvdXJjZUdwdURhdGFDYWNoZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdzb3VyY2UgZ3B1IGRhdGEgZm9yIG1lbWNweSBkb2VzIG5vdCBleGlzdCcpO1xuICAgIH1cbiAgICAvLyBnZXQgZGVzdGluYXRpb24gZ3B1IGJ1ZmZlclxuICAgIGNvbnN0IGRlc3RpbmF0aW9uR3B1RGF0YUNhY2hlID0gdGhpcy5zdG9yYWdlQ2FjaGUuZ2V0KGRlc3RpbmF0aW9uSWQpO1xuICAgIGlmICghZGVzdGluYXRpb25HcHVEYXRhQ2FjaGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignZGVzdGluYXRpb24gZ3B1IGRhdGEgZm9yIG1lbWNweSBkb2VzIG5vdCBleGlzdCcpO1xuICAgIH1cbiAgICBpZiAoc291cmNlR3B1RGF0YUNhY2hlLm9yaWdpbmFsU2l6ZSAhPT0gZGVzdGluYXRpb25HcHVEYXRhQ2FjaGUub3JpZ2luYWxTaXplKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2luY29uc2lzdGVudCBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIGdwdSBkYXRhIHNpemUnKTtcbiAgICB9XG4gICAgY29uc3Qgc2l6ZSA9IGNhbGNOb3JtYWxpemVkQnVmZmVyU2l6ZShzb3VyY2VHcHVEYXRhQ2FjaGUub3JpZ2luYWxTaXplKTtcbiAgICAvLyBHUFUgY29weVxuICAgIHRoaXMuYmFja2VuZC5nZXRDb21tYW5kRW5jb2RlcigpLmNvcHlCdWZmZXJUb0J1ZmZlcihcbiAgICAgICAgc291cmNlR3B1RGF0YUNhY2hlLmdwdURhdGEuYnVmZmVyLCAwLCBkZXN0aW5hdGlvbkdwdURhdGFDYWNoZS5ncHVEYXRhLmJ1ZmZlciwgMCwgc2l6ZSk7XG4gIH1cblxuICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICBjcmVhdGUoc2l6ZTogbnVtYmVyLCB1c2FnZSA9IEdQVUJ1ZmZlclVzYWdlLlNUT1JBR0UgfCBHUFVCdWZmZXJVc2FnZS5DT1BZX1NSQyB8IEdQVUJ1ZmZlclVzYWdlLkNPUFlfRFNUKTogR3B1RGF0YSB7XG4gICAgLy8gISEhXG4gICAgLy8gISEhIElNUE9SVEFOVDogVE9ETzogd2hldGhlciB3ZSBzaG91bGQga2VlcCB0aGUgc3RvcmFnZSBidWZmZXIgZXZlcnkgdGltZSwgb3IgYWx3YXlzIGNyZWF0ZSBuZXcgb25lcy5cbiAgICAvLyAhISEgICAgICAgICAgICAgICAgICBUaGlzIG5lZWQgdG8gYmUgZmlndXJlZCBvdXQgYnkgcGVyZm9ybWFuY2UgdGVzdCByZXN1bHRzLlxuICAgIC8vICEhIVxuXG4gICAgY29uc3QgYnVmZmVyU2l6ZSA9IGNhbGNOb3JtYWxpemVkQnVmZmVyU2l6ZShzaXplKTtcblxuICAgIC8vIGNyZWF0ZSBncHUgYnVmZmVyXG4gICAgY29uc3QgZ3B1QnVmZmVyID0gdGhpcy5iYWNrZW5kLmRldmljZS5jcmVhdGVCdWZmZXIoe3NpemU6IGJ1ZmZlclNpemUsIHVzYWdlfSk7XG5cbiAgICBjb25zdCBncHVEYXRhID0ge2lkOiBjcmVhdGVOZXdHcHVEYXRhSWQoKSwgdHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdCwgYnVmZmVyOiBncHVCdWZmZXJ9O1xuICAgIHRoaXMuc3RvcmFnZUNhY2hlLnNldChncHVEYXRhLmlkLCB7Z3B1RGF0YSwgb3JpZ2luYWxTaXplOiBzaXplfSk7XG5cbiAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW1dlYkdQVV0gR3B1RGF0YU1hbmFnZXIuY3JlYXRlKHNpemU9JHtzaXplfSkgPT4gaWQ9JHtncHVEYXRhLmlkfWApO1xuICAgIHJldHVybiBncHVEYXRhO1xuICB9XG5cbiAgZ2V0KGlkOiBHcHVEYXRhSWQpOiBHcHVEYXRhfHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuc3RvcmFnZUNhY2hlLmdldChpZCk/LmdwdURhdGE7XG4gIH1cblxuICByZWxlYXNlKGlkOiBHcHVEYXRhSWQpOiBudW1iZXIge1xuICAgIGNvbnN0IGNhY2hlZERhdGEgPSB0aGlzLnN0b3JhZ2VDYWNoZS5nZXQoaWQpO1xuICAgIGlmICghY2FjaGVkRGF0YSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdyZWxlYXNpbmcgZGF0YSBkb2VzIG5vdCBleGlzdCcpO1xuICAgIH1cblxuICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbV2ViR1BVXSBHcHVEYXRhTWFuYWdlci5yZWxlYXNlKGlkPSR7aWR9KSwgZ3B1RGF0YUlkPSR7Y2FjaGVkRGF0YS5ncHVEYXRhLmlkfWApO1xuXG4gICAgdGhpcy5zdG9yYWdlQ2FjaGUuZGVsZXRlKGlkKTtcbiAgICB0aGlzLmJ1ZmZlcnNQZW5kaW5nLnB1c2goY2FjaGVkRGF0YS5ncHVEYXRhLmJ1ZmZlcik7XG4gICAgLy8gY2FjaGVkRGF0YS5ncHVEYXRhLmJ1ZmZlci5kZXN0cm95KCk7XG5cbiAgICBjb25zdCBkb3dubG9hZGluZ0RhdGEgPSB0aGlzLmRvd25sb2FkQ2FjaGUuZ2V0KGlkKTtcbiAgICBpZiAoZG93bmxvYWRpbmdEYXRhKSB7XG4gICAgICB0aGlzLmRvd25sb2FkQ2FjaGUuZGVsZXRlKGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2FjaGVkRGF0YS5vcmlnaW5hbFNpemU7XG4gIH1cblxuICBhc3luYyBkb3dubG9hZChpZDogR3B1RGF0YUlkKTogUHJvbWlzZTxBcnJheUJ1ZmZlckxpa2U+IHtcbiAgICBjb25zdCBkb3dubG9hZERhdGEgPSB0aGlzLmRvd25sb2FkQ2FjaGUuZ2V0KGlkKTtcbiAgICBpZiAoZG93bmxvYWREYXRhKSB7XG4gICAgICByZXR1cm4gZG93bmxvYWREYXRhLmRhdGE7XG4gICAgfVxuXG4gICAgY29uc3QgY2FjaGVkRGF0YSA9IHRoaXMuc3RvcmFnZUNhY2hlLmdldChpZCk7XG4gICAgaWYgKCFjYWNoZWREYXRhKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RhdGEgZG9lcyBub3QgZXhpc3QnKTtcbiAgICB9XG5cbiAgICBjb25zdCBjb21tYW5kRW5jb2RlciA9IHRoaXMuYmFja2VuZC5nZXRDb21tYW5kRW5jb2RlcigpO1xuICAgIHRoaXMuYmFja2VuZC5lbmRDb21wdXRlUGFzcygpO1xuICAgIGNvbnN0IGdwdVJlYWRCdWZmZXIgPSB0aGlzLmJhY2tlbmQuZGV2aWNlLmNyZWF0ZUJ1ZmZlcihcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgICAgICAge3NpemU6IGNhY2hlZERhdGEub3JpZ2luYWxTaXplLCB1c2FnZTogR1BVQnVmZmVyVXNhZ2UuQ09QWV9EU1QgfCBHUFVCdWZmZXJVc2FnZS5NQVBfUkVBRH0pO1xuICAgIGNvbW1hbmRFbmNvZGVyLmNvcHlCdWZmZXJUb0J1ZmZlcihcbiAgICAgICAgY2FjaGVkRGF0YS5ncHVEYXRhLmJ1ZmZlciAvKiBzb3VyY2UgYnVmZmVyICovLCAwIC8qIHNvdXJjZSBvZmZzZXQgKi8sIGdwdVJlYWRCdWZmZXIgLyogZGVzdGluYXRpb24gYnVmZmVyICovLFxuICAgICAgICAwIC8qIGRlc3RpbmF0aW9uIG9mZnNldCAqLywgY2FjaGVkRGF0YS5vcmlnaW5hbFNpemUgLyogc2l6ZSAqL1xuICAgICk7XG4gICAgdGhpcy5iYWNrZW5kLmZsdXNoKCk7XG5cbiAgICBjb25zdCByZWFkRGF0YVByb21pc2UgPSBuZXcgUHJvbWlzZTxBcnJheUJ1ZmZlcj4oKHJlc29sdmUpID0+IHtcbiAgICAgIGdwdVJlYWRCdWZmZXIubWFwQXN5bmMoR1BVTWFwTW9kZS5SRUFEKS50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc3QgZGF0YSA9IGdwdVJlYWRCdWZmZXIuZ2V0TWFwcGVkUmFuZ2UoKS5zbGljZSgwKTtcbiAgICAgICAgZ3B1UmVhZEJ1ZmZlci5kZXN0cm95KCk7XG4gICAgICAgIHJlc29sdmUoZGF0YSk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRoaXMuZG93bmxvYWRDYWNoZS5zZXQoaWQsIHtkYXRhOiByZWFkRGF0YVByb21pc2V9KTtcblxuICAgIHJldHVybiByZWFkRGF0YVByb21pc2U7XG4gIH1cblxuICByZWZyZXNoUGVuZGluZ0J1ZmZlcnMoKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBidWZmZXIgb2YgdGhpcy5idWZmZXJzRm9yVXBsb2FkaW5nUGVuZGluZykge1xuICAgICAgYnVmZmVyLmRlc3Ryb3koKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBidWZmZXIgb2YgdGhpcy5idWZmZXJzUGVuZGluZykge1xuICAgICAgYnVmZmVyLmRlc3Ryb3koKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGNyZWF0ZUdwdURhdGFNYW5hZ2VyID0gKC4uLmFyZ3M6IENvbnN0cnVjdG9yUGFyYW1ldGVyczx0eXBlb2YgR3B1RGF0YU1hbmFnZXJJbXBsPik6IEdwdURhdGFNYW5hZ2VyID0+XG4gICAgbmV3IEdwdURhdGFNYW5hZ2VySW1wbCguLi5hcmdzKTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQgKiBhcyBiaW5hcnlPcHMgZnJvbSAnLi9vcHMvYmluYXJ5LW9wJztcbmltcG9ydCB7Y29udiwgcGFyc2VDb252QXR0cmlidXRlc30gZnJvbSAnLi9vcHMvY29udic7XG5pbXBvcnQge2dlbW0sIHBhcnNlR2VtbUF0dHJpYnV0ZXN9IGZyb20gJy4vb3BzL2dlbW0nO1xuaW1wb3J0IHttYXRNdWx9IGZyb20gJy4vb3BzL21hdG11bCc7XG5pbXBvcnQgKiBhcyBwb29sIGZyb20gJy4vb3BzL3Bvb2wnO1xuaW1wb3J0IHtwYXJzZVRyYW5zcG9zZUF0dHJpYnV0ZXMsIHRyYW5zcG9zZX0gZnJvbSAnLi9vcHMvdHJhbnNwb3NlJztcbmltcG9ydCAqIGFzIHVuYXJ5T3BzIGZyb20gJy4vb3BzL3VuYXJ5LW9wJztcbmltcG9ydCB7Q29tcHV0ZUNvbnRleHR9IGZyb20gJy4vdHlwZXMnO1xuXG5leHBvcnQgdHlwZSBSdW5GdW5jdGlvbiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlPzogdW5rbm93bikgPT4gdm9pZDtcbmV4cG9ydCB0eXBlIFBhcnNlQXR0cmlidXRlRnVuY3Rpb24gPSAoYXR0cmlidXRlUmF3OiB1bmtub3duKSA9PiB1bmtub3duO1xuZXhwb3J0IHR5cGUgT3BlcmF0b3JJbXBsZW1lbnRhdGlvbiA9IFtSdW5GdW5jdGlvbl18W1J1bkZ1bmN0aW9uLCBQYXJzZUF0dHJpYnV0ZUZ1bmN0aW9uXTtcblxuZXhwb3J0IGNvbnN0IFdFQkdQVV9PUF9SRVNPTFZFX1JVTEVTOiBNYXA8c3RyaW5nLCBPcGVyYXRvckltcGxlbWVudGF0aW9uPiA9IG5ldyBNYXAoW1xuICBbJ0FicycsIFt1bmFyeU9wcy5hYnNdXSxcbiAgWydBY29zJywgW3VuYXJ5T3BzLmFjb3NdXSxcbiAgWydBY29zaCcsIFt1bmFyeU9wcy5hY29zaF1dLFxuICBbJ0FkZCcsIFtiaW5hcnlPcHMuYWRkXV0sXG4gIFsnQXNpbicsIFt1bmFyeU9wcy5hc2luXV0sXG4gIFsnQXNpbmgnLCBbdW5hcnlPcHMuYXNpbmhdXSxcbiAgWydBdGFuJywgW3VuYXJ5T3BzLmF0YW5dXSxcbiAgWydBdGFuaCcsIFt1bmFyeU9wcy5hdGFuaF1dLFxuICAvLyBUT0RPOiBzdXBwb3J0IG5ldyBhdHRyaWJ1dGVzIGZvciBBdmVyYWdlUG9vbC0xMFxuICBbJ0F2ZXJhZ2VQb29sJywgW3Bvb2wuYXZlcmFnZVBvb2wsIHBvb2wucGFyc2VBdmVyYWdlUG9vbEF0dHJpYnV0ZXNdXSxcbiAgWydDZWlsJywgW3VuYXJ5T3BzLmNlaWxdXSxcbiAgWydDbGlwVjEwJywgW3VuYXJ5T3BzLmNsaXBWMTBdXSxcbiAgWydDbGlwJywgW3VuYXJ5T3BzLmNsaXBdXSxcbiAgWydDb252JywgW2NvbnYsIHBhcnNlQ29udkF0dHJpYnV0ZXNdXSxcbiAgWydDb3MnLCBbdW5hcnlPcHMuY29zXV0sXG4gIFsnQ29zaCcsIFt1bmFyeU9wcy5jb3NoXV0sXG4gIFsnRGl2JywgW2JpbmFyeU9wcy5kaXZdXSxcbiAgWydFbHUnLCBbdW5hcnlPcHMuZWx1LCB1bmFyeU9wcy5wYXJzZUFscGhhQXR0cmlidXRlc11dLFxuICBbJ0VyZicsIFt1bmFyeU9wcy5lcmZdXSxcbiAgWydFeHAnLCBbdW5hcnlPcHMuZXhwXV0sXG4gIFsnRmxvb3InLCBbdW5hcnlPcHMuZmxvb3JdXSxcbiAgWydHZW1tJywgW2dlbW0sIHBhcnNlR2VtbUF0dHJpYnV0ZXNdXSxcbiAgWydHbG9iYWxBdmVyYWdlUG9vbCcsIFtwb29sLmdsb2JhbEF2ZXJhZ2VQb29sLCBwb29sLnBhcnNlR2xvYmFsQXZlcmFnZVBvb2xBdHRyaWJ1dGVzXV0sXG4gIFsnR2xvYmFsTWF4UG9vbCcsIFtwb29sLmdsb2JhbE1heFBvb2wsIHBvb2wucGFyc2VHbG9iYWxNYXhQb29sQXR0cmlidXRlc11dLFxuICBbJ0xlYWt5UmVsdScsIFt1bmFyeU9wcy5sZWFreVJlbHUsIHVuYXJ5T3BzLnBhcnNlQWxwaGFBdHRyaWJ1dGVzXV0sXG4gIFsnTWF0TXVsJywgW21hdE11bF1dLFxuICAvLyBUT0RPOiBzdXBwb3J0IG5ldyBhdHRyaWJ1dGVzIGZvciBNYXhQb29sLTggYW5kIE1heFBvb2wtMTBcbiAgWydNYXhQb29sJywgW3Bvb2wubWF4UG9vbCwgcG9vbC5wYXJzZU1heFBvb2xBdHRyaWJ1dGVzXV0sXG4gIFsnTXVsJywgW2JpbmFyeU9wcy5tdWxdXSxcbiAgWydOZWcnLCBbdW5hcnlPcHMubmVnXV0sXG4gIFsnUG93JywgW2JpbmFyeU9wcy5wb3ddXSxcbiAgWydSZWNpcHJvY2FsJywgW3VuYXJ5T3BzLnJlY2lwcm9jYWxdXSxcbiAgWydSZWx1JywgW3VuYXJ5T3BzLnJlbHVdXSxcbiAgWydTaWdtb2lkJywgW3VuYXJ5T3BzLnNpZ21vaWRdXSxcbiAgWydTaW4nLCBbdW5hcnlPcHMuc2luXV0sXG4gIFsnU2luaCcsIFt1bmFyeU9wcy5zaW5oXV0sXG4gIFsnU3FydCcsIFt1bmFyeU9wcy5zcXJ0XV0sXG4gIFsnU3ViJywgW2JpbmFyeU9wcy5zdWJdXSxcbiAgWydUYW4nLCBbdW5hcnlPcHMudGFuXV0sXG4gIFsnVGFuaCcsIFt1bmFyeU9wcy50YW5oXV0sXG4gIFsnVGhyZXNob2xkZWRSZWx1JywgW3VuYXJ5T3BzLnRocmVzaG9sZGVkUmVsdSwgdW5hcnlPcHMucGFyc2VBbHBoYUF0dHJpYnV0ZXNdXSxcbiAgWydUcmFuc3Bvc2UnLCBbdHJhbnNwb3NlLCBwYXJzZVRyYW5zcG9zZUF0dHJpYnV0ZXNdXSxcbl0pO1xuIiwiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IDIwMjEgR29vZ2xlIExMQy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAqL1xuXG4vLyBzYW1wbGVkIGZyb20gW0B0ZW5zb3JmbG93L3RmanNdIHRmanMtYmFja2VuZC13ZWJncHUvc3JjL2FjdGl2YXRpb25fdXRpbC50c1xuLy9cbi8vIG1vZGlmaWVkIHRvIGZpdCB0aGUgbmVlZHMgb2YgdGhlIHByb2plY3RcblxuZXhwb3J0IGRlY2xhcmUgdHlwZSBBY3RpdmF0aW9uID0gJ2xpbmVhcicgfCAncmVsdScgfCAncHJlbHUnIHwgJ2VsdScgfCAncmVsdTYnIHwgJ2xlYWt5cmVsdScgfCAnc2lnbW9pZCc7XG5cbmV4cG9ydCBjb25zdCB0eXBlU25pcHBldCA9IChjb21wb25lbnQ6IG51bWJlcikgPT4ge1xuICBzd2l0Y2ggKGNvbXBvbmVudCkge1xuICAgIGNhc2UgMTpcbiAgICAgIHJldHVybiAnZjMyJztcbiAgICBjYXNlIDI6XG4gICAgICByZXR1cm4gJ3ZlYzI8ZjMyPic7XG4gICAgY2FzZSAzOlxuICAgICAgcmV0dXJuICd2ZWMzPGYzMj4nO1xuICAgIGNhc2UgNDpcbiAgICAgIHJldHVybiAndmVjNDxmMzI+JztcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbXBvbmVudH0tY29tcG9uZW50IGlzIG5vdCBzdXBwb3J0ZWQuYCk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBhY3RpdmF0aW9uRm5TbmlwcGV0ID1cbiAgICAoYWN0aXZhdGlvbj86IEFjdGl2YXRpb24sIF9oYXNQcmVsdUFjdGl2YXRpb25XZWlnaHRzID0gZmFsc2UsIF9wYWNrZWQgPSBmYWxzZSwgX2Nvb3Jkc0xlbmd0aCA9IDMpOiBzdHJpbmcgPT4ge1xuICAgICAgaWYgKCFhY3RpdmF0aW9uKSB7XG4gICAgICAgIHJldHVybiAnJztcbiAgICAgIH1cblxuICAgICAgLy8gVE9ETzogYWRkIGltcGxlbWVudGF0aW9uc1xuICAgICAgcmV0dXJuICcnO1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBiaWFzQWN0aXZhdGlvblNuaXBwZXQgPSAoaGFzQmlhczogYm9vbGVhbiwgYWN0aXZhdGlvbj86IEFjdGl2YXRpb24pOiBzdHJpbmcgPT4gYFxuICAgICAgJHtoYXNCaWFzID8gJ3ZhbHVlID0gdmFsdWUgKyBnZXRCaWFzQnlPdXRwdXRDb29yZHMoY29vcmRzKTsnIDogJyd9XG4gICAgICAke2FjdGl2YXRpb24gPyAndmFsdWUgPSBhY3RpdmF0aW9uKHZhbHVlLCBjb29yZHMpOycgOiAnJ31cbiAgICAgIGA7XG4iLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbi8vIHNhbXBsZWQgZnJvbSBbQHRlbnNvcmZsb3cvdGZqc10gdGZqcy1iYWNrZW5kLXdlYmdwdS9zcmMvY29udjJkX21tX3dlYmdwdS50c1xuLy9cbi8vIG1vZGlmaWVkIHRvIGZpdCB0aGUgbmVlZHMgb2YgdGhlIHByb2plY3RcblxuaW1wb3J0IHtMT0dfREVCVUd9IGZyb20gJy4uLy4uLy4uL2xvZyc7XG5pbXBvcnQge1RlbnNvclZpZXd9IGZyb20gJy4uLy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1NoYXBlVXRpbH0gZnJvbSAnLi4vLi4vLi4vdXRpbCc7XG5pbXBvcnQge0dwdURhdGFUeXBlLCBQcm9ncmFtSW5mbywgUHJvZ3JhbU1ldGFkYXRhfSBmcm9tICcuLi8uLi90eXBlcyc7XG5pbXBvcnQge0NvbnZBdHRyaWJ1dGVzfSBmcm9tICcuLi9jb252JztcblxuaW1wb3J0IHtBY3RpdmF0aW9uLCBhY3RpdmF0aW9uRm5TbmlwcGV0LCBiaWFzQWN0aXZhdGlvblNuaXBwZXQsIHR5cGVTbmlwcGV0fSBmcm9tICcuL2FjdGl2YXRpb25fdXRpbCc7XG5pbXBvcnQge3V0aWxGdW5jdGlvbnN9IGZyb20gJy4vY29udl91dGlsJztcbmltcG9ydCB7bWFrZU1hdE11bFBhY2tlZFNvdXJjZSwgbWFrZU1hdE11bFBhY2tlZFZlYzRTb3VyY2V9IGZyb20gJy4vbWF0bXVsX3BhY2tlZF93ZWJncHUnO1xuXG5jb25zdCBjb252MmRDb21tb25TbmlwcGV0ID1cbiAgICAoaXNDaGFubmVsc0xhc3Q6IGJvb2xlYW4sIGZpdEFPdXRlcjogYm9vbGVhbiwgZml0Qk91dGVyOiBib29sZWFuLCBmaXRJbm5lcjogYm9vbGVhbiwgYWRkQmlhcyA9IGZhbHNlLFxuICAgICBhY3RpdmF0aW9uPzogQWN0aXZhdGlvbiwgaGFzUHJlbHVBY3RpdmF0aW9uV2VpZ2h0cyA9IGZhbHNlLCBpbm5lckVsZW1lbnRTaXplWCA9IDQsIGlubmVyRWxlbWVudFNpemVXID0gNCxcbiAgICAgaW5uZXJFbGVtZW50U2l6ZSA9IDQpOiBzdHJpbmcgPT4ge1xuICAgICAgY29uc3QgZ2V0WFNuaXBwZXQgPSAoaW5uZXJFbGVtZW50U2l6ZTogbnVtYmVyKSA9PiB7XG4gICAgICAgIHN3aXRjaCAoaW5uZXJFbGVtZW50U2l6ZSkge1xuICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgIHJldHVybiAncmVzRGF0YSA9IHhbeEluZGV4XTsnO1xuICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgIHJldHVybiAncmVzRGF0YSA9IHZlYzM8ZjMyPih4W3hJbmRleF0sIHhbeEluZGV4ICsgMV0sIHhbeEluZGV4ICsgMl0pOyc7XG4gICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgcmV0dXJuICdyZXNEYXRhID0geFt4SW5kZXggLyA0XTsnO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGlubmVyRWxlbWVudFNpemUgJHtpbm5lckVsZW1lbnRTaXplfSBpcyBub3Qgc3VwcG9ydGVkLmApO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgY29uc3QgZ2V0V1NuaXBwZXQgPSAoaW5uZXJFbGVtZW50U2l6ZTogbnVtYmVyKSA9PiB7XG4gICAgICAgIHN3aXRjaCAoaW5uZXJFbGVtZW50U2l6ZSkge1xuICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgIHJldHVybiAncmV0dXJuIHdbcm93ICogd1NoYXBlWzNdICsgY29sSW5dOyc7XG4gICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgcmV0dXJuICdyZXR1cm4gd1tyb3cgKiB3U2hhcGVbM10gLyA0ICsgY29sSW5dOyc7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgaW5uZXJFbGVtZW50U2l6ZSAke2lubmVyRWxlbWVudFNpemV9IGlzIG5vdCBzdXBwb3J0ZWQuYCk7XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICBjb25zdCBjb29yZEFTbmlwcGV0ID0gaXNDaGFubmVsc0xhc3QgPyBgXG4gICAgbGV0IGNvb3JkID0gdmVjNDxpMzI+KGJhdGNoLCB4Um93LCB4Q29sLCB4Q2gpO1xuICAgIGAgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYFxuICAgIGxldCBjb29yZCA9IHZlYzQ8aTMyPihiYXRjaCwgeENoLCB4Um93LCB4Q29sKTtcbiAgICBgO1xuXG4gICAgICBjb25zdCBjb29yZFJlc1NuaXBwZXQgPSBpc0NoYW5uZWxzTGFzdCA/IGBcbiAgICBsZXQgY29vcmRzID0gdmVjNDxpMzI+KFxuICAgICAgYmF0Y2gsXG4gICAgICByb3cgLyBvdXRXaWR0aCxcbiAgICAgIHJvdyAlIG91dFdpZHRoLFxuICAgICAgY29sKTtcbiAgICBgIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYFxuICAgIGxldCBjb29yZHMgPSB2ZWM0PGkzMj4oXG4gICAgICBiYXRjaCxcbiAgICAgIHJvdyxcbiAgICAgIGNvbCAvIG91dFdpZHRoLFxuICAgICAgY29sICUgb3V0V2lkdGgpO1xuICAgIGA7XG5cbiAgICAgIGNvbnN0IHhIZWlnaHQgPSBpc0NoYW5uZWxzTGFzdCA/ICd4U2hhcGVbMV0nIDogJ3hTaGFwZVsyXSc7XG4gICAgICBjb25zdCB4V2lkdGggPSBpc0NoYW5uZWxzTGFzdCA/ICd4U2hhcGVbMl0nIDogJ3hTaGFwZVszXSc7XG4gICAgICBjb25zdCByb3cgPSBpc0NoYW5uZWxzTGFzdCA/ICdyb3cnIDogJ2NvbCc7XG4gICAgICBjb25zdCBjb2wgPSBpc0NoYW5uZWxzTGFzdCA/ICdjb2wnIDogJ3Jvdyc7XG4gICAgICBjb25zdCByZWFkWFNuaXBwZXQgPSBgXG4gICAgbGV0IGluQ2hhbm5lbHMgPSB3U2hhcGVbMl07XG4gICAgbGV0IG91dFdpZHRoID0gJHtpc0NoYW5uZWxzTGFzdCA/ICdvdXRTaGFwZVsyXScgOiAnb3V0U2hhcGVbM10nfTtcbiAgICBsZXQgb3V0Um93ID0gJHtyb3d9IC8gb3V0V2lkdGg7XG4gICAgbGV0IG91dENvbCA9ICR7cm93fSAlIG91dFdpZHRoO1xuXG4gICAgbGV0IFdSb3cgPSAke2NvbH0gLyAoZmlsdGVyRGltc1sxXSAqIGluQ2hhbm5lbHMpO1xuICAgIGxldCBXQ29sID0gJHtjb2x9IC8gaW5DaGFubmVscyAlIGZpbHRlckRpbXNbMV07XG4gICAgbGV0IHhSb3cgPSBvdXRSb3cgKiBzdHJpZGVbMF0gKyBkaWxhdGlvblswXSAqIFdSb3cgLSBwYWRbMF07XG4gICAgbGV0IHhDb2wgPSBvdXRDb2wgKiBzdHJpZGVbMV0gKyBkaWxhdGlvblsxXSAqIFdDb2wgLSBwYWRbMV07XG4gICAgbGV0IHhDaCA9ICR7Y29sfSAlIGluQ2hhbm5lbHM7XG4gICAgdmFyIHJlc0RhdGEgPSAke3R5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemVYKX0oMC4wKTtcbiAgICAvLyBUaGUgYm91bmRzIGNoZWNraW5nIGlzIGFsd2F5cyBuZWVkZWQgc2luY2Ugd2UgdXNlIGl0IHRvIHBhZCB6ZXJvIGZvclxuICAgIC8vIHRoZSAnc2FtZScgcGFkZGluZyB0eXBlLlxuICAgIGlmICh4Um93ID49IDAgJiYgeFJvdyA8ICR7eEhlaWdodH0gJiYgeENvbCA+PSAwICYmIHhDb2wgPCAke3hXaWR0aH0pIHtcbiAgICAgICR7Y29vcmRBU25pcHBldH1cbiAgICAgIGxldCB4SW5kZXggPSBnZXRJbmRleEZyb21Db29yZHM0RChjb29yZCwgeFNoYXBlKTtcbiAgICAgICR7Z2V0WFNuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVgpfVxuICAgIH1cbiAgICByZXR1cm4gcmVzRGF0YTtgO1xuXG4gICAgICBjb25zdCBzYW1wbGVYID0gaXNDaGFubmVsc0xhc3QgPyAoZml0QU91dGVyICYmIGZpdElubmVyID8gYFxuICAgIGxldCBjb2wgPSBjb2xJbiAqICR7aW5uZXJFbGVtZW50U2l6ZVh9O1xuICAgICR7cmVhZFhTbmlwcGV0fWAgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBcbiAgICBsZXQgY29sID0gY29sSW4gKiAke2lubmVyRWxlbWVudFNpemVYfTtcbiAgICBpZiAocm93IDwgZGltQU91dGVyICYmIGNvbCA8IGRpbUlubmVyKSB7XG4gICAgICAke3JlYWRYU25pcHBldH1cbiAgICB9XG4gICAgcmV0dXJuICR7dHlwZVNuaXBwZXQoaW5uZXJFbGVtZW50U2l6ZVgpfSgwLjApO2ApIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChmaXRJbm5lciAmJiBmaXRCT3V0ZXIgPyBgXG4gICAgbGV0IGNvbCA9IGNvbEluICogJHtpbm5lckVsZW1lbnRTaXplWH07XG4gICAgJHtyZWFkWFNuaXBwZXR9YCA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYFxuICAgIGxldCBjb2wgPSBjb2xJbiAqICR7aW5uZXJFbGVtZW50U2l6ZVh9O1xuICAgIGlmIChyb3cgPCBkaW1Jbm5lciAmJiBjb2wgPCBkaW1CT3V0ZXIpIHtcbiAgICAgICR7cmVhZFhTbmlwcGV0fVxuICAgIH1cbiAgICByZXR1cm4gJHt0eXBlU25pcHBldChpbm5lckVsZW1lbnRTaXplWCl9KDAuMCk7YCk7XG5cbiAgICAgIGNvbnN0IHNhbXBsZVcgPSBgJHtnZXRXU25pcHBldChpbm5lckVsZW1lbnRTaXplVyl9YDtcblxuICAgICAgY29uc3QgcmVzVHlwZSA9IHR5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemUpO1xuICAgICAgY29uc3QgYVR5cGUgPSBpc0NoYW5uZWxzTGFzdCA/IHR5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemVYKSA6IHR5cGVTbmlwcGV0KGlubmVyRWxlbWVudFNpemVXKTtcbiAgICAgIGNvbnN0IGJUeXBlID0gaXNDaGFubmVsc0xhc3QgPyB0eXBlU25pcHBldChpbm5lckVsZW1lbnRTaXplVykgOiB0eXBlU25pcHBldChpbm5lckVsZW1lbnRTaXplWCk7XG4gICAgICBjb25zdCB1c2VyQ29kZSA9IGBcbiAgICAke2FjdGl2YXRpb25GblNuaXBwZXQoYWN0aXZhdGlvbiwgaGFzUHJlbHVBY3RpdmF0aW9uV2VpZ2h0cywgaW5uZXJFbGVtZW50U2l6ZSA9PT0gNCwgNCl9XG4gICAgZm4gbW1fcmVhZEEoYmF0Y2g6IGkzMiwgcm93IDogaTMyLCBjb2xJbiA6IGkzMikgLT4gJHthVHlwZX0ge1xuICAgICAgJHtpc0NoYW5uZWxzTGFzdCA/IHNhbXBsZVggOiBzYW1wbGVXfVxuICAgIH1cblxuICAgIGZuIG1tX3JlYWRCKGJhdGNoOiBpMzIsIHJvdyA6IGkzMiwgY29sSW4gOiBpMzIpIC0+ICR7YlR5cGV9IHtcbiAgICAgICR7aXNDaGFubmVsc0xhc3QgPyBzYW1wbGVXIDogc2FtcGxlWH1cbiAgICB9XG5cbiAgICBmbiBtbV93cml0ZShiYXRjaDogaTMyLCByb3cgOiBpMzIsIGNvbEluIDogaTMyLCB2YWx1ZUluIDogJHtyZXNUeXBlfSkge1xuICAgICAgbGV0IGNvbCA9IGNvbEluICogJHtpbm5lckVsZW1lbnRTaXplfTtcbiAgICAgIGlmIChyb3cgPCBkaW1BT3V0ZXIgJiYgY29sIDwgZGltQk91dGVyKVxuICAgICAge1xuICAgICAgdmFyIHZhbHVlID0gdmFsdWVJbjtcbiAgICAgIGxldCBvdXRXaWR0aCA9ICR7aXNDaGFubmVsc0xhc3QgPyAnb3V0U2hhcGVbMl0nIDogJ291dFNoYXBlWzNdJ307XG4gICAgICAke2Nvb3JkUmVzU25pcHBldH1cbiAgICAgICR7Ymlhc0FjdGl2YXRpb25TbmlwcGV0KGFkZEJpYXMsIGFjdGl2YXRpb24pfVxuICAgICAgc2V0T3V0cHV0QXRDb29yZHMoY29vcmRzWzBdLCBjb29yZHNbMV0sIGNvb3Jkc1syXSwgY29vcmRzWzNdLCB2YWx1ZSk7XG4gICAgICB9XG4gICAgfWA7XG4gICAgICByZXR1cm4gdXNlckNvZGU7XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZUNvbnYyRE1hdE11bFByb2dyYW1JbmZvID1cbiAgICAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIG1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEsIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzLFxuICAgICBvdXRwdXRTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIGRpbUFPdXRlcjogbnVtYmVyLCBkaW1CT3V0ZXI6IG51bWJlciwgZGltSW5uZXI6IG51bWJlciwgaGFzQmlhczogYm9vbGVhbixcbiAgICAgc2VxdWVudGlhbEFjY2Vzc0J5VGhyZWFkczogYm9vbGVhbik6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IGlzQ2hhbm5lbHNMYXN0ID0gYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJztcbiAgICAgIGNvbnN0IGluQ2hhbm5lbHMgPSBpc0NoYW5uZWxzTGFzdCA/IGlucHV0c1swXS5kaW1zWzNdIDogaW5wdXRzWzBdLmRpbXNbMV07XG4gICAgICBjb25zdCBiYXRjaFNpemUgPSBvdXRwdXRTaGFwZVswXTtcbiAgICAgIGNvbnN0IG91dFdpZHRoID0gaXNDaGFubmVsc0xhc3QgPyBvdXRwdXRTaGFwZVsyXSA6IG91dHB1dFNoYXBlWzNdO1xuICAgICAgY29uc3Qgb3V0SGVpZ2h0ID0gaXNDaGFubmVsc0xhc3QgPyBvdXRwdXRTaGFwZVsxXSA6IG91dHB1dFNoYXBlWzJdO1xuICAgICAgY29uc3Qgb3V0Q2hhbm5lbHMgPSBpc0NoYW5uZWxzTGFzdCA/IG91dHB1dFNoYXBlWzNdIDogb3V0cHV0U2hhcGVbMV07XG4gICAgICBjb25zdCBpc1ZlYzQgPSAoKChpbkNoYW5uZWxzICUgNCA9PT0gMCB8fCBpbkNoYW5uZWxzICUgMyA9PT0gMCkgJiYgaXNDaGFubmVsc0xhc3QpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgKG91dFdpZHRoICUgNCA9PT0gMCAmJiAhaXNDaGFubmVsc0xhc3QpKSAmJlxuICAgICAgICAgIG91dENoYW5uZWxzICUgNCA9PT0gMDtcblxuICAgICAgLy8gVE9ETzogZmluZSB0dW5lIHNpemVcbiAgICAgIGNvbnN0IGRpc3BhdGNoWCA9IGlzQ2hhbm5lbHNMYXN0ID8gb3V0Q2hhbm5lbHMgOiBvdXRXaWR0aCAqIG91dEhlaWdodDtcbiAgICAgIGNvbnN0IGRpc3BhdGNoWSA9IGlzQ2hhbm5lbHNMYXN0ID8gb3V0V2lkdGggKiBvdXRIZWlnaHQgOiBvdXRDaGFubmVscztcbiAgICAgIGNvbnN0IHdvcmtHcm91cFNpemU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9XG4gICAgICAgICAgaXNWZWM0ID8gWzgsIDgsIDFdIDogW2Rpc3BhdGNoWCA8PSA0ID8gNCA6IDE2LCBkaXNwYXRjaFggPiA0ICYmIGRpc3BhdGNoWSA8PSA0ID8gNCA6IDE2LCAxXTtcbiAgICAgIGNvbnN0IGVsZW1lbnRzUGVyVGhyZWFkID1cbiAgICAgICAgICBpc1ZlYzQgPyBbNCwgNCwgMV0gOiBbZGlzcGF0Y2hYIDw9IDQgPyAxIDogMiwgZGlzcGF0Y2hYID4gNCAmJiBkaXNwYXRjaFkgPD0gNCA/IDEgOiAyLCAxXTtcbiAgICAgIGNvbnN0IGRpc3BhdGNoID0gW1xuICAgICAgICBNYXRoLmNlaWwoZGlzcGF0Y2hYIC8gd29ya0dyb3VwU2l6ZVswXSAvIGVsZW1lbnRzUGVyVGhyZWFkWzBdKSxcbiAgICAgICAgTWF0aC5jZWlsKGRpc3BhdGNoWSAvIHdvcmtHcm91cFNpemVbMV0gLyBlbGVtZW50c1BlclRocmVhZFsxXSksXG4gICAgICAgIE1hdGguY2VpbChiYXRjaFNpemUgLyB3b3JrR3JvdXBTaXplWzJdIC8gZWxlbWVudHNQZXJUaHJlYWRbMV0pXG4gICAgICBdO1xuXG4gICAgICBMT0dfREVCVUcoJ3ZlcmJvc2UnLCAoKSA9PiBgW2NvbnYyZF9tbV93ZWJncHVdIGRpc3BhdGNoID0gJHtkaXNwYXRjaH1gKTtcblxuICAgICAgY29uc3QgaW5uZXJFbGVtZW50U2l6ZSA9IGlzVmVjNCA/IChpc0NoYW5uZWxzTGFzdCAmJiBpbkNoYW5uZWxzICUgNCAhPT0gMCA/IDMgOiA0KSA6IGVsZW1lbnRzUGVyVGhyZWFkWzBdO1xuXG4gICAgICBjb25zdCB0aWxlQU91dGVyID0gd29ya0dyb3VwU2l6ZVsxXSAqIGVsZW1lbnRzUGVyVGhyZWFkWzFdO1xuICAgICAgY29uc3QgdGlsZUJPdXRlciA9IHdvcmtHcm91cFNpemVbMF0gKiBlbGVtZW50c1BlclRocmVhZFswXTtcbiAgICAgIGNvbnN0IHRpbGVJbm5lciA9IE1hdGgubWF4KHdvcmtHcm91cFNpemVbMF0gKiBpbm5lckVsZW1lbnRTaXplLCB3b3JrR3JvdXBTaXplWzFdKTtcblxuICAgICAgY29uc3QgZml0QU91dGVyID0gZGltQU91dGVyICUgdGlsZUFPdXRlciA9PT0gMDtcbiAgICAgIGNvbnN0IGZpdEJPdXRlciA9IGRpbUJPdXRlciAlIHRpbGVCT3V0ZXIgPT09IDA7XG4gICAgICBjb25zdCBmaXRJbm5lciA9IGRpbUlubmVyICUgdGlsZUlubmVyID09PSAwO1xuXG4gICAgICBjb25zdCBlbGVtZW50c1NpemUgPSBpc1ZlYzQgPyBbaW5uZXJFbGVtZW50U2l6ZSwgNCwgNF0gOiBbMSwgMSwgMV07XG5cbiAgICAgIGNvbnN0IGRlY2xhcmVJbnB1dHMgPSBbXG4gICAgICAgIGBAZ3JvdXAoMCkgQGJpbmRpbmcoMCkgdmFyPHN0b3JhZ2UsIHJlYWQ+IHg6IGFycmF5PCR7aXNWZWM0ICYmIGlubmVyRWxlbWVudFNpemUgPT09IDQgPyAndmVjNDxmMzI+JyA6ICdmMzInfT47YCxcbiAgICAgICAgYEBncm91cCgwKSBAYmluZGluZygxKSB2YXI8c3RvcmFnZSwgcmVhZD4gdzogYXJyYXk8JHtpc1ZlYzQgPyAndmVjNDxmMzI+JyA6ICdmMzInfT47YFxuICAgICAgXTtcbiAgICAgIGxldCBkZWNsYXJlRnVuY3Rpb25zID0gYFxuICAgICAgZm4gc2V0T3V0cHV0QXRJbmRleChmbGF0SW5kZXggOiBpMzIsIHZhbHVlIDogJHtpc1ZlYzQgPyAndmVjNDxmMzI+JyA6ICdmMzInfSkge1xuICAgICAgICByZXN1bHRbZmxhdEluZGV4XSA9ICR7aXNWZWM0ID8gJ3ZlYzQ8ZjMyPicgOiAnZjMyJ30odmFsdWUpO1xuICAgICAgfVxuICAgICAgZm4gc2V0T3V0cHV0QXRDb29yZHMoZDAgOiBpMzIsIGQxIDogaTMyLCBkMiA6IGkzMiwgZDMgOiBpMzIsIHZhbHVlIDogJHtpc1ZlYzQgPyAndmVjNDxmMzI+JyA6ICdmMzInfSkge1xuICAgICAgICBsZXQgZmxhdEluZGV4ID0gZ2V0T3V0cHV0SW5kZXhGcm9tQ29vcmRzKHZlYzQ8aTMyPihkMCwgZDEsIGQyLCBkMykpO1xuICAgICAgICBzZXRPdXRwdXRBdEluZGV4KGZsYXRJbmRleCAke2lzVmVjNCA/ICcvIDQnIDogJyd9LCB2YWx1ZSk7XG4gICAgICB9YDtcbiAgICAgIGlmIChoYXNCaWFzKSB7XG4gICAgICAgIGRlY2xhcmVJbnB1dHMucHVzaChgQGdyb3VwKDApIEBiaW5kaW5nKDIpIHZhcjxzdG9yYWdlLCByZWFkPiBiaWFzOiBhcnJheTwke2lzVmVjNCA/ICd2ZWM0PGYzMj4nIDogJ2YzMid9PjtgKTtcbiAgICAgICAgZGVjbGFyZUZ1bmN0aW9ucyArPSBgXG4gICAgICAgIGZuIGdldEJpYXNCeU91dHB1dENvb3Jkcyhjb29yZHMgOiB2ZWM0PGkzMj4pIC0+ICR7aXNWZWM0ID8gJ3ZlYzQ8ZjMyPicgOiAnZjMyJ30ge1xuICAgICAgICAgIHJldHVybiBiaWFzW2Nvb3Jkcy4ke2lzQ2hhbm5lbHNMYXN0ID8gJ3cnIDogJ3knfSR7aXNWZWM0ID8gJy8gNCcgOiAnJ31dO1xuICAgICAgICB9YDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgIG91dHB1dHM6IFt7ZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUsIGdwdURhdGFUeXBlOiBHcHVEYXRhVHlwZS5kZWZhdWx0fV0sXG4gICAgICAgIGRpc3BhdGNoR3JvdXA6ICgpID0+ICh7eDogZGlzcGF0Y2hbMF0sIHk6IGRpc3BhdGNoWzFdLCB6OiBkaXNwYXRjaFsyXX0pLFxuICAgICAgICBnZXRTaGFkZXJTb3VyY2U6ICgpID0+IGBcbiAgICAgICAgJHt1dGlsRnVuY3Rpb25zfVxuICAgICAgICAvL3N0cnVjdCBVbmlmb3JtcyB7IHhTaGFwZSA6IHZlYzQ8aTMyPiwgd1NoYXBlIDogdmVjNDxpMzI+LCBvdXRTaGFwZSA6IHZlYzQ8aTMyPixcbiAgICAgICAgLy8gIG91dFNoYXBlU3RyaWRlczogdmVjMzxpMzI+LCBmaWx0ZXJEaW1zIDogdmVjMjxpMzI+LCBwYWQgOiB2ZWMyPGkzMj4sIHN0cmlkZSA6IHZlYzI8aTMyPixcbiAgICAgICAgLy8gIGRpbGF0aW9uIDogdmVjMjxpMzI+LCBkaW1BT3V0ZXIgOiBpMzIsIGRpbUJPdXRlciA6IGkzMiwgZGltSW5uZXIgOiBpMzIgfTtcbiAgICAgICAgJHtkZWNsYXJlSW5wdXRzLmpvaW4oJycpfVxuICAgICAgICBAZ3JvdXAoMCkgQGJpbmRpbmcoJHtkZWNsYXJlSW5wdXRzLmxlbmd0aH0pIHZhcjxzdG9yYWdlLCByZWFkX3dyaXRlPiByZXN1bHQ6IGFycmF5PCR7XG4gICAgICAgICAgICBpc1ZlYzQgPyAndmVjNDxmMzI+JyA6ICdmMzInfT47XG4gICAgICAgIC8vQGdyb3VwKDApIEBiaW5kaW5nKCR7ZGVjbGFyZUlucHV0cy5sZW5ndGggKyAxfSkgdmFyPHVuaWZvcm0+IHVuaWZvcm1zOiBVbmlmb3JtcztcblxuICAgICAgICBjb25zdCB4U2hhcGUgOiB2ZWM0PGkzMj4gPSB2ZWM0PGkzMj4oJHtpbnB1dHNbMF0uZGltcy5qb2luKCcsJyl9KTtcbiAgICAgICAgY29uc3Qgd1NoYXBlIDogdmVjNDxpMzI+ID0gdmVjNDxpMzI+KCR7aW5wdXRzWzFdLmRpbXMuam9pbignLCcpfSk7XG4gICAgICAgIGNvbnN0IG91dFNoYXBlIDogdmVjNDxpMzI+ID0gdmVjNDxpMzI+KCR7b3V0cHV0U2hhcGUuam9pbignLCcpfSk7XG4gICAgICAgIGNvbnN0IG91dFNoYXBlU3RyaWRlcyA6IHZlYzM8aTMyPiA9IHZlYzM8aTMyPigke1NoYXBlVXRpbC5jb21wdXRlU3RyaWRlcyhvdXRwdXRTaGFwZSkuc2xpY2UoMCwgMykuam9pbignLCcpfSk7XG4gICAgICAgIGNvbnN0IGZpbHRlckRpbXMgOiB2ZWMyPGkzMj4gPSB2ZWMyPGkzMj4oJHthdHRyaWJ1dGVzLmtlcm5lbFNoYXBlWzBdfSwgJHthdHRyaWJ1dGVzLmtlcm5lbFNoYXBlWzFdfSk7XG4gICAgICAgIGNvbnN0IHBhZCA6IHZlYzI8aTMyPiA9IHZlYzI8aTMyPigke2F0dHJpYnV0ZXMucGFkc1swXX0sICR7YXR0cmlidXRlcy5wYWRzWzFdfSk7XG4gICAgICAgIGNvbnN0IHN0cmlkZSA6IHZlYzI8aTMyPiA9IHZlYzI8aTMyPigke2F0dHJpYnV0ZXMuc3RyaWRlc1swXX0sICR7YXR0cmlidXRlcy5zdHJpZGVzWzFdfSk7XG4gICAgICAgIGNvbnN0IGRpbGF0aW9uIDogdmVjMjxpMzI+ID0gdmVjMjxpMzI+KCR7YXR0cmlidXRlcy5kaWxhdGlvbnNbMF19LCAke2F0dHJpYnV0ZXMuZGlsYXRpb25zWzFdfSk7XG4gICAgICAgIGNvbnN0IGRpbUFPdXRlciA6IGkzMiA9ICR7ZGltQU91dGVyfTtcbiAgICAgICAgY29uc3QgZGltQk91dGVyIDogaTMyID0gJHtkaW1CT3V0ZXJ9O1xuICAgICAgICBjb25zdCBkaW1Jbm5lciA6IGkzMiA9ICR7ZGltSW5uZXJ9O1xuICAgICAgICAke2RlY2xhcmVGdW5jdGlvbnN9XG4gICAgICAgICR7XG4gICAgICAgICAgICBjb252MmRDb21tb25TbmlwcGV0KFxuICAgICAgICAgICAgICAgIGlzQ2hhbm5lbHNMYXN0LCBmaXRBT3V0ZXIsIGZpdEJPdXRlciwgZml0SW5uZXIsIGhhc0JpYXMsIHVuZGVmaW5lZCwgZmFsc2UsIGVsZW1lbnRzU2l6ZVswXSxcbiAgICAgICAgICAgICAgICBlbGVtZW50c1NpemVbMV0sIGVsZW1lbnRzU2l6ZVsyXSl9XG4gICAgICAgICAgICAke1xuICAgICAgICAgICAgaXNWZWM0ID8gbWFrZU1hdE11bFBhY2tlZFZlYzRTb3VyY2UoZWxlbWVudHNQZXJUaHJlYWQsIHdvcmtHcm91cFNpemUsICFpc0NoYW5uZWxzTGFzdCwgdGlsZUlubmVyKSA6XG4gICAgICAgICAgICAgICAgICAgICBtYWtlTWF0TXVsUGFja2VkU291cmNlKFxuICAgICAgICAgICAgICAgICAgICAgICAgIGVsZW1lbnRzUGVyVGhyZWFkLCB3b3JrR3JvdXBTaXplLCAhaXNDaGFubmVsc0xhc3QsIHRpbGVJbm5lciwgZmFsc2UsIHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICBzZXF1ZW50aWFsQWNjZXNzQnlUaHJlYWRzKX1gXG4gICAgICB9O1xuICAgIH07XG4iLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAyMCBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbi8vIHNhbXBsZWQgZnJvbSBbQHRlbnNvcmZsb3cvdGZqc10gdGZqcy1jb3JlL3NyYy9vcHMvY29udl91dGlsLnRzXG4vL1xuLy8gbW9kaWZpZWQgdG8gZml0IHRoZSBuZWVkcyBvZiB0aGUgcHJvamVjdFxuXG5leHBvcnQgY29uc3QgdXRpbEZ1bmN0aW9ucyA9IGBcbmZuIGdldEluZGV4RnJvbUNvb3JkczREKGNvb3JkcyA6IHZlYzQ8aTMyPiwgc2hhcGUgOiB2ZWM0PGkzMj4pIC0+IGkzMiB7XG4gIHJldHVybiBkb3QoY29vcmRzLCB2ZWM0PGkzMj4oXG4gICAgICBzaGFwZS55ICogc2hhcGUueiAqIHNoYXBlLncsIHNoYXBlLnogKiBzaGFwZS53LCBzaGFwZS53LCAxKSk7XG59XG5mbiBnZXRPdXRwdXRJbmRleEZyb21Db29yZHMoY29vcmRzIDogdmVjNDxpMzI+KSAtPiBpMzIge1xuICByZXR1cm4gZG90KGNvb3JkcywgdmVjNDxpMzI+KFxuICAgIG91dFNoYXBlU3RyaWRlcy54LCBvdXRTaGFwZVN0cmlkZXMueSwgb3V0U2hhcGVTdHJpZGVzLnosIDEpKTtcbn1cbmA7XG4iLCIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxOSBHb29nbGUgTExDLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICovXG5cbi8vIHNhbXBsZWQgZnJvbSBbQHRlbnNvcmZsb3cvdGZqc10gdGZqcy1iYWNrZW5kLXdlYmdwdS9zcmMvbWF0bXVsX3BhY2tlZF93ZWJncHUudHNcbi8vXG4vLyBtb2RpZmllZCB0byBmaXQgdGhlIG5lZWRzIG9mIHRoZSBwcm9qZWN0XG5cbmNvbnN0IHdyaXRlRGF0YVRvU3ViQVZlYzRTbmlwcGV0ID0gKHRyYW5zcG9zZTogYm9vbGVhbikgPT4ge1xuICBpZiAodHJhbnNwb3NlKSB7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgbW1fQXN1YltpbnB1dFJvd11baW5wdXRDb2xdID0gbW1fcmVhZEEoYmF0Y2gsXG4gICAgICAgICAga1N0YXJ0ICsgaW5wdXRSb3csXG4gICAgICAgICAgZ2xvYmFsUm93U3RhcnQgLyBpbm5lckVsZW1lbnRTaXplICsgaW5wdXRDb2wpO1xuICAgICAgICBgO1xuXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgbW1fQXN1YltpbnB1dFJvd11baW5wdXRDb2xdID0gbW1fcmVhZEEoYmF0Y2gsXG4gICAgICAgICAgZ2xvYmFsUm93ICsgaW5uZXJSb3csXG4gICAgICAgICAga1N0YXJ0IC8gaW5uZXJFbGVtZW50U2l6ZSArIGlucHV0Q29sKTtcbiAgICAgICAgYDtcbiAgfVxufTtcblxuY29uc3QgY2FsY3VsYXRlUmVzdWx0U25pcHBldCA9ICh0cmFuc3Bvc2VBOiBib29sZWFuLCBpbm5lckVsZW1lbnRTaXplOiBudW1iZXIpID0+IHtcbiAgaWYgKHRyYW5zcG9zZUEpIHtcbiAgICByZXR1cm4gYFxuICAgICAgICBsZXQgQUNhY2hlZDAgPSBtbV9Bc3ViW2sgKiBpbm5lckVsZW1lbnRTaXplXVtsb2NhbFJvd107XG4gICAgICAgIGxldCBBQ2FjaGVkMSA9IG1tX0FzdWJbayAqIGlubmVyRWxlbWVudFNpemUgKyAxXVtsb2NhbFJvd107XG4gICAgICAgIGxldCBBQ2FjaGVkMiA9IG1tX0FzdWJbayAqIGlubmVyRWxlbWVudFNpemUgKyAyXVtsb2NhbFJvd107XG4gICAgICAgICR7aW5uZXJFbGVtZW50U2l6ZSA9PT0gMyA/ICcnIDogJ2xldCBBQ2FjaGVkMyA9IG1tX0FzdWJbayAqIGlubmVyRWxlbWVudFNpemUgKyAzXVtsb2NhbFJvd107J31cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb3dQZXJUaHJlYWQ7IGkgPSBpICsgMSkge1xuICAgICAgICAgIGFjY1tpXSA9IEJDYWNoZWQwICogQUNhY2hlZDBbaV0gKyBhY2NbaV07XG4gICAgICAgICAgYWNjW2ldID0gQkNhY2hlZDEgKiBBQ2FjaGVkMVtpXSArIGFjY1tpXTtcbiAgICAgICAgICBhY2NbaV0gPSBCQ2FjaGVkMiAqIEFDYWNoZWQyW2ldICsgYWNjW2ldO1xuICAgICAgICAgICR7aW5uZXJFbGVtZW50U2l6ZSA9PT0gMyA/ICcnIDogJ2FjY1tpXSA9IEJDYWNoZWQzICogQUNhY2hlZDNbaV0gKyBhY2NbaV07J31cbiAgICAgICAgfWA7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByb3dQZXJUaHJlYWQ7IGkgPSBpICsgMSkge1xuICAgICAgICAgIGxldCBBQ2FjaGVkID0gbW1fQXN1Ylt0aWxlUm93ICsgaV1ba107XG4gICAgICAgICAgYWNjW2ldID0gQkNhY2hlZDAgKiBBQ2FjaGVkLnggKyBhY2NbaV07XG4gICAgICAgICAgYWNjW2ldID0gQkNhY2hlZDEgKiBBQ2FjaGVkLnkgKyBhY2NbaV07XG4gICAgICAgICAgYWNjW2ldID0gQkNhY2hlZDIgKiBBQ2FjaGVkLnogKyBhY2NbaV07XG4gICAgICAgICAgJHtpbm5lckVsZW1lbnRTaXplID09PSAzID8gJycgOiAnYWNjW2ldID0gQkNhY2hlZDMgKiBBQ2FjaGVkLncgKyBhY2NbaV07J31cbiAgICAgICAgfWA7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBtYWtlTWF0TXVsUGFja2VkVmVjNFNvdXJjZSA9XG4gICAgKHdvcmtQZXJUaHJlYWQ6IG51bWJlcltdLCB3b3JrZ3JvdXBTaXplOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sIHRyYW5zcG9zZUEgPSBmYWxzZSwgdGlsZUlubmVyID0gMzIsXG4gICAgIHNwbGl0SyA9IGZhbHNlLCBzcGxpdGVkRGltSW5uZXIgPSAzMiwgaXNWZWN0b3JBID0gZmFsc2UpOiBzdHJpbmcgPT4ge1xuICAgICAgY29uc3QgdGlsZUFPdXRlciA9IHdvcmtncm91cFNpemVbMV0gKiB3b3JrUGVyVGhyZWFkWzFdO1xuICAgICAgY29uc3QgdGlsZUJPdXRlciA9IHdvcmtncm91cFNpemVbMF0gKiB3b3JrUGVyVGhyZWFkWzBdO1xuICAgICAgY29uc3QgdGlsZUFXaWR0aCA9IHRyYW5zcG9zZUEgPyB0aWxlQU91dGVyIDogdGlsZUlubmVyO1xuICAgICAgY29uc3QgdGlsZUFIaWdodCA9IHRyYW5zcG9zZUEgPyB0aWxlSW5uZXIgOiB0aWxlQU91dGVyO1xuICAgICAgY29uc3QgaW5uZXJFbGVtZW50U2l6ZSA9IHRpbGVBV2lkdGggLyB3b3JrZ3JvdXBTaXplWzBdO1xuICAgICAgY29uc3Qgcm93UGVyVGhyZWFkQiA9IHRpbGVJbm5lciAvIHdvcmtncm91cFNpemVbMV07XG5cbiAgICAgIGlmICghKCgodHJhbnNwb3NlQSAmJiBpbm5lckVsZW1lbnRTaXplID09PSA0ICYmIHdvcmtQZXJUaHJlYWRbMV0gPT09IDQpIHx8XG4gICAgICAgICAgICAgKCF0cmFuc3Bvc2VBICYmIChpbm5lckVsZW1lbnRTaXplID09PSAzIHx8IGlubmVyRWxlbWVudFNpemUgPT09IDQpKSkgJiZcbiAgICAgICAgICAgIHRpbGVBV2lkdGggJSB3b3JrZ3JvdXBTaXplWzBdID09PSAwICYmIHRpbGVJbm5lciAlIHdvcmtncm91cFNpemVbMV0gPT09IDAgJiYgd29ya1BlclRocmVhZFswXSA9PT0gNCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJZiB0cmFuc3Bvc2VBICR7dHJhbnNwb3NlQX0gaXMgdHJ1ZSwgaW5uZXJFbGVtZW50U2l6ZSAke1xuICAgICAgICAgICAgaW5uZXJFbGVtZW50U2l6ZX0gYW5kIHdvcmtQZXJUaHJlYWRbMV0gJHt3b3JrUGVyVGhyZWFkWzFdfSBtdXN0IGJlIDQuXG4gICAgICBPdGhlcndpc2UsIGlubmVyRWxlbWVudFNpemUgJHtpbm5lckVsZW1lbnRTaXplfSBtdXN0IGJlIDMgb3IgNC5cbiAgdGlsZUFXaWR0aCAke3RpbGVBV2lkdGh9IG11c3QgYmUgZGl2aXNpYmxlIGJ5IHdvcmtncm91cFNpemVbMF0ke3dvcmtncm91cFNpemVbMF19LiB0aWxlSW5uZXIgJHtcbiAgICAgICAgICAgIHRpbGVJbm5lcn0gbXVzdCBiZSBkaXZpc2libGUgYnkgd29ya2dyb3VwU2l6ZVsxXSAke3dvcmtncm91cFNpemVbMV19LiBjb2xQZXJUaHJlYWQgJHtcbiAgICAgICAgICAgIHdvcmtQZXJUaHJlYWRbMF19IG11c3QgYmUgNC5gKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBgXG52YXI8d29ya2dyb3VwPiBtbV9Bc3ViIDogYXJyYXk8YXJyYXk8dmVjJHtpbm5lckVsZW1lbnRTaXplfTxmMzI+LCAke3RpbGVBV2lkdGggLyBpbm5lckVsZW1lbnRTaXplfT4sICR7dGlsZUFIaWdodH0+O1xudmFyPHdvcmtncm91cD4gbW1fQnN1YiA6IGFycmF5PGFycmF5PHZlYzQ8ZjMyPiwgJHt0aWxlQk91dGVyIC8gd29ya1BlclRocmVhZFswXX0+LCAke3RpbGVJbm5lcn0+O1xuXG5jb25zdCByb3dQZXJUaHJlYWQgPSAke3dvcmtQZXJUaHJlYWRbMV19O1xuY29uc3QgY29sUGVyVGhyZWFkID0gJHt3b3JrUGVyVGhyZWFkWzBdfTtcbmNvbnN0IGlubmVyRWxlbWVudFNpemUgPSAke2lubmVyRWxlbWVudFNpemV9O1xuY29uc3QgdGlsZUlubmVyID0gJHt0aWxlSW5uZXJ9O1xuXG5AY29tcHV0ZSBAd29ya2dyb3VwX3NpemUoJHt3b3JrZ3JvdXBTaXplWzBdfSwgJHt3b3JrZ3JvdXBTaXplWzFdfSwgJHt3b3JrZ3JvdXBTaXplWzJdfSlcbmZuIG1haW4oQGJ1aWx0aW4obG9jYWxfaW52b2NhdGlvbl9pZCkgbG9jYWxJZCA6IHZlYzM8dTMyPixcbiAgICAgICAgQGJ1aWx0aW4oZ2xvYmFsX2ludm9jYXRpb25faWQpIGdsb2JhbElkIDogdmVjMzx1MzI+LFxuICAgICAgICBAYnVpbHRpbih3b3JrZ3JvdXBfaWQpIHdvcmtncm91cElkIDogdmVjMzx1MzI+KSB7XG4gIGxldCBsb2NhbFJvdyA9IGkzMihsb2NhbElkLnkpO1xuICBsZXQgdGlsZVJvdyA9ICR7aXNWZWN0b3JBID8gJzAnIDogJ2xvY2FsUm93ICogcm93UGVyVGhyZWFkJ307XG4gIGxldCB0aWxlQ29sID0gaTMyKGxvY2FsSWQueCk7XG5cbiAgbGV0IGdsb2JhbFJvdyA9ICR7aXNWZWN0b3JBID8gJzAnIDogJ2kzMihnbG9iYWxJZC55KSAqIHJvd1BlclRocmVhZCd9O1xuICBsZXQgZ2xvYmFsQ29sID0gaTMyKGdsb2JhbElkLngpO1xuICBsZXQgYmF0Y2ggPSAke3NwbGl0SyA/ICcwJyA6ICdpMzIoZ2xvYmFsSWQueiknfTtcbiAgbGV0IGdsb2JhbFJvd1N0YXJ0ID0gaTMyKHdvcmtncm91cElkLnkpICogJHt0aWxlQU91dGVyfTtcblxuICBsZXQgbnVtVGlsZXMgPSAke3NwbGl0SyA/IGAke01hdGguY2VpbChzcGxpdGVkRGltSW5uZXIgLyB0aWxlSW5uZXIpfWAgOiAnKGRpbUlubmVyIC0gMSkgLyB0aWxlSW5uZXIgKyAxJ307XG4gIHZhciBrU3RhcnQgPSAke3NwbGl0SyA/IGBpMzIoZ2xvYmFsSWQueikgKiAke3NwbGl0ZWREaW1Jbm5lcn1gIDogJzAnfTtcblxuICB2YXIgYWNjOiBhcnJheTx2ZWM0PGYzMj4sIHJvd1BlclRocmVhZD47XG5cbiAgLy8gTG9vcCBvdmVyIHNoYXJlZCBkaW1lbnNpb24uXG4gIGxldCB0aWxlUm93QiA9IGxvY2FsUm93ICogJHtyb3dQZXJUaHJlYWRCfTtcbiAgZm9yICh2YXIgdCA9IDA7IHQgPCBudW1UaWxlczsgdCA9IHQgKyAxKSB7XG4gICAgICAvLyBMb2FkIG9uZSB0aWxlIG9mIEEgaW50byBsb2NhbCBtZW1vcnkuXG4gICAgICBmb3IgKHZhciBpbm5lclJvdyA9IDA7IGlubmVyUm93IDwgcm93UGVyVGhyZWFkOyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICAgICAgICAgIGxldCBpbnB1dFJvdyA9IHRpbGVSb3cgKyBpbm5lclJvdztcbiAgICAgICAgICBsZXQgaW5wdXRDb2wgPSB0aWxlQ29sO1xuICAgICAgICAgICR7d3JpdGVEYXRhVG9TdWJBVmVjNFNuaXBwZXQodHJhbnNwb3NlQSl9XG4gICAgICB9XG5cbiAgICAgIC8vIExvYWQgb25lIHRpbGUgb2YgQiBpbnRvIGxvY2FsIG1lbW9yeS5cbiAgICAgIGZvciAodmFyIGlubmVyUm93ID0gMDsgaW5uZXJSb3cgPCAke3Jvd1BlclRocmVhZEJ9OyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICAgICAgICAgIGxldCBpbnB1dFJvdyA9IHRpbGVSb3dCICsgaW5uZXJSb3c7XG4gICAgICAgICAgbGV0IGlucHV0Q29sID0gdGlsZUNvbDtcbiAgICAgICAgICBtbV9Cc3ViW2lucHV0Um93XVtpbnB1dENvbF0gPSBtbV9yZWFkQihiYXRjaCwga1N0YXJ0ICsgaW5wdXRSb3csIGdsb2JhbENvbCk7XG4gICAgICB9XG4gICAgICBrU3RhcnQgPSBrU3RhcnQgKyB0aWxlSW5uZXI7XG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICAgIC8vIENvbXB1dGUgYWNjIHZhbHVlcyBmb3IgYSBzaW5nbGUgdGhyZWFkLlxuICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCB0aWxlSW5uZXIgLyBpbm5lckVsZW1lbnRTaXplOyBrID0gayArIDEpIHtcbiAgICAgICAgICBsZXQgQkNhY2hlZDAgPSBtbV9Cc3ViW2sgKiBpbm5lckVsZW1lbnRTaXplXVt0aWxlQ29sXTtcbiAgICAgICAgICBsZXQgQkNhY2hlZDEgPSBtbV9Cc3ViW2sgKiBpbm5lckVsZW1lbnRTaXplICsgMV1bdGlsZUNvbF07XG4gICAgICAgICAgbGV0IEJDYWNoZWQyID0gbW1fQnN1YltrICogaW5uZXJFbGVtZW50U2l6ZSArIDJdW3RpbGVDb2xdO1xuICAgICAgICAgICR7aW5uZXJFbGVtZW50U2l6ZSA9PT0gMyA/ICcnIDogJ2xldCBCQ2FjaGVkMyA9IG1tX0JzdWJbayAqIGlubmVyRWxlbWVudFNpemUgKyAzXVt0aWxlQ29sXTsnfVxuXG4gICAgICAgICAgJHtjYWxjdWxhdGVSZXN1bHRTbmlwcGV0KHRyYW5zcG9zZUEsIGlubmVyRWxlbWVudFNpemUpfVxuICAgICAgfVxuXG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gIH1cblxuICBmb3IgKHZhciBpbm5lclJvdyA9IDA7IGlubmVyUm93IDwgcm93UGVyVGhyZWFkOyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICAgICAgbW1fd3JpdGUoYmF0Y2gsIGdsb2JhbFJvdyArIGlubmVyUm93LCBnbG9iYWxDb2wsIGFjY1tpbm5lclJvd10pO1xuICB9XG59YDtcbiAgICB9O1xuXG5jb25zdCB3cml0ZURhdGFUb1N1YkFTbmlwcGV0ID0gKHRyYW5zcG9zZTogYm9vbGVhbikgPT4ge1xuICBpZiAodHJhbnNwb3NlKSB7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgICAgIG1tX0FzdWJbaW5wdXRSb3ddW2lucHV0Q29sXSA9IG1tX3JlYWRBKGJhdGNoLFxuICAgICAgICAgICAgICBrU3RhcnQgKyBpbnB1dFJvdyxcbiAgICAgICAgICAgICAgZ2xvYmFsUm93U3RhcnQgKyBpbnB1dENvbCk7XG4gICAgICAgICAgICBgO1xuXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGBcbiAgICAgICAgICAgIG1tX0FzdWJbaW5wdXRSb3ddW2lucHV0Q29sXSA9IG1tX3JlYWRBKGJhdGNoLFxuICAgICAgICAgICAgICBnbG9iYWxSb3dTdGFydCArIGlucHV0Um93LFxuICAgICAgICAgICAgICBrU3RhcnQgKyBpbnB1dENvbCk7XG4gICAgICAgICAgICBgO1xuICB9XG59O1xuXG5jb25zdCByZWFkRGF0YUZyb21TdWJBU25pcHBldCA9ICh0cmFuc3Bvc2VBOiBib29sZWFuKSA9PlxuICAgIHRyYW5zcG9zZUEgPyAnbGV0IEFDYWNoZWQgPSBtbV9Bc3ViW2tdW3RpbGVSb3cgKyBpbm5lclJvd107JyA6ICdsZXQgQUNhY2hlZCA9IG1tX0FzdWJbdGlsZVJvdyArIGlubmVyUm93XVtrXTsnO1xuXG4vLyBzZXF1ZW50aWFsQWNjZXNzQnlUaHJlYWRzIG1lYW5zIHNlcXVlbnRpYWwgZGF0YSBpbiBtZW1vcnkgaXMgYWNjZXNzZWQgYnlcbi8vIHRocmVhZHMsIGluc3RlYWQgb2YgYSBzaW5nbGUgdGhyZWFkIChkZWZhdWx0IGJlaGF2aW9yKS5cbmV4cG9ydCBjb25zdCBtYWtlTWF0TXVsUGFja2VkU291cmNlID1cbiAgICAod29ya1BlclRocmVhZDogbnVtYmVyW10sIHdvcmtncm91cFNpemU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSwgdHJhbnNwb3NlQSA9IGZhbHNlLCB0aWxlSW5uZXIgPSAzMixcbiAgICAgc3BsaXRLID0gZmFsc2UsIHNwbGl0ZWREaW1Jbm5lciA9IDMyLCBzZXF1ZW50aWFsQWNjZXNzQnlUaHJlYWRzID0gZmFsc2UpOiBzdHJpbmcgPT4ge1xuICAgICAgY29uc3QgdGlsZUFPdXRlciA9IHdvcmtQZXJUaHJlYWRbMV0gKiB3b3JrZ3JvdXBTaXplWzFdO1xuICAgICAgY29uc3QgdGlsZUJPdXRlciA9IHdvcmtQZXJUaHJlYWRbMF0gKiB3b3JrZ3JvdXBTaXplWzBdO1xuICAgICAgY29uc3QgdGlsZUFXaWR0aCA9IHRyYW5zcG9zZUEgPyB0aWxlQU91dGVyIDogdGlsZUlubmVyO1xuICAgICAgY29uc3QgdGlsZUFIaWdodCA9IHRyYW5zcG9zZUEgPyB0aWxlSW5uZXIgOiB0aWxlQU91dGVyO1xuXG4gICAgICBpZiAoISh0aWxlQUhpZ2h0ICUgd29ya2dyb3VwU2l6ZVsxXSA9PT0gMCAmJiB0aWxlQVdpZHRoICUgd29ya2dyb3VwU2l6ZVswXSA9PT0gMCAmJlxuICAgICAgICAgICAgdGlsZUlubmVyICUgd29ya2dyb3VwU2l6ZVsxXSA9PT0gMCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB0aWxlQUhpZ2h0ICR7dGlsZUFIaWdodH0gbXVzdCBiZSBkaXZpc2libGUgYnkgd29ya2dyb3VwU2l6ZVsxXSR7XG4gICAgICAgICAgICB3b3JrZ3JvdXBTaXplWzFdfSwgdGlsZUFXaWR0aCAke3RpbGVBV2lkdGh9IG11c3QgYmUgZGl2aXNpYmxlIGJ5IHdvcmtncm91cFNpemVbMF0ke1xuICAgICAgICAgICAgd29ya2dyb3VwU2l6ZVswXX0sIHRpbGVJbm5lciAke3RpbGVJbm5lcn0gbXVzdCBiZSBkaXZpc2libGUgYnkgd29ya2dyb3VwU2l6ZVsxXSR7d29ya2dyb3VwU2l6ZVsxXX1gKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJvd1BlclRocmVhZEEgPSB0aWxlQUhpZ2h0IC8gd29ya2dyb3VwU2l6ZVsxXTtcbiAgICAgIGNvbnN0IGNvbFBlclRocmVhZEEgPSB0aWxlQVdpZHRoIC8gd29ya2dyb3VwU2l6ZVswXTtcbiAgICAgIGNvbnN0IHJvd1BlclRocmVhZEIgPSB0aWxlSW5uZXIgLyB3b3JrZ3JvdXBTaXplWzFdO1xuICAgICAgY29uc3QgbWF0bXVsU25pcHBldCA9IHNlcXVlbnRpYWxBY2Nlc3NCeVRocmVhZHMgP1xuICAgICAgICAgIGBcbiAgICBsZXQgbG9jYWxSb3cgPSBpMzIobG9jYWxJZC55KTtcbiAgICBsZXQgbG9jYWxDb2wgPSBpMzIobG9jYWxJZC54KTtcbiAgICBsZXQgZ2xvYmFsUm93U3RhcnQgPSBpMzIod29ya2dyb3VwSWQueSkgKiAke3RpbGVBT3V0ZXJ9O1xuICAgIGxldCBnbG9iYWxDb2xTdGFydCA9IGkzMih3b3JrZ3JvdXBJZC54KSAqICR7dGlsZUJPdXRlcn07XG5cbiAgICAvLyBMb29wIG92ZXIgc2hhcmVkIGRpbWVuc2lvbi5cbiAgICBmb3IgKHZhciB0ID0gMDsgdCA8IG51bVRpbGVzOyB0ID0gdCArIDEpIHtcbiAgICAgIC8vIExvYWQgb25lIHRpbGUgb2YgQSBpbnRvIGxvY2FsIG1lbW9yeS5cbiAgICAgIGZvciAodmFyIGlucHV0Um93ID0gbG9jYWxSb3c7IGlucHV0Um93IDwgJHt0aWxlQUhpZ2h0fTsgaW5wdXRSb3cgPSBpbnB1dFJvdyArICR7d29ya2dyb3VwU2l6ZVsxXX0pIHtcbiAgICAgICAgZm9yICh2YXIgaW5wdXRDb2wgPSBsb2NhbENvbDsgaW5wdXRDb2wgPCAke3RpbGVBV2lkdGh9OyBpbnB1dENvbCA9IGlucHV0Q29sICsgJHt3b3JrZ3JvdXBTaXplWzBdfSkge1xuICAgICAgICAgICR7d3JpdGVEYXRhVG9TdWJBU25pcHBldCh0cmFuc3Bvc2VBKX1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgLy8gTG9hZCBvbmUgdGlsZSBvZiBCIGludG8gbG9jYWwgbWVtb3J5LlxuICAgICAgZm9yICh2YXIgaW5wdXRSb3cgPSBsb2NhbFJvdzsgaW5wdXRSb3cgPCAke3RpbGVJbm5lcn07IGlucHV0Um93ID0gaW5wdXRSb3cgKyAke3dvcmtncm91cFNpemVbMV19KSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpbnB1dENvbCA9IGxvY2FsQ29sOyBpbnB1dENvbCA8ICR7dGlsZUJPdXRlcn07IGlucHV0Q29sID0gaW5wdXRDb2wgKyAke3dvcmtncm91cFNpemVbMF19KSB7XG4gICAgICAgICAgbW1fQnN1YltpbnB1dFJvd11baW5wdXRDb2xdID0gbW1fcmVhZEIoYmF0Y2gsXG4gICAgICAgICAgICBrU3RhcnQgKyBpbnB1dFJvdyxcbiAgICAgICAgICAgIGdsb2JhbENvbFN0YXJ0ICsgaW5wdXRDb2wpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBrU3RhcnQgPSBrU3RhcnQgKyB0aWxlSW5uZXI7XG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG5cbiAgICAgIC8vIENvbXB1dGUgYWNjIHZhbHVlcyBmb3IgYSBzaW5nbGUgdGhyZWFkLlxuICAgICAgdmFyIEJDYWNoZWQgOiBhcnJheTxmMzIsIGNvbFBlclRocmVhZD47XG4gICAgICBmb3IgKHZhciBrID0gMDsgayA8IHRpbGVJbm5lcjsgayA9IGsgKyAxKSB7XG4gICAgICAgIGZvciAodmFyIGlubmVyID0gMDsgaW5uZXIgPCBjb2xQZXJUaHJlYWQ7IGlubmVyID0gaW5uZXIgKyAxKSB7XG4gICAgICAgICAgQkNhY2hlZFtpbm5lcl0gPSBtbV9Cc3ViW2tdW2xvY2FsQ29sICsgaW5uZXIgKiAke3dvcmtncm91cFNpemVbMF19XTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBpbm5lclJvdyA9IDA7IGlubmVyUm93IDwgcm93UGVyVGhyZWFkOyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICAgICAgICAgIGxldCBBQ2FjaGVkID0gJHtcbiAgICAgICAgICAgICAgdHJhbnNwb3NlQSA/IGBtbV9Bc3ViW2tdW2xvY2FsUm93ICsgaW5uZXJSb3cgKiAke3dvcmtncm91cFNpemVbMV19XTtgIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIGBtbV9Bc3ViW2xvY2FsUm93ICsgaW5uZXJSb3cgKiAke3dvcmtncm91cFNpemVbMV19XVtrXTtgfVxuICAgICAgICAgIGZvciAodmFyIGlubmVyQ29sID0gMDsgaW5uZXJDb2wgPCBjb2xQZXJUaHJlYWQ7IGlubmVyQ29sID0gaW5uZXJDb2wgKyAxKSB7XG4gICAgICAgICAgICBhY2NbaW5uZXJSb3ddW2lubmVyQ29sXSA9IGFjY1tpbm5lclJvd11baW5uZXJDb2xdICtcbiAgICAgICAgICAgICAgICBBQ2FjaGVkICogQkNhY2hlZFtpbm5lckNvbF07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICB3b3JrZ3JvdXBCYXJyaWVyKCk7XG4gICAgfVxuICAgIGZvciAodmFyIGlubmVyUm93ID0gMDsgaW5uZXJSb3cgPCByb3dQZXJUaHJlYWQ7IGlubmVyUm93ID0gaW5uZXJSb3cgKyAxKSB7XG4gICAgICBsZXQgZ1JvdyA9IGdsb2JhbFJvd1N0YXJ0ICsgbG9jYWxSb3cgKyBpbm5lclJvdyAqICR7d29ya2dyb3VwU2l6ZVsxXX07XG4gICAgICBmb3IgKHZhciBpbm5lckNvbCA9IDA7IGlubmVyQ29sIDwgY29sUGVyVGhyZWFkOyBpbm5lckNvbCA9IGlubmVyQ29sICsgMSkge1xuICAgICAgICBsZXQgZ0NvbCA9IGdsb2JhbENvbFN0YXJ0ICsgbG9jYWxDb2wgKyBpbm5lckNvbCAqICR7d29ya2dyb3VwU2l6ZVswXX07XG4gICAgICAgIG1tX3dyaXRlKGJhdGNoLCBnUm93LCBnQ29sLCBhY2NbaW5uZXJSb3ddW2lubmVyQ29sXSk7XG4gICAgICB9XG4gICAgfVxuICAgIGAgOlxuICAgICAgICAgIGBcbmxldCB0aWxlUm93ID0gaTMyKGxvY2FsSWQueSkgKiByb3dQZXJUaHJlYWQ7XG5sZXQgdGlsZUNvbCA9IGkzMihsb2NhbElkLngpICogY29sUGVyVGhyZWFkO1xuXG5sZXQgZ2xvYmFsUm93ID0gaTMyKGdsb2JhbElkLnkpICogcm93UGVyVGhyZWFkO1xubGV0IGdsb2JhbENvbCA9IGkzMihnbG9iYWxJZC54KSAqIGNvbFBlclRocmVhZDtcbmxldCBnbG9iYWxSb3dTdGFydCA9IGkzMih3b3JrZ3JvdXBJZC55KSAqICR7dGlsZUFPdXRlcn07XG5cbmxldCB0aWxlUm93QSA9IGkzMihsb2NhbElkLnkpICogJHtyb3dQZXJUaHJlYWRBfTtcbmxldCB0aWxlQ29sQSA9IGkzMihsb2NhbElkLngpICogJHtjb2xQZXJUaHJlYWRBfTtcbmxldCB0aWxlUm93QiA9IGkzMihsb2NhbElkLnkpICogJHtyb3dQZXJUaHJlYWRCfTtcbi8vIExvb3Agb3ZlciBzaGFyZWQgZGltZW5zaW9uLlxuZm9yICh2YXIgdCA9IDA7IHQgPCBudW1UaWxlczsgdCA9IHQgKyAxKSB7XG4gIC8vIExvYWQgb25lIHRpbGUgb2YgQSBpbnRvIGxvY2FsIG1lbW9yeS5cbiAgZm9yICh2YXIgaW5uZXJSb3cgPSAwOyBpbm5lclJvdyA8ICR7cm93UGVyVGhyZWFkQX07IGlubmVyUm93ID0gaW5uZXJSb3cgKyAxKSB7XG4gICAgZm9yICh2YXIgaW5uZXJDb2wgPSAwOyBpbm5lckNvbCA8ICR7Y29sUGVyVGhyZWFkQX07IGlubmVyQ29sID0gaW5uZXJDb2wgKyAxKSB7XG4gICAgICBsZXQgaW5wdXRSb3cgPSB0aWxlUm93QSArIGlubmVyUm93O1xuICAgICAgbGV0IGlucHV0Q29sID0gdGlsZUNvbEEgKyBpbm5lckNvbDtcbiAgICAgICR7d3JpdGVEYXRhVG9TdWJBU25pcHBldCh0cmFuc3Bvc2VBKX1cbiAgICB9XG4gIH1cblxuICAvLyBMb2FkIG9uZSB0aWxlIG9mIEIgaW50byBsb2NhbCBtZW1vcnkuXG4gIGZvciAodmFyIGlubmVyUm93ID0gMDsgaW5uZXJSb3cgPCAke3Jvd1BlclRocmVhZEJ9OyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICAgIGZvciAodmFyIGlubmVyQ29sID0gMDsgaW5uZXJDb2wgPCBjb2xQZXJUaHJlYWQ7IGlubmVyQ29sID0gaW5uZXJDb2wgKyAxKSB7XG4gICAgICBsZXQgaW5wdXRSb3cgPSB0aWxlUm93QiArIGlubmVyUm93O1xuICAgICAgbGV0IGlucHV0Q29sID0gdGlsZUNvbCArIGlubmVyQ29sO1xuICAgICAgbW1fQnN1YltpbnB1dFJvd11baW5wdXRDb2xdID0gbW1fcmVhZEIoYmF0Y2gsXG4gICAgICAgIGtTdGFydCArIGlucHV0Um93LFxuICAgICAgICBnbG9iYWxDb2wgKyBpbm5lckNvbCk7XG4gICAgfVxuICB9XG4gIGtTdGFydCA9IGtTdGFydCArIHRpbGVJbm5lcjtcbiAgd29ya2dyb3VwQmFycmllcigpO1xuXG4gIC8vIENvbXB1dGUgYWNjIHZhbHVlcyBmb3IgYSBzaW5nbGUgdGhyZWFkLlxuICB2YXIgQkNhY2hlZCA6IGFycmF5PGYzMiwgY29sUGVyVGhyZWFkPjtcbiAgZm9yICh2YXIgayA9IDA7IGsgPCB0aWxlSW5uZXI7IGsgPSBrICsgMSkge1xuICAgIGZvciAodmFyIGlubmVyID0gMDsgaW5uZXIgPCBjb2xQZXJUaHJlYWQ7IGlubmVyID0gaW5uZXIgKyAxKSB7XG4gICAgICBCQ2FjaGVkW2lubmVyXSA9IG1tX0JzdWJba11bdGlsZUNvbCArIGlubmVyXTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBpbm5lclJvdyA9IDA7IGlubmVyUm93IDwgcm93UGVyVGhyZWFkOyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICAgICAgJHtyZWFkRGF0YUZyb21TdWJBU25pcHBldCh0cmFuc3Bvc2VBKX1cbiAgICAgIGZvciAodmFyIGlubmVyQ29sID0gMDsgaW5uZXJDb2wgPCBjb2xQZXJUaHJlYWQ7IGlubmVyQ29sID0gaW5uZXJDb2wgKyAxKSB7XG4gICAgICAgIGFjY1tpbm5lclJvd11baW5uZXJDb2xdID0gYWNjW2lubmVyUm93XVtpbm5lckNvbF0gKyBBQ2FjaGVkICogQkNhY2hlZFtpbm5lckNvbF07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgd29ya2dyb3VwQmFycmllcigpO1xufVxuXG5mb3IgKHZhciBpbm5lclJvdyA9IDA7IGlubmVyUm93IDwgcm93UGVyVGhyZWFkOyBpbm5lclJvdyA9IGlubmVyUm93ICsgMSkge1xuICBmb3IgKHZhciBpbm5lckNvbCA9IDA7IGlubmVyQ29sIDwgY29sUGVyVGhyZWFkOyBpbm5lckNvbCA9IGlubmVyQ29sICsgMSkge1xuICAgIG1tX3dyaXRlKGJhdGNoLCBnbG9iYWxSb3cgKyBpbm5lclJvdywgZ2xvYmFsQ29sICsgaW5uZXJDb2wsXG4gICAgICAgIGFjY1tpbm5lclJvd11baW5uZXJDb2xdKTtcbiAgfVxufVxuYDtcblxuICAgICAgcmV0dXJuIGBcbiAgdmFyPHdvcmtncm91cD4gbW1fQXN1YiA6IGFycmF5PGFycmF5PGYzMiwgJHt0aWxlQVdpZHRofT4sICR7dGlsZUFIaWdodH0+O1xuICB2YXI8d29ya2dyb3VwPiBtbV9Cc3ViIDogYXJyYXk8YXJyYXk8ZjMyLCAke3RpbGVCT3V0ZXJ9PiwgJHt0aWxlSW5uZXJ9PjtcbiAgY29uc3Qgcm93UGVyVGhyZWFkID0gJHt3b3JrUGVyVGhyZWFkWzFdfTtcbiAgY29uc3QgY29sUGVyVGhyZWFkID0gJHt3b3JrUGVyVGhyZWFkWzBdfTtcbiAgY29uc3QgdGlsZUlubmVyID0gJHt0aWxlSW5uZXJ9O1xuXG5AY29tcHV0ZSBAd29ya2dyb3VwX3NpemUoJHt3b3JrZ3JvdXBTaXplWzBdfSwgJHt3b3JrZ3JvdXBTaXplWzFdfSwgJHt3b3JrZ3JvdXBTaXplWzJdfSlcbmZuIG1haW4oQGJ1aWx0aW4obG9jYWxfaW52b2NhdGlvbl9pZCkgbG9jYWxJZCA6IHZlYzM8dTMyPixcbiAgICAgICAgQGJ1aWx0aW4oZ2xvYmFsX2ludm9jYXRpb25faWQpIGdsb2JhbElkIDogdmVjMzx1MzI+LFxuICAgICAgICBAYnVpbHRpbih3b3JrZ3JvdXBfaWQpIHdvcmtncm91cElkIDogdmVjMzx1MzI+KSB7XG4gICAgbGV0IGJhdGNoID0gJHtzcGxpdEsgPyAnMCcgOiAnaTMyKGdsb2JhbElkLnopJ307XG4gICAgbGV0IG51bVRpbGVzID0gJHtzcGxpdEsgPyBgJHtNYXRoLmNlaWwoc3BsaXRlZERpbUlubmVyIC8gdGlsZUlubmVyKX1gIDogJyhkaW1Jbm5lciAtIDEpIC8gdGlsZUlubmVyICsgMSd9O1xuICAgIHZhciBrU3RhcnQgPSAke3NwbGl0SyA/IGBpMzIoZ2xvYmFsSWQueikgKiAke3NwbGl0ZWREaW1Jbm5lcn1gIDogJzAnfTtcblxuICAgIHZhciBhY2MgOiBhcnJheTxhcnJheTxmMzIsIGNvbFBlclRocmVhZD4sIHJvd1BlclRocmVhZD47XG5cbiAgICAvLyBXaXRob3V0IHRoaXMgaW5pdGlhbGl6YXRpb24gc3RyYW5nZSB2YWx1ZXMgc2hvdyB1cCBpbiBhY2MuXG4gICAgZm9yICh2YXIgaW5uZXJSb3cgPSAwOyBpbm5lclJvdyA8IHJvd1BlclRocmVhZDsgaW5uZXJSb3cgPSBpbm5lclJvdyArIDEpIHtcbiAgICAgIGZvciAodmFyIGlubmVyQ29sID0gMDsgaW5uZXJDb2wgPCBjb2xQZXJUaHJlYWQ7IGlubmVyQ29sID0gaW5uZXJDb2wgKyAxKSB7XG4gICAgICAgIGFjY1tpbm5lclJvd11baW5uZXJDb2xdID0gMC4wO1xuICAgICAgfVxuICAgIH1cbiAgICAke21hdG11bFNuaXBwZXR9XG4gIH1cbmA7XG4gICAgfTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1RlbnNvclZpZXd9IGZyb20gJy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge0Jyb2FkY2FzdFV0aWwsIFNoYXBlVXRpbH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQge0NvbXB1dGVDb250ZXh0LCBHcHVEYXRhVHlwZSwgUHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGF9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtjcmVhdGVJbmRpY2VzSGVscGVyLCBTaGFkZXJIZWxwZXJ9IGZyb20gJy4vY29tbW9uJztcblxudHlwZSBCdWlsdGluRnVuY3Rpb25OYW1lID0gc3RyaW5nO1xudHlwZSBCaW5hcnlDdXN0b21FeHByZXNzaW9uID0gKGV4cHJlc3Npb25BOiBzdHJpbmcsIGV4cHJlc3Npb25COiBzdHJpbmcpID0+IHN0cmluZztcbnR5cGUgQmluYXJ5RnVuY3Rpb25DYWxsID0gQnVpbHRpbkZ1bmN0aW9uTmFtZXxCaW5hcnlDdXN0b21FeHByZXNzaW9ufHtcbiAgc2NhbGFyOiBCaW5hcnlDdXN0b21FeHByZXNzaW9uO1xuICB2ZWN0b3I6IEJpbmFyeUN1c3RvbUV4cHJlc3Npb247XG59O1xuXG5jb25zdCBjcmVhdGVCaW5hcnlPcFByb2dyYW1TaGFkZXIgPVxuICAgIChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlciwgZGltc0E6IHJlYWRvbmx5IG51bWJlcltdLCBkaW1zQjogcmVhZG9ubHkgbnVtYmVyW10sIGRpbXNPdXRwdXQ6IHJlYWRvbmx5IG51bWJlcltdLFxuICAgICB2ZWN0b3JpemU6IGJvb2xlYW4sIGRvQnJvYWRjYXN0OiBib29sZWFuLCBmdW5jQ2FsbDogQmluYXJ5RnVuY3Rpb25DYWxsLCBhZGRpdGlvbmFsSW1wbGVtZW50YXRpb24/OiBzdHJpbmcsXG4gICAgIHR5cGVBID0gJ2YzMicsIHR5cGVCID0gJ2YzMicsIHR5cGVPdXRwdXQgPSAnZjMyJykgPT4ge1xuICAgICAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKGRpbXNPdXRwdXQpO1xuICAgICAgY29uc3QgdmVjU2l6ZSA9IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNCk7XG5cbiAgICAgIGxldCBleHByZXNzaW9uU2NhbGFyOiBCaW5hcnlDdXN0b21FeHByZXNzaW9uO1xuICAgICAgbGV0IGV4cHJlc3Npb25WZWN0b3I6IEJpbmFyeUN1c3RvbUV4cHJlc3Npb247XG4gICAgICBpZiAodHlwZW9mIGZ1bmNDYWxsID09PSAnc3RyaW5nJykge1xuICAgICAgICBleHByZXNzaW9uU2NhbGFyID0gZXhwcmVzc2lvblZlY3RvciA9IChhLCBiKSA9PiBgJHtmdW5jQ2FsbH0oKCR7YX0pLCgke2J9KSlgO1xuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZnVuY0NhbGwgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgZXhwcmVzc2lvblNjYWxhciA9IGV4cHJlc3Npb25WZWN0b3IgPSBmdW5jQ2FsbDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGV4cHJlc3Npb25TY2FsYXIgPSBmdW5jQ2FsbC5zY2FsYXI7XG4gICAgICAgIGV4cHJlc3Npb25WZWN0b3IgPSBmdW5jQ2FsbC52ZWN0b3I7XG4gICAgICB9XG5cbiAgICAgIGxldCBicm9hZGNhc3RJbXBsID0gJyc7XG4gICAgICBjb25zdCBvdXRwdXRJbmRpY2VzSGVscGVyID0gY3JlYXRlSW5kaWNlc0hlbHBlcignb3V0cHV0JywgZGltc091dHB1dCk7XG4gICAgICBpZiAoZG9Ccm9hZGNhc3QpIHtcbiAgICAgICAgY29uc3QgY2FsY09mZnNldEltcGwgPSAoZGltczogcmVhZG9ubHkgbnVtYmVyW10pID0+IHtcbiAgICAgICAgICBjb25zdCBzdHJpZGVzID0gU2hhcGVVdGlsLmNvbXB1dGVTdHJpZGVzKGRpbXMpO1xuICAgICAgICAgIGNvbnN0IG9mZnNldHM6IHN0cmluZ1tdID0gW107XG4gICAgICAgICAgZm9yIChsZXQgaSA9IGRpbXMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIGNvbnN0IGlkeCA9IGRpbXNPdXRwdXQubGVuZ3RoID09PSAwID8gJzB1JyA6XG4gICAgICAgICAgICAgICAgKGRpbXNPdXRwdXQubGVuZ3RoID09PSAxKSAgICAgICA/ICcoKm91dHB1dEluZGljZXMpJyA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGAoKm91dHB1dEluZGljZXMpWyR7aSArIGRpbXNPdXRwdXQubGVuZ3RoIC0gZGltcy5sZW5ndGh9XWA7XG4gICAgICAgICAgICBvZmZzZXRzLnB1c2goYCR7c3RyaWRlc1tpXX11ICogKCR7aWR4fSAlICR7ZGltc1tpXX11KWApO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gb2Zmc2V0cy5sZW5ndGggPiAwID8gb2Zmc2V0cy5qb2luKCcrJykgOiAnMHUnO1xuICAgICAgICB9O1xuXG4gICAgICAgIGJyb2FkY2FzdEltcGwgPSBgXG4gICR7b3V0cHV0SW5kaWNlc0hlbHBlci5vMmlJbXBsfVxuXG4gIGZuIGNhbGNPZmZzZXRBKG91dHB1dEluZGljZXM6IHB0cjxmdW5jdGlvbiwgJHtvdXRwdXRJbmRpY2VzSGVscGVyLmlUeXBlfT4pIC0+IHUzMiB7XG4gICAgcmV0dXJuICR7Y2FsY09mZnNldEltcGwoZGltc0EpfTtcbiAgfVxuXG4gIGZuIGNhbGNPZmZzZXRCKG91dHB1dEluZGljZXM6IHB0cjxmdW5jdGlvbiwgJHtvdXRwdXRJbmRpY2VzSGVscGVyLmlUeXBlfT4pIC0+IHUzMiB7XG4gICAgcmV0dXJuICR7Y2FsY09mZnNldEltcGwoZGltc0IpfTtcbiAgfVxuICBgO1xuICAgICAgfVxuXG4gICAgICBsZXQgYXNzaWdubWVudDogc3RyaW5nO1xuICAgICAgaWYgKHZlY3Rvcml6ZSkge1xuICAgICAgICBpZiAoZG9Ccm9hZGNhc3QpIHtcbiAgICAgICAgICBhc3NpZ25tZW50ID0gYFxuICAgICAgJHtvdXRwdXRJbmRpY2VzSGVscGVyLmluZGljZXNWYXJpYWJsZURlY2xhcmF0aW9uKCdvdXRwdXRJbmRpY2VzJyl9XG4gICAgICAke291dHB1dEluZGljZXNIZWxwZXIubzJpQ2FsbCgnZ2xvYmFsX2lkeCAqIDR1JywgJ291dHB1dEluZGljZXMnKX1cbiAgICAgIGxldCBvZmZzZXRBID0gY2FsY09mZnNldEEoJm91dHB1dEluZGljZXMpO1xuICAgICAgbGV0IG9mZnNldEIgPSBjYWxjT2Zmc2V0Qigmb3V0cHV0SW5kaWNlcyk7XG4gICAgICBvdXRwdXREYXRhW2dsb2JhbF9pZHhdID0gJHtleHByZXNzaW9uVmVjdG9yKCdhRGF0YVtvZmZzZXRBIC8gNHVdJywgJ2JEYXRhW29mZnNldEIgLyA0dV0nKX07YDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBhc3NpZ25tZW50ID0gYG91dHB1dERhdGFbZ2xvYmFsX2lkeF0gPSAke2V4cHJlc3Npb25WZWN0b3IoJ2FEYXRhW2dsb2JhbF9pZHhdJywgJ2JEYXRhW2dsb2JhbF9pZHhdJyl9O2A7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICghZG9Ccm9hZGNhc3QpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ25vIG5lY2Vzc2FyeSB0byB1c2Ugc2NhbGFyIGltcGxlbWVudGF0aW9uIGZvciBlbGVtZW50LXdpc2UgYmluYXJ5IG9wIGltcGxlbWVudGF0aW9uLicpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHNpbmdsZUFzc2lnbm1lbnQgPSAoeDogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgY29uc3QgZXhwcmVzc2lvbkEgPSBgYURhdGFbaW5kZXhBJHt4fV1bY29tcG9uZW50QSR7eH1dYDtcbiAgICAgICAgICBjb25zdCBleHByZXNzaW9uQiA9IGBiRGF0YVtpbmRleEIke3h9XVtjb21wb25lbnRCJHt4fV1gO1xuICAgICAgICAgIHJldHVybiBgXG4gICAgICAke291dHB1dEluZGljZXNIZWxwZXIubzJpQ2FsbChgZ2xvYmFsX2lkeCAqIDR1ICsgJHt4fXVgLCAnb3V0cHV0SW5kaWNlcycpfVxuICAgICAgbGV0IG9mZnNldEEke3h9ID0gY2FsY09mZnNldEEoJm91dHB1dEluZGljZXMpO1xuICAgICAgbGV0IG9mZnNldEIke3h9ID0gY2FsY09mZnNldEIoJm91dHB1dEluZGljZXMpO1xuICAgICAgbGV0IGluZGV4QSR7eH0gPSBvZmZzZXRBJHt4fSAvIDR1O1xuICAgICAgbGV0IGluZGV4QiR7eH0gPSBvZmZzZXRCJHt4fSAvIDR1O1xuICAgICAgbGV0IGNvbXBvbmVudEEke3h9ID0gb2Zmc2V0QSR7eH0gJSA0dTtcbiAgICAgIGxldCBjb21wb25lbnRCJHt4fSA9IG9mZnNldEIke3h9ICUgNHU7XG4gICAgICBvdXRwdXREYXRhW2dsb2JhbF9pZHhdWyR7eH1dID0gJHtleHByZXNzaW9uU2NhbGFyKGV4cHJlc3Npb25BLCBleHByZXNzaW9uQil9O2A7XG4gICAgICAgIH07XG5cbiAgICAgICAgYXNzaWdubWVudCA9IGBcbiAgICAgICR7b3V0cHV0SW5kaWNlc0hlbHBlci5pbmRpY2VzVmFyaWFibGVEZWNsYXJhdGlvbignb3V0cHV0SW5kaWNlcycpfVxuICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KDApfVxuICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KDEpfVxuICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KDIpfVxuICAgICAgJHtzaW5nbGVBc3NpZ25tZW50KDMpfWA7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBgXG4gIEBncm91cCgwKSBAYmluZGluZygwKSB2YXI8c3RvcmFnZSwgcmVhZD4gYURhdGEgOiBhcnJheTx2ZWM0PCR7dHlwZUF9Pj47XG4gIEBncm91cCgwKSBAYmluZGluZygxKSB2YXI8c3RvcmFnZSwgcmVhZD4gYkRhdGEgOiBhcnJheTx2ZWM0PCR7dHlwZUJ9Pj47XG4gIEBncm91cCgwKSBAYmluZGluZygyKSB2YXI8c3RvcmFnZSwgcmVhZF93cml0ZT4gb3V0cHV0RGF0YSA6IGFycmF5PHZlYzQ8JHt0eXBlT3V0cHV0fT4+O1xuXG4gICR7YWRkaXRpb25hbEltcGxlbWVudGF0aW9uID8/ICcnfVxuICAke2Jyb2FkY2FzdEltcGx9XG5cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcyh2ZWNTaXplKX1cbiAgICAke2Fzc2lnbm1lbnR9XG4gIH1gO1xuICAgIH07XG5cbmNvbnN0IGNyZWF0ZUJpbmFyeU9wUHJvZ3JhbUluZm8gPVxuICAgIChtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhLCBhOiBUZW5zb3JWaWV3LCBiOiBUZW5zb3JWaWV3LCBmdW5jQ2FsbDogQmluYXJ5RnVuY3Rpb25DYWxsLFxuICAgICBhZGRpdGlvbmFsSW1wbGVtZW50YXRpb24/OiBzdHJpbmcsIG91dHB1dERhdGFUeXBlOiBudW1iZXIgPSBhLmRhdGFUeXBlKTogUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgY29uc3QgaXNCcm9hZGNhc3QgPSAhU2hhcGVVdGlsLmFyZUVxdWFsKGEuZGltcywgYi5kaW1zKTtcbiAgICAgIGxldCBvdXRwdXRTaGFwZSA9IGEuZGltcztcbiAgICAgIGxldCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUoYS5kaW1zKTtcblxuICAgICAgbGV0IHZlY3Rvcml6ZSA9IGZhbHNlO1xuXG4gICAgICAvLyBUT0RPOiBkZWFsIHdpdGggemVyby1zaXplZCB0ZW5zb3JzIChlZy4gZGltcz1bMSwwXSlcblxuICAgICAgaWYgKGlzQnJvYWRjYXN0KSB7XG4gICAgICAgIGNvbnN0IGNhbGN1bGF0ZWRTaGFwZSA9IEJyb2FkY2FzdFV0aWwuY2FsY1NoYXBlKGEuZGltcywgYi5kaW1zLCBmYWxzZSk7XG4gICAgICAgIGlmICghY2FsY3VsYXRlZFNoYXBlKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXCd0IHBlcmZvcm0gYmluYXJ5IG9wIG9uIHRoZSBnaXZlbiB0ZW5zb3JzJyk7XG4gICAgICAgIH1cbiAgICAgICAgb3V0cHV0U2hhcGUgPSBjYWxjdWxhdGVkU2hhcGU7XG4gICAgICAgIG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG5cbiAgICAgICAgLy8gY2hlY2sgd2hldGhlciB2ZWN0b3JpemUgY2FuIGJlIGVuYWJsZWRcbiAgICAgICAgbGV0IHNoYXJlZERpbWVuc2lvbiA9IDE7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0U2hhcGUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBjb25zdCBkaW1BID0gYS5kaW1zW2EuZGltcy5sZW5ndGggLSBpXSA/PyAxO1xuICAgICAgICAgIGNvbnN0IGRpbUIgPSBiLmRpbXNbYi5kaW1zLmxlbmd0aCAtIGldID8/IDE7XG4gICAgICAgICAgaWYgKGRpbUEgPT09IGRpbUIpIHtcbiAgICAgICAgICAgIHNoYXJlZERpbWVuc2lvbiAqPSBkaW1BO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNoYXJlZERpbWVuc2lvbiAlIDQgPT09IDApIHtcbiAgICAgICAgICB2ZWN0b3JpemUgPSB0cnVlO1xuICAgICAgICB9XG5cblxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gZWxlbWVudC13aXNlXG4gICAgICAgIHZlY3Rvcml6ZSA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICBnZXRTaGFkZXJTb3VyY2U6IChzaGFkZXJIZWxwZXIpID0+IGNyZWF0ZUJpbmFyeU9wUHJvZ3JhbVNoYWRlcihcbiAgICAgICAgICAgIHNoYWRlckhlbHBlciwgYS5kaW1zLCBiLmRpbXMsIG91dHB1dFNoYXBlLCB2ZWN0b3JpemUsIGlzQnJvYWRjYXN0LCBmdW5jQ2FsbCwgYWRkaXRpb25hbEltcGxlbWVudGF0aW9uKSxcbiAgICAgICAgb3V0cHV0czogW3tkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IG91dHB1dERhdGFUeXBlLCBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdH1dLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiAoKSA9PlxuICAgICAgICAgICAgKHt4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovIC8gKHZlY3Rvcml6ZSA/IDQgOiAxKSAvKiB2ZWMgc2l6ZSAqLyl9KVxuICAgICAgfTtcbiAgICB9O1xuXG5jb25zdCBjcmVhdGVCaW5hcnlPcFByb2dyYW1JbmZvTG9hZGVyID1cbiAgICAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIG5hbWU6IHN0cmluZywgZnVuY0NhbGw6IEJpbmFyeUZ1bmN0aW9uQ2FsbCwgYWRkaXRpb25hbEltcGxlbWVudGF0aW9uPzogc3RyaW5nLFxuICAgICBjYWNoZUtleT86IHN0cmluZyk6IFByb2dyYW1JbmZvTG9hZGVyID0+IHtcbiAgICAgIGNvbnN0IG1ldGFkYXRhOlxuICAgICAgICAgIFByb2dyYW1NZXRhZGF0YSA9IHtuYW1lLCBpbnB1dFR5cGVzOiBbR3B1RGF0YVR5cGUuZGVmYXVsdCwgR3B1RGF0YVR5cGUuZGVmYXVsdF0sIGNhY2hlSGludDogY2FjaGVLZXl9O1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgIGdldDogKCkgPT4gY3JlYXRlQmluYXJ5T3BQcm9ncmFtSW5mbyhtZXRhZGF0YSwgaW5wdXRzWzBdLCBpbnB1dHNbMV0sIGZ1bmNDYWxsLCBhZGRpdGlvbmFsSW1wbGVtZW50YXRpb24pXG4gICAgICB9O1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCBhZGQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUJpbmFyeU9wUHJvZ3JhbUluZm9Mb2FkZXIoY29udGV4dC5pbnB1dHMsICdBZGQnLCAoYSwgYikgPT4gYCR7YX0rJHtifWApKTtcbn07XG5cbmV4cG9ydCBjb25zdCBkaXYgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUJpbmFyeU9wUHJvZ3JhbUluZm9Mb2FkZXIoY29udGV4dC5pbnB1dHMsICdEaXYnLCAoYSwgYikgPT4gYCR7YX0vJHtifWApKTtcbn07XG5cbmV4cG9ydCBjb25zdCBtdWwgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUJpbmFyeU9wUHJvZ3JhbUluZm9Mb2FkZXIoY29udGV4dC5pbnB1dHMsICdNdWwnLCAoYSwgYikgPT4gYCR7YX0qJHtifWApKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwb3cgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUJpbmFyeU9wUHJvZ3JhbUluZm9Mb2FkZXIoXG4gICAgICBjb250ZXh0LmlucHV0cywgJ1BvdycsICh7c2NhbGFyOiAoYSwgYikgPT4gYHBvd19mMzIoJHthfSwke2J9KWAsIHZlY3RvcjogKGEsIGIpID0+IGBwb3dfdmYzMigke2F9LCR7Yn0pYH0pLCBgXG4gICAgZm4gcG93X2YzMihhIDogZjMyLCBiIDogZjMyKSAtPiBmMzIge1xuICAgICAgaWYgKGIgPT0gMC4wKSB7XG4gICAgICAgIHJldHVybiAxLjA7XG4gICAgICB9IGVsc2UgaWYgKGEgPCAwLjAgJiYgYiAhPSBmbG9vcihiKSkge1xuICAgICAgICByZXR1cm4gcG93KGEsIGIpOyAvLyBOYU5cbiAgICAgIH1cbiAgICAgIHJldHVybiBzZWxlY3Qoc2lnbihhKSwgMS4wLCByb3VuZChhYnMoYikgJSAyLjApICE9IDEuMCkgKiBwb3coYWJzKGEpLCBiKTtcbiAgICB9XG4gICAgZm4gcG93X3ZmMzIoYSA6IHZlYzQ8ZjMyPiwgYiA6IHZlYzQ8ZjMyPikgLT4gdmVjNDxmMzI+IHtcbiAgICAgIC8vIFRPRE86IGltcGxlbWVudCB2ZWN0b3JpemVkIHBvd1xuICAgICAgcmV0dXJuIHZlYzQ8ZjMyPihwb3dfZjMyKGEueCwgYi54KSwgcG93X2YzMihhLnksIGIueSksIHBvd19mMzIoYS56LCBiLnopLCBwb3dfZjMyKGEudywgYi53KSk7XG4gICAgfVxuICAgICAgYCkpO1xufTtcblxuZXhwb3J0IGNvbnN0IHN1YiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlQmluYXJ5T3BQcm9ncmFtSW5mb0xvYWRlcihjb250ZXh0LmlucHV0cywgJ1N1YicsIChhLCBiKSA9PiBgJHthfS0ke2J9YCkpO1xufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1NoYXBlVXRpbH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5cbi8qKlxuICogY29uc3RhbnQgdmFsdWUgZm9yIGEgd29ya2dyb3VwIHNpemUuXG4gKlxuICogV2UgZGVmaW5pdGVseSBjYW4gZG8gZnVydGhlciBvcHRpbWl6YXRpb24gaW4gZnV0dXJlLCBidXQgZm9yIG5vdyB3ZSB1c2UgNjQuXG4gKlxuICogcnVsZSBvZiB0aHVtYjogVXNlIFthIHdvcmtncm91cCBzaXplIG9mXSA2NCB1bmxlc3MgeW91IGtub3cgd2hhdCBHUFUgeW91IGFyZSB0YXJnZXRpbmcgb3IgdGhhdCB5b3VyIHdvcmtsb2FkXG4gKiAgICAgICAgICAgICAgICBuZWVkcyBzb21ldGhpbmcgZGlmZmVyZW50LlxuICpcbiAqIGZyb206IGh0dHBzOi8vc3VybWEuZGV2L3RoaW5ncy93ZWJncHUvXG4gKiovXG5leHBvcnQgY29uc3QgV09SS0dST1VQX1NJWkUgPSA2NDtcblxuZXhwb3J0IGludGVyZmFjZSBJbmRpY2VzSGVscGVyIHtcbiAgLyoqXG4gICAqIFdHU0wgY29kZSBvZiBmdW5jdGlvbiBpbXBsZW1lbnRhdGlvbiBmb3Igb2Zmc2V0LXRvLWluZGljZXNcbiAgICovXG4gIG8yaUltcGw6IHN0cmluZztcbiAgLyoqXG4gICAqIFdHU0wgY29kZSBvZiBmdW5jdGlvbiBjYWxsIGZvciBvZmZzZXQtdG8taW5kaWNlc1xuICAgKi9cbiAgbzJpQ2FsbDogKHZhck9mZnNldDogc3RyaW5nLCB2YXJJbmRpY2VzOiBzdHJpbmcpID0+IHN0cmluZztcbiAgLyoqXG4gICAqIFdHU0wgY29kZSBvZiBmdW5jdGlvbiBpbXBsZW1lbnRhdGlvbiBmb3IgaW5kaWNlcy10by1vZmZzZXRcbiAgICovXG4gIGkyb0ltcGw6IHN0cmluZztcbiAgLyoqXG4gICAqIFdHU0wgY29kZSBvZiBmdW5jdGlvbiBpbXBsZW1lbnRhdGlvbiBmb3IgaW5kaWNlcy10by1vZmZzZXRcbiAgICpcbiAgICogQHBhcmFtIGlzUHRyIC0gd2hldGhlciB0aGUgdmFyaWFibGUgaXMgYSBwb2ludGVyLiBkZWZhdWx0IGlzIGZhbHNlLlxuICAgKi9cbiAgaTJvRXhwcmVzc2lvbjogKHZhckluZGljZXM6IHN0cmluZywgaXNQdHI/OiBib29sZWFuKSA9PiBzdHJpbmc7XG4gIC8qKlxuICAgKiBXR1NMIGNvZGUgb2YgaW5kaWNlcyB2YXJpYWJsZSBkZWNsYXJhdGlvblxuICAgKlxuICAgKiBAcGFyYW0gdiAtIHZhcmlhYmxlIG5hbWUuXG4gICAqIEBwYXJhbSBpbml0IC0gaW5pdGlhbCB2YWx1ZS5cbiAgICovXG4gIGluZGljZXNWYXJpYWJsZURlY2xhcmF0aW9uOiAodjogc3RyaW5nLCBpbml0Pzogc3RyaW5nW10pID0+IHN0cmluZztcbiAgLyoqXG4gICAqIGRhdGEgdHlwZSBvZiBpbmRpY2VzXG4gICAqL1xuICBpVHlwZTogc3RyaW5nO1xufVxuXG5leHBvcnQgY29uc3QgY3JlYXRlSW5kaWNlc0hlbHBlciA9IChuYW1lOiBzdHJpbmcsIHNoYXBlOiByZWFkb25seSBudW1iZXJbXSk6IEluZGljZXNIZWxwZXIgPT4ge1xuICBjb25zdCBpVHlwZSA9IHNoYXBlLmxlbmd0aCA8IDIgPyAndTMyJyA6IGBhcnJheTx1MzIsICR7c2hhcGUubGVuZ3RofT5gO1xuXG4gIGNvbnN0IHN0cmlkZXMgPSBTaGFwZVV0aWwuY29tcHV0ZVN0cmlkZXMoc2hhcGUpO1xuICBsZXQgbzJpU25pcHBldCA9ICcnO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHNoYXBlLmxlbmd0aCAtIDE7IGkrKykge1xuICAgIG8yaVNuaXBwZXQgKz0gYFxuICAgIGxldCBkaW0ke2l9ID0gY3VycmVudCAvICR7c3RyaWRlc1tpXX11O1xuICAgIGxldCByZXN0JHtpfSA9IGN1cnJlbnQgJSAke3N0cmlkZXNbaV19dTtcbiAgICAoKmluZGljZXMpWyR7aX1dID0gZGltJHtpfTtcbiAgICBjdXJyZW50ID0gcmVzdCR7aX07XG4gICAgYDtcbiAgfVxuICBvMmlTbmlwcGV0ICs9IGAoKmluZGljZXMpWyR7c2hhcGUubGVuZ3RoIC0gMX1dID0gY3VycmVudDtgO1xuXG4gIGNvbnN0IG8yaUltcGwgPSBzaGFwZS5sZW5ndGggPCAyID8gJycgOiBgXG4gIGZuIGloX28yaV8ke25hbWV9KG9mZnNldDogdTMyLCBpbmRpY2VzOiBwdHI8ZnVuY3Rpb24sICR7aVR5cGV9Pikge1xuICAgIHZhciBjdXJyZW50ID0gb2Zmc2V0O1xuICAgICR7bzJpU25pcHBldH1cbiAgfWA7XG5cbiAgY29uc3QgbzJpQ2FsbCA9ICh2YXJPZmZzZXQ6IHN0cmluZywgdmFySW5kaWNlczogc3RyaW5nKSA9PlxuICAgICAgc2hhcGUubGVuZ3RoIDwgMiA/IGAke3ZhckluZGljZXN9PSR7dmFyT2Zmc2V0fTtgIDogYGloX28yaV8ke25hbWV9KCR7dmFyT2Zmc2V0fSwgJiR7dmFySW5kaWNlc30pO2A7XG5cbiAgY29uc3Qgb2Zmc2V0czogc3RyaW5nW10gPSBbXTtcbiAgaWYgKHNoYXBlLmxlbmd0aCA9PT0gMCkge1xuICAgIG9mZnNldHMucHVzaCgnMHUnKTtcbiAgfSBlbHNlIGlmIChzaGFwZS5sZW5ndGggPCAyKSB7XG4gICAgb2Zmc2V0cy5wdXNoKCcoKmluZGljZXMpJyk7XG4gIH0gZWxzZSB7XG4gICAgZm9yIChsZXQgaSA9IHNoYXBlLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBvZmZzZXRzLnB1c2goYCR7c3RyaWRlc1tpXX11ICogKCgqaW5kaWNlcylbJHtpfV0pYCk7XG4gICAgfVxuICB9XG5cbiAgY29uc3QgaTJvSW1wbCA9IHNoYXBlLmxlbmd0aCA8IDIgPyAnJyA6IGBcbiAgZm4gaWhfaTJvXyR7bmFtZX0oaW5kaWNlczogcHRyPGZ1bmN0aW9uLCAke2lUeXBlfT4pIC0+IHUzMiB7XG4gICAgcmV0dXJuICR7b2Zmc2V0cy5qb2luKCcrJyl9O1xuICB9YDtcblxuICBjb25zdCBpMm9FeHByZXNzaW9uID0gKHZhckluZGljZXM6IHN0cmluZywgaXNQdHI/OiBib29sZWFuKSA9PlxuICAgICAgc2hhcGUubGVuZ3RoIDwgMiA/IGAoJHtpc1B0ciA/ICcqJyA6ICcnfSR7dmFySW5kaWNlc30pYCA6IGBpaF9pMm9fJHtuYW1lfSgke2lzUHRyID8gJycgOiAnJid9JHt2YXJJbmRpY2VzfSlgO1xuXG4gIGNvbnN0IGluZGljZXNWYXJpYWJsZURlY2xhcmF0aW9uID0gKHY6IHN0cmluZywgaW5pdD86IHN0cmluZ1tdKSA9PlxuICAgICAgYHZhciAke3Z9OiR7aVR5cGV9JHtpbml0ID8gYD0ke2lUeXBlfSgke2luaXQuam9pbignLCcpfSlgIDogJyd9O2A7XG5cbiAgcmV0dXJuIHtvMmlJbXBsLCBvMmlDYWxsLCBpMm9JbXBsLCBpMm9FeHByZXNzaW9uLCBpbmRpY2VzVmFyaWFibGVEZWNsYXJhdGlvbiwgaVR5cGV9O1xufTtcblxuLyoqXG4gKiBBIFNoYWRlckhlbHBlciBpcyBhIGhlbHBlciBjbGFzcyBmb3IgZ2VuZXJhdGluZyBXR1NMIGNvZGUuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2hhZGVySGVscGVyIHtcbiAgbWFpblN0YXJ0KHdvcmtncm91cFNpemU/OiBudW1iZXJ8W251bWJlciwgbnVtYmVyLCBudW1iZXJdKTogc3RyaW5nO1xuICBndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKHNpemU6IHVua25vd24pOiBzdHJpbmc7XG59XG5cbmNsYXNzIFNoYWRlckhlbHBlckltcGwgaW1wbGVtZW50cyBTaGFkZXJIZWxwZXIge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIG5vcm1hbGl6ZWREaXNwYXRjaEdyb3VwOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0pIHt9XG4gIGd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMoc2l6ZTogbnVtYmVyfHN0cmluZyk6IHN0cmluZyB7XG4gICAgLy8gR3VhcmQgYWdhaW5zdCBvdXQtb2YtYm91bmRzIHdvcmsgZ3JvdXAgc2l6ZXNcbiAgICBjb25zdCBzaXplSW5Db2RlID0gdHlwZW9mIHNpemUgPT09ICdudW1iZXInID8gYCR7c2l6ZX11YCA6IHNpemU7XG4gICAgcmV0dXJuIGBpZiAoZ2xvYmFsX2lkeCA+PSAke3NpemVJbkNvZGV9KSB7IHJldHVybjsgfWA7XG4gIH1cbiAgbWFpblN0YXJ0KHdvcmtncm91cFNpemU6IG51bWJlcnxbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPSBXT1JLR1JPVVBfU0laRSkge1xuICAgIGNvbnN0IHdvcmtncm91cFNpemVYID0gdHlwZW9mIHdvcmtncm91cFNpemUgPT09ICdudW1iZXInID8gd29ya2dyb3VwU2l6ZSA6IHdvcmtncm91cFNpemVbMF07XG4gICAgY29uc3Qgd29ya2dyb3VwU2l6ZVkgPSB0eXBlb2Ygd29ya2dyb3VwU2l6ZSA9PT0gJ251bWJlcicgPyAxIDogd29ya2dyb3VwU2l6ZVsxXTtcbiAgICBjb25zdCB3b3JrZ3JvdXBTaXplWiA9IHR5cGVvZiB3b3JrZ3JvdXBTaXplID09PSAnbnVtYmVyJyA/IDEgOiB3b3JrZ3JvdXBTaXplWzJdO1xuXG4gICAgY29uc3QgaXMxRGltZW5zaW9uRGlzcGF0Y2ggPSB0aGlzLm5vcm1hbGl6ZWREaXNwYXRjaEdyb3VwWzFdID09PSAxICYmIHRoaXMubm9ybWFsaXplZERpc3BhdGNoR3JvdXBbMl0gPT09IDE7XG4gICAgY29uc3QgcGFyYW1MaXN0ID0gaXMxRGltZW5zaW9uRGlzcGF0Y2ggPyAnQGJ1aWx0aW4oZ2xvYmFsX2ludm9jYXRpb25faWQpIGdsb2JhbF9pZCA6IHZlYzM8dTMyPicgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYEBidWlsdGluKGxvY2FsX2ludm9jYXRpb25faW5kZXgpIGxvY2FsX2luZGV4IDogdTMyLFxuICAgIEBidWlsdGluKHdvcmtncm91cF9pZCkgd29ya2dyb3VwX2lkIDogdmVjMzx1MzI+YDtcbiAgICBjb25zdCBnbG9iYWxJZHhEZWZpbml0aW9uID0gaXMxRGltZW5zaW9uRGlzcGF0Y2ggP1xuICAgICAgICAnbGV0IGdsb2JhbF9pZHggPSBnbG9iYWxfaWQueDsnIDpcbiAgICAgICAgYGxldCBnbG9iYWxfaWR4ID0gKHdvcmtncm91cF9pZC56ICogJHt0aGlzLm5vcm1hbGl6ZWREaXNwYXRjaEdyb3VwWzBdICogdGhpcy5ub3JtYWxpemVkRGlzcGF0Y2hHcm91cFsxXX11ICtcbiAgICAgICAgICB3b3JrZ3JvdXBfaWQueSAqICR7dGhpcy5ub3JtYWxpemVkRGlzcGF0Y2hHcm91cFswXX11ICsgd29ya2dyb3VwX2lkLngpICogJHtcbiAgICAgICAgICAgIHdvcmtncm91cFNpemVYICogd29ya2dyb3VwU2l6ZVkgKiB3b3JrZ3JvdXBTaXplWn11ICsgbG9jYWxfaW5kZXg7YDtcblxuICAgIHJldHVybiBgQGNvbXB1dGUgQHdvcmtncm91cF9zaXplKCR7d29ya2dyb3VwU2l6ZVh9LCAke3dvcmtncm91cFNpemVZfSwgJHt3b3JrZ3JvdXBTaXplWn0pXG4gIGZuIG1haW4oJHtwYXJhbUxpc3R9KSB7XG4gICAgJHtnbG9iYWxJZHhEZWZpbml0aW9ufVxuICBgO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVTaGFkZXJIZWxwZXIgPSAoZGlzcGF0Y2hHcm91cDogW251bWJlciwgbnVtYmVyLCBudW1iZXJdKTogU2hhZGVySGVscGVyID0+XG4gICAgbmV3IFNoYWRlckhlbHBlckltcGwoZGlzcGF0Y2hHcm91cCk7XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtUZW5zb3JWaWV3fSBmcm9tICcuLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtTaGFwZVV0aWx9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHtHcHVEYXRhVHlwZSwgUHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGF9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtjcmVhdGVJbmRpY2VzSGVscGVyLCBTaGFkZXJIZWxwZXJ9IGZyb20gJy4vY29tbW9uJztcbmltcG9ydCB7Y2FsY3VsYXRlT3V0cHV0U2hhcGUsIENvbnZBdHRyaWJ1dGVzfSBmcm9tICcuL2NvbnYnO1xuaW1wb3J0IHtnZXRBY3RpY2F0aW9uU25pcHBldH0gZnJvbSAnLi9mdXNlLXV0aWxzJztcblxuY29uc3QgY3JlYXRlR3JvdXBlZENvbnZQcm9ncmFtTWV0YWRhdGEgPSAoaGFzQmlhczogYm9vbGVhbiwgY2FjaGVIaW50OiBzdHJpbmcpOiBQcm9ncmFtTWV0YWRhdGEgPT4gKHtcbiAgbmFtZTogJ0dyb3VwZWRDb252JyxcbiAgaW5wdXRUeXBlczogaGFzQmlhcyA/IFtHcHVEYXRhVHlwZS5kZWZhdWx0LCBHcHVEYXRhVHlwZS5kZWZhdWx0LCBHcHVEYXRhVHlwZS5kZWZhdWx0XSA6XG4gICAgICAgICAgICAgICAgICAgICAgICBbR3B1RGF0YVR5cGUuZGVmYXVsdCwgR3B1RGF0YVR5cGUuZGVmYXVsdF0sXG4gIGNhY2hlSGludFxufSk7XG5cbmNvbnN0IGNyZWF0ZUdyb3VwZWRDb252UHJvZ3JhbUluZm8gPVxuICAgIChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgbWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSwgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMsXG4gICAgIHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uPzogKHNoYXBlOiByZWFkb25seSBudW1iZXJbXSkgPT4gbnVtYmVyW10pOiBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICBjb25zdCBoYXNCaWFzID0gaW5wdXRzLmxlbmd0aCA+IDI7XG4gICAgICBjb25zdCBwcm9jZXNzQmlhcyA9IGhhc0JpYXMgPyAndmFsdWUgKz0gYltvdXRwdXRfY2hhbm5lbF07JyA6ICcnO1xuICAgICAgY29uc3QgeFNoYXBlID0gaW5wdXRzWzBdLmRpbXM7XG4gICAgICBjb25zdCB3U2hhcGUgPSBpbnB1dHNbMV0uZGltcztcbiAgICAgIGNvbnN0IG91dHB1dENoYW5uZWxzUGVyR3JvdXAgPSB3U2hhcGVbMF0gLyBhdHRyaWJ1dGVzLmdyb3VwO1xuXG4gICAgICBjb25zdCBkYXRhVHlwZSA9ICdmMzInOyAgLy8gVE9ETzogc3VwcG9ydCBvdGhlciBkYXRhIHR5cGVcbiAgICAgIGNvbnN0IHthY3RpdmF0aW9uRnVuY3Rpb24sIGFwcGx5QWN0aXZhdGlvbn0gPSBnZXRBY3RpY2F0aW9uU25pcHBldChhdHRyaWJ1dGVzKTtcbiAgICAgIGNvbnN0IGlucHV0U3RvcmFnZUJ1ZmZlcnNEZWNsYXJhdGlvbnMgPSBbXG4gICAgICAgIGBAZ3JvdXAoMCkgQGJpbmRpbmcoMCkgdmFyPHN0b3JhZ2UsIHJlYWQ+IHggOiBhcnJheTwke2RhdGFUeXBlfT47YCxcbiAgICAgICAgYEBncm91cCgwKSBAYmluZGluZygxKSB2YXI8c3RvcmFnZSwgcmVhZD4gdyA6IGFycmF5PCR7ZGF0YVR5cGV9PjtgXG4gICAgICBdO1xuICAgICAgaWYgKGhhc0JpYXMpIHtcbiAgICAgICAgaW5wdXRTdG9yYWdlQnVmZmVyc0RlY2xhcmF0aW9ucy5wdXNoKGBAZ3JvdXAoMCkgQGJpbmRpbmcoMikgdmFyPHN0b3JhZ2UsIHJlYWQ+IGIgOiBhcnJheTwke2RhdGFUeXBlfT47YCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGlzQ2hhbm5lbExhc3QgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnO1xuICAgICAgY29uc3Qgb3V0cHV0U2hhcGUgPSBjYWxjdWxhdGVPdXRwdXRTaGFwZShcbiAgICAgICAgICB4U2hhcGUsIHdTaGFwZSwgYXR0cmlidXRlcy5kaWxhdGlvbnMsIGF0dHJpYnV0ZXMucGFkcywgYXR0cmlidXRlcy5zdHJpZGVzLCBpc0NoYW5uZWxMYXN0KTtcbiAgICAgIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gICAgICBjb25zdCBvdXRwdXRJbmRpY2VzSGVscGVyID0gY3JlYXRlSW5kaWNlc0hlbHBlcignb3V0cHV0Jywgb3V0cHV0U2hhcGUpO1xuICAgICAgY29uc3QgeEluZGljZXNIZWxwZXIgPSBjcmVhdGVJbmRpY2VzSGVscGVyKCd4JywgeFNoYXBlKTtcbiAgICAgIGNvbnN0IHdJbmRpY2VzSGVscGVyID0gY3JlYXRlSW5kaWNlc0hlbHBlcigndycsIHdTaGFwZSk7XG5cbiAgICAgIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gYFxuICBjb25zdCBzdHJpZGVzOiB2ZWMyPHUzMj4gPSB2ZWMyKCR7YXR0cmlidXRlcy5zdHJpZGVzWzBdfXUsICR7YXR0cmlidXRlcy5zdHJpZGVzWzFdfXUpO1xuICBjb25zdCBwYWRzOiB2ZWMyPHUzMj4gPSB2ZWMyKCR7YXR0cmlidXRlcy5wYWRzWzBdfXUsICR7YXR0cmlidXRlcy5wYWRzWzFdfXUpO1xuXG4gICR7aW5wdXRTdG9yYWdlQnVmZmVyc0RlY2xhcmF0aW9ucy5qb2luKCdcXG4nKX1cbiAgQGdyb3VwKDApIEBiaW5kaW5nKCR7aW5wdXRTdG9yYWdlQnVmZmVyc0RlY2xhcmF0aW9ucy5sZW5ndGh9KSB2YXI8c3RvcmFnZSwgcmVhZF93cml0ZT4gb3V0cHV0IDogYXJyYXk8JHtkYXRhVHlwZX0+O1xuXG4gICR7YWN0aXZhdGlvbkZ1bmN0aW9ufVxuICAke291dHB1dEluZGljZXNIZWxwZXIubzJpSW1wbH1cbiAgJHt4SW5kaWNlc0hlbHBlci5pMm9JbXBsfVxuICAke3dJbmRpY2VzSGVscGVyLmkyb0ltcGx9XG5cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcyhvdXRwdXRTaXplKX1cblxuICAgICR7b3V0cHV0SW5kaWNlc0hlbHBlci5pbmRpY2VzVmFyaWFibGVEZWNsYXJhdGlvbignb3V0cHV0SW5kaWNlcycpfVxuICAgICR7b3V0cHV0SW5kaWNlc0hlbHBlci5vMmlDYWxsKCdnbG9iYWxfaWR4JywgJ291dHB1dEluZGljZXMnKX1cbiAgICBsZXQgYmF0Y2g6IHUzMiA9IG91dHB1dEluZGljZXNbMF07XG4gICAgbGV0IG91dHB1dF9jaGFubmVsOiB1MzIgPSBvdXRwdXRJbmRpY2VzWyR7aXNDaGFubmVsTGFzdCA/IDMgOiAxfV07XG4gICAgbGV0IHhSQ0Nvcm5lcjogdmVjMjx1MzI+ID0gdmVjMjx1MzI+KG91dHB1dEluZGljZXNbJHtpc0NoYW5uZWxMYXN0ID8gMSA6IDJ9XSwgb3V0cHV0SW5kaWNlc1ske1xuICAgICAgICAgIGlzQ2hhbm5lbExhc3QgPyAyIDogM31dKSAqIHN0cmlkZXMgLSBwYWRzO1xuICAgIGxldCBncm91cF9pZDogdTMyID0gb3V0cHV0X2NoYW5uZWwgLyAke291dHB1dENoYW5uZWxzUGVyR3JvdXB9dTtcblxuICAgIHZhciB2YWx1ZTogJHtkYXRhVHlwZX0gPSAke2RhdGFUeXBlfSgwKTtcbiAgICBmb3IgKHZhciB3SW5DaGFubmVsOiB1MzIgPSAwdTsgd0luQ2hhbm5lbCA8ICR7d1NoYXBlWzFdfXU7IHdJbkNoYW5uZWwrKykge1xuICAgICAgbGV0IGlucHV0X2NoYW5uZWwgPSBncm91cF9pZCAqICR7d1NoYXBlWzFdfXUgKyB3SW5DaGFubmVsO1xuICAgICAgZm9yICh2YXIgd0hlaWdodDogdTMyID0gMHU7IHdIZWlnaHQgPCAke3dTaGFwZVsyXX11OyB3SGVpZ2h0KyspIHtcbiAgICAgICAgbGV0IHhIZWlnaHQgPSB4UkNDb3JuZXIueCArIHdIZWlnaHQgKiAke2F0dHJpYnV0ZXMuZGlsYXRpb25zWzBdfXU7XG5cbiAgICAgICAgaWYgKHhIZWlnaHQgPCAwdSB8fCB4SGVpZ2h0ID49ICR7eFNoYXBlW2lzQ2hhbm5lbExhc3QgPyAxIDogMl19dSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yICh2YXIgd1dpZHRoOiB1MzIgPSAwdTsgd1dpZHRoIDwgJHt3U2hhcGVbM119dTsgd1dpZHRoKyspIHtcbiAgICAgICAgICBsZXQgeFdpZHRoID0geFJDQ29ybmVyLnkgKyB3V2lkdGggKiAke2F0dHJpYnV0ZXMuZGlsYXRpb25zWzFdfXU7XG4gICAgICAgICAgaWYgKHhXaWR0aCA8IDB1IHx8IHhXaWR0aCA+PSAke3hTaGFwZVtpc0NoYW5uZWxMYXN0ID8gMiA6IDNdfXUpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgIH1cblxuICAgICAgICAgICR7XG4gICAgICAgICAgeEluZGljZXNIZWxwZXIuaW5kaWNlc1ZhcmlhYmxlRGVjbGFyYXRpb24oXG4gICAgICAgICAgICAgICd4SW5kaWNlcycsXG4gICAgICAgICAgICAgIGlzQ2hhbm5lbExhc3QgPyBbJ2JhdGNoJywgJ3hIZWlnaHQnLCAneFdpZHRoJywgJ2lucHV0X2NoYW5uZWwnXSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdiYXRjaCcsICdpbnB1dF9jaGFubmVsJywgJ3hIZWlnaHQnLCAneFdpZHRoJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXSl9XG4gICAgICAgICAgbGV0IHhWYWwgPSB4WyR7eEluZGljZXNIZWxwZXIuaTJvRXhwcmVzc2lvbigneEluZGljZXMnKX1dO1xuICAgICAgICAgICR7XG4gICAgICAgICAgd0luZGljZXNIZWxwZXIuaW5kaWNlc1ZhcmlhYmxlRGVjbGFyYXRpb24oJ3dJbmRpY2VzJywgW1xuICAgICAgICAgICAgJ291dHB1dF9jaGFubmVsJywgJ3dJbkNoYW5uZWwnLCAnd0hlaWdodCcsICd3V2lkdGgnXG4gICAgICAgICAgXSl9XG4gICAgICAgICAgbGV0IHdWYWwgPSB3WyR7d0luZGljZXNIZWxwZXIuaTJvRXhwcmVzc2lvbignd0luZGljZXMnKX1dO1xuICAgICAgICAgIHZhbHVlICs9IHhWYWwqd1ZhbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICAke3Byb2Nlc3NCaWFzfVxuICAgICR7YXBwbHlBY3RpdmF0aW9ufVxuICAgIG91dHB1dFtnbG9iYWxfaWR4XSA9IHZhbHVlO1xuICB9YDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICBvdXRwdXRzOiBbe1xuICAgICAgICAgIGRpbXM6IHNxdWVlemVPdXRwdXRTaGFwZUZ1bmN0aW9uID8gc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24ob3V0cHV0U2hhcGUpIDogb3V0cHV0U2hhcGUsXG4gICAgICAgICAgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSxcbiAgICAgICAgICBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdFxuICAgICAgICB9XSxcbiAgICAgICAgZ2V0U2hhZGVyU291cmNlLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiAoKSA9PiAoe3g6IE1hdGguY2VpbChvdXRwdXRTaXplIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8pfSlcbiAgICAgIH07XG4gICAgfTtcblxuLyoqXG4gKiBuYWl2ZSBncm91cGVkIGNvbnYgaW1wbGVtZW50YXRpb24sIHN1cHBvcnRzIDFkLzJkIGNvbnZcbiAqIEBwYXJhbSBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbiAtIGFuIG9wdGlvbmFsIGZ1bmN0aW9uIHRvIHNxdWVlemUgdGhlIG91dHB1dCBzaGFwZSwgb25seSB1c2VkIGluIGNvbnYxZFxuICovXG5leHBvcnQgY29uc3QgY3JlYXRlR3JvdXBlZENvbnZQcm9ncmFtSW5mb0xvYWRlciA9XG4gICAgKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyxcbiAgICAgc3F1ZWV6ZU91dHB1dFNoYXBlRnVuY3Rpb24/OiAoc2hhcGU6IHJlYWRvbmx5IG51bWJlcltdKSA9PiBudW1iZXJbXSk6IFByb2dyYW1JbmZvTG9hZGVyID0+IHtcbiAgICAgIGNvbnN0IG1ldGFkYXRhID0gY3JlYXRlR3JvdXBlZENvbnZQcm9ncmFtTWV0YWRhdGEoaW5wdXRzLmxlbmd0aCA+IDIsIGF0dHJpYnV0ZXMuY2FjaGVLZXkpO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgIGdldDogKCkgPT4gY3JlYXRlR3JvdXBlZENvbnZQcm9ncmFtSW5mbyhpbnB1dHMsIG1ldGFkYXRhLCBhdHRyaWJ1dGVzLCBzcXVlZXplT3V0cHV0U2hhcGVGdW5jdGlvbilcbiAgICAgIH07XG4gICAgfTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0RhdGFUeXBlfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQge1RlbnNvclZpZXd9IGZyb20gJy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge1Bvb2xDb252VXRpbH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQge0F0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtDb21wdXRlQ29udGV4dH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge2NyZWF0ZUdyb3VwZWRDb252UHJvZ3JhbUluZm9Mb2FkZXJ9IGZyb20gJy4vY29udi1ncm91cGVkJztcbmltcG9ydCB7Y3JlYXRlQ29udjJETWF0TXVsUHJvZ3JhbUluZm9Mb2FkZXJ9IGZyb20gJy4vY29udjJkLW1tJztcbmltcG9ydCB7SW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcywgcGFyc2VJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzfSBmcm9tICcuL2Z1c2UtdXRpbHMnO1xuaW1wb3J0IHtjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbywgVHJhbnNwb3NlQXR0cmlidXRlcywgdHJhbnNwb3NlUHJvZ3JhbU1ldGFkYXRhfSBmcm9tICcuL3RyYW5zcG9zZSc7XG5cbmV4cG9ydCBjb25zdCBjYWxjdWxhdGVPdXRwdXRTaGFwZSA9XG4gICAgKGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBrZXJuZWxTaGFwZTogcmVhZG9ubHkgbnVtYmVyW10sIGRpbGF0aW9uczogcmVhZG9ubHkgbnVtYmVyW10sXG4gICAgIGFkanVzdFBhZHM6IHJlYWRvbmx5IG51bWJlcltdLCBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXSwgaXNDaGFubmVsTGFzdDogYm9vbGVhbik6IG51bWJlcltdID0+IHtcbiAgICAgIGNvbnN0IGJhdGNoU2l6ZSA9IGlucHV0U2hhcGVbMF07XG4gICAgICBjb25zdCBpbnB1dFNwYXRpYWxTaGFwZSA9IGlucHV0U2hhcGUuc2xpY2UoaXNDaGFubmVsTGFzdCA/IDEgOiAyLCBpc0NoYW5uZWxMYXN0ID8gMyA6IDQpO1xuICAgICAgY29uc3Qgc3BhdGlhbFJhbmsgPSBpbnB1dFNwYXRpYWxTaGFwZS5sZW5ndGg7XG4gICAgICBjb25zdCBvdXRDaGFubmVscyA9IGtlcm5lbFNoYXBlWzBdO1xuICAgICAgY29uc3Qga2VybmVsU3BhdGlhbFNoYXBlID0ga2VybmVsU2hhcGUuc2xpY2UoMik7XG4gICAgICBjb25zdCBkaWxhdGVkS2VybmVsU2hhcGUgPSBrZXJuZWxTcGF0aWFsU2hhcGUubWFwKCh2LCBpKSA9PiB2ICsgKHYgLSAxKSAqIChkaWxhdGlvbnNbaV0gLSAxKSk7XG4gICAgICBjb25zdCBpbnB1dFNwYXRpYWxTaGFwZVdpdGhQYWQgPSBpbnB1dFNwYXRpYWxTaGFwZS5tYXAoKHYsIGkpID0+IHYgKyBhZGp1c3RQYWRzW2ldICsgYWRqdXN0UGFkc1tpICsgc3BhdGlhbFJhbmtdKTtcbiAgICAgIGNvbnN0IG91dHB1dFNoYXBlID1cbiAgICAgICAgICBpbnB1dFNwYXRpYWxTaGFwZVdpdGhQYWQubWFwKCh2LCBpKSA9PiBNYXRoLmZsb29yKCh2IC0gZGlsYXRlZEtlcm5lbFNoYXBlW2ldICsgc3RyaWRlc1tpXSkgLyBzdHJpZGVzW2ldKSk7XG4gICAgICBvdXRwdXRTaGFwZS5zcGxpY2UoMCwgMCwgYmF0Y2hTaXplKTtcbiAgICAgIG91dHB1dFNoYXBlLnNwbGljZShpc0NoYW5uZWxMYXN0ID8gMyA6IDEsIDAsIG91dENoYW5uZWxzKTtcbiAgICAgIHJldHVybiBvdXRwdXRTaGFwZTtcbiAgICB9O1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbnZBdHRyaWJ1dGVzIGV4dGVuZHMgSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcywgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgYXV0b1BhZDogc3RyaW5nO1xuICByZWFkb25seSBkaWxhdGlvbnM6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSBmb3JtYXQ6ICdOSFdDJ3wnTkNIVyc7XG4gIHJlYWRvbmx5IGdyb3VwOiBudW1iZXI7XG4gIHJlYWRvbmx5IGtlcm5lbFNoYXBlOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgcGFkczogcmVhZG9ubHkgbnVtYmVyW107XG4gIHJlYWRvbmx5IHN0cmlkZXM6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSB3SXNDb25zdDogYm9vbGVhbjtcbn1cblxuLy8gZm9yIHRyYW5zcG9zaW5nIHdlaWdodCB0ZW5zb3IgZnJvbSBbTSwgQy9ncm91cCwgS0gsIEtXXSB0byBbS0gsIEtXLCBDL2dyb3VwLCBNXVxuY29uc3Qgd2VpZ2h0VHJhbnNwb3NlQXR0cmlidXRlOiBUcmFuc3Bvc2VBdHRyaWJ1dGVzID0gY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5KHtwZXJtOiBbMiwgMywgMSwgMF19KTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGF0dHJpYnV0ZXM6IENvbnZBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIC8vIFJlZmVyIHRvIHRoZSBiZWxvdyBsaW5rIGZvciBhbGwgaW5wdXQgY2hlY2tzXG4gIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9vbm54L29ubngvYmxvYi9tYXN0ZXIvZG9jcy9PcGVyYXRvcnMubWQjQ29udlxuICBpZiAoIWlucHV0cyB8fCAoaW5wdXRzLmxlbmd0aCAhPT0gMiAmJiBpbnB1dHMubGVuZ3RoICE9PSAzKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ29udiByZXF1aXJlcyAyIG9yIDMgaW5wdXRzJyk7XG4gIH1cblxuICAvLyBUT0RPIDogTmVlZCB0byBhZGQgc3VwcG9ydCBmb3IgbXVsdGktZGltZW5zaW9uYWwgY29udlxuICBpZiAoaW5wdXRzWzBdLmRpbXMubGVuZ3RoICE9PSA0ICYmIGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gMykge1xuICAgIHRocm93IG5ldyBFcnJvcignY3VycmVudGx5IG9ubHkgc3VwcG9ydCBjb252IDFEIGFuZCAyRCcpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS5kaW1zLmxlbmd0aCAhPT0gaW5wdXRzWzFdLmRpbXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdmaWx0ZXIgZG9lcyBub3QgaGF2ZSBzYW1lIGRpbWVuc2lvbiBhcyBpbnB1dCcpO1xuICB9XG5cbiAgLy8gRklMVEVSX0lOX0NIQU5ORUwgc2hvdWxkIGJlIGVxdWFsIHRvIERBVEFfQ0hBTk5FTFxuICBjb25zdCBkYXRhQ2hhbm5lbCA9IGlucHV0c1swXS5kaW1zW2F0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQycgPyBpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAxIDogMV07XG4gIGNvbnN0IGZpbHRlckluQ2hhbm5lbCA9IGlucHV0c1sxXS5kaW1zWzFdICogYXR0cmlidXRlcy5ncm91cDtcbiAgaWYgKGRhdGFDaGFubmVsICE9PSBmaWx0ZXJJbkNoYW5uZWwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZJTFRFUl9JTl9DSEFOTkVMIHNob3VsZCBiZSBlcXVhbCB0byBEQVRBX0NIQU5ORUwnKTtcbiAgfVxuXG4gIC8vIGlmIGJpYXMgaXMgcHJvdmlkZWQgaXQgc2hvdWxkIGJlIDFEIGFuZCB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIHNob3VsZCBiZSBlcXVhbCB0byB0aGUgbnVtYmVyIG9mIGZlYXR1cmUgbWFwc1xuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiAoaW5wdXRzWzJdLmRpbXMubGVuZ3RoICE9PSAxIHx8IGlucHV0c1sxXS5kaW1zWzBdICE9PSBpbnB1dHNbMl0uZGltc1swXSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgYmlhcycpO1xuICB9XG5cbiAgY29uc3Qgc3BhdGlhbFJhbmsgPSBpbnB1dHNbMF0uZGltcy5sZW5ndGggLSAyO1xuICAvLyB3cm9uZyBkaWxhdGlvbnMgZGltZW5zaW9uXG4gIGlmIChhdHRyaWJ1dGVzLmRpbGF0aW9ucy5sZW5ndGggIT09IHNwYXRpYWxSYW5rKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBkaWxhdGlvbnMgc2hvdWxkIGJlICR7c3BhdGlhbFJhbmt9RGApO1xuICB9XG5cbiAgLy8gV3Jvbmcgc3RyaWRlcyBkaW1lbnNpb25cbiAgaWYgKGF0dHJpYnV0ZXMuc3RyaWRlcy5sZW5ndGggIT09IHNwYXRpYWxSYW5rKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBzdHJpZGVzIHNob3VsZCBiZSAke3NwYXRpYWxSYW5rfURgKTtcbiAgfVxuXG4gIC8vIFdyb25nIHBhZHMgZGltZW5zaW9uXG4gIGlmIChhdHRyaWJ1dGVzLnBhZHMubGVuZ3RoICE9PSBzcGF0aWFsUmFuayAqIDIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYHBhZHMgc2hvdWxkIGJlICR7c3BhdGlhbFJhbmsgKiAyfURgKTtcbiAgfVxuXG4gIC8vIGlmIGtlcm5lbFNoYXBlIGlzIHNwZWNpZmllZCwgaXQncyBkYXRhIGxlbmd0aCBtdXN0IGJlIDIgbGVzcyB0aGFuIGRpbXMgbGVuZ3RoIG9mIHRoZSB3ZWlnaHRzIHRlbnNvclxuICAvLyAodGhlIGZpcnN0IDIgZGltcyBhcmUgYmF0Y2hfc2l6ZSBhbmQgY2hhbm5lbHMpXG4gIGlmIChhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCAhPT0gMCAmJiBhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlLmxlbmd0aCAhPT0gaW5wdXRzWzFdLmRpbXMubGVuZ3RoIC0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBrZXJuZWwgc2hhcGUnKTtcbiAgfVxuXG4gIC8vIFRPRE8gOiBOZWVkIHRvIGFkZCBzdXBwb3J0IGZvciBmbG9hdDY0XG4gIGlmIChpbnB1dHNbMF0uZGF0YVR5cGUgIT09IERhdGFUeXBlLmZsb2F0IHx8IGlucHV0c1sxXS5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuZmxvYXQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbnYgaW5wdXQoWCxXKSBzaG91bGQgYmUgZmxvYXQgdGVuc29yJyk7XG4gIH1cblxuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiBpbnB1dHNbMl0uZGF0YVR5cGUgIT09IERhdGFUeXBlLmZsb2F0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdDb252IGlucHV0KGJpYXMpIHNob3VsZCBiZSBmbG9hdCB0ZW5zb3InKTtcbiAgfVxufTtcblxuY29uc3QgZ2V0QWRqdXN0ZWRDb252QXR0cmlidXRlcyA9IDxUIGV4dGVuZHMgQ29udkF0dHJpYnV0ZXM+KGF0dHJpYnV0ZXM6IFQsIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogVCA9PiB7XG4gIGNvbnN0IGtlcm5lbFNoYXBlID0gYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5zbGljZSgpO1xuICAvLyBpZiBrZXJuZWxTaGFwZSBpcyBub3Qgc3BlY2lmaWVkIGluIHRoZSBhdHRyaWJ1dGVzIG9mIHRoaXMgb3AsIGluZmVyIGl0IGZyb20gdGhlIHdlaWdodCB0ZW5zb3IgZGltc1xuICBmb3IgKGxldCBpID0gMjsgaSA8IGlucHV0c1sxXS5kaW1zLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKGtlcm5lbFNoYXBlW2kgLSAyXSA9PT0gMCkge1xuICAgICAga2VybmVsU2hhcGVbaSAtIDJdID0gaW5wdXRzWzFdLmRpbXNbaV07XG4gICAgfVxuICB9XG4gIGNvbnN0IHBhZHMgPSBhdHRyaWJ1dGVzLnBhZHMuc2xpY2UoKTtcbiAgUG9vbENvbnZVdGlsLmFkanVzdFBhZHNCYXNlZE9uQXV0b1BhZChcbiAgICAgIGlucHV0c1swXS5kaW1zLCBhdHRyaWJ1dGVzLnN0cmlkZXMsIGF0dHJpYnV0ZXMuZGlsYXRpb25zLCBrZXJuZWxTaGFwZSwgcGFkcywgYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJyxcbiAgICAgIGF0dHJpYnV0ZXMuYXV0b1BhZCk7XG5cbiAgLy8gYWx3YXlzIHJldHVybiBhIG5ldyBvYmplY3Qgc28gZG9lcyBub3QgbW9kaWZ5IHRoZSBvcmlnaW5hbCBhdHRyaWJ1dGVzXG4gIGNvbnN0IG5ld0F0dHJpYnV0ZXM6IFQgPSBPYmplY3QuYXNzaWduKHt9LCBhdHRyaWJ1dGVzKTtcbiAgT2JqZWN0LmFzc2lnbihuZXdBdHRyaWJ1dGVzLCB7a2VybmVsU2hhcGUsIHBhZHMsIGNhY2hlS2V5OiBhdHRyaWJ1dGVzLmNhY2hlS2V5fSk7XG4gIHJldHVybiBuZXdBdHRyaWJ1dGVzO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlQ29udkF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBDb252QXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGFjdGl2YXRpb25BdHRyaWJ1dGVzID0gcGFyc2VJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzKGF0dHJpYnV0ZXMpO1xuICAvLyBUT0RPIDogTWFrZSB0aGlzIGdlbmVyaWMgZW5vdWdoIHRvIGNvbXB1dGUgZGVmYXVsdCBhdHRyaWJ1dGVzIGZvciBtdWx0aS1kaW1lbnNpb25hbCBjb252XG4gIGNvbnN0IGZvcm1hdCA9IGF0dHJpYnV0ZXMuZm9ybWF0IGFzICdOSFdDJyB8ICdOQ0hXJztcbiAgY29uc3QgYXV0b1BhZCA9IFsnTk9UU0VUJywgJ1ZBTElEJywgJ1NBTUVfVVBQRVInLCAnU0FNRV9MT1dFUiddW2F0dHJpYnV0ZXMuYXV0b19wYWQgYXMgbnVtYmVyXTtcbiAgY29uc3QgZGlsYXRpb25zID0gYXR0cmlidXRlcy5kaWxhdGlvbnMgYXMgW251bWJlciwgbnVtYmVyXTtcbiAgY29uc3QgZ3JvdXAgPSBhdHRyaWJ1dGVzLmdyb3VwIGFzIG51bWJlcjtcbiAgY29uc3Qga2VybmVsU2hhcGUgPSBhdHRyaWJ1dGVzLmtlcm5lbF9zaGFwZSBhcyBbbnVtYmVyLCBudW1iZXJdO1xuICBjb25zdCBwYWRzID0gYXR0cmlidXRlcy5wYWRzIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdO1xuICBjb25zdCBzdHJpZGVzID0gYXR0cmlidXRlcy5zdHJpZGVzIGFzIFtudW1iZXIsIG51bWJlcl07XG4gIGNvbnN0IHdJc0NvbnN0ID0gKGF0dHJpYnV0ZXMud19pc19jb25zdCBhcyAoKSA9PiBib29sZWFuKSgpO1xuXG4gIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoXG4gICAgICB7YXV0b1BhZCwgZm9ybWF0LCBkaWxhdGlvbnMsIGdyb3VwLCBrZXJuZWxTaGFwZSwgcGFkcywgc3RyaWRlcywgd0lzQ29uc3QsIC4uLmFjdGl2YXRpb25BdHRyaWJ1dGVzfSk7XG59O1xuXG5jb25zdCBjb252MmQgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb25zdCBhZGp1c3RlZEF0dHJpYnV0ZXMgPSBnZXRBZGp1c3RlZENvbnZBdHRyaWJ1dGVzKGF0dHJpYnV0ZXMsIGlucHV0cyk7XG5cbiAgLy8gY2hlY2sgYXR0cmlidXRlc1xuXG4gIGNvbnN0IGhhc0JpYXMgPSBpbnB1dHMubGVuZ3RoID09PSAzO1xuICAvLyBjb25zdCBoYXNQcmVsdUFjdGl2YXRpb25XZWlnaHRzID0gZmFsc2U7IC8qIFRPRE86IGFkZCBzdXBwb3J0IGZvciBwcmVsdSBhY3RpdmF0aW9uIHdlaWdodHMgKi9cbiAgY29uc3QgaXNDaGFubmVsc0xhc3QgPSBhdHRyaWJ1dGVzLmZvcm1hdCA9PT0gJ05IV0MnO1xuXG4gIC8vIGNvbnN0IGJhdGNoU2l6ZSA9IGNvbnRleHQuaW5wdXRzWzBdLmRpbXNbMF07XG4gIGNvbnN0IGlucHV0SGVpZ2h0ID0gaW5wdXRzWzBdLmRpbXNbaXNDaGFubmVsc0xhc3QgPyAxIDogMl07XG4gIGNvbnN0IGlucHV0V2lkdGggPSBpbnB1dHNbMF0uZGltc1tpc0NoYW5uZWxzTGFzdCA/IDIgOiAzXTtcbiAgY29uc3QgaW5wdXRDaGFubmVscyA9IGlucHV0c1swXS5kaW1zW2lzQ2hhbm5lbHNMYXN0ID8gMyA6IDFdO1xuICBjb25zdCB3ZWlnaHRIZWlnaHQgPSBpbnB1dHNbMV0uZGltc1syXTtcbiAgY29uc3Qgd2VpZ2h0V2lkdGggPSBpbnB1dHNbMV0uZGltc1szXTtcblxuICBjb25zdCBvdXRwdXRTaGFwZSA9IGNhbGN1bGF0ZU91dHB1dFNoYXBlKFxuICAgICAgaW5wdXRzWzBdLmRpbXMsIGlucHV0c1sxXS5kaW1zLCBhdHRyaWJ1dGVzLmRpbGF0aW9ucywgYWRqdXN0ZWRBdHRyaWJ1dGVzLnBhZHMsIGF0dHJpYnV0ZXMuc3RyaWRlcyxcbiAgICAgIGlzQ2hhbm5lbHNMYXN0KTtcbiAgY29uc3Qgb3V0SGVpZ2h0ID0gb3V0cHV0U2hhcGVbaXNDaGFubmVsc0xhc3QgPyAxIDogMl07XG4gIGNvbnN0IG91dFdpZHRoID0gb3V0cHV0U2hhcGVbaXNDaGFubmVsc0xhc3QgPyAyIDogM107XG4gIGNvbnN0IG91dENoYW5uZWxzID0gb3V0cHV0U2hhcGVbaXNDaGFubmVsc0xhc3QgPyAzIDogMV07XG5cbiAgY29uc3Qgc2FtZVNpemUgPVxuICAgICAgaXNDaGFubmVsc0xhc3QgJiYgd2VpZ2h0SGVpZ2h0ID09PSBpbnB1dEhlaWdodCAmJiB3ZWlnaHRXaWR0aCA9PT0gaW5wdXRXaWR0aCAmJiBhdHRyaWJ1dGVzLmF1dG9QYWQgPT09ICdWQUxJRCc7XG4gIGlmIChzYW1lU2l6ZSB8fFxuICAgICAgKHdlaWdodEhlaWdodCA9PT0gMSAmJiB3ZWlnaHRXaWR0aCA9PT0gMSAmJiBhdHRyaWJ1dGVzLmRpbGF0aW9uc1swXSA9PT0gMSAmJiBhdHRyaWJ1dGVzLmRpbGF0aW9uc1sxXSA9PT0gMSAmJlxuICAgICAgIGF0dHJpYnV0ZXMuc3RyaWRlc1swXSA9PT0gMSAmJiBhdHRyaWJ1dGVzLnN0cmlkZXNbMV0gPT09IDEgJiZcbiAgICAgICAoYXR0cmlidXRlcy5hdXRvUGFkID09PSAnU0FNRV9VUFBFUicgfHwgYXR0cmlidXRlcy5hdXRvUGFkID09PSAnU0FNRV9MT1dFUicgfHxcbiAgICAgICAgYXR0cmlidXRlcy5hdXRvUGFkID09PSAnVkFMSUQnKSkpIHtcbiAgICAvLyBUT0RPOiBpbXBsZW1lbnQgY29udjJkQnlNYXRNdWwoKVxuICAgIGNvbnRleHQuY29tcHV0ZShjcmVhdGVHcm91cGVkQ29udlByb2dyYW1JbmZvTG9hZGVyKGlucHV0cywgYWRqdXN0ZWRBdHRyaWJ1dGVzKSk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKCFpc0NoYW5uZWxzTGFzdCB8fCBhdHRyaWJ1dGVzLmdyb3VwICE9PSAxKSB7XG4gICAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUdyb3VwZWRDb252UHJvZ3JhbUluZm9Mb2FkZXIoaW5wdXRzLCBhZGp1c3RlZEF0dHJpYnV0ZXMpKTtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBUT0RPOiBpbXBsZW1lbnQgY29udjJkV2l0aEltMkNvbCgpXG5cbiAgY29uc3QgZGltQU91dGVyID0gaXNDaGFubmVsc0xhc3QgPyBvdXRIZWlnaHQgKiBvdXRXaWR0aCA6IG91dENoYW5uZWxzO1xuICBjb25zdCBkaW1CT3V0ZXIgPSBpc0NoYW5uZWxzTGFzdCA/IG91dENoYW5uZWxzIDogb3V0SGVpZ2h0ICogb3V0V2lkdGg7XG4gIGNvbnN0IGRpbUlubmVyID0gd2VpZ2h0SGVpZ2h0ICogd2VpZ2h0V2lkdGggKiBpbnB1dENoYW5uZWxzO1xuXG4gIGNvbnN0IHNlcXVlbnRpYWxBY2Nlc3NCeVRocmVhZHMgPSAvKiBiYWNrZW5kLmFkYXB0ZXJJbmZvLmlzSW50ZWwoKSAqLyB0cnVlO1xuXG4gIC8vIFNURVAuMTogdHJhbnNwb3NlIHdlaWdodFxuICBjb25zdCB0cmFuc3Bvc2VkV2VpZ2h0ID0gKGNvbnRleHQuY3VzdG9tRGF0YS53VCBhcyBUZW5zb3JWaWV3IHwgdW5kZWZpbmVkKSA/P1xuICAgICAgY29udGV4dC5jb21wdXRlKFxuICAgICAgICAgIHtcbiAgICAgICAgICAgIC4uLnRyYW5zcG9zZVByb2dyYW1NZXRhZGF0YSxcbiAgICAgICAgICAgIGNhY2hlSGludDogd2VpZ2h0VHJhbnNwb3NlQXR0cmlidXRlLmNhY2hlS2V5LFxuICAgICAgICAgICAgZ2V0OiAoKSA9PiBjcmVhdGVUcmFuc3Bvc2VQcm9ncmFtSW5mbyhpbnB1dHNbMV0sIHdlaWdodFRyYW5zcG9zZUF0dHJpYnV0ZS5wZXJtKVxuICAgICAgICAgIH0sXG4gICAgICAgICAge2lucHV0czogWzFdLCBvdXRwdXRzOiBbYXR0cmlidXRlcy53SXNDb25zdCA/IC0yIDogLTFdfSlbMF07XG4gIGlmIChhdHRyaWJ1dGVzLndJc0NvbnN0ICYmICFjb250ZXh0LmN1c3RvbURhdGEud1QpIHtcbiAgICBjb250ZXh0LmN1c3RvbURhdGEud1QgPSB0cmFuc3Bvc2VkV2VpZ2h0O1xuICB9XG5cbiAgLy8gU1RFUC4yOiBwcmVwYXJlIHJlc2hhcGVkIGlucHV0c1xuICBjb25zdCBjb252SW5wdXRzID0gW2lucHV0c1swXSwgdHJhbnNwb3NlZFdlaWdodF07XG4gIGlmIChoYXNCaWFzKSB7XG4gICAgaWYgKCFpc0NoYW5uZWxzTGFzdCAmJiBpbnB1dHNbMl0uZGltcy5sZW5ndGggPT09IDEpIHtcbiAgICAgIGNvbnZJbnB1dHMucHVzaChpbnB1dHNbMl0ucmVzaGFwZShbaW5wdXRzWzJdLmRpbXNbMF0sIDEsIDFdKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnZJbnB1dHMucHVzaChpbnB1dHNbMl0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIFNURVAuMzogY29tcHV0ZSBtYXRtdWxcbiAgY29udGV4dC5jb21wdXRlKFxuICAgICAgY3JlYXRlQ29udjJETWF0TXVsUHJvZ3JhbUluZm9Mb2FkZXIoXG4gICAgICAgICAgY29udklucHV0cywgYWRqdXN0ZWRBdHRyaWJ1dGVzLCBvdXRwdXRTaGFwZSwgZGltQU91dGVyLCBkaW1CT3V0ZXIsIGRpbUlubmVyLCBoYXNCaWFzLFxuICAgICAgICAgIHNlcXVlbnRpYWxBY2Nlc3NCeVRocmVhZHMpLFxuICAgICAge2lucHV0czogY29udklucHV0c30pO1xufTtcblxuY29uc3QgY29udjFkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICAvLyBleHRlbmQgdGhlIGlucHV0IHRvIDJEIGJ5IGFkZGluZyBIIGRpbWVuc2lvblxuICBjb25zdCBpc0NoYW5uZWxMYXN0ID0gYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJztcbiAgY29uc3QgaW5wdXRzID0gW1xuICAgIGNvbnRleHQuaW5wdXRzWzBdLnJlc2hhcGUoXG4gICAgICAgIGlzQ2hhbm5lbExhc3QgP1xuICAgICAgICAgICAgLy8gW04sIFcsIENdIC0+IFtOLCBIPTEsIFcsIENdXG4gICAgICAgICAgICBbY29udGV4dC5pbnB1dHNbMF0uZGltc1swXSwgMSwgY29udGV4dC5pbnB1dHNbMF0uZGltc1sxXSwgY29udGV4dC5pbnB1dHNbMF0uZGltc1syXV0gOlxuICAgICAgICAgICAgLy8gW04sIEMsIFddIC0+IFtOLCBDLCBIPTEsIFddXG4gICAgICAgICAgICBbY29udGV4dC5pbnB1dHNbMF0uZGltc1swXSwgY29udGV4dC5pbnB1dHNbMF0uZGltc1sxXSwgMSwgY29udGV4dC5pbnB1dHNbMF0uZGltc1syXV0pLFxuICAgIC8vW0ZJTFRFUl9PVVRfQ0hBTk5FTCwgRklMVEVSX0lOX0NIQU5ORUwsIGtXXSAtPiBbRklMVEVSX09VVF9DSEFOTkVMLCBGSUxURVJfSU5fQ0hBTk5FTCwga0g9MSwga1ddXG4gICAgY29udGV4dC5pbnB1dHNbMV0ucmVzaGFwZShbY29udGV4dC5pbnB1dHNbMV0uZGltc1swXSwgY29udGV4dC5pbnB1dHNbMV0uZGltc1sxXSwgMSwgY29udGV4dC5pbnB1dHNbMV0uZGltc1syXV0pXG4gIF07XG4gIGlmIChjb250ZXh0LmlucHV0cy5sZW5ndGggPT09IDMpIHtcbiAgICBpbnB1dHMucHVzaChjb250ZXh0LmlucHV0c1syXSk7XG4gIH1cbiAgY29uc3QgcGFkcyA9IFswLCBhdHRyaWJ1dGVzLnBhZHNbMF0sIDAsIGF0dHJpYnV0ZXMucGFkc1sxXV07XG4gIGNvbnN0IHN0cmlkZXMgPSBbMV0uY29uY2F0KGF0dHJpYnV0ZXMuc3RyaWRlcyk7XG4gIGNvbnN0IGRpbGF0aW9ucyA9IFsxXS5jb25jYXQoYXR0cmlidXRlcy5kaWxhdGlvbnMpO1xuICBjb25zdCBrZXJuZWxTaGFwZSA9IFsxXS5jb25jYXQoYXR0cmlidXRlcy5rZXJuZWxTaGFwZSk7XG4gIGNvbnN0IGFkanVzdGVkQXR0cmlidXRlcyA9IGdldEFkanVzdGVkQ29udkF0dHJpYnV0ZXMoey4uLmF0dHJpYnV0ZXMsIHBhZHMsIHN0cmlkZXMsIGRpbGF0aW9ucywga2VybmVsU2hhcGV9LCBpbnB1dHMpO1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlR3JvdXBlZENvbnZQcm9ncmFtSW5mb0xvYWRlcihcbiAgICAgIGlucHV0cywgYWRqdXN0ZWRBdHRyaWJ1dGVzLFxuICAgICAgb3V0cHV0U2hhcGUgPT4gaXNDaGFubmVsTGFzdCA/IFtvdXRwdXRTaGFwZVswXSwgb3V0cHV0U2hhcGVbMl0sIG91dHB1dFNoYXBlWzNdXSA6IFtdKSk7XG59O1xuXG5leHBvcnQgY29uc3QgY29udiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogQ29udkF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpOyAgLy8gY3VycmVudGx5IHdpbGwgZmFpbCBpZiBub3QgY29udjFELzJEXG4gIGlmIChjb250ZXh0LmlucHV0c1swXS5kaW1zLmxlbmd0aCA9PT0gMykge1xuICAgIGNvbnYxZChjb250ZXh0LCBhdHRyaWJ1dGVzKTtcbiAgfSBlbHNlIHtcbiAgICBjb252MmQoY29udGV4dCwgY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpO1xuICB9XG59O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7VGVuc29yVmlld30gZnJvbSAnLi4vLi4vdGVuc29yJztcbmltcG9ydCB7R3B1RGF0YVR5cGUsIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGF9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtjcmVhdGVDb252MkRNYXRNdWxQcm9ncmFtSW5mb30gZnJvbSAnLi8zcmQtcGFydHkvY29udjJkX21tX3dlYmdwdSc7XG5pbXBvcnQge0NvbnZBdHRyaWJ1dGVzfSBmcm9tICcuL2NvbnYnO1xuXG5cbmNvbnN0IGNyZWF0ZUNvbnYyRE1hdE11bFByb2dyYW1NZXRhZGF0YSA9IChoYXNCaWFzOiBib29sZWFuLCBjYWNoZUhpbnQ6IHN0cmluZyk6IFByb2dyYW1NZXRhZGF0YSA9PiAoe1xuICBuYW1lOiAnQ29udjJETWF0TXVsJyxcbiAgaW5wdXRUeXBlczogaGFzQmlhcyA/IFtHcHVEYXRhVHlwZS5kZWZhdWx0LCBHcHVEYXRhVHlwZS5kZWZhdWx0LCBHcHVEYXRhVHlwZS5kZWZhdWx0XSA6XG4gICAgICAgICAgICAgICAgICAgICAgICBbR3B1RGF0YVR5cGUuZGVmYXVsdCwgR3B1RGF0YVR5cGUuZGVmYXVsdF0sXG4gIGNhY2hlSGludFxufSk7XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVDb252MkRNYXRNdWxQcm9ncmFtSW5mb0xvYWRlciA9XG4gICAgKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdLCBhdHRyaWJ1dGVzOiBDb252QXR0cmlidXRlcywgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBkaW1BT3V0ZXI6IG51bWJlcixcbiAgICAgZGltQk91dGVyOiBudW1iZXIsIGRpbUlubmVyOiBudW1iZXIsIGhhc0JpYXM6IGJvb2xlYW4sIHNlcXVlbnRpYWxBY2Nlc3NCeVRocmVhZHM6IGJvb2xlYW4pOiBQcm9ncmFtSW5mb0xvYWRlciA9PiB7XG4gICAgICBjb25zdCBtZXRhZGF0YSA9IGNyZWF0ZUNvbnYyRE1hdE11bFByb2dyYW1NZXRhZGF0YShoYXNCaWFzLCBhdHRyaWJ1dGVzLmNhY2hlS2V5KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgICBnZXQ6ICgpID0+IGNyZWF0ZUNvbnYyRE1hdE11bFByb2dyYW1JbmZvKFxuICAgICAgICAgICAgaW5wdXRzLCBtZXRhZGF0YSwgYXR0cmlidXRlcywgb3V0cHV0U2hhcGUsIGRpbUFPdXRlciwgZGltQk91dGVyLCBkaW1Jbm5lciwgaGFzQmlhcyxcbiAgICAgICAgICAgIHNlcXVlbnRpYWxBY2Nlc3NCeVRocmVhZHMpXG4gICAgICB9O1xuICAgIH07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtNQVhfQ0xJUCwgTUlOX0NMSVB9IGZyb20gJy4uLy4uL3V0aWwnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMge1xuICByZWFkb25seSBhY3RpdmF0aW9uOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNsaXBNaW4/OiBudW1iZXI7XG4gIHJlYWRvbmx5IGNsaXBNYXg/OiBudW1iZXI7XG4gIHJlYWRvbmx5IGFjdGl2YXRpb25DYWNoZUtleTogc3RyaW5nO1xufVxuXG5leHBvcnQgY29uc3QgZ2V0QWN0aWNhdGlvblNuaXBwZXQgPVxuICAgIChhdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzKToge2FjdGl2YXRpb25GdW5jdGlvbjogc3RyaW5nOyBhcHBseUFjdGl2YXRpb246IHN0cmluZ30gPT4ge1xuICAgICAgc3dpdGNoIChhdHRyaWJ1dGVzLmFjdGl2YXRpb24pIHtcbiAgICAgICAgY2FzZSAnUmVsdSc6XG4gICAgICAgICAgcmV0dXJuIHthY3RpdmF0aW9uRnVuY3Rpb246ICcnLCBhcHBseUFjdGl2YXRpb246ICd2YWx1ZSA9IG1heCh2YWx1ZSwgMC4wKTsnfTtcbiAgICAgICAgY2FzZSAnU2lnbW9pZCc6XG4gICAgICAgICAgcmV0dXJuIHthY3RpdmF0aW9uRnVuY3Rpb246ICcnLCBhcHBseUFjdGl2YXRpb246ICd2YWx1ZSA9ICgxLjAgLyAoMS4wICsgZXhwKC12YWx1ZSkpKTsnfTtcbiAgICAgICAgY2FzZSAnQ2xpcCc6XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGFjdGl2YXRpb25GdW5jdGlvbjpcbiAgICAgICAgICAgICAgICBgY29uc3QgY2xpcF9taW5fPWYzMigke2F0dHJpYnV0ZXMuY2xpcE1pbiF9KTtjb25zdCBjbGlwX21heF89ZjMyKCR7YXR0cmlidXRlcy5jbGlwTWF4IX0pO2AsXG4gICAgICAgICAgICBhcHBseUFjdGl2YXRpb246ICd2YWx1ZSA9IGNsYW1wKHZhbHVlLCBjbGlwX21pbl8sIGNsaXBfbWF4Xyk7J1xuICAgICAgICAgIH07XG4gICAgICAgICAgLy8gVE9ETzogYWRkaW5nIG90aGVyIGFjdGl2YXRpb25zIHRoYXQgY2FuIGJlIGZ1c2VkLlxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybiB7YWN0aXZhdGlvbkZ1bmN0aW9uOiAnJywgYXBwbHlBY3RpdmF0aW9uOiAnJ307XG4gICAgICB9XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlSW50ZXJuYWxBY3RpdmF0aW9uQXR0cmlidXRlcyA9XG4gICAgKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+fHVuZGVmaW5lZCk6IEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXMgPT4ge1xuICAgICAgY29uc3QgYWN0aXZhdGlvbiA9IGF0dHJpYnV0ZXM/LmFjdGl2YXRpb24gYXMgc3RyaW5nIHx8ICcnO1xuXG4gICAgICBpZiAoYWN0aXZhdGlvbiA9PT0gJ0NsaXAnKSB7XG4gICAgICAgIGNvbnN0IFtjbGlwTWluLCBjbGlwTWF4XSA9IGF0dHJpYnV0ZXM/LmFjdGl2YXRpb25fcGFyYW1zIGFzIFtudW1iZXIsIG51bWJlcl0gfHwgW01JTl9DTElQLCBNQVhfQ0xJUF07XG4gICAgICAgIHJldHVybiB7YWN0aXZhdGlvbiwgY2xpcE1heCwgY2xpcE1pbiwgYWN0aXZhdGlvbkNhY2hlS2V5OiBgJHthY3RpdmF0aW9ufToke2NsaXBNaW59LCR7Y2xpcE1heH1gfTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB7YWN0aXZhdGlvbiwgYWN0aXZhdGlvbkNhY2hlS2V5OiBhY3RpdmF0aW9ufTtcbiAgICB9O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7RGF0YVR5cGV9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7VGVuc29yVmlld30gZnJvbSAnLi4vLi4vdGVuc29yJztcbmltcG9ydCB7R2VtbVV0aWwsIFNoYXBlVXRpbH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQge0F0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtDb21wdXRlQ29udGV4dCwgR3B1RGF0YVR5cGUsIFByb2dyYW1JbmZvLCBQcm9ncmFtSW5mb0xvYWRlciwgUHJvZ3JhbU1ldGFkYXRhfSBmcm9tICcuLi90eXBlcyc7XG5cbmltcG9ydCB7U2hhZGVySGVscGVyfSBmcm9tICcuL2NvbW1vbic7XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnB1dCBpcyBtaXNzaW5nJyk7XG4gIH1cbiAgaWYgKGlucHV0cy5sZW5ndGggPCAyIHx8IGlucHV0cy5sZW5ndGggPiAzKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhaWQgaW5wdXQgbnVtYmVyLicpO1xuICB9XG5cbiAgLy8gJ0MnIGNhbiBiZSBvZiBkaW1lbnNpb25hbGl0eSAwLCAxIG9yIDIgb25seVxuICBpZiAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiBpbnB1dHNbMl0uZGltcy5sZW5ndGggPiAyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHNoYXBlIG9mIEMnKTtcbiAgfVxuXG4gIGlmICgoaW5wdXRzWzBdLmRhdGFUeXBlICE9PSBEYXRhVHlwZS5mbG9hdCkgfHwgKGlucHV0c1sxXS5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuZmxvYXQpIHx8XG4gICAgICAoaW5wdXRzLmxlbmd0aCA9PT0gMyAmJiBpbnB1dHNbMl0uZGF0YVR5cGUgIT09IERhdGFUeXBlLmZsb2F0KSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBpbnB1dCB0eXBlLicpO1xuICB9XG5cbiAgaWYgKChpbnB1dHNbMF0uZGF0YVR5cGUgIT09IGlucHV0c1sxXS5kYXRhVHlwZSkgfHxcbiAgICAgIChpbnB1dHMubGVuZ3RoID09PSAzICYmIGlucHV0c1swXS5kYXRhVHlwZSAhPT0gaW5wdXRzWzJdLmRhdGFUeXBlKSkge1xuICAgIHRocm93IG5ldyBFcnJvcignSW5wdXQgdHlwZXMgYXJlIG1pc21hdGNoZWQnKTtcbiAgfVxufTtcblxuZXhwb3J0IGludGVyZmFjZSBHZW1tQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHRyYW5zQTogYm9vbGVhbjtcbiAgdHJhbnNCOiBib29sZWFuO1xuICBhbHBoYTogbnVtYmVyO1xuICBiZXRhOiBudW1iZXI7XG59XG5cbmNvbnN0IG9mZnNldEMgPSAobTogbnVtYmVyLCBuOiBudW1iZXIsIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogc3RyaW5nID0+IHtcbiAgaWYgKGRpbXMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuICcwdSc7XG4gIH1cblxuICBjb25zdCBicm9hZGNhc3RNID0gKGRpbXMubGVuZ3RoID09PSAxICYmIG0gIT09IDEpIHx8IChkaW1zLmxlbmd0aCA9PT0gMiAmJiBkaW1zWzBdICE9PSBtKTtcbiAgY29uc3QgYnJvYWRjYXN0TiA9IGRpbXNbZGltcy5sZW5ndGggLSAxXSAhPT0gbjtcblxuICBsZXQgb2Zmc2V0ID0gJzB1JztcbiAgaWYgKCFicm9hZGNhc3RNKSB7XG4gICAgb2Zmc2V0ICs9IGArIG0gKiAke2RpbXNbZGltcy5sZW5ndGggLSAxXX11YDtcbiAgfVxuICBpZiAoIWJyb2FkY2FzdE4pIHtcbiAgICBvZmZzZXQgKz0gJytuJztcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQ7XG59O1xuXG5jb25zdCBjcmVhdGVHZW1tUHJvZ3JhbUluZm8gPVxuICAgIChtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhLCBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogR2VtbUF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICBjb25zdCBhU2hhcGUgPSBpbnB1dHNbMF0uZGltcy5zbGljZSgpO1xuICAgICAgY29uc3QgYlNoYXBlID0gaW5wdXRzWzFdLmRpbXMuc2xpY2UoKTtcbiAgICAgIGNvbnN0IFtNLCBOLCBLXSA9IEdlbW1VdGlsLmdldFNoYXBlT2ZHZW1tUmVzdWx0KFxuICAgICAgICAgIGFTaGFwZSwgYXR0cmlidXRlcy50cmFuc0EsIGJTaGFwZSwgYXR0cmlidXRlcy50cmFuc0IsIGlucHV0cy5sZW5ndGggPT09IDMgPyBpbnB1dHNbMl0uZGltcyA6IHVuZGVmaW5lZCk7XG4gICAgICBjb25zdCBvdXRwdXRTaGFwZSA9IFtNLCBOXTtcbiAgICAgIGlmICghb3V0cHV0U2hhcGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXCd0IHVzZSBnZW1tIG9uIHRoZSBnaXZlbiB0ZW5zb3JzJyk7XG4gICAgICB9XG4gICAgICBjb25zdCBvdXRwdXRTaXplID0gU2hhcGVVdGlsLnNpemUob3V0cHV0U2hhcGUpO1xuICAgICAgbGV0IGxpbmUgPSAnJztcbiAgICAgIGlmIChhdHRyaWJ1dGVzLnRyYW5zQSAmJiBhdHRyaWJ1dGVzLnRyYW5zQikge1xuICAgICAgICBsaW5lID0gJ3ZhbHVlICs9IGFbayAqIE0gKyBtXSAqIGJbbiAqIEsgKyBrXTsnO1xuICAgICAgfSBlbHNlIGlmIChhdHRyaWJ1dGVzLnRyYW5zQSAmJiAhYXR0cmlidXRlcy50cmFuc0IpIHtcbiAgICAgICAgbGluZSA9ICd2YWx1ZSArPSBhW2sgKiBNICsgbV0gKiBiW2sgKiBOICsgbl07JztcbiAgICAgIH0gZWxzZSBpZiAoIWF0dHJpYnV0ZXMudHJhbnNBICYmIGF0dHJpYnV0ZXMudHJhbnNCKSB7XG4gICAgICAgIGxpbmUgPSAndmFsdWUgKz0gYVttICogSyArIGtdICogYltuICogSyArIGtdOyc7XG4gICAgICB9IGVsc2UgaWYgKCFhdHRyaWJ1dGVzLnRyYW5zQSAmJiAhYXR0cmlidXRlcy50cmFuc0IpIHtcbiAgICAgICAgbGluZSA9ICd2YWx1ZSArPSBhW20gKiBLICsga10gKiBiW2sgKiBOICsgbl07JztcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGF0YVR5cGUgPSAnZjMyJzsgIC8vIFRPRE86IHN1cHBvcnQgb3RoZXIgZGF0YSB0eXBlXG4gICAgICBjb25zdCBjYWxjdWxhdGVBbHBoYSA9IGF0dHJpYnV0ZXMuYWxwaGEgPT09IDEgPyAnJyA6ICd2YWx1ZSAqPSBhbHBoYTsnO1xuICAgICAgY29uc3QgY2FsY3VsYXRlQyA9IGlucHV0cy5sZW5ndGggPT09IDMgPyBgdmFsdWUgKz0gYmV0YSAqIGNbJHtvZmZzZXRDKE0sIE4sIGlucHV0c1syXS5kaW1zKX1dO2AgOiAnJztcbiAgICAgIGNvbnN0IGlucHV0U3RvcmFnZUJ1ZmZlcnNEZWNsYXJhdGlvbnMgPSBbXG4gICAgICAgIGBAZ3JvdXAoMCkgQGJpbmRpbmcoMCkgdmFyPHN0b3JhZ2UsIHJlYWQ+IGEgOiBhcnJheTwke2RhdGFUeXBlfT47YCxcbiAgICAgICAgYEBncm91cCgwKSBAYmluZGluZygxKSB2YXI8c3RvcmFnZSwgcmVhZD4gYiA6IGFycmF5PCR7ZGF0YVR5cGV9PjtgXG4gICAgICBdO1xuICAgICAgaWYgKGlucHV0cy5sZW5ndGggPT09IDMpIHtcbiAgICAgICAgaW5wdXRTdG9yYWdlQnVmZmVyc0RlY2xhcmF0aW9ucy5wdXNoKGBAZ3JvdXAoMCkgQGJpbmRpbmcoMikgdmFyPHN0b3JhZ2UsIHJlYWQ+IGMgOiBhcnJheTwke2RhdGFUeXBlfT47YCk7XG4gICAgICB9XG4gICAgICBjb25zdCBnZXRTaGFkZXJTb3VyY2UgPSAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIpID0+IGBcbiAgY29uc3QgTTogdTMyID0gJHtNfXU7XG4gIGNvbnN0IE46IHUzMiA9ICR7Tn11O1xuICBjb25zdCBLOiB1MzIgPSAke0t9dTtcbiAgY29uc3QgYWxwaGEgPSAke2RhdGFUeXBlfSgke2F0dHJpYnV0ZXMuYWxwaGF9KTtcbiAgY29uc3QgYmV0YSA9ICR7ZGF0YVR5cGV9KCR7YXR0cmlidXRlcy5iZXRhfSk7XG5cbiAgJHtpbnB1dFN0b3JhZ2VCdWZmZXJzRGVjbGFyYXRpb25zLmpvaW4oJ1xcbicpfVxuICBAZ3JvdXAoMCkgQGJpbmRpbmcoJHtpbnB1dHMubGVuZ3RofSkgdmFyPHN0b3JhZ2UsIHJlYWRfd3JpdGU+IG91dHB1dCA6IGFycmF5PCR7ZGF0YVR5cGV9PjtcblxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKG91dHB1dFNpemUpfVxuXG4gICAgbGV0IG0gPSBnbG9iYWxfaWQueCAvIE47XG4gICAgbGV0IG4gPSBnbG9iYWxfaWQueCAlIE47XG5cbiAgICB2YXIgdmFsdWUgPSAke2RhdGFUeXBlfSgwKTtcbiAgICBmb3IgKHZhciBrOiB1MzIgPSAwdTsgazwke0t9dTsgaysrKSB7XG4gICAgICAke2xpbmV9XG4gICAgfVxuXG4gICAgJHtjYWxjdWxhdGVBbHBoYX1cbiAgICAke2NhbGN1bGF0ZUN9XG4gICAgb3V0cHV0W2dsb2JhbF9pZC54XSA9IHZhbHVlO1xuXG4gIH1gO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgIG91dHB1dHM6IFt7ZGltczogb3V0cHV0U2hhcGUsIGRhdGFUeXBlOiBpbnB1dHNbMF0uZGF0YVR5cGUsIGdwdURhdGFUeXBlOiBHcHVEYXRhVHlwZS5kZWZhdWx0fV0sXG4gICAgICAgIGdldFNoYWRlclNvdXJjZSxcbiAgICAgICAgZGlzcGF0Y2hHcm91cDogKCkgPT4gKHt4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKX0pXG4gICAgICB9O1xuICAgIH07XG5cbmNvbnN0IGNyZWF0ZUdlbW1Qcm9ncmFtSW5mb0xvYWRlciA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogR2VtbUF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mb0xvYWRlciA9PiB7XG4gIGNvbnN0IG1ldGFkYXRhID0ge1xuICAgIG5hbWU6ICdHZW1tJyxcbiAgICBpbnB1dFR5cGVzOiBpbnB1dHMubGVuZ3RoID09PSAzID8gW0dwdURhdGFUeXBlLmRlZmF1bHQsIEdwdURhdGFUeXBlLmRlZmF1bHQsIEdwdURhdGFUeXBlLmRlZmF1bHRdIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW0dwdURhdGFUeXBlLmRlZmF1bHQsIEdwdURhdGFUeXBlLmRlZmF1bHRdLFxuICAgIGNhY2hlSGludDogYXR0cmlidXRlcy5jYWNoZUtleVxuICB9O1xuXG4gIHJldHVybiB7Li4ubWV0YWRhdGEsIGdldDogKCkgPT4gY3JlYXRlR2VtbVByb2dyYW1JbmZvKG1ldGFkYXRhLCBpbnB1dHMsIGF0dHJpYnV0ZXMpfTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZW1tID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBHZW1tQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVHZW1tUHJvZ3JhbUluZm9Mb2FkZXIoY29udGV4dC5pbnB1dHMsIGF0dHJpYnV0ZXMpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUdlbW1BdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogR2VtbUF0dHJpYnV0ZXMgPT5cbiAgICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoYXR0cmlidXRlcyBhcyBPbWl0PEdlbW1BdHRyaWJ1dGVzLCBrZXlvZiBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXk+KTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0RhdGFUeXBlfSBmcm9tICcuLi8uLi8uLi93YXNtLWNvbW1vbic7XG5pbXBvcnQge1RlbnNvclZpZXd9IGZyb20gJy4uLy4uL3RlbnNvcic7XG5pbXBvcnQge0Jyb2FkY2FzdFV0aWwsIFNoYXBlVXRpbH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQge0NvbXB1dGVDb250ZXh0LCBHcHVEYXRhVHlwZSwgUHJvZ3JhbUluZm8sIFByb2dyYW1JbmZvTG9hZGVyLCBQcm9ncmFtTWV0YWRhdGF9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtTaGFkZXJIZWxwZXJ9IGZyb20gJy4vY29tbW9uJztcbmltcG9ydCB7Z2V0QWN0aWNhdGlvblNuaXBwZXQsIEludGVybmFsQWN0aXZhdGlvbkF0dHJpYnV0ZXN9IGZyb20gJy4vZnVzZS11dGlscyc7XG5cblxuY29uc3QgY3JlYXRlTWF0bXVsUHJvZ3JhbU1ldGFkYXRhID0gKGhhc0JpYXM6IGJvb2xlYW4sIGNhY2hlSGludDogc3RyaW5nKSA9PiAoe1xuICBuYW1lOiAnTWF0TXVsJyxcbiAgaW5wdXRUeXBlczogaGFzQmlhcyA/IFtHcHVEYXRhVHlwZS5kZWZhdWx0LCBHcHVEYXRhVHlwZS5kZWZhdWx0LCBHcHVEYXRhVHlwZS5kZWZhdWx0XSA6XG4gICAgICAgICAgICAgICAgICAgICAgICBbR3B1RGF0YVR5cGUuZGVmYXVsdCwgR3B1RGF0YVR5cGUuZGVmYXVsdF0sXG4gIGNhY2hlSGludFxufSk7XG5cbmNvbnN0IGNyZWF0ZU1hdG11bFByb2dyYW1JbmZvID1cbiAgICAobWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSwgaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGFjdGl2YXRpb25BdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzKTpcbiAgICAgICAgUHJvZ3JhbUluZm8gPT4ge1xuICAgICAgICAgIGNvbnN0IGFTaGFwZSA9IGlucHV0c1swXS5kaW1zO1xuICAgICAgICAgIGNvbnN0IGJTaGFwZSA9IGlucHV0c1sxXS5kaW1zO1xuICAgICAgICAgIGNvbnN0IG91dHB1dFNoYXBlID0gQnJvYWRjYXN0VXRpbC5jYWxjU2hhcGUoYVNoYXBlLCBiU2hhcGUsIHRydWUpO1xuICAgICAgICAgIGlmICghb3V0cHV0U2hhcGUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuXFwndCB1c2UgbWF0bXVsIG9uIHRoZSBnaXZlbiB0ZW5zb3JzJyk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gICAgICAgICAgLy8gVE9ETzogc3VwcG9ydCBicm9hZGNhc3RpbmdcblxuICAgICAgICAgIGNvbnN0IGRhdGFUeXBlID0gJ2YzMic7ICAvLyBUT0RPOiBzdXBwb3J0IG90aGVyIGRhdGEgdHlwZVxuICAgICAgICAgIGNvbnN0IHthY3RpdmF0aW9uRnVuY3Rpb24sIGFwcGx5QWN0aXZhdGlvbn0gPSBnZXRBY3RpY2F0aW9uU25pcHBldChhY3RpdmF0aW9uQXR0cmlidXRlcyk7XG5cbiAgICAgICAgICBjb25zdCBNID0gb3V0cHV0U2hhcGVbb3V0cHV0U2hhcGUubGVuZ3RoIC0gMl07XG4gICAgICAgICAgY29uc3QgSyA9IGFTaGFwZVthU2hhcGUubGVuZ3RoIC0gMV07XG4gICAgICAgICAgY29uc3QgTiA9IG91dHB1dFNoYXBlW291dHB1dFNoYXBlLmxlbmd0aCAtIDFdO1xuICAgICAgICAgIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gYFxuICBjb25zdCBNOiB1MzIgPSAke019dTtcbiAgY29uc3QgTjogdTMyID0gJHtOfXU7XG4gIGNvbnN0IEs6IHUzMiA9ICR7S311O1xuXG4gIEBncm91cCgwKSBAYmluZGluZygwKSB2YXI8c3RvcmFnZSwgcmVhZD4gYSA6IGFycmF5PCR7ZGF0YVR5cGV9PjtcbiAgQGdyb3VwKDApIEBiaW5kaW5nKDEpIHZhcjxzdG9yYWdlLCByZWFkPiBiIDogYXJyYXk8JHtkYXRhVHlwZX0+O1xuICBAZ3JvdXAoMCkgQGJpbmRpbmcoMikgdmFyPHN0b3JhZ2UsIHJlYWRfd3JpdGU+IG91dHB1dCA6IGFycmF5PCR7ZGF0YVR5cGV9PjtcblxuICAke2FjdGl2YXRpb25GdW5jdGlvbn1cblxuICAke3NoYWRlckhlbHBlci5tYWluU3RhcnQoKX1cbiAgICAke3NoYWRlckhlbHBlci5ndWFyZEFnYWluc3RPdXRPZkJvdW5kc1dvcmtncm91cFNpemVzKG91dHB1dFNpemUpfVxuXG4gICAgbGV0IHN0YWNrID0gZ2xvYmFsX2lkeCAvIChNICogTik7XG4gICAgbGV0IG1uID0gZ2xvYmFsX2lkeCAlIChNICogTik7XG4gICAgbGV0IG4gPSBnbG9iYWxfaWR4ICUgTjtcbiAgICBsZXQgbSA9IG1uIC8gTjtcblxuICAgIGxldCBvZmZzZXRBID0gc3RhY2sgKiAoTSAqIEspO1xuICAgIGxldCBvZmZzZXRCID0gc3RhY2sgKiAoSyAqIE4pO1xuXG4gICAgdmFyIHZhbHVlID0gJHtkYXRhVHlwZX0oMCk7XG4gICAgZm9yICh2YXIgazogdTMyID0gMHU7IGs8JHtLfXU7IGsrKykge1xuICAgICAgdmFsdWUgKz0gYVtvZmZzZXRBICsgbSAqIEsgKyBrXSAqIGJbb2Zmc2V0QiArIGsgKiBOICsgbl07XG4gICAgfVxuICAgICR7YXBwbHlBY3RpdmF0aW9ufVxuICAgIG91dHB1dFtnbG9iYWxfaWR4XSA9IHZhbHVlO1xuICB9YDtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4ubWV0YWRhdGEsXG4gICAgICAgICAgICBvdXRwdXRzOiBbe2RpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXRzWzBdLmRhdGFUeXBlLCBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGUuZGVmYXVsdH1dLFxuICAgICAgICAgICAgZ2V0U2hhZGVyU291cmNlLFxuICAgICAgICAgICAgZGlzcGF0Y2hHcm91cDogKCkgPT4gKHt4OiBNYXRoLmNlaWwob3V0cHV0U2l6ZSAvIDY0IC8qIHdvcmtncm91cCBzaXplICovKX0pXG4gICAgICAgICAgfTtcbiAgICAgICAgfTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZU1hdG11bFByb2dyYW1JbmZvTG9hZGVyID1cbiAgICAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIGFjdGl2YXRpb25BdHRyaWJ1dGVzOiBJbnRlcm5hbEFjdGl2YXRpb25BdHRyaWJ1dGVzKTogUHJvZ3JhbUluZm9Mb2FkZXIgPT4ge1xuICAgICAgY29uc3QgbWV0YWRhdGEgPSBjcmVhdGVNYXRtdWxQcm9ncmFtTWV0YWRhdGEoaW5wdXRzLmxlbmd0aCA+IDIsIGFjdGl2YXRpb25BdHRyaWJ1dGVzLmFjdGl2YXRpb25DYWNoZUtleSk7XG4gICAgICByZXR1cm4gey4uLm1ldGFkYXRhLCBnZXQ6ICgpID0+IGNyZWF0ZU1hdG11bFByb2dyYW1JbmZvKG1ldGFkYXRhLCBpbnB1dHMsIGFjdGl2YXRpb25BdHRyaWJ1dGVzKX07XG4gICAgfTtcblxuY29uc3QgdmFsaWRhdGVJbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiB2b2lkID0+IHtcbiAgaWYgKCFpbnB1dHMgfHwgaW5wdXRzLmxlbmd0aCAhPT0gMikge1xuICAgIHRocm93IG5ldyBFcnJvcignTWF0TXVsIHJlcXVpcmVzIDIgaW5wdXRzLicpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS5kaW1zW2lucHV0c1swXS5kaW1zLmxlbmd0aCAtIDFdICE9PSBpbnB1dHNbMV0uZGltc1tpbnB1dHNbMV0uZGltcy5sZW5ndGggLSAyXSkge1xuICAgIHRocm93IG5ldyBFcnJvcignc2hhcmVkIGRpbWVuc2lvbiBkb2VzIG5vdCBtYXRjaC4nKTtcbiAgfVxuXG4gIGlmIChpbnB1dHNbMF0uZGF0YVR5cGUgIT09IERhdGFUeXBlLmZsb2F0IHx8IGlucHV0c1sxXS5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuZmxvYXQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2lucHV0cyBzaG91bGQgYmUgZmxvYXQgdHlwZScpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgbWF0TXVsID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIHZhbGlkYXRlSW5wdXRzKGNvbnRleHQuaW5wdXRzKTtcblxuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlTWF0bXVsUHJvZ3JhbUluZm9Mb2FkZXIoY29udGV4dC5pbnB1dHMsIHthY3RpdmF0aW9uOiAnJywgYWN0aXZhdGlvbkNhY2hlS2V5OiAnJ30pKTtcbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtEYXRhVHlwZX0gZnJvbSAnLi4vLi4vLi4vd2FzbS1jb21tb24nO1xuaW1wb3J0IHtUZW5zb3JWaWV3fSBmcm9tICcuLi8uLi90ZW5zb3InO1xuaW1wb3J0IHtQb29sQ29udlV0aWwsIFNoYXBlVXRpbH0gZnJvbSAnLi4vLi4vdXRpbCc7XG5pbXBvcnQge0F0dHJpYnV0ZVdpdGhDYWNoZUtleSwgY3JlYXRlQXR0cmlidXRlV2l0aENhY2hlS2V5fSBmcm9tICcuLi9hdHRyaWJ1dGUtd2l0aC1jYWNoZS1rZXknO1xuaW1wb3J0IHtDb21wdXRlQ29udGV4dCwgR3B1RGF0YVR5cGUsIFByb2dyYW1JbmZvLCBQcm9ncmFtTWV0YWRhdGF9IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtjcmVhdGVJbmRpY2VzSGVscGVyLCBTaGFkZXJIZWxwZXJ9IGZyb20gJy4vY29tbW9uJztcblxuLy8gVE9ETzogc3VwcG9ydDpcbi8vIC0gY2VpbF9tb2RlICAgICAgICAgICAgICAgICBcInRlc3RfbWF4cG9vbF8yZF9jZWlsXCJcbi8vIC0gc3RvcmFnZV9vcmRlciAgICAgICAgICAgICBcInRlc3RfbWF4cG9vbF93aXRoX2FyZ21heF8yZF9wcmVjb21wdXRlZF9zdHJpZGVzXCJcbi8vIC0gW01heFBvb2xdIGRpbGF0aW9ucyAgICAgICBcInRlc3RfbWF4cG9vbF8yZF9kaWxhdGlvbnNcIlxuLy8gLSBbTWF4UG9vbF0gb3V0cHV0WzFdICAgICAgIFwidGVzdF9tYXhwb29sX3dpdGhfYXJnbWF4XzJkX3ByZWNvbXB1dGVkX3BhZHNcIlxuXG5jb25zdCB2YWxpZGF0ZUlucHV0cyA9IChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSk6IHZvaWQgPT4ge1xuICBpZiAoIWlucHV0cyB8fCBpbnB1dHMubGVuZ3RoICE9PSAxKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdQb29sIG9wcyByZXF1aXJlcyAxIGlucHV0LicpO1xuICB9XG4gIGlmIChpbnB1dHNbMF0uZGltcy5sZW5ndGggIT09IDQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1Bvb2wgb3BzIHN1cHBvcnRzIDItRCBpbnB1dHMgb25seSBmb3Igbm93LicpO1xuICB9XG4gIGlmIChpbnB1dHNbMF0uZGF0YVR5cGUgIT09IERhdGFUeXBlLmZsb2F0KSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGlucHV0IHR5cGUuJyk7XG4gIH1cbn07XG5cbmNvbnN0IGdldEFkanVzdGVkUG9vbEF0dHJpYnV0ZXNBbmRPdXRwdXRTaGFwZSA9IDxBdHRyaWJ1dGVUeXBlIGV4dGVuZHMgQXZlcmFnZVBvb2xBdHRyaWJ1dGVzfE1heFBvb2xBdHRyaWJ1dGVzPihcbiAgICBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgYXR0cmlidXRlczogQXR0cmlidXRlVHlwZSwgaXNHbG9iYWxPcGVyYXRvcjogYm9vbGVhbik6IFtBdHRyaWJ1dGVUeXBlLCBudW1iZXJbXV0gPT4ge1xuICBjb25zdCBpc0NoYW5uZWxzTGFzdCA9IGF0dHJpYnV0ZXMuZm9ybWF0ID09PSAnTkhXQyc7XG4gIGNvbnN0IGlucHV0U2hhcGVBc0NoYW5uZWxGaXJzdCA9IGlzQ2hhbm5lbHNMYXN0ID9cbiAgICAgIFtpbnB1dHNbMF0uZGltc1swXSwgaW5wdXRzWzBdLmRpbXNbM10sIGlucHV0c1swXS5kaW1zWzFdLCBpbnB1dHNbMF0uZGltc1syXV0gOlxuICAgICAgaW5wdXRzWzBdLmRpbXMuc2xpY2UoKTtcbiAgY29uc3QgaGFzRGlsYXRpb25zID0gT2JqZWN0Lmhhc093blByb3BlcnR5LmNhbGwoYXR0cmlidXRlcywgJ2RpbGF0aW9ucycpO1xuICBjb25zdCBrZXJuZWxTaGFwZSA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGUuc2xpY2UoKTtcbiAgY29uc3Qgc3RyaWRlcyA9IGF0dHJpYnV0ZXMuc3RyaWRlcy5zbGljZSgpO1xuICBjb25zdCBkaWxhdGlvbnM6IG51bWJlcltdID0gaGFzRGlsYXRpb25zID8gKGF0dHJpYnV0ZXMgYXMgTWF4UG9vbEF0dHJpYnV0ZXMpLmRpbGF0aW9ucy5zbGljZSgpIDogW107XG4gIGNvbnN0IHBhZHMgPSBhdHRyaWJ1dGVzLnBhZHMuc2xpY2UoKTtcbiAgUG9vbENvbnZVdGlsLmFkanVzdFBvb2xBdHRyaWJ1dGVzKGlzR2xvYmFsT3BlcmF0b3IsIGlucHV0U2hhcGVBc0NoYW5uZWxGaXJzdCwga2VybmVsU2hhcGUsIHN0cmlkZXMsIGRpbGF0aW9ucywgcGFkcyk7XG5cbiAgY29uc3Qgb3V0cHV0U2hhcGVBc0NoYW5uZWxGaXJzdCA9IFBvb2xDb252VXRpbC5jb21wdXRlUG9vbE91dHB1dFNoYXBlKFxuICAgICAgaXNHbG9iYWxPcGVyYXRvciwgaW5wdXRTaGFwZUFzQ2hhbm5lbEZpcnN0LCBzdHJpZGVzLCBkaWxhdGlvbnMsIGtlcm5lbFNoYXBlLCBwYWRzLCBhdHRyaWJ1dGVzLmF1dG9QYWQpO1xuXG4gIGNvbnN0IG5ld0F0dHJpYnV0ZXMgPSBPYmplY3QuYXNzaWduKHt9LCBhdHRyaWJ1dGVzKTtcbiAgaWYgKGhhc0RpbGF0aW9ucykge1xuICAgIE9iamVjdC5hc3NpZ24obmV3QXR0cmlidXRlcywge2tlcm5lbFNoYXBlLCBzdHJpZGVzLCBwYWRzLCBkaWxhdGlvbnMsIGNhY2hlS2V5OiBhdHRyaWJ1dGVzLmNhY2hlS2V5fSk7XG4gIH0gZWxzZSB7XG4gICAgT2JqZWN0LmFzc2lnbihuZXdBdHRyaWJ1dGVzLCB7a2VybmVsU2hhcGUsIHN0cmlkZXMsIHBhZHMsIGNhY2hlS2V5OiBhdHRyaWJ1dGVzLmNhY2hlS2V5fSk7XG4gIH1cbiAgcmV0dXJuIFtcbiAgICBuZXdBdHRyaWJ1dGVzLFxuICAgIGlzQ2hhbm5lbHNMYXN0ID9cbiAgICAgICAgW1xuICAgICAgICAgIG91dHB1dFNoYXBlQXNDaGFubmVsRmlyc3RbMF0sIG91dHB1dFNoYXBlQXNDaGFubmVsRmlyc3RbMl0sIG91dHB1dFNoYXBlQXNDaGFubmVsRmlyc3RbM10sXG4gICAgICAgICAgb3V0cHV0U2hhcGVBc0NoYW5uZWxGaXJzdFsxXVxuICAgICAgICBdIDpcbiAgICAgICAgb3V0cHV0U2hhcGVBc0NoYW5uZWxGaXJzdFxuICBdO1xufTtcblxuY29uc3QgZ2VuZXJhdGVQb29saW5nQ29kZSA9IDxBdHRyaWJ1dGVUeXBlIGV4dGVuZHMgQXZlcmFnZVBvb2xBdHRyaWJ1dGVzfE1heFBvb2xBdHRyaWJ1dGVzPihcbiAgICBzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlciwgaW5wdXREaW1zOiByZWFkb25seSBudW1iZXJbXSwgb3V0cHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBhdHRyaWJ1dGVzOiBBdHRyaWJ1dGVUeXBlLFxuICAgIG9wMTogc3RyaW5nLCBvcDI6IHN0cmluZywgZGF0YVR5cGU6IHN0cmluZywgc3RhcnQ6IHN0cmluZyk6IHN0cmluZyA9PiB7XG4gIGNvbnN0IGlzQ2hhbm5lbHNMYXN0ID0gYXR0cmlidXRlcy5mb3JtYXQgPT09ICdOSFdDJztcbiAgY29uc3QgcmFuayA9IGlucHV0RGltcy5sZW5ndGg7XG4gIGNvbnN0IG91dHB1dFNpemUgPSBTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSk7XG4gIGNvbnN0IG91dHB1dEluZGljZXNIZWxwZXIgPSBjcmVhdGVJbmRpY2VzSGVscGVyKCdvdXRwdXQnLCBvdXRwdXRTaGFwZSk7XG4gIGNvbnN0IHhJbmRpY2VzSGVscGVyID0gY3JlYXRlSW5kaWNlc0hlbHBlcigneCcsIGlucHV0RGltcyk7XG5cbiAgaWYgKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoIDw9IDIpIHtcbiAgICBjb25zdCBrdyA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGVbYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggLSAxXTtcbiAgICBjb25zdCBzdyA9IGF0dHJpYnV0ZXMuc3RyaWRlc1thdHRyaWJ1dGVzLnN0cmlkZXMubGVuZ3RoIC0gMV07XG4gICAgY29uc3QgcHdTdGFydCA9IGF0dHJpYnV0ZXMucGFkc1thdHRyaWJ1dGVzLnBhZHMubGVuZ3RoIC8gMiAtIDFdO1xuICAgIGNvbnN0IHB3RW5kID0gYXR0cmlidXRlcy5wYWRzW2F0dHJpYnV0ZXMucGFkcy5sZW5ndGggLSAxXTtcbiAgICBjb25zdCBkaW1JZHhXID0gcmFuayAtIChpc0NoYW5uZWxzTGFzdCA/IDIgOiAxKTtcbiAgICBsZXQgY29kZVcgPSAnJztcbiAgICBsZXQgY29kZUggPSAnJztcbiAgICBsZXQgY29kZUhFbmQgPSAnJztcbiAgICBpZiAocHdTdGFydCArIHB3RW5kICE9PSAwKSB7XG4gICAgICBjb2RlVyA9IGBcbiAgICAgICAgICAgICAgZm9yICh2YXIgaTogdTMyID0gMHU7IGkgPCAke2t3fXU7IGkrKykge1xuICAgICAgICAgICAgICAgIHhJbmRpY2VzWyR7ZGltSWR4V31dID0gaW5kaWNlc1ske2RpbUlkeFd9XSAqICR7c3d9IC0gJHtwd1N0YXJ0fSArIGk7XG4gICAgICAgICAgICAgICAgaWYgKHhJbmRpY2VzWyR7ZGltSWR4V31dIDwgMCB8fCB4SW5kaWNlc1ske2RpbUlkeFd9XSA+PSAke2lucHV0RGltc1tkaW1JZHhXXX0pIHtcbiAgICAgICAgICAgICAgICAgIHBhZCsrO1xuICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGxldCB4X3ZhbCA9IHhbJHt4SW5kaWNlc0hlbHBlci5pMm9FeHByZXNzaW9uKCd4SW5kaWNlcycpfV07XG4gICAgICAgICAgICAgICAgJHtvcDF9XG4gICAgICAgICAgICAgIH1gO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb2RlVyA9IGBcbiAgICAgICAgICAgICAgZm9yICh2YXIgaTogdTMyID0gMHU7IGkgPCAke2t3fXU7IGkrKykge1xuICAgICAgICAgICAgICAgIHhJbmRpY2VzWyR7ZGltSWR4V31dID0gaW5kaWNlc1ske2RpbUlkeFd9XSAqICR7c3d9IC0gJHtwd1N0YXJ0fSArIGk7XG4gICAgICAgICAgICAgICAgbGV0IHhfdmFsID0geFske3hJbmRpY2VzSGVscGVyLmkyb0V4cHJlc3Npb24oJ3hJbmRpY2VzJyl9XTtcbiAgICAgICAgICAgICAgICAke29wMX1cbiAgICAgICAgICAgICAgfWA7XG4gICAgfVxuXG4gICAgaWYgKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUubGVuZ3RoID09PSAyKSB7XG4gICAgICBjb25zdCBraCA9IGF0dHJpYnV0ZXMua2VybmVsU2hhcGVbYXR0cmlidXRlcy5rZXJuZWxTaGFwZS5sZW5ndGggLSAyXTtcbiAgICAgIGNvbnN0IHNoID0gYXR0cmlidXRlcy5zdHJpZGVzW2F0dHJpYnV0ZXMuc3RyaWRlcy5sZW5ndGggLSAyXTtcbiAgICAgIGNvbnN0IHBoU3RhcnQgPSBhdHRyaWJ1dGVzLnBhZHNbYXR0cmlidXRlcy5wYWRzLmxlbmd0aCAvIDIgLSAyXTtcbiAgICAgIGNvbnN0IHBoRW5kID0gYXR0cmlidXRlcy5wYWRzW2F0dHJpYnV0ZXMucGFkcy5sZW5ndGggLSAyXTtcbiAgICAgIGNvbnN0IGRpbUlkeEggPSByYW5rIC0gKGlzQ2hhbm5lbHNMYXN0ID8gMyA6IDIpO1xuICAgICAgY29uc3QgZGltSCA9IGlucHV0RGltc1tkaW1JZHhIXTtcbiAgICAgIGlmIChwaFN0YXJ0ICsgcGhFbmQgIT09IDApIHtcbiAgICAgICAgY29kZUggPSBgXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgajogdTMyID0gMHU7IGogPCAke2tofXU7IGorKykge1xuICAgICAgICAgICAgICAgICAgeEluZGljZXNbJHtkaW1JZHhIfV0gPSBpbmRpY2VzWyR7ZGltSWR4SH1dICogJHtzaH0gLSAke3BoU3RhcnR9ICsgajtcbiAgICAgICAgICAgICAgICAgIGlmICh4SW5kaWNlc1ske2RpbUlkeEh9XSA8IDAgfHwgeEluZGljZXNbJHtkaW1JZHhIfV0gPj0gJHtkaW1IfSkge1xuICAgICAgICAgICAgICAgICAgICBwYWQrPSAke2t3fTtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb2RlSCA9IGBcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqOiB1MzIgPSAwdTsgaiA8ICR7a2h9dTsgaisrKSB7XG4gICAgICAgICAgICAgICAgICB4SW5kaWNlc1ske2RpbUlkeEh9XSA9IGluZGljZXNbJHtkaW1JZHhIfV0gKiAke3NofSAtICR7cGhTdGFydH0gKyBqO1xuICAgICAgICAgICAgICAgIGA7XG4gICAgICB9XG4gICAgICBjb2RlSEVuZCA9IGBcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgYDtcbiAgICB9XG5cbiAgICBjb25zdCBwb29saW5nQ29kZSA9IGBcbiAgICAgICAgICAgIEBncm91cCgwKSBAYmluZGluZygwKSB2YXI8c3RvcmFnZSwgcmVhZD4geCA6IGFycmF5PCR7ZGF0YVR5cGV9PjtcbiAgICAgICAgICAgIEBncm91cCgwKSBAYmluZGluZygxKSB2YXI8c3RvcmFnZSwgcmVhZF93cml0ZT4gb3V0cHV0IDogYXJyYXk8JHtkYXRhVHlwZX0+O1xuXG4gICAgICAgICAgICAke291dHB1dEluZGljZXNIZWxwZXIubzJpSW1wbH1cbiAgICAgICAgICAgICR7eEluZGljZXNIZWxwZXIuaTJvSW1wbH1cblxuICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMob3V0cHV0U2l6ZSl9XG5cbiAgICAgICAgICAgICAgJHtvdXRwdXRJbmRpY2VzSGVscGVyLmluZGljZXNWYXJpYWJsZURlY2xhcmF0aW9uKCdpbmRpY2VzJyl9XG4gICAgICAgICAgICAgICR7b3V0cHV0SW5kaWNlc0hlbHBlci5vMmlDYWxsKCdnbG9iYWxfaWR4JywgJ2luZGljZXMnKX1cbiAgICAgICAgICAgICAgJHtvdXRwdXRJbmRpY2VzSGVscGVyLmluZGljZXNWYXJpYWJsZURlY2xhcmF0aW9uKCd4SW5kaWNlcycpfVxuICAgICAgICAgICAgICAke291dHB1dEluZGljZXNIZWxwZXIubzJpQ2FsbCgnZ2xvYmFsX2lkeCcsICd4SW5kaWNlcycpfVxuXG4gICAgICAgICAgICAgIHZhciB2YWx1ZTogJHtkYXRhVHlwZX0gPSAke2RhdGFUeXBlfSgke3N0YXJ0fSk7XG4gICAgICAgICAgICAgIHZhciBwYWQgPSAwO1xuICAgICAgICAgICAgICAke2NvZGVIfVxuICAgICAgICAgICAgICAke2NvZGVXfVxuICAgICAgICAgICAgICAke2NvZGVIRW5kfVxuICAgICAgICAgICAgICAke29wMn1cblxuICAgICAgICAgICAgICBvdXRwdXRbZ2xvYmFsX2lkeF0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH1gO1xuICAgIHJldHVybiBwb29saW5nQ29kZTtcbiAgfSBlbHNlIHtcbiAgICBpZiAoaXNDaGFubmVsc0xhc3QpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUG9vbGluZyB3aXRoIGtlcm5lbFNoYXBlLmxlbmd0aCA+IDIgaXMgbm90IHN1cHBvcnRlZCBmb3IgTkhXQyBmb3JtYXQuJyk7XG4gICAgfVxuICAgIGNvbnN0IGtlcm5lbFNpemUgPSBTaGFwZVV0aWwuc2l6ZShhdHRyaWJ1dGVzLmtlcm5lbFNoYXBlKTtcbiAgICBjb25zdCBrZXJuZWxTdHJpZGVzID0gU2hhcGVVdGlsLmNvbXB1dGVTdHJpZGVzKGF0dHJpYnV0ZXMua2VybmVsU2hhcGUpO1xuICAgIGNvbnN0IHN0cmlkZXNSYW5rID0ga2VybmVsU3RyaWRlcy5sZW5ndGg7XG4gICAgY29uc3QgcGFkc1JhbmsgPSBhdHRyaWJ1dGVzLnBhZHMubGVuZ3RoO1xuICAgIGNvbnN0IGhhc1BhZHMgPSBhdHRyaWJ1dGVzLnBhZHMucmVkdWNlKChzdW0sIGN1cikgPT4gc3VtICsgY3VyKTtcbiAgICBsZXQgcGFkQ29kZSA9ICcnO1xuICAgIGlmIChoYXNQYWRzKSB7XG4gICAgICBwYWRDb2RlID0gYFxuICAgICAgICAgICAgICAgIGlmICh4SW5kaWNlc1tqXSA+PSBpbnB1dERpbXNbal0pIHtcbiAgICAgICAgICAgICAgICAgIHBhZCsrO1xuICAgICAgICAgICAgICAgICAgaXNQYWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmICghaXNQYWQpIHtcbiAgICAgICAgICAgICAgICBsZXQgeF92YWwgPSB4WyR7eEluZGljZXNIZWxwZXIuaTJvRXhwcmVzc2lvbigneEluZGljZXMnKX1dO1xuICAgICAgICAgICAgICAgICR7b3AxfVxuICAgICAgICAgICAgICB9YDtcbiAgICB9IGVsc2Uge1xuICAgICAgcGFkQ29kZSA9IGBcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBsZXQgeF92YWwgPSB4WyR7eEluZGljZXNIZWxwZXIuaTJvRXhwcmVzc2lvbigneEluZGljZXMnKX1dO1xuICAgICAgICAgICAgICAke29wMX1cbiAgICAgICAgICAgIGA7XG4gICAgfVxuICAgIGNvbnN0IHBvb2xpbmdDb2RlID0gYFxuICAgICAgICAgICAgQGdyb3VwKDApIEBiaW5kaW5nKDApIHZhcjxzdG9yYWdlLCByZWFkPiB4IDogYXJyYXk8JHtkYXRhVHlwZX0+O1xuICAgICAgICAgICAgQGdyb3VwKDApIEBiaW5kaW5nKDEpIHZhcjxzdG9yYWdlLCByZWFkX3dyaXRlPiBvdXRwdXQgOiBhcnJheTwke2RhdGFUeXBlfT47XG5cbiAgICAgICAgICAgICR7b3V0cHV0SW5kaWNlc0hlbHBlci5vMmlJbXBsfVxuICAgICAgICAgICAgJHt4SW5kaWNlc0hlbHBlci5pMm9JbXBsfVxuXG4gICAgICAgICAgICBjb25zdCBwYWRzID0gYXJyYXk8dTMyLCAke3BhZHNSYW5rfT4oJHthdHRyaWJ1dGVzLnBhZHMubWFwKGkgPT4gYCR7aX11YCkuam9pbignLCcpfSk7XG4gICAgICAgICAgICBjb25zdCBpbnB1dERpbXMgPSBhcnJheTx1MzIsICR7cmFua30+KCR7aW5wdXREaW1zLm1hcChpID0+IGAke2l9dWApLmpvaW4oJywnKX0pO1xuICAgICAgICAgICAgY29uc3Qga2VybmVsU3RyaWRlcyA9IGFycmF5PHUzMiwgJHtzdHJpZGVzUmFua30+KCR7a2VybmVsU3RyaWRlcy5tYXAoaSA9PiBgJHtpfXVgKS5qb2luKCcsJyl9KTtcbiAgICAgICAgICAgIGNvbnN0IHN0cmlkZXMgPSBhcnJheTx1MzIsICR7c3RyaWRlc1Jhbmt9Pigke2F0dHJpYnV0ZXMuc3RyaWRlcy5tYXAoaSA9PiBgJHtpfXVgKS5qb2luKCcsJyl9KTtcblxuICAgICAgICAgICAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgICAgICAgICAgICR7c2hhZGVySGVscGVyLmd1YXJkQWdhaW5zdE91dE9mQm91bmRzV29ya2dyb3VwU2l6ZXMob3V0cHV0U2l6ZSl9XG5cbiAgICAgICAgICAgICAgJHtvdXRwdXRJbmRpY2VzSGVscGVyLmluZGljZXNWYXJpYWJsZURlY2xhcmF0aW9uKCdpbmRpY2VzJyl9XG4gICAgICAgICAgICAgICR7b3V0cHV0SW5kaWNlc0hlbHBlci5vMmlDYWxsKCdnbG9iYWxfaWR4JywgJ2luZGljZXMnKX1cbiAgICAgICAgICAgICAgJHtvdXRwdXRJbmRpY2VzSGVscGVyLmluZGljZXNWYXJpYWJsZURlY2xhcmF0aW9uKCd4SW5kaWNlcycpfVxuICAgICAgICAgICAgICAke291dHB1dEluZGljZXNIZWxwZXIubzJpQ2FsbCgnZ2xvYmFsX2lkeCcsICd4SW5kaWNlcycpfVxuXG4gICAgICAgICAgICAgIHZhciBvZmZzZXRzOiBhcnJheTx1MzIsICR7c3RyaWRlc1Jhbmt9PjtcblxuICAgICAgICAgICAgICB2YXIgdmFsdWUgPSAke2RhdGFUeXBlfSgke3N0YXJ0fSk7XG4gICAgICAgICAgICAgIHZhciBwYWQgPSAwO1xuICAgICAgICAgICAgICB2YXIgaXNQYWQgPSBmYWxzZTtcblxuICAgICAgICAgICAgICBmb3IgKHZhciBpOiB1MzIgPSAwdTsgaSA8ICR7a2VybmVsU2l6ZX11OyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgb2Zmc2V0ID0gaTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMHU7IGogPCAke3N0cmlkZXNSYW5rIC0gMX11OyBqKyspIHtcbiAgICAgICAgICAgICAgICAgIG9mZnNldHNbal0gPSBvZmZzZXQgLyBrZXJuZWxTdHJpZGVzW2pdO1xuICAgICAgICAgICAgICAgICAgb2Zmc2V0IC09IG9mZnNldHNbal0gKiBrZXJuZWxTdHJpZGVzW2pdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvZmZzZXRzWyR7c3RyaWRlc1JhbmsgLSAxfV0gPSBvZmZzZXQ7XG5cbiAgICAgICAgICAgICAgICBpc1BhZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAke3JhbmsgLSBzdHJpZGVzUmFua311OyBqIDwgJHtyYW5rfXU7IGorKykge1xuICAgICAgICAgICAgICAgICAgeEluZGljZXNbal0gPSBpbmRpY2VzW2pdICogc3RyaWRlc1tqIC0gJHtyYW5rIC0gc3RyaWRlc1Jhbmt9dV1cbiAgICAgICAgICAgICAgICAgICAgKyBvZmZzZXRzW2ogLSAke3JhbmsgLSBzdHJpZGVzUmFua311XSAtIHBhZHNbaiAtIDJ1XTtcbiAgICAgICAgICAgICAgICAgICR7cGFkQ29kZX1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAke29wMn1cblxuICAgICAgICAgICAgICBvdXRwdXRbZ2xvYmFsX2lkeF0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH1gO1xuICAgIHJldHVybiBwb29saW5nQ29kZTtcbiAgfVxufTtcblxuZXhwb3J0IGludGVyZmFjZSBGb3JtYXRBdHRyaWJ1dGVzIHtcbiAgcmVhZG9ubHkgZm9ybWF0OiAnTkhXQyd8J05DSFcnO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFBvb2xDb21tb25BdHRyaWJ1dGVzIGV4dGVuZHMgRm9ybWF0QXR0cmlidXRlcyB7XG4gIHJlYWRvbmx5IGF1dG9QYWQ6IHN0cmluZztcbiAgcmVhZG9ubHkgY2VpbE1vZGU6IG51bWJlcjtcbiAgcmVhZG9ubHkga2VybmVsU2hhcGU6IHJlYWRvbmx5IG51bWJlcltdO1xuICByZWFkb25seSBzdHJpZGVzOiByZWFkb25seSBudW1iZXJbXTtcbiAgcmVhZG9ubHkgcGFkczogcmVhZG9ubHkgbnVtYmVyW107XG59XG5cbmNvbnN0IHBhcnNlUG9vbENvbW1vbkF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBQb29sQ29tbW9uQXR0cmlidXRlcyA9PiAoe1xuICBmb3JtYXQ6IGF0dHJpYnV0ZXMuZm9ybWF0IGFzIEZvcm1hdEF0dHJpYnV0ZXNbJ2Zvcm1hdCddLFxuICBhdXRvUGFkOiBbJ05PVFNFVCcsICdWQUxJRCcsICdTQU1FX1VQUEVSJywgJ1NBTUVfTE9XRVInXVthdHRyaWJ1dGVzLmF1dG9fcGFkIGFzIG51bWJlcl0sXG4gIGNlaWxNb2RlOiBhdHRyaWJ1dGVzLmNlaWxfbW9kZSBhcyBudW1iZXIsXG4gIGtlcm5lbFNoYXBlOiBhdHRyaWJ1dGVzLmtlcm5lbF9zaGFwZSBhcyBbbnVtYmVyLCBudW1iZXJdLFxuICBzdHJpZGVzOiBhdHRyaWJ1dGVzLnN0cmlkZXMgYXMgW251bWJlciwgbnVtYmVyXSxcbiAgcGFkczogYXR0cmlidXRlcy5wYWRzIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyLCBudW1iZXJdXG59KTtcblxuZXhwb3J0IGludGVyZmFjZSBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMgZXh0ZW5kcyBQb29sQ29tbW9uQXR0cmlidXRlcywgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgY291bnRJbmNsdWRlUGFkOiBib29sZWFuO1xufVxuXG5jb25zdCBjcmVhdGVBdmVyYWdlUG9vbFByb2dyYW1JbmZvID1cbiAgICAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10sIG1ldGFkYXRhOiBQcm9ncmFtTWV0YWRhdGEsIGlzR2xvYmFsT3BlcmF0b3I6IGJvb2xlYW4sXG4gICAgIGF0dHJpYnV0ZXM6IEF2ZXJhZ2VQb29sQXR0cmlidXRlcyk6IFByb2dyYW1JbmZvID0+IHtcbiAgICAgIGNvbnN0IFthZGp1c3RlZEF0dHJpYnV0ZXMsIG91dHB1dFNoYXBlXSA9XG4gICAgICAgICAgZ2V0QWRqdXN0ZWRQb29sQXR0cmlidXRlc0FuZE91dHB1dFNoYXBlKGlucHV0cywgYXR0cmlidXRlcywgaXNHbG9iYWxPcGVyYXRvcik7XG4gICAgICBjb25zdCBrZXJuZWxTaXplID0gU2hhcGVVdGlsLnNpemUoYWRqdXN0ZWRBdHRyaWJ1dGVzLmtlcm5lbFNoYXBlKTtcblxuICAgICAgY29uc3QgZGF0YVR5cGUgPSAnZjMyJztcblxuICAgICAgY29uc3Qgb3AxID0gJ3ZhbHVlICs9IHhfdmFsOyc7XG4gICAgICBsZXQgb3AyID0gJyc7XG4gICAgICBpZiAoYWRqdXN0ZWRBdHRyaWJ1dGVzLmNvdW50SW5jbHVkZVBhZCkge1xuICAgICAgICBvcDIgKz0gYHZhbHVlIC89ICR7ZGF0YVR5cGV9KCR7a2VybmVsU2l6ZX0pO2A7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcDIgKz0gYHZhbHVlIC89ICR7ZGF0YVR5cGV9KCR7a2VybmVsU2l6ZX0gLSBwYWQpO2A7XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgb3V0cHV0czogW3tkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSwgZ3B1RGF0YVR5cGU6IEdwdURhdGFUeXBlLmRlZmF1bHR9XSxcbiAgICAgICAgZ2V0U2hhZGVyU291cmNlOiBzaGFkZXJIZWxwZXIgPT4gZ2VuZXJhdGVQb29saW5nQ29kZShcbiAgICAgICAgICAgIHNoYWRlckhlbHBlciwgaW5wdXRzWzBdLmRpbXMsIG91dHB1dFNoYXBlLCBhZGp1c3RlZEF0dHJpYnV0ZXMsIG9wMSwgb3AyLCBkYXRhVHlwZSwgJzAuMCcpLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiAoKSA9PiAoe3g6IE1hdGguY2VpbChTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLyl9KVxuICAgICAgfTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgcGFyc2VBdmVyYWdlUG9vbEF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBjb3VudEluY2x1ZGVQYWQgPSAoYXR0cmlidXRlcy5jb3VudF9pbmNsdWRlX3BhZCBhcyBudW1iZXIpID09PSAwID8gZmFsc2UgOiB0cnVlO1xuXG4gIGNvbnN0IGF0dHIgPSBwYXJzZVBvb2xDb21tb25BdHRyaWJ1dGVzKGF0dHJpYnV0ZXMpO1xuICAvLyBUT0RPOiBzdXBwb3J0IGF0dHJpYnV0ZSAnY2VpbF9tb2RlJ1xuICBpZiAoYXR0ci5jZWlsTW9kZSAhPT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXNpbmcgY2VpbCgpIGluIHNoYXBlIGNvbXB1dGF0aW9uIGlzIG5vdCB5ZXQgc3VwcG9ydGVkIGZvciBBdmVyYWdlUG9vbCcpO1xuICB9XG5cbiAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7Y291bnRJbmNsdWRlUGFkLCAuLi5hdHRyfSk7XG59O1xuXG5leHBvcnQgY29uc3QgYXZlcmFnZVBvb2wgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEF2ZXJhZ2VQb29sQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnN0IG1ldGFkYXRhID0ge25hbWU6ICdBdmVyYWdlUG9vbCcsIGlucHV0VHlwZXM6IFtHcHVEYXRhVHlwZS5kZWZhdWx0XSwgY2FjaGVIaW50OiBhdHRyaWJ1dGVzLmNhY2hlS2V5fTtcbiAgY29udGV4dC5jb21wdXRlKHsuLi5tZXRhZGF0YSwgZ2V0OiAoKSA9PiBjcmVhdGVBdmVyYWdlUG9vbFByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzLCBtZXRhZGF0YSwgZmFsc2UsIGF0dHJpYnV0ZXMpfSk7XG59O1xuXG5jb25zdCBnbG9iYWxQb29sQXR0cmlidXRlcyA9IHtcbiAgYXV0b1BhZDogJycsXG4gIGNlaWxNb2RlOiAwLFxuICBjb3VudEluY2x1ZGVQYWQ6IGZhbHNlLFxuICBrZXJuZWxTaGFwZTogW10sXG4gIHN0cmlkZXM6IFtdLFxuICBwYWRzOiBbXSxcbiAgc3RvcmFnZU9yZGVyOiAwLFxuICBkaWxhdGlvbnM6IFtdLFxuICBjYWNoZUtleTogJydcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUdsb2JhbEF2ZXJhZ2VQb29sQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IEF2ZXJhZ2VQb29sQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IGZvcm1hdCA9IGF0dHJpYnV0ZXMuZm9ybWF0IGFzIEZvcm1hdEF0dHJpYnV0ZXNbJ2Zvcm1hdCddO1xuICByZXR1cm4ge2Zvcm1hdCwgLi4uZ2xvYmFsUG9vbEF0dHJpYnV0ZXMsIGNhY2hlS2V5OiBmb3JtYXR9O1xufTtcblxuZXhwb3J0IGNvbnN0IGdsb2JhbEF2ZXJhZ2VQb29sID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBBdmVyYWdlUG9vbEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb25zdCBtZXRhZGF0YSA9IHtuYW1lOiAnR2xvYmFsQXZlcmFnZVBvb2wnLCBpbnB1dFR5cGVzOiBbR3B1RGF0YVR5cGUuZGVmYXVsdF0sIGNhY2hlSGludDogYXR0cmlidXRlcy5jYWNoZUtleX07XG4gIGNvbnRleHQuY29tcHV0ZSh7Li4ubWV0YWRhdGEsIGdldDogKCkgPT4gY3JlYXRlQXZlcmFnZVBvb2xQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgbWV0YWRhdGEsIHRydWUsIGF0dHJpYnV0ZXMpfSk7XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIE1heFBvb2xBdHRyaWJ1dGVzIGV4dGVuZHMgUG9vbENvbW1vbkF0dHJpYnV0ZXMsIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IHN0b3JhZ2VPcmRlcjogbnVtYmVyO1xuICByZWFkb25seSBkaWxhdGlvbnM6IG51bWJlcltdO1xufVxuXG5jb25zdCBjcmVhdGVNYXhQb29sUHJvZ3JhbUluZm8gPVxuICAgIChpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXSwgbWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSwgaXNHbG9iYWxPcGVyYXRvcjogYm9vbGVhbixcbiAgICAgYXR0cmlidXRlczogTWF4UG9vbEF0dHJpYnV0ZXMpOiBQcm9ncmFtSW5mbyA9PiB7XG4gICAgICBjb25zdCBbYWRqdXN0ZWRBdHRyaWJ1dGVzLCBvdXRwdXRTaGFwZV0gPVxuICAgICAgICAgIGdldEFkanVzdGVkUG9vbEF0dHJpYnV0ZXNBbmRPdXRwdXRTaGFwZShpbnB1dHMsIGF0dHJpYnV0ZXMsIGlzR2xvYmFsT3BlcmF0b3IpO1xuICAgICAgY29uc3Qgb3AxID0gYFxuICAgICAgdmFsdWUgPSBtYXgoeF92YWwsIHZhbHVlKTtcbiAgICBgO1xuICAgICAgY29uc3Qgb3AyID0gJyc7XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgb3V0cHV0czogW3tkaW1zOiBvdXRwdXRTaGFwZSwgZGF0YVR5cGU6IGlucHV0c1swXS5kYXRhVHlwZSwgZ3B1RGF0YVR5cGU6IEdwdURhdGFUeXBlLmRlZmF1bHR9XSxcbiAgICAgICAgZ2V0U2hhZGVyU291cmNlOiBzaGFkZXJIZWxwZXIgPT5cbiAgICAgICAgICAgIGdlbmVyYXRlUG9vbGluZ0NvZGUoc2hhZGVySGVscGVyLCBpbnB1dHNbMF0uZGltcywgb3V0cHV0U2hhcGUsIGFkanVzdGVkQXR0cmlidXRlcywgb3AxLCBvcDIsICdmMzInLCAnLTFlNScpLFxuICAgICAgICBkaXNwYXRjaEdyb3VwOiAoKSA9PiAoe3g6IE1hdGguY2VpbChTaGFwZVV0aWwuc2l6ZShvdXRwdXRTaGFwZSkgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLyl9KVxuICAgICAgfTtcbiAgICB9O1xuXG5leHBvcnQgY29uc3QgbWF4UG9vbCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogTWF4UG9vbEF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgdmFsaWRhdGVJbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjb25zdCBtZXRhZGF0YSA9IHtuYW1lOiAnTWF4UG9vbCcsIGlucHV0VHlwZXM6IFtHcHVEYXRhVHlwZS5kZWZhdWx0XSwgY2FjaGVIaW50OiBhdHRyaWJ1dGVzLmNhY2hlS2V5fTtcbiAgY29udGV4dC5jb21wdXRlKHsuLi5tZXRhZGF0YSwgZ2V0OiAoKSA9PiBjcmVhdGVNYXhQb29sUHJvZ3JhbUluZm8oY29udGV4dC5pbnB1dHMsIG1ldGFkYXRhLCBmYWxzZSwgYXR0cmlidXRlcyl9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZU1heFBvb2xBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogTWF4UG9vbEF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBzdG9yYWdlT3JkZXIgPSBhdHRyaWJ1dGVzLnN0b3JhZ2Vfb3JkZXIgYXMgbnVtYmVyO1xuICBjb25zdCBkaWxhdGlvbnMgPSBhdHRyaWJ1dGVzLmRpbGF0aW9ucyBhcyBbbnVtYmVyLCBudW1iZXJdO1xuXG4gIGNvbnN0IGF0dHIgPSBwYXJzZVBvb2xDb21tb25BdHRyaWJ1dGVzKGF0dHJpYnV0ZXMpO1xuICAvLyBUT0RPOiBzdXBwb3J0IGF0dHJpYnV0ZSAnY2VpbF9tb2RlJyBhbmQgJ3N0b3JhZ2Vfb3JkZXInXG4gIGlmIChzdG9yYWdlT3JkZXIgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvbHVtbiBtYWpvciBzdG9yYWdlIG9yZGVyIGlzIG5vdCB5ZXQgc3VwcG9ydGVkIGZvciBNYXhQb29sJyk7XG4gIH1cbiAgaWYgKGF0dHIuY2VpbE1vZGUgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3VzaW5nIGNlaWwoKSBpbiBzaGFwZSBjb21wdXRhdGlvbiBpcyBub3QgeWV0IHN1cHBvcnRlZCBmb3IgTWF4UG9vbCcpO1xuICB9XG5cbiAgcmV0dXJuIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleSh7c3RvcmFnZU9yZGVyLCBkaWxhdGlvbnMsIC4uLmF0dHJ9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBwYXJzZUdsb2JhbE1heFBvb2xBdHRyaWJ1dGVzID0gKGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogTWF4UG9vbEF0dHJpYnV0ZXMgPT4ge1xuICBjb25zdCBmb3JtYXQgPSBhdHRyaWJ1dGVzLmZvcm1hdCBhcyBGb3JtYXRBdHRyaWJ1dGVzWydmb3JtYXQnXTtcbiAgcmV0dXJuIHtmb3JtYXQsIC4uLmdsb2JhbFBvb2xBdHRyaWJ1dGVzLCBjYWNoZUtleTogZm9ybWF0fTtcbn07XG5cbmV4cG9ydCBjb25zdCBnbG9iYWxNYXhQb29sID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBNYXhQb29sQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnN0IG1ldGFkYXRhID0ge25hbWU6ICdHbG9iYWxNYXhQb29sJywgaW5wdXRUeXBlczogW0dwdURhdGFUeXBlLmRlZmF1bHRdLCBjYWNoZUhpbnQ6IGF0dHJpYnV0ZXMuY2FjaGVLZXl9O1xuICBjb250ZXh0LmNvbXB1dGUoey4uLm1ldGFkYXRhLCBnZXQ6ICgpID0+IGNyZWF0ZU1heFBvb2xQcm9ncmFtSW5mbyhjb250ZXh0LmlucHV0cywgbWV0YWRhdGEsIHRydWUsIGF0dHJpYnV0ZXMpfSk7XG59O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7RGF0YVR5cGV9IGZyb20gJy4uLy4uLy4uL3dhc20tY29tbW9uJztcbmltcG9ydCB7VGVuc29yVmlld30gZnJvbSAnLi4vLi4vdGVuc29yJztcbmltcG9ydCB7U2hhcGVVdGlsfSBmcm9tICcuLi8uLi91dGlsJztcbmltcG9ydCB7QXR0cmlidXRlV2l0aENhY2hlS2V5LCBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXl9IGZyb20gJy4uL2F0dHJpYnV0ZS13aXRoLWNhY2hlLWtleSc7XG5pbXBvcnQge0NvbXB1dGVDb250ZXh0LCBHcHVEYXRhVHlwZSwgUHJvZ3JhbUluZm99IGZyb20gJy4uL3R5cGVzJztcblxuaW1wb3J0IHtjcmVhdGVJbmRpY2VzSGVscGVyLCBTaGFkZXJIZWxwZXJ9IGZyb20gJy4vY29tbW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBUcmFuc3Bvc2VBdHRyaWJ1dGVzIGV4dGVuZHMgQXR0cmlidXRlV2l0aENhY2hlS2V5IHtcbiAgcmVhZG9ubHkgcGVybTogbnVtYmVyW107XG59XG5cbmV4cG9ydCBjb25zdCB0cmFuc3Bvc2VQcm9ncmFtTWV0YWRhdGEgPSB7XG4gIG5hbWU6ICdUcmFuc3Bvc2UnLFxuICBpbnB1dFR5cGVzOiBbR3B1RGF0YVR5cGUuZGVmYXVsdF1cbn07XG5cbmNvbnN0IHZhbGlkYXRlSW5wdXRzID0gKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKTogdm9pZCA9PiB7XG4gIGlmICghaW5wdXRzIHx8IGlucHV0cy5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RyYW5zcG9zZSByZXF1aXJlcyAxIGlucHV0LicpO1xuICB9XG5cbiAgaWYgKGlucHV0c1swXS5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuZmxvYXQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2lucHV0IHNob3VsZCBiZSBmbG9hdCB0ZW5zb3InKTtcbiAgfVxufTtcblxuY29uc3QgZ2V0QWRqdXN0ZWRQZXJtID0gKGlucHV0U2hhcGU6IHJlYWRvbmx5IG51bWJlcltdLCBwZXJtOiBudW1iZXJbXSk6IG51bWJlcltdID0+XG4gICAgKHBlcm0gJiYgcGVybS5sZW5ndGggIT09IGlucHV0U2hhcGUubGVuZ3RoKSA/IFsuLi4oaW5wdXRTaGFwZS5rZXlzKCkpXS5yZXZlcnNlKCkgOiBwZXJtO1xuXG5jb25zdCBnZXRPdXRwdXRTaGFwZSA9IChpbnB1dFNoYXBlOiByZWFkb25seSBudW1iZXJbXSwgcGVybTogbnVtYmVyW10pOiByZWFkb25seSBudW1iZXJbXSA9PlxuICAgIFNoYXBlVXRpbC5zb3J0QmFzZWRPblBlcm0oaW5wdXRTaGFwZSwgZ2V0QWRqdXN0ZWRQZXJtKGlucHV0U2hhcGUsIHBlcm0pKTtcblxuY29uc3QgcGVybUZ1bmN0aW9uQm9keSA9IChwZXJtOiBudW1iZXJbXSwgcmFuazogbnVtYmVyKTogc3RyaW5nID0+IHtcbiAgY29uc3QgcmV2ZXJzZUZ1bmMgPSBbXTtcbiAgcmV2ZXJzZUZ1bmMucHVzaChgZm4gcGVybShhOiBwdHI8ZnVuY3Rpb24sIGFycmF5PHUzMiwgJHtyYW5rfT4+LCBpOiBwdHI8ZnVuY3Rpb24sIGFycmF5PHUzMiwgJHtyYW5rfT4+KSB7YCk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcmFuazsgKytpKSB7XG4gICAgcmV2ZXJzZUZ1bmMucHVzaChgXFx0KCphKVske3Blcm1baV19XT0oKmkpWyR7aX1dO2ApO1xuICB9XG4gIHJldmVyc2VGdW5jLnB1c2goJ1xcdH0nKTtcbiAgcmV0dXJuIHJldmVyc2VGdW5jLmpvaW4oJ1xcbicpO1xufTtcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvID0gKGlucHV0OiBUZW5zb3JWaWV3LCBwZXJtQXR0cjogbnVtYmVyW10pOiBQcm9ncmFtSW5mbyA9PiB7XG4gIGNvbnN0IGRhdGFUeXBlID0gJ2YzMic7ICAvLyBUT0RPOiBzdXBwb3J0IG90aGVyIGRhdGEgdHlwZVxuICBjb25zdCBpbnB1dFNoYXBlID0gaW5wdXQuZGltcztcbiAgY29uc3QgcGVybSA9IGdldEFkanVzdGVkUGVybShpbnB1dFNoYXBlLCBwZXJtQXR0cik7XG4gIGNvbnN0IG91dHB1dFNoYXBlID0gZ2V0T3V0cHV0U2hhcGUoaW5wdXRTaGFwZSwgcGVybSk7XG4gIGNvbnN0IHJhbmsgPSBpbnB1dFNoYXBlLmxlbmd0aDtcbiAgY29uc3Qgb3V0cHV0U2l6ZSA9IFNoYXBlVXRpbC5zaXplKG91dHB1dFNoYXBlKTtcbiAgLy8gQSBkaW1zPVske2lucHV0c1swXS5kaW1zLnRvU3RyaW5nKCl9XVxuICAvLyBvdXQgRGltcz1bJHt1bnBhY2tlZE91dHB1dFNoYXBlLnRvU3RyaW5nKCl9XVxuICAvLyBiYXNlZCBvbiBwZXJtPVske3Blcm0udG9TdHJpbmcoKX1dXG5cbiAgY29uc3Qgb3V0cHV0SW5kaWNlc0hlbHBlciA9IGNyZWF0ZUluZGljZXNIZWxwZXIoJ291dHB1dCcsIG91dHB1dFNoYXBlKTtcbiAgY29uc3QgaW5wdXRJbmRpY2VzSGVscGVyID0gY3JlYXRlSW5kaWNlc0hlbHBlcignYScsIGlucHV0U2hhcGUpO1xuXG4gIGNvbnN0IGdldFNoYWRlclNvdXJjZSA9IChzaGFkZXJIZWxwZXI6IFNoYWRlckhlbHBlcikgPT4gYFxuICBAZ3JvdXAoMCkgQGJpbmRpbmcoMCkgdmFyPHN0b3JhZ2UsIHJlYWQ+IGEgOiBhcnJheTwke2RhdGFUeXBlfT47XG4gIEBncm91cCgwKSBAYmluZGluZygxKSB2YXI8c3RvcmFnZSwgcmVhZF93cml0ZT4gb3V0cHV0IDogYXJyYXk8JHtkYXRhVHlwZX0+O1xuXG4gICR7cGVybUZ1bmN0aW9uQm9keShwZXJtLCByYW5rKX1cbiAgJHtvdXRwdXRJbmRpY2VzSGVscGVyLm8yaUltcGx9XG4gICR7aW5wdXRJbmRpY2VzSGVscGVyLmkyb0ltcGx9XG5cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcyhvdXRwdXRTaXplKX1cblxuICAgICR7b3V0cHV0SW5kaWNlc0hlbHBlci5pbmRpY2VzVmFyaWFibGVEZWNsYXJhdGlvbignaW5kaWNlcycpfVxuICAgICR7b3V0cHV0SW5kaWNlc0hlbHBlci5vMmlDYWxsKCdnbG9iYWxfaWR4JywgJ2luZGljZXMnKX1cbiAgICAke2lucHV0SW5kaWNlc0hlbHBlci5pbmRpY2VzVmFyaWFibGVEZWNsYXJhdGlvbignYUluZGljZXMnKX1cbiAgICBwZXJtKCZhSW5kaWNlcywgJmluZGljZXMpO1xuXG4gICAgb3V0cHV0W2dsb2JhbF9pZHhdID0gYVske2lucHV0SW5kaWNlc0hlbHBlci5pMm9FeHByZXNzaW9uKCdhSW5kaWNlcycpfV07XG4gIH1gO1xuICByZXR1cm4ge1xuICAgIC4uLnRyYW5zcG9zZVByb2dyYW1NZXRhZGF0YSxcbiAgICBvdXRwdXRzOiBbe2RpbXM6IG91dHB1dFNoYXBlLCBkYXRhVHlwZTogaW5wdXQuZGF0YVR5cGUsIGdwdURhdGFUeXBlOiBHcHVEYXRhVHlwZS5kZWZhdWx0fV0sXG4gICAgZ2V0U2hhZGVyU291cmNlLFxuICAgIGRpc3BhdGNoR3JvdXA6ICgpID0+ICh7eDogTWF0aC5jZWlsKG91dHB1dFNpemUgLyA2NCAvKiB3b3JrZ3JvdXAgc2l6ZSAqLyl9KVxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IHRyYW5zcG9zZSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCwgYXR0cmlidXRlczogVHJhbnNwb3NlQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICB2YWxpZGF0ZUlucHV0cyhjb250ZXh0LmlucHV0cyk7XG4gIGNvbnRleHQuY29tcHV0ZSh7XG4gICAgLi4udHJhbnNwb3NlUHJvZ3JhbU1ldGFkYXRhLFxuICAgIGNhY2hlSGludDogYXR0cmlidXRlcy5jYWNoZUtleSxcbiAgICBnZXQ6ICgpID0+IGNyZWF0ZVRyYW5zcG9zZVByb2dyYW1JbmZvKGNvbnRleHQuaW5wdXRzWzBdLCBhdHRyaWJ1dGVzLnBlcm0pXG4gIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IHBhcnNlVHJhbnNwb3NlQXR0cmlidXRlcyA9IChhdHRyaWJ1dGVzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IFRyYW5zcG9zZUF0dHJpYnV0ZXMgPT5cbiAgICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe3Blcm06IGF0dHJpYnV0ZXMucGVybSBhcyBudW1iZXJbXX0pO1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7VGVuc29yVmlld30gZnJvbSAnLi4vLi4vdGVuc29yJztcbmltcG9ydCB7TUFYX0NMSVAsIE1JTl9DTElQLCBTaGFwZVV0aWx9IGZyb20gJy4uLy4uL3V0aWwnO1xuaW1wb3J0IHtBdHRyaWJ1dGVXaXRoQ2FjaGVLZXksIGNyZWF0ZUF0dHJpYnV0ZVdpdGhDYWNoZUtleX0gZnJvbSAnLi4vYXR0cmlidXRlLXdpdGgtY2FjaGUta2V5JztcbmltcG9ydCB7Q29tcHV0ZUNvbnRleHQsIEdwdURhdGFUeXBlLCBQcm9ncmFtSW5mbywgUHJvZ3JhbUluZm9Mb2FkZXIsIFByb2dyYW1NZXRhZGF0YX0gZnJvbSAnLi4vdHlwZXMnO1xuXG5pbXBvcnQge1NoYWRlckhlbHBlcn0gZnJvbSAnLi9jb21tb24nO1xuXG50eXBlIEJ1aWx0aW5GdW5jdGlvbk5hbWUgPSBzdHJpbmc7XG50eXBlIEVsZW1lbnR3aXNlQ3VzdG9tRXhwcmVzc2lvbiA9IChleHByZXNzaW9uOiBzdHJpbmcpID0+IHN0cmluZztcbnR5cGUgRWxlbWVudHdpc2VGdW5jdGlvbkNhbGwgPSBCdWlsdGluRnVuY3Rpb25OYW1lfEVsZW1lbnR3aXNlQ3VzdG9tRXhwcmVzc2lvbjtcblxuY29uc3QgY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtU2hhZGVyID1cbiAgICAoc2hhZGVySGVscGVyOiBTaGFkZXJIZWxwZXIsIGRhdGFzaXplOiBudW1iZXIsIGZ1bmNDYWxsOiBFbGVtZW50d2lzZUZ1bmN0aW9uQ2FsbCxcbiAgICAgYWRkaXRpb25hbEltcGxlbWVudGF0aW9uPzogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgICAgIGNvbnN0IHZlY1NpemUgPSBNYXRoLmNlaWwoZGF0YXNpemUgLyA0KTtcblxuICAgICAgbGV0IGV4cHJlc3Npb24gPSAnJztcbiAgICAgIGlmICh0eXBlb2YgZnVuY0NhbGwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGV4cHJlc3Npb24gPSBgJHtmdW5jQ2FsbH0oYSlgO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXhwcmVzc2lvbiA9IGZ1bmNDYWxsKCdhJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gYFxuICBAZ3JvdXAoMCkgQGJpbmRpbmcoMCkgdmFyPHN0b3JhZ2UsIHJlYWQ+IGlucHV0RGF0YSA6IGFycmF5PHZlYzQ8ZjMyPj47XG4gIEBncm91cCgwKSBAYmluZGluZygxKSB2YXI8c3RvcmFnZSwgcmVhZF93cml0ZT4gb3V0cHV0RGF0YSA6IGFycmF5PHZlYzQ8ZjMyPj47XG5cbiAgJHthZGRpdGlvbmFsSW1wbGVtZW50YXRpb24gPz8gJyd9XG5cbiAgJHtzaGFkZXJIZWxwZXIubWFpblN0YXJ0KCl9XG4gICAgJHtzaGFkZXJIZWxwZXIuZ3VhcmRBZ2FpbnN0T3V0T2ZCb3VuZHNXb3JrZ3JvdXBTaXplcyh2ZWNTaXplKX1cblxuICAgIGxldCBhID0gaW5wdXREYXRhW2dsb2JhbF9pZHhdO1xuICAgIG91dHB1dERhdGFbZ2xvYmFsX2lkeF0gPSAke2V4cHJlc3Npb259O1xuICB9YDtcbiAgICB9O1xuXG5jb25zdCBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvID1cbiAgICAobWV0YWRhdGE6IFByb2dyYW1NZXRhZGF0YSwgaW5wdXQ6IFRlbnNvclZpZXcsIGZ1bmNDYWxsOiBFbGVtZW50d2lzZUZ1bmN0aW9uQ2FsbCxcbiAgICAgYWRkaXRpb25hbEltcGxlbWVudGF0aW9uPzogc3RyaW5nKTogUHJvZ3JhbUluZm8gPT4gKHtcbiAgICAgIC4uLm1ldGFkYXRhLFxuICAgICAgZ2V0U2hhZGVyU291cmNlOiBzaGFkZXJIZWxwZXIgPT5cbiAgICAgICAgICBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1TaGFkZXIoc2hhZGVySGVscGVyLCBTaGFwZVV0aWwuc2l6ZShpbnB1dC5kaW1zKSwgZnVuY0NhbGwsIGFkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbiksXG4gICAgICBvdXRwdXRzOiBbe2RpbXM6IGlucHV0LmRpbXMsIGRhdGFUeXBlOiBpbnB1dC5kYXRhVHlwZSwgZ3B1RGF0YVR5cGU6IEdwdURhdGFUeXBlLmRlZmF1bHR9XSxcbiAgICAgIGRpc3BhdGNoR3JvdXA6IChpbnB1dFRlbnNvcnMpID0+XG4gICAgICAgICAgKHt4OiBNYXRoLmNlaWwoU2hhcGVVdGlsLnNpemUoaW5wdXRUZW5zb3JzWzBdLmRpbXMpIC8gNjQgLyogd29ya2dyb3VwIHNpemUgKi8gLyA0IC8qIHZlYyBzaXplICovKX0pXG4gICAgfSk7XG5cbmNvbnN0IGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIgPVxuICAgIChpbnB1dDogVGVuc29yVmlldywgbmFtZTogc3RyaW5nLCBmdW5jQ2FsbDogRWxlbWVudHdpc2VGdW5jdGlvbkNhbGwsIGFkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbj86IHN0cmluZyxcbiAgICAgY2FjaGVLZXk/OiBzdHJpbmcpOiBQcm9ncmFtSW5mb0xvYWRlciA9PiB7XG4gICAgICBjb25zdCBtZXRhZGF0YTogUHJvZ3JhbU1ldGFkYXRhID0ge25hbWUsIGlucHV0VHlwZXM6IFtHcHVEYXRhVHlwZS5kZWZhdWx0XSwgY2FjaGVIaW50OiBjYWNoZUtleX07XG4gICAgICByZXR1cm4ge1xuICAgICAgICAuLi5tZXRhZGF0YSxcbiAgICAgICAgZ2V0OiAoKSA9PiBjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvKG1ldGFkYXRhLCBpbnB1dCwgZnVuY0NhbGwsIGFkZGl0aW9uYWxJbXBsZW1lbnRhdGlvbilcbiAgICAgIH07XG4gICAgfTtcblxuZXhwb3J0IGNvbnN0IGFicyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihjb250ZXh0LmlucHV0c1swXSwgJ0FicycsICdhYnMnKSk7XG59O1xuXG5leHBvcnQgY29uc3QgYWNvcyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihjb250ZXh0LmlucHV0c1swXSwgJ0Fjb3MnLCAnYWNvcycpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBhY29zaCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihjb250ZXh0LmlucHV0c1swXSwgJ0Fjb3NoJywgJ2Fjb3NoJykpO1xufTtcblxuZXhwb3J0IGNvbnN0IGFzaW4gPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoY29udGV4dC5pbnB1dHNbMF0sICdBc2luJywgJ2FzaW4nKSk7XG59O1xuXG5leHBvcnQgY29uc3QgYXNpbmggPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoY29udGV4dC5pbnB1dHNbMF0sICdBc2luaCcsICdhc2luaCcpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBhdGFuID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvTG9hZGVyKGNvbnRleHQuaW5wdXRzWzBdLCAnQXRhbicsICdhdGFuJykpO1xufTtcbmV4cG9ydCBjb25zdCBhdGFuaCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihjb250ZXh0LmlucHV0c1swXSwgJ0F0YW5oJywgJ2F0YW5oJykpO1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBDbGlwQXR0cmlidXRlcyBleHRlbmRzIEF0dHJpYnV0ZVdpdGhDYWNoZUtleSB7XG4gIHJlYWRvbmx5IG1pbjogbnVtYmVyO1xuICByZWFkb25seSBtYXg6IG51bWJlcjtcbn1cblxuZXhwb3J0IGNvbnN0IGNsaXBWMTAgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IENsaXBBdHRyaWJ1dGVzKTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShcbiAgICAgIGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoXG4gICAgICAgICAgY29udGV4dC5pbnB1dHNbMF0sICdDbGlwJywgYSA9PiBgY2xhbXAoJHthfSwgY2xpcF9taW5fLCBjbGlwX21heF8pYCwgYFxuICAgIGNvbnN0IGNsaXBfbWluXzogdmVjNDxmMzI+ID0gdmVjNChmMzIoJHthdHRyaWJ1dGVzLm1pbn0pKTtcbiAgICBjb25zdCBjbGlwX21heF86IHZlYzQ8ZjMyPiA9IHZlYzQoZjMyKCR7YXR0cmlidXRlcy5tYXh9KSk7XG5gLFxuICAgICAgICAgIGF0dHJpYnV0ZXMuY2FjaGVLZXkpLFxuICAgICAge2lucHV0czogWzBdfSk7XG59O1xuY29uc3QgZ2VuZXJhdGVDbGlwQXR0cmlidXRlc0Zyb21JbnB1dHMgPSAoaW5wdXRzOiByZWFkb25seSBUZW5zb3JWaWV3W10pOiBDbGlwQXR0cmlidXRlcyA9PiB7XG4gIGNvbnN0IG1pbiA9IChpbnB1dHMubGVuZ3RoID49IDIpID8gaW5wdXRzWzFdLmdldEZsb2F0MzJBcnJheSgpWzBdIDogTUlOX0NMSVA7XG4gIGNvbnN0IG1heCA9IChpbnB1dHMubGVuZ3RoID49IDMpID8gaW5wdXRzWzJdLmdldEZsb2F0MzJBcnJheSgpWzBdIDogTUFYX0NMSVA7XG4gIHJldHVybiBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoe21pbiwgbWF4fSk7XG59O1xuXG5leHBvcnQgY29uc3QgY2xpcCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb25zdCBhdHRyaWJ1dGVzID0gZ2VuZXJhdGVDbGlwQXR0cmlidXRlc0Zyb21JbnB1dHMoY29udGV4dC5pbnB1dHMpO1xuICBjbGlwVjEwKGNvbnRleHQsIGF0dHJpYnV0ZXMpO1xufTtcblxuZXhwb3J0IGNvbnN0IGNlaWwgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoY29udGV4dC5pbnB1dHNbMF0sICdDZWlsJywgJ2NlaWwnKSk7XG59O1xuXG5leHBvcnQgY29uc3QgY29zID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvTG9hZGVyKGNvbnRleHQuaW5wdXRzWzBdLCAnQ29zJywgJ2NvcycpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBjb3NoID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvTG9hZGVyKGNvbnRleHQuaW5wdXRzWzBdLCAnQ29zaCcsICdjb3NoJykpO1xufTtcblxuZXhwb3J0IGludGVyZmFjZSBBbHBoYUF0dHJpYnV0ZXMgZXh0ZW5kcyBBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkge1xuICByZWFkb25seSBhbHBoYTogbnVtYmVyO1xufVxuXG5leHBvcnQgY29uc3QgcGFyc2VBbHBoYUF0dHJpYnV0ZXMgPSAoYXR0cmlidXRlczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBBbHBoYUF0dHJpYnV0ZXMgPT5cbiAgICBjcmVhdGVBdHRyaWJ1dGVXaXRoQ2FjaGVLZXkoYXR0cmlidXRlcyBhcyB7YWxwaGE6IG51bWJlcn0pO1xuXG5leHBvcnQgY29uc3QgZWx1ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0LCBhdHRyaWJ1dGVzOiBBbHBoYUF0dHJpYnV0ZXMpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoXG4gICAgICBjb250ZXh0LmlucHV0c1swXSwgJ0VsdScsIGEgPT4gYGVsdV92ZjMyKCR7YX0pYCwgYFxuICBjb25zdCBlbHVfYWxwaGFfOiBmMzIgPSBmMzIoJHthdHRyaWJ1dGVzLmFscGhhfSk7XG5cbiAgZm4gZWx1X2YzMihhOiBmMzIpIC0+IGYzMiB7XG4gIHJldHVybiBzZWxlY3QoKGV4cChhKSAtIDEuMCkgKiBlbHVfYWxwaGFfLCBhLCBhID49IDAuMCk7XG4gIH1cblxuICBmbiBlbHVfdmYzMih2OiB2ZWM0PGYzMj4pIC0+IHZlYzQ8ZjMyPiB7XG4gIHJldHVybiB2ZWM0KGVsdV9mMzIodi54KSwgZWx1X2YzMih2LnkpLCBlbHVfZjMyKHYueiksIGVsdV9mMzIodi53KSk7XG4gIH1gLFxuICAgICAgYXR0cmlidXRlcy5jYWNoZUtleSkpO1xufTtcblxuZXhwb3J0IGNvbnN0IGVyZiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihjb250ZXh0LmlucHV0c1swXSwgJ0VyZicsIGEgPT4gYGVyZl92ZjMyKCR7YX0pYCwgYFxuICBjb25zdCByMDogZjMyID0gMC4zMjc1OTExO1xuICBjb25zdCByMTogZjMyID0gMC4yNTQ4Mjk1OTI7XG4gIGNvbnN0IHIyOiBmMzIgPSAtMC4yODQ0OTY3MzY7XG4gIGNvbnN0IHIzOiBmMzIgPSAxLjQyMTQxMzc0MTtcbiAgY29uc3QgcjQ6IGYzMiA9IC0xLjQ1MzE1MjAyNztcbiAgY29uc3QgcjU6IGYzMiA9IDEuMDYxNDA1NDI5O1xuXG4gIGZuIGVyZl92ZjMyKHY6IHZlYzQ8ZjMyPikgLT4gdmVjNDxmMzI+IHtcbiAgICBsZXQgYWJzdiA9IGFicyh2KTtcbiAgICBsZXQgeCA9IDEuMCAvICgxLjAgKyByMCAqIGFic3YpO1xuICAgIHJldHVybiBzaWduKHYpICogKDEuMCAtICgoKChyNSAqIHggKyByNCkgKiB4ICsgcjMpICogeCArIHIyKSAqIHggKyByMSkgKiB4ICogZXhwKC1hYnN2ICogYWJzdikpO1xuICB9YCkpO1xufTtcblxuZXhwb3J0IGNvbnN0IGV4cCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihjb250ZXh0LmlucHV0c1swXSwgJ0V4cCcsICdleHAnKSk7XG59O1xuXG5leHBvcnQgY29uc3QgZmxvb3IgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoY29udGV4dC5pbnB1dHNbMF0sICdGbG9vcicsICdmbG9vcicpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBsZWFreVJlbHUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEFscGhhQXR0cmlidXRlcyk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLCAnTGVha3lSZWx1JywgYSA9PiBgc2VsZWN0KGxlYWt5X3JlbHVfYWxwaGFfICogJHthfSwgJHthfSwgJHthfSA+PSB2ZWM0PGYzMj4oMC4wKSlgLFxuICAgICAgYGNvbnN0IGxlYWt5X3JlbHVfYWxwaGFfOiBmMzIgPSBmMzIoJHthdHRyaWJ1dGVzLmFscGhhfSk7YCwgYXR0cmlidXRlcy5jYWNoZUtleSkpO1xufTtcblxuZXhwb3J0IGNvbnN0IG5lZyA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihjb250ZXh0LmlucHV0c1swXSwgJ05lZycsIGEgPT4gYC0ke2F9YCkpO1xufTtcblxuZXhwb3J0IGNvbnN0IHJlY2lwcm9jYWwgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQpOiB2b2lkID0+IHtcbiAgY29udGV4dC5jb21wdXRlKGNyZWF0ZUVsZW1lbnR3aXNlUHJvZ3JhbUluZm9Mb2FkZXIoY29udGV4dC5pbnB1dHNbMF0sICdSZWNpcHJvY2FsJywgYSA9PiBgMS4wLyR7YX1gKSk7XG59O1xuXG5leHBvcnQgY29uc3QgcmVsdSA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihcbiAgICAgIGNvbnRleHQuaW5wdXRzWzBdLCAnUmVsdScsIGEgPT4gYHNlbGVjdCh2ZWM0PGYzMj4oMC4wKSwgJHthfSwgJHthfSA+IHZlYzQ8ZjMyPigwLjApKWApKTtcbn07XG5cbmV4cG9ydCBjb25zdCBzaWdtb2lkID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvTG9hZGVyKGNvbnRleHQuaW5wdXRzWzBdLCAnU2lnbW9pZCcsIGEgPT4gYCgxLjAgLyAoMS4wICsgZXhwKC0ke2F9KSkpYCkpO1xufTtcblxuZXhwb3J0IGNvbnN0IHNpbiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihjb250ZXh0LmlucHV0c1swXSwgJ1NpbicsICdzaW4nKSk7XG59O1xuXG5leHBvcnQgY29uc3Qgc2luaCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihjb250ZXh0LmlucHV0c1swXSwgJ1NpbmgnLCAnc2luaCcpKTtcbn07XG5cbmV4cG9ydCBjb25zdCBzcXJ0ID0gKGNvbnRleHQ6IENvbXB1dGVDb250ZXh0KTogdm9pZCA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvTG9hZGVyKGNvbnRleHQuaW5wdXRzWzBdLCAnU3FydCcsICdzcXJ0JykpO1xufTtcblxuZXhwb3J0IGNvbnN0IHRhbiA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihjb250ZXh0LmlucHV0c1swXSwgJ1RhbicsICd0YW4nKSk7XG59O1xuXG5leHBvcnQgY29uc3QgdGFuaCA9IChjb250ZXh0OiBDb21wdXRlQ29udGV4dCk6IHZvaWQgPT4ge1xuICBjb250ZXh0LmNvbXB1dGUoY3JlYXRlRWxlbWVudHdpc2VQcm9ncmFtSW5mb0xvYWRlcihjb250ZXh0LmlucHV0c1swXSwgJ1RhbmgnLCAndGFuaCcpKTtcbn07XG5cbmV4cG9ydCBjb25zdCB0aHJlc2hvbGRlZFJlbHUgPSAoY29udGV4dDogQ29tcHV0ZUNvbnRleHQsIGF0dHJpYnV0ZXM6IEFscGhhQXR0cmlidXRlcyk6IG51bWJlciA9PiB7XG4gIGNvbnRleHQuY29tcHV0ZShjcmVhdGVFbGVtZW50d2lzZVByb2dyYW1JbmZvTG9hZGVyKFxuICAgICAgY29udGV4dC5pbnB1dHNbMF0sICdUaHJlc2hvbGRlZFJlbHUnLCBhID0+IGBzZWxlY3QodmVjNDxmMzI+KDAuMCksICR7YX0sICR7YX0gPiB0aHJlc2hvbGRlZF9yZWx1X2FscGhhXylgLFxuICAgICAgYGNvbnN0IHRocmVzaG9sZGVkX3JlbHVfYWxwaGFfOiB2ZWM0PGYzMj4gPSB2ZWM0PGYzMj4oJHthdHRyaWJ1dGVzLmFscGhhfSk7YCwgYXR0cmlidXRlcy5jYWNoZUtleSkpO1xuICByZXR1cm4gMDtcbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtXZWJHcHVCYWNrZW5kfSBmcm9tICcuLi9iYWNrZW5kLXdlYmdwdSc7XG5pbXBvcnQge0xPR19ERUJVR30gZnJvbSAnLi4vbG9nJztcblxuaW1wb3J0IHtjcmVhdGVTaGFkZXJIZWxwZXJ9IGZyb20gJy4vb3BzL2NvbW1vbic7XG5pbXBvcnQge0FydGlmYWN0LCBHcHVEYXRhLCBQcm9ncmFtSW5mb30gZnJvbSAnLi90eXBlcyc7XG5cbi8qKlxuICogUHJvZ3JhbU1hbmFnZXIgaXMgdGhlIG1haW4gY2xhc3MgYmVoaW5kIHJ1bm5pbmcgY29tcHV0YXRpb25zXG4gKiBJdCBidWlsZHMgUHJvZ3JhbUluZm8ncyBpbnRvIEFydGlmYWN0c1xuICogSXQgY29tcGlsZXMgZ2l2ZW4gUHJvZ3JhbUluZm8ncyBpbnRvIFdlYkdMIFByb3JhbXMgKGNhY2hlZCBhcyBBcnRpZmFjdHMpXG4gKiBVc2VzIHRoZSBhcnRpZmFjdCB0byBydW4gdGhlIGNvbXB1dGF0aW9uIGJ5IGNhbGxpbmcgRHJhdyBvblxuICogdGhlIFdlYkdMIGRyYXdpbmcgYnVmZmVyXG4gKiBQcm9ncmFtTWFuYWdlciBhdXRvbWF0aWNhbGx5IG1hcHMgKGJpbmRzKSBpbnB1dCB2YXJpYWJsZXMgdG8gdGhlaXJcbiAqIGNvcnJlc3BvbmRpbmcgTG9jYXRpb24ncyBpbiB0aGUgYmluYXJ5IHByb2dyYW1cbiAqL1xuZXhwb3J0IGNsYXNzIFByb2dyYW1NYW5hZ2VyIHtcbiAgcmVwbzogTWFwPHVua25vd24sIEFydGlmYWN0PjsgIC8vIHRoaXMgc2hvdWxkIGJlIHBlci1zZXNzaW9uIG9iamVjdFxuICBhdHRyaWJ1dGVzQm91bmQ6IGJvb2xlYW47XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBiYWNrZW5kOiBXZWJHcHVCYWNrZW5kKSB7XG4gICAgdGhpcy5yZXBvID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuYXR0cmlidXRlc0JvdW5kID0gZmFsc2U7XG4gIH1cbiAgZ2V0QXJ0aWZhY3Qoa2V5OiB1bmtub3duKTogQXJ0aWZhY3R8dW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5yZXBvLmdldChrZXkpO1xuICB9XG4gIHNldEFydGlmYWN0KGtleTogdW5rbm93biwgYXJ0aWZhY3Q6IEFydGlmYWN0KTogdm9pZCB7XG4gICAgdGhpcy5yZXBvLnNldChrZXksIGFydGlmYWN0KTtcbiAgfVxuICBydW4oYnVpbGRBcnRpZmFjdDogQXJ0aWZhY3QsIGlucHV0czogR3B1RGF0YVtdLCBvdXRwdXRzOiBHcHVEYXRhW10sIGRpc3BhdGNoR3JvdXA6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSk6IHZvaWQge1xuICAgIGNvbnN0IGRldmljZSA9IHRoaXMuYmFja2VuZC5kZXZpY2U7XG4gICAgY29uc3QgY29tcHV0ZVBhc3NFbmNvZGVyID0gdGhpcy5iYWNrZW5kLmdldENvbXB1dGVQYXNzRW5jb2RlcigpO1xuXG4gICAgaWYgKHRoaXMuYmFja2VuZC5wcm9maWxpbmdFbmFibGVkKSB7XG4gICAgICAvLyBwcm9maWxpbmcgd3JpdGUgc3RhcnQgdGltZXN0YW1wXG5cbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55XG4gICAgICAoY29tcHV0ZVBhc3NFbmNvZGVyIGFzIGFueSkud3JpdGVUaW1lc3RhbXAodGhpcy5iYWNrZW5kLnByb2ZpbGluZ1F1ZXJ5U2V0LCAwKTtcbiAgICB9XG5cbiAgICBjb21wdXRlUGFzc0VuY29kZXIuc2V0UGlwZWxpbmUoYnVpbGRBcnRpZmFjdC5jb21wdXRlUGlwZWxpbmUpO1xuICAgIGNvbnN0IGVudHJpZXMgPSBbXTtcbiAgICBmb3IgKGNvbnN0IGlucHV0IG9mIGlucHV0cykge1xuICAgICAgZW50cmllcy5wdXNoKHtiaW5kaW5nOiBlbnRyaWVzLmxlbmd0aCwgcmVzb3VyY2U6IHtidWZmZXI6IGlucHV0LmJ1ZmZlcn19KTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBvdXRwdXQgb2Ygb3V0cHV0cykge1xuICAgICAgZW50cmllcy5wdXNoKHtiaW5kaW5nOiBlbnRyaWVzLmxlbmd0aCwgcmVzb3VyY2U6IHtidWZmZXI6IG91dHB1dC5idWZmZXJ9fSk7XG4gICAgfVxuICAgIGNvbnN0IGJpbmRHcm91cCA9IGRldmljZS5jcmVhdGVCaW5kR3JvdXAoe2xheW91dDogYnVpbGRBcnRpZmFjdC5jb21wdXRlUGlwZWxpbmUuZ2V0QmluZEdyb3VwTGF5b3V0KDApLCBlbnRyaWVzfSk7XG4gICAgY29tcHV0ZVBhc3NFbmNvZGVyLnNldEJpbmRHcm91cCgwLCBiaW5kR3JvdXApO1xuXG4gICAgY29tcHV0ZVBhc3NFbmNvZGVyLmRpc3BhdGNoV29ya2dyb3VwcyguLi5kaXNwYXRjaEdyb3VwKTtcblxuICAgIHRoaXMuYmFja2VuZC5wZW5kaW5nRGlzcGF0Y2hOdW1iZXIrKztcblxuICAgIGlmICh0aGlzLmJhY2tlbmQucHJvZmlsaW5nRW5hYmxlZCkge1xuICAgICAgLy8gcHJvZmlsaW5nIHdyaXRlIGVuZCB0aW1lc3RhbXBcblxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICAgIChjb21wdXRlUGFzc0VuY29kZXIgYXMgYW55KS53cml0ZVRpbWVzdGFtcCh0aGlzLmJhY2tlbmQucHJvZmlsaW5nUXVlcnlTZXQsIDEpO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgICAgIGNvbnN0IHF1ZXJ5RGF0YSA9IHRoaXMuYmFja2VuZC5ncHVEYXRhTWFuYWdlci5jcmVhdGUoMTYsIEdQVUJ1ZmZlclVzYWdlLkNPUFlfU1JDIHwgR1BVQnVmZmVyVXNhZ2UuUVVFUllfUkVTT0xWRSk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tYml0d2lzZVxuICAgICAgY29uc3Qgc3luY0RhdGEgPSB0aGlzLmJhY2tlbmQuZ3B1RGF0YU1hbmFnZXIuY3JlYXRlKDE2LCBHUFVCdWZmZXJVc2FnZS5NQVBfUkVBRCB8IEdQVUJ1ZmZlclVzYWdlLkNPUFlfRFNUKTtcblxuICAgICAgdGhpcy5iYWNrZW5kLmVuZENvbXB1dGVQYXNzKCk7XG4gICAgICB0aGlzLmJhY2tlbmQuZ2V0Q29tbWFuZEVuY29kZXIoKS5yZXNvbHZlUXVlcnlTZXQodGhpcy5iYWNrZW5kLnByb2ZpbGluZ1F1ZXJ5U2V0LCAwLCAyLCBxdWVyeURhdGEuYnVmZmVyLCAwKTtcbiAgICAgIHRoaXMuYmFja2VuZC5nZXRDb21tYW5kRW5jb2RlcigpLmNvcHlCdWZmZXJUb0J1ZmZlcihxdWVyeURhdGEuYnVmZmVyLCAwLCBzeW5jRGF0YS5idWZmZXIsIDAsIDE2KTtcbiAgICAgIHRoaXMuYmFja2VuZC5mbHVzaCgpO1xuXG4gICAgICBjb25zdCBrZXJuZWxJZCA9IHRoaXMuYmFja2VuZC5jdXJyZW50S2VybmVsSWQhO1xuICAgICAgY29uc3Qga2VybmVsTmFtZSA9IHRoaXMuYmFja2VuZC5rZXJuZWxzLmdldChrZXJuZWxJZCkhWzBdO1xuXG4gICAgICBzeW5jRGF0YS5idWZmZXIubWFwQXN5bmMoR1BVTWFwTW9kZS5SRUFEKS50aGVuKCgpID0+IHtcbiAgICAgICAgY29uc3QgbWFwcGVkRGF0YSA9IG5ldyBCaWdVaW50NjRBcnJheShzeW5jRGF0YS5idWZmZXIuZ2V0TWFwcGVkUmFuZ2UoKSk7XG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZVU2NCA9IG1hcHBlZERhdGFbMF07XG4gICAgICAgIGNvbnN0IGVuZFRpbWVVNjQgPSBtYXBwZWREYXRhWzFdO1xuXG4gICAgICAgIHN5bmNEYXRhLmJ1ZmZlci51bm1hcCgpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5iYWNrZW5kLnByb2ZpbGluZ1RpbWVCYXNlID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHRoaXMuYmFja2VuZC5wcm9maWxpbmdUaW1lQmFzZSA9IHN0YXJ0VGltZVU2NDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHN0YXJ0VGltZSA9IE51bWJlcihzdGFydFRpbWVVNjQgLSB0aGlzLmJhY2tlbmQucHJvZmlsaW5nVGltZUJhc2UpO1xuICAgICAgICBjb25zdCBlbmRUaW1lID0gTnVtYmVyKGVuZFRpbWVVNjQgLSB0aGlzLmJhY2tlbmQucHJvZmlsaW5nVGltZUJhc2UpO1xuXG4gICAgICAgIGlmICghTnVtYmVyLmlzU2FmZUludGVnZXIoc3RhcnRUaW1lKSB8fCAhTnVtYmVyLmlzU2FmZUludGVnZXIoZW5kVGltZSkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignaW5jb3JyZWN0IHRpbWVzdGFtcCByYW5nZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5iYWNrZW5kLmdwdURhdGFNYW5hZ2VyLnJlbGVhc2UocXVlcnlEYXRhLmlkKTtcbiAgICAgICAgdGhpcy5iYWNrZW5kLmdwdURhdGFNYW5hZ2VyLnJlbGVhc2Uoc3luY0RhdGEuaWQpO1xuXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1jb25zb2xlXG4gICAgICAgIGNvbnNvbGUubG9nKGBbcHJvZmlsaW5nXSBrZXJuZWwgXCIke2tlcm5lbElkfXwke2tlcm5lbE5hbWV9XCIgZXhlY3V0aW9uIHRpbWU6ICR7ZW5kVGltZSAtIHN0YXJ0VGltZX0gbnNgKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmJhY2tlbmQucGVuZGluZ0Rpc3BhdGNoTnVtYmVyID49IDE2KSB7XG4gICAgICB0aGlzLmJhY2tlbmQuZmx1c2goKTtcbiAgICB9XG4gIH1cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICAvLyB0aGlzLnJlcG8uZm9yRWFjaChhID0+IHRoaXMuZ2xDb250ZXh0LmRlbGV0ZVByb2dyYW0oYS5wcm9ncmFtKSk7XG4gIH1cbiAgYnVpbGQocHJvZ3JhbUluZm86IFByb2dyYW1JbmZvLCBub3JtYWxpemVkRGlzcGF0Y2hHcm91cFNpemU6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSk6IEFydGlmYWN0IHtcbiAgICBjb25zdCBkZXZpY2UgPSB0aGlzLmJhY2tlbmQuZGV2aWNlO1xuXG4gICAgY29uc3QgY29kZSA9IHByb2dyYW1JbmZvLmdldFNoYWRlclNvdXJjZShjcmVhdGVTaGFkZXJIZWxwZXIobm9ybWFsaXplZERpc3BhdGNoR3JvdXBTaXplKSk7XG4gICAgY29uc3Qgc2hhZGVyTW9kdWxlID0gZGV2aWNlLmNyZWF0ZVNoYWRlck1vZHVsZSh7Y29kZX0pO1xuICAgIExPR19ERUJVRygndmVyYm9zZScsICgpID0+IGBbV2ViR1BVXSBzaGFkZXIgY29kZTogJHtjb2RlfWApO1xuXG4gICAgY29uc3QgY29tcHV0ZVBpcGVsaW5lID1cbiAgICAgICAgZGV2aWNlLmNyZWF0ZUNvbXB1dGVQaXBlbGluZSh7Y29tcHV0ZToge21vZHVsZTogc2hhZGVyTW9kdWxlLCBlbnRyeVBvaW50OiAnbWFpbid9LCBsYXlvdXQ6ICdhdXRvJ30pO1xuXG4gICAgcmV0dXJuIHtwcm9ncmFtSW5mbywgY29tcHV0ZVBpcGVsaW5lfTtcbiAgfVxuXG4gIG5vcm1hbGl6ZURpc3BhdGNoR3JvdXBTaXplKGRpc3BhdGNoR3JvdXA6IFJldHVyblR5cGU8UHJvZ3JhbUluZm9bJ2Rpc3BhdGNoR3JvdXAnXT4pOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0ge1xuICAgIGNvbnN0IHggPSB0eXBlb2YgZGlzcGF0Y2hHcm91cCA9PT0gJ251bWJlcicgPyBkaXNwYXRjaEdyb3VwIDogZGlzcGF0Y2hHcm91cC54O1xuICAgIGNvbnN0IHkgPSB0eXBlb2YgZGlzcGF0Y2hHcm91cCA9PT0gJ251bWJlcicgPyAxIDogKGRpc3BhdGNoR3JvdXAueSB8fCAxKTtcbiAgICBjb25zdCB6ID0gdHlwZW9mIGRpc3BhdGNoR3JvdXAgPT09ICdudW1iZXInID8gMSA6IChkaXNwYXRjaEdyb3VwLnogfHwgMSk7XG4gICAgY29uc3QgbGltaXRQZXJEaW1lbnNpb24gPSB0aGlzLmJhY2tlbmQuZGV2aWNlLmxpbWl0cy5tYXhDb21wdXRlV29ya2dyb3Vwc1BlckRpbWVuc2lvbjtcbiAgICBpZiAoeCA8PSBsaW1pdFBlckRpbWVuc2lvbiAmJiB5IDw9IGxpbWl0UGVyRGltZW5zaW9uICYmIHogPD0gbGltaXRQZXJEaW1lbnNpb24pIHtcbiAgICAgIHJldHVybiBbeCwgeSwgel07XG4gICAgfVxuICAgIGNvbnN0IHNpemUgPSB4ICogeSAqIHo7XG4gICAgbGV0IGRpc3BhdGNoQXZlcmFnZSA9IE1hdGguY2VpbChNYXRoLnNxcnQoc2l6ZSkpO1xuICAgIGlmIChkaXNwYXRjaEF2ZXJhZ2UgPiBsaW1pdFBlckRpbWVuc2lvbikge1xuICAgICAgZGlzcGF0Y2hBdmVyYWdlID0gTWF0aC5jZWlsKE1hdGguY2JydChzaXplKSk7XG4gICAgICBpZiAoZGlzcGF0Y2hBdmVyYWdlID4gbGltaXRQZXJEaW1lbnNpb24pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUb3RhbCBkaXNwYXRjaCBzaXplIGV4Y2VlZHMgV2ViR1BVIG1heGltdW0uJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gW2Rpc3BhdGNoQXZlcmFnZSwgZGlzcGF0Y2hBdmVyYWdlLCBkaXNwYXRjaEF2ZXJhZ2VdO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gW2Rpc3BhdGNoQXZlcmFnZSwgZGlzcGF0Y2hBdmVyYWdlLCAxXTtcbiAgICB9XG4gIH1cbn1cbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge1RlbnNvciwgVGVuc29yVmlld30gZnJvbSAnLi4vdGVuc29yJztcblxuaW1wb3J0IHtTaGFkZXJIZWxwZXJ9IGZyb20gJy4vb3BzL2NvbW1vbic7XG5cbmV4cG9ydCBlbnVtIEdwdURhdGFUeXBlIHtcbiAgZGVmYXVsdCA9IDAsXG4gIHVwbG9hZCA9IDEsXG4gIHByb2ZpbGUgPSAyXG59XG5leHBvcnQgdHlwZSBHcHVEYXRhSWQgPSBudW1iZXI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR3B1RGF0YSB7XG4gIHR5cGU6IEdwdURhdGFUeXBlO1xuICBpZDogR3B1RGF0YUlkO1xuICBidWZmZXI6IEdQVUJ1ZmZlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBUZW5zb3JJbmZvIHtcbiAgaWQ/OiBUZW5zb3IuSWQ7XG4gIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdO1xuICBkYXRhVHlwZTogbnVtYmVyO1xuICBncHVEYXRhVHlwZTogR3B1RGF0YVR5cGU7XG59XG5cblxuZXhwb3J0IGludGVyZmFjZSBQcm9ncmFtVmFyaWFibGUge1xuICB0eXBlOiAnZmxvYXQnfCdpbnQnO1xuICBuYW1lOiBzdHJpbmc7XG4gIGFycmF5TGVuZ3RoPzogbnVtYmVyO1xuICBkYXRhOiBudW1iZXJ8bnVtYmVyW107XG59XG5cblxuZXhwb3J0IGludGVyZmFjZSBQcm9ncmFtTWV0YWRhdGEge1xuICAvKipcbiAgICogdGhlIG5hbWUgb2YgdGhlIHByb2dyYW0uIHVzZWQgZm9yIGRlYnVnZ2luZyBhbmQgcHJvZmlsaW5nXG4gICAqL1xuICBuYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIGdwdSBkYXRhIHR5cGVzIGZvciBlYWNoIGlucHV0XG4gICAqL1xuICBpbnB1dFR5cGVzOiBHcHVEYXRhVHlwZVtdO1xuICAvKipcbiAgICogYW4gb3B0aW9uYWwgc3RyaW5nIGFzIGEgY2FjaGUgaGludCBpbiB0aGUgYXJ0aWZhY3QgY2FjaGVcbiAgICovXG4gIGNhY2hlSGludD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBBIFByb2dyYW1JbmZvTG9hZGVyIGFsbG93c1xuICovXG5leHBvcnQgaW50ZXJmYWNlIFByb2dyYW1JbmZvTG9hZGVyIGV4dGVuZHMgUHJvZ3JhbU1ldGFkYXRhIHtcbiAgLyoqXG4gICAqIGEgZnVuY3Rpb24gdG8gZ2V0IHRoZSBwcm9ncmFtIGluZm9cbiAgICovXG4gIGdldCgpOiBQcm9ncmFtSW5mbztcbn1cblxuLyoqXG4gKiBBIHNldCBvZiBkYXRhIHRoYXQgcmVwcmVzZW50IGEgc2hhZGVyIHByb2dyYW1cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQcm9ncmFtSW5mbyBleHRlbmRzIFByb2dyYW1NZXRhZGF0YSB7XG4gIC8qKlxuICAgKiBpbmZvcm1hdGlvbiBvZiB1bmlmb3JtIHZhcmlhYmxlc1xuICAgKi9cbiAgdmFyaWFibGVzPzogUHJvZ3JhbVZhcmlhYmxlW107XG4gIC8qKlxuICAgKiB0ZW5zb3IgaW5mbyBmb3Igb3V0cHV0c1xuICAgKi9cbiAgb3V0cHV0czogVGVuc29ySW5mb1tdO1xuICAvKipcbiAgICogdGhlIHNoYWRlcidzIHByb2Nlc3Npbmcgc291cmNlIGNvZGVcbiAgICovXG4gIGdldFNoYWRlclNvdXJjZTogKHNoYWRlckhlbHBlcjogU2hhZGVySGVscGVyKSA9PiBzdHJpbmc7XG4gIC8qKlxuICAgKiBkZWZhdWx0IGlzIFwibWFpblwiXG4gICAqL1xuICAvLyBlbnRyeVBvaW50OiBzdHJpbmc7XG5cbiAgZGlzcGF0Y2hHcm91cDogKGlucHV0czogcmVhZG9ubHkgVGVuc29yVmlld1tdKSA9PiB7XG4gICAgeDogbnVtYmVyO1xuICAgIHk/OiBudW1iZXI7XG4gICAgej86IG51bWJlcjtcbiAgfTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBcnRpZmFjdCB7XG4gIHByb2dyYW1JbmZvOiBQcm9ncmFtSW5mbztcbiAgY29tcHV0ZVBpcGVsaW5lOiBHUFVDb21wdXRlUGlwZWxpbmU7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29tcHV0ZUNvbnRleHRJbnB1dHNPdXRwdXRzTWFwcGluZyB7XG4gIC8qKlxuICAgKiBzcGVjaWZ5IHRoZSBtYXBwaW5nIHRvIHRoZSBwcm9ncmFtJ3MgaW5wdXRzLiB0aGUgdmFsdWUgY2FuIGJlIGEgbnVtYmVyIG9yIGEgdGVuc29yIHZpZXcuXG4gICAqIC0gaWYgaXQncyBhIG51bWJlciwgaXQncyB0aGUgaW5kZXggb2YgdGhlIGtlcm5lbCdzIGlucHV0XG4gICAqIC0gaWYgaXQncyBhIHRlbnNvciB2aWV3LCBpdCdzIGFuIGV4aXN0aW5nIHRlbnNvciB2aWV3IHRoYXQgd2lsbCBiZSB1c2VkIGFzIHRoZSBpbnB1dFxuICAgKlxuICAgKiBpZiBpbnB1dHMgaXMgbm90IHNwZWNpZmllZCwgdGhlIG1hcHBpbmcgd2lsbCBiZSB0aGUga2VybmVsJ3MgaW5wdXRzIGluIG9yZGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgaW5wdXRzPzogUmVhZG9ubHlBcnJheTxUZW5zb3JWaWV3fG51bWJlcj47XG4gIC8qKlxuICAgKiBzcGVjaWZ5IHRoZSBtYXBwaW5nIHRvIHRoZSBwcm9ncmFtJ3Mgb3V0cHV0cy4gdGhlIHZhbHVlIG11c3QgYmUgYSBudW1iZXIuXG4gICAqIC0gaWYgaXQncyBhIG5vbi1uZWdhdGl2ZSBudW1iZXIsIGl0J3MgdGhlIGluZGV4IG9mIHRoZSBrZXJuZWwncyBvdXRwdXRcbiAgICogLSBpZiBpdCdzIC0xLCBpdCdzIGFuIG91dHB1dCB0aGF0IHdpbGwgYmUgY3JlYXRlZCBhcyBhIHRlbXBvcmFyeSB2YWx1ZS4gdGhpcyB2YWx1ZSB3aWxsIGJlIHJlbGVhc2VkIGFmdGVyXG4gICAqIHRoZSBrZXJuZWwgaXMgZXhlY3V0ZWQuXG4gICAqIC0gaWYgaXQncyAtMiwgaXQncyBhbiBvdXRwdXQgdGhhdCB3aWxsIGJlIGNyZWF0ZWQgYXMgYSBwZXJzaXN0ZW50IHZhbHVlLiB0aGlzIHZhbHVlIHdpbGwgYmUgcmVsZWFzZWQgd2hlbiB0aGVcbiAgICoga2VybmVsIGlzIHJlbGVhc2VkLlxuICAgKlxuICAgKiBpZiBvdXRwdXRzIGlzIG5vdCBzcGVjaWZpZWQsIHRoZSBtYXBwaW5nIHdpbGwgYmUgdGhlIGtlcm5lbCdzIG91dHB1dHMgaW4gb3JkZXIuXG4gICAqL1xuICByZWFkb25seSBvdXRwdXRzPzogcmVhZG9ubHkgbnVtYmVyW107XG59XG5cbi8qKlxuICogQSBDb21wdXRlQ29udGV4dCBpbnN0YW5jZSBjYXJyaWVzIHRoZSBzdGF0ZXMgdGhhdCByZXByZXNlbnRpbmcgdGhlIGN1cnJlbnQgcnVubmluZyBvZiBhIGtlcm5lbC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb21wdXRlQ29udGV4dCB7XG4gIC8qKlxuICAgKiBzdG9yZXMgdGhlIHBvaW50ZXIgdG8gT3BLZXJuZWxDb250ZXh0XG4gICAqL1xuICByZWFkb25seSBvcEtlcm5lbENvbnRleHQ6IG51bWJlcjtcblxuICAvKipcbiAgICogYSBsaXN0IG9mIGlucHV0cywgZWFjaCBpbnB1dCBpcyBhbiBpbnN0YW5jZSBvZiBUZW5zb3JWaWV3XG4gICAqL1xuICByZWFkb25seSBpbnB1dHM6IHJlYWRvbmx5IFRlbnNvclZpZXdbXTtcblxuICAvKipcbiAgICogYSBjdXN0b20gZGF0YSBvYmplY3QgdGhhdCBjYW4gYmUgdXNlZCB0byBzdG9yZSBhbnkgZGF0YSB0aGF0IGlzIG5lZWRlZCBieSB0aGUga2VybmVsXG4gICAqL1xuICByZWFkb25seSBjdXN0b21EYXRhOiB7W2tleTogc3RyaW5nXTogdW5rbm93bn07XG5cbiAgY29tcHV0ZShwcm9ncmFtOiBQcm9ncmFtSW5mb0xvYWRlcnxQcm9ncmFtSW5mbywgaW5wdXRzT3V0cHV0c01hcHBpbmc/OiBDb21wdXRlQ29udGV4dElucHV0c091dHB1dHNNYXBwaW5nKTpcbiAgICAgIFRlbnNvclZpZXdbXTtcbiAgb3V0cHV0KGluZGV4OiBudW1iZXIsIGRpbXM6IHJlYWRvbmx5IG51bWJlcltdKTogbnVtYmVyO1xufVxuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmludGVyZmFjZSBFeHRyYU9wdGlvbnNIYW5kbGVyIHtcbiAgKG5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IHZvaWQ7XG59XG5cbmV4cG9ydCBjb25zdCBpdGVyYXRlRXh0cmFPcHRpb25zID1cbiAgICAob3B0aW9uczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sIHByZWZpeDogc3RyaW5nLCBzZWVuOiBXZWFrU2V0PFJlY29yZDxzdHJpbmcsIHVua25vd24+PixcbiAgICAgaGFuZGxlcjogRXh0cmFPcHRpb25zSGFuZGxlcik6IHZvaWQgPT4ge1xuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zID09ICdvYmplY3QnICYmIG9wdGlvbnMgIT09IG51bGwpIHtcbiAgICAgICAgaWYgKHNlZW4uaGFzKG9wdGlvbnMpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDaXJjdWxhciByZWZlcmVuY2UgaW4gb3B0aW9ucycpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNlZW4uYWRkKG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIE9iamVjdC5lbnRyaWVzKG9wdGlvbnMpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgICBjb25zdCBuYW1lID0gKHByZWZpeCkgPyBwcmVmaXggKyBrZXkgOiBrZXk7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgaXRlcmF0ZUV4dHJhT3B0aW9ucyh2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgbmFtZSArICcuJywgc2VlbiwgaGFuZGxlcik7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgaGFuZGxlcihuYW1lLCB2YWx1ZS50b1N0cmluZygpKTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJykge1xuICAgICAgICAgIGhhbmRsZXIobmFtZSwgKHZhbHVlKSA/ICcxJyA6ICcwJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4ndCBoYW5kbGUgZXh0cmEgY29uZmlnIHR5cGU6ICR7dHlwZW9mIHZhbHVlfWApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7ZW52LCBJbmZlcmVuY2VTZXNzaW9ufSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQge2luaXQgYXMgaW5pdEpzZXB9IGZyb20gJy4vanNlcC9pbml0JztcbmltcG9ydCB7T3J0V2FzbU1lc3NhZ2UsIFNlcmlhbGl6YWJsZU1vZGVsZGF0YSwgU2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhLCBTZXJpYWxpemFibGVUZW5zb3J9IGZyb20gJy4vcHJveHktbWVzc2FnZXMnO1xuaW1wb3J0ICogYXMgY29yZSBmcm9tICcuL3dhc20tY29yZS1pbXBsJztcbmltcG9ydCB7Z2V0SW5zdGFuY2UsIGluaXRpYWxpemVXZWJBc3NlbWJseX0gZnJvbSAnLi93YXNtLWZhY3RvcnknO1xuXG5jb25zdCBpc1Byb3h5ID0gKCk6IGJvb2xlYW4gPT4gISFlbnYud2FzbS5wcm94eSAmJiB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnO1xubGV0IHByb3h5V29ya2VyOiBXb3JrZXJ8dW5kZWZpbmVkO1xubGV0IGluaXRpYWxpemluZyA9IGZhbHNlO1xubGV0IGluaXRpYWxpemVkID0gZmFsc2U7XG5sZXQgYWJvcnRlZCA9IGZhbHNlO1xuXG4vLyByZXNvbHZlOyByZWplY3RcbnR5cGUgUHJvbWlzZUNhbGxiYWNrczxUID0gdm9pZD4gPSBbKHJlc3VsdDogVCkgPT4gdm9pZCwgKHJlYXNvbjogdW5rbm93bikgPT4gdm9pZF07XG5cbmxldCBpbml0V2FzbUNhbGxiYWNrczogUHJvbWlzZUNhbGxiYWNrcztcbmxldCBpbml0T3J0Q2FsbGJhY2tzOiBQcm9taXNlQ2FsbGJhY2tzO1xuY29uc3QgY3JlYXRlU2Vzc2lvbkFsbG9jYXRlQ2FsbGJhY2tzOiBBcnJheTxQcm9taXNlQ2FsbGJhY2tzPFNlcmlhbGl6YWJsZU1vZGVsZGF0YT4+ID0gW107XG5jb25zdCBjcmVhdGVTZXNzaW9uRmluYWxpemVDYWxsYmFja3M6IEFycmF5PFByb21pc2VDYWxsYmFja3M8U2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhPj4gPSBbXTtcbmNvbnN0IGNyZWF0ZVNlc3Npb25DYWxsYmFja3M6IEFycmF5PFByb21pc2VDYWxsYmFja3M8U2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhPj4gPSBbXTtcbmNvbnN0IHJlbGVhc2VTZXNzaW9uQ2FsbGJhY2tzOiBBcnJheTxQcm9taXNlQ2FsbGJhY2tzPHZvaWQ+PiA9IFtdO1xuY29uc3QgcnVuQ2FsbGJhY2tzOiBBcnJheTxQcm9taXNlQ2FsbGJhY2tzPFNlcmlhbGl6YWJsZVRlbnNvcltdPj4gPSBbXTtcbmNvbnN0IGVuZFByb2ZpbGluZ0NhbGxiYWNrczogQXJyYXk8UHJvbWlzZUNhbGxiYWNrczx2b2lkPj4gPSBbXTtcblxuY29uc3QgZW5zdXJlV29ya2VyID0gKCk6IHZvaWQgPT4ge1xuICBpZiAoaW5pdGlhbGl6aW5nIHx8ICFpbml0aWFsaXplZCB8fCBhYm9ydGVkIHx8ICFwcm94eVdvcmtlcikge1xuICAgIHRocm93IG5ldyBFcnJvcignd29ya2VyIG5vdCByZWFkeScpO1xuICB9XG59O1xuXG5jb25zdCBvblByb3h5V29ya2VyTWVzc2FnZSA9IChldjogTWVzc2FnZUV2ZW50PE9ydFdhc21NZXNzYWdlPik6IHZvaWQgPT4ge1xuICBzd2l0Y2ggKGV2LmRhdGEudHlwZSkge1xuICAgIGNhc2UgJ2luaXQtd2FzbSc6XG4gICAgICBpbml0aWFsaXppbmcgPSBmYWxzZTtcbiAgICAgIGlmIChldi5kYXRhLmVycikge1xuICAgICAgICBhYm9ydGVkID0gdHJ1ZTtcbiAgICAgICAgaW5pdFdhc21DYWxsYmFja3NbMV0oZXYuZGF0YS5lcnIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICAgICAgICBpbml0V2FzbUNhbGxiYWNrc1swXSgpO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnaW5pdC1vcnQnOlxuICAgICAgaWYgKGV2LmRhdGEuZXJyKSB7XG4gICAgICAgIGluaXRPcnRDYWxsYmFja3NbMV0oZXYuZGF0YS5lcnIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaW5pdE9ydENhbGxiYWNrc1swXSgpO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAnY3JlYXRlX2FsbG9jYXRlJzpcbiAgICAgIGlmIChldi5kYXRhLmVycikge1xuICAgICAgICBjcmVhdGVTZXNzaW9uQWxsb2NhdGVDYWxsYmFja3Muc2hpZnQoKSFbMV0oZXYuZGF0YS5lcnIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY3JlYXRlU2Vzc2lvbkFsbG9jYXRlQ2FsbGJhY2tzLnNoaWZ0KCkhWzBdKGV2LmRhdGEub3V0ISk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdjcmVhdGVfZmluYWxpemUnOlxuICAgICAgaWYgKGV2LmRhdGEuZXJyKSB7XG4gICAgICAgIGNyZWF0ZVNlc3Npb25GaW5hbGl6ZUNhbGxiYWNrcy5zaGlmdCgpIVsxXShldi5kYXRhLmVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjcmVhdGVTZXNzaW9uRmluYWxpemVDYWxsYmFja3Muc2hpZnQoKSFbMF0oZXYuZGF0YS5vdXQhKTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2NyZWF0ZSc6XG4gICAgICBpZiAoZXYuZGF0YS5lcnIpIHtcbiAgICAgICAgY3JlYXRlU2Vzc2lvbkNhbGxiYWNrcy5zaGlmdCgpIVsxXShldi5kYXRhLmVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjcmVhdGVTZXNzaW9uQ2FsbGJhY2tzLnNoaWZ0KCkhWzBdKGV2LmRhdGEub3V0ISk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdyZWxlYXNlJzpcbiAgICAgIGlmIChldi5kYXRhLmVycikge1xuICAgICAgICByZWxlYXNlU2Vzc2lvbkNhbGxiYWNrcy5zaGlmdCgpIVsxXShldi5kYXRhLmVycik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZWxlYXNlU2Vzc2lvbkNhbGxiYWNrcy5zaGlmdCgpIVswXSgpO1xuICAgICAgfVxuICAgICAgYnJlYWs7XG4gICAgY2FzZSAncnVuJzpcbiAgICAgIGlmIChldi5kYXRhLmVycikge1xuICAgICAgICBydW5DYWxsYmFja3Muc2hpZnQoKSFbMV0oZXYuZGF0YS5lcnIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcnVuQ2FsbGJhY2tzLnNoaWZ0KCkhWzBdKGV2LmRhdGEub3V0ISk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdlbmQtcHJvZmlsaW5nJzpcbiAgICAgIGlmIChldi5kYXRhLmVycikge1xuICAgICAgICBlbmRQcm9maWxpbmdDYWxsYmFja3Muc2hpZnQoKSFbMV0oZXYuZGF0YS5lcnIpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZW5kUHJvZmlsaW5nQ2FsbGJhY2tzLnNoaWZ0KCkhWzBdKCk7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICB9XG59O1xuXG5jb25zdCBzY3JpcHRTcmMgPSB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnID8gKGRvY3VtZW50Py5jdXJyZW50U2NyaXB0IGFzIEhUTUxTY3JpcHRFbGVtZW50KT8uc3JjIDogdW5kZWZpbmVkO1xuXG5leHBvcnQgY29uc3QgaW5pdFdhc20gPSBhc3luYygpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSAmJiBpc1Byb3h5KCkpIHtcbiAgICBpZiAoaW5pdGlhbGl6ZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGluaXRpYWxpemluZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdtdWx0aXBsZSBjYWxscyB0byBcXCdpbml0V2FzbSgpXFwnIGRldGVjdGVkLicpO1xuICAgIH1cbiAgICBpZiAoYWJvcnRlZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdwcmV2aW91cyBjYWxsIHRvIFxcJ2luaXRXYXNtKClcXCcgZmFpbGVkLicpO1xuICAgIH1cblxuICAgIGluaXRpYWxpemluZyA9IHRydWU7XG5cbiAgICAvLyBvdmVyd3JpdGUgd2FzbSBmaWxlcGF0aHNcbiAgICBpZiAoZW52Lndhc20ud2FzbVBhdGhzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChzY3JpcHRTcmMgJiYgc2NyaXB0U3JjLmluZGV4T2YoJ2Jsb2I6JykgIT09IDApIHtcbiAgICAgICAgZW52Lndhc20ud2FzbVBhdGhzID0gc2NyaXB0U3JjLnN1YnN0cigwLCArKHNjcmlwdFNyYykubGFzdEluZGV4T2YoJy8nKSArIDEpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBwcm94eVdvcmtlcj8udGVybWluYXRlKCk7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXZhci1yZXF1aXJlcywgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICAgICAgcHJveHlXb3JrZXIgPSByZXF1aXJlKCd3b3JrZXItbG9hZGVyP2lubGluZT1uby1mYWxsYmFjayEuL3Byb3h5LXdvcmtlci9tYWluJykuZGVmYXVsdCgpIGFzIFdvcmtlcjtcbiAgICAgIHByb3h5V29ya2VyLm9ubWVzc2FnZSA9IG9uUHJveHlXb3JrZXJNZXNzYWdlO1xuICAgICAgaW5pdFdhc21DYWxsYmFja3MgPSBbcmVzb2x2ZSwgcmVqZWN0XTtcbiAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0ge3R5cGU6ICdpbml0LXdhc20nLCBpbiA6IGVudi53YXNtfTtcbiAgICAgIHByb3h5V29ya2VyLnBvc3RNZXNzYWdlKG1lc3NhZ2UpO1xuICAgIH0pO1xuXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGluaXRpYWxpemVXZWJBc3NlbWJseShlbnYud2FzbSk7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBpbml0T3J0ID0gYXN5bmMobnVtVGhyZWFkczogbnVtYmVyLCBsb2dnaW5nTGV2ZWw6IG51bWJlcik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1BST1hZICYmIGlzUHJveHkoKSkge1xuICAgIGVuc3VyZVdvcmtlcigpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBpbml0T3J0Q2FsbGJhY2tzID0gW3Jlc29sdmUsIHJlamVjdF07XG4gICAgICBjb25zdCBtZXNzYWdlOiBPcnRXYXNtTWVzc2FnZSA9IHt0eXBlOiAnaW5pdC1vcnQnLCBpbiA6IHtudW1UaHJlYWRzLCBsb2dnaW5nTGV2ZWx9fTtcbiAgICAgIHByb3h5V29ya2VyIS5wb3N0TWVzc2FnZShtZXNzYWdlKTtcblxuICAgICAgLy8gVE9ETzogc3VwcG9ydCBKU0VQIGluIHdvcmtlclxuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGNvcmUuaW5pdE9ydChudW1UaHJlYWRzLCBsb2dnaW5nTGV2ZWwpO1xuXG4gICAgLy8gaW5pdCBKU0VQIGlmIGF2YWlsYWJsZVxuICAgIGF3YWl0IGluaXRKc2VwKGdldEluc3RhbmNlKCkpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlU2Vzc2lvbkFsbG9jYXRlID0gYXN5bmMobW9kZWw6IFVpbnQ4QXJyYXkpOiBQcm9taXNlPFNlcmlhbGl6YWJsZU1vZGVsZGF0YT4gPT4ge1xuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1BST1hZICYmIGlzUHJveHkoKSkge1xuICAgIGVuc3VyZVdvcmtlcigpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxTZXJpYWxpemFibGVNb2RlbGRhdGE+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGNyZWF0ZVNlc3Npb25BbGxvY2F0ZUNhbGxiYWNrcy5wdXNoKFtyZXNvbHZlLCByZWplY3RdKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0ge3R5cGU6ICdjcmVhdGVfYWxsb2NhdGUnLCBpbiA6IHttb2RlbH19O1xuICAgICAgcHJveHlXb3JrZXIhLnBvc3RNZXNzYWdlKG1lc3NhZ2UsIFttb2RlbC5idWZmZXJdKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gY29yZS5jcmVhdGVTZXNzaW9uQWxsb2NhdGUobW9kZWwpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlU2Vzc2lvbkZpbmFsaXplID0gYXN5bmMobW9kZWxkYXRhOiBTZXJpYWxpemFibGVNb2RlbGRhdGEsIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zKTpcbiAgICBQcm9taXNlPFNlcmlhbGl6YWJsZVNlc3Npb25NZXRhZGF0YT4gPT4ge1xuICAgICAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSAmJiBpc1Byb3h5KCkpIHtcbiAgICAgICAgZW5zdXJlV29ya2VyKCk7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZTxTZXJpYWxpemFibGVTZXNzaW9uTWV0YWRhdGE+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICBjcmVhdGVTZXNzaW9uRmluYWxpemVDYWxsYmFja3MucHVzaChbcmVzb2x2ZSwgcmVqZWN0XSk7XG4gICAgICAgICAgY29uc3QgbWVzc2FnZTogT3J0V2FzbU1lc3NhZ2UgPSB7dHlwZTogJ2NyZWF0ZV9maW5hbGl6ZScsIGluIDoge21vZGVsZGF0YSwgb3B0aW9uc319O1xuICAgICAgICAgIHByb3h5V29ya2VyIS5wb3N0TWVzc2FnZShtZXNzYWdlKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gY29yZS5jcmVhdGVTZXNzaW9uRmluYWxpemUobW9kZWxkYXRhLCBvcHRpb25zKTtcbiAgICAgIH1cbiAgICB9O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlU2Vzc2lvbiA9XG4gICAgYXN5bmMobW9kZWw6IFVpbnQ4QXJyYXksIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zKTogUHJvbWlzZTxTZXJpYWxpemFibGVTZXNzaW9uTWV0YWRhdGE+ID0+IHtcbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSAmJiBpc1Byb3h5KCkpIHtcbiAgICBlbnN1cmVXb3JrZXIoKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8U2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjcmVhdGVTZXNzaW9uQ2FsbGJhY2tzLnB1c2goW3Jlc29sdmUsIHJlamVjdF0pO1xuICAgICAgY29uc3QgbWVzc2FnZTogT3J0V2FzbU1lc3NhZ2UgPSB7dHlwZTogJ2NyZWF0ZScsIGluIDoge21vZGVsLCBvcHRpb25zfX07XG4gICAgICBwcm94eVdvcmtlciEucG9zdE1lc3NhZ2UobWVzc2FnZSwgW21vZGVsLmJ1ZmZlcl0pO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBjb3JlLmNyZWF0ZVNlc3Npb24obW9kZWwsIG9wdGlvbnMpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgcmVsZWFzZVNlc3Npb24gPSBhc3luYyhzZXNzaW9uSWQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4gPT4ge1xuICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1BST1hZICYmIGlzUHJveHkoKSkge1xuICAgIGVuc3VyZVdvcmtlcigpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICByZWxlYXNlU2Vzc2lvbkNhbGxiYWNrcy5wdXNoKFtyZXNvbHZlLCByZWplY3RdKTtcbiAgICAgIGNvbnN0IG1lc3NhZ2U6IE9ydFdhc21NZXNzYWdlID0ge3R5cGU6ICdyZWxlYXNlJywgaW4gOiBzZXNzaW9uSWR9O1xuICAgICAgcHJveHlXb3JrZXIhLnBvc3RNZXNzYWdlKG1lc3NhZ2UpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGNvcmUucmVsZWFzZVNlc3Npb24oc2Vzc2lvbklkKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IHJ1biA9IGFzeW5jKFxuICAgIHNlc3Npb25JZDogbnVtYmVyLCBpbnB1dEluZGljZXM6IG51bWJlcltdLCBpbnB1dHM6IFNlcmlhbGl6YWJsZVRlbnNvcltdLCBvdXRwdXRJbmRpY2VzOiBudW1iZXJbXSxcbiAgICBvcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlJ1bk9wdGlvbnMpOiBQcm9taXNlPFNlcmlhbGl6YWJsZVRlbnNvcltdPiA9PiB7XG4gIGlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU01fUFJPWFkgJiYgaXNQcm94eSgpKSB7XG4gICAgZW5zdXJlV29ya2VyKCk7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPFNlcmlhbGl6YWJsZVRlbnNvcltdPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBydW5DYWxsYmFja3MucHVzaChbcmVzb2x2ZSwgcmVqZWN0XSk7XG4gICAgICBjb25zdCBtZXNzYWdlOiBPcnRXYXNtTWVzc2FnZSA9IHt0eXBlOiAncnVuJywgaW4gOiB7c2Vzc2lvbklkLCBpbnB1dEluZGljZXMsIGlucHV0cywgb3V0cHV0SW5kaWNlcywgb3B0aW9uc319O1xuICAgICAgcHJveHlXb3JrZXIhLnBvc3RNZXNzYWdlKG1lc3NhZ2UsIGNvcmUuZXh0cmFjdFRyYW5zZmVyYWJsZUJ1ZmZlcnMoaW5wdXRzKSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGNvcmUucnVuKHNlc3Npb25JZCwgaW5wdXRJbmRpY2VzLCBpbnB1dHMsIG91dHB1dEluZGljZXMsIG9wdGlvbnMpO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgZW5kUHJvZmlsaW5nID0gYXN5bmMoc2Vzc2lvbklkOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9QUk9YWSAmJiBpc1Byb3h5KCkpIHtcbiAgICBlbnN1cmVXb3JrZXIoKTtcbiAgICByZXR1cm4gbmV3IFByb21pc2U8dm9pZD4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgZW5kUHJvZmlsaW5nQ2FsbGJhY2tzLnB1c2goW3Jlc29sdmUsIHJlamVjdF0pO1xuICAgICAgY29uc3QgbWVzc2FnZTogT3J0V2FzbU1lc3NhZ2UgPSB7dHlwZTogJ2VuZC1wcm9maWxpbmcnLCBpbiA6IHNlc3Npb25JZH07XG4gICAgICBwcm94eVdvcmtlciEucG9zdE1lc3NhZ2UobWVzc2FnZSk7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgY29yZS5lbmRQcm9maWxpbmcoc2Vzc2lvbklkKTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0luZmVyZW5jZVNlc3Npb259IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbmltcG9ydCB7aXRlcmF0ZUV4dHJhT3B0aW9uc30gZnJvbSAnLi9vcHRpb25zLXV0aWxzJztcbmltcG9ydCB7YWxsb2NXYXNtU3RyaW5nfSBmcm9tICcuL3N0cmluZy11dGlscyc7XG5pbXBvcnQge2dldEluc3RhbmNlfSBmcm9tICcuL3dhc20tZmFjdG9yeSc7XG5cbmV4cG9ydCBjb25zdCBzZXRSdW5PcHRpb25zID0gKG9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uUnVuT3B0aW9ucyk6IFtudW1iZXIsIG51bWJlcltdXSA9PiB7XG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuICBsZXQgcnVuT3B0aW9uc0hhbmRsZSA9IDA7XG4gIGNvbnN0IGFsbG9jczogbnVtYmVyW10gPSBbXTtcblxuICBjb25zdCBydW5PcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlJ1bk9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIHRyeSB7XG4gICAgaWYgKG9wdGlvbnM/LmxvZ1NldmVyaXR5TGV2ZWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcnVuT3B0aW9ucy5sb2dTZXZlcml0eUxldmVsID0gMjsgIC8vIERlZmF1bHQgdG8gd2FybmluZ1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIHR5cGVvZiBvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwgIT09ICdudW1iZXInIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKG9wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbCkgfHxcbiAgICAgICAgb3B0aW9ucy5sb2dTZXZlcml0eUxldmVsIDwgMCB8fCBvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwgPiA0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGxvZyBzZXJ2ZXJpdHkgbGV2ZWwgaXMgbm90IHZhbGlkOiAke29wdGlvbnMubG9nU2V2ZXJpdHlMZXZlbH1gKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucz8ubG9nVmVyYm9zaXR5TGV2ZWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcnVuT3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCA9IDA7ICAvLyBEZWZhdWx0IHRvIDBcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBvcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsICE9PSAnbnVtYmVyJyB8fCAhTnVtYmVyLmlzSW50ZWdlcihvcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBsb2cgdmVyYm9zaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtvcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsfWApO1xuICAgIH1cblxuICAgIGlmIChvcHRpb25zPy50ZXJtaW5hdGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcnVuT3B0aW9ucy50ZXJtaW5hdGUgPSBmYWxzZTtcbiAgICB9XG5cbiAgICBsZXQgdGFnRGF0YU9mZnNldCA9IDA7XG4gICAgaWYgKG9wdGlvbnM/LnRhZyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0YWdEYXRhT2Zmc2V0ID0gYWxsb2NXYXNtU3RyaW5nKG9wdGlvbnMudGFnLCBhbGxvY3MpO1xuICAgIH1cblxuICAgIHJ1bk9wdGlvbnNIYW5kbGUgPSB3YXNtLl9PcnRDcmVhdGVSdW5PcHRpb25zKFxuICAgICAgICBydW5PcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwhLCBydW5PcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsISwgISFydW5PcHRpb25zLnRlcm1pbmF0ZSEsIHRhZ0RhdGFPZmZzZXQpO1xuICAgIGlmIChydW5PcHRpb25zSGFuZGxlID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcJ3QgY3JlYXRlIHJ1biBvcHRpb25zJyk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnM/LmV4dHJhICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGl0ZXJhdGVFeHRyYU9wdGlvbnMob3B0aW9ucy5leHRyYSwgJycsIG5ldyBXZWFrU2V0PFJlY29yZDxzdHJpbmcsIHVua25vd24+PigpLCAoa2V5LCB2YWx1ZSkgPT4ge1xuICAgICAgICBjb25zdCBrZXlEYXRhT2Zmc2V0ID0gYWxsb2NXYXNtU3RyaW5nKGtleSwgYWxsb2NzKTtcbiAgICAgICAgY29uc3QgdmFsdWVEYXRhT2Zmc2V0ID0gYWxsb2NXYXNtU3RyaW5nKHZhbHVlLCBhbGxvY3MpO1xuXG4gICAgICAgIGlmICh3YXNtLl9PcnRBZGRSdW5Db25maWdFbnRyeShydW5PcHRpb25zSGFuZGxlLCBrZXlEYXRhT2Zmc2V0LCB2YWx1ZURhdGFPZmZzZXQpICE9PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4ndCBzZXQgYSBydW4gY29uZmlnIGVudHJ5OiAke2tleX0gLSAke3ZhbHVlfWApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gW3J1bk9wdGlvbnNIYW5kbGUsIGFsbG9jc107XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAocnVuT3B0aW9uc0hhbmRsZSAhPT0gMCkge1xuICAgICAgd2FzbS5fT3J0UmVsZWFzZVJ1bk9wdGlvbnMocnVuT3B0aW9uc0hhbmRsZSk7XG4gICAgfVxuICAgIGFsbG9jcy5mb3JFYWNoKHdhc20uX2ZyZWUpO1xuICAgIHRocm93IGU7XG4gIH1cbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtyZWFkRmlsZX0gZnJvbSAnZnMnO1xuaW1wb3J0IHtlbnYsIEluZmVyZW5jZVNlc3Npb24sIFNlc3Npb25IYW5kbGVyLCBUZW5zb3J9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5pbXBvcnQge3Byb21pc2lmeX0gZnJvbSAndXRpbCc7XG5cbmltcG9ydCB7U2VyaWFsaXphYmxlTW9kZWxkYXRhfSBmcm9tICcuL3Byb3h5LW1lc3NhZ2VzJztcbmltcG9ydCB7Y3JlYXRlU2Vzc2lvbiwgY3JlYXRlU2Vzc2lvbkFsbG9jYXRlLCBjcmVhdGVTZXNzaW9uRmluYWxpemUsIGVuZFByb2ZpbGluZywgaW5pdE9ydCwgcmVsZWFzZVNlc3Npb24sIHJ1bn0gZnJvbSAnLi9wcm94eS13cmFwcGVyJztcbmltcG9ydCB7bG9nTGV2ZWxTdHJpbmdUb0VudW19IGZyb20gJy4vd2FzbS1jb21tb24nO1xuXG5sZXQgb3J0SW5pdDogYm9vbGVhbjtcblxuZXhwb3J0IGNsYXNzIE9ubnhydW50aW1lV2ViQXNzZW1ibHlTZXNzaW9uSGFuZGxlciBpbXBsZW1lbnRzIFNlc3Npb25IYW5kbGVyIHtcbiAgcHJpdmF0ZSBzZXNzaW9uSWQ6IG51bWJlcjtcblxuICBpbnB1dE5hbWVzOiBzdHJpbmdbXTtcbiAgb3V0cHV0TmFtZXM6IHN0cmluZ1tdO1xuXG4gIGFzeW5jIGNyZWF0ZVNlc3Npb25BbGxvY2F0ZShwYXRoOiBzdHJpbmcpOiBQcm9taXNlPFNlcmlhbGl6YWJsZU1vZGVsZGF0YT4ge1xuICAgIC8vIGZldGNoIG1vZGVsIGZyb20gdXJsIGFuZCBtb3ZlIHRvIHdhc20gaGVhcC4gVGhlIGFycmF5YnVmZmZlciB0aGF0IGhlbGQgdGhlIGh0dHBcbiAgICAvLyByZXNwb25zZSBpcyBmcmVlZCBvbmNlIHdlIHJldHVyblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2gocGF0aCk7XG4gICAgY29uc3QgYXJyYXlCdWZmZXIgPSBhd2FpdCByZXNwb25zZS5hcnJheUJ1ZmZlcigpO1xuICAgIHJldHVybiBjcmVhdGVTZXNzaW9uQWxsb2NhdGUobmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWZmZXIpKTtcbiAgfVxuXG4gIGFzeW5jIGxvYWRNb2RlbChwYXRoT3JCdWZmZXI6IHN0cmluZ3xVaW50OEFycmF5LCBvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghb3J0SW5pdCkge1xuICAgICAgYXdhaXQgaW5pdE9ydChlbnYud2FzbS5udW1UaHJlYWRzISwgbG9nTGV2ZWxTdHJpbmdUb0VudW0oZW52LmxvZ0xldmVsISkpO1xuICAgICAgb3J0SW5pdCA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBwYXRoT3JCdWZmZXIgPT09ICdzdHJpbmcnKSB7XG4gICAgICBpZiAodHlwZW9mIGZldGNoID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAvLyBub2RlXG4gICAgICAgIGNvbnN0IG1vZGVsID0gYXdhaXQgcHJvbWlzaWZ5KHJlYWRGaWxlKShwYXRoT3JCdWZmZXIpO1xuICAgICAgICBbdGhpcy5zZXNzaW9uSWQsIHRoaXMuaW5wdXROYW1lcywgdGhpcy5vdXRwdXROYW1lc10gPSBhd2FpdCBjcmVhdGVTZXNzaW9uKG1vZGVsLCBvcHRpb25zKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGJyb3dzZXJcbiAgICAgICAgLy8gZmV0Y2ggbW9kZWwgYW5kIG1vdmUgdG8gd2FzbSBoZWFwLlxuICAgICAgICBjb25zdCBtb2RlbERhdGE6IFNlcmlhbGl6YWJsZU1vZGVsZGF0YSA9IGF3YWl0IHRoaXMuY3JlYXRlU2Vzc2lvbkFsbG9jYXRlKHBhdGhPckJ1ZmZlcik7XG4gICAgICAgIC8vIGNyZWF0ZSB0aGUgc2Vzc2lvblxuICAgICAgICBbdGhpcy5zZXNzaW9uSWQsIHRoaXMuaW5wdXROYW1lcywgdGhpcy5vdXRwdXROYW1lc10gPSBhd2FpdCBjcmVhdGVTZXNzaW9uRmluYWxpemUobW9kZWxEYXRhLCBvcHRpb25zKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgW3RoaXMuc2Vzc2lvbklkLCB0aGlzLmlucHV0TmFtZXMsIHRoaXMub3V0cHV0TmFtZXNdID0gYXdhaXQgY3JlYXRlU2Vzc2lvbihwYXRoT3JCdWZmZXIsIG9wdGlvbnMpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGRpc3Bvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHJlbGVhc2VTZXNzaW9uKHRoaXMuc2Vzc2lvbklkKTtcbiAgfVxuXG4gIGFzeW5jIHJ1bihmZWVkczogU2Vzc2lvbkhhbmRsZXIuRmVlZHNUeXBlLCBmZXRjaGVzOiBTZXNzaW9uSGFuZGxlci5GZXRjaGVzVHlwZSwgb3B0aW9uczogSW5mZXJlbmNlU2Vzc2lvbi5SdW5PcHRpb25zKTpcbiAgICAgIFByb21pc2U8U2Vzc2lvbkhhbmRsZXIuUmV0dXJuVHlwZT4ge1xuICAgIGNvbnN0IGlucHV0QXJyYXk6IFRlbnNvcltdID0gW107XG4gICAgY29uc3QgaW5wdXRJbmRpY2VzOiBudW1iZXJbXSA9IFtdO1xuICAgIE9iamVjdC5lbnRyaWVzKGZlZWRzKS5mb3JFYWNoKGt2cCA9PiB7XG4gICAgICBjb25zdCBuYW1lID0ga3ZwWzBdO1xuICAgICAgY29uc3QgdGVuc29yID0ga3ZwWzFdO1xuICAgICAgY29uc3QgaW5kZXggPSB0aGlzLmlucHV0TmFtZXMuaW5kZXhPZihuYW1lKTtcbiAgICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIGlucHV0ICcke25hbWV9J2ApO1xuICAgICAgfVxuICAgICAgaW5wdXRBcnJheS5wdXNoKHRlbnNvcik7XG4gICAgICBpbnB1dEluZGljZXMucHVzaChpbmRleCk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBvdXRwdXRJbmRpY2VzOiBudW1iZXJbXSA9IFtdO1xuICAgIE9iamVjdC5lbnRyaWVzKGZldGNoZXMpLmZvckVhY2goa3ZwID0+IHtcbiAgICAgIGNvbnN0IG5hbWUgPSBrdnBbMF07XG4gICAgICAvLyBUT0RPOiBzdXBwb3J0IHByZS1hbGxvY2F0ZWQgb3V0cHV0XG4gICAgICBjb25zdCBpbmRleCA9IHRoaXMub3V0cHV0TmFtZXMuaW5kZXhPZihuYW1lKTtcbiAgICAgIGlmIChpbmRleCA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIG91dHB1dCAnJHtuYW1lfSdgKTtcbiAgICAgIH1cbiAgICAgIG91dHB1dEluZGljZXMucHVzaChpbmRleCk7XG4gICAgfSk7XG5cbiAgICBjb25zdCBvdXRwdXRzID1cbiAgICAgICAgYXdhaXQgcnVuKHRoaXMuc2Vzc2lvbklkLCBpbnB1dEluZGljZXMsIGlucHV0QXJyYXkubWFwKHQgPT4gW3QudHlwZSwgdC5kaW1zLCB0LmRhdGFdKSwgb3V0cHV0SW5kaWNlcywgb3B0aW9ucyk7XG5cbiAgICBjb25zdCByZXN1bHQ6IFNlc3Npb25IYW5kbGVyLlJldHVyblR5cGUgPSB7fTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG91dHB1dHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHJlc3VsdFt0aGlzLm91dHB1dE5hbWVzW291dHB1dEluZGljZXNbaV1dXSA9IG5ldyBUZW5zb3Iob3V0cHV0c1tpXVswXSwgb3V0cHV0c1tpXVsyXSwgb3V0cHV0c1tpXVsxXSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBzdGFydFByb2ZpbGluZygpOiB2b2lkIHtcbiAgICAvLyBUT0RPOiBpbXBsZW1lbnQgcHJvZmlsaW5nXG4gIH1cblxuICBlbmRQcm9maWxpbmcoKTogdm9pZCB7XG4gICAgdm9pZCBlbmRQcm9maWxpbmcodGhpcy5zZXNzaW9uSWQpO1xuICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtJbmZlcmVuY2VTZXNzaW9ufSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuXG5pbXBvcnQge2l0ZXJhdGVFeHRyYU9wdGlvbnN9IGZyb20gJy4vb3B0aW9ucy11dGlscyc7XG5pbXBvcnQge2FsbG9jV2FzbVN0cmluZ30gZnJvbSAnLi9zdHJpbmctdXRpbHMnO1xuaW1wb3J0IHtnZXRJbnN0YW5jZX0gZnJvbSAnLi93YXNtLWZhY3RvcnknO1xuXG5jb25zdCBnZXRHcmFwaE9wdGltemF0aW9uTGV2ZWwgPSAoZ3JhcGhPcHRpbWl6YXRpb25MZXZlbDogc3RyaW5nfHVua25vd24pOiBudW1iZXIgPT4ge1xuICBzd2l0Y2ggKGdyYXBoT3B0aW1pemF0aW9uTGV2ZWwpIHtcbiAgICBjYXNlICdkaXNhYmxlZCc6XG4gICAgICByZXR1cm4gMDtcbiAgICBjYXNlICdiYXNpYyc6XG4gICAgICByZXR1cm4gMTtcbiAgICBjYXNlICdleHRlbmRlZCc6XG4gICAgICByZXR1cm4gMjtcbiAgICBjYXNlICdhbGwnOlxuICAgICAgcmV0dXJuIDk5O1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIGdyYXBoIG9wdGltaXphdGlvbiBsZXZlbDogJHtncmFwaE9wdGltaXphdGlvbkxldmVsfWApO1xuICB9XG59O1xuXG5jb25zdCBnZXRFeGVjdXRpb25Nb2RlID0gKGV4ZWN1dGlvbk1vZGU6ICdzZXF1ZW50aWFsJ3wncGFyYWxsZWwnKTogbnVtYmVyID0+IHtcbiAgc3dpdGNoIChleGVjdXRpb25Nb2RlKSB7XG4gICAgY2FzZSAnc2VxdWVudGlhbCc6XG4gICAgICByZXR1cm4gMDtcbiAgICBjYXNlICdwYXJhbGxlbCc6XG4gICAgICByZXR1cm4gMTtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBleGVjdXRpb24gbW9kZTogJHtleGVjdXRpb25Nb2RlfWApO1xuICB9XG59O1xuXG5jb25zdCBhcHBlbmREZWZhdWx0T3B0aW9ucyA9IChvcHRpb25zOiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zKTogdm9pZCA9PiB7XG4gIGlmICghb3B0aW9ucy5leHRyYSkge1xuICAgIG9wdGlvbnMuZXh0cmEgPSB7fTtcbiAgfVxuICBpZiAoIW9wdGlvbnMuZXh0cmEuc2Vzc2lvbikge1xuICAgIG9wdGlvbnMuZXh0cmEuc2Vzc2lvbiA9IHt9O1xuICB9XG4gIGNvbnN0IHNlc3Npb24gPSBvcHRpb25zLmV4dHJhLnNlc3Npb24gYXMgUmVjb3JkPHN0cmluZywgc3RyaW5nPjtcbiAgaWYgKCFzZXNzaW9uLnVzZV9vcnRfbW9kZWxfYnl0ZXNfZGlyZWN0bHkpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2FtZWxjYXNlXG4gICAgc2Vzc2lvbi51c2Vfb3J0X21vZGVsX2J5dGVzX2RpcmVjdGx5ID0gJzEnO1xuICB9XG5cbiAgLy8gaWYgdXNpbmcgSlNFUCB3aXRoIFdlYkdQVSwgYWx3YXlzIGRpc2FibGUgbWVtb3J5IHBhdHRlcm5cbiAgaWYgKG9wdGlvbnMuZXhlY3V0aW9uUHJvdmlkZXJzICYmXG4gICAgICBvcHRpb25zLmV4ZWN1dGlvblByb3ZpZGVycy5zb21lKGVwID0+ICh0eXBlb2YgZXAgPT09ICdzdHJpbmcnID8gZXAgOiBlcC5uYW1lKSA9PT0gJ3dlYmdwdScpKSB7XG4gICAgb3B0aW9ucy5lbmFibGVNZW1QYXR0ZXJuID0gZmFsc2U7XG4gIH1cbn07XG5cbmNvbnN0IHNldEV4ZWN1dGlvblByb3ZpZGVycyA9XG4gICAgKHNlc3Npb25PcHRpb25zSGFuZGxlOiBudW1iZXIsIGV4ZWN1dGlvblByb3ZpZGVyczogcmVhZG9ubHkgSW5mZXJlbmNlU2Vzc2lvbi5FeGVjdXRpb25Qcm92aWRlckNvbmZpZ1tdLFxuICAgICBhbGxvY3M6IG51bWJlcltdKTogdm9pZCA9PiB7XG4gICAgICBmb3IgKGNvbnN0IGVwIG9mIGV4ZWN1dGlvblByb3ZpZGVycykge1xuICAgICAgICBsZXQgZXBOYW1lID0gdHlwZW9mIGVwID09PSAnc3RyaW5nJyA/IGVwIDogZXAubmFtZTtcblxuICAgICAgICAvLyBjaGVjayBFUCBuYW1lXG4gICAgICAgIHN3aXRjaCAoZXBOYW1lKSB7XG4gICAgICAgICAgY2FzZSAneG5ucGFjayc6XG4gICAgICAgICAgICBlcE5hbWUgPSAnWE5OUEFDSyc7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICd3ZWJncHUnOlxuICAgICAgICAgICAgZXBOYW1lID0gJ0pTJztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ3dhc20nOlxuICAgICAgICAgIGNhc2UgJ2NwdSc6XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub3Qgc3VwcG9ydGVkIEVQOiAke2VwTmFtZX1gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGVwTmFtZURhdGFPZmZzZXQgPSBhbGxvY1dhc21TdHJpbmcoZXBOYW1lLCBhbGxvY3MpO1xuICAgICAgICBpZiAoZ2V0SW5zdGFuY2UoKS5fT3J0QXBwZW5kRXhlY3V0aW9uUHJvdmlkZXIoc2Vzc2lvbk9wdGlvbnNIYW5kbGUsIGVwTmFtZURhdGFPZmZzZXQpICE9PSAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4ndCBhcHBlbmQgZXhlY3V0aW9uIHByb3ZpZGVyOiAke2VwTmFtZX1gKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbmV4cG9ydCBjb25zdCBzZXRTZXNzaW9uT3B0aW9ucyA9IChvcHRpb25zPzogSW5mZXJlbmNlU2Vzc2lvbi5TZXNzaW9uT3B0aW9ucyk6IFtudW1iZXIsIG51bWJlcltdXSA9PiB7XG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuICBsZXQgc2Vzc2lvbk9wdGlvbnNIYW5kbGUgPSAwO1xuICBjb25zdCBhbGxvY3M6IG51bWJlcltdID0gW107XG5cbiAgY29uc3Qgc2Vzc2lvbk9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICBhcHBlbmREZWZhdWx0T3B0aW9ucyhzZXNzaW9uT3B0aW9ucyk7XG5cbiAgdHJ5IHtcbiAgICBjb25zdCBncmFwaE9wdGltaXphdGlvbkxldmVsID0gZ2V0R3JhcGhPcHRpbXphdGlvbkxldmVsKHNlc3Npb25PcHRpb25zLmdyYXBoT3B0aW1pemF0aW9uTGV2ZWwgPz8gJ2FsbCcpO1xuICAgIGNvbnN0IGV4ZWN1dGlvbk1vZGUgPSBnZXRFeGVjdXRpb25Nb2RlKHNlc3Npb25PcHRpb25zLmV4ZWN1dGlvbk1vZGUgPz8gJ3NlcXVlbnRpYWwnKTtcbiAgICBjb25zdCBsb2dJZERhdGFPZmZzZXQgPVxuICAgICAgICB0eXBlb2Ygc2Vzc2lvbk9wdGlvbnMubG9nSWQgPT09ICdzdHJpbmcnID8gYWxsb2NXYXNtU3RyaW5nKHNlc3Npb25PcHRpb25zLmxvZ0lkLCBhbGxvY3MpIDogMDtcblxuICAgIGNvbnN0IGxvZ1NldmVyaXR5TGV2ZWwgPSBzZXNzaW9uT3B0aW9ucy5sb2dTZXZlcml0eUxldmVsID8/IDI7ICAvLyBEZWZhdWx0IHRvIDIgLSB3YXJuaW5nXG4gICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGxvZ1NldmVyaXR5TGV2ZWwpIHx8IGxvZ1NldmVyaXR5TGV2ZWwgPCAwIHx8IGxvZ1NldmVyaXR5TGV2ZWwgPiA0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGxvZyBzZXJ2ZXJpdHkgbGV2ZWwgaXMgbm90IHZhbGlkOiAke2xvZ1NldmVyaXR5TGV2ZWx9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgbG9nVmVyYm9zaXR5TGV2ZWwgPSBzZXNzaW9uT3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCA/PyAwOyAgLy8gRGVmYXVsdCB0byAwIC0gdmVyYm9zZVxuICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihsb2dWZXJib3NpdHlMZXZlbCkgfHwgbG9nVmVyYm9zaXR5TGV2ZWwgPCAwIHx8IGxvZ1ZlcmJvc2l0eUxldmVsID4gNCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBsb2cgdmVyYm9zaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtsb2dWZXJib3NpdHlMZXZlbH1gKTtcbiAgICB9XG5cbiAgICBjb25zdCBvcHRpbWl6ZWRNb2RlbEZpbGVQYXRoT2Zmc2V0ID0gdHlwZW9mIHNlc3Npb25PcHRpb25zLm9wdGltaXplZE1vZGVsRmlsZVBhdGggPT09ICdzdHJpbmcnID9cbiAgICAgICAgYWxsb2NXYXNtU3RyaW5nKHNlc3Npb25PcHRpb25zLm9wdGltaXplZE1vZGVsRmlsZVBhdGgsIGFsbG9jcykgOlxuICAgICAgICAwO1xuXG4gICAgc2Vzc2lvbk9wdGlvbnNIYW5kbGUgPSB3YXNtLl9PcnRDcmVhdGVTZXNzaW9uT3B0aW9ucyhcbiAgICAgICAgZ3JhcGhPcHRpbWl6YXRpb25MZXZlbCwgISFzZXNzaW9uT3B0aW9ucy5lbmFibGVDcHVNZW1BcmVuYSwgISFzZXNzaW9uT3B0aW9ucy5lbmFibGVNZW1QYXR0ZXJuLCBleGVjdXRpb25Nb2RlLFxuICAgICAgICAhIXNlc3Npb25PcHRpb25zLmVuYWJsZVByb2ZpbGluZywgMCwgbG9nSWREYXRhT2Zmc2V0LCBsb2dTZXZlcml0eUxldmVsLCBsb2dWZXJib3NpdHlMZXZlbCxcbiAgICAgICAgb3B0aW1pemVkTW9kZWxGaWxlUGF0aE9mZnNldCk7XG4gICAgaWYgKHNlc3Npb25PcHRpb25zSGFuZGxlID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcJ3QgY3JlYXRlIHNlc3Npb24gb3B0aW9ucycpO1xuICAgIH1cblxuICAgIGlmIChzZXNzaW9uT3B0aW9ucy5leGVjdXRpb25Qcm92aWRlcnMpIHtcbiAgICAgIHNldEV4ZWN1dGlvblByb3ZpZGVycyhzZXNzaW9uT3B0aW9uc0hhbmRsZSwgc2Vzc2lvbk9wdGlvbnMuZXhlY3V0aW9uUHJvdmlkZXJzLCBhbGxvY3MpO1xuICAgIH1cblxuICAgIGlmIChzZXNzaW9uT3B0aW9ucy5leHRyYSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBpdGVyYXRlRXh0cmFPcHRpb25zKHNlc3Npb25PcHRpb25zLmV4dHJhLCAnJywgbmV3IFdlYWtTZXQ8UmVjb3JkPHN0cmluZywgdW5rbm93bj4+KCksIChrZXksIHZhbHVlKSA9PiB7XG4gICAgICAgIGNvbnN0IGtleURhdGFPZmZzZXQgPSBhbGxvY1dhc21TdHJpbmcoa2V5LCBhbGxvY3MpO1xuICAgICAgICBjb25zdCB2YWx1ZURhdGFPZmZzZXQgPSBhbGxvY1dhc21TdHJpbmcodmFsdWUsIGFsbG9jcyk7XG5cbiAgICAgICAgaWYgKHdhc20uX09ydEFkZFNlc3Npb25Db25maWdFbnRyeShzZXNzaW9uT3B0aW9uc0hhbmRsZSwga2V5RGF0YU9mZnNldCwgdmFsdWVEYXRhT2Zmc2V0KSAhPT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3Qgc2V0IGEgc2Vzc2lvbiBjb25maWcgZW50cnk6ICR7a2V5fSAtICR7dmFsdWV9YCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBbc2Vzc2lvbk9wdGlvbnNIYW5kbGUsIGFsbG9jc107XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoc2Vzc2lvbk9wdGlvbnNIYW5kbGUgIT09IDApIHtcbiAgICAgIHdhc20uX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucyhzZXNzaW9uT3B0aW9uc0hhbmRsZSk7XG4gICAgfVxuICAgIGFsbG9jcy5mb3JFYWNoKHdhc20uX2ZyZWUpO1xuICAgIHRocm93IGU7XG4gIH1cbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtnZXRJbnN0YW5jZX0gZnJvbSAnLi93YXNtLWZhY3RvcnknO1xuXG5leHBvcnQgY29uc3QgYWxsb2NXYXNtU3RyaW5nID0gKGRhdGE6IHN0cmluZywgYWxsb2NzOiBudW1iZXJbXSk6IG51bWJlciA9PiB7XG4gIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuXG4gIGNvbnN0IGRhdGFMZW5ndGggPSB3YXNtLmxlbmd0aEJ5dGVzVVRGOChkYXRhKSArIDE7XG4gIGNvbnN0IGRhdGFPZmZzZXQgPSB3YXNtLl9tYWxsb2MoZGF0YUxlbmd0aCk7XG4gIHdhc20uc3RyaW5nVG9VVEY4KGRhdGEsIGRhdGFPZmZzZXQsIGRhdGFMZW5ndGgpO1xuICBhbGxvY3MucHVzaChkYXRhT2Zmc2V0KTtcblxuICByZXR1cm4gZGF0YU9mZnNldDtcbn07XG4iLCIvLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cblxuaW1wb3J0IHtUZW5zb3J9IGZyb20gJ29ubnhydW50aW1lLWNvbW1vbic7XG5cbi8qKlxuICogQ29waWVkIGZyb20gT05OWCBkZWZpbml0aW9uLiBVc2UgdGhpcyB0byBkcm9wIGRlcGVuZGVuY3kgJ29ubnhfcHJvdG8nIHRvIGRlY3JlYXNlIGNvbXBpbGVkIC5qcyBmaWxlIHNpemUuXG4gKi9cbmV4cG9ydCBjb25zdCBlbnVtIERhdGFUeXBlIHtcbiAgdW5kZWZpbmVkID0gMCxcbiAgZmxvYXQgPSAxLFxuICB1aW50OCA9IDIsXG4gIGludDggPSAzLFxuICB1aW50MTYgPSA0LFxuICBpbnQxNiA9IDUsXG4gIGludDMyID0gNixcbiAgaW50NjQgPSA3LFxuICBzdHJpbmcgPSA4LFxuICBib29sID0gOSxcbiAgZmxvYXQxNiA9IDEwLFxuICBkb3VibGUgPSAxMSxcbiAgdWludDMyID0gMTIsXG4gIHVpbnQ2NCA9IDEzLFxuICBjb21wbGV4NjQgPSAxNCxcbiAgY29tcGxleDEyOCA9IDE1LFxuICBiZmxvYXQxNiA9IDE2XG59XG5cbi8qKlxuICogTWFwIHN0cmluZyB0ZW5zb3IgZGF0YSB0byBlbnVtIHZhbHVlXG4gKi9cbmV4cG9ydCBjb25zdCB0ZW5zb3JEYXRhVHlwZVN0cmluZ1RvRW51bSA9ICh0eXBlOiBzdHJpbmcpOiBEYXRhVHlwZSA9PiB7XG4gIHN3aXRjaCAodHlwZSkge1xuICAgIGNhc2UgJ2ludDgnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLmludDg7XG4gICAgY2FzZSAndWludDgnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLnVpbnQ4O1xuICAgIGNhc2UgJ2Jvb2wnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLmJvb2w7XG4gICAgY2FzZSAnaW50MTYnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLmludDE2O1xuICAgIGNhc2UgJ3VpbnQxNic6XG4gICAgICByZXR1cm4gRGF0YVR5cGUudWludDE2O1xuICAgIGNhc2UgJ2ludDMyJzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5pbnQzMjtcbiAgICBjYXNlICd1aW50MzInOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLnVpbnQzMjtcbiAgICBjYXNlICdmbG9hdDMyJzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5mbG9hdDtcbiAgICBjYXNlICdmbG9hdDY0JzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5kb3VibGU7XG4gICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgIHJldHVybiBEYXRhVHlwZS5zdHJpbmc7XG4gICAgY2FzZSAnaW50NjQnOlxuICAgICAgcmV0dXJuIERhdGFUeXBlLmludDY0O1xuICAgIGNhc2UgJ3VpbnQ2NCc6XG4gICAgICByZXR1cm4gRGF0YVR5cGUudWludDY0O1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZGF0YSB0eXBlOiAke3R5cGV9YCk7XG4gIH1cbn07XG5cbi8qKlxuICogTWFwIGVudW0gdmFsdWUgdG8gc3RyaW5nIHRlbnNvciBkYXRhXG4gKi9cbmV4cG9ydCBjb25zdCB0ZW5zb3JEYXRhVHlwZUVudW1Ub1N0cmluZyA9ICh0eXBlUHJvdG86IERhdGFUeXBlKTogVGVuc29yLlR5cGUgPT4ge1xuICBzd2l0Y2ggKHR5cGVQcm90bykge1xuICAgIGNhc2UgRGF0YVR5cGUuaW50ODpcbiAgICAgIHJldHVybiAnaW50OCc7XG4gICAgY2FzZSBEYXRhVHlwZS51aW50ODpcbiAgICAgIHJldHVybiAndWludDgnO1xuICAgIGNhc2UgRGF0YVR5cGUuYm9vbDpcbiAgICAgIHJldHVybiAnYm9vbCc7XG4gICAgY2FzZSBEYXRhVHlwZS5pbnQxNjpcbiAgICAgIHJldHVybiAnaW50MTYnO1xuICAgIGNhc2UgRGF0YVR5cGUudWludDE2OlxuICAgICAgcmV0dXJuICd1aW50MTYnO1xuICAgIGNhc2UgRGF0YVR5cGUuaW50MzI6XG4gICAgICByZXR1cm4gJ2ludDMyJztcbiAgICBjYXNlIERhdGFUeXBlLnVpbnQzMjpcbiAgICAgIHJldHVybiAndWludDMyJztcbiAgICBjYXNlIERhdGFUeXBlLmZsb2F0OlxuICAgICAgcmV0dXJuICdmbG9hdDMyJztcbiAgICBjYXNlIERhdGFUeXBlLmRvdWJsZTpcbiAgICAgIHJldHVybiAnZmxvYXQ2NCc7XG4gICAgY2FzZSBEYXRhVHlwZS5zdHJpbmc6XG4gICAgICByZXR1cm4gJ3N0cmluZyc7XG4gICAgY2FzZSBEYXRhVHlwZS5pbnQ2NDpcbiAgICAgIHJldHVybiAnaW50NjQnO1xuICAgIGNhc2UgRGF0YVR5cGUudWludDY0OlxuICAgICAgcmV0dXJuICd1aW50NjQnO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZGF0YSB0eXBlOiAke3R5cGVQcm90b31gKTtcbiAgfVxufTtcblxuLyoqXG4gKiBnZXQgdGVuc29yIGVsZW1lbnQgc2l6ZSBpbiBieXRlcyBieSB0aGUgZ2l2ZW4gZGF0YSB0eXBlXG4gKiBAcmV0dXJucyBzaXplIGluIGludGVnZXIgb3IgdW5kZWZpbmVkIGlmIHRoZSBkYXRhIHR5cGUgaXMgbm90IHN1cHBvcnRlZFxuICovXG5leHBvcnQgY29uc3QgZ2V0VGVuc29yRWxlbWVudFNpemUgPSAoZGF0ZVR5cGU6IG51bWJlcik6IG51bWJlcnxcbiAgICB1bmRlZmluZWQgPT4gW3VuZGVmaW5lZCwgNCwgMSwgMSwgMiwgMiwgNCwgOCwgdW5kZWZpbmVkLCAxLCAyLCA4LCA0LCA4LCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkXVtkYXRlVHlwZV07XG5cbi8qKlxuICogZ2V0IHR5cGVkIGFycmF5IGNvbnN0cnVjdG9yIGJ5IHRoZSBnaXZlbiB0ZW5zb3IgdHlwZVxuICovXG5leHBvcnQgY29uc3QgdGVuc29yVHlwZVRvVHlwZWRBcnJheUNvbnN0cnVjdG9yID0gKHR5cGU6IFRlbnNvci5UeXBlKTogRmxvYXQzMkFycmF5Q29uc3RydWN0b3J8VWludDhBcnJheUNvbnN0cnVjdG9yfFxuICAgIEludDhBcnJheUNvbnN0cnVjdG9yfFVpbnQxNkFycmF5Q29uc3RydWN0b3J8SW50MTZBcnJheUNvbnN0cnVjdG9yfEludDMyQXJyYXlDb25zdHJ1Y3RvcnxCaWdJbnQ2NEFycmF5Q29uc3RydWN0b3J8XG4gICAgVWludDhBcnJheUNvbnN0cnVjdG9yfEZsb2F0NjRBcnJheUNvbnN0cnVjdG9yfFVpbnQzMkFycmF5Q29uc3RydWN0b3J8QmlnVWludDY0QXJyYXlDb25zdHJ1Y3RvciA9PiB7XG4gICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgY2FzZSAnZmxvYXQzMic6XG4gICAgICAgICAgcmV0dXJuIEZsb2F0MzJBcnJheTtcbiAgICAgICAgY2FzZSAndWludDgnOlxuICAgICAgICAgIHJldHVybiBVaW50OEFycmF5O1xuICAgICAgICBjYXNlICdpbnQ4JzpcbiAgICAgICAgICByZXR1cm4gSW50OEFycmF5O1xuICAgICAgICBjYXNlICd1aW50MTYnOlxuICAgICAgICAgIHJldHVybiBVaW50MTZBcnJheTtcbiAgICAgICAgY2FzZSAnaW50MTYnOlxuICAgICAgICAgIHJldHVybiBJbnQxNkFycmF5O1xuICAgICAgICBjYXNlICdpbnQzMic6XG4gICAgICAgICAgcmV0dXJuIEludDMyQXJyYXk7XG4gICAgICAgIGNhc2UgJ2Jvb2wnOlxuICAgICAgICAgIHJldHVybiBVaW50OEFycmF5O1xuICAgICAgICBjYXNlICdmbG9hdDY0JzpcbiAgICAgICAgICByZXR1cm4gRmxvYXQ2NEFycmF5O1xuICAgICAgICBjYXNlICd1aW50MzInOlxuICAgICAgICAgIHJldHVybiBVaW50MzJBcnJheTtcbiAgICAgICAgY2FzZSAnaW50NjQnOlxuICAgICAgICAgIHJldHVybiBCaWdJbnQ2NEFycmF5O1xuICAgICAgICBjYXNlICd1aW50NjQnOlxuICAgICAgICAgIHJldHVybiBCaWdVaW50NjRBcnJheTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVuc3VwcG9ydGVkIHR5cGU6ICR7dHlwZX1gKTtcbiAgICAgIH1cbiAgICB9O1xuXG4vKipcbiAqIE1hcCBzdHJpbmcgbG9nIGxldmVsIHRvIGludGVnZXIgdmFsdWVcbiAqL1xuZXhwb3J0IGNvbnN0IGxvZ0xldmVsU3RyaW5nVG9FbnVtID0gKGxvZ0xldmVsOiAndmVyYm9zZSd8J2luZm8nfCd3YXJuaW5nJ3wnZXJyb3InfCdmYXRhbCcpOiBudW1iZXIgPT4ge1xuICBzd2l0Y2ggKGxvZ0xldmVsKSB7XG4gICAgY2FzZSAndmVyYm9zZSc6XG4gICAgICByZXR1cm4gMDtcbiAgICBjYXNlICdpbmZvJzpcbiAgICAgIHJldHVybiAxO1xuICAgIGNhc2UgJ3dhcm5pbmcnOlxuICAgICAgcmV0dXJuIDI7XG4gICAgY2FzZSAnZXJyb3InOlxuICAgICAgcmV0dXJuIDM7XG4gICAgY2FzZSAnZmF0YWwnOlxuICAgICAgcmV0dXJuIDQ7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgbG9nZ2luZyBsZXZlbDogJHtsb2dMZXZlbH1gKTtcbiAgfVxufTtcbiIsIi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxuXG5pbXBvcnQge0luZmVyZW5jZVNlc3Npb24sIFRlbnNvcn0gZnJvbSAnb25ueHJ1bnRpbWUtY29tbW9uJztcblxuaW1wb3J0IHtTZXJpYWxpemFibGVNb2RlbGRhdGEsIFNlcmlhbGl6YWJsZVNlc3Npb25NZXRhZGF0YSwgU2VyaWFsaXphYmxlVGVuc29yfSBmcm9tICcuL3Byb3h5LW1lc3NhZ2VzJztcbmltcG9ydCB7c2V0UnVuT3B0aW9uc30gZnJvbSAnLi9ydW4tb3B0aW9ucyc7XG5pbXBvcnQge3NldFNlc3Npb25PcHRpb25zfSBmcm9tICcuL3Nlc3Npb24tb3B0aW9ucyc7XG5pbXBvcnQge2FsbG9jV2FzbVN0cmluZ30gZnJvbSAnLi9zdHJpbmctdXRpbHMnO1xuaW1wb3J0IHt0ZW5zb3JEYXRhVHlwZUVudW1Ub1N0cmluZywgdGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0sIHRlbnNvclR5cGVUb1R5cGVkQXJyYXlDb25zdHJ1Y3Rvcn0gZnJvbSAnLi93YXNtLWNvbW1vbic7XG5pbXBvcnQge2dldEluc3RhbmNlfSBmcm9tICcuL3dhc20tZmFjdG9yeSc7XG5cbi8qKlxuICogaW5pdGlhbGl6ZSBPUlQgZW52aXJvbm1lbnQuXG4gKiBAcGFyYW0gbnVtVGhyZWFkcyBTZXRHbG9iYWxJbnRyYU9wTnVtVGhyZWFkcyhudW1UaHJlYWRzKVxuICogQHBhcmFtIGxvZ2dpbmdMZXZlbCBDcmVhdGVFbnYoc3RhdGljX2Nhc3Q8T3J0TG9nZ2luZ0xldmVsPihsb2dnaW5nX2xldmVsKSlcbiAqL1xuZXhwb3J0IGNvbnN0IGluaXRPcnQgPSAobnVtVGhyZWFkczogbnVtYmVyLCBsb2dnaW5nTGV2ZWw6IG51bWJlcik6IHZvaWQgPT4ge1xuICBjb25zdCBlcnJvckNvZGUgPSBnZXRJbnN0YW5jZSgpLl9PcnRJbml0KG51bVRocmVhZHMsIGxvZ2dpbmdMZXZlbCk7XG4gIGlmIChlcnJvckNvZGUgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IGluaXRpYWxpemUgb25ueHJ1bnRpbWUuIGVycm9yIGNvZGUgPSAke2Vycm9yQ29kZX1gKTtcbiAgfVxufTtcblxuLyoqXG4gKiAgdHVwbGUgZWxlbWVudHMgYXJlOiBJbmZlcmVuY2VTZXNzaW9uIElEOyBpbnB1dE5hbWVzVVRGOEVuY29kZWQ7IG91dHB1dE5hbWVzVVRGOEVuY29kZWRcbiAqL1xudHlwZSBTZXNzaW9uTWV0YWRhdGEgPSBbbnVtYmVyLCBudW1iZXJbXSwgbnVtYmVyW11dO1xuXG5jb25zdCBhY3RpdmVTZXNzaW9ucyA9IG5ldyBNYXA8bnVtYmVyLCBTZXNzaW9uTWV0YWRhdGE+KCk7XG5cbi8qKlxuICogY3JlYXRlIGFuIGluc3RhbmNlIG9mIEluZmVyZW5jZVNlc3Npb24uXG4gKiBAcmV0dXJucyB0aGUgbWV0YWRhdGEgb2YgSW5mZXJlbmNlU2Vzc2lvbi4gMC12YWx1ZSBoYW5kbGUgZm9yIGZhaWx1cmUuXG4gKi9cbmV4cG9ydCBjb25zdCBjcmVhdGVTZXNzaW9uQWxsb2NhdGUgPSAobW9kZWw6IFVpbnQ4QXJyYXkpOiBbbnVtYmVyLCBudW1iZXJdID0+IHtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG4gIGNvbnN0IG1vZGVsRGF0YU9mZnNldCA9IHdhc20uX21hbGxvYyhtb2RlbC5ieXRlTGVuZ3RoKTtcbiAgd2FzbS5IRUFQVTguc2V0KG1vZGVsLCBtb2RlbERhdGFPZmZzZXQpO1xuICByZXR1cm4gW21vZGVsRGF0YU9mZnNldCwgbW9kZWwuYnl0ZUxlbmd0aF07XG59O1xuXG5leHBvcnQgY29uc3QgY3JlYXRlU2Vzc2lvbkZpbmFsaXplID1cbiAgICAobW9kZWxEYXRhOiBTZXJpYWxpemFibGVNb2RlbGRhdGEsIG9wdGlvbnM/OiBJbmZlcmVuY2VTZXNzaW9uLlNlc3Npb25PcHRpb25zKTogU2VyaWFsaXphYmxlU2Vzc2lvbk1ldGFkYXRhID0+IHtcbiAgICAgIGNvbnN0IHdhc20gPSBnZXRJbnN0YW5jZSgpO1xuXG4gICAgICBsZXQgc2Vzc2lvbkhhbmRsZSA9IDA7XG4gICAgICBsZXQgc2Vzc2lvbk9wdGlvbnNIYW5kbGUgPSAwO1xuICAgICAgbGV0IGFsbG9jczogbnVtYmVyW10gPSBbXTtcblxuICAgICAgdHJ5IHtcbiAgICAgICAgW3Nlc3Npb25PcHRpb25zSGFuZGxlLCBhbGxvY3NdID0gc2V0U2Vzc2lvbk9wdGlvbnMob3B0aW9ucyk7XG5cbiAgICAgICAgc2Vzc2lvbkhhbmRsZSA9IHdhc20uX09ydENyZWF0ZVNlc3Npb24obW9kZWxEYXRhWzBdLCBtb2RlbERhdGFbMV0sIHNlc3Npb25PcHRpb25zSGFuZGxlKTtcbiAgICAgICAgaWYgKHNlc3Npb25IYW5kbGUgPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcJ3QgY3JlYXRlIGEgc2Vzc2lvbicpO1xuICAgICAgICB9XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB3YXNtLl9mcmVlKG1vZGVsRGF0YVswXSk7XG4gICAgICAgIGlmIChzZXNzaW9uT3B0aW9uc0hhbmRsZSAhPT0gMCkge1xuICAgICAgICAgIHdhc20uX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucyhzZXNzaW9uT3B0aW9uc0hhbmRsZSk7XG4gICAgICAgIH1cbiAgICAgICAgYWxsb2NzLmZvckVhY2god2FzbS5fZnJlZSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGlucHV0Q291bnQgPSB3YXNtLl9PcnRHZXRJbnB1dENvdW50KHNlc3Npb25IYW5kbGUpO1xuICAgICAgY29uc3Qgb3V0cHV0Q291bnQgPSB3YXNtLl9PcnRHZXRPdXRwdXRDb3VudChzZXNzaW9uSGFuZGxlKTtcblxuICAgICAgY29uc3QgaW5wdXROYW1lcyA9IFtdO1xuICAgICAgY29uc3QgaW5wdXROYW1lc1VURjhFbmNvZGVkID0gW107XG4gICAgICBjb25zdCBvdXRwdXROYW1lcyA9IFtdO1xuICAgICAgY29uc3Qgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZCA9IFtdO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dENvdW50OyBpKyspIHtcbiAgICAgICAgY29uc3QgbmFtZSA9IHdhc20uX09ydEdldElucHV0TmFtZShzZXNzaW9uSGFuZGxlLCBpKTtcbiAgICAgICAgaWYgKG5hbWUgPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcJ3QgZ2V0IGFuIGlucHV0IG5hbWUnKTtcbiAgICAgICAgfVxuICAgICAgICBpbnB1dE5hbWVzVVRGOEVuY29kZWQucHVzaChuYW1lKTtcbiAgICAgICAgaW5wdXROYW1lcy5wdXNoKHdhc20uVVRGOFRvU3RyaW5nKG5hbWUpKTtcbiAgICAgIH1cbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0Q291bnQ7IGkrKykge1xuICAgICAgICBjb25zdCBuYW1lID0gd2FzbS5fT3J0R2V0T3V0cHV0TmFtZShzZXNzaW9uSGFuZGxlLCBpKTtcbiAgICAgICAgaWYgKG5hbWUgPT09IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcJ3QgZ2V0IGFuIG91dHB1dCBuYW1lJyk7XG4gICAgICAgIH1cbiAgICAgICAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZC5wdXNoKG5hbWUpO1xuICAgICAgICBvdXRwdXROYW1lcy5wdXNoKHdhc20uVVRGOFRvU3RyaW5nKG5hbWUpKTtcbiAgICAgIH1cblxuICAgICAgYWN0aXZlU2Vzc2lvbnMuc2V0KHNlc3Npb25IYW5kbGUsIFtzZXNzaW9uSGFuZGxlLCBpbnB1dE5hbWVzVVRGOEVuY29kZWQsIG91dHB1dE5hbWVzVVRGOEVuY29kZWRdKTtcbiAgICAgIHJldHVybiBbc2Vzc2lvbkhhbmRsZSwgaW5wdXROYW1lcywgb3V0cHV0TmFtZXNdO1xuICAgIH07XG5cblxuLyoqXG4gKiBjcmVhdGUgYW4gaW5zdGFuY2Ugb2YgSW5mZXJlbmNlU2Vzc2lvbi5cbiAqIEByZXR1cm5zIHRoZSBtZXRhZGF0YSBvZiBJbmZlcmVuY2VTZXNzaW9uLiAwLXZhbHVlIGhhbmRsZSBmb3IgZmFpbHVyZS5cbiAqL1xuZXhwb3J0IGNvbnN0IGNyZWF0ZVNlc3Npb24gPVxuICAgIChtb2RlbDogVWludDhBcnJheSwgb3B0aW9ucz86IEluZmVyZW5jZVNlc3Npb24uU2Vzc2lvbk9wdGlvbnMpOiBTZXJpYWxpemFibGVTZXNzaW9uTWV0YWRhdGEgPT4ge1xuICAgICAgY29uc3QgbW9kZWxEYXRhOiBTZXJpYWxpemFibGVNb2RlbGRhdGEgPSBjcmVhdGVTZXNzaW9uQWxsb2NhdGUobW9kZWwpO1xuICAgICAgcmV0dXJuIGNyZWF0ZVNlc3Npb25GaW5hbGl6ZShtb2RlbERhdGEsIG9wdGlvbnMpO1xuICAgIH07XG5cbmV4cG9ydCBjb25zdCByZWxlYXNlU2Vzc2lvbiA9IChzZXNzaW9uSWQ6IG51bWJlcik6IHZvaWQgPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgY29uc3Qgc2Vzc2lvbiA9IGFjdGl2ZVNlc3Npb25zLmdldChzZXNzaW9uSWQpO1xuICBpZiAoIXNlc3Npb24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgc2Vzc2lvbiBpZCcpO1xuICB9XG4gIGNvbnN0IHNlc3Npb25IYW5kbGUgPSBzZXNzaW9uWzBdO1xuICBjb25zdCBpbnB1dE5hbWVzVVRGOEVuY29kZWQgPSBzZXNzaW9uWzFdO1xuICBjb25zdCBvdXRwdXROYW1lc1VURjhFbmNvZGVkID0gc2Vzc2lvblsyXTtcblxuICBpbnB1dE5hbWVzVVRGOEVuY29kZWQuZm9yRWFjaCh3YXNtLl9PcnRGcmVlKTtcbiAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZC5mb3JFYWNoKHdhc20uX09ydEZyZWUpO1xuICB3YXNtLl9PcnRSZWxlYXNlU2Vzc2lvbihzZXNzaW9uSGFuZGxlKTtcbiAgYWN0aXZlU2Vzc2lvbnMuZGVsZXRlKHNlc3Npb25JZCk7XG59O1xuXG4vKipcbiAqIHBlcmZvcm0gaW5mZXJlbmNlIHJ1blxuICovXG5leHBvcnQgY29uc3QgcnVuID0gYXN5bmMoXG4gICAgc2Vzc2lvbklkOiBudW1iZXIsIGlucHV0SW5kaWNlczogbnVtYmVyW10sIGlucHV0czogU2VyaWFsaXphYmxlVGVuc29yW10sIG91dHB1dEluZGljZXM6IG51bWJlcltdLFxuICAgIG9wdGlvbnM6IEluZmVyZW5jZVNlc3Npb24uUnVuT3B0aW9ucyk6IFByb21pc2U8U2VyaWFsaXphYmxlVGVuc29yW10+ID0+IHtcbiAgY29uc3Qgd2FzbSA9IGdldEluc3RhbmNlKCk7XG4gIGNvbnN0IHNlc3Npb24gPSBhY3RpdmVTZXNzaW9ucy5nZXQoc2Vzc2lvbklkKTtcbiAgaWYgKCFzZXNzaW9uKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIHNlc3Npb24gaWQnKTtcbiAgfVxuICBjb25zdCBzZXNzaW9uSGFuZGxlID0gc2Vzc2lvblswXTtcbiAgY29uc3QgaW5wdXROYW1lc1VURjhFbmNvZGVkID0gc2Vzc2lvblsxXTtcbiAgY29uc3Qgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZCA9IHNlc3Npb25bMl07XG5cbiAgY29uc3QgaW5wdXRDb3VudCA9IGlucHV0SW5kaWNlcy5sZW5ndGg7XG4gIGNvbnN0IG91dHB1dENvdW50ID0gb3V0cHV0SW5kaWNlcy5sZW5ndGg7XG5cbiAgbGV0IHJ1bk9wdGlvbnNIYW5kbGUgPSAwO1xuICBsZXQgcnVuT3B0aW9uc0FsbG9jczogbnVtYmVyW10gPSBbXTtcblxuICBjb25zdCBpbnB1dFZhbHVlczogbnVtYmVyW10gPSBbXTtcbiAgY29uc3QgaW5wdXRBbGxvY3M6IG51bWJlcltdID0gW107XG5cbiAgdHJ5IHtcbiAgICBbcnVuT3B0aW9uc0hhbmRsZSwgcnVuT3B0aW9uc0FsbG9jc10gPSBzZXRSdW5PcHRpb25zKG9wdGlvbnMpO1xuXG4gICAgLy8gY3JlYXRlIGlucHV0IHRlbnNvcnNcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0Q291bnQ7IGkrKykge1xuICAgICAgY29uc3QgZGF0YVR5cGUgPSBpbnB1dHNbaV1bMF07XG4gICAgICBjb25zdCBkaW1zID0gaW5wdXRzW2ldWzFdO1xuICAgICAgY29uc3QgZGF0YSA9IGlucHV0c1tpXVsyXTtcblxuICAgICAgbGV0IGRhdGFPZmZzZXQ6IG51bWJlcjtcbiAgICAgIGxldCBkYXRhQnl0ZUxlbmd0aDogbnVtYmVyO1xuXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShkYXRhKSkge1xuICAgICAgICAvLyBzdHJpbmcgdGVuc29yXG4gICAgICAgIGRhdGFCeXRlTGVuZ3RoID0gNCAqIGRhdGEubGVuZ3RoO1xuICAgICAgICBkYXRhT2Zmc2V0ID0gd2FzbS5fbWFsbG9jKGRhdGFCeXRlTGVuZ3RoKTtcbiAgICAgICAgaW5wdXRBbGxvY3MucHVzaChkYXRhT2Zmc2V0KTtcbiAgICAgICAgbGV0IGRhdGFJbmRleCA9IGRhdGFPZmZzZXQgLyA0O1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGRhdGFbaV0gIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGB0ZW5zb3IgZGF0YSBhdCBpbmRleCAke2l9IGlzIG5vdCBhIHN0cmluZ2ApO1xuICAgICAgICAgIH1cbiAgICAgICAgICB3YXNtLkhFQVBVMzJbZGF0YUluZGV4KytdID0gYWxsb2NXYXNtU3RyaW5nKGRhdGFbaV0sIGlucHV0QWxsb2NzKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZGF0YUJ5dGVMZW5ndGggPSBkYXRhLmJ5dGVMZW5ndGg7XG4gICAgICAgIGRhdGFPZmZzZXQgPSB3YXNtLl9tYWxsb2MoZGF0YUJ5dGVMZW5ndGgpO1xuICAgICAgICBpbnB1dEFsbG9jcy5wdXNoKGRhdGFPZmZzZXQpO1xuICAgICAgICB3YXNtLkhFQVBVOC5zZXQobmV3IFVpbnQ4QXJyYXkoZGF0YS5idWZmZXIsIGRhdGEuYnl0ZU9mZnNldCwgZGF0YUJ5dGVMZW5ndGgpLCBkYXRhT2Zmc2V0KTtcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc3RhY2sgPSB3YXNtLnN0YWNrU2F2ZSgpO1xuICAgICAgY29uc3QgZGltc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyg0ICogZGltcy5sZW5ndGgpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgbGV0IGRpbUluZGV4ID0gZGltc09mZnNldCAvIDQ7XG4gICAgICAgIGRpbXMuZm9yRWFjaChkID0+IHdhc20uSEVBUDMyW2RpbUluZGV4KytdID0gZCk7XG4gICAgICAgIGNvbnN0IHRlbnNvciA9IHdhc20uX09ydENyZWF0ZVRlbnNvcihcbiAgICAgICAgICAgIHRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtKGRhdGFUeXBlKSwgZGF0YU9mZnNldCwgZGF0YUJ5dGVMZW5ndGgsIGRpbXNPZmZzZXQsIGRpbXMubGVuZ3RoKTtcbiAgICAgICAgaWYgKHRlbnNvciA9PT0gMCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuXFwndCBjcmVhdGUgYSB0ZW5zb3InKTtcbiAgICAgICAgfVxuICAgICAgICBpbnB1dFZhbHVlcy5wdXNoKHRlbnNvcik7XG4gICAgICB9IGZpbmFsbHkge1xuICAgICAgICB3YXNtLnN0YWNrUmVzdG9yZShzdGFjayk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgYmVmb3JlUnVuU3RhY2sgPSB3YXNtLnN0YWNrU2F2ZSgpO1xuICAgIGNvbnN0IGlucHV0VmFsdWVzT2Zmc2V0ID0gd2FzbS5zdGFja0FsbG9jKGlucHV0Q291bnQgKiA0KTtcbiAgICBjb25zdCBpbnB1dE5hbWVzT2Zmc2V0ID0gd2FzbS5zdGFja0FsbG9jKGlucHV0Q291bnQgKiA0KTtcbiAgICBjb25zdCBvdXRwdXRWYWx1ZXNPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2Mob3V0cHV0Q291bnQgKiA0KTtcbiAgICBjb25zdCBvdXRwdXROYW1lc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyhvdXRwdXRDb3VudCAqIDQpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGxldCBpbnB1dFZhbHVlc0luZGV4ID0gaW5wdXRWYWx1ZXNPZmZzZXQgLyA0O1xuICAgICAgbGV0IGlucHV0TmFtZXNJbmRleCA9IGlucHV0TmFtZXNPZmZzZXQgLyA0O1xuICAgICAgbGV0IG91dHB1dFZhbHVlc0luZGV4ID0gb3V0cHV0VmFsdWVzT2Zmc2V0IC8gNDtcbiAgICAgIGxldCBvdXRwdXROYW1lc0luZGV4ID0gb3V0cHV0TmFtZXNPZmZzZXQgLyA0O1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dENvdW50OyBpKyspIHtcbiAgICAgICAgd2FzbS5IRUFQVTMyW2lucHV0VmFsdWVzSW5kZXgrK10gPSBpbnB1dFZhbHVlc1tpXTtcbiAgICAgICAgd2FzbS5IRUFQVTMyW2lucHV0TmFtZXNJbmRleCsrXSA9IGlucHV0TmFtZXNVVEY4RW5jb2RlZFtpbnB1dEluZGljZXNbaV1dO1xuICAgICAgfVxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXRDb3VudDsgaSsrKSB7XG4gICAgICAgIHdhc20uSEVBUFUzMltvdXRwdXRWYWx1ZXNJbmRleCsrXSA9IDA7XG4gICAgICAgIHdhc20uSEVBUFUzMltvdXRwdXROYW1lc0luZGV4KytdID0gb3V0cHV0TmFtZXNVVEY4RW5jb2RlZFtvdXRwdXRJbmRpY2VzW2ldXTtcbiAgICAgIH1cblxuICAgICAgLy8gc3VwcG9ydCBSdW5PcHRpb25zXG4gICAgICBsZXQgZXJyb3JDb2RlID0gd2FzbS5fT3J0UnVuKFxuICAgICAgICAgIHNlc3Npb25IYW5kbGUsIGlucHV0TmFtZXNPZmZzZXQsIGlucHV0VmFsdWVzT2Zmc2V0LCBpbnB1dENvdW50LCBvdXRwdXROYW1lc09mZnNldCwgb3V0cHV0Q291bnQsXG4gICAgICAgICAgb3V0cHV0VmFsdWVzT2Zmc2V0LCBydW5PcHRpb25zSGFuZGxlKTtcblxuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxuICAgICAgY29uc3QgcnVuUHJvbWlzZSA9IHdhc20uanNlcFJ1blByb21pc2U7XG4gICAgICBpZiAocnVuUHJvbWlzZSAmJiB0eXBlb2YgcnVuUHJvbWlzZS50aGVuICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBlcnJvckNvZGUgPSBhd2FpdCBydW5Qcm9taXNlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBvdXRwdXQ6IFNlcmlhbGl6YWJsZVRlbnNvcltdID0gW107XG5cbiAgICAgIGlmIChlcnJvckNvZGUgPT09IDApIHtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXRDb3VudDsgaSsrKSB7XG4gICAgICAgICAgY29uc3QgdGVuc29yID0gd2FzbS5IRUFQVTMyW291dHB1dFZhbHVlc09mZnNldCAvIDQgKyBpXTtcblxuICAgICAgICAgIGNvbnN0IGJlZm9yZUdldFRlbnNvckRhdGFTdGFjayA9IHdhc20uc3RhY2tTYXZlKCk7XG4gICAgICAgICAgLy8gc3RhY2sgYWxsb2NhdGUgNCBwb2ludGVyIHZhbHVlXG4gICAgICAgICAgY29uc3QgdGVuc29yRGF0YU9mZnNldCA9IHdhc20uc3RhY2tBbGxvYyg0ICogNCk7XG5cbiAgICAgICAgICBsZXQgdHlwZTogVGVuc29yLlR5cGV8dW5kZWZpbmVkLCBkYXRhT2Zmc2V0ID0gMDtcbiAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgZXJyb3JDb2RlID0gd2FzbS5fT3J0R2V0VGVuc29yRGF0YShcbiAgICAgICAgICAgICAgICB0ZW5zb3IsIHRlbnNvckRhdGFPZmZzZXQsIHRlbnNvckRhdGFPZmZzZXQgKyA0LCB0ZW5zb3JEYXRhT2Zmc2V0ICsgOCwgdGVuc29yRGF0YU9mZnNldCArIDEyKTtcbiAgICAgICAgICAgIGlmIChlcnJvckNvZGUgIT09IDApIHtcbiAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4ndCBhY2Nlc3Mgb3V0cHV0IHRlbnNvciBkYXRhLiBlcnJvciBjb2RlID0gJHtlcnJvckNvZGV9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsZXQgdGVuc29yRGF0YUluZGV4ID0gdGVuc29yRGF0YU9mZnNldCAvIDQ7XG4gICAgICAgICAgICBjb25zdCBkYXRhVHlwZSA9IHdhc20uSEVBUFUzMlt0ZW5zb3JEYXRhSW5kZXgrK107XG4gICAgICAgICAgICBkYXRhT2Zmc2V0ID0gd2FzbS5IRUFQVTMyW3RlbnNvckRhdGFJbmRleCsrXTtcbiAgICAgICAgICAgIGNvbnN0IGRpbXNPZmZzZXQgPSB3YXNtLkhFQVBVMzJbdGVuc29yRGF0YUluZGV4KytdO1xuICAgICAgICAgICAgY29uc3QgZGltc0xlbmd0aCA9IHdhc20uSEVBUFUzMlt0ZW5zb3JEYXRhSW5kZXgrK107XG4gICAgICAgICAgICBjb25zdCBkaW1zID0gW107XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRpbXNMZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICBkaW1zLnB1c2god2FzbS5IRUFQVTMyW2RpbXNPZmZzZXQgLyA0ICsgaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2FzbS5fT3J0RnJlZShkaW1zT2Zmc2V0KTtcblxuICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IGRpbXMubGVuZ3RoID09PSAwID8gMSA6IGRpbXMucmVkdWNlKChhLCBiKSA9PiBhICogYik7XG4gICAgICAgICAgICB0eXBlID0gdGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcoZGF0YVR5cGUpO1xuICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHN0cmluZ0RhdGE6IHN0cmluZ1tdID0gW107XG4gICAgICAgICAgICAgIGxldCBkYXRhSW5kZXggPSBkYXRhT2Zmc2V0IC8gNDtcbiAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaXplOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBvZmZzZXQgPSB3YXNtLkhFQVBVMzJbZGF0YUluZGV4KytdO1xuICAgICAgICAgICAgICAgIGNvbnN0IG1heEJ5dGVzVG9SZWFkID0gaSA9PT0gc2l6ZSAtIDEgPyB1bmRlZmluZWQgOiB3YXNtLkhFQVBVMzJbZGF0YUluZGV4XSAtIG9mZnNldDtcbiAgICAgICAgICAgICAgICBzdHJpbmdEYXRhLnB1c2god2FzbS5VVEY4VG9TdHJpbmcob2Zmc2V0LCBtYXhCeXRlc1RvUmVhZCkpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIG91dHB1dC5wdXNoKFt0eXBlLCBkaW1zLCBzdHJpbmdEYXRhXSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBjb25zdCB0eXBlZEFycmF5Q29uc3RydWN0b3IgPSB0ZW5zb3JUeXBlVG9UeXBlZEFycmF5Q29uc3RydWN0b3IodHlwZSk7XG4gICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBuZXcgdHlwZWRBcnJheUNvbnN0cnVjdG9yKHNpemUpO1xuICAgICAgICAgICAgICBuZXcgVWludDhBcnJheShkYXRhLmJ1ZmZlciwgZGF0YS5ieXRlT2Zmc2V0LCBkYXRhLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgICAuc2V0KHdhc20uSEVBUFU4LnN1YmFycmF5KGRhdGFPZmZzZXQsIGRhdGFPZmZzZXQgKyBkYXRhLmJ5dGVMZW5ndGgpKTtcbiAgICAgICAgICAgICAgb3V0cHV0LnB1c2goW3R5cGUsIGRpbXMsIGRhdGFdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgd2FzbS5zdGFja1Jlc3RvcmUoYmVmb3JlR2V0VGVuc29yRGF0YVN0YWNrKTtcbiAgICAgICAgICAgIGlmICh0eXBlID09PSAnc3RyaW5nJyAmJiBkYXRhT2Zmc2V0KSB7XG4gICAgICAgICAgICAgIHdhc20uX2ZyZWUoZGF0YU9mZnNldCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3YXNtLl9PcnRSZWxlYXNlVGVuc29yKHRlbnNvcik7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChlcnJvckNvZGUgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgZmFpbGVkIHRvIGNhbGwgT3J0UnVuKCkuIGVycm9yIGNvZGUgPSAke2Vycm9yQ29kZX0uYCk7XG4gICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHdhc20uc3RhY2tSZXN0b3JlKGJlZm9yZVJ1blN0YWNrKTtcbiAgICB9XG4gIH0gZmluYWxseSB7XG4gICAgaW5wdXRWYWx1ZXMuZm9yRWFjaCh3YXNtLl9PcnRSZWxlYXNlVGVuc29yKTtcbiAgICBpbnB1dEFsbG9jcy5mb3JFYWNoKHdhc20uX2ZyZWUpO1xuXG4gICAgd2FzbS5fT3J0UmVsZWFzZVJ1bk9wdGlvbnMocnVuT3B0aW9uc0hhbmRsZSk7XG4gICAgcnVuT3B0aW9uc0FsbG9jcy5mb3JFYWNoKHdhc20uX2ZyZWUpO1xuICB9XG59O1xuXG4vKipcbiAqIGVuZCBwcm9maWxpbmdcbiAqL1xuZXhwb3J0IGNvbnN0IGVuZFByb2ZpbGluZyA9IChzZXNzaW9uSWQ6IG51bWJlcik6IHZvaWQgPT4ge1xuICBjb25zdCB3YXNtID0gZ2V0SW5zdGFuY2UoKTtcbiAgY29uc3Qgc2Vzc2lvbiA9IGFjdGl2ZVNlc3Npb25zLmdldChzZXNzaW9uSWQpO1xuICBpZiAoIXNlc3Npb24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgc2Vzc2lvbiBpZCcpO1xuICB9XG4gIGNvbnN0IHNlc3Npb25IYW5kbGUgPSBzZXNzaW9uWzBdO1xuXG4gIC8vIHByb2ZpbGUgZmlsZSBuYW1lIGlzIG5vdCB1c2VkIHlldCwgYnV0IGl0IG11c3QgYmUgZnJlZWQuXG4gIGNvbnN0IHByb2ZpbGVGaWxlTmFtZSA9IHdhc20uX09ydEVuZFByb2ZpbGluZyhzZXNzaW9uSGFuZGxlKTtcbiAgaWYgKHByb2ZpbGVGaWxlTmFtZSA9PT0gMCkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2FuXFwndCBnZXQgYW4gcHJvZmlsZSBmaWxlIG5hbWUnKTtcbiAgfVxuICB3YXNtLl9PcnRGcmVlKHByb2ZpbGVGaWxlTmFtZSk7XG59O1xuXG5leHBvcnQgY29uc3QgZXh0cmFjdFRyYW5zZmVyYWJsZUJ1ZmZlcnMgPSAodGVuc29yczogcmVhZG9ubHkgU2VyaWFsaXphYmxlVGVuc29yW10pOiBBcnJheUJ1ZmZlckxpa2VbXSA9PiB7XG4gIGNvbnN0IGJ1ZmZlcnM6IEFycmF5QnVmZmVyTGlrZVtdID0gW107XG4gIGZvciAoY29uc3QgdGVuc29yIG9mIHRlbnNvcnMpIHtcbiAgICBjb25zdCBkYXRhID0gdGVuc29yWzJdO1xuICAgIGlmICghQXJyYXkuaXNBcnJheShkYXRhKSAmJiBkYXRhLmJ1ZmZlcikge1xuICAgICAgYnVmZmVycy5wdXNoKGRhdGEuYnVmZmVyKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGJ1ZmZlcnM7XG59O1xuIiwiLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXG5cbmltcG9ydCB7RW52fSBmcm9tICdvbm54cnVudGltZS1jb21tb24nO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcblxuaW1wb3J0IHtPcnRXYXNtTW9kdWxlfSBmcm9tICcuL2JpbmRpbmcvb3J0LXdhc20nO1xuaW1wb3J0IHtPcnRXYXNtVGhyZWFkZWRNb2R1bGV9IGZyb20gJy4vYmluZGluZy9vcnQtd2FzbS10aHJlYWRlZCc7XG5cbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMgKi9cbmNvbnN0IG9ydFdhc21GYWN0b3J5OiBFbXNjcmlwdGVuTW9kdWxlRmFjdG9yeTxPcnRXYXNtTW9kdWxlPiA9XG4gICAgQlVJTERfREVGUy5ESVNBQkxFX1dFQkdQVSA/IHJlcXVpcmUoJy4vYmluZGluZy9vcnQtd2FzbS5qcycpIDogcmVxdWlyZSgnLi9iaW5kaW5nL29ydC13YXNtLXNpbWQuanNlcC5qcycpO1xuXG5jb25zdCBvcnRXYXNtRmFjdG9yeVRocmVhZGVkOiBFbXNjcmlwdGVuTW9kdWxlRmFjdG9yeTxPcnRXYXNtTW9kdWxlPiA9ICFCVUlMRF9ERUZTLkRJU0FCTEVfV0FTTV9USFJFQUQgP1xuICAgIChCVUlMRF9ERUZTLkRJU0FCTEVfV0VCR1BVID8gcmVxdWlyZSgnLi9iaW5kaW5nL29ydC13YXNtLXRocmVhZGVkLmpzJykgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWlyZSgnLi9iaW5kaW5nL29ydC13YXNtLXNpbWQtdGhyZWFkZWQuanNlcC5qcycpKSA6XG4gICAgb3J0V2FzbUZhY3Rvcnk7XG4vKiBlc2xpbnQtZW5hYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMgKi9cblxubGV0IHdhc206IE9ydFdhc21Nb2R1bGV8dW5kZWZpbmVkO1xubGV0IGluaXRpYWxpemVkID0gZmFsc2U7XG5sZXQgaW5pdGlhbGl6aW5nID0gZmFsc2U7XG5sZXQgYWJvcnRlZCA9IGZhbHNlO1xuXG5jb25zdCBpc011bHRpVGhyZWFkU3VwcG9ydGVkID0gKCk6IGJvb2xlYW4gPT4ge1xuICB0cnkge1xuICAgIC8vIElmICdTaGFyZWRBcnJheUJ1ZmZlcicgaXMgbm90IGF2YWlsYWJsZSwgV2ViQXNzZW1ibHkgdGhyZWFkcyB3aWxsIG5vdCB3b3JrLlxuICAgIGlmICh0eXBlb2YgU2hhcmVkQXJyYXlCdWZmZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLy8gVGVzdCBmb3IgdHJhbnNmZXJhYmlsaXR5IG9mIFNBQnMgKGZvciBicm93c2Vycy4gbmVlZGVkIGZvciBGaXJlZm94KVxuICAgIC8vIGh0dHBzOi8vZ3JvdXBzLmdvb2dsZS5jb20vZm9ydW0vIyFtc2cvbW96aWxsYS5kZXYucGxhdGZvcm0vSUhrQlpsSEVUcEEvZHdzTU5jaFdFUUFKXG4gICAgaWYgKHR5cGVvZiBNZXNzYWdlQ2hhbm5lbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIG5ldyBNZXNzYWdlQ2hhbm5lbCgpLnBvcnQxLnBvc3RNZXNzYWdlKG5ldyBTaGFyZWRBcnJheUJ1ZmZlcigxKSk7XG4gICAgfVxuXG4gICAgLy8gVGVzdCBmb3IgV2ViQXNzZW1ibHkgdGhyZWFkcyBjYXBhYmlsaXR5IChmb3IgYm90aCBicm93c2VycyBhbmQgTm9kZS5qcylcbiAgICAvLyBUaGlzIHR5cGVkIGFycmF5IGlzIGEgV2ViQXNzZW1ibHkgcHJvZ3JhbSBjb250YWluaW5nIHRocmVhZGVkIGluc3RydWN0aW9ucy5cbiAgICByZXR1cm4gV2ViQXNzZW1ibHkudmFsaWRhdGUobmV3IFVpbnQ4QXJyYXkoW1xuICAgICAgMCwgOTcsIDExNSwgMTA5LCAxLCAwLCAgMCwgIDAsIDEsIDQsIDEsICA5NiwgMCwgICAwLCAgMywgMiwgMSwgIDAsIDUsXG4gICAgICA0LCAxLCAgMywgICAxLCAgIDEsIDEwLCAxMSwgMSwgOSwgMCwgNjUsIDAsICAyNTQsIDE2LCAyLCAwLCAyNiwgMTFcbiAgICBdKSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn07XG5cbmNvbnN0IGlzU2ltZFN1cHBvcnRlZCA9ICgpOiBib29sZWFuID0+IHtcbiAgdHJ5IHtcbiAgICAvLyBUZXN0IGZvciBXZWJBc3NlbWJseSBTSU1EIGNhcGFiaWxpdHkgKGZvciBib3RoIGJyb3dzZXJzIGFuZCBOb2RlLmpzKVxuICAgIC8vIFRoaXMgdHlwZWQgYXJyYXkgaXMgYSBXZWJBc3NlbWJseSBwcm9ncmFtIGNvbnRhaW5pbmcgU0lNRCBpbnN0cnVjdGlvbnMuXG5cbiAgICAvLyBUaGUgYmluYXJ5IGRhdGEgaXMgZ2VuZXJhdGVkIGZyb20gdGhlIGZvbGxvd2luZyBjb2RlIGJ5IHdhdDJ3YXNtOlxuICAgIC8vXG4gICAgLy8gKG1vZHVsZVxuICAgIC8vICAgKHR5cGUgJHQwIChmdW5jKSlcbiAgICAvLyAgIChmdW5jICRmMCAodHlwZSAkdDApXG4gICAgLy8gICAgIChkcm9wXG4gICAgLy8gICAgICAgKGkzMng0LmRvdF9pMTZ4OF9zXG4gICAgLy8gICAgICAgICAoaTh4MTYuc3BsYXRcbiAgICAvLyAgICAgICAgICAgKGkzMi5jb25zdCAwKSlcbiAgICAvLyAgICAgICAgICh2MTI4LmNvbnN0IGkzMng0IDB4MDAwMDAwMDAgMHgwMDAwMDAwMCAweDAwMDAwMDAwIDB4MDAwMDAwMDApKSkpKVxuXG4gICAgcmV0dXJuIFdlYkFzc2VtYmx5LnZhbGlkYXRlKG5ldyBVaW50OEFycmF5KFtcbiAgICAgIDAsICAgOTcsIDExNSwgMTA5LCAxLCAwLCAwLCAwLCAxLCA0LCAxLCA5NiwgMCwgMCwgMywgMiwgMSwgMCwgMTAsIDMwLCAxLCAgIDI4LCAgMCwgNjUsIDAsXG4gICAgICAyNTMsIDE1LCAyNTMsIDEyLCAgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgIDAsIDAsIDAsIDAsIDAsIDAsIDAsICAwLCAgMjUzLCAxODYsIDEsIDI2LCAxMVxuICAgIF0pKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufTtcblxuY29uc3QgZ2V0V2FzbUZpbGVOYW1lID0gKHVzZVNpbWQ6IGJvb2xlYW4sIHVzZVRocmVhZHM6IGJvb2xlYW4pID0+IHtcbiAgaWYgKHVzZVRocmVhZHMpIHtcbiAgICByZXR1cm4gdXNlU2ltZCA/ICdvcnQtd2FzbS1zaW1kLXRocmVhZGVkLndhc20nIDogJ29ydC13YXNtLXRocmVhZGVkLndhc20nO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiB1c2VTaW1kID8gJ29ydC13YXNtLXNpbWQud2FzbScgOiAnb3J0LXdhc20ud2FzbSc7XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBpbml0aWFsaXplV2ViQXNzZW1ibHkgPSBhc3luYyhmbGFnczogRW52LldlYkFzc2VtYmx5RmxhZ3MpOiBQcm9taXNlPHZvaWQ+ID0+IHtcbiAgaWYgKGluaXRpYWxpemVkKSB7XG4gICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICB9XG4gIGlmIChpbml0aWFsaXppbmcpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ211bHRpcGxlIGNhbGxzIHRvIFxcJ2luaXRpYWxpemVXZWJBc3NlbWJseSgpXFwnIGRldGVjdGVkLicpO1xuICB9XG4gIGlmIChhYm9ydGVkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcmV2aW91cyBjYWxsIHRvIFxcJ2luaXRpYWxpemVXZWJBc3NlbWJseSgpXFwnIGZhaWxlZC4nKTtcbiAgfVxuXG4gIGluaXRpYWxpemluZyA9IHRydWU7XG5cbiAgLy8gd2FzbSBmbGFncyBhcmUgYWxyZWFkeSBpbml0aWFsaXplZFxuICBjb25zdCB0aW1lb3V0ID0gZmxhZ3MuaW5pdFRpbWVvdXQhO1xuICBjb25zdCBudW1UaHJlYWRzID0gZmxhZ3MubnVtVGhyZWFkcyE7XG4gIGNvbnN0IHNpbWQgPSBmbGFncy5zaW1kITtcblxuICBjb25zdCB1c2VUaHJlYWRzID0gbnVtVGhyZWFkcyA+IDEgJiYgaXNNdWx0aVRocmVhZFN1cHBvcnRlZCgpO1xuICBjb25zdCB1c2VTaW1kID0gc2ltZCAmJiBpc1NpbWRTdXBwb3J0ZWQoKTtcblxuICBjb25zdCB3YXNtUGF0aHMgPSBmbGFncy53YXNtUGF0aHM7XG4gIGNvbnN0IHdhc21QcmVmaXhPdmVycmlkZSA9IHR5cGVvZiB3YXNtUGF0aHMgPT09ICdzdHJpbmcnID8gd2FzbVBhdGhzIDogdW5kZWZpbmVkO1xuICBjb25zdCB3YXNtRmlsZU5hbWUgPSBnZXRXYXNtRmlsZU5hbWUodXNlU2ltZCwgdXNlVGhyZWFkcyk7XG4gIGNvbnN0IHdhc21QYXRoT3ZlcnJpZGUgPSB0eXBlb2Ygd2FzbVBhdGhzID09PSAnb2JqZWN0JyA/IHdhc21QYXRoc1t3YXNtRmlsZU5hbWVdIDogdW5kZWZpbmVkO1xuXG4gIGxldCBpc1RpbWVvdXQgPSBmYWxzZTtcblxuICBjb25zdCB0YXNrczogQXJyYXk8UHJvbWlzZTx2b2lkPj4gPSBbXTtcblxuICAvLyBwcm9taXNlIGZvciB0aW1lb3V0XG4gIGlmICh0aW1lb3V0ID4gMCkge1xuICAgIHRhc2tzLnB1c2gobmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBpc1RpbWVvdXQgPSB0cnVlO1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9LCB0aW1lb3V0KTtcbiAgICB9KSk7XG4gIH1cblxuICAvLyBwcm9taXNlIGZvciBtb2R1bGUgaW5pdGlhbGl6YXRpb25cbiAgdGFza3MucHVzaChuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgY29uc3QgZmFjdG9yeSA9IHVzZVRocmVhZHMgPyBvcnRXYXNtRmFjdG9yeVRocmVhZGVkIDogb3J0V2FzbUZhY3Rvcnk7XG4gICAgY29uc3QgY29uZmlnOiBQYXJ0aWFsPE9ydFdhc21Nb2R1bGU+ID0ge1xuICAgICAgbG9jYXRlRmlsZTogKGZpbGVOYW1lOiBzdHJpbmcsIHNjcmlwdERpcmVjdG9yeTogc3RyaW5nKSA9PiB7XG4gICAgICAgIGlmICghQlVJTERfREVGUy5ESVNBQkxFX1dBU01fVEhSRUFEICYmIHVzZVRocmVhZHMgJiYgZmlsZU5hbWUuZW5kc1dpdGgoJy53b3JrZXIuanMnKSAmJlxuICAgICAgICAgICAgdHlwZW9mIEJsb2IgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgcmV0dXJuIFVSTC5jcmVhdGVPYmplY3RVUkwobmV3IEJsb2IoXG4gICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIHJlcXVpcmUoKSBmdW5jdGlvbiBpcyBoYW5kbGVkIGJ5IHdlYnBhY2sgdG8gbG9hZCBmaWxlIGNvbnRlbnQgb2YgdGhlIGNvcnJlc3BvbmRpbmcgLndvcmtlci5qc1xuICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXG4gICAgICAgICAgICAgICAgcmVxdWlyZSgnLi9iaW5kaW5nL29ydC13YXNtLXRocmVhZGVkLndvcmtlci5qcycpXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIHt0eXBlOiAndGV4dC9qYXZhc2NyaXB0J30pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmaWxlTmFtZS5lbmRzV2l0aCgnLndhc20nKSkge1xuICAgICAgICAgIGlmICh3YXNtUGF0aE92ZXJyaWRlKSB7XG4gICAgICAgICAgICByZXR1cm4gd2FzbVBhdGhPdmVycmlkZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBwcmVmaXggPSB3YXNtUHJlZml4T3ZlcnJpZGUgPz8gc2NyaXB0RGlyZWN0b3J5O1xuXG4gICAgICAgICAgaWYgKCFCVUlMRF9ERUZTLkRJU0FCTEVfV0VCR1BVKSB7XG4gICAgICAgICAgICBpZiAod2FzbUZpbGVOYW1lID09PSAnb3J0LXdhc20tc2ltZC53YXNtJykge1xuICAgICAgICAgICAgICByZXR1cm4gcHJlZml4ICsgJ29ydC13YXNtLXNpbWQuanNlcC53YXNtJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAod2FzbUZpbGVOYW1lID09PSAnb3J0LXdhc20tc2ltZC10aHJlYWRlZC53YXNtJykge1xuICAgICAgICAgICAgICByZXR1cm4gcHJlZml4ICsgJ29ydC13YXNtLXNpbWQtdGhyZWFkZWQuanNlcC53YXNtJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gcHJlZml4ICsgd2FzbUZpbGVOYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHNjcmlwdERpcmVjdG9yeSArIGZpbGVOYW1lO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBpZiAoIUJVSUxEX0RFRlMuRElTQUJMRV9XQVNNX1RIUkVBRCAmJiB1c2VUaHJlYWRzKSB7XG4gICAgICBpZiAodHlwZW9mIEJsb2IgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGNvbmZpZy5tYWluU2NyaXB0VXJsT3JCbG9iID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJ29ydC13YXNtLXRocmVhZGVkLmpzJyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBzY3JpcHRTb3VyY2VDb2RlID0gYHZhciBvcnRXYXNtVGhyZWFkZWQ9KGZ1bmN0aW9uKCl7dmFyIF9zY3JpcHREaXI7cmV0dXJuICR7ZmFjdG9yeS50b1N0cmluZygpfX0pKCk7YDtcbiAgICAgICAgY29uZmlnLm1haW5TY3JpcHRVcmxPckJsb2IgPSBuZXcgQmxvYihbc2NyaXB0U291cmNlQ29kZV0sIHt0eXBlOiAndGV4dC9qYXZhc2NyaXB0J30pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZhY3RvcnkoY29uZmlnKS50aGVuKFxuICAgICAgICAvLyB3YXNtIG1vZHVsZSBpbml0aWFsaXplZCBzdWNjZXNzZnVsbHlcbiAgICAgICAgbW9kdWxlID0+IHtcbiAgICAgICAgICBpbml0aWFsaXppbmcgPSBmYWxzZTtcbiAgICAgICAgICBpbml0aWFsaXplZCA9IHRydWU7XG4gICAgICAgICAgd2FzbSA9IG1vZHVsZTtcbiAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgIH0sXG4gICAgICAgIC8vIHdhc20gbW9kdWxlIGZhaWxlZCB0byBpbml0aWFsaXplXG4gICAgICAgICh3aGF0KSA9PiB7XG4gICAgICAgICAgaW5pdGlhbGl6aW5nID0gZmFsc2U7XG4gICAgICAgICAgYWJvcnRlZCA9IHRydWU7XG4gICAgICAgICAgcmVqZWN0KHdoYXQpO1xuICAgICAgICB9KTtcbiAgfSkpO1xuXG4gIGF3YWl0IFByb21pc2UucmFjZSh0YXNrcyk7XG5cbiAgaWYgKGlzVGltZW91dCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgV2ViQXNzZW1ibHkgYmFja2VuZCBpbml0aWFsaXppbmcgZmFpbGVkIGR1ZSB0byB0aW1lb3V0OiAke3RpbWVvdXR9bXNgKTtcbiAgfVxufTtcblxuZXhwb3J0IGNvbnN0IGdldEluc3RhbmNlID0gKCk6IE9ydFdhc21Nb2R1bGUgPT4ge1xuICBpZiAoaW5pdGlhbGl6ZWQgJiYgd2FzbSkge1xuICAgIHJldHVybiB3YXNtO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdXZWJBc3NlbWJseSBpcyBub3QgaW5pdGlhbGl6ZWQgeWV0LicpO1xufTtcblxuZXhwb3J0IGNvbnN0IGRpc3Bvc2UgPSAoKTogdm9pZCA9PiB7XG4gIGlmIChpbml0aWFsaXplZCAmJiAhaW5pdGlhbGl6aW5nICYmICFhYm9ydGVkKSB7XG4gICAgaW5pdGlhbGl6aW5nID0gdHJ1ZTtcblxuICAgICh3YXNtIGFzIE9ydFdhc21UaHJlYWRlZE1vZHVsZSkuUFRocmVhZD8udGVybWluYXRlQWxsVGhyZWFkcygpO1xuICAgIHdhc20gPSB1bmRlZmluZWQ7XG5cbiAgICBpbml0aWFsaXppbmcgPSBmYWxzZTtcbiAgICBpbml0aWFsaXplZCA9IGZhbHNlO1xuICAgIGFib3J0ZWQgPSB0cnVlO1xuICB9XG59O1xuIiwiXG5pbXBvcnQgd29ya2VyIGZyb20gXCIhIS4uLy4uLy4uLy4uL25vZGVfbW9kdWxlcy93b3JrZXItbG9hZGVyL2Rpc3QvcnVudGltZS9pbmxpbmUuanNcIjtcblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gV29ya2VyX2ZuKCkge1xuICByZXR1cm4gd29ya2VyKFwiLyohXFxuKiBPTk5YIFJ1bnRpbWUgV2ViIHYxLjE1LjFcXG4qIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxcbiogTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxcbiovXFxuLyoqKioqKi8gKCgpID0+IHsgLy8gd2VicGFja0Jvb3RzdHJhcFxcbi8qKioqKiovIFxcdHZhciBfX3dlYnBhY2tfbW9kdWxlc19fID0gKHtcXG5cXG4vKioqLyBcXFwiLi9saWIvd2FzbS9vcHRpb25zLXV0aWxzLnRzXFxcIjpcXG4vKiEqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiAuL2xpYi93YXNtL29wdGlvbnMtdXRpbHMudHMgKioqIVxcbiAgXFxcXCoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xcbi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMpID0+IHtcXG5cXG5cXFwidXNlIHN0cmljdFxcXCI7XFxuXFxuLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXFxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcXFwiX19lc01vZHVsZVxcXCIsICh7IHZhbHVlOiB0cnVlIH0pKTtcXG5leHBvcnRzLml0ZXJhdGVFeHRyYU9wdGlvbnMgPSB2b2lkIDA7XFxuY29uc3QgaXRlcmF0ZUV4dHJhT3B0aW9ucyA9IChvcHRpb25zLCBwcmVmaXgsIHNlZW4sIGhhbmRsZXIpID0+IHtcXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zID09ICdvYmplY3QnICYmIG9wdGlvbnMgIT09IG51bGwpIHtcXG4gICAgICAgIGlmIChzZWVuLmhhcyhvcHRpb25zKSkge1xcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2lyY3VsYXIgcmVmZXJlbmNlIGluIG9wdGlvbnMnKTtcXG4gICAgICAgIH1cXG4gICAgICAgIGVsc2Uge1xcbiAgICAgICAgICAgIHNlZW4uYWRkKG9wdGlvbnMpO1xcbiAgICAgICAgfVxcbiAgICB9XFxuICAgIE9iamVjdC5lbnRyaWVzKG9wdGlvbnMpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xcbiAgICAgICAgY29uc3QgbmFtZSA9IChwcmVmaXgpID8gcHJlZml4ICsga2V5IDoga2V5O1xcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcXG4gICAgICAgICAgICAoMCwgZXhwb3J0cy5pdGVyYXRlRXh0cmFPcHRpb25zKSh2YWx1ZSwgbmFtZSArICcuJywgc2VlbiwgaGFuZGxlcik7XFxuICAgICAgICB9XFxuICAgICAgICBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcXG4gICAgICAgICAgICBoYW5kbGVyKG5hbWUsIHZhbHVlLnRvU3RyaW5nKCkpO1xcbiAgICAgICAgfVxcbiAgICAgICAgZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbicpIHtcXG4gICAgICAgICAgICBoYW5kbGVyKG5hbWUsICh2YWx1ZSkgPyAnMScgOiAnMCcpO1xcbiAgICAgICAgfVxcbiAgICAgICAgZWxzZSB7XFxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4ndCBoYW5kbGUgZXh0cmEgY29uZmlnIHR5cGU6ICR7dHlwZW9mIHZhbHVlfWApO1xcbiAgICAgICAgfVxcbiAgICB9KTtcXG59O1xcbmV4cG9ydHMuaXRlcmF0ZUV4dHJhT3B0aW9ucyA9IGl0ZXJhdGVFeHRyYU9wdGlvbnM7XFxuXFxuXFxuLyoqKi8gfSksXFxuXFxuLyoqKi8gXFxcIi4vbGliL3dhc20vcnVuLW9wdGlvbnMudHNcXFwiOlxcbi8qISoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiAuL2xpYi93YXNtL3J1bi1vcHRpb25zLnRzICoqKiFcXG4gIFxcXFwqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXFxuLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4ge1xcblxcblxcXCJ1c2Ugc3RyaWN0XFxcIjtcXG5cXG4vLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXFxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFxcXCJfX2VzTW9kdWxlXFxcIiwgKHsgdmFsdWU6IHRydWUgfSkpO1xcbmV4cG9ydHMuc2V0UnVuT3B0aW9ucyA9IHZvaWQgMDtcXG5jb25zdCBvcHRpb25zX3V0aWxzXzEgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL29wdGlvbnMtdXRpbHMgKi8gXFxcIi4vbGliL3dhc20vb3B0aW9ucy11dGlscy50c1xcXCIpO1xcbmNvbnN0IHN0cmluZ191dGlsc18xID0gX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgLi9zdHJpbmctdXRpbHMgKi8gXFxcIi4vbGliL3dhc20vc3RyaW5nLXV0aWxzLnRzXFxcIik7XFxuY29uc3Qgd2FzbV9mYWN0b3J5XzEgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL3dhc20tZmFjdG9yeSAqLyBcXFwiLi9saWIvd2FzbS93YXNtLWZhY3RvcnkudHNcXFwiKTtcXG5jb25zdCBzZXRSdW5PcHRpb25zID0gKG9wdGlvbnMpID0+IHtcXG4gICAgY29uc3Qgd2FzbSA9ICgwLCB3YXNtX2ZhY3RvcnlfMS5nZXRJbnN0YW5jZSkoKTtcXG4gICAgbGV0IHJ1bk9wdGlvbnNIYW5kbGUgPSAwO1xcbiAgICBjb25zdCBhbGxvY3MgPSBbXTtcXG4gICAgY29uc3QgcnVuT3B0aW9ucyA9IG9wdGlvbnMgfHwge307XFxuICAgIHRyeSB7XFxuICAgICAgICBpZiAoKG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5sb2dTZXZlcml0eUxldmVsKSA9PT0gdW5kZWZpbmVkKSB7XFxuICAgICAgICAgICAgcnVuT3B0aW9ucy5sb2dTZXZlcml0eUxldmVsID0gMjsgLy8gRGVmYXVsdCB0byB3YXJuaW5nXFxuICAgICAgICB9XFxuICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb3B0aW9ucy5sb2dTZXZlcml0eUxldmVsICE9PSAnbnVtYmVyJyB8fCAhTnVtYmVyLmlzSW50ZWdlcihvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwpIHx8XFxuICAgICAgICAgICAgb3B0aW9ucy5sb2dTZXZlcml0eUxldmVsIDwgMCB8fCBvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwgPiA0KSB7XFxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBsb2cgc2VydmVyaXR5IGxldmVsIGlzIG5vdCB2YWxpZDogJHtvcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWx9YCk7XFxuICAgICAgICB9XFxuICAgICAgICBpZiAoKG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbCkgPT09IHVuZGVmaW5lZCkge1xcbiAgICAgICAgICAgIHJ1bk9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwgPSAwOyAvLyBEZWZhdWx0IHRvIDBcXG4gICAgICAgIH1cXG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsICE9PSAnbnVtYmVyJyB8fCAhTnVtYmVyLmlzSW50ZWdlcihvcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsKSkge1xcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgbG9nIHZlcmJvc2l0eSBsZXZlbCBpcyBub3QgdmFsaWQ6ICR7b3B0aW9ucy5sb2dWZXJib3NpdHlMZXZlbH1gKTtcXG4gICAgICAgIH1cXG4gICAgICAgIGlmICgob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLnRlcm1pbmF0ZSkgPT09IHVuZGVmaW5lZCkge1xcbiAgICAgICAgICAgIHJ1bk9wdGlvbnMudGVybWluYXRlID0gZmFsc2U7XFxuICAgICAgICB9XFxuICAgICAgICBsZXQgdGFnRGF0YU9mZnNldCA9IDA7XFxuICAgICAgICBpZiAoKG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy50YWcpICE9PSB1bmRlZmluZWQpIHtcXG4gICAgICAgICAgICB0YWdEYXRhT2Zmc2V0ID0gKDAsIHN0cmluZ191dGlsc18xLmFsbG9jV2FzbVN0cmluZykob3B0aW9ucy50YWcsIGFsbG9jcyk7XFxuICAgICAgICB9XFxuICAgICAgICBydW5PcHRpb25zSGFuZGxlID0gd2FzbS5fT3J0Q3JlYXRlUnVuT3B0aW9ucyhydW5PcHRpb25zLmxvZ1NldmVyaXR5TGV2ZWwsIHJ1bk9wdGlvbnMubG9nVmVyYm9zaXR5TGV2ZWwsICEhcnVuT3B0aW9ucy50ZXJtaW5hdGUsIHRhZ0RhdGFPZmZzZXQpO1xcbiAgICAgICAgaWYgKHJ1bk9wdGlvbnNIYW5kbGUgPT09IDApIHtcXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcXFwndCBjcmVhdGUgcnVuIG9wdGlvbnMnKTtcXG4gICAgICAgIH1cXG4gICAgICAgIGlmICgob3B0aW9ucyA9PT0gbnVsbCB8fCBvcHRpb25zID09PSB2b2lkIDAgPyB2b2lkIDAgOiBvcHRpb25zLmV4dHJhKSAhPT0gdW5kZWZpbmVkKSB7XFxuICAgICAgICAgICAgKDAsIG9wdGlvbnNfdXRpbHNfMS5pdGVyYXRlRXh0cmFPcHRpb25zKShvcHRpb25zLmV4dHJhLCAnJywgbmV3IFdlYWtTZXQoKSwgKGtleSwgdmFsdWUpID0+IHtcXG4gICAgICAgICAgICAgICAgY29uc3Qga2V5RGF0YU9mZnNldCA9ICgwLCBzdHJpbmdfdXRpbHNfMS5hbGxvY1dhc21TdHJpbmcpKGtleSwgYWxsb2NzKTtcXG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWVEYXRhT2Zmc2V0ID0gKDAsIHN0cmluZ191dGlsc18xLmFsbG9jV2FzbVN0cmluZykodmFsdWUsIGFsbG9jcyk7XFxuICAgICAgICAgICAgICAgIGlmICh3YXNtLl9PcnRBZGRSdW5Db25maWdFbnRyeShydW5PcHRpb25zSGFuZGxlLCBrZXlEYXRhT2Zmc2V0LCB2YWx1ZURhdGFPZmZzZXQpICE9PSAwKSB7XFxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IHNldCBhIHJ1biBjb25maWcgZW50cnk6ICR7a2V5fSAtICR7dmFsdWV9YCk7XFxuICAgICAgICAgICAgICAgIH1cXG4gICAgICAgICAgICB9KTtcXG4gICAgICAgIH1cXG4gICAgICAgIHJldHVybiBbcnVuT3B0aW9uc0hhbmRsZSwgYWxsb2NzXTtcXG4gICAgfVxcbiAgICBjYXRjaCAoZSkge1xcbiAgICAgICAgaWYgKHJ1bk9wdGlvbnNIYW5kbGUgIT09IDApIHtcXG4gICAgICAgICAgICB3YXNtLl9PcnRSZWxlYXNlUnVuT3B0aW9ucyhydW5PcHRpb25zSGFuZGxlKTtcXG4gICAgICAgIH1cXG4gICAgICAgIGFsbG9jcy5mb3JFYWNoKHdhc20uX2ZyZWUpO1xcbiAgICAgICAgdGhyb3cgZTtcXG4gICAgfVxcbn07XFxuZXhwb3J0cy5zZXRSdW5PcHRpb25zID0gc2V0UnVuT3B0aW9ucztcXG5cXG5cXG4vKioqLyB9KSxcXG5cXG4vKioqLyBcXFwiLi9saWIvd2FzbS9zZXNzaW9uLW9wdGlvbnMudHNcXFwiOlxcbi8qISoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiohKlxcXFxcXG4gICEqKiogLi9saWIvd2FzbS9zZXNzaW9uLW9wdGlvbnMudHMgKioqIVxcbiAgXFxcXCoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXFxuLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4ge1xcblxcblxcXCJ1c2Ugc3RyaWN0XFxcIjtcXG5cXG4vLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXFxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFxcXCJfX2VzTW9kdWxlXFxcIiwgKHsgdmFsdWU6IHRydWUgfSkpO1xcbmV4cG9ydHMuc2V0U2Vzc2lvbk9wdGlvbnMgPSB2b2lkIDA7XFxuY29uc3Qgb3B0aW9uc191dGlsc18xID0gX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgLi9vcHRpb25zLXV0aWxzICovIFxcXCIuL2xpYi93YXNtL29wdGlvbnMtdXRpbHMudHNcXFwiKTtcXG5jb25zdCBzdHJpbmdfdXRpbHNfMSA9IF9fd2VicGFja19yZXF1aXJlX18oLyohIC4vc3RyaW5nLXV0aWxzICovIFxcXCIuL2xpYi93YXNtL3N0cmluZy11dGlscy50c1xcXCIpO1xcbmNvbnN0IHdhc21fZmFjdG9yeV8xID0gX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgLi93YXNtLWZhY3RvcnkgKi8gXFxcIi4vbGliL3dhc20vd2FzbS1mYWN0b3J5LnRzXFxcIik7XFxuY29uc3QgZ2V0R3JhcGhPcHRpbXphdGlvbkxldmVsID0gKGdyYXBoT3B0aW1pemF0aW9uTGV2ZWwpID0+IHtcXG4gICAgc3dpdGNoIChncmFwaE9wdGltaXphdGlvbkxldmVsKSB7XFxuICAgICAgICBjYXNlICdkaXNhYmxlZCc6XFxuICAgICAgICAgICAgcmV0dXJuIDA7XFxuICAgICAgICBjYXNlICdiYXNpYyc6XFxuICAgICAgICAgICAgcmV0dXJuIDE7XFxuICAgICAgICBjYXNlICdleHRlbmRlZCc6XFxuICAgICAgICAgICAgcmV0dXJuIDI7XFxuICAgICAgICBjYXNlICdhbGwnOlxcbiAgICAgICAgICAgIHJldHVybiA5OTtcXG4gICAgICAgIGRlZmF1bHQ6XFxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBncmFwaCBvcHRpbWl6YXRpb24gbGV2ZWw6ICR7Z3JhcGhPcHRpbWl6YXRpb25MZXZlbH1gKTtcXG4gICAgfVxcbn07XFxuY29uc3QgZ2V0RXhlY3V0aW9uTW9kZSA9IChleGVjdXRpb25Nb2RlKSA9PiB7XFxuICAgIHN3aXRjaCAoZXhlY3V0aW9uTW9kZSkge1xcbiAgICAgICAgY2FzZSAnc2VxdWVudGlhbCc6XFxuICAgICAgICAgICAgcmV0dXJuIDA7XFxuICAgICAgICBjYXNlICdwYXJhbGxlbCc6XFxuICAgICAgICAgICAgcmV0dXJuIDE7XFxuICAgICAgICBkZWZhdWx0OlxcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZXhlY3V0aW9uIG1vZGU6ICR7ZXhlY3V0aW9uTW9kZX1gKTtcXG4gICAgfVxcbn07XFxuY29uc3QgYXBwZW5kRGVmYXVsdE9wdGlvbnMgPSAob3B0aW9ucykgPT4ge1xcbiAgICBpZiAoIW9wdGlvbnMuZXh0cmEpIHtcXG4gICAgICAgIG9wdGlvbnMuZXh0cmEgPSB7fTtcXG4gICAgfVxcbiAgICBpZiAoIW9wdGlvbnMuZXh0cmEuc2Vzc2lvbikge1xcbiAgICAgICAgb3B0aW9ucy5leHRyYS5zZXNzaW9uID0ge307XFxuICAgIH1cXG4gICAgY29uc3Qgc2Vzc2lvbiA9IG9wdGlvbnMuZXh0cmEuc2Vzc2lvbjtcXG4gICAgaWYgKCFzZXNzaW9uLnVzZV9vcnRfbW9kZWxfYnl0ZXNfZGlyZWN0bHkpIHtcXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBjYW1lbGNhc2VcXG4gICAgICAgIHNlc3Npb24udXNlX29ydF9tb2RlbF9ieXRlc19kaXJlY3RseSA9ICcxJztcXG4gICAgfVxcbiAgICAvLyBpZiB1c2luZyBKU0VQIHdpdGggV2ViR1BVLCBhbHdheXMgZGlzYWJsZSBtZW1vcnkgcGF0dGVyblxcbiAgICBpZiAob3B0aW9ucy5leGVjdXRpb25Qcm92aWRlcnMgJiZcXG4gICAgICAgIG9wdGlvbnMuZXhlY3V0aW9uUHJvdmlkZXJzLnNvbWUoZXAgPT4gKHR5cGVvZiBlcCA9PT0gJ3N0cmluZycgPyBlcCA6IGVwLm5hbWUpID09PSAnd2ViZ3B1JykpIHtcXG4gICAgICAgIG9wdGlvbnMuZW5hYmxlTWVtUGF0dGVybiA9IGZhbHNlO1xcbiAgICB9XFxufTtcXG5jb25zdCBzZXRFeGVjdXRpb25Qcm92aWRlcnMgPSAoc2Vzc2lvbk9wdGlvbnNIYW5kbGUsIGV4ZWN1dGlvblByb3ZpZGVycywgYWxsb2NzKSA9PiB7XFxuICAgIGZvciAoY29uc3QgZXAgb2YgZXhlY3V0aW9uUHJvdmlkZXJzKSB7XFxuICAgICAgICBsZXQgZXBOYW1lID0gdHlwZW9mIGVwID09PSAnc3RyaW5nJyA/IGVwIDogZXAubmFtZTtcXG4gICAgICAgIC8vIGNoZWNrIEVQIG5hbWVcXG4gICAgICAgIHN3aXRjaCAoZXBOYW1lKSB7XFxuICAgICAgICAgICAgY2FzZSAneG5ucGFjayc6XFxuICAgICAgICAgICAgICAgIGVwTmFtZSA9ICdYTk5QQUNLJztcXG4gICAgICAgICAgICAgICAgYnJlYWs7XFxuICAgICAgICAgICAgY2FzZSAnd2ViZ3B1JzpcXG4gICAgICAgICAgICAgICAgZXBOYW1lID0gJ0pTJztcXG4gICAgICAgICAgICAgICAgYnJlYWs7XFxuICAgICAgICAgICAgY2FzZSAnd2FzbSc6XFxuICAgICAgICAgICAgY2FzZSAnY3B1JzpcXG4gICAgICAgICAgICAgICAgY29udGludWU7XFxuICAgICAgICAgICAgZGVmYXVsdDpcXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBub3Qgc3VwcG9ydGVkIEVQOiAke2VwTmFtZX1gKTtcXG4gICAgICAgIH1cXG4gICAgICAgIGNvbnN0IGVwTmFtZURhdGFPZmZzZXQgPSAoMCwgc3RyaW5nX3V0aWxzXzEuYWxsb2NXYXNtU3RyaW5nKShlcE5hbWUsIGFsbG9jcyk7XFxuICAgICAgICBpZiAoKDAsIHdhc21fZmFjdG9yeV8xLmdldEluc3RhbmNlKSgpLl9PcnRBcHBlbmRFeGVjdXRpb25Qcm92aWRlcihzZXNzaW9uT3B0aW9uc0hhbmRsZSwgZXBOYW1lRGF0YU9mZnNldCkgIT09IDApIHtcXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IGFwcGVuZCBleGVjdXRpb24gcHJvdmlkZXI6ICR7ZXBOYW1lfWApO1xcbiAgICAgICAgfVxcbiAgICB9XFxufTtcXG5jb25zdCBzZXRTZXNzaW9uT3B0aW9ucyA9IChvcHRpb25zKSA9PiB7XFxuICAgIHZhciBfYSwgX2IsIF9jLCBfZDtcXG4gICAgY29uc3Qgd2FzbSA9ICgwLCB3YXNtX2ZhY3RvcnlfMS5nZXRJbnN0YW5jZSkoKTtcXG4gICAgbGV0IHNlc3Npb25PcHRpb25zSGFuZGxlID0gMDtcXG4gICAgY29uc3QgYWxsb2NzID0gW107XFxuICAgIGNvbnN0IHNlc3Npb25PcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcXG4gICAgYXBwZW5kRGVmYXVsdE9wdGlvbnMoc2Vzc2lvbk9wdGlvbnMpO1xcbiAgICB0cnkge1xcbiAgICAgICAgY29uc3QgZ3JhcGhPcHRpbWl6YXRpb25MZXZlbCA9IGdldEdyYXBoT3B0aW16YXRpb25MZXZlbCgoX2EgPSBzZXNzaW9uT3B0aW9ucy5ncmFwaE9wdGltaXphdGlvbkxldmVsKSAhPT0gbnVsbCAmJiBfYSAhPT0gdm9pZCAwID8gX2EgOiAnYWxsJyk7XFxuICAgICAgICBjb25zdCBleGVjdXRpb25Nb2RlID0gZ2V0RXhlY3V0aW9uTW9kZSgoX2IgPSBzZXNzaW9uT3B0aW9ucy5leGVjdXRpb25Nb2RlKSAhPT0gbnVsbCAmJiBfYiAhPT0gdm9pZCAwID8gX2IgOiAnc2VxdWVudGlhbCcpO1xcbiAgICAgICAgY29uc3QgbG9nSWREYXRhT2Zmc2V0ID0gdHlwZW9mIHNlc3Npb25PcHRpb25zLmxvZ0lkID09PSAnc3RyaW5nJyA/ICgwLCBzdHJpbmdfdXRpbHNfMS5hbGxvY1dhc21TdHJpbmcpKHNlc3Npb25PcHRpb25zLmxvZ0lkLCBhbGxvY3MpIDogMDtcXG4gICAgICAgIGNvbnN0IGxvZ1NldmVyaXR5TGV2ZWwgPSAoX2MgPSBzZXNzaW9uT3B0aW9ucy5sb2dTZXZlcml0eUxldmVsKSAhPT0gbnVsbCAmJiBfYyAhPT0gdm9pZCAwID8gX2MgOiAyOyAvLyBEZWZhdWx0IHRvIDIgLSB3YXJuaW5nXFxuICAgICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIobG9nU2V2ZXJpdHlMZXZlbCkgfHwgbG9nU2V2ZXJpdHlMZXZlbCA8IDAgfHwgbG9nU2V2ZXJpdHlMZXZlbCA+IDQpIHtcXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGxvZyBzZXJ2ZXJpdHkgbGV2ZWwgaXMgbm90IHZhbGlkOiAke2xvZ1NldmVyaXR5TGV2ZWx9YCk7XFxuICAgICAgICB9XFxuICAgICAgICBjb25zdCBsb2dWZXJib3NpdHlMZXZlbCA9IChfZCA9IHNlc3Npb25PcHRpb25zLmxvZ1ZlcmJvc2l0eUxldmVsKSAhPT0gbnVsbCAmJiBfZCAhPT0gdm9pZCAwID8gX2QgOiAwOyAvLyBEZWZhdWx0IHRvIDAgLSB2ZXJib3NlXFxuICAgICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIobG9nVmVyYm9zaXR5TGV2ZWwpIHx8IGxvZ1ZlcmJvc2l0eUxldmVsIDwgMCB8fCBsb2dWZXJib3NpdHlMZXZlbCA+IDQpIHtcXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGxvZyB2ZXJib3NpdHkgbGV2ZWwgaXMgbm90IHZhbGlkOiAke2xvZ1ZlcmJvc2l0eUxldmVsfWApO1xcbiAgICAgICAgfVxcbiAgICAgICAgY29uc3Qgb3B0aW1pemVkTW9kZWxGaWxlUGF0aE9mZnNldCA9IHR5cGVvZiBzZXNzaW9uT3B0aW9ucy5vcHRpbWl6ZWRNb2RlbEZpbGVQYXRoID09PSAnc3RyaW5nJyA/XFxuICAgICAgICAgICAgKDAsIHN0cmluZ191dGlsc18xLmFsbG9jV2FzbVN0cmluZykoc2Vzc2lvbk9wdGlvbnMub3B0aW1pemVkTW9kZWxGaWxlUGF0aCwgYWxsb2NzKSA6XFxuICAgICAgICAgICAgMDtcXG4gICAgICAgIHNlc3Npb25PcHRpb25zSGFuZGxlID0gd2FzbS5fT3J0Q3JlYXRlU2Vzc2lvbk9wdGlvbnMoZ3JhcGhPcHRpbWl6YXRpb25MZXZlbCwgISFzZXNzaW9uT3B0aW9ucy5lbmFibGVDcHVNZW1BcmVuYSwgISFzZXNzaW9uT3B0aW9ucy5lbmFibGVNZW1QYXR0ZXJuLCBleGVjdXRpb25Nb2RlLCAhIXNlc3Npb25PcHRpb25zLmVuYWJsZVByb2ZpbGluZywgMCwgbG9nSWREYXRhT2Zmc2V0LCBsb2dTZXZlcml0eUxldmVsLCBsb2dWZXJib3NpdHlMZXZlbCwgb3B0aW1pemVkTW9kZWxGaWxlUGF0aE9mZnNldCk7XFxuICAgICAgICBpZiAoc2Vzc2lvbk9wdGlvbnNIYW5kbGUgPT09IDApIHtcXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcXFwndCBjcmVhdGUgc2Vzc2lvbiBvcHRpb25zJyk7XFxuICAgICAgICB9XFxuICAgICAgICBpZiAoc2Vzc2lvbk9wdGlvbnMuZXhlY3V0aW9uUHJvdmlkZXJzKSB7XFxuICAgICAgICAgICAgc2V0RXhlY3V0aW9uUHJvdmlkZXJzKHNlc3Npb25PcHRpb25zSGFuZGxlLCBzZXNzaW9uT3B0aW9ucy5leGVjdXRpb25Qcm92aWRlcnMsIGFsbG9jcyk7XFxuICAgICAgICB9XFxuICAgICAgICBpZiAoc2Vzc2lvbk9wdGlvbnMuZXh0cmEgIT09IHVuZGVmaW5lZCkge1xcbiAgICAgICAgICAgICgwLCBvcHRpb25zX3V0aWxzXzEuaXRlcmF0ZUV4dHJhT3B0aW9ucykoc2Vzc2lvbk9wdGlvbnMuZXh0cmEsICcnLCBuZXcgV2Vha1NldCgpLCAoa2V5LCB2YWx1ZSkgPT4ge1xcbiAgICAgICAgICAgICAgICBjb25zdCBrZXlEYXRhT2Zmc2V0ID0gKDAsIHN0cmluZ191dGlsc18xLmFsbG9jV2FzbVN0cmluZykoa2V5LCBhbGxvY3MpO1xcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZURhdGFPZmZzZXQgPSAoMCwgc3RyaW5nX3V0aWxzXzEuYWxsb2NXYXNtU3RyaW5nKSh2YWx1ZSwgYWxsb2NzKTtcXG4gICAgICAgICAgICAgICAgaWYgKHdhc20uX09ydEFkZFNlc3Npb25Db25maWdFbnRyeShzZXNzaW9uT3B0aW9uc0hhbmRsZSwga2V5RGF0YU9mZnNldCwgdmFsdWVEYXRhT2Zmc2V0KSAhPT0gMCkge1xcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW4ndCBzZXQgYSBzZXNzaW9uIGNvbmZpZyBlbnRyeTogJHtrZXl9IC0gJHt2YWx1ZX1gKTtcXG4gICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIH0pO1xcbiAgICAgICAgfVxcbiAgICAgICAgcmV0dXJuIFtzZXNzaW9uT3B0aW9uc0hhbmRsZSwgYWxsb2NzXTtcXG4gICAgfVxcbiAgICBjYXRjaCAoZSkge1xcbiAgICAgICAgaWYgKHNlc3Npb25PcHRpb25zSGFuZGxlICE9PSAwKSB7XFxuICAgICAgICAgICAgd2FzbS5fT3J0UmVsZWFzZVNlc3Npb25PcHRpb25zKHNlc3Npb25PcHRpb25zSGFuZGxlKTtcXG4gICAgICAgIH1cXG4gICAgICAgIGFsbG9jcy5mb3JFYWNoKHdhc20uX2ZyZWUpO1xcbiAgICAgICAgdGhyb3cgZTtcXG4gICAgfVxcbn07XFxuZXhwb3J0cy5zZXRTZXNzaW9uT3B0aW9ucyA9IHNldFNlc3Npb25PcHRpb25zO1xcblxcblxcbi8qKiovIH0pLFxcblxcbi8qKiovIFxcXCIuL2xpYi93YXNtL3N0cmluZy11dGlscy50c1xcXCI6XFxuLyohKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiAuL2xpYi93YXNtL3N0cmluZy11dGlscy50cyAqKiohXFxuICBcXFxcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cXG4vKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7XFxuXFxuXFxcInVzZSBzdHJpY3RcXFwiO1xcblxcbi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxcbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXFxcIl9fZXNNb2R1bGVcXFwiLCAoeyB2YWx1ZTogdHJ1ZSB9KSk7XFxuZXhwb3J0cy5hbGxvY1dhc21TdHJpbmcgPSB2b2lkIDA7XFxuY29uc3Qgd2FzbV9mYWN0b3J5XzEgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL3dhc20tZmFjdG9yeSAqLyBcXFwiLi9saWIvd2FzbS93YXNtLWZhY3RvcnkudHNcXFwiKTtcXG5jb25zdCBhbGxvY1dhc21TdHJpbmcgPSAoZGF0YSwgYWxsb2NzKSA9PiB7XFxuICAgIGNvbnN0IHdhc20gPSAoMCwgd2FzbV9mYWN0b3J5XzEuZ2V0SW5zdGFuY2UpKCk7XFxuICAgIGNvbnN0IGRhdGFMZW5ndGggPSB3YXNtLmxlbmd0aEJ5dGVzVVRGOChkYXRhKSArIDE7XFxuICAgIGNvbnN0IGRhdGFPZmZzZXQgPSB3YXNtLl9tYWxsb2MoZGF0YUxlbmd0aCk7XFxuICAgIHdhc20uc3RyaW5nVG9VVEY4KGRhdGEsIGRhdGFPZmZzZXQsIGRhdGFMZW5ndGgpO1xcbiAgICBhbGxvY3MucHVzaChkYXRhT2Zmc2V0KTtcXG4gICAgcmV0dXJuIGRhdGFPZmZzZXQ7XFxufTtcXG5leHBvcnRzLmFsbG9jV2FzbVN0cmluZyA9IGFsbG9jV2FzbVN0cmluZztcXG5cXG5cXG4vKioqLyB9KSxcXG5cXG4vKioqLyBcXFwiLi9saWIvd2FzbS93YXNtLWNvbW1vbi50c1xcXCI6XFxuLyohKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqISpcXFxcXFxuICAhKioqIC4vbGliL3dhc20vd2FzbS1jb21tb24udHMgKioqIVxcbiAgXFxcXCoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cXG4vKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzKSA9PiB7XFxuXFxuXFxcInVzZSBzdHJpY3RcXFwiO1xcblxcbi8vIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxcbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZS5cXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXFxcIl9fZXNNb2R1bGVcXFwiLCAoeyB2YWx1ZTogdHJ1ZSB9KSk7XFxuZXhwb3J0cy5sb2dMZXZlbFN0cmluZ1RvRW51bSA9IGV4cG9ydHMudGVuc29yVHlwZVRvVHlwZWRBcnJheUNvbnN0cnVjdG9yID0gZXhwb3J0cy5nZXRUZW5zb3JFbGVtZW50U2l6ZSA9IGV4cG9ydHMudGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcgPSBleHBvcnRzLnRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtID0gdm9pZCAwO1xcbi8qKlxcbiAqIE1hcCBzdHJpbmcgdGVuc29yIGRhdGEgdG8gZW51bSB2YWx1ZVxcbiAqL1xcbmNvbnN0IHRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtID0gKHR5cGUpID0+IHtcXG4gICAgc3dpdGNoICh0eXBlKSB7XFxuICAgICAgICBjYXNlICdpbnQ4JzpcXG4gICAgICAgICAgICByZXR1cm4gMyAvKiBEYXRhVHlwZS5pbnQ4ICovO1xcbiAgICAgICAgY2FzZSAndWludDgnOlxcbiAgICAgICAgICAgIHJldHVybiAyIC8qIERhdGFUeXBlLnVpbnQ4ICovO1xcbiAgICAgICAgY2FzZSAnYm9vbCc6XFxuICAgICAgICAgICAgcmV0dXJuIDkgLyogRGF0YVR5cGUuYm9vbCAqLztcXG4gICAgICAgIGNhc2UgJ2ludDE2JzpcXG4gICAgICAgICAgICByZXR1cm4gNSAvKiBEYXRhVHlwZS5pbnQxNiAqLztcXG4gICAgICAgIGNhc2UgJ3VpbnQxNic6XFxuICAgICAgICAgICAgcmV0dXJuIDQgLyogRGF0YVR5cGUudWludDE2ICovO1xcbiAgICAgICAgY2FzZSAnaW50MzInOlxcbiAgICAgICAgICAgIHJldHVybiA2IC8qIERhdGFUeXBlLmludDMyICovO1xcbiAgICAgICAgY2FzZSAndWludDMyJzpcXG4gICAgICAgICAgICByZXR1cm4gMTIgLyogRGF0YVR5cGUudWludDMyICovO1xcbiAgICAgICAgY2FzZSAnZmxvYXQzMic6XFxuICAgICAgICAgICAgcmV0dXJuIDEgLyogRGF0YVR5cGUuZmxvYXQgKi87XFxuICAgICAgICBjYXNlICdmbG9hdDY0JzpcXG4gICAgICAgICAgICByZXR1cm4gMTEgLyogRGF0YVR5cGUuZG91YmxlICovO1xcbiAgICAgICAgY2FzZSAnc3RyaW5nJzpcXG4gICAgICAgICAgICByZXR1cm4gOCAvKiBEYXRhVHlwZS5zdHJpbmcgKi87XFxuICAgICAgICBjYXNlICdpbnQ2NCc6XFxuICAgICAgICAgICAgcmV0dXJuIDcgLyogRGF0YVR5cGUuaW50NjQgKi87XFxuICAgICAgICBjYXNlICd1aW50NjQnOlxcbiAgICAgICAgICAgIHJldHVybiAxMyAvKiBEYXRhVHlwZS51aW50NjQgKi87XFxuICAgICAgICBkZWZhdWx0OlxcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgZGF0YSB0eXBlOiAke3R5cGV9YCk7XFxuICAgIH1cXG59O1xcbmV4cG9ydHMudGVuc29yRGF0YVR5cGVTdHJpbmdUb0VudW0gPSB0ZW5zb3JEYXRhVHlwZVN0cmluZ1RvRW51bTtcXG4vKipcXG4gKiBNYXAgZW51bSB2YWx1ZSB0byBzdHJpbmcgdGVuc29yIGRhdGFcXG4gKi9cXG5jb25zdCB0ZW5zb3JEYXRhVHlwZUVudW1Ub1N0cmluZyA9ICh0eXBlUHJvdG8pID0+IHtcXG4gICAgc3dpdGNoICh0eXBlUHJvdG8pIHtcXG4gICAgICAgIGNhc2UgMyAvKiBEYXRhVHlwZS5pbnQ4ICovOlxcbiAgICAgICAgICAgIHJldHVybiAnaW50OCc7XFxuICAgICAgICBjYXNlIDIgLyogRGF0YVR5cGUudWludDggKi86XFxuICAgICAgICAgICAgcmV0dXJuICd1aW50OCc7XFxuICAgICAgICBjYXNlIDkgLyogRGF0YVR5cGUuYm9vbCAqLzpcXG4gICAgICAgICAgICByZXR1cm4gJ2Jvb2wnO1xcbiAgICAgICAgY2FzZSA1IC8qIERhdGFUeXBlLmludDE2ICovOlxcbiAgICAgICAgICAgIHJldHVybiAnaW50MTYnO1xcbiAgICAgICAgY2FzZSA0IC8qIERhdGFUeXBlLnVpbnQxNiAqLzpcXG4gICAgICAgICAgICByZXR1cm4gJ3VpbnQxNic7XFxuICAgICAgICBjYXNlIDYgLyogRGF0YVR5cGUuaW50MzIgKi86XFxuICAgICAgICAgICAgcmV0dXJuICdpbnQzMic7XFxuICAgICAgICBjYXNlIDEyIC8qIERhdGFUeXBlLnVpbnQzMiAqLzpcXG4gICAgICAgICAgICByZXR1cm4gJ3VpbnQzMic7XFxuICAgICAgICBjYXNlIDEgLyogRGF0YVR5cGUuZmxvYXQgKi86XFxuICAgICAgICAgICAgcmV0dXJuICdmbG9hdDMyJztcXG4gICAgICAgIGNhc2UgMTEgLyogRGF0YVR5cGUuZG91YmxlICovOlxcbiAgICAgICAgICAgIHJldHVybiAnZmxvYXQ2NCc7XFxuICAgICAgICBjYXNlIDggLyogRGF0YVR5cGUuc3RyaW5nICovOlxcbiAgICAgICAgICAgIHJldHVybiAnc3RyaW5nJztcXG4gICAgICAgIGNhc2UgNyAvKiBEYXRhVHlwZS5pbnQ2NCAqLzpcXG4gICAgICAgICAgICByZXR1cm4gJ2ludDY0JztcXG4gICAgICAgIGNhc2UgMTMgLyogRGF0YVR5cGUudWludDY0ICovOlxcbiAgICAgICAgICAgIHJldHVybiAndWludDY0JztcXG4gICAgICAgIGRlZmF1bHQ6XFxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCBkYXRhIHR5cGU6ICR7dHlwZVByb3RvfWApO1xcbiAgICB9XFxufTtcXG5leHBvcnRzLnRlbnNvckRhdGFUeXBlRW51bVRvU3RyaW5nID0gdGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmc7XFxuLyoqXFxuICogZ2V0IHRlbnNvciBlbGVtZW50IHNpemUgaW4gYnl0ZXMgYnkgdGhlIGdpdmVuIGRhdGEgdHlwZVxcbiAqIEByZXR1cm5zIHNpemUgaW4gaW50ZWdlciBvciB1bmRlZmluZWQgaWYgdGhlIGRhdGEgdHlwZSBpcyBub3Qgc3VwcG9ydGVkXFxuICovXFxuY29uc3QgZ2V0VGVuc29yRWxlbWVudFNpemUgPSAoZGF0ZVR5cGUpID0+IFt1bmRlZmluZWQsIDQsIDEsIDEsIDIsIDIsIDQsIDgsIHVuZGVmaW5lZCwgMSwgMiwgOCwgNCwgOCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZF1bZGF0ZVR5cGVdO1xcbmV4cG9ydHMuZ2V0VGVuc29yRWxlbWVudFNpemUgPSBnZXRUZW5zb3JFbGVtZW50U2l6ZTtcXG4vKipcXG4gKiBnZXQgdHlwZWQgYXJyYXkgY29uc3RydWN0b3IgYnkgdGhlIGdpdmVuIHRlbnNvciB0eXBlXFxuICovXFxuY29uc3QgdGVuc29yVHlwZVRvVHlwZWRBcnJheUNvbnN0cnVjdG9yID0gKHR5cGUpID0+IHtcXG4gICAgc3dpdGNoICh0eXBlKSB7XFxuICAgICAgICBjYXNlICdmbG9hdDMyJzpcXG4gICAgICAgICAgICByZXR1cm4gRmxvYXQzMkFycmF5O1xcbiAgICAgICAgY2FzZSAndWludDgnOlxcbiAgICAgICAgICAgIHJldHVybiBVaW50OEFycmF5O1xcbiAgICAgICAgY2FzZSAnaW50OCc6XFxuICAgICAgICAgICAgcmV0dXJuIEludDhBcnJheTtcXG4gICAgICAgIGNhc2UgJ3VpbnQxNic6XFxuICAgICAgICAgICAgcmV0dXJuIFVpbnQxNkFycmF5O1xcbiAgICAgICAgY2FzZSAnaW50MTYnOlxcbiAgICAgICAgICAgIHJldHVybiBJbnQxNkFycmF5O1xcbiAgICAgICAgY2FzZSAnaW50MzInOlxcbiAgICAgICAgICAgIHJldHVybiBJbnQzMkFycmF5O1xcbiAgICAgICAgY2FzZSAnYm9vbCc6XFxuICAgICAgICAgICAgcmV0dXJuIFVpbnQ4QXJyYXk7XFxuICAgICAgICBjYXNlICdmbG9hdDY0JzpcXG4gICAgICAgICAgICByZXR1cm4gRmxvYXQ2NEFycmF5O1xcbiAgICAgICAgY2FzZSAndWludDMyJzpcXG4gICAgICAgICAgICByZXR1cm4gVWludDMyQXJyYXk7XFxuICAgICAgICBjYXNlICdpbnQ2NCc6XFxuICAgICAgICAgICAgcmV0dXJuIEJpZ0ludDY0QXJyYXk7XFxuICAgICAgICBjYXNlICd1aW50NjQnOlxcbiAgICAgICAgICAgIHJldHVybiBCaWdVaW50NjRBcnJheTtcXG4gICAgICAgIGRlZmF1bHQ6XFxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1bnN1cHBvcnRlZCB0eXBlOiAke3R5cGV9YCk7XFxuICAgIH1cXG59O1xcbmV4cG9ydHMudGVuc29yVHlwZVRvVHlwZWRBcnJheUNvbnN0cnVjdG9yID0gdGVuc29yVHlwZVRvVHlwZWRBcnJheUNvbnN0cnVjdG9yO1xcbi8qKlxcbiAqIE1hcCBzdHJpbmcgbG9nIGxldmVsIHRvIGludGVnZXIgdmFsdWVcXG4gKi9cXG5jb25zdCBsb2dMZXZlbFN0cmluZ1RvRW51bSA9IChsb2dMZXZlbCkgPT4ge1xcbiAgICBzd2l0Y2ggKGxvZ0xldmVsKSB7XFxuICAgICAgICBjYXNlICd2ZXJib3NlJzpcXG4gICAgICAgICAgICByZXR1cm4gMDtcXG4gICAgICAgIGNhc2UgJ2luZm8nOlxcbiAgICAgICAgICAgIHJldHVybiAxO1xcbiAgICAgICAgY2FzZSAnd2FybmluZyc6XFxuICAgICAgICAgICAgcmV0dXJuIDI7XFxuICAgICAgICBjYXNlICdlcnJvcic6XFxuICAgICAgICAgICAgcmV0dXJuIDM7XFxuICAgICAgICBjYXNlICdmYXRhbCc6XFxuICAgICAgICAgICAgcmV0dXJuIDQ7XFxuICAgICAgICBkZWZhdWx0OlxcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5zdXBwb3J0ZWQgbG9nZ2luZyBsZXZlbDogJHtsb2dMZXZlbH1gKTtcXG4gICAgfVxcbn07XFxuZXhwb3J0cy5sb2dMZXZlbFN0cmluZ1RvRW51bSA9IGxvZ0xldmVsU3RyaW5nVG9FbnVtO1xcblxcblxcbi8qKiovIH0pLFxcblxcbi8qKiovIFxcXCIuL2xpYi93YXNtL3dhc20tY29yZS1pbXBsLnRzXFxcIjpcXG4vKiEqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiohKlxcXFxcXG4gICEqKiogLi9saWIvd2FzbS93YXNtLWNvcmUtaW1wbC50cyAqKiohXFxuICBcXFxcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xcbi8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHtcXG5cXG5cXFwidXNlIHN0cmljdFxcXCI7XFxuXFxuLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXFxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcXFwiX19lc01vZHVsZVxcXCIsICh7IHZhbHVlOiB0cnVlIH0pKTtcXG5leHBvcnRzLmV4dHJhY3RUcmFuc2ZlcmFibGVCdWZmZXJzID0gZXhwb3J0cy5lbmRQcm9maWxpbmcgPSBleHBvcnRzLnJ1biA9IGV4cG9ydHMucmVsZWFzZVNlc3Npb24gPSBleHBvcnRzLmNyZWF0ZVNlc3Npb24gPSBleHBvcnRzLmNyZWF0ZVNlc3Npb25GaW5hbGl6ZSA9IGV4cG9ydHMuY3JlYXRlU2Vzc2lvbkFsbG9jYXRlID0gZXhwb3J0cy5pbml0T3J0ID0gdm9pZCAwO1xcbmNvbnN0IHJ1bl9vcHRpb25zXzEgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL3J1bi1vcHRpb25zICovIFxcXCIuL2xpYi93YXNtL3J1bi1vcHRpb25zLnRzXFxcIik7XFxuY29uc3Qgc2Vzc2lvbl9vcHRpb25zXzEgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL3Nlc3Npb24tb3B0aW9ucyAqLyBcXFwiLi9saWIvd2FzbS9zZXNzaW9uLW9wdGlvbnMudHNcXFwiKTtcXG5jb25zdCBzdHJpbmdfdXRpbHNfMSA9IF9fd2VicGFja19yZXF1aXJlX18oLyohIC4vc3RyaW5nLXV0aWxzICovIFxcXCIuL2xpYi93YXNtL3N0cmluZy11dGlscy50c1xcXCIpO1xcbmNvbnN0IHdhc21fY29tbW9uXzEgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL3dhc20tY29tbW9uICovIFxcXCIuL2xpYi93YXNtL3dhc20tY29tbW9uLnRzXFxcIik7XFxuY29uc3Qgd2FzbV9mYWN0b3J5XzEgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL3dhc20tZmFjdG9yeSAqLyBcXFwiLi9saWIvd2FzbS93YXNtLWZhY3RvcnkudHNcXFwiKTtcXG4vKipcXG4gKiBpbml0aWFsaXplIE9SVCBlbnZpcm9ubWVudC5cXG4gKiBAcGFyYW0gbnVtVGhyZWFkcyBTZXRHbG9iYWxJbnRyYU9wTnVtVGhyZWFkcyhudW1UaHJlYWRzKVxcbiAqIEBwYXJhbSBsb2dnaW5nTGV2ZWwgQ3JlYXRlRW52KHN0YXRpY19jYXN0PE9ydExvZ2dpbmdMZXZlbD4obG9nZ2luZ19sZXZlbCkpXFxuICovXFxuY29uc3QgaW5pdE9ydCA9IChudW1UaHJlYWRzLCBsb2dnaW5nTGV2ZWwpID0+IHtcXG4gICAgY29uc3QgZXJyb3JDb2RlID0gKDAsIHdhc21fZmFjdG9yeV8xLmdldEluc3RhbmNlKSgpLl9PcnRJbml0KG51bVRocmVhZHMsIGxvZ2dpbmdMZXZlbCk7XFxuICAgIGlmIChlcnJvckNvZGUgIT09IDApIHtcXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQ2FuJ3QgaW5pdGlhbGl6ZSBvbm54cnVudGltZS4gZXJyb3IgY29kZSA9ICR7ZXJyb3JDb2RlfWApO1xcbiAgICB9XFxufTtcXG5leHBvcnRzLmluaXRPcnQgPSBpbml0T3J0O1xcbmNvbnN0IGFjdGl2ZVNlc3Npb25zID0gbmV3IE1hcCgpO1xcbi8qKlxcbiAqIGNyZWF0ZSBhbiBpbnN0YW5jZSBvZiBJbmZlcmVuY2VTZXNzaW9uLlxcbiAqIEByZXR1cm5zIHRoZSBtZXRhZGF0YSBvZiBJbmZlcmVuY2VTZXNzaW9uLiAwLXZhbHVlIGhhbmRsZSBmb3IgZmFpbHVyZS5cXG4gKi9cXG5jb25zdCBjcmVhdGVTZXNzaW9uQWxsb2NhdGUgPSAobW9kZWwpID0+IHtcXG4gICAgY29uc3Qgd2FzbSA9ICgwLCB3YXNtX2ZhY3RvcnlfMS5nZXRJbnN0YW5jZSkoKTtcXG4gICAgY29uc3QgbW9kZWxEYXRhT2Zmc2V0ID0gd2FzbS5fbWFsbG9jKG1vZGVsLmJ5dGVMZW5ndGgpO1xcbiAgICB3YXNtLkhFQVBVOC5zZXQobW9kZWwsIG1vZGVsRGF0YU9mZnNldCk7XFxuICAgIHJldHVybiBbbW9kZWxEYXRhT2Zmc2V0LCBtb2RlbC5ieXRlTGVuZ3RoXTtcXG59O1xcbmV4cG9ydHMuY3JlYXRlU2Vzc2lvbkFsbG9jYXRlID0gY3JlYXRlU2Vzc2lvbkFsbG9jYXRlO1xcbmNvbnN0IGNyZWF0ZVNlc3Npb25GaW5hbGl6ZSA9IChtb2RlbERhdGEsIG9wdGlvbnMpID0+IHtcXG4gICAgY29uc3Qgd2FzbSA9ICgwLCB3YXNtX2ZhY3RvcnlfMS5nZXRJbnN0YW5jZSkoKTtcXG4gICAgbGV0IHNlc3Npb25IYW5kbGUgPSAwO1xcbiAgICBsZXQgc2Vzc2lvbk9wdGlvbnNIYW5kbGUgPSAwO1xcbiAgICBsZXQgYWxsb2NzID0gW107XFxuICAgIHRyeSB7XFxuICAgICAgICBbc2Vzc2lvbk9wdGlvbnNIYW5kbGUsIGFsbG9jc10gPSAoMCwgc2Vzc2lvbl9vcHRpb25zXzEuc2V0U2Vzc2lvbk9wdGlvbnMpKG9wdGlvbnMpO1xcbiAgICAgICAgc2Vzc2lvbkhhbmRsZSA9IHdhc20uX09ydENyZWF0ZVNlc3Npb24obW9kZWxEYXRhWzBdLCBtb2RlbERhdGFbMV0sIHNlc3Npb25PcHRpb25zSGFuZGxlKTtcXG4gICAgICAgIGlmIChzZXNzaW9uSGFuZGxlID09PSAwKSB7XFxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXFxcJ3QgY3JlYXRlIGEgc2Vzc2lvbicpO1xcbiAgICAgICAgfVxcbiAgICB9XFxuICAgIGZpbmFsbHkge1xcbiAgICAgICAgd2FzbS5fZnJlZShtb2RlbERhdGFbMF0pO1xcbiAgICAgICAgaWYgKHNlc3Npb25PcHRpb25zSGFuZGxlICE9PSAwKSB7XFxuICAgICAgICAgICAgd2FzbS5fT3J0UmVsZWFzZVNlc3Npb25PcHRpb25zKHNlc3Npb25PcHRpb25zSGFuZGxlKTtcXG4gICAgICAgIH1cXG4gICAgICAgIGFsbG9jcy5mb3JFYWNoKHdhc20uX2ZyZWUpO1xcbiAgICB9XFxuICAgIGNvbnN0IGlucHV0Q291bnQgPSB3YXNtLl9PcnRHZXRJbnB1dENvdW50KHNlc3Npb25IYW5kbGUpO1xcbiAgICBjb25zdCBvdXRwdXRDb3VudCA9IHdhc20uX09ydEdldE91dHB1dENvdW50KHNlc3Npb25IYW5kbGUpO1xcbiAgICBjb25zdCBpbnB1dE5hbWVzID0gW107XFxuICAgIGNvbnN0IGlucHV0TmFtZXNVVEY4RW5jb2RlZCA9IFtdO1xcbiAgICBjb25zdCBvdXRwdXROYW1lcyA9IFtdO1xcbiAgICBjb25zdCBvdXRwdXROYW1lc1VURjhFbmNvZGVkID0gW107XFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRDb3VudDsgaSsrKSB7XFxuICAgICAgICBjb25zdCBuYW1lID0gd2FzbS5fT3J0R2V0SW5wdXROYW1lKHNlc3Npb25IYW5kbGUsIGkpO1xcbiAgICAgICAgaWYgKG5hbWUgPT09IDApIHtcXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhblxcXFwndCBnZXQgYW4gaW5wdXQgbmFtZScpO1xcbiAgICAgICAgfVxcbiAgICAgICAgaW5wdXROYW1lc1VURjhFbmNvZGVkLnB1c2gobmFtZSk7XFxuICAgICAgICBpbnB1dE5hbWVzLnB1c2god2FzbS5VVEY4VG9TdHJpbmcobmFtZSkpO1xcbiAgICB9XFxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3V0cHV0Q291bnQ7IGkrKykge1xcbiAgICAgICAgY29uc3QgbmFtZSA9IHdhc20uX09ydEdldE91dHB1dE5hbWUoc2Vzc2lvbkhhbmRsZSwgaSk7XFxuICAgICAgICBpZiAobmFtZSA9PT0gMCkge1xcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuXFxcXCd0IGdldCBhbiBvdXRwdXQgbmFtZScpO1xcbiAgICAgICAgfVxcbiAgICAgICAgb3V0cHV0TmFtZXNVVEY4RW5jb2RlZC5wdXNoKG5hbWUpO1xcbiAgICAgICAgb3V0cHV0TmFtZXMucHVzaCh3YXNtLlVURjhUb1N0cmluZyhuYW1lKSk7XFxuICAgIH1cXG4gICAgYWN0aXZlU2Vzc2lvbnMuc2V0KHNlc3Npb25IYW5kbGUsIFtzZXNzaW9uSGFuZGxlLCBpbnB1dE5hbWVzVVRGOEVuY29kZWQsIG91dHB1dE5hbWVzVVRGOEVuY29kZWRdKTtcXG4gICAgcmV0dXJuIFtzZXNzaW9uSGFuZGxlLCBpbnB1dE5hbWVzLCBvdXRwdXROYW1lc107XFxufTtcXG5leHBvcnRzLmNyZWF0ZVNlc3Npb25GaW5hbGl6ZSA9IGNyZWF0ZVNlc3Npb25GaW5hbGl6ZTtcXG4vKipcXG4gKiBjcmVhdGUgYW4gaW5zdGFuY2Ugb2YgSW5mZXJlbmNlU2Vzc2lvbi5cXG4gKiBAcmV0dXJucyB0aGUgbWV0YWRhdGEgb2YgSW5mZXJlbmNlU2Vzc2lvbi4gMC12YWx1ZSBoYW5kbGUgZm9yIGZhaWx1cmUuXFxuICovXFxuY29uc3QgY3JlYXRlU2Vzc2lvbiA9IChtb2RlbCwgb3B0aW9ucykgPT4ge1xcbiAgICBjb25zdCBtb2RlbERhdGEgPSAoMCwgZXhwb3J0cy5jcmVhdGVTZXNzaW9uQWxsb2NhdGUpKG1vZGVsKTtcXG4gICAgcmV0dXJuICgwLCBleHBvcnRzLmNyZWF0ZVNlc3Npb25GaW5hbGl6ZSkobW9kZWxEYXRhLCBvcHRpb25zKTtcXG59O1xcbmV4cG9ydHMuY3JlYXRlU2Vzc2lvbiA9IGNyZWF0ZVNlc3Npb247XFxuY29uc3QgcmVsZWFzZVNlc3Npb24gPSAoc2Vzc2lvbklkKSA9PiB7XFxuICAgIGNvbnN0IHdhc20gPSAoMCwgd2FzbV9mYWN0b3J5XzEuZ2V0SW5zdGFuY2UpKCk7XFxuICAgIGNvbnN0IHNlc3Npb24gPSBhY3RpdmVTZXNzaW9ucy5nZXQoc2Vzc2lvbklkKTtcXG4gICAgaWYgKCFzZXNzaW9uKSB7XFxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgc2Vzc2lvbiBpZCcpO1xcbiAgICB9XFxuICAgIGNvbnN0IHNlc3Npb25IYW5kbGUgPSBzZXNzaW9uWzBdO1xcbiAgICBjb25zdCBpbnB1dE5hbWVzVVRGOEVuY29kZWQgPSBzZXNzaW9uWzFdO1xcbiAgICBjb25zdCBvdXRwdXROYW1lc1VURjhFbmNvZGVkID0gc2Vzc2lvblsyXTtcXG4gICAgaW5wdXROYW1lc1VURjhFbmNvZGVkLmZvckVhY2god2FzbS5fT3J0RnJlZSk7XFxuICAgIG91dHB1dE5hbWVzVVRGOEVuY29kZWQuZm9yRWFjaCh3YXNtLl9PcnRGcmVlKTtcXG4gICAgd2FzbS5fT3J0UmVsZWFzZVNlc3Npb24oc2Vzc2lvbkhhbmRsZSk7XFxuICAgIGFjdGl2ZVNlc3Npb25zLmRlbGV0ZShzZXNzaW9uSWQpO1xcbn07XFxuZXhwb3J0cy5yZWxlYXNlU2Vzc2lvbiA9IHJlbGVhc2VTZXNzaW9uO1xcbi8qKlxcbiAqIHBlcmZvcm0gaW5mZXJlbmNlIHJ1blxcbiAqL1xcbmNvbnN0IHJ1biA9IGFzeW5jIChzZXNzaW9uSWQsIGlucHV0SW5kaWNlcywgaW5wdXRzLCBvdXRwdXRJbmRpY2VzLCBvcHRpb25zKSA9PiB7XFxuICAgIGNvbnN0IHdhc20gPSAoMCwgd2FzbV9mYWN0b3J5XzEuZ2V0SW5zdGFuY2UpKCk7XFxuICAgIGNvbnN0IHNlc3Npb24gPSBhY3RpdmVTZXNzaW9ucy5nZXQoc2Vzc2lvbklkKTtcXG4gICAgaWYgKCFzZXNzaW9uKSB7XFxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgc2Vzc2lvbiBpZCcpO1xcbiAgICB9XFxuICAgIGNvbnN0IHNlc3Npb25IYW5kbGUgPSBzZXNzaW9uWzBdO1xcbiAgICBjb25zdCBpbnB1dE5hbWVzVVRGOEVuY29kZWQgPSBzZXNzaW9uWzFdO1xcbiAgICBjb25zdCBvdXRwdXROYW1lc1VURjhFbmNvZGVkID0gc2Vzc2lvblsyXTtcXG4gICAgY29uc3QgaW5wdXRDb3VudCA9IGlucHV0SW5kaWNlcy5sZW5ndGg7XFxuICAgIGNvbnN0IG91dHB1dENvdW50ID0gb3V0cHV0SW5kaWNlcy5sZW5ndGg7XFxuICAgIGxldCBydW5PcHRpb25zSGFuZGxlID0gMDtcXG4gICAgbGV0IHJ1bk9wdGlvbnNBbGxvY3MgPSBbXTtcXG4gICAgY29uc3QgaW5wdXRWYWx1ZXMgPSBbXTtcXG4gICAgY29uc3QgaW5wdXRBbGxvY3MgPSBbXTtcXG4gICAgdHJ5IHtcXG4gICAgICAgIFtydW5PcHRpb25zSGFuZGxlLCBydW5PcHRpb25zQWxsb2NzXSA9ICgwLCBydW5fb3B0aW9uc18xLnNldFJ1bk9wdGlvbnMpKG9wdGlvbnMpO1xcbiAgICAgICAgLy8gY3JlYXRlIGlucHV0IHRlbnNvcnNcXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRDb3VudDsgaSsrKSB7XFxuICAgICAgICAgICAgY29uc3QgZGF0YVR5cGUgPSBpbnB1dHNbaV1bMF07XFxuICAgICAgICAgICAgY29uc3QgZGltcyA9IGlucHV0c1tpXVsxXTtcXG4gICAgICAgICAgICBjb25zdCBkYXRhID0gaW5wdXRzW2ldWzJdO1xcbiAgICAgICAgICAgIGxldCBkYXRhT2Zmc2V0O1xcbiAgICAgICAgICAgIGxldCBkYXRhQnl0ZUxlbmd0aDtcXG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShkYXRhKSkge1xcbiAgICAgICAgICAgICAgICAvLyBzdHJpbmcgdGVuc29yXFxuICAgICAgICAgICAgICAgIGRhdGFCeXRlTGVuZ3RoID0gNCAqIGRhdGEubGVuZ3RoO1xcbiAgICAgICAgICAgICAgICBkYXRhT2Zmc2V0ID0gd2FzbS5fbWFsbG9jKGRhdGFCeXRlTGVuZ3RoKTtcXG4gICAgICAgICAgICAgICAgaW5wdXRBbGxvY3MucHVzaChkYXRhT2Zmc2V0KTtcXG4gICAgICAgICAgICAgICAgbGV0IGRhdGFJbmRleCA9IGRhdGFPZmZzZXQgLyA0O1xcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZGF0YVtpXSAhPT0gJ3N0cmluZycpIHtcXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGB0ZW5zb3IgZGF0YSBhdCBpbmRleCAke2l9IGlzIG5vdCBhIHN0cmluZ2ApO1xcbiAgICAgICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgICAgICAgICAgd2FzbS5IRUFQVTMyW2RhdGFJbmRleCsrXSA9ICgwLCBzdHJpbmdfdXRpbHNfMS5hbGxvY1dhc21TdHJpbmcpKGRhdGFbaV0sIGlucHV0QWxsb2NzKTtcXG4gICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICBlbHNlIHtcXG4gICAgICAgICAgICAgICAgZGF0YUJ5dGVMZW5ndGggPSBkYXRhLmJ5dGVMZW5ndGg7XFxuICAgICAgICAgICAgICAgIGRhdGFPZmZzZXQgPSB3YXNtLl9tYWxsb2MoZGF0YUJ5dGVMZW5ndGgpO1xcbiAgICAgICAgICAgICAgICBpbnB1dEFsbG9jcy5wdXNoKGRhdGFPZmZzZXQpO1xcbiAgICAgICAgICAgICAgICB3YXNtLkhFQVBVOC5zZXQobmV3IFVpbnQ4QXJyYXkoZGF0YS5idWZmZXIsIGRhdGEuYnl0ZU9mZnNldCwgZGF0YUJ5dGVMZW5ndGgpLCBkYXRhT2Zmc2V0KTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgY29uc3Qgc3RhY2sgPSB3YXNtLnN0YWNrU2F2ZSgpO1xcbiAgICAgICAgICAgIGNvbnN0IGRpbXNPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2MoNCAqIGRpbXMubGVuZ3RoKTtcXG4gICAgICAgICAgICB0cnkge1xcbiAgICAgICAgICAgICAgICBsZXQgZGltSW5kZXggPSBkaW1zT2Zmc2V0IC8gNDtcXG4gICAgICAgICAgICAgICAgZGltcy5mb3JFYWNoKGQgPT4gd2FzbS5IRUFQMzJbZGltSW5kZXgrK10gPSBkKTtcXG4gICAgICAgICAgICAgICAgY29uc3QgdGVuc29yID0gd2FzbS5fT3J0Q3JlYXRlVGVuc29yKCgwLCB3YXNtX2NvbW1vbl8xLnRlbnNvckRhdGFUeXBlU3RyaW5nVG9FbnVtKShkYXRhVHlwZSksIGRhdGFPZmZzZXQsIGRhdGFCeXRlTGVuZ3RoLCBkaW1zT2Zmc2V0LCBkaW1zLmxlbmd0aCk7XFxuICAgICAgICAgICAgICAgIGlmICh0ZW5zb3IgPT09IDApIHtcXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2FuXFxcXCd0IGNyZWF0ZSBhIHRlbnNvcicpO1xcbiAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgICAgIGlucHV0VmFsdWVzLnB1c2godGVuc29yKTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgZmluYWxseSB7XFxuICAgICAgICAgICAgICAgIHdhc20uc3RhY2tSZXN0b3JlKHN0YWNrKTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICB9XFxuICAgICAgICBjb25zdCBiZWZvcmVSdW5TdGFjayA9IHdhc20uc3RhY2tTYXZlKCk7XFxuICAgICAgICBjb25zdCBpbnB1dFZhbHVlc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyhpbnB1dENvdW50ICogNCk7XFxuICAgICAgICBjb25zdCBpbnB1dE5hbWVzT2Zmc2V0ID0gd2FzbS5zdGFja0FsbG9jKGlucHV0Q291bnQgKiA0KTtcXG4gICAgICAgIGNvbnN0IG91dHB1dFZhbHVlc09mZnNldCA9IHdhc20uc3RhY2tBbGxvYyhvdXRwdXRDb3VudCAqIDQpO1xcbiAgICAgICAgY29uc3Qgb3V0cHV0TmFtZXNPZmZzZXQgPSB3YXNtLnN0YWNrQWxsb2Mob3V0cHV0Q291bnQgKiA0KTtcXG4gICAgICAgIHRyeSB7XFxuICAgICAgICAgICAgbGV0IGlucHV0VmFsdWVzSW5kZXggPSBpbnB1dFZhbHVlc09mZnNldCAvIDQ7XFxuICAgICAgICAgICAgbGV0IGlucHV0TmFtZXNJbmRleCA9IGlucHV0TmFtZXNPZmZzZXQgLyA0O1xcbiAgICAgICAgICAgIGxldCBvdXRwdXRWYWx1ZXNJbmRleCA9IG91dHB1dFZhbHVlc09mZnNldCAvIDQ7XFxuICAgICAgICAgICAgbGV0IG91dHB1dE5hbWVzSW5kZXggPSBvdXRwdXROYW1lc09mZnNldCAvIDQ7XFxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dENvdW50OyBpKyspIHtcXG4gICAgICAgICAgICAgICAgd2FzbS5IRUFQVTMyW2lucHV0VmFsdWVzSW5kZXgrK10gPSBpbnB1dFZhbHVlc1tpXTtcXG4gICAgICAgICAgICAgICAgd2FzbS5IRUFQVTMyW2lucHV0TmFtZXNJbmRleCsrXSA9IGlucHV0TmFtZXNVVEY4RW5jb2RlZFtpbnB1dEluZGljZXNbaV1dO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG91dHB1dENvdW50OyBpKyspIHtcXG4gICAgICAgICAgICAgICAgd2FzbS5IRUFQVTMyW291dHB1dFZhbHVlc0luZGV4KytdID0gMDtcXG4gICAgICAgICAgICAgICAgd2FzbS5IRUFQVTMyW291dHB1dE5hbWVzSW5kZXgrK10gPSBvdXRwdXROYW1lc1VURjhFbmNvZGVkW291dHB1dEluZGljZXNbaV1dO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICAvLyBzdXBwb3J0IFJ1bk9wdGlvbnNcXG4gICAgICAgICAgICBsZXQgZXJyb3JDb2RlID0gd2FzbS5fT3J0UnVuKHNlc3Npb25IYW5kbGUsIGlucHV0TmFtZXNPZmZzZXQsIGlucHV0VmFsdWVzT2Zmc2V0LCBpbnB1dENvdW50LCBvdXRwdXROYW1lc09mZnNldCwgb3V0cHV0Q291bnQsIG91dHB1dFZhbHVlc09mZnNldCwgcnVuT3B0aW9uc0hhbmRsZSk7XFxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxcbiAgICAgICAgICAgIGNvbnN0IHJ1blByb21pc2UgPSB3YXNtLmpzZXBSdW5Qcm9taXNlO1xcbiAgICAgICAgICAgIGlmIChydW5Qcm9taXNlICYmIHR5cGVvZiBydW5Qcm9taXNlLnRoZW4gIT09ICd1bmRlZmluZWQnKSB7XFxuICAgICAgICAgICAgICAgIGVycm9yQ29kZSA9IGF3YWl0IHJ1blByb21pc2U7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIGNvbnN0IG91dHB1dCA9IFtdO1xcbiAgICAgICAgICAgIGlmIChlcnJvckNvZGUgPT09IDApIHtcXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvdXRwdXRDb3VudDsgaSsrKSB7XFxuICAgICAgICAgICAgICAgICAgICBjb25zdCB0ZW5zb3IgPSB3YXNtLkhFQVBVMzJbb3V0cHV0VmFsdWVzT2Zmc2V0IC8gNCArIGldO1xcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYmVmb3JlR2V0VGVuc29yRGF0YVN0YWNrID0gd2FzbS5zdGFja1NhdmUoKTtcXG4gICAgICAgICAgICAgICAgICAgIC8vIHN0YWNrIGFsbG9jYXRlIDQgcG9pbnRlciB2YWx1ZVxcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGVuc29yRGF0YU9mZnNldCA9IHdhc20uc3RhY2tBbGxvYyg0ICogNCk7XFxuICAgICAgICAgICAgICAgICAgICBsZXQgdHlwZSwgZGF0YU9mZnNldCA9IDA7XFxuICAgICAgICAgICAgICAgICAgICB0cnkge1xcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yQ29kZSA9IHdhc20uX09ydEdldFRlbnNvckRhdGEodGVuc29yLCB0ZW5zb3JEYXRhT2Zmc2V0LCB0ZW5zb3JEYXRhT2Zmc2V0ICsgNCwgdGVuc29yRGF0YU9mZnNldCArIDgsIHRlbnNvckRhdGFPZmZzZXQgKyAxMik7XFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yQ29kZSAhPT0gMCkge1xcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbid0IGFjY2VzcyBvdXRwdXQgdGVuc29yIGRhdGEuIGVycm9yIGNvZGUgPSAke2Vycm9yQ29kZX1gKTtcXG4gICAgICAgICAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHRlbnNvckRhdGFJbmRleCA9IHRlbnNvckRhdGFPZmZzZXQgLyA0O1xcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRhdGFUeXBlID0gd2FzbS5IRUFQVTMyW3RlbnNvckRhdGFJbmRleCsrXTtcXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhT2Zmc2V0ID0gd2FzbS5IRUFQVTMyW3RlbnNvckRhdGFJbmRleCsrXTtcXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkaW1zT2Zmc2V0ID0gd2FzbS5IRUFQVTMyW3RlbnNvckRhdGFJbmRleCsrXTtcXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkaW1zTGVuZ3RoID0gd2FzbS5IRUFQVTMyW3RlbnNvckRhdGFJbmRleCsrXTtcXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBkaW1zID0gW107XFxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBkaW1zTGVuZ3RoOyBpKyspIHtcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltcy5wdXNoKHdhc20uSEVBUFUzMltkaW1zT2Zmc2V0IC8gNCArIGldKTtcXG4gICAgICAgICAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgICAgICAgICAgICAgd2FzbS5fT3J0RnJlZShkaW1zT2Zmc2V0KTtcXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzaXplID0gZGltcy5sZW5ndGggPT09IDAgPyAxIDogZGltcy5yZWR1Y2UoKGEsIGIpID0+IGEgKiBiKTtcXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlID0gKDAsIHdhc21fY29tbW9uXzEudGVuc29yRGF0YVR5cGVFbnVtVG9TdHJpbmcpKGRhdGFUeXBlKTtcXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHtcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3RyaW5nRGF0YSA9IFtdO1xcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgZGF0YUluZGV4ID0gZGF0YU9mZnNldCAvIDQ7XFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2l6ZTsgaSsrKSB7XFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvZmZzZXQgPSB3YXNtLkhFQVBVMzJbZGF0YUluZGV4KytdO1xcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWF4Qnl0ZXNUb1JlYWQgPSBpID09PSBzaXplIC0gMSA/IHVuZGVmaW5lZCA6IHdhc20uSEVBUFUzMltkYXRhSW5kZXhdIC0gb2Zmc2V0O1xcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nRGF0YS5wdXNoKHdhc20uVVRGOFRvU3RyaW5nKG9mZnNldCwgbWF4Qnl0ZXNUb1JlYWQpKTtcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChbdHlwZSwgZGltcywgc3RyaW5nRGF0YV0pO1xcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cXG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdHlwZWRBcnJheUNvbnN0cnVjdG9yID0gKDAsIHdhc21fY29tbW9uXzEudGVuc29yVHlwZVRvVHlwZWRBcnJheUNvbnN0cnVjdG9yKSh0eXBlKTtcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGF0YSA9IG5ldyB0eXBlZEFycmF5Q29uc3RydWN0b3Ioc2l6ZSk7XFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBVaW50OEFycmF5KGRhdGEuYnVmZmVyLCBkYXRhLmJ5dGVPZmZzZXQsIGRhdGEuYnl0ZUxlbmd0aClcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5zZXQod2FzbS5IRUFQVTguc3ViYXJyYXkoZGF0YU9mZnNldCwgZGF0YU9mZnNldCArIGRhdGEuYnl0ZUxlbmd0aCkpO1xcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChbdHlwZSwgZGltcywgZGF0YV0pO1xcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cXG4gICAgICAgICAgICAgICAgICAgIH1cXG4gICAgICAgICAgICAgICAgICAgIGZpbmFsbHkge1xcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhc20uc3RhY2tSZXN0b3JlKGJlZm9yZUdldFRlbnNvckRhdGFTdGFjayk7XFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdzdHJpbmcnICYmIGRhdGFPZmZzZXQpIHtcXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd2FzbS5fZnJlZShkYXRhT2Zmc2V0KTtcXG4gICAgICAgICAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgICAgICAgICAgICAgd2FzbS5fT3J0UmVsZWFzZVRlbnNvcih0ZW5zb3IpO1xcbiAgICAgICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIGlmIChlcnJvckNvZGUgPT09IDApIHtcXG4gICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dDtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgZWxzZSB7XFxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgZmFpbGVkIHRvIGNhbGwgT3J0UnVuKCkuIGVycm9yIGNvZGUgPSAke2Vycm9yQ29kZX0uYCk7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgfVxcbiAgICAgICAgZmluYWxseSB7XFxuICAgICAgICAgICAgd2FzbS5zdGFja1Jlc3RvcmUoYmVmb3JlUnVuU3RhY2spO1xcbiAgICAgICAgfVxcbiAgICB9XFxuICAgIGZpbmFsbHkge1xcbiAgICAgICAgaW5wdXRWYWx1ZXMuZm9yRWFjaCh3YXNtLl9PcnRSZWxlYXNlVGVuc29yKTtcXG4gICAgICAgIGlucHV0QWxsb2NzLmZvckVhY2god2FzbS5fZnJlZSk7XFxuICAgICAgICB3YXNtLl9PcnRSZWxlYXNlUnVuT3B0aW9ucyhydW5PcHRpb25zSGFuZGxlKTtcXG4gICAgICAgIHJ1bk9wdGlvbnNBbGxvY3MuZm9yRWFjaCh3YXNtLl9mcmVlKTtcXG4gICAgfVxcbn07XFxuZXhwb3J0cy5ydW4gPSBydW47XFxuLyoqXFxuICogZW5kIHByb2ZpbGluZ1xcbiAqL1xcbmNvbnN0IGVuZFByb2ZpbGluZyA9IChzZXNzaW9uSWQpID0+IHtcXG4gICAgY29uc3Qgd2FzbSA9ICgwLCB3YXNtX2ZhY3RvcnlfMS5nZXRJbnN0YW5jZSkoKTtcXG4gICAgY29uc3Qgc2Vzc2lvbiA9IGFjdGl2ZVNlc3Npb25zLmdldChzZXNzaW9uSWQpO1xcbiAgICBpZiAoIXNlc3Npb24pIHtcXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBzZXNzaW9uIGlkJyk7XFxuICAgIH1cXG4gICAgY29uc3Qgc2Vzc2lvbkhhbmRsZSA9IHNlc3Npb25bMF07XFxuICAgIC8vIHByb2ZpbGUgZmlsZSBuYW1lIGlzIG5vdCB1c2VkIHlldCwgYnV0IGl0IG11c3QgYmUgZnJlZWQuXFxuICAgIGNvbnN0IHByb2ZpbGVGaWxlTmFtZSA9IHdhc20uX09ydEVuZFByb2ZpbGluZyhzZXNzaW9uSGFuZGxlKTtcXG4gICAgaWYgKHByb2ZpbGVGaWxlTmFtZSA9PT0gMCkge1xcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5cXFxcJ3QgZ2V0IGFuIHByb2ZpbGUgZmlsZSBuYW1lJyk7XFxuICAgIH1cXG4gICAgd2FzbS5fT3J0RnJlZShwcm9maWxlRmlsZU5hbWUpO1xcbn07XFxuZXhwb3J0cy5lbmRQcm9maWxpbmcgPSBlbmRQcm9maWxpbmc7XFxuY29uc3QgZXh0cmFjdFRyYW5zZmVyYWJsZUJ1ZmZlcnMgPSAodGVuc29ycykgPT4ge1xcbiAgICBjb25zdCBidWZmZXJzID0gW107XFxuICAgIGZvciAoY29uc3QgdGVuc29yIG9mIHRlbnNvcnMpIHtcXG4gICAgICAgIGNvbnN0IGRhdGEgPSB0ZW5zb3JbMl07XFxuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGF0YSkgJiYgZGF0YS5idWZmZXIpIHtcXG4gICAgICAgICAgICBidWZmZXJzLnB1c2goZGF0YS5idWZmZXIpO1xcbiAgICAgICAgfVxcbiAgICB9XFxuICAgIHJldHVybiBidWZmZXJzO1xcbn07XFxuZXhwb3J0cy5leHRyYWN0VHJhbnNmZXJhYmxlQnVmZmVycyA9IGV4dHJhY3RUcmFuc2ZlcmFibGVCdWZmZXJzO1xcblxcblxcbi8qKiovIH0pLFxcblxcbi8qKiovIFxcXCIuL2xpYi93YXNtL3dhc20tZmFjdG9yeS50c1xcXCI6XFxuLyohKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiAuL2xpYi93YXNtL3dhc20tZmFjdG9yeS50cyAqKiohXFxuICBcXFxcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cXG4vKioqLyAoZnVuY3Rpb24oX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pIHtcXG5cXG5cXFwidXNlIHN0cmljdFxcXCI7XFxudmFyIF9fZGlybmFtZSA9IFxcXCIvXFxcIjtcXG5cXG4vLyBDb3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cXG4vLyBMaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuXFxudmFyIF9fY3JlYXRlQmluZGluZyA9ICh0aGlzICYmIHRoaXMuX19jcmVhdGVCaW5kaW5nKSB8fCAoT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xcbiAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XFxuICAgIGlmICghZGVzYyB8fCAoXFxcImdldFxcXCIgaW4gZGVzYyA/ICFtLl9fZXNNb2R1bGUgOiBkZXNjLndyaXRhYmxlIHx8IGRlc2MuY29uZmlndXJhYmxlKSkge1xcbiAgICAgIGRlc2MgPSB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZnVuY3Rpb24oKSB7IHJldHVybiBtW2tdOyB9IH07XFxuICAgIH1cXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG8sIGsyLCBkZXNjKTtcXG59KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xcbiAgICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xcbiAgICBvW2syXSA9IG1ba107XFxufSkpO1xcbnZhciBfX3NldE1vZHVsZURlZmF1bHQgPSAodGhpcyAmJiB0aGlzLl9fc2V0TW9kdWxlRGVmYXVsdCkgfHwgKE9iamVjdC5jcmVhdGUgPyAoZnVuY3Rpb24obywgdikge1xcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkobywgXFxcImRlZmF1bHRcXFwiLCB7IGVudW1lcmFibGU6IHRydWUsIHZhbHVlOiB2IH0pO1xcbn0pIDogZnVuY3Rpb24obywgdikge1xcbiAgICBvW1xcXCJkZWZhdWx0XFxcIl0gPSB2O1xcbn0pO1xcbnZhciBfX2ltcG9ydFN0YXIgPSAodGhpcyAmJiB0aGlzLl9faW1wb3J0U3RhcikgfHwgZnVuY3Rpb24gKG1vZCkge1xcbiAgICBpZiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSByZXR1cm4gbW9kO1xcbiAgICB2YXIgcmVzdWx0ID0ge307XFxuICAgIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayBpbiBtb2QpIGlmIChrICE9PSBcXFwiZGVmYXVsdFxcXCIgJiYgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1vZCwgaykpIF9fY3JlYXRlQmluZGluZyhyZXN1bHQsIG1vZCwgayk7XFxuICAgIF9fc2V0TW9kdWxlRGVmYXVsdChyZXN1bHQsIG1vZCk7XFxuICAgIHJldHVybiByZXN1bHQ7XFxufTtcXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXFxcIl9fZXNNb2R1bGVcXFwiLCAoeyB2YWx1ZTogdHJ1ZSB9KSk7XFxuZXhwb3J0cy5kaXNwb3NlID0gZXhwb3J0cy5nZXRJbnN0YW5jZSA9IGV4cG9ydHMuaW5pdGlhbGl6ZVdlYkFzc2VtYmx5ID0gdm9pZCAwO1xcbmNvbnN0IHBhdGggPSBfX2ltcG9ydFN0YXIoX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgcGF0aCAqLyBcXFwiPzdhYTVcXFwiKSk7XFxuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0cyAqL1xcbmNvbnN0IG9ydFdhc21GYWN0b3J5ID0gIHRydWUgPyBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL2JpbmRpbmcvb3J0LXdhc20uanMgKi8gXFxcIi4vbGliL3dhc20vYmluZGluZy9vcnQtd2FzbS5qc1xcXCIpIDogMDtcXG5jb25zdCBvcnRXYXNtRmFjdG9yeVRocmVhZGVkID0gIHRydWUgP1xcbiAgICAoIHRydWUgPyBfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISAuL2JpbmRpbmcvb3J0LXdhc20tdGhyZWFkZWQuanMgKi8gXFxcIi4vbGliL3dhc20vYmluZGluZy9vcnQtd2FzbS10aHJlYWRlZC5qc1xcXCIpIDpcXG4gICAgICAgIDApIDpcXG4gICAgMDtcXG4vKiBlc2xpbnQtZW5hYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHMgKi9cXG5sZXQgd2FzbTtcXG5sZXQgaW5pdGlhbGl6ZWQgPSBmYWxzZTtcXG5sZXQgaW5pdGlhbGl6aW5nID0gZmFsc2U7XFxubGV0IGFib3J0ZWQgPSBmYWxzZTtcXG5jb25zdCBpc011bHRpVGhyZWFkU3VwcG9ydGVkID0gKCkgPT4ge1xcbiAgICB0cnkge1xcbiAgICAgICAgLy8gSWYgJ1NoYXJlZEFycmF5QnVmZmVyJyBpcyBub3QgYXZhaWxhYmxlLCBXZWJBc3NlbWJseSB0aHJlYWRzIHdpbGwgbm90IHdvcmsuXFxuICAgICAgICBpZiAodHlwZW9mIFNoYXJlZEFycmF5QnVmZmVyID09PSAndW5kZWZpbmVkJykge1xcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcXG4gICAgICAgIH1cXG4gICAgICAgIC8vIFRlc3QgZm9yIHRyYW5zZmVyYWJpbGl0eSBvZiBTQUJzIChmb3IgYnJvd3NlcnMuIG5lZWRlZCBmb3IgRmlyZWZveClcXG4gICAgICAgIC8vIGh0dHBzOi8vZ3JvdXBzLmdvb2dsZS5jb20vZm9ydW0vIyFtc2cvbW96aWxsYS5kZXYucGxhdGZvcm0vSUhrQlpsSEVUcEEvZHdzTU5jaFdFUUFKXFxuICAgICAgICBpZiAodHlwZW9mIE1lc3NhZ2VDaGFubmVsICE9PSAndW5kZWZpbmVkJykge1xcbiAgICAgICAgICAgIG5ldyBNZXNzYWdlQ2hhbm5lbCgpLnBvcnQxLnBvc3RNZXNzYWdlKG5ldyBTaGFyZWRBcnJheUJ1ZmZlcigxKSk7XFxuICAgICAgICB9XFxuICAgICAgICAvLyBUZXN0IGZvciBXZWJBc3NlbWJseSB0aHJlYWRzIGNhcGFiaWxpdHkgKGZvciBib3RoIGJyb3dzZXJzIGFuZCBOb2RlLmpzKVxcbiAgICAgICAgLy8gVGhpcyB0eXBlZCBhcnJheSBpcyBhIFdlYkFzc2VtYmx5IHByb2dyYW0gY29udGFpbmluZyB0aHJlYWRlZCBpbnN0cnVjdGlvbnMuXFxuICAgICAgICByZXR1cm4gV2ViQXNzZW1ibHkudmFsaWRhdGUobmV3IFVpbnQ4QXJyYXkoW1xcbiAgICAgICAgICAgIDAsIDk3LCAxMTUsIDEwOSwgMSwgMCwgMCwgMCwgMSwgNCwgMSwgOTYsIDAsIDAsIDMsIDIsIDEsIDAsIDUsXFxuICAgICAgICAgICAgNCwgMSwgMywgMSwgMSwgMTAsIDExLCAxLCA5LCAwLCA2NSwgMCwgMjU0LCAxNiwgMiwgMCwgMjYsIDExXFxuICAgICAgICBdKSk7XFxuICAgIH1cXG4gICAgY2F0Y2ggKGUpIHtcXG4gICAgICAgIHJldHVybiBmYWxzZTtcXG4gICAgfVxcbn07XFxuY29uc3QgaXNTaW1kU3VwcG9ydGVkID0gKCkgPT4ge1xcbiAgICB0cnkge1xcbiAgICAgICAgLy8gVGVzdCBmb3IgV2ViQXNzZW1ibHkgU0lNRCBjYXBhYmlsaXR5IChmb3IgYm90aCBicm93c2VycyBhbmQgTm9kZS5qcylcXG4gICAgICAgIC8vIFRoaXMgdHlwZWQgYXJyYXkgaXMgYSBXZWJBc3NlbWJseSBwcm9ncmFtIGNvbnRhaW5pbmcgU0lNRCBpbnN0cnVjdGlvbnMuXFxuICAgICAgICAvLyBUaGUgYmluYXJ5IGRhdGEgaXMgZ2VuZXJhdGVkIGZyb20gdGhlIGZvbGxvd2luZyBjb2RlIGJ5IHdhdDJ3YXNtOlxcbiAgICAgICAgLy9cXG4gICAgICAgIC8vIChtb2R1bGVcXG4gICAgICAgIC8vICAgKHR5cGUgJHQwIChmdW5jKSlcXG4gICAgICAgIC8vICAgKGZ1bmMgJGYwICh0eXBlICR0MClcXG4gICAgICAgIC8vICAgICAoZHJvcFxcbiAgICAgICAgLy8gICAgICAgKGkzMng0LmRvdF9pMTZ4OF9zXFxuICAgICAgICAvLyAgICAgICAgIChpOHgxNi5zcGxhdFxcbiAgICAgICAgLy8gICAgICAgICAgIChpMzIuY29uc3QgMCkpXFxuICAgICAgICAvLyAgICAgICAgICh2MTI4LmNvbnN0IGkzMng0IDB4MDAwMDAwMDAgMHgwMDAwMDAwMCAweDAwMDAwMDAwIDB4MDAwMDAwMDApKSkpKVxcbiAgICAgICAgcmV0dXJuIFdlYkFzc2VtYmx5LnZhbGlkYXRlKG5ldyBVaW50OEFycmF5KFtcXG4gICAgICAgICAgICAwLCA5NywgMTE1LCAxMDksIDEsIDAsIDAsIDAsIDEsIDQsIDEsIDk2LCAwLCAwLCAzLCAyLCAxLCAwLCAxMCwgMzAsIDEsIDI4LCAwLCA2NSwgMCxcXG4gICAgICAgICAgICAyNTMsIDE1LCAyNTMsIDEyLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAyNTMsIDE4NiwgMSwgMjYsIDExXFxuICAgICAgICBdKSk7XFxuICAgIH1cXG4gICAgY2F0Y2ggKGUpIHtcXG4gICAgICAgIHJldHVybiBmYWxzZTtcXG4gICAgfVxcbn07XFxuY29uc3QgZ2V0V2FzbUZpbGVOYW1lID0gKHVzZVNpbWQsIHVzZVRocmVhZHMpID0+IHtcXG4gICAgaWYgKHVzZVRocmVhZHMpIHtcXG4gICAgICAgIHJldHVybiB1c2VTaW1kID8gJ29ydC13YXNtLXNpbWQtdGhyZWFkZWQud2FzbScgOiAnb3J0LXdhc20tdGhyZWFkZWQud2FzbSc7XFxuICAgIH1cXG4gICAgZWxzZSB7XFxuICAgICAgICByZXR1cm4gdXNlU2ltZCA/ICdvcnQtd2FzbS1zaW1kLndhc20nIDogJ29ydC13YXNtLndhc20nO1xcbiAgICB9XFxufTtcXG5jb25zdCBpbml0aWFsaXplV2ViQXNzZW1ibHkgPSBhc3luYyAoZmxhZ3MpID0+IHtcXG4gICAgaWYgKGluaXRpYWxpemVkKSB7XFxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XFxuICAgIH1cXG4gICAgaWYgKGluaXRpYWxpemluZykge1xcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtdWx0aXBsZSBjYWxscyB0byBcXFxcJ2luaXRpYWxpemVXZWJBc3NlbWJseSgpXFxcXCcgZGV0ZWN0ZWQuJyk7XFxuICAgIH1cXG4gICAgaWYgKGFib3J0ZWQpIHtcXG4gICAgICAgIHRocm93IG5ldyBFcnJvcigncHJldmlvdXMgY2FsbCB0byBcXFxcJ2luaXRpYWxpemVXZWJBc3NlbWJseSgpXFxcXCcgZmFpbGVkLicpO1xcbiAgICB9XFxuICAgIGluaXRpYWxpemluZyA9IHRydWU7XFxuICAgIC8vIHdhc20gZmxhZ3MgYXJlIGFscmVhZHkgaW5pdGlhbGl6ZWRcXG4gICAgY29uc3QgdGltZW91dCA9IGZsYWdzLmluaXRUaW1lb3V0O1xcbiAgICBjb25zdCBudW1UaHJlYWRzID0gZmxhZ3MubnVtVGhyZWFkcztcXG4gICAgY29uc3Qgc2ltZCA9IGZsYWdzLnNpbWQ7XFxuICAgIGNvbnN0IHVzZVRocmVhZHMgPSBudW1UaHJlYWRzID4gMSAmJiBpc011bHRpVGhyZWFkU3VwcG9ydGVkKCk7XFxuICAgIGNvbnN0IHVzZVNpbWQgPSBzaW1kICYmIGlzU2ltZFN1cHBvcnRlZCgpO1xcbiAgICBjb25zdCB3YXNtUGF0aHMgPSBmbGFncy53YXNtUGF0aHM7XFxuICAgIGNvbnN0IHdhc21QcmVmaXhPdmVycmlkZSA9IHR5cGVvZiB3YXNtUGF0aHMgPT09ICdzdHJpbmcnID8gd2FzbVBhdGhzIDogdW5kZWZpbmVkO1xcbiAgICBjb25zdCB3YXNtRmlsZU5hbWUgPSBnZXRXYXNtRmlsZU5hbWUodXNlU2ltZCwgdXNlVGhyZWFkcyk7XFxuICAgIGNvbnN0IHdhc21QYXRoT3ZlcnJpZGUgPSB0eXBlb2Ygd2FzbVBhdGhzID09PSAnb2JqZWN0JyA/IHdhc21QYXRoc1t3YXNtRmlsZU5hbWVdIDogdW5kZWZpbmVkO1xcbiAgICBsZXQgaXNUaW1lb3V0ID0gZmFsc2U7XFxuICAgIGNvbnN0IHRhc2tzID0gW107XFxuICAgIC8vIHByb21pc2UgZm9yIHRpbWVvdXRcXG4gICAgaWYgKHRpbWVvdXQgPiAwKSB7XFxuICAgICAgICB0YXNrcy5wdXNoKG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XFxuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XFxuICAgICAgICAgICAgICAgIGlzVGltZW91dCA9IHRydWU7XFxuICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcXG4gICAgICAgICAgICB9LCB0aW1lb3V0KTtcXG4gICAgICAgIH0pKTtcXG4gICAgfVxcbiAgICAvLyBwcm9taXNlIGZvciBtb2R1bGUgaW5pdGlhbGl6YXRpb25cXG4gICAgdGFza3MucHVzaChuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XFxuICAgICAgICBjb25zdCBmYWN0b3J5ID0gdXNlVGhyZWFkcyA/IG9ydFdhc21GYWN0b3J5VGhyZWFkZWQgOiBvcnRXYXNtRmFjdG9yeTtcXG4gICAgICAgIGNvbnN0IGNvbmZpZyA9IHtcXG4gICAgICAgICAgICBsb2NhdGVGaWxlOiAoZmlsZU5hbWUsIHNjcmlwdERpcmVjdG9yeSkgPT4ge1xcbiAgICAgICAgICAgICAgICBpZiAoIHRydWUgJiYgdXNlVGhyZWFkcyAmJiBmaWxlTmFtZS5lbmRzV2l0aCgnLndvcmtlci5qcycpICYmXFxuICAgICAgICAgICAgICAgICAgICB0eXBlb2YgQmxvYiAhPT0gJ3VuZGVmaW5lZCcpIHtcXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBVUkwuY3JlYXRlT2JqZWN0VVJMKG5ldyBCbG9iKFtcXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHJlcXVpcmUoKSBmdW5jdGlvbiBpcyBoYW5kbGVkIGJ5IHdlYnBhY2sgdG8gbG9hZCBmaWxlIGNvbnRlbnQgb2YgdGhlIGNvcnJlc3BvbmRpbmcgLndvcmtlci5qc1xcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tcmVxdWlyZS1pbXBvcnRzXFxuICAgICAgICAgICAgICAgICAgICAgICAgX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgLi9iaW5kaW5nL29ydC13YXNtLXRocmVhZGVkLndvcmtlci5qcyAqLyBcXFwiLi9saWIvd2FzbS9iaW5kaW5nL29ydC13YXNtLXRocmVhZGVkLndvcmtlci5qc1xcXCIpXFxuICAgICAgICAgICAgICAgICAgICBdLCB7IHR5cGU6ICd0ZXh0L2phdmFzY3JpcHQnIH0pKTtcXG4gICAgICAgICAgICAgICAgfVxcbiAgICAgICAgICAgICAgICBpZiAoZmlsZU5hbWUuZW5kc1dpdGgoJy53YXNtJykpIHtcXG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXNtUGF0aE92ZXJyaWRlKSB7XFxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdhc21QYXRoT3ZlcnJpZGU7XFxuICAgICAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgICAgICAgICBjb25zdCBwcmVmaXggPSB3YXNtUHJlZml4T3ZlcnJpZGUgIT09IG51bGwgJiYgd2FzbVByZWZpeE92ZXJyaWRlICE9PSB2b2lkIDAgPyB3YXNtUHJlZml4T3ZlcnJpZGUgOiBzY3JpcHREaXJlY3Rvcnk7XFxuICAgICAgICAgICAgICAgICAgICBpZiAoZmFsc2UpIHt9XFxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJlZml4ICsgd2FzbUZpbGVOYW1lO1xcbiAgICAgICAgICAgICAgICB9XFxuICAgICAgICAgICAgICAgIHJldHVybiBzY3JpcHREaXJlY3RvcnkgKyBmaWxlTmFtZTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICB9O1xcbiAgICAgICAgaWYgKCB0cnVlICYmIHVzZVRocmVhZHMpIHtcXG4gICAgICAgICAgICBpZiAodHlwZW9mIEJsb2IgPT09ICd1bmRlZmluZWQnKSB7XFxuICAgICAgICAgICAgICAgIGNvbmZpZy5tYWluU2NyaXB0VXJsT3JCbG9iID0gcGF0aC5qb2luKF9fZGlybmFtZSwgJ29ydC13YXNtLXRocmVhZGVkLmpzJyk7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIGVsc2Uge1xcbiAgICAgICAgICAgICAgICBjb25zdCBzY3JpcHRTb3VyY2VDb2RlID0gYHZhciBvcnRXYXNtVGhyZWFkZWQ9KGZ1bmN0aW9uKCl7dmFyIF9zY3JpcHREaXI7cmV0dXJuICR7ZmFjdG9yeS50b1N0cmluZygpfX0pKCk7YDtcXG4gICAgICAgICAgICAgICAgY29uZmlnLm1haW5TY3JpcHRVcmxPckJsb2IgPSBuZXcgQmxvYihbc2NyaXB0U291cmNlQ29kZV0sIHsgdHlwZTogJ3RleHQvamF2YXNjcmlwdCcgfSk7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgfVxcbiAgICAgICAgZmFjdG9yeShjb25maWcpLnRoZW4oXFxuICAgICAgICAvLyB3YXNtIG1vZHVsZSBpbml0aWFsaXplZCBzdWNjZXNzZnVsbHlcXG4gICAgICAgIG1vZHVsZSA9PiB7XFxuICAgICAgICAgICAgaW5pdGlhbGl6aW5nID0gZmFsc2U7XFxuICAgICAgICAgICAgaW5pdGlhbGl6ZWQgPSB0cnVlO1xcbiAgICAgICAgICAgIHdhc20gPSBtb2R1bGU7XFxuICAgICAgICAgICAgcmVzb2x2ZSgpO1xcbiAgICAgICAgfSwgXFxuICAgICAgICAvLyB3YXNtIG1vZHVsZSBmYWlsZWQgdG8gaW5pdGlhbGl6ZVxcbiAgICAgICAgKHdoYXQpID0+IHtcXG4gICAgICAgICAgICBpbml0aWFsaXppbmcgPSBmYWxzZTtcXG4gICAgICAgICAgICBhYm9ydGVkID0gdHJ1ZTtcXG4gICAgICAgICAgICByZWplY3Qod2hhdCk7XFxuICAgICAgICB9KTtcXG4gICAgfSkpO1xcbiAgICBhd2FpdCBQcm9taXNlLnJhY2UodGFza3MpO1xcbiAgICBpZiAoaXNUaW1lb3V0KSB7XFxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFdlYkFzc2VtYmx5IGJhY2tlbmQgaW5pdGlhbGl6aW5nIGZhaWxlZCBkdWUgdG8gdGltZW91dDogJHt0aW1lb3V0fW1zYCk7XFxuICAgIH1cXG59O1xcbmV4cG9ydHMuaW5pdGlhbGl6ZVdlYkFzc2VtYmx5ID0gaW5pdGlhbGl6ZVdlYkFzc2VtYmx5O1xcbmNvbnN0IGdldEluc3RhbmNlID0gKCkgPT4ge1xcbiAgICBpZiAoaW5pdGlhbGl6ZWQgJiYgd2FzbSkge1xcbiAgICAgICAgcmV0dXJuIHdhc207XFxuICAgIH1cXG4gICAgdGhyb3cgbmV3IEVycm9yKCdXZWJBc3NlbWJseSBpcyBub3QgaW5pdGlhbGl6ZWQgeWV0LicpO1xcbn07XFxuZXhwb3J0cy5nZXRJbnN0YW5jZSA9IGdldEluc3RhbmNlO1xcbmNvbnN0IGRpc3Bvc2UgPSAoKSA9PiB7XFxuICAgIHZhciBfYTtcXG4gICAgaWYgKGluaXRpYWxpemVkICYmICFpbml0aWFsaXppbmcgJiYgIWFib3J0ZWQpIHtcXG4gICAgICAgIGluaXRpYWxpemluZyA9IHRydWU7XFxuICAgICAgICAoX2EgPSB3YXNtLlBUaHJlYWQpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS50ZXJtaW5hdGVBbGxUaHJlYWRzKCk7XFxuICAgICAgICB3YXNtID0gdW5kZWZpbmVkO1xcbiAgICAgICAgaW5pdGlhbGl6aW5nID0gZmFsc2U7XFxuICAgICAgICBpbml0aWFsaXplZCA9IGZhbHNlO1xcbiAgICAgICAgYWJvcnRlZCA9IHRydWU7XFxuICAgIH1cXG59O1xcbmV4cG9ydHMuZGlzcG9zZSA9IGRpc3Bvc2U7XFxuXFxuXFxuLyoqKi8gfSksXFxuXFxuLyoqKi8gXFxcIi4vbGliL3dhc20vYmluZGluZy9vcnQtd2FzbS10aHJlYWRlZC5qc1xcXCI6XFxuLyohKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiohKlxcXFxcXG4gICEqKiogLi9saWIvd2FzbS9iaW5kaW5nL29ydC13YXNtLXRocmVhZGVkLmpzICoqKiFcXG4gIFxcXFwqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cXG4vKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7XFxuXFxudmFyIF9fZmlsZW5hbWUgPSBcXFwiL2luZGV4LmpzXFxcIjtcXG52YXIgX19kaXJuYW1lID0gXFxcIi9cXFwiO1xcblxcclxcbnZhciBvcnRXYXNtVGhyZWFkZWQgPSAoKCkgPT4ge1xcclxcbiAgdmFyIF9zY3JpcHREaXIgPSB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnICYmIGRvY3VtZW50LmN1cnJlbnRTY3JpcHQgPyBkb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYyA6IHVuZGVmaW5lZDtcXHJcXG4gIGlmICh0cnVlKSBfc2NyaXB0RGlyID0gX3NjcmlwdERpciB8fCBfX2ZpbGVuYW1lO1xcclxcbiAgcmV0dXJuIChcXHJcXG5mdW5jdGlvbihvcnRXYXNtVGhyZWFkZWQpIHtcXHJcXG4gIG9ydFdhc21UaHJlYWRlZCA9IG9ydFdhc21UaHJlYWRlZCB8fCB7fTtcXHJcXG5cXHJcXG5cXHJcXG5mdW5jdGlvbiBjKCl7ay5idWZmZXIhPWwmJm0oay5idWZmZXIpO3JldHVybiBhYX1mdW5jdGlvbiBxKCl7ay5idWZmZXIhPWwmJm0oay5idWZmZXIpO3JldHVybiBiYX1mdW5jdGlvbiB0KCl7ay5idWZmZXIhPWwmJm0oay5idWZmZXIpO3JldHVybiBjYX1mdW5jdGlvbiB3KCl7ay5idWZmZXIhPWwmJm0oay5idWZmZXIpO3JldHVybiBkYX1mdW5jdGlvbiBlYSgpe2suYnVmZmVyIT1sJiZtKGsuYnVmZmVyKTtyZXR1cm4gZmF9bnVsbDt2YXIgeDt4fHwoeD10eXBlb2Ygb3J0V2FzbVRocmVhZGVkICE9PSAndW5kZWZpbmVkJyA/IG9ydFdhc21UaHJlYWRlZCA6IHt9KTt2YXIgaGEsaWE7eC5yZWFkeT1uZXcgUHJvbWlzZShmdW5jdGlvbihhLGIpe2hhPWE7aWE9Yn0pO1xcclxcbnZhciBqYT1PYmplY3QuYXNzaWduKHt9LHgpLGthPVxcXCIuL3RoaXMucHJvZ3JhbVxcXCIsej0oYSxiKT0+e3Rocm93IGI7fSxsYT1cXFwib2JqZWN0XFxcIj09dHlwZW9mIHdpbmRvdyxBPVxcXCJmdW5jdGlvblxcXCI9PXR5cGVvZiBpbXBvcnRTY3JpcHRzLEI9XFxcIm9iamVjdFxcXCI9PXR5cGVvZiBwcm9jZXNzJiZcXFwib2JqZWN0XFxcIj09dHlwZW9mIHByb2Nlc3MudmVyc2lvbnMmJlxcXCJzdHJpbmdcXFwiPT10eXBlb2YgcHJvY2Vzcy52ZXJzaW9ucy5ub2RlLEM9eC5FTlZJUk9OTUVOVF9JU19QVEhSRUFEfHwhMSxEPVxcXCJcXFwiO2Z1bmN0aW9uIG1hKGEpe3JldHVybiB4LmxvY2F0ZUZpbGU/eC5sb2NhdGVGaWxlKGEsRCk6RCthfXZhciBuYSxGLEcsZnMsSCxJO1xcclxcbmlmKEIpe0Q9QT8oX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgcGF0aCAqLyBcXFwiPzc1YzZcXFwiKS5kaXJuYW1lKShEKStcXFwiL1xcXCI6X19kaXJuYW1lK1xcXCIvXFxcIjtJPSgpPT57SHx8KGZzPV9fd2VicGFja19yZXF1aXJlX18oLyohIGZzICovIFxcXCI/NjNjOFxcXCIpLEg9X193ZWJwYWNrX3JlcXVpcmVfXygvKiEgcGF0aCAqLyBcXFwiPzc1YzZcXFwiKSl9O25hPWZ1bmN0aW9uKGIsZCl7SSgpO2I9SC5ub3JtYWxpemUoYik7cmV0dXJuIGZzLnJlYWRGaWxlU3luYyhiLGQ/dm9pZCAwOlxcXCJ1dGY4XFxcIil9O0c9Yj0+e2I9bmEoYiwhMCk7Yi5idWZmZXJ8fChiPW5ldyBVaW50OEFycmF5KGIpKTtyZXR1cm4gYn07Rj0oYixkLGUpPT57SSgpO2I9SC5ub3JtYWxpemUoYik7ZnMucmVhZEZpbGUoYixmdW5jdGlvbihnLGgpe2c/ZShnKTpkKGguYnVmZmVyKX0pfTsxPHByb2Nlc3MuYXJndi5sZW5ndGgmJihrYT1wcm9jZXNzLmFyZ3ZbMV0ucmVwbGFjZSgvXFxcXFxcXFwvZyxcXFwiL1xcXCIpKTtwcm9jZXNzLmFyZ3Yuc2xpY2UoMik7cHJvY2Vzcy5vbihcXFwidW5jYXVnaHRFeGNlcHRpb25cXFwiLGZ1bmN0aW9uKGIpe2lmKCEoYiBpbnN0YW5jZW9mIEspKXRocm93IGI7fSk7cHJvY2Vzcy5vbihcXFwidW5oYW5kbGVkUmVqZWN0aW9uXFxcIixcXHJcXG5mdW5jdGlvbihiKXt0aHJvdyBiO30pO3o9KGIsZCk9PntpZihub0V4aXRSdW50aW1lKXRocm93IHByb2Nlc3MuZXhpdENvZGU9YixkO2QgaW5zdGFuY2VvZiBLfHxMKFxcXCJleGl0aW5nIGR1ZSB0byBleGNlcHRpb246IFxcXCIrZCk7cHJvY2Vzcy5leGl0KGIpfTt4Lmluc3BlY3Q9ZnVuY3Rpb24oKXtyZXR1cm5cXFwiW0Vtc2NyaXB0ZW4gTW9kdWxlIG9iamVjdF1cXFwifTtsZXQgYTt0cnl7YT1fX3dlYnBhY2tfcmVxdWlyZV9fKC8qISB3b3JrZXJfdGhyZWFkcyAqLyBcXFwiP2M2ZjdcXFwiKX1jYXRjaChiKXt0aHJvdyBjb25zb2xlLmVycm9yKCdUaGUgXFxcIndvcmtlcl90aHJlYWRzXFxcIiBtb2R1bGUgaXMgbm90IHN1cHBvcnRlZCBpbiB0aGlzIG5vZGUuanMgYnVpbGQgLSBwZXJoYXBzIGEgbmV3ZXIgdmVyc2lvbiBpcyBuZWVkZWQ/JyksYjt9X193ZWJwYWNrX3JlcXVpcmVfXy5nLldvcmtlcj1hLldvcmtlcn1lbHNlIGlmKGxhfHxBKUE/RD1zZWxmLmxvY2F0aW9uLmhyZWY6XFxcInVuZGVmaW5lZFxcXCIhPXR5cGVvZiBkb2N1bWVudCYmZG9jdW1lbnQuY3VycmVudFNjcmlwdCYmKEQ9ZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmMpLFxcclxcbl9zY3JpcHREaXImJihEPV9zY3JpcHREaXIpLDAhPT1ELmluZGV4T2YoXFxcImJsb2I6XFxcIik/RD1ELnN1YnN0cigwLEQucmVwbGFjZSgvWz8jXS4qLyxcXFwiXFxcIikubGFzdEluZGV4T2YoXFxcIi9cXFwiKSsxKTpEPVxcXCJcXFwiLEJ8fChuYT1hPT57dmFyIGI9bmV3IFhNTEh0dHBSZXF1ZXN0O2Iub3BlbihcXFwiR0VUXFxcIixhLCExKTtiLnNlbmQobnVsbCk7cmV0dXJuIGIucmVzcG9uc2VUZXh0fSxBJiYoRz1hPT57dmFyIGI9bmV3IFhNTEh0dHBSZXF1ZXN0O2Iub3BlbihcXFwiR0VUXFxcIixhLCExKTtiLnJlc3BvbnNlVHlwZT1cXFwiYXJyYXlidWZmZXJcXFwiO2Iuc2VuZChudWxsKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYi5yZXNwb25zZSl9KSxGPShhLGIsZCk9Pnt2YXIgZT1uZXcgWE1MSHR0cFJlcXVlc3Q7ZS5vcGVuKFxcXCJHRVRcXFwiLGEsITApO2UucmVzcG9uc2VUeXBlPVxcXCJhcnJheWJ1ZmZlclxcXCI7ZS5vbmxvYWQ9KCk9PnsyMDA9PWUuc3RhdHVzfHwwPT1lLnN0YXR1cyYmZS5yZXNwb25zZT9iKGUucmVzcG9uc2UpOmQoKX07ZS5vbmVycm9yPVxcclxcbmQ7ZS5zZW5kKG51bGwpfSk7QiYmXFxcInVuZGVmaW5lZFxcXCI9PXR5cGVvZiBwZXJmb3JtYW5jZSYmKF9fd2VicGFja19yZXF1aXJlX18uZy5wZXJmb3JtYW5jZT0oX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgcGVyZl9ob29rcyAqLyBcXFwiPzY3NGZcXFwiKS5wZXJmb3JtYW5jZSkpO3ZhciBvYT1jb25zb2xlLmxvZy5iaW5kKGNvbnNvbGUpLHBhPWNvbnNvbGUud2Fybi5iaW5kKGNvbnNvbGUpO0ImJihJKCksb2E9YT0+ZnMud3JpdGVTeW5jKDEsYStcXFwiXFxcXG5cXFwiKSxwYT1hPT5mcy53cml0ZVN5bmMoMixhK1xcXCJcXFxcblxcXCIpKTt2YXIgcWE9eC5wcmludHx8b2EsTD14LnByaW50RXJyfHxwYTtPYmplY3QuYXNzaWduKHgsamEpO2phPW51bGw7eC50aGlzUHJvZ3JhbSYmKGthPXgudGhpc1Byb2dyYW0pO3gucXVpdCYmKHo9eC5xdWl0KTt2YXIgTTt4Lndhc21CaW5hcnkmJihNPXgud2FzbUJpbmFyeSk7dmFyIG5vRXhpdFJ1bnRpbWU9eC5ub0V4aXRSdW50aW1lfHwhMDtcXFwib2JqZWN0XFxcIiE9dHlwZW9mIFdlYkFzc2VtYmx5JiZOKFxcXCJubyBuYXRpdmUgd2FzbSBzdXBwb3J0IGRldGVjdGVkXFxcIik7XFxyXFxudmFyIGsscmEsc2E9ITEsdGE9XFxcInVuZGVmaW5lZFxcXCIhPXR5cGVvZiBUZXh0RGVjb2Rlcj9uZXcgVGV4dERlY29kZXIoXFxcInV0ZjhcXFwiKTp2b2lkIDA7XFxyXFxuZnVuY3Rpb24gdWEoYSxiLGQpe2I+Pj49MDt2YXIgZT1iK2Q7Zm9yKGQ9YjthW2RdJiYhKGQ+PWUpOykrK2Q7aWYoMTY8ZC1iJiZhLmJ1ZmZlciYmdGEpcmV0dXJuIHRhLmRlY29kZShhLmJ1ZmZlciBpbnN0YW5jZW9mIFNoYXJlZEFycmF5QnVmZmVyP2Euc2xpY2UoYixkKTphLnN1YmFycmF5KGIsZCkpO2ZvcihlPVxcXCJcXFwiO2I8ZDspe3ZhciBnPWFbYisrXTtpZihnJjEyOCl7dmFyIGg9YVtiKytdJjYzO2lmKDE5Mj09KGcmMjI0KSllKz1TdHJpbmcuZnJvbUNoYXJDb2RlKChnJjMxKTw8NnxoKTtlbHNle3ZhciBuPWFbYisrXSY2MztnPTIyND09KGcmMjQwKT8oZyYxNSk8PDEyfGg8PDZ8bjooZyY3KTw8MTh8aDw8MTJ8bjw8NnxhW2IrK10mNjM7NjU1MzY+Zz9lKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGcpOihnLT02NTUzNixlKz1TdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2fGc+PjEwLDU2MzIwfGcmMTAyMykpfX1lbHNlIGUrPVN0cmluZy5mcm9tQ2hhckNvZGUoZyl9cmV0dXJuIGV9XFxyXFxuZnVuY3Rpb24gdmEoYSxiKXtyZXR1cm4oYT4+Pj0wKT91YShxKCksYSxiKTpcXFwiXFxcIn1cXHJcXG5mdW5jdGlvbiB3YShhLGIsZCxlKXtkPj4+PTA7aWYoISgwPGUpKXJldHVybiAwO3ZhciBnPWQ7ZT1kK2UtMTtmb3IodmFyIGg9MDtoPGEubGVuZ3RoOysraCl7dmFyIG49YS5jaGFyQ29kZUF0KGgpO2lmKDU1Mjk2PD1uJiY1NzM0Mz49bil7dmFyIHU9YS5jaGFyQ29kZUF0KCsraCk7bj02NTUzNisoKG4mMTAyMyk8PDEwKXx1JjEwMjN9aWYoMTI3Pj1uKXtpZihkPj1lKWJyZWFrO2JbZCsrPj4+MF09bn1lbHNle2lmKDIwNDc+PW4pe2lmKGQrMT49ZSlicmVhaztiW2QrKz4+PjBdPTE5MnxuPj42fWVsc2V7aWYoNjU1MzU+PW4pe2lmKGQrMj49ZSlicmVhaztiW2QrKz4+PjBdPTIyNHxuPj4xMn1lbHNle2lmKGQrMz49ZSlicmVhaztiW2QrKz4+PjBdPTI0MHxuPj4xODtiW2QrKz4+PjBdPTEyOHxuPj4xMiY2M31iW2QrKz4+PjBdPTEyOHxuPj42JjYzfWJbZCsrPj4+MF09MTI4fG4mNjN9fWJbZD4+PjBdPTA7cmV0dXJuIGQtZ31cXHJcXG5mdW5jdGlvbiB4YShhKXtmb3IodmFyIGI9MCxkPTA7ZDxhLmxlbmd0aDsrK2Qpe3ZhciBlPWEuY2hhckNvZGVBdChkKTsxMjc+PWU/YisrOjIwNDc+PWU/Yis9Mjo1NTI5Njw9ZSYmNTczNDM+PWU/KGIrPTQsKytkKTpiKz0zfXJldHVybiBifXZhciBsLGFhLGJhLGNhLGRhLGZhO0MmJihsPXguYnVmZmVyKTtmdW5jdGlvbiBtKGEpe2w9YTt4LkhFQVA4PWFhPW5ldyBJbnQ4QXJyYXkoYSk7eC5IRUFQMTY9bmV3IEludDE2QXJyYXkoYSk7eC5IRUFQMzI9Y2E9bmV3IEludDMyQXJyYXkoYSk7eC5IRUFQVTg9YmE9bmV3IFVpbnQ4QXJyYXkoYSk7eC5IRUFQVTE2PW5ldyBVaW50MTZBcnJheShhKTt4LkhFQVBVMzI9ZGE9bmV3IFVpbnQzMkFycmF5KGEpO3guSEVBUEYzMj1uZXcgRmxvYXQzMkFycmF5KGEpO3guSEVBUEY2ND1mYT1uZXcgRmxvYXQ2NEFycmF5KGEpfXZhciB5YT14LklOSVRJQUxfTUVNT1JZfHwxNjc3NzIxNjtcXHJcXG5pZihDKWs9eC53YXNtTWVtb3J5LGw9eC5idWZmZXI7ZWxzZSBpZih4Lndhc21NZW1vcnkpaz14Lndhc21NZW1vcnk7ZWxzZSBpZihrPW5ldyBXZWJBc3NlbWJseS5NZW1vcnkoe2luaXRpYWw6eWEvNjU1MzYsbWF4aW11bTo2NTUzNixzaGFyZWQ6ITB9KSwhKGsuYnVmZmVyIGluc3RhbmNlb2YgU2hhcmVkQXJyYXlCdWZmZXIpKXRocm93IEwoXFxcInJlcXVlc3RlZCBhIHNoYXJlZCBXZWJBc3NlbWJseS5NZW1vcnkgYnV0IHRoZSByZXR1cm5lZCBidWZmZXIgaXMgbm90IGEgU2hhcmVkQXJyYXlCdWZmZXIsIGluZGljYXRpbmcgdGhhdCB3aGlsZSB0aGUgYnJvd3NlciBoYXMgU2hhcmVkQXJyYXlCdWZmZXIgaXQgZG9lcyBub3QgaGF2ZSBXZWJBc3NlbWJseSB0aHJlYWRzIHN1cHBvcnQgLSB5b3UgbWF5IG5lZWQgdG8gc2V0IGEgZmxhZ1xcXCIpLEImJmNvbnNvbGUubG9nKFxcXCIob24gbm9kZSB5b3UgbWF5IG5lZWQ6IC0tZXhwZXJpbWVudGFsLXdhc20tdGhyZWFkcyAtLWV4cGVyaW1lbnRhbC13YXNtLWJ1bGstbWVtb3J5IGFuZCBhbHNvIHVzZSBhIHJlY2VudCB2ZXJzaW9uKVxcXCIpLFxcclxcbkVycm9yKFxcXCJiYWQgbWVtb3J5XFxcIik7ayYmKGw9ay5idWZmZXIpO3lhPWwuYnl0ZUxlbmd0aDttKGwpO3ZhciB6YSxBYT1bXSxCYT1bXSxDYT1bXTtmdW5jdGlvbiBEYSgpe3ZhciBhPXgucHJlUnVuLnNoaWZ0KCk7QWEudW5zaGlmdChhKX12YXIgTz0wLEVhPW51bGwsUD1udWxsO2Z1bmN0aW9uIE4oYSl7aWYoQylwb3N0TWVzc2FnZSh7Y21kOlxcXCJvbkFib3J0XFxcIixhcmc6YX0pO2Vsc2UgaWYoeC5vbkFib3J0KXgub25BYm9ydChhKTthPVxcXCJBYm9ydGVkKFxcXCIrYStcXFwiKVxcXCI7TChhKTtzYT0hMDthPW5ldyBXZWJBc3NlbWJseS5SdW50aW1lRXJyb3IoYStcXFwiLiBCdWlsZCB3aXRoIC1zQVNTRVJUSU9OUyBmb3IgbW9yZSBpbmZvLlxcXCIpO2lhKGEpO3Rocm93IGE7fWZ1bmN0aW9uIEZhKCl7cmV0dXJuIFEuc3RhcnRzV2l0aChcXFwiZGF0YTphcHBsaWNhdGlvbi9vY3RldC1zdHJlYW07YmFzZTY0LFxcXCIpfXZhciBRO1E9XFxcIm9ydC13YXNtLXRocmVhZGVkLndhc21cXFwiO0ZhKCl8fChRPW1hKFEpKTtcXHJcXG5mdW5jdGlvbiBHYSgpe3ZhciBhPVE7dHJ5e2lmKGE9PVEmJk0pcmV0dXJuIG5ldyBVaW50OEFycmF5KE0pO2lmKEcpcmV0dXJuIEcoYSk7dGhyb3dcXFwiYm90aCBhc3luYyBhbmQgc3luYyBmZXRjaGluZyBvZiB0aGUgd2FzbSBmYWlsZWRcXFwiO31jYXRjaChiKXtOKGIpfX1cXHJcXG5mdW5jdGlvbiBIYSgpe2lmKCFNJiYobGF8fEEpKXtpZihcXFwiZnVuY3Rpb25cXFwiPT10eXBlb2YgZmV0Y2gmJiFRLnN0YXJ0c1dpdGgoXFxcImZpbGU6Ly9cXFwiKSlyZXR1cm4gZmV0Y2goUSx7Y3JlZGVudGlhbHM6XFxcInNhbWUtb3JpZ2luXFxcIn0pLnRoZW4oZnVuY3Rpb24oYSl7aWYoIWEub2spdGhyb3dcXFwiZmFpbGVkIHRvIGxvYWQgd2FzbSBiaW5hcnkgZmlsZSBhdCAnXFxcIitRK1xcXCInXFxcIjtyZXR1cm4gYS5hcnJheUJ1ZmZlcigpfSkuY2F0Y2goZnVuY3Rpb24oKXtyZXR1cm4gR2EoKX0pO2lmKEYpcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKGEsYil7RihRLGZ1bmN0aW9uKGQpe2EobmV3IFVpbnQ4QXJyYXkoZCkpfSxiKX0pfXJldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKGZ1bmN0aW9uKCl7cmV0dXJuIEdhKCl9KX12YXIgSWE9e307XFxyXFxuZnVuY3Rpb24gSyhhKXt0aGlzLm5hbWU9XFxcIkV4aXRTdGF0dXNcXFwiO3RoaXMubWVzc2FnZT1cXFwiUHJvZ3JhbSB0ZXJtaW5hdGVkIHdpdGggZXhpdChcXFwiK2ErXFxcIilcXFwiO3RoaXMuc3RhdHVzPWF9ZnVuY3Rpb24gSmEoYSl7KGE9Ui5MYVthXSl8fE4oKTtSLlhhKGEpfWZ1bmN0aW9uIEthKGEpe3ZhciBiPVIubGIoKTtpZighYilyZXR1cm4gNjtSLlJhLnB1c2goYik7Ui5MYVthLkthXT1iO2IuS2E9YS5LYTt2YXIgZD17Y21kOlxcXCJydW5cXFwiLHN0YXJ0X3JvdXRpbmU6YS5wYixhcmc6YS5pYixwdGhyZWFkX3B0cjphLkthfTtiLlFhPSgpPT57ZC50aW1lPXBlcmZvcm1hbmNlLm5vdygpO2IucG9zdE1lc3NhZ2UoZCxhLnZiKX07Yi5sb2FkZWQmJihiLlFhKCksZGVsZXRlIGIuUWEpO3JldHVybiAwfWZ1bmN0aW9uIExhKGEpe2lmKEMpcmV0dXJuIFMoMSwxLGEpO2lmKCFub0V4aXRSdW50aW1lKXtSLnFiKCk7aWYoeC5vbkV4aXQpeC5vbkV4aXQoYSk7c2E9ITB9eihhLG5ldyBLKGEpKX1cXHJcXG5mdW5jdGlvbiBNYShhLGIpe2lmKCFiJiZDKXRocm93IE5hKGEpLFxcXCJ1bndpbmRcXFwiO0xhKGEpfVxcclxcbnZhciBSPXtPYTpbXSxSYTpbXSwkYTpbXSxMYTp7fSxVYTpmdW5jdGlvbigpe0MmJlIubWIoKX0seGI6ZnVuY3Rpb24oKXt9LG1iOmZ1bmN0aW9uKCl7Ui5yZWNlaXZlT2JqZWN0VHJhbnNmZXI9Ui5vYjtSLnRocmVhZEluaXRUTFM9Ui5aYTtSLnNldEV4aXRTdGF0dXM9Ui5ZYTtub0V4aXRSdW50aW1lPSExfSxZYTpmdW5jdGlvbigpe30scWI6ZnVuY3Rpb24oKXtmb3IodmFyIGEgb2YgT2JqZWN0LnZhbHVlcyhSLkxhKSlSLlhhKGEpO2ZvcihhIG9mIFIuT2EpYS50ZXJtaW5hdGUoKTtSLk9hPVtdfSxYYTpmdW5jdGlvbihhKXt2YXIgYj1hLkthO2RlbGV0ZSBSLkxhW2JdO1IuT2EucHVzaChhKTtSLlJhLnNwbGljZShSLlJhLmluZGV4T2YoYSksMSk7YS5LYT0wO09hKGIpfSxvYjpmdW5jdGlvbigpe30sWmE6ZnVuY3Rpb24oKXtSLiRhLmZvckVhY2goYT0+YSgpKX0sbmI6ZnVuY3Rpb24oYSxiKXthLm9ubWVzc2FnZT1kPT57ZD1kLmRhdGE7dmFyIGU9ZC5jbWQ7YS5LYSYmKFIua2I9YS5LYSk7XFxyXFxuaWYoZC50YXJnZXRUaHJlYWQmJmQudGFyZ2V0VGhyZWFkIT1UKCkpe3ZhciBnPVIuTGFbZC55Yl07Zz9nLnBvc3RNZXNzYWdlKGQsZC50cmFuc2Zlckxpc3QpOkwoJ0ludGVybmFsIGVycm9yISBXb3JrZXIgc2VudCBhIG1lc3NhZ2UgXFxcIicrZSsnXFxcIiB0byB0YXJnZXQgcHRocmVhZCAnK2QudGFyZ2V0VGhyZWFkK1xcXCIsIGJ1dCB0aGF0IHRocmVhZCBubyBsb25nZXIgZXhpc3RzIVxcXCIpfWVsc2UgaWYoXFxcInByb2Nlc3NQcm94eWluZ1F1ZXVlXFxcIj09PWUpUGEoZC5xdWV1ZSk7ZWxzZSBpZihcXFwic3Bhd25UaHJlYWRcXFwiPT09ZSlLYShkKTtlbHNlIGlmKFxcXCJjbGVhbnVwVGhyZWFkXFxcIj09PWUpSmEoZC50aHJlYWQpO2Vsc2UgaWYoXFxcImtpbGxUaHJlYWRcXFwiPT09ZSlkPWQudGhyZWFkLGU9Ui5MYVtkXSxkZWxldGUgUi5MYVtkXSxlLnRlcm1pbmF0ZSgpLE9hKGQpLFIuUmEuc3BsaWNlKFIuUmEuaW5kZXhPZihlKSwxKSxlLkthPTA7ZWxzZSBpZihcXFwiY2FuY2VsVGhyZWFkXFxcIj09PWUpUi5MYVtkLnRocmVhZF0ucG9zdE1lc3NhZ2Uoe2NtZDpcXFwiY2FuY2VsXFxcIn0pO1xcclxcbmVsc2UgaWYoXFxcImxvYWRlZFxcXCI9PT1lKWEubG9hZGVkPSEwLGImJmIoYSksYS5RYSYmKGEuUWEoKSxkZWxldGUgYS5RYSk7ZWxzZSBpZihcXFwicHJpbnRcXFwiPT09ZSlxYShcXFwiVGhyZWFkIFxcXCIrZC50aHJlYWRJZCtcXFwiOiBcXFwiK2QudGV4dCk7ZWxzZSBpZihcXFwicHJpbnRFcnJcXFwiPT09ZSlMKFxcXCJUaHJlYWQgXFxcIitkLnRocmVhZElkK1xcXCI6IFxcXCIrZC50ZXh0KTtlbHNlIGlmKFxcXCJhbGVydFxcXCI9PT1lKWFsZXJ0KFxcXCJUaHJlYWQgXFxcIitkLnRocmVhZElkK1xcXCI6IFxcXCIrZC50ZXh0KTtlbHNlIGlmKFxcXCJzZXRpbW1lZGlhdGVcXFwiPT09ZC50YXJnZXQpYS5wb3N0TWVzc2FnZShkKTtlbHNlIGlmKFxcXCJvbkFib3J0XFxcIj09PWUpe2lmKHgub25BYm9ydCl4Lm9uQWJvcnQoZC5hcmcpfWVsc2UgZSYmTChcXFwid29ya2VyIHNlbnQgYW4gdW5rbm93biBjb21tYW5kIFxcXCIrZSk7Ui5rYj12b2lkIDB9O2Eub25lcnJvcj1kPT57TChcXFwid29ya2VyIHNlbnQgYW4gZXJyb3IhIFxcXCIrZC5maWxlbmFtZStcXFwiOlxcXCIrZC5saW5lbm8rXFxcIjogXFxcIitkLm1lc3NhZ2UpO3Rocm93IGQ7fTtCJiZcXHJcXG4oYS5vbihcXFwibWVzc2FnZVxcXCIsZnVuY3Rpb24oZCl7YS5vbm1lc3NhZ2Uoe2RhdGE6ZH0pfSksYS5vbihcXFwiZXJyb3JcXFwiLGZ1bmN0aW9uKGQpe2Eub25lcnJvcihkKX0pLGEub24oXFxcImRldGFjaGVkRXhpdFxcXCIsZnVuY3Rpb24oKXt9KSk7YS5wb3N0TWVzc2FnZSh7Y21kOlxcXCJsb2FkXFxcIix1cmxPckJsb2I6eC5tYWluU2NyaXB0VXJsT3JCbG9ifHxfc2NyaXB0RGlyLHdhc21NZW1vcnk6ayx3YXNtTW9kdWxlOnJhfSl9LGhiOmZ1bmN0aW9uKCl7dmFyIGE9bWEoXFxcIm9ydC13YXNtLXRocmVhZGVkLndvcmtlci5qc1xcXCIpO1IuT2EucHVzaChuZXcgV29ya2VyKGEpKX0sbGI6ZnVuY3Rpb24oKXswPT1SLk9hLmxlbmd0aCYmKFIuaGIoKSxSLm5iKFIuT2FbMF0pKTtyZXR1cm4gUi5PYS5wb3AoKX19O3guUFRocmVhZD1SO2Z1bmN0aW9uIFUoYSl7Zm9yKDswPGEubGVuZ3RoOylhLnNoaWZ0KCkoeCl9ZnVuY3Rpb24gUWEoYSl7dmFyIGI9UmEoKTthPWEoKTtWKGIpO3JldHVybiBhfVxcclxcbnguZXN0YWJsaXNoU3RhY2tTcGFjZT1mdW5jdGlvbigpe3ZhciBhPVQoKSxiPXQoKVthKzQ0Pj4yPj4+MF07YT10KClbYSs0OD4+Mj4+PjBdO1NhKGIsYi1hKTtWKGIpfTtmdW5jdGlvbiBOYShhKXtpZihDKXJldHVybiBTKDIsMCxhKTt0cnl7TWEoYSl9Y2F0Y2goYil7YiBpbnN0YW5jZW9mIEt8fFxcXCJ1bndpbmRcXFwiPT1ifHx6KDEsYil9fXZhciBXPVtdO3guaW52b2tlRW50cnlQb2ludD1mdW5jdGlvbihhLGIpe3ZhciBkPVdbYV07ZHx8KGE+PVcubGVuZ3RoJiYoVy5sZW5ndGg9YSsxKSxXW2FdPWQ9emEuZ2V0KGEpKTthPWQoYik7bm9FeGl0UnVudGltZT9SLllhKGEpOlRhKGEpfTtmdW5jdGlvbiBVYShhLGIpe2MoKS5zZXQoYSxiPj4+MCl9XFxyXFxuZnVuY3Rpb24gVmEoYSl7dGhpcy5QYT1hLTI0O3RoaXMuZ2I9ZnVuY3Rpb24oYil7dygpW3RoaXMuUGErND4+Mj4+PjBdPWJ9O3RoaXMuY2I9ZnVuY3Rpb24oYil7dygpW3RoaXMuUGErOD4+Mj4+PjBdPWJ9O3RoaXMuZWI9ZnVuY3Rpb24oKXt0KClbdGhpcy5QYT4+Mj4+PjBdPTB9O3RoaXMuYmI9ZnVuY3Rpb24oKXt2YXIgYj0wO2MoKVt0aGlzLlBhKzEyPj4wPj4+MF09Yn07dGhpcy5mYj1mdW5jdGlvbigpe3ZhciBiPTA7YygpW3RoaXMuUGErMTM+PjA+Pj4wXT1ifTt0aGlzLlVhPWZ1bmN0aW9uKGIsZCl7dGhpcy5hYigpO3RoaXMuZ2IoYik7dGhpcy5jYihkKTt0aGlzLmViKCk7dGhpcy5iYigpO3RoaXMuZmIoKX07dGhpcy5hYj1mdW5jdGlvbigpe3coKVt0aGlzLlBhKzE2Pj4yPj4+MF09MH19dmFyIFdhPTA7ZnVuY3Rpb24gWGEoYSxiLGQsZSl7cmV0dXJuIEM/UygzLDEsYSxiLGQsZSk6WWEoYSxiLGQsZSl9XFxyXFxuZnVuY3Rpb24gWWEoYSxiLGQsZSl7aWYoXFxcInVuZGVmaW5lZFxcXCI9PXR5cGVvZiBTaGFyZWRBcnJheUJ1ZmZlcilyZXR1cm4gTChcXFwiQ3VycmVudCBlbnZpcm9ubWVudCBkb2VzIG5vdCBzdXBwb3J0IFNoYXJlZEFycmF5QnVmZmVyLCBwdGhyZWFkcyBhcmUgbm90IGF2YWlsYWJsZSFcXFwiKSw2O3ZhciBnPVtdO2lmKEMmJjA9PT1nLmxlbmd0aClyZXR1cm4gWGEoYSxiLGQsZSk7YT17cGI6ZCxLYTphLGliOmUsdmI6Z307cmV0dXJuIEM/KGEud2I9XFxcInNwYXduVGhyZWFkXFxcIixwb3N0TWVzc2FnZShhLGcpLDApOkthKGEpfWZ1bmN0aW9uIFphKGEsYixkKXtyZXR1cm4gQz9TKDQsMSxhLGIsZCk6MH1mdW5jdGlvbiAkYShhLGIpe2lmKEMpcmV0dXJuIFMoNSwxLGEsYil9ZnVuY3Rpb24gYWIoYSxiKXtpZihDKXJldHVybiBTKDYsMSxhLGIpfWZ1bmN0aW9uIGJiKGEsYixkKXtpZihDKXJldHVybiBTKDcsMSxhLGIsZCl9ZnVuY3Rpb24gY2IoYSxiLGQpe3JldHVybiBDP1MoOCwxLGEsYixkKTowfVxcclxcbmZ1bmN0aW9uIGRiKGEsYil7aWYoQylyZXR1cm4gUyg5LDEsYSxiKX1mdW5jdGlvbiBlYihhLGIsZCl7aWYoQylyZXR1cm4gUygxMCwxLGEsYixkKX1mdW5jdGlvbiBmYihhLGIsZCxlKXtpZihDKXJldHVybiBTKDExLDEsYSxiLGQsZSl9ZnVuY3Rpb24gZ2IoYSxiLGQsZSl7aWYoQylyZXR1cm4gUygxMiwxLGEsYixkLGUpfWZ1bmN0aW9uIGhiKGEsYixkLGUpe2lmKEMpcmV0dXJuIFMoMTMsMSxhLGIsZCxlKX1mdW5jdGlvbiBpYihhKXtpZihDKXJldHVybiBTKDE0LDEsYSl9ZnVuY3Rpb24gamIoYSxiKXtpZihDKXJldHVybiBTKDE1LDEsYSxiKX1mdW5jdGlvbiBrYihhLGIsZCl7aWYoQylyZXR1cm4gUygxNiwxLGEsYixkKX1mdW5jdGlvbiBQYShhKXtBdG9taWNzLnN0b3JlKHQoKSxhPj4yLDEpO1QoKSYmbGIoYSk7QXRvbWljcy5jb21wYXJlRXhjaGFuZ2UodCgpLGE+PjIsMSwwKX14LmV4ZWN1dGVOb3RpZmllZFByb3h5aW5nUXVldWU9UGE7XFxyXFxuZnVuY3Rpb24gbWIoYSl7cmV0dXJuIHcoKVthPj4+Ml0rNDI5NDk2NzI5Nip0KClbYSs0Pj4+Ml19ZnVuY3Rpb24gbmIoYSxiLGQsZSxnLGgpe3JldHVybiBDP1MoMTcsMSxhLGIsZCxlLGcsaCk6LTUyfWZ1bmN0aW9uIG9iKGEsYixkLGUsZyxoKXtpZihDKXJldHVybiBTKDE4LDEsYSxiLGQsZSxnLGgpfWZ1bmN0aW9uIHBiKGEpe3ZhciBiPXhhKGEpKzEsZD1xYihiKTtkJiZ3YShhLGMoKSxkLGIpO3JldHVybiBkfVxcclxcbmZ1bmN0aW9uIHJiKGEsYixkKXtmdW5jdGlvbiBlKHYpe3JldHVybih2PXYudG9UaW1lU3RyaW5nKCkubWF0Y2goL1xcXFwoKFtBLVphLXogXSspXFxcXCkkLykpP3ZbMV06XFxcIkdNVFxcXCJ9aWYoQylyZXR1cm4gUygxOSwxLGEsYixkKTt2YXIgZz0obmV3IERhdGUpLmdldEZ1bGxZZWFyKCksaD1uZXcgRGF0ZShnLDAsMSksbj1uZXcgRGF0ZShnLDYsMSk7Zz1oLmdldFRpbWV6b25lT2Zmc2V0KCk7dmFyIHU9bi5nZXRUaW1lem9uZU9mZnNldCgpLEU9TWF0aC5tYXgoZyx1KTt0KClbYT4+Mj4+PjBdPTYwKkU7dCgpW2I+PjI+Pj4wXT1OdW1iZXIoZyE9dSk7YT1lKGgpO2I9ZShuKTthPXBiKGEpO2I9cGIoYik7dTxnPyh3KClbZD4+Mj4+PjBdPWEsdygpW2QrND4+Mj4+PjBdPWIpOih3KClbZD4+Mj4+PjBdPWIsdygpW2QrND4+Mj4+PjBdPWEpfWZ1bmN0aW9uIHNiKGEsYixkKXtzYi5qYnx8KHNiLmpiPSEwLHJiKGEsYixkKSl9dmFyIFgsdGI7XFxyXFxudGI9Qj8oKT0+e3ZhciBhPXByb2Nlc3MuaHJ0aW1lKCk7cmV0dXJuIDFFMyphWzBdK2FbMV0vMUU2fTpDPygpPT5wZXJmb3JtYW5jZS5ub3coKS14Ll9fcGVyZm9ybWFuY2Vfbm93X2Nsb2NrX2RyaWZ0OigpPT5wZXJmb3JtYW5jZS5ub3coKTtmdW5jdGlvbiBTKGEsYil7dmFyIGQ9YXJndW1lbnRzLmxlbmd0aC0yLGU9YXJndW1lbnRzO3JldHVybiBRYSgoKT0+e2Zvcih2YXIgZz11Yig4KmQpLGg9Zz4+MyxuPTA7bjxkO24rKyl7dmFyIHU9ZVsyK25dO2VhKClbaCtuPj4+MF09dX1yZXR1cm4gdmIoYSxkLGcsYil9KX12YXIgd2I9W10seGI9e307XFxyXFxuZnVuY3Rpb24geWIoKXtpZighemIpe3ZhciBhPXtVU0VSOlxcXCJ3ZWJfdXNlclxcXCIsTE9HTkFNRTpcXFwid2ViX3VzZXJcXFwiLFBBVEg6XFxcIi9cXFwiLFBXRDpcXFwiL1xcXCIsSE9NRTpcXFwiL2hvbWUvd2ViX3VzZXJcXFwiLExBTkc6KFxcXCJvYmplY3RcXFwiPT10eXBlb2YgbmF2aWdhdG9yJiZuYXZpZ2F0b3IubGFuZ3VhZ2VzJiZuYXZpZ2F0b3IubGFuZ3VhZ2VzWzBdfHxcXFwiQ1xcXCIpLnJlcGxhY2UoXFxcIi1cXFwiLFxcXCJfXFxcIikrXFxcIi5VVEYtOFxcXCIsXzprYXx8XFxcIi4vdGhpcy5wcm9ncmFtXFxcIn0sYjtmb3IoYiBpbiB4Yil2b2lkIDA9PT14YltiXT9kZWxldGUgYVtiXTphW2JdPXhiW2JdO3ZhciBkPVtdO2ZvcihiIGluIGEpZC5wdXNoKGIrXFxcIj1cXFwiK2FbYl0pO3piPWR9cmV0dXJuIHpifXZhciB6YjtcXHJcXG5mdW5jdGlvbiBBYihhLGIpe2lmKEMpcmV0dXJuIFMoMjAsMSxhLGIpO3ZhciBkPTA7eWIoKS5mb3JFYWNoKGZ1bmN0aW9uKGUsZyl7dmFyIGg9YitkO2c9dygpW2ErNCpnPj4yPj4+MF09aDtmb3IoaD0wO2g8ZS5sZW5ndGg7KytoKWMoKVtnKys+PjA+Pj4wXT1lLmNoYXJDb2RlQXQoaCk7YygpW2c+PjA+Pj4wXT0wO2QrPWUubGVuZ3RoKzF9KTtyZXR1cm4gMH1mdW5jdGlvbiBCYihhLGIpe2lmKEMpcmV0dXJuIFMoMjEsMSxhLGIpO3ZhciBkPXliKCk7dygpW2E+PjI+Pj4wXT1kLmxlbmd0aDt2YXIgZT0wO2QuZm9yRWFjaChmdW5jdGlvbihnKXtlKz1nLmxlbmd0aCsxfSk7dygpW2I+PjI+Pj4wXT1lO3JldHVybiAwfWZ1bmN0aW9uIENiKGEpe3JldHVybiBDP1MoMjIsMSxhKTo1Mn1mdW5jdGlvbiBHYihhLGIsZCxlKXtyZXR1cm4gQz9TKDIzLDEsYSxiLGQsZSk6NTJ9ZnVuY3Rpb24gSGIoYSxiLGQsZSxnKXtyZXR1cm4gQz9TKDI0LDEsYSxiLGQsZSxnKTo3MH1cXHJcXG52YXIgSWI9W251bGwsW10sW11dO2Z1bmN0aW9uIEpiKGEsYixkLGUpe2lmKEMpcmV0dXJuIFMoMjUsMSxhLGIsZCxlKTtmb3IodmFyIGc9MCxoPTA7aDxkO2grKyl7dmFyIG49dygpW2I+PjI+Pj4wXSx1PXcoKVtiKzQ+PjI+Pj4wXTtiKz04O2Zvcih2YXIgRT0wO0U8dTtFKyspe3ZhciB2PXEoKVtuK0U+Pj4wXSx5PUliW2FdOzA9PT12fHwxMD09PXY/KCgxPT09YT9xYTpMKSh1YSh5LDApKSx5Lmxlbmd0aD0wKTp5LnB1c2godil9Zys9dX13KClbZT4+Mj4+PjBdPWc7cmV0dXJuIDB9XFxyXFxuZnVuY3Rpb24gS2IoKXtpZihcXFwib2JqZWN0XFxcIj09dHlwZW9mIGNyeXB0byYmXFxcImZ1bmN0aW9uXFxcIj09dHlwZW9mIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMpe3ZhciBhPW5ldyBVaW50OEFycmF5KDEpO3JldHVybigpPT57Y3J5cHRvLmdldFJhbmRvbVZhbHVlcyhhKTtyZXR1cm4gYVswXX19aWYoQil0cnl7dmFyIGI9X193ZWJwYWNrX3JlcXVpcmVfXygvKiEgY3J5cHRvICovIFxcXCI/ODkyZFxcXCIpO3JldHVybigpPT5iLnJhbmRvbUJ5dGVzKDEpWzBdfWNhdGNoKGQpe31yZXR1cm4oKT0+TihcXFwicmFuZG9tRGV2aWNlXFxcIil9ZnVuY3Rpb24gWShhLGIpe1kuV2F8fChZLldhPUtiKCkpO2Zvcih2YXIgZD0wO2Q8YjtkKyspYygpW2ErZD4+MD4+PjBdPVkuV2EoKTtyZXR1cm4gMH1mdW5jdGlvbiBaKGEpe3JldHVybiAwPT09YSU0JiYoMCE9PWElMTAwfHwwPT09YSU0MDApfXZhciBMYj1bMzEsMjksMzEsMzAsMzEsMzAsMzEsMzEsMzAsMzEsMzAsMzFdLE1iPVszMSwyOCwzMSwzMCwzMSwzMCwzMSwzMSwzMCwzMSwzMCwzMV07XFxyXFxuZnVuY3Rpb24gTmIoYSl7dmFyIGI9QXJyYXkoeGEoYSkrMSk7d2EoYSxiLDAsYi5sZW5ndGgpO3JldHVybiBifVxcclxcbmZ1bmN0aW9uIE9iKGEsYixkLGUpe2Z1bmN0aW9uIGcoZixwLHIpe2ZvcihmPVxcXCJudW1iZXJcXFwiPT10eXBlb2YgZj9mLnRvU3RyaW5nKCk6Znx8XFxcIlxcXCI7Zi5sZW5ndGg8cDspZj1yWzBdK2Y7cmV0dXJuIGZ9ZnVuY3Rpb24gaChmLHApe3JldHVybiBnKGYscCxcXFwiMFxcXCIpfWZ1bmN0aW9uIG4oZixwKXtmdW5jdGlvbiByKERiKXtyZXR1cm4gMD5EYj8tMTowPERiPzE6MH12YXIgSjswPT09KEo9cihmLmdldEZ1bGxZZWFyKCktcC5nZXRGdWxsWWVhcigpKSkmJjA9PT0oSj1yKGYuZ2V0TW9udGgoKS1wLmdldE1vbnRoKCkpKSYmKEo9cihmLmdldERhdGUoKS1wLmdldERhdGUoKSkpO3JldHVybiBKfWZ1bmN0aW9uIHUoZil7c3dpdGNoKGYuZ2V0RGF5KCkpe2Nhc2UgMDpyZXR1cm4gbmV3IERhdGUoZi5nZXRGdWxsWWVhcigpLTEsMTEsMjkpO2Nhc2UgMTpyZXR1cm4gZjtjYXNlIDI6cmV0dXJuIG5ldyBEYXRlKGYuZ2V0RnVsbFllYXIoKSwwLDMpO2Nhc2UgMzpyZXR1cm4gbmV3IERhdGUoZi5nZXRGdWxsWWVhcigpLFxcclxcbjAsMik7Y2FzZSA0OnJldHVybiBuZXcgRGF0ZShmLmdldEZ1bGxZZWFyKCksMCwxKTtjYXNlIDU6cmV0dXJuIG5ldyBEYXRlKGYuZ2V0RnVsbFllYXIoKS0xLDExLDMxKTtjYXNlIDY6cmV0dXJuIG5ldyBEYXRlKGYuZ2V0RnVsbFllYXIoKS0xLDExLDMwKX19ZnVuY3Rpb24gRShmKXt2YXIgcD1mLk1hO2ZvcihmPW5ldyBEYXRlKChuZXcgRGF0ZShmLk5hKzE5MDAsMCwxKSkuZ2V0VGltZSgpKTswPHA7KXt2YXIgcj1mLmdldE1vbnRoKCksSj0oWihmLmdldEZ1bGxZZWFyKCkpP0xiOk1iKVtyXTtpZihwPkotZi5nZXREYXRlKCkpcC09Si1mLmdldERhdGUoKSsxLGYuc2V0RGF0ZSgxKSwxMT5yP2Yuc2V0TW9udGgocisxKTooZi5zZXRNb250aCgwKSxmLnNldEZ1bGxZZWFyKGYuZ2V0RnVsbFllYXIoKSsxKSk7ZWxzZXtmLnNldERhdGUoZi5nZXREYXRlKCkrcCk7YnJlYWt9fXI9bmV3IERhdGUoZi5nZXRGdWxsWWVhcigpKzEsMCw0KTtwPXUobmV3IERhdGUoZi5nZXRGdWxsWWVhcigpLFxcclxcbjAsNCkpO3I9dShyKTtyZXR1cm4gMD49bihwLGYpPzA+PW4ocixmKT9mLmdldEZ1bGxZZWFyKCkrMTpmLmdldEZ1bGxZZWFyKCk6Zi5nZXRGdWxsWWVhcigpLTF9dmFyIHY9dCgpW2UrNDA+PjI+Pj4wXTtlPXt0Yjp0KClbZT4+Mj4+PjBdLHNiOnQoKVtlKzQ+PjI+Pj4wXSxTYTp0KClbZSs4Pj4yPj4+MF0sVmE6dCgpW2UrMTI+PjI+Pj4wXSxUYTp0KClbZSsxNj4+Mj4+PjBdLE5hOnQoKVtlKzIwPj4yPj4+MF0sSmE6dCgpW2UrMjQ+PjI+Pj4wXSxNYTp0KClbZSsyOD4+Mj4+PjBdLHpiOnQoKVtlKzMyPj4yPj4+MF0scmI6dCgpW2UrMzY+PjI+Pj4wXSx1Yjp2P3ZhKHYpOlxcXCJcXFwifTtkPXZhKGQpO3Y9e1xcXCIlY1xcXCI6XFxcIiVhICViICVkICVIOiVNOiVTICVZXFxcIixcXFwiJURcXFwiOlxcXCIlbS8lZC8leVxcXCIsXFxcIiVGXFxcIjpcXFwiJVktJW0tJWRcXFwiLFxcXCIlaFxcXCI6XFxcIiViXFxcIixcXFwiJXJcXFwiOlxcXCIlSTolTTolUyAlcFxcXCIsXFxcIiVSXFxcIjpcXFwiJUg6JU1cXFwiLFxcXCIlVFxcXCI6XFxcIiVIOiVNOiVTXFxcIixcXFwiJXhcXFwiOlxcXCIlbS8lZC8leVxcXCIsXFxcIiVYXFxcIjpcXFwiJUg6JU06JVNcXFwiLFxcXCIlRWNcXFwiOlxcXCIlY1xcXCIsXFxcIiVFQ1xcXCI6XFxcIiVDXFxcIixcXHJcXG5cXFwiJUV4XFxcIjpcXFwiJW0vJWQvJXlcXFwiLFxcXCIlRVhcXFwiOlxcXCIlSDolTTolU1xcXCIsXFxcIiVFeVxcXCI6XFxcIiV5XFxcIixcXFwiJUVZXFxcIjpcXFwiJVlcXFwiLFxcXCIlT2RcXFwiOlxcXCIlZFxcXCIsXFxcIiVPZVxcXCI6XFxcIiVlXFxcIixcXFwiJU9IXFxcIjpcXFwiJUhcXFwiLFxcXCIlT0lcXFwiOlxcXCIlSVxcXCIsXFxcIiVPbVxcXCI6XFxcIiVtXFxcIixcXFwiJU9NXFxcIjpcXFwiJU1cXFwiLFxcXCIlT1NcXFwiOlxcXCIlU1xcXCIsXFxcIiVPdVxcXCI6XFxcIiV1XFxcIixcXFwiJU9VXFxcIjpcXFwiJVVcXFwiLFxcXCIlT1ZcXFwiOlxcXCIlVlxcXCIsXFxcIiVPd1xcXCI6XFxcIiV3XFxcIixcXFwiJU9XXFxcIjpcXFwiJVdcXFwiLFxcXCIlT3lcXFwiOlxcXCIleVxcXCJ9O2Zvcih2YXIgeSBpbiB2KWQ9ZC5yZXBsYWNlKG5ldyBSZWdFeHAoeSxcXFwiZ1xcXCIpLHZbeV0pO3ZhciBFYj1cXFwiU3VuZGF5IE1vbmRheSBUdWVzZGF5IFdlZG5lc2RheSBUaHVyc2RheSBGcmlkYXkgU2F0dXJkYXlcXFwiLnNwbGl0KFxcXCIgXFxcIiksRmI9XFxcIkphbnVhcnkgRmVicnVhcnkgTWFyY2ggQXByaWwgTWF5IEp1bmUgSnVseSBBdWd1c3QgU2VwdGVtYmVyIE9jdG9iZXIgTm92ZW1iZXIgRGVjZW1iZXJcXFwiLnNwbGl0KFxcXCIgXFxcIik7dj17XFxcIiVhXFxcIjpmdW5jdGlvbihmKXtyZXR1cm4gRWJbZi5KYV0uc3Vic3RyaW5nKDAsMyl9LFxcXCIlQVxcXCI6ZnVuY3Rpb24oZil7cmV0dXJuIEViW2YuSmFdfSxcXHJcXG5cXFwiJWJcXFwiOmZ1bmN0aW9uKGYpe3JldHVybiBGYltmLlRhXS5zdWJzdHJpbmcoMCwzKX0sXFxcIiVCXFxcIjpmdW5jdGlvbihmKXtyZXR1cm4gRmJbZi5UYV19LFxcXCIlQ1xcXCI6ZnVuY3Rpb24oZil7cmV0dXJuIGgoKGYuTmErMTkwMCkvMTAwfDAsMil9LFxcXCIlZFxcXCI6ZnVuY3Rpb24oZil7cmV0dXJuIGgoZi5WYSwyKX0sXFxcIiVlXFxcIjpmdW5jdGlvbihmKXtyZXR1cm4gZyhmLlZhLDIsXFxcIiBcXFwiKX0sXFxcIiVnXFxcIjpmdW5jdGlvbihmKXtyZXR1cm4gRShmKS50b1N0cmluZygpLnN1YnN0cmluZygyKX0sXFxcIiVHXFxcIjpmdW5jdGlvbihmKXtyZXR1cm4gRShmKX0sXFxcIiVIXFxcIjpmdW5jdGlvbihmKXtyZXR1cm4gaChmLlNhLDIpfSxcXFwiJUlcXFwiOmZ1bmN0aW9uKGYpe2Y9Zi5TYTswPT1mP2Y9MTI6MTI8ZiYmKGYtPTEyKTtyZXR1cm4gaChmLDIpfSxcXFwiJWpcXFwiOmZ1bmN0aW9uKGYpe2Zvcih2YXIgcD0wLHI9MDtyPD1mLlRhLTE7cCs9KFooZi5OYSsxOTAwKT9MYjpNYilbcisrXSk7cmV0dXJuIGgoZi5WYStwLDMpfSxcXFwiJW1cXFwiOmZ1bmN0aW9uKGYpe3JldHVybiBoKGYuVGErXFxyXFxuMSwyKX0sXFxcIiVNXFxcIjpmdW5jdGlvbihmKXtyZXR1cm4gaChmLnNiLDIpfSxcXFwiJW5cXFwiOmZ1bmN0aW9uKCl7cmV0dXJuXFxcIlxcXFxuXFxcIn0sXFxcIiVwXFxcIjpmdW5jdGlvbihmKXtyZXR1cm4gMDw9Zi5TYSYmMTI+Zi5TYT9cXFwiQU1cXFwiOlxcXCJQTVxcXCJ9LFxcXCIlU1xcXCI6ZnVuY3Rpb24oZil7cmV0dXJuIGgoZi50YiwyKX0sXFxcIiV0XFxcIjpmdW5jdGlvbigpe3JldHVyblxcXCJcXFxcdFxcXCJ9LFxcXCIldVxcXCI6ZnVuY3Rpb24oZil7cmV0dXJuIGYuSmF8fDd9LFxcXCIlVVxcXCI6ZnVuY3Rpb24oZil7cmV0dXJuIGgoTWF0aC5mbG9vcigoZi5NYSs3LWYuSmEpLzcpLDIpfSxcXFwiJVZcXFwiOmZ1bmN0aW9uKGYpe3ZhciBwPU1hdGguZmxvb3IoKGYuTWErNy0oZi5KYSs2KSU3KS83KTsyPj0oZi5KYSszNzEtZi5NYS0yKSU3JiZwKys7aWYocCk1Mz09cCYmKHI9KGYuSmErMzcxLWYuTWEpJTcsND09cnx8Mz09ciYmWihmLk5hKXx8KHA9MSkpO2Vsc2V7cD01Mjt2YXIgcj0oZi5KYSs3LWYuTWEtMSklNzsoND09cnx8NT09ciYmWihmLk5hJTQwMC0xKSkmJnArK31yZXR1cm4gaChwLDIpfSxcXHJcXG5cXFwiJXdcXFwiOmZ1bmN0aW9uKGYpe3JldHVybiBmLkphfSxcXFwiJVdcXFwiOmZ1bmN0aW9uKGYpe3JldHVybiBoKE1hdGguZmxvb3IoKGYuTWErNy0oZi5KYSs2KSU3KS83KSwyKX0sXFxcIiV5XFxcIjpmdW5jdGlvbihmKXtyZXR1cm4oZi5OYSsxOTAwKS50b1N0cmluZygpLnN1YnN0cmluZygyKX0sXFxcIiVZXFxcIjpmdW5jdGlvbihmKXtyZXR1cm4gZi5OYSsxOTAwfSxcXFwiJXpcXFwiOmZ1bmN0aW9uKGYpe2Y9Zi5yYjt2YXIgcD0wPD1mO2Y9TWF0aC5hYnMoZikvNjA7cmV0dXJuKHA/XFxcIitcXFwiOlxcXCItXFxcIikrU3RyaW5nKFxcXCIwMDAwXFxcIisoZi82MCoxMDArZiU2MCkpLnNsaWNlKC00KX0sXFxcIiVaXFxcIjpmdW5jdGlvbihmKXtyZXR1cm4gZi51Yn0sXFxcIiUlXFxcIjpmdW5jdGlvbigpe3JldHVyblxcXCIlXFxcIn19O2Q9ZC5yZXBsYWNlKC8lJS9nLFxcXCJcXFxceDAwXFxcXHgwMFxcXCIpO2Zvcih5IGluIHYpZC5pbmNsdWRlcyh5KSYmKGQ9ZC5yZXBsYWNlKG5ldyBSZWdFeHAoeSxcXFwiZ1xcXCIpLHZbeV0oZSkpKTtkPWQucmVwbGFjZSgvXFxcXDBcXFxcMC9nLFxcXCIlXFxcIik7eT1OYihkKTtpZih5Lmxlbmd0aD5cXHJcXG5iKXJldHVybiAwO1VhKHksYSk7cmV0dXJuIHkubGVuZ3RoLTF9Ui5VYSgpO1xcclxcbnZhciBQYj1bbnVsbCxMYSxOYSxYYSxaYSwkYSxhYixiYixjYixkYixlYixmYixnYixoYixpYixqYixrYixuYixvYixyYixBYixCYixDYixHYixIYixKYl0sUmI9e2I6ZnVuY3Rpb24oYSl7cmV0dXJuIHFiKGErMjQpKzI0fSxjOmZ1bmN0aW9uKGEsYixkKXsobmV3IFZhKGEpKS5VYShiLGQpO1dhKys7dGhyb3cgYTt9LEw6ZnVuY3Rpb24oYSl7UWIoYSwhQSwxLCFsYSk7Ui5aYSgpfSxsOmZ1bmN0aW9uKGEpe0M/cG9zdE1lc3NhZ2Uoe2NtZDpcXFwiY2xlYW51cFRocmVhZFxcXCIsdGhyZWFkOmF9KTpKYShhKX0sRDpZYSxpOlphLFI6JGEsejphYixCOmJiLFQ6Y2IsUDpkYixJOmViLE86ZmIscDpnYixBOmhiLHg6aWIsUTpqYix5OmtiLHI6ZnVuY3Rpb24oKXt9LGo6ZnVuY3Rpb24oKXtOKFxcXCJUbyB1c2UgZGxvcGVuLCB5b3UgbmVlZCBlbmFibGUgZHluYW1pYyBsaW5raW5nLCBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2Vtc2NyaXB0ZW4tY29yZS9lbXNjcmlwdGVuL3dpa2kvTGlua2luZ1xcXCIpfSxzOmZ1bmN0aW9uKCl7TihcXFwiVG8gdXNlIGRsb3BlbiwgeW91IG5lZWQgZW5hYmxlIGR5bmFtaWMgbGlua2luZywgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9lbXNjcmlwdGVuLWNvcmUvZW1zY3JpcHRlbi93aWtpL0xpbmtpbmdcXFwiKX0sXFxyXFxucTpmdW5jdGlvbigpe3JldHVybiBEYXRlLm5vdygpfSxFOmZ1bmN0aW9uKCl7cmV0dXJuIDIwOTcxNTJ9LFY6ZnVuY3Rpb24oKXtyZXR1cm4hMH0sRjpmdW5jdGlvbihhLGIsZCxlKXtpZihhPT1iKXNldFRpbWVvdXQoKCk9PlBhKGUpKTtlbHNlIGlmKEMpcG9zdE1lc3NhZ2Uoe3RhcmdldFRocmVhZDphLGNtZDpcXFwicHJvY2Vzc1Byb3h5aW5nUXVldWVcXFwiLHF1ZXVlOmV9KTtlbHNle2E9Ui5MYVthXTtpZighYSlyZXR1cm47YS5wb3N0TWVzc2FnZSh7Y21kOlxcXCJwcm9jZXNzUHJveHlpbmdRdWV1ZVxcXCIscXVldWU6ZX0pfXJldHVybiAxfSxLOmZ1bmN0aW9uKCl7cmV0dXJuLTF9LFc6ZnVuY3Rpb24oYSxiKXthPW5ldyBEYXRlKDFFMyptYihhKSk7dCgpW2I+PjI+Pj4wXT1hLmdldFVUQ1NlY29uZHMoKTt0KClbYis0Pj4yPj4+MF09YS5nZXRVVENNaW51dGVzKCk7dCgpW2IrOD4+Mj4+PjBdPWEuZ2V0VVRDSG91cnMoKTt0KClbYisxMj4+Mj4+PjBdPWEuZ2V0VVRDRGF0ZSgpO3QoKVtiKzE2Pj4yPj4+XFxyXFxuMF09YS5nZXRVVENNb250aCgpO3QoKVtiKzIwPj4yPj4+MF09YS5nZXRVVENGdWxsWWVhcigpLTE5MDA7dCgpW2IrMjQ+PjI+Pj4wXT1hLmdldFVUQ0RheSgpO2E9KGEuZ2V0VGltZSgpLURhdGUuVVRDKGEuZ2V0VVRDRnVsbFllYXIoKSwwLDEsMCwwLDAsMCkpLzg2NEU1fDA7dCgpW2IrMjg+PjI+Pj4wXT1hfSxYOmZ1bmN0aW9uKGEsYil7YT1uZXcgRGF0ZSgxRTMqbWIoYSkpO3QoKVtiPj4yPj4+MF09YS5nZXRTZWNvbmRzKCk7dCgpW2IrND4+Mj4+PjBdPWEuZ2V0TWludXRlcygpO3QoKVtiKzg+PjI+Pj4wXT1hLmdldEhvdXJzKCk7dCgpW2IrMTI+PjI+Pj4wXT1hLmdldERhdGUoKTt0KClbYisxNj4+Mj4+PjBdPWEuZ2V0TW9udGgoKTt0KClbYisyMD4+Mj4+PjBdPWEuZ2V0RnVsbFllYXIoKS0xOTAwO3QoKVtiKzI0Pj4yPj4+MF09YS5nZXREYXkoKTt2YXIgZD1uZXcgRGF0ZShhLmdldEZ1bGxZZWFyKCksMCwxKSxlPShhLmdldFRpbWUoKS1kLmdldFRpbWUoKSkvODY0RTV8MDt0KClbYitcXHJcXG4yOD4+Mj4+PjBdPWU7dCgpW2IrMzY+PjI+Pj4wXT0tKDYwKmEuZ2V0VGltZXpvbmVPZmZzZXQoKSk7ZT0obmV3IERhdGUoYS5nZXRGdWxsWWVhcigpLDYsMSkpLmdldFRpbWV6b25lT2Zmc2V0KCk7ZD1kLmdldFRpbWV6b25lT2Zmc2V0KCk7YT0oZSE9ZCYmYS5nZXRUaW1lem9uZU9mZnNldCgpPT1NYXRoLm1pbihkLGUpKXwwO3QoKVtiKzMyPj4yPj4+MF09YX0sWTpmdW5jdGlvbihhKXt2YXIgYj1uZXcgRGF0ZSh0KClbYSsyMD4+Mj4+PjBdKzE5MDAsdCgpW2ErMTY+PjI+Pj4wXSx0KClbYSsxMj4+Mj4+PjBdLHQoKVthKzg+PjI+Pj4wXSx0KClbYSs0Pj4yPj4+MF0sdCgpW2E+PjI+Pj4wXSwwKSxkPXQoKVthKzMyPj4yPj4+MF0sZT1iLmdldFRpbWV6b25lT2Zmc2V0KCksZz1uZXcgRGF0ZShiLmdldEZ1bGxZZWFyKCksMCwxKSxoPShuZXcgRGF0ZShiLmdldEZ1bGxZZWFyKCksNiwxKSkuZ2V0VGltZXpvbmVPZmZzZXQoKSxuPWcuZ2V0VGltZXpvbmVPZmZzZXQoKSx1PU1hdGgubWluKG4sXFxyXFxuaCk7MD5kP3QoKVthKzMyPj4yPj4+MF09TnVtYmVyKGghPW4mJnU9PWUpOjA8ZCE9KHU9PWUpJiYoaD1NYXRoLm1heChuLGgpLGIuc2V0VGltZShiLmdldFRpbWUoKSs2RTQqKCgwPGQ/dTpoKS1lKSkpO3QoKVthKzI0Pj4yPj4+MF09Yi5nZXREYXkoKTtkPShiLmdldFRpbWUoKS1nLmdldFRpbWUoKSkvODY0RTV8MDt0KClbYSsyOD4+Mj4+PjBdPWQ7dCgpW2E+PjI+Pj4wXT1iLmdldFNlY29uZHMoKTt0KClbYSs0Pj4yPj4+MF09Yi5nZXRNaW51dGVzKCk7dCgpW2ErOD4+Mj4+PjBdPWIuZ2V0SG91cnMoKTt0KClbYSsxMj4+Mj4+PjBdPWIuZ2V0RGF0ZSgpO3QoKVthKzE2Pj4yPj4+MF09Yi5nZXRNb250aCgpO3JldHVybiBiLmdldFRpbWUoKS8xRTN8MH0sRzpuYixIOm9iLFo6c2IsZDpmdW5jdGlvbigpe04oXFxcIlxcXCIpfSxtOmZ1bmN0aW9uKCl7aWYoIUImJiFBKXt2YXIgYT1cXFwiQmxvY2tpbmcgb24gdGhlIG1haW4gdGhyZWFkIGlzIHZlcnkgZGFuZ2Vyb3VzLCBzZWUgaHR0cHM6Ly9lbXNjcmlwdGVuLm9yZy9kb2NzL3BvcnRpbmcvcHRocmVhZHMuaHRtbCNibG9ja2luZy1vbi10aGUtbWFpbi1icm93c2VyLXRocmVhZFxcXCI7XFxyXFxuWHx8KFg9e30pO1hbYV18fChYW2FdPTEsQiYmKGE9XFxcIndhcm5pbmc6IFxcXCIrYSksTChhKSl9fSx3OmZ1bmN0aW9uKCl7cmV0dXJuIDQyOTQ5MDE3NjB9LGY6dGIsUzpmdW5jdGlvbihhLGIsZCl7cSgpLmNvcHlXaXRoaW4oYT4+PjAsYj4+PjAsYitkPj4+MCl9LGc6ZnVuY3Rpb24oKXtyZXR1cm4gQj8oX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgb3MgKi8gXFxcIj9hZWRiXFxcIikuY3B1cykoKS5sZW5ndGg6bmF2aWdhdG9yLmhhcmR3YXJlQ29uY3VycmVuY3l9LEo6ZnVuY3Rpb24oYSxiLGQpe3diLmxlbmd0aD1iO2Q+Pj0zO2Zvcih2YXIgZT0wO2U8YjtlKyspd2JbZV09ZWEoKVtkK2U+Pj4wXTtyZXR1cm4oMD5hP0lhWy1hLTFdOlBiW2FdKS5hcHBseShudWxsLHdiKX0sdjpmdW5jdGlvbihhKXt2YXIgYj1xKCkubGVuZ3RoO2E+Pj49MDtpZihhPD1ifHw0Mjk0OTAxNzYwPGEpcmV0dXJuITE7Zm9yKHZhciBkPTE7ND49ZDtkKj0yKXt2YXIgZT1iKigxKy4yL2QpO2U9TWF0aC5taW4oZSxhKzEwMDY2MzI5Nik7dmFyIGc9TWF0aDtlPU1hdGgubWF4KGEsXFxyXFxuZSk7Zz1nLm1pbi5jYWxsKGcsNDI5NDkwMTc2MCxlKyg2NTUzNi1lJTY1NTM2KSU2NTUzNik7YTp7dHJ5e2suZ3JvdyhnLWwuYnl0ZUxlbmd0aCs2NTUzNT4+PjE2KTttKGsuYnVmZmVyKTt2YXIgaD0xO2JyZWFrIGF9Y2F0Y2gobil7fWg9dm9pZCAwfWlmKGgpcmV0dXJuITB9cmV0dXJuITF9LFU6ZnVuY3Rpb24oKXt0aHJvd1xcXCJ1bndpbmRcXFwiO30sTTpBYixOOkJiLGs6TWEsaDpDYixvOkdiLHQ6SGIsbjpKYix1OlksYTprfHx4Lndhc21NZW1vcnksQzpPYixlOmZ1bmN0aW9uKGEsYixkLGUpe3JldHVybiBPYihhLGIsZCxlKX19O1xcclxcbihmdW5jdGlvbigpe2Z1bmN0aW9uIGEoZyxoKXt4LmFzbT1nLmV4cG9ydHM7Ui4kYS5wdXNoKHguYXNtLndhKTt6YT14LmFzbS56YTtCYS51bnNoaWZ0KHguYXNtLl8pO3JhPWg7Q3x8KE8tLSx4Lm1vbml0b3JSdW5EZXBlbmRlbmNpZXMmJngubW9uaXRvclJ1bkRlcGVuZGVuY2llcyhPKSwwPT1PJiYobnVsbCE9PUVhJiYoY2xlYXJJbnRlcnZhbChFYSksRWE9bnVsbCksUCYmKGc9UCxQPW51bGwsZygpKSkpfWZ1bmN0aW9uIGIoZyl7YShnLmluc3RhbmNlLGcubW9kdWxlKX1mdW5jdGlvbiBkKGcpe3JldHVybiBIYSgpLnRoZW4oZnVuY3Rpb24oaCl7cmV0dXJuIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKGgsZSl9KS50aGVuKGZ1bmN0aW9uKGgpe3JldHVybiBofSkudGhlbihnLGZ1bmN0aW9uKGgpe0woXFxcImZhaWxlZCB0byBhc3luY2hyb25vdXNseSBwcmVwYXJlIHdhc206IFxcXCIraCk7TihoKX0pfXZhciBlPXthOlJifTtDfHwoTysrLHgubW9uaXRvclJ1bkRlcGVuZGVuY2llcyYmeC5tb25pdG9yUnVuRGVwZW5kZW5jaWVzKE8pKTtcXHJcXG5pZih4Lmluc3RhbnRpYXRlV2FzbSl0cnl7cmV0dXJuIHguaW5zdGFudGlhdGVXYXNtKGUsYSl9Y2F0Y2goZyl7cmV0dXJuIEwoXFxcIk1vZHVsZS5pbnN0YW50aWF0ZVdhc20gY2FsbGJhY2sgZmFpbGVkIHdpdGggZXJyb3I6IFxcXCIrZyksITF9KGZ1bmN0aW9uKCl7cmV0dXJuIE18fFxcXCJmdW5jdGlvblxcXCIhPXR5cGVvZiBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZVN0cmVhbWluZ3x8RmEoKXx8US5zdGFydHNXaXRoKFxcXCJmaWxlOi8vXFxcIil8fEJ8fFxcXCJmdW5jdGlvblxcXCIhPXR5cGVvZiBmZXRjaD9kKGIpOmZldGNoKFEse2NyZWRlbnRpYWxzOlxcXCJzYW1lLW9yaWdpblxcXCJ9KS50aGVuKGZ1bmN0aW9uKGcpe3JldHVybiBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZVN0cmVhbWluZyhnLGUpLnRoZW4oYixmdW5jdGlvbihoKXtMKFxcXCJ3YXNtIHN0cmVhbWluZyBjb21waWxlIGZhaWxlZDogXFxcIitoKTtMKFxcXCJmYWxsaW5nIGJhY2sgdG8gQXJyYXlCdWZmZXIgaW5zdGFudGlhdGlvblxcXCIpO3JldHVybiBkKGIpfSl9KX0pKCkuY2F0Y2goaWEpO1xcclxcbnJldHVybnt9fSkoKTt4Ll9fX3dhc21fY2FsbF9jdG9ycz1mdW5jdGlvbigpe3JldHVybih4Ll9fX3dhc21fY2FsbF9jdG9ycz14LmFzbS5fKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydEluaXQ9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0SW5pdD14LmFzbS4kKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydENyZWF0ZVNlc3Npb25PcHRpb25zPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydENyZWF0ZVNlc3Npb25PcHRpb25zPXguYXNtLmFhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydEFwcGVuZEV4ZWN1dGlvblByb3ZpZGVyPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEFwcGVuZEV4ZWN1dGlvblByb3ZpZGVyPXguYXNtLmJhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydEFkZFNlc3Npb25Db25maWdFbnRyeT1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRBZGRTZXNzaW9uQ29uZmlnRW50cnk9eC5hc20uY2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XFxyXFxueC5fT3J0UmVsZWFzZVNlc3Npb25PcHRpb25zPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucz14LmFzbS5kYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRDcmVhdGVTZXNzaW9uPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydENyZWF0ZVNlc3Npb249eC5hc20uZWEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0UmVsZWFzZVNlc3Npb249ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0UmVsZWFzZVNlc3Npb249eC5hc20uZmEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0R2V0SW5wdXRDb3VudD1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRHZXRJbnB1dENvdW50PXguYXNtLmdhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydEdldE91dHB1dENvdW50PWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEdldE91dHB1dENvdW50PXguYXNtLmhhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O1xcclxcbnguX09ydEdldElucHV0TmFtZT1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRHZXRJbnB1dE5hbWU9eC5hc20uaWEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0R2V0T3V0cHV0TmFtZT1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRHZXRPdXRwdXROYW1lPXguYXNtLmphKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydEZyZWU9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0RnJlZT14LmFzbS5rYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRDcmVhdGVUZW5zb3I9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0Q3JlYXRlVGVuc29yPXguYXNtLmxhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydEdldFRlbnNvckRhdGE9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0R2V0VGVuc29yRGF0YT14LmFzbS5tYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtcXHJcXG54Ll9PcnRSZWxlYXNlVGVuc29yPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydFJlbGVhc2VUZW5zb3I9eC5hc20ubmEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0Q3JlYXRlUnVuT3B0aW9ucz1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRDcmVhdGVSdW5PcHRpb25zPXguYXNtLm9hKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydEFkZFJ1bkNvbmZpZ0VudHJ5PWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEFkZFJ1bkNvbmZpZ0VudHJ5PXguYXNtLnBhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydFJlbGVhc2VSdW5PcHRpb25zPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydFJlbGVhc2VSdW5PcHRpb25zPXguYXNtLnFhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydFJ1bj1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRSdW49eC5hc20ucmEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XFxyXFxueC5fT3J0RW5kUHJvZmlsaW5nPWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEVuZFByb2ZpbGluZz14LmFzbS5zYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt2YXIgVD14Ll9wdGhyZWFkX3NlbGY9ZnVuY3Rpb24oKXtyZXR1cm4oVD14Ll9wdGhyZWFkX3NlbGY9eC5hc20udGEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0scWI9eC5fbWFsbG9jPWZ1bmN0aW9uKCl7cmV0dXJuKHFiPXguX21hbGxvYz14LmFzbS51YSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9mcmVlPWZ1bmN0aW9uKCl7cmV0dXJuKHguX2ZyZWU9eC5hc20udmEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fX2Vtc2NyaXB0ZW5fdGxzX2luaXQ9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fX2Vtc2NyaXB0ZW5fdGxzX2luaXQ9eC5hc20ud2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XFxyXFxudmFyIFFiPXguX19lbXNjcmlwdGVuX3RocmVhZF9pbml0PWZ1bmN0aW9uKCl7cmV0dXJuKFFiPXguX19lbXNjcmlwdGVuX3RocmVhZF9pbml0PXguYXNtLnhhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX19lbXNjcmlwdGVuX3RocmVhZF9jcmFzaGVkPWZ1bmN0aW9uKCl7cmV0dXJuKHguX19lbXNjcmlwdGVuX3RocmVhZF9jcmFzaGVkPXguYXNtLnlhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O1xcclxcbnZhciB2Yj14Ll9lbXNjcmlwdGVuX3J1bl9pbl9tYWluX3J1bnRpbWVfdGhyZWFkX2pzPWZ1bmN0aW9uKCl7cmV0dXJuKHZiPXguX2Vtc2NyaXB0ZW5fcnVuX2luX21haW5fcnVudGltZV90aHJlYWRfanM9eC5hc20uQWEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sbGI9eC5fX2Vtc2NyaXB0ZW5fcHJveHlfZXhlY3V0ZV90YXNrX3F1ZXVlPWZ1bmN0aW9uKCl7cmV0dXJuKGxiPXguX19lbXNjcmlwdGVuX3Byb3h5X2V4ZWN1dGVfdGFza19xdWV1ZT14LmFzbS5CYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxPYT14Ll9fZW1zY3JpcHRlbl90aHJlYWRfZnJlZV9kYXRhPWZ1bmN0aW9uKCl7cmV0dXJuKE9hPXguX19lbXNjcmlwdGVuX3RocmVhZF9mcmVlX2RhdGE9eC5hc20uQ2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sVGE9eC5fX2Vtc2NyaXB0ZW5fdGhyZWFkX2V4aXQ9ZnVuY3Rpb24oKXtyZXR1cm4oVGE9eC5fX2Vtc2NyaXB0ZW5fdGhyZWFkX2V4aXQ9eC5hc20uRGEpLmFwcGx5KG51bGwsXFxyXFxuYXJndW1lbnRzKX0sU2E9eC5fZW1zY3JpcHRlbl9zdGFja19zZXRfbGltaXRzPWZ1bmN0aW9uKCl7cmV0dXJuKFNhPXguX2Vtc2NyaXB0ZW5fc3RhY2tfc2V0X2xpbWl0cz14LmFzbS5FYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxSYT14LnN0YWNrU2F2ZT1mdW5jdGlvbigpe3JldHVybihSYT14LnN0YWNrU2F2ZT14LmFzbS5GYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxWPXguc3RhY2tSZXN0b3JlPWZ1bmN0aW9uKCl7cmV0dXJuKFY9eC5zdGFja1Jlc3RvcmU9eC5hc20uR2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sdWI9eC5zdGFja0FsbG9jPWZ1bmN0aW9uKCl7cmV0dXJuKHViPXguc3RhY2tBbGxvYz14LmFzbS5IYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9fX2N4YV9pc19wb2ludGVyX3R5cGU9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fX19jeGFfaXNfcG9pbnRlcl90eXBlPXguYXNtLklhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guVVRGOFRvU3RyaW5nPXZhO1xcclxcbnguc3RyaW5nVG9VVEY4PWZ1bmN0aW9uKGEsYixkKXtyZXR1cm4gd2EoYSxxKCksYixkKX07eC5sZW5ndGhCeXRlc1VURjg9eGE7eC5rZWVwUnVudGltZUFsaXZlPWZ1bmN0aW9uKCl7cmV0dXJuIG5vRXhpdFJ1bnRpbWV9O3gud2FzbU1lbW9yeT1rO3guc3RhY2tTYXZlPVJhO3guc3RhY2tSZXN0b3JlPVY7eC5zdGFja0FsbG9jPXViO3guRXhpdFN0YXR1cz1LO3guUFRocmVhZD1SO3ZhciBTYjtQPWZ1bmN0aW9uIFRiKCl7U2J8fFViKCk7U2J8fChQPVRiKX07XFxyXFxuZnVuY3Rpb24gVWIoKXtmdW5jdGlvbiBhKCl7aWYoIVNiJiYoU2I9ITAseC5jYWxsZWRSdW49ITAsIXNhKSl7Q3x8VShCYSk7aGEoeCk7aWYoeC5vblJ1bnRpbWVJbml0aWFsaXplZCl4Lm9uUnVudGltZUluaXRpYWxpemVkKCk7aWYoIUMpe2lmKHgucG9zdFJ1bilmb3IoXFxcImZ1bmN0aW9uXFxcIj09dHlwZW9mIHgucG9zdFJ1biYmKHgucG9zdFJ1bj1beC5wb3N0UnVuXSk7eC5wb3N0UnVuLmxlbmd0aDspe3ZhciBiPXgucG9zdFJ1bi5zaGlmdCgpO0NhLnVuc2hpZnQoYil9VShDYSl9fX1pZighKDA8TykpaWYoQyloYSh4KSxDfHxVKEJhKSxwb3N0TWVzc2FnZSh7Y21kOlxcXCJsb2FkZWRcXFwifSk7ZWxzZXtpZih4LnByZVJ1bilmb3IoXFxcImZ1bmN0aW9uXFxcIj09dHlwZW9mIHgucHJlUnVuJiYoeC5wcmVSdW49W3gucHJlUnVuXSk7eC5wcmVSdW4ubGVuZ3RoOylEYSgpO1UoQWEpOzA8T3x8KHguc2V0U3RhdHVzPyh4LnNldFN0YXR1cyhcXFwiUnVubmluZy4uLlxcXCIpLHNldFRpbWVvdXQoZnVuY3Rpb24oKXtzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7eC5zZXRTdGF0dXMoXFxcIlxcXCIpfSxcXHJcXG4xKTthKCl9LDEpKTphKCkpfX1pZih4LnByZUluaXQpZm9yKFxcXCJmdW5jdGlvblxcXCI9PXR5cGVvZiB4LnByZUluaXQmJih4LnByZUluaXQ9W3gucHJlSW5pdF0pOzA8eC5wcmVJbml0Lmxlbmd0aDspeC5wcmVJbml0LnBvcCgpKCk7VWIoKTtcXHJcXG5cXHJcXG5cXHJcXG4gIHJldHVybiBvcnRXYXNtVGhyZWFkZWQucmVhZHlcXHJcXG59XFxyXFxuKTtcXHJcXG59KSgpO1xcclxcbmlmICh0cnVlKVxcclxcbiAgbW9kdWxlLmV4cG9ydHMgPSBvcnRXYXNtVGhyZWFkZWQ7XFxyXFxuZWxzZSB7fVxcclxcblxcblxcbi8qKiovIH0pLFxcblxcbi8qKiovIFxcXCIuL2xpYi93YXNtL2JpbmRpbmcvb3J0LXdhc20uanNcXFwiOlxcbi8qISoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqISpcXFxcXFxuICAhKioqIC4vbGliL3dhc20vYmluZGluZy9vcnQtd2FzbS5qcyAqKiohXFxuICBcXFxcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXFxuLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4ge1xcblxcbnZhciBfX2ZpbGVuYW1lID0gXFxcIi9pbmRleC5qc1xcXCI7XFxudmFyIF9fZGlybmFtZSA9IFxcXCIvXFxcIjtcXG5cXHJcXG52YXIgb3J0V2FzbSA9ICgoKSA9PiB7XFxyXFxuICB2YXIgX3NjcmlwdERpciA9IHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgZG9jdW1lbnQuY3VycmVudFNjcmlwdCA/IGRvY3VtZW50LmN1cnJlbnRTY3JpcHQuc3JjIDogdW5kZWZpbmVkO1xcclxcbiAgaWYgKHRydWUpIF9zY3JpcHREaXIgPSBfc2NyaXB0RGlyIHx8IF9fZmlsZW5hbWU7XFxyXFxuICByZXR1cm4gKFxcclxcbmZ1bmN0aW9uKG9ydFdhc20pIHtcXHJcXG4gIG9ydFdhc20gPSBvcnRXYXNtIHx8IHt9O1xcclxcblxcclxcblxcclxcbm51bGw7dmFyIGI7Ynx8KGI9dHlwZW9mIG9ydFdhc20gIT09ICd1bmRlZmluZWQnID8gb3J0V2FzbSA6IHt9KTt2YXIgYWEsaztiLnJlYWR5PW5ldyBQcm9taXNlKGZ1bmN0aW9uKGEsYyl7YWE9YTtrPWN9KTt2YXIgYmE9T2JqZWN0LmFzc2lnbih7fSxiKSxwPVxcXCIuL3RoaXMucHJvZ3JhbVxcXCIsdD0oYSxjKT0+e3Rocm93IGM7fSxjYT1cXFwib2JqZWN0XFxcIj09dHlwZW9mIHdpbmRvdyx1PVxcXCJmdW5jdGlvblxcXCI9PXR5cGVvZiBpbXBvcnRTY3JpcHRzLHg9XFxcIm9iamVjdFxcXCI9PXR5cGVvZiBwcm9jZXNzJiZcXFwib2JqZWN0XFxcIj09dHlwZW9mIHByb2Nlc3MudmVyc2lvbnMmJlxcXCJzdHJpbmdcXFwiPT10eXBlb2YgcHJvY2Vzcy52ZXJzaW9ucy5ub2RlLHk9XFxcIlxcXCIseixBLEMsZnMsRCxFO1xcclxcbmlmKHgpeT11PyhfX3dlYnBhY2tfcmVxdWlyZV9fKC8qISBwYXRoICovIFxcXCI/NzVjNlxcXCIpLmRpcm5hbWUpKHkpK1xcXCIvXFxcIjpfX2Rpcm5hbWUrXFxcIi9cXFwiLEU9KCk9PntEfHwoZnM9X193ZWJwYWNrX3JlcXVpcmVfXygvKiEgZnMgKi8gXFxcIj82M2M4XFxcIiksRD1fX3dlYnBhY2tfcmVxdWlyZV9fKC8qISBwYXRoICovIFxcXCI/NzVjNlxcXCIpKX0sej1mdW5jdGlvbihhLGMpe0UoKTthPUQubm9ybWFsaXplKGEpO3JldHVybiBmcy5yZWFkRmlsZVN5bmMoYSxjP3ZvaWQgMDpcXFwidXRmOFxcXCIpfSxDPWE9PnthPXooYSwhMCk7YS5idWZmZXJ8fChhPW5ldyBVaW50OEFycmF5KGEpKTtyZXR1cm4gYX0sQT0oYSxjLGUpPT57RSgpO2E9RC5ub3JtYWxpemUoYSk7ZnMucmVhZEZpbGUoYSxmdW5jdGlvbihmLGcpe2Y/ZShmKTpjKGcuYnVmZmVyKX0pfSwxPHByb2Nlc3MuYXJndi5sZW5ndGgmJihwPXByb2Nlc3MuYXJndlsxXS5yZXBsYWNlKC9cXFxcXFxcXC9nLFxcXCIvXFxcIikpLHByb2Nlc3MuYXJndi5zbGljZSgyKSxwcm9jZXNzLm9uKFxcXCJ1bmNhdWdodEV4Y2VwdGlvblxcXCIsZnVuY3Rpb24oYSl7aWYoIShhIGluc3RhbmNlb2YgRikpdGhyb3cgYTt9KSxwcm9jZXNzLm9uKFxcXCJ1bmhhbmRsZWRSZWplY3Rpb25cXFwiLFxcclxcbmZ1bmN0aW9uKGEpe3Rocm93IGE7fSksdD0oYSxjKT0+e2lmKG5vRXhpdFJ1bnRpbWUpdGhyb3cgcHJvY2Vzcy5leGl0Q29kZT1hLGM7YyBpbnN0YW5jZW9mIEZ8fEcoXFxcImV4aXRpbmcgZHVlIHRvIGV4Y2VwdGlvbjogXFxcIitjKTtwcm9jZXNzLmV4aXQoYSl9LGIuaW5zcGVjdD1mdW5jdGlvbigpe3JldHVyblxcXCJbRW1zY3JpcHRlbiBNb2R1bGUgb2JqZWN0XVxcXCJ9O2Vsc2UgaWYoY2F8fHUpdT95PXNlbGYubG9jYXRpb24uaHJlZjpcXFwidW5kZWZpbmVkXFxcIiE9dHlwZW9mIGRvY3VtZW50JiZkb2N1bWVudC5jdXJyZW50U2NyaXB0JiYoeT1kb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYyksX3NjcmlwdERpciYmKHk9X3NjcmlwdERpciksMCE9PXkuaW5kZXhPZihcXFwiYmxvYjpcXFwiKT95PXkuc3Vic3RyKDAseS5yZXBsYWNlKC9bPyNdLiovLFxcXCJcXFwiKS5sYXN0SW5kZXhPZihcXFwiL1xcXCIpKzEpOnk9XFxcIlxcXCIsej1hPT57dmFyIGM9bmV3IFhNTEh0dHBSZXF1ZXN0O2Mub3BlbihcXFwiR0VUXFxcIixhLCExKTtjLnNlbmQobnVsbCk7cmV0dXJuIGMucmVzcG9uc2VUZXh0fSxcXHJcXG51JiYoQz1hPT57dmFyIGM9bmV3IFhNTEh0dHBSZXF1ZXN0O2Mub3BlbihcXFwiR0VUXFxcIixhLCExKTtjLnJlc3BvbnNlVHlwZT1cXFwiYXJyYXlidWZmZXJcXFwiO2Muc2VuZChudWxsKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYy5yZXNwb25zZSl9KSxBPShhLGMsZSk9Pnt2YXIgZj1uZXcgWE1MSHR0cFJlcXVlc3Q7Zi5vcGVuKFxcXCJHRVRcXFwiLGEsITApO2YucmVzcG9uc2VUeXBlPVxcXCJhcnJheWJ1ZmZlclxcXCI7Zi5vbmxvYWQ9KCk9PnsyMDA9PWYuc3RhdHVzfHwwPT1mLnN0YXR1cyYmZi5yZXNwb25zZT9jKGYucmVzcG9uc2UpOmUoKX07Zi5vbmVycm9yPWU7Zi5zZW5kKG51bGwpfTt2YXIgZGE9Yi5wcmludHx8Y29uc29sZS5sb2cuYmluZChjb25zb2xlKSxHPWIucHJpbnRFcnJ8fGNvbnNvbGUud2Fybi5iaW5kKGNvbnNvbGUpO09iamVjdC5hc3NpZ24oYixiYSk7YmE9bnVsbDtiLnRoaXNQcm9ncmFtJiYocD1iLnRoaXNQcm9ncmFtKTtiLnF1aXQmJih0PWIucXVpdCk7dmFyIEg7XFxyXFxuYi53YXNtQmluYXJ5JiYoSD1iLndhc21CaW5hcnkpO3ZhciBub0V4aXRSdW50aW1lPWIubm9FeGl0UnVudGltZXx8ITA7XFxcIm9iamVjdFxcXCIhPXR5cGVvZiBXZWJBc3NlbWJseSYmSShcXFwibm8gbmF0aXZlIHdhc20gc3VwcG9ydCBkZXRlY3RlZFxcXCIpO3ZhciBKLEs9ITEsZWE9XFxcInVuZGVmaW5lZFxcXCIhPXR5cGVvZiBUZXh0RGVjb2Rlcj9uZXcgVGV4dERlY29kZXIoXFxcInV0ZjhcXFwiKTp2b2lkIDA7XFxyXFxuZnVuY3Rpb24gZmEoYSxjLGUpe2M+Pj49MDt2YXIgZj1jK2U7Zm9yKGU9YzthW2VdJiYhKGU+PWYpOykrK2U7aWYoMTY8ZS1jJiZhLmJ1ZmZlciYmZWEpcmV0dXJuIGVhLmRlY29kZShhLnN1YmFycmF5KGMsZSkpO2ZvcihmPVxcXCJcXFwiO2M8ZTspe3ZhciBnPWFbYysrXTtpZihnJjEyOCl7dmFyIGg9YVtjKytdJjYzO2lmKDE5Mj09KGcmMjI0KSlmKz1TdHJpbmcuZnJvbUNoYXJDb2RlKChnJjMxKTw8NnxoKTtlbHNle3ZhciBsPWFbYysrXSY2MztnPTIyND09KGcmMjQwKT8oZyYxNSk8PDEyfGg8PDZ8bDooZyY3KTw8MTh8aDw8MTJ8bDw8NnxhW2MrK10mNjM7NjU1MzY+Zz9mKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGcpOihnLT02NTUzNixmKz1TdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2fGc+PjEwLDU2MzIwfGcmMTAyMykpfX1lbHNlIGYrPVN0cmluZy5mcm9tQ2hhckNvZGUoZyl9cmV0dXJuIGZ9ZnVuY3Rpb24gTChhLGMpe3JldHVybihhPj4+PTApP2ZhKE0sYSxjKTpcXFwiXFxcIn1cXHJcXG5mdW5jdGlvbiBOKGEsYyxlLGYpe2U+Pj49MDtpZighKDA8ZikpcmV0dXJuIDA7dmFyIGc9ZTtmPWUrZi0xO2Zvcih2YXIgaD0wO2g8YS5sZW5ndGg7KytoKXt2YXIgbD1hLmNoYXJDb2RlQXQoaCk7aWYoNTUyOTY8PWwmJjU3MzQzPj1sKXt2YXIgcT1hLmNoYXJDb2RlQXQoKytoKTtsPTY1NTM2KygobCYxMDIzKTw8MTApfHEmMTAyM31pZigxMjc+PWwpe2lmKGU+PWYpYnJlYWs7Y1tlKys+Pj4wXT1sfWVsc2V7aWYoMjA0Nz49bCl7aWYoZSsxPj1mKWJyZWFrO2NbZSsrPj4+MF09MTkyfGw+PjZ9ZWxzZXtpZig2NTUzNT49bCl7aWYoZSsyPj1mKWJyZWFrO2NbZSsrPj4+MF09MjI0fGw+PjEyfWVsc2V7aWYoZSszPj1mKWJyZWFrO2NbZSsrPj4+MF09MjQwfGw+PjE4O2NbZSsrPj4+MF09MTI4fGw+PjEyJjYzfWNbZSsrPj4+MF09MTI4fGw+PjYmNjN9Y1tlKys+Pj4wXT0xMjh8bCY2M319Y1tlPj4+MF09MDtyZXR1cm4gZS1nfVxcclxcbmZ1bmN0aW9uIE8oYSl7Zm9yKHZhciBjPTAsZT0wO2U8YS5sZW5ndGg7KytlKXt2YXIgZj1hLmNoYXJDb2RlQXQoZSk7MTI3Pj1mP2MrKzoyMDQ3Pj1mP2MrPTI6NTUyOTY8PWYmJjU3MzQzPj1mPyhjKz00LCsrZSk6Yys9M31yZXR1cm4gY312YXIgaGEsUCxNLFEsUjtmdW5jdGlvbiBpYSgpe3ZhciBhPUouYnVmZmVyO2hhPWE7Yi5IRUFQOD1QPW5ldyBJbnQ4QXJyYXkoYSk7Yi5IRUFQMTY9bmV3IEludDE2QXJyYXkoYSk7Yi5IRUFQMzI9UT1uZXcgSW50MzJBcnJheShhKTtiLkhFQVBVOD1NPW5ldyBVaW50OEFycmF5KGEpO2IuSEVBUFUxNj1uZXcgVWludDE2QXJyYXkoYSk7Yi5IRUFQVTMyPVI9bmV3IFVpbnQzMkFycmF5KGEpO2IuSEVBUEYzMj1uZXcgRmxvYXQzMkFycmF5KGEpO2IuSEVBUEY2ND1uZXcgRmxvYXQ2NEFycmF5KGEpfXZhciBqYT1bXSxrYT1bXSxsYT1bXTtmdW5jdGlvbiBtYSgpe3ZhciBhPWIucHJlUnVuLnNoaWZ0KCk7amEudW5zaGlmdChhKX1cXHJcXG52YXIgUz0wLFQ9bnVsbCxVPW51bGw7ZnVuY3Rpb24gSShhKXtpZihiLm9uQWJvcnQpYi5vbkFib3J0KGEpO2E9XFxcIkFib3J0ZWQoXFxcIithK1xcXCIpXFxcIjtHKGEpO0s9ITA7YT1uZXcgV2ViQXNzZW1ibHkuUnVudGltZUVycm9yKGErXFxcIi4gQnVpbGQgd2l0aCAtc0FTU0VSVElPTlMgZm9yIG1vcmUgaW5mby5cXFwiKTtrKGEpO3Rocm93IGE7fWZ1bmN0aW9uIG5hKCl7cmV0dXJuIFYuc3RhcnRzV2l0aChcXFwiZGF0YTphcHBsaWNhdGlvbi9vY3RldC1zdHJlYW07YmFzZTY0LFxcXCIpfXZhciBWO1Y9XFxcIm9ydC13YXNtLndhc21cXFwiO2lmKCFuYSgpKXt2YXIgb2E9VjtWPWIubG9jYXRlRmlsZT9iLmxvY2F0ZUZpbGUob2EseSk6eStvYX1mdW5jdGlvbiBwYSgpe3ZhciBhPVY7dHJ5e2lmKGE9PVYmJkgpcmV0dXJuIG5ldyBVaW50OEFycmF5KEgpO2lmKEMpcmV0dXJuIEMoYSk7dGhyb3dcXFwiYm90aCBhc3luYyBhbmQgc3luYyBmZXRjaGluZyBvZiB0aGUgd2FzbSBmYWlsZWRcXFwiO31jYXRjaChjKXtJKGMpfX1cXHJcXG5mdW5jdGlvbiBxYSgpe2lmKCFIJiYoY2F8fHUpKXtpZihcXFwiZnVuY3Rpb25cXFwiPT10eXBlb2YgZmV0Y2gmJiFWLnN0YXJ0c1dpdGgoXFxcImZpbGU6Ly9cXFwiKSlyZXR1cm4gZmV0Y2goVix7Y3JlZGVudGlhbHM6XFxcInNhbWUtb3JpZ2luXFxcIn0pLnRoZW4oZnVuY3Rpb24oYSl7aWYoIWEub2spdGhyb3dcXFwiZmFpbGVkIHRvIGxvYWQgd2FzbSBiaW5hcnkgZmlsZSBhdCAnXFxcIitWK1xcXCInXFxcIjtyZXR1cm4gYS5hcnJheUJ1ZmZlcigpfSkuY2F0Y2goZnVuY3Rpb24oKXtyZXR1cm4gcGEoKX0pO2lmKEEpcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKGEsYyl7QShWLGZ1bmN0aW9uKGUpe2EobmV3IFVpbnQ4QXJyYXkoZSkpfSxjKX0pfXJldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKGZ1bmN0aW9uKCl7cmV0dXJuIHBhKCl9KX1mdW5jdGlvbiBGKGEpe3RoaXMubmFtZT1cXFwiRXhpdFN0YXR1c1xcXCI7dGhpcy5tZXNzYWdlPVxcXCJQcm9ncmFtIHRlcm1pbmF0ZWQgd2l0aCBleGl0KFxcXCIrYStcXFwiKVxcXCI7dGhpcy5zdGF0dXM9YX1cXHJcXG5mdW5jdGlvbiBXKGEpe2Zvcig7MDxhLmxlbmd0aDspYS5zaGlmdCgpKGIpfWZ1bmN0aW9uIHJhKGEpe3RoaXMuc2E9YS0yNDt0aGlzLklhPWZ1bmN0aW9uKGMpe1JbdGhpcy5zYSs0Pj4yPj4+MF09Y307dGhpcy5CYT1mdW5jdGlvbihjKXtSW3RoaXMuc2ErOD4+Mj4+PjBdPWN9O3RoaXMuR2E9ZnVuY3Rpb24oKXtRW3RoaXMuc2E+PjI+Pj4wXT0wfTt0aGlzLkFhPWZ1bmN0aW9uKCl7UFt0aGlzLnNhKzEyPj4wPj4+MF09MH07dGhpcy5IYT1mdW5jdGlvbigpe1BbdGhpcy5zYSsxMz4+MD4+PjBdPTB9O3RoaXMueWE9ZnVuY3Rpb24oYyxlKXt0aGlzLnphKCk7dGhpcy5JYShjKTt0aGlzLkJhKGUpO3RoaXMuR2EoKTt0aGlzLkFhKCk7dGhpcy5IYSgpfTt0aGlzLnphPWZ1bmN0aW9uKCl7Ult0aGlzLnNhKzE2Pj4yPj4+MF09MH19dmFyIHNhPTA7ZnVuY3Rpb24gdGEoYSl7dmFyIGM9TyhhKSsxLGU9dWEoYyk7ZSYmTihhLFAsZSxjKTtyZXR1cm4gZX1cXHJcXG5mdW5jdGlvbiB2YShhLGMsZSl7ZnVuY3Rpb24gZih3KXtyZXR1cm4odz13LnRvVGltZVN0cmluZygpLm1hdGNoKC9cXFxcKChbQS1aYS16IF0rKVxcXFwpJC8pKT93WzFdOlxcXCJHTVRcXFwifXZhciBnPShuZXcgRGF0ZSkuZ2V0RnVsbFllYXIoKSxoPW5ldyBEYXRlKGcsMCwxKSxsPW5ldyBEYXRlKGcsNiwxKTtnPWguZ2V0VGltZXpvbmVPZmZzZXQoKTt2YXIgcT1sLmdldFRpbWV6b25lT2Zmc2V0KCk7UVthPj4yPj4+MF09NjAqTWF0aC5tYXgoZyxxKTtRW2M+PjI+Pj4wXT1OdW1iZXIoZyE9cSk7YT1mKGgpO2M9ZihsKTthPXRhKGEpO2M9dGEoYyk7cTxnPyhSW2U+PjI+Pj4wXT1hLFJbZSs0Pj4yPj4+MF09Yyk6KFJbZT4+Mj4+PjBdPWMsUltlKzQ+PjI+Pj4wXT1hKX1mdW5jdGlvbiB3YShhLGMsZSl7d2EueGF8fCh3YS54YT0hMCx2YShhLGMsZSkpfXZhciBBYT17fTtcXHJcXG5mdW5jdGlvbiBCYSgpe2lmKCFDYSl7dmFyIGE9e1VTRVI6XFxcIndlYl91c2VyXFxcIixMT0dOQU1FOlxcXCJ3ZWJfdXNlclxcXCIsUEFUSDpcXFwiL1xcXCIsUFdEOlxcXCIvXFxcIixIT01FOlxcXCIvaG9tZS93ZWJfdXNlclxcXCIsTEFORzooXFxcIm9iamVjdFxcXCI9PXR5cGVvZiBuYXZpZ2F0b3ImJm5hdmlnYXRvci5sYW5ndWFnZXMmJm5hdmlnYXRvci5sYW5ndWFnZXNbMF18fFxcXCJDXFxcIikucmVwbGFjZShcXFwiLVxcXCIsXFxcIl9cXFwiKStcXFwiLlVURi04XFxcIixfOnB8fFxcXCIuL3RoaXMucHJvZ3JhbVxcXCJ9LGM7Zm9yKGMgaW4gQWEpdm9pZCAwPT09QWFbY10/ZGVsZXRlIGFbY106YVtjXT1BYVtjXTt2YXIgZT1bXTtmb3IoYyBpbiBhKWUucHVzaChjK1xcXCI9XFxcIithW2NdKTtDYT1lfXJldHVybiBDYX12YXIgQ2EsRGE9W251bGwsW10sW11dO1xcclxcbmZ1bmN0aW9uIEVhKCl7aWYoXFxcIm9iamVjdFxcXCI9PXR5cGVvZiBjcnlwdG8mJlxcXCJmdW5jdGlvblxcXCI9PXR5cGVvZiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKXt2YXIgYT1uZXcgVWludDhBcnJheSgxKTtyZXR1cm4oKT0+e2NyeXB0by5nZXRSYW5kb21WYWx1ZXMoYSk7cmV0dXJuIGFbMF19fWlmKHgpdHJ5e3ZhciBjPV9fd2VicGFja19yZXF1aXJlX18oLyohIGNyeXB0byAqLyBcXFwiPzg5MmRcXFwiKTtyZXR1cm4oKT0+Yy5yYW5kb21CeXRlcygxKVswXX1jYXRjaChlKXt9cmV0dXJuKCk9PkkoXFxcInJhbmRvbURldmljZVxcXCIpfWZ1bmN0aW9uIFgoYSxjKXtYLndhfHwoWC53YT1FYSgpKTtmb3IodmFyIGU9MDtlPGM7ZSsrKVBbYStlPj4wPj4+MF09WC53YSgpO3JldHVybiAwfWZ1bmN0aW9uIFkoYSl7cmV0dXJuIDA9PT1hJTQmJigwIT09YSUxMDB8fDA9PT1hJTQwMCl9dmFyIEZhPVszMSwyOSwzMSwzMCwzMSwzMCwzMSwzMSwzMCwzMSwzMCwzMV0sR2E9WzMxLDI4LDMxLDMwLDMxLDMwLDMxLDMxLDMwLDMxLDMwLDMxXTtcXHJcXG5mdW5jdGlvbiBIYShhKXt2YXIgYz1BcnJheShPKGEpKzEpO04oYSxjLDAsYy5sZW5ndGgpO3JldHVybiBjfVxcclxcbmZ1bmN0aW9uIElhKGEsYyxlLGYpe2Z1bmN0aW9uIGcoZCxtLG4pe2ZvcihkPVxcXCJudW1iZXJcXFwiPT10eXBlb2YgZD9kLnRvU3RyaW5nKCk6ZHx8XFxcIlxcXCI7ZC5sZW5ndGg8bTspZD1uWzBdK2Q7cmV0dXJuIGR9ZnVuY3Rpb24gaChkLG0pe3JldHVybiBnKGQsbSxcXFwiMFxcXCIpfWZ1bmN0aW9uIGwoZCxtKXtmdW5jdGlvbiBuKHhhKXtyZXR1cm4gMD54YT8tMTowPHhhPzE6MH12YXIgQjswPT09KEI9bihkLmdldEZ1bGxZZWFyKCktbS5nZXRGdWxsWWVhcigpKSkmJjA9PT0oQj1uKGQuZ2V0TW9udGgoKS1tLmdldE1vbnRoKCkpKSYmKEI9bihkLmdldERhdGUoKS1tLmdldERhdGUoKSkpO3JldHVybiBCfWZ1bmN0aW9uIHEoZCl7c3dpdGNoKGQuZ2V0RGF5KCkpe2Nhc2UgMDpyZXR1cm4gbmV3IERhdGUoZC5nZXRGdWxsWWVhcigpLTEsMTEsMjkpO2Nhc2UgMTpyZXR1cm4gZDtjYXNlIDI6cmV0dXJuIG5ldyBEYXRlKGQuZ2V0RnVsbFllYXIoKSwwLDMpO2Nhc2UgMzpyZXR1cm4gbmV3IERhdGUoZC5nZXRGdWxsWWVhcigpLFxcclxcbjAsMik7Y2FzZSA0OnJldHVybiBuZXcgRGF0ZShkLmdldEZ1bGxZZWFyKCksMCwxKTtjYXNlIDU6cmV0dXJuIG5ldyBEYXRlKGQuZ2V0RnVsbFllYXIoKS0xLDExLDMxKTtjYXNlIDY6cmV0dXJuIG5ldyBEYXRlKGQuZ2V0RnVsbFllYXIoKS0xLDExLDMwKX19ZnVuY3Rpb24gdyhkKXt2YXIgbT1kLnFhO2ZvcihkPW5ldyBEYXRlKChuZXcgRGF0ZShkLnJhKzE5MDAsMCwxKSkuZ2V0VGltZSgpKTswPG07KXt2YXIgbj1kLmdldE1vbnRoKCksQj0oWShkLmdldEZ1bGxZZWFyKCkpP0ZhOkdhKVtuXTtpZihtPkItZC5nZXREYXRlKCkpbS09Qi1kLmdldERhdGUoKSsxLGQuc2V0RGF0ZSgxKSwxMT5uP2Quc2V0TW9udGgobisxKTooZC5zZXRNb250aCgwKSxkLnNldEZ1bGxZZWFyKGQuZ2V0RnVsbFllYXIoKSsxKSk7ZWxzZXtkLnNldERhdGUoZC5nZXREYXRlKCkrbSk7YnJlYWt9fW49bmV3IERhdGUoZC5nZXRGdWxsWWVhcigpKzEsMCw0KTttPXEobmV3IERhdGUoZC5nZXRGdWxsWWVhcigpLFxcclxcbjAsNCkpO249cShuKTtyZXR1cm4gMD49bChtLGQpPzA+PWwobixkKT9kLmdldEZ1bGxZZWFyKCkrMTpkLmdldEZ1bGxZZWFyKCk6ZC5nZXRGdWxsWWVhcigpLTF9dmFyIHY9UVtmKzQwPj4yPj4+MF07Zj17RWE6UVtmPj4yPj4+MF0sRGE6UVtmKzQ+PjI+Pj4wXSx0YTpRW2YrOD4+Mj4+PjBdLHZhOlFbZisxMj4+Mj4+PjBdLHVhOlFbZisxNj4+Mj4+PjBdLHJhOlFbZisyMD4+Mj4+PjBdLGxhOlFbZisyND4+Mj4+PjBdLHFhOlFbZisyOD4+Mj4+PjBdLEphOlFbZiszMj4+Mj4+PjBdLENhOlFbZiszNj4+Mj4+PjBdLEZhOnY/TCh2KTpcXFwiXFxcIn07ZT1MKGUpO3Y9e1xcXCIlY1xcXCI6XFxcIiVhICViICVkICVIOiVNOiVTICVZXFxcIixcXFwiJURcXFwiOlxcXCIlbS8lZC8leVxcXCIsXFxcIiVGXFxcIjpcXFwiJVktJW0tJWRcXFwiLFxcXCIlaFxcXCI6XFxcIiViXFxcIixcXFwiJXJcXFwiOlxcXCIlSTolTTolUyAlcFxcXCIsXFxcIiVSXFxcIjpcXFwiJUg6JU1cXFwiLFxcXCIlVFxcXCI6XFxcIiVIOiVNOiVTXFxcIixcXFwiJXhcXFwiOlxcXCIlbS8lZC8leVxcXCIsXFxcIiVYXFxcIjpcXFwiJUg6JU06JVNcXFwiLFxcXCIlRWNcXFwiOlxcXCIlY1xcXCIsXFxcIiVFQ1xcXCI6XFxcIiVDXFxcIixcXFwiJUV4XFxcIjpcXFwiJW0vJWQvJXlcXFwiLFxcclxcblxcXCIlRVhcXFwiOlxcXCIlSDolTTolU1xcXCIsXFxcIiVFeVxcXCI6XFxcIiV5XFxcIixcXFwiJUVZXFxcIjpcXFwiJVlcXFwiLFxcXCIlT2RcXFwiOlxcXCIlZFxcXCIsXFxcIiVPZVxcXCI6XFxcIiVlXFxcIixcXFwiJU9IXFxcIjpcXFwiJUhcXFwiLFxcXCIlT0lcXFwiOlxcXCIlSVxcXCIsXFxcIiVPbVxcXCI6XFxcIiVtXFxcIixcXFwiJU9NXFxcIjpcXFwiJU1cXFwiLFxcXCIlT1NcXFwiOlxcXCIlU1xcXCIsXFxcIiVPdVxcXCI6XFxcIiV1XFxcIixcXFwiJU9VXFxcIjpcXFwiJVVcXFwiLFxcXCIlT1ZcXFwiOlxcXCIlVlxcXCIsXFxcIiVPd1xcXCI6XFxcIiV3XFxcIixcXFwiJU9XXFxcIjpcXFwiJVdcXFwiLFxcXCIlT3lcXFwiOlxcXCIleVxcXCJ9O2Zvcih2YXIgciBpbiB2KWU9ZS5yZXBsYWNlKG5ldyBSZWdFeHAocixcXFwiZ1xcXCIpLHZbcl0pO3ZhciB5YT1cXFwiU3VuZGF5IE1vbmRheSBUdWVzZGF5IFdlZG5lc2RheSBUaHVyc2RheSBGcmlkYXkgU2F0dXJkYXlcXFwiLnNwbGl0KFxcXCIgXFxcIiksemE9XFxcIkphbnVhcnkgRmVicnVhcnkgTWFyY2ggQXByaWwgTWF5IEp1bmUgSnVseSBBdWd1c3QgU2VwdGVtYmVyIE9jdG9iZXIgTm92ZW1iZXIgRGVjZW1iZXJcXFwiLnNwbGl0KFxcXCIgXFxcIik7dj17XFxcIiVhXFxcIjpmdW5jdGlvbihkKXtyZXR1cm4geWFbZC5sYV0uc3Vic3RyaW5nKDAsMyl9LFxcXCIlQVxcXCI6ZnVuY3Rpb24oZCl7cmV0dXJuIHlhW2QubGFdfSxcXFwiJWJcXFwiOmZ1bmN0aW9uKGQpe3JldHVybiB6YVtkLnVhXS5zdWJzdHJpbmcoMCxcXHJcXG4zKX0sXFxcIiVCXFxcIjpmdW5jdGlvbihkKXtyZXR1cm4gemFbZC51YV19LFxcXCIlQ1xcXCI6ZnVuY3Rpb24oZCl7cmV0dXJuIGgoKGQucmErMTkwMCkvMTAwfDAsMil9LFxcXCIlZFxcXCI6ZnVuY3Rpb24oZCl7cmV0dXJuIGgoZC52YSwyKX0sXFxcIiVlXFxcIjpmdW5jdGlvbihkKXtyZXR1cm4gZyhkLnZhLDIsXFxcIiBcXFwiKX0sXFxcIiVnXFxcIjpmdW5jdGlvbihkKXtyZXR1cm4gdyhkKS50b1N0cmluZygpLnN1YnN0cmluZygyKX0sXFxcIiVHXFxcIjpmdW5jdGlvbihkKXtyZXR1cm4gdyhkKX0sXFxcIiVIXFxcIjpmdW5jdGlvbihkKXtyZXR1cm4gaChkLnRhLDIpfSxcXFwiJUlcXFwiOmZ1bmN0aW9uKGQpe2Q9ZC50YTswPT1kP2Q9MTI6MTI8ZCYmKGQtPTEyKTtyZXR1cm4gaChkLDIpfSxcXFwiJWpcXFwiOmZ1bmN0aW9uKGQpe2Zvcih2YXIgbT0wLG49MDtuPD1kLnVhLTE7bSs9KFkoZC5yYSsxOTAwKT9GYTpHYSlbbisrXSk7cmV0dXJuIGgoZC52YSttLDMpfSxcXFwiJW1cXFwiOmZ1bmN0aW9uKGQpe3JldHVybiBoKGQudWErMSwyKX0sXFxcIiVNXFxcIjpmdW5jdGlvbihkKXtyZXR1cm4gaChkLkRhLFxcclxcbjIpfSxcXFwiJW5cXFwiOmZ1bmN0aW9uKCl7cmV0dXJuXFxcIlxcXFxuXFxcIn0sXFxcIiVwXFxcIjpmdW5jdGlvbihkKXtyZXR1cm4gMDw9ZC50YSYmMTI+ZC50YT9cXFwiQU1cXFwiOlxcXCJQTVxcXCJ9LFxcXCIlU1xcXCI6ZnVuY3Rpb24oZCl7cmV0dXJuIGgoZC5FYSwyKX0sXFxcIiV0XFxcIjpmdW5jdGlvbigpe3JldHVyblxcXCJcXFxcdFxcXCJ9LFxcXCIldVxcXCI6ZnVuY3Rpb24oZCl7cmV0dXJuIGQubGF8fDd9LFxcXCIlVVxcXCI6ZnVuY3Rpb24oZCl7cmV0dXJuIGgoTWF0aC5mbG9vcigoZC5xYSs3LWQubGEpLzcpLDIpfSxcXFwiJVZcXFwiOmZ1bmN0aW9uKGQpe3ZhciBtPU1hdGguZmxvb3IoKGQucWErNy0oZC5sYSs2KSU3KS83KTsyPj0oZC5sYSszNzEtZC5xYS0yKSU3JiZtKys7aWYobSk1Mz09bSYmKG49KGQubGErMzcxLWQucWEpJTcsND09bnx8Mz09biYmWShkLnJhKXx8KG09MSkpO2Vsc2V7bT01Mjt2YXIgbj0oZC5sYSs3LWQucWEtMSklNzsoND09bnx8NT09biYmWShkLnJhJTQwMC0xKSkmJm0rK31yZXR1cm4gaChtLDIpfSxcXFwiJXdcXFwiOmZ1bmN0aW9uKGQpe3JldHVybiBkLmxhfSxcXFwiJVdcXFwiOmZ1bmN0aW9uKGQpe3JldHVybiBoKE1hdGguZmxvb3IoKGQucWErXFxyXFxuNy0oZC5sYSs2KSU3KS83KSwyKX0sXFxcIiV5XFxcIjpmdW5jdGlvbihkKXtyZXR1cm4oZC5yYSsxOTAwKS50b1N0cmluZygpLnN1YnN0cmluZygyKX0sXFxcIiVZXFxcIjpmdW5jdGlvbihkKXtyZXR1cm4gZC5yYSsxOTAwfSxcXFwiJXpcXFwiOmZ1bmN0aW9uKGQpe2Q9ZC5DYTt2YXIgbT0wPD1kO2Q9TWF0aC5hYnMoZCkvNjA7cmV0dXJuKG0/XFxcIitcXFwiOlxcXCItXFxcIikrU3RyaW5nKFxcXCIwMDAwXFxcIisoZC82MCoxMDArZCU2MCkpLnNsaWNlKC00KX0sXFxcIiVaXFxcIjpmdW5jdGlvbihkKXtyZXR1cm4gZC5GYX0sXFxcIiUlXFxcIjpmdW5jdGlvbigpe3JldHVyblxcXCIlXFxcIn19O2U9ZS5yZXBsYWNlKC8lJS9nLFxcXCJcXFxceDAwXFxcXHgwMFxcXCIpO2ZvcihyIGluIHYpZS5pbmNsdWRlcyhyKSYmKGU9ZS5yZXBsYWNlKG5ldyBSZWdFeHAocixcXFwiZ1xcXCIpLHZbcl0oZikpKTtlPWUucmVwbGFjZSgvXFxcXDBcXFxcMC9nLFxcXCIlXFxcIik7cj1IYShlKTtpZihyLmxlbmd0aD5jKXJldHVybiAwO1Auc2V0KHIsYT4+PjApO3JldHVybiByLmxlbmd0aC0xfVxcclxcbnZhciBKYT17YTpmdW5jdGlvbihhKXtyZXR1cm4gdWEoYSsyNCkrMjR9LGI6ZnVuY3Rpb24oYSxjLGUpeyhuZXcgcmEoYSkpLnlhKGMsZSk7c2ErKzt0aHJvdyBhO30sZzpmdW5jdGlvbigpe3JldHVybiAwfSxJOmZ1bmN0aW9uKCl7fSx3OmZ1bmN0aW9uKCl7fSx5OmZ1bmN0aW9uKCl7fSxLOmZ1bmN0aW9uKCl7cmV0dXJuIDB9LEc6ZnVuY3Rpb24oKXt9LEM6ZnVuY3Rpb24oKXt9LEY6ZnVuY3Rpb24oKXt9LGs6ZnVuY3Rpb24oKXt9LHg6ZnVuY3Rpb24oKXt9LHU6ZnVuY3Rpb24oKXt9LEg6ZnVuY3Rpb24oKXt9LHY6ZnVuY3Rpb24oKXt9LG46ZnVuY3Rpb24oKXt9LHA6ZnVuY3Rpb24oKXtJKFxcXCJUbyB1c2UgZGxvcGVuLCB5b3UgbmVlZCBlbmFibGUgZHluYW1pYyBsaW5raW5nLCBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2Vtc2NyaXB0ZW4tY29yZS9lbXNjcmlwdGVuL3dpa2kvTGlua2luZ1xcXCIpfSxvOmZ1bmN0aW9uKCl7SShcXFwiVG8gdXNlIGRsb3BlbiwgeW91IG5lZWQgZW5hYmxlIGR5bmFtaWMgbGlua2luZywgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9lbXNjcmlwdGVuLWNvcmUvZW1zY3JpcHRlbi93aWtpL0xpbmtpbmdcXFwiKX0sXFxyXFxubDpmdW5jdGlvbigpe3JldHVybiBEYXRlLm5vdygpfSxMOmZ1bmN0aW9uKCl7cmV0dXJuITB9LE06ZnVuY3Rpb24oYSxjKXthPW5ldyBEYXRlKDFFMyooUlthPj4+Ml0rNDI5NDk2NzI5NipRW2ErND4+PjJdKSk7UVtjPj4yPj4+MF09YS5nZXRVVENTZWNvbmRzKCk7UVtjKzQ+PjI+Pj4wXT1hLmdldFVUQ01pbnV0ZXMoKTtRW2MrOD4+Mj4+PjBdPWEuZ2V0VVRDSG91cnMoKTtRW2MrMTI+PjI+Pj4wXT1hLmdldFVUQ0RhdGUoKTtRW2MrMTY+PjI+Pj4wXT1hLmdldFVUQ01vbnRoKCk7UVtjKzIwPj4yPj4+MF09YS5nZXRVVENGdWxsWWVhcigpLTE5MDA7UVtjKzI0Pj4yPj4+MF09YS5nZXRVVENEYXkoKTtRW2MrMjg+PjI+Pj4wXT0oYS5nZXRUaW1lKCktRGF0ZS5VVEMoYS5nZXRVVENGdWxsWWVhcigpLDAsMSwwLDAsMCwwKSkvODY0RTV8MH0sTjpmdW5jdGlvbihhLGMpe2E9bmV3IERhdGUoMUUzKihSW2E+Pj4yXSs0Mjk0OTY3Mjk2KlFbYSs0Pj4+Ml0pKTtRW2M+PjI+Pj4wXT1hLmdldFNlY29uZHMoKTtcXHJcXG5RW2MrND4+Mj4+PjBdPWEuZ2V0TWludXRlcygpO1FbYys4Pj4yPj4+MF09YS5nZXRIb3VycygpO1FbYysxMj4+Mj4+PjBdPWEuZ2V0RGF0ZSgpO1FbYysxNj4+Mj4+PjBdPWEuZ2V0TW9udGgoKTtRW2MrMjA+PjI+Pj4wXT1hLmdldEZ1bGxZZWFyKCktMTkwMDtRW2MrMjQ+PjI+Pj4wXT1hLmdldERheSgpO3ZhciBlPW5ldyBEYXRlKGEuZ2V0RnVsbFllYXIoKSwwLDEpO1FbYysyOD4+Mj4+PjBdPShhLmdldFRpbWUoKS1lLmdldFRpbWUoKSkvODY0RTV8MDtRW2MrMzY+PjI+Pj4wXT0tKDYwKmEuZ2V0VGltZXpvbmVPZmZzZXQoKSk7dmFyIGY9KG5ldyBEYXRlKGEuZ2V0RnVsbFllYXIoKSw2LDEpKS5nZXRUaW1lem9uZU9mZnNldCgpO2U9ZS5nZXRUaW1lem9uZU9mZnNldCgpO1FbYyszMj4+Mj4+PjBdPShmIT1lJiZhLmdldFRpbWV6b25lT2Zmc2V0KCk9PU1hdGgubWluKGUsZikpfDB9LE86ZnVuY3Rpb24oYSl7dmFyIGM9bmV3IERhdGUoUVthKzIwPj4yPj4+MF0rMTkwMCxRW2ErMTY+PlxcclxcbjI+Pj4wXSxRW2ErMTI+PjI+Pj4wXSxRW2ErOD4+Mj4+PjBdLFFbYSs0Pj4yPj4+MF0sUVthPj4yPj4+MF0sMCksZT1RW2ErMzI+PjI+Pj4wXSxmPWMuZ2V0VGltZXpvbmVPZmZzZXQoKSxnPW5ldyBEYXRlKGMuZ2V0RnVsbFllYXIoKSwwLDEpLGg9KG5ldyBEYXRlKGMuZ2V0RnVsbFllYXIoKSw2LDEpKS5nZXRUaW1lem9uZU9mZnNldCgpLGw9Zy5nZXRUaW1lem9uZU9mZnNldCgpLHE9TWF0aC5taW4obCxoKTswPmU/UVthKzMyPj4yPj4+MF09TnVtYmVyKGghPWwmJnE9PWYpOjA8ZSE9KHE9PWYpJiYoaD1NYXRoLm1heChsLGgpLGMuc2V0VGltZShjLmdldFRpbWUoKSs2RTQqKCgwPGU/cTpoKS1mKSkpO1FbYSsyND4+Mj4+PjBdPWMuZ2V0RGF5KCk7UVthKzI4Pj4yPj4+MF09KGMuZ2V0VGltZSgpLWcuZ2V0VGltZSgpKS84NjRFNXwwO1FbYT4+Mj4+PjBdPWMuZ2V0U2Vjb25kcygpO1FbYSs0Pj4yPj4+MF09Yy5nZXRNaW51dGVzKCk7UVthKzg+PjI+Pj4wXT1jLmdldEhvdXJzKCk7UVthK1xcclxcbjEyPj4yPj4+MF09Yy5nZXREYXRlKCk7UVthKzE2Pj4yPj4+MF09Yy5nZXRNb250aCgpO3JldHVybiBjLmdldFRpbWUoKS8xRTN8MH0sejpmdW5jdGlvbigpe3JldHVybi01Mn0sQjpmdW5jdGlvbigpe30sbTp3YSxkOmZ1bmN0aW9uKCl7SShcXFwiXFxcIil9LHQ6ZnVuY3Rpb24oKXtyZXR1cm4gNDI5NDkwMTc2MH0saDp4PygpPT57dmFyIGE9cHJvY2Vzcy5ocnRpbWUoKTtyZXR1cm4gMUUzKmFbMF0rYVsxXS8xRTZ9OigpPT5wZXJmb3JtYW5jZS5ub3coKSxKOmZ1bmN0aW9uKGEsYyxlKXtNLmNvcHlXaXRoaW4oYT4+PjAsYz4+PjAsYytlPj4+MCl9LGY6ZnVuY3Rpb24oYSl7dmFyIGM9TS5sZW5ndGg7YT4+Pj0wO2lmKDQyOTQ5MDE3NjA8YSlyZXR1cm4hMTtmb3IodmFyIGU9MTs0Pj1lO2UqPTIpe3ZhciBmPWMqKDErLjIvZSk7Zj1NYXRoLm1pbihmLGErMTAwNjYzMjk2KTt2YXIgZz1NYXRoO2Y9TWF0aC5tYXgoYSxmKTtnPWcubWluLmNhbGwoZyw0Mjk0OTAxNzYwLGYrKDY1NTM2LWYlNjU1MzYpJVxcclxcbjY1NTM2KTthOnt0cnl7Si5ncm93KGctaGEuYnl0ZUxlbmd0aCs2NTUzNT4+PjE2KTtpYSgpO3ZhciBoPTE7YnJlYWsgYX1jYXRjaChsKXt9aD12b2lkIDB9aWYoaClyZXR1cm4hMH1yZXR1cm4hMX0sRDpmdW5jdGlvbihhLGMpe3ZhciBlPTA7QmEoKS5mb3JFYWNoKGZ1bmN0aW9uKGYsZyl7dmFyIGg9YytlO2c9UlthKzQqZz4+Mj4+PjBdPWg7Zm9yKGg9MDtoPGYubGVuZ3RoOysraClQW2crKz4+MD4+PjBdPWYuY2hhckNvZGVBdChoKTtQW2c+PjA+Pj4wXT0wO2UrPWYubGVuZ3RoKzF9KTtyZXR1cm4gMH0sRTpmdW5jdGlvbihhLGMpe3ZhciBlPUJhKCk7UlthPj4yPj4+MF09ZS5sZW5ndGg7dmFyIGY9MDtlLmZvckVhY2goZnVuY3Rpb24oZyl7Zis9Zy5sZW5ndGgrMX0pO1JbYz4+Mj4+PjBdPWY7cmV0dXJuIDB9LHI6ZnVuY3Rpb24oYSl7aWYoIW5vRXhpdFJ1bnRpbWUpe2lmKGIub25FeGl0KWIub25FeGl0KGEpO0s9ITB9dChhLG5ldyBGKGEpKX0sZTpmdW5jdGlvbigpe3JldHVybiA1Mn0sXFxyXFxuajpmdW5jdGlvbigpe3JldHVybiA1Mn0scTpmdW5jdGlvbigpe3JldHVybiA3MH0saTpmdW5jdGlvbihhLGMsZSxmKXtmb3IodmFyIGc9MCxoPTA7aDxlO2grKyl7dmFyIGw9UltjPj4yPj4+MF0scT1SW2MrND4+Mj4+PjBdO2MrPTg7Zm9yKHZhciB3PTA7dzxxO3crKyl7dmFyIHY9TVtsK3c+Pj4wXSxyPURhW2FdOzA9PT12fHwxMD09PXY/KCgxPT09YT9kYTpHKShmYShyLDApKSxyLmxlbmd0aD0wKTpyLnB1c2godil9Zys9cX1SW2Y+PjI+Pj4wXT1nO3JldHVybiAwfSxzOlgsQTpJYSxjOmZ1bmN0aW9uKGEsYyxlLGYpe3JldHVybiBJYShhLGMsZSxmKX19O1xcclxcbihmdW5jdGlvbigpe2Z1bmN0aW9uIGEoZyl7Yi5hc209Zy5leHBvcnRzO0o9Yi5hc20uUDtpYSgpO2thLnVuc2hpZnQoYi5hc20uUSk7Uy0tO2IubW9uaXRvclJ1bkRlcGVuZGVuY2llcyYmYi5tb25pdG9yUnVuRGVwZW5kZW5jaWVzKFMpOzA9PVMmJihudWxsIT09VCYmKGNsZWFySW50ZXJ2YWwoVCksVD1udWxsKSxVJiYoZz1VLFU9bnVsbCxnKCkpKX1mdW5jdGlvbiBjKGcpe2EoZy5pbnN0YW5jZSl9ZnVuY3Rpb24gZShnKXtyZXR1cm4gcWEoKS50aGVuKGZ1bmN0aW9uKGgpe3JldHVybiBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZShoLGYpfSkudGhlbihmdW5jdGlvbihoKXtyZXR1cm4gaH0pLnRoZW4oZyxmdW5jdGlvbihoKXtHKFxcXCJmYWlsZWQgdG8gYXN5bmNocm9ub3VzbHkgcHJlcGFyZSB3YXNtOiBcXFwiK2gpO0koaCl9KX12YXIgZj17YTpKYX07UysrO2IubW9uaXRvclJ1bkRlcGVuZGVuY2llcyYmYi5tb25pdG9yUnVuRGVwZW5kZW5jaWVzKFMpO2lmKGIuaW5zdGFudGlhdGVXYXNtKXRyeXtyZXR1cm4gYi5pbnN0YW50aWF0ZVdhc20oZixcXHJcXG5hKX1jYXRjaChnKXtyZXR1cm4gRyhcXFwiTW9kdWxlLmluc3RhbnRpYXRlV2FzbSBjYWxsYmFjayBmYWlsZWQgd2l0aCBlcnJvcjogXFxcIitnKSwhMX0oZnVuY3Rpb24oKXtyZXR1cm4gSHx8XFxcImZ1bmN0aW9uXFxcIiE9dHlwZW9mIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nfHxuYSgpfHxWLnN0YXJ0c1dpdGgoXFxcImZpbGU6Ly9cXFwiKXx8eHx8XFxcImZ1bmN0aW9uXFxcIiE9dHlwZW9mIGZldGNoP2UoYyk6ZmV0Y2goVix7Y3JlZGVudGlhbHM6XFxcInNhbWUtb3JpZ2luXFxcIn0pLnRoZW4oZnVuY3Rpb24oZyl7cmV0dXJuIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nKGcsZikudGhlbihjLGZ1bmN0aW9uKGgpe0coXFxcIndhc20gc3RyZWFtaW5nIGNvbXBpbGUgZmFpbGVkOiBcXFwiK2gpO0coXFxcImZhbGxpbmcgYmFjayB0byBBcnJheUJ1ZmZlciBpbnN0YW50aWF0aW9uXFxcIik7cmV0dXJuIGUoYyl9KX0pfSkoKS5jYXRjaChrKTtyZXR1cm57fX0pKCk7XFxyXFxuYi5fX193YXNtX2NhbGxfY3RvcnM9ZnVuY3Rpb24oKXtyZXR1cm4oYi5fX193YXNtX2NhbGxfY3RvcnM9Yi5hc20uUSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLl9PcnRJbml0PWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydEluaXQ9Yi5hc20uUikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLl9PcnRDcmVhdGVTZXNzaW9uT3B0aW9ucz1mdW5jdGlvbigpe3JldHVybihiLl9PcnRDcmVhdGVTZXNzaW9uT3B0aW9ucz1iLmFzbS5TKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2IuX09ydEFwcGVuZEV4ZWN1dGlvblByb3ZpZGVyPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydEFwcGVuZEV4ZWN1dGlvblByb3ZpZGVyPWIuYXNtLlQpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07Yi5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5PWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydEFkZFNlc3Npb25Db25maWdFbnRyeT1iLmFzbS5VKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O1xcclxcbmIuX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucz1mdW5jdGlvbigpe3JldHVybihiLl9PcnRSZWxlYXNlU2Vzc2lvbk9wdGlvbnM9Yi5hc20uVikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLl9PcnRDcmVhdGVTZXNzaW9uPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydENyZWF0ZVNlc3Npb249Yi5hc20uVykuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLl9PcnRSZWxlYXNlU2Vzc2lvbj1mdW5jdGlvbigpe3JldHVybihiLl9PcnRSZWxlYXNlU2Vzc2lvbj1iLmFzbS5YKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2IuX09ydEdldElucHV0Q291bnQ9ZnVuY3Rpb24oKXtyZXR1cm4oYi5fT3J0R2V0SW5wdXRDb3VudD1iLmFzbS5ZKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2IuX09ydEdldE91dHB1dENvdW50PWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydEdldE91dHB1dENvdW50PWIuYXNtLlopLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XFxyXFxuYi5fT3J0R2V0SW5wdXROYW1lPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydEdldElucHV0TmFtZT1iLmFzbS5fKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2IuX09ydEdldE91dHB1dE5hbWU9ZnVuY3Rpb24oKXtyZXR1cm4oYi5fT3J0R2V0T3V0cHV0TmFtZT1iLmFzbS4kKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2IuX09ydEZyZWU9ZnVuY3Rpb24oKXtyZXR1cm4oYi5fT3J0RnJlZT1iLmFzbS5hYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLl9PcnRDcmVhdGVUZW5zb3I9ZnVuY3Rpb24oKXtyZXR1cm4oYi5fT3J0Q3JlYXRlVGVuc29yPWIuYXNtLmJhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2IuX09ydEdldFRlbnNvckRhdGE9ZnVuY3Rpb24oKXtyZXR1cm4oYi5fT3J0R2V0VGVuc29yRGF0YT1iLmFzbS5jYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtcXHJcXG5iLl9PcnRSZWxlYXNlVGVuc29yPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydFJlbGVhc2VUZW5zb3I9Yi5hc20uZGEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07Yi5fT3J0Q3JlYXRlUnVuT3B0aW9ucz1mdW5jdGlvbigpe3JldHVybihiLl9PcnRDcmVhdGVSdW5PcHRpb25zPWIuYXNtLmVhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2IuX09ydEFkZFJ1bkNvbmZpZ0VudHJ5PWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydEFkZFJ1bkNvbmZpZ0VudHJ5PWIuYXNtLmZhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2IuX09ydFJlbGVhc2VSdW5PcHRpb25zPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydFJlbGVhc2VSdW5PcHRpb25zPWIuYXNtLmdhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2IuX09ydFJ1bj1mdW5jdGlvbigpe3JldHVybihiLl9PcnRSdW49Yi5hc20uaGEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XFxyXFxuYi5fT3J0RW5kUHJvZmlsaW5nPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydEVuZFByb2ZpbGluZz1iLmFzbS5pYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt2YXIgdWE9Yi5fbWFsbG9jPWZ1bmN0aW9uKCl7cmV0dXJuKHVhPWIuX21hbGxvYz1iLmFzbS5qYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLl9mcmVlPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX2ZyZWU9Yi5hc20ua2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07dmFyIEthPWIuc3RhY2tTYXZlPWZ1bmN0aW9uKCl7cmV0dXJuKEthPWIuc3RhY2tTYXZlPWIuYXNtLm1hKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LExhPWIuc3RhY2tSZXN0b3JlPWZ1bmN0aW9uKCl7cmV0dXJuKExhPWIuc3RhY2tSZXN0b3JlPWIuYXNtLm5hKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LE1hPWIuc3RhY2tBbGxvYz1mdW5jdGlvbigpe3JldHVybihNYT1iLnN0YWNrQWxsb2M9Yi5hc20ub2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XFxyXFxuYi5fX19jeGFfaXNfcG9pbnRlcl90eXBlPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX19fY3hhX2lzX3BvaW50ZXJfdHlwZT1iLmFzbS5wYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLlVURjhUb1N0cmluZz1MO2Iuc3RyaW5nVG9VVEY4PWZ1bmN0aW9uKGEsYyxlKXtyZXR1cm4gTihhLE0sYyxlKX07Yi5sZW5ndGhCeXRlc1VURjg9TztiLnN0YWNrU2F2ZT1LYTtiLnN0YWNrUmVzdG9yZT1MYTtiLnN0YWNrQWxsb2M9TWE7dmFyIFo7VT1mdW5jdGlvbiBOYSgpe1p8fE9hKCk7Wnx8KFU9TmEpfTtcXHJcXG5mdW5jdGlvbiBPYSgpe2Z1bmN0aW9uIGEoKXtpZighWiYmKFo9ITAsYi5jYWxsZWRSdW49ITAsIUspKXtXKGthKTthYShiKTtpZihiLm9uUnVudGltZUluaXRpYWxpemVkKWIub25SdW50aW1lSW5pdGlhbGl6ZWQoKTtpZihiLnBvc3RSdW4pZm9yKFxcXCJmdW5jdGlvblxcXCI9PXR5cGVvZiBiLnBvc3RSdW4mJihiLnBvc3RSdW49W2IucG9zdFJ1bl0pO2IucG9zdFJ1bi5sZW5ndGg7KXt2YXIgYz1iLnBvc3RSdW4uc2hpZnQoKTtsYS51bnNoaWZ0KGMpfVcobGEpfX1pZighKDA8Uykpe2lmKGIucHJlUnVuKWZvcihcXFwiZnVuY3Rpb25cXFwiPT10eXBlb2YgYi5wcmVSdW4mJihiLnByZVJ1bj1bYi5wcmVSdW5dKTtiLnByZVJ1bi5sZW5ndGg7KW1hKCk7VyhqYSk7MDxTfHwoYi5zZXRTdGF0dXM/KGIuc2V0U3RhdHVzKFxcXCJSdW5uaW5nLi4uXFxcIiksc2V0VGltZW91dChmdW5jdGlvbigpe3NldFRpbWVvdXQoZnVuY3Rpb24oKXtiLnNldFN0YXR1cyhcXFwiXFxcIil9LDEpO2EoKX0sMSkpOmEoKSl9fVxcclxcbmlmKGIucHJlSW5pdClmb3IoXFxcImZ1bmN0aW9uXFxcIj09dHlwZW9mIGIucHJlSW5pdCYmKGIucHJlSW5pdD1bYi5wcmVJbml0XSk7MDxiLnByZUluaXQubGVuZ3RoOyliLnByZUluaXQucG9wKCkoKTtPYSgpO1xcclxcblxcclxcblxcclxcbiAgcmV0dXJuIG9ydFdhc20ucmVhZHlcXHJcXG59XFxyXFxuKTtcXHJcXG59KSgpO1xcclxcbmlmICh0cnVlKVxcclxcbiAgbW9kdWxlLmV4cG9ydHMgPSBvcnRXYXNtO1xcclxcbmVsc2Uge31cXHJcXG5cXG5cXG4vKioqLyB9KSxcXG5cXG4vKioqLyBcXFwiLi9saWIvd2FzbS9iaW5kaW5nL29ydC13YXNtLXRocmVhZGVkLndvcmtlci5qc1xcXCI6XFxuLyohKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqISpcXFxcXFxuICAhKioqIC4vbGliL3dhc20vYmluZGluZy9vcnQtd2FzbS10aHJlYWRlZC53b3JrZXIuanMgKioqIVxcbiAgXFxcXCoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cXG4vKioqLyAoKG1vZHVsZSkgPT4ge1xcblxcblxcXCJ1c2Ugc3RyaWN0XFxcIjtcXG5tb2R1bGUuZXhwb3J0cyA9IFxcXCJcXFxcXFxcInVzZSBzdHJpY3RcXFxcXFxcIjt2YXIgTW9kdWxlPXt9O3ZhciBFTlZJUk9OTUVOVF9JU19OT0RFPXR5cGVvZiBwcm9jZXNzPT1cXFxcXFxcIm9iamVjdFxcXFxcXFwiJiZ0eXBlb2YgcHJvY2Vzcy52ZXJzaW9ucz09XFxcXFxcXCJvYmplY3RcXFxcXFxcIiYmdHlwZW9mIHByb2Nlc3MudmVyc2lvbnMubm9kZT09XFxcXFxcXCJzdHJpbmdcXFxcXFxcIjtpZihFTlZJUk9OTUVOVF9JU19OT0RFKXt2YXIgbm9kZVdvcmtlclRocmVhZHM9cmVxdWlyZShcXFxcXFxcIndvcmtlcl90aHJlYWRzXFxcXFxcXCIpO3ZhciBwYXJlbnRQb3J0PW5vZGVXb3JrZXJUaHJlYWRzLnBhcmVudFBvcnQ7cGFyZW50UG9ydC5vbihcXFxcXFxcIm1lc3NhZ2VcXFxcXFxcIixkYXRhPT5vbm1lc3NhZ2Uoe2RhdGE6ZGF0YX0pKTt2YXIgZnM9cmVxdWlyZShcXFxcXFxcImZzXFxcXFxcXCIpO09iamVjdC5hc3NpZ24oZ2xvYmFsLHtzZWxmOmdsb2JhbCxyZXF1aXJlOnJlcXVpcmUsTW9kdWxlOk1vZHVsZSxsb2NhdGlvbjp7aHJlZjpfX2ZpbGVuYW1lfSxXb3JrZXI6bm9kZVdvcmtlclRocmVhZHMuV29ya2VyLGltcG9ydFNjcmlwdHM6ZnVuY3Rpb24oZil7KDAsZXZhbCkoZnMucmVhZEZpbGVTeW5jKGYsXFxcXFxcXCJ1dGY4XFxcXFxcXCIpKX0scG9zdE1lc3NhZ2U6ZnVuY3Rpb24obXNnKXtwYXJlbnRQb3J0LnBvc3RNZXNzYWdlKG1zZyl9LHBlcmZvcm1hbmNlOmdsb2JhbC5wZXJmb3JtYW5jZXx8e25vdzpmdW5jdGlvbigpe3JldHVybiBEYXRlLm5vdygpfX19KX12YXIgaW5pdGlhbGl6ZWRKUz1mYWxzZTt2YXIgcGVuZGluZ05vdGlmaWVkUHJveHlpbmdRdWV1ZXM9W107ZnVuY3Rpb24gdGhyZWFkUHJpbnRFcnIoKXt2YXIgdGV4dD1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpLmpvaW4oXFxcXFxcXCIgXFxcXFxcXCIpO2lmKEVOVklST05NRU5UX0lTX05PREUpe2ZzLndyaXRlU3luYygyLHRleHQrXFxcXFxcXCJcXFxcXFxcXG5cXFxcXFxcIik7cmV0dXJufWNvbnNvbGUuZXJyb3IodGV4dCl9ZnVuY3Rpb24gdGhyZWFkQWxlcnQoKXt2YXIgdGV4dD1BcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpLmpvaW4oXFxcXFxcXCIgXFxcXFxcXCIpO3Bvc3RNZXNzYWdlKHtjbWQ6XFxcXFxcXCJhbGVydFxcXFxcXFwiLHRleHQ6dGV4dCx0aHJlYWRJZDpNb2R1bGVbXFxcXFxcXCJfcHRocmVhZF9zZWxmXFxcXFxcXCJdKCl9KX12YXIgZXJyPXRocmVhZFByaW50RXJyO3NlbGYuYWxlcnQ9dGhyZWFkQWxlcnQ7TW9kdWxlW1xcXFxcXFwiaW5zdGFudGlhdGVXYXNtXFxcXFxcXCJdPShpbmZvLHJlY2VpdmVJbnN0YW5jZSk9Pnt2YXIgaW5zdGFuY2U9bmV3IFdlYkFzc2VtYmx5Lkluc3RhbmNlKE1vZHVsZVtcXFxcXFxcIndhc21Nb2R1bGVcXFxcXFxcIl0saW5mbyk7cmVjZWl2ZUluc3RhbmNlKGluc3RhbmNlKTtNb2R1bGVbXFxcXFxcXCJ3YXNtTW9kdWxlXFxcXFxcXCJdPW51bGw7cmV0dXJuIGluc3RhbmNlLmV4cG9ydHN9O3NlbGYub251bmhhbmRsZWRyZWplY3Rpb249ZT0+e3Rocm93IGUucmVhc29uPz9lfTtzZWxmLm9ubWVzc2FnZT1lPT57dHJ5e2lmKGUuZGF0YS5jbWQ9PT1cXFxcXFxcImxvYWRcXFxcXFxcIil7TW9kdWxlW1xcXFxcXFwid2FzbU1vZHVsZVxcXFxcXFwiXT1lLmRhdGEud2FzbU1vZHVsZTtNb2R1bGVbXFxcXFxcXCJ3YXNtTWVtb3J5XFxcXFxcXCJdPWUuZGF0YS53YXNtTWVtb3J5O01vZHVsZVtcXFxcXFxcImJ1ZmZlclxcXFxcXFwiXT1Nb2R1bGVbXFxcXFxcXCJ3YXNtTWVtb3J5XFxcXFxcXCJdLmJ1ZmZlcjtNb2R1bGVbXFxcXFxcXCJFTlZJUk9OTUVOVF9JU19QVEhSRUFEXFxcXFxcXCJdPXRydWU7aWYodHlwZW9mIGUuZGF0YS51cmxPckJsb2I9PVxcXFxcXFwic3RyaW5nXFxcXFxcXCIpe2ltcG9ydFNjcmlwdHMoZS5kYXRhLnVybE9yQmxvYil9ZWxzZXt2YXIgb2JqZWN0VXJsPVVSTC5jcmVhdGVPYmplY3RVUkwoZS5kYXRhLnVybE9yQmxvYik7aW1wb3J0U2NyaXB0cyhvYmplY3RVcmwpO1VSTC5yZXZva2VPYmplY3RVUkwob2JqZWN0VXJsKX1vcnRXYXNtVGhyZWFkZWQoTW9kdWxlKS50aGVuKGZ1bmN0aW9uKGluc3RhbmNlKXtNb2R1bGU9aW5zdGFuY2V9KX1lbHNlIGlmKGUuZGF0YS5jbWQ9PT1cXFxcXFxcInJ1blxcXFxcXFwiKXtNb2R1bGVbXFxcXFxcXCJfX3BlcmZvcm1hbmNlX25vd19jbG9ja19kcmlmdFxcXFxcXFwiXT1wZXJmb3JtYW5jZS5ub3coKS1lLmRhdGEudGltZTtNb2R1bGVbXFxcXFxcXCJfX2Vtc2NyaXB0ZW5fdGhyZWFkX2luaXRcXFxcXFxcIl0oZS5kYXRhLnB0aHJlYWRfcHRyLC8qaXNNYWluQnJvd3NlclRocmVhZD0qLzAsLyppc01haW5SdW50aW1lVGhyZWFkPSovMCwvKmNhbkJsb2NrPSovMSk7TW9kdWxlW1xcXFxcXFwiZXN0YWJsaXNoU3RhY2tTcGFjZVxcXFxcXFwiXSgpO01vZHVsZVtcXFxcXFxcIlBUaHJlYWRcXFxcXFxcIl0ucmVjZWl2ZU9iamVjdFRyYW5zZmVyKGUuZGF0YSk7TW9kdWxlW1xcXFxcXFwiUFRocmVhZFxcXFxcXFwiXS50aHJlYWRJbml0VExTKCk7aWYoIWluaXRpYWxpemVkSlMpe3BlbmRpbmdOb3RpZmllZFByb3h5aW5nUXVldWVzLmZvckVhY2gocXVldWU9PntNb2R1bGVbXFxcXFxcXCJleGVjdXRlTm90aWZpZWRQcm94eWluZ1F1ZXVlXFxcXFxcXCJdKHF1ZXVlKX0pO3BlbmRpbmdOb3RpZmllZFByb3h5aW5nUXVldWVzPVtdO2luaXRpYWxpemVkSlM9dHJ1ZX10cnl7TW9kdWxlW1xcXFxcXFwiaW52b2tlRW50cnlQb2ludFxcXFxcXFwiXShlLmRhdGEuc3RhcnRfcm91dGluZSxlLmRhdGEuYXJnKX1jYXRjaChleCl7aWYoZXghPVxcXFxcXFwidW53aW5kXFxcXFxcXCIpe2lmKGV4IGluc3RhbmNlb2YgTW9kdWxlW1xcXFxcXFwiRXhpdFN0YXR1c1xcXFxcXFwiXSl7aWYoTW9kdWxlW1xcXFxcXFwia2VlcFJ1bnRpbWVBbGl2ZVxcXFxcXFwiXSgpKXt9ZWxzZXtNb2R1bGVbXFxcXFxcXCJfX2Vtc2NyaXB0ZW5fdGhyZWFkX2V4aXRcXFxcXFxcIl0oZXguc3RhdHVzKX19ZWxzZXt0aHJvdyBleH19fX1lbHNlIGlmKGUuZGF0YS5jbWQ9PT1cXFxcXFxcImNhbmNlbFxcXFxcXFwiKXtpZihNb2R1bGVbXFxcXFxcXCJfcHRocmVhZF9zZWxmXFxcXFxcXCJdKCkpe01vZHVsZVtcXFxcXFxcIl9fZW1zY3JpcHRlbl90aHJlYWRfZXhpdFxcXFxcXFwiXSgtMSl9fWVsc2UgaWYoZS5kYXRhLnRhcmdldD09PVxcXFxcXFwic2V0aW1tZWRpYXRlXFxcXFxcXCIpe31lbHNlIGlmKGUuZGF0YS5jbWQ9PT1cXFxcXFxcInByb2Nlc3NQcm94eWluZ1F1ZXVlXFxcXFxcXCIpe2lmKGluaXRpYWxpemVkSlMpe01vZHVsZVtcXFxcXFxcImV4ZWN1dGVOb3RpZmllZFByb3h5aW5nUXVldWVcXFxcXFxcIl0oZS5kYXRhLnF1ZXVlKX1lbHNle3BlbmRpbmdOb3RpZmllZFByb3h5aW5nUXVldWVzLnB1c2goZS5kYXRhLnF1ZXVlKX19ZWxzZXtlcnIoXFxcXFxcXCJ3b3JrZXIuanMgcmVjZWl2ZWQgdW5rbm93biBjb21tYW5kIFxcXFxcXFwiK2UuZGF0YS5jbWQpO2VycihlLmRhdGEpfX1jYXRjaChleCl7ZXJyKFxcXFxcXFwid29ya2VyLmpzIG9ubWVzc2FnZSgpIGNhcHR1cmVkIGFuIHVuY2F1Z2h0IGV4Y2VwdGlvbjogXFxcXFxcXCIrZXgpO2lmKGV4JiZleC5zdGFjayllcnIoZXguc3RhY2spO2lmKE1vZHVsZVtcXFxcXFxcIl9fZW1zY3JpcHRlbl90aHJlYWRfY3Jhc2hlZFxcXFxcXFwiXSl7TW9kdWxlW1xcXFxcXFwiX19lbXNjcmlwdGVuX3RocmVhZF9jcmFzaGVkXFxcXFxcXCJdKCl9dGhyb3cgZXh9fTtcXFxcclxcXFxuXFxcIjtcXG5cXG4vKioqLyB9KSxcXG5cXG4vKioqLyBcXFwiPzg5MmRcXFwiOlxcbi8qISoqKioqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiBjcnlwdG8gKGlnbm9yZWQpICoqKiFcXG4gIFxcXFwqKioqKioqKioqKioqKioqKioqKioqKiovXFxuLyoqKi8gKCgpID0+IHtcXG5cXG4vKiAoaWdub3JlZCkgKi9cXG5cXG4vKioqLyB9KSxcXG5cXG4vKioqLyBcXFwiPzYzYzhcXFwiOlxcbi8qISoqKioqKioqKioqKioqKioqKioqISpcXFxcXFxuICAhKioqIGZzIChpZ25vcmVkKSAqKiohXFxuICBcXFxcKioqKioqKioqKioqKioqKioqKiovXFxuLyoqKi8gKCgpID0+IHtcXG5cXG4vKiAoaWdub3JlZCkgKi9cXG5cXG4vKioqLyB9KSxcXG5cXG4vKioqLyBcXFwiP2FlZGJcXFwiOlxcbi8qISoqKioqKioqKioqKioqKioqKioqISpcXFxcXFxuICAhKioqIG9zIChpZ25vcmVkKSAqKiohXFxuICBcXFxcKioqKioqKioqKioqKioqKioqKiovXFxuLyoqKi8gKCgpID0+IHtcXG5cXG4vKiAoaWdub3JlZCkgKi9cXG5cXG4vKioqLyB9KSxcXG5cXG4vKioqLyBcXFwiPzc1YzZcXFwiOlxcbi8qISoqKioqKioqKioqKioqKioqKioqKiohKlxcXFxcXG4gICEqKiogcGF0aCAoaWdub3JlZCkgKioqIVxcbiAgXFxcXCoqKioqKioqKioqKioqKioqKioqKiovXFxuLyoqKi8gKCgpID0+IHtcXG5cXG4vKiAoaWdub3JlZCkgKi9cXG5cXG4vKioqLyB9KSxcXG5cXG4vKioqLyBcXFwiPzY3NGZcXFwiOlxcbi8qISoqKioqKioqKioqKioqKioqKioqKioqKioqKiohKlxcXFxcXG4gICEqKiogcGVyZl9ob29rcyAoaWdub3JlZCkgKioqIVxcbiAgXFxcXCoqKioqKioqKioqKioqKioqKioqKioqKioqKiovXFxuLyoqKi8gKCgpID0+IHtcXG5cXG4vKiAoaWdub3JlZCkgKi9cXG5cXG4vKioqLyB9KSxcXG5cXG4vKioqLyBcXFwiP2M2ZjdcXFwiOlxcbi8qISoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqISpcXFxcXFxuICAhKioqIHdvcmtlcl90aHJlYWRzIChpZ25vcmVkKSAqKiohXFxuICBcXFxcKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXFxuLyoqKi8gKCgpID0+IHtcXG5cXG4vKiAoaWdub3JlZCkgKi9cXG5cXG4vKioqLyB9KSxcXG5cXG4vKioqLyBcXFwiPzdhYTVcXFwiOlxcbi8qISoqKioqKioqKioqKioqKioqKioqKiohKlxcXFxcXG4gICEqKiogcGF0aCAoaWdub3JlZCkgKioqIVxcbiAgXFxcXCoqKioqKioqKioqKioqKioqKioqKiovXFxuLyoqKi8gKCgpID0+IHtcXG5cXG4vKiAoaWdub3JlZCkgKi9cXG5cXG4vKioqLyB9KVxcblxcbi8qKioqKiovIFxcdH0pO1xcbi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXFxuLyoqKioqKi8gXFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxcbi8qKioqKiovIFxcdHZhciBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX18gPSB7fTtcXG4vKioqKioqLyBcXHRcXG4vKioqKioqLyBcXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxcbi8qKioqKiovIFxcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcXG4vKioqKioqLyBcXHRcXHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcXG4vKioqKioqLyBcXHRcXHR2YXIgY2FjaGVkTW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXTtcXG4vKioqKioqLyBcXHRcXHRpZiAoY2FjaGVkTW9kdWxlICE9PSB1bmRlZmluZWQpIHtcXG4vKioqKioqLyBcXHRcXHRcXHRyZXR1cm4gY2FjaGVkTW9kdWxlLmV4cG9ydHM7XFxuLyoqKioqKi8gXFx0XFx0fVxcbi8qKioqKiovIFxcdFxcdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXFxuLyoqKioqKi8gXFx0XFx0dmFyIG1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF0gPSB7XFxuLyoqKioqKi8gXFx0XFx0XFx0Ly8gbm8gbW9kdWxlLmlkIG5lZWRlZFxcbi8qKioqKiovIFxcdFxcdFxcdC8vIG5vIG1vZHVsZS5sb2FkZWQgbmVlZGVkXFxuLyoqKioqKi8gXFx0XFx0XFx0ZXhwb3J0czoge31cXG4vKioqKioqLyBcXHRcXHR9O1xcbi8qKioqKiovIFxcdFxcbi8qKioqKiovIFxcdFxcdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxcbi8qKioqKiovIFxcdFxcdF9fd2VicGFja19tb2R1bGVzX19bbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xcbi8qKioqKiovIFxcdFxcbi8qKioqKiovIFxcdFxcdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXFxuLyoqKioqKi8gXFx0XFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xcbi8qKioqKiovIFxcdH1cXG4vKioqKioqLyBcXHRcXG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xcbi8qKioqKiovIFxcdC8qIHdlYnBhY2svcnVudGltZS9nbG9iYWwgKi9cXG4vKioqKioqLyBcXHQoKCkgPT4ge1xcbi8qKioqKiovIFxcdFxcdF9fd2VicGFja19yZXF1aXJlX18uZyA9IChmdW5jdGlvbigpIHtcXG4vKioqKioqLyBcXHRcXHRcXHRpZiAodHlwZW9mIGdsb2JhbFRoaXMgPT09ICdvYmplY3QnKSByZXR1cm4gZ2xvYmFsVGhpcztcXG4vKioqKioqLyBcXHRcXHRcXHR0cnkge1xcbi8qKioqKiovIFxcdFxcdFxcdFxcdHJldHVybiB0aGlzIHx8IG5ldyBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpO1xcbi8qKioqKiovIFxcdFxcdFxcdH0gY2F0Y2ggKGUpIHtcXG4vKioqKioqLyBcXHRcXHRcXHRcXHRpZiAodHlwZW9mIHdpbmRvdyA9PT0gJ29iamVjdCcpIHJldHVybiB3aW5kb3c7XFxuLyoqKioqKi8gXFx0XFx0XFx0fVxcbi8qKioqKiovIFxcdFxcdH0pKCk7XFxuLyoqKioqKi8gXFx0fSkoKTtcXG4vKioqKioqLyBcXHRcXG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xcbnZhciBfX3dlYnBhY2tfZXhwb3J0c19fID0ge307XFxuLy8gVGhpcyBlbnRyeSBuZWVkIHRvIGJlIHdyYXBwZWQgaW4gYW4gSUlGRSBiZWNhdXNlIGl0IG5lZWQgdG8gYmUgaW4gc3RyaWN0IG1vZGUuXFxuKCgpID0+IHtcXG5cXFwidXNlIHN0cmljdFxcXCI7XFxudmFyIGV4cG9ydHMgPSBfX3dlYnBhY2tfZXhwb3J0c19fO1xcbi8qISoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiEqXFxcXFxcbiAgISoqKiAuLi9ub2RlX21vZHVsZXMvdHMtbG9hZGVyL2luZGV4LmpzPz9ydWxlU2V0WzFdLnJ1bGVzWzBdLnVzZVswXSEuL2xpYi93YXNtL3Byb3h5LXdvcmtlci9tYWluLnRzICoqKiFcXG4gIFxcXFwqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXFxuXFxuLy8gQ29weXJpZ2h0IChjKSBNaWNyb3NvZnQgQ29ycG9yYXRpb24uIEFsbCByaWdodHMgcmVzZXJ2ZWQuXFxuLy8gTGljZW5zZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlLlxcbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcXFwiX19lc01vZHVsZVxcXCIsICh7IHZhbHVlOiB0cnVlIH0pKTtcXG5jb25zdCB3YXNtX2NvcmVfaW1wbF8xID0gX193ZWJwYWNrX3JlcXVpcmVfXygvKiEgLi4vd2FzbS1jb3JlLWltcGwgKi8gXFxcIi4vbGliL3dhc20vd2FzbS1jb3JlLWltcGwudHNcXFwiKTtcXG5jb25zdCB3YXNtX2ZhY3RvcnlfMSA9IF9fd2VicGFja19yZXF1aXJlX18oLyohIC4uL3dhc20tZmFjdG9yeSAqLyBcXFwiLi9saWIvd2FzbS93YXNtLWZhY3RvcnkudHNcXFwiKTtcXG5zZWxmLm9ubWVzc2FnZSA9IChldikgPT4ge1xcbiAgICBzd2l0Y2ggKGV2LmRhdGEudHlwZSkge1xcbiAgICAgICAgY2FzZSAnaW5pdC13YXNtJzpcXG4gICAgICAgICAgICAoMCwgd2FzbV9mYWN0b3J5XzEuaW5pdGlhbGl6ZVdlYkFzc2VtYmx5KShldi5kYXRhLmluKVxcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiBwb3N0TWVzc2FnZSh7IHR5cGU6ICdpbml0LXdhc20nIH0pLCBlcnIgPT4gcG9zdE1lc3NhZ2UoeyB0eXBlOiAnaW5pdC13YXNtJywgZXJyIH0pKTtcXG4gICAgICAgICAgICBicmVhaztcXG4gICAgICAgIGNhc2UgJ2luaXQtb3J0JzpcXG4gICAgICAgICAgICB0cnkge1xcbiAgICAgICAgICAgICAgICBjb25zdCB7IG51bVRocmVhZHMsIGxvZ2dpbmdMZXZlbCB9ID0gZXYuZGF0YS5pbjtcXG4gICAgICAgICAgICAgICAgKDAsIHdhc21fY29yZV9pbXBsXzEuaW5pdE9ydCkobnVtVGhyZWFkcywgbG9nZ2luZ0xldmVsKTtcXG4gICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlOiAnaW5pdC1vcnQnIH0pO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICBjYXRjaCAoZXJyKSB7XFxuICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZTogJ2luaXQtb3J0JywgZXJyIH0pO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICBicmVhaztcXG4gICAgICAgIGNhc2UgJ2NyZWF0ZV9hbGxvY2F0ZSc6XFxuICAgICAgICAgICAgdHJ5IHtcXG4gICAgICAgICAgICAgICAgY29uc3QgeyBtb2RlbCB9ID0gZXYuZGF0YS5pbjtcXG4gICAgICAgICAgICAgICAgY29uc3QgbW9kZWxkYXRhID0gKDAsIHdhc21fY29yZV9pbXBsXzEuY3JlYXRlU2Vzc2lvbkFsbG9jYXRlKShtb2RlbCk7XFxuICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZTogJ2NyZWF0ZV9hbGxvY2F0ZScsIG91dDogbW9kZWxkYXRhIH0pO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICBjYXRjaCAoZXJyKSB7XFxuICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZTogJ2NyZWF0ZV9hbGxvY2F0ZScsIGVyciB9KTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgYnJlYWs7XFxuICAgICAgICBjYXNlICdjcmVhdGVfZmluYWxpemUnOlxcbiAgICAgICAgICAgIHRyeSB7XFxuICAgICAgICAgICAgICAgIGNvbnN0IHsgbW9kZWxkYXRhLCBvcHRpb25zIH0gPSBldi5kYXRhLmluO1xcbiAgICAgICAgICAgICAgICBjb25zdCBzZXNzaW9uTWV0YWRhdGEgPSAoMCwgd2FzbV9jb3JlX2ltcGxfMS5jcmVhdGVTZXNzaW9uRmluYWxpemUpKG1vZGVsZGF0YSwgb3B0aW9ucyk7XFxuICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZTogJ2NyZWF0ZV9maW5hbGl6ZScsIG91dDogc2Vzc2lvbk1ldGFkYXRhIH0pO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICBjYXRjaCAoZXJyKSB7XFxuICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZTogJ2NyZWF0ZV9maW5hbGl6ZScsIGVyciB9KTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgYnJlYWs7XFxuICAgICAgICBjYXNlICdjcmVhdGUnOlxcbiAgICAgICAgICAgIHRyeSB7XFxuICAgICAgICAgICAgICAgIGNvbnN0IHsgbW9kZWwsIG9wdGlvbnMgfSA9IGV2LmRhdGEuaW47XFxuICAgICAgICAgICAgICAgIGNvbnN0IHNlc3Npb25NZXRhZGF0YSA9ICgwLCB3YXNtX2NvcmVfaW1wbF8xLmNyZWF0ZVNlc3Npb24pKG1vZGVsLCBvcHRpb25zKTtcXG4gICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlOiAnY3JlYXRlJywgb3V0OiBzZXNzaW9uTWV0YWRhdGEgfSk7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIGNhdGNoIChlcnIpIHtcXG4gICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlOiAnY3JlYXRlJywgZXJyIH0pO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICBicmVhaztcXG4gICAgICAgIGNhc2UgJ3JlbGVhc2UnOlxcbiAgICAgICAgICAgIHRyeSB7XFxuICAgICAgICAgICAgICAgIGNvbnN0IGhhbmRsZXIgPSBldi5kYXRhLmluO1xcbiAgICAgICAgICAgICAgICAoMCwgd2FzbV9jb3JlX2ltcGxfMS5yZWxlYXNlU2Vzc2lvbikoaGFuZGxlcik7XFxuICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZTogJ3JlbGVhc2UnIH0pO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICBjYXRjaCAoZXJyKSB7XFxuICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZTogJ3JlbGVhc2UnLCBlcnIgfSk7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIGJyZWFrO1xcbiAgICAgICAgY2FzZSAncnVuJzpcXG4gICAgICAgICAgICB0cnkge1xcbiAgICAgICAgICAgICAgICBjb25zdCB7IHNlc3Npb25JZCwgaW5wdXRJbmRpY2VzLCBpbnB1dHMsIG91dHB1dEluZGljZXMsIG9wdGlvbnMgfSA9IGV2LmRhdGEuaW47XFxuICAgICAgICAgICAgICAgICgwLCB3YXNtX2NvcmVfaW1wbF8xLnJ1bikoc2Vzc2lvbklkLCBpbnB1dEluZGljZXMsIGlucHV0cywgb3V0cHV0SW5kaWNlcywgb3B0aW9ucylcXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKG91dHB1dHMgPT4ge1xcbiAgICAgICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlOiAncnVuJywgb3V0OiBvdXRwdXRzIH0sICgwLCB3YXNtX2NvcmVfaW1wbF8xLmV4dHJhY3RUcmFuc2ZlcmFibGVCdWZmZXJzKShvdXRwdXRzKSk7XFxuICAgICAgICAgICAgICAgIH0sIGVyciA9PiB7XFxuICAgICAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZSh7IHR5cGU6ICdydW4nLCBlcnIgfSk7XFxuICAgICAgICAgICAgICAgIH0pO1xcbiAgICAgICAgICAgIH1cXG4gICAgICAgICAgICBjYXRjaCAoZXJyKSB7XFxuICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgdHlwZTogJ3J1bicsIGVyciB9KTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgYnJlYWs7XFxuICAgICAgICBjYXNlICdlbmQtcHJvZmlsaW5nJzpcXG4gICAgICAgICAgICB0cnkge1xcbiAgICAgICAgICAgICAgICBjb25zdCBoYW5kbGVyID0gZXYuZGF0YS5pbjtcXG4gICAgICAgICAgICAgICAgKDAsIHdhc21fY29yZV9pbXBsXzEuZW5kUHJvZmlsaW5nKShoYW5kbGVyKTtcXG4gICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlOiAnZW5kLXByb2ZpbGluZycgfSk7XFxuICAgICAgICAgICAgfVxcbiAgICAgICAgICAgIGNhdGNoIChlcnIpIHtcXG4gICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyB0eXBlOiAnZW5kLXByb2ZpbGluZycsIGVyciB9KTtcXG4gICAgICAgICAgICB9XFxuICAgICAgICAgICAgYnJlYWs7XFxuICAgICAgICBkZWZhdWx0OlxcbiAgICB9XFxufTtcXG5cXG59KSgpO1xcblxcbi8qKioqKiovIH0pKClcXG47XFxuXCIsIFwiV29ya2VyXCIsIHVuZGVmaW5lZCwgdW5kZWZpbmVkKTtcbn1cbiIsIlwidXNlIHN0cmljdFwiO1xuXG4vKiBlc2xpbnQtZW52IGJyb3dzZXIgKi9cblxuLyogZXNsaW50LWRpc2FibGUgbm8tdW5kZWYsIG5vLXVzZS1iZWZvcmUtZGVmaW5lLCBuZXctY2FwICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjb250ZW50LCB3b3JrZXJDb25zdHJ1Y3Rvciwgd29ya2VyT3B0aW9ucywgdXJsKSB7XG4gIHZhciBnbG9iYWxTY29wZSA9IHNlbGYgfHwgd2luZG93O1xuXG4gIHRyeSB7XG4gICAgdHJ5IHtcbiAgICAgIHZhciBibG9iO1xuXG4gICAgICB0cnkge1xuICAgICAgICAvLyBOZXcgQVBJXG4gICAgICAgIGJsb2IgPSBuZXcgZ2xvYmFsU2NvcGUuQmxvYihbY29udGVudF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyBCbG9iQnVpbGRlciA9IERlcHJlY2F0ZWQsIGJ1dCB3aWRlbHkgaW1wbGVtZW50ZWRcbiAgICAgICAgdmFyIEJsb2JCdWlsZGVyID0gZ2xvYmFsU2NvcGUuQmxvYkJ1aWxkZXIgfHwgZ2xvYmFsU2NvcGUuV2ViS2l0QmxvYkJ1aWxkZXIgfHwgZ2xvYmFsU2NvcGUuTW96QmxvYkJ1aWxkZXIgfHwgZ2xvYmFsU2NvcGUuTVNCbG9iQnVpbGRlcjtcbiAgICAgICAgYmxvYiA9IG5ldyBCbG9iQnVpbGRlcigpO1xuICAgICAgICBibG9iLmFwcGVuZChjb250ZW50KTtcbiAgICAgICAgYmxvYiA9IGJsb2IuZ2V0QmxvYigpO1xuICAgICAgfVxuXG4gICAgICB2YXIgVVJMID0gZ2xvYmFsU2NvcGUuVVJMIHx8IGdsb2JhbFNjb3BlLndlYmtpdFVSTDtcbiAgICAgIHZhciBvYmplY3RVUkwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKGJsb2IpO1xuICAgICAgdmFyIHdvcmtlciA9IG5ldyBnbG9iYWxTY29wZVt3b3JrZXJDb25zdHJ1Y3Rvcl0ob2JqZWN0VVJMLCB3b3JrZXJPcHRpb25zKTtcbiAgICAgIFVSTC5yZXZva2VPYmplY3RVUkwob2JqZWN0VVJMKTtcbiAgICAgIHJldHVybiB3b3JrZXI7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgcmV0dXJuIG5ldyBnbG9iYWxTY29wZVt3b3JrZXJDb25zdHJ1Y3Rvcl0oXCJkYXRhOmFwcGxpY2F0aW9uL2phdmFzY3JpcHQsXCIuY29uY2F0KGVuY29kZVVSSUNvbXBvbmVudChjb250ZW50KSksIHdvcmtlck9wdGlvbnMpO1xuICAgIH1cbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmICghdXJsKSB7XG4gICAgICB0aHJvdyBFcnJvcihcIklubGluZSB3b3JrZXIgaXMgbm90IHN1cHBvcnRlZFwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IGdsb2JhbFNjb3BlW3dvcmtlckNvbnN0cnVjdG9yXSh1cmwsIHdvcmtlck9wdGlvbnMpO1xuICB9XG59OyIsIlxyXG52YXIgb3J0V2FzbVRocmVhZGVkID0gKCgpID0+IHtcclxuICB2YXIgX3NjcmlwdERpciA9IHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgZG9jdW1lbnQuY3VycmVudFNjcmlwdCA/IGRvY3VtZW50LmN1cnJlbnRTY3JpcHQuc3JjIDogdW5kZWZpbmVkO1xyXG4gIGlmICh0eXBlb2YgX19maWxlbmFtZSAhPT0gJ3VuZGVmaW5lZCcpIF9zY3JpcHREaXIgPSBfc2NyaXB0RGlyIHx8IF9fZmlsZW5hbWU7XHJcbiAgcmV0dXJuIChcclxuZnVuY3Rpb24ob3J0V2FzbVRocmVhZGVkKSB7XHJcbiAgb3J0V2FzbVRocmVhZGVkID0gb3J0V2FzbVRocmVhZGVkIHx8IHt9O1xyXG5cclxuXHJcbmZ1bmN0aW9uIGMoKXtrLmJ1ZmZlciE9bCYmbShrLmJ1ZmZlcik7cmV0dXJuIGFhfWZ1bmN0aW9uIHEoKXtrLmJ1ZmZlciE9bCYmbShrLmJ1ZmZlcik7cmV0dXJuIGJhfWZ1bmN0aW9uIHQoKXtrLmJ1ZmZlciE9bCYmbShrLmJ1ZmZlcik7cmV0dXJuIGNhfWZ1bmN0aW9uIHcoKXtrLmJ1ZmZlciE9bCYmbShrLmJ1ZmZlcik7cmV0dXJuIGRhfWZ1bmN0aW9uIGVhKCl7ay5idWZmZXIhPWwmJm0oay5idWZmZXIpO3JldHVybiBmYX1udWxsO3ZhciB4O3h8fCh4PXR5cGVvZiBvcnRXYXNtVGhyZWFkZWQgIT09ICd1bmRlZmluZWQnID8gb3J0V2FzbVRocmVhZGVkIDoge30pO3ZhciBoYSxpYTt4LnJlYWR5PW5ldyBQcm9taXNlKGZ1bmN0aW9uKGEsYil7aGE9YTtpYT1ifSk7XHJcbnZhciBqYT1PYmplY3QuYXNzaWduKHt9LHgpLGthPVwiLi90aGlzLnByb2dyYW1cIix6PShhLGIpPT57dGhyb3cgYjt9LGxhPVwib2JqZWN0XCI9PXR5cGVvZiB3aW5kb3csQT1cImZ1bmN0aW9uXCI9PXR5cGVvZiBpbXBvcnRTY3JpcHRzLEI9XCJvYmplY3RcIj09dHlwZW9mIHByb2Nlc3MmJlwib2JqZWN0XCI9PXR5cGVvZiBwcm9jZXNzLnZlcnNpb25zJiZcInN0cmluZ1wiPT10eXBlb2YgcHJvY2Vzcy52ZXJzaW9ucy5ub2RlLEM9eC5FTlZJUk9OTUVOVF9JU19QVEhSRUFEfHwhMSxEPVwiXCI7ZnVuY3Rpb24gbWEoYSl7cmV0dXJuIHgubG9jYXRlRmlsZT94LmxvY2F0ZUZpbGUoYSxEKTpEK2F9dmFyIG5hLEYsRyxmcyxILEk7XHJcbmlmKEIpe0Q9QT9yZXF1aXJlKFwicGF0aFwiKS5kaXJuYW1lKEQpK1wiL1wiOl9fZGlybmFtZStcIi9cIjtJPSgpPT57SHx8KGZzPXJlcXVpcmUoXCJmc1wiKSxIPXJlcXVpcmUoXCJwYXRoXCIpKX07bmE9ZnVuY3Rpb24oYixkKXtJKCk7Yj1ILm5vcm1hbGl6ZShiKTtyZXR1cm4gZnMucmVhZEZpbGVTeW5jKGIsZD92b2lkIDA6XCJ1dGY4XCIpfTtHPWI9PntiPW5hKGIsITApO2IuYnVmZmVyfHwoYj1uZXcgVWludDhBcnJheShiKSk7cmV0dXJuIGJ9O0Y9KGIsZCxlKT0+e0koKTtiPUgubm9ybWFsaXplKGIpO2ZzLnJlYWRGaWxlKGIsZnVuY3Rpb24oZyxoKXtnP2UoZyk6ZChoLmJ1ZmZlcil9KX07MTxwcm9jZXNzLmFyZ3YubGVuZ3RoJiYoa2E9cHJvY2Vzcy5hcmd2WzFdLnJlcGxhY2UoL1xcXFwvZyxcIi9cIikpO3Byb2Nlc3MuYXJndi5zbGljZSgyKTtwcm9jZXNzLm9uKFwidW5jYXVnaHRFeGNlcHRpb25cIixmdW5jdGlvbihiKXtpZighKGIgaW5zdGFuY2VvZiBLKSl0aHJvdyBiO30pO3Byb2Nlc3Mub24oXCJ1bmhhbmRsZWRSZWplY3Rpb25cIixcclxuZnVuY3Rpb24oYil7dGhyb3cgYjt9KTt6PShiLGQpPT57aWYobm9FeGl0UnVudGltZSl0aHJvdyBwcm9jZXNzLmV4aXRDb2RlPWIsZDtkIGluc3RhbmNlb2YgS3x8TChcImV4aXRpbmcgZHVlIHRvIGV4Y2VwdGlvbjogXCIrZCk7cHJvY2Vzcy5leGl0KGIpfTt4Lmluc3BlY3Q9ZnVuY3Rpb24oKXtyZXR1cm5cIltFbXNjcmlwdGVuIE1vZHVsZSBvYmplY3RdXCJ9O2xldCBhO3RyeXthPXJlcXVpcmUoXCJ3b3JrZXJfdGhyZWFkc1wiKX1jYXRjaChiKXt0aHJvdyBjb25zb2xlLmVycm9yKCdUaGUgXCJ3b3JrZXJfdGhyZWFkc1wiIG1vZHVsZSBpcyBub3Qgc3VwcG9ydGVkIGluIHRoaXMgbm9kZS5qcyBidWlsZCAtIHBlcmhhcHMgYSBuZXdlciB2ZXJzaW9uIGlzIG5lZWRlZD8nKSxiO31nbG9iYWwuV29ya2VyPWEuV29ya2VyfWVsc2UgaWYobGF8fEEpQT9EPXNlbGYubG9jYXRpb24uaHJlZjpcInVuZGVmaW5lZFwiIT10eXBlb2YgZG9jdW1lbnQmJmRvY3VtZW50LmN1cnJlbnRTY3JpcHQmJihEPWRvY3VtZW50LmN1cnJlbnRTY3JpcHQuc3JjKSxcclxuX3NjcmlwdERpciYmKEQ9X3NjcmlwdERpciksMCE9PUQuaW5kZXhPZihcImJsb2I6XCIpP0Q9RC5zdWJzdHIoMCxELnJlcGxhY2UoL1s/I10uKi8sXCJcIikubGFzdEluZGV4T2YoXCIvXCIpKzEpOkQ9XCJcIixCfHwobmE9YT0+e3ZhciBiPW5ldyBYTUxIdHRwUmVxdWVzdDtiLm9wZW4oXCJHRVRcIixhLCExKTtiLnNlbmQobnVsbCk7cmV0dXJuIGIucmVzcG9uc2VUZXh0fSxBJiYoRz1hPT57dmFyIGI9bmV3IFhNTEh0dHBSZXF1ZXN0O2Iub3BlbihcIkdFVFwiLGEsITEpO2IucmVzcG9uc2VUeXBlPVwiYXJyYXlidWZmZXJcIjtiLnNlbmQobnVsbCk7cmV0dXJuIG5ldyBVaW50OEFycmF5KGIucmVzcG9uc2UpfSksRj0oYSxiLGQpPT57dmFyIGU9bmV3IFhNTEh0dHBSZXF1ZXN0O2Uub3BlbihcIkdFVFwiLGEsITApO2UucmVzcG9uc2VUeXBlPVwiYXJyYXlidWZmZXJcIjtlLm9ubG9hZD0oKT0+ezIwMD09ZS5zdGF0dXN8fDA9PWUuc3RhdHVzJiZlLnJlc3BvbnNlP2IoZS5yZXNwb25zZSk6ZCgpfTtlLm9uZXJyb3I9XHJcbmQ7ZS5zZW5kKG51bGwpfSk7QiYmXCJ1bmRlZmluZWRcIj09dHlwZW9mIHBlcmZvcm1hbmNlJiYoZ2xvYmFsLnBlcmZvcm1hbmNlPXJlcXVpcmUoXCJwZXJmX2hvb2tzXCIpLnBlcmZvcm1hbmNlKTt2YXIgb2E9Y29uc29sZS5sb2cuYmluZChjb25zb2xlKSxwYT1jb25zb2xlLndhcm4uYmluZChjb25zb2xlKTtCJiYoSSgpLG9hPWE9PmZzLndyaXRlU3luYygxLGErXCJcXG5cIikscGE9YT0+ZnMud3JpdGVTeW5jKDIsYStcIlxcblwiKSk7dmFyIHFhPXgucHJpbnR8fG9hLEw9eC5wcmludEVycnx8cGE7T2JqZWN0LmFzc2lnbih4LGphKTtqYT1udWxsO3gudGhpc1Byb2dyYW0mJihrYT14LnRoaXNQcm9ncmFtKTt4LnF1aXQmJih6PXgucXVpdCk7dmFyIE07eC53YXNtQmluYXJ5JiYoTT14Lndhc21CaW5hcnkpO3ZhciBub0V4aXRSdW50aW1lPXgubm9FeGl0UnVudGltZXx8ITA7XCJvYmplY3RcIiE9dHlwZW9mIFdlYkFzc2VtYmx5JiZOKFwibm8gbmF0aXZlIHdhc20gc3VwcG9ydCBkZXRlY3RlZFwiKTtcclxudmFyIGsscmEsc2E9ITEsdGE9XCJ1bmRlZmluZWRcIiE9dHlwZW9mIFRleHREZWNvZGVyP25ldyBUZXh0RGVjb2RlcihcInV0ZjhcIik6dm9pZCAwO1xyXG5mdW5jdGlvbiB1YShhLGIsZCl7Yj4+Pj0wO3ZhciBlPWIrZDtmb3IoZD1iO2FbZF0mJiEoZD49ZSk7KSsrZDtpZigxNjxkLWImJmEuYnVmZmVyJiZ0YSlyZXR1cm4gdGEuZGVjb2RlKGEuYnVmZmVyIGluc3RhbmNlb2YgU2hhcmVkQXJyYXlCdWZmZXI/YS5zbGljZShiLGQpOmEuc3ViYXJyYXkoYixkKSk7Zm9yKGU9XCJcIjtiPGQ7KXt2YXIgZz1hW2IrK107aWYoZyYxMjgpe3ZhciBoPWFbYisrXSY2MztpZigxOTI9PShnJjIyNCkpZSs9U3RyaW5nLmZyb21DaGFyQ29kZSgoZyYzMSk8PDZ8aCk7ZWxzZXt2YXIgbj1hW2IrK10mNjM7Zz0yMjQ9PShnJjI0MCk/KGcmMTUpPDwxMnxoPDw2fG46KGcmNyk8PDE4fGg8PDEyfG48PDZ8YVtiKytdJjYzOzY1NTM2Pmc/ZSs9U3RyaW5nLmZyb21DaGFyQ29kZShnKTooZy09NjU1MzYsZSs9U3RyaW5nLmZyb21DaGFyQ29kZSg1NTI5NnxnPj4xMCw1NjMyMHxnJjEwMjMpKX19ZWxzZSBlKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGcpfXJldHVybiBlfVxyXG5mdW5jdGlvbiB2YShhLGIpe3JldHVybihhPj4+PTApP3VhKHEoKSxhLGIpOlwiXCJ9XHJcbmZ1bmN0aW9uIHdhKGEsYixkLGUpe2Q+Pj49MDtpZighKDA8ZSkpcmV0dXJuIDA7dmFyIGc9ZDtlPWQrZS0xO2Zvcih2YXIgaD0wO2g8YS5sZW5ndGg7KytoKXt2YXIgbj1hLmNoYXJDb2RlQXQoaCk7aWYoNTUyOTY8PW4mJjU3MzQzPj1uKXt2YXIgdT1hLmNoYXJDb2RlQXQoKytoKTtuPTY1NTM2KygobiYxMDIzKTw8MTApfHUmMTAyM31pZigxMjc+PW4pe2lmKGQ+PWUpYnJlYWs7YltkKys+Pj4wXT1ufWVsc2V7aWYoMjA0Nz49bil7aWYoZCsxPj1lKWJyZWFrO2JbZCsrPj4+MF09MTkyfG4+PjZ9ZWxzZXtpZig2NTUzNT49bil7aWYoZCsyPj1lKWJyZWFrO2JbZCsrPj4+MF09MjI0fG4+PjEyfWVsc2V7aWYoZCszPj1lKWJyZWFrO2JbZCsrPj4+MF09MjQwfG4+PjE4O2JbZCsrPj4+MF09MTI4fG4+PjEyJjYzfWJbZCsrPj4+MF09MTI4fG4+PjYmNjN9YltkKys+Pj4wXT0xMjh8biY2M319YltkPj4+MF09MDtyZXR1cm4gZC1nfVxyXG5mdW5jdGlvbiB4YShhKXtmb3IodmFyIGI9MCxkPTA7ZDxhLmxlbmd0aDsrK2Qpe3ZhciBlPWEuY2hhckNvZGVBdChkKTsxMjc+PWU/YisrOjIwNDc+PWU/Yis9Mjo1NTI5Njw9ZSYmNTczNDM+PWU/KGIrPTQsKytkKTpiKz0zfXJldHVybiBifXZhciBsLGFhLGJhLGNhLGRhLGZhO0MmJihsPXguYnVmZmVyKTtmdW5jdGlvbiBtKGEpe2w9YTt4LkhFQVA4PWFhPW5ldyBJbnQ4QXJyYXkoYSk7eC5IRUFQMTY9bmV3IEludDE2QXJyYXkoYSk7eC5IRUFQMzI9Y2E9bmV3IEludDMyQXJyYXkoYSk7eC5IRUFQVTg9YmE9bmV3IFVpbnQ4QXJyYXkoYSk7eC5IRUFQVTE2PW5ldyBVaW50MTZBcnJheShhKTt4LkhFQVBVMzI9ZGE9bmV3IFVpbnQzMkFycmF5KGEpO3guSEVBUEYzMj1uZXcgRmxvYXQzMkFycmF5KGEpO3guSEVBUEY2ND1mYT1uZXcgRmxvYXQ2NEFycmF5KGEpfXZhciB5YT14LklOSVRJQUxfTUVNT1JZfHwxNjc3NzIxNjtcclxuaWYoQylrPXgud2FzbU1lbW9yeSxsPXguYnVmZmVyO2Vsc2UgaWYoeC53YXNtTWVtb3J5KWs9eC53YXNtTWVtb3J5O2Vsc2UgaWYoaz1uZXcgV2ViQXNzZW1ibHkuTWVtb3J5KHtpbml0aWFsOnlhLzY1NTM2LG1heGltdW06NjU1MzYsc2hhcmVkOiEwfSksIShrLmJ1ZmZlciBpbnN0YW5jZW9mIFNoYXJlZEFycmF5QnVmZmVyKSl0aHJvdyBMKFwicmVxdWVzdGVkIGEgc2hhcmVkIFdlYkFzc2VtYmx5Lk1lbW9yeSBidXQgdGhlIHJldHVybmVkIGJ1ZmZlciBpcyBub3QgYSBTaGFyZWRBcnJheUJ1ZmZlciwgaW5kaWNhdGluZyB0aGF0IHdoaWxlIHRoZSBicm93c2VyIGhhcyBTaGFyZWRBcnJheUJ1ZmZlciBpdCBkb2VzIG5vdCBoYXZlIFdlYkFzc2VtYmx5IHRocmVhZHMgc3VwcG9ydCAtIHlvdSBtYXkgbmVlZCB0byBzZXQgYSBmbGFnXCIpLEImJmNvbnNvbGUubG9nKFwiKG9uIG5vZGUgeW91IG1heSBuZWVkOiAtLWV4cGVyaW1lbnRhbC13YXNtLXRocmVhZHMgLS1leHBlcmltZW50YWwtd2FzbS1idWxrLW1lbW9yeSBhbmQgYWxzbyB1c2UgYSByZWNlbnQgdmVyc2lvbilcIiksXHJcbkVycm9yKFwiYmFkIG1lbW9yeVwiKTtrJiYobD1rLmJ1ZmZlcik7eWE9bC5ieXRlTGVuZ3RoO20obCk7dmFyIHphLEFhPVtdLEJhPVtdLENhPVtdO2Z1bmN0aW9uIERhKCl7dmFyIGE9eC5wcmVSdW4uc2hpZnQoKTtBYS51bnNoaWZ0KGEpfXZhciBPPTAsRWE9bnVsbCxQPW51bGw7ZnVuY3Rpb24gTihhKXtpZihDKXBvc3RNZXNzYWdlKHtjbWQ6XCJvbkFib3J0XCIsYXJnOmF9KTtlbHNlIGlmKHgub25BYm9ydCl4Lm9uQWJvcnQoYSk7YT1cIkFib3J0ZWQoXCIrYStcIilcIjtMKGEpO3NhPSEwO2E9bmV3IFdlYkFzc2VtYmx5LlJ1bnRpbWVFcnJvcihhK1wiLiBCdWlsZCB3aXRoIC1zQVNTRVJUSU9OUyBmb3IgbW9yZSBpbmZvLlwiKTtpYShhKTt0aHJvdyBhO31mdW5jdGlvbiBGYSgpe3JldHVybiBRLnN0YXJ0c1dpdGgoXCJkYXRhOmFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbTtiYXNlNjQsXCIpfXZhciBRO1E9XCJvcnQtd2FzbS10aHJlYWRlZC53YXNtXCI7RmEoKXx8KFE9bWEoUSkpO1xyXG5mdW5jdGlvbiBHYSgpe3ZhciBhPVE7dHJ5e2lmKGE9PVEmJk0pcmV0dXJuIG5ldyBVaW50OEFycmF5KE0pO2lmKEcpcmV0dXJuIEcoYSk7dGhyb3dcImJvdGggYXN5bmMgYW5kIHN5bmMgZmV0Y2hpbmcgb2YgdGhlIHdhc20gZmFpbGVkXCI7fWNhdGNoKGIpe04oYil9fVxyXG5mdW5jdGlvbiBIYSgpe2lmKCFNJiYobGF8fEEpKXtpZihcImZ1bmN0aW9uXCI9PXR5cGVvZiBmZXRjaCYmIVEuc3RhcnRzV2l0aChcImZpbGU6Ly9cIikpcmV0dXJuIGZldGNoKFEse2NyZWRlbnRpYWxzOlwic2FtZS1vcmlnaW5cIn0pLnRoZW4oZnVuY3Rpb24oYSl7aWYoIWEub2spdGhyb3dcImZhaWxlZCB0byBsb2FkIHdhc20gYmluYXJ5IGZpbGUgYXQgJ1wiK1ErXCInXCI7cmV0dXJuIGEuYXJyYXlCdWZmZXIoKX0pLmNhdGNoKGZ1bmN0aW9uKCl7cmV0dXJuIEdhKCl9KTtpZihGKXJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihhLGIpe0YoUSxmdW5jdGlvbihkKXthKG5ldyBVaW50OEFycmF5KGQpKX0sYil9KX1yZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbigpe3JldHVybiBHYSgpfSl9dmFyIElhPXt9O1xyXG5mdW5jdGlvbiBLKGEpe3RoaXMubmFtZT1cIkV4aXRTdGF0dXNcIjt0aGlzLm1lc3NhZ2U9XCJQcm9ncmFtIHRlcm1pbmF0ZWQgd2l0aCBleGl0KFwiK2ErXCIpXCI7dGhpcy5zdGF0dXM9YX1mdW5jdGlvbiBKYShhKXsoYT1SLkxhW2FdKXx8TigpO1IuWGEoYSl9ZnVuY3Rpb24gS2EoYSl7dmFyIGI9Ui5sYigpO2lmKCFiKXJldHVybiA2O1IuUmEucHVzaChiKTtSLkxhW2EuS2FdPWI7Yi5LYT1hLkthO3ZhciBkPXtjbWQ6XCJydW5cIixzdGFydF9yb3V0aW5lOmEucGIsYXJnOmEuaWIscHRocmVhZF9wdHI6YS5LYX07Yi5RYT0oKT0+e2QudGltZT1wZXJmb3JtYW5jZS5ub3coKTtiLnBvc3RNZXNzYWdlKGQsYS52Yil9O2IubG9hZGVkJiYoYi5RYSgpLGRlbGV0ZSBiLlFhKTtyZXR1cm4gMH1mdW5jdGlvbiBMYShhKXtpZihDKXJldHVybiBTKDEsMSxhKTtpZighbm9FeGl0UnVudGltZSl7Ui5xYigpO2lmKHgub25FeGl0KXgub25FeGl0KGEpO3NhPSEwfXooYSxuZXcgSyhhKSl9XHJcbmZ1bmN0aW9uIE1hKGEsYil7aWYoIWImJkMpdGhyb3cgTmEoYSksXCJ1bndpbmRcIjtMYShhKX1cclxudmFyIFI9e09hOltdLFJhOltdLCRhOltdLExhOnt9LFVhOmZ1bmN0aW9uKCl7QyYmUi5tYigpfSx4YjpmdW5jdGlvbigpe30sbWI6ZnVuY3Rpb24oKXtSLnJlY2VpdmVPYmplY3RUcmFuc2Zlcj1SLm9iO1IudGhyZWFkSW5pdFRMUz1SLlphO1Iuc2V0RXhpdFN0YXR1cz1SLllhO25vRXhpdFJ1bnRpbWU9ITF9LFlhOmZ1bmN0aW9uKCl7fSxxYjpmdW5jdGlvbigpe2Zvcih2YXIgYSBvZiBPYmplY3QudmFsdWVzKFIuTGEpKVIuWGEoYSk7Zm9yKGEgb2YgUi5PYSlhLnRlcm1pbmF0ZSgpO1IuT2E9W119LFhhOmZ1bmN0aW9uKGEpe3ZhciBiPWEuS2E7ZGVsZXRlIFIuTGFbYl07Ui5PYS5wdXNoKGEpO1IuUmEuc3BsaWNlKFIuUmEuaW5kZXhPZihhKSwxKTthLkthPTA7T2EoYil9LG9iOmZ1bmN0aW9uKCl7fSxaYTpmdW5jdGlvbigpe1IuJGEuZm9yRWFjaChhPT5hKCkpfSxuYjpmdW5jdGlvbihhLGIpe2Eub25tZXNzYWdlPWQ9PntkPWQuZGF0YTt2YXIgZT1kLmNtZDthLkthJiYoUi5rYj1hLkthKTtcclxuaWYoZC50YXJnZXRUaHJlYWQmJmQudGFyZ2V0VGhyZWFkIT1UKCkpe3ZhciBnPVIuTGFbZC55Yl07Zz9nLnBvc3RNZXNzYWdlKGQsZC50cmFuc2Zlckxpc3QpOkwoJ0ludGVybmFsIGVycm9yISBXb3JrZXIgc2VudCBhIG1lc3NhZ2UgXCInK2UrJ1wiIHRvIHRhcmdldCBwdGhyZWFkICcrZC50YXJnZXRUaHJlYWQrXCIsIGJ1dCB0aGF0IHRocmVhZCBubyBsb25nZXIgZXhpc3RzIVwiKX1lbHNlIGlmKFwicHJvY2Vzc1Byb3h5aW5nUXVldWVcIj09PWUpUGEoZC5xdWV1ZSk7ZWxzZSBpZihcInNwYXduVGhyZWFkXCI9PT1lKUthKGQpO2Vsc2UgaWYoXCJjbGVhbnVwVGhyZWFkXCI9PT1lKUphKGQudGhyZWFkKTtlbHNlIGlmKFwia2lsbFRocmVhZFwiPT09ZSlkPWQudGhyZWFkLGU9Ui5MYVtkXSxkZWxldGUgUi5MYVtkXSxlLnRlcm1pbmF0ZSgpLE9hKGQpLFIuUmEuc3BsaWNlKFIuUmEuaW5kZXhPZihlKSwxKSxlLkthPTA7ZWxzZSBpZihcImNhbmNlbFRocmVhZFwiPT09ZSlSLkxhW2QudGhyZWFkXS5wb3N0TWVzc2FnZSh7Y21kOlwiY2FuY2VsXCJ9KTtcclxuZWxzZSBpZihcImxvYWRlZFwiPT09ZSlhLmxvYWRlZD0hMCxiJiZiKGEpLGEuUWEmJihhLlFhKCksZGVsZXRlIGEuUWEpO2Vsc2UgaWYoXCJwcmludFwiPT09ZSlxYShcIlRocmVhZCBcIitkLnRocmVhZElkK1wiOiBcIitkLnRleHQpO2Vsc2UgaWYoXCJwcmludEVyclwiPT09ZSlMKFwiVGhyZWFkIFwiK2QudGhyZWFkSWQrXCI6IFwiK2QudGV4dCk7ZWxzZSBpZihcImFsZXJ0XCI9PT1lKWFsZXJ0KFwiVGhyZWFkIFwiK2QudGhyZWFkSWQrXCI6IFwiK2QudGV4dCk7ZWxzZSBpZihcInNldGltbWVkaWF0ZVwiPT09ZC50YXJnZXQpYS5wb3N0TWVzc2FnZShkKTtlbHNlIGlmKFwib25BYm9ydFwiPT09ZSl7aWYoeC5vbkFib3J0KXgub25BYm9ydChkLmFyZyl9ZWxzZSBlJiZMKFwid29ya2VyIHNlbnQgYW4gdW5rbm93biBjb21tYW5kIFwiK2UpO1Iua2I9dm9pZCAwfTthLm9uZXJyb3I9ZD0+e0woXCJ3b3JrZXIgc2VudCBhbiBlcnJvciEgXCIrZC5maWxlbmFtZStcIjpcIitkLmxpbmVubytcIjogXCIrZC5tZXNzYWdlKTt0aHJvdyBkO307QiYmXHJcbihhLm9uKFwibWVzc2FnZVwiLGZ1bmN0aW9uKGQpe2Eub25tZXNzYWdlKHtkYXRhOmR9KX0pLGEub24oXCJlcnJvclwiLGZ1bmN0aW9uKGQpe2Eub25lcnJvcihkKX0pLGEub24oXCJkZXRhY2hlZEV4aXRcIixmdW5jdGlvbigpe30pKTthLnBvc3RNZXNzYWdlKHtjbWQ6XCJsb2FkXCIsdXJsT3JCbG9iOngubWFpblNjcmlwdFVybE9yQmxvYnx8X3NjcmlwdERpcix3YXNtTWVtb3J5Omssd2FzbU1vZHVsZTpyYX0pfSxoYjpmdW5jdGlvbigpe3ZhciBhPW1hKFwib3J0LXdhc20tdGhyZWFkZWQud29ya2VyLmpzXCIpO1IuT2EucHVzaChuZXcgV29ya2VyKGEpKX0sbGI6ZnVuY3Rpb24oKXswPT1SLk9hLmxlbmd0aCYmKFIuaGIoKSxSLm5iKFIuT2FbMF0pKTtyZXR1cm4gUi5PYS5wb3AoKX19O3guUFRocmVhZD1SO2Z1bmN0aW9uIFUoYSl7Zm9yKDswPGEubGVuZ3RoOylhLnNoaWZ0KCkoeCl9ZnVuY3Rpb24gUWEoYSl7dmFyIGI9UmEoKTthPWEoKTtWKGIpO3JldHVybiBhfVxyXG54LmVzdGFibGlzaFN0YWNrU3BhY2U9ZnVuY3Rpb24oKXt2YXIgYT1UKCksYj10KClbYSs0ND4+Mj4+PjBdO2E9dCgpW2ErNDg+PjI+Pj4wXTtTYShiLGItYSk7VihiKX07ZnVuY3Rpb24gTmEoYSl7aWYoQylyZXR1cm4gUygyLDAsYSk7dHJ5e01hKGEpfWNhdGNoKGIpe2IgaW5zdGFuY2VvZiBLfHxcInVud2luZFwiPT1ifHx6KDEsYil9fXZhciBXPVtdO3guaW52b2tlRW50cnlQb2ludD1mdW5jdGlvbihhLGIpe3ZhciBkPVdbYV07ZHx8KGE+PVcubGVuZ3RoJiYoVy5sZW5ndGg9YSsxKSxXW2FdPWQ9emEuZ2V0KGEpKTthPWQoYik7bm9FeGl0UnVudGltZT9SLllhKGEpOlRhKGEpfTtmdW5jdGlvbiBVYShhLGIpe2MoKS5zZXQoYSxiPj4+MCl9XHJcbmZ1bmN0aW9uIFZhKGEpe3RoaXMuUGE9YS0yNDt0aGlzLmdiPWZ1bmN0aW9uKGIpe3coKVt0aGlzLlBhKzQ+PjI+Pj4wXT1ifTt0aGlzLmNiPWZ1bmN0aW9uKGIpe3coKVt0aGlzLlBhKzg+PjI+Pj4wXT1ifTt0aGlzLmViPWZ1bmN0aW9uKCl7dCgpW3RoaXMuUGE+PjI+Pj4wXT0wfTt0aGlzLmJiPWZ1bmN0aW9uKCl7dmFyIGI9MDtjKClbdGhpcy5QYSsxMj4+MD4+PjBdPWJ9O3RoaXMuZmI9ZnVuY3Rpb24oKXt2YXIgYj0wO2MoKVt0aGlzLlBhKzEzPj4wPj4+MF09Yn07dGhpcy5VYT1mdW5jdGlvbihiLGQpe3RoaXMuYWIoKTt0aGlzLmdiKGIpO3RoaXMuY2IoZCk7dGhpcy5lYigpO3RoaXMuYmIoKTt0aGlzLmZiKCl9O3RoaXMuYWI9ZnVuY3Rpb24oKXt3KClbdGhpcy5QYSsxNj4+Mj4+PjBdPTB9fXZhciBXYT0wO2Z1bmN0aW9uIFhhKGEsYixkLGUpe3JldHVybiBDP1MoMywxLGEsYixkLGUpOllhKGEsYixkLGUpfVxyXG5mdW5jdGlvbiBZYShhLGIsZCxlKXtpZihcInVuZGVmaW5lZFwiPT10eXBlb2YgU2hhcmVkQXJyYXlCdWZmZXIpcmV0dXJuIEwoXCJDdXJyZW50IGVudmlyb25tZW50IGRvZXMgbm90IHN1cHBvcnQgU2hhcmVkQXJyYXlCdWZmZXIsIHB0aHJlYWRzIGFyZSBub3QgYXZhaWxhYmxlIVwiKSw2O3ZhciBnPVtdO2lmKEMmJjA9PT1nLmxlbmd0aClyZXR1cm4gWGEoYSxiLGQsZSk7YT17cGI6ZCxLYTphLGliOmUsdmI6Z307cmV0dXJuIEM/KGEud2I9XCJzcGF3blRocmVhZFwiLHBvc3RNZXNzYWdlKGEsZyksMCk6S2EoYSl9ZnVuY3Rpb24gWmEoYSxiLGQpe3JldHVybiBDP1MoNCwxLGEsYixkKTowfWZ1bmN0aW9uICRhKGEsYil7aWYoQylyZXR1cm4gUyg1LDEsYSxiKX1mdW5jdGlvbiBhYihhLGIpe2lmKEMpcmV0dXJuIFMoNiwxLGEsYil9ZnVuY3Rpb24gYmIoYSxiLGQpe2lmKEMpcmV0dXJuIFMoNywxLGEsYixkKX1mdW5jdGlvbiBjYihhLGIsZCl7cmV0dXJuIEM/Uyg4LDEsYSxiLGQpOjB9XHJcbmZ1bmN0aW9uIGRiKGEsYil7aWYoQylyZXR1cm4gUyg5LDEsYSxiKX1mdW5jdGlvbiBlYihhLGIsZCl7aWYoQylyZXR1cm4gUygxMCwxLGEsYixkKX1mdW5jdGlvbiBmYihhLGIsZCxlKXtpZihDKXJldHVybiBTKDExLDEsYSxiLGQsZSl9ZnVuY3Rpb24gZ2IoYSxiLGQsZSl7aWYoQylyZXR1cm4gUygxMiwxLGEsYixkLGUpfWZ1bmN0aW9uIGhiKGEsYixkLGUpe2lmKEMpcmV0dXJuIFMoMTMsMSxhLGIsZCxlKX1mdW5jdGlvbiBpYihhKXtpZihDKXJldHVybiBTKDE0LDEsYSl9ZnVuY3Rpb24gamIoYSxiKXtpZihDKXJldHVybiBTKDE1LDEsYSxiKX1mdW5jdGlvbiBrYihhLGIsZCl7aWYoQylyZXR1cm4gUygxNiwxLGEsYixkKX1mdW5jdGlvbiBQYShhKXtBdG9taWNzLnN0b3JlKHQoKSxhPj4yLDEpO1QoKSYmbGIoYSk7QXRvbWljcy5jb21wYXJlRXhjaGFuZ2UodCgpLGE+PjIsMSwwKX14LmV4ZWN1dGVOb3RpZmllZFByb3h5aW5nUXVldWU9UGE7XHJcbmZ1bmN0aW9uIG1iKGEpe3JldHVybiB3KClbYT4+PjJdKzQyOTQ5NjcyOTYqdCgpW2ErND4+PjJdfWZ1bmN0aW9uIG5iKGEsYixkLGUsZyxoKXtyZXR1cm4gQz9TKDE3LDEsYSxiLGQsZSxnLGgpOi01Mn1mdW5jdGlvbiBvYihhLGIsZCxlLGcsaCl7aWYoQylyZXR1cm4gUygxOCwxLGEsYixkLGUsZyxoKX1mdW5jdGlvbiBwYihhKXt2YXIgYj14YShhKSsxLGQ9cWIoYik7ZCYmd2EoYSxjKCksZCxiKTtyZXR1cm4gZH1cclxuZnVuY3Rpb24gcmIoYSxiLGQpe2Z1bmN0aW9uIGUodil7cmV0dXJuKHY9di50b1RpbWVTdHJpbmcoKS5tYXRjaCgvXFwoKFtBLVphLXogXSspXFwpJC8pKT92WzFdOlwiR01UXCJ9aWYoQylyZXR1cm4gUygxOSwxLGEsYixkKTt2YXIgZz0obmV3IERhdGUpLmdldEZ1bGxZZWFyKCksaD1uZXcgRGF0ZShnLDAsMSksbj1uZXcgRGF0ZShnLDYsMSk7Zz1oLmdldFRpbWV6b25lT2Zmc2V0KCk7dmFyIHU9bi5nZXRUaW1lem9uZU9mZnNldCgpLEU9TWF0aC5tYXgoZyx1KTt0KClbYT4+Mj4+PjBdPTYwKkU7dCgpW2I+PjI+Pj4wXT1OdW1iZXIoZyE9dSk7YT1lKGgpO2I9ZShuKTthPXBiKGEpO2I9cGIoYik7dTxnPyh3KClbZD4+Mj4+PjBdPWEsdygpW2QrND4+Mj4+PjBdPWIpOih3KClbZD4+Mj4+PjBdPWIsdygpW2QrND4+Mj4+PjBdPWEpfWZ1bmN0aW9uIHNiKGEsYixkKXtzYi5qYnx8KHNiLmpiPSEwLHJiKGEsYixkKSl9dmFyIFgsdGI7XHJcbnRiPUI/KCk9Pnt2YXIgYT1wcm9jZXNzLmhydGltZSgpO3JldHVybiAxRTMqYVswXSthWzFdLzFFNn06Qz8oKT0+cGVyZm9ybWFuY2Uubm93KCkteC5fX3BlcmZvcm1hbmNlX25vd19jbG9ja19kcmlmdDooKT0+cGVyZm9ybWFuY2Uubm93KCk7ZnVuY3Rpb24gUyhhLGIpe3ZhciBkPWFyZ3VtZW50cy5sZW5ndGgtMixlPWFyZ3VtZW50cztyZXR1cm4gUWEoKCk9Pntmb3IodmFyIGc9dWIoOCpkKSxoPWc+PjMsbj0wO248ZDtuKyspe3ZhciB1PWVbMituXTtlYSgpW2grbj4+PjBdPXV9cmV0dXJuIHZiKGEsZCxnLGIpfSl9dmFyIHdiPVtdLHhiPXt9O1xyXG5mdW5jdGlvbiB5Yigpe2lmKCF6Yil7dmFyIGE9e1VTRVI6XCJ3ZWJfdXNlclwiLExPR05BTUU6XCJ3ZWJfdXNlclwiLFBBVEg6XCIvXCIsUFdEOlwiL1wiLEhPTUU6XCIvaG9tZS93ZWJfdXNlclwiLExBTkc6KFwib2JqZWN0XCI9PXR5cGVvZiBuYXZpZ2F0b3ImJm5hdmlnYXRvci5sYW5ndWFnZXMmJm5hdmlnYXRvci5sYW5ndWFnZXNbMF18fFwiQ1wiKS5yZXBsYWNlKFwiLVwiLFwiX1wiKStcIi5VVEYtOFwiLF86a2F8fFwiLi90aGlzLnByb2dyYW1cIn0sYjtmb3IoYiBpbiB4Yil2b2lkIDA9PT14YltiXT9kZWxldGUgYVtiXTphW2JdPXhiW2JdO3ZhciBkPVtdO2ZvcihiIGluIGEpZC5wdXNoKGIrXCI9XCIrYVtiXSk7emI9ZH1yZXR1cm4gemJ9dmFyIHpiO1xyXG5mdW5jdGlvbiBBYihhLGIpe2lmKEMpcmV0dXJuIFMoMjAsMSxhLGIpO3ZhciBkPTA7eWIoKS5mb3JFYWNoKGZ1bmN0aW9uKGUsZyl7dmFyIGg9YitkO2c9dygpW2ErNCpnPj4yPj4+MF09aDtmb3IoaD0wO2g8ZS5sZW5ndGg7KytoKWMoKVtnKys+PjA+Pj4wXT1lLmNoYXJDb2RlQXQoaCk7YygpW2c+PjA+Pj4wXT0wO2QrPWUubGVuZ3RoKzF9KTtyZXR1cm4gMH1mdW5jdGlvbiBCYihhLGIpe2lmKEMpcmV0dXJuIFMoMjEsMSxhLGIpO3ZhciBkPXliKCk7dygpW2E+PjI+Pj4wXT1kLmxlbmd0aDt2YXIgZT0wO2QuZm9yRWFjaChmdW5jdGlvbihnKXtlKz1nLmxlbmd0aCsxfSk7dygpW2I+PjI+Pj4wXT1lO3JldHVybiAwfWZ1bmN0aW9uIENiKGEpe3JldHVybiBDP1MoMjIsMSxhKTo1Mn1mdW5jdGlvbiBHYihhLGIsZCxlKXtyZXR1cm4gQz9TKDIzLDEsYSxiLGQsZSk6NTJ9ZnVuY3Rpb24gSGIoYSxiLGQsZSxnKXtyZXR1cm4gQz9TKDI0LDEsYSxiLGQsZSxnKTo3MH1cclxudmFyIEliPVtudWxsLFtdLFtdXTtmdW5jdGlvbiBKYihhLGIsZCxlKXtpZihDKXJldHVybiBTKDI1LDEsYSxiLGQsZSk7Zm9yKHZhciBnPTAsaD0wO2g8ZDtoKyspe3ZhciBuPXcoKVtiPj4yPj4+MF0sdT13KClbYis0Pj4yPj4+MF07Yis9ODtmb3IodmFyIEU9MDtFPHU7RSsrKXt2YXIgdj1xKClbbitFPj4+MF0seT1JYlthXTswPT09dnx8MTA9PT12PygoMT09PWE/cWE6TCkodWEoeSwwKSkseS5sZW5ndGg9MCk6eS5wdXNoKHYpfWcrPXV9dygpW2U+PjI+Pj4wXT1nO3JldHVybiAwfVxyXG5mdW5jdGlvbiBLYigpe2lmKFwib2JqZWN0XCI9PXR5cGVvZiBjcnlwdG8mJlwiZnVuY3Rpb25cIj09dHlwZW9mIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMpe3ZhciBhPW5ldyBVaW50OEFycmF5KDEpO3JldHVybigpPT57Y3J5cHRvLmdldFJhbmRvbVZhbHVlcyhhKTtyZXR1cm4gYVswXX19aWYoQil0cnl7dmFyIGI9cmVxdWlyZShcImNyeXB0b1wiKTtyZXR1cm4oKT0+Yi5yYW5kb21CeXRlcygxKVswXX1jYXRjaChkKXt9cmV0dXJuKCk9Pk4oXCJyYW5kb21EZXZpY2VcIil9ZnVuY3Rpb24gWShhLGIpe1kuV2F8fChZLldhPUtiKCkpO2Zvcih2YXIgZD0wO2Q8YjtkKyspYygpW2ErZD4+MD4+PjBdPVkuV2EoKTtyZXR1cm4gMH1mdW5jdGlvbiBaKGEpe3JldHVybiAwPT09YSU0JiYoMCE9PWElMTAwfHwwPT09YSU0MDApfXZhciBMYj1bMzEsMjksMzEsMzAsMzEsMzAsMzEsMzEsMzAsMzEsMzAsMzFdLE1iPVszMSwyOCwzMSwzMCwzMSwzMCwzMSwzMSwzMCwzMSwzMCwzMV07XHJcbmZ1bmN0aW9uIE5iKGEpe3ZhciBiPUFycmF5KHhhKGEpKzEpO3dhKGEsYiwwLGIubGVuZ3RoKTtyZXR1cm4gYn1cclxuZnVuY3Rpb24gT2IoYSxiLGQsZSl7ZnVuY3Rpb24gZyhmLHAscil7Zm9yKGY9XCJudW1iZXJcIj09dHlwZW9mIGY/Zi50b1N0cmluZygpOmZ8fFwiXCI7Zi5sZW5ndGg8cDspZj1yWzBdK2Y7cmV0dXJuIGZ9ZnVuY3Rpb24gaChmLHApe3JldHVybiBnKGYscCxcIjBcIil9ZnVuY3Rpb24gbihmLHApe2Z1bmN0aW9uIHIoRGIpe3JldHVybiAwPkRiPy0xOjA8RGI/MTowfXZhciBKOzA9PT0oSj1yKGYuZ2V0RnVsbFllYXIoKS1wLmdldEZ1bGxZZWFyKCkpKSYmMD09PShKPXIoZi5nZXRNb250aCgpLXAuZ2V0TW9udGgoKSkpJiYoSj1yKGYuZ2V0RGF0ZSgpLXAuZ2V0RGF0ZSgpKSk7cmV0dXJuIEp9ZnVuY3Rpb24gdShmKXtzd2l0Y2goZi5nZXREYXkoKSl7Y2FzZSAwOnJldHVybiBuZXcgRGF0ZShmLmdldEZ1bGxZZWFyKCktMSwxMSwyOSk7Y2FzZSAxOnJldHVybiBmO2Nhc2UgMjpyZXR1cm4gbmV3IERhdGUoZi5nZXRGdWxsWWVhcigpLDAsMyk7Y2FzZSAzOnJldHVybiBuZXcgRGF0ZShmLmdldEZ1bGxZZWFyKCksXHJcbjAsMik7Y2FzZSA0OnJldHVybiBuZXcgRGF0ZShmLmdldEZ1bGxZZWFyKCksMCwxKTtjYXNlIDU6cmV0dXJuIG5ldyBEYXRlKGYuZ2V0RnVsbFllYXIoKS0xLDExLDMxKTtjYXNlIDY6cmV0dXJuIG5ldyBEYXRlKGYuZ2V0RnVsbFllYXIoKS0xLDExLDMwKX19ZnVuY3Rpb24gRShmKXt2YXIgcD1mLk1hO2ZvcihmPW5ldyBEYXRlKChuZXcgRGF0ZShmLk5hKzE5MDAsMCwxKSkuZ2V0VGltZSgpKTswPHA7KXt2YXIgcj1mLmdldE1vbnRoKCksSj0oWihmLmdldEZ1bGxZZWFyKCkpP0xiOk1iKVtyXTtpZihwPkotZi5nZXREYXRlKCkpcC09Si1mLmdldERhdGUoKSsxLGYuc2V0RGF0ZSgxKSwxMT5yP2Yuc2V0TW9udGgocisxKTooZi5zZXRNb250aCgwKSxmLnNldEZ1bGxZZWFyKGYuZ2V0RnVsbFllYXIoKSsxKSk7ZWxzZXtmLnNldERhdGUoZi5nZXREYXRlKCkrcCk7YnJlYWt9fXI9bmV3IERhdGUoZi5nZXRGdWxsWWVhcigpKzEsMCw0KTtwPXUobmV3IERhdGUoZi5nZXRGdWxsWWVhcigpLFxyXG4wLDQpKTtyPXUocik7cmV0dXJuIDA+PW4ocCxmKT8wPj1uKHIsZik/Zi5nZXRGdWxsWWVhcigpKzE6Zi5nZXRGdWxsWWVhcigpOmYuZ2V0RnVsbFllYXIoKS0xfXZhciB2PXQoKVtlKzQwPj4yPj4+MF07ZT17dGI6dCgpW2U+PjI+Pj4wXSxzYjp0KClbZSs0Pj4yPj4+MF0sU2E6dCgpW2UrOD4+Mj4+PjBdLFZhOnQoKVtlKzEyPj4yPj4+MF0sVGE6dCgpW2UrMTY+PjI+Pj4wXSxOYTp0KClbZSsyMD4+Mj4+PjBdLEphOnQoKVtlKzI0Pj4yPj4+MF0sTWE6dCgpW2UrMjg+PjI+Pj4wXSx6Yjp0KClbZSszMj4+Mj4+PjBdLHJiOnQoKVtlKzM2Pj4yPj4+MF0sdWI6dj92YSh2KTpcIlwifTtkPXZhKGQpO3Y9e1wiJWNcIjpcIiVhICViICVkICVIOiVNOiVTICVZXCIsXCIlRFwiOlwiJW0vJWQvJXlcIixcIiVGXCI6XCIlWS0lbS0lZFwiLFwiJWhcIjpcIiViXCIsXCIlclwiOlwiJUk6JU06JVMgJXBcIixcIiVSXCI6XCIlSDolTVwiLFwiJVRcIjpcIiVIOiVNOiVTXCIsXCIleFwiOlwiJW0vJWQvJXlcIixcIiVYXCI6XCIlSDolTTolU1wiLFwiJUVjXCI6XCIlY1wiLFwiJUVDXCI6XCIlQ1wiLFxyXG5cIiVFeFwiOlwiJW0vJWQvJXlcIixcIiVFWFwiOlwiJUg6JU06JVNcIixcIiVFeVwiOlwiJXlcIixcIiVFWVwiOlwiJVlcIixcIiVPZFwiOlwiJWRcIixcIiVPZVwiOlwiJWVcIixcIiVPSFwiOlwiJUhcIixcIiVPSVwiOlwiJUlcIixcIiVPbVwiOlwiJW1cIixcIiVPTVwiOlwiJU1cIixcIiVPU1wiOlwiJVNcIixcIiVPdVwiOlwiJXVcIixcIiVPVVwiOlwiJVVcIixcIiVPVlwiOlwiJVZcIixcIiVPd1wiOlwiJXdcIixcIiVPV1wiOlwiJVdcIixcIiVPeVwiOlwiJXlcIn07Zm9yKHZhciB5IGluIHYpZD1kLnJlcGxhY2UobmV3IFJlZ0V4cCh5LFwiZ1wiKSx2W3ldKTt2YXIgRWI9XCJTdW5kYXkgTW9uZGF5IFR1ZXNkYXkgV2VkbmVzZGF5IFRodXJzZGF5IEZyaWRheSBTYXR1cmRheVwiLnNwbGl0KFwiIFwiKSxGYj1cIkphbnVhcnkgRmVicnVhcnkgTWFyY2ggQXByaWwgTWF5IEp1bmUgSnVseSBBdWd1c3QgU2VwdGVtYmVyIE9jdG9iZXIgTm92ZW1iZXIgRGVjZW1iZXJcIi5zcGxpdChcIiBcIik7dj17XCIlYVwiOmZ1bmN0aW9uKGYpe3JldHVybiBFYltmLkphXS5zdWJzdHJpbmcoMCwzKX0sXCIlQVwiOmZ1bmN0aW9uKGYpe3JldHVybiBFYltmLkphXX0sXHJcblwiJWJcIjpmdW5jdGlvbihmKXtyZXR1cm4gRmJbZi5UYV0uc3Vic3RyaW5nKDAsMyl9LFwiJUJcIjpmdW5jdGlvbihmKXtyZXR1cm4gRmJbZi5UYV19LFwiJUNcIjpmdW5jdGlvbihmKXtyZXR1cm4gaCgoZi5OYSsxOTAwKS8xMDB8MCwyKX0sXCIlZFwiOmZ1bmN0aW9uKGYpe3JldHVybiBoKGYuVmEsMil9LFwiJWVcIjpmdW5jdGlvbihmKXtyZXR1cm4gZyhmLlZhLDIsXCIgXCIpfSxcIiVnXCI6ZnVuY3Rpb24oZil7cmV0dXJuIEUoZikudG9TdHJpbmcoKS5zdWJzdHJpbmcoMil9LFwiJUdcIjpmdW5jdGlvbihmKXtyZXR1cm4gRShmKX0sXCIlSFwiOmZ1bmN0aW9uKGYpe3JldHVybiBoKGYuU2EsMil9LFwiJUlcIjpmdW5jdGlvbihmKXtmPWYuU2E7MD09Zj9mPTEyOjEyPGYmJihmLT0xMik7cmV0dXJuIGgoZiwyKX0sXCIlalwiOmZ1bmN0aW9uKGYpe2Zvcih2YXIgcD0wLHI9MDtyPD1mLlRhLTE7cCs9KFooZi5OYSsxOTAwKT9MYjpNYilbcisrXSk7cmV0dXJuIGgoZi5WYStwLDMpfSxcIiVtXCI6ZnVuY3Rpb24oZil7cmV0dXJuIGgoZi5UYStcclxuMSwyKX0sXCIlTVwiOmZ1bmN0aW9uKGYpe3JldHVybiBoKGYuc2IsMil9LFwiJW5cIjpmdW5jdGlvbigpe3JldHVyblwiXFxuXCJ9LFwiJXBcIjpmdW5jdGlvbihmKXtyZXR1cm4gMDw9Zi5TYSYmMTI+Zi5TYT9cIkFNXCI6XCJQTVwifSxcIiVTXCI6ZnVuY3Rpb24oZil7cmV0dXJuIGgoZi50YiwyKX0sXCIldFwiOmZ1bmN0aW9uKCl7cmV0dXJuXCJcXHRcIn0sXCIldVwiOmZ1bmN0aW9uKGYpe3JldHVybiBmLkphfHw3fSxcIiVVXCI6ZnVuY3Rpb24oZil7cmV0dXJuIGgoTWF0aC5mbG9vcigoZi5NYSs3LWYuSmEpLzcpLDIpfSxcIiVWXCI6ZnVuY3Rpb24oZil7dmFyIHA9TWF0aC5mbG9vcigoZi5NYSs3LShmLkphKzYpJTcpLzcpOzI+PShmLkphKzM3MS1mLk1hLTIpJTcmJnArKztpZihwKTUzPT1wJiYocj0oZi5KYSszNzEtZi5NYSklNyw0PT1yfHwzPT1yJiZaKGYuTmEpfHwocD0xKSk7ZWxzZXtwPTUyO3ZhciByPShmLkphKzctZi5NYS0xKSU3Oyg0PT1yfHw1PT1yJiZaKGYuTmElNDAwLTEpKSYmcCsrfXJldHVybiBoKHAsMil9LFxyXG5cIiV3XCI6ZnVuY3Rpb24oZil7cmV0dXJuIGYuSmF9LFwiJVdcIjpmdW5jdGlvbihmKXtyZXR1cm4gaChNYXRoLmZsb29yKChmLk1hKzctKGYuSmErNiklNykvNyksMil9LFwiJXlcIjpmdW5jdGlvbihmKXtyZXR1cm4oZi5OYSsxOTAwKS50b1N0cmluZygpLnN1YnN0cmluZygyKX0sXCIlWVwiOmZ1bmN0aW9uKGYpe3JldHVybiBmLk5hKzE5MDB9LFwiJXpcIjpmdW5jdGlvbihmKXtmPWYucmI7dmFyIHA9MDw9ZjtmPU1hdGguYWJzKGYpLzYwO3JldHVybihwP1wiK1wiOlwiLVwiKStTdHJpbmcoXCIwMDAwXCIrKGYvNjAqMTAwK2YlNjApKS5zbGljZSgtNCl9LFwiJVpcIjpmdW5jdGlvbihmKXtyZXR1cm4gZi51Yn0sXCIlJVwiOmZ1bmN0aW9uKCl7cmV0dXJuXCIlXCJ9fTtkPWQucmVwbGFjZSgvJSUvZyxcIlxceDAwXFx4MDBcIik7Zm9yKHkgaW4gdilkLmluY2x1ZGVzKHkpJiYoZD1kLnJlcGxhY2UobmV3IFJlZ0V4cCh5LFwiZ1wiKSx2W3ldKGUpKSk7ZD1kLnJlcGxhY2UoL1xcMFxcMC9nLFwiJVwiKTt5PU5iKGQpO2lmKHkubGVuZ3RoPlxyXG5iKXJldHVybiAwO1VhKHksYSk7cmV0dXJuIHkubGVuZ3RoLTF9Ui5VYSgpO1xyXG52YXIgUGI9W251bGwsTGEsTmEsWGEsWmEsJGEsYWIsYmIsY2IsZGIsZWIsZmIsZ2IsaGIsaWIsamIsa2IsbmIsb2IscmIsQWIsQmIsQ2IsR2IsSGIsSmJdLFJiPXtiOmZ1bmN0aW9uKGEpe3JldHVybiBxYihhKzI0KSsyNH0sYzpmdW5jdGlvbihhLGIsZCl7KG5ldyBWYShhKSkuVWEoYixkKTtXYSsrO3Rocm93IGE7fSxMOmZ1bmN0aW9uKGEpe1FiKGEsIUEsMSwhbGEpO1IuWmEoKX0sbDpmdW5jdGlvbihhKXtDP3Bvc3RNZXNzYWdlKHtjbWQ6XCJjbGVhbnVwVGhyZWFkXCIsdGhyZWFkOmF9KTpKYShhKX0sRDpZYSxpOlphLFI6JGEsejphYixCOmJiLFQ6Y2IsUDpkYixJOmViLE86ZmIscDpnYixBOmhiLHg6aWIsUTpqYix5OmtiLHI6ZnVuY3Rpb24oKXt9LGo6ZnVuY3Rpb24oKXtOKFwiVG8gdXNlIGRsb3BlbiwgeW91IG5lZWQgZW5hYmxlIGR5bmFtaWMgbGlua2luZywgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9lbXNjcmlwdGVuLWNvcmUvZW1zY3JpcHRlbi93aWtpL0xpbmtpbmdcIil9LHM6ZnVuY3Rpb24oKXtOKFwiVG8gdXNlIGRsb3BlbiwgeW91IG5lZWQgZW5hYmxlIGR5bmFtaWMgbGlua2luZywgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9lbXNjcmlwdGVuLWNvcmUvZW1zY3JpcHRlbi93aWtpL0xpbmtpbmdcIil9LFxyXG5xOmZ1bmN0aW9uKCl7cmV0dXJuIERhdGUubm93KCl9LEU6ZnVuY3Rpb24oKXtyZXR1cm4gMjA5NzE1Mn0sVjpmdW5jdGlvbigpe3JldHVybiEwfSxGOmZ1bmN0aW9uKGEsYixkLGUpe2lmKGE9PWIpc2V0VGltZW91dCgoKT0+UGEoZSkpO2Vsc2UgaWYoQylwb3N0TWVzc2FnZSh7dGFyZ2V0VGhyZWFkOmEsY21kOlwicHJvY2Vzc1Byb3h5aW5nUXVldWVcIixxdWV1ZTplfSk7ZWxzZXthPVIuTGFbYV07aWYoIWEpcmV0dXJuO2EucG9zdE1lc3NhZ2Uoe2NtZDpcInByb2Nlc3NQcm94eWluZ1F1ZXVlXCIscXVldWU6ZX0pfXJldHVybiAxfSxLOmZ1bmN0aW9uKCl7cmV0dXJuLTF9LFc6ZnVuY3Rpb24oYSxiKXthPW5ldyBEYXRlKDFFMyptYihhKSk7dCgpW2I+PjI+Pj4wXT1hLmdldFVUQ1NlY29uZHMoKTt0KClbYis0Pj4yPj4+MF09YS5nZXRVVENNaW51dGVzKCk7dCgpW2IrOD4+Mj4+PjBdPWEuZ2V0VVRDSG91cnMoKTt0KClbYisxMj4+Mj4+PjBdPWEuZ2V0VVRDRGF0ZSgpO3QoKVtiKzE2Pj4yPj4+XHJcbjBdPWEuZ2V0VVRDTW9udGgoKTt0KClbYisyMD4+Mj4+PjBdPWEuZ2V0VVRDRnVsbFllYXIoKS0xOTAwO3QoKVtiKzI0Pj4yPj4+MF09YS5nZXRVVENEYXkoKTthPShhLmdldFRpbWUoKS1EYXRlLlVUQyhhLmdldFVUQ0Z1bGxZZWFyKCksMCwxLDAsMCwwLDApKS84NjRFNXwwO3QoKVtiKzI4Pj4yPj4+MF09YX0sWDpmdW5jdGlvbihhLGIpe2E9bmV3IERhdGUoMUUzKm1iKGEpKTt0KClbYj4+Mj4+PjBdPWEuZ2V0U2Vjb25kcygpO3QoKVtiKzQ+PjI+Pj4wXT1hLmdldE1pbnV0ZXMoKTt0KClbYis4Pj4yPj4+MF09YS5nZXRIb3VycygpO3QoKVtiKzEyPj4yPj4+MF09YS5nZXREYXRlKCk7dCgpW2IrMTY+PjI+Pj4wXT1hLmdldE1vbnRoKCk7dCgpW2IrMjA+PjI+Pj4wXT1hLmdldEZ1bGxZZWFyKCktMTkwMDt0KClbYisyND4+Mj4+PjBdPWEuZ2V0RGF5KCk7dmFyIGQ9bmV3IERhdGUoYS5nZXRGdWxsWWVhcigpLDAsMSksZT0oYS5nZXRUaW1lKCktZC5nZXRUaW1lKCkpLzg2NEU1fDA7dCgpW2IrXHJcbjI4Pj4yPj4+MF09ZTt0KClbYiszNj4+Mj4+PjBdPS0oNjAqYS5nZXRUaW1lem9uZU9mZnNldCgpKTtlPShuZXcgRGF0ZShhLmdldEZ1bGxZZWFyKCksNiwxKSkuZ2V0VGltZXpvbmVPZmZzZXQoKTtkPWQuZ2V0VGltZXpvbmVPZmZzZXQoKTthPShlIT1kJiZhLmdldFRpbWV6b25lT2Zmc2V0KCk9PU1hdGgubWluKGQsZSkpfDA7dCgpW2IrMzI+PjI+Pj4wXT1hfSxZOmZ1bmN0aW9uKGEpe3ZhciBiPW5ldyBEYXRlKHQoKVthKzIwPj4yPj4+MF0rMTkwMCx0KClbYSsxNj4+Mj4+PjBdLHQoKVthKzEyPj4yPj4+MF0sdCgpW2ErOD4+Mj4+PjBdLHQoKVthKzQ+PjI+Pj4wXSx0KClbYT4+Mj4+PjBdLDApLGQ9dCgpW2ErMzI+PjI+Pj4wXSxlPWIuZ2V0VGltZXpvbmVPZmZzZXQoKSxnPW5ldyBEYXRlKGIuZ2V0RnVsbFllYXIoKSwwLDEpLGg9KG5ldyBEYXRlKGIuZ2V0RnVsbFllYXIoKSw2LDEpKS5nZXRUaW1lem9uZU9mZnNldCgpLG49Zy5nZXRUaW1lem9uZU9mZnNldCgpLHU9TWF0aC5taW4obixcclxuaCk7MD5kP3QoKVthKzMyPj4yPj4+MF09TnVtYmVyKGghPW4mJnU9PWUpOjA8ZCE9KHU9PWUpJiYoaD1NYXRoLm1heChuLGgpLGIuc2V0VGltZShiLmdldFRpbWUoKSs2RTQqKCgwPGQ/dTpoKS1lKSkpO3QoKVthKzI0Pj4yPj4+MF09Yi5nZXREYXkoKTtkPShiLmdldFRpbWUoKS1nLmdldFRpbWUoKSkvODY0RTV8MDt0KClbYSsyOD4+Mj4+PjBdPWQ7dCgpW2E+PjI+Pj4wXT1iLmdldFNlY29uZHMoKTt0KClbYSs0Pj4yPj4+MF09Yi5nZXRNaW51dGVzKCk7dCgpW2ErOD4+Mj4+PjBdPWIuZ2V0SG91cnMoKTt0KClbYSsxMj4+Mj4+PjBdPWIuZ2V0RGF0ZSgpO3QoKVthKzE2Pj4yPj4+MF09Yi5nZXRNb250aCgpO3JldHVybiBiLmdldFRpbWUoKS8xRTN8MH0sRzpuYixIOm9iLFo6c2IsZDpmdW5jdGlvbigpe04oXCJcIil9LG06ZnVuY3Rpb24oKXtpZighQiYmIUEpe3ZhciBhPVwiQmxvY2tpbmcgb24gdGhlIG1haW4gdGhyZWFkIGlzIHZlcnkgZGFuZ2Vyb3VzLCBzZWUgaHR0cHM6Ly9lbXNjcmlwdGVuLm9yZy9kb2NzL3BvcnRpbmcvcHRocmVhZHMuaHRtbCNibG9ja2luZy1vbi10aGUtbWFpbi1icm93c2VyLXRocmVhZFwiO1xyXG5YfHwoWD17fSk7WFthXXx8KFhbYV09MSxCJiYoYT1cIndhcm5pbmc6IFwiK2EpLEwoYSkpfX0sdzpmdW5jdGlvbigpe3JldHVybiA0Mjk0OTAxNzYwfSxmOnRiLFM6ZnVuY3Rpb24oYSxiLGQpe3EoKS5jb3B5V2l0aGluKGE+Pj4wLGI+Pj4wLGIrZD4+PjApfSxnOmZ1bmN0aW9uKCl7cmV0dXJuIEI/cmVxdWlyZShcIm9zXCIpLmNwdXMoKS5sZW5ndGg6bmF2aWdhdG9yLmhhcmR3YXJlQ29uY3VycmVuY3l9LEo6ZnVuY3Rpb24oYSxiLGQpe3diLmxlbmd0aD1iO2Q+Pj0zO2Zvcih2YXIgZT0wO2U8YjtlKyspd2JbZV09ZWEoKVtkK2U+Pj4wXTtyZXR1cm4oMD5hP0lhWy1hLTFdOlBiW2FdKS5hcHBseShudWxsLHdiKX0sdjpmdW5jdGlvbihhKXt2YXIgYj1xKCkubGVuZ3RoO2E+Pj49MDtpZihhPD1ifHw0Mjk0OTAxNzYwPGEpcmV0dXJuITE7Zm9yKHZhciBkPTE7ND49ZDtkKj0yKXt2YXIgZT1iKigxKy4yL2QpO2U9TWF0aC5taW4oZSxhKzEwMDY2MzI5Nik7dmFyIGc9TWF0aDtlPU1hdGgubWF4KGEsXHJcbmUpO2c9Zy5taW4uY2FsbChnLDQyOTQ5MDE3NjAsZSsoNjU1MzYtZSU2NTUzNiklNjU1MzYpO2E6e3RyeXtrLmdyb3coZy1sLmJ5dGVMZW5ndGgrNjU1MzU+Pj4xNik7bShrLmJ1ZmZlcik7dmFyIGg9MTticmVhayBhfWNhdGNoKG4pe31oPXZvaWQgMH1pZihoKXJldHVybiEwfXJldHVybiExfSxVOmZ1bmN0aW9uKCl7dGhyb3dcInVud2luZFwiO30sTTpBYixOOkJiLGs6TWEsaDpDYixvOkdiLHQ6SGIsbjpKYix1OlksYTprfHx4Lndhc21NZW1vcnksQzpPYixlOmZ1bmN0aW9uKGEsYixkLGUpe3JldHVybiBPYihhLGIsZCxlKX19O1xyXG4oZnVuY3Rpb24oKXtmdW5jdGlvbiBhKGcsaCl7eC5hc209Zy5leHBvcnRzO1IuJGEucHVzaCh4LmFzbS53YSk7emE9eC5hc20uemE7QmEudW5zaGlmdCh4LmFzbS5fKTtyYT1oO0N8fChPLS0seC5tb25pdG9yUnVuRGVwZW5kZW5jaWVzJiZ4Lm1vbml0b3JSdW5EZXBlbmRlbmNpZXMoTyksMD09TyYmKG51bGwhPT1FYSYmKGNsZWFySW50ZXJ2YWwoRWEpLEVhPW51bGwpLFAmJihnPVAsUD1udWxsLGcoKSkpKX1mdW5jdGlvbiBiKGcpe2EoZy5pbnN0YW5jZSxnLm1vZHVsZSl9ZnVuY3Rpb24gZChnKXtyZXR1cm4gSGEoKS50aGVuKGZ1bmN0aW9uKGgpe3JldHVybiBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZShoLGUpfSkudGhlbihmdW5jdGlvbihoKXtyZXR1cm4gaH0pLnRoZW4oZyxmdW5jdGlvbihoKXtMKFwiZmFpbGVkIHRvIGFzeW5jaHJvbm91c2x5IHByZXBhcmUgd2FzbTogXCIraCk7TihoKX0pfXZhciBlPXthOlJifTtDfHwoTysrLHgubW9uaXRvclJ1bkRlcGVuZGVuY2llcyYmeC5tb25pdG9yUnVuRGVwZW5kZW5jaWVzKE8pKTtcclxuaWYoeC5pbnN0YW50aWF0ZVdhc20pdHJ5e3JldHVybiB4Lmluc3RhbnRpYXRlV2FzbShlLGEpfWNhdGNoKGcpe3JldHVybiBMKFwiTW9kdWxlLmluc3RhbnRpYXRlV2FzbSBjYWxsYmFjayBmYWlsZWQgd2l0aCBlcnJvcjogXCIrZyksITF9KGZ1bmN0aW9uKCl7cmV0dXJuIE18fFwiZnVuY3Rpb25cIiE9dHlwZW9mIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nfHxGYSgpfHxRLnN0YXJ0c1dpdGgoXCJmaWxlOi8vXCIpfHxCfHxcImZ1bmN0aW9uXCIhPXR5cGVvZiBmZXRjaD9kKGIpOmZldGNoKFEse2NyZWRlbnRpYWxzOlwic2FtZS1vcmlnaW5cIn0pLnRoZW4oZnVuY3Rpb24oZyl7cmV0dXJuIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nKGcsZSkudGhlbihiLGZ1bmN0aW9uKGgpe0woXCJ3YXNtIHN0cmVhbWluZyBjb21waWxlIGZhaWxlZDogXCIraCk7TChcImZhbGxpbmcgYmFjayB0byBBcnJheUJ1ZmZlciBpbnN0YW50aWF0aW9uXCIpO3JldHVybiBkKGIpfSl9KX0pKCkuY2F0Y2goaWEpO1xyXG5yZXR1cm57fX0pKCk7eC5fX193YXNtX2NhbGxfY3RvcnM9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fX193YXNtX2NhbGxfY3RvcnM9eC5hc20uXykuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRJbml0PWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEluaXQ9eC5hc20uJCkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRDcmVhdGVTZXNzaW9uT3B0aW9ucz1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRDcmVhdGVTZXNzaW9uT3B0aW9ucz14LmFzbS5hYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRBcHBlbmRFeGVjdXRpb25Qcm92aWRlcj1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRBcHBlbmRFeGVjdXRpb25Qcm92aWRlcj14LmFzbS5iYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRBZGRTZXNzaW9uQ29uZmlnRW50cnk9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5PXguYXNtLmNhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O1xyXG54Ll9PcnRSZWxlYXNlU2Vzc2lvbk9wdGlvbnM9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0UmVsZWFzZVNlc3Npb25PcHRpb25zPXguYXNtLmRhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydENyZWF0ZVNlc3Npb249ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0Q3JlYXRlU2Vzc2lvbj14LmFzbS5lYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRSZWxlYXNlU2Vzc2lvbj1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRSZWxlYXNlU2Vzc2lvbj14LmFzbS5mYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRHZXRJbnB1dENvdW50PWZ1bmN0aW9uKCl7cmV0dXJuKHguX09ydEdldElucHV0Q291bnQ9eC5hc20uZ2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0R2V0T3V0cHV0Q291bnQ9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0R2V0T3V0cHV0Q291bnQ9eC5hc20uaGEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XHJcbnguX09ydEdldElucHV0TmFtZT1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRHZXRJbnB1dE5hbWU9eC5hc20uaWEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5fT3J0R2V0T3V0cHV0TmFtZT1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRHZXRPdXRwdXROYW1lPXguYXNtLmphKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydEZyZWU9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0RnJlZT14LmFzbS5rYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRDcmVhdGVUZW5zb3I9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0Q3JlYXRlVGVuc29yPXguYXNtLmxhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydEdldFRlbnNvckRhdGE9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0R2V0VGVuc29yRGF0YT14LmFzbS5tYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtcclxueC5fT3J0UmVsZWFzZVRlbnNvcj1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRSZWxlYXNlVGVuc29yPXguYXNtLm5hKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX09ydENyZWF0ZVJ1bk9wdGlvbnM9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0Q3JlYXRlUnVuT3B0aW9ucz14LmFzbS5vYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRBZGRSdW5Db25maWdFbnRyeT1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRBZGRSdW5Db25maWdFbnRyeT14LmFzbS5wYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRSZWxlYXNlUnVuT3B0aW9ucz1mdW5jdGlvbigpe3JldHVybih4Ll9PcnRSZWxlYXNlUnVuT3B0aW9ucz14LmFzbS5xYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9PcnRSdW49ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0UnVuPXguYXNtLnJhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O1xyXG54Ll9PcnRFbmRQcm9maWxpbmc9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fT3J0RW5kUHJvZmlsaW5nPXguYXNtLnNhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3ZhciBUPXguX3B0aHJlYWRfc2VsZj1mdW5jdGlvbigpe3JldHVybihUPXguX3B0aHJlYWRfc2VsZj14LmFzbS50YSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfSxxYj14Ll9tYWxsb2M9ZnVuY3Rpb24oKXtyZXR1cm4ocWI9eC5fbWFsbG9jPXguYXNtLnVhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX2ZyZWU9ZnVuY3Rpb24oKXtyZXR1cm4oeC5fZnJlZT14LmFzbS52YSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt4Ll9fZW1zY3JpcHRlbl90bHNfaW5pdD1mdW5jdGlvbigpe3JldHVybih4Ll9fZW1zY3JpcHRlbl90bHNfaW5pdD14LmFzbS53YSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtcclxudmFyIFFiPXguX19lbXNjcmlwdGVuX3RocmVhZF9pbml0PWZ1bmN0aW9uKCl7cmV0dXJuKFFiPXguX19lbXNjcmlwdGVuX3RocmVhZF9pbml0PXguYXNtLnhhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX19lbXNjcmlwdGVuX3RocmVhZF9jcmFzaGVkPWZ1bmN0aW9uKCl7cmV0dXJuKHguX19lbXNjcmlwdGVuX3RocmVhZF9jcmFzaGVkPXguYXNtLnlhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O1xyXG52YXIgdmI9eC5fZW1zY3JpcHRlbl9ydW5faW5fbWFpbl9ydW50aW1lX3RocmVhZF9qcz1mdW5jdGlvbigpe3JldHVybih2Yj14Ll9lbXNjcmlwdGVuX3J1bl9pbl9tYWluX3J1bnRpbWVfdGhyZWFkX2pzPXguYXNtLkFhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LGxiPXguX19lbXNjcmlwdGVuX3Byb3h5X2V4ZWN1dGVfdGFza19xdWV1ZT1mdW5jdGlvbigpe3JldHVybihsYj14Ll9fZW1zY3JpcHRlbl9wcm94eV9leGVjdXRlX3Rhc2tfcXVldWU9eC5hc20uQmEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX0sT2E9eC5fX2Vtc2NyaXB0ZW5fdGhyZWFkX2ZyZWVfZGF0YT1mdW5jdGlvbigpe3JldHVybihPYT14Ll9fZW1zY3JpcHRlbl90aHJlYWRfZnJlZV9kYXRhPXguYXNtLkNhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFRhPXguX19lbXNjcmlwdGVuX3RocmVhZF9leGl0PWZ1bmN0aW9uKCl7cmV0dXJuKFRhPXguX19lbXNjcmlwdGVuX3RocmVhZF9leGl0PXguYXNtLkRhKS5hcHBseShudWxsLFxyXG5hcmd1bWVudHMpfSxTYT14Ll9lbXNjcmlwdGVuX3N0YWNrX3NldF9saW1pdHM9ZnVuY3Rpb24oKXtyZXR1cm4oU2E9eC5fZW1zY3JpcHRlbl9zdGFja19zZXRfbGltaXRzPXguYXNtLkVhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFJhPXguc3RhY2tTYXZlPWZ1bmN0aW9uKCl7cmV0dXJuKFJhPXguc3RhY2tTYXZlPXguYXNtLkZhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LFY9eC5zdGFja1Jlc3RvcmU9ZnVuY3Rpb24oKXtyZXR1cm4oVj14LnN0YWNrUmVzdG9yZT14LmFzbS5HYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfSx1Yj14LnN0YWNrQWxsb2M9ZnVuY3Rpb24oKXtyZXR1cm4odWI9eC5zdGFja0FsbG9jPXguYXNtLkhhKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O3guX19fY3hhX2lzX3BvaW50ZXJfdHlwZT1mdW5jdGlvbigpe3JldHVybih4Ll9fX2N4YV9pc19wb2ludGVyX3R5cGU9eC5hc20uSWEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07eC5VVEY4VG9TdHJpbmc9dmE7XHJcbnguc3RyaW5nVG9VVEY4PWZ1bmN0aW9uKGEsYixkKXtyZXR1cm4gd2EoYSxxKCksYixkKX07eC5sZW5ndGhCeXRlc1VURjg9eGE7eC5rZWVwUnVudGltZUFsaXZlPWZ1bmN0aW9uKCl7cmV0dXJuIG5vRXhpdFJ1bnRpbWV9O3gud2FzbU1lbW9yeT1rO3guc3RhY2tTYXZlPVJhO3guc3RhY2tSZXN0b3JlPVY7eC5zdGFja0FsbG9jPXViO3guRXhpdFN0YXR1cz1LO3guUFRocmVhZD1SO3ZhciBTYjtQPWZ1bmN0aW9uIFRiKCl7U2J8fFViKCk7U2J8fChQPVRiKX07XHJcbmZ1bmN0aW9uIFViKCl7ZnVuY3Rpb24gYSgpe2lmKCFTYiYmKFNiPSEwLHguY2FsbGVkUnVuPSEwLCFzYSkpe0N8fFUoQmEpO2hhKHgpO2lmKHgub25SdW50aW1lSW5pdGlhbGl6ZWQpeC5vblJ1bnRpbWVJbml0aWFsaXplZCgpO2lmKCFDKXtpZih4LnBvc3RSdW4pZm9yKFwiZnVuY3Rpb25cIj09dHlwZW9mIHgucG9zdFJ1biYmKHgucG9zdFJ1bj1beC5wb3N0UnVuXSk7eC5wb3N0UnVuLmxlbmd0aDspe3ZhciBiPXgucG9zdFJ1bi5zaGlmdCgpO0NhLnVuc2hpZnQoYil9VShDYSl9fX1pZighKDA8TykpaWYoQyloYSh4KSxDfHxVKEJhKSxwb3N0TWVzc2FnZSh7Y21kOlwibG9hZGVkXCJ9KTtlbHNle2lmKHgucHJlUnVuKWZvcihcImZ1bmN0aW9uXCI9PXR5cGVvZiB4LnByZVJ1biYmKHgucHJlUnVuPVt4LnByZVJ1bl0pO3gucHJlUnVuLmxlbmd0aDspRGEoKTtVKEFhKTswPE98fCh4LnNldFN0YXR1cz8oeC5zZXRTdGF0dXMoXCJSdW5uaW5nLi4uXCIpLHNldFRpbWVvdXQoZnVuY3Rpb24oKXtzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7eC5zZXRTdGF0dXMoXCJcIil9LFxyXG4xKTthKCl9LDEpKTphKCkpfX1pZih4LnByZUluaXQpZm9yKFwiZnVuY3Rpb25cIj09dHlwZW9mIHgucHJlSW5pdCYmKHgucHJlSW5pdD1beC5wcmVJbml0XSk7MDx4LnByZUluaXQubGVuZ3RoOyl4LnByZUluaXQucG9wKCkoKTtVYigpO1xyXG5cclxuXHJcbiAgcmV0dXJuIG9ydFdhc21UaHJlYWRlZC5yZWFkeVxyXG59XHJcbik7XHJcbn0pKCk7XHJcbmlmICh0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcpXHJcbiAgbW9kdWxlLmV4cG9ydHMgPSBvcnRXYXNtVGhyZWFkZWQ7XHJcbmVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lWydhbWQnXSlcclxuICBkZWZpbmUoW10sIGZ1bmN0aW9uKCkgeyByZXR1cm4gb3J0V2FzbVRocmVhZGVkOyB9KTtcclxuZWxzZSBpZiAodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnKVxyXG4gIGV4cG9ydHNbXCJvcnRXYXNtVGhyZWFkZWRcIl0gPSBvcnRXYXNtVGhyZWFkZWQ7XHJcbiIsIlxyXG52YXIgb3J0V2FzbSA9ICgoKSA9PiB7XHJcbiAgdmFyIF9zY3JpcHREaXIgPSB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnICYmIGRvY3VtZW50LmN1cnJlbnRTY3JpcHQgPyBkb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYyA6IHVuZGVmaW5lZDtcclxuICBpZiAodHlwZW9mIF9fZmlsZW5hbWUgIT09ICd1bmRlZmluZWQnKSBfc2NyaXB0RGlyID0gX3NjcmlwdERpciB8fCBfX2ZpbGVuYW1lO1xyXG4gIHJldHVybiAoXHJcbmZ1bmN0aW9uKG9ydFdhc20pIHtcclxuICBvcnRXYXNtID0gb3J0V2FzbSB8fCB7fTtcclxuXHJcblxyXG5udWxsO3ZhciBiO2J8fChiPXR5cGVvZiBvcnRXYXNtICE9PSAndW5kZWZpbmVkJyA/IG9ydFdhc20gOiB7fSk7dmFyIGFhLGs7Yi5yZWFkeT1uZXcgUHJvbWlzZShmdW5jdGlvbihhLGMpe2FhPWE7az1jfSk7dmFyIGJhPU9iamVjdC5hc3NpZ24oe30sYikscD1cIi4vdGhpcy5wcm9ncmFtXCIsdD0oYSxjKT0+e3Rocm93IGM7fSxjYT1cIm9iamVjdFwiPT10eXBlb2Ygd2luZG93LHU9XCJmdW5jdGlvblwiPT10eXBlb2YgaW1wb3J0U2NyaXB0cyx4PVwib2JqZWN0XCI9PXR5cGVvZiBwcm9jZXNzJiZcIm9iamVjdFwiPT10eXBlb2YgcHJvY2Vzcy52ZXJzaW9ucyYmXCJzdHJpbmdcIj09dHlwZW9mIHByb2Nlc3MudmVyc2lvbnMubm9kZSx5PVwiXCIseixBLEMsZnMsRCxFO1xyXG5pZih4KXk9dT9yZXF1aXJlKFwicGF0aFwiKS5kaXJuYW1lKHkpK1wiL1wiOl9fZGlybmFtZStcIi9cIixFPSgpPT57RHx8KGZzPXJlcXVpcmUoXCJmc1wiKSxEPXJlcXVpcmUoXCJwYXRoXCIpKX0sej1mdW5jdGlvbihhLGMpe0UoKTthPUQubm9ybWFsaXplKGEpO3JldHVybiBmcy5yZWFkRmlsZVN5bmMoYSxjP3ZvaWQgMDpcInV0ZjhcIil9LEM9YT0+e2E9eihhLCEwKTthLmJ1ZmZlcnx8KGE9bmV3IFVpbnQ4QXJyYXkoYSkpO3JldHVybiBhfSxBPShhLGMsZSk9PntFKCk7YT1ELm5vcm1hbGl6ZShhKTtmcy5yZWFkRmlsZShhLGZ1bmN0aW9uKGYsZyl7Zj9lKGYpOmMoZy5idWZmZXIpfSl9LDE8cHJvY2Vzcy5hcmd2Lmxlbmd0aCYmKHA9cHJvY2Vzcy5hcmd2WzFdLnJlcGxhY2UoL1xcXFwvZyxcIi9cIikpLHByb2Nlc3MuYXJndi5zbGljZSgyKSxwcm9jZXNzLm9uKFwidW5jYXVnaHRFeGNlcHRpb25cIixmdW5jdGlvbihhKXtpZighKGEgaW5zdGFuY2VvZiBGKSl0aHJvdyBhO30pLHByb2Nlc3Mub24oXCJ1bmhhbmRsZWRSZWplY3Rpb25cIixcclxuZnVuY3Rpb24oYSl7dGhyb3cgYTt9KSx0PShhLGMpPT57aWYobm9FeGl0UnVudGltZSl0aHJvdyBwcm9jZXNzLmV4aXRDb2RlPWEsYztjIGluc3RhbmNlb2YgRnx8RyhcImV4aXRpbmcgZHVlIHRvIGV4Y2VwdGlvbjogXCIrYyk7cHJvY2Vzcy5leGl0KGEpfSxiLmluc3BlY3Q9ZnVuY3Rpb24oKXtyZXR1cm5cIltFbXNjcmlwdGVuIE1vZHVsZSBvYmplY3RdXCJ9O2Vsc2UgaWYoY2F8fHUpdT95PXNlbGYubG9jYXRpb24uaHJlZjpcInVuZGVmaW5lZFwiIT10eXBlb2YgZG9jdW1lbnQmJmRvY3VtZW50LmN1cnJlbnRTY3JpcHQmJih5PWRvY3VtZW50LmN1cnJlbnRTY3JpcHQuc3JjKSxfc2NyaXB0RGlyJiYoeT1fc2NyaXB0RGlyKSwwIT09eS5pbmRleE9mKFwiYmxvYjpcIik/eT15LnN1YnN0cigwLHkucmVwbGFjZSgvWz8jXS4qLyxcIlwiKS5sYXN0SW5kZXhPZihcIi9cIikrMSk6eT1cIlwiLHo9YT0+e3ZhciBjPW5ldyBYTUxIdHRwUmVxdWVzdDtjLm9wZW4oXCJHRVRcIixhLCExKTtjLnNlbmQobnVsbCk7cmV0dXJuIGMucmVzcG9uc2VUZXh0fSxcclxudSYmKEM9YT0+e3ZhciBjPW5ldyBYTUxIdHRwUmVxdWVzdDtjLm9wZW4oXCJHRVRcIixhLCExKTtjLnJlc3BvbnNlVHlwZT1cImFycmF5YnVmZmVyXCI7Yy5zZW5kKG51bGwpO3JldHVybiBuZXcgVWludDhBcnJheShjLnJlc3BvbnNlKX0pLEE9KGEsYyxlKT0+e3ZhciBmPW5ldyBYTUxIdHRwUmVxdWVzdDtmLm9wZW4oXCJHRVRcIixhLCEwKTtmLnJlc3BvbnNlVHlwZT1cImFycmF5YnVmZmVyXCI7Zi5vbmxvYWQ9KCk9PnsyMDA9PWYuc3RhdHVzfHwwPT1mLnN0YXR1cyYmZi5yZXNwb25zZT9jKGYucmVzcG9uc2UpOmUoKX07Zi5vbmVycm9yPWU7Zi5zZW5kKG51bGwpfTt2YXIgZGE9Yi5wcmludHx8Y29uc29sZS5sb2cuYmluZChjb25zb2xlKSxHPWIucHJpbnRFcnJ8fGNvbnNvbGUud2Fybi5iaW5kKGNvbnNvbGUpO09iamVjdC5hc3NpZ24oYixiYSk7YmE9bnVsbDtiLnRoaXNQcm9ncmFtJiYocD1iLnRoaXNQcm9ncmFtKTtiLnF1aXQmJih0PWIucXVpdCk7dmFyIEg7XHJcbmIud2FzbUJpbmFyeSYmKEg9Yi53YXNtQmluYXJ5KTt2YXIgbm9FeGl0UnVudGltZT1iLm5vRXhpdFJ1bnRpbWV8fCEwO1wib2JqZWN0XCIhPXR5cGVvZiBXZWJBc3NlbWJseSYmSShcIm5vIG5hdGl2ZSB3YXNtIHN1cHBvcnQgZGV0ZWN0ZWRcIik7dmFyIEosSz0hMSxlYT1cInVuZGVmaW5lZFwiIT10eXBlb2YgVGV4dERlY29kZXI/bmV3IFRleHREZWNvZGVyKFwidXRmOFwiKTp2b2lkIDA7XHJcbmZ1bmN0aW9uIGZhKGEsYyxlKXtjPj4+PTA7dmFyIGY9YytlO2ZvcihlPWM7YVtlXSYmIShlPj1mKTspKytlO2lmKDE2PGUtYyYmYS5idWZmZXImJmVhKXJldHVybiBlYS5kZWNvZGUoYS5zdWJhcnJheShjLGUpKTtmb3IoZj1cIlwiO2M8ZTspe3ZhciBnPWFbYysrXTtpZihnJjEyOCl7dmFyIGg9YVtjKytdJjYzO2lmKDE5Mj09KGcmMjI0KSlmKz1TdHJpbmcuZnJvbUNoYXJDb2RlKChnJjMxKTw8NnxoKTtlbHNle3ZhciBsPWFbYysrXSY2MztnPTIyND09KGcmMjQwKT8oZyYxNSk8PDEyfGg8PDZ8bDooZyY3KTw8MTh8aDw8MTJ8bDw8NnxhW2MrK10mNjM7NjU1MzY+Zz9mKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGcpOihnLT02NTUzNixmKz1TdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2fGc+PjEwLDU2MzIwfGcmMTAyMykpfX1lbHNlIGYrPVN0cmluZy5mcm9tQ2hhckNvZGUoZyl9cmV0dXJuIGZ9ZnVuY3Rpb24gTChhLGMpe3JldHVybihhPj4+PTApP2ZhKE0sYSxjKTpcIlwifVxyXG5mdW5jdGlvbiBOKGEsYyxlLGYpe2U+Pj49MDtpZighKDA8ZikpcmV0dXJuIDA7dmFyIGc9ZTtmPWUrZi0xO2Zvcih2YXIgaD0wO2g8YS5sZW5ndGg7KytoKXt2YXIgbD1hLmNoYXJDb2RlQXQoaCk7aWYoNTUyOTY8PWwmJjU3MzQzPj1sKXt2YXIgcT1hLmNoYXJDb2RlQXQoKytoKTtsPTY1NTM2KygobCYxMDIzKTw8MTApfHEmMTAyM31pZigxMjc+PWwpe2lmKGU+PWYpYnJlYWs7Y1tlKys+Pj4wXT1sfWVsc2V7aWYoMjA0Nz49bCl7aWYoZSsxPj1mKWJyZWFrO2NbZSsrPj4+MF09MTkyfGw+PjZ9ZWxzZXtpZig2NTUzNT49bCl7aWYoZSsyPj1mKWJyZWFrO2NbZSsrPj4+MF09MjI0fGw+PjEyfWVsc2V7aWYoZSszPj1mKWJyZWFrO2NbZSsrPj4+MF09MjQwfGw+PjE4O2NbZSsrPj4+MF09MTI4fGw+PjEyJjYzfWNbZSsrPj4+MF09MTI4fGw+PjYmNjN9Y1tlKys+Pj4wXT0xMjh8bCY2M319Y1tlPj4+MF09MDtyZXR1cm4gZS1nfVxyXG5mdW5jdGlvbiBPKGEpe2Zvcih2YXIgYz0wLGU9MDtlPGEubGVuZ3RoOysrZSl7dmFyIGY9YS5jaGFyQ29kZUF0KGUpOzEyNz49Zj9jKys6MjA0Nz49Zj9jKz0yOjU1Mjk2PD1mJiY1NzM0Mz49Zj8oYys9NCwrK2UpOmMrPTN9cmV0dXJuIGN9dmFyIGhhLFAsTSxRLFI7ZnVuY3Rpb24gaWEoKXt2YXIgYT1KLmJ1ZmZlcjtoYT1hO2IuSEVBUDg9UD1uZXcgSW50OEFycmF5KGEpO2IuSEVBUDE2PW5ldyBJbnQxNkFycmF5KGEpO2IuSEVBUDMyPVE9bmV3IEludDMyQXJyYXkoYSk7Yi5IRUFQVTg9TT1uZXcgVWludDhBcnJheShhKTtiLkhFQVBVMTY9bmV3IFVpbnQxNkFycmF5KGEpO2IuSEVBUFUzMj1SPW5ldyBVaW50MzJBcnJheShhKTtiLkhFQVBGMzI9bmV3IEZsb2F0MzJBcnJheShhKTtiLkhFQVBGNjQ9bmV3IEZsb2F0NjRBcnJheShhKX12YXIgamE9W10sa2E9W10sbGE9W107ZnVuY3Rpb24gbWEoKXt2YXIgYT1iLnByZVJ1bi5zaGlmdCgpO2phLnVuc2hpZnQoYSl9XHJcbnZhciBTPTAsVD1udWxsLFU9bnVsbDtmdW5jdGlvbiBJKGEpe2lmKGIub25BYm9ydCliLm9uQWJvcnQoYSk7YT1cIkFib3J0ZWQoXCIrYStcIilcIjtHKGEpO0s9ITA7YT1uZXcgV2ViQXNzZW1ibHkuUnVudGltZUVycm9yKGErXCIuIEJ1aWxkIHdpdGggLXNBU1NFUlRJT05TIGZvciBtb3JlIGluZm8uXCIpO2soYSk7dGhyb3cgYTt9ZnVuY3Rpb24gbmEoKXtyZXR1cm4gVi5zdGFydHNXaXRoKFwiZGF0YTphcHBsaWNhdGlvbi9vY3RldC1zdHJlYW07YmFzZTY0LFwiKX12YXIgVjtWPVwib3J0LXdhc20ud2FzbVwiO2lmKCFuYSgpKXt2YXIgb2E9VjtWPWIubG9jYXRlRmlsZT9iLmxvY2F0ZUZpbGUob2EseSk6eStvYX1mdW5jdGlvbiBwYSgpe3ZhciBhPVY7dHJ5e2lmKGE9PVYmJkgpcmV0dXJuIG5ldyBVaW50OEFycmF5KEgpO2lmKEMpcmV0dXJuIEMoYSk7dGhyb3dcImJvdGggYXN5bmMgYW5kIHN5bmMgZmV0Y2hpbmcgb2YgdGhlIHdhc20gZmFpbGVkXCI7fWNhdGNoKGMpe0koYyl9fVxyXG5mdW5jdGlvbiBxYSgpe2lmKCFIJiYoY2F8fHUpKXtpZihcImZ1bmN0aW9uXCI9PXR5cGVvZiBmZXRjaCYmIVYuc3RhcnRzV2l0aChcImZpbGU6Ly9cIikpcmV0dXJuIGZldGNoKFYse2NyZWRlbnRpYWxzOlwic2FtZS1vcmlnaW5cIn0pLnRoZW4oZnVuY3Rpb24oYSl7aWYoIWEub2spdGhyb3dcImZhaWxlZCB0byBsb2FkIHdhc20gYmluYXJ5IGZpbGUgYXQgJ1wiK1YrXCInXCI7cmV0dXJuIGEuYXJyYXlCdWZmZXIoKX0pLmNhdGNoKGZ1bmN0aW9uKCl7cmV0dXJuIHBhKCl9KTtpZihBKXJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihhLGMpe0EoVixmdW5jdGlvbihlKXthKG5ldyBVaW50OEFycmF5KGUpKX0sYyl9KX1yZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCkudGhlbihmdW5jdGlvbigpe3JldHVybiBwYSgpfSl9ZnVuY3Rpb24gRihhKXt0aGlzLm5hbWU9XCJFeGl0U3RhdHVzXCI7dGhpcy5tZXNzYWdlPVwiUHJvZ3JhbSB0ZXJtaW5hdGVkIHdpdGggZXhpdChcIithK1wiKVwiO3RoaXMuc3RhdHVzPWF9XHJcbmZ1bmN0aW9uIFcoYSl7Zm9yKDswPGEubGVuZ3RoOylhLnNoaWZ0KCkoYil9ZnVuY3Rpb24gcmEoYSl7dGhpcy5zYT1hLTI0O3RoaXMuSWE9ZnVuY3Rpb24oYyl7Ult0aGlzLnNhKzQ+PjI+Pj4wXT1jfTt0aGlzLkJhPWZ1bmN0aW9uKGMpe1JbdGhpcy5zYSs4Pj4yPj4+MF09Y307dGhpcy5HYT1mdW5jdGlvbigpe1FbdGhpcy5zYT4+Mj4+PjBdPTB9O3RoaXMuQWE9ZnVuY3Rpb24oKXtQW3RoaXMuc2ErMTI+PjA+Pj4wXT0wfTt0aGlzLkhhPWZ1bmN0aW9uKCl7UFt0aGlzLnNhKzEzPj4wPj4+MF09MH07dGhpcy55YT1mdW5jdGlvbihjLGUpe3RoaXMuemEoKTt0aGlzLklhKGMpO3RoaXMuQmEoZSk7dGhpcy5HYSgpO3RoaXMuQWEoKTt0aGlzLkhhKCl9O3RoaXMuemE9ZnVuY3Rpb24oKXtSW3RoaXMuc2ErMTY+PjI+Pj4wXT0wfX12YXIgc2E9MDtmdW5jdGlvbiB0YShhKXt2YXIgYz1PKGEpKzEsZT11YShjKTtlJiZOKGEsUCxlLGMpO3JldHVybiBlfVxyXG5mdW5jdGlvbiB2YShhLGMsZSl7ZnVuY3Rpb24gZih3KXtyZXR1cm4odz13LnRvVGltZVN0cmluZygpLm1hdGNoKC9cXCgoW0EtWmEteiBdKylcXCkkLykpP3dbMV06XCJHTVRcIn12YXIgZz0obmV3IERhdGUpLmdldEZ1bGxZZWFyKCksaD1uZXcgRGF0ZShnLDAsMSksbD1uZXcgRGF0ZShnLDYsMSk7Zz1oLmdldFRpbWV6b25lT2Zmc2V0KCk7dmFyIHE9bC5nZXRUaW1lem9uZU9mZnNldCgpO1FbYT4+Mj4+PjBdPTYwKk1hdGgubWF4KGcscSk7UVtjPj4yPj4+MF09TnVtYmVyKGchPXEpO2E9ZihoKTtjPWYobCk7YT10YShhKTtjPXRhKGMpO3E8Zz8oUltlPj4yPj4+MF09YSxSW2UrND4+Mj4+PjBdPWMpOihSW2U+PjI+Pj4wXT1jLFJbZSs0Pj4yPj4+MF09YSl9ZnVuY3Rpb24gd2EoYSxjLGUpe3dhLnhhfHwod2EueGE9ITAsdmEoYSxjLGUpKX12YXIgQWE9e307XHJcbmZ1bmN0aW9uIEJhKCl7aWYoIUNhKXt2YXIgYT17VVNFUjpcIndlYl91c2VyXCIsTE9HTkFNRTpcIndlYl91c2VyXCIsUEFUSDpcIi9cIixQV0Q6XCIvXCIsSE9NRTpcIi9ob21lL3dlYl91c2VyXCIsTEFORzooXCJvYmplY3RcIj09dHlwZW9mIG5hdmlnYXRvciYmbmF2aWdhdG9yLmxhbmd1YWdlcyYmbmF2aWdhdG9yLmxhbmd1YWdlc1swXXx8XCJDXCIpLnJlcGxhY2UoXCItXCIsXCJfXCIpK1wiLlVURi04XCIsXzpwfHxcIi4vdGhpcy5wcm9ncmFtXCJ9LGM7Zm9yKGMgaW4gQWEpdm9pZCAwPT09QWFbY10/ZGVsZXRlIGFbY106YVtjXT1BYVtjXTt2YXIgZT1bXTtmb3IoYyBpbiBhKWUucHVzaChjK1wiPVwiK2FbY10pO0NhPWV9cmV0dXJuIENhfXZhciBDYSxEYT1bbnVsbCxbXSxbXV07XHJcbmZ1bmN0aW9uIEVhKCl7aWYoXCJvYmplY3RcIj09dHlwZW9mIGNyeXB0byYmXCJmdW5jdGlvblwiPT10eXBlb2YgY3J5cHRvLmdldFJhbmRvbVZhbHVlcyl7dmFyIGE9bmV3IFVpbnQ4QXJyYXkoMSk7cmV0dXJuKCk9PntjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKGEpO3JldHVybiBhWzBdfX1pZih4KXRyeXt2YXIgYz1yZXF1aXJlKFwiY3J5cHRvXCIpO3JldHVybigpPT5jLnJhbmRvbUJ5dGVzKDEpWzBdfWNhdGNoKGUpe31yZXR1cm4oKT0+SShcInJhbmRvbURldmljZVwiKX1mdW5jdGlvbiBYKGEsYyl7WC53YXx8KFgud2E9RWEoKSk7Zm9yKHZhciBlPTA7ZTxjO2UrKylQW2ErZT4+MD4+PjBdPVgud2EoKTtyZXR1cm4gMH1mdW5jdGlvbiBZKGEpe3JldHVybiAwPT09YSU0JiYoMCE9PWElMTAwfHwwPT09YSU0MDApfXZhciBGYT1bMzEsMjksMzEsMzAsMzEsMzAsMzEsMzEsMzAsMzEsMzAsMzFdLEdhPVszMSwyOCwzMSwzMCwzMSwzMCwzMSwzMSwzMCwzMSwzMCwzMV07XHJcbmZ1bmN0aW9uIEhhKGEpe3ZhciBjPUFycmF5KE8oYSkrMSk7TihhLGMsMCxjLmxlbmd0aCk7cmV0dXJuIGN9XHJcbmZ1bmN0aW9uIElhKGEsYyxlLGYpe2Z1bmN0aW9uIGcoZCxtLG4pe2ZvcihkPVwibnVtYmVyXCI9PXR5cGVvZiBkP2QudG9TdHJpbmcoKTpkfHxcIlwiO2QubGVuZ3RoPG07KWQ9blswXStkO3JldHVybiBkfWZ1bmN0aW9uIGgoZCxtKXtyZXR1cm4gZyhkLG0sXCIwXCIpfWZ1bmN0aW9uIGwoZCxtKXtmdW5jdGlvbiBuKHhhKXtyZXR1cm4gMD54YT8tMTowPHhhPzE6MH12YXIgQjswPT09KEI9bihkLmdldEZ1bGxZZWFyKCktbS5nZXRGdWxsWWVhcigpKSkmJjA9PT0oQj1uKGQuZ2V0TW9udGgoKS1tLmdldE1vbnRoKCkpKSYmKEI9bihkLmdldERhdGUoKS1tLmdldERhdGUoKSkpO3JldHVybiBCfWZ1bmN0aW9uIHEoZCl7c3dpdGNoKGQuZ2V0RGF5KCkpe2Nhc2UgMDpyZXR1cm4gbmV3IERhdGUoZC5nZXRGdWxsWWVhcigpLTEsMTEsMjkpO2Nhc2UgMTpyZXR1cm4gZDtjYXNlIDI6cmV0dXJuIG5ldyBEYXRlKGQuZ2V0RnVsbFllYXIoKSwwLDMpO2Nhc2UgMzpyZXR1cm4gbmV3IERhdGUoZC5nZXRGdWxsWWVhcigpLFxyXG4wLDIpO2Nhc2UgNDpyZXR1cm4gbmV3IERhdGUoZC5nZXRGdWxsWWVhcigpLDAsMSk7Y2FzZSA1OnJldHVybiBuZXcgRGF0ZShkLmdldEZ1bGxZZWFyKCktMSwxMSwzMSk7Y2FzZSA2OnJldHVybiBuZXcgRGF0ZShkLmdldEZ1bGxZZWFyKCktMSwxMSwzMCl9fWZ1bmN0aW9uIHcoZCl7dmFyIG09ZC5xYTtmb3IoZD1uZXcgRGF0ZSgobmV3IERhdGUoZC5yYSsxOTAwLDAsMSkpLmdldFRpbWUoKSk7MDxtOyl7dmFyIG49ZC5nZXRNb250aCgpLEI9KFkoZC5nZXRGdWxsWWVhcigpKT9GYTpHYSlbbl07aWYobT5CLWQuZ2V0RGF0ZSgpKW0tPUItZC5nZXREYXRlKCkrMSxkLnNldERhdGUoMSksMTE+bj9kLnNldE1vbnRoKG4rMSk6KGQuc2V0TW9udGgoMCksZC5zZXRGdWxsWWVhcihkLmdldEZ1bGxZZWFyKCkrMSkpO2Vsc2V7ZC5zZXREYXRlKGQuZ2V0RGF0ZSgpK20pO2JyZWFrfX1uPW5ldyBEYXRlKGQuZ2V0RnVsbFllYXIoKSsxLDAsNCk7bT1xKG5ldyBEYXRlKGQuZ2V0RnVsbFllYXIoKSxcclxuMCw0KSk7bj1xKG4pO3JldHVybiAwPj1sKG0sZCk/MD49bChuLGQpP2QuZ2V0RnVsbFllYXIoKSsxOmQuZ2V0RnVsbFllYXIoKTpkLmdldEZ1bGxZZWFyKCktMX12YXIgdj1RW2YrNDA+PjI+Pj4wXTtmPXtFYTpRW2Y+PjI+Pj4wXSxEYTpRW2YrND4+Mj4+PjBdLHRhOlFbZis4Pj4yPj4+MF0sdmE6UVtmKzEyPj4yPj4+MF0sdWE6UVtmKzE2Pj4yPj4+MF0scmE6UVtmKzIwPj4yPj4+MF0sbGE6UVtmKzI0Pj4yPj4+MF0scWE6UVtmKzI4Pj4yPj4+MF0sSmE6UVtmKzMyPj4yPj4+MF0sQ2E6UVtmKzM2Pj4yPj4+MF0sRmE6dj9MKHYpOlwiXCJ9O2U9TChlKTt2PXtcIiVjXCI6XCIlYSAlYiAlZCAlSDolTTolUyAlWVwiLFwiJURcIjpcIiVtLyVkLyV5XCIsXCIlRlwiOlwiJVktJW0tJWRcIixcIiVoXCI6XCIlYlwiLFwiJXJcIjpcIiVJOiVNOiVTICVwXCIsXCIlUlwiOlwiJUg6JU1cIixcIiVUXCI6XCIlSDolTTolU1wiLFwiJXhcIjpcIiVtLyVkLyV5XCIsXCIlWFwiOlwiJUg6JU06JVNcIixcIiVFY1wiOlwiJWNcIixcIiVFQ1wiOlwiJUNcIixcIiVFeFwiOlwiJW0vJWQvJXlcIixcclxuXCIlRVhcIjpcIiVIOiVNOiVTXCIsXCIlRXlcIjpcIiV5XCIsXCIlRVlcIjpcIiVZXCIsXCIlT2RcIjpcIiVkXCIsXCIlT2VcIjpcIiVlXCIsXCIlT0hcIjpcIiVIXCIsXCIlT0lcIjpcIiVJXCIsXCIlT21cIjpcIiVtXCIsXCIlT01cIjpcIiVNXCIsXCIlT1NcIjpcIiVTXCIsXCIlT3VcIjpcIiV1XCIsXCIlT1VcIjpcIiVVXCIsXCIlT1ZcIjpcIiVWXCIsXCIlT3dcIjpcIiV3XCIsXCIlT1dcIjpcIiVXXCIsXCIlT3lcIjpcIiV5XCJ9O2Zvcih2YXIgciBpbiB2KWU9ZS5yZXBsYWNlKG5ldyBSZWdFeHAocixcImdcIiksdltyXSk7dmFyIHlhPVwiU3VuZGF5IE1vbmRheSBUdWVzZGF5IFdlZG5lc2RheSBUaHVyc2RheSBGcmlkYXkgU2F0dXJkYXlcIi5zcGxpdChcIiBcIiksemE9XCJKYW51YXJ5IEZlYnJ1YXJ5IE1hcmNoIEFwcmlsIE1heSBKdW5lIEp1bHkgQXVndXN0IFNlcHRlbWJlciBPY3RvYmVyIE5vdmVtYmVyIERlY2VtYmVyXCIuc3BsaXQoXCIgXCIpO3Y9e1wiJWFcIjpmdW5jdGlvbihkKXtyZXR1cm4geWFbZC5sYV0uc3Vic3RyaW5nKDAsMyl9LFwiJUFcIjpmdW5jdGlvbihkKXtyZXR1cm4geWFbZC5sYV19LFwiJWJcIjpmdW5jdGlvbihkKXtyZXR1cm4gemFbZC51YV0uc3Vic3RyaW5nKDAsXHJcbjMpfSxcIiVCXCI6ZnVuY3Rpb24oZCl7cmV0dXJuIHphW2QudWFdfSxcIiVDXCI6ZnVuY3Rpb24oZCl7cmV0dXJuIGgoKGQucmErMTkwMCkvMTAwfDAsMil9LFwiJWRcIjpmdW5jdGlvbihkKXtyZXR1cm4gaChkLnZhLDIpfSxcIiVlXCI6ZnVuY3Rpb24oZCl7cmV0dXJuIGcoZC52YSwyLFwiIFwiKX0sXCIlZ1wiOmZ1bmN0aW9uKGQpe3JldHVybiB3KGQpLnRvU3RyaW5nKCkuc3Vic3RyaW5nKDIpfSxcIiVHXCI6ZnVuY3Rpb24oZCl7cmV0dXJuIHcoZCl9LFwiJUhcIjpmdW5jdGlvbihkKXtyZXR1cm4gaChkLnRhLDIpfSxcIiVJXCI6ZnVuY3Rpb24oZCl7ZD1kLnRhOzA9PWQ/ZD0xMjoxMjxkJiYoZC09MTIpO3JldHVybiBoKGQsMil9LFwiJWpcIjpmdW5jdGlvbihkKXtmb3IodmFyIG09MCxuPTA7bjw9ZC51YS0xO20rPShZKGQucmErMTkwMCk/RmE6R2EpW24rK10pO3JldHVybiBoKGQudmErbSwzKX0sXCIlbVwiOmZ1bmN0aW9uKGQpe3JldHVybiBoKGQudWErMSwyKX0sXCIlTVwiOmZ1bmN0aW9uKGQpe3JldHVybiBoKGQuRGEsXHJcbjIpfSxcIiVuXCI6ZnVuY3Rpb24oKXtyZXR1cm5cIlxcblwifSxcIiVwXCI6ZnVuY3Rpb24oZCl7cmV0dXJuIDA8PWQudGEmJjEyPmQudGE/XCJBTVwiOlwiUE1cIn0sXCIlU1wiOmZ1bmN0aW9uKGQpe3JldHVybiBoKGQuRWEsMil9LFwiJXRcIjpmdW5jdGlvbigpe3JldHVyblwiXFx0XCJ9LFwiJXVcIjpmdW5jdGlvbihkKXtyZXR1cm4gZC5sYXx8N30sXCIlVVwiOmZ1bmN0aW9uKGQpe3JldHVybiBoKE1hdGguZmxvb3IoKGQucWErNy1kLmxhKS83KSwyKX0sXCIlVlwiOmZ1bmN0aW9uKGQpe3ZhciBtPU1hdGguZmxvb3IoKGQucWErNy0oZC5sYSs2KSU3KS83KTsyPj0oZC5sYSszNzEtZC5xYS0yKSU3JiZtKys7aWYobSk1Mz09bSYmKG49KGQubGErMzcxLWQucWEpJTcsND09bnx8Mz09biYmWShkLnJhKXx8KG09MSkpO2Vsc2V7bT01Mjt2YXIgbj0oZC5sYSs3LWQucWEtMSklNzsoND09bnx8NT09biYmWShkLnJhJTQwMC0xKSkmJm0rK31yZXR1cm4gaChtLDIpfSxcIiV3XCI6ZnVuY3Rpb24oZCl7cmV0dXJuIGQubGF9LFwiJVdcIjpmdW5jdGlvbihkKXtyZXR1cm4gaChNYXRoLmZsb29yKChkLnFhK1xyXG43LShkLmxhKzYpJTcpLzcpLDIpfSxcIiV5XCI6ZnVuY3Rpb24oZCl7cmV0dXJuKGQucmErMTkwMCkudG9TdHJpbmcoKS5zdWJzdHJpbmcoMil9LFwiJVlcIjpmdW5jdGlvbihkKXtyZXR1cm4gZC5yYSsxOTAwfSxcIiV6XCI6ZnVuY3Rpb24oZCl7ZD1kLkNhO3ZhciBtPTA8PWQ7ZD1NYXRoLmFicyhkKS82MDtyZXR1cm4obT9cIitcIjpcIi1cIikrU3RyaW5nKFwiMDAwMFwiKyhkLzYwKjEwMCtkJTYwKSkuc2xpY2UoLTQpfSxcIiVaXCI6ZnVuY3Rpb24oZCl7cmV0dXJuIGQuRmF9LFwiJSVcIjpmdW5jdGlvbigpe3JldHVyblwiJVwifX07ZT1lLnJlcGxhY2UoLyUlL2csXCJcXHgwMFxceDAwXCIpO2ZvcihyIGluIHYpZS5pbmNsdWRlcyhyKSYmKGU9ZS5yZXBsYWNlKG5ldyBSZWdFeHAocixcImdcIiksdltyXShmKSkpO2U9ZS5yZXBsYWNlKC9cXDBcXDAvZyxcIiVcIik7cj1IYShlKTtpZihyLmxlbmd0aD5jKXJldHVybiAwO1Auc2V0KHIsYT4+PjApO3JldHVybiByLmxlbmd0aC0xfVxyXG52YXIgSmE9e2E6ZnVuY3Rpb24oYSl7cmV0dXJuIHVhKGErMjQpKzI0fSxiOmZ1bmN0aW9uKGEsYyxlKXsobmV3IHJhKGEpKS55YShjLGUpO3NhKys7dGhyb3cgYTt9LGc6ZnVuY3Rpb24oKXtyZXR1cm4gMH0sSTpmdW5jdGlvbigpe30sdzpmdW5jdGlvbigpe30seTpmdW5jdGlvbigpe30sSzpmdW5jdGlvbigpe3JldHVybiAwfSxHOmZ1bmN0aW9uKCl7fSxDOmZ1bmN0aW9uKCl7fSxGOmZ1bmN0aW9uKCl7fSxrOmZ1bmN0aW9uKCl7fSx4OmZ1bmN0aW9uKCl7fSx1OmZ1bmN0aW9uKCl7fSxIOmZ1bmN0aW9uKCl7fSx2OmZ1bmN0aW9uKCl7fSxuOmZ1bmN0aW9uKCl7fSxwOmZ1bmN0aW9uKCl7SShcIlRvIHVzZSBkbG9wZW4sIHlvdSBuZWVkIGVuYWJsZSBkeW5hbWljIGxpbmtpbmcsIHNlZSBodHRwczovL2dpdGh1Yi5jb20vZW1zY3JpcHRlbi1jb3JlL2Vtc2NyaXB0ZW4vd2lraS9MaW5raW5nXCIpfSxvOmZ1bmN0aW9uKCl7SShcIlRvIHVzZSBkbG9wZW4sIHlvdSBuZWVkIGVuYWJsZSBkeW5hbWljIGxpbmtpbmcsIHNlZSBodHRwczovL2dpdGh1Yi5jb20vZW1zY3JpcHRlbi1jb3JlL2Vtc2NyaXB0ZW4vd2lraS9MaW5raW5nXCIpfSxcclxubDpmdW5jdGlvbigpe3JldHVybiBEYXRlLm5vdygpfSxMOmZ1bmN0aW9uKCl7cmV0dXJuITB9LE06ZnVuY3Rpb24oYSxjKXthPW5ldyBEYXRlKDFFMyooUlthPj4+Ml0rNDI5NDk2NzI5NipRW2ErND4+PjJdKSk7UVtjPj4yPj4+MF09YS5nZXRVVENTZWNvbmRzKCk7UVtjKzQ+PjI+Pj4wXT1hLmdldFVUQ01pbnV0ZXMoKTtRW2MrOD4+Mj4+PjBdPWEuZ2V0VVRDSG91cnMoKTtRW2MrMTI+PjI+Pj4wXT1hLmdldFVUQ0RhdGUoKTtRW2MrMTY+PjI+Pj4wXT1hLmdldFVUQ01vbnRoKCk7UVtjKzIwPj4yPj4+MF09YS5nZXRVVENGdWxsWWVhcigpLTE5MDA7UVtjKzI0Pj4yPj4+MF09YS5nZXRVVENEYXkoKTtRW2MrMjg+PjI+Pj4wXT0oYS5nZXRUaW1lKCktRGF0ZS5VVEMoYS5nZXRVVENGdWxsWWVhcigpLDAsMSwwLDAsMCwwKSkvODY0RTV8MH0sTjpmdW5jdGlvbihhLGMpe2E9bmV3IERhdGUoMUUzKihSW2E+Pj4yXSs0Mjk0OTY3Mjk2KlFbYSs0Pj4+Ml0pKTtRW2M+PjI+Pj4wXT1hLmdldFNlY29uZHMoKTtcclxuUVtjKzQ+PjI+Pj4wXT1hLmdldE1pbnV0ZXMoKTtRW2MrOD4+Mj4+PjBdPWEuZ2V0SG91cnMoKTtRW2MrMTI+PjI+Pj4wXT1hLmdldERhdGUoKTtRW2MrMTY+PjI+Pj4wXT1hLmdldE1vbnRoKCk7UVtjKzIwPj4yPj4+MF09YS5nZXRGdWxsWWVhcigpLTE5MDA7UVtjKzI0Pj4yPj4+MF09YS5nZXREYXkoKTt2YXIgZT1uZXcgRGF0ZShhLmdldEZ1bGxZZWFyKCksMCwxKTtRW2MrMjg+PjI+Pj4wXT0oYS5nZXRUaW1lKCktZS5nZXRUaW1lKCkpLzg2NEU1fDA7UVtjKzM2Pj4yPj4+MF09LSg2MCphLmdldFRpbWV6b25lT2Zmc2V0KCkpO3ZhciBmPShuZXcgRGF0ZShhLmdldEZ1bGxZZWFyKCksNiwxKSkuZ2V0VGltZXpvbmVPZmZzZXQoKTtlPWUuZ2V0VGltZXpvbmVPZmZzZXQoKTtRW2MrMzI+PjI+Pj4wXT0oZiE9ZSYmYS5nZXRUaW1lem9uZU9mZnNldCgpPT1NYXRoLm1pbihlLGYpKXwwfSxPOmZ1bmN0aW9uKGEpe3ZhciBjPW5ldyBEYXRlKFFbYSsyMD4+Mj4+PjBdKzE5MDAsUVthKzE2Pj5cclxuMj4+PjBdLFFbYSsxMj4+Mj4+PjBdLFFbYSs4Pj4yPj4+MF0sUVthKzQ+PjI+Pj4wXSxRW2E+PjI+Pj4wXSwwKSxlPVFbYSszMj4+Mj4+PjBdLGY9Yy5nZXRUaW1lem9uZU9mZnNldCgpLGc9bmV3IERhdGUoYy5nZXRGdWxsWWVhcigpLDAsMSksaD0obmV3IERhdGUoYy5nZXRGdWxsWWVhcigpLDYsMSkpLmdldFRpbWV6b25lT2Zmc2V0KCksbD1nLmdldFRpbWV6b25lT2Zmc2V0KCkscT1NYXRoLm1pbihsLGgpOzA+ZT9RW2ErMzI+PjI+Pj4wXT1OdW1iZXIoaCE9bCYmcT09Zik6MDxlIT0ocT09ZikmJihoPU1hdGgubWF4KGwsaCksYy5zZXRUaW1lKGMuZ2V0VGltZSgpKzZFNCooKDA8ZT9xOmgpLWYpKSk7UVthKzI0Pj4yPj4+MF09Yy5nZXREYXkoKTtRW2ErMjg+PjI+Pj4wXT0oYy5nZXRUaW1lKCktZy5nZXRUaW1lKCkpLzg2NEU1fDA7UVthPj4yPj4+MF09Yy5nZXRTZWNvbmRzKCk7UVthKzQ+PjI+Pj4wXT1jLmdldE1pbnV0ZXMoKTtRW2ErOD4+Mj4+PjBdPWMuZ2V0SG91cnMoKTtRW2ErXHJcbjEyPj4yPj4+MF09Yy5nZXREYXRlKCk7UVthKzE2Pj4yPj4+MF09Yy5nZXRNb250aCgpO3JldHVybiBjLmdldFRpbWUoKS8xRTN8MH0sejpmdW5jdGlvbigpe3JldHVybi01Mn0sQjpmdW5jdGlvbigpe30sbTp3YSxkOmZ1bmN0aW9uKCl7SShcIlwiKX0sdDpmdW5jdGlvbigpe3JldHVybiA0Mjk0OTAxNzYwfSxoOng/KCk9Pnt2YXIgYT1wcm9jZXNzLmhydGltZSgpO3JldHVybiAxRTMqYVswXSthWzFdLzFFNn06KCk9PnBlcmZvcm1hbmNlLm5vdygpLEo6ZnVuY3Rpb24oYSxjLGUpe00uY29weVdpdGhpbihhPj4+MCxjPj4+MCxjK2U+Pj4wKX0sZjpmdW5jdGlvbihhKXt2YXIgYz1NLmxlbmd0aDthPj4+PTA7aWYoNDI5NDkwMTc2MDxhKXJldHVybiExO2Zvcih2YXIgZT0xOzQ+PWU7ZSo9Mil7dmFyIGY9YyooMSsuMi9lKTtmPU1hdGgubWluKGYsYSsxMDA2NjMyOTYpO3ZhciBnPU1hdGg7Zj1NYXRoLm1heChhLGYpO2c9Zy5taW4uY2FsbChnLDQyOTQ5MDE3NjAsZisoNjU1MzYtZiU2NTUzNiklXHJcbjY1NTM2KTthOnt0cnl7Si5ncm93KGctaGEuYnl0ZUxlbmd0aCs2NTUzNT4+PjE2KTtpYSgpO3ZhciBoPTE7YnJlYWsgYX1jYXRjaChsKXt9aD12b2lkIDB9aWYoaClyZXR1cm4hMH1yZXR1cm4hMX0sRDpmdW5jdGlvbihhLGMpe3ZhciBlPTA7QmEoKS5mb3JFYWNoKGZ1bmN0aW9uKGYsZyl7dmFyIGg9YytlO2c9UlthKzQqZz4+Mj4+PjBdPWg7Zm9yKGg9MDtoPGYubGVuZ3RoOysraClQW2crKz4+MD4+PjBdPWYuY2hhckNvZGVBdChoKTtQW2c+PjA+Pj4wXT0wO2UrPWYubGVuZ3RoKzF9KTtyZXR1cm4gMH0sRTpmdW5jdGlvbihhLGMpe3ZhciBlPUJhKCk7UlthPj4yPj4+MF09ZS5sZW5ndGg7dmFyIGY9MDtlLmZvckVhY2goZnVuY3Rpb24oZyl7Zis9Zy5sZW5ndGgrMX0pO1JbYz4+Mj4+PjBdPWY7cmV0dXJuIDB9LHI6ZnVuY3Rpb24oYSl7aWYoIW5vRXhpdFJ1bnRpbWUpe2lmKGIub25FeGl0KWIub25FeGl0KGEpO0s9ITB9dChhLG5ldyBGKGEpKX0sZTpmdW5jdGlvbigpe3JldHVybiA1Mn0sXHJcbmo6ZnVuY3Rpb24oKXtyZXR1cm4gNTJ9LHE6ZnVuY3Rpb24oKXtyZXR1cm4gNzB9LGk6ZnVuY3Rpb24oYSxjLGUsZil7Zm9yKHZhciBnPTAsaD0wO2g8ZTtoKyspe3ZhciBsPVJbYz4+Mj4+PjBdLHE9UltjKzQ+PjI+Pj4wXTtjKz04O2Zvcih2YXIgdz0wO3c8cTt3Kyspe3ZhciB2PU1bbCt3Pj4+MF0scj1EYVthXTswPT09dnx8MTA9PT12PygoMT09PWE/ZGE6RykoZmEociwwKSksci5sZW5ndGg9MCk6ci5wdXNoKHYpfWcrPXF9UltmPj4yPj4+MF09ZztyZXR1cm4gMH0sczpYLEE6SWEsYzpmdW5jdGlvbihhLGMsZSxmKXtyZXR1cm4gSWEoYSxjLGUsZil9fTtcclxuKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gYShnKXtiLmFzbT1nLmV4cG9ydHM7Sj1iLmFzbS5QO2lhKCk7a2EudW5zaGlmdChiLmFzbS5RKTtTLS07Yi5tb25pdG9yUnVuRGVwZW5kZW5jaWVzJiZiLm1vbml0b3JSdW5EZXBlbmRlbmNpZXMoUyk7MD09UyYmKG51bGwhPT1UJiYoY2xlYXJJbnRlcnZhbChUKSxUPW51bGwpLFUmJihnPVUsVT1udWxsLGcoKSkpfWZ1bmN0aW9uIGMoZyl7YShnLmluc3RhbmNlKX1mdW5jdGlvbiBlKGcpe3JldHVybiBxYSgpLnRoZW4oZnVuY3Rpb24oaCl7cmV0dXJuIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlKGgsZil9KS50aGVuKGZ1bmN0aW9uKGgpe3JldHVybiBofSkudGhlbihnLGZ1bmN0aW9uKGgpe0coXCJmYWlsZWQgdG8gYXN5bmNocm9ub3VzbHkgcHJlcGFyZSB3YXNtOiBcIitoKTtJKGgpfSl9dmFyIGY9e2E6SmF9O1MrKztiLm1vbml0b3JSdW5EZXBlbmRlbmNpZXMmJmIubW9uaXRvclJ1bkRlcGVuZGVuY2llcyhTKTtpZihiLmluc3RhbnRpYXRlV2FzbSl0cnl7cmV0dXJuIGIuaW5zdGFudGlhdGVXYXNtKGYsXHJcbmEpfWNhdGNoKGcpe3JldHVybiBHKFwiTW9kdWxlLmluc3RhbnRpYXRlV2FzbSBjYWxsYmFjayBmYWlsZWQgd2l0aCBlcnJvcjogXCIrZyksITF9KGZ1bmN0aW9uKCl7cmV0dXJuIEh8fFwiZnVuY3Rpb25cIiE9dHlwZW9mIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nfHxuYSgpfHxWLnN0YXJ0c1dpdGgoXCJmaWxlOi8vXCIpfHx4fHxcImZ1bmN0aW9uXCIhPXR5cGVvZiBmZXRjaD9lKGMpOmZldGNoKFYse2NyZWRlbnRpYWxzOlwic2FtZS1vcmlnaW5cIn0pLnRoZW4oZnVuY3Rpb24oZyl7cmV0dXJuIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nKGcsZikudGhlbihjLGZ1bmN0aW9uKGgpe0coXCJ3YXNtIHN0cmVhbWluZyBjb21waWxlIGZhaWxlZDogXCIraCk7RyhcImZhbGxpbmcgYmFjayB0byBBcnJheUJ1ZmZlciBpbnN0YW50aWF0aW9uXCIpO3JldHVybiBlKGMpfSl9KX0pKCkuY2F0Y2goayk7cmV0dXJue319KSgpO1xyXG5iLl9fX3dhc21fY2FsbF9jdG9ycz1mdW5jdGlvbigpe3JldHVybihiLl9fX3dhc21fY2FsbF9jdG9ycz1iLmFzbS5RKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2IuX09ydEluaXQ9ZnVuY3Rpb24oKXtyZXR1cm4oYi5fT3J0SW5pdD1iLmFzbS5SKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2IuX09ydENyZWF0ZVNlc3Npb25PcHRpb25zPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydENyZWF0ZVNlc3Npb25PcHRpb25zPWIuYXNtLlMpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07Yi5fT3J0QXBwZW5kRXhlY3V0aW9uUHJvdmlkZXI9ZnVuY3Rpb24oKXtyZXR1cm4oYi5fT3J0QXBwZW5kRXhlY3V0aW9uUHJvdmlkZXI9Yi5hc20uVCkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLl9PcnRBZGRTZXNzaW9uQ29uZmlnRW50cnk9ZnVuY3Rpb24oKXtyZXR1cm4oYi5fT3J0QWRkU2Vzc2lvbkNvbmZpZ0VudHJ5PWIuYXNtLlUpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XHJcbmIuX09ydFJlbGVhc2VTZXNzaW9uT3B0aW9ucz1mdW5jdGlvbigpe3JldHVybihiLl9PcnRSZWxlYXNlU2Vzc2lvbk9wdGlvbnM9Yi5hc20uVikuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLl9PcnRDcmVhdGVTZXNzaW9uPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydENyZWF0ZVNlc3Npb249Yi5hc20uVykuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLl9PcnRSZWxlYXNlU2Vzc2lvbj1mdW5jdGlvbigpe3JldHVybihiLl9PcnRSZWxlYXNlU2Vzc2lvbj1iLmFzbS5YKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2IuX09ydEdldElucHV0Q291bnQ9ZnVuY3Rpb24oKXtyZXR1cm4oYi5fT3J0R2V0SW5wdXRDb3VudD1iLmFzbS5ZKS5hcHBseShudWxsLGFyZ3VtZW50cyl9O2IuX09ydEdldE91dHB1dENvdW50PWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydEdldE91dHB1dENvdW50PWIuYXNtLlopLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XHJcbmIuX09ydEdldElucHV0TmFtZT1mdW5jdGlvbigpe3JldHVybihiLl9PcnRHZXRJbnB1dE5hbWU9Yi5hc20uXykuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLl9PcnRHZXRPdXRwdXROYW1lPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydEdldE91dHB1dE5hbWU9Yi5hc20uJCkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLl9PcnRGcmVlPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydEZyZWU9Yi5hc20uYWEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07Yi5fT3J0Q3JlYXRlVGVuc29yPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydENyZWF0ZVRlbnNvcj1iLmFzbS5iYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLl9PcnRHZXRUZW5zb3JEYXRhPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydEdldFRlbnNvckRhdGE9Yi5hc20uY2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XHJcbmIuX09ydFJlbGVhc2VUZW5zb3I9ZnVuY3Rpb24oKXtyZXR1cm4oYi5fT3J0UmVsZWFzZVRlbnNvcj1iLmFzbS5kYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLl9PcnRDcmVhdGVSdW5PcHRpb25zPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydENyZWF0ZVJ1bk9wdGlvbnM9Yi5hc20uZWEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07Yi5fT3J0QWRkUnVuQ29uZmlnRW50cnk9ZnVuY3Rpb24oKXtyZXR1cm4oYi5fT3J0QWRkUnVuQ29uZmlnRW50cnk9Yi5hc20uZmEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07Yi5fT3J0UmVsZWFzZVJ1bk9wdGlvbnM9ZnVuY3Rpb24oKXtyZXR1cm4oYi5fT3J0UmVsZWFzZVJ1bk9wdGlvbnM9Yi5hc20uZ2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07Yi5fT3J0UnVuPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydFJ1bj1iLmFzbS5oYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtcclxuYi5fT3J0RW5kUHJvZmlsaW5nPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX09ydEVuZFByb2ZpbGluZz1iLmFzbS5pYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTt2YXIgdWE9Yi5fbWFsbG9jPWZ1bmN0aW9uKCl7cmV0dXJuKHVhPWIuX21hbGxvYz1iLmFzbS5qYSkuYXBwbHkobnVsbCxhcmd1bWVudHMpfTtiLl9mcmVlPWZ1bmN0aW9uKCl7cmV0dXJuKGIuX2ZyZWU9Yi5hc20ua2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07dmFyIEthPWIuc3RhY2tTYXZlPWZ1bmN0aW9uKCl7cmV0dXJuKEthPWIuc3RhY2tTYXZlPWIuYXNtLm1hKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LExhPWIuc3RhY2tSZXN0b3JlPWZ1bmN0aW9uKCl7cmV0dXJuKExhPWIuc3RhY2tSZXN0b3JlPWIuYXNtLm5hKS5hcHBseShudWxsLGFyZ3VtZW50cyl9LE1hPWIuc3RhY2tBbGxvYz1mdW5jdGlvbigpe3JldHVybihNYT1iLnN0YWNrQWxsb2M9Yi5hc20ub2EpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07XHJcbmIuX19fY3hhX2lzX3BvaW50ZXJfdHlwZT1mdW5jdGlvbigpe3JldHVybihiLl9fX2N4YV9pc19wb2ludGVyX3R5cGU9Yi5hc20ucGEpLmFwcGx5KG51bGwsYXJndW1lbnRzKX07Yi5VVEY4VG9TdHJpbmc9TDtiLnN0cmluZ1RvVVRGOD1mdW5jdGlvbihhLGMsZSl7cmV0dXJuIE4oYSxNLGMsZSl9O2IubGVuZ3RoQnl0ZXNVVEY4PU87Yi5zdGFja1NhdmU9S2E7Yi5zdGFja1Jlc3RvcmU9TGE7Yi5zdGFja0FsbG9jPU1hO3ZhciBaO1U9ZnVuY3Rpb24gTmEoKXtafHxPYSgpO1p8fChVPU5hKX07XHJcbmZ1bmN0aW9uIE9hKCl7ZnVuY3Rpb24gYSgpe2lmKCFaJiYoWj0hMCxiLmNhbGxlZFJ1bj0hMCwhSykpe1coa2EpO2FhKGIpO2lmKGIub25SdW50aW1lSW5pdGlhbGl6ZWQpYi5vblJ1bnRpbWVJbml0aWFsaXplZCgpO2lmKGIucG9zdFJ1bilmb3IoXCJmdW5jdGlvblwiPT10eXBlb2YgYi5wb3N0UnVuJiYoYi5wb3N0UnVuPVtiLnBvc3RSdW5dKTtiLnBvc3RSdW4ubGVuZ3RoOyl7dmFyIGM9Yi5wb3N0UnVuLnNoaWZ0KCk7bGEudW5zaGlmdChjKX1XKGxhKX19aWYoISgwPFMpKXtpZihiLnByZVJ1bilmb3IoXCJmdW5jdGlvblwiPT10eXBlb2YgYi5wcmVSdW4mJihiLnByZVJ1bj1bYi5wcmVSdW5dKTtiLnByZVJ1bi5sZW5ndGg7KW1hKCk7VyhqYSk7MDxTfHwoYi5zZXRTdGF0dXM/KGIuc2V0U3RhdHVzKFwiUnVubmluZy4uLlwiKSxzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7c2V0VGltZW91dChmdW5jdGlvbigpe2Iuc2V0U3RhdHVzKFwiXCIpfSwxKTthKCl9LDEpKTphKCkpfX1cclxuaWYoYi5wcmVJbml0KWZvcihcImZ1bmN0aW9uXCI9PXR5cGVvZiBiLnByZUluaXQmJihiLnByZUluaXQ9W2IucHJlSW5pdF0pOzA8Yi5wcmVJbml0Lmxlbmd0aDspYi5wcmVJbml0LnBvcCgpKCk7T2EoKTtcclxuXHJcblxyXG4gIHJldHVybiBvcnRXYXNtLnJlYWR5XHJcbn1cclxuKTtcclxufSkoKTtcclxuaWYgKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlID09PSAnb2JqZWN0JylcclxuICBtb2R1bGUuZXhwb3J0cyA9IG9ydFdhc207XHJcbmVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lWydhbWQnXSlcclxuICBkZWZpbmUoW10sIGZ1bmN0aW9uKCkgeyByZXR1cm4gb3J0V2FzbTsgfSk7XHJcbmVsc2UgaWYgKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JylcclxuICBleHBvcnRzW1wib3J0V2FzbVwiXSA9IG9ydFdhc207XHJcbiIsIlwidXNlIHN0cmljdFwiO1xyXG5tb2R1bGUuZXhwb3J0cyA9IGFzUHJvbWlzZTtcclxuXHJcbi8qKlxyXG4gKiBDYWxsYmFjayBhcyB1c2VkIGJ5IHtAbGluayB1dGlsLmFzUHJvbWlzZX0uXHJcbiAqIEB0eXBlZGVmIGFzUHJvbWlzZUNhbGxiYWNrXHJcbiAqIEB0eXBlIHtmdW5jdGlvbn1cclxuICogQHBhcmFtIHtFcnJvcnxudWxsfSBlcnJvciBFcnJvciwgaWYgYW55XHJcbiAqIEBwYXJhbSB7Li4uKn0gcGFyYW1zIEFkZGl0aW9uYWwgYXJndW1lbnRzXHJcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgYSBwcm9taXNlIGZyb20gYSBub2RlLXN0eWxlIGNhbGxiYWNrIGZ1bmN0aW9uLlxyXG4gKiBAbWVtYmVyb2YgdXRpbFxyXG4gKiBAcGFyYW0ge2FzUHJvbWlzZUNhbGxiYWNrfSBmbiBGdW5jdGlvbiB0byBjYWxsXHJcbiAqIEBwYXJhbSB7Kn0gY3R4IEZ1bmN0aW9uIGNvbnRleHRcclxuICogQHBhcmFtIHsuLi4qfSBwYXJhbXMgRnVuY3Rpb24gYXJndW1lbnRzXHJcbiAqIEByZXR1cm5zIHtQcm9taXNlPCo+fSBQcm9taXNpZmllZCBmdW5jdGlvblxyXG4gKi9cclxuZnVuY3Rpb24gYXNQcm9taXNlKGZuLCBjdHgvKiwgdmFyYXJncyAqLykge1xyXG4gICAgdmFyIHBhcmFtcyAgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCAtIDEpLFxyXG4gICAgICAgIG9mZnNldCAgPSAwLFxyXG4gICAgICAgIGluZGV4ICAgPSAyLFxyXG4gICAgICAgIHBlbmRpbmcgPSB0cnVlO1xyXG4gICAgd2hpbGUgKGluZGV4IDwgYXJndW1lbnRzLmxlbmd0aClcclxuICAgICAgICBwYXJhbXNbb2Zmc2V0KytdID0gYXJndW1lbnRzW2luZGV4KytdO1xyXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIGV4ZWN1dG9yKHJlc29sdmUsIHJlamVjdCkge1xyXG4gICAgICAgIHBhcmFtc1tvZmZzZXRdID0gZnVuY3Rpb24gY2FsbGJhY2soZXJyLyosIHZhcmFyZ3MgKi8pIHtcclxuICAgICAgICAgICAgaWYgKHBlbmRpbmcpIHtcclxuICAgICAgICAgICAgICAgIHBlbmRpbmcgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgIGlmIChlcnIpXHJcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XHJcbiAgICAgICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyYW1zID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGggLSAxKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0ID0gMDtcclxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAob2Zmc2V0IDwgcGFyYW1zLmxlbmd0aClcclxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zW29mZnNldCsrXSA9IGFyZ3VtZW50c1tvZmZzZXRdO1xyXG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUuYXBwbHkobnVsbCwgcGFyYW1zKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcbiAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgZm4uYXBwbHkoY3R4IHx8IG51bGwsIHBhcmFtcyk7XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XHJcbiAgICAgICAgICAgIGlmIChwZW5kaW5nKSB7XHJcbiAgICAgICAgICAgICAgICBwZW5kaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICByZWplY3QoZXJyKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH0pO1xyXG59XHJcbiIsIlwidXNlIHN0cmljdFwiO1xyXG5cclxuLyoqXHJcbiAqIEEgbWluaW1hbCBiYXNlNjQgaW1wbGVtZW50YXRpb24gZm9yIG51bWJlciBhcnJheXMuXHJcbiAqIEBtZW1iZXJvZiB1dGlsXHJcbiAqIEBuYW1lc3BhY2VcclxuICovXHJcbnZhciBiYXNlNjQgPSBleHBvcnRzO1xyXG5cclxuLyoqXHJcbiAqIENhbGN1bGF0ZXMgdGhlIGJ5dGUgbGVuZ3RoIG9mIGEgYmFzZTY0IGVuY29kZWQgc3RyaW5nLlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIEJhc2U2NCBlbmNvZGVkIHN0cmluZ1xyXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBCeXRlIGxlbmd0aFxyXG4gKi9cclxuYmFzZTY0Lmxlbmd0aCA9IGZ1bmN0aW9uIGxlbmd0aChzdHJpbmcpIHtcclxuICAgIHZhciBwID0gc3RyaW5nLmxlbmd0aDtcclxuICAgIGlmICghcClcclxuICAgICAgICByZXR1cm4gMDtcclxuICAgIHZhciBuID0gMDtcclxuICAgIHdoaWxlICgtLXAgJSA0ID4gMSAmJiBzdHJpbmcuY2hhckF0KHApID09PSBcIj1cIilcclxuICAgICAgICArK247XHJcbiAgICByZXR1cm4gTWF0aC5jZWlsKHN0cmluZy5sZW5ndGggKiAzKSAvIDQgLSBuO1xyXG59O1xyXG5cclxuLy8gQmFzZTY0IGVuY29kaW5nIHRhYmxlXHJcbnZhciBiNjQgPSBuZXcgQXJyYXkoNjQpO1xyXG5cclxuLy8gQmFzZTY0IGRlY29kaW5nIHRhYmxlXHJcbnZhciBzNjQgPSBuZXcgQXJyYXkoMTIzKTtcclxuXHJcbi8vIDY1Li45MCwgOTcuLjEyMiwgNDguLjU3LCA0MywgNDdcclxuZm9yICh2YXIgaSA9IDA7IGkgPCA2NDspXHJcbiAgICBzNjRbYjY0W2ldID0gaSA8IDI2ID8gaSArIDY1IDogaSA8IDUyID8gaSArIDcxIDogaSA8IDYyID8gaSAtIDQgOiBpIC0gNTkgfCA0M10gPSBpKys7XHJcblxyXG4vKipcclxuICogRW5jb2RlcyBhIGJ1ZmZlciB0byBhIGJhc2U2NCBlbmNvZGVkIHN0cmluZy5cclxuICogQHBhcmFtIHtVaW50OEFycmF5fSBidWZmZXIgU291cmNlIGJ1ZmZlclxyXG4gKiBAcGFyYW0ge251bWJlcn0gc3RhcnQgU291cmNlIHN0YXJ0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgU291cmNlIGVuZFxyXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBCYXNlNjQgZW5jb2RlZCBzdHJpbmdcclxuICovXHJcbmJhc2U2NC5lbmNvZGUgPSBmdW5jdGlvbiBlbmNvZGUoYnVmZmVyLCBzdGFydCwgZW5kKSB7XHJcbiAgICB2YXIgcGFydHMgPSBudWxsLFxyXG4gICAgICAgIGNodW5rID0gW107XHJcbiAgICB2YXIgaSA9IDAsIC8vIG91dHB1dCBpbmRleFxyXG4gICAgICAgIGogPSAwLCAvLyBnb3RvIGluZGV4XHJcbiAgICAgICAgdDsgICAgIC8vIHRlbXBvcmFyeVxyXG4gICAgd2hpbGUgKHN0YXJ0IDwgZW5kKSB7XHJcbiAgICAgICAgdmFyIGIgPSBidWZmZXJbc3RhcnQrK107XHJcbiAgICAgICAgc3dpdGNoIChqKSB7XHJcbiAgICAgICAgICAgIGNhc2UgMDpcclxuICAgICAgICAgICAgICAgIGNodW5rW2krK10gPSBiNjRbYiA+PiAyXTtcclxuICAgICAgICAgICAgICAgIHQgPSAoYiAmIDMpIDw8IDQ7XHJcbiAgICAgICAgICAgICAgICBqID0gMTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIDE6XHJcbiAgICAgICAgICAgICAgICBjaHVua1tpKytdID0gYjY0W3QgfCBiID4+IDRdO1xyXG4gICAgICAgICAgICAgICAgdCA9IChiICYgMTUpIDw8IDI7XHJcbiAgICAgICAgICAgICAgICBqID0gMjtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIDI6XHJcbiAgICAgICAgICAgICAgICBjaHVua1tpKytdID0gYjY0W3QgfCBiID4+IDZdO1xyXG4gICAgICAgICAgICAgICAgY2h1bmtbaSsrXSA9IGI2NFtiICYgNjNdO1xyXG4gICAgICAgICAgICAgICAgaiA9IDA7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGkgPiA4MTkxKSB7XHJcbiAgICAgICAgICAgIChwYXJ0cyB8fCAocGFydHMgPSBbXSkpLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShTdHJpbmcsIGNodW5rKSk7XHJcbiAgICAgICAgICAgIGkgPSAwO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGlmIChqKSB7XHJcbiAgICAgICAgY2h1bmtbaSsrXSA9IGI2NFt0XTtcclxuICAgICAgICBjaHVua1tpKytdID0gNjE7XHJcbiAgICAgICAgaWYgKGogPT09IDEpXHJcbiAgICAgICAgICAgIGNodW5rW2krK10gPSA2MTtcclxuICAgIH1cclxuICAgIGlmIChwYXJ0cykge1xyXG4gICAgICAgIGlmIChpKVxyXG4gICAgICAgICAgICBwYXJ0cy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBjaHVuay5zbGljZSgwLCBpKSkpO1xyXG4gICAgICAgIHJldHVybiBwYXJ0cy5qb2luKFwiXCIpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBjaHVuay5zbGljZSgwLCBpKSk7XHJcbn07XHJcblxyXG52YXIgaW52YWxpZEVuY29kaW5nID0gXCJpbnZhbGlkIGVuY29kaW5nXCI7XHJcblxyXG4vKipcclxuICogRGVjb2RlcyBhIGJhc2U2NCBlbmNvZGVkIHN0cmluZyB0byBhIGJ1ZmZlci5cclxuICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBTb3VyY2Ugc3RyaW5nXHJcbiAqIEBwYXJhbSB7VWludDhBcnJheX0gYnVmZmVyIERlc3RpbmF0aW9uIGJ1ZmZlclxyXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IERlc3RpbmF0aW9uIG9mZnNldFxyXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBOdW1iZXIgb2YgYnl0ZXMgd3JpdHRlblxyXG4gKiBAdGhyb3dzIHtFcnJvcn0gSWYgZW5jb2RpbmcgaXMgaW52YWxpZFxyXG4gKi9cclxuYmFzZTY0LmRlY29kZSA9IGZ1bmN0aW9uIGRlY29kZShzdHJpbmcsIGJ1ZmZlciwgb2Zmc2V0KSB7XHJcbiAgICB2YXIgc3RhcnQgPSBvZmZzZXQ7XHJcbiAgICB2YXIgaiA9IDAsIC8vIGdvdG8gaW5kZXhcclxuICAgICAgICB0OyAgICAgLy8gdGVtcG9yYXJ5XHJcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0cmluZy5sZW5ndGg7KSB7XHJcbiAgICAgICAgdmFyIGMgPSBzdHJpbmcuY2hhckNvZGVBdChpKyspO1xyXG4gICAgICAgIGlmIChjID09PSA2MSAmJiBqID4gMSlcclxuICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgaWYgKChjID0gczY0W2NdKSA9PT0gdW5kZWZpbmVkKVxyXG4gICAgICAgICAgICB0aHJvdyBFcnJvcihpbnZhbGlkRW5jb2RpbmcpO1xyXG4gICAgICAgIHN3aXRjaCAoaikge1xyXG4gICAgICAgICAgICBjYXNlIDA6XHJcbiAgICAgICAgICAgICAgICB0ID0gYztcclxuICAgICAgICAgICAgICAgIGogPSAxO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGNhc2UgMTpcclxuICAgICAgICAgICAgICAgIGJ1ZmZlcltvZmZzZXQrK10gPSB0IDw8IDIgfCAoYyAmIDQ4KSA+PiA0O1xyXG4gICAgICAgICAgICAgICAgdCA9IGM7XHJcbiAgICAgICAgICAgICAgICBqID0gMjtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBjYXNlIDI6XHJcbiAgICAgICAgICAgICAgICBidWZmZXJbb2Zmc2V0KytdID0gKHQgJiAxNSkgPDwgNCB8IChjICYgNjApID4+IDI7XHJcbiAgICAgICAgICAgICAgICB0ID0gYztcclxuICAgICAgICAgICAgICAgIGogPSAzO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGNhc2UgMzpcclxuICAgICAgICAgICAgICAgIGJ1ZmZlcltvZmZzZXQrK10gPSAodCAmIDMpIDw8IDYgfCBjO1xyXG4gICAgICAgICAgICAgICAgaiA9IDA7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBpZiAoaiA9PT0gMSlcclxuICAgICAgICB0aHJvdyBFcnJvcihpbnZhbGlkRW5jb2RpbmcpO1xyXG4gICAgcmV0dXJuIG9mZnNldCAtIHN0YXJ0O1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoZSBzcGVjaWZpZWQgc3RyaW5nIGFwcGVhcnMgdG8gYmUgYmFzZTY0IGVuY29kZWQuXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmcgU3RyaW5nIHRvIHRlc3RcclxuICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiBwcm9iYWJseSBiYXNlNjQgZW5jb2RlZCwgb3RoZXJ3aXNlIGZhbHNlXHJcbiAqL1xyXG5iYXNlNjQudGVzdCA9IGZ1bmN0aW9uIHRlc3Qoc3RyaW5nKSB7XHJcbiAgICByZXR1cm4gL14oPzpbQS1aYS16MC05Ky9dezR9KSooPzpbQS1aYS16MC05Ky9dezJ9PT18W0EtWmEtejAtOSsvXXszfT0pPyQvLnRlc3Qoc3RyaW5nKTtcclxufTtcclxuIiwiXCJ1c2Ugc3RyaWN0XCI7XHJcbm1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xyXG5cclxuLyoqXHJcbiAqIENvbnN0cnVjdHMgYSBuZXcgZXZlbnQgZW1pdHRlciBpbnN0YW5jZS5cclxuICogQGNsYXNzZGVzYyBBIG1pbmltYWwgZXZlbnQgZW1pdHRlci5cclxuICogQG1lbWJlcm9mIHV0aWxcclxuICogQGNvbnN0cnVjdG9yXHJcbiAqL1xyXG5mdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWdpc3RlcmVkIGxpc3RlbmVycy5cclxuICAgICAqIEB0eXBlIHtPYmplY3QuPHN0cmluZywqPn1cclxuICAgICAqIEBwcml2YXRlXHJcbiAgICAgKi9cclxuICAgIHRoaXMuX2xpc3RlbmVycyA9IHt9O1xyXG59XHJcblxyXG4vKipcclxuICogUmVnaXN0ZXJzIGFuIGV2ZW50IGxpc3RlbmVyLlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZ0IEV2ZW50IG5hbWVcclxuICogQHBhcmFtIHtmdW5jdGlvbn0gZm4gTGlzdGVuZXJcclxuICogQHBhcmFtIHsqfSBbY3R4XSBMaXN0ZW5lciBjb250ZXh0XHJcbiAqIEByZXR1cm5zIHt1dGlsLkV2ZW50RW1pdHRlcn0gYHRoaXNgXHJcbiAqL1xyXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLm9uID0gZnVuY3Rpb24gb24oZXZ0LCBmbiwgY3R4KSB7XHJcbiAgICAodGhpcy5fbGlzdGVuZXJzW2V2dF0gfHwgKHRoaXMuX2xpc3RlbmVyc1tldnRdID0gW10pKS5wdXNoKHtcclxuICAgICAgICBmbiAgOiBmbixcclxuICAgICAgICBjdHggOiBjdHggfHwgdGhpc1xyXG4gICAgfSk7XHJcbiAgICByZXR1cm4gdGhpcztcclxufTtcclxuXHJcbi8qKlxyXG4gKiBSZW1vdmVzIGFuIGV2ZW50IGxpc3RlbmVyIG9yIGFueSBtYXRjaGluZyBsaXN0ZW5lcnMgaWYgYXJndW1lbnRzIGFyZSBvbWl0dGVkLlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gW2V2dF0gRXZlbnQgbmFtZS4gUmVtb3ZlcyBhbGwgbGlzdGVuZXJzIGlmIG9taXR0ZWQuXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IFtmbl0gTGlzdGVuZXIgdG8gcmVtb3ZlLiBSZW1vdmVzIGFsbCBsaXN0ZW5lcnMgb2YgYGV2dGAgaWYgb21pdHRlZC5cclxuICogQHJldHVybnMge3V0aWwuRXZlbnRFbWl0dGVyfSBgdGhpc2BcclxuICovXHJcbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub2ZmID0gZnVuY3Rpb24gb2ZmKGV2dCwgZm4pIHtcclxuICAgIGlmIChldnQgPT09IHVuZGVmaW5lZClcclxuICAgICAgICB0aGlzLl9saXN0ZW5lcnMgPSB7fTtcclxuICAgIGVsc2Uge1xyXG4gICAgICAgIGlmIChmbiA9PT0gdW5kZWZpbmVkKVxyXG4gICAgICAgICAgICB0aGlzLl9saXN0ZW5lcnNbZXZ0XSA9IFtdO1xyXG4gICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5fbGlzdGVuZXJzW2V2dF07XHJcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDspXHJcbiAgICAgICAgICAgICAgICBpZiAobGlzdGVuZXJzW2ldLmZuID09PSBmbilcclxuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcnMuc3BsaWNlKGksIDEpO1xyXG4gICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgICsraTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gdGhpcztcclxufTtcclxuXHJcbi8qKlxyXG4gKiBFbWl0cyBhbiBldmVudCBieSBjYWxsaW5nIGl0cyBsaXN0ZW5lcnMgd2l0aCB0aGUgc3BlY2lmaWVkIGFyZ3VtZW50cy5cclxuICogQHBhcmFtIHtzdHJpbmd9IGV2dCBFdmVudCBuYW1lXHJcbiAqIEBwYXJhbSB7Li4uKn0gYXJncyBBcmd1bWVudHNcclxuICogQHJldHVybnMge3V0aWwuRXZlbnRFbWl0dGVyfSBgdGhpc2BcclxuICovXHJcbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uIGVtaXQoZXZ0KSB7XHJcbiAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5fbGlzdGVuZXJzW2V2dF07XHJcbiAgICBpZiAobGlzdGVuZXJzKSB7XHJcbiAgICAgICAgdmFyIGFyZ3MgPSBbXSxcclxuICAgICAgICAgICAgaSA9IDE7XHJcbiAgICAgICAgZm9yICg7IGkgPCBhcmd1bWVudHMubGVuZ3RoOylcclxuICAgICAgICAgICAgYXJncy5wdXNoKGFyZ3VtZW50c1tpKytdKTtcclxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdGVuZXJzLmxlbmd0aDspXHJcbiAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5mbi5hcHBseShsaXN0ZW5lcnNbaSsrXS5jdHgsIGFyZ3MpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRoaXM7XHJcbn07XHJcbiIsIlwidXNlIHN0cmljdFwiO1xyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KGZhY3RvcnkpO1xyXG5cclxuLyoqXHJcbiAqIFJlYWRzIC8gd3JpdGVzIGZsb2F0cyAvIGRvdWJsZXMgZnJvbSAvIHRvIGJ1ZmZlcnMuXHJcbiAqIEBuYW1lIHV0aWwuZmxvYXRcclxuICogQG5hbWVzcGFjZVxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBXcml0ZXMgYSAzMiBiaXQgZmxvYXQgdG8gYSBidWZmZXIgdXNpbmcgbGl0dGxlIGVuZGlhbiBieXRlIG9yZGVyLlxyXG4gKiBAbmFtZSB1dGlsLmZsb2F0LndyaXRlRmxvYXRMRVxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHtudW1iZXJ9IHZhbCBWYWx1ZSB0byB3cml0ZVxyXG4gKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGJ1ZiBUYXJnZXQgYnVmZmVyXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBwb3MgVGFyZ2V0IGJ1ZmZlciBvZmZzZXRcclxuICogQHJldHVybnMge3VuZGVmaW5lZH1cclxuICovXHJcblxyXG4vKipcclxuICogV3JpdGVzIGEgMzIgYml0IGZsb2F0IHRvIGEgYnVmZmVyIHVzaW5nIGJpZyBlbmRpYW4gYnl0ZSBvcmRlci5cclxuICogQG5hbWUgdXRpbC5mbG9hdC53cml0ZUZsb2F0QkVcclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWwgVmFsdWUgdG8gd3JpdGVcclxuICogQHBhcmFtIHtVaW50OEFycmF5fSBidWYgVGFyZ2V0IGJ1ZmZlclxyXG4gKiBAcGFyYW0ge251bWJlcn0gcG9zIFRhcmdldCBidWZmZXIgb2Zmc2V0XHJcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIFJlYWRzIGEgMzIgYml0IGZsb2F0IGZyb20gYSBidWZmZXIgdXNpbmcgbGl0dGxlIGVuZGlhbiBieXRlIG9yZGVyLlxyXG4gKiBAbmFtZSB1dGlsLmZsb2F0LnJlYWRGbG9hdExFXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGJ1ZiBTb3VyY2UgYnVmZmVyXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBwb3MgU291cmNlIGJ1ZmZlciBvZmZzZXRcclxuICogQHJldHVybnMge251bWJlcn0gVmFsdWUgcmVhZFxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBSZWFkcyBhIDMyIGJpdCBmbG9hdCBmcm9tIGEgYnVmZmVyIHVzaW5nIGJpZyBlbmRpYW4gYnl0ZSBvcmRlci5cclxuICogQG5hbWUgdXRpbC5mbG9hdC5yZWFkRmxvYXRCRVxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHtVaW50OEFycmF5fSBidWYgU291cmNlIGJ1ZmZlclxyXG4gKiBAcGFyYW0ge251bWJlcn0gcG9zIFNvdXJjZSBidWZmZXIgb2Zmc2V0XHJcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcclxuICovXHJcblxyXG4vKipcclxuICogV3JpdGVzIGEgNjQgYml0IGRvdWJsZSB0byBhIGJ1ZmZlciB1c2luZyBsaXR0bGUgZW5kaWFuIGJ5dGUgb3JkZXIuXHJcbiAqIEBuYW1lIHV0aWwuZmxvYXQud3JpdGVEb3VibGVMRVxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHtudW1iZXJ9IHZhbCBWYWx1ZSB0byB3cml0ZVxyXG4gKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGJ1ZiBUYXJnZXQgYnVmZmVyXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBwb3MgVGFyZ2V0IGJ1ZmZlciBvZmZzZXRcclxuICogQHJldHVybnMge3VuZGVmaW5lZH1cclxuICovXHJcblxyXG4vKipcclxuICogV3JpdGVzIGEgNjQgYml0IGRvdWJsZSB0byBhIGJ1ZmZlciB1c2luZyBiaWcgZW5kaWFuIGJ5dGUgb3JkZXIuXHJcbiAqIEBuYW1lIHV0aWwuZmxvYXQud3JpdGVEb3VibGVCRVxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHtudW1iZXJ9IHZhbCBWYWx1ZSB0byB3cml0ZVxyXG4gKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGJ1ZiBUYXJnZXQgYnVmZmVyXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBwb3MgVGFyZ2V0IGJ1ZmZlciBvZmZzZXRcclxuICogQHJldHVybnMge3VuZGVmaW5lZH1cclxuICovXHJcblxyXG4vKipcclxuICogUmVhZHMgYSA2NCBiaXQgZG91YmxlIGZyb20gYSBidWZmZXIgdXNpbmcgbGl0dGxlIGVuZGlhbiBieXRlIG9yZGVyLlxyXG4gKiBAbmFtZSB1dGlsLmZsb2F0LnJlYWREb3VibGVMRVxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHtVaW50OEFycmF5fSBidWYgU291cmNlIGJ1ZmZlclxyXG4gKiBAcGFyYW0ge251bWJlcn0gcG9zIFNvdXJjZSBidWZmZXIgb2Zmc2V0XHJcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcclxuICovXHJcblxyXG4vKipcclxuICogUmVhZHMgYSA2NCBiaXQgZG91YmxlIGZyb20gYSBidWZmZXIgdXNpbmcgYmlnIGVuZGlhbiBieXRlIG9yZGVyLlxyXG4gKiBAbmFtZSB1dGlsLmZsb2F0LnJlYWREb3VibGVCRVxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHtVaW50OEFycmF5fSBidWYgU291cmNlIGJ1ZmZlclxyXG4gKiBAcGFyYW0ge251bWJlcn0gcG9zIFNvdXJjZSBidWZmZXIgb2Zmc2V0XHJcbiAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcclxuICovXHJcblxyXG4vLyBGYWN0b3J5IGZ1bmN0aW9uIGZvciB0aGUgcHVycG9zZSBvZiBub2RlLWJhc2VkIHRlc3RpbmcgaW4gbW9kaWZpZWQgZ2xvYmFsIGVudmlyb25tZW50c1xyXG5mdW5jdGlvbiBmYWN0b3J5KGV4cG9ydHMpIHtcclxuXHJcbiAgICAvLyBmbG9hdDogdHlwZWQgYXJyYXlcclxuICAgIGlmICh0eXBlb2YgRmxvYXQzMkFycmF5ICE9PSBcInVuZGVmaW5lZFwiKSAoZnVuY3Rpb24oKSB7XHJcblxyXG4gICAgICAgIHZhciBmMzIgPSBuZXcgRmxvYXQzMkFycmF5KFsgLTAgXSksXHJcbiAgICAgICAgICAgIGY4YiA9IG5ldyBVaW50OEFycmF5KGYzMi5idWZmZXIpLFxyXG4gICAgICAgICAgICBsZSAgPSBmOGJbM10gPT09IDEyODtcclxuXHJcbiAgICAgICAgZnVuY3Rpb24gd3JpdGVGbG9hdF9mMzJfY3B5KHZhbCwgYnVmLCBwb3MpIHtcclxuICAgICAgICAgICAgZjMyWzBdID0gdmFsO1xyXG4gICAgICAgICAgICBidWZbcG9zICAgIF0gPSBmOGJbMF07XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgKyAxXSA9IGY4YlsxXTtcclxuICAgICAgICAgICAgYnVmW3BvcyArIDJdID0gZjhiWzJdO1xyXG4gICAgICAgICAgICBidWZbcG9zICsgM10gPSBmOGJbM107XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmdW5jdGlvbiB3cml0ZUZsb2F0X2YzMl9yZXYodmFsLCBidWYsIHBvcykge1xyXG4gICAgICAgICAgICBmMzJbMF0gPSB2YWw7XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgICAgXSA9IGY4YlszXTtcclxuICAgICAgICAgICAgYnVmW3BvcyArIDFdID0gZjhiWzJdO1xyXG4gICAgICAgICAgICBidWZbcG9zICsgMl0gPSBmOGJbMV07XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgKyAzXSA9IGY4YlswXTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXHJcbiAgICAgICAgZXhwb3J0cy53cml0ZUZsb2F0TEUgPSBsZSA/IHdyaXRlRmxvYXRfZjMyX2NweSA6IHdyaXRlRmxvYXRfZjMyX3JldjtcclxuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xyXG4gICAgICAgIGV4cG9ydHMud3JpdGVGbG9hdEJFID0gbGUgPyB3cml0ZUZsb2F0X2YzMl9yZXYgOiB3cml0ZUZsb2F0X2YzMl9jcHk7XHJcblxyXG4gICAgICAgIGZ1bmN0aW9uIHJlYWRGbG9hdF9mMzJfY3B5KGJ1ZiwgcG9zKSB7XHJcbiAgICAgICAgICAgIGY4YlswXSA9IGJ1Zltwb3MgICAgXTtcclxuICAgICAgICAgICAgZjhiWzFdID0gYnVmW3BvcyArIDFdO1xyXG4gICAgICAgICAgICBmOGJbMl0gPSBidWZbcG9zICsgMl07XHJcbiAgICAgICAgICAgIGY4YlszXSA9IGJ1Zltwb3MgKyAzXTtcclxuICAgICAgICAgICAgcmV0dXJuIGYzMlswXTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZ1bmN0aW9uIHJlYWRGbG9hdF9mMzJfcmV2KGJ1ZiwgcG9zKSB7XHJcbiAgICAgICAgICAgIGY4YlszXSA9IGJ1Zltwb3MgICAgXTtcclxuICAgICAgICAgICAgZjhiWzJdID0gYnVmW3BvcyArIDFdO1xyXG4gICAgICAgICAgICBmOGJbMV0gPSBidWZbcG9zICsgMl07XHJcbiAgICAgICAgICAgIGY4YlswXSA9IGJ1Zltwb3MgKyAzXTtcclxuICAgICAgICAgICAgcmV0dXJuIGYzMlswXTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXHJcbiAgICAgICAgZXhwb3J0cy5yZWFkRmxvYXRMRSA9IGxlID8gcmVhZEZsb2F0X2YzMl9jcHkgOiByZWFkRmxvYXRfZjMyX3JldjtcclxuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xyXG4gICAgICAgIGV4cG9ydHMucmVhZEZsb2F0QkUgPSBsZSA/IHJlYWRGbG9hdF9mMzJfcmV2IDogcmVhZEZsb2F0X2YzMl9jcHk7XHJcblxyXG4gICAgLy8gZmxvYXQ6IGllZWU3NTRcclxuICAgIH0pKCk7IGVsc2UgKGZ1bmN0aW9uKCkge1xyXG5cclxuICAgICAgICBmdW5jdGlvbiB3cml0ZUZsb2F0X2llZWU3NTQod3JpdGVVaW50LCB2YWwsIGJ1ZiwgcG9zKSB7XHJcbiAgICAgICAgICAgIHZhciBzaWduID0gdmFsIDwgMCA/IDEgOiAwO1xyXG4gICAgICAgICAgICBpZiAoc2lnbilcclxuICAgICAgICAgICAgICAgIHZhbCA9IC12YWw7XHJcbiAgICAgICAgICAgIGlmICh2YWwgPT09IDApXHJcbiAgICAgICAgICAgICAgICB3cml0ZVVpbnQoMSAvIHZhbCA+IDAgPyAvKiBwb3NpdGl2ZSAqLyAwIDogLyogbmVnYXRpdmUgMCAqLyAyMTQ3NDgzNjQ4LCBidWYsIHBvcyk7XHJcbiAgICAgICAgICAgIGVsc2UgaWYgKGlzTmFOKHZhbCkpXHJcbiAgICAgICAgICAgICAgICB3cml0ZVVpbnQoMjE0MzI4OTM0NCwgYnVmLCBwb3MpO1xyXG4gICAgICAgICAgICBlbHNlIGlmICh2YWwgPiAzLjQwMjgyMzQ2NjM4NTI4ODZlKzM4KSAvLyArLUluZmluaXR5XHJcbiAgICAgICAgICAgICAgICB3cml0ZVVpbnQoKHNpZ24gPDwgMzEgfCAyMTM5MDk1MDQwKSA+Pj4gMCwgYnVmLCBwb3MpO1xyXG4gICAgICAgICAgICBlbHNlIGlmICh2YWwgPCAxLjE3NTQ5NDM1MDgyMjI4NzVlLTM4KSAvLyBkZW5vcm1hbFxyXG4gICAgICAgICAgICAgICAgd3JpdGVVaW50KChzaWduIDw8IDMxIHwgTWF0aC5yb3VuZCh2YWwgLyAxLjQwMTI5ODQ2NDMyNDgxN2UtNDUpKSA+Pj4gMCwgYnVmLCBwb3MpO1xyXG4gICAgICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHZhciBleHBvbmVudCA9IE1hdGguZmxvb3IoTWF0aC5sb2codmFsKSAvIE1hdGguTE4yKSxcclxuICAgICAgICAgICAgICAgICAgICBtYW50aXNzYSA9IE1hdGgucm91bmQodmFsICogTWF0aC5wb3coMiwgLWV4cG9uZW50KSAqIDgzODg2MDgpICYgODM4ODYwNztcclxuICAgICAgICAgICAgICAgIHdyaXRlVWludCgoc2lnbiA8PCAzMSB8IGV4cG9uZW50ICsgMTI3IDw8IDIzIHwgbWFudGlzc2EpID4+PiAwLCBidWYsIHBvcyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGV4cG9ydHMud3JpdGVGbG9hdExFID0gd3JpdGVGbG9hdF9pZWVlNzU0LmJpbmQobnVsbCwgd3JpdGVVaW50TEUpO1xyXG4gICAgICAgIGV4cG9ydHMud3JpdGVGbG9hdEJFID0gd3JpdGVGbG9hdF9pZWVlNzU0LmJpbmQobnVsbCwgd3JpdGVVaW50QkUpO1xyXG5cclxuICAgICAgICBmdW5jdGlvbiByZWFkRmxvYXRfaWVlZTc1NChyZWFkVWludCwgYnVmLCBwb3MpIHtcclxuICAgICAgICAgICAgdmFyIHVpbnQgPSByZWFkVWludChidWYsIHBvcyksXHJcbiAgICAgICAgICAgICAgICBzaWduID0gKHVpbnQgPj4gMzEpICogMiArIDEsXHJcbiAgICAgICAgICAgICAgICBleHBvbmVudCA9IHVpbnQgPj4+IDIzICYgMjU1LFxyXG4gICAgICAgICAgICAgICAgbWFudGlzc2EgPSB1aW50ICYgODM4ODYwNztcclxuICAgICAgICAgICAgcmV0dXJuIGV4cG9uZW50ID09PSAyNTVcclxuICAgICAgICAgICAgICAgID8gbWFudGlzc2FcclxuICAgICAgICAgICAgICAgID8gTmFOXHJcbiAgICAgICAgICAgICAgICA6IHNpZ24gKiBJbmZpbml0eVxyXG4gICAgICAgICAgICAgICAgOiBleHBvbmVudCA9PT0gMCAvLyBkZW5vcm1hbFxyXG4gICAgICAgICAgICAgICAgPyBzaWduICogMS40MDEyOTg0NjQzMjQ4MTdlLTQ1ICogbWFudGlzc2FcclxuICAgICAgICAgICAgICAgIDogc2lnbiAqIE1hdGgucG93KDIsIGV4cG9uZW50IC0gMTUwKSAqIChtYW50aXNzYSArIDgzODg2MDgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZXhwb3J0cy5yZWFkRmxvYXRMRSA9IHJlYWRGbG9hdF9pZWVlNzU0LmJpbmQobnVsbCwgcmVhZFVpbnRMRSk7XHJcbiAgICAgICAgZXhwb3J0cy5yZWFkRmxvYXRCRSA9IHJlYWRGbG9hdF9pZWVlNzU0LmJpbmQobnVsbCwgcmVhZFVpbnRCRSk7XHJcblxyXG4gICAgfSkoKTtcclxuXHJcbiAgICAvLyBkb3VibGU6IHR5cGVkIGFycmF5XHJcbiAgICBpZiAodHlwZW9mIEZsb2F0NjRBcnJheSAhPT0gXCJ1bmRlZmluZWRcIikgKGZ1bmN0aW9uKCkge1xyXG5cclxuICAgICAgICB2YXIgZjY0ID0gbmV3IEZsb2F0NjRBcnJheShbLTBdKSxcclxuICAgICAgICAgICAgZjhiID0gbmV3IFVpbnQ4QXJyYXkoZjY0LmJ1ZmZlciksXHJcbiAgICAgICAgICAgIGxlICA9IGY4Yls3XSA9PT0gMTI4O1xyXG5cclxuICAgICAgICBmdW5jdGlvbiB3cml0ZURvdWJsZV9mNjRfY3B5KHZhbCwgYnVmLCBwb3MpIHtcclxuICAgICAgICAgICAgZjY0WzBdID0gdmFsO1xyXG4gICAgICAgICAgICBidWZbcG9zICAgIF0gPSBmOGJbMF07XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgKyAxXSA9IGY4YlsxXTtcclxuICAgICAgICAgICAgYnVmW3BvcyArIDJdID0gZjhiWzJdO1xyXG4gICAgICAgICAgICBidWZbcG9zICsgM10gPSBmOGJbM107XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgKyA0XSA9IGY4Yls0XTtcclxuICAgICAgICAgICAgYnVmW3BvcyArIDVdID0gZjhiWzVdO1xyXG4gICAgICAgICAgICBidWZbcG9zICsgNl0gPSBmOGJbNl07XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgKyA3XSA9IGY4Yls3XTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZ1bmN0aW9uIHdyaXRlRG91YmxlX2Y2NF9yZXYodmFsLCBidWYsIHBvcykge1xyXG4gICAgICAgICAgICBmNjRbMF0gPSB2YWw7XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgICAgXSA9IGY4Yls3XTtcclxuICAgICAgICAgICAgYnVmW3BvcyArIDFdID0gZjhiWzZdO1xyXG4gICAgICAgICAgICBidWZbcG9zICsgMl0gPSBmOGJbNV07XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgKyAzXSA9IGY4Yls0XTtcclxuICAgICAgICAgICAgYnVmW3BvcyArIDRdID0gZjhiWzNdO1xyXG4gICAgICAgICAgICBidWZbcG9zICsgNV0gPSBmOGJbMl07XHJcbiAgICAgICAgICAgIGJ1Zltwb3MgKyA2XSA9IGY4YlsxXTtcclxuICAgICAgICAgICAgYnVmW3BvcyArIDddID0gZjhiWzBdO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cclxuICAgICAgICBleHBvcnRzLndyaXRlRG91YmxlTEUgPSBsZSA/IHdyaXRlRG91YmxlX2Y2NF9jcHkgOiB3cml0ZURvdWJsZV9mNjRfcmV2O1xyXG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXHJcbiAgICAgICAgZXhwb3J0cy53cml0ZURvdWJsZUJFID0gbGUgPyB3cml0ZURvdWJsZV9mNjRfcmV2IDogd3JpdGVEb3VibGVfZjY0X2NweTtcclxuXHJcbiAgICAgICAgZnVuY3Rpb24gcmVhZERvdWJsZV9mNjRfY3B5KGJ1ZiwgcG9zKSB7XHJcbiAgICAgICAgICAgIGY4YlswXSA9IGJ1Zltwb3MgICAgXTtcclxuICAgICAgICAgICAgZjhiWzFdID0gYnVmW3BvcyArIDFdO1xyXG4gICAgICAgICAgICBmOGJbMl0gPSBidWZbcG9zICsgMl07XHJcbiAgICAgICAgICAgIGY4YlszXSA9IGJ1Zltwb3MgKyAzXTtcclxuICAgICAgICAgICAgZjhiWzRdID0gYnVmW3BvcyArIDRdO1xyXG4gICAgICAgICAgICBmOGJbNV0gPSBidWZbcG9zICsgNV07XHJcbiAgICAgICAgICAgIGY4Yls2XSA9IGJ1Zltwb3MgKyA2XTtcclxuICAgICAgICAgICAgZjhiWzddID0gYnVmW3BvcyArIDddO1xyXG4gICAgICAgICAgICByZXR1cm4gZjY0WzBdO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZnVuY3Rpb24gcmVhZERvdWJsZV9mNjRfcmV2KGJ1ZiwgcG9zKSB7XHJcbiAgICAgICAgICAgIGY4Yls3XSA9IGJ1Zltwb3MgICAgXTtcclxuICAgICAgICAgICAgZjhiWzZdID0gYnVmW3BvcyArIDFdO1xyXG4gICAgICAgICAgICBmOGJbNV0gPSBidWZbcG9zICsgMl07XHJcbiAgICAgICAgICAgIGY4Yls0XSA9IGJ1Zltwb3MgKyAzXTtcclxuICAgICAgICAgICAgZjhiWzNdID0gYnVmW3BvcyArIDRdO1xyXG4gICAgICAgICAgICBmOGJbMl0gPSBidWZbcG9zICsgNV07XHJcbiAgICAgICAgICAgIGY4YlsxXSA9IGJ1Zltwb3MgKyA2XTtcclxuICAgICAgICAgICAgZjhiWzBdID0gYnVmW3BvcyArIDddO1xyXG4gICAgICAgICAgICByZXR1cm4gZjY0WzBdO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cclxuICAgICAgICBleHBvcnRzLnJlYWREb3VibGVMRSA9IGxlID8gcmVhZERvdWJsZV9mNjRfY3B5IDogcmVhZERvdWJsZV9mNjRfcmV2O1xyXG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXHJcbiAgICAgICAgZXhwb3J0cy5yZWFkRG91YmxlQkUgPSBsZSA/IHJlYWREb3VibGVfZjY0X3JldiA6IHJlYWREb3VibGVfZjY0X2NweTtcclxuXHJcbiAgICAvLyBkb3VibGU6IGllZWU3NTRcclxuICAgIH0pKCk7IGVsc2UgKGZ1bmN0aW9uKCkge1xyXG5cclxuICAgICAgICBmdW5jdGlvbiB3cml0ZURvdWJsZV9pZWVlNzU0KHdyaXRlVWludCwgb2ZmMCwgb2ZmMSwgdmFsLCBidWYsIHBvcykge1xyXG4gICAgICAgICAgICB2YXIgc2lnbiA9IHZhbCA8IDAgPyAxIDogMDtcclxuICAgICAgICAgICAgaWYgKHNpZ24pXHJcbiAgICAgICAgICAgICAgICB2YWwgPSAtdmFsO1xyXG4gICAgICAgICAgICBpZiAodmFsID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICB3cml0ZVVpbnQoMCwgYnVmLCBwb3MgKyBvZmYwKTtcclxuICAgICAgICAgICAgICAgIHdyaXRlVWludCgxIC8gdmFsID4gMCA/IC8qIHBvc2l0aXZlICovIDAgOiAvKiBuZWdhdGl2ZSAwICovIDIxNDc0ODM2NDgsIGJ1ZiwgcG9zICsgb2ZmMSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNOYU4odmFsKSkge1xyXG4gICAgICAgICAgICAgICAgd3JpdGVVaW50KDAsIGJ1ZiwgcG9zICsgb2ZmMCk7XHJcbiAgICAgICAgICAgICAgICB3cml0ZVVpbnQoMjE0Njk1OTM2MCwgYnVmLCBwb3MgKyBvZmYxKTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmICh2YWwgPiAxLjc5NzY5MzEzNDg2MjMxNTdlKzMwOCkgeyAvLyArLUluZmluaXR5XHJcbiAgICAgICAgICAgICAgICB3cml0ZVVpbnQoMCwgYnVmLCBwb3MgKyBvZmYwKTtcclxuICAgICAgICAgICAgICAgIHdyaXRlVWludCgoc2lnbiA8PCAzMSB8IDIxNDY0MzUwNzIpID4+PiAwLCBidWYsIHBvcyArIG9mZjEpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdmFyIG1hbnRpc3NhO1xyXG4gICAgICAgICAgICAgICAgaWYgKHZhbCA8IDIuMjI1MDczODU4NTA3MjAxNGUtMzA4KSB7IC8vIGRlbm9ybWFsXHJcbiAgICAgICAgICAgICAgICAgICAgbWFudGlzc2EgPSB2YWwgLyA1ZS0zMjQ7XHJcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVVaW50KG1hbnRpc3NhID4+PiAwLCBidWYsIHBvcyArIG9mZjApO1xyXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlVWludCgoc2lnbiA8PCAzMSB8IG1hbnRpc3NhIC8gNDI5NDk2NzI5NikgPj4+IDAsIGJ1ZiwgcG9zICsgb2ZmMSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBleHBvbmVudCA9IE1hdGguZmxvb3IoTWF0aC5sb2codmFsKSAvIE1hdGguTE4yKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoZXhwb25lbnQgPT09IDEwMjQpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cG9uZW50ID0gMTAyMztcclxuICAgICAgICAgICAgICAgICAgICBtYW50aXNzYSA9IHZhbCAqIE1hdGgucG93KDIsIC1leHBvbmVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVVaW50KG1hbnRpc3NhICogNDUwMzU5OTYyNzM3MDQ5NiA+Pj4gMCwgYnVmLCBwb3MgKyBvZmYwKTtcclxuICAgICAgICAgICAgICAgICAgICB3cml0ZVVpbnQoKHNpZ24gPDwgMzEgfCBleHBvbmVudCArIDEwMjMgPDwgMjAgfCBtYW50aXNzYSAqIDEwNDg1NzYgJiAxMDQ4NTc1KSA+Pj4gMCwgYnVmLCBwb3MgKyBvZmYxKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZXhwb3J0cy53cml0ZURvdWJsZUxFID0gd3JpdGVEb3VibGVfaWVlZTc1NC5iaW5kKG51bGwsIHdyaXRlVWludExFLCAwLCA0KTtcclxuICAgICAgICBleHBvcnRzLndyaXRlRG91YmxlQkUgPSB3cml0ZURvdWJsZV9pZWVlNzU0LmJpbmQobnVsbCwgd3JpdGVVaW50QkUsIDQsIDApO1xyXG5cclxuICAgICAgICBmdW5jdGlvbiByZWFkRG91YmxlX2llZWU3NTQocmVhZFVpbnQsIG9mZjAsIG9mZjEsIGJ1ZiwgcG9zKSB7XHJcbiAgICAgICAgICAgIHZhciBsbyA9IHJlYWRVaW50KGJ1ZiwgcG9zICsgb2ZmMCksXHJcbiAgICAgICAgICAgICAgICBoaSA9IHJlYWRVaW50KGJ1ZiwgcG9zICsgb2ZmMSk7XHJcbiAgICAgICAgICAgIHZhciBzaWduID0gKGhpID4+IDMxKSAqIDIgKyAxLFxyXG4gICAgICAgICAgICAgICAgZXhwb25lbnQgPSBoaSA+Pj4gMjAgJiAyMDQ3LFxyXG4gICAgICAgICAgICAgICAgbWFudGlzc2EgPSA0Mjk0OTY3Mjk2ICogKGhpICYgMTA0ODU3NSkgKyBsbztcclxuICAgICAgICAgICAgcmV0dXJuIGV4cG9uZW50ID09PSAyMDQ3XHJcbiAgICAgICAgICAgICAgICA/IG1hbnRpc3NhXHJcbiAgICAgICAgICAgICAgICA/IE5hTlxyXG4gICAgICAgICAgICAgICAgOiBzaWduICogSW5maW5pdHlcclxuICAgICAgICAgICAgICAgIDogZXhwb25lbnQgPT09IDAgLy8gZGVub3JtYWxcclxuICAgICAgICAgICAgICAgID8gc2lnbiAqIDVlLTMyNCAqIG1hbnRpc3NhXHJcbiAgICAgICAgICAgICAgICA6IHNpZ24gKiBNYXRoLnBvdygyLCBleHBvbmVudCAtIDEwNzUpICogKG1hbnRpc3NhICsgNDUwMzU5OTYyNzM3MDQ5Nik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBleHBvcnRzLnJlYWREb3VibGVMRSA9IHJlYWREb3VibGVfaWVlZTc1NC5iaW5kKG51bGwsIHJlYWRVaW50TEUsIDAsIDQpO1xyXG4gICAgICAgIGV4cG9ydHMucmVhZERvdWJsZUJFID0gcmVhZERvdWJsZV9pZWVlNzU0LmJpbmQobnVsbCwgcmVhZFVpbnRCRSwgNCwgMCk7XHJcblxyXG4gICAgfSkoKTtcclxuXHJcbiAgICByZXR1cm4gZXhwb3J0cztcclxufVxyXG5cclxuLy8gdWludCBoZWxwZXJzXHJcblxyXG5mdW5jdGlvbiB3cml0ZVVpbnRMRSh2YWwsIGJ1ZiwgcG9zKSB7XHJcbiAgICBidWZbcG9zICAgIF0gPSAgdmFsICAgICAgICAmIDI1NTtcclxuICAgIGJ1Zltwb3MgKyAxXSA9ICB2YWwgPj4+IDggICYgMjU1O1xyXG4gICAgYnVmW3BvcyArIDJdID0gIHZhbCA+Pj4gMTYgJiAyNTU7XHJcbiAgICBidWZbcG9zICsgM10gPSAgdmFsID4+PiAyNDtcclxufVxyXG5cclxuZnVuY3Rpb24gd3JpdGVVaW50QkUodmFsLCBidWYsIHBvcykge1xyXG4gICAgYnVmW3BvcyAgICBdID0gIHZhbCA+Pj4gMjQ7XHJcbiAgICBidWZbcG9zICsgMV0gPSAgdmFsID4+PiAxNiAmIDI1NTtcclxuICAgIGJ1Zltwb3MgKyAyXSA9ICB2YWwgPj4+IDggICYgMjU1O1xyXG4gICAgYnVmW3BvcyArIDNdID0gIHZhbCAgICAgICAgJiAyNTU7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHJlYWRVaW50TEUoYnVmLCBwb3MpIHtcclxuICAgIHJldHVybiAoYnVmW3BvcyAgICBdXHJcbiAgICAgICAgICB8IGJ1Zltwb3MgKyAxXSA8PCA4XHJcbiAgICAgICAgICB8IGJ1Zltwb3MgKyAyXSA8PCAxNlxyXG4gICAgICAgICAgfCBidWZbcG9zICsgM10gPDwgMjQpID4+PiAwO1xyXG59XHJcblxyXG5mdW5jdGlvbiByZWFkVWludEJFKGJ1ZiwgcG9zKSB7XHJcbiAgICByZXR1cm4gKGJ1Zltwb3MgICAgXSA8PCAyNFxyXG4gICAgICAgICAgfCBidWZbcG9zICsgMV0gPDwgMTZcclxuICAgICAgICAgIHwgYnVmW3BvcyArIDJdIDw8IDhcclxuICAgICAgICAgIHwgYnVmW3BvcyArIDNdKSA+Pj4gMDtcclxufVxyXG4iLCJcInVzZSBzdHJpY3RcIjtcclxubW9kdWxlLmV4cG9ydHMgPSBpbnF1aXJlO1xyXG5cclxuLyoqXHJcbiAqIFJlcXVpcmVzIGEgbW9kdWxlIG9ubHkgaWYgYXZhaWxhYmxlLlxyXG4gKiBAbWVtYmVyb2YgdXRpbFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbW9kdWxlTmFtZSBNb2R1bGUgdG8gcmVxdWlyZVxyXG4gKiBAcmV0dXJucyB7P09iamVjdH0gUmVxdWlyZWQgbW9kdWxlIGlmIGF2YWlsYWJsZSBhbmQgbm90IGVtcHR5LCBvdGhlcndpc2UgYG51bGxgXHJcbiAqL1xyXG5mdW5jdGlvbiBpbnF1aXJlKG1vZHVsZU5hbWUpIHtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgdmFyIG1vZCA9IGV2YWwoXCJxdWlyZVwiLnJlcGxhY2UoL14vLFwicmVcIikpKG1vZHVsZU5hbWUpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLWV2YWxcclxuICAgICAgICBpZiAobW9kICYmIChtb2QubGVuZ3RoIHx8IE9iamVjdC5rZXlzKG1vZCkubGVuZ3RoKSlcclxuICAgICAgICAgICAgcmV0dXJuIG1vZDtcclxuICAgIH0gY2F0Y2ggKGUpIHt9IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tZW1wdHlcclxuICAgIHJldHVybiBudWxsO1xyXG59XHJcbiIsIlwidXNlIHN0cmljdFwiO1xyXG5tb2R1bGUuZXhwb3J0cyA9IHBvb2w7XHJcblxyXG4vKipcclxuICogQW4gYWxsb2NhdG9yIGFzIHVzZWQgYnkge0BsaW5rIHV0aWwucG9vbH0uXHJcbiAqIEB0eXBlZGVmIFBvb2xBbGxvY2F0b3JcclxuICogQHR5cGUge2Z1bmN0aW9ufVxyXG4gKiBAcGFyYW0ge251bWJlcn0gc2l6ZSBCdWZmZXIgc2l6ZVxyXG4gKiBAcmV0dXJucyB7VWludDhBcnJheX0gQnVmZmVyXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIEEgc2xpY2VyIGFzIHVzZWQgYnkge0BsaW5rIHV0aWwucG9vbH0uXHJcbiAqIEB0eXBlZGVmIFBvb2xTbGljZXJcclxuICogQHR5cGUge2Z1bmN0aW9ufVxyXG4gKiBAcGFyYW0ge251bWJlcn0gc3RhcnQgU3RhcnQgb2Zmc2V0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgRW5kIG9mZnNldFxyXG4gKiBAcmV0dXJucyB7VWludDhBcnJheX0gQnVmZmVyIHNsaWNlXHJcbiAqIEB0aGlzIHtVaW50OEFycmF5fVxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBBIGdlbmVyYWwgcHVycG9zZSBidWZmZXIgcG9vbC5cclxuICogQG1lbWJlcm9mIHV0aWxcclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7UG9vbEFsbG9jYXRvcn0gYWxsb2MgQWxsb2NhdG9yXHJcbiAqIEBwYXJhbSB7UG9vbFNsaWNlcn0gc2xpY2UgU2xpY2VyXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBbc2l6ZT04MTkyXSBTbGFiIHNpemVcclxuICogQHJldHVybnMge1Bvb2xBbGxvY2F0b3J9IFBvb2xlZCBhbGxvY2F0b3JcclxuICovXHJcbmZ1bmN0aW9uIHBvb2woYWxsb2MsIHNsaWNlLCBzaXplKSB7XHJcbiAgICB2YXIgU0laRSAgID0gc2l6ZSB8fCA4MTkyO1xyXG4gICAgdmFyIE1BWCAgICA9IFNJWkUgPj4+IDE7XHJcbiAgICB2YXIgc2xhYiAgID0gbnVsbDtcclxuICAgIHZhciBvZmZzZXQgPSBTSVpFO1xyXG4gICAgcmV0dXJuIGZ1bmN0aW9uIHBvb2xfYWxsb2Moc2l6ZSkge1xyXG4gICAgICAgIGlmIChzaXplIDwgMSB8fCBzaXplID4gTUFYKVxyXG4gICAgICAgICAgICByZXR1cm4gYWxsb2Moc2l6ZSk7XHJcbiAgICAgICAgaWYgKG9mZnNldCArIHNpemUgPiBTSVpFKSB7XHJcbiAgICAgICAgICAgIHNsYWIgPSBhbGxvYyhTSVpFKTtcclxuICAgICAgICAgICAgb2Zmc2V0ID0gMDtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIGJ1ZiA9IHNsaWNlLmNhbGwoc2xhYiwgb2Zmc2V0LCBvZmZzZXQgKz0gc2l6ZSk7XHJcbiAgICAgICAgaWYgKG9mZnNldCAmIDcpIC8vIGFsaWduIHRvIDMyIGJpdFxyXG4gICAgICAgICAgICBvZmZzZXQgPSAob2Zmc2V0IHwgNykgKyAxO1xyXG4gICAgICAgIHJldHVybiBidWY7XHJcbiAgICB9O1xyXG59XHJcbiIsIlwidXNlIHN0cmljdFwiO1xyXG5cclxuLyoqXHJcbiAqIEEgbWluaW1hbCBVVEY4IGltcGxlbWVudGF0aW9uIGZvciBudW1iZXIgYXJyYXlzLlxyXG4gKiBAbWVtYmVyb2YgdXRpbFxyXG4gKiBAbmFtZXNwYWNlXHJcbiAqL1xyXG52YXIgdXRmOCA9IGV4cG9ydHM7XHJcblxyXG4vKipcclxuICogQ2FsY3VsYXRlcyB0aGUgVVRGOCBieXRlIGxlbmd0aCBvZiBhIHN0cmluZy5cclxuICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBTdHJpbmdcclxuICogQHJldHVybnMge251bWJlcn0gQnl0ZSBsZW5ndGhcclxuICovXHJcbnV0ZjgubGVuZ3RoID0gZnVuY3Rpb24gdXRmOF9sZW5ndGgoc3RyaW5nKSB7XHJcbiAgICB2YXIgbGVuID0gMCxcclxuICAgICAgICBjID0gMDtcclxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgKytpKSB7XHJcbiAgICAgICAgYyA9IHN0cmluZy5jaGFyQ29kZUF0KGkpO1xyXG4gICAgICAgIGlmIChjIDwgMTI4KVxyXG4gICAgICAgICAgICBsZW4gKz0gMTtcclxuICAgICAgICBlbHNlIGlmIChjIDwgMjA0OClcclxuICAgICAgICAgICAgbGVuICs9IDI7XHJcbiAgICAgICAgZWxzZSBpZiAoKGMgJiAweEZDMDApID09PSAweEQ4MDAgJiYgKHN0cmluZy5jaGFyQ29kZUF0KGkgKyAxKSAmIDB4RkMwMCkgPT09IDB4REMwMCkge1xyXG4gICAgICAgICAgICArK2k7XHJcbiAgICAgICAgICAgIGxlbiArPSA0O1xyXG4gICAgICAgIH0gZWxzZVxyXG4gICAgICAgICAgICBsZW4gKz0gMztcclxuICAgIH1cclxuICAgIHJldHVybiBsZW47XHJcbn07XHJcblxyXG4vKipcclxuICogUmVhZHMgVVRGOCBieXRlcyBhcyBhIHN0cmluZy5cclxuICogQHBhcmFtIHtVaW50OEFycmF5fSBidWZmZXIgU291cmNlIGJ1ZmZlclxyXG4gKiBAcGFyYW0ge251bWJlcn0gc3RhcnQgU291cmNlIHN0YXJ0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBlbmQgU291cmNlIGVuZFxyXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBTdHJpbmcgcmVhZFxyXG4gKi9cclxudXRmOC5yZWFkID0gZnVuY3Rpb24gdXRmOF9yZWFkKGJ1ZmZlciwgc3RhcnQsIGVuZCkge1xyXG4gICAgdmFyIGxlbiA9IGVuZCAtIHN0YXJ0O1xyXG4gICAgaWYgKGxlbiA8IDEpXHJcbiAgICAgICAgcmV0dXJuIFwiXCI7XHJcbiAgICB2YXIgcGFydHMgPSBudWxsLFxyXG4gICAgICAgIGNodW5rID0gW10sXHJcbiAgICAgICAgaSA9IDAsIC8vIGNoYXIgb2Zmc2V0XHJcbiAgICAgICAgdDsgICAgIC8vIHRlbXBvcmFyeVxyXG4gICAgd2hpbGUgKHN0YXJ0IDwgZW5kKSB7XHJcbiAgICAgICAgdCA9IGJ1ZmZlcltzdGFydCsrXTtcclxuICAgICAgICBpZiAodCA8IDEyOClcclxuICAgICAgICAgICAgY2h1bmtbaSsrXSA9IHQ7XHJcbiAgICAgICAgZWxzZSBpZiAodCA+IDE5MSAmJiB0IDwgMjI0KVxyXG4gICAgICAgICAgICBjaHVua1tpKytdID0gKHQgJiAzMSkgPDwgNiB8IGJ1ZmZlcltzdGFydCsrXSAmIDYzO1xyXG4gICAgICAgIGVsc2UgaWYgKHQgPiAyMzkgJiYgdCA8IDM2NSkge1xyXG4gICAgICAgICAgICB0ID0gKCh0ICYgNykgPDwgMTggfCAoYnVmZmVyW3N0YXJ0KytdICYgNjMpIDw8IDEyIHwgKGJ1ZmZlcltzdGFydCsrXSAmIDYzKSA8PCA2IHwgYnVmZmVyW3N0YXJ0KytdICYgNjMpIC0gMHgxMDAwMDtcclxuICAgICAgICAgICAgY2h1bmtbaSsrXSA9IDB4RDgwMCArICh0ID4+IDEwKTtcclxuICAgICAgICAgICAgY2h1bmtbaSsrXSA9IDB4REMwMCArICh0ICYgMTAyMyk7XHJcbiAgICAgICAgfSBlbHNlXHJcbiAgICAgICAgICAgIGNodW5rW2krK10gPSAodCAmIDE1KSA8PCAxMiB8IChidWZmZXJbc3RhcnQrK10gJiA2MykgPDwgNiB8IGJ1ZmZlcltzdGFydCsrXSAmIDYzO1xyXG4gICAgICAgIGlmIChpID4gODE5MSkge1xyXG4gICAgICAgICAgICAocGFydHMgfHwgKHBhcnRzID0gW10pKS5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBjaHVuaykpO1xyXG4gICAgICAgICAgICBpID0gMDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbiAgICBpZiAocGFydHMpIHtcclxuICAgICAgICBpZiAoaSlcclxuICAgICAgICAgICAgcGFydHMucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFN0cmluZywgY2h1bmsuc2xpY2UoMCwgaSkpKTtcclxuICAgICAgICByZXR1cm4gcGFydHMuam9pbihcIlwiKTtcclxuICAgIH1cclxuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFN0cmluZywgY2h1bmsuc2xpY2UoMCwgaSkpO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFdyaXRlcyBhIHN0cmluZyBhcyBVVEY4IGJ5dGVzLlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyaW5nIFNvdXJjZSBzdHJpbmdcclxuICogQHBhcmFtIHtVaW50OEFycmF5fSBidWZmZXIgRGVzdGluYXRpb24gYnVmZmVyXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXQgRGVzdGluYXRpb24gb2Zmc2V0XHJcbiAqIEByZXR1cm5zIHtudW1iZXJ9IEJ5dGVzIHdyaXR0ZW5cclxuICovXHJcbnV0Zjgud3JpdGUgPSBmdW5jdGlvbiB1dGY4X3dyaXRlKHN0cmluZywgYnVmZmVyLCBvZmZzZXQpIHtcclxuICAgIHZhciBzdGFydCA9IG9mZnNldCxcclxuICAgICAgICBjMSwgLy8gY2hhcmFjdGVyIDFcclxuICAgICAgICBjMjsgLy8gY2hhcmFjdGVyIDJcclxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgKytpKSB7XHJcbiAgICAgICAgYzEgPSBzdHJpbmcuY2hhckNvZGVBdChpKTtcclxuICAgICAgICBpZiAoYzEgPCAxMjgpIHtcclxuICAgICAgICAgICAgYnVmZmVyW29mZnNldCsrXSA9IGMxO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoYzEgPCAyMDQ4KSB7XHJcbiAgICAgICAgICAgIGJ1ZmZlcltvZmZzZXQrK10gPSBjMSA+PiA2ICAgICAgIHwgMTkyO1xyXG4gICAgICAgICAgICBidWZmZXJbb2Zmc2V0KytdID0gYzEgICAgICAgJiA2MyB8IDEyODtcclxuICAgICAgICB9IGVsc2UgaWYgKChjMSAmIDB4RkMwMCkgPT09IDB4RDgwMCAmJiAoKGMyID0gc3RyaW5nLmNoYXJDb2RlQXQoaSArIDEpKSAmIDB4RkMwMCkgPT09IDB4REMwMCkge1xyXG4gICAgICAgICAgICBjMSA9IDB4MTAwMDAgKyAoKGMxICYgMHgwM0ZGKSA8PCAxMCkgKyAoYzIgJiAweDAzRkYpO1xyXG4gICAgICAgICAgICArK2k7XHJcbiAgICAgICAgICAgIGJ1ZmZlcltvZmZzZXQrK10gPSBjMSA+PiAxOCAgICAgIHwgMjQwO1xyXG4gICAgICAgICAgICBidWZmZXJbb2Zmc2V0KytdID0gYzEgPj4gMTIgJiA2MyB8IDEyODtcclxuICAgICAgICAgICAgYnVmZmVyW29mZnNldCsrXSA9IGMxID4+IDYgICYgNjMgfCAxMjg7XHJcbiAgICAgICAgICAgIGJ1ZmZlcltvZmZzZXQrK10gPSBjMSAgICAgICAmIDYzIHwgMTI4O1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGJ1ZmZlcltvZmZzZXQrK10gPSBjMSA+PiAxMiAgICAgIHwgMjI0O1xyXG4gICAgICAgICAgICBidWZmZXJbb2Zmc2V0KytdID0gYzEgPj4gNiAgJiA2MyB8IDEyODtcclxuICAgICAgICAgICAgYnVmZmVyW29mZnNldCsrXSA9IGMxICAgICAgICYgNjMgfCAxMjg7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIG9mZnNldCAtIHN0YXJ0O1xyXG59O1xyXG4iLCJcInVzZSBzdHJpY3RcIjtcclxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcclxudmFyIEd1aWQgPSAvKiogQGNsYXNzICovIChmdW5jdGlvbiAoKSB7XHJcbiAgICBmdW5jdGlvbiBHdWlkKGd1aWQpIHtcclxuICAgICAgICBpZiAoIWd1aWQpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgYXJndW1lbnQ7IGB2YWx1ZWAgaGFzIG5vIHZhbHVlLlwiKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy52YWx1ZSA9IEd1aWQuRU1QVFk7XHJcbiAgICAgICAgaWYgKGd1aWQgJiYgR3VpZC5pc0d1aWQoZ3VpZCkpIHtcclxuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IGd1aWQ7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgR3VpZC5pc0d1aWQgPSBmdW5jdGlvbiAoZ3VpZCkge1xyXG4gICAgICAgIHZhciB2YWx1ZSA9IGd1aWQudG9TdHJpbmcoKTtcclxuICAgICAgICByZXR1cm4gZ3VpZCAmJiAoZ3VpZCBpbnN0YW5jZW9mIEd1aWQgfHwgR3VpZC52YWxpZGF0b3IudGVzdCh2YWx1ZSkpO1xyXG4gICAgfTtcclxuICAgIEd1aWQuY3JlYXRlID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHJldHVybiBuZXcgR3VpZChbR3VpZC5nZW4oMiksIEd1aWQuZ2VuKDEpLCBHdWlkLmdlbigxKSwgR3VpZC5nZW4oMSksIEd1aWQuZ2VuKDMpXS5qb2luKFwiLVwiKSk7XHJcbiAgICB9O1xyXG4gICAgR3VpZC5jcmVhdGVFbXB0eSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4gbmV3IEd1aWQoXCJlbXB0eWd1aWRcIik7XHJcbiAgICB9O1xyXG4gICAgR3VpZC5wYXJzZSA9IGZ1bmN0aW9uIChndWlkKSB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBHdWlkKGd1aWQpO1xyXG4gICAgfTtcclxuICAgIEd1aWQucmF3ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHJldHVybiBbR3VpZC5nZW4oMiksIEd1aWQuZ2VuKDEpLCBHdWlkLmdlbigxKSwgR3VpZC5nZW4oMSksIEd1aWQuZ2VuKDMpXS5qb2luKFwiLVwiKTtcclxuICAgIH07XHJcbiAgICBHdWlkLmdlbiA9IGZ1bmN0aW9uIChjb3VudCkge1xyXG4gICAgICAgIHZhciBvdXQgPSBcIlwiO1xyXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xyXG4gICAgICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tYml0d2lzZVxyXG4gICAgICAgICAgICBvdXQgKz0gKCgoMSArIE1hdGgucmFuZG9tKCkpICogMHgxMDAwMCkgfCAwKS50b1N0cmluZygxNikuc3Vic3RyaW5nKDEpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gb3V0O1xyXG4gICAgfTtcclxuICAgIEd1aWQucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uIChvdGhlcikge1xyXG4gICAgICAgIC8vIENvbXBhcmluZyBzdHJpbmcgYHZhbHVlYCBhZ2FpbnN0IHByb3ZpZGVkIGBndWlkYCB3aWxsIGF1dG8tY2FsbFxyXG4gICAgICAgIC8vIHRvU3RyaW5nIG9uIGBndWlkYCBmb3IgY29tcGFyaXNvblxyXG4gICAgICAgIHJldHVybiBHdWlkLmlzR3VpZChvdGhlcikgJiYgdGhpcy52YWx1ZSA9PT0gb3RoZXIudG9TdHJpbmcoKTtcclxuICAgIH07XHJcbiAgICBHdWlkLnByb3RvdHlwZS5pc0VtcHR5ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLnZhbHVlID09PSBHdWlkLkVNUFRZO1xyXG4gICAgfTtcclxuICAgIEd1aWQucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xyXG4gICAgfTtcclxuICAgIEd1aWQucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICB2YWx1ZTogdGhpcy52YWx1ZVxyXG4gICAgICAgIH07XHJcbiAgICB9O1xyXG4gICAgR3VpZC52YWxpZGF0b3IgPSBuZXcgUmVnRXhwKFwiXlthLXowLTldezh9LVthLXowLTldezR9LVthLXowLTldezR9LVthLXowLTldezR9LVthLXowLTldezEyfSRcIiwgXCJpXCIpO1xyXG4gICAgR3VpZC5FTVBUWSA9IFwiMDAwMDAwMDAtMDAwMC0wMDAwLTAwMDAtMDAwMDAwMDAwMDAwXCI7XHJcbiAgICByZXR1cm4gR3VpZDtcclxufSgpKTtcclxuZXhwb3J0cy5HdWlkID0gR3VpZDtcclxuIiwibW9kdWxlLmV4cG9ydHMgPSBMb25nO1xyXG5cclxuLyoqXHJcbiAqIHdhc20gb3B0aW1pemF0aW9ucywgdG8gZG8gbmF0aXZlIGk2NCBtdWx0aXBsaWNhdGlvbiBhbmQgZGl2aWRlXHJcbiAqL1xyXG52YXIgd2FzbSA9IG51bGw7XHJcblxyXG50cnkge1xyXG4gIHdhc20gPSBuZXcgV2ViQXNzZW1ibHkuSW5zdGFuY2UobmV3IFdlYkFzc2VtYmx5Lk1vZHVsZShuZXcgVWludDhBcnJheShbXHJcbiAgICAwLCA5NywgMTE1LCAxMDksIDEsIDAsIDAsIDAsIDEsIDEzLCAyLCA5NiwgMCwgMSwgMTI3LCA5NiwgNCwgMTI3LCAxMjcsIDEyNywgMTI3LCAxLCAxMjcsIDMsIDcsIDYsIDAsIDEsIDEsIDEsIDEsIDEsIDYsIDYsIDEsIDEyNywgMSwgNjUsIDAsIDExLCA3LCA1MCwgNiwgMywgMTA5LCAxMTcsIDEwOCwgMCwgMSwgNSwgMTAwLCAxMDUsIDExOCwgOTUsIDExNSwgMCwgMiwgNSwgMTAwLCAxMDUsIDExOCwgOTUsIDExNywgMCwgMywgNSwgMTE0LCAxMDEsIDEwOSwgOTUsIDExNSwgMCwgNCwgNSwgMTE0LCAxMDEsIDEwOSwgOTUsIDExNywgMCwgNSwgOCwgMTAzLCAxMDEsIDExNiwgOTUsIDEwNCwgMTA1LCAxMDMsIDEwNCwgMCwgMCwgMTAsIDE5MSwgMSwgNiwgNCwgMCwgMzUsIDAsIDExLCAzNiwgMSwgMSwgMTI2LCAzMiwgMCwgMTczLCAzMiwgMSwgMTczLCA2NiwgMzIsIDEzNCwgMTMyLCAzMiwgMiwgMTczLCAzMiwgMywgMTczLCA2NiwgMzIsIDEzNCwgMTMyLCAxMjYsIDM0LCA0LCA2NiwgMzIsIDEzNSwgMTY3LCAzNiwgMCwgMzIsIDQsIDE2NywgMTEsIDM2LCAxLCAxLCAxMjYsIDMyLCAwLCAxNzMsIDMyLCAxLCAxNzMsIDY2LCAzMiwgMTM0LCAxMzIsIDMyLCAyLCAxNzMsIDMyLCAzLCAxNzMsIDY2LCAzMiwgMTM0LCAxMzIsIDEyNywgMzQsIDQsIDY2LCAzMiwgMTM1LCAxNjcsIDM2LCAwLCAzMiwgNCwgMTY3LCAxMSwgMzYsIDEsIDEsIDEyNiwgMzIsIDAsIDE3MywgMzIsIDEsIDE3MywgNjYsIDMyLCAxMzQsIDEzMiwgMzIsIDIsIDE3MywgMzIsIDMsIDE3MywgNjYsIDMyLCAxMzQsIDEzMiwgMTI4LCAzNCwgNCwgNjYsIDMyLCAxMzUsIDE2NywgMzYsIDAsIDMyLCA0LCAxNjcsIDExLCAzNiwgMSwgMSwgMTI2LCAzMiwgMCwgMTczLCAzMiwgMSwgMTczLCA2NiwgMzIsIDEzNCwgMTMyLCAzMiwgMiwgMTczLCAzMiwgMywgMTczLCA2NiwgMzIsIDEzNCwgMTMyLCAxMjksIDM0LCA0LCA2NiwgMzIsIDEzNSwgMTY3LCAzNiwgMCwgMzIsIDQsIDE2NywgMTEsIDM2LCAxLCAxLCAxMjYsIDMyLCAwLCAxNzMsIDMyLCAxLCAxNzMsIDY2LCAzMiwgMTM0LCAxMzIsIDMyLCAyLCAxNzMsIDMyLCAzLCAxNzMsIDY2LCAzMiwgMTM0LCAxMzIsIDEzMCwgMzQsIDQsIDY2LCAzMiwgMTM1LCAxNjcsIDM2LCAwLCAzMiwgNCwgMTY3LCAxMVxyXG4gIF0pKSwge30pLmV4cG9ydHM7XHJcbn0gY2F0Y2ggKGUpIHtcclxuICAvLyBubyB3YXNtIHN1cHBvcnQgOihcclxufVxyXG5cclxuLyoqXHJcbiAqIENvbnN0cnVjdHMgYSA2NCBiaXQgdHdvJ3MtY29tcGxlbWVudCBpbnRlZ2VyLCBnaXZlbiBpdHMgbG93IGFuZCBoaWdoIDMyIGJpdCB2YWx1ZXMgYXMgKnNpZ25lZCogaW50ZWdlcnMuXHJcbiAqICBTZWUgdGhlIGZyb20qIGZ1bmN0aW9ucyBiZWxvdyBmb3IgbW9yZSBjb252ZW5pZW50IHdheXMgb2YgY29uc3RydWN0aW5nIExvbmdzLlxyXG4gKiBAZXhwb3J0cyBMb25nXHJcbiAqIEBjbGFzcyBBIExvbmcgY2xhc3MgZm9yIHJlcHJlc2VudGluZyBhIDY0IGJpdCB0d28ncy1jb21wbGVtZW50IGludGVnZXIgdmFsdWUuXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBsb3cgVGhlIGxvdyAoc2lnbmVkKSAzMiBiaXRzIG9mIHRoZSBsb25nXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBoaWdoIFRoZSBoaWdoIChzaWduZWQpIDMyIGJpdHMgb2YgdGhlIGxvbmdcclxuICogQHBhcmFtIHtib29sZWFuPX0gdW5zaWduZWQgV2hldGhlciB1bnNpZ25lZCBvciBub3QsIGRlZmF1bHRzIHRvIHNpZ25lZFxyXG4gKiBAY29uc3RydWN0b3JcclxuICovXHJcbmZ1bmN0aW9uIExvbmcobG93LCBoaWdoLCB1bnNpZ25lZCkge1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGxvdyAzMiBiaXRzIGFzIGEgc2lnbmVkIHZhbHVlLlxyXG4gICAgICogQHR5cGUge251bWJlcn1cclxuICAgICAqL1xyXG4gICAgdGhpcy5sb3cgPSBsb3cgfCAwO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGhpZ2ggMzIgYml0cyBhcyBhIHNpZ25lZCB2YWx1ZS5cclxuICAgICAqIEB0eXBlIHtudW1iZXJ9XHJcbiAgICAgKi9cclxuICAgIHRoaXMuaGlnaCA9IGhpZ2ggfCAwO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogV2hldGhlciB1bnNpZ25lZCBvciBub3QuXHJcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cclxuICAgICAqL1xyXG4gICAgdGhpcy51bnNpZ25lZCA9ICEhdW5zaWduZWQ7XHJcbn1cclxuXHJcbi8vIFRoZSBpbnRlcm5hbCByZXByZXNlbnRhdGlvbiBvZiBhIGxvbmcgaXMgdGhlIHR3byBnaXZlbiBzaWduZWQsIDMyLWJpdCB2YWx1ZXMuXHJcbi8vIFdlIHVzZSAzMi1iaXQgcGllY2VzIGJlY2F1c2UgdGhlc2UgYXJlIHRoZSBzaXplIG9mIGludGVnZXJzIG9uIHdoaWNoXHJcbi8vIEphdmFzY3JpcHQgcGVyZm9ybXMgYml0LW9wZXJhdGlvbnMuICBGb3Igb3BlcmF0aW9ucyBsaWtlIGFkZGl0aW9uIGFuZFxyXG4vLyBtdWx0aXBsaWNhdGlvbiwgd2Ugc3BsaXQgZWFjaCBudW1iZXIgaW50byAxNiBiaXQgcGllY2VzLCB3aGljaCBjYW4gZWFzaWx5IGJlXHJcbi8vIG11bHRpcGxpZWQgd2l0aGluIEphdmFzY3JpcHQncyBmbG9hdGluZy1wb2ludCByZXByZXNlbnRhdGlvbiB3aXRob3V0IG92ZXJmbG93XHJcbi8vIG9yIGNoYW5nZSBpbiBzaWduLlxyXG4vL1xyXG4vLyBJbiB0aGUgYWxnb3JpdGhtcyBiZWxvdywgd2UgZnJlcXVlbnRseSByZWR1Y2UgdGhlIG5lZ2F0aXZlIGNhc2UgdG8gdGhlXHJcbi8vIHBvc2l0aXZlIGNhc2UgYnkgbmVnYXRpbmcgdGhlIGlucHV0KHMpIGFuZCB0aGVuIHBvc3QtcHJvY2Vzc2luZyB0aGUgcmVzdWx0LlxyXG4vLyBOb3RlIHRoYXQgd2UgbXVzdCBBTFdBWVMgY2hlY2sgc3BlY2lhbGx5IHdoZXRoZXIgdGhvc2UgdmFsdWVzIGFyZSBNSU5fVkFMVUVcclxuLy8gKC0yXjYzKSBiZWNhdXNlIC1NSU5fVkFMVUUgPT0gTUlOX1ZBTFVFIChzaW5jZSAyXjYzIGNhbm5vdCBiZSByZXByZXNlbnRlZCBhc1xyXG4vLyBhIHBvc2l0aXZlIG51bWJlciwgaXQgb3ZlcmZsb3dzIGJhY2sgaW50byBhIG5lZ2F0aXZlKS4gIE5vdCBoYW5kbGluZyB0aGlzXHJcbi8vIGNhc2Ugd291bGQgb2Z0ZW4gcmVzdWx0IGluIGluZmluaXRlIHJlY3Vyc2lvbi5cclxuLy9cclxuLy8gQ29tbW9uIGNvbnN0YW50IHZhbHVlcyBaRVJPLCBPTkUsIE5FR19PTkUsIGV0Yy4gYXJlIGRlZmluZWQgYmVsb3cgdGhlIGZyb20qXHJcbi8vIG1ldGhvZHMgb24gd2hpY2ggdGhleSBkZXBlbmQuXHJcblxyXG4vKipcclxuICogQW4gaW5kaWNhdG9yIHVzZWQgdG8gcmVsaWFibHkgZGV0ZXJtaW5lIGlmIGFuIG9iamVjdCBpcyBhIExvbmcgb3Igbm90LlxyXG4gKiBAdHlwZSB7Ym9vbGVhbn1cclxuICogQGNvbnN0XHJcbiAqIEBwcml2YXRlXHJcbiAqL1xyXG5Mb25nLnByb3RvdHlwZS5fX2lzTG9uZ19fO1xyXG5cclxuT2JqZWN0LmRlZmluZVByb3BlcnR5KExvbmcucHJvdG90eXBlLCBcIl9faXNMb25nX19cIiwgeyB2YWx1ZTogdHJ1ZSB9KTtcclxuXHJcbi8qKlxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHsqfSBvYmogT2JqZWN0XHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKiBAaW5uZXJcclxuICovXHJcbmZ1bmN0aW9uIGlzTG9uZyhvYmopIHtcclxuICAgIHJldHVybiAob2JqICYmIG9ialtcIl9faXNMb25nX19cIl0pID09PSB0cnVlO1xyXG59XHJcblxyXG4vKipcclxuICogVGVzdHMgaWYgdGhlIHNwZWNpZmllZCBvYmplY3QgaXMgYSBMb25nLlxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHsqfSBvYmogT2JqZWN0XHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZy5pc0xvbmcgPSBpc0xvbmc7XHJcblxyXG4vKipcclxuICogQSBjYWNoZSBvZiB0aGUgTG9uZyByZXByZXNlbnRhdGlvbnMgb2Ygc21hbGwgaW50ZWdlciB2YWx1ZXMuXHJcbiAqIEB0eXBlIHshT2JqZWN0fVxyXG4gKiBAaW5uZXJcclxuICovXHJcbnZhciBJTlRfQ0FDSEUgPSB7fTtcclxuXHJcbi8qKlxyXG4gKiBBIGNhY2hlIG9mIHRoZSBMb25nIHJlcHJlc2VudGF0aW9ucyBvZiBzbWFsbCB1bnNpZ25lZCBpbnRlZ2VyIHZhbHVlcy5cclxuICogQHR5cGUgeyFPYmplY3R9XHJcbiAqIEBpbm5lclxyXG4gKi9cclxudmFyIFVJTlRfQ0FDSEUgPSB7fTtcclxuXHJcbi8qKlxyXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcclxuICogQHBhcmFtIHtib29sZWFuPX0gdW5zaWduZWRcclxuICogQHJldHVybnMgeyFMb25nfVxyXG4gKiBAaW5uZXJcclxuICovXHJcbmZ1bmN0aW9uIGZyb21JbnQodmFsdWUsIHVuc2lnbmVkKSB7XHJcbiAgICB2YXIgb2JqLCBjYWNoZWRPYmosIGNhY2hlO1xyXG4gICAgaWYgKHVuc2lnbmVkKSB7XHJcbiAgICAgICAgdmFsdWUgPj4+PSAwO1xyXG4gICAgICAgIGlmIChjYWNoZSA9ICgwIDw9IHZhbHVlICYmIHZhbHVlIDwgMjU2KSkge1xyXG4gICAgICAgICAgICBjYWNoZWRPYmogPSBVSU5UX0NBQ0hFW3ZhbHVlXTtcclxuICAgICAgICAgICAgaWYgKGNhY2hlZE9iailcclxuICAgICAgICAgICAgICAgIHJldHVybiBjYWNoZWRPYmo7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIG9iaiA9IGZyb21CaXRzKHZhbHVlLCAodmFsdWUgfCAwKSA8IDAgPyAtMSA6IDAsIHRydWUpO1xyXG4gICAgICAgIGlmIChjYWNoZSlcclxuICAgICAgICAgICAgVUlOVF9DQUNIRVt2YWx1ZV0gPSBvYmo7XHJcbiAgICAgICAgcmV0dXJuIG9iajtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdmFsdWUgfD0gMDtcclxuICAgICAgICBpZiAoY2FjaGUgPSAoLTEyOCA8PSB2YWx1ZSAmJiB2YWx1ZSA8IDEyOCkpIHtcclxuICAgICAgICAgICAgY2FjaGVkT2JqID0gSU5UX0NBQ0hFW3ZhbHVlXTtcclxuICAgICAgICAgICAgaWYgKGNhY2hlZE9iailcclxuICAgICAgICAgICAgICAgIHJldHVybiBjYWNoZWRPYmo7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIG9iaiA9IGZyb21CaXRzKHZhbHVlLCB2YWx1ZSA8IDAgPyAtMSA6IDAsIGZhbHNlKTtcclxuICAgICAgICBpZiAoY2FjaGUpXHJcbiAgICAgICAgICAgIElOVF9DQUNIRVt2YWx1ZV0gPSBvYmo7XHJcbiAgICAgICAgcmV0dXJuIG9iajtcclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgYSBMb25nIHJlcHJlc2VudGluZyB0aGUgZ2l2ZW4gMzIgYml0IGludGVnZXIgdmFsdWUuXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVGhlIDMyIGJpdCBpbnRlZ2VyIGluIHF1ZXN0aW9uXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbj19IHVuc2lnbmVkIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LCBkZWZhdWx0cyB0byBzaWduZWRcclxuICogQHJldHVybnMgeyFMb25nfSBUaGUgY29ycmVzcG9uZGluZyBMb25nIHZhbHVlXHJcbiAqL1xyXG5Mb25nLmZyb21JbnQgPSBmcm9tSW50O1xyXG5cclxuLyoqXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxyXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSB1bnNpZ25lZFxyXG4gKiBAcmV0dXJucyB7IUxvbmd9XHJcbiAqIEBpbm5lclxyXG4gKi9cclxuZnVuY3Rpb24gZnJvbU51bWJlcih2YWx1ZSwgdW5zaWduZWQpIHtcclxuICAgIGlmIChpc05hTih2YWx1ZSkpXHJcbiAgICAgICAgcmV0dXJuIHVuc2lnbmVkID8gVVpFUk8gOiBaRVJPO1xyXG4gICAgaWYgKHVuc2lnbmVkKSB7XHJcbiAgICAgICAgaWYgKHZhbHVlIDwgMClcclxuICAgICAgICAgICAgcmV0dXJuIFVaRVJPO1xyXG4gICAgICAgIGlmICh2YWx1ZSA+PSBUV09fUFdSXzY0X0RCTClcclxuICAgICAgICAgICAgcmV0dXJuIE1BWF9VTlNJR05FRF9WQUxVRTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgICAgaWYgKHZhbHVlIDw9IC1UV09fUFdSXzYzX0RCTClcclxuICAgICAgICAgICAgcmV0dXJuIE1JTl9WQUxVRTtcclxuICAgICAgICBpZiAodmFsdWUgKyAxID49IFRXT19QV1JfNjNfREJMKVxyXG4gICAgICAgICAgICByZXR1cm4gTUFYX1ZBTFVFO1xyXG4gICAgfVxyXG4gICAgaWYgKHZhbHVlIDwgMClcclxuICAgICAgICByZXR1cm4gZnJvbU51bWJlcigtdmFsdWUsIHVuc2lnbmVkKS5uZWcoKTtcclxuICAgIHJldHVybiBmcm9tQml0cygodmFsdWUgJSBUV09fUFdSXzMyX0RCTCkgfCAwLCAodmFsdWUgLyBUV09fUFdSXzMyX0RCTCkgfCAwLCB1bnNpZ25lZCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIGEgTG9uZyByZXByZXNlbnRpbmcgdGhlIGdpdmVuIHZhbHVlLCBwcm92aWRlZCB0aGF0IGl0IGlzIGEgZmluaXRlIG51bWJlci4gT3RoZXJ3aXNlLCB6ZXJvIGlzIHJldHVybmVkLlxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFRoZSBudW1iZXIgaW4gcXVlc3Rpb25cclxuICogQHBhcmFtIHtib29sZWFuPX0gdW5zaWduZWQgV2hldGhlciB1bnNpZ25lZCBvciBub3QsIGRlZmF1bHRzIHRvIHNpZ25lZFxyXG4gKiBAcmV0dXJucyB7IUxvbmd9IFRoZSBjb3JyZXNwb25kaW5nIExvbmcgdmFsdWVcclxuICovXHJcbkxvbmcuZnJvbU51bWJlciA9IGZyb21OdW1iZXI7XHJcblxyXG4vKipcclxuICogQHBhcmFtIHtudW1iZXJ9IGxvd0JpdHNcclxuICogQHBhcmFtIHtudW1iZXJ9IGhpZ2hCaXRzXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbj19IHVuc2lnbmVkXHJcbiAqIEByZXR1cm5zIHshTG9uZ31cclxuICogQGlubmVyXHJcbiAqL1xyXG5mdW5jdGlvbiBmcm9tQml0cyhsb3dCaXRzLCBoaWdoQml0cywgdW5zaWduZWQpIHtcclxuICAgIHJldHVybiBuZXcgTG9uZyhsb3dCaXRzLCBoaWdoQml0cywgdW5zaWduZWQpO1xyXG59XHJcblxyXG4vKipcclxuICogUmV0dXJucyBhIExvbmcgcmVwcmVzZW50aW5nIHRoZSA2NCBiaXQgaW50ZWdlciB0aGF0IGNvbWVzIGJ5IGNvbmNhdGVuYXRpbmcgdGhlIGdpdmVuIGxvdyBhbmQgaGlnaCBiaXRzLiBFYWNoIGlzXHJcbiAqICBhc3N1bWVkIHRvIHVzZSAzMiBiaXRzLlxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHtudW1iZXJ9IGxvd0JpdHMgVGhlIGxvdyAzMiBiaXRzXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBoaWdoQml0cyBUaGUgaGlnaCAzMiBiaXRzXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbj19IHVuc2lnbmVkIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LCBkZWZhdWx0cyB0byBzaWduZWRcclxuICogQHJldHVybnMgeyFMb25nfSBUaGUgY29ycmVzcG9uZGluZyBMb25nIHZhbHVlXHJcbiAqL1xyXG5Mb25nLmZyb21CaXRzID0gZnJvbUJpdHM7XHJcblxyXG4vKipcclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBiYXNlXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBleHBvbmVudFxyXG4gKiBAcmV0dXJucyB7bnVtYmVyfVxyXG4gKiBAaW5uZXJcclxuICovXHJcbnZhciBwb3dfZGJsID0gTWF0aC5wb3c7IC8vIFVzZWQgNCB0aW1lcyAoNCo4IHRvIDE1KzQpXHJcblxyXG4vKipcclxuICogQHBhcmFtIHtzdHJpbmd9IHN0clxyXG4gKiBAcGFyYW0geyhib29sZWFufG51bWJlcik9fSB1bnNpZ25lZFxyXG4gKiBAcGFyYW0ge251bWJlcj19IHJhZGl4XHJcbiAqIEByZXR1cm5zIHshTG9uZ31cclxuICogQGlubmVyXHJcbiAqL1xyXG5mdW5jdGlvbiBmcm9tU3RyaW5nKHN0ciwgdW5zaWduZWQsIHJhZGl4KSB7XHJcbiAgICBpZiAoc3RyLmxlbmd0aCA9PT0gMClcclxuICAgICAgICB0aHJvdyBFcnJvcignZW1wdHkgc3RyaW5nJyk7XHJcbiAgICBpZiAoc3RyID09PSBcIk5hTlwiIHx8IHN0ciA9PT0gXCJJbmZpbml0eVwiIHx8IHN0ciA9PT0gXCIrSW5maW5pdHlcIiB8fCBzdHIgPT09IFwiLUluZmluaXR5XCIpXHJcbiAgICAgICAgcmV0dXJuIFpFUk87XHJcbiAgICBpZiAodHlwZW9mIHVuc2lnbmVkID09PSAnbnVtYmVyJykge1xyXG4gICAgICAgIC8vIEZvciBnb29nLm1hdGgubG9uZyBjb21wYXRpYmlsaXR5XHJcbiAgICAgICAgcmFkaXggPSB1bnNpZ25lZCxcclxuICAgICAgICB1bnNpZ25lZCA9IGZhbHNlO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICB1bnNpZ25lZCA9ICEhIHVuc2lnbmVkO1xyXG4gICAgfVxyXG4gICAgcmFkaXggPSByYWRpeCB8fCAxMDtcclxuICAgIGlmIChyYWRpeCA8IDIgfHwgMzYgPCByYWRpeClcclxuICAgICAgICB0aHJvdyBSYW5nZUVycm9yKCdyYWRpeCcpO1xyXG5cclxuICAgIHZhciBwO1xyXG4gICAgaWYgKChwID0gc3RyLmluZGV4T2YoJy0nKSkgPiAwKVxyXG4gICAgICAgIHRocm93IEVycm9yKCdpbnRlcmlvciBoeXBoZW4nKTtcclxuICAgIGVsc2UgaWYgKHAgPT09IDApIHtcclxuICAgICAgICByZXR1cm4gZnJvbVN0cmluZyhzdHIuc3Vic3RyaW5nKDEpLCB1bnNpZ25lZCwgcmFkaXgpLm5lZygpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIERvIHNldmVyYWwgKDgpIGRpZ2l0cyBlYWNoIHRpbWUgdGhyb3VnaCB0aGUgbG9vcCwgc28gYXMgdG9cclxuICAgIC8vIG1pbmltaXplIHRoZSBjYWxscyB0byB0aGUgdmVyeSBleHBlbnNpdmUgZW11bGF0ZWQgZGl2LlxyXG4gICAgdmFyIHJhZGl4VG9Qb3dlciA9IGZyb21OdW1iZXIocG93X2RibChyYWRpeCwgOCkpO1xyXG5cclxuICAgIHZhciByZXN1bHQgPSBaRVJPO1xyXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpICs9IDgpIHtcclxuICAgICAgICB2YXIgc2l6ZSA9IE1hdGgubWluKDgsIHN0ci5sZW5ndGggLSBpKSxcclxuICAgICAgICAgICAgdmFsdWUgPSBwYXJzZUludChzdHIuc3Vic3RyaW5nKGksIGkgKyBzaXplKSwgcmFkaXgpO1xyXG4gICAgICAgIGlmIChzaXplIDwgOCkge1xyXG4gICAgICAgICAgICB2YXIgcG93ZXIgPSBmcm9tTnVtYmVyKHBvd19kYmwocmFkaXgsIHNpemUpKTtcclxuICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0Lm11bChwb3dlcikuYWRkKGZyb21OdW1iZXIodmFsdWUpKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXN1bHQgPSByZXN1bHQubXVsKHJhZGl4VG9Qb3dlcik7XHJcbiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5hZGQoZnJvbU51bWJlcih2YWx1ZSkpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIHJlc3VsdC51bnNpZ25lZCA9IHVuc2lnbmVkO1xyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgYSBMb25nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBnaXZlbiBzdHJpbmcsIHdyaXR0ZW4gdXNpbmcgdGhlIHNwZWNpZmllZCByYWRpeC5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgVGhlIHRleHR1YWwgcmVwcmVzZW50YXRpb24gb2YgdGhlIExvbmdcclxuICogQHBhcmFtIHsoYm9vbGVhbnxudW1iZXIpPX0gdW5zaWduZWQgV2hldGhlciB1bnNpZ25lZCBvciBub3QsIGRlZmF1bHRzIHRvIHNpZ25lZFxyXG4gKiBAcGFyYW0ge251bWJlcj19IHJhZGl4IFRoZSByYWRpeCBpbiB3aGljaCB0aGUgdGV4dCBpcyB3cml0dGVuICgyLTM2KSwgZGVmYXVsdHMgdG8gMTBcclxuICogQHJldHVybnMgeyFMb25nfSBUaGUgY29ycmVzcG9uZGluZyBMb25nIHZhbHVlXHJcbiAqL1xyXG5Mb25nLmZyb21TdHJpbmcgPSBmcm9tU3RyaW5nO1xyXG5cclxuLyoqXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd8IXtsb3c6IG51bWJlciwgaGlnaDogbnVtYmVyLCB1bnNpZ25lZDogYm9vbGVhbn19IHZhbFxyXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSB1bnNpZ25lZFxyXG4gKiBAcmV0dXJucyB7IUxvbmd9XHJcbiAqIEBpbm5lclxyXG4gKi9cclxuZnVuY3Rpb24gZnJvbVZhbHVlKHZhbCwgdW5zaWduZWQpIHtcclxuICAgIGlmICh0eXBlb2YgdmFsID09PSAnbnVtYmVyJylcclxuICAgICAgICByZXR1cm4gZnJvbU51bWJlcih2YWwsIHVuc2lnbmVkKTtcclxuICAgIGlmICh0eXBlb2YgdmFsID09PSAnc3RyaW5nJylcclxuICAgICAgICByZXR1cm4gZnJvbVN0cmluZyh2YWwsIHVuc2lnbmVkKTtcclxuICAgIC8vIFRocm93cyBmb3Igbm9uLW9iamVjdHMsIGNvbnZlcnRzIG5vbi1pbnN0YW5jZW9mIExvbmc6XHJcbiAgICByZXR1cm4gZnJvbUJpdHModmFsLmxvdywgdmFsLmhpZ2gsIHR5cGVvZiB1bnNpZ25lZCA9PT0gJ2Jvb2xlYW4nID8gdW5zaWduZWQgOiB2YWwudW5zaWduZWQpO1xyXG59XHJcblxyXG4vKipcclxuICogQ29udmVydHMgdGhlIHNwZWNpZmllZCB2YWx1ZSB0byBhIExvbmcgdXNpbmcgdGhlIGFwcHJvcHJpYXRlIGZyb20qIGZ1bmN0aW9uIGZvciBpdHMgdHlwZS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ3whe2xvdzogbnVtYmVyLCBoaWdoOiBudW1iZXIsIHVuc2lnbmVkOiBib29sZWFufX0gdmFsIFZhbHVlXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbj19IHVuc2lnbmVkIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LCBkZWZhdWx0cyB0byBzaWduZWRcclxuICogQHJldHVybnMgeyFMb25nfVxyXG4gKi9cclxuTG9uZy5mcm9tVmFsdWUgPSBmcm9tVmFsdWU7XHJcblxyXG4vLyBOT1RFOiB0aGUgY29tcGlsZXIgc2hvdWxkIGlubGluZSB0aGVzZSBjb25zdGFudCB2YWx1ZXMgYmVsb3cgYW5kIHRoZW4gcmVtb3ZlIHRoZXNlIHZhcmlhYmxlcywgc28gdGhlcmUgc2hvdWxkIGJlXHJcbi8vIG5vIHJ1bnRpbWUgcGVuYWx0eSBmb3IgdGhlc2UuXHJcblxyXG4vKipcclxuICogQHR5cGUge251bWJlcn1cclxuICogQGNvbnN0XHJcbiAqIEBpbm5lclxyXG4gKi9cclxudmFyIFRXT19QV1JfMTZfREJMID0gMSA8PCAxNjtcclxuXHJcbi8qKlxyXG4gKiBAdHlwZSB7bnVtYmVyfVxyXG4gKiBAY29uc3RcclxuICogQGlubmVyXHJcbiAqL1xyXG52YXIgVFdPX1BXUl8yNF9EQkwgPSAxIDw8IDI0O1xyXG5cclxuLyoqXHJcbiAqIEB0eXBlIHtudW1iZXJ9XHJcbiAqIEBjb25zdFxyXG4gKiBAaW5uZXJcclxuICovXHJcbnZhciBUV09fUFdSXzMyX0RCTCA9IFRXT19QV1JfMTZfREJMICogVFdPX1BXUl8xNl9EQkw7XHJcblxyXG4vKipcclxuICogQHR5cGUge251bWJlcn1cclxuICogQGNvbnN0XHJcbiAqIEBpbm5lclxyXG4gKi9cclxudmFyIFRXT19QV1JfNjRfREJMID0gVFdPX1BXUl8zMl9EQkwgKiBUV09fUFdSXzMyX0RCTDtcclxuXHJcbi8qKlxyXG4gKiBAdHlwZSB7bnVtYmVyfVxyXG4gKiBAY29uc3RcclxuICogQGlubmVyXHJcbiAqL1xyXG52YXIgVFdPX1BXUl82M19EQkwgPSBUV09fUFdSXzY0X0RCTCAvIDI7XHJcblxyXG4vKipcclxuICogQHR5cGUgeyFMb25nfVxyXG4gKiBAY29uc3RcclxuICogQGlubmVyXHJcbiAqL1xyXG52YXIgVFdPX1BXUl8yNCA9IGZyb21JbnQoVFdPX1BXUl8yNF9EQkwpO1xyXG5cclxuLyoqXHJcbiAqIEB0eXBlIHshTG9uZ31cclxuICogQGlubmVyXHJcbiAqL1xyXG52YXIgWkVSTyA9IGZyb21JbnQoMCk7XHJcblxyXG4vKipcclxuICogU2lnbmVkIHplcm8uXHJcbiAqIEB0eXBlIHshTG9uZ31cclxuICovXHJcbkxvbmcuWkVSTyA9IFpFUk87XHJcblxyXG4vKipcclxuICogQHR5cGUgeyFMb25nfVxyXG4gKiBAaW5uZXJcclxuICovXHJcbnZhciBVWkVSTyA9IGZyb21JbnQoMCwgdHJ1ZSk7XHJcblxyXG4vKipcclxuICogVW5zaWduZWQgemVyby5cclxuICogQHR5cGUgeyFMb25nfVxyXG4gKi9cclxuTG9uZy5VWkVSTyA9IFVaRVJPO1xyXG5cclxuLyoqXHJcbiAqIEB0eXBlIHshTG9uZ31cclxuICogQGlubmVyXHJcbiAqL1xyXG52YXIgT05FID0gZnJvbUludCgxKTtcclxuXHJcbi8qKlxyXG4gKiBTaWduZWQgb25lLlxyXG4gKiBAdHlwZSB7IUxvbmd9XHJcbiAqL1xyXG5Mb25nLk9ORSA9IE9ORTtcclxuXHJcbi8qKlxyXG4gKiBAdHlwZSB7IUxvbmd9XHJcbiAqIEBpbm5lclxyXG4gKi9cclxudmFyIFVPTkUgPSBmcm9tSW50KDEsIHRydWUpO1xyXG5cclxuLyoqXHJcbiAqIFVuc2lnbmVkIG9uZS5cclxuICogQHR5cGUgeyFMb25nfVxyXG4gKi9cclxuTG9uZy5VT05FID0gVU9ORTtcclxuXHJcbi8qKlxyXG4gKiBAdHlwZSB7IUxvbmd9XHJcbiAqIEBpbm5lclxyXG4gKi9cclxudmFyIE5FR19PTkUgPSBmcm9tSW50KC0xKTtcclxuXHJcbi8qKlxyXG4gKiBTaWduZWQgbmVnYXRpdmUgb25lLlxyXG4gKiBAdHlwZSB7IUxvbmd9XHJcbiAqL1xyXG5Mb25nLk5FR19PTkUgPSBORUdfT05FO1xyXG5cclxuLyoqXHJcbiAqIEB0eXBlIHshTG9uZ31cclxuICogQGlubmVyXHJcbiAqL1xyXG52YXIgTUFYX1ZBTFVFID0gZnJvbUJpdHMoMHhGRkZGRkZGRnwwLCAweDdGRkZGRkZGfDAsIGZhbHNlKTtcclxuXHJcbi8qKlxyXG4gKiBNYXhpbXVtIHNpZ25lZCB2YWx1ZS5cclxuICogQHR5cGUgeyFMb25nfVxyXG4gKi9cclxuTG9uZy5NQVhfVkFMVUUgPSBNQVhfVkFMVUU7XHJcblxyXG4vKipcclxuICogQHR5cGUgeyFMb25nfVxyXG4gKiBAaW5uZXJcclxuICovXHJcbnZhciBNQVhfVU5TSUdORURfVkFMVUUgPSBmcm9tQml0cygweEZGRkZGRkZGfDAsIDB4RkZGRkZGRkZ8MCwgdHJ1ZSk7XHJcblxyXG4vKipcclxuICogTWF4aW11bSB1bnNpZ25lZCB2YWx1ZS5cclxuICogQHR5cGUgeyFMb25nfVxyXG4gKi9cclxuTG9uZy5NQVhfVU5TSUdORURfVkFMVUUgPSBNQVhfVU5TSUdORURfVkFMVUU7XHJcblxyXG4vKipcclxuICogQHR5cGUgeyFMb25nfVxyXG4gKiBAaW5uZXJcclxuICovXHJcbnZhciBNSU5fVkFMVUUgPSBmcm9tQml0cygwLCAweDgwMDAwMDAwfDAsIGZhbHNlKTtcclxuXHJcbi8qKlxyXG4gKiBNaW5pbXVtIHNpZ25lZCB2YWx1ZS5cclxuICogQHR5cGUgeyFMb25nfVxyXG4gKi9cclxuTG9uZy5NSU5fVkFMVUUgPSBNSU5fVkFMVUU7XHJcblxyXG4vKipcclxuICogQGFsaWFzIExvbmcucHJvdG90eXBlXHJcbiAqIEBpbm5lclxyXG4gKi9cclxudmFyIExvbmdQcm90b3R5cGUgPSBMb25nLnByb3RvdHlwZTtcclxuXHJcbi8qKlxyXG4gKiBDb252ZXJ0cyB0aGUgTG9uZyB0byBhIDMyIGJpdCBpbnRlZ2VyLCBhc3N1bWluZyBpdCBpcyBhIDMyIGJpdCBpbnRlZ2VyLlxyXG4gKiBAcmV0dXJucyB7bnVtYmVyfVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS50b0ludCA9IGZ1bmN0aW9uIHRvSW50KCkge1xyXG4gICAgcmV0dXJuIHRoaXMudW5zaWduZWQgPyB0aGlzLmxvdyA+Pj4gMCA6IHRoaXMubG93O1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIENvbnZlcnRzIHRoZSBMb25nIHRvIGEgdGhlIG5lYXJlc3QgZmxvYXRpbmctcG9pbnQgcmVwcmVzZW50YXRpb24gb2YgdGhpcyB2YWx1ZSAoZG91YmxlLCA1MyBiaXQgbWFudGlzc2EpLlxyXG4gKiBAcmV0dXJucyB7bnVtYmVyfVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS50b051bWJlciA9IGZ1bmN0aW9uIHRvTnVtYmVyKCkge1xyXG4gICAgaWYgKHRoaXMudW5zaWduZWQpXHJcbiAgICAgICAgcmV0dXJuICgodGhpcy5oaWdoID4+PiAwKSAqIFRXT19QV1JfMzJfREJMKSArICh0aGlzLmxvdyA+Pj4gMCk7XHJcbiAgICByZXR1cm4gdGhpcy5oaWdoICogVFdPX1BXUl8zMl9EQkwgKyAodGhpcy5sb3cgPj4+IDApO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIENvbnZlcnRzIHRoZSBMb25nIHRvIGEgc3RyaW5nIHdyaXR0ZW4gaW4gdGhlIHNwZWNpZmllZCByYWRpeC5cclxuICogQHBhcmFtIHtudW1iZXI9fSByYWRpeCBSYWRpeCAoMi0zNiksIGRlZmF1bHRzIHRvIDEwXHJcbiAqIEByZXR1cm5zIHtzdHJpbmd9XHJcbiAqIEBvdmVycmlkZVxyXG4gKiBAdGhyb3dzIHtSYW5nZUVycm9yfSBJZiBgcmFkaXhgIGlzIG91dCBvZiByYW5nZVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKHJhZGl4KSB7XHJcbiAgICByYWRpeCA9IHJhZGl4IHx8IDEwO1xyXG4gICAgaWYgKHJhZGl4IDwgMiB8fCAzNiA8IHJhZGl4KVxyXG4gICAgICAgIHRocm93IFJhbmdlRXJyb3IoJ3JhZGl4Jyk7XHJcbiAgICBpZiAodGhpcy5pc1plcm8oKSlcclxuICAgICAgICByZXR1cm4gJzAnO1xyXG4gICAgaWYgKHRoaXMuaXNOZWdhdGl2ZSgpKSB7IC8vIFVuc2lnbmVkIExvbmdzIGFyZSBuZXZlciBuZWdhdGl2ZVxyXG4gICAgICAgIGlmICh0aGlzLmVxKE1JTl9WQUxVRSkpIHtcclxuICAgICAgICAgICAgLy8gV2UgbmVlZCB0byBjaGFuZ2UgdGhlIExvbmcgdmFsdWUgYmVmb3JlIGl0IGNhbiBiZSBuZWdhdGVkLCBzbyB3ZSByZW1vdmVcclxuICAgICAgICAgICAgLy8gdGhlIGJvdHRvbS1tb3N0IGRpZ2l0IGluIHRoaXMgYmFzZSBhbmQgdGhlbiByZWN1cnNlIHRvIGRvIHRoZSByZXN0LlxyXG4gICAgICAgICAgICB2YXIgcmFkaXhMb25nID0gZnJvbU51bWJlcihyYWRpeCksXHJcbiAgICAgICAgICAgICAgICBkaXYgPSB0aGlzLmRpdihyYWRpeExvbmcpLFxyXG4gICAgICAgICAgICAgICAgcmVtMSA9IGRpdi5tdWwocmFkaXhMb25nKS5zdWIodGhpcyk7XHJcbiAgICAgICAgICAgIHJldHVybiBkaXYudG9TdHJpbmcocmFkaXgpICsgcmVtMS50b0ludCgpLnRvU3RyaW5nKHJhZGl4KTtcclxuICAgICAgICB9IGVsc2VcclxuICAgICAgICAgICAgcmV0dXJuICctJyArIHRoaXMubmVnKCkudG9TdHJpbmcocmFkaXgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIERvIHNldmVyYWwgKDYpIGRpZ2l0cyBlYWNoIHRpbWUgdGhyb3VnaCB0aGUgbG9vcCwgc28gYXMgdG9cclxuICAgIC8vIG1pbmltaXplIHRoZSBjYWxscyB0byB0aGUgdmVyeSBleHBlbnNpdmUgZW11bGF0ZWQgZGl2LlxyXG4gICAgdmFyIHJhZGl4VG9Qb3dlciA9IGZyb21OdW1iZXIocG93X2RibChyYWRpeCwgNiksIHRoaXMudW5zaWduZWQpLFxyXG4gICAgICAgIHJlbSA9IHRoaXM7XHJcbiAgICB2YXIgcmVzdWx0ID0gJyc7XHJcbiAgICB3aGlsZSAodHJ1ZSkge1xyXG4gICAgICAgIHZhciByZW1EaXYgPSByZW0uZGl2KHJhZGl4VG9Qb3dlciksXHJcbiAgICAgICAgICAgIGludHZhbCA9IHJlbS5zdWIocmVtRGl2Lm11bChyYWRpeFRvUG93ZXIpKS50b0ludCgpID4+PiAwLFxyXG4gICAgICAgICAgICBkaWdpdHMgPSBpbnR2YWwudG9TdHJpbmcocmFkaXgpO1xyXG4gICAgICAgIHJlbSA9IHJlbURpdjtcclxuICAgICAgICBpZiAocmVtLmlzWmVybygpKVxyXG4gICAgICAgICAgICByZXR1cm4gZGlnaXRzICsgcmVzdWx0O1xyXG4gICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICB3aGlsZSAoZGlnaXRzLmxlbmd0aCA8IDYpXHJcbiAgICAgICAgICAgICAgICBkaWdpdHMgPSAnMCcgKyBkaWdpdHM7XHJcbiAgICAgICAgICAgIHJlc3VsdCA9ICcnICsgZGlnaXRzICsgcmVzdWx0O1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufTtcclxuXHJcbi8qKlxyXG4gKiBHZXRzIHRoZSBoaWdoIDMyIGJpdHMgYXMgYSBzaWduZWQgaW50ZWdlci5cclxuICogQHJldHVybnMge251bWJlcn0gU2lnbmVkIGhpZ2ggYml0c1xyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5nZXRIaWdoQml0cyA9IGZ1bmN0aW9uIGdldEhpZ2hCaXRzKCkge1xyXG4gICAgcmV0dXJuIHRoaXMuaGlnaDtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBHZXRzIHRoZSBoaWdoIDMyIGJpdHMgYXMgYW4gdW5zaWduZWQgaW50ZWdlci5cclxuICogQHJldHVybnMge251bWJlcn0gVW5zaWduZWQgaGlnaCBiaXRzXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmdldEhpZ2hCaXRzVW5zaWduZWQgPSBmdW5jdGlvbiBnZXRIaWdoQml0c1Vuc2lnbmVkKCkge1xyXG4gICAgcmV0dXJuIHRoaXMuaGlnaCA+Pj4gMDtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBHZXRzIHRoZSBsb3cgMzIgYml0cyBhcyBhIHNpZ25lZCBpbnRlZ2VyLlxyXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBTaWduZWQgbG93IGJpdHNcclxuICovXHJcbkxvbmdQcm90b3R5cGUuZ2V0TG93Qml0cyA9IGZ1bmN0aW9uIGdldExvd0JpdHMoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5sb3c7XHJcbn07XHJcblxyXG4vKipcclxuICogR2V0cyB0aGUgbG93IDMyIGJpdHMgYXMgYW4gdW5zaWduZWQgaW50ZWdlci5cclxuICogQHJldHVybnMge251bWJlcn0gVW5zaWduZWQgbG93IGJpdHNcclxuICovXHJcbkxvbmdQcm90b3R5cGUuZ2V0TG93Qml0c1Vuc2lnbmVkID0gZnVuY3Rpb24gZ2V0TG93Qml0c1Vuc2lnbmVkKCkge1xyXG4gICAgcmV0dXJuIHRoaXMubG93ID4+PiAwO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIEdldHMgdGhlIG51bWJlciBvZiBiaXRzIG5lZWRlZCB0byByZXByZXNlbnQgdGhlIGFic29sdXRlIHZhbHVlIG9mIHRoaXMgTG9uZy5cclxuICogQHJldHVybnMge251bWJlcn1cclxuICovXHJcbkxvbmdQcm90b3R5cGUuZ2V0TnVtQml0c0FicyA9IGZ1bmN0aW9uIGdldE51bUJpdHNBYnMoKSB7XHJcbiAgICBpZiAodGhpcy5pc05lZ2F0aXZlKCkpIC8vIFVuc2lnbmVkIExvbmdzIGFyZSBuZXZlciBuZWdhdGl2ZVxyXG4gICAgICAgIHJldHVybiB0aGlzLmVxKE1JTl9WQUxVRSkgPyA2NCA6IHRoaXMubmVnKCkuZ2V0TnVtQml0c0FicygpO1xyXG4gICAgdmFyIHZhbCA9IHRoaXMuaGlnaCAhPSAwID8gdGhpcy5oaWdoIDogdGhpcy5sb3c7XHJcbiAgICBmb3IgKHZhciBiaXQgPSAzMTsgYml0ID4gMDsgYml0LS0pXHJcbiAgICAgICAgaWYgKCh2YWwgJiAoMSA8PCBiaXQpKSAhPSAwKVxyXG4gICAgICAgICAgICBicmVhaztcclxuICAgIHJldHVybiB0aGlzLmhpZ2ggIT0gMCA/IGJpdCArIDMzIDogYml0ICsgMTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBlcXVhbHMgemVyby5cclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmlzWmVybyA9IGZ1bmN0aW9uIGlzWmVybygpIHtcclxuICAgIHJldHVybiB0aGlzLmhpZ2ggPT09IDAgJiYgdGhpcy5sb3cgPT09IDA7XHJcbn07XHJcblxyXG4vKipcclxuICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgZXF1YWxzIHplcm8uIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjaXNaZXJvfS5cclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmVxeiA9IExvbmdQcm90b3R5cGUuaXNaZXJvO1xyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGlzIG5lZ2F0aXZlLlxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICovXHJcbkxvbmdQcm90b3R5cGUuaXNOZWdhdGl2ZSA9IGZ1bmN0aW9uIGlzTmVnYXRpdmUoKSB7XHJcbiAgICByZXR1cm4gIXRoaXMudW5zaWduZWQgJiYgdGhpcy5oaWdoIDwgMDtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBwb3NpdGl2ZS5cclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmlzUG9zaXRpdmUgPSBmdW5jdGlvbiBpc1Bvc2l0aXZlKCkge1xyXG4gICAgcmV0dXJuIHRoaXMudW5zaWduZWQgfHwgdGhpcy5oaWdoID49IDA7XHJcbn07XHJcblxyXG4vKipcclxuICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgaXMgb2RkLlxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICovXHJcbkxvbmdQcm90b3R5cGUuaXNPZGQgPSBmdW5jdGlvbiBpc09kZCgpIHtcclxuICAgIHJldHVybiAodGhpcy5sb3cgJiAxKSA9PT0gMTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBldmVuLlxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICovXHJcbkxvbmdQcm90b3R5cGUuaXNFdmVuID0gZnVuY3Rpb24gaXNFdmVuKCkge1xyXG4gICAgcmV0dXJuICh0aGlzLmxvdyAmIDEpID09PSAwO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGVxdWFscyB0aGUgc3BlY2lmaWVkJ3MuXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uIGVxdWFscyhvdGhlcikge1xyXG4gICAgaWYgKCFpc0xvbmcob3RoZXIpKVxyXG4gICAgICAgIG90aGVyID0gZnJvbVZhbHVlKG90aGVyKTtcclxuICAgIGlmICh0aGlzLnVuc2lnbmVkICE9PSBvdGhlci51bnNpZ25lZCAmJiAodGhpcy5oaWdoID4+PiAzMSkgPT09IDEgJiYgKG90aGVyLmhpZ2ggPj4+IDMxKSA9PT0gMSlcclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICByZXR1cm4gdGhpcy5oaWdoID09PSBvdGhlci5oaWdoICYmIHRoaXMubG93ID09PSBvdGhlci5sb3c7XHJcbn07XHJcblxyXG4vKipcclxuICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgZXF1YWxzIHRoZSBzcGVjaWZpZWQncy4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgTG9uZyNlcXVhbHN9LlxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciB2YWx1ZVxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICovXHJcbkxvbmdQcm90b3R5cGUuZXEgPSBMb25nUHJvdG90eXBlLmVxdWFscztcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBkaWZmZXJzIGZyb20gdGhlIHNwZWNpZmllZCdzLlxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5ub3RFcXVhbHMgPSBmdW5jdGlvbiBub3RFcXVhbHMob3RoZXIpIHtcclxuICAgIHJldHVybiAhdGhpcy5lcSgvKiB2YWxpZGF0ZXMgKi8gb3RoZXIpO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGRpZmZlcnMgZnJvbSB0aGUgc3BlY2lmaWVkJ3MuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjbm90RXF1YWxzfS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLm5lcSA9IExvbmdQcm90b3R5cGUubm90RXF1YWxzO1xyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGRpZmZlcnMgZnJvbSB0aGUgc3BlY2lmaWVkJ3MuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjbm90RXF1YWxzfS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLm5lID0gTG9uZ1Byb3RvdHlwZS5ub3RFcXVhbHM7XHJcblxyXG4vKipcclxuICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgaXMgbGVzcyB0aGFuIHRoZSBzcGVjaWZpZWQncy5cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciB2YWx1ZVxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICovXHJcbkxvbmdQcm90b3R5cGUubGVzc1RoYW4gPSBmdW5jdGlvbiBsZXNzVGhhbihvdGhlcikge1xyXG4gICAgcmV0dXJuIHRoaXMuY29tcCgvKiB2YWxpZGF0ZXMgKi8gb3RoZXIpIDwgMDtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBsZXNzIHRoYW4gdGhlIHNwZWNpZmllZCdzLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI2xlc3NUaGFufS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmx0ID0gTG9uZ1Byb3RvdHlwZS5sZXNzVGhhbjtcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdGhlIHNwZWNpZmllZCdzLlxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5sZXNzVGhhbk9yRXF1YWwgPSBmdW5jdGlvbiBsZXNzVGhhbk9yRXF1YWwob3RoZXIpIHtcclxuICAgIHJldHVybiB0aGlzLmNvbXAoLyogdmFsaWRhdGVzICovIG90aGVyKSA8PSAwO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGlzIGxlc3MgdGhhbiBvciBlcXVhbCB0aGUgc3BlY2lmaWVkJ3MuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjbGVzc1RoYW5PckVxdWFsfS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmx0ZSA9IExvbmdQcm90b3R5cGUubGVzc1RoYW5PckVxdWFsO1xyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGlzIGxlc3MgdGhhbiBvciBlcXVhbCB0aGUgc3BlY2lmaWVkJ3MuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjbGVzc1RoYW5PckVxdWFsfS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmxlID0gTG9uZ1Byb3RvdHlwZS5sZXNzVGhhbk9yRXF1YWw7XHJcblxyXG4vKipcclxuICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgaXMgZ3JlYXRlciB0aGFuIHRoZSBzcGVjaWZpZWQncy5cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciB2YWx1ZVxyXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICovXHJcbkxvbmdQcm90b3R5cGUuZ3JlYXRlclRoYW4gPSBmdW5jdGlvbiBncmVhdGVyVGhhbihvdGhlcikge1xyXG4gICAgcmV0dXJuIHRoaXMuY29tcCgvKiB2YWxpZGF0ZXMgKi8gb3RoZXIpID4gMDtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBncmVhdGVyIHRoYW4gdGhlIHNwZWNpZmllZCdzLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI2dyZWF0ZXJUaGFufS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmd0ID0gTG9uZ1Byb3RvdHlwZS5ncmVhdGVyVGhhbjtcclxuXHJcbi8qKlxyXG4gKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdGhlIHNwZWNpZmllZCdzLlxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5ncmVhdGVyVGhhbk9yRXF1YWwgPSBmdW5jdGlvbiBncmVhdGVyVGhhbk9yRXF1YWwob3RoZXIpIHtcclxuICAgIHJldHVybiB0aGlzLmNvbXAoLyogdmFsaWRhdGVzICovIG90aGVyKSA+PSAwO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGlzIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0aGUgc3BlY2lmaWVkJ3MuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjZ3JlYXRlclRoYW5PckVxdWFsfS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmd0ZSA9IExvbmdQcm90b3R5cGUuZ3JlYXRlclRoYW5PckVxdWFsO1xyXG5cclxuLyoqXHJcbiAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGlzIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0aGUgc3BlY2lmaWVkJ3MuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjZ3JlYXRlclRoYW5PckVxdWFsfS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmdlID0gTG9uZ1Byb3RvdHlwZS5ncmVhdGVyVGhhbk9yRXF1YWw7XHJcblxyXG4vKipcclxuICogQ29tcGFyZXMgdGhpcyBMb25nJ3MgdmFsdWUgd2l0aCB0aGUgc3BlY2lmaWVkJ3MuXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICogQHJldHVybnMge251bWJlcn0gMCBpZiB0aGV5IGFyZSB0aGUgc2FtZSwgMSBpZiB0aGUgdGhpcyBpcyBncmVhdGVyIGFuZCAtMVxyXG4gKiAgaWYgdGhlIGdpdmVuIG9uZSBpcyBncmVhdGVyXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmNvbXBhcmUgPSBmdW5jdGlvbiBjb21wYXJlKG90aGVyKSB7XHJcbiAgICBpZiAoIWlzTG9uZyhvdGhlcikpXHJcbiAgICAgICAgb3RoZXIgPSBmcm9tVmFsdWUob3RoZXIpO1xyXG4gICAgaWYgKHRoaXMuZXEob3RoZXIpKVxyXG4gICAgICAgIHJldHVybiAwO1xyXG4gICAgdmFyIHRoaXNOZWcgPSB0aGlzLmlzTmVnYXRpdmUoKSxcclxuICAgICAgICBvdGhlck5lZyA9IG90aGVyLmlzTmVnYXRpdmUoKTtcclxuICAgIGlmICh0aGlzTmVnICYmICFvdGhlck5lZylcclxuICAgICAgICByZXR1cm4gLTE7XHJcbiAgICBpZiAoIXRoaXNOZWcgJiYgb3RoZXJOZWcpXHJcbiAgICAgICAgcmV0dXJuIDE7XHJcbiAgICAvLyBBdCB0aGlzIHBvaW50IHRoZSBzaWduIGJpdHMgYXJlIHRoZSBzYW1lXHJcbiAgICBpZiAoIXRoaXMudW5zaWduZWQpXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuc3ViKG90aGVyKS5pc05lZ2F0aXZlKCkgPyAtMSA6IDE7XHJcbiAgICAvLyBCb3RoIGFyZSBwb3NpdGl2ZSBpZiBhdCBsZWFzdCBvbmUgaXMgdW5zaWduZWRcclxuICAgIHJldHVybiAob3RoZXIuaGlnaCA+Pj4gMCkgPiAodGhpcy5oaWdoID4+PiAwKSB8fCAob3RoZXIuaGlnaCA9PT0gdGhpcy5oaWdoICYmIChvdGhlci5sb3cgPj4+IDApID4gKHRoaXMubG93ID4+PiAwKSkgPyAtMSA6IDE7XHJcbn07XHJcblxyXG4vKipcclxuICogQ29tcGFyZXMgdGhpcyBMb25nJ3MgdmFsdWUgd2l0aCB0aGUgc3BlY2lmaWVkJ3MuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjY29tcGFyZX0uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAqIEByZXR1cm5zIHtudW1iZXJ9IDAgaWYgdGhleSBhcmUgdGhlIHNhbWUsIDEgaWYgdGhlIHRoaXMgaXMgZ3JlYXRlciBhbmQgLTFcclxuICogIGlmIHRoZSBnaXZlbiBvbmUgaXMgZ3JlYXRlclxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5jb21wID0gTG9uZ1Byb3RvdHlwZS5jb21wYXJlO1xyXG5cclxuLyoqXHJcbiAqIE5lZ2F0ZXMgdGhpcyBMb25nJ3MgdmFsdWUuXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gTmVnYXRlZCBMb25nXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLm5lZ2F0ZSA9IGZ1bmN0aW9uIG5lZ2F0ZSgpIHtcclxuICAgIGlmICghdGhpcy51bnNpZ25lZCAmJiB0aGlzLmVxKE1JTl9WQUxVRSkpXHJcbiAgICAgICAgcmV0dXJuIE1JTl9WQUxVRTtcclxuICAgIHJldHVybiB0aGlzLm5vdCgpLmFkZChPTkUpO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIE5lZ2F0ZXMgdGhpcyBMb25nJ3MgdmFsdWUuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjbmVnYXRlfS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gTmVnYXRlZCBMb25nXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLm5lZyA9IExvbmdQcm90b3R5cGUubmVnYXRlO1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIHN1bSBvZiB0aGlzIGFuZCB0aGUgc3BlY2lmaWVkIExvbmcuXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gYWRkZW5kIEFkZGVuZFxyXG4gKiBAcmV0dXJucyB7IUxvbmd9IFN1bVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5hZGQgPSBmdW5jdGlvbiBhZGQoYWRkZW5kKSB7XHJcbiAgICBpZiAoIWlzTG9uZyhhZGRlbmQpKVxyXG4gICAgICAgIGFkZGVuZCA9IGZyb21WYWx1ZShhZGRlbmQpO1xyXG5cclxuICAgIC8vIERpdmlkZSBlYWNoIG51bWJlciBpbnRvIDQgY2h1bmtzIG9mIDE2IGJpdHMsIGFuZCB0aGVuIHN1bSB0aGUgY2h1bmtzLlxyXG5cclxuICAgIHZhciBhNDggPSB0aGlzLmhpZ2ggPj4+IDE2O1xyXG4gICAgdmFyIGEzMiA9IHRoaXMuaGlnaCAmIDB4RkZGRjtcclxuICAgIHZhciBhMTYgPSB0aGlzLmxvdyA+Pj4gMTY7XHJcbiAgICB2YXIgYTAwID0gdGhpcy5sb3cgJiAweEZGRkY7XHJcblxyXG4gICAgdmFyIGI0OCA9IGFkZGVuZC5oaWdoID4+PiAxNjtcclxuICAgIHZhciBiMzIgPSBhZGRlbmQuaGlnaCAmIDB4RkZGRjtcclxuICAgIHZhciBiMTYgPSBhZGRlbmQubG93ID4+PiAxNjtcclxuICAgIHZhciBiMDAgPSBhZGRlbmQubG93ICYgMHhGRkZGO1xyXG5cclxuICAgIHZhciBjNDggPSAwLCBjMzIgPSAwLCBjMTYgPSAwLCBjMDAgPSAwO1xyXG4gICAgYzAwICs9IGEwMCArIGIwMDtcclxuICAgIGMxNiArPSBjMDAgPj4+IDE2O1xyXG4gICAgYzAwICY9IDB4RkZGRjtcclxuICAgIGMxNiArPSBhMTYgKyBiMTY7XHJcbiAgICBjMzIgKz0gYzE2ID4+PiAxNjtcclxuICAgIGMxNiAmPSAweEZGRkY7XHJcbiAgICBjMzIgKz0gYTMyICsgYjMyO1xyXG4gICAgYzQ4ICs9IGMzMiA+Pj4gMTY7XHJcbiAgICBjMzIgJj0gMHhGRkZGO1xyXG4gICAgYzQ4ICs9IGE0OCArIGI0ODtcclxuICAgIGM0OCAmPSAweEZGRkY7XHJcbiAgICByZXR1cm4gZnJvbUJpdHMoKGMxNiA8PCAxNikgfCBjMDAsIChjNDggPDwgMTYpIHwgYzMyLCB0aGlzLnVuc2lnbmVkKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoZSBkaWZmZXJlbmNlIG9mIHRoaXMgYW5kIHRoZSBzcGVjaWZpZWQgTG9uZy5cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBzdWJ0cmFoZW5kIFN1YnRyYWhlbmRcclxuICogQHJldHVybnMgeyFMb25nfSBEaWZmZXJlbmNlXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLnN1YnRyYWN0ID0gZnVuY3Rpb24gc3VidHJhY3Qoc3VidHJhaGVuZCkge1xyXG4gICAgaWYgKCFpc0xvbmcoc3VidHJhaGVuZCkpXHJcbiAgICAgICAgc3VidHJhaGVuZCA9IGZyb21WYWx1ZShzdWJ0cmFoZW5kKTtcclxuICAgIHJldHVybiB0aGlzLmFkZChzdWJ0cmFoZW5kLm5lZygpKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoZSBkaWZmZXJlbmNlIG9mIHRoaXMgYW5kIHRoZSBzcGVjaWZpZWQgTG9uZy4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgTG9uZyNzdWJ0cmFjdH0uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IHN1YnRyYWhlbmQgU3VidHJhaGVuZFxyXG4gKiBAcmV0dXJucyB7IUxvbmd9IERpZmZlcmVuY2VcclxuICovXHJcbkxvbmdQcm90b3R5cGUuc3ViID0gTG9uZ1Byb3RvdHlwZS5zdWJ0cmFjdDtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoZSBwcm9kdWN0IG9mIHRoaXMgYW5kIHRoZSBzcGVjaWZpZWQgTG9uZy5cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBtdWx0aXBsaWVyIE11bHRpcGxpZXJcclxuICogQHJldHVybnMgeyFMb25nfSBQcm9kdWN0XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLm11bHRpcGx5ID0gZnVuY3Rpb24gbXVsdGlwbHkobXVsdGlwbGllcikge1xyXG4gICAgaWYgKHRoaXMuaXNaZXJvKCkpXHJcbiAgICAgICAgcmV0dXJuIFpFUk87XHJcbiAgICBpZiAoIWlzTG9uZyhtdWx0aXBsaWVyKSlcclxuICAgICAgICBtdWx0aXBsaWVyID0gZnJvbVZhbHVlKG11bHRpcGxpZXIpO1xyXG5cclxuICAgIC8vIHVzZSB3YXNtIHN1cHBvcnQgaWYgcHJlc2VudFxyXG4gICAgaWYgKHdhc20pIHtcclxuICAgICAgICB2YXIgbG93ID0gd2FzbS5tdWwodGhpcy5sb3csXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaGlnaCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgbXVsdGlwbGllci5sb3csXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIG11bHRpcGxpZXIuaGlnaCk7XHJcbiAgICAgICAgcmV0dXJuIGZyb21CaXRzKGxvdywgd2FzbS5nZXRfaGlnaCgpLCB0aGlzLnVuc2lnbmVkKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAobXVsdGlwbGllci5pc1plcm8oKSlcclxuICAgICAgICByZXR1cm4gWkVSTztcclxuICAgIGlmICh0aGlzLmVxKE1JTl9WQUxVRSkpXHJcbiAgICAgICAgcmV0dXJuIG11bHRpcGxpZXIuaXNPZGQoKSA/IE1JTl9WQUxVRSA6IFpFUk87XHJcbiAgICBpZiAobXVsdGlwbGllci5lcShNSU5fVkFMVUUpKVxyXG4gICAgICAgIHJldHVybiB0aGlzLmlzT2RkKCkgPyBNSU5fVkFMVUUgOiBaRVJPO1xyXG5cclxuICAgIGlmICh0aGlzLmlzTmVnYXRpdmUoKSkge1xyXG4gICAgICAgIGlmIChtdWx0aXBsaWVyLmlzTmVnYXRpdmUoKSlcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubmVnKCkubXVsKG11bHRpcGxpZXIubmVnKCkpO1xyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubmVnKCkubXVsKG11bHRpcGxpZXIpLm5lZygpO1xyXG4gICAgfSBlbHNlIGlmIChtdWx0aXBsaWVyLmlzTmVnYXRpdmUoKSlcclxuICAgICAgICByZXR1cm4gdGhpcy5tdWwobXVsdGlwbGllci5uZWcoKSkubmVnKCk7XHJcblxyXG4gICAgLy8gSWYgYm90aCBsb25ncyBhcmUgc21hbGwsIHVzZSBmbG9hdCBtdWx0aXBsaWNhdGlvblxyXG4gICAgaWYgKHRoaXMubHQoVFdPX1BXUl8yNCkgJiYgbXVsdGlwbGllci5sdChUV09fUFdSXzI0KSlcclxuICAgICAgICByZXR1cm4gZnJvbU51bWJlcih0aGlzLnRvTnVtYmVyKCkgKiBtdWx0aXBsaWVyLnRvTnVtYmVyKCksIHRoaXMudW5zaWduZWQpO1xyXG5cclxuICAgIC8vIERpdmlkZSBlYWNoIGxvbmcgaW50byA0IGNodW5rcyBvZiAxNiBiaXRzLCBhbmQgdGhlbiBhZGQgdXAgNHg0IHByb2R1Y3RzLlxyXG4gICAgLy8gV2UgY2FuIHNraXAgcHJvZHVjdHMgdGhhdCB3b3VsZCBvdmVyZmxvdy5cclxuXHJcbiAgICB2YXIgYTQ4ID0gdGhpcy5oaWdoID4+PiAxNjtcclxuICAgIHZhciBhMzIgPSB0aGlzLmhpZ2ggJiAweEZGRkY7XHJcbiAgICB2YXIgYTE2ID0gdGhpcy5sb3cgPj4+IDE2O1xyXG4gICAgdmFyIGEwMCA9IHRoaXMubG93ICYgMHhGRkZGO1xyXG5cclxuICAgIHZhciBiNDggPSBtdWx0aXBsaWVyLmhpZ2ggPj4+IDE2O1xyXG4gICAgdmFyIGIzMiA9IG11bHRpcGxpZXIuaGlnaCAmIDB4RkZGRjtcclxuICAgIHZhciBiMTYgPSBtdWx0aXBsaWVyLmxvdyA+Pj4gMTY7XHJcbiAgICB2YXIgYjAwID0gbXVsdGlwbGllci5sb3cgJiAweEZGRkY7XHJcblxyXG4gICAgdmFyIGM0OCA9IDAsIGMzMiA9IDAsIGMxNiA9IDAsIGMwMCA9IDA7XHJcbiAgICBjMDAgKz0gYTAwICogYjAwO1xyXG4gICAgYzE2ICs9IGMwMCA+Pj4gMTY7XHJcbiAgICBjMDAgJj0gMHhGRkZGO1xyXG4gICAgYzE2ICs9IGExNiAqIGIwMDtcclxuICAgIGMzMiArPSBjMTYgPj4+IDE2O1xyXG4gICAgYzE2ICY9IDB4RkZGRjtcclxuICAgIGMxNiArPSBhMDAgKiBiMTY7XHJcbiAgICBjMzIgKz0gYzE2ID4+PiAxNjtcclxuICAgIGMxNiAmPSAweEZGRkY7XHJcbiAgICBjMzIgKz0gYTMyICogYjAwO1xyXG4gICAgYzQ4ICs9IGMzMiA+Pj4gMTY7XHJcbiAgICBjMzIgJj0gMHhGRkZGO1xyXG4gICAgYzMyICs9IGExNiAqIGIxNjtcclxuICAgIGM0OCArPSBjMzIgPj4+IDE2O1xyXG4gICAgYzMyICY9IDB4RkZGRjtcclxuICAgIGMzMiArPSBhMDAgKiBiMzI7XHJcbiAgICBjNDggKz0gYzMyID4+PiAxNjtcclxuICAgIGMzMiAmPSAweEZGRkY7XHJcbiAgICBjNDggKz0gYTQ4ICogYjAwICsgYTMyICogYjE2ICsgYTE2ICogYjMyICsgYTAwICogYjQ4O1xyXG4gICAgYzQ4ICY9IDB4RkZGRjtcclxuICAgIHJldHVybiBmcm9tQml0cygoYzE2IDw8IDE2KSB8IGMwMCwgKGM0OCA8PCAxNikgfCBjMzIsIHRoaXMudW5zaWduZWQpO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIHByb2R1Y3Qgb2YgdGhpcyBhbmQgdGhlIHNwZWNpZmllZCBMb25nLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI211bHRpcGx5fS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gbXVsdGlwbGllciBNdWx0aXBsaWVyXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gUHJvZHVjdFxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5tdWwgPSBMb25nUHJvdG90eXBlLm11bHRpcGx5O1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhpcyBMb25nIGRpdmlkZWQgYnkgdGhlIHNwZWNpZmllZC4gVGhlIHJlc3VsdCBpcyBzaWduZWQgaWYgdGhpcyBMb25nIGlzIHNpZ25lZCBvclxyXG4gKiAgdW5zaWduZWQgaWYgdGhpcyBMb25nIGlzIHVuc2lnbmVkLlxyXG4gKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IGRpdmlzb3IgRGl2aXNvclxyXG4gKiBAcmV0dXJucyB7IUxvbmd9IFF1b3RpZW50XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmRpdmlkZSA9IGZ1bmN0aW9uIGRpdmlkZShkaXZpc29yKSB7XHJcbiAgICBpZiAoIWlzTG9uZyhkaXZpc29yKSlcclxuICAgICAgICBkaXZpc29yID0gZnJvbVZhbHVlKGRpdmlzb3IpO1xyXG4gICAgaWYgKGRpdmlzb3IuaXNaZXJvKCkpXHJcbiAgICAgICAgdGhyb3cgRXJyb3IoJ2RpdmlzaW9uIGJ5IHplcm8nKTtcclxuXHJcbiAgICAvLyB1c2Ugd2FzbSBzdXBwb3J0IGlmIHByZXNlbnRcclxuICAgIGlmICh3YXNtKSB7XHJcbiAgICAgICAgLy8gZ3VhcmQgYWdhaW5zdCBzaWduZWQgZGl2aXNpb24gb3ZlcmZsb3c6IHRoZSBsYXJnZXN0XHJcbiAgICAgICAgLy8gbmVnYXRpdmUgbnVtYmVyIC8gLTEgd291bGQgYmUgMSBsYXJnZXIgdGhhbiB0aGUgbGFyZ2VzdFxyXG4gICAgICAgIC8vIHBvc2l0aXZlIG51bWJlciwgZHVlIHRvIHR3bydzIGNvbXBsZW1lbnQuXHJcbiAgICAgICAgaWYgKCF0aGlzLnVuc2lnbmVkICYmXHJcbiAgICAgICAgICAgIHRoaXMuaGlnaCA9PT0gLTB4ODAwMDAwMDAgJiZcclxuICAgICAgICAgICAgZGl2aXNvci5sb3cgPT09IC0xICYmIGRpdmlzb3IuaGlnaCA9PT0gLTEpIHtcclxuICAgICAgICAgICAgLy8gYmUgY29uc2lzdGVudCB3aXRoIG5vbi13YXNtIGNvZGUgcGF0aFxyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIGxvdyA9ICh0aGlzLnVuc2lnbmVkID8gd2FzbS5kaXZfdSA6IHdhc20uZGl2X3MpKFxyXG4gICAgICAgICAgICB0aGlzLmxvdyxcclxuICAgICAgICAgICAgdGhpcy5oaWdoLFxyXG4gICAgICAgICAgICBkaXZpc29yLmxvdyxcclxuICAgICAgICAgICAgZGl2aXNvci5oaWdoXHJcbiAgICAgICAgKTtcclxuICAgICAgICByZXR1cm4gZnJvbUJpdHMobG93LCB3YXNtLmdldF9oaWdoKCksIHRoaXMudW5zaWduZWQpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmlzWmVybygpKVxyXG4gICAgICAgIHJldHVybiB0aGlzLnVuc2lnbmVkID8gVVpFUk8gOiBaRVJPO1xyXG4gICAgdmFyIGFwcHJveCwgcmVtLCByZXM7XHJcbiAgICBpZiAoIXRoaXMudW5zaWduZWQpIHtcclxuICAgICAgICAvLyBUaGlzIHNlY3Rpb24gaXMgb25seSByZWxldmFudCBmb3Igc2lnbmVkIGxvbmdzIGFuZCBpcyBkZXJpdmVkIGZyb20gdGhlXHJcbiAgICAgICAgLy8gY2xvc3VyZSBsaWJyYXJ5IGFzIGEgd2hvbGUuXHJcbiAgICAgICAgaWYgKHRoaXMuZXEoTUlOX1ZBTFVFKSkge1xyXG4gICAgICAgICAgICBpZiAoZGl2aXNvci5lcShPTkUpIHx8IGRpdmlzb3IuZXEoTkVHX09ORSkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gTUlOX1ZBTFVFOyAgLy8gcmVjYWxsIHRoYXQgLU1JTl9WQUxVRSA9PSBNSU5fVkFMVUVcclxuICAgICAgICAgICAgZWxzZSBpZiAoZGl2aXNvci5lcShNSU5fVkFMVUUpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIE9ORTtcclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAvLyBBdCB0aGlzIHBvaW50LCB3ZSBoYXZlIHxvdGhlcnwgPj0gMiwgc28gfHRoaXMvb3RoZXJ8IDwgfE1JTl9WQUxVRXwuXHJcbiAgICAgICAgICAgICAgICB2YXIgaGFsZlRoaXMgPSB0aGlzLnNocigxKTtcclxuICAgICAgICAgICAgICAgIGFwcHJveCA9IGhhbGZUaGlzLmRpdihkaXZpc29yKS5zaGwoMSk7XHJcbiAgICAgICAgICAgICAgICBpZiAoYXBwcm94LmVxKFpFUk8pKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRpdmlzb3IuaXNOZWdhdGl2ZSgpID8gT05FIDogTkVHX09ORTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmVtID0gdGhpcy5zdWIoZGl2aXNvci5tdWwoYXBwcm94KSk7XHJcbiAgICAgICAgICAgICAgICAgICAgcmVzID0gYXBwcm94LmFkZChyZW0uZGl2KGRpdmlzb3IpKTtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIGlmIChkaXZpc29yLmVxKE1JTl9WQUxVRSkpXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnVuc2lnbmVkID8gVVpFUk8gOiBaRVJPO1xyXG4gICAgICAgIGlmICh0aGlzLmlzTmVnYXRpdmUoKSkge1xyXG4gICAgICAgICAgICBpZiAoZGl2aXNvci5pc05lZ2F0aXZlKCkpXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5uZWcoKS5kaXYoZGl2aXNvci5uZWcoKSk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm5lZygpLmRpdihkaXZpc29yKS5uZWcoKTtcclxuICAgICAgICB9IGVsc2UgaWYgKGRpdmlzb3IuaXNOZWdhdGl2ZSgpKVxyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kaXYoZGl2aXNvci5uZWcoKSkubmVnKCk7XHJcbiAgICAgICAgcmVzID0gWkVSTztcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gVGhlIGFsZ29yaXRobSBiZWxvdyBoYXMgbm90IGJlZW4gbWFkZSBmb3IgdW5zaWduZWQgbG9uZ3MuIEl0J3MgdGhlcmVmb3JlXHJcbiAgICAgICAgLy8gcmVxdWlyZWQgdG8gdGFrZSBzcGVjaWFsIGNhcmUgb2YgdGhlIE1TQiBwcmlvciB0byBydW5uaW5nIGl0LlxyXG4gICAgICAgIGlmICghZGl2aXNvci51bnNpZ25lZClcclxuICAgICAgICAgICAgZGl2aXNvciA9IGRpdmlzb3IudG9VbnNpZ25lZCgpO1xyXG4gICAgICAgIGlmIChkaXZpc29yLmd0KHRoaXMpKVxyXG4gICAgICAgICAgICByZXR1cm4gVVpFUk87XHJcbiAgICAgICAgaWYgKGRpdmlzb3IuZ3QodGhpcy5zaHJ1KDEpKSkgLy8gMTUgPj4+IDEgPSA3IDsgd2l0aCBkaXZpc29yID0gOCA7IHRydWVcclxuICAgICAgICAgICAgcmV0dXJuIFVPTkU7XHJcbiAgICAgICAgcmVzID0gVVpFUk87XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmVwZWF0IHRoZSBmb2xsb3dpbmcgdW50aWwgdGhlIHJlbWFpbmRlciBpcyBsZXNzIHRoYW4gb3RoZXI6ICBmaW5kIGFcclxuICAgIC8vIGZsb2F0aW5nLXBvaW50IHRoYXQgYXBwcm94aW1hdGVzIHJlbWFpbmRlciAvIG90aGVyICpmcm9tIGJlbG93KiwgYWRkIHRoaXNcclxuICAgIC8vIGludG8gdGhlIHJlc3VsdCwgYW5kIHN1YnRyYWN0IGl0IGZyb20gdGhlIHJlbWFpbmRlci4gIEl0IGlzIGNyaXRpY2FsIHRoYXRcclxuICAgIC8vIHRoZSBhcHByb3hpbWF0ZSB2YWx1ZSBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gdGhlIHJlYWwgdmFsdWUgc28gdGhhdCB0aGVcclxuICAgIC8vIHJlbWFpbmRlciBuZXZlciBiZWNvbWVzIG5lZ2F0aXZlLlxyXG4gICAgcmVtID0gdGhpcztcclxuICAgIHdoaWxlIChyZW0uZ3RlKGRpdmlzb3IpKSB7XHJcbiAgICAgICAgLy8gQXBwcm94aW1hdGUgdGhlIHJlc3VsdCBvZiBkaXZpc2lvbi4gVGhpcyBtYXkgYmUgYSBsaXR0bGUgZ3JlYXRlciBvclxyXG4gICAgICAgIC8vIHNtYWxsZXIgdGhhbiB0aGUgYWN0dWFsIHZhbHVlLlxyXG4gICAgICAgIGFwcHJveCA9IE1hdGgubWF4KDEsIE1hdGguZmxvb3IocmVtLnRvTnVtYmVyKCkgLyBkaXZpc29yLnRvTnVtYmVyKCkpKTtcclxuXHJcbiAgICAgICAgLy8gV2Ugd2lsbCB0d2VhayB0aGUgYXBwcm94aW1hdGUgcmVzdWx0IGJ5IGNoYW5naW5nIGl0IGluIHRoZSA0OC10aCBkaWdpdCBvclxyXG4gICAgICAgIC8vIHRoZSBzbWFsbGVzdCBub24tZnJhY3Rpb25hbCBkaWdpdCwgd2hpY2hldmVyIGlzIGxhcmdlci5cclxuICAgICAgICB2YXIgbG9nMiA9IE1hdGguY2VpbChNYXRoLmxvZyhhcHByb3gpIC8gTWF0aC5MTjIpLFxyXG4gICAgICAgICAgICBkZWx0YSA9IChsb2cyIDw9IDQ4KSA/IDEgOiBwb3dfZGJsKDIsIGxvZzIgLSA0OCksXHJcblxyXG4gICAgICAgIC8vIERlY3JlYXNlIHRoZSBhcHByb3hpbWF0aW9uIHVudGlsIGl0IGlzIHNtYWxsZXIgdGhhbiB0aGUgcmVtYWluZGVyLiAgTm90ZVxyXG4gICAgICAgIC8vIHRoYXQgaWYgaXQgaXMgdG9vIGxhcmdlLCB0aGUgcHJvZHVjdCBvdmVyZmxvd3MgYW5kIGlzIG5lZ2F0aXZlLlxyXG4gICAgICAgICAgICBhcHByb3hSZXMgPSBmcm9tTnVtYmVyKGFwcHJveCksXHJcbiAgICAgICAgICAgIGFwcHJveFJlbSA9IGFwcHJveFJlcy5tdWwoZGl2aXNvcik7XHJcbiAgICAgICAgd2hpbGUgKGFwcHJveFJlbS5pc05lZ2F0aXZlKCkgfHwgYXBwcm94UmVtLmd0KHJlbSkpIHtcclxuICAgICAgICAgICAgYXBwcm94IC09IGRlbHRhO1xyXG4gICAgICAgICAgICBhcHByb3hSZXMgPSBmcm9tTnVtYmVyKGFwcHJveCwgdGhpcy51bnNpZ25lZCk7XHJcbiAgICAgICAgICAgIGFwcHJveFJlbSA9IGFwcHJveFJlcy5tdWwoZGl2aXNvcik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBXZSBrbm93IHRoZSBhbnN3ZXIgY2FuJ3QgYmUgemVyby4uLiBhbmQgYWN0dWFsbHksIHplcm8gd291bGQgY2F1c2VcclxuICAgICAgICAvLyBpbmZpbml0ZSByZWN1cnNpb24gc2luY2Ugd2Ugd291bGQgbWFrZSBubyBwcm9ncmVzcy5cclxuICAgICAgICBpZiAoYXBwcm94UmVzLmlzWmVybygpKVxyXG4gICAgICAgICAgICBhcHByb3hSZXMgPSBPTkU7XHJcblxyXG4gICAgICAgIHJlcyA9IHJlcy5hZGQoYXBwcm94UmVzKTtcclxuICAgICAgICByZW0gPSByZW0uc3ViKGFwcHJveFJlbSk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcmVzO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhpcyBMb25nIGRpdmlkZWQgYnkgdGhlIHNwZWNpZmllZC4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgTG9uZyNkaXZpZGV9LlxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBkaXZpc29yIERpdmlzb3JcclxuICogQHJldHVybnMgeyFMb25nfSBRdW90aWVudFxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5kaXYgPSBMb25nUHJvdG90eXBlLmRpdmlkZTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoaXMgTG9uZyBtb2R1bG8gdGhlIHNwZWNpZmllZC5cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBkaXZpc29yIERpdmlzb3JcclxuICogQHJldHVybnMgeyFMb25nfSBSZW1haW5kZXJcclxuICovXHJcbkxvbmdQcm90b3R5cGUubW9kdWxvID0gZnVuY3Rpb24gbW9kdWxvKGRpdmlzb3IpIHtcclxuICAgIGlmICghaXNMb25nKGRpdmlzb3IpKVxyXG4gICAgICAgIGRpdmlzb3IgPSBmcm9tVmFsdWUoZGl2aXNvcik7XHJcblxyXG4gICAgLy8gdXNlIHdhc20gc3VwcG9ydCBpZiBwcmVzZW50XHJcbiAgICBpZiAod2FzbSkge1xyXG4gICAgICAgIHZhciBsb3cgPSAodGhpcy51bnNpZ25lZCA/IHdhc20ucmVtX3UgOiB3YXNtLnJlbV9zKShcclxuICAgICAgICAgICAgdGhpcy5sb3csXHJcbiAgICAgICAgICAgIHRoaXMuaGlnaCxcclxuICAgICAgICAgICAgZGl2aXNvci5sb3csXHJcbiAgICAgICAgICAgIGRpdmlzb3IuaGlnaFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgcmV0dXJuIGZyb21CaXRzKGxvdywgd2FzbS5nZXRfaGlnaCgpLCB0aGlzLnVuc2lnbmVkKTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdGhpcy5zdWIodGhpcy5kaXYoZGl2aXNvcikubXVsKGRpdmlzb3IpKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoaXMgTG9uZyBtb2R1bG8gdGhlIHNwZWNpZmllZC4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgTG9uZyNtb2R1bG99LlxyXG4gKiBAZnVuY3Rpb25cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBkaXZpc29yIERpdmlzb3JcclxuICogQHJldHVybnMgeyFMb25nfSBSZW1haW5kZXJcclxuICovXHJcbkxvbmdQcm90b3R5cGUubW9kID0gTG9uZ1Byb3RvdHlwZS5tb2R1bG87XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGlzIExvbmcgbW9kdWxvIHRoZSBzcGVjaWZpZWQuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjbW9kdWxvfS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gZGl2aXNvciBEaXZpc29yXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gUmVtYWluZGVyXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLnJlbSA9IExvbmdQcm90b3R5cGUubW9kdWxvO1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIGJpdHdpc2UgTk9UIG9mIHRoaXMgTG9uZy5cclxuICogQHJldHVybnMgeyFMb25nfVxyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5ub3QgPSBmdW5jdGlvbiBub3QoKSB7XHJcbiAgICByZXR1cm4gZnJvbUJpdHMofnRoaXMubG93LCB+dGhpcy5oaWdoLCB0aGlzLnVuc2lnbmVkKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoZSBiaXR3aXNlIEFORCBvZiB0aGlzIExvbmcgYW5kIHRoZSBzcGVjaWZpZWQuXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgTG9uZ1xyXG4gKiBAcmV0dXJucyB7IUxvbmd9XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLmFuZCA9IGZ1bmN0aW9uIGFuZChvdGhlcikge1xyXG4gICAgaWYgKCFpc0xvbmcob3RoZXIpKVxyXG4gICAgICAgIG90aGVyID0gZnJvbVZhbHVlKG90aGVyKTtcclxuICAgIHJldHVybiBmcm9tQml0cyh0aGlzLmxvdyAmIG90aGVyLmxvdywgdGhpcy5oaWdoICYgb3RoZXIuaGlnaCwgdGhpcy51bnNpZ25lZCk7XHJcbn07XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGUgYml0d2lzZSBPUiBvZiB0aGlzIExvbmcgYW5kIHRoZSBzcGVjaWZpZWQuXHJcbiAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgTG9uZ1xyXG4gKiBAcmV0dXJucyB7IUxvbmd9XHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLm9yID0gZnVuY3Rpb24gb3Iob3RoZXIpIHtcclxuICAgIGlmICghaXNMb25nKG90aGVyKSlcclxuICAgICAgICBvdGhlciA9IGZyb21WYWx1ZShvdGhlcik7XHJcbiAgICByZXR1cm4gZnJvbUJpdHModGhpcy5sb3cgfCBvdGhlci5sb3csIHRoaXMuaGlnaCB8IG90aGVyLmhpZ2gsIHRoaXMudW5zaWduZWQpO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIGJpdHdpc2UgWE9SIG9mIHRoaXMgTG9uZyBhbmQgdGhlIGdpdmVuIG9uZS5cclxuICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciBMb25nXHJcbiAqIEByZXR1cm5zIHshTG9uZ31cclxuICovXHJcbkxvbmdQcm90b3R5cGUueG9yID0gZnVuY3Rpb24geG9yKG90aGVyKSB7XHJcbiAgICBpZiAoIWlzTG9uZyhvdGhlcikpXHJcbiAgICAgICAgb3RoZXIgPSBmcm9tVmFsdWUob3RoZXIpO1xyXG4gICAgcmV0dXJuIGZyb21CaXRzKHRoaXMubG93IF4gb3RoZXIubG93LCB0aGlzLmhpZ2ggXiBvdGhlci5oaWdoLCB0aGlzLnVuc2lnbmVkKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoaXMgTG9uZyB3aXRoIGJpdHMgc2hpZnRlZCB0byB0aGUgbGVmdCBieSB0aGUgZ2l2ZW4gYW1vdW50LlxyXG4gKiBAcGFyYW0ge251bWJlcnwhTG9uZ30gbnVtQml0cyBOdW1iZXIgb2YgYml0c1xyXG4gKiBAcmV0dXJucyB7IUxvbmd9IFNoaWZ0ZWQgTG9uZ1xyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5zaGlmdExlZnQgPSBmdW5jdGlvbiBzaGlmdExlZnQobnVtQml0cykge1xyXG4gICAgaWYgKGlzTG9uZyhudW1CaXRzKSlcclxuICAgICAgICBudW1CaXRzID0gbnVtQml0cy50b0ludCgpO1xyXG4gICAgaWYgKChudW1CaXRzICY9IDYzKSA9PT0gMClcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIGVsc2UgaWYgKG51bUJpdHMgPCAzMilcclxuICAgICAgICByZXR1cm4gZnJvbUJpdHModGhpcy5sb3cgPDwgbnVtQml0cywgKHRoaXMuaGlnaCA8PCBudW1CaXRzKSB8ICh0aGlzLmxvdyA+Pj4gKDMyIC0gbnVtQml0cykpLCB0aGlzLnVuc2lnbmVkKTtcclxuICAgIGVsc2VcclxuICAgICAgICByZXR1cm4gZnJvbUJpdHMoMCwgdGhpcy5sb3cgPDwgKG51bUJpdHMgLSAzMiksIHRoaXMudW5zaWduZWQpO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhpcyBMb25nIHdpdGggYml0cyBzaGlmdGVkIHRvIHRoZSBsZWZ0IGJ5IHRoZSBnaXZlbiBhbW91bnQuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjc2hpZnRMZWZ0fS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7bnVtYmVyfCFMb25nfSBudW1CaXRzIE51bWJlciBvZiBiaXRzXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gU2hpZnRlZCBMb25nXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLnNobCA9IExvbmdQcm90b3R5cGUuc2hpZnRMZWZ0O1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhpcyBMb25nIHdpdGggYml0cyBhcml0aG1ldGljYWxseSBzaGlmdGVkIHRvIHRoZSByaWdodCBieSB0aGUgZ2l2ZW4gYW1vdW50LlxyXG4gKiBAcGFyYW0ge251bWJlcnwhTG9uZ30gbnVtQml0cyBOdW1iZXIgb2YgYml0c1xyXG4gKiBAcmV0dXJucyB7IUxvbmd9IFNoaWZ0ZWQgTG9uZ1xyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5zaGlmdFJpZ2h0ID0gZnVuY3Rpb24gc2hpZnRSaWdodChudW1CaXRzKSB7XHJcbiAgICBpZiAoaXNMb25nKG51bUJpdHMpKVxyXG4gICAgICAgIG51bUJpdHMgPSBudW1CaXRzLnRvSW50KCk7XHJcbiAgICBpZiAoKG51bUJpdHMgJj0gNjMpID09PSAwKVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgZWxzZSBpZiAobnVtQml0cyA8IDMyKVxyXG4gICAgICAgIHJldHVybiBmcm9tQml0cygodGhpcy5sb3cgPj4+IG51bUJpdHMpIHwgKHRoaXMuaGlnaCA8PCAoMzIgLSBudW1CaXRzKSksIHRoaXMuaGlnaCA+PiBudW1CaXRzLCB0aGlzLnVuc2lnbmVkKTtcclxuICAgIGVsc2VcclxuICAgICAgICByZXR1cm4gZnJvbUJpdHModGhpcy5oaWdoID4+IChudW1CaXRzIC0gMzIpLCB0aGlzLmhpZ2ggPj0gMCA/IDAgOiAtMSwgdGhpcy51bnNpZ25lZCk7XHJcbn07XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGlzIExvbmcgd2l0aCBiaXRzIGFyaXRobWV0aWNhbGx5IHNoaWZ0ZWQgdG8gdGhlIHJpZ2h0IGJ5IHRoZSBnaXZlbiBhbW91bnQuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjc2hpZnRSaWdodH0uXHJcbiAqIEBmdW5jdGlvblxyXG4gKiBAcGFyYW0ge251bWJlcnwhTG9uZ30gbnVtQml0cyBOdW1iZXIgb2YgYml0c1xyXG4gKiBAcmV0dXJucyB7IUxvbmd9IFNoaWZ0ZWQgTG9uZ1xyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5zaHIgPSBMb25nUHJvdG90eXBlLnNoaWZ0UmlnaHQ7XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGlzIExvbmcgd2l0aCBiaXRzIGxvZ2ljYWxseSBzaGlmdGVkIHRvIHRoZSByaWdodCBieSB0aGUgZ2l2ZW4gYW1vdW50LlxyXG4gKiBAcGFyYW0ge251bWJlcnwhTG9uZ30gbnVtQml0cyBOdW1iZXIgb2YgYml0c1xyXG4gKiBAcmV0dXJucyB7IUxvbmd9IFNoaWZ0ZWQgTG9uZ1xyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS5zaGlmdFJpZ2h0VW5zaWduZWQgPSBmdW5jdGlvbiBzaGlmdFJpZ2h0VW5zaWduZWQobnVtQml0cykge1xyXG4gICAgaWYgKGlzTG9uZyhudW1CaXRzKSlcclxuICAgICAgICBudW1CaXRzID0gbnVtQml0cy50b0ludCgpO1xyXG4gICAgbnVtQml0cyAmPSA2MztcclxuICAgIGlmIChudW1CaXRzID09PSAwKVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgZWxzZSB7XHJcbiAgICAgICAgdmFyIGhpZ2ggPSB0aGlzLmhpZ2g7XHJcbiAgICAgICAgaWYgKG51bUJpdHMgPCAzMikge1xyXG4gICAgICAgICAgICB2YXIgbG93ID0gdGhpcy5sb3c7XHJcbiAgICAgICAgICAgIHJldHVybiBmcm9tQml0cygobG93ID4+PiBudW1CaXRzKSB8IChoaWdoIDw8ICgzMiAtIG51bUJpdHMpKSwgaGlnaCA+Pj4gbnVtQml0cywgdGhpcy51bnNpZ25lZCk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChudW1CaXRzID09PSAzMilcclxuICAgICAgICAgICAgcmV0dXJuIGZyb21CaXRzKGhpZ2gsIDAsIHRoaXMudW5zaWduZWQpO1xyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgICAgcmV0dXJuIGZyb21CaXRzKGhpZ2ggPj4+IChudW1CaXRzIC0gMzIpLCAwLCB0aGlzLnVuc2lnbmVkKTtcclxuICAgIH1cclxufTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoaXMgTG9uZyB3aXRoIGJpdHMgbG9naWNhbGx5IHNoaWZ0ZWQgdG8gdGhlIHJpZ2h0IGJ5IHRoZSBnaXZlbiBhbW91bnQuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjc2hpZnRSaWdodFVuc2lnbmVkfS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7bnVtYmVyfCFMb25nfSBudW1CaXRzIE51bWJlciBvZiBiaXRzXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gU2hpZnRlZCBMb25nXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLnNocnUgPSBMb25nUHJvdG90eXBlLnNoaWZ0UmlnaHRVbnNpZ25lZDtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoaXMgTG9uZyB3aXRoIGJpdHMgbG9naWNhbGx5IHNoaWZ0ZWQgdG8gdGhlIHJpZ2h0IGJ5IHRoZSBnaXZlbiBhbW91bnQuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjc2hpZnRSaWdodFVuc2lnbmVkfS5cclxuICogQGZ1bmN0aW9uXHJcbiAqIEBwYXJhbSB7bnVtYmVyfCFMb25nfSBudW1CaXRzIE51bWJlciBvZiBiaXRzXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gU2hpZnRlZCBMb25nXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLnNocl91ID0gTG9uZ1Byb3RvdHlwZS5zaGlmdFJpZ2h0VW5zaWduZWQ7XHJcblxyXG4vKipcclxuICogQ29udmVydHMgdGhpcyBMb25nIHRvIHNpZ25lZC5cclxuICogQHJldHVybnMgeyFMb25nfSBTaWduZWQgbG9uZ1xyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS50b1NpZ25lZCA9IGZ1bmN0aW9uIHRvU2lnbmVkKCkge1xyXG4gICAgaWYgKCF0aGlzLnVuc2lnbmVkKVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgcmV0dXJuIGZyb21CaXRzKHRoaXMubG93LCB0aGlzLmhpZ2gsIGZhbHNlKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBDb252ZXJ0cyB0aGlzIExvbmcgdG8gdW5zaWduZWQuXHJcbiAqIEByZXR1cm5zIHshTG9uZ30gVW5zaWduZWQgbG9uZ1xyXG4gKi9cclxuTG9uZ1Byb3RvdHlwZS50b1Vuc2lnbmVkID0gZnVuY3Rpb24gdG9VbnNpZ25lZCgpIHtcclxuICAgIGlmICh0aGlzLnVuc2lnbmVkKVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgcmV0dXJuIGZyb21CaXRzKHRoaXMubG93LCB0aGlzLmhpZ2gsIHRydWUpO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIENvbnZlcnRzIHRoaXMgTG9uZyB0byBpdHMgYnl0ZSByZXByZXNlbnRhdGlvbi5cclxuICogQHBhcmFtIHtib29sZWFuPX0gbGUgV2hldGhlciBsaXR0bGUgb3IgYmlnIGVuZGlhbiwgZGVmYXVsdHMgdG8gYmlnIGVuZGlhblxyXG4gKiBAcmV0dXJucyB7IUFycmF5LjxudW1iZXI+fSBCeXRlIHJlcHJlc2VudGF0aW9uXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLnRvQnl0ZXMgPSBmdW5jdGlvbiB0b0J5dGVzKGxlKSB7XHJcbiAgICByZXR1cm4gbGUgPyB0aGlzLnRvQnl0ZXNMRSgpIDogdGhpcy50b0J5dGVzQkUoKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBDb252ZXJ0cyB0aGlzIExvbmcgdG8gaXRzIGxpdHRsZSBlbmRpYW4gYnl0ZSByZXByZXNlbnRhdGlvbi5cclxuICogQHJldHVybnMgeyFBcnJheS48bnVtYmVyPn0gTGl0dGxlIGVuZGlhbiBieXRlIHJlcHJlc2VudGF0aW9uXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLnRvQnl0ZXNMRSA9IGZ1bmN0aW9uIHRvQnl0ZXNMRSgpIHtcclxuICAgIHZhciBoaSA9IHRoaXMuaGlnaCxcclxuICAgICAgICBsbyA9IHRoaXMubG93O1xyXG4gICAgcmV0dXJuIFtcclxuICAgICAgICBsbyAgICAgICAgJiAweGZmLFxyXG4gICAgICAgIGxvID4+PiAgOCAmIDB4ZmYsXHJcbiAgICAgICAgbG8gPj4+IDE2ICYgMHhmZixcclxuICAgICAgICBsbyA+Pj4gMjQgICAgICAgLFxyXG4gICAgICAgIGhpICAgICAgICAmIDB4ZmYsXHJcbiAgICAgICAgaGkgPj4+ICA4ICYgMHhmZixcclxuICAgICAgICBoaSA+Pj4gMTYgJiAweGZmLFxyXG4gICAgICAgIGhpID4+PiAyNFxyXG4gICAgXTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBDb252ZXJ0cyB0aGlzIExvbmcgdG8gaXRzIGJpZyBlbmRpYW4gYnl0ZSByZXByZXNlbnRhdGlvbi5cclxuICogQHJldHVybnMgeyFBcnJheS48bnVtYmVyPn0gQmlnIGVuZGlhbiBieXRlIHJlcHJlc2VudGF0aW9uXHJcbiAqL1xyXG5Mb25nUHJvdG90eXBlLnRvQnl0ZXNCRSA9IGZ1bmN0aW9uIHRvQnl0ZXNCRSgpIHtcclxuICAgIHZhciBoaSA9IHRoaXMuaGlnaCxcclxuICAgICAgICBsbyA9IHRoaXMubG93O1xyXG4gICAgcmV0dXJuIFtcclxuICAgICAgICBoaSA+Pj4gMjQgICAgICAgLFxyXG4gICAgICAgIGhpID4+PiAxNiAmIDB4ZmYsXHJcbiAgICAgICAgaGkgPj4+ICA4ICYgMHhmZixcclxuICAgICAgICBoaSAgICAgICAgJiAweGZmLFxyXG4gICAgICAgIGxvID4+PiAyNCAgICAgICAsXHJcbiAgICAgICAgbG8gPj4+IDE2ICYgMHhmZixcclxuICAgICAgICBsbyA+Pj4gIDggJiAweGZmLFxyXG4gICAgICAgIGxvICAgICAgICAmIDB4ZmZcclxuICAgIF07XHJcbn07XHJcblxyXG4vKipcclxuICogQ3JlYXRlcyBhIExvbmcgZnJvbSBpdHMgYnl0ZSByZXByZXNlbnRhdGlvbi5cclxuICogQHBhcmFtIHshQXJyYXkuPG51bWJlcj59IGJ5dGVzIEJ5dGUgcmVwcmVzZW50YXRpb25cclxuICogQHBhcmFtIHtib29sZWFuPX0gdW5zaWduZWQgV2hldGhlciB1bnNpZ25lZCBvciBub3QsIGRlZmF1bHRzIHRvIHNpZ25lZFxyXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSBsZSBXaGV0aGVyIGxpdHRsZSBvciBiaWcgZW5kaWFuLCBkZWZhdWx0cyB0byBiaWcgZW5kaWFuXHJcbiAqIEByZXR1cm5zIHtMb25nfSBUaGUgY29ycmVzcG9uZGluZyBMb25nIHZhbHVlXHJcbiAqL1xyXG5Mb25nLmZyb21CeXRlcyA9IGZ1bmN0aW9uIGZyb21CeXRlcyhieXRlcywgdW5zaWduZWQsIGxlKSB7XHJcbiAgICByZXR1cm4gbGUgPyBMb25nLmZyb21CeXRlc0xFKGJ5dGVzLCB1bnNpZ25lZCkgOiBMb25nLmZyb21CeXRlc0JFKGJ5dGVzLCB1bnNpZ25lZCk7XHJcbn07XHJcblxyXG4vKipcclxuICogQ3JlYXRlcyBhIExvbmcgZnJvbSBpdHMgbGl0dGxlIGVuZGlhbiBieXRlIHJlcHJlc2VudGF0aW9uLlxyXG4gKiBAcGFyYW0geyFBcnJheS48bnVtYmVyPn0gYnl0ZXMgTGl0dGxlIGVuZGlhbiBieXRlIHJlcHJlc2VudGF0aW9uXHJcbiAqIEBwYXJhbSB7Ym9vbGVhbj19IHVuc2lnbmVkIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LCBkZWZhdWx0cyB0byBzaWduZWRcclxuICogQHJldHVybnMge0xvbmd9IFRoZSBjb3JyZXNwb25kaW5nIExvbmcgdmFsdWVcclxuICovXHJcbkxvbmcuZnJvbUJ5dGVzTEUgPSBmdW5jdGlvbiBmcm9tQnl0ZXNMRShieXRlcywgdW5zaWduZWQpIHtcclxuICAgIHJldHVybiBuZXcgTG9uZyhcclxuICAgICAgICBieXRlc1swXSAgICAgICB8XHJcbiAgICAgICAgYnl0ZXNbMV0gPDwgIDggfFxyXG4gICAgICAgIGJ5dGVzWzJdIDw8IDE2IHxcclxuICAgICAgICBieXRlc1szXSA8PCAyNCxcclxuICAgICAgICBieXRlc1s0XSAgICAgICB8XHJcbiAgICAgICAgYnl0ZXNbNV0gPDwgIDggfFxyXG4gICAgICAgIGJ5dGVzWzZdIDw8IDE2IHxcclxuICAgICAgICBieXRlc1s3XSA8PCAyNCxcclxuICAgICAgICB1bnNpZ25lZFxyXG4gICAgKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBDcmVhdGVzIGEgTG9uZyBmcm9tIGl0cyBiaWcgZW5kaWFuIGJ5dGUgcmVwcmVzZW50YXRpb24uXHJcbiAqIEBwYXJhbSB7IUFycmF5LjxudW1iZXI+fSBieXRlcyBCaWcgZW5kaWFuIGJ5dGUgcmVwcmVzZW50YXRpb25cclxuICogQHBhcmFtIHtib29sZWFuPX0gdW5zaWduZWQgV2hldGhlciB1bnNpZ25lZCBvciBub3QsIGRlZmF1bHRzIHRvIHNpZ25lZFxyXG4gKiBAcmV0dXJucyB7TG9uZ30gVGhlIGNvcnJlc3BvbmRpbmcgTG9uZyB2YWx1ZVxyXG4gKi9cclxuTG9uZy5mcm9tQnl0ZXNCRSA9IGZ1bmN0aW9uIGZyb21CeXRlc0JFKGJ5dGVzLCB1bnNpZ25lZCkge1xyXG4gICAgcmV0dXJuIG5ldyBMb25nKFxyXG4gICAgICAgIGJ5dGVzWzRdIDw8IDI0IHxcclxuICAgICAgICBieXRlc1s1XSA8PCAxNiB8XHJcbiAgICAgICAgYnl0ZXNbNl0gPDwgIDggfFxyXG4gICAgICAgIGJ5dGVzWzddLFxyXG4gICAgICAgIGJ5dGVzWzBdIDw8IDI0IHxcclxuICAgICAgICBieXRlc1sxXSA8PCAxNiB8XHJcbiAgICAgICAgYnl0ZXNbMl0gPDwgIDggfFxyXG4gICAgICAgIGJ5dGVzWzNdLFxyXG4gICAgICAgIHVuc2lnbmVkXHJcbiAgICApO1xyXG59O1xyXG4iLCIvKmVzbGludC1kaXNhYmxlIGJsb2NrLXNjb3BlZC12YXIsIGlkLWxlbmd0aCwgbm8tY29udHJvbC1yZWdleCwgbm8tbWFnaWMtbnVtYmVycywgbm8tcHJvdG90eXBlLWJ1aWx0aW5zLCBuby1yZWRlY2xhcmUsIG5vLXNoYWRvdywgbm8tdmFyLCBzb3J0LXZhcnMqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciAkcHJvdG9idWYgPSByZXF1aXJlKFwicHJvdG9idWZqcy9taW5pbWFsXCIpO1xuXG4vLyBDb21tb24gYWxpYXNlc1xudmFyICRSZWFkZXIgPSAkcHJvdG9idWYuUmVhZGVyLCAkV3JpdGVyID0gJHByb3RvYnVmLldyaXRlciwgJHV0aWwgPSAkcHJvdG9idWYudXRpbDtcblxuLy8gRXhwb3J0ZWQgcm9vdCBuYW1lc3BhY2VcbnZhciAkcm9vdCA9ICRwcm90b2J1Zi5yb290c1tcImRlZmF1bHRcIl0gfHwgKCRwcm90b2J1Zi5yb290c1tcImRlZmF1bHRcIl0gPSB7fSk7XG5cbiRyb290Lm9ubnggPSAoZnVuY3Rpb24oKSB7XG5cbiAgICAvKipcbiAgICAgKiBOYW1lc3BhY2Ugb25ueC5cbiAgICAgKiBAZXhwb3J0cyBvbm54XG4gICAgICogQG5hbWVzcGFjZVxuICAgICAqL1xuICAgIHZhciBvbm54ID0ge307XG5cbiAgICAvKipcbiAgICAgKiBWZXJzaW9uIGVudW0uXG4gICAgICogQG5hbWUgb25ueC5WZXJzaW9uXG4gICAgICogQGVudW0ge3N0cmluZ31cbiAgICAgKiBAcHJvcGVydHkge251bWJlcn0gX1NUQVJUX1ZFUlNJT049MCBfU1RBUlRfVkVSU0lPTiB2YWx1ZVxuICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBJUl9WRVJTSU9OXzIwMTdfMTBfMTA9MSBJUl9WRVJTSU9OXzIwMTdfMTBfMTAgdmFsdWVcbiAgICAgKiBAcHJvcGVydHkge251bWJlcn0gSVJfVkVSU0lPTl8yMDE3XzEwXzMwPTIgSVJfVkVSU0lPTl8yMDE3XzEwXzMwIHZhbHVlXG4gICAgICogQHByb3BlcnR5IHtudW1iZXJ9IElSX1ZFUlNJT05fMjAxN18xMV8zPTMgSVJfVkVSU0lPTl8yMDE3XzExXzMgdmFsdWVcbiAgICAgKiBAcHJvcGVydHkge251bWJlcn0gSVJfVkVSU0lPTl8yMDE5XzFfMjI9NCBJUl9WRVJTSU9OXzIwMTlfMV8yMiB2YWx1ZVxuICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBJUl9WRVJTSU9OPTUgSVJfVkVSU0lPTiB2YWx1ZVxuICAgICAqL1xuICAgIG9ubnguVmVyc2lvbiA9IChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHZhbHVlc0J5SWQgPSB7fSwgdmFsdWVzID0gT2JqZWN0LmNyZWF0ZSh2YWx1ZXNCeUlkKTtcbiAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbMF0gPSBcIl9TVEFSVF9WRVJTSU9OXCJdID0gMDtcbiAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbMV0gPSBcIklSX1ZFUlNJT05fMjAxN18xMF8xMFwiXSA9IDE7XG4gICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzJdID0gXCJJUl9WRVJTSU9OXzIwMTdfMTBfMzBcIl0gPSAyO1xuICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFszXSA9IFwiSVJfVkVSU0lPTl8yMDE3XzExXzNcIl0gPSAzO1xuICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFs0XSA9IFwiSVJfVkVSU0lPTl8yMDE5XzFfMjJcIl0gPSA0O1xuICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFs1XSA9IFwiSVJfVkVSU0lPTlwiXSA9IDU7XG4gICAgICAgIHJldHVybiB2YWx1ZXM7XG4gICAgfSkoKTtcblxuICAgIG9ubnguQXR0cmlidXRlUHJvdG8gPSAoZnVuY3Rpb24oKSB7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFByb3BlcnRpZXMgb2YgYW4gQXR0cmlidXRlUHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBpbnRlcmZhY2UgSUF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtuYW1lXSBBdHRyaWJ1dGVQcm90byBuYW1lXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtyZWZBdHRyTmFtZV0gQXR0cmlidXRlUHJvdG8gcmVmQXR0ck5hbWVcbiAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gW2RvY1N0cmluZ10gQXR0cmlidXRlUHJvdG8gZG9jU3RyaW5nXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7b25ueC5BdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlfG51bGx9IFt0eXBlXSBBdHRyaWJ1dGVQcm90byB0eXBlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfG51bGx9IFtmXSBBdHRyaWJ1dGVQcm90byBmXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfExvbmd8bnVsbH0gW2ldIEF0dHJpYnV0ZVByb3RvIGlcbiAgICAgICAgICogQHByb3BlcnR5IHtVaW50OEFycmF5fG51bGx9IFtzXSBBdHRyaWJ1dGVQcm90byBzXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7b25ueC5JVGVuc29yUHJvdG98bnVsbH0gW3RdIEF0dHJpYnV0ZVByb3RvIHRcbiAgICAgICAgICogQHByb3BlcnR5IHtvbm54LklHcmFwaFByb3RvfG51bGx9IFtnXSBBdHRyaWJ1dGVQcm90byBnXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPG51bWJlcj58bnVsbH0gW2Zsb2F0c10gQXR0cmlidXRlUHJvdG8gZmxvYXRzXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPG51bWJlcnxMb25nPnxudWxsfSBbaW50c10gQXR0cmlidXRlUHJvdG8gaW50c1xuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5LjxVaW50OEFycmF5PnxudWxsfSBbc3RyaW5nc10gQXR0cmlidXRlUHJvdG8gc3RyaW5nc1xuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5Ljxvbm54LklUZW5zb3JQcm90bz58bnVsbH0gW3RlbnNvcnNdIEF0dHJpYnV0ZVByb3RvIHRlbnNvcnNcbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48b25ueC5JR3JhcGhQcm90bz58bnVsbH0gW2dyYXBoc10gQXR0cmlidXRlUHJvdG8gZ3JhcGhzXG4gICAgICAgICAqL1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IEF0dHJpYnV0ZVByb3RvLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAY2xhc3NkZXNjIFJlcHJlc2VudHMgYW4gQXR0cmlidXRlUHJvdG8uXG4gICAgICAgICAqIEBpbXBsZW1lbnRzIElBdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklBdHRyaWJ1dGVQcm90bz19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gQXR0cmlidXRlUHJvdG8ocHJvcGVydGllcykge1xuICAgICAgICAgICAgdGhpcy5mbG9hdHMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuaW50cyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5zdHJpbmdzID0gW107XG4gICAgICAgICAgICB0aGlzLnRlbnNvcnMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuZ3JhcGhzID0gW107XG4gICAgICAgICAgICBpZiAocHJvcGVydGllcylcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyksIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXNba2V5c1tpXV0gIT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNba2V5c1tpXV0gPSBwcm9wZXJ0aWVzW2tleXNbaV1dO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEF0dHJpYnV0ZVByb3RvIG5hbWUuXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gbmFtZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLnByb3RvdHlwZS5uYW1lID0gXCJcIjtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQXR0cmlidXRlUHJvdG8gcmVmQXR0ck5hbWUuXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gcmVmQXR0ck5hbWVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBBdHRyaWJ1dGVQcm90by5wcm90b3R5cGUucmVmQXR0ck5hbWUgPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBdHRyaWJ1dGVQcm90byBkb2NTdHJpbmcuXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gZG9jU3RyaW5nXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8ucHJvdG90eXBlLmRvY1N0cmluZyA9IFwiXCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEF0dHJpYnV0ZVByb3RvIHR5cGUuXG4gICAgICAgICAqIEBtZW1iZXIge29ubnguQXR0cmlidXRlUHJvdG8uQXR0cmlidXRlVHlwZX0gdHlwZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLnByb3RvdHlwZS50eXBlID0gMDtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQXR0cmlidXRlUHJvdG8gZi5cbiAgICAgICAgICogQG1lbWJlciB7bnVtYmVyfSBmXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8ucHJvdG90eXBlLmYgPSAwO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBdHRyaWJ1dGVQcm90byBpLlxuICAgICAgICAgKiBAbWVtYmVyIHtudW1iZXJ8TG9uZ30gaVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLnByb3RvdHlwZS5pID0gJHV0aWwuTG9uZyA/ICR1dGlsLkxvbmcuZnJvbUJpdHMoMCwwLGZhbHNlKSA6IDA7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEF0dHJpYnV0ZVByb3RvIHMuXG4gICAgICAgICAqIEBtZW1iZXIge1VpbnQ4QXJyYXl9IHNcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBBdHRyaWJ1dGVQcm90by5wcm90b3R5cGUucyA9ICR1dGlsLm5ld0J1ZmZlcihbXSk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEF0dHJpYnV0ZVByb3RvIHQuXG4gICAgICAgICAqIEBtZW1iZXIge29ubnguSVRlbnNvclByb3RvfG51bGx8dW5kZWZpbmVkfSB0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8ucHJvdG90eXBlLnQgPSBudWxsO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBdHRyaWJ1dGVQcm90byBnLlxuICAgICAgICAgKiBAbWVtYmVyIHtvbm54LklHcmFwaFByb3RvfG51bGx8dW5kZWZpbmVkfSBnXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8ucHJvdG90eXBlLmcgPSBudWxsO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBdHRyaWJ1dGVQcm90byBmbG9hdHMuXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5LjxudW1iZXI+fSBmbG9hdHNcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBBdHRyaWJ1dGVQcm90by5wcm90b3R5cGUuZmxvYXRzID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQXR0cmlidXRlUHJvdG8gaW50cy5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG51bWJlcnxMb25nPn0gaW50c1xuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLnByb3RvdHlwZS5pbnRzID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQXR0cmlidXRlUHJvdG8gc3RyaW5ncy5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPFVpbnQ4QXJyYXk+fSBzdHJpbmdzXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8ucHJvdG90eXBlLnN0cmluZ3MgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBdHRyaWJ1dGVQcm90byB0ZW5zb3JzLlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48b25ueC5JVGVuc29yUHJvdG8+fSB0ZW5zb3JzXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8ucHJvdG90eXBlLnRlbnNvcnMgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBBdHRyaWJ1dGVQcm90byBncmFwaHMuXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5Ljxvbm54LklHcmFwaFByb3RvPn0gZ3JhcGhzXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8ucHJvdG90eXBlLmdyYXBocyA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBuZXcgQXR0cmlidXRlUHJvdG8gaW5zdGFuY2UgdXNpbmcgdGhlIHNwZWNpZmllZCBwcm9wZXJ0aWVzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gY3JlYXRlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklBdHRyaWJ1dGVQcm90bz19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5BdHRyaWJ1dGVQcm90b30gQXR0cmlidXRlUHJvdG8gaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEF0dHJpYnV0ZVByb3RvKHByb3BlcnRpZXMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmNvZGVzIHRoZSBzcGVjaWZpZWQgQXR0cmlidXRlUHJvdG8gbWVzc2FnZS4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5BdHRyaWJ1dGVQcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JQXR0cmlidXRlUHJvdG99IG1lc3NhZ2UgQXR0cmlidXRlUHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBBdHRyaWJ1dGVQcm90by5lbmNvZGUgPSBmdW5jdGlvbiBlbmNvZGUobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICBpZiAoIXdyaXRlcilcbiAgICAgICAgICAgICAgICB3cml0ZXIgPSAkV3JpdGVyLmNyZWF0ZSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJuYW1lXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMSwgd2lyZVR5cGUgMiA9Ki8xMCkuc3RyaW5nKG1lc3NhZ2UubmFtZSk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5mICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImZcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAyLCB3aXJlVHlwZSA1ID0qLzIxKS5mbG9hdChtZXNzYWdlLmYpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJpXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMywgd2lyZVR5cGUgMCA9Ki8yNCkuaW50NjQobWVzc2FnZS5pKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnMgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwic1wiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDQsIHdpcmVUeXBlIDIgPSovMzQpLmJ5dGVzKG1lc3NhZ2Uucyk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50ICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInRcIikpXG4gICAgICAgICAgICAgICAgJHJvb3Qub25ueC5UZW5zb3JQcm90by5lbmNvZGUobWVzc2FnZS50LCB3cml0ZXIudWludDMyKC8qIGlkIDUsIHdpcmVUeXBlIDIgPSovNDIpLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5nICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImdcIikpXG4gICAgICAgICAgICAgICAgJHJvb3Qub25ueC5HcmFwaFByb3RvLmVuY29kZShtZXNzYWdlLmcsIHdyaXRlci51aW50MzIoLyogaWQgNiwgd2lyZVR5cGUgMiA9Ki81MCkuZm9yaygpKS5sZGVsaW0oKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmZsb2F0cyAhPSBudWxsICYmIG1lc3NhZ2UuZmxvYXRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgNywgd2lyZVR5cGUgMiA9Ki81OCkuZm9yaygpO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5mbG9hdHMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci5mbG9hdChtZXNzYWdlLmZsb2F0c1tpXSk7XG4gICAgICAgICAgICAgICAgd3JpdGVyLmxkZWxpbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW50cyAhPSBudWxsICYmIG1lc3NhZ2UuaW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDgsIHdpcmVUeXBlIDIgPSovNjYpLmZvcmsoKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuaW50cy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLmludDY0KG1lc3NhZ2UuaW50c1tpXSk7XG4gICAgICAgICAgICAgICAgd3JpdGVyLmxkZWxpbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uuc3RyaW5ncyAhPSBudWxsICYmIG1lc3NhZ2Uuc3RyaW5ncy5sZW5ndGgpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLnN0cmluZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgOSwgd2lyZVR5cGUgMiA9Ki83NCkuYnl0ZXMobWVzc2FnZS5zdHJpbmdzW2ldKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnRlbnNvcnMgIT0gbnVsbCAmJiBtZXNzYWdlLnRlbnNvcnMubGVuZ3RoKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS50ZW5zb3JzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICAkcm9vdC5vbm54LlRlbnNvclByb3RvLmVuY29kZShtZXNzYWdlLnRlbnNvcnNbaV0sIHdyaXRlci51aW50MzIoLyogaWQgMTAsIHdpcmVUeXBlIDIgPSovODIpLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5ncmFwaHMgIT0gbnVsbCAmJiBtZXNzYWdlLmdyYXBocy5sZW5ndGgpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmdyYXBocy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgJHJvb3Qub25ueC5HcmFwaFByb3RvLmVuY29kZShtZXNzYWdlLmdyYXBoc1tpXSwgd3JpdGVyLnVpbnQzMigvKiBpZCAxMSwgd2lyZVR5cGUgMiA9Ki85MCkuZm9yaygpKS5sZGVsaW0oKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvY1N0cmluZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb2NTdHJpbmdcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAxMywgd2lyZVR5cGUgMiA9Ki8xMDYpLnN0cmluZyhtZXNzYWdlLmRvY1N0cmluZyk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50eXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInR5cGVcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAyMCwgd2lyZVR5cGUgMCA9Ki8xNjApLmludDMyKG1lc3NhZ2UudHlwZSk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5yZWZBdHRyTmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJyZWZBdHRyTmFtZVwiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDIxLCB3aXJlVHlwZSAyID0qLzE3MCkuc3RyaW5nKG1lc3NhZ2UucmVmQXR0ck5hbWUpO1xuICAgICAgICAgICAgcmV0dXJuIHdyaXRlcjtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIEF0dHJpYnV0ZVByb3RvIG1lc3NhZ2UsIGxlbmd0aCBkZWxpbWl0ZWQuIERvZXMgbm90IGltcGxpY2l0bHkge0BsaW5rIG9ubnguQXR0cmlidXRlUHJvdG8udmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSUF0dHJpYnV0ZVByb3RvfSBtZXNzYWdlIEF0dHJpYnV0ZVByb3RvIG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5Xcml0ZXJ9IFt3cml0ZXJdIFdyaXRlciB0byBlbmNvZGUgdG9cbiAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8uZW5jb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikubGRlbGltKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYW4gQXR0cmlidXRlUHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlci5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5BdHRyaWJ1dGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aF0gTWVzc2FnZSBsZW5ndGggaWYga25vd24gYmVmb3JlaGFuZFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5BdHRyaWJ1dGVQcm90b30gQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBBdHRyaWJ1dGVQcm90by5kZWNvZGUgPSBmdW5jdGlvbiBkZWNvZGUocmVhZGVyLCBsZW5ndGgpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9ICRSZWFkZXIuY3JlYXRlKHJlYWRlcik7XG4gICAgICAgICAgICB2YXIgZW5kID0gbGVuZ3RoID09PSB1bmRlZmluZWQgPyByZWFkZXIubGVuIDogcmVhZGVyLnBvcyArIGxlbmd0aCwgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LkF0dHJpYnV0ZVByb3RvKCk7XG4gICAgICAgICAgICB3aGlsZSAocmVhZGVyLnBvcyA8IGVuZCkge1xuICAgICAgICAgICAgICAgIHZhciB0YWcgPSByZWFkZXIudWludDMyKCk7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0YWcgPj4+IDMpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UubmFtZSA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyMTpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5yZWZBdHRyTmFtZSA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAxMzpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kb2NTdHJpbmcgPSByZWFkZXIuc3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjA6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UudHlwZSA9IHJlYWRlci5pbnQzMigpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZiA9IHJlYWRlci5mbG9hdCgpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaSA9IHJlYWRlci5pbnQ2NCgpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UucyA9IHJlYWRlci5ieXRlcygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UudCA9ICRyb290Lm9ubnguVGVuc29yUHJvdG8uZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmcgPSAkcm9vdC5vbm54LkdyYXBoUHJvdG8uZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA3OlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLmZsb2F0cyAmJiBtZXNzYWdlLmZsb2F0cy5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5mbG9hdHMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCh0YWcgJiA3KSA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVuZDIgPSByZWFkZXIudWludDMyKCkgKyByZWFkZXIucG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZmxvYXRzLnB1c2gocmVhZGVyLmZsb2F0KCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZmxvYXRzLnB1c2gocmVhZGVyLmZsb2F0KCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDg6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2UuaW50cyAmJiBtZXNzYWdlLmludHMubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW50cyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHRhZyAmIDcpID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZW5kMiA9IHJlYWRlci51aW50MzIoKSArIHJlYWRlci5wb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAocmVhZGVyLnBvcyA8IGVuZDIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pbnRzLnB1c2gocmVhZGVyLmludDY0KCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW50cy5wdXNoKHJlYWRlci5pbnQ2NCgpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA5OlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLnN0cmluZ3MgJiYgbWVzc2FnZS5zdHJpbmdzLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnN0cmluZ3MgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5zdHJpbmdzLnB1c2gocmVhZGVyLmJ5dGVzKCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDEwOlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLnRlbnNvcnMgJiYgbWVzc2FnZS50ZW5zb3JzLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnRlbnNvcnMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS50ZW5zb3JzLnB1c2goJHJvb3Qub25ueC5UZW5zb3JQcm90by5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAxMTpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5ncmFwaHMgJiYgbWVzc2FnZS5ncmFwaHMubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZ3JhcGhzID0gW107XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZ3JhcGhzLnB1c2goJHJvb3Qub25ueC5HcmFwaFByb3RvLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZWFkZXIuc2tpcFR5cGUodGFnICYgNyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGFuIEF0dHJpYnV0ZVByb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIsIGxlbmd0aCBkZWxpbWl0ZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHJldHVybnMge29ubnguQXR0cmlidXRlUHJvdG99IEF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8uZGVjb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkKHJlYWRlcikge1xuICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgcmVhZGVyID0gbmV3ICRSZWFkZXIocmVhZGVyKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFZlcmlmaWVzIGFuIEF0dHJpYnV0ZVByb3RvIG1lc3NhZ2UuXG4gICAgICAgICAqIEBmdW5jdGlvbiB2ZXJpZnlcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBtZXNzYWdlIFBsYWluIG9iamVjdCB0byB2ZXJpZnlcbiAgICAgICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfSBgbnVsbGAgaWYgdmFsaWQsIG90aGVyd2lzZSB0aGUgcmVhc29uIHdoeSBpdCBpcyBub3RcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLnZlcmlmeSA9IGZ1bmN0aW9uIHZlcmlmeShtZXNzYWdlKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgIT09IFwib2JqZWN0XCIgfHwgbWVzc2FnZSA9PT0gbnVsbClcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJvYmplY3QgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwibmFtZVwiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UubmFtZSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm5hbWU6IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucmVmQXR0ck5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwicmVmQXR0ck5hbWVcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLnJlZkF0dHJOYW1lKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwicmVmQXR0ck5hbWU6IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9jU3RyaW5nICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvY1N0cmluZ1wiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UuZG9jU3RyaW5nKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZG9jU3RyaW5nOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnR5cGUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidHlwZVwiKSlcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKG1lc3NhZ2UudHlwZSkge1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInR5cGU6IGVudW0gdmFsdWUgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgY2FzZSA3OlxuICAgICAgICAgICAgICAgIGNhc2UgODpcbiAgICAgICAgICAgICAgICBjYXNlIDk6XG4gICAgICAgICAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJmXCIpKVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZS5mICE9PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJmOiBudW1iZXIgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmkgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiaVwiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmkpICYmICEobWVzc2FnZS5pICYmICR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmkubG93KSAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5pLmhpZ2gpKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiaTogaW50ZWdlcnxMb25nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5zICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInNcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5zICYmIHR5cGVvZiBtZXNzYWdlLnMubGVuZ3RoID09PSBcIm51bWJlclwiIHx8ICR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UucykpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJzOiBidWZmZXIgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnQgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidFwiKSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnJvciA9ICRyb290Lm9ubnguVGVuc29yUHJvdG8udmVyaWZ5KG1lc3NhZ2UudCk7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJ0LlwiICsgZXJyb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5nICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImdcIikpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXJyb3IgPSAkcm9vdC5vbm54LkdyYXBoUHJvdG8udmVyaWZ5KG1lc3NhZ2UuZyk7XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJnLlwiICsgZXJyb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5mbG9hdHMgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZmxvYXRzXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UuZmxvYXRzKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZmxvYXRzOiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5mbG9hdHMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZS5mbG9hdHNbaV0gIT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJmbG9hdHM6IG51bWJlcltdIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pbnRzICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImludHNcIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS5pbnRzKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiaW50czogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuaW50cy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5pbnRzW2ldKSAmJiAhKG1lc3NhZ2UuaW50c1tpXSAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5pbnRzW2ldLmxvdykgJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuaW50c1tpXS5oaWdoKSkpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJpbnRzOiBpbnRlZ2VyfExvbmdbXSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uuc3RyaW5ncyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJzdHJpbmdzXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2Uuc3RyaW5ncykpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInN0cmluZ3M6IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLnN0cmluZ3MubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2Uuc3RyaW5nc1tpXSAmJiB0eXBlb2YgbWVzc2FnZS5zdHJpbmdzW2ldLmxlbmd0aCA9PT0gXCJudW1iZXJcIiB8fCAkdXRpbC5pc1N0cmluZyhtZXNzYWdlLnN0cmluZ3NbaV0pKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcInN0cmluZ3M6IGJ1ZmZlcltdIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50ZW5zb3JzICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInRlbnNvcnNcIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS50ZW5zb3JzKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwidGVuc29yczogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UudGVuc29ycy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXJyb3IgPSAkcm9vdC5vbm54LlRlbnNvclByb3RvLnZlcmlmeShtZXNzYWdlLnRlbnNvcnNbaV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJ0ZW5zb3JzLlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZ3JhcGhzICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImdyYXBoc1wiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLmdyYXBocykpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImdyYXBoczogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuZ3JhcGhzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlcnJvciA9ICRyb290Lm9ubnguR3JhcGhQcm90by52ZXJpZnkobWVzc2FnZS5ncmFwaHNbaV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJncmFwaHMuXCIgKyBlcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhbiBBdHRyaWJ1dGVQcm90byBtZXNzYWdlIGZyb20gYSBwbGFpbiBvYmplY3QuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIHRoZWlyIHJlc3BlY3RpdmUgaW50ZXJuYWwgdHlwZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBmcm9tT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gb2JqZWN0IFBsYWluIG9iamVjdFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5BdHRyaWJ1dGVQcm90b30gQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLmZyb21PYmplY3QgPSBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICAgICAgaWYgKG9iamVjdCBpbnN0YW5jZW9mICRyb290Lm9ubnguQXR0cmlidXRlUHJvdG8pXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgICAgIHZhciBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguQXR0cmlidXRlUHJvdG8oKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QubmFtZSAhPSBudWxsKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UubmFtZSA9IFN0cmluZyhvYmplY3QubmFtZSk7XG4gICAgICAgICAgICBpZiAob2JqZWN0LnJlZkF0dHJOYW1lICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5yZWZBdHRyTmFtZSA9IFN0cmluZyhvYmplY3QucmVmQXR0ck5hbWUpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5kb2NTdHJpbmcgIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmRvY1N0cmluZyA9IFN0cmluZyhvYmplY3QuZG9jU3RyaW5nKTtcbiAgICAgICAgICAgIHN3aXRjaCAob2JqZWN0LnR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgXCJVTkRFRklORURcIjpcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICBtZXNzYWdlLnR5cGUgPSAwO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcIkZMT0FUXCI6XG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgbWVzc2FnZS50eXBlID0gMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJJTlRcIjpcbiAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICBtZXNzYWdlLnR5cGUgPSAyO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcIlNUUklOR1wiOlxuICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgIG1lc3NhZ2UudHlwZSA9IDM7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiVEVOU09SXCI6XG4gICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgbWVzc2FnZS50eXBlID0gNDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJHUkFQSFwiOlxuICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgIG1lc3NhZ2UudHlwZSA9IDU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwiRkxPQVRTXCI6XG4gICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgbWVzc2FnZS50eXBlID0gNjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJJTlRTXCI6XG4gICAgICAgICAgICBjYXNlIDc6XG4gICAgICAgICAgICAgICAgbWVzc2FnZS50eXBlID0gNztcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJTVFJJTkdTXCI6XG4gICAgICAgICAgICBjYXNlIDg6XG4gICAgICAgICAgICAgICAgbWVzc2FnZS50eXBlID0gODtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJURU5TT1JTXCI6XG4gICAgICAgICAgICBjYXNlIDk6XG4gICAgICAgICAgICAgICAgbWVzc2FnZS50eXBlID0gOTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJHUkFQSFNcIjpcbiAgICAgICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgICAgICAgbWVzc2FnZS50eXBlID0gMTA7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LmYgIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmYgPSBOdW1iZXIob2JqZWN0LmYpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5pICE9IG51bGwpXG4gICAgICAgICAgICAgICAgaWYgKCR1dGlsLkxvbmcpXG4gICAgICAgICAgICAgICAgICAgIChtZXNzYWdlLmkgPSAkdXRpbC5Mb25nLmZyb21WYWx1ZShvYmplY3QuaSkpLnVuc2lnbmVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5pID09PSBcInN0cmluZ1wiKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmkgPSBwYXJzZUludChvYmplY3QuaSwgMTApO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QuaSA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pID0gb2JqZWN0Lmk7XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5pID09PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmkgPSBuZXcgJHV0aWwuTG9uZ0JpdHMob2JqZWN0LmkubG93ID4+PiAwLCBvYmplY3QuaS5oaWdoID4+PiAwKS50b051bWJlcigpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5zICE9IG51bGwpXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QucyA9PT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgICAgICAgICAgJHV0aWwuYmFzZTY0LmRlY29kZShvYmplY3QucywgbWVzc2FnZS5zID0gJHV0aWwubmV3QnVmZmVyKCR1dGlsLmJhc2U2NC5sZW5ndGgob2JqZWN0LnMpKSwgMCk7XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAob2JqZWN0LnMubGVuZ3RoKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnMgPSBvYmplY3QucztcbiAgICAgICAgICAgIGlmIChvYmplY3QudCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QudCAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguQXR0cmlidXRlUHJvdG8udDogb2JqZWN0IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UudCA9ICRyb290Lm9ubnguVGVuc29yUHJvdG8uZnJvbU9iamVjdChvYmplY3QudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LmcgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LmcgIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LkF0dHJpYnV0ZVByb3RvLmc6IG9iamVjdCBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmcgPSAkcm9vdC5vbm54LkdyYXBoUHJvdG8uZnJvbU9iamVjdChvYmplY3QuZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LmZsb2F0cykge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3QuZmxvYXRzKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguQXR0cmlidXRlUHJvdG8uZmxvYXRzOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmZsb2F0cyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LmZsb2F0cy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5mbG9hdHNbaV0gPSBOdW1iZXIob2JqZWN0LmZsb2F0c1tpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LmludHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0LmludHMpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5BdHRyaWJ1dGVQcm90by5pbnRzOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmludHMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC5pbnRzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoJHV0aWwuTG9uZylcbiAgICAgICAgICAgICAgICAgICAgICAgIChtZXNzYWdlLmludHNbaV0gPSAkdXRpbC5Mb25nLmZyb21WYWx1ZShvYmplY3QuaW50c1tpXSkpLnVuc2lnbmVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QuaW50c1tpXSA9PT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW50c1tpXSA9IHBhcnNlSW50KG9iamVjdC5pbnRzW2ldLCAxMCk7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QuaW50c1tpXSA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW50c1tpXSA9IG9iamVjdC5pbnRzW2ldO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmludHNbaV0gPT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmludHNbaV0gPSBuZXcgJHV0aWwuTG9uZ0JpdHMob2JqZWN0LmludHNbaV0ubG93ID4+PiAwLCBvYmplY3QuaW50c1tpXS5oaWdoID4+PiAwKS50b051bWJlcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5zdHJpbmdzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5zdHJpbmdzKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguQXR0cmlidXRlUHJvdG8uc3RyaW5nczogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5zdHJpbmdzID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3Quc3RyaW5ncy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3Quc3RyaW5nc1tpXSA9PT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICR1dGlsLmJhc2U2NC5kZWNvZGUob2JqZWN0LnN0cmluZ3NbaV0sIG1lc3NhZ2Uuc3RyaW5nc1tpXSA9ICR1dGlsLm5ld0J1ZmZlcigkdXRpbC5iYXNlNjQubGVuZ3RoKG9iamVjdC5zdHJpbmdzW2ldKSksIDApO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChvYmplY3Quc3RyaW5nc1tpXS5sZW5ndGgpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnN0cmluZ3NbaV0gPSBvYmplY3Quc3RyaW5nc1tpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvYmplY3QudGVuc29ycykge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3QudGVuc29ycykpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LkF0dHJpYnV0ZVByb3RvLnRlbnNvcnM6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UudGVuc29ycyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LnRlbnNvcnMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QudGVuc29yc1tpXSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LkF0dHJpYnV0ZVByb3RvLnRlbnNvcnM6IG9iamVjdCBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS50ZW5zb3JzW2ldID0gJHJvb3Qub25ueC5UZW5zb3JQcm90by5mcm9tT2JqZWN0KG9iamVjdC50ZW5zb3JzW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LmdyYXBocykge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3QuZ3JhcGhzKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguQXR0cmlidXRlUHJvdG8uZ3JhcGhzOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmdyYXBocyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LmdyYXBocy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdC5ncmFwaHNbaV0gIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5BdHRyaWJ1dGVQcm90by5ncmFwaHM6IG9iamVjdCBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5ncmFwaHNbaV0gPSAkcm9vdC5vbm54LkdyYXBoUHJvdG8uZnJvbU9iamVjdChvYmplY3QuZ3JhcGhzW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIHBsYWluIG9iamVjdCBmcm9tIGFuIEF0dHJpYnV0ZVByb3RvIG1lc3NhZ2UuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIG90aGVyIHR5cGVzIGlmIHNwZWNpZmllZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LkF0dHJpYnV0ZVByb3RvfSBtZXNzYWdlIEF0dHJpYnV0ZVByb3RvXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLklDb252ZXJzaW9uT3B0aW9uc30gW29wdGlvbnNdIENvbnZlcnNpb24gb3B0aW9uc1xuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IFBsYWluIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgQXR0cmlidXRlUHJvdG8udG9PYmplY3QgPSBmdW5jdGlvbiB0b09iamVjdChtZXNzYWdlLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMpXG4gICAgICAgICAgICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgICAgICAgdmFyIG9iamVjdCA9IHt9O1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuYXJyYXlzIHx8IG9wdGlvbnMuZGVmYXVsdHMpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QuZmxvYXRzID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0LmludHMgPSBbXTtcbiAgICAgICAgICAgICAgICBvYmplY3Quc3RyaW5ncyA9IFtdO1xuICAgICAgICAgICAgICAgIG9iamVjdC50ZW5zb3JzID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0LmdyYXBocyA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGVmYXVsdHMpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QubmFtZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmYgPSAwO1xuICAgICAgICAgICAgICAgIGlmICgkdXRpbC5Mb25nKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsb25nID0gbmV3ICR1dGlsLkxvbmcoMCwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBvYmplY3QuaSA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IGxvbmcudG9TdHJpbmcoKSA6IG9wdGlvbnMubG9uZ3MgPT09IE51bWJlciA/IGxvbmcudG9OdW1iZXIoKSA6IGxvbmc7XG4gICAgICAgICAgICAgICAgfSBlbHNlXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5pID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gXCIwXCIgOiAwO1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmJ5dGVzID09PSBTdHJpbmcpXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5zID0gXCJcIjtcbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuYnl0ZXMgIT09IEFycmF5KVxuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnMgPSAkdXRpbC5uZXdCdWZmZXIob2JqZWN0LnMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvYmplY3QudCA9IG51bGw7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmcgPSBudWxsO1xuICAgICAgICAgICAgICAgIG9iamVjdC5kb2NTdHJpbmcgPSBcIlwiO1xuICAgICAgICAgICAgICAgIG9iamVjdC50eXBlID0gb3B0aW9ucy5lbnVtcyA9PT0gU3RyaW5nID8gXCJVTkRFRklORURcIiA6IDA7XG4gICAgICAgICAgICAgICAgb2JqZWN0LnJlZkF0dHJOYW1lID0gXCJcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwibmFtZVwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QubmFtZSA9IG1lc3NhZ2UubmFtZTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmYgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZlwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QuZiA9IG9wdGlvbnMuanNvbiAmJiAhaXNGaW5pdGUobWVzc2FnZS5mKSA/IFN0cmluZyhtZXNzYWdlLmYpIDogbWVzc2FnZS5mO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJpXCIpKVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZS5pID09PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuaSA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IFN0cmluZyhtZXNzYWdlLmkpIDogbWVzc2FnZS5pO1xuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmkgPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyAkdXRpbC5Mb25nLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG1lc3NhZ2UuaSkgOiBvcHRpb25zLmxvbmdzID09PSBOdW1iZXIgPyBuZXcgJHV0aWwuTG9uZ0JpdHMobWVzc2FnZS5pLmxvdyA+Pj4gMCwgbWVzc2FnZS5pLmhpZ2ggPj4+IDApLnRvTnVtYmVyKCkgOiBtZXNzYWdlLmk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5zICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInNcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LnMgPSBvcHRpb25zLmJ5dGVzID09PSBTdHJpbmcgPyAkdXRpbC5iYXNlNjQuZW5jb2RlKG1lc3NhZ2UucywgMCwgbWVzc2FnZS5zLmxlbmd0aCkgOiBvcHRpb25zLmJ5dGVzID09PSBBcnJheSA/IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKG1lc3NhZ2UucykgOiBtZXNzYWdlLnM7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50ICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInRcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LnQgPSAkcm9vdC5vbm54LlRlbnNvclByb3RvLnRvT2JqZWN0KG1lc3NhZ2UudCwgb3B0aW9ucyk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5nICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImdcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmcgPSAkcm9vdC5vbm54LkdyYXBoUHJvdG8udG9PYmplY3QobWVzc2FnZS5nLCBvcHRpb25zKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmZsb2F0cyAmJiBtZXNzYWdlLmZsb2F0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QuZmxvYXRzID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLmZsb2F0cy5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmZsb2F0c1tqXSA9IG9wdGlvbnMuanNvbiAmJiAhaXNGaW5pdGUobWVzc2FnZS5mbG9hdHNbal0pID8gU3RyaW5nKG1lc3NhZ2UuZmxvYXRzW2pdKSA6IG1lc3NhZ2UuZmxvYXRzW2pdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW50cyAmJiBtZXNzYWdlLmludHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmludHMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2UuaW50cy5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlLmludHNbal0gPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QuaW50c1tqXSA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IFN0cmluZyhtZXNzYWdlLmludHNbal0pIDogbWVzc2FnZS5pbnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QuaW50c1tqXSA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/ICR1dGlsLkxvbmcucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobWVzc2FnZS5pbnRzW2pdKSA6IG9wdGlvbnMubG9uZ3MgPT09IE51bWJlciA/IG5ldyAkdXRpbC5Mb25nQml0cyhtZXNzYWdlLmludHNbal0ubG93ID4+PiAwLCBtZXNzYWdlLmludHNbal0uaGlnaCA+Pj4gMCkudG9OdW1iZXIoKSA6IG1lc3NhZ2UuaW50c1tqXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnN0cmluZ3MgJiYgbWVzc2FnZS5zdHJpbmdzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5zdHJpbmdzID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLnN0cmluZ3MubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5zdHJpbmdzW2pdID0gb3B0aW9ucy5ieXRlcyA9PT0gU3RyaW5nID8gJHV0aWwuYmFzZTY0LmVuY29kZShtZXNzYWdlLnN0cmluZ3Nbal0sIDAsIG1lc3NhZ2Uuc3RyaW5nc1tqXS5sZW5ndGgpIDogb3B0aW9ucy5ieXRlcyA9PT0gQXJyYXkgPyBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChtZXNzYWdlLnN0cmluZ3Nbal0pIDogbWVzc2FnZS5zdHJpbmdzW2pdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudGVuc29ycyAmJiBtZXNzYWdlLnRlbnNvcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LnRlbnNvcnMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2UudGVuc29ycy5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnRlbnNvcnNbal0gPSAkcm9vdC5vbm54LlRlbnNvclByb3RvLnRvT2JqZWN0KG1lc3NhZ2UudGVuc29yc1tqXSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5ncmFwaHMgJiYgbWVzc2FnZS5ncmFwaHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmdyYXBocyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5ncmFwaHMubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5ncmFwaHNbal0gPSAkcm9vdC5vbm54LkdyYXBoUHJvdG8udG9PYmplY3QobWVzc2FnZS5ncmFwaHNbal0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9jU3RyaW5nICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvY1N0cmluZ1wiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QuZG9jU3RyaW5nID0gbWVzc2FnZS5kb2NTdHJpbmc7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50eXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInR5cGVcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LnR5cGUgPSBvcHRpb25zLmVudW1zID09PSBTdHJpbmcgPyAkcm9vdC5vbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGVbbWVzc2FnZS50eXBlXSA6IG1lc3NhZ2UudHlwZTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnJlZkF0dHJOYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInJlZkF0dHJOYW1lXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5yZWZBdHRyTmFtZSA9IG1lc3NhZ2UucmVmQXR0ck5hbWU7XG4gICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIEF0dHJpYnV0ZVByb3RvIHRvIEpTT04uXG4gICAgICAgICAqIEBmdW5jdGlvbiB0b0pTT05cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguQXR0cmlidXRlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gSlNPTiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIEF0dHJpYnV0ZVByb3RvLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci50b09iamVjdCh0aGlzLCAkcHJvdG9idWYudXRpbC50b0pTT05PcHRpb25zKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQXR0cmlidXRlVHlwZSBlbnVtLlxuICAgICAgICAgKiBAbmFtZSBvbm54LkF0dHJpYnV0ZVByb3RvLkF0dHJpYnV0ZVR5cGVcbiAgICAgICAgICogQGVudW0ge3N0cmluZ31cbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IFVOREVGSU5FRD0wIFVOREVGSU5FRCB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gRkxPQVQ9MSBGTE9BVCB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gSU5UPTIgSU5UIHZhbHVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBTVFJJTkc9MyBTVFJJTkcgdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IFRFTlNPUj00IFRFTlNPUiB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gR1JBUEg9NSBHUkFQSCB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gRkxPQVRTPTYgRkxPQVRTIHZhbHVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBJTlRTPTcgSU5UUyB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gU1RSSU5HUz04IFNUUklOR1MgdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IFRFTlNPUlM9OSBURU5TT1JTIHZhbHVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBHUkFQSFM9MTAgR1JBUEhTIHZhbHVlXG4gICAgICAgICAqL1xuICAgICAgICBBdHRyaWJ1dGVQcm90by5BdHRyaWJ1dGVUeXBlID0gKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIHZhbHVlc0J5SWQgPSB7fSwgdmFsdWVzID0gT2JqZWN0LmNyZWF0ZSh2YWx1ZXNCeUlkKTtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzBdID0gXCJVTkRFRklORURcIl0gPSAwO1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbMV0gPSBcIkZMT0FUXCJdID0gMTtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzJdID0gXCJJTlRcIl0gPSAyO1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbM10gPSBcIlNUUklOR1wiXSA9IDM7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFs0XSA9IFwiVEVOU09SXCJdID0gNDtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzVdID0gXCJHUkFQSFwiXSA9IDU7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFs2XSA9IFwiRkxPQVRTXCJdID0gNjtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzddID0gXCJJTlRTXCJdID0gNztcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzhdID0gXCJTVFJJTkdTXCJdID0gODtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzldID0gXCJURU5TT1JTXCJdID0gOTtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzEwXSA9IFwiR1JBUEhTXCJdID0gMTA7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWVzO1xuICAgICAgICB9KSgpO1xuXG4gICAgICAgIHJldHVybiBBdHRyaWJ1dGVQcm90bztcbiAgICB9KSgpO1xuXG4gICAgb25ueC5WYWx1ZUluZm9Qcm90byA9IChmdW5jdGlvbigpIHtcblxuICAgICAgICAvKipcbiAgICAgICAgICogUHJvcGVydGllcyBvZiBhIFZhbHVlSW5mb1Byb3RvLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAaW50ZXJmYWNlIElWYWx1ZUluZm9Qcm90b1xuICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbbmFtZV0gVmFsdWVJbmZvUHJvdG8gbmFtZVxuICAgICAgICAgKiBAcHJvcGVydHkge29ubnguSVR5cGVQcm90b3xudWxsfSBbdHlwZV0gVmFsdWVJbmZvUHJvdG8gdHlwZVxuICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbZG9jU3RyaW5nXSBWYWx1ZUluZm9Qcm90byBkb2NTdHJpbmdcbiAgICAgICAgICovXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnN0cnVjdHMgYSBuZXcgVmFsdWVJbmZvUHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBjbGFzc2Rlc2MgUmVwcmVzZW50cyBhIFZhbHVlSW5mb1Byb3RvLlxuICAgICAgICAgKiBAaW1wbGVtZW50cyBJVmFsdWVJbmZvUHJvdG9cbiAgICAgICAgICogQGNvbnN0cnVjdG9yXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JVmFsdWVJbmZvUHJvdG89fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIFZhbHVlSW5mb1Byb3RvKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKSwgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllc1trZXlzW2ldXSAhPSBudWxsKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1trZXlzW2ldXSA9IHByb3BlcnRpZXNba2V5c1tpXV07XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogVmFsdWVJbmZvUHJvdG8gbmFtZS5cbiAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBuYW1lXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlZhbHVlSW5mb1Byb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVmFsdWVJbmZvUHJvdG8ucHJvdG90eXBlLm5hbWUgPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBWYWx1ZUluZm9Qcm90byB0eXBlLlxuICAgICAgICAgKiBAbWVtYmVyIHtvbm54LklUeXBlUHJvdG98bnVsbHx1bmRlZmluZWR9IHR5cGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVmFsdWVJbmZvUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBWYWx1ZUluZm9Qcm90by5wcm90b3R5cGUudHlwZSA9IG51bGw7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFZhbHVlSW5mb1Byb3RvIGRvY1N0cmluZy5cbiAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBkb2NTdHJpbmdcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVmFsdWVJbmZvUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBWYWx1ZUluZm9Qcm90by5wcm90b3R5cGUuZG9jU3RyaW5nID0gXCJcIjtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIG5ldyBWYWx1ZUluZm9Qcm90byBpbnN0YW5jZSB1c2luZyB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBjcmVhdGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVmFsdWVJbmZvUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVZhbHVlSW5mb1Byb3RvPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlZhbHVlSW5mb1Byb3RvfSBWYWx1ZUluZm9Qcm90byBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVmFsdWVJbmZvUHJvdG8uY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgVmFsdWVJbmZvUHJvdG8ocHJvcGVydGllcyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBWYWx1ZUluZm9Qcm90byBtZXNzYWdlLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LlZhbHVlSW5mb1Byb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlZhbHVlSW5mb1Byb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklWYWx1ZUluZm9Qcm90b30gbWVzc2FnZSBWYWx1ZUluZm9Qcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIFZhbHVlSW5mb1Byb3RvLmVuY29kZSA9IGZ1bmN0aW9uIGVuY29kZShtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIGlmICghd3JpdGVyKVxuICAgICAgICAgICAgICAgIHdyaXRlciA9ICRXcml0ZXIuY3JlYXRlKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5uYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm5hbWVcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAxLCB3aXJlVHlwZSAyID0qLzEwKS5zdHJpbmcobWVzc2FnZS5uYW1lKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnR5cGUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidHlwZVwiKSlcbiAgICAgICAgICAgICAgICAkcm9vdC5vbm54LlR5cGVQcm90by5lbmNvZGUobWVzc2FnZS50eXBlLCB3cml0ZXIudWludDMyKC8qIGlkIDIsIHdpcmVUeXBlIDIgPSovMTgpLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb2NTdHJpbmcgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9jU3RyaW5nXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMywgd2lyZVR5cGUgMiA9Ki8yNikuc3RyaW5nKG1lc3NhZ2UuZG9jU3RyaW5nKTtcbiAgICAgICAgICAgIHJldHVybiB3cml0ZXI7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBWYWx1ZUluZm9Qcm90byBtZXNzYWdlLCBsZW5ndGggZGVsaW1pdGVkLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LlZhbHVlSW5mb1Byb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlZhbHVlSW5mb1Byb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklWYWx1ZUluZm9Qcm90b30gbWVzc2FnZSBWYWx1ZUluZm9Qcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIFZhbHVlSW5mb1Byb3RvLmVuY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZChtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVuY29kZShtZXNzYWdlLCB3cml0ZXIpLmxkZWxpbSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGEgVmFsdWVJbmZvUHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlci5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5WYWx1ZUluZm9Qcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aF0gTWVzc2FnZSBsZW5ndGggaWYga25vd24gYmVmb3JlaGFuZFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5WYWx1ZUluZm9Qcm90b30gVmFsdWVJbmZvUHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBWYWx1ZUluZm9Qcm90by5kZWNvZGUgPSBmdW5jdGlvbiBkZWNvZGUocmVhZGVyLCBsZW5ndGgpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9ICRSZWFkZXIuY3JlYXRlKHJlYWRlcik7XG4gICAgICAgICAgICB2YXIgZW5kID0gbGVuZ3RoID09PSB1bmRlZmluZWQgPyByZWFkZXIubGVuIDogcmVhZGVyLnBvcyArIGxlbmd0aCwgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LlZhbHVlSW5mb1Byb3RvKCk7XG4gICAgICAgICAgICB3aGlsZSAocmVhZGVyLnBvcyA8IGVuZCkge1xuICAgICAgICAgICAgICAgIHZhciB0YWcgPSByZWFkZXIudWludDMyKCk7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0YWcgPj4+IDMpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UubmFtZSA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnR5cGUgPSAkcm9vdC5vbm54LlR5cGVQcm90by5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG9jU3RyaW5nID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZWFkZXIuc2tpcFR5cGUodGFnICYgNyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGEgVmFsdWVJbmZvUHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlciwgbGVuZ3RoIGRlbGltaXRlZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5WYWx1ZUluZm9Qcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5WYWx1ZUluZm9Qcm90b30gVmFsdWVJbmZvUHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBWYWx1ZUluZm9Qcm90by5kZWNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWQocmVhZGVyKSB7XG4gICAgICAgICAgICBpZiAoIShyZWFkZXIgaW5zdGFuY2VvZiAkUmVhZGVyKSlcbiAgICAgICAgICAgICAgICByZWFkZXIgPSBuZXcgJFJlYWRlcihyZWFkZXIpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogVmVyaWZpZXMgYSBWYWx1ZUluZm9Qcm90byBtZXNzYWdlLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdmVyaWZ5XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlZhbHVlSW5mb1Byb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gbWVzc2FnZSBQbGFpbiBvYmplY3QgdG8gdmVyaWZ5XG4gICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH0gYG51bGxgIGlmIHZhbGlkLCBvdGhlcndpc2UgdGhlIHJlYXNvbiB3aHkgaXQgaXMgbm90XG4gICAgICAgICAqL1xuICAgICAgICBWYWx1ZUluZm9Qcm90by52ZXJpZnkgPSBmdW5jdGlvbiB2ZXJpZnkobWVzc2FnZSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlICE9PSBcIm9iamVjdFwiIHx8IG1lc3NhZ2UgPT09IG51bGwpXG4gICAgICAgICAgICAgICAgcmV0dXJuIFwib2JqZWN0IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5uYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm5hbWVcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLm5hbWUpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJuYW1lOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnR5cGUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidHlwZVwiKSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnJvciA9ICRyb290Lm9ubnguVHlwZVByb3RvLnZlcmlmeShtZXNzYWdlLnR5cGUpO1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwidHlwZS5cIiArIGVycm9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9jU3RyaW5nICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvY1N0cmluZ1wiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UuZG9jU3RyaW5nKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZG9jU3RyaW5nOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgVmFsdWVJbmZvUHJvdG8gbWVzc2FnZSBmcm9tIGEgcGxhaW4gb2JqZWN0LiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byB0aGVpciByZXNwZWN0aXZlIGludGVybmFsIHR5cGVzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZnJvbU9iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5WYWx1ZUluZm9Qcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG9iamVjdCBQbGFpbiBvYmplY3RcbiAgICAgICAgICogQHJldHVybnMge29ubnguVmFsdWVJbmZvUHJvdG99IFZhbHVlSW5mb1Byb3RvXG4gICAgICAgICAqL1xuICAgICAgICBWYWx1ZUluZm9Qcm90by5mcm9tT2JqZWN0ID0gZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChvYmplY3QgaW5zdGFuY2VvZiAkcm9vdC5vbm54LlZhbHVlSW5mb1Byb3RvKVxuICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgICAgICB2YXIgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LlZhbHVlSW5mb1Byb3RvKCk7XG4gICAgICAgICAgICBpZiAob2JqZWN0Lm5hbWUgIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLm5hbWUgPSBTdHJpbmcob2JqZWN0Lm5hbWUpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC50eXBlICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdC50eXBlICE9PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5WYWx1ZUluZm9Qcm90by50eXBlOiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS50eXBlID0gJHJvb3Qub25ueC5UeXBlUHJvdG8uZnJvbU9iamVjdChvYmplY3QudHlwZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LmRvY1N0cmluZyAhPSBudWxsKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG9jU3RyaW5nID0gU3RyaW5nKG9iamVjdC5kb2NTdHJpbmcpO1xuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBwbGFpbiBvYmplY3QgZnJvbSBhIFZhbHVlSW5mb1Byb3RvIG1lc3NhZ2UuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIG90aGVyIHR5cGVzIGlmIHNwZWNpZmllZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlZhbHVlSW5mb1Byb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LlZhbHVlSW5mb1Byb3RvfSBtZXNzYWdlIFZhbHVlSW5mb1Byb3RvXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLklDb252ZXJzaW9uT3B0aW9uc30gW29wdGlvbnNdIENvbnZlcnNpb24gb3B0aW9uc1xuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IFBsYWluIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgVmFsdWVJbmZvUHJvdG8udG9PYmplY3QgPSBmdW5jdGlvbiB0b09iamVjdChtZXNzYWdlLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMpXG4gICAgICAgICAgICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgICAgICAgdmFyIG9iamVjdCA9IHt9O1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGVmYXVsdHMpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QubmFtZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgb2JqZWN0LnR5cGUgPSBudWxsO1xuICAgICAgICAgICAgICAgIG9iamVjdC5kb2NTdHJpbmcgPSBcIlwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJuYW1lXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5uYW1lID0gbWVzc2FnZS5uYW1lO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudHlwZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJ0eXBlXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC50eXBlID0gJHJvb3Qub25ueC5UeXBlUHJvdG8udG9PYmplY3QobWVzc2FnZS50eXBlLCBvcHRpb25zKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvY1N0cmluZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb2NTdHJpbmdcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvY1N0cmluZyA9IG1lc3NhZ2UuZG9jU3RyaW5nO1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udmVydHMgdGhpcyBWYWx1ZUluZm9Qcm90byB0byBKU09OLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdG9KU09OXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlZhbHVlSW5mb1Byb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IEpTT04gb2JqZWN0XG4gICAgICAgICAqL1xuICAgICAgICBWYWx1ZUluZm9Qcm90by5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IudG9PYmplY3QodGhpcywgJHByb3RvYnVmLnV0aWwudG9KU09OT3B0aW9ucyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIFZhbHVlSW5mb1Byb3RvO1xuICAgIH0pKCk7XG5cbiAgICBvbm54Lk5vZGVQcm90byA9IChmdW5jdGlvbigpIHtcblxuICAgICAgICAvKipcbiAgICAgICAgICogUHJvcGVydGllcyBvZiBhIE5vZGVQcm90by5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnhcbiAgICAgICAgICogQGludGVyZmFjZSBJTm9kZVByb3RvXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPHN0cmluZz58bnVsbH0gW2lucHV0XSBOb2RlUHJvdG8gaW5wdXRcbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48c3RyaW5nPnxudWxsfSBbb3V0cHV0XSBOb2RlUHJvdG8gb3V0cHV0XG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtuYW1lXSBOb2RlUHJvdG8gbmFtZVxuICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbb3BUeXBlXSBOb2RlUHJvdG8gb3BUeXBlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtkb21haW5dIE5vZGVQcm90byBkb21haW5cbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48b25ueC5JQXR0cmlidXRlUHJvdG8+fG51bGx9IFthdHRyaWJ1dGVdIE5vZGVQcm90byBhdHRyaWJ1dGVcbiAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gW2RvY1N0cmluZ10gTm9kZVByb3RvIGRvY1N0cmluZ1xuICAgICAgICAgKi9cblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29uc3RydWN0cyBhIG5ldyBOb2RlUHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBjbGFzc2Rlc2MgUmVwcmVzZW50cyBhIE5vZGVQcm90by5cbiAgICAgICAgICogQGltcGxlbWVudHMgSU5vZGVQcm90b1xuICAgICAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklOb2RlUHJvdG89fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIE5vZGVQcm90byhwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICB0aGlzLmlucHV0ID0gW107XG4gICAgICAgICAgICB0aGlzLm91dHB1dCA9IFtdO1xuICAgICAgICAgICAgdGhpcy5hdHRyaWJ1dGUgPSBbXTtcbiAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKSwgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllc1trZXlzW2ldXSAhPSBudWxsKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1trZXlzW2ldXSA9IHByb3BlcnRpZXNba2V5c1tpXV07XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogTm9kZVByb3RvIGlucHV0LlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48c3RyaW5nPn0gaW5wdXRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTm9kZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgTm9kZVByb3RvLnByb3RvdHlwZS5pbnB1dCA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE5vZGVQcm90byBvdXRwdXQuXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5LjxzdHJpbmc+fSBvdXRwdXRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTm9kZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgTm9kZVByb3RvLnByb3RvdHlwZS5vdXRwdXQgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBOb2RlUHJvdG8gbmFtZS5cbiAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBuYW1lXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk5vZGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE5vZGVQcm90by5wcm90b3R5cGUubmFtZSA9IFwiXCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE5vZGVQcm90byBvcFR5cGUuXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gb3BUeXBlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk5vZGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE5vZGVQcm90by5wcm90b3R5cGUub3BUeXBlID0gXCJcIjtcblxuICAgICAgICAvKipcbiAgICAgICAgICogTm9kZVByb3RvIGRvbWFpbi5cbiAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBkb21haW5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTm9kZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgTm9kZVByb3RvLnByb3RvdHlwZS5kb21haW4gPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBOb2RlUHJvdG8gYXR0cmlidXRlLlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48b25ueC5JQXR0cmlidXRlUHJvdG8+fSBhdHRyaWJ1dGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTm9kZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgTm9kZVByb3RvLnByb3RvdHlwZS5hdHRyaWJ1dGUgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBOb2RlUHJvdG8gZG9jU3RyaW5nLlxuICAgICAgICAgKiBAbWVtYmVyIHtzdHJpbmd9IGRvY1N0cmluZ1xuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Ob2RlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBOb2RlUHJvdG8ucHJvdG90eXBlLmRvY1N0cmluZyA9IFwiXCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBuZXcgTm9kZVByb3RvIGluc3RhbmNlIHVzaW5nIHRoZSBzcGVjaWZpZWQgcHJvcGVydGllcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGNyZWF0ZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Ob2RlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSU5vZGVQcm90bz19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5Ob2RlUHJvdG99IE5vZGVQcm90byBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgTm9kZVByb3RvLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IE5vZGVQcm90byhwcm9wZXJ0aWVzKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIE5vZGVQcm90byBtZXNzYWdlLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54Lk5vZGVQcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Ob2RlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSU5vZGVQcm90b30gbWVzc2FnZSBOb2RlUHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBOb2RlUHJvdG8uZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgaWYgKCF3cml0ZXIpXG4gICAgICAgICAgICAgICAgd3JpdGVyID0gJFdyaXRlci5jcmVhdGUoKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmlucHV0ICE9IG51bGwgJiYgbWVzc2FnZS5pbnB1dC5sZW5ndGgpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmlucHV0Lmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDEsIHdpcmVUeXBlIDIgPSovMTApLnN0cmluZyhtZXNzYWdlLmlucHV0W2ldKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm91dHB1dCAhPSBudWxsICYmIG1lc3NhZ2Uub3V0cHV0Lmxlbmd0aClcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2Uub3V0cHV0Lmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDIsIHdpcmVUeXBlIDIgPSovMTgpLnN0cmluZyhtZXNzYWdlLm91dHB1dFtpXSk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5uYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm5hbWVcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAzLCB3aXJlVHlwZSAyID0qLzI2KS5zdHJpbmcobWVzc2FnZS5uYW1lKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm9wVHlwZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJvcFR5cGVcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCA0LCB3aXJlVHlwZSAyID0qLzM0KS5zdHJpbmcobWVzc2FnZS5vcFR5cGUpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuYXR0cmlidXRlICE9IG51bGwgJiYgbWVzc2FnZS5hdHRyaWJ1dGUubGVuZ3RoKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5hdHRyaWJ1dGUubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgICRyb290Lm9ubnguQXR0cmlidXRlUHJvdG8uZW5jb2RlKG1lc3NhZ2UuYXR0cmlidXRlW2ldLCB3cml0ZXIudWludDMyKC8qIGlkIDUsIHdpcmVUeXBlIDIgPSovNDIpLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb2NTdHJpbmcgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9jU3RyaW5nXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgNiwgd2lyZVR5cGUgMiA9Ki81MCkuc3RyaW5nKG1lc3NhZ2UuZG9jU3RyaW5nKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvbWFpbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb21haW5cIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCA3LCB3aXJlVHlwZSAyID0qLzU4KS5zdHJpbmcobWVzc2FnZS5kb21haW4pO1xuICAgICAgICAgICAgcmV0dXJuIHdyaXRlcjtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIE5vZGVQcm90byBtZXNzYWdlLCBsZW5ndGggZGVsaW1pdGVkLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54Lk5vZGVQcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Ob2RlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSU5vZGVQcm90b30gbWVzc2FnZSBOb2RlUHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBOb2RlUHJvdG8uZW5jb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikubGRlbGltKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYSBOb2RlUHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlci5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Ob2RlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGhdIE1lc3NhZ2UgbGVuZ3RoIGlmIGtub3duIGJlZm9yZWhhbmRcbiAgICAgICAgICogQHJldHVybnMge29ubnguTm9kZVByb3RvfSBOb2RlUHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBOb2RlUHJvdG8uZGVjb2RlID0gZnVuY3Rpb24gZGVjb2RlKHJlYWRlciwgbGVuZ3RoKSB7XG4gICAgICAgICAgICBpZiAoIShyZWFkZXIgaW5zdGFuY2VvZiAkUmVhZGVyKSlcbiAgICAgICAgICAgICAgICByZWFkZXIgPSAkUmVhZGVyLmNyZWF0ZShyZWFkZXIpO1xuICAgICAgICAgICAgdmFyIGVuZCA9IGxlbmd0aCA9PT0gdW5kZWZpbmVkID8gcmVhZGVyLmxlbiA6IHJlYWRlci5wb3MgKyBsZW5ndGgsIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5Ob2RlUHJvdG8oKTtcbiAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRhZyA9IHJlYWRlci51aW50MzIoKTtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRhZyA+Pj4gMykge1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5pbnB1dCAmJiBtZXNzYWdlLmlucHV0Lmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmlucHV0ID0gW107XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW5wdXQucHVzaChyZWFkZXIuc3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2Uub3V0cHV0ICYmIG1lc3NhZ2Uub3V0cHV0Lmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm91dHB1dCA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm91dHB1dC5wdXNoKHJlYWRlci5zdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5uYW1lID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2Uub3BUeXBlID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDc6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG9tYWluID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2UuYXR0cmlidXRlICYmIG1lc3NhZ2UuYXR0cmlidXRlLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmF0dHJpYnV0ZSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmF0dHJpYnV0ZS5wdXNoKCRyb290Lm9ubnguQXR0cmlidXRlUHJvdG8uZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kb2NTdHJpbmcgPSByZWFkZXIuc3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlci5za2lwVHlwZSh0YWcgJiA3KTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYSBOb2RlUHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlciwgbGVuZ3RoIGRlbGltaXRlZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Ob2RlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHJldHVybnMge29ubnguTm9kZVByb3RvfSBOb2RlUHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBOb2RlUHJvdG8uZGVjb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkKHJlYWRlcikge1xuICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgcmVhZGVyID0gbmV3ICRSZWFkZXIocmVhZGVyKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFZlcmlmaWVzIGEgTm9kZVByb3RvIG1lc3NhZ2UuXG4gICAgICAgICAqIEBmdW5jdGlvbiB2ZXJpZnlcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTm9kZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gbWVzc2FnZSBQbGFpbiBvYmplY3QgdG8gdmVyaWZ5XG4gICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH0gYG51bGxgIGlmIHZhbGlkLCBvdGhlcndpc2UgdGhlIHJlYXNvbiB3aHkgaXQgaXMgbm90XG4gICAgICAgICAqL1xuICAgICAgICBOb2RlUHJvdG8udmVyaWZ5ID0gZnVuY3Rpb24gdmVyaWZ5KG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSAhPT0gXCJvYmplY3RcIiB8fCBtZXNzYWdlID09PSBudWxsKVxuICAgICAgICAgICAgICAgIHJldHVybiBcIm9iamVjdCBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW5wdXQgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiaW5wdXRcIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS5pbnB1dCkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImlucHV0OiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5pbnB1dC5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLmlucHV0W2ldKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcImlucHV0OiBzdHJpbmdbXSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uub3V0cHV0ICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm91dHB1dFwiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLm91dHB1dCkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm91dHB1dDogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2Uub3V0cHV0Lmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2Uub3V0cHV0W2ldKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm91dHB1dDogc3RyaW5nW10gZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwibmFtZVwiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UubmFtZSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm5hbWU6IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uub3BUeXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm9wVHlwZVwiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2Uub3BUeXBlKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwib3BUeXBlOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvbWFpbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb21haW5cIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLmRvbWFpbikpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRvbWFpbjogc3RyaW5nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5hdHRyaWJ1dGUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiYXR0cmlidXRlXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UuYXR0cmlidXRlKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiYXR0cmlidXRlOiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5hdHRyaWJ1dGUubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5BdHRyaWJ1dGVQcm90by52ZXJpZnkobWVzc2FnZS5hdHRyaWJ1dGVbaV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJhdHRyaWJ1dGUuXCIgKyBlcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb2NTdHJpbmcgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9jU3RyaW5nXCIpKVxuICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5kb2NTdHJpbmcpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJkb2NTdHJpbmc6IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBOb2RlUHJvdG8gbWVzc2FnZSBmcm9tIGEgcGxhaW4gb2JqZWN0LiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byB0aGVpciByZXNwZWN0aXZlIGludGVybmFsIHR5cGVzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZnJvbU9iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Ob2RlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBvYmplY3QgUGxhaW4gb2JqZWN0XG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54Lk5vZGVQcm90b30gTm9kZVByb3RvXG4gICAgICAgICAqL1xuICAgICAgICBOb2RlUHJvdG8uZnJvbU9iamVjdCA9IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgICAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgJHJvb3Qub25ueC5Ob2RlUHJvdG8pXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgICAgIHZhciBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguTm9kZVByb3RvKCk7XG4gICAgICAgICAgICBpZiAob2JqZWN0LmlucHV0KSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5pbnB1dCkpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54Lk5vZGVQcm90by5pbnB1dDogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5pbnB1dCA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LmlucHV0Lmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmlucHV0W2ldID0gU3RyaW5nKG9iamVjdC5pbnB1dFtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0Lm91dHB1dCkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3Qub3V0cHV0KSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguTm9kZVByb3RvLm91dHB1dDogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5vdXRwdXQgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC5vdXRwdXQubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2Uub3V0cHV0W2ldID0gU3RyaW5nKG9iamVjdC5vdXRwdXRbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5uYW1lICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5uYW1lID0gU3RyaW5nKG9iamVjdC5uYW1lKTtcbiAgICAgICAgICAgIGlmIChvYmplY3Qub3BUeXBlICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5vcFR5cGUgPSBTdHJpbmcob2JqZWN0Lm9wVHlwZSk7XG4gICAgICAgICAgICBpZiAob2JqZWN0LmRvbWFpbiAhPSBudWxsKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG9tYWluID0gU3RyaW5nKG9iamVjdC5kb21haW4pO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5hdHRyaWJ1dGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0LmF0dHJpYnV0ZSkpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54Lk5vZGVQcm90by5hdHRyaWJ1dGU6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UuYXR0cmlidXRlID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3QuYXR0cmlidXRlLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LmF0dHJpYnV0ZVtpXSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54Lk5vZGVQcm90by5hdHRyaWJ1dGU6IG9iamVjdCBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5hdHRyaWJ1dGVbaV0gPSAkcm9vdC5vbm54LkF0dHJpYnV0ZVByb3RvLmZyb21PYmplY3Qob2JqZWN0LmF0dHJpYnV0ZVtpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5kb2NTdHJpbmcgIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmRvY1N0cmluZyA9IFN0cmluZyhvYmplY3QuZG9jU3RyaW5nKTtcbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgcGxhaW4gb2JqZWN0IGZyb20gYSBOb2RlUHJvdG8gbWVzc2FnZS4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gb3RoZXIgdHlwZXMgaWYgc3BlY2lmaWVkLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdG9PYmplY3RcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTm9kZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54Lk5vZGVQcm90b30gbWVzc2FnZSBOb2RlUHJvdG9cbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuSUNvbnZlcnNpb25PcHRpb25zfSBbb3B0aW9uc10gQ29udmVyc2lvbiBvcHRpb25zXG4gICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gUGxhaW4gb2JqZWN0XG4gICAgICAgICAqL1xuICAgICAgICBOb2RlUHJvdG8udG9PYmplY3QgPSBmdW5jdGlvbiB0b09iamVjdChtZXNzYWdlLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMpXG4gICAgICAgICAgICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgICAgICAgdmFyIG9iamVjdCA9IHt9O1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuYXJyYXlzIHx8IG9wdGlvbnMuZGVmYXVsdHMpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QuaW5wdXQgPSBbXTtcbiAgICAgICAgICAgICAgICBvYmplY3Qub3V0cHV0ID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0LmF0dHJpYnV0ZSA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGVmYXVsdHMpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QubmFtZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgb2JqZWN0Lm9wVHlwZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvY1N0cmluZyA9IFwiXCI7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvbWFpbiA9IFwiXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pbnB1dCAmJiBtZXNzYWdlLmlucHV0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5pbnB1dCA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5pbnB1dC5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmlucHV0W2pdID0gbWVzc2FnZS5pbnB1dFtqXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm91dHB1dCAmJiBtZXNzYWdlLm91dHB1dC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3Qub3V0cHV0ID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLm91dHB1dC5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0Lm91dHB1dFtqXSA9IG1lc3NhZ2Uub3V0cHV0W2pdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJuYW1lXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5uYW1lID0gbWVzc2FnZS5uYW1lO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uub3BUeXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm9wVHlwZVwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3Qub3BUeXBlID0gbWVzc2FnZS5vcFR5cGU7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5hdHRyaWJ1dGUgJiYgbWVzc2FnZS5hdHRyaWJ1dGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmF0dHJpYnV0ZSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5hdHRyaWJ1dGUubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5hdHRyaWJ1dGVbal0gPSAkcm9vdC5vbm54LkF0dHJpYnV0ZVByb3RvLnRvT2JqZWN0KG1lc3NhZ2UuYXR0cmlidXRlW2pdLCBvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvY1N0cmluZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb2NTdHJpbmdcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvY1N0cmluZyA9IG1lc3NhZ2UuZG9jU3RyaW5nO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9tYWluICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvbWFpblwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QuZG9tYWluID0gbWVzc2FnZS5kb21haW47XG4gICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIE5vZGVQcm90byB0byBKU09OLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdG9KU09OXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk5vZGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBKU09OIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgTm9kZVByb3RvLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci50b09iamVjdCh0aGlzLCAkcHJvdG9idWYudXRpbC50b0pTT05PcHRpb25zKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gTm9kZVByb3RvO1xuICAgIH0pKCk7XG5cbiAgICBvbm54Lk1vZGVsUHJvdG8gPSAoZnVuY3Rpb24oKSB7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFByb3BlcnRpZXMgb2YgYSBNb2RlbFByb3RvLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAaW50ZXJmYWNlIElNb2RlbFByb3RvXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfExvbmd8bnVsbH0gW2lyVmVyc2lvbl0gTW9kZWxQcm90byBpclZlcnNpb25cbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48b25ueC5JT3BlcmF0b3JTZXRJZFByb3RvPnxudWxsfSBbb3BzZXRJbXBvcnRdIE1vZGVsUHJvdG8gb3BzZXRJbXBvcnRcbiAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gW3Byb2R1Y2VyTmFtZV0gTW9kZWxQcm90byBwcm9kdWNlck5hbWVcbiAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gW3Byb2R1Y2VyVmVyc2lvbl0gTW9kZWxQcm90byBwcm9kdWNlclZlcnNpb25cbiAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gW2RvbWFpbl0gTW9kZWxQcm90byBkb21haW5cbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ8TG9uZ3xudWxsfSBbbW9kZWxWZXJzaW9uXSBNb2RlbFByb3RvIG1vZGVsVmVyc2lvblxuICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbZG9jU3RyaW5nXSBNb2RlbFByb3RvIGRvY1N0cmluZ1xuICAgICAgICAgKiBAcHJvcGVydHkge29ubnguSUdyYXBoUHJvdG98bnVsbH0gW2dyYXBoXSBNb2RlbFByb3RvIGdyYXBoXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPG9ubnguSVN0cmluZ1N0cmluZ0VudHJ5UHJvdG8+fG51bGx9IFttZXRhZGF0YVByb3BzXSBNb2RlbFByb3RvIG1ldGFkYXRhUHJvcHNcbiAgICAgICAgICovXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnN0cnVjdHMgYSBuZXcgTW9kZWxQcm90by5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnhcbiAgICAgICAgICogQGNsYXNzZGVzYyBSZXByZXNlbnRzIGEgTW9kZWxQcm90by5cbiAgICAgICAgICogQGltcGxlbWVudHMgSU1vZGVsUHJvdG9cbiAgICAgICAgICogQGNvbnN0cnVjdG9yXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JTW9kZWxQcm90bz19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gTW9kZWxQcm90byhwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICB0aGlzLm9wc2V0SW1wb3J0ID0gW107XG4gICAgICAgICAgICB0aGlzLm1ldGFkYXRhUHJvcHMgPSBbXTtcbiAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKSwgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllc1trZXlzW2ldXSAhPSBudWxsKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1trZXlzW2ldXSA9IHByb3BlcnRpZXNba2V5c1tpXV07XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogTW9kZWxQcm90byBpclZlcnNpb24uXG4gICAgICAgICAqIEBtZW1iZXIge251bWJlcnxMb25nfSBpclZlcnNpb25cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTW9kZWxQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE1vZGVsUHJvdG8ucHJvdG90eXBlLmlyVmVyc2lvbiA9ICR1dGlsLkxvbmcgPyAkdXRpbC5Mb25nLmZyb21CaXRzKDAsMCxmYWxzZSkgOiAwO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBNb2RlbFByb3RvIG9wc2V0SW1wb3J0LlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48b25ueC5JT3BlcmF0b3JTZXRJZFByb3RvPn0gb3BzZXRJbXBvcnRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTW9kZWxQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE1vZGVsUHJvdG8ucHJvdG90eXBlLm9wc2V0SW1wb3J0ID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogTW9kZWxQcm90byBwcm9kdWNlck5hbWUuXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gcHJvZHVjZXJOYW1lXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLnByb3RvdHlwZS5wcm9kdWNlck5hbWUgPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBNb2RlbFByb3RvIHByb2R1Y2VyVmVyc2lvbi5cbiAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBwcm9kdWNlclZlcnNpb25cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTW9kZWxQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE1vZGVsUHJvdG8ucHJvdG90eXBlLnByb2R1Y2VyVmVyc2lvbiA9IFwiXCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE1vZGVsUHJvdG8gZG9tYWluLlxuICAgICAgICAgKiBAbWVtYmVyIHtzdHJpbmd9IGRvbWFpblxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Nb2RlbFByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgTW9kZWxQcm90by5wcm90b3R5cGUuZG9tYWluID0gXCJcIjtcblxuICAgICAgICAvKipcbiAgICAgICAgICogTW9kZWxQcm90byBtb2RlbFZlcnNpb24uXG4gICAgICAgICAqIEBtZW1iZXIge251bWJlcnxMb25nfSBtb2RlbFZlcnNpb25cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTW9kZWxQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE1vZGVsUHJvdG8ucHJvdG90eXBlLm1vZGVsVmVyc2lvbiA9ICR1dGlsLkxvbmcgPyAkdXRpbC5Mb25nLmZyb21CaXRzKDAsMCxmYWxzZSkgOiAwO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBNb2RlbFByb3RvIGRvY1N0cmluZy5cbiAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBkb2NTdHJpbmdcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTW9kZWxQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE1vZGVsUHJvdG8ucHJvdG90eXBlLmRvY1N0cmluZyA9IFwiXCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE1vZGVsUHJvdG8gZ3JhcGguXG4gICAgICAgICAqIEBtZW1iZXIge29ubnguSUdyYXBoUHJvdG98bnVsbHx1bmRlZmluZWR9IGdyYXBoXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLnByb3RvdHlwZS5ncmFwaCA9IG51bGw7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIE1vZGVsUHJvdG8gbWV0YWRhdGFQcm9wcy5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG9ubnguSVN0cmluZ1N0cmluZ0VudHJ5UHJvdG8+fSBtZXRhZGF0YVByb3BzXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLnByb3RvdHlwZS5tZXRhZGF0YVByb3BzID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIG5ldyBNb2RlbFByb3RvIGluc3RhbmNlIHVzaW5nIHRoZSBzcGVjaWZpZWQgcHJvcGVydGllcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGNyZWF0ZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Nb2RlbFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklNb2RlbFByb3RvPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54Lk1vZGVsUHJvdG99IE1vZGVsUHJvdG8gaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE1vZGVsUHJvdG8uY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgTW9kZWxQcm90byhwcm9wZXJ0aWVzKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIE1vZGVsUHJvdG8gbWVzc2FnZS4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5Nb2RlbFByb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSU1vZGVsUHJvdG99IG1lc3NhZ2UgTW9kZWxQcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIE1vZGVsUHJvdG8uZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgaWYgKCF3cml0ZXIpXG4gICAgICAgICAgICAgICAgd3JpdGVyID0gJFdyaXRlci5jcmVhdGUoKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmlyVmVyc2lvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJpclZlcnNpb25cIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAxLCB3aXJlVHlwZSAwID0qLzgpLmludDY0KG1lc3NhZ2UuaXJWZXJzaW9uKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnByb2R1Y2VyTmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJwcm9kdWNlck5hbWVcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAyLCB3aXJlVHlwZSAyID0qLzE4KS5zdHJpbmcobWVzc2FnZS5wcm9kdWNlck5hbWUpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucHJvZHVjZXJWZXJzaW9uICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInByb2R1Y2VyVmVyc2lvblwiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDMsIHdpcmVUeXBlIDIgPSovMjYpLnN0cmluZyhtZXNzYWdlLnByb2R1Y2VyVmVyc2lvbik7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb21haW4gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9tYWluXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgNCwgd2lyZVR5cGUgMiA9Ki8zNCkuc3RyaW5nKG1lc3NhZ2UuZG9tYWluKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm1vZGVsVmVyc2lvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJtb2RlbFZlcnNpb25cIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCA1LCB3aXJlVHlwZSAwID0qLzQwKS5pbnQ2NChtZXNzYWdlLm1vZGVsVmVyc2lvbik7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb2NTdHJpbmcgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9jU3RyaW5nXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgNiwgd2lyZVR5cGUgMiA9Ki81MCkuc3RyaW5nKG1lc3NhZ2UuZG9jU3RyaW5nKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmdyYXBoICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImdyYXBoXCIpKVxuICAgICAgICAgICAgICAgICRyb290Lm9ubnguR3JhcGhQcm90by5lbmNvZGUobWVzc2FnZS5ncmFwaCwgd3JpdGVyLnVpbnQzMigvKiBpZCA3LCB3aXJlVHlwZSAyID0qLzU4KS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uub3BzZXRJbXBvcnQgIT0gbnVsbCAmJiBtZXNzYWdlLm9wc2V0SW1wb3J0Lmxlbmd0aClcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2Uub3BzZXRJbXBvcnQubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgICRyb290Lm9ubnguT3BlcmF0b3JTZXRJZFByb3RvLmVuY29kZShtZXNzYWdlLm9wc2V0SW1wb3J0W2ldLCB3cml0ZXIudWludDMyKC8qIGlkIDgsIHdpcmVUeXBlIDIgPSovNjYpLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5tZXRhZGF0YVByb3BzICE9IG51bGwgJiYgbWVzc2FnZS5tZXRhZGF0YVByb3BzLmxlbmd0aClcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UubWV0YWRhdGFQcm9wcy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgJHJvb3Qub25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvLmVuY29kZShtZXNzYWdlLm1ldGFkYXRhUHJvcHNbaV0sIHdyaXRlci51aW50MzIoLyogaWQgMTQsIHdpcmVUeXBlIDIgPSovMTE0KS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgcmV0dXJuIHdyaXRlcjtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIE1vZGVsUHJvdG8gbWVzc2FnZSwgbGVuZ3RoIGRlbGltaXRlZC4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5Nb2RlbFByb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSU1vZGVsUHJvdG99IG1lc3NhZ2UgTW9kZWxQcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIE1vZGVsUHJvdG8uZW5jb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikubGRlbGltKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYSBNb2RlbFByb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTW9kZWxQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aF0gTWVzc2FnZSBsZW5ndGggaWYga25vd24gYmVmb3JlaGFuZFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5Nb2RlbFByb3RvfSBNb2RlbFByb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgTW9kZWxQcm90by5kZWNvZGUgPSBmdW5jdGlvbiBkZWNvZGUocmVhZGVyLCBsZW5ndGgpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9ICRSZWFkZXIuY3JlYXRlKHJlYWRlcik7XG4gICAgICAgICAgICB2YXIgZW5kID0gbGVuZ3RoID09PSB1bmRlZmluZWQgPyByZWFkZXIubGVuIDogcmVhZGVyLnBvcyArIGxlbmd0aCwgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54Lk1vZGVsUHJvdG8oKTtcbiAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRhZyA9IHJlYWRlci51aW50MzIoKTtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRhZyA+Pj4gMykge1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pclZlcnNpb24gPSByZWFkZXIuaW50NjQoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA4OlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLm9wc2V0SW1wb3J0ICYmIG1lc3NhZ2Uub3BzZXRJbXBvcnQubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2Uub3BzZXRJbXBvcnQgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5vcHNldEltcG9ydC5wdXNoKCRyb290Lm9ubnguT3BlcmF0b3JTZXRJZFByb3RvLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UucHJvZHVjZXJOYW1lID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UucHJvZHVjZXJWZXJzaW9uID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG9tYWluID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UubW9kZWxWZXJzaW9uID0gcmVhZGVyLmludDY0KCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kb2NTdHJpbmcgPSByZWFkZXIuc3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNzpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5ncmFwaCA9ICRyb290Lm9ubnguR3JhcGhQcm90by5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDE0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLm1ldGFkYXRhUHJvcHMgJiYgbWVzc2FnZS5tZXRhZGF0YVByb3BzLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm1ldGFkYXRhUHJvcHMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5tZXRhZGF0YVByb3BzLnB1c2goJHJvb3Qub25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZWFkZXIuc2tpcFR5cGUodGFnICYgNyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGEgTW9kZWxQcm90byBtZXNzYWdlIGZyb20gdGhlIHNwZWNpZmllZCByZWFkZXIgb3IgYnVmZmVyLCBsZW5ndGggZGVsaW1pdGVkLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHJldHVybnMge29ubnguTW9kZWxQcm90b30gTW9kZWxQcm90b1xuICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHBheWxvYWQgaXMgbm90IGEgcmVhZGVyIG9yIHZhbGlkIGJ1ZmZlclxuICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICovXG4gICAgICAgIE1vZGVsUHJvdG8uZGVjb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkKHJlYWRlcikge1xuICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgcmVhZGVyID0gbmV3ICRSZWFkZXIocmVhZGVyKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFZlcmlmaWVzIGEgTW9kZWxQcm90byBtZXNzYWdlLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdmVyaWZ5XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk1vZGVsUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBtZXNzYWdlIFBsYWluIG9iamVjdCB0byB2ZXJpZnlcbiAgICAgICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfSBgbnVsbGAgaWYgdmFsaWQsIG90aGVyd2lzZSB0aGUgcmVhc29uIHdoeSBpdCBpcyBub3RcbiAgICAgICAgICovXG4gICAgICAgIE1vZGVsUHJvdG8udmVyaWZ5ID0gZnVuY3Rpb24gdmVyaWZ5KG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSAhPT0gXCJvYmplY3RcIiB8fCBtZXNzYWdlID09PSBudWxsKVxuICAgICAgICAgICAgICAgIHJldHVybiBcIm9iamVjdCBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaXJWZXJzaW9uICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImlyVmVyc2lvblwiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmlyVmVyc2lvbikgJiYgIShtZXNzYWdlLmlyVmVyc2lvbiAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5pclZlcnNpb24ubG93KSAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5pclZlcnNpb24uaGlnaCkpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJpclZlcnNpb246IGludGVnZXJ8TG9uZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uub3BzZXRJbXBvcnQgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwib3BzZXRJbXBvcnRcIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS5vcHNldEltcG9ydCkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm9wc2V0SW1wb3J0OiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5vcHNldEltcG9ydC5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXJyb3IgPSAkcm9vdC5vbm54Lk9wZXJhdG9yU2V0SWRQcm90by52ZXJpZnkobWVzc2FnZS5vcHNldEltcG9ydFtpXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm9wc2V0SW1wb3J0LlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucHJvZHVjZXJOYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInByb2R1Y2VyTmFtZVwiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UucHJvZHVjZXJOYW1lKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwicHJvZHVjZXJOYW1lOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnByb2R1Y2VyVmVyc2lvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJwcm9kdWNlclZlcnNpb25cIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLnByb2R1Y2VyVmVyc2lvbikpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInByb2R1Y2VyVmVyc2lvbjogc3RyaW5nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb21haW4gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9tYWluXCIpKVxuICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5kb21haW4pKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJkb21haW46IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubW9kZWxWZXJzaW9uICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm1vZGVsVmVyc2lvblwiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLm1vZGVsVmVyc2lvbikgJiYgIShtZXNzYWdlLm1vZGVsVmVyc2lvbiAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5tb2RlbFZlcnNpb24ubG93KSAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5tb2RlbFZlcnNpb24uaGlnaCkpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJtb2RlbFZlcnNpb246IGludGVnZXJ8TG9uZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9jU3RyaW5nICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvY1N0cmluZ1wiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UuZG9jU3RyaW5nKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZG9jU3RyaW5nOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmdyYXBoICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImdyYXBoXCIpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5HcmFwaFByb3RvLnZlcmlmeShtZXNzYWdlLmdyYXBoKTtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImdyYXBoLlwiICsgZXJyb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5tZXRhZGF0YVByb3BzICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm1ldGFkYXRhUHJvcHNcIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS5tZXRhZGF0YVByb3BzKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwibWV0YWRhdGFQcm9wczogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UubWV0YWRhdGFQcm9wcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXJyb3IgPSAkcm9vdC5vbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG8udmVyaWZ5KG1lc3NhZ2UubWV0YWRhdGFQcm9wc1tpXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm1ldGFkYXRhUHJvcHMuXCIgKyBlcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIE1vZGVsUHJvdG8gbWVzc2FnZSBmcm9tIGEgcGxhaW4gb2JqZWN0LiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byB0aGVpciByZXNwZWN0aXZlIGludGVybmFsIHR5cGVzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZnJvbU9iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5Nb2RlbFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gb2JqZWN0IFBsYWluIG9iamVjdFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5Nb2RlbFByb3RvfSBNb2RlbFByb3RvXG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLmZyb21PYmplY3QgPSBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICAgICAgaWYgKG9iamVjdCBpbnN0YW5jZW9mICRyb290Lm9ubnguTW9kZWxQcm90bylcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5Nb2RlbFByb3RvKCk7XG4gICAgICAgICAgICBpZiAob2JqZWN0LmlyVmVyc2lvbiAhPSBudWxsKVxuICAgICAgICAgICAgICAgIGlmICgkdXRpbC5Mb25nKVxuICAgICAgICAgICAgICAgICAgICAobWVzc2FnZS5pclZlcnNpb24gPSAkdXRpbC5Mb25nLmZyb21WYWx1ZShvYmplY3QuaXJWZXJzaW9uKSkudW5zaWduZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmlyVmVyc2lvbiA9PT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pclZlcnNpb24gPSBwYXJzZUludChvYmplY3QuaXJWZXJzaW9uLCAxMCk7XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5pclZlcnNpb24gPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaXJWZXJzaW9uID0gb2JqZWN0LmlyVmVyc2lvbjtcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmlyVmVyc2lvbiA9PT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pclZlcnNpb24gPSBuZXcgJHV0aWwuTG9uZ0JpdHMob2JqZWN0LmlyVmVyc2lvbi5sb3cgPj4+IDAsIG9iamVjdC5pclZlcnNpb24uaGlnaCA+Pj4gMCkudG9OdW1iZXIoKTtcbiAgICAgICAgICAgIGlmIChvYmplY3Qub3BzZXRJbXBvcnQpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0Lm9wc2V0SW1wb3J0KSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguTW9kZWxQcm90by5vcHNldEltcG9ydDogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5vcHNldEltcG9ydCA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0Lm9wc2V0SW1wb3J0Lmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0Lm9wc2V0SW1wb3J0W2ldICE9PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguTW9kZWxQcm90by5vcHNldEltcG9ydDogb2JqZWN0IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm9wc2V0SW1wb3J0W2ldID0gJHJvb3Qub25ueC5PcGVyYXRvclNldElkUHJvdG8uZnJvbU9iamVjdChvYmplY3Qub3BzZXRJbXBvcnRbaV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvYmplY3QucHJvZHVjZXJOYW1lICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5wcm9kdWNlck5hbWUgPSBTdHJpbmcob2JqZWN0LnByb2R1Y2VyTmFtZSk7XG4gICAgICAgICAgICBpZiAob2JqZWN0LnByb2R1Y2VyVmVyc2lvbiAhPSBudWxsKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UucHJvZHVjZXJWZXJzaW9uID0gU3RyaW5nKG9iamVjdC5wcm9kdWNlclZlcnNpb24pO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5kb21haW4gIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmRvbWFpbiA9IFN0cmluZyhvYmplY3QuZG9tYWluKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QubW9kZWxWZXJzaW9uICE9IG51bGwpXG4gICAgICAgICAgICAgICAgaWYgKCR1dGlsLkxvbmcpXG4gICAgICAgICAgICAgICAgICAgIChtZXNzYWdlLm1vZGVsVmVyc2lvbiA9ICR1dGlsLkxvbmcuZnJvbVZhbHVlKG9iamVjdC5tb2RlbFZlcnNpb24pKS51bnNpZ25lZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QubW9kZWxWZXJzaW9uID09PSBcInN0cmluZ1wiKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm1vZGVsVmVyc2lvbiA9IHBhcnNlSW50KG9iamVjdC5tb2RlbFZlcnNpb24sIDEwKTtcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0Lm1vZGVsVmVyc2lvbiA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5tb2RlbFZlcnNpb24gPSBvYmplY3QubW9kZWxWZXJzaW9uO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QubW9kZWxWZXJzaW9uID09PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm1vZGVsVmVyc2lvbiA9IG5ldyAkdXRpbC5Mb25nQml0cyhvYmplY3QubW9kZWxWZXJzaW9uLmxvdyA+Pj4gMCwgb2JqZWN0Lm1vZGVsVmVyc2lvbi5oaWdoID4+PiAwKS50b051bWJlcigpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5kb2NTdHJpbmcgIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmRvY1N0cmluZyA9IFN0cmluZyhvYmplY3QuZG9jU3RyaW5nKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QuZ3JhcGggIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LmdyYXBoICE9PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5Nb2RlbFByb3RvLmdyYXBoOiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5ncmFwaCA9ICRyb290Lm9ubnguR3JhcGhQcm90by5mcm9tT2JqZWN0KG9iamVjdC5ncmFwaCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0Lm1ldGFkYXRhUHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0Lm1ldGFkYXRhUHJvcHMpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5Nb2RlbFByb3RvLm1ldGFkYXRhUHJvcHM6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UubWV0YWRhdGFQcm9wcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0Lm1ldGFkYXRhUHJvcHMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QubWV0YWRhdGFQcm9wc1tpXSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54Lk1vZGVsUHJvdG8ubWV0YWRhdGFQcm9wczogb2JqZWN0IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm1ldGFkYXRhUHJvcHNbaV0gPSAkcm9vdC5vbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG8uZnJvbU9iamVjdChvYmplY3QubWV0YWRhdGFQcm9wc1tpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBwbGFpbiBvYmplY3QgZnJvbSBhIE1vZGVsUHJvdG8gbWVzc2FnZS4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gb3RoZXIgdHlwZXMgaWYgc3BlY2lmaWVkLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdG9PYmplY3RcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTW9kZWxQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5Nb2RlbFByb3RvfSBtZXNzYWdlIE1vZGVsUHJvdG9cbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuSUNvbnZlcnNpb25PcHRpb25zfSBbb3B0aW9uc10gQ29udmVyc2lvbiBvcHRpb25zXG4gICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gUGxhaW4gb2JqZWN0XG4gICAgICAgICAqL1xuICAgICAgICBNb2RlbFByb3RvLnRvT2JqZWN0ID0gZnVuY3Rpb24gdG9PYmplY3QobWVzc2FnZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKCFvcHRpb25zKVxuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmFycmF5cyB8fCBvcHRpb25zLmRlZmF1bHRzKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0Lm9wc2V0SW1wb3J0ID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0Lm1ldGFkYXRhUHJvcHMgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvcHRpb25zLmRlZmF1bHRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCR1dGlsLkxvbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxvbmcgPSBuZXcgJHV0aWwuTG9uZygwLCAwLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5pclZlcnNpb24gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBsb25nLnRvU3RyaW5nKCkgOiBvcHRpb25zLmxvbmdzID09PSBOdW1iZXIgPyBsb25nLnRvTnVtYmVyKCkgOiBsb25nO1xuICAgICAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuaXJWZXJzaW9uID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gXCIwXCIgOiAwO1xuICAgICAgICAgICAgICAgIG9iamVjdC5wcm9kdWNlck5hbWUgPSBcIlwiO1xuICAgICAgICAgICAgICAgIG9iamVjdC5wcm9kdWNlclZlcnNpb24gPSBcIlwiO1xuICAgICAgICAgICAgICAgIG9iamVjdC5kb21haW4gPSBcIlwiO1xuICAgICAgICAgICAgICAgIGlmICgkdXRpbC5Mb25nKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsb25nID0gbmV3ICR1dGlsLkxvbmcoMCwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICBvYmplY3QubW9kZWxWZXJzaW9uID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gbG9uZy50b1N0cmluZygpIDogb3B0aW9ucy5sb25ncyA9PT0gTnVtYmVyID8gbG9uZy50b051bWJlcigpIDogbG9uZztcbiAgICAgICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0Lm1vZGVsVmVyc2lvbiA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IFwiMFwiIDogMDtcbiAgICAgICAgICAgICAgICBvYmplY3QuZG9jU3RyaW5nID0gXCJcIjtcbiAgICAgICAgICAgICAgICBvYmplY3QuZ3JhcGggPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaXJWZXJzaW9uICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImlyVmVyc2lvblwiKSlcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UuaXJWZXJzaW9uID09PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuaXJWZXJzaW9uID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gU3RyaW5nKG1lc3NhZ2UuaXJWZXJzaW9uKSA6IG1lc3NhZ2UuaXJWZXJzaW9uO1xuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmlyVmVyc2lvbiA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/ICR1dGlsLkxvbmcucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobWVzc2FnZS5pclZlcnNpb24pIDogb3B0aW9ucy5sb25ncyA9PT0gTnVtYmVyID8gbmV3ICR1dGlsLkxvbmdCaXRzKG1lc3NhZ2UuaXJWZXJzaW9uLmxvdyA+Pj4gMCwgbWVzc2FnZS5pclZlcnNpb24uaGlnaCA+Pj4gMCkudG9OdW1iZXIoKSA6IG1lc3NhZ2UuaXJWZXJzaW9uO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucHJvZHVjZXJOYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInByb2R1Y2VyTmFtZVwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QucHJvZHVjZXJOYW1lID0gbWVzc2FnZS5wcm9kdWNlck5hbWU7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5wcm9kdWNlclZlcnNpb24gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwicHJvZHVjZXJWZXJzaW9uXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5wcm9kdWNlclZlcnNpb24gPSBtZXNzYWdlLnByb2R1Y2VyVmVyc2lvbjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvbWFpbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb21haW5cIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvbWFpbiA9IG1lc3NhZ2UuZG9tYWluO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubW9kZWxWZXJzaW9uICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm1vZGVsVmVyc2lvblwiKSlcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UubW9kZWxWZXJzaW9uID09PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QubW9kZWxWZXJzaW9uID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gU3RyaW5nKG1lc3NhZ2UubW9kZWxWZXJzaW9uKSA6IG1lc3NhZ2UubW9kZWxWZXJzaW9uO1xuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0Lm1vZGVsVmVyc2lvbiA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/ICR1dGlsLkxvbmcucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobWVzc2FnZS5tb2RlbFZlcnNpb24pIDogb3B0aW9ucy5sb25ncyA9PT0gTnVtYmVyID8gbmV3ICR1dGlsLkxvbmdCaXRzKG1lc3NhZ2UubW9kZWxWZXJzaW9uLmxvdyA+Pj4gMCwgbWVzc2FnZS5tb2RlbFZlcnNpb24uaGlnaCA+Pj4gMCkudG9OdW1iZXIoKSA6IG1lc3NhZ2UubW9kZWxWZXJzaW9uO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG9jU3RyaW5nICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRvY1N0cmluZ1wiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QuZG9jU3RyaW5nID0gbWVzc2FnZS5kb2NTdHJpbmc7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5ncmFwaCAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJncmFwaFwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QuZ3JhcGggPSAkcm9vdC5vbm54LkdyYXBoUHJvdG8udG9PYmplY3QobWVzc2FnZS5ncmFwaCwgb3B0aW9ucyk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5vcHNldEltcG9ydCAmJiBtZXNzYWdlLm9wc2V0SW1wb3J0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5vcHNldEltcG9ydCA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5vcHNldEltcG9ydC5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0Lm9wc2V0SW1wb3J0W2pdID0gJHJvb3Qub25ueC5PcGVyYXRvclNldElkUHJvdG8udG9PYmplY3QobWVzc2FnZS5vcHNldEltcG9ydFtqXSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5tZXRhZGF0YVByb3BzICYmIG1lc3NhZ2UubWV0YWRhdGFQcm9wcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QubWV0YWRhdGFQcm9wcyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5tZXRhZGF0YVByb3BzLmxlbmd0aDsgKytqKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QubWV0YWRhdGFQcm9wc1tqXSA9ICRyb290Lm9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90by50b09iamVjdChtZXNzYWdlLm1ldGFkYXRhUHJvcHNbal0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udmVydHMgdGhpcyBNb2RlbFByb3RvIHRvIEpTT04uXG4gICAgICAgICAqIEBmdW5jdGlvbiB0b0pTT05cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguTW9kZWxQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBKU09OIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgTW9kZWxQcm90by5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IudG9PYmplY3QodGhpcywgJHByb3RvYnVmLnV0aWwudG9KU09OT3B0aW9ucyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIE1vZGVsUHJvdG87XG4gICAgfSkoKTtcblxuICAgIG9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90byA9IChmdW5jdGlvbigpIHtcblxuICAgICAgICAvKipcbiAgICAgICAgICogUHJvcGVydGllcyBvZiBhIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBpbnRlcmZhY2UgSVN0cmluZ1N0cmluZ0VudHJ5UHJvdG9cbiAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gW2tleV0gU3RyaW5nU3RyaW5nRW50cnlQcm90byBrZXlcbiAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gW3ZhbHVlXSBTdHJpbmdTdHJpbmdFbnRyeVByb3RvIHZhbHVlXG4gICAgICAgICAqL1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBjbGFzc2Rlc2MgUmVwcmVzZW50cyBhIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8uXG4gICAgICAgICAqIEBpbXBsZW1lbnRzIElTdHJpbmdTdHJpbmdFbnRyeVByb3RvXG4gICAgICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVN0cmluZ1N0cmluZ0VudHJ5UHJvdG89fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8ocHJvcGVydGllcykge1xuICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5cyA9IE9iamVjdC5rZXlzKHByb3BlcnRpZXMpLCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzW2tleXNbaV1dICE9IG51bGwpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzW2tleXNbaV1dID0gcHJvcGVydGllc1trZXlzW2ldXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTdHJpbmdTdHJpbmdFbnRyeVByb3RvIGtleS5cbiAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBrZXlcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8ucHJvdG90eXBlLmtleSA9IFwiXCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8gdmFsdWUuXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gdmFsdWVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8ucHJvdG90eXBlLnZhbHVlID0gXCJcIjtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIG5ldyBTdHJpbmdTdHJpbmdFbnRyeVByb3RvIGluc3RhbmNlIHVzaW5nIHRoZSBzcGVjaWZpZWQgcHJvcGVydGllcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGNyZWF0ZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklTdHJpbmdTdHJpbmdFbnRyeVByb3RvPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG99IFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8gaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8uY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU3RyaW5nU3RyaW5nRW50cnlQcm90byhwcm9wZXJ0aWVzKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8gbWVzc2FnZS4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVN0cmluZ1N0cmluZ0VudHJ5UHJvdG99IG1lc3NhZ2UgU3RyaW5nU3RyaW5nRW50cnlQcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8uZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgaWYgKCF3cml0ZXIpXG4gICAgICAgICAgICAgICAgd3JpdGVyID0gJFdyaXRlci5jcmVhdGUoKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmtleSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAxLCB3aXJlVHlwZSAyID0qLzEwKS5zdHJpbmcobWVzc2FnZS5rZXkpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudmFsdWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidmFsdWVcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAyLCB3aXJlVHlwZSAyID0qLzE4KS5zdHJpbmcobWVzc2FnZS52YWx1ZSk7XG4gICAgICAgICAgICByZXR1cm4gd3JpdGVyO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmNvZGVzIHRoZSBzcGVjaWZpZWQgU3RyaW5nU3RyaW5nRW50cnlQcm90byBtZXNzYWdlLCBsZW5ndGggZGVsaW1pdGVkLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG8udmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JU3RyaW5nU3RyaW5nRW50cnlQcm90b30gbWVzc2FnZSBTdHJpbmdTdHJpbmdFbnRyeVByb3RvIG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5Xcml0ZXJ9IFt3cml0ZXJdIFdyaXRlciB0byBlbmNvZGUgdG9cbiAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgKi9cbiAgICAgICAgU3RyaW5nU3RyaW5nRW50cnlQcm90by5lbmNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWQobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGUobWVzc2FnZSwgd3JpdGVyKS5sZGVsaW0oKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlci5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbGVuZ3RoXSBNZXNzYWdlIGxlbmd0aCBpZiBrbm93biBiZWZvcmVoYW5kXG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG99IFN0cmluZ1N0cmluZ0VudHJ5UHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBTdHJpbmdTdHJpbmdFbnRyeVByb3RvLmRlY29kZSA9IGZ1bmN0aW9uIGRlY29kZShyZWFkZXIsIGxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgcmVhZGVyID0gJFJlYWRlci5jcmVhdGUocmVhZGVyKTtcbiAgICAgICAgICAgIHZhciBlbmQgPSBsZW5ndGggPT09IHVuZGVmaW5lZCA/IHJlYWRlci5sZW4gOiByZWFkZXIucG9zICsgbGVuZ3RoLCBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90bygpO1xuICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGFnID0gcmVhZGVyLnVpbnQzMigpO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGFnID4+PiAzKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmtleSA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnZhbHVlID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZWFkZXIuc2tpcFR5cGUodGFnICYgNyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGEgU3RyaW5nU3RyaW5nRW50cnlQcm90byBtZXNzYWdlIGZyb20gdGhlIHNwZWNpZmllZCByZWFkZXIgb3IgYnVmZmVyLCBsZW5ndGggZGVsaW1pdGVkLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHJldHVybnMge29ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90b30gU3RyaW5nU3RyaW5nRW50cnlQcm90b1xuICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHBheWxvYWQgaXMgbm90IGEgcmVhZGVyIG9yIHZhbGlkIGJ1ZmZlclxuICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICovXG4gICAgICAgIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8uZGVjb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkKHJlYWRlcikge1xuICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgcmVhZGVyID0gbmV3ICRSZWFkZXIocmVhZGVyKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFZlcmlmaWVzIGEgU3RyaW5nU3RyaW5nRW50cnlQcm90byBtZXNzYWdlLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdmVyaWZ5XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBtZXNzYWdlIFBsYWluIG9iamVjdCB0byB2ZXJpZnlcbiAgICAgICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfSBgbnVsbGAgaWYgdmFsaWQsIG90aGVyd2lzZSB0aGUgcmVhc29uIHdoeSBpdCBpcyBub3RcbiAgICAgICAgICovXG4gICAgICAgIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8udmVyaWZ5ID0gZnVuY3Rpb24gdmVyaWZ5KG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSAhPT0gXCJvYmplY3RcIiB8fCBtZXNzYWdlID09PSBudWxsKVxuICAgICAgICAgICAgICAgIHJldHVybiBcIm9iamVjdCBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uua2V5ICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImtleVwiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2Uua2V5KSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwia2V5OiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnZhbHVlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpKVxuICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNTdHJpbmcobWVzc2FnZS52YWx1ZSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInZhbHVlOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgU3RyaW5nU3RyaW5nRW50cnlQcm90byBtZXNzYWdlIGZyb20gYSBwbGFpbiBvYmplY3QuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIHRoZWlyIHJlc3BlY3RpdmUgaW50ZXJuYWwgdHlwZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBmcm9tT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBvYmplY3QgUGxhaW4gb2JqZWN0XG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG99IFN0cmluZ1N0cmluZ0VudHJ5UHJvdG9cbiAgICAgICAgICovXG4gICAgICAgIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8uZnJvbU9iamVjdCA9IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgICAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgJHJvb3Qub25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvKVxuICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgICAgICB2YXIgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG8oKTtcbiAgICAgICAgICAgIGlmIChvYmplY3Qua2V5ICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5rZXkgPSBTdHJpbmcob2JqZWN0LmtleSk7XG4gICAgICAgICAgICBpZiAob2JqZWN0LnZhbHVlICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS52YWx1ZSA9IFN0cmluZyhvYmplY3QudmFsdWUpO1xuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBwbGFpbiBvYmplY3QgZnJvbSBhIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8gbWVzc2FnZS4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gb3RoZXIgdHlwZXMgaWYgc3BlY2lmaWVkLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdG9PYmplY3RcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvfSBtZXNzYWdlIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG9cbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuSUNvbnZlcnNpb25PcHRpb25zfSBbb3B0aW9uc10gQ29udmVyc2lvbiBvcHRpb25zXG4gICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gUGxhaW4gb2JqZWN0XG4gICAgICAgICAqL1xuICAgICAgICBTdHJpbmdTdHJpbmdFbnRyeVByb3RvLnRvT2JqZWN0ID0gZnVuY3Rpb24gdG9PYmplY3QobWVzc2FnZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKCFvcHRpb25zKVxuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmRlZmF1bHRzKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmtleSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgb2JqZWN0LnZhbHVlID0gXCJcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmtleSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmtleSA9IG1lc3NhZ2Uua2V5O1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudmFsdWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidmFsdWVcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LnZhbHVlID0gbWVzc2FnZS52YWx1ZTtcbiAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnZlcnRzIHRoaXMgU3RyaW5nU3RyaW5nRW50cnlQcm90byB0byBKU09OLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdG9KU09OXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gSlNPTiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIFN0cmluZ1N0cmluZ0VudHJ5UHJvdG8ucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLnRvT2JqZWN0KHRoaXMsICRwcm90b2J1Zi51dGlsLnRvSlNPTk9wdGlvbnMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBTdHJpbmdTdHJpbmdFbnRyeVByb3RvO1xuICAgIH0pKCk7XG5cbiAgICBvbm54LlRlbnNvckFubm90YXRpb24gPSAoZnVuY3Rpb24oKSB7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFByb3BlcnRpZXMgb2YgYSBUZW5zb3JBbm5vdGF0aW9uLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAaW50ZXJmYWNlIElUZW5zb3JBbm5vdGF0aW9uXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFt0ZW5zb3JOYW1lXSBUZW5zb3JBbm5vdGF0aW9uIHRlbnNvck5hbWVcbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48b25ueC5JU3RyaW5nU3RyaW5nRW50cnlQcm90bz58bnVsbH0gW3F1YW50UGFyYW1ldGVyVGVuc29yTmFtZXNdIFRlbnNvckFubm90YXRpb24gcXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lc1xuICAgICAgICAgKi9cblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29uc3RydWN0cyBhIG5ldyBUZW5zb3JBbm5vdGF0aW9uLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAY2xhc3NkZXNjIFJlcHJlc2VudHMgYSBUZW5zb3JBbm5vdGF0aW9uLlxuICAgICAgICAgKiBAaW1wbGVtZW50cyBJVGVuc29yQW5ub3RhdGlvblxuICAgICAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklUZW5zb3JBbm5vdGF0aW9uPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBUZW5zb3JBbm5vdGF0aW9uKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHRoaXMucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcyA9IFtdO1xuICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5cyA9IE9iamVjdC5rZXlzKHByb3BlcnRpZXMpLCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzW2tleXNbaV1dICE9IG51bGwpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzW2tleXNbaV1dID0gcHJvcGVydGllc1trZXlzW2ldXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUZW5zb3JBbm5vdGF0aW9uIHRlbnNvck5hbWUuXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gdGVuc29yTmFtZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JBbm5vdGF0aW9uXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yQW5ub3RhdGlvbi5wcm90b3R5cGUudGVuc29yTmFtZSA9IFwiXCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRlbnNvckFubm90YXRpb24gcXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcy5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG9ubnguSVN0cmluZ1N0cmluZ0VudHJ5UHJvdG8+fSBxdWFudFBhcmFtZXRlclRlbnNvck5hbWVzXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvckFubm90YXRpb25cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JBbm5vdGF0aW9uLnByb3RvdHlwZS5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIG5ldyBUZW5zb3JBbm5vdGF0aW9uIGluc3RhbmNlIHVzaW5nIHRoZSBzcGVjaWZpZWQgcHJvcGVydGllcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGNyZWF0ZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JBbm5vdGF0aW9uXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklUZW5zb3JBbm5vdGF0aW9uPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvckFubm90YXRpb259IFRlbnNvckFubm90YXRpb24gaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvckFubm90YXRpb24uY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgVGVuc29yQW5ub3RhdGlvbihwcm9wZXJ0aWVzKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIFRlbnNvckFubm90YXRpb24gbWVzc2FnZS4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5UZW5zb3JBbm5vdGF0aW9uLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvckFubm90YXRpb25cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVRlbnNvckFubm90YXRpb259IG1lc3NhZ2UgVGVuc29yQW5ub3RhdGlvbiBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvckFubm90YXRpb24uZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgaWYgKCF3cml0ZXIpXG4gICAgICAgICAgICAgICAgd3JpdGVyID0gJFdyaXRlci5jcmVhdGUoKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnRlbnNvck5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidGVuc29yTmFtZVwiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDEsIHdpcmVUeXBlIDIgPSovMTApLnN0cmluZyhtZXNzYWdlLnRlbnNvck5hbWUpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcyAhPSBudWxsICYmIG1lc3NhZ2UucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcy5sZW5ndGgpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgICRyb290Lm9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90by5lbmNvZGUobWVzc2FnZS5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzW2ldLCB3cml0ZXIudWludDMyKC8qIGlkIDIsIHdpcmVUeXBlIDIgPSovMTgpLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICByZXR1cm4gd3JpdGVyO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmNvZGVzIHRoZSBzcGVjaWZpZWQgVGVuc29yQW5ub3RhdGlvbiBtZXNzYWdlLCBsZW5ndGggZGVsaW1pdGVkLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LlRlbnNvckFubm90YXRpb24udmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yQW5ub3RhdGlvblxuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JVGVuc29yQW5ub3RhdGlvbn0gbWVzc2FnZSBUZW5zb3JBbm5vdGF0aW9uIG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5Xcml0ZXJ9IFt3cml0ZXJdIFdyaXRlciB0byBlbmNvZGUgdG9cbiAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yQW5ub3RhdGlvbi5lbmNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWQobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGUobWVzc2FnZSwgd3JpdGVyKS5sZGVsaW0oKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhIFRlbnNvckFubm90YXRpb24gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlci5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JBbm5vdGF0aW9uXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbGVuZ3RoXSBNZXNzYWdlIGxlbmd0aCBpZiBrbm93biBiZWZvcmVoYW5kXG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvckFubm90YXRpb259IFRlbnNvckFubm90YXRpb25cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JBbm5vdGF0aW9uLmRlY29kZSA9IGZ1bmN0aW9uIGRlY29kZShyZWFkZXIsIGxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgcmVhZGVyID0gJFJlYWRlci5jcmVhdGUocmVhZGVyKTtcbiAgICAgICAgICAgIHZhciBlbmQgPSBsZW5ndGggPT09IHVuZGVmaW5lZCA/IHJlYWRlci5sZW4gOiByZWFkZXIucG9zICsgbGVuZ3RoLCBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguVGVuc29yQW5ub3RhdGlvbigpO1xuICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGFnID0gcmVhZGVyLnVpbnQzMigpO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGFnID4+PiAzKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnRlbnNvck5hbWUgPSByZWFkZXIuc3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzICYmIG1lc3NhZ2UucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcy5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzID0gW107XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcy5wdXNoKCRyb290Lm9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90by5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnNraXBUeXBlKHRhZyAmIDcpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhIFRlbnNvckFubm90YXRpb24gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlciwgbGVuZ3RoIGRlbGltaXRlZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JBbm5vdGF0aW9uXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvckFubm90YXRpb259IFRlbnNvckFubm90YXRpb25cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JBbm5vdGF0aW9uLmRlY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZChyZWFkZXIpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9IG5ldyAkUmVhZGVyKHJlYWRlcik7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBWZXJpZmllcyBhIFRlbnNvckFubm90YXRpb24gbWVzc2FnZS5cbiAgICAgICAgICogQGZ1bmN0aW9uIHZlcmlmeVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JBbm5vdGF0aW9uXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gbWVzc2FnZSBQbGFpbiBvYmplY3QgdG8gdmVyaWZ5XG4gICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH0gYG51bGxgIGlmIHZhbGlkLCBvdGhlcndpc2UgdGhlIHJlYXNvbiB3aHkgaXQgaXMgbm90XG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JBbm5vdGF0aW9uLnZlcmlmeSA9IGZ1bmN0aW9uIHZlcmlmeShtZXNzYWdlKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgIT09IFwib2JqZWN0XCIgfHwgbWVzc2FnZSA9PT0gbnVsbClcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJvYmplY3QgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnRlbnNvck5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidGVuc29yTmFtZVwiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UudGVuc29yTmFtZSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInRlbnNvck5hbWU6IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJxdWFudFBhcmFtZXRlclRlbnNvck5hbWVzXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcykpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXM6IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvLnZlcmlmeShtZXNzYWdlLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXNbaV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJxdWFudFBhcmFtZXRlclRlbnNvck5hbWVzLlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBUZW5zb3JBbm5vdGF0aW9uIG1lc3NhZ2UgZnJvbSBhIHBsYWluIG9iamVjdC4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gdGhlaXIgcmVzcGVjdGl2ZSBpbnRlcm5hbCB0eXBlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGZyb21PYmplY3RcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yQW5ub3RhdGlvblxuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG9iamVjdCBQbGFpbiBvYmplY3RcbiAgICAgICAgICogQHJldHVybnMge29ubnguVGVuc29yQW5ub3RhdGlvbn0gVGVuc29yQW5ub3RhdGlvblxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yQW5ub3RhdGlvbi5mcm9tT2JqZWN0ID0gZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChvYmplY3QgaW5zdGFuY2VvZiAkcm9vdC5vbm54LlRlbnNvckFubm90YXRpb24pXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgICAgIHZhciBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguVGVuc29yQW5ub3RhdGlvbigpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC50ZW5zb3JOYW1lICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS50ZW5zb3JOYW1lID0gU3RyaW5nKG9iamVjdC50ZW5zb3JOYW1lKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcykge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3QucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcykpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LlRlbnNvckFubm90YXRpb24ucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lczogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3QucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdC5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzW2ldICE9PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguVGVuc29yQW5ub3RhdGlvbi5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzOiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lc1tpXSA9ICRyb290Lm9ubnguU3RyaW5nU3RyaW5nRW50cnlQcm90by5mcm9tT2JqZWN0KG9iamVjdC5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIHBsYWluIG9iamVjdCBmcm9tIGEgVGVuc29yQW5ub3RhdGlvbiBtZXNzYWdlLiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byBvdGhlciB0eXBlcyBpZiBzcGVjaWZpZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiB0b09iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JBbm5vdGF0aW9uXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LlRlbnNvckFubm90YXRpb259IG1lc3NhZ2UgVGVuc29yQW5ub3RhdGlvblxuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5JQ29udmVyc2lvbk9wdGlvbnN9IFtvcHRpb25zXSBDb252ZXJzaW9uIG9wdGlvbnNcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBQbGFpbiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvckFubm90YXRpb24udG9PYmplY3QgPSBmdW5jdGlvbiB0b09iamVjdChtZXNzYWdlLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMpXG4gICAgICAgICAgICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgICAgICAgdmFyIG9iamVjdCA9IHt9O1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuYXJyYXlzIHx8IG9wdGlvbnMuZGVmYXVsdHMpXG4gICAgICAgICAgICAgICAgb2JqZWN0LnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMgPSBbXTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmRlZmF1bHRzKVxuICAgICAgICAgICAgICAgIG9iamVjdC50ZW5zb3JOYW1lID0gXCJcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnRlbnNvck5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidGVuc29yTmFtZVwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QudGVuc29yTmFtZSA9IG1lc3NhZ2UudGVuc29yTmFtZTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMgJiYgbWVzc2FnZS5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLnF1YW50UGFyYW1ldGVyVGVuc29yTmFtZXMubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5xdWFudFBhcmFtZXRlclRlbnNvck5hbWVzW2pdID0gJHJvb3Qub25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvLnRvT2JqZWN0KG1lc3NhZ2UucXVhbnRQYXJhbWV0ZXJUZW5zb3JOYW1lc1tqXSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIFRlbnNvckFubm90YXRpb24gdG8gSlNPTi5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvSlNPTlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JBbm5vdGF0aW9uXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IEpTT04gb2JqZWN0XG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JBbm5vdGF0aW9uLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci50b09iamVjdCh0aGlzLCAkcHJvdG9idWYudXRpbC50b0pTT05PcHRpb25zKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gVGVuc29yQW5ub3RhdGlvbjtcbiAgICB9KSgpO1xuXG4gICAgb25ueC5HcmFwaFByb3RvID0gKGZ1bmN0aW9uKCkge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQcm9wZXJ0aWVzIG9mIGEgR3JhcGhQcm90by5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnhcbiAgICAgICAgICogQGludGVyZmFjZSBJR3JhcGhQcm90b1xuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5Ljxvbm54LklOb2RlUHJvdG8+fG51bGx9IFtub2RlXSBHcmFwaFByb3RvIG5vZGVcbiAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gW25hbWVdIEdyYXBoUHJvdG8gbmFtZVxuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5Ljxvbm54LklUZW5zb3JQcm90bz58bnVsbH0gW2luaXRpYWxpemVyXSBHcmFwaFByb3RvIGluaXRpYWxpemVyXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtkb2NTdHJpbmddIEdyYXBoUHJvdG8gZG9jU3RyaW5nXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPG9ubnguSVZhbHVlSW5mb1Byb3RvPnxudWxsfSBbaW5wdXRdIEdyYXBoUHJvdG8gaW5wdXRcbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48b25ueC5JVmFsdWVJbmZvUHJvdG8+fG51bGx9IFtvdXRwdXRdIEdyYXBoUHJvdG8gb3V0cHV0XG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPG9ubnguSVZhbHVlSW5mb1Byb3RvPnxudWxsfSBbdmFsdWVJbmZvXSBHcmFwaFByb3RvIHZhbHVlSW5mb1xuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5Ljxvbm54LklUZW5zb3JBbm5vdGF0aW9uPnxudWxsfSBbcXVhbnRpemF0aW9uQW5ub3RhdGlvbl0gR3JhcGhQcm90byBxdWFudGl6YXRpb25Bbm5vdGF0aW9uXG4gICAgICAgICAqL1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IEdyYXBoUHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBjbGFzc2Rlc2MgUmVwcmVzZW50cyBhIEdyYXBoUHJvdG8uXG4gICAgICAgICAqIEBpbXBsZW1lbnRzIElHcmFwaFByb3RvXG4gICAgICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAgICAgKiBAcGFyYW0ge29ubnguSUdyYXBoUHJvdG89fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIEdyYXBoUHJvdG8ocHJvcGVydGllcykge1xuICAgICAgICAgICAgdGhpcy5ub2RlID0gW107XG4gICAgICAgICAgICB0aGlzLmluaXRpYWxpemVyID0gW107XG4gICAgICAgICAgICB0aGlzLmlucHV0ID0gW107XG4gICAgICAgICAgICB0aGlzLm91dHB1dCA9IFtdO1xuICAgICAgICAgICAgdGhpcy52YWx1ZUluZm8gPSBbXTtcbiAgICAgICAgICAgIHRoaXMucXVhbnRpemF0aW9uQW5ub3RhdGlvbiA9IFtdO1xuICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5cyA9IE9iamVjdC5rZXlzKHByb3BlcnRpZXMpLCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzW2tleXNbaV1dICE9IG51bGwpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzW2tleXNbaV1dID0gcHJvcGVydGllc1trZXlzW2ldXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHcmFwaFByb3RvIG5vZGUuXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5Ljxvbm54LklOb2RlUHJvdG8+fSBub2RlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkdyYXBoUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBHcmFwaFByb3RvLnByb3RvdHlwZS5ub2RlID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogR3JhcGhQcm90byBuYW1lLlxuICAgICAgICAgKiBAbWVtYmVyIHtzdHJpbmd9IG5hbWVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguR3JhcGhQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEdyYXBoUHJvdG8ucHJvdG90eXBlLm5hbWUgPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHcmFwaFByb3RvIGluaXRpYWxpemVyLlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48b25ueC5JVGVuc29yUHJvdG8+fSBpbml0aWFsaXplclxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5HcmFwaFByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgR3JhcGhQcm90by5wcm90b3R5cGUuaW5pdGlhbGl6ZXIgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBHcmFwaFByb3RvIGRvY1N0cmluZy5cbiAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBkb2NTdHJpbmdcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguR3JhcGhQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEdyYXBoUHJvdG8ucHJvdG90eXBlLmRvY1N0cmluZyA9IFwiXCI7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdyYXBoUHJvdG8gaW5wdXQuXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5Ljxvbm54LklWYWx1ZUluZm9Qcm90bz59IGlucHV0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkdyYXBoUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBHcmFwaFByb3RvLnByb3RvdHlwZS5pbnB1dCA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdyYXBoUHJvdG8gb3V0cHV0LlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48b25ueC5JVmFsdWVJbmZvUHJvdG8+fSBvdXRwdXRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguR3JhcGhQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEdyYXBoUHJvdG8ucHJvdG90eXBlLm91dHB1dCA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdyYXBoUHJvdG8gdmFsdWVJbmZvLlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48b25ueC5JVmFsdWVJbmZvUHJvdG8+fSB2YWx1ZUluZm9cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguR3JhcGhQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEdyYXBoUHJvdG8ucHJvdG90eXBlLnZhbHVlSW5mbyA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEdyYXBoUHJvdG8gcXVhbnRpemF0aW9uQW5ub3RhdGlvbi5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG9ubnguSVRlbnNvckFubm90YXRpb24+fSBxdWFudGl6YXRpb25Bbm5vdGF0aW9uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkdyYXBoUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBHcmFwaFByb3RvLnByb3RvdHlwZS5xdWFudGl6YXRpb25Bbm5vdGF0aW9uID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIG5ldyBHcmFwaFByb3RvIGluc3RhbmNlIHVzaW5nIHRoZSBzcGVjaWZpZWQgcHJvcGVydGllcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGNyZWF0ZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5HcmFwaFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklHcmFwaFByb3RvPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LkdyYXBoUHJvdG99IEdyYXBoUHJvdG8gaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIEdyYXBoUHJvdG8uY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgR3JhcGhQcm90byhwcm9wZXJ0aWVzKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIEdyYXBoUHJvdG8gbWVzc2FnZS4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5HcmFwaFByb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkdyYXBoUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSUdyYXBoUHJvdG99IG1lc3NhZ2UgR3JhcGhQcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIEdyYXBoUHJvdG8uZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgaWYgKCF3cml0ZXIpXG4gICAgICAgICAgICAgICAgd3JpdGVyID0gJFdyaXRlci5jcmVhdGUoKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm5vZGUgIT0gbnVsbCAmJiBtZXNzYWdlLm5vZGUubGVuZ3RoKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5ub2RlLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICAkcm9vdC5vbm54Lk5vZGVQcm90by5lbmNvZGUobWVzc2FnZS5ub2RlW2ldLCB3cml0ZXIudWludDMyKC8qIGlkIDEsIHdpcmVUeXBlIDIgPSovMTApLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5uYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm5hbWVcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAyLCB3aXJlVHlwZSAyID0qLzE4KS5zdHJpbmcobWVzc2FnZS5uYW1lKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmluaXRpYWxpemVyICE9IG51bGwgJiYgbWVzc2FnZS5pbml0aWFsaXplci5sZW5ndGgpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmluaXRpYWxpemVyLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICAkcm9vdC5vbm54LlRlbnNvclByb3RvLmVuY29kZShtZXNzYWdlLmluaXRpYWxpemVyW2ldLCB3cml0ZXIudWludDMyKC8qIGlkIDUsIHdpcmVUeXBlIDIgPSovNDIpLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb2NTdHJpbmcgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9jU3RyaW5nXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMTAsIHdpcmVUeXBlIDIgPSovODIpLnN0cmluZyhtZXNzYWdlLmRvY1N0cmluZyk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pbnB1dCAhPSBudWxsICYmIG1lc3NhZ2UuaW5wdXQubGVuZ3RoKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5pbnB1dC5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgJHJvb3Qub25ueC5WYWx1ZUluZm9Qcm90by5lbmNvZGUobWVzc2FnZS5pbnB1dFtpXSwgd3JpdGVyLnVpbnQzMigvKiBpZCAxMSwgd2lyZVR5cGUgMiA9Ki85MCkuZm9yaygpKS5sZGVsaW0oKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm91dHB1dCAhPSBudWxsICYmIG1lc3NhZ2Uub3V0cHV0Lmxlbmd0aClcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2Uub3V0cHV0Lmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICAkcm9vdC5vbm54LlZhbHVlSW5mb1Byb3RvLmVuY29kZShtZXNzYWdlLm91dHB1dFtpXSwgd3JpdGVyLnVpbnQzMigvKiBpZCAxMiwgd2lyZVR5cGUgMiA9Ki85OCkuZm9yaygpKS5sZGVsaW0oKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnZhbHVlSW5mbyAhPSBudWxsICYmIG1lc3NhZ2UudmFsdWVJbmZvLmxlbmd0aClcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UudmFsdWVJbmZvLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICAkcm9vdC5vbm54LlZhbHVlSW5mb1Byb3RvLmVuY29kZShtZXNzYWdlLnZhbHVlSW5mb1tpXSwgd3JpdGVyLnVpbnQzMigvKiBpZCAxMywgd2lyZVR5cGUgMiA9Ki8xMDYpLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5xdWFudGl6YXRpb25Bbm5vdGF0aW9uICE9IG51bGwgJiYgbWVzc2FnZS5xdWFudGl6YXRpb25Bbm5vdGF0aW9uLmxlbmd0aClcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UucXVhbnRpemF0aW9uQW5ub3RhdGlvbi5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgJHJvb3Qub25ueC5UZW5zb3JBbm5vdGF0aW9uLmVuY29kZShtZXNzYWdlLnF1YW50aXphdGlvbkFubm90YXRpb25baV0sIHdyaXRlci51aW50MzIoLyogaWQgMTQsIHdpcmVUeXBlIDIgPSovMTE0KS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgcmV0dXJuIHdyaXRlcjtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIEdyYXBoUHJvdG8gbWVzc2FnZSwgbGVuZ3RoIGRlbGltaXRlZC4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5HcmFwaFByb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkdyYXBoUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSUdyYXBoUHJvdG99IG1lc3NhZ2UgR3JhcGhQcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIEdyYXBoUHJvdG8uZW5jb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikubGRlbGltKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYSBHcmFwaFByb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguR3JhcGhQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aF0gTWVzc2FnZSBsZW5ndGggaWYga25vd24gYmVmb3JlaGFuZFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5HcmFwaFByb3RvfSBHcmFwaFByb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgR3JhcGhQcm90by5kZWNvZGUgPSBmdW5jdGlvbiBkZWNvZGUocmVhZGVyLCBsZW5ndGgpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9ICRSZWFkZXIuY3JlYXRlKHJlYWRlcik7XG4gICAgICAgICAgICB2YXIgZW5kID0gbGVuZ3RoID09PSB1bmRlZmluZWQgPyByZWFkZXIubGVuIDogcmVhZGVyLnBvcyArIGxlbmd0aCwgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LkdyYXBoUHJvdG8oKTtcbiAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRhZyA9IHJlYWRlci51aW50MzIoKTtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRhZyA+Pj4gMykge1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5ub2RlICYmIG1lc3NhZ2Uubm9kZS5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5ub2RlID0gW107XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2Uubm9kZS5wdXNoKCRyb290Lm9ubnguTm9kZVByb3RvLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UubmFtZSA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLmluaXRpYWxpemVyICYmIG1lc3NhZ2UuaW5pdGlhbGl6ZXIubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW5pdGlhbGl6ZXIgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pbml0aWFsaXplci5wdXNoKCRyb290Lm9ubnguVGVuc29yUHJvdG8uZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG9jU3RyaW5nID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDExOlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLmlucHV0ICYmIG1lc3NhZ2UuaW5wdXQubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW5wdXQgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pbnB1dC5wdXNoKCRyb290Lm9ubnguVmFsdWVJbmZvUHJvdG8uZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTI6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2Uub3V0cHV0ICYmIG1lc3NhZ2Uub3V0cHV0Lmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm91dHB1dCA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm91dHB1dC5wdXNoKCRyb290Lm9ubnguVmFsdWVJbmZvUHJvdG8uZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTM6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2UudmFsdWVJbmZvICYmIG1lc3NhZ2UudmFsdWVJbmZvLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnZhbHVlSW5mbyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnZhbHVlSW5mby5wdXNoKCRyb290Lm9ubnguVmFsdWVJbmZvUHJvdG8uZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2UucXVhbnRpemF0aW9uQW5ub3RhdGlvbiAmJiBtZXNzYWdlLnF1YW50aXphdGlvbkFubm90YXRpb24ubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UucXVhbnRpemF0aW9uQW5ub3RhdGlvbiA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnF1YW50aXphdGlvbkFubm90YXRpb24ucHVzaCgkcm9vdC5vbm54LlRlbnNvckFubm90YXRpb24uZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlci5za2lwVHlwZSh0YWcgJiA3KTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYSBHcmFwaFByb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIsIGxlbmd0aCBkZWxpbWl0ZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguR3JhcGhQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5HcmFwaFByb3RvfSBHcmFwaFByb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgR3JhcGhQcm90by5kZWNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWQocmVhZGVyKSB7XG4gICAgICAgICAgICBpZiAoIShyZWFkZXIgaW5zdGFuY2VvZiAkUmVhZGVyKSlcbiAgICAgICAgICAgICAgICByZWFkZXIgPSBuZXcgJFJlYWRlcihyZWFkZXIpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogVmVyaWZpZXMgYSBHcmFwaFByb3RvIG1lc3NhZ2UuXG4gICAgICAgICAqIEBmdW5jdGlvbiB2ZXJpZnlcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguR3JhcGhQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG1lc3NhZ2UgUGxhaW4gb2JqZWN0IHRvIHZlcmlmeVxuICAgICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9IGBudWxsYCBpZiB2YWxpZCwgb3RoZXJ3aXNlIHRoZSByZWFzb24gd2h5IGl0IGlzIG5vdFxuICAgICAgICAgKi9cbiAgICAgICAgR3JhcGhQcm90by52ZXJpZnkgPSBmdW5jdGlvbiB2ZXJpZnkobWVzc2FnZSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlICE9PSBcIm9iamVjdFwiIHx8IG1lc3NhZ2UgPT09IG51bGwpXG4gICAgICAgICAgICAgICAgcmV0dXJuIFwib2JqZWN0IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5ub2RlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm5vZGVcIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS5ub2RlKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwibm9kZTogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2Uubm9kZS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXJyb3IgPSAkcm9vdC5vbm54Lk5vZGVQcm90by52ZXJpZnkobWVzc2FnZS5ub2RlW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwibm9kZS5cIiArIGVycm9yO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwibmFtZVwiKSlcbiAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UubmFtZSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm5hbWU6IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW5pdGlhbGl6ZXIgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiaW5pdGlhbGl6ZXJcIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS5pbml0aWFsaXplcikpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImluaXRpYWxpemVyOiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5pbml0aWFsaXplci5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXJyb3IgPSAkcm9vdC5vbm54LlRlbnNvclByb3RvLnZlcmlmeShtZXNzYWdlLmluaXRpYWxpemVyW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiaW5pdGlhbGl6ZXIuXCIgKyBlcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb2NTdHJpbmcgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9jU3RyaW5nXCIpKVxuICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5kb2NTdHJpbmcpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJkb2NTdHJpbmc6IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW5wdXQgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiaW5wdXRcIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS5pbnB1dCkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImlucHV0OiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5pbnB1dC5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXJyb3IgPSAkcm9vdC5vbm54LlZhbHVlSW5mb1Byb3RvLnZlcmlmeShtZXNzYWdlLmlucHV0W2ldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiaW5wdXQuXCIgKyBlcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5vdXRwdXQgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwib3V0cHV0XCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2Uub3V0cHV0KSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwib3V0cHV0OiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5vdXRwdXQubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5WYWx1ZUluZm9Qcm90by52ZXJpZnkobWVzc2FnZS5vdXRwdXRbaV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJvdXRwdXQuXCIgKyBlcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS52YWx1ZUluZm8gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidmFsdWVJbmZvXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UudmFsdWVJbmZvKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwidmFsdWVJbmZvOiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS52YWx1ZUluZm8ubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5WYWx1ZUluZm9Qcm90by52ZXJpZnkobWVzc2FnZS52YWx1ZUluZm9baV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJ2YWx1ZUluZm8uXCIgKyBlcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5xdWFudGl6YXRpb25Bbm5vdGF0aW9uICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInF1YW50aXphdGlvbkFubm90YXRpb25cIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS5xdWFudGl6YXRpb25Bbm5vdGF0aW9uKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwicXVhbnRpemF0aW9uQW5ub3RhdGlvbjogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UucXVhbnRpemF0aW9uQW5ub3RhdGlvbi5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXJyb3IgPSAkcm9vdC5vbm54LlRlbnNvckFubm90YXRpb24udmVyaWZ5KG1lc3NhZ2UucXVhbnRpemF0aW9uQW5ub3RhdGlvbltpXSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcilcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcInF1YW50aXphdGlvbkFubm90YXRpb24uXCIgKyBlcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIEdyYXBoUHJvdG8gbWVzc2FnZSBmcm9tIGEgcGxhaW4gb2JqZWN0LiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byB0aGVpciByZXNwZWN0aXZlIGludGVybmFsIHR5cGVzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZnJvbU9iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5HcmFwaFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gb2JqZWN0IFBsYWluIG9iamVjdFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5HcmFwaFByb3RvfSBHcmFwaFByb3RvXG4gICAgICAgICAqL1xuICAgICAgICBHcmFwaFByb3RvLmZyb21PYmplY3QgPSBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICAgICAgaWYgKG9iamVjdCBpbnN0YW5jZW9mICRyb290Lm9ubnguR3JhcGhQcm90bylcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5HcmFwaFByb3RvKCk7XG4gICAgICAgICAgICBpZiAob2JqZWN0Lm5vZGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0Lm5vZGUpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5HcmFwaFByb3RvLm5vZGU6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2Uubm9kZSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0Lm5vZGUubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3Qubm9kZVtpXSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LkdyYXBoUHJvdG8ubm9kZTogb2JqZWN0IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm5vZGVbaV0gPSAkcm9vdC5vbm54Lk5vZGVQcm90by5mcm9tT2JqZWN0KG9iamVjdC5ub2RlW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0Lm5hbWUgIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLm5hbWUgPSBTdHJpbmcob2JqZWN0Lm5hbWUpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5pbml0aWFsaXplcikge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3QuaW5pdGlhbGl6ZXIpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5HcmFwaFByb3RvLmluaXRpYWxpemVyOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmluaXRpYWxpemVyID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3QuaW5pdGlhbGl6ZXIubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QuaW5pdGlhbGl6ZXJbaV0gIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5HcmFwaFByb3RvLmluaXRpYWxpemVyOiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW5pdGlhbGl6ZXJbaV0gPSAkcm9vdC5vbm54LlRlbnNvclByb3RvLmZyb21PYmplY3Qob2JqZWN0LmluaXRpYWxpemVyW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LmRvY1N0cmluZyAhPSBudWxsKVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG9jU3RyaW5nID0gU3RyaW5nKG9iamVjdC5kb2NTdHJpbmcpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5pbnB1dCkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3QuaW5wdXQpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5HcmFwaFByb3RvLmlucHV0OiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmlucHV0ID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3QuaW5wdXQubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QuaW5wdXRbaV0gIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5HcmFwaFByb3RvLmlucHV0OiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW5wdXRbaV0gPSAkcm9vdC5vbm54LlZhbHVlSW5mb1Byb3RvLmZyb21PYmplY3Qob2JqZWN0LmlucHV0W2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0Lm91dHB1dCkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3Qub3V0cHV0KSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguR3JhcGhQcm90by5vdXRwdXQ6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2Uub3V0cHV0ID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3Qub3V0cHV0Lmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0Lm91dHB1dFtpXSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LkdyYXBoUHJvdG8ub3V0cHV0OiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2Uub3V0cHV0W2ldID0gJHJvb3Qub25ueC5WYWx1ZUluZm9Qcm90by5mcm9tT2JqZWN0KG9iamVjdC5vdXRwdXRbaV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvYmplY3QudmFsdWVJbmZvKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC52YWx1ZUluZm8pKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5HcmFwaFByb3RvLnZhbHVlSW5mbzogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS52YWx1ZUluZm8gPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC52YWx1ZUluZm8ubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QudmFsdWVJbmZvW2ldICE9PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguR3JhcGhQcm90by52YWx1ZUluZm86IG9iamVjdCBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS52YWx1ZUluZm9baV0gPSAkcm9vdC5vbm54LlZhbHVlSW5mb1Byb3RvLmZyb21PYmplY3Qob2JqZWN0LnZhbHVlSW5mb1tpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5xdWFudGl6YXRpb25Bbm5vdGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5xdWFudGl6YXRpb25Bbm5vdGF0aW9uKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguR3JhcGhQcm90by5xdWFudGl6YXRpb25Bbm5vdGF0aW9uOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLnF1YW50aXphdGlvbkFubm90YXRpb24gPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC5xdWFudGl6YXRpb25Bbm5vdGF0aW9uLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LnF1YW50aXphdGlvbkFubm90YXRpb25baV0gIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5HcmFwaFByb3RvLnF1YW50aXphdGlvbkFubm90YXRpb246IG9iamVjdCBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5xdWFudGl6YXRpb25Bbm5vdGF0aW9uW2ldID0gJHJvb3Qub25ueC5UZW5zb3JBbm5vdGF0aW9uLmZyb21PYmplY3Qob2JqZWN0LnF1YW50aXphdGlvbkFubm90YXRpb25baV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgcGxhaW4gb2JqZWN0IGZyb20gYSBHcmFwaFByb3RvIG1lc3NhZ2UuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIG90aGVyIHR5cGVzIGlmIHNwZWNpZmllZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkdyYXBoUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguR3JhcGhQcm90b30gbWVzc2FnZSBHcmFwaFByb3RvXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLklDb252ZXJzaW9uT3B0aW9uc30gW29wdGlvbnNdIENvbnZlcnNpb24gb3B0aW9uc1xuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IFBsYWluIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgR3JhcGhQcm90by50b09iamVjdCA9IGZ1bmN0aW9uIHRvT2JqZWN0KG1lc3NhZ2UsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghb3B0aW9ucylcbiAgICAgICAgICAgICAgICBvcHRpb25zID0ge307XG4gICAgICAgICAgICB2YXIgb2JqZWN0ID0ge307XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5hcnJheXMgfHwgb3B0aW9ucy5kZWZhdWx0cykge1xuICAgICAgICAgICAgICAgIG9iamVjdC5ub2RlID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0LmluaXRpYWxpemVyID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0LmlucHV0ID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0Lm91dHB1dCA9IFtdO1xuICAgICAgICAgICAgICAgIG9iamVjdC52YWx1ZUluZm8gPSBbXTtcbiAgICAgICAgICAgICAgICBvYmplY3QucXVhbnRpemF0aW9uQW5ub3RhdGlvbiA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGVmYXVsdHMpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QubmFtZSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvY1N0cmluZyA9IFwiXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5ub2RlICYmIG1lc3NhZ2Uubm9kZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3Qubm9kZSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5ub2RlLmxlbmd0aDsgKytqKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3Qubm9kZVtqXSA9ICRyb290Lm9ubnguTm9kZVByb3RvLnRvT2JqZWN0KG1lc3NhZ2Uubm9kZVtqXSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5uYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm5hbWVcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0Lm5hbWUgPSBtZXNzYWdlLm5hbWU7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pbml0aWFsaXplciAmJiBtZXNzYWdlLmluaXRpYWxpemVyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5pbml0aWFsaXplciA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5pbml0aWFsaXplci5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmluaXRpYWxpemVyW2pdID0gJHJvb3Qub25ueC5UZW5zb3JQcm90by50b09iamVjdChtZXNzYWdlLmluaXRpYWxpemVyW2pdLCBvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvY1N0cmluZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb2NTdHJpbmdcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvY1N0cmluZyA9IG1lc3NhZ2UuZG9jU3RyaW5nO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW5wdXQgJiYgbWVzc2FnZS5pbnB1dC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QuaW5wdXQgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2UuaW5wdXQubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5pbnB1dFtqXSA9ICRyb290Lm9ubnguVmFsdWVJbmZvUHJvdG8udG9PYmplY3QobWVzc2FnZS5pbnB1dFtqXSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5vdXRwdXQgJiYgbWVzc2FnZS5vdXRwdXQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0Lm91dHB1dCA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5vdXRwdXQubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5vdXRwdXRbal0gPSAkcm9vdC5vbm54LlZhbHVlSW5mb1Byb3RvLnRvT2JqZWN0KG1lc3NhZ2Uub3V0cHV0W2pdLCBvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnZhbHVlSW5mbyAmJiBtZXNzYWdlLnZhbHVlSW5mby5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QudmFsdWVJbmZvID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLnZhbHVlSW5mby5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnZhbHVlSW5mb1tqXSA9ICRyb290Lm9ubnguVmFsdWVJbmZvUHJvdG8udG9PYmplY3QobWVzc2FnZS52YWx1ZUluZm9bal0sIG9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UucXVhbnRpemF0aW9uQW5ub3RhdGlvbiAmJiBtZXNzYWdlLnF1YW50aXphdGlvbkFubm90YXRpb24ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LnF1YW50aXphdGlvbkFubm90YXRpb24gPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2UucXVhbnRpemF0aW9uQW5ub3RhdGlvbi5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnF1YW50aXphdGlvbkFubm90YXRpb25bal0gPSAkcm9vdC5vbm54LlRlbnNvckFubm90YXRpb24udG9PYmplY3QobWVzc2FnZS5xdWFudGl6YXRpb25Bbm5vdGF0aW9uW2pdLCBvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnZlcnRzIHRoaXMgR3JhcGhQcm90byB0byBKU09OLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdG9KU09OXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LkdyYXBoUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gSlNPTiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIEdyYXBoUHJvdG8ucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLnRvT2JqZWN0KHRoaXMsICRwcm90b2J1Zi51dGlsLnRvSlNPTk9wdGlvbnMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJldHVybiBHcmFwaFByb3RvO1xuICAgIH0pKCk7XG5cbiAgICBvbm54LlRlbnNvclByb3RvID0gKGZ1bmN0aW9uKCkge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQcm9wZXJ0aWVzIG9mIGEgVGVuc29yUHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBpbnRlcmZhY2UgSVRlbnNvclByb3RvXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPG51bWJlcnxMb25nPnxudWxsfSBbZGltc10gVGVuc29yUHJvdG8gZGltc1xuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcnxudWxsfSBbZGF0YVR5cGVdIFRlbnNvclByb3RvIGRhdGFUeXBlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7b25ueC5UZW5zb3JQcm90by5JU2VnbWVudHxudWxsfSBbc2VnbWVudF0gVGVuc29yUHJvdG8gc2VnbWVudFxuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5LjxudW1iZXI+fG51bGx9IFtmbG9hdERhdGFdIFRlbnNvclByb3RvIGZsb2F0RGF0YVxuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5LjxudW1iZXI+fG51bGx9IFtpbnQzMkRhdGFdIFRlbnNvclByb3RvIGludDMyRGF0YVxuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5LjxVaW50OEFycmF5PnxudWxsfSBbc3RyaW5nRGF0YV0gVGVuc29yUHJvdG8gc3RyaW5nRGF0YVxuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5LjxudW1iZXJ8TG9uZz58bnVsbH0gW2ludDY0RGF0YV0gVGVuc29yUHJvdG8gaW50NjREYXRhXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtuYW1lXSBUZW5zb3JQcm90byBuYW1lXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtkb2NTdHJpbmddIFRlbnNvclByb3RvIGRvY1N0cmluZ1xuICAgICAgICAgKiBAcHJvcGVydHkge1VpbnQ4QXJyYXl8bnVsbH0gW3Jhd0RhdGFdIFRlbnNvclByb3RvIHJhd0RhdGFcbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48b25ueC5JU3RyaW5nU3RyaW5nRW50cnlQcm90bz58bnVsbH0gW2V4dGVybmFsRGF0YV0gVGVuc29yUHJvdG8gZXh0ZXJuYWxEYXRhXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7b25ueC5UZW5zb3JQcm90by5EYXRhTG9jYXRpb258bnVsbH0gW2RhdGFMb2NhdGlvbl0gVGVuc29yUHJvdG8gZGF0YUxvY2F0aW9uXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7QXJyYXkuPG51bWJlcj58bnVsbH0gW2RvdWJsZURhdGFdIFRlbnNvclByb3RvIGRvdWJsZURhdGFcbiAgICAgICAgICogQHByb3BlcnR5IHtBcnJheS48bnVtYmVyfExvbmc+fG51bGx9IFt1aW50NjREYXRhXSBUZW5zb3JQcm90byB1aW50NjREYXRhXG4gICAgICAgICAqL1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IFRlbnNvclByb3RvLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAY2xhc3NkZXNjIFJlcHJlc2VudHMgYSBUZW5zb3JQcm90by5cbiAgICAgICAgICogQGltcGxlbWVudHMgSVRlbnNvclByb3RvXG4gICAgICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVRlbnNvclByb3RvPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBUZW5zb3JQcm90byhwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICB0aGlzLmRpbXMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuZmxvYXREYXRhID0gW107XG4gICAgICAgICAgICB0aGlzLmludDMyRGF0YSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5zdHJpbmdEYXRhID0gW107XG4gICAgICAgICAgICB0aGlzLmludDY0RGF0YSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5leHRlcm5hbERhdGEgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuZG91YmxlRGF0YSA9IFtdO1xuICAgICAgICAgICAgdGhpcy51aW50NjREYXRhID0gW107XG4gICAgICAgICAgICBpZiAocHJvcGVydGllcylcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyksIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXNba2V5c1tpXV0gIT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNba2V5c1tpXV0gPSBwcm9wZXJ0aWVzW2tleXNbaV1dO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRlbnNvclByb3RvIGRpbXMuXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5LjxudW1iZXJ8TG9uZz59IGRpbXNcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JQcm90by5wcm90b3R5cGUuZGltcyA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRlbnNvclByb3RvIGRhdGFUeXBlLlxuICAgICAgICAgKiBAbWVtYmVyIHtudW1iZXJ9IGRhdGFUeXBlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8ucHJvdG90eXBlLmRhdGFUeXBlID0gMDtcblxuICAgICAgICAvKipcbiAgICAgICAgICogVGVuc29yUHJvdG8gc2VnbWVudC5cbiAgICAgICAgICogQG1lbWJlciB7b25ueC5UZW5zb3JQcm90by5JU2VnbWVudHxudWxsfHVuZGVmaW5lZH0gc2VnbWVudFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLnByb3RvdHlwZS5zZWdtZW50ID0gbnVsbDtcblxuICAgICAgICAvKipcbiAgICAgICAgICogVGVuc29yUHJvdG8gZmxvYXREYXRhLlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48bnVtYmVyPn0gZmxvYXREYXRhXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8ucHJvdG90eXBlLmZsb2F0RGF0YSA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRlbnNvclByb3RvIGludDMyRGF0YS5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG51bWJlcj59IGludDMyRGF0YVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLnByb3RvdHlwZS5pbnQzMkRhdGEgPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUZW5zb3JQcm90byBzdHJpbmdEYXRhLlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48VWludDhBcnJheT59IHN0cmluZ0RhdGFcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JQcm90by5wcm90b3R5cGUuc3RyaW5nRGF0YSA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRlbnNvclByb3RvIGludDY0RGF0YS5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG51bWJlcnxMb25nPn0gaW50NjREYXRhXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8ucHJvdG90eXBlLmludDY0RGF0YSA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRlbnNvclByb3RvIG5hbWUuXG4gICAgICAgICAqIEBtZW1iZXIge3N0cmluZ30gbmFtZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLnByb3RvdHlwZS5uYW1lID0gXCJcIjtcblxuICAgICAgICAvKipcbiAgICAgICAgICogVGVuc29yUHJvdG8gZG9jU3RyaW5nLlxuICAgICAgICAgKiBAbWVtYmVyIHtzdHJpbmd9IGRvY1N0cmluZ1xuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLnByb3RvdHlwZS5kb2NTdHJpbmcgPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUZW5zb3JQcm90byByYXdEYXRhLlxuICAgICAgICAgKiBAbWVtYmVyIHtVaW50OEFycmF5fSByYXdEYXRhXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8ucHJvdG90eXBlLnJhd0RhdGEgPSAkdXRpbC5uZXdCdWZmZXIoW10pO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUZW5zb3JQcm90byBleHRlcm5hbERhdGEuXG4gICAgICAgICAqIEBtZW1iZXIge0FycmF5Ljxvbm54LklTdHJpbmdTdHJpbmdFbnRyeVByb3RvPn0gZXh0ZXJuYWxEYXRhXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8ucHJvdG90eXBlLmV4dGVybmFsRGF0YSA9ICR1dGlsLmVtcHR5QXJyYXk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFRlbnNvclByb3RvIGRhdGFMb2NhdGlvbi5cbiAgICAgICAgICogQG1lbWJlciB7b25ueC5UZW5zb3JQcm90by5EYXRhTG9jYXRpb259IGRhdGFMb2NhdGlvblxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLnByb3RvdHlwZS5kYXRhTG9jYXRpb24gPSAwO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUZW5zb3JQcm90byBkb3VibGVEYXRhLlxuICAgICAgICAgKiBAbWVtYmVyIHtBcnJheS48bnVtYmVyPn0gZG91YmxlRGF0YVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLnByb3RvdHlwZS5kb3VibGVEYXRhID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogVGVuc29yUHJvdG8gdWludDY0RGF0YS5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG51bWJlcnxMb25nPn0gdWludDY0RGF0YVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLnByb3RvdHlwZS51aW50NjREYXRhID0gJHV0aWwuZW1wdHlBcnJheTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIG5ldyBUZW5zb3JQcm90byBpbnN0YW5jZSB1c2luZyB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBjcmVhdGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVRlbnNvclByb3RvPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclByb3RvfSBUZW5zb3JQcm90byBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8uY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgVGVuc29yUHJvdG8ocHJvcGVydGllcyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBUZW5zb3JQcm90byBtZXNzYWdlLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LlRlbnNvclByb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklUZW5zb3JQcm90b30gbWVzc2FnZSBUZW5zb3JQcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLmVuY29kZSA9IGZ1bmN0aW9uIGVuY29kZShtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIGlmICghd3JpdGVyKVxuICAgICAgICAgICAgICAgIHdyaXRlciA9ICRXcml0ZXIuY3JlYXRlKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kaW1zICE9IG51bGwgJiYgbWVzc2FnZS5kaW1zLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMSwgd2lyZVR5cGUgMiA9Ki8xMCkuZm9yaygpO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5kaW1zLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIuaW50NjQobWVzc2FnZS5kaW1zW2ldKTtcbiAgICAgICAgICAgICAgICB3cml0ZXIubGRlbGltKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kYXRhVHlwZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkYXRhVHlwZVwiKSlcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDIsIHdpcmVUeXBlIDAgPSovMTYpLmludDMyKG1lc3NhZ2UuZGF0YVR5cGUpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uuc2VnbWVudCAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJzZWdtZW50XCIpKVxuICAgICAgICAgICAgICAgICRyb290Lm9ubnguVGVuc29yUHJvdG8uU2VnbWVudC5lbmNvZGUobWVzc2FnZS5zZWdtZW50LCB3cml0ZXIudWludDMyKC8qIGlkIDMsIHdpcmVUeXBlIDIgPSovMjYpLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5mbG9hdERhdGEgIT0gbnVsbCAmJiBtZXNzYWdlLmZsb2F0RGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDQsIHdpcmVUeXBlIDIgPSovMzQpLmZvcmsoKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuZmxvYXREYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIuZmxvYXQobWVzc2FnZS5mbG9hdERhdGFbaV0pO1xuICAgICAgICAgICAgICAgIHdyaXRlci5sZGVsaW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmludDMyRGF0YSAhPSBudWxsICYmIG1lc3NhZ2UuaW50MzJEYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgNSwgd2lyZVR5cGUgMiA9Ki80MikuZm9yaygpO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5pbnQzMkRhdGEubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci5pbnQzMihtZXNzYWdlLmludDMyRGF0YVtpXSk7XG4gICAgICAgICAgICAgICAgd3JpdGVyLmxkZWxpbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uuc3RyaW5nRGF0YSAhPSBudWxsICYmIG1lc3NhZ2Uuc3RyaW5nRGF0YS5sZW5ndGgpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLnN0cmluZ0RhdGEubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgNiwgd2lyZVR5cGUgMiA9Ki81MCkuYnl0ZXMobWVzc2FnZS5zdHJpbmdEYXRhW2ldKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmludDY0RGF0YSAhPSBudWxsICYmIG1lc3NhZ2UuaW50NjREYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgNywgd2lyZVR5cGUgMiA9Ki81OCkuZm9yaygpO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5pbnQ2NERhdGEubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci5pbnQ2NChtZXNzYWdlLmludDY0RGF0YVtpXSk7XG4gICAgICAgICAgICAgICAgd3JpdGVyLmxkZWxpbSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UubmFtZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJuYW1lXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgOCwgd2lyZVR5cGUgMiA9Ki82Nikuc3RyaW5nKG1lc3NhZ2UubmFtZSk7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5yYXdEYXRhICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInJhd0RhdGFcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCA5LCB3aXJlVHlwZSAyID0qLzc0KS5ieXRlcyhtZXNzYWdlLnJhd0RhdGEpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG91YmxlRGF0YSAhPSBudWxsICYmIG1lc3NhZ2UuZG91YmxlRGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDEwLCB3aXJlVHlwZSAyID0qLzgyKS5mb3JrKCk7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmRvdWJsZURhdGEubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci5kb3VibGUobWVzc2FnZS5kb3VibGVEYXRhW2ldKTtcbiAgICAgICAgICAgICAgICB3cml0ZXIubGRlbGltKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS51aW50NjREYXRhICE9IG51bGwgJiYgbWVzc2FnZS51aW50NjREYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMTEsIHdpcmVUeXBlIDIgPSovOTApLmZvcmsoKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UudWludDY0RGF0YS5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQ2NChtZXNzYWdlLnVpbnQ2NERhdGFbaV0pO1xuICAgICAgICAgICAgICAgIHdyaXRlci5sZGVsaW0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvY1N0cmluZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb2NTdHJpbmdcIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAxMiwgd2lyZVR5cGUgMiA9Ki85OCkuc3RyaW5nKG1lc3NhZ2UuZG9jU3RyaW5nKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmV4dGVybmFsRGF0YSAhPSBudWxsICYmIG1lc3NhZ2UuZXh0ZXJuYWxEYXRhLmxlbmd0aClcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuZXh0ZXJuYWxEYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICAkcm9vdC5vbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG8uZW5jb2RlKG1lc3NhZ2UuZXh0ZXJuYWxEYXRhW2ldLCB3cml0ZXIudWludDMyKC8qIGlkIDEzLCB3aXJlVHlwZSAyID0qLzEwNikuZm9yaygpKS5sZGVsaW0oKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRhdGFMb2NhdGlvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkYXRhTG9jYXRpb25cIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAxNCwgd2lyZVR5cGUgMCA9Ki8xMTIpLmludDMyKG1lc3NhZ2UuZGF0YUxvY2F0aW9uKTtcbiAgICAgICAgICAgIHJldHVybiB3cml0ZXI7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBUZW5zb3JQcm90byBtZXNzYWdlLCBsZW5ndGggZGVsaW1pdGVkLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LlRlbnNvclByb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklUZW5zb3JQcm90b30gbWVzc2FnZSBUZW5zb3JQcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclByb3RvLmVuY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZChtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVuY29kZShtZXNzYWdlLCB3cml0ZXIpLmxkZWxpbSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGEgVGVuc29yUHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlci5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aF0gTWVzc2FnZSBsZW5ndGggaWYga25vd24gYmVmb3JlaGFuZFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UZW5zb3JQcm90b30gVGVuc29yUHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JQcm90by5kZWNvZGUgPSBmdW5jdGlvbiBkZWNvZGUocmVhZGVyLCBsZW5ndGgpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9ICRSZWFkZXIuY3JlYXRlKHJlYWRlcik7XG4gICAgICAgICAgICB2YXIgZW5kID0gbGVuZ3RoID09PSB1bmRlZmluZWQgPyByZWFkZXIubGVuIDogcmVhZGVyLnBvcyArIGxlbmd0aCwgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LlRlbnNvclByb3RvKCk7XG4gICAgICAgICAgICB3aGlsZSAocmVhZGVyLnBvcyA8IGVuZCkge1xuICAgICAgICAgICAgICAgIHZhciB0YWcgPSByZWFkZXIudWludDMyKCk7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0YWcgPj4+IDMpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2UuZGltcyAmJiBtZXNzYWdlLmRpbXMubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGltcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHRhZyAmIDcpID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZW5kMiA9IHJlYWRlci51aW50MzIoKSArIHJlYWRlci5wb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAocmVhZGVyLnBvcyA8IGVuZDIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kaW1zLnB1c2gocmVhZGVyLmludDY0KCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGltcy5wdXNoKHJlYWRlci5pbnQ2NCgpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRhdGFUeXBlID0gcmVhZGVyLmludDMyKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5zZWdtZW50ID0gJHJvb3Qub25ueC5UZW5zb3JQcm90by5TZWdtZW50LmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5mbG9hdERhdGEgJiYgbWVzc2FnZS5mbG9hdERhdGEubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZmxvYXREYXRhID0gW107XG4gICAgICAgICAgICAgICAgICAgIGlmICgodGFnICYgNykgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlbmQyID0gcmVhZGVyLnVpbnQzMigpICsgcmVhZGVyLnBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kMilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmZsb2F0RGF0YS5wdXNoKHJlYWRlci5mbG9hdCgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmZsb2F0RGF0YS5wdXNoKHJlYWRlci5mbG9hdCgpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLmludDMyRGF0YSAmJiBtZXNzYWdlLmludDMyRGF0YS5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5pbnQzMkRhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCh0YWcgJiA3KSA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVuZDIgPSByZWFkZXIudWludDMyKCkgKyByZWFkZXIucG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW50MzJEYXRhLnB1c2gocmVhZGVyLmludDMyKCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW50MzJEYXRhLnB1c2gocmVhZGVyLmludDMyKCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2Uuc3RyaW5nRGF0YSAmJiBtZXNzYWdlLnN0cmluZ0RhdGEubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2Uuc3RyaW5nRGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnN0cmluZ0RhdGEucHVzaChyZWFkZXIuYnl0ZXMoKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNzpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5pbnQ2NERhdGEgJiYgbWVzc2FnZS5pbnQ2NERhdGEubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW50NjREYXRhID0gW107XG4gICAgICAgICAgICAgICAgICAgIGlmICgodGFnICYgNykgPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBlbmQyID0gcmVhZGVyLnVpbnQzMigpICsgcmVhZGVyLnBvcztcbiAgICAgICAgICAgICAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kMilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmludDY0RGF0YS5wdXNoKHJlYWRlci5pbnQ2NCgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmludDY0RGF0YS5wdXNoKHJlYWRlci5pbnQ2NCgpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA4OlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLm5hbWUgPSByZWFkZXIuc3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTI6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG9jU3RyaW5nID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDk6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UucmF3RGF0YSA9IHJlYWRlci5ieXRlcygpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDEzOlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLmV4dGVybmFsRGF0YSAmJiBtZXNzYWdlLmV4dGVybmFsRGF0YS5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5leHRlcm5hbERhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5leHRlcm5hbERhdGEucHVzaCgkcm9vdC5vbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG8uZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTQ6XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGF0YUxvY2F0aW9uID0gcmVhZGVyLmludDMyKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2UuZG91YmxlRGF0YSAmJiBtZXNzYWdlLmRvdWJsZURhdGEubGVuZ3RoKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG91YmxlRGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoKHRhZyAmIDcpID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZW5kMiA9IHJlYWRlci51aW50MzIoKSArIHJlYWRlci5wb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAocmVhZGVyLnBvcyA8IGVuZDIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kb3VibGVEYXRhLnB1c2gocmVhZGVyLmRvdWJsZSgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRvdWJsZURhdGEucHVzaChyZWFkZXIuZG91YmxlKCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDExOlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLnVpbnQ2NERhdGEgJiYgbWVzc2FnZS51aW50NjREYXRhLmxlbmd0aCkpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnVpbnQ2NERhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCh0YWcgJiA3KSA9PT0gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGVuZDIgPSByZWFkZXIudWludDMyKCkgKyByZWFkZXIucG9zO1xuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UudWludDY0RGF0YS5wdXNoKHJlYWRlci51aW50NjQoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS51aW50NjREYXRhLnB1c2gocmVhZGVyLnVpbnQ2NCgpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnNraXBUeXBlKHRhZyAmIDcpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhIFRlbnNvclByb3RvIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIsIGxlbmd0aCBkZWxpbWl0ZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHJldHVybnMge29ubnguVGVuc29yUHJvdG99IFRlbnNvclByb3RvXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8uZGVjb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkKHJlYWRlcikge1xuICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgcmVhZGVyID0gbmV3ICRSZWFkZXIocmVhZGVyKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFZlcmlmaWVzIGEgVGVuc29yUHJvdG8gbWVzc2FnZS5cbiAgICAgICAgICogQGZ1bmN0aW9uIHZlcmlmeVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG1lc3NhZ2UgUGxhaW4gb2JqZWN0IHRvIHZlcmlmeVxuICAgICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9IGBudWxsYCBpZiB2YWxpZCwgb3RoZXJ3aXNlIHRoZSByZWFzb24gd2h5IGl0IGlzIG5vdFxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8udmVyaWZ5ID0gZnVuY3Rpb24gdmVyaWZ5KG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSAhPT0gXCJvYmplY3RcIiB8fCBtZXNzYWdlID09PSBudWxsKVxuICAgICAgICAgICAgICAgIHJldHVybiBcIm9iamVjdCBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGltcyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkaW1zXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UuZGltcykpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRpbXM6IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmRpbXMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuZGltc1tpXSkgJiYgIShtZXNzYWdlLmRpbXNbaV0gJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuZGltc1tpXS5sb3cpICYmICR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmRpbXNbaV0uaGlnaCkpKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZGltczogaW50ZWdlcnxMb25nW10gZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRhdGFUeXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRhdGFUeXBlXCIpKVxuICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuZGF0YVR5cGUpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJkYXRhVHlwZTogaW50ZWdlciBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uuc2VnbWVudCAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJzZWdtZW50XCIpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5UZW5zb3JQcm90by5TZWdtZW50LnZlcmlmeShtZXNzYWdlLnNlZ21lbnQpO1xuICAgICAgICAgICAgICAgIGlmIChlcnJvcilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwic2VnbWVudC5cIiArIGVycm9yO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZmxvYXREYXRhICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImZsb2F0RGF0YVwiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLmZsb2F0RGF0YSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImZsb2F0RGF0YTogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuZmxvYXREYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UuZmxvYXREYXRhW2ldICE9PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZmxvYXREYXRhOiBudW1iZXJbXSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW50MzJEYXRhICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImludDMyRGF0YVwiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLmludDMyRGF0YSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImludDMyRGF0YTogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuaW50MzJEYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmludDMyRGF0YVtpXSkpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJpbnQzMkRhdGE6IGludGVnZXJbXSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2Uuc3RyaW5nRGF0YSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJzdHJpbmdEYXRhXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2Uuc3RyaW5nRGF0YSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInN0cmluZ0RhdGE6IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLnN0cmluZ0RhdGEubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmICghKG1lc3NhZ2Uuc3RyaW5nRGF0YVtpXSAmJiB0eXBlb2YgbWVzc2FnZS5zdHJpbmdEYXRhW2ldLmxlbmd0aCA9PT0gXCJudW1iZXJcIiB8fCAkdXRpbC5pc1N0cmluZyhtZXNzYWdlLnN0cmluZ0RhdGFbaV0pKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcInN0cmluZ0RhdGE6IGJ1ZmZlcltdIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5pbnQ2NERhdGEgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiaW50NjREYXRhXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UuaW50NjREYXRhKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiaW50NjREYXRhOiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5pbnQ2NERhdGEubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuaW50NjREYXRhW2ldKSAmJiAhKG1lc3NhZ2UuaW50NjREYXRhW2ldICYmICR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmludDY0RGF0YVtpXS5sb3cpICYmICR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmludDY0RGF0YVtpXS5oaWdoKSkpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJpbnQ2NERhdGE6IGludGVnZXJ8TG9uZ1tdIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5uYW1lICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcIm5hbWVcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLm5hbWUpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJuYW1lOiBzdHJpbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvY1N0cmluZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb2NTdHJpbmdcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLmRvY1N0cmluZykpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRvY1N0cmluZzogc3RyaW5nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5yYXdEYXRhICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInJhd0RhdGFcIikpXG4gICAgICAgICAgICAgICAgaWYgKCEobWVzc2FnZS5yYXdEYXRhICYmIHR5cGVvZiBtZXNzYWdlLnJhd0RhdGEubGVuZ3RoID09PSBcIm51bWJlclwiIHx8ICR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UucmF3RGF0YSkpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJyYXdEYXRhOiBidWZmZXIgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmV4dGVybmFsRGF0YSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJleHRlcm5hbERhdGFcIikpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkobWVzc2FnZS5leHRlcm5hbERhdGEpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJleHRlcm5hbERhdGE6IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmV4dGVybmFsRGF0YS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXJyb3IgPSAkcm9vdC5vbm54LlN0cmluZ1N0cmluZ0VudHJ5UHJvdG8udmVyaWZ5KG1lc3NhZ2UuZXh0ZXJuYWxEYXRhW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZXh0ZXJuYWxEYXRhLlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGF0YUxvY2F0aW9uICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRhdGFMb2NhdGlvblwiKSlcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKG1lc3NhZ2UuZGF0YUxvY2F0aW9uKSB7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZGF0YUxvY2F0aW9uOiBlbnVtIHZhbHVlIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZG91YmxlRGF0YSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb3VibGVEYXRhXCIpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG1lc3NhZ2UuZG91YmxlRGF0YSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRvdWJsZURhdGE6IGFycmF5IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtZXNzYWdlLmRvdWJsZURhdGEubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZS5kb3VibGVEYXRhW2ldICE9PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZG91YmxlRGF0YTogbnVtYmVyW10gZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnVpbnQ2NERhdGEgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidWludDY0RGF0YVwiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLnVpbnQ2NERhdGEpKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJ1aW50NjREYXRhOiBhcnJheSBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS51aW50NjREYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLnVpbnQ2NERhdGFbaV0pICYmICEobWVzc2FnZS51aW50NjREYXRhW2ldICYmICR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLnVpbnQ2NERhdGFbaV0ubG93KSAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS51aW50NjREYXRhW2ldLmhpZ2gpKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcInVpbnQ2NERhdGE6IGludGVnZXJ8TG9uZ1tdIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIFRlbnNvclByb3RvIG1lc3NhZ2UgZnJvbSBhIHBsYWluIG9iamVjdC4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gdGhlaXIgcmVzcGVjdGl2ZSBpbnRlcm5hbCB0eXBlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGZyb21PYmplY3RcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBvYmplY3QgUGxhaW4gb2JqZWN0XG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclByb3RvfSBUZW5zb3JQcm90b1xuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8uZnJvbU9iamVjdCA9IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgICAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgJHJvb3Qub25ueC5UZW5zb3JQcm90bylcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5UZW5zb3JQcm90bygpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5kaW1zKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5kaW1zKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguVGVuc29yUHJvdG8uZGltczogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5kaW1zID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3QuZGltcy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKCR1dGlsLkxvbmcpXG4gICAgICAgICAgICAgICAgICAgICAgICAobWVzc2FnZS5kaW1zW2ldID0gJHV0aWwuTG9uZy5mcm9tVmFsdWUob2JqZWN0LmRpbXNbaV0pKS51bnNpZ25lZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmRpbXNbaV0gPT09IFwic3RyaW5nXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRpbXNbaV0gPSBwYXJzZUludChvYmplY3QuZGltc1tpXSwgMTApO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmRpbXNbaV0gPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRpbXNbaV0gPSBvYmplY3QuZGltc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5kaW1zW2ldID09PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kaW1zW2ldID0gbmV3ICR1dGlsLkxvbmdCaXRzKG9iamVjdC5kaW1zW2ldLmxvdyA+Pj4gMCwgb2JqZWN0LmRpbXNbaV0uaGlnaCA+Pj4gMCkudG9OdW1iZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvYmplY3QuZGF0YVR5cGUgIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmRhdGFUeXBlID0gb2JqZWN0LmRhdGFUeXBlIHwgMDtcbiAgICAgICAgICAgIGlmIChvYmplY3Quc2VnbWVudCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3Quc2VnbWVudCAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguVGVuc29yUHJvdG8uc2VnbWVudDogb2JqZWN0IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2Uuc2VnbWVudCA9ICRyb290Lm9ubnguVGVuc29yUHJvdG8uU2VnbWVudC5mcm9tT2JqZWN0KG9iamVjdC5zZWdtZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvYmplY3QuZmxvYXREYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5mbG9hdERhdGEpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5UZW5zb3JQcm90by5mbG9hdERhdGE6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UuZmxvYXREYXRhID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3QuZmxvYXREYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmZsb2F0RGF0YVtpXSA9IE51bWJlcihvYmplY3QuZmxvYXREYXRhW2ldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvYmplY3QuaW50MzJEYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5pbnQzMkRhdGEpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5UZW5zb3JQcm90by5pbnQzMkRhdGE6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW50MzJEYXRhID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3QuaW50MzJEYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmludDMyRGF0YVtpXSA9IG9iamVjdC5pbnQzMkRhdGFbaV0gfCAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5zdHJpbmdEYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5zdHJpbmdEYXRhKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguVGVuc29yUHJvdG8uc3RyaW5nRGF0YTogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5zdHJpbmdEYXRhID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3Quc3RyaW5nRGF0YS5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3Quc3RyaW5nRGF0YVtpXSA9PT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICR1dGlsLmJhc2U2NC5kZWNvZGUob2JqZWN0LnN0cmluZ0RhdGFbaV0sIG1lc3NhZ2Uuc3RyaW5nRGF0YVtpXSA9ICR1dGlsLm5ld0J1ZmZlcigkdXRpbC5iYXNlNjQubGVuZ3RoKG9iamVjdC5zdHJpbmdEYXRhW2ldKSksIDApO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChvYmplY3Quc3RyaW5nRGF0YVtpXS5sZW5ndGgpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnN0cmluZ0RhdGFbaV0gPSBvYmplY3Quc3RyaW5nRGF0YVtpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvYmplY3QuaW50NjREYXRhKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KG9iamVjdC5pbnQ2NERhdGEpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5UZW5zb3JQcm90by5pbnQ2NERhdGE6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW50NjREYXRhID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBvYmplY3QuaW50NjREYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoJHV0aWwuTG9uZylcbiAgICAgICAgICAgICAgICAgICAgICAgIChtZXNzYWdlLmludDY0RGF0YVtpXSA9ICR1dGlsLkxvbmcuZnJvbVZhbHVlKG9iamVjdC5pbnQ2NERhdGFbaV0pKS51bnNpZ25lZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmludDY0RGF0YVtpXSA9PT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW50NjREYXRhW2ldID0gcGFyc2VJbnQob2JqZWN0LmludDY0RGF0YVtpXSwgMTApO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmludDY0RGF0YVtpXSA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaW50NjREYXRhW2ldID0gb2JqZWN0LmludDY0RGF0YVtpXTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5pbnQ2NERhdGFbaV0gPT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmludDY0RGF0YVtpXSA9IG5ldyAkdXRpbC5Mb25nQml0cyhvYmplY3QuaW50NjREYXRhW2ldLmxvdyA+Pj4gMCwgb2JqZWN0LmludDY0RGF0YVtpXS5oaWdoID4+PiAwKS50b051bWJlcigpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9iamVjdC5uYW1lICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5uYW1lID0gU3RyaW5nKG9iamVjdC5uYW1lKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QuZG9jU3RyaW5nICE9IG51bGwpXG4gICAgICAgICAgICAgICAgbWVzc2FnZS5kb2NTdHJpbmcgPSBTdHJpbmcob2JqZWN0LmRvY1N0cmluZyk7XG4gICAgICAgICAgICBpZiAob2JqZWN0LnJhd0RhdGEgIT0gbnVsbClcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdC5yYXdEYXRhID09PSBcInN0cmluZ1wiKVxuICAgICAgICAgICAgICAgICAgICAkdXRpbC5iYXNlNjQuZGVjb2RlKG9iamVjdC5yYXdEYXRhLCBtZXNzYWdlLnJhd0RhdGEgPSAkdXRpbC5uZXdCdWZmZXIoJHV0aWwuYmFzZTY0Lmxlbmd0aChvYmplY3QucmF3RGF0YSkpLCAwKTtcbiAgICAgICAgICAgICAgICBlbHNlIGlmIChvYmplY3QucmF3RGF0YS5sZW5ndGgpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UucmF3RGF0YSA9IG9iamVjdC5yYXdEYXRhO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5leHRlcm5hbERhdGEpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0LmV4dGVybmFsRGF0YSkpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LlRlbnNvclByb3RvLmV4dGVybmFsRGF0YTogYXJyYXkgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgbWVzc2FnZS5leHRlcm5hbERhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC5leHRlcm5hbERhdGEubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QuZXh0ZXJuYWxEYXRhW2ldICE9PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguVGVuc29yUHJvdG8uZXh0ZXJuYWxEYXRhOiBvYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZXh0ZXJuYWxEYXRhW2ldID0gJHJvb3Qub25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvLmZyb21PYmplY3Qob2JqZWN0LmV4dGVybmFsRGF0YVtpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc3dpdGNoIChvYmplY3QuZGF0YUxvY2F0aW9uKSB7XG4gICAgICAgICAgICBjYXNlIFwiREVGQVVMVFwiOlxuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGF0YUxvY2F0aW9uID0gMDtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJFWFRFUk5BTFwiOlxuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGF0YUxvY2F0aW9uID0gMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvYmplY3QuZG91YmxlRGF0YSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvYmplY3QuZG91YmxlRGF0YSkpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LlRlbnNvclByb3RvLmRvdWJsZURhdGE6IGFycmF5IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG91YmxlRGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LmRvdWJsZURhdGEubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZG91YmxlRGF0YVtpXSA9IE51bWJlcihvYmplY3QuZG91YmxlRGF0YVtpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LnVpbnQ2NERhdGEpIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0LnVpbnQ2NERhdGEpKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5UZW5zb3JQcm90by51aW50NjREYXRhOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLnVpbnQ2NERhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC51aW50NjREYXRhLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoJHV0aWwuTG9uZylcbiAgICAgICAgICAgICAgICAgICAgICAgIChtZXNzYWdlLnVpbnQ2NERhdGFbaV0gPSAkdXRpbC5Mb25nLmZyb21WYWx1ZShvYmplY3QudWludDY0RGF0YVtpXSkpLnVuc2lnbmVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC51aW50NjREYXRhW2ldID09PSBcInN0cmluZ1wiKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS51aW50NjREYXRhW2ldID0gcGFyc2VJbnQob2JqZWN0LnVpbnQ2NERhdGFbaV0sIDEwKTtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC51aW50NjREYXRhW2ldID09PSBcIm51bWJlclwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS51aW50NjREYXRhW2ldID0gb2JqZWN0LnVpbnQ2NERhdGFbaV07XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QudWludDY0RGF0YVtpXSA9PT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UudWludDY0RGF0YVtpXSA9IG5ldyAkdXRpbC5Mb25nQml0cyhvYmplY3QudWludDY0RGF0YVtpXS5sb3cgPj4+IDAsIG9iamVjdC51aW50NjREYXRhW2ldLmhpZ2ggPj4+IDApLnRvTnVtYmVyKHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBwbGFpbiBvYmplY3QgZnJvbSBhIFRlbnNvclByb3RvIG1lc3NhZ2UuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIG90aGVyIHR5cGVzIGlmIHNwZWNpZmllZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LlRlbnNvclByb3RvfSBtZXNzYWdlIFRlbnNvclByb3RvXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLklDb252ZXJzaW9uT3B0aW9uc30gW29wdGlvbnNdIENvbnZlcnNpb24gb3B0aW9uc1xuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IFBsYWluIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8udG9PYmplY3QgPSBmdW5jdGlvbiB0b09iamVjdChtZXNzYWdlLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMpXG4gICAgICAgICAgICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgICAgICAgdmFyIG9iamVjdCA9IHt9O1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuYXJyYXlzIHx8IG9wdGlvbnMuZGVmYXVsdHMpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QuZGltcyA9IFtdO1xuICAgICAgICAgICAgICAgIG9iamVjdC5mbG9hdERhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICBvYmplY3QuaW50MzJEYXRhID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0LnN0cmluZ0RhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICBvYmplY3QuaW50NjREYXRhID0gW107XG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvdWJsZURhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICBvYmplY3QudWludDY0RGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgIG9iamVjdC5leHRlcm5hbERhdGEgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvcHRpb25zLmRlZmF1bHRzKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmRhdGFUeXBlID0gMDtcbiAgICAgICAgICAgICAgICBvYmplY3Quc2VnbWVudCA9IG51bGw7XG4gICAgICAgICAgICAgICAgb2JqZWN0Lm5hbWUgPSBcIlwiO1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmJ5dGVzID09PSBTdHJpbmcpXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5yYXdEYXRhID0gXCJcIjtcbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnJhd0RhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuYnl0ZXMgIT09IEFycmF5KVxuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnJhd0RhdGEgPSAkdXRpbC5uZXdCdWZmZXIob2JqZWN0LnJhd0RhdGEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvYmplY3QuZG9jU3RyaW5nID0gXCJcIjtcbiAgICAgICAgICAgICAgICBvYmplY3QuZGF0YUxvY2F0aW9uID0gb3B0aW9ucy5lbnVtcyA9PT0gU3RyaW5nID8gXCJERUZBVUxUXCIgOiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGltcyAmJiBtZXNzYWdlLmRpbXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmRpbXMgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2UuZGltcy5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlLmRpbXNbal0gPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QuZGltc1tqXSA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IFN0cmluZyhtZXNzYWdlLmRpbXNbal0pIDogbWVzc2FnZS5kaW1zW2pdO1xuICAgICAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QuZGltc1tqXSA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/ICR1dGlsLkxvbmcucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobWVzc2FnZS5kaW1zW2pdKSA6IG9wdGlvbnMubG9uZ3MgPT09IE51bWJlciA/IG5ldyAkdXRpbC5Mb25nQml0cyhtZXNzYWdlLmRpbXNbal0ubG93ID4+PiAwLCBtZXNzYWdlLmRpbXNbal0uaGlnaCA+Pj4gMCkudG9OdW1iZXIoKSA6IG1lc3NhZ2UuZGltc1tqXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRhdGFUeXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRhdGFUeXBlXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5kYXRhVHlwZSA9IG1lc3NhZ2UuZGF0YVR5cGU7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5zZWdtZW50ICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInNlZ21lbnRcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LnNlZ21lbnQgPSAkcm9vdC5vbm54LlRlbnNvclByb3RvLlNlZ21lbnQudG9PYmplY3QobWVzc2FnZS5zZWdtZW50LCBvcHRpb25zKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmZsb2F0RGF0YSAmJiBtZXNzYWdlLmZsb2F0RGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QuZmxvYXREYXRhID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLmZsb2F0RGF0YS5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmZsb2F0RGF0YVtqXSA9IG9wdGlvbnMuanNvbiAmJiAhaXNGaW5pdGUobWVzc2FnZS5mbG9hdERhdGFbal0pID8gU3RyaW5nKG1lc3NhZ2UuZmxvYXREYXRhW2pdKSA6IG1lc3NhZ2UuZmxvYXREYXRhW2pdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW50MzJEYXRhICYmIG1lc3NhZ2UuaW50MzJEYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5pbnQzMkRhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2UuaW50MzJEYXRhLmxlbmd0aDsgKytqKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuaW50MzJEYXRhW2pdID0gbWVzc2FnZS5pbnQzMkRhdGFbal07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5zdHJpbmdEYXRhICYmIG1lc3NhZ2Uuc3RyaW5nRGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3Quc3RyaW5nRGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS5zdHJpbmdEYXRhLmxlbmd0aDsgKytqKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3Quc3RyaW5nRGF0YVtqXSA9IG9wdGlvbnMuYnl0ZXMgPT09IFN0cmluZyA/ICR1dGlsLmJhc2U2NC5lbmNvZGUobWVzc2FnZS5zdHJpbmdEYXRhW2pdLCAwLCBtZXNzYWdlLnN0cmluZ0RhdGFbal0ubGVuZ3RoKSA6IG9wdGlvbnMuYnl0ZXMgPT09IEFycmF5ID8gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwobWVzc2FnZS5zdHJpbmdEYXRhW2pdKSA6IG1lc3NhZ2Uuc3RyaW5nRGF0YVtqXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmludDY0RGF0YSAmJiBtZXNzYWdlLmludDY0RGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QuaW50NjREYXRhID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLmludDY0RGF0YS5sZW5ndGg7ICsrailcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlLmludDY0RGF0YVtqXSA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC5pbnQ2NERhdGFbal0gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBTdHJpbmcobWVzc2FnZS5pbnQ2NERhdGFbal0pIDogbWVzc2FnZS5pbnQ2NERhdGFbal07XG4gICAgICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC5pbnQ2NERhdGFbal0gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyAkdXRpbC5Mb25nLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG1lc3NhZ2UuaW50NjREYXRhW2pdKSA6IG9wdGlvbnMubG9uZ3MgPT09IE51bWJlciA/IG5ldyAkdXRpbC5Mb25nQml0cyhtZXNzYWdlLmludDY0RGF0YVtqXS5sb3cgPj4+IDAsIG1lc3NhZ2UuaW50NjREYXRhW2pdLmhpZ2ggPj4+IDApLnRvTnVtYmVyKCkgOiBtZXNzYWdlLmludDY0RGF0YVtqXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLm5hbWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwibmFtZVwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QubmFtZSA9IG1lc3NhZ2UubmFtZTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnJhd0RhdGEgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwicmF3RGF0YVwiKSlcbiAgICAgICAgICAgICAgICBvYmplY3QucmF3RGF0YSA9IG9wdGlvbnMuYnl0ZXMgPT09IFN0cmluZyA/ICR1dGlsLmJhc2U2NC5lbmNvZGUobWVzc2FnZS5yYXdEYXRhLCAwLCBtZXNzYWdlLnJhd0RhdGEubGVuZ3RoKSA6IG9wdGlvbnMuYnl0ZXMgPT09IEFycmF5ID8gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwobWVzc2FnZS5yYXdEYXRhKSA6IG1lc3NhZ2UucmF3RGF0YTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvdWJsZURhdGEgJiYgbWVzc2FnZS5kb3VibGVEYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5kb3VibGVEYXRhID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtZXNzYWdlLmRvdWJsZURhdGEubGVuZ3RoOyArK2opXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5kb3VibGVEYXRhW2pdID0gb3B0aW9ucy5qc29uICYmICFpc0Zpbml0ZShtZXNzYWdlLmRvdWJsZURhdGFbal0pID8gU3RyaW5nKG1lc3NhZ2UuZG91YmxlRGF0YVtqXSkgOiBtZXNzYWdlLmRvdWJsZURhdGFbal07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS51aW50NjREYXRhICYmIG1lc3NhZ2UudWludDY0RGF0YS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QudWludDY0RGF0YSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbWVzc2FnZS51aW50NjREYXRhLmxlbmd0aDsgKytqKVxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UudWludDY0RGF0YVtqXSA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC51aW50NjREYXRhW2pdID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gU3RyaW5nKG1lc3NhZ2UudWludDY0RGF0YVtqXSkgOiBtZXNzYWdlLnVpbnQ2NERhdGFbal07XG4gICAgICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC51aW50NjREYXRhW2pdID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gJHV0aWwuTG9uZy5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChtZXNzYWdlLnVpbnQ2NERhdGFbal0pIDogb3B0aW9ucy5sb25ncyA9PT0gTnVtYmVyID8gbmV3ICR1dGlsLkxvbmdCaXRzKG1lc3NhZ2UudWludDY0RGF0YVtqXS5sb3cgPj4+IDAsIG1lc3NhZ2UudWludDY0RGF0YVtqXS5oaWdoID4+PiAwKS50b051bWJlcih0cnVlKSA6IG1lc3NhZ2UudWludDY0RGF0YVtqXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvY1N0cmluZyAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb2NTdHJpbmdcIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvY1N0cmluZyA9IG1lc3NhZ2UuZG9jU3RyaW5nO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZXh0ZXJuYWxEYXRhICYmIG1lc3NhZ2UuZXh0ZXJuYWxEYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5leHRlcm5hbERhdGEgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2UuZXh0ZXJuYWxEYXRhLmxlbmd0aDsgKytqKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuZXh0ZXJuYWxEYXRhW2pdID0gJHJvb3Qub25ueC5TdHJpbmdTdHJpbmdFbnRyeVByb3RvLnRvT2JqZWN0KG1lc3NhZ2UuZXh0ZXJuYWxEYXRhW2pdLCBvcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRhdGFMb2NhdGlvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkYXRhTG9jYXRpb25cIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmRhdGFMb2NhdGlvbiA9IG9wdGlvbnMuZW51bXMgPT09IFN0cmluZyA/ICRyb290Lm9ubnguVGVuc29yUHJvdG8uRGF0YUxvY2F0aW9uW21lc3NhZ2UuZGF0YUxvY2F0aW9uXSA6IG1lc3NhZ2UuZGF0YUxvY2F0aW9uO1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udmVydHMgdGhpcyBUZW5zb3JQcm90byB0byBKU09OLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdG9KU09OXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IEpTT04gb2JqZWN0XG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JQcm90by5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IudG9PYmplY3QodGhpcywgJHByb3RvYnVmLnV0aWwudG9KU09OT3B0aW9ucyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERhdGFUeXBlIGVudW0uXG4gICAgICAgICAqIEBuYW1lIG9ubnguVGVuc29yUHJvdG8uRGF0YVR5cGVcbiAgICAgICAgICogQGVudW0ge3N0cmluZ31cbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IFVOREVGSU5FRD0wIFVOREVGSU5FRCB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gRkxPQVQ9MSBGTE9BVCB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gVUlOVDg9MiBVSU5UOCB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gSU5UOD0zIElOVDggdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IFVJTlQxNj00IFVJTlQxNiB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gSU5UMTY9NSBJTlQxNiB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gSU5UMzI9NiBJTlQzMiB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gSU5UNjQ9NyBJTlQ2NCB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gU1RSSU5HPTggU1RSSU5HIHZhbHVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBCT09MPTkgQk9PTCB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gRkxPQVQxNj0xMCBGTE9BVDE2IHZhbHVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBET1VCTEU9MTEgRE9VQkxFIHZhbHVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBVSU5UMzI9MTIgVUlOVDMyIHZhbHVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBVSU5UNjQ9MTMgVUlOVDY0IHZhbHVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBDT01QTEVYNjQ9MTQgQ09NUExFWDY0IHZhbHVlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBDT01QTEVYMTI4PTE1IENPTVBMRVgxMjggdmFsdWVcbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IEJGTE9BVDE2PTE2IEJGTE9BVDE2IHZhbHVlXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JQcm90by5EYXRhVHlwZSA9IChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHZhciB2YWx1ZXNCeUlkID0ge30sIHZhbHVlcyA9IE9iamVjdC5jcmVhdGUodmFsdWVzQnlJZCk7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFswXSA9IFwiVU5ERUZJTkVEXCJdID0gMDtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzFdID0gXCJGTE9BVFwiXSA9IDE7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFsyXSA9IFwiVUlOVDhcIl0gPSAyO1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbM10gPSBcIklOVDhcIl0gPSAzO1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbNF0gPSBcIlVJTlQxNlwiXSA9IDQ7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFs1XSA9IFwiSU5UMTZcIl0gPSA1O1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbNl0gPSBcIklOVDMyXCJdID0gNjtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzddID0gXCJJTlQ2NFwiXSA9IDc7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFs4XSA9IFwiU1RSSU5HXCJdID0gODtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzldID0gXCJCT09MXCJdID0gOTtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzEwXSA9IFwiRkxPQVQxNlwiXSA9IDEwO1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbMTFdID0gXCJET1VCTEVcIl0gPSAxMTtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzEyXSA9IFwiVUlOVDMyXCJdID0gMTI7XG4gICAgICAgICAgICB2YWx1ZXNbdmFsdWVzQnlJZFsxM10gPSBcIlVJTlQ2NFwiXSA9IDEzO1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbMTRdID0gXCJDT01QTEVYNjRcIl0gPSAxNDtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzE1XSA9IFwiQ09NUExFWDEyOFwiXSA9IDE1O1xuICAgICAgICAgICAgdmFsdWVzW3ZhbHVlc0J5SWRbMTZdID0gXCJCRkxPQVQxNlwiXSA9IDE2O1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlcztcbiAgICAgICAgfSkoKTtcblxuICAgICAgICBUZW5zb3JQcm90by5TZWdtZW50ID0gKGZ1bmN0aW9uKCkge1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFByb3BlcnRpZXMgb2YgYSBTZWdtZW50LlxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG9cbiAgICAgICAgICAgICAqIEBpbnRlcmZhY2UgSVNlZ21lbnRcbiAgICAgICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfExvbmd8bnVsbH0gW2JlZ2luXSBTZWdtZW50IGJlZ2luXG4gICAgICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcnxMb25nfG51bGx9IFtlbmRdIFNlZ21lbnQgZW5kXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IFNlZ21lbnQuXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90b1xuICAgICAgICAgICAgICogQGNsYXNzZGVzYyBSZXByZXNlbnRzIGEgU2VnbWVudC5cbiAgICAgICAgICAgICAqIEBpbXBsZW1lbnRzIElTZWdtZW50XG4gICAgICAgICAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgICAgICAgICAqIEBwYXJhbSB7b25ueC5UZW5zb3JQcm90by5JU2VnbWVudD19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBmdW5jdGlvbiBTZWdtZW50KHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcylcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIga2V5cyA9IE9iamVjdC5rZXlzKHByb3BlcnRpZXMpLCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllc1trZXlzW2ldXSAhPSBudWxsKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNba2V5c1tpXV0gPSBwcm9wZXJ0aWVzW2tleXNbaV1dO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNlZ21lbnQgYmVnaW4uXG4gICAgICAgICAgICAgKiBAbWVtYmVyIHtudW1iZXJ8TG9uZ30gYmVnaW5cbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvLlNlZ21lbnRcbiAgICAgICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBTZWdtZW50LnByb3RvdHlwZS5iZWdpbiA9ICR1dGlsLkxvbmcgPyAkdXRpbC5Mb25nLmZyb21CaXRzKDAsMCxmYWxzZSkgOiAwO1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNlZ21lbnQgZW5kLlxuICAgICAgICAgICAgICogQG1lbWJlciB7bnVtYmVyfExvbmd9IGVuZFxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG8uU2VnbWVudFxuICAgICAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIFNlZ21lbnQucHJvdG90eXBlLmVuZCA9ICR1dGlsLkxvbmcgPyAkdXRpbC5Mb25nLmZyb21CaXRzKDAsMCxmYWxzZSkgOiAwO1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIENyZWF0ZXMgYSBuZXcgU2VnbWVudCBpbnN0YW5jZSB1c2luZyB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gY3JlYXRlXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90by5TZWdtZW50XG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0ge29ubnguVGVuc29yUHJvdG8uSVNlZ21lbnQ9fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclByb3RvLlNlZ21lbnR9IFNlZ21lbnQgaW5zdGFuY2VcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgU2VnbWVudC5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUocHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU2VnbWVudChwcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIFNlZ21lbnQgbWVzc2FnZS4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5UZW5zb3JQcm90by5TZWdtZW50LnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZVxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG8uU2VnbWVudFxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHtvbm54LlRlbnNvclByb3RvLklTZWdtZW50fSBtZXNzYWdlIFNlZ21lbnQgbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5Xcml0ZXJ9IFt3cml0ZXJdIFdyaXRlciB0byBlbmNvZGUgdG9cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgU2VnbWVudC5lbmNvZGUgPSBmdW5jdGlvbiBlbmNvZGUobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF3cml0ZXIpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlciA9ICRXcml0ZXIuY3JlYXRlKCk7XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuYmVnaW4gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiYmVnaW5cIikpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMSwgd2lyZVR5cGUgMCA9Ki84KS5pbnQ2NChtZXNzYWdlLmJlZ2luKTtcbiAgICAgICAgICAgICAgICBpZiAobWVzc2FnZS5lbmQgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZW5kXCIpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDIsIHdpcmVUeXBlIDAgPSovMTYpLmludDY0KG1lc3NhZ2UuZW5kKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gd3JpdGVyO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBFbmNvZGVzIHRoZSBzcGVjaWZpZWQgU2VnbWVudCBtZXNzYWdlLCBsZW5ndGggZGVsaW1pdGVkLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LlRlbnNvclByb3RvLlNlZ21lbnQudmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90by5TZWdtZW50XG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0ge29ubnguVGVuc29yUHJvdG8uSVNlZ21lbnR9IG1lc3NhZ2UgU2VnbWVudCBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBTZWdtZW50LmVuY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZChtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGUobWVzc2FnZSwgd3JpdGVyKS5sZGVsaW0oKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogRGVjb2RlcyBhIFNlZ21lbnQgbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlci5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvLlNlZ21lbnRcbiAgICAgICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGhdIE1lc3NhZ2UgbGVuZ3RoIGlmIGtub3duIGJlZm9yZWhhbmRcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclByb3RvLlNlZ21lbnR9IFNlZ21lbnRcbiAgICAgICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgU2VnbWVudC5kZWNvZGUgPSBmdW5jdGlvbiBkZWNvZGUocmVhZGVyLCBsZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIShyZWFkZXIgaW5zdGFuY2VvZiAkUmVhZGVyKSlcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyID0gJFJlYWRlci5jcmVhdGUocmVhZGVyKTtcbiAgICAgICAgICAgICAgICB2YXIgZW5kID0gbGVuZ3RoID09PSB1bmRlZmluZWQgPyByZWFkZXIubGVuIDogcmVhZGVyLnBvcyArIGxlbmd0aCwgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LlRlbnNvclByb3RvLlNlZ21lbnQoKTtcbiAgICAgICAgICAgICAgICB3aGlsZSAocmVhZGVyLnBvcyA8IGVuZCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdGFnID0gcmVhZGVyLnVpbnQzMigpO1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHRhZyA+Pj4gMykge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmJlZ2luID0gcmVhZGVyLmludDY0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5lbmQgPSByZWFkZXIuaW50NjQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnNraXBUeXBlKHRhZyAmIDcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIERlY29kZXMgYSBTZWdtZW50IG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIsIGxlbmd0aCBkZWxpbWl0ZWQuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90by5TZWdtZW50XG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclByb3RvLlNlZ21lbnR9IFNlZ21lbnRcbiAgICAgICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgU2VnbWVudC5kZWNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWQocmVhZGVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgICAgIHJlYWRlciA9IG5ldyAkUmVhZGVyKHJlYWRlcik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogVmVyaWZpZXMgYSBTZWdtZW50IG1lc3NhZ2UuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gdmVyaWZ5XG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JQcm90by5TZWdtZW50XG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBtZXNzYWdlIFBsYWluIG9iamVjdCB0byB2ZXJpZnlcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH0gYG51bGxgIGlmIHZhbGlkLCBvdGhlcndpc2UgdGhlIHJlYXNvbiB3aHkgaXQgaXMgbm90XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIFNlZ21lbnQudmVyaWZ5ID0gZnVuY3Rpb24gdmVyaWZ5KG1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgIT09IFwib2JqZWN0XCIgfHwgbWVzc2FnZSA9PT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwib2JqZWN0IGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuYmVnaW4gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiYmVnaW5cIikpXG4gICAgICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuYmVnaW4pICYmICEobWVzc2FnZS5iZWdpbiAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5iZWdpbi5sb3cpICYmICR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmJlZ2luLmhpZ2gpKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcImJlZ2luOiBpbnRlZ2VyfExvbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBpZiAobWVzc2FnZS5lbmQgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZW5kXCIpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmVuZCkgJiYgIShtZXNzYWdlLmVuZCAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5lbmQubG93KSAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5lbmQuaGlnaCkpKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZW5kOiBpbnRlZ2VyfExvbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQ3JlYXRlcyBhIFNlZ21lbnQgbWVzc2FnZSBmcm9tIGEgcGxhaW4gb2JqZWN0LiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byB0aGVpciByZXNwZWN0aXZlIGludGVybmFsIHR5cGVzLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIGZyb21PYmplY3RcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvLlNlZ21lbnRcbiAgICAgICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG9iamVjdCBQbGFpbiBvYmplY3RcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclByb3RvLlNlZ21lbnR9IFNlZ21lbnRcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgU2VnbWVudC5mcm9tT2JqZWN0ID0gZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgJHJvb3Qub25ueC5UZW5zb3JQcm90by5TZWdtZW50KVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICAgICAgICAgIHZhciBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguVGVuc29yUHJvdG8uU2VnbWVudCgpO1xuICAgICAgICAgICAgICAgIGlmIChvYmplY3QuYmVnaW4gIT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgaWYgKCR1dGlsLkxvbmcpXG4gICAgICAgICAgICAgICAgICAgICAgICAobWVzc2FnZS5iZWdpbiA9ICR1dGlsLkxvbmcuZnJvbVZhbHVlKG9iamVjdC5iZWdpbikpLnVuc2lnbmVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QuYmVnaW4gPT09IFwic3RyaW5nXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmJlZ2luID0gcGFyc2VJbnQob2JqZWN0LmJlZ2luLCAxMCk7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QuYmVnaW4gPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmJlZ2luID0gb2JqZWN0LmJlZ2luO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmJlZ2luID09PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5iZWdpbiA9IG5ldyAkdXRpbC5Mb25nQml0cyhvYmplY3QuYmVnaW4ubG93ID4+PiAwLCBvYmplY3QuYmVnaW4uaGlnaCA+Pj4gMCkudG9OdW1iZXIoKTtcbiAgICAgICAgICAgICAgICBpZiAob2JqZWN0LmVuZCAhPSBudWxsKVxuICAgICAgICAgICAgICAgICAgICBpZiAoJHV0aWwuTG9uZylcbiAgICAgICAgICAgICAgICAgICAgICAgIChtZXNzYWdlLmVuZCA9ICR1dGlsLkxvbmcuZnJvbVZhbHVlKG9iamVjdC5lbmQpKS51bnNpZ25lZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmVuZCA9PT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZW5kID0gcGFyc2VJbnQob2JqZWN0LmVuZCwgMTApO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmVuZCA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZW5kID0gb2JqZWN0LmVuZDtcbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIG9iamVjdC5lbmQgPT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmVuZCA9IG5ldyAkdXRpbC5Mb25nQml0cyhvYmplY3QuZW5kLmxvdyA+Pj4gMCwgb2JqZWN0LmVuZC5oaWdoID4+PiAwKS50b051bWJlcigpO1xuICAgICAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBDcmVhdGVzIGEgcGxhaW4gb2JqZWN0IGZyb20gYSBTZWdtZW50IG1lc3NhZ2UuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIG90aGVyIHR5cGVzIGlmIHNwZWNpZmllZC5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiB0b09iamVjdFxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yUHJvdG8uU2VnbWVudFxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHtvbm54LlRlbnNvclByb3RvLlNlZ21lbnR9IG1lc3NhZ2UgU2VnbWVudFxuICAgICAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuSUNvbnZlcnNpb25PcHRpb25zfSBbb3B0aW9uc10gQ29udmVyc2lvbiBvcHRpb25zXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IFBsYWluIG9iamVjdFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBTZWdtZW50LnRvT2JqZWN0ID0gZnVuY3Rpb24gdG9PYmplY3QobWVzc2FnZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghb3B0aW9ucylcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5kZWZhdWx0cykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoJHV0aWwuTG9uZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxvbmcgPSBuZXcgJHV0aWwuTG9uZygwLCAwLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3QuYmVnaW4gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBsb25nLnRvU3RyaW5nKCkgOiBvcHRpb25zLmxvbmdzID09PSBOdW1iZXIgPyBsb25nLnRvTnVtYmVyKCkgOiBsb25nO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC5iZWdpbiA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IFwiMFwiIDogMDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCR1dGlsLkxvbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsb25nID0gbmV3ICR1dGlsLkxvbmcoMCwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmVuZCA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IGxvbmcudG9TdHJpbmcoKSA6IG9wdGlvbnMubG9uZ3MgPT09IE51bWJlciA/IGxvbmcudG9OdW1iZXIoKSA6IGxvbmc7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmVuZCA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IFwiMFwiIDogMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuYmVnaW4gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiYmVnaW5cIikpXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZS5iZWdpbiA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC5iZWdpbiA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IFN0cmluZyhtZXNzYWdlLmJlZ2luKSA6IG1lc3NhZ2UuYmVnaW47XG4gICAgICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC5iZWdpbiA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/ICR1dGlsLkxvbmcucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobWVzc2FnZS5iZWdpbikgOiBvcHRpb25zLmxvbmdzID09PSBOdW1iZXIgPyBuZXcgJHV0aWwuTG9uZ0JpdHMobWVzc2FnZS5iZWdpbi5sb3cgPj4+IDAsIG1lc3NhZ2UuYmVnaW4uaGlnaCA+Pj4gMCkudG9OdW1iZXIoKSA6IG1lc3NhZ2UuYmVnaW47XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZW5kICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImVuZFwiKSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlLmVuZCA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC5lbmQgPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBTdHJpbmcobWVzc2FnZS5lbmQpIDogbWVzc2FnZS5lbmQ7XG4gICAgICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC5lbmQgPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyAkdXRpbC5Mb25nLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG1lc3NhZ2UuZW5kKSA6IG9wdGlvbnMubG9uZ3MgPT09IE51bWJlciA/IG5ldyAkdXRpbC5Mb25nQml0cyhtZXNzYWdlLmVuZC5sb3cgPj4+IDAsIG1lc3NhZ2UuZW5kLmhpZ2ggPj4+IDApLnRvTnVtYmVyKCkgOiBtZXNzYWdlLmVuZDtcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIFNlZ21lbnQgdG8gSlNPTi5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiB0b0pTT05cbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclByb3RvLlNlZ21lbnRcbiAgICAgICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBKU09OIG9iamVjdFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBTZWdtZW50LnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IudG9PYmplY3QodGhpcywgJHByb3RvYnVmLnV0aWwudG9KU09OT3B0aW9ucyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICByZXR1cm4gU2VnbWVudDtcbiAgICAgICAgfSkoKTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGF0YUxvY2F0aW9uIGVudW0uXG4gICAgICAgICAqIEBuYW1lIG9ubnguVGVuc29yUHJvdG8uRGF0YUxvY2F0aW9uXG4gICAgICAgICAqIEBlbnVtIHtzdHJpbmd9XG4gICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBERUZBVUxUPTAgREVGQVVMVCB2YWx1ZVxuICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gRVhURVJOQUw9MSBFWFRFUk5BTCB2YWx1ZVxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yUHJvdG8uRGF0YUxvY2F0aW9uID0gKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgdmFyIHZhbHVlc0J5SWQgPSB7fSwgdmFsdWVzID0gT2JqZWN0LmNyZWF0ZSh2YWx1ZXNCeUlkKTtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzBdID0gXCJERUZBVUxUXCJdID0gMDtcbiAgICAgICAgICAgIHZhbHVlc1t2YWx1ZXNCeUlkWzFdID0gXCJFWFRFUk5BTFwiXSA9IDE7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWVzO1xuICAgICAgICB9KSgpO1xuXG4gICAgICAgIHJldHVybiBUZW5zb3JQcm90bztcbiAgICB9KSgpO1xuXG4gICAgb25ueC5UZW5zb3JTaGFwZVByb3RvID0gKGZ1bmN0aW9uKCkge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQcm9wZXJ0aWVzIG9mIGEgVGVuc29yU2hhcGVQcm90by5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnhcbiAgICAgICAgICogQGludGVyZmFjZSBJVGVuc29yU2hhcGVQcm90b1xuICAgICAgICAgKiBAcHJvcGVydHkge0FycmF5Ljxvbm54LlRlbnNvclNoYXBlUHJvdG8uSURpbWVuc2lvbj58bnVsbH0gW2RpbV0gVGVuc29yU2hhcGVQcm90byBkaW1cbiAgICAgICAgICovXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnN0cnVjdHMgYSBuZXcgVGVuc29yU2hhcGVQcm90by5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnhcbiAgICAgICAgICogQGNsYXNzZGVzYyBSZXByZXNlbnRzIGEgVGVuc29yU2hhcGVQcm90by5cbiAgICAgICAgICogQGltcGxlbWVudHMgSVRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICogQGNvbnN0cnVjdG9yXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JVGVuc29yU2hhcGVQcm90bz19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gVGVuc29yU2hhcGVQcm90byhwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICB0aGlzLmRpbSA9IFtdO1xuICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMpXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5cyA9IE9iamVjdC5rZXlzKHByb3BlcnRpZXMpLCBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzW2tleXNbaV1dICE9IG51bGwpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzW2tleXNbaV1dID0gcHJvcGVydGllc1trZXlzW2ldXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBUZW5zb3JTaGFwZVByb3RvIGRpbS5cbiAgICAgICAgICogQG1lbWJlciB7QXJyYXkuPG9ubnguVGVuc29yU2hhcGVQcm90by5JRGltZW5zaW9uPn0gZGltXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JTaGFwZVByb3RvLnByb3RvdHlwZS5kaW0gPSAkdXRpbC5lbXB0eUFycmF5O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgbmV3IFRlbnNvclNoYXBlUHJvdG8gaW5zdGFuY2UgdXNpbmcgdGhlIHNwZWNpZmllZCBwcm9wZXJ0aWVzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gY3JlYXRlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVRlbnNvclNoYXBlUHJvdG89fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICogQHJldHVybnMge29ubnguVGVuc29yU2hhcGVQcm90b30gVGVuc29yU2hhcGVQcm90byBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yU2hhcGVQcm90by5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUocHJvcGVydGllcykge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBUZW5zb3JTaGFwZVByb3RvKHByb3BlcnRpZXMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmNvZGVzIHRoZSBzcGVjaWZpZWQgVGVuc29yU2hhcGVQcm90byBtZXNzYWdlLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LlRlbnNvclNoYXBlUHJvdG8udmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBlbmNvZGVcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JVGVuc29yU2hhcGVQcm90b30gbWVzc2FnZSBUZW5zb3JTaGFwZVByb3RvIG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5Xcml0ZXJ9IFt3cml0ZXJdIFdyaXRlciB0byBlbmNvZGUgdG9cbiAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yU2hhcGVQcm90by5lbmNvZGUgPSBmdW5jdGlvbiBlbmNvZGUobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICBpZiAoIXdyaXRlcilcbiAgICAgICAgICAgICAgICB3cml0ZXIgPSAkV3JpdGVyLmNyZWF0ZSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGltICE9IG51bGwgJiYgbWVzc2FnZS5kaW0ubGVuZ3RoKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbWVzc2FnZS5kaW0ubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICAgICAgICAgICRyb290Lm9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb24uZW5jb2RlKG1lc3NhZ2UuZGltW2ldLCB3cml0ZXIudWludDMyKC8qIGlkIDEsIHdpcmVUeXBlIDIgPSovMTApLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICByZXR1cm4gd3JpdGVyO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmNvZGVzIHRoZSBzcGVjaWZpZWQgVGVuc29yU2hhcGVQcm90byBtZXNzYWdlLCBsZW5ndGggZGVsaW1pdGVkLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LlRlbnNvclNoYXBlUHJvdG8udmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JVGVuc29yU2hhcGVQcm90b30gbWVzc2FnZSBUZW5zb3JTaGFwZVByb3RvIG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5Xcml0ZXJ9IFt3cml0ZXJdIFdyaXRlciB0byBlbmNvZGUgdG9cbiAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yU2hhcGVQcm90by5lbmNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWQobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGUobWVzc2FnZSwgd3JpdGVyKS5sZGVsaW0oKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhIFRlbnNvclNoYXBlUHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlci5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbbGVuZ3RoXSBNZXNzYWdlIGxlbmd0aCBpZiBrbm93biBiZWZvcmVoYW5kXG4gICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclNoYXBlUHJvdG99IFRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JTaGFwZVByb3RvLmRlY29kZSA9IGZ1bmN0aW9uIGRlY29kZShyZWFkZXIsIGxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgcmVhZGVyID0gJFJlYWRlci5jcmVhdGUocmVhZGVyKTtcbiAgICAgICAgICAgIHZhciBlbmQgPSBsZW5ndGggPT09IHVuZGVmaW5lZCA/IHJlYWRlci5sZW4gOiByZWFkZXIucG9zICsgbGVuZ3RoLCBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguVGVuc29yU2hhcGVQcm90bygpO1xuICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGFnID0gcmVhZGVyLnVpbnQzMigpO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGFnID4+PiAzKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBpZiAoIShtZXNzYWdlLmRpbSAmJiBtZXNzYWdlLmRpbS5sZW5ndGgpKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kaW0gPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kaW0ucHVzaCgkcm9vdC5vbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9uLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZWFkZXIuc2tpcFR5cGUodGFnICYgNyk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGEgVGVuc29yU2hhcGVQcm90byBtZXNzYWdlIGZyb20gdGhlIHNwZWNpZmllZCByZWFkZXIgb3IgYnVmZmVyLCBsZW5ndGggZGVsaW1pdGVkLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHJldHVybnMge29ubnguVGVuc29yU2hhcGVQcm90b30gVGVuc29yU2hhcGVQcm90b1xuICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHBheWxvYWQgaXMgbm90IGEgcmVhZGVyIG9yIHZhbGlkIGJ1ZmZlclxuICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclNoYXBlUHJvdG8uZGVjb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkKHJlYWRlcikge1xuICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgcmVhZGVyID0gbmV3ICRSZWFkZXIocmVhZGVyKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFZlcmlmaWVzIGEgVGVuc29yU2hhcGVQcm90byBtZXNzYWdlLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdmVyaWZ5XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge09iamVjdC48c3RyaW5nLCo+fSBtZXNzYWdlIFBsYWluIG9iamVjdCB0byB2ZXJpZnlcbiAgICAgICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfSBgbnVsbGAgaWYgdmFsaWQsIG90aGVyd2lzZSB0aGUgcmVhc29uIHdoeSBpdCBpcyBub3RcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclNoYXBlUHJvdG8udmVyaWZ5ID0gZnVuY3Rpb24gdmVyaWZ5KG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSAhPT0gXCJvYmplY3RcIiB8fCBtZXNzYWdlID09PSBudWxsKVxuICAgICAgICAgICAgICAgIHJldHVybiBcIm9iamVjdCBleHBlY3RlZFwiO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGltICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRpbVwiKSkge1xuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShtZXNzYWdlLmRpbSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRpbTogYXJyYXkgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1lc3NhZ2UuZGltLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlcnJvciA9ICRyb290Lm9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb24udmVyaWZ5KG1lc3NhZ2UuZGltW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZGltLlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBUZW5zb3JTaGFwZVByb3RvIG1lc3NhZ2UgZnJvbSBhIHBsYWluIG9iamVjdC4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gdGhlaXIgcmVzcGVjdGl2ZSBpbnRlcm5hbCB0eXBlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGZyb21PYmplY3RcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG9iamVjdCBQbGFpbiBvYmplY3RcbiAgICAgICAgICogQHJldHVybnMge29ubnguVGVuc29yU2hhcGVQcm90b30gVGVuc29yU2hhcGVQcm90b1xuICAgICAgICAgKi9cbiAgICAgICAgVGVuc29yU2hhcGVQcm90by5mcm9tT2JqZWN0ID0gZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChvYmplY3QgaW5zdGFuY2VvZiAkcm9vdC5vbm54LlRlbnNvclNoYXBlUHJvdG8pXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgICAgIHZhciBtZXNzYWdlID0gbmV3ICRyb290Lm9ubnguVGVuc29yU2hhcGVQcm90bygpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5kaW0pIHtcbiAgICAgICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqZWN0LmRpbSkpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LlRlbnNvclNoYXBlUHJvdG8uZGltOiBhcnJheSBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmRpbSA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgb2JqZWN0LmRpbS5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdC5kaW1baV0gIT09IFwib2JqZWN0XCIpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCIub25ueC5UZW5zb3JTaGFwZVByb3RvLmRpbTogb2JqZWN0IGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRpbVtpXSA9ICRyb290Lm9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb24uZnJvbU9iamVjdChvYmplY3QuZGltW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIHBsYWluIG9iamVjdCBmcm9tIGEgVGVuc29yU2hhcGVQcm90byBtZXNzYWdlLiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byBvdGhlciB0eXBlcyBpZiBzcGVjaWZpZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiB0b09iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LlRlbnNvclNoYXBlUHJvdG99IG1lc3NhZ2UgVGVuc29yU2hhcGVQcm90b1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5JQ29udmVyc2lvbk9wdGlvbnN9IFtvcHRpb25zXSBDb252ZXJzaW9uIG9wdGlvbnNcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBQbGFpbiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIFRlbnNvclNoYXBlUHJvdG8udG9PYmplY3QgPSBmdW5jdGlvbiB0b09iamVjdChtZXNzYWdlLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMpXG4gICAgICAgICAgICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgICAgICAgdmFyIG9iamVjdCA9IHt9O1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuYXJyYXlzIHx8IG9wdGlvbnMuZGVmYXVsdHMpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmRpbSA9IFtdO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGltICYmIG1lc3NhZ2UuZGltLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5kaW0gPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1lc3NhZ2UuZGltLmxlbmd0aDsgKytqKVxuICAgICAgICAgICAgICAgICAgICBvYmplY3QuZGltW2pdID0gJHJvb3Qub25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvbi50b09iamVjdChtZXNzYWdlLmRpbVtqXSwgb3B0aW9ucyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIFRlbnNvclNoYXBlUHJvdG8gdG8gSlNPTi5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvSlNPTlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IEpTT04gb2JqZWN0XG4gICAgICAgICAqL1xuICAgICAgICBUZW5zb3JTaGFwZVByb3RvLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci50b09iamVjdCh0aGlzLCAkcHJvdG9idWYudXRpbC50b0pTT05PcHRpb25zKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvbiA9IChmdW5jdGlvbigpIHtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBQcm9wZXJ0aWVzIG9mIGEgRGltZW5zaW9uLlxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90b1xuICAgICAgICAgICAgICogQGludGVyZmFjZSBJRGltZW5zaW9uXG4gICAgICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcnxMb25nfG51bGx9IFtkaW1WYWx1ZV0gRGltZW5zaW9uIGRpbVZhbHVlXG4gICAgICAgICAgICAgKiBAcHJvcGVydHkge3N0cmluZ3xudWxsfSBbZGltUGFyYW1dIERpbWVuc2lvbiBkaW1QYXJhbVxuICAgICAgICAgICAgICogQHByb3BlcnR5IHtzdHJpbmd8bnVsbH0gW2Rlbm90YXRpb25dIERpbWVuc2lvbiBkZW5vdGF0aW9uXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IERpbWVuc2lvbi5cbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG9cbiAgICAgICAgICAgICAqIEBjbGFzc2Rlc2MgUmVwcmVzZW50cyBhIERpbWVuc2lvbi5cbiAgICAgICAgICAgICAqIEBpbXBsZW1lbnRzIElEaW1lbnNpb25cbiAgICAgICAgICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAgICAgICAgICogQHBhcmFtIHtvbm54LlRlbnNvclNoYXBlUHJvdG8uSURpbWVuc2lvbj19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBmdW5jdGlvbiBEaW1lbnNpb24ocHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzKVxuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyksIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzW2tleXNbaV1dICE9IG51bGwpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1trZXlzW2ldXSA9IHByb3BlcnRpZXNba2V5c1tpXV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogRGltZW5zaW9uIGRpbVZhbHVlLlxuICAgICAgICAgICAgICogQG1lbWJlciB7bnVtYmVyfExvbmd9IGRpbVZhbHVlXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvblxuICAgICAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIERpbWVuc2lvbi5wcm90b3R5cGUuZGltVmFsdWUgPSAkdXRpbC5Mb25nID8gJHV0aWwuTG9uZy5mcm9tQml0cygwLDAsZmFsc2UpIDogMDtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBEaW1lbnNpb24gZGltUGFyYW0uXG4gICAgICAgICAgICAgKiBAbWVtYmVyIHtzdHJpbmd9IGRpbVBhcmFtXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvblxuICAgICAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIERpbWVuc2lvbi5wcm90b3R5cGUuZGltUGFyYW0gPSBcIlwiO1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIERpbWVuc2lvbiBkZW5vdGF0aW9uLlxuICAgICAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBkZW5vdGF0aW9uXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvblxuICAgICAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIERpbWVuc2lvbi5wcm90b3R5cGUuZGVub3RhdGlvbiA9IFwiXCI7XG5cbiAgICAgICAgICAgIC8vIE9uZU9mIGZpZWxkIG5hbWVzIGJvdW5kIHRvIHZpcnR1YWwgZ2V0dGVycyBhbmQgc2V0dGVyc1xuICAgICAgICAgICAgdmFyICRvbmVPZkZpZWxkcztcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBEaW1lbnNpb24gdmFsdWUuXG4gICAgICAgICAgICAgKiBAbWVtYmVyIHtcImRpbVZhbHVlXCJ8XCJkaW1QYXJhbVwifHVuZGVmaW5lZH0gdmFsdWVcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9uXG4gICAgICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KERpbWVuc2lvbi5wcm90b3R5cGUsIFwidmFsdWVcIiwge1xuICAgICAgICAgICAgICAgIGdldDogJHV0aWwub25lT2ZHZXR0ZXIoJG9uZU9mRmllbGRzID0gW1wiZGltVmFsdWVcIiwgXCJkaW1QYXJhbVwiXSksXG4gICAgICAgICAgICAgICAgc2V0OiAkdXRpbC5vbmVPZlNldHRlcigkb25lT2ZGaWVsZHMpXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBDcmVhdGVzIGEgbmV3IERpbWVuc2lvbiBpbnN0YW5jZSB1c2luZyB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gY3JlYXRlXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvblxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHtvbm54LlRlbnNvclNoYXBlUHJvdG8uSURpbWVuc2lvbj19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgICAgICogQHJldHVybnMge29ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb259IERpbWVuc2lvbiBpbnN0YW5jZVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBEaW1lbnNpb24uY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IERpbWVuc2lvbihwcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIERpbWVuc2lvbiBtZXNzYWdlLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9uLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZVxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb25cbiAgICAgICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICAgICAqIEBwYXJhbSB7b25ueC5UZW5zb3JTaGFwZVByb3RvLklEaW1lbnNpb259IG1lc3NhZ2UgRGltZW5zaW9uIG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIERpbWVuc2lvbi5lbmNvZGUgPSBmdW5jdGlvbiBlbmNvZGUobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF3cml0ZXIpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlciA9ICRXcml0ZXIuY3JlYXRlKCk7XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGltVmFsdWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZGltVmFsdWVcIikpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMSwgd2lyZVR5cGUgMCA9Ki84KS5pbnQ2NChtZXNzYWdlLmRpbVZhbHVlKTtcbiAgICAgICAgICAgICAgICBpZiAobWVzc2FnZS5kaW1QYXJhbSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkaW1QYXJhbVwiKSlcbiAgICAgICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAyLCB3aXJlVHlwZSAyID0qLzE4KS5zdHJpbmcobWVzc2FnZS5kaW1QYXJhbSk7XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGVub3RhdGlvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkZW5vdGF0aW9uXCIpKVxuICAgICAgICAgICAgICAgICAgICB3cml0ZXIudWludDMyKC8qIGlkIDMsIHdpcmVUeXBlIDIgPSovMjYpLnN0cmluZyhtZXNzYWdlLmRlbm90YXRpb24pO1xuICAgICAgICAgICAgICAgIHJldHVybiB3cml0ZXI7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBEaW1lbnNpb24gbWVzc2FnZSwgbGVuZ3RoIGRlbGltaXRlZC4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvbi52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9uXG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0ge29ubnguVGVuc29yU2hhcGVQcm90by5JRGltZW5zaW9ufSBtZXNzYWdlIERpbWVuc2lvbiBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBEaW1lbnNpb24uZW5jb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmVuY29kZShtZXNzYWdlLCB3cml0ZXIpLmxkZWxpbSgpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBEZWNvZGVzIGEgRGltZW5zaW9uIG1lc3NhZ2UgZnJvbSB0aGUgc3BlY2lmaWVkIHJlYWRlciBvciBidWZmZXIuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvblxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuUmVhZGVyfFVpbnQ4QXJyYXl9IHJlYWRlciBSZWFkZXIgb3IgYnVmZmVyIHRvIGRlY29kZSBmcm9tXG4gICAgICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aF0gTWVzc2FnZSBsZW5ndGggaWYga25vd24gYmVmb3JlaGFuZFxuICAgICAgICAgICAgICogQHJldHVybnMge29ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb259IERpbWVuc2lvblxuICAgICAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBEaW1lbnNpb24uZGVjb2RlID0gZnVuY3Rpb24gZGVjb2RlKHJlYWRlciwgbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgICAgIHJlYWRlciA9ICRSZWFkZXIuY3JlYXRlKHJlYWRlcik7XG4gICAgICAgICAgICAgICAgdmFyIGVuZCA9IGxlbmd0aCA9PT0gdW5kZWZpbmVkID8gcmVhZGVyLmxlbiA6IHJlYWRlci5wb3MgKyBsZW5ndGgsIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvbigpO1xuICAgICAgICAgICAgICAgIHdoaWxlIChyZWFkZXIucG9zIDwgZW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0YWcgPSByZWFkZXIudWludDMyKCk7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodGFnID4+PiAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGltVmFsdWUgPSByZWFkZXIuaW50NjQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRpbVBhcmFtID0gcmVhZGVyLnN0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGVub3RhdGlvbiA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnNraXBUeXBlKHRhZyAmIDcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIERlY29kZXMgYSBEaW1lbnNpb24gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlciwgbGVuZ3RoIGRlbGltaXRlZC5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9uXG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtvbm54LlRlbnNvclNoYXBlUHJvdG8uRGltZW5zaW9ufSBEaW1lbnNpb25cbiAgICAgICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgcGF5bG9hZCBpcyBub3QgYSByZWFkZXIgb3IgdmFsaWQgYnVmZmVyXG4gICAgICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgRGltZW5zaW9uLmRlY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZChyZWFkZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAoIShyZWFkZXIgaW5zdGFuY2VvZiAkUmVhZGVyKSlcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyID0gbmV3ICRSZWFkZXIocmVhZGVyKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kZWNvZGUocmVhZGVyLCByZWFkZXIudWludDMyKCkpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBWZXJpZmllcyBhIERpbWVuc2lvbiBtZXNzYWdlLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIHZlcmlmeVxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb25cbiAgICAgICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG1lc3NhZ2UgUGxhaW4gb2JqZWN0IHRvIHZlcmlmeVxuICAgICAgICAgICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfSBgbnVsbGAgaWYgdmFsaWQsIG90aGVyd2lzZSB0aGUgcmVhc29uIHdoeSBpdCBpcyBub3RcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgRGltZW5zaW9uLnZlcmlmeSA9IGZ1bmN0aW9uIHZlcmlmeShtZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlICE9PSBcIm9iamVjdFwiIHx8IG1lc3NhZ2UgPT09IG51bGwpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm9iamVjdCBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGltVmFsdWUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZGltVmFsdWVcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllcy52YWx1ZSA9IDE7XG4gICAgICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UuZGltVmFsdWUpICYmICEobWVzc2FnZS5kaW1WYWx1ZSAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS5kaW1WYWx1ZS5sb3cpICYmICR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmRpbVZhbHVlLmhpZ2gpKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRpbVZhbHVlOiBpbnRlZ2VyfExvbmcgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGltUGFyYW0gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZGltUGFyYW1cIikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMudmFsdWUgPT09IDEpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJ2YWx1ZTogbXVsdGlwbGUgdmFsdWVzXCI7XG4gICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXMudmFsdWUgPSAxO1xuICAgICAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzU3RyaW5nKG1lc3NhZ2UuZGltUGFyYW0pKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZGltUGFyYW06IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobWVzc2FnZS5kZW5vdGF0aW9uICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRlbm90YXRpb25cIikpXG4gICAgICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5kZW5vdGF0aW9uKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRlbm90YXRpb246IHN0cmluZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBDcmVhdGVzIGEgRGltZW5zaW9uIG1lc3NhZ2UgZnJvbSBhIHBsYWluIG9iamVjdC4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gdGhlaXIgcmVzcGVjdGl2ZSBpbnRlcm5hbCB0eXBlcy5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiBmcm9tT2JqZWN0XG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvblxuICAgICAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gb2JqZWN0IFBsYWluIG9iamVjdFxuICAgICAgICAgICAgICogQHJldHVybnMge29ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb259IERpbWVuc2lvblxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBEaW1lbnNpb24uZnJvbU9iamVjdCA9IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgaWYgKG9iamVjdCBpbnN0YW5jZW9mICRyb290Lm9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb24pXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvbigpO1xuICAgICAgICAgICAgICAgIGlmIChvYmplY3QuZGltVmFsdWUgIT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgaWYgKCR1dGlsLkxvbmcpXG4gICAgICAgICAgICAgICAgICAgICAgICAobWVzc2FnZS5kaW1WYWx1ZSA9ICR1dGlsLkxvbmcuZnJvbVZhbHVlKG9iamVjdC5kaW1WYWx1ZSkpLnVuc2lnbmVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QuZGltVmFsdWUgPT09IFwic3RyaW5nXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRpbVZhbHVlID0gcGFyc2VJbnQob2JqZWN0LmRpbVZhbHVlLCAxMCk7XG4gICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QuZGltVmFsdWUgPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRpbVZhbHVlID0gb2JqZWN0LmRpbVZhbHVlO1xuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LmRpbVZhbHVlID09PSBcIm9iamVjdFwiKVxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kaW1WYWx1ZSA9IG5ldyAkdXRpbC5Mb25nQml0cyhvYmplY3QuZGltVmFsdWUubG93ID4+PiAwLCBvYmplY3QuZGltVmFsdWUuaGlnaCA+Pj4gMCkudG9OdW1iZXIoKTtcbiAgICAgICAgICAgICAgICBpZiAob2JqZWN0LmRpbVBhcmFtICE9IG51bGwpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZGltUGFyYW0gPSBTdHJpbmcob2JqZWN0LmRpbVBhcmFtKTtcbiAgICAgICAgICAgICAgICBpZiAob2JqZWN0LmRlbm90YXRpb24gIT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5kZW5vdGF0aW9uID0gU3RyaW5nKG9iamVjdC5kZW5vdGF0aW9uKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQ3JlYXRlcyBhIHBsYWluIG9iamVjdCBmcm9tIGEgRGltZW5zaW9uIG1lc3NhZ2UuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIG90aGVyIHR5cGVzIGlmIHNwZWNpZmllZC5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiB0b09iamVjdFxuICAgICAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVGVuc29yU2hhcGVQcm90by5EaW1lbnNpb25cbiAgICAgICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICAgICAqIEBwYXJhbSB7b25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvbn0gbWVzc2FnZSBEaW1lbnNpb25cbiAgICAgICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLklDb252ZXJzaW9uT3B0aW9uc30gW29wdGlvbnNdIENvbnZlcnNpb24gb3B0aW9uc1xuICAgICAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBQbGFpbiBvYmplY3RcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgRGltZW5zaW9uLnRvT2JqZWN0ID0gZnVuY3Rpb24gdG9PYmplY3QobWVzc2FnZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghb3B0aW9ucylcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5kZWZhdWx0cylcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmRlbm90YXRpb24gPSBcIlwiO1xuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLmRpbVZhbHVlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRpbVZhbHVlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZS5kaW1WYWx1ZSA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC5kaW1WYWx1ZSA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/IFN0cmluZyhtZXNzYWdlLmRpbVZhbHVlKSA6IG1lc3NhZ2UuZGltVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC5kaW1WYWx1ZSA9IG9wdGlvbnMubG9uZ3MgPT09IFN0cmluZyA/ICR1dGlsLkxvbmcucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobWVzc2FnZS5kaW1WYWx1ZSkgOiBvcHRpb25zLmxvbmdzID09PSBOdW1iZXIgPyBuZXcgJHV0aWwuTG9uZ0JpdHMobWVzc2FnZS5kaW1WYWx1ZS5sb3cgPj4+IDAsIG1lc3NhZ2UuZGltVmFsdWUuaGlnaCA+Pj4gMCkudG9OdW1iZXIoKSA6IG1lc3NhZ2UuZGltVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLm9uZW9mcylcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdC52YWx1ZSA9IFwiZGltVmFsdWVcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGltUGFyYW0gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZGltUGFyYW1cIikpIHtcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmRpbVBhcmFtID0gbWVzc2FnZS5kaW1QYXJhbTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMub25lb2ZzKVxuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnZhbHVlID0gXCJkaW1QYXJhbVwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobWVzc2FnZS5kZW5vdGF0aW9uICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRlbm90YXRpb25cIikpXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC5kZW5vdGF0aW9uID0gbWVzc2FnZS5kZW5vdGF0aW9uO1xuICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIENvbnZlcnRzIHRoaXMgRGltZW5zaW9uIHRvIEpTT04uXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gdG9KU09OXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UZW5zb3JTaGFwZVByb3RvLkRpbWVuc2lvblxuICAgICAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IEpTT04gb2JqZWN0XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIERpbWVuc2lvbi5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLnRvT2JqZWN0KHRoaXMsICRwcm90b2J1Zi51dGlsLnRvSlNPTk9wdGlvbnMpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgcmV0dXJuIERpbWVuc2lvbjtcbiAgICAgICAgfSkoKTtcblxuICAgICAgICByZXR1cm4gVGVuc29yU2hhcGVQcm90bztcbiAgICB9KSgpO1xuXG4gICAgb25ueC5UeXBlUHJvdG8gPSAoZnVuY3Rpb24oKSB7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFByb3BlcnRpZXMgb2YgYSBUeXBlUHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBpbnRlcmZhY2UgSVR5cGVQcm90b1xuICAgICAgICAgKiBAcHJvcGVydHkge29ubnguVHlwZVByb3RvLklUZW5zb3J8bnVsbH0gW3RlbnNvclR5cGVdIFR5cGVQcm90byB0ZW5zb3JUeXBlXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtkZW5vdGF0aW9uXSBUeXBlUHJvdG8gZGVub3RhdGlvblxuICAgICAgICAgKi9cblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29uc3RydWN0cyBhIG5ldyBUeXBlUHJvdG8uXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54XG4gICAgICAgICAqIEBjbGFzc2Rlc2MgUmVwcmVzZW50cyBhIFR5cGVQcm90by5cbiAgICAgICAgICogQGltcGxlbWVudHMgSVR5cGVQcm90b1xuICAgICAgICAgKiBAY29uc3RydWN0b3JcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklUeXBlUHJvdG89fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIFR5cGVQcm90byhwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICBpZiAocHJvcGVydGllcylcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXlzID0gT2JqZWN0LmtleXMocHJvcGVydGllcyksIGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7ICsraSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXNba2V5c1tpXV0gIT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNba2V5c1tpXV0gPSBwcm9wZXJ0aWVzW2tleXNbaV1dO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFR5cGVQcm90byB0ZW5zb3JUeXBlLlxuICAgICAgICAgKiBAbWVtYmVyIHtvbm54LlR5cGVQcm90by5JVGVuc29yfG51bGx8dW5kZWZpbmVkfSB0ZW5zb3JUeXBlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlR5cGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIFR5cGVQcm90by5wcm90b3R5cGUudGVuc29yVHlwZSA9IG51bGw7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFR5cGVQcm90byBkZW5vdGF0aW9uLlxuICAgICAgICAgKiBAbWVtYmVyIHtzdHJpbmd9IGRlbm90YXRpb25cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVHlwZVByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVHlwZVByb3RvLnByb3RvdHlwZS5kZW5vdGF0aW9uID0gXCJcIjtcblxuICAgICAgICAvLyBPbmVPZiBmaWVsZCBuYW1lcyBib3VuZCB0byB2aXJ0dWFsIGdldHRlcnMgYW5kIHNldHRlcnNcbiAgICAgICAgdmFyICRvbmVPZkZpZWxkcztcblxuICAgICAgICAvKipcbiAgICAgICAgICogVHlwZVByb3RvIHZhbHVlLlxuICAgICAgICAgKiBAbWVtYmVyIHtcInRlbnNvclR5cGVcInx1bmRlZmluZWR9IHZhbHVlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlR5cGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICovXG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShUeXBlUHJvdG8ucHJvdG90eXBlLCBcInZhbHVlXCIsIHtcbiAgICAgICAgICAgIGdldDogJHV0aWwub25lT2ZHZXR0ZXIoJG9uZU9mRmllbGRzID0gW1widGVuc29yVHlwZVwiXSksXG4gICAgICAgICAgICBzZXQ6ICR1dGlsLm9uZU9mU2V0dGVyKCRvbmVPZkZpZWxkcylcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBuZXcgVHlwZVByb3RvIGluc3RhbmNlIHVzaW5nIHRoZSBzcGVjaWZpZWQgcHJvcGVydGllcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGNyZWF0ZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVR5cGVQcm90bz19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UeXBlUHJvdG99IFR5cGVQcm90byBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgVHlwZVByb3RvLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFR5cGVQcm90byhwcm9wZXJ0aWVzKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIFR5cGVQcm90byBtZXNzYWdlLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LlR5cGVQcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSVR5cGVQcm90b30gbWVzc2FnZSBUeXBlUHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBUeXBlUHJvdG8uZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgaWYgKCF3cml0ZXIpXG4gICAgICAgICAgICAgICAgd3JpdGVyID0gJFdyaXRlci5jcmVhdGUoKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnRlbnNvclR5cGUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidGVuc29yVHlwZVwiKSlcbiAgICAgICAgICAgICAgICAkcm9vdC5vbm54LlR5cGVQcm90by5UZW5zb3IuZW5jb2RlKG1lc3NhZ2UudGVuc29yVHlwZSwgd3JpdGVyLnVpbnQzMigvKiBpZCAxLCB3aXJlVHlwZSAyID0qLzEwKS5mb3JrKCkpLmxkZWxpbSgpO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGVub3RhdGlvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkZW5vdGF0aW9uXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgNiwgd2lyZVR5cGUgMiA9Ki81MCkuc3RyaW5nKG1lc3NhZ2UuZGVub3RhdGlvbik7XG4gICAgICAgICAgICByZXR1cm4gd3JpdGVyO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbmNvZGVzIHRoZSBzcGVjaWZpZWQgVHlwZVByb3RvIG1lc3NhZ2UsIGxlbmd0aCBkZWxpbWl0ZWQuIERvZXMgbm90IGltcGxpY2l0bHkge0BsaW5rIG9ubnguVHlwZVByb3RvLnZlcmlmeXx2ZXJpZnl9IG1lc3NhZ2VzLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlR5cGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5JVHlwZVByb3RvfSBtZXNzYWdlIFR5cGVQcm90byBtZXNzYWdlIG9yIHBsYWluIG9iamVjdCB0byBlbmNvZGVcbiAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAqIEByZXR1cm5zIHskcHJvdG9idWYuV3JpdGVyfSBXcml0ZXJcbiAgICAgICAgICovXG4gICAgICAgIFR5cGVQcm90by5lbmNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWQobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lbmNvZGUobWVzc2FnZSwgd3JpdGVyKS5sZGVsaW0oKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhIFR5cGVQcm90byBtZXNzYWdlIGZyb20gdGhlIHNwZWNpZmllZCByZWFkZXIgb3IgYnVmZmVyLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlR5cGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aF0gTWVzc2FnZSBsZW5ndGggaWYga25vd24gYmVmb3JlaGFuZFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5UeXBlUHJvdG99IFR5cGVQcm90b1xuICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHBheWxvYWQgaXMgbm90IGEgcmVhZGVyIG9yIHZhbGlkIGJ1ZmZlclxuICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICovXG4gICAgICAgIFR5cGVQcm90by5kZWNvZGUgPSBmdW5jdGlvbiBkZWNvZGUocmVhZGVyLCBsZW5ndGgpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9ICRSZWFkZXIuY3JlYXRlKHJlYWRlcik7XG4gICAgICAgICAgICB2YXIgZW5kID0gbGVuZ3RoID09PSB1bmRlZmluZWQgPyByZWFkZXIubGVuIDogcmVhZGVyLnBvcyArIGxlbmd0aCwgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LlR5cGVQcm90bygpO1xuICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGFnID0gcmVhZGVyLnVpbnQzMigpO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGFnID4+PiAzKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnRlbnNvclR5cGUgPSAkcm9vdC5vbm54LlR5cGVQcm90by5UZW5zb3IuZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRlbm90YXRpb24gPSByZWFkZXIuc3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJlYWRlci5za2lwVHlwZSh0YWcgJiA3KTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIERlY29kZXMgYSBUeXBlUHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlciwgbGVuZ3RoIGRlbGltaXRlZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHJldHVybnMge29ubnguVHlwZVByb3RvfSBUeXBlUHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBUeXBlUHJvdG8uZGVjb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkKHJlYWRlcikge1xuICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgcmVhZGVyID0gbmV3ICRSZWFkZXIocmVhZGVyKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFZlcmlmaWVzIGEgVHlwZVByb3RvIG1lc3NhZ2UuXG4gICAgICAgICAqIEBmdW5jdGlvbiB2ZXJpZnlcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguVHlwZVByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gbWVzc2FnZSBQbGFpbiBvYmplY3QgdG8gdmVyaWZ5XG4gICAgICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH0gYG51bGxgIGlmIHZhbGlkLCBvdGhlcndpc2UgdGhlIHJlYXNvbiB3aHkgaXQgaXMgbm90XG4gICAgICAgICAqL1xuICAgICAgICBUeXBlUHJvdG8udmVyaWZ5ID0gZnVuY3Rpb24gdmVyaWZ5KG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWVzc2FnZSAhPT0gXCJvYmplY3RcIiB8fCBtZXNzYWdlID09PSBudWxsKVxuICAgICAgICAgICAgICAgIHJldHVybiBcIm9iamVjdCBleHBlY3RlZFwiO1xuICAgICAgICAgICAgdmFyIHByb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnRlbnNvclR5cGUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidGVuc29yVHlwZVwiKSkge1xuICAgICAgICAgICAgICAgIHByb3BlcnRpZXMudmFsdWUgPSAxO1xuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5UeXBlUHJvdG8uVGVuc29yLnZlcmlmeShtZXNzYWdlLnRlbnNvclR5cGUpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJ0ZW5zb3JUeXBlLlwiICsgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZGVub3RhdGlvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkZW5vdGF0aW9uXCIpKVxuICAgICAgICAgICAgICAgIGlmICghJHV0aWwuaXNTdHJpbmcobWVzc2FnZS5kZW5vdGF0aW9uKSlcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiZGVub3RhdGlvbjogc3RyaW5nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIFR5cGVQcm90byBtZXNzYWdlIGZyb20gYSBwbGFpbiBvYmplY3QuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIHRoZWlyIHJlc3BlY3RpdmUgaW50ZXJuYWwgdHlwZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBmcm9tT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlR5cGVQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG9iamVjdCBQbGFpbiBvYmplY3RcbiAgICAgICAgICogQHJldHVybnMge29ubnguVHlwZVByb3RvfSBUeXBlUHJvdG9cbiAgICAgICAgICovXG4gICAgICAgIFR5cGVQcm90by5mcm9tT2JqZWN0ID0gZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChvYmplY3QgaW5zdGFuY2VvZiAkcm9vdC5vbm54LlR5cGVQcm90bylcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5UeXBlUHJvdG8oKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QudGVuc29yVHlwZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QudGVuc29yVHlwZSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiLm9ubnguVHlwZVByb3RvLnRlbnNvclR5cGU6IG9iamVjdCBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICBtZXNzYWdlLnRlbnNvclR5cGUgPSAkcm9vdC5vbm54LlR5cGVQcm90by5UZW5zb3IuZnJvbU9iamVjdChvYmplY3QudGVuc29yVHlwZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob2JqZWN0LmRlbm90YXRpb24gIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmRlbm90YXRpb24gPSBTdHJpbmcob2JqZWN0LmRlbm90YXRpb24pO1xuICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBwbGFpbiBvYmplY3QgZnJvbSBhIFR5cGVQcm90byBtZXNzYWdlLiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byBvdGhlciB0eXBlcyBpZiBzcGVjaWZpZWQuXG4gICAgICAgICAqIEBmdW5jdGlvbiB0b09iamVjdFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguVHlwZVByb3RvfSBtZXNzYWdlIFR5cGVQcm90b1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5JQ29udmVyc2lvbk9wdGlvbnN9IFtvcHRpb25zXSBDb252ZXJzaW9uIG9wdGlvbnNcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBQbGFpbiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIFR5cGVQcm90by50b09iamVjdCA9IGZ1bmN0aW9uIHRvT2JqZWN0KG1lc3NhZ2UsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghb3B0aW9ucylcbiAgICAgICAgICAgICAgICBvcHRpb25zID0ge307XG4gICAgICAgICAgICB2YXIgb2JqZWN0ID0ge307XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5kZWZhdWx0cylcbiAgICAgICAgICAgICAgICBvYmplY3QuZGVub3RhdGlvbiA9IFwiXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS50ZW5zb3JUeXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInRlbnNvclR5cGVcIikpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QudGVuc29yVHlwZSA9ICRyb290Lm9ubnguVHlwZVByb3RvLlRlbnNvci50b09iamVjdChtZXNzYWdlLnRlbnNvclR5cGUsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLm9uZW9mcylcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnZhbHVlID0gXCJ0ZW5zb3JUeXBlXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kZW5vdGF0aW9uICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImRlbm90YXRpb25cIikpXG4gICAgICAgICAgICAgICAgb2JqZWN0LmRlbm90YXRpb24gPSBtZXNzYWdlLmRlbm90YXRpb247XG4gICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIFR5cGVQcm90byB0byBKU09OLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdG9KU09OXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlR5cGVQcm90b1xuICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBKU09OIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgVHlwZVByb3RvLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci50b09iamVjdCh0aGlzLCAkcHJvdG9idWYudXRpbC50b0pTT05PcHRpb25zKTtcbiAgICAgICAgfTtcblxuICAgICAgICBUeXBlUHJvdG8uVGVuc29yID0gKGZ1bmN0aW9uKCkge1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFByb3BlcnRpZXMgb2YgYSBUZW5zb3IuXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG9cbiAgICAgICAgICAgICAqIEBpbnRlcmZhY2UgSVRlbnNvclxuICAgICAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ8bnVsbH0gW2VsZW1UeXBlXSBUZW5zb3IgZWxlbVR5cGVcbiAgICAgICAgICAgICAqIEBwcm9wZXJ0eSB7b25ueC5JVGVuc29yU2hhcGVQcm90b3xudWxsfSBbc2hhcGVdIFRlbnNvciBzaGFwZVxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQ29uc3RydWN0cyBhIG5ldyBUZW5zb3IuXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG9cbiAgICAgICAgICAgICAqIEBjbGFzc2Rlc2MgUmVwcmVzZW50cyBhIFRlbnNvci5cbiAgICAgICAgICAgICAqIEBpbXBsZW1lbnRzIElUZW5zb3JcbiAgICAgICAgICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAgICAgICAgICogQHBhcmFtIHtvbm54LlR5cGVQcm90by5JVGVuc29yPX0gW3Byb3BlcnRpZXNdIFByb3BlcnRpZXMgdG8gc2V0XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGZ1bmN0aW9uIFRlbnNvcihwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMpXG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGtleXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKSwgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXNba2V5c1tpXV0gIT0gbnVsbClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzW2tleXNbaV1dID0gcHJvcGVydGllc1trZXlzW2ldXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBUZW5zb3IgZWxlbVR5cGUuXG4gICAgICAgICAgICAgKiBAbWVtYmVyIHtudW1iZXJ9IGVsZW1UeXBlXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG8uVGVuc29yXG4gICAgICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgVGVuc29yLnByb3RvdHlwZS5lbGVtVHlwZSA9IDA7XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogVGVuc29yIHNoYXBlLlxuICAgICAgICAgICAgICogQG1lbWJlciB7b25ueC5JVGVuc29yU2hhcGVQcm90b3xudWxsfHVuZGVmaW5lZH0gc2hhcGVcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlR5cGVQcm90by5UZW5zb3JcbiAgICAgICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBUZW5zb3IucHJvdG90eXBlLnNoYXBlID0gbnVsbDtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBDcmVhdGVzIGEgbmV3IFRlbnNvciBpbnN0YW5jZSB1c2luZyB0aGUgc3BlY2lmaWVkIHByb3BlcnRpZXMuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gY3JlYXRlXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG8uVGVuc29yXG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0ge29ubnguVHlwZVByb3RvLklUZW5zb3I9fSBbcHJvcGVydGllc10gUHJvcGVydGllcyB0byBzZXRcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtvbm54LlR5cGVQcm90by5UZW5zb3J9IFRlbnNvciBpbnN0YW5jZVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBUZW5zb3IuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFRlbnNvcihwcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIFRlbnNvciBtZXNzYWdlLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LlR5cGVQcm90by5UZW5zb3IudmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG8uVGVuc29yXG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0ge29ubnguVHlwZVByb3RvLklUZW5zb3J9IG1lc3NhZ2UgVGVuc29yIG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIFRlbnNvci5lbmNvZGUgPSBmdW5jdGlvbiBlbmNvZGUobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF3cml0ZXIpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlciA9ICRXcml0ZXIuY3JlYXRlKCk7XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuZWxlbVR5cGUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZWxlbVR5cGVcIikpXG4gICAgICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMSwgd2lyZVR5cGUgMCA9Ki84KS5pbnQzMihtZXNzYWdlLmVsZW1UeXBlKTtcbiAgICAgICAgICAgICAgICBpZiAobWVzc2FnZS5zaGFwZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJzaGFwZVwiKSlcbiAgICAgICAgICAgICAgICAgICAgJHJvb3Qub25ueC5UZW5zb3JTaGFwZVByb3RvLmVuY29kZShtZXNzYWdlLnNoYXBlLCB3cml0ZXIudWludDMyKC8qIGlkIDIsIHdpcmVUeXBlIDIgPSovMTgpLmZvcmsoKSkubGRlbGltKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHdyaXRlcjtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIFRlbnNvciBtZXNzYWdlLCBsZW5ndGggZGVsaW1pdGVkLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54LlR5cGVQcm90by5UZW5zb3IudmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gZW5jb2RlRGVsaW1pdGVkXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG8uVGVuc29yXG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0ge29ubnguVHlwZVByb3RvLklUZW5zb3J9IG1lc3NhZ2UgVGVuc29yIG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgICAgICogQHBhcmFtIHskcHJvdG9idWYuV3JpdGVyfSBbd3JpdGVyXSBXcml0ZXIgdG8gZW5jb2RlIHRvXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIFRlbnNvci5lbmNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWQobWVzc2FnZSwgd3JpdGVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikubGRlbGltKCk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIERlY29kZXMgYSBUZW5zb3IgbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlci5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlR5cGVQcm90by5UZW5zb3JcbiAgICAgICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGhdIE1lc3NhZ2UgbGVuZ3RoIGlmIGtub3duIGJlZm9yZWhhbmRcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtvbm54LlR5cGVQcm90by5UZW5zb3J9IFRlbnNvclxuICAgICAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICAgICAqIEB0aHJvd3MgeyRwcm90b2J1Zi51dGlsLlByb3RvY29sRXJyb3J9IElmIHJlcXVpcmVkIGZpZWxkcyBhcmUgbWlzc2luZ1xuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBUZW5zb3IuZGVjb2RlID0gZnVuY3Rpb24gZGVjb2RlKHJlYWRlciwgbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgICAgIHJlYWRlciA9ICRSZWFkZXIuY3JlYXRlKHJlYWRlcik7XG4gICAgICAgICAgICAgICAgdmFyIGVuZCA9IGxlbmd0aCA9PT0gdW5kZWZpbmVkID8gcmVhZGVyLmxlbiA6IHJlYWRlci5wb3MgKyBsZW5ndGgsIG1lc3NhZ2UgPSBuZXcgJHJvb3Qub25ueC5UeXBlUHJvdG8uVGVuc29yKCk7XG4gICAgICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHRhZyA9IHJlYWRlci51aW50MzIoKTtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0YWcgPj4+IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5lbGVtVHlwZSA9IHJlYWRlci5pbnQzMigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2Uuc2hhcGUgPSAkcm9vdC5vbm54LlRlbnNvclNoYXBlUHJvdG8uZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnNraXBUeXBlKHRhZyAmIDcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIERlY29kZXMgYSBUZW5zb3IgbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlciwgbGVuZ3RoIGRlbGltaXRlZC5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlR5cGVQcm90by5UZW5zb3JcbiAgICAgICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgICAgICogQHJldHVybnMge29ubnguVHlwZVByb3RvLlRlbnNvcn0gVGVuc29yXG4gICAgICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHBheWxvYWQgaXMgbm90IGEgcmVhZGVyIG9yIHZhbGlkIGJ1ZmZlclxuICAgICAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIFRlbnNvci5kZWNvZGVEZWxpbWl0ZWQgPSBmdW5jdGlvbiBkZWNvZGVEZWxpbWl0ZWQocmVhZGVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgICAgIHJlYWRlciA9IG5ldyAkUmVhZGVyKHJlYWRlcik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlKHJlYWRlciwgcmVhZGVyLnVpbnQzMigpKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogVmVyaWZpZXMgYSBUZW5zb3IgbWVzc2FnZS5cbiAgICAgICAgICAgICAqIEBmdW5jdGlvbiB2ZXJpZnlcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlR5cGVQcm90by5UZW5zb3JcbiAgICAgICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG1lc3NhZ2UgUGxhaW4gb2JqZWN0IHRvIHZlcmlmeVxuICAgICAgICAgICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfSBgbnVsbGAgaWYgdmFsaWQsIG90aGVyd2lzZSB0aGUgcmVhc29uIHdoeSBpdCBpcyBub3RcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgVGVuc29yLnZlcmlmeSA9IGZ1bmN0aW9uIHZlcmlmeShtZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXNzYWdlICE9PSBcIm9iamVjdFwiIHx8IG1lc3NhZ2UgPT09IG51bGwpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm9iamVjdCBleHBlY3RlZFwiO1xuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLmVsZW1UeXBlICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcImVsZW1UeXBlXCIpKVxuICAgICAgICAgICAgICAgICAgICBpZiAoISR1dGlsLmlzSW50ZWdlcihtZXNzYWdlLmVsZW1UeXBlKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBcImVsZW1UeXBlOiBpbnRlZ2VyIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2Uuc2hhcGUgIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwic2hhcGVcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGVycm9yID0gJHJvb3Qub25ueC5UZW5zb3JTaGFwZVByb3RvLnZlcmlmeShtZXNzYWdlLnNoYXBlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwic2hhcGUuXCIgKyBlcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIENyZWF0ZXMgYSBUZW5zb3IgbWVzc2FnZSBmcm9tIGEgcGxhaW4gb2JqZWN0LiBBbHNvIGNvbnZlcnRzIHZhbHVlcyB0byB0aGVpciByZXNwZWN0aXZlIGludGVybmFsIHR5cGVzLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIGZyb21PYmplY3RcbiAgICAgICAgICAgICAqIEBtZW1iZXJvZiBvbm54LlR5cGVQcm90by5UZW5zb3JcbiAgICAgICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG9iamVjdCBQbGFpbiBvYmplY3RcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtvbm54LlR5cGVQcm90by5UZW5zb3J9IFRlbnNvclxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBUZW5zb3IuZnJvbU9iamVjdCA9IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgaWYgKG9iamVjdCBpbnN0YW5jZW9mICRyb290Lm9ubnguVHlwZVByb3RvLlRlbnNvcilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgICAgICAgICB2YXIgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54LlR5cGVQcm90by5UZW5zb3IoKTtcbiAgICAgICAgICAgICAgICBpZiAob2JqZWN0LmVsZW1UeXBlICE9IG51bGwpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuZWxlbVR5cGUgPSBvYmplY3QuZWxlbVR5cGUgfCAwO1xuICAgICAgICAgICAgICAgIGlmIChvYmplY3Quc2hhcGUgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdC5zaGFwZSAhPT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIi5vbm54LlR5cGVQcm90by5UZW5zb3Iuc2hhcGU6IG9iamVjdCBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5zaGFwZSA9ICRyb290Lm9ubnguVGVuc29yU2hhcGVQcm90by5mcm9tT2JqZWN0KG9iamVjdC5zaGFwZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBDcmVhdGVzIGEgcGxhaW4gb2JqZWN0IGZyb20gYSBUZW5zb3IgbWVzc2FnZS4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gb3RoZXIgdHlwZXMgaWYgc3BlY2lmaWVkLlxuICAgICAgICAgICAgICogQGZ1bmN0aW9uIHRvT2JqZWN0XG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG8uVGVuc29yXG4gICAgICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAgICAgKiBAcGFyYW0ge29ubnguVHlwZVByb3RvLlRlbnNvcn0gbWVzc2FnZSBUZW5zb3JcbiAgICAgICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLklDb252ZXJzaW9uT3B0aW9uc30gW29wdGlvbnNdIENvbnZlcnNpb24gb3B0aW9uc1xuICAgICAgICAgICAgICogQHJldHVybnMge09iamVjdC48c3RyaW5nLCo+fSBQbGFpbiBvYmplY3RcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgVGVuc29yLnRvT2JqZWN0ID0gZnVuY3Rpb24gdG9PYmplY3QobWVzc2FnZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghb3B0aW9ucylcbiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5kZWZhdWx0cykge1xuICAgICAgICAgICAgICAgICAgICBvYmplY3QuZWxlbVR5cGUgPSAwO1xuICAgICAgICAgICAgICAgICAgICBvYmplY3Quc2hhcGUgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobWVzc2FnZS5lbGVtVHlwZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJlbGVtVHlwZVwiKSlcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LmVsZW1UeXBlID0gbWVzc2FnZS5lbGVtVHlwZTtcbiAgICAgICAgICAgICAgICBpZiAobWVzc2FnZS5zaGFwZSAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJzaGFwZVwiKSlcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnNoYXBlID0gJHJvb3Qub25ueC5UZW5zb3JTaGFwZVByb3RvLnRvT2JqZWN0KG1lc3NhZ2Uuc2hhcGUsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIENvbnZlcnRzIHRoaXMgVGVuc29yIHRvIEpTT04uXG4gICAgICAgICAgICAgKiBAZnVuY3Rpb24gdG9KU09OXG4gICAgICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5UeXBlUHJvdG8uVGVuc29yXG4gICAgICAgICAgICAgKiBAaW5zdGFuY2VcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gSlNPTiBvYmplY3RcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgVGVuc29yLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiB0b0pTT04oKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IudG9PYmplY3QodGhpcywgJHByb3RvYnVmLnV0aWwudG9KU09OT3B0aW9ucyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICByZXR1cm4gVGVuc29yO1xuICAgICAgICB9KSgpO1xuXG4gICAgICAgIHJldHVybiBUeXBlUHJvdG87XG4gICAgfSkoKTtcblxuICAgIG9ubnguT3BlcmF0b3JTZXRJZFByb3RvID0gKGZ1bmN0aW9uKCkge1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBQcm9wZXJ0aWVzIG9mIGFuIE9wZXJhdG9yU2V0SWRQcm90by5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnhcbiAgICAgICAgICogQGludGVyZmFjZSBJT3BlcmF0b3JTZXRJZFByb3RvXG4gICAgICAgICAqIEBwcm9wZXJ0eSB7c3RyaW5nfG51bGx9IFtkb21haW5dIE9wZXJhdG9yU2V0SWRQcm90byBkb21haW5cbiAgICAgICAgICogQHByb3BlcnR5IHtudW1iZXJ8TG9uZ3xudWxsfSBbdmVyc2lvbl0gT3BlcmF0b3JTZXRJZFByb3RvIHZlcnNpb25cbiAgICAgICAgICovXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENvbnN0cnVjdHMgYSBuZXcgT3BlcmF0b3JTZXRJZFByb3RvLlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueFxuICAgICAgICAgKiBAY2xhc3NkZXNjIFJlcHJlc2VudHMgYW4gT3BlcmF0b3JTZXRJZFByb3RvLlxuICAgICAgICAgKiBAaW1wbGVtZW50cyBJT3BlcmF0b3JTZXRJZFByb3RvXG4gICAgICAgICAqIEBjb25zdHJ1Y3RvclxuICAgICAgICAgKiBAcGFyYW0ge29ubnguSU9wZXJhdG9yU2V0SWRQcm90bz19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gT3BlcmF0b3JTZXRJZFByb3RvKHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzKVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleXMgPSBPYmplY3Qua2V5cyhwcm9wZXJ0aWVzKSwgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKVxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllc1trZXlzW2ldXSAhPSBudWxsKVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1trZXlzW2ldXSA9IHByb3BlcnRpZXNba2V5c1tpXV07XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogT3BlcmF0b3JTZXRJZFByb3RvIGRvbWFpbi5cbiAgICAgICAgICogQG1lbWJlciB7c3RyaW5nfSBkb21haW5cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguT3BlcmF0b3JTZXRJZFByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgT3BlcmF0b3JTZXRJZFByb3RvLnByb3RvdHlwZS5kb21haW4gPSBcIlwiO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBPcGVyYXRvclNldElkUHJvdG8gdmVyc2lvbi5cbiAgICAgICAgICogQG1lbWJlciB7bnVtYmVyfExvbmd9IHZlcnNpb25cbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguT3BlcmF0b3JTZXRJZFByb3RvXG4gICAgICAgICAqIEBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgT3BlcmF0b3JTZXRJZFByb3RvLnByb3RvdHlwZS52ZXJzaW9uID0gJHV0aWwuTG9uZyA/ICR1dGlsLkxvbmcuZnJvbUJpdHMoMCwwLGZhbHNlKSA6IDA7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYSBuZXcgT3BlcmF0b3JTZXRJZFByb3RvIGluc3RhbmNlIHVzaW5nIHRoZSBzcGVjaWZpZWQgcHJvcGVydGllcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGNyZWF0ZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5PcGVyYXRvclNldElkUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSU9wZXJhdG9yU2V0SWRQcm90bz19IFtwcm9wZXJ0aWVzXSBQcm9wZXJ0aWVzIHRvIHNldFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5PcGVyYXRvclNldElkUHJvdG99IE9wZXJhdG9yU2V0SWRQcm90byBpbnN0YW5jZVxuICAgICAgICAgKi9cbiAgICAgICAgT3BlcmF0b3JTZXRJZFByb3RvLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZShwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IE9wZXJhdG9yU2V0SWRQcm90byhwcm9wZXJ0aWVzKTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRW5jb2RlcyB0aGUgc3BlY2lmaWVkIE9wZXJhdG9yU2V0SWRQcm90byBtZXNzYWdlLiBEb2VzIG5vdCBpbXBsaWNpdGx5IHtAbGluayBvbm54Lk9wZXJhdG9yU2V0SWRQcm90by52ZXJpZnl8dmVyaWZ5fSBtZXNzYWdlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGVuY29kZVxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5PcGVyYXRvclNldElkUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0ge29ubnguSU9wZXJhdG9yU2V0SWRQcm90b30gbWVzc2FnZSBPcGVyYXRvclNldElkUHJvdG8gbWVzc2FnZSBvciBwbGFpbiBvYmplY3QgdG8gZW5jb2RlXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLldyaXRlcn0gW3dyaXRlcl0gV3JpdGVyIHRvIGVuY29kZSB0b1xuICAgICAgICAgKiBAcmV0dXJucyB7JHByb3RvYnVmLldyaXRlcn0gV3JpdGVyXG4gICAgICAgICAqL1xuICAgICAgICBPcGVyYXRvclNldElkUHJvdG8uZW5jb2RlID0gZnVuY3Rpb24gZW5jb2RlKG1lc3NhZ2UsIHdyaXRlcikge1xuICAgICAgICAgICAgaWYgKCF3cml0ZXIpXG4gICAgICAgICAgICAgICAgd3JpdGVyID0gJFdyaXRlci5jcmVhdGUoKTtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvbWFpbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb21haW5cIikpXG4gICAgICAgICAgICAgICAgd3JpdGVyLnVpbnQzMigvKiBpZCAxLCB3aXJlVHlwZSAyID0qLzEwKS5zdHJpbmcobWVzc2FnZS5kb21haW4pO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UudmVyc2lvbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJ2ZXJzaW9uXCIpKVxuICAgICAgICAgICAgICAgIHdyaXRlci51aW50MzIoLyogaWQgMiwgd2lyZVR5cGUgMCA9Ki8xNikuaW50NjQobWVzc2FnZS52ZXJzaW9uKTtcbiAgICAgICAgICAgIHJldHVybiB3cml0ZXI7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuY29kZXMgdGhlIHNwZWNpZmllZCBPcGVyYXRvclNldElkUHJvdG8gbWVzc2FnZSwgbGVuZ3RoIGRlbGltaXRlZC4gRG9lcyBub3QgaW1wbGljaXRseSB7QGxpbmsgb25ueC5PcGVyYXRvclNldElkUHJvdG8udmVyaWZ5fHZlcmlmeX0gbWVzc2FnZXMuXG4gICAgICAgICAqIEBmdW5jdGlvbiBlbmNvZGVEZWxpbWl0ZWRcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguT3BlcmF0b3JTZXRJZFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtvbm54LklPcGVyYXRvclNldElkUHJvdG99IG1lc3NhZ2UgT3BlcmF0b3JTZXRJZFByb3RvIG1lc3NhZ2Ugb3IgcGxhaW4gb2JqZWN0IHRvIGVuY29kZVxuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5Xcml0ZXJ9IFt3cml0ZXJdIFdyaXRlciB0byBlbmNvZGUgdG9cbiAgICAgICAgICogQHJldHVybnMgeyRwcm90b2J1Zi5Xcml0ZXJ9IFdyaXRlclxuICAgICAgICAgKi9cbiAgICAgICAgT3BlcmF0b3JTZXRJZFByb3RvLmVuY29kZURlbGltaXRlZCA9IGZ1bmN0aW9uIGVuY29kZURlbGltaXRlZChtZXNzYWdlLCB3cml0ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVuY29kZShtZXNzYWdlLCB3cml0ZXIpLmxkZWxpbSgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBEZWNvZGVzIGFuIE9wZXJhdG9yU2V0SWRQcm90byBtZXNzYWdlIGZyb20gdGhlIHNwZWNpZmllZCByZWFkZXIgb3IgYnVmZmVyLlxuICAgICAgICAgKiBAZnVuY3Rpb24gZGVjb2RlXG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk9wZXJhdG9yU2V0SWRQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLlJlYWRlcnxVaW50OEFycmF5fSByZWFkZXIgUmVhZGVyIG9yIGJ1ZmZlciB0byBkZWNvZGUgZnJvbVxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xlbmd0aF0gTWVzc2FnZSBsZW5ndGggaWYga25vd24gYmVmb3JlaGFuZFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5PcGVyYXRvclNldElkUHJvdG99IE9wZXJhdG9yU2V0SWRQcm90b1xuICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgdGhlIHBheWxvYWQgaXMgbm90IGEgcmVhZGVyIG9yIHZhbGlkIGJ1ZmZlclxuICAgICAgICAgKiBAdGhyb3dzIHskcHJvdG9idWYudXRpbC5Qcm90b2NvbEVycm9yfSBJZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAgICAgICAgICovXG4gICAgICAgIE9wZXJhdG9yU2V0SWRQcm90by5kZWNvZGUgPSBmdW5jdGlvbiBkZWNvZGUocmVhZGVyLCBsZW5ndGgpIHtcbiAgICAgICAgICAgIGlmICghKHJlYWRlciBpbnN0YW5jZW9mICRSZWFkZXIpKVxuICAgICAgICAgICAgICAgIHJlYWRlciA9ICRSZWFkZXIuY3JlYXRlKHJlYWRlcik7XG4gICAgICAgICAgICB2YXIgZW5kID0gbGVuZ3RoID09PSB1bmRlZmluZWQgPyByZWFkZXIubGVuIDogcmVhZGVyLnBvcyArIGxlbmd0aCwgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54Lk9wZXJhdG9yU2V0SWRQcm90bygpO1xuICAgICAgICAgICAgd2hpbGUgKHJlYWRlci5wb3MgPCBlbmQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGFnID0gcmVhZGVyLnVpbnQzMigpO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGFnID4+PiAzKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLmRvbWFpbiA9IHJlYWRlci5zdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLnZlcnNpb24gPSByZWFkZXIuaW50NjQoKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmVhZGVyLnNraXBUeXBlKHRhZyAmIDcpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogRGVjb2RlcyBhbiBPcGVyYXRvclNldElkUHJvdG8gbWVzc2FnZSBmcm9tIHRoZSBzcGVjaWZpZWQgcmVhZGVyIG9yIGJ1ZmZlciwgbGVuZ3RoIGRlbGltaXRlZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIGRlY29kZURlbGltaXRlZFxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5PcGVyYXRvclNldElkUHJvdG9cbiAgICAgICAgICogQHN0YXRpY1xuICAgICAgICAgKiBAcGFyYW0geyRwcm90b2J1Zi5SZWFkZXJ8VWludDhBcnJheX0gcmVhZGVyIFJlYWRlciBvciBidWZmZXIgdG8gZGVjb2RlIGZyb21cbiAgICAgICAgICogQHJldHVybnMge29ubnguT3BlcmF0b3JTZXRJZFByb3RvfSBPcGVyYXRvclNldElkUHJvdG9cbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIHRoZSBwYXlsb2FkIGlzIG5vdCBhIHJlYWRlciBvciB2YWxpZCBidWZmZXJcbiAgICAgICAgICogQHRocm93cyB7JHByb3RvYnVmLnV0aWwuUHJvdG9jb2xFcnJvcn0gSWYgcmVxdWlyZWQgZmllbGRzIGFyZSBtaXNzaW5nXG4gICAgICAgICAqL1xuICAgICAgICBPcGVyYXRvclNldElkUHJvdG8uZGVjb2RlRGVsaW1pdGVkID0gZnVuY3Rpb24gZGVjb2RlRGVsaW1pdGVkKHJlYWRlcikge1xuICAgICAgICAgICAgaWYgKCEocmVhZGVyIGluc3RhbmNlb2YgJFJlYWRlcikpXG4gICAgICAgICAgICAgICAgcmVhZGVyID0gbmV3ICRSZWFkZXIocmVhZGVyKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY29kZShyZWFkZXIsIHJlYWRlci51aW50MzIoKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIFZlcmlmaWVzIGFuIE9wZXJhdG9yU2V0SWRQcm90byBtZXNzYWdlLlxuICAgICAgICAgKiBAZnVuY3Rpb24gdmVyaWZ5XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk9wZXJhdG9yU2V0SWRQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IG1lc3NhZ2UgUGxhaW4gb2JqZWN0IHRvIHZlcmlmeVxuICAgICAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9IGBudWxsYCBpZiB2YWxpZCwgb3RoZXJ3aXNlIHRoZSByZWFzb24gd2h5IGl0IGlzIG5vdFxuICAgICAgICAgKi9cbiAgICAgICAgT3BlcmF0b3JTZXRJZFByb3RvLnZlcmlmeSA9IGZ1bmN0aW9uIHZlcmlmeShtZXNzYWdlKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UgIT09IFwib2JqZWN0XCIgfHwgbWVzc2FnZSA9PT0gbnVsbClcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJvYmplY3QgZXhwZWN0ZWRcIjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLmRvbWFpbiAhPSBudWxsICYmIG1lc3NhZ2UuaGFzT3duUHJvcGVydHkoXCJkb21haW5cIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc1N0cmluZyhtZXNzYWdlLmRvbWFpbikpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcImRvbWFpbjogc3RyaW5nIGV4cGVjdGVkXCI7XG4gICAgICAgICAgICBpZiAobWVzc2FnZS52ZXJzaW9uICE9IG51bGwgJiYgbWVzc2FnZS5oYXNPd25Qcm9wZXJ0eShcInZlcnNpb25cIikpXG4gICAgICAgICAgICAgICAgaWYgKCEkdXRpbC5pc0ludGVnZXIobWVzc2FnZS52ZXJzaW9uKSAmJiAhKG1lc3NhZ2UudmVyc2lvbiAmJiAkdXRpbC5pc0ludGVnZXIobWVzc2FnZS52ZXJzaW9uLmxvdykgJiYgJHV0aWwuaXNJbnRlZ2VyKG1lc3NhZ2UudmVyc2lvbi5oaWdoKSkpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInZlcnNpb246IGludGVnZXJ8TG9uZyBleHBlY3RlZFwiO1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIENyZWF0ZXMgYW4gT3BlcmF0b3JTZXRJZFByb3RvIG1lc3NhZ2UgZnJvbSBhIHBsYWluIG9iamVjdC4gQWxzbyBjb252ZXJ0cyB2YWx1ZXMgdG8gdGhlaXIgcmVzcGVjdGl2ZSBpbnRlcm5hbCB0eXBlcy5cbiAgICAgICAgICogQGZ1bmN0aW9uIGZyb21PYmplY3RcbiAgICAgICAgICogQG1lbWJlcm9mIG9ubnguT3BlcmF0b3JTZXRJZFByb3RvXG4gICAgICAgICAqIEBzdGF0aWNcbiAgICAgICAgICogQHBhcmFtIHtPYmplY3QuPHN0cmluZywqPn0gb2JqZWN0IFBsYWluIG9iamVjdFxuICAgICAgICAgKiBAcmV0dXJucyB7b25ueC5PcGVyYXRvclNldElkUHJvdG99IE9wZXJhdG9yU2V0SWRQcm90b1xuICAgICAgICAgKi9cbiAgICAgICAgT3BlcmF0b3JTZXRJZFByb3RvLmZyb21PYmplY3QgPSBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICAgICAgaWYgKG9iamVjdCBpbnN0YW5jZW9mICRyb290Lm9ubnguT3BlcmF0b3JTZXRJZFByb3RvKVxuICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgICAgICB2YXIgbWVzc2FnZSA9IG5ldyAkcm9vdC5vbm54Lk9wZXJhdG9yU2V0SWRQcm90bygpO1xuICAgICAgICAgICAgaWYgKG9iamVjdC5kb21haW4gIT0gbnVsbClcbiAgICAgICAgICAgICAgICBtZXNzYWdlLmRvbWFpbiA9IFN0cmluZyhvYmplY3QuZG9tYWluKTtcbiAgICAgICAgICAgIGlmIChvYmplY3QudmVyc2lvbiAhPSBudWxsKVxuICAgICAgICAgICAgICAgIGlmICgkdXRpbC5Mb25nKVxuICAgICAgICAgICAgICAgICAgICAobWVzc2FnZS52ZXJzaW9uID0gJHV0aWwuTG9uZy5mcm9tVmFsdWUob2JqZWN0LnZlcnNpb24pKS51bnNpZ25lZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QudmVyc2lvbiA9PT0gXCJzdHJpbmdcIilcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS52ZXJzaW9uID0gcGFyc2VJbnQob2JqZWN0LnZlcnNpb24sIDEwKTtcbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0LnZlcnNpb24gPT09IFwibnVtYmVyXCIpXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UudmVyc2lvbiA9IG9iamVjdC52ZXJzaW9uO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBvYmplY3QudmVyc2lvbiA9PT0gXCJvYmplY3RcIilcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS52ZXJzaW9uID0gbmV3ICR1dGlsLkxvbmdCaXRzKG9iamVjdC52ZXJzaW9uLmxvdyA+Pj4gMCwgb2JqZWN0LnZlcnNpb24uaGlnaCA+Pj4gMCkudG9OdW1iZXIoKTtcbiAgICAgICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBDcmVhdGVzIGEgcGxhaW4gb2JqZWN0IGZyb20gYW4gT3BlcmF0b3JTZXRJZFByb3RvIG1lc3NhZ2UuIEFsc28gY29udmVydHMgdmFsdWVzIHRvIG90aGVyIHR5cGVzIGlmIHNwZWNpZmllZC5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvT2JqZWN0XG4gICAgICAgICAqIEBtZW1iZXJvZiBvbm54Lk9wZXJhdG9yU2V0SWRQcm90b1xuICAgICAgICAgKiBAc3RhdGljXG4gICAgICAgICAqIEBwYXJhbSB7b25ueC5PcGVyYXRvclNldElkUHJvdG99IG1lc3NhZ2UgT3BlcmF0b3JTZXRJZFByb3RvXG4gICAgICAgICAqIEBwYXJhbSB7JHByb3RvYnVmLklDb252ZXJzaW9uT3B0aW9uc30gW29wdGlvbnNdIENvbnZlcnNpb24gb3B0aW9uc1xuICAgICAgICAgKiBAcmV0dXJucyB7T2JqZWN0LjxzdHJpbmcsKj59IFBsYWluIG9iamVjdFxuICAgICAgICAgKi9cbiAgICAgICAgT3BlcmF0b3JTZXRJZFByb3RvLnRvT2JqZWN0ID0gZnVuY3Rpb24gdG9PYmplY3QobWVzc2FnZSwgb3B0aW9ucykge1xuICAgICAgICAgICAgaWYgKCFvcHRpb25zKVxuICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmRlZmF1bHRzKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LmRvbWFpbiA9IFwiXCI7XG4gICAgICAgICAgICAgICAgaWYgKCR1dGlsLkxvbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxvbmcgPSBuZXcgJHV0aWwuTG9uZygwLCAwLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC52ZXJzaW9uID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gbG9uZy50b1N0cmluZygpIDogb3B0aW9ucy5sb25ncyA9PT0gTnVtYmVyID8gbG9uZy50b051bWJlcigpIDogbG9uZztcbiAgICAgICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnZlcnNpb24gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBcIjBcIiA6IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWVzc2FnZS5kb21haW4gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwiZG9tYWluXCIpKVxuICAgICAgICAgICAgICAgIG9iamVjdC5kb21haW4gPSBtZXNzYWdlLmRvbWFpbjtcbiAgICAgICAgICAgIGlmIChtZXNzYWdlLnZlcnNpb24gIT0gbnVsbCAmJiBtZXNzYWdlLmhhc093blByb3BlcnR5KFwidmVyc2lvblwiKSlcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1lc3NhZ2UudmVyc2lvbiA9PT0gXCJudW1iZXJcIilcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0LnZlcnNpb24gPSBvcHRpb25zLmxvbmdzID09PSBTdHJpbmcgPyBTdHJpbmcobWVzc2FnZS52ZXJzaW9uKSA6IG1lc3NhZ2UudmVyc2lvbjtcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdC52ZXJzaW9uID0gb3B0aW9ucy5sb25ncyA9PT0gU3RyaW5nID8gJHV0aWwuTG9uZy5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChtZXNzYWdlLnZlcnNpb24pIDogb3B0aW9ucy5sb25ncyA9PT0gTnVtYmVyID8gbmV3ICR1dGlsLkxvbmdCaXRzKG1lc3NhZ2UudmVyc2lvbi5sb3cgPj4+IDAsIG1lc3NhZ2UudmVyc2lvbi5oaWdoID4+PiAwKS50b051bWJlcigpIDogbWVzc2FnZS52ZXJzaW9uO1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQ29udmVydHMgdGhpcyBPcGVyYXRvclNldElkUHJvdG8gdG8gSlNPTi5cbiAgICAgICAgICogQGZ1bmN0aW9uIHRvSlNPTlxuICAgICAgICAgKiBAbWVtYmVyb2Ygb25ueC5PcGVyYXRvclNldElkUHJvdG9cbiAgICAgICAgICogQGluc3RhbmNlXG4gICAgICAgICAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gSlNPTiBvYmplY3RcbiAgICAgICAgICovXG4gICAgICAgIE9wZXJhdG9yU2V0SWRQcm90by5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IudG9PYmplY3QodGhpcywgJHByb3RvYnVmLnV0aWwudG9KU09OT3B0aW9ucyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIE9wZXJhdG9yU2V0SWRQcm90bztcbiAgICB9KSgpO1xuXG4gICAgcmV0dXJuIG9ubng7XG59KSgpO1xuXG5tb2R1bGUuZXhwb3J0cyA9ICRyb290O1xuIiwiLy8gbWluaW1hbCBsaWJyYXJ5IGVudHJ5IHBvaW50LlxuXG5cInVzZSBzdHJpY3RcIjtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcIi4vc3JjL2luZGV4LW1pbmltYWxcIik7XG4iLCJcInVzZSBzdHJpY3RcIjtcbnZhciBwcm90b2J1ZiA9IGV4cG9ydHM7XG5cbi8qKlxuICogQnVpbGQgdHlwZSwgb25lIG9mIGBcImZ1bGxcImAsIGBcImxpZ2h0XCJgIG9yIGBcIm1pbmltYWxcImAuXG4gKiBAbmFtZSBidWlsZFxuICogQHR5cGUge3N0cmluZ31cbiAqIEBjb25zdFxuICovXG5wcm90b2J1Zi5idWlsZCA9IFwibWluaW1hbFwiO1xuXG4vLyBTZXJpYWxpemF0aW9uXG5wcm90b2J1Zi5Xcml0ZXIgICAgICAgPSByZXF1aXJlKFwiLi93cml0ZXJcIik7XG5wcm90b2J1Zi5CdWZmZXJXcml0ZXIgPSByZXF1aXJlKFwiLi93cml0ZXJfYnVmZmVyXCIpO1xucHJvdG9idWYuUmVhZGVyICAgICAgID0gcmVxdWlyZShcIi4vcmVhZGVyXCIpO1xucHJvdG9idWYuQnVmZmVyUmVhZGVyID0gcmVxdWlyZShcIi4vcmVhZGVyX2J1ZmZlclwiKTtcblxuLy8gVXRpbGl0eVxucHJvdG9idWYudXRpbCAgICAgICAgID0gcmVxdWlyZShcIi4vdXRpbC9taW5pbWFsXCIpO1xucHJvdG9idWYucnBjICAgICAgICAgID0gcmVxdWlyZShcIi4vcnBjXCIpO1xucHJvdG9idWYucm9vdHMgICAgICAgID0gcmVxdWlyZShcIi4vcm9vdHNcIik7XG5wcm90b2J1Zi5jb25maWd1cmUgICAgPSBjb25maWd1cmU7XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4vKipcbiAqIFJlY29uZmlndXJlcyB0aGUgbGlicmFyeSBhY2NvcmRpbmcgdG8gdGhlIGVudmlyb25tZW50LlxuICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAqL1xuZnVuY3Rpb24gY29uZmlndXJlKCkge1xuICAgIHByb3RvYnVmLnV0aWwuX2NvbmZpZ3VyZSgpO1xuICAgIHByb3RvYnVmLldyaXRlci5fY29uZmlndXJlKHByb3RvYnVmLkJ1ZmZlcldyaXRlcik7XG4gICAgcHJvdG9idWYuUmVhZGVyLl9jb25maWd1cmUocHJvdG9idWYuQnVmZmVyUmVhZGVyKTtcbn1cblxuLy8gU2V0IHVwIGJ1ZmZlciB1dGlsaXR5IGFjY29yZGluZyB0byB0aGUgZW52aXJvbm1lbnRcbmNvbmZpZ3VyZSgpO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5tb2R1bGUuZXhwb3J0cyA9IFJlYWRlcjtcblxudmFyIHV0aWwgICAgICA9IHJlcXVpcmUoXCIuL3V0aWwvbWluaW1hbFwiKTtcblxudmFyIEJ1ZmZlclJlYWRlcjsgLy8gY3ljbGljXG5cbnZhciBMb25nQml0cyAgPSB1dGlsLkxvbmdCaXRzLFxuICAgIHV0ZjggICAgICA9IHV0aWwudXRmODtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbmZ1bmN0aW9uIGluZGV4T3V0T2ZSYW5nZShyZWFkZXIsIHdyaXRlTGVuZ3RoKSB7XG4gICAgcmV0dXJuIFJhbmdlRXJyb3IoXCJpbmRleCBvdXQgb2YgcmFuZ2U6IFwiICsgcmVhZGVyLnBvcyArIFwiICsgXCIgKyAod3JpdGVMZW5ndGggfHwgMSkgKyBcIiA+IFwiICsgcmVhZGVyLmxlbik7XG59XG5cbi8qKlxuICogQ29uc3RydWN0cyBhIG5ldyByZWFkZXIgaW5zdGFuY2UgdXNpbmcgdGhlIHNwZWNpZmllZCBidWZmZXIuXG4gKiBAY2xhc3NkZXNjIFdpcmUgZm9ybWF0IHJlYWRlciB1c2luZyBgVWludDhBcnJheWAgaWYgYXZhaWxhYmxlLCBvdGhlcndpc2UgYEFycmF5YC5cbiAqIEBjb25zdHJ1Y3RvclxuICogQHBhcmFtIHtVaW50OEFycmF5fSBidWZmZXIgQnVmZmVyIHRvIHJlYWQgZnJvbVxuICovXG5mdW5jdGlvbiBSZWFkZXIoYnVmZmVyKSB7XG5cbiAgICAvKipcbiAgICAgKiBSZWFkIGJ1ZmZlci5cbiAgICAgKiBAdHlwZSB7VWludDhBcnJheX1cbiAgICAgKi9cbiAgICB0aGlzLmJ1ZiA9IGJ1ZmZlcjtcblxuICAgIC8qKlxuICAgICAqIFJlYWQgYnVmZmVyIHBvc2l0aW9uLlxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG4gICAgdGhpcy5wb3MgPSAwO1xuXG4gICAgLyoqXG4gICAgICogUmVhZCBidWZmZXIgbGVuZ3RoLlxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG4gICAgdGhpcy5sZW4gPSBidWZmZXIubGVuZ3RoO1xufVxuXG52YXIgY3JlYXRlX2FycmF5ID0gdHlwZW9mIFVpbnQ4QXJyYXkgIT09IFwidW5kZWZpbmVkXCJcbiAgICA/IGZ1bmN0aW9uIGNyZWF0ZV90eXBlZF9hcnJheShidWZmZXIpIHtcbiAgICAgICAgaWYgKGJ1ZmZlciBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkgfHwgQXJyYXkuaXNBcnJheShidWZmZXIpKVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBSZWFkZXIoYnVmZmVyKTtcbiAgICAgICAgdGhyb3cgRXJyb3IoXCJpbGxlZ2FsIGJ1ZmZlclwiKTtcbiAgICB9XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICA6IGZ1bmN0aW9uIGNyZWF0ZV9hcnJheShidWZmZXIpIHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoYnVmZmVyKSlcbiAgICAgICAgICAgIHJldHVybiBuZXcgUmVhZGVyKGJ1ZmZlcik7XG4gICAgICAgIHRocm93IEVycm9yKFwiaWxsZWdhbCBidWZmZXJcIik7XG4gICAgfTtcblxudmFyIGNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZSgpIHtcbiAgICByZXR1cm4gdXRpbC5CdWZmZXJcbiAgICAgICAgPyBmdW5jdGlvbiBjcmVhdGVfYnVmZmVyX3NldHVwKGJ1ZmZlcikge1xuICAgICAgICAgICAgcmV0dXJuIChSZWFkZXIuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlX2J1ZmZlcihidWZmZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdXRpbC5CdWZmZXIuaXNCdWZmZXIoYnVmZmVyKVxuICAgICAgICAgICAgICAgICAgICA/IG5ldyBCdWZmZXJSZWFkZXIoYnVmZmVyKVxuICAgICAgICAgICAgICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgICAgICAgICAgICAgICA6IGNyZWF0ZV9hcnJheShidWZmZXIpO1xuICAgICAgICAgICAgfSkoYnVmZmVyKTtcbiAgICAgICAgfVxuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgICA6IGNyZWF0ZV9hcnJheTtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyByZWFkZXIgdXNpbmcgdGhlIHNwZWNpZmllZCBidWZmZXIuXG4gKiBAZnVuY3Rpb25cbiAqIEBwYXJhbSB7VWludDhBcnJheXxCdWZmZXJ9IGJ1ZmZlciBCdWZmZXIgdG8gcmVhZCBmcm9tXG4gKiBAcmV0dXJucyB7UmVhZGVyfEJ1ZmZlclJlYWRlcn0gQSB7QGxpbmsgQnVmZmVyUmVhZGVyfSBpZiBgYnVmZmVyYCBpcyBhIEJ1ZmZlciwgb3RoZXJ3aXNlIGEge0BsaW5rIFJlYWRlcn1cbiAqIEB0aHJvd3Mge0Vycm9yfSBJZiBgYnVmZmVyYCBpcyBub3QgYSB2YWxpZCBidWZmZXJcbiAqL1xuUmVhZGVyLmNyZWF0ZSA9IGNyZWF0ZSgpO1xuXG5SZWFkZXIucHJvdG90eXBlLl9zbGljZSA9IHV0aWwuQXJyYXkucHJvdG90eXBlLnN1YmFycmF5IHx8IC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovIHV0aWwuQXJyYXkucHJvdG90eXBlLnNsaWNlO1xuXG4vKipcbiAqIFJlYWRzIGEgdmFyaW50IGFzIGFuIHVuc2lnbmVkIDMyIGJpdCB2YWx1ZS5cbiAqIEBmdW5jdGlvblxuICogQHJldHVybnMge251bWJlcn0gVmFsdWUgcmVhZFxuICovXG5SZWFkZXIucHJvdG90eXBlLnVpbnQzMiA9IChmdW5jdGlvbiByZWFkX3VpbnQzMl9zZXR1cCgpIHtcbiAgICB2YXIgdmFsdWUgPSA0Mjk0OTY3Mjk1OyAvLyBvcHRpbWl6ZXIgdHlwZS1oaW50LCB0ZW5kcyB0byBkZW9wdCBvdGhlcndpc2UgKD8hKVxuICAgIHJldHVybiBmdW5jdGlvbiByZWFkX3VpbnQzMigpIHtcbiAgICAgICAgdmFsdWUgPSAoICAgICAgICAgdGhpcy5idWZbdGhpcy5wb3NdICYgMTI3ICAgICAgICkgPj4+IDA7IGlmICh0aGlzLmJ1Zlt0aGlzLnBvcysrXSA8IDEyOCkgcmV0dXJuIHZhbHVlO1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSB8ICh0aGlzLmJ1Zlt0aGlzLnBvc10gJiAxMjcpIDw8ICA3KSA+Pj4gMDsgaWYgKHRoaXMuYnVmW3RoaXMucG9zKytdIDwgMTI4KSByZXR1cm4gdmFsdWU7XG4gICAgICAgIHZhbHVlID0gKHZhbHVlIHwgKHRoaXMuYnVmW3RoaXMucG9zXSAmIDEyNykgPDwgMTQpID4+PiAwOyBpZiAodGhpcy5idWZbdGhpcy5wb3MrK10gPCAxMjgpIHJldHVybiB2YWx1ZTtcbiAgICAgICAgdmFsdWUgPSAodmFsdWUgfCAodGhpcy5idWZbdGhpcy5wb3NdICYgMTI3KSA8PCAyMSkgPj4+IDA7IGlmICh0aGlzLmJ1Zlt0aGlzLnBvcysrXSA8IDEyOCkgcmV0dXJuIHZhbHVlO1xuICAgICAgICB2YWx1ZSA9ICh2YWx1ZSB8ICh0aGlzLmJ1Zlt0aGlzLnBvc10gJiAgMTUpIDw8IDI4KSA+Pj4gMDsgaWYgKHRoaXMuYnVmW3RoaXMucG9zKytdIDwgMTI4KSByZXR1cm4gdmFsdWU7XG5cbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICAgIGlmICgodGhpcy5wb3MgKz0gNSkgPiB0aGlzLmxlbikge1xuICAgICAgICAgICAgdGhpcy5wb3MgPSB0aGlzLmxlbjtcbiAgICAgICAgICAgIHRocm93IGluZGV4T3V0T2ZSYW5nZSh0aGlzLCAxMCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH07XG59KSgpO1xuXG4vKipcbiAqIFJlYWRzIGEgdmFyaW50IGFzIGEgc2lnbmVkIDMyIGJpdCB2YWx1ZS5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcbiAqL1xuUmVhZGVyLnByb3RvdHlwZS5pbnQzMiA9IGZ1bmN0aW9uIHJlYWRfaW50MzIoKSB7XG4gICAgcmV0dXJuIHRoaXMudWludDMyKCkgfCAwO1xufTtcblxuLyoqXG4gKiBSZWFkcyBhIHppZy16YWcgZW5jb2RlZCB2YXJpbnQgYXMgYSBzaWduZWQgMzIgYml0IHZhbHVlLlxuICogQHJldHVybnMge251bWJlcn0gVmFsdWUgcmVhZFxuICovXG5SZWFkZXIucHJvdG90eXBlLnNpbnQzMiA9IGZ1bmN0aW9uIHJlYWRfc2ludDMyKCkge1xuICAgIHZhciB2YWx1ZSA9IHRoaXMudWludDMyKCk7XG4gICAgcmV0dXJuIHZhbHVlID4+PiAxIF4gLSh2YWx1ZSAmIDEpIHwgMDtcbn07XG5cbi8qIGVzbGludC1kaXNhYmxlIG5vLWludmFsaWQtdGhpcyAqL1xuXG5mdW5jdGlvbiByZWFkTG9uZ1ZhcmludCgpIHtcbiAgICAvLyB0ZW5kcyB0byBkZW9wdCB3aXRoIGxvY2FsIHZhcnMgZm9yIG9jdGV0IGV0Yy5cbiAgICB2YXIgYml0cyA9IG5ldyBMb25nQml0cygwLCAwKTtcbiAgICB2YXIgaSA9IDA7XG4gICAgaWYgKHRoaXMubGVuIC0gdGhpcy5wb3MgPiA0KSB7IC8vIGZhc3Qgcm91dGUgKGxvKVxuICAgICAgICBmb3IgKDsgaSA8IDQ7ICsraSkge1xuICAgICAgICAgICAgLy8gMXN0Li40dGhcbiAgICAgICAgICAgIGJpdHMubG8gPSAoYml0cy5sbyB8ICh0aGlzLmJ1Zlt0aGlzLnBvc10gJiAxMjcpIDw8IGkgKiA3KSA+Pj4gMDtcbiAgICAgICAgICAgIGlmICh0aGlzLmJ1Zlt0aGlzLnBvcysrXSA8IDEyOClcbiAgICAgICAgICAgICAgICByZXR1cm4gYml0cztcbiAgICAgICAgfVxuICAgICAgICAvLyA1dGhcbiAgICAgICAgYml0cy5sbyA9IChiaXRzLmxvIHwgKHRoaXMuYnVmW3RoaXMucG9zXSAmIDEyNykgPDwgMjgpID4+PiAwO1xuICAgICAgICBiaXRzLmhpID0gKGJpdHMuaGkgfCAodGhpcy5idWZbdGhpcy5wb3NdICYgMTI3KSA+PiAgNCkgPj4+IDA7XG4gICAgICAgIGlmICh0aGlzLmJ1Zlt0aGlzLnBvcysrXSA8IDEyOClcbiAgICAgICAgICAgIHJldHVybiBiaXRzO1xuICAgICAgICBpID0gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBmb3IgKDsgaSA8IDM7ICsraSkge1xuICAgICAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICAgICAgICBpZiAodGhpcy5wb3MgPj0gdGhpcy5sZW4pXG4gICAgICAgICAgICAgICAgdGhyb3cgaW5kZXhPdXRPZlJhbmdlKHRoaXMpO1xuICAgICAgICAgICAgLy8gMXN0Li4zdGhcbiAgICAgICAgICAgIGJpdHMubG8gPSAoYml0cy5sbyB8ICh0aGlzLmJ1Zlt0aGlzLnBvc10gJiAxMjcpIDw8IGkgKiA3KSA+Pj4gMDtcbiAgICAgICAgICAgIGlmICh0aGlzLmJ1Zlt0aGlzLnBvcysrXSA8IDEyOClcbiAgICAgICAgICAgICAgICByZXR1cm4gYml0cztcbiAgICAgICAgfVxuICAgICAgICAvLyA0dGhcbiAgICAgICAgYml0cy5sbyA9IChiaXRzLmxvIHwgKHRoaXMuYnVmW3RoaXMucG9zKytdICYgMTI3KSA8PCBpICogNykgPj4+IDA7XG4gICAgICAgIHJldHVybiBiaXRzO1xuICAgIH1cbiAgICBpZiAodGhpcy5sZW4gLSB0aGlzLnBvcyA+IDQpIHsgLy8gZmFzdCByb3V0ZSAoaGkpXG4gICAgICAgIGZvciAoOyBpIDwgNTsgKytpKSB7XG4gICAgICAgICAgICAvLyA2dGguLjEwdGhcbiAgICAgICAgICAgIGJpdHMuaGkgPSAoYml0cy5oaSB8ICh0aGlzLmJ1Zlt0aGlzLnBvc10gJiAxMjcpIDw8IGkgKiA3ICsgMykgPj4+IDA7XG4gICAgICAgICAgICBpZiAodGhpcy5idWZbdGhpcy5wb3MrK10gPCAxMjgpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGJpdHM7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBmb3IgKDsgaSA8IDU7ICsraSkge1xuICAgICAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICAgICAgICBpZiAodGhpcy5wb3MgPj0gdGhpcy5sZW4pXG4gICAgICAgICAgICAgICAgdGhyb3cgaW5kZXhPdXRPZlJhbmdlKHRoaXMpO1xuICAgICAgICAgICAgLy8gNnRoLi4xMHRoXG4gICAgICAgICAgICBiaXRzLmhpID0gKGJpdHMuaGkgfCAodGhpcy5idWZbdGhpcy5wb3NdICYgMTI3KSA8PCBpICogNyArIDMpID4+PiAwO1xuICAgICAgICAgICAgaWYgKHRoaXMuYnVmW3RoaXMucG9zKytdIDwgMTI4KVxuICAgICAgICAgICAgICAgIHJldHVybiBiaXRzO1xuICAgICAgICB9XG4gICAgfVxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdGhyb3cgRXJyb3IoXCJpbnZhbGlkIHZhcmludCBlbmNvZGluZ1wiKTtcbn1cblxuLyogZXNsaW50LWVuYWJsZSBuby1pbnZhbGlkLXRoaXMgKi9cblxuLyoqXG4gKiBSZWFkcyBhIHZhcmludCBhcyBhIHNpZ25lZCA2NCBiaXQgdmFsdWUuXG4gKiBAbmFtZSBSZWFkZXIjaW50NjRcbiAqIEBmdW5jdGlvblxuICogQHJldHVybnMge0xvbmd9IFZhbHVlIHJlYWRcbiAqL1xuXG4vKipcbiAqIFJlYWRzIGEgdmFyaW50IGFzIGFuIHVuc2lnbmVkIDY0IGJpdCB2YWx1ZS5cbiAqIEBuYW1lIFJlYWRlciN1aW50NjRcbiAqIEBmdW5jdGlvblxuICogQHJldHVybnMge0xvbmd9IFZhbHVlIHJlYWRcbiAqL1xuXG4vKipcbiAqIFJlYWRzIGEgemlnLXphZyBlbmNvZGVkIHZhcmludCBhcyBhIHNpZ25lZCA2NCBiaXQgdmFsdWUuXG4gKiBAbmFtZSBSZWFkZXIjc2ludDY0XG4gKiBAZnVuY3Rpb25cbiAqIEByZXR1cm5zIHtMb25nfSBWYWx1ZSByZWFkXG4gKi9cblxuLyoqXG4gKiBSZWFkcyBhIHZhcmludCBhcyBhIGJvb2xlYW4uXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gVmFsdWUgcmVhZFxuICovXG5SZWFkZXIucHJvdG90eXBlLmJvb2wgPSBmdW5jdGlvbiByZWFkX2Jvb2woKSB7XG4gICAgcmV0dXJuIHRoaXMudWludDMyKCkgIT09IDA7XG59O1xuXG5mdW5jdGlvbiByZWFkRml4ZWQzMl9lbmQoYnVmLCBlbmQpIHsgLy8gbm90ZSB0aGF0IHRoaXMgdXNlcyBgZW5kYCwgbm90IGBwb3NgXG4gICAgcmV0dXJuIChidWZbZW5kIC0gNF1cbiAgICAgICAgICB8IGJ1ZltlbmQgLSAzXSA8PCA4XG4gICAgICAgICAgfCBidWZbZW5kIC0gMl0gPDwgMTZcbiAgICAgICAgICB8IGJ1ZltlbmQgLSAxXSA8PCAyNCkgPj4+IDA7XG59XG5cbi8qKlxuICogUmVhZHMgZml4ZWQgMzIgYml0cyBhcyBhbiB1bnNpZ25lZCAzMiBiaXQgaW50ZWdlci5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcbiAqL1xuUmVhZGVyLnByb3RvdHlwZS5maXhlZDMyID0gZnVuY3Rpb24gcmVhZF9maXhlZDMyKCkge1xuXG4gICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgaWYgKHRoaXMucG9zICsgNCA+IHRoaXMubGVuKVxuICAgICAgICB0aHJvdyBpbmRleE91dE9mUmFuZ2UodGhpcywgNCk7XG5cbiAgICByZXR1cm4gcmVhZEZpeGVkMzJfZW5kKHRoaXMuYnVmLCB0aGlzLnBvcyArPSA0KTtcbn07XG5cbi8qKlxuICogUmVhZHMgZml4ZWQgMzIgYml0cyBhcyBhIHNpZ25lZCAzMiBiaXQgaW50ZWdlci5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcbiAqL1xuUmVhZGVyLnByb3RvdHlwZS5zZml4ZWQzMiA9IGZ1bmN0aW9uIHJlYWRfc2ZpeGVkMzIoKSB7XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICBpZiAodGhpcy5wb3MgKyA0ID4gdGhpcy5sZW4pXG4gICAgICAgIHRocm93IGluZGV4T3V0T2ZSYW5nZSh0aGlzLCA0KTtcblxuICAgIHJldHVybiByZWFkRml4ZWQzMl9lbmQodGhpcy5idWYsIHRoaXMucG9zICs9IDQpIHwgMDtcbn07XG5cbi8qIGVzbGludC1kaXNhYmxlIG5vLWludmFsaWQtdGhpcyAqL1xuXG5mdW5jdGlvbiByZWFkRml4ZWQ2NCgvKiB0aGlzOiBSZWFkZXIgKi8pIHtcblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmICh0aGlzLnBvcyArIDggPiB0aGlzLmxlbilcbiAgICAgICAgdGhyb3cgaW5kZXhPdXRPZlJhbmdlKHRoaXMsIDgpO1xuXG4gICAgcmV0dXJuIG5ldyBMb25nQml0cyhyZWFkRml4ZWQzMl9lbmQodGhpcy5idWYsIHRoaXMucG9zICs9IDQpLCByZWFkRml4ZWQzMl9lbmQodGhpcy5idWYsIHRoaXMucG9zICs9IDQpKTtcbn1cblxuLyogZXNsaW50LWVuYWJsZSBuby1pbnZhbGlkLXRoaXMgKi9cblxuLyoqXG4gKiBSZWFkcyBmaXhlZCA2NCBiaXRzLlxuICogQG5hbWUgUmVhZGVyI2ZpeGVkNjRcbiAqIEBmdW5jdGlvblxuICogQHJldHVybnMge0xvbmd9IFZhbHVlIHJlYWRcbiAqL1xuXG4vKipcbiAqIFJlYWRzIHppZy16YWcgZW5jb2RlZCBmaXhlZCA2NCBiaXRzLlxuICogQG5hbWUgUmVhZGVyI3NmaXhlZDY0XG4gKiBAZnVuY3Rpb25cbiAqIEByZXR1cm5zIHtMb25nfSBWYWx1ZSByZWFkXG4gKi9cblxuLyoqXG4gKiBSZWFkcyBhIGZsb2F0ICgzMiBiaXQpIGFzIGEgbnVtYmVyLlxuICogQGZ1bmN0aW9uXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBWYWx1ZSByZWFkXG4gKi9cblJlYWRlci5wcm90b3R5cGUuZmxvYXQgPSBmdW5jdGlvbiByZWFkX2Zsb2F0KCkge1xuXG4gICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgaWYgKHRoaXMucG9zICsgNCA+IHRoaXMubGVuKVxuICAgICAgICB0aHJvdyBpbmRleE91dE9mUmFuZ2UodGhpcywgNCk7XG5cbiAgICB2YXIgdmFsdWUgPSB1dGlsLmZsb2F0LnJlYWRGbG9hdExFKHRoaXMuYnVmLCB0aGlzLnBvcyk7XG4gICAgdGhpcy5wb3MgKz0gNDtcbiAgICByZXR1cm4gdmFsdWU7XG59O1xuXG4vKipcbiAqIFJlYWRzIGEgZG91YmxlICg2NCBiaXQgZmxvYXQpIGFzIGEgbnVtYmVyLlxuICogQGZ1bmN0aW9uXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBWYWx1ZSByZWFkXG4gKi9cblJlYWRlci5wcm90b3R5cGUuZG91YmxlID0gZnVuY3Rpb24gcmVhZF9kb3VibGUoKSB7XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICBpZiAodGhpcy5wb3MgKyA4ID4gdGhpcy5sZW4pXG4gICAgICAgIHRocm93IGluZGV4T3V0T2ZSYW5nZSh0aGlzLCA0KTtcblxuICAgIHZhciB2YWx1ZSA9IHV0aWwuZmxvYXQucmVhZERvdWJsZUxFKHRoaXMuYnVmLCB0aGlzLnBvcyk7XG4gICAgdGhpcy5wb3MgKz0gODtcbiAgICByZXR1cm4gdmFsdWU7XG59O1xuXG4vKipcbiAqIFJlYWRzIGEgc2VxdWVuY2Ugb2YgYnl0ZXMgcHJlY2VlZGVkIGJ5IGl0cyBsZW5ndGggYXMgYSB2YXJpbnQuXG4gKiBAcmV0dXJucyB7VWludDhBcnJheX0gVmFsdWUgcmVhZFxuICovXG5SZWFkZXIucHJvdG90eXBlLmJ5dGVzID0gZnVuY3Rpb24gcmVhZF9ieXRlcygpIHtcbiAgICB2YXIgbGVuZ3RoID0gdGhpcy51aW50MzIoKSxcbiAgICAgICAgc3RhcnQgID0gdGhpcy5wb3MsXG4gICAgICAgIGVuZCAgICA9IHRoaXMucG9zICsgbGVuZ3RoO1xuXG4gICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgaWYgKGVuZCA+IHRoaXMubGVuKVxuICAgICAgICB0aHJvdyBpbmRleE91dE9mUmFuZ2UodGhpcywgbGVuZ3RoKTtcblxuICAgIHRoaXMucG9zICs9IGxlbmd0aDtcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh0aGlzLmJ1ZikpIC8vIHBsYWluIGFycmF5XG4gICAgICAgIHJldHVybiB0aGlzLmJ1Zi5zbGljZShzdGFydCwgZW5kKTtcbiAgICByZXR1cm4gc3RhcnQgPT09IGVuZCAvLyBmaXggZm9yIElFIDEwL1dpbjggYW5kIG90aGVycycgc3ViYXJyYXkgcmV0dXJuaW5nIGFycmF5IG9mIHNpemUgMVxuICAgICAgICA/IG5ldyB0aGlzLmJ1Zi5jb25zdHJ1Y3RvcigwKVxuICAgICAgICA6IHRoaXMuX3NsaWNlLmNhbGwodGhpcy5idWYsIHN0YXJ0LCBlbmQpO1xufTtcblxuLyoqXG4gKiBSZWFkcyBhIHN0cmluZyBwcmVjZWVkZWQgYnkgaXRzIGJ5dGUgbGVuZ3RoIGFzIGEgdmFyaW50LlxuICogQHJldHVybnMge3N0cmluZ30gVmFsdWUgcmVhZFxuICovXG5SZWFkZXIucHJvdG90eXBlLnN0cmluZyA9IGZ1bmN0aW9uIHJlYWRfc3RyaW5nKCkge1xuICAgIHZhciBieXRlcyA9IHRoaXMuYnl0ZXMoKTtcbiAgICByZXR1cm4gdXRmOC5yZWFkKGJ5dGVzLCAwLCBieXRlcy5sZW5ndGgpO1xufTtcblxuLyoqXG4gKiBTa2lwcyB0aGUgc3BlY2lmaWVkIG51bWJlciBvZiBieXRlcyBpZiBzcGVjaWZpZWQsIG90aGVyd2lzZSBza2lwcyBhIHZhcmludC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbbGVuZ3RoXSBMZW5ndGggaWYga25vd24sIG90aGVyd2lzZSBhIHZhcmludCBpcyBhc3N1bWVkXG4gKiBAcmV0dXJucyB7UmVhZGVyfSBgdGhpc2BcbiAqL1xuUmVhZGVyLnByb3RvdHlwZS5za2lwID0gZnVuY3Rpb24gc2tpcChsZW5ndGgpIHtcbiAgICBpZiAodHlwZW9mIGxlbmd0aCA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgaWYgKi9cbiAgICAgICAgaWYgKHRoaXMucG9zICsgbGVuZ3RoID4gdGhpcy5sZW4pXG4gICAgICAgICAgICB0aHJvdyBpbmRleE91dE9mUmFuZ2UodGhpcywgbGVuZ3RoKTtcbiAgICAgICAgdGhpcy5wb3MgKz0gbGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgICAgICAgICAgaWYgKHRoaXMucG9zID49IHRoaXMubGVuKVxuICAgICAgICAgICAgICAgIHRocm93IGluZGV4T3V0T2ZSYW5nZSh0aGlzKTtcbiAgICAgICAgfSB3aGlsZSAodGhpcy5idWZbdGhpcy5wb3MrK10gJiAxMjgpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogU2tpcHMgdGhlIG5leHQgZWxlbWVudCBvZiB0aGUgc3BlY2lmaWVkIHdpcmUgdHlwZS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB3aXJlVHlwZSBXaXJlIHR5cGUgcmVjZWl2ZWRcbiAqIEByZXR1cm5zIHtSZWFkZXJ9IGB0aGlzYFxuICovXG5SZWFkZXIucHJvdG90eXBlLnNraXBUeXBlID0gZnVuY3Rpb24od2lyZVR5cGUpIHtcbiAgICBzd2l0Y2ggKHdpcmVUeXBlKSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgIHRoaXMuc2tpcCgpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgIHRoaXMuc2tpcCg4KTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICB0aGlzLnNraXAodGhpcy51aW50MzIoKSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgd2hpbGUgKCh3aXJlVHlwZSA9IHRoaXMudWludDMyKCkgJiA3KSAhPT0gNCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2tpcFR5cGUod2lyZVR5cGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgIHRoaXMuc2tpcCg0KTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICB0aHJvdyBFcnJvcihcImludmFsaWQgd2lyZSB0eXBlIFwiICsgd2lyZVR5cGUgKyBcIiBhdCBvZmZzZXQgXCIgKyB0aGlzLnBvcyk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xufTtcblxuUmVhZGVyLl9jb25maWd1cmUgPSBmdW5jdGlvbihCdWZmZXJSZWFkZXJfKSB7XG4gICAgQnVmZmVyUmVhZGVyID0gQnVmZmVyUmVhZGVyXztcbiAgICBSZWFkZXIuY3JlYXRlID0gY3JlYXRlKCk7XG4gICAgQnVmZmVyUmVhZGVyLl9jb25maWd1cmUoKTtcblxuICAgIHZhciBmbiA9IHV0aWwuTG9uZyA/IFwidG9Mb25nXCIgOiAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqLyBcInRvTnVtYmVyXCI7XG4gICAgdXRpbC5tZXJnZShSZWFkZXIucHJvdG90eXBlLCB7XG5cbiAgICAgICAgaW50NjQ6IGZ1bmN0aW9uIHJlYWRfaW50NjQoKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVhZExvbmdWYXJpbnQuY2FsbCh0aGlzKVtmbl0oZmFsc2UpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHVpbnQ2NDogZnVuY3Rpb24gcmVhZF91aW50NjQoKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVhZExvbmdWYXJpbnQuY2FsbCh0aGlzKVtmbl0odHJ1ZSk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgc2ludDY0OiBmdW5jdGlvbiByZWFkX3NpbnQ2NCgpIHtcbiAgICAgICAgICAgIHJldHVybiByZWFkTG9uZ1ZhcmludC5jYWxsKHRoaXMpLnp6RGVjb2RlKClbZm5dKGZhbHNlKTtcbiAgICAgICAgfSxcblxuICAgICAgICBmaXhlZDY0OiBmdW5jdGlvbiByZWFkX2ZpeGVkNjQoKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVhZEZpeGVkNjQuY2FsbCh0aGlzKVtmbl0odHJ1ZSk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgc2ZpeGVkNjQ6IGZ1bmN0aW9uIHJlYWRfc2ZpeGVkNjQoKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVhZEZpeGVkNjQuY2FsbCh0aGlzKVtmbl0oZmFsc2UpO1xuICAgICAgICB9XG5cbiAgICB9KTtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcbm1vZHVsZS5leHBvcnRzID0gQnVmZmVyUmVhZGVyO1xuXG4vLyBleHRlbmRzIFJlYWRlclxudmFyIFJlYWRlciA9IHJlcXVpcmUoXCIuL3JlYWRlclwiKTtcbihCdWZmZXJSZWFkZXIucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShSZWFkZXIucHJvdG90eXBlKSkuY29uc3RydWN0b3IgPSBCdWZmZXJSZWFkZXI7XG5cbnZhciB1dGlsID0gcmVxdWlyZShcIi4vdXRpbC9taW5pbWFsXCIpO1xuXG4vKipcbiAqIENvbnN0cnVjdHMgYSBuZXcgYnVmZmVyIHJlYWRlciBpbnN0YW5jZS5cbiAqIEBjbGFzc2Rlc2MgV2lyZSBmb3JtYXQgcmVhZGVyIHVzaW5nIG5vZGUgYnVmZmVycy5cbiAqIEBleHRlbmRzIFJlYWRlclxuICogQGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge0J1ZmZlcn0gYnVmZmVyIEJ1ZmZlciB0byByZWFkIGZyb21cbiAqL1xuZnVuY3Rpb24gQnVmZmVyUmVhZGVyKGJ1ZmZlcikge1xuICAgIFJlYWRlci5jYWxsKHRoaXMsIGJ1ZmZlcik7XG5cbiAgICAvKipcbiAgICAgKiBSZWFkIGJ1ZmZlci5cbiAgICAgKiBAbmFtZSBCdWZmZXJSZWFkZXIjYnVmXG4gICAgICogQHR5cGUge0J1ZmZlcn1cbiAgICAgKi9cbn1cblxuQnVmZmVyUmVhZGVyLl9jb25maWd1cmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICBpZiAodXRpbC5CdWZmZXIpXG4gICAgICAgIEJ1ZmZlclJlYWRlci5wcm90b3R5cGUuX3NsaWNlID0gdXRpbC5CdWZmZXIucHJvdG90eXBlLnNsaWNlO1xufTtcblxuXG4vKipcbiAqIEBvdmVycmlkZVxuICovXG5CdWZmZXJSZWFkZXIucHJvdG90eXBlLnN0cmluZyA9IGZ1bmN0aW9uIHJlYWRfc3RyaW5nX2J1ZmZlcigpIHtcbiAgICB2YXIgbGVuID0gdGhpcy51aW50MzIoKTsgLy8gbW9kaWZpZXMgcG9zXG4gICAgcmV0dXJuIHRoaXMuYnVmLnV0ZjhTbGljZVxuICAgICAgICA/IHRoaXMuYnVmLnV0ZjhTbGljZSh0aGlzLnBvcywgdGhpcy5wb3MgPSBNYXRoLm1pbih0aGlzLnBvcyArIGxlbiwgdGhpcy5sZW4pKVxuICAgICAgICA6IHRoaXMuYnVmLnRvU3RyaW5nKFwidXRmLThcIiwgdGhpcy5wb3MsIHRoaXMucG9zID0gTWF0aC5taW4odGhpcy5wb3MgKyBsZW4sIHRoaXMubGVuKSk7XG59O1xuXG4vKipcbiAqIFJlYWRzIGEgc2VxdWVuY2Ugb2YgYnl0ZXMgcHJlY2VlZGVkIGJ5IGl0cyBsZW5ndGggYXMgYSB2YXJpbnQuXG4gKiBAbmFtZSBCdWZmZXJSZWFkZXIjYnl0ZXNcbiAqIEBmdW5jdGlvblxuICogQHJldHVybnMge0J1ZmZlcn0gVmFsdWUgcmVhZFxuICovXG5cbkJ1ZmZlclJlYWRlci5fY29uZmlndXJlKCk7XG4iLCJcInVzZSBzdHJpY3RcIjtcbm1vZHVsZS5leHBvcnRzID0ge307XG5cbi8qKlxuICogTmFtZWQgcm9vdHMuXG4gKiBUaGlzIGlzIHdoZXJlIHBianMgc3RvcmVzIGdlbmVyYXRlZCBzdHJ1Y3R1cmVzICh0aGUgb3B0aW9uIGAtciwgLS1yb290YCBzcGVjaWZpZXMgYSBuYW1lKS5cbiAqIENhbiBhbHNvIGJlIHVzZWQgbWFudWFsbHkgdG8gbWFrZSByb290cyBhdmFpbGFibGUgYWNjcm9zcyBtb2R1bGVzLlxuICogQG5hbWUgcm9vdHNcbiAqIEB0eXBlIHtPYmplY3QuPHN0cmluZyxSb290Pn1cbiAqIEBleGFtcGxlXG4gKiAvLyBwYmpzIC1yIG15cm9vdCAtbyBjb21waWxlZC5qcyAuLi5cbiAqXG4gKiAvLyBpbiBhbm90aGVyIG1vZHVsZTpcbiAqIHJlcXVpcmUoXCIuL2NvbXBpbGVkLmpzXCIpO1xuICpcbiAqIC8vIGluIGFueSBzdWJzZXF1ZW50IG1vZHVsZTpcbiAqIHZhciByb290ID0gcHJvdG9idWYucm9vdHNbXCJteXJvb3RcIl07XG4gKi9cbiIsIlwidXNlIHN0cmljdFwiO1xuXG4vKipcbiAqIFN0cmVhbWluZyBSUEMgaGVscGVycy5cbiAqIEBuYW1lc3BhY2VcbiAqL1xudmFyIHJwYyA9IGV4cG9ydHM7XG5cbi8qKlxuICogUlBDIGltcGxlbWVudGF0aW9uIHBhc3NlZCB0byB7QGxpbmsgU2VydmljZSNjcmVhdGV9IHBlcmZvcm1pbmcgYSBzZXJ2aWNlIHJlcXVlc3Qgb24gbmV0d29yayBsZXZlbCwgaS5lLiBieSB1dGlsaXppbmcgaHR0cCByZXF1ZXN0cyBvciB3ZWJzb2NrZXRzLlxuICogQHR5cGVkZWYgUlBDSW1wbFxuICogQHR5cGUge2Z1bmN0aW9ufVxuICogQHBhcmFtIHtNZXRob2R8cnBjLlNlcnZpY2VNZXRob2Q8TWVzc2FnZTx7fT4sTWVzc2FnZTx7fT4+fSBtZXRob2QgUmVmbGVjdGVkIG9yIHN0YXRpYyBtZXRob2QgYmVpbmcgY2FsbGVkXG4gKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IHJlcXVlc3REYXRhIFJlcXVlc3QgZGF0YVxuICogQHBhcmFtIHtSUENJbXBsQ2FsbGJhY2t9IGNhbGxiYWNrIENhbGxiYWNrIGZ1bmN0aW9uXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICogQGV4YW1wbGVcbiAqIGZ1bmN0aW9uIHJwY0ltcGwobWV0aG9kLCByZXF1ZXN0RGF0YSwgY2FsbGJhY2spIHtcbiAqICAgICBpZiAocHJvdG9idWYudXRpbC5sY0ZpcnN0KG1ldGhvZC5uYW1lKSAhPT0gXCJteU1ldGhvZFwiKSAvLyBjb21wYXRpYmxlIHdpdGggc3RhdGljIGNvZGVcbiAqICAgICAgICAgdGhyb3cgRXJyb3IoXCJubyBzdWNoIG1ldGhvZFwiKTtcbiAqICAgICBhc3luY2hyb25vdXNseU9idGFpbkFSZXNwb25zZShyZXF1ZXN0RGF0YSwgZnVuY3Rpb24oZXJyLCByZXNwb25zZURhdGEpIHtcbiAqICAgICAgICAgY2FsbGJhY2soZXJyLCByZXNwb25zZURhdGEpO1xuICogICAgIH0pO1xuICogfVxuICovXG5cbi8qKlxuICogTm9kZS1zdHlsZSBjYWxsYmFjayBhcyB1c2VkIGJ5IHtAbGluayBSUENJbXBsfS5cbiAqIEB0eXBlZGVmIFJQQ0ltcGxDYWxsYmFja1xuICogQHR5cGUge2Z1bmN0aW9ufVxuICogQHBhcmFtIHtFcnJvcnxudWxsfSBlcnJvciBFcnJvciwgaWYgYW55LCBvdGhlcndpc2UgYG51bGxgXG4gKiBAcGFyYW0ge1VpbnQ4QXJyYXl8bnVsbH0gW3Jlc3BvbnNlXSBSZXNwb25zZSBkYXRhIG9yIGBudWxsYCB0byBzaWduYWwgZW5kIG9mIHN0cmVhbSwgaWYgdGhlcmUgaGFzbid0IGJlZW4gYW4gZXJyb3JcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gKi9cblxucnBjLlNlcnZpY2UgPSByZXF1aXJlKFwiLi9ycGMvc2VydmljZVwiKTtcbiIsIlwidXNlIHN0cmljdFwiO1xubW9kdWxlLmV4cG9ydHMgPSBTZXJ2aWNlO1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoXCIuLi91dGlsL21pbmltYWxcIik7XG5cbi8vIEV4dGVuZHMgRXZlbnRFbWl0dGVyXG4oU2VydmljZS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHV0aWwuRXZlbnRFbWl0dGVyLnByb3RvdHlwZSkpLmNvbnN0cnVjdG9yID0gU2VydmljZTtcblxuLyoqXG4gKiBBIHNlcnZpY2UgbWV0aG9kIGNhbGxiYWNrIGFzIHVzZWQgYnkge0BsaW5rIHJwYy5TZXJ2aWNlTWV0aG9kfFNlcnZpY2VNZXRob2R9LlxuICpcbiAqIERpZmZlcnMgZnJvbSB7QGxpbmsgUlBDSW1wbENhbGxiYWNrfSBpbiB0aGF0IGl0IGlzIGFuIGFjdHVhbCBjYWxsYmFjayBvZiBhIHNlcnZpY2UgbWV0aG9kIHdoaWNoIG1heSBub3QgcmV0dXJuIGByZXNwb25zZSA9IG51bGxgLlxuICogQHR5cGVkZWYgcnBjLlNlcnZpY2VNZXRob2RDYWxsYmFja1xuICogQHRlbXBsYXRlIFRSZXMgZXh0ZW5kcyBNZXNzYWdlPFRSZXM+XG4gKiBAdHlwZSB7ZnVuY3Rpb259XG4gKiBAcGFyYW0ge0Vycm9yfG51bGx9IGVycm9yIEVycm9yLCBpZiBhbnlcbiAqIEBwYXJhbSB7VFJlc30gW3Jlc3BvbnNlXSBSZXNwb25zZSBtZXNzYWdlXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICovXG5cbi8qKlxuICogQSBzZXJ2aWNlIG1ldGhvZCBwYXJ0IG9mIGEge0BsaW5rIHJwYy5TZXJ2aWNlfSBhcyBjcmVhdGVkIGJ5IHtAbGluayBTZXJ2aWNlLmNyZWF0ZX0uXG4gKiBAdHlwZWRlZiBycGMuU2VydmljZU1ldGhvZFxuICogQHRlbXBsYXRlIFRSZXEgZXh0ZW5kcyBNZXNzYWdlPFRSZXE+XG4gKiBAdGVtcGxhdGUgVFJlcyBleHRlbmRzIE1lc3NhZ2U8VFJlcz5cbiAqIEB0eXBlIHtmdW5jdGlvbn1cbiAqIEBwYXJhbSB7VFJlcXxQcm9wZXJ0aWVzPFRSZXE+fSByZXF1ZXN0IFJlcXVlc3QgbWVzc2FnZSBvciBwbGFpbiBvYmplY3RcbiAqIEBwYXJhbSB7cnBjLlNlcnZpY2VNZXRob2RDYWxsYmFjazxUUmVzPn0gW2NhbGxiYWNrXSBOb2RlLXN0eWxlIGNhbGxiYWNrIGNhbGxlZCB3aXRoIHRoZSBlcnJvciwgaWYgYW55LCBhbmQgdGhlIHJlc3BvbnNlIG1lc3NhZ2VcbiAqIEByZXR1cm5zIHtQcm9taXNlPE1lc3NhZ2U8VFJlcz4+fSBQcm9taXNlIGlmIGBjYWxsYmFja2AgaGFzIGJlZW4gb21pdHRlZCwgb3RoZXJ3aXNlIGB1bmRlZmluZWRgXG4gKi9cblxuLyoqXG4gKiBDb25zdHJ1Y3RzIGEgbmV3IFJQQyBzZXJ2aWNlIGluc3RhbmNlLlxuICogQGNsYXNzZGVzYyBBbiBSUEMgc2VydmljZSBhcyByZXR1cm5lZCBieSB7QGxpbmsgU2VydmljZSNjcmVhdGV9LlxuICogQGV4cG9ydHMgcnBjLlNlcnZpY2VcbiAqIEBleHRlbmRzIHV0aWwuRXZlbnRFbWl0dGVyXG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7UlBDSW1wbH0gcnBjSW1wbCBSUEMgaW1wbGVtZW50YXRpb25cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW3JlcXVlc3REZWxpbWl0ZWQ9ZmFsc2VdIFdoZXRoZXIgcmVxdWVzdHMgYXJlIGxlbmd0aC1kZWxpbWl0ZWRcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW3Jlc3BvbnNlRGVsaW1pdGVkPWZhbHNlXSBXaGV0aGVyIHJlc3BvbnNlcyBhcmUgbGVuZ3RoLWRlbGltaXRlZFxuICovXG5mdW5jdGlvbiBTZXJ2aWNlKHJwY0ltcGwsIHJlcXVlc3REZWxpbWl0ZWQsIHJlc3BvbnNlRGVsaW1pdGVkKSB7XG5cbiAgICBpZiAodHlwZW9mIHJwY0ltcGwgIT09IFwiZnVuY3Rpb25cIilcbiAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwicnBjSW1wbCBtdXN0IGJlIGEgZnVuY3Rpb25cIik7XG5cbiAgICB1dGlsLkV2ZW50RW1pdHRlci5jYWxsKHRoaXMpO1xuXG4gICAgLyoqXG4gICAgICogUlBDIGltcGxlbWVudGF0aW9uLiBCZWNvbWVzIGBudWxsYCBvbmNlIHRoZSBzZXJ2aWNlIGlzIGVuZGVkLlxuICAgICAqIEB0eXBlIHtSUENJbXBsfG51bGx9XG4gICAgICovXG4gICAgdGhpcy5ycGNJbXBsID0gcnBjSW1wbDtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgcmVxdWVzdHMgYXJlIGxlbmd0aC1kZWxpbWl0ZWQuXG4gICAgICogQHR5cGUge2Jvb2xlYW59XG4gICAgICovXG4gICAgdGhpcy5yZXF1ZXN0RGVsaW1pdGVkID0gQm9vbGVhbihyZXF1ZXN0RGVsaW1pdGVkKTtcblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgcmVzcG9uc2VzIGFyZSBsZW5ndGgtZGVsaW1pdGVkLlxuICAgICAqIEB0eXBlIHtib29sZWFufVxuICAgICAqL1xuICAgIHRoaXMucmVzcG9uc2VEZWxpbWl0ZWQgPSBCb29sZWFuKHJlc3BvbnNlRGVsaW1pdGVkKTtcbn1cblxuLyoqXG4gKiBDYWxscyBhIHNlcnZpY2UgbWV0aG9kIHRocm91Z2gge0BsaW5rIHJwYy5TZXJ2aWNlI3JwY0ltcGx8cnBjSW1wbH0uXG4gKiBAcGFyYW0ge01ldGhvZHxycGMuU2VydmljZU1ldGhvZDxUUmVxLFRSZXM+fSBtZXRob2QgUmVmbGVjdGVkIG9yIHN0YXRpYyBtZXRob2RcbiAqIEBwYXJhbSB7Q29uc3RydWN0b3I8VFJlcT59IHJlcXVlc3RDdG9yIFJlcXVlc3QgY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7Q29uc3RydWN0b3I8VFJlcz59IHJlc3BvbnNlQ3RvciBSZXNwb25zZSBjb25zdHJ1Y3RvclxuICogQHBhcmFtIHtUUmVxfFByb3BlcnRpZXM8VFJlcT59IHJlcXVlc3QgUmVxdWVzdCBtZXNzYWdlIG9yIHBsYWluIG9iamVjdFxuICogQHBhcmFtIHtycGMuU2VydmljZU1ldGhvZENhbGxiYWNrPFRSZXM+fSBjYWxsYmFjayBTZXJ2aWNlIGNhbGxiYWNrXG4gKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICogQHRlbXBsYXRlIFRSZXEgZXh0ZW5kcyBNZXNzYWdlPFRSZXE+XG4gKiBAdGVtcGxhdGUgVFJlcyBleHRlbmRzIE1lc3NhZ2U8VFJlcz5cbiAqL1xuU2VydmljZS5wcm90b3R5cGUucnBjQ2FsbCA9IGZ1bmN0aW9uIHJwY0NhbGwobWV0aG9kLCByZXF1ZXN0Q3RvciwgcmVzcG9uc2VDdG9yLCByZXF1ZXN0LCBjYWxsYmFjaykge1xuXG4gICAgaWYgKCFyZXF1ZXN0KVxuICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJyZXF1ZXN0IG11c3QgYmUgc3BlY2lmaWVkXCIpO1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIGlmICghY2FsbGJhY2spXG4gICAgICAgIHJldHVybiB1dGlsLmFzUHJvbWlzZShycGNDYWxsLCBzZWxmLCBtZXRob2QsIHJlcXVlc3RDdG9yLCByZXNwb25zZUN0b3IsIHJlcXVlc3QpO1xuXG4gICAgaWYgKCFzZWxmLnJwY0ltcGwpIHtcbiAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHsgY2FsbGJhY2soRXJyb3IoXCJhbHJlYWR5IGVuZGVkXCIpKTsgfSwgMCk7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIHNlbGYucnBjSW1wbChcbiAgICAgICAgICAgIG1ldGhvZCxcbiAgICAgICAgICAgIHJlcXVlc3RDdG9yW3NlbGYucmVxdWVzdERlbGltaXRlZCA/IFwiZW5jb2RlRGVsaW1pdGVkXCIgOiBcImVuY29kZVwiXShyZXF1ZXN0KS5maW5pc2goKSxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJwY0NhbGxiYWNrKGVyciwgcmVzcG9uc2UpIHtcblxuICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5lbWl0KFwiZXJyb3JcIiwgZXJyLCBtZXRob2QpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2soZXJyKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2UgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5lbmQoLyogZW5kZWRCeVJQQyAqLyB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShyZXNwb25zZSBpbnN0YW5jZW9mIHJlc3BvbnNlQ3RvcikpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlID0gcmVzcG9uc2VDdG9yW3NlbGYucmVzcG9uc2VEZWxpbWl0ZWQgPyBcImRlY29kZURlbGltaXRlZFwiIDogXCJkZWNvZGVcIl0ocmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuZW1pdChcImVycm9yXCIsIGVyciwgbWV0aG9kKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjYWxsYmFjayhlcnIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgc2VsZi5lbWl0KFwiZGF0YVwiLCByZXNwb25zZSwgbWV0aG9kKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2FsbGJhY2sobnVsbCwgcmVzcG9uc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBzZWxmLmVtaXQoXCJlcnJvclwiLCBlcnIsIG1ldGhvZCk7XG4gICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7IGNhbGxiYWNrKGVycik7IH0sIDApO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbn07XG5cbi8qKlxuICogRW5kcyB0aGlzIHNlcnZpY2UgYW5kIGVtaXRzIHRoZSBgZW5kYCBldmVudC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2VuZGVkQnlSUEM9ZmFsc2VdIFdoZXRoZXIgdGhlIHNlcnZpY2UgaGFzIGJlZW4gZW5kZWQgYnkgdGhlIFJQQyBpbXBsZW1lbnRhdGlvbi5cbiAqIEByZXR1cm5zIHtycGMuU2VydmljZX0gYHRoaXNgXG4gKi9cblNlcnZpY2UucHJvdG90eXBlLmVuZCA9IGZ1bmN0aW9uIGVuZChlbmRlZEJ5UlBDKSB7XG4gICAgaWYgKHRoaXMucnBjSW1wbCkge1xuICAgICAgICBpZiAoIWVuZGVkQnlSUEMpIC8vIHNpZ25hbCBlbmQgdG8gcnBjSW1wbFxuICAgICAgICAgICAgdGhpcy5ycGNJbXBsKG51bGwsIG51bGwsIG51bGwpO1xuICAgICAgICB0aGlzLnJwY0ltcGwgPSBudWxsO1xuICAgICAgICB0aGlzLmVtaXQoXCJlbmRcIikub2ZmKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xubW9kdWxlLmV4cG9ydHMgPSBMb25nQml0cztcblxudmFyIHV0aWwgPSByZXF1aXJlKFwiLi4vdXRpbC9taW5pbWFsXCIpO1xuXG4vKipcbiAqIENvbnN0cnVjdHMgbmV3IGxvbmcgYml0cy5cbiAqIEBjbGFzc2Rlc2MgSGVscGVyIGNsYXNzIGZvciB3b3JraW5nIHdpdGggdGhlIGxvdyBhbmQgaGlnaCBiaXRzIG9mIGEgNjQgYml0IHZhbHVlLlxuICogQG1lbWJlcm9mIHV0aWxcbiAqIEBjb25zdHJ1Y3RvclxuICogQHBhcmFtIHtudW1iZXJ9IGxvIExvdyAzMiBiaXRzLCB1bnNpZ25lZFxuICogQHBhcmFtIHtudW1iZXJ9IGhpIEhpZ2ggMzIgYml0cywgdW5zaWduZWRcbiAqL1xuZnVuY3Rpb24gTG9uZ0JpdHMobG8sIGhpKSB7XG5cbiAgICAvLyBub3RlIHRoYXQgdGhlIGNhc3RzIGJlbG93IGFyZSB0aGVvcmV0aWNhbGx5IHVubmVjZXNzYXJ5IGFzIG9mIHRvZGF5LCBidXQgb2xkZXIgc3RhdGljYWxseVxuICAgIC8vIGdlbmVyYXRlZCBjb252ZXJ0ZXIgY29kZSBtaWdodCBzdGlsbCBjYWxsIHRoZSBjdG9yIHdpdGggc2lnbmVkIDMyYml0cy4ga2VwdCBmb3IgY29tcGF0LlxuXG4gICAgLyoqXG4gICAgICogTG93IGJpdHMuXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cbiAgICB0aGlzLmxvID0gbG8gPj4+IDA7XG5cbiAgICAvKipcbiAgICAgKiBIaWdoIGJpdHMuXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cbiAgICB0aGlzLmhpID0gaGkgPj4+IDA7XG59XG5cbi8qKlxuICogWmVybyBiaXRzLlxuICogQG1lbWJlcm9mIHV0aWwuTG9uZ0JpdHNcbiAqIEB0eXBlIHt1dGlsLkxvbmdCaXRzfVxuICovXG52YXIgemVybyA9IExvbmdCaXRzLnplcm8gPSBuZXcgTG9uZ0JpdHMoMCwgMCk7XG5cbnplcm8udG9OdW1iZXIgPSBmdW5jdGlvbigpIHsgcmV0dXJuIDA7IH07XG56ZXJvLnp6RW5jb2RlID0gemVyby56ekRlY29kZSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfTtcbnplcm8ubGVuZ3RoID0gZnVuY3Rpb24oKSB7IHJldHVybiAxOyB9O1xuXG4vKipcbiAqIFplcm8gaGFzaC5cbiAqIEBtZW1iZXJvZiB1dGlsLkxvbmdCaXRzXG4gKiBAdHlwZSB7c3RyaW5nfVxuICovXG52YXIgemVyb0hhc2ggPSBMb25nQml0cy56ZXJvSGFzaCA9IFwiXFwwXFwwXFwwXFwwXFwwXFwwXFwwXFwwXCI7XG5cbi8qKlxuICogQ29uc3RydWN0cyBuZXcgbG9uZyBiaXRzIGZyb20gdGhlIHNwZWNpZmllZCBudW1iZXIuXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWVcbiAqIEByZXR1cm5zIHt1dGlsLkxvbmdCaXRzfSBJbnN0YW5jZVxuICovXG5Mb25nQml0cy5mcm9tTnVtYmVyID0gZnVuY3Rpb24gZnJvbU51bWJlcih2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PT0gMClcbiAgICAgICAgcmV0dXJuIHplcm87XG4gICAgdmFyIHNpZ24gPSB2YWx1ZSA8IDA7XG4gICAgaWYgKHNpZ24pXG4gICAgICAgIHZhbHVlID0gLXZhbHVlO1xuICAgIHZhciBsbyA9IHZhbHVlID4+PiAwLFxuICAgICAgICBoaSA9ICh2YWx1ZSAtIGxvKSAvIDQyOTQ5NjcyOTYgPj4+IDA7XG4gICAgaWYgKHNpZ24pIHtcbiAgICAgICAgaGkgPSB+aGkgPj4+IDA7XG4gICAgICAgIGxvID0gfmxvID4+PiAwO1xuICAgICAgICBpZiAoKytsbyA+IDQyOTQ5NjcyOTUpIHtcbiAgICAgICAgICAgIGxvID0gMDtcbiAgICAgICAgICAgIGlmICgrK2hpID4gNDI5NDk2NzI5NSlcbiAgICAgICAgICAgICAgICBoaSA9IDA7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5ldyBMb25nQml0cyhsbywgaGkpO1xufTtcblxuLyoqXG4gKiBDb25zdHJ1Y3RzIG5ldyBsb25nIGJpdHMgZnJvbSBhIG51bWJlciwgbG9uZyBvciBzdHJpbmcuXG4gKiBAcGFyYW0ge0xvbmd8bnVtYmVyfHN0cmluZ30gdmFsdWUgVmFsdWVcbiAqIEByZXR1cm5zIHt1dGlsLkxvbmdCaXRzfSBJbnN0YW5jZVxuICovXG5Mb25nQml0cy5mcm9tID0gZnVuY3Rpb24gZnJvbSh2YWx1ZSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwibnVtYmVyXCIpXG4gICAgICAgIHJldHVybiBMb25nQml0cy5mcm9tTnVtYmVyKHZhbHVlKTtcbiAgICBpZiAodXRpbC5pc1N0cmluZyh2YWx1ZSkpIHtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICAgICAgaWYgKHV0aWwuTG9uZylcbiAgICAgICAgICAgIHZhbHVlID0gdXRpbC5Mb25nLmZyb21TdHJpbmcodmFsdWUpO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICByZXR1cm4gTG9uZ0JpdHMuZnJvbU51bWJlcihwYXJzZUludCh2YWx1ZSwgMTApKTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlLmxvdyB8fCB2YWx1ZS5oaWdoID8gbmV3IExvbmdCaXRzKHZhbHVlLmxvdyA+Pj4gMCwgdmFsdWUuaGlnaCA+Pj4gMCkgOiB6ZXJvO1xufTtcblxuLyoqXG4gKiBDb252ZXJ0cyB0aGlzIGxvbmcgYml0cyB0byBhIHBvc3NpYmx5IHVuc2FmZSBKYXZhU2NyaXB0IG51bWJlci5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW3Vuc2lnbmVkPWZhbHNlXSBXaGV0aGVyIHVuc2lnbmVkIG9yIG5vdFxuICogQHJldHVybnMge251bWJlcn0gUG9zc2libHkgdW5zYWZlIG51bWJlclxuICovXG5Mb25nQml0cy5wcm90b3R5cGUudG9OdW1iZXIgPSBmdW5jdGlvbiB0b051bWJlcih1bnNpZ25lZCkge1xuICAgIGlmICghdW5zaWduZWQgJiYgdGhpcy5oaSA+Pj4gMzEpIHtcbiAgICAgICAgdmFyIGxvID0gfnRoaXMubG8gKyAxID4+PiAwLFxuICAgICAgICAgICAgaGkgPSB+dGhpcy5oaSAgICAgPj4+IDA7XG4gICAgICAgIGlmICghbG8pXG4gICAgICAgICAgICBoaSA9IGhpICsgMSA+Pj4gMDtcbiAgICAgICAgcmV0dXJuIC0obG8gKyBoaSAqIDQyOTQ5NjcyOTYpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5sbyArIHRoaXMuaGkgKiA0Mjk0OTY3Mjk2O1xufTtcblxuLyoqXG4gKiBDb252ZXJ0cyB0aGlzIGxvbmcgYml0cyB0byBhIGxvbmcuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFt1bnNpZ25lZD1mYWxzZV0gV2hldGhlciB1bnNpZ25lZCBvciBub3RcbiAqIEByZXR1cm5zIHtMb25nfSBMb25nXG4gKi9cbkxvbmdCaXRzLnByb3RvdHlwZS50b0xvbmcgPSBmdW5jdGlvbiB0b0xvbmcodW5zaWduZWQpIHtcbiAgICByZXR1cm4gdXRpbC5Mb25nXG4gICAgICAgID8gbmV3IHV0aWwuTG9uZyh0aGlzLmxvIHwgMCwgdGhpcy5oaSB8IDAsIEJvb2xlYW4odW5zaWduZWQpKVxuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgICA6IHsgbG93OiB0aGlzLmxvIHwgMCwgaGlnaDogdGhpcy5oaSB8IDAsIHVuc2lnbmVkOiBCb29sZWFuKHVuc2lnbmVkKSB9O1xufTtcblxudmFyIGNoYXJDb2RlQXQgPSBTdHJpbmcucHJvdG90eXBlLmNoYXJDb2RlQXQ7XG5cbi8qKlxuICogQ29uc3RydWN0cyBuZXcgbG9uZyBiaXRzIGZyb20gdGhlIHNwZWNpZmllZCA4IGNoYXJhY3RlcnMgbG9uZyBoYXNoLlxuICogQHBhcmFtIHtzdHJpbmd9IGhhc2ggSGFzaFxuICogQHJldHVybnMge3V0aWwuTG9uZ0JpdHN9IEJpdHNcbiAqL1xuTG9uZ0JpdHMuZnJvbUhhc2ggPSBmdW5jdGlvbiBmcm9tSGFzaChoYXNoKSB7XG4gICAgaWYgKGhhc2ggPT09IHplcm9IYXNoKVxuICAgICAgICByZXR1cm4gemVybztcbiAgICByZXR1cm4gbmV3IExvbmdCaXRzKFxuICAgICAgICAoIGNoYXJDb2RlQXQuY2FsbChoYXNoLCAwKVxuICAgICAgICB8IGNoYXJDb2RlQXQuY2FsbChoYXNoLCAxKSA8PCA4XG4gICAgICAgIHwgY2hhckNvZGVBdC5jYWxsKGhhc2gsIDIpIDw8IDE2XG4gICAgICAgIHwgY2hhckNvZGVBdC5jYWxsKGhhc2gsIDMpIDw8IDI0KSA+Pj4gMFxuICAgICxcbiAgICAgICAgKCBjaGFyQ29kZUF0LmNhbGwoaGFzaCwgNClcbiAgICAgICAgfCBjaGFyQ29kZUF0LmNhbGwoaGFzaCwgNSkgPDwgOFxuICAgICAgICB8IGNoYXJDb2RlQXQuY2FsbChoYXNoLCA2KSA8PCAxNlxuICAgICAgICB8IGNoYXJDb2RlQXQuY2FsbChoYXNoLCA3KSA8PCAyNCkgPj4+IDBcbiAgICApO1xufTtcblxuLyoqXG4gKiBDb252ZXJ0cyB0aGlzIGxvbmcgYml0cyB0byBhIDggY2hhcmFjdGVycyBsb25nIGhhc2guXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBIYXNoXG4gKi9cbkxvbmdCaXRzLnByb3RvdHlwZS50b0hhc2ggPSBmdW5jdGlvbiB0b0hhc2goKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoXG4gICAgICAgIHRoaXMubG8gICAgICAgICYgMjU1LFxuICAgICAgICB0aGlzLmxvID4+PiA4ICAmIDI1NSxcbiAgICAgICAgdGhpcy5sbyA+Pj4gMTYgJiAyNTUsXG4gICAgICAgIHRoaXMubG8gPj4+IDI0ICAgICAgLFxuICAgICAgICB0aGlzLmhpICAgICAgICAmIDI1NSxcbiAgICAgICAgdGhpcy5oaSA+Pj4gOCAgJiAyNTUsXG4gICAgICAgIHRoaXMuaGkgPj4+IDE2ICYgMjU1LFxuICAgICAgICB0aGlzLmhpID4+PiAyNFxuICAgICk7XG59O1xuXG4vKipcbiAqIFppZy16YWcgZW5jb2RlcyB0aGlzIGxvbmcgYml0cy5cbiAqIEByZXR1cm5zIHt1dGlsLkxvbmdCaXRzfSBgdGhpc2BcbiAqL1xuTG9uZ0JpdHMucHJvdG90eXBlLnp6RW5jb2RlID0gZnVuY3Rpb24genpFbmNvZGUoKSB7XG4gICAgdmFyIG1hc2sgPSAgIHRoaXMuaGkgPj4gMzE7XG4gICAgdGhpcy5oaSAgPSAoKHRoaXMuaGkgPDwgMSB8IHRoaXMubG8gPj4+IDMxKSBeIG1hc2spID4+PiAwO1xuICAgIHRoaXMubG8gID0gKCB0aGlzLmxvIDw8IDEgICAgICAgICAgICAgICAgICAgXiBtYXNrKSA+Pj4gMDtcbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogWmlnLXphZyBkZWNvZGVzIHRoaXMgbG9uZyBiaXRzLlxuICogQHJldHVybnMge3V0aWwuTG9uZ0JpdHN9IGB0aGlzYFxuICovXG5Mb25nQml0cy5wcm90b3R5cGUuenpEZWNvZGUgPSBmdW5jdGlvbiB6ekRlY29kZSgpIHtcbiAgICB2YXIgbWFzayA9IC0odGhpcy5sbyAmIDEpO1xuICAgIHRoaXMubG8gID0gKCh0aGlzLmxvID4+PiAxIHwgdGhpcy5oaSA8PCAzMSkgXiBtYXNrKSA+Pj4gMDtcbiAgICB0aGlzLmhpICA9ICggdGhpcy5oaSA+Pj4gMSAgICAgICAgICAgICAgICAgIF4gbWFzaykgPj4+IDA7XG4gICAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIENhbGN1bGF0ZXMgdGhlIGxlbmd0aCBvZiB0aGlzIGxvbmdiaXRzIHdoZW4gZW5jb2RlZCBhcyBhIHZhcmludC5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IExlbmd0aFxuICovXG5Mb25nQml0cy5wcm90b3R5cGUubGVuZ3RoID0gZnVuY3Rpb24gbGVuZ3RoKCkge1xuICAgIHZhciBwYXJ0MCA9ICB0aGlzLmxvLFxuICAgICAgICBwYXJ0MSA9ICh0aGlzLmxvID4+PiAyOCB8IHRoaXMuaGkgPDwgNCkgPj4+IDAsXG4gICAgICAgIHBhcnQyID0gIHRoaXMuaGkgPj4+IDI0O1xuICAgIHJldHVybiBwYXJ0MiA9PT0gMFxuICAgICAgICAgPyBwYXJ0MSA9PT0gMFxuICAgICAgICAgICA/IHBhcnQwIDwgMTYzODRcbiAgICAgICAgICAgICA/IHBhcnQwIDwgMTI4ID8gMSA6IDJcbiAgICAgICAgICAgICA6IHBhcnQwIDwgMjA5NzE1MiA/IDMgOiA0XG4gICAgICAgICAgIDogcGFydDEgPCAxNjM4NFxuICAgICAgICAgICAgID8gcGFydDEgPCAxMjggPyA1IDogNlxuICAgICAgICAgICAgIDogcGFydDEgPCAyMDk3MTUyID8gNyA6IDhcbiAgICAgICAgIDogcGFydDIgPCAxMjggPyA5IDogMTA7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG52YXIgdXRpbCA9IGV4cG9ydHM7XG5cbi8vIHVzZWQgdG8gcmV0dXJuIGEgUHJvbWlzZSB3aGVyZSBjYWxsYmFjayBpcyBvbWl0dGVkXG51dGlsLmFzUHJvbWlzZSA9IHJlcXVpcmUoXCJAcHJvdG9idWZqcy9hc3Byb21pc2VcIik7XG5cbi8vIGNvbnZlcnRzIHRvIC8gZnJvbSBiYXNlNjQgZW5jb2RlZCBzdHJpbmdzXG51dGlsLmJhc2U2NCA9IHJlcXVpcmUoXCJAcHJvdG9idWZqcy9iYXNlNjRcIik7XG5cbi8vIGJhc2UgY2xhc3Mgb2YgcnBjLlNlcnZpY2VcbnV0aWwuRXZlbnRFbWl0dGVyID0gcmVxdWlyZShcIkBwcm90b2J1ZmpzL2V2ZW50ZW1pdHRlclwiKTtcblxuLy8gZmxvYXQgaGFuZGxpbmcgYWNjcm9zcyBicm93c2Vyc1xudXRpbC5mbG9hdCA9IHJlcXVpcmUoXCJAcHJvdG9idWZqcy9mbG9hdFwiKTtcblxuLy8gcmVxdWlyZXMgbW9kdWxlcyBvcHRpb25hbGx5IGFuZCBoaWRlcyB0aGUgY2FsbCBmcm9tIGJ1bmRsZXJzXG51dGlsLmlucXVpcmUgPSByZXF1aXJlKFwiQHByb3RvYnVmanMvaW5xdWlyZVwiKTtcblxuLy8gY29udmVydHMgdG8gLyBmcm9tIHV0ZjggZW5jb2RlZCBzdHJpbmdzXG51dGlsLnV0ZjggPSByZXF1aXJlKFwiQHByb3RvYnVmanMvdXRmOFwiKTtcblxuLy8gcHJvdmlkZXMgYSBub2RlLWxpa2UgYnVmZmVyIHBvb2wgaW4gdGhlIGJyb3dzZXJcbnV0aWwucG9vbCA9IHJlcXVpcmUoXCJAcHJvdG9idWZqcy9wb29sXCIpO1xuXG4vLyB1dGlsaXR5IHRvIHdvcmsgd2l0aCB0aGUgbG93IGFuZCBoaWdoIGJpdHMgb2YgYSA2NCBiaXQgdmFsdWVcbnV0aWwuTG9uZ0JpdHMgPSByZXF1aXJlKFwiLi9sb25nYml0c1wiKTtcblxuLyoqXG4gKiBXaGV0aGVyIHJ1bm5pbmcgd2l0aGluIG5vZGUgb3Igbm90LlxuICogQG1lbWJlcm9mIHV0aWxcbiAqIEB0eXBlIHtib29sZWFufVxuICovXG51dGlsLmlzTm9kZSA9IEJvb2xlYW4odHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIlxuICAgICAgICAgICAgICAgICAgICYmIGdsb2JhbFxuICAgICAgICAgICAgICAgICAgICYmIGdsb2JhbC5wcm9jZXNzXG4gICAgICAgICAgICAgICAgICAgJiYgZ2xvYmFsLnByb2Nlc3MudmVyc2lvbnNcbiAgICAgICAgICAgICAgICAgICAmJiBnbG9iYWwucHJvY2Vzcy52ZXJzaW9ucy5ub2RlKTtcblxuLyoqXG4gKiBHbG9iYWwgb2JqZWN0IHJlZmVyZW5jZS5cbiAqIEBtZW1iZXJvZiB1dGlsXG4gKiBAdHlwZSB7T2JqZWN0fVxuICovXG51dGlsLmdsb2JhbCA9IHV0aWwuaXNOb2RlICYmIGdsb2JhbFxuICAgICAgICAgICB8fCB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiICYmIHdpbmRvd1xuICAgICAgICAgICB8fCB0eXBlb2Ygc2VsZiAgICE9PSBcInVuZGVmaW5lZFwiICYmIHNlbGZcbiAgICAgICAgICAgfHwgdGhpczsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1pbnZhbGlkLXRoaXNcblxuLyoqXG4gKiBBbiBpbW11YWJsZSBlbXB0eSBhcnJheS5cbiAqIEBtZW1iZXJvZiB1dGlsXG4gKiBAdHlwZSB7QXJyYXkuPCo+fVxuICogQGNvbnN0XG4gKi9cbnV0aWwuZW1wdHlBcnJheSA9IE9iamVjdC5mcmVlemUgPyBPYmplY3QuZnJlZXplKFtdKSA6IC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovIFtdOyAvLyB1c2VkIG9uIHByb3RvdHlwZXNcblxuLyoqXG4gKiBBbiBpbW11dGFibGUgZW1wdHkgb2JqZWN0LlxuICogQHR5cGUge09iamVjdH1cbiAqIEBjb25zdFxuICovXG51dGlsLmVtcHR5T2JqZWN0ID0gT2JqZWN0LmZyZWV6ZSA/IE9iamVjdC5mcmVlemUoe30pIDogLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi8ge307IC8vIHVzZWQgb24gcHJvdG90eXBlc1xuXG4vKipcbiAqIFRlc3RzIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgYW4gaW50ZWdlci5cbiAqIEBmdW5jdGlvblxuICogQHBhcmFtIHsqfSB2YWx1ZSBWYWx1ZSB0byB0ZXN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIGlmIHRoZSB2YWx1ZSBpcyBhbiBpbnRlZ2VyXG4gKi9cbnV0aWwuaXNJbnRlZ2VyID0gTnVtYmVyLmlzSW50ZWdlciB8fCAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqLyBmdW5jdGlvbiBpc0ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiICYmIGlzRmluaXRlKHZhbHVlKSAmJiBNYXRoLmZsb29yKHZhbHVlKSA9PT0gdmFsdWU7XG59O1xuXG4vKipcbiAqIFRlc3RzIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgYSBzdHJpbmcuXG4gKiBAcGFyYW0geyp9IHZhbHVlIFZhbHVlIHRvIHRlc3RcbiAqIEByZXR1cm5zIHtib29sZWFufSBgdHJ1ZWAgaWYgdGhlIHZhbHVlIGlzIGEgc3RyaW5nXG4gKi9cbnV0aWwuaXNTdHJpbmcgPSBmdW5jdGlvbiBpc1N0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgfHwgdmFsdWUgaW5zdGFuY2VvZiBTdHJpbmc7XG59O1xuXG4vKipcbiAqIFRlc3RzIGlmIHRoZSBzcGVjaWZpZWQgdmFsdWUgaXMgYSBub24tbnVsbCBvYmplY3QuXG4gKiBAcGFyYW0geyp9IHZhbHVlIFZhbHVlIHRvIHRlc3RcbiAqIEByZXR1cm5zIHtib29sZWFufSBgdHJ1ZWAgaWYgdGhlIHZhbHVlIGlzIGEgbm9uLW51bGwgb2JqZWN0XG4gKi9cbnV0aWwuaXNPYmplY3QgPSBmdW5jdGlvbiBpc09iamVjdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09IFwib2JqZWN0XCI7XG59O1xuXG4vKipcbiAqIENoZWNrcyBpZiBhIHByb3BlcnR5IG9uIGEgbWVzc2FnZSBpcyBjb25zaWRlcmVkIHRvIGJlIHByZXNlbnQuXG4gKiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayB1dGlsLmlzU2V0fS5cbiAqIEBmdW5jdGlvblxuICogQHBhcmFtIHtPYmplY3R9IG9iaiBQbGFpbiBvYmplY3Qgb3IgbWVzc2FnZSBpbnN0YW5jZVxuICogQHBhcmFtIHtzdHJpbmd9IHByb3AgUHJvcGVydHkgbmFtZVxuICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiBjb25zaWRlcmVkIHRvIGJlIHByZXNlbnQsIG90aGVyd2lzZSBgZmFsc2VgXG4gKi9cbnV0aWwuaXNzZXQgPVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIHByb3BlcnR5IG9uIGEgbWVzc2FnZSBpcyBjb25zaWRlcmVkIHRvIGJlIHByZXNlbnQuXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqIFBsYWluIG9iamVjdCBvciBtZXNzYWdlIGluc3RhbmNlXG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcCBQcm9wZXJ0eSBuYW1lXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIGlmIGNvbnNpZGVyZWQgdG8gYmUgcHJlc2VudCwgb3RoZXJ3aXNlIGBmYWxzZWBcbiAqL1xudXRpbC5pc1NldCA9IGZ1bmN0aW9uIGlzU2V0KG9iaiwgcHJvcCkge1xuICAgIHZhciB2YWx1ZSA9IG9ialtwcm9wXTtcbiAgICBpZiAodmFsdWUgIT0gbnVsbCAmJiBvYmouaGFzT3duUHJvcGVydHkocHJvcCkpIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgZXFlcWVxLCBuby1wcm90b3R5cGUtYnVpbHRpbnNcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSAhPT0gXCJvYmplY3RcIiB8fCAoQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyB2YWx1ZS5sZW5ndGggOiBPYmplY3Qua2V5cyh2YWx1ZSkubGVuZ3RoKSA+IDA7XG4gICAgcmV0dXJuIGZhbHNlO1xufTtcblxuLyoqXG4gKiBBbnkgY29tcGF0aWJsZSBCdWZmZXIgaW5zdGFuY2UuXG4gKiBUaGlzIGlzIGEgbWluaW1hbCBzdGFuZC1hbG9uZSBkZWZpbml0aW9uIG9mIGEgQnVmZmVyIGluc3RhbmNlLiBUaGUgYWN0dWFsIHR5cGUgaXMgdGhhdCBleHBvcnRlZCBieSBub2RlJ3MgdHlwaW5ncy5cbiAqIEBpbnRlcmZhY2UgQnVmZmVyXG4gKiBAZXh0ZW5kcyBVaW50OEFycmF5XG4gKi9cblxuLyoqXG4gKiBOb2RlJ3MgQnVmZmVyIGNsYXNzIGlmIGF2YWlsYWJsZS5cbiAqIEB0eXBlIHtDb25zdHJ1Y3RvcjxCdWZmZXI+fVxuICovXG51dGlsLkJ1ZmZlciA9IChmdW5jdGlvbigpIHtcbiAgICB0cnkge1xuICAgICAgICB2YXIgQnVmZmVyID0gdXRpbC5pbnF1aXJlKFwiYnVmZmVyXCIpLkJ1ZmZlcjtcbiAgICAgICAgLy8gcmVmdXNlIHRvIHVzZSBub24tbm9kZSBidWZmZXJzIGlmIG5vdCBleHBsaWNpdGx5IGFzc2lnbmVkIChwZXJmIHJlYXNvbnMpOlxuICAgICAgICByZXR1cm4gQnVmZmVyLnByb3RvdHlwZS51dGY4V3JpdGUgPyBCdWZmZXIgOiAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqLyBudWxsO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxufSkoKTtcblxuLy8gSW50ZXJuYWwgYWxpYXMgb2Ygb3IgcG9seWZ1bGwgZm9yIEJ1ZmZlci5mcm9tLlxudXRpbC5fQnVmZmVyX2Zyb20gPSBudWxsO1xuXG4vLyBJbnRlcm5hbCBhbGlhcyBvZiBvciBwb2x5ZmlsbCBmb3IgQnVmZmVyLmFsbG9jVW5zYWZlLlxudXRpbC5fQnVmZmVyX2FsbG9jVW5zYWZlID0gbnVsbDtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGJ1ZmZlciBvZiB3aGF0ZXZlciB0eXBlIHN1cHBvcnRlZCBieSB0aGUgZW52aXJvbm1lbnQuXG4gKiBAcGFyYW0ge251bWJlcnxudW1iZXJbXX0gW3NpemVPckFycmF5PTBdIEJ1ZmZlciBzaXplIG9yIG51bWJlciBhcnJheVxuICogQHJldHVybnMge1VpbnQ4QXJyYXl8QnVmZmVyfSBCdWZmZXJcbiAqL1xudXRpbC5uZXdCdWZmZXIgPSBmdW5jdGlvbiBuZXdCdWZmZXIoc2l6ZU9yQXJyYXkpIHtcbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgIHJldHVybiB0eXBlb2Ygc2l6ZU9yQXJyYXkgPT09IFwibnVtYmVyXCJcbiAgICAgICAgPyB1dGlsLkJ1ZmZlclxuICAgICAgICAgICAgPyB1dGlsLl9CdWZmZXJfYWxsb2NVbnNhZmUoc2l6ZU9yQXJyYXkpXG4gICAgICAgICAgICA6IG5ldyB1dGlsLkFycmF5KHNpemVPckFycmF5KVxuICAgICAgICA6IHV0aWwuQnVmZmVyXG4gICAgICAgICAgICA/IHV0aWwuX0J1ZmZlcl9mcm9tKHNpemVPckFycmF5KVxuICAgICAgICAgICAgOiB0eXBlb2YgVWludDhBcnJheSA9PT0gXCJ1bmRlZmluZWRcIlxuICAgICAgICAgICAgICAgID8gc2l6ZU9yQXJyYXlcbiAgICAgICAgICAgICAgICA6IG5ldyBVaW50OEFycmF5KHNpemVPckFycmF5KTtcbn07XG5cbi8qKlxuICogQXJyYXkgaW1wbGVtZW50YXRpb24gdXNlZCBpbiB0aGUgYnJvd3Nlci4gYFVpbnQ4QXJyYXlgIGlmIHN1cHBvcnRlZCwgb3RoZXJ3aXNlIGBBcnJheWAuXG4gKiBAdHlwZSB7Q29uc3RydWN0b3I8VWludDhBcnJheT59XG4gKi9cbnV0aWwuQXJyYXkgPSB0eXBlb2YgVWludDhBcnJheSAhPT0gXCJ1bmRlZmluZWRcIiA/IFVpbnQ4QXJyYXkgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi8gOiBBcnJheTtcblxuLyoqXG4gKiBBbnkgY29tcGF0aWJsZSBMb25nIGluc3RhbmNlLlxuICogVGhpcyBpcyBhIG1pbmltYWwgc3RhbmQtYWxvbmUgZGVmaW5pdGlvbiBvZiBhIExvbmcgaW5zdGFuY2UuIFRoZSBhY3R1YWwgdHlwZSBpcyB0aGF0IGV4cG9ydGVkIGJ5IGxvbmcuanMuXG4gKiBAaW50ZXJmYWNlIExvbmdcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBsb3cgTG93IGJpdHNcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBoaWdoIEhpZ2ggYml0c1xuICogQHByb3BlcnR5IHtib29sZWFufSB1bnNpZ25lZCBXaGV0aGVyIHVuc2lnbmVkIG9yIG5vdFxuICovXG5cbi8qKlxuICogTG9uZy5qcydzIExvbmcgY2xhc3MgaWYgYXZhaWxhYmxlLlxuICogQHR5cGUge0NvbnN0cnVjdG9yPExvbmc+fVxuICovXG51dGlsLkxvbmcgPSAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqLyB1dGlsLmdsb2JhbC5kY29kZUlPICYmIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovIHV0aWwuZ2xvYmFsLmRjb2RlSU8uTG9uZ1xuICAgICAgICAgfHwgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi8gdXRpbC5nbG9iYWwuTG9uZ1xuICAgICAgICAgfHwgdXRpbC5pbnF1aXJlKFwibG9uZ1wiKTtcblxuLyoqXG4gKiBSZWd1bGFyIGV4cHJlc3Npb24gdXNlZCB0byB2ZXJpZnkgMiBiaXQgKGBib29sYCkgbWFwIGtleXMuXG4gKiBAdHlwZSB7UmVnRXhwfVxuICogQGNvbnN0XG4gKi9cbnV0aWwua2V5MlJlID0gL150cnVlfGZhbHNlfDB8MSQvO1xuXG4vKipcbiAqIFJlZ3VsYXIgZXhwcmVzc2lvbiB1c2VkIHRvIHZlcmlmeSAzMiBiaXQgKGBpbnQzMmAgZXRjLikgbWFwIGtleXMuXG4gKiBAdHlwZSB7UmVnRXhwfVxuICogQGNvbnN0XG4gKi9cbnV0aWwua2V5MzJSZSA9IC9eLT8oPzowfFsxLTldWzAtOV0qKSQvO1xuXG4vKipcbiAqIFJlZ3VsYXIgZXhwcmVzc2lvbiB1c2VkIHRvIHZlcmlmeSA2NCBiaXQgKGBpbnQ2NGAgZXRjLikgbWFwIGtleXMuXG4gKiBAdHlwZSB7UmVnRXhwfVxuICogQGNvbnN0XG4gKi9cbnV0aWwua2V5NjRSZSA9IC9eKD86W1xcXFx4MDAtXFxcXHhmZl17OH18LT8oPzowfFsxLTldWzAtOV0qKSkkLztcblxuLyoqXG4gKiBDb252ZXJ0cyBhIG51bWJlciBvciBsb25nIHRvIGFuIDggY2hhcmFjdGVycyBsb25nIGhhc2ggc3RyaW5nLlxuICogQHBhcmFtIHtMb25nfG51bWJlcn0gdmFsdWUgVmFsdWUgdG8gY29udmVydFxuICogQHJldHVybnMge3N0cmluZ30gSGFzaFxuICovXG51dGlsLmxvbmdUb0hhc2ggPSBmdW5jdGlvbiBsb25nVG9IYXNoKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlXG4gICAgICAgID8gdXRpbC5Mb25nQml0cy5mcm9tKHZhbHVlKS50b0hhc2goKVxuICAgICAgICA6IHV0aWwuTG9uZ0JpdHMuemVyb0hhc2g7XG59O1xuXG4vKipcbiAqIENvbnZlcnRzIGFuIDggY2hhcmFjdGVycyBsb25nIGhhc2ggc3RyaW5nIHRvIGEgbG9uZyBvciBudW1iZXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gaGFzaCBIYXNoXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFt1bnNpZ25lZD1mYWxzZV0gV2hldGhlciB1bnNpZ25lZCBvciBub3RcbiAqIEByZXR1cm5zIHtMb25nfG51bWJlcn0gT3JpZ2luYWwgdmFsdWVcbiAqL1xudXRpbC5sb25nRnJvbUhhc2ggPSBmdW5jdGlvbiBsb25nRnJvbUhhc2goaGFzaCwgdW5zaWduZWQpIHtcbiAgICB2YXIgYml0cyA9IHV0aWwuTG9uZ0JpdHMuZnJvbUhhc2goaGFzaCk7XG4gICAgaWYgKHV0aWwuTG9uZylcbiAgICAgICAgcmV0dXJuIHV0aWwuTG9uZy5mcm9tQml0cyhiaXRzLmxvLCBiaXRzLmhpLCB1bnNpZ25lZCk7XG4gICAgcmV0dXJuIGJpdHMudG9OdW1iZXIoQm9vbGVhbih1bnNpZ25lZCkpO1xufTtcblxuLyoqXG4gKiBNZXJnZXMgdGhlIHByb3BlcnRpZXMgb2YgdGhlIHNvdXJjZSBvYmplY3QgaW50byB0aGUgZGVzdGluYXRpb24gb2JqZWN0LlxuICogQG1lbWJlcm9mIHV0aWxcbiAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IGRzdCBEZXN0aW5hdGlvbiBvYmplY3RcbiAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IHNyYyBTb3VyY2Ugb2JqZWN0XG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtpZk5vdFNldD1mYWxzZV0gTWVyZ2VzIG9ubHkgaWYgdGhlIGtleSBpcyBub3QgYWxyZWFkeSBzZXRcbiAqIEByZXR1cm5zIHtPYmplY3QuPHN0cmluZywqPn0gRGVzdGluYXRpb24gb2JqZWN0XG4gKi9cbmZ1bmN0aW9uIG1lcmdlKGRzdCwgc3JjLCBpZk5vdFNldCkgeyAvLyB1c2VkIGJ5IGNvbnZlcnRlcnNcbiAgICBmb3IgKHZhciBrZXlzID0gT2JqZWN0LmtleXMoc3JjKSwgaSA9IDA7IGkgPCBrZXlzLmxlbmd0aDsgKytpKVxuICAgICAgICBpZiAoZHN0W2tleXNbaV1dID09PSB1bmRlZmluZWQgfHwgIWlmTm90U2V0KVxuICAgICAgICAgICAgZHN0W2tleXNbaV1dID0gc3JjW2tleXNbaV1dO1xuICAgIHJldHVybiBkc3Q7XG59XG5cbnV0aWwubWVyZ2UgPSBtZXJnZTtcblxuLyoqXG4gKiBDb252ZXJ0cyB0aGUgZmlyc3QgY2hhcmFjdGVyIG9mIGEgc3RyaW5nIHRvIGxvd2VyIGNhc2UuXG4gKiBAcGFyYW0ge3N0cmluZ30gc3RyIFN0cmluZyB0byBjb252ZXJ0XG4gKiBAcmV0dXJucyB7c3RyaW5nfSBDb252ZXJ0ZWQgc3RyaW5nXG4gKi9cbnV0aWwubGNGaXJzdCA9IGZ1bmN0aW9uIGxjRmlyc3Qoc3RyKSB7XG4gICAgcmV0dXJuIHN0ci5jaGFyQXQoMCkudG9Mb3dlckNhc2UoKSArIHN0ci5zdWJzdHJpbmcoMSk7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBjdXN0b20gZXJyb3IgY29uc3RydWN0b3IuXG4gKiBAbWVtYmVyb2YgdXRpbFxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgRXJyb3IgbmFtZVxuICogQHJldHVybnMge0NvbnN0cnVjdG9yPEVycm9yPn0gQ3VzdG9tIGVycm9yIGNvbnN0cnVjdG9yXG4gKi9cbmZ1bmN0aW9uIG5ld0Vycm9yKG5hbWUpIHtcblxuICAgIGZ1bmN0aW9uIEN1c3RvbUVycm9yKG1lc3NhZ2UsIHByb3BlcnRpZXMpIHtcblxuICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgQ3VzdG9tRXJyb3IpKVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBDdXN0b21FcnJvcihtZXNzYWdlLCBwcm9wZXJ0aWVzKTtcblxuICAgICAgICAvLyBFcnJvci5jYWxsKHRoaXMsIG1lc3NhZ2UpO1xuICAgICAgICAvLyBeIGp1c3QgcmV0dXJucyBhIG5ldyBlcnJvciBpbnN0YW5jZSBiZWNhdXNlIHRoZSBjdG9yIGNhbiBiZSBjYWxsZWQgYXMgYSBmdW5jdGlvblxuXG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCBcIm1lc3NhZ2VcIiwgeyBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbWVzc2FnZTsgfSB9KTtcblxuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgICBpZiAoRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UpIC8vIG5vZGVcbiAgICAgICAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIEN1c3RvbUVycm9yKTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIFwic3RhY2tcIiwgeyB2YWx1ZTogbmV3IEVycm9yKCkuc3RhY2sgfHwgXCJcIiB9KTtcblxuICAgICAgICBpZiAocHJvcGVydGllcylcbiAgICAgICAgICAgIG1lcmdlKHRoaXMsIHByb3BlcnRpZXMpO1xuICAgIH1cblxuICAgIChDdXN0b21FcnJvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEVycm9yLnByb3RvdHlwZSkpLmNvbnN0cnVjdG9yID0gQ3VzdG9tRXJyb3I7XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQ3VzdG9tRXJyb3IucHJvdG90eXBlLCBcIm5hbWVcIiwgeyBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbmFtZTsgfSB9KTtcblxuICAgIEN1c3RvbUVycm9yLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5uYW1lICsgXCI6IFwiICsgdGhpcy5tZXNzYWdlO1xuICAgIH07XG5cbiAgICByZXR1cm4gQ3VzdG9tRXJyb3I7XG59XG5cbnV0aWwubmV3RXJyb3IgPSBuZXdFcnJvcjtcblxuLyoqXG4gKiBDb25zdHJ1Y3RzIGEgbmV3IHByb3RvY29sIGVycm9yLlxuICogQGNsYXNzZGVzYyBFcnJvciBzdWJjbGFzcyBpbmRpY2F0aW5nIGEgcHJvdG9jb2wgc3BlY2lmYyBlcnJvci5cbiAqIEBtZW1iZXJvZiB1dGlsXG4gKiBAZXh0ZW5kcyBFcnJvclxuICogQHRlbXBsYXRlIFQgZXh0ZW5kcyBNZXNzYWdlPFQ+XG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIEVycm9yIG1lc3NhZ2VcbiAqIEBwYXJhbSB7T2JqZWN0LjxzdHJpbmcsKj59IFtwcm9wZXJ0aWVzXSBBZGRpdGlvbmFsIHByb3BlcnRpZXNcbiAqIEBleGFtcGxlXG4gKiB0cnkge1xuICogICAgIE15TWVzc2FnZS5kZWNvZGUoc29tZUJ1ZmZlcik7IC8vIHRocm93cyBpZiByZXF1aXJlZCBmaWVsZHMgYXJlIG1pc3NpbmdcbiAqIH0gY2F0Y2ggKGUpIHtcbiAqICAgICBpZiAoZSBpbnN0YW5jZW9mIFByb3RvY29sRXJyb3IgJiYgZS5pbnN0YW5jZSlcbiAqICAgICAgICAgY29uc29sZS5sb2coXCJkZWNvZGVkIHNvIGZhcjogXCIgKyBKU09OLnN0cmluZ2lmeShlLmluc3RhbmNlKSk7XG4gKiB9XG4gKi9cbnV0aWwuUHJvdG9jb2xFcnJvciA9IG5ld0Vycm9yKFwiUHJvdG9jb2xFcnJvclwiKTtcblxuLyoqXG4gKiBTbyBmYXIgZGVjb2RlZCBtZXNzYWdlIGluc3RhbmNlLlxuICogQG5hbWUgdXRpbC5Qcm90b2NvbEVycm9yI2luc3RhbmNlXG4gKiBAdHlwZSB7TWVzc2FnZTxUPn1cbiAqL1xuXG4vKipcbiAqIEEgT25lT2YgZ2V0dGVyIGFzIHJldHVybmVkIGJ5IHtAbGluayB1dGlsLm9uZU9mR2V0dGVyfS5cbiAqIEB0eXBlZGVmIE9uZU9mR2V0dGVyXG4gKiBAdHlwZSB7ZnVuY3Rpb259XG4gKiBAcmV0dXJucyB7c3RyaW5nfHVuZGVmaW5lZH0gU2V0IGZpZWxkIG5hbWUsIGlmIGFueVxuICovXG5cbi8qKlxuICogQnVpbGRzIGEgZ2V0dGVyIGZvciBhIG9uZW9mJ3MgcHJlc2VudCBmaWVsZCBuYW1lLlxuICogQHBhcmFtIHtzdHJpbmdbXX0gZmllbGROYW1lcyBGaWVsZCBuYW1lc1xuICogQHJldHVybnMge09uZU9mR2V0dGVyfSBVbmJvdW5kIGdldHRlclxuICovXG51dGlsLm9uZU9mR2V0dGVyID0gZnVuY3Rpb24gZ2V0T25lT2YoZmllbGROYW1lcykge1xuICAgIHZhciBmaWVsZE1hcCA9IHt9O1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmllbGROYW1lcy5sZW5ndGg7ICsraSlcbiAgICAgICAgZmllbGRNYXBbZmllbGROYW1lc1tpXV0gPSAxO1xuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMge3N0cmluZ3x1bmRlZmluZWR9IFNldCBmaWVsZCBuYW1lLCBpZiBhbnlcbiAgICAgKiBAdGhpcyBPYmplY3RcbiAgICAgKiBAaWdub3JlXG4gICAgICovXG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGNvbnNpc3RlbnQtcmV0dXJuXG4gICAgICAgIGZvciAodmFyIGtleXMgPSBPYmplY3Qua2V5cyh0aGlzKSwgaSA9IGtleXMubGVuZ3RoIC0gMTsgaSA+IC0xOyAtLWkpXG4gICAgICAgICAgICBpZiAoZmllbGRNYXBba2V5c1tpXV0gPT09IDEgJiYgdGhpc1trZXlzW2ldXSAhPT0gdW5kZWZpbmVkICYmIHRoaXNba2V5c1tpXV0gIT09IG51bGwpXG4gICAgICAgICAgICAgICAgcmV0dXJuIGtleXNbaV07XG4gICAgfTtcbn07XG5cbi8qKlxuICogQSBPbmVPZiBzZXR0ZXIgYXMgcmV0dXJuZWQgYnkge0BsaW5rIHV0aWwub25lT2ZTZXR0ZXJ9LlxuICogQHR5cGVkZWYgT25lT2ZTZXR0ZXJcbiAqIEB0eXBlIHtmdW5jdGlvbn1cbiAqIEBwYXJhbSB7c3RyaW5nfHVuZGVmaW5lZH0gdmFsdWUgRmllbGQgbmFtZVxuICogQHJldHVybnMge3VuZGVmaW5lZH1cbiAqL1xuXG4vKipcbiAqIEJ1aWxkcyBhIHNldHRlciBmb3IgYSBvbmVvZidzIHByZXNlbnQgZmllbGQgbmFtZS5cbiAqIEBwYXJhbSB7c3RyaW5nW119IGZpZWxkTmFtZXMgRmllbGQgbmFtZXNcbiAqIEByZXR1cm5zIHtPbmVPZlNldHRlcn0gVW5ib3VuZCBzZXR0ZXJcbiAqL1xudXRpbC5vbmVPZlNldHRlciA9IGZ1bmN0aW9uIHNldE9uZU9mKGZpZWxkTmFtZXMpIHtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIEZpZWxkIG5hbWVcbiAgICAgKiBAcmV0dXJucyB7dW5kZWZpbmVkfVxuICAgICAqIEB0aGlzIE9iamVjdFxuICAgICAqIEBpZ25vcmVcbiAgICAgKi9cbiAgICByZXR1cm4gZnVuY3Rpb24obmFtZSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGZpZWxkTmFtZXMubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICBpZiAoZmllbGROYW1lc1tpXSAhPT0gbmFtZSlcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpc1tmaWVsZE5hbWVzW2ldXTtcbiAgICB9O1xufTtcblxuLyoqXG4gKiBEZWZhdWx0IGNvbnZlcnNpb24gb3B0aW9ucyB1c2VkIGZvciB7QGxpbmsgTWVzc2FnZSN0b0pTT059IGltcGxlbWVudGF0aW9ucy5cbiAqXG4gKiBUaGVzZSBvcHRpb25zIGFyZSBjbG9zZSB0byBwcm90bzMncyBKU09OIG1hcHBpbmcgd2l0aCB0aGUgZXhjZXB0aW9uIHRoYXQgaW50ZXJuYWwgdHlwZXMgbGlrZSBBbnkgYXJlIGhhbmRsZWQganVzdCBsaWtlIG1lc3NhZ2VzLiBNb3JlIHByZWNpc2VseTpcbiAqXG4gKiAtIExvbmdzIGJlY29tZSBzdHJpbmdzXG4gKiAtIEVudW1zIGJlY29tZSBzdHJpbmcga2V5c1xuICogLSBCeXRlcyBiZWNvbWUgYmFzZTY0IGVuY29kZWQgc3RyaW5nc1xuICogLSAoU3ViLSlNZXNzYWdlcyBiZWNvbWUgcGxhaW4gb2JqZWN0c1xuICogLSBNYXBzIGJlY29tZSBwbGFpbiBvYmplY3RzIHdpdGggYWxsIHN0cmluZyBrZXlzXG4gKiAtIFJlcGVhdGVkIGZpZWxkcyBiZWNvbWUgYXJyYXlzXG4gKiAtIE5hTiBhbmQgSW5maW5pdHkgZm9yIGZsb2F0IGFuZCBkb3VibGUgZmllbGRzIGJlY29tZSBzdHJpbmdzXG4gKlxuICogQHR5cGUge0lDb252ZXJzaW9uT3B0aW9uc31cbiAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXJzLmdvb2dsZS5jb20vcHJvdG9jb2wtYnVmZmVycy9kb2NzL3Byb3RvMz9obD1lbiNqc29uXG4gKi9cbnV0aWwudG9KU09OT3B0aW9ucyA9IHtcbiAgICBsb25nczogU3RyaW5nLFxuICAgIGVudW1zOiBTdHJpbmcsXG4gICAgYnl0ZXM6IFN0cmluZyxcbiAgICBqc29uOiB0cnVlXG59O1xuXG4vLyBTZXRzIHVwIGJ1ZmZlciB1dGlsaXR5IGFjY29yZGluZyB0byB0aGUgZW52aXJvbm1lbnQgKGNhbGxlZCBpbiBpbmRleC1taW5pbWFsKVxudXRpbC5fY29uZmlndXJlID0gZnVuY3Rpb24oKSB7XG4gICAgdmFyIEJ1ZmZlciA9IHV0aWwuQnVmZmVyO1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBpZiAqL1xuICAgIGlmICghQnVmZmVyKSB7XG4gICAgICAgIHV0aWwuX0J1ZmZlcl9mcm9tID0gdXRpbC5fQnVmZmVyX2FsbG9jVW5zYWZlID0gbnVsbDtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyBiZWNhdXNlIG5vZGUgNC54IGJ1ZmZlcnMgYXJlIGluY29tcGF0aWJsZSAmIGltbXV0YWJsZVxuICAgIC8vIHNlZTogaHR0cHM6Ly9naXRodWIuY29tL2Rjb2RlSU8vcHJvdG9idWYuanMvcHVsbC82NjVcbiAgICB1dGlsLl9CdWZmZXJfZnJvbSA9IEJ1ZmZlci5mcm9tICE9PSBVaW50OEFycmF5LmZyb20gJiYgQnVmZmVyLmZyb20gfHxcbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgZnVuY3Rpb24gQnVmZmVyX2Zyb20odmFsdWUsIGVuY29kaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEJ1ZmZlcih2YWx1ZSwgZW5jb2RpbmcpO1xuICAgICAgICB9O1xuICAgIHV0aWwuX0J1ZmZlcl9hbGxvY1Vuc2FmZSA9IEJ1ZmZlci5hbGxvY1Vuc2FmZSB8fFxuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuICAgICAgICBmdW5jdGlvbiBCdWZmZXJfYWxsb2NVbnNhZmUoc2l6ZSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBCdWZmZXIoc2l6ZSk7XG4gICAgICAgIH07XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5tb2R1bGUuZXhwb3J0cyA9IFdyaXRlcjtcblxudmFyIHV0aWwgICAgICA9IHJlcXVpcmUoXCIuL3V0aWwvbWluaW1hbFwiKTtcblxudmFyIEJ1ZmZlcldyaXRlcjsgLy8gY3ljbGljXG5cbnZhciBMb25nQml0cyAgPSB1dGlsLkxvbmdCaXRzLFxuICAgIGJhc2U2NCAgICA9IHV0aWwuYmFzZTY0LFxuICAgIHV0ZjggICAgICA9IHV0aWwudXRmODtcblxuLyoqXG4gKiBDb25zdHJ1Y3RzIGEgbmV3IHdyaXRlciBvcGVyYXRpb24gaW5zdGFuY2UuXG4gKiBAY2xhc3NkZXNjIFNjaGVkdWxlZCB3cml0ZXIgb3BlcmF0aW9uLlxuICogQGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKCosIFVpbnQ4QXJyYXksIG51bWJlcil9IGZuIEZ1bmN0aW9uIHRvIGNhbGxcbiAqIEBwYXJhbSB7bnVtYmVyfSBsZW4gVmFsdWUgYnl0ZSBsZW5ndGhcbiAqIEBwYXJhbSB7Kn0gdmFsIFZhbHVlIHRvIHdyaXRlXG4gKiBAaWdub3JlXG4gKi9cbmZ1bmN0aW9uIE9wKGZuLCBsZW4sIHZhbCkge1xuXG4gICAgLyoqXG4gICAgICogRnVuY3Rpb24gdG8gY2FsbC5cbiAgICAgKiBAdHlwZSB7ZnVuY3Rpb24oVWludDhBcnJheSwgbnVtYmVyLCAqKX1cbiAgICAgKi9cbiAgICB0aGlzLmZuID0gZm47XG5cbiAgICAvKipcbiAgICAgKiBWYWx1ZSBieXRlIGxlbmd0aC5cbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgICAqL1xuICAgIHRoaXMubGVuID0gbGVuO1xuXG4gICAgLyoqXG4gICAgICogTmV4dCBvcGVyYXRpb24uXG4gICAgICogQHR5cGUge1dyaXRlci5PcHx1bmRlZmluZWR9XG4gICAgICovXG4gICAgdGhpcy5uZXh0ID0gdW5kZWZpbmVkO1xuXG4gICAgLyoqXG4gICAgICogVmFsdWUgdG8gd3JpdGUuXG4gICAgICogQHR5cGUgeyp9XG4gICAgICovXG4gICAgdGhpcy52YWwgPSB2YWw7IC8vIHR5cGUgdmFyaWVzXG59XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG5mdW5jdGlvbiBub29wKCkge30gLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1lbXB0eS1mdW5jdGlvblxuXG4vKipcbiAqIENvbnN0cnVjdHMgYSBuZXcgd3JpdGVyIHN0YXRlIGluc3RhbmNlLlxuICogQGNsYXNzZGVzYyBDb3BpZWQgd3JpdGVyIHN0YXRlLlxuICogQG1lbWJlcm9mIFdyaXRlclxuICogQGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge1dyaXRlcn0gd3JpdGVyIFdyaXRlciB0byBjb3B5IHN0YXRlIGZyb21cbiAqIEBpZ25vcmVcbiAqL1xuZnVuY3Rpb24gU3RhdGUod3JpdGVyKSB7XG5cbiAgICAvKipcbiAgICAgKiBDdXJyZW50IGhlYWQuXG4gICAgICogQHR5cGUge1dyaXRlci5PcH1cbiAgICAgKi9cbiAgICB0aGlzLmhlYWQgPSB3cml0ZXIuaGVhZDtcblxuICAgIC8qKlxuICAgICAqIEN1cnJlbnQgdGFpbC5cbiAgICAgKiBAdHlwZSB7V3JpdGVyLk9wfVxuICAgICAqL1xuICAgIHRoaXMudGFpbCA9IHdyaXRlci50YWlsO1xuXG4gICAgLyoqXG4gICAgICogQ3VycmVudCBidWZmZXIgbGVuZ3RoLlxuICAgICAqIEB0eXBlIHtudW1iZXJ9XG4gICAgICovXG4gICAgdGhpcy5sZW4gPSB3cml0ZXIubGVuO1xuXG4gICAgLyoqXG4gICAgICogTmV4dCBzdGF0ZS5cbiAgICAgKiBAdHlwZSB7U3RhdGV8bnVsbH1cbiAgICAgKi9cbiAgICB0aGlzLm5leHQgPSB3cml0ZXIuc3RhdGVzO1xufVxuXG4vKipcbiAqIENvbnN0cnVjdHMgYSBuZXcgd3JpdGVyIGluc3RhbmNlLlxuICogQGNsYXNzZGVzYyBXaXJlIGZvcm1hdCB3cml0ZXIgdXNpbmcgYFVpbnQ4QXJyYXlgIGlmIGF2YWlsYWJsZSwgb3RoZXJ3aXNlIGBBcnJheWAuXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZnVuY3Rpb24gV3JpdGVyKCkge1xuXG4gICAgLyoqXG4gICAgICogQ3VycmVudCBsZW5ndGguXG4gICAgICogQHR5cGUge251bWJlcn1cbiAgICAgKi9cbiAgICB0aGlzLmxlbiA9IDA7XG5cbiAgICAvKipcbiAgICAgKiBPcGVyYXRpb25zIGhlYWQuXG4gICAgICogQHR5cGUge09iamVjdH1cbiAgICAgKi9cbiAgICB0aGlzLmhlYWQgPSBuZXcgT3Aobm9vcCwgMCwgMCk7XG5cbiAgICAvKipcbiAgICAgKiBPcGVyYXRpb25zIHRhaWxcbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqL1xuICAgIHRoaXMudGFpbCA9IHRoaXMuaGVhZDtcblxuICAgIC8qKlxuICAgICAqIExpbmtlZCBmb3JrZWQgc3RhdGVzLlxuICAgICAqIEB0eXBlIHtPYmplY3R8bnVsbH1cbiAgICAgKi9cbiAgICB0aGlzLnN0YXRlcyA9IG51bGw7XG5cbiAgICAvLyBXaGVuIGEgdmFsdWUgaXMgd3JpdHRlbiwgdGhlIHdyaXRlciBjYWxjdWxhdGVzIGl0cyBieXRlIGxlbmd0aCBhbmQgcHV0cyBpdCBpbnRvIGEgbGlua2VkXG4gICAgLy8gbGlzdCBvZiBvcGVyYXRpb25zIHRvIHBlcmZvcm0gd2hlbiBmaW5pc2goKSBpcyBjYWxsZWQuIFRoaXMgYm90aCBhbGxvd3MgdXMgdG8gYWxsb2NhdGVcbiAgICAvLyBidWZmZXJzIG9mIHRoZSBleGFjdCByZXF1aXJlZCBzaXplIGFuZCByZWR1Y2VzIHRoZSBhbW91bnQgb2Ygd29yayB3ZSBoYXZlIHRvIGRvIGNvbXBhcmVkXG4gICAgLy8gdG8gZmlyc3QgY2FsY3VsYXRpbmcgb3ZlciBvYmplY3RzIGFuZCB0aGVuIGVuY29kaW5nIG92ZXIgb2JqZWN0cy4gSW4gb3VyIGNhc2UsIHRoZSBlbmNvZGluZ1xuICAgIC8vIHBhcnQgaXMganVzdCBhIGxpbmtlZCBsaXN0IHdhbGsgY2FsbGluZyBvcGVyYXRpb25zIHdpdGggYWxyZWFkeSBwcmVwYXJlZCB2YWx1ZXMuXG59XG5cbnZhciBjcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUoKSB7XG4gICAgcmV0dXJuIHV0aWwuQnVmZmVyXG4gICAgICAgID8gZnVuY3Rpb24gY3JlYXRlX2J1ZmZlcl9zZXR1cCgpIHtcbiAgICAgICAgICAgIHJldHVybiAoV3JpdGVyLmNyZWF0ZSA9IGZ1bmN0aW9uIGNyZWF0ZV9idWZmZXIoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBCdWZmZXJXcml0ZXIoKTtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH1cbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgOiBmdW5jdGlvbiBjcmVhdGVfYXJyYXkoKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFdyaXRlcigpO1xuICAgICAgICB9O1xufTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IHdyaXRlci5cbiAqIEBmdW5jdGlvblxuICogQHJldHVybnMge0J1ZmZlcldyaXRlcnxXcml0ZXJ9IEEge0BsaW5rIEJ1ZmZlcldyaXRlcn0gd2hlbiBCdWZmZXJzIGFyZSBzdXBwb3J0ZWQsIG90aGVyd2lzZSBhIHtAbGluayBXcml0ZXJ9XG4gKi9cbldyaXRlci5jcmVhdGUgPSBjcmVhdGUoKTtcblxuLyoqXG4gKiBBbGxvY2F0ZXMgYSBidWZmZXIgb2YgdGhlIHNwZWNpZmllZCBzaXplLlxuICogQHBhcmFtIHtudW1iZXJ9IHNpemUgQnVmZmVyIHNpemVcbiAqIEByZXR1cm5zIHtVaW50OEFycmF5fSBCdWZmZXJcbiAqL1xuV3JpdGVyLmFsbG9jID0gZnVuY3Rpb24gYWxsb2Moc2l6ZSkge1xuICAgIHJldHVybiBuZXcgdXRpbC5BcnJheShzaXplKTtcbn07XG5cbi8vIFVzZSBVaW50OEFycmF5IGJ1ZmZlciBwb29sIGluIHRoZSBicm93c2VyLCBqdXN0IGxpa2Ugbm9kZSBkb2VzIHdpdGggYnVmZmVyc1xuLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbmlmICh1dGlsLkFycmF5ICE9PSBBcnJheSlcbiAgICBXcml0ZXIuYWxsb2MgPSB1dGlsLnBvb2woV3JpdGVyLmFsbG9jLCB1dGlsLkFycmF5LnByb3RvdHlwZS5zdWJhcnJheSk7XG5cbi8qKlxuICogUHVzaGVzIGEgbmV3IG9wZXJhdGlvbiB0byB0aGUgcXVldWUuXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKFVpbnQ4QXJyYXksIG51bWJlciwgKil9IGZuIEZ1bmN0aW9uIHRvIGNhbGxcbiAqIEBwYXJhbSB7bnVtYmVyfSBsZW4gVmFsdWUgYnl0ZSBsZW5ndGhcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWwgVmFsdWUgdG8gd3JpdGVcbiAqIEByZXR1cm5zIHtXcml0ZXJ9IGB0aGlzYFxuICogQHByaXZhdGVcbiAqL1xuV3JpdGVyLnByb3RvdHlwZS5fcHVzaCA9IGZ1bmN0aW9uIHB1c2goZm4sIGxlbiwgdmFsKSB7XG4gICAgdGhpcy50YWlsID0gdGhpcy50YWlsLm5leHQgPSBuZXcgT3AoZm4sIGxlbiwgdmFsKTtcbiAgICB0aGlzLmxlbiArPSBsZW47XG4gICAgcmV0dXJuIHRoaXM7XG59O1xuXG5mdW5jdGlvbiB3cml0ZUJ5dGUodmFsLCBidWYsIHBvcykge1xuICAgIGJ1Zltwb3NdID0gdmFsICYgMjU1O1xufVxuXG5mdW5jdGlvbiB3cml0ZVZhcmludDMyKHZhbCwgYnVmLCBwb3MpIHtcbiAgICB3aGlsZSAodmFsID4gMTI3KSB7XG4gICAgICAgIGJ1Zltwb3MrK10gPSB2YWwgJiAxMjcgfCAxMjg7XG4gICAgICAgIHZhbCA+Pj49IDc7XG4gICAgfVxuICAgIGJ1Zltwb3NdID0gdmFsO1xufVxuXG4vKipcbiAqIENvbnN0cnVjdHMgYSBuZXcgdmFyaW50IHdyaXRlciBvcGVyYXRpb24gaW5zdGFuY2UuXG4gKiBAY2xhc3NkZXNjIFNjaGVkdWxlZCB2YXJpbnQgd3JpdGVyIG9wZXJhdGlvbi5cbiAqIEBleHRlbmRzIE9wXG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7bnVtYmVyfSBsZW4gVmFsdWUgYnl0ZSBsZW5ndGhcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWwgVmFsdWUgdG8gd3JpdGVcbiAqIEBpZ25vcmVcbiAqL1xuZnVuY3Rpb24gVmFyaW50T3AobGVuLCB2YWwpIHtcbiAgICB0aGlzLmxlbiA9IGxlbjtcbiAgICB0aGlzLm5leHQgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy52YWwgPSB2YWw7XG59XG5cblZhcmludE9wLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoT3AucHJvdG90eXBlKTtcblZhcmludE9wLnByb3RvdHlwZS5mbiA9IHdyaXRlVmFyaW50MzI7XG5cbi8qKlxuICogV3JpdGVzIGFuIHVuc2lnbmVkIDMyIGJpdCB2YWx1ZSBhcyBhIHZhcmludC5cbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxuICogQHJldHVybnMge1dyaXRlcn0gYHRoaXNgXG4gKi9cbldyaXRlci5wcm90b3R5cGUudWludDMyID0gZnVuY3Rpb24gd3JpdGVfdWludDMyKHZhbHVlKSB7XG4gICAgLy8gaGVyZSwgdGhlIGNhbGwgdG8gdGhpcy5wdXNoIGhhcyBiZWVuIGlubGluZWQgYW5kIGEgdmFyaW50IHNwZWNpZmljIE9wIHN1YmNsYXNzIGlzIHVzZWQuXG4gICAgLy8gdWludDMyIGlzIGJ5IGZhciB0aGUgbW9zdCBmcmVxdWVudGx5IHVzZWQgb3BlcmF0aW9uIGFuZCBiZW5lZml0cyBzaWduaWZpY2FudGx5IGZyb20gdGhpcy5cbiAgICB0aGlzLmxlbiArPSAodGhpcy50YWlsID0gdGhpcy50YWlsLm5leHQgPSBuZXcgVmFyaW50T3AoXG4gICAgICAgICh2YWx1ZSA9IHZhbHVlID4+PiAwKVxuICAgICAgICAgICAgICAgIDwgMTI4ICAgICAgID8gMVxuICAgICAgICA6IHZhbHVlIDwgMTYzODQgICAgID8gMlxuICAgICAgICA6IHZhbHVlIDwgMjA5NzE1MiAgID8gM1xuICAgICAgICA6IHZhbHVlIDwgMjY4NDM1NDU2ID8gNFxuICAgICAgICA6ICAgICAgICAgICAgICAgICAgICAgNSxcbiAgICB2YWx1ZSkpLmxlbjtcbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogV3JpdGVzIGEgc2lnbmVkIDMyIGJpdCB2YWx1ZSBhcyBhIHZhcmludC5cbiAqIEBmdW5jdGlvblxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXG4gKiBAcmV0dXJucyB7V3JpdGVyfSBgdGhpc2BcbiAqL1xuV3JpdGVyLnByb3RvdHlwZS5pbnQzMiA9IGZ1bmN0aW9uIHdyaXRlX2ludDMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlIDwgMFxuICAgICAgICA/IHRoaXMuX3B1c2god3JpdGVWYXJpbnQ2NCwgMTAsIExvbmdCaXRzLmZyb21OdW1iZXIodmFsdWUpKSAvLyAxMCBieXRlcyBwZXIgc3BlY1xuICAgICAgICA6IHRoaXMudWludDMyKHZhbHVlKTtcbn07XG5cbi8qKlxuICogV3JpdGVzIGEgMzIgYml0IHZhbHVlIGFzIGEgdmFyaW50LCB6aWctemFnIGVuY29kZWQuXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWUgdG8gd3JpdGVcbiAqIEByZXR1cm5zIHtXcml0ZXJ9IGB0aGlzYFxuICovXG5Xcml0ZXIucHJvdG90eXBlLnNpbnQzMiA9IGZ1bmN0aW9uIHdyaXRlX3NpbnQzMih2YWx1ZSkge1xuICAgIHJldHVybiB0aGlzLnVpbnQzMigodmFsdWUgPDwgMSBeIHZhbHVlID4+IDMxKSA+Pj4gMCk7XG59O1xuXG5mdW5jdGlvbiB3cml0ZVZhcmludDY0KHZhbCwgYnVmLCBwb3MpIHtcbiAgICB3aGlsZSAodmFsLmhpKSB7XG4gICAgICAgIGJ1Zltwb3MrK10gPSB2YWwubG8gJiAxMjcgfCAxMjg7XG4gICAgICAgIHZhbC5sbyA9ICh2YWwubG8gPj4+IDcgfCB2YWwuaGkgPDwgMjUpID4+PiAwO1xuICAgICAgICB2YWwuaGkgPj4+PSA3O1xuICAgIH1cbiAgICB3aGlsZSAodmFsLmxvID4gMTI3KSB7XG4gICAgICAgIGJ1Zltwb3MrK10gPSB2YWwubG8gJiAxMjcgfCAxMjg7XG4gICAgICAgIHZhbC5sbyA9IHZhbC5sbyA+Pj4gNztcbiAgICB9XG4gICAgYnVmW3BvcysrXSA9IHZhbC5sbztcbn1cblxuLyoqXG4gKiBXcml0ZXMgYW4gdW5zaWduZWQgNjQgYml0IHZhbHVlIGFzIGEgdmFyaW50LlxuICogQHBhcmFtIHtMb25nfG51bWJlcnxzdHJpbmd9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXG4gKiBAcmV0dXJucyB7V3JpdGVyfSBgdGhpc2BcbiAqIEB0aHJvd3Mge1R5cGVFcnJvcn0gSWYgYHZhbHVlYCBpcyBhIHN0cmluZyBhbmQgbm8gbG9uZyBsaWJyYXJ5IGlzIHByZXNlbnQuXG4gKi9cbldyaXRlci5wcm90b3R5cGUudWludDY0ID0gZnVuY3Rpb24gd3JpdGVfdWludDY0KHZhbHVlKSB7XG4gICAgdmFyIGJpdHMgPSBMb25nQml0cy5mcm9tKHZhbHVlKTtcbiAgICByZXR1cm4gdGhpcy5fcHVzaCh3cml0ZVZhcmludDY0LCBiaXRzLmxlbmd0aCgpLCBiaXRzKTtcbn07XG5cbi8qKlxuICogV3JpdGVzIGEgc2lnbmVkIDY0IGJpdCB2YWx1ZSBhcyBhIHZhcmludC5cbiAqIEBmdW5jdGlvblxuICogQHBhcmFtIHtMb25nfG51bWJlcnxzdHJpbmd9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXG4gKiBAcmV0dXJucyB7V3JpdGVyfSBgdGhpc2BcbiAqIEB0aHJvd3Mge1R5cGVFcnJvcn0gSWYgYHZhbHVlYCBpcyBhIHN0cmluZyBhbmQgbm8gbG9uZyBsaWJyYXJ5IGlzIHByZXNlbnQuXG4gKi9cbldyaXRlci5wcm90b3R5cGUuaW50NjQgPSBXcml0ZXIucHJvdG90eXBlLnVpbnQ2NDtcblxuLyoqXG4gKiBXcml0ZXMgYSBzaWduZWQgNjQgYml0IHZhbHVlIGFzIGEgdmFyaW50LCB6aWctemFnIGVuY29kZWQuXG4gKiBAcGFyYW0ge0xvbmd8bnVtYmVyfHN0cmluZ30gdmFsdWUgVmFsdWUgdG8gd3JpdGVcbiAqIEByZXR1cm5zIHtXcml0ZXJ9IGB0aGlzYFxuICogQHRocm93cyB7VHlwZUVycm9yfSBJZiBgdmFsdWVgIGlzIGEgc3RyaW5nIGFuZCBubyBsb25nIGxpYnJhcnkgaXMgcHJlc2VudC5cbiAqL1xuV3JpdGVyLnByb3RvdHlwZS5zaW50NjQgPSBmdW5jdGlvbiB3cml0ZV9zaW50NjQodmFsdWUpIHtcbiAgICB2YXIgYml0cyA9IExvbmdCaXRzLmZyb20odmFsdWUpLnp6RW5jb2RlKCk7XG4gICAgcmV0dXJuIHRoaXMuX3B1c2god3JpdGVWYXJpbnQ2NCwgYml0cy5sZW5ndGgoKSwgYml0cyk7XG59O1xuXG4vKipcbiAqIFdyaXRlcyBhIGJvb2xpc2ggdmFsdWUgYXMgYSB2YXJpbnQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IHZhbHVlIFZhbHVlIHRvIHdyaXRlXG4gKiBAcmV0dXJucyB7V3JpdGVyfSBgdGhpc2BcbiAqL1xuV3JpdGVyLnByb3RvdHlwZS5ib29sID0gZnVuY3Rpb24gd3JpdGVfYm9vbCh2YWx1ZSkge1xuICAgIHJldHVybiB0aGlzLl9wdXNoKHdyaXRlQnl0ZSwgMSwgdmFsdWUgPyAxIDogMCk7XG59O1xuXG5mdW5jdGlvbiB3cml0ZUZpeGVkMzIodmFsLCBidWYsIHBvcykge1xuICAgIGJ1Zltwb3MgICAgXSA9ICB2YWwgICAgICAgICAmIDI1NTtcbiAgICBidWZbcG9zICsgMV0gPSAgdmFsID4+PiA4ICAgJiAyNTU7XG4gICAgYnVmW3BvcyArIDJdID0gIHZhbCA+Pj4gMTYgICYgMjU1O1xuICAgIGJ1Zltwb3MgKyAzXSA9ICB2YWwgPj4+IDI0O1xufVxuXG4vKipcbiAqIFdyaXRlcyBhbiB1bnNpZ25lZCAzMiBiaXQgdmFsdWUgYXMgZml4ZWQgMzIgYml0cy5cbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxuICogQHJldHVybnMge1dyaXRlcn0gYHRoaXNgXG4gKi9cbldyaXRlci5wcm90b3R5cGUuZml4ZWQzMiA9IGZ1bmN0aW9uIHdyaXRlX2ZpeGVkMzIodmFsdWUpIHtcbiAgICByZXR1cm4gdGhpcy5fcHVzaCh3cml0ZUZpeGVkMzIsIDQsIHZhbHVlID4+PiAwKTtcbn07XG5cbi8qKlxuICogV3JpdGVzIGEgc2lnbmVkIDMyIGJpdCB2YWx1ZSBhcyBmaXhlZCAzMiBiaXRzLlxuICogQGZ1bmN0aW9uXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWUgdG8gd3JpdGVcbiAqIEByZXR1cm5zIHtXcml0ZXJ9IGB0aGlzYFxuICovXG5Xcml0ZXIucHJvdG90eXBlLnNmaXhlZDMyID0gV3JpdGVyLnByb3RvdHlwZS5maXhlZDMyO1xuXG4vKipcbiAqIFdyaXRlcyBhbiB1bnNpZ25lZCA2NCBiaXQgdmFsdWUgYXMgZml4ZWQgNjQgYml0cy5cbiAqIEBwYXJhbSB7TG9uZ3xudW1iZXJ8c3RyaW5nfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxuICogQHJldHVybnMge1dyaXRlcn0gYHRoaXNgXG4gKiBAdGhyb3dzIHtUeXBlRXJyb3J9IElmIGB2YWx1ZWAgaXMgYSBzdHJpbmcgYW5kIG5vIGxvbmcgbGlicmFyeSBpcyBwcmVzZW50LlxuICovXG5Xcml0ZXIucHJvdG90eXBlLmZpeGVkNjQgPSBmdW5jdGlvbiB3cml0ZV9maXhlZDY0KHZhbHVlKSB7XG4gICAgdmFyIGJpdHMgPSBMb25nQml0cy5mcm9tKHZhbHVlKTtcbiAgICByZXR1cm4gdGhpcy5fcHVzaCh3cml0ZUZpeGVkMzIsIDQsIGJpdHMubG8pLl9wdXNoKHdyaXRlRml4ZWQzMiwgNCwgYml0cy5oaSk7XG59O1xuXG4vKipcbiAqIFdyaXRlcyBhIHNpZ25lZCA2NCBiaXQgdmFsdWUgYXMgZml4ZWQgNjQgYml0cy5cbiAqIEBmdW5jdGlvblxuICogQHBhcmFtIHtMb25nfG51bWJlcnxzdHJpbmd9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXG4gKiBAcmV0dXJucyB7V3JpdGVyfSBgdGhpc2BcbiAqIEB0aHJvd3Mge1R5cGVFcnJvcn0gSWYgYHZhbHVlYCBpcyBhIHN0cmluZyBhbmQgbm8gbG9uZyBsaWJyYXJ5IGlzIHByZXNlbnQuXG4gKi9cbldyaXRlci5wcm90b3R5cGUuc2ZpeGVkNjQgPSBXcml0ZXIucHJvdG90eXBlLmZpeGVkNjQ7XG5cbi8qKlxuICogV3JpdGVzIGEgZmxvYXQgKDMyIGJpdCkuXG4gKiBAZnVuY3Rpb25cbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxuICogQHJldHVybnMge1dyaXRlcn0gYHRoaXNgXG4gKi9cbldyaXRlci5wcm90b3R5cGUuZmxvYXQgPSBmdW5jdGlvbiB3cml0ZV9mbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiB0aGlzLl9wdXNoKHV0aWwuZmxvYXQud3JpdGVGbG9hdExFLCA0LCB2YWx1ZSk7XG59O1xuXG4vKipcbiAqIFdyaXRlcyBhIGRvdWJsZSAoNjQgYml0IGZsb2F0KS5cbiAqIEBmdW5jdGlvblxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXG4gKiBAcmV0dXJucyB7V3JpdGVyfSBgdGhpc2BcbiAqL1xuV3JpdGVyLnByb3RvdHlwZS5kb3VibGUgPSBmdW5jdGlvbiB3cml0ZV9kb3VibGUodmFsdWUpIHtcbiAgICByZXR1cm4gdGhpcy5fcHVzaCh1dGlsLmZsb2F0LndyaXRlRG91YmxlTEUsIDgsIHZhbHVlKTtcbn07XG5cbnZhciB3cml0ZUJ5dGVzID0gdXRpbC5BcnJheS5wcm90b3R5cGUuc2V0XG4gICAgPyBmdW5jdGlvbiB3cml0ZUJ5dGVzX3NldCh2YWwsIGJ1ZiwgcG9zKSB7XG4gICAgICAgIGJ1Zi5zZXQodmFsLCBwb3MpOyAvLyBhbHNvIHdvcmtzIGZvciBwbGFpbiBhcnJheSB2YWx1ZXNcbiAgICB9XG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICA6IGZ1bmN0aW9uIHdyaXRlQnl0ZXNfZm9yKHZhbCwgYnVmLCBwb3MpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2YWwubGVuZ3RoOyArK2kpXG4gICAgICAgICAgICBidWZbcG9zICsgaV0gPSB2YWxbaV07XG4gICAgfTtcblxuLyoqXG4gKiBXcml0ZXMgYSBzZXF1ZW5jZSBvZiBieXRlcy5cbiAqIEBwYXJhbSB7VWludDhBcnJheXxzdHJpbmd9IHZhbHVlIEJ1ZmZlciBvciBiYXNlNjQgZW5jb2RlZCBzdHJpbmcgdG8gd3JpdGVcbiAqIEByZXR1cm5zIHtXcml0ZXJ9IGB0aGlzYFxuICovXG5Xcml0ZXIucHJvdG90eXBlLmJ5dGVzID0gZnVuY3Rpb24gd3JpdGVfYnl0ZXModmFsdWUpIHtcbiAgICB2YXIgbGVuID0gdmFsdWUubGVuZ3RoID4+PiAwO1xuICAgIGlmICghbGVuKVxuICAgICAgICByZXR1cm4gdGhpcy5fcHVzaCh3cml0ZUJ5dGUsIDEsIDApO1xuICAgIGlmICh1dGlsLmlzU3RyaW5nKHZhbHVlKSkge1xuICAgICAgICB2YXIgYnVmID0gV3JpdGVyLmFsbG9jKGxlbiA9IGJhc2U2NC5sZW5ndGgodmFsdWUpKTtcbiAgICAgICAgYmFzZTY0LmRlY29kZSh2YWx1ZSwgYnVmLCAwKTtcbiAgICAgICAgdmFsdWUgPSBidWY7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnVpbnQzMihsZW4pLl9wdXNoKHdyaXRlQnl0ZXMsIGxlbiwgdmFsdWUpO1xufTtcblxuLyoqXG4gKiBXcml0ZXMgYSBzdHJpbmcuXG4gKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgVmFsdWUgdG8gd3JpdGVcbiAqIEByZXR1cm5zIHtXcml0ZXJ9IGB0aGlzYFxuICovXG5Xcml0ZXIucHJvdG90eXBlLnN0cmluZyA9IGZ1bmN0aW9uIHdyaXRlX3N0cmluZyh2YWx1ZSkge1xuICAgIHZhciBsZW4gPSB1dGY4Lmxlbmd0aCh2YWx1ZSk7XG4gICAgcmV0dXJuIGxlblxuICAgICAgICA/IHRoaXMudWludDMyKGxlbikuX3B1c2godXRmOC53cml0ZSwgbGVuLCB2YWx1ZSlcbiAgICAgICAgOiB0aGlzLl9wdXNoKHdyaXRlQnl0ZSwgMSwgMCk7XG59O1xuXG4vKipcbiAqIEZvcmtzIHRoaXMgd3JpdGVyJ3Mgc3RhdGUgYnkgcHVzaGluZyBpdCB0byBhIHN0YWNrLlxuICogQ2FsbGluZyB7QGxpbmsgV3JpdGVyI3Jlc2V0fHJlc2V0fSBvciB7QGxpbmsgV3JpdGVyI2xkZWxpbXxsZGVsaW19IHJlc2V0cyB0aGUgd3JpdGVyIHRvIHRoZSBwcmV2aW91cyBzdGF0ZS5cbiAqIEByZXR1cm5zIHtXcml0ZXJ9IGB0aGlzYFxuICovXG5Xcml0ZXIucHJvdG90eXBlLmZvcmsgPSBmdW5jdGlvbiBmb3JrKCkge1xuICAgIHRoaXMuc3RhdGVzID0gbmV3IFN0YXRlKHRoaXMpO1xuICAgIHRoaXMuaGVhZCA9IHRoaXMudGFpbCA9IG5ldyBPcChub29wLCAwLCAwKTtcbiAgICB0aGlzLmxlbiA9IDA7XG4gICAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFJlc2V0cyB0aGlzIGluc3RhbmNlIHRvIHRoZSBsYXN0IHN0YXRlLlxuICogQHJldHVybnMge1dyaXRlcn0gYHRoaXNgXG4gKi9cbldyaXRlci5wcm90b3R5cGUucmVzZXQgPSBmdW5jdGlvbiByZXNldCgpIHtcbiAgICBpZiAodGhpcy5zdGF0ZXMpIHtcbiAgICAgICAgdGhpcy5oZWFkICAgPSB0aGlzLnN0YXRlcy5oZWFkO1xuICAgICAgICB0aGlzLnRhaWwgICA9IHRoaXMuc3RhdGVzLnRhaWw7XG4gICAgICAgIHRoaXMubGVuICAgID0gdGhpcy5zdGF0ZXMubGVuO1xuICAgICAgICB0aGlzLnN0YXRlcyA9IHRoaXMuc3RhdGVzLm5leHQ7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5oZWFkID0gdGhpcy50YWlsID0gbmV3IE9wKG5vb3AsIDAsIDApO1xuICAgICAgICB0aGlzLmxlbiAgPSAwO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogUmVzZXRzIHRvIHRoZSBsYXN0IHN0YXRlIGFuZCBhcHBlbmRzIHRoZSBmb3JrIHN0YXRlJ3MgY3VycmVudCB3cml0ZSBsZW5ndGggYXMgYSB2YXJpbnQgZm9sbG93ZWQgYnkgaXRzIG9wZXJhdGlvbnMuXG4gKiBAcmV0dXJucyB7V3JpdGVyfSBgdGhpc2BcbiAqL1xuV3JpdGVyLnByb3RvdHlwZS5sZGVsaW0gPSBmdW5jdGlvbiBsZGVsaW0oKSB7XG4gICAgdmFyIGhlYWQgPSB0aGlzLmhlYWQsXG4gICAgICAgIHRhaWwgPSB0aGlzLnRhaWwsXG4gICAgICAgIGxlbiAgPSB0aGlzLmxlbjtcbiAgICB0aGlzLnJlc2V0KCkudWludDMyKGxlbik7XG4gICAgaWYgKGxlbikge1xuICAgICAgICB0aGlzLnRhaWwubmV4dCA9IGhlYWQubmV4dDsgLy8gc2tpcCBub29wXG4gICAgICAgIHRoaXMudGFpbCA9IHRhaWw7XG4gICAgICAgIHRoaXMubGVuICs9IGxlbjtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIEZpbmlzaGVzIHRoZSB3cml0ZSBvcGVyYXRpb24uXG4gKiBAcmV0dXJucyB7VWludDhBcnJheX0gRmluaXNoZWQgYnVmZmVyXG4gKi9cbldyaXRlci5wcm90b3R5cGUuZmluaXNoID0gZnVuY3Rpb24gZmluaXNoKCkge1xuICAgIHZhciBoZWFkID0gdGhpcy5oZWFkLm5leHQsIC8vIHNraXAgbm9vcFxuICAgICAgICBidWYgID0gdGhpcy5jb25zdHJ1Y3Rvci5hbGxvYyh0aGlzLmxlbiksXG4gICAgICAgIHBvcyAgPSAwO1xuICAgIHdoaWxlIChoZWFkKSB7XG4gICAgICAgIGhlYWQuZm4oaGVhZC52YWwsIGJ1ZiwgcG9zKTtcbiAgICAgICAgcG9zICs9IGhlYWQubGVuO1xuICAgICAgICBoZWFkID0gaGVhZC5uZXh0O1xuICAgIH1cbiAgICAvLyB0aGlzLmhlYWQgPSB0aGlzLnRhaWwgPSBudWxsO1xuICAgIHJldHVybiBidWY7XG59O1xuXG5Xcml0ZXIuX2NvbmZpZ3VyZSA9IGZ1bmN0aW9uKEJ1ZmZlcldyaXRlcl8pIHtcbiAgICBCdWZmZXJXcml0ZXIgPSBCdWZmZXJXcml0ZXJfO1xuICAgIFdyaXRlci5jcmVhdGUgPSBjcmVhdGUoKTtcbiAgICBCdWZmZXJXcml0ZXIuX2NvbmZpZ3VyZSgpO1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xubW9kdWxlLmV4cG9ydHMgPSBCdWZmZXJXcml0ZXI7XG5cbi8vIGV4dGVuZHMgV3JpdGVyXG52YXIgV3JpdGVyID0gcmVxdWlyZShcIi4vd3JpdGVyXCIpO1xuKEJ1ZmZlcldyaXRlci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKFdyaXRlci5wcm90b3R5cGUpKS5jb25zdHJ1Y3RvciA9IEJ1ZmZlcldyaXRlcjtcblxudmFyIHV0aWwgPSByZXF1aXJlKFwiLi91dGlsL21pbmltYWxcIik7XG5cbi8qKlxuICogQ29uc3RydWN0cyBhIG5ldyBidWZmZXIgd3JpdGVyIGluc3RhbmNlLlxuICogQGNsYXNzZGVzYyBXaXJlIGZvcm1hdCB3cml0ZXIgdXNpbmcgbm9kZSBidWZmZXJzLlxuICogQGV4dGVuZHMgV3JpdGVyXG4gKiBAY29uc3RydWN0b3JcbiAqL1xuZnVuY3Rpb24gQnVmZmVyV3JpdGVyKCkge1xuICAgIFdyaXRlci5jYWxsKHRoaXMpO1xufVxuXG5CdWZmZXJXcml0ZXIuX2NvbmZpZ3VyZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAvKipcbiAgICAgKiBBbGxvY2F0ZXMgYSBidWZmZXIgb2YgdGhlIHNwZWNpZmllZCBzaXplLlxuICAgICAqIEBmdW5jdGlvblxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzaXplIEJ1ZmZlciBzaXplXG4gICAgICogQHJldHVybnMge0J1ZmZlcn0gQnVmZmVyXG4gICAgICovXG4gICAgQnVmZmVyV3JpdGVyLmFsbG9jID0gdXRpbC5fQnVmZmVyX2FsbG9jVW5zYWZlO1xuXG4gICAgQnVmZmVyV3JpdGVyLndyaXRlQnl0ZXNCdWZmZXIgPSB1dGlsLkJ1ZmZlciAmJiB1dGlsLkJ1ZmZlci5wcm90b3R5cGUgaW5zdGFuY2VvZiBVaW50OEFycmF5ICYmIHV0aWwuQnVmZmVyLnByb3RvdHlwZS5zZXQubmFtZSA9PT0gXCJzZXRcIlxuICAgICAgICA/IGZ1bmN0aW9uIHdyaXRlQnl0ZXNCdWZmZXJfc2V0KHZhbCwgYnVmLCBwb3MpIHtcbiAgICAgICAgICBidWYuc2V0KHZhbCwgcG9zKTsgLy8gZmFzdGVyIHRoYW4gY29weSAocmVxdWlyZXMgbm9kZSA+PSA0IHdoZXJlIEJ1ZmZlcnMgZXh0ZW5kIFVpbnQ4QXJyYXkgYW5kIHNldCBpcyBwcm9wZXJseSBpbmhlcml0ZWQpXG4gICAgICAgICAgLy8gYWxzbyB3b3JrcyBmb3IgcGxhaW4gYXJyYXkgdmFsdWVzXG4gICAgICAgIH1cbiAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICAgICAgOiBmdW5jdGlvbiB3cml0ZUJ5dGVzQnVmZmVyX2NvcHkodmFsLCBidWYsIHBvcykge1xuICAgICAgICAgIGlmICh2YWwuY29weSkgLy8gQnVmZmVyIHZhbHVlc1xuICAgICAgICAgICAgdmFsLmNvcHkoYnVmLCBwb3MsIDAsIHZhbC5sZW5ndGgpO1xuICAgICAgICAgIGVsc2UgZm9yICh2YXIgaSA9IDA7IGkgPCB2YWwubGVuZ3RoOykgLy8gcGxhaW4gYXJyYXkgdmFsdWVzXG4gICAgICAgICAgICBidWZbcG9zKytdID0gdmFsW2krK107XG4gICAgICAgIH07XG59O1xuXG5cbi8qKlxuICogQG92ZXJyaWRlXG4gKi9cbkJ1ZmZlcldyaXRlci5wcm90b3R5cGUuYnl0ZXMgPSBmdW5jdGlvbiB3cml0ZV9ieXRlc19idWZmZXIodmFsdWUpIHtcbiAgICBpZiAodXRpbC5pc1N0cmluZyh2YWx1ZSkpXG4gICAgICAgIHZhbHVlID0gdXRpbC5fQnVmZmVyX2Zyb20odmFsdWUsIFwiYmFzZTY0XCIpO1xuICAgIHZhciBsZW4gPSB2YWx1ZS5sZW5ndGggPj4+IDA7XG4gICAgdGhpcy51aW50MzIobGVuKTtcbiAgICBpZiAobGVuKVxuICAgICAgICB0aGlzLl9wdXNoKEJ1ZmZlcldyaXRlci53cml0ZUJ5dGVzQnVmZmVyLCBsZW4sIHZhbHVlKTtcbiAgICByZXR1cm4gdGhpcztcbn07XG5cbmZ1bmN0aW9uIHdyaXRlU3RyaW5nQnVmZmVyKHZhbCwgYnVmLCBwb3MpIHtcbiAgICBpZiAodmFsLmxlbmd0aCA8IDQwKSAvLyBwbGFpbiBqcyBpcyBmYXN0ZXIgZm9yIHNob3J0IHN0cmluZ3MgKHByb2JhYmx5IGR1ZSB0byByZWR1bmRhbnQgYXNzZXJ0aW9ucylcbiAgICAgICAgdXRpbC51dGY4LndyaXRlKHZhbCwgYnVmLCBwb3MpO1xuICAgIGVsc2UgaWYgKGJ1Zi51dGY4V3JpdGUpXG4gICAgICAgIGJ1Zi51dGY4V3JpdGUodmFsLCBwb3MpO1xuICAgIGVsc2VcbiAgICAgICAgYnVmLndyaXRlKHZhbCwgcG9zKTtcbn1cblxuLyoqXG4gKiBAb3ZlcnJpZGVcbiAqL1xuQnVmZmVyV3JpdGVyLnByb3RvdHlwZS5zdHJpbmcgPSBmdW5jdGlvbiB3cml0ZV9zdHJpbmdfYnVmZmVyKHZhbHVlKSB7XG4gICAgdmFyIGxlbiA9IHV0aWwuQnVmZmVyLmJ5dGVMZW5ndGgodmFsdWUpO1xuICAgIHRoaXMudWludDMyKGxlbik7XG4gICAgaWYgKGxlbilcbiAgICAgICAgdGhpcy5fcHVzaCh3cml0ZVN0cmluZ0J1ZmZlciwgbGVuLCB2YWx1ZSk7XG4gICAgcmV0dXJuIHRoaXM7XG59O1xuXG5cbi8qKlxuICogRmluaXNoZXMgdGhlIHdyaXRlIG9wZXJhdGlvbi5cbiAqIEBuYW1lIEJ1ZmZlcldyaXRlciNmaW5pc2hcbiAqIEBmdW5jdGlvblxuICogQHJldHVybnMge0J1ZmZlcn0gRmluaXNoZWQgYnVmZmVyXG4gKi9cblxuQnVmZmVyV3JpdGVyLl9jb25maWd1cmUoKTtcbiIsIi8qIChpZ25vcmVkKSAqLyIsIi8qIChpZ25vcmVkKSAqLyIsIi8qIChpZ25vcmVkKSAqLyIsIi8qIChpZ25vcmVkKSAqLyIsIi8qIChpZ25vcmVkKSAqLyIsIi8qIChpZ25vcmVkKSAqLyIsIi8qIChpZ25vcmVkKSAqLyIsIi8qIChpZ25vcmVkKSAqLyIsIi8qIChpZ25vcmVkKSAqLyIsIi8qIChpZ25vcmVkKSAqLyIsIi8qIChpZ25vcmVkKSAqLyIsIi8qIChpZ25vcmVkKSAqLyIsIi8vLyBAZmlsZVxuLy8vIEBhZGR0b2dyb3VwIGZsYXRidWZmZXJzX2phdmFzY3JpcHRfYXBpXG4vLy8gQHtcbi8vLyBAY29uZCBGTEFUQlVGRkVSU19JTlRFUk5BTFxuXG4vKipcbiAqIEBmaWxlb3ZlcnZpZXdcbiAqXG4gKiBOZWVkIHRvIHN1cHByZXNzICdnbG9iYWwgdGhpcycgZXJyb3Igc28gdGhlIE5vZGUuanMgZXhwb3J0IGxpbmUgZG9lc24ndCBjYXVzZVxuICogY2xvc3VyZSBjb21waWxlIHRvIGVycm9yIG91dC5cbiAqIEBzdXBwcmVzcyB7Z2xvYmFsVGhpc31cbiAqL1xuXG4vKipcbiAqIEBjb25zdFxuICogQG5hbWVzcGFjZVxuICovXG52YXIgZmxhdGJ1ZmZlcnMgPSB7fTtcblxuLyoqXG4gKiBAdHlwZWRlZiB7bnVtYmVyfVxuICovXG5mbGF0YnVmZmVycy5PZmZzZXQ7XG5cbi8qKlxuICogQHR5cGVkZWYge3tcbiAqICAgYmI6IGZsYXRidWZmZXJzLkJ5dGVCdWZmZXIsXG4gKiAgIGJiX3BvczogbnVtYmVyXG4gKiB9fVxuICovXG5mbGF0YnVmZmVycy5UYWJsZTtcblxuLyoqXG4gKiBAdHlwZSB7bnVtYmVyfVxuICogQGNvbnN0XG4gKi9cbmZsYXRidWZmZXJzLlNJWkVPRl9TSE9SVCA9IDI7XG5cbi8qKlxuICogQHR5cGUge251bWJlcn1cbiAqIEBjb25zdFxuICovXG5mbGF0YnVmZmVycy5TSVpFT0ZfSU5UID0gNDtcblxuLyoqXG4gKiBAdHlwZSB7bnVtYmVyfVxuICogQGNvbnN0XG4gKi9cbmZsYXRidWZmZXJzLkZJTEVfSURFTlRJRklFUl9MRU5HVEggPSA0O1xuXG4vKipcbiAqIEB0eXBlIHtudW1iZXJ9XG4gKiBAY29uc3RcbiAqL1xuZmxhdGJ1ZmZlcnMuU0laRV9QUkVGSVhfTEVOR1RIID0gNDtcblxuLyoqXG4gKiBAZW51bSB7bnVtYmVyfVxuICovXG5mbGF0YnVmZmVycy5FbmNvZGluZyA9IHtcbiAgVVRGOF9CWVRFUzogMSxcbiAgVVRGMTZfU1RSSU5HOiAyXG59O1xuXG4vKipcbiAqIEB0eXBlIHtJbnQzMkFycmF5fVxuICogQGNvbnN0XG4gKi9cbmZsYXRidWZmZXJzLmludDMyID0gbmV3IEludDMyQXJyYXkoMik7XG5cbi8qKlxuICogQHR5cGUge0Zsb2F0MzJBcnJheX1cbiAqIEBjb25zdFxuICovXG5mbGF0YnVmZmVycy5mbG9hdDMyID0gbmV3IEZsb2F0MzJBcnJheShmbGF0YnVmZmVycy5pbnQzMi5idWZmZXIpO1xuXG4vKipcbiAqIEB0eXBlIHtGbG9hdDY0QXJyYXl9XG4gKiBAY29uc3RcbiAqL1xuZmxhdGJ1ZmZlcnMuZmxvYXQ2NCA9IG5ldyBGbG9hdDY0QXJyYXkoZmxhdGJ1ZmZlcnMuaW50MzIuYnVmZmVyKTtcblxuLyoqXG4gKiBAdHlwZSB7Ym9vbGVhbn1cbiAqIEBjb25zdFxuICovXG5mbGF0YnVmZmVycy5pc0xpdHRsZUVuZGlhbiA9IG5ldyBVaW50MTZBcnJheShuZXcgVWludDhBcnJheShbMSwgMF0pLmJ1ZmZlcilbMF0gPT09IDE7XG5cbi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbi8qKlxuICogQGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge251bWJlcn0gbG93XG4gKiBAcGFyYW0ge251bWJlcn0gaGlnaFxuICovXG5mbGF0YnVmZmVycy5Mb25nID0gZnVuY3Rpb24obG93LCBoaWdoKSB7XG4gIC8qKlxuICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgKiBAY29uc3RcbiAgICovXG4gIHRoaXMubG93ID0gbG93IHwgMDtcblxuICAvKipcbiAgICogQHR5cGUge251bWJlcn1cbiAgICogQGNvbnN0XG4gICAqL1xuICB0aGlzLmhpZ2ggPSBoaWdoIHwgMDtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IGxvd1xuICogQHBhcmFtIHtudW1iZXJ9IGhpZ2hcbiAqIEByZXR1cm5zIHshZmxhdGJ1ZmZlcnMuTG9uZ31cbiAqL1xuZmxhdGJ1ZmZlcnMuTG9uZy5jcmVhdGUgPSBmdW5jdGlvbihsb3csIGhpZ2gpIHtcbiAgLy8gU3BlY2lhbC1jYXNlIHplcm8gdG8gYXZvaWQgR0Mgb3ZlcmhlYWQgZm9yIGRlZmF1bHQgdmFsdWVzXG4gIHJldHVybiBsb3cgPT0gMCAmJiBoaWdoID09IDAgPyBmbGF0YnVmZmVycy5Mb25nLlpFUk8gOiBuZXcgZmxhdGJ1ZmZlcnMuTG9uZyhsb3csIGhpZ2gpO1xufTtcblxuLyoqXG4gKiBAcmV0dXJucyB7bnVtYmVyfVxuICovXG5mbGF0YnVmZmVycy5Mb25nLnByb3RvdHlwZS50b0Zsb2F0NjQgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuICh0aGlzLmxvdyA+Pj4gMCkgKyB0aGlzLmhpZ2ggKiAweDEwMDAwMDAwMDtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtmbGF0YnVmZmVycy5Mb25nfSBvdGhlclxuICogQHJldHVybnMge2Jvb2xlYW59XG4gKi9cbmZsYXRidWZmZXJzLkxvbmcucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uKG90aGVyKSB7XG4gIHJldHVybiB0aGlzLmxvdyA9PSBvdGhlci5sb3cgJiYgdGhpcy5oaWdoID09IG90aGVyLmhpZ2g7XG59O1xuXG4vKipcbiAqIEB0eXBlIHshZmxhdGJ1ZmZlcnMuTG9uZ31cbiAqIEBjb25zdFxuICovXG5mbGF0YnVmZmVycy5Mb25nLlpFUk8gPSBuZXcgZmxhdGJ1ZmZlcnMuTG9uZygwLCAwKTtcblxuLy8vIEBlbmRjb25kXG4vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuLyoqXG4gKiBDcmVhdGUgYSBGbGF0QnVmZmVyQnVpbGRlci5cbiAqXG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7bnVtYmVyPX0gb3B0X2luaXRpYWxfc2l6ZVxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyID0gZnVuY3Rpb24ob3B0X2luaXRpYWxfc2l6ZSkge1xuICBpZiAoIW9wdF9pbml0aWFsX3NpemUpIHtcbiAgICB2YXIgaW5pdGlhbF9zaXplID0gMTAyNDtcbiAgfSBlbHNlIHtcbiAgICB2YXIgaW5pdGlhbF9zaXplID0gb3B0X2luaXRpYWxfc2l6ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAdHlwZSB7ZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcn1cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHRoaXMuYmIgPSBmbGF0YnVmZmVycy5CeXRlQnVmZmVyLmFsbG9jYXRlKGluaXRpYWxfc2l6ZSk7XG5cbiAgLyoqXG4gICAqIFJlbWFpbmluZyBzcGFjZSBpbiB0aGUgQnl0ZUJ1ZmZlci5cbiAgICpcbiAgICogQHR5cGUge251bWJlcn1cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHRoaXMuc3BhY2UgPSBpbml0aWFsX3NpemU7XG5cbiAgLyoqXG4gICAqIE1pbmltdW0gYWxpZ25tZW50IGVuY291bnRlcmVkIHNvIGZhci5cbiAgICpcbiAgICogQHR5cGUge251bWJlcn1cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHRoaXMubWluYWxpZ24gPSAxO1xuXG4gIC8qKlxuICAgKiBUaGUgdnRhYmxlIGZvciB0aGUgY3VycmVudCB0YWJsZS5cbiAgICpcbiAgICogQHR5cGUge0FycmF5LjxudW1iZXI+fVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgdGhpcy52dGFibGUgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBUaGUgYW1vdW50IG9mIGZpZWxkcyB3ZSdyZSBhY3R1YWxseSB1c2luZy5cbiAgICpcbiAgICogQHR5cGUge251bWJlcn1cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHRoaXMudnRhYmxlX2luX3VzZSA9IDA7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgd2UgYXJlIGN1cnJlbnRseSBzZXJpYWxpemluZyBhIHRhYmxlLlxuICAgKlxuICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHRoaXMuaXNOZXN0ZWQgPSBmYWxzZTtcblxuICAvKipcbiAgICogU3RhcnRpbmcgb2Zmc2V0IG9mIHRoZSBjdXJyZW50IHN0cnVjdC90YWJsZS5cbiAgICpcbiAgICogQHR5cGUge251bWJlcn1cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHRoaXMub2JqZWN0X3N0YXJ0ID0gMDtcblxuICAvKipcbiAgICogTGlzdCBvZiBvZmZzZXRzIG9mIGFsbCB2dGFibGVzLlxuICAgKlxuICAgKiBAdHlwZSB7QXJyYXkuPG51bWJlcj59XG4gICAqIEBwcml2YXRlXG4gICAqL1xuICB0aGlzLnZ0YWJsZXMgPSBbXTtcblxuICAvKipcbiAgICogRm9yIHRoZSBjdXJyZW50IHZlY3RvciBiZWluZyBidWlsdC5cbiAgICpcbiAgICogQHR5cGUge251bWJlcn1cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHRoaXMudmVjdG9yX251bV9lbGVtcyA9IDA7XG5cbiAgLyoqXG4gICAqIEZhbHNlIG9taXRzIGRlZmF1bHQgdmFsdWVzIGZyb20gdGhlIHNlcmlhbGl6ZWQgZGF0YVxuICAgKlxuICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHRoaXMuZm9yY2VfZGVmYXVsdHMgPSBmYWxzZTtcbn07XG5cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuYmIuY2xlYXIoKTtcbiAgdGhpcy5zcGFjZSA9IHRoaXMuYmIuY2FwYWNpdHkoKTtcbiAgdGhpcy5taW5hbGlnbiA9IDE7XG4gIHRoaXMudnRhYmxlID0gbnVsbDtcbiAgdGhpcy52dGFibGVfaW5fdXNlID0gMDtcbiAgdGhpcy5pc05lc3RlZCA9IGZhbHNlO1xuICB0aGlzLm9iamVjdF9zdGFydCA9IDA7XG4gIHRoaXMudnRhYmxlcyA9IFtdO1xuICB0aGlzLnZlY3Rvcl9udW1fZWxlbXMgPSAwO1xuICB0aGlzLmZvcmNlX2RlZmF1bHRzID0gZmFsc2U7XG59O1xuXG4vKipcbiAqIEluIG9yZGVyIHRvIHNhdmUgc3BhY2UsIGZpZWxkcyB0aGF0IGFyZSBzZXQgdG8gdGhlaXIgZGVmYXVsdCB2YWx1ZVxuICogZG9uJ3QgZ2V0IHNlcmlhbGl6ZWQgaW50byB0aGUgYnVmZmVyLiBGb3JjaW5nIGRlZmF1bHRzIHByb3ZpZGVzIGFcbiAqIHdheSB0byBtYW51YWxseSBkaXNhYmxlIHRoaXMgb3B0aW1pemF0aW9uLlxuICpcbiAqIEBwYXJhbSB7Ym9vbGVhbn0gZm9yY2VEZWZhdWx0cyB0cnVlIGFsd2F5cyBzZXJpYWxpemVzIGRlZmF1bHQgdmFsdWVzXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmZvcmNlRGVmYXVsdHMgPSBmdW5jdGlvbihmb3JjZURlZmF1bHRzKSB7XG4gIHRoaXMuZm9yY2VfZGVmYXVsdHMgPSBmb3JjZURlZmF1bHRzO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIEJ5dGVCdWZmZXIgcmVwcmVzZW50aW5nIHRoZSBGbGF0QnVmZmVyLiBPbmx5IGNhbGwgdGhpcyBhZnRlciB5b3UndmVcbiAqIGNhbGxlZCBmaW5pc2goKS4gVGhlIGFjdHVhbCBkYXRhIHN0YXJ0cyBhdCB0aGUgQnl0ZUJ1ZmZlcidzIGN1cnJlbnQgcG9zaXRpb24sXG4gKiBub3QgbmVjZXNzYXJpbHkgYXQgMC5cbiAqXG4gKiBAcmV0dXJucyB7ZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcn1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuZGF0YUJ1ZmZlciA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5iYjtcbn07XG5cbi8qKlxuICogR2V0IHRoZSBieXRlcyByZXByZXNlbnRpbmcgdGhlIEZsYXRCdWZmZXIuIE9ubHkgY2FsbCB0aGlzIGFmdGVyIHlvdSd2ZVxuICogY2FsbGVkIGZpbmlzaCgpLlxuICpcbiAqIEByZXR1cm5zIHshVWludDhBcnJheX1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuYXNVaW50OEFycmF5ID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLmJiLmJ5dGVzKCkuc3ViYXJyYXkodGhpcy5iYi5wb3NpdGlvbigpLCB0aGlzLmJiLnBvc2l0aW9uKCkgKyB0aGlzLm9mZnNldCgpKTtcbn07XG5cbi8vLyBAY29uZCBGTEFUQlVGRkVSU19JTlRFUk5BTFxuLyoqXG4gKiBQcmVwYXJlIHRvIHdyaXRlIGFuIGVsZW1lbnQgb2YgYHNpemVgIGFmdGVyIGBhZGRpdGlvbmFsX2J5dGVzYCBoYXZlIGJlZW5cbiAqIHdyaXR0ZW4sIGUuZy4gaWYgeW91IHdyaXRlIGEgc3RyaW5nLCB5b3UgbmVlZCB0byBhbGlnbiBzdWNoIHRoZSBpbnQgbGVuZ3RoXG4gKiBmaWVsZCBpcyBhbGlnbmVkIHRvIDQgYnl0ZXMsIGFuZCB0aGUgc3RyaW5nIGRhdGEgZm9sbG93cyBpdCBkaXJlY3RseS4gSWYgYWxsXG4gKiB5b3UgbmVlZCB0byBkbyBpcyBhbGlnbm1lbnQsIGBhZGRpdGlvbmFsX2J5dGVzYCB3aWxsIGJlIDAuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHNpemUgVGhpcyBpcyB0aGUgb2YgdGhlIG5ldyBlbGVtZW50IHRvIHdyaXRlXG4gKiBAcGFyYW0ge251bWJlcn0gYWRkaXRpb25hbF9ieXRlcyBUaGUgcGFkZGluZyBzaXplXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLnByZXAgPSBmdW5jdGlvbihzaXplLCBhZGRpdGlvbmFsX2J5dGVzKSB7XG4gIC8vIFRyYWNrIHRoZSBiaWdnZXN0IHRoaW5nIHdlJ3ZlIGV2ZXIgYWxpZ25lZCB0by5cbiAgaWYgKHNpemUgPiB0aGlzLm1pbmFsaWduKSB7XG4gICAgdGhpcy5taW5hbGlnbiA9IHNpemU7XG4gIH1cblxuICAvLyBGaW5kIHRoZSBhbW91bnQgb2YgYWxpZ25tZW50IG5lZWRlZCBzdWNoIHRoYXQgYHNpemVgIGlzIHByb3Blcmx5XG4gIC8vIGFsaWduZWQgYWZ0ZXIgYGFkZGl0aW9uYWxfYnl0ZXNgXG4gIHZhciBhbGlnbl9zaXplID0gKCh+KHRoaXMuYmIuY2FwYWNpdHkoKSAtIHRoaXMuc3BhY2UgKyBhZGRpdGlvbmFsX2J5dGVzKSkgKyAxKSAmIChzaXplIC0gMSk7XG5cbiAgLy8gUmVhbGxvY2F0ZSB0aGUgYnVmZmVyIGlmIG5lZWRlZC5cbiAgd2hpbGUgKHRoaXMuc3BhY2UgPCBhbGlnbl9zaXplICsgc2l6ZSArIGFkZGl0aW9uYWxfYnl0ZXMpIHtcbiAgICB2YXIgb2xkX2J1Zl9zaXplID0gdGhpcy5iYi5jYXBhY2l0eSgpO1xuICAgIHRoaXMuYmIgPSBmbGF0YnVmZmVycy5CdWlsZGVyLmdyb3dCeXRlQnVmZmVyKHRoaXMuYmIpO1xuICAgIHRoaXMuc3BhY2UgKz0gdGhpcy5iYi5jYXBhY2l0eSgpIC0gb2xkX2J1Zl9zaXplO1xuICB9XG5cbiAgdGhpcy5wYWQoYWxpZ25fc2l6ZSk7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBieXRlX3NpemVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUucGFkID0gZnVuY3Rpb24oYnl0ZV9zaXplKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYnl0ZV9zaXplOyBpKyspIHtcbiAgICB0aGlzLmJiLndyaXRlSW50OCgtLXRoaXMuc3BhY2UsIDApO1xuICB9XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS53cml0ZUludDggPSBmdW5jdGlvbih2YWx1ZSkge1xuICB0aGlzLmJiLndyaXRlSW50OCh0aGlzLnNwYWNlIC09IDEsIHZhbHVlKTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLndyaXRlSW50MTYgPSBmdW5jdGlvbih2YWx1ZSkge1xuICB0aGlzLmJiLndyaXRlSW50MTYodGhpcy5zcGFjZSAtPSAyLCB2YWx1ZSk7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS53cml0ZUludDMyID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgdGhpcy5iYi53cml0ZUludDMyKHRoaXMuc3BhY2UgLT0gNCwgdmFsdWUpO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge2ZsYXRidWZmZXJzLkxvbmd9IHZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLndyaXRlSW50NjQgPSBmdW5jdGlvbih2YWx1ZSkge1xuICB0aGlzLmJiLndyaXRlSW50NjQodGhpcy5zcGFjZSAtPSA4LCB2YWx1ZSk7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS53cml0ZUZsb2F0MzIgPSBmdW5jdGlvbih2YWx1ZSkge1xuICB0aGlzLmJiLndyaXRlRmxvYXQzMih0aGlzLnNwYWNlIC09IDQsIHZhbHVlKTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLndyaXRlRmxvYXQ2NCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHRoaXMuYmIud3JpdGVGbG9hdDY0KHRoaXMuc3BhY2UgLT0gOCwgdmFsdWUpO1xufTtcbi8vLyBAZW5kY29uZFxuXG4vKipcbiAqIEFkZCBhbiBgaW50OGAgdG8gdGhlIGJ1ZmZlciwgcHJvcGVybHkgYWxpZ25lZCwgYW5kIGdyb3dzIHRoZSBidWZmZXIgKGlmIG5lY2Vzc2FyeSkuXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVGhlIGBpbnQ4YCB0byBhZGQgdGhlIHRoZSBidWZmZXIuXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmFkZEludDggPSBmdW5jdGlvbih2YWx1ZSkge1xuICB0aGlzLnByZXAoMSwgMCk7XG4gIHRoaXMud3JpdGVJbnQ4KHZhbHVlKTtcbn07XG5cbi8qKlxuICogQWRkIGFuIGBpbnQxNmAgdG8gdGhlIGJ1ZmZlciwgcHJvcGVybHkgYWxpZ25lZCwgYW5kIGdyb3dzIHRoZSBidWZmZXIgKGlmIG5lY2Vzc2FyeSkuXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVGhlIGBpbnQxNmAgdG8gYWRkIHRoZSB0aGUgYnVmZmVyLlxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5hZGRJbnQxNiA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHRoaXMucHJlcCgyLCAwKTtcbiAgdGhpcy53cml0ZUludDE2KHZhbHVlKTtcbn07XG5cbi8qKlxuICogQWRkIGFuIGBpbnQzMmAgdG8gdGhlIGJ1ZmZlciwgcHJvcGVybHkgYWxpZ25lZCwgYW5kIGdyb3dzIHRoZSBidWZmZXIgKGlmIG5lY2Vzc2FyeSkuXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVGhlIGBpbnQzMmAgdG8gYWRkIHRoZSB0aGUgYnVmZmVyLlxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5hZGRJbnQzMiA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHRoaXMucHJlcCg0LCAwKTtcbiAgdGhpcy53cml0ZUludDMyKHZhbHVlKTtcbn07XG5cbi8qKlxuICogQWRkIGFuIGBpbnQ2NGAgdG8gdGhlIGJ1ZmZlciwgcHJvcGVybHkgYWxpZ25lZCwgYW5kIGdyb3dzIHRoZSBidWZmZXIgKGlmIG5lY2Vzc2FyeSkuXG4gKiBAcGFyYW0ge2ZsYXRidWZmZXJzLkxvbmd9IHZhbHVlIFRoZSBgaW50NjRgIHRvIGFkZCB0aGUgdGhlIGJ1ZmZlci5cbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuYWRkSW50NjQgPSBmdW5jdGlvbih2YWx1ZSkge1xuICB0aGlzLnByZXAoOCwgMCk7XG4gIHRoaXMud3JpdGVJbnQ2NCh2YWx1ZSk7XG59O1xuXG4vKipcbiAqIEFkZCBhIGBmbG9hdDMyYCB0byB0aGUgYnVmZmVyLCBwcm9wZXJseSBhbGlnbmVkLCBhbmQgZ3Jvd3MgdGhlIGJ1ZmZlciAoaWYgbmVjZXNzYXJ5KS5cbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBUaGUgYGZsb2F0MzJgIHRvIGFkZCB0aGUgdGhlIGJ1ZmZlci5cbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuYWRkRmxvYXQzMiA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gIHRoaXMucHJlcCg0LCAwKTtcbiAgdGhpcy53cml0ZUZsb2F0MzIodmFsdWUpO1xufTtcblxuLyoqXG4gKiBBZGQgYSBgZmxvYXQ2NGAgdG8gdGhlIGJ1ZmZlciwgcHJvcGVybHkgYWxpZ25lZCwgYW5kIGdyb3dzIHRoZSBidWZmZXIgKGlmIG5lY2Vzc2FyeSkuXG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVGhlIGBmbG9hdDY0YCB0byBhZGQgdGhlIHRoZSBidWZmZXIuXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmFkZEZsb2F0NjQgPSBmdW5jdGlvbih2YWx1ZSkge1xuICB0aGlzLnByZXAoOCwgMCk7XG4gIHRoaXMud3JpdGVGbG9hdDY0KHZhbHVlKTtcbn07XG5cbi8vLyBAY29uZCBGTEFUQlVGRkVSU19JTlRFUk5BTFxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gdm9mZnNldFxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKiBAcGFyYW0ge251bWJlcn0gZGVmYXVsdFZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmFkZEZpZWxkSW50OCA9IGZ1bmN0aW9uKHZvZmZzZXQsIHZhbHVlLCBkZWZhdWx0VmFsdWUpIHtcbiAgaWYgKHRoaXMuZm9yY2VfZGVmYXVsdHMgfHwgdmFsdWUgIT0gZGVmYXVsdFZhbHVlKSB7XG4gICAgdGhpcy5hZGRJbnQ4KHZhbHVlKTtcbiAgICB0aGlzLnNsb3Qodm9mZnNldCk7XG4gIH1cbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IHZvZmZzZXRcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICogQHBhcmFtIHtudW1iZXJ9IGRlZmF1bHRWYWx1ZVxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5hZGRGaWVsZEludDE2ID0gZnVuY3Rpb24odm9mZnNldCwgdmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICBpZiAodGhpcy5mb3JjZV9kZWZhdWx0cyB8fCB2YWx1ZSAhPSBkZWZhdWx0VmFsdWUpIHtcbiAgICB0aGlzLmFkZEludDE2KHZhbHVlKTtcbiAgICB0aGlzLnNsb3Qodm9mZnNldCk7XG4gIH1cbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IHZvZmZzZXRcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICogQHBhcmFtIHtudW1iZXJ9IGRlZmF1bHRWYWx1ZVxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5hZGRGaWVsZEludDMyID0gZnVuY3Rpb24odm9mZnNldCwgdmFsdWUsIGRlZmF1bHRWYWx1ZSkge1xuICBpZiAodGhpcy5mb3JjZV9kZWZhdWx0cyB8fCB2YWx1ZSAhPSBkZWZhdWx0VmFsdWUpIHtcbiAgICB0aGlzLmFkZEludDMyKHZhbHVlKTtcbiAgICB0aGlzLnNsb3Qodm9mZnNldCk7XG4gIH1cbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IHZvZmZzZXRcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuTG9uZ30gdmFsdWVcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuTG9uZ30gZGVmYXVsdFZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmFkZEZpZWxkSW50NjQgPSBmdW5jdGlvbih2b2Zmc2V0LCB2YWx1ZSwgZGVmYXVsdFZhbHVlKSB7XG4gIGlmICh0aGlzLmZvcmNlX2RlZmF1bHRzIHx8ICF2YWx1ZS5lcXVhbHMoZGVmYXVsdFZhbHVlKSkge1xuICAgIHRoaXMuYWRkSW50NjQodmFsdWUpO1xuICAgIHRoaXMuc2xvdCh2b2Zmc2V0KTtcbiAgfVxufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gdm9mZnNldFxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKiBAcGFyYW0ge251bWJlcn0gZGVmYXVsdFZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmFkZEZpZWxkRmxvYXQzMiA9IGZ1bmN0aW9uKHZvZmZzZXQsIHZhbHVlLCBkZWZhdWx0VmFsdWUpIHtcbiAgaWYgKHRoaXMuZm9yY2VfZGVmYXVsdHMgfHwgdmFsdWUgIT0gZGVmYXVsdFZhbHVlKSB7XG4gICAgdGhpcy5hZGRGbG9hdDMyKHZhbHVlKTtcbiAgICB0aGlzLnNsb3Qodm9mZnNldCk7XG4gIH1cbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IHZvZmZzZXRcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICogQHBhcmFtIHtudW1iZXJ9IGRlZmF1bHRWYWx1ZVxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5hZGRGaWVsZEZsb2F0NjQgPSBmdW5jdGlvbih2b2Zmc2V0LCB2YWx1ZSwgZGVmYXVsdFZhbHVlKSB7XG4gIGlmICh0aGlzLmZvcmNlX2RlZmF1bHRzIHx8IHZhbHVlICE9IGRlZmF1bHRWYWx1ZSkge1xuICAgIHRoaXMuYWRkRmxvYXQ2NCh2YWx1ZSk7XG4gICAgdGhpcy5zbG90KHZvZmZzZXQpO1xuICB9XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSB2b2Zmc2V0XG4gKiBAcGFyYW0ge2ZsYXRidWZmZXJzLk9mZnNldH0gdmFsdWVcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuT2Zmc2V0fSBkZWZhdWx0VmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuYWRkRmllbGRPZmZzZXQgPSBmdW5jdGlvbih2b2Zmc2V0LCB2YWx1ZSwgZGVmYXVsdFZhbHVlKSB7XG4gIGlmICh0aGlzLmZvcmNlX2RlZmF1bHRzIHx8IHZhbHVlICE9IGRlZmF1bHRWYWx1ZSkge1xuICAgIHRoaXMuYWRkT2Zmc2V0KHZhbHVlKTtcbiAgICB0aGlzLnNsb3Qodm9mZnNldCk7XG4gIH1cbn07XG5cbi8qKlxuICogU3RydWN0cyBhcmUgc3RvcmVkIGlubGluZSwgc28gbm90aGluZyBhZGRpdGlvbmFsIGlzIGJlaW5nIGFkZGVkLiBgZGAgaXMgYWx3YXlzIDAuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHZvZmZzZXRcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuT2Zmc2V0fSB2YWx1ZVxuICogQHBhcmFtIHtmbGF0YnVmZmVycy5PZmZzZXR9IGRlZmF1bHRWYWx1ZVxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5hZGRGaWVsZFN0cnVjdCA9IGZ1bmN0aW9uKHZvZmZzZXQsIHZhbHVlLCBkZWZhdWx0VmFsdWUpIHtcbiAgaWYgKHZhbHVlICE9IGRlZmF1bHRWYWx1ZSkge1xuICAgIHRoaXMubmVzdGVkKHZhbHVlKTtcbiAgICB0aGlzLnNsb3Qodm9mZnNldCk7XG4gIH1cbn07XG5cbi8qKlxuICogU3RydWN0dXJlcyBhcmUgYWx3YXlzIHN0b3JlZCBpbmxpbmUsIHRoZXkgbmVlZCB0byBiZSBjcmVhdGVkIHJpZ2h0XG4gKiB3aGVyZSB0aGV5J3JlIHVzZWQuICBZb3UnbGwgZ2V0IHRoaXMgYXNzZXJ0aW9uIGZhaWx1cmUgaWYgeW91XG4gKiBjcmVhdGVkIGl0IGVsc2V3aGVyZS5cbiAqXG4gKiBAcGFyYW0ge2ZsYXRidWZmZXJzLk9mZnNldH0gb2JqIFRoZSBvZmZzZXQgb2YgdGhlIGNyZWF0ZWQgb2JqZWN0XG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLm5lc3RlZCA9IGZ1bmN0aW9uKG9iaikge1xuICBpZiAob2JqICE9IHRoaXMub2Zmc2V0KCkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZsYXRCdWZmZXJzOiBzdHJ1Y3QgbXVzdCBiZSBzZXJpYWxpemVkIGlubGluZS4nKTtcbiAgfVxufTtcblxuLyoqXG4gKiBTaG91bGQgbm90IGJlIGNyZWF0aW5nIGFueSBvdGhlciBvYmplY3QsIHN0cmluZyBvciB2ZWN0b3JcbiAqIHdoaWxlIGFuIG9iamVjdCBpcyBiZWluZyBjb25zdHJ1Y3RlZFxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5ub3ROZXN0ZWQgPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMuaXNOZXN0ZWQpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZsYXRCdWZmZXJzOiBvYmplY3Qgc2VyaWFsaXphdGlvbiBtdXN0IG5vdCBiZSBuZXN0ZWQuJyk7XG4gIH1cbn07XG5cbi8qKlxuICogU2V0IHRoZSBjdXJyZW50IHZ0YWJsZSBhdCBgdm9mZnNldGAgdG8gdGhlIGN1cnJlbnQgbG9jYXRpb24gaW4gdGhlIGJ1ZmZlci5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gdm9mZnNldFxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5zbG90ID0gZnVuY3Rpb24odm9mZnNldCkge1xuICB0aGlzLnZ0YWJsZVt2b2Zmc2V0XSA9IHRoaXMub2Zmc2V0KCk7XG59O1xuXG4vKipcbiAqIEByZXR1cm5zIHtmbGF0YnVmZmVycy5PZmZzZXR9IE9mZnNldCByZWxhdGl2ZSB0byB0aGUgZW5kIG9mIHRoZSBidWZmZXIuXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLm9mZnNldCA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5iYi5jYXBhY2l0eSgpIC0gdGhpcy5zcGFjZTtcbn07XG5cbi8qKlxuICogRG91YmxlcyB0aGUgc2l6ZSBvZiB0aGUgYmFja2luZyBCeXRlQnVmZmVyIGFuZCBjb3BpZXMgdGhlIG9sZCBkYXRhIHRvd2FyZHNcbiAqIHRoZSBlbmQgb2YgdGhlIG5ldyBidWZmZXIgKHNpbmNlIHdlIGJ1aWxkIHRoZSBidWZmZXIgYmFja3dhcmRzKS5cbiAqXG4gKiBAcGFyYW0ge2ZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ9IGJiIFRoZSBjdXJyZW50IGJ1ZmZlciB3aXRoIHRoZSBleGlzdGluZyBkYXRhXG4gKiBAcmV0dXJucyB7IWZsYXRidWZmZXJzLkJ5dGVCdWZmZXJ9IEEgbmV3IGJ5dGUgYnVmZmVyIHdpdGggdGhlIG9sZCBkYXRhIGNvcGllZFxuICogdG8gaXQuIFRoZSBkYXRhIGlzIGxvY2F0ZWQgYXQgdGhlIGVuZCBvZiB0aGUgYnVmZmVyLlxuICpcbiAqIHVpbnQ4QXJyYXkuc2V0KCkgZm9ybWFsbHkgdGFrZXMge0FycmF5PG51bWJlcj58QXJyYXlCdWZmZXJWaWV3fSwgc28gdG8gcGFzc1xuICogaXQgYSB1aW50OEFycmF5IHdlIG5lZWQgdG8gc3VwcHJlc3MgdGhlIHR5cGUgY2hlY2s6XG4gKiBAc3VwcHJlc3Mge2NoZWNrVHlwZXN9XG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIuZ3Jvd0J5dGVCdWZmZXIgPSBmdW5jdGlvbihiYikge1xuICB2YXIgb2xkX2J1Zl9zaXplID0gYmIuY2FwYWNpdHkoKTtcblxuICAvLyBFbnN1cmUgd2UgZG9uJ3QgZ3JvdyBiZXlvbmQgd2hhdCBmaXRzIGluIGFuIGludC5cbiAgaWYgKG9sZF9idWZfc2l6ZSAmIDB4QzAwMDAwMDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZsYXRCdWZmZXJzOiBjYW5ub3QgZ3JvdyBidWZmZXIgYmV5b25kIDIgZ2lnYWJ5dGVzLicpO1xuICB9XG5cbiAgdmFyIG5ld19idWZfc2l6ZSA9IG9sZF9idWZfc2l6ZSA8PCAxO1xuICB2YXIgbmJiID0gZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5hbGxvY2F0ZShuZXdfYnVmX3NpemUpO1xuICBuYmIuc2V0UG9zaXRpb24obmV3X2J1Zl9zaXplIC0gb2xkX2J1Zl9zaXplKTtcbiAgbmJiLmJ5dGVzKCkuc2V0KGJiLmJ5dGVzKCksIG5ld19idWZfc2l6ZSAtIG9sZF9idWZfc2l6ZSk7XG4gIHJldHVybiBuYmI7XG59O1xuLy8vIEBlbmRjb25kXG5cbi8qKlxuICogQWRkcyBvbiBvZmZzZXQsIHJlbGF0aXZlIHRvIHdoZXJlIGl0IHdpbGwgYmUgd3JpdHRlbi5cbiAqXG4gKiBAcGFyYW0ge2ZsYXRidWZmZXJzLk9mZnNldH0gb2Zmc2V0IFRoZSBvZmZzZXQgdG8gYWRkLlxuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5hZGRPZmZzZXQgPSBmdW5jdGlvbihvZmZzZXQpIHtcbiAgdGhpcy5wcmVwKGZsYXRidWZmZXJzLlNJWkVPRl9JTlQsIDApOyAvLyBFbnN1cmUgYWxpZ25tZW50IGlzIGFscmVhZHkgZG9uZS5cbiAgdGhpcy53cml0ZUludDMyKHRoaXMub2Zmc2V0KCkgLSBvZmZzZXQgKyBmbGF0YnVmZmVycy5TSVpFT0ZfSU5UKTtcbn07XG5cbi8vLyBAY29uZCBGTEFUQlVGRkVSU19JTlRFUk5BTFxuLyoqXG4gKiBTdGFydCBlbmNvZGluZyBhIG5ldyBvYmplY3QgaW4gdGhlIGJ1ZmZlci4gIFVzZXJzIHdpbGwgbm90IHVzdWFsbHkgbmVlZCB0b1xuICogY2FsbCB0aGlzIGRpcmVjdGx5LiBUaGUgRmxhdEJ1ZmZlcnMgY29tcGlsZXIgd2lsbCBnZW5lcmF0ZSBoZWxwZXIgbWV0aG9kc1xuICogdGhhdCBjYWxsIHRoaXMgbWV0aG9kIGludGVybmFsbHkuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IG51bWZpZWxkc1xuICovXG5mbGF0YnVmZmVycy5CdWlsZGVyLnByb3RvdHlwZS5zdGFydE9iamVjdCA9IGZ1bmN0aW9uKG51bWZpZWxkcykge1xuICB0aGlzLm5vdE5lc3RlZCgpO1xuICBpZiAodGhpcy52dGFibGUgPT0gbnVsbCkge1xuICAgIHRoaXMudnRhYmxlID0gW107XG4gIH1cbiAgdGhpcy52dGFibGVfaW5fdXNlID0gbnVtZmllbGRzO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IG51bWZpZWxkczsgaSsrKSB7XG4gICAgdGhpcy52dGFibGVbaV0gPSAwOyAvLyBUaGlzIHdpbGwgcHVzaCBhZGRpdGlvbmFsIGVsZW1lbnRzIGFzIG5lZWRlZFxuICB9XG4gIHRoaXMuaXNOZXN0ZWQgPSB0cnVlO1xuICB0aGlzLm9iamVjdF9zdGFydCA9IHRoaXMub2Zmc2V0KCk7XG59O1xuXG4vKipcbiAqIEZpbmlzaCBvZmYgd3JpdGluZyB0aGUgb2JqZWN0IHRoYXQgaXMgdW5kZXIgY29uc3RydWN0aW9uLlxuICpcbiAqIEByZXR1cm5zIHtmbGF0YnVmZmVycy5PZmZzZXR9IFRoZSBvZmZzZXQgdG8gdGhlIG9iamVjdCBpbnNpZGUgYGRhdGFCdWZmZXJgXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmVuZE9iamVjdCA9IGZ1bmN0aW9uKCkge1xuICBpZiAodGhpcy52dGFibGUgPT0gbnVsbCB8fCAhdGhpcy5pc05lc3RlZCkge1xuICAgIHRocm93IG5ldyBFcnJvcignRmxhdEJ1ZmZlcnM6IGVuZE9iamVjdCBjYWxsZWQgd2l0aG91dCBzdGFydE9iamVjdCcpO1xuICB9XG5cbiAgdGhpcy5hZGRJbnQzMigwKTtcbiAgdmFyIHZ0YWJsZWxvYyA9IHRoaXMub2Zmc2V0KCk7XG5cbiAgLy8gVHJpbSB0cmFpbGluZyB6ZXJvZXMuXG4gIHZhciBpID0gdGhpcy52dGFibGVfaW5fdXNlIC0gMTtcbiAgZm9yICg7IGkgPj0gMCAmJiB0aGlzLnZ0YWJsZVtpXSA9PSAwOyBpLS0pIHt9XG4gIHZhciB0cmltbWVkX3NpemUgPSBpICsgMTtcblxuICAvLyBXcml0ZSBvdXQgdGhlIGN1cnJlbnQgdnRhYmxlLlxuICBmb3IgKDsgaSA+PSAwOyBpLS0pIHtcbiAgICAvLyBPZmZzZXQgcmVsYXRpdmUgdG8gdGhlIHN0YXJ0IG9mIHRoZSB0YWJsZS5cbiAgICB0aGlzLmFkZEludDE2KHRoaXMudnRhYmxlW2ldICE9IDAgPyB2dGFibGVsb2MgLSB0aGlzLnZ0YWJsZVtpXSA6IDApO1xuICB9XG5cbiAgdmFyIHN0YW5kYXJkX2ZpZWxkcyA9IDI7IC8vIFRoZSBmaWVsZHMgYmVsb3c6XG4gIHRoaXMuYWRkSW50MTYodnRhYmxlbG9jIC0gdGhpcy5vYmplY3Rfc3RhcnQpO1xuICB2YXIgbGVuID0gKHRyaW1tZWRfc2l6ZSArIHN0YW5kYXJkX2ZpZWxkcykgKiBmbGF0YnVmZmVycy5TSVpFT0ZfU0hPUlQ7XG4gIHRoaXMuYWRkSW50MTYobGVuKTtcblxuICAvLyBTZWFyY2ggZm9yIGFuIGV4aXN0aW5nIHZ0YWJsZSB0aGF0IG1hdGNoZXMgdGhlIGN1cnJlbnQgb25lLlxuICB2YXIgZXhpc3RpbmdfdnRhYmxlID0gMDtcbiAgdmFyIHZ0MSA9IHRoaXMuc3BhY2U7XG5vdXRlcl9sb29wOlxuICBmb3IgKGkgPSAwOyBpIDwgdGhpcy52dGFibGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHZ0MiA9IHRoaXMuYmIuY2FwYWNpdHkoKSAtIHRoaXMudnRhYmxlc1tpXTtcbiAgICBpZiAobGVuID09IHRoaXMuYmIucmVhZEludDE2KHZ0MikpIHtcbiAgICAgIGZvciAodmFyIGogPSBmbGF0YnVmZmVycy5TSVpFT0ZfU0hPUlQ7IGogPCBsZW47IGogKz0gZmxhdGJ1ZmZlcnMuU0laRU9GX1NIT1JUKSB7XG4gICAgICAgIGlmICh0aGlzLmJiLnJlYWRJbnQxNih2dDEgKyBqKSAhPSB0aGlzLmJiLnJlYWRJbnQxNih2dDIgKyBqKSkge1xuICAgICAgICAgIGNvbnRpbnVlIG91dGVyX2xvb3A7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGV4aXN0aW5nX3Z0YWJsZSA9IHRoaXMudnRhYmxlc1tpXTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIGlmIChleGlzdGluZ192dGFibGUpIHtcbiAgICAvLyBGb3VuZCBhIG1hdGNoOlxuICAgIC8vIFJlbW92ZSB0aGUgY3VycmVudCB2dGFibGUuXG4gICAgdGhpcy5zcGFjZSA9IHRoaXMuYmIuY2FwYWNpdHkoKSAtIHZ0YWJsZWxvYztcblxuICAgIC8vIFBvaW50IHRhYmxlIHRvIGV4aXN0aW5nIHZ0YWJsZS5cbiAgICB0aGlzLmJiLndyaXRlSW50MzIodGhpcy5zcGFjZSwgZXhpc3RpbmdfdnRhYmxlIC0gdnRhYmxlbG9jKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBObyBtYXRjaDpcbiAgICAvLyBBZGQgdGhlIGxvY2F0aW9uIG9mIHRoZSBjdXJyZW50IHZ0YWJsZSB0byB0aGUgbGlzdCBvZiB2dGFibGVzLlxuICAgIHRoaXMudnRhYmxlcy5wdXNoKHRoaXMub2Zmc2V0KCkpO1xuXG4gICAgLy8gUG9pbnQgdGFibGUgdG8gY3VycmVudCB2dGFibGUuXG4gICAgdGhpcy5iYi53cml0ZUludDMyKHRoaXMuYmIuY2FwYWNpdHkoKSAtIHZ0YWJsZWxvYywgdGhpcy5vZmZzZXQoKSAtIHZ0YWJsZWxvYyk7XG4gIH1cblxuICB0aGlzLmlzTmVzdGVkID0gZmFsc2U7XG4gIHJldHVybiB2dGFibGVsb2M7XG59O1xuLy8vIEBlbmRjb25kXG5cbi8qKlxuICogRmluYWxpemUgYSBidWZmZXIsIHBvaXRpbmcgdG8gdGhlIGdpdmVuIGByb290X3RhYmxlYC5cbiAqXG4gKiBAcGFyYW0ge2ZsYXRidWZmZXJzLk9mZnNldH0gcm9vdF90YWJsZVxuICogQHBhcmFtIHtzdHJpbmc9fSBvcHRfZmlsZV9pZGVudGlmaWVyXG4gKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfc2l6ZV9wcmVmaXhcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuZmluaXNoID0gZnVuY3Rpb24ocm9vdF90YWJsZSwgb3B0X2ZpbGVfaWRlbnRpZmllciwgb3B0X3NpemVfcHJlZml4KSB7XG4gIHZhciBzaXplX3ByZWZpeCA9IG9wdF9zaXplX3ByZWZpeCA/IGZsYXRidWZmZXJzLlNJWkVfUFJFRklYX0xFTkdUSCA6IDA7XG4gIGlmIChvcHRfZmlsZV9pZGVudGlmaWVyKSB7XG4gICAgdmFyIGZpbGVfaWRlbnRpZmllciA9IG9wdF9maWxlX2lkZW50aWZpZXI7XG4gICAgdGhpcy5wcmVwKHRoaXMubWluYWxpZ24sIGZsYXRidWZmZXJzLlNJWkVPRl9JTlQgK1xuICAgICAgZmxhdGJ1ZmZlcnMuRklMRV9JREVOVElGSUVSX0xFTkdUSCArIHNpemVfcHJlZml4KTtcbiAgICBpZiAoZmlsZV9pZGVudGlmaWVyLmxlbmd0aCAhPSBmbGF0YnVmZmVycy5GSUxFX0lERU5USUZJRVJfTEVOR1RIKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZsYXRCdWZmZXJzOiBmaWxlIGlkZW50aWZpZXIgbXVzdCBiZSBsZW5ndGggJyArXG4gICAgICAgIGZsYXRidWZmZXJzLkZJTEVfSURFTlRJRklFUl9MRU5HVEgpO1xuICAgIH1cbiAgICBmb3IgKHZhciBpID0gZmxhdGJ1ZmZlcnMuRklMRV9JREVOVElGSUVSX0xFTkdUSCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICB0aGlzLndyaXRlSW50OChmaWxlX2lkZW50aWZpZXIuY2hhckNvZGVBdChpKSk7XG4gICAgfVxuICB9XG4gIHRoaXMucHJlcCh0aGlzLm1pbmFsaWduLCBmbGF0YnVmZmVycy5TSVpFT0ZfSU5UICsgc2l6ZV9wcmVmaXgpO1xuICB0aGlzLmFkZE9mZnNldChyb290X3RhYmxlKTtcbiAgaWYgKHNpemVfcHJlZml4KSB7XG4gICAgdGhpcy5hZGRJbnQzMih0aGlzLmJiLmNhcGFjaXR5KCkgLSB0aGlzLnNwYWNlKTtcbiAgfVxuICB0aGlzLmJiLnNldFBvc2l0aW9uKHRoaXMuc3BhY2UpO1xufTtcblxuLyoqXG4gKiBGaW5hbGl6ZSBhIHNpemUgcHJlZml4ZWQgYnVmZmVyLCBwb2ludGluZyB0byB0aGUgZ2l2ZW4gYHJvb3RfdGFibGVgLlxuICpcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuT2Zmc2V0fSByb290X3RhYmxlXG4gKiBAcGFyYW0ge3N0cmluZz19IG9wdF9maWxlX2lkZW50aWZpZXJcbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuZmluaXNoU2l6ZVByZWZpeGVkID0gZnVuY3Rpb24gKHJvb3RfdGFibGUsIG9wdF9maWxlX2lkZW50aWZpZXIpIHtcbiAgdGhpcy5maW5pc2gocm9vdF90YWJsZSwgb3B0X2ZpbGVfaWRlbnRpZmllciwgdHJ1ZSk7XG59O1xuXG4vLy8gQGNvbmQgRkxBVEJVRkZFUlNfSU5URVJOQUxcbi8qKlxuICogVGhpcyBjaGVja3MgYSByZXF1aXJlZCBmaWVsZCBoYXMgYmVlbiBzZXQgaW4gYSBnaXZlbiB0YWJsZSB0aGF0IGhhc1xuICoganVzdCBiZWVuIGNvbnN0cnVjdGVkLlxuICpcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuT2Zmc2V0fSB0YWJsZVxuICogQHBhcmFtIHtudW1iZXJ9IGZpZWxkXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLnJlcXVpcmVkRmllbGQgPSBmdW5jdGlvbih0YWJsZSwgZmllbGQpIHtcbiAgdmFyIHRhYmxlX3N0YXJ0ID0gdGhpcy5iYi5jYXBhY2l0eSgpIC0gdGFibGU7XG4gIHZhciB2dGFibGVfc3RhcnQgPSB0YWJsZV9zdGFydCAtIHRoaXMuYmIucmVhZEludDMyKHRhYmxlX3N0YXJ0KTtcbiAgdmFyIG9rID0gdGhpcy5iYi5yZWFkSW50MTYodnRhYmxlX3N0YXJ0ICsgZmllbGQpICE9IDA7XG5cbiAgLy8gSWYgdGhpcyBmYWlscywgdGhlIGNhbGxlciB3aWxsIHNob3cgd2hhdCBmaWVsZCBuZWVkcyB0byBiZSBzZXQuXG4gIGlmICghb2spIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZsYXRCdWZmZXJzOiBmaWVsZCAnICsgZmllbGQgKyAnIG11c3QgYmUgc2V0Jyk7XG4gIH1cbn07XG5cbi8qKlxuICogU3RhcnQgYSBuZXcgYXJyYXkvdmVjdG9yIG9mIG9iamVjdHMuICBVc2VycyB1c3VhbGx5IHdpbGwgbm90IGNhbGxcbiAqIHRoaXMgZGlyZWN0bHkuIFRoZSBGbGF0QnVmZmVycyBjb21waWxlciB3aWxsIGNyZWF0ZSBhIHN0YXJ0L2VuZFxuICogbWV0aG9kIGZvciB2ZWN0b3IgdHlwZXMgaW4gZ2VuZXJhdGVkIGNvZGUuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IGVsZW1fc2l6ZSBUaGUgc2l6ZSBvZiBlYWNoIGVsZW1lbnQgaW4gdGhlIGFycmF5XG4gKiBAcGFyYW0ge251bWJlcn0gbnVtX2VsZW1zIFRoZSBudW1iZXIgb2YgZWxlbWVudHMgaW4gdGhlIGFycmF5XG4gKiBAcGFyYW0ge251bWJlcn0gYWxpZ25tZW50IFRoZSBhbGlnbm1lbnQgb2YgdGhlIGFycmF5XG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLnN0YXJ0VmVjdG9yID0gZnVuY3Rpb24oZWxlbV9zaXplLCBudW1fZWxlbXMsIGFsaWdubWVudCkge1xuICB0aGlzLm5vdE5lc3RlZCgpO1xuICB0aGlzLnZlY3Rvcl9udW1fZWxlbXMgPSBudW1fZWxlbXM7XG4gIHRoaXMucHJlcChmbGF0YnVmZmVycy5TSVpFT0ZfSU5ULCBlbGVtX3NpemUgKiBudW1fZWxlbXMpO1xuICB0aGlzLnByZXAoYWxpZ25tZW50LCBlbGVtX3NpemUgKiBudW1fZWxlbXMpOyAvLyBKdXN0IGluIGNhc2UgYWxpZ25tZW50ID4gaW50LlxufTtcblxuLyoqXG4gKiBGaW5pc2ggb2ZmIHRoZSBjcmVhdGlvbiBvZiBhbiBhcnJheSBhbmQgYWxsIGl0cyBlbGVtZW50cy4gVGhlIGFycmF5IG11c3QgYmVcbiAqIGNyZWF0ZWQgd2l0aCBgc3RhcnRWZWN0b3JgLlxuICpcbiAqIEByZXR1cm5zIHtmbGF0YnVmZmVycy5PZmZzZXR9IFRoZSBvZmZzZXQgYXQgd2hpY2ggdGhlIG5ld2x5IGNyZWF0ZWQgYXJyYXlcbiAqIHN0YXJ0cy5cbiAqL1xuZmxhdGJ1ZmZlcnMuQnVpbGRlci5wcm90b3R5cGUuZW5kVmVjdG9yID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMud3JpdGVJbnQzMih0aGlzLnZlY3Rvcl9udW1fZWxlbXMpO1xuICByZXR1cm4gdGhpcy5vZmZzZXQoKTtcbn07XG4vLy8gQGVuZGNvbmRcblxuLyoqXG4gKiBFbmNvZGUgdGhlIHN0cmluZyBgc2AgaW4gdGhlIGJ1ZmZlciB1c2luZyBVVEYtOC4gSWYgYSBVaW50OEFycmF5IGlzIHBhc3NlZFxuICogaW5zdGVhZCBvZiBhIHN0cmluZywgaXQgaXMgYXNzdW1lZCB0byBjb250YWluIHZhbGlkIFVURi04IGVuY29kZWQgZGF0YS5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ3xVaW50OEFycmF5fSBzIFRoZSBzdHJpbmcgdG8gZW5jb2RlXG4gKiBAcmV0dXJuIHtmbGF0YnVmZmVycy5PZmZzZXR9IFRoZSBvZmZzZXQgaW4gdGhlIGJ1ZmZlciB3aGVyZSB0aGUgZW5jb2RlZCBzdHJpbmcgc3RhcnRzXG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmNyZWF0ZVN0cmluZyA9IGZ1bmN0aW9uKHMpIHtcbiAgaWYgKHMgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgdmFyIHV0ZjggPSBzO1xuICB9IGVsc2Uge1xuICAgIHZhciB1dGY4ID0gW107XG4gICAgdmFyIGkgPSAwO1xuXG4gICAgd2hpbGUgKGkgPCBzLmxlbmd0aCkge1xuICAgICAgdmFyIGNvZGVQb2ludDtcblxuICAgICAgLy8gRGVjb2RlIFVURi0xNlxuICAgICAgdmFyIGEgPSBzLmNoYXJDb2RlQXQoaSsrKTtcbiAgICAgIGlmIChhIDwgMHhEODAwIHx8IGEgPj0gMHhEQzAwKSB7XG4gICAgICAgIGNvZGVQb2ludCA9IGE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgYiA9IHMuY2hhckNvZGVBdChpKyspO1xuICAgICAgICBjb2RlUG9pbnQgPSAoYSA8PCAxMCkgKyBiICsgKDB4MTAwMDAgLSAoMHhEODAwIDw8IDEwKSAtIDB4REMwMCk7XG4gICAgICB9XG5cbiAgICAgIC8vIEVuY29kZSBVVEYtOFxuICAgICAgaWYgKGNvZGVQb2ludCA8IDB4ODApIHtcbiAgICAgICAgdXRmOC5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoY29kZVBvaW50IDwgMHg4MDApIHtcbiAgICAgICAgICB1dGY4LnB1c2goKChjb2RlUG9pbnQgPj4gNikgJiAweDFGKSB8IDB4QzApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChjb2RlUG9pbnQgPCAweDEwMDAwKSB7XG4gICAgICAgICAgICB1dGY4LnB1c2goKChjb2RlUG9pbnQgPj4gMTIpICYgMHgwRikgfCAweEUwKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdXRmOC5wdXNoKFxuICAgICAgICAgICAgICAoKGNvZGVQb2ludCA+PiAxOCkgJiAweDA3KSB8IDB4RjAsXG4gICAgICAgICAgICAgICgoY29kZVBvaW50ID4+IDEyKSAmIDB4M0YpIHwgMHg4MCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHV0ZjgucHVzaCgoKGNvZGVQb2ludCA+PiA2KSAmIDB4M0YpIHwgMHg4MCk7XG4gICAgICAgIH1cbiAgICAgICAgdXRmOC5wdXNoKChjb2RlUG9pbnQgJiAweDNGKSB8IDB4ODApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHRoaXMuYWRkSW50OCgwKTtcbiAgdGhpcy5zdGFydFZlY3RvcigxLCB1dGY4Lmxlbmd0aCwgMSk7XG4gIHRoaXMuYmIuc2V0UG9zaXRpb24odGhpcy5zcGFjZSAtPSB1dGY4Lmxlbmd0aCk7XG4gIGZvciAodmFyIGkgPSAwLCBvZmZzZXQgPSB0aGlzLnNwYWNlLCBieXRlcyA9IHRoaXMuYmIuYnl0ZXMoKTsgaSA8IHV0ZjgubGVuZ3RoOyBpKyspIHtcbiAgICBieXRlc1tvZmZzZXQrK10gPSB1dGY4W2ldO1xuICB9XG4gIHJldHVybiB0aGlzLmVuZFZlY3RvcigpO1xufTtcblxuLyoqXG4gKiBBIGhlbHBlciBmdW5jdGlvbiB0byBhdm9pZCBnZW5lcmF0ZWQgY29kZSBkZXBlbmRpbmcgb24gdGhpcyBmaWxlIGRpcmVjdGx5LlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBsb3dcbiAqIEBwYXJhbSB7bnVtYmVyfSBoaWdoXG4gKiBAcmV0dXJucyB7IWZsYXRidWZmZXJzLkxvbmd9XG4gKi9cbmZsYXRidWZmZXJzLkJ1aWxkZXIucHJvdG90eXBlLmNyZWF0ZUxvbmcgPSBmdW5jdGlvbihsb3csIGhpZ2gpIHtcbiAgcmV0dXJuIGZsYXRidWZmZXJzLkxvbmcuY3JlYXRlKGxvdywgaGlnaCk7XG59O1xuLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cbi8vLyBAY29uZCBGTEFUQlVGRkVSU19JTlRFUk5BTFxuLyoqXG4gKiBDcmVhdGUgYSBuZXcgQnl0ZUJ1ZmZlciB3aXRoIGEgZ2l2ZW4gYXJyYXkgb2YgYnl0ZXMgKGBVaW50OEFycmF5YCkuXG4gKlxuICogQGNvbnN0cnVjdG9yXG4gKiBAcGFyYW0ge1VpbnQ4QXJyYXl9IGJ5dGVzXG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIgPSBmdW5jdGlvbihieXRlcykge1xuICAvKipcbiAgICogQHR5cGUge1VpbnQ4QXJyYXl9XG4gICAqIEBwcml2YXRlXG4gICAqL1xuICB0aGlzLmJ5dGVzXyA9IGJ5dGVzO1xuXG4gIC8qKlxuICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgdGhpcy5wb3NpdGlvbl8gPSAwO1xufTtcblxuLyoqXG4gKiBDcmVhdGUgYW5kIGFsbG9jYXRlIGEgbmV3IEJ5dGVCdWZmZXIgd2l0aCBhIGdpdmVuIHNpemUuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IGJ5dGVfc2l6ZVxuICogQHJldHVybnMgeyFmbGF0YnVmZmVycy5CeXRlQnVmZmVyfVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLmFsbG9jYXRlID0gZnVuY3Rpb24oYnl0ZV9zaXplKSB7XG4gIHJldHVybiBuZXcgZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlcihuZXcgVWludDhBcnJheShieXRlX3NpemUpKTtcbn07XG5cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMucG9zaXRpb25fID0gMDtcbn07XG5cbi8qKlxuICogR2V0IHRoZSB1bmRlcmx5aW5nIGBVaW50OEFycmF5YC5cbiAqXG4gKiBAcmV0dXJucyB7VWludDhBcnJheX1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUuYnl0ZXMgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHRoaXMuYnl0ZXNfO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGJ1ZmZlcidzIHBvc2l0aW9uLlxuICpcbiAqIEByZXR1cm5zIHtudW1iZXJ9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLnBvc2l0aW9uID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLnBvc2l0aW9uXztcbn07XG5cbi8qKlxuICogU2V0IHRoZSBidWZmZXIncyBwb3NpdGlvbi5cbiAqXG4gKiBAcGFyYW0ge251bWJlcn0gcG9zaXRpb25cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUuc2V0UG9zaXRpb24gPSBmdW5jdGlvbihwb3NpdGlvbikge1xuICB0aGlzLnBvc2l0aW9uXyA9IHBvc2l0aW9uO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIGJ1ZmZlcidzIGNhcGFjaXR5LlxuICpcbiAqIEByZXR1cm5zIHtudW1iZXJ9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLmNhcGFjaXR5ID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiB0aGlzLmJ5dGVzXy5sZW5ndGg7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqIEByZXR1cm5zIHtudW1iZXJ9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLnJlYWRJbnQ4ID0gZnVuY3Rpb24ob2Zmc2V0KSB7XG4gIHJldHVybiB0aGlzLnJlYWRVaW50OChvZmZzZXQpIDw8IDI0ID4+IDI0O1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcmV0dXJucyB7bnVtYmVyfVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS5yZWFkVWludDggPSBmdW5jdGlvbihvZmZzZXQpIHtcbiAgcmV0dXJuIHRoaXMuYnl0ZXNfW29mZnNldF07XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqIEByZXR1cm5zIHtudW1iZXJ9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNiA9IGZ1bmN0aW9uKG9mZnNldCkge1xuICByZXR1cm4gdGhpcy5yZWFkVWludDE2KG9mZnNldCkgPDwgMTYgPj4gMTY7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqIEByZXR1cm5zIHtudW1iZXJ9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLnJlYWRVaW50MTYgPSBmdW5jdGlvbihvZmZzZXQpIHtcbiAgcmV0dXJuIHRoaXMuYnl0ZXNfW29mZnNldF0gfCB0aGlzLmJ5dGVzX1tvZmZzZXQgKyAxXSA8PCA4O1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcmV0dXJucyB7bnVtYmVyfVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MzIgPSBmdW5jdGlvbihvZmZzZXQpIHtcbiAgcmV0dXJuIHRoaXMuYnl0ZXNfW29mZnNldF0gfCB0aGlzLmJ5dGVzX1tvZmZzZXQgKyAxXSA8PCA4IHwgdGhpcy5ieXRlc19bb2Zmc2V0ICsgMl0gPDwgMTYgfCB0aGlzLmJ5dGVzX1tvZmZzZXQgKyAzXSA8PCAyNDtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHJldHVybnMge251bWJlcn1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUucmVhZFVpbnQzMiA9IGZ1bmN0aW9uKG9mZnNldCkge1xuICByZXR1cm4gdGhpcy5yZWFkSW50MzIob2Zmc2V0KSA+Pj4gMDtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHJldHVybnMgeyFmbGF0YnVmZmVycy5Mb25nfVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50NjQgPSBmdW5jdGlvbihvZmZzZXQpIHtcbiAgcmV0dXJuIG5ldyBmbGF0YnVmZmVycy5Mb25nKHRoaXMucmVhZEludDMyKG9mZnNldCksIHRoaXMucmVhZEludDMyKG9mZnNldCArIDQpKTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHJldHVybnMgeyFmbGF0YnVmZmVycy5Mb25nfVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS5yZWFkVWludDY0ID0gZnVuY3Rpb24ob2Zmc2V0KSB7XG4gIHJldHVybiBuZXcgZmxhdGJ1ZmZlcnMuTG9uZyh0aGlzLnJlYWRVaW50MzIob2Zmc2V0KSwgdGhpcy5yZWFkVWludDMyKG9mZnNldCArIDQpKTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHJldHVybnMge251bWJlcn1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0MzIgPSBmdW5jdGlvbihvZmZzZXQpIHtcbiAgZmxhdGJ1ZmZlcnMuaW50MzJbMF0gPSB0aGlzLnJlYWRJbnQzMihvZmZzZXQpO1xuICByZXR1cm4gZmxhdGJ1ZmZlcnMuZmxvYXQzMlswXTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHJldHVybnMge251bWJlcn1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0NjQgPSBmdW5jdGlvbihvZmZzZXQpIHtcbiAgZmxhdGJ1ZmZlcnMuaW50MzJbZmxhdGJ1ZmZlcnMuaXNMaXR0bGVFbmRpYW4gPyAwIDogMV0gPSB0aGlzLnJlYWRJbnQzMihvZmZzZXQpO1xuICBmbGF0YnVmZmVycy5pbnQzMltmbGF0YnVmZmVycy5pc0xpdHRsZUVuZGlhbiA/IDEgOiAwXSA9IHRoaXMucmVhZEludDMyKG9mZnNldCArIDQpO1xuICByZXR1cm4gZmxhdGJ1ZmZlcnMuZmxvYXQ2NFswXTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHBhcmFtIHtudW1iZXJ8Ym9vbGVhbn0gdmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQ4ID0gZnVuY3Rpb24ob2Zmc2V0LCB2YWx1ZSkge1xuICB0aGlzLmJ5dGVzX1tvZmZzZXRdID0gLyoqIEB0eXBlIHtudW1iZXJ9ICovKHZhbHVlKTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLndyaXRlVWludDggPSBmdW5jdGlvbihvZmZzZXQsIHZhbHVlKSB7XG4gIHRoaXMuYnl0ZXNfW29mZnNldF0gPSB2YWx1ZTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTYgPSBmdW5jdGlvbihvZmZzZXQsIHZhbHVlKSB7XG4gIHRoaXMuYnl0ZXNfW29mZnNldF0gPSB2YWx1ZTtcbiAgdGhpcy5ieXRlc19bb2Zmc2V0ICsgMV0gPSB2YWx1ZSA+PiA4O1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUud3JpdGVVaW50MTYgPSBmdW5jdGlvbihvZmZzZXQsIHZhbHVlKSB7XG4gICAgdGhpcy5ieXRlc19bb2Zmc2V0XSA9IHZhbHVlO1xuICAgIHRoaXMuYnl0ZXNfW29mZnNldCArIDFdID0gdmFsdWUgPj4gODtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzIgPSBmdW5jdGlvbihvZmZzZXQsIHZhbHVlKSB7XG4gIHRoaXMuYnl0ZXNfW29mZnNldF0gPSB2YWx1ZTtcbiAgdGhpcy5ieXRlc19bb2Zmc2V0ICsgMV0gPSB2YWx1ZSA+PiA4O1xuICB0aGlzLmJ5dGVzX1tvZmZzZXQgKyAyXSA9IHZhbHVlID4+IDE2O1xuICB0aGlzLmJ5dGVzX1tvZmZzZXQgKyAzXSA9IHZhbHVlID4+IDI0O1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUud3JpdGVVaW50MzIgPSBmdW5jdGlvbihvZmZzZXQsIHZhbHVlKSB7XG4gICAgdGhpcy5ieXRlc19bb2Zmc2V0XSA9IHZhbHVlO1xuICAgIHRoaXMuYnl0ZXNfW29mZnNldCArIDFdID0gdmFsdWUgPj4gODtcbiAgICB0aGlzLmJ5dGVzX1tvZmZzZXQgKyAyXSA9IHZhbHVlID4+IDE2O1xuICAgIHRoaXMuYnl0ZXNfW29mZnNldCArIDNdID0gdmFsdWUgPj4gMjQ7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqIEBwYXJhbSB7ZmxhdGJ1ZmZlcnMuTG9uZ30gdmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQ2NCA9IGZ1bmN0aW9uKG9mZnNldCwgdmFsdWUpIHtcbiAgdGhpcy53cml0ZUludDMyKG9mZnNldCwgdmFsdWUubG93KTtcbiAgdGhpcy53cml0ZUludDMyKG9mZnNldCArIDQsIHZhbHVlLmhpZ2gpO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcGFyYW0ge2ZsYXRidWZmZXJzLkxvbmd9IHZhbHVlXG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLndyaXRlVWludDY0ID0gZnVuY3Rpb24ob2Zmc2V0LCB2YWx1ZSkge1xuICAgIHRoaXMud3JpdGVVaW50MzIob2Zmc2V0LCB2YWx1ZS5sb3cpO1xuICAgIHRoaXMud3JpdGVVaW50MzIob2Zmc2V0ICsgNCwgdmFsdWUuaGlnaCk7XG59O1xuXG4vKipcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0MzIgPSBmdW5jdGlvbihvZmZzZXQsIHZhbHVlKSB7XG4gIGZsYXRidWZmZXJzLmZsb2F0MzJbMF0gPSB2YWx1ZTtcbiAgdGhpcy53cml0ZUludDMyKG9mZnNldCwgZmxhdGJ1ZmZlcnMuaW50MzJbMF0pO1xufTtcblxuLyoqXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUud3JpdGVGbG9hdDY0ID0gZnVuY3Rpb24ob2Zmc2V0LCB2YWx1ZSkge1xuICBmbGF0YnVmZmVycy5mbG9hdDY0WzBdID0gdmFsdWU7XG4gIHRoaXMud3JpdGVJbnQzMihvZmZzZXQsIGZsYXRidWZmZXJzLmludDMyW2ZsYXRidWZmZXJzLmlzTGl0dGxlRW5kaWFuID8gMCA6IDFdKTtcbiAgdGhpcy53cml0ZUludDMyKG9mZnNldCArIDQsIGZsYXRidWZmZXJzLmludDMyW2ZsYXRidWZmZXJzLmlzTGl0dGxlRW5kaWFuID8gMSA6IDBdKTtcbn07XG5cbi8qKlxuICogUmV0dXJuIHRoZSBmaWxlIGlkZW50aWZpZXIuICAgQmVoYXZpb3IgaXMgdW5kZWZpbmVkIGZvciBGbGF0QnVmZmVycyB3aG9zZVxuICogc2NoZW1hIGRvZXMgbm90IGluY2x1ZGUgYSBmaWxlX2lkZW50aWZpZXIgKGxpa2VseSBwb2ludHMgYXQgcGFkZGluZyBvciB0aGVcbiAqIHN0YXJ0IG9mIGEgdGhlIHJvb3QgdnRhYmxlKS5cbiAqIEByZXR1cm5zIHtzdHJpbmd9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLmdldEJ1ZmZlcklkZW50aWZpZXIgPSBmdW5jdGlvbigpIHtcbiAgaWYgKHRoaXMuYnl0ZXNfLmxlbmd0aCA8IHRoaXMucG9zaXRpb25fICsgZmxhdGJ1ZmZlcnMuU0laRU9GX0lOVCArXG4gICAgICBmbGF0YnVmZmVycy5GSUxFX0lERU5USUZJRVJfTEVOR1RIKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnRmxhdEJ1ZmZlcnM6IEJ5dGVCdWZmZXIgaXMgdG9vIHNob3J0IHRvIGNvbnRhaW4gYW4gaWRlbnRpZmllci4nKTtcbiAgfVxuICB2YXIgcmVzdWx0ID0gXCJcIjtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBmbGF0YnVmZmVycy5GSUxFX0lERU5USUZJRVJfTEVOR1RIOyBpKyspIHtcbiAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShcbiAgICAgICAgdGhpcy5yZWFkSW50OCh0aGlzLnBvc2l0aW9uXyArIGZsYXRidWZmZXJzLlNJWkVPRl9JTlQgKyBpKSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbi8qKlxuICogTG9vayB1cCBhIGZpZWxkIGluIHRoZSB2dGFibGUsIHJldHVybiBhbiBvZmZzZXQgaW50byB0aGUgb2JqZWN0LCBvciAwIGlmIHRoZVxuICogZmllbGQgaXMgbm90IHByZXNlbnQuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IGJiX3Bvc1xuICogQHBhcmFtIHtudW1iZXJ9IHZ0YWJsZV9vZmZzZXRcbiAqIEByZXR1cm5zIHtudW1iZXJ9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLl9fb2Zmc2V0ID0gZnVuY3Rpb24oYmJfcG9zLCB2dGFibGVfb2Zmc2V0KSB7XG4gIHZhciB2dGFibGUgPSBiYl9wb3MgLSB0aGlzLnJlYWRJbnQzMihiYl9wb3MpO1xuICByZXR1cm4gdnRhYmxlX29mZnNldCA8IHRoaXMucmVhZEludDE2KHZ0YWJsZSkgPyB0aGlzLnJlYWRJbnQxNih2dGFibGUgKyB2dGFibGVfb2Zmc2V0KSA6IDA7XG59O1xuXG4vKipcbiAqIEluaXRpYWxpemUgYW55IFRhYmxlLWRlcml2ZWQgdHlwZSB0byBwb2ludCB0byB0aGUgdW5pb24gYXQgdGhlIGdpdmVuIG9mZnNldC5cbiAqXG4gKiBAcGFyYW0ge2ZsYXRidWZmZXJzLlRhYmxlfSB0XG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcmV0dXJucyB7ZmxhdGJ1ZmZlcnMuVGFibGV9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLl9fdW5pb24gPSBmdW5jdGlvbih0LCBvZmZzZXQpIHtcbiAgdC5iYl9wb3MgPSBvZmZzZXQgKyB0aGlzLnJlYWRJbnQzMihvZmZzZXQpO1xuICB0LmJiID0gdGhpcztcbiAgcmV0dXJuIHQ7XG59O1xuXG4vKipcbiAqIENyZWF0ZSBhIEphdmFTY3JpcHQgc3RyaW5nIGZyb20gVVRGLTggZGF0YSBzdG9yZWQgaW5zaWRlIHRoZSBGbGF0QnVmZmVyLlxuICogVGhpcyBhbGxvY2F0ZXMgYSBuZXcgc3RyaW5nIGFuZCBjb252ZXJ0cyB0byB3aWRlIGNoYXJzIHVwb24gZWFjaCBhY2Nlc3MuXG4gKlxuICogVG8gYXZvaWQgdGhlIGNvbnZlcnNpb24gdG8gVVRGLTE2LCBwYXNzIGZsYXRidWZmZXJzLkVuY29kaW5nLlVURjhfQllURVMgYXNcbiAqIHRoZSBcIm9wdGlvbmFsRW5jb2RpbmdcIiBhcmd1bWVudC4gVGhpcyBpcyB1c2VmdWwgZm9yIGF2b2lkaW5nIGNvbnZlcnNpb24gdG9cbiAqIGFuZCBmcm9tIFVURi0xNiB3aGVuIHRoZSBkYXRhIHdpbGwganVzdCBiZSBwYWNrYWdlZCBiYWNrIHVwIGluIGFub3RoZXJcbiAqIEZsYXRCdWZmZXIgbGF0ZXIgb24uXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHBhcmFtIHtmbGF0YnVmZmVycy5FbmNvZGluZz19IG9wdF9lbmNvZGluZyBEZWZhdWx0cyB0byBVVEYxNl9TVFJJTkdcbiAqIEByZXR1cm5zIHtzdHJpbmd8IVVpbnQ4QXJyYXl9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLl9fc3RyaW5nID0gZnVuY3Rpb24ob2Zmc2V0LCBvcHRfZW5jb2RpbmcpIHtcbiAgb2Zmc2V0ICs9IHRoaXMucmVhZEludDMyKG9mZnNldCk7XG5cbiAgdmFyIGxlbmd0aCA9IHRoaXMucmVhZEludDMyKG9mZnNldCk7XG4gIHZhciByZXN1bHQgPSAnJztcbiAgdmFyIGkgPSAwO1xuXG4gIG9mZnNldCArPSBmbGF0YnVmZmVycy5TSVpFT0ZfSU5UO1xuXG4gIGlmIChvcHRfZW5jb2RpbmcgPT09IGZsYXRidWZmZXJzLkVuY29kaW5nLlVURjhfQllURVMpIHtcbiAgICByZXR1cm4gdGhpcy5ieXRlc18uc3ViYXJyYXkob2Zmc2V0LCBvZmZzZXQgKyBsZW5ndGgpO1xuICB9XG5cbiAgd2hpbGUgKGkgPCBsZW5ndGgpIHtcbiAgICB2YXIgY29kZVBvaW50O1xuXG4gICAgLy8gRGVjb2RlIFVURi04XG4gICAgdmFyIGEgPSB0aGlzLnJlYWRVaW50OChvZmZzZXQgKyBpKyspO1xuICAgIGlmIChhIDwgMHhDMCkge1xuICAgICAgY29kZVBvaW50ID0gYTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGIgPSB0aGlzLnJlYWRVaW50OChvZmZzZXQgKyBpKyspO1xuICAgICAgaWYgKGEgPCAweEUwKSB7XG4gICAgICAgIGNvZGVQb2ludCA9XG4gICAgICAgICAgKChhICYgMHgxRikgPDwgNikgfFxuICAgICAgICAgIChiICYgMHgzRik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgYyA9IHRoaXMucmVhZFVpbnQ4KG9mZnNldCArIGkrKyk7XG4gICAgICAgIGlmIChhIDwgMHhGMCkge1xuICAgICAgICAgIGNvZGVQb2ludCA9XG4gICAgICAgICAgICAoKGEgJiAweDBGKSA8PCAxMikgfFxuICAgICAgICAgICAgKChiICYgMHgzRikgPDwgNikgfFxuICAgICAgICAgICAgKGMgJiAweDNGKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YXIgZCA9IHRoaXMucmVhZFVpbnQ4KG9mZnNldCArIGkrKyk7XG4gICAgICAgICAgY29kZVBvaW50ID1cbiAgICAgICAgICAgICgoYSAmIDB4MDcpIDw8IDE4KSB8XG4gICAgICAgICAgICAoKGIgJiAweDNGKSA8PCAxMikgfFxuICAgICAgICAgICAgKChjICYgMHgzRikgPDwgNikgfFxuICAgICAgICAgICAgKGQgJiAweDNGKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEVuY29kZSBVVEYtMTZcbiAgICBpZiAoY29kZVBvaW50IDwgMHgxMDAwMCkge1xuICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoY29kZVBvaW50KTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29kZVBvaW50IC09IDB4MTAwMDA7XG4gICAgICByZXN1bHQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShcbiAgICAgICAgKGNvZGVQb2ludCA+PiAxMCkgKyAweEQ4MDAsXG4gICAgICAgIChjb2RlUG9pbnQgJiAoKDEgPDwgMTApIC0gMSkpICsgMHhEQzAwKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufTtcblxuLyoqXG4gKiBSZXRyaWV2ZSB0aGUgcmVsYXRpdmUgb2Zmc2V0IHN0b3JlZCBhdCBcIm9mZnNldFwiXG4gKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XG4gKiBAcmV0dXJucyB7bnVtYmVyfVxuICovXG5mbGF0YnVmZmVycy5CeXRlQnVmZmVyLnByb3RvdHlwZS5fX2luZGlyZWN0ID0gZnVuY3Rpb24ob2Zmc2V0KSB7XG4gIHJldHVybiBvZmZzZXQgKyB0aGlzLnJlYWRJbnQzMihvZmZzZXQpO1xufTtcblxuLyoqXG4gKiBHZXQgdGhlIHN0YXJ0IG9mIGRhdGEgb2YgYSB2ZWN0b3Igd2hvc2Ugb2Zmc2V0IGlzIHN0b3JlZCBhdCBcIm9mZnNldFwiIGluIHRoaXMgb2JqZWN0LlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcbiAqIEByZXR1cm5zIHtudW1iZXJ9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLl9fdmVjdG9yID0gZnVuY3Rpb24ob2Zmc2V0KSB7XG4gIHJldHVybiBvZmZzZXQgKyB0aGlzLnJlYWRJbnQzMihvZmZzZXQpICsgZmxhdGJ1ZmZlcnMuU0laRU9GX0lOVDsgLy8gZGF0YSBzdGFydHMgYWZ0ZXIgdGhlIGxlbmd0aFxufTtcblxuLyoqXG4gKiBHZXQgdGhlIGxlbmd0aCBvZiBhIHZlY3RvciB3aG9zZSBvZmZzZXQgaXMgc3RvcmVkIGF0IFwib2Zmc2V0XCIgaW4gdGhpcyBvYmplY3QuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IG9mZnNldFxuICogQHJldHVybnMge251bWJlcn1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUuX192ZWN0b3JfbGVuID0gZnVuY3Rpb24ob2Zmc2V0KSB7XG4gIHJldHVybiB0aGlzLnJlYWRJbnQzMihvZmZzZXQgKyB0aGlzLnJlYWRJbnQzMihvZmZzZXQpKTtcbn07XG5cbi8qKlxuICogQHBhcmFtIHtzdHJpbmd9IGlkZW50XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZmxhdGJ1ZmZlcnMuQnl0ZUJ1ZmZlci5wcm90b3R5cGUuX19oYXNfaWRlbnRpZmllciA9IGZ1bmN0aW9uKGlkZW50KSB7XG4gIGlmIChpZGVudC5sZW5ndGggIT0gZmxhdGJ1ZmZlcnMuRklMRV9JREVOVElGSUVSX0xFTkdUSCkge1xuICAgIHRocm93IG5ldyBFcnJvcignRmxhdEJ1ZmZlcnM6IGZpbGUgaWRlbnRpZmllciBtdXN0IGJlIGxlbmd0aCAnICtcbiAgICAgICAgICAgICAgICAgICAgZmxhdGJ1ZmZlcnMuRklMRV9JREVOVElGSUVSX0xFTkdUSCk7XG4gIH1cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBmbGF0YnVmZmVycy5GSUxFX0lERU5USUZJRVJfTEVOR1RIOyBpKyspIHtcbiAgICBpZiAoaWRlbnQuY2hhckNvZGVBdChpKSAhPSB0aGlzLnJlYWRJbnQ4KHRoaXMucG9zaXRpb25fICsgZmxhdGJ1ZmZlcnMuU0laRU9GX0lOVCArIGkpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG4gIHJldHVybiB0cnVlO1xufTtcblxuLyoqXG4gKiBBIGhlbHBlciBmdW5jdGlvbiB0byBhdm9pZCBnZW5lcmF0ZWQgY29kZSBkZXBlbmRpbmcgb24gdGhpcyBmaWxlIGRpcmVjdGx5LlxuICpcbiAqIEBwYXJhbSB7bnVtYmVyfSBsb3dcbiAqIEBwYXJhbSB7bnVtYmVyfSBoaWdoXG4gKiBAcmV0dXJucyB7IWZsYXRidWZmZXJzLkxvbmd9XG4gKi9cbmZsYXRidWZmZXJzLkJ5dGVCdWZmZXIucHJvdG90eXBlLmNyZWF0ZUxvbmcgPSBmdW5jdGlvbihsb3csIGhpZ2gpIHtcbiAgcmV0dXJuIGZsYXRidWZmZXJzLkxvbmcuY3JlYXRlKGxvdywgaGlnaCk7XG59O1xuXG4vLyBFeHBvcnRzIGZvciBOb2RlLmpzIGFuZCBSZXF1aXJlSlNcbmV4cG9ydCB7IGZsYXRidWZmZXJzIH07XG5cbi8vLyBAZW5kY29uZFxuLy8vIEB9XG4iLCIvLyBUaGUgbW9kdWxlIGNhY2hlXG52YXIgX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fID0ge307XG5cbi8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG5mdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuXHR2YXIgY2FjaGVkTW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXTtcblx0aWYgKGNhY2hlZE1vZHVsZSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0cmV0dXJuIGNhY2hlZE1vZHVsZS5leHBvcnRzO1xuXHR9XG5cdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG5cdHZhciBtb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdID0ge1xuXHRcdC8vIG5vIG1vZHVsZS5pZCBuZWVkZWRcblx0XHQvLyBubyBtb2R1bGUubG9hZGVkIG5lZWRlZFxuXHRcdGV4cG9ydHM6IHt9XG5cdH07XG5cblx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG5cdF9fd2VicGFja19tb2R1bGVzX19bbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG5cdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG5cdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbn1cblxuIiwiLy8gZ2V0RGVmYXVsdEV4cG9ydCBmdW5jdGlvbiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1oYXJtb255IG1vZHVsZXNcbl9fd2VicGFja19yZXF1aXJlX18ubiA9IChtb2R1bGUpID0+IHtcblx0dmFyIGdldHRlciA9IG1vZHVsZSAmJiBtb2R1bGUuX19lc01vZHVsZSA/XG5cdFx0KCkgPT4gKG1vZHVsZVsnZGVmYXVsdCddKSA6XG5cdFx0KCkgPT4gKG1vZHVsZSk7XG5cdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsIHsgYTogZ2V0dGVyIH0pO1xuXHRyZXR1cm4gZ2V0dGVyO1xufTsiLCIvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9ucyBmb3IgaGFybW9ueSBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSAoZXhwb3J0cywgZGVmaW5pdGlvbikgPT4ge1xuXHRmb3IodmFyIGtleSBpbiBkZWZpbml0aW9uKSB7XG5cdFx0aWYoX193ZWJwYWNrX3JlcXVpcmVfXy5vKGRlZmluaXRpb24sIGtleSkgJiYgIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBrZXkpKSB7XG5cdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywga2V5LCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZGVmaW5pdGlvbltrZXldIH0pO1xuXHRcdH1cblx0fVxufTsiLCJfX3dlYnBhY2tfcmVxdWlyZV9fLmcgPSAoZnVuY3Rpb24oKSB7XG5cdGlmICh0eXBlb2YgZ2xvYmFsVGhpcyA9PT0gJ29iamVjdCcpIHJldHVybiBnbG9iYWxUaGlzO1xuXHR0cnkge1xuXHRcdHJldHVybiB0aGlzIHx8IG5ldyBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0aWYgKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnKSByZXR1cm4gd2luZG93O1xuXHR9XG59KSgpOyIsIl9fd2VicGFja19yZXF1aXJlX18ubyA9IChvYmosIHByb3ApID0+IChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKSkiLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCIiLCIvLyBzdGFydHVwXG4vLyBMb2FkIGVudHJ5IG1vZHVsZSBhbmQgcmV0dXJuIGV4cG9ydHNcbi8vIFRoaXMgZW50cnkgbW9kdWxlIGlzIHJlZmVyZW5jZWQgYnkgb3RoZXIgbW9kdWxlcyBzbyBpdCBjYW4ndCBiZSBpbmxpbmVkXG52YXIgX193ZWJwYWNrX2V4cG9ydHNfXyA9IF9fd2VicGFja19yZXF1aXJlX18oXCIuL2xpYi9pbmRleC50c1wiKTtcbiIsIiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ== + +globalThis.ort = module.exports || exports || this.ort; +ort.env.wasm.numThreads = 2; +ort.env.wasm.proxy = true; +ort.env.wasm.wasmPaths = 'node_modules/onnxruntime-web/dist/'; \ No newline at end of file diff --git a/graalwasm/graalwasm-onnx-runtime/src/main/resources/script.js b/graalwasm/graalwasm-onnx-runtime/src/main/resources/script.js new file mode 100644 index 00000000..1d794b93 --- /dev/null +++ b/graalwasm/graalwasm-onnx-runtime/src/main/resources/script.js @@ -0,0 +1,28 @@ +let session = null ; +async function predict(modelBuffer,dataX,dataY) { + try { + + const session = await ort.InferenceSession.create(new Uint8Array(modelBuffer)); + + // prepare inputs. a tensor need its corresponding TypedArray as data + const dataA = Float32Array.from(dataX); + const dataB = Float32Array.from(dataY); + const tensorA = new ort.Tensor('float32', dataA, [3, 4]); + const tensorB = new ort.Tensor('float32', dataB, [4, 3]); + + // prepare feeds. use model input names as keys. + const feeds = { a: tensorA, b: tensorB }; + + // feed inputs and run + const results = await session.run(feeds); + + // read from results + const dataC = results.c.data; + console.log(dataC); + + return dataC; + } catch (e) { + document.write(`failed to inference ONNX model: ${e}.`); + } + +} \ No newline at end of file