| /* Sinon.JS 20.0.0, 2025-03-24, @license BSD-3 */(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.sinon = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){ |
| "use strict"; |
| |
| const behavior = require("./sinon/behavior"); |
| const createSandbox = require("./sinon/create-sandbox"); |
| const extend = require("./sinon/util/core/extend"); |
| const fakeTimers = require("./sinon/util/fake-timers"); |
| const Sandbox = require("./sinon/sandbox"); |
| const stub = require("./sinon/stub"); |
| const promise = require("./sinon/promise"); |
| |
| /** |
| * @returns {object} a configured sandbox |
| */ |
| module.exports = function createApi() { |
| const apiMethods = { |
| createSandbox: createSandbox, |
| match: require("@sinonjs/samsam").createMatcher, |
| restoreObject: require("./sinon/restore-object"), |
| |
| expectation: require("./sinon/mock-expectation"), |
| |
| // fake timers |
| timers: fakeTimers.timers, |
| |
| addBehavior: function (name, fn) { |
| behavior.addBehavior(stub, name, fn); |
| }, |
| |
| // fake promise |
| promise: promise, |
| }; |
| |
| const sandbox = new Sandbox(); |
| return extend(sandbox, apiMethods); |
| }; |
| |
| },{"./sinon/behavior":4,"./sinon/create-sandbox":7,"./sinon/mock-expectation":11,"./sinon/promise":13,"./sinon/restore-object":18,"./sinon/sandbox":19,"./sinon/stub":22,"./sinon/util/core/extend":25,"./sinon/util/fake-timers":39,"@sinonjs/samsam":86}],2:[function(require,module,exports){ |
| "use strict"; |
| |
| const createApi = require("./create-sinon-api"); |
| |
| module.exports = createApi(); |
| |
| },{"./create-sinon-api":1}],3:[function(require,module,exports){ |
| "use strict"; |
| /** @module */ |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const calledInOrder = require("@sinonjs/commons").calledInOrder; |
| const createMatcher = require("@sinonjs/samsam").createMatcher; |
| const orderByFirstCall = require("@sinonjs/commons").orderByFirstCall; |
| const timesInWords = require("./util/core/times-in-words"); |
| const inspect = require("util").inspect; |
| const stringSlice = require("@sinonjs/commons").prototypes.string.slice; |
| const globalObject = require("@sinonjs/commons").global; |
| |
| const arraySlice = arrayProto.slice; |
| const concat = arrayProto.concat; |
| const forEach = arrayProto.forEach; |
| const join = arrayProto.join; |
| const splice = arrayProto.splice; |
| |
| function applyDefaults(obj, defaults) { |
| for (const key of Object.keys(defaults)) { |
| const val = obj[key]; |
| if (val === null || typeof val === "undefined") { |
| obj[key] = defaults[key]; |
| } |
| } |
| } |
| |
| /** |
| * @typedef {object} CreateAssertOptions |
| * @global |
| * |
| * @property {boolean} [shouldLimitAssertionLogs] default is false |
| * @property {number} [assertionLogLimit] default is 10K |
| */ |
| |
| /** |
| * Create an assertion object that exposes several methods to invoke |
| * |
| * @param {CreateAssertOptions} [opts] options bag |
| * @returns {object} object with multiple assertion methods |
| */ |
| function createAssertObject(opts) { |
| const cleanedAssertOptions = opts || {}; |
| applyDefaults(cleanedAssertOptions, { |
| shouldLimitAssertionLogs: false, |
| assertionLogLimit: 1e4, |
| }); |
| |
| const assert = { |
| failException: "AssertError", |
| |
| fail: function fail(message) { |
| let msg = message; |
| if (cleanedAssertOptions.shouldLimitAssertionLogs) { |
| msg = message.substring( |
| 0, |
| cleanedAssertOptions.assertionLogLimit, |
| ); |
| } |
| const error = new Error(msg); |
| error.name = this.failException || assert.failException; |
| |
| throw error; |
| }, |
| |
| pass: function pass() { |
| return; |
| }, |
| |
| callOrder: function assertCallOrder() { |
| verifyIsStub.apply(null, arguments); |
| let expected = ""; |
| let actual = ""; |
| |
| if (!calledInOrder(arguments)) { |
| try { |
| expected = join(arguments, ", "); |
| const calls = arraySlice(arguments); |
| let i = calls.length; |
| while (i) { |
| if (!calls[--i].called) { |
| splice(calls, i, 1); |
| } |
| } |
| actual = join(orderByFirstCall(calls), ", "); |
| } catch (e) { |
| // If this fails, we'll just fall back to the blank string |
| } |
| |
| failAssertion( |
| this, |
| `expected ${expected} to be called in order but were called as ${actual}`, |
| ); |
| } else { |
| assert.pass("callOrder"); |
| } |
| }, |
| |
| callCount: function assertCallCount(method, count) { |
| verifyIsStub(method); |
| |
| let msg; |
| if (typeof count !== "number") { |
| msg = |
| `expected ${inspect(count)} to be a number ` + |
| `but was of type ${typeof count}`; |
| failAssertion(this, msg); |
| } else if (method.callCount !== count) { |
| msg = |
| `expected %n to be called ${timesInWords(count)} ` + |
| `but was called %c%C`; |
| failAssertion(this, method.printf(msg)); |
| } else { |
| assert.pass("callCount"); |
| } |
| }, |
| |
| expose: function expose(target, options) { |
| if (!target) { |
| throw new TypeError("target is null or undefined"); |
| } |
| |
| const o = options || {}; |
| const prefix = |
| (typeof o.prefix === "undefined" && "assert") || o.prefix; |
| const includeFail = |
| typeof o.includeFail === "undefined" || Boolean(o.includeFail); |
| const instance = this; |
| |
| forEach(Object.keys(instance), function (method) { |
| if ( |
| method !== "expose" && |
| (includeFail || !/^(fail)/.test(method)) |
| ) { |
| target[exposedName(prefix, method)] = instance[method]; |
| } |
| }); |
| |
| return target; |
| }, |
| |
| match: function match(actual, expectation) { |
| const matcher = createMatcher(expectation); |
| if (matcher.test(actual)) { |
| assert.pass("match"); |
| } else { |
| const formatted = [ |
| "expected value to match", |
| ` expected = ${inspect(expectation)}`, |
| ` actual = ${inspect(actual)}`, |
| ]; |
| |
| failAssertion(this, join(formatted, "\n")); |
| } |
| }, |
| }; |
| |
| function verifyIsStub() { |
| const args = arraySlice(arguments); |
| |
| forEach(args, function (method) { |
| if (!method) { |
| assert.fail("fake is not a spy"); |
| } |
| |
| if (method.proxy && method.proxy.isSinonProxy) { |
| verifyIsStub(method.proxy); |
| } else { |
| if (typeof method !== "function") { |
| assert.fail(`${method} is not a function`); |
| } |
| |
| if (typeof method.getCall !== "function") { |
| assert.fail(`${method} is not stubbed`); |
| } |
| } |
| }); |
| } |
| |
| function verifyIsValidAssertion(assertionMethod, assertionArgs) { |
| switch (assertionMethod) { |
| case "notCalled": |
| case "called": |
| case "calledOnce": |
| case "calledTwice": |
| case "calledThrice": |
| if (assertionArgs.length !== 0) { |
| assert.fail( |
| `${assertionMethod} takes 1 argument but was called with ${ |
| assertionArgs.length + 1 |
| } arguments`, |
| ); |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| |
| function failAssertion(object, msg) { |
| const obj = object || globalObject; |
| const failMethod = obj.fail || assert.fail; |
| failMethod.call(obj, msg); |
| } |
| |
| function mirrorPropAsAssertion(name, method, message) { |
| let msg = message; |
| let meth = method; |
| if (arguments.length === 2) { |
| msg = method; |
| meth = name; |
| } |
| |
| assert[name] = function (fake) { |
| verifyIsStub(fake); |
| |
| const args = arraySlice(arguments, 1); |
| let failed = false; |
| |
| verifyIsValidAssertion(name, args); |
| |
| if (typeof meth === "function") { |
| failed = !meth(fake); |
| } else { |
| failed = |
| typeof fake[meth] === "function" |
| ? !fake[meth].apply(fake, args) |
| : !fake[meth]; |
| } |
| |
| if (failed) { |
| failAssertion( |
| this, |
| (fake.printf || fake.proxy.printf).apply( |
| fake, |
| concat([msg], args), |
| ), |
| ); |
| } else { |
| assert.pass(name); |
| } |
| }; |
| } |
| |
| function exposedName(prefix, prop) { |
| return !prefix || /^fail/.test(prop) |
| ? prop |
| : prefix + |
| stringSlice(prop, 0, 1).toUpperCase() + |
| stringSlice(prop, 1); |
| } |
| |
| mirrorPropAsAssertion( |
| "called", |
| "expected %n to have been called at least once but was never called", |
| ); |
| mirrorPropAsAssertion( |
| "notCalled", |
| function (spy) { |
| return !spy.called; |
| }, |
| "expected %n to not have been called but was called %c%C", |
| ); |
| mirrorPropAsAssertion( |
| "calledOnce", |
| "expected %n to be called once but was called %c%C", |
| ); |
| mirrorPropAsAssertion( |
| "calledTwice", |
| "expected %n to be called twice but was called %c%C", |
| ); |
| mirrorPropAsAssertion( |
| "calledThrice", |
| "expected %n to be called thrice but was called %c%C", |
| ); |
| mirrorPropAsAssertion( |
| "calledOn", |
| "expected %n to be called with %1 as this but was called with %t", |
| ); |
| mirrorPropAsAssertion( |
| "alwaysCalledOn", |
| "expected %n to always be called with %1 as this but was called with %t", |
| ); |
| mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new"); |
| mirrorPropAsAssertion( |
| "alwaysCalledWithNew", |
| "expected %n to always be called with new", |
| ); |
| mirrorPropAsAssertion( |
| "calledWith", |
| "expected %n to be called with arguments %D", |
| ); |
| mirrorPropAsAssertion( |
| "calledWithMatch", |
| "expected %n to be called with match %D", |
| ); |
| mirrorPropAsAssertion( |
| "alwaysCalledWith", |
| "expected %n to always be called with arguments %D", |
| ); |
| mirrorPropAsAssertion( |
| "alwaysCalledWithMatch", |
| "expected %n to always be called with match %D", |
| ); |
| mirrorPropAsAssertion( |
| "calledWithExactly", |
| "expected %n to be called with exact arguments %D", |
| ); |
| mirrorPropAsAssertion( |
| "calledOnceWithExactly", |
| "expected %n to be called once and with exact arguments %D", |
| ); |
| mirrorPropAsAssertion( |
| "calledOnceWithMatch", |
| "expected %n to be called once and with match %D", |
| ); |
| mirrorPropAsAssertion( |
| "alwaysCalledWithExactly", |
| "expected %n to always be called with exact arguments %D", |
| ); |
| mirrorPropAsAssertion( |
| "neverCalledWith", |
| "expected %n to never be called with arguments %*%C", |
| ); |
| mirrorPropAsAssertion( |
| "neverCalledWithMatch", |
| "expected %n to never be called with match %*%C", |
| ); |
| mirrorPropAsAssertion("threw", "%n did not throw exception%C"); |
| mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C"); |
| |
| return assert; |
| } |
| |
| module.exports = createAssertObject(); |
| module.exports.createAssertObject = createAssertObject; |
| |
| },{"./util/core/times-in-words":35,"@sinonjs/commons":46,"@sinonjs/samsam":86,"util":90}],4:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const extend = require("./util/core/extend"); |
| const functionName = require("@sinonjs/commons").functionName; |
| const nextTick = require("./util/core/next-tick"); |
| const valueToString = require("@sinonjs/commons").valueToString; |
| const exportAsyncBehaviors = require("./util/core/export-async-behaviors"); |
| |
| const concat = arrayProto.concat; |
| const join = arrayProto.join; |
| const reverse = arrayProto.reverse; |
| const slice = arrayProto.slice; |
| |
| const useLeftMostCallback = -1; |
| const useRightMostCallback = -2; |
| |
| function getCallback(behavior, args) { |
| const callArgAt = behavior.callArgAt; |
| |
| if (callArgAt >= 0) { |
| return args[callArgAt]; |
| } |
| |
| let argumentList; |
| |
| if (callArgAt === useLeftMostCallback) { |
| argumentList = args; |
| } |
| |
| if (callArgAt === useRightMostCallback) { |
| argumentList = reverse(slice(args)); |
| } |
| |
| const callArgProp = behavior.callArgProp; |
| |
| for (let i = 0, l = argumentList.length; i < l; ++i) { |
| if (!callArgProp && typeof argumentList[i] === "function") { |
| return argumentList[i]; |
| } |
| |
| if ( |
| callArgProp && |
| argumentList[i] && |
| typeof argumentList[i][callArgProp] === "function" |
| ) { |
| return argumentList[i][callArgProp]; |
| } |
| } |
| |
| return null; |
| } |
| |
| function getCallbackError(behavior, func, args) { |
| if (behavior.callArgAt < 0) { |
| let msg; |
| |
| if (behavior.callArgProp) { |
| msg = `${functionName( |
| behavior.stub, |
| )} expected to yield to '${valueToString( |
| behavior.callArgProp, |
| )}', but no object with such a property was passed.`; |
| } else { |
| msg = `${functionName( |
| behavior.stub, |
| )} expected to yield, but no callback was passed.`; |
| } |
| |
| if (args.length > 0) { |
| msg += ` Received [${join(args, ", ")}]`; |
| } |
| |
| return msg; |
| } |
| |
| return `argument at index ${behavior.callArgAt} is not a function: ${func}`; |
| } |
| |
| function ensureArgs(name, behavior, args) { |
| // map function name to internal property |
| // callsArg => callArgAt |
| const property = name.replace(/sArg/, "ArgAt"); |
| const index = behavior[property]; |
| |
| if (index >= args.length) { |
| throw new TypeError( |
| `${name} failed: ${index + 1} arguments required but only ${ |
| args.length |
| } present`, |
| ); |
| } |
| } |
| |
| function callCallback(behavior, args) { |
| if (typeof behavior.callArgAt === "number") { |
| ensureArgs("callsArg", behavior, args); |
| const func = getCallback(behavior, args); |
| |
| if (typeof func !== "function") { |
| throw new TypeError(getCallbackError(behavior, func, args)); |
| } |
| |
| if (behavior.callbackAsync) { |
| nextTick(function () { |
| func.apply( |
| behavior.callbackContext, |
| behavior.callbackArguments, |
| ); |
| }); |
| } else { |
| return func.apply( |
| behavior.callbackContext, |
| behavior.callbackArguments, |
| ); |
| } |
| } |
| |
| return undefined; |
| } |
| |
| const proto = { |
| create: function create(stub) { |
| const behavior = extend({}, proto); |
| delete behavior.create; |
| delete behavior.addBehavior; |
| delete behavior.createBehavior; |
| behavior.stub = stub; |
| |
| if (stub.defaultBehavior && stub.defaultBehavior.promiseLibrary) { |
| behavior.promiseLibrary = stub.defaultBehavior.promiseLibrary; |
| } |
| |
| return behavior; |
| }, |
| |
| isPresent: function isPresent() { |
| return ( |
| typeof this.callArgAt === "number" || |
| this.exception || |
| this.exceptionCreator || |
| typeof this.returnArgAt === "number" || |
| this.returnThis || |
| typeof this.resolveArgAt === "number" || |
| this.resolveThis || |
| typeof this.throwArgAt === "number" || |
| this.fakeFn || |
| this.returnValueDefined |
| ); |
| }, |
| |
| /*eslint complexity: ["error", 20]*/ |
| invoke: function invoke(context, args) { |
| /* |
| * callCallback (conditionally) calls ensureArgs |
| * |
| * Note: callCallback intentionally happens before |
| * everything else and cannot be moved lower |
| */ |
| const returnValue = callCallback(this, args); |
| |
| if (this.exception) { |
| throw this.exception; |
| } else if (this.exceptionCreator) { |
| this.exception = this.exceptionCreator(); |
| this.exceptionCreator = undefined; |
| throw this.exception; |
| } else if (typeof this.returnArgAt === "number") { |
| ensureArgs("returnsArg", this, args); |
| return args[this.returnArgAt]; |
| } else if (this.returnThis) { |
| return context; |
| } else if (typeof this.throwArgAt === "number") { |
| ensureArgs("throwsArg", this, args); |
| throw args[this.throwArgAt]; |
| } else if (this.fakeFn) { |
| return this.fakeFn.apply(context, args); |
| } else if (typeof this.resolveArgAt === "number") { |
| ensureArgs("resolvesArg", this, args); |
| return (this.promiseLibrary || Promise).resolve( |
| args[this.resolveArgAt], |
| ); |
| } else if (this.resolveThis) { |
| return (this.promiseLibrary || Promise).resolve(context); |
| } else if (this.resolve) { |
| return (this.promiseLibrary || Promise).resolve(this.returnValue); |
| } else if (this.reject) { |
| return (this.promiseLibrary || Promise).reject(this.returnValue); |
| } else if (this.callsThrough) { |
| const wrappedMethod = this.effectiveWrappedMethod(); |
| |
| return wrappedMethod.apply(context, args); |
| } else if (this.callsThroughWithNew) { |
| // Get the original method (assumed to be a constructor in this case) |
| const WrappedClass = this.effectiveWrappedMethod(); |
| // Turn the arguments object into a normal array |
| const argsArray = slice(args); |
| // Call the constructor |
| const F = WrappedClass.bind.apply( |
| WrappedClass, |
| concat([null], argsArray), |
| ); |
| return new F(); |
| } else if (typeof this.returnValue !== "undefined") { |
| return this.returnValue; |
| } else if (typeof this.callArgAt === "number") { |
| return returnValue; |
| } |
| |
| return this.returnValue; |
| }, |
| |
| effectiveWrappedMethod: function effectiveWrappedMethod() { |
| for (let stubb = this.stub; stubb; stubb = stubb.parent) { |
| if (stubb.wrappedMethod) { |
| return stubb.wrappedMethod; |
| } |
| } |
| throw new Error("Unable to find wrapped method"); |
| }, |
| |
| onCall: function onCall(index) { |
| return this.stub.onCall(index); |
| }, |
| |
| onFirstCall: function onFirstCall() { |
| return this.stub.onFirstCall(); |
| }, |
| |
| onSecondCall: function onSecondCall() { |
| return this.stub.onSecondCall(); |
| }, |
| |
| onThirdCall: function onThirdCall() { |
| return this.stub.onThirdCall(); |
| }, |
| |
| withArgs: function withArgs(/* arguments */) { |
| throw new Error( |
| 'Defining a stub by invoking "stub.onCall(...).withArgs(...)" ' + |
| 'is not supported. Use "stub.withArgs(...).onCall(...)" ' + |
| "to define sequential behavior for calls with certain arguments.", |
| ); |
| }, |
| }; |
| |
| function createBehavior(behaviorMethod) { |
| return function () { |
| this.defaultBehavior = this.defaultBehavior || proto.create(this); |
| this.defaultBehavior[behaviorMethod].apply( |
| this.defaultBehavior, |
| arguments, |
| ); |
| return this; |
| }; |
| } |
| |
| function addBehavior(stub, name, fn) { |
| proto[name] = function () { |
| fn.apply(this, concat([this], slice(arguments))); |
| return this.stub || this; |
| }; |
| |
| stub[name] = createBehavior(name); |
| } |
| |
| proto.addBehavior = addBehavior; |
| proto.createBehavior = createBehavior; |
| |
| const asyncBehaviors = exportAsyncBehaviors(proto); |
| |
| module.exports = extend.nonEnum({}, proto, asyncBehaviors); |
| |
| },{"./util/core/export-async-behaviors":24,"./util/core/extend":25,"./util/core/next-tick":33,"@sinonjs/commons":46}],5:[function(require,module,exports){ |
| "use strict"; |
| |
| const walk = require("./util/core/walk"); |
| const getPropertyDescriptor = require("./util/core/get-property-descriptor"); |
| const hasOwnProperty = |
| require("@sinonjs/commons").prototypes.object.hasOwnProperty; |
| const push = require("@sinonjs/commons").prototypes.array.push; |
| |
| function collectMethod(methods, object, prop, propOwner) { |
| if ( |
| typeof getPropertyDescriptor(propOwner, prop).value === "function" && |
| hasOwnProperty(object, prop) |
| ) { |
| push(methods, object[prop]); |
| } |
| } |
| |
| // This function returns an array of all the own methods on the passed object |
| function collectOwnMethods(object) { |
| const methods = []; |
| |
| walk(object, collectMethod.bind(null, methods, object)); |
| |
| return methods; |
| } |
| |
| module.exports = collectOwnMethods; |
| |
| },{"./util/core/get-property-descriptor":28,"./util/core/walk":37,"@sinonjs/commons":46}],6:[function(require,module,exports){ |
| "use strict"; |
| |
| module.exports = class Colorizer { |
| constructor(supportsColor = require("supports-color")) { |
| this.supportsColor = supportsColor; |
| } |
| |
| /** |
| * Should be renamed to true #privateField |
| * when we can ensure ES2022 support |
| * |
| * @private |
| */ |
| colorize(str, color) { |
| if (this.supportsColor.stdout === false) { |
| return str; |
| } |
| |
| return `\x1b[${color}m${str}\x1b[0m`; |
| } |
| |
| red(str) { |
| return this.colorize(str, 31); |
| } |
| |
| green(str) { |
| return this.colorize(str, 32); |
| } |
| |
| cyan(str) { |
| return this.colorize(str, 96); |
| } |
| |
| white(str) { |
| return this.colorize(str, 39); |
| } |
| |
| bold(str) { |
| return this.colorize(str, 1); |
| } |
| }; |
| |
| },{"supports-color":93}],7:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const Sandbox = require("./sandbox"); |
| |
| const forEach = arrayProto.forEach; |
| const push = arrayProto.push; |
| |
| function prepareSandboxFromConfig(config) { |
| const sandbox = new Sandbox({ assertOptions: config.assertOptions }); |
| |
| if (config.useFakeTimers) { |
| if (typeof config.useFakeTimers === "object") { |
| sandbox.useFakeTimers(config.useFakeTimers); |
| } else { |
| sandbox.useFakeTimers(); |
| } |
| } |
| |
| return sandbox; |
| } |
| |
| function exposeValue(sandbox, config, key, value) { |
| if (!value) { |
| return; |
| } |
| |
| if (config.injectInto && !(key in config.injectInto)) { |
| config.injectInto[key] = value; |
| push(sandbox.injectedKeys, key); |
| } else { |
| push(sandbox.args, value); |
| } |
| } |
| |
| /** |
| * Options to customize a sandbox |
| * |
| * The sandbox's methods can be injected into another object for |
| * convenience. The `injectInto` configuration option can name an |
| * object to add properties to. |
| * |
| * @typedef {object} SandboxConfig |
| * @property {string[]} properties The properties of the API to expose on the sandbox. Examples: ['spy', 'fake', 'restore'] |
| * @property {object} injectInto an object in which to inject properties from the sandbox (a facade). This is mostly an integration feature (sinon-test being one). |
| * @property {boolean} useFakeTimers whether timers are faked by default |
| * @property {object} [assertOptions] see CreateAssertOptions in ./assert |
| * |
| * This type def is really suffering from JSDoc not having standardized |
| * how to reference types defined in other modules :( |
| */ |
| |
| /** |
| * A configured sinon sandbox (private type) |
| * |
| * @typedef {object} ConfiguredSinonSandboxType |
| * @private |
| * @augments Sandbox |
| * @property {string[]} injectedKeys the keys that have been injected (from config.injectInto) |
| * @property {*[]} args the arguments for the sandbox |
| */ |
| |
| /** |
| * Create a sandbox |
| * |
| * As of Sinon 5 the `sinon` instance itself is a Sandbox, so you |
| * hardly ever need to create additional instances for the sake of testing |
| * |
| * @param config {SandboxConfig} |
| * @returns {Sandbox} |
| */ |
| function createSandbox(config) { |
| if (!config) { |
| return new Sandbox(); |
| } |
| |
| const configuredSandbox = prepareSandboxFromConfig(config); |
| configuredSandbox.args = configuredSandbox.args || []; |
| configuredSandbox.injectedKeys = []; |
| configuredSandbox.injectInto = config.injectInto; |
| const exposed = configuredSandbox.inject({}); |
| |
| if (config.properties) { |
| forEach(config.properties, function (prop) { |
| const value = |
| exposed[prop] || (prop === "sandbox" && configuredSandbox); |
| exposeValue(configuredSandbox, config, prop, value); |
| }); |
| } else { |
| exposeValue(configuredSandbox, config, "sandbox"); |
| } |
| |
| return configuredSandbox; |
| } |
| |
| module.exports = createSandbox; |
| |
| },{"./sandbox":19,"@sinonjs/commons":46}],8:[function(require,module,exports){ |
| "use strict"; |
| |
| const stub = require("./stub"); |
| const sinonType = require("./util/core/sinon-type"); |
| const forEach = require("@sinonjs/commons").prototypes.array.forEach; |
| |
| function isStub(value) { |
| return sinonType.get(value) === "stub"; |
| } |
| |
| module.exports = function createStubInstance(constructor, overrides) { |
| if (typeof constructor !== "function") { |
| throw new TypeError("The constructor should be a function."); |
| } |
| |
| const stubInstance = Object.create(constructor.prototype); |
| sinonType.set(stubInstance, "stub-instance"); |
| |
| const stubbedObject = stub(stubInstance); |
| |
| forEach(Object.keys(overrides || {}), function (propertyName) { |
| if (propertyName in stubbedObject) { |
| const value = overrides[propertyName]; |
| if (isStub(value)) { |
| stubbedObject[propertyName] = value; |
| } else { |
| stubbedObject[propertyName].returns(value); |
| } |
| } else { |
| throw new Error( |
| `Cannot stub ${propertyName}. Property does not exist!`, |
| ); |
| } |
| }); |
| return stubbedObject; |
| }; |
| |
| },{"./stub":22,"./util/core/sinon-type":34,"@sinonjs/commons":46}],9:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const isPropertyConfigurable = require("./util/core/is-property-configurable"); |
| const exportAsyncBehaviors = require("./util/core/export-async-behaviors"); |
| const extend = require("./util/core/extend"); |
| |
| const slice = arrayProto.slice; |
| |
| const useLeftMostCallback = -1; |
| const useRightMostCallback = -2; |
| |
| function throwsException(fake, error, message) { |
| if (typeof error === "function") { |
| fake.exceptionCreator = error; |
| } else if (typeof error === "string") { |
| fake.exceptionCreator = function () { |
| const newException = new Error( |
| message || `Sinon-provided ${error}`, |
| ); |
| newException.name = error; |
| return newException; |
| }; |
| } else if (!error) { |
| fake.exceptionCreator = function () { |
| return new Error("Error"); |
| }; |
| } else { |
| fake.exception = error; |
| } |
| } |
| |
| const defaultBehaviors = { |
| callsFake: function callsFake(fake, fn) { |
| fake.fakeFn = fn; |
| fake.exception = undefined; |
| fake.exceptionCreator = undefined; |
| fake.callsThrough = false; |
| }, |
| |
| callsArg: function callsArg(fake, index) { |
| if (typeof index !== "number") { |
| throw new TypeError("argument index is not number"); |
| } |
| |
| fake.callArgAt = index; |
| fake.callbackArguments = []; |
| fake.callbackContext = undefined; |
| fake.callArgProp = undefined; |
| fake.callbackAsync = false; |
| fake.callsThrough = false; |
| }, |
| |
| callsArgOn: function callsArgOn(fake, index, context) { |
| if (typeof index !== "number") { |
| throw new TypeError("argument index is not number"); |
| } |
| |
| fake.callArgAt = index; |
| fake.callbackArguments = []; |
| fake.callbackContext = context; |
| fake.callArgProp = undefined; |
| fake.callbackAsync = false; |
| fake.callsThrough = false; |
| }, |
| |
| callsArgWith: function callsArgWith(fake, index) { |
| if (typeof index !== "number") { |
| throw new TypeError("argument index is not number"); |
| } |
| |
| fake.callArgAt = index; |
| fake.callbackArguments = slice(arguments, 2); |
| fake.callbackContext = undefined; |
| fake.callArgProp = undefined; |
| fake.callbackAsync = false; |
| fake.callsThrough = false; |
| }, |
| |
| callsArgOnWith: function callsArgWith(fake, index, context) { |
| if (typeof index !== "number") { |
| throw new TypeError("argument index is not number"); |
| } |
| |
| fake.callArgAt = index; |
| fake.callbackArguments = slice(arguments, 3); |
| fake.callbackContext = context; |
| fake.callArgProp = undefined; |
| fake.callbackAsync = false; |
| fake.callsThrough = false; |
| }, |
| |
| yields: function (fake) { |
| fake.callArgAt = useLeftMostCallback; |
| fake.callbackArguments = slice(arguments, 1); |
| fake.callbackContext = undefined; |
| fake.callArgProp = undefined; |
| fake.callbackAsync = false; |
| fake.fakeFn = undefined; |
| fake.callsThrough = false; |
| }, |
| |
| yieldsRight: function (fake) { |
| fake.callArgAt = useRightMostCallback; |
| fake.callbackArguments = slice(arguments, 1); |
| fake.callbackContext = undefined; |
| fake.callArgProp = undefined; |
| fake.callbackAsync = false; |
| fake.callsThrough = false; |
| fake.fakeFn = undefined; |
| }, |
| |
| yieldsOn: function (fake, context) { |
| fake.callArgAt = useLeftMostCallback; |
| fake.callbackArguments = slice(arguments, 2); |
| fake.callbackContext = context; |
| fake.callArgProp = undefined; |
| fake.callbackAsync = false; |
| fake.callsThrough = false; |
| fake.fakeFn = undefined; |
| }, |
| |
| yieldsTo: function (fake, prop) { |
| fake.callArgAt = useLeftMostCallback; |
| fake.callbackArguments = slice(arguments, 2); |
| fake.callbackContext = undefined; |
| fake.callArgProp = prop; |
| fake.callbackAsync = false; |
| fake.callsThrough = false; |
| fake.fakeFn = undefined; |
| }, |
| |
| yieldsToOn: function (fake, prop, context) { |
| fake.callArgAt = useLeftMostCallback; |
| fake.callbackArguments = slice(arguments, 3); |
| fake.callbackContext = context; |
| fake.callArgProp = prop; |
| fake.callbackAsync = false; |
| fake.fakeFn = undefined; |
| }, |
| |
| throws: throwsException, |
| throwsException: throwsException, |
| |
| returns: function returns(fake, value) { |
| fake.callsThrough = false; |
| fake.returnValue = value; |
| fake.resolve = false; |
| fake.reject = false; |
| fake.returnValueDefined = true; |
| fake.exception = undefined; |
| fake.exceptionCreator = undefined; |
| fake.fakeFn = undefined; |
| }, |
| |
| returnsArg: function returnsArg(fake, index) { |
| if (typeof index !== "number") { |
| throw new TypeError("argument index is not number"); |
| } |
| fake.callsThrough = false; |
| |
| fake.returnArgAt = index; |
| }, |
| |
| throwsArg: function throwsArg(fake, index) { |
| if (typeof index !== "number") { |
| throw new TypeError("argument index is not number"); |
| } |
| fake.callsThrough = false; |
| |
| fake.throwArgAt = index; |
| }, |
| |
| returnsThis: function returnsThis(fake) { |
| fake.returnThis = true; |
| fake.callsThrough = false; |
| }, |
| |
| resolves: function resolves(fake, value) { |
| fake.returnValue = value; |
| fake.resolve = true; |
| fake.resolveThis = false; |
| fake.reject = false; |
| fake.returnValueDefined = true; |
| fake.exception = undefined; |
| fake.exceptionCreator = undefined; |
| fake.fakeFn = undefined; |
| fake.callsThrough = false; |
| }, |
| |
| resolvesArg: function resolvesArg(fake, index) { |
| if (typeof index !== "number") { |
| throw new TypeError("argument index is not number"); |
| } |
| fake.resolveArgAt = index; |
| fake.returnValue = undefined; |
| fake.resolve = true; |
| fake.resolveThis = false; |
| fake.reject = false; |
| fake.returnValueDefined = false; |
| fake.exception = undefined; |
| fake.exceptionCreator = undefined; |
| fake.fakeFn = undefined; |
| fake.callsThrough = false; |
| }, |
| |
| rejects: function rejects(fake, error, message) { |
| let reason; |
| if (typeof error === "string") { |
| reason = new Error(message || ""); |
| reason.name = error; |
| } else if (!error) { |
| reason = new Error("Error"); |
| } else { |
| reason = error; |
| } |
| fake.returnValue = reason; |
| fake.resolve = false; |
| fake.resolveThis = false; |
| fake.reject = true; |
| fake.returnValueDefined = true; |
| fake.exception = undefined; |
| fake.exceptionCreator = undefined; |
| fake.fakeFn = undefined; |
| fake.callsThrough = false; |
| |
| return fake; |
| }, |
| |
| resolvesThis: function resolvesThis(fake) { |
| fake.returnValue = undefined; |
| fake.resolve = false; |
| fake.resolveThis = true; |
| fake.reject = false; |
| fake.returnValueDefined = false; |
| fake.exception = undefined; |
| fake.exceptionCreator = undefined; |
| fake.fakeFn = undefined; |
| fake.callsThrough = false; |
| }, |
| |
| callThrough: function callThrough(fake) { |
| fake.callsThrough = true; |
| }, |
| |
| callThroughWithNew: function callThroughWithNew(fake) { |
| fake.callsThroughWithNew = true; |
| }, |
| |
| get: function get(fake, getterFunction) { |
| const rootStub = fake.stub || fake; |
| |
| Object.defineProperty(rootStub.rootObj, rootStub.propName, { |
| get: getterFunction, |
| configurable: isPropertyConfigurable( |
| rootStub.rootObj, |
| rootStub.propName, |
| ), |
| }); |
| |
| return fake; |
| }, |
| |
| set: function set(fake, setterFunction) { |
| const rootStub = fake.stub || fake; |
| |
| Object.defineProperty( |
| rootStub.rootObj, |
| rootStub.propName, |
| // eslint-disable-next-line accessor-pairs |
| { |
| set: setterFunction, |
| configurable: isPropertyConfigurable( |
| rootStub.rootObj, |
| rootStub.propName, |
| ), |
| }, |
| ); |
| |
| return fake; |
| }, |
| |
| value: function value(fake, newVal) { |
| const rootStub = fake.stub || fake; |
| |
| Object.defineProperty(rootStub.rootObj, rootStub.propName, { |
| value: newVal, |
| enumerable: true, |
| writable: true, |
| configurable: |
| rootStub.shadowsPropOnPrototype || |
| isPropertyConfigurable(rootStub.rootObj, rootStub.propName), |
| }); |
| |
| return fake; |
| }, |
| }; |
| |
| const asyncBehaviors = exportAsyncBehaviors(defaultBehaviors); |
| |
| module.exports = extend({}, defaultBehaviors, asyncBehaviors); |
| |
| },{"./util/core/export-async-behaviors":24,"./util/core/extend":25,"./util/core/is-property-configurable":31,"@sinonjs/commons":46}],10:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const createProxy = require("./proxy"); |
| const nextTick = require("./util/core/next-tick"); |
| |
| const slice = arrayProto.slice; |
| |
| module.exports = fake; |
| |
| /** |
| * Returns a `fake` that records all calls, arguments and return values. |
| * |
| * When an `f` argument is supplied, this implementation will be used. |
| * |
| * @example |
| * // create an empty fake |
| * var f1 = sinon.fake(); |
| * |
| * f1(); |
| * |
| * f1.calledOnce() |
| * // true |
| * |
| * @example |
| * function greet(greeting) { |
| * console.log(`Hello ${greeting}`); |
| * } |
| * |
| * // create a fake with implementation |
| * var f2 = sinon.fake(greet); |
| * |
| * // Hello world |
| * f2("world"); |
| * |
| * f2.calledWith("world"); |
| * // true |
| * |
| * @param {Function|undefined} f |
| * @returns {Function} |
| * @namespace |
| */ |
| function fake(f) { |
| if (arguments.length > 0 && typeof f !== "function") { |
| throw new TypeError("Expected f argument to be a Function"); |
| } |
| |
| return wrapFunc(f); |
| } |
| |
| /** |
| * Creates a `fake` that returns the provided `value`, as well as recording all |
| * calls, arguments and return values. |
| * |
| * @example |
| * var f1 = sinon.fake.returns(42); |
| * |
| * f1(); |
| * // 42 |
| * |
| * @memberof fake |
| * @param {*} value |
| * @returns {Function} |
| */ |
| fake.returns = function returns(value) { |
| // eslint-disable-next-line jsdoc/require-jsdoc |
| function f() { |
| return value; |
| } |
| |
| return wrapFunc(f); |
| }; |
| |
| /** |
| * Creates a `fake` that throws an Error. |
| * If the `value` argument does not have Error in its prototype chain, it will |
| * be used for creating a new error. |
| * |
| * @example |
| * var f1 = sinon.fake.throws("hello"); |
| * |
| * f1(); |
| * // Uncaught Error: hello |
| * |
| * @example |
| * var f2 = sinon.fake.throws(new TypeError("Invalid argument")); |
| * |
| * f2(); |
| * // Uncaught TypeError: Invalid argument |
| * |
| * @memberof fake |
| * @param {*|Error} value |
| * @returns {Function} |
| */ |
| fake.throws = function throws(value) { |
| // eslint-disable-next-line jsdoc/require-jsdoc |
| function f() { |
| throw getError(value); |
| } |
| |
| return wrapFunc(f); |
| }; |
| |
| /** |
| * Creates a `fake` that returns a promise that resolves to the passed `value` |
| * argument. |
| * |
| * @example |
| * var f1 = sinon.fake.resolves("apple pie"); |
| * |
| * await f1(); |
| * // "apple pie" |
| * |
| * @memberof fake |
| * @param {*} value |
| * @returns {Function} |
| */ |
| fake.resolves = function resolves(value) { |
| // eslint-disable-next-line jsdoc/require-jsdoc |
| function f() { |
| return Promise.resolve(value); |
| } |
| |
| return wrapFunc(f); |
| }; |
| |
| /** |
| * Creates a `fake` that returns a promise that rejects to the passed `value` |
| * argument. When `value` does not have Error in its prototype chain, it will be |
| * wrapped in an Error. |
| * |
| * @example |
| * var f1 = sinon.fake.rejects(":("); |
| * |
| * try { |
| * await f1(); |
| * } catch (error) { |
| * console.log(error); |
| * // ":(" |
| * } |
| * |
| * @memberof fake |
| * @param {*} value |
| * @returns {Function} |
| */ |
| fake.rejects = function rejects(value) { |
| // eslint-disable-next-line jsdoc/require-jsdoc |
| function f() { |
| return Promise.reject(getError(value)); |
| } |
| |
| return wrapFunc(f); |
| }; |
| |
| /** |
| * Returns a `fake` that calls the callback with the defined arguments. |
| * |
| * @example |
| * function callback() { |
| * console.log(arguments.join("*")); |
| * } |
| * |
| * const f1 = sinon.fake.yields("apple", "pie"); |
| * |
| * f1(callback); |
| * // "apple*pie" |
| * |
| * @memberof fake |
| * @returns {Function} |
| */ |
| fake.yields = function yields() { |
| const values = slice(arguments); |
| |
| // eslint-disable-next-line jsdoc/require-jsdoc |
| function f() { |
| const callback = arguments[arguments.length - 1]; |
| if (typeof callback !== "function") { |
| throw new TypeError("Expected last argument to be a function"); |
| } |
| |
| callback.apply(null, values); |
| } |
| |
| return wrapFunc(f); |
| }; |
| |
| /** |
| * Returns a `fake` that calls the callback **asynchronously** with the |
| * defined arguments. |
| * |
| * @example |
| * function callback() { |
| * console.log(arguments.join("*")); |
| * } |
| * |
| * const f1 = sinon.fake.yields("apple", "pie"); |
| * |
| * f1(callback); |
| * |
| * setTimeout(() => { |
| * // "apple*pie" |
| * }); |
| * |
| * @memberof fake |
| * @returns {Function} |
| */ |
| fake.yieldsAsync = function yieldsAsync() { |
| const values = slice(arguments); |
| |
| // eslint-disable-next-line jsdoc/require-jsdoc |
| function f() { |
| const callback = arguments[arguments.length - 1]; |
| if (typeof callback !== "function") { |
| throw new TypeError("Expected last argument to be a function"); |
| } |
| nextTick(function () { |
| callback.apply(null, values); |
| }); |
| } |
| |
| return wrapFunc(f); |
| }; |
| |
| let uuid = 0; |
| /** |
| * Creates a proxy (sinon concept) from the passed function. |
| * |
| * @private |
| * @param {Function} f |
| * @returns {Function} |
| */ |
| function wrapFunc(f) { |
| const fakeInstance = function () { |
| let firstArg, lastArg; |
| |
| if (arguments.length > 0) { |
| firstArg = arguments[0]; |
| lastArg = arguments[arguments.length - 1]; |
| } |
| |
| const callback = |
| lastArg && typeof lastArg === "function" ? lastArg : undefined; |
| |
| /* eslint-disable no-use-before-define */ |
| proxy.firstArg = firstArg; |
| proxy.lastArg = lastArg; |
| proxy.callback = callback; |
| |
| return f && f.apply(this, arguments); |
| }; |
| const proxy = createProxy(fakeInstance, f || fakeInstance); |
| |
| proxy.displayName = "fake"; |
| proxy.id = `fake#${uuid++}`; |
| |
| return proxy; |
| } |
| |
| /** |
| * Returns an Error instance from the passed value, if the value is not |
| * already an Error instance. |
| * |
| * @private |
| * @param {*} value [description] |
| * @returns {Error} [description] |
| */ |
| function getError(value) { |
| return value instanceof Error ? value : new Error(value); |
| } |
| |
| },{"./proxy":17,"./util/core/next-tick":33,"@sinonjs/commons":46}],11:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const proxyInvoke = require("./proxy-invoke"); |
| const proxyCallToString = require("./proxy-call").toString; |
| const timesInWords = require("./util/core/times-in-words"); |
| const extend = require("./util/core/extend"); |
| const match = require("@sinonjs/samsam").createMatcher; |
| const stub = require("./stub"); |
| const assert = require("./assert"); |
| const deepEqual = require("@sinonjs/samsam").deepEqual; |
| const inspect = require("util").inspect; |
| const valueToString = require("@sinonjs/commons").valueToString; |
| |
| const every = arrayProto.every; |
| const forEach = arrayProto.forEach; |
| const push = arrayProto.push; |
| const slice = arrayProto.slice; |
| |
| function callCountInWords(callCount) { |
| if (callCount === 0) { |
| return "never called"; |
| } |
| |
| return `called ${timesInWords(callCount)}`; |
| } |
| |
| function expectedCallCountInWords(expectation) { |
| const min = expectation.minCalls; |
| const max = expectation.maxCalls; |
| |
| if (typeof min === "number" && typeof max === "number") { |
| let str = timesInWords(min); |
| |
| if (min !== max) { |
| str = `at least ${str} and at most ${timesInWords(max)}`; |
| } |
| |
| return str; |
| } |
| |
| if (typeof min === "number") { |
| return `at least ${timesInWords(min)}`; |
| } |
| |
| return `at most ${timesInWords(max)}`; |
| } |
| |
| function receivedMinCalls(expectation) { |
| const hasMinLimit = typeof expectation.minCalls === "number"; |
| return !hasMinLimit || expectation.callCount >= expectation.minCalls; |
| } |
| |
| function receivedMaxCalls(expectation) { |
| if (typeof expectation.maxCalls !== "number") { |
| return false; |
| } |
| |
| return expectation.callCount === expectation.maxCalls; |
| } |
| |
| function verifyMatcher(possibleMatcher, arg) { |
| const isMatcher = match.isMatcher(possibleMatcher); |
| |
| return (isMatcher && possibleMatcher.test(arg)) || true; |
| } |
| |
| const mockExpectation = { |
| minCalls: 1, |
| maxCalls: 1, |
| |
| create: function create(methodName) { |
| const expectation = extend.nonEnum(stub(), mockExpectation); |
| delete expectation.create; |
| expectation.method = methodName; |
| |
| return expectation; |
| }, |
| |
| invoke: function invoke(func, thisValue, args) { |
| this.verifyCallAllowed(thisValue, args); |
| |
| return proxyInvoke.apply(this, arguments); |
| }, |
| |
| atLeast: function atLeast(num) { |
| if (typeof num !== "number") { |
| throw new TypeError(`'${valueToString(num)}' is not number`); |
| } |
| |
| if (!this.limitsSet) { |
| this.maxCalls = null; |
| this.limitsSet = true; |
| } |
| |
| this.minCalls = num; |
| |
| return this; |
| }, |
| |
| atMost: function atMost(num) { |
| if (typeof num !== "number") { |
| throw new TypeError(`'${valueToString(num)}' is not number`); |
| } |
| |
| if (!this.limitsSet) { |
| this.minCalls = null; |
| this.limitsSet = true; |
| } |
| |
| this.maxCalls = num; |
| |
| return this; |
| }, |
| |
| never: function never() { |
| return this.exactly(0); |
| }, |
| |
| once: function once() { |
| return this.exactly(1); |
| }, |
| |
| twice: function twice() { |
| return this.exactly(2); |
| }, |
| |
| thrice: function thrice() { |
| return this.exactly(3); |
| }, |
| |
| exactly: function exactly(num) { |
| if (typeof num !== "number") { |
| throw new TypeError(`'${valueToString(num)}' is not a number`); |
| } |
| |
| this.atLeast(num); |
| return this.atMost(num); |
| }, |
| |
| met: function met() { |
| return !this.failed && receivedMinCalls(this); |
| }, |
| |
| verifyCallAllowed: function verifyCallAllowed(thisValue, args) { |
| const expectedArguments = this.expectedArguments; |
| |
| if (receivedMaxCalls(this)) { |
| this.failed = true; |
| mockExpectation.fail( |
| `${this.method} already called ${timesInWords(this.maxCalls)}`, |
| ); |
| } |
| |
| if ("expectedThis" in this && this.expectedThis !== thisValue) { |
| mockExpectation.fail( |
| `${this.method} called with ${valueToString( |
| thisValue, |
| )} as thisValue, expected ${valueToString(this.expectedThis)}`, |
| ); |
| } |
| |
| if (!("expectedArguments" in this)) { |
| return; |
| } |
| |
| if (!args) { |
| mockExpectation.fail( |
| `${this.method} received no arguments, expected ${inspect( |
| expectedArguments, |
| )}`, |
| ); |
| } |
| |
| if (args.length < expectedArguments.length) { |
| mockExpectation.fail( |
| `${this.method} received too few arguments (${inspect( |
| args, |
| )}), expected ${inspect(expectedArguments)}`, |
| ); |
| } |
| |
| if ( |
| this.expectsExactArgCount && |
| args.length !== expectedArguments.length |
| ) { |
| mockExpectation.fail( |
| `${this.method} received too many arguments (${inspect( |
| args, |
| )}), expected ${inspect(expectedArguments)}`, |
| ); |
| } |
| |
| forEach( |
| expectedArguments, |
| function (expectedArgument, i) { |
| if (!verifyMatcher(expectedArgument, args[i])) { |
| mockExpectation.fail( |
| `${this.method} received wrong arguments ${inspect( |
| args, |
| )}, didn't match ${String(expectedArguments)}`, |
| ); |
| } |
| |
| if (!deepEqual(args[i], expectedArgument)) { |
| mockExpectation.fail( |
| `${this.method} received wrong arguments ${inspect( |
| args, |
| )}, expected ${inspect(expectedArguments)}`, |
| ); |
| } |
| }, |
| this, |
| ); |
| }, |
| |
| allowsCall: function allowsCall(thisValue, args) { |
| const expectedArguments = this.expectedArguments; |
| |
| if (this.met() && receivedMaxCalls(this)) { |
| return false; |
| } |
| |
| if ("expectedThis" in this && this.expectedThis !== thisValue) { |
| return false; |
| } |
| |
| if (!("expectedArguments" in this)) { |
| return true; |
| } |
| |
| // eslint-disable-next-line no-underscore-dangle |
| const _args = args || []; |
| |
| if (_args.length < expectedArguments.length) { |
| return false; |
| } |
| |
| if ( |
| this.expectsExactArgCount && |
| _args.length !== expectedArguments.length |
| ) { |
| return false; |
| } |
| |
| return every(expectedArguments, function (expectedArgument, i) { |
| if (!verifyMatcher(expectedArgument, _args[i])) { |
| return false; |
| } |
| |
| if (!deepEqual(_args[i], expectedArgument)) { |
| return false; |
| } |
| |
| return true; |
| }); |
| }, |
| |
| withArgs: function withArgs() { |
| this.expectedArguments = slice(arguments); |
| return this; |
| }, |
| |
| withExactArgs: function withExactArgs() { |
| this.withArgs.apply(this, arguments); |
| this.expectsExactArgCount = true; |
| return this; |
| }, |
| |
| on: function on(thisValue) { |
| this.expectedThis = thisValue; |
| return this; |
| }, |
| |
| toString: function () { |
| const args = slice(this.expectedArguments || []); |
| |
| if (!this.expectsExactArgCount) { |
| push(args, "[...]"); |
| } |
| |
| const callStr = proxyCallToString.call({ |
| proxy: this.method || "anonymous mock expectation", |
| args: args, |
| }); |
| |
| const message = `${callStr.replace( |
| ", [...", |
| "[, ...", |
| )} ${expectedCallCountInWords(this)}`; |
| |
| if (this.met()) { |
| return `Expectation met: ${message}`; |
| } |
| |
| return `Expected ${message} (${callCountInWords(this.callCount)})`; |
| }, |
| |
| verify: function verify() { |
| if (!this.met()) { |
| mockExpectation.fail(String(this)); |
| } else { |
| mockExpectation.pass(String(this)); |
| } |
| |
| return true; |
| }, |
| |
| pass: function pass(message) { |
| assert.pass(message); |
| }, |
| |
| fail: function fail(message) { |
| const exception = new Error(message); |
| exception.name = "ExpectationError"; |
| |
| throw exception; |
| }, |
| }; |
| |
| module.exports = mockExpectation; |
| |
| },{"./assert":3,"./proxy-call":15,"./proxy-invoke":16,"./stub":22,"./util/core/extend":25,"./util/core/times-in-words":35,"@sinonjs/commons":46,"@sinonjs/samsam":86,"util":90}],12:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const mockExpectation = require("./mock-expectation"); |
| const proxyCallToString = require("./proxy-call").toString; |
| const extend = require("./util/core/extend"); |
| const deepEqual = require("@sinonjs/samsam").deepEqual; |
| const wrapMethod = require("./util/core/wrap-method"); |
| |
| const concat = arrayProto.concat; |
| const filter = arrayProto.filter; |
| const forEach = arrayProto.forEach; |
| const every = arrayProto.every; |
| const join = arrayProto.join; |
| const push = arrayProto.push; |
| const slice = arrayProto.slice; |
| const unshift = arrayProto.unshift; |
| |
| function mock(object) { |
| if (!object || typeof object === "string") { |
| return mockExpectation.create(object ? object : "Anonymous mock"); |
| } |
| |
| return mock.create(object); |
| } |
| |
| function each(collection, callback) { |
| const col = collection || []; |
| |
| forEach(col, callback); |
| } |
| |
| function arrayEquals(arr1, arr2, compareLength) { |
| if (compareLength && arr1.length !== arr2.length) { |
| return false; |
| } |
| |
| return every(arr1, function (element, i) { |
| return deepEqual(arr2[i], element); |
| }); |
| } |
| |
| extend(mock, { |
| create: function create(object) { |
| if (!object) { |
| throw new TypeError("object is null"); |
| } |
| |
| const mockObject = extend.nonEnum({}, mock, { object: object }); |
| delete mockObject.create; |
| |
| return mockObject; |
| }, |
| |
| expects: function expects(method) { |
| if (!method) { |
| throw new TypeError("method is falsy"); |
| } |
| |
| if (!this.expectations) { |
| this.expectations = {}; |
| this.proxies = []; |
| this.failures = []; |
| } |
| |
| if (!this.expectations[method]) { |
| this.expectations[method] = []; |
| const mockObject = this; |
| |
| wrapMethod(this.object, method, function () { |
| return mockObject.invokeMethod(method, this, arguments); |
| }); |
| |
| push(this.proxies, method); |
| } |
| |
| const expectation = mockExpectation.create(method); |
| expectation.wrappedMethod = this.object[method].wrappedMethod; |
| push(this.expectations[method], expectation); |
| |
| return expectation; |
| }, |
| |
| restore: function restore() { |
| const object = this.object; |
| |
| each(this.proxies, function (proxy) { |
| if (typeof object[proxy].restore === "function") { |
| object[proxy].restore(); |
| } |
| }); |
| }, |
| |
| verify: function verify() { |
| const expectations = this.expectations || {}; |
| const messages = this.failures ? slice(this.failures) : []; |
| const met = []; |
| |
| each(this.proxies, function (proxy) { |
| each(expectations[proxy], function (expectation) { |
| if (!expectation.met()) { |
| push(messages, String(expectation)); |
| } else { |
| push(met, String(expectation)); |
| } |
| }); |
| }); |
| |
| this.restore(); |
| |
| if (messages.length > 0) { |
| mockExpectation.fail(join(concat(messages, met), "\n")); |
| } else if (met.length > 0) { |
| mockExpectation.pass(join(concat(messages, met), "\n")); |
| } |
| |
| return true; |
| }, |
| |
| invokeMethod: function invokeMethod(method, thisValue, args) { |
| /* if we cannot find any matching files we will explicitly call mockExpection#fail with error messages */ |
| /* eslint consistent-return: "off" */ |
| const expectations = |
| this.expectations && this.expectations[method] |
| ? this.expectations[method] |
| : []; |
| const currentArgs = args || []; |
| let available; |
| |
| const expectationsWithMatchingArgs = filter( |
| expectations, |
| function (expectation) { |
| const expectedArgs = expectation.expectedArguments || []; |
| |
| return arrayEquals( |
| expectedArgs, |
| currentArgs, |
| expectation.expectsExactArgCount, |
| ); |
| }, |
| ); |
| |
| const expectationsToApply = filter( |
| expectationsWithMatchingArgs, |
| function (expectation) { |
| return ( |
| !expectation.met() && |
| expectation.allowsCall(thisValue, args) |
| ); |
| }, |
| ); |
| |
| if (expectationsToApply.length > 0) { |
| return expectationsToApply[0].apply(thisValue, args); |
| } |
| |
| const messages = []; |
| let exhausted = 0; |
| |
| forEach(expectationsWithMatchingArgs, function (expectation) { |
| if (expectation.allowsCall(thisValue, args)) { |
| available = available || expectation; |
| } else { |
| exhausted += 1; |
| } |
| }); |
| |
| if (available && exhausted === 0) { |
| return available.apply(thisValue, args); |
| } |
| |
| forEach(expectations, function (expectation) { |
| push(messages, ` ${String(expectation)}`); |
| }); |
| |
| unshift( |
| messages, |
| `Unexpected call: ${proxyCallToString.call({ |
| proxy: method, |
| args: args, |
| })}`, |
| ); |
| |
| const err = new Error(); |
| if (!err.stack) { |
| // PhantomJS does not serialize the stack trace until the error has been thrown |
| try { |
| throw err; |
| } catch (e) { |
| /* empty */ |
| } |
| } |
| push( |
| this.failures, |
| `Unexpected call: ${proxyCallToString.call({ |
| proxy: method, |
| args: args, |
| stack: err.stack, |
| })}`, |
| ); |
| |
| mockExpectation.fail(join(messages, "\n")); |
| }, |
| }); |
| |
| module.exports = mock; |
| |
| },{"./mock-expectation":11,"./proxy-call":15,"./util/core/extend":25,"./util/core/wrap-method":38,"@sinonjs/commons":46,"@sinonjs/samsam":86}],13:[function(require,module,exports){ |
| "use strict"; |
| |
| const fake = require("./fake"); |
| const isRestorable = require("./util/core/is-restorable"); |
| |
| const STATUS_PENDING = "pending"; |
| const STATUS_RESOLVED = "resolved"; |
| const STATUS_REJECTED = "rejected"; |
| |
| /** |
| * Returns a fake for a given function or undefined. If no function is given, a |
| * new fake is returned. If the given function is already a fake, it is |
| * returned as is. Otherwise the given function is wrapped in a new fake. |
| * |
| * @param {Function} [executor] The optional executor function. |
| * @returns {Function} |
| */ |
| function getFakeExecutor(executor) { |
| if (isRestorable(executor)) { |
| return executor; |
| } |
| if (executor) { |
| return fake(executor); |
| } |
| return fake(); |
| } |
| |
| /** |
| * Returns a new promise that exposes it's internal `status`, `resolvedValue` |
| * and `rejectedValue` and can be resolved or rejected from the outside by |
| * calling `resolve(value)` or `reject(reason)`. |
| * |
| * @param {Function} [executor] The optional executor function. |
| * @returns {Promise} |
| */ |
| function promise(executor) { |
| const fakeExecutor = getFakeExecutor(executor); |
| const sinonPromise = new Promise(fakeExecutor); |
| |
| sinonPromise.status = STATUS_PENDING; |
| sinonPromise |
| .then(function (value) { |
| sinonPromise.status = STATUS_RESOLVED; |
| sinonPromise.resolvedValue = value; |
| }) |
| .catch(function (reason) { |
| sinonPromise.status = STATUS_REJECTED; |
| sinonPromise.rejectedValue = reason; |
| }); |
| |
| /** |
| * Resolves or rejects the promise with the given status and value. |
| * |
| * @param {string} status |
| * @param {*} value |
| * @param {Function} callback |
| */ |
| function finalize(status, value, callback) { |
| if (sinonPromise.status !== STATUS_PENDING) { |
| throw new Error(`Promise already ${sinonPromise.status}`); |
| } |
| |
| sinonPromise.status = status; |
| callback(value); |
| } |
| |
| sinonPromise.resolve = function (value) { |
| finalize(STATUS_RESOLVED, value, fakeExecutor.firstCall.args[0]); |
| // Return the promise so that callers can await it: |
| return sinonPromise; |
| }; |
| sinonPromise.reject = function (reason) { |
| finalize(STATUS_REJECTED, reason, fakeExecutor.firstCall.args[1]); |
| // Return a new promise that resolves when the sinon promise was |
| // rejected, so that callers can await it: |
| return new Promise(function (resolve) { |
| sinonPromise.catch(() => resolve()); |
| }); |
| }; |
| |
| return sinonPromise; |
| } |
| |
| module.exports = promise; |
| |
| },{"./fake":10,"./util/core/is-restorable":32}],14:[function(require,module,exports){ |
| "use strict"; |
| |
| const push = require("@sinonjs/commons").prototypes.array.push; |
| |
| exports.incrementCallCount = function incrementCallCount(proxy) { |
| proxy.called = true; |
| proxy.callCount += 1; |
| proxy.notCalled = false; |
| proxy.calledOnce = proxy.callCount === 1; |
| proxy.calledTwice = proxy.callCount === 2; |
| proxy.calledThrice = proxy.callCount === 3; |
| }; |
| |
| exports.createCallProperties = function createCallProperties(proxy) { |
| proxy.firstCall = proxy.getCall(0); |
| proxy.secondCall = proxy.getCall(1); |
| proxy.thirdCall = proxy.getCall(2); |
| proxy.lastCall = proxy.getCall(proxy.callCount - 1); |
| }; |
| |
| exports.delegateToCalls = function delegateToCalls( |
| proxy, |
| method, |
| matchAny, |
| actual, |
| returnsValues, |
| notCalled, |
| totalCallCount, |
| ) { |
| proxy[method] = function () { |
| if (!this.called) { |
| if (notCalled) { |
| return notCalled.apply(this, arguments); |
| } |
| return false; |
| } |
| |
| if (totalCallCount !== undefined && this.callCount !== totalCallCount) { |
| return false; |
| } |
| |
| let currentCall; |
| let matches = 0; |
| const returnValues = []; |
| |
| for (let i = 0, l = this.callCount; i < l; i += 1) { |
| currentCall = this.getCall(i); |
| const returnValue = currentCall[actual || method].apply( |
| currentCall, |
| arguments, |
| ); |
| push(returnValues, returnValue); |
| if (returnValue) { |
| matches += 1; |
| |
| if (matchAny) { |
| return true; |
| } |
| } |
| } |
| |
| if (returnsValues) { |
| return returnValues; |
| } |
| return matches === this.callCount; |
| }; |
| }; |
| |
| },{"@sinonjs/commons":46}],15:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const match = require("@sinonjs/samsam").createMatcher; |
| const deepEqual = require("@sinonjs/samsam").deepEqual; |
| const functionName = require("@sinonjs/commons").functionName; |
| const inspect = require("util").inspect; |
| const valueToString = require("@sinonjs/commons").valueToString; |
| |
| const concat = arrayProto.concat; |
| const filter = arrayProto.filter; |
| const join = arrayProto.join; |
| const map = arrayProto.map; |
| const reduce = arrayProto.reduce; |
| const slice = arrayProto.slice; |
| |
| /** |
| * @param proxy |
| * @param text |
| * @param args |
| */ |
| function throwYieldError(proxy, text, args) { |
| let msg = functionName(proxy) + text; |
| if (args.length) { |
| msg += ` Received [${join(slice(args), ", ")}]`; |
| } |
| throw new Error(msg); |
| } |
| |
| const callProto = { |
| calledOn: function calledOn(thisValue) { |
| if (match.isMatcher(thisValue)) { |
| return thisValue.test(this.thisValue); |
| } |
| return this.thisValue === thisValue; |
| }, |
| |
| calledWith: function calledWith() { |
| const self = this; |
| const calledWithArgs = slice(arguments); |
| |
| if (calledWithArgs.length > self.args.length) { |
| return false; |
| } |
| |
| return reduce( |
| calledWithArgs, |
| function (prev, arg, i) { |
| return prev && deepEqual(self.args[i], arg); |
| }, |
| true, |
| ); |
| }, |
| |
| calledWithMatch: function calledWithMatch() { |
| const self = this; |
| const calledWithMatchArgs = slice(arguments); |
| |
| if (calledWithMatchArgs.length > self.args.length) { |
| return false; |
| } |
| |
| return reduce( |
| calledWithMatchArgs, |
| function (prev, expectation, i) { |
| const actual = self.args[i]; |
| |
| return prev && match(expectation).test(actual); |
| }, |
| true, |
| ); |
| }, |
| |
| calledWithExactly: function calledWithExactly() { |
| return ( |
| arguments.length === this.args.length && |
| this.calledWith.apply(this, arguments) |
| ); |
| }, |
| |
| notCalledWith: function notCalledWith() { |
| return !this.calledWith.apply(this, arguments); |
| }, |
| |
| notCalledWithMatch: function notCalledWithMatch() { |
| return !this.calledWithMatch.apply(this, arguments); |
| }, |
| |
| returned: function returned(value) { |
| return deepEqual(this.returnValue, value); |
| }, |
| |
| threw: function threw(error) { |
| if (typeof error === "undefined" || !this.exception) { |
| return Boolean(this.exception); |
| } |
| |
| return this.exception === error || this.exception.name === error; |
| }, |
| |
| calledWithNew: function calledWithNew() { |
| return this.proxy.prototype && this.thisValue instanceof this.proxy; |
| }, |
| |
| calledBefore: function (other) { |
| return this.callId < other.callId; |
| }, |
| |
| calledAfter: function (other) { |
| return this.callId > other.callId; |
| }, |
| |
| calledImmediatelyBefore: function (other) { |
| return this.callId === other.callId - 1; |
| }, |
| |
| calledImmediatelyAfter: function (other) { |
| return this.callId === other.callId + 1; |
| }, |
| |
| callArg: function (pos) { |
| this.ensureArgIsAFunction(pos); |
| return this.args[pos](); |
| }, |
| |
| callArgOn: function (pos, thisValue) { |
| this.ensureArgIsAFunction(pos); |
| return this.args[pos].apply(thisValue); |
| }, |
| |
| callArgWith: function (pos) { |
| return this.callArgOnWith.apply( |
| this, |
| concat([pos, null], slice(arguments, 1)), |
| ); |
| }, |
| |
| callArgOnWith: function (pos, thisValue) { |
| this.ensureArgIsAFunction(pos); |
| const args = slice(arguments, 2); |
| return this.args[pos].apply(thisValue, args); |
| }, |
| |
| throwArg: function (pos) { |
| if (pos > this.args.length) { |
| throw new TypeError( |
| `Not enough arguments: ${pos} required but only ${this.args.length} present`, |
| ); |
| } |
| |
| throw this.args[pos]; |
| }, |
| |
| yield: function () { |
| return this.yieldOn.apply(this, concat([null], slice(arguments, 0))); |
| }, |
| |
| yieldOn: function (thisValue) { |
| const args = slice(this.args); |
| const yieldFn = filter(args, function (arg) { |
| return typeof arg === "function"; |
| })[0]; |
| |
| if (!yieldFn) { |
| throwYieldError( |
| this.proxy, |
| " cannot yield since no callback was passed.", |
| args, |
| ); |
| } |
| |
| return yieldFn.apply(thisValue, slice(arguments, 1)); |
| }, |
| |
| yieldTo: function (prop) { |
| return this.yieldToOn.apply( |
| this, |
| concat([prop, null], slice(arguments, 1)), |
| ); |
| }, |
| |
| yieldToOn: function (prop, thisValue) { |
| const args = slice(this.args); |
| const yieldArg = filter(args, function (arg) { |
| return arg && typeof arg[prop] === "function"; |
| })[0]; |
| const yieldFn = yieldArg && yieldArg[prop]; |
| |
| if (!yieldFn) { |
| throwYieldError( |
| this.proxy, |
| ` cannot yield to '${valueToString( |
| prop, |
| )}' since no callback was passed.`, |
| args, |
| ); |
| } |
| |
| return yieldFn.apply(thisValue, slice(arguments, 2)); |
| }, |
| |
| toString: function () { |
| if (!this.args) { |
| return ":("; |
| } |
| |
| let callStr = this.proxy ? `${String(this.proxy)}(` : ""; |
| const formattedArgs = map(this.args, function (arg) { |
| return inspect(arg); |
| }); |
| |
| callStr = `${callStr + join(formattedArgs, ", ")})`; |
| |
| if (typeof this.returnValue !== "undefined") { |
| callStr += ` => ${inspect(this.returnValue)}`; |
| } |
| |
| if (this.exception) { |
| callStr += ` !${this.exception.name}`; |
| |
| if (this.exception.message) { |
| callStr += `(${this.exception.message})`; |
| } |
| } |
| if (this.stack) { |
| // If we have a stack, add the first frame that's in end-user code |
| // Skip the first two frames because they will refer to Sinon code |
| callStr += (this.stack.split("\n")[3] || "unknown").replace( |
| /^\s*(?:at\s+|@)?/, |
| " at ", |
| ); |
| } |
| |
| return callStr; |
| }, |
| |
| ensureArgIsAFunction: function (pos) { |
| if (typeof this.args[pos] !== "function") { |
| throw new TypeError( |
| `Expected argument at position ${pos} to be a Function, but was ${typeof this |
| .args[pos]}`, |
| ); |
| } |
| }, |
| }; |
| Object.defineProperty(callProto, "stack", { |
| enumerable: true, |
| configurable: true, |
| get: function () { |
| return (this.errorWithCallStack && this.errorWithCallStack.stack) || ""; |
| }, |
| }); |
| |
| callProto.invokeCallback = callProto.yield; |
| |
| /** |
| * @param proxy |
| * @param thisValue |
| * @param args |
| * @param returnValue |
| * @param exception |
| * @param id |
| * @param errorWithCallStack |
| * |
| * @returns {object} proxyCall |
| */ |
| function createProxyCall( |
| proxy, |
| thisValue, |
| args, |
| returnValue, |
| exception, |
| id, |
| errorWithCallStack, |
| ) { |
| if (typeof id !== "number") { |
| throw new TypeError("Call id is not a number"); |
| } |
| |
| let firstArg, lastArg; |
| |
| if (args.length > 0) { |
| firstArg = args[0]; |
| lastArg = args[args.length - 1]; |
| } |
| |
| const proxyCall = Object.create(callProto); |
| const callback = |
| lastArg && typeof lastArg === "function" ? lastArg : undefined; |
| |
| proxyCall.proxy = proxy; |
| proxyCall.thisValue = thisValue; |
| proxyCall.args = args; |
| proxyCall.firstArg = firstArg; |
| proxyCall.lastArg = lastArg; |
| proxyCall.callback = callback; |
| proxyCall.returnValue = returnValue; |
| proxyCall.exception = exception; |
| proxyCall.callId = id; |
| proxyCall.errorWithCallStack = errorWithCallStack; |
| |
| return proxyCall; |
| } |
| createProxyCall.toString = callProto.toString; // used by mocks |
| |
| module.exports = createProxyCall; |
| |
| },{"@sinonjs/commons":46,"@sinonjs/samsam":86,"util":90}],16:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const proxyCallUtil = require("./proxy-call-util"); |
| |
| const push = arrayProto.push; |
| const forEach = arrayProto.forEach; |
| const concat = arrayProto.concat; |
| const ErrorConstructor = Error.prototype.constructor; |
| const bind = Function.prototype.bind; |
| |
| let callId = 0; |
| |
| module.exports = function invoke(func, thisValue, args) { |
| const matchings = this.matchingFakes(args); |
| const currentCallId = callId++; |
| let exception, returnValue; |
| |
| proxyCallUtil.incrementCallCount(this); |
| push(this.thisValues, thisValue); |
| push(this.args, args); |
| push(this.callIds, currentCallId); |
| forEach(matchings, function (matching) { |
| proxyCallUtil.incrementCallCount(matching); |
| push(matching.thisValues, thisValue); |
| push(matching.args, args); |
| push(matching.callIds, currentCallId); |
| }); |
| |
| // Make call properties available from within the spied function: |
| proxyCallUtil.createCallProperties(this); |
| forEach(matchings, proxyCallUtil.createCallProperties); |
| |
| try { |
| this.invoking = true; |
| |
| const thisCall = this.getCall(this.callCount - 1); |
| |
| if (thisCall.calledWithNew()) { |
| // Call through with `new` |
| returnValue = new (bind.apply( |
| this.func || func, |
| concat([thisValue], args), |
| ))(); |
| |
| if ( |
| typeof returnValue !== "object" && |
| typeof returnValue !== "function" |
| ) { |
| returnValue = thisValue; |
| } |
| } else { |
| returnValue = (this.func || func).apply(thisValue, args); |
| } |
| } catch (e) { |
| exception = e; |
| } finally { |
| delete this.invoking; |
| } |
| |
| push(this.exceptions, exception); |
| push(this.returnValues, returnValue); |
| forEach(matchings, function (matching) { |
| push(matching.exceptions, exception); |
| push(matching.returnValues, returnValue); |
| }); |
| |
| const err = new ErrorConstructor(); |
| // 1. Please do not get stack at this point. It may be so very slow, and not actually used |
| // 2. PhantomJS does not serialize the stack trace until the error has been thrown: |
| // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack |
| try { |
| throw err; |
| } catch (e) { |
| /* empty */ |
| } |
| push(this.errorsWithCallStack, err); |
| forEach(matchings, function (matching) { |
| push(matching.errorsWithCallStack, err); |
| }); |
| |
| // Make return value and exception available in the calls: |
| proxyCallUtil.createCallProperties(this); |
| forEach(matchings, proxyCallUtil.createCallProperties); |
| |
| if (exception !== undefined) { |
| throw exception; |
| } |
| |
| return returnValue; |
| }; |
| |
| },{"./proxy-call-util":14,"@sinonjs/commons":46}],17:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const extend = require("./util/core/extend"); |
| const functionToString = require("./util/core/function-to-string"); |
| const proxyCall = require("./proxy-call"); |
| const proxyCallUtil = require("./proxy-call-util"); |
| const proxyInvoke = require("./proxy-invoke"); |
| const inspect = require("util").inspect; |
| |
| const push = arrayProto.push; |
| const forEach = arrayProto.forEach; |
| const slice = arrayProto.slice; |
| |
| const emptyFakes = Object.freeze([]); |
| |
| // Public API |
| const proxyApi = { |
| toString: functionToString, |
| |
| named: function named(name) { |
| this.displayName = name; |
| const nameDescriptor = Object.getOwnPropertyDescriptor(this, "name"); |
| if (nameDescriptor && nameDescriptor.configurable) { |
| // IE 11 functions don't have a name. |
| // Safari 9 has names that are not configurable. |
| nameDescriptor.value = name; |
| Object.defineProperty(this, "name", nameDescriptor); |
| } |
| return this; |
| }, |
| |
| invoke: proxyInvoke, |
| |
| /* |
| * Hook for derived implementation to return fake instances matching the |
| * given arguments. |
| */ |
| matchingFakes: function (/*args, strict*/) { |
| return emptyFakes; |
| }, |
| |
| getCall: function getCall(index) { |
| let i = index; |
| if (i < 0) { |
| // Negative indices means counting backwards from the last call |
| i += this.callCount; |
| } |
| if (i < 0 || i >= this.callCount) { |
| return null; |
| } |
| |
| return proxyCall( |
| this, |
| this.thisValues[i], |
| this.args[i], |
| this.returnValues[i], |
| this.exceptions[i], |
| this.callIds[i], |
| this.errorsWithCallStack[i], |
| ); |
| }, |
| |
| getCalls: function () { |
| const calls = []; |
| let i; |
| |
| for (i = 0; i < this.callCount; i++) { |
| push(calls, this.getCall(i)); |
| } |
| |
| return calls; |
| }, |
| |
| calledBefore: function calledBefore(proxy) { |
| if (!this.called) { |
| return false; |
| } |
| |
| if (!proxy.called) { |
| return true; |
| } |
| |
| return this.callIds[0] < proxy.callIds[proxy.callIds.length - 1]; |
| }, |
| |
| calledAfter: function calledAfter(proxy) { |
| if (!this.called || !proxy.called) { |
| return false; |
| } |
| |
| return this.callIds[this.callCount - 1] > proxy.callIds[0]; |
| }, |
| |
| calledImmediatelyBefore: function calledImmediatelyBefore(proxy) { |
| if (!this.called || !proxy.called) { |
| return false; |
| } |
| |
| return ( |
| this.callIds[this.callCount - 1] === |
| proxy.callIds[proxy.callCount - 1] - 1 |
| ); |
| }, |
| |
| calledImmediatelyAfter: function calledImmediatelyAfter(proxy) { |
| if (!this.called || !proxy.called) { |
| return false; |
| } |
| |
| return ( |
| this.callIds[this.callCount - 1] === |
| proxy.callIds[proxy.callCount - 1] + 1 |
| ); |
| }, |
| |
| formatters: require("./spy-formatters"), |
| printf: function (format) { |
| const spyInstance = this; |
| const args = slice(arguments, 1); |
| let formatter; |
| |
| return (format || "").replace(/%(.)/g, function (match, specifier) { |
| formatter = proxyApi.formatters[specifier]; |
| |
| if (typeof formatter === "function") { |
| return String(formatter(spyInstance, args)); |
| } else if (!isNaN(parseInt(specifier, 10))) { |
| return inspect(args[specifier - 1]); |
| } |
| |
| return `%${specifier}`; |
| }); |
| }, |
| |
| resetHistory: function () { |
| if (this.invoking) { |
| const err = new Error( |
| "Cannot reset Sinon function while invoking it. " + |
| "Move the call to .resetHistory outside of the callback.", |
| ); |
| err.name = "InvalidResetException"; |
| throw err; |
| } |
| |
| this.called = false; |
| this.notCalled = true; |
| this.calledOnce = false; |
| this.calledTwice = false; |
| this.calledThrice = false; |
| this.callCount = 0; |
| this.firstCall = null; |
| this.secondCall = null; |
| this.thirdCall = null; |
| this.lastCall = null; |
| this.args = []; |
| this.firstArg = null; |
| this.lastArg = null; |
| this.returnValues = []; |
| this.thisValues = []; |
| this.exceptions = []; |
| this.callIds = []; |
| this.errorsWithCallStack = []; |
| |
| if (this.fakes) { |
| forEach(this.fakes, function (fake) { |
| fake.resetHistory(); |
| }); |
| } |
| |
| return this; |
| }, |
| }; |
| |
| const delegateToCalls = proxyCallUtil.delegateToCalls; |
| delegateToCalls(proxyApi, "calledOn", true); |
| delegateToCalls(proxyApi, "alwaysCalledOn", false, "calledOn"); |
| delegateToCalls(proxyApi, "calledWith", true); |
| delegateToCalls( |
| proxyApi, |
| "calledOnceWith", |
| true, |
| "calledWith", |
| false, |
| undefined, |
| 1, |
| ); |
| delegateToCalls(proxyApi, "calledWithMatch", true); |
| delegateToCalls(proxyApi, "alwaysCalledWith", false, "calledWith"); |
| delegateToCalls(proxyApi, "alwaysCalledWithMatch", false, "calledWithMatch"); |
| delegateToCalls(proxyApi, "calledWithExactly", true); |
| delegateToCalls( |
| proxyApi, |
| "calledOnceWithExactly", |
| true, |
| "calledWithExactly", |
| false, |
| undefined, |
| 1, |
| ); |
| delegateToCalls( |
| proxyApi, |
| "calledOnceWithMatch", |
| true, |
| "calledWithMatch", |
| false, |
| undefined, |
| 1, |
| ); |
| delegateToCalls( |
| proxyApi, |
| "alwaysCalledWithExactly", |
| false, |
| "calledWithExactly", |
| ); |
| delegateToCalls( |
| proxyApi, |
| "neverCalledWith", |
| false, |
| "notCalledWith", |
| false, |
| function () { |
| return true; |
| }, |
| ); |
| delegateToCalls( |
| proxyApi, |
| "neverCalledWithMatch", |
| false, |
| "notCalledWithMatch", |
| false, |
| function () { |
| return true; |
| }, |
| ); |
| delegateToCalls(proxyApi, "threw", true); |
| delegateToCalls(proxyApi, "alwaysThrew", false, "threw"); |
| delegateToCalls(proxyApi, "returned", true); |
| delegateToCalls(proxyApi, "alwaysReturned", false, "returned"); |
| delegateToCalls(proxyApi, "calledWithNew", true); |
| delegateToCalls(proxyApi, "alwaysCalledWithNew", false, "calledWithNew"); |
| |
| function createProxy(func, originalFunc) { |
| const proxy = wrapFunction(func, originalFunc); |
| |
| // Inherit function properties: |
| extend(proxy, func); |
| |
| proxy.prototype = func.prototype; |
| |
| extend.nonEnum(proxy, proxyApi); |
| |
| return proxy; |
| } |
| |
| function wrapFunction(func, originalFunc) { |
| const arity = originalFunc.length; |
| let p; |
| // Do not change this to use an eval. Projects that depend on sinon block the use of eval. |
| // ref: https://github.com/sinonjs/sinon/issues/710 |
| switch (arity) { |
| /*eslint-disable no-unused-vars, max-len*/ |
| case 0: |
| p = function proxy() { |
| return p.invoke(func, this, slice(arguments)); |
| }; |
| break; |
| case 1: |
| p = function proxy(a) { |
| return p.invoke(func, this, slice(arguments)); |
| }; |
| break; |
| case 2: |
| p = function proxy(a, b) { |
| return p.invoke(func, this, slice(arguments)); |
| }; |
| break; |
| case 3: |
| p = function proxy(a, b, c) { |
| return p.invoke(func, this, slice(arguments)); |
| }; |
| break; |
| case 4: |
| p = function proxy(a, b, c, d) { |
| return p.invoke(func, this, slice(arguments)); |
| }; |
| break; |
| case 5: |
| p = function proxy(a, b, c, d, e) { |
| return p.invoke(func, this, slice(arguments)); |
| }; |
| break; |
| case 6: |
| p = function proxy(a, b, c, d, e, f) { |
| return p.invoke(func, this, slice(arguments)); |
| }; |
| break; |
| case 7: |
| p = function proxy(a, b, c, d, e, f, g) { |
| return p.invoke(func, this, slice(arguments)); |
| }; |
| break; |
| case 8: |
| p = function proxy(a, b, c, d, e, f, g, h) { |
| return p.invoke(func, this, slice(arguments)); |
| }; |
| break; |
| case 9: |
| p = function proxy(a, b, c, d, e, f, g, h, i) { |
| return p.invoke(func, this, slice(arguments)); |
| }; |
| break; |
| case 10: |
| p = function proxy(a, b, c, d, e, f, g, h, i, j) { |
| return p.invoke(func, this, slice(arguments)); |
| }; |
| break; |
| case 11: |
| p = function proxy(a, b, c, d, e, f, g, h, i, j, k) { |
| return p.invoke(func, this, slice(arguments)); |
| }; |
| break; |
| case 12: |
| p = function proxy(a, b, c, d, e, f, g, h, i, j, k, l) { |
| return p.invoke(func, this, slice(arguments)); |
| }; |
| break; |
| default: |
| p = function proxy() { |
| return p.invoke(func, this, slice(arguments)); |
| }; |
| break; |
| /*eslint-enable*/ |
| } |
| const nameDescriptor = Object.getOwnPropertyDescriptor( |
| originalFunc, |
| "name", |
| ); |
| if (nameDescriptor && nameDescriptor.configurable) { |
| // IE 11 functions don't have a name. |
| // Safari 9 has names that are not configurable. |
| Object.defineProperty(p, "name", nameDescriptor); |
| } |
| extend.nonEnum(p, { |
| isSinonProxy: true, |
| |
| called: false, |
| notCalled: true, |
| calledOnce: false, |
| calledTwice: false, |
| calledThrice: false, |
| callCount: 0, |
| firstCall: null, |
| firstArg: null, |
| secondCall: null, |
| thirdCall: null, |
| lastCall: null, |
| lastArg: null, |
| args: [], |
| returnValues: [], |
| thisValues: [], |
| exceptions: [], |
| callIds: [], |
| errorsWithCallStack: [], |
| }); |
| return p; |
| } |
| |
| module.exports = createProxy; |
| |
| },{"./proxy-call":15,"./proxy-call-util":14,"./proxy-invoke":16,"./spy-formatters":20,"./util/core/extend":25,"./util/core/function-to-string":26,"@sinonjs/commons":46,"util":90}],18:[function(require,module,exports){ |
| "use strict"; |
| |
| const walkObject = require("./util/core/walk-object"); |
| |
| function filter(object, property) { |
| return object[property].restore && object[property].restore.sinon; |
| } |
| |
| function restore(object, property) { |
| object[property].restore(); |
| } |
| |
| function restoreObject(object) { |
| return walkObject(restore, object, filter); |
| } |
| |
| module.exports = restoreObject; |
| |
| },{"./util/core/walk-object":36}],19:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const logger = require("@sinonjs/commons").deprecated; |
| const collectOwnMethods = require("./collect-own-methods"); |
| const getPropertyDescriptor = require("./util/core/get-property-descriptor"); |
| const isPropertyConfigurable = require("./util/core/is-property-configurable"); |
| const match = require("@sinonjs/samsam").createMatcher; |
| const sinonAssert = require("./assert"); |
| const sinonClock = require("./util/fake-timers"); |
| const sinonMock = require("./mock"); |
| const sinonSpy = require("./spy"); |
| const sinonStub = require("./stub"); |
| const sinonCreateStubInstance = require("./create-stub-instance"); |
| const sinonFake = require("./fake"); |
| const valueToString = require("@sinonjs/commons").valueToString; |
| |
| const DEFAULT_LEAK_THRESHOLD = 10000; |
| |
| const filter = arrayProto.filter; |
| const forEach = arrayProto.forEach; |
| const push = arrayProto.push; |
| const reverse = arrayProto.reverse; |
| |
| function applyOnEach(fakes, method) { |
| const matchingFakes = filter(fakes, function (fake) { |
| return typeof fake[method] === "function"; |
| }); |
| |
| forEach(matchingFakes, function (fake) { |
| fake[method](); |
| }); |
| } |
| |
| function throwOnAccessors(descriptor) { |
| if (typeof descriptor.get === "function") { |
| throw new Error("Use sandbox.replaceGetter for replacing getters"); |
| } |
| |
| if (typeof descriptor.set === "function") { |
| throw new Error("Use sandbox.replaceSetter for replacing setters"); |
| } |
| } |
| |
| function verifySameType(object, property, replacement) { |
| if (typeof object[property] !== typeof replacement) { |
| throw new TypeError( |
| `Cannot replace ${typeof object[ |
| property |
| ]} with ${typeof replacement}`, |
| ); |
| } |
| } |
| |
| function checkForValidArguments(descriptor, property, replacement) { |
| if (typeof descriptor === "undefined") { |
| throw new TypeError( |
| `Cannot replace non-existent property ${valueToString( |
| property, |
| )}. Perhaps you meant sandbox.define()?`, |
| ); |
| } |
| |
| if (typeof replacement === "undefined") { |
| throw new TypeError("Expected replacement argument to be defined"); |
| } |
| } |
| |
| /** |
| * A sinon sandbox |
| * |
| * @param opts |
| * @param {object} [opts.assertOptions] see the CreateAssertOptions in ./assert |
| * @class |
| */ |
| function Sandbox(opts = {}) { |
| const sandbox = this; |
| const assertOptions = opts.assertOptions || {}; |
| let fakeRestorers = []; |
| |
| let collection = []; |
| let loggedLeakWarning = false; |
| sandbox.leakThreshold = DEFAULT_LEAK_THRESHOLD; |
| |
| function addToCollection(object) { |
| if ( |
| push(collection, object) > sandbox.leakThreshold && |
| !loggedLeakWarning |
| ) { |
| // eslint-disable-next-line no-console |
| logger.printWarning( |
| "Potential memory leak detected; be sure to call restore() to clean up your sandbox. To suppress this warning, modify the leakThreshold property of your sandbox.", |
| ); |
| loggedLeakWarning = true; |
| } |
| } |
| |
| sandbox.assert = sinonAssert.createAssertObject(assertOptions); |
| |
| // this is for testing only |
| sandbox.getFakes = function getFakes() { |
| return collection; |
| }; |
| |
| sandbox.createStubInstance = function createStubInstance() { |
| const stubbed = sinonCreateStubInstance.apply(null, arguments); |
| |
| const ownMethods = collectOwnMethods(stubbed); |
| |
| forEach(ownMethods, function (method) { |
| addToCollection(method); |
| }); |
| |
| return stubbed; |
| }; |
| |
| sandbox.inject = function inject(obj) { |
| obj.spy = function () { |
| return sandbox.spy.apply(null, arguments); |
| }; |
| |
| obj.stub = function () { |
| return sandbox.stub.apply(null, arguments); |
| }; |
| |
| obj.mock = function () { |
| return sandbox.mock.apply(null, arguments); |
| }; |
| |
| obj.createStubInstance = function () { |
| return sandbox.createStubInstance.apply(sandbox, arguments); |
| }; |
| |
| obj.fake = function () { |
| return sandbox.fake.apply(null, arguments); |
| }; |
| |
| obj.define = function () { |
| return sandbox.define.apply(null, arguments); |
| }; |
| |
| obj.replace = function () { |
| return sandbox.replace.apply(null, arguments); |
| }; |
| |
| obj.replaceSetter = function () { |
| return sandbox.replaceSetter.apply(null, arguments); |
| }; |
| |
| obj.replaceGetter = function () { |
| return sandbox.replaceGetter.apply(null, arguments); |
| }; |
| |
| if (sandbox.clock) { |
| obj.clock = sandbox.clock; |
| } |
| |
| obj.match = match; |
| |
| return obj; |
| }; |
| |
| sandbox.mock = function mock() { |
| const m = sinonMock.apply(null, arguments); |
| |
| addToCollection(m); |
| |
| return m; |
| }; |
| |
| sandbox.reset = function reset() { |
| applyOnEach(collection, "reset"); |
| applyOnEach(collection, "resetHistory"); |
| }; |
| |
| sandbox.resetBehavior = function resetBehavior() { |
| applyOnEach(collection, "resetBehavior"); |
| }; |
| |
| sandbox.resetHistory = function resetHistory() { |
| function privateResetHistory(f) { |
| const method = f.resetHistory || f.reset; |
| if (method) { |
| method.call(f); |
| } |
| } |
| |
| forEach(collection, privateResetHistory); |
| }; |
| |
| sandbox.restore = function restore() { |
| if (arguments.length) { |
| throw new Error( |
| "sandbox.restore() does not take any parameters. Perhaps you meant stub.restore()", |
| ); |
| } |
| |
| reverse(collection); |
| applyOnEach(collection, "restore"); |
| collection = []; |
| |
| forEach(fakeRestorers, function (restorer) { |
| restorer(); |
| }); |
| fakeRestorers = []; |
| |
| sandbox.restoreContext(); |
| }; |
| |
| sandbox.restoreContext = function restoreContext() { |
| if (!sandbox.injectedKeys) { |
| return; |
| } |
| |
| forEach(sandbox.injectedKeys, function (injectedKey) { |
| delete sandbox.injectInto[injectedKey]; |
| }); |
| |
| sandbox.injectedKeys.length = 0; |
| }; |
| |
| /** |
| * Creates a restorer function for the property |
| * |
| * @param {object|Function} object |
| * @param {string} property |
| * @param {boolean} forceAssignment |
| * @returns {Function} restorer function |
| */ |
| function getFakeRestorer(object, property, forceAssignment = false) { |
| const descriptor = getPropertyDescriptor(object, property); |
| const value = forceAssignment && object[property]; |
| |
| function restorer() { |
| if (forceAssignment) { |
| object[property] = value; |
| } else if (descriptor?.isOwn) { |
| Object.defineProperty(object, property, descriptor); |
| } else { |
| delete object[property]; |
| } |
| } |
| |
| restorer.object = object; |
| restorer.property = property; |
| return restorer; |
| } |
| |
| function verifyNotReplaced(object, property) { |
| forEach(fakeRestorers, function (fakeRestorer) { |
| if ( |
| fakeRestorer.object === object && |
| fakeRestorer.property === property |
| ) { |
| throw new TypeError( |
| `Attempted to replace ${property} which is already replaced`, |
| ); |
| } |
| }); |
| } |
| |
| /** |
| * Replace an existing property |
| * |
| * @param {object|Function} object |
| * @param {string} property |
| * @param {*} replacement a fake, stub, spy or any other value |
| * @returns {*} |
| */ |
| sandbox.replace = function replace(object, property, replacement) { |
| const descriptor = getPropertyDescriptor(object, property); |
| checkForValidArguments(descriptor, property, replacement); |
| throwOnAccessors(descriptor); |
| verifySameType(object, property, replacement); |
| |
| verifyNotReplaced(object, property); |
| |
| // store a function for restoring the replaced property |
| push(fakeRestorers, getFakeRestorer(object, property)); |
| |
| object[property] = replacement; |
| |
| return replacement; |
| }; |
| |
| sandbox.replace.usingAccessor = function replaceUsingAccessor( |
| object, |
| property, |
| replacement, |
| ) { |
| const descriptor = getPropertyDescriptor(object, property); |
| checkForValidArguments(descriptor, property, replacement); |
| verifySameType(object, property, replacement); |
| |
| verifyNotReplaced(object, property); |
| |
| // store a function for restoring the replaced property |
| push(fakeRestorers, getFakeRestorer(object, property, true)); |
| |
| object[property] = replacement; |
| |
| return replacement; |
| }; |
| |
| sandbox.define = function define(object, property, value) { |
| const descriptor = getPropertyDescriptor(object, property); |
| |
| if (descriptor) { |
| throw new TypeError( |
| `Cannot define the already existing property ${valueToString( |
| property, |
| )}. Perhaps you meant sandbox.replace()?`, |
| ); |
| } |
| |
| if (typeof value === "undefined") { |
| throw new TypeError("Expected value argument to be defined"); |
| } |
| |
| verifyNotReplaced(object, property); |
| |
| // store a function for restoring the defined property |
| push(fakeRestorers, getFakeRestorer(object, property)); |
| |
| object[property] = value; |
| |
| return value; |
| }; |
| |
| sandbox.replaceGetter = function replaceGetter( |
| object, |
| property, |
| replacement, |
| ) { |
| const descriptor = getPropertyDescriptor(object, property); |
| |
| if (typeof descriptor === "undefined") { |
| throw new TypeError( |
| `Cannot replace non-existent property ${valueToString( |
| property, |
| )}`, |
| ); |
| } |
| |
| if (typeof replacement !== "function") { |
| throw new TypeError( |
| "Expected replacement argument to be a function", |
| ); |
| } |
| |
| if (typeof descriptor.get !== "function") { |
| throw new Error("`object.property` is not a getter"); |
| } |
| |
| verifyNotReplaced(object, property); |
| |
| // store a function for restoring the replaced property |
| push(fakeRestorers, getFakeRestorer(object, property)); |
| |
| Object.defineProperty(object, property, { |
| get: replacement, |
| configurable: isPropertyConfigurable(object, property), |
| }); |
| |
| return replacement; |
| }; |
| |
| sandbox.replaceSetter = function replaceSetter( |
| object, |
| property, |
| replacement, |
| ) { |
| const descriptor = getPropertyDescriptor(object, property); |
| |
| if (typeof descriptor === "undefined") { |
| throw new TypeError( |
| `Cannot replace non-existent property ${valueToString( |
| property, |
| )}`, |
| ); |
| } |
| |
| if (typeof replacement !== "function") { |
| throw new TypeError( |
| "Expected replacement argument to be a function", |
| ); |
| } |
| |
| if (typeof descriptor.set !== "function") { |
| throw new Error("`object.property` is not a setter"); |
| } |
| |
| verifyNotReplaced(object, property); |
| |
| // store a function for restoring the replaced property |
| push(fakeRestorers, getFakeRestorer(object, property)); |
| |
| // eslint-disable-next-line accessor-pairs |
| Object.defineProperty(object, property, { |
| set: replacement, |
| configurable: isPropertyConfigurable(object, property), |
| }); |
| |
| return replacement; |
| }; |
| |
| function commonPostInitSetup(args, spy) { |
| const [object, property, types] = args; |
| |
| const isSpyingOnEntireObject = |
| typeof property === "undefined" && typeof object === "object"; |
| |
| if (isSpyingOnEntireObject) { |
| const ownMethods = collectOwnMethods(spy); |
| |
| forEach(ownMethods, function (method) { |
| addToCollection(method); |
| }); |
| } else if (Array.isArray(types)) { |
| for (const accessorType of types) { |
| addToCollection(spy[accessorType]); |
| } |
| } else { |
| addToCollection(spy); |
| } |
| |
| return spy; |
| } |
| |
| sandbox.spy = function spy() { |
| const createdSpy = sinonSpy.apply(sinonSpy, arguments); |
| return commonPostInitSetup(arguments, createdSpy); |
| }; |
| |
| sandbox.stub = function stub() { |
| const createdStub = sinonStub.apply(sinonStub, arguments); |
| return commonPostInitSetup(arguments, createdStub); |
| }; |
| |
| // eslint-disable-next-line no-unused-vars |
| sandbox.fake = function fake(f) { |
| const s = sinonFake.apply(sinonFake, arguments); |
| |
| addToCollection(s); |
| |
| return s; |
| }; |
| |
| forEach(Object.keys(sinonFake), function (key) { |
| const fakeBehavior = sinonFake[key]; |
| if (typeof fakeBehavior === "function") { |
| sandbox.fake[key] = function () { |
| const s = fakeBehavior.apply(fakeBehavior, arguments); |
| |
| addToCollection(s); |
| |
| return s; |
| }; |
| } |
| }); |
| |
| sandbox.useFakeTimers = function useFakeTimers(args) { |
| const clock = sinonClock.useFakeTimers.call(null, args); |
| |
| sandbox.clock = clock; |
| addToCollection(clock); |
| |
| return clock; |
| }; |
| |
| sandbox.verify = function verify() { |
| applyOnEach(collection, "verify"); |
| }; |
| |
| sandbox.verifyAndRestore = function verifyAndRestore() { |
| let exception; |
| |
| try { |
| sandbox.verify(); |
| } catch (e) { |
| exception = e; |
| } |
| |
| sandbox.restore(); |
| |
| if (exception) { |
| throw exception; |
| } |
| }; |
| } |
| |
| Sandbox.prototype.match = match; |
| |
| module.exports = Sandbox; |
| |
| },{"./assert":3,"./collect-own-methods":5,"./create-stub-instance":8,"./fake":10,"./mock":12,"./spy":21,"./stub":22,"./util/core/get-property-descriptor":28,"./util/core/is-property-configurable":31,"./util/fake-timers":39,"@sinonjs/commons":46,"@sinonjs/samsam":86}],20:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const Colorizer = require("./colorizer"); |
| const colororizer = new Colorizer(); |
| const match = require("@sinonjs/samsam").createMatcher; |
| const timesInWords = require("./util/core/times-in-words"); |
| const inspect = require("util").inspect; |
| const jsDiff = require("diff"); |
| |
| const join = arrayProto.join; |
| const map = arrayProto.map; |
| const push = arrayProto.push; |
| const slice = arrayProto.slice; |
| |
| /** |
| * |
| * @param matcher |
| * @param calledArg |
| * @param calledArgMessage |
| * |
| * @returns {string} the colored text |
| */ |
| function colorSinonMatchText(matcher, calledArg, calledArgMessage) { |
| let calledArgumentMessage = calledArgMessage; |
| let matcherMessage = matcher.message; |
| if (!matcher.test(calledArg)) { |
| matcherMessage = colororizer.red(matcher.message); |
| if (calledArgumentMessage) { |
| calledArgumentMessage = colororizer.green(calledArgumentMessage); |
| } |
| } |
| return `${calledArgumentMessage} ${matcherMessage}`; |
| } |
| |
| /** |
| * @param diff |
| * |
| * @returns {string} the colored diff |
| */ |
| function colorDiffText(diff) { |
| const objects = map(diff, function (part) { |
| let text = part.value; |
| if (part.added) { |
| text = colororizer.green(text); |
| } else if (part.removed) { |
| text = colororizer.red(text); |
| } |
| if (diff.length === 2) { |
| text += " "; // format simple diffs |
| } |
| return text; |
| }); |
| return join(objects, ""); |
| } |
| |
| /** |
| * |
| * @param value |
| * @returns {string} a quoted string |
| */ |
| function quoteStringValue(value) { |
| if (typeof value === "string") { |
| return JSON.stringify(value); |
| } |
| return value; |
| } |
| |
| module.exports = { |
| c: function (spyInstance) { |
| return timesInWords(spyInstance.callCount); |
| }, |
| |
| n: function (spyInstance) { |
| // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods |
| return spyInstance.toString(); |
| }, |
| |
| D: function (spyInstance, args) { |
| let message = ""; |
| |
| for (let i = 0, l = spyInstance.callCount; i < l; ++i) { |
| // describe multiple calls |
| if (l > 1) { |
| message += `\nCall ${i + 1}:`; |
| } |
| const calledArgs = spyInstance.getCall(i).args; |
| const expectedArgs = slice(args); |
| |
| for ( |
| let j = 0; |
| j < calledArgs.length || j < expectedArgs.length; |
| ++j |
| ) { |
| let calledArg = calledArgs[j]; |
| let expectedArg = expectedArgs[j]; |
| if (calledArg) { |
| calledArg = quoteStringValue(calledArg); |
| } |
| |
| if (expectedArg) { |
| expectedArg = quoteStringValue(expectedArg); |
| } |
| |
| message += "\n"; |
| |
| const calledArgMessage = |
| j < calledArgs.length ? inspect(calledArg) : ""; |
| if (match.isMatcher(expectedArg)) { |
| message += colorSinonMatchText( |
| expectedArg, |
| calledArg, |
| calledArgMessage, |
| ); |
| } else { |
| const expectedArgMessage = |
| j < expectedArgs.length ? inspect(expectedArg) : ""; |
| const diff = jsDiff.diffJson( |
| calledArgMessage, |
| expectedArgMessage, |
| ); |
| message += colorDiffText(diff); |
| } |
| } |
| } |
| |
| return message; |
| }, |
| |
| C: function (spyInstance) { |
| const calls = []; |
| |
| for (let i = 0, l = spyInstance.callCount; i < l; ++i) { |
| // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods |
| let stringifiedCall = ` ${spyInstance.getCall(i).toString()}`; |
| if (/\n/.test(calls[i - 1])) { |
| stringifiedCall = `\n${stringifiedCall}`; |
| } |
| push(calls, stringifiedCall); |
| } |
| |
| return calls.length > 0 ? `\n${join(calls, "\n")}` : ""; |
| }, |
| |
| t: function (spyInstance) { |
| const objects = []; |
| |
| for (let i = 0, l = spyInstance.callCount; i < l; ++i) { |
| push(objects, inspect(spyInstance.thisValues[i])); |
| } |
| |
| return join(objects, ", "); |
| }, |
| |
| "*": function (spyInstance, args) { |
| return join( |
| map(args, function (arg) { |
| return inspect(arg); |
| }), |
| ", ", |
| ); |
| }, |
| }; |
| |
| },{"./colorizer":6,"./util/core/times-in-words":35,"@sinonjs/commons":46,"@sinonjs/samsam":86,"diff":91,"util":90}],21:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const createProxy = require("./proxy"); |
| const extend = require("./util/core/extend"); |
| const functionName = require("@sinonjs/commons").functionName; |
| const getPropertyDescriptor = require("./util/core/get-property-descriptor"); |
| const deepEqual = require("@sinonjs/samsam").deepEqual; |
| const isEsModule = require("./util/core/is-es-module"); |
| const proxyCallUtil = require("./proxy-call-util"); |
| const walkObject = require("./util/core/walk-object"); |
| const wrapMethod = require("./util/core/wrap-method"); |
| const valueToString = require("@sinonjs/commons").valueToString; |
| |
| /* cache references to library methods so that they also can be stubbed without problems */ |
| const forEach = arrayProto.forEach; |
| const pop = arrayProto.pop; |
| const push = arrayProto.push; |
| const slice = arrayProto.slice; |
| const filter = Array.prototype.filter; |
| |
| let uuid = 0; |
| |
| function matches(fake, args, strict) { |
| const margs = fake.matchingArguments; |
| if ( |
| margs.length <= args.length && |
| deepEqual(slice(args, 0, margs.length), margs) |
| ) { |
| return !strict || margs.length === args.length; |
| } |
| return false; |
| } |
| |
| // Public API |
| const spyApi = { |
| withArgs: function () { |
| const args = slice(arguments); |
| const matching = pop(this.matchingFakes(args, true)); |
| if (matching) { |
| return matching; |
| } |
| |
| const original = this; |
| const fake = this.instantiateFake(); |
| fake.matchingArguments = args; |
| fake.parent = this; |
| push(this.fakes, fake); |
| |
| fake.withArgs = function () { |
| return original.withArgs.apply(original, arguments); |
| }; |
| |
| forEach(original.args, function (arg, i) { |
| if (!matches(fake, arg)) { |
| return; |
| } |
| |
| proxyCallUtil.incrementCallCount(fake); |
| push(fake.thisValues, original.thisValues[i]); |
| push(fake.args, arg); |
| push(fake.returnValues, original.returnValues[i]); |
| push(fake.exceptions, original.exceptions[i]); |
| push(fake.callIds, original.callIds[i]); |
| }); |
| |
| proxyCallUtil.createCallProperties(fake); |
| |
| return fake; |
| }, |
| |
| // Override proxy default implementation |
| matchingFakes: function (args, strict) { |
| return filter.call(this.fakes, function (fake) { |
| return matches(fake, args, strict); |
| }); |
| }, |
| }; |
| |
| /* eslint-disable @sinonjs/no-prototype-methods/no-prototype-methods */ |
| const delegateToCalls = proxyCallUtil.delegateToCalls; |
| delegateToCalls(spyApi, "callArg", false, "callArgWith", true, function () { |
| throw new Error( |
| `${this.toString()} cannot call arg since it was not yet invoked.`, |
| ); |
| }); |
| spyApi.callArgWith = spyApi.callArg; |
| delegateToCalls(spyApi, "callArgOn", false, "callArgOnWith", true, function () { |
| throw new Error( |
| `${this.toString()} cannot call arg since it was not yet invoked.`, |
| ); |
| }); |
| spyApi.callArgOnWith = spyApi.callArgOn; |
| delegateToCalls(spyApi, "throwArg", false, "throwArg", false, function () { |
| throw new Error( |
| `${this.toString()} cannot throw arg since it was not yet invoked.`, |
| ); |
| }); |
| delegateToCalls(spyApi, "yield", false, "yield", true, function () { |
| throw new Error( |
| `${this.toString()} cannot yield since it was not yet invoked.`, |
| ); |
| }); |
| // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode. |
| spyApi.invokeCallback = spyApi.yield; |
| delegateToCalls(spyApi, "yieldOn", false, "yieldOn", true, function () { |
| throw new Error( |
| `${this.toString()} cannot yield since it was not yet invoked.`, |
| ); |
| }); |
| delegateToCalls(spyApi, "yieldTo", false, "yieldTo", true, function (property) { |
| throw new Error( |
| `${this.toString()} cannot yield to '${valueToString( |
| property, |
| )}' since it was not yet invoked.`, |
| ); |
| }); |
| delegateToCalls( |
| spyApi, |
| "yieldToOn", |
| false, |
| "yieldToOn", |
| true, |
| function (property) { |
| throw new Error( |
| `${this.toString()} cannot yield to '${valueToString( |
| property, |
| )}' since it was not yet invoked.`, |
| ); |
| }, |
| ); |
| |
| function createSpy(func) { |
| let name; |
| let funk = func; |
| |
| if (typeof funk !== "function") { |
| funk = function () { |
| return; |
| }; |
| } else { |
| name = functionName(funk); |
| } |
| |
| const proxy = createProxy(funk, funk); |
| |
| // Inherit spy API: |
| extend.nonEnum(proxy, spyApi); |
| extend.nonEnum(proxy, { |
| displayName: name || "spy", |
| fakes: [], |
| instantiateFake: createSpy, |
| id: `spy#${uuid++}`, |
| }); |
| return proxy; |
| } |
| |
| function spy(object, property, types) { |
| if (isEsModule(object)) { |
| throw new TypeError("ES Modules cannot be spied"); |
| } |
| |
| if (!property && typeof object === "function") { |
| return createSpy(object); |
| } |
| |
| if (!property && typeof object === "object") { |
| return walkObject(spy, object); |
| } |
| |
| if (!object && !property) { |
| return createSpy(function () { |
| return; |
| }); |
| } |
| |
| if (!types) { |
| return wrapMethod(object, property, createSpy(object[property])); |
| } |
| |
| const descriptor = {}; |
| const methodDesc = getPropertyDescriptor(object, property); |
| |
| forEach(types, function (type) { |
| descriptor[type] = createSpy(methodDesc[type]); |
| }); |
| |
| return wrapMethod(object, property, descriptor); |
| } |
| |
| extend(spy, spyApi); |
| module.exports = spy; |
| |
| },{"./proxy":17,"./proxy-call-util":14,"./util/core/extend":25,"./util/core/get-property-descriptor":28,"./util/core/is-es-module":29,"./util/core/walk-object":36,"./util/core/wrap-method":38,"@sinonjs/commons":46,"@sinonjs/samsam":86}],22:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const behavior = require("./behavior"); |
| const behaviors = require("./default-behaviors"); |
| const createProxy = require("./proxy"); |
| const functionName = require("@sinonjs/commons").functionName; |
| const hasOwnProperty = |
| require("@sinonjs/commons").prototypes.object.hasOwnProperty; |
| const isNonExistentProperty = require("./util/core/is-non-existent-property"); |
| const spy = require("./spy"); |
| const extend = require("./util/core/extend"); |
| const getPropertyDescriptor = require("./util/core/get-property-descriptor"); |
| const isEsModule = require("./util/core/is-es-module"); |
| const sinonType = require("./util/core/sinon-type"); |
| const wrapMethod = require("./util/core/wrap-method"); |
| const throwOnFalsyObject = require("./throw-on-falsy-object"); |
| const valueToString = require("@sinonjs/commons").valueToString; |
| const walkObject = require("./util/core/walk-object"); |
| |
| const forEach = arrayProto.forEach; |
| const pop = arrayProto.pop; |
| const slice = arrayProto.slice; |
| const sort = arrayProto.sort; |
| |
| let uuid = 0; |
| |
| function createStub(originalFunc) { |
| // eslint-disable-next-line prefer-const |
| let proxy; |
| |
| function functionStub() { |
| const args = slice(arguments); |
| const matchings = proxy.matchingFakes(args); |
| |
| const fnStub = |
| pop( |
| sort(matchings, function (a, b) { |
| return ( |
| a.matchingArguments.length - b.matchingArguments.length |
| ); |
| }), |
| ) || proxy; |
| return getCurrentBehavior(fnStub).invoke(this, arguments); |
| } |
| |
| proxy = createProxy(functionStub, originalFunc || functionStub); |
| // Inherit spy API: |
| extend.nonEnum(proxy, spy); |
| // Inherit stub API: |
| extend.nonEnum(proxy, stub); |
| |
| const name = originalFunc ? functionName(originalFunc) : null; |
| extend.nonEnum(proxy, { |
| fakes: [], |
| instantiateFake: createStub, |
| displayName: name || "stub", |
| defaultBehavior: null, |
| behaviors: [], |
| id: `stub#${uuid++}`, |
| }); |
| |
| sinonType.set(proxy, "stub"); |
| |
| return proxy; |
| } |
| |
| function stub(object, property) { |
| if (arguments.length > 2) { |
| throw new TypeError( |
| "stub(obj, 'meth', fn) has been removed, see documentation", |
| ); |
| } |
| |
| if (isEsModule(object)) { |
| throw new TypeError("ES Modules cannot be stubbed"); |
| } |
| |
| throwOnFalsyObject.apply(null, arguments); |
| |
| if (isNonExistentProperty(object, property)) { |
| throw new TypeError( |
| `Cannot stub non-existent property ${valueToString(property)}`, |
| ); |
| } |
| |
| const actualDescriptor = getPropertyDescriptor(object, property); |
| |
| assertValidPropertyDescriptor(actualDescriptor, property); |
| |
| const isObjectOrFunction = |
| typeof object === "object" || typeof object === "function"; |
| const isStubbingEntireObject = |
| typeof property === "undefined" && isObjectOrFunction; |
| const isCreatingNewStub = !object && typeof property === "undefined"; |
| const isStubbingNonFuncProperty = |
| isObjectOrFunction && |
| typeof property !== "undefined" && |
| (typeof actualDescriptor === "undefined" || |
| typeof actualDescriptor.value !== "function"); |
| |
| if (isStubbingEntireObject) { |
| return walkObject(stub, object); |
| } |
| |
| if (isCreatingNewStub) { |
| return createStub(); |
| } |
| |
| const func = |
| typeof actualDescriptor.value === "function" |
| ? actualDescriptor.value |
| : null; |
| const s = createStub(func); |
| |
| extend.nonEnum(s, { |
| rootObj: object, |
| propName: property, |
| shadowsPropOnPrototype: !actualDescriptor.isOwn, |
| restore: function restore() { |
| if (actualDescriptor !== undefined && actualDescriptor.isOwn) { |
| Object.defineProperty(object, property, actualDescriptor); |
| return; |
| } |
| |
| delete object[property]; |
| }, |
| }); |
| |
| return isStubbingNonFuncProperty ? s : wrapMethod(object, property, s); |
| } |
| |
| function assertValidPropertyDescriptor(descriptor, property) { |
| if (!descriptor || !property) { |
| return; |
| } |
| if (descriptor.isOwn && !descriptor.configurable && !descriptor.writable) { |
| throw new TypeError( |
| `Descriptor for property ${property} is non-configurable and non-writable`, |
| ); |
| } |
| if ((descriptor.get || descriptor.set) && !descriptor.configurable) { |
| throw new TypeError( |
| `Descriptor for accessor property ${property} is non-configurable`, |
| ); |
| } |
| if (isDataDescriptor(descriptor) && !descriptor.writable) { |
| throw new TypeError( |
| `Descriptor for data property ${property} is non-writable`, |
| ); |
| } |
| } |
| |
| function isDataDescriptor(descriptor) { |
| return ( |
| !descriptor.value && |
| !descriptor.writable && |
| !descriptor.set && |
| !descriptor.get |
| ); |
| } |
| |
| /*eslint-disable no-use-before-define*/ |
| function getParentBehaviour(stubInstance) { |
| return stubInstance.parent && getCurrentBehavior(stubInstance.parent); |
| } |
| |
| function getDefaultBehavior(stubInstance) { |
| return ( |
| stubInstance.defaultBehavior || |
| getParentBehaviour(stubInstance) || |
| behavior.create(stubInstance) |
| ); |
| } |
| |
| function getCurrentBehavior(stubInstance) { |
| const currentBehavior = stubInstance.behaviors[stubInstance.callCount - 1]; |
| return currentBehavior && currentBehavior.isPresent() |
| ? currentBehavior |
| : getDefaultBehavior(stubInstance); |
| } |
| /*eslint-enable no-use-before-define*/ |
| |
| const proto = { |
| resetBehavior: function () { |
| this.defaultBehavior = null; |
| this.behaviors = []; |
| |
| delete this.returnValue; |
| delete this.returnArgAt; |
| delete this.throwArgAt; |
| delete this.resolveArgAt; |
| delete this.fakeFn; |
| this.returnThis = false; |
| this.resolveThis = false; |
| |
| forEach(this.fakes, function (fake) { |
| fake.resetBehavior(); |
| }); |
| }, |
| |
| reset: function () { |
| this.resetHistory(); |
| this.resetBehavior(); |
| }, |
| |
| onCall: function onCall(index) { |
| if (!this.behaviors[index]) { |
| this.behaviors[index] = behavior.create(this); |
| } |
| |
| return this.behaviors[index]; |
| }, |
| |
| onFirstCall: function onFirstCall() { |
| return this.onCall(0); |
| }, |
| |
| onSecondCall: function onSecondCall() { |
| return this.onCall(1); |
| }, |
| |
| onThirdCall: function onThirdCall() { |
| return this.onCall(2); |
| }, |
| |
| withArgs: function withArgs() { |
| const fake = spy.withArgs.apply(this, arguments); |
| if (this.defaultBehavior && this.defaultBehavior.promiseLibrary) { |
| fake.defaultBehavior = |
| fake.defaultBehavior || behavior.create(fake); |
| fake.defaultBehavior.promiseLibrary = |
| this.defaultBehavior.promiseLibrary; |
| } |
| return fake; |
| }, |
| }; |
| |
| forEach(Object.keys(behavior), function (method) { |
| if ( |
| hasOwnProperty(behavior, method) && |
| !hasOwnProperty(proto, method) && |
| method !== "create" && |
| method !== "invoke" |
| ) { |
| proto[method] = behavior.createBehavior(method); |
| } |
| }); |
| |
| forEach(Object.keys(behaviors), function (method) { |
| if (hasOwnProperty(behaviors, method) && !hasOwnProperty(proto, method)) { |
| behavior.addBehavior(stub, method, behaviors[method]); |
| } |
| }); |
| |
| extend(stub, proto); |
| module.exports = stub; |
| |
| },{"./behavior":4,"./default-behaviors":9,"./proxy":17,"./spy":21,"./throw-on-falsy-object":23,"./util/core/extend":25,"./util/core/get-property-descriptor":28,"./util/core/is-es-module":29,"./util/core/is-non-existent-property":30,"./util/core/sinon-type":34,"./util/core/walk-object":36,"./util/core/wrap-method":38,"@sinonjs/commons":46}],23:[function(require,module,exports){ |
| "use strict"; |
| const valueToString = require("@sinonjs/commons").valueToString; |
| |
| function throwOnFalsyObject(object, property) { |
| if (property && !object) { |
| const type = object === null ? "null" : "undefined"; |
| throw new Error( |
| `Trying to stub property '${valueToString(property)}' of ${type}`, |
| ); |
| } |
| } |
| |
| module.exports = throwOnFalsyObject; |
| |
| },{"@sinonjs/commons":46}],24:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const reduce = arrayProto.reduce; |
| |
| module.exports = function exportAsyncBehaviors(behaviorMethods) { |
| return reduce( |
| Object.keys(behaviorMethods), |
| function (acc, method) { |
| // need to avoid creating another async versions of the newly added async methods |
| if (method.match(/^(callsArg|yields)/) && !method.match(/Async/)) { |
| acc[`${method}Async`] = function () { |
| const result = behaviorMethods[method].apply( |
| this, |
| arguments, |
| ); |
| this.callbackAsync = true; |
| return result; |
| }; |
| } |
| return acc; |
| }, |
| {}, |
| ); |
| }; |
| |
| },{"@sinonjs/commons":46}],25:[function(require,module,exports){ |
| "use strict"; |
| |
| const arrayProto = require("@sinonjs/commons").prototypes.array; |
| const hasOwnProperty = |
| require("@sinonjs/commons").prototypes.object.hasOwnProperty; |
| |
| const join = arrayProto.join; |
| const push = arrayProto.push; |
| |
| // Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug |
| const hasDontEnumBug = (function () { |
| const obj = { |
| constructor: function () { |
| return "0"; |
| }, |
| toString: function () { |
| return "1"; |
| }, |
| valueOf: function () { |
| return "2"; |
| }, |
| toLocaleString: function () { |
| return "3"; |
| }, |
| prototype: function () { |
| return "4"; |
| }, |
| isPrototypeOf: function () { |
| return "5"; |
| }, |
| propertyIsEnumerable: function () { |
| return "6"; |
| }, |
| hasOwnProperty: function () { |
| return "7"; |
| }, |
| length: function () { |
| return "8"; |
| }, |
| unique: function () { |
| return "9"; |
| }, |
| }; |
| |
| const result = []; |
| for (const prop in obj) { |
| if (hasOwnProperty(obj, prop)) { |
| push(result, obj[prop]()); |
| } |
| } |
| return join(result, "") !== "0123456789"; |
| })(); |
| |
| /** |
| * |
| * @param target |
| * @param sources |
| * @param doCopy |
| * @returns {*} target |
| */ |
| function extendCommon(target, sources, doCopy) { |
| let source, i, prop; |
| |
| for (i = 0; i < sources.length; i++) { |
| source = sources[i]; |
| |
| for (prop in source) { |
| if (hasOwnProperty(source, prop)) { |
| doCopy(target, source, prop); |
| } |
| } |
| |
| // Make sure we copy (own) toString method even when in JScript with DontEnum bug |
| // See https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug |
| if ( |
| hasDontEnumBug && |
| hasOwnProperty(source, "toString") && |
| source.toString !== target.toString |
| ) { |
| target.toString = source.toString; |
| } |
| } |
| |
| return target; |
| } |
| |
| /** |
| * Public: Extend target in place with all (own) properties, except 'name' when [[writable]] is false, |
| * from sources in-order. Thus, last source will override properties in previous sources. |
| * |
| * @param {object} target - The Object to extend |
| * @param {object[]} sources - Objects to copy properties from. |
| * @returns {object} the extended target |
| */ |
| module.exports = function extend(target, ...sources) { |
| return extendCommon( |
| target, |
| sources, |
| function copyValue(dest, source, prop) { |
| const destOwnPropertyDescriptor = Object.getOwnPropertyDescriptor( |
| dest, |
| prop, |
| ); |
| const sourceOwnPropertyDescriptor = Object.getOwnPropertyDescriptor( |
| source, |
| prop, |
| ); |
| |
| if (prop === "name" && !destOwnPropertyDescriptor.writable) { |
| return; |
| } |
| const descriptors = { |
| configurable: sourceOwnPropertyDescriptor.configurable, |
| enumerable: sourceOwnPropertyDescriptor.enumerable, |
| }; |
| /* |
| if the source has an Accessor property copy over the accessor functions (get and set) |
| data properties has writable attribute where as accessor property don't |
| REF: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#properties |
| */ |
| |
| if (hasOwnProperty(sourceOwnPropertyDescriptor, "writable")) { |
| descriptors.writable = sourceOwnPropertyDescriptor.writable; |
| descriptors.value = sourceOwnPropertyDescriptor.value; |
| } else { |
| if (sourceOwnPropertyDescriptor.get) { |
| descriptors.get = |
| sourceOwnPropertyDescriptor.get.bind(dest); |
| } |
| if (sourceOwnPropertyDescriptor.set) { |
| descriptors.set = |
| sourceOwnPropertyDescriptor.set.bind(dest); |
| } |
| } |
| Object.defineProperty(dest, prop, descriptors); |
| }, |
| ); |
| }; |
| |
| /** |
| * Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will |
| * override properties in previous sources. Define the properties as non enumerable. |
| * |
| * @param {object} target - The Object to extend |
| * @param {object[]} sources - Objects to copy properties from. |
| * @returns {object} the extended target |
| */ |
| module.exports.nonEnum = function extendNonEnum(target, ...sources) { |
| return extendCommon( |
| target, |
| sources, |
| function copyProperty(dest, source, prop) { |
| Object.defineProperty(dest, prop, { |
| value: source[prop], |
| enumerable: false, |
| configurable: true, |
| writable: true, |
| }); |
| }, |
| ); |
| }; |
| |
| },{"@sinonjs/commons":46}],26:[function(require,module,exports){ |
| "use strict"; |
| |
| module.exports = function toString() { |
| let i, prop, thisValue; |
| if (this.getCall && this.callCount) { |
| i = this.callCount; |
| |
| while (i--) { |
| thisValue = this.getCall(i).thisValue; |
| |
| // eslint-disable-next-line guard-for-in |
| for (prop in thisValue) { |
| try { |
| if (thisValue[prop] === this) { |
| return prop; |
| } |
| } catch (e) { |
| // no-op - accessing props can throw an error, nothing to do here |
| } |
| } |
| } |
| } |
| |
| return this.displayName || "sinon fake"; |
| }; |
| |
| },{}],27:[function(require,module,exports){ |
| "use strict"; |
| |
| /* istanbul ignore next : not testing that setTimeout works */ |
| function nextTick(callback) { |
| setTimeout(callback, 0); |
| } |
| |
| module.exports = function getNextTick(process, setImmediate) { |
| if (typeof process === "object" && typeof process.nextTick === "function") { |
| return process.nextTick; |
| } |
| |
| if (typeof setImmediate === "function") { |
| return setImmediate; |
| } |
| |
| return nextTick; |
| }; |
| |
| },{}],28:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * @typedef {object} PropertyDescriptor |
| * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty#description |
| * @property {boolean} configurable defaults to false |
| * @property {boolean} enumerable defaults to false |
| * @property {boolean} writable defaults to false |
| * @property {*} value defaults to undefined |
| * @property {Function} get defaults to undefined |
| * @property {Function} set defaults to undefined |
| */ |
| |
| /* |
| * The following type def is strictly speaking illegal in JSDoc, but the expression forms a |
| * legal Typescript union type and is understood by Visual Studio and the IntelliJ |
| * family of editors. The "TS" flavor of JSDoc is becoming the de-facto standard these |
| * days for that reason (and the fact that JSDoc is essentially unmaintained) |
| */ |
| |
| /** |
| * @typedef {{isOwn: boolean} & PropertyDescriptor} SinonPropertyDescriptor |
| * a slightly enriched property descriptor |
| * @property {boolean} isOwn true if the descriptor is owned by this object, false if it comes from the prototype |
| */ |
| |
| /** |
| * Returns a slightly modified property descriptor that one can tell is from the object or the prototype |
| * |
| * @param {*} object |
| * @param {string} property |
| * @returns {SinonPropertyDescriptor} |
| */ |
| function getPropertyDescriptor(object, property) { |
| let proto = object; |
| let descriptor; |
| const isOwn = Boolean( |
| object && Object.getOwnPropertyDescriptor(object, property), |
| ); |
| |
| while ( |
| proto && |
| !(descriptor = Object.getOwnPropertyDescriptor(proto, property)) |
| ) { |
| proto = Object.getPrototypeOf(proto); |
| } |
| |
| if (descriptor) { |
| descriptor.isOwn = isOwn; |
| } |
| |
| return descriptor; |
| } |
| |
| module.exports = getPropertyDescriptor; |
| |
| },{}],29:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * Verify if an object is a ECMAScript Module |
| * |
| * As the exports from a module is immutable we cannot alter the exports |
| * using spies or stubs. Let the consumer know this to avoid bug reports |
| * on weird error messages. |
| * |
| * @param {object} object The object to examine |
| * @returns {boolean} true when the object is a module |
| */ |
| module.exports = function (object) { |
| return ( |
| object && |
| typeof Symbol !== "undefined" && |
| object[Symbol.toStringTag] === "Module" && |
| Object.isSealed(object) |
| ); |
| }; |
| |
| },{}],30:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * @param {*} object |
| * @param {string} property |
| * @returns {boolean} whether a prop exists in the prototype chain |
| */ |
| function isNonExistentProperty(object, property) { |
| return Boolean( |
| object && typeof property !== "undefined" && !(property in object), |
| ); |
| } |
| |
| module.exports = isNonExistentProperty; |
| |
| },{}],31:[function(require,module,exports){ |
| "use strict"; |
| |
| const getPropertyDescriptor = require("./get-property-descriptor"); |
| |
| function isPropertyConfigurable(obj, propName) { |
| const propertyDescriptor = getPropertyDescriptor(obj, propName); |
| |
| return propertyDescriptor ? propertyDescriptor.configurable : true; |
| } |
| |
| module.exports = isPropertyConfigurable; |
| |
| },{"./get-property-descriptor":28}],32:[function(require,module,exports){ |
| "use strict"; |
| |
| function isRestorable(obj) { |
| return ( |
| typeof obj === "function" && |
| typeof obj.restore === "function" && |
| obj.restore.sinon |
| ); |
| } |
| |
| module.exports = isRestorable; |
| |
| },{}],33:[function(require,module,exports){ |
| "use strict"; |
| |
| const globalObject = require("@sinonjs/commons").global; |
| const getNextTick = require("./get-next-tick"); |
| |
| module.exports = getNextTick(globalObject.process, globalObject.setImmediate); |
| |
| },{"./get-next-tick":27,"@sinonjs/commons":46}],34:[function(require,module,exports){ |
| "use strict"; |
| |
| const sinonTypeSymbolProperty = Symbol("SinonType"); |
| |
| module.exports = { |
| /** |
| * Set the type of a Sinon object to make it possible to identify it later at runtime |
| * |
| * @param {object|Function} object object/function to set the type on |
| * @param {string} type the named type of the object/function |
| */ |
| set(object, type) { |
| Object.defineProperty(object, sinonTypeSymbolProperty, { |
| value: type, |
| configurable: false, |
| enumerable: false, |
| }); |
| }, |
| get(object) { |
| return object && object[sinonTypeSymbolProperty]; |
| }, |
| }; |
| |
| },{}],35:[function(require,module,exports){ |
| "use strict"; |
| |
| const array = [null, "once", "twice", "thrice"]; |
| |
| module.exports = function timesInWords(count) { |
| return array[count] || `${count || 0} times`; |
| }; |
| |
| },{}],36:[function(require,module,exports){ |
| "use strict"; |
| |
| const functionName = require("@sinonjs/commons").functionName; |
| |
| const getPropertyDescriptor = require("./get-property-descriptor"); |
| const walk = require("./walk"); |
| |
| /** |
| * A utility that allows traversing an object, applying mutating functions on the properties |
| * |
| * @param {Function} mutator called on each property |
| * @param {object} object the object we are walking over |
| * @param {Function} filter a predicate (boolean function) that will decide whether or not to apply the mutator to the current property |
| * @returns {void} nothing |
| */ |
| function walkObject(mutator, object, filter) { |
| let called = false; |
| const name = functionName(mutator); |
| |
| if (!object) { |
| throw new Error( |
| `Trying to ${name} object but received ${String(object)}`, |
| ); |
| } |
| |
| walk(object, function (prop, propOwner) { |
| // we don't want to stub things like toString(), valueOf(), etc. so we only stub if the object |
| // is not Object.prototype |
| if ( |
| propOwner !== Object.prototype && |
| prop !== "constructor" && |
| typeof getPropertyDescriptor(propOwner, prop).value === "function" |
| ) { |
| if (filter) { |
| if (filter(object, prop)) { |
| called = true; |
| mutator(object, prop); |
| } |
| } else { |
| called = true; |
| mutator(object, prop); |
| } |
| } |
| }); |
| |
| if (!called) { |
| throw new Error( |
| `Found no methods on object to which we could apply mutations`, |
| ); |
| } |
| |
| return object; |
| } |
| |
| module.exports = walkObject; |
| |
| },{"./get-property-descriptor":28,"./walk":37,"@sinonjs/commons":46}],37:[function(require,module,exports){ |
| "use strict"; |
| |
| const forEach = require("@sinonjs/commons").prototypes.array.forEach; |
| |
| function walkInternal(obj, iterator, context, originalObj, seen) { |
| let prop; |
| const proto = Object.getPrototypeOf(obj); |
| |
| if (typeof Object.getOwnPropertyNames !== "function") { |
| // We explicitly want to enumerate through all of the prototype's properties |
| // in this case, therefore we deliberately leave out an own property check. |
| /* eslint-disable-next-line guard-for-in */ |
| for (prop in obj) { |
| iterator.call(context, obj[prop], prop, obj); |
| } |
| |
| return; |
| } |
| |
| forEach(Object.getOwnPropertyNames(obj), function (k) { |
| if (seen[k] !== true) { |
| seen[k] = true; |
| const target = |
| typeof Object.getOwnPropertyDescriptor(obj, k).get === |
| "function" |
| ? originalObj |
| : obj; |
| iterator.call(context, k, target); |
| } |
| }); |
| |
| if (proto) { |
| walkInternal(proto, iterator, context, originalObj, seen); |
| } |
| } |
| |
| /* Walks the prototype chain of an object and iterates over every own property |
| * name encountered. The iterator is called in the same fashion that Array.prototype.forEach |
| * works, where it is passed the value, key, and own object as the 1st, 2nd, and 3rd positional |
| * argument, respectively. In cases where Object.getOwnPropertyNames is not available, walk will |
| * default to using a simple for..in loop. |
| * |
| * obj - The object to walk the prototype chain for. |
| * iterator - The function to be called on each pass of the walk. |
| * context - (Optional) When given, the iterator will be called with this object as the receiver. |
| */ |
| module.exports = function walk(obj, iterator, context) { |
| return walkInternal(obj, iterator, context, obj, {}); |
| }; |
| |
| },{"@sinonjs/commons":46}],38:[function(require,module,exports){ |
| "use strict"; |
| |
| // eslint-disable-next-line no-empty-function |
| const noop = () => {}; |
| const getPropertyDescriptor = require("./get-property-descriptor"); |
| const extend = require("./extend"); |
| const sinonType = require("./sinon-type"); |
| const hasOwnProperty = |
| require("@sinonjs/commons").prototypes.object.hasOwnProperty; |
| const valueToString = require("@sinonjs/commons").valueToString; |
| const push = require("@sinonjs/commons").prototypes.array.push; |
| |
| function isFunction(obj) { |
| return ( |
| typeof obj === "function" || |
| Boolean(obj && obj.constructor && obj.call && obj.apply) |
| ); |
| } |
| |
| function mirrorProperties(target, source) { |
| for (const prop in source) { |
| if (!hasOwnProperty(target, prop)) { |
| target[prop] = source[prop]; |
| } |
| } |
| } |
| |
| function getAccessor(object, property, method) { |
| const accessors = ["get", "set"]; |
| const descriptor = getPropertyDescriptor(object, property); |
| |
| for (let i = 0; i < accessors.length; i++) { |
| if ( |
| descriptor[accessors[i]] && |
| descriptor[accessors[i]].name === method.name |
| ) { |
| return accessors[i]; |
| } |
| } |
| return null; |
| } |
| |
| // Cheap way to detect if we have ES5 support. |
| const hasES5Support = "keys" in Object; |
| |
| module.exports = function wrapMethod(object, property, method) { |
| if (!object) { |
| throw new TypeError("Should wrap property of object"); |
| } |
| |
| if (typeof method !== "function" && typeof method !== "object") { |
| throw new TypeError( |
| "Method wrapper should be a function or a property descriptor", |
| ); |
| } |
| |
| function checkWrappedMethod(wrappedMethod) { |
| let error; |
| |
| if (!isFunction(wrappedMethod)) { |
| error = new TypeError( |
| `Attempted to wrap ${typeof wrappedMethod} property ${valueToString( |
| property, |
| )} as function`, |
| ); |
| } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) { |
| error = new TypeError( |
| `Attempted to wrap ${valueToString( |
| property, |
| )} which is already wrapped`, |
| ); |
| } else if (wrappedMethod.calledBefore) { |
| const verb = wrappedMethod.returns ? "stubbed" : "spied on"; |
| error = new TypeError( |
| `Attempted to wrap ${valueToString( |
| property, |
| )} which is already ${verb}`, |
| ); |
| } |
| |
| if (error) { |
| if (wrappedMethod && wrappedMethod.stackTraceError) { |
| error.stack += `\n--------------\n${wrappedMethod.stackTraceError.stack}`; |
| } |
| throw error; |
| } |
| } |
| |
| let error, wrappedMethod, i, wrappedMethodDesc, target, accessor; |
| |
| const wrappedMethods = []; |
| |
| function simplePropertyAssignment() { |
| wrappedMethod = object[property]; |
| checkWrappedMethod(wrappedMethod); |
| object[property] = method; |
| method.displayName = property; |
| } |
| |
| // Firefox has a problem when using hasOwn.call on objects from other frames. |
| const owned = object.hasOwnProperty |
| ? object.hasOwnProperty(property) // eslint-disable-line @sinonjs/no-prototype-methods/no-prototype-methods |
| : hasOwnProperty(object, property); |
| |
| if (hasES5Support) { |
| const methodDesc = |
| typeof method === "function" ? { value: method } : method; |
| wrappedMethodDesc = getPropertyDescriptor(object, property); |
| |
| if (!wrappedMethodDesc) { |
| error = new TypeError( |
| `Attempted to wrap ${typeof wrappedMethod} property ${property} as function`, |
| ); |
| } else if ( |
| wrappedMethodDesc.restore && |
| wrappedMethodDesc.restore.sinon |
| ) { |
| error = new TypeError( |
| `Attempted to wrap ${property} which is already wrapped`, |
| ); |
| } |
| if (error) { |
| if (wrappedMethodDesc && wrappedMethodDesc.stackTraceError) { |
| error.stack += `\n--------------\n${wrappedMethodDesc.stackTraceError.stack}`; |
| } |
| throw error; |
| } |
| |
| const types = Object.keys(methodDesc); |
| for (i = 0; i < types.length; i++) { |
| wrappedMethod = wrappedMethodDesc[types[i]]; |
| checkWrappedMethod(wrappedMethod); |
| push(wrappedMethods, wrappedMethod); |
| } |
| |
| mirrorProperties(methodDesc, wrappedMethodDesc); |
| for (i = 0; i < types.length; i++) { |
| mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]); |
| } |
| |
| // you are not allowed to flip the configurable prop on an |
| // existing descriptor to anything but false (#2514) |
| if (!owned) { |
| methodDesc.configurable = true; |
| } |
| |
| Object.defineProperty(object, property, methodDesc); |
| |
| // catch failing assignment |
| // this is the converse of the check in `.restore` below |
| if (typeof method === "function" && object[property] !== method) { |
| // correct any wrongdoings caused by the defineProperty call above, |
| // such as adding new items (if object was a Storage object) |
| delete object[property]; |
| simplePropertyAssignment(); |
| } |
| } else { |
| simplePropertyAssignment(); |
| } |
| |
| extendObjectWithWrappedMethods(); |
| |
| function extendObjectWithWrappedMethods() { |
| for (i = 0; i < wrappedMethods.length; i++) { |
| accessor = getAccessor(object, property, wrappedMethods[i]); |
| target = accessor ? method[accessor] : method; |
| extend.nonEnum(target, { |
| displayName: property, |
| wrappedMethod: wrappedMethods[i], |
| |
| // Set up an Error object for a stack trace which can be used later to find what line of |
| // code the original method was created on. |
| stackTraceError: new Error("Stack Trace for original"), |
| |
| restore: restore, |
| }); |
| |
| target.restore.sinon = true; |
| if (!hasES5Support) { |
| mirrorProperties(target, wrappedMethod); |
| } |
| } |
| } |
| |
| function restore() { |
| accessor = getAccessor(object, property, this.wrappedMethod); |
| let descriptor; |
| // For prototype properties try to reset by delete first. |
| // If this fails (ex: localStorage on mobile safari) then force a reset |
| // via direct assignment. |
| if (accessor) { |
| if (!owned) { |
| try { |
| // In some cases `delete` may throw an error |
| delete object[property][accessor]; |
| } catch (e) {} // eslint-disable-line no-empty |
| // For native code functions `delete` fails without throwing an error |
| // on Chrome < 43, PhantomJS, etc. |
| } else if (hasES5Support) { |
| descriptor = getPropertyDescriptor(object, property); |
| descriptor[accessor] = wrappedMethodDesc[accessor]; |
| Object.defineProperty(object, property, descriptor); |
| } |
| |
| if (hasES5Support) { |
| descriptor = getPropertyDescriptor(object, property); |
| if (descriptor && descriptor.value === target) { |
| object[property][accessor] = this.wrappedMethod; |
| } |
| } else { |
| // Use strict equality comparison to check failures then force a reset |
| // via direct assignment. |
| if (object[property][accessor] === target) { |
| object[property][accessor] = this.wrappedMethod; |
| } |
| } |
| } else { |
| if (!owned) { |
| try { |
| delete object[property]; |
| } catch (e) {} // eslint-disable-line no-empty |
| } else if (hasES5Support) { |
| Object.defineProperty(object, property, wrappedMethodDesc); |
| } |
| |
| if (hasES5Support) { |
| descriptor = getPropertyDescriptor(object, property); |
| if (descriptor && descriptor.value === target) { |
| object[property] = this.wrappedMethod; |
| } |
| } else { |
| if (object[property] === target) { |
| object[property] = this.wrappedMethod; |
| } |
| } |
| } |
| if (sinonType.get(object) === "stub-instance") { |
| // this is simply to avoid errors after restoring if something should |
| // traverse the object in a cleanup phase, ref #2477 |
| object[property] = noop; |
| } |
| } |
| |
| return method; |
| }; |
| |
| },{"./extend":25,"./get-property-descriptor":28,"./sinon-type":34,"@sinonjs/commons":46}],39:[function(require,module,exports){ |
| "use strict"; |
| |
| const extend = require("./core/extend"); |
| const FakeTimers = require("@sinonjs/fake-timers"); |
| const globalObject = require("@sinonjs/commons").global; |
| |
| /** |
| * |
| * @param config |
| * @param globalCtx |
| * |
| * @returns {object} the clock, after installing it on the global context, if given |
| */ |
| function createClock(config, globalCtx) { |
| let FakeTimersCtx = FakeTimers; |
| if (globalCtx !== null && typeof globalCtx === "object") { |
| FakeTimersCtx = FakeTimers.withGlobal(globalCtx); |
| } |
| const clock = FakeTimersCtx.install(config); |
| clock.restore = clock.uninstall; |
| return clock; |
| } |
| |
| /** |
| * |
| * @param obj |
| * @param globalPropName |
| */ |
| function addIfDefined(obj, globalPropName) { |
| const globalProp = globalObject[globalPropName]; |
| if (typeof globalProp !== "undefined") { |
| obj[globalPropName] = globalProp; |
| } |
| } |
| |
| /** |
| * @param {number|Date|object} dateOrConfig The unix epoch value to install with (default 0) |
| * @returns {object} Returns a lolex clock instance |
| */ |
| exports.useFakeTimers = function (dateOrConfig) { |
| const hasArguments = typeof dateOrConfig !== "undefined"; |
| const argumentIsDateLike = |
| (typeof dateOrConfig === "number" || dateOrConfig instanceof Date) && |
| arguments.length === 1; |
| const argumentIsObject = |
| dateOrConfig !== null && |
| typeof dateOrConfig === "object" && |
| arguments.length === 1; |
| |
| if (!hasArguments) { |
| return createClock({ |
| now: 0, |
| }); |
| } |
| |
| if (argumentIsDateLike) { |
| return createClock({ |
| now: dateOrConfig, |
| }); |
| } |
| |
| if (argumentIsObject) { |
| const config = extend.nonEnum({}, dateOrConfig); |
| const globalCtx = config.global; |
| delete config.global; |
| return createClock(config, globalCtx); |
| } |
| |
| throw new TypeError( |
| "useFakeTimers expected epoch or config object. See https://github.com/sinonjs/sinon", |
| ); |
| }; |
| |
| exports.clock = { |
| create: function (now) { |
| return FakeTimers.createClock(now); |
| }, |
| }; |
| |
| const timers = { |
| setTimeout: setTimeout, |
| clearTimeout: clearTimeout, |
| setInterval: setInterval, |
| clearInterval: clearInterval, |
| Date: Date, |
| }; |
| addIfDefined(timers, "setImmediate"); |
| addIfDefined(timers, "clearImmediate"); |
| |
| exports.timers = timers; |
| |
| },{"./core/extend":25,"@sinonjs/commons":46,"@sinonjs/fake-timers":59}],40:[function(require,module,exports){ |
| "use strict"; |
| |
| var every = require("./prototypes/array").every; |
| |
| /** |
| * @private |
| */ |
| function hasCallsLeft(callMap, spy) { |
| if (callMap[spy.id] === undefined) { |
| callMap[spy.id] = 0; |
| } |
| |
| return callMap[spy.id] < spy.callCount; |
| } |
| |
| /** |
| * @private |
| */ |
| function checkAdjacentCalls(callMap, spy, index, spies) { |
| var calledBeforeNext = true; |
| |
| if (index !== spies.length - 1) { |
| calledBeforeNext = spy.calledBefore(spies[index + 1]); |
| } |
| |
| if (hasCallsLeft(callMap, spy) && calledBeforeNext) { |
| callMap[spy.id] += 1; |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /** |
| * A Sinon proxy object (fake, spy, stub) |
| * @typedef {object} SinonProxy |
| * @property {Function} calledBefore - A method that determines if this proxy was called before another one |
| * @property {string} id - Some id |
| * @property {number} callCount - Number of times this proxy has been called |
| */ |
| |
| /** |
| * Returns true when the spies have been called in the order they were supplied in |
| * @param {SinonProxy[] | SinonProxy} spies An array of proxies, or several proxies as arguments |
| * @returns {boolean} true when spies are called in order, false otherwise |
| */ |
| function calledInOrder(spies) { |
| var callMap = {}; |
| // eslint-disable-next-line no-underscore-dangle |
| var _spies = arguments.length > 1 ? arguments : spies; |
| |
| return every(_spies, checkAdjacentCalls.bind(null, callMap)); |
| } |
| |
| module.exports = calledInOrder; |
| |
| },{"./prototypes/array":48}],41:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * Returns a display name for a value from a constructor |
| * @param {object} value A value to examine |
| * @returns {(string|null)} A string or null |
| */ |
| function className(value) { |
| const name = value.constructor && value.constructor.name; |
| return name || null; |
| } |
| |
| module.exports = className; |
| |
| },{}],42:[function(require,module,exports){ |
| /* eslint-disable no-console */ |
| "use strict"; |
| |
| /** |
| * Returns a function that will invoke the supplied function and print a |
| * deprecation warning to the console each time it is called. |
| * @param {Function} func |
| * @param {string} msg |
| * @returns {Function} |
| */ |
| exports.wrap = function (func, msg) { |
| var wrapped = function () { |
| exports.printWarning(msg); |
| return func.apply(this, arguments); |
| }; |
| if (func.prototype) { |
| wrapped.prototype = func.prototype; |
| } |
| return wrapped; |
| }; |
| |
| /** |
| * Returns a string which can be supplied to `wrap()` to notify the user that a |
| * particular part of the sinon API has been deprecated. |
| * @param {string} packageName |
| * @param {string} funcName |
| * @returns {string} |
| */ |
| exports.defaultMsg = function (packageName, funcName) { |
| return `${packageName}.${funcName} is deprecated and will be removed from the public API in a future version of ${packageName}.`; |
| }; |
| |
| /** |
| * Prints a warning on the console, when it exists |
| * @param {string} msg |
| * @returns {undefined} |
| */ |
| exports.printWarning = function (msg) { |
| /* istanbul ignore next */ |
| if (typeof process === "object" && process.emitWarning) { |
| // Emit Warnings in Node |
| process.emitWarning(msg); |
| } else if (console.info) { |
| console.info(msg); |
| } else { |
| console.log(msg); |
| } |
| }; |
| |
| },{}],43:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * Returns true when fn returns true for all members of obj. |
| * This is an every implementation that works for all iterables |
| * @param {object} obj |
| * @param {Function} fn |
| * @returns {boolean} |
| */ |
| module.exports = function every(obj, fn) { |
| var pass = true; |
| |
| try { |
| // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods |
| obj.forEach(function () { |
| if (!fn.apply(this, arguments)) { |
| // Throwing an error is the only way to break `forEach` |
| throw new Error(); |
| } |
| }); |
| } catch (e) { |
| pass = false; |
| } |
| |
| return pass; |
| }; |
| |
| },{}],44:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * Returns a display name for a function |
| * @param {Function} func |
| * @returns {string} |
| */ |
| module.exports = function functionName(func) { |
| if (!func) { |
| return ""; |
| } |
| |
| try { |
| return ( |
| func.displayName || |
| func.name || |
| // Use function decomposition as a last resort to get function |
| // name. Does not rely on function decomposition to work - if it |
| // doesn't debugging will be slightly less informative |
| // (i.e. toString will say 'spy' rather than 'myFunc'). |
| (String(func).match(/function ([^\s(]+)/) || [])[1] |
| ); |
| } catch (e) { |
| // Stringify may fail and we might get an exception, as a last-last |
| // resort fall back to empty string. |
| return ""; |
| } |
| }; |
| |
| },{}],45:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * A reference to the global object |
| * @type {object} globalObject |
| */ |
| var globalObject; |
| |
| /* istanbul ignore else */ |
| if (typeof global !== "undefined") { |
| // Node |
| globalObject = global; |
| } else if (typeof window !== "undefined") { |
| // Browser |
| globalObject = window; |
| } else { |
| // WebWorker |
| globalObject = self; |
| } |
| |
| module.exports = globalObject; |
| |
| },{}],46:[function(require,module,exports){ |
| "use strict"; |
| |
| module.exports = { |
| global: require("./global"), |
| calledInOrder: require("./called-in-order"), |
| className: require("./class-name"), |
| deprecated: require("./deprecated"), |
| every: require("./every"), |
| functionName: require("./function-name"), |
| orderByFirstCall: require("./order-by-first-call"), |
| prototypes: require("./prototypes"), |
| typeOf: require("./type-of"), |
| valueToString: require("./value-to-string"), |
| }; |
| |
| },{"./called-in-order":40,"./class-name":41,"./deprecated":42,"./every":43,"./function-name":44,"./global":45,"./order-by-first-call":47,"./prototypes":51,"./type-of":57,"./value-to-string":58}],47:[function(require,module,exports){ |
| "use strict"; |
| |
| var sort = require("./prototypes/array").sort; |
| var slice = require("./prototypes/array").slice; |
| |
| /** |
| * @private |
| */ |
| function comparator(a, b) { |
| // uuid, won't ever be equal |
| var aCall = a.getCall(0); |
| var bCall = b.getCall(0); |
| var aId = (aCall && aCall.callId) || -1; |
| var bId = (bCall && bCall.callId) || -1; |
| |
| return aId < bId ? -1 : 1; |
| } |
| |
| /** |
| * A Sinon proxy object (fake, spy, stub) |
| * @typedef {object} SinonProxy |
| * @property {Function} getCall - A method that can return the first call |
| */ |
| |
| /** |
| * Sorts an array of SinonProxy instances (fake, spy, stub) by their first call |
| * @param {SinonProxy[] | SinonProxy} spies |
| * @returns {SinonProxy[]} |
| */ |
| function orderByFirstCall(spies) { |
| return sort(slice(spies), comparator); |
| } |
| |
| module.exports = orderByFirstCall; |
| |
| },{"./prototypes/array":48}],48:[function(require,module,exports){ |
| "use strict"; |
| |
| var copyPrototype = require("./copy-prototype-methods"); |
| |
| module.exports = copyPrototype(Array.prototype); |
| |
| },{"./copy-prototype-methods":49}],49:[function(require,module,exports){ |
| "use strict"; |
| |
| var call = Function.call; |
| var throwsOnProto = require("./throws-on-proto"); |
| |
| var disallowedProperties = [ |
| // ignore size because it throws from Map |
| "size", |
| "caller", |
| "callee", |
| "arguments", |
| ]; |
| |
| // This branch is covered when tests are run with `--disable-proto=throw`, |
| // however we can test both branches at the same time, so this is ignored |
| /* istanbul ignore next */ |
| if (throwsOnProto) { |
| disallowedProperties.push("__proto__"); |
| } |
| |
| module.exports = function copyPrototypeMethods(prototype) { |
| // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods |
| return Object.getOwnPropertyNames(prototype).reduce(function ( |
| result, |
| name |
| ) { |
| if (disallowedProperties.includes(name)) { |
| return result; |
| } |
| |
| if (typeof prototype[name] !== "function") { |
| return result; |
| } |
| |
| result[name] = call.bind(prototype[name]); |
| |
| return result; |
| }, |
| Object.create(null)); |
| }; |
| |
| },{"./throws-on-proto":56}],50:[function(require,module,exports){ |
| "use strict"; |
| |
| var copyPrototype = require("./copy-prototype-methods"); |
| |
| module.exports = copyPrototype(Function.prototype); |
| |
| },{"./copy-prototype-methods":49}],51:[function(require,module,exports){ |
| "use strict"; |
| |
| module.exports = { |
| array: require("./array"), |
| function: require("./function"), |
| map: require("./map"), |
| object: require("./object"), |
| set: require("./set"), |
| string: require("./string"), |
| }; |
| |
| },{"./array":48,"./function":50,"./map":52,"./object":53,"./set":54,"./string":55}],52:[function(require,module,exports){ |
| "use strict"; |
| |
| var copyPrototype = require("./copy-prototype-methods"); |
| |
| module.exports = copyPrototype(Map.prototype); |
| |
| },{"./copy-prototype-methods":49}],53:[function(require,module,exports){ |
| "use strict"; |
| |
| var copyPrototype = require("./copy-prototype-methods"); |
| |
| module.exports = copyPrototype(Object.prototype); |
| |
| },{"./copy-prototype-methods":49}],54:[function(require,module,exports){ |
| "use strict"; |
| |
| var copyPrototype = require("./copy-prototype-methods"); |
| |
| module.exports = copyPrototype(Set.prototype); |
| |
| },{"./copy-prototype-methods":49}],55:[function(require,module,exports){ |
| "use strict"; |
| |
| var copyPrototype = require("./copy-prototype-methods"); |
| |
| module.exports = copyPrototype(String.prototype); |
| |
| },{"./copy-prototype-methods":49}],56:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * Is true when the environment causes an error to be thrown for accessing the |
| * __proto__ property. |
| * This is necessary in order to support `node --disable-proto=throw`. |
| * |
| * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto |
| * @type {boolean} |
| */ |
| let throwsOnProto; |
| try { |
| const object = {}; |
| // eslint-disable-next-line no-proto, no-unused-expressions |
| object.__proto__; |
| throwsOnProto = false; |
| } catch (_) { |
| // This branch is covered when tests are run with `--disable-proto=throw`, |
| // however we can test both branches at the same time, so this is ignored |
| /* istanbul ignore next */ |
| throwsOnProto = true; |
| } |
| |
| module.exports = throwsOnProto; |
| |
| },{}],57:[function(require,module,exports){ |
| "use strict"; |
| |
| var type = require("type-detect"); |
| |
| /** |
| * Returns the lower-case result of running type from type-detect on the value |
| * @param {*} value |
| * @returns {string} |
| */ |
| module.exports = function typeOf(value) { |
| return type(value).toLowerCase(); |
| }; |
| |
| },{"type-detect":94}],58:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * Returns a string representation of the value |
| * @param {*} value |
| * @returns {string} |
| */ |
| function valueToString(value) { |
| if (value && value.toString) { |
| // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods |
| return value.toString(); |
| } |
| return String(value); |
| } |
| |
| module.exports = valueToString; |
| |
| },{}],59:[function(require,module,exports){ |
| "use strict"; |
| |
| const globalObject = require("@sinonjs/commons").global; |
| let timersModule, timersPromisesModule; |
| if (typeof require === "function" && typeof module === "object") { |
| try { |
| timersModule = require("timers"); |
| } catch (e) { |
| // ignored |
| } |
| try { |
| timersPromisesModule = require("timers/promises"); |
| } catch (e) { |
| // ignored |
| } |
| } |
| |
| /** |
| * @typedef {object} IdleDeadline |
| * @property {boolean} didTimeout - whether or not the callback was called before reaching the optional timeout |
| * @property {function():number} timeRemaining - a floating-point value providing an estimate of the number of milliseconds remaining in the current idle period |
| */ |
| |
| /** |
| * Queues a function to be called during a browser's idle periods |
| * |
| * @callback RequestIdleCallback |
| * @param {function(IdleDeadline)} callback |
| * @param {{timeout: number}} options - an options object |
| * @returns {number} the id |
| */ |
| |
| /** |
| * @callback NextTick |
| * @param {VoidVarArgsFunc} callback - the callback to run |
| * @param {...*} args - optional arguments to call the callback with |
| * @returns {void} |
| */ |
| |
| /** |
| * @callback SetImmediate |
| * @param {VoidVarArgsFunc} callback - the callback to run |
| * @param {...*} args - optional arguments to call the callback with |
| * @returns {NodeImmediate} |
| */ |
| |
| /** |
| * @callback VoidVarArgsFunc |
| * @param {...*} callback - the callback to run |
| * @returns {void} |
| */ |
| |
| /** |
| * @typedef RequestAnimationFrame |
| * @property {function(number):void} requestAnimationFrame |
| * @returns {number} - the id |
| */ |
| |
| /** |
| * @typedef Performance |
| * @property {function(): number} now |
| */ |
| |
| /* eslint-disable jsdoc/require-property-description */ |
| /** |
| * @typedef {object} Clock |
| * @property {number} now - the current time |
| * @property {Date} Date - the Date constructor |
| * @property {number} loopLimit - the maximum number of timers before assuming an infinite loop |
| * @property {RequestIdleCallback} requestIdleCallback |
| * @property {function(number):void} cancelIdleCallback |
| * @property {setTimeout} setTimeout |
| * @property {clearTimeout} clearTimeout |
| * @property {NextTick} nextTick |
| * @property {queueMicrotask} queueMicrotask |
| * @property {setInterval} setInterval |
| * @property {clearInterval} clearInterval |
| * @property {SetImmediate} setImmediate |
| * @property {function(NodeImmediate):void} clearImmediate |
| * @property {function():number} countTimers |
| * @property {RequestAnimationFrame} requestAnimationFrame |
| * @property {function(number):void} cancelAnimationFrame |
| * @property {function():void} runMicrotasks |
| * @property {function(string | number): number} tick |
| * @property {function(string | number): Promise<number>} tickAsync |
| * @property {function(): number} next |
| * @property {function(): Promise<number>} nextAsync |
| * @property {function(): number} runAll |
| * @property {function(): number} runToFrame |
| * @property {function(): Promise<number>} runAllAsync |
| * @property {function(): number} runToLast |
| * @property {function(): Promise<number>} runToLastAsync |
| * @property {function(): void} reset |
| * @property {function(number | Date): void} setSystemTime |
| * @property {function(number): void} jump |
| * @property {Performance} performance |
| * @property {function(number[]): number[]} hrtime - process.hrtime (legacy) |
| * @property {function(): void} uninstall Uninstall the clock. |
| * @property {Function[]} methods - the methods that are faked |
| * @property {boolean} [shouldClearNativeTimers] inherited from config |
| * @property {{methodName:string, original:any}[] | undefined} timersModuleMethods |
| * @property {{methodName:string, original:any}[] | undefined} timersPromisesModuleMethods |
| * @property {Map<function(): void, AbortSignal>} abortListenerMap |
| */ |
| /* eslint-enable jsdoc/require-property-description */ |
| |
| /** |
| * Configuration object for the `install` method. |
| * |
| * @typedef {object} Config |
| * @property {number|Date} [now] a number (in milliseconds) or a Date object (default epoch) |
| * @property {string[]} [toFake] names of the methods that should be faked. |
| * @property {number} [loopLimit] the maximum number of timers that will be run when calling runAll() |
| * @property {boolean} [shouldAdvanceTime] tells FakeTimers to increment mocked time automatically (default false) |
| * @property {number} [advanceTimeDelta] increment mocked time every <<advanceTimeDelta>> ms (default: 20ms) |
| * @property {boolean} [shouldClearNativeTimers] forwards clear timer calls to native functions if they are not fakes (default: false) |
| * @property {boolean} [ignoreMissingTimers] default is false, meaning asking to fake timers that are not present will throw an error |
| */ |
| |
| /* eslint-disable jsdoc/require-property-description */ |
| /** |
| * The internal structure to describe a scheduled fake timer |
| * |
| * @typedef {object} Timer |
| * @property {Function} func |
| * @property {*[]} args |
| * @property {number} delay |
| * @property {number} callAt |
| * @property {number} createdAt |
| * @property {boolean} immediate |
| * @property {number} id |
| * @property {Error} [error] |
| */ |
| |
| /** |
| * A Node timer |
| * |
| * @typedef {object} NodeImmediate |
| * @property {function(): boolean} hasRef |
| * @property {function(): NodeImmediate} ref |
| * @property {function(): NodeImmediate} unref |
| */ |
| /* eslint-enable jsdoc/require-property-description */ |
| |
| /* eslint-disable complexity */ |
| |
| /** |
| * Mocks available features in the specified global namespace. |
| * |
| * @param {*} _global Namespace to mock (e.g. `window`) |
| * @returns {FakeTimers} |
| */ |
| function withGlobal(_global) { |
| const maxTimeout = Math.pow(2, 31) - 1; //see https://heycam.github.io/webidl/#abstract-opdef-converttoint |
| const idCounterStart = 1e12; // arbitrarily large number to avoid collisions with native timer IDs |
| const NOOP = function () { |
| return undefined; |
| }; |
| const NOOP_ARRAY = function () { |
| return []; |
| }; |
| const isPresent = {}; |
| let timeoutResult, |
| addTimerReturnsObject = false; |
| |
| if (_global.setTimeout) { |
| isPresent.setTimeout = true; |
| timeoutResult = _global.setTimeout(NOOP, 0); |
| addTimerReturnsObject = typeof timeoutResult === "object"; |
| } |
| isPresent.clearTimeout = Boolean(_global.clearTimeout); |
| isPresent.setInterval = Boolean(_global.setInterval); |
| isPresent.clearInterval = Boolean(_global.clearInterval); |
| isPresent.hrtime = |
| _global.process && typeof _global.process.hrtime === "function"; |
| isPresent.hrtimeBigint = |
| isPresent.hrtime && typeof _global.process.hrtime.bigint === "function"; |
| isPresent.nextTick = |
| _global.process && typeof _global.process.nextTick === "function"; |
| const utilPromisify = _global.process && require("util").promisify; |
| isPresent.performance = |
| _global.performance && typeof _global.performance.now === "function"; |
| const hasPerformancePrototype = |
| _global.Performance && |
| (typeof _global.Performance).match(/^(function|object)$/); |
| const hasPerformanceConstructorPrototype = |
| _global.performance && |
| _global.performance.constructor && |
| _global.performance.constructor.prototype; |
| isPresent.queueMicrotask = _global.hasOwnProperty("queueMicrotask"); |
| isPresent.requestAnimationFrame = |
| _global.requestAnimationFrame && |
| typeof _global.requestAnimationFrame === "function"; |
| isPresent.cancelAnimationFrame = |
| _global.cancelAnimationFrame && |
| typeof _global.cancelAnimationFrame === "function"; |
| isPresent.requestIdleCallback = |
| _global.requestIdleCallback && |
| typeof _global.requestIdleCallback === "function"; |
| isPresent.cancelIdleCallbackPresent = |
| _global.cancelIdleCallback && |
| typeof _global.cancelIdleCallback === "function"; |
| isPresent.setImmediate = |
| _global.setImmediate && typeof _global.setImmediate === "function"; |
| isPresent.clearImmediate = |
| _global.clearImmediate && typeof _global.clearImmediate === "function"; |
| isPresent.Intl = _global.Intl && typeof _global.Intl === "object"; |
| |
| if (_global.clearTimeout) { |
| _global.clearTimeout(timeoutResult); |
| } |
| |
| const NativeDate = _global.Date; |
| const NativeIntl = _global.Intl; |
| let uniqueTimerId = idCounterStart; |
| |
| if (NativeDate === undefined) { |
| throw new Error( |
| "The global scope doesn't have a `Date` object" + |
| " (see https://github.com/sinonjs/sinon/issues/1852#issuecomment-419622780)", |
| ); |
| } |
| isPresent.Date = true; |
| |
| /** |
| * The PerformanceEntry object encapsulates a single performance metric |
| * that is part of the browser's performance timeline. |
| * |
| * This is an object returned by the `mark` and `measure` methods on the Performance prototype |
| */ |
| class FakePerformanceEntry { |
| constructor(name, entryType, startTime, duration) { |
| this.name = name; |
| this.entryType = entryType; |
| this.startTime = startTime; |
| this.duration = duration; |
| } |
| |
| toJSON() { |
| return JSON.stringify({ ...this }); |
| } |
| } |
| |
| /** |
| * @param {number} num |
| * @returns {boolean} |
| */ |
| function isNumberFinite(num) { |
| if (Number.isFinite) { |
| return Number.isFinite(num); |
| } |
| |
| return isFinite(num); |
| } |
| |
| let isNearInfiniteLimit = false; |
| |
| /** |
| * @param {Clock} clock |
| * @param {number} i |
| */ |
| function checkIsNearInfiniteLimit(clock, i) { |
| if (clock.loopLimit && i === clock.loopLimit - 1) { |
| isNearInfiniteLimit = true; |
| } |
| } |
| |
| /** |
| * |
| */ |
| function resetIsNearInfiniteLimit() { |
| isNearInfiniteLimit = false; |
| } |
| |
| /** |
| * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into |
| * number of milliseconds. This is used to support human-readable strings passed |
| * to clock.tick() |
| * |
| * @param {string} str |
| * @returns {number} |
| */ |
| function parseTime(str) { |
| if (!str) { |
| return 0; |
| } |
| |
| const strings = str.split(":"); |
| const l = strings.length; |
| let i = l; |
| let ms = 0; |
| let parsed; |
| |
| if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) { |
| throw new Error( |
| "tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits", |
| ); |
| } |
| |
| while (i--) { |
| parsed = parseInt(strings[i], 10); |
| |
| if (parsed >= 60) { |
| throw new Error(`Invalid time ${str}`); |
| } |
| |
| ms += parsed * Math.pow(60, l - i - 1); |
| } |
| |
| return ms * 1000; |
| } |
| |
| /** |
| * Get the decimal part of the millisecond value as nanoseconds |
| * |
| * @param {number} msFloat the number of milliseconds |
| * @returns {number} an integer number of nanoseconds in the range [0,1e6) |
| * |
| * Example: nanoRemainer(123.456789) -> 456789 |
| */ |
| function nanoRemainder(msFloat) { |
| const modulo = 1e6; |
| const remainder = (msFloat * 1e6) % modulo; |
| const positiveRemainder = |
| remainder < 0 ? remainder + modulo : remainder; |
| |
| return Math.floor(positiveRemainder); |
| } |
| |
| /** |
| * Used to grok the `now` parameter to createClock. |
| * |
| * @param {Date|number} epoch the system time |
| * @returns {number} |
| */ |
| function getEpoch(epoch) { |
| if (!epoch) { |
| return 0; |
| } |
| if (typeof epoch.getTime === "function") { |
| return epoch.getTime(); |
| } |
| if (typeof epoch === "number") { |
| return epoch; |
| } |
| throw new TypeError("now should be milliseconds since UNIX epoch"); |
| } |
| |
| /** |
| * @param {number} from |
| * @param {number} to |
| * @param {Timer} timer |
| * @returns {boolean} |
| */ |
| function inRange(from, to, timer) { |
| return timer && timer.callAt >= from && timer.callAt <= to; |
| } |
| |
| /** |
| * @param {Clock} clock |
| * @param {Timer} job |
| */ |
| function getInfiniteLoopError(clock, job) { |
| const infiniteLoopError = new Error( |
| `Aborting after running ${clock.loopLimit} timers, assuming an infinite loop!`, |
| ); |
| |
| if (!job.error) { |
| return infiniteLoopError; |
| } |
| |
| // pattern never matched in Node |
| const computedTargetPattern = /target\.*[<|(|[].*?[>|\]|)]\s*/; |
| let clockMethodPattern = new RegExp( |
| String(Object.keys(clock).join("|")), |
| ); |
| |
| if (addTimerReturnsObject) { |
| // node.js environment |
| clockMethodPattern = new RegExp( |
| `\\s+at (Object\\.)?(?:${Object.keys(clock).join("|")})\\s+`, |
| ); |
| } |
| |
| let matchedLineIndex = -1; |
| job.error.stack.split("\n").some(function (line, i) { |
| // If we've matched a computed target line (e.g. setTimeout) then we |
| // don't need to look any further. Return true to stop iterating. |
| const matchedComputedTarget = line.match(computedTargetPattern); |
| /* istanbul ignore if */ |
| if (matchedComputedTarget) { |
| matchedLineIndex = i; |
| return true; |
| } |
| |
| // If we've matched a clock method line, then there may still be |
| // others further down the trace. Return false to keep iterating. |
| const matchedClockMethod = line.match(clockMethodPattern); |
| if (matchedClockMethod) { |
| matchedLineIndex = i; |
| return false; |
| } |
| |
| // If we haven't matched anything on this line, but we matched |
| // previously and set the matched line index, then we can stop. |
| // If we haven't matched previously, then we should keep iterating. |
| return matchedLineIndex >= 0; |
| }); |
| |
| const stack = `${infiniteLoopError}\n${job.type || "Microtask"} - ${ |
| job.func.name || "anonymous" |
| }\n${job.error.stack |
| .split("\n") |
| .slice(matchedLineIndex + 1) |
| .join("\n")}`; |
| |
| try { |
| Object.defineProperty(infiniteLoopError, "stack", { |
| value: stack, |
| }); |
| } catch (e) { |
| // noop |
| } |
| |
| return infiniteLoopError; |
| } |
| |
| //eslint-disable-next-line jsdoc/require-jsdoc |
| function createDate() { |
| class ClockDate extends NativeDate { |
| /** |
| * @param {number} year |
| * @param {number} month |
| * @param {number} date |
| * @param {number} hour |
| * @param {number} minute |
| * @param {number} second |
| * @param {number} ms |
| * @returns void |
| */ |
| // eslint-disable-next-line no-unused-vars |
| constructor(year, month, date, hour, minute, second, ms) { |
| // Defensive and verbose to avoid potential harm in passing |
| // explicit undefined when user does not pass argument |
| if (arguments.length === 0) { |
| super(ClockDate.clock.now); |
| } else { |
| super(...arguments); |
| } |
| |
| // ensures identity checks using the constructor prop still works |
| // this should have no other functional effect |
| Object.defineProperty(this, "constructor", { |
| value: NativeDate, |
| enumerable: false, |
| }); |
| } |
| |
| static [Symbol.hasInstance](instance) { |
| return instance instanceof NativeDate; |
| } |
| } |
| |
| ClockDate.isFake = true; |
| |
| if (NativeDate.now) { |
| ClockDate.now = function now() { |
| return ClockDate.clock.now; |
| }; |
| } |
| |
| if (NativeDate.toSource) { |
| ClockDate.toSource = function toSource() { |
| return NativeDate.toSource(); |
| }; |
| } |
| |
| ClockDate.toString = function toString() { |
| return NativeDate.toString(); |
| }; |
| |
| // noinspection UnnecessaryLocalVariableJS |
| /** |
| * A normal Class constructor cannot be called without `new`, but Date can, so we need |
| * to wrap it in a Proxy in order to ensure this functionality of Date is kept intact |
| * |
| * @type {ClockDate} |
| */ |
| const ClockDateProxy = new Proxy(ClockDate, { |
| // handler for [[Call]] invocations (i.e. not using `new`) |
| apply() { |
| // the Date constructor called as a function, ref Ecma-262 Edition 5.1, section 15.9.2. |
| // This remains so in the 10th edition of 2019 as well. |
| if (this instanceof ClockDate) { |
| throw new TypeError( |
| "A Proxy should only capture `new` calls with the `construct` handler. This is not supposed to be possible, so check the logic.", |
| ); |
| } |
| |
| return new NativeDate(ClockDate.clock.now).toString(); |
| }, |
| }); |
| |
| return ClockDateProxy; |
| } |
| |
| /** |
| * Mirror Intl by default on our fake implementation |
| * |
| * Most of the properties are the original native ones, |
| * but we need to take control of those that have a |
| * dependency on the current clock. |
| * |
| * @returns {object} the partly fake Intl implementation |
| */ |
| function createIntl() { |
| const ClockIntl = {}; |
| /* |
| * All properties of Intl are non-enumerable, so we need |
| * to do a bit of work to get them out. |
| */ |
| Object.getOwnPropertyNames(NativeIntl).forEach( |
| (property) => (ClockIntl[property] = NativeIntl[property]), |
| ); |
| |
| ClockIntl.DateTimeFormat = function (...args) { |
| const realFormatter = new NativeIntl.DateTimeFormat(...args); |
| const formatter = {}; |
| |
| ["formatRange", "formatRangeToParts", "resolvedOptions"].forEach( |
| (method) => { |
| formatter[method] = |
| realFormatter[method].bind(realFormatter); |
| }, |
| ); |
| |
| ["format", "formatToParts"].forEach((method) => { |
| formatter[method] = function (date) { |
| return realFormatter[method](date || ClockIntl.clock.now); |
| }; |
| }); |
| |
| return formatter; |
| }; |
| |
| ClockIntl.DateTimeFormat.prototype = Object.create( |
| NativeIntl.DateTimeFormat.prototype, |
| ); |
| |
| ClockIntl.DateTimeFormat.supportedLocalesOf = |
| NativeIntl.DateTimeFormat.supportedLocalesOf; |
| |
| return ClockIntl; |
| } |
| |
| //eslint-disable-next-line jsdoc/require-jsdoc |
| function enqueueJob(clock, job) { |
| // enqueues a microtick-deferred task - ecma262/#sec-enqueuejob |
| if (!clock.jobs) { |
| clock.jobs = []; |
| } |
| clock.jobs.push(job); |
| } |
| |
| //eslint-disable-next-line jsdoc/require-jsdoc |
| function runJobs(clock) { |
| // runs all microtick-deferred tasks - ecma262/#sec-runjobs |
| if (!clock.jobs) { |
| return; |
| } |
| for (let i = 0; i < clock.jobs.length; i++) { |
| const job = clock.jobs[i]; |
| job.func.apply(null, job.args); |
| |
| checkIsNearInfiniteLimit(clock, i); |
| if (clock.loopLimit && i > clock.loopLimit) { |
| throw getInfiniteLoopError(clock, job); |
| } |
| } |
| resetIsNearInfiniteLimit(); |
| clock.jobs = []; |
| } |
| |
| /** |
| * @param {Clock} clock |
| * @param {Timer} timer |
| * @returns {number} id of the created timer |
| */ |
| function addTimer(clock, timer) { |
| if (timer.func === undefined) { |
| throw new Error("Callback must be provided to timer calls"); |
| } |
| |
| if (addTimerReturnsObject) { |
| // Node.js environment |
| if (typeof timer.func !== "function") { |
| throw new TypeError( |
| `[ERR_INVALID_CALLBACK]: Callback must be a function. Received ${ |
| timer.func |
| } of type ${typeof timer.func}`, |
| ); |
| } |
| } |
| |
| if (isNearInfiniteLimit) { |
| timer.error = new Error(); |
| } |
| |
| timer.type = timer.immediate ? "Immediate" : "Timeout"; |
| |
| if (timer.hasOwnProperty("delay")) { |
| if (typeof timer.delay !== "number") { |
| timer.delay = parseInt(timer.delay, 10); |
| } |
| |
| if (!isNumberFinite(timer.delay)) { |
| timer.delay = 0; |
| } |
| timer.delay = timer.delay > maxTimeout ? 1 : timer.delay; |
| timer.delay = Math.max(0, timer.delay); |
| } |
| |
| if (timer.hasOwnProperty("interval")) { |
| timer.type = "Interval"; |
| timer.interval = timer.interval > maxTimeout ? 1 : timer.interval; |
| } |
| |
| if (timer.hasOwnProperty("animation")) { |
| timer.type = "AnimationFrame"; |
| timer.animation = true; |
| } |
| |
| if (timer.hasOwnProperty("idleCallback")) { |
| timer.type = "IdleCallback"; |
| timer.idleCallback = true; |
| } |
| |
| if (!clock.timers) { |
| clock.timers = {}; |
| } |
| |
| timer.id = uniqueTimerId++; |
| timer.createdAt = clock.now; |
| timer.callAt = |
| clock.now + (parseInt(timer.delay) || (clock.duringTick ? 1 : 0)); |
| |
| clock.timers[timer.id] = timer; |
| |
| if (addTimerReturnsObject) { |
| const res = { |
| refed: true, |
| ref: function () { |
| this.refed = true; |
| return res; |
| }, |
| unref: function () { |
| this.refed = false; |
| return res; |
| }, |
| hasRef: function () { |
| return this.refed; |
| }, |
| refresh: function () { |
| timer.callAt = |
| clock.now + |
| (parseInt(timer.delay) || (clock.duringTick ? 1 : 0)); |
| |
| // it _might_ have been removed, but if not the assignment is perfectly fine |
| clock.timers[timer.id] = timer; |
| |
| return res; |
| }, |
| [Symbol.toPrimitive]: function () { |
| return timer.id; |
| }, |
| }; |
| return res; |
| } |
| |
| return timer.id; |
| } |
| |
| /* eslint consistent-return: "off" */ |
| /** |
| * Timer comparitor |
| * |
| * @param {Timer} a |
| * @param {Timer} b |
| * @returns {number} |
| */ |
| function compareTimers(a, b) { |
| // Sort first by absolute timing |
| if (a.callAt < b.callAt) { |
| return -1; |
| } |
| if (a.callAt > b.callAt) { |
| return 1; |
| } |
| |
| // Sort next by immediate, immediate timers take precedence |
| if (a.immediate && !b.immediate) { |
| return -1; |
| } |
| if (!a.immediate && b.immediate) { |
| return 1; |
| } |
| |
| // Sort next by creation time, earlier-created timers take precedence |
| if (a.createdAt < b.createdAt) { |
| return -1; |
| } |
| if (a.createdAt > b.createdAt) { |
| return 1; |
| } |
| |
| // Sort next by id, lower-id timers take precedence |
| if (a.id < b.id) { |
| return -1; |
| } |
| if (a.id > b.id) { |
| return 1; |
| } |
| |
| // As timer ids are unique, no fallback `0` is necessary |
| } |
| |
| /** |
| * @param {Clock} clock |
| * @param {number} from |
| * @param {number} to |
| * @returns {Timer} |
| */ |
| function firstTimerInRange(clock, from, to) { |
| const timers = clock.timers; |
| let timer = null; |
| let id, isInRange; |
| |
| for (id in timers) { |
| if (timers.hasOwnProperty(id)) { |
| isInRange = inRange(from, to, timers[id]); |
| |
| if ( |
| isInRange && |
| (!timer || compareTimers(timer, timers[id]) === 1) |
| ) { |
| timer = timers[id]; |
| } |
| } |
| } |
| |
| return timer; |
| } |
| |
| /** |
| * @param {Clock} clock |
| * @returns {Timer} |
| */ |
| function firstTimer(clock) { |
| const timers = clock.timers; |
| let timer = null; |
| let id; |
| |
| for (id in timers) { |
| if (timers.hasOwnProperty(id)) { |
| if (!timer || compareTimers(timer, timers[id]) === 1) { |
| timer = timers[id]; |
| } |
| } |
| } |
| |
| return timer; |
| } |
| |
| /** |
| * @param {Clock} clock |
| * @returns {Timer} |
| */ |
| function lastTimer(clock) { |
| const timers = clock.timers; |
| let timer = null; |
| let id; |
| |
| for (id in timers) { |
| if (timers.hasOwnProperty(id)) { |
| if (!timer || compareTimers(timer, timers[id]) === -1) { |
| timer = timers[id]; |
| } |
| } |
| } |
| |
| return timer; |
| } |
| |
| /** |
| * @param {Clock} clock |
| * @param {Timer} timer |
| */ |
| function callTimer(clock, timer) { |
| if (typeof timer.interval === "number") { |
| clock.timers[timer.id].callAt += timer.interval; |
| } else { |
| delete clock.timers[timer.id]; |
| } |
| |
| if (typeof timer.func === "function") { |
| timer.func.apply(null, timer.args); |
| } else { |
| /* eslint no-eval: "off" */ |
| const eval2 = eval; |
| (function () { |
| eval2(timer.func); |
| })(); |
| } |
| } |
| |
| /** |
| * Gets clear handler name for a given timer type |
| * |
| * @param {string} ttype |
| */ |
| function getClearHandler(ttype) { |
| if (ttype === "IdleCallback" || ttype === "AnimationFrame") { |
| return `cancel${ttype}`; |
| } |
| return `clear${ttype}`; |
| } |
| |
| /** |
| * Gets schedule handler name for a given timer type |
| * |
| * @param {string} ttype |
| */ |
| function getScheduleHandler(ttype) { |
| if (ttype === "IdleCallback" || ttype === "AnimationFrame") { |
| return `request${ttype}`; |
| } |
| return `set${ttype}`; |
| } |
| |
| /** |
| * Creates an anonymous function to warn only once |
| */ |
| function createWarnOnce() { |
| let calls = 0; |
| return function (msg) { |
| // eslint-disable-next-line |
| !calls++ && console.warn(msg); |
| }; |
| } |
| const warnOnce = createWarnOnce(); |
| |
| /** |
| * @param {Clock} clock |
| * @param {number} timerId |
| * @param {string} ttype |
| */ |
| function clearTimer(clock, timerId, ttype) { |
| if (!timerId) { |
| // null appears to be allowed in most browsers, and appears to be |
| // relied upon by some libraries, like Bootstrap carousel |
| return; |
| } |
| |
| if (!clock.timers) { |
| clock.timers = {}; |
| } |
| |
| // in Node, the ID is stored as the primitive value for `Timeout` objects |
| // for `Immediate` objects, no ID exists, so it gets coerced to NaN |
| const id = Number(timerId); |
| |
| if (Number.isNaN(id) || id < idCounterStart) { |
| const handlerName = getClearHandler(ttype); |
| |
| if (clock.shouldClearNativeTimers === true) { |
| const nativeHandler = clock[`_${handlerName}`]; |
| return typeof nativeHandler === "function" |
| ? nativeHandler(timerId) |
| : undefined; |
| } |
| warnOnce( |
| `FakeTimers: ${handlerName} was invoked to clear a native timer instead of one created by this library.` + |
| "\nTo automatically clean-up native timers, use `shouldClearNativeTimers`.", |
| ); |
| } |
| |
| if (clock.timers.hasOwnProperty(id)) { |
| // check that the ID matches a timer of the correct type |
| const timer = clock.timers[id]; |
| if ( |
| timer.type === ttype || |
| (timer.type === "Timeout" && ttype === "Interval") || |
| (timer.type === "Interval" && ttype === "Timeout") |
| ) { |
| delete clock.timers[id]; |
| } else { |
| const clear = getClearHandler(ttype); |
| const schedule = getScheduleHandler(timer.type); |
| throw new Error( |
| `Cannot clear timer: timer created with ${schedule}() but cleared with ${clear}()`, |
| ); |
| } |
| } |
| } |
| |
| /** |
| * @param {Clock} clock |
| * @param {Config} config |
| * @returns {Timer[]} |
| */ |
| function uninstall(clock, config) { |
| let method, i, l; |
| const installedHrTime = "_hrtime"; |
| const installedNextTick = "_nextTick"; |
| |
| for (i = 0, l = clock.methods.length; i < l; i++) { |
| method = clock.methods[i]; |
| if (method === "hrtime" && _global.process) { |
| _global.process.hrtime = clock[installedHrTime]; |
| } else if (method === "nextTick" && _global.process) { |
| _global.process.nextTick = clock[installedNextTick]; |
| } else if (method === "performance") { |
| const originalPerfDescriptor = Object.getOwnPropertyDescriptor( |
| clock, |
| `_${method}`, |
| ); |
| if ( |
| originalPerfDescriptor && |
| originalPerfDescriptor.get && |
| !originalPerfDescriptor.set |
| ) { |
| Object.defineProperty( |
| _global, |
| method, |
| originalPerfDescriptor, |
| ); |
| } else if (originalPerfDescriptor.configurable) { |
| _global[method] = clock[`_${method}`]; |
| } |
| } else { |
| if (_global[method] && _global[method].hadOwnProperty) { |
| _global[method] = clock[`_${method}`]; |
| } else { |
| try { |
| delete _global[method]; |
| } catch (ignore) { |
| /* eslint no-empty: "off" */ |
| } |
| } |
| } |
| if (clock.timersModuleMethods !== undefined) { |
| for (let j = 0; j < clock.timersModuleMethods.length; j++) { |
| const entry = clock.timersModuleMethods[j]; |
| timersModule[entry.methodName] = entry.original; |
| } |
| } |
| if (clock.timersPromisesModuleMethods !== undefined) { |
| for ( |
| let j = 0; |
| j < clock.timersPromisesModuleMethods.length; |
| j++ |
| ) { |
| const entry = clock.timersPromisesModuleMethods[j]; |
| timersPromisesModule[entry.methodName] = entry.original; |
| } |
| } |
| } |
| |
| if (config.shouldAdvanceTime === true) { |
| _global.clearInterval(clock.attachedInterval); |
| } |
| |
| // Prevent multiple executions which will completely remove these props |
| clock.methods = []; |
| |
| for (const [listener, signal] of clock.abortListenerMap.entries()) { |
| signal.removeEventListener("abort", listener); |
| clock.abortListenerMap.delete(listener); |
| } |
| |
| // return pending timers, to enable checking what timers remained on uninstall |
| if (!clock.timers) { |
| return []; |
| } |
| return Object.keys(clock.timers).map(function mapper(key) { |
| return clock.timers[key]; |
| }); |
| } |
| |
| /** |
| * @param {object} target the target containing the method to replace |
| * @param {string} method the keyname of the method on the target |
| * @param {Clock} clock |
| */ |
| function hijackMethod(target, method, clock) { |
| clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call( |
| target, |
| method, |
| ); |
| clock[`_${method}`] = target[method]; |
| |
| if (method === "Date") { |
| target[method] = clock[method]; |
| } else if (method === "Intl") { |
| target[method] = clock[method]; |
| } else if (method === "performance") { |
| const originalPerfDescriptor = Object.getOwnPropertyDescriptor( |
| target, |
| method, |
| ); |
| // JSDOM has a read only performance field so we have to save/copy it differently |
| if ( |
| originalPerfDescriptor && |
| originalPerfDescriptor.get && |
| !originalPerfDescriptor.set |
| ) { |
| Object.defineProperty( |
| clock, |
| `_${method}`, |
| originalPerfDescriptor, |
| ); |
| |
| const perfDescriptor = Object.getOwnPropertyDescriptor( |
| clock, |
| method, |
| ); |
| Object.defineProperty(target, method, perfDescriptor); |
| } else { |
| target[method] = clock[method]; |
| } |
| } else { |
| target[method] = function () { |
| return clock[method].apply(clock, arguments); |
| }; |
| |
| Object.defineProperties( |
| target[method], |
| Object.getOwnPropertyDescriptors(clock[method]), |
| ); |
| } |
| |
| target[method].clock = clock; |
| } |
| |
| /** |
| * @param {Clock} clock |
| * @param {number} advanceTimeDelta |
| */ |
| function doIntervalTick(clock, advanceTimeDelta) { |
| clock.tick(advanceTimeDelta); |
| } |
| |
| /** |
| * @typedef {object} Timers |
| * @property {setTimeout} setTimeout |
| * @property {clearTimeout} clearTimeout |
| * @property {setInterval} setInterval |
| * @property {clearInterval} clearInterval |
| * @property {Date} Date |
| * @property {Intl} Intl |
| * @property {SetImmediate=} setImmediate |
| * @property {function(NodeImmediate): void=} clearImmediate |
| * @property {function(number[]):number[]=} hrtime |
| * @property {NextTick=} nextTick |
| * @property {Performance=} performance |
| * @property {RequestAnimationFrame=} requestAnimationFrame |
| * @property {boolean=} queueMicrotask |
| * @property {function(number): void=} cancelAnimationFrame |
| * @property {RequestIdleCallback=} requestIdleCallback |
| * @property {function(number): void=} cancelIdleCallback |
| */ |
| |
| /** @type {Timers} */ |
| const timers = { |
| setTimeout: _global.setTimeout, |
| clearTimeout: _global.clearTimeout, |
| setInterval: _global.setInterval, |
| clearInterval: _global.clearInterval, |
| Date: _global.Date, |
| }; |
| |
| if (isPresent.setImmediate) { |
| timers.setImmediate = _global.setImmediate; |
| } |
| |
| if (isPresent.clearImmediate) { |
| timers.clearImmediate = _global.clearImmediate; |
| } |
| |
| if (isPresent.hrtime) { |
| timers.hrtime = _global.process.hrtime; |
| } |
| |
| if (isPresent.nextTick) { |
| timers.nextTick = _global.process.nextTick; |
| } |
| |
| if (isPresent.performance) { |
| timers.performance = _global.performance; |
| } |
| |
| if (isPresent.requestAnimationFrame) { |
| timers.requestAnimationFrame = _global.requestAnimationFrame; |
| } |
| |
| if (isPresent.queueMicrotask) { |
| timers.queueMicrotask = _global.queueMicrotask; |
| } |
| |
| if (isPresent.cancelAnimationFrame) { |
| timers.cancelAnimationFrame = _global.cancelAnimationFrame; |
| } |
| |
| if (isPresent.requestIdleCallback) { |
| timers.requestIdleCallback = _global.requestIdleCallback; |
| } |
| |
| if (isPresent.cancelIdleCallback) { |
| timers.cancelIdleCallback = _global.cancelIdleCallback; |
| } |
| |
| if (isPresent.Intl) { |
| timers.Intl = _global.Intl; |
| } |
| |
| const originalSetTimeout = _global.setImmediate || _global.setTimeout; |
| |
| /** |
| * @param {Date|number} [start] the system time - non-integer values are floored |
| * @param {number} [loopLimit] maximum number of timers that will be run when calling runAll() |
| * @returns {Clock} |
| */ |
| function createClock(start, loopLimit) { |
| // eslint-disable-next-line no-param-reassign |
| start = Math.floor(getEpoch(start)); |
| // eslint-disable-next-line no-param-reassign |
| loopLimit = loopLimit || 1000; |
| let nanos = 0; |
| const adjustedSystemTime = [0, 0]; // [millis, nanoremainder] |
| |
| const clock = { |
| now: start, |
| Date: createDate(), |
| loopLimit: loopLimit, |
| }; |
| |
| clock.Date.clock = clock; |
| |
| //eslint-disable-next-line jsdoc/require-jsdoc |
| function getTimeToNextFrame() { |
| return 16 - ((clock.now - start) % 16); |
| } |
| |
| //eslint-disable-next-line jsdoc/require-jsdoc |
| function hrtime(prev) { |
| const millisSinceStart = clock.now - adjustedSystemTime[0] - start; |
| const secsSinceStart = Math.floor(millisSinceStart / 1000); |
| const remainderInNanos = |
| (millisSinceStart - secsSinceStart * 1e3) * 1e6 + |
| nanos - |
| adjustedSystemTime[1]; |
| |
| if (Array.isArray(prev)) { |
| if (prev[1] > 1e9) { |
| throw new TypeError( |
| "Number of nanoseconds can't exceed a billion", |
| ); |
| } |
| |
| const oldSecs = prev[0]; |
| let nanoDiff = remainderInNanos - prev[1]; |
| let secDiff = secsSinceStart - oldSecs; |
| |
| if (nanoDiff < 0) { |
| nanoDiff += 1e9; |
| secDiff -= 1; |
| } |
| |
| return [secDiff, nanoDiff]; |
| } |
| return [secsSinceStart, remainderInNanos]; |
| } |
| |
| /** |
| * A high resolution timestamp in milliseconds. |
| * |
| * @typedef {number} DOMHighResTimeStamp |
| */ |
| |
| /** |
| * performance.now() |
| * |
| * @returns {DOMHighResTimeStamp} |
| */ |
| function fakePerformanceNow() { |
| const hrt = hrtime(); |
| const millis = hrt[0] * 1000 + hrt[1] / 1e6; |
| return millis; |
| } |
| |
| if (isPresent.hrtimeBigint) { |
| hrtime.bigint = function () { |
| const parts = hrtime(); |
| return BigInt(parts[0]) * BigInt(1e9) + BigInt(parts[1]); // eslint-disable-line |
| }; |
| } |
| |
| if (isPresent.Intl) { |
| clock.Intl = createIntl(); |
| clock.Intl.clock = clock; |
| } |
| |
| clock.requestIdleCallback = function requestIdleCallback( |
| func, |
| timeout, |
| ) { |
| let timeToNextIdlePeriod = 0; |
| |
| if (clock.countTimers() > 0) { |
| timeToNextIdlePeriod = 50; // const for now |
| } |
| |
| const result = addTimer(clock, { |
| func: func, |
| args: Array.prototype.slice.call(arguments, 2), |
| delay: |
| typeof timeout === "undefined" |
| ? timeToNextIdlePeriod |
| : Math.min(timeout, timeToNextIdlePeriod), |
| idleCallback: true, |
| }); |
| |
| return Number(result); |
| }; |
| |
| clock.cancelIdleCallback = function cancelIdleCallback(timerId) { |
| return clearTimer(clock, timerId, "IdleCallback"); |
| }; |
| |
| clock.setTimeout = function setTimeout(func, timeout) { |
| return addTimer(clock, { |
| func: func, |
| args: Array.prototype.slice.call(arguments, 2), |
| delay: timeout, |
| }); |
| }; |
| if (typeof _global.Promise !== "undefined" && utilPromisify) { |
| clock.setTimeout[utilPromisify.custom] = |
| function promisifiedSetTimeout(timeout, arg) { |
| return new _global.Promise(function setTimeoutExecutor( |
| resolve, |
| ) { |
| addTimer(clock, { |
| func: resolve, |
| args: [arg], |
| delay: timeout, |
| }); |
| }); |
| }; |
| } |
| |
| clock.clearTimeout = function clearTimeout(timerId) { |
| return clearTimer(clock, timerId, "Timeout"); |
| }; |
| |
| clock.nextTick = function nextTick(func) { |
| return enqueueJob(clock, { |
| func: func, |
| args: Array.prototype.slice.call(arguments, 1), |
| error: isNearInfiniteLimit ? new Error() : null, |
| }); |
| }; |
| |
| clock.queueMicrotask = function queueMicrotask(func) { |
| return clock.nextTick(func); // explicitly drop additional arguments |
| }; |
| |
| clock.setInterval = function setInterval(func, timeout) { |
| // eslint-disable-next-line no-param-reassign |
| timeout = parseInt(timeout, 10); |
| return addTimer(clock, { |
| func: func, |
| args: Array.prototype.slice.call(arguments, 2), |
| delay: timeout, |
| interval: timeout, |
| }); |
| }; |
| |
| clock.clearInterval = function clearInterval(timerId) { |
| return clearTimer(clock, timerId, "Interval"); |
| }; |
| |
| if (isPresent.setImmediate) { |
| clock.setImmediate = function setImmediate(func) { |
| return addTimer(clock, { |
| func: func, |
| args: Array.prototype.slice.call(arguments, 1), |
| immediate: true, |
| }); |
| }; |
| |
| if (typeof _global.Promise !== "undefined" && utilPromisify) { |
| clock.setImmediate[utilPromisify.custom] = |
| function promisifiedSetImmediate(arg) { |
| return new _global.Promise( |
| function setImmediateExecutor(resolve) { |
| addTimer(clock, { |
| func: resolve, |
| args: [arg], |
| immediate: true, |
| }); |
| }, |
| ); |
| }; |
| } |
| |
| clock.clearImmediate = function clearImmediate(timerId) { |
| return clearTimer(clock, timerId, "Immediate"); |
| }; |
| } |
| |
| clock.countTimers = function countTimers() { |
| return ( |
| Object.keys(clock.timers || {}).length + |
| (clock.jobs || []).length |
| ); |
| }; |
| |
| clock.requestAnimationFrame = function requestAnimationFrame(func) { |
| const result = addTimer(clock, { |
| func: func, |
| delay: getTimeToNextFrame(), |
| get args() { |
| return [fakePerformanceNow()]; |
| }, |
| animation: true, |
| }); |
| |
| return Number(result); |
| }; |
| |
| clock.cancelAnimationFrame = function cancelAnimationFrame(timerId) { |
| return clearTimer(clock, timerId, "AnimationFrame"); |
| }; |
| |
| clock.runMicrotasks = function runMicrotasks() { |
| runJobs(clock); |
| }; |
| |
| /** |
| * @param {number|string} tickValue milliseconds or a string parseable by parseTime |
| * @param {boolean} isAsync |
| * @param {Function} resolve |
| * @param {Function} reject |
| * @returns {number|undefined} will return the new `now` value or nothing for async |
| */ |
| function doTick(tickValue, isAsync, resolve, reject) { |
| const msFloat = |
| typeof tickValue === "number" |
| ? tickValue |
| : parseTime(tickValue); |
| const ms = Math.floor(msFloat); |
| const remainder = nanoRemainder(msFloat); |
| let nanosTotal = nanos + remainder; |
| let tickTo = clock.now + ms; |
| |
| if (msFloat < 0) { |
| throw new TypeError("Negative ticks are not supported"); |
| } |
| |
| // adjust for positive overflow |
| if (nanosTotal >= 1e6) { |
| tickTo += 1; |
| nanosTotal -= 1e6; |
| } |
| |
| nanos = nanosTotal; |
| let tickFrom = clock.now; |
| let previous = clock.now; |
| // ESLint fails to detect this correctly |
| /* eslint-disable prefer-const */ |
| let timer, |
| firstException, |
| oldNow, |
| nextPromiseTick, |
| compensationCheck, |
| postTimerCall; |
| /* eslint-enable prefer-const */ |
| |
| clock.duringTick = true; |
| |
| // perform microtasks |
| oldNow = clock.now; |
| runJobs(clock); |
| if (oldNow !== clock.now) { |
| // compensate for any setSystemTime() call during microtask callback |
| tickFrom += clock.now - oldNow; |
| tickTo += clock.now - oldNow; |
| } |
| |
| //eslint-disable-next-line jsdoc/require-jsdoc |
| function doTickInner() { |
| // perform each timer in the requested range |
| timer = firstTimerInRange(clock, tickFrom, tickTo); |
| // eslint-disable-next-line no-unmodified-loop-condition |
| while (timer && tickFrom <= tickTo) { |
| if (clock.timers[timer.id]) { |
| tickFrom = timer.callAt; |
| clock.now = timer.callAt; |
| oldNow = clock.now; |
| try { |
| runJobs(clock); |
| callTimer(clock, timer); |
| } catch (e) { |
| firstException = firstException || e; |
| } |
| |
| if (isAsync) { |
| // finish up after native setImmediate callback to allow |
| // all native es6 promises to process their callbacks after |
| // each timer fires. |
| originalSetTimeout(nextPromiseTick); |
| return; |
| } |
| |
| compensationCheck(); |
| } |
| |
| postTimerCall(); |
| } |
| |
| // perform process.nextTick()s again |
| oldNow = clock.now; |
| runJobs(clock); |
| if (oldNow !== clock.now) { |
| // compensate for any setSystemTime() call during process.nextTick() callback |
| tickFrom += clock.now - oldNow; |
| tickTo += clock.now - oldNow; |
| } |
| clock.duringTick = false; |
| |
| // corner case: during runJobs new timers were scheduled which could be in the range [clock.now, tickTo] |
| timer = firstTimerInRange(clock, tickFrom, tickTo); |
| if (timer) { |
| try { |
| clock.tick(tickTo - clock.now); // do it all again - for the remainder of the requested range |
| } catch (e) { |
| firstException = firstException || e; |
| } |
| } else { |
| // no timers remaining in the requested range: move the clock all the way to the end |
| clock.now = tickTo; |
| |
| // update nanos |
| nanos = nanosTotal; |
| } |
| if (firstException) { |
| throw firstException; |
| } |
| |
| if (isAsync) { |
| resolve(clock.now); |
| } else { |
| return clock.now; |
| } |
| } |
| |
| nextPromiseTick = |
| isAsync && |
| function () { |
| try { |
| compensationCheck(); |
| postTimerCall(); |
| doTickInner(); |
| } catch (e) { |
| reject(e); |
| } |
| }; |
| |
| compensationCheck = function () { |
| // compensate for any setSystemTime() call during timer callback |
| if (oldNow !== clock.now) { |
| tickFrom += clock.now - oldNow; |
| tickTo += clock.now - oldNow; |
| previous += clock.now - oldNow; |
| } |
| }; |
| |
| postTimerCall = function () { |
| timer = firstTimerInRange(clock, previous, tickTo); |
| previous = tickFrom; |
| }; |
| |
| return doTickInner(); |
| } |
| |
| /** |
| * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" |
| * @returns {number} will return the new `now` value |
| */ |
| clock.tick = function tick(tickValue) { |
| return doTick(tickValue, false); |
| }; |
| |
| if (typeof _global.Promise !== "undefined") { |
| /** |
| * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" |
| * @returns {Promise} |
| */ |
| clock.tickAsync = function tickAsync(tickValue) { |
| return new _global.Promise(function (resolve, reject) { |
| originalSetTimeout(function () { |
| try { |
| doTick(tickValue, true, resolve, reject); |
| } catch (e) { |
| reject(e); |
| } |
| }); |
| }); |
| }; |
| } |
| |
| clock.next = function next() { |
| runJobs(clock); |
| const timer = firstTimer(clock); |
| if (!timer) { |
| return clock.now; |
| } |
| |
| clock.duringTick = true; |
| try { |
| clock.now = timer.callAt; |
| callTimer(clock, timer); |
| runJobs(clock); |
| return clock.now; |
| } finally { |
| clock.duringTick = false; |
| } |
| }; |
| |
| if (typeof _global.Promise !== "undefined") { |
| clock.nextAsync = function nextAsync() { |
| return new _global.Promise(function (resolve, reject) { |
| originalSetTimeout(function () { |
| try { |
| const timer = firstTimer(clock); |
| if (!timer) { |
| resolve(clock.now); |
| return; |
| } |
| |
| let err; |
| clock.duringTick = true; |
| clock.now = timer.callAt; |
| try { |
| callTimer(clock, timer); |
| } catch (e) { |
| err = e; |
| } |
| clock.duringTick = false; |
| |
| originalSetTimeout(function () { |
| if (err) { |
| reject(err); |
| } else { |
| resolve(clock.now); |
| } |
| }); |
| } catch (e) { |
| reject(e); |
| } |
| }); |
| }); |
| }; |
| } |
| |
| clock.runAll = function runAll() { |
| let numTimers, i; |
| runJobs(clock); |
| for (i = 0; i < clock.loopLimit; i++) { |
| if (!clock.timers) { |
| resetIsNearInfiniteLimit(); |
| return clock.now; |
| } |
| |
| numTimers = Object.keys(clock.timers).length; |
| if (numTimers === 0) { |
| resetIsNearInfiniteLimit(); |
| return clock.now; |
| } |
| |
| clock.next(); |
| checkIsNearInfiniteLimit(clock, i); |
| } |
| |
| const excessJob = firstTimer(clock); |
| throw getInfiniteLoopError(clock, excessJob); |
| }; |
| |
| clock.runToFrame = function runToFrame() { |
| return clock.tick(getTimeToNextFrame()); |
| }; |
| |
| if (typeof _global.Promise !== "undefined") { |
| clock.runAllAsync = function runAllAsync() { |
| return new _global.Promise(function (resolve, reject) { |
| let i = 0; |
| /** |
| * |
| */ |
| function doRun() { |
| originalSetTimeout(function () { |
| try { |
| runJobs(clock); |
| |
| let numTimers; |
| if (i < clock.loopLimit) { |
| if (!clock.timers) { |
| resetIsNearInfiniteLimit(); |
| resolve(clock.now); |
| return; |
| } |
| |
| numTimers = Object.keys( |
| clock.timers, |
| ).length; |
| if (numTimers === 0) { |
| resetIsNearInfiniteLimit(); |
| resolve(clock.now); |
| return; |
| } |
| |
| clock.next(); |
| |
| i++; |
| |
| doRun(); |
| checkIsNearInfiniteLimit(clock, i); |
| return; |
| } |
| |
| const excessJob = firstTimer(clock); |
| reject(getInfiniteLoopError(clock, excessJob)); |
| } catch (e) { |
| reject(e); |
| } |
| }); |
| } |
| doRun(); |
| }); |
| }; |
| } |
| |
| clock.runToLast = function runToLast() { |
| const timer = lastTimer(clock); |
| if (!timer) { |
| runJobs(clock); |
| return clock.now; |
| } |
| |
| return clock.tick(timer.callAt - clock.now); |
| }; |
| |
| if (typeof _global.Promise !== "undefined") { |
| clock.runToLastAsync = function runToLastAsync() { |
| return new _global.Promise(function (resolve, reject) { |
| originalSetTimeout(function () { |
| try { |
| const timer = lastTimer(clock); |
| if (!timer) { |
| runJobs(clock); |
| resolve(clock.now); |
| } |
| |
| resolve(clock.tickAsync(timer.callAt - clock.now)); |
| } catch (e) { |
| reject(e); |
| } |
| }); |
| }); |
| }; |
| } |
| |
| clock.reset = function reset() { |
| nanos = 0; |
| clock.timers = {}; |
| clock.jobs = []; |
| clock.now = start; |
| }; |
| |
| clock.setSystemTime = function setSystemTime(systemTime) { |
| // determine time difference |
| const newNow = getEpoch(systemTime); |
| const difference = newNow - clock.now; |
| let id, timer; |
| |
| adjustedSystemTime[0] = adjustedSystemTime[0] + difference; |
| adjustedSystemTime[1] = adjustedSystemTime[1] + nanos; |
| // update 'system clock' |
| clock.now = newNow; |
| nanos = 0; |
| |
| // update timers and intervals to keep them stable |
| for (id in clock.timers) { |
| if (clock.timers.hasOwnProperty(id)) { |
| timer = clock.timers[id]; |
| timer.createdAt += difference; |
| timer.callAt += difference; |
| } |
| } |
| }; |
| |
| /** |
| * @param {string|number} tickValue number of milliseconds or a human-readable value like "01:11:15" |
| * @returns {number} will return the new `now` value |
| */ |
| clock.jump = function jump(tickValue) { |
| const msFloat = |
| typeof tickValue === "number" |
| ? tickValue |
| : parseTime(tickValue); |
| const ms = Math.floor(msFloat); |
| |
| for (const timer of Object.values(clock.timers)) { |
| if (clock.now + ms > timer.callAt) { |
| timer.callAt = clock.now + ms; |
| } |
| } |
| clock.tick(ms); |
| }; |
| |
| if (isPresent.performance) { |
| clock.performance = Object.create(null); |
| clock.performance.now = fakePerformanceNow; |
| } |
| |
| if (isPresent.hrtime) { |
| clock.hrtime = hrtime; |
| } |
| |
| return clock; |
| } |
| |
| /* eslint-disable complexity */ |
| |
| /** |
| * @param {Config=} [config] Optional config |
| * @returns {Clock} |
| */ |
| function install(config) { |
| if ( |
| arguments.length > 1 || |
| config instanceof Date || |
| Array.isArray(config) || |
| typeof config === "number" |
| ) { |
| throw new TypeError( |
| `FakeTimers.install called with ${String( |
| config, |
| )} install requires an object parameter`, |
| ); |
| } |
| |
| if (_global.Date.isFake === true) { |
| // Timers are already faked; this is a problem. |
| // Make the user reset timers before continuing. |
| throw new TypeError( |
| "Can't install fake timers twice on the same global object.", |
| ); |
| } |
| |
| // eslint-disable-next-line no-param-reassign |
| config = typeof config !== "undefined" ? config : {}; |
| config.shouldAdvanceTime = config.shouldAdvanceTime || false; |
| config.advanceTimeDelta = config.advanceTimeDelta || 20; |
| config.shouldClearNativeTimers = |
| config.shouldClearNativeTimers || false; |
| |
| if (config.target) { |
| throw new TypeError( |
| "config.target is no longer supported. Use `withGlobal(target)` instead.", |
| ); |
| } |
| |
| /** |
| * @param {string} timer/object the name of the thing that is not present |
| * @param timer |
| */ |
| function handleMissingTimer(timer) { |
| if (config.ignoreMissingTimers) { |
| return; |
| } |
| |
| throw new ReferenceError( |
| `non-existent timers and/or objects cannot be faked: '${timer}'`, |
| ); |
| } |
| |
| let i, l; |
| const clock = createClock(config.now, config.loopLimit); |
| clock.shouldClearNativeTimers = config.shouldClearNativeTimers; |
| |
| clock.uninstall = function () { |
| return uninstall(clock, config); |
| }; |
| |
| clock.abortListenerMap = new Map(); |
| |
| clock.methods = config.toFake || []; |
| |
| if (clock.methods.length === 0) { |
| clock.methods = Object.keys(timers); |
| } |
| |
| if (config.shouldAdvanceTime === true) { |
| const intervalTick = doIntervalTick.bind( |
| null, |
| clock, |
| config.advanceTimeDelta, |
| ); |
| const intervalId = _global.setInterval( |
| intervalTick, |
| config.advanceTimeDelta, |
| ); |
| clock.attachedInterval = intervalId; |
| } |
| |
| if (clock.methods.includes("performance")) { |
| const proto = (() => { |
| if (hasPerformanceConstructorPrototype) { |
| return _global.performance.constructor.prototype; |
| } |
| if (hasPerformancePrototype) { |
| return _global.Performance.prototype; |
| } |
| })(); |
| if (proto) { |
| Object.getOwnPropertyNames(proto).forEach(function (name) { |
| if (name !== "now") { |
| clock.performance[name] = |
| name.indexOf("getEntries") === 0 |
| ? NOOP_ARRAY |
| : NOOP; |
| } |
| }); |
| // ensure `mark` returns a value that is valid |
| clock.performance.mark = (name) => |
| new FakePerformanceEntry(name, "mark", 0, 0); |
| clock.performance.measure = (name) => |
| new FakePerformanceEntry(name, "measure", 0, 100); |
| } else if ((config.toFake || []).includes("performance")) { |
| return handleMissingTimer("performance"); |
| } |
| } |
| if (_global === globalObject && timersModule) { |
| clock.timersModuleMethods = []; |
| } |
| if (_global === globalObject && timersPromisesModule) { |
| clock.timersPromisesModuleMethods = []; |
| } |
| for (i = 0, l = clock.methods.length; i < l; i++) { |
| const nameOfMethodToReplace = clock.methods[i]; |
| |
| if (!isPresent[nameOfMethodToReplace]) { |
| handleMissingTimer(nameOfMethodToReplace); |
| // eslint-disable-next-line |
| continue; |
| } |
| |
| if (nameOfMethodToReplace === "hrtime") { |
| if ( |
| _global.process && |
| typeof _global.process.hrtime === "function" |
| ) { |
| hijackMethod(_global.process, nameOfMethodToReplace, clock); |
| } |
| } else if (nameOfMethodToReplace === "nextTick") { |
| if ( |
| _global.process && |
| typeof _global.process.nextTick === "function" |
| ) { |
| hijackMethod(_global.process, nameOfMethodToReplace, clock); |
| } |
| } else { |
| hijackMethod(_global, nameOfMethodToReplace, clock); |
| } |
| if ( |
| clock.timersModuleMethods !== undefined && |
| timersModule[nameOfMethodToReplace] |
| ) { |
| const original = timersModule[nameOfMethodToReplace]; |
| clock.timersModuleMethods.push({ |
| methodName: nameOfMethodToReplace, |
| original: original, |
| }); |
| timersModule[nameOfMethodToReplace] = |
| _global[nameOfMethodToReplace]; |
| } |
| if (clock.timersPromisesModuleMethods !== undefined) { |
| if (nameOfMethodToReplace === "setTimeout") { |
| clock.timersPromisesModuleMethods.push({ |
| methodName: "setTimeout", |
| original: timersPromisesModule.setTimeout, |
| }); |
| |
| timersPromisesModule.setTimeout = ( |
| delay, |
| value, |
| options = {}, |
| ) => |
| new Promise((resolve, reject) => { |
| const abort = () => { |
| options.signal.removeEventListener( |
| "abort", |
| abort, |
| ); |
| clock.abortListenerMap.delete(abort); |
| |
| // This is safe, there is no code path that leads to this function |
| // being invoked before handle has been assigned. |
| // eslint-disable-next-line no-use-before-define |
| clock.clearTimeout(handle); |
| reject(options.signal.reason); |
| }; |
| |
| const handle = clock.setTimeout(() => { |
| if (options.signal) { |
| options.signal.removeEventListener( |
| "abort", |
| abort, |
| ); |
| clock.abortListenerMap.delete(abort); |
| } |
| |
| resolve(value); |
| }, delay); |
| |
| if (options.signal) { |
| if (options.signal.aborted) { |
| abort(); |
| } else { |
| options.signal.addEventListener( |
| "abort", |
| abort, |
| ); |
| clock.abortListenerMap.set( |
| abort, |
| options.signal, |
| ); |
| } |
| } |
| }); |
| } else if (nameOfMethodToReplace === "setImmediate") { |
| clock.timersPromisesModuleMethods.push({ |
| methodName: "setImmediate", |
| original: timersPromisesModule.setImmediate, |
| }); |
| |
| timersPromisesModule.setImmediate = (value, options = {}) => |
| new Promise((resolve, reject) => { |
| const abort = () => { |
| options.signal.removeEventListener( |
| "abort", |
| abort, |
| ); |
| clock.abortListenerMap.delete(abort); |
| |
| // This is safe, there is no code path that leads to this function |
| // being invoked before handle has been assigned. |
| // eslint-disable-next-line no-use-before-define |
| clock.clearImmediate(handle); |
| reject(options.signal.reason); |
| }; |
| |
| const handle = clock.setImmediate(() => { |
| if (options.signal) { |
| options.signal.removeEventListener( |
| "abort", |
| abort, |
| ); |
| clock.abortListenerMap.delete(abort); |
| } |
| |
| resolve(value); |
| }); |
| |
| if (options.signal) { |
| if (options.signal.aborted) { |
| abort(); |
| } else { |
| options.signal.addEventListener( |
| "abort", |
| abort, |
| ); |
| clock.abortListenerMap.set( |
| abort, |
| options.signal, |
| ); |
| } |
| } |
| }); |
| } else if (nameOfMethodToReplace === "setInterval") { |
| clock.timersPromisesModuleMethods.push({ |
| methodName: "setInterval", |
| original: timersPromisesModule.setInterval, |
| }); |
| |
| timersPromisesModule.setInterval = ( |
| delay, |
| value, |
| options = {}, |
| ) => ({ |
| [Symbol.asyncIterator]: () => { |
| const createResolvable = () => { |
| let resolve, reject; |
| const promise = new Promise((res, rej) => { |
| resolve = res; |
| reject = rej; |
| }); |
| promise.resolve = resolve; |
| promise.reject = reject; |
| return promise; |
| }; |
| |
| let done = false; |
| let hasThrown = false; |
| let returnCall; |
| let nextAvailable = 0; |
| const nextQueue = []; |
| |
| const handle = clock.setInterval(() => { |
| if (nextQueue.length > 0) { |
| nextQueue.shift().resolve(); |
| } else { |
| nextAvailable++; |
| } |
| }, delay); |
| |
| const abort = () => { |
| options.signal.removeEventListener( |
| "abort", |
| abort, |
| ); |
| clock.abortListenerMap.delete(abort); |
| |
| clock.clearInterval(handle); |
| done = true; |
| for (const resolvable of nextQueue) { |
| resolvable.resolve(); |
| } |
| }; |
| |
| if (options.signal) { |
| if (options.signal.aborted) { |
| done = true; |
| } else { |
| options.signal.addEventListener( |
| "abort", |
| abort, |
| ); |
| clock.abortListenerMap.set( |
| abort, |
| options.signal, |
| ); |
| } |
| } |
| |
| return { |
| next: async () => { |
| if (options.signal?.aborted && !hasThrown) { |
| hasThrown = true; |
| throw options.signal.reason; |
| } |
| |
| if (done) { |
| return { done: true, value: undefined }; |
| } |
| |
| if (nextAvailable > 0) { |
| nextAvailable--; |
| return { done: false, value: value }; |
| } |
| |
| const resolvable = createResolvable(); |
| nextQueue.push(resolvable); |
| |
| await resolvable; |
| |
| if (returnCall && nextQueue.length === 0) { |
| returnCall.resolve(); |
| } |
| |
| if (options.signal?.aborted && !hasThrown) { |
| hasThrown = true; |
| throw options.signal.reason; |
| } |
| |
| if (done) { |
| return { done: true, value: undefined }; |
| } |
| |
| return { done: false, value: value }; |
| }, |
| return: async () => { |
| if (done) { |
| return { done: true, value: undefined }; |
| } |
| |
| if (nextQueue.length > 0) { |
| returnCall = createResolvable(); |
| await returnCall; |
| } |
| |
| clock.clearInterval(handle); |
| done = true; |
| |
| if (options.signal) { |
| options.signal.removeEventListener( |
| "abort", |
| abort, |
| ); |
| clock.abortListenerMap.delete(abort); |
| } |
| |
| return { done: true, value: undefined }; |
| }, |
| }; |
| }, |
| }); |
| } |
| } |
| } |
| |
| return clock; |
| } |
| |
| /* eslint-enable complexity */ |
| |
| return { |
| timers: timers, |
| createClock: createClock, |
| install: install, |
| withGlobal: withGlobal, |
| }; |
| } |
| |
| /** |
| * @typedef {object} FakeTimers |
| * @property {Timers} timers |
| * @property {createClock} createClock |
| * @property {Function} install |
| * @property {withGlobal} withGlobal |
| */ |
| |
| /* eslint-enable complexity */ |
| |
| /** @type {FakeTimers} */ |
| const defaultImplementation = withGlobal(globalObject); |
| |
| exports.timers = defaultImplementation.timers; |
| exports.createClock = defaultImplementation.createClock; |
| exports.install = defaultImplementation.install; |
| exports.withGlobal = withGlobal; |
| |
| },{"@sinonjs/commons":46,"timers":undefined,"timers/promises":undefined,"util":90}],60:[function(require,module,exports){ |
| "use strict"; |
| |
| var ARRAY_TYPES = [ |
| Array, |
| Int8Array, |
| Uint8Array, |
| Uint8ClampedArray, |
| Int16Array, |
| Uint16Array, |
| Int32Array, |
| Uint32Array, |
| Float32Array, |
| Float64Array, |
| ]; |
| |
| module.exports = ARRAY_TYPES; |
| |
| },{}],61:[function(require,module,exports){ |
| "use strict"; |
| |
| var arrayProto = require("@sinonjs/commons").prototypes.array; |
| var deepEqual = require("./deep-equal").use(createMatcher); // eslint-disable-line no-use-before-define |
| var every = require("@sinonjs/commons").every; |
| var functionName = require("@sinonjs/commons").functionName; |
| var get = require("lodash.get"); |
| var iterableToString = require("./iterable-to-string"); |
| var objectProto = require("@sinonjs/commons").prototypes.object; |
| var typeOf = require("@sinonjs/commons").typeOf; |
| var valueToString = require("@sinonjs/commons").valueToString; |
| |
| var assertMatcher = require("./create-matcher/assert-matcher"); |
| var assertMethodExists = require("./create-matcher/assert-method-exists"); |
| var assertType = require("./create-matcher/assert-type"); |
| var isIterable = require("./create-matcher/is-iterable"); |
| var isMatcher = require("./create-matcher/is-matcher"); |
| |
| var matcherPrototype = require("./create-matcher/matcher-prototype"); |
| |
| var arrayIndexOf = arrayProto.indexOf; |
| var some = arrayProto.some; |
| |
| var hasOwnProperty = objectProto.hasOwnProperty; |
| var objectToString = objectProto.toString; |
| |
| var TYPE_MAP = require("./create-matcher/type-map")(createMatcher); // eslint-disable-line no-use-before-define |
| |
| /** |
| * Creates a matcher object for the passed expectation |
| * |
| * @alias module:samsam.createMatcher |
| * @param {*} expectation An expecttation |
| * @param {string} message A message for the expectation |
| * @returns {object} A matcher object |
| */ |
| function createMatcher(expectation, message) { |
| var m = Object.create(matcherPrototype); |
| var type = typeOf(expectation); |
| |
| if (message !== undefined && typeof message !== "string") { |
| throw new TypeError("Message should be a string"); |
| } |
| |
| if (arguments.length > 2) { |
| throw new TypeError( |
| `Expected 1 or 2 arguments, received ${arguments.length}`, |
| ); |
| } |
| |
| if (type in TYPE_MAP) { |
| TYPE_MAP[type](m, expectation, message); |
| } else { |
| m.test = function (actual) { |
| return deepEqual(actual, expectation); |
| }; |
| } |
| |
| if (!m.message) { |
| m.message = `match(${valueToString(expectation)})`; |
| } |
| |
| // ensure that nothing mutates the exported message value, ref https://github.com/sinonjs/sinon/issues/2502 |
| Object.defineProperty(m, "message", { |
| configurable: false, |
| writable: false, |
| value: m.message, |
| }); |
| |
| return m; |
| } |
| |
| createMatcher.isMatcher = isMatcher; |
| |
| createMatcher.any = createMatcher(function () { |
| return true; |
| }, "any"); |
| |
| createMatcher.defined = createMatcher(function (actual) { |
| return actual !== null && actual !== undefined; |
| }, "defined"); |
| |
| createMatcher.truthy = createMatcher(function (actual) { |
| return Boolean(actual); |
| }, "truthy"); |
| |
| createMatcher.falsy = createMatcher(function (actual) { |
| return !actual; |
| }, "falsy"); |
| |
| createMatcher.same = function (expectation) { |
| return createMatcher( |
| function (actual) { |
| return expectation === actual; |
| }, |
| `same(${valueToString(expectation)})`, |
| ); |
| }; |
| |
| createMatcher.in = function (arrayOfExpectations) { |
| if (typeOf(arrayOfExpectations) !== "array") { |
| throw new TypeError("array expected"); |
| } |
| |
| return createMatcher( |
| function (actual) { |
| return some(arrayOfExpectations, function (expectation) { |
| return expectation === actual; |
| }); |
| }, |
| `in(${valueToString(arrayOfExpectations)})`, |
| ); |
| }; |
| |
| createMatcher.typeOf = function (type) { |
| assertType(type, "string", "type"); |
| return createMatcher(function (actual) { |
| return typeOf(actual) === type; |
| }, `typeOf("${type}")`); |
| }; |
| |
| createMatcher.instanceOf = function (type) { |
| /* istanbul ignore if */ |
| if ( |
| typeof Symbol === "undefined" || |
| typeof Symbol.hasInstance === "undefined" |
| ) { |
| assertType(type, "function", "type"); |
| } else { |
| assertMethodExists( |
| type, |
| Symbol.hasInstance, |
| "type", |
| "[Symbol.hasInstance]", |
| ); |
| } |
| return createMatcher( |
| function (actual) { |
| return actual instanceof type; |
| }, |
| `instanceOf(${functionName(type) || objectToString(type)})`, |
| ); |
| }; |
| |
| /** |
| * Creates a property matcher |
| * |
| * @private |
| * @param {Function} propertyTest A function to test the property against a value |
| * @param {string} messagePrefix A prefix to use for messages generated by the matcher |
| * @returns {object} A matcher |
| */ |
| function createPropertyMatcher(propertyTest, messagePrefix) { |
| return function (property, value) { |
| assertType(property, "string", "property"); |
| var onlyProperty = arguments.length === 1; |
| var message = `${messagePrefix}("${property}"`; |
| if (!onlyProperty) { |
| message += `, ${valueToString(value)}`; |
| } |
| message += ")"; |
| return createMatcher(function (actual) { |
| if ( |
| actual === undefined || |
| actual === null || |
| !propertyTest(actual, property) |
| ) { |
| return false; |
| } |
| return onlyProperty || deepEqual(actual[property], value); |
| }, message); |
| }; |
| } |
| |
| createMatcher.has = createPropertyMatcher(function (actual, property) { |
| if (typeof actual === "object") { |
| return property in actual; |
| } |
| return actual[property] !== undefined; |
| }, "has"); |
| |
| createMatcher.hasOwn = createPropertyMatcher(function (actual, property) { |
| return hasOwnProperty(actual, property); |
| }, "hasOwn"); |
| |
| createMatcher.hasNested = function (property, value) { |
| assertType(property, "string", "property"); |
| var onlyProperty = arguments.length === 1; |
| var message = `hasNested("${property}"`; |
| if (!onlyProperty) { |
| message += `, ${valueToString(value)}`; |
| } |
| message += ")"; |
| return createMatcher(function (actual) { |
| if ( |
| actual === undefined || |
| actual === null || |
| get(actual, property) === undefined |
| ) { |
| return false; |
| } |
| return onlyProperty || deepEqual(get(actual, property), value); |
| }, message); |
| }; |
| |
| var jsonParseResultTypes = { |
| null: true, |
| boolean: true, |
| number: true, |
| string: true, |
| object: true, |
| array: true, |
| }; |
| createMatcher.json = function (value) { |
| if (!jsonParseResultTypes[typeOf(value)]) { |
| throw new TypeError("Value cannot be the result of JSON.parse"); |
| } |
| var message = `json(${JSON.stringify(value, null, " ")})`; |
| return createMatcher(function (actual) { |
| var parsed; |
| try { |
| parsed = JSON.parse(actual); |
| } catch (e) { |
| return false; |
| } |
| return deepEqual(parsed, value); |
| }, message); |
| }; |
| |
| createMatcher.every = function (predicate) { |
| assertMatcher(predicate); |
| |
| return createMatcher(function (actual) { |
| if (typeOf(actual) === "object") { |
| return every(Object.keys(actual), function (key) { |
| return predicate.test(actual[key]); |
| }); |
| } |
| |
| return ( |
| isIterable(actual) && |
| every(actual, function (element) { |
| return predicate.test(element); |
| }) |
| ); |
| }, `every(${predicate.message})`); |
| }; |
| |
| createMatcher.some = function (predicate) { |
| assertMatcher(predicate); |
| |
| return createMatcher(function (actual) { |
| if (typeOf(actual) === "object") { |
| return !every(Object.keys(actual), function (key) { |
| return !predicate.test(actual[key]); |
| }); |
| } |
| |
| return ( |
| isIterable(actual) && |
| !every(actual, function (element) { |
| return !predicate.test(element); |
| }) |
| ); |
| }, `some(${predicate.message})`); |
| }; |
| |
| createMatcher.array = createMatcher.typeOf("array"); |
| |
| createMatcher.array.deepEquals = function (expectation) { |
| return createMatcher( |
| function (actual) { |
| // Comparing lengths is the fastest way to spot a difference before iterating through every item |
| var sameLength = actual.length === expectation.length; |
| return ( |
| typeOf(actual) === "array" && |
| sameLength && |
| every(actual, function (element, index) { |
| var expected = expectation[index]; |
| return typeOf(expected) === "array" && |
| typeOf(element) === "array" |
| ? createMatcher.array.deepEquals(expected).test(element) |
| : deepEqual(expected, element); |
| }) |
| ); |
| }, |
| `deepEquals([${iterableToString(expectation)}])`, |
| ); |
| }; |
| |
| createMatcher.array.startsWith = function (expectation) { |
| return createMatcher( |
| function (actual) { |
| return ( |
| typeOf(actual) === "array" && |
| every(expectation, function (expectedElement, index) { |
| return actual[index] === expectedElement; |
| }) |
| ); |
| }, |
| `startsWith([${iterableToString(expectation)}])`, |
| ); |
| }; |
| |
| createMatcher.array.endsWith = function (expectation) { |
| return createMatcher( |
| function (actual) { |
| // This indicates the index in which we should start matching |
| var offset = actual.length - expectation.length; |
| |
| return ( |
| typeOf(actual) === "array" && |
| every(expectation, function (expectedElement, index) { |
| return actual[offset + index] === expectedElement; |
| }) |
| ); |
| }, |
| `endsWith([${iterableToString(expectation)}])`, |
| ); |
| }; |
| |
| createMatcher.array.contains = function (expectation) { |
| return createMatcher( |
| function (actual) { |
| return ( |
| typeOf(actual) === "array" && |
| every(expectation, function (expectedElement) { |
| return arrayIndexOf(actual, expectedElement) !== -1; |
| }) |
| ); |
| }, |
| `contains([${iterableToString(expectation)}])`, |
| ); |
| }; |
| |
| createMatcher.map = createMatcher.typeOf("map"); |
| |
| createMatcher.map.deepEquals = function mapDeepEquals(expectation) { |
| return createMatcher( |
| function (actual) { |
| // Comparing lengths is the fastest way to spot a difference before iterating through every item |
| var sameLength = actual.size === expectation.size; |
| return ( |
| typeOf(actual) === "map" && |
| sameLength && |
| every(actual, function (element, key) { |
| return ( |
| expectation.has(key) && expectation.get(key) === element |
| ); |
| }) |
| ); |
| }, |
| `deepEquals(Map[${iterableToString(expectation)}])`, |
| ); |
| }; |
| |
| createMatcher.map.contains = function mapContains(expectation) { |
| return createMatcher( |
| function (actual) { |
| return ( |
| typeOf(actual) === "map" && |
| every(expectation, function (element, key) { |
| return actual.has(key) && actual.get(key) === element; |
| }) |
| ); |
| }, |
| `contains(Map[${iterableToString(expectation)}])`, |
| ); |
| }; |
| |
| createMatcher.set = createMatcher.typeOf("set"); |
| |
| createMatcher.set.deepEquals = function setDeepEquals(expectation) { |
| return createMatcher( |
| function (actual) { |
| // Comparing lengths is the fastest way to spot a difference before iterating through every item |
| var sameLength = actual.size === expectation.size; |
| return ( |
| typeOf(actual) === "set" && |
| sameLength && |
| every(actual, function (element) { |
| return expectation.has(element); |
| }) |
| ); |
| }, |
| `deepEquals(Set[${iterableToString(expectation)}])`, |
| ); |
| }; |
| |
| createMatcher.set.contains = function setContains(expectation) { |
| return createMatcher( |
| function (actual) { |
| return ( |
| typeOf(actual) === "set" && |
| every(expectation, function (element) { |
| return actual.has(element); |
| }) |
| ); |
| }, |
| `contains(Set[${iterableToString(expectation)}])`, |
| ); |
| }; |
| |
| createMatcher.bool = createMatcher.typeOf("boolean"); |
| createMatcher.number = createMatcher.typeOf("number"); |
| createMatcher.string = createMatcher.typeOf("string"); |
| createMatcher.object = createMatcher.typeOf("object"); |
| createMatcher.func = createMatcher.typeOf("function"); |
| createMatcher.regexp = createMatcher.typeOf("regexp"); |
| createMatcher.date = createMatcher.typeOf("date"); |
| createMatcher.symbol = createMatcher.typeOf("symbol"); |
| |
| module.exports = createMatcher; |
| |
| },{"./create-matcher/assert-matcher":62,"./create-matcher/assert-method-exists":63,"./create-matcher/assert-type":64,"./create-matcher/is-iterable":65,"./create-matcher/is-matcher":66,"./create-matcher/matcher-prototype":68,"./create-matcher/type-map":69,"./deep-equal":70,"./iterable-to-string":84,"@sinonjs/commons":46,"lodash.get":92}],62:[function(require,module,exports){ |
| "use strict"; |
| |
| var isMatcher = require("./is-matcher"); |
| |
| /** |
| * Throws a TypeError when `value` is not a matcher |
| * |
| * @private |
| * @param {*} value The value to examine |
| */ |
| function assertMatcher(value) { |
| if (!isMatcher(value)) { |
| throw new TypeError("Matcher expected"); |
| } |
| } |
| |
| module.exports = assertMatcher; |
| |
| },{"./is-matcher":66}],63:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * Throws a TypeError when expected method doesn't exist |
| * |
| * @private |
| * @param {*} value A value to examine |
| * @param {string} method The name of the method to look for |
| * @param {name} name A name to use for the error message |
| * @param {string} methodPath The name of the method to use for error messages |
| * @throws {TypeError} When the method doesn't exist |
| */ |
| function assertMethodExists(value, method, name, methodPath) { |
| if (value[method] === null || value[method] === undefined) { |
| throw new TypeError(`Expected ${name} to have method ${methodPath}`); |
| } |
| } |
| |
| module.exports = assertMethodExists; |
| |
| },{}],64:[function(require,module,exports){ |
| "use strict"; |
| |
| var typeOf = require("@sinonjs/commons").typeOf; |
| |
| /** |
| * Ensures that value is of type |
| * |
| * @private |
| * @param {*} value A value to examine |
| * @param {string} type A basic JavaScript type to compare to, e.g. "object", "string" |
| * @param {string} name A string to use for the error message |
| * @throws {TypeError} If value is not of the expected type |
| * @returns {undefined} |
| */ |
| function assertType(value, type, name) { |
| var actual = typeOf(value); |
| if (actual !== type) { |
| throw new TypeError( |
| `Expected type of ${name} to be ${type}, but was ${actual}`, |
| ); |
| } |
| } |
| |
| module.exports = assertType; |
| |
| },{"@sinonjs/commons":46}],65:[function(require,module,exports){ |
| "use strict"; |
| |
| var typeOf = require("@sinonjs/commons").typeOf; |
| |
| /** |
| * Returns `true` for iterables |
| * |
| * @private |
| * @param {*} value A value to examine |
| * @returns {boolean} Returns `true` when `value` looks like an iterable |
| */ |
| function isIterable(value) { |
| return Boolean(value) && typeOf(value.forEach) === "function"; |
| } |
| |
| module.exports = isIterable; |
| |
| },{"@sinonjs/commons":46}],66:[function(require,module,exports){ |
| "use strict"; |
| |
| var isPrototypeOf = require("@sinonjs/commons").prototypes.object.isPrototypeOf; |
| |
| var matcherPrototype = require("./matcher-prototype"); |
| |
| /** |
| * Returns `true` when `object` is a matcher |
| * |
| * @private |
| * @param {*} object A value to examine |
| * @returns {boolean} Returns `true` when `object` is a matcher |
| */ |
| function isMatcher(object) { |
| return isPrototypeOf(matcherPrototype, object); |
| } |
| |
| module.exports = isMatcher; |
| |
| },{"./matcher-prototype":68,"@sinonjs/commons":46}],67:[function(require,module,exports){ |
| "use strict"; |
| |
| var every = require("@sinonjs/commons").prototypes.array.every; |
| var concat = require("@sinonjs/commons").prototypes.array.concat; |
| var typeOf = require("@sinonjs/commons").typeOf; |
| |
| var deepEqualFactory = require("../deep-equal").use; |
| |
| var identical = require("../identical"); |
| var isMatcher = require("./is-matcher"); |
| |
| var keys = Object.keys; |
| var getOwnPropertySymbols = Object.getOwnPropertySymbols; |
| |
| /** |
| * Matches `actual` with `expectation` |
| * |
| * @private |
| * @param {*} actual A value to examine |
| * @param {object} expectation An object with properties to match on |
| * @param {object} matcher A matcher to use for comparison |
| * @returns {boolean} Returns true when `actual` matches all properties in `expectation` |
| */ |
| function matchObject(actual, expectation, matcher) { |
| var deepEqual = deepEqualFactory(matcher); |
| if (actual === null || actual === undefined) { |
| return false; |
| } |
| |
| var expectedKeys = keys(expectation); |
| /* istanbul ignore else: cannot collect coverage for engine that doesn't support Symbol */ |
| if (typeOf(getOwnPropertySymbols) === "function") { |
| expectedKeys = concat(expectedKeys, getOwnPropertySymbols(expectation)); |
| } |
| |
| return every(expectedKeys, function (key) { |
| var exp = expectation[key]; |
| var act = actual[key]; |
| |
| if (isMatcher(exp)) { |
| if (!exp.test(act)) { |
| return false; |
| } |
| } else if (typeOf(exp) === "object") { |
| if (identical(exp, act)) { |
| return true; |
| } |
| if (!matchObject(act, exp, matcher)) { |
| return false; |
| } |
| } else if (!deepEqual(act, exp)) { |
| return false; |
| } |
| |
| return true; |
| }); |
| } |
| |
| module.exports = matchObject; |
| |
| },{"../deep-equal":70,"../identical":72,"./is-matcher":66,"@sinonjs/commons":46}],68:[function(require,module,exports){ |
| "use strict"; |
| |
| var matcherPrototype = { |
| toString: function () { |
| return this.message; |
| }, |
| }; |
| |
| matcherPrototype.or = function (valueOrMatcher) { |
| var createMatcher = require("../create-matcher"); |
| var isMatcher = createMatcher.isMatcher; |
| |
| if (!arguments.length) { |
| throw new TypeError("Matcher expected"); |
| } |
| |
| var m2 = isMatcher(valueOrMatcher) |
| ? valueOrMatcher |
| : createMatcher(valueOrMatcher); |
| var m1 = this; |
| var or = Object.create(matcherPrototype); |
| or.test = function (actual) { |
| return m1.test(actual) || m2.test(actual); |
| }; |
| or.message = `${m1.message}.or(${m2.message})`; |
| return or; |
| }; |
| |
| matcherPrototype.and = function (valueOrMatcher) { |
| var createMatcher = require("../create-matcher"); |
| var isMatcher = createMatcher.isMatcher; |
| |
| if (!arguments.length) { |
| throw new TypeError("Matcher expected"); |
| } |
| |
| var m2 = isMatcher(valueOrMatcher) |
| ? valueOrMatcher |
| : createMatcher(valueOrMatcher); |
| var m1 = this; |
| var and = Object.create(matcherPrototype); |
| and.test = function (actual) { |
| return m1.test(actual) && m2.test(actual); |
| }; |
| and.message = `${m1.message}.and(${m2.message})`; |
| return and; |
| }; |
| |
| module.exports = matcherPrototype; |
| |
| },{"../create-matcher":61}],69:[function(require,module,exports){ |
| "use strict"; |
| |
| var functionName = require("@sinonjs/commons").functionName; |
| var join = require("@sinonjs/commons").prototypes.array.join; |
| var map = require("@sinonjs/commons").prototypes.array.map; |
| var stringIndexOf = require("@sinonjs/commons").prototypes.string.indexOf; |
| var valueToString = require("@sinonjs/commons").valueToString; |
| |
| var matchObject = require("./match-object"); |
| |
| var createTypeMap = function (match) { |
| return { |
| function: function (m, expectation, message) { |
| m.test = expectation; |
| m.message = message || `match(${functionName(expectation)})`; |
| }, |
| number: function (m, expectation) { |
| m.test = function (actual) { |
| // we need type coercion here |
| return expectation == actual; // eslint-disable-line eqeqeq |
| }; |
| }, |
| object: function (m, expectation) { |
| var array = []; |
| |
| if (typeof expectation.test === "function") { |
| m.test = function (actual) { |
| return expectation.test(actual) === true; |
| }; |
| m.message = `match(${functionName(expectation.test)})`; |
| return m; |
| } |
| |
| array = map(Object.keys(expectation), function (key) { |
| return `${key}: ${valueToString(expectation[key])}`; |
| }); |
| |
| m.test = function (actual) { |
| return matchObject(actual, expectation, match); |
| }; |
| m.message = `match(${join(array, ", ")})`; |
| |
| return m; |
| }, |
| regexp: function (m, expectation) { |
| m.test = function (actual) { |
| return typeof actual === "string" && expectation.test(actual); |
| }; |
| }, |
| string: function (m, expectation) { |
| m.test = function (actual) { |
| return ( |
| typeof actual === "string" && |
| stringIndexOf(actual, expectation) !== -1 |
| ); |
| }; |
| m.message = `match("${expectation}")`; |
| }, |
| }; |
| }; |
| |
| module.exports = createTypeMap; |
| |
| },{"./match-object":67,"@sinonjs/commons":46}],70:[function(require,module,exports){ |
| "use strict"; |
| |
| var valueToString = require("@sinonjs/commons").valueToString; |
| var className = require("@sinonjs/commons").className; |
| var typeOf = require("@sinonjs/commons").typeOf; |
| var arrayProto = require("@sinonjs/commons").prototypes.array; |
| var objectProto = require("@sinonjs/commons").prototypes.object; |
| var mapForEach = require("@sinonjs/commons").prototypes.map.forEach; |
| |
| var getClass = require("./get-class"); |
| var identical = require("./identical"); |
| var isArguments = require("./is-arguments"); |
| var isArrayType = require("./is-array-type"); |
| var isDate = require("./is-date"); |
| var isElement = require("./is-element"); |
| var isIterable = require("./is-iterable"); |
| var isMap = require("./is-map"); |
| var isNaN = require("./is-nan"); |
| var isObject = require("./is-object"); |
| var isSet = require("./is-set"); |
| var isSubset = require("./is-subset"); |
| |
| var concat = arrayProto.concat; |
| var every = arrayProto.every; |
| var push = arrayProto.push; |
| |
| var getTime = Date.prototype.getTime; |
| var hasOwnProperty = objectProto.hasOwnProperty; |
| var indexOf = arrayProto.indexOf; |
| var keys = Object.keys; |
| var getOwnPropertySymbols = Object.getOwnPropertySymbols; |
| |
| /** |
| * Deep equal comparison. Two values are "deep equal" when: |
| * |
| * - They are equal, according to samsam.identical |
| * - They are both date objects representing the same time |
| * - They are both arrays containing elements that are all deepEqual |
| * - They are objects with the same set of properties, and each property |
| * in ``actual`` is deepEqual to the corresponding property in ``expectation`` |
| * |
| * Supports cyclic objects. |
| * |
| * @alias module:samsam.deepEqual |
| * @param {*} actual The object to examine |
| * @param {*} expectation The object actual is expected to be equal to |
| * @param {object} match A value to match on |
| * @returns {boolean} Returns true when actual and expectation are considered equal |
| */ |
| function deepEqualCyclic(actual, expectation, match) { |
| // used for cyclic comparison |
| // contain already visited objects |
| var actualObjects = []; |
| var expectationObjects = []; |
| // contain pathes (position in the object structure) |
| // of the already visited objects |
| // indexes same as in objects arrays |
| var actualPaths = []; |
| var expectationPaths = []; |
| // contains combinations of already compared objects |
| // in the manner: { "$1['ref']$2['ref']": true } |
| var compared = {}; |
| |
| // does the recursion for the deep equal check |
| // eslint-disable-next-line complexity |
| return (function deepEqual( |
| actualObj, |
| expectationObj, |
| actualPath, |
| expectationPath, |
| ) { |
| // If both are matchers they must be the same instance in order to be |
| // considered equal If we didn't do that we would end up running one |
| // matcher against the other |
| if (match && match.isMatcher(expectationObj)) { |
| if (match.isMatcher(actualObj)) { |
| return actualObj === expectationObj; |
| } |
| return expectationObj.test(actualObj); |
| } |
| |
| var actualType = typeof actualObj; |
| var expectationType = typeof expectationObj; |
| |
| if ( |
| actualObj === expectationObj || |
| isNaN(actualObj) || |
| isNaN(expectationObj) || |
| actualObj === null || |
| expectationObj === null || |
| actualObj === undefined || |
| expectationObj === undefined || |
| actualType !== "object" || |
| expectationType !== "object" |
| ) { |
| return identical(actualObj, expectationObj); |
| } |
| |
| // Elements are only equal if identical(expected, actual) |
| if (isElement(actualObj) || isElement(expectationObj)) { |
| return false; |
| } |
| |
| var isActualDate = isDate(actualObj); |
| var isExpectationDate = isDate(expectationObj); |
| if (isActualDate || isExpectationDate) { |
| if ( |
| !isActualDate || |
| !isExpectationDate || |
| getTime.call(actualObj) !== getTime.call(expectationObj) |
| ) { |
| return false; |
| } |
| } |
| |
| if (actualObj instanceof RegExp && expectationObj instanceof RegExp) { |
| if (valueToString(actualObj) !== valueToString(expectationObj)) { |
| return false; |
| } |
| } |
| |
| if (actualObj instanceof Promise && expectationObj instanceof Promise) { |
| return actualObj === expectationObj; |
| } |
| |
| if (actualObj instanceof Error && expectationObj instanceof Error) { |
| return actualObj === expectationObj; |
| } |
| |
| var actualClass = getClass(actualObj); |
| var expectationClass = getClass(expectationObj); |
| var actualKeys = keys(actualObj); |
| var expectationKeys = keys(expectationObj); |
| var actualName = className(actualObj); |
| var expectationName = className(expectationObj); |
| var expectationSymbols = |
| typeOf(getOwnPropertySymbols) === "function" |
| ? getOwnPropertySymbols(expectationObj) |
| : /* istanbul ignore next: cannot collect coverage for engine that doesn't support Symbol */ |
| []; |
| var expectationKeysAndSymbols = concat( |
| expectationKeys, |
| expectationSymbols, |
| ); |
| |
| if (isArguments(actualObj) || isArguments(expectationObj)) { |
| if (actualObj.length !== expectationObj.length) { |
| return false; |
| } |
| } else { |
| if ( |
| actualType !== expectationType || |
| actualClass !== expectationClass || |
| actualKeys.length !== expectationKeys.length || |
| (actualName && |
| expectationName && |
| actualName !== expectationName) |
| ) { |
| return false; |
| } |
| } |
| |
| if (isSet(actualObj) || isSet(expectationObj)) { |
| if ( |
| !isSet(actualObj) || |
| !isSet(expectationObj) || |
| actualObj.size !== expectationObj.size |
| ) { |
| return false; |
| } |
| |
| return isSubset(actualObj, expectationObj, deepEqual); |
| } |
| |
| if (isMap(actualObj) || isMap(expectationObj)) { |
| if ( |
| !isMap(actualObj) || |
| !isMap(expectationObj) || |
| actualObj.size !== expectationObj.size |
| ) { |
| return false; |
| } |
| |
| var mapsDeeplyEqual = true; |
| mapForEach(actualObj, function (value, key) { |
| mapsDeeplyEqual = |
| mapsDeeplyEqual && |
| deepEqualCyclic(value, expectationObj.get(key)); |
| }); |
| |
| return mapsDeeplyEqual; |
| } |
| |
| // jQuery objects have iteration protocols |
| // see: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols |
| // But, they don't work well with the implementation concerning iterables below, |
| // so we will detect them and use jQuery's own equality function |
| /* istanbul ignore next -- this can only be tested in the `test-headless` script */ |
| if ( |
| actualObj.constructor && |
| actualObj.constructor.name === "jQuery" && |
| typeof actualObj.is === "function" |
| ) { |
| return actualObj.is(expectationObj); |
| } |
| |
| var isActualNonArrayIterable = |
| isIterable(actualObj) && |
| !isArrayType(actualObj) && |
| !isArguments(actualObj); |
| var isExpectationNonArrayIterable = |
| isIterable(expectationObj) && |
| !isArrayType(expectationObj) && |
| !isArguments(expectationObj); |
| if (isActualNonArrayIterable || isExpectationNonArrayIterable) { |
| var actualArray = Array.from(actualObj); |
| var expectationArray = Array.from(expectationObj); |
| if (actualArray.length !== expectationArray.length) { |
| return false; |
| } |
| |
| var arrayDeeplyEquals = true; |
| every(actualArray, function (key) { |
| arrayDeeplyEquals = |
| arrayDeeplyEquals && |
| deepEqualCyclic(actualArray[key], expectationArray[key]); |
| }); |
| |
| return arrayDeeplyEquals; |
| } |
| |
| return every(expectationKeysAndSymbols, function (key) { |
| if (!hasOwnProperty(actualObj, key)) { |
| return false; |
| } |
| |
| var actualValue = actualObj[key]; |
| var expectationValue = expectationObj[key]; |
| var actualObject = isObject(actualValue); |
| var expectationObject = isObject(expectationValue); |
| // determines, if the objects were already visited |
| // (it's faster to check for isObject first, than to |
| // get -1 from getIndex for non objects) |
| var actualIndex = actualObject |
| ? indexOf(actualObjects, actualValue) |
| : -1; |
| var expectationIndex = expectationObject |
| ? indexOf(expectationObjects, expectationValue) |
| : -1; |
| // determines the new paths of the objects |
| // - for non cyclic objects the current path will be extended |
| // by current property name |
| // - for cyclic objects the stored path is taken |
| var newActualPath = |
| actualIndex !== -1 |
| ? actualPaths[actualIndex] |
| : `${actualPath}[${JSON.stringify(key)}]`; |
| var newExpectationPath = |
| expectationIndex !== -1 |
| ? expectationPaths[expectationIndex] |
| : `${expectationPath}[${JSON.stringify(key)}]`; |
| var combinedPath = newActualPath + newExpectationPath; |
| |
| // stop recursion if current objects are already compared |
| if (compared[combinedPath]) { |
| return true; |
| } |
| |
| // remember the current objects and their paths |
| if (actualIndex === -1 && actualObject) { |
| push(actualObjects, actualValue); |
| push(actualPaths, newActualPath); |
| } |
| if (expectationIndex === -1 && expectationObject) { |
| push(expectationObjects, expectationValue); |
| push(expectationPaths, newExpectationPath); |
| } |
| |
| // remember that the current objects are already compared |
| if (actualObject && expectationObject) { |
| compared[combinedPath] = true; |
| } |
| |
| // End of cyclic logic |
| |
| // neither actualValue nor expectationValue is a cycle |
| // continue with next level |
| return deepEqual( |
| actualValue, |
| expectationValue, |
| newActualPath, |
| newExpectationPath, |
| ); |
| }); |
| })(actual, expectation, "$1", "$2"); |
| } |
| |
| deepEqualCyclic.use = function (match) { |
| return function deepEqual(a, b) { |
| return deepEqualCyclic(a, b, match); |
| }; |
| }; |
| |
| module.exports = deepEqualCyclic; |
| |
| },{"./get-class":71,"./identical":72,"./is-arguments":73,"./is-array-type":74,"./is-date":75,"./is-element":76,"./is-iterable":77,"./is-map":78,"./is-nan":79,"./is-object":81,"./is-set":82,"./is-subset":83,"@sinonjs/commons":46}],71:[function(require,module,exports){ |
| "use strict"; |
| |
| var toString = require("@sinonjs/commons").prototypes.object.toString; |
| |
| /** |
| * Returns the internal `Class` by calling `Object.prototype.toString` |
| * with the provided value as `this`. Return value is a `String`, naming the |
| * internal class, e.g. "Array" |
| * |
| * @private |
| * @param {*} value - Any value |
| * @returns {string} - A string representation of the `Class` of `value` |
| */ |
| function getClass(value) { |
| return toString(value).split(/[ \]]/)[1]; |
| } |
| |
| module.exports = getClass; |
| |
| },{"@sinonjs/commons":46}],72:[function(require,module,exports){ |
| "use strict"; |
| |
| var isNaN = require("./is-nan"); |
| var isNegZero = require("./is-neg-zero"); |
| |
| /** |
| * Strict equality check according to EcmaScript Harmony's `egal`. |
| * |
| * **From the Harmony wiki:** |
| * > An `egal` function simply makes available the internal `SameValue` function |
| * > from section 9.12 of the ES5 spec. If two values are egal, then they are not |
| * > observably distinguishable. |
| * |
| * `identical` returns `true` when `===` is `true`, except for `-0` and |
| * `+0`, where it returns `false`. Additionally, it returns `true` when |
| * `NaN` is compared to itself. |
| * |
| * @alias module:samsam.identical |
| * @param {*} obj1 The first value to compare |
| * @param {*} obj2 The second value to compare |
| * @returns {boolean} Returns `true` when the objects are *egal*, `false` otherwise |
| */ |
| function identical(obj1, obj2) { |
| if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) { |
| return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2); |
| } |
| |
| return false; |
| } |
| |
| module.exports = identical; |
| |
| },{"./is-nan":79,"./is-neg-zero":80}],73:[function(require,module,exports){ |
| "use strict"; |
| |
| var getClass = require("./get-class"); |
| |
| /** |
| * Returns `true` when `object` is an `arguments` object, `false` otherwise |
| * |
| * @alias module:samsam.isArguments |
| * @param {*} object - The object to examine |
| * @returns {boolean} `true` when `object` is an `arguments` object |
| */ |
| function isArguments(object) { |
| return getClass(object) === "Arguments"; |
| } |
| |
| module.exports = isArguments; |
| |
| },{"./get-class":71}],74:[function(require,module,exports){ |
| "use strict"; |
| |
| var functionName = require("@sinonjs/commons").functionName; |
| var indexOf = require("@sinonjs/commons").prototypes.array.indexOf; |
| var map = require("@sinonjs/commons").prototypes.array.map; |
| var ARRAY_TYPES = require("./array-types"); |
| var type = require("type-detect"); |
| |
| /** |
| * Returns `true` when `object` is an array type, `false` otherwise |
| * |
| * @param {*} object - The object to examine |
| * @returns {boolean} `true` when `object` is an array type |
| * @private |
| */ |
| function isArrayType(object) { |
| return indexOf(map(ARRAY_TYPES, functionName), type(object)) !== -1; |
| } |
| |
| module.exports = isArrayType; |
| |
| },{"./array-types":60,"@sinonjs/commons":46,"type-detect":87}],75:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * Returns `true` when `value` is an instance of Date |
| * |
| * @private |
| * @param {Date} value The value to examine |
| * @returns {boolean} `true` when `value` is an instance of Date |
| */ |
| function isDate(value) { |
| return value instanceof Date; |
| } |
| |
| module.exports = isDate; |
| |
| },{}],76:[function(require,module,exports){ |
| "use strict"; |
| |
| var div = typeof document !== "undefined" && document.createElement("div"); |
| |
| /** |
| * Returns `true` when `object` is a DOM element node. |
| * |
| * Unlike Underscore.js/lodash, this function will return `false` if `object` |
| * is an *element-like* object, i.e. a regular object with a `nodeType` |
| * property that holds the value `1`. |
| * |
| * @alias module:samsam.isElement |
| * @param {object} object The object to examine |
| * @returns {boolean} Returns `true` for DOM element nodes |
| */ |
| function isElement(object) { |
| if (!object || object.nodeType !== 1 || !div) { |
| return false; |
| } |
| try { |
| object.appendChild(div); |
| object.removeChild(div); |
| } catch (e) { |
| return false; |
| } |
| return true; |
| } |
| |
| module.exports = isElement; |
| |
| },{}],77:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * Returns `true` when the argument is an iterable, `false` otherwise |
| * |
| * @alias module:samsam.isIterable |
| * @param {*} val - A value to examine |
| * @returns {boolean} Returns `true` when the argument is an iterable, `false` otherwise |
| */ |
| function isIterable(val) { |
| // checks for null and undefined |
| if (typeof val !== "object") { |
| return false; |
| } |
| return typeof val[Symbol.iterator] === "function"; |
| } |
| |
| module.exports = isIterable; |
| |
| },{}],78:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * Returns `true` when `value` is a Map |
| * |
| * @param {*} value A value to examine |
| * @returns {boolean} `true` when `value` is an instance of `Map`, `false` otherwise |
| * @private |
| */ |
| function isMap(value) { |
| return typeof Map !== "undefined" && value instanceof Map; |
| } |
| |
| module.exports = isMap; |
| |
| },{}],79:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * Compares a `value` to `NaN` |
| * |
| * @private |
| * @param {*} value A value to examine |
| * @returns {boolean} Returns `true` when `value` is `NaN` |
| */ |
| function isNaN(value) { |
| // Unlike global `isNaN`, this function avoids type coercion |
| // `typeof` check avoids IE host object issues, hat tip to |
| // lodash |
| |
| // eslint-disable-next-line no-self-compare |
| return typeof value === "number" && value !== value; |
| } |
| |
| module.exports = isNaN; |
| |
| },{}],80:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * Returns `true` when `value` is `-0` |
| * |
| * @alias module:samsam.isNegZero |
| * @param {*} value A value to examine |
| * @returns {boolean} Returns `true` when `value` is `-0` |
| */ |
| function isNegZero(value) { |
| return value === 0 && 1 / value === -Infinity; |
| } |
| |
| module.exports = isNegZero; |
| |
| },{}],81:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * Returns `true` when the value is a regular Object and not a specialized Object |
| * |
| * This helps speed up deepEqual cyclic checks |
| * |
| * The premise is that only Objects are stored in the visited array. |
| * So if this function returns false, we don't have to do the |
| * expensive operation of searching for the value in the the array of already |
| * visited objects |
| * |
| * @private |
| * @param {object} value The object to examine |
| * @returns {boolean} `true` when the object is a non-specialised object |
| */ |
| function isObject(value) { |
| return ( |
| typeof value === "object" && |
| value !== null && |
| // none of these are collection objects, so we can return false |
| !(value instanceof Boolean) && |
| !(value instanceof Date) && |
| !(value instanceof Error) && |
| !(value instanceof Number) && |
| !(value instanceof RegExp) && |
| !(value instanceof String) |
| ); |
| } |
| |
| module.exports = isObject; |
| |
| },{}],82:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * Returns `true` when the argument is an instance of Set, `false` otherwise |
| * |
| * @alias module:samsam.isSet |
| * @param {*} val - A value to examine |
| * @returns {boolean} Returns `true` when the argument is an instance of Set, `false` otherwise |
| */ |
| function isSet(val) { |
| return (typeof Set !== "undefined" && val instanceof Set) || false; |
| } |
| |
| module.exports = isSet; |
| |
| },{}],83:[function(require,module,exports){ |
| "use strict"; |
| |
| var forEach = require("@sinonjs/commons").prototypes.set.forEach; |
| |
| /** |
| * Returns `true` when `s1` is a subset of `s2`, `false` otherwise |
| * |
| * @private |
| * @param {Array|Set} s1 The target value |
| * @param {Array|Set} s2 The containing value |
| * @param {Function} compare A comparison function, should return `true` when |
| * values are considered equal |
| * @returns {boolean} Returns `true` when `s1` is a subset of `s2`, `false`` otherwise |
| */ |
| function isSubset(s1, s2, compare) { |
| var allContained = true; |
| forEach(s1, function (v1) { |
| var includes = false; |
| forEach(s2, function (v2) { |
| if (compare(v2, v1)) { |
| includes = true; |
| } |
| }); |
| allContained = allContained && includes; |
| }); |
| |
| return allContained; |
| } |
| |
| module.exports = isSubset; |
| |
| },{"@sinonjs/commons":46}],84:[function(require,module,exports){ |
| "use strict"; |
| |
| var slice = require("@sinonjs/commons").prototypes.string.slice; |
| var typeOf = require("@sinonjs/commons").typeOf; |
| var valueToString = require("@sinonjs/commons").valueToString; |
| |
| /** |
| * Creates a string represenation of an iterable object |
| * |
| * @private |
| * @param {object} obj The iterable object to stringify |
| * @returns {string} A string representation |
| */ |
| function iterableToString(obj) { |
| if (typeOf(obj) === "map") { |
| return mapToString(obj); |
| } |
| |
| return genericIterableToString(obj); |
| } |
| |
| /** |
| * Creates a string representation of a Map |
| * |
| * @private |
| * @param {Map} map The map to stringify |
| * @returns {string} A string representation |
| */ |
| function mapToString(map) { |
| var representation = ""; |
| |
| // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods |
| map.forEach(function (value, key) { |
| representation += `[${stringify(key)},${stringify(value)}],`; |
| }); |
| |
| representation = slice(representation, 0, -1); |
| return representation; |
| } |
| |
| /** |
| * Create a string represenation for an iterable |
| * |
| * @private |
| * @param {object} iterable The iterable to stringify |
| * @returns {string} A string representation |
| */ |
| function genericIterableToString(iterable) { |
| var representation = ""; |
| |
| // eslint-disable-next-line @sinonjs/no-prototype-methods/no-prototype-methods |
| iterable.forEach(function (value) { |
| representation += `${stringify(value)},`; |
| }); |
| |
| representation = slice(representation, 0, -1); |
| return representation; |
| } |
| |
| /** |
| * Creates a string representation of the passed `item` |
| * |
| * @private |
| * @param {object} item The item to stringify |
| * @returns {string} A string representation of `item` |
| */ |
| function stringify(item) { |
| return typeof item === "string" ? `'${item}'` : valueToString(item); |
| } |
| |
| module.exports = iterableToString; |
| |
| },{"@sinonjs/commons":46}],85:[function(require,module,exports){ |
| "use strict"; |
| |
| var valueToString = require("@sinonjs/commons").valueToString; |
| var indexOf = require("@sinonjs/commons").prototypes.string.indexOf; |
| var forEach = require("@sinonjs/commons").prototypes.array.forEach; |
| var type = require("type-detect"); |
| |
| var engineCanCompareMaps = typeof Array.from === "function"; |
| var deepEqual = require("./deep-equal").use(match); // eslint-disable-line no-use-before-define |
| var isArrayType = require("./is-array-type"); |
| var isSubset = require("./is-subset"); |
| var createMatcher = require("./create-matcher"); |
| |
| /** |
| * Returns true when `array` contains all of `subset` as defined by the `compare` |
| * argument |
| * |
| * @param {Array} array An array to search for a subset |
| * @param {Array} subset The subset to find in the array |
| * @param {Function} compare A comparison function |
| * @returns {boolean} [description] |
| * @private |
| */ |
| function arrayContains(array, subset, compare) { |
| if (subset.length === 0) { |
| return true; |
| } |
| var i, l, j, k; |
| for (i = 0, l = array.length; i < l; ++i) { |
| if (compare(array[i], subset[0])) { |
| for (j = 0, k = subset.length; j < k; ++j) { |
| if (i + j >= l) { |
| return false; |
| } |
| if (!compare(array[i + j], subset[j])) { |
| return false; |
| } |
| } |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /* eslint-disable complexity */ |
| /** |
| * Matches an object with a matcher (or value) |
| * |
| * @alias module:samsam.match |
| * @param {object} object The object candidate to match |
| * @param {object} matcherOrValue A matcher or value to match against |
| * @returns {boolean} true when `object` matches `matcherOrValue` |
| */ |
| function match(object, matcherOrValue) { |
| if (matcherOrValue && typeof matcherOrValue.test === "function") { |
| return matcherOrValue.test(object); |
| } |
| |
| switch (type(matcherOrValue)) { |
| case "bigint": |
| case "boolean": |
| case "number": |
| case "symbol": |
| return matcherOrValue === object; |
| case "function": |
| return matcherOrValue(object) === true; |
| case "string": |
| var notNull = typeof object === "string" || Boolean(object); |
| return ( |
| notNull && |
| indexOf( |
| valueToString(object).toLowerCase(), |
| matcherOrValue.toLowerCase(), |
| ) >= 0 |
| ); |
| case "null": |
| return object === null; |
| case "undefined": |
| return typeof object === "undefined"; |
| case "Date": |
| /* istanbul ignore else */ |
| if (type(object) === "Date") { |
| return object.getTime() === matcherOrValue.getTime(); |
| } |
| /* istanbul ignore next: this is basically the rest of the function, which is covered */ |
| break; |
| case "Array": |
| case "Int8Array": |
| case "Uint8Array": |
| case "Uint8ClampedArray": |
| case "Int16Array": |
| case "Uint16Array": |
| case "Int32Array": |
| case "Uint32Array": |
| case "Float32Array": |
| case "Float64Array": |
| return ( |
| isArrayType(matcherOrValue) && |
| arrayContains(object, matcherOrValue, match) |
| ); |
| case "Map": |
| /* istanbul ignore next: this is covered by a test, that is only run in IE, but we collect coverage information in node*/ |
| if (!engineCanCompareMaps) { |
| throw new Error( |
| "The JavaScript engine does not support Array.from and cannot reliably do value comparison of Map instances", |
| ); |
| } |
| |
| return ( |
| type(object) === "Map" && |
| arrayContains( |
| Array.from(object), |
| Array.from(matcherOrValue), |
| match, |
| ) |
| ); |
| default: |
| break; |
| } |
| |
| switch (type(object)) { |
| case "null": |
| return false; |
| case "Set": |
| return isSubset(matcherOrValue, object, match); |
| default: |
| break; |
| } |
| |
| /* istanbul ignore else */ |
| if (matcherOrValue && typeof matcherOrValue === "object") { |
| if (matcherOrValue === object) { |
| return true; |
| } |
| if (typeof object !== "object") { |
| return false; |
| } |
| var prop; |
| // eslint-disable-next-line guard-for-in |
| for (prop in matcherOrValue) { |
| var value = object[prop]; |
| if ( |
| typeof value === "undefined" && |
| typeof object.getAttribute === "function" |
| ) { |
| value = object.getAttribute(prop); |
| } |
| if ( |
| matcherOrValue[prop] === null || |
| typeof matcherOrValue[prop] === "undefined" |
| ) { |
| if (value !== matcherOrValue[prop]) { |
| return false; |
| } |
| } else if ( |
| typeof value === "undefined" || |
| !deepEqual(value, matcherOrValue[prop]) |
| ) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /* istanbul ignore next */ |
| throw new Error("Matcher was an unknown or unsupported type"); |
| } |
| /* eslint-enable complexity */ |
| |
| forEach(Object.keys(createMatcher), function (key) { |
| match[key] = createMatcher[key]; |
| }); |
| |
| module.exports = match; |
| |
| },{"./create-matcher":61,"./deep-equal":70,"./is-array-type":74,"./is-subset":83,"@sinonjs/commons":46,"type-detect":87}],86:[function(require,module,exports){ |
| "use strict"; |
| |
| /** |
| * @module samsam |
| */ |
| var identical = require("./identical"); |
| var isArguments = require("./is-arguments"); |
| var isElement = require("./is-element"); |
| var isNegZero = require("./is-neg-zero"); |
| var isSet = require("./is-set"); |
| var isMap = require("./is-map"); |
| var match = require("./match"); |
| var deepEqualCyclic = require("./deep-equal").use(match); |
| var createMatcher = require("./create-matcher"); |
| |
| module.exports = { |
| createMatcher: createMatcher, |
| deepEqual: deepEqualCyclic, |
| identical: identical, |
| isArguments: isArguments, |
| isElement: isElement, |
| isMap: isMap, |
| isNegZero: isNegZero, |
| isSet: isSet, |
| match: match, |
| }; |
| |
| },{"./create-matcher":61,"./deep-equal":70,"./identical":72,"./is-arguments":73,"./is-element":76,"./is-map":78,"./is-neg-zero":80,"./is-set":82,"./match":85}],87:[function(require,module,exports){ |
| (function (global, factory) { |
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : |
| typeof define === 'function' && define.amd ? define(factory) : |
| (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.typeDetect = factory()); |
| })(this, (function () { 'use strict'; |
| |
| var promiseExists = typeof Promise === 'function'; |
| var globalObject = (function (Obj) { |
| if (typeof globalThis === 'object') { |
| return globalThis; |
| } |
| Object.defineProperty(Obj, 'typeDetectGlobalObject', { |
| get: function get() { |
| return this; |
| }, |
| configurable: true, |
| }); |
| var global = typeDetectGlobalObject; |
| delete Obj.typeDetectGlobalObject; |
| return global; |
| })(Object.prototype); |
| var symbolExists = typeof Symbol !== 'undefined'; |
| var mapExists = typeof Map !== 'undefined'; |
| var setExists = typeof Set !== 'undefined'; |
| var weakMapExists = typeof WeakMap !== 'undefined'; |
| var weakSetExists = typeof WeakSet !== 'undefined'; |
| var dataViewExists = typeof DataView !== 'undefined'; |
| var symbolIteratorExists = symbolExists && typeof Symbol.iterator !== 'undefined'; |
| var symbolToStringTagExists = symbolExists && typeof Symbol.toStringTag !== 'undefined'; |
| var setEntriesExists = setExists && typeof Set.prototype.entries === 'function'; |
| var mapEntriesExists = mapExists && typeof Map.prototype.entries === 'function'; |
| var setIteratorPrototype = setEntriesExists && Object.getPrototypeOf(new Set().entries()); |
| var mapIteratorPrototype = mapEntriesExists && Object.getPrototypeOf(new Map().entries()); |
| var arrayIteratorExists = symbolIteratorExists && typeof Array.prototype[Symbol.iterator] === 'function'; |
| var arrayIteratorPrototype = arrayIteratorExists && Object.getPrototypeOf([][Symbol.iterator]()); |
| var stringIteratorExists = symbolIteratorExists && typeof String.prototype[Symbol.iterator] === 'function'; |
| var stringIteratorPrototype = stringIteratorExists && Object.getPrototypeOf(''[Symbol.iterator]()); |
| var toStringLeftSliceLength = 8; |
| var toStringRightSliceLength = -1; |
| function typeDetect(obj) { |
| var typeofObj = typeof obj; |
| if (typeofObj !== 'object') { |
| return typeofObj; |
| } |
| if (obj === null) { |
| return 'null'; |
| } |
| if (obj === globalObject) { |
| return 'global'; |
| } |
| if (Array.isArray(obj) && |
| (symbolToStringTagExists === false || !(Symbol.toStringTag in obj))) { |
| return 'Array'; |
| } |
| if (typeof window === 'object' && window !== null) { |
| if (typeof window.location === 'object' && obj === window.location) { |
| return 'Location'; |
| } |
| if (typeof window.document === 'object' && obj === window.document) { |
| return 'Document'; |
| } |
| if (typeof window.navigator === 'object') { |
| if (typeof window.navigator.mimeTypes === 'object' && |
| obj === window.navigator.mimeTypes) { |
| return 'MimeTypeArray'; |
| } |
| if (typeof window.navigator.plugins === 'object' && |
| obj === window.navigator.plugins) { |
| return 'PluginArray'; |
| } |
| } |
| if ((typeof window.HTMLElement === 'function' || |
| typeof window.HTMLElement === 'object') && |
| obj instanceof window.HTMLElement) { |
| if (obj.tagName === 'BLOCKQUOTE') { |
| return 'HTMLQuoteElement'; |
| } |
| if (obj.tagName === 'TD') { |
| return 'HTMLTableDataCellElement'; |
| } |
| if (obj.tagName === 'TH') { |
| return 'HTMLTableHeaderCellElement'; |
| } |
| } |
| } |
| var stringTag = (symbolToStringTagExists && obj[Symbol.toStringTag]); |
| if (typeof stringTag === 'string') { |
| return stringTag; |
| } |
| var objPrototype = Object.getPrototypeOf(obj); |
| if (objPrototype === RegExp.prototype) { |
| return 'RegExp'; |
| } |
| if (objPrototype === Date.prototype) { |
| return 'Date'; |
| } |
| if (promiseExists && objPrototype === Promise.prototype) { |
| return 'Promise'; |
| } |
| if (setExists && objPrototype === Set.prototype) { |
| return 'Set'; |
| } |
| if (mapExists && objPrototype === Map.prototype) { |
| return 'Map'; |
| } |
| if (weakSetExists && objPrototype === WeakSet.prototype) { |
| return 'WeakSet'; |
| } |
| if (weakMapExists && objPrototype === WeakMap.prototype) { |
| return 'WeakMap'; |
| } |
| if (dataViewExists && objPrototype === DataView.prototype) { |
| return 'DataView'; |
| } |
| if (mapExists && objPrototype === mapIteratorPrototype) { |
| return 'Map Iterator'; |
| } |
| if (setExists && objPrototype === setIteratorPrototype) { |
| return 'Set Iterator'; |
| } |
| if (arrayIteratorExists && objPrototype === arrayIteratorPrototype) { |
| return 'Array Iterator'; |
| } |
| if (stringIteratorExists && objPrototype === stringIteratorPrototype) { |
| return 'String Iterator'; |
| } |
| if (objPrototype === null) { |
| return 'Object'; |
| } |
| return Object |
| .prototype |
| .toString |
| .call(obj) |
| .slice(toStringLeftSliceLength, toStringRightSliceLength); |
| } |
| |
| return typeDetect; |
| |
| })); |
| |
| },{}],88:[function(require,module,exports){ |
| if (typeof Object.create === 'function') { |
| // implementation from standard node.js 'util' module |
| module.exports = function inherits(ctor, superCtor) { |
| ctor.super_ = superCtor |
| ctor.prototype = Object.create(superCtor.prototype, { |
| constructor: { |
| value: ctor, |
| enumerable: false, |
| writable: true, |
| configurable: true |
| } |
| }); |
| }; |
| } else { |
| // old school shim for old browsers |
| module.exports = function inherits(ctor, superCtor) { |
| ctor.super_ = superCtor |
| var TempCtor = function () {} |
| TempCtor.prototype = superCtor.prototype |
| ctor.prototype = new TempCtor() |
| ctor.prototype.constructor = ctor |
| } |
| } |
| |
| },{}],89:[function(require,module,exports){ |
| module.exports = function isBuffer(arg) { |
| return arg && typeof arg === 'object' |
| && typeof arg.copy === 'function' |
| && typeof arg.fill === 'function' |
| && typeof arg.readUInt8 === 'function'; |
| } |
| },{}],90:[function(require,module,exports){ |
| // Copyright Joyent, Inc. and other Node contributors. |
| // |
| // Permission is hereby granted, free of charge, to any person obtaining a |
| // copy of this software and associated documentation files (the |
| // "Software"), to deal in the Software without restriction, including |
| // without limitation the rights to use, copy, modify, merge, publish, |
| // distribute, sublicense, and/or sell copies of the Software, and to permit |
| // persons to whom the Software is furnished to do so, subject to the |
| // following conditions: |
| // |
| // The above copyright notice and this permission notice shall be included |
| // in all copies or substantial portions of the Software. |
| // |
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN |
| // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
| // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
| // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
| // USE OR OTHER DEALINGS IN THE SOFTWARE. |
| |
| var formatRegExp = /%[sdj%]/g; |
| exports.format = function(f) { |
| if (!isString(f)) { |
| var objects = []; |
| for (var i = 0; i < arguments.length; i++) { |
| objects.push(inspect(arguments[i])); |
| } |
| return objects.join(' '); |
| } |
| |
| var i = 1; |
| var args = arguments; |
| var len = args.length; |
| var str = String(f).replace(formatRegExp, function(x) { |
| if (x === '%%') return '%'; |
| if (i >= len) return x; |
| switch (x) { |
| case '%s': return String(args[i++]); |
| case '%d': return Number(args[i++]); |
| case '%j': |
| try { |
| return JSON.stringify(args[i++]); |
| } catch (_) { |
| return '[Circular]'; |
| } |
| default: |
| return x; |
| } |
| }); |
| for (var x = args[i]; i < len; x = args[++i]) { |
| if (isNull(x) || !isObject(x)) { |
| str += ' ' + x; |
| } else { |
| str += ' ' + inspect(x); |
| } |
| } |
| return str; |
| }; |
| |
| |
| // Mark that a method should not be used. |
| // Returns a modified function which warns once by default. |
| // If --no-deprecation is set, then it is a no-op. |
| exports.deprecate = function(fn, msg) { |
| // Allow for deprecating things in the process of starting up. |
| if (isUndefined(global.process)) { |
| return function() { |
| return exports.deprecate(fn, msg).apply(this, arguments); |
| }; |
| } |
| |
| if (process.noDeprecation === true) { |
| return fn; |
| } |
| |
| var warned = false; |
| function deprecated() { |
| if (!warned) { |
| if (process.throwDeprecation) { |
| throw new Error(msg); |
| } else if (process.traceDeprecation) { |
| console.trace(msg); |
| } else { |
| console.error(msg); |
| } |
| warned = true; |
| } |
| return fn.apply(this, arguments); |
| } |
| |
| return deprecated; |
| }; |
| |
| |
| var debugs = {}; |
| var debugEnviron; |
| exports.debuglog = function(set) { |
| if (isUndefined(debugEnviron)) |
| debugEnviron = process.env.NODE_DEBUG || ''; |
| set = set.toUpperCase(); |
| if (!debugs[set]) { |
| if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { |
| var pid = process.pid; |
| debugs[set] = function() { |
| var msg = exports.format.apply(exports, arguments); |
| console.error('%s %d: %s', set, pid, msg); |
| }; |
| } else { |
| debugs[set] = function() {}; |
| } |
| } |
| return debugs[set]; |
| }; |
| |
| |
| /** |
| * Echos the value of a value. Trys to print the value out |
| * in the best way possible given the different types. |
| * |
| * @param {Object} obj The object to print out. |
| * @param {Object} opts Optional options object that alters the output. |
| */ |
| /* legacy: obj, showHidden, depth, colors*/ |
| function inspect(obj, opts) { |
| // default options |
| var ctx = { |
| seen: [], |
| stylize: stylizeNoColor |
| }; |
| // legacy... |
| if (arguments.length >= 3) ctx.depth = arguments[2]; |
| if (arguments.length >= 4) ctx.colors = arguments[3]; |
| if (isBoolean(opts)) { |
| // legacy... |
| ctx.showHidden = opts; |
| } else if (opts) { |
| // got an "options" object |
| exports._extend(ctx, opts); |
| } |
| // set default options |
| if (isUndefined(ctx.showHidden)) ctx.showHidden = false; |
| if (isUndefined(ctx.depth)) ctx.depth = 2; |
| if (isUndefined(ctx.colors)) ctx.colors = false; |
| if (isUndefined(ctx.customInspect)) ctx.customInspect = true; |
| if (ctx.colors) ctx.stylize = stylizeWithColor; |
| return formatValue(ctx, obj, ctx.depth); |
| } |
| exports.inspect = inspect; |
| |
| |
| // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics |
| inspect.colors = { |
| 'bold' : [1, 22], |
| 'italic' : [3, 23], |
| 'underline' : [4, 24], |
| 'inverse' : [7, 27], |
| 'white' : [37, 39], |
| 'grey' : [90, 39], |
| 'black' : [30, 39], |
| 'blue' : [34, 39], |
| 'cyan' : [36, 39], |
| 'green' : [32, 39], |
| 'magenta' : [35, 39], |
| 'red' : [31, 39], |
| 'yellow' : [33, 39] |
| }; |
| |
| // Don't use 'blue' not visible on cmd.exe |
| inspect.styles = { |
| 'special': 'cyan', |
| 'number': 'yellow', |
| 'boolean': 'yellow', |
| 'undefined': 'grey', |
| 'null': 'bold', |
| 'string': 'green', |
| 'date': 'magenta', |
| // "name": intentionally not styling |
| 'regexp': 'red' |
| }; |
| |
| |
| function stylizeWithColor(str, styleType) { |
| var style = inspect.styles[styleType]; |
| |
| if (style) { |
| return '\u001b[' + inspect.colors[style][0] + 'm' + str + |
| '\u001b[' + inspect.colors[style][1] + 'm'; |
| } else { |
| return str; |
| } |
| } |
| |
| |
| function stylizeNoColor(str, styleType) { |
| return str; |
| } |
| |
| |
| function arrayToHash(array) { |
| var hash = {}; |
| |
| array.forEach(function(val, idx) { |
| hash[val] = true; |
| }); |
| |
| return hash; |
| } |
| |
| |
| function formatValue(ctx, value, recurseTimes) { |
| // Provide a hook for user-specified inspect functions. |
| // Check that value is an object with an inspect function on it |
| if (ctx.customInspect && |
| value && |
| isFunction(value.inspect) && |
| // Filter out the util module, it's inspect function is special |
| value.inspect !== exports.inspect && |
| // Also filter out any prototype objects using the circular check. |
| !(value.constructor && value.constructor.prototype === value)) { |
| var ret = value.inspect(recurseTimes, ctx); |
| if (!isString(ret)) { |
| ret = formatValue(ctx, ret, recurseTimes); |
| } |
| return ret; |
| } |
| |
| // Primitive types cannot have properties |
| var primitive = formatPrimitive(ctx, value); |
| if (primitive) { |
| return primitive; |
| } |
| |
| // Look up the keys of the object. |
| var keys = Object.keys(value); |
| var visibleKeys = arrayToHash(keys); |
| |
| if (ctx.showHidden) { |
| keys = Object.getOwnPropertyNames(value); |
| } |
| |
| // IE doesn't make error fields non-enumerable |
| // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx |
| if (isError(value) |
| && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { |
| return formatError(value); |
| } |
| |
| // Some type of object without properties can be shortcutted. |
| if (keys.length === 0) { |
| if (isFunction(value)) { |
| var name = value.name ? ': ' + value.name : ''; |
| return ctx.stylize('[Function' + name + ']', 'special'); |
| } |
| if (isRegExp(value)) { |
| return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); |
| } |
| if (isDate(value)) { |
| return ctx.stylize(Date.prototype.toString.call(value), 'date'); |
| } |
| if (isError(value)) { |
| return formatError(value); |
| } |
| } |
| |
| var base = '', array = false, braces = ['{', '}']; |
| |
| // Make Array say that they are Array |
| if (isArray(value)) { |
| array = true; |
| braces = ['[', ']']; |
| } |
| |
| // Make functions say that they are functions |
| if (isFunction(value)) { |
| var n = value.name ? ': ' + value.name : ''; |
| base = ' [Function' + n + ']'; |
| } |
| |
| // Make RegExps say that they are RegExps |
| if (isRegExp(value)) { |
| base = ' ' + RegExp.prototype.toString.call(value); |
| } |
| |
| // Make dates with properties first say the date |
| if (isDate(value)) { |
| base = ' ' + Date.prototype.toUTCString.call(value); |
| } |
| |
| // Make error with message first say the error |
| if (isError(value)) { |
| base = ' ' + formatError(value); |
| } |
| |
| if (keys.length === 0 && (!array || value.length == 0)) { |
| return braces[0] + base + braces[1]; |
| } |
| |
| if (recurseTimes < 0) { |
| if (isRegExp(value)) { |
| return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); |
| } else { |
| return ctx.stylize('[Object]', 'special'); |
| } |
| } |
| |
| ctx.seen.push(value); |
| |
| var output; |
| if (array) { |
| output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); |
| } else { |
| output = keys.map(function(key) { |
| return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); |
| }); |
| } |
| |
| ctx.seen.pop(); |
| |
| return reduceToSingleString(output, base, braces); |
| } |
| |
| |
| function formatPrimitive(ctx, value) { |
| if (isUndefined(value)) |
| return ctx.stylize('undefined', 'undefined'); |
| if (isString(value)) { |
| var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') |
| .replace(/'/g, "\\'") |
| .replace(/\\"/g, '"') + '\''; |
| return ctx.stylize(simple, 'string'); |
| } |
| if (isNumber(value)) |
| return ctx.stylize('' + value, 'number'); |
| if (isBoolean(value)) |
| return ctx.stylize('' + value, 'boolean'); |
| // For some reason typeof null is "object", so special case here. |
| if (isNull(value)) |
| return ctx.stylize('null', 'null'); |
| } |
| |
| |
| function formatError(value) { |
| return '[' + Error.prototype.toString.call(value) + ']'; |
| } |
| |
| |
| function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { |
| var output = []; |
| for (var i = 0, l = value.length; i < l; ++i) { |
| if (hasOwnProperty(value, String(i))) { |
| output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, |
| String(i), true)); |
| } else { |
| output.push(''); |
| } |
| } |
| keys.forEach(function(key) { |
| if (!key.match(/^\d+$/)) { |
| output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, |
| key, true)); |
| } |
| }); |
| return output; |
| } |
| |
| |
| function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { |
| var name, str, desc; |
| desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; |
| if (desc.get) { |
| if (desc.set) { |
| str = ctx.stylize('[Getter/Setter]', 'special'); |
| } else { |
| str = ctx.stylize('[Getter]', 'special'); |
| } |
| } else { |
| if (desc.set) { |
| str = ctx.stylize('[Setter]', 'special'); |
| } |
| } |
| if (!hasOwnProperty(visibleKeys, key)) { |
| name = '[' + key + ']'; |
| } |
| if (!str) { |
| if (ctx.seen.indexOf(desc.value) < 0) { |
| if (isNull(recurseTimes)) { |
| str = formatValue(ctx, desc.value, null); |
| } else { |
| str = formatValue(ctx, desc.value, recurseTimes - 1); |
| } |
| if (str.indexOf('\n') > -1) { |
| if (array) { |
| str = str.split('\n').map(function(line) { |
| return ' ' + line; |
| }).join('\n').substr(2); |
| } else { |
| str = '\n' + str.split('\n').map(function(line) { |
| return ' ' + line; |
| }).join('\n'); |
| } |
| } |
| } else { |
| str = ctx.stylize('[Circular]', 'special'); |
| } |
| } |
| if (isUndefined(name)) { |
| if (array && key.match(/^\d+$/)) { |
| return str; |
| } |
| name = JSON.stringify('' + key); |
| if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { |
| name = name.substr(1, name.length - 2); |
| name = ctx.stylize(name, 'name'); |
| } else { |
| name = name.replace(/'/g, "\\'") |
| .replace(/\\"/g, '"') |
| .replace(/(^"|"$)/g, "'"); |
| name = ctx.stylize(name, 'string'); |
| } |
| } |
| |
| return name + ': ' + str; |
| } |
| |
| |
| function reduceToSingleString(output, base, braces) { |
| var numLinesEst = 0; |
| var length = output.reduce(function(prev, cur) { |
| numLinesEst++; |
| if (cur.indexOf('\n') >= 0) numLinesEst++; |
| return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; |
| }, 0); |
| |
| if (length > 60) { |
| return braces[0] + |
| (base === '' ? '' : base + '\n ') + |
| ' ' + |
| output.join(',\n ') + |
| ' ' + |
| braces[1]; |
| } |
| |
| return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; |
| } |
| |
| |
| // NOTE: These type checking functions intentionally don't use `instanceof` |
| // because it is fragile and can be easily faked with `Object.create()`. |
| function isArray(ar) { |
| return Array.isArray(ar); |
| } |
| exports.isArray = isArray; |
| |
| function isBoolean(arg) { |
| return typeof arg === 'boolean'; |
| } |
| exports.isBoolean = isBoolean; |
| |
| function isNull(arg) { |
| return arg === null; |
| } |
| exports.isNull = isNull; |
| |
| function isNullOrUndefined(arg) { |
| return arg == null; |
| } |
| exports.isNullOrUndefined = isNullOrUndefined; |
| |
| function isNumber(arg) { |
| return typeof arg === 'number'; |
| } |
| exports.isNumber = isNumber; |
| |
| function isString(arg) { |
| return typeof arg === 'string'; |
| } |
| exports.isString = isString; |
| |
| function isSymbol(arg) { |
| return typeof arg === 'symbol'; |
| } |
| exports.isSymbol = isSymbol; |
| |
| function isUndefined(arg) { |
| return arg === void 0; |
| } |
| exports.isUndefined = isUndefined; |
| |
| function isRegExp(re) { |
| return isObject(re) && objectToString(re) === '[object RegExp]'; |
| } |
| exports.isRegExp = isRegExp; |
| |
| function isObject(arg) { |
| return typeof arg === 'object' && arg !== null; |
| } |
| exports.isObject = isObject; |
| |
| function isDate(d) { |
| return isObject(d) && objectToString(d) === '[object Date]'; |
| } |
| exports.isDate = isDate; |
| |
| function isError(e) { |
| return isObject(e) && |
| (objectToString(e) === '[object Error]' || e instanceof Error); |
| } |
| exports.isError = isError; |
| |
| function isFunction(arg) { |
| return typeof arg === 'function'; |
| } |
| exports.isFunction = isFunction; |
| |
| function isPrimitive(arg) { |
| return arg === null || |
| typeof arg === 'boolean' || |
| typeof arg === 'number' || |
| typeof arg === 'string' || |
| typeof arg === 'symbol' || // ES6 symbol |
| typeof arg === 'undefined'; |
| } |
| exports.isPrimitive = isPrimitive; |
| |
| exports.isBuffer = require('./support/isBuffer'); |
| |
| function objectToString(o) { |
| return Object.prototype.toString.call(o); |
| } |
| |
| |
| function pad(n) { |
| return n < 10 ? '0' + n.toString(10) : n.toString(10); |
| } |
| |
| |
| var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', |
| 'Oct', 'Nov', 'Dec']; |
| |
| // 26 Feb 16:19:34 |
| function timestamp() { |
| var d = new Date(); |
| var time = [pad(d.getHours()), |
| pad(d.getMinutes()), |
| pad(d.getSeconds())].join(':'); |
| return [d.getDate(), months[d.getMonth()], time].join(' '); |
| } |
| |
| |
| // log is just a thin wrapper to console.log that prepends a timestamp |
| exports.log = function() { |
| console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); |
| }; |
| |
| |
| /** |
| * Inherit the prototype methods from one constructor into another. |
| * |
| * The Function.prototype.inherits from lang.js rewritten as a standalone |
| * function (not on Function.prototype). NOTE: If this file is to be loaded |
| * during bootstrapping this function needs to be rewritten using some native |
| * functions as prototype setup using normal JavaScript does not work as |
| * expected during bootstrapping (see mirror.js in r114903). |
| * |
| * @param {function} ctor Constructor function which needs to inherit the |
| * prototype. |
| * @param {function} superCtor Constructor function to inherit prototype from. |
| */ |
| exports.inherits = require('inherits'); |
| |
| exports._extend = function(origin, add) { |
| // Don't do anything if add isn't an object |
| if (!add || !isObject(add)) return origin; |
| |
| var keys = Object.keys(add); |
| var i = keys.length; |
| while (i--) { |
| origin[keys[i]] = add[keys[i]]; |
| } |
| return origin; |
| }; |
| |
| function hasOwnProperty(obj, prop) { |
| return Object.prototype.hasOwnProperty.call(obj, prop); |
| } |
| |
| },{"./support/isBuffer":89,"inherits":88}],91:[function(require,module,exports){ |
| /*! |
| |
| diff v7.0.0 |
| |
| BSD 3-Clause License |
| |
| Copyright (c) 2009-2015, Kevin Decker <kpdecker@gmail.com> |
| All rights reserved. |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions are met: |
| |
| 1. Redistributions of source code must retain the above copyright notice, this |
| list of conditions and the following disclaimer. |
| |
| 2. Redistributions in binary form must reproduce the above copyright notice, |
| this list of conditions and the following disclaimer in the documentation |
| and/or other materials provided with the distribution. |
| |
| 3. Neither the name of the copyright holder nor the names of its |
| contributors may be used to endorse or promote products derived from |
| this software without specific prior written permission. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE |
| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| @license |
| */ |
| (function (global, factory) { |
| typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : |
| typeof define === 'function' && define.amd ? define(['exports'], factory) : |
| (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Diff = {})); |
| })(this, (function (exports) { 'use strict'; |
| |
| function Diff() {} |
| Diff.prototype = { |
| diff: function diff(oldString, newString) { |
| var _options$timeout; |
| var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; |
| var callback = options.callback; |
| if (typeof options === 'function') { |
| callback = options; |
| options = {}; |
| } |
| var self = this; |
| function done(value) { |
| value = self.postProcess(value, options); |
| if (callback) { |
| setTimeout(function () { |
| callback(value); |
| }, 0); |
| return true; |
| } else { |
| return value; |
| } |
| } |
| |
| // Allow subclasses to massage the input prior to running |
| oldString = this.castInput(oldString, options); |
| newString = this.castInput(newString, options); |
| oldString = this.removeEmpty(this.tokenize(oldString, options)); |
| newString = this.removeEmpty(this.tokenize(newString, options)); |
| var newLen = newString.length, |
| oldLen = oldString.length; |
| var editLength = 1; |
| var maxEditLength = newLen + oldLen; |
| if (options.maxEditLength != null) { |
| maxEditLength = Math.min(maxEditLength, options.maxEditLength); |
| } |
| var maxExecutionTime = (_options$timeout = options.timeout) !== null && _options$timeout !== void 0 ? _options$timeout : Infinity; |
| var abortAfterTimestamp = Date.now() + maxExecutionTime; |
| var bestPath = [{ |
| oldPos: -1, |
| lastComponent: undefined |
| }]; |
| |
| // Seed editLength = 0, i.e. the content starts with the same values |
| var newPos = this.extractCommon(bestPath[0], newString, oldString, 0, options); |
| if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) { |
| // Identity per the equality and tokenizer |
| return done(buildValues(self, bestPath[0].lastComponent, newString, oldString, self.useLongestToken)); |
| } |
| |
| // Once we hit the right edge of the edit graph on some diagonal k, we can |
| // definitely reach the end of the edit graph in no more than k edits, so |
| // there's no point in considering any moves to diagonal k+1 any more (from |
| // which we're guaranteed to need at least k+1 more edits). |
| // Similarly, once we've reached the bottom of the edit graph, there's no |
| // point considering moves to lower diagonals. |
| // We record this fact by setting minDiagonalToConsider and |
| // maxDiagonalToConsider to some finite value once we've hit the edge of |
| // the edit graph. |
| // This optimization is not faithful to the original algorithm presented in |
| // Myers's paper, which instead pointlessly extends D-paths off the end of |
| // the edit graph - see page 7 of Myers's paper which notes this point |
| // explicitly and illustrates it with a diagram. This has major performance |
| // implications for some common scenarios. For instance, to compute a diff |
| // where the new text simply appends d characters on the end of the |
| // original text of length n, the true Myers algorithm will take O(n+d^2) |
| // time while this optimization needs only O(n+d) time. |
| var minDiagonalToConsider = -Infinity, |
| maxDiagonalToConsider = Infinity; |
| |
| // Main worker method. checks all permutations of a given edit length for acceptance. |
| function execEditLength() { |
| for (var diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) { |
| var basePath = void 0; |
| var removePath = bestPath[diagonalPath - 1], |
| addPath = bestPath[diagonalPath + 1]; |
| if (removePath) { |
| // No one else is going to attempt to use this value, clear it |
| bestPath[diagonalPath - 1] = undefined; |
| } |
| var canAdd = false; |
| if (addPath) { |
| // what newPos will be after we do an insertion: |
| var addPathNewPos = addPath.oldPos - diagonalPath; |
| canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen; |
| } |
| var canRemove = removePath && removePath.oldPos + 1 < oldLen; |
| if (!canAdd && !canRemove) { |
| // If this path is a terminal then prune |
| bestPath[diagonalPath] = undefined; |
| continue; |
| } |
| |
| // Select the diagonal that we want to branch from. We select the prior |
| // path whose position in the old string is the farthest from the origin |
| // and does not pass the bounds of the diff graph |
| if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) { |
| basePath = self.addToPath(addPath, true, false, 0, options); |
| } else { |
| basePath = self.addToPath(removePath, false, true, 1, options); |
| } |
| newPos = self.extractCommon(basePath, newString, oldString, diagonalPath, options); |
| if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) { |
| // If we have hit the end of both strings, then we are done |
| return done(buildValues(self, basePath.lastComponent, newString, oldString, self.useLongestToken)); |
| } else { |
| bestPath[diagonalPath] = basePath; |
| if (basePath.oldPos + 1 >= oldLen) { |
| maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1); |
| } |
| if (newPos + 1 >= newLen) { |
| minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1); |
| } |
| } |
| } |
| editLength++; |
| } |
| |
| // Performs the length of edit iteration. Is a bit fugly as this has to support the |
| // sync and async mode which is never fun. Loops over execEditLength until a value |
| // is produced, or until the edit length exceeds options.maxEditLength (if given), |
| // in which case it will return undefined. |
| if (callback) { |
| (function exec() { |
| setTimeout(function () { |
| if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) { |
| return callback(); |
| } |
| if (!execEditLength()) { |
| exec(); |
| } |
| }, 0); |
| })(); |
| } else { |
| while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) { |
| var ret = execEditLength(); |
| if (ret) { |
| return ret; |
| } |
| } |
| } |
| }, |
| addToPath: function addToPath(path, added, removed, oldPosInc, options) { |
| var last = path.lastComponent; |
| if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) { |
| return { |
| oldPos: path.oldPos + oldPosInc, |
| lastComponent: { |
| count: last.count + 1, |
| added: added, |
| removed: removed, |
| previousComponent: last.previousComponent |
| } |
| }; |
| } else { |
| return { |
| oldPos: path.oldPos + oldPosInc, |
| lastComponent: { |
| count: 1, |
| added: added, |
| removed: removed, |
| previousComponent: last |
| } |
| }; |
| } |
| }, |
| extractCommon: function extractCommon(basePath, newString, oldString, diagonalPath, options) { |
| var newLen = newString.length, |
| oldLen = oldString.length, |
| oldPos = basePath.oldPos, |
| newPos = oldPos - diagonalPath, |
| commonCount = 0; |
| while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldString[oldPos + 1], newString[newPos + 1], options)) { |
| newPos++; |
| oldPos++; |
| commonCount++; |
| if (options.oneChangePerToken) { |
| basePath.lastComponent = { |
| count: 1, |
| previousComponent: basePath.lastComponent, |
| added: false, |
| removed: false |
| }; |
| } |
| } |
| if (commonCount && !options.oneChangePerToken) { |
| basePath.lastComponent = { |
| count: commonCount, |
| previousComponent: basePath.lastComponent, |
| added: false, |
| removed: false |
| }; |
| } |
| basePath.oldPos = oldPos; |
| return newPos; |
| }, |
| equals: function equals(left, right, options) { |
| if (options.comparator) { |
| return options.comparator(left, right); |
| } else { |
| return left === right || options.ignoreCase && left.toLowerCase() === right.toLowerCase(); |
| } |
| }, |
| removeEmpty: function removeEmpty(array) { |
| var ret = []; |
| for (var i = 0; i < array.length; i++) { |
| if (array[i]) { |
| ret.push(array[i]); |
| } |
| } |
| return ret; |
| }, |
| castInput: function castInput(value) { |
| return value; |
| }, |
| tokenize: function tokenize(value) { |
| return Array.from(value); |
| }, |
| join: function join(chars) { |
| return chars.join(''); |
| }, |
| postProcess: function postProcess(changeObjects) { |
| return changeObjects; |
| } |
| }; |
| function buildValues(diff, lastComponent, newString, oldString, useLongestToken) { |
| // First we convert our linked list of components in reverse order to an |
| // array in the right order: |
| var components = []; |
| var nextComponent; |
| while (lastComponent) { |
| components.push(lastComponent); |
| nextComponent = lastComponent.previousComponent; |
| delete lastComponent.previousComponent; |
| lastComponent = nextComponent; |
| } |
| components.reverse(); |
| var componentPos = 0, |
| componentLen = components.length, |
| newPos = 0, |
| oldPos = 0; |
| for (; componentPos < componentLen; componentPos++) { |
| var component = components[componentPos]; |
| if (!component.removed) { |
| if (!component.added && useLongestToken) { |
| var value = newString.slice(newPos, newPos + component.count); |
| value = value.map(function (value, i) { |
| var oldValue = oldString[oldPos + i]; |
| return oldValue.length > value.length ? oldValue : value; |
| }); |
| component.value = diff.join(value); |
| } else { |
| component.value = diff.join(newString.slice(newPos, newPos + component.count)); |
| } |
| newPos += component.count; |
| |
| // Common case |
| if (!component.added) { |
| oldPos += component.count; |
| } |
| } else { |
| component.value = diff.join(oldString.slice(oldPos, oldPos + component.count)); |
| oldPos += component.count; |
| } |
| } |
| return components; |
| } |
| |
| var characterDiff = new Diff(); |
| function diffChars(oldStr, newStr, options) { |
| return characterDiff.diff(oldStr, newStr, options); |
| } |
| |
| function longestCommonPrefix(str1, str2) { |
| var i; |
| for (i = 0; i < str1.length && i < str2.length; i++) { |
| if (str1[i] != str2[i]) { |
| return str1.slice(0, i); |
| } |
| } |
| return str1.slice(0, i); |
| } |
| function longestCommonSuffix(str1, str2) { |
| var i; |
| |
| // Unlike longestCommonPrefix, we need a special case to handle all scenarios |
| // where we return the empty string since str1.slice(-0) will return the |
| // entire string. |
| if (!str1 || !str2 || str1[str1.length - 1] != str2[str2.length - 1]) { |
| return ''; |
| } |
| for (i = 0; i < str1.length && i < str2.length; i++) { |
| if (str1[str1.length - (i + 1)] != str2[str2.length - (i + 1)]) { |
| return str1.slice(-i); |
| } |
| } |
| return str1.slice(-i); |
| } |
| function replacePrefix(string, oldPrefix, newPrefix) { |
| if (string.slice(0, oldPrefix.length) != oldPrefix) { |
| throw Error("string ".concat(JSON.stringify(string), " doesn't start with prefix ").concat(JSON.stringify(oldPrefix), "; this is a bug")); |
| } |
| return newPrefix + string.slice(oldPrefix.length); |
| } |
| function replaceSuffix(string, oldSuffix, newSuffix) { |
| if (!oldSuffix) { |
| return string + newSuffix; |
| } |
| if (string.slice(-oldSuffix.length) != oldSuffix) { |
| throw Error("string ".concat(JSON.stringify(string), " doesn't end with suffix ").concat(JSON.stringify(oldSuffix), "; this is a bug")); |
| } |
| return string.slice(0, -oldSuffix.length) + newSuffix; |
| } |
| function removePrefix(string, oldPrefix) { |
| return replacePrefix(string, oldPrefix, ''); |
| } |
| function removeSuffix(string, oldSuffix) { |
| return replaceSuffix(string, oldSuffix, ''); |
| } |
| function maximumOverlap(string1, string2) { |
| return string2.slice(0, overlapCount(string1, string2)); |
| } |
| |
| // Nicked from https://stackoverflow.com/a/60422853/1709587 |
| function overlapCount(a, b) { |
| // Deal with cases where the strings differ in length |
| var startA = 0; |
| if (a.length > b.length) { |
| startA = a.length - b.length; |
| } |
| var endB = b.length; |
| if (a.length < b.length) { |
| endB = a.length; |
| } |
| // Create a back-reference for each index |
| // that should be followed in case of a mismatch. |
| // We only need B to make these references: |
| var map = Array(endB); |
| var k = 0; // Index that lags behind j |
| map[0] = 0; |
| for (var j = 1; j < endB; j++) { |
| if (b[j] == b[k]) { |
| map[j] = map[k]; // skip over the same character (optional optimisation) |
| } else { |
| map[j] = k; |
| } |
| while (k > 0 && b[j] != b[k]) { |
| k = map[k]; |
| } |
| if (b[j] == b[k]) { |
| k++; |
| } |
| } |
| // Phase 2: use these references while iterating over A |
| k = 0; |
| for (var i = startA; i < a.length; i++) { |
| while (k > 0 && a[i] != b[k]) { |
| k = map[k]; |
| } |
| if (a[i] == b[k]) { |
| k++; |
| } |
| } |
| return k; |
| } |
| |
| /** |
| * Returns true if the string consistently uses Windows line endings. |
| */ |
| function hasOnlyWinLineEndings(string) { |
| return string.includes('\r\n') && !string.startsWith('\n') && !string.match(/[^\r]\n/); |
| } |
| |
| /** |
| * Returns true if the string consistently uses Unix line endings. |
| */ |
| function hasOnlyUnixLineEndings(string) { |
| return !string.includes('\r\n') && string.includes('\n'); |
| } |
| |
| // Based on https://en.wikipedia.org/wiki/Latin_script_in_Unicode |
| // |
| // Ranges and exceptions: |
| // Latin-1 Supplement, 0080–00FF |
| // - U+00D7 × Multiplication sign |
| // - U+00F7 ÷ Division sign |
| // Latin Extended-A, 0100–017F |
| // Latin Extended-B, 0180–024F |
| // IPA Extensions, 0250–02AF |
| // Spacing Modifier Letters, 02B0–02FF |
| // - U+02C7 ˇ ˇ Caron |
| // - U+02D8 ˘ ˘ Breve |
| // - U+02D9 ˙ ˙ Dot Above |
| // - U+02DA ˚ ˚ Ring Above |
| // - U+02DB ˛ ˛ Ogonek |
| // - U+02DC ˜ ˜ Small Tilde |
| // - U+02DD ˝ ˝ Double Acute Accent |
| // Latin Extended Additional, 1E00–1EFF |
| var extendedWordChars = "a-zA-Z0-9_\\u{C0}-\\u{FF}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}"; |
| |
| // Each token is one of the following: |
| // - A punctuation mark plus the surrounding whitespace |
| // - A word plus the surrounding whitespace |
| // - Pure whitespace (but only in the special case where this the entire text |
| // is just whitespace) |
| // |
| // We have to include surrounding whitespace in the tokens because the two |
| // alternative approaches produce horribly broken results: |
| // * If we just discard the whitespace, we can't fully reproduce the original |
| // text from the sequence of tokens and any attempt to render the diff will |
| // get the whitespace wrong. |
| // * If we have separate tokens for whitespace, then in a typical text every |
| // second token will be a single space character. But this often results in |
| // the optimal diff between two texts being a perverse one that preserves |
| // the spaces between words but deletes and reinserts actual common words. |
| // See https://github.com/kpdecker/jsdiff/issues/160#issuecomment-1866099640 |
| // for an example. |
| // |
| // Keeping the surrounding whitespace of course has implications for .equals |
| // and .join, not just .tokenize. |
| |
| // This regex does NOT fully implement the tokenization rules described above. |
| // Instead, it gives runs of whitespace their own "token". The tokenize method |
| // then handles stitching whitespace tokens onto adjacent word or punctuation |
| // tokens. |
| var tokenizeIncludingWhitespace = new RegExp("[".concat(extendedWordChars, "]+|\\s+|[^").concat(extendedWordChars, "]"), 'ug'); |
| var wordDiff = new Diff(); |
| wordDiff.equals = function (left, right, options) { |
| if (options.ignoreCase) { |
| left = left.toLowerCase(); |
| right = right.toLowerCase(); |
| } |
| return left.trim() === right.trim(); |
| }; |
| wordDiff.tokenize = function (value) { |
| var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; |
| var parts; |
| if (options.intlSegmenter) { |
| if (options.intlSegmenter.resolvedOptions().granularity != 'word') { |
| throw new Error('The segmenter passed must have a granularity of "word"'); |
| } |
| parts = Array.from(options.intlSegmenter.segment(value), function (segment) { |
| return segment.segment; |
| }); |
| } else { |
| parts = value.match(tokenizeIncludingWhitespace) || []; |
| } |
| var tokens = []; |
| var prevPart = null; |
| parts.forEach(function (part) { |
| if (/\s/.test(part)) { |
| if (prevPart == null) { |
| tokens.push(part); |
| } else { |
| tokens.push(tokens.pop() + part); |
| } |
| } else if (/\s/.test(prevPart)) { |
| if (tokens[tokens.length - 1] == prevPart) { |
| tokens.push(tokens.pop() + part); |
| } else { |
| tokens.push(prevPart + part); |
| } |
| } else { |
| tokens.push(part); |
| } |
| prevPart = part; |
| }); |
| return tokens; |
| }; |
| wordDiff.join = function (tokens) { |
| // Tokens being joined here will always have appeared consecutively in the |
| // same text, so we can simply strip off the leading whitespace from all the |
| // tokens except the first (and except any whitespace-only tokens - but such |
| // a token will always be the first and only token anyway) and then join them |
| // and the whitespace around words and punctuation will end up correct. |
| return tokens.map(function (token, i) { |
| if (i == 0) { |
| return token; |
| } else { |
| return token.replace(/^\s+/, ''); |
| } |
| }).join(''); |
| }; |
| wordDiff.postProcess = function (changes, options) { |
| if (!changes || options.oneChangePerToken) { |
| return changes; |
| } |
| var lastKeep = null; |
| // Change objects representing any insertion or deletion since the last |
| // "keep" change object. There can be at most one of each. |
| var insertion = null; |
| var deletion = null; |
| changes.forEach(function (change) { |
| if (change.added) { |
| insertion = change; |
| } else if (change.removed) { |
| deletion = change; |
| } else { |
| if (insertion || deletion) { |
| // May be false at start of text |
| dedupeWhitespaceInChangeObjects(lastKeep, deletion, insertion, change); |
| } |
| lastKeep = change; |
| insertion = null; |
| deletion = null; |
| } |
| }); |
| if (insertion || deletion) { |
| dedupeWhitespaceInChangeObjects(lastKeep, deletion, insertion, null); |
| } |
| return changes; |
| }; |
| function diffWords(oldStr, newStr, options) { |
| // This option has never been documented and never will be (it's clearer to |
| // just call `diffWordsWithSpace` directly if you need that behavior), but |
| // has existed in jsdiff for a long time, so we retain support for it here |
| // for the sake of backwards compatibility. |
| if ((options === null || options === void 0 ? void 0 : options.ignoreWhitespace) != null && !options.ignoreWhitespace) { |
| return diffWordsWithSpace(oldStr, newStr, options); |
| } |
| return wordDiff.diff(oldStr, newStr, options); |
| } |
| function dedupeWhitespaceInChangeObjects(startKeep, deletion, insertion, endKeep) { |
| // Before returning, we tidy up the leading and trailing whitespace of the |
| // change objects to eliminate cases where trailing whitespace in one object |
| // is repeated as leading whitespace in the next. |
| // Below are examples of the outcomes we want here to explain the code. |
| // I=insert, K=keep, D=delete |
| // 1. diffing 'foo bar baz' vs 'foo baz' |
| // Prior to cleanup, we have K:'foo ' D:' bar ' K:' baz' |
| // After cleanup, we want: K:'foo ' D:'bar ' K:'baz' |
| // |
| // 2. Diffing 'foo bar baz' vs 'foo qux baz' |
| // Prior to cleanup, we have K:'foo ' D:' bar ' I:' qux ' K:' baz' |
| // After cleanup, we want K:'foo ' D:'bar' I:'qux' K:' baz' |
| // |
| // 3. Diffing 'foo\nbar baz' vs 'foo baz' |
| // Prior to cleanup, we have K:'foo ' D:'\nbar ' K:' baz' |
| // After cleanup, we want K'foo' D:'\nbar' K:' baz' |
| // |
| // 4. Diffing 'foo baz' vs 'foo\nbar baz' |
| // Prior to cleanup, we have K:'foo\n' I:'\nbar ' K:' baz' |
| // After cleanup, we ideally want K'foo' I:'\nbar' K:' baz' |
| // but don't actually manage this currently (the pre-cleanup change |
| // objects don't contain enough information to make it possible). |
| // |
| // 5. Diffing 'foo bar baz' vs 'foo baz' |
| // Prior to cleanup, we have K:'foo ' D:' bar ' K:' baz' |
| // After cleanup, we want K:'foo ' D:' bar ' K:'baz' |
| // |
| // Our handling is unavoidably imperfect in the case where there's a single |
| // indel between keeps and the whitespace has changed. For instance, consider |
| // diffing 'foo\tbar\nbaz' vs 'foo baz'. Unless we create an extra change |
| // object to represent the insertion of the space character (which isn't even |
| // a token), we have no way to avoid losing information about the texts' |
| // original whitespace in the result we return. Still, we do our best to |
| // output something that will look sensible if we e.g. print it with |
| // insertions in green and deletions in red. |
| |
| // Between two "keep" change objects (or before the first or after the last |
| // change object), we can have either: |
| // * A "delete" followed by an "insert" |
| // * Just an "insert" |
| // * Just a "delete" |
| // We handle the three cases separately. |
| if (deletion && insertion) { |
| var oldWsPrefix = deletion.value.match(/^\s*/)[0]; |
| var oldWsSuffix = deletion.value.match(/\s*$/)[0]; |
| var newWsPrefix = insertion.value.match(/^\s*/)[0]; |
| var newWsSuffix = insertion.value.match(/\s*$/)[0]; |
| if (startKeep) { |
| var commonWsPrefix = longestCommonPrefix(oldWsPrefix, newWsPrefix); |
| startKeep.value = replaceSuffix(startKeep.value, newWsPrefix, commonWsPrefix); |
| deletion.value = removePrefix(deletion.value, commonWsPrefix); |
| insertion.value = removePrefix(insertion.value, commonWsPrefix); |
| } |
| if (endKeep) { |
| var commonWsSuffix = longestCommonSuffix(oldWsSuffix, newWsSuffix); |
| endKeep.value = replacePrefix(endKeep.value, newWsSuffix, commonWsSuffix); |
| deletion.value = removeSuffix(deletion.value, commonWsSuffix); |
| insertion.value = removeSuffix(insertion.value, commonWsSuffix); |
| } |
| } else if (insertion) { |
| // The whitespaces all reflect what was in the new text rather than |
| // the old, so we essentially have no information about whitespace |
| // insertion or deletion. We just want to dedupe the whitespace. |
| // We do that by having each change object keep its trailing |
| // whitespace and deleting duplicate leading whitespace where |
| // present. |
| if (startKeep) { |
| insertion.value = insertion.value.replace(/^\s*/, ''); |
| } |
| if (endKeep) { |
| endKeep.value = endKeep.value.replace(/^\s*/, ''); |
| } |
| // otherwise we've got a deletion and no insertion |
| } else if (startKeep && endKeep) { |
| var newWsFull = endKeep.value.match(/^\s*/)[0], |
| delWsStart = deletion.value.match(/^\s*/)[0], |
| delWsEnd = deletion.value.match(/\s*$/)[0]; |
| |
| // Any whitespace that comes straight after startKeep in both the old and |
| // new texts, assign to startKeep and remove from the deletion. |
| var newWsStart = longestCommonPrefix(newWsFull, delWsStart); |
| deletion.value = removePrefix(deletion.value, newWsStart); |
| |
| // Any whitespace that comes straight before endKeep in both the old and |
| // new texts, and hasn't already been assigned to startKeep, assign to |
| // endKeep and remove from the deletion. |
| var newWsEnd = longestCommonSuffix(removePrefix(newWsFull, newWsStart), delWsEnd); |
| deletion.value = removeSuffix(deletion.value, newWsEnd); |
| endKeep.value = replacePrefix(endKeep.value, newWsFull, newWsEnd); |
| |
| // If there's any whitespace from the new text that HASN'T already been |
| // assigned, assign it to the start: |
| startKeep.value = replaceSuffix(startKeep.value, newWsFull, newWsFull.slice(0, newWsFull.length - newWsEnd.length)); |
| } else if (endKeep) { |
| // We are at the start of the text. Preserve all the whitespace on |
| // endKeep, and just remove whitespace from the end of deletion to the |
| // extent that it overlaps with the start of endKeep. |
| var endKeepWsPrefix = endKeep.value.match(/^\s*/)[0]; |
| var deletionWsSuffix = deletion.value.match(/\s*$/)[0]; |
| var overlap = maximumOverlap(deletionWsSuffix, endKeepWsPrefix); |
| deletion.value = removeSuffix(deletion.value, overlap); |
| } else if (startKeep) { |
| // We are at the END of the text. Preserve all the whitespace on |
| // startKeep, and just remove whitespace from the start of deletion to |
| // the extent that it overlaps with the end of startKeep. |
| var startKeepWsSuffix = startKeep.value.match(/\s*$/)[0]; |
| var deletionWsPrefix = deletion.value.match(/^\s*/)[0]; |
| var _overlap = maximumOverlap(startKeepWsSuffix, deletionWsPrefix); |
| deletion.value = removePrefix(deletion.value, _overlap); |
| } |
| } |
| var wordWithSpaceDiff = new Diff(); |
| wordWithSpaceDiff.tokenize = function (value) { |
| // Slightly different to the tokenizeIncludingWhitespace regex used above in |
| // that this one treats each individual newline as a distinct tokens, rather |
| // than merging them into other surrounding whitespace. This was requested |
| // in https://github.com/kpdecker/jsdiff/issues/180 & |
| // https://github.com/kpdecker/jsdiff/issues/211 |
| var regex = new RegExp("(\\r?\\n)|[".concat(extendedWordChars, "]+|[^\\S\\n\\r]+|[^").concat(extendedWordChars, "]"), 'ug'); |
| return value.match(regex) || []; |
| }; |
| function diffWordsWithSpace(oldStr, newStr, options) { |
| return wordWithSpaceDiff.diff(oldStr, newStr, options); |
| } |
| |
| function generateOptions(options, defaults) { |
| if (typeof options === 'function') { |
| defaults.callback = options; |
| } else if (options) { |
| for (var name in options) { |
| /* istanbul ignore else */ |
| if (options.hasOwnProperty(name)) { |
| defaults[name] = options[name]; |
| } |
| } |
| } |
| return defaults; |
| } |
| |
| var lineDiff = new Diff(); |
| lineDiff.tokenize = function (value, options) { |
| if (options.stripTrailingCr) { |
| // remove one \r before \n to match GNU diff's --strip-trailing-cr behavior |
| value = value.replace(/\r\n/g, '\n'); |
| } |
| var retLines = [], |
| linesAndNewlines = value.split(/(\n|\r\n)/); |
| |
| // Ignore the final empty token that occurs if the string ends with a new line |
| if (!linesAndNewlines[linesAndNewlines.length - 1]) { |
| linesAndNewlines.pop(); |
| } |
| |
| // Merge the content and line separators into single tokens |
| for (var i = 0; i < linesAndNewlines.length; i++) { |
| var line = linesAndNewlines[i]; |
| if (i % 2 && !options.newlineIsToken) { |
| retLines[retLines.length - 1] += line; |
| } else { |
| retLines.push(line); |
| } |
| } |
| return retLines; |
| }; |
| lineDiff.equals = function (left, right, options) { |
| // If we're ignoring whitespace, we need to normalise lines by stripping |
| // whitespace before checking equality. (This has an annoying interaction |
| // with newlineIsToken that requires special handling: if newlines get their |
| // own token, then we DON'T want to trim the *newline* tokens down to empty |
| // strings, since this would cause us to treat whitespace-only line content |
| // as equal to a separator between lines, which would be weird and |
| // inconsistent with the documented behavior of the options.) |
| if (options.ignoreWhitespace) { |
| if (!options.newlineIsToken || !left.includes('\n')) { |
| left = left.trim(); |
| } |
| if (!options.newlineIsToken || !right.includes('\n')) { |
| right = right.trim(); |
| } |
| } else if (options.ignoreNewlineAtEof && !options.newlineIsToken) { |
| if (left.endsWith('\n')) { |
| left = left.slice(0, -1); |
| } |
| if (right.endsWith('\n')) { |
| right = right.slice(0, -1); |
| } |
| } |
| return Diff.prototype.equals.call(this, left, right, options); |
| }; |
| function diffLines(oldStr, newStr, callback) { |
| return lineDiff.diff(oldStr, newStr, callback); |
| } |
| |
| // Kept for backwards compatibility. This is a rather arbitrary wrapper method |
| // that just calls `diffLines` with `ignoreWhitespace: true`. It's confusing to |
| // have two ways to do exactly the same thing in the API, so we no longer |
| // document this one (library users should explicitly use `diffLines` with |
| // `ignoreWhitespace: true` instead) but we keep it around to maintain |
| // compatibility with code that used old versions. |
| function diffTrimmedLines(oldStr, newStr, callback) { |
| var options = generateOptions(callback, { |
| ignoreWhitespace: true |
| }); |
| return lineDiff.diff(oldStr, newStr, options); |
| } |
| |
| var sentenceDiff = new Diff(); |
| sentenceDiff.tokenize = function (value) { |
| return value.split(/(\S.+?[.!?])(?=\s+|$)/); |
| }; |
| function diffSentences(oldStr, newStr, callback) { |
| return sentenceDiff.diff(oldStr, newStr, callback); |
| } |
| |
| var cssDiff = new Diff(); |
| cssDiff.tokenize = function (value) { |
| return value.split(/([{}:;,]|\s+)/); |
| }; |
| function diffCss(oldStr, newStr, callback) { |
| return cssDiff.diff(oldStr, newStr, callback); |
| } |
| |
| function ownKeys(e, r) { |
| var t = Object.keys(e); |
| if (Object.getOwnPropertySymbols) { |
| var o = Object.getOwnPropertySymbols(e); |
| r && (o = o.filter(function (r) { |
| return Object.getOwnPropertyDescriptor(e, r).enumerable; |
| })), t.push.apply(t, o); |
| } |
| return t; |
| } |
| function _objectSpread2(e) { |
| for (var r = 1; r < arguments.length; r++) { |
| var t = null != arguments[r] ? arguments[r] : {}; |
| r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { |
| _defineProperty(e, r, t[r]); |
| }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { |
| Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); |
| }); |
| } |
| return e; |
| } |
| function _toPrimitive(t, r) { |
| if ("object" != typeof t || !t) return t; |
| var e = t[Symbol.toPrimitive]; |
| if (void 0 !== e) { |
| var i = e.call(t, r || "default"); |
| if ("object" != typeof i) return i; |
| throw new TypeError("@@toPrimitive must return a primitive value."); |
| } |
| return ("string" === r ? String : Number)(t); |
| } |
| function _toPropertyKey(t) { |
| var i = _toPrimitive(t, "string"); |
| return "symbol" == typeof i ? i : i + ""; |
| } |
| function _typeof(o) { |
| "@babel/helpers - typeof"; |
| |
| return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { |
| return typeof o; |
| } : function (o) { |
| return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; |
| }, _typeof(o); |
| } |
| function _defineProperty(obj, key, value) { |
| key = _toPropertyKey(key); |
| if (key in obj) { |
| Object.defineProperty(obj, key, { |
| value: value, |
| enumerable: true, |
| configurable: true, |
| writable: true |
| }); |
| } else { |
| obj[key] = value; |
| } |
| return obj; |
| } |
| function _toConsumableArray(arr) { |
| return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); |
| } |
| function _arrayWithoutHoles(arr) { |
| if (Array.isArray(arr)) return _arrayLikeToArray(arr); |
| } |
| function _iterableToArray(iter) { |
| if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); |
| } |
| function _unsupportedIterableToArray(o, minLen) { |
| if (!o) return; |
| if (typeof o === "string") return _arrayLikeToArray(o, minLen); |
| var n = Object.prototype.toString.call(o).slice(8, -1); |
| if (n === "Object" && o.constructor) n = o.constructor.name; |
| if (n === "Map" || n === "Set") return Array.from(o); |
| if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); |
| } |
| function _arrayLikeToArray(arr, len) { |
| if (len == null || len > arr.length) len = arr.length; |
| for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; |
| return arr2; |
| } |
| function _nonIterableSpread() { |
| throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); |
| } |
| |
| var jsonDiff = new Diff(); |
| // Discriminate between two lines of pretty-printed, serialized JSON where one of them has a |
| // dangling comma and the other doesn't. Turns out including the dangling comma yields the nicest output: |
| jsonDiff.useLongestToken = true; |
| jsonDiff.tokenize = lineDiff.tokenize; |
| jsonDiff.castInput = function (value, options) { |
| var undefinedReplacement = options.undefinedReplacement, |
| _options$stringifyRep = options.stringifyReplacer, |
| stringifyReplacer = _options$stringifyRep === void 0 ? function (k, v) { |
| return typeof v === 'undefined' ? undefinedReplacement : v; |
| } : _options$stringifyRep; |
| return typeof value === 'string' ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), stringifyReplacer, ' '); |
| }; |
| jsonDiff.equals = function (left, right, options) { |
| return Diff.prototype.equals.call(jsonDiff, left.replace(/,([\r\n])/g, '$1'), right.replace(/,([\r\n])/g, '$1'), options); |
| }; |
| function diffJson(oldObj, newObj, options) { |
| return jsonDiff.diff(oldObj, newObj, options); |
| } |
| |
| // This function handles the presence of circular references by bailing out when encountering an |
| // object that is already on the "stack" of items being processed. Accepts an optional replacer |
| function canonicalize(obj, stack, replacementStack, replacer, key) { |
| stack = stack || []; |
| replacementStack = replacementStack || []; |
| if (replacer) { |
| obj = replacer(key, obj); |
| } |
| var i; |
| for (i = 0; i < stack.length; i += 1) { |
| if (stack[i] === obj) { |
| return replacementStack[i]; |
| } |
| } |
| var canonicalizedObj; |
| if ('[object Array]' === Object.prototype.toString.call(obj)) { |
| stack.push(obj); |
| canonicalizedObj = new Array(obj.length); |
| replacementStack.push(canonicalizedObj); |
| for (i = 0; i < obj.length; i += 1) { |
| canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack, replacer, key); |
| } |
| stack.pop(); |
| replacementStack.pop(); |
| return canonicalizedObj; |
| } |
| if (obj && obj.toJSON) { |
| obj = obj.toJSON(); |
| } |
| if (_typeof(obj) === 'object' && obj !== null) { |
| stack.push(obj); |
| canonicalizedObj = {}; |
| replacementStack.push(canonicalizedObj); |
| var sortedKeys = [], |
| _key; |
| for (_key in obj) { |
| /* istanbul ignore else */ |
| if (Object.prototype.hasOwnProperty.call(obj, _key)) { |
| sortedKeys.push(_key); |
| } |
| } |
| sortedKeys.sort(); |
| for (i = 0; i < sortedKeys.length; i += 1) { |
| _key = sortedKeys[i]; |
| canonicalizedObj[_key] = canonicalize(obj[_key], stack, replacementStack, replacer, _key); |
| } |
| stack.pop(); |
| replacementStack.pop(); |
| } else { |
| canonicalizedObj = obj; |
| } |
| return canonicalizedObj; |
| } |
| |
| var arrayDiff = new Diff(); |
| arrayDiff.tokenize = function (value) { |
| return value.slice(); |
| }; |
| arrayDiff.join = arrayDiff.removeEmpty = function (value) { |
| return value; |
| }; |
| function diffArrays(oldArr, newArr, callback) { |
| return arrayDiff.diff(oldArr, newArr, callback); |
| } |
| |
| function unixToWin(patch) { |
| if (Array.isArray(patch)) { |
| return patch.map(unixToWin); |
| } |
| return _objectSpread2(_objectSpread2({}, patch), {}, { |
| hunks: patch.hunks.map(function (hunk) { |
| return _objectSpread2(_objectSpread2({}, hunk), {}, { |
| lines: hunk.lines.map(function (line, i) { |
| var _hunk$lines; |
| return line.startsWith('\\') || line.endsWith('\r') || (_hunk$lines = hunk.lines[i + 1]) !== null && _hunk$lines !== void 0 && _hunk$lines.startsWith('\\') ? line : line + '\r'; |
| }) |
| }); |
| }) |
| }); |
| } |
| function winToUnix(patch) { |
| if (Array.isArray(patch)) { |
| return patch.map(winToUnix); |
| } |
| return _objectSpread2(_objectSpread2({}, patch), {}, { |
| hunks: patch.hunks.map(function (hunk) { |
| return _objectSpread2(_objectSpread2({}, hunk), {}, { |
| lines: hunk.lines.map(function (line) { |
| return line.endsWith('\r') ? line.substring(0, line.length - 1) : line; |
| }) |
| }); |
| }) |
| }); |
| } |
| |
| /** |
| * Returns true if the patch consistently uses Unix line endings (or only involves one line and has |
| * no line endings). |
| */ |
| function isUnix(patch) { |
| if (!Array.isArray(patch)) { |
| patch = [patch]; |
| } |
| return !patch.some(function (index) { |
| return index.hunks.some(function (hunk) { |
| return hunk.lines.some(function (line) { |
| return !line.startsWith('\\') && line.endsWith('\r'); |
| }); |
| }); |
| }); |
| } |
| |
| /** |
| * Returns true if the patch uses Windows line endings and only Windows line endings. |
| */ |
| function isWin(patch) { |
| if (!Array.isArray(patch)) { |
| patch = [patch]; |
| } |
| return patch.some(function (index) { |
| return index.hunks.some(function (hunk) { |
| return hunk.lines.some(function (line) { |
| return line.endsWith('\r'); |
| }); |
| }); |
| }) && patch.every(function (index) { |
| return index.hunks.every(function (hunk) { |
| return hunk.lines.every(function (line, i) { |
| var _hunk$lines2; |
| return line.startsWith('\\') || line.endsWith('\r') || ((_hunk$lines2 = hunk.lines[i + 1]) === null || _hunk$lines2 === void 0 ? void 0 : _hunk$lines2.startsWith('\\')); |
| }); |
| }); |
| }); |
| } |
| |
| function parsePatch(uniDiff) { |
| var diffstr = uniDiff.split(/\n/), |
| list = [], |
| i = 0; |
| function parseIndex() { |
| var index = {}; |
| list.push(index); |
| |
| // Parse diff metadata |
| while (i < diffstr.length) { |
| var line = diffstr[i]; |
| |
| // File header found, end parsing diff metadata |
| if (/^(\-\-\-|\+\+\+|@@)\s/.test(line)) { |
| break; |
| } |
| |
| // Diff index |
| var header = /^(?:Index:|diff(?: -r \w+)+)\s+(.+?)\s*$/.exec(line); |
| if (header) { |
| index.index = header[1]; |
| } |
| i++; |
| } |
| |
| // Parse file headers if they are defined. Unified diff requires them, but |
| // there's no technical issues to have an isolated hunk without file header |
| parseFileHeader(index); |
| parseFileHeader(index); |
| |
| // Parse hunks |
| index.hunks = []; |
| while (i < diffstr.length) { |
| var _line = diffstr[i]; |
| if (/^(Index:\s|diff\s|\-\-\-\s|\+\+\+\s|===================================================================)/.test(_line)) { |
| break; |
| } else if (/^@@/.test(_line)) { |
| index.hunks.push(parseHunk()); |
| } else if (_line) { |
| throw new Error('Unknown line ' + (i + 1) + ' ' + JSON.stringify(_line)); |
| } else { |
| i++; |
| } |
| } |
| } |
| |
| // Parses the --- and +++ headers, if none are found, no lines |
| // are consumed. |
| function parseFileHeader(index) { |
| var fileHeader = /^(---|\+\+\+)\s+(.*)\r?$/.exec(diffstr[i]); |
| if (fileHeader) { |
| var keyPrefix = fileHeader[1] === '---' ? 'old' : 'new'; |
| var data = fileHeader[2].split('\t', 2); |
| var fileName = data[0].replace(/\\\\/g, '\\'); |
| if (/^".*"$/.test(fileName)) { |
| fileName = fileName.substr(1, fileName.length - 2); |
| } |
| index[keyPrefix + 'FileName'] = fileName; |
| index[keyPrefix + 'Header'] = (data[1] || '').trim(); |
| i++; |
| } |
| } |
| |
| // Parses a hunk |
| // This assumes that we are at the start of a hunk. |
| function parseHunk() { |
| var chunkHeaderIndex = i, |
| chunkHeaderLine = diffstr[i++], |
| chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/); |
| var hunk = { |
| oldStart: +chunkHeader[1], |
| oldLines: typeof chunkHeader[2] === 'undefined' ? 1 : +chunkHeader[2], |
| newStart: +chunkHeader[3], |
| newLines: typeof chunkHeader[4] === 'undefined' ? 1 : +chunkHeader[4], |
| lines: [] |
| }; |
| |
| // Unified Diff Format quirk: If the chunk size is 0, |
| // the first number is one lower than one would expect. |
| // https://www.artima.com/weblogs/viewpost.jsp?thread=164293 |
| if (hunk.oldLines === 0) { |
| hunk.oldStart += 1; |
| } |
| if (hunk.newLines === 0) { |
| hunk.newStart += 1; |
| } |
| var addCount = 0, |
| removeCount = 0; |
| for (; i < diffstr.length && (removeCount < hunk.oldLines || addCount < hunk.newLines || (_diffstr$i = diffstr[i]) !== null && _diffstr$i !== void 0 && _diffstr$i.startsWith('\\')); i++) { |
| var _diffstr$i; |
| var operation = diffstr[i].length == 0 && i != diffstr.length - 1 ? ' ' : diffstr[i][0]; |
| if (operation === '+' || operation === '-' || operation === ' ' || operation === '\\') { |
| hunk.lines.push(diffstr[i]); |
| if (operation === '+') { |
| addCount++; |
| } else if (operation === '-') { |
| removeCount++; |
| } else if (operation === ' ') { |
| addCount++; |
| removeCount++; |
| } |
| } else { |
| throw new Error("Hunk at line ".concat(chunkHeaderIndex + 1, " contained invalid line ").concat(diffstr[i])); |
| } |
| } |
| |
| // Handle the empty block count case |
| if (!addCount && hunk.newLines === 1) { |
| hunk.newLines = 0; |
| } |
| if (!removeCount && hunk.oldLines === 1) { |
| hunk.oldLines = 0; |
| } |
| |
| // Perform sanity checking |
| if (addCount !== hunk.newLines) { |
| throw new Error('Added line count did not match for hunk at line ' + (chunkHeaderIndex + 1)); |
| } |
| if (removeCount !== hunk.oldLines) { |
| throw new Error('Removed line count did not match for hunk at line ' + (chunkHeaderIndex + 1)); |
| } |
| return hunk; |
| } |
| while (i < diffstr.length) { |
| parseIndex(); |
| } |
| return list; |
| } |
| |
| // Iterator that traverses in the range of [min, max], stepping |
| // by distance from a given start position. I.e. for [0, 4], with |
| // start of 2, this will iterate 2, 3, 1, 4, 0. |
| function distanceIterator (start, minLine, maxLine) { |
| var wantForward = true, |
| backwardExhausted = false, |
| forwardExhausted = false, |
| localOffset = 1; |
| return function iterator() { |
| if (wantForward && !forwardExhausted) { |
| if (backwardExhausted) { |
| localOffset++; |
| } else { |
| wantForward = false; |
| } |
| |
| // Check if trying to fit beyond text length, and if not, check it fits |
| // after offset location (or desired location on first iteration) |
| if (start + localOffset <= maxLine) { |
| return start + localOffset; |
| } |
| forwardExhausted = true; |
| } |
| if (!backwardExhausted) { |
| if (!forwardExhausted) { |
| wantForward = true; |
| } |
| |
| // Check if trying to fit before text beginning, and if not, check it fits |
| // before offset location |
| if (minLine <= start - localOffset) { |
| return start - localOffset++; |
| } |
| backwardExhausted = true; |
| return iterator(); |
| } |
| |
| // We tried to fit hunk before text beginning and beyond text length, then |
| // hunk can't fit on the text. Return undefined |
| }; |
| } |
| |
| function applyPatch(source, uniDiff) { |
| var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; |
| if (typeof uniDiff === 'string') { |
| uniDiff = parsePatch(uniDiff); |
| } |
| if (Array.isArray(uniDiff)) { |
| if (uniDiff.length > 1) { |
| throw new Error('applyPatch only works with a single input.'); |
| } |
| uniDiff = uniDiff[0]; |
| } |
| if (options.autoConvertLineEndings || options.autoConvertLineEndings == null) { |
| if (hasOnlyWinLineEndings(source) && isUnix(uniDiff)) { |
| uniDiff = unixToWin(uniDiff); |
| } else if (hasOnlyUnixLineEndings(source) && isWin(uniDiff)) { |
| uniDiff = winToUnix(uniDiff); |
| } |
| } |
| |
| // Apply the diff to the input |
| var lines = source.split('\n'), |
| hunks = uniDiff.hunks, |
| compareLine = options.compareLine || function (lineNumber, line, operation, patchContent) { |
| return line === patchContent; |
| }, |
| fuzzFactor = options.fuzzFactor || 0, |
| minLine = 0; |
| if (fuzzFactor < 0 || !Number.isInteger(fuzzFactor)) { |
| throw new Error('fuzzFactor must be a non-negative integer'); |
| } |
| |
| // Special case for empty patch. |
| if (!hunks.length) { |
| return source; |
| } |
| |
| // Before anything else, handle EOFNL insertion/removal. If the patch tells us to make a change |
| // to the EOFNL that is redundant/impossible - i.e. to remove a newline that's not there, or add a |
| // newline that already exists - then we either return false and fail to apply the patch (if |
| // fuzzFactor is 0) or simply ignore the problem and do nothing (if fuzzFactor is >0). |
| // If we do need to remove/add a newline at EOF, this will always be in the final hunk: |
| var prevLine = '', |
| removeEOFNL = false, |
| addEOFNL = false; |
| for (var i = 0; i < hunks[hunks.length - 1].lines.length; i++) { |
| var line = hunks[hunks.length - 1].lines[i]; |
| if (line[0] == '\\') { |
| if (prevLine[0] == '+') { |
| removeEOFNL = true; |
| } else if (prevLine[0] == '-') { |
| addEOFNL = true; |
| } |
| } |
| prevLine = line; |
| } |
| if (removeEOFNL) { |
| if (addEOFNL) { |
| // This means the final line gets changed but doesn't have a trailing newline in either the |
| // original or patched version. In that case, we do nothing if fuzzFactor > 0, and if |
| // fuzzFactor is 0, we simply validate that the source file has no trailing newline. |
| if (!fuzzFactor && lines[lines.length - 1] == '') { |
| return false; |
| } |
| } else if (lines[lines.length - 1] == '') { |
| lines.pop(); |
| } else if (!fuzzFactor) { |
| return false; |
| } |
| } else if (addEOFNL) { |
| if (lines[lines.length - 1] != '') { |
| lines.push(''); |
| } else if (!fuzzFactor) { |
| return false; |
| } |
| } |
| |
| /** |
| * Checks if the hunk can be made to fit at the provided location with at most `maxErrors` |
| * insertions, substitutions, or deletions, while ensuring also that: |
| * - lines deleted in the hunk match exactly, and |
| * - wherever an insertion operation or block of insertion operations appears in the hunk, the |
| * immediately preceding and following lines of context match exactly |
| * |
| * `toPos` should be set such that lines[toPos] is meant to match hunkLines[0]. |
| * |
| * If the hunk can be applied, returns an object with properties `oldLineLastI` and |
| * `replacementLines`. Otherwise, returns null. |
| */ |
| function applyHunk(hunkLines, toPos, maxErrors) { |
| var hunkLinesI = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; |
| var lastContextLineMatched = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; |
| var patchedLines = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : []; |
| var patchedLinesLength = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : 0; |
| var nConsecutiveOldContextLines = 0; |
| var nextContextLineMustMatch = false; |
| for (; hunkLinesI < hunkLines.length; hunkLinesI++) { |
| var hunkLine = hunkLines[hunkLinesI], |
| operation = hunkLine.length > 0 ? hunkLine[0] : ' ', |
| content = hunkLine.length > 0 ? hunkLine.substr(1) : hunkLine; |
| if (operation === '-') { |
| if (compareLine(toPos + 1, lines[toPos], operation, content)) { |
| toPos++; |
| nConsecutiveOldContextLines = 0; |
| } else { |
| if (!maxErrors || lines[toPos] == null) { |
| return null; |
| } |
| patchedLines[patchedLinesLength] = lines[toPos]; |
| return applyHunk(hunkLines, toPos + 1, maxErrors - 1, hunkLinesI, false, patchedLines, patchedLinesLength + 1); |
| } |
| } |
| if (operation === '+') { |
| if (!lastContextLineMatched) { |
| return null; |
| } |
| patchedLines[patchedLinesLength] = content; |
| patchedLinesLength++; |
| nConsecutiveOldContextLines = 0; |
| nextContextLineMustMatch = true; |
| } |
| if (operation === ' ') { |
| nConsecutiveOldContextLines++; |
| patchedLines[patchedLinesLength] = lines[toPos]; |
| if (compareLine(toPos + 1, lines[toPos], operation, content)) { |
| patchedLinesLength++; |
| lastContextLineMatched = true; |
| nextContextLineMustMatch = false; |
| toPos++; |
| } else { |
| if (nextContextLineMustMatch || !maxErrors) { |
| return null; |
| } |
| |
| // Consider 3 possibilities in sequence: |
| // 1. lines contains a *substitution* not included in the patch context, or |
| // 2. lines contains an *insertion* not included in the patch context, or |
| // 3. lines contains a *deletion* not included in the patch context |
| // The first two options are of course only possible if the line from lines is non-null - |
| // i.e. only option 3 is possible if we've overrun the end of the old file. |
| return lines[toPos] && (applyHunk(hunkLines, toPos + 1, maxErrors - 1, hunkLinesI + 1, false, patchedLines, patchedLinesLength + 1) || applyHunk(hunkLines, toPos + 1, maxErrors - 1, hunkLinesI, false, patchedLines, patchedLinesLength + 1)) || applyHunk(hunkLines, toPos, maxErrors - 1, hunkLinesI + 1, false, patchedLines, patchedLinesLength); |
| } |
| } |
| } |
| |
| // Before returning, trim any unmodified context lines off the end of patchedLines and reduce |
| // toPos (and thus oldLineLastI) accordingly. This allows later hunks to be applied to a region |
| // that starts in this hunk's trailing context. |
| patchedLinesLength -= nConsecutiveOldContextLines; |
| toPos -= nConsecutiveOldContextLines; |
| patchedLines.length = patchedLinesLength; |
| return { |
| patchedLines: patchedLines, |
| oldLineLastI: toPos - 1 |
| }; |
| } |
| var resultLines = []; |
| |
| // Search best fit offsets for each hunk based on the previous ones |
| var prevHunkOffset = 0; |
| for (var _i = 0; _i < hunks.length; _i++) { |
| var hunk = hunks[_i]; |
| var hunkResult = void 0; |
| var maxLine = lines.length - hunk.oldLines + fuzzFactor; |
| var toPos = void 0; |
| for (var maxErrors = 0; maxErrors <= fuzzFactor; maxErrors++) { |
| toPos = hunk.oldStart + prevHunkOffset - 1; |
| var iterator = distanceIterator(toPos, minLine, maxLine); |
| for (; toPos !== undefined; toPos = iterator()) { |
| hunkResult = applyHunk(hunk.lines, toPos, maxErrors); |
| if (hunkResult) { |
| break; |
| } |
| } |
| if (hunkResult) { |
| break; |
| } |
| } |
| if (!hunkResult) { |
| return false; |
| } |
| |
| // Copy everything from the end of where we applied the last hunk to the start of this hunk |
| for (var _i2 = minLine; _i2 < toPos; _i2++) { |
| resultLines.push(lines[_i2]); |
| } |
| |
| // Add the lines produced by applying the hunk: |
| for (var _i3 = 0; _i3 < hunkResult.patchedLines.length; _i3++) { |
| var _line = hunkResult.patchedLines[_i3]; |
| resultLines.push(_line); |
| } |
| |
| // Set lower text limit to end of the current hunk, so next ones don't try |
| // to fit over already patched text |
| minLine = hunkResult.oldLineLastI + 1; |
| |
| // Note the offset between where the patch said the hunk should've applied and where we |
| // applied it, so we can adjust future hunks accordingly: |
| prevHunkOffset = toPos + 1 - hunk.oldStart; |
| } |
| |
| // Copy over the rest of the lines from the old text |
| for (var _i4 = minLine; _i4 < lines.length; _i4++) { |
| resultLines.push(lines[_i4]); |
| } |
| return resultLines.join('\n'); |
| } |
| |
| // Wrapper that supports multiple file patches via callbacks. |
| function applyPatches(uniDiff, options) { |
| if (typeof uniDiff === 'string') { |
| uniDiff = parsePatch(uniDiff); |
| } |
| var currentIndex = 0; |
| function processIndex() { |
| var index = uniDiff[currentIndex++]; |
| if (!index) { |
| return options.complete(); |
| } |
| options.loadFile(index, function (err, data) { |
| if (err) { |
| return options.complete(err); |
| } |
| var updatedContent = applyPatch(data, index, options); |
| options.patched(index, updatedContent, function (err) { |
| if (err) { |
| return options.complete(err); |
| } |
| processIndex(); |
| }); |
| }); |
| } |
| processIndex(); |
| } |
| |
| function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) { |
| if (!options) { |
| options = {}; |
| } |
| if (typeof options === 'function') { |
| options = { |
| callback: options |
| }; |
| } |
| if (typeof options.context === 'undefined') { |
| options.context = 4; |
| } |
| if (options.newlineIsToken) { |
| throw new Error('newlineIsToken may not be used with patch-generation functions, only with diffing functions'); |
| } |
| if (!options.callback) { |
| return diffLinesResultToPatch(diffLines(oldStr, newStr, options)); |
| } else { |
| var _options = options, |
| _callback = _options.callback; |
| diffLines(oldStr, newStr, _objectSpread2(_objectSpread2({}, options), {}, { |
| callback: function callback(diff) { |
| var patch = diffLinesResultToPatch(diff); |
| _callback(patch); |
| } |
| })); |
| } |
| function diffLinesResultToPatch(diff) { |
| // STEP 1: Build up the patch with no "\ No newline at end of file" lines and with the arrays |
| // of lines containing trailing newline characters. We'll tidy up later... |
| |
| if (!diff) { |
| return; |
| } |
| diff.push({ |
| value: '', |
| lines: [] |
| }); // Append an empty value to make cleanup easier |
| |
| function contextLines(lines) { |
| return lines.map(function (entry) { |
| return ' ' + entry; |
| }); |
| } |
| var hunks = []; |
| var oldRangeStart = 0, |
| newRangeStart = 0, |
| curRange = [], |
| oldLine = 1, |
| newLine = 1; |
| var _loop = function _loop() { |
| var current = diff[i], |
| lines = current.lines || splitLines(current.value); |
| current.lines = lines; |
| if (current.added || current.removed) { |
| var _curRange; |
| // If we have previous context, start with that |
| if (!oldRangeStart) { |
| var prev = diff[i - 1]; |
| oldRangeStart = oldLine; |
| newRangeStart = newLine; |
| if (prev) { |
| curRange = options.context > 0 ? contextLines(prev.lines.slice(-options.context)) : []; |
| oldRangeStart -= curRange.length; |
| newRangeStart -= curRange.length; |
| } |
| } |
| |
| // Output our changes |
| (_curRange = curRange).push.apply(_curRange, _toConsumableArray(lines.map(function (entry) { |
| return (current.added ? '+' : '-') + entry; |
| }))); |
| |
| // Track the updated file position |
| if (current.added) { |
| newLine += lines.length; |
| } else { |
| oldLine += lines.length; |
| } |
| } else { |
| // Identical context lines. Track line changes |
| if (oldRangeStart) { |
| // Close out any changes that have been output (or join overlapping) |
| if (lines.length <= options.context * 2 && i < diff.length - 2) { |
| var _curRange2; |
| // Overlapping |
| (_curRange2 = curRange).push.apply(_curRange2, _toConsumableArray(contextLines(lines))); |
| } else { |
| var _curRange3; |
| // end the range and output |
| var contextSize = Math.min(lines.length, options.context); |
| (_curRange3 = curRange).push.apply(_curRange3, _toConsumableArray(contextLines(lines.slice(0, contextSize)))); |
| var _hunk = { |
| oldStart: oldRangeStart, |
| oldLines: oldLine - oldRangeStart + contextSize, |
| newStart: newRangeStart, |
| newLines: newLine - newRangeStart + contextSize, |
| lines: curRange |
| }; |
| hunks.push(_hunk); |
| oldRangeStart = 0; |
| newRangeStart = 0; |
| curRange = []; |
| } |
| } |
| oldLine += lines.length; |
| newLine += lines.length; |
| } |
| }; |
| for (var i = 0; i < diff.length; i++) { |
| _loop(); |
| } |
| |
| // Step 2: eliminate the trailing `\n` from each line of each hunk, and, where needed, add |
| // "\ No newline at end of file". |
| for (var _i = 0, _hunks = hunks; _i < _hunks.length; _i++) { |
| var hunk = _hunks[_i]; |
| for (var _i2 = 0; _i2 < hunk.lines.length; _i2++) { |
| if (hunk.lines[_i2].endsWith('\n')) { |
| hunk.lines[_i2] = hunk.lines[_i2].slice(0, -1); |
| } else { |
| hunk.lines.splice(_i2 + 1, 0, '\\ No newline at end of file'); |
| _i2++; // Skip the line we just added, then continue iterating |
| } |
| } |
| } |
| return { |
| oldFileName: oldFileName, |
| newFileName: newFileName, |
| oldHeader: oldHeader, |
| newHeader: newHeader, |
| hunks: hunks |
| }; |
| } |
| } |
| function formatPatch(diff) { |
| if (Array.isArray(diff)) { |
| return diff.map(formatPatch).join('\n'); |
| } |
| var ret = []; |
| if (diff.oldFileName == diff.newFileName) { |
| ret.push('Index: ' + diff.oldFileName); |
| } |
| ret.push('==================================================================='); |
| ret.push('--- ' + diff.oldFileName + (typeof diff.oldHeader === 'undefined' ? '' : '\t' + diff.oldHeader)); |
| ret.push('+++ ' + diff.newFileName + (typeof diff.newHeader === 'undefined' ? '' : '\t' + diff.newHeader)); |
| for (var i = 0; i < diff.hunks.length; i++) { |
| var hunk = diff.hunks[i]; |
| // Unified Diff Format quirk: If the chunk size is 0, |
| // the first number is one lower than one would expect. |
| // https://www.artima.com/weblogs/viewpost.jsp?thread=164293 |
| if (hunk.oldLines === 0) { |
| hunk.oldStart -= 1; |
| } |
| if (hunk.newLines === 0) { |
| hunk.newStart -= 1; |
| } |
| ret.push('@@ -' + hunk.oldStart + ',' + hunk.oldLines + ' +' + hunk.newStart + ',' + hunk.newLines + ' @@'); |
| ret.push.apply(ret, hunk.lines); |
| } |
| return ret.join('\n') + '\n'; |
| } |
| function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) { |
| var _options2; |
| if (typeof options === 'function') { |
| options = { |
| callback: options |
| }; |
| } |
| if (!((_options2 = options) !== null && _options2 !== void 0 && _options2.callback)) { |
| var patchObj = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options); |
| if (!patchObj) { |
| return; |
| } |
| return formatPatch(patchObj); |
| } else { |
| var _options3 = options, |
| _callback2 = _options3.callback; |
| structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, _objectSpread2(_objectSpread2({}, options), {}, { |
| callback: function callback(patchObj) { |
| if (!patchObj) { |
| _callback2(); |
| } else { |
| _callback2(formatPatch(patchObj)); |
| } |
| } |
| })); |
| } |
| } |
| function createPatch(fileName, oldStr, newStr, oldHeader, newHeader, options) { |
| return createTwoFilesPatch(fileName, fileName, oldStr, newStr, oldHeader, newHeader, options); |
| } |
| |
| /** |
| * Split `text` into an array of lines, including the trailing newline character (where present) |
| */ |
| function splitLines(text) { |
| var hasTrailingNl = text.endsWith('\n'); |
| var result = text.split('\n').map(function (line) { |
| return line + '\n'; |
| }); |
| if (hasTrailingNl) { |
| result.pop(); |
| } else { |
| result.push(result.pop().slice(0, -1)); |
| } |
| return result; |
| } |
| |
| function arrayEqual(a, b) { |
| if (a.length !== b.length) { |
| return false; |
| } |
| return arrayStartsWith(a, b); |
| } |
| function arrayStartsWith(array, start) { |
| if (start.length > array.length) { |
| return false; |
| } |
| for (var i = 0; i < start.length; i++) { |
| if (start[i] !== array[i]) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| function calcLineCount(hunk) { |
| var _calcOldNewLineCount = calcOldNewLineCount(hunk.lines), |
| oldLines = _calcOldNewLineCount.oldLines, |
| newLines = _calcOldNewLineCount.newLines; |
| if (oldLines !== undefined) { |
| hunk.oldLines = oldLines; |
| } else { |
| delete hunk.oldLines; |
| } |
| if (newLines !== undefined) { |
| hunk.newLines = newLines; |
| } else { |
| delete hunk.newLines; |
| } |
| } |
| function merge(mine, theirs, base) { |
| mine = loadPatch(mine, base); |
| theirs = loadPatch(theirs, base); |
| var ret = {}; |
| |
| // For index we just let it pass through as it doesn't have any necessary meaning. |
| // Leaving sanity checks on this to the API consumer that may know more about the |
| // meaning in their own context. |
| if (mine.index || theirs.index) { |
| ret.index = mine.index || theirs.index; |
| } |
| if (mine.newFileName || theirs.newFileName) { |
| if (!fileNameChanged(mine)) { |
| // No header or no change in ours, use theirs (and ours if theirs does not exist) |
| ret.oldFileName = theirs.oldFileName || mine.oldFileName; |
| ret.newFileName = theirs.newFileName || mine.newFileName; |
| ret.oldHeader = theirs.oldHeader || mine.oldHeader; |
| ret.newHeader = theirs.newHeader || mine.newHeader; |
| } else if (!fileNameChanged(theirs)) { |
| // No header or no change in theirs, use ours |
| ret.oldFileName = mine.oldFileName; |
| ret.newFileName = mine.newFileName; |
| ret.oldHeader = mine.oldHeader; |
| ret.newHeader = mine.newHeader; |
| } else { |
| // Both changed... figure it out |
| ret.oldFileName = selectField(ret, mine.oldFileName, theirs.oldFileName); |
| ret.newFileName = selectField(ret, mine.newFileName, theirs.newFileName); |
| ret.oldHeader = selectField(ret, mine.oldHeader, theirs.oldHeader); |
| ret.newHeader = selectField(ret, mine.newHeader, theirs.newHeader); |
| } |
| } |
| ret.hunks = []; |
| var mineIndex = 0, |
| theirsIndex = 0, |
| mineOffset = 0, |
| theirsOffset = 0; |
| while (mineIndex < mine.hunks.length || theirsIndex < theirs.hunks.length) { |
| var mineCurrent = mine.hunks[mineIndex] || { |
| oldStart: Infinity |
| }, |
| theirsCurrent = theirs.hunks[theirsIndex] || { |
| oldStart: Infinity |
| }; |
| if (hunkBefore(mineCurrent, theirsCurrent)) { |
| // This patch does not overlap with any of the others, yay. |
| ret.hunks.push(cloneHunk(mineCurrent, mineOffset)); |
| mineIndex++; |
| theirsOffset += mineCurrent.newLines - mineCurrent.oldLines; |
| } else if (hunkBefore(theirsCurrent, mineCurrent)) { |
| // This patch does not overlap with any of the others, yay. |
| ret.hunks.push(cloneHunk(theirsCurrent, theirsOffset)); |
| theirsIndex++; |
| mineOffset += theirsCurrent.newLines - theirsCurrent.oldLines; |
| } else { |
| // Overlap, merge as best we can |
| var mergedHunk = { |
| oldStart: Math.min(mineCurrent.oldStart, theirsCurrent.oldStart), |
| oldLines: 0, |
| newStart: Math.min(mineCurrent.newStart + mineOffset, theirsCurrent.oldStart + theirsOffset), |
| newLines: 0, |
| lines: [] |
| }; |
| mergeLines(mergedHunk, mineCurrent.oldStart, mineCurrent.lines, theirsCurrent.oldStart, theirsCurrent.lines); |
| theirsIndex++; |
| mineIndex++; |
| ret.hunks.push(mergedHunk); |
| } |
| } |
| return ret; |
| } |
| function loadPatch(param, base) { |
| if (typeof param === 'string') { |
| if (/^@@/m.test(param) || /^Index:/m.test(param)) { |
| return parsePatch(param)[0]; |
| } |
| if (!base) { |
| throw new Error('Must provide a base reference or pass in a patch'); |
| } |
| return structuredPatch(undefined, undefined, base, param); |
| } |
| return param; |
| } |
| function fileNameChanged(patch) { |
| return patch.newFileName && patch.newFileName !== patch.oldFileName; |
| } |
| function selectField(index, mine, theirs) { |
| if (mine === theirs) { |
| return mine; |
| } else { |
| index.conflict = true; |
| return { |
| mine: mine, |
| theirs: theirs |
| }; |
| } |
| } |
| function hunkBefore(test, check) { |
| return test.oldStart < check.oldStart && test.oldStart + test.oldLines < check.oldStart; |
| } |
| function cloneHunk(hunk, offset) { |
| return { |
| oldStart: hunk.oldStart, |
| oldLines: hunk.oldLines, |
| newStart: hunk.newStart + offset, |
| newLines: hunk.newLines, |
| lines: hunk.lines |
| }; |
| } |
| function mergeLines(hunk, mineOffset, mineLines, theirOffset, theirLines) { |
| // This will generally result in a conflicted hunk, but there are cases where the context |
| // is the only overlap where we can successfully merge the content here. |
| var mine = { |
| offset: mineOffset, |
| lines: mineLines, |
| index: 0 |
| }, |
| their = { |
| offset: theirOffset, |
| lines: theirLines, |
| index: 0 |
| }; |
| |
| // Handle any leading content |
| insertLeading(hunk, mine, their); |
| insertLeading(hunk, their, mine); |
| |
| // Now in the overlap content. Scan through and select the best changes from each. |
| while (mine.index < mine.lines.length && their.index < their.lines.length) { |
| var mineCurrent = mine.lines[mine.index], |
| theirCurrent = their.lines[their.index]; |
| if ((mineCurrent[0] === '-' || mineCurrent[0] === '+') && (theirCurrent[0] === '-' || theirCurrent[0] === '+')) { |
| // Both modified ... |
| mutualChange(hunk, mine, their); |
| } else if (mineCurrent[0] === '+' && theirCurrent[0] === ' ') { |
| var _hunk$lines; |
| // Mine inserted |
| (_hunk$lines = hunk.lines).push.apply(_hunk$lines, _toConsumableArray(collectChange(mine))); |
| } else if (theirCurrent[0] === '+' && mineCurrent[0] === ' ') { |
| var _hunk$lines2; |
| // Theirs inserted |
| (_hunk$lines2 = hunk.lines).push.apply(_hunk$lines2, _toConsumableArray(collectChange(their))); |
| } else if (mineCurrent[0] === '-' && theirCurrent[0] === ' ') { |
| // Mine removed or edited |
| removal(hunk, mine, their); |
| } else if (theirCurrent[0] === '-' && mineCurrent[0] === ' ') { |
| // Their removed or edited |
| removal(hunk, their, mine, true); |
| } else if (mineCurrent === theirCurrent) { |
| // Context identity |
| hunk.lines.push(mineCurrent); |
| mine.index++; |
| their.index++; |
| } else { |
| // Context mismatch |
| conflict(hunk, collectChange(mine), collectChange(their)); |
| } |
| } |
| |
| // Now push anything that may be remaining |
| insertTrailing(hunk, mine); |
| insertTrailing(hunk, their); |
| calcLineCount(hunk); |
| } |
| function mutualChange(hunk, mine, their) { |
| var myChanges = collectChange(mine), |
| theirChanges = collectChange(their); |
| if (allRemoves(myChanges) && allRemoves(theirChanges)) { |
| // Special case for remove changes that are supersets of one another |
| if (arrayStartsWith(myChanges, theirChanges) && skipRemoveSuperset(their, myChanges, myChanges.length - theirChanges.length)) { |
| var _hunk$lines3; |
| (_hunk$lines3 = hunk.lines).push.apply(_hunk$lines3, _toConsumableArray(myChanges)); |
| return; |
| } else if (arrayStartsWith(theirChanges, myChanges) && skipRemoveSuperset(mine, theirChanges, theirChanges.length - myChanges.length)) { |
| var _hunk$lines4; |
| (_hunk$lines4 = hunk.lines).push.apply(_hunk$lines4, _toConsumableArray(theirChanges)); |
| return; |
| } |
| } else if (arrayEqual(myChanges, theirChanges)) { |
| var _hunk$lines5; |
| (_hunk$lines5 = hunk.lines).push.apply(_hunk$lines5, _toConsumableArray(myChanges)); |
| return; |
| } |
| conflict(hunk, myChanges, theirChanges); |
| } |
| function removal(hunk, mine, their, swap) { |
| var myChanges = collectChange(mine), |
| theirChanges = collectContext(their, myChanges); |
| if (theirChanges.merged) { |
| var _hunk$lines6; |
| (_hunk$lines6 = hunk.lines).push.apply(_hunk$lines6, _toConsumableArray(theirChanges.merged)); |
| } else { |
| conflict(hunk, swap ? theirChanges : myChanges, swap ? myChanges : theirChanges); |
| } |
| } |
| function conflict(hunk, mine, their) { |
| hunk.conflict = true; |
| hunk.lines.push({ |
| conflict: true, |
| mine: mine, |
| theirs: their |
| }); |
| } |
| function insertLeading(hunk, insert, their) { |
| while (insert.offset < their.offset && insert.index < insert.lines.length) { |
| var line = insert.lines[insert.index++]; |
| hunk.lines.push(line); |
| insert.offset++; |
| } |
| } |
| function insertTrailing(hunk, insert) { |
| while (insert.index < insert.lines.length) { |
| var line = insert.lines[insert.index++]; |
| hunk.lines.push(line); |
| } |
| } |
| function collectChange(state) { |
| var ret = [], |
| operation = state.lines[state.index][0]; |
| while (state.index < state.lines.length) { |
| var line = state.lines[state.index]; |
| |
| // Group additions that are immediately after subtractions and treat them as one "atomic" modify change. |
| if (operation === '-' && line[0] === '+') { |
| operation = '+'; |
| } |
| if (operation === line[0]) { |
| ret.push(line); |
| state.index++; |
| } else { |
| break; |
| } |
| } |
| return ret; |
| } |
| function collectContext(state, matchChanges) { |
| var changes = [], |
| merged = [], |
| matchIndex = 0, |
| contextChanges = false, |
| conflicted = false; |
| while (matchIndex < matchChanges.length && state.index < state.lines.length) { |
| var change = state.lines[state.index], |
| match = matchChanges[matchIndex]; |
| |
| // Once we've hit our add, then we are done |
| if (match[0] === '+') { |
| break; |
| } |
| contextChanges = contextChanges || change[0] !== ' '; |
| merged.push(match); |
| matchIndex++; |
| |
| // Consume any additions in the other block as a conflict to attempt |
| // to pull in the remaining context after this |
| if (change[0] === '+') { |
| conflicted = true; |
| while (change[0] === '+') { |
| changes.push(change); |
| change = state.lines[++state.index]; |
| } |
| } |
| if (match.substr(1) === change.substr(1)) { |
| changes.push(change); |
| state.index++; |
| } else { |
| conflicted = true; |
| } |
| } |
| if ((matchChanges[matchIndex] || '')[0] === '+' && contextChanges) { |
| conflicted = true; |
| } |
| if (conflicted) { |
| return changes; |
| } |
| while (matchIndex < matchChanges.length) { |
| merged.push(matchChanges[matchIndex++]); |
| } |
| return { |
| merged: merged, |
| changes: changes |
| }; |
| } |
| function allRemoves(changes) { |
| return changes.reduce(function (prev, change) { |
| return prev && change[0] === '-'; |
| }, true); |
| } |
| function skipRemoveSuperset(state, removeChanges, delta) { |
| for (var i = 0; i < delta; i++) { |
| var changeContent = removeChanges[removeChanges.length - delta + i].substr(1); |
| if (state.lines[state.index + i] !== ' ' + changeContent) { |
| return false; |
| } |
| } |
| state.index += delta; |
| return true; |
| } |
| function calcOldNewLineCount(lines) { |
| var oldLines = 0; |
| var newLines = 0; |
| lines.forEach(function (line) { |
| if (typeof line !== 'string') { |
| var myCount = calcOldNewLineCount(line.mine); |
| var theirCount = calcOldNewLineCount(line.theirs); |
| if (oldLines !== undefined) { |
| if (myCount.oldLines === theirCount.oldLines) { |
| oldLines += myCount.oldLines; |
| } else { |
| oldLines = undefined; |
| } |
| } |
| if (newLines !== undefined) { |
| if (myCount.newLines === theirCount.newLines) { |
| newLines += myCount.newLines; |
| } else { |
| newLines = undefined; |
| } |
| } |
| } else { |
| if (newLines !== undefined && (line[0] === '+' || line[0] === ' ')) { |
| newLines++; |
| } |
| if (oldLines !== undefined && (line[0] === '-' || line[0] === ' ')) { |
| oldLines++; |
| } |
| } |
| }); |
| return { |
| oldLines: oldLines, |
| newLines: newLines |
| }; |
| } |
| |
| function reversePatch(structuredPatch) { |
| if (Array.isArray(structuredPatch)) { |
| return structuredPatch.map(reversePatch).reverse(); |
| } |
| return _objectSpread2(_objectSpread2({}, structuredPatch), {}, { |
| oldFileName: structuredPatch.newFileName, |
| oldHeader: structuredPatch.newHeader, |
| newFileName: structuredPatch.oldFileName, |
| newHeader: structuredPatch.oldHeader, |
| hunks: structuredPatch.hunks.map(function (hunk) { |
| return { |
| oldLines: hunk.newLines, |
| oldStart: hunk.newStart, |
| newLines: hunk.oldLines, |
| newStart: hunk.oldStart, |
| lines: hunk.lines.map(function (l) { |
| if (l.startsWith('-')) { |
| return "+".concat(l.slice(1)); |
| } |
| if (l.startsWith('+')) { |
| return "-".concat(l.slice(1)); |
| } |
| return l; |
| }) |
| }; |
| }) |
| }); |
| } |
| |
| // See: http://code.google.com/p/google-diff-match-patch/wiki/API |
| function convertChangesToDMP(changes) { |
| var ret = [], |
| change, |
| operation; |
| for (var i = 0; i < changes.length; i++) { |
| change = changes[i]; |
| if (change.added) { |
| operation = 1; |
| } else if (change.removed) { |
| operation = -1; |
| } else { |
| operation = 0; |
| } |
| ret.push([operation, change.value]); |
| } |
| return ret; |
| } |
| |
| function convertChangesToXML(changes) { |
| var ret = []; |
| for (var i = 0; i < changes.length; i++) { |
| var change = changes[i]; |
| if (change.added) { |
| ret.push('<ins>'); |
| } else if (change.removed) { |
| ret.push('<del>'); |
| } |
| ret.push(escapeHTML(change.value)); |
| if (change.added) { |
| ret.push('</ins>'); |
| } else if (change.removed) { |
| ret.push('</del>'); |
| } |
| } |
| return ret.join(''); |
| } |
| function escapeHTML(s) { |
| var n = s; |
| n = n.replace(/&/g, '&'); |
| n = n.replace(/</g, '<'); |
| n = n.replace(/>/g, '>'); |
| n = n.replace(/"/g, '"'); |
| return n; |
| } |
| |
| exports.Diff = Diff; |
| exports.applyPatch = applyPatch; |
| exports.applyPatches = applyPatches; |
| exports.canonicalize = canonicalize; |
| exports.convertChangesToDMP = convertChangesToDMP; |
| exports.convertChangesToXML = convertChangesToXML; |
| exports.createPatch = createPatch; |
| exports.createTwoFilesPatch = createTwoFilesPatch; |
| exports.diffArrays = diffArrays; |
| exports.diffChars = diffChars; |
| exports.diffCss = diffCss; |
| exports.diffJson = diffJson; |
| exports.diffLines = diffLines; |
| exports.diffSentences = diffSentences; |
| exports.diffTrimmedLines = diffTrimmedLines; |
| exports.diffWords = diffWords; |
| exports.diffWordsWithSpace = diffWordsWithSpace; |
| exports.formatPatch = formatPatch; |
| exports.merge = merge; |
| exports.parsePatch = parsePatch; |
| exports.reversePatch = reversePatch; |
| exports.structuredPatch = structuredPatch; |
| |
| })); |
| |
| },{}],92:[function(require,module,exports){ |
| /** |
| * lodash (Custom Build) <https://lodash.com/> |
| * Build: `lodash modularize exports="npm" -o ./` |
| * Copyright jQuery Foundation and other contributors <https://jquery.org/> |
| * Released under MIT license <https://lodash.com/license> |
| * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE> |
| * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors |
| */ |
| |
| /** Used as the `TypeError` message for "Functions" methods. */ |
| var FUNC_ERROR_TEXT = 'Expected a function'; |
| |
| /** Used to stand-in for `undefined` hash values. */ |
| var HASH_UNDEFINED = '__lodash_hash_undefined__'; |
| |
| /** Used as references for various `Number` constants. */ |
| var INFINITY = 1 / 0; |
| |
| /** `Object#toString` result references. */ |
| var funcTag = '[object Function]', |
| genTag = '[object GeneratorFunction]', |
| symbolTag = '[object Symbol]'; |
| |
| /** Used to match property names within property paths. */ |
| var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, |
| reIsPlainProp = /^\w*$/, |
| reLeadingDot = /^\./, |
| rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; |
| |
| /** |
| * Used to match `RegExp` |
| * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). |
| */ |
| var reRegExpChar = /[\\^$.*+?()[\]{}|]/g; |
| |
| /** Used to match backslashes in property paths. */ |
| var reEscapeChar = /\\(\\)?/g; |
| |
| /** Used to detect host constructors (Safari). */ |
| var reIsHostCtor = /^\[object .+?Constructor\]$/; |
| |
| /** Detect free variable `global` from Node.js. */ |
| var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; |
| |
| /** Detect free variable `self`. */ |
| var freeSelf = typeof self == 'object' && self && self.Object === Object && self; |
| |
| /** Used as a reference to the global object. */ |
| var root = freeGlobal || freeSelf || Function('return this')(); |
| |
| /** |
| * Gets the value at `key` of `object`. |
| * |
| * @private |
| * @param {Object} [object] The object to query. |
| * @param {string} key The key of the property to get. |
| * @returns {*} Returns the property value. |
| */ |
| function getValue(object, key) { |
| return object == null ? undefined : object[key]; |
| } |
| |
| /** |
| * Checks if `value` is a host object in IE < 9. |
| * |
| * @private |
| * @param {*} value The value to check. |
| * @returns {boolean} Returns `true` if `value` is a host object, else `false`. |
| */ |
| function isHostObject(value) { |
| // Many host objects are `Object` objects that can coerce to strings |
| // despite having improperly defined `toString` methods. |
| var result = false; |
| if (value != null && typeof value.toString != 'function') { |
| try { |
| result = !!(value + ''); |
| } catch (e) {} |
| } |
| return result; |
| } |
| |
| /** Used for built-in method references. */ |
| var arrayProto = Array.prototype, |
| funcProto = Function.prototype, |
| objectProto = Object.prototype; |
| |
| /** Used to detect overreaching core-js shims. */ |
| var coreJsData = root['__core-js_shared__']; |
| |
| /** Used to detect methods masquerading as native. */ |
| var maskSrcKey = (function() { |
| var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); |
| return uid ? ('Symbol(src)_1.' + uid) : ''; |
| }()); |
| |
| /** Used to resolve the decompiled source of functions. */ |
| var funcToString = funcProto.toString; |
| |
| /** Used to check objects for own properties. */ |
| var hasOwnProperty = objectProto.hasOwnProperty; |
| |
| /** |
| * Used to resolve the |
| * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) |
| * of values. |
| */ |
| var objectToString = objectProto.toString; |
| |
| /** Used to detect if a method is native. */ |
| var reIsNative = RegExp('^' + |
| funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') |
| .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' |
| ); |
| |
| /** Built-in value references. */ |
| var Symbol = root.Symbol, |
| splice = arrayProto.splice; |
| |
| /* Built-in method references that are verified to be native. */ |
| var Map = getNative(root, 'Map'), |
| nativeCreate = getNative(Object, 'create'); |
| |
| /** Used to convert symbols to primitives and strings. */ |
| var symbolProto = Symbol ? Symbol.prototype : undefined, |
| symbolToString = symbolProto ? symbolProto.toString : undefined; |
| |
| /** |
| * Creates a hash object. |
| * |
| * @private |
| * @constructor |
| * @param {Array} [entries] The key-value pairs to cache. |
| */ |
| function Hash(entries) { |
| var index = -1, |
| length = entries ? entries.length : 0; |
| |
| this.clear(); |
| while (++index < length) { |
| var entry = entries[index]; |
| this.set(entry[0], entry[1]); |
| } |
| } |
| |
| /** |
| * Removes all key-value entries from the hash. |
| * |
| * @private |
| * @name clear |
| * @memberOf Hash |
| */ |
| function hashClear() { |
| this.__data__ = nativeCreate ? nativeCreate(null) : {}; |
| } |
| |
| /** |
| * Removes `key` and its value from the hash. |
| * |
| * @private |
| * @name delete |
| * @memberOf Hash |
| * @param {Object} hash The hash to modify. |
| * @param {string} key The key of the value to remove. |
| * @returns {boolean} Returns `true` if the entry was removed, else `false`. |
| */ |
| function hashDelete(key) { |
| return this.has(key) && delete this.__data__[key]; |
| } |
| |
| /** |
| * Gets the hash value for `key`. |
| * |
| * @private |
| * @name get |
| * @memberOf Hash |
| * @param {string} key The key of the value to get. |
| * @returns {*} Returns the entry value. |
| */ |
| function hashGet(key) { |
| var data = this.__data__; |
| if (nativeCreate) { |
| var result = data[key]; |
| return result === HASH_UNDEFINED ? undefined : result; |
| } |
| return hasOwnProperty.call(data, key) ? data[key] : undefined; |
| } |
| |
| /** |
| * Checks if a hash value for `key` exists. |
| * |
| * @private |
| * @name has |
| * @memberOf Hash |
| * @param {string} key The key of the entry to check. |
| * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. |
| */ |
| function hashHas(key) { |
| var data = this.__data__; |
| return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key); |
| } |
| |
| /** |
| * Sets the hash `key` to `value`. |
| * |
| * @private |
| * @name set |
| * @memberOf Hash |
| * @param {string} key The key of the value to set. |
| * @param {*} value The value to set. |
| * @returns {Object} Returns the hash instance. |
| */ |
| function hashSet(key, value) { |
| var data = this.__data__; |
| data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; |
| return this; |
| } |
| |
| // Add methods to `Hash`. |
| Hash.prototype.clear = hashClear; |
| Hash.prototype['delete'] = hashDelete; |
| Hash.prototype.get = hashGet; |
| Hash.prototype.has = hashHas; |
| Hash.prototype.set = hashSet; |
| |
| /** |
| * Creates an list cache object. |
| * |
| * @private |
| * @constructor |
| * @param {Array} [entries] The key-value pairs to cache. |
| */ |
| function ListCache(entries) { |
| var index = -1, |
| length = entries ? entries.length : 0; |
| |
| this.clear(); |
| while (++index < length) { |
| var entry = entries[index]; |
| this.set(entry[0], entry[1]); |
| } |
| } |
| |
| /** |
| * Removes all key-value entries from the list cache. |
| * |
| * @private |
| * @name clear |
| * @memberOf ListCache |
| */ |
| function listCacheClear() { |
| this.__data__ = []; |
| } |
| |
| /** |
| * Removes `key` and its value from the list cache. |
| * |
| * @private |
| * @name delete |
| * @memberOf ListCache |
| * @param {string} key The key of the value to remove. |
| * @returns {boolean} Returns `true` if the entry was removed, else `false`. |
| */ |
| function listCacheDelete(key) { |
| var data = this.__data__, |
| index = assocIndexOf(data, key); |
| |
| if (index < 0) { |
| return false; |
| } |
| var lastIndex = data.length - 1; |
| if (index == lastIndex) { |
| data.pop(); |
| } else { |
| splice.call(data, index, 1); |
| } |
| return true; |
| } |
| |
| /** |
| * Gets the list cache value for `key`. |
| * |
| * @private |
| * @name get |
| * @memberOf ListCache |
| * @param {string} key The key of the value to get. |
| * @returns {*} Returns the entry value. |
| */ |
| function listCacheGet(key) { |
| var data = this.__data__, |
| index = assocIndexOf(data, key); |
| |
| return index < 0 ? undefined : data[index][1]; |
| } |
| |
| /** |
| * Checks if a list cache value for `key` exists. |
| * |
| * @private |
| * @name has |
| * @memberOf ListCache |
| * @param {string} key The key of the entry to check. |
| * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. |
| */ |
| function listCacheHas(key) { |
| return assocIndexOf(this.__data__, key) > -1; |
| } |
| |
| /** |
| * Sets the list cache `key` to `value`. |
| * |
| * @private |
| * @name set |
| * @memberOf ListCache |
| * @param {string} key The key of the value to set. |
| * @param {*} value The value to set. |
| * @returns {Object} Returns the list cache instance. |
| */ |
| function listCacheSet(key, value) { |
| var data = this.__data__, |
| index = assocIndexOf(data, key); |
| |
| if (index < 0) { |
| data.push([key, value]); |
| } else { |
| data[index][1] = value; |
| } |
| return this; |
| } |
| |
| // Add methods to `ListCache`. |
| ListCache.prototype.clear = listCacheClear; |
| ListCache.prototype['delete'] = listCacheDelete; |
| ListCache.prototype.get = listCacheGet; |
| ListCache.prototype.has = listCacheHas; |
| ListCache.prototype.set = listCacheSet; |
| |
| /** |
| * Creates a map cache object to store key-value pairs. |
| * |
| * @private |
| * @constructor |
| * @param {Array} [entries] The key-value pairs to cache. |
| */ |
| function MapCache(entries) { |
| var index = -1, |
| length = entries ? entries.length : 0; |
| |
| this.clear(); |
| while (++index < length) { |
| var entry = entries[index]; |
| this.set(entry[0], entry[1]); |
| } |
| } |
| |
| /** |
| * Removes all key-value entries from the map. |
| * |
| * @private |
| * @name clear |
| * @memberOf MapCache |
| */ |
| function mapCacheClear() { |
| this.__data__ = { |
| 'hash': new Hash, |
| 'map': new (Map || ListCache), |
| 'string': new Hash |
| }; |
| } |
| |
| /** |
| * Removes `key` and its value from the map. |
| * |
| * @private |
| * @name delete |
| * @memberOf MapCache |
| * @param {string} key The key of the value to remove. |
| * @returns {boolean} Returns `true` if the entry was removed, else `false`. |
| */ |
| function mapCacheDelete(key) { |
| return getMapData(this, key)['delete'](key); |
| } |
| |
| /** |
| * Gets the map value for `key`. |
| * |
| * @private |
| * @name get |
| * @memberOf MapCache |
| * @param {string} key The key of the value to get. |
| * @returns {*} Returns the entry value. |
| */ |
| function mapCacheGet(key) { |
| return getMapData(this, key).get(key); |
| } |
| |
| /** |
| * Checks if a map value for `key` exists. |
| * |
| * @private |
| * @name has |
| * @memberOf MapCache |
| * @param {string} key The key of the entry to check. |
| * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. |
| */ |
| function mapCacheHas(key) { |
| return getMapData(this, key).has(key); |
| } |
| |
| /** |
| * Sets the map `key` to `value`. |
| * |
| * @private |
| * @name set |
| * @memberOf MapCache |
| * @param {string} key The key of the value to set. |
| * @param {*} value The value to set. |
| * @returns {Object} Returns the map cache instance. |
| */ |
| function mapCacheSet(key, value) { |
| getMapData(this, key).set(key, value); |
| return this; |
| } |
| |
| // Add methods to `MapCache`. |
| MapCache.prototype.clear = mapCacheClear; |
| MapCache.prototype['delete'] = mapCacheDelete; |
| MapCache.prototype.get = mapCacheGet; |
| MapCache.prototype.has = mapCacheHas; |
| MapCache.prototype.set = mapCacheSet; |
| |
| /** |
| * Gets the index at which the `key` is found in `array` of key-value pairs. |
| * |
| * @private |
| * @param {Array} array The array to inspect. |
| * @param {*} key The key to search for. |
| * @returns {number} Returns the index of the matched value, else `-1`. |
| */ |
| function assocIndexOf(array, key) { |
| var length = array.length; |
| while (length--) { |
| if (eq(array[length][0], key)) { |
| return length; |
| } |
| } |
| return -1; |
| } |
| |
| /** |
| * The base implementation of `_.get` without support for default values. |
| * |
| * @private |
| * @param {Object} object The object to query. |
| * @param {Array|string} path The path of the property to get. |
| * @returns {*} Returns the resolved value. |
| */ |
| function baseGet(object, path) { |
| path = isKey(path, object) ? [path] : castPath(path); |
| |
| var index = 0, |
| length = path.length; |
| |
| while (object != null && index < length) { |
| object = object[toKey(path[index++])]; |
| } |
| return (index && index == length) ? object : undefined; |
| } |
| |
| /** |
| * The base implementation of `_.isNative` without bad shim checks. |
| * |
| * @private |
| * @param {*} value The value to check. |
| * @returns {boolean} Returns `true` if `value` is a native function, |
| * else `false`. |
| */ |
| function baseIsNative(value) { |
| if (!isObject(value) || isMasked(value)) { |
| return false; |
| } |
| var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor; |
| return pattern.test(toSource(value)); |
| } |
| |
| /** |
| * The base implementation of `_.toString` which doesn't convert nullish |
| * values to empty strings. |
| * |
| * @private |
| * @param {*} value The value to process. |
| * @returns {string} Returns the string. |
| */ |
| function baseToString(value) { |
| // Exit early for strings to avoid a performance hit in some environments. |
| if (typeof value == 'string') { |
| return value; |
| } |
| if (isSymbol(value)) { |
| return symbolToString ? symbolToString.call(value) : ''; |
| } |
| var result = (value + ''); |
| return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; |
| } |
| |
| /** |
| * Casts `value` to a path array if it's not one. |
| * |
| * @private |
| * @param {*} value The value to inspect. |
| * @returns {Array} Returns the cast property path array. |
| */ |
| function castPath(value) { |
| return isArray(value) ? value : stringToPath(value); |
| } |
| |
| /** |
| * Gets the data for `map`. |
| * |
| * @private |
| * @param {Object} map The map to query. |
| * @param {string} key The reference key. |
| * @returns {*} Returns the map data. |
| */ |
| function getMapData(map, key) { |
| var data = map.__data__; |
| return isKeyable(key) |
| ? data[typeof key == 'string' ? 'string' : 'hash'] |
| : data.map; |
| } |
| |
| /** |
| * Gets the native function at `key` of `object`. |
| * |
| * @private |
| * @param {Object} object The object to query. |
| * @param {string} key The key of the method to get. |
| * @returns {*} Returns the function if it's native, else `undefined`. |
| */ |
| function getNative(object, key) { |
| var value = getValue(object, key); |
| return baseIsNative(value) ? value : undefined; |
| } |
| |
| /** |
| * Checks if `value` is a property name and not a property path. |
| * |
| * @private |
| * @param {*} value The value to check. |
| * @param {Object} [object] The object to query keys on. |
| * @returns {boolean} Returns `true` if `value` is a property name, else `false`. |
| */ |
| function isKey(value, object) { |
| if (isArray(value)) { |
| return false; |
| } |
| var type = typeof value; |
| if (type == 'number' || type == 'symbol' || type == 'boolean' || |
| value == null || isSymbol(value)) { |
| return true; |
| } |
| return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || |
| (object != null && value in Object(object)); |
| } |
| |
| /** |
| * Checks if `value` is suitable for use as unique object key. |
| * |
| * @private |
| * @param {*} value The value to check. |
| * @returns {boolean} Returns `true` if `value` is suitable, else `false`. |
| */ |
| function isKeyable(value) { |
| var type = typeof value; |
| return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') |
| ? (value !== '__proto__') |
| : (value === null); |
| } |
| |
| /** |
| * Checks if `func` has its source masked. |
| * |
| * @private |
| * @param {Function} func The function to check. |
| * @returns {boolean} Returns `true` if `func` is masked, else `false`. |
| */ |
| function isMasked(func) { |
| return !!maskSrcKey && (maskSrcKey in func); |
| } |
| |
| /** |
| * Converts `string` to a property path array. |
| * |
| * @private |
| * @param {string} string The string to convert. |
| * @returns {Array} Returns the property path array. |
| */ |
| var stringToPath = memoize(function(string) { |
| string = toString(string); |
| |
| var result = []; |
| if (reLeadingDot.test(string)) { |
| result.push(''); |
| } |
| string.replace(rePropName, function(match, number, quote, string) { |
| result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match)); |
| }); |
| return result; |
| }); |
| |
| /** |
| * Converts `value` to a string key if it's not a string or symbol. |
| * |
| * @private |
| * @param {*} value The value to inspect. |
| * @returns {string|symbol} Returns the key. |
| */ |
| function toKey(value) { |
| if (typeof value == 'string' || isSymbol(value)) { |
| return value; |
| } |
| var result = (value + ''); |
| return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; |
| } |
| |
| /** |
| * Converts `func` to its source code. |
| * |
| * @private |
| * @param {Function} func The function to process. |
| * @returns {string} Returns the source code. |
| */ |
| function toSource(func) { |
| if (func != null) { |
| try { |
| return funcToString.call(func); |
| } catch (e) {} |
| try { |
| return (func + ''); |
| } catch (e) {} |
| } |
| return ''; |
| } |
| |
| /** |
| * Creates a function that memoizes the result of `func`. If `resolver` is |
| * provided, it determines the cache key for storing the result based on the |
| * arguments provided to the memoized function. By default, the first argument |
| * provided to the memoized function is used as the map cache key. The `func` |
| * is invoked with the `this` binding of the memoized function. |
| * |
| * **Note:** The cache is exposed as the `cache` property on the memoized |
| * function. Its creation may be customized by replacing the `_.memoize.Cache` |
| * constructor with one whose instances implement the |
| * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) |
| * method interface of `delete`, `get`, `has`, and `set`. |
| * |
| * @static |
| * @memberOf _ |
| * @since 0.1.0 |
| * @category Function |
| * @param {Function} func The function to have its output memoized. |
| * @param {Function} [resolver] The function to resolve the cache key. |
| * @returns {Function} Returns the new memoized function. |
| * @example |
| * |
| * var object = { 'a': 1, 'b': 2 }; |
| * var other = { 'c': 3, 'd': 4 }; |
| * |
| * var values = _.memoize(_.values); |
| * values(object); |
| * // => [1, 2] |
| * |
| * values(other); |
| * // => [3, 4] |
| * |
| * object.a = 2; |
| * values(object); |
| * // => [1, 2] |
| * |
| * // Modify the result cache. |
| * values.cache.set(object, ['a', 'b']); |
| * values(object); |
| * // => ['a', 'b'] |
| * |
| * // Replace `_.memoize.Cache`. |
| * _.memoize.Cache = WeakMap; |
| */ |
| function memoize(func, resolver) { |
| if (typeof func != 'function' || (resolver && typeof resolver != 'function')) { |
| throw new TypeError(FUNC_ERROR_TEXT); |
| } |
| var memoized = function() { |
| var args = arguments, |
| key = resolver ? resolver.apply(this, args) : args[0], |
| cache = memoized.cache; |
| |
| if (cache.has(key)) { |
| return cache.get(key); |
| } |
| var result = func.apply(this, args); |
| memoized.cache = cache.set(key, result); |
| return result; |
| }; |
| memoized.cache = new (memoize.Cache || MapCache); |
| return memoized; |
| } |
| |
| // Assign cache to `_.memoize`. |
| memoize.Cache = MapCache; |
| |
| /** |
| * Performs a |
| * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) |
| * comparison between two values to determine if they are equivalent. |
| * |
| * @static |
| * @memberOf _ |
| * @since 4.0.0 |
| * @category Lang |
| * @param {*} value The value to compare. |
| * @param {*} other The other value to compare. |
| * @returns {boolean} Returns `true` if the values are equivalent, else `false`. |
| * @example |
| * |
| * var object = { 'a': 1 }; |
| * var other = { 'a': 1 }; |
| * |
| * _.eq(object, object); |
| * // => true |
| * |
| * _.eq(object, other); |
| * // => false |
| * |
| * _.eq('a', 'a'); |
| * // => true |
| * |
| * _.eq('a', Object('a')); |
| * // => false |
| * |
| * _.eq(NaN, NaN); |
| * // => true |
| */ |
| function eq(value, other) { |
| return value === other || (value !== value && other !== other); |
| } |
| |
| /** |
| * Checks if `value` is classified as an `Array` object. |
| * |
| * @static |
| * @memberOf _ |
| * @since 0.1.0 |
| * @category Lang |
| * @param {*} value The value to check. |
| * @returns {boolean} Returns `true` if `value` is an array, else `false`. |
| * @example |
| * |
| * _.isArray([1, 2, 3]); |
| * // => true |
| * |
| * _.isArray(document.body.children); |
| * // => false |
| * |
| * _.isArray('abc'); |
| * // => false |
| * |
| * _.isArray(_.noop); |
| * // => false |
| */ |
| var isArray = Array.isArray; |
| |
| /** |
| * Checks if `value` is classified as a `Function` object. |
| * |
| * @static |
| * @memberOf _ |
| * @since 0.1.0 |
| * @category Lang |
| * @param {*} value The value to check. |
| * @returns {boolean} Returns `true` if `value` is a function, else `false`. |
| * @example |
| * |
| * _.isFunction(_); |
| * // => true |
| * |
| * _.isFunction(/abc/); |
| * // => false |
| */ |
| function isFunction(value) { |
| // The use of `Object#toString` avoids issues with the `typeof` operator |
| // in Safari 8-9 which returns 'object' for typed array and other constructors. |
| var tag = isObject(value) ? objectToString.call(value) : ''; |
| return tag == funcTag || tag == genTag; |
| } |
| |
| /** |
| * Checks if `value` is the |
| * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) |
| * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) |
| * |
| * @static |
| * @memberOf _ |
| * @since 0.1.0 |
| * @category Lang |
| * @param {*} value The value to check. |
| * @returns {boolean} Returns `true` if `value` is an object, else `false`. |
| * @example |
| * |
| * _.isObject({}); |
| * // => true |
| * |
| * _.isObject([1, 2, 3]); |
| * // => true |
| * |
| * _.isObject(_.noop); |
| * // => true |
| * |
| * _.isObject(null); |
| * // => false |
| */ |
| function isObject(value) { |
| var type = typeof value; |
| return !!value && (type == 'object' || type == 'function'); |
| } |
| |
| /** |
| * Checks if `value` is object-like. A value is object-like if it's not `null` |
| * and has a `typeof` result of "object". |
| * |
| * @static |
| * @memberOf _ |
| * @since 4.0.0 |
| * @category Lang |
| * @param {*} value The value to check. |
| * @returns {boolean} Returns `true` if `value` is object-like, else `false`. |
| * @example |
| * |
| * _.isObjectLike({}); |
| * // => true |
| * |
| * _.isObjectLike([1, 2, 3]); |
| * // => true |
| * |
| * _.isObjectLike(_.noop); |
| * // => false |
| * |
| * _.isObjectLike(null); |
| * // => false |
| */ |
| function isObjectLike(value) { |
| return !!value && typeof value == 'object'; |
| } |
| |
| /** |
| * Checks if `value` is classified as a `Symbol` primitive or object. |
| * |
| * @static |
| * @memberOf _ |
| * @since 4.0.0 |
| * @category Lang |
| * @param {*} value The value to check. |
| * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. |
| * @example |
| * |
| * _.isSymbol(Symbol.iterator); |
| * // => true |
| * |
| * _.isSymbol('abc'); |
| * // => false |
| */ |
| function isSymbol(value) { |
| return typeof value == 'symbol' || |
| (isObjectLike(value) && objectToString.call(value) == symbolTag); |
| } |
| |
| /** |
| * Converts `value` to a string. An empty string is returned for `null` |
| * and `undefined` values. The sign of `-0` is preserved. |
| * |
| * @static |
| * @memberOf _ |
| * @since 4.0.0 |
| * @category Lang |
| * @param {*} value The value to process. |
| * @returns {string} Returns the string. |
| * @example |
| * |
| * _.toString(null); |
| * // => '' |
| * |
| * _.toString(-0); |
| * // => '-0' |
| * |
| * _.toString([1, 2, 3]); |
| * // => '1,2,3' |
| */ |
| function toString(value) { |
| return value == null ? '' : baseToString(value); |
| } |
| |
| /** |
| * Gets the value at `path` of `object`. If the resolved value is |
| * `undefined`, the `defaultValue` is returned in its place. |
| * |
| * @static |
| * @memberOf _ |
| * @since 3.7.0 |
| * @category Object |
| * @param {Object} object The object to query. |
| * @param {Array|string} path The path of the property to get. |
| * @param {*} [defaultValue] The value returned for `undefined` resolved values. |
| * @returns {*} Returns the resolved value. |
| * @example |
| * |
| * var object = { 'a': [{ 'b': { 'c': 3 } }] }; |
| * |
| * _.get(object, 'a[0].b.c'); |
| * // => 3 |
| * |
| * _.get(object, ['a', '0', 'b', 'c']); |
| * // => 3 |
| * |
| * _.get(object, 'a.b.c', 'default'); |
| * // => 'default' |
| */ |
| function get(object, path, defaultValue) { |
| var result = object == null ? undefined : baseGet(object, path); |
| return result === undefined ? defaultValue : result; |
| } |
| |
| module.exports = get; |
| |
| },{}],93:[function(require,module,exports){ |
| 'use strict'; |
| module.exports = { |
| stdout: false, |
| stderr: false |
| }; |
| |
| },{}],94:[function(require,module,exports){ |
| (function (global, factory) { |
| typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : |
| typeof define === 'function' && define.amd ? define(factory) : |
| (global.typeDetect = factory()); |
| }(this, (function () { 'use strict'; |
| |
| /* ! |
| * type-detect |
| * Copyright(c) 2013 jake luer <jake@alogicalparadox.com> |
| * MIT Licensed |
| */ |
| var promiseExists = typeof Promise === 'function'; |
| |
| /* eslint-disable no-undef */ |
| var globalObject = typeof self === 'object' ? self : global; // eslint-disable-line id-blacklist |
| |
| var symbolExists = typeof Symbol !== 'undefined'; |
| var mapExists = typeof Map !== 'undefined'; |
| var setExists = typeof Set !== 'undefined'; |
| var weakMapExists = typeof WeakMap !== 'undefined'; |
| var weakSetExists = typeof WeakSet !== 'undefined'; |
| var dataViewExists = typeof DataView !== 'undefined'; |
| var symbolIteratorExists = symbolExists && typeof Symbol.iterator !== 'undefined'; |
| var symbolToStringTagExists = symbolExists && typeof Symbol.toStringTag !== 'undefined'; |
| var setEntriesExists = setExists && typeof Set.prototype.entries === 'function'; |
| var mapEntriesExists = mapExists && typeof Map.prototype.entries === 'function'; |
| var setIteratorPrototype = setEntriesExists && Object.getPrototypeOf(new Set().entries()); |
| var mapIteratorPrototype = mapEntriesExists && Object.getPrototypeOf(new Map().entries()); |
| var arrayIteratorExists = symbolIteratorExists && typeof Array.prototype[Symbol.iterator] === 'function'; |
| var arrayIteratorPrototype = arrayIteratorExists && Object.getPrototypeOf([][Symbol.iterator]()); |
| var stringIteratorExists = symbolIteratorExists && typeof String.prototype[Symbol.iterator] === 'function'; |
| var stringIteratorPrototype = stringIteratorExists && Object.getPrototypeOf(''[Symbol.iterator]()); |
| var toStringLeftSliceLength = 8; |
| var toStringRightSliceLength = -1; |
| /** |
| * ### typeOf (obj) |
| * |
| * Uses `Object.prototype.toString` to determine the type of an object, |
| * normalising behaviour across engine versions & well optimised. |
| * |
| * @param {Mixed} object |
| * @return {String} object type |
| * @api public |
| */ |
| function typeDetect(obj) { |
| /* ! Speed optimisation |
| * Pre: |
| * string literal x 3,039,035 ops/sec ±1.62% (78 runs sampled) |
| * boolean literal x 1,424,138 ops/sec ±4.54% (75 runs sampled) |
| * number literal x 1,653,153 ops/sec ±1.91% (82 runs sampled) |
| * undefined x 9,978,660 ops/sec ±1.92% (75 runs sampled) |
| * function x 2,556,769 ops/sec ±1.73% (77 runs sampled) |
| * Post: |
| * string literal x 38,564,796 ops/sec ±1.15% (79 runs sampled) |
| * boolean literal x 31,148,940 ops/sec ±1.10% (79 runs sampled) |
| * number literal x 32,679,330 ops/sec ±1.90% (78 runs sampled) |
| * undefined x 32,363,368 ops/sec ±1.07% (82 runs sampled) |
| * function x 31,296,870 ops/sec ±0.96% (83 runs sampled) |
| */ |
| var typeofObj = typeof obj; |
| if (typeofObj !== 'object') { |
| return typeofObj; |
| } |
| |
| /* ! Speed optimisation |
| * Pre: |
| * null x 28,645,765 ops/sec ±1.17% (82 runs sampled) |
| * Post: |
| * null x 36,428,962 ops/sec ±1.37% (84 runs sampled) |
| */ |
| if (obj === null) { |
| return 'null'; |
| } |
| |
| /* ! Spec Conformance |
| * Test: `Object.prototype.toString.call(window)`` |
| * - Node === "[object global]" |
| * - Chrome === "[object global]" |
| * - Firefox === "[object Window]" |
| * - PhantomJS === "[object Window]" |
| * - Safari === "[object Window]" |
| * - IE 11 === "[object Window]" |
| * - IE Edge === "[object Window]" |
| * Test: `Object.prototype.toString.call(this)`` |
| * - Chrome Worker === "[object global]" |
| * - Firefox Worker === "[object DedicatedWorkerGlobalScope]" |
| * - Safari Worker === "[object DedicatedWorkerGlobalScope]" |
| * - IE 11 Worker === "[object WorkerGlobalScope]" |
| * - IE Edge Worker === "[object WorkerGlobalScope]" |
| */ |
| if (obj === globalObject) { |
| return 'global'; |
| } |
| |
| /* ! Speed optimisation |
| * Pre: |
| * array literal x 2,888,352 ops/sec ±0.67% (82 runs sampled) |
| * Post: |
| * array literal x 22,479,650 ops/sec ±0.96% (81 runs sampled) |
| */ |
| if ( |
| Array.isArray(obj) && |
| (symbolToStringTagExists === false || !(Symbol.toStringTag in obj)) |
| ) { |
| return 'Array'; |
| } |
| |
| // Not caching existence of `window` and related properties due to potential |
| // for `window` to be unset before tests in quasi-browser environments. |
| if (typeof window === 'object' && window !== null) { |
| /* ! Spec Conformance |
| * (https://html.spec.whatwg.org/multipage/browsers.html#location) |
| * WhatWG HTML$7.7.3 - The `Location` interface |
| * Test: `Object.prototype.toString.call(window.location)`` |
| * - IE <=11 === "[object Object]" |
| * - IE Edge <=13 === "[object Object]" |
| */ |
| if (typeof window.location === 'object' && obj === window.location) { |
| return 'Location'; |
| } |
| |
| /* ! Spec Conformance |
| * (https://html.spec.whatwg.org/#document) |
| * WhatWG HTML$3.1.1 - The `Document` object |
| * Note: Most browsers currently adher to the W3C DOM Level 2 spec |
| * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-26809268) |
| * which suggests that browsers should use HTMLTableCellElement for |
| * both TD and TH elements. WhatWG separates these. |
| * WhatWG HTML states: |
| * > For historical reasons, Window objects must also have a |
| * > writable, configurable, non-enumerable property named |
| * > HTMLDocument whose value is the Document interface object. |
| * Test: `Object.prototype.toString.call(document)`` |
| * - Chrome === "[object HTMLDocument]" |
| * - Firefox === "[object HTMLDocument]" |
| * - Safari === "[object HTMLDocument]" |
| * - IE <=10 === "[object Document]" |
| * - IE 11 === "[object HTMLDocument]" |
| * - IE Edge <=13 === "[object HTMLDocument]" |
| */ |
| if (typeof window.document === 'object' && obj === window.document) { |
| return 'Document'; |
| } |
| |
| if (typeof window.navigator === 'object') { |
| /* ! Spec Conformance |
| * (https://html.spec.whatwg.org/multipage/webappapis.html#mimetypearray) |
| * WhatWG HTML$8.6.1.5 - Plugins - Interface MimeTypeArray |
| * Test: `Object.prototype.toString.call(navigator.mimeTypes)`` |
| * - IE <=10 === "[object MSMimeTypesCollection]" |
| */ |
| if (typeof window.navigator.mimeTypes === 'object' && |
| obj === window.navigator.mimeTypes) { |
| return 'MimeTypeArray'; |
| } |
| |
| /* ! Spec Conformance |
| * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) |
| * WhatWG HTML$8.6.1.5 - Plugins - Interface PluginArray |
| * Test: `Object.prototype.toString.call(navigator.plugins)`` |
| * - IE <=10 === "[object MSPluginsCollection]" |
| */ |
| if (typeof window.navigator.plugins === 'object' && |
| obj === window.navigator.plugins) { |
| return 'PluginArray'; |
| } |
| } |
| |
| if ((typeof window.HTMLElement === 'function' || |
| typeof window.HTMLElement === 'object') && |
| obj instanceof window.HTMLElement) { |
| /* ! Spec Conformance |
| * (https://html.spec.whatwg.org/multipage/webappapis.html#pluginarray) |
| * WhatWG HTML$4.4.4 - The `blockquote` element - Interface `HTMLQuoteElement` |
| * Test: `Object.prototype.toString.call(document.createElement('blockquote'))`` |
| * - IE <=10 === "[object HTMLBlockElement]" |
| */ |
| if (obj.tagName === 'BLOCKQUOTE') { |
| return 'HTMLQuoteElement'; |
| } |
| |
| /* ! Spec Conformance |
| * (https://html.spec.whatwg.org/#htmltabledatacellelement) |
| * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableDataCellElement` |
| * Note: Most browsers currently adher to the W3C DOM Level 2 spec |
| * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) |
| * which suggests that browsers should use HTMLTableCellElement for |
| * both TD and TH elements. WhatWG separates these. |
| * Test: Object.prototype.toString.call(document.createElement('td')) |
| * - Chrome === "[object HTMLTableCellElement]" |
| * - Firefox === "[object HTMLTableCellElement]" |
| * - Safari === "[object HTMLTableCellElement]" |
| */ |
| if (obj.tagName === 'TD') { |
| return 'HTMLTableDataCellElement'; |
| } |
| |
| /* ! Spec Conformance |
| * (https://html.spec.whatwg.org/#htmltableheadercellelement) |
| * WhatWG HTML$4.9.9 - The `td` element - Interface `HTMLTableHeaderCellElement` |
| * Note: Most browsers currently adher to the W3C DOM Level 2 spec |
| * (https://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-82915075) |
| * which suggests that browsers should use HTMLTableCellElement for |
| * both TD and TH elements. WhatWG separates these. |
| * Test: Object.prototype.toString.call(document.createElement('th')) |
| * - Chrome === "[object HTMLTableCellElement]" |
| * - Firefox === "[object HTMLTableCellElement]" |
| * - Safari === "[object HTMLTableCellElement]" |
| */ |
| if (obj.tagName === 'TH') { |
| return 'HTMLTableHeaderCellElement'; |
| } |
| } |
| } |
| |
| /* ! Speed optimisation |
| * Pre: |
| * Float64Array x 625,644 ops/sec ±1.58% (80 runs sampled) |
| * Float32Array x 1,279,852 ops/sec ±2.91% (77 runs sampled) |
| * Uint32Array x 1,178,185 ops/sec ±1.95% (83 runs sampled) |
| * Uint16Array x 1,008,380 ops/sec ±2.25% (80 runs sampled) |
| * Uint8Array x 1,128,040 ops/sec ±2.11% (81 runs sampled) |
| * Int32Array x 1,170,119 ops/sec ±2.88% (80 runs sampled) |
| * Int16Array x 1,176,348 ops/sec ±5.79% (86 runs sampled) |
| * Int8Array x 1,058,707 ops/sec ±4.94% (77 runs sampled) |
| * Uint8ClampedArray x 1,110,633 ops/sec ±4.20% (80 runs sampled) |
| * Post: |
| * Float64Array x 7,105,671 ops/sec ±13.47% (64 runs sampled) |
| * Float32Array x 5,887,912 ops/sec ±1.46% (82 runs sampled) |
| * Uint32Array x 6,491,661 ops/sec ±1.76% (79 runs sampled) |
| * Uint16Array x 6,559,795 ops/sec ±1.67% (82 runs sampled) |
| * Uint8Array x 6,463,966 ops/sec ±1.43% (85 runs sampled) |
| * Int32Array x 5,641,841 ops/sec ±3.49% (81 runs sampled) |
| * Int16Array x 6,583,511 ops/sec ±1.98% (80 runs sampled) |
| * Int8Array x 6,606,078 ops/sec ±1.74% (81 runs sampled) |
| * Uint8ClampedArray x 6,602,224 ops/sec ±1.77% (83 runs sampled) |
| */ |
| var stringTag = (symbolToStringTagExists && obj[Symbol.toStringTag]); |
| if (typeof stringTag === 'string') { |
| return stringTag; |
| } |
| |
| var objPrototype = Object.getPrototypeOf(obj); |
| /* ! Speed optimisation |
| * Pre: |
| * regex literal x 1,772,385 ops/sec ±1.85% (77 runs sampled) |
| * regex constructor x 2,143,634 ops/sec ±2.46% (78 runs sampled) |
| * Post: |
| * regex literal x 3,928,009 ops/sec ±0.65% (78 runs sampled) |
| * regex constructor x 3,931,108 ops/sec ±0.58% (84 runs sampled) |
| */ |
| if (objPrototype === RegExp.prototype) { |
| return 'RegExp'; |
| } |
| |
| /* ! Speed optimisation |
| * Pre: |
| * date x 2,130,074 ops/sec ±4.42% (68 runs sampled) |
| * Post: |
| * date x 3,953,779 ops/sec ±1.35% (77 runs sampled) |
| */ |
| if (objPrototype === Date.prototype) { |
| return 'Date'; |
| } |
| |
| /* ! Spec Conformance |
| * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-promise.prototype-@@tostringtag) |
| * ES6$25.4.5.4 - Promise.prototype[@@toStringTag] should be "Promise": |
| * Test: `Object.prototype.toString.call(Promise.resolve())`` |
| * - Chrome <=47 === "[object Object]" |
| * - Edge <=20 === "[object Object]" |
| * - Firefox 29-Latest === "[object Promise]" |
| * - Safari 7.1-Latest === "[object Promise]" |
| */ |
| if (promiseExists && objPrototype === Promise.prototype) { |
| return 'Promise'; |
| } |
| |
| /* ! Speed optimisation |
| * Pre: |
| * set x 2,222,186 ops/sec ±1.31% (82 runs sampled) |
| * Post: |
| * set x 4,545,879 ops/sec ±1.13% (83 runs sampled) |
| */ |
| if (setExists && objPrototype === Set.prototype) { |
| return 'Set'; |
| } |
| |
| /* ! Speed optimisation |
| * Pre: |
| * map x 2,396,842 ops/sec ±1.59% (81 runs sampled) |
| * Post: |
| * map x 4,183,945 ops/sec ±6.59% (82 runs sampled) |
| */ |
| if (mapExists && objPrototype === Map.prototype) { |
| return 'Map'; |
| } |
| |
| /* ! Speed optimisation |
| * Pre: |
| * weakset x 1,323,220 ops/sec ±2.17% (76 runs sampled) |
| * Post: |
| * weakset x 4,237,510 ops/sec ±2.01% (77 runs sampled) |
| */ |
| if (weakSetExists && objPrototype === WeakSet.prototype) { |
| return 'WeakSet'; |
| } |
| |
| /* ! Speed optimisation |
| * Pre: |
| * weakmap x 1,500,260 ops/sec ±2.02% (78 runs sampled) |
| * Post: |
| * weakmap x 3,881,384 ops/sec ±1.45% (82 runs sampled) |
| */ |
| if (weakMapExists && objPrototype === WeakMap.prototype) { |
| return 'WeakMap'; |
| } |
| |
| /* ! Spec Conformance |
| * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-dataview.prototype-@@tostringtag) |
| * ES6$24.2.4.21 - DataView.prototype[@@toStringTag] should be "DataView": |
| * Test: `Object.prototype.toString.call(new DataView(new ArrayBuffer(1)))`` |
| * - Edge <=13 === "[object Object]" |
| */ |
| if (dataViewExists && objPrototype === DataView.prototype) { |
| return 'DataView'; |
| } |
| |
| /* ! Spec Conformance |
| * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%mapiteratorprototype%-@@tostringtag) |
| * ES6$23.1.5.2.2 - %MapIteratorPrototype%[@@toStringTag] should be "Map Iterator": |
| * Test: `Object.prototype.toString.call(new Map().entries())`` |
| * - Edge <=13 === "[object Object]" |
| */ |
| if (mapExists && objPrototype === mapIteratorPrototype) { |
| return 'Map Iterator'; |
| } |
| |
| /* ! Spec Conformance |
| * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%setiteratorprototype%-@@tostringtag) |
| * ES6$23.2.5.2.2 - %SetIteratorPrototype%[@@toStringTag] should be "Set Iterator": |
| * Test: `Object.prototype.toString.call(new Set().entries())`` |
| * - Edge <=13 === "[object Object]" |
| */ |
| if (setExists && objPrototype === setIteratorPrototype) { |
| return 'Set Iterator'; |
| } |
| |
| /* ! Spec Conformance |
| * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%arrayiteratorprototype%-@@tostringtag) |
| * ES6$22.1.5.2.2 - %ArrayIteratorPrototype%[@@toStringTag] should be "Array Iterator": |
| * Test: `Object.prototype.toString.call([][Symbol.iterator]())`` |
| * - Edge <=13 === "[object Object]" |
| */ |
| if (arrayIteratorExists && objPrototype === arrayIteratorPrototype) { |
| return 'Array Iterator'; |
| } |
| |
| /* ! Spec Conformance |
| * (http://www.ecma-international.org/ecma-262/6.0/index.html#sec-%stringiteratorprototype%-@@tostringtag) |
| * ES6$21.1.5.2.2 - %StringIteratorPrototype%[@@toStringTag] should be "String Iterator": |
| * Test: `Object.prototype.toString.call(''[Symbol.iterator]())`` |
| * - Edge <=13 === "[object Object]" |
| */ |
| if (stringIteratorExists && objPrototype === stringIteratorPrototype) { |
| return 'String Iterator'; |
| } |
| |
| /* ! Speed optimisation |
| * Pre: |
| * object from null x 2,424,320 ops/sec ±1.67% (76 runs sampled) |
| * Post: |
| * object from null x 5,838,000 ops/sec ±0.99% (84 runs sampled) |
| */ |
| if (objPrototype === null) { |
| return 'Object'; |
| } |
| |
| return Object |
| .prototype |
| .toString |
| .call(obj) |
| .slice(toStringLeftSliceLength, toStringRightSliceLength); |
| } |
| |
| return typeDetect; |
| |
| }))); |
| |
| },{}]},{},[2])(2) |
| }); |
| |
| //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJsaWIvY3JlYXRlLXNpbm9uLWFwaS5qcyIsImxpYi9zaW5vbi5qcyIsImxpYi9zaW5vbi9hc3NlcnQuanMiLCJsaWIvc2lub24vYmVoYXZpb3IuanMiLCJsaWIvc2lub24vY29sbGVjdC1vd24tbWV0aG9kcy5qcyIsImxpYi9zaW5vbi9jb2xvcml6ZXIuanMiLCJsaWIvc2lub24vY3JlYXRlLXNhbmRib3guanMiLCJsaWIvc2lub24vY3JlYXRlLXN0dWItaW5zdGFuY2UuanMiLCJsaWIvc2lub24vZGVmYXVsdC1iZWhhdmlvcnMuanMiLCJsaWIvc2lub24vZmFrZS5qcyIsImxpYi9zaW5vbi9tb2NrLWV4cGVjdGF0aW9uLmpzIiwibGliL3Npbm9uL21vY2suanMiLCJsaWIvc2lub24vcHJvbWlzZS5qcyIsImxpYi9zaW5vbi9wcm94eS1jYWxsLXV0aWwuanMiLCJsaWIvc2lub24vcHJveHktY2FsbC5qcyIsImxpYi9zaW5vbi9wcm94eS1pbnZva2UuanMiLCJsaWIvc2lub24vcHJveHkuanMiLCJsaWIvc2lub24vcmVzdG9yZS1vYmplY3QuanMiLCJsaWIvc2lub24vc2FuZGJveC5qcyIsImxpYi9zaW5vbi9zcHktZm9ybWF0dGVycy5qcyIsImxpYi9zaW5vbi9zcHkuanMiLCJsaWIvc2lub24vc3R1Yi5qcyIsImxpYi9zaW5vbi90aHJvdy1vbi1mYWxzeS1vYmplY3QuanMiLCJsaWIvc2lub24vdXRpbC9jb3JlL2V4cG9ydC1hc3luYy1iZWhhdmlvcnMuanMiLCJsaWIvc2lub24vdXRpbC9jb3JlL2V4dGVuZC5qcyIsImxpYi9zaW5vbi91dGlsL2NvcmUvZnVuY3Rpb24tdG8tc3RyaW5nLmpzIiwibGliL3Npbm9uL3V0aWwvY29yZS9nZXQtbmV4dC10aWNrLmpzIiwibGliL3Npbm9uL3V0aWwvY29yZS9nZXQtcHJvcGVydHktZGVzY3JpcHRvci5qcyIsImxpYi9zaW5vbi91dGlsL2NvcmUvaXMtZXMtbW9kdWxlLmpzIiwibGliL3Npbm9uL3V0aWwvY29yZS9pcy1ub24tZXhpc3RlbnQtcHJvcGVydHkuanMiLCJsaWIvc2lub24vdXRpbC9jb3JlL2lzLXByb3BlcnR5LWNvbmZpZ3VyYWJsZS5qcyIsImxpYi9zaW5vbi91dGlsL2NvcmUvaXMtcmVzdG9yYWJsZS5qcyIsImxpYi9zaW5vbi91dGlsL2NvcmUvbmV4dC10aWNrLmpzIiwibGliL3Npbm9uL3V0aWwvY29yZS9zaW5vbi10eXBlLmpzIiwibGliL3Npbm9uL3V0aWwvY29yZS90aW1lcy1pbi13b3Jkcy5qcyIsImxpYi9zaW5vbi91dGlsL2NvcmUvd2Fsay1vYmplY3QuanMiLCJsaWIvc2lub24vdXRpbC9jb3JlL3dhbGsuanMiLCJsaWIvc2lub24vdXRpbC9jb3JlL3dyYXAtbWV0aG9kLmpzIiwibGliL3Npbm9uL3V0aWwvZmFrZS10aW1lcnMuanMiLCJub2RlX21vZHVsZXMvQHNpbm9uanMvY29tbW9ucy9saWIvY2FsbGVkLWluLW9yZGVyLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL2NvbW1vbnMvbGliL2NsYXNzLW5hbWUuanMiLCJub2RlX21vZHVsZXMvQHNpbm9uanMvY29tbW9ucy9saWIvZGVwcmVjYXRlZC5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9jb21tb25zL2xpYi9ldmVyeS5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9jb21tb25zL2xpYi9mdW5jdGlvbi1uYW1lLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL2NvbW1vbnMvbGliL2dsb2JhbC5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9jb21tb25zL2xpYi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9jb21tb25zL2xpYi9vcmRlci1ieS1maXJzdC1jYWxsLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL2NvbW1vbnMvbGliL3Byb3RvdHlwZXMvYXJyYXkuanMiLCJub2RlX21vZHVsZXMvQHNpbm9uanMvY29tbW9ucy9saWIvcHJvdG90eXBlcy9jb3B5LXByb3RvdHlwZS1tZXRob2RzLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL2NvbW1vbnMvbGliL3Byb3RvdHlwZXMvZnVuY3Rpb24uanMiLCJub2RlX21vZHVsZXMvQHNpbm9uanMvY29tbW9ucy9saWIvcHJvdG90eXBlcy9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9jb21tb25zL2xpYi9wcm90b3R5cGVzL21hcC5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9jb21tb25zL2xpYi9wcm90b3R5cGVzL29iamVjdC5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9jb21tb25zL2xpYi9wcm90b3R5cGVzL3NldC5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9jb21tb25zL2xpYi9wcm90b3R5cGVzL3N0cmluZy5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9jb21tb25zL2xpYi9wcm90b3R5cGVzL3Rocm93cy1vbi1wcm90by5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9jb21tb25zL2xpYi90eXBlLW9mLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL2NvbW1vbnMvbGliL3ZhbHVlLXRvLXN0cmluZy5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9mYWtlLXRpbWVycy9zcmMvZmFrZS10aW1lcnMtc3JjLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL3NhbXNhbS9saWIvYXJyYXktdHlwZXMuanMiLCJub2RlX21vZHVsZXMvQHNpbm9uanMvc2Ftc2FtL2xpYi9jcmVhdGUtbWF0Y2hlci5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9zYW1zYW0vbGliL2NyZWF0ZS1tYXRjaGVyL2Fzc2VydC1tYXRjaGVyLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL3NhbXNhbS9saWIvY3JlYXRlLW1hdGNoZXIvYXNzZXJ0LW1ldGhvZC1leGlzdHMuanMiLCJub2RlX21vZHVsZXMvQHNpbm9uanMvc2Ftc2FtL2xpYi9jcmVhdGUtbWF0Y2hlci9hc3NlcnQtdHlwZS5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9zYW1zYW0vbGliL2NyZWF0ZS1tYXRjaGVyL2lzLWl0ZXJhYmxlLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL3NhbXNhbS9saWIvY3JlYXRlLW1hdGNoZXIvaXMtbWF0Y2hlci5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9zYW1zYW0vbGliL2NyZWF0ZS1tYXRjaGVyL21hdGNoLW9iamVjdC5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9zYW1zYW0vbGliL2NyZWF0ZS1tYXRjaGVyL21hdGNoZXItcHJvdG90eXBlLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL3NhbXNhbS9saWIvY3JlYXRlLW1hdGNoZXIvdHlwZS1tYXAuanMiLCJub2RlX21vZHVsZXMvQHNpbm9uanMvc2Ftc2FtL2xpYi9kZWVwLWVxdWFsLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL3NhbXNhbS9saWIvZ2V0LWNsYXNzLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL3NhbXNhbS9saWIvaWRlbnRpY2FsLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL3NhbXNhbS9saWIvaXMtYXJndW1lbnRzLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL3NhbXNhbS9saWIvaXMtYXJyYXktdHlwZS5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9zYW1zYW0vbGliL2lzLWRhdGUuanMiLCJub2RlX21vZHVsZXMvQHNpbm9uanMvc2Ftc2FtL2xpYi9pcy1lbGVtZW50LmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL3NhbXNhbS9saWIvaXMtaXRlcmFibGUuanMiLCJub2RlX21vZHVsZXMvQHNpbm9uanMvc2Ftc2FtL2xpYi9pcy1tYXAuanMiLCJub2RlX21vZHVsZXMvQHNpbm9uanMvc2Ftc2FtL2xpYi9pcy1uYW4uanMiLCJub2RlX21vZHVsZXMvQHNpbm9uanMvc2Ftc2FtL2xpYi9pcy1uZWctemVyby5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9zYW1zYW0vbGliL2lzLW9iamVjdC5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9zYW1zYW0vbGliL2lzLXNldC5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9zYW1zYW0vbGliL2lzLXN1YnNldC5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9zYW1zYW0vbGliL2l0ZXJhYmxlLXRvLXN0cmluZy5qcyIsIm5vZGVfbW9kdWxlcy9Ac2lub25qcy9zYW1zYW0vbGliL21hdGNoLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL3NhbXNhbS9saWIvc2Ftc2FtLmpzIiwibm9kZV9tb2R1bGVzL0BzaW5vbmpzL3NhbXNhbS9ub2RlX21vZHVsZXMvdHlwZS1kZXRlY3QvdHlwZS1kZXRlY3QuanMiLCJub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvaW5oZXJpdHMvaW5oZXJpdHNfYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy91dGlsL3N1cHBvcnQvaXNCdWZmZXJCcm93c2VyLmpzIiwibm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL3V0aWwvdXRpbC5qcyIsIm5vZGVfbW9kdWxlcy9kaWZmL2Rpc3QvZGlmZi5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2guZ2V0L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3N1cHBvcnRzLWNvbG9yL2Jyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvdHlwZS1kZXRlY3QvdHlwZS1kZXRlY3QuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN1NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3UUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDalVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5TUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOWVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbktBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDalFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDYkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyUEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDYkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNubkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3WkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNkQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxa0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFqRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuNkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24oKXtmdW5jdGlvbiByKGUsbix0KXtmdW5jdGlvbiBvKGksZil7aWYoIW5baV0pe2lmKCFlW2ldKXt2YXIgYz1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlO2lmKCFmJiZjKXJldHVybiBjKGksITApO2lmKHUpcmV0dXJuIHUoaSwhMCk7dmFyIGE9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitpK1wiJ1wiKTt0aHJvdyBhLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsYX12YXIgcD1uW2ldPXtleHBvcnRzOnt9fTtlW2ldWzBdLmNhbGwocC5leHBvcnRzLGZ1bmN0aW9uKHIpe3ZhciBuPWVbaV1bMV1bcl07cmV0dXJuIG8obnx8cil9LHAscC5leHBvcnRzLHIsZSxuLHQpfXJldHVybiBuW2ldLmV4cG9ydHN9Zm9yKHZhciB1PVwiZnVuY3Rpb25cIj09dHlwZW9mIHJlcXVpcmUmJnJlcXVpcmUsaT0wO2k8dC5sZW5ndGg7aSsrKW8odFtpXSk7cmV0dXJuIG99cmV0dXJuIHJ9KSgpIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IGJlaGF2aW9yID0gcmVxdWlyZShcIi4vc2lub24vYmVoYXZpb3JcIik7XG5jb25zdCBjcmVhdGVTYW5kYm94ID0gcmVxdWlyZShcIi4vc2lub24vY3JlYXRlLXNhbmRib3hcIik7XG5jb25zdCBleHRlbmQgPSByZXF1aXJlKFwiLi9zaW5vbi91dGlsL2NvcmUvZXh0ZW5kXCIpO1xuY29uc3QgZmFrZVRpbWVycyA9IHJlcXVpcmUoXCIuL3Npbm9uL3V0aWwvZmFrZS10aW1lcnNcIik7XG5jb25zdCBTYW5kYm94ID0gcmVxdWlyZShcIi4vc2lub24vc2FuZGJveFwiKTtcbmNvbnN0IHN0dWIgPSByZXF1aXJlKFwiLi9zaW5vbi9zdHViXCIpO1xuY29uc3QgcHJvbWlzZSA9IHJlcXVpcmUoXCIuL3Npbm9uL3Byb21pc2VcIik7XG5cbi8qKlxuICogQHJldHVybnMge29iamVjdH0gYSBjb25maWd1cmVkIHNhbmRib3hcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcmVhdGVBcGkoKSB7XG4gICAgY29uc3QgYXBpTWV0aG9kcyA9IHtcbiAgICAgICAgY3JlYXRlU2FuZGJveDogY3JlYXRlU2FuZGJveCxcbiAgICAgICAgbWF0Y2g6IHJlcXVpcmUoXCJAc2lub25qcy9zYW1zYW1cIikuY3JlYXRlTWF0Y2hlcixcbiAgICAgICAgcmVzdG9yZU9iamVjdDogcmVxdWlyZShcIi4vc2lub24vcmVzdG9yZS1vYmplY3RcIiksXG5cbiAgICAgICAgZXhwZWN0YXRpb246IHJlcXVpcmUoXCIuL3Npbm9uL21vY2stZXhwZWN0YXRpb25cIiksXG5cbiAgICAgICAgLy8gZmFrZSB0aW1lcnNcbiAgICAgICAgdGltZXJzOiBmYWtlVGltZXJzLnRpbWVycyxcblxuICAgICAgICBhZGRCZWhhdmlvcjogZnVuY3Rpb24gKG5hbWUsIGZuKSB7XG4gICAgICAgICAgICBiZWhhdmlvci5hZGRCZWhhdmlvcihzdHViLCBuYW1lLCBmbik7XG4gICAgICAgIH0sXG5cbiAgICAgICAgLy8gZmFrZSBwcm9taXNlXG4gICAgICAgIHByb21pc2U6IHByb21pc2UsXG4gICAgfTtcblxuICAgIGNvbnN0IHNhbmRib3ggPSBuZXcgU2FuZGJveCgpO1xuICAgIHJldHVybiBleHRlbmQoc2FuZGJveCwgYXBpTWV0aG9kcyk7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IGNyZWF0ZUFwaSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1zaW5vbi1hcGlcIik7XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlQXBpKCk7XG4iLCJcInVzZSBzdHJpY3RcIjtcbi8qKiBAbW9kdWxlICovXG5cbmNvbnN0IGFycmF5UHJvdG8gPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLmFycmF5O1xuY29uc3QgY2FsbGVkSW5PcmRlciA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLmNhbGxlZEluT3JkZXI7XG5jb25zdCBjcmVhdGVNYXRjaGVyID0gcmVxdWlyZShcIkBzaW5vbmpzL3NhbXNhbVwiKS5jcmVhdGVNYXRjaGVyO1xuY29uc3Qgb3JkZXJCeUZpcnN0Q2FsbCA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLm9yZGVyQnlGaXJzdENhbGw7XG5jb25zdCB0aW1lc0luV29yZHMgPSByZXF1aXJlKFwiLi91dGlsL2NvcmUvdGltZXMtaW4td29yZHNcIik7XG5jb25zdCBpbnNwZWN0ID0gcmVxdWlyZShcInV0aWxcIikuaW5zcGVjdDtcbmNvbnN0IHN0cmluZ1NsaWNlID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikucHJvdG90eXBlcy5zdHJpbmcuc2xpY2U7XG5jb25zdCBnbG9iYWxPYmplY3QgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5nbG9iYWw7XG5cbmNvbnN0IGFycmF5U2xpY2UgPSBhcnJheVByb3RvLnNsaWNlO1xuY29uc3QgY29uY2F0ID0gYXJyYXlQcm90by5jb25jYXQ7XG5jb25zdCBmb3JFYWNoID0gYXJyYXlQcm90by5mb3JFYWNoO1xuY29uc3Qgam9pbiA9IGFycmF5UHJvdG8uam9pbjtcbmNvbnN0IHNwbGljZSA9IGFycmF5UHJvdG8uc3BsaWNlO1xuXG5mdW5jdGlvbiBhcHBseURlZmF1bHRzKG9iaiwgZGVmYXVsdHMpIHtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhkZWZhdWx0cykpIHtcbiAgICAgICAgY29uc3QgdmFsID0gb2JqW2tleV07XG4gICAgICAgIGlmICh2YWwgPT09IG51bGwgfHwgdHlwZW9mIHZhbCA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgb2JqW2tleV0gPSBkZWZhdWx0c1trZXldO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIEB0eXBlZGVmIHtvYmplY3R9IENyZWF0ZUFzc2VydE9wdGlvbnNcbiAqIEBnbG9iYWxcbiAqXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtzaG91bGRMaW1pdEFzc2VydGlvbkxvZ3NdIGRlZmF1bHQgaXMgZmFsc2VcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSAgW2Fzc2VydGlvbkxvZ0xpbWl0XSBkZWZhdWx0IGlzIDEwS1xuICovXG5cbi8qKlxuICogQ3JlYXRlIGFuIGFzc2VydGlvbiBvYmplY3QgdGhhdCBleHBvc2VzIHNldmVyYWwgbWV0aG9kcyB0byBpbnZva2VcbiAqXG4gKiBAcGFyYW0ge0NyZWF0ZUFzc2VydE9wdGlvbnN9ICBbb3B0c10gb3B0aW9ucyBiYWdcbiAqIEByZXR1cm5zIHtvYmplY3R9IG9iamVjdCB3aXRoIG11bHRpcGxlIGFzc2VydGlvbiBtZXRob2RzXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUFzc2VydE9iamVjdChvcHRzKSB7XG4gICAgY29uc3QgY2xlYW5lZEFzc2VydE9wdGlvbnMgPSBvcHRzIHx8IHt9O1xuICAgIGFwcGx5RGVmYXVsdHMoY2xlYW5lZEFzc2VydE9wdGlvbnMsIHtcbiAgICAgICAgc2hvdWxkTGltaXRBc3NlcnRpb25Mb2dzOiBmYWxzZSxcbiAgICAgICAgYXNzZXJ0aW9uTG9nTGltaXQ6IDFlNCxcbiAgICB9KTtcblxuICAgIGNvbnN0IGFzc2VydCA9IHtcbiAgICAgICAgZmFpbEV4Y2VwdGlvbjogXCJBc3NlcnRFcnJvclwiLFxuXG4gICAgICAgIGZhaWw6IGZ1bmN0aW9uIGZhaWwobWVzc2FnZSkge1xuICAgICAgICAgICAgbGV0IG1zZyA9IG1lc3NhZ2U7XG4gICAgICAgICAgICBpZiAoY2xlYW5lZEFzc2VydE9wdGlvbnMuc2hvdWxkTGltaXRBc3NlcnRpb25Mb2dzKSB7XG4gICAgICAgICAgICAgICAgbXNnID0gbWVzc2FnZS5zdWJzdHJpbmcoXG4gICAgICAgICAgICAgICAgICAgIDAsXG4gICAgICAgICAgICAgICAgICAgIGNsZWFuZWRBc3NlcnRPcHRpb25zLmFzc2VydGlvbkxvZ0xpbWl0LFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBlcnJvciA9IG5ldyBFcnJvcihtc2cpO1xuICAgICAgICAgICAgZXJyb3IubmFtZSA9IHRoaXMuZmFpbEV4Y2VwdGlvbiB8fCBhc3NlcnQuZmFpbEV4Y2VwdGlvbjtcblxuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH0sXG5cbiAgICAgICAgcGFzczogZnVuY3Rpb24gcGFzcygpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSxcblxuICAgICAgICBjYWxsT3JkZXI6IGZ1bmN0aW9uIGFzc2VydENhbGxPcmRlcigpIHtcbiAgICAgICAgICAgIHZlcmlmeUlzU3R1Yi5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgbGV0IGV4cGVjdGVkID0gXCJcIjtcbiAgICAgICAgICAgIGxldCBhY3R1YWwgPSBcIlwiO1xuXG4gICAgICAgICAgICBpZiAoIWNhbGxlZEluT3JkZXIoYXJndW1lbnRzKSkge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cGVjdGVkID0gam9pbihhcmd1bWVudHMsIFwiLCBcIik7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbGxzID0gYXJyYXlTbGljZShhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgICAgICBsZXQgaSA9IGNhbGxzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY2FsbHNbLS1pXS5jYWxsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcGxpY2UoY2FsbHMsIGksIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGFjdHVhbCA9IGpvaW4ob3JkZXJCeUZpcnN0Q2FsbChjYWxscyksIFwiLCBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGlzIGZhaWxzLCB3ZSdsbCBqdXN0IGZhbGwgYmFjayB0byB0aGUgYmxhbmsgc3RyaW5nXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZmFpbEFzc2VydGlvbihcbiAgICAgICAgICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICAgICAgICAgICAgYGV4cGVjdGVkICR7ZXhwZWN0ZWR9IHRvIGJlIGNhbGxlZCBpbiBvcmRlciBidXQgd2VyZSBjYWxsZWQgYXMgJHthY3R1YWx9YCxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQucGFzcyhcImNhbGxPcmRlclwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBjYWxsQ291bnQ6IGZ1bmN0aW9uIGFzc2VydENhbGxDb3VudChtZXRob2QsIGNvdW50KSB7XG4gICAgICAgICAgICB2ZXJpZnlJc1N0dWIobWV0aG9kKTtcblxuICAgICAgICAgICAgbGV0IG1zZztcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY291bnQgIT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICBtc2cgPVxuICAgICAgICAgICAgICAgICAgICBgZXhwZWN0ZWQgJHtpbnNwZWN0KGNvdW50KX0gdG8gYmUgYSBudW1iZXIgYCArXG4gICAgICAgICAgICAgICAgICAgIGBidXQgd2FzIG9mIHR5cGUgJHt0eXBlb2YgY291bnR9YDtcbiAgICAgICAgICAgICAgICBmYWlsQXNzZXJ0aW9uKHRoaXMsIG1zZyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1ldGhvZC5jYWxsQ291bnQgIT09IGNvdW50KSB7XG4gICAgICAgICAgICAgICAgbXNnID1cbiAgICAgICAgICAgICAgICAgICAgYGV4cGVjdGVkICVuIHRvIGJlIGNhbGxlZCAke3RpbWVzSW5Xb3Jkcyhjb3VudCl9IGAgK1xuICAgICAgICAgICAgICAgICAgICBgYnV0IHdhcyBjYWxsZWQgJWMlQ2A7XG4gICAgICAgICAgICAgICAgZmFpbEFzc2VydGlvbih0aGlzLCBtZXRob2QucHJpbnRmKG1zZykpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQucGFzcyhcImNhbGxDb3VudFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBleHBvc2U6IGZ1bmN0aW9uIGV4cG9zZSh0YXJnZXQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghdGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcInRhcmdldCBpcyBudWxsIG9yIHVuZGVmaW5lZFwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgbyA9IG9wdGlvbnMgfHwge307XG4gICAgICAgICAgICBjb25zdCBwcmVmaXggPVxuICAgICAgICAgICAgICAgICh0eXBlb2Ygby5wcmVmaXggPT09IFwidW5kZWZpbmVkXCIgJiYgXCJhc3NlcnRcIikgfHwgby5wcmVmaXg7XG4gICAgICAgICAgICBjb25zdCBpbmNsdWRlRmFpbCA9XG4gICAgICAgICAgICAgICAgdHlwZW9mIG8uaW5jbHVkZUZhaWwgPT09IFwidW5kZWZpbmVkXCIgfHwgQm9vbGVhbihvLmluY2x1ZGVGYWlsKTtcbiAgICAgICAgICAgIGNvbnN0IGluc3RhbmNlID0gdGhpcztcblxuICAgICAgICAgICAgZm9yRWFjaChPYmplY3Qua2V5cyhpbnN0YW5jZSksIGZ1bmN0aW9uIChtZXRob2QpIHtcbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgIG1ldGhvZCAhPT0gXCJleHBvc2VcIiAmJlxuICAgICAgICAgICAgICAgICAgICAoaW5jbHVkZUZhaWwgfHwgIS9eKGZhaWwpLy50ZXN0KG1ldGhvZCkpXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldFtleHBvc2VkTmFtZShwcmVmaXgsIG1ldGhvZCldID0gaW5zdGFuY2VbbWV0aG9kXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgcmV0dXJuIHRhcmdldDtcbiAgICAgICAgfSxcblxuICAgICAgICBtYXRjaDogZnVuY3Rpb24gbWF0Y2goYWN0dWFsLCBleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgY29uc3QgbWF0Y2hlciA9IGNyZWF0ZU1hdGNoZXIoZXhwZWN0YXRpb24pO1xuICAgICAgICAgICAgaWYgKG1hdGNoZXIudGVzdChhY3R1YWwpKSB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0LnBhc3MoXCJtYXRjaFwiKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZm9ybWF0dGVkID0gW1xuICAgICAgICAgICAgICAgICAgICBcImV4cGVjdGVkIHZhbHVlIHRvIG1hdGNoXCIsXG4gICAgICAgICAgICAgICAgICAgIGAgICAgZXhwZWN0ZWQgPSAke2luc3BlY3QoZXhwZWN0YXRpb24pfWAsXG4gICAgICAgICAgICAgICAgICAgIGAgICAgYWN0dWFsID0gJHtpbnNwZWN0KGFjdHVhbCl9YCxcbiAgICAgICAgICAgICAgICBdO1xuXG4gICAgICAgICAgICAgICAgZmFpbEFzc2VydGlvbih0aGlzLCBqb2luKGZvcm1hdHRlZCwgXCJcXG5cIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgIH07XG5cbiAgICBmdW5jdGlvbiB2ZXJpZnlJc1N0dWIoKSB7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSBhcnJheVNsaWNlKGFyZ3VtZW50cyk7XG5cbiAgICAgICAgZm9yRWFjaChhcmdzLCBmdW5jdGlvbiAobWV0aG9kKSB7XG4gICAgICAgICAgICBpZiAoIW1ldGhvZCkge1xuICAgICAgICAgICAgICAgIGFzc2VydC5mYWlsKFwiZmFrZSBpcyBub3QgYSBzcHlcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChtZXRob2QucHJveHkgJiYgbWV0aG9kLnByb3h5LmlzU2lub25Qcm94eSkge1xuICAgICAgICAgICAgICAgIHZlcmlmeUlzU3R1YihtZXRob2QucHJveHkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1ldGhvZCAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5mYWlsKGAke21ldGhvZH0gaXMgbm90IGEgZnVuY3Rpb25gKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1ldGhvZC5nZXRDYWxsICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmZhaWwoYCR7bWV0aG9kfSBpcyBub3Qgc3R1YmJlZGApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdmVyaWZ5SXNWYWxpZEFzc2VydGlvbihhc3NlcnRpb25NZXRob2QsIGFzc2VydGlvbkFyZ3MpIHtcbiAgICAgICAgc3dpdGNoIChhc3NlcnRpb25NZXRob2QpIHtcbiAgICAgICAgICAgIGNhc2UgXCJub3RDYWxsZWRcIjpcbiAgICAgICAgICAgIGNhc2UgXCJjYWxsZWRcIjpcbiAgICAgICAgICAgIGNhc2UgXCJjYWxsZWRPbmNlXCI6XG4gICAgICAgICAgICBjYXNlIFwiY2FsbGVkVHdpY2VcIjpcbiAgICAgICAgICAgIGNhc2UgXCJjYWxsZWRUaHJpY2VcIjpcbiAgICAgICAgICAgICAgICBpZiAoYXNzZXJ0aW9uQXJncy5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmZhaWwoXG4gICAgICAgICAgICAgICAgICAgICAgICBgJHthc3NlcnRpb25NZXRob2R9IHRha2VzIDEgYXJndW1lbnQgYnV0IHdhcyBjYWxsZWQgd2l0aCAke1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2VydGlvbkFyZ3MubGVuZ3RoICsgMVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBhcmd1bWVudHNgLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmYWlsQXNzZXJ0aW9uKG9iamVjdCwgbXNnKSB7XG4gICAgICAgIGNvbnN0IG9iaiA9IG9iamVjdCB8fCBnbG9iYWxPYmplY3Q7XG4gICAgICAgIGNvbnN0IGZhaWxNZXRob2QgPSBvYmouZmFpbCB8fCBhc3NlcnQuZmFpbDtcbiAgICAgICAgZmFpbE1ldGhvZC5jYWxsKG9iaiwgbXNnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtaXJyb3JQcm9wQXNBc3NlcnRpb24obmFtZSwgbWV0aG9kLCBtZXNzYWdlKSB7XG4gICAgICAgIGxldCBtc2cgPSBtZXNzYWdlO1xuICAgICAgICBsZXQgbWV0aCA9IG1ldGhvZDtcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICAgIG1zZyA9IG1ldGhvZDtcbiAgICAgICAgICAgIG1ldGggPSBuYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgYXNzZXJ0W25hbWVdID0gZnVuY3Rpb24gKGZha2UpIHtcbiAgICAgICAgICAgIHZlcmlmeUlzU3R1YihmYWtlKTtcblxuICAgICAgICAgICAgY29uc3QgYXJncyA9IGFycmF5U2xpY2UoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgICAgIGxldCBmYWlsZWQgPSBmYWxzZTtcblxuICAgICAgICAgICAgdmVyaWZ5SXNWYWxpZEFzc2VydGlvbihuYW1lLCBhcmdzKTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXRoID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICBmYWlsZWQgPSAhbWV0aChmYWtlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZmFpbGVkID1cbiAgICAgICAgICAgICAgICAgICAgdHlwZW9mIGZha2VbbWV0aF0gPT09IFwiZnVuY3Rpb25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgPyAhZmFrZVttZXRoXS5hcHBseShmYWtlLCBhcmdzKVxuICAgICAgICAgICAgICAgICAgICAgICAgOiAhZmFrZVttZXRoXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGZhaWxlZCkge1xuICAgICAgICAgICAgICAgIGZhaWxBc3NlcnRpb24oXG4gICAgICAgICAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICAgICAgICAgIChmYWtlLnByaW50ZiB8fCBmYWtlLnByb3h5LnByaW50ZikuYXBwbHkoXG4gICAgICAgICAgICAgICAgICAgICAgICBmYWtlLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29uY2F0KFttc2ddLCBhcmdzKSxcbiAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQucGFzcyhuYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBleHBvc2VkTmFtZShwcmVmaXgsIHByb3ApIHtcbiAgICAgICAgcmV0dXJuICFwcmVmaXggfHwgL15mYWlsLy50ZXN0KHByb3ApXG4gICAgICAgICAgICA/IHByb3BcbiAgICAgICAgICAgIDogcHJlZml4ICtcbiAgICAgICAgICAgICAgICAgIHN0cmluZ1NsaWNlKHByb3AsIDAsIDEpLnRvVXBwZXJDYXNlKCkgK1xuICAgICAgICAgICAgICAgICAgc3RyaW5nU2xpY2UocHJvcCwgMSk7XG4gICAgfVxuXG4gICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFxuICAgICAgICBcImNhbGxlZFwiLFxuICAgICAgICBcImV4cGVjdGVkICVuIHRvIGhhdmUgYmVlbiBjYWxsZWQgYXQgbGVhc3Qgb25jZSBidXQgd2FzIG5ldmVyIGNhbGxlZFwiLFxuICAgICk7XG4gICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFxuICAgICAgICBcIm5vdENhbGxlZFwiLFxuICAgICAgICBmdW5jdGlvbiAoc3B5KSB7XG4gICAgICAgICAgICByZXR1cm4gIXNweS5jYWxsZWQ7XG4gICAgICAgIH0sXG4gICAgICAgIFwiZXhwZWN0ZWQgJW4gdG8gbm90IGhhdmUgYmVlbiBjYWxsZWQgYnV0IHdhcyBjYWxsZWQgJWMlQ1wiLFxuICAgICk7XG4gICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFxuICAgICAgICBcImNhbGxlZE9uY2VcIixcbiAgICAgICAgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgb25jZSBidXQgd2FzIGNhbGxlZCAlYyVDXCIsXG4gICAgKTtcbiAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXG4gICAgICAgIFwiY2FsbGVkVHdpY2VcIixcbiAgICAgICAgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgdHdpY2UgYnV0IHdhcyBjYWxsZWQgJWMlQ1wiLFxuICAgICk7XG4gICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFxuICAgICAgICBcImNhbGxlZFRocmljZVwiLFxuICAgICAgICBcImV4cGVjdGVkICVuIHRvIGJlIGNhbGxlZCB0aHJpY2UgYnV0IHdhcyBjYWxsZWQgJWMlQ1wiLFxuICAgICk7XG4gICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFxuICAgICAgICBcImNhbGxlZE9uXCIsXG4gICAgICAgIFwiZXhwZWN0ZWQgJW4gdG8gYmUgY2FsbGVkIHdpdGggJTEgYXMgdGhpcyBidXQgd2FzIGNhbGxlZCB3aXRoICV0XCIsXG4gICAgKTtcbiAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXG4gICAgICAgIFwiYWx3YXlzQ2FsbGVkT25cIixcbiAgICAgICAgXCJleHBlY3RlZCAlbiB0byBhbHdheXMgYmUgY2FsbGVkIHdpdGggJTEgYXMgdGhpcyBidXQgd2FzIGNhbGxlZCB3aXRoICV0XCIsXG4gICAgKTtcbiAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJjYWxsZWRXaXRoTmV3XCIsIFwiZXhwZWN0ZWQgJW4gdG8gYmUgY2FsbGVkIHdpdGggbmV3XCIpO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcbiAgICAgICAgXCJhbHdheXNDYWxsZWRXaXRoTmV3XCIsXG4gICAgICAgIFwiZXhwZWN0ZWQgJW4gdG8gYWx3YXlzIGJlIGNhbGxlZCB3aXRoIG5ld1wiLFxuICAgICk7XG4gICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFxuICAgICAgICBcImNhbGxlZFdpdGhcIixcbiAgICAgICAgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgd2l0aCBhcmd1bWVudHMgJURcIixcbiAgICApO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcbiAgICAgICAgXCJjYWxsZWRXaXRoTWF0Y2hcIixcbiAgICAgICAgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgd2l0aCBtYXRjaCAlRFwiLFxuICAgICk7XG4gICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFxuICAgICAgICBcImFsd2F5c0NhbGxlZFdpdGhcIixcbiAgICAgICAgXCJleHBlY3RlZCAlbiB0byBhbHdheXMgYmUgY2FsbGVkIHdpdGggYXJndW1lbnRzICVEXCIsXG4gICAgKTtcbiAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXG4gICAgICAgIFwiYWx3YXlzQ2FsbGVkV2l0aE1hdGNoXCIsXG4gICAgICAgIFwiZXhwZWN0ZWQgJW4gdG8gYWx3YXlzIGJlIGNhbGxlZCB3aXRoIG1hdGNoICVEXCIsXG4gICAgKTtcbiAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXG4gICAgICAgIFwiY2FsbGVkV2l0aEV4YWN0bHlcIixcbiAgICAgICAgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgd2l0aCBleGFjdCBhcmd1bWVudHMgJURcIixcbiAgICApO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcbiAgICAgICAgXCJjYWxsZWRPbmNlV2l0aEV4YWN0bHlcIixcbiAgICAgICAgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgb25jZSBhbmQgd2l0aCBleGFjdCBhcmd1bWVudHMgJURcIixcbiAgICApO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcbiAgICAgICAgXCJjYWxsZWRPbmNlV2l0aE1hdGNoXCIsXG4gICAgICAgIFwiZXhwZWN0ZWQgJW4gdG8gYmUgY2FsbGVkIG9uY2UgYW5kIHdpdGggbWF0Y2ggJURcIixcbiAgICApO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcbiAgICAgICAgXCJhbHdheXNDYWxsZWRXaXRoRXhhY3RseVwiLFxuICAgICAgICBcImV4cGVjdGVkICVuIHRvIGFsd2F5cyBiZSBjYWxsZWQgd2l0aCBleGFjdCBhcmd1bWVudHMgJURcIixcbiAgICApO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcbiAgICAgICAgXCJuZXZlckNhbGxlZFdpdGhcIixcbiAgICAgICAgXCJleHBlY3RlZCAlbiB0byBuZXZlciBiZSBjYWxsZWQgd2l0aCBhcmd1bWVudHMgJSolQ1wiLFxuICAgICk7XG4gICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFxuICAgICAgICBcIm5ldmVyQ2FsbGVkV2l0aE1hdGNoXCIsXG4gICAgICAgIFwiZXhwZWN0ZWQgJW4gdG8gbmV2ZXIgYmUgY2FsbGVkIHdpdGggbWF0Y2ggJSolQ1wiLFxuICAgICk7XG4gICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwidGhyZXdcIiwgXCIlbiBkaWQgbm90IHRocm93IGV4Y2VwdGlvbiVDXCIpO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImFsd2F5c1RocmV3XCIsIFwiJW4gZGlkIG5vdCBhbHdheXMgdGhyb3cgZXhjZXB0aW9uJUNcIik7XG5cbiAgICByZXR1cm4gYXNzZXJ0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUFzc2VydE9iamVjdCgpO1xubW9kdWxlLmV4cG9ydHMuY3JlYXRlQXNzZXJ0T2JqZWN0ID0gY3JlYXRlQXNzZXJ0T2JqZWN0O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IGFycmF5UHJvdG8gPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLmFycmF5O1xuY29uc3QgZXh0ZW5kID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlL2V4dGVuZFwiKTtcbmNvbnN0IGZ1bmN0aW9uTmFtZSA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLmZ1bmN0aW9uTmFtZTtcbmNvbnN0IG5leHRUaWNrID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlL25leHQtdGlja1wiKTtcbmNvbnN0IHZhbHVlVG9TdHJpbmcgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS52YWx1ZVRvU3RyaW5nO1xuY29uc3QgZXhwb3J0QXN5bmNCZWhhdmlvcnMgPSByZXF1aXJlKFwiLi91dGlsL2NvcmUvZXhwb3J0LWFzeW5jLWJlaGF2aW9yc1wiKTtcblxuY29uc3QgY29uY2F0ID0gYXJyYXlQcm90by5jb25jYXQ7XG5jb25zdCBqb2luID0gYXJyYXlQcm90by5qb2luO1xuY29uc3QgcmV2ZXJzZSA9IGFycmF5UHJvdG8ucmV2ZXJzZTtcbmNvbnN0IHNsaWNlID0gYXJyYXlQcm90by5zbGljZTtcblxuY29uc3QgdXNlTGVmdE1vc3RDYWxsYmFjayA9IC0xO1xuY29uc3QgdXNlUmlnaHRNb3N0Q2FsbGJhY2sgPSAtMjtcblxuZnVuY3Rpb24gZ2V0Q2FsbGJhY2soYmVoYXZpb3IsIGFyZ3MpIHtcbiAgICBjb25zdCBjYWxsQXJnQXQgPSBiZWhhdmlvci5jYWxsQXJnQXQ7XG5cbiAgICBpZiAoY2FsbEFyZ0F0ID49IDApIHtcbiAgICAgICAgcmV0dXJuIGFyZ3NbY2FsbEFyZ0F0XTtcbiAgICB9XG5cbiAgICBsZXQgYXJndW1lbnRMaXN0O1xuXG4gICAgaWYgKGNhbGxBcmdBdCA9PT0gdXNlTGVmdE1vc3RDYWxsYmFjaykge1xuICAgICAgICBhcmd1bWVudExpc3QgPSBhcmdzO1xuICAgIH1cblxuICAgIGlmIChjYWxsQXJnQXQgPT09IHVzZVJpZ2h0TW9zdENhbGxiYWNrKSB7XG4gICAgICAgIGFyZ3VtZW50TGlzdCA9IHJldmVyc2Uoc2xpY2UoYXJncykpO1xuICAgIH1cblxuICAgIGNvbnN0IGNhbGxBcmdQcm9wID0gYmVoYXZpb3IuY2FsbEFyZ1Byb3A7XG5cbiAgICBmb3IgKGxldCBpID0gMCwgbCA9IGFyZ3VtZW50TGlzdC5sZW5ndGg7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgaWYgKCFjYWxsQXJnUHJvcCAmJiB0eXBlb2YgYXJndW1lbnRMaXN0W2ldID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBhcmd1bWVudExpc3RbaV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoXG4gICAgICAgICAgICBjYWxsQXJnUHJvcCAmJlxuICAgICAgICAgICAgYXJndW1lbnRMaXN0W2ldICYmXG4gICAgICAgICAgICB0eXBlb2YgYXJndW1lbnRMaXN0W2ldW2NhbGxBcmdQcm9wXSA9PT0gXCJmdW5jdGlvblwiXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIGFyZ3VtZW50TGlzdFtpXVtjYWxsQXJnUHJvcF07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbn1cblxuZnVuY3Rpb24gZ2V0Q2FsbGJhY2tFcnJvcihiZWhhdmlvciwgZnVuYywgYXJncykge1xuICAgIGlmIChiZWhhdmlvci5jYWxsQXJnQXQgPCAwKSB7XG4gICAgICAgIGxldCBtc2c7XG5cbiAgICAgICAgaWYgKGJlaGF2aW9yLmNhbGxBcmdQcm9wKSB7XG4gICAgICAgICAgICBtc2cgPSBgJHtmdW5jdGlvbk5hbWUoXG4gICAgICAgICAgICAgICAgYmVoYXZpb3Iuc3R1YixcbiAgICAgICAgICAgICl9IGV4cGVjdGVkIHRvIHlpZWxkIHRvICcke3ZhbHVlVG9TdHJpbmcoXG4gICAgICAgICAgICAgICAgYmVoYXZpb3IuY2FsbEFyZ1Byb3AsXG4gICAgICAgICAgICApfScsIGJ1dCBubyBvYmplY3Qgd2l0aCBzdWNoIGEgcHJvcGVydHkgd2FzIHBhc3NlZC5gO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbXNnID0gYCR7ZnVuY3Rpb25OYW1lKFxuICAgICAgICAgICAgICAgIGJlaGF2aW9yLnN0dWIsXG4gICAgICAgICAgICApfSBleHBlY3RlZCB0byB5aWVsZCwgYnV0IG5vIGNhbGxiYWNrIHdhcyBwYXNzZWQuYDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhcmdzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIG1zZyArPSBgIFJlY2VpdmVkIFske2pvaW4oYXJncywgXCIsIFwiKX1dYDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBtc2c7XG4gICAgfVxuXG4gICAgcmV0dXJuIGBhcmd1bWVudCBhdCBpbmRleCAke2JlaGF2aW9yLmNhbGxBcmdBdH0gaXMgbm90IGEgZnVuY3Rpb246ICR7ZnVuY31gO1xufVxuXG5mdW5jdGlvbiBlbnN1cmVBcmdzKG5hbWUsIGJlaGF2aW9yLCBhcmdzKSB7XG4gICAgLy8gbWFwIGZ1bmN0aW9uIG5hbWUgdG8gaW50ZXJuYWwgcHJvcGVydHlcbiAgICAvLyAgIGNhbGxzQXJnID0+IGNhbGxBcmdBdFxuICAgIGNvbnN0IHByb3BlcnR5ID0gbmFtZS5yZXBsYWNlKC9zQXJnLywgXCJBcmdBdFwiKTtcbiAgICBjb25zdCBpbmRleCA9IGJlaGF2aW9yW3Byb3BlcnR5XTtcblxuICAgIGlmIChpbmRleCA+PSBhcmdzLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgYCR7bmFtZX0gZmFpbGVkOiAke2luZGV4ICsgMX0gYXJndW1lbnRzIHJlcXVpcmVkIGJ1dCBvbmx5ICR7XG4gICAgICAgICAgICAgICAgYXJncy5sZW5ndGhcbiAgICAgICAgICAgIH0gcHJlc2VudGAsXG4gICAgICAgICk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjYWxsQ2FsbGJhY2soYmVoYXZpb3IsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIGJlaGF2aW9yLmNhbGxBcmdBdCA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICBlbnN1cmVBcmdzKFwiY2FsbHNBcmdcIiwgYmVoYXZpb3IsIGFyZ3MpO1xuICAgICAgICBjb25zdCBmdW5jID0gZ2V0Q2FsbGJhY2soYmVoYXZpb3IsIGFyZ3MpO1xuXG4gICAgICAgIGlmICh0eXBlb2YgZnVuYyAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGdldENhbGxiYWNrRXJyb3IoYmVoYXZpb3IsIGZ1bmMsIGFyZ3MpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChiZWhhdmlvci5jYWxsYmFja0FzeW5jKSB7XG4gICAgICAgICAgICBuZXh0VGljayhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgZnVuYy5hcHBseShcbiAgICAgICAgICAgICAgICAgICAgYmVoYXZpb3IuY2FsbGJhY2tDb250ZXh0LFxuICAgICAgICAgICAgICAgICAgICBiZWhhdmlvci5jYWxsYmFja0FyZ3VtZW50cyxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuYy5hcHBseShcbiAgICAgICAgICAgICAgICBiZWhhdmlvci5jYWxsYmFja0NvbnRleHQsXG4gICAgICAgICAgICAgICAgYmVoYXZpb3IuY2FsbGJhY2tBcmd1bWVudHMsXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuY29uc3QgcHJvdG8gPSB7XG4gICAgY3JlYXRlOiBmdW5jdGlvbiBjcmVhdGUoc3R1Yikge1xuICAgICAgICBjb25zdCBiZWhhdmlvciA9IGV4dGVuZCh7fSwgcHJvdG8pO1xuICAgICAgICBkZWxldGUgYmVoYXZpb3IuY3JlYXRlO1xuICAgICAgICBkZWxldGUgYmVoYXZpb3IuYWRkQmVoYXZpb3I7XG4gICAgICAgIGRlbGV0ZSBiZWhhdmlvci5jcmVhdGVCZWhhdmlvcjtcbiAgICAgICAgYmVoYXZpb3Iuc3R1YiA9IHN0dWI7XG5cbiAgICAgICAgaWYgKHN0dWIuZGVmYXVsdEJlaGF2aW9yICYmIHN0dWIuZGVmYXVsdEJlaGF2aW9yLnByb21pc2VMaWJyYXJ5KSB7XG4gICAgICAgICAgICBiZWhhdmlvci5wcm9taXNlTGlicmFyeSA9IHN0dWIuZGVmYXVsdEJlaGF2aW9yLnByb21pc2VMaWJyYXJ5O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGJlaGF2aW9yO1xuICAgIH0sXG5cbiAgICBpc1ByZXNlbnQ6IGZ1bmN0aW9uIGlzUHJlc2VudCgpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIHR5cGVvZiB0aGlzLmNhbGxBcmdBdCA9PT0gXCJudW1iZXJcIiB8fFxuICAgICAgICAgICAgdGhpcy5leGNlcHRpb24gfHxcbiAgICAgICAgICAgIHRoaXMuZXhjZXB0aW9uQ3JlYXRvciB8fFxuICAgICAgICAgICAgdHlwZW9mIHRoaXMucmV0dXJuQXJnQXQgPT09IFwibnVtYmVyXCIgfHxcbiAgICAgICAgICAgIHRoaXMucmV0dXJuVGhpcyB8fFxuICAgICAgICAgICAgdHlwZW9mIHRoaXMucmVzb2x2ZUFyZ0F0ID09PSBcIm51bWJlclwiIHx8XG4gICAgICAgICAgICB0aGlzLnJlc29sdmVUaGlzIHx8XG4gICAgICAgICAgICB0eXBlb2YgdGhpcy50aHJvd0FyZ0F0ID09PSBcIm51bWJlclwiIHx8XG4gICAgICAgICAgICB0aGlzLmZha2VGbiB8fFxuICAgICAgICAgICAgdGhpcy5yZXR1cm5WYWx1ZURlZmluZWRcbiAgICAgICAgKTtcbiAgICB9LFxuXG4gICAgLyplc2xpbnQgY29tcGxleGl0eTogW1wiZXJyb3JcIiwgMjBdKi9cbiAgICBpbnZva2U6IGZ1bmN0aW9uIGludm9rZShjb250ZXh0LCBhcmdzKSB7XG4gICAgICAgIC8qXG4gICAgICAgICAqIGNhbGxDYWxsYmFjayAoY29uZGl0aW9uYWxseSkgY2FsbHMgZW5zdXJlQXJnc1xuICAgICAgICAgKlxuICAgICAgICAgKiBOb3RlOiBjYWxsQ2FsbGJhY2sgaW50ZW50aW9uYWxseSBoYXBwZW5zIGJlZm9yZVxuICAgICAgICAgKiBldmVyeXRoaW5nIGVsc2UgYW5kIGNhbm5vdCBiZSBtb3ZlZCBsb3dlclxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3QgcmV0dXJuVmFsdWUgPSBjYWxsQ2FsbGJhY2sodGhpcywgYXJncyk7XG5cbiAgICAgICAgaWYgKHRoaXMuZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICB0aHJvdyB0aGlzLmV4Y2VwdGlvbjtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmV4Y2VwdGlvbkNyZWF0b3IpIHtcbiAgICAgICAgICAgIHRoaXMuZXhjZXB0aW9uID0gdGhpcy5leGNlcHRpb25DcmVhdG9yKCk7XG4gICAgICAgICAgICB0aGlzLmV4Y2VwdGlvbkNyZWF0b3IgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aHJvdyB0aGlzLmV4Y2VwdGlvbjtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpcy5yZXR1cm5BcmdBdCA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgZW5zdXJlQXJncyhcInJldHVybnNBcmdcIiwgdGhpcywgYXJncyk7XG4gICAgICAgICAgICByZXR1cm4gYXJnc1t0aGlzLnJldHVybkFyZ0F0XTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnJldHVyblRoaXMpIHtcbiAgICAgICAgICAgIHJldHVybiBjb250ZXh0O1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGlzLnRocm93QXJnQXQgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgIGVuc3VyZUFyZ3MoXCJ0aHJvd3NBcmdcIiwgdGhpcywgYXJncyk7XG4gICAgICAgICAgICB0aHJvdyBhcmdzW3RoaXMudGhyb3dBcmdBdF07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5mYWtlRm4pIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmZha2VGbi5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpcy5yZXNvbHZlQXJnQXQgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgIGVuc3VyZUFyZ3MoXCJyZXNvbHZlc0FyZ1wiLCB0aGlzLCBhcmdzKTtcbiAgICAgICAgICAgIHJldHVybiAodGhpcy5wcm9taXNlTGlicmFyeSB8fCBQcm9taXNlKS5yZXNvbHZlKFxuICAgICAgICAgICAgICAgIGFyZ3NbdGhpcy5yZXNvbHZlQXJnQXRdLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnJlc29sdmVUaGlzKSB7XG4gICAgICAgICAgICByZXR1cm4gKHRoaXMucHJvbWlzZUxpYnJhcnkgfHwgUHJvbWlzZSkucmVzb2x2ZShjb250ZXh0KTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnJlc29sdmUpIHtcbiAgICAgICAgICAgIHJldHVybiAodGhpcy5wcm9taXNlTGlicmFyeSB8fCBQcm9taXNlKS5yZXNvbHZlKHRoaXMucmV0dXJuVmFsdWUpO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMucmVqZWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gKHRoaXMucHJvbWlzZUxpYnJhcnkgfHwgUHJvbWlzZSkucmVqZWN0KHRoaXMucmV0dXJuVmFsdWUpO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuY2FsbHNUaHJvdWdoKSB7XG4gICAgICAgICAgICBjb25zdCB3cmFwcGVkTWV0aG9kID0gdGhpcy5lZmZlY3RpdmVXcmFwcGVkTWV0aG9kKCk7XG5cbiAgICAgICAgICAgIHJldHVybiB3cmFwcGVkTWV0aG9kLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuY2FsbHNUaHJvdWdoV2l0aE5ldykge1xuICAgICAgICAgICAgLy8gR2V0IHRoZSBvcmlnaW5hbCBtZXRob2QgKGFzc3VtZWQgdG8gYmUgYSBjb25zdHJ1Y3RvciBpbiB0aGlzIGNhc2UpXG4gICAgICAgICAgICBjb25zdCBXcmFwcGVkQ2xhc3MgPSB0aGlzLmVmZmVjdGl2ZVdyYXBwZWRNZXRob2QoKTtcbiAgICAgICAgICAgIC8vIFR1cm4gdGhlIGFyZ3VtZW50cyBvYmplY3QgaW50byBhIG5vcm1hbCBhcnJheVxuICAgICAgICAgICAgY29uc3QgYXJnc0FycmF5ID0gc2xpY2UoYXJncyk7XG4gICAgICAgICAgICAvLyBDYWxsIHRoZSBjb25zdHJ1Y3RvclxuICAgICAgICAgICAgY29uc3QgRiA9IFdyYXBwZWRDbGFzcy5iaW5kLmFwcGx5KFxuICAgICAgICAgICAgICAgIFdyYXBwZWRDbGFzcyxcbiAgICAgICAgICAgICAgICBjb25jYXQoW251bGxdLCBhcmdzQXJyYXkpLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRigpO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGlzLnJldHVyblZhbHVlICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZXR1cm5WYWx1ZTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpcy5jYWxsQXJnQXQgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLnJldHVyblZhbHVlO1xuICAgIH0sXG5cbiAgICBlZmZlY3RpdmVXcmFwcGVkTWV0aG9kOiBmdW5jdGlvbiBlZmZlY3RpdmVXcmFwcGVkTWV0aG9kKCkge1xuICAgICAgICBmb3IgKGxldCBzdHViYiA9IHRoaXMuc3R1Yjsgc3R1YmI7IHN0dWJiID0gc3R1YmIucGFyZW50KSB7XG4gICAgICAgICAgICBpZiAoc3R1YmIud3JhcHBlZE1ldGhvZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzdHViYi53cmFwcGVkTWV0aG9kO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuYWJsZSB0byBmaW5kIHdyYXBwZWQgbWV0aG9kXCIpO1xuICAgIH0sXG5cbiAgICBvbkNhbGw6IGZ1bmN0aW9uIG9uQ2FsbChpbmRleCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdHViLm9uQ2FsbChpbmRleCk7XG4gICAgfSxcblxuICAgIG9uRmlyc3RDYWxsOiBmdW5jdGlvbiBvbkZpcnN0Q2FsbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3R1Yi5vbkZpcnN0Q2FsbCgpO1xuICAgIH0sXG5cbiAgICBvblNlY29uZENhbGw6IGZ1bmN0aW9uIG9uU2Vjb25kQ2FsbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3R1Yi5vblNlY29uZENhbGwoKTtcbiAgICB9LFxuXG4gICAgb25UaGlyZENhbGw6IGZ1bmN0aW9uIG9uVGhpcmRDYWxsKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdHViLm9uVGhpcmRDYWxsKCk7XG4gICAgfSxcblxuICAgIHdpdGhBcmdzOiBmdW5jdGlvbiB3aXRoQXJncygvKiBhcmd1bWVudHMgKi8pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgJ0RlZmluaW5nIGEgc3R1YiBieSBpbnZva2luZyBcInN0dWIub25DYWxsKC4uLikud2l0aEFyZ3MoLi4uKVwiICcgK1xuICAgICAgICAgICAgICAgICdpcyBub3Qgc3VwcG9ydGVkLiBVc2UgXCJzdHViLndpdGhBcmdzKC4uLikub25DYWxsKC4uLilcIiAnICtcbiAgICAgICAgICAgICAgICBcInRvIGRlZmluZSBzZXF1ZW50aWFsIGJlaGF2aW9yIGZvciBjYWxscyB3aXRoIGNlcnRhaW4gYXJndW1lbnRzLlwiLFxuICAgICAgICApO1xuICAgIH0sXG59O1xuXG5mdW5jdGlvbiBjcmVhdGVCZWhhdmlvcihiZWhhdmlvck1ldGhvZCkge1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZGVmYXVsdEJlaGF2aW9yID0gdGhpcy5kZWZhdWx0QmVoYXZpb3IgfHwgcHJvdG8uY3JlYXRlKHRoaXMpO1xuICAgICAgICB0aGlzLmRlZmF1bHRCZWhhdmlvcltiZWhhdmlvck1ldGhvZF0uYXBwbHkoXG4gICAgICAgICAgICB0aGlzLmRlZmF1bHRCZWhhdmlvcixcbiAgICAgICAgICAgIGFyZ3VtZW50cyxcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gYWRkQmVoYXZpb3Ioc3R1YiwgbmFtZSwgZm4pIHtcbiAgICBwcm90b1tuYW1lXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZm4uYXBwbHkodGhpcywgY29uY2F0KFt0aGlzXSwgc2xpY2UoYXJndW1lbnRzKSkpO1xuICAgICAgICByZXR1cm4gdGhpcy5zdHViIHx8IHRoaXM7XG4gICAgfTtcblxuICAgIHN0dWJbbmFtZV0gPSBjcmVhdGVCZWhhdmlvcihuYW1lKTtcbn1cblxucHJvdG8uYWRkQmVoYXZpb3IgPSBhZGRCZWhhdmlvcjtcbnByb3RvLmNyZWF0ZUJlaGF2aW9yID0gY3JlYXRlQmVoYXZpb3I7XG5cbmNvbnN0IGFzeW5jQmVoYXZpb3JzID0gZXhwb3J0QXN5bmNCZWhhdmlvcnMocHJvdG8pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGV4dGVuZC5ub25FbnVtKHt9LCBwcm90bywgYXN5bmNCZWhhdmlvcnMpO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IHdhbGsgPSByZXF1aXJlKFwiLi91dGlsL2NvcmUvd2Fsa1wiKTtcbmNvbnN0IGdldFByb3BlcnR5RGVzY3JpcHRvciA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZS9nZXQtcHJvcGVydHktZGVzY3JpcHRvclwiKTtcbmNvbnN0IGhhc093blByb3BlcnR5ID1cbiAgICByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLm9iamVjdC5oYXNPd25Qcm9wZXJ0eTtcbmNvbnN0IHB1c2ggPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLmFycmF5LnB1c2g7XG5cbmZ1bmN0aW9uIGNvbGxlY3RNZXRob2QobWV0aG9kcywgb2JqZWN0LCBwcm9wLCBwcm9wT3duZXIpIHtcbiAgICBpZiAoXG4gICAgICAgIHR5cGVvZiBnZXRQcm9wZXJ0eURlc2NyaXB0b3IocHJvcE93bmVyLCBwcm9wKS52YWx1ZSA9PT0gXCJmdW5jdGlvblwiICYmXG4gICAgICAgIGhhc093blByb3BlcnR5KG9iamVjdCwgcHJvcClcbiAgICApIHtcbiAgICAgICAgcHVzaChtZXRob2RzLCBvYmplY3RbcHJvcF0pO1xuICAgIH1cbn1cblxuLy8gVGhpcyBmdW5jdGlvbiByZXR1cm5zIGFuIGFycmF5IG9mIGFsbCB0aGUgb3duIG1ldGhvZHMgb24gdGhlIHBhc3NlZCBvYmplY3RcbmZ1bmN0aW9uIGNvbGxlY3RPd25NZXRob2RzKG9iamVjdCkge1xuICAgIGNvbnN0IG1ldGhvZHMgPSBbXTtcblxuICAgIHdhbGsob2JqZWN0LCBjb2xsZWN0TWV0aG9kLmJpbmQobnVsbCwgbWV0aG9kcywgb2JqZWN0KSk7XG5cbiAgICByZXR1cm4gbWV0aG9kcztcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjb2xsZWN0T3duTWV0aG9kcztcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsYXNzIENvbG9yaXplciB7XG4gICAgY29uc3RydWN0b3Ioc3VwcG9ydHNDb2xvciA9IHJlcXVpcmUoXCJzdXBwb3J0cy1jb2xvclwiKSkge1xuICAgICAgICB0aGlzLnN1cHBvcnRzQ29sb3IgPSBzdXBwb3J0c0NvbG9yO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNob3VsZCBiZSByZW5hbWVkIHRvIHRydWUgI3ByaXZhdGVGaWVsZFxuICAgICAqIHdoZW4gd2UgY2FuIGVuc3VyZSBFUzIwMjIgc3VwcG9ydFxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBjb2xvcml6ZShzdHIsIGNvbG9yKSB7XG4gICAgICAgIGlmICh0aGlzLnN1cHBvcnRzQ29sb3Iuc3Rkb3V0ID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuIHN0cjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBgXFx4MWJbJHtjb2xvcn1tJHtzdHJ9XFx4MWJbMG1gO1xuICAgIH1cblxuICAgIHJlZChzdHIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29sb3JpemUoc3RyLCAzMSk7XG4gICAgfVxuXG4gICAgZ3JlZW4oc3RyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbG9yaXplKHN0ciwgMzIpO1xuICAgIH1cblxuICAgIGN5YW4oc3RyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbG9yaXplKHN0ciwgOTYpO1xuICAgIH1cblxuICAgIHdoaXRlKHN0cikge1xuICAgICAgICByZXR1cm4gdGhpcy5jb2xvcml6ZShzdHIsIDM5KTtcbiAgICB9XG5cbiAgICBib2xkKHN0cikge1xuICAgICAgICByZXR1cm4gdGhpcy5jb2xvcml6ZShzdHIsIDEpO1xuICAgIH1cbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuY29uc3QgYXJyYXlQcm90byA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnByb3RvdHlwZXMuYXJyYXk7XG5jb25zdCBTYW5kYm94ID0gcmVxdWlyZShcIi4vc2FuZGJveFwiKTtcblxuY29uc3QgZm9yRWFjaCA9IGFycmF5UHJvdG8uZm9yRWFjaDtcbmNvbnN0IHB1c2ggPSBhcnJheVByb3RvLnB1c2g7XG5cbmZ1bmN0aW9uIHByZXBhcmVTYW5kYm94RnJvbUNvbmZpZyhjb25maWcpIHtcbiAgICBjb25zdCBzYW5kYm94ID0gbmV3IFNhbmRib3goeyBhc3NlcnRPcHRpb25zOiBjb25maWcuYXNzZXJ0T3B0aW9ucyB9KTtcblxuICAgIGlmIChjb25maWcudXNlRmFrZVRpbWVycykge1xuICAgICAgICBpZiAodHlwZW9mIGNvbmZpZy51c2VGYWtlVGltZXJzID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICBzYW5kYm94LnVzZUZha2VUaW1lcnMoY29uZmlnLnVzZUZha2VUaW1lcnMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2FuZGJveC51c2VGYWtlVGltZXJzKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gc2FuZGJveDtcbn1cblxuZnVuY3Rpb24gZXhwb3NlVmFsdWUoc2FuZGJveCwgY29uZmlnLCBrZXksIHZhbHVlKSB7XG4gICAgaWYgKCF2YWx1ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGNvbmZpZy5pbmplY3RJbnRvICYmICEoa2V5IGluIGNvbmZpZy5pbmplY3RJbnRvKSkge1xuICAgICAgICBjb25maWcuaW5qZWN0SW50b1trZXldID0gdmFsdWU7XG4gICAgICAgIHB1c2goc2FuZGJveC5pbmplY3RlZEtleXMsIGtleSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcHVzaChzYW5kYm94LmFyZ3MsIHZhbHVlKTtcbiAgICB9XG59XG5cbi8qKlxuICogT3B0aW9ucyB0byBjdXN0b21pemUgYSBzYW5kYm94XG4gKlxuICogVGhlIHNhbmRib3gncyBtZXRob2RzIGNhbiBiZSBpbmplY3RlZCBpbnRvIGFub3RoZXIgb2JqZWN0IGZvclxuICogY29udmVuaWVuY2UuIFRoZSBgaW5qZWN0SW50b2AgY29uZmlndXJhdGlvbiBvcHRpb24gY2FuIG5hbWUgYW5cbiAqIG9iamVjdCB0byBhZGQgcHJvcGVydGllcyB0by5cbiAqXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBTYW5kYm94Q29uZmlnXG4gKiBAcHJvcGVydHkge3N0cmluZ1tdfSBwcm9wZXJ0aWVzIFRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBBUEkgdG8gZXhwb3NlIG9uIHRoZSBzYW5kYm94LiBFeGFtcGxlczogWydzcHknLCAnZmFrZScsICdyZXN0b3JlJ11cbiAqIEBwcm9wZXJ0eSB7b2JqZWN0fSBpbmplY3RJbnRvIGFuIG9iamVjdCBpbiB3aGljaCB0byBpbmplY3QgcHJvcGVydGllcyBmcm9tIHRoZSBzYW5kYm94IChhIGZhY2FkZSkuIFRoaXMgaXMgbW9zdGx5IGFuIGludGVncmF0aW9uIGZlYXR1cmUgKHNpbm9uLXRlc3QgYmVpbmcgb25lKS5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gdXNlRmFrZVRpbWVycyAgd2hldGhlciB0aW1lcnMgYXJlIGZha2VkIGJ5IGRlZmF1bHRcbiAqIEBwcm9wZXJ0eSB7b2JqZWN0fSBbYXNzZXJ0T3B0aW9uc10gc2VlIENyZWF0ZUFzc2VydE9wdGlvbnMgaW4gLi9hc3NlcnRcbiAqXG4gKiBUaGlzIHR5cGUgZGVmIGlzIHJlYWxseSBzdWZmZXJpbmcgZnJvbSBKU0RvYyBub3QgaGF2aW5nIHN0YW5kYXJkaXplZFxuICogaG93IHRvIHJlZmVyZW5jZSB0eXBlcyBkZWZpbmVkIGluIG90aGVyIG1vZHVsZXMgOihcbiAqL1xuXG4vKipcbiAqIEEgY29uZmlndXJlZCBzaW5vbiBzYW5kYm94IChwcml2YXRlIHR5cGUpXG4gKlxuICogQHR5cGVkZWYge29iamVjdH0gQ29uZmlndXJlZFNpbm9uU2FuZGJveFR5cGVcbiAqIEBwcml2YXRlXG4gKiBAYXVnbWVudHMgU2FuZGJveFxuICogQHByb3BlcnR5IHtzdHJpbmdbXX0gaW5qZWN0ZWRLZXlzIHRoZSBrZXlzIHRoYXQgaGF2ZSBiZWVuIGluamVjdGVkIChmcm9tIGNvbmZpZy5pbmplY3RJbnRvKVxuICogQHByb3BlcnR5IHsqW119IGFyZ3MgdGhlIGFyZ3VtZW50cyBmb3IgdGhlIHNhbmRib3hcbiAqL1xuXG4vKipcbiAqIENyZWF0ZSBhIHNhbmRib3hcbiAqXG4gKiBBcyBvZiBTaW5vbiA1IHRoZSBgc2lub25gIGluc3RhbmNlIGl0c2VsZiBpcyBhIFNhbmRib3gsIHNvIHlvdVxuICogaGFyZGx5IGV2ZXIgbmVlZCB0byBjcmVhdGUgYWRkaXRpb25hbCBpbnN0YW5jZXMgZm9yIHRoZSBzYWtlIG9mIHRlc3RpbmdcbiAqXG4gKiBAcGFyYW0gY29uZmlnIHtTYW5kYm94Q29uZmlnfVxuICogQHJldHVybnMge1NhbmRib3h9XG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVNhbmRib3goY29uZmlnKSB7XG4gICAgaWYgKCFjb25maWcpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBTYW5kYm94KCk7XG4gICAgfVxuXG4gICAgY29uc3QgY29uZmlndXJlZFNhbmRib3ggPSBwcmVwYXJlU2FuZGJveEZyb21Db25maWcoY29uZmlnKTtcbiAgICBjb25maWd1cmVkU2FuZGJveC5hcmdzID0gY29uZmlndXJlZFNhbmRib3guYXJncyB8fCBbXTtcbiAgICBjb25maWd1cmVkU2FuZGJveC5pbmplY3RlZEtleXMgPSBbXTtcbiAgICBjb25maWd1cmVkU2FuZGJveC5pbmplY3RJbnRvID0gY29uZmlnLmluamVjdEludG87XG4gICAgY29uc3QgZXhwb3NlZCA9IGNvbmZpZ3VyZWRTYW5kYm94LmluamVjdCh7fSk7XG5cbiAgICBpZiAoY29uZmlnLnByb3BlcnRpZXMpIHtcbiAgICAgICAgZm9yRWFjaChjb25maWcucHJvcGVydGllcywgZnVuY3Rpb24gKHByb3ApIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID1cbiAgICAgICAgICAgICAgICBleHBvc2VkW3Byb3BdIHx8IChwcm9wID09PSBcInNhbmRib3hcIiAmJiBjb25maWd1cmVkU2FuZGJveCk7XG4gICAgICAgICAgICBleHBvc2VWYWx1ZShjb25maWd1cmVkU2FuZGJveCwgY29uZmlnLCBwcm9wLCB2YWx1ZSk7XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGV4cG9zZVZhbHVlKGNvbmZpZ3VyZWRTYW5kYm94LCBjb25maWcsIFwic2FuZGJveFwiKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY29uZmlndXJlZFNhbmRib3g7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlU2FuZGJveDtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5jb25zdCBzdHViID0gcmVxdWlyZShcIi4vc3R1YlwiKTtcbmNvbnN0IHNpbm9uVHlwZSA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZS9zaW5vbi10eXBlXCIpO1xuY29uc3QgZm9yRWFjaCA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnByb3RvdHlwZXMuYXJyYXkuZm9yRWFjaDtcblxuZnVuY3Rpb24gaXNTdHViKHZhbHVlKSB7XG4gICAgcmV0dXJuIHNpbm9uVHlwZS5nZXQodmFsdWUpID09PSBcInN0dWJcIjtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcmVhdGVTdHViSW5zdGFuY2UoY29uc3RydWN0b3IsIG92ZXJyaWRlcykge1xuICAgIGlmICh0eXBlb2YgY29uc3RydWN0b3IgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiVGhlIGNvbnN0cnVjdG9yIHNob3VsZCBiZSBhIGZ1bmN0aW9uLlwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBzdHViSW5zdGFuY2UgPSBPYmplY3QuY3JlYXRlKGNvbnN0cnVjdG9yLnByb3RvdHlwZSk7XG4gICAgc2lub25UeXBlLnNldChzdHViSW5zdGFuY2UsIFwic3R1Yi1pbnN0YW5jZVwiKTtcblxuICAgIGNvbnN0IHN0dWJiZWRPYmplY3QgPSBzdHViKHN0dWJJbnN0YW5jZSk7XG5cbiAgICBmb3JFYWNoKE9iamVjdC5rZXlzKG92ZXJyaWRlcyB8fCB7fSksIGZ1bmN0aW9uIChwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgaWYgKHByb3BlcnR5TmFtZSBpbiBzdHViYmVkT2JqZWN0KSB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IG92ZXJyaWRlc1twcm9wZXJ0eU5hbWVdO1xuICAgICAgICAgICAgaWYgKGlzU3R1Yih2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICBzdHViYmVkT2JqZWN0W3Byb3BlcnR5TmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3R1YmJlZE9iamVjdFtwcm9wZXJ0eU5hbWVdLnJldHVybnModmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgIGBDYW5ub3Qgc3R1YiAke3Byb3BlcnR5TmFtZX0uIFByb3BlcnR5IGRvZXMgbm90IGV4aXN0IWAsXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHN0dWJiZWRPYmplY3Q7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IGFycmF5UHJvdG8gPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLmFycmF5O1xuY29uc3QgaXNQcm9wZXJ0eUNvbmZpZ3VyYWJsZSA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZS9pcy1wcm9wZXJ0eS1jb25maWd1cmFibGVcIik7XG5jb25zdCBleHBvcnRBc3luY0JlaGF2aW9ycyA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZS9leHBvcnQtYXN5bmMtYmVoYXZpb3JzXCIpO1xuY29uc3QgZXh0ZW5kID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlL2V4dGVuZFwiKTtcblxuY29uc3Qgc2xpY2UgPSBhcnJheVByb3RvLnNsaWNlO1xuXG5jb25zdCB1c2VMZWZ0TW9zdENhbGxiYWNrID0gLTE7XG5jb25zdCB1c2VSaWdodE1vc3RDYWxsYmFjayA9IC0yO1xuXG5mdW5jdGlvbiB0aHJvd3NFeGNlcHRpb24oZmFrZSwgZXJyb3IsIG1lc3NhZ2UpIHtcbiAgICBpZiAodHlwZW9mIGVycm9yID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgZmFrZS5leGNlcHRpb25DcmVhdG9yID0gZXJyb3I7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZXJyb3IgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgZmFrZS5leGNlcHRpb25DcmVhdG9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY29uc3QgbmV3RXhjZXB0aW9uID0gbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgIG1lc3NhZ2UgfHwgYFNpbm9uLXByb3ZpZGVkICR7ZXJyb3J9YCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBuZXdFeGNlcHRpb24ubmFtZSA9IGVycm9yO1xuICAgICAgICAgICAgcmV0dXJuIG5ld0V4Y2VwdGlvbjtcbiAgICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKCFlcnJvcikge1xuICAgICAgICBmYWtlLmV4Y2VwdGlvbkNyZWF0b3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEVycm9yKFwiRXJyb3JcIik7XG4gICAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZmFrZS5leGNlcHRpb24gPSBlcnJvcjtcbiAgICB9XG59XG5cbmNvbnN0IGRlZmF1bHRCZWhhdmlvcnMgPSB7XG4gICAgY2FsbHNGYWtlOiBmdW5jdGlvbiBjYWxsc0Zha2UoZmFrZSwgZm4pIHtcbiAgICAgICAgZmFrZS5mYWtlRm4gPSBmbjtcbiAgICAgICAgZmFrZS5leGNlcHRpb24gPSB1bmRlZmluZWQ7XG4gICAgICAgIGZha2UuZXhjZXB0aW9uQ3JlYXRvciA9IHVuZGVmaW5lZDtcbiAgICAgICAgZmFrZS5jYWxsc1Rocm91Z2ggPSBmYWxzZTtcbiAgICB9LFxuXG4gICAgY2FsbHNBcmc6IGZ1bmN0aW9uIGNhbGxzQXJnKGZha2UsIGluZGV4KSB7XG4gICAgICAgIGlmICh0eXBlb2YgaW5kZXggIT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBpbmRleCBpcyBub3QgbnVtYmVyXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZmFrZS5jYWxsQXJnQXQgPSBpbmRleDtcbiAgICAgICAgZmFrZS5jYWxsYmFja0FyZ3VtZW50cyA9IFtdO1xuICAgICAgICBmYWtlLmNhbGxiYWNrQ29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgZmFrZS5jYWxsQXJnUHJvcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgZmFrZS5jYWxsYmFja0FzeW5jID0gZmFsc2U7XG4gICAgICAgIGZha2UuY2FsbHNUaHJvdWdoID0gZmFsc2U7XG4gICAgfSxcblxuICAgIGNhbGxzQXJnT246IGZ1bmN0aW9uIGNhbGxzQXJnT24oZmFrZSwgaW5kZXgsIGNvbnRleHQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBpbmRleCAhPT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcImFyZ3VtZW50IGluZGV4IGlzIG5vdCBudW1iZXJcIik7XG4gICAgICAgIH1cblxuICAgICAgICBmYWtlLmNhbGxBcmdBdCA9IGluZGV4O1xuICAgICAgICBmYWtlLmNhbGxiYWNrQXJndW1lbnRzID0gW107XG4gICAgICAgIGZha2UuY2FsbGJhY2tDb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgZmFrZS5jYWxsQXJnUHJvcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgZmFrZS5jYWxsYmFja0FzeW5jID0gZmFsc2U7XG4gICAgICAgIGZha2UuY2FsbHNUaHJvdWdoID0gZmFsc2U7XG4gICAgfSxcblxuICAgIGNhbGxzQXJnV2l0aDogZnVuY3Rpb24gY2FsbHNBcmdXaXRoKGZha2UsIGluZGV4KSB7XG4gICAgICAgIGlmICh0eXBlb2YgaW5kZXggIT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBpbmRleCBpcyBub3QgbnVtYmVyXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgZmFrZS5jYWxsQXJnQXQgPSBpbmRleDtcbiAgICAgICAgZmFrZS5jYWxsYmFja0FyZ3VtZW50cyA9IHNsaWNlKGFyZ3VtZW50cywgMik7XG4gICAgICAgIGZha2UuY2FsbGJhY2tDb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgICBmYWtlLmNhbGxBcmdQcm9wID0gdW5kZWZpbmVkO1xuICAgICAgICBmYWtlLmNhbGxiYWNrQXN5bmMgPSBmYWxzZTtcbiAgICAgICAgZmFrZS5jYWxsc1Rocm91Z2ggPSBmYWxzZTtcbiAgICB9LFxuXG4gICAgY2FsbHNBcmdPbldpdGg6IGZ1bmN0aW9uIGNhbGxzQXJnV2l0aChmYWtlLCBpbmRleCwgY29udGV4dCkge1xuICAgICAgICBpZiAodHlwZW9mIGluZGV4ICE9PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiYXJndW1lbnQgaW5kZXggaXMgbm90IG51bWJlclwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZha2UuY2FsbEFyZ0F0ID0gaW5kZXg7XG4gICAgICAgIGZha2UuY2FsbGJhY2tBcmd1bWVudHMgPSBzbGljZShhcmd1bWVudHMsIDMpO1xuICAgICAgICBmYWtlLmNhbGxiYWNrQ29udGV4dCA9IGNvbnRleHQ7XG4gICAgICAgIGZha2UuY2FsbEFyZ1Byb3AgPSB1bmRlZmluZWQ7XG4gICAgICAgIGZha2UuY2FsbGJhY2tBc3luYyA9IGZhbHNlO1xuICAgICAgICBmYWtlLmNhbGxzVGhyb3VnaCA9IGZhbHNlO1xuICAgIH0sXG5cbiAgICB5aWVsZHM6IGZ1bmN0aW9uIChmYWtlKSB7XG4gICAgICAgIGZha2UuY2FsbEFyZ0F0ID0gdXNlTGVmdE1vc3RDYWxsYmFjaztcbiAgICAgICAgZmFrZS5jYWxsYmFja0FyZ3VtZW50cyA9IHNsaWNlKGFyZ3VtZW50cywgMSk7XG4gICAgICAgIGZha2UuY2FsbGJhY2tDb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgICBmYWtlLmNhbGxBcmdQcm9wID0gdW5kZWZpbmVkO1xuICAgICAgICBmYWtlLmNhbGxiYWNrQXN5bmMgPSBmYWxzZTtcbiAgICAgICAgZmFrZS5mYWtlRm4gPSB1bmRlZmluZWQ7XG4gICAgICAgIGZha2UuY2FsbHNUaHJvdWdoID0gZmFsc2U7XG4gICAgfSxcblxuICAgIHlpZWxkc1JpZ2h0OiBmdW5jdGlvbiAoZmFrZSkge1xuICAgICAgICBmYWtlLmNhbGxBcmdBdCA9IHVzZVJpZ2h0TW9zdENhbGxiYWNrO1xuICAgICAgICBmYWtlLmNhbGxiYWNrQXJndW1lbnRzID0gc2xpY2UoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgZmFrZS5jYWxsYmFja0NvbnRleHQgPSB1bmRlZmluZWQ7XG4gICAgICAgIGZha2UuY2FsbEFyZ1Byb3AgPSB1bmRlZmluZWQ7XG4gICAgICAgIGZha2UuY2FsbGJhY2tBc3luYyA9IGZhbHNlO1xuICAgICAgICBmYWtlLmNhbGxzVGhyb3VnaCA9IGZhbHNlO1xuICAgICAgICBmYWtlLmZha2VGbiA9IHVuZGVmaW5lZDtcbiAgICB9LFxuXG4gICAgeWllbGRzT246IGZ1bmN0aW9uIChmYWtlLCBjb250ZXh0KSB7XG4gICAgICAgIGZha2UuY2FsbEFyZ0F0ID0gdXNlTGVmdE1vc3RDYWxsYmFjaztcbiAgICAgICAgZmFrZS5jYWxsYmFja0FyZ3VtZW50cyA9IHNsaWNlKGFyZ3VtZW50cywgMik7XG4gICAgICAgIGZha2UuY2FsbGJhY2tDb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgZmFrZS5jYWxsQXJnUHJvcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgZmFrZS5jYWxsYmFja0FzeW5jID0gZmFsc2U7XG4gICAgICAgIGZha2UuY2FsbHNUaHJvdWdoID0gZmFsc2U7XG4gICAgICAgIGZha2UuZmFrZUZuID0gdW5kZWZpbmVkO1xuICAgIH0sXG5cbiAgICB5aWVsZHNUbzogZnVuY3Rpb24gKGZha2UsIHByb3ApIHtcbiAgICAgICAgZmFrZS5jYWxsQXJnQXQgPSB1c2VMZWZ0TW9zdENhbGxiYWNrO1xuICAgICAgICBmYWtlLmNhbGxiYWNrQXJndW1lbnRzID0gc2xpY2UoYXJndW1lbnRzLCAyKTtcbiAgICAgICAgZmFrZS5jYWxsYmFja0NvbnRleHQgPSB1bmRlZmluZWQ7XG4gICAgICAgIGZha2UuY2FsbEFyZ1Byb3AgPSBwcm9wO1xuICAgICAgICBmYWtlLmNhbGxiYWNrQXN5bmMgPSBmYWxzZTtcbiAgICAgICAgZmFrZS5jYWxsc1Rocm91Z2ggPSBmYWxzZTtcbiAgICAgICAgZmFrZS5mYWtlRm4gPSB1bmRlZmluZWQ7XG4gICAgfSxcblxuICAgIHlpZWxkc1RvT246IGZ1bmN0aW9uIChmYWtlLCBwcm9wLCBjb250ZXh0KSB7XG4gICAgICAgIGZha2UuY2FsbEFyZ0F0ID0gdXNlTGVmdE1vc3RDYWxsYmFjaztcbiAgICAgICAgZmFrZS5jYWxsYmFja0FyZ3VtZW50cyA9IHNsaWNlKGFyZ3VtZW50cywgMyk7XG4gICAgICAgIGZha2UuY2FsbGJhY2tDb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgZmFrZS5jYWxsQXJnUHJvcCA9IHByb3A7XG4gICAgICAgIGZha2UuY2FsbGJhY2tBc3luYyA9IGZhbHNlO1xuICAgICAgICBmYWtlLmZha2VGbiA9IHVuZGVmaW5lZDtcbiAgICB9LFxuXG4gICAgdGhyb3dzOiB0aHJvd3NFeGNlcHRpb24sXG4gICAgdGhyb3dzRXhjZXB0aW9uOiB0aHJvd3NFeGNlcHRpb24sXG5cbiAgICByZXR1cm5zOiBmdW5jdGlvbiByZXR1cm5zKGZha2UsIHZhbHVlKSB7XG4gICAgICAgIGZha2UuY2FsbHNUaHJvdWdoID0gZmFsc2U7XG4gICAgICAgIGZha2UucmV0dXJuVmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgZmFrZS5yZXNvbHZlID0gZmFsc2U7XG4gICAgICAgIGZha2UucmVqZWN0ID0gZmFsc2U7XG4gICAgICAgIGZha2UucmV0dXJuVmFsdWVEZWZpbmVkID0gdHJ1ZTtcbiAgICAgICAgZmFrZS5leGNlcHRpb24gPSB1bmRlZmluZWQ7XG4gICAgICAgIGZha2UuZXhjZXB0aW9uQ3JlYXRvciA9IHVuZGVmaW5lZDtcbiAgICAgICAgZmFrZS5mYWtlRm4gPSB1bmRlZmluZWQ7XG4gICAgfSxcblxuICAgIHJldHVybnNBcmc6IGZ1bmN0aW9uIHJldHVybnNBcmcoZmFrZSwgaW5kZXgpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBpbmRleCAhPT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcImFyZ3VtZW50IGluZGV4IGlzIG5vdCBudW1iZXJcIik7XG4gICAgICAgIH1cbiAgICAgICAgZmFrZS5jYWxsc1Rocm91Z2ggPSBmYWxzZTtcblxuICAgICAgICBmYWtlLnJldHVybkFyZ0F0ID0gaW5kZXg7XG4gICAgfSxcblxuICAgIHRocm93c0FyZzogZnVuY3Rpb24gdGhyb3dzQXJnKGZha2UsIGluZGV4KSB7XG4gICAgICAgIGlmICh0eXBlb2YgaW5kZXggIT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBpbmRleCBpcyBub3QgbnVtYmVyXCIpO1xuICAgICAgICB9XG4gICAgICAgIGZha2UuY2FsbHNUaHJvdWdoID0gZmFsc2U7XG5cbiAgICAgICAgZmFrZS50aHJvd0FyZ0F0ID0gaW5kZXg7XG4gICAgfSxcblxuICAgIHJldHVybnNUaGlzOiBmdW5jdGlvbiByZXR1cm5zVGhpcyhmYWtlKSB7XG4gICAgICAgIGZha2UucmV0dXJuVGhpcyA9IHRydWU7XG4gICAgICAgIGZha2UuY2FsbHNUaHJvdWdoID0gZmFsc2U7XG4gICAgfSxcblxuICAgIHJlc29sdmVzOiBmdW5jdGlvbiByZXNvbHZlcyhmYWtlLCB2YWx1ZSkge1xuICAgICAgICBmYWtlLnJldHVyblZhbHVlID0gdmFsdWU7XG4gICAgICAgIGZha2UucmVzb2x2ZSA9IHRydWU7XG4gICAgICAgIGZha2UucmVzb2x2ZVRoaXMgPSBmYWxzZTtcbiAgICAgICAgZmFrZS5yZWplY3QgPSBmYWxzZTtcbiAgICAgICAgZmFrZS5yZXR1cm5WYWx1ZURlZmluZWQgPSB0cnVlO1xuICAgICAgICBmYWtlLmV4Y2VwdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgZmFrZS5leGNlcHRpb25DcmVhdG9yID0gdW5kZWZpbmVkO1xuICAgICAgICBmYWtlLmZha2VGbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgZmFrZS5jYWxsc1Rocm91Z2ggPSBmYWxzZTtcbiAgICB9LFxuXG4gICAgcmVzb2x2ZXNBcmc6IGZ1bmN0aW9uIHJlc29sdmVzQXJnKGZha2UsIGluZGV4KSB7XG4gICAgICAgIGlmICh0eXBlb2YgaW5kZXggIT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBpbmRleCBpcyBub3QgbnVtYmVyXCIpO1xuICAgICAgICB9XG4gICAgICAgIGZha2UucmVzb2x2ZUFyZ0F0ID0gaW5kZXg7XG4gICAgICAgIGZha2UucmV0dXJuVmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgICAgIGZha2UucmVzb2x2ZSA9IHRydWU7XG4gICAgICAgIGZha2UucmVzb2x2ZVRoaXMgPSBmYWxzZTtcbiAgICAgICAgZmFrZS5yZWplY3QgPSBmYWxzZTtcbiAgICAgICAgZmFrZS5yZXR1cm5WYWx1ZURlZmluZWQgPSBmYWxzZTtcbiAgICAgICAgZmFrZS5leGNlcHRpb24gPSB1bmRlZmluZWQ7XG4gICAgICAgIGZha2UuZXhjZXB0aW9uQ3JlYXRvciA9IHVuZGVmaW5lZDtcbiAgICAgICAgZmFrZS5mYWtlRm4gPSB1bmRlZmluZWQ7XG4gICAgICAgIGZha2UuY2FsbHNUaHJvdWdoID0gZmFsc2U7XG4gICAgfSxcblxuICAgIHJlamVjdHM6IGZ1bmN0aW9uIHJlamVjdHMoZmFrZSwgZXJyb3IsIG1lc3NhZ2UpIHtcbiAgICAgICAgbGV0IHJlYXNvbjtcbiAgICAgICAgaWYgKHR5cGVvZiBlcnJvciA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgcmVhc29uID0gbmV3IEVycm9yKG1lc3NhZ2UgfHwgXCJcIik7XG4gICAgICAgICAgICByZWFzb24ubmFtZSA9IGVycm9yO1xuICAgICAgICB9IGVsc2UgaWYgKCFlcnJvcikge1xuICAgICAgICAgICAgcmVhc29uID0gbmV3IEVycm9yKFwiRXJyb3JcIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZWFzb24gPSBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgICBmYWtlLnJldHVyblZhbHVlID0gcmVhc29uO1xuICAgICAgICBmYWtlLnJlc29sdmUgPSBmYWxzZTtcbiAgICAgICAgZmFrZS5yZXNvbHZlVGhpcyA9IGZhbHNlO1xuICAgICAgICBmYWtlLnJlamVjdCA9IHRydWU7XG4gICAgICAgIGZha2UucmV0dXJuVmFsdWVEZWZpbmVkID0gdHJ1ZTtcbiAgICAgICAgZmFrZS5leGNlcHRpb24gPSB1bmRlZmluZWQ7XG4gICAgICAgIGZha2UuZXhjZXB0aW9uQ3JlYXRvciA9IHVuZGVmaW5lZDtcbiAgICAgICAgZmFrZS5mYWtlRm4gPSB1bmRlZmluZWQ7XG4gICAgICAgIGZha2UuY2FsbHNUaHJvdWdoID0gZmFsc2U7XG5cbiAgICAgICAgcmV0dXJuIGZha2U7XG4gICAgfSxcblxuICAgIHJlc29sdmVzVGhpczogZnVuY3Rpb24gcmVzb2x2ZXNUaGlzKGZha2UpIHtcbiAgICAgICAgZmFrZS5yZXR1cm5WYWx1ZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgZmFrZS5yZXNvbHZlID0gZmFsc2U7XG4gICAgICAgIGZha2UucmVzb2x2ZVRoaXMgPSB0cnVlO1xuICAgICAgICBmYWtlLnJlamVjdCA9IGZhbHNlO1xuICAgICAgICBmYWtlLnJldHVyblZhbHVlRGVmaW5lZCA9IGZhbHNlO1xuICAgICAgICBmYWtlLmV4Y2VwdGlvbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgZmFrZS5leGNlcHRpb25DcmVhdG9yID0gdW5kZWZpbmVkO1xuICAgICAgICBmYWtlLmZha2VGbiA9IHVuZGVmaW5lZDtcbiAgICAgICAgZmFrZS5jYWxsc1Rocm91Z2ggPSBmYWxzZTtcbiAgICB9LFxuXG4gICAgY2FsbFRocm91Z2g6IGZ1bmN0aW9uIGNhbGxUaHJvdWdoKGZha2UpIHtcbiAgICAgICAgZmFrZS5jYWxsc1Rocm91Z2ggPSB0cnVlO1xuICAgIH0sXG5cbiAgICBjYWxsVGhyb3VnaFdpdGhOZXc6IGZ1bmN0aW9uIGNhbGxUaHJvdWdoV2l0aE5ldyhmYWtlKSB7XG4gICAgICAgIGZha2UuY2FsbHNUaHJvdWdoV2l0aE5ldyA9IHRydWU7XG4gICAgfSxcblxuICAgIGdldDogZnVuY3Rpb24gZ2V0KGZha2UsIGdldHRlckZ1bmN0aW9uKSB7XG4gICAgICAgIGNvbnN0IHJvb3RTdHViID0gZmFrZS5zdHViIHx8IGZha2U7XG5cbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHJvb3RTdHViLnJvb3RPYmosIHJvb3RTdHViLnByb3BOYW1lLCB7XG4gICAgICAgICAgICBnZXQ6IGdldHRlckZ1bmN0aW9uLFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiBpc1Byb3BlcnR5Q29uZmlndXJhYmxlKFxuICAgICAgICAgICAgICAgIHJvb3RTdHViLnJvb3RPYmosXG4gICAgICAgICAgICAgICAgcm9vdFN0dWIucHJvcE5hbWUsXG4gICAgICAgICAgICApLFxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gZmFrZTtcbiAgICB9LFxuXG4gICAgc2V0OiBmdW5jdGlvbiBzZXQoZmFrZSwgc2V0dGVyRnVuY3Rpb24pIHtcbiAgICAgICAgY29uc3Qgcm9vdFN0dWIgPSBmYWtlLnN0dWIgfHwgZmFrZTtcblxuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoXG4gICAgICAgICAgICByb290U3R1Yi5yb290T2JqLFxuICAgICAgICAgICAgcm9vdFN0dWIucHJvcE5hbWUsXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgYWNjZXNzb3ItcGFpcnNcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBzZXQ6IHNldHRlckZ1bmN0aW9uLFxuICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogaXNQcm9wZXJ0eUNvbmZpZ3VyYWJsZShcbiAgICAgICAgICAgICAgICAgICAgcm9vdFN0dWIucm9vdE9iaixcbiAgICAgICAgICAgICAgICAgICAgcm9vdFN0dWIucHJvcE5hbWUsXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICk7XG5cbiAgICAgICAgcmV0dXJuIGZha2U7XG4gICAgfSxcblxuICAgIHZhbHVlOiBmdW5jdGlvbiB2YWx1ZShmYWtlLCBuZXdWYWwpIHtcbiAgICAgICAgY29uc3Qgcm9vdFN0dWIgPSBmYWtlLnN0dWIgfHwgZmFrZTtcblxuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkocm9vdFN0dWIucm9vdE9iaiwgcm9vdFN0dWIucHJvcE5hbWUsIHtcbiAgICAgICAgICAgIHZhbHVlOiBuZXdWYWwsXG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6XG4gICAgICAgICAgICAgICAgcm9vdFN0dWIuc2hhZG93c1Byb3BPblByb3RvdHlwZSB8fFxuICAgICAgICAgICAgICAgIGlzUHJvcGVydHlDb25maWd1cmFibGUocm9vdFN0dWIucm9vdE9iaiwgcm9vdFN0dWIucHJvcE5hbWUpLFxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gZmFrZTtcbiAgICB9LFxufTtcblxuY29uc3QgYXN5bmNCZWhhdmlvcnMgPSBleHBvcnRBc3luY0JlaGF2aW9ycyhkZWZhdWx0QmVoYXZpb3JzKTtcblxubW9kdWxlLmV4cG9ydHMgPSBleHRlbmQoe30sIGRlZmF1bHRCZWhhdmlvcnMsIGFzeW5jQmVoYXZpb3JzKTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5jb25zdCBhcnJheVByb3RvID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikucHJvdG90eXBlcy5hcnJheTtcbmNvbnN0IGNyZWF0ZVByb3h5ID0gcmVxdWlyZShcIi4vcHJveHlcIik7XG5jb25zdCBuZXh0VGljayA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZS9uZXh0LXRpY2tcIik7XG5cbmNvbnN0IHNsaWNlID0gYXJyYXlQcm90by5zbGljZTtcblxubW9kdWxlLmV4cG9ydHMgPSBmYWtlO1xuXG4vKipcbiAqIFJldHVybnMgYSBgZmFrZWAgdGhhdCByZWNvcmRzIGFsbCBjYWxscywgYXJndW1lbnRzIGFuZCByZXR1cm4gdmFsdWVzLlxuICpcbiAqIFdoZW4gYW4gYGZgIGFyZ3VtZW50IGlzIHN1cHBsaWVkLCB0aGlzIGltcGxlbWVudGF0aW9uIHdpbGwgYmUgdXNlZC5cbiAqXG4gKiBAZXhhbXBsZVxuICogLy8gY3JlYXRlIGFuIGVtcHR5IGZha2VcbiAqIHZhciBmMSA9IHNpbm9uLmZha2UoKTtcbiAqXG4gKiBmMSgpO1xuICpcbiAqIGYxLmNhbGxlZE9uY2UoKVxuICogLy8gdHJ1ZVxuICpcbiAqIEBleGFtcGxlXG4gKiBmdW5jdGlvbiBncmVldChncmVldGluZykge1xuICogICBjb25zb2xlLmxvZyhgSGVsbG8gJHtncmVldGluZ31gKTtcbiAqIH1cbiAqXG4gKiAvLyBjcmVhdGUgYSBmYWtlIHdpdGggaW1wbGVtZW50YXRpb25cbiAqIHZhciBmMiA9IHNpbm9uLmZha2UoZ3JlZXQpO1xuICpcbiAqIC8vIEhlbGxvIHdvcmxkXG4gKiBmMihcIndvcmxkXCIpO1xuICpcbiAqIGYyLmNhbGxlZFdpdGgoXCJ3b3JsZFwiKTtcbiAqIC8vIHRydWVcbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufHVuZGVmaW5lZH0gZlxuICogQHJldHVybnMge0Z1bmN0aW9ufVxuICogQG5hbWVzcGFjZVxuICovXG5mdW5jdGlvbiBmYWtlKGYpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgdHlwZW9mIGYgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiRXhwZWN0ZWQgZiBhcmd1bWVudCB0byBiZSBhIEZ1bmN0aW9uXCIpO1xuICAgIH1cblxuICAgIHJldHVybiB3cmFwRnVuYyhmKTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgYGZha2VgIHRoYXQgcmV0dXJucyB0aGUgcHJvdmlkZWQgYHZhbHVlYCwgYXMgd2VsbCBhcyByZWNvcmRpbmcgYWxsXG4gKiBjYWxscywgYXJndW1lbnRzIGFuZCByZXR1cm4gdmFsdWVzLlxuICpcbiAqIEBleGFtcGxlXG4gKiB2YXIgZjEgPSBzaW5vbi5mYWtlLnJldHVybnMoNDIpO1xuICpcbiAqIGYxKCk7XG4gKiAvLyA0MlxuICpcbiAqIEBtZW1iZXJvZiBmYWtlXG4gKiBAcGFyYW0geyp9IHZhbHVlXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259XG4gKi9cbmZha2UucmV0dXJucyA9IGZ1bmN0aW9uIHJldHVybnModmFsdWUpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUganNkb2MvcmVxdWlyZS1qc2RvY1xuICAgIGZ1bmN0aW9uIGYoKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gd3JhcEZ1bmMoZik7XG59O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBgZmFrZWAgdGhhdCB0aHJvd3MgYW4gRXJyb3IuXG4gKiBJZiB0aGUgYHZhbHVlYCBhcmd1bWVudCBkb2VzIG5vdCBoYXZlIEVycm9yIGluIGl0cyBwcm90b3R5cGUgY2hhaW4sIGl0IHdpbGxcbiAqIGJlIHVzZWQgZm9yIGNyZWF0aW5nIGEgbmV3IGVycm9yLlxuICpcbiAqIEBleGFtcGxlXG4gKiB2YXIgZjEgPSBzaW5vbi5mYWtlLnRocm93cyhcImhlbGxvXCIpO1xuICpcbiAqIGYxKCk7XG4gKiAvLyBVbmNhdWdodCBFcnJvcjogaGVsbG9cbiAqXG4gKiBAZXhhbXBsZVxuICogdmFyIGYyID0gc2lub24uZmFrZS50aHJvd3MobmV3IFR5cGVFcnJvcihcIkludmFsaWQgYXJndW1lbnRcIikpO1xuICpcbiAqIGYyKCk7XG4gKiAvLyBVbmNhdWdodCBUeXBlRXJyb3I6IEludmFsaWQgYXJndW1lbnRcbiAqXG4gKiBAbWVtYmVyb2YgZmFrZVxuICogQHBhcmFtIHsqfEVycm9yfSB2YWx1ZVxuICogQHJldHVybnMge0Z1bmN0aW9ufVxuICovXG5mYWtlLnRocm93cyA9IGZ1bmN0aW9uIHRocm93cyh2YWx1ZSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBqc2RvYy9yZXF1aXJlLWpzZG9jXG4gICAgZnVuY3Rpb24gZigpIHtcbiAgICAgICAgdGhyb3cgZ2V0RXJyb3IodmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiB3cmFwRnVuYyhmKTtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIGBmYWtlYCB0aGF0IHJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHBhc3NlZCBgdmFsdWVgXG4gKiBhcmd1bWVudC5cbiAqXG4gKiBAZXhhbXBsZVxuICogdmFyIGYxID0gc2lub24uZmFrZS5yZXNvbHZlcyhcImFwcGxlIHBpZVwiKTtcbiAqXG4gKiBhd2FpdCBmMSgpO1xuICogLy8gXCJhcHBsZSBwaWVcIlxuICpcbiAqIEBtZW1iZXJvZiBmYWtlXG4gKiBAcGFyYW0geyp9IHZhbHVlXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259XG4gKi9cbmZha2UucmVzb2x2ZXMgPSBmdW5jdGlvbiByZXNvbHZlcyh2YWx1ZSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBqc2RvYy9yZXF1aXJlLWpzZG9jXG4gICAgZnVuY3Rpb24gZigpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHdyYXBGdW5jKGYpO1xufTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgYGZha2VgIHRoYXQgcmV0dXJucyBhIHByb21pc2UgdGhhdCByZWplY3RzIHRvIHRoZSBwYXNzZWQgYHZhbHVlYFxuICogYXJndW1lbnQuIFdoZW4gYHZhbHVlYCBkb2VzIG5vdCBoYXZlIEVycm9yIGluIGl0cyBwcm90b3R5cGUgY2hhaW4sIGl0IHdpbGwgYmVcbiAqIHdyYXBwZWQgaW4gYW4gRXJyb3IuXG4gKlxuICogQGV4YW1wbGVcbiAqIHZhciBmMSA9IHNpbm9uLmZha2UucmVqZWN0cyhcIjooXCIpO1xuICpcbiAqIHRyeSB7XG4gKiAgIGF3YWl0IGYxKCk7XG4gKiB9IGNhdGNoIChlcnJvcikge1xuICogICBjb25zb2xlLmxvZyhlcnJvcik7XG4gKiAgIC8vIFwiOihcIlxuICogfVxuICpcbiAqIEBtZW1iZXJvZiBmYWtlXG4gKiBAcGFyYW0geyp9IHZhbHVlXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259XG4gKi9cbmZha2UucmVqZWN0cyA9IGZ1bmN0aW9uIHJlamVjdHModmFsdWUpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUganNkb2MvcmVxdWlyZS1qc2RvY1xuICAgIGZ1bmN0aW9uIGYoKSB7XG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChnZXRFcnJvcih2YWx1ZSkpO1xuICAgIH1cblxuICAgIHJldHVybiB3cmFwRnVuYyhmKTtcbn07XG5cbi8qKlxuICogUmV0dXJucyBhIGBmYWtlYCB0aGF0IGNhbGxzIHRoZSBjYWxsYmFjayB3aXRoIHRoZSBkZWZpbmVkIGFyZ3VtZW50cy5cbiAqXG4gKiBAZXhhbXBsZVxuICogZnVuY3Rpb24gY2FsbGJhY2soKSB7XG4gKiAgIGNvbnNvbGUubG9nKGFyZ3VtZW50cy5qb2luKFwiKlwiKSk7XG4gKiB9XG4gKlxuICogY29uc3QgZjEgPSBzaW5vbi5mYWtlLnlpZWxkcyhcImFwcGxlXCIsIFwicGllXCIpO1xuICpcbiAqIGYxKGNhbGxiYWNrKTtcbiAqIC8vIFwiYXBwbGUqcGllXCJcbiAqXG4gKiBAbWVtYmVyb2YgZmFrZVxuICogQHJldHVybnMge0Z1bmN0aW9ufVxuICovXG5mYWtlLnlpZWxkcyA9IGZ1bmN0aW9uIHlpZWxkcygpIHtcbiAgICBjb25zdCB2YWx1ZXMgPSBzbGljZShhcmd1bWVudHMpO1xuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGpzZG9jL3JlcXVpcmUtanNkb2NcbiAgICBmdW5jdGlvbiBmKCkge1xuICAgICAgICBjb25zdCBjYWxsYmFjayA9IGFyZ3VtZW50c1thcmd1bWVudHMubGVuZ3RoIC0gMV07XG4gICAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkV4cGVjdGVkIGxhc3QgYXJndW1lbnQgdG8gYmUgYSBmdW5jdGlvblwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNhbGxiYWNrLmFwcGx5KG51bGwsIHZhbHVlcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHdyYXBGdW5jKGYpO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIGEgYGZha2VgIHRoYXQgY2FsbHMgdGhlIGNhbGxiYWNrICoqYXN5bmNocm9ub3VzbHkqKiB3aXRoIHRoZVxuICogZGVmaW5lZCBhcmd1bWVudHMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGZ1bmN0aW9uIGNhbGxiYWNrKCkge1xuICogICBjb25zb2xlLmxvZyhhcmd1bWVudHMuam9pbihcIipcIikpO1xuICogfVxuICpcbiAqIGNvbnN0IGYxID0gc2lub24uZmFrZS55aWVsZHMoXCJhcHBsZVwiLCBcInBpZVwiKTtcbiAqXG4gKiBmMShjYWxsYmFjayk7XG4gKlxuICogc2V0VGltZW91dCgoKSA9PiB7XG4gKiAgIC8vIFwiYXBwbGUqcGllXCJcbiAqIH0pO1xuICpcbiAqIEBtZW1iZXJvZiBmYWtlXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259XG4gKi9cbmZha2UueWllbGRzQXN5bmMgPSBmdW5jdGlvbiB5aWVsZHNBc3luYygpIHtcbiAgICBjb25zdCB2YWx1ZXMgPSBzbGljZShhcmd1bWVudHMpO1xuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGpzZG9jL3JlcXVpcmUtanNkb2NcbiAgICBmdW5jdGlvbiBmKCkge1xuICAgICAgICBjb25zdCBjYWxsYmFjayA9IGFyZ3VtZW50c1thcmd1bWVudHMubGVuZ3RoIC0gMV07XG4gICAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkV4cGVjdGVkIGxhc3QgYXJndW1lbnQgdG8gYmUgYSBmdW5jdGlvblwiKTtcbiAgICAgICAgfVxuICAgICAgICBuZXh0VGljayhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjYWxsYmFjay5hcHBseShudWxsLCB2YWx1ZXMpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gd3JhcEZ1bmMoZik7XG59O1xuXG5sZXQgdXVpZCA9IDA7XG4vKipcbiAqIENyZWF0ZXMgYSBwcm94eSAoc2lub24gY29uY2VwdCkgZnJvbSB0aGUgcGFzc2VkIGZ1bmN0aW9uLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0gIHtGdW5jdGlvbn0gZlxuICogQHJldHVybnMge0Z1bmN0aW9ufVxuICovXG5mdW5jdGlvbiB3cmFwRnVuYyhmKSB7XG4gICAgY29uc3QgZmFrZUluc3RhbmNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBsZXQgZmlyc3RBcmcsIGxhc3RBcmc7XG5cbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICBmaXJzdEFyZyA9IGFyZ3VtZW50c1swXTtcbiAgICAgICAgICAgIGxhc3RBcmcgPSBhcmd1bWVudHNbYXJndW1lbnRzLmxlbmd0aCAtIDFdO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2FsbGJhY2sgPVxuICAgICAgICAgICAgbGFzdEFyZyAmJiB0eXBlb2YgbGFzdEFyZyA9PT0gXCJmdW5jdGlvblwiID8gbGFzdEFyZyA6IHVuZGVmaW5lZDtcblxuICAgICAgICAvKiBlc2xpbnQtZGlzYWJsZSBuby11c2UtYmVmb3JlLWRlZmluZSAqL1xuICAgICAgICBwcm94eS5maXJzdEFyZyA9IGZpcnN0QXJnO1xuICAgICAgICBwcm94eS5sYXN0QXJnID0gbGFzdEFyZztcbiAgICAgICAgcHJveHkuY2FsbGJhY2sgPSBjYWxsYmFjaztcblxuICAgICAgICByZXR1cm4gZiAmJiBmLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgICBjb25zdCBwcm94eSA9IGNyZWF0ZVByb3h5KGZha2VJbnN0YW5jZSwgZiB8fCBmYWtlSW5zdGFuY2UpO1xuXG4gICAgcHJveHkuZGlzcGxheU5hbWUgPSBcImZha2VcIjtcbiAgICBwcm94eS5pZCA9IGBmYWtlIyR7dXVpZCsrfWA7XG5cbiAgICByZXR1cm4gcHJveHk7XG59XG5cbi8qKlxuICogUmV0dXJucyBhbiBFcnJvciBpbnN0YW5jZSBmcm9tIHRoZSBwYXNzZWQgdmFsdWUsIGlmIHRoZSB2YWx1ZSBpcyBub3RcbiAqIGFscmVhZHkgYW4gRXJyb3IgaW5zdGFuY2UuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSAgeyp9IHZhbHVlIFtkZXNjcmlwdGlvbl1cbiAqIEByZXR1cm5zIHtFcnJvcn0gICAgICAgW2Rlc2NyaXB0aW9uXVxuICovXG5mdW5jdGlvbiBnZXRFcnJvcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEVycm9yID8gdmFsdWUgOiBuZXcgRXJyb3IodmFsdWUpO1xufVxuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IGFycmF5UHJvdG8gPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLmFycmF5O1xuY29uc3QgcHJveHlJbnZva2UgPSByZXF1aXJlKFwiLi9wcm94eS1pbnZva2VcIik7XG5jb25zdCBwcm94eUNhbGxUb1N0cmluZyA9IHJlcXVpcmUoXCIuL3Byb3h5LWNhbGxcIikudG9TdHJpbmc7XG5jb25zdCB0aW1lc0luV29yZHMgPSByZXF1aXJlKFwiLi91dGlsL2NvcmUvdGltZXMtaW4td29yZHNcIik7XG5jb25zdCBleHRlbmQgPSByZXF1aXJlKFwiLi91dGlsL2NvcmUvZXh0ZW5kXCIpO1xuY29uc3QgbWF0Y2ggPSByZXF1aXJlKFwiQHNpbm9uanMvc2Ftc2FtXCIpLmNyZWF0ZU1hdGNoZXI7XG5jb25zdCBzdHViID0gcmVxdWlyZShcIi4vc3R1YlwiKTtcbmNvbnN0IGFzc2VydCA9IHJlcXVpcmUoXCIuL2Fzc2VydFwiKTtcbmNvbnN0IGRlZXBFcXVhbCA9IHJlcXVpcmUoXCJAc2lub25qcy9zYW1zYW1cIikuZGVlcEVxdWFsO1xuY29uc3QgaW5zcGVjdCA9IHJlcXVpcmUoXCJ1dGlsXCIpLmluc3BlY3Q7XG5jb25zdCB2YWx1ZVRvU3RyaW5nID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikudmFsdWVUb1N0cmluZztcblxuY29uc3QgZXZlcnkgPSBhcnJheVByb3RvLmV2ZXJ5O1xuY29uc3QgZm9yRWFjaCA9IGFycmF5UHJvdG8uZm9yRWFjaDtcbmNvbnN0IHB1c2ggPSBhcnJheVByb3RvLnB1c2g7XG5jb25zdCBzbGljZSA9IGFycmF5UHJvdG8uc2xpY2U7XG5cbmZ1bmN0aW9uIGNhbGxDb3VudEluV29yZHMoY2FsbENvdW50KSB7XG4gICAgaWYgKGNhbGxDb3VudCA9PT0gMCkge1xuICAgICAgICByZXR1cm4gXCJuZXZlciBjYWxsZWRcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gYGNhbGxlZCAke3RpbWVzSW5Xb3JkcyhjYWxsQ291bnQpfWA7XG59XG5cbmZ1bmN0aW9uIGV4cGVjdGVkQ2FsbENvdW50SW5Xb3JkcyhleHBlY3RhdGlvbikge1xuICAgIGNvbnN0IG1pbiA9IGV4cGVjdGF0aW9uLm1pbkNhbGxzO1xuICAgIGNvbnN0IG1heCA9IGV4cGVjdGF0aW9uLm1heENhbGxzO1xuXG4gICAgaWYgKHR5cGVvZiBtaW4gPT09IFwibnVtYmVyXCIgJiYgdHlwZW9mIG1heCA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICBsZXQgc3RyID0gdGltZXNJbldvcmRzKG1pbik7XG5cbiAgICAgICAgaWYgKG1pbiAhPT0gbWF4KSB7XG4gICAgICAgICAgICBzdHIgPSBgYXQgbGVhc3QgJHtzdHJ9IGFuZCBhdCBtb3N0ICR7dGltZXNJbldvcmRzKG1heCl9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzdHI7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBtaW4gPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgcmV0dXJuIGBhdCBsZWFzdCAke3RpbWVzSW5Xb3JkcyhtaW4pfWA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGBhdCBtb3N0ICR7dGltZXNJbldvcmRzKG1heCl9YDtcbn1cblxuZnVuY3Rpb24gcmVjZWl2ZWRNaW5DYWxscyhleHBlY3RhdGlvbikge1xuICAgIGNvbnN0IGhhc01pbkxpbWl0ID0gdHlwZW9mIGV4cGVjdGF0aW9uLm1pbkNhbGxzID09PSBcIm51bWJlclwiO1xuICAgIHJldHVybiAhaGFzTWluTGltaXQgfHwgZXhwZWN0YXRpb24uY2FsbENvdW50ID49IGV4cGVjdGF0aW9uLm1pbkNhbGxzO1xufVxuXG5mdW5jdGlvbiByZWNlaXZlZE1heENhbGxzKGV4cGVjdGF0aW9uKSB7XG4gICAgaWYgKHR5cGVvZiBleHBlY3RhdGlvbi5tYXhDYWxscyAhPT0gXCJudW1iZXJcIikge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIGV4cGVjdGF0aW9uLmNhbGxDb3VudCA9PT0gZXhwZWN0YXRpb24ubWF4Q2FsbHM7XG59XG5cbmZ1bmN0aW9uIHZlcmlmeU1hdGNoZXIocG9zc2libGVNYXRjaGVyLCBhcmcpIHtcbiAgICBjb25zdCBpc01hdGNoZXIgPSBtYXRjaC5pc01hdGNoZXIocG9zc2libGVNYXRjaGVyKTtcblxuICAgIHJldHVybiAoaXNNYXRjaGVyICYmIHBvc3NpYmxlTWF0Y2hlci50ZXN0KGFyZykpIHx8IHRydWU7XG59XG5cbmNvbnN0IG1vY2tFeHBlY3RhdGlvbiA9IHtcbiAgICBtaW5DYWxsczogMSxcbiAgICBtYXhDYWxsczogMSxcblxuICAgIGNyZWF0ZTogZnVuY3Rpb24gY3JlYXRlKG1ldGhvZE5hbWUpIHtcbiAgICAgICAgY29uc3QgZXhwZWN0YXRpb24gPSBleHRlbmQubm9uRW51bShzdHViKCksIG1vY2tFeHBlY3RhdGlvbik7XG4gICAgICAgIGRlbGV0ZSBleHBlY3RhdGlvbi5jcmVhdGU7XG4gICAgICAgIGV4cGVjdGF0aW9uLm1ldGhvZCA9IG1ldGhvZE5hbWU7XG5cbiAgICAgICAgcmV0dXJuIGV4cGVjdGF0aW9uO1xuICAgIH0sXG5cbiAgICBpbnZva2U6IGZ1bmN0aW9uIGludm9rZShmdW5jLCB0aGlzVmFsdWUsIGFyZ3MpIHtcbiAgICAgICAgdGhpcy52ZXJpZnlDYWxsQWxsb3dlZCh0aGlzVmFsdWUsIGFyZ3MpO1xuXG4gICAgICAgIHJldHVybiBwcm94eUludm9rZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH0sXG5cbiAgICBhdExlYXN0OiBmdW5jdGlvbiBhdExlYXN0KG51bSkge1xuICAgICAgICBpZiAodHlwZW9mIG51bSAhPT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgJyR7dmFsdWVUb1N0cmluZyhudW0pfScgaXMgbm90IG51bWJlcmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLmxpbWl0c1NldCkge1xuICAgICAgICAgICAgdGhpcy5tYXhDYWxscyA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLmxpbWl0c1NldCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm1pbkNhbGxzID0gbnVtO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBhdE1vc3Q6IGZ1bmN0aW9uIGF0TW9zdChudW0pIHtcbiAgICAgICAgaWYgKHR5cGVvZiBudW0gIT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYCcke3ZhbHVlVG9TdHJpbmcobnVtKX0nIGlzIG5vdCBudW1iZXJgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5saW1pdHNTZXQpIHtcbiAgICAgICAgICAgIHRoaXMubWluQ2FsbHMgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5saW1pdHNTZXQgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5tYXhDYWxscyA9IG51bTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgbmV2ZXI6IGZ1bmN0aW9uIG5ldmVyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5leGFjdGx5KDApO1xuICAgIH0sXG5cbiAgICBvbmNlOiBmdW5jdGlvbiBvbmNlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5leGFjdGx5KDEpO1xuICAgIH0sXG5cbiAgICB0d2ljZTogZnVuY3Rpb24gdHdpY2UoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmV4YWN0bHkoMik7XG4gICAgfSxcblxuICAgIHRocmljZTogZnVuY3Rpb24gdGhyaWNlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5leGFjdGx5KDMpO1xuICAgIH0sXG5cbiAgICBleGFjdGx5OiBmdW5jdGlvbiBleGFjdGx5KG51bSkge1xuICAgICAgICBpZiAodHlwZW9mIG51bSAhPT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgJyR7dmFsdWVUb1N0cmluZyhudW0pfScgaXMgbm90IGEgbnVtYmVyYCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmF0TGVhc3QobnVtKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXRNb3N0KG51bSk7XG4gICAgfSxcblxuICAgIG1ldDogZnVuY3Rpb24gbWV0KCkge1xuICAgICAgICByZXR1cm4gIXRoaXMuZmFpbGVkICYmIHJlY2VpdmVkTWluQ2FsbHModGhpcyk7XG4gICAgfSxcblxuICAgIHZlcmlmeUNhbGxBbGxvd2VkOiBmdW5jdGlvbiB2ZXJpZnlDYWxsQWxsb3dlZCh0aGlzVmFsdWUsIGFyZ3MpIHtcbiAgICAgICAgY29uc3QgZXhwZWN0ZWRBcmd1bWVudHMgPSB0aGlzLmV4cGVjdGVkQXJndW1lbnRzO1xuXG4gICAgICAgIGlmIChyZWNlaXZlZE1heENhbGxzKHRoaXMpKSB7XG4gICAgICAgICAgICB0aGlzLmZhaWxlZCA9IHRydWU7XG4gICAgICAgICAgICBtb2NrRXhwZWN0YXRpb24uZmFpbChcbiAgICAgICAgICAgICAgICBgJHt0aGlzLm1ldGhvZH0gYWxyZWFkeSBjYWxsZWQgJHt0aW1lc0luV29yZHModGhpcy5tYXhDYWxscyl9YCxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoXCJleHBlY3RlZFRoaXNcIiBpbiB0aGlzICYmIHRoaXMuZXhwZWN0ZWRUaGlzICE9PSB0aGlzVmFsdWUpIHtcbiAgICAgICAgICAgIG1vY2tFeHBlY3RhdGlvbi5mYWlsKFxuICAgICAgICAgICAgICAgIGAke3RoaXMubWV0aG9kfSBjYWxsZWQgd2l0aCAke3ZhbHVlVG9TdHJpbmcoXG4gICAgICAgICAgICAgICAgICAgIHRoaXNWYWx1ZSxcbiAgICAgICAgICAgICAgICApfSBhcyB0aGlzVmFsdWUsIGV4cGVjdGVkICR7dmFsdWVUb1N0cmluZyh0aGlzLmV4cGVjdGVkVGhpcyl9YCxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIShcImV4cGVjdGVkQXJndW1lbnRzXCIgaW4gdGhpcykpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghYXJncykge1xuICAgICAgICAgICAgbW9ja0V4cGVjdGF0aW9uLmZhaWwoXG4gICAgICAgICAgICAgICAgYCR7dGhpcy5tZXRob2R9IHJlY2VpdmVkIG5vIGFyZ3VtZW50cywgZXhwZWN0ZWQgJHtpbnNwZWN0KFxuICAgICAgICAgICAgICAgICAgICBleHBlY3RlZEFyZ3VtZW50cyxcbiAgICAgICAgICAgICAgICApfWAsXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGFyZ3MubGVuZ3RoIDwgZXhwZWN0ZWRBcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgICBtb2NrRXhwZWN0YXRpb24uZmFpbChcbiAgICAgICAgICAgICAgICBgJHt0aGlzLm1ldGhvZH0gcmVjZWl2ZWQgdG9vIGZldyBhcmd1bWVudHMgKCR7aW5zcGVjdChcbiAgICAgICAgICAgICAgICAgICAgYXJncyxcbiAgICAgICAgICAgICAgICApfSksIGV4cGVjdGVkICR7aW5zcGVjdChleHBlY3RlZEFyZ3VtZW50cyl9YCxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoXG4gICAgICAgICAgICB0aGlzLmV4cGVjdHNFeGFjdEFyZ0NvdW50ICYmXG4gICAgICAgICAgICBhcmdzLmxlbmd0aCAhPT0gZXhwZWN0ZWRBcmd1bWVudHMubGVuZ3RoXG4gICAgICAgICkge1xuICAgICAgICAgICAgbW9ja0V4cGVjdGF0aW9uLmZhaWwoXG4gICAgICAgICAgICAgICAgYCR7dGhpcy5tZXRob2R9IHJlY2VpdmVkIHRvbyBtYW55IGFyZ3VtZW50cyAoJHtpbnNwZWN0KFxuICAgICAgICAgICAgICAgICAgICBhcmdzLFxuICAgICAgICAgICAgICAgICl9KSwgZXhwZWN0ZWQgJHtpbnNwZWN0KGV4cGVjdGVkQXJndW1lbnRzKX1gLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvckVhY2goXG4gICAgICAgICAgICBleHBlY3RlZEFyZ3VtZW50cyxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChleHBlY3RlZEFyZ3VtZW50LCBpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF2ZXJpZnlNYXRjaGVyKGV4cGVjdGVkQXJndW1lbnQsIGFyZ3NbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vY2tFeHBlY3RhdGlvbi5mYWlsKFxuICAgICAgICAgICAgICAgICAgICAgICAgYCR7dGhpcy5tZXRob2R9IHJlY2VpdmVkIHdyb25nIGFyZ3VtZW50cyAke2luc3BlY3QoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJncyxcbiAgICAgICAgICAgICAgICAgICAgICAgICl9LCBkaWRuJ3QgbWF0Y2ggJHtTdHJpbmcoZXhwZWN0ZWRBcmd1bWVudHMpfWAsXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFkZWVwRXF1YWwoYXJnc1tpXSwgZXhwZWN0ZWRBcmd1bWVudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9ja0V4cGVjdGF0aW9uLmZhaWwoXG4gICAgICAgICAgICAgICAgICAgICAgICBgJHt0aGlzLm1ldGhvZH0gcmVjZWl2ZWQgd3JvbmcgYXJndW1lbnRzICR7aW5zcGVjdChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmdzLFxuICAgICAgICAgICAgICAgICAgICAgICAgKX0sIGV4cGVjdGVkICR7aW5zcGVjdChleHBlY3RlZEFyZ3VtZW50cyl9YCxcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgKTtcbiAgICB9LFxuXG4gICAgYWxsb3dzQ2FsbDogZnVuY3Rpb24gYWxsb3dzQ2FsbCh0aGlzVmFsdWUsIGFyZ3MpIHtcbiAgICAgICAgY29uc3QgZXhwZWN0ZWRBcmd1bWVudHMgPSB0aGlzLmV4cGVjdGVkQXJndW1lbnRzO1xuXG4gICAgICAgIGlmICh0aGlzLm1ldCgpICYmIHJlY2VpdmVkTWF4Q2FsbHModGhpcykpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChcImV4cGVjdGVkVGhpc1wiIGluIHRoaXMgJiYgdGhpcy5leHBlY3RlZFRoaXMgIT09IHRoaXNWYWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEoXCJleHBlY3RlZEFyZ3VtZW50c1wiIGluIHRoaXMpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bmRlcnNjb3JlLWRhbmdsZVxuICAgICAgICBjb25zdCBfYXJncyA9IGFyZ3MgfHwgW107XG5cbiAgICAgICAgaWYgKF9hcmdzLmxlbmd0aCA8IGV4cGVjdGVkQXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5leHBlY3RzRXhhY3RBcmdDb3VudCAmJlxuICAgICAgICAgICAgX2FyZ3MubGVuZ3RoICE9PSBleHBlY3RlZEFyZ3VtZW50cy5sZW5ndGhcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZXZlcnkoZXhwZWN0ZWRBcmd1bWVudHMsIGZ1bmN0aW9uIChleHBlY3RlZEFyZ3VtZW50LCBpKSB7XG4gICAgICAgICAgICBpZiAoIXZlcmlmeU1hdGNoZXIoZXhwZWN0ZWRBcmd1bWVudCwgX2FyZ3NbaV0pKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWRlZXBFcXVhbChfYXJnc1tpXSwgZXhwZWN0ZWRBcmd1bWVudCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICB9LFxuXG4gICAgd2l0aEFyZ3M6IGZ1bmN0aW9uIHdpdGhBcmdzKCkge1xuICAgICAgICB0aGlzLmV4cGVjdGVkQXJndW1lbnRzID0gc2xpY2UoYXJndW1lbnRzKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIHdpdGhFeGFjdEFyZ3M6IGZ1bmN0aW9uIHdpdGhFeGFjdEFyZ3MoKSB7XG4gICAgICAgIHRoaXMud2l0aEFyZ3MuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgdGhpcy5leHBlY3RzRXhhY3RBcmdDb3VudCA9IHRydWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBvbjogZnVuY3Rpb24gb24odGhpc1ZhbHVlKSB7XG4gICAgICAgIHRoaXMuZXhwZWN0ZWRUaGlzID0gdGhpc1ZhbHVlO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgdG9TdHJpbmc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3QgYXJncyA9IHNsaWNlKHRoaXMuZXhwZWN0ZWRBcmd1bWVudHMgfHwgW10pO1xuXG4gICAgICAgIGlmICghdGhpcy5leHBlY3RzRXhhY3RBcmdDb3VudCkge1xuICAgICAgICAgICAgcHVzaChhcmdzLCBcIlsuLi5dXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2FsbFN0ciA9IHByb3h5Q2FsbFRvU3RyaW5nLmNhbGwoe1xuICAgICAgICAgICAgcHJveHk6IHRoaXMubWV0aG9kIHx8IFwiYW5vbnltb3VzIG1vY2sgZXhwZWN0YXRpb25cIixcbiAgICAgICAgICAgIGFyZ3M6IGFyZ3MsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBgJHtjYWxsU3RyLnJlcGxhY2UoXG4gICAgICAgICAgICBcIiwgWy4uLlwiLFxuICAgICAgICAgICAgXCJbLCAuLi5cIixcbiAgICAgICAgKX0gJHtleHBlY3RlZENhbGxDb3VudEluV29yZHModGhpcyl9YDtcblxuICAgICAgICBpZiAodGhpcy5tZXQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGBFeHBlY3RhdGlvbiBtZXQ6ICR7bWVzc2FnZX1gO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGBFeHBlY3RlZCAke21lc3NhZ2V9ICgke2NhbGxDb3VudEluV29yZHModGhpcy5jYWxsQ291bnQpfSlgO1xuICAgIH0sXG5cbiAgICB2ZXJpZnk6IGZ1bmN0aW9uIHZlcmlmeSgpIHtcbiAgICAgICAgaWYgKCF0aGlzLm1ldCgpKSB7XG4gICAgICAgICAgICBtb2NrRXhwZWN0YXRpb24uZmFpbChTdHJpbmcodGhpcykpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbW9ja0V4cGVjdGF0aW9uLnBhc3MoU3RyaW5nKHRoaXMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICBwYXNzOiBmdW5jdGlvbiBwYXNzKG1lc3NhZ2UpIHtcbiAgICAgICAgYXNzZXJ0LnBhc3MobWVzc2FnZSk7XG4gICAgfSxcblxuICAgIGZhaWw6IGZ1bmN0aW9uIGZhaWwobWVzc2FnZSkge1xuICAgICAgICBjb25zdCBleGNlcHRpb24gPSBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgICAgIGV4Y2VwdGlvbi5uYW1lID0gXCJFeHBlY3RhdGlvbkVycm9yXCI7XG5cbiAgICAgICAgdGhyb3cgZXhjZXB0aW9uO1xuICAgIH0sXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IG1vY2tFeHBlY3RhdGlvbjtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5jb25zdCBhcnJheVByb3RvID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikucHJvdG90eXBlcy5hcnJheTtcbmNvbnN0IG1vY2tFeHBlY3RhdGlvbiA9IHJlcXVpcmUoXCIuL21vY2stZXhwZWN0YXRpb25cIik7XG5jb25zdCBwcm94eUNhbGxUb1N0cmluZyA9IHJlcXVpcmUoXCIuL3Byb3h5LWNhbGxcIikudG9TdHJpbmc7XG5jb25zdCBleHRlbmQgPSByZXF1aXJlKFwiLi91dGlsL2NvcmUvZXh0ZW5kXCIpO1xuY29uc3QgZGVlcEVxdWFsID0gcmVxdWlyZShcIkBzaW5vbmpzL3NhbXNhbVwiKS5kZWVwRXF1YWw7XG5jb25zdCB3cmFwTWV0aG9kID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlL3dyYXAtbWV0aG9kXCIpO1xuXG5jb25zdCBjb25jYXQgPSBhcnJheVByb3RvLmNvbmNhdDtcbmNvbnN0IGZpbHRlciA9IGFycmF5UHJvdG8uZmlsdGVyO1xuY29uc3QgZm9yRWFjaCA9IGFycmF5UHJvdG8uZm9yRWFjaDtcbmNvbnN0IGV2ZXJ5ID0gYXJyYXlQcm90by5ldmVyeTtcbmNvbnN0IGpvaW4gPSBhcnJheVByb3RvLmpvaW47XG5jb25zdCBwdXNoID0gYXJyYXlQcm90by5wdXNoO1xuY29uc3Qgc2xpY2UgPSBhcnJheVByb3RvLnNsaWNlO1xuY29uc3QgdW5zaGlmdCA9IGFycmF5UHJvdG8udW5zaGlmdDtcblxuZnVuY3Rpb24gbW9jayhvYmplY3QpIHtcbiAgICBpZiAoIW9iamVjdCB8fCB0eXBlb2Ygb2JqZWN0ID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIHJldHVybiBtb2NrRXhwZWN0YXRpb24uY3JlYXRlKG9iamVjdCA/IG9iamVjdCA6IFwiQW5vbnltb3VzIG1vY2tcIik7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vY2suY3JlYXRlKG9iamVjdCk7XG59XG5cbmZ1bmN0aW9uIGVhY2goY29sbGVjdGlvbiwgY2FsbGJhY2spIHtcbiAgICBjb25zdCBjb2wgPSBjb2xsZWN0aW9uIHx8IFtdO1xuXG4gICAgZm9yRWFjaChjb2wsIGNhbGxiYWNrKTtcbn1cblxuZnVuY3Rpb24gYXJyYXlFcXVhbHMoYXJyMSwgYXJyMiwgY29tcGFyZUxlbmd0aCkge1xuICAgIGlmIChjb21wYXJlTGVuZ3RoICYmIGFycjEubGVuZ3RoICE9PSBhcnIyLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIGV2ZXJ5KGFycjEsIGZ1bmN0aW9uIChlbGVtZW50LCBpKSB7XG4gICAgICAgIHJldHVybiBkZWVwRXF1YWwoYXJyMltpXSwgZWxlbWVudCk7XG4gICAgfSk7XG59XG5cbmV4dGVuZChtb2NrLCB7XG4gICAgY3JlYXRlOiBmdW5jdGlvbiBjcmVhdGUob2JqZWN0KSB7XG4gICAgICAgIGlmICghb2JqZWN0KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwib2JqZWN0IGlzIG51bGxcIik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBtb2NrT2JqZWN0ID0gZXh0ZW5kLm5vbkVudW0oe30sIG1vY2ssIHsgb2JqZWN0OiBvYmplY3QgfSk7XG4gICAgICAgIGRlbGV0ZSBtb2NrT2JqZWN0LmNyZWF0ZTtcblxuICAgICAgICByZXR1cm4gbW9ja09iamVjdDtcbiAgICB9LFxuXG4gICAgZXhwZWN0czogZnVuY3Rpb24gZXhwZWN0cyhtZXRob2QpIHtcbiAgICAgICAgaWYgKCFtZXRob2QpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJtZXRob2QgaXMgZmFsc3lcIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuZXhwZWN0YXRpb25zKSB7XG4gICAgICAgICAgICB0aGlzLmV4cGVjdGF0aW9ucyA9IHt9O1xuICAgICAgICAgICAgdGhpcy5wcm94aWVzID0gW107XG4gICAgICAgICAgICB0aGlzLmZhaWx1cmVzID0gW107XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuZXhwZWN0YXRpb25zW21ldGhvZF0pIHtcbiAgICAgICAgICAgIHRoaXMuZXhwZWN0YXRpb25zW21ldGhvZF0gPSBbXTtcbiAgICAgICAgICAgIGNvbnN0IG1vY2tPYmplY3QgPSB0aGlzO1xuXG4gICAgICAgICAgICB3cmFwTWV0aG9kKHRoaXMub2JqZWN0LCBtZXRob2QsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9ja09iamVjdC5pbnZva2VNZXRob2QobWV0aG9kLCB0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHB1c2godGhpcy5wcm94aWVzLCBtZXRob2QpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZXhwZWN0YXRpb24gPSBtb2NrRXhwZWN0YXRpb24uY3JlYXRlKG1ldGhvZCk7XG4gICAgICAgIGV4cGVjdGF0aW9uLndyYXBwZWRNZXRob2QgPSB0aGlzLm9iamVjdFttZXRob2RdLndyYXBwZWRNZXRob2Q7XG4gICAgICAgIHB1c2godGhpcy5leHBlY3RhdGlvbnNbbWV0aG9kXSwgZXhwZWN0YXRpb24pO1xuXG4gICAgICAgIHJldHVybiBleHBlY3RhdGlvbjtcbiAgICB9LFxuXG4gICAgcmVzdG9yZTogZnVuY3Rpb24gcmVzdG9yZSgpIHtcbiAgICAgICAgY29uc3Qgb2JqZWN0ID0gdGhpcy5vYmplY3Q7XG5cbiAgICAgICAgZWFjaCh0aGlzLnByb3hpZXMsIGZ1bmN0aW9uIChwcm94eSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3RbcHJveHldLnJlc3RvcmUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIG9iamVjdFtwcm94eV0ucmVzdG9yZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9LFxuXG4gICAgdmVyaWZ5OiBmdW5jdGlvbiB2ZXJpZnkoKSB7XG4gICAgICAgIGNvbnN0IGV4cGVjdGF0aW9ucyA9IHRoaXMuZXhwZWN0YXRpb25zIHx8IHt9O1xuICAgICAgICBjb25zdCBtZXNzYWdlcyA9IHRoaXMuZmFpbHVyZXMgPyBzbGljZSh0aGlzLmZhaWx1cmVzKSA6IFtdO1xuICAgICAgICBjb25zdCBtZXQgPSBbXTtcblxuICAgICAgICBlYWNoKHRoaXMucHJveGllcywgZnVuY3Rpb24gKHByb3h5KSB7XG4gICAgICAgICAgICBlYWNoKGV4cGVjdGF0aW9uc1twcm94eV0sIGZ1bmN0aW9uIChleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgICAgIGlmICghZXhwZWN0YXRpb24ubWV0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHVzaChtZXNzYWdlcywgU3RyaW5nKGV4cGVjdGF0aW9uKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcHVzaChtZXQsIFN0cmluZyhleHBlY3RhdGlvbikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnJlc3RvcmUoKTtcblxuICAgICAgICBpZiAobWVzc2FnZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgbW9ja0V4cGVjdGF0aW9uLmZhaWwoam9pbihjb25jYXQobWVzc2FnZXMsIG1ldCksIFwiXFxuXCIpKTtcbiAgICAgICAgfSBlbHNlIGlmIChtZXQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgbW9ja0V4cGVjdGF0aW9uLnBhc3Moam9pbihjb25jYXQobWVzc2FnZXMsIG1ldCksIFwiXFxuXCIpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG5cbiAgICBpbnZva2VNZXRob2Q6IGZ1bmN0aW9uIGludm9rZU1ldGhvZChtZXRob2QsIHRoaXNWYWx1ZSwgYXJncykge1xuICAgICAgICAvKiBpZiB3ZSBjYW5ub3QgZmluZCBhbnkgbWF0Y2hpbmcgZmlsZXMgd2Ugd2lsbCBleHBsaWNpdGx5IGNhbGwgbW9ja0V4cGVjdGlvbiNmYWlsIHdpdGggZXJyb3IgbWVzc2FnZXMgKi9cbiAgICAgICAgLyogZXNsaW50IGNvbnNpc3RlbnQtcmV0dXJuOiBcIm9mZlwiICovXG4gICAgICAgIGNvbnN0IGV4cGVjdGF0aW9ucyA9XG4gICAgICAgICAgICB0aGlzLmV4cGVjdGF0aW9ucyAmJiB0aGlzLmV4cGVjdGF0aW9uc1ttZXRob2RdXG4gICAgICAgICAgICAgICAgPyB0aGlzLmV4cGVjdGF0aW9uc1ttZXRob2RdXG4gICAgICAgICAgICAgICAgOiBbXTtcbiAgICAgICAgY29uc3QgY3VycmVudEFyZ3MgPSBhcmdzIHx8IFtdO1xuICAgICAgICBsZXQgYXZhaWxhYmxlO1xuXG4gICAgICAgIGNvbnN0IGV4cGVjdGF0aW9uc1dpdGhNYXRjaGluZ0FyZ3MgPSBmaWx0ZXIoXG4gICAgICAgICAgICBleHBlY3RhdGlvbnMsXG4gICAgICAgICAgICBmdW5jdGlvbiAoZXhwZWN0YXRpb24pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBleHBlY3RlZEFyZ3MgPSBleHBlY3RhdGlvbi5leHBlY3RlZEFyZ3VtZW50cyB8fCBbXTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBhcnJheUVxdWFscyhcbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0ZWRBcmdzLFxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50QXJncyxcbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0YXRpb24uZXhwZWN0c0V4YWN0QXJnQ291bnQsXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgZXhwZWN0YXRpb25zVG9BcHBseSA9IGZpbHRlcihcbiAgICAgICAgICAgIGV4cGVjdGF0aW9uc1dpdGhNYXRjaGluZ0FyZ3MsXG4gICAgICAgICAgICBmdW5jdGlvbiAoZXhwZWN0YXRpb24pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgICAgICAhZXhwZWN0YXRpb24ubWV0KCkgJiZcbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0YXRpb24uYWxsb3dzQ2FsbCh0aGlzVmFsdWUsIGFyZ3MpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKGV4cGVjdGF0aW9uc1RvQXBwbHkubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGV4cGVjdGF0aW9uc1RvQXBwbHlbMF0uYXBwbHkodGhpc1ZhbHVlLCBhcmdzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gW107XG4gICAgICAgIGxldCBleGhhdXN0ZWQgPSAwO1xuXG4gICAgICAgIGZvckVhY2goZXhwZWN0YXRpb25zV2l0aE1hdGNoaW5nQXJncywgZnVuY3Rpb24gKGV4cGVjdGF0aW9uKSB7XG4gICAgICAgICAgICBpZiAoZXhwZWN0YXRpb24uYWxsb3dzQ2FsbCh0aGlzVmFsdWUsIGFyZ3MpKSB7XG4gICAgICAgICAgICAgICAgYXZhaWxhYmxlID0gYXZhaWxhYmxlIHx8IGV4cGVjdGF0aW9uO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBleGhhdXN0ZWQgKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKGF2YWlsYWJsZSAmJiBleGhhdXN0ZWQgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBhdmFpbGFibGUuYXBwbHkodGhpc1ZhbHVlLCBhcmdzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvckVhY2goZXhwZWN0YXRpb25zLCBmdW5jdGlvbiAoZXhwZWN0YXRpb24pIHtcbiAgICAgICAgICAgIHB1c2gobWVzc2FnZXMsIGAgICAgJHtTdHJpbmcoZXhwZWN0YXRpb24pfWApO1xuICAgICAgICB9KTtcblxuICAgICAgICB1bnNoaWZ0KFxuICAgICAgICAgICAgbWVzc2FnZXMsXG4gICAgICAgICAgICBgVW5leHBlY3RlZCBjYWxsOiAke3Byb3h5Q2FsbFRvU3RyaW5nLmNhbGwoe1xuICAgICAgICAgICAgICAgIHByb3h5OiBtZXRob2QsXG4gICAgICAgICAgICAgICAgYXJnczogYXJncyxcbiAgICAgICAgICAgIH0pfWAsXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3QgZXJyID0gbmV3IEVycm9yKCk7XG4gICAgICAgIGlmICghZXJyLnN0YWNrKSB7XG4gICAgICAgICAgICAvLyBQaGFudG9tSlMgZG9lcyBub3Qgc2VyaWFsaXplIHRoZSBzdGFjayB0cmFjZSB1bnRpbCB0aGUgZXJyb3IgaGFzIGJlZW4gdGhyb3duXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAvKiBlbXB0eSAqL1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHB1c2goXG4gICAgICAgICAgICB0aGlzLmZhaWx1cmVzLFxuICAgICAgICAgICAgYFVuZXhwZWN0ZWQgY2FsbDogJHtwcm94eUNhbGxUb1N0cmluZy5jYWxsKHtcbiAgICAgICAgICAgICAgICBwcm94eTogbWV0aG9kLFxuICAgICAgICAgICAgICAgIGFyZ3M6IGFyZ3MsXG4gICAgICAgICAgICAgICAgc3RhY2s6IGVyci5zdGFjayxcbiAgICAgICAgICAgIH0pfWAsXG4gICAgICAgICk7XG5cbiAgICAgICAgbW9ja0V4cGVjdGF0aW9uLmZhaWwoam9pbihtZXNzYWdlcywgXCJcXG5cIikpO1xuICAgIH0sXG59KTtcblxubW9kdWxlLmV4cG9ydHMgPSBtb2NrO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IGZha2UgPSByZXF1aXJlKFwiLi9mYWtlXCIpO1xuY29uc3QgaXNSZXN0b3JhYmxlID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlL2lzLXJlc3RvcmFibGVcIik7XG5cbmNvbnN0IFNUQVRVU19QRU5ESU5HID0gXCJwZW5kaW5nXCI7XG5jb25zdCBTVEFUVVNfUkVTT0xWRUQgPSBcInJlc29sdmVkXCI7XG5jb25zdCBTVEFUVVNfUkVKRUNURUQgPSBcInJlamVjdGVkXCI7XG5cbi8qKlxuICogUmV0dXJucyBhIGZha2UgZm9yIGEgZ2l2ZW4gZnVuY3Rpb24gb3IgdW5kZWZpbmVkLiBJZiBubyBmdW5jdGlvbiBpcyBnaXZlbiwgYVxuICogbmV3IGZha2UgaXMgcmV0dXJuZWQuIElmIHRoZSBnaXZlbiBmdW5jdGlvbiBpcyBhbHJlYWR5IGEgZmFrZSwgaXQgaXNcbiAqIHJldHVybmVkIGFzIGlzLiBPdGhlcndpc2UgdGhlIGdpdmVuIGZ1bmN0aW9uIGlzIHdyYXBwZWQgaW4gYSBuZXcgZmFrZS5cbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbZXhlY3V0b3JdIFRoZSBvcHRpb25hbCBleGVjdXRvciBmdW5jdGlvbi5cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn1cbiAqL1xuZnVuY3Rpb24gZ2V0RmFrZUV4ZWN1dG9yKGV4ZWN1dG9yKSB7XG4gICAgaWYgKGlzUmVzdG9yYWJsZShleGVjdXRvcikpIHtcbiAgICAgICAgcmV0dXJuIGV4ZWN1dG9yO1xuICAgIH1cbiAgICBpZiAoZXhlY3V0b3IpIHtcbiAgICAgICAgcmV0dXJuIGZha2UoZXhlY3V0b3IpO1xuICAgIH1cbiAgICByZXR1cm4gZmFrZSgpO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBuZXcgcHJvbWlzZSB0aGF0IGV4cG9zZXMgaXQncyBpbnRlcm5hbCBgc3RhdHVzYCwgYHJlc29sdmVkVmFsdWVgXG4gKiBhbmQgYHJlamVjdGVkVmFsdWVgIGFuZCBjYW4gYmUgcmVzb2x2ZWQgb3IgcmVqZWN0ZWQgZnJvbSB0aGUgb3V0c2lkZSBieVxuICogY2FsbGluZyBgcmVzb2x2ZSh2YWx1ZSlgIG9yIGByZWplY3QocmVhc29uKWAuXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW2V4ZWN1dG9yXSBUaGUgb3B0aW9uYWwgZXhlY3V0b3IgZnVuY3Rpb24uXG4gKiBAcmV0dXJucyB7UHJvbWlzZX1cbiAqL1xuZnVuY3Rpb24gcHJvbWlzZShleGVjdXRvcikge1xuICAgIGNvbnN0IGZha2VFeGVjdXRvciA9IGdldEZha2VFeGVjdXRvcihleGVjdXRvcik7XG4gICAgY29uc3Qgc2lub25Qcm9taXNlID0gbmV3IFByb21pc2UoZmFrZUV4ZWN1dG9yKTtcblxuICAgIHNpbm9uUHJvbWlzZS5zdGF0dXMgPSBTVEFUVVNfUEVORElORztcbiAgICBzaW5vblByb21pc2VcbiAgICAgICAgLnRoZW4oZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICBzaW5vblByb21pc2Uuc3RhdHVzID0gU1RBVFVTX1JFU09MVkVEO1xuICAgICAgICAgICAgc2lub25Qcm9taXNlLnJlc29sdmVkVmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHtcbiAgICAgICAgICAgIHNpbm9uUHJvbWlzZS5zdGF0dXMgPSBTVEFUVVNfUkVKRUNURUQ7XG4gICAgICAgICAgICBzaW5vblByb21pc2UucmVqZWN0ZWRWYWx1ZSA9IHJlYXNvbjtcbiAgICAgICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiBSZXNvbHZlcyBvciByZWplY3RzIHRoZSBwcm9taXNlIHdpdGggdGhlIGdpdmVuIHN0YXR1cyBhbmQgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RhdHVzXG4gICAgICogQHBhcmFtIHsqfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gICAgICovXG4gICAgZnVuY3Rpb24gZmluYWxpemUoc3RhdHVzLCB2YWx1ZSwgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKHNpbm9uUHJvbWlzZS5zdGF0dXMgIT09IFNUQVRVU19QRU5ESU5HKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFByb21pc2UgYWxyZWFkeSAke3Npbm9uUHJvbWlzZS5zdGF0dXN9YCk7XG4gICAgICAgIH1cblxuICAgICAgICBzaW5vblByb21pc2Uuc3RhdHVzID0gc3RhdHVzO1xuICAgICAgICBjYWxsYmFjayh2YWx1ZSk7XG4gICAgfVxuXG4gICAgc2lub25Qcm9taXNlLnJlc29sdmUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgZmluYWxpemUoU1RBVFVTX1JFU09MVkVELCB2YWx1ZSwgZmFrZUV4ZWN1dG9yLmZpcnN0Q2FsbC5hcmdzWzBdKTtcbiAgICAgICAgLy8gUmV0dXJuIHRoZSBwcm9taXNlIHNvIHRoYXQgY2FsbGVycyBjYW4gYXdhaXQgaXQ6XG4gICAgICAgIHJldHVybiBzaW5vblByb21pc2U7XG4gICAgfTtcbiAgICBzaW5vblByb21pc2UucmVqZWN0ID0gZnVuY3Rpb24gKHJlYXNvbikge1xuICAgICAgICBmaW5hbGl6ZShTVEFUVVNfUkVKRUNURUQsIHJlYXNvbiwgZmFrZUV4ZWN1dG9yLmZpcnN0Q2FsbC5hcmdzWzFdKTtcbiAgICAgICAgLy8gUmV0dXJuIGEgbmV3IHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBzaW5vbiBwcm9taXNlIHdhc1xuICAgICAgICAvLyByZWplY3RlZCwgc28gdGhhdCBjYWxsZXJzIGNhbiBhd2FpdCBpdDpcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlKSB7XG4gICAgICAgICAgICBzaW5vblByb21pc2UuY2F0Y2goKCkgPT4gcmVzb2x2ZSgpKTtcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIHJldHVybiBzaW5vblByb21pc2U7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gcHJvbWlzZTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5jb25zdCBwdXNoID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikucHJvdG90eXBlcy5hcnJheS5wdXNoO1xuXG5leHBvcnRzLmluY3JlbWVudENhbGxDb3VudCA9IGZ1bmN0aW9uIGluY3JlbWVudENhbGxDb3VudChwcm94eSkge1xuICAgIHByb3h5LmNhbGxlZCA9IHRydWU7XG4gICAgcHJveHkuY2FsbENvdW50ICs9IDE7XG4gICAgcHJveHkubm90Q2FsbGVkID0gZmFsc2U7XG4gICAgcHJveHkuY2FsbGVkT25jZSA9IHByb3h5LmNhbGxDb3VudCA9PT0gMTtcbiAgICBwcm94eS5jYWxsZWRUd2ljZSA9IHByb3h5LmNhbGxDb3VudCA9PT0gMjtcbiAgICBwcm94eS5jYWxsZWRUaHJpY2UgPSBwcm94eS5jYWxsQ291bnQgPT09IDM7XG59O1xuXG5leHBvcnRzLmNyZWF0ZUNhbGxQcm9wZXJ0aWVzID0gZnVuY3Rpb24gY3JlYXRlQ2FsbFByb3BlcnRpZXMocHJveHkpIHtcbiAgICBwcm94eS5maXJzdENhbGwgPSBwcm94eS5nZXRDYWxsKDApO1xuICAgIHByb3h5LnNlY29uZENhbGwgPSBwcm94eS5nZXRDYWxsKDEpO1xuICAgIHByb3h5LnRoaXJkQ2FsbCA9IHByb3h5LmdldENhbGwoMik7XG4gICAgcHJveHkubGFzdENhbGwgPSBwcm94eS5nZXRDYWxsKHByb3h5LmNhbGxDb3VudCAtIDEpO1xufTtcblxuZXhwb3J0cy5kZWxlZ2F0ZVRvQ2FsbHMgPSBmdW5jdGlvbiBkZWxlZ2F0ZVRvQ2FsbHMoXG4gICAgcHJveHksXG4gICAgbWV0aG9kLFxuICAgIG1hdGNoQW55LFxuICAgIGFjdHVhbCxcbiAgICByZXR1cm5zVmFsdWVzLFxuICAgIG5vdENhbGxlZCxcbiAgICB0b3RhbENhbGxDb3VudCxcbikge1xuICAgIHByb3h5W21ldGhvZF0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5jYWxsZWQpIHtcbiAgICAgICAgICAgIGlmIChub3RDYWxsZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbm90Q2FsbGVkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodG90YWxDYWxsQ291bnQgIT09IHVuZGVmaW5lZCAmJiB0aGlzLmNhbGxDb3VudCAhPT0gdG90YWxDYWxsQ291bnQpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBjdXJyZW50Q2FsbDtcbiAgICAgICAgbGV0IG1hdGNoZXMgPSAwO1xuICAgICAgICBjb25zdCByZXR1cm5WYWx1ZXMgPSBbXTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMCwgbCA9IHRoaXMuY2FsbENvdW50OyBpIDwgbDsgaSArPSAxKSB7XG4gICAgICAgICAgICBjdXJyZW50Q2FsbCA9IHRoaXMuZ2V0Q2FsbChpKTtcbiAgICAgICAgICAgIGNvbnN0IHJldHVyblZhbHVlID0gY3VycmVudENhbGxbYWN0dWFsIHx8IG1ldGhvZF0uYXBwbHkoXG4gICAgICAgICAgICAgICAgY3VycmVudENhbGwsXG4gICAgICAgICAgICAgICAgYXJndW1lbnRzLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHB1c2gocmV0dXJuVmFsdWVzLCByZXR1cm5WYWx1ZSk7XG4gICAgICAgICAgICBpZiAocmV0dXJuVmFsdWUpIHtcbiAgICAgICAgICAgICAgICBtYXRjaGVzICs9IDE7XG5cbiAgICAgICAgICAgICAgICBpZiAobWF0Y2hBbnkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJldHVybnNWYWx1ZXMpIHtcbiAgICAgICAgICAgIHJldHVybiByZXR1cm5WYWx1ZXM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1hdGNoZXMgPT09IHRoaXMuY2FsbENvdW50O1xuICAgIH07XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IGFycmF5UHJvdG8gPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLmFycmF5O1xuY29uc3QgbWF0Y2ggPSByZXF1aXJlKFwiQHNpbm9uanMvc2Ftc2FtXCIpLmNyZWF0ZU1hdGNoZXI7XG5jb25zdCBkZWVwRXF1YWwgPSByZXF1aXJlKFwiQHNpbm9uanMvc2Ftc2FtXCIpLmRlZXBFcXVhbDtcbmNvbnN0IGZ1bmN0aW9uTmFtZSA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLmZ1bmN0aW9uTmFtZTtcbmNvbnN0IGluc3BlY3QgPSByZXF1aXJlKFwidXRpbFwiKS5pbnNwZWN0O1xuY29uc3QgdmFsdWVUb1N0cmluZyA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnZhbHVlVG9TdHJpbmc7XG5cbmNvbnN0IGNvbmNhdCA9IGFycmF5UHJvdG8uY29uY2F0O1xuY29uc3QgZmlsdGVyID0gYXJyYXlQcm90by5maWx0ZXI7XG5jb25zdCBqb2luID0gYXJyYXlQcm90by5qb2luO1xuY29uc3QgbWFwID0gYXJyYXlQcm90by5tYXA7XG5jb25zdCByZWR1Y2UgPSBhcnJheVByb3RvLnJlZHVjZTtcbmNvbnN0IHNsaWNlID0gYXJyYXlQcm90by5zbGljZTtcblxuLyoqXG4gKiBAcGFyYW0gcHJveHlcbiAqIEBwYXJhbSB0ZXh0XG4gKiBAcGFyYW0gYXJnc1xuICovXG5mdW5jdGlvbiB0aHJvd1lpZWxkRXJyb3IocHJveHksIHRleHQsIGFyZ3MpIHtcbiAgICBsZXQgbXNnID0gZnVuY3Rpb25OYW1lKHByb3h5KSArIHRleHQ7XG4gICAgaWYgKGFyZ3MubGVuZ3RoKSB7XG4gICAgICAgIG1zZyArPSBgIFJlY2VpdmVkIFske2pvaW4oc2xpY2UoYXJncyksIFwiLCBcIil9XWA7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xufVxuXG5jb25zdCBjYWxsUHJvdG8gPSB7XG4gICAgY2FsbGVkT246IGZ1bmN0aW9uIGNhbGxlZE9uKHRoaXNWYWx1ZSkge1xuICAgICAgICBpZiAobWF0Y2guaXNNYXRjaGVyKHRoaXNWYWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzVmFsdWUudGVzdCh0aGlzLnRoaXNWYWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMudGhpc1ZhbHVlID09PSB0aGlzVmFsdWU7XG4gICAgfSxcblxuICAgIGNhbGxlZFdpdGg6IGZ1bmN0aW9uIGNhbGxlZFdpdGgoKSB7XG4gICAgICAgIGNvbnN0IHNlbGYgPSB0aGlzO1xuICAgICAgICBjb25zdCBjYWxsZWRXaXRoQXJncyA9IHNsaWNlKGFyZ3VtZW50cyk7XG5cbiAgICAgICAgaWYgKGNhbGxlZFdpdGhBcmdzLmxlbmd0aCA+IHNlbGYuYXJncy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZWR1Y2UoXG4gICAgICAgICAgICBjYWxsZWRXaXRoQXJncyxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChwcmV2LCBhcmcsIGkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcHJldiAmJiBkZWVwRXF1YWwoc2VsZi5hcmdzW2ldLCBhcmcpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRydWUsXG4gICAgICAgICk7XG4gICAgfSxcblxuICAgIGNhbGxlZFdpdGhNYXRjaDogZnVuY3Rpb24gY2FsbGVkV2l0aE1hdGNoKCkge1xuICAgICAgICBjb25zdCBzZWxmID0gdGhpcztcbiAgICAgICAgY29uc3QgY2FsbGVkV2l0aE1hdGNoQXJncyA9IHNsaWNlKGFyZ3VtZW50cyk7XG5cbiAgICAgICAgaWYgKGNhbGxlZFdpdGhNYXRjaEFyZ3MubGVuZ3RoID4gc2VsZi5hcmdzLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlZHVjZShcbiAgICAgICAgICAgIGNhbGxlZFdpdGhNYXRjaEFyZ3MsXG4gICAgICAgICAgICBmdW5jdGlvbiAocHJldiwgZXhwZWN0YXRpb24sIGkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBhY3R1YWwgPSBzZWxmLmFyZ3NbaV07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJldiAmJiBtYXRjaChleHBlY3RhdGlvbikudGVzdChhY3R1YWwpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRydWUsXG4gICAgICAgICk7XG4gICAgfSxcblxuICAgIGNhbGxlZFdpdGhFeGFjdGx5OiBmdW5jdGlvbiBjYWxsZWRXaXRoRXhhY3RseSgpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGFyZ3VtZW50cy5sZW5ndGggPT09IHRoaXMuYXJncy5sZW5ndGggJiZcbiAgICAgICAgICAgIHRoaXMuY2FsbGVkV2l0aC5hcHBseSh0aGlzLCBhcmd1bWVudHMpXG4gICAgICAgICk7XG4gICAgfSxcblxuICAgIG5vdENhbGxlZFdpdGg6IGZ1bmN0aW9uIG5vdENhbGxlZFdpdGgoKSB7XG4gICAgICAgIHJldHVybiAhdGhpcy5jYWxsZWRXaXRoLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfSxcblxuICAgIG5vdENhbGxlZFdpdGhNYXRjaDogZnVuY3Rpb24gbm90Q2FsbGVkV2l0aE1hdGNoKCkge1xuICAgICAgICByZXR1cm4gIXRoaXMuY2FsbGVkV2l0aE1hdGNoLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfSxcblxuICAgIHJldHVybmVkOiBmdW5jdGlvbiByZXR1cm5lZCh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gZGVlcEVxdWFsKHRoaXMucmV0dXJuVmFsdWUsIHZhbHVlKTtcbiAgICB9LFxuXG4gICAgdGhyZXc6IGZ1bmN0aW9uIHRocmV3KGVycm9yKSB7XG4gICAgICAgIGlmICh0eXBlb2YgZXJyb3IgPT09IFwidW5kZWZpbmVkXCIgfHwgIXRoaXMuZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gQm9vbGVhbih0aGlzLmV4Y2VwdGlvbik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5leGNlcHRpb24gPT09IGVycm9yIHx8IHRoaXMuZXhjZXB0aW9uLm5hbWUgPT09IGVycm9yO1xuICAgIH0sXG5cbiAgICBjYWxsZWRXaXRoTmV3OiBmdW5jdGlvbiBjYWxsZWRXaXRoTmV3KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5wcm94eS5wcm90b3R5cGUgJiYgdGhpcy50aGlzVmFsdWUgaW5zdGFuY2VvZiB0aGlzLnByb3h5O1xuICAgIH0sXG5cbiAgICBjYWxsZWRCZWZvcmU6IGZ1bmN0aW9uIChvdGhlcikge1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxsSWQgPCBvdGhlci5jYWxsSWQ7XG4gICAgfSxcblxuICAgIGNhbGxlZEFmdGVyOiBmdW5jdGlvbiAob3RoZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsbElkID4gb3RoZXIuY2FsbElkO1xuICAgIH0sXG5cbiAgICBjYWxsZWRJbW1lZGlhdGVseUJlZm9yZTogZnVuY3Rpb24gKG90aGVyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGxJZCA9PT0gb3RoZXIuY2FsbElkIC0gMTtcbiAgICB9LFxuXG4gICAgY2FsbGVkSW1tZWRpYXRlbHlBZnRlcjogZnVuY3Rpb24gKG90aGVyKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhbGxJZCA9PT0gb3RoZXIuY2FsbElkICsgMTtcbiAgICB9LFxuXG4gICAgY2FsbEFyZzogZnVuY3Rpb24gKHBvcykge1xuICAgICAgICB0aGlzLmVuc3VyZUFyZ0lzQUZ1bmN0aW9uKHBvcyk7XG4gICAgICAgIHJldHVybiB0aGlzLmFyZ3NbcG9zXSgpO1xuICAgIH0sXG5cbiAgICBjYWxsQXJnT246IGZ1bmN0aW9uIChwb3MsIHRoaXNWYWx1ZSkge1xuICAgICAgICB0aGlzLmVuc3VyZUFyZ0lzQUZ1bmN0aW9uKHBvcyk7XG4gICAgICAgIHJldHVybiB0aGlzLmFyZ3NbcG9zXS5hcHBseSh0aGlzVmFsdWUpO1xuICAgIH0sXG5cbiAgICBjYWxsQXJnV2l0aDogZnVuY3Rpb24gKHBvcykge1xuICAgICAgICByZXR1cm4gdGhpcy5jYWxsQXJnT25XaXRoLmFwcGx5KFxuICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICAgIGNvbmNhdChbcG9zLCBudWxsXSwgc2xpY2UoYXJndW1lbnRzLCAxKSksXG4gICAgICAgICk7XG4gICAgfSxcblxuICAgIGNhbGxBcmdPbldpdGg6IGZ1bmN0aW9uIChwb3MsIHRoaXNWYWx1ZSkge1xuICAgICAgICB0aGlzLmVuc3VyZUFyZ0lzQUZ1bmN0aW9uKHBvcyk7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSBzbGljZShhcmd1bWVudHMsIDIpO1xuICAgICAgICByZXR1cm4gdGhpcy5hcmdzW3Bvc10uYXBwbHkodGhpc1ZhbHVlLCBhcmdzKTtcbiAgICB9LFxuXG4gICAgdGhyb3dBcmc6IGZ1bmN0aW9uIChwb3MpIHtcbiAgICAgICAgaWYgKHBvcyA+IHRoaXMuYXJncy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICAgICAgYE5vdCBlbm91Z2ggYXJndW1lbnRzOiAke3Bvc30gcmVxdWlyZWQgYnV0IG9ubHkgJHt0aGlzLmFyZ3MubGVuZ3RofSBwcmVzZW50YCxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyB0aGlzLmFyZ3NbcG9zXTtcbiAgICB9LFxuXG4gICAgeWllbGQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMueWllbGRPbi5hcHBseSh0aGlzLCBjb25jYXQoW251bGxdLCBzbGljZShhcmd1bWVudHMsIDApKSk7XG4gICAgfSxcblxuICAgIHlpZWxkT246IGZ1bmN0aW9uICh0aGlzVmFsdWUpIHtcbiAgICAgICAgY29uc3QgYXJncyA9IHNsaWNlKHRoaXMuYXJncyk7XG4gICAgICAgIGNvbnN0IHlpZWxkRm4gPSBmaWx0ZXIoYXJncywgZnVuY3Rpb24gKGFyZykge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBhcmcgPT09IFwiZnVuY3Rpb25cIjtcbiAgICAgICAgfSlbMF07XG5cbiAgICAgICAgaWYgKCF5aWVsZEZuKSB7XG4gICAgICAgICAgICB0aHJvd1lpZWxkRXJyb3IoXG4gICAgICAgICAgICAgICAgdGhpcy5wcm94eSxcbiAgICAgICAgICAgICAgICBcIiBjYW5ub3QgeWllbGQgc2luY2Ugbm8gY2FsbGJhY2sgd2FzIHBhc3NlZC5cIixcbiAgICAgICAgICAgICAgICBhcmdzLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB5aWVsZEZuLmFwcGx5KHRoaXNWYWx1ZSwgc2xpY2UoYXJndW1lbnRzLCAxKSk7XG4gICAgfSxcblxuICAgIHlpZWxkVG86IGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnlpZWxkVG9Pbi5hcHBseShcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICBjb25jYXQoW3Byb3AsIG51bGxdLCBzbGljZShhcmd1bWVudHMsIDEpKSxcbiAgICAgICAgKTtcbiAgICB9LFxuXG4gICAgeWllbGRUb09uOiBmdW5jdGlvbiAocHJvcCwgdGhpc1ZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSBzbGljZSh0aGlzLmFyZ3MpO1xuICAgICAgICBjb25zdCB5aWVsZEFyZyA9IGZpbHRlcihhcmdzLCBmdW5jdGlvbiAoYXJnKSB7XG4gICAgICAgICAgICByZXR1cm4gYXJnICYmIHR5cGVvZiBhcmdbcHJvcF0gPT09IFwiZnVuY3Rpb25cIjtcbiAgICAgICAgfSlbMF07XG4gICAgICAgIGNvbnN0IHlpZWxkRm4gPSB5aWVsZEFyZyAmJiB5aWVsZEFyZ1twcm9wXTtcblxuICAgICAgICBpZiAoIXlpZWxkRm4pIHtcbiAgICAgICAgICAgIHRocm93WWllbGRFcnJvcihcbiAgICAgICAgICAgICAgICB0aGlzLnByb3h5LFxuICAgICAgICAgICAgICAgIGAgY2Fubm90IHlpZWxkIHRvICcke3ZhbHVlVG9TdHJpbmcoXG4gICAgICAgICAgICAgICAgICAgIHByb3AsXG4gICAgICAgICAgICAgICAgKX0nIHNpbmNlIG5vIGNhbGxiYWNrIHdhcyBwYXNzZWQuYCxcbiAgICAgICAgICAgICAgICBhcmdzLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB5aWVsZEZuLmFwcGx5KHRoaXNWYWx1ZSwgc2xpY2UoYXJndW1lbnRzLCAyKSk7XG4gICAgfSxcblxuICAgIHRvU3RyaW5nOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5hcmdzKSB7XG4gICAgICAgICAgICByZXR1cm4gXCI6KFwiO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNhbGxTdHIgPSB0aGlzLnByb3h5ID8gYCR7U3RyaW5nKHRoaXMucHJveHkpfShgIDogXCJcIjtcbiAgICAgICAgY29uc3QgZm9ybWF0dGVkQXJncyA9IG1hcCh0aGlzLmFyZ3MsIGZ1bmN0aW9uIChhcmcpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnNwZWN0KGFyZyk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNhbGxTdHIgPSBgJHtjYWxsU3RyICsgam9pbihmb3JtYXR0ZWRBcmdzLCBcIiwgXCIpfSlgO1xuXG4gICAgICAgIGlmICh0eXBlb2YgdGhpcy5yZXR1cm5WYWx1ZSAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgY2FsbFN0ciArPSBgID0+ICR7aW5zcGVjdCh0aGlzLnJldHVyblZhbHVlKX1gO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICBjYWxsU3RyICs9IGAgISR7dGhpcy5leGNlcHRpb24ubmFtZX1gO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5leGNlcHRpb24ubWVzc2FnZSkge1xuICAgICAgICAgICAgICAgIGNhbGxTdHIgKz0gYCgke3RoaXMuZXhjZXB0aW9uLm1lc3NhZ2V9KWA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuc3RhY2spIHtcbiAgICAgICAgICAgIC8vIElmIHdlIGhhdmUgYSBzdGFjaywgYWRkIHRoZSBmaXJzdCBmcmFtZSB0aGF0J3MgaW4gZW5kLXVzZXIgY29kZVxuICAgICAgICAgICAgLy8gU2tpcCB0aGUgZmlyc3QgdHdvIGZyYW1lcyBiZWNhdXNlIHRoZXkgd2lsbCByZWZlciB0byBTaW5vbiBjb2RlXG4gICAgICAgICAgICBjYWxsU3RyICs9ICh0aGlzLnN0YWNrLnNwbGl0KFwiXFxuXCIpWzNdIHx8IFwidW5rbm93blwiKS5yZXBsYWNlKFxuICAgICAgICAgICAgICAgIC9eXFxzKig/OmF0XFxzK3xAKT8vLFxuICAgICAgICAgICAgICAgIFwiIGF0IFwiLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjYWxsU3RyO1xuICAgIH0sXG5cbiAgICBlbnN1cmVBcmdJc0FGdW5jdGlvbjogZnVuY3Rpb24gKHBvcykge1xuICAgICAgICBpZiAodHlwZW9mIHRoaXMuYXJnc1twb3NdICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICAgICAgYEV4cGVjdGVkIGFyZ3VtZW50IGF0IHBvc2l0aW9uICR7cG9zfSB0byBiZSBhIEZ1bmN0aW9uLCBidXQgd2FzICR7dHlwZW9mIHRoaXNcbiAgICAgICAgICAgICAgICAgICAgLmFyZ3NbcG9zXX1gLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH0sXG59O1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KGNhbGxQcm90bywgXCJzdGFja1wiLCB7XG4gICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICBjb25maWd1cmFibGU6IHRydWUsXG4gICAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAodGhpcy5lcnJvcldpdGhDYWxsU3RhY2sgJiYgdGhpcy5lcnJvcldpdGhDYWxsU3RhY2suc3RhY2spIHx8IFwiXCI7XG4gICAgfSxcbn0pO1xuXG5jYWxsUHJvdG8uaW52b2tlQ2FsbGJhY2sgPSBjYWxsUHJvdG8ueWllbGQ7XG5cbi8qKlxuICogQHBhcmFtIHByb3h5XG4gKiBAcGFyYW0gdGhpc1ZhbHVlXG4gKiBAcGFyYW0gYXJnc1xuICogQHBhcmFtIHJldHVyblZhbHVlXG4gKiBAcGFyYW0gZXhjZXB0aW9uXG4gKiBAcGFyYW0gaWRcbiAqIEBwYXJhbSBlcnJvcldpdGhDYWxsU3RhY2tcbiAqXG4gKiBAcmV0dXJucyB7b2JqZWN0fSBwcm94eUNhbGxcbiAqL1xuZnVuY3Rpb24gY3JlYXRlUHJveHlDYWxsKFxuICAgIHByb3h5LFxuICAgIHRoaXNWYWx1ZSxcbiAgICBhcmdzLFxuICAgIHJldHVyblZhbHVlLFxuICAgIGV4Y2VwdGlvbixcbiAgICBpZCxcbiAgICBlcnJvcldpdGhDYWxsU3RhY2ssXG4pIHtcbiAgICBpZiAodHlwZW9mIGlkICE9PSBcIm51bWJlclwiKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYWxsIGlkIGlzIG5vdCBhIG51bWJlclwiKTtcbiAgICB9XG5cbiAgICBsZXQgZmlyc3RBcmcsIGxhc3RBcmc7XG5cbiAgICBpZiAoYXJncy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGZpcnN0QXJnID0gYXJnc1swXTtcbiAgICAgICAgbGFzdEFyZyA9IGFyZ3NbYXJncy5sZW5ndGggLSAxXTtcbiAgICB9XG5cbiAgICBjb25zdCBwcm94eUNhbGwgPSBPYmplY3QuY3JlYXRlKGNhbGxQcm90byk7XG4gICAgY29uc3QgY2FsbGJhY2sgPVxuICAgICAgICBsYXN0QXJnICYmIHR5cGVvZiBsYXN0QXJnID09PSBcImZ1bmN0aW9uXCIgPyBsYXN0QXJnIDogdW5kZWZpbmVkO1xuXG4gICAgcHJveHlDYWxsLnByb3h5ID0gcHJveHk7XG4gICAgcHJveHlDYWxsLnRoaXNWYWx1ZSA9IHRoaXNWYWx1ZTtcbiAgICBwcm94eUNhbGwuYXJncyA9IGFyZ3M7XG4gICAgcHJveHlDYWxsLmZpcnN0QXJnID0gZmlyc3RBcmc7XG4gICAgcHJveHlDYWxsLmxhc3RBcmcgPSBsYXN0QXJnO1xuICAgIHByb3h5Q2FsbC5jYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgIHByb3h5Q2FsbC5yZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlO1xuICAgIHByb3h5Q2FsbC5leGNlcHRpb24gPSBleGNlcHRpb247XG4gICAgcHJveHlDYWxsLmNhbGxJZCA9IGlkO1xuICAgIHByb3h5Q2FsbC5lcnJvcldpdGhDYWxsU3RhY2sgPSBlcnJvcldpdGhDYWxsU3RhY2s7XG5cbiAgICByZXR1cm4gcHJveHlDYWxsO1xufVxuY3JlYXRlUHJveHlDYWxsLnRvU3RyaW5nID0gY2FsbFByb3RvLnRvU3RyaW5nOyAvLyB1c2VkIGJ5IG1vY2tzXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlUHJveHlDYWxsO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IGFycmF5UHJvdG8gPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLmFycmF5O1xuY29uc3QgcHJveHlDYWxsVXRpbCA9IHJlcXVpcmUoXCIuL3Byb3h5LWNhbGwtdXRpbFwiKTtcblxuY29uc3QgcHVzaCA9IGFycmF5UHJvdG8ucHVzaDtcbmNvbnN0IGZvckVhY2ggPSBhcnJheVByb3RvLmZvckVhY2g7XG5jb25zdCBjb25jYXQgPSBhcnJheVByb3RvLmNvbmNhdDtcbmNvbnN0IEVycm9yQ29uc3RydWN0b3IgPSBFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3I7XG5jb25zdCBiaW5kID0gRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQ7XG5cbmxldCBjYWxsSWQgPSAwO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGludm9rZShmdW5jLCB0aGlzVmFsdWUsIGFyZ3MpIHtcbiAgICBjb25zdCBtYXRjaGluZ3MgPSB0aGlzLm1hdGNoaW5nRmFrZXMoYXJncyk7XG4gICAgY29uc3QgY3VycmVudENhbGxJZCA9IGNhbGxJZCsrO1xuICAgIGxldCBleGNlcHRpb24sIHJldHVyblZhbHVlO1xuXG4gICAgcHJveHlDYWxsVXRpbC5pbmNyZW1lbnRDYWxsQ291bnQodGhpcyk7XG4gICAgcHVzaCh0aGlzLnRoaXNWYWx1ZXMsIHRoaXNWYWx1ZSk7XG4gICAgcHVzaCh0aGlzLmFyZ3MsIGFyZ3MpO1xuICAgIHB1c2godGhpcy5jYWxsSWRzLCBjdXJyZW50Q2FsbElkKTtcbiAgICBmb3JFYWNoKG1hdGNoaW5ncywgZnVuY3Rpb24gKG1hdGNoaW5nKSB7XG4gICAgICAgIHByb3h5Q2FsbFV0aWwuaW5jcmVtZW50Q2FsbENvdW50KG1hdGNoaW5nKTtcbiAgICAgICAgcHVzaChtYXRjaGluZy50aGlzVmFsdWVzLCB0aGlzVmFsdWUpO1xuICAgICAgICBwdXNoKG1hdGNoaW5nLmFyZ3MsIGFyZ3MpO1xuICAgICAgICBwdXNoKG1hdGNoaW5nLmNhbGxJZHMsIGN1cnJlbnRDYWxsSWQpO1xuICAgIH0pO1xuXG4gICAgLy8gTWFrZSBjYWxsIHByb3BlcnRpZXMgYXZhaWxhYmxlIGZyb20gd2l0aGluIHRoZSBzcGllZCBmdW5jdGlvbjpcbiAgICBwcm94eUNhbGxVdGlsLmNyZWF0ZUNhbGxQcm9wZXJ0aWVzKHRoaXMpO1xuICAgIGZvckVhY2gobWF0Y2hpbmdzLCBwcm94eUNhbGxVdGlsLmNyZWF0ZUNhbGxQcm9wZXJ0aWVzKTtcblxuICAgIHRyeSB7XG4gICAgICAgIHRoaXMuaW52b2tpbmcgPSB0cnVlO1xuXG4gICAgICAgIGNvbnN0IHRoaXNDYWxsID0gdGhpcy5nZXRDYWxsKHRoaXMuY2FsbENvdW50IC0gMSk7XG5cbiAgICAgICAgaWYgKHRoaXNDYWxsLmNhbGxlZFdpdGhOZXcoKSkge1xuICAgICAgICAgICAgLy8gQ2FsbCB0aHJvdWdoIHdpdGggYG5ld2BcbiAgICAgICAgICAgIHJldHVyblZhbHVlID0gbmV3IChiaW5kLmFwcGx5KFxuICAgICAgICAgICAgICAgIHRoaXMuZnVuYyB8fCBmdW5jLFxuICAgICAgICAgICAgICAgIGNvbmNhdChbdGhpc1ZhbHVlXSwgYXJncyksXG4gICAgICAgICAgICApKSgpO1xuXG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgdHlwZW9mIHJldHVyblZhbHVlICE9PSBcIm9iamVjdFwiICYmXG4gICAgICAgICAgICAgICAgdHlwZW9mIHJldHVyblZhbHVlICE9PSBcImZ1bmN0aW9uXCJcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVyblZhbHVlID0gdGhpc1ZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSAodGhpcy5mdW5jIHx8IGZ1bmMpLmFwcGx5KHRoaXNWYWx1ZSwgYXJncyk7XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGV4Y2VwdGlvbiA9IGU7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgZGVsZXRlIHRoaXMuaW52b2tpbmc7XG4gICAgfVxuXG4gICAgcHVzaCh0aGlzLmV4Y2VwdGlvbnMsIGV4Y2VwdGlvbik7XG4gICAgcHVzaCh0aGlzLnJldHVyblZhbHVlcywgcmV0dXJuVmFsdWUpO1xuICAgIGZvckVhY2gobWF0Y2hpbmdzLCBmdW5jdGlvbiAobWF0Y2hpbmcpIHtcbiAgICAgICAgcHVzaChtYXRjaGluZy5leGNlcHRpb25zLCBleGNlcHRpb24pO1xuICAgICAgICBwdXNoKG1hdGNoaW5nLnJldHVyblZhbHVlcywgcmV0dXJuVmFsdWUpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgZXJyID0gbmV3IEVycm9yQ29uc3RydWN0b3IoKTtcbiAgICAvLyAxLiBQbGVhc2UgZG8gbm90IGdldCBzdGFjayBhdCB0aGlzIHBvaW50LiBJdCBtYXkgYmUgc28gdmVyeSBzbG93LCBhbmQgbm90IGFjdHVhbGx5IHVzZWRcbiAgICAvLyAyLiBQaGFudG9tSlMgZG9lcyBub3Qgc2VyaWFsaXplIHRoZSBzdGFjayB0cmFjZSB1bnRpbCB0aGUgZXJyb3IgaGFzIGJlZW4gdGhyb3duOlxuICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Vycm9yL1N0YWNrXG4gICAgdHJ5IHtcbiAgICAgICAgdGhyb3cgZXJyO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLyogZW1wdHkgKi9cbiAgICB9XG4gICAgcHVzaCh0aGlzLmVycm9yc1dpdGhDYWxsU3RhY2ssIGVycik7XG4gICAgZm9yRWFjaChtYXRjaGluZ3MsIGZ1bmN0aW9uIChtYXRjaGluZykge1xuICAgICAgICBwdXNoKG1hdGNoaW5nLmVycm9yc1dpdGhDYWxsU3RhY2ssIGVycik7XG4gICAgfSk7XG5cbiAgICAvLyBNYWtlIHJldHVybiB2YWx1ZSBhbmQgZXhjZXB0aW9uIGF2YWlsYWJsZSBpbiB0aGUgY2FsbHM6XG4gICAgcHJveHlDYWxsVXRpbC5jcmVhdGVDYWxsUHJvcGVydGllcyh0aGlzKTtcbiAgICBmb3JFYWNoKG1hdGNoaW5ncywgcHJveHlDYWxsVXRpbC5jcmVhdGVDYWxsUHJvcGVydGllcyk7XG5cbiAgICBpZiAoZXhjZXB0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgZXhjZXB0aW9uO1xuICAgIH1cblxuICAgIHJldHVybiByZXR1cm5WYWx1ZTtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuY29uc3QgYXJyYXlQcm90byA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnByb3RvdHlwZXMuYXJyYXk7XG5jb25zdCBleHRlbmQgPSByZXF1aXJlKFwiLi91dGlsL2NvcmUvZXh0ZW5kXCIpO1xuY29uc3QgZnVuY3Rpb25Ub1N0cmluZyA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZS9mdW5jdGlvbi10by1zdHJpbmdcIik7XG5jb25zdCBwcm94eUNhbGwgPSByZXF1aXJlKFwiLi9wcm94eS1jYWxsXCIpO1xuY29uc3QgcHJveHlDYWxsVXRpbCA9IHJlcXVpcmUoXCIuL3Byb3h5LWNhbGwtdXRpbFwiKTtcbmNvbnN0IHByb3h5SW52b2tlID0gcmVxdWlyZShcIi4vcHJveHktaW52b2tlXCIpO1xuY29uc3QgaW5zcGVjdCA9IHJlcXVpcmUoXCJ1dGlsXCIpLmluc3BlY3Q7XG5cbmNvbnN0IHB1c2ggPSBhcnJheVByb3RvLnB1c2g7XG5jb25zdCBmb3JFYWNoID0gYXJyYXlQcm90by5mb3JFYWNoO1xuY29uc3Qgc2xpY2UgPSBhcnJheVByb3RvLnNsaWNlO1xuXG5jb25zdCBlbXB0eUZha2VzID0gT2JqZWN0LmZyZWV6ZShbXSk7XG5cbi8vIFB1YmxpYyBBUElcbmNvbnN0IHByb3h5QXBpID0ge1xuICAgIHRvU3RyaW5nOiBmdW5jdGlvblRvU3RyaW5nLFxuXG4gICAgbmFtZWQ6IGZ1bmN0aW9uIG5hbWVkKG5hbWUpIHtcbiAgICAgICAgdGhpcy5kaXNwbGF5TmFtZSA9IG5hbWU7XG4gICAgICAgIGNvbnN0IG5hbWVEZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0aGlzLCBcIm5hbWVcIik7XG4gICAgICAgIGlmIChuYW1lRGVzY3JpcHRvciAmJiBuYW1lRGVzY3JpcHRvci5jb25maWd1cmFibGUpIHtcbiAgICAgICAgICAgIC8vIElFIDExIGZ1bmN0aW9ucyBkb24ndCBoYXZlIGEgbmFtZS5cbiAgICAgICAgICAgIC8vIFNhZmFyaSA5IGhhcyBuYW1lcyB0aGF0IGFyZSBub3QgY29uZmlndXJhYmxlLlxuICAgICAgICAgICAgbmFtZURlc2NyaXB0b3IudmFsdWUgPSBuYW1lO1xuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIFwibmFtZVwiLCBuYW1lRGVzY3JpcHRvcik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIGludm9rZTogcHJveHlJbnZva2UsXG5cbiAgICAvKlxuICAgICAqIEhvb2sgZm9yIGRlcml2ZWQgaW1wbGVtZW50YXRpb24gdG8gcmV0dXJuIGZha2UgaW5zdGFuY2VzIG1hdGNoaW5nIHRoZVxuICAgICAqIGdpdmVuIGFyZ3VtZW50cy5cbiAgICAgKi9cbiAgICBtYXRjaGluZ0Zha2VzOiBmdW5jdGlvbiAoLyphcmdzLCBzdHJpY3QqLykge1xuICAgICAgICByZXR1cm4gZW1wdHlGYWtlcztcbiAgICB9LFxuXG4gICAgZ2V0Q2FsbDogZnVuY3Rpb24gZ2V0Q2FsbChpbmRleCkge1xuICAgICAgICBsZXQgaSA9IGluZGV4O1xuICAgICAgICBpZiAoaSA8IDApIHtcbiAgICAgICAgICAgIC8vIE5lZ2F0aXZlIGluZGljZXMgbWVhbnMgY291bnRpbmcgYmFja3dhcmRzIGZyb20gdGhlIGxhc3QgY2FsbFxuICAgICAgICAgICAgaSArPSB0aGlzLmNhbGxDb3VudDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaSA8IDAgfHwgaSA+PSB0aGlzLmNhbGxDb3VudCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcHJveHlDYWxsKFxuICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICAgIHRoaXMudGhpc1ZhbHVlc1tpXSxcbiAgICAgICAgICAgIHRoaXMuYXJnc1tpXSxcbiAgICAgICAgICAgIHRoaXMucmV0dXJuVmFsdWVzW2ldLFxuICAgICAgICAgICAgdGhpcy5leGNlcHRpb25zW2ldLFxuICAgICAgICAgICAgdGhpcy5jYWxsSWRzW2ldLFxuICAgICAgICAgICAgdGhpcy5lcnJvcnNXaXRoQ2FsbFN0YWNrW2ldLFxuICAgICAgICApO1xuICAgIH0sXG5cbiAgICBnZXRDYWxsczogZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBjYWxscyA9IFtdO1xuICAgICAgICBsZXQgaTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jYWxsQ291bnQ7IGkrKykge1xuICAgICAgICAgICAgcHVzaChjYWxscywgdGhpcy5nZXRDYWxsKGkpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjYWxscztcbiAgICB9LFxuXG4gICAgY2FsbGVkQmVmb3JlOiBmdW5jdGlvbiBjYWxsZWRCZWZvcmUocHJveHkpIHtcbiAgICAgICAgaWYgKCF0aGlzLmNhbGxlZCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFwcm94eS5jYWxsZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsbElkc1swXSA8IHByb3h5LmNhbGxJZHNbcHJveHkuY2FsbElkcy5sZW5ndGggLSAxXTtcbiAgICB9LFxuXG4gICAgY2FsbGVkQWZ0ZXI6IGZ1bmN0aW9uIGNhbGxlZEFmdGVyKHByb3h5KSB7XG4gICAgICAgIGlmICghdGhpcy5jYWxsZWQgfHwgIXByb3h5LmNhbGxlZCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuY2FsbElkc1t0aGlzLmNhbGxDb3VudCAtIDFdID4gcHJveHkuY2FsbElkc1swXTtcbiAgICB9LFxuXG4gICAgY2FsbGVkSW1tZWRpYXRlbHlCZWZvcmU6IGZ1bmN0aW9uIGNhbGxlZEltbWVkaWF0ZWx5QmVmb3JlKHByb3h5KSB7XG4gICAgICAgIGlmICghdGhpcy5jYWxsZWQgfHwgIXByb3h5LmNhbGxlZCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIHRoaXMuY2FsbElkc1t0aGlzLmNhbGxDb3VudCAtIDFdID09PVxuICAgICAgICAgICAgcHJveHkuY2FsbElkc1twcm94eS5jYWxsQ291bnQgLSAxXSAtIDFcbiAgICAgICAgKTtcbiAgICB9LFxuXG4gICAgY2FsbGVkSW1tZWRpYXRlbHlBZnRlcjogZnVuY3Rpb24gY2FsbGVkSW1tZWRpYXRlbHlBZnRlcihwcm94eSkge1xuICAgICAgICBpZiAoIXRoaXMuY2FsbGVkIHx8ICFwcm94eS5jYWxsZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLmNhbGxJZHNbdGhpcy5jYWxsQ291bnQgLSAxXSA9PT1cbiAgICAgICAgICAgIHByb3h5LmNhbGxJZHNbcHJveHkuY2FsbENvdW50IC0gMV0gKyAxXG4gICAgICAgICk7XG4gICAgfSxcblxuICAgIGZvcm1hdHRlcnM6IHJlcXVpcmUoXCIuL3NweS1mb3JtYXR0ZXJzXCIpLFxuICAgIHByaW50ZjogZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICBjb25zdCBzcHlJbnN0YW5jZSA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSBzbGljZShhcmd1bWVudHMsIDEpO1xuICAgICAgICBsZXQgZm9ybWF0dGVyO1xuXG4gICAgICAgIHJldHVybiAoZm9ybWF0IHx8IFwiXCIpLnJlcGxhY2UoLyUoLikvZywgZnVuY3Rpb24gKG1hdGNoLCBzcGVjaWZpZXIpIHtcbiAgICAgICAgICAgIGZvcm1hdHRlciA9IHByb3h5QXBpLmZvcm1hdHRlcnNbc3BlY2lmaWVyXTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBmb3JtYXR0ZXIgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcoZm9ybWF0dGVyKHNweUluc3RhbmNlLCBhcmdzKSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFpc05hTihwYXJzZUludChzcGVjaWZpZXIsIDEwKSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaW5zcGVjdChhcmdzW3NwZWNpZmllciAtIDFdKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGAlJHtzcGVjaWZpZXJ9YDtcbiAgICAgICAgfSk7XG4gICAgfSxcblxuICAgIHJlc2V0SGlzdG9yeTogZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pbnZva2luZykge1xuICAgICAgICAgICAgY29uc3QgZXJyID0gbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgIFwiQ2Fubm90IHJlc2V0IFNpbm9uIGZ1bmN0aW9uIHdoaWxlIGludm9raW5nIGl0LiBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwiTW92ZSB0aGUgY2FsbCB0byAucmVzZXRIaXN0b3J5IG91dHNpZGUgb2YgdGhlIGNhbGxiYWNrLlwiLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGVyci5uYW1lID0gXCJJbnZhbGlkUmVzZXRFeGNlcHRpb25cIjtcbiAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuY2FsbGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMubm90Q2FsbGVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5jYWxsZWRPbmNlID0gZmFsc2U7XG4gICAgICAgIHRoaXMuY2FsbGVkVHdpY2UgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5jYWxsZWRUaHJpY2UgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5jYWxsQ291bnQgPSAwO1xuICAgICAgICB0aGlzLmZpcnN0Q2FsbCA9IG51bGw7XG4gICAgICAgIHRoaXMuc2Vjb25kQ2FsbCA9IG51bGw7XG4gICAgICAgIHRoaXMudGhpcmRDYWxsID0gbnVsbDtcbiAgICAgICAgdGhpcy5sYXN0Q2FsbCA9IG51bGw7XG4gICAgICAgIHRoaXMuYXJncyA9IFtdO1xuICAgICAgICB0aGlzLmZpcnN0QXJnID0gbnVsbDtcbiAgICAgICAgdGhpcy5sYXN0QXJnID0gbnVsbDtcbiAgICAgICAgdGhpcy5yZXR1cm5WYWx1ZXMgPSBbXTtcbiAgICAgICAgdGhpcy50aGlzVmFsdWVzID0gW107XG4gICAgICAgIHRoaXMuZXhjZXB0aW9ucyA9IFtdO1xuICAgICAgICB0aGlzLmNhbGxJZHMgPSBbXTtcbiAgICAgICAgdGhpcy5lcnJvcnNXaXRoQ2FsbFN0YWNrID0gW107XG5cbiAgICAgICAgaWYgKHRoaXMuZmFrZXMpIHtcbiAgICAgICAgICAgIGZvckVhY2godGhpcy5mYWtlcywgZnVuY3Rpb24gKGZha2UpIHtcbiAgICAgICAgICAgICAgICBmYWtlLnJlc2V0SGlzdG9yeSgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxufTtcblxuY29uc3QgZGVsZWdhdGVUb0NhbGxzID0gcHJveHlDYWxsVXRpbC5kZWxlZ2F0ZVRvQ2FsbHM7XG5kZWxlZ2F0ZVRvQ2FsbHMocHJveHlBcGksIFwiY2FsbGVkT25cIiwgdHJ1ZSk7XG5kZWxlZ2F0ZVRvQ2FsbHMocHJveHlBcGksIFwiYWx3YXlzQ2FsbGVkT25cIiwgZmFsc2UsIFwiY2FsbGVkT25cIik7XG5kZWxlZ2F0ZVRvQ2FsbHMocHJveHlBcGksIFwiY2FsbGVkV2l0aFwiLCB0cnVlKTtcbmRlbGVnYXRlVG9DYWxscyhcbiAgICBwcm94eUFwaSxcbiAgICBcImNhbGxlZE9uY2VXaXRoXCIsXG4gICAgdHJ1ZSxcbiAgICBcImNhbGxlZFdpdGhcIixcbiAgICBmYWxzZSxcbiAgICB1bmRlZmluZWQsXG4gICAgMSxcbik7XG5kZWxlZ2F0ZVRvQ2FsbHMocHJveHlBcGksIFwiY2FsbGVkV2l0aE1hdGNoXCIsIHRydWUpO1xuZGVsZWdhdGVUb0NhbGxzKHByb3h5QXBpLCBcImFsd2F5c0NhbGxlZFdpdGhcIiwgZmFsc2UsIFwiY2FsbGVkV2l0aFwiKTtcbmRlbGVnYXRlVG9DYWxscyhwcm94eUFwaSwgXCJhbHdheXNDYWxsZWRXaXRoTWF0Y2hcIiwgZmFsc2UsIFwiY2FsbGVkV2l0aE1hdGNoXCIpO1xuZGVsZWdhdGVUb0NhbGxzKHByb3h5QXBpLCBcImNhbGxlZFdpdGhFeGFjdGx5XCIsIHRydWUpO1xuZGVsZWdhdGVUb0NhbGxzKFxuICAgIHByb3h5QXBpLFxuICAgIFwiY2FsbGVkT25jZVdpdGhFeGFjdGx5XCIsXG4gICAgdHJ1ZSxcbiAgICBcImNhbGxlZFdpdGhFeGFjdGx5XCIsXG4gICAgZmFsc2UsXG4gICAgdW5kZWZpbmVkLFxuICAgIDEsXG4pO1xuZGVsZWdhdGVUb0NhbGxzKFxuICAgIHByb3h5QXBpLFxuICAgIFwiY2FsbGVkT25jZVdpdGhNYXRjaFwiLFxuICAgIHRydWUsXG4gICAgXCJjYWxsZWRXaXRoTWF0Y2hcIixcbiAgICBmYWxzZSxcbiAgICB1bmRlZmluZWQsXG4gICAgMSxcbik7XG5kZWxlZ2F0ZVRvQ2FsbHMoXG4gICAgcHJveHlBcGksXG4gICAgXCJhbHdheXNDYWxsZWRXaXRoRXhhY3RseVwiLFxuICAgIGZhbHNlLFxuICAgIFwiY2FsbGVkV2l0aEV4YWN0bHlcIixcbik7XG5kZWxlZ2F0ZVRvQ2FsbHMoXG4gICAgcHJveHlBcGksXG4gICAgXCJuZXZlckNhbGxlZFdpdGhcIixcbiAgICBmYWxzZSxcbiAgICBcIm5vdENhbGxlZFdpdGhcIixcbiAgICBmYWxzZSxcbiAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0sXG4pO1xuZGVsZWdhdGVUb0NhbGxzKFxuICAgIHByb3h5QXBpLFxuICAgIFwibmV2ZXJDYWxsZWRXaXRoTWF0Y2hcIixcbiAgICBmYWxzZSxcbiAgICBcIm5vdENhbGxlZFdpdGhNYXRjaFwiLFxuICAgIGZhbHNlLFxuICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSxcbik7XG5kZWxlZ2F0ZVRvQ2FsbHMocHJveHlBcGksIFwidGhyZXdcIiwgdHJ1ZSk7XG5kZWxlZ2F0ZVRvQ2FsbHMocHJveHlBcGksIFwiYWx3YXlzVGhyZXdcIiwgZmFsc2UsIFwidGhyZXdcIik7XG5kZWxlZ2F0ZVRvQ2FsbHMocHJveHlBcGksIFwicmV0dXJuZWRcIiwgdHJ1ZSk7XG5kZWxlZ2F0ZVRvQ2FsbHMocHJveHlBcGksIFwiYWx3YXlzUmV0dXJuZWRcIiwgZmFsc2UsIFwicmV0dXJuZWRcIik7XG5kZWxlZ2F0ZVRvQ2FsbHMocHJveHlBcGksIFwiY2FsbGVkV2l0aE5ld1wiLCB0cnVlKTtcbmRlbGVnYXRlVG9DYWxscyhwcm94eUFwaSwgXCJhbHdheXNDYWxsZWRXaXRoTmV3XCIsIGZhbHNlLCBcImNhbGxlZFdpdGhOZXdcIik7XG5cbmZ1bmN0aW9uIGNyZWF0ZVByb3h5KGZ1bmMsIG9yaWdpbmFsRnVuYykge1xuICAgIGNvbnN0IHByb3h5ID0gd3JhcEZ1bmN0aW9uKGZ1bmMsIG9yaWdpbmFsRnVuYyk7XG5cbiAgICAvLyBJbmhlcml0IGZ1bmN0aW9uIHByb3BlcnRpZXM6XG4gICAgZXh0ZW5kKHByb3h5LCBmdW5jKTtcblxuICAgIHByb3h5LnByb3RvdHlwZSA9IGZ1bmMucHJvdG90eXBlO1xuXG4gICAgZXh0ZW5kLm5vbkVudW0ocHJveHksIHByb3h5QXBpKTtcblxuICAgIHJldHVybiBwcm94eTtcbn1cblxuZnVuY3Rpb24gd3JhcEZ1bmN0aW9uKGZ1bmMsIG9yaWdpbmFsRnVuYykge1xuICAgIGNvbnN0IGFyaXR5ID0gb3JpZ2luYWxGdW5jLmxlbmd0aDtcbiAgICBsZXQgcDtcbiAgICAvLyBEbyBub3QgY2hhbmdlIHRoaXMgdG8gdXNlIGFuIGV2YWwuIFByb2plY3RzIHRoYXQgZGVwZW5kIG9uIHNpbm9uIGJsb2NrIHRoZSB1c2Ugb2YgZXZhbC5cbiAgICAvLyByZWY6IGh0dHBzOi8vZ2l0aHViLmNvbS9zaW5vbmpzL3Npbm9uL2lzc3Vlcy83MTBcbiAgICBzd2l0Y2ggKGFyaXR5KSB7XG4gICAgICAgIC8qZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMsIG1heC1sZW4qL1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICBwID0gZnVuY3Rpb24gcHJveHkoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHAuaW52b2tlKGZ1bmMsIHRoaXMsIHNsaWNlKGFyZ3VtZW50cykpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICBwID0gZnVuY3Rpb24gcHJveHkoYSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwLmludm9rZShmdW5jLCB0aGlzLCBzbGljZShhcmd1bWVudHMpKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgcCA9IGZ1bmN0aW9uIHByb3h5KGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcC5pbnZva2UoZnVuYywgdGhpcywgc2xpY2UoYXJndW1lbnRzKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgIHAgPSBmdW5jdGlvbiBwcm94eShhLCBiLCBjKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHAuaW52b2tlKGZ1bmMsIHRoaXMsIHNsaWNlKGFyZ3VtZW50cykpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICBwID0gZnVuY3Rpb24gcHJveHkoYSwgYiwgYywgZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwLmludm9rZShmdW5jLCB0aGlzLCBzbGljZShhcmd1bWVudHMpKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgcCA9IGZ1bmN0aW9uIHByb3h5KGEsIGIsIGMsIGQsIGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcC5pbnZva2UoZnVuYywgdGhpcywgc2xpY2UoYXJndW1lbnRzKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgIHAgPSBmdW5jdGlvbiBwcm94eShhLCBiLCBjLCBkLCBlLCBmKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHAuaW52b2tlKGZ1bmMsIHRoaXMsIHNsaWNlKGFyZ3VtZW50cykpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDc6XG4gICAgICAgICAgICBwID0gZnVuY3Rpb24gcHJveHkoYSwgYiwgYywgZCwgZSwgZiwgZykge1xuICAgICAgICAgICAgICAgIHJldHVybiBwLmludm9rZShmdW5jLCB0aGlzLCBzbGljZShhcmd1bWVudHMpKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSA4OlxuICAgICAgICAgICAgcCA9IGZ1bmN0aW9uIHByb3h5KGEsIGIsIGMsIGQsIGUsIGYsIGcsIGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcC5pbnZva2UoZnVuYywgdGhpcywgc2xpY2UoYXJndW1lbnRzKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgOTpcbiAgICAgICAgICAgIHAgPSBmdW5jdGlvbiBwcm94eShhLCBiLCBjLCBkLCBlLCBmLCBnLCBoLCBpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHAuaW52b2tlKGZ1bmMsIHRoaXMsIHNsaWNlKGFyZ3VtZW50cykpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDEwOlxuICAgICAgICAgICAgcCA9IGZ1bmN0aW9uIHByb3h5KGEsIGIsIGMsIGQsIGUsIGYsIGcsIGgsIGksIGopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcC5pbnZva2UoZnVuYywgdGhpcywgc2xpY2UoYXJndW1lbnRzKSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMTE6XG4gICAgICAgICAgICBwID0gZnVuY3Rpb24gcHJveHkoYSwgYiwgYywgZCwgZSwgZiwgZywgaCwgaSwgaiwgaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBwLmludm9rZShmdW5jLCB0aGlzLCBzbGljZShhcmd1bWVudHMpKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAxMjpcbiAgICAgICAgICAgIHAgPSBmdW5jdGlvbiBwcm94eShhLCBiLCBjLCBkLCBlLCBmLCBnLCBoLCBpLCBqLCBrLCBsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHAuaW52b2tlKGZ1bmMsIHRoaXMsIHNsaWNlKGFyZ3VtZW50cykpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcCA9IGZ1bmN0aW9uIHByb3h5KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwLmludm9rZShmdW5jLCB0aGlzLCBzbGljZShhcmd1bWVudHMpKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgLyplc2xpbnQtZW5hYmxlKi9cbiAgICB9XG4gICAgY29uc3QgbmFtZURlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKFxuICAgICAgICBvcmlnaW5hbEZ1bmMsXG4gICAgICAgIFwibmFtZVwiLFxuICAgICk7XG4gICAgaWYgKG5hbWVEZXNjcmlwdG9yICYmIG5hbWVEZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSkge1xuICAgICAgICAvLyBJRSAxMSBmdW5jdGlvbnMgZG9uJ3QgaGF2ZSBhIG5hbWUuXG4gICAgICAgIC8vIFNhZmFyaSA5IGhhcyBuYW1lcyB0aGF0IGFyZSBub3QgY29uZmlndXJhYmxlLlxuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkocCwgXCJuYW1lXCIsIG5hbWVEZXNjcmlwdG9yKTtcbiAgICB9XG4gICAgZXh0ZW5kLm5vbkVudW0ocCwge1xuICAgICAgICBpc1Npbm9uUHJveHk6IHRydWUsXG5cbiAgICAgICAgY2FsbGVkOiBmYWxzZSxcbiAgICAgICAgbm90Q2FsbGVkOiB0cnVlLFxuICAgICAgICBjYWxsZWRPbmNlOiBmYWxzZSxcbiAgICAgICAgY2FsbGVkVHdpY2U6IGZhbHNlLFxuICAgICAgICBjYWxsZWRUaHJpY2U6IGZhbHNlLFxuICAgICAgICBjYWxsQ291bnQ6IDAsXG4gICAgICAgIGZpcnN0Q2FsbDogbnVsbCxcbiAgICAgICAgZmlyc3RBcmc6IG51bGwsXG4gICAgICAgIHNlY29uZENhbGw6IG51bGwsXG4gICAgICAgIHRoaXJkQ2FsbDogbnVsbCxcbiAgICAgICAgbGFzdENhbGw6IG51bGwsXG4gICAgICAgIGxhc3RBcmc6IG51bGwsXG4gICAgICAgIGFyZ3M6IFtdLFxuICAgICAgICByZXR1cm5WYWx1ZXM6IFtdLFxuICAgICAgICB0aGlzVmFsdWVzOiBbXSxcbiAgICAgICAgZXhjZXB0aW9uczogW10sXG4gICAgICAgIGNhbGxJZHM6IFtdLFxuICAgICAgICBlcnJvcnNXaXRoQ2FsbFN0YWNrOiBbXSxcbiAgICB9KTtcbiAgICByZXR1cm4gcDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVQcm94eTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5jb25zdCB3YWxrT2JqZWN0ID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlL3dhbGstb2JqZWN0XCIpO1xuXG5mdW5jdGlvbiBmaWx0ZXIob2JqZWN0LCBwcm9wZXJ0eSkge1xuICAgIHJldHVybiBvYmplY3RbcHJvcGVydHldLnJlc3RvcmUgJiYgb2JqZWN0W3Byb3BlcnR5XS5yZXN0b3JlLnNpbm9uO1xufVxuXG5mdW5jdGlvbiByZXN0b3JlKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICBvYmplY3RbcHJvcGVydHldLnJlc3RvcmUoKTtcbn1cblxuZnVuY3Rpb24gcmVzdG9yZU9iamVjdChvYmplY3QpIHtcbiAgICByZXR1cm4gd2Fsa09iamVjdChyZXN0b3JlLCBvYmplY3QsIGZpbHRlcik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gcmVzdG9yZU9iamVjdDtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5jb25zdCBhcnJheVByb3RvID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikucHJvdG90eXBlcy5hcnJheTtcbmNvbnN0IGxvZ2dlciA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLmRlcHJlY2F0ZWQ7XG5jb25zdCBjb2xsZWN0T3duTWV0aG9kcyA9IHJlcXVpcmUoXCIuL2NvbGxlY3Qtb3duLW1ldGhvZHNcIik7XG5jb25zdCBnZXRQcm9wZXJ0eURlc2NyaXB0b3IgPSByZXF1aXJlKFwiLi91dGlsL2NvcmUvZ2V0LXByb3BlcnR5LWRlc2NyaXB0b3JcIik7XG5jb25zdCBpc1Byb3BlcnR5Q29uZmlndXJhYmxlID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlL2lzLXByb3BlcnR5LWNvbmZpZ3VyYWJsZVwiKTtcbmNvbnN0IG1hdGNoID0gcmVxdWlyZShcIkBzaW5vbmpzL3NhbXNhbVwiKS5jcmVhdGVNYXRjaGVyO1xuY29uc3Qgc2lub25Bc3NlcnQgPSByZXF1aXJlKFwiLi9hc3NlcnRcIik7XG5jb25zdCBzaW5vbkNsb2NrID0gcmVxdWlyZShcIi4vdXRpbC9mYWtlLXRpbWVyc1wiKTtcbmNvbnN0IHNpbm9uTW9jayA9IHJlcXVpcmUoXCIuL21vY2tcIik7XG5jb25zdCBzaW5vblNweSA9IHJlcXVpcmUoXCIuL3NweVwiKTtcbmNvbnN0IHNpbm9uU3R1YiA9IHJlcXVpcmUoXCIuL3N0dWJcIik7XG5jb25zdCBzaW5vbkNyZWF0ZVN0dWJJbnN0YW5jZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1zdHViLWluc3RhbmNlXCIpO1xuY29uc3Qgc2lub25GYWtlID0gcmVxdWlyZShcIi4vZmFrZVwiKTtcbmNvbnN0IHZhbHVlVG9TdHJpbmcgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS52YWx1ZVRvU3RyaW5nO1xuXG5jb25zdCBERUZBVUxUX0xFQUtfVEhSRVNIT0xEID0gMTAwMDA7XG5cbmNvbnN0IGZpbHRlciA9IGFycmF5UHJvdG8uZmlsdGVyO1xuY29uc3QgZm9yRWFjaCA9IGFycmF5UHJvdG8uZm9yRWFjaDtcbmNvbnN0IHB1c2ggPSBhcnJheVByb3RvLnB1c2g7XG5jb25zdCByZXZlcnNlID0gYXJyYXlQcm90by5yZXZlcnNlO1xuXG5mdW5jdGlvbiBhcHBseU9uRWFjaChmYWtlcywgbWV0aG9kKSB7XG4gICAgY29uc3QgbWF0Y2hpbmdGYWtlcyA9IGZpbHRlcihmYWtlcywgZnVuY3Rpb24gKGZha2UpIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBmYWtlW21ldGhvZF0gPT09IFwiZnVuY3Rpb25cIjtcbiAgICB9KTtcblxuICAgIGZvckVhY2gobWF0Y2hpbmdGYWtlcywgZnVuY3Rpb24gKGZha2UpIHtcbiAgICAgICAgZmFrZVttZXRob2RdKCk7XG4gICAgfSk7XG59XG5cbmZ1bmN0aW9uIHRocm93T25BY2Nlc3NvcnMoZGVzY3JpcHRvcikge1xuICAgIGlmICh0eXBlb2YgZGVzY3JpcHRvci5nZXQgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVc2Ugc2FuZGJveC5yZXBsYWNlR2V0dGVyIGZvciByZXBsYWNpbmcgZ2V0dGVyc1wiKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGRlc2NyaXB0b3Iuc2V0ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVXNlIHNhbmRib3gucmVwbGFjZVNldHRlciBmb3IgcmVwbGFjaW5nIHNldHRlcnNcIik7XG4gICAgfVxufVxuXG5mdW5jdGlvbiB2ZXJpZnlTYW1lVHlwZShvYmplY3QsIHByb3BlcnR5LCByZXBsYWNlbWVudCkge1xuICAgIGlmICh0eXBlb2Ygb2JqZWN0W3Byb3BlcnR5XSAhPT0gdHlwZW9mIHJlcGxhY2VtZW50KSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICBgQ2Fubm90IHJlcGxhY2UgJHt0eXBlb2Ygb2JqZWN0W1xuICAgICAgICAgICAgICAgIHByb3BlcnR5XG4gICAgICAgICAgICBdfSB3aXRoICR7dHlwZW9mIHJlcGxhY2VtZW50fWAsXG4gICAgICAgICk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjaGVja0ZvclZhbGlkQXJndW1lbnRzKGRlc2NyaXB0b3IsIHByb3BlcnR5LCByZXBsYWNlbWVudCkge1xuICAgIGlmICh0eXBlb2YgZGVzY3JpcHRvciA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgYENhbm5vdCByZXBsYWNlIG5vbi1leGlzdGVudCBwcm9wZXJ0eSAke3ZhbHVlVG9TdHJpbmcoXG4gICAgICAgICAgICAgICAgcHJvcGVydHksXG4gICAgICAgICAgICApfS4gUGVyaGFwcyB5b3UgbWVhbnQgc2FuZGJveC5kZWZpbmUoKT9gLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgcmVwbGFjZW1lbnQgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkV4cGVjdGVkIHJlcGxhY2VtZW50IGFyZ3VtZW50IHRvIGJlIGRlZmluZWRcIik7XG4gICAgfVxufVxuXG4vKipcbiAqIEEgc2lub24gc2FuZGJveFxuICpcbiAqIEBwYXJhbSBvcHRzXG4gKiBAcGFyYW0ge29iamVjdH0gW29wdHMuYXNzZXJ0T3B0aW9uc10gc2VlIHRoZSBDcmVhdGVBc3NlcnRPcHRpb25zIGluIC4vYXNzZXJ0XG4gKiBAY2xhc3NcbiAqL1xuZnVuY3Rpb24gU2FuZGJveChvcHRzID0ge30pIHtcbiAgICBjb25zdCBzYW5kYm94ID0gdGhpcztcbiAgICBjb25zdCBhc3NlcnRPcHRpb25zID0gb3B0cy5hc3NlcnRPcHRpb25zIHx8IHt9O1xuICAgIGxldCBmYWtlUmVzdG9yZXJzID0gW107XG5cbiAgICBsZXQgY29sbGVjdGlvbiA9IFtdO1xuICAgIGxldCBsb2dnZWRMZWFrV2FybmluZyA9IGZhbHNlO1xuICAgIHNhbmRib3gubGVha1RocmVzaG9sZCA9IERFRkFVTFRfTEVBS19USFJFU0hPTEQ7XG5cbiAgICBmdW5jdGlvbiBhZGRUb0NvbGxlY3Rpb24ob2JqZWN0KSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIHB1c2goY29sbGVjdGlvbiwgb2JqZWN0KSA+IHNhbmRib3gubGVha1RocmVzaG9sZCAmJlxuICAgICAgICAgICAgIWxvZ2dlZExlYWtXYXJuaW5nXG4gICAgICAgICkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICAgICAgICAgIGxvZ2dlci5wcmludFdhcm5pbmcoXG4gICAgICAgICAgICAgICAgXCJQb3RlbnRpYWwgbWVtb3J5IGxlYWsgZGV0ZWN0ZWQ7IGJlIHN1cmUgdG8gY2FsbCByZXN0b3JlKCkgdG8gY2xlYW4gdXAgeW91ciBzYW5kYm94LiBUbyBzdXBwcmVzcyB0aGlzIHdhcm5pbmcsIG1vZGlmeSB0aGUgbGVha1RocmVzaG9sZCBwcm9wZXJ0eSBvZiB5b3VyIHNhbmRib3guXCIsXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgbG9nZ2VkTGVha1dhcm5pbmcgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2FuZGJveC5hc3NlcnQgPSBzaW5vbkFzc2VydC5jcmVhdGVBc3NlcnRPYmplY3QoYXNzZXJ0T3B0aW9ucyk7XG5cbiAgICAvLyB0aGlzIGlzIGZvciB0ZXN0aW5nIG9ubHlcbiAgICBzYW5kYm94LmdldEZha2VzID0gZnVuY3Rpb24gZ2V0RmFrZXMoKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICAgIH07XG5cbiAgICBzYW5kYm94LmNyZWF0ZVN0dWJJbnN0YW5jZSA9IGZ1bmN0aW9uIGNyZWF0ZVN0dWJJbnN0YW5jZSgpIHtcbiAgICAgICAgY29uc3Qgc3R1YmJlZCA9IHNpbm9uQ3JlYXRlU3R1Ykluc3RhbmNlLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG5cbiAgICAgICAgY29uc3Qgb3duTWV0aG9kcyA9IGNvbGxlY3RPd25NZXRob2RzKHN0dWJiZWQpO1xuXG4gICAgICAgIGZvckVhY2gob3duTWV0aG9kcywgZnVuY3Rpb24gKG1ldGhvZCkge1xuICAgICAgICAgICAgYWRkVG9Db2xsZWN0aW9uKG1ldGhvZCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBzdHViYmVkO1xuICAgIH07XG5cbiAgICBzYW5kYm94LmluamVjdCA9IGZ1bmN0aW9uIGluamVjdChvYmopIHtcbiAgICAgICAgb2JqLnNweSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBzYW5kYm94LnNweS5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIG9iai5zdHViID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHNhbmRib3guc3R1Yi5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIG9iai5tb2NrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHNhbmRib3gubW9jay5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIG9iai5jcmVhdGVTdHViSW5zdGFuY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gc2FuZGJveC5jcmVhdGVTdHViSW5zdGFuY2UuYXBwbHkoc2FuZGJveCwgYXJndW1lbnRzKTtcbiAgICAgICAgfTtcblxuICAgICAgICBvYmouZmFrZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBzYW5kYm94LmZha2UuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgICAgfTtcblxuICAgICAgICBvYmouZGVmaW5lID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHNhbmRib3guZGVmaW5lLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgb2JqLnJlcGxhY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gc2FuZGJveC5yZXBsYWNlLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgb2JqLnJlcGxhY2VTZXR0ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gc2FuZGJveC5yZXBsYWNlU2V0dGVyLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgb2JqLnJlcGxhY2VHZXR0ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gc2FuZGJveC5yZXBsYWNlR2V0dGVyLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHNhbmRib3guY2xvY2spIHtcbiAgICAgICAgICAgIG9iai5jbG9jayA9IHNhbmRib3guY2xvY2s7XG4gICAgICAgIH1cblxuICAgICAgICBvYmoubWF0Y2ggPSBtYXRjaDtcblxuICAgICAgICByZXR1cm4gb2JqO1xuICAgIH07XG5cbiAgICBzYW5kYm94Lm1vY2sgPSBmdW5jdGlvbiBtb2NrKCkge1xuICAgICAgICBjb25zdCBtID0gc2lub25Nb2NrLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG5cbiAgICAgICAgYWRkVG9Db2xsZWN0aW9uKG0pO1xuXG4gICAgICAgIHJldHVybiBtO1xuICAgIH07XG5cbiAgICBzYW5kYm94LnJlc2V0ID0gZnVuY3Rpb24gcmVzZXQoKSB7XG4gICAgICAgIGFwcGx5T25FYWNoKGNvbGxlY3Rpb24sIFwicmVzZXRcIik7XG4gICAgICAgIGFwcGx5T25FYWNoKGNvbGxlY3Rpb24sIFwicmVzZXRIaXN0b3J5XCIpO1xuICAgIH07XG5cbiAgICBzYW5kYm94LnJlc2V0QmVoYXZpb3IgPSBmdW5jdGlvbiByZXNldEJlaGF2aW9yKCkge1xuICAgICAgICBhcHBseU9uRWFjaChjb2xsZWN0aW9uLCBcInJlc2V0QmVoYXZpb3JcIik7XG4gICAgfTtcblxuICAgIHNhbmRib3gucmVzZXRIaXN0b3J5ID0gZnVuY3Rpb24gcmVzZXRIaXN0b3J5KCkge1xuICAgICAgICBmdW5jdGlvbiBwcml2YXRlUmVzZXRIaXN0b3J5KGYpIHtcbiAgICAgICAgICAgIGNvbnN0IG1ldGhvZCA9IGYucmVzZXRIaXN0b3J5IHx8IGYucmVzZXQ7XG4gICAgICAgICAgICBpZiAobWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgbWV0aG9kLmNhbGwoZik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3JFYWNoKGNvbGxlY3Rpb24sIHByaXZhdGVSZXNldEhpc3RvcnkpO1xuICAgIH07XG5cbiAgICBzYW5kYm94LnJlc3RvcmUgPSBmdW5jdGlvbiByZXN0b3JlKCkge1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgIFwic2FuZGJveC5yZXN0b3JlKCkgZG9lcyBub3QgdGFrZSBhbnkgcGFyYW1ldGVycy4gUGVyaGFwcyB5b3UgbWVhbnQgc3R1Yi5yZXN0b3JlKClcIixcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICByZXZlcnNlKGNvbGxlY3Rpb24pO1xuICAgICAgICBhcHBseU9uRWFjaChjb2xsZWN0aW9uLCBcInJlc3RvcmVcIik7XG4gICAgICAgIGNvbGxlY3Rpb24gPSBbXTtcblxuICAgICAgICBmb3JFYWNoKGZha2VSZXN0b3JlcnMsIGZ1bmN0aW9uIChyZXN0b3Jlcikge1xuICAgICAgICAgICAgcmVzdG9yZXIoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGZha2VSZXN0b3JlcnMgPSBbXTtcblxuICAgICAgICBzYW5kYm94LnJlc3RvcmVDb250ZXh0KCk7XG4gICAgfTtcblxuICAgIHNhbmRib3gucmVzdG9yZUNvbnRleHQgPSBmdW5jdGlvbiByZXN0b3JlQ29udGV4dCgpIHtcbiAgICAgICAgaWYgKCFzYW5kYm94LmluamVjdGVkS2V5cykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yRWFjaChzYW5kYm94LmluamVjdGVkS2V5cywgZnVuY3Rpb24gKGluamVjdGVkS2V5KSB7XG4gICAgICAgICAgICBkZWxldGUgc2FuZGJveC5pbmplY3RJbnRvW2luamVjdGVkS2V5XTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2FuZGJveC5pbmplY3RlZEtleXMubGVuZ3RoID0gMDtcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIHJlc3RvcmVyIGZ1bmN0aW9uIGZvciB0aGUgcHJvcGVydHlcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fEZ1bmN0aW9ufSBvYmplY3RcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcGVydHlcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGZvcmNlQXNzaWdubWVudFxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gcmVzdG9yZXIgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRGYWtlUmVzdG9yZXIob2JqZWN0LCBwcm9wZXJ0eSwgZm9yY2VBc3NpZ25tZW50ID0gZmFsc2UpIHtcbiAgICAgICAgY29uc3QgZGVzY3JpcHRvciA9IGdldFByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBmb3JjZUFzc2lnbm1lbnQgJiYgb2JqZWN0W3Byb3BlcnR5XTtcblxuICAgICAgICBmdW5jdGlvbiByZXN0b3JlcigpIHtcbiAgICAgICAgICAgIGlmIChmb3JjZUFzc2lnbm1lbnQpIHtcbiAgICAgICAgICAgICAgICBvYmplY3RbcHJvcGVydHldID0gdmFsdWU7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGRlc2NyaXB0b3I/LmlzT3duKSB7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iamVjdCwgcHJvcGVydHksIGRlc2NyaXB0b3IpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgb2JqZWN0W3Byb3BlcnR5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3RvcmVyLm9iamVjdCA9IG9iamVjdDtcbiAgICAgICAgcmVzdG9yZXIucHJvcGVydHkgPSBwcm9wZXJ0eTtcbiAgICAgICAgcmV0dXJuIHJlc3RvcmVyO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHZlcmlmeU5vdFJlcGxhY2VkKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICAgICAgZm9yRWFjaChmYWtlUmVzdG9yZXJzLCBmdW5jdGlvbiAoZmFrZVJlc3RvcmVyKSB7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgZmFrZVJlc3RvcmVyLm9iamVjdCA9PT0gb2JqZWN0ICYmXG4gICAgICAgICAgICAgICAgZmFrZVJlc3RvcmVyLnByb3BlcnR5ID09PSBwcm9wZXJ0eVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgYEF0dGVtcHRlZCB0byByZXBsYWNlICR7cHJvcGVydHl9IHdoaWNoIGlzIGFscmVhZHkgcmVwbGFjZWRgLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlcGxhY2UgYW4gZXhpc3RpbmcgcHJvcGVydHlcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fEZ1bmN0aW9ufSBvYmplY3RcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcHJvcGVydHlcbiAgICAgKiBAcGFyYW0geyp9IHJlcGxhY2VtZW50IGEgZmFrZSwgc3R1Yiwgc3B5IG9yIGFueSBvdGhlciB2YWx1ZVxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHNhbmRib3gucmVwbGFjZSA9IGZ1bmN0aW9uIHJlcGxhY2Uob2JqZWN0LCBwcm9wZXJ0eSwgcmVwbGFjZW1lbnQpIHtcbiAgICAgICAgY29uc3QgZGVzY3JpcHRvciA9IGdldFByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTtcbiAgICAgICAgY2hlY2tGb3JWYWxpZEFyZ3VtZW50cyhkZXNjcmlwdG9yLCBwcm9wZXJ0eSwgcmVwbGFjZW1lbnQpO1xuICAgICAgICB0aHJvd09uQWNjZXNzb3JzKGRlc2NyaXB0b3IpO1xuICAgICAgICB2ZXJpZnlTYW1lVHlwZShvYmplY3QsIHByb3BlcnR5LCByZXBsYWNlbWVudCk7XG5cbiAgICAgICAgdmVyaWZ5Tm90UmVwbGFjZWQob2JqZWN0LCBwcm9wZXJ0eSk7XG5cbiAgICAgICAgLy8gc3RvcmUgYSBmdW5jdGlvbiBmb3IgcmVzdG9yaW5nIHRoZSByZXBsYWNlZCBwcm9wZXJ0eVxuICAgICAgICBwdXNoKGZha2VSZXN0b3JlcnMsIGdldEZha2VSZXN0b3JlcihvYmplY3QsIHByb3BlcnR5KSk7XG5cbiAgICAgICAgb2JqZWN0W3Byb3BlcnR5XSA9IHJlcGxhY2VtZW50O1xuXG4gICAgICAgIHJldHVybiByZXBsYWNlbWVudDtcbiAgICB9O1xuXG4gICAgc2FuZGJveC5yZXBsYWNlLnVzaW5nQWNjZXNzb3IgPSBmdW5jdGlvbiByZXBsYWNlVXNpbmdBY2Nlc3NvcihcbiAgICAgICAgb2JqZWN0LFxuICAgICAgICBwcm9wZXJ0eSxcbiAgICAgICAgcmVwbGFjZW1lbnQsXG4gICAgKSB7XG4gICAgICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBnZXRQcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wZXJ0eSk7XG4gICAgICAgIGNoZWNrRm9yVmFsaWRBcmd1bWVudHMoZGVzY3JpcHRvciwgcHJvcGVydHksIHJlcGxhY2VtZW50KTtcbiAgICAgICAgdmVyaWZ5U2FtZVR5cGUob2JqZWN0LCBwcm9wZXJ0eSwgcmVwbGFjZW1lbnQpO1xuXG4gICAgICAgIHZlcmlmeU5vdFJlcGxhY2VkKG9iamVjdCwgcHJvcGVydHkpO1xuXG4gICAgICAgIC8vIHN0b3JlIGEgZnVuY3Rpb24gZm9yIHJlc3RvcmluZyB0aGUgcmVwbGFjZWQgcHJvcGVydHlcbiAgICAgICAgcHVzaChmYWtlUmVzdG9yZXJzLCBnZXRGYWtlUmVzdG9yZXIob2JqZWN0LCBwcm9wZXJ0eSwgdHJ1ZSkpO1xuXG4gICAgICAgIG9iamVjdFtwcm9wZXJ0eV0gPSByZXBsYWNlbWVudDtcblxuICAgICAgICByZXR1cm4gcmVwbGFjZW1lbnQ7XG4gICAgfTtcblxuICAgIHNhbmRib3guZGVmaW5lID0gZnVuY3Rpb24gZGVmaW5lKG9iamVjdCwgcHJvcGVydHksIHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBnZXRQcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wZXJ0eSk7XG5cbiAgICAgICAgaWYgKGRlc2NyaXB0b3IpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICAgICAgYENhbm5vdCBkZWZpbmUgdGhlIGFscmVhZHkgZXhpc3RpbmcgcHJvcGVydHkgJHt2YWx1ZVRvU3RyaW5nKFxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eSxcbiAgICAgICAgICAgICAgICApfS4gUGVyaGFwcyB5b3UgbWVhbnQgc2FuZGJveC5yZXBsYWNlKCk/YCxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiRXhwZWN0ZWQgdmFsdWUgYXJndW1lbnQgdG8gYmUgZGVmaW5lZFwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZlcmlmeU5vdFJlcGxhY2VkKG9iamVjdCwgcHJvcGVydHkpO1xuXG4gICAgICAgIC8vIHN0b3JlIGEgZnVuY3Rpb24gZm9yIHJlc3RvcmluZyB0aGUgZGVmaW5lZCBwcm9wZXJ0eVxuICAgICAgICBwdXNoKGZha2VSZXN0b3JlcnMsIGdldEZha2VSZXN0b3JlcihvYmplY3QsIHByb3BlcnR5KSk7XG5cbiAgICAgICAgb2JqZWN0W3Byb3BlcnR5XSA9IHZhbHVlO1xuXG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9O1xuXG4gICAgc2FuZGJveC5yZXBsYWNlR2V0dGVyID0gZnVuY3Rpb24gcmVwbGFjZUdldHRlcihcbiAgICAgICAgb2JqZWN0LFxuICAgICAgICBwcm9wZXJ0eSxcbiAgICAgICAgcmVwbGFjZW1lbnQsXG4gICAgKSB7XG4gICAgICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBnZXRQcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wZXJ0eSk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBkZXNjcmlwdG9yID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgICAgIGBDYW5ub3QgcmVwbGFjZSBub24tZXhpc3RlbnQgcHJvcGVydHkgJHt2YWx1ZVRvU3RyaW5nKFxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eSxcbiAgICAgICAgICAgICAgICApfWAsXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiByZXBsYWNlbWVudCAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgICAgIFwiRXhwZWN0ZWQgcmVwbGFjZW1lbnQgYXJndW1lbnQgdG8gYmUgYSBmdW5jdGlvblwiLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgZGVzY3JpcHRvci5nZXQgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYG9iamVjdC5wcm9wZXJ0eWAgaXMgbm90IGEgZ2V0dGVyXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmVyaWZ5Tm90UmVwbGFjZWQob2JqZWN0LCBwcm9wZXJ0eSk7XG5cbiAgICAgICAgLy8gc3RvcmUgYSBmdW5jdGlvbiBmb3IgcmVzdG9yaW5nIHRoZSByZXBsYWNlZCBwcm9wZXJ0eVxuICAgICAgICBwdXNoKGZha2VSZXN0b3JlcnMsIGdldEZha2VSZXN0b3JlcihvYmplY3QsIHByb3BlcnR5KSk7XG5cbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iamVjdCwgcHJvcGVydHksIHtcbiAgICAgICAgICAgIGdldDogcmVwbGFjZW1lbnQsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IGlzUHJvcGVydHlDb25maWd1cmFibGUob2JqZWN0LCBwcm9wZXJ0eSksXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiByZXBsYWNlbWVudDtcbiAgICB9O1xuXG4gICAgc2FuZGJveC5yZXBsYWNlU2V0dGVyID0gZnVuY3Rpb24gcmVwbGFjZVNldHRlcihcbiAgICAgICAgb2JqZWN0LFxuICAgICAgICBwcm9wZXJ0eSxcbiAgICAgICAgcmVwbGFjZW1lbnQsXG4gICAgKSB7XG4gICAgICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBnZXRQcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wZXJ0eSk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBkZXNjcmlwdG9yID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgICAgIGBDYW5ub3QgcmVwbGFjZSBub24tZXhpc3RlbnQgcHJvcGVydHkgJHt2YWx1ZVRvU3RyaW5nKFxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eSxcbiAgICAgICAgICAgICAgICApfWAsXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiByZXBsYWNlbWVudCAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgICAgIFwiRXhwZWN0ZWQgcmVwbGFjZW1lbnQgYXJndW1lbnQgdG8gYmUgYSBmdW5jdGlvblwiLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgZGVzY3JpcHRvci5zZXQgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYG9iamVjdC5wcm9wZXJ0eWAgaXMgbm90IGEgc2V0dGVyXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmVyaWZ5Tm90UmVwbGFjZWQob2JqZWN0LCBwcm9wZXJ0eSk7XG5cbiAgICAgICAgLy8gc3RvcmUgYSBmdW5jdGlvbiBmb3IgcmVzdG9yaW5nIHRoZSByZXBsYWNlZCBwcm9wZXJ0eVxuICAgICAgICBwdXNoKGZha2VSZXN0b3JlcnMsIGdldEZha2VSZXN0b3JlcihvYmplY3QsIHByb3BlcnR5KSk7XG5cbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGFjY2Vzc29yLXBhaXJzXG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmplY3QsIHByb3BlcnR5LCB7XG4gICAgICAgICAgICBzZXQ6IHJlcGxhY2VtZW50LFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiBpc1Byb3BlcnR5Q29uZmlndXJhYmxlKG9iamVjdCwgcHJvcGVydHkpLFxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcmVwbGFjZW1lbnQ7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGNvbW1vblBvc3RJbml0U2V0dXAoYXJncywgc3B5KSB7XG4gICAgICAgIGNvbnN0IFtvYmplY3QsIHByb3BlcnR5LCB0eXBlc10gPSBhcmdzO1xuXG4gICAgICAgIGNvbnN0IGlzU3B5aW5nT25FbnRpcmVPYmplY3QgPVxuICAgICAgICAgICAgdHlwZW9mIHByb3BlcnR5ID09PSBcInVuZGVmaW5lZFwiICYmIHR5cGVvZiBvYmplY3QgPT09IFwib2JqZWN0XCI7XG5cbiAgICAgICAgaWYgKGlzU3B5aW5nT25FbnRpcmVPYmplY3QpIHtcbiAgICAgICAgICAgIGNvbnN0IG93bk1ldGhvZHMgPSBjb2xsZWN0T3duTWV0aG9kcyhzcHkpO1xuXG4gICAgICAgICAgICBmb3JFYWNoKG93bk1ldGhvZHMsIGZ1bmN0aW9uIChtZXRob2QpIHtcbiAgICAgICAgICAgICAgICBhZGRUb0NvbGxlY3Rpb24obWV0aG9kKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkodHlwZXMpKSB7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGFjY2Vzc29yVHlwZSBvZiB0eXBlcykge1xuICAgICAgICAgICAgICAgIGFkZFRvQ29sbGVjdGlvbihzcHlbYWNjZXNzb3JUeXBlXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhZGRUb0NvbGxlY3Rpb24oc3B5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzcHk7XG4gICAgfVxuXG4gICAgc2FuZGJveC5zcHkgPSBmdW5jdGlvbiBzcHkoKSB7XG4gICAgICAgIGNvbnN0IGNyZWF0ZWRTcHkgPSBzaW5vblNweS5hcHBseShzaW5vblNweSwgYXJndW1lbnRzKTtcbiAgICAgICAgcmV0dXJuIGNvbW1vblBvc3RJbml0U2V0dXAoYXJndW1lbnRzLCBjcmVhdGVkU3B5KTtcbiAgICB9O1xuXG4gICAgc2FuZGJveC5zdHViID0gZnVuY3Rpb24gc3R1YigpIHtcbiAgICAgICAgY29uc3QgY3JlYXRlZFN0dWIgPSBzaW5vblN0dWIuYXBwbHkoc2lub25TdHViLCBhcmd1bWVudHMpO1xuICAgICAgICByZXR1cm4gY29tbW9uUG9zdEluaXRTZXR1cChhcmd1bWVudHMsIGNyZWF0ZWRTdHViKTtcbiAgICB9O1xuXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVudXNlZC12YXJzXG4gICAgc2FuZGJveC5mYWtlID0gZnVuY3Rpb24gZmFrZShmKSB7XG4gICAgICAgIGNvbnN0IHMgPSBzaW5vbkZha2UuYXBwbHkoc2lub25GYWtlLCBhcmd1bWVudHMpO1xuXG4gICAgICAgIGFkZFRvQ29sbGVjdGlvbihzKTtcblxuICAgICAgICByZXR1cm4gcztcbiAgICB9O1xuXG4gICAgZm9yRWFjaChPYmplY3Qua2V5cyhzaW5vbkZha2UpLCBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIGNvbnN0IGZha2VCZWhhdmlvciA9IHNpbm9uRmFrZVtrZXldO1xuICAgICAgICBpZiAodHlwZW9mIGZha2VCZWhhdmlvciA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICBzYW5kYm94LmZha2Vba2V5XSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzID0gZmFrZUJlaGF2aW9yLmFwcGx5KGZha2VCZWhhdmlvciwgYXJndW1lbnRzKTtcblxuICAgICAgICAgICAgICAgIGFkZFRvQ29sbGVjdGlvbihzKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgc2FuZGJveC51c2VGYWtlVGltZXJzID0gZnVuY3Rpb24gdXNlRmFrZVRpbWVycyhhcmdzKSB7XG4gICAgICAgIGNvbnN0IGNsb2NrID0gc2lub25DbG9jay51c2VGYWtlVGltZXJzLmNhbGwobnVsbCwgYXJncyk7XG5cbiAgICAgICAgc2FuZGJveC5jbG9jayA9IGNsb2NrO1xuICAgICAgICBhZGRUb0NvbGxlY3Rpb24oY2xvY2spO1xuXG4gICAgICAgIHJldHVybiBjbG9jaztcbiAgICB9O1xuXG4gICAgc2FuZGJveC52ZXJpZnkgPSBmdW5jdGlvbiB2ZXJpZnkoKSB7XG4gICAgICAgIGFwcGx5T25FYWNoKGNvbGxlY3Rpb24sIFwidmVyaWZ5XCIpO1xuICAgIH07XG5cbiAgICBzYW5kYm94LnZlcmlmeUFuZFJlc3RvcmUgPSBmdW5jdGlvbiB2ZXJpZnlBbmRSZXN0b3JlKCkge1xuICAgICAgICBsZXQgZXhjZXB0aW9uO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBzYW5kYm94LnZlcmlmeSgpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBleGNlcHRpb24gPSBlO1xuICAgICAgICB9XG5cbiAgICAgICAgc2FuZGJveC5yZXN0b3JlKCk7XG5cbiAgICAgICAgaWYgKGV4Y2VwdGlvbikge1xuICAgICAgICAgICAgdGhyb3cgZXhjZXB0aW9uO1xuICAgICAgICB9XG4gICAgfTtcbn1cblxuU2FuZGJveC5wcm90b3R5cGUubWF0Y2ggPSBtYXRjaDtcblxubW9kdWxlLmV4cG9ydHMgPSBTYW5kYm94O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IGFycmF5UHJvdG8gPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLmFycmF5O1xuY29uc3QgQ29sb3JpemVyID0gcmVxdWlyZShcIi4vY29sb3JpemVyXCIpO1xuY29uc3QgY29sb3Jvcml6ZXIgPSBuZXcgQ29sb3JpemVyKCk7XG5jb25zdCBtYXRjaCA9IHJlcXVpcmUoXCJAc2lub25qcy9zYW1zYW1cIikuY3JlYXRlTWF0Y2hlcjtcbmNvbnN0IHRpbWVzSW5Xb3JkcyA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZS90aW1lcy1pbi13b3Jkc1wiKTtcbmNvbnN0IGluc3BlY3QgPSByZXF1aXJlKFwidXRpbFwiKS5pbnNwZWN0O1xuY29uc3QganNEaWZmID0gcmVxdWlyZShcImRpZmZcIik7XG5cbmNvbnN0IGpvaW4gPSBhcnJheVByb3RvLmpvaW47XG5jb25zdCBtYXAgPSBhcnJheVByb3RvLm1hcDtcbmNvbnN0IHB1c2ggPSBhcnJheVByb3RvLnB1c2g7XG5jb25zdCBzbGljZSA9IGFycmF5UHJvdG8uc2xpY2U7XG5cbi8qKlxuICpcbiAqIEBwYXJhbSBtYXRjaGVyXG4gKiBAcGFyYW0gY2FsbGVkQXJnXG4gKiBAcGFyYW0gY2FsbGVkQXJnTWVzc2FnZVxuICpcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSBjb2xvcmVkIHRleHRcbiAqL1xuZnVuY3Rpb24gY29sb3JTaW5vbk1hdGNoVGV4dChtYXRjaGVyLCBjYWxsZWRBcmcsIGNhbGxlZEFyZ01lc3NhZ2UpIHtcbiAgICBsZXQgY2FsbGVkQXJndW1lbnRNZXNzYWdlID0gY2FsbGVkQXJnTWVzc2FnZTtcbiAgICBsZXQgbWF0Y2hlck1lc3NhZ2UgPSBtYXRjaGVyLm1lc3NhZ2U7XG4gICAgaWYgKCFtYXRjaGVyLnRlc3QoY2FsbGVkQXJnKSkge1xuICAgICAgICBtYXRjaGVyTWVzc2FnZSA9IGNvbG9yb3JpemVyLnJlZChtYXRjaGVyLm1lc3NhZ2UpO1xuICAgICAgICBpZiAoY2FsbGVkQXJndW1lbnRNZXNzYWdlKSB7XG4gICAgICAgICAgICBjYWxsZWRBcmd1bWVudE1lc3NhZ2UgPSBjb2xvcm9yaXplci5ncmVlbihjYWxsZWRBcmd1bWVudE1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBgJHtjYWxsZWRBcmd1bWVudE1lc3NhZ2V9ICR7bWF0Y2hlck1lc3NhZ2V9YDtcbn1cblxuLyoqXG4gKiBAcGFyYW0gZGlmZlxuICpcbiAqIEByZXR1cm5zIHtzdHJpbmd9IHRoZSBjb2xvcmVkIGRpZmZcbiAqL1xuZnVuY3Rpb24gY29sb3JEaWZmVGV4dChkaWZmKSB7XG4gICAgY29uc3Qgb2JqZWN0cyA9IG1hcChkaWZmLCBmdW5jdGlvbiAocGFydCkge1xuICAgICAgICBsZXQgdGV4dCA9IHBhcnQudmFsdWU7XG4gICAgICAgIGlmIChwYXJ0LmFkZGVkKSB7XG4gICAgICAgICAgICB0ZXh0ID0gY29sb3Jvcml6ZXIuZ3JlZW4odGV4dCk7XG4gICAgICAgIH0gZWxzZSBpZiAocGFydC5yZW1vdmVkKSB7XG4gICAgICAgICAgICB0ZXh0ID0gY29sb3Jvcml6ZXIucmVkKHRleHQpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkaWZmLmxlbmd0aCA9PT0gMikge1xuICAgICAgICAgICAgdGV4dCArPSBcIiBcIjsgLy8gZm9ybWF0IHNpbXBsZSBkaWZmc1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0ZXh0O1xuICAgIH0pO1xuICAgIHJldHVybiBqb2luKG9iamVjdHMsIFwiXCIpO1xufVxuXG4vKipcbiAqXG4gKiBAcGFyYW0gdmFsdWVcbiAqIEByZXR1cm5zIHtzdHJpbmd9IGEgcXVvdGVkIHN0cmluZ1xuICovXG5mdW5jdGlvbiBxdW90ZVN0cmluZ1ZhbHVlKHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGM6IGZ1bmN0aW9uIChzcHlJbnN0YW5jZSkge1xuICAgICAgICByZXR1cm4gdGltZXNJbldvcmRzKHNweUluc3RhbmNlLmNhbGxDb3VudCk7XG4gICAgfSxcblxuICAgIG46IGZ1bmN0aW9uIChzcHlJbnN0YW5jZSkge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHNpbm9uanMvbm8tcHJvdG90eXBlLW1ldGhvZHMvbm8tcHJvdG90eXBlLW1ldGhvZHNcbiAgICAgICAgcmV0dXJuIHNweUluc3RhbmNlLnRvU3RyaW5nKCk7XG4gICAgfSxcblxuICAgIEQ6IGZ1bmN0aW9uIChzcHlJbnN0YW5jZSwgYXJncykge1xuICAgICAgICBsZXQgbWVzc2FnZSA9IFwiXCI7XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDAsIGwgPSBzcHlJbnN0YW5jZS5jYWxsQ291bnQ7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgIC8vIGRlc2NyaWJlIG11bHRpcGxlIGNhbGxzXG4gICAgICAgICAgICBpZiAobCA+IDEpIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlICs9IGBcXG5DYWxsICR7aSArIDF9OmA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBjYWxsZWRBcmdzID0gc3B5SW5zdGFuY2UuZ2V0Q2FsbChpKS5hcmdzO1xuICAgICAgICAgICAgY29uc3QgZXhwZWN0ZWRBcmdzID0gc2xpY2UoYXJncyk7XG5cbiAgICAgICAgICAgIGZvciAoXG4gICAgICAgICAgICAgICAgbGV0IGogPSAwO1xuICAgICAgICAgICAgICAgIGogPCBjYWxsZWRBcmdzLmxlbmd0aCB8fCBqIDwgZXhwZWN0ZWRBcmdzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICArK2pcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGxldCBjYWxsZWRBcmcgPSBjYWxsZWRBcmdzW2pdO1xuICAgICAgICAgICAgICAgIGxldCBleHBlY3RlZEFyZyA9IGV4cGVjdGVkQXJnc1tqXTtcbiAgICAgICAgICAgICAgICBpZiAoY2FsbGVkQXJnKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxlZEFyZyA9IHF1b3RlU3RyaW5nVmFsdWUoY2FsbGVkQXJnKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoZXhwZWN0ZWRBcmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0ZWRBcmcgPSBxdW90ZVN0cmluZ1ZhbHVlKGV4cGVjdGVkQXJnKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBtZXNzYWdlICs9IFwiXFxuXCI7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBjYWxsZWRBcmdNZXNzYWdlID1cbiAgICAgICAgICAgICAgICAgICAgaiA8IGNhbGxlZEFyZ3MubGVuZ3RoID8gaW5zcGVjdChjYWxsZWRBcmcpIDogXCJcIjtcbiAgICAgICAgICAgICAgICBpZiAobWF0Y2guaXNNYXRjaGVyKGV4cGVjdGVkQXJnKSkge1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlICs9IGNvbG9yU2lub25NYXRjaFRleHQoXG4gICAgICAgICAgICAgICAgICAgICAgICBleHBlY3RlZEFyZyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxlZEFyZyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxlZEFyZ01lc3NhZ2UsXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXhwZWN0ZWRBcmdNZXNzYWdlID1cbiAgICAgICAgICAgICAgICAgICAgICAgIGogPCBleHBlY3RlZEFyZ3MubGVuZ3RoID8gaW5zcGVjdChleHBlY3RlZEFyZykgOiBcIlwiO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBkaWZmID0ganNEaWZmLmRpZmZKc29uKFxuICAgICAgICAgICAgICAgICAgICAgICAgY2FsbGVkQXJnTWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVjdGVkQXJnTWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSArPSBjb2xvckRpZmZUZXh0KGRpZmYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgIH0sXG5cbiAgICBDOiBmdW5jdGlvbiAoc3B5SW5zdGFuY2UpIHtcbiAgICAgICAgY29uc3QgY2FsbHMgPSBbXTtcblxuICAgICAgICBmb3IgKGxldCBpID0gMCwgbCA9IHNweUluc3RhbmNlLmNhbGxDb3VudDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBzaW5vbmpzL25vLXByb3RvdHlwZS1tZXRob2RzL25vLXByb3RvdHlwZS1tZXRob2RzXG4gICAgICAgICAgICBsZXQgc3RyaW5naWZpZWRDYWxsID0gYCAgICAke3NweUluc3RhbmNlLmdldENhbGwoaSkudG9TdHJpbmcoKX1gO1xuICAgICAgICAgICAgaWYgKC9cXG4vLnRlc3QoY2FsbHNbaSAtIDFdKSkge1xuICAgICAgICAgICAgICAgIHN0cmluZ2lmaWVkQ2FsbCA9IGBcXG4ke3N0cmluZ2lmaWVkQ2FsbH1gO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcHVzaChjYWxscywgc3RyaW5naWZpZWRDYWxsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjYWxscy5sZW5ndGggPiAwID8gYFxcbiR7am9pbihjYWxscywgXCJcXG5cIil9YCA6IFwiXCI7XG4gICAgfSxcblxuICAgIHQ6IGZ1bmN0aW9uIChzcHlJbnN0YW5jZSkge1xuICAgICAgICBjb25zdCBvYmplY3RzID0gW107XG5cbiAgICAgICAgZm9yIChsZXQgaSA9IDAsIGwgPSBzcHlJbnN0YW5jZS5jYWxsQ291bnQ7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgIHB1c2gob2JqZWN0cywgaW5zcGVjdChzcHlJbnN0YW5jZS50aGlzVmFsdWVzW2ldKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gam9pbihvYmplY3RzLCBcIiwgXCIpO1xuICAgIH0sXG5cbiAgICBcIipcIjogZnVuY3Rpb24gKHNweUluc3RhbmNlLCBhcmdzKSB7XG4gICAgICAgIHJldHVybiBqb2luKFxuICAgICAgICAgICAgbWFwKGFyZ3MsIGZ1bmN0aW9uIChhcmcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaW5zcGVjdChhcmcpO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBcIiwgXCIsXG4gICAgICAgICk7XG4gICAgfSxcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuY29uc3QgYXJyYXlQcm90byA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnByb3RvdHlwZXMuYXJyYXk7XG5jb25zdCBjcmVhdGVQcm94eSA9IHJlcXVpcmUoXCIuL3Byb3h5XCIpO1xuY29uc3QgZXh0ZW5kID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlL2V4dGVuZFwiKTtcbmNvbnN0IGZ1bmN0aW9uTmFtZSA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLmZ1bmN0aW9uTmFtZTtcbmNvbnN0IGdldFByb3BlcnR5RGVzY3JpcHRvciA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZS9nZXQtcHJvcGVydHktZGVzY3JpcHRvclwiKTtcbmNvbnN0IGRlZXBFcXVhbCA9IHJlcXVpcmUoXCJAc2lub25qcy9zYW1zYW1cIikuZGVlcEVxdWFsO1xuY29uc3QgaXNFc01vZHVsZSA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZS9pcy1lcy1tb2R1bGVcIik7XG5jb25zdCBwcm94eUNhbGxVdGlsID0gcmVxdWlyZShcIi4vcHJveHktY2FsbC11dGlsXCIpO1xuY29uc3Qgd2Fsa09iamVjdCA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZS93YWxrLW9iamVjdFwiKTtcbmNvbnN0IHdyYXBNZXRob2QgPSByZXF1aXJlKFwiLi91dGlsL2NvcmUvd3JhcC1tZXRob2RcIik7XG5jb25zdCB2YWx1ZVRvU3RyaW5nID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikudmFsdWVUb1N0cmluZztcblxuLyogY2FjaGUgcmVmZXJlbmNlcyB0byBsaWJyYXJ5IG1ldGhvZHMgc28gdGhhdCB0aGV5IGFsc28gY2FuIGJlIHN0dWJiZWQgd2l0aG91dCBwcm9ibGVtcyAqL1xuY29uc3QgZm9yRWFjaCA9IGFycmF5UHJvdG8uZm9yRWFjaDtcbmNvbnN0IHBvcCA9IGFycmF5UHJvdG8ucG9wO1xuY29uc3QgcHVzaCA9IGFycmF5UHJvdG8ucHVzaDtcbmNvbnN0IHNsaWNlID0gYXJyYXlQcm90by5zbGljZTtcbmNvbnN0IGZpbHRlciA9IEFycmF5LnByb3RvdHlwZS5maWx0ZXI7XG5cbmxldCB1dWlkID0gMDtcblxuZnVuY3Rpb24gbWF0Y2hlcyhmYWtlLCBhcmdzLCBzdHJpY3QpIHtcbiAgICBjb25zdCBtYXJncyA9IGZha2UubWF0Y2hpbmdBcmd1bWVudHM7XG4gICAgaWYgKFxuICAgICAgICBtYXJncy5sZW5ndGggPD0gYXJncy5sZW5ndGggJiZcbiAgICAgICAgZGVlcEVxdWFsKHNsaWNlKGFyZ3MsIDAsIG1hcmdzLmxlbmd0aCksIG1hcmdzKVxuICAgICkge1xuICAgICAgICByZXR1cm4gIXN0cmljdCB8fCBtYXJncy5sZW5ndGggPT09IGFyZ3MubGVuZ3RoO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG59XG5cbi8vIFB1YmxpYyBBUElcbmNvbnN0IHNweUFwaSA9IHtcbiAgICB3aXRoQXJnczogZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zdCBhcmdzID0gc2xpY2UoYXJndW1lbnRzKTtcbiAgICAgICAgY29uc3QgbWF0Y2hpbmcgPSBwb3AodGhpcy5tYXRjaGluZ0Zha2VzKGFyZ3MsIHRydWUpKTtcbiAgICAgICAgaWYgKG1hdGNoaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hpbmc7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBvcmlnaW5hbCA9IHRoaXM7XG4gICAgICAgIGNvbnN0IGZha2UgPSB0aGlzLmluc3RhbnRpYXRlRmFrZSgpO1xuICAgICAgICBmYWtlLm1hdGNoaW5nQXJndW1lbnRzID0gYXJncztcbiAgICAgICAgZmFrZS5wYXJlbnQgPSB0aGlzO1xuICAgICAgICBwdXNoKHRoaXMuZmFrZXMsIGZha2UpO1xuXG4gICAgICAgIGZha2Uud2l0aEFyZ3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gb3JpZ2luYWwud2l0aEFyZ3MuYXBwbHkob3JpZ2luYWwsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgZm9yRWFjaChvcmlnaW5hbC5hcmdzLCBmdW5jdGlvbiAoYXJnLCBpKSB7XG4gICAgICAgICAgICBpZiAoIW1hdGNoZXMoZmFrZSwgYXJnKSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcHJveHlDYWxsVXRpbC5pbmNyZW1lbnRDYWxsQ291bnQoZmFrZSk7XG4gICAgICAgICAgICBwdXNoKGZha2UudGhpc1ZhbHVlcywgb3JpZ2luYWwudGhpc1ZhbHVlc1tpXSk7XG4gICAgICAgICAgICBwdXNoKGZha2UuYXJncywgYXJnKTtcbiAgICAgICAgICAgIHB1c2goZmFrZS5yZXR1cm5WYWx1ZXMsIG9yaWdpbmFsLnJldHVyblZhbHVlc1tpXSk7XG4gICAgICAgICAgICBwdXNoKGZha2UuZXhjZXB0aW9ucywgb3JpZ2luYWwuZXhjZXB0aW9uc1tpXSk7XG4gICAgICAgICAgICBwdXNoKGZha2UuY2FsbElkcywgb3JpZ2luYWwuY2FsbElkc1tpXSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHByb3h5Q2FsbFV0aWwuY3JlYXRlQ2FsbFByb3BlcnRpZXMoZmFrZSk7XG5cbiAgICAgICAgcmV0dXJuIGZha2U7XG4gICAgfSxcblxuICAgIC8vIE92ZXJyaWRlIHByb3h5IGRlZmF1bHQgaW1wbGVtZW50YXRpb25cbiAgICBtYXRjaGluZ0Zha2VzOiBmdW5jdGlvbiAoYXJncywgc3RyaWN0KSB7XG4gICAgICAgIHJldHVybiBmaWx0ZXIuY2FsbCh0aGlzLmZha2VzLCBmdW5jdGlvbiAoZmFrZSkge1xuICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXMoZmFrZSwgYXJncywgc3RyaWN0KTtcbiAgICAgICAgfSk7XG4gICAgfSxcbn07XG5cbi8qIGVzbGludC1kaXNhYmxlIEBzaW5vbmpzL25vLXByb3RvdHlwZS1tZXRob2RzL25vLXByb3RvdHlwZS1tZXRob2RzICovXG5jb25zdCBkZWxlZ2F0ZVRvQ2FsbHMgPSBwcm94eUNhbGxVdGlsLmRlbGVnYXRlVG9DYWxscztcbmRlbGVnYXRlVG9DYWxscyhzcHlBcGksIFwiY2FsbEFyZ1wiLCBmYWxzZSwgXCJjYWxsQXJnV2l0aFwiLCB0cnVlLCBmdW5jdGlvbiAoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgJHt0aGlzLnRvU3RyaW5nKCl9IGNhbm5vdCBjYWxsIGFyZyBzaW5jZSBpdCB3YXMgbm90IHlldCBpbnZva2VkLmAsXG4gICAgKTtcbn0pO1xuc3B5QXBpLmNhbGxBcmdXaXRoID0gc3B5QXBpLmNhbGxBcmc7XG5kZWxlZ2F0ZVRvQ2FsbHMoc3B5QXBpLCBcImNhbGxBcmdPblwiLCBmYWxzZSwgXCJjYWxsQXJnT25XaXRoXCIsIHRydWUsIGZ1bmN0aW9uICgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGAke3RoaXMudG9TdHJpbmcoKX0gY2Fubm90IGNhbGwgYXJnIHNpbmNlIGl0IHdhcyBub3QgeWV0IGludm9rZWQuYCxcbiAgICApO1xufSk7XG5zcHlBcGkuY2FsbEFyZ09uV2l0aCA9IHNweUFwaS5jYWxsQXJnT247XG5kZWxlZ2F0ZVRvQ2FsbHMoc3B5QXBpLCBcInRocm93QXJnXCIsIGZhbHNlLCBcInRocm93QXJnXCIsIGZhbHNlLCBmdW5jdGlvbiAoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgJHt0aGlzLnRvU3RyaW5nKCl9IGNhbm5vdCB0aHJvdyBhcmcgc2luY2UgaXQgd2FzIG5vdCB5ZXQgaW52b2tlZC5gLFxuICAgICk7XG59KTtcbmRlbGVnYXRlVG9DYWxscyhzcHlBcGksIFwieWllbGRcIiwgZmFsc2UsIFwieWllbGRcIiwgdHJ1ZSwgZnVuY3Rpb24gKCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYCR7dGhpcy50b1N0cmluZygpfSBjYW5ub3QgeWllbGQgc2luY2UgaXQgd2FzIG5vdCB5ZXQgaW52b2tlZC5gLFxuICAgICk7XG59KTtcbi8vIFwiaW52b2tlQ2FsbGJhY2tcIiBpcyBhbiBhbGlhcyBmb3IgXCJ5aWVsZFwiIHNpbmNlIFwieWllbGRcIiBpcyBpbnZhbGlkIGluIHN0cmljdCBtb2RlLlxuc3B5QXBpLmludm9rZUNhbGxiYWNrID0gc3B5QXBpLnlpZWxkO1xuZGVsZWdhdGVUb0NhbGxzKHNweUFwaSwgXCJ5aWVsZE9uXCIsIGZhbHNlLCBcInlpZWxkT25cIiwgdHJ1ZSwgZnVuY3Rpb24gKCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYCR7dGhpcy50b1N0cmluZygpfSBjYW5ub3QgeWllbGQgc2luY2UgaXQgd2FzIG5vdCB5ZXQgaW52b2tlZC5gLFxuICAgICk7XG59KTtcbmRlbGVnYXRlVG9DYWxscyhzcHlBcGksIFwieWllbGRUb1wiLCBmYWxzZSwgXCJ5aWVsZFRvXCIsIHRydWUsIGZ1bmN0aW9uIChwcm9wZXJ0eSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYCR7dGhpcy50b1N0cmluZygpfSBjYW5ub3QgeWllbGQgdG8gJyR7dmFsdWVUb1N0cmluZyhcbiAgICAgICAgICAgIHByb3BlcnR5LFxuICAgICAgICApfScgc2luY2UgaXQgd2FzIG5vdCB5ZXQgaW52b2tlZC5gLFxuICAgICk7XG59KTtcbmRlbGVnYXRlVG9DYWxscyhcbiAgICBzcHlBcGksXG4gICAgXCJ5aWVsZFRvT25cIixcbiAgICBmYWxzZSxcbiAgICBcInlpZWxkVG9PblwiLFxuICAgIHRydWUsXG4gICAgZnVuY3Rpb24gKHByb3BlcnR5KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGAke3RoaXMudG9TdHJpbmcoKX0gY2Fubm90IHlpZWxkIHRvICcke3ZhbHVlVG9TdHJpbmcoXG4gICAgICAgICAgICAgICAgcHJvcGVydHksXG4gICAgICAgICAgICApfScgc2luY2UgaXQgd2FzIG5vdCB5ZXQgaW52b2tlZC5gLFxuICAgICAgICApO1xuICAgIH0sXG4pO1xuXG5mdW5jdGlvbiBjcmVhdGVTcHkoZnVuYykge1xuICAgIGxldCBuYW1lO1xuICAgIGxldCBmdW5rID0gZnVuYztcblxuICAgIGlmICh0eXBlb2YgZnVuayAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIGZ1bmsgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbmFtZSA9IGZ1bmN0aW9uTmFtZShmdW5rKTtcbiAgICB9XG5cbiAgICBjb25zdCBwcm94eSA9IGNyZWF0ZVByb3h5KGZ1bmssIGZ1bmspO1xuXG4gICAgLy8gSW5oZXJpdCBzcHkgQVBJOlxuICAgIGV4dGVuZC5ub25FbnVtKHByb3h5LCBzcHlBcGkpO1xuICAgIGV4dGVuZC5ub25FbnVtKHByb3h5LCB7XG4gICAgICAgIGRpc3BsYXlOYW1lOiBuYW1lIHx8IFwic3B5XCIsXG4gICAgICAgIGZha2VzOiBbXSxcbiAgICAgICAgaW5zdGFudGlhdGVGYWtlOiBjcmVhdGVTcHksXG4gICAgICAgIGlkOiBgc3B5IyR7dXVpZCsrfWAsXG4gICAgfSk7XG4gICAgcmV0dXJuIHByb3h5O1xufVxuXG5mdW5jdGlvbiBzcHkob2JqZWN0LCBwcm9wZXJ0eSwgdHlwZXMpIHtcbiAgICBpZiAoaXNFc01vZHVsZShvYmplY3QpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJFUyBNb2R1bGVzIGNhbm5vdCBiZSBzcGllZFwiKTtcbiAgICB9XG5cbiAgICBpZiAoIXByb3BlcnR5ICYmIHR5cGVvZiBvYmplY3QgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICByZXR1cm4gY3JlYXRlU3B5KG9iamVjdCk7XG4gICAgfVxuXG4gICAgaWYgKCFwcm9wZXJ0eSAmJiB0eXBlb2Ygb2JqZWN0ID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHJldHVybiB3YWxrT2JqZWN0KHNweSwgb2JqZWN0KTtcbiAgICB9XG5cbiAgICBpZiAoIW9iamVjdCAmJiAhcHJvcGVydHkpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZVNweShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICghdHlwZXMpIHtcbiAgICAgICAgcmV0dXJuIHdyYXBNZXRob2Qob2JqZWN0LCBwcm9wZXJ0eSwgY3JlYXRlU3B5KG9iamVjdFtwcm9wZXJ0eV0pKTtcbiAgICB9XG5cbiAgICBjb25zdCBkZXNjcmlwdG9yID0ge307XG4gICAgY29uc3QgbWV0aG9kRGVzYyA9IGdldFByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTtcblxuICAgIGZvckVhY2godHlwZXMsIGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgIGRlc2NyaXB0b3JbdHlwZV0gPSBjcmVhdGVTcHkobWV0aG9kRGVzY1t0eXBlXSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gd3JhcE1ldGhvZChvYmplY3QsIHByb3BlcnR5LCBkZXNjcmlwdG9yKTtcbn1cblxuZXh0ZW5kKHNweSwgc3B5QXBpKTtcbm1vZHVsZS5leHBvcnRzID0gc3B5O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IGFycmF5UHJvdG8gPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLmFycmF5O1xuY29uc3QgYmVoYXZpb3IgPSByZXF1aXJlKFwiLi9iZWhhdmlvclwiKTtcbmNvbnN0IGJlaGF2aW9ycyA9IHJlcXVpcmUoXCIuL2RlZmF1bHQtYmVoYXZpb3JzXCIpO1xuY29uc3QgY3JlYXRlUHJveHkgPSByZXF1aXJlKFwiLi9wcm94eVwiKTtcbmNvbnN0IGZ1bmN0aW9uTmFtZSA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLmZ1bmN0aW9uTmFtZTtcbmNvbnN0IGhhc093blByb3BlcnR5ID1cbiAgICByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLm9iamVjdC5oYXNPd25Qcm9wZXJ0eTtcbmNvbnN0IGlzTm9uRXhpc3RlbnRQcm9wZXJ0eSA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZS9pcy1ub24tZXhpc3RlbnQtcHJvcGVydHlcIik7XG5jb25zdCBzcHkgPSByZXF1aXJlKFwiLi9zcHlcIik7XG5jb25zdCBleHRlbmQgPSByZXF1aXJlKFwiLi91dGlsL2NvcmUvZXh0ZW5kXCIpO1xuY29uc3QgZ2V0UHJvcGVydHlEZXNjcmlwdG9yID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlL2dldC1wcm9wZXJ0eS1kZXNjcmlwdG9yXCIpO1xuY29uc3QgaXNFc01vZHVsZSA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZS9pcy1lcy1tb2R1bGVcIik7XG5jb25zdCBzaW5vblR5cGUgPSByZXF1aXJlKFwiLi91dGlsL2NvcmUvc2lub24tdHlwZVwiKTtcbmNvbnN0IHdyYXBNZXRob2QgPSByZXF1aXJlKFwiLi91dGlsL2NvcmUvd3JhcC1tZXRob2RcIik7XG5jb25zdCB0aHJvd09uRmFsc3lPYmplY3QgPSByZXF1aXJlKFwiLi90aHJvdy1vbi1mYWxzeS1vYmplY3RcIik7XG5jb25zdCB2YWx1ZVRvU3RyaW5nID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikudmFsdWVUb1N0cmluZztcbmNvbnN0IHdhbGtPYmplY3QgPSByZXF1aXJlKFwiLi91dGlsL2NvcmUvd2Fsay1vYmplY3RcIik7XG5cbmNvbnN0IGZvckVhY2ggPSBhcnJheVByb3RvLmZvckVhY2g7XG5jb25zdCBwb3AgPSBhcnJheVByb3RvLnBvcDtcbmNvbnN0IHNsaWNlID0gYXJyYXlQcm90by5zbGljZTtcbmNvbnN0IHNvcnQgPSBhcnJheVByb3RvLnNvcnQ7XG5cbmxldCB1dWlkID0gMDtcblxuZnVuY3Rpb24gY3JlYXRlU3R1YihvcmlnaW5hbEZ1bmMpIHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLWNvbnN0XG4gICAgbGV0IHByb3h5O1xuXG4gICAgZnVuY3Rpb24gZnVuY3Rpb25TdHViKCkge1xuICAgICAgICBjb25zdCBhcmdzID0gc2xpY2UoYXJndW1lbnRzKTtcbiAgICAgICAgY29uc3QgbWF0Y2hpbmdzID0gcHJveHkubWF0Y2hpbmdGYWtlcyhhcmdzKTtcblxuICAgICAgICBjb25zdCBmblN0dWIgPVxuICAgICAgICAgICAgcG9wKFxuICAgICAgICAgICAgICAgIHNvcnQobWF0Y2hpbmdzLCBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgICAgICAgICAgYS5tYXRjaGluZ0FyZ3VtZW50cy5sZW5ndGggLSBiLm1hdGNoaW5nQXJndW1lbnRzLmxlbmd0aFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgKSB8fCBwcm94eTtcbiAgICAgICAgcmV0dXJuIGdldEN1cnJlbnRCZWhhdmlvcihmblN0dWIpLmludm9rZSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cblxuICAgIHByb3h5ID0gY3JlYXRlUHJveHkoZnVuY3Rpb25TdHViLCBvcmlnaW5hbEZ1bmMgfHwgZnVuY3Rpb25TdHViKTtcbiAgICAvLyBJbmhlcml0IHNweSBBUEk6XG4gICAgZXh0ZW5kLm5vbkVudW0ocHJveHksIHNweSk7XG4gICAgLy8gSW5oZXJpdCBzdHViIEFQSTpcbiAgICBleHRlbmQubm9uRW51bShwcm94eSwgc3R1Yik7XG5cbiAgICBjb25zdCBuYW1lID0gb3JpZ2luYWxGdW5jID8gZnVuY3Rpb25OYW1lKG9yaWdpbmFsRnVuYykgOiBudWxsO1xuICAgIGV4dGVuZC5ub25FbnVtKHByb3h5LCB7XG4gICAgICAgIGZha2VzOiBbXSxcbiAgICAgICAgaW5zdGFudGlhdGVGYWtlOiBjcmVhdGVTdHViLFxuICAgICAgICBkaXNwbGF5TmFtZTogbmFtZSB8fCBcInN0dWJcIixcbiAgICAgICAgZGVmYXVsdEJlaGF2aW9yOiBudWxsLFxuICAgICAgICBiZWhhdmlvcnM6IFtdLFxuICAgICAgICBpZDogYHN0dWIjJHt1dWlkKyt9YCxcbiAgICB9KTtcblxuICAgIHNpbm9uVHlwZS5zZXQocHJveHksIFwic3R1YlwiKTtcblxuICAgIHJldHVybiBwcm94eTtcbn1cblxuZnVuY3Rpb24gc3R1YihvYmplY3QsIHByb3BlcnR5KSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAyKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICBcInN0dWIob2JqLCAnbWV0aCcsIGZuKSBoYXMgYmVlbiByZW1vdmVkLCBzZWUgZG9jdW1lbnRhdGlvblwiLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGlmIChpc0VzTW9kdWxlKG9iamVjdCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkVTIE1vZHVsZXMgY2Fubm90IGJlIHN0dWJiZWRcIik7XG4gICAgfVxuXG4gICAgdGhyb3dPbkZhbHN5T2JqZWN0LmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG5cbiAgICBpZiAoaXNOb25FeGlzdGVudFByb3BlcnR5KG9iamVjdCwgcHJvcGVydHkpKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICBgQ2Fubm90IHN0dWIgbm9uLWV4aXN0ZW50IHByb3BlcnR5ICR7dmFsdWVUb1N0cmluZyhwcm9wZXJ0eSl9YCxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBhY3R1YWxEZXNjcmlwdG9yID0gZ2V0UHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpO1xuXG4gICAgYXNzZXJ0VmFsaWRQcm9wZXJ0eURlc2NyaXB0b3IoYWN0dWFsRGVzY3JpcHRvciwgcHJvcGVydHkpO1xuXG4gICAgY29uc3QgaXNPYmplY3RPckZ1bmN0aW9uID1cbiAgICAgICAgdHlwZW9mIG9iamVjdCA9PT0gXCJvYmplY3RcIiB8fCB0eXBlb2Ygb2JqZWN0ID09PSBcImZ1bmN0aW9uXCI7XG4gICAgY29uc3QgaXNTdHViYmluZ0VudGlyZU9iamVjdCA9XG4gICAgICAgIHR5cGVvZiBwcm9wZXJ0eSA9PT0gXCJ1bmRlZmluZWRcIiAmJiBpc09iamVjdE9yRnVuY3Rpb247XG4gICAgY29uc3QgaXNDcmVhdGluZ05ld1N0dWIgPSAhb2JqZWN0ICYmIHR5cGVvZiBwcm9wZXJ0eSA9PT0gXCJ1bmRlZmluZWRcIjtcbiAgICBjb25zdCBpc1N0dWJiaW5nTm9uRnVuY1Byb3BlcnR5ID1cbiAgICAgICAgaXNPYmplY3RPckZ1bmN0aW9uICYmXG4gICAgICAgIHR5cGVvZiBwcm9wZXJ0eSAhPT0gXCJ1bmRlZmluZWRcIiAmJlxuICAgICAgICAodHlwZW9mIGFjdHVhbERlc2NyaXB0b3IgPT09IFwidW5kZWZpbmVkXCIgfHxcbiAgICAgICAgICAgIHR5cGVvZiBhY3R1YWxEZXNjcmlwdG9yLnZhbHVlICE9PSBcImZ1bmN0aW9uXCIpO1xuXG4gICAgaWYgKGlzU3R1YmJpbmdFbnRpcmVPYmplY3QpIHtcbiAgICAgICAgcmV0dXJuIHdhbGtPYmplY3Qoc3R1Yiwgb2JqZWN0KTtcbiAgICB9XG5cbiAgICBpZiAoaXNDcmVhdGluZ05ld1N0dWIpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZVN0dWIoKTtcbiAgICB9XG5cbiAgICBjb25zdCBmdW5jID1cbiAgICAgICAgdHlwZW9mIGFjdHVhbERlc2NyaXB0b3IudmFsdWUgPT09IFwiZnVuY3Rpb25cIlxuICAgICAgICAgICAgPyBhY3R1YWxEZXNjcmlwdG9yLnZhbHVlXG4gICAgICAgICAgICA6IG51bGw7XG4gICAgY29uc3QgcyA9IGNyZWF0ZVN0dWIoZnVuYyk7XG5cbiAgICBleHRlbmQubm9uRW51bShzLCB7XG4gICAgICAgIHJvb3RPYmo6IG9iamVjdCxcbiAgICAgICAgcHJvcE5hbWU6IHByb3BlcnR5LFxuICAgICAgICBzaGFkb3dzUHJvcE9uUHJvdG90eXBlOiAhYWN0dWFsRGVzY3JpcHRvci5pc093bixcbiAgICAgICAgcmVzdG9yZTogZnVuY3Rpb24gcmVzdG9yZSgpIHtcbiAgICAgICAgICAgIGlmIChhY3R1YWxEZXNjcmlwdG9yICE9PSB1bmRlZmluZWQgJiYgYWN0dWFsRGVzY3JpcHRvci5pc093bikge1xuICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmplY3QsIHByb3BlcnR5LCBhY3R1YWxEZXNjcmlwdG9yKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGRlbGV0ZSBvYmplY3RbcHJvcGVydHldO1xuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIGlzU3R1YmJpbmdOb25GdW5jUHJvcGVydHkgPyBzIDogd3JhcE1ldGhvZChvYmplY3QsIHByb3BlcnR5LCBzKTtcbn1cblxuZnVuY3Rpb24gYXNzZXJ0VmFsaWRQcm9wZXJ0eURlc2NyaXB0b3IoZGVzY3JpcHRvciwgcHJvcGVydHkpIHtcbiAgICBpZiAoIWRlc2NyaXB0b3IgfHwgIXByb3BlcnR5KSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGRlc2NyaXB0b3IuaXNPd24gJiYgIWRlc2NyaXB0b3IuY29uZmlndXJhYmxlICYmICFkZXNjcmlwdG9yLndyaXRhYmxlKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICBgRGVzY3JpcHRvciBmb3IgcHJvcGVydHkgJHtwcm9wZXJ0eX0gaXMgbm9uLWNvbmZpZ3VyYWJsZSBhbmQgbm9uLXdyaXRhYmxlYCxcbiAgICAgICAgKTtcbiAgICB9XG4gICAgaWYgKChkZXNjcmlwdG9yLmdldCB8fCBkZXNjcmlwdG9yLnNldCkgJiYgIWRlc2NyaXB0b3IuY29uZmlndXJhYmxlKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICBgRGVzY3JpcHRvciBmb3IgYWNjZXNzb3IgcHJvcGVydHkgJHtwcm9wZXJ0eX0gaXMgbm9uLWNvbmZpZ3VyYWJsZWAsXG4gICAgICAgICk7XG4gICAgfVxuICAgIGlmIChpc0RhdGFEZXNjcmlwdG9yKGRlc2NyaXB0b3IpICYmICFkZXNjcmlwdG9yLndyaXRhYmxlKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICBgRGVzY3JpcHRvciBmb3IgZGF0YSBwcm9wZXJ0eSAke3Byb3BlcnR5fSBpcyBub24td3JpdGFibGVgLFxuICAgICAgICApO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaXNEYXRhRGVzY3JpcHRvcihkZXNjcmlwdG9yKSB7XG4gICAgcmV0dXJuIChcbiAgICAgICAgIWRlc2NyaXB0b3IudmFsdWUgJiZcbiAgICAgICAgIWRlc2NyaXB0b3Iud3JpdGFibGUgJiZcbiAgICAgICAgIWRlc2NyaXB0b3Iuc2V0ICYmXG4gICAgICAgICFkZXNjcmlwdG9yLmdldFxuICAgICk7XG59XG5cbi8qZXNsaW50LWRpc2FibGUgbm8tdXNlLWJlZm9yZS1kZWZpbmUqL1xuZnVuY3Rpb24gZ2V0UGFyZW50QmVoYXZpb3VyKHN0dWJJbnN0YW5jZSkge1xuICAgIHJldHVybiBzdHViSW5zdGFuY2UucGFyZW50ICYmIGdldEN1cnJlbnRCZWhhdmlvcihzdHViSW5zdGFuY2UucGFyZW50KTtcbn1cblxuZnVuY3Rpb24gZ2V0RGVmYXVsdEJlaGF2aW9yKHN0dWJJbnN0YW5jZSkge1xuICAgIHJldHVybiAoXG4gICAgICAgIHN0dWJJbnN0YW5jZS5kZWZhdWx0QmVoYXZpb3IgfHxcbiAgICAgICAgZ2V0UGFyZW50QmVoYXZpb3VyKHN0dWJJbnN0YW5jZSkgfHxcbiAgICAgICAgYmVoYXZpb3IuY3JlYXRlKHN0dWJJbnN0YW5jZSlcbiAgICApO1xufVxuXG5mdW5jdGlvbiBnZXRDdXJyZW50QmVoYXZpb3Ioc3R1Ykluc3RhbmNlKSB7XG4gICAgY29uc3QgY3VycmVudEJlaGF2aW9yID0gc3R1Ykluc3RhbmNlLmJlaGF2aW9yc1tzdHViSW5zdGFuY2UuY2FsbENvdW50IC0gMV07XG4gICAgcmV0dXJuIGN1cnJlbnRCZWhhdmlvciAmJiBjdXJyZW50QmVoYXZpb3IuaXNQcmVzZW50KClcbiAgICAgICAgPyBjdXJyZW50QmVoYXZpb3JcbiAgICAgICAgOiBnZXREZWZhdWx0QmVoYXZpb3Ioc3R1Ykluc3RhbmNlKTtcbn1cbi8qZXNsaW50LWVuYWJsZSBuby11c2UtYmVmb3JlLWRlZmluZSovXG5cbmNvbnN0IHByb3RvID0ge1xuICAgIHJlc2V0QmVoYXZpb3I6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kZWZhdWx0QmVoYXZpb3IgPSBudWxsO1xuICAgICAgICB0aGlzLmJlaGF2aW9ycyA9IFtdO1xuXG4gICAgICAgIGRlbGV0ZSB0aGlzLnJldHVyblZhbHVlO1xuICAgICAgICBkZWxldGUgdGhpcy5yZXR1cm5BcmdBdDtcbiAgICAgICAgZGVsZXRlIHRoaXMudGhyb3dBcmdBdDtcbiAgICAgICAgZGVsZXRlIHRoaXMucmVzb2x2ZUFyZ0F0O1xuICAgICAgICBkZWxldGUgdGhpcy5mYWtlRm47XG4gICAgICAgIHRoaXMucmV0dXJuVGhpcyA9IGZhbHNlO1xuICAgICAgICB0aGlzLnJlc29sdmVUaGlzID0gZmFsc2U7XG5cbiAgICAgICAgZm9yRWFjaCh0aGlzLmZha2VzLCBmdW5jdGlvbiAoZmFrZSkge1xuICAgICAgICAgICAgZmFrZS5yZXNldEJlaGF2aW9yKCk7XG4gICAgICAgIH0pO1xuICAgIH0sXG5cbiAgICByZXNldDogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlc2V0SGlzdG9yeSgpO1xuICAgICAgICB0aGlzLnJlc2V0QmVoYXZpb3IoKTtcbiAgICB9LFxuXG4gICAgb25DYWxsOiBmdW5jdGlvbiBvbkNhbGwoaW5kZXgpIHtcbiAgICAgICAgaWYgKCF0aGlzLmJlaGF2aW9yc1tpbmRleF0pIHtcbiAgICAgICAgICAgIHRoaXMuYmVoYXZpb3JzW2luZGV4XSA9IGJlaGF2aW9yLmNyZWF0ZSh0aGlzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLmJlaGF2aW9yc1tpbmRleF07XG4gICAgfSxcblxuICAgIG9uRmlyc3RDYWxsOiBmdW5jdGlvbiBvbkZpcnN0Q2FsbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub25DYWxsKDApO1xuICAgIH0sXG5cbiAgICBvblNlY29uZENhbGw6IGZ1bmN0aW9uIG9uU2Vjb25kQ2FsbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub25DYWxsKDEpO1xuICAgIH0sXG5cbiAgICBvblRoaXJkQ2FsbDogZnVuY3Rpb24gb25UaGlyZENhbGwoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm9uQ2FsbCgyKTtcbiAgICB9LFxuXG4gICAgd2l0aEFyZ3M6IGZ1bmN0aW9uIHdpdGhBcmdzKCkge1xuICAgICAgICBjb25zdCBmYWtlID0gc3B5LndpdGhBcmdzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIGlmICh0aGlzLmRlZmF1bHRCZWhhdmlvciAmJiB0aGlzLmRlZmF1bHRCZWhhdmlvci5wcm9taXNlTGlicmFyeSkge1xuICAgICAgICAgICAgZmFrZS5kZWZhdWx0QmVoYXZpb3IgPVxuICAgICAgICAgICAgICAgIGZha2UuZGVmYXVsdEJlaGF2aW9yIHx8IGJlaGF2aW9yLmNyZWF0ZShmYWtlKTtcbiAgICAgICAgICAgIGZha2UuZGVmYXVsdEJlaGF2aW9yLnByb21pc2VMaWJyYXJ5ID1cbiAgICAgICAgICAgICAgICB0aGlzLmRlZmF1bHRCZWhhdmlvci5wcm9taXNlTGlicmFyeTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFrZTtcbiAgICB9LFxufTtcblxuZm9yRWFjaChPYmplY3Qua2V5cyhiZWhhdmlvciksIGZ1bmN0aW9uIChtZXRob2QpIHtcbiAgICBpZiAoXG4gICAgICAgIGhhc093blByb3BlcnR5KGJlaGF2aW9yLCBtZXRob2QpICYmXG4gICAgICAgICFoYXNPd25Qcm9wZXJ0eShwcm90bywgbWV0aG9kKSAmJlxuICAgICAgICBtZXRob2QgIT09IFwiY3JlYXRlXCIgJiZcbiAgICAgICAgbWV0aG9kICE9PSBcImludm9rZVwiXG4gICAgKSB7XG4gICAgICAgIHByb3RvW21ldGhvZF0gPSBiZWhhdmlvci5jcmVhdGVCZWhhdmlvcihtZXRob2QpO1xuICAgIH1cbn0pO1xuXG5mb3JFYWNoKE9iamVjdC5rZXlzKGJlaGF2aW9ycyksIGZ1bmN0aW9uIChtZXRob2QpIHtcbiAgICBpZiAoaGFzT3duUHJvcGVydHkoYmVoYXZpb3JzLCBtZXRob2QpICYmICFoYXNPd25Qcm9wZXJ0eShwcm90bywgbWV0aG9kKSkge1xuICAgICAgICBiZWhhdmlvci5hZGRCZWhhdmlvcihzdHViLCBtZXRob2QsIGJlaGF2aW9yc1ttZXRob2RdKTtcbiAgICB9XG59KTtcblxuZXh0ZW5kKHN0dWIsIHByb3RvKTtcbm1vZHVsZS5leHBvcnRzID0gc3R1YjtcbiIsIlwidXNlIHN0cmljdFwiO1xuY29uc3QgdmFsdWVUb1N0cmluZyA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnZhbHVlVG9TdHJpbmc7XG5cbmZ1bmN0aW9uIHRocm93T25GYWxzeU9iamVjdChvYmplY3QsIHByb3BlcnR5KSB7XG4gICAgaWYgKHByb3BlcnR5ICYmICFvYmplY3QpIHtcbiAgICAgICAgY29uc3QgdHlwZSA9IG9iamVjdCA9PT0gbnVsbCA/IFwibnVsbFwiIDogXCJ1bmRlZmluZWRcIjtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYFRyeWluZyB0byBzdHViIHByb3BlcnR5ICcke3ZhbHVlVG9TdHJpbmcocHJvcGVydHkpfScgb2YgJHt0eXBlfWAsXG4gICAgICAgICk7XG4gICAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHRocm93T25GYWxzeU9iamVjdDtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5jb25zdCBhcnJheVByb3RvID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikucHJvdG90eXBlcy5hcnJheTtcbmNvbnN0IHJlZHVjZSA9IGFycmF5UHJvdG8ucmVkdWNlO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGV4cG9ydEFzeW5jQmVoYXZpb3JzKGJlaGF2aW9yTWV0aG9kcykge1xuICAgIHJldHVybiByZWR1Y2UoXG4gICAgICAgIE9iamVjdC5rZXlzKGJlaGF2aW9yTWV0aG9kcyksXG4gICAgICAgIGZ1bmN0aW9uIChhY2MsIG1ldGhvZCkge1xuICAgICAgICAgICAgLy8gbmVlZCB0byBhdm9pZCBjcmVhdGluZyBhbm90aGVyIGFzeW5jIHZlcnNpb25zIG9mIHRoZSBuZXdseSBhZGRlZCBhc3luYyBtZXRob2RzXG4gICAgICAgICAgICBpZiAobWV0aG9kLm1hdGNoKC9eKGNhbGxzQXJnfHlpZWxkcykvKSAmJiAhbWV0aG9kLm1hdGNoKC9Bc3luYy8pKSB7XG4gICAgICAgICAgICAgICAgYWNjW2Ake21ldGhvZH1Bc3luY2BdID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBiZWhhdmlvck1ldGhvZHNbbWV0aG9kXS5hcHBseShcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBhcmd1bWVudHMsXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBc3luYyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgIH0sXG4gICAgICAgIHt9LFxuICAgICk7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IGFycmF5UHJvdG8gPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLmFycmF5O1xuY29uc3QgaGFzT3duUHJvcGVydHkgPVxuICAgIHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnByb3RvdHlwZXMub2JqZWN0Lmhhc093blByb3BlcnR5O1xuXG5jb25zdCBqb2luID0gYXJyYXlQcm90by5qb2luO1xuY29uc3QgcHVzaCA9IGFycmF5UHJvdG8ucHVzaDtcblxuLy8gQWRhcHRlZCBmcm9tIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuL2RvY3MvRUNNQVNjcmlwdF9Eb250RW51bV9hdHRyaWJ1dGUjSlNjcmlwdF9Eb250RW51bV9CdWdcbmNvbnN0IGhhc0RvbnRFbnVtQnVnID0gKGZ1bmN0aW9uICgpIHtcbiAgICBjb25zdCBvYmogPSB7XG4gICAgICAgIGNvbnN0cnVjdG9yOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gXCIwXCI7XG4gICAgICAgIH0sXG4gICAgICAgIHRvU3RyaW5nOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gXCIxXCI7XG4gICAgICAgIH0sXG4gICAgICAgIHZhbHVlT2Y6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBcIjJcIjtcbiAgICAgICAgfSxcbiAgICAgICAgdG9Mb2NhbGVTdHJpbmc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBcIjNcIjtcbiAgICAgICAgfSxcbiAgICAgICAgcHJvdG90eXBlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gXCI0XCI7XG4gICAgICAgIH0sXG4gICAgICAgIGlzUHJvdG90eXBlT2Y6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBcIjVcIjtcbiAgICAgICAgfSxcbiAgICAgICAgcHJvcGVydHlJc0VudW1lcmFibGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBcIjZcIjtcbiAgICAgICAgfSxcbiAgICAgICAgaGFzT3duUHJvcGVydHk6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBcIjdcIjtcbiAgICAgICAgfSxcbiAgICAgICAgbGVuZ3RoOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gXCI4XCI7XG4gICAgICAgIH0sXG4gICAgICAgIHVuaXF1ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIFwiOVwiO1xuICAgICAgICB9LFxuICAgIH07XG5cbiAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICBmb3IgKGNvbnN0IHByb3AgaW4gb2JqKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wZXJ0eShvYmosIHByb3ApKSB7XG4gICAgICAgICAgICBwdXNoKHJlc3VsdCwgb2JqW3Byb3BdKCkpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBqb2luKHJlc3VsdCwgXCJcIikgIT09IFwiMDEyMzQ1Njc4OVwiO1xufSkoKTtcblxuLyoqXG4gKlxuICogQHBhcmFtIHRhcmdldFxuICogQHBhcmFtIHNvdXJjZXNcbiAqIEBwYXJhbSBkb0NvcHlcbiAqIEByZXR1cm5zIHsqfSB0YXJnZXRcbiAqL1xuZnVuY3Rpb24gZXh0ZW5kQ29tbW9uKHRhcmdldCwgc291cmNlcywgZG9Db3B5KSB7XG4gICAgbGV0IHNvdXJjZSwgaSwgcHJvcDtcblxuICAgIGZvciAoaSA9IDA7IGkgPCBzb3VyY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHNvdXJjZSA9IHNvdXJjZXNbaV07XG5cbiAgICAgICAgZm9yIChwcm9wIGluIHNvdXJjZSkge1xuICAgICAgICAgICAgaWYgKGhhc093blByb3BlcnR5KHNvdXJjZSwgcHJvcCkpIHtcbiAgICAgICAgICAgICAgICBkb0NvcHkodGFyZ2V0LCBzb3VyY2UsIHByb3ApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gTWFrZSBzdXJlIHdlIGNvcHkgKG93bikgdG9TdHJpbmcgbWV0aG9kIGV2ZW4gd2hlbiBpbiBKU2NyaXB0IHdpdGggRG9udEVudW0gYnVnXG4gICAgICAgIC8vIFNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi9kb2NzL0VDTUFTY3JpcHRfRG9udEVudW1fYXR0cmlidXRlI0pTY3JpcHRfRG9udEVudW1fQnVnXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGhhc0RvbnRFbnVtQnVnICYmXG4gICAgICAgICAgICBoYXNPd25Qcm9wZXJ0eShzb3VyY2UsIFwidG9TdHJpbmdcIikgJiZcbiAgICAgICAgICAgIHNvdXJjZS50b1N0cmluZyAhPT0gdGFyZ2V0LnRvU3RyaW5nXG4gICAgICAgICkge1xuICAgICAgICAgICAgdGFyZ2V0LnRvU3RyaW5nID0gc291cmNlLnRvU3RyaW5nO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRhcmdldDtcbn1cblxuLyoqXG4gKiBQdWJsaWM6IEV4dGVuZCB0YXJnZXQgaW4gcGxhY2Ugd2l0aCBhbGwgKG93bikgcHJvcGVydGllcywgZXhjZXB0ICduYW1lJyB3aGVuIFtbd3JpdGFibGVdXSBpcyBmYWxzZSxcbiAqICAgICAgICAgZnJvbSBzb3VyY2VzIGluLW9yZGVyLiBUaHVzLCBsYXN0IHNvdXJjZSB3aWxsIG92ZXJyaWRlIHByb3BlcnRpZXMgaW4gcHJldmlvdXMgc291cmNlcy5cbiAqXG4gKiBAcGFyYW0ge29iamVjdH0gdGFyZ2V0IC0gVGhlIE9iamVjdCB0byBleHRlbmRcbiAqIEBwYXJhbSB7b2JqZWN0W119IHNvdXJjZXMgLSBPYmplY3RzIHRvIGNvcHkgcHJvcGVydGllcyBmcm9tLlxuICogQHJldHVybnMge29iamVjdH0gdGhlIGV4dGVuZGVkIHRhcmdldFxuICovXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGV4dGVuZCh0YXJnZXQsIC4uLnNvdXJjZXMpIHtcbiAgICByZXR1cm4gZXh0ZW5kQ29tbW9uKFxuICAgICAgICB0YXJnZXQsXG4gICAgICAgIHNvdXJjZXMsXG4gICAgICAgIGZ1bmN0aW9uIGNvcHlWYWx1ZShkZXN0LCBzb3VyY2UsIHByb3ApIHtcbiAgICAgICAgICAgIGNvbnN0IGRlc3RPd25Qcm9wZXJ0eURlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKFxuICAgICAgICAgICAgICAgIGRlc3QsXG4gICAgICAgICAgICAgICAgcHJvcCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjb25zdCBzb3VyY2VPd25Qcm9wZXJ0eURlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKFxuICAgICAgICAgICAgICAgIHNvdXJjZSxcbiAgICAgICAgICAgICAgICBwcm9wLFxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgaWYgKHByb3AgPT09IFwibmFtZVwiICYmICFkZXN0T3duUHJvcGVydHlEZXNjcmlwdG9yLndyaXRhYmxlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZGVzY3JpcHRvcnMgPSB7XG4gICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiBzb3VyY2VPd25Qcm9wZXJ0eURlc2NyaXB0b3IuY29uZmlndXJhYmxlLFxuICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IHNvdXJjZU93blByb3BlcnR5RGVzY3JpcHRvci5lbnVtZXJhYmxlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAgaWYgdGhlIHNvdXJjZSBoYXMgYW4gQWNjZXNzb3IgcHJvcGVydHkgY29weSBvdmVyIHRoZSBhY2Nlc3NvciBmdW5jdGlvbnMgKGdldCBhbmQgc2V0KVxuICAgICAgICAgICAgICAgIGRhdGEgcHJvcGVydGllcyBoYXMgd3JpdGFibGUgYXR0cmlidXRlIHdoZXJlIGFzIGFjY2Vzc29yIHByb3BlcnR5IGRvbid0XG4gICAgICAgICAgICAgICAgUkVGOiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L0RhdGFfc3RydWN0dXJlcyNwcm9wZXJ0aWVzXG4gICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICBpZiAoaGFzT3duUHJvcGVydHkoc291cmNlT3duUHJvcGVydHlEZXNjcmlwdG9yLCBcIndyaXRhYmxlXCIpKSB7XG4gICAgICAgICAgICAgICAgZGVzY3JpcHRvcnMud3JpdGFibGUgPSBzb3VyY2VPd25Qcm9wZXJ0eURlc2NyaXB0b3Iud3JpdGFibGU7XG4gICAgICAgICAgICAgICAgZGVzY3JpcHRvcnMudmFsdWUgPSBzb3VyY2VPd25Qcm9wZXJ0eURlc2NyaXB0b3IudmFsdWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChzb3VyY2VPd25Qcm9wZXJ0eURlc2NyaXB0b3IuZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0b3JzLmdldCA9XG4gICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VPd25Qcm9wZXJ0eURlc2NyaXB0b3IuZ2V0LmJpbmQoZGVzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzb3VyY2VPd25Qcm9wZXJ0eURlc2NyaXB0b3Iuc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0b3JzLnNldCA9XG4gICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VPd25Qcm9wZXJ0eURlc2NyaXB0b3Iuc2V0LmJpbmQoZGVzdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGRlc3QsIHByb3AsIGRlc2NyaXB0b3JzKTtcbiAgICAgICAgfSxcbiAgICApO1xufTtcblxuLyoqXG4gKiBQdWJsaWM6IEV4dGVuZCB0YXJnZXQgaW4gcGxhY2Ugd2l0aCBhbGwgKG93bikgcHJvcGVydGllcyBmcm9tIHNvdXJjZXMgaW4tb3JkZXIuIFRodXMsIGxhc3Qgc291cmNlIHdpbGxcbiAqICAgICAgICAgb3ZlcnJpZGUgcHJvcGVydGllcyBpbiBwcmV2aW91cyBzb3VyY2VzLiBEZWZpbmUgdGhlIHByb3BlcnRpZXMgYXMgbm9uIGVudW1lcmFibGUuXG4gKlxuICogQHBhcmFtIHtvYmplY3R9IHRhcmdldCAtIFRoZSBPYmplY3QgdG8gZXh0ZW5kXG4gKiBAcGFyYW0ge29iamVjdFtdfSBzb3VyY2VzIC0gT2JqZWN0cyB0byBjb3B5IHByb3BlcnRpZXMgZnJvbS5cbiAqIEByZXR1cm5zIHtvYmplY3R9IHRoZSBleHRlbmRlZCB0YXJnZXRcbiAqL1xubW9kdWxlLmV4cG9ydHMubm9uRW51bSA9IGZ1bmN0aW9uIGV4dGVuZE5vbkVudW0odGFyZ2V0LCAuLi5zb3VyY2VzKSB7XG4gICAgcmV0dXJuIGV4dGVuZENvbW1vbihcbiAgICAgICAgdGFyZ2V0LFxuICAgICAgICBzb3VyY2VzLFxuICAgICAgICBmdW5jdGlvbiBjb3B5UHJvcGVydHkoZGVzdCwgc291cmNlLCBwcm9wKSB7XG4gICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZGVzdCwgcHJvcCwge1xuICAgICAgICAgICAgICAgIHZhbHVlOiBzb3VyY2VbcHJvcF0sXG4gICAgICAgICAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sXG4gICAgKTtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICBsZXQgaSwgcHJvcCwgdGhpc1ZhbHVlO1xuICAgIGlmICh0aGlzLmdldENhbGwgJiYgdGhpcy5jYWxsQ291bnQpIHtcbiAgICAgICAgaSA9IHRoaXMuY2FsbENvdW50O1xuXG4gICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgIHRoaXNWYWx1ZSA9IHRoaXMuZ2V0Q2FsbChpKS50aGlzVmFsdWU7XG5cbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBndWFyZC1mb3ItaW5cbiAgICAgICAgICAgIGZvciAocHJvcCBpbiB0aGlzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpc1ZhbHVlW3Byb3BdID09PSB0aGlzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJvcDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gbm8tb3AgLSBhY2Nlc3NpbmcgcHJvcHMgY2FuIHRocm93IGFuIGVycm9yLCBub3RoaW5nIHRvIGRvIGhlcmVcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5kaXNwbGF5TmFtZSB8fCBcInNpbm9uIGZha2VcIjtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgOiBub3QgdGVzdGluZyB0aGF0IHNldFRpbWVvdXQgd29ya3MgKi9cbmZ1bmN0aW9uIG5leHRUaWNrKGNhbGxiYWNrKSB7XG4gICAgc2V0VGltZW91dChjYWxsYmFjaywgMCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZ2V0TmV4dFRpY2socHJvY2Vzcywgc2V0SW1tZWRpYXRlKSB7XG4gICAgaWYgKHR5cGVvZiBwcm9jZXNzID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBwcm9jZXNzLm5leHRUaWNrID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3MubmV4dFRpY2s7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBzZXRJbW1lZGlhdGUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICByZXR1cm4gc2V0SW1tZWRpYXRlO1xuICAgIH1cblxuICAgIHJldHVybiBuZXh0VGljaztcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuLyoqXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBQcm9wZXJ0eURlc2NyaXB0b3JcbiAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvT2JqZWN0L2RlZmluZVByb3BlcnR5I2Rlc2NyaXB0aW9uXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IGNvbmZpZ3VyYWJsZSBkZWZhdWx0cyB0byBmYWxzZVxuICogQHByb3BlcnR5IHtib29sZWFufSBlbnVtZXJhYmxlICAgZGVmYXVsdHMgdG8gZmFsc2VcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gd3JpdGFibGUgICAgIGRlZmF1bHRzIHRvIGZhbHNlXG4gKiBAcHJvcGVydHkgeyp9IHZhbHVlIGRlZmF1bHRzIHRvIHVuZGVmaW5lZFxuICogQHByb3BlcnR5IHtGdW5jdGlvbn0gZ2V0IGRlZmF1bHRzIHRvIHVuZGVmaW5lZFxuICogQHByb3BlcnR5IHtGdW5jdGlvbn0gc2V0IGRlZmF1bHRzIHRvIHVuZGVmaW5lZFxuICovXG5cbi8qXG4gKiBUaGUgZm9sbG93aW5nIHR5cGUgZGVmIGlzIHN0cmljdGx5IHNwZWFraW5nIGlsbGVnYWwgaW4gSlNEb2MsIGJ1dCB0aGUgZXhwcmVzc2lvbiBmb3JtcyBhXG4gKiBsZWdhbCBUeXBlc2NyaXB0IHVuaW9uIHR5cGUgYW5kIGlzIHVuZGVyc3Rvb2QgYnkgVmlzdWFsIFN0dWRpbyBhbmQgdGhlIEludGVsbGlKXG4gKiBmYW1pbHkgb2YgZWRpdG9ycy4gVGhlIFwiVFNcIiBmbGF2b3Igb2YgSlNEb2MgaXMgYmVjb21pbmcgdGhlIGRlLWZhY3RvIHN0YW5kYXJkIHRoZXNlXG4gKiBkYXlzIGZvciB0aGF0IHJlYXNvbiAoYW5kIHRoZSBmYWN0IHRoYXQgSlNEb2MgaXMgZXNzZW50aWFsbHkgdW5tYWludGFpbmVkKVxuICovXG5cbi8qKlxuICogQHR5cGVkZWYge3tpc093bjogYm9vbGVhbn0gJiBQcm9wZXJ0eURlc2NyaXB0b3J9IFNpbm9uUHJvcGVydHlEZXNjcmlwdG9yXG4gKiBhIHNsaWdodGx5IGVucmljaGVkIHByb3BlcnR5IGRlc2NyaXB0b3JcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gaXNPd24gdHJ1ZSBpZiB0aGUgZGVzY3JpcHRvciBpcyBvd25lZCBieSB0aGlzIG9iamVjdCwgZmFsc2UgaWYgaXQgY29tZXMgZnJvbSB0aGUgcHJvdG90eXBlXG4gKi9cblxuLyoqXG4gKiBSZXR1cm5zIGEgc2xpZ2h0bHkgbW9kaWZpZWQgcHJvcGVydHkgZGVzY3JpcHRvciB0aGF0IG9uZSBjYW4gdGVsbCBpcyBmcm9tIHRoZSBvYmplY3Qgb3IgdGhlIHByb3RvdHlwZVxuICpcbiAqIEBwYXJhbSB7Kn0gb2JqZWN0XG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcGVydHlcbiAqIEByZXR1cm5zIHtTaW5vblByb3BlcnR5RGVzY3JpcHRvcn1cbiAqL1xuZnVuY3Rpb24gZ2V0UHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICBsZXQgcHJvdG8gPSBvYmplY3Q7XG4gICAgbGV0IGRlc2NyaXB0b3I7XG4gICAgY29uc3QgaXNPd24gPSBCb29sZWFuKFxuICAgICAgICBvYmplY3QgJiYgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KSxcbiAgICApO1xuXG4gICAgd2hpbGUgKFxuICAgICAgICBwcm90byAmJlxuICAgICAgICAhKGRlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHByb3RvLCBwcm9wZXJ0eSkpXG4gICAgKSB7XG4gICAgICAgIHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHByb3RvKTtcbiAgICB9XG5cbiAgICBpZiAoZGVzY3JpcHRvcikge1xuICAgICAgICBkZXNjcmlwdG9yLmlzT3duID0gaXNPd247XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlc2NyaXB0b3I7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0UHJvcGVydHlEZXNjcmlwdG9yO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbi8qKlxuICogVmVyaWZ5IGlmIGFuIG9iamVjdCBpcyBhIEVDTUFTY3JpcHQgTW9kdWxlXG4gKlxuICogQXMgdGhlIGV4cG9ydHMgZnJvbSBhIG1vZHVsZSBpcyBpbW11dGFibGUgd2UgY2Fubm90IGFsdGVyIHRoZSBleHBvcnRzXG4gKiB1c2luZyBzcGllcyBvciBzdHVicy4gTGV0IHRoZSBjb25zdW1lciBrbm93IHRoaXMgdG8gYXZvaWQgYnVnIHJlcG9ydHNcbiAqIG9uIHdlaXJkIGVycm9yIG1lc3NhZ2VzLlxuICpcbiAqIEBwYXJhbSB7b2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBleGFtaW5lXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSB3aGVuIHRoZSBvYmplY3QgaXMgYSBtb2R1bGVcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqZWN0KSB7XG4gICAgcmV0dXJuIChcbiAgICAgICAgb2JqZWN0ICYmXG4gICAgICAgIHR5cGVvZiBTeW1ib2wgIT09IFwidW5kZWZpbmVkXCIgJiZcbiAgICAgICAgb2JqZWN0W1N5bWJvbC50b1N0cmluZ1RhZ10gPT09IFwiTW9kdWxlXCIgJiZcbiAgICAgICAgT2JqZWN0LmlzU2VhbGVkKG9iamVjdClcbiAgICApO1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG4vKipcbiAqIEBwYXJhbSB7Kn0gb2JqZWN0XG4gKiBAcGFyYW0ge3N0cmluZ30gcHJvcGVydHlcbiAqIEByZXR1cm5zIHtib29sZWFufSB3aGV0aGVyIGEgcHJvcCBleGlzdHMgaW4gdGhlIHByb3RvdHlwZSBjaGFpblxuICovXG5mdW5jdGlvbiBpc05vbkV4aXN0ZW50UHJvcGVydHkob2JqZWN0LCBwcm9wZXJ0eSkge1xuICAgIHJldHVybiBCb29sZWFuKFxuICAgICAgICBvYmplY3QgJiYgdHlwZW9mIHByb3BlcnR5ICE9PSBcInVuZGVmaW5lZFwiICYmICEocHJvcGVydHkgaW4gb2JqZWN0KSxcbiAgICApO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlzTm9uRXhpc3RlbnRQcm9wZXJ0eTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5jb25zdCBnZXRQcm9wZXJ0eURlc2NyaXB0b3IgPSByZXF1aXJlKFwiLi9nZXQtcHJvcGVydHktZGVzY3JpcHRvclwiKTtcblxuZnVuY3Rpb24gaXNQcm9wZXJ0eUNvbmZpZ3VyYWJsZShvYmosIHByb3BOYW1lKSB7XG4gICAgY29uc3QgcHJvcGVydHlEZXNjcmlwdG9yID0gZ2V0UHJvcGVydHlEZXNjcmlwdG9yKG9iaiwgcHJvcE5hbWUpO1xuXG4gICAgcmV0dXJuIHByb3BlcnR5RGVzY3JpcHRvciA/IHByb3BlcnR5RGVzY3JpcHRvci5jb25maWd1cmFibGUgOiB0cnVlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlzUHJvcGVydHlDb25maWd1cmFibGU7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuZnVuY3Rpb24gaXNSZXN0b3JhYmxlKG9iaikge1xuICAgIHJldHVybiAoXG4gICAgICAgIHR5cGVvZiBvYmogPT09IFwiZnVuY3Rpb25cIiAmJlxuICAgICAgICB0eXBlb2Ygb2JqLnJlc3RvcmUgPT09IFwiZnVuY3Rpb25cIiAmJlxuICAgICAgICBvYmoucmVzdG9yZS5zaW5vblxuICAgICk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNSZXN0b3JhYmxlO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IGdsb2JhbE9iamVjdCA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLmdsb2JhbDtcbmNvbnN0IGdldE5leHRUaWNrID0gcmVxdWlyZShcIi4vZ2V0LW5leHQtdGlja1wiKTtcblxubW9kdWxlLmV4cG9ydHMgPSBnZXROZXh0VGljayhnbG9iYWxPYmplY3QucHJvY2VzcywgZ2xvYmFsT2JqZWN0LnNldEltbWVkaWF0ZSk7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuY29uc3Qgc2lub25UeXBlU3ltYm9sUHJvcGVydHkgPSBTeW1ib2woXCJTaW5vblR5cGVcIik7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIC8qKlxuICAgICAqIFNldCB0aGUgdHlwZSBvZiBhIFNpbm9uIG9iamVjdCB0byBtYWtlIGl0IHBvc3NpYmxlIHRvIGlkZW50aWZ5IGl0IGxhdGVyIGF0IHJ1bnRpbWVcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fEZ1bmN0aW9ufSBvYmplY3QgIG9iamVjdC9mdW5jdGlvbiB0byBzZXQgdGhlIHR5cGUgb25cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdHlwZSB0aGUgbmFtZWQgdHlwZSBvZiB0aGUgb2JqZWN0L2Z1bmN0aW9uXG4gICAgICovXG4gICAgc2V0KG9iamVjdCwgdHlwZSkge1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkob2JqZWN0LCBzaW5vblR5cGVTeW1ib2xQcm9wZXJ0eSwge1xuICAgICAgICAgICAgdmFsdWU6IHR5cGUsXG4gICAgICAgICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgICAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgZ2V0KG9iamVjdCkge1xuICAgICAgICByZXR1cm4gb2JqZWN0ICYmIG9iamVjdFtzaW5vblR5cGVTeW1ib2xQcm9wZXJ0eV07XG4gICAgfSxcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuY29uc3QgYXJyYXkgPSBbbnVsbCwgXCJvbmNlXCIsIFwidHdpY2VcIiwgXCJ0aHJpY2VcIl07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gdGltZXNJbldvcmRzKGNvdW50KSB7XG4gICAgcmV0dXJuIGFycmF5W2NvdW50XSB8fCBgJHtjb3VudCB8fCAwfSB0aW1lc2A7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IGZ1bmN0aW9uTmFtZSA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLmZ1bmN0aW9uTmFtZTtcblxuY29uc3QgZ2V0UHJvcGVydHlEZXNjcmlwdG9yID0gcmVxdWlyZShcIi4vZ2V0LXByb3BlcnR5LWRlc2NyaXB0b3JcIik7XG5jb25zdCB3YWxrID0gcmVxdWlyZShcIi4vd2Fsa1wiKTtcblxuLyoqXG4gKiBBIHV0aWxpdHkgdGhhdCBhbGxvd3MgdHJhdmVyc2luZyBhbiBvYmplY3QsIGFwcGx5aW5nIG11dGF0aW5nIGZ1bmN0aW9ucyBvbiB0aGUgcHJvcGVydGllc1xuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IG11dGF0b3IgY2FsbGVkIG9uIGVhY2ggcHJvcGVydHlcbiAqIEBwYXJhbSB7b2JqZWN0fSBvYmplY3QgdGhlIG9iamVjdCB3ZSBhcmUgd2Fsa2luZyBvdmVyXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmaWx0ZXIgYSBwcmVkaWNhdGUgKGJvb2xlYW4gZnVuY3Rpb24pIHRoYXQgd2lsbCBkZWNpZGUgd2hldGhlciBvciBub3QgdG8gYXBwbHkgdGhlIG11dGF0b3IgdG8gdGhlIGN1cnJlbnQgcHJvcGVydHlcbiAqIEByZXR1cm5zIHt2b2lkfSBub3RoaW5nXG4gKi9cbmZ1bmN0aW9uIHdhbGtPYmplY3QobXV0YXRvciwgb2JqZWN0LCBmaWx0ZXIpIHtcbiAgICBsZXQgY2FsbGVkID0gZmFsc2U7XG4gICAgY29uc3QgbmFtZSA9IGZ1bmN0aW9uTmFtZShtdXRhdG9yKTtcblxuICAgIGlmICghb2JqZWN0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBUcnlpbmcgdG8gJHtuYW1lfSBvYmplY3QgYnV0IHJlY2VpdmVkICR7U3RyaW5nKG9iamVjdCl9YCxcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICB3YWxrKG9iamVjdCwgZnVuY3Rpb24gKHByb3AsIHByb3BPd25lcikge1xuICAgICAgICAvLyB3ZSBkb24ndCB3YW50IHRvIHN0dWIgdGhpbmdzIGxpa2UgdG9TdHJpbmcoKSwgdmFsdWVPZigpLCBldGMuIHNvIHdlIG9ubHkgc3R1YiBpZiB0aGUgb2JqZWN0XG4gICAgICAgIC8vIGlzIG5vdCBPYmplY3QucHJvdG90eXBlXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIHByb3BPd25lciAhPT0gT2JqZWN0LnByb3RvdHlwZSAmJlxuICAgICAgICAgICAgcHJvcCAhPT0gXCJjb25zdHJ1Y3RvclwiICYmXG4gICAgICAgICAgICB0eXBlb2YgZ2V0UHJvcGVydHlEZXNjcmlwdG9yKHByb3BPd25lciwgcHJvcCkudmFsdWUgPT09IFwiZnVuY3Rpb25cIlxuICAgICAgICApIHtcbiAgICAgICAgICAgIGlmIChmaWx0ZXIpIHtcbiAgICAgICAgICAgICAgICBpZiAoZmlsdGVyKG9iamVjdCwgcHJvcCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgbXV0YXRvcihvYmplY3QsIHByb3ApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2FsbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBtdXRhdG9yKG9iamVjdCwgcHJvcCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmICghY2FsbGVkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgIGBGb3VuZCBubyBtZXRob2RzIG9uIG9iamVjdCB0byB3aGljaCB3ZSBjb3VsZCBhcHBseSBtdXRhdGlvbnNgLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBvYmplY3Q7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gd2Fsa09iamVjdDtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5jb25zdCBmb3JFYWNoID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikucHJvdG90eXBlcy5hcnJheS5mb3JFYWNoO1xuXG5mdW5jdGlvbiB3YWxrSW50ZXJuYWwob2JqLCBpdGVyYXRvciwgY29udGV4dCwgb3JpZ2luYWxPYmosIHNlZW4pIHtcbiAgICBsZXQgcHJvcDtcbiAgICBjb25zdCBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihvYmopO1xuXG4gICAgaWYgKHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyAhPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIC8vIFdlIGV4cGxpY2l0bHkgd2FudCB0byBlbnVtZXJhdGUgdGhyb3VnaCBhbGwgb2YgdGhlIHByb3RvdHlwZSdzIHByb3BlcnRpZXNcbiAgICAgICAgLy8gaW4gdGhpcyBjYXNlLCB0aGVyZWZvcmUgd2UgZGVsaWJlcmF0ZWx5IGxlYXZlIG91dCBhbiBvd24gcHJvcGVydHkgY2hlY2suXG4gICAgICAgIC8qIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBndWFyZC1mb3ItaW4gKi9cbiAgICAgICAgZm9yIChwcm9wIGluIG9iaikge1xuICAgICAgICAgICAgaXRlcmF0b3IuY2FsbChjb250ZXh0LCBvYmpbcHJvcF0sIHByb3AsIG9iaik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZm9yRWFjaChPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhvYmopLCBmdW5jdGlvbiAoaykge1xuICAgICAgICBpZiAoc2VlbltrXSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgc2VlbltrXSA9IHRydWU7XG4gICAgICAgICAgICBjb25zdCB0YXJnZXQgPVxuICAgICAgICAgICAgICAgIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG9iaiwgaykuZ2V0ID09PVxuICAgICAgICAgICAgICAgIFwiZnVuY3Rpb25cIlxuICAgICAgICAgICAgICAgICAgICA/IG9yaWdpbmFsT2JqXG4gICAgICAgICAgICAgICAgICAgIDogb2JqO1xuICAgICAgICAgICAgaXRlcmF0b3IuY2FsbChjb250ZXh0LCBrLCB0YXJnZXQpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAocHJvdG8pIHtcbiAgICAgICAgd2Fsa0ludGVybmFsKHByb3RvLCBpdGVyYXRvciwgY29udGV4dCwgb3JpZ2luYWxPYmosIHNlZW4pO1xuICAgIH1cbn1cblxuLyogV2Fsa3MgdGhlIHByb3RvdHlwZSBjaGFpbiBvZiBhbiBvYmplY3QgYW5kIGl0ZXJhdGVzIG92ZXIgZXZlcnkgb3duIHByb3BlcnR5XG4gKiBuYW1lIGVuY291bnRlcmVkLiBUaGUgaXRlcmF0b3IgaXMgY2FsbGVkIGluIHRoZSBzYW1lIGZhc2hpb24gdGhhdCBBcnJheS5wcm90b3R5cGUuZm9yRWFjaFxuICogd29ya3MsIHdoZXJlIGl0IGlzIHBhc3NlZCB0aGUgdmFsdWUsIGtleSwgYW5kIG93biBvYmplY3QgYXMgdGhlIDFzdCwgMm5kLCBhbmQgM3JkIHBvc2l0aW9uYWxcbiAqIGFyZ3VtZW50LCByZXNwZWN0aXZlbHkuIEluIGNhc2VzIHdoZXJlIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzIGlzIG5vdCBhdmFpbGFibGUsIHdhbGsgd2lsbFxuICogZGVmYXVsdCB0byB1c2luZyBhIHNpbXBsZSBmb3IuLmluIGxvb3AuXG4gKlxuICogb2JqIC0gVGhlIG9iamVjdCB0byB3YWxrIHRoZSBwcm90b3R5cGUgY2hhaW4gZm9yLlxuICogaXRlcmF0b3IgLSBUaGUgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIG9uIGVhY2ggcGFzcyBvZiB0aGUgd2Fsay5cbiAqIGNvbnRleHQgLSAoT3B0aW9uYWwpIFdoZW4gZ2l2ZW4sIHRoZSBpdGVyYXRvciB3aWxsIGJlIGNhbGxlZCB3aXRoIHRoaXMgb2JqZWN0IGFzIHRoZSByZWNlaXZlci5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB3YWxrKG9iaiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICByZXR1cm4gd2Fsa0ludGVybmFsKG9iaiwgaXRlcmF0b3IsIGNvbnRleHQsIG9iaiwge30pO1xufTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZW1wdHktZnVuY3Rpb25cbmNvbnN0IG5vb3AgPSAoKSA9PiB7fTtcbmNvbnN0IGdldFByb3BlcnR5RGVzY3JpcHRvciA9IHJlcXVpcmUoXCIuL2dldC1wcm9wZXJ0eS1kZXNjcmlwdG9yXCIpO1xuY29uc3QgZXh0ZW5kID0gcmVxdWlyZShcIi4vZXh0ZW5kXCIpO1xuY29uc3Qgc2lub25UeXBlID0gcmVxdWlyZShcIi4vc2lub24tdHlwZVwiKTtcbmNvbnN0IGhhc093blByb3BlcnR5ID1cbiAgICByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLm9iamVjdC5oYXNPd25Qcm9wZXJ0eTtcbmNvbnN0IHZhbHVlVG9TdHJpbmcgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS52YWx1ZVRvU3RyaW5nO1xuY29uc3QgcHVzaCA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnByb3RvdHlwZXMuYXJyYXkucHVzaDtcblxuZnVuY3Rpb24gaXNGdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gKFxuICAgICAgICB0eXBlb2Ygb2JqID09PSBcImZ1bmN0aW9uXCIgfHxcbiAgICAgICAgQm9vbGVhbihvYmogJiYgb2JqLmNvbnN0cnVjdG9yICYmIG9iai5jYWxsICYmIG9iai5hcHBseSlcbiAgICApO1xufVxuXG5mdW5jdGlvbiBtaXJyb3JQcm9wZXJ0aWVzKHRhcmdldCwgc291cmNlKSB7XG4gICAgZm9yIChjb25zdCBwcm9wIGluIHNvdXJjZSkge1xuICAgICAgICBpZiAoIWhhc093blByb3BlcnR5KHRhcmdldCwgcHJvcCkpIHtcbiAgICAgICAgICAgIHRhcmdldFtwcm9wXSA9IHNvdXJjZVtwcm9wXTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0QWNjZXNzb3Iob2JqZWN0LCBwcm9wZXJ0eSwgbWV0aG9kKSB7XG4gICAgY29uc3QgYWNjZXNzb3JzID0gW1wiZ2V0XCIsIFwic2V0XCJdO1xuICAgIGNvbnN0IGRlc2NyaXB0b3IgPSBnZXRQcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wZXJ0eSk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFjY2Vzc29ycy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICBkZXNjcmlwdG9yW2FjY2Vzc29yc1tpXV0gJiZcbiAgICAgICAgICAgIGRlc2NyaXB0b3JbYWNjZXNzb3JzW2ldXS5uYW1lID09PSBtZXRob2QubmFtZVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiBhY2Nlc3NvcnNbaV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbi8vIENoZWFwIHdheSB0byBkZXRlY3QgaWYgd2UgaGF2ZSBFUzUgc3VwcG9ydC5cbmNvbnN0IGhhc0VTNVN1cHBvcnQgPSBcImtleXNcIiBpbiBPYmplY3Q7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gd3JhcE1ldGhvZChvYmplY3QsIHByb3BlcnR5LCBtZXRob2QpIHtcbiAgICBpZiAoIW9iamVjdCkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU2hvdWxkIHdyYXAgcHJvcGVydHkgb2Ygb2JqZWN0XCIpO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgbWV0aG9kICE9PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIG1ldGhvZCAhPT0gXCJvYmplY3RcIikge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgXCJNZXRob2Qgd3JhcHBlciBzaG91bGQgYmUgYSBmdW5jdGlvbiBvciBhIHByb3BlcnR5IGRlc2NyaXB0b3JcIixcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjaGVja1dyYXBwZWRNZXRob2Qod3JhcHBlZE1ldGhvZCkge1xuICAgICAgICBsZXQgZXJyb3I7XG5cbiAgICAgICAgaWYgKCFpc0Z1bmN0aW9uKHdyYXBwZWRNZXRob2QpKSB7XG4gICAgICAgICAgICBlcnJvciA9IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICAgICAgYEF0dGVtcHRlZCB0byB3cmFwICR7dHlwZW9mIHdyYXBwZWRNZXRob2R9IHByb3BlcnR5ICR7dmFsdWVUb1N0cmluZyhcbiAgICAgICAgICAgICAgICAgICAgcHJvcGVydHksXG4gICAgICAgICAgICAgICAgKX0gYXMgZnVuY3Rpb25gLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIGlmICh3cmFwcGVkTWV0aG9kLnJlc3RvcmUgJiYgd3JhcHBlZE1ldGhvZC5yZXN0b3JlLnNpbm9uKSB7XG4gICAgICAgICAgICBlcnJvciA9IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICAgICAgYEF0dGVtcHRlZCB0byB3cmFwICR7dmFsdWVUb1N0cmluZyhcbiAgICAgICAgICAgICAgICAgICAgcHJvcGVydHksXG4gICAgICAgICAgICAgICAgKX0gd2hpY2ggaXMgYWxyZWFkeSB3cmFwcGVkYCxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAod3JhcHBlZE1ldGhvZC5jYWxsZWRCZWZvcmUpIHtcbiAgICAgICAgICAgIGNvbnN0IHZlcmIgPSB3cmFwcGVkTWV0aG9kLnJldHVybnMgPyBcInN0dWJiZWRcIiA6IFwic3BpZWQgb25cIjtcbiAgICAgICAgICAgIGVycm9yID0gbmV3IFR5cGVFcnJvcihcbiAgICAgICAgICAgICAgICBgQXR0ZW1wdGVkIHRvIHdyYXAgJHt2YWx1ZVRvU3RyaW5nKFxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eSxcbiAgICAgICAgICAgICAgICApfSB3aGljaCBpcyBhbHJlYWR5ICR7dmVyYn1gLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgaWYgKHdyYXBwZWRNZXRob2QgJiYgd3JhcHBlZE1ldGhvZC5zdGFja1RyYWNlRXJyb3IpIHtcbiAgICAgICAgICAgICAgICBlcnJvci5zdGFjayArPSBgXFxuLS0tLS0tLS0tLS0tLS1cXG4ke3dyYXBwZWRNZXRob2Quc3RhY2tUcmFjZUVycm9yLnN0YWNrfWA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGxldCBlcnJvciwgd3JhcHBlZE1ldGhvZCwgaSwgd3JhcHBlZE1ldGhvZERlc2MsIHRhcmdldCwgYWNjZXNzb3I7XG5cbiAgICBjb25zdCB3cmFwcGVkTWV0aG9kcyA9IFtdO1xuXG4gICAgZnVuY3Rpb24gc2ltcGxlUHJvcGVydHlBc3NpZ25tZW50KCkge1xuICAgICAgICB3cmFwcGVkTWV0aG9kID0gb2JqZWN0W3Byb3BlcnR5XTtcbiAgICAgICAgY2hlY2tXcmFwcGVkTWV0aG9kKHdyYXBwZWRNZXRob2QpO1xuICAgICAgICBvYmplY3RbcHJvcGVydHldID0gbWV0aG9kO1xuICAgICAgICBtZXRob2QuZGlzcGxheU5hbWUgPSBwcm9wZXJ0eTtcbiAgICB9XG5cbiAgICAvLyBGaXJlZm94IGhhcyBhIHByb2JsZW0gd2hlbiB1c2luZyBoYXNPd24uY2FsbCBvbiBvYmplY3RzIGZyb20gb3RoZXIgZnJhbWVzLlxuICAgIGNvbnN0IG93bmVkID0gb2JqZWN0Lmhhc093blByb3BlcnR5XG4gICAgICAgID8gb2JqZWN0Lmhhc093blByb3BlcnR5KHByb3BlcnR5KSAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIEBzaW5vbmpzL25vLXByb3RvdHlwZS1tZXRob2RzL25vLXByb3RvdHlwZS1tZXRob2RzXG4gICAgICAgIDogaGFzT3duUHJvcGVydHkob2JqZWN0LCBwcm9wZXJ0eSk7XG5cbiAgICBpZiAoaGFzRVM1U3VwcG9ydCkge1xuICAgICAgICBjb25zdCBtZXRob2REZXNjID1cbiAgICAgICAgICAgIHR5cGVvZiBtZXRob2QgPT09IFwiZnVuY3Rpb25cIiA/IHsgdmFsdWU6IG1ldGhvZCB9IDogbWV0aG9kO1xuICAgICAgICB3cmFwcGVkTWV0aG9kRGVzYyA9IGdldFByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KTtcblxuICAgICAgICBpZiAoIXdyYXBwZWRNZXRob2REZXNjKSB7XG4gICAgICAgICAgICBlcnJvciA9IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICAgICAgYEF0dGVtcHRlZCB0byB3cmFwICR7dHlwZW9mIHdyYXBwZWRNZXRob2R9IHByb3BlcnR5ICR7cHJvcGVydHl9IGFzIGZ1bmN0aW9uYCxcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICB3cmFwcGVkTWV0aG9kRGVzYy5yZXN0b3JlICYmXG4gICAgICAgICAgICB3cmFwcGVkTWV0aG9kRGVzYy5yZXN0b3JlLnNpbm9uXG4gICAgICAgICkge1xuICAgICAgICAgICAgZXJyb3IgPSBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgICAgIGBBdHRlbXB0ZWQgdG8gd3JhcCAke3Byb3BlcnR5fSB3aGljaCBpcyBhbHJlYWR5IHdyYXBwZWRgLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIGlmICh3cmFwcGVkTWV0aG9kRGVzYyAmJiB3cmFwcGVkTWV0aG9kRGVzYy5zdGFja1RyYWNlRXJyb3IpIHtcbiAgICAgICAgICAgICAgICBlcnJvci5zdGFjayArPSBgXFxuLS0tLS0tLS0tLS0tLS1cXG4ke3dyYXBwZWRNZXRob2REZXNjLnN0YWNrVHJhY2VFcnJvci5zdGFja31gO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB0eXBlcyA9IE9iamVjdC5rZXlzKG1ldGhvZERlc2MpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdHlwZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHdyYXBwZWRNZXRob2QgPSB3cmFwcGVkTWV0aG9kRGVzY1t0eXBlc1tpXV07XG4gICAgICAgICAgICBjaGVja1dyYXBwZWRNZXRob2Qod3JhcHBlZE1ldGhvZCk7XG4gICAgICAgICAgICBwdXNoKHdyYXBwZWRNZXRob2RzLCB3cmFwcGVkTWV0aG9kKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG1pcnJvclByb3BlcnRpZXMobWV0aG9kRGVzYywgd3JhcHBlZE1ldGhvZERlc2MpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdHlwZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIG1pcnJvclByb3BlcnRpZXMobWV0aG9kRGVzY1t0eXBlc1tpXV0sIHdyYXBwZWRNZXRob2REZXNjW3R5cGVzW2ldXSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB5b3UgYXJlIG5vdCBhbGxvd2VkIHRvIGZsaXAgdGhlIGNvbmZpZ3VyYWJsZSBwcm9wIG9uIGFuXG4gICAgICAgIC8vIGV4aXN0aW5nIGRlc2NyaXB0b3IgdG8gYW55dGhpbmcgYnV0IGZhbHNlICgjMjUxNClcbiAgICAgICAgaWYgKCFvd25lZCkge1xuICAgICAgICAgICAgbWV0aG9kRGVzYy5jb25maWd1cmFibGUgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iamVjdCwgcHJvcGVydHksIG1ldGhvZERlc2MpO1xuXG4gICAgICAgIC8vIGNhdGNoIGZhaWxpbmcgYXNzaWdubWVudFxuICAgICAgICAvLyB0aGlzIGlzIHRoZSBjb252ZXJzZSBvZiB0aGUgY2hlY2sgaW4gYC5yZXN0b3JlYCBiZWxvd1xuICAgICAgICBpZiAodHlwZW9mIG1ldGhvZCA9PT0gXCJmdW5jdGlvblwiICYmIG9iamVjdFtwcm9wZXJ0eV0gIT09IG1ldGhvZCkge1xuICAgICAgICAgICAgLy8gY29ycmVjdCBhbnkgd3Jvbmdkb2luZ3MgY2F1c2VkIGJ5IHRoZSBkZWZpbmVQcm9wZXJ0eSBjYWxsIGFib3ZlLFxuICAgICAgICAgICAgLy8gc3VjaCBhcyBhZGRpbmcgbmV3IGl0ZW1zIChpZiBvYmplY3Qgd2FzIGEgU3RvcmFnZSBvYmplY3QpXG4gICAgICAgICAgICBkZWxldGUgb2JqZWN0W3Byb3BlcnR5XTtcbiAgICAgICAgICAgIHNpbXBsZVByb3BlcnR5QXNzaWdubWVudCgpO1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc2ltcGxlUHJvcGVydHlBc3NpZ25tZW50KCk7XG4gICAgfVxuXG4gICAgZXh0ZW5kT2JqZWN0V2l0aFdyYXBwZWRNZXRob2RzKCk7XG5cbiAgICBmdW5jdGlvbiBleHRlbmRPYmplY3RXaXRoV3JhcHBlZE1ldGhvZHMoKSB7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB3cmFwcGVkTWV0aG9kcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYWNjZXNzb3IgPSBnZXRBY2Nlc3NvcihvYmplY3QsIHByb3BlcnR5LCB3cmFwcGVkTWV0aG9kc1tpXSk7XG4gICAgICAgICAgICB0YXJnZXQgPSBhY2Nlc3NvciA/IG1ldGhvZFthY2Nlc3Nvcl0gOiBtZXRob2Q7XG4gICAgICAgICAgICBleHRlbmQubm9uRW51bSh0YXJnZXQsIHtcbiAgICAgICAgICAgICAgICBkaXNwbGF5TmFtZTogcHJvcGVydHksXG4gICAgICAgICAgICAgICAgd3JhcHBlZE1ldGhvZDogd3JhcHBlZE1ldGhvZHNbaV0sXG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgdXAgYW4gRXJyb3Igb2JqZWN0IGZvciBhIHN0YWNrIHRyYWNlIHdoaWNoIGNhbiBiZSB1c2VkIGxhdGVyIHRvIGZpbmQgd2hhdCBsaW5lIG9mXG4gICAgICAgICAgICAgICAgLy8gY29kZSB0aGUgb3JpZ2luYWwgbWV0aG9kIHdhcyBjcmVhdGVkIG9uLlxuICAgICAgICAgICAgICAgIHN0YWNrVHJhY2VFcnJvcjogbmV3IEVycm9yKFwiU3RhY2sgVHJhY2UgZm9yIG9yaWdpbmFsXCIpLFxuXG4gICAgICAgICAgICAgICAgcmVzdG9yZTogcmVzdG9yZSxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0YXJnZXQucmVzdG9yZS5zaW5vbiA9IHRydWU7XG4gICAgICAgICAgICBpZiAoIWhhc0VTNVN1cHBvcnQpIHtcbiAgICAgICAgICAgICAgICBtaXJyb3JQcm9wZXJ0aWVzKHRhcmdldCwgd3JhcHBlZE1ldGhvZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXN0b3JlKCkge1xuICAgICAgICBhY2Nlc3NvciA9IGdldEFjY2Vzc29yKG9iamVjdCwgcHJvcGVydHksIHRoaXMud3JhcHBlZE1ldGhvZCk7XG4gICAgICAgIGxldCBkZXNjcmlwdG9yO1xuICAgICAgICAvLyBGb3IgcHJvdG90eXBlIHByb3BlcnRpZXMgdHJ5IHRvIHJlc2V0IGJ5IGRlbGV0ZSBmaXJzdC5cbiAgICAgICAgLy8gSWYgdGhpcyBmYWlscyAoZXg6IGxvY2FsU3RvcmFnZSBvbiBtb2JpbGUgc2FmYXJpKSB0aGVuIGZvcmNlIGEgcmVzZXRcbiAgICAgICAgLy8gdmlhIGRpcmVjdCBhc3NpZ25tZW50LlxuICAgICAgICBpZiAoYWNjZXNzb3IpIHtcbiAgICAgICAgICAgIGlmICghb3duZWQpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJbiBzb21lIGNhc2VzIGBkZWxldGVgIG1heSB0aHJvdyBhbiBlcnJvclxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgb2JqZWN0W3Byb3BlcnR5XVthY2Nlc3Nvcl07XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge30gLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1lbXB0eVxuICAgICAgICAgICAgICAgIC8vIEZvciBuYXRpdmUgY29kZSBmdW5jdGlvbnMgYGRlbGV0ZWAgZmFpbHMgd2l0aG91dCB0aHJvd2luZyBhbiBlcnJvclxuICAgICAgICAgICAgICAgIC8vIG9uIENocm9tZSA8IDQzLCBQaGFudG9tSlMsIGV0Yy5cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaGFzRVM1U3VwcG9ydCkge1xuICAgICAgICAgICAgICAgIGRlc2NyaXB0b3IgPSBnZXRQcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wZXJ0eSk7XG4gICAgICAgICAgICAgICAgZGVzY3JpcHRvclthY2Nlc3Nvcl0gPSB3cmFwcGVkTWV0aG9kRGVzY1thY2Nlc3Nvcl07XG4gICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iamVjdCwgcHJvcGVydHksIGRlc2NyaXB0b3IpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaGFzRVM1U3VwcG9ydCkge1xuICAgICAgICAgICAgICAgIGRlc2NyaXB0b3IgPSBnZXRQcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wZXJ0eSk7XG4gICAgICAgICAgICAgICAgaWYgKGRlc2NyaXB0b3IgJiYgZGVzY3JpcHRvci52YWx1ZSA9PT0gdGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIG9iamVjdFtwcm9wZXJ0eV1bYWNjZXNzb3JdID0gdGhpcy53cmFwcGVkTWV0aG9kO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gVXNlIHN0cmljdCBlcXVhbGl0eSBjb21wYXJpc29uIHRvIGNoZWNrIGZhaWx1cmVzIHRoZW4gZm9yY2UgYSByZXNldFxuICAgICAgICAgICAgICAgIC8vIHZpYSBkaXJlY3QgYXNzaWdubWVudC5cbiAgICAgICAgICAgICAgICBpZiAob2JqZWN0W3Byb3BlcnR5XVthY2Nlc3Nvcl0gPT09IHRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICBvYmplY3RbcHJvcGVydHldW2FjY2Vzc29yXSA9IHRoaXMud3JhcHBlZE1ldGhvZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoIW93bmVkKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIG9iamVjdFtwcm9wZXJ0eV07XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge30gLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1lbXB0eVxuICAgICAgICAgICAgfSBlbHNlIGlmIChoYXNFUzVTdXBwb3J0KSB7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iamVjdCwgcHJvcGVydHksIHdyYXBwZWRNZXRob2REZXNjKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGhhc0VTNVN1cHBvcnQpIHtcbiAgICAgICAgICAgICAgICBkZXNjcmlwdG9yID0gZ2V0UHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpO1xuICAgICAgICAgICAgICAgIGlmIChkZXNjcmlwdG9yICYmIGRlc2NyaXB0b3IudmFsdWUgPT09IHRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICBvYmplY3RbcHJvcGVydHldID0gdGhpcy53cmFwcGVkTWV0aG9kO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKG9iamVjdFtwcm9wZXJ0eV0gPT09IHRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICBvYmplY3RbcHJvcGVydHldID0gdGhpcy53cmFwcGVkTWV0aG9kO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoc2lub25UeXBlLmdldChvYmplY3QpID09PSBcInN0dWItaW5zdGFuY2VcIikge1xuICAgICAgICAgICAgLy8gdGhpcyBpcyBzaW1wbHkgdG8gYXZvaWQgZXJyb3JzIGFmdGVyIHJlc3RvcmluZyBpZiBzb21ldGhpbmcgc2hvdWxkXG4gICAgICAgICAgICAvLyB0cmF2ZXJzZSB0aGUgb2JqZWN0IGluIGEgY2xlYW51cCBwaGFzZSwgcmVmICMyNDc3XG4gICAgICAgICAgICBvYmplY3RbcHJvcGVydHldID0gbm9vcDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBtZXRob2Q7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNvbnN0IGV4dGVuZCA9IHJlcXVpcmUoXCIuL2NvcmUvZXh0ZW5kXCIpO1xuY29uc3QgRmFrZVRpbWVycyA9IHJlcXVpcmUoXCJAc2lub25qcy9mYWtlLXRpbWVyc1wiKTtcbmNvbnN0IGdsb2JhbE9iamVjdCA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLmdsb2JhbDtcblxuLyoqXG4gKlxuICogQHBhcmFtIGNvbmZpZ1xuICogQHBhcmFtIGdsb2JhbEN0eFxuICpcbiAqIEByZXR1cm5zIHtvYmplY3R9IHRoZSBjbG9jaywgYWZ0ZXIgaW5zdGFsbGluZyBpdCBvbiB0aGUgZ2xvYmFsIGNvbnRleHQsIGlmIGdpdmVuXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUNsb2NrKGNvbmZpZywgZ2xvYmFsQ3R4KSB7XG4gICAgbGV0IEZha2VUaW1lcnNDdHggPSBGYWtlVGltZXJzO1xuICAgIGlmIChnbG9iYWxDdHggIT09IG51bGwgJiYgdHlwZW9mIGdsb2JhbEN0eCA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICBGYWtlVGltZXJzQ3R4ID0gRmFrZVRpbWVycy53aXRoR2xvYmFsKGdsb2JhbEN0eCk7XG4gICAgfVxuICAgIGNvbnN0IGNsb2NrID0gRmFrZVRpbWVyc0N0eC5pbnN0YWxsKGNvbmZpZyk7XG4gICAgY2xvY2sucmVzdG9yZSA9IGNsb2NrLnVuaW5zdGFsbDtcbiAgICByZXR1cm4gY2xvY2s7XG59XG5cbi8qKlxuICpcbiAqIEBwYXJhbSBvYmpcbiAqIEBwYXJhbSBnbG9iYWxQcm9wTmFtZVxuICovXG5mdW5jdGlvbiBhZGRJZkRlZmluZWQob2JqLCBnbG9iYWxQcm9wTmFtZSkge1xuICAgIGNvbnN0IGdsb2JhbFByb3AgPSBnbG9iYWxPYmplY3RbZ2xvYmFsUHJvcE5hbWVdO1xuICAgIGlmICh0eXBlb2YgZ2xvYmFsUHJvcCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICBvYmpbZ2xvYmFsUHJvcE5hbWVdID0gZ2xvYmFsUHJvcDtcbiAgICB9XG59XG5cbi8qKlxuICogQHBhcmFtIHtudW1iZXJ8RGF0ZXxvYmplY3R9IGRhdGVPckNvbmZpZyBUaGUgdW5peCBlcG9jaCB2YWx1ZSB0byBpbnN0YWxsIHdpdGggKGRlZmF1bHQgMClcbiAqIEByZXR1cm5zIHtvYmplY3R9IFJldHVybnMgYSBsb2xleCBjbG9jayBpbnN0YW5jZVxuICovXG5leHBvcnRzLnVzZUZha2VUaW1lcnMgPSBmdW5jdGlvbiAoZGF0ZU9yQ29uZmlnKSB7XG4gICAgY29uc3QgaGFzQXJndW1lbnRzID0gdHlwZW9mIGRhdGVPckNvbmZpZyAhPT0gXCJ1bmRlZmluZWRcIjtcbiAgICBjb25zdCBhcmd1bWVudElzRGF0ZUxpa2UgPVxuICAgICAgICAodHlwZW9mIGRhdGVPckNvbmZpZyA9PT0gXCJudW1iZXJcIiB8fCBkYXRlT3JDb25maWcgaW5zdGFuY2VvZiBEYXRlKSAmJlxuICAgICAgICBhcmd1bWVudHMubGVuZ3RoID09PSAxO1xuICAgIGNvbnN0IGFyZ3VtZW50SXNPYmplY3QgPVxuICAgICAgICBkYXRlT3JDb25maWcgIT09IG51bGwgJiZcbiAgICAgICAgdHlwZW9mIGRhdGVPckNvbmZpZyA9PT0gXCJvYmplY3RcIiAmJlxuICAgICAgICBhcmd1bWVudHMubGVuZ3RoID09PSAxO1xuXG4gICAgaWYgKCFoYXNBcmd1bWVudHMpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUNsb2NrKHtcbiAgICAgICAgICAgIG5vdzogMCxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgaWYgKGFyZ3VtZW50SXNEYXRlTGlrZSkge1xuICAgICAgICByZXR1cm4gY3JlYXRlQ2xvY2soe1xuICAgICAgICAgICAgbm93OiBkYXRlT3JDb25maWcsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmIChhcmd1bWVudElzT2JqZWN0KSB7XG4gICAgICAgIGNvbnN0IGNvbmZpZyA9IGV4dGVuZC5ub25FbnVtKHt9LCBkYXRlT3JDb25maWcpO1xuICAgICAgICBjb25zdCBnbG9iYWxDdHggPSBjb25maWcuZ2xvYmFsO1xuICAgICAgICBkZWxldGUgY29uZmlnLmdsb2JhbDtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUNsb2NrKGNvbmZpZywgZ2xvYmFsQ3R4KTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICBcInVzZUZha2VUaW1lcnMgZXhwZWN0ZWQgZXBvY2ggb3IgY29uZmlnIG9iamVjdC4gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9zaW5vbmpzL3Npbm9uXCIsXG4gICAgKTtcbn07XG5cbmV4cG9ydHMuY2xvY2sgPSB7XG4gICAgY3JlYXRlOiBmdW5jdGlvbiAobm93KSB7XG4gICAgICAgIHJldHVybiBGYWtlVGltZXJzLmNyZWF0ZUNsb2NrKG5vdyk7XG4gICAgfSxcbn07XG5cbmNvbnN0IHRpbWVycyA9IHtcbiAgICBzZXRUaW1lb3V0OiBzZXRUaW1lb3V0LFxuICAgIGNsZWFyVGltZW91dDogY2xlYXJUaW1lb3V0LFxuICAgIHNldEludGVydmFsOiBzZXRJbnRlcnZhbCxcbiAgICBjbGVhckludGVydmFsOiBjbGVhckludGVydmFsLFxuICAgIERhdGU6IERhdGUsXG59O1xuYWRkSWZEZWZpbmVkKHRpbWVycywgXCJzZXRJbW1lZGlhdGVcIik7XG5hZGRJZkRlZmluZWQodGltZXJzLCBcImNsZWFySW1tZWRpYXRlXCIpO1xuXG5leHBvcnRzLnRpbWVycyA9IHRpbWVycztcbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgZXZlcnkgPSByZXF1aXJlKFwiLi9wcm90b3R5cGVzL2FycmF5XCIpLmV2ZXJ5O1xuXG4vKipcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGhhc0NhbGxzTGVmdChjYWxsTWFwLCBzcHkpIHtcbiAgICBpZiAoY2FsbE1hcFtzcHkuaWRdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY2FsbE1hcFtzcHkuaWRdID0gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gY2FsbE1hcFtzcHkuaWRdIDwgc3B5LmNhbGxDb3VudDtcbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBjaGVja0FkamFjZW50Q2FsbHMoY2FsbE1hcCwgc3B5LCBpbmRleCwgc3BpZXMpIHtcbiAgICB2YXIgY2FsbGVkQmVmb3JlTmV4dCA9IHRydWU7XG5cbiAgICBpZiAoaW5kZXggIT09IHNwaWVzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgY2FsbGVkQmVmb3JlTmV4dCA9IHNweS5jYWxsZWRCZWZvcmUoc3BpZXNbaW5kZXggKyAxXSk7XG4gICAgfVxuXG4gICAgaWYgKGhhc0NhbGxzTGVmdChjYWxsTWFwLCBzcHkpICYmIGNhbGxlZEJlZm9yZU5leHQpIHtcbiAgICAgICAgY2FsbE1hcFtzcHkuaWRdICs9IDE7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBBIFNpbm9uIHByb3h5IG9iamVjdCAoZmFrZSwgc3B5LCBzdHViKVxuICogQHR5cGVkZWYge29iamVjdH0gU2lub25Qcm94eVxuICogQHByb3BlcnR5IHtGdW5jdGlvbn0gY2FsbGVkQmVmb3JlIC0gQSBtZXRob2QgdGhhdCBkZXRlcm1pbmVzIGlmIHRoaXMgcHJveHkgd2FzIGNhbGxlZCBiZWZvcmUgYW5vdGhlciBvbmVcbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBpZCAtIFNvbWUgaWRcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBjYWxsQ291bnQgLSBOdW1iZXIgb2YgdGltZXMgdGhpcyBwcm94eSBoYXMgYmVlbiBjYWxsZWRcbiAqL1xuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSB3aGVuIHRoZSBzcGllcyBoYXZlIGJlZW4gY2FsbGVkIGluIHRoZSBvcmRlciB0aGV5IHdlcmUgc3VwcGxpZWQgaW5cbiAqIEBwYXJhbSAge1Npbm9uUHJveHlbXSB8IFNpbm9uUHJveHl9IHNwaWVzIEFuIGFycmF5IG9mIHByb3hpZXMsIG9yIHNldmVyYWwgcHJveGllcyBhcyBhcmd1bWVudHNcbiAqIEByZXR1cm5zIHtib29sZWFufSB0cnVlIHdoZW4gc3BpZXMgYXJlIGNhbGxlZCBpbiBvcmRlciwgZmFsc2Ugb3RoZXJ3aXNlXG4gKi9cbmZ1bmN0aW9uIGNhbGxlZEluT3JkZXIoc3BpZXMpIHtcbiAgICB2YXIgY2FsbE1hcCA9IHt9O1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bmRlcnNjb3JlLWRhbmdsZVxuICAgIHZhciBfc3BpZXMgPSBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50cyA6IHNwaWVzO1xuXG4gICAgcmV0dXJuIGV2ZXJ5KF9zcGllcywgY2hlY2tBZGphY2VudENhbGxzLmJpbmQobnVsbCwgY2FsbE1hcCkpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNhbGxlZEluT3JkZXI7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuLyoqXG4gKiBSZXR1cm5zIGEgZGlzcGxheSBuYW1lIGZvciBhIHZhbHVlIGZyb20gYSBjb25zdHJ1Y3RvclxuICogQHBhcmFtICB7b2JqZWN0fSB2YWx1ZSBBIHZhbHVlIHRvIGV4YW1pbmVcbiAqIEByZXR1cm5zIHsoc3RyaW5nfG51bGwpfSBBIHN0cmluZyBvciBudWxsXG4gKi9cbmZ1bmN0aW9uIGNsYXNzTmFtZSh2YWx1ZSkge1xuICAgIGNvbnN0IG5hbWUgPSB2YWx1ZS5jb25zdHJ1Y3RvciAmJiB2YWx1ZS5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgIHJldHVybiBuYW1lIHx8IG51bGw7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY2xhc3NOYW1lO1xuIiwiLyogZXNsaW50LWRpc2FibGUgbm8tY29uc29sZSAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbi8qKlxuICogUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBpbnZva2UgdGhlIHN1cHBsaWVkIGZ1bmN0aW9uIGFuZCBwcmludCBhXG4gKiBkZXByZWNhdGlvbiB3YXJuaW5nIHRvIHRoZSBjb25zb2xlIGVhY2ggdGltZSBpdCBpcyBjYWxsZWQuXG4gKiBAcGFyYW0gIHtGdW5jdGlvbn0gZnVuY1xuICogQHBhcmFtICB7c3RyaW5nfSBtc2dcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn1cbiAqL1xuZXhwb3J0cy53cmFwID0gZnVuY3Rpb24gKGZ1bmMsIG1zZykge1xuICAgIHZhciB3cmFwcGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBleHBvcnRzLnByaW50V2FybmluZyhtc2cpO1xuICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG4gICAgaWYgKGZ1bmMucHJvdG90eXBlKSB7XG4gICAgICAgIHdyYXBwZWQucHJvdG90eXBlID0gZnVuYy5wcm90b3R5cGU7XG4gICAgfVxuICAgIHJldHVybiB3cmFwcGVkO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIGEgc3RyaW5nIHdoaWNoIGNhbiBiZSBzdXBwbGllZCB0byBgd3JhcCgpYCB0byBub3RpZnkgdGhlIHVzZXIgdGhhdCBhXG4gKiBwYXJ0aWN1bGFyIHBhcnQgb2YgdGhlIHNpbm9uIEFQSSBoYXMgYmVlbiBkZXByZWNhdGVkLlxuICogQHBhcmFtICB7c3RyaW5nfSBwYWNrYWdlTmFtZVxuICogQHBhcmFtICB7c3RyaW5nfSBmdW5jTmFtZVxuICogQHJldHVybnMge3N0cmluZ31cbiAqL1xuZXhwb3J0cy5kZWZhdWx0TXNnID0gZnVuY3Rpb24gKHBhY2thZ2VOYW1lLCBmdW5jTmFtZSkge1xuICAgIHJldHVybiBgJHtwYWNrYWdlTmFtZX0uJHtmdW5jTmFtZX0gaXMgZGVwcmVjYXRlZCBhbmQgd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIHB1YmxpYyBBUEkgaW4gYSBmdXR1cmUgdmVyc2lvbiBvZiAke3BhY2thZ2VOYW1lfS5gO1xufTtcblxuLyoqXG4gKiBQcmludHMgYSB3YXJuaW5nIG9uIHRoZSBjb25zb2xlLCB3aGVuIGl0IGV4aXN0c1xuICogQHBhcmFtICB7c3RyaW5nfSBtc2dcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gKi9cbmV4cG9ydHMucHJpbnRXYXJuaW5nID0gZnVuY3Rpb24gKG1zZykge1xuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgaWYgKHR5cGVvZiBwcm9jZXNzID09PSBcIm9iamVjdFwiICYmIHByb2Nlc3MuZW1pdFdhcm5pbmcpIHtcbiAgICAgICAgLy8gRW1pdCBXYXJuaW5ncyBpbiBOb2RlXG4gICAgICAgIHByb2Nlc3MuZW1pdFdhcm5pbmcobXNnKTtcbiAgICB9IGVsc2UgaWYgKGNvbnNvbGUuaW5mbykge1xuICAgICAgICBjb25zb2xlLmluZm8obXNnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLmxvZyhtc2cpO1xuICAgIH1cbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgd2hlbiBmbiByZXR1cm5zIHRydWUgZm9yIGFsbCBtZW1iZXJzIG9mIG9iai5cbiAqIFRoaXMgaXMgYW4gZXZlcnkgaW1wbGVtZW50YXRpb24gdGhhdCB3b3JrcyBmb3IgYWxsIGl0ZXJhYmxlc1xuICogQHBhcmFtICB7b2JqZWN0fSAgIG9ialxuICogQHBhcmFtICB7RnVuY3Rpb259IGZuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBldmVyeShvYmosIGZuKSB7XG4gICAgdmFyIHBhc3MgPSB0cnVlO1xuXG4gICAgdHJ5IHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBzaW5vbmpzL25vLXByb3RvdHlwZS1tZXRob2RzL25vLXByb3RvdHlwZS1tZXRob2RzXG4gICAgICAgIG9iai5mb3JFYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICghZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKSkge1xuICAgICAgICAgICAgICAgIC8vIFRocm93aW5nIGFuIGVycm9yIGlzIHRoZSBvbmx5IHdheSB0byBicmVhayBgZm9yRWFjaGBcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBwYXNzID0gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhc3M7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbi8qKlxuICogUmV0dXJucyBhIGRpc3BsYXkgbmFtZSBmb3IgYSBmdW5jdGlvblxuICogQHBhcmFtICB7RnVuY3Rpb259IGZ1bmNcbiAqIEByZXR1cm5zIHtzdHJpbmd9XG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZnVuY3Rpb25OYW1lKGZ1bmMpIHtcbiAgICBpZiAoIWZ1bmMpIHtcbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGZ1bmMuZGlzcGxheU5hbWUgfHxcbiAgICAgICAgICAgIGZ1bmMubmFtZSB8fFxuICAgICAgICAgICAgLy8gVXNlIGZ1bmN0aW9uIGRlY29tcG9zaXRpb24gYXMgYSBsYXN0IHJlc29ydCB0byBnZXQgZnVuY3Rpb25cbiAgICAgICAgICAgIC8vIG5hbWUuIERvZXMgbm90IHJlbHkgb24gZnVuY3Rpb24gZGVjb21wb3NpdGlvbiB0byB3b3JrIC0gaWYgaXRcbiAgICAgICAgICAgIC8vIGRvZXNuJ3QgZGVidWdnaW5nIHdpbGwgYmUgc2xpZ2h0bHkgbGVzcyBpbmZvcm1hdGl2ZVxuICAgICAgICAgICAgLy8gKGkuZS4gdG9TdHJpbmcgd2lsbCBzYXkgJ3NweScgcmF0aGVyIHRoYW4gJ215RnVuYycpLlxuICAgICAgICAgICAgKFN0cmluZyhmdW5jKS5tYXRjaCgvZnVuY3Rpb24gKFteXFxzKF0rKS8pIHx8IFtdKVsxXVxuICAgICAgICApO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8gU3RyaW5naWZ5IG1heSBmYWlsIGFuZCB3ZSBtaWdodCBnZXQgYW4gZXhjZXB0aW9uLCBhcyBhIGxhc3QtbGFzdFxuICAgICAgICAvLyByZXNvcnQgZmFsbCBiYWNrIHRvIGVtcHR5IHN0cmluZy5cbiAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgfVxufTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG4vKipcbiAqIEEgcmVmZXJlbmNlIHRvIHRoZSBnbG9iYWwgb2JqZWN0XG4gKiBAdHlwZSB7b2JqZWN0fSBnbG9iYWxPYmplY3RcbiAqL1xudmFyIGdsb2JhbE9iamVjdDtcblxuLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbmlmICh0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgLy8gTm9kZVxuICAgIGdsb2JhbE9iamVjdCA9IGdsb2JhbDtcbn0gZWxzZSBpZiAodHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIC8vIEJyb3dzZXJcbiAgICBnbG9iYWxPYmplY3QgPSB3aW5kb3c7XG59IGVsc2Uge1xuICAgIC8vIFdlYldvcmtlclxuICAgIGdsb2JhbE9iamVjdCA9IHNlbGY7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZ2xvYmFsT2JqZWN0O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIGdsb2JhbDogcmVxdWlyZShcIi4vZ2xvYmFsXCIpLFxuICAgIGNhbGxlZEluT3JkZXI6IHJlcXVpcmUoXCIuL2NhbGxlZC1pbi1vcmRlclwiKSxcbiAgICBjbGFzc05hbWU6IHJlcXVpcmUoXCIuL2NsYXNzLW5hbWVcIiksXG4gICAgZGVwcmVjYXRlZDogcmVxdWlyZShcIi4vZGVwcmVjYXRlZFwiKSxcbiAgICBldmVyeTogcmVxdWlyZShcIi4vZXZlcnlcIiksXG4gICAgZnVuY3Rpb25OYW1lOiByZXF1aXJlKFwiLi9mdW5jdGlvbi1uYW1lXCIpLFxuICAgIG9yZGVyQnlGaXJzdENhbGw6IHJlcXVpcmUoXCIuL29yZGVyLWJ5LWZpcnN0LWNhbGxcIiksXG4gICAgcHJvdG90eXBlczogcmVxdWlyZShcIi4vcHJvdG90eXBlc1wiKSxcbiAgICB0eXBlT2Y6IHJlcXVpcmUoXCIuL3R5cGUtb2ZcIiksXG4gICAgdmFsdWVUb1N0cmluZzogcmVxdWlyZShcIi4vdmFsdWUtdG8tc3RyaW5nXCIpLFxufTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgc29ydCA9IHJlcXVpcmUoXCIuL3Byb3RvdHlwZXMvYXJyYXlcIikuc29ydDtcbnZhciBzbGljZSA9IHJlcXVpcmUoXCIuL3Byb3RvdHlwZXMvYXJyYXlcIikuc2xpY2U7XG5cbi8qKlxuICogQHByaXZhdGVcbiAqL1xuZnVuY3Rpb24gY29tcGFyYXRvcihhLCBiKSB7XG4gICAgLy8gdXVpZCwgd29uJ3QgZXZlciBiZSBlcXVhbFxuICAgIHZhciBhQ2FsbCA9IGEuZ2V0Q2FsbCgwKTtcbiAgICB2YXIgYkNhbGwgPSBiLmdldENhbGwoMCk7XG4gICAgdmFyIGFJZCA9IChhQ2FsbCAmJiBhQ2FsbC5jYWxsSWQpIHx8IC0xO1xuICAgIHZhciBiSWQgPSAoYkNhbGwgJiYgYkNhbGwuY2FsbElkKSB8fCAtMTtcblxuICAgIHJldHVybiBhSWQgPCBiSWQgPyAtMSA6IDE7XG59XG5cbi8qKlxuICogQSBTaW5vbiBwcm94eSBvYmplY3QgKGZha2UsIHNweSwgc3R1YilcbiAqIEB0eXBlZGVmIHtvYmplY3R9IFNpbm9uUHJveHlcbiAqIEBwcm9wZXJ0eSB7RnVuY3Rpb259IGdldENhbGwgLSBBIG1ldGhvZCB0aGF0IGNhbiByZXR1cm4gdGhlIGZpcnN0IGNhbGxcbiAqL1xuXG4vKipcbiAqIFNvcnRzIGFuIGFycmF5IG9mIFNpbm9uUHJveHkgaW5zdGFuY2VzIChmYWtlLCBzcHksIHN0dWIpIGJ5IHRoZWlyIGZpcnN0IGNhbGxcbiAqIEBwYXJhbSAge1Npbm9uUHJveHlbXSB8IFNpbm9uUHJveHl9IHNwaWVzXG4gKiBAcmV0dXJucyB7U2lub25Qcm94eVtdfVxuICovXG5mdW5jdGlvbiBvcmRlckJ5Rmlyc3RDYWxsKHNwaWVzKSB7XG4gICAgcmV0dXJuIHNvcnQoc2xpY2Uoc3BpZXMpLCBjb21wYXJhdG9yKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBvcmRlckJ5Rmlyc3RDYWxsO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBjb3B5UHJvdG90eXBlID0gcmVxdWlyZShcIi4vY29weS1wcm90b3R5cGUtbWV0aG9kc1wiKTtcblxubW9kdWxlLmV4cG9ydHMgPSBjb3B5UHJvdG90eXBlKEFycmF5LnByb3RvdHlwZSk7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGNhbGwgPSBGdW5jdGlvbi5jYWxsO1xudmFyIHRocm93c09uUHJvdG8gPSByZXF1aXJlKFwiLi90aHJvd3Mtb24tcHJvdG9cIik7XG5cbnZhciBkaXNhbGxvd2VkUHJvcGVydGllcyA9IFtcbiAgICAvLyBpZ25vcmUgc2l6ZSBiZWNhdXNlIGl0IHRocm93cyBmcm9tIE1hcFxuICAgIFwic2l6ZVwiLFxuICAgIFwiY2FsbGVyXCIsXG4gICAgXCJjYWxsZWVcIixcbiAgICBcImFyZ3VtZW50c1wiLFxuXTtcblxuLy8gVGhpcyBicmFuY2ggaXMgY292ZXJlZCB3aGVuIHRlc3RzIGFyZSBydW4gd2l0aCBgLS1kaXNhYmxlLXByb3RvPXRocm93YCxcbi8vIGhvd2V2ZXIgd2UgY2FuIHRlc3QgYm90aCBicmFuY2hlcyBhdCB0aGUgc2FtZSB0aW1lLCBzbyB0aGlzIGlzIGlnbm9yZWRcbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG5pZiAodGhyb3dzT25Qcm90bykge1xuICAgIGRpc2FsbG93ZWRQcm9wZXJ0aWVzLnB1c2goXCJfX3Byb3RvX19cIik7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gY29weVByb3RvdHlwZU1ldGhvZHMocHJvdG90eXBlKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBzaW5vbmpzL25vLXByb3RvdHlwZS1tZXRob2RzL25vLXByb3RvdHlwZS1tZXRob2RzXG4gICAgcmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHByb3RvdHlwZSkucmVkdWNlKGZ1bmN0aW9uIChcbiAgICAgICAgcmVzdWx0LFxuICAgICAgICBuYW1lXG4gICAgKSB7XG4gICAgICAgIGlmIChkaXNhbGxvd2VkUHJvcGVydGllcy5pbmNsdWRlcyhuYW1lKSkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgcHJvdG90eXBlW25hbWVdICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXN1bHRbbmFtZV0gPSBjYWxsLmJpbmQocHJvdG90eXBlW25hbWVdKTtcblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sXG4gICAgT2JqZWN0LmNyZWF0ZShudWxsKSk7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBjb3B5UHJvdG90eXBlID0gcmVxdWlyZShcIi4vY29weS1wcm90b3R5cGUtbWV0aG9kc1wiKTtcblxubW9kdWxlLmV4cG9ydHMgPSBjb3B5UHJvdG90eXBlKEZ1bmN0aW9uLnByb3RvdHlwZSk7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgYXJyYXk6IHJlcXVpcmUoXCIuL2FycmF5XCIpLFxuICAgIGZ1bmN0aW9uOiByZXF1aXJlKFwiLi9mdW5jdGlvblwiKSxcbiAgICBtYXA6IHJlcXVpcmUoXCIuL21hcFwiKSxcbiAgICBvYmplY3Q6IHJlcXVpcmUoXCIuL29iamVjdFwiKSxcbiAgICBzZXQ6IHJlcXVpcmUoXCIuL3NldFwiKSxcbiAgICBzdHJpbmc6IHJlcXVpcmUoXCIuL3N0cmluZ1wiKSxcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGNvcHlQcm90b3R5cGUgPSByZXF1aXJlKFwiLi9jb3B5LXByb3RvdHlwZS1tZXRob2RzXCIpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNvcHlQcm90b3R5cGUoTWFwLnByb3RvdHlwZSk7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGNvcHlQcm90b3R5cGUgPSByZXF1aXJlKFwiLi9jb3B5LXByb3RvdHlwZS1tZXRob2RzXCIpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNvcHlQcm90b3R5cGUoT2JqZWN0LnByb3RvdHlwZSk7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGNvcHlQcm90b3R5cGUgPSByZXF1aXJlKFwiLi9jb3B5LXByb3RvdHlwZS1tZXRob2RzXCIpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNvcHlQcm90b3R5cGUoU2V0LnByb3RvdHlwZSk7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGNvcHlQcm90b3R5cGUgPSByZXF1aXJlKFwiLi9jb3B5LXByb3RvdHlwZS1tZXRob2RzXCIpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNvcHlQcm90b3R5cGUoU3RyaW5nLnByb3RvdHlwZSk7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuLyoqXG4gKiBJcyB0cnVlIHdoZW4gdGhlIGVudmlyb25tZW50IGNhdXNlcyBhbiBlcnJvciB0byBiZSB0aHJvd24gZm9yIGFjY2Vzc2luZyB0aGVcbiAqIF9fcHJvdG9fXyBwcm9wZXJ0eS5cbiAqIFRoaXMgaXMgbmVjZXNzYXJ5IGluIG9yZGVyIHRvIHN1cHBvcnQgYG5vZGUgLS1kaXNhYmxlLXByb3RvPXRocm93YC5cbiAqXG4gKiBTZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvT2JqZWN0L3Byb3RvXG4gKiBAdHlwZSB7Ym9vbGVhbn1cbiAqL1xubGV0IHRocm93c09uUHJvdG87XG50cnkge1xuICAgIGNvbnN0IG9iamVjdCA9IHt9O1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1wcm90bywgbm8tdW51c2VkLWV4cHJlc3Npb25zXG4gICAgb2JqZWN0Ll9fcHJvdG9fXztcbiAgICB0aHJvd3NPblByb3RvID0gZmFsc2U7XG59IGNhdGNoIChfKSB7XG4gICAgLy8gVGhpcyBicmFuY2ggaXMgY292ZXJlZCB3aGVuIHRlc3RzIGFyZSBydW4gd2l0aCBgLS1kaXNhYmxlLXByb3RvPXRocm93YCxcbiAgICAvLyBob3dldmVyIHdlIGNhbiB0ZXN0IGJvdGggYnJhbmNoZXMgYXQgdGhlIHNhbWUgdGltZSwgc28gdGhpcyBpcyBpZ25vcmVkXG4gICAgLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbiAgICB0aHJvd3NPblByb3RvID0gdHJ1ZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB0aHJvd3NPblByb3RvO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciB0eXBlID0gcmVxdWlyZShcInR5cGUtZGV0ZWN0XCIpO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGxvd2VyLWNhc2UgcmVzdWx0IG9mIHJ1bm5pbmcgdHlwZSBmcm9tIHR5cGUtZGV0ZWN0IG9uIHRoZSB2YWx1ZVxuICogQHBhcmFtICB7Kn0gdmFsdWVcbiAqIEByZXR1cm5zIHtzdHJpbmd9XG4gKi9cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gdHlwZU9mKHZhbHVlKSB7XG4gICAgcmV0dXJuIHR5cGUodmFsdWUpLnRvTG93ZXJDYXNlKCk7XG59O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbi8qKlxuICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgdmFsdWVcbiAqIEBwYXJhbSAgeyp9IHZhbHVlXG4gKiBAcmV0dXJucyB7c3RyaW5nfVxuICovXG5mdW5jdGlvbiB2YWx1ZVRvU3RyaW5nKHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlICYmIHZhbHVlLnRvU3RyaW5nKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAc2lub25qcy9uby1wcm90b3R5cGUtbWV0aG9kcy9uby1wcm90b3R5cGUtbWV0aG9kc1xuICAgICAgICByZXR1cm4gdmFsdWUudG9TdHJpbmcoKTtcbiAgICB9XG4gICAgcmV0dXJuIFN0cmluZyh2YWx1ZSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gdmFsdWVUb1N0cmluZztcbiIsIlwidXNlIHN0cmljdFwiO1xuXG5jb25zdCBnbG9iYWxPYmplY3QgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5nbG9iYWw7XG5sZXQgdGltZXJzTW9kdWxlLCB0aW1lcnNQcm9taXNlc01vZHVsZTtcbmlmICh0eXBlb2YgcmVxdWlyZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIpIHtcbiAgICB0cnkge1xuICAgICAgICB0aW1lcnNNb2R1bGUgPSByZXF1aXJlKFwidGltZXJzXCIpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgLy8gaWdub3JlZFxuICAgIH1cbiAgICB0cnkge1xuICAgICAgICB0aW1lcnNQcm9taXNlc01vZHVsZSA9IHJlcXVpcmUoXCJ0aW1lcnMvcHJvbWlzZXNcIik7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAvLyBpZ25vcmVkXG4gICAgfVxufVxuXG4vKipcbiAqIEB0eXBlZGVmIHtvYmplY3R9IElkbGVEZWFkbGluZVxuICogQHByb3BlcnR5IHtib29sZWFufSBkaWRUaW1lb3V0IC0gd2hldGhlciBvciBub3QgdGhlIGNhbGxiYWNrIHdhcyBjYWxsZWQgYmVmb3JlIHJlYWNoaW5nIHRoZSBvcHRpb25hbCB0aW1lb3V0XG4gKiBAcHJvcGVydHkge2Z1bmN0aW9uKCk6bnVtYmVyfSB0aW1lUmVtYWluaW5nIC0gYSBmbG9hdGluZy1wb2ludCB2YWx1ZSBwcm92aWRpbmcgYW4gZXN0aW1hdGUgb2YgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgcmVtYWluaW5nIGluIHRoZSBjdXJyZW50IGlkbGUgcGVyaW9kXG4gKi9cblxuLyoqXG4gKiBRdWV1ZXMgYSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgZHVyaW5nIGEgYnJvd3NlcidzIGlkbGUgcGVyaW9kc1xuICpcbiAqIEBjYWxsYmFjayBSZXF1ZXN0SWRsZUNhbGxiYWNrXG4gKiBAcGFyYW0ge2Z1bmN0aW9uKElkbGVEZWFkbGluZSl9IGNhbGxiYWNrXG4gKiBAcGFyYW0ge3t0aW1lb3V0OiBudW1iZXJ9fSBvcHRpb25zIC0gYW4gb3B0aW9ucyBvYmplY3RcbiAqIEByZXR1cm5zIHtudW1iZXJ9IHRoZSBpZFxuICovXG5cbi8qKlxuICogQGNhbGxiYWNrIE5leHRUaWNrXG4gKiBAcGFyYW0ge1ZvaWRWYXJBcmdzRnVuY30gY2FsbGJhY2sgLSB0aGUgY2FsbGJhY2sgdG8gcnVuXG4gKiBAcGFyYW0gey4uLip9IGFyZ3MgLSBvcHRpb25hbCBhcmd1bWVudHMgdG8gY2FsbCB0aGUgY2FsbGJhY2sgd2l0aFxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cblxuLyoqXG4gKiBAY2FsbGJhY2sgU2V0SW1tZWRpYXRlXG4gKiBAcGFyYW0ge1ZvaWRWYXJBcmdzRnVuY30gY2FsbGJhY2sgLSB0aGUgY2FsbGJhY2sgdG8gcnVuXG4gKiBAcGFyYW0gey4uLip9IGFyZ3MgLSBvcHRpb25hbCBhcmd1bWVudHMgdG8gY2FsbCB0aGUgY2FsbGJhY2sgd2l0aFxuICogQHJldHVybnMge05vZGVJbW1lZGlhdGV9XG4gKi9cblxuLyoqXG4gKiBAY2FsbGJhY2sgVm9pZFZhckFyZ3NGdW5jXG4gKiBAcGFyYW0gey4uLip9IGNhbGxiYWNrIC0gdGhlIGNhbGxiYWNrIHRvIHJ1blxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiBSZXF1ZXN0QW5pbWF0aW9uRnJhbWVcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24obnVtYmVyKTp2b2lkfSByZXF1ZXN0QW5pbWF0aW9uRnJhbWVcbiAqIEByZXR1cm5zIHtudW1iZXJ9IC0gdGhlIGlkXG4gKi9cblxuLyoqXG4gKiBAdHlwZWRlZiBQZXJmb3JtYW5jZVxuICogQHByb3BlcnR5IHtmdW5jdGlvbigpOiBudW1iZXJ9IG5vd1xuICovXG5cbi8qIGVzbGludC1kaXNhYmxlIGpzZG9jL3JlcXVpcmUtcHJvcGVydHktZGVzY3JpcHRpb24gKi9cbi8qKlxuICogQHR5cGVkZWYge29iamVjdH0gQ2xvY2tcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBub3cgLSB0aGUgY3VycmVudCB0aW1lXG4gKiBAcHJvcGVydHkge0RhdGV9IERhdGUgLSB0aGUgRGF0ZSBjb25zdHJ1Y3RvclxuICogQHByb3BlcnR5IHtudW1iZXJ9IGxvb3BMaW1pdCAtIHRoZSBtYXhpbXVtIG51bWJlciBvZiB0aW1lcnMgYmVmb3JlIGFzc3VtaW5nIGFuIGluZmluaXRlIGxvb3BcbiAqIEBwcm9wZXJ0eSB7UmVxdWVzdElkbGVDYWxsYmFja30gcmVxdWVzdElkbGVDYWxsYmFja1xuICogQHByb3BlcnR5IHtmdW5jdGlvbihudW1iZXIpOnZvaWR9IGNhbmNlbElkbGVDYWxsYmFja1xuICogQHByb3BlcnR5IHtzZXRUaW1lb3V0fSBzZXRUaW1lb3V0XG4gKiBAcHJvcGVydHkge2NsZWFyVGltZW91dH0gY2xlYXJUaW1lb3V0XG4gKiBAcHJvcGVydHkge05leHRUaWNrfSBuZXh0VGlja1xuICogQHByb3BlcnR5IHtxdWV1ZU1pY3JvdGFza30gcXVldWVNaWNyb3Rhc2tcbiAqIEBwcm9wZXJ0eSB7c2V0SW50ZXJ2YWx9IHNldEludGVydmFsXG4gKiBAcHJvcGVydHkge2NsZWFySW50ZXJ2YWx9IGNsZWFySW50ZXJ2YWxcbiAqIEBwcm9wZXJ0eSB7U2V0SW1tZWRpYXRlfSBzZXRJbW1lZGlhdGVcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24oTm9kZUltbWVkaWF0ZSk6dm9pZH0gY2xlYXJJbW1lZGlhdGVcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24oKTpudW1iZXJ9IGNvdW50VGltZXJzXG4gKiBAcHJvcGVydHkge1JlcXVlc3RBbmltYXRpb25GcmFtZX0gcmVxdWVzdEFuaW1hdGlvbkZyYW1lXG4gKiBAcHJvcGVydHkge2Z1bmN0aW9uKG51bWJlcik6dm9pZH0gY2FuY2VsQW5pbWF0aW9uRnJhbWVcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24oKTp2b2lkfSBydW5NaWNyb3Rhc2tzXG4gKiBAcHJvcGVydHkge2Z1bmN0aW9uKHN0cmluZyB8IG51bWJlcik6IG51bWJlcn0gdGlja1xuICogQHByb3BlcnR5IHtmdW5jdGlvbihzdHJpbmcgfCBudW1iZXIpOiBQcm9taXNlPG51bWJlcj59IHRpY2tBc3luY1xuICogQHByb3BlcnR5IHtmdW5jdGlvbigpOiBudW1iZXJ9IG5leHRcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24oKTogUHJvbWlzZTxudW1iZXI+fSBuZXh0QXN5bmNcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24oKTogbnVtYmVyfSBydW5BbGxcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24oKTogbnVtYmVyfSBydW5Ub0ZyYW1lXG4gKiBAcHJvcGVydHkge2Z1bmN0aW9uKCk6IFByb21pc2U8bnVtYmVyPn0gcnVuQWxsQXN5bmNcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24oKTogbnVtYmVyfSBydW5Ub0xhc3RcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24oKTogUHJvbWlzZTxudW1iZXI+fSBydW5Ub0xhc3RBc3luY1xuICogQHByb3BlcnR5IHtmdW5jdGlvbigpOiB2b2lkfSByZXNldFxuICogQHByb3BlcnR5IHtmdW5jdGlvbihudW1iZXIgfCBEYXRlKTogdm9pZH0gc2V0U3lzdGVtVGltZVxuICogQHByb3BlcnR5IHtmdW5jdGlvbihudW1iZXIpOiB2b2lkfSBqdW1wXG4gKiBAcHJvcGVydHkge1BlcmZvcm1hbmNlfSBwZXJmb3JtYW5jZVxuICogQHByb3BlcnR5IHtmdW5jdGlvbihudW1iZXJbXSk6IG51bWJlcltdfSBocnRpbWUgLSBwcm9jZXNzLmhydGltZSAobGVnYWN5KVxuICogQHByb3BlcnR5IHtmdW5jdGlvbigpOiB2b2lkfSB1bmluc3RhbGwgVW5pbnN0YWxsIHRoZSBjbG9jay5cbiAqIEBwcm9wZXJ0eSB7RnVuY3Rpb25bXX0gbWV0aG9kcyAtIHRoZSBtZXRob2RzIHRoYXQgYXJlIGZha2VkXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtzaG91bGRDbGVhck5hdGl2ZVRpbWVyc10gaW5oZXJpdGVkIGZyb20gY29uZmlnXG4gKiBAcHJvcGVydHkge3ttZXRob2ROYW1lOnN0cmluZywgb3JpZ2luYWw6YW55fVtdIHwgdW5kZWZpbmVkfSB0aW1lcnNNb2R1bGVNZXRob2RzXG4gKiBAcHJvcGVydHkge3ttZXRob2ROYW1lOnN0cmluZywgb3JpZ2luYWw6YW55fVtdIHwgdW5kZWZpbmVkfSB0aW1lcnNQcm9taXNlc01vZHVsZU1ldGhvZHNcbiAqIEBwcm9wZXJ0eSB7TWFwPGZ1bmN0aW9uKCk6IHZvaWQsIEFib3J0U2lnbmFsPn0gYWJvcnRMaXN0ZW5lck1hcFxuICovXG4vKiBlc2xpbnQtZW5hYmxlIGpzZG9jL3JlcXVpcmUtcHJvcGVydHktZGVzY3JpcHRpb24gKi9cblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIG9iamVjdCBmb3IgdGhlIGBpbnN0YWxsYCBtZXRob2QuXG4gKlxuICogQHR5cGVkZWYge29iamVjdH0gQ29uZmlnXG4gKiBAcHJvcGVydHkge251bWJlcnxEYXRlfSBbbm93XSBhIG51bWJlciAoaW4gbWlsbGlzZWNvbmRzKSBvciBhIERhdGUgb2JqZWN0IChkZWZhdWx0IGVwb2NoKVxuICogQHByb3BlcnR5IHtzdHJpbmdbXX0gW3RvRmFrZV0gbmFtZXMgb2YgdGhlIG1ldGhvZHMgdGhhdCBzaG91bGQgYmUgZmFrZWQuXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2xvb3BMaW1pdF0gdGhlIG1heGltdW0gbnVtYmVyIG9mIHRpbWVycyB0aGF0IHdpbGwgYmUgcnVuIHdoZW4gY2FsbGluZyBydW5BbGwoKVxuICogQHByb3BlcnR5IHtib29sZWFufSBbc2hvdWxkQWR2YW5jZVRpbWVdIHRlbGxzIEZha2VUaW1lcnMgdG8gaW5jcmVtZW50IG1vY2tlZCB0aW1lIGF1dG9tYXRpY2FsbHkgKGRlZmF1bHQgZmFsc2UpXG4gKiBAcHJvcGVydHkge251bWJlcn0gW2FkdmFuY2VUaW1lRGVsdGFdIGluY3JlbWVudCBtb2NrZWQgdGltZSBldmVyeSA8PGFkdmFuY2VUaW1lRGVsdGE+PiBtcyAoZGVmYXVsdDogMjBtcylcbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW3Nob3VsZENsZWFyTmF0aXZlVGltZXJzXSBmb3J3YXJkcyBjbGVhciB0aW1lciBjYWxscyB0byBuYXRpdmUgZnVuY3Rpb25zIGlmIHRoZXkgYXJlIG5vdCBmYWtlcyAoZGVmYXVsdDogZmFsc2UpXG4gKiBAcHJvcGVydHkge2Jvb2xlYW59IFtpZ25vcmVNaXNzaW5nVGltZXJzXSBkZWZhdWx0IGlzIGZhbHNlLCBtZWFuaW5nIGFza2luZyB0byBmYWtlIHRpbWVycyB0aGF0IGFyZSBub3QgcHJlc2VudCB3aWxsIHRocm93IGFuIGVycm9yXG4gKi9cblxuLyogZXNsaW50LWRpc2FibGUganNkb2MvcmVxdWlyZS1wcm9wZXJ0eS1kZXNjcmlwdGlvbiAqL1xuLyoqXG4gKiBUaGUgaW50ZXJuYWwgc3RydWN0dXJlIHRvIGRlc2NyaWJlIGEgc2NoZWR1bGVkIGZha2UgdGltZXJcbiAqXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBUaW1lclxuICogQHByb3BlcnR5IHtGdW5jdGlvbn0gZnVuY1xuICogQHByb3BlcnR5IHsqW119IGFyZ3NcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBkZWxheVxuICogQHByb3BlcnR5IHtudW1iZXJ9IGNhbGxBdFxuICogQHByb3BlcnR5IHtudW1iZXJ9IGNyZWF0ZWRBdFxuICogQHByb3BlcnR5IHtib29sZWFufSBpbW1lZGlhdGVcbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBpZFxuICogQHByb3BlcnR5IHtFcnJvcn0gW2Vycm9yXVxuICovXG5cbi8qKlxuICogQSBOb2RlIHRpbWVyXG4gKlxuICogQHR5cGVkZWYge29iamVjdH0gTm9kZUltbWVkaWF0ZVxuICogQHByb3BlcnR5IHtmdW5jdGlvbigpOiBib29sZWFufSBoYXNSZWZcbiAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24oKTogTm9kZUltbWVkaWF0ZX0gcmVmXG4gKiBAcHJvcGVydHkge2Z1bmN0aW9uKCk6IE5vZGVJbW1lZGlhdGV9IHVucmVmXG4gKi9cbi8qIGVzbGludC1lbmFibGUganNkb2MvcmVxdWlyZS1wcm9wZXJ0eS1kZXNjcmlwdGlvbiAqL1xuXG4vKiBlc2xpbnQtZGlzYWJsZSBjb21wbGV4aXR5ICovXG5cbi8qKlxuICogTW9ja3MgYXZhaWxhYmxlIGZlYXR1cmVzIGluIHRoZSBzcGVjaWZpZWQgZ2xvYmFsIG5hbWVzcGFjZS5cbiAqXG4gKiBAcGFyYW0geyp9IF9nbG9iYWwgTmFtZXNwYWNlIHRvIG1vY2sgKGUuZy4gYHdpbmRvd2ApXG4gKiBAcmV0dXJucyB7RmFrZVRpbWVyc31cbiAqL1xuZnVuY3Rpb24gd2l0aEdsb2JhbChfZ2xvYmFsKSB7XG4gICAgY29uc3QgbWF4VGltZW91dCA9IE1hdGgucG93KDIsIDMxKSAtIDE7IC8vc2VlIGh0dHBzOi8vaGV5Y2FtLmdpdGh1Yi5pby93ZWJpZGwvI2Fic3RyYWN0LW9wZGVmLWNvbnZlcnR0b2ludFxuICAgIGNvbnN0IGlkQ291bnRlclN0YXJ0ID0gMWUxMjsgLy8gYXJiaXRyYXJpbHkgbGFyZ2UgbnVtYmVyIHRvIGF2b2lkIGNvbGxpc2lvbnMgd2l0aCBuYXRpdmUgdGltZXIgSURzXG4gICAgY29uc3QgTk9PUCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9O1xuICAgIGNvbnN0IE5PT1BfQVJSQVkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9O1xuICAgIGNvbnN0IGlzUHJlc2VudCA9IHt9O1xuICAgIGxldCB0aW1lb3V0UmVzdWx0LFxuICAgICAgICBhZGRUaW1lclJldHVybnNPYmplY3QgPSBmYWxzZTtcblxuICAgIGlmIChfZ2xvYmFsLnNldFRpbWVvdXQpIHtcbiAgICAgICAgaXNQcmVzZW50LnNldFRpbWVvdXQgPSB0cnVlO1xuICAgICAgICB0aW1lb3V0UmVzdWx0ID0gX2dsb2JhbC5zZXRUaW1lb3V0KE5PT1AsIDApO1xuICAgICAgICBhZGRUaW1lclJldHVybnNPYmplY3QgPSB0eXBlb2YgdGltZW91dFJlc3VsdCA9PT0gXCJvYmplY3RcIjtcbiAgICB9XG4gICAgaXNQcmVzZW50LmNsZWFyVGltZW91dCA9IEJvb2xlYW4oX2dsb2JhbC5jbGVhclRpbWVvdXQpO1xuICAgIGlzUHJlc2VudC5zZXRJbnRlcnZhbCA9IEJvb2xlYW4oX2dsb2JhbC5zZXRJbnRlcnZhbCk7XG4gICAgaXNQcmVzZW50LmNsZWFySW50ZXJ2YWwgPSBCb29sZWFuKF9nbG9iYWwuY2xlYXJJbnRlcnZhbCk7XG4gICAgaXNQcmVzZW50LmhydGltZSA9XG4gICAgICAgIF9nbG9iYWwucHJvY2VzcyAmJiB0eXBlb2YgX2dsb2JhbC5wcm9jZXNzLmhydGltZSA9PT0gXCJmdW5jdGlvblwiO1xuICAgIGlzUHJlc2VudC5ocnRpbWVCaWdpbnQgPVxuICAgICAgICBpc1ByZXNlbnQuaHJ0aW1lICYmIHR5cGVvZiBfZ2xvYmFsLnByb2Nlc3MuaHJ0aW1lLmJpZ2ludCA9PT0gXCJmdW5jdGlvblwiO1xuICAgIGlzUHJlc2VudC5uZXh0VGljayA9XG4gICAgICAgIF9nbG9iYWwucHJvY2VzcyAmJiB0eXBlb2YgX2dsb2JhbC5wcm9jZXNzLm5leHRUaWNrID09PSBcImZ1bmN0aW9uXCI7XG4gICAgY29uc3QgdXRpbFByb21pc2lmeSA9IF9nbG9iYWwucHJvY2VzcyAmJiByZXF1aXJlKFwidXRpbFwiKS5wcm9taXNpZnk7XG4gICAgaXNQcmVzZW50LnBlcmZvcm1hbmNlID1cbiAgICAgICAgX2dsb2JhbC5wZXJmb3JtYW5jZSAmJiB0eXBlb2YgX2dsb2JhbC5wZXJmb3JtYW5jZS5ub3cgPT09IFwiZnVuY3Rpb25cIjtcbiAgICBjb25zdCBoYXNQZXJmb3JtYW5jZVByb3RvdHlwZSA9XG4gICAgICAgIF9nbG9iYWwuUGVyZm9ybWFuY2UgJiZcbiAgICAgICAgKHR5cGVvZiBfZ2xvYmFsLlBlcmZvcm1hbmNlKS5tYXRjaCgvXihmdW5jdGlvbnxvYmplY3QpJC8pO1xuICAgIGNvbnN0IGhhc1BlcmZvcm1hbmNlQ29uc3RydWN0b3JQcm90b3R5cGUgPVxuICAgICAgICBfZ2xvYmFsLnBlcmZvcm1hbmNlICYmXG4gICAgICAgIF9nbG9iYWwucGVyZm9ybWFuY2UuY29uc3RydWN0b3IgJiZcbiAgICAgICAgX2dsb2JhbC5wZXJmb3JtYW5jZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgaXNQcmVzZW50LnF1ZXVlTWljcm90YXNrID0gX2dsb2JhbC5oYXNPd25Qcm9wZXJ0eShcInF1ZXVlTWljcm90YXNrXCIpO1xuICAgIGlzUHJlc2VudC5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgPVxuICAgICAgICBfZ2xvYmFsLnJlcXVlc3RBbmltYXRpb25GcmFtZSAmJlxuICAgICAgICB0eXBlb2YgX2dsb2JhbC5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgPT09IFwiZnVuY3Rpb25cIjtcbiAgICBpc1ByZXNlbnQuY2FuY2VsQW5pbWF0aW9uRnJhbWUgPVxuICAgICAgICBfZ2xvYmFsLmNhbmNlbEFuaW1hdGlvbkZyYW1lICYmXG4gICAgICAgIHR5cGVvZiBfZ2xvYmFsLmNhbmNlbEFuaW1hdGlvbkZyYW1lID09PSBcImZ1bmN0aW9uXCI7XG4gICAgaXNQcmVzZW50LnJlcXVlc3RJZGxlQ2FsbGJhY2sgPVxuICAgICAgICBfZ2xvYmFsLnJlcXVlc3RJZGxlQ2FsbGJhY2sgJiZcbiAgICAgICAgdHlwZW9mIF9nbG9iYWwucmVxdWVzdElkbGVDYWxsYmFjayA9PT0gXCJmdW5jdGlvblwiO1xuICAgIGlzUHJlc2VudC5jYW5jZWxJZGxlQ2FsbGJhY2tQcmVzZW50ID1cbiAgICAgICAgX2dsb2JhbC5jYW5jZWxJZGxlQ2FsbGJhY2sgJiZcbiAgICAgICAgdHlwZW9mIF9nbG9iYWwuY2FuY2VsSWRsZUNhbGxiYWNrID09PSBcImZ1bmN0aW9uXCI7XG4gICAgaXNQcmVzZW50LnNldEltbWVkaWF0ZSA9XG4gICAgICAgIF9nbG9iYWwuc2V0SW1tZWRpYXRlICYmIHR5cGVvZiBfZ2xvYmFsLnNldEltbWVkaWF0ZSA9PT0gXCJmdW5jdGlvblwiO1xuICAgIGlzUHJlc2VudC5jbGVhckltbWVkaWF0ZSA9XG4gICAgICAgIF9nbG9iYWwuY2xlYXJJbW1lZGlhdGUgJiYgdHlwZW9mIF9nbG9iYWwuY2xlYXJJbW1lZGlhdGUgPT09IFwiZnVuY3Rpb25cIjtcbiAgICBpc1ByZXNlbnQuSW50bCA9IF9nbG9iYWwuSW50bCAmJiB0eXBlb2YgX2dsb2JhbC5JbnRsID09PSBcIm9iamVjdFwiO1xuXG4gICAgaWYgKF9nbG9iYWwuY2xlYXJUaW1lb3V0KSB7XG4gICAgICAgIF9nbG9iYWwuY2xlYXJUaW1lb3V0KHRpbWVvdXRSZXN1bHQpO1xuICAgIH1cblxuICAgIGNvbnN0IE5hdGl2ZURhdGUgPSBfZ2xvYmFsLkRhdGU7XG4gICAgY29uc3QgTmF0aXZlSW50bCA9IF9nbG9iYWwuSW50bDtcbiAgICBsZXQgdW5pcXVlVGltZXJJZCA9IGlkQ291bnRlclN0YXJ0O1xuXG4gICAgaWYgKE5hdGl2ZURhdGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBcIlRoZSBnbG9iYWwgc2NvcGUgZG9lc24ndCBoYXZlIGEgYERhdGVgIG9iamVjdFwiICtcbiAgICAgICAgICAgICAgICBcIiAoc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9zaW5vbmpzL3Npbm9uL2lzc3Vlcy8xODUyI2lzc3VlY29tbWVudC00MTk2MjI3ODApXCIsXG4gICAgICAgICk7XG4gICAgfVxuICAgIGlzUHJlc2VudC5EYXRlID0gdHJ1ZTtcblxuICAgIC8qKlxuICAgICAqIFRoZSBQZXJmb3JtYW5jZUVudHJ5IG9iamVjdCBlbmNhcHN1bGF0ZXMgYSBzaW5nbGUgcGVyZm9ybWFuY2UgbWV0cmljXG4gICAgICogdGhhdCBpcyBwYXJ0IG9mIHRoZSBicm93c2VyJ3MgcGVyZm9ybWFuY2UgdGltZWxpbmUuXG4gICAgICpcbiAgICAgKiBUaGlzIGlzIGFuIG9iamVjdCByZXR1cm5lZCBieSB0aGUgYG1hcmtgIGFuZCBgbWVhc3VyZWAgbWV0aG9kcyBvbiB0aGUgUGVyZm9ybWFuY2UgcHJvdG90eXBlXG4gICAgICovXG4gICAgY2xhc3MgRmFrZVBlcmZvcm1hbmNlRW50cnkge1xuICAgICAgICBjb25zdHJ1Y3RvcihuYW1lLCBlbnRyeVR5cGUsIHN0YXJ0VGltZSwgZHVyYXRpb24pIHtcbiAgICAgICAgICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gICAgICAgICAgICB0aGlzLmVudHJ5VHlwZSA9IGVudHJ5VHlwZTtcbiAgICAgICAgICAgIHRoaXMuc3RhcnRUaW1lID0gc3RhcnRUaW1lO1xuICAgICAgICAgICAgdGhpcy5kdXJhdGlvbiA9IGR1cmF0aW9uO1xuICAgICAgICB9XG5cbiAgICAgICAgdG9KU09OKCkge1xuICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHsgLi4udGhpcyB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBudW1cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc051bWJlckZpbml0ZShudW0pIHtcbiAgICAgICAgaWYgKE51bWJlci5pc0Zpbml0ZSkge1xuICAgICAgICAgICAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShudW0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGlzRmluaXRlKG51bSk7XG4gICAgfVxuXG4gICAgbGV0IGlzTmVhckluZmluaXRlTGltaXQgPSBmYWxzZTtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7Q2xvY2t9IGNsb2NrXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGlcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjaGVja0lzTmVhckluZmluaXRlTGltaXQoY2xvY2ssIGkpIHtcbiAgICAgICAgaWYgKGNsb2NrLmxvb3BMaW1pdCAmJiBpID09PSBjbG9jay5sb29wTGltaXQgLSAxKSB7XG4gICAgICAgICAgICBpc05lYXJJbmZpbml0ZUxpbWl0ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqXG4gICAgICovXG4gICAgZnVuY3Rpb24gcmVzZXRJc05lYXJJbmZpbml0ZUxpbWl0KCkge1xuICAgICAgICBpc05lYXJJbmZpbml0ZUxpbWl0ID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGFyc2Ugc3RyaW5ncyBsaWtlIFwiMDE6MTA6MDBcIiAobWVhbmluZyAxIGhvdXIsIDEwIG1pbnV0ZXMsIDAgc2Vjb25kcykgaW50b1xuICAgICAqIG51bWJlciBvZiBtaWxsaXNlY29uZHMuIFRoaXMgaXMgdXNlZCB0byBzdXBwb3J0IGh1bWFuLXJlYWRhYmxlIHN0cmluZ3MgcGFzc2VkXG4gICAgICogdG8gY2xvY2sudGljaygpXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyXG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBwYXJzZVRpbWUoc3RyKSB7XG4gICAgICAgIGlmICghc3RyKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHN0cmluZ3MgPSBzdHIuc3BsaXQoXCI6XCIpO1xuICAgICAgICBjb25zdCBsID0gc3RyaW5ncy5sZW5ndGg7XG4gICAgICAgIGxldCBpID0gbDtcbiAgICAgICAgbGV0IG1zID0gMDtcbiAgICAgICAgbGV0IHBhcnNlZDtcblxuICAgICAgICBpZiAobCA+IDMgfHwgIS9eKFxcZFxcZDopezAsMn1cXGRcXGQ/JC8udGVzdChzdHIpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgXCJ0aWNrIG9ubHkgdW5kZXJzdGFuZHMgbnVtYmVycywgJ206cycgYW5kICdoOm06cycuIEVhY2ggcGFydCBtdXN0IGJlIHR3byBkaWdpdHNcIixcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICBwYXJzZWQgPSBwYXJzZUludChzdHJpbmdzW2ldLCAxMCk7XG5cbiAgICAgICAgICAgIGlmIChwYXJzZWQgPj0gNjApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgdGltZSAke3N0cn1gKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbXMgKz0gcGFyc2VkICogTWF0aC5wb3coNjAsIGwgLSBpIC0gMSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbXMgKiAxMDAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgZGVjaW1hbCBwYXJ0IG9mIHRoZSBtaWxsaXNlY29uZCB2YWx1ZSBhcyBuYW5vc2Vjb25kc1xuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1zRmxvYXQgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHNcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBhbiBpbnRlZ2VyIG51bWJlciBvZiBuYW5vc2Vjb25kcyBpbiB0aGUgcmFuZ2UgWzAsMWU2KVxuICAgICAqXG4gICAgICogRXhhbXBsZTogbmFub1JlbWFpbmVyKDEyMy40NTY3ODkpIC0+IDQ1Njc4OVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG5hbm9SZW1haW5kZXIobXNGbG9hdCkge1xuICAgICAgICBjb25zdCBtb2R1bG8gPSAxZTY7XG4gICAgICAgIGNvbnN0IHJlbWFpbmRlciA9IChtc0Zsb2F0ICogMWU2KSAlIG1vZHVsbztcbiAgICAgICAgY29uc3QgcG9zaXRpdmVSZW1haW5kZXIgPVxuICAgICAgICAgICAgcmVtYWluZGVyIDwgMCA/IHJlbWFpbmRlciArIG1vZHVsbyA6IHJlbWFpbmRlcjtcblxuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihwb3NpdGl2ZVJlbWFpbmRlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXNlZCB0byBncm9rIHRoZSBgbm93YCBwYXJhbWV0ZXIgdG8gY3JlYXRlQ2xvY2suXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0RhdGV8bnVtYmVyfSBlcG9jaCB0aGUgc3lzdGVtIHRpbWVcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldEVwb2NoKGVwb2NoKSB7XG4gICAgICAgIGlmICghZXBvY2gpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgZXBvY2guZ2V0VGltZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICByZXR1cm4gZXBvY2guZ2V0VGltZSgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgZXBvY2ggPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBlcG9jaDtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwibm93IHNob3VsZCBiZSBtaWxsaXNlY29uZHMgc2luY2UgVU5JWCBlcG9jaFwiKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZnJvbVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB0b1xuICAgICAqIEBwYXJhbSB7VGltZXJ9IHRpbWVyXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgZnVuY3Rpb24gaW5SYW5nZShmcm9tLCB0bywgdGltZXIpIHtcbiAgICAgICAgcmV0dXJuIHRpbWVyICYmIHRpbWVyLmNhbGxBdCA+PSBmcm9tICYmIHRpbWVyLmNhbGxBdCA8PSB0bztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge0Nsb2NrfSBjbG9ja1xuICAgICAqIEBwYXJhbSB7VGltZXJ9IGpvYlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGdldEluZmluaXRlTG9vcEVycm9yKGNsb2NrLCBqb2IpIHtcbiAgICAgICAgY29uc3QgaW5maW5pdGVMb29wRXJyb3IgPSBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgQWJvcnRpbmcgYWZ0ZXIgcnVubmluZyAke2Nsb2NrLmxvb3BMaW1pdH0gdGltZXJzLCBhc3N1bWluZyBhbiBpbmZpbml0ZSBsb29wIWAsXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKCFqb2IuZXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBpbmZpbml0ZUxvb3BFcnJvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHBhdHRlcm4gbmV2ZXIgbWF0Y2hlZCBpbiBOb2RlXG4gICAgICAgIGNvbnN0IGNvbXB1dGVkVGFyZ2V0UGF0dGVybiA9IC90YXJnZXRcXC4qWzx8KHxbXS4qP1s+fFxcXXwpXVxccyovO1xuICAgICAgICBsZXQgY2xvY2tNZXRob2RQYXR0ZXJuID0gbmV3IFJlZ0V4cChcbiAgICAgICAgICAgIFN0cmluZyhPYmplY3Qua2V5cyhjbG9jaykuam9pbihcInxcIikpLFxuICAgICAgICApO1xuXG4gICAgICAgIGlmIChhZGRUaW1lclJldHVybnNPYmplY3QpIHtcbiAgICAgICAgICAgIC8vIG5vZGUuanMgZW52aXJvbm1lbnRcbiAgICAgICAgICAgIGNsb2NrTWV0aG9kUGF0dGVybiA9IG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAgICAgYFxcXFxzK2F0IChPYmplY3RcXFxcLik/KD86JHtPYmplY3Qua2V5cyhjbG9jaykuam9pbihcInxcIil9KVxcXFxzK2AsXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG1hdGNoZWRMaW5lSW5kZXggPSAtMTtcbiAgICAgICAgam9iLmVycm9yLnN0YWNrLnNwbGl0KFwiXFxuXCIpLnNvbWUoZnVuY3Rpb24gKGxpbmUsIGkpIHtcbiAgICAgICAgICAgIC8vIElmIHdlJ3ZlIG1hdGNoZWQgYSBjb21wdXRlZCB0YXJnZXQgbGluZSAoZS5nLiBzZXRUaW1lb3V0KSB0aGVuIHdlXG4gICAgICAgICAgICAvLyBkb24ndCBuZWVkIHRvIGxvb2sgYW55IGZ1cnRoZXIuIFJldHVybiB0cnVlIHRvIHN0b3AgaXRlcmF0aW5nLlxuICAgICAgICAgICAgY29uc3QgbWF0Y2hlZENvbXB1dGVkVGFyZ2V0ID0gbGluZS5tYXRjaChjb21wdXRlZFRhcmdldFBhdHRlcm4pO1xuICAgICAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgICAgICAgICBpZiAobWF0Y2hlZENvbXB1dGVkVGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgbWF0Y2hlZExpbmVJbmRleCA9IGk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIElmIHdlJ3ZlIG1hdGNoZWQgYSBjbG9jayBtZXRob2QgbGluZSwgdGhlbiB0aGVyZSBtYXkgc3RpbGwgYmVcbiAgICAgICAgICAgIC8vIG90aGVycyBmdXJ0aGVyIGRvd24gdGhlIHRyYWNlLiBSZXR1cm4gZmFsc2UgdG8ga2VlcCBpdGVyYXRpbmcuXG4gICAgICAgICAgICBjb25zdCBtYXRjaGVkQ2xvY2tNZXRob2QgPSBsaW5lLm1hdGNoKGNsb2NrTWV0aG9kUGF0dGVybik7XG4gICAgICAgICAgICBpZiAobWF0Y2hlZENsb2NrTWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgbWF0Y2hlZExpbmVJbmRleCA9IGk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJZiB3ZSBoYXZlbid0IG1hdGNoZWQgYW55dGhpbmcgb24gdGhpcyBsaW5lLCBidXQgd2UgbWF0Y2hlZFxuICAgICAgICAgICAgLy8gcHJldmlvdXNseSBhbmQgc2V0IHRoZSBtYXRjaGVkIGxpbmUgaW5kZXgsIHRoZW4gd2UgY2FuIHN0b3AuXG4gICAgICAgICAgICAvLyBJZiB3ZSBoYXZlbid0IG1hdGNoZWQgcHJldmlvdXNseSwgdGhlbiB3ZSBzaG91bGQga2VlcCBpdGVyYXRpbmcuXG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hlZExpbmVJbmRleCA+PSAwO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBzdGFjayA9IGAke2luZmluaXRlTG9vcEVycm9yfVxcbiR7am9iLnR5cGUgfHwgXCJNaWNyb3Rhc2tcIn0gLSAke1xuICAgICAgICAgICAgam9iLmZ1bmMubmFtZSB8fCBcImFub255bW91c1wiXG4gICAgICAgIH1cXG4ke2pvYi5lcnJvci5zdGFja1xuICAgICAgICAgICAgLnNwbGl0KFwiXFxuXCIpXG4gICAgICAgICAgICAuc2xpY2UobWF0Y2hlZExpbmVJbmRleCArIDEpXG4gICAgICAgICAgICAuam9pbihcIlxcblwiKX1gO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoaW5maW5pdGVMb29wRXJyb3IsIFwic3RhY2tcIiwge1xuICAgICAgICAgICAgICAgIHZhbHVlOiBzdGFjayxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAvLyBub29wXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gaW5maW5pdGVMb29wRXJyb3I7XG4gICAgfVxuXG4gICAgLy9lc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUganNkb2MvcmVxdWlyZS1qc2RvY1xuICAgIGZ1bmN0aW9uIGNyZWF0ZURhdGUoKSB7XG4gICAgICAgIGNsYXNzIENsb2NrRGF0ZSBleHRlbmRzIE5hdGl2ZURhdGUge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0geWVhclxuICAgICAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IG1vbnRoXG4gICAgICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gZGF0ZVxuICAgICAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IGhvdXJcbiAgICAgICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtaW51dGVcbiAgICAgICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzZWNvbmRcbiAgICAgICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtc1xuICAgICAgICAgICAgICogQHJldHVybnMgdm9pZFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkLXZhcnNcbiAgICAgICAgICAgIGNvbnN0cnVjdG9yKHllYXIsIG1vbnRoLCBkYXRlLCBob3VyLCBtaW51dGUsIHNlY29uZCwgbXMpIHtcbiAgICAgICAgICAgICAgICAvLyBEZWZlbnNpdmUgYW5kIHZlcmJvc2UgdG8gYXZvaWQgcG90ZW50aWFsIGhhcm0gaW4gcGFzc2luZ1xuICAgICAgICAgICAgICAgIC8vIGV4cGxpY2l0IHVuZGVmaW5lZCB3aGVuIHVzZXIgZG9lcyBub3QgcGFzcyBhcmd1bWVudFxuICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHN1cGVyKENsb2NrRGF0ZS5jbG9jay5ub3cpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHN1cGVyKC4uLmFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZW5zdXJlcyBpZGVudGl0eSBjaGVja3MgdXNpbmcgdGhlIGNvbnN0cnVjdG9yIHByb3Agc3RpbGwgd29ya3NcbiAgICAgICAgICAgICAgICAvLyB0aGlzIHNob3VsZCBoYXZlIG5vIG90aGVyIGZ1bmN0aW9uYWwgZWZmZWN0XG4gICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIFwiY29uc3RydWN0b3JcIiwge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogTmF0aXZlRGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHN0YXRpYyBbU3ltYm9sLmhhc0luc3RhbmNlXShpbnN0YW5jZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpbnN0YW5jZSBpbnN0YW5jZW9mIE5hdGl2ZURhdGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBDbG9ja0RhdGUuaXNGYWtlID0gdHJ1ZTtcblxuICAgICAgICBpZiAoTmF0aXZlRGF0ZS5ub3cpIHtcbiAgICAgICAgICAgIENsb2NrRGF0ZS5ub3cgPSBmdW5jdGlvbiBub3coKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIENsb2NrRGF0ZS5jbG9jay5ub3c7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKE5hdGl2ZURhdGUudG9Tb3VyY2UpIHtcbiAgICAgICAgICAgIENsb2NrRGF0ZS50b1NvdXJjZSA9IGZ1bmN0aW9uIHRvU291cmNlKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBOYXRpdmVEYXRlLnRvU291cmNlKCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgQ2xvY2tEYXRlLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gTmF0aXZlRGF0ZS50b1N0cmluZygpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIG5vaW5zcGVjdGlvbiBVbm5lY2Vzc2FyeUxvY2FsVmFyaWFibGVKU1xuICAgICAgICAvKipcbiAgICAgICAgICogQSBub3JtYWwgQ2xhc3MgY29uc3RydWN0b3IgY2Fubm90IGJlIGNhbGxlZCB3aXRob3V0IGBuZXdgLCBidXQgRGF0ZSBjYW4sIHNvIHdlIG5lZWRcbiAgICAgICAgICogdG8gd3JhcCBpdCBpbiBhIFByb3h5IGluIG9yZGVyIHRvIGVuc3VyZSB0aGlzIGZ1bmN0aW9uYWxpdHkgb2YgRGF0ZSBpcyBrZXB0IGludGFjdFxuICAgICAgICAgKlxuICAgICAgICAgKiBAdHlwZSB7Q2xvY2tEYXRlfVxuICAgICAgICAgKi9cbiAgICAgICAgY29uc3QgQ2xvY2tEYXRlUHJveHkgPSBuZXcgUHJveHkoQ2xvY2tEYXRlLCB7XG4gICAgICAgICAgICAvLyBoYW5kbGVyIGZvciBbW0NhbGxdXSBpbnZvY2F0aW9ucyAoaS5lLiBub3QgdXNpbmcgYG5ld2ApXG4gICAgICAgICAgICBhcHBseSgpIHtcbiAgICAgICAgICAgICAgICAvLyB0aGUgRGF0ZSBjb25zdHJ1Y3RvciBjYWxsZWQgYXMgYSBmdW5jdGlvbiwgcmVmIEVjbWEtMjYyIEVkaXRpb24gNS4xLCBzZWN0aW9uIDE1LjkuMi5cbiAgICAgICAgICAgICAgICAvLyBUaGlzIHJlbWFpbnMgc28gaW4gdGhlIDEwdGggZWRpdGlvbiBvZiAyMDE5IGFzIHdlbGwuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMgaW5zdGFuY2VvZiBDbG9ja0RhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiQSBQcm94eSBzaG91bGQgb25seSBjYXB0dXJlIGBuZXdgIGNhbGxzIHdpdGggdGhlIGBjb25zdHJ1Y3RgIGhhbmRsZXIuIFRoaXMgaXMgbm90IHN1cHBvc2VkIHRvIGJlIHBvc3NpYmxlLCBzbyBjaGVjayB0aGUgbG9naWMuXCIsXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBOYXRpdmVEYXRlKENsb2NrRGF0ZS5jbG9jay5ub3cpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gQ2xvY2tEYXRlUHJveHk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWlycm9yIEludGwgYnkgZGVmYXVsdCBvbiBvdXIgZmFrZSBpbXBsZW1lbnRhdGlvblxuICAgICAqXG4gICAgICogTW9zdCBvZiB0aGUgcHJvcGVydGllcyBhcmUgdGhlIG9yaWdpbmFsIG5hdGl2ZSBvbmVzLFxuICAgICAqIGJ1dCB3ZSBuZWVkIHRvIHRha2UgY29udHJvbCBvZiB0aG9zZSB0aGF0IGhhdmUgYVxuICAgICAqIGRlcGVuZGVuY3kgb24gdGhlIGN1cnJlbnQgY2xvY2suXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7b2JqZWN0fSB0aGUgcGFydGx5IGZha2UgSW50bCBpbXBsZW1lbnRhdGlvblxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUludGwoKSB7XG4gICAgICAgIGNvbnN0IENsb2NrSW50bCA9IHt9O1xuICAgICAgICAvKlxuICAgICAgICAgKiBBbGwgcHJvcGVydGllcyBvZiBJbnRsIGFyZSBub24tZW51bWVyYWJsZSwgc28gd2UgbmVlZFxuICAgICAgICAgKiB0byBkbyBhIGJpdCBvZiB3b3JrIHRvIGdldCB0aGVtIG91dC5cbiAgICAgICAgICovXG4gICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKE5hdGl2ZUludGwpLmZvckVhY2goXG4gICAgICAgICAgICAocHJvcGVydHkpID0+IChDbG9ja0ludGxbcHJvcGVydHldID0gTmF0aXZlSW50bFtwcm9wZXJ0eV0pLFxuICAgICAgICApO1xuXG4gICAgICAgIENsb2NrSW50bC5EYXRlVGltZUZvcm1hdCA9IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgICAgICBjb25zdCByZWFsRm9ybWF0dGVyID0gbmV3IE5hdGl2ZUludGwuRGF0ZVRpbWVGb3JtYXQoLi4uYXJncyk7XG4gICAgICAgICAgICBjb25zdCBmb3JtYXR0ZXIgPSB7fTtcblxuICAgICAgICAgICAgW1wiZm9ybWF0UmFuZ2VcIiwgXCJmb3JtYXRSYW5nZVRvUGFydHNcIiwgXCJyZXNvbHZlZE9wdGlvbnNcIl0uZm9yRWFjaChcbiAgICAgICAgICAgICAgICAobWV0aG9kKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGZvcm1hdHRlclttZXRob2RdID1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJlYWxGb3JtYXR0ZXJbbWV0aG9kXS5iaW5kKHJlYWxGb3JtYXR0ZXIpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBbXCJmb3JtYXRcIiwgXCJmb3JtYXRUb1BhcnRzXCJdLmZvckVhY2goKG1ldGhvZCkgPT4ge1xuICAgICAgICAgICAgICAgIGZvcm1hdHRlclttZXRob2RdID0gZnVuY3Rpb24gKGRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlYWxGb3JtYXR0ZXJbbWV0aG9kXShkYXRlIHx8IENsb2NrSW50bC5jbG9jay5ub3cpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdHRlcjtcbiAgICAgICAgfTtcblxuICAgICAgICBDbG9ja0ludGwuRGF0ZVRpbWVGb3JtYXQucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShcbiAgICAgICAgICAgIE5hdGl2ZUludGwuRGF0ZVRpbWVGb3JtYXQucHJvdG90eXBlLFxuICAgICAgICApO1xuXG4gICAgICAgIENsb2NrSW50bC5EYXRlVGltZUZvcm1hdC5zdXBwb3J0ZWRMb2NhbGVzT2YgPVxuICAgICAgICAgICAgTmF0aXZlSW50bC5EYXRlVGltZUZvcm1hdC5zdXBwb3J0ZWRMb2NhbGVzT2Y7XG5cbiAgICAgICAgcmV0dXJuIENsb2NrSW50bDtcbiAgICB9XG5cbiAgICAvL2VzbGludC1kaXNhYmxlLW5leHQtbGluZSBqc2RvYy9yZXF1aXJlLWpzZG9jXG4gICAgZnVuY3Rpb24gZW5xdWV1ZUpvYihjbG9jaywgam9iKSB7XG4gICAgICAgIC8vIGVucXVldWVzIGEgbWljcm90aWNrLWRlZmVycmVkIHRhc2sgLSBlY21hMjYyLyNzZWMtZW5xdWV1ZWpvYlxuICAgICAgICBpZiAoIWNsb2NrLmpvYnMpIHtcbiAgICAgICAgICAgIGNsb2NrLmpvYnMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBjbG9jay5qb2JzLnB1c2goam9iKTtcbiAgICB9XG5cbiAgICAvL2VzbGludC1kaXNhYmxlLW5leHQtbGluZSBqc2RvYy9yZXF1aXJlLWpzZG9jXG4gICAgZnVuY3Rpb24gcnVuSm9icyhjbG9jaykge1xuICAgICAgICAvLyBydW5zIGFsbCBtaWNyb3RpY2stZGVmZXJyZWQgdGFza3MgLSBlY21hMjYyLyNzZWMtcnVuam9ic1xuICAgICAgICBpZiAoIWNsb2NrLmpvYnMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNsb2NrLmpvYnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGpvYiA9IGNsb2NrLmpvYnNbaV07XG4gICAgICAgICAgICBqb2IuZnVuYy5hcHBseShudWxsLCBqb2IuYXJncyk7XG5cbiAgICAgICAgICAgIGNoZWNrSXNOZWFySW5maW5pdGVMaW1pdChjbG9jaywgaSk7XG4gICAgICAgICAgICBpZiAoY2xvY2subG9vcExpbWl0ICYmIGkgPiBjbG9jay5sb29wTGltaXQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBnZXRJbmZpbml0ZUxvb3BFcnJvcihjbG9jaywgam9iKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXNldElzTmVhckluZmluaXRlTGltaXQoKTtcbiAgICAgICAgY2xvY2suam9icyA9IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7Q2xvY2t9IGNsb2NrXG4gICAgICogQHBhcmFtIHtUaW1lcn0gdGltZXJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBpZCBvZiB0aGUgY3JlYXRlZCB0aW1lclxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFkZFRpbWVyKGNsb2NrLCB0aW1lcikge1xuICAgICAgICBpZiAodGltZXIuZnVuYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYWxsYmFjayBtdXN0IGJlIHByb3ZpZGVkIHRvIHRpbWVyIGNhbGxzXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGFkZFRpbWVyUmV0dXJuc09iamVjdCkge1xuICAgICAgICAgICAgLy8gTm9kZS5qcyBlbnZpcm9ubWVudFxuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aW1lci5mdW5jICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgICAgICAgICBgW0VSUl9JTlZBTElEX0NBTExCQUNLXTogQ2FsbGJhY2sgbXVzdCBiZSBhIGZ1bmN0aW9uLiBSZWNlaXZlZCAke1xuICAgICAgICAgICAgICAgICAgICAgICAgdGltZXIuZnVuY1xuICAgICAgICAgICAgICAgICAgICB9IG9mIHR5cGUgJHt0eXBlb2YgdGltZXIuZnVuY31gLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXNOZWFySW5maW5pdGVMaW1pdCkge1xuICAgICAgICAgICAgdGltZXIuZXJyb3IgPSBuZXcgRXJyb3IoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRpbWVyLnR5cGUgPSB0aW1lci5pbW1lZGlhdGUgPyBcIkltbWVkaWF0ZVwiIDogXCJUaW1lb3V0XCI7XG5cbiAgICAgICAgaWYgKHRpbWVyLmhhc093blByb3BlcnR5KFwiZGVsYXlcIikpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGltZXIuZGVsYXkgIT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICB0aW1lci5kZWxheSA9IHBhcnNlSW50KHRpbWVyLmRlbGF5LCAxMCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghaXNOdW1iZXJGaW5pdGUodGltZXIuZGVsYXkpKSB7XG4gICAgICAgICAgICAgICAgdGltZXIuZGVsYXkgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGltZXIuZGVsYXkgPSB0aW1lci5kZWxheSA+IG1heFRpbWVvdXQgPyAxIDogdGltZXIuZGVsYXk7XG4gICAgICAgICAgICB0aW1lci5kZWxheSA9IE1hdGgubWF4KDAsIHRpbWVyLmRlbGF5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aW1lci5oYXNPd25Qcm9wZXJ0eShcImludGVydmFsXCIpKSB7XG4gICAgICAgICAgICB0aW1lci50eXBlID0gXCJJbnRlcnZhbFwiO1xuICAgICAgICAgICAgdGltZXIuaW50ZXJ2YWwgPSB0aW1lci5pbnRlcnZhbCA+IG1heFRpbWVvdXQgPyAxIDogdGltZXIuaW50ZXJ2YWw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGltZXIuaGFzT3duUHJvcGVydHkoXCJhbmltYXRpb25cIikpIHtcbiAgICAgICAgICAgIHRpbWVyLnR5cGUgPSBcIkFuaW1hdGlvbkZyYW1lXCI7XG4gICAgICAgICAgICB0aW1lci5hbmltYXRpb24gPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRpbWVyLmhhc093blByb3BlcnR5KFwiaWRsZUNhbGxiYWNrXCIpKSB7XG4gICAgICAgICAgICB0aW1lci50eXBlID0gXCJJZGxlQ2FsbGJhY2tcIjtcbiAgICAgICAgICAgIHRpbWVyLmlkbGVDYWxsYmFjayA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWNsb2NrLnRpbWVycykge1xuICAgICAgICAgICAgY2xvY2sudGltZXJzID0ge307XG4gICAgICAgIH1cblxuICAgICAgICB0aW1lci5pZCA9IHVuaXF1ZVRpbWVySWQrKztcbiAgICAgICAgdGltZXIuY3JlYXRlZEF0ID0gY2xvY2subm93O1xuICAgICAgICB0aW1lci5jYWxsQXQgPVxuICAgICAgICAgICAgY2xvY2subm93ICsgKHBhcnNlSW50KHRpbWVyLmRlbGF5KSB8fCAoY2xvY2suZHVyaW5nVGljayA/IDEgOiAwKSk7XG5cbiAgICAgICAgY2xvY2sudGltZXJzW3RpbWVyLmlkXSA9IHRpbWVyO1xuXG4gICAgICAgIGlmIChhZGRUaW1lclJldHVybnNPYmplY3QpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlcyA9IHtcbiAgICAgICAgICAgICAgICByZWZlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgICByZWY6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWZlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB1bnJlZjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlZmVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBoYXNSZWY6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVmZWQ7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICByZWZyZXNoOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRpbWVyLmNhbGxBdCA9XG4gICAgICAgICAgICAgICAgICAgICAgICBjbG9jay5ub3cgK1xuICAgICAgICAgICAgICAgICAgICAgICAgKHBhcnNlSW50KHRpbWVyLmRlbGF5KSB8fCAoY2xvY2suZHVyaW5nVGljayA/IDEgOiAwKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gaXQgX21pZ2h0XyBoYXZlIGJlZW4gcmVtb3ZlZCwgYnV0IGlmIG5vdCB0aGUgYXNzaWdubWVudCBpcyBwZXJmZWN0bHkgZmluZVxuICAgICAgICAgICAgICAgICAgICBjbG9jay50aW1lcnNbdGltZXIuaWRdID0gdGltZXI7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIFtTeW1ib2wudG9QcmltaXRpdmVdOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aW1lci5pZDtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGltZXIuaWQ7XG4gICAgfVxuXG4gICAgLyogZXNsaW50IGNvbnNpc3RlbnQtcmV0dXJuOiBcIm9mZlwiICovXG4gICAgLyoqXG4gICAgICogVGltZXIgY29tcGFyaXRvclxuICAgICAqXG4gICAgICogQHBhcmFtIHtUaW1lcn0gYVxuICAgICAqIEBwYXJhbSB7VGltZXJ9IGJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvbXBhcmVUaW1lcnMoYSwgYikge1xuICAgICAgICAvLyBTb3J0IGZpcnN0IGJ5IGFic29sdXRlIHRpbWluZ1xuICAgICAgICBpZiAoYS5jYWxsQXQgPCBiLmNhbGxBdCkge1xuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhLmNhbGxBdCA+IGIuY2FsbEF0KSB7XG4gICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNvcnQgbmV4dCBieSBpbW1lZGlhdGUsIGltbWVkaWF0ZSB0aW1lcnMgdGFrZSBwcmVjZWRlbmNlXG4gICAgICAgIGlmIChhLmltbWVkaWF0ZSAmJiAhYi5pbW1lZGlhdGUpIHtcbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWEuaW1tZWRpYXRlICYmIGIuaW1tZWRpYXRlKSB7XG4gICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNvcnQgbmV4dCBieSBjcmVhdGlvbiB0aW1lLCBlYXJsaWVyLWNyZWF0ZWQgdGltZXJzIHRha2UgcHJlY2VkZW5jZVxuICAgICAgICBpZiAoYS5jcmVhdGVkQXQgPCBiLmNyZWF0ZWRBdCkge1xuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhLmNyZWF0ZWRBdCA+IGIuY3JlYXRlZEF0KSB7XG4gICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNvcnQgbmV4dCBieSBpZCwgbG93ZXItaWQgdGltZXJzIHRha2UgcHJlY2VkZW5jZVxuICAgICAgICBpZiAoYS5pZCA8IGIuaWQpIHtcbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYS5pZCA+IGIuaWQpIHtcbiAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQXMgdGltZXIgaWRzIGFyZSB1bmlxdWUsIG5vIGZhbGxiYWNrIGAwYCBpcyBuZWNlc3NhcnlcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge0Nsb2NrfSBjbG9ja1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBmcm9tXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHRvXG4gICAgICogQHJldHVybnMge1RpbWVyfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGZpcnN0VGltZXJJblJhbmdlKGNsb2NrLCBmcm9tLCB0bykge1xuICAgICAgICBjb25zdCB0aW1lcnMgPSBjbG9jay50aW1lcnM7XG4gICAgICAgIGxldCB0aW1lciA9IG51bGw7XG4gICAgICAgIGxldCBpZCwgaXNJblJhbmdlO1xuXG4gICAgICAgIGZvciAoaWQgaW4gdGltZXJzKSB7XG4gICAgICAgICAgICBpZiAodGltZXJzLmhhc093blByb3BlcnR5KGlkKSkge1xuICAgICAgICAgICAgICAgIGlzSW5SYW5nZSA9IGluUmFuZ2UoZnJvbSwgdG8sIHRpbWVyc1tpZF0pO1xuXG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICBpc0luUmFuZ2UgJiZcbiAgICAgICAgICAgICAgICAgICAgKCF0aW1lciB8fCBjb21wYXJlVGltZXJzKHRpbWVyLCB0aW1lcnNbaWRdKSA9PT0gMSlcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgdGltZXIgPSB0aW1lcnNbaWRdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aW1lcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge0Nsb2NrfSBjbG9ja1xuICAgICAqIEByZXR1cm5zIHtUaW1lcn1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmaXJzdFRpbWVyKGNsb2NrKSB7XG4gICAgICAgIGNvbnN0IHRpbWVycyA9IGNsb2NrLnRpbWVycztcbiAgICAgICAgbGV0IHRpbWVyID0gbnVsbDtcbiAgICAgICAgbGV0IGlkO1xuXG4gICAgICAgIGZvciAoaWQgaW4gdGltZXJzKSB7XG4gICAgICAgICAgICBpZiAodGltZXJzLmhhc093blByb3BlcnR5KGlkKSkge1xuICAgICAgICAgICAgICAgIGlmICghdGltZXIgfHwgY29tcGFyZVRpbWVycyh0aW1lciwgdGltZXJzW2lkXSkgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGltZXIgPSB0aW1lcnNbaWRdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aW1lcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge0Nsb2NrfSBjbG9ja1xuICAgICAqIEByZXR1cm5zIHtUaW1lcn1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBsYXN0VGltZXIoY2xvY2spIHtcbiAgICAgICAgY29uc3QgdGltZXJzID0gY2xvY2sudGltZXJzO1xuICAgICAgICBsZXQgdGltZXIgPSBudWxsO1xuICAgICAgICBsZXQgaWQ7XG5cbiAgICAgICAgZm9yIChpZCBpbiB0aW1lcnMpIHtcbiAgICAgICAgICAgIGlmICh0aW1lcnMuaGFzT3duUHJvcGVydHkoaWQpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aW1lciB8fCBjb21wYXJlVGltZXJzKHRpbWVyLCB0aW1lcnNbaWRdKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGltZXIgPSB0aW1lcnNbaWRdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aW1lcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge0Nsb2NrfSBjbG9ja1xuICAgICAqIEBwYXJhbSB7VGltZXJ9IHRpbWVyXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2FsbFRpbWVyKGNsb2NrLCB0aW1lcikge1xuICAgICAgICBpZiAodHlwZW9mIHRpbWVyLmludGVydmFsID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICBjbG9jay50aW1lcnNbdGltZXIuaWRdLmNhbGxBdCArPSB0aW1lci5pbnRlcnZhbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRlbGV0ZSBjbG9jay50aW1lcnNbdGltZXIuaWRdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiB0aW1lci5mdW5jID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHRpbWVyLmZ1bmMuYXBwbHkobnVsbCwgdGltZXIuYXJncyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvKiBlc2xpbnQgbm8tZXZhbDogXCJvZmZcIiAqL1xuICAgICAgICAgICAgY29uc3QgZXZhbDIgPSBldmFsO1xuICAgICAgICAgICAgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBldmFsMih0aW1lci5mdW5jKTtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIGNsZWFyIGhhbmRsZXIgbmFtZSBmb3IgYSBnaXZlbiB0aW1lciB0eXBlXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdHR5cGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBnZXRDbGVhckhhbmRsZXIodHR5cGUpIHtcbiAgICAgICAgaWYgKHR0eXBlID09PSBcIklkbGVDYWxsYmFja1wiIHx8IHR0eXBlID09PSBcIkFuaW1hdGlvbkZyYW1lXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBgY2FuY2VsJHt0dHlwZX1gO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBgY2xlYXIke3R0eXBlfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyBzY2hlZHVsZSBoYW5kbGVyIG5hbWUgZm9yIGEgZ2l2ZW4gdGltZXIgdHlwZVxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHR0eXBlXG4gICAgICovXG4gICAgZnVuY3Rpb24gZ2V0U2NoZWR1bGVIYW5kbGVyKHR0eXBlKSB7XG4gICAgICAgIGlmICh0dHlwZSA9PT0gXCJJZGxlQ2FsbGJhY2tcIiB8fCB0dHlwZSA9PT0gXCJBbmltYXRpb25GcmFtZVwiKSB7XG4gICAgICAgICAgICByZXR1cm4gYHJlcXVlc3Qke3R0eXBlfWA7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGBzZXQke3R0eXBlfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhbiBhbm9ueW1vdXMgZnVuY3Rpb24gdG8gd2FybiBvbmx5IG9uY2VcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmVhdGVXYXJuT25jZSgpIHtcbiAgICAgICAgbGV0IGNhbGxzID0gMDtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChtc2cpIHtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgICAgICAgICAgIWNhbGxzKysgJiYgY29uc29sZS53YXJuKG1zZyk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIGNvbnN0IHdhcm5PbmNlID0gY3JlYXRlV2Fybk9uY2UoKTtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7Q2xvY2t9IGNsb2NrXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHRpbWVySWRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdHR5cGVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjbGVhclRpbWVyKGNsb2NrLCB0aW1lcklkLCB0dHlwZSkge1xuICAgICAgICBpZiAoIXRpbWVySWQpIHtcbiAgICAgICAgICAgIC8vIG51bGwgYXBwZWFycyB0byBiZSBhbGxvd2VkIGluIG1vc3QgYnJvd3NlcnMsIGFuZCBhcHBlYXJzIHRvIGJlXG4gICAgICAgICAgICAvLyByZWxpZWQgdXBvbiBieSBzb21lIGxpYnJhcmllcywgbGlrZSBCb290c3RyYXAgY2Fyb3VzZWxcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghY2xvY2sudGltZXJzKSB7XG4gICAgICAgICAgICBjbG9jay50aW1lcnMgPSB7fTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGluIE5vZGUsIHRoZSBJRCBpcyBzdG9yZWQgYXMgdGhlIHByaW1pdGl2ZSB2YWx1ZSBmb3IgYFRpbWVvdXRgIG9iamVjdHNcbiAgICAgICAgLy8gZm9yIGBJbW1lZGlhdGVgIG9iamVjdHMsIG5vIElEIGV4aXN0cywgc28gaXQgZ2V0cyBjb2VyY2VkIHRvIE5hTlxuICAgICAgICBjb25zdCBpZCA9IE51bWJlcih0aW1lcklkKTtcblxuICAgICAgICBpZiAoTnVtYmVyLmlzTmFOKGlkKSB8fCBpZCA8IGlkQ291bnRlclN0YXJ0KSB7XG4gICAgICAgICAgICBjb25zdCBoYW5kbGVyTmFtZSA9IGdldENsZWFySGFuZGxlcih0dHlwZSk7XG5cbiAgICAgICAgICAgIGlmIChjbG9jay5zaG91bGRDbGVhck5hdGl2ZVRpbWVycyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG5hdGl2ZUhhbmRsZXIgPSBjbG9ja1tgXyR7aGFuZGxlck5hbWV9YF07XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBuYXRpdmVIYW5kbGVyID09PSBcImZ1bmN0aW9uXCJcbiAgICAgICAgICAgICAgICAgICAgPyBuYXRpdmVIYW5kbGVyKHRpbWVySWQpXG4gICAgICAgICAgICAgICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd2Fybk9uY2UoXG4gICAgICAgICAgICAgICAgYEZha2VUaW1lcnM6ICR7aGFuZGxlck5hbWV9IHdhcyBpbnZva2VkIHRvIGNsZWFyIGEgbmF0aXZlIHRpbWVyIGluc3RlYWQgb2Ygb25lIGNyZWF0ZWQgYnkgdGhpcyBsaWJyYXJ5LmAgK1xuICAgICAgICAgICAgICAgICAgICBcIlxcblRvIGF1dG9tYXRpY2FsbHkgY2xlYW4tdXAgbmF0aXZlIHRpbWVycywgdXNlIGBzaG91bGRDbGVhck5hdGl2ZVRpbWVyc2AuXCIsXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNsb2NrLnRpbWVycy5oYXNPd25Qcm9wZXJ0eShpZCkpIHtcbiAgICAgICAgICAgIC8vIGNoZWNrIHRoYXQgdGhlIElEIG1hdGNoZXMgYSB0aW1lciBvZiB0aGUgY29ycmVjdCB0eXBlXG4gICAgICAgICAgICBjb25zdCB0aW1lciA9IGNsb2NrLnRpbWVyc1tpZF07XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgdGltZXIudHlwZSA9PT0gdHR5cGUgfHxcbiAgICAgICAgICAgICAgICAodGltZXIudHlwZSA9PT0gXCJUaW1lb3V0XCIgJiYgdHR5cGUgPT09IFwiSW50ZXJ2YWxcIikgfHxcbiAgICAgICAgICAgICAgICAodGltZXIudHlwZSA9PT0gXCJJbnRlcnZhbFwiICYmIHR0eXBlID09PSBcIlRpbWVvdXRcIilcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBjbG9jay50aW1lcnNbaWRdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjbGVhciA9IGdldENsZWFySGFuZGxlcih0dHlwZSk7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2NoZWR1bGUgPSBnZXRTY2hlZHVsZUhhbmRsZXIodGltZXIudHlwZSk7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgICAgICAgICBgQ2Fubm90IGNsZWFyIHRpbWVyOiB0aW1lciBjcmVhdGVkIHdpdGggJHtzY2hlZHVsZX0oKSBidXQgY2xlYXJlZCB3aXRoICR7Y2xlYXJ9KClgLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge0Nsb2NrfSBjbG9ja1xuICAgICAqIEBwYXJhbSB7Q29uZmlnfSBjb25maWdcbiAgICAgKiBAcmV0dXJucyB7VGltZXJbXX1cbiAgICAgKi9cbiAgICBmdW5jdGlvbiB1bmluc3RhbGwoY2xvY2ssIGNvbmZpZykge1xuICAgICAgICBsZXQgbWV0aG9kLCBpLCBsO1xuICAgICAgICBjb25zdCBpbnN0YWxsZWRIclRpbWUgPSBcIl9ocnRpbWVcIjtcbiAgICAgICAgY29uc3QgaW5zdGFsbGVkTmV4dFRpY2sgPSBcIl9uZXh0VGlja1wiO1xuXG4gICAgICAgIGZvciAoaSA9IDAsIGwgPSBjbG9jay5tZXRob2RzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgbWV0aG9kID0gY2xvY2subWV0aG9kc1tpXTtcbiAgICAgICAgICAgIGlmIChtZXRob2QgPT09IFwiaHJ0aW1lXCIgJiYgX2dsb2JhbC5wcm9jZXNzKSB7XG4gICAgICAgICAgICAgICAgX2dsb2JhbC5wcm9jZXNzLmhydGltZSA9IGNsb2NrW2luc3RhbGxlZEhyVGltZV07XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG1ldGhvZCA9PT0gXCJuZXh0VGlja1wiICYmIF9nbG9iYWwucHJvY2Vzcykge1xuICAgICAgICAgICAgICAgIF9nbG9iYWwucHJvY2Vzcy5uZXh0VGljayA9IGNsb2NrW2luc3RhbGxlZE5leHRUaWNrXTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobWV0aG9kID09PSBcInBlcmZvcm1hbmNlXCIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBvcmlnaW5hbFBlcmZEZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihcbiAgICAgICAgICAgICAgICAgICAgY2xvY2ssXG4gICAgICAgICAgICAgICAgICAgIGBfJHttZXRob2R9YCxcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgb3JpZ2luYWxQZXJmRGVzY3JpcHRvciAmJlxuICAgICAgICAgICAgICAgICAgICBvcmlnaW5hbFBlcmZEZXNjcmlwdG9yLmdldCAmJlxuICAgICAgICAgICAgICAgICAgICAhb3JpZ2luYWxQZXJmRGVzY3JpcHRvci5zZXRcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFxuICAgICAgICAgICAgICAgICAgICAgICAgX2dsb2JhbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9yaWdpbmFsUGVyZkRlc2NyaXB0b3IsXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChvcmlnaW5hbFBlcmZEZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSkge1xuICAgICAgICAgICAgICAgICAgICBfZ2xvYmFsW21ldGhvZF0gPSBjbG9ja1tgXyR7bWV0aG9kfWBdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKF9nbG9iYWxbbWV0aG9kXSAmJiBfZ2xvYmFsW21ldGhvZF0uaGFkT3duUHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICAgICAgX2dsb2JhbFttZXRob2RdID0gY2xvY2tbYF8ke21ldGhvZH1gXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIF9nbG9iYWxbbWV0aG9kXTtcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoaWdub3JlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvKiBlc2xpbnQgbm8tZW1wdHk6IFwib2ZmXCIgKi9cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjbG9jay50aW1lcnNNb2R1bGVNZXRob2RzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGNsb2NrLnRpbWVyc01vZHVsZU1ldGhvZHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZW50cnkgPSBjbG9jay50aW1lcnNNb2R1bGVNZXRob2RzW2pdO1xuICAgICAgICAgICAgICAgICAgICB0aW1lcnNNb2R1bGVbZW50cnkubWV0aG9kTmFtZV0gPSBlbnRyeS5vcmlnaW5hbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoY2xvY2sudGltZXJzUHJvbWlzZXNNb2R1bGVNZXRob2RzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBmb3IgKFxuICAgICAgICAgICAgICAgICAgICBsZXQgaiA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGogPCBjbG9jay50aW1lcnNQcm9taXNlc01vZHVsZU1ldGhvZHMubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBqKytcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZW50cnkgPSBjbG9jay50aW1lcnNQcm9taXNlc01vZHVsZU1ldGhvZHNbal07XG4gICAgICAgICAgICAgICAgICAgIHRpbWVyc1Byb21pc2VzTW9kdWxlW2VudHJ5Lm1ldGhvZE5hbWVdID0gZW50cnkub3JpZ2luYWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNvbmZpZy5zaG91bGRBZHZhbmNlVGltZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgX2dsb2JhbC5jbGVhckludGVydmFsKGNsb2NrLmF0dGFjaGVkSW50ZXJ2YWwpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUHJldmVudCBtdWx0aXBsZSBleGVjdXRpb25zIHdoaWNoIHdpbGwgY29tcGxldGVseSByZW1vdmUgdGhlc2UgcHJvcHNcbiAgICAgICAgY2xvY2subWV0aG9kcyA9IFtdO1xuXG4gICAgICAgIGZvciAoY29uc3QgW2xpc3RlbmVyLCBzaWduYWxdIG9mIGNsb2NrLmFib3J0TGlzdGVuZXJNYXAuZW50cmllcygpKSB7XG4gICAgICAgICAgICBzaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsIGxpc3RlbmVyKTtcbiAgICAgICAgICAgIGNsb2NrLmFib3J0TGlzdGVuZXJNYXAuZGVsZXRlKGxpc3RlbmVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJldHVybiBwZW5kaW5nIHRpbWVycywgdG8gZW5hYmxlIGNoZWNraW5nIHdoYXQgdGltZXJzIHJlbWFpbmVkIG9uIHVuaW5zdGFsbFxuICAgICAgICBpZiAoIWNsb2NrLnRpbWVycykge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyhjbG9jay50aW1lcnMpLm1hcChmdW5jdGlvbiBtYXBwZXIoa2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gY2xvY2sudGltZXJzW2tleV07XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSB0YXJnZXQgdGhlIHRhcmdldCBjb250YWluaW5nIHRoZSBtZXRob2QgdG8gcmVwbGFjZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2QgdGhlIGtleW5hbWUgb2YgdGhlIG1ldGhvZCBvbiB0aGUgdGFyZ2V0XG4gICAgICogQHBhcmFtIHtDbG9ja30gY2xvY2tcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBoaWphY2tNZXRob2QodGFyZ2V0LCBtZXRob2QsIGNsb2NrKSB7XG4gICAgICAgIGNsb2NrW21ldGhvZF0uaGFkT3duUHJvcGVydHkgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoXG4gICAgICAgICAgICB0YXJnZXQsXG4gICAgICAgICAgICBtZXRob2QsXG4gICAgICAgICk7XG4gICAgICAgIGNsb2NrW2BfJHttZXRob2R9YF0gPSB0YXJnZXRbbWV0aG9kXTtcblxuICAgICAgICBpZiAobWV0aG9kID09PSBcIkRhdGVcIikge1xuICAgICAgICAgICAgdGFyZ2V0W21ldGhvZF0gPSBjbG9ja1ttZXRob2RdO1xuICAgICAgICB9IGVsc2UgaWYgKG1ldGhvZCA9PT0gXCJJbnRsXCIpIHtcbiAgICAgICAgICAgIHRhcmdldFttZXRob2RdID0gY2xvY2tbbWV0aG9kXTtcbiAgICAgICAgfSBlbHNlIGlmIChtZXRob2QgPT09IFwicGVyZm9ybWFuY2VcIikge1xuICAgICAgICAgICAgY29uc3Qgb3JpZ2luYWxQZXJmRGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoXG4gICAgICAgICAgICAgICAgdGFyZ2V0LFxuICAgICAgICAgICAgICAgIG1ldGhvZCxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICAvLyBKU0RPTSBoYXMgYSByZWFkIG9ubHkgcGVyZm9ybWFuY2UgZmllbGQgc28gd2UgaGF2ZSB0byBzYXZlL2NvcHkgaXQgZGlmZmVyZW50bHlcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBvcmlnaW5hbFBlcmZEZXNjcmlwdG9yICYmXG4gICAgICAgICAgICAgICAgb3JpZ2luYWxQZXJmRGVzY3JpcHRvci5nZXQgJiZcbiAgICAgICAgICAgICAgICAhb3JpZ2luYWxQZXJmRGVzY3JpcHRvci5zZXRcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShcbiAgICAgICAgICAgICAgICAgICAgY2xvY2ssXG4gICAgICAgICAgICAgICAgICAgIGBfJHttZXRob2R9YCxcbiAgICAgICAgICAgICAgICAgICAgb3JpZ2luYWxQZXJmRGVzY3JpcHRvcixcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgY29uc3QgcGVyZkRlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKFxuICAgICAgICAgICAgICAgICAgICBjbG9jayxcbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgbWV0aG9kLCBwZXJmRGVzY3JpcHRvcik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRhcmdldFttZXRob2RdID0gY2xvY2tbbWV0aG9kXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRhcmdldFttZXRob2RdID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjbG9ja1ttZXRob2RdLmFwcGx5KGNsb2NrLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoXG4gICAgICAgICAgICAgICAgdGFyZ2V0W21ldGhvZF0sXG4gICAgICAgICAgICAgICAgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMoY2xvY2tbbWV0aG9kXSksXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGFyZ2V0W21ldGhvZF0uY2xvY2sgPSBjbG9jaztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0ge0Nsb2NrfSBjbG9ja1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBhZHZhbmNlVGltZURlbHRhXG4gICAgICovXG4gICAgZnVuY3Rpb24gZG9JbnRlcnZhbFRpY2soY2xvY2ssIGFkdmFuY2VUaW1lRGVsdGEpIHtcbiAgICAgICAgY2xvY2sudGljayhhZHZhbmNlVGltZURlbHRhKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAdHlwZWRlZiB7b2JqZWN0fSBUaW1lcnNcbiAgICAgKiBAcHJvcGVydHkge3NldFRpbWVvdXR9IHNldFRpbWVvdXRcbiAgICAgKiBAcHJvcGVydHkge2NsZWFyVGltZW91dH0gY2xlYXJUaW1lb3V0XG4gICAgICogQHByb3BlcnR5IHtzZXRJbnRlcnZhbH0gc2V0SW50ZXJ2YWxcbiAgICAgKiBAcHJvcGVydHkge2NsZWFySW50ZXJ2YWx9IGNsZWFySW50ZXJ2YWxcbiAgICAgKiBAcHJvcGVydHkge0RhdGV9IERhdGVcbiAgICAgKiBAcHJvcGVydHkge0ludGx9IEludGxcbiAgICAgKiBAcHJvcGVydHkge1NldEltbWVkaWF0ZT19IHNldEltbWVkaWF0ZVxuICAgICAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24oTm9kZUltbWVkaWF0ZSk6IHZvaWQ9fSBjbGVhckltbWVkaWF0ZVxuICAgICAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24obnVtYmVyW10pOm51bWJlcltdPX0gaHJ0aW1lXG4gICAgICogQHByb3BlcnR5IHtOZXh0VGljaz19IG5leHRUaWNrXG4gICAgICogQHByb3BlcnR5IHtQZXJmb3JtYW5jZT19IHBlcmZvcm1hbmNlXG4gICAgICogQHByb3BlcnR5IHtSZXF1ZXN0QW5pbWF0aW9uRnJhbWU9fSByZXF1ZXN0QW5pbWF0aW9uRnJhbWVcbiAgICAgKiBAcHJvcGVydHkge2Jvb2xlYW49fSBxdWV1ZU1pY3JvdGFza1xuICAgICAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24obnVtYmVyKTogdm9pZD19IGNhbmNlbEFuaW1hdGlvbkZyYW1lXG4gICAgICogQHByb3BlcnR5IHtSZXF1ZXN0SWRsZUNhbGxiYWNrPX0gcmVxdWVzdElkbGVDYWxsYmFja1xuICAgICAqIEBwcm9wZXJ0eSB7ZnVuY3Rpb24obnVtYmVyKTogdm9pZD19IGNhbmNlbElkbGVDYWxsYmFja1xuICAgICAqL1xuXG4gICAgLyoqIEB0eXBlIHtUaW1lcnN9ICovXG4gICAgY29uc3QgdGltZXJzID0ge1xuICAgICAgICBzZXRUaW1lb3V0OiBfZ2xvYmFsLnNldFRpbWVvdXQsXG4gICAgICAgIGNsZWFyVGltZW91dDogX2dsb2JhbC5jbGVhclRpbWVvdXQsXG4gICAgICAgIHNldEludGVydmFsOiBfZ2xvYmFsLnNldEludGVydmFsLFxuICAgICAgICBjbGVhckludGVydmFsOiBfZ2xvYmFsLmNsZWFySW50ZXJ2YWwsXG4gICAgICAgIERhdGU6IF9nbG9iYWwuRGF0ZSxcbiAgICB9O1xuXG4gICAgaWYgKGlzUHJlc2VudC5zZXRJbW1lZGlhdGUpIHtcbiAgICAgICAgdGltZXJzLnNldEltbWVkaWF0ZSA9IF9nbG9iYWwuc2V0SW1tZWRpYXRlO1xuICAgIH1cblxuICAgIGlmIChpc1ByZXNlbnQuY2xlYXJJbW1lZGlhdGUpIHtcbiAgICAgICAgdGltZXJzLmNsZWFySW1tZWRpYXRlID0gX2dsb2JhbC5jbGVhckltbWVkaWF0ZTtcbiAgICB9XG5cbiAgICBpZiAoaXNQcmVzZW50LmhydGltZSkge1xuICAgICAgICB0aW1lcnMuaHJ0aW1lID0gX2dsb2JhbC5wcm9jZXNzLmhydGltZTtcbiAgICB9XG5cbiAgICBpZiAoaXNQcmVzZW50Lm5leHRUaWNrKSB7XG4gICAgICAgIHRpbWVycy5uZXh0VGljayA9IF9nbG9iYWwucHJvY2Vzcy5uZXh0VGljaztcbiAgICB9XG5cbiAgICBpZiAoaXNQcmVzZW50LnBlcmZvcm1hbmNlKSB7XG4gICAgICAgIHRpbWVycy5wZXJmb3JtYW5jZSA9IF9nbG9iYWwucGVyZm9ybWFuY2U7XG4gICAgfVxuXG4gICAgaWYgKGlzUHJlc2VudC5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUpIHtcbiAgICAgICAgdGltZXJzLnJlcXVlc3RBbmltYXRpb25GcmFtZSA9IF9nbG9iYWwucmVxdWVzdEFuaW1hdGlvbkZyYW1lO1xuICAgIH1cblxuICAgIGlmIChpc1ByZXNlbnQucXVldWVNaWNyb3Rhc2spIHtcbiAgICAgICAgdGltZXJzLnF1ZXVlTWljcm90YXNrID0gX2dsb2JhbC5xdWV1ZU1pY3JvdGFzaztcbiAgICB9XG5cbiAgICBpZiAoaXNQcmVzZW50LmNhbmNlbEFuaW1hdGlvbkZyYW1lKSB7XG4gICAgICAgIHRpbWVycy5jYW5jZWxBbmltYXRpb25GcmFtZSA9IF9nbG9iYWwuY2FuY2VsQW5pbWF0aW9uRnJhbWU7XG4gICAgfVxuXG4gICAgaWYgKGlzUHJlc2VudC5yZXF1ZXN0SWRsZUNhbGxiYWNrKSB7XG4gICAgICAgIHRpbWVycy5yZXF1ZXN0SWRsZUNhbGxiYWNrID0gX2dsb2JhbC5yZXF1ZXN0SWRsZUNhbGxiYWNrO1xuICAgIH1cblxuICAgIGlmIChpc1ByZXNlbnQuY2FuY2VsSWRsZUNhbGxiYWNrKSB7XG4gICAgICAgIHRpbWVycy5jYW5jZWxJZGxlQ2FsbGJhY2sgPSBfZ2xvYmFsLmNhbmNlbElkbGVDYWxsYmFjaztcbiAgICB9XG5cbiAgICBpZiAoaXNQcmVzZW50LkludGwpIHtcbiAgICAgICAgdGltZXJzLkludGwgPSBfZ2xvYmFsLkludGw7XG4gICAgfVxuXG4gICAgY29uc3Qgb3JpZ2luYWxTZXRUaW1lb3V0ID0gX2dsb2JhbC5zZXRJbW1lZGlhdGUgfHwgX2dsb2JhbC5zZXRUaW1lb3V0O1xuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHtEYXRlfG51bWJlcn0gW3N0YXJ0XSB0aGUgc3lzdGVtIHRpbWUgLSBub24taW50ZWdlciB2YWx1ZXMgYXJlIGZsb29yZWRcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW2xvb3BMaW1pdF0gbWF4aW11bSBudW1iZXIgb2YgdGltZXJzIHRoYXQgd2lsbCBiZSBydW4gd2hlbiBjYWxsaW5nIHJ1bkFsbCgpXG4gICAgICogQHJldHVybnMge0Nsb2NrfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZUNsb2NrKHN0YXJ0LCBsb29wTGltaXQpIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXBhcmFtLXJlYXNzaWduXG4gICAgICAgIHN0YXJ0ID0gTWF0aC5mbG9vcihnZXRFcG9jaChzdGFydCkpO1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcGFyYW0tcmVhc3NpZ25cbiAgICAgICAgbG9vcExpbWl0ID0gbG9vcExpbWl0IHx8IDEwMDA7XG4gICAgICAgIGxldCBuYW5vcyA9IDA7XG4gICAgICAgIGNvbnN0IGFkanVzdGVkU3lzdGVtVGltZSA9IFswLCAwXTsgLy8gW21pbGxpcywgbmFub3JlbWFpbmRlcl1cblxuICAgICAgICBjb25zdCBjbG9jayA9IHtcbiAgICAgICAgICAgIG5vdzogc3RhcnQsXG4gICAgICAgICAgICBEYXRlOiBjcmVhdGVEYXRlKCksXG4gICAgICAgICAgICBsb29wTGltaXQ6IGxvb3BMaW1pdCxcbiAgICAgICAgfTtcblxuICAgICAgICBjbG9jay5EYXRlLmNsb2NrID0gY2xvY2s7XG5cbiAgICAgICAgLy9lc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUganNkb2MvcmVxdWlyZS1qc2RvY1xuICAgICAgICBmdW5jdGlvbiBnZXRUaW1lVG9OZXh0RnJhbWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gMTYgLSAoKGNsb2NrLm5vdyAtIHN0YXJ0KSAlIDE2KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGpzZG9jL3JlcXVpcmUtanNkb2NcbiAgICAgICAgZnVuY3Rpb24gaHJ0aW1lKHByZXYpIHtcbiAgICAgICAgICAgIGNvbnN0IG1pbGxpc1NpbmNlU3RhcnQgPSBjbG9jay5ub3cgLSBhZGp1c3RlZFN5c3RlbVRpbWVbMF0gLSBzdGFydDtcbiAgICAgICAgICAgIGNvbnN0IHNlY3NTaW5jZVN0YXJ0ID0gTWF0aC5mbG9vcihtaWxsaXNTaW5jZVN0YXJ0IC8gMTAwMCk7XG4gICAgICAgICAgICBjb25zdCByZW1haW5kZXJJbk5hbm9zID1cbiAgICAgICAgICAgICAgICAobWlsbGlzU2luY2VTdGFydCAtIHNlY3NTaW5jZVN0YXJ0ICogMWUzKSAqIDFlNiArXG4gICAgICAgICAgICAgICAgbmFub3MgLVxuICAgICAgICAgICAgICAgIGFkanVzdGVkU3lzdGVtVGltZVsxXTtcblxuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocHJldikpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldlsxXSA+IDFlOSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgXCJOdW1iZXIgb2YgbmFub3NlY29uZHMgY2FuJ3QgZXhjZWVkIGEgYmlsbGlvblwiLFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNvbnN0IG9sZFNlY3MgPSBwcmV2WzBdO1xuICAgICAgICAgICAgICAgIGxldCBuYW5vRGlmZiA9IHJlbWFpbmRlckluTmFub3MgLSBwcmV2WzFdO1xuICAgICAgICAgICAgICAgIGxldCBzZWNEaWZmID0gc2Vjc1NpbmNlU3RhcnQgLSBvbGRTZWNzO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5hbm9EaWZmIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICBuYW5vRGlmZiArPSAxZTk7XG4gICAgICAgICAgICAgICAgICAgIHNlY0RpZmYgLT0gMTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gW3NlY0RpZmYsIG5hbm9EaWZmXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBbc2Vjc1NpbmNlU3RhcnQsIHJlbWFpbmRlckluTmFub3NdO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEEgaGlnaCByZXNvbHV0aW9uIHRpbWVzdGFtcCBpbiBtaWxsaXNlY29uZHMuXG4gICAgICAgICAqXG4gICAgICAgICAqIEB0eXBlZGVmIHtudW1iZXJ9IERPTUhpZ2hSZXNUaW1lU3RhbXBcbiAgICAgICAgICovXG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIHBlcmZvcm1hbmNlLm5vdygpXG4gICAgICAgICAqXG4gICAgICAgICAqIEByZXR1cm5zIHtET01IaWdoUmVzVGltZVN0YW1wfVxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gZmFrZVBlcmZvcm1hbmNlTm93KCkge1xuICAgICAgICAgICAgY29uc3QgaHJ0ID0gaHJ0aW1lKCk7XG4gICAgICAgICAgICBjb25zdCBtaWxsaXMgPSBocnRbMF0gKiAxMDAwICsgaHJ0WzFdIC8gMWU2O1xuICAgICAgICAgICAgcmV0dXJuIG1pbGxpcztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc1ByZXNlbnQuaHJ0aW1lQmlnaW50KSB7XG4gICAgICAgICAgICBocnRpbWUuYmlnaW50ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhcnRzID0gaHJ0aW1lKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEJpZ0ludChwYXJ0c1swXSkgKiBCaWdJbnQoMWU5KSArIEJpZ0ludChwYXJ0c1sxXSk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmVcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXNQcmVzZW50LkludGwpIHtcbiAgICAgICAgICAgIGNsb2NrLkludGwgPSBjcmVhdGVJbnRsKCk7XG4gICAgICAgICAgICBjbG9jay5JbnRsLmNsb2NrID0gY2xvY2s7XG4gICAgICAgIH1cblxuICAgICAgICBjbG9jay5yZXF1ZXN0SWRsZUNhbGxiYWNrID0gZnVuY3Rpb24gcmVxdWVzdElkbGVDYWxsYmFjayhcbiAgICAgICAgICAgIGZ1bmMsXG4gICAgICAgICAgICB0aW1lb3V0LFxuICAgICAgICApIHtcbiAgICAgICAgICAgIGxldCB0aW1lVG9OZXh0SWRsZVBlcmlvZCA9IDA7XG5cbiAgICAgICAgICAgIGlmIChjbG9jay5jb3VudFRpbWVycygpID4gMCkge1xuICAgICAgICAgICAgICAgIHRpbWVUb05leHRJZGxlUGVyaW9kID0gNTA7IC8vIGNvbnN0IGZvciBub3dcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYWRkVGltZXIoY2xvY2ssIHtcbiAgICAgICAgICAgICAgICBmdW5jOiBmdW5jLFxuICAgICAgICAgICAgICAgIGFyZ3M6IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMiksXG4gICAgICAgICAgICAgICAgZGVsYXk6XG4gICAgICAgICAgICAgICAgICAgIHR5cGVvZiB0aW1lb3V0ID09PSBcInVuZGVmaW5lZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICA/IHRpbWVUb05leHRJZGxlUGVyaW9kXG4gICAgICAgICAgICAgICAgICAgICAgICA6IE1hdGgubWluKHRpbWVvdXQsIHRpbWVUb05leHRJZGxlUGVyaW9kKSxcbiAgICAgICAgICAgICAgICBpZGxlQ2FsbGJhY2s6IHRydWUsXG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgcmV0dXJuIE51bWJlcihyZXN1bHQpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNsb2NrLmNhbmNlbElkbGVDYWxsYmFjayA9IGZ1bmN0aW9uIGNhbmNlbElkbGVDYWxsYmFjayh0aW1lcklkKSB7XG4gICAgICAgICAgICByZXR1cm4gY2xlYXJUaW1lcihjbG9jaywgdGltZXJJZCwgXCJJZGxlQ2FsbGJhY2tcIik7XG4gICAgICAgIH07XG5cbiAgICAgICAgY2xvY2suc2V0VGltZW91dCA9IGZ1bmN0aW9uIHNldFRpbWVvdXQoZnVuYywgdGltZW91dCkge1xuICAgICAgICAgICAgcmV0dXJuIGFkZFRpbWVyKGNsb2NrLCB7XG4gICAgICAgICAgICAgICAgZnVuYzogZnVuYyxcbiAgICAgICAgICAgICAgICBhcmdzOiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpLFxuICAgICAgICAgICAgICAgIGRlbGF5OiB0aW1lb3V0LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG4gICAgICAgIGlmICh0eXBlb2YgX2dsb2JhbC5Qcm9taXNlICE9PSBcInVuZGVmaW5lZFwiICYmIHV0aWxQcm9taXNpZnkpIHtcbiAgICAgICAgICAgIGNsb2NrLnNldFRpbWVvdXRbdXRpbFByb21pc2lmeS5jdXN0b21dID1cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBwcm9taXNpZmllZFNldFRpbWVvdXQodGltZW91dCwgYXJnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgX2dsb2JhbC5Qcm9taXNlKGZ1bmN0aW9uIHNldFRpbWVvdXRFeGVjdXRvcihcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUsXG4gICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkVGltZXIoY2xvY2ssIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jOiByZXNvbHZlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3M6IFthcmddLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGF5OiB0aW1lb3V0LFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBjbG9jay5jbGVhclRpbWVvdXQgPSBmdW5jdGlvbiBjbGVhclRpbWVvdXQodGltZXJJZCkge1xuICAgICAgICAgICAgcmV0dXJuIGNsZWFyVGltZXIoY2xvY2ssIHRpbWVySWQsIFwiVGltZW91dFwiKTtcbiAgICAgICAgfTtcblxuICAgICAgICBjbG9jay5uZXh0VGljayA9IGZ1bmN0aW9uIG5leHRUaWNrKGZ1bmMpIHtcbiAgICAgICAgICAgIHJldHVybiBlbnF1ZXVlSm9iKGNsb2NrLCB7XG4gICAgICAgICAgICAgICAgZnVuYzogZnVuYyxcbiAgICAgICAgICAgICAgICBhcmdzOiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICAgICAgICAgIGVycm9yOiBpc05lYXJJbmZpbml0ZUxpbWl0ID8gbmV3IEVycm9yKCkgOiBudWxsLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgY2xvY2sucXVldWVNaWNyb3Rhc2sgPSBmdW5jdGlvbiBxdWV1ZU1pY3JvdGFzayhmdW5jKSB7XG4gICAgICAgICAgICByZXR1cm4gY2xvY2submV4dFRpY2soZnVuYyk7IC8vIGV4cGxpY2l0bHkgZHJvcCBhZGRpdGlvbmFsIGFyZ3VtZW50c1xuICAgICAgICB9O1xuXG4gICAgICAgIGNsb2NrLnNldEludGVydmFsID0gZnVuY3Rpb24gc2V0SW50ZXJ2YWwoZnVuYywgdGltZW91dCkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXBhcmFtLXJlYXNzaWduXG4gICAgICAgICAgICB0aW1lb3V0ID0gcGFyc2VJbnQodGltZW91dCwgMTApO1xuICAgICAgICAgICAgcmV0dXJuIGFkZFRpbWVyKGNsb2NrLCB7XG4gICAgICAgICAgICAgICAgZnVuYzogZnVuYyxcbiAgICAgICAgICAgICAgICBhcmdzOiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpLFxuICAgICAgICAgICAgICAgIGRlbGF5OiB0aW1lb3V0LFxuICAgICAgICAgICAgICAgIGludGVydmFsOiB0aW1lb3V0LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgY2xvY2suY2xlYXJJbnRlcnZhbCA9IGZ1bmN0aW9uIGNsZWFySW50ZXJ2YWwodGltZXJJZCkge1xuICAgICAgICAgICAgcmV0dXJuIGNsZWFyVGltZXIoY2xvY2ssIHRpbWVySWQsIFwiSW50ZXJ2YWxcIik7XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGlzUHJlc2VudC5zZXRJbW1lZGlhdGUpIHtcbiAgICAgICAgICAgIGNsb2NrLnNldEltbWVkaWF0ZSA9IGZ1bmN0aW9uIHNldEltbWVkaWF0ZShmdW5jKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFkZFRpbWVyKGNsb2NrLCB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmM6IGZ1bmMsXG4gICAgICAgICAgICAgICAgICAgIGFyZ3M6IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSksXG4gICAgICAgICAgICAgICAgICAgIGltbWVkaWF0ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgX2dsb2JhbC5Qcm9taXNlICE9PSBcInVuZGVmaW5lZFwiICYmIHV0aWxQcm9taXNpZnkpIHtcbiAgICAgICAgICAgICAgICBjbG9jay5zZXRJbW1lZGlhdGVbdXRpbFByb21pc2lmeS5jdXN0b21dID1cbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gcHJvbWlzaWZpZWRTZXRJbW1lZGlhdGUoYXJnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IF9nbG9iYWwuUHJvbWlzZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbiBzZXRJbW1lZGlhdGVFeGVjdXRvcihyZXNvbHZlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZFRpbWVyKGNsb2NrLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jOiByZXNvbHZlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJnczogW2FyZ10sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbW1lZGlhdGU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjbG9jay5jbGVhckltbWVkaWF0ZSA9IGZ1bmN0aW9uIGNsZWFySW1tZWRpYXRlKHRpbWVySWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2xlYXJUaW1lcihjbG9jaywgdGltZXJJZCwgXCJJbW1lZGlhdGVcIik7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY2xvY2suY291bnRUaW1lcnMgPSBmdW5jdGlvbiBjb3VudFRpbWVycygpIHtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgT2JqZWN0LmtleXMoY2xvY2sudGltZXJzIHx8IHt9KS5sZW5ndGggK1xuICAgICAgICAgICAgICAgIChjbG9jay5qb2JzIHx8IFtdKS5sZW5ndGhcbiAgICAgICAgICAgICk7XG4gICAgICAgIH07XG5cbiAgICAgICAgY2xvY2sucmVxdWVzdEFuaW1hdGlvbkZyYW1lID0gZnVuY3Rpb24gcmVxdWVzdEFuaW1hdGlvbkZyYW1lKGZ1bmMpIHtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGFkZFRpbWVyKGNsb2NrLCB7XG4gICAgICAgICAgICAgICAgZnVuYzogZnVuYyxcbiAgICAgICAgICAgICAgICBkZWxheTogZ2V0VGltZVRvTmV4dEZyYW1lKCksXG4gICAgICAgICAgICAgICAgZ2V0IGFyZ3MoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBbZmFrZVBlcmZvcm1hbmNlTm93KCldO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgYW5pbWF0aW9uOiB0cnVlLFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHJldHVybiBOdW1iZXIocmVzdWx0KTtcbiAgICAgICAgfTtcblxuICAgICAgICBjbG9jay5jYW5jZWxBbmltYXRpb25GcmFtZSA9IGZ1bmN0aW9uIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRpbWVySWQpIHtcbiAgICAgICAgICAgIHJldHVybiBjbGVhclRpbWVyKGNsb2NrLCB0aW1lcklkLCBcIkFuaW1hdGlvbkZyYW1lXCIpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGNsb2NrLnJ1bk1pY3JvdGFza3MgPSBmdW5jdGlvbiBydW5NaWNyb3Rhc2tzKCkge1xuICAgICAgICAgICAgcnVuSm9icyhjbG9jayk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ30gdGlja1ZhbHVlIG1pbGxpc2Vjb25kcyBvciBhIHN0cmluZyBwYXJzZWFibGUgYnkgcGFyc2VUaW1lXG4gICAgICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNBc3luY1xuICAgICAgICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSByZXNvbHZlXG4gICAgICAgICAqIEBwYXJhbSB7RnVuY3Rpb259IHJlamVjdFxuICAgICAgICAgKiBAcmV0dXJucyB7bnVtYmVyfHVuZGVmaW5lZH0gd2lsbCByZXR1cm4gdGhlIG5ldyBgbm93YCB2YWx1ZSBvciBub3RoaW5nIGZvciBhc3luY1xuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gZG9UaWNrKHRpY2tWYWx1ZSwgaXNBc3luYywgcmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgICBjb25zdCBtc0Zsb2F0ID1cbiAgICAgICAgICAgICAgICB0eXBlb2YgdGlja1ZhbHVlID09PSBcIm51bWJlclwiXG4gICAgICAgICAgICAgICAgICAgID8gdGlja1ZhbHVlXG4gICAgICAgICAgICAgICAgICAgIDogcGFyc2VUaW1lKHRpY2tWYWx1ZSk7XG4gICAgICAgICAgICBjb25zdCBtcyA9IE1hdGguZmxvb3IobXNGbG9hdCk7XG4gICAgICAgICAgICBjb25zdCByZW1haW5kZXIgPSBuYW5vUmVtYWluZGVyKG1zRmxvYXQpO1xuICAgICAgICAgICAgbGV0IG5hbm9zVG90YWwgPSBuYW5vcyArIHJlbWFpbmRlcjtcbiAgICAgICAgICAgIGxldCB0aWNrVG8gPSBjbG9jay5ub3cgKyBtcztcblxuICAgICAgICAgICAgaWYgKG1zRmxvYXQgPCAwKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk5lZ2F0aXZlIHRpY2tzIGFyZSBub3Qgc3VwcG9ydGVkXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBhZGp1c3QgZm9yIHBvc2l0aXZlIG92ZXJmbG93XG4gICAgICAgICAgICBpZiAobmFub3NUb3RhbCA+PSAxZTYpIHtcbiAgICAgICAgICAgICAgICB0aWNrVG8gKz0gMTtcbiAgICAgICAgICAgICAgICBuYW5vc1RvdGFsIC09IDFlNjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbmFub3MgPSBuYW5vc1RvdGFsO1xuICAgICAgICAgICAgbGV0IHRpY2tGcm9tID0gY2xvY2subm93O1xuICAgICAgICAgICAgbGV0IHByZXZpb3VzID0gY2xvY2subm93O1xuICAgICAgICAgICAgLy8gRVNMaW50IGZhaWxzIHRvIGRldGVjdCB0aGlzIGNvcnJlY3RseVxuICAgICAgICAgICAgLyogZXNsaW50LWRpc2FibGUgcHJlZmVyLWNvbnN0ICovXG4gICAgICAgICAgICBsZXQgdGltZXIsXG4gICAgICAgICAgICAgICAgZmlyc3RFeGNlcHRpb24sXG4gICAgICAgICAgICAgICAgb2xkTm93LFxuICAgICAgICAgICAgICAgIG5leHRQcm9taXNlVGljayxcbiAgICAgICAgICAgICAgICBjb21wZW5zYXRpb25DaGVjayxcbiAgICAgICAgICAgICAgICBwb3N0VGltZXJDYWxsO1xuICAgICAgICAgICAgLyogZXNsaW50LWVuYWJsZSBwcmVmZXItY29uc3QgKi9cblxuICAgICAgICAgICAgY2xvY2suZHVyaW5nVGljayA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIHBlcmZvcm0gbWljcm90YXNrc1xuICAgICAgICAgICAgb2xkTm93ID0gY2xvY2subm93O1xuICAgICAgICAgICAgcnVuSm9icyhjbG9jayk7XG4gICAgICAgICAgICBpZiAob2xkTm93ICE9PSBjbG9jay5ub3cpIHtcbiAgICAgICAgICAgICAgICAvLyBjb21wZW5zYXRlIGZvciBhbnkgc2V0U3lzdGVtVGltZSgpIGNhbGwgZHVyaW5nIG1pY3JvdGFzayBjYWxsYmFja1xuICAgICAgICAgICAgICAgIHRpY2tGcm9tICs9IGNsb2NrLm5vdyAtIG9sZE5vdztcbiAgICAgICAgICAgICAgICB0aWNrVG8gKz0gY2xvY2subm93IC0gb2xkTm93O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvL2VzbGludC1kaXNhYmxlLW5leHQtbGluZSBqc2RvYy9yZXF1aXJlLWpzZG9jXG4gICAgICAgICAgICBmdW5jdGlvbiBkb1RpY2tJbm5lcigpIHtcbiAgICAgICAgICAgICAgICAvLyBwZXJmb3JtIGVhY2ggdGltZXIgaW4gdGhlIHJlcXVlc3RlZCByYW5nZVxuICAgICAgICAgICAgICAgIHRpbWVyID0gZmlyc3RUaW1lckluUmFuZ2UoY2xvY2ssIHRpY2tGcm9tLCB0aWNrVG8pO1xuICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bm1vZGlmaWVkLWxvb3AtY29uZGl0aW9uXG4gICAgICAgICAgICAgICAgd2hpbGUgKHRpbWVyICYmIHRpY2tGcm9tIDw9IHRpY2tUbykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2xvY2sudGltZXJzW3RpbWVyLmlkXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGlja0Zyb20gPSB0aW1lci5jYWxsQXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbG9jay5ub3cgPSB0aW1lci5jYWxsQXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICBvbGROb3cgPSBjbG9jay5ub3c7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bkpvYnMoY2xvY2spO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxUaW1lcihjbG9jaywgdGltZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpcnN0RXhjZXB0aW9uID0gZmlyc3RFeGNlcHRpb24gfHwgZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzQXN5bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBmaW5pc2ggdXAgYWZ0ZXIgbmF0aXZlIHNldEltbWVkaWF0ZSBjYWxsYmFjayB0byBhbGxvd1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFsbCBuYXRpdmUgZXM2IHByb21pc2VzIHRvIHByb2Nlc3MgdGhlaXIgY2FsbGJhY2tzIGFmdGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZWFjaCB0aW1lciBmaXJlcy5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmlnaW5hbFNldFRpbWVvdXQobmV4dFByb21pc2VUaWNrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbXBlbnNhdGlvbkNoZWNrKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBwb3N0VGltZXJDYWxsKCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcGVyZm9ybSBwcm9jZXNzLm5leHRUaWNrKClzIGFnYWluXG4gICAgICAgICAgICAgICAgb2xkTm93ID0gY2xvY2subm93O1xuICAgICAgICAgICAgICAgIHJ1bkpvYnMoY2xvY2spO1xuICAgICAgICAgICAgICAgIGlmIChvbGROb3cgIT09IGNsb2NrLm5vdykge1xuICAgICAgICAgICAgICAgICAgICAvLyBjb21wZW5zYXRlIGZvciBhbnkgc2V0U3lzdGVtVGltZSgpIGNhbGwgZHVyaW5nIHByb2Nlc3MubmV4dFRpY2soKSBjYWxsYmFja1xuICAgICAgICAgICAgICAgICAgICB0aWNrRnJvbSArPSBjbG9jay5ub3cgLSBvbGROb3c7XG4gICAgICAgICAgICAgICAgICAgIHRpY2tUbyArPSBjbG9jay5ub3cgLSBvbGROb3c7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNsb2NrLmR1cmluZ1RpY2sgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIC8vIGNvcm5lciBjYXNlOiBkdXJpbmcgcnVuSm9icyBuZXcgdGltZXJzIHdlcmUgc2NoZWR1bGVkIHdoaWNoIGNvdWxkIGJlIGluIHRoZSByYW5nZSBbY2xvY2subm93LCB0aWNrVG9dXG4gICAgICAgICAgICAgICAgdGltZXIgPSBmaXJzdFRpbWVySW5SYW5nZShjbG9jaywgdGlja0Zyb20sIHRpY2tUbyk7XG4gICAgICAgICAgICAgICAgaWYgKHRpbWVyKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbG9jay50aWNrKHRpY2tUbyAtIGNsb2NrLm5vdyk7IC8vIGRvIGl0IGFsbCBhZ2FpbiAtIGZvciB0aGUgcmVtYWluZGVyIG9mIHRoZSByZXF1ZXN0ZWQgcmFuZ2VcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmlyc3RFeGNlcHRpb24gPSBmaXJzdEV4Y2VwdGlvbiB8fCBlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gbm8gdGltZXJzIHJlbWFpbmluZyBpbiB0aGUgcmVxdWVzdGVkIHJhbmdlOiBtb3ZlIHRoZSBjbG9jayBhbGwgdGhlIHdheSB0byB0aGUgZW5kXG4gICAgICAgICAgICAgICAgICAgIGNsb2NrLm5vdyA9IHRpY2tUbztcblxuICAgICAgICAgICAgICAgICAgICAvLyB1cGRhdGUgbmFub3NcbiAgICAgICAgICAgICAgICAgICAgbmFub3MgPSBuYW5vc1RvdGFsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZmlyc3RFeGNlcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZmlyc3RFeGNlcHRpb247XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXN5bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShjbG9jay5ub3cpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjbG9jay5ub3c7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBuZXh0UHJvbWlzZVRpY2sgPVxuICAgICAgICAgICAgICAgIGlzQXN5bmMgJiZcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb21wZW5zYXRpb25DaGVjaygpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcG9zdFRpbWVyQ2FsbCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9UaWNrSW5uZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgY29tcGVuc2F0aW9uQ2hlY2sgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgLy8gY29tcGVuc2F0ZSBmb3IgYW55IHNldFN5c3RlbVRpbWUoKSBjYWxsIGR1cmluZyB0aW1lciBjYWxsYmFja1xuICAgICAgICAgICAgICAgIGlmIChvbGROb3cgIT09IGNsb2NrLm5vdykge1xuICAgICAgICAgICAgICAgICAgICB0aWNrRnJvbSArPSBjbG9jay5ub3cgLSBvbGROb3c7XG4gICAgICAgICAgICAgICAgICAgIHRpY2tUbyArPSBjbG9jay5ub3cgLSBvbGROb3c7XG4gICAgICAgICAgICAgICAgICAgIHByZXZpb3VzICs9IGNsb2NrLm5vdyAtIG9sZE5vdztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBwb3N0VGltZXJDYWxsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRpbWVyID0gZmlyc3RUaW1lckluUmFuZ2UoY2xvY2ssIHByZXZpb3VzLCB0aWNrVG8pO1xuICAgICAgICAgICAgICAgIHByZXZpb3VzID0gdGlja0Zyb207XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICByZXR1cm4gZG9UaWNrSW5uZXIoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IHRpY2tWYWx1ZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIG9yIGEgaHVtYW4tcmVhZGFibGUgdmFsdWUgbGlrZSBcIjAxOjExOjE1XCJcbiAgICAgICAgICogQHJldHVybnMge251bWJlcn0gd2lsbCByZXR1cm4gdGhlIG5ldyBgbm93YCB2YWx1ZVxuICAgICAgICAgKi9cbiAgICAgICAgY2xvY2sudGljayA9IGZ1bmN0aW9uIHRpY2sodGlja1ZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gZG9UaWNrKHRpY2tWYWx1ZSwgZmFsc2UpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh0eXBlb2YgX2dsb2JhbC5Qcm9taXNlICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gdGlja1ZhbHVlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgb3IgYSBodW1hbi1yZWFkYWJsZSB2YWx1ZSBsaWtlIFwiMDE6MTE6MTVcIlxuICAgICAgICAgICAgICogQHJldHVybnMge1Byb21pc2V9XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGNsb2NrLnRpY2tBc3luYyA9IGZ1bmN0aW9uIHRpY2tBc3luYyh0aWNrVmFsdWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IF9nbG9iYWwuUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIG9yaWdpbmFsU2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvVGljayh0aWNrVmFsdWUsIHRydWUsIHJlc29sdmUsIHJlamVjdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBjbG9jay5uZXh0ID0gZnVuY3Rpb24gbmV4dCgpIHtcbiAgICAgICAgICAgIHJ1bkpvYnMoY2xvY2spO1xuICAgICAgICAgICAgY29uc3QgdGltZXIgPSBmaXJzdFRpbWVyKGNsb2NrKTtcbiAgICAgICAgICAgIGlmICghdGltZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2xvY2subm93O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjbG9jay5kdXJpbmdUaWNrID0gdHJ1ZTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY2xvY2subm93ID0gdGltZXIuY2FsbEF0O1xuICAgICAgICAgICAgICAgIGNhbGxUaW1lcihjbG9jaywgdGltZXIpO1xuICAgICAgICAgICAgICAgIHJ1bkpvYnMoY2xvY2spO1xuICAgICAgICAgICAgICAgIHJldHVybiBjbG9jay5ub3c7XG4gICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgIGNsb2NrLmR1cmluZ1RpY2sgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBpZiAodHlwZW9mIF9nbG9iYWwuUHJvbWlzZSAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgY2xvY2submV4dEFzeW5jID0gZnVuY3Rpb24gbmV4dEFzeW5jKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgX2dsb2JhbC5Qcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgb3JpZ2luYWxTZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGltZXIgPSBmaXJzdFRpbWVyKGNsb2NrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRpbWVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoY2xvY2subm93KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBlcnI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvY2suZHVyaW5nVGljayA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvY2subm93ID0gdGltZXIuY2FsbEF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxUaW1lcihjbG9jaywgdGltZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXJyID0gZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvY2suZHVyaW5nVGljayA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZ2luYWxTZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGNsb2NrLm5vdyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNsb2NrLnJ1bkFsbCA9IGZ1bmN0aW9uIHJ1bkFsbCgpIHtcbiAgICAgICAgICAgIGxldCBudW1UaW1lcnMsIGk7XG4gICAgICAgICAgICBydW5Kb2JzKGNsb2NrKTtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBjbG9jay5sb29wTGltaXQ7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICghY2xvY2sudGltZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc2V0SXNOZWFySW5maW5pdGVMaW1pdCgpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2xvY2subm93O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIG51bVRpbWVycyA9IE9iamVjdC5rZXlzKGNsb2NrLnRpbWVycykubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGlmIChudW1UaW1lcnMgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzZXRJc05lYXJJbmZpbml0ZUxpbWl0KCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjbG9jay5ub3c7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY2xvY2submV4dCgpO1xuICAgICAgICAgICAgICAgIGNoZWNrSXNOZWFySW5maW5pdGVMaW1pdChjbG9jaywgaSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGV4Y2Vzc0pvYiA9IGZpcnN0VGltZXIoY2xvY2spO1xuICAgICAgICAgICAgdGhyb3cgZ2V0SW5maW5pdGVMb29wRXJyb3IoY2xvY2ssIGV4Y2Vzc0pvYik7XG4gICAgICAgIH07XG5cbiAgICAgICAgY2xvY2sucnVuVG9GcmFtZSA9IGZ1bmN0aW9uIHJ1blRvRnJhbWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gY2xvY2sudGljayhnZXRUaW1lVG9OZXh0RnJhbWUoKSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHR5cGVvZiBfZ2xvYmFsLlByb21pc2UgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgIGNsb2NrLnJ1bkFsbEFzeW5jID0gZnVuY3Rpb24gcnVuQWxsQXN5bmMoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBfZ2xvYmFsLlByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAgICAgKlxuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gZG9SdW4oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvcmlnaW5hbFNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJ1bkpvYnMoY2xvY2spO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBudW1UaW1lcnM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpIDwgY2xvY2subG9vcExpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNsb2NrLnRpbWVycykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0SXNOZWFySW5maW5pdGVMaW1pdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoY2xvY2subm93KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG51bVRpbWVycyA9IE9iamVjdC5rZXlzKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb2NrLnRpbWVycyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICkubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG51bVRpbWVycyA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0SXNOZWFySW5maW5pdGVMaW1pdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoY2xvY2subm93KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb2NrLm5leHQoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaSsrO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb1J1bigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tJc05lYXJJbmZpbml0ZUxpbWl0KGNsb2NrLCBpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4Y2Vzc0pvYiA9IGZpcnN0VGltZXIoY2xvY2spO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZ2V0SW5maW5pdGVMb29wRXJyb3IoY2xvY2ssIGV4Y2Vzc0pvYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvUnVuKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY2xvY2sucnVuVG9MYXN0ID0gZnVuY3Rpb24gcnVuVG9MYXN0KCkge1xuICAgICAgICAgICAgY29uc3QgdGltZXIgPSBsYXN0VGltZXIoY2xvY2spO1xuICAgICAgICAgICAgaWYgKCF0aW1lcikge1xuICAgICAgICAgICAgICAgIHJ1bkpvYnMoY2xvY2spO1xuICAgICAgICAgICAgICAgIHJldHVybiBjbG9jay5ub3c7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBjbG9jay50aWNrKHRpbWVyLmNhbGxBdCAtIGNsb2NrLm5vdyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHR5cGVvZiBfZ2xvYmFsLlByb21pc2UgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgIGNsb2NrLnJ1blRvTGFzdEFzeW5jID0gZnVuY3Rpb24gcnVuVG9MYXN0QXN5bmMoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBfZ2xvYmFsLlByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgICAgICAgICBvcmlnaW5hbFNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0aW1lciA9IGxhc3RUaW1lcihjbG9jayk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCF0aW1lcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBydW5Kb2JzKGNsb2NrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShjbG9jay5ub3cpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoY2xvY2sudGlja0FzeW5jKHRpbWVyLmNhbGxBdCAtIGNsb2NrLm5vdykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgY2xvY2sucmVzZXQgPSBmdW5jdGlvbiByZXNldCgpIHtcbiAgICAgICAgICAgIG5hbm9zID0gMDtcbiAgICAgICAgICAgIGNsb2NrLnRpbWVycyA9IHt9O1xuICAgICAgICAgICAgY2xvY2suam9icyA9IFtdO1xuICAgICAgICAgICAgY2xvY2subm93ID0gc3RhcnQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgY2xvY2suc2V0U3lzdGVtVGltZSA9IGZ1bmN0aW9uIHNldFN5c3RlbVRpbWUoc3lzdGVtVGltZSkge1xuICAgICAgICAgICAgLy8gZGV0ZXJtaW5lIHRpbWUgZGlmZmVyZW5jZVxuICAgICAgICAgICAgY29uc3QgbmV3Tm93ID0gZ2V0RXBvY2goc3lzdGVtVGltZSk7XG4gICAgICAgICAgICBjb25zdCBkaWZmZXJlbmNlID0gbmV3Tm93IC0gY2xvY2subm93O1xuICAgICAgICAgICAgbGV0IGlkLCB0aW1lcjtcblxuICAgICAgICAgICAgYWRqdXN0ZWRTeXN0ZW1UaW1lWzBdID0gYWRqdXN0ZWRTeXN0ZW1UaW1lWzBdICsgZGlmZmVyZW5jZTtcbiAgICAgICAgICAgIGFkanVzdGVkU3lzdGVtVGltZVsxXSA9IGFkanVzdGVkU3lzdGVtVGltZVsxXSArIG5hbm9zO1xuICAgICAgICAgICAgLy8gdXBkYXRlICdzeXN0ZW0gY2xvY2snXG4gICAgICAgICAgICBjbG9jay5ub3cgPSBuZXdOb3c7XG4gICAgICAgICAgICBuYW5vcyA9IDA7XG5cbiAgICAgICAgICAgIC8vIHVwZGF0ZSB0aW1lcnMgYW5kIGludGVydmFscyB0byBrZWVwIHRoZW0gc3RhYmxlXG4gICAgICAgICAgICBmb3IgKGlkIGluIGNsb2NrLnRpbWVycykge1xuICAgICAgICAgICAgICAgIGlmIChjbG9jay50aW1lcnMuaGFzT3duUHJvcGVydHkoaWQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRpbWVyID0gY2xvY2sudGltZXJzW2lkXTtcbiAgICAgICAgICAgICAgICAgICAgdGltZXIuY3JlYXRlZEF0ICs9IGRpZmZlcmVuY2U7XG4gICAgICAgICAgICAgICAgICAgIHRpbWVyLmNhbGxBdCArPSBkaWZmZXJlbmNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSB0aWNrVmFsdWUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyBvciBhIGh1bWFuLXJlYWRhYmxlIHZhbHVlIGxpa2UgXCIwMToxMToxNVwiXG4gICAgICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IHdpbGwgcmV0dXJuIHRoZSBuZXcgYG5vd2AgdmFsdWVcbiAgICAgICAgICovXG4gICAgICAgIGNsb2NrLmp1bXAgPSBmdW5jdGlvbiBqdW1wKHRpY2tWYWx1ZSkge1xuICAgICAgICAgICAgY29uc3QgbXNGbG9hdCA9XG4gICAgICAgICAgICAgICAgdHlwZW9mIHRpY2tWYWx1ZSA9PT0gXCJudW1iZXJcIlxuICAgICAgICAgICAgICAgICAgICA/IHRpY2tWYWx1ZVxuICAgICAgICAgICAgICAgICAgICA6IHBhcnNlVGltZSh0aWNrVmFsdWUpO1xuICAgICAgICAgICAgY29uc3QgbXMgPSBNYXRoLmZsb29yKG1zRmxvYXQpO1xuXG4gICAgICAgICAgICBmb3IgKGNvbnN0IHRpbWVyIG9mIE9iamVjdC52YWx1ZXMoY2xvY2sudGltZXJzKSkge1xuICAgICAgICAgICAgICAgIGlmIChjbG9jay5ub3cgKyBtcyA+IHRpbWVyLmNhbGxBdCkge1xuICAgICAgICAgICAgICAgICAgICB0aW1lci5jYWxsQXQgPSBjbG9jay5ub3cgKyBtcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjbG9jay50aWNrKG1zKTtcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAoaXNQcmVzZW50LnBlcmZvcm1hbmNlKSB7XG4gICAgICAgICAgICBjbG9jay5wZXJmb3JtYW5jZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgICAgICAgICBjbG9jay5wZXJmb3JtYW5jZS5ub3cgPSBmYWtlUGVyZm9ybWFuY2VOb3c7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXNQcmVzZW50LmhydGltZSkge1xuICAgICAgICAgICAgY2xvY2suaHJ0aW1lID0gaHJ0aW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNsb2NrO1xuICAgIH1cblxuICAgIC8qIGVzbGludC1kaXNhYmxlIGNvbXBsZXhpdHkgKi9cblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB7Q29uZmlnPX0gW2NvbmZpZ10gT3B0aW9uYWwgY29uZmlnXG4gICAgICogQHJldHVybnMge0Nsb2NrfVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGluc3RhbGwoY29uZmlnKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGFyZ3VtZW50cy5sZW5ndGggPiAxIHx8XG4gICAgICAgICAgICBjb25maWcgaW5zdGFuY2VvZiBEYXRlIHx8XG4gICAgICAgICAgICBBcnJheS5pc0FycmF5KGNvbmZpZykgfHxcbiAgICAgICAgICAgIHR5cGVvZiBjb25maWcgPT09IFwibnVtYmVyXCJcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgICAgIGBGYWtlVGltZXJzLmluc3RhbGwgY2FsbGVkIHdpdGggJHtTdHJpbmcoXG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgICAgICApfSBpbnN0YWxsIHJlcXVpcmVzIGFuIG9iamVjdCBwYXJhbWV0ZXJgLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChfZ2xvYmFsLkRhdGUuaXNGYWtlID09PSB0cnVlKSB7XG4gICAgICAgICAgICAvLyBUaW1lcnMgYXJlIGFscmVhZHkgZmFrZWQ7IHRoaXMgaXMgYSBwcm9ibGVtLlxuICAgICAgICAgICAgLy8gTWFrZSB0aGUgdXNlciByZXNldCB0aW1lcnMgYmVmb3JlIGNvbnRpbnVpbmcuXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgICAgIFwiQ2FuJ3QgaW5zdGFsbCBmYWtlIHRpbWVycyB0d2ljZSBvbiB0aGUgc2FtZSBnbG9iYWwgb2JqZWN0LlwiLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1wYXJhbS1yZWFzc2lnblxuICAgICAgICBjb25maWcgPSB0eXBlb2YgY29uZmlnICE9PSBcInVuZGVmaW5lZFwiID8gY29uZmlnIDoge307XG4gICAgICAgIGNvbmZpZy5zaG91bGRBZHZhbmNlVGltZSA9IGNvbmZpZy5zaG91bGRBZHZhbmNlVGltZSB8fCBmYWxzZTtcbiAgICAgICAgY29uZmlnLmFkdmFuY2VUaW1lRGVsdGEgPSBjb25maWcuYWR2YW5jZVRpbWVEZWx0YSB8fCAyMDtcbiAgICAgICAgY29uZmlnLnNob3VsZENsZWFyTmF0aXZlVGltZXJzID1cbiAgICAgICAgICAgIGNvbmZpZy5zaG91bGRDbGVhck5hdGl2ZVRpbWVycyB8fCBmYWxzZTtcblxuICAgICAgICBpZiAoY29uZmlnLnRhcmdldCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgICAgICAgICBcImNvbmZpZy50YXJnZXQgaXMgbm8gbG9uZ2VyIHN1cHBvcnRlZC4gVXNlIGB3aXRoR2xvYmFsKHRhcmdldClgIGluc3RlYWQuXCIsXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0aW1lci9vYmplY3QgdGhlIG5hbWUgb2YgdGhlIHRoaW5nIHRoYXQgaXMgbm90IHByZXNlbnRcbiAgICAgICAgICogQHBhcmFtIHRpbWVyXG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBoYW5kbGVNaXNzaW5nVGltZXIodGltZXIpIHtcbiAgICAgICAgICAgIGlmIChjb25maWcuaWdub3JlTWlzc2luZ1RpbWVycykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhyb3cgbmV3IFJlZmVyZW5jZUVycm9yKFxuICAgICAgICAgICAgICAgIGBub24tZXhpc3RlbnQgdGltZXJzIGFuZC9vciBvYmplY3RzIGNhbm5vdCBiZSBmYWtlZDogJyR7dGltZXJ9J2AsXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGksIGw7XG4gICAgICAgIGNvbnN0IGNsb2NrID0gY3JlYXRlQ2xvY2soY29uZmlnLm5vdywgY29uZmlnLmxvb3BMaW1pdCk7XG4gICAgICAgIGNsb2NrLnNob3VsZENsZWFyTmF0aXZlVGltZXJzID0gY29uZmlnLnNob3VsZENsZWFyTmF0aXZlVGltZXJzO1xuXG4gICAgICAgIGNsb2NrLnVuaW5zdGFsbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB1bmluc3RhbGwoY2xvY2ssIGNvbmZpZyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgY2xvY2suYWJvcnRMaXN0ZW5lck1hcCA9IG5ldyBNYXAoKTtcblxuICAgICAgICBjbG9jay5tZXRob2RzID0gY29uZmlnLnRvRmFrZSB8fCBbXTtcblxuICAgICAgICBpZiAoY2xvY2subWV0aG9kcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGNsb2NrLm1ldGhvZHMgPSBPYmplY3Qua2V5cyh0aW1lcnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNvbmZpZy5zaG91bGRBZHZhbmNlVGltZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgY29uc3QgaW50ZXJ2YWxUaWNrID0gZG9JbnRlcnZhbFRpY2suYmluZChcbiAgICAgICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgICAgIGNsb2NrLFxuICAgICAgICAgICAgICAgIGNvbmZpZy5hZHZhbmNlVGltZURlbHRhLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGludGVydmFsSWQgPSBfZ2xvYmFsLnNldEludGVydmFsKFxuICAgICAgICAgICAgICAgIGludGVydmFsVGljayxcbiAgICAgICAgICAgICAgICBjb25maWcuYWR2YW5jZVRpbWVEZWx0YSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBjbG9jay5hdHRhY2hlZEludGVydmFsID0gaW50ZXJ2YWxJZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjbG9jay5tZXRob2RzLmluY2x1ZGVzKFwicGVyZm9ybWFuY2VcIikpIHtcbiAgICAgICAgICAgIGNvbnN0IHByb3RvID0gKCgpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGVyZm9ybWFuY2VDb25zdHJ1Y3RvclByb3RvdHlwZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2dsb2JhbC5wZXJmb3JtYW5jZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChoYXNQZXJmb3JtYW5jZVByb3RvdHlwZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gX2dsb2JhbC5QZXJmb3JtYW5jZS5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgICAgIGlmIChwcm90bykge1xuICAgICAgICAgICAgICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHByb3RvKS5mb3JFYWNoKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChuYW1lICE9PSBcIm5vd1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbG9jay5wZXJmb3JtYW5jZVtuYW1lXSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZS5pbmRleE9mKFwiZ2V0RW50cmllc1wiKSA9PT0gMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IE5PT1BfQVJSQVlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBOT09QO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgLy8gZW5zdXJlIGBtYXJrYCByZXR1cm5zIGEgdmFsdWUgdGhhdCBpcyB2YWxpZFxuICAgICAgICAgICAgICAgIGNsb2NrLnBlcmZvcm1hbmNlLm1hcmsgPSAobmFtZSkgPT5cbiAgICAgICAgICAgICAgICAgICAgbmV3IEZha2VQZXJmb3JtYW5jZUVudHJ5KG5hbWUsIFwibWFya1wiLCAwLCAwKTtcbiAgICAgICAgICAgICAgICBjbG9jay5wZXJmb3JtYW5jZS5tZWFzdXJlID0gKG5hbWUpID0+XG4gICAgICAgICAgICAgICAgICAgIG5ldyBGYWtlUGVyZm9ybWFuY2VFbnRyeShuYW1lLCBcIm1lYXN1cmVcIiwgMCwgMTAwKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoKGNvbmZpZy50b0Zha2UgfHwgW10pLmluY2x1ZGVzKFwicGVyZm9ybWFuY2VcIikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlTWlzc2luZ1RpbWVyKFwicGVyZm9ybWFuY2VcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKF9nbG9iYWwgPT09IGdsb2JhbE9iamVjdCAmJiB0aW1lcnNNb2R1bGUpIHtcbiAgICAgICAgICAgIGNsb2NrLnRpbWVyc01vZHVsZU1ldGhvZHMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoX2dsb2JhbCA9PT0gZ2xvYmFsT2JqZWN0ICYmIHRpbWVyc1Byb21pc2VzTW9kdWxlKSB7XG4gICAgICAgICAgICBjbG9jay50aW1lcnNQcm9taXNlc01vZHVsZU1ldGhvZHMgPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwLCBsID0gY2xvY2subWV0aG9kcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgIGNvbnN0IG5hbWVPZk1ldGhvZFRvUmVwbGFjZSA9IGNsb2NrLm1ldGhvZHNbaV07XG5cbiAgICAgICAgICAgIGlmICghaXNQcmVzZW50W25hbWVPZk1ldGhvZFRvUmVwbGFjZV0pIHtcbiAgICAgICAgICAgICAgICBoYW5kbGVNaXNzaW5nVGltZXIobmFtZU9mTWV0aG9kVG9SZXBsYWNlKTtcbiAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG5hbWVPZk1ldGhvZFRvUmVwbGFjZSA9PT0gXCJocnRpbWVcIikge1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgX2dsb2JhbC5wcm9jZXNzICYmXG4gICAgICAgICAgICAgICAgICAgIHR5cGVvZiBfZ2xvYmFsLnByb2Nlc3MuaHJ0aW1lID09PSBcImZ1bmN0aW9uXCJcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgaGlqYWNrTWV0aG9kKF9nbG9iYWwucHJvY2VzcywgbmFtZU9mTWV0aG9kVG9SZXBsYWNlLCBjbG9jayk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChuYW1lT2ZNZXRob2RUb1JlcGxhY2UgPT09IFwibmV4dFRpY2tcIikge1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgX2dsb2JhbC5wcm9jZXNzICYmXG4gICAgICAgICAgICAgICAgICAgIHR5cGVvZiBfZ2xvYmFsLnByb2Nlc3MubmV4dFRpY2sgPT09IFwiZnVuY3Rpb25cIlxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBoaWphY2tNZXRob2QoX2dsb2JhbC5wcm9jZXNzLCBuYW1lT2ZNZXRob2RUb1JlcGxhY2UsIGNsb2NrKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGhpamFja01ldGhvZChfZ2xvYmFsLCBuYW1lT2ZNZXRob2RUb1JlcGxhY2UsIGNsb2NrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBjbG9jay50aW1lcnNNb2R1bGVNZXRob2RzICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgICAgICB0aW1lcnNNb2R1bGVbbmFtZU9mTWV0aG9kVG9SZXBsYWNlXVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgb3JpZ2luYWwgPSB0aW1lcnNNb2R1bGVbbmFtZU9mTWV0aG9kVG9SZXBsYWNlXTtcbiAgICAgICAgICAgICAgICBjbG9jay50aW1lcnNNb2R1bGVNZXRob2RzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICBtZXRob2ROYW1lOiBuYW1lT2ZNZXRob2RUb1JlcGxhY2UsXG4gICAgICAgICAgICAgICAgICAgIG9yaWdpbmFsOiBvcmlnaW5hbCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aW1lcnNNb2R1bGVbbmFtZU9mTWV0aG9kVG9SZXBsYWNlXSA9XG4gICAgICAgICAgICAgICAgICAgIF9nbG9iYWxbbmFtZU9mTWV0aG9kVG9SZXBsYWNlXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjbG9jay50aW1lcnNQcm9taXNlc01vZHVsZU1ldGhvZHMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmIChuYW1lT2ZNZXRob2RUb1JlcGxhY2UgPT09IFwic2V0VGltZW91dFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsb2NrLnRpbWVyc1Byb21pc2VzTW9kdWxlTWV0aG9kcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZE5hbWU6IFwic2V0VGltZW91dFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgb3JpZ2luYWw6IHRpbWVyc1Byb21pc2VzTW9kdWxlLnNldFRpbWVvdXQsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHRpbWVyc1Byb21pc2VzTW9kdWxlLnNldFRpbWVvdXQgPSAoXG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxheSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucyA9IHt9LFxuICAgICAgICAgICAgICAgICAgICApID0+XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYWJvcnQgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuc2lnbmFsLnJlbW92ZUV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImFib3J0XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhYm9ydCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvY2suYWJvcnRMaXN0ZW5lck1hcC5kZWxldGUoYWJvcnQpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgaXMgc2FmZSwgdGhlcmUgaXMgbm8gY29kZSBwYXRoIHRoYXQgbGVhZHMgdG8gdGhpcyBmdW5jdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBiZWluZyBpbnZva2VkIGJlZm9yZSBoYW5kbGUgaGFzIGJlZW4gYXNzaWduZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11c2UtYmVmb3JlLWRlZmluZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9jay5jbGVhclRpbWVvdXQoaGFuZGxlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG9wdGlvbnMuc2lnbmFsLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhhbmRsZSA9IGNsb2NrLnNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5zaWduYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuc2lnbmFsLnJlbW92ZUV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJhYm9ydFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFib3J0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb2NrLmFib3J0TGlzdGVuZXJNYXAuZGVsZXRlKGFib3J0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIGRlbGF5KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnNpZ25hbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5zaWduYWwuYWJvcnRlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWJvcnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJhYm9ydFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFib3J0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb2NrLmFib3J0TGlzdGVuZXJNYXAuc2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFib3J0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuc2lnbmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobmFtZU9mTWV0aG9kVG9SZXBsYWNlID09PSBcInNldEltbWVkaWF0ZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsb2NrLnRpbWVyc1Byb21pc2VzTW9kdWxlTWV0aG9kcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZE5hbWU6IFwic2V0SW1tZWRpYXRlXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBvcmlnaW5hbDogdGltZXJzUHJvbWlzZXNNb2R1bGUuc2V0SW1tZWRpYXRlLFxuICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICB0aW1lcnNQcm9taXNlc01vZHVsZS5zZXRJbW1lZGlhdGUgPSAodmFsdWUsIG9wdGlvbnMgPSB7fSkgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhYm9ydCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5zaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYWJvcnRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFib3J0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9jay5hYm9ydExpc3RlbmVyTWFwLmRlbGV0ZShhYm9ydCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBpcyBzYWZlLCB0aGVyZSBpcyBubyBjb2RlIHBhdGggdGhhdCBsZWFkcyB0byB0aGlzIGZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGJlaW5nIGludm9rZWQgYmVmb3JlIGhhbmRsZSBoYXMgYmVlbiBhc3NpZ25lZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVzZS1iZWZvcmUtZGVmaW5lXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb2NrLmNsZWFySW1tZWRpYXRlKGhhbmRsZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChvcHRpb25zLnNpZ25hbC5yZWFzb24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBoYW5kbGUgPSBjbG9jay5zZXRJbW1lZGlhdGUoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5zaWduYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuc2lnbmFsLnJlbW92ZUV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJhYm9ydFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFib3J0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb2NrLmFib3J0TGlzdGVuZXJNYXAuZGVsZXRlKGFib3J0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuc2lnbmFsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnNpZ25hbC5hYm9ydGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhYm9ydCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5zaWduYWwuYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImFib3J0XCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWJvcnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvY2suYWJvcnRMaXN0ZW5lck1hcC5zZXQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWJvcnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5zaWduYWwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChuYW1lT2ZNZXRob2RUb1JlcGxhY2UgPT09IFwic2V0SW50ZXJ2YWxcIikge1xuICAgICAgICAgICAgICAgICAgICBjbG9jay50aW1lcnNQcm9taXNlc01vZHVsZU1ldGhvZHMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2ROYW1lOiBcInNldEludGVydmFsXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBvcmlnaW5hbDogdGltZXJzUHJvbWlzZXNNb2R1bGUuc2V0SW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHRpbWVyc1Byb21pc2VzTW9kdWxlLnNldEludGVydmFsID0gKFxuICAgICAgICAgICAgICAgICAgICAgICAgZGVsYXksXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMgPSB7fSxcbiAgICAgICAgICAgICAgICAgICAgKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAgICAgW1N5bWJvbC5hc3luY0l0ZXJhdG9yXTogKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNyZWF0ZVJlc29sdmFibGUgPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZXNvbHZlLCByZWplY3Q7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzLCByZWopID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUgPSByZXM7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QgPSByZWo7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9taXNlLnJlc29sdmUgPSByZXNvbHZlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9taXNlLnJlamVjdCA9IHJlamVjdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkb25lID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IGhhc1Rocm93biA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCByZXR1cm5DYWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBuZXh0QXZhaWxhYmxlID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXh0UXVldWUgPSBbXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGhhbmRsZSA9IGNsb2NrLnNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5leHRRdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXh0UXVldWUuc2hpZnQoKS5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXh0QXZhaWxhYmxlKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LCBkZWxheSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhYm9ydCA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5zaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiYWJvcnRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFib3J0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9jay5hYm9ydExpc3RlbmVyTWFwLmRlbGV0ZShhYm9ydCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvY2suY2xlYXJJbnRlcnZhbChoYW5kbGUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCByZXNvbHZhYmxlIG9mIG5leHRRdWV1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2YWJsZS5yZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuc2lnbmFsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnNpZ25hbC5hYm9ydGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJhYm9ydFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFib3J0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb2NrLmFib3J0TGlzdGVuZXJNYXAuc2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFib3J0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wdGlvbnMuc2lnbmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5leHQ6IGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnNpZ25hbD8uYWJvcnRlZCAmJiAhaGFzVGhyb3duKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGhyb3duID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBvcHRpb25zLnNpZ25hbC5yZWFzb247XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb25lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgZG9uZTogdHJ1ZSwgdmFsdWU6IHVuZGVmaW5lZCB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobmV4dEF2YWlsYWJsZSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXh0QXZhaWxhYmxlLS07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgZG9uZTogZmFsc2UsIHZhbHVlOiB2YWx1ZSB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZXNvbHZhYmxlID0gY3JlYXRlUmVzb2x2YWJsZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV4dFF1ZXVlLnB1c2gocmVzb2x2YWJsZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHJlc29sdmFibGU7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXR1cm5DYWxsICYmIG5leHRRdWV1ZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm5DYWxsLnJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuc2lnbmFsPy5hYm9ydGVkICYmICFoYXNUaHJvd24pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHJvd24gPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG9wdGlvbnMuc2lnbmFsLnJlYXNvbjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4geyBkb25lOiB0cnVlLCB2YWx1ZTogdW5kZWZpbmVkIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IGRvbmU6IGZhbHNlLCB2YWx1ZTogdmFsdWUgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuOiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9uZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IGRvbmU6IHRydWUsIHZhbHVlOiB1bmRlZmluZWQgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5leHRRdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuQ2FsbCA9IGNyZWF0ZVJlc29sdmFibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhd2FpdCByZXR1cm5DYWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9jay5jbGVhckludGVydmFsKGhhbmRsZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuc2lnbmFsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3B0aW9ucy5zaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJhYm9ydFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhYm9ydCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsb2NrLmFib3J0TGlzdGVuZXJNYXAuZGVsZXRlKGFib3J0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgZG9uZTogdHJ1ZSwgdmFsdWU6IHVuZGVmaW5lZCB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY2xvY2s7XG4gICAgfVxuXG4gICAgLyogZXNsaW50LWVuYWJsZSBjb21wbGV4aXR5ICovXG5cbiAgICByZXR1cm4ge1xuICAgICAgICB0aW1lcnM6IHRpbWVycyxcbiAgICAgICAgY3JlYXRlQ2xvY2s6IGNyZWF0ZUNsb2NrLFxuICAgICAgICBpbnN0YWxsOiBpbnN0YWxsLFxuICAgICAgICB3aXRoR2xvYmFsOiB3aXRoR2xvYmFsLFxuICAgIH07XG59XG5cbi8qKlxuICogQHR5cGVkZWYge29iamVjdH0gRmFrZVRpbWVyc1xuICogQHByb3BlcnR5IHtUaW1lcnN9IHRpbWVyc1xuICogQHByb3BlcnR5IHtjcmVhdGVDbG9ja30gY3JlYXRlQ2xvY2tcbiAqIEBwcm9wZXJ0eSB7RnVuY3Rpb259IGluc3RhbGxcbiAqIEBwcm9wZXJ0eSB7d2l0aEdsb2JhbH0gd2l0aEdsb2JhbFxuICovXG5cbi8qIGVzbGludC1lbmFibGUgY29tcGxleGl0eSAqL1xuXG4vKiogQHR5cGUge0Zha2VUaW1lcnN9ICovXG5jb25zdCBkZWZhdWx0SW1wbGVtZW50YXRpb24gPSB3aXRoR2xvYmFsKGdsb2JhbE9iamVjdCk7XG5cbmV4cG9ydHMudGltZXJzID0gZGVmYXVsdEltcGxlbWVudGF0aW9uLnRpbWVycztcbmV4cG9ydHMuY3JlYXRlQ2xvY2sgPSBkZWZhdWx0SW1wbGVtZW50YXRpb24uY3JlYXRlQ2xvY2s7XG5leHBvcnRzLmluc3RhbGwgPSBkZWZhdWx0SW1wbGVtZW50YXRpb24uaW5zdGFsbDtcbmV4cG9ydHMud2l0aEdsb2JhbCA9IHdpdGhHbG9iYWw7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIEFSUkFZX1RZUEVTID0gW1xuICAgIEFycmF5LFxuICAgIEludDhBcnJheSxcbiAgICBVaW50OEFycmF5LFxuICAgIFVpbnQ4Q2xhbXBlZEFycmF5LFxuICAgIEludDE2QXJyYXksXG4gICAgVWludDE2QXJyYXksXG4gICAgSW50MzJBcnJheSxcbiAgICBVaW50MzJBcnJheSxcbiAgICBGbG9hdDMyQXJyYXksXG4gICAgRmxvYXQ2NEFycmF5LFxuXTtcblxubW9kdWxlLmV4cG9ydHMgPSBBUlJBWV9UWVBFUztcbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgYXJyYXlQcm90byA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnByb3RvdHlwZXMuYXJyYXk7XG52YXIgZGVlcEVxdWFsID0gcmVxdWlyZShcIi4vZGVlcC1lcXVhbFwiKS51c2UoY3JlYXRlTWF0Y2hlcik7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdXNlLWJlZm9yZS1kZWZpbmVcbnZhciBldmVyeSA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLmV2ZXJ5O1xudmFyIGZ1bmN0aW9uTmFtZSA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLmZ1bmN0aW9uTmFtZTtcbnZhciBnZXQgPSByZXF1aXJlKFwibG9kYXNoLmdldFwiKTtcbnZhciBpdGVyYWJsZVRvU3RyaW5nID0gcmVxdWlyZShcIi4vaXRlcmFibGUtdG8tc3RyaW5nXCIpO1xudmFyIG9iamVjdFByb3RvID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikucHJvdG90eXBlcy5vYmplY3Q7XG52YXIgdHlwZU9mID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikudHlwZU9mO1xudmFyIHZhbHVlVG9TdHJpbmcgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS52YWx1ZVRvU3RyaW5nO1xuXG52YXIgYXNzZXJ0TWF0Y2hlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1tYXRjaGVyL2Fzc2VydC1tYXRjaGVyXCIpO1xudmFyIGFzc2VydE1ldGhvZEV4aXN0cyA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1tYXRjaGVyL2Fzc2VydC1tZXRob2QtZXhpc3RzXCIpO1xudmFyIGFzc2VydFR5cGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtbWF0Y2hlci9hc3NlcnQtdHlwZVwiKTtcbnZhciBpc0l0ZXJhYmxlID0gcmVxdWlyZShcIi4vY3JlYXRlLW1hdGNoZXIvaXMtaXRlcmFibGVcIik7XG52YXIgaXNNYXRjaGVyID0gcmVxdWlyZShcIi4vY3JlYXRlLW1hdGNoZXIvaXMtbWF0Y2hlclwiKTtcblxudmFyIG1hdGNoZXJQcm90b3R5cGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtbWF0Y2hlci9tYXRjaGVyLXByb3RvdHlwZVwiKTtcblxudmFyIGFycmF5SW5kZXhPZiA9IGFycmF5UHJvdG8uaW5kZXhPZjtcbnZhciBzb21lID0gYXJyYXlQcm90by5zb21lO1xuXG52YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcbnZhciBvYmplY3RUb1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG52YXIgVFlQRV9NQVAgPSByZXF1aXJlKFwiLi9jcmVhdGUtbWF0Y2hlci90eXBlLW1hcFwiKShjcmVhdGVNYXRjaGVyKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11c2UtYmVmb3JlLWRlZmluZVxuXG4vKipcbiAqIENyZWF0ZXMgYSBtYXRjaGVyIG9iamVjdCBmb3IgdGhlIHBhc3NlZCBleHBlY3RhdGlvblxuICpcbiAqIEBhbGlhcyBtb2R1bGU6c2Ftc2FtLmNyZWF0ZU1hdGNoZXJcbiAqIEBwYXJhbSB7Kn0gZXhwZWN0YXRpb24gQW4gZXhwZWN0dGF0aW9uXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSBBIG1lc3NhZ2UgZm9yIHRoZSBleHBlY3RhdGlvblxuICogQHJldHVybnMge29iamVjdH0gQSBtYXRjaGVyIG9iamVjdFxuICovXG5mdW5jdGlvbiBjcmVhdGVNYXRjaGVyKGV4cGVjdGF0aW9uLCBtZXNzYWdlKSB7XG4gICAgdmFyIG0gPSBPYmplY3QuY3JlYXRlKG1hdGNoZXJQcm90b3R5cGUpO1xuICAgIHZhciB0eXBlID0gdHlwZU9mKGV4cGVjdGF0aW9uKTtcblxuICAgIGlmIChtZXNzYWdlICE9PSB1bmRlZmluZWQgJiYgdHlwZW9mIG1lc3NhZ2UgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk1lc3NhZ2Ugc2hvdWxkIGJlIGEgc3RyaW5nXCIpO1xuICAgIH1cblxuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMikge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgICAgYEV4cGVjdGVkIDEgb3IgMiBhcmd1bWVudHMsIHJlY2VpdmVkICR7YXJndW1lbnRzLmxlbmd0aH1gLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGlmICh0eXBlIGluIFRZUEVfTUFQKSB7XG4gICAgICAgIFRZUEVfTUFQW3R5cGVdKG0sIGV4cGVjdGF0aW9uLCBtZXNzYWdlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtLnRlc3QgPSBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICByZXR1cm4gZGVlcEVxdWFsKGFjdHVhbCwgZXhwZWN0YXRpb24pO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGlmICghbS5tZXNzYWdlKSB7XG4gICAgICAgIG0ubWVzc2FnZSA9IGBtYXRjaCgke3ZhbHVlVG9TdHJpbmcoZXhwZWN0YXRpb24pfSlgO1xuICAgIH1cblxuICAgIC8vIGVuc3VyZSB0aGF0IG5vdGhpbmcgbXV0YXRlcyB0aGUgZXhwb3J0ZWQgbWVzc2FnZSB2YWx1ZSwgcmVmIGh0dHBzOi8vZ2l0aHViLmNvbS9zaW5vbmpzL3Npbm9uL2lzc3Vlcy8yNTAyXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG0sIFwibWVzc2FnZVwiLCB7XG4gICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiBmYWxzZSxcbiAgICAgICAgdmFsdWU6IG0ubWVzc2FnZSxcbiAgICB9KTtcblxuICAgIHJldHVybiBtO1xufVxuXG5jcmVhdGVNYXRjaGVyLmlzTWF0Y2hlciA9IGlzTWF0Y2hlcjtcblxuY3JlYXRlTWF0Y2hlci5hbnkgPSBjcmVhdGVNYXRjaGVyKGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbn0sIFwiYW55XCIpO1xuXG5jcmVhdGVNYXRjaGVyLmRlZmluZWQgPSBjcmVhdGVNYXRjaGVyKGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICByZXR1cm4gYWN0dWFsICE9PSBudWxsICYmIGFjdHVhbCAhPT0gdW5kZWZpbmVkO1xufSwgXCJkZWZpbmVkXCIpO1xuXG5jcmVhdGVNYXRjaGVyLnRydXRoeSA9IGNyZWF0ZU1hdGNoZXIoZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgIHJldHVybiBCb29sZWFuKGFjdHVhbCk7XG59LCBcInRydXRoeVwiKTtcblxuY3JlYXRlTWF0Y2hlci5mYWxzeSA9IGNyZWF0ZU1hdGNoZXIoZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgIHJldHVybiAhYWN0dWFsO1xufSwgXCJmYWxzeVwiKTtcblxuY3JlYXRlTWF0Y2hlci5zYW1lID0gZnVuY3Rpb24gKGV4cGVjdGF0aW9uKSB7XG4gICAgcmV0dXJuIGNyZWF0ZU1hdGNoZXIoXG4gICAgICAgIGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgIHJldHVybiBleHBlY3RhdGlvbiA9PT0gYWN0dWFsO1xuICAgICAgICB9LFxuICAgICAgICBgc2FtZSgke3ZhbHVlVG9TdHJpbmcoZXhwZWN0YXRpb24pfSlgLFxuICAgICk7XG59O1xuXG5jcmVhdGVNYXRjaGVyLmluID0gZnVuY3Rpb24gKGFycmF5T2ZFeHBlY3RhdGlvbnMpIHtcbiAgICBpZiAodHlwZU9mKGFycmF5T2ZFeHBlY3RhdGlvbnMpICE9PSBcImFycmF5XCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcImFycmF5IGV4cGVjdGVkXCIpO1xuICAgIH1cblxuICAgIHJldHVybiBjcmVhdGVNYXRjaGVyKFxuICAgICAgICBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICByZXR1cm4gc29tZShhcnJheU9mRXhwZWN0YXRpb25zLCBmdW5jdGlvbiAoZXhwZWN0YXRpb24pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXhwZWN0YXRpb24gPT09IGFjdHVhbDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuICAgICAgICBgaW4oJHt2YWx1ZVRvU3RyaW5nKGFycmF5T2ZFeHBlY3RhdGlvbnMpfSlgLFxuICAgICk7XG59O1xuXG5jcmVhdGVNYXRjaGVyLnR5cGVPZiA9IGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgYXNzZXJ0VHlwZSh0eXBlLCBcInN0cmluZ1wiLCBcInR5cGVcIik7XG4gICAgcmV0dXJuIGNyZWF0ZU1hdGNoZXIoZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICByZXR1cm4gdHlwZU9mKGFjdHVhbCkgPT09IHR5cGU7XG4gICAgfSwgYHR5cGVPZihcIiR7dHlwZX1cIilgKTtcbn07XG5cbmNyZWF0ZU1hdGNoZXIuaW5zdGFuY2VPZiA9IGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIGlmICovXG4gICAgaWYgKFxuICAgICAgICB0eXBlb2YgU3ltYm9sID09PSBcInVuZGVmaW5lZFwiIHx8XG4gICAgICAgIHR5cGVvZiBTeW1ib2wuaGFzSW5zdGFuY2UgPT09IFwidW5kZWZpbmVkXCJcbiAgICApIHtcbiAgICAgICAgYXNzZXJ0VHlwZSh0eXBlLCBcImZ1bmN0aW9uXCIsIFwidHlwZVwiKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBhc3NlcnRNZXRob2RFeGlzdHMoXG4gICAgICAgICAgICB0eXBlLFxuICAgICAgICAgICAgU3ltYm9sLmhhc0luc3RhbmNlLFxuICAgICAgICAgICAgXCJ0eXBlXCIsXG4gICAgICAgICAgICBcIltTeW1ib2wuaGFzSW5zdGFuY2VdXCIsXG4gICAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiBjcmVhdGVNYXRjaGVyKFxuICAgICAgICBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICByZXR1cm4gYWN0dWFsIGluc3RhbmNlb2YgdHlwZTtcbiAgICAgICAgfSxcbiAgICAgICAgYGluc3RhbmNlT2YoJHtmdW5jdGlvbk5hbWUodHlwZSkgfHwgb2JqZWN0VG9TdHJpbmcodHlwZSl9KWAsXG4gICAgKTtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIHByb3BlcnR5IG1hdGNoZXJcbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gcHJvcGVydHlUZXN0IEEgZnVuY3Rpb24gdG8gdGVzdCB0aGUgcHJvcGVydHkgYWdhaW5zdCBhIHZhbHVlXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVByZWZpeCBBIHByZWZpeCB0byB1c2UgZm9yIG1lc3NhZ2VzIGdlbmVyYXRlZCBieSB0aGUgbWF0Y2hlclxuICogQHJldHVybnMge29iamVjdH0gQSBtYXRjaGVyXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVByb3BlcnR5TWF0Y2hlcihwcm9wZXJ0eVRlc3QsIG1lc3NhZ2VQcmVmaXgpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKHByb3BlcnR5LCB2YWx1ZSkge1xuICAgICAgICBhc3NlcnRUeXBlKHByb3BlcnR5LCBcInN0cmluZ1wiLCBcInByb3BlcnR5XCIpO1xuICAgICAgICB2YXIgb25seVByb3BlcnR5ID0gYXJndW1lbnRzLmxlbmd0aCA9PT0gMTtcbiAgICAgICAgdmFyIG1lc3NhZ2UgPSBgJHttZXNzYWdlUHJlZml4fShcIiR7cHJvcGVydHl9XCJgO1xuICAgICAgICBpZiAoIW9ubHlQcm9wZXJ0eSkge1xuICAgICAgICAgICAgbWVzc2FnZSArPSBgLCAke3ZhbHVlVG9TdHJpbmcodmFsdWUpfWA7XG4gICAgICAgIH1cbiAgICAgICAgbWVzc2FnZSArPSBcIilcIjtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZU1hdGNoZXIoZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIGFjdHVhbCA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAgICAgICAgICAgYWN0dWFsID09PSBudWxsIHx8XG4gICAgICAgICAgICAgICAgIXByb3BlcnR5VGVzdChhY3R1YWwsIHByb3BlcnR5KVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG9ubHlQcm9wZXJ0eSB8fCBkZWVwRXF1YWwoYWN0dWFsW3Byb3BlcnR5XSwgdmFsdWUpO1xuICAgICAgICB9LCBtZXNzYWdlKTtcbiAgICB9O1xufVxuXG5jcmVhdGVNYXRjaGVyLmhhcyA9IGNyZWF0ZVByb3BlcnR5TWF0Y2hlcihmdW5jdGlvbiAoYWN0dWFsLCBwcm9wZXJ0eSkge1xuICAgIGlmICh0eXBlb2YgYWN0dWFsID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIHJldHVybiBwcm9wZXJ0eSBpbiBhY3R1YWw7XG4gICAgfVxuICAgIHJldHVybiBhY3R1YWxbcHJvcGVydHldICE9PSB1bmRlZmluZWQ7XG59LCBcImhhc1wiKTtcblxuY3JlYXRlTWF0Y2hlci5oYXNPd24gPSBjcmVhdGVQcm9wZXJ0eU1hdGNoZXIoZnVuY3Rpb24gKGFjdHVhbCwgcHJvcGVydHkpIHtcbiAgICByZXR1cm4gaGFzT3duUHJvcGVydHkoYWN0dWFsLCBwcm9wZXJ0eSk7XG59LCBcImhhc093blwiKTtcblxuY3JlYXRlTWF0Y2hlci5oYXNOZXN0ZWQgPSBmdW5jdGlvbiAocHJvcGVydHksIHZhbHVlKSB7XG4gICAgYXNzZXJ0VHlwZShwcm9wZXJ0eSwgXCJzdHJpbmdcIiwgXCJwcm9wZXJ0eVwiKTtcbiAgICB2YXIgb25seVByb3BlcnR5ID0gYXJndW1lbnRzLmxlbmd0aCA9PT0gMTtcbiAgICB2YXIgbWVzc2FnZSA9IGBoYXNOZXN0ZWQoXCIke3Byb3BlcnR5fVwiYDtcbiAgICBpZiAoIW9ubHlQcm9wZXJ0eSkge1xuICAgICAgICBtZXNzYWdlICs9IGAsICR7dmFsdWVUb1N0cmluZyh2YWx1ZSl9YDtcbiAgICB9XG4gICAgbWVzc2FnZSArPSBcIilcIjtcbiAgICByZXR1cm4gY3JlYXRlTWF0Y2hlcihmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGFjdHVhbCA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAgICAgICBhY3R1YWwgPT09IG51bGwgfHxcbiAgICAgICAgICAgIGdldChhY3R1YWwsIHByb3BlcnR5KSA9PT0gdW5kZWZpbmVkXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvbmx5UHJvcGVydHkgfHwgZGVlcEVxdWFsKGdldChhY3R1YWwsIHByb3BlcnR5KSwgdmFsdWUpO1xuICAgIH0sIG1lc3NhZ2UpO1xufTtcblxudmFyIGpzb25QYXJzZVJlc3VsdFR5cGVzID0ge1xuICAgIG51bGw6IHRydWUsXG4gICAgYm9vbGVhbjogdHJ1ZSxcbiAgICBudW1iZXI6IHRydWUsXG4gICAgc3RyaW5nOiB0cnVlLFxuICAgIG9iamVjdDogdHJ1ZSxcbiAgICBhcnJheTogdHJ1ZSxcbn07XG5jcmVhdGVNYXRjaGVyLmpzb24gPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICBpZiAoIWpzb25QYXJzZVJlc3VsdFR5cGVzW3R5cGVPZih2YWx1ZSldKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJWYWx1ZSBjYW5ub3QgYmUgdGhlIHJlc3VsdCBvZiBKU09OLnBhcnNlXCIpO1xuICAgIH1cbiAgICB2YXIgbWVzc2FnZSA9IGBqc29uKCR7SlNPTi5zdHJpbmdpZnkodmFsdWUsIG51bGwsIFwiICBcIil9KWA7XG4gICAgcmV0dXJuIGNyZWF0ZU1hdGNoZXIoZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICB2YXIgcGFyc2VkO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcGFyc2VkID0gSlNPTi5wYXJzZShhY3R1YWwpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRlZXBFcXVhbChwYXJzZWQsIHZhbHVlKTtcbiAgICB9LCBtZXNzYWdlKTtcbn07XG5cbmNyZWF0ZU1hdGNoZXIuZXZlcnkgPSBmdW5jdGlvbiAocHJlZGljYXRlKSB7XG4gICAgYXNzZXJ0TWF0Y2hlcihwcmVkaWNhdGUpO1xuXG4gICAgcmV0dXJuIGNyZWF0ZU1hdGNoZXIoZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICBpZiAodHlwZU9mKGFjdHVhbCkgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgIHJldHVybiBldmVyeShPYmplY3Qua2V5cyhhY3R1YWwpLCBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByZWRpY2F0ZS50ZXN0KGFjdHVhbFtrZXldKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGlzSXRlcmFibGUoYWN0dWFsKSAmJlxuICAgICAgICAgICAgZXZlcnkoYWN0dWFsLCBmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwcmVkaWNhdGUudGVzdChlbGVtZW50KTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfSwgYGV2ZXJ5KCR7cHJlZGljYXRlLm1lc3NhZ2V9KWApO1xufTtcblxuY3JlYXRlTWF0Y2hlci5zb21lID0gZnVuY3Rpb24gKHByZWRpY2F0ZSkge1xuICAgIGFzc2VydE1hdGNoZXIocHJlZGljYXRlKTtcblxuICAgIHJldHVybiBjcmVhdGVNYXRjaGVyKGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgaWYgKHR5cGVPZihhY3R1YWwpID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICByZXR1cm4gIWV2ZXJ5KE9iamVjdC5rZXlzKGFjdHVhbCksIGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gIXByZWRpY2F0ZS50ZXN0KGFjdHVhbFtrZXldKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGlzSXRlcmFibGUoYWN0dWFsKSAmJlxuICAgICAgICAgICAgIWV2ZXJ5KGFjdHVhbCwgZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gIXByZWRpY2F0ZS50ZXN0KGVsZW1lbnQpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICB9LCBgc29tZSgke3ByZWRpY2F0ZS5tZXNzYWdlfSlgKTtcbn07XG5cbmNyZWF0ZU1hdGNoZXIuYXJyYXkgPSBjcmVhdGVNYXRjaGVyLnR5cGVPZihcImFycmF5XCIpO1xuXG5jcmVhdGVNYXRjaGVyLmFycmF5LmRlZXBFcXVhbHMgPSBmdW5jdGlvbiAoZXhwZWN0YXRpb24pIHtcbiAgICByZXR1cm4gY3JlYXRlTWF0Y2hlcihcbiAgICAgICAgZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgLy8gQ29tcGFyaW5nIGxlbmd0aHMgaXMgdGhlIGZhc3Rlc3Qgd2F5IHRvIHNwb3QgYSBkaWZmZXJlbmNlIGJlZm9yZSBpdGVyYXRpbmcgdGhyb3VnaCBldmVyeSBpdGVtXG4gICAgICAgICAgICB2YXIgc2FtZUxlbmd0aCA9IGFjdHVhbC5sZW5ndGggPT09IGV4cGVjdGF0aW9uLmxlbmd0aDtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgdHlwZU9mKGFjdHVhbCkgPT09IFwiYXJyYXlcIiAmJlxuICAgICAgICAgICAgICAgIHNhbWVMZW5ndGggJiZcbiAgICAgICAgICAgICAgICBldmVyeShhY3R1YWwsIGZ1bmN0aW9uIChlbGVtZW50LCBpbmRleCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXhwZWN0ZWQgPSBleHBlY3RhdGlvbltpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0eXBlT2YoZXhwZWN0ZWQpID09PSBcImFycmF5XCIgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVPZihlbGVtZW50KSA9PT0gXCJhcnJheVwiXG4gICAgICAgICAgICAgICAgICAgICAgICA/IGNyZWF0ZU1hdGNoZXIuYXJyYXkuZGVlcEVxdWFscyhleHBlY3RlZCkudGVzdChlbGVtZW50KVxuICAgICAgICAgICAgICAgICAgICAgICAgOiBkZWVwRXF1YWwoZXhwZWN0ZWQsIGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApO1xuICAgICAgICB9LFxuICAgICAgICBgZGVlcEVxdWFscyhbJHtpdGVyYWJsZVRvU3RyaW5nKGV4cGVjdGF0aW9uKX1dKWAsXG4gICAgKTtcbn07XG5cbmNyZWF0ZU1hdGNoZXIuYXJyYXkuc3RhcnRzV2l0aCA9IGZ1bmN0aW9uIChleHBlY3RhdGlvbikge1xuICAgIHJldHVybiBjcmVhdGVNYXRjaGVyKFxuICAgICAgICBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIHR5cGVPZihhY3R1YWwpID09PSBcImFycmF5XCIgJiZcbiAgICAgICAgICAgICAgICBldmVyeShleHBlY3RhdGlvbiwgZnVuY3Rpb24gKGV4cGVjdGVkRWxlbWVudCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFjdHVhbFtpbmRleF0gPT09IGV4cGVjdGVkRWxlbWVudDtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSxcbiAgICAgICAgYHN0YXJ0c1dpdGgoWyR7aXRlcmFibGVUb1N0cmluZyhleHBlY3RhdGlvbil9XSlgLFxuICAgICk7XG59O1xuXG5jcmVhdGVNYXRjaGVyLmFycmF5LmVuZHNXaXRoID0gZnVuY3Rpb24gKGV4cGVjdGF0aW9uKSB7XG4gICAgcmV0dXJuIGNyZWF0ZU1hdGNoZXIoXG4gICAgICAgIGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgaW5kaWNhdGVzIHRoZSBpbmRleCBpbiB3aGljaCB3ZSBzaG91bGQgc3RhcnQgbWF0Y2hpbmdcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSBhY3R1YWwubGVuZ3RoIC0gZXhwZWN0YXRpb24ubGVuZ3RoO1xuXG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIHR5cGVPZihhY3R1YWwpID09PSBcImFycmF5XCIgJiZcbiAgICAgICAgICAgICAgICBldmVyeShleHBlY3RhdGlvbiwgZnVuY3Rpb24gKGV4cGVjdGVkRWxlbWVudCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFjdHVhbFtvZmZzZXQgKyBpbmRleF0gPT09IGV4cGVjdGVkRWxlbWVudDtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSxcbiAgICAgICAgYGVuZHNXaXRoKFske2l0ZXJhYmxlVG9TdHJpbmcoZXhwZWN0YXRpb24pfV0pYCxcbiAgICApO1xufTtcblxuY3JlYXRlTWF0Y2hlci5hcnJheS5jb250YWlucyA9IGZ1bmN0aW9uIChleHBlY3RhdGlvbikge1xuICAgIHJldHVybiBjcmVhdGVNYXRjaGVyKFxuICAgICAgICBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIHR5cGVPZihhY3R1YWwpID09PSBcImFycmF5XCIgJiZcbiAgICAgICAgICAgICAgICBldmVyeShleHBlY3RhdGlvbiwgZnVuY3Rpb24gKGV4cGVjdGVkRWxlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXJyYXlJbmRleE9mKGFjdHVhbCwgZXhwZWN0ZWRFbGVtZW50KSAhPT0gLTE7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0sXG4gICAgICAgIGBjb250YWlucyhbJHtpdGVyYWJsZVRvU3RyaW5nKGV4cGVjdGF0aW9uKX1dKWAsXG4gICAgKTtcbn07XG5cbmNyZWF0ZU1hdGNoZXIubWFwID0gY3JlYXRlTWF0Y2hlci50eXBlT2YoXCJtYXBcIik7XG5cbmNyZWF0ZU1hdGNoZXIubWFwLmRlZXBFcXVhbHMgPSBmdW5jdGlvbiBtYXBEZWVwRXF1YWxzKGV4cGVjdGF0aW9uKSB7XG4gICAgcmV0dXJuIGNyZWF0ZU1hdGNoZXIoXG4gICAgICAgIGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgIC8vIENvbXBhcmluZyBsZW5ndGhzIGlzIHRoZSBmYXN0ZXN0IHdheSB0byBzcG90IGEgZGlmZmVyZW5jZSBiZWZvcmUgaXRlcmF0aW5nIHRocm91Z2ggZXZlcnkgaXRlbVxuICAgICAgICAgICAgdmFyIHNhbWVMZW5ndGggPSBhY3R1YWwuc2l6ZSA9PT0gZXhwZWN0YXRpb24uc2l6ZTtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgdHlwZU9mKGFjdHVhbCkgPT09IFwibWFwXCIgJiZcbiAgICAgICAgICAgICAgICBzYW1lTGVuZ3RoICYmXG4gICAgICAgICAgICAgICAgZXZlcnkoYWN0dWFsLCBmdW5jdGlvbiAoZWxlbWVudCwga2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBleHBlY3RhdGlvbi5oYXMoa2V5KSAmJiBleHBlY3RhdGlvbi5nZXQoa2V5KSA9PT0gZWxlbWVudFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApO1xuICAgICAgICB9LFxuICAgICAgICBgZGVlcEVxdWFscyhNYXBbJHtpdGVyYWJsZVRvU3RyaW5nKGV4cGVjdGF0aW9uKX1dKWAsXG4gICAgKTtcbn07XG5cbmNyZWF0ZU1hdGNoZXIubWFwLmNvbnRhaW5zID0gZnVuY3Rpb24gbWFwQ29udGFpbnMoZXhwZWN0YXRpb24pIHtcbiAgICByZXR1cm4gY3JlYXRlTWF0Y2hlcihcbiAgICAgICAgZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICB0eXBlT2YoYWN0dWFsKSA9PT0gXCJtYXBcIiAmJlxuICAgICAgICAgICAgICAgIGV2ZXJ5KGV4cGVjdGF0aW9uLCBmdW5jdGlvbiAoZWxlbWVudCwga2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhY3R1YWwuaGFzKGtleSkgJiYgYWN0dWFsLmdldChrZXkpID09PSBlbGVtZW50O1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApO1xuICAgICAgICB9LFxuICAgICAgICBgY29udGFpbnMoTWFwWyR7aXRlcmFibGVUb1N0cmluZyhleHBlY3RhdGlvbil9XSlgLFxuICAgICk7XG59O1xuXG5jcmVhdGVNYXRjaGVyLnNldCA9IGNyZWF0ZU1hdGNoZXIudHlwZU9mKFwic2V0XCIpO1xuXG5jcmVhdGVNYXRjaGVyLnNldC5kZWVwRXF1YWxzID0gZnVuY3Rpb24gc2V0RGVlcEVxdWFscyhleHBlY3RhdGlvbikge1xuICAgIHJldHVybiBjcmVhdGVNYXRjaGVyKFxuICAgICAgICBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICAvLyBDb21wYXJpbmcgbGVuZ3RocyBpcyB0aGUgZmFzdGVzdCB3YXkgdG8gc3BvdCBhIGRpZmZlcmVuY2UgYmVmb3JlIGl0ZXJhdGluZyB0aHJvdWdoIGV2ZXJ5IGl0ZW1cbiAgICAgICAgICAgIHZhciBzYW1lTGVuZ3RoID0gYWN0dWFsLnNpemUgPT09IGV4cGVjdGF0aW9uLnNpemU7XG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIHR5cGVPZihhY3R1YWwpID09PSBcInNldFwiICYmXG4gICAgICAgICAgICAgICAgc2FtZUxlbmd0aCAmJlxuICAgICAgICAgICAgICAgIGV2ZXJ5KGFjdHVhbCwgZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV4cGVjdGF0aW9uLmhhcyhlbGVtZW50KTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSxcbiAgICAgICAgYGRlZXBFcXVhbHMoU2V0WyR7aXRlcmFibGVUb1N0cmluZyhleHBlY3RhdGlvbil9XSlgLFxuICAgICk7XG59O1xuXG5jcmVhdGVNYXRjaGVyLnNldC5jb250YWlucyA9IGZ1bmN0aW9uIHNldENvbnRhaW5zKGV4cGVjdGF0aW9uKSB7XG4gICAgcmV0dXJuIGNyZWF0ZU1hdGNoZXIoXG4gICAgICAgIGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgdHlwZU9mKGFjdHVhbCkgPT09IFwic2V0XCIgJiZcbiAgICAgICAgICAgICAgICBldmVyeShleHBlY3RhdGlvbiwgZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFjdHVhbC5oYXMoZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0sXG4gICAgICAgIGBjb250YWlucyhTZXRbJHtpdGVyYWJsZVRvU3RyaW5nKGV4cGVjdGF0aW9uKX1dKWAsXG4gICAgKTtcbn07XG5cbmNyZWF0ZU1hdGNoZXIuYm9vbCA9IGNyZWF0ZU1hdGNoZXIudHlwZU9mKFwiYm9vbGVhblwiKTtcbmNyZWF0ZU1hdGNoZXIubnVtYmVyID0gY3JlYXRlTWF0Y2hlci50eXBlT2YoXCJudW1iZXJcIik7XG5jcmVhdGVNYXRjaGVyLnN0cmluZyA9IGNyZWF0ZU1hdGNoZXIudHlwZU9mKFwic3RyaW5nXCIpO1xuY3JlYXRlTWF0Y2hlci5vYmplY3QgPSBjcmVhdGVNYXRjaGVyLnR5cGVPZihcIm9iamVjdFwiKTtcbmNyZWF0ZU1hdGNoZXIuZnVuYyA9IGNyZWF0ZU1hdGNoZXIudHlwZU9mKFwiZnVuY3Rpb25cIik7XG5jcmVhdGVNYXRjaGVyLnJlZ2V4cCA9IGNyZWF0ZU1hdGNoZXIudHlwZU9mKFwicmVnZXhwXCIpO1xuY3JlYXRlTWF0Y2hlci5kYXRlID0gY3JlYXRlTWF0Y2hlci50eXBlT2YoXCJkYXRlXCIpO1xuY3JlYXRlTWF0Y2hlci5zeW1ib2wgPSBjcmVhdGVNYXRjaGVyLnR5cGVPZihcInN5bWJvbFwiKTtcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVNYXRjaGVyO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBpc01hdGNoZXIgPSByZXF1aXJlKFwiLi9pcy1tYXRjaGVyXCIpO1xuXG4vKipcbiAqIFRocm93cyBhIFR5cGVFcnJvciB3aGVuIGB2YWx1ZWAgaXMgbm90IGEgbWF0Y2hlclxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBleGFtaW5lXG4gKi9cbmZ1bmN0aW9uIGFzc2VydE1hdGNoZXIodmFsdWUpIHtcbiAgICBpZiAoIWlzTWF0Y2hlcih2YWx1ZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk1hdGNoZXIgZXhwZWN0ZWRcIik7XG4gICAgfVxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGFzc2VydE1hdGNoZXI7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuLyoqXG4gKiBUaHJvd3MgYSBUeXBlRXJyb3Igd2hlbiBleHBlY3RlZCBtZXRob2QgZG9lc24ndCBleGlzdFxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIEEgdmFsdWUgdG8gZXhhbWluZVxuICogQHBhcmFtIHtzdHJpbmd9IG1ldGhvZCBUaGUgbmFtZSBvZiB0aGUgbWV0aG9kIHRvIGxvb2sgZm9yXG4gKiBAcGFyYW0ge25hbWV9IG5hbWUgQSBuYW1lIHRvIHVzZSBmb3IgdGhlIGVycm9yIG1lc3NhZ2VcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXRob2RQYXRoIFRoZSBuYW1lIG9mIHRoZSBtZXRob2QgdG8gdXNlIGZvciBlcnJvciBtZXNzYWdlc1xuICogQHRocm93cyB7VHlwZUVycm9yfSBXaGVuIHRoZSBtZXRob2QgZG9lc24ndCBleGlzdFxuICovXG5mdW5jdGlvbiBhc3NlcnRNZXRob2RFeGlzdHModmFsdWUsIG1ldGhvZCwgbmFtZSwgbWV0aG9kUGF0aCkge1xuICAgIGlmICh2YWx1ZVttZXRob2RdID09PSBudWxsIHx8IHZhbHVlW21ldGhvZF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBFeHBlY3RlZCAke25hbWV9IHRvIGhhdmUgbWV0aG9kICR7bWV0aG9kUGF0aH1gKTtcbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYXNzZXJ0TWV0aG9kRXhpc3RzO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciB0eXBlT2YgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS50eXBlT2Y7XG5cbi8qKlxuICogRW5zdXJlcyB0aGF0IHZhbHVlIGlzIG9mIHR5cGVcbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBBIHZhbHVlIHRvIGV4YW1pbmVcbiAqIEBwYXJhbSB7c3RyaW5nfSB0eXBlIEEgYmFzaWMgSmF2YVNjcmlwdCB0eXBlIHRvIGNvbXBhcmUgdG8sIGUuZy4gXCJvYmplY3RcIiwgXCJzdHJpbmdcIlxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgQSBzdHJpbmcgdG8gdXNlIGZvciB0aGUgZXJyb3IgbWVzc2FnZVxuICogQHRocm93cyB7VHlwZUVycm9yfSBJZiB2YWx1ZSBpcyBub3Qgb2YgdGhlIGV4cGVjdGVkIHR5cGVcbiAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gKi9cbmZ1bmN0aW9uIGFzc2VydFR5cGUodmFsdWUsIHR5cGUsIG5hbWUpIHtcbiAgICB2YXIgYWN0dWFsID0gdHlwZU9mKHZhbHVlKTtcbiAgICBpZiAoYWN0dWFsICE9PSB0eXBlKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXG4gICAgICAgICAgICBgRXhwZWN0ZWQgdHlwZSBvZiAke25hbWV9IHRvIGJlICR7dHlwZX0sIGJ1dCB3YXMgJHthY3R1YWx9YCxcbiAgICAgICAgKTtcbiAgICB9XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYXNzZXJ0VHlwZTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgdHlwZU9mID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikudHlwZU9mO1xuXG4vKipcbiAqIFJldHVybnMgYHRydWVgIGZvciBpdGVyYWJsZXNcbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBBIHZhbHVlIHRvIGV4YW1pbmVcbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCB3aGVuIGB2YWx1ZWAgbG9va3MgbGlrZSBhbiBpdGVyYWJsZVxuICovXG5mdW5jdGlvbiBpc0l0ZXJhYmxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJvb2xlYW4odmFsdWUpICYmIHR5cGVPZih2YWx1ZS5mb3JFYWNoKSA9PT0gXCJmdW5jdGlvblwiO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlzSXRlcmFibGU7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGlzUHJvdG90eXBlT2YgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLm9iamVjdC5pc1Byb3RvdHlwZU9mO1xuXG52YXIgbWF0Y2hlclByb3RvdHlwZSA9IHJlcXVpcmUoXCIuL21hdGNoZXItcHJvdG90eXBlXCIpO1xuXG4vKipcbiAqIFJldHVybnMgYHRydWVgIHdoZW4gYG9iamVjdGAgaXMgYSBtYXRjaGVyXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gb2JqZWN0IEEgdmFsdWUgdG8gZXhhbWluZVxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIHdoZW4gYG9iamVjdGAgaXMgYSBtYXRjaGVyXG4gKi9cbmZ1bmN0aW9uIGlzTWF0Y2hlcihvYmplY3QpIHtcbiAgICByZXR1cm4gaXNQcm90b3R5cGVPZihtYXRjaGVyUHJvdG90eXBlLCBvYmplY3QpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlzTWF0Y2hlcjtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgZXZlcnkgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLmFycmF5LmV2ZXJ5O1xudmFyIGNvbmNhdCA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnByb3RvdHlwZXMuYXJyYXkuY29uY2F0O1xudmFyIHR5cGVPZiA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnR5cGVPZjtcblxudmFyIGRlZXBFcXVhbEZhY3RvcnkgPSByZXF1aXJlKFwiLi4vZGVlcC1lcXVhbFwiKS51c2U7XG5cbnZhciBpZGVudGljYWwgPSByZXF1aXJlKFwiLi4vaWRlbnRpY2FsXCIpO1xudmFyIGlzTWF0Y2hlciA9IHJlcXVpcmUoXCIuL2lzLW1hdGNoZXJcIik7XG5cbnZhciBrZXlzID0gT2JqZWN0LmtleXM7XG52YXIgZ2V0T3duUHJvcGVydHlTeW1ib2xzID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scztcblxuLyoqXG4gKiBNYXRjaGVzIGBhY3R1YWxgIHdpdGggYGV4cGVjdGF0aW9uYFxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IGFjdHVhbCBBIHZhbHVlIHRvIGV4YW1pbmVcbiAqIEBwYXJhbSB7b2JqZWN0fSBleHBlY3RhdGlvbiBBbiBvYmplY3Qgd2l0aCBwcm9wZXJ0aWVzIHRvIG1hdGNoIG9uXG4gKiBAcGFyYW0ge29iamVjdH0gbWF0Y2hlciBBIG1hdGNoZXIgdG8gdXNlIGZvciBjb21wYXJpc29uXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyB0cnVlIHdoZW4gYGFjdHVhbGAgbWF0Y2hlcyBhbGwgcHJvcGVydGllcyBpbiBgZXhwZWN0YXRpb25gXG4gKi9cbmZ1bmN0aW9uIG1hdGNoT2JqZWN0KGFjdHVhbCwgZXhwZWN0YXRpb24sIG1hdGNoZXIpIHtcbiAgICB2YXIgZGVlcEVxdWFsID0gZGVlcEVxdWFsRmFjdG9yeShtYXRjaGVyKTtcbiAgICBpZiAoYWN0dWFsID09PSBudWxsIHx8IGFjdHVhbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB2YXIgZXhwZWN0ZWRLZXlzID0ga2V5cyhleHBlY3RhdGlvbik7XG4gICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2U6IGNhbm5vdCBjb2xsZWN0IGNvdmVyYWdlIGZvciBlbmdpbmUgdGhhdCBkb2Vzbid0IHN1cHBvcnQgU3ltYm9sICovXG4gICAgaWYgKHR5cGVPZihnZXRPd25Qcm9wZXJ0eVN5bWJvbHMpID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgZXhwZWN0ZWRLZXlzID0gY29uY2F0KGV4cGVjdGVkS2V5cywgZ2V0T3duUHJvcGVydHlTeW1ib2xzKGV4cGVjdGF0aW9uKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGV2ZXJ5KGV4cGVjdGVkS2V5cywgZnVuY3Rpb24gKGtleSkge1xuICAgICAgICB2YXIgZXhwID0gZXhwZWN0YXRpb25ba2V5XTtcbiAgICAgICAgdmFyIGFjdCA9IGFjdHVhbFtrZXldO1xuXG4gICAgICAgIGlmIChpc01hdGNoZXIoZXhwKSkge1xuICAgICAgICAgICAgaWYgKCFleHAudGVzdChhY3QpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHR5cGVPZihleHApID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICBpZiAoaWRlbnRpY2FsKGV4cCwgYWN0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFtYXRjaE9iamVjdChhY3QsIGV4cCwgbWF0Y2hlcikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoIWRlZXBFcXVhbChhY3QsIGV4cCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG1hdGNoT2JqZWN0O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBtYXRjaGVyUHJvdG90eXBlID0ge1xuICAgIHRvU3RyaW5nOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2U7XG4gICAgfSxcbn07XG5cbm1hdGNoZXJQcm90b3R5cGUub3IgPSBmdW5jdGlvbiAodmFsdWVPck1hdGNoZXIpIHtcbiAgICB2YXIgY3JlYXRlTWF0Y2hlciA9IHJlcXVpcmUoXCIuLi9jcmVhdGUtbWF0Y2hlclwiKTtcbiAgICB2YXIgaXNNYXRjaGVyID0gY3JlYXRlTWF0Y2hlci5pc01hdGNoZXI7XG5cbiAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk1hdGNoZXIgZXhwZWN0ZWRcIik7XG4gICAgfVxuXG4gICAgdmFyIG0yID0gaXNNYXRjaGVyKHZhbHVlT3JNYXRjaGVyKVxuICAgICAgICA/IHZhbHVlT3JNYXRjaGVyXG4gICAgICAgIDogY3JlYXRlTWF0Y2hlcih2YWx1ZU9yTWF0Y2hlcik7XG4gICAgdmFyIG0xID0gdGhpcztcbiAgICB2YXIgb3IgPSBPYmplY3QuY3JlYXRlKG1hdGNoZXJQcm90b3R5cGUpO1xuICAgIG9yLnRlc3QgPSBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgIHJldHVybiBtMS50ZXN0KGFjdHVhbCkgfHwgbTIudGVzdChhY3R1YWwpO1xuICAgIH07XG4gICAgb3IubWVzc2FnZSA9IGAke20xLm1lc3NhZ2V9Lm9yKCR7bTIubWVzc2FnZX0pYDtcbiAgICByZXR1cm4gb3I7XG59O1xuXG5tYXRjaGVyUHJvdG90eXBlLmFuZCA9IGZ1bmN0aW9uICh2YWx1ZU9yTWF0Y2hlcikge1xuICAgIHZhciBjcmVhdGVNYXRjaGVyID0gcmVxdWlyZShcIi4uL2NyZWF0ZS1tYXRjaGVyXCIpO1xuICAgIHZhciBpc01hdGNoZXIgPSBjcmVhdGVNYXRjaGVyLmlzTWF0Y2hlcjtcblxuICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWF0Y2hlciBleHBlY3RlZFwiKTtcbiAgICB9XG5cbiAgICB2YXIgbTIgPSBpc01hdGNoZXIodmFsdWVPck1hdGNoZXIpXG4gICAgICAgID8gdmFsdWVPck1hdGNoZXJcbiAgICAgICAgOiBjcmVhdGVNYXRjaGVyKHZhbHVlT3JNYXRjaGVyKTtcbiAgICB2YXIgbTEgPSB0aGlzO1xuICAgIHZhciBhbmQgPSBPYmplY3QuY3JlYXRlKG1hdGNoZXJQcm90b3R5cGUpO1xuICAgIGFuZC50ZXN0ID0gZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICByZXR1cm4gbTEudGVzdChhY3R1YWwpICYmIG0yLnRlc3QoYWN0dWFsKTtcbiAgICB9O1xuICAgIGFuZC5tZXNzYWdlID0gYCR7bTEubWVzc2FnZX0uYW5kKCR7bTIubWVzc2FnZX0pYDtcbiAgICByZXR1cm4gYW5kO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBtYXRjaGVyUHJvdG90eXBlO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBmdW5jdGlvbk5hbWUgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5mdW5jdGlvbk5hbWU7XG52YXIgam9pbiA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnByb3RvdHlwZXMuYXJyYXkuam9pbjtcbnZhciBtYXAgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLmFycmF5Lm1hcDtcbnZhciBzdHJpbmdJbmRleE9mID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikucHJvdG90eXBlcy5zdHJpbmcuaW5kZXhPZjtcbnZhciB2YWx1ZVRvU3RyaW5nID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikudmFsdWVUb1N0cmluZztcblxudmFyIG1hdGNoT2JqZWN0ID0gcmVxdWlyZShcIi4vbWF0Y2gtb2JqZWN0XCIpO1xuXG52YXIgY3JlYXRlVHlwZU1hcCA9IGZ1bmN0aW9uIChtYXRjaCkge1xuICAgIHJldHVybiB7XG4gICAgICAgIGZ1bmN0aW9uOiBmdW5jdGlvbiAobSwgZXhwZWN0YXRpb24sIG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIG0udGVzdCA9IGV4cGVjdGF0aW9uO1xuICAgICAgICAgICAgbS5tZXNzYWdlID0gbWVzc2FnZSB8fCBgbWF0Y2goJHtmdW5jdGlvbk5hbWUoZXhwZWN0YXRpb24pfSlgO1xuICAgICAgICB9LFxuICAgICAgICBudW1iZXI6IGZ1bmN0aW9uIChtLCBleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgbS50ZXN0ID0gZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgICAgIC8vIHdlIG5lZWQgdHlwZSBjb2VyY2lvbiBoZXJlXG4gICAgICAgICAgICAgICAgcmV0dXJuIGV4cGVjdGF0aW9uID09IGFjdHVhbDsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBlcWVxZXFcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sXG4gICAgICAgIG9iamVjdDogZnVuY3Rpb24gKG0sIGV4cGVjdGF0aW9uKSB7XG4gICAgICAgICAgICB2YXIgYXJyYXkgPSBbXTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBleHBlY3RhdGlvbi50ZXN0ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICBtLnRlc3QgPSBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBleHBlY3RhdGlvbi50ZXN0KGFjdHVhbCkgPT09IHRydWU7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBtLm1lc3NhZ2UgPSBgbWF0Y2goJHtmdW5jdGlvbk5hbWUoZXhwZWN0YXRpb24udGVzdCl9KWA7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGFycmF5ID0gbWFwKE9iamVjdC5rZXlzKGV4cGVjdGF0aW9uKSwgZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBgJHtrZXl9OiAke3ZhbHVlVG9TdHJpbmcoZXhwZWN0YXRpb25ba2V5XSl9YDtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBtLnRlc3QgPSBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hdGNoT2JqZWN0KGFjdHVhbCwgZXhwZWN0YXRpb24sIG1hdGNoKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBtLm1lc3NhZ2UgPSBgbWF0Y2goJHtqb2luKGFycmF5LCBcIiwgXCIpfSlgO1xuXG4gICAgICAgICAgICByZXR1cm4gbTtcbiAgICAgICAgfSxcbiAgICAgICAgcmVnZXhwOiBmdW5jdGlvbiAobSwgZXhwZWN0YXRpb24pIHtcbiAgICAgICAgICAgIG0udGVzdCA9IGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIGFjdHVhbCA9PT0gXCJzdHJpbmdcIiAmJiBleHBlY3RhdGlvbi50ZXN0KGFjdHVhbCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LFxuICAgICAgICBzdHJpbmc6IGZ1bmN0aW9uIChtLCBleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgbS50ZXN0ID0gZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgICAgIHR5cGVvZiBhY3R1YWwgPT09IFwic3RyaW5nXCIgJiZcbiAgICAgICAgICAgICAgICAgICAgc3RyaW5nSW5kZXhPZihhY3R1YWwsIGV4cGVjdGF0aW9uKSAhPT0gLTFcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIG0ubWVzc2FnZSA9IGBtYXRjaChcIiR7ZXhwZWN0YXRpb259XCIpYDtcbiAgICAgICAgfSxcbiAgICB9O1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVUeXBlTWFwO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciB2YWx1ZVRvU3RyaW5nID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikudmFsdWVUb1N0cmluZztcbnZhciBjbGFzc05hbWUgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5jbGFzc05hbWU7XG52YXIgdHlwZU9mID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikudHlwZU9mO1xudmFyIGFycmF5UHJvdG8gPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLmFycmF5O1xudmFyIG9iamVjdFByb3RvID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikucHJvdG90eXBlcy5vYmplY3Q7XG52YXIgbWFwRm9yRWFjaCA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnByb3RvdHlwZXMubWFwLmZvckVhY2g7XG5cbnZhciBnZXRDbGFzcyA9IHJlcXVpcmUoXCIuL2dldC1jbGFzc1wiKTtcbnZhciBpZGVudGljYWwgPSByZXF1aXJlKFwiLi9pZGVudGljYWxcIik7XG52YXIgaXNBcmd1bWVudHMgPSByZXF1aXJlKFwiLi9pcy1hcmd1bWVudHNcIik7XG52YXIgaXNBcnJheVR5cGUgPSByZXF1aXJlKFwiLi9pcy1hcnJheS10eXBlXCIpO1xudmFyIGlzRGF0ZSA9IHJlcXVpcmUoXCIuL2lzLWRhdGVcIik7XG52YXIgaXNFbGVtZW50ID0gcmVxdWlyZShcIi4vaXMtZWxlbWVudFwiKTtcbnZhciBpc0l0ZXJhYmxlID0gcmVxdWlyZShcIi4vaXMtaXRlcmFibGVcIik7XG52YXIgaXNNYXAgPSByZXF1aXJlKFwiLi9pcy1tYXBcIik7XG52YXIgaXNOYU4gPSByZXF1aXJlKFwiLi9pcy1uYW5cIik7XG52YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiLi9pcy1vYmplY3RcIik7XG52YXIgaXNTZXQgPSByZXF1aXJlKFwiLi9pcy1zZXRcIik7XG52YXIgaXNTdWJzZXQgPSByZXF1aXJlKFwiLi9pcy1zdWJzZXRcIik7XG5cbnZhciBjb25jYXQgPSBhcnJheVByb3RvLmNvbmNhdDtcbnZhciBldmVyeSA9IGFycmF5UHJvdG8uZXZlcnk7XG52YXIgcHVzaCA9IGFycmF5UHJvdG8ucHVzaDtcblxudmFyIGdldFRpbWUgPSBEYXRlLnByb3RvdHlwZS5nZXRUaW1lO1xudmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG52YXIgaW5kZXhPZiA9IGFycmF5UHJvdG8uaW5kZXhPZjtcbnZhciBrZXlzID0gT2JqZWN0LmtleXM7XG52YXIgZ2V0T3duUHJvcGVydHlTeW1ib2xzID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scztcblxuLyoqXG4gKiBEZWVwIGVxdWFsIGNvbXBhcmlzb24uIFR3byB2YWx1ZXMgYXJlIFwiZGVlcCBlcXVhbFwiIHdoZW46XG4gKlxuICogICAtIFRoZXkgYXJlIGVxdWFsLCBhY2NvcmRpbmcgdG8gc2Ftc2FtLmlkZW50aWNhbFxuICogICAtIFRoZXkgYXJlIGJvdGggZGF0ZSBvYmplY3RzIHJlcHJlc2VudGluZyB0aGUgc2FtZSB0aW1lXG4gKiAgIC0gVGhleSBhcmUgYm90aCBhcnJheXMgY29udGFpbmluZyBlbGVtZW50cyB0aGF0IGFyZSBhbGwgZGVlcEVxdWFsXG4gKiAgIC0gVGhleSBhcmUgb2JqZWN0cyB3aXRoIHRoZSBzYW1lIHNldCBvZiBwcm9wZXJ0aWVzLCBhbmQgZWFjaCBwcm9wZXJ0eVxuICogICAgIGluIGBgYWN0dWFsYGAgaXMgZGVlcEVxdWFsIHRvIHRoZSBjb3JyZXNwb25kaW5nIHByb3BlcnR5IGluIGBgZXhwZWN0YXRpb25gYFxuICpcbiAqIFN1cHBvcnRzIGN5Y2xpYyBvYmplY3RzLlxuICpcbiAqIEBhbGlhcyBtb2R1bGU6c2Ftc2FtLmRlZXBFcXVhbFxuICogQHBhcmFtIHsqfSBhY3R1YWwgVGhlIG9iamVjdCB0byBleGFtaW5lXG4gKiBAcGFyYW0geyp9IGV4cGVjdGF0aW9uIFRoZSBvYmplY3QgYWN0dWFsIGlzIGV4cGVjdGVkIHRvIGJlIGVxdWFsIHRvXG4gKiBAcGFyYW0ge29iamVjdH0gbWF0Y2ggQSB2YWx1ZSB0byBtYXRjaCBvblxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgdHJ1ZSB3aGVuIGFjdHVhbCBhbmQgZXhwZWN0YXRpb24gYXJlIGNvbnNpZGVyZWQgZXF1YWxcbiAqL1xuZnVuY3Rpb24gZGVlcEVxdWFsQ3ljbGljKGFjdHVhbCwgZXhwZWN0YXRpb24sIG1hdGNoKSB7XG4gICAgLy8gdXNlZCBmb3IgY3ljbGljIGNvbXBhcmlzb25cbiAgICAvLyBjb250YWluIGFscmVhZHkgdmlzaXRlZCBvYmplY3RzXG4gICAgdmFyIGFjdHVhbE9iamVjdHMgPSBbXTtcbiAgICB2YXIgZXhwZWN0YXRpb25PYmplY3RzID0gW107XG4gICAgLy8gY29udGFpbiBwYXRoZXMgKHBvc2l0aW9uIGluIHRoZSBvYmplY3Qgc3RydWN0dXJlKVxuICAgIC8vIG9mIHRoZSBhbHJlYWR5IHZpc2l0ZWQgb2JqZWN0c1xuICAgIC8vIGluZGV4ZXMgc2FtZSBhcyBpbiBvYmplY3RzIGFycmF5c1xuICAgIHZhciBhY3R1YWxQYXRocyA9IFtdO1xuICAgIHZhciBleHBlY3RhdGlvblBhdGhzID0gW107XG4gICAgLy8gY29udGFpbnMgY29tYmluYXRpb25zIG9mIGFscmVhZHkgY29tcGFyZWQgb2JqZWN0c1xuICAgIC8vIGluIHRoZSBtYW5uZXI6IHsgXCIkMVsncmVmJ10kMlsncmVmJ11cIjogdHJ1ZSB9XG4gICAgdmFyIGNvbXBhcmVkID0ge307XG5cbiAgICAvLyBkb2VzIHRoZSByZWN1cnNpb24gZm9yIHRoZSBkZWVwIGVxdWFsIGNoZWNrXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHlcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGRlZXBFcXVhbChcbiAgICAgICAgYWN0dWFsT2JqLFxuICAgICAgICBleHBlY3RhdGlvbk9iaixcbiAgICAgICAgYWN0dWFsUGF0aCxcbiAgICAgICAgZXhwZWN0YXRpb25QYXRoLFxuICAgICkge1xuICAgICAgICAvLyBJZiBib3RoIGFyZSBtYXRjaGVycyB0aGV5IG11c3QgYmUgdGhlIHNhbWUgaW5zdGFuY2UgaW4gb3JkZXIgdG8gYmVcbiAgICAgICAgLy8gY29uc2lkZXJlZCBlcXVhbCBJZiB3ZSBkaWRuJ3QgZG8gdGhhdCB3ZSB3b3VsZCBlbmQgdXAgcnVubmluZyBvbmVcbiAgICAgICAgLy8gbWF0Y2hlciBhZ2FpbnN0IHRoZSBvdGhlclxuICAgICAgICBpZiAobWF0Y2ggJiYgbWF0Y2guaXNNYXRjaGVyKGV4cGVjdGF0aW9uT2JqKSkge1xuICAgICAgICAgICAgaWYgKG1hdGNoLmlzTWF0Y2hlcihhY3R1YWxPYmopKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFjdHVhbE9iaiA9PT0gZXhwZWN0YXRpb25PYmo7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZXhwZWN0YXRpb25PYmoudGVzdChhY3R1YWxPYmopO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGFjdHVhbFR5cGUgPSB0eXBlb2YgYWN0dWFsT2JqO1xuICAgICAgICB2YXIgZXhwZWN0YXRpb25UeXBlID0gdHlwZW9mIGV4cGVjdGF0aW9uT2JqO1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGFjdHVhbE9iaiA9PT0gZXhwZWN0YXRpb25PYmogfHxcbiAgICAgICAgICAgIGlzTmFOKGFjdHVhbE9iaikgfHxcbiAgICAgICAgICAgIGlzTmFOKGV4cGVjdGF0aW9uT2JqKSB8fFxuICAgICAgICAgICAgYWN0dWFsT2JqID09PSBudWxsIHx8XG4gICAgICAgICAgICBleHBlY3RhdGlvbk9iaiA9PT0gbnVsbCB8fFxuICAgICAgICAgICAgYWN0dWFsT2JqID09PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAgIGV4cGVjdGF0aW9uT2JqID09PSB1bmRlZmluZWQgfHxcbiAgICAgICAgICAgIGFjdHVhbFR5cGUgIT09IFwib2JqZWN0XCIgfHxcbiAgICAgICAgICAgIGV4cGVjdGF0aW9uVHlwZSAhPT0gXCJvYmplY3RcIlxuICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiBpZGVudGljYWwoYWN0dWFsT2JqLCBleHBlY3RhdGlvbk9iaik7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBFbGVtZW50cyBhcmUgb25seSBlcXVhbCBpZiBpZGVudGljYWwoZXhwZWN0ZWQsIGFjdHVhbClcbiAgICAgICAgaWYgKGlzRWxlbWVudChhY3R1YWxPYmopIHx8IGlzRWxlbWVudChleHBlY3RhdGlvbk9iaikpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBpc0FjdHVhbERhdGUgPSBpc0RhdGUoYWN0dWFsT2JqKTtcbiAgICAgICAgdmFyIGlzRXhwZWN0YXRpb25EYXRlID0gaXNEYXRlKGV4cGVjdGF0aW9uT2JqKTtcbiAgICAgICAgaWYgKGlzQWN0dWFsRGF0ZSB8fCBpc0V4cGVjdGF0aW9uRGF0ZSkge1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICFpc0FjdHVhbERhdGUgfHxcbiAgICAgICAgICAgICAgICAhaXNFeHBlY3RhdGlvbkRhdGUgfHxcbiAgICAgICAgICAgICAgICBnZXRUaW1lLmNhbGwoYWN0dWFsT2JqKSAhPT0gZ2V0VGltZS5jYWxsKGV4cGVjdGF0aW9uT2JqKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGFjdHVhbE9iaiBpbnN0YW5jZW9mIFJlZ0V4cCAmJiBleHBlY3RhdGlvbk9iaiBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgaWYgKHZhbHVlVG9TdHJpbmcoYWN0dWFsT2JqKSAhPT0gdmFsdWVUb1N0cmluZyhleHBlY3RhdGlvbk9iaikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYWN0dWFsT2JqIGluc3RhbmNlb2YgUHJvbWlzZSAmJiBleHBlY3RhdGlvbk9iaiBpbnN0YW5jZW9mIFByb21pc2UpIHtcbiAgICAgICAgICAgIHJldHVybiBhY3R1YWxPYmogPT09IGV4cGVjdGF0aW9uT2JqO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGFjdHVhbE9iaiBpbnN0YW5jZW9mIEVycm9yICYmIGV4cGVjdGF0aW9uT2JqIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBhY3R1YWxPYmogPT09IGV4cGVjdGF0aW9uT2JqO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGFjdHVhbENsYXNzID0gZ2V0Q2xhc3MoYWN0dWFsT2JqKTtcbiAgICAgICAgdmFyIGV4cGVjdGF0aW9uQ2xhc3MgPSBnZXRDbGFzcyhleHBlY3RhdGlvbk9iaik7XG4gICAgICAgIHZhciBhY3R1YWxLZXlzID0ga2V5cyhhY3R1YWxPYmopO1xuICAgICAgICB2YXIgZXhwZWN0YXRpb25LZXlzID0ga2V5cyhleHBlY3RhdGlvbk9iaik7XG4gICAgICAgIHZhciBhY3R1YWxOYW1lID0gY2xhc3NOYW1lKGFjdHVhbE9iaik7XG4gICAgICAgIHZhciBleHBlY3RhdGlvbk5hbWUgPSBjbGFzc05hbWUoZXhwZWN0YXRpb25PYmopO1xuICAgICAgICB2YXIgZXhwZWN0YXRpb25TeW1ib2xzID1cbiAgICAgICAgICAgIHR5cGVPZihnZXRPd25Qcm9wZXJ0eVN5bWJvbHMpID09PSBcImZ1bmN0aW9uXCJcbiAgICAgICAgICAgICAgICA/IGdldE93blByb3BlcnR5U3ltYm9scyhleHBlY3RhdGlvbk9iailcbiAgICAgICAgICAgICAgICA6IC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiBjYW5ub3QgY29sbGVjdCBjb3ZlcmFnZSBmb3IgZW5naW5lIHRoYXQgZG9lc24ndCBzdXBwb3J0IFN5bWJvbCAqL1xuICAgICAgICAgICAgICAgICAgW107XG4gICAgICAgIHZhciBleHBlY3RhdGlvbktleXNBbmRTeW1ib2xzID0gY29uY2F0KFxuICAgICAgICAgICAgZXhwZWN0YXRpb25LZXlzLFxuICAgICAgICAgICAgZXhwZWN0YXRpb25TeW1ib2xzLFxuICAgICAgICApO1xuXG4gICAgICAgIGlmIChpc0FyZ3VtZW50cyhhY3R1YWxPYmopIHx8IGlzQXJndW1lbnRzKGV4cGVjdGF0aW9uT2JqKSkge1xuICAgICAgICAgICAgaWYgKGFjdHVhbE9iai5sZW5ndGggIT09IGV4cGVjdGF0aW9uT2JqLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBhY3R1YWxUeXBlICE9PSBleHBlY3RhdGlvblR5cGUgfHxcbiAgICAgICAgICAgICAgICBhY3R1YWxDbGFzcyAhPT0gZXhwZWN0YXRpb25DbGFzcyB8fFxuICAgICAgICAgICAgICAgIGFjdHVhbEtleXMubGVuZ3RoICE9PSBleHBlY3RhdGlvbktleXMubGVuZ3RoIHx8XG4gICAgICAgICAgICAgICAgKGFjdHVhbE5hbWUgJiZcbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0YXRpb25OYW1lICYmXG4gICAgICAgICAgICAgICAgICAgIGFjdHVhbE5hbWUgIT09IGV4cGVjdGF0aW9uTmFtZSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc1NldChhY3R1YWxPYmopIHx8IGlzU2V0KGV4cGVjdGF0aW9uT2JqKSkge1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICFpc1NldChhY3R1YWxPYmopIHx8XG4gICAgICAgICAgICAgICAgIWlzU2V0KGV4cGVjdGF0aW9uT2JqKSB8fFxuICAgICAgICAgICAgICAgIGFjdHVhbE9iai5zaXplICE9PSBleHBlY3RhdGlvbk9iai5zaXplXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBpc1N1YnNldChhY3R1YWxPYmosIGV4cGVjdGF0aW9uT2JqLCBkZWVwRXF1YWwpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzTWFwKGFjdHVhbE9iaikgfHwgaXNNYXAoZXhwZWN0YXRpb25PYmopKSB7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgIWlzTWFwKGFjdHVhbE9iaikgfHxcbiAgICAgICAgICAgICAgICAhaXNNYXAoZXhwZWN0YXRpb25PYmopIHx8XG4gICAgICAgICAgICAgICAgYWN0dWFsT2JqLnNpemUgIT09IGV4cGVjdGF0aW9uT2JqLnNpemVcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIG1hcHNEZWVwbHlFcXVhbCA9IHRydWU7XG4gICAgICAgICAgICBtYXBGb3JFYWNoKGFjdHVhbE9iaiwgZnVuY3Rpb24gKHZhbHVlLCBrZXkpIHtcbiAgICAgICAgICAgICAgICBtYXBzRGVlcGx5RXF1YWwgPVxuICAgICAgICAgICAgICAgICAgICBtYXBzRGVlcGx5RXF1YWwgJiZcbiAgICAgICAgICAgICAgICAgICAgZGVlcEVxdWFsQ3ljbGljKHZhbHVlLCBleHBlY3RhdGlvbk9iai5nZXQoa2V5KSk7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgcmV0dXJuIG1hcHNEZWVwbHlFcXVhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGpRdWVyeSBvYmplY3RzIGhhdmUgaXRlcmF0aW9uIHByb3RvY29sc1xuICAgICAgICAvLyBzZWU6IGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0l0ZXJhdGlvbl9wcm90b2NvbHNcbiAgICAgICAgLy8gQnV0LCB0aGV5IGRvbid0IHdvcmsgd2VsbCB3aXRoIHRoZSBpbXBsZW1lbnRhdGlvbiBjb25jZXJuaW5nIGl0ZXJhYmxlcyBiZWxvdyxcbiAgICAgICAgLy8gc28gd2Ugd2lsbCBkZXRlY3QgdGhlbSBhbmQgdXNlIGpRdWVyeSdzIG93biBlcXVhbGl0eSBmdW5jdGlvblxuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAtLSB0aGlzIGNhbiBvbmx5IGJlIHRlc3RlZCBpbiB0aGUgYHRlc3QtaGVhZGxlc3NgIHNjcmlwdCAqL1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICBhY3R1YWxPYmouY29uc3RydWN0b3IgJiZcbiAgICAgICAgICAgIGFjdHVhbE9iai5jb25zdHJ1Y3Rvci5uYW1lID09PSBcImpRdWVyeVwiICYmXG4gICAgICAgICAgICB0eXBlb2YgYWN0dWFsT2JqLmlzID09PSBcImZ1bmN0aW9uXCJcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm4gYWN0dWFsT2JqLmlzKGV4cGVjdGF0aW9uT2JqKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBpc0FjdHVhbE5vbkFycmF5SXRlcmFibGUgPVxuICAgICAgICAgICAgaXNJdGVyYWJsZShhY3R1YWxPYmopICYmXG4gICAgICAgICAgICAhaXNBcnJheVR5cGUoYWN0dWFsT2JqKSAmJlxuICAgICAgICAgICAgIWlzQXJndW1lbnRzKGFjdHVhbE9iaik7XG4gICAgICAgIHZhciBpc0V4cGVjdGF0aW9uTm9uQXJyYXlJdGVyYWJsZSA9XG4gICAgICAgICAgICBpc0l0ZXJhYmxlKGV4cGVjdGF0aW9uT2JqKSAmJlxuICAgICAgICAgICAgIWlzQXJyYXlUeXBlKGV4cGVjdGF0aW9uT2JqKSAmJlxuICAgICAgICAgICAgIWlzQXJndW1lbnRzKGV4cGVjdGF0aW9uT2JqKTtcbiAgICAgICAgaWYgKGlzQWN0dWFsTm9uQXJyYXlJdGVyYWJsZSB8fCBpc0V4cGVjdGF0aW9uTm9uQXJyYXlJdGVyYWJsZSkge1xuICAgICAgICAgICAgdmFyIGFjdHVhbEFycmF5ID0gQXJyYXkuZnJvbShhY3R1YWxPYmopO1xuICAgICAgICAgICAgdmFyIGV4cGVjdGF0aW9uQXJyYXkgPSBBcnJheS5mcm9tKGV4cGVjdGF0aW9uT2JqKTtcbiAgICAgICAgICAgIGlmIChhY3R1YWxBcnJheS5sZW5ndGggIT09IGV4cGVjdGF0aW9uQXJyYXkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgYXJyYXlEZWVwbHlFcXVhbHMgPSB0cnVlO1xuICAgICAgICAgICAgZXZlcnkoYWN0dWFsQXJyYXksIGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnJheURlZXBseUVxdWFscyA9XG4gICAgICAgICAgICAgICAgICAgIGFycmF5RGVlcGx5RXF1YWxzICYmXG4gICAgICAgICAgICAgICAgICAgIGRlZXBFcXVhbEN5Y2xpYyhhY3R1YWxBcnJheVtrZXldLCBleHBlY3RhdGlvbkFycmF5W2tleV0pO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIHJldHVybiBhcnJheURlZXBseUVxdWFscztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBldmVyeShleHBlY3RhdGlvbktleXNBbmRTeW1ib2xzLCBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3BlcnR5KGFjdHVhbE9iaiwga2V5KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGFjdHVhbFZhbHVlID0gYWN0dWFsT2JqW2tleV07XG4gICAgICAgICAgICB2YXIgZXhwZWN0YXRpb25WYWx1ZSA9IGV4cGVjdGF0aW9uT2JqW2tleV07XG4gICAgICAgICAgICB2YXIgYWN0dWFsT2JqZWN0ID0gaXNPYmplY3QoYWN0dWFsVmFsdWUpO1xuICAgICAgICAgICAgdmFyIGV4cGVjdGF0aW9uT2JqZWN0ID0gaXNPYmplY3QoZXhwZWN0YXRpb25WYWx1ZSk7XG4gICAgICAgICAgICAvLyBkZXRlcm1pbmVzLCBpZiB0aGUgb2JqZWN0cyB3ZXJlIGFscmVhZHkgdmlzaXRlZFxuICAgICAgICAgICAgLy8gKGl0J3MgZmFzdGVyIHRvIGNoZWNrIGZvciBpc09iamVjdCBmaXJzdCwgdGhhbiB0b1xuICAgICAgICAgICAgLy8gZ2V0IC0xIGZyb20gZ2V0SW5kZXggZm9yIG5vbiBvYmplY3RzKVxuICAgICAgICAgICAgdmFyIGFjdHVhbEluZGV4ID0gYWN0dWFsT2JqZWN0XG4gICAgICAgICAgICAgICAgPyBpbmRleE9mKGFjdHVhbE9iamVjdHMsIGFjdHVhbFZhbHVlKVxuICAgICAgICAgICAgICAgIDogLTE7XG4gICAgICAgICAgICB2YXIgZXhwZWN0YXRpb25JbmRleCA9IGV4cGVjdGF0aW9uT2JqZWN0XG4gICAgICAgICAgICAgICAgPyBpbmRleE9mKGV4cGVjdGF0aW9uT2JqZWN0cywgZXhwZWN0YXRpb25WYWx1ZSlcbiAgICAgICAgICAgICAgICA6IC0xO1xuICAgICAgICAgICAgLy8gZGV0ZXJtaW5lcyB0aGUgbmV3IHBhdGhzIG9mIHRoZSBvYmplY3RzXG4gICAgICAgICAgICAvLyAtIGZvciBub24gY3ljbGljIG9iamVjdHMgdGhlIGN1cnJlbnQgcGF0aCB3aWxsIGJlIGV4dGVuZGVkXG4gICAgICAgICAgICAvLyAgIGJ5IGN1cnJlbnQgcHJvcGVydHkgbmFtZVxuICAgICAgICAgICAgLy8gLSBmb3IgY3ljbGljIG9iamVjdHMgdGhlIHN0b3JlZCBwYXRoIGlzIHRha2VuXG4gICAgICAgICAgICB2YXIgbmV3QWN0dWFsUGF0aCA9XG4gICAgICAgICAgICAgICAgYWN0dWFsSW5kZXggIT09IC0xXG4gICAgICAgICAgICAgICAgICAgID8gYWN0dWFsUGF0aHNbYWN0dWFsSW5kZXhdXG4gICAgICAgICAgICAgICAgICAgIDogYCR7YWN0dWFsUGF0aH1bJHtKU09OLnN0cmluZ2lmeShrZXkpfV1gO1xuICAgICAgICAgICAgdmFyIG5ld0V4cGVjdGF0aW9uUGF0aCA9XG4gICAgICAgICAgICAgICAgZXhwZWN0YXRpb25JbmRleCAhPT0gLTFcbiAgICAgICAgICAgICAgICAgICAgPyBleHBlY3RhdGlvblBhdGhzW2V4cGVjdGF0aW9uSW5kZXhdXG4gICAgICAgICAgICAgICAgICAgIDogYCR7ZXhwZWN0YXRpb25QYXRofVske0pTT04uc3RyaW5naWZ5KGtleSl9XWA7XG4gICAgICAgICAgICB2YXIgY29tYmluZWRQYXRoID0gbmV3QWN0dWFsUGF0aCArIG5ld0V4cGVjdGF0aW9uUGF0aDtcblxuICAgICAgICAgICAgLy8gc3RvcCByZWN1cnNpb24gaWYgY3VycmVudCBvYmplY3RzIGFyZSBhbHJlYWR5IGNvbXBhcmVkXG4gICAgICAgICAgICBpZiAoY29tcGFyZWRbY29tYmluZWRQYXRoXSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyByZW1lbWJlciB0aGUgY3VycmVudCBvYmplY3RzIGFuZCB0aGVpciBwYXRoc1xuICAgICAgICAgICAgaWYgKGFjdHVhbEluZGV4ID09PSAtMSAmJiBhY3R1YWxPYmplY3QpIHtcbiAgICAgICAgICAgICAgICBwdXNoKGFjdHVhbE9iamVjdHMsIGFjdHVhbFZhbHVlKTtcbiAgICAgICAgICAgICAgICBwdXNoKGFjdHVhbFBhdGhzLCBuZXdBY3R1YWxQYXRoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChleHBlY3RhdGlvbkluZGV4ID09PSAtMSAmJiBleHBlY3RhdGlvbk9iamVjdCkge1xuICAgICAgICAgICAgICAgIHB1c2goZXhwZWN0YXRpb25PYmplY3RzLCBleHBlY3RhdGlvblZhbHVlKTtcbiAgICAgICAgICAgICAgICBwdXNoKGV4cGVjdGF0aW9uUGF0aHMsIG5ld0V4cGVjdGF0aW9uUGF0aCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHJlbWVtYmVyIHRoYXQgdGhlIGN1cnJlbnQgb2JqZWN0cyBhcmUgYWxyZWFkeSBjb21wYXJlZFxuICAgICAgICAgICAgaWYgKGFjdHVhbE9iamVjdCAmJiBleHBlY3RhdGlvbk9iamVjdCkge1xuICAgICAgICAgICAgICAgIGNvbXBhcmVkW2NvbWJpbmVkUGF0aF0gPSB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFbmQgb2YgY3ljbGljIGxvZ2ljXG5cbiAgICAgICAgICAgIC8vIG5laXRoZXIgYWN0dWFsVmFsdWUgbm9yIGV4cGVjdGF0aW9uVmFsdWUgaXMgYSBjeWNsZVxuICAgICAgICAgICAgLy8gY29udGludWUgd2l0aCBuZXh0IGxldmVsXG4gICAgICAgICAgICByZXR1cm4gZGVlcEVxdWFsKFxuICAgICAgICAgICAgICAgIGFjdHVhbFZhbHVlLFxuICAgICAgICAgICAgICAgIGV4cGVjdGF0aW9uVmFsdWUsXG4gICAgICAgICAgICAgICAgbmV3QWN0dWFsUGF0aCxcbiAgICAgICAgICAgICAgICBuZXdFeHBlY3RhdGlvblBhdGgsXG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICB9KShhY3R1YWwsIGV4cGVjdGF0aW9uLCBcIiQxXCIsIFwiJDJcIik7XG59XG5cbmRlZXBFcXVhbEN5Y2xpYy51c2UgPSBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gZGVlcEVxdWFsKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGRlZXBFcXVhbEN5Y2xpYyhhLCBiLCBtYXRjaCk7XG4gICAgfTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZGVlcEVxdWFsQ3ljbGljO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciB0b1N0cmluZyA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnByb3RvdHlwZXMub2JqZWN0LnRvU3RyaW5nO1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGludGVybmFsIGBDbGFzc2AgYnkgY2FsbGluZyBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ2BcbiAqIHdpdGggdGhlIHByb3ZpZGVkIHZhbHVlIGFzIGB0aGlzYC4gUmV0dXJuIHZhbHVlIGlzIGEgYFN0cmluZ2AsIG5hbWluZyB0aGVcbiAqIGludGVybmFsIGNsYXNzLCBlLmcuIFwiQXJyYXlcIlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0gIHsqfSB2YWx1ZSAtIEFueSB2YWx1ZVxuICogQHJldHVybnMge3N0cmluZ30gLSBBIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgYENsYXNzYCBvZiBgdmFsdWVgXG4gKi9cbmZ1bmN0aW9uIGdldENsYXNzKHZhbHVlKSB7XG4gICAgcmV0dXJuIHRvU3RyaW5nKHZhbHVlKS5zcGxpdCgvWyBcXF1dLylbMV07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0Q2xhc3M7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGlzTmFOID0gcmVxdWlyZShcIi4vaXMtbmFuXCIpO1xudmFyIGlzTmVnWmVybyA9IHJlcXVpcmUoXCIuL2lzLW5lZy16ZXJvXCIpO1xuXG4vKipcbiAqIFN0cmljdCBlcXVhbGl0eSBjaGVjayBhY2NvcmRpbmcgdG8gRWNtYVNjcmlwdCBIYXJtb255J3MgYGVnYWxgLlxuICpcbiAqICoqRnJvbSB0aGUgSGFybW9ueSB3aWtpOioqXG4gKiA+IEFuIGBlZ2FsYCBmdW5jdGlvbiBzaW1wbHkgbWFrZXMgYXZhaWxhYmxlIHRoZSBpbnRlcm5hbCBgU2FtZVZhbHVlYCBmdW5jdGlvblxuICogPiBmcm9tIHNlY3Rpb24gOS4xMiBvZiB0aGUgRVM1IHNwZWMuIElmIHR3byB2YWx1ZXMgYXJlIGVnYWwsIHRoZW4gdGhleSBhcmUgbm90XG4gKiA+IG9ic2VydmFibHkgZGlzdGluZ3Vpc2hhYmxlLlxuICpcbiAqIGBpZGVudGljYWxgIHJldHVybnMgYHRydWVgIHdoZW4gYD09PWAgaXMgYHRydWVgLCBleGNlcHQgZm9yIGAtMGAgYW5kXG4gKiBgKzBgLCB3aGVyZSBpdCByZXR1cm5zIGBmYWxzZWAuIEFkZGl0aW9uYWxseSwgaXQgcmV0dXJucyBgdHJ1ZWAgd2hlblxuICogYE5hTmAgaXMgY29tcGFyZWQgdG8gaXRzZWxmLlxuICpcbiAqIEBhbGlhcyBtb2R1bGU6c2Ftc2FtLmlkZW50aWNhbFxuICogQHBhcmFtIHsqfSBvYmoxIFRoZSBmaXJzdCB2YWx1ZSB0byBjb21wYXJlXG4gKiBAcGFyYW0geyp9IG9iajIgVGhlIHNlY29uZCB2YWx1ZSB0byBjb21wYXJlXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgd2hlbiB0aGUgb2JqZWN0cyBhcmUgKmVnYWwqLCBgZmFsc2VgIG90aGVyd2lzZVxuICovXG5mdW5jdGlvbiBpZGVudGljYWwob2JqMSwgb2JqMikge1xuICAgIGlmIChvYmoxID09PSBvYmoyIHx8IChpc05hTihvYmoxKSAmJiBpc05hTihvYmoyKSkpIHtcbiAgICAgICAgcmV0dXJuIG9iajEgIT09IDAgfHwgaXNOZWdaZXJvKG9iajEpID09PSBpc05lZ1plcm8ob2JqMik7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlkZW50aWNhbDtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgZ2V0Q2xhc3MgPSByZXF1aXJlKFwiLi9nZXQtY2xhc3NcIik7XG5cbi8qKlxuICogUmV0dXJucyBgdHJ1ZWAgd2hlbiBgb2JqZWN0YCBpcyBhbiBgYXJndW1lbnRzYCBvYmplY3QsIGBmYWxzZWAgb3RoZXJ3aXNlXG4gKlxuICogQGFsaWFzIG1vZHVsZTpzYW1zYW0uaXNBcmd1bWVudHNcbiAqIEBwYXJhbSAgeyp9ICBvYmplY3QgLSBUaGUgb2JqZWN0IHRvIGV4YW1pbmVcbiAqIEByZXR1cm5zIHtib29sZWFufSBgdHJ1ZWAgd2hlbiBgb2JqZWN0YCBpcyBhbiBgYXJndW1lbnRzYCBvYmplY3RcbiAqL1xuZnVuY3Rpb24gaXNBcmd1bWVudHMob2JqZWN0KSB7XG4gICAgcmV0dXJuIGdldENsYXNzKG9iamVjdCkgPT09IFwiQXJndW1lbnRzXCI7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNBcmd1bWVudHM7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGZ1bmN0aW9uTmFtZSA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLmZ1bmN0aW9uTmFtZTtcbnZhciBpbmRleE9mID0gcmVxdWlyZShcIkBzaW5vbmpzL2NvbW1vbnNcIikucHJvdG90eXBlcy5hcnJheS5pbmRleE9mO1xudmFyIG1hcCA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnByb3RvdHlwZXMuYXJyYXkubWFwO1xudmFyIEFSUkFZX1RZUEVTID0gcmVxdWlyZShcIi4vYXJyYXktdHlwZXNcIik7XG52YXIgdHlwZSA9IHJlcXVpcmUoXCJ0eXBlLWRldGVjdFwiKTtcblxuLyoqXG4gKiBSZXR1cm5zIGB0cnVlYCB3aGVuIGBvYmplY3RgIGlzIGFuIGFycmF5IHR5cGUsIGBmYWxzZWAgb3RoZXJ3aXNlXG4gKlxuICogQHBhcmFtICB7Kn0gIG9iamVjdCAtIFRoZSBvYmplY3QgdG8gZXhhbWluZVxuICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCB3aGVuIGBvYmplY3RgIGlzIGFuIGFycmF5IHR5cGVcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGlzQXJyYXlUeXBlKG9iamVjdCkge1xuICAgIHJldHVybiBpbmRleE9mKG1hcChBUlJBWV9UWVBFUywgZnVuY3Rpb25OYW1lKSwgdHlwZShvYmplY3QpKSAhPT0gLTE7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNBcnJheVR5cGU7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuLyoqXG4gKiBSZXR1cm5zIGB0cnVlYCB3aGVuIGB2YWx1ZWAgaXMgYW4gaW5zdGFuY2Ugb2YgRGF0ZVxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0gIHtEYXRlfSAgdmFsdWUgVGhlIHZhbHVlIHRvIGV4YW1pbmVcbiAqIEByZXR1cm5zIHtib29sZWFufSAgICAgYHRydWVgIHdoZW4gYHZhbHVlYCBpcyBhbiBpbnN0YW5jZSBvZiBEYXRlXG4gKi9cbmZ1bmN0aW9uIGlzRGF0ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIERhdGU7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNEYXRlO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBkaXYgPSB0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIgJiYgZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcblxuLyoqXG4gKiBSZXR1cm5zIGB0cnVlYCB3aGVuIGBvYmplY3RgIGlzIGEgRE9NIGVsZW1lbnQgbm9kZS5cbiAqXG4gKiBVbmxpa2UgVW5kZXJzY29yZS5qcy9sb2Rhc2gsIHRoaXMgZnVuY3Rpb24gd2lsbCByZXR1cm4gYGZhbHNlYCBpZiBgb2JqZWN0YFxuICogaXMgYW4gKmVsZW1lbnQtbGlrZSogb2JqZWN0LCBpLmUuIGEgcmVndWxhciBvYmplY3Qgd2l0aCBhIGBub2RlVHlwZWBcbiAqIHByb3BlcnR5IHRoYXQgaG9sZHMgdGhlIHZhbHVlIGAxYC5cbiAqXG4gKiBAYWxpYXMgbW9kdWxlOnNhbXNhbS5pc0VsZW1lbnRcbiAqIEBwYXJhbSB7b2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBleGFtaW5lXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgZm9yIERPTSBlbGVtZW50IG5vZGVzXG4gKi9cbmZ1bmN0aW9uIGlzRWxlbWVudChvYmplY3QpIHtcbiAgICBpZiAoIW9iamVjdCB8fCBvYmplY3Qubm9kZVR5cGUgIT09IDEgfHwgIWRpdikge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIG9iamVjdC5hcHBlbmRDaGlsZChkaXYpO1xuICAgICAgICBvYmplY3QucmVtb3ZlQ2hpbGQoZGl2KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNFbGVtZW50O1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbi8qKlxuICogUmV0dXJucyBgdHJ1ZWAgd2hlbiB0aGUgYXJndW1lbnQgaXMgYW4gaXRlcmFibGUsIGBmYWxzZWAgb3RoZXJ3aXNlXG4gKlxuICogQGFsaWFzIG1vZHVsZTpzYW1zYW0uaXNJdGVyYWJsZVxuICogQHBhcmFtICB7Kn0gIHZhbCAtIEEgdmFsdWUgdG8gZXhhbWluZVxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIHdoZW4gdGhlIGFyZ3VtZW50IGlzIGFuIGl0ZXJhYmxlLCBgZmFsc2VgIG90aGVyd2lzZVxuICovXG5mdW5jdGlvbiBpc0l0ZXJhYmxlKHZhbCkge1xuICAgIC8vIGNoZWNrcyBmb3IgbnVsbCBhbmQgdW5kZWZpbmVkXG4gICAgaWYgKHR5cGVvZiB2YWwgIT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdHlwZW9mIHZhbFtTeW1ib2wuaXRlcmF0b3JdID09PSBcImZ1bmN0aW9uXCI7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNJdGVyYWJsZTtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG4vKipcbiAqIFJldHVybnMgYHRydWVgIHdoZW4gYHZhbHVlYCBpcyBhIE1hcFxuICpcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgQSB2YWx1ZSB0byBleGFtaW5lXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gYHRydWVgIHdoZW4gYHZhbHVlYCBpcyBhbiBpbnN0YW5jZSBvZiBgTWFwYCwgYGZhbHNlYCBvdGhlcndpc2VcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGlzTWFwKHZhbHVlKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBNYXAgIT09IFwidW5kZWZpbmVkXCIgJiYgdmFsdWUgaW5zdGFuY2VvZiBNYXA7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNNYXA7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuLyoqXG4gKiBDb21wYXJlcyBhIGB2YWx1ZWAgdG8gYE5hTmBcbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBBIHZhbHVlIHRvIGV4YW1pbmVcbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCB3aGVuIGB2YWx1ZWAgaXMgYE5hTmBcbiAqL1xuZnVuY3Rpb24gaXNOYU4odmFsdWUpIHtcbiAgICAvLyBVbmxpa2UgZ2xvYmFsIGBpc05hTmAsIHRoaXMgZnVuY3Rpb24gYXZvaWRzIHR5cGUgY29lcmNpb25cbiAgICAvLyBgdHlwZW9mYCBjaGVjayBhdm9pZHMgSUUgaG9zdCBvYmplY3QgaXNzdWVzLCBoYXQgdGlwIHRvXG4gICAgLy8gbG9kYXNoXG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2VsZi1jb21wYXJlXG4gICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIiAmJiB2YWx1ZSAhPT0gdmFsdWU7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNOYU47XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuLyoqXG4gKiBSZXR1cm5zIGB0cnVlYCB3aGVuIGB2YWx1ZWAgaXMgYC0wYFxuICpcbiAqIEBhbGlhcyBtb2R1bGU6c2Ftc2FtLmlzTmVnWmVyb1xuICogQHBhcmFtIHsqfSB2YWx1ZSBBIHZhbHVlIHRvIGV4YW1pbmVcbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCB3aGVuIGB2YWx1ZWAgaXMgYC0wYFxuICovXG5mdW5jdGlvbiBpc05lZ1plcm8odmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlID09PSAtSW5maW5pdHk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNOZWdaZXJvO1xuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbi8qKlxuICogUmV0dXJucyBgdHJ1ZWAgd2hlbiB0aGUgdmFsdWUgaXMgYSByZWd1bGFyIE9iamVjdCBhbmQgbm90IGEgc3BlY2lhbGl6ZWQgT2JqZWN0XG4gKlxuICogVGhpcyBoZWxwcyBzcGVlZCB1cCBkZWVwRXF1YWwgY3ljbGljIGNoZWNrc1xuICpcbiAqIFRoZSBwcmVtaXNlIGlzIHRoYXQgb25seSBPYmplY3RzIGFyZSBzdG9yZWQgaW4gdGhlIHZpc2l0ZWQgYXJyYXkuXG4gKiBTbyBpZiB0aGlzIGZ1bmN0aW9uIHJldHVybnMgZmFsc2UsIHdlIGRvbid0IGhhdmUgdG8gZG8gdGhlXG4gKiBleHBlbnNpdmUgb3BlcmF0aW9uIG9mIHNlYXJjaGluZyBmb3IgdGhlIHZhbHVlIGluIHRoZSB0aGUgYXJyYXkgb2YgYWxyZWFkeVxuICogdmlzaXRlZCBvYmplY3RzXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSAge29iamVjdH0gICB2YWx1ZSBUaGUgb2JqZWN0IHRvIGV4YW1pbmVcbiAqIEByZXR1cm5zIHtib29sZWFufSAgICAgICBgdHJ1ZWAgd2hlbiB0aGUgb2JqZWN0IGlzIGEgbm9uLXNwZWNpYWxpc2VkIG9iamVjdFxuICovXG5mdW5jdGlvbiBpc09iamVjdCh2YWx1ZSkge1xuICAgIHJldHVybiAoXG4gICAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gXCJvYmplY3RcIiAmJlxuICAgICAgICB2YWx1ZSAhPT0gbnVsbCAmJlxuICAgICAgICAvLyBub25lIG9mIHRoZXNlIGFyZSBjb2xsZWN0aW9uIG9iamVjdHMsIHNvIHdlIGNhbiByZXR1cm4gZmFsc2VcbiAgICAgICAgISh2YWx1ZSBpbnN0YW5jZW9mIEJvb2xlYW4pICYmXG4gICAgICAgICEodmFsdWUgaW5zdGFuY2VvZiBEYXRlKSAmJlxuICAgICAgICAhKHZhbHVlIGluc3RhbmNlb2YgRXJyb3IpICYmXG4gICAgICAgICEodmFsdWUgaW5zdGFuY2VvZiBOdW1iZXIpICYmXG4gICAgICAgICEodmFsdWUgaW5zdGFuY2VvZiBSZWdFeHApICYmXG4gICAgICAgICEodmFsdWUgaW5zdGFuY2VvZiBTdHJpbmcpXG4gICAgKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc09iamVjdDtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG4vKipcbiAqIFJldHVybnMgYHRydWVgIHdoZW4gdGhlIGFyZ3VtZW50IGlzIGFuIGluc3RhbmNlIG9mIFNldCwgYGZhbHNlYCBvdGhlcndpc2VcbiAqXG4gKiBAYWxpYXMgbW9kdWxlOnNhbXNhbS5pc1NldFxuICogQHBhcmFtICB7Kn0gIHZhbCAtIEEgdmFsdWUgdG8gZXhhbWluZVxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIHdoZW4gdGhlIGFyZ3VtZW50IGlzIGFuIGluc3RhbmNlIG9mIFNldCwgYGZhbHNlYCBvdGhlcndpc2VcbiAqL1xuZnVuY3Rpb24gaXNTZXQodmFsKSB7XG4gICAgcmV0dXJuICh0eXBlb2YgU2V0ICE9PSBcInVuZGVmaW5lZFwiICYmIHZhbCBpbnN0YW5jZW9mIFNldCkgfHwgZmFsc2U7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNTZXQ7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGZvckVhY2ggPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLnNldC5mb3JFYWNoO1xuXG4vKipcbiAqIFJldHVybnMgYHRydWVgIHdoZW4gYHMxYCBpcyBhIHN1YnNldCBvZiBgczJgLCBgZmFsc2VgIG90aGVyd2lzZVxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0gIHtBcnJheXxTZXR9ICBzMSAgICAgIFRoZSB0YXJnZXQgdmFsdWVcbiAqIEBwYXJhbSAge0FycmF5fFNldH0gIHMyICAgICAgVGhlIGNvbnRhaW5pbmcgdmFsdWVcbiAqIEBwYXJhbSAge0Z1bmN0aW9ufSAgY29tcGFyZSBBIGNvbXBhcmlzb24gZnVuY3Rpb24sIHNob3VsZCByZXR1cm4gYHRydWVgIHdoZW5cbiAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgYXJlIGNvbnNpZGVyZWQgZXF1YWxcbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCB3aGVuIGBzMWAgaXMgYSBzdWJzZXQgb2YgYHMyYCwgYGZhbHNlYGAgb3RoZXJ3aXNlXG4gKi9cbmZ1bmN0aW9uIGlzU3Vic2V0KHMxLCBzMiwgY29tcGFyZSkge1xuICAgIHZhciBhbGxDb250YWluZWQgPSB0cnVlO1xuICAgIGZvckVhY2goczEsIGZ1bmN0aW9uICh2MSkge1xuICAgICAgICB2YXIgaW5jbHVkZXMgPSBmYWxzZTtcbiAgICAgICAgZm9yRWFjaChzMiwgZnVuY3Rpb24gKHYyKSB7XG4gICAgICAgICAgICBpZiAoY29tcGFyZSh2MiwgdjEpKSB7XG4gICAgICAgICAgICAgICAgaW5jbHVkZXMgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgYWxsQ29udGFpbmVkID0gYWxsQ29udGFpbmVkICYmIGluY2x1ZGVzO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIGFsbENvbnRhaW5lZDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc1N1YnNldDtcbiIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgc2xpY2UgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLnN0cmluZy5zbGljZTtcbnZhciB0eXBlT2YgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS50eXBlT2Y7XG52YXIgdmFsdWVUb1N0cmluZyA9IHJlcXVpcmUoXCJAc2lub25qcy9jb21tb25zXCIpLnZhbHVlVG9TdHJpbmc7XG5cbi8qKlxuICogQ3JlYXRlcyBhIHN0cmluZyByZXByZXNlbmF0aW9uIG9mIGFuIGl0ZXJhYmxlIG9iamVjdFxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0gICB7b2JqZWN0fSBvYmogVGhlIGl0ZXJhYmxlIG9iamVjdCB0byBzdHJpbmdpZnlcbiAqIEByZXR1cm5zIHtzdHJpbmd9ICAgICBBIHN0cmluZyByZXByZXNlbnRhdGlvblxuICovXG5mdW5jdGlvbiBpdGVyYWJsZVRvU3RyaW5nKG9iaikge1xuICAgIGlmICh0eXBlT2Yob2JqKSA9PT0gXCJtYXBcIikge1xuICAgICAgICByZXR1cm4gbWFwVG9TdHJpbmcob2JqKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZ2VuZXJpY0l0ZXJhYmxlVG9TdHJpbmcob2JqKTtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgTWFwXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSAgIHtNYXB9IG1hcCAgICBUaGUgbWFwIHRvIHN0cmluZ2lmeVxuICogQHJldHVybnMge3N0cmluZ30gICAgIEEgc3RyaW5nIHJlcHJlc2VudGF0aW9uXG4gKi9cbmZ1bmN0aW9uIG1hcFRvU3RyaW5nKG1hcCkge1xuICAgIHZhciByZXByZXNlbnRhdGlvbiA9IFwiXCI7XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHNpbm9uanMvbm8tcHJvdG90eXBlLW1ldGhvZHMvbm8tcHJvdG90eXBlLW1ldGhvZHNcbiAgICBtYXAuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSkge1xuICAgICAgICByZXByZXNlbnRhdGlvbiArPSBgWyR7c3RyaW5naWZ5KGtleSl9LCR7c3RyaW5naWZ5KHZhbHVlKX1dLGA7XG4gICAgfSk7XG5cbiAgICByZXByZXNlbnRhdGlvbiA9IHNsaWNlKHJlcHJlc2VudGF0aW9uLCAwLCAtMSk7XG4gICAgcmV0dXJuIHJlcHJlc2VudGF0aW9uO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIHN0cmluZyByZXByZXNlbmF0aW9uIGZvciBhbiBpdGVyYWJsZVxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0gICB7b2JqZWN0fSBpdGVyYWJsZSBUaGUgaXRlcmFibGUgdG8gc3RyaW5naWZ5XG4gKiBAcmV0dXJucyB7c3RyaW5nfSAgICAgICAgICBBIHN0cmluZyByZXByZXNlbnRhdGlvblxuICovXG5mdW5jdGlvbiBnZW5lcmljSXRlcmFibGVUb1N0cmluZyhpdGVyYWJsZSkge1xuICAgIHZhciByZXByZXNlbnRhdGlvbiA9IFwiXCI7XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHNpbm9uanMvbm8tcHJvdG90eXBlLW1ldGhvZHMvbm8tcHJvdG90eXBlLW1ldGhvZHNcbiAgICBpdGVyYWJsZS5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICByZXByZXNlbnRhdGlvbiArPSBgJHtzdHJpbmdpZnkodmFsdWUpfSxgO1xuICAgIH0pO1xuXG4gICAgcmVwcmVzZW50YXRpb24gPSBzbGljZShyZXByZXNlbnRhdGlvbiwgMCwgLTEpO1xuICAgIHJldHVybiByZXByZXNlbnRhdGlvbjtcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBwYXNzZWQgYGl0ZW1gXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSAge29iamVjdH0gaXRlbSBUaGUgaXRlbSB0byBzdHJpbmdpZnlcbiAqIEByZXR1cm5zIHtzdHJpbmd9ICAgICAgQSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgYGl0ZW1gXG4gKi9cbmZ1bmN0aW9uIHN0cmluZ2lmeShpdGVtKSB7XG4gICAgcmV0dXJuIHR5cGVvZiBpdGVtID09PSBcInN0cmluZ1wiID8gYCcke2l0ZW19J2AgOiB2YWx1ZVRvU3RyaW5nKGl0ZW0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGl0ZXJhYmxlVG9TdHJpbmc7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIHZhbHVlVG9TdHJpbmcgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS52YWx1ZVRvU3RyaW5nO1xudmFyIGluZGV4T2YgPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLnN0cmluZy5pbmRleE9mO1xudmFyIGZvckVhY2ggPSByZXF1aXJlKFwiQHNpbm9uanMvY29tbW9uc1wiKS5wcm90b3R5cGVzLmFycmF5LmZvckVhY2g7XG52YXIgdHlwZSA9IHJlcXVpcmUoXCJ0eXBlLWRldGVjdFwiKTtcblxudmFyIGVuZ2luZUNhbkNvbXBhcmVNYXBzID0gdHlwZW9mIEFycmF5LmZyb20gPT09IFwiZnVuY3Rpb25cIjtcbnZhciBkZWVwRXF1YWwgPSByZXF1aXJlKFwiLi9kZWVwLWVxdWFsXCIpLnVzZShtYXRjaCk7IC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdXNlLWJlZm9yZS1kZWZpbmVcbnZhciBpc0FycmF5VHlwZSA9IHJlcXVpcmUoXCIuL2lzLWFycmF5LXR5cGVcIik7XG52YXIgaXNTdWJzZXQgPSByZXF1aXJlKFwiLi9pcy1zdWJzZXRcIik7XG52YXIgY3JlYXRlTWF0Y2hlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1tYXRjaGVyXCIpO1xuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSB3aGVuIGBhcnJheWAgY29udGFpbnMgYWxsIG9mIGBzdWJzZXRgIGFzIGRlZmluZWQgYnkgdGhlIGBjb21wYXJlYFxuICogYXJndW1lbnRcbiAqXG4gKiBAcGFyYW0gIHtBcnJheX0gYXJyYXkgICBBbiBhcnJheSB0byBzZWFyY2ggZm9yIGEgc3Vic2V0XG4gKiBAcGFyYW0gIHtBcnJheX0gc3Vic2V0ICBUaGUgc3Vic2V0IHRvIGZpbmQgaW4gdGhlIGFycmF5XG4gKiBAcGFyYW0gIHtGdW5jdGlvbn0gY29tcGFyZSBBIGNvbXBhcmlzb24gZnVuY3Rpb25cbiAqIEByZXR1cm5zIHtib29sZWFufSAgICAgICAgIFtkZXNjcmlwdGlvbl1cbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGFycmF5Q29udGFpbnMoYXJyYXksIHN1YnNldCwgY29tcGFyZSkge1xuICAgIGlmIChzdWJzZXQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICB2YXIgaSwgbCwgaiwgaztcbiAgICBmb3IgKGkgPSAwLCBsID0gYXJyYXkubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgIGlmIChjb21wYXJlKGFycmF5W2ldLCBzdWJzZXRbMF0pKSB7XG4gICAgICAgICAgICBmb3IgKGogPSAwLCBrID0gc3Vic2V0Lmxlbmd0aDsgaiA8IGs7ICsraikge1xuICAgICAgICAgICAgICAgIGlmIChpICsgaiA+PSBsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCFjb21wYXJlKGFycmF5W2kgKyBqXSwgc3Vic2V0W2pdKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG4vKiBlc2xpbnQtZGlzYWJsZSBjb21wbGV4aXR5ICovXG4vKipcbiAqIE1hdGNoZXMgYW4gb2JqZWN0IHdpdGggYSBtYXRjaGVyIChvciB2YWx1ZSlcbiAqXG4gKiBAYWxpYXMgbW9kdWxlOnNhbXNhbS5tYXRjaFxuICogQHBhcmFtIHtvYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IGNhbmRpZGF0ZSB0byBtYXRjaFxuICogQHBhcmFtIHtvYmplY3R9IG1hdGNoZXJPclZhbHVlIEEgbWF0Y2hlciBvciB2YWx1ZSB0byBtYXRjaCBhZ2FpbnN0XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSB3aGVuIGBvYmplY3RgIG1hdGNoZXMgYG1hdGNoZXJPclZhbHVlYFxuICovXG5mdW5jdGlvbiBtYXRjaChvYmplY3QsIG1hdGNoZXJPclZhbHVlKSB7XG4gICAgaWYgKG1hdGNoZXJPclZhbHVlICYmIHR5cGVvZiBtYXRjaGVyT3JWYWx1ZS50ZXN0ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgcmV0dXJuIG1hdGNoZXJPclZhbHVlLnRlc3Qob2JqZWN0KTtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKHR5cGUobWF0Y2hlck9yVmFsdWUpKSB7XG4gICAgICAgIGNhc2UgXCJiaWdpbnRcIjpcbiAgICAgICAgY2FzZSBcImJvb2xlYW5cIjpcbiAgICAgICAgY2FzZSBcIm51bWJlclwiOlxuICAgICAgICBjYXNlIFwic3ltYm9sXCI6XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hlck9yVmFsdWUgPT09IG9iamVjdDtcbiAgICAgICAgY2FzZSBcImZ1bmN0aW9uXCI6XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hlck9yVmFsdWUob2JqZWN0KSA9PT0gdHJ1ZTtcbiAgICAgICAgY2FzZSBcInN0cmluZ1wiOlxuICAgICAgICAgICAgdmFyIG5vdE51bGwgPSB0eXBlb2Ygb2JqZWN0ID09PSBcInN0cmluZ1wiIHx8IEJvb2xlYW4ob2JqZWN0KTtcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgbm90TnVsbCAmJlxuICAgICAgICAgICAgICAgIGluZGV4T2YoXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlVG9TdHJpbmcob2JqZWN0KS50b0xvd2VyQ2FzZSgpLFxuICAgICAgICAgICAgICAgICAgICBtYXRjaGVyT3JWYWx1ZS50b0xvd2VyQ2FzZSgpLFxuICAgICAgICAgICAgICAgICkgPj0gMFxuICAgICAgICAgICAgKTtcbiAgICAgICAgY2FzZSBcIm51bGxcIjpcbiAgICAgICAgICAgIHJldHVybiBvYmplY3QgPT09IG51bGw7XG4gICAgICAgIGNhc2UgXCJ1bmRlZmluZWRcIjpcbiAgICAgICAgICAgIHJldHVybiB0eXBlb2Ygb2JqZWN0ID09PSBcInVuZGVmaW5lZFwiO1xuICAgICAgICBjYXNlIFwiRGF0ZVwiOlxuICAgICAgICAgICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICAgICAgICAgIGlmICh0eXBlKG9iamVjdCkgPT09IFwiRGF0ZVwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdC5nZXRUaW1lKCkgPT09IG1hdGNoZXJPclZhbHVlLmdldFRpbWUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiB0aGlzIGlzIGJhc2ljYWxseSB0aGUgcmVzdCBvZiB0aGUgZnVuY3Rpb24sIHdoaWNoIGlzIGNvdmVyZWQgKi9cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiQXJyYXlcIjpcbiAgICAgICAgY2FzZSBcIkludDhBcnJheVwiOlxuICAgICAgICBjYXNlIFwiVWludDhBcnJheVwiOlxuICAgICAgICBjYXNlIFwiVWludDhDbGFtcGVkQXJyYXlcIjpcbiAgICAgICAgY2FzZSBcIkludDE2QXJyYXlcIjpcbiAgICAgICAgY2FzZSBcIlVpbnQxNkFycmF5XCI6XG4gICAgICAgIGNhc2UgXCJJbnQzMkFycmF5XCI6XG4gICAgICAgIGNhc2UgXCJVaW50MzJBcnJheVwiOlxuICAgICAgICBjYXNlIFwiRmxvYXQzMkFycmF5XCI6XG4gICAgICAgIGNhc2UgXCJGbG9hdDY0QXJyYXlcIjpcbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgaXNBcnJheVR5cGUobWF0Y2hlck9yVmFsdWUpICYmXG4gICAgICAgICAgICAgICAgYXJyYXlDb250YWlucyhvYmplY3QsIG1hdGNoZXJPclZhbHVlLCBtYXRjaClcbiAgICAgICAgICAgICk7XG4gICAgICAgIGNhc2UgXCJNYXBcIjpcbiAgICAgICAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0OiB0aGlzIGlzIGNvdmVyZWQgYnkgYSB0ZXN0LCB0aGF0IGlzIG9ubHkgcnVuIGluIElFLCBidXQgd2UgY29sbGVjdCBjb3ZlcmFnZSBpbmZvcm1hdGlvbiBpbiBub2RlKi9cbiAgICAgICAgICAgIGlmICghZW5naW5lQ2FuQ29tcGFyZU1hcHMpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIFwiVGhlIEphdmFTY3JpcHQgZW5naW5lIGRvZXMgbm90IHN1cHBvcnQgQXJyYXkuZnJvbSBhbmQgY2Fubm90IHJlbGlhYmx5IGRvIHZhbHVlIGNvbXBhcmlzb24gb2YgTWFwIGluc3RhbmNlc1wiLFxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAgICAgdHlwZShvYmplY3QpID09PSBcIk1hcFwiICYmXG4gICAgICAgICAgICAgICAgYXJyYXlDb250YWlucyhcbiAgICAgICAgICAgICAgICAgICAgQXJyYXkuZnJvbShvYmplY3QpLFxuICAgICAgICAgICAgICAgICAgICBBcnJheS5mcm9tKG1hdGNoZXJPclZhbHVlKSxcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2gsXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIHN3aXRjaCAodHlwZShvYmplY3QpKSB7XG4gICAgICAgIGNhc2UgXCJudWxsXCI6XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIGNhc2UgXCJTZXRcIjpcbiAgICAgICAgICAgIHJldHVybiBpc1N1YnNldChtYXRjaGVyT3JWYWx1ZSwgb2JqZWN0LCBtYXRjaCk7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgIGlmIChtYXRjaGVyT3JWYWx1ZSAmJiB0eXBlb2YgbWF0Y2hlck9yVmFsdWUgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgaWYgKG1hdGNoZXJPclZhbHVlID09PSBvYmplY3QpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0ICE9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHByb3A7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBndWFyZC1mb3ItaW5cbiAgICAgICAgZm9yIChwcm9wIGluIG1hdGNoZXJPclZhbHVlKSB7XG4gICAgICAgICAgICB2YXIgdmFsdWUgPSBvYmplY3RbcHJvcF07XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgdHlwZW9mIHZhbHVlID09PSBcInVuZGVmaW5lZFwiICYmXG4gICAgICAgICAgICAgICAgdHlwZW9mIG9iamVjdC5nZXRBdHRyaWJ1dGUgPT09IFwiZnVuY3Rpb25cIlxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSBvYmplY3QuZ2V0QXR0cmlidXRlKHByb3ApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIG1hdGNoZXJPclZhbHVlW3Byb3BdID09PSBudWxsIHx8XG4gICAgICAgICAgICAgICAgdHlwZW9mIG1hdGNoZXJPclZhbHVlW3Byb3BdID09PSBcInVuZGVmaW5lZFwiXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICBpZiAodmFsdWUgIT09IG1hdGNoZXJPclZhbHVlW3Byb3BdKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgICAgICAgIHR5cGVvZiB2YWx1ZSA9PT0gXCJ1bmRlZmluZWRcIiB8fFxuICAgICAgICAgICAgICAgICFkZWVwRXF1YWwodmFsdWUsIG1hdGNoZXJPclZhbHVlW3Byb3BdKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiTWF0Y2hlciB3YXMgYW4gdW5rbm93biBvciB1bnN1cHBvcnRlZCB0eXBlXCIpO1xufVxuLyogZXNsaW50LWVuYWJsZSBjb21wbGV4aXR5ICovXG5cbmZvckVhY2goT2JqZWN0LmtleXMoY3JlYXRlTWF0Y2hlciksIGZ1bmN0aW9uIChrZXkpIHtcbiAgICBtYXRjaFtrZXldID0gY3JlYXRlTWF0Y2hlcltrZXldO1xufSk7XG5cbm1vZHVsZS5leHBvcnRzID0gbWF0Y2g7XG4iLCJcInVzZSBzdHJpY3RcIjtcblxuLyoqXG4gKiBAbW9kdWxlIHNhbXNhbVxuICovXG52YXIgaWRlbnRpY2FsID0gcmVxdWlyZShcIi4vaWRlbnRpY2FsXCIpO1xudmFyIGlzQXJndW1lbnRzID0gcmVxdWlyZShcIi4vaXMtYXJndW1lbnRzXCIpO1xudmFyIGlzRWxlbWVudCA9IHJlcXVpcmUoXCIuL2lzLWVsZW1lbnRcIik7XG52YXIgaXNOZWdaZXJvID0gcmVxdWlyZShcIi4vaXMtbmVnLXplcm9cIik7XG52YXIgaXNTZXQgPSByZXF1aXJlKFwiLi9pcy1zZXRcIik7XG52YXIgaXNNYXAgPSByZXF1aXJlKFwiLi9pcy1tYXBcIik7XG52YXIgbWF0Y2ggPSByZXF1aXJlKFwiLi9tYXRjaFwiKTtcbnZhciBkZWVwRXF1YWxDeWNsaWMgPSByZXF1aXJlKFwiLi9kZWVwLWVxdWFsXCIpLnVzZShtYXRjaCk7XG52YXIgY3JlYXRlTWF0Y2hlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1tYXRjaGVyXCIpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBjcmVhdGVNYXRjaGVyOiBjcmVhdGVNYXRjaGVyLFxuICAgIGRlZXBFcXVhbDogZGVlcEVxdWFsQ3ljbGljLFxuICAgIGlkZW50aWNhbDogaWRlbnRpY2FsLFxuICAgIGlzQXJndW1lbnRzOiBpc0FyZ3VtZW50cyxcbiAgICBpc0VsZW1lbnQ6IGlzRWxlbWVudCxcbiAgICBpc01hcDogaXNNYXAsXG4gICAgaXNOZWdaZXJvOiBpc05lZ1plcm8sXG4gICAgaXNTZXQ6IGlzU2V0LFxuICAgIG1hdGNoOiBtYXRjaCxcbn07XG4iLCIoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpIDpcbiAgICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoZmFjdG9yeSkgOlxuICAgIChnbG9iYWwgPSB0eXBlb2YgZ2xvYmFsVGhpcyAhPT0gJ3VuZGVmaW5lZCcgPyBnbG9iYWxUaGlzIDogZ2xvYmFsIHx8IHNlbGYsIGdsb2JhbC50eXBlRGV0ZWN0ID0gZmFjdG9yeSgpKTtcbn0pKHRoaXMsIChmdW5jdGlvbiAoKSB7ICd1c2Ugc3RyaWN0JztcblxuICAgIHZhciBwcm9taXNlRXhpc3RzID0gdHlwZW9mIFByb21pc2UgPT09ICdmdW5jdGlvbic7XG4gICAgdmFyIGdsb2JhbE9iamVjdCA9IChmdW5jdGlvbiAoT2JqKSB7XG4gICAgICAgIGlmICh0eXBlb2YgZ2xvYmFsVGhpcyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHJldHVybiBnbG9iYWxUaGlzO1xuICAgICAgICB9XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShPYmosICd0eXBlRGV0ZWN0R2xvYmFsT2JqZWN0Jywge1xuICAgICAgICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICB9KTtcbiAgICAgICAgdmFyIGdsb2JhbCA9IHR5cGVEZXRlY3RHbG9iYWxPYmplY3Q7XG4gICAgICAgIGRlbGV0ZSBPYmoudHlwZURldGVjdEdsb2JhbE9iamVjdDtcbiAgICAgICAgcmV0dXJuIGdsb2JhbDtcbiAgICB9KShPYmplY3QucHJvdG90eXBlKTtcbiAgICB2YXIgc3ltYm9sRXhpc3RzID0gdHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCc7XG4gICAgdmFyIG1hcEV4aXN0cyA9IHR5cGVvZiBNYXAgIT09ICd1bmRlZmluZWQnO1xuICAgIHZhciBzZXRFeGlzdHMgPSB0eXBlb2YgU2V0ICE9PSAndW5kZWZpbmVkJztcbiAgICB2YXIgd2Vha01hcEV4aXN0cyA9IHR5cGVvZiBXZWFrTWFwICE9PSAndW5kZWZpbmVkJztcbiAgICB2YXIgd2Vha1NldEV4aXN0cyA9IHR5cGVvZiBXZWFrU2V0ICE9PSAndW5kZWZpbmVkJztcbiAgICB2YXIgZGF0YVZpZXdFeGlzdHMgPSB0eXBlb2YgRGF0YVZpZXcgIT09ICd1bmRlZmluZWQnO1xuICAgIHZhciBzeW1ib2xJdGVyYXRvckV4aXN0cyA9IHN5bWJvbEV4aXN0cyAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yICE9PSAndW5kZWZpbmVkJztcbiAgICB2YXIgc3ltYm9sVG9TdHJpbmdUYWdFeGlzdHMgPSBzeW1ib2xFeGlzdHMgJiYgdHlwZW9mIFN5bWJvbC50b1N0cmluZ1RhZyAhPT0gJ3VuZGVmaW5lZCc7XG4gICAgdmFyIHNldEVudHJpZXNFeGlzdHMgPSBzZXRFeGlzdHMgJiYgdHlwZW9mIFNldC5wcm90b3R5cGUuZW50cmllcyA9PT0gJ2Z1bmN0aW9uJztcbiAgICB2YXIgbWFwRW50cmllc0V4aXN0cyA9IG1hcEV4aXN0cyAmJiB0eXBlb2YgTWFwLnByb3RvdHlwZS5lbnRyaWVzID09PSAnZnVuY3Rpb24nO1xuICAgIHZhciBzZXRJdGVyYXRvclByb3RvdHlwZSA9IHNldEVudHJpZXNFeGlzdHMgJiYgT2JqZWN0LmdldFByb3RvdHlwZU9mKG5ldyBTZXQoKS5lbnRyaWVzKCkpO1xuICAgIHZhciBtYXBJdGVyYXRvclByb3RvdHlwZSA9IG1hcEVudHJpZXNFeGlzdHMgJiYgT2JqZWN0LmdldFByb3RvdHlwZU9mKG5ldyBNYXAoKS5lbnRyaWVzKCkpO1xuICAgIHZhciBhcnJheUl0ZXJhdG9yRXhpc3RzID0gc3ltYm9sSXRlcmF0b3JFeGlzdHMgJiYgdHlwZW9mIEFycmF5LnByb3RvdHlwZVtTeW1ib2wuaXRlcmF0b3JdID09PSAnZnVuY3Rpb24nO1xuICAgIHZhciBhcnJheUl0ZXJhdG9yUHJvdG90eXBlID0gYXJyYXlJdGVyYXRvckV4aXN0cyAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YoW11bU3ltYm9sLml0ZXJhdG9yXSgpKTtcbiAgICB2YXIgc3RyaW5nSXRlcmF0b3JFeGlzdHMgPSBzeW1ib2xJdGVyYXRvckV4aXN0cyAmJiB0eXBlb2YgU3RyaW5nLnByb3RvdHlwZVtTeW1ib2wuaXRlcmF0b3JdID09PSAnZnVuY3Rpb24nO1xuICAgIHZhciBzdHJpbmdJdGVyYXRvclByb3RvdHlwZSA9IHN0cmluZ0l0ZXJhdG9yRXhpc3RzICYmIE9iamVjdC5nZXRQcm90b3R5cGVPZignJ1tTeW1ib2wuaXRlcmF0b3JdKCkpO1xuICAgIHZhciB0b1N0cmluZ0xlZnRTbGljZUxlbmd0aCA9IDg7XG4gICAgdmFyIHRvU3RyaW5nUmlnaHRTbGljZUxlbmd0aCA9IC0xO1xuICAgIGZ1bmN0aW9uIHR5cGVEZXRlY3Qob2JqKSB7XG4gICAgICAgIHZhciB0eXBlb2ZPYmogPSB0eXBlb2Ygb2JqO1xuICAgICAgICBpZiAodHlwZW9mT2JqICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZk9iajtcbiAgICAgICAgfVxuICAgICAgICBpZiAob2JqID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gJ251bGwnO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvYmogPT09IGdsb2JhbE9iamVjdCkge1xuICAgICAgICAgICAgcmV0dXJuICdnbG9iYWwnO1xuICAgICAgICB9XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KG9iaikgJiZcbiAgICAgICAgICAgIChzeW1ib2xUb1N0cmluZ1RhZ0V4aXN0cyA9PT0gZmFsc2UgfHwgIShTeW1ib2wudG9TdHJpbmdUYWcgaW4gb2JqKSkpIHtcbiAgICAgICAgICAgIHJldHVybiAnQXJyYXknO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSAnb2JqZWN0JyAmJiB3aW5kb3cgIT09IG51bGwpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygd2luZG93LmxvY2F0aW9uID09PSAnb2JqZWN0JyAmJiBvYmogPT09IHdpbmRvdy5sb2NhdGlvbikge1xuICAgICAgICAgICAgICAgIHJldHVybiAnTG9jYXRpb24nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cuZG9jdW1lbnQgPT09ICdvYmplY3QnICYmIG9iaiA9PT0gd2luZG93LmRvY3VtZW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICdEb2N1bWVudCc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHlwZW9mIHdpbmRvdy5uYXZpZ2F0b3IgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cubmF2aWdhdG9yLm1pbWVUeXBlcyA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgICAgICAgICAgICAgb2JqID09PSB3aW5kb3cubmF2aWdhdG9yLm1pbWVUeXBlcykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ01pbWVUeXBlQXJyYXknO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHdpbmRvdy5uYXZpZ2F0b3IucGx1Z2lucyA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgICAgICAgICAgICAgb2JqID09PSB3aW5kb3cubmF2aWdhdG9yLnBsdWdpbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdQbHVnaW5BcnJheSc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCh0eXBlb2Ygd2luZG93LkhUTUxFbGVtZW50ID09PSAnZnVuY3Rpb24nIHx8XG4gICAgICAgICAgICAgICAgdHlwZW9mIHdpbmRvdy5IVE1MRWxlbWVudCA9PT0gJ29iamVjdCcpICYmXG4gICAgICAgICAgICAgICAgb2JqIGluc3RhbmNlb2Ygd2luZG93LkhUTUxFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKG9iai50YWdOYW1lID09PSAnQkxPQ0tRVU9URScpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdIVE1MUXVvdGVFbGVtZW50JztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG9iai50YWdOYW1lID09PSAnVEQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnSFRNTFRhYmxlRGF0YUNlbGxFbGVtZW50JztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG9iai50YWdOYW1lID09PSAnVEgnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnSFRNTFRhYmxlSGVhZGVyQ2VsbEVsZW1lbnQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB2YXIgc3RyaW5nVGFnID0gKHN5bWJvbFRvU3RyaW5nVGFnRXhpc3RzICYmIG9ialtTeW1ib2wudG9TdHJpbmdUYWddKTtcbiAgICAgICAgaWYgKHR5cGVvZiBzdHJpbmdUYWcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nVGFnO1xuICAgICAgICB9XG4gICAgICAgIHZhciBvYmpQcm90b3R5cGUgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2Yob2JqKTtcbiAgICAgICAgaWYgKG9ialByb3RvdHlwZSA9PT0gUmVnRXhwLnByb3RvdHlwZSkge1xuICAgICAgICAgICAgcmV0dXJuICdSZWdFeHAnO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvYmpQcm90b3R5cGUgPT09IERhdGUucHJvdG90eXBlKSB7XG4gICAgICAgICAgICByZXR1cm4gJ0RhdGUnO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwcm9taXNlRXhpc3RzICYmIG9ialByb3RvdHlwZSA9PT0gUHJvbWlzZS5wcm90b3R5cGUpIHtcbiAgICAgICAgICAgIHJldHVybiAnUHJvbWlzZSc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNldEV4aXN0cyAmJiBvYmpQcm90b3R5cGUgPT09IFNldC5wcm90b3R5cGUpIHtcbiAgICAgICAgICAgIHJldHVybiAnU2V0JztcbiAgICAgICAgfVxuICAgICAgICBpZiAobWFwRXhpc3RzICYmIG9ialByb3RvdHlwZSA9PT0gTWFwLnByb3RvdHlwZSkge1xuICAgICAgICAgICAgcmV0dXJuICdNYXAnO1xuICAgICAgICB9XG4gICAgICAgIGlmICh3ZWFrU2V0RXhpc3RzICYmIG9ialByb3RvdHlwZSA9PT0gV2Vha1NldC5wcm90b3R5cGUpIHtcbiAgICAgICAgICAgIHJldHVybiAnV2Vha1NldCc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHdlYWtNYXBFeGlzdHMgJiYgb2JqUHJvdG90eXBlID09PSBXZWFrTWFwLnByb3RvdHlwZSkge1xuICAgICAgICAgICAgcmV0dXJuICdXZWFrTWFwJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoZGF0YVZpZXdFeGlzdHMgJiYgb2JqUHJvdG90eXBlID09PSBEYXRhVmlldy5wcm90b3R5cGUpIHtcbiAgICAgICAgICAgIHJldHVybiAnRGF0YVZpZXcnO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYXBFeGlzdHMgJiYgb2JqUHJvdG90eXBlID09PSBtYXBJdGVyYXRvclByb3RvdHlwZSkge1xuICAgICAgICAgICAgcmV0dXJuICdNYXAgSXRlcmF0b3InO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzZXRFeGlzdHMgJiYgb2JqUHJvdG90eXBlID09PSBzZXRJdGVyYXRvclByb3RvdHlwZSkge1xuICAgICAgICAgICAgcmV0dXJuICdTZXQgSXRlcmF0b3InO1xuICAgICAgICB9XG4gICAgICAgIGlmIChhcnJheUl0ZXJhdG9yRXhpc3RzICYmIG9ialByb3RvdHlwZSA9PT0gYXJyYXlJdGVyYXRvclByb3RvdHlwZSkge1xuICAgICAgICAgICAgcmV0dXJuICdBcnJheSBJdGVyYXRvcic7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHN0cmluZ0l0ZXJhdG9yRXhpc3RzICYmIG9ialByb3RvdHlwZSA9PT0gc3RyaW5nSXRlcmF0b3JQcm90b3R5cGUpIHtcbiAgICAgICAgICAgIHJldHVybiAnU3RyaW5nIEl0ZXJhdG9yJztcbiAgICAgICAgfVxuICAgICAgICBpZiAob2JqUHJvdG90eXBlID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gJ09iamVjdCc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIE9iamVjdFxuICAgICAgICAgICAgLnByb3RvdHlwZVxuICAgICAgICAgICAgLnRvU3RyaW5nXG4gICAgICAgICAgICAuY2FsbChvYmopXG4gICAgICAgICAgICAuc2xpY2UodG9TdHJpbmdMZWZ0U2xpY2VMZW5ndGgsIHRvU3RyaW5nUmlnaHRTbGljZUxlbmd0aCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHR5cGVEZXRlY3Q7XG5cbn0pKTtcbiIsImlmICh0eXBlb2YgT2JqZWN0LmNyZWF0ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAvLyBpbXBsZW1lbnRhdGlvbiBmcm9tIHN0YW5kYXJkIG5vZGUuanMgJ3V0aWwnIG1vZHVsZVxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGluaGVyaXRzKGN0b3IsIHN1cGVyQ3Rvcikge1xuICAgIGN0b3Iuc3VwZXJfID0gc3VwZXJDdG9yXG4gICAgY3Rvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ3Rvci5wcm90b3R5cGUsIHtcbiAgICAgIGNvbnN0cnVjdG9yOiB7XG4gICAgICAgIHZhbHVlOiBjdG9yLFxuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgfVxuICAgIH0pO1xuICB9O1xufSBlbHNlIHtcbiAgLy8gb2xkIHNjaG9vbCBzaGltIGZvciBvbGQgYnJvd3NlcnNcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIHZhciBUZW1wQ3RvciA9IGZ1bmN0aW9uICgpIHt9XG4gICAgVGVtcEN0b3IucHJvdG90eXBlID0gc3VwZXJDdG9yLnByb3RvdHlwZVxuICAgIGN0b3IucHJvdG90eXBlID0gbmV3IFRlbXBDdG9yKClcbiAgICBjdG9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IGN0b3JcbiAgfVxufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc0J1ZmZlcihhcmcpIHtcbiAgcmV0dXJuIGFyZyAmJiB0eXBlb2YgYXJnID09PSAnb2JqZWN0J1xuICAgICYmIHR5cGVvZiBhcmcuY29weSA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcuZmlsbCA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcucmVhZFVJbnQ4ID09PSAnZnVuY3Rpb24nO1xufSIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG52YXIgZm9ybWF0UmVnRXhwID0gLyVbc2RqJV0vZztcbmV4cG9ydHMuZm9ybWF0ID0gZnVuY3Rpb24oZikge1xuICBpZiAoIWlzU3RyaW5nKGYpKSB7XG4gICAgdmFyIG9iamVjdHMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgb2JqZWN0cy5wdXNoKGluc3BlY3QoYXJndW1lbnRzW2ldKSk7XG4gICAgfVxuICAgIHJldHVybiBvYmplY3RzLmpvaW4oJyAnKTtcbiAgfVxuXG4gIHZhciBpID0gMTtcbiAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gIHZhciBsZW4gPSBhcmdzLmxlbmd0aDtcbiAgdmFyIHN0ciA9IFN0cmluZyhmKS5yZXBsYWNlKGZvcm1hdFJlZ0V4cCwgZnVuY3Rpb24oeCkge1xuICAgIGlmICh4ID09PSAnJSUnKSByZXR1cm4gJyUnO1xuICAgIGlmIChpID49IGxlbikgcmV0dXJuIHg7XG4gICAgc3dpdGNoICh4KSB7XG4gICAgICBjYXNlICclcyc6IHJldHVybiBTdHJpbmcoYXJnc1tpKytdKTtcbiAgICAgIGNhc2UgJyVkJzogcmV0dXJuIE51bWJlcihhcmdzW2krK10pO1xuICAgICAgY2FzZSAnJWonOlxuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShhcmdzW2krK10pO1xuICAgICAgICB9IGNhdGNoIChfKSB7XG4gICAgICAgICAgcmV0dXJuICdbQ2lyY3VsYXJdJztcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHg7XG4gICAgfVxuICB9KTtcbiAgZm9yICh2YXIgeCA9IGFyZ3NbaV07IGkgPCBsZW47IHggPSBhcmdzWysraV0pIHtcbiAgICBpZiAoaXNOdWxsKHgpIHx8ICFpc09iamVjdCh4KSkge1xuICAgICAgc3RyICs9ICcgJyArIHg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciArPSAnICcgKyBpbnNwZWN0KHgpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gc3RyO1xufTtcblxuXG4vLyBNYXJrIHRoYXQgYSBtZXRob2Qgc2hvdWxkIG5vdCBiZSB1c2VkLlxuLy8gUmV0dXJucyBhIG1vZGlmaWVkIGZ1bmN0aW9uIHdoaWNoIHdhcm5zIG9uY2UgYnkgZGVmYXVsdC5cbi8vIElmIC0tbm8tZGVwcmVjYXRpb24gaXMgc2V0LCB0aGVuIGl0IGlzIGEgbm8tb3AuXG5leHBvcnRzLmRlcHJlY2F0ZSA9IGZ1bmN0aW9uKGZuLCBtc2cpIHtcbiAgLy8gQWxsb3cgZm9yIGRlcHJlY2F0aW5nIHRoaW5ncyBpbiB0aGUgcHJvY2VzcyBvZiBzdGFydGluZyB1cC5cbiAgaWYgKGlzVW5kZWZpbmVkKGdsb2JhbC5wcm9jZXNzKSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBleHBvcnRzLmRlcHJlY2F0ZShmbiwgbXNnKS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG4gIH1cblxuICBpZiAocHJvY2Vzcy5ub0RlcHJlY2F0aW9uID09PSB0cnVlKSB7XG4gICAgcmV0dXJuIGZuO1xuICB9XG5cbiAgdmFyIHdhcm5lZCA9IGZhbHNlO1xuICBmdW5jdGlvbiBkZXByZWNhdGVkKCkge1xuICAgIGlmICghd2FybmVkKSB7XG4gICAgICBpZiAocHJvY2Vzcy50aHJvd0RlcHJlY2F0aW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgICAgfSBlbHNlIGlmIChwcm9jZXNzLnRyYWNlRGVwcmVjYXRpb24pIHtcbiAgICAgICAgY29uc29sZS50cmFjZShtc2cpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihtc2cpO1xuICAgICAgfVxuICAgICAgd2FybmVkID0gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gIH1cblxuICByZXR1cm4gZGVwcmVjYXRlZDtcbn07XG5cblxudmFyIGRlYnVncyA9IHt9O1xudmFyIGRlYnVnRW52aXJvbjtcbmV4cG9ydHMuZGVidWdsb2cgPSBmdW5jdGlvbihzZXQpIHtcbiAgaWYgKGlzVW5kZWZpbmVkKGRlYnVnRW52aXJvbikpXG4gICAgZGVidWdFbnZpcm9uID0gcHJvY2Vzcy5lbnYuTk9ERV9ERUJVRyB8fCAnJztcbiAgc2V0ID0gc2V0LnRvVXBwZXJDYXNlKCk7XG4gIGlmICghZGVidWdzW3NldF0pIHtcbiAgICBpZiAobmV3IFJlZ0V4cCgnXFxcXGInICsgc2V0ICsgJ1xcXFxiJywgJ2knKS50ZXN0KGRlYnVnRW52aXJvbikpIHtcbiAgICAgIHZhciBwaWQgPSBwcm9jZXNzLnBpZDtcbiAgICAgIGRlYnVnc1tzZXRdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBtc2cgPSBleHBvcnRzLmZvcm1hdC5hcHBseShleHBvcnRzLCBhcmd1bWVudHMpO1xuICAgICAgICBjb25zb2xlLmVycm9yKCclcyAlZDogJXMnLCBzZXQsIHBpZCwgbXNnKTtcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlYnVnc1tzZXRdID0gZnVuY3Rpb24oKSB7fTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGRlYnVnc1tzZXRdO1xufTtcblxuXG4vKipcbiAqIEVjaG9zIHRoZSB2YWx1ZSBvZiBhIHZhbHVlLiBUcnlzIHRvIHByaW50IHRoZSB2YWx1ZSBvdXRcbiAqIGluIHRoZSBiZXN0IHdheSBwb3NzaWJsZSBnaXZlbiB0aGUgZGlmZmVyZW50IHR5cGVzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBwcmludCBvdXQuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0cyBPcHRpb25hbCBvcHRpb25zIG9iamVjdCB0aGF0IGFsdGVycyB0aGUgb3V0cHV0LlxuICovXG4vKiBsZWdhY3k6IG9iaiwgc2hvd0hpZGRlbiwgZGVwdGgsIGNvbG9ycyovXG5mdW5jdGlvbiBpbnNwZWN0KG9iaiwgb3B0cykge1xuICAvLyBkZWZhdWx0IG9wdGlvbnNcbiAgdmFyIGN0eCA9IHtcbiAgICBzZWVuOiBbXSxcbiAgICBzdHlsaXplOiBzdHlsaXplTm9Db2xvclxuICB9O1xuICAvLyBsZWdhY3kuLi5cbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPj0gMykgY3R4LmRlcHRoID0gYXJndW1lbnRzWzJdO1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+PSA0KSBjdHguY29sb3JzID0gYXJndW1lbnRzWzNdO1xuICBpZiAoaXNCb29sZWFuKG9wdHMpKSB7XG4gICAgLy8gbGVnYWN5Li4uXG4gICAgY3R4LnNob3dIaWRkZW4gPSBvcHRzO1xuICB9IGVsc2UgaWYgKG9wdHMpIHtcbiAgICAvLyBnb3QgYW4gXCJvcHRpb25zXCIgb2JqZWN0XG4gICAgZXhwb3J0cy5fZXh0ZW5kKGN0eCwgb3B0cyk7XG4gIH1cbiAgLy8gc2V0IGRlZmF1bHQgb3B0aW9uc1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LnNob3dIaWRkZW4pKSBjdHguc2hvd0hpZGRlbiA9IGZhbHNlO1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LmRlcHRoKSkgY3R4LmRlcHRoID0gMjtcbiAgaWYgKGlzVW5kZWZpbmVkKGN0eC5jb2xvcnMpKSBjdHguY29sb3JzID0gZmFsc2U7XG4gIGlmIChpc1VuZGVmaW5lZChjdHguY3VzdG9tSW5zcGVjdCkpIGN0eC5jdXN0b21JbnNwZWN0ID0gdHJ1ZTtcbiAgaWYgKGN0eC5jb2xvcnMpIGN0eC5zdHlsaXplID0gc3R5bGl6ZVdpdGhDb2xvcjtcbiAgcmV0dXJuIGZvcm1hdFZhbHVlKGN0eCwgb2JqLCBjdHguZGVwdGgpO1xufVxuZXhwb3J0cy5pbnNwZWN0ID0gaW5zcGVjdDtcblxuXG4vLyBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FOU0lfZXNjYXBlX2NvZGUjZ3JhcGhpY3Ncbmluc3BlY3QuY29sb3JzID0ge1xuICAnYm9sZCcgOiBbMSwgMjJdLFxuICAnaXRhbGljJyA6IFszLCAyM10sXG4gICd1bmRlcmxpbmUnIDogWzQsIDI0XSxcbiAgJ2ludmVyc2UnIDogWzcsIDI3XSxcbiAgJ3doaXRlJyA6IFszNywgMzldLFxuICAnZ3JleScgOiBbOTAsIDM5XSxcbiAgJ2JsYWNrJyA6IFszMCwgMzldLFxuICAnYmx1ZScgOiBbMzQsIDM5XSxcbiAgJ2N5YW4nIDogWzM2LCAzOV0sXG4gICdncmVlbicgOiBbMzIsIDM5XSxcbiAgJ21hZ2VudGEnIDogWzM1LCAzOV0sXG4gICdyZWQnIDogWzMxLCAzOV0sXG4gICd5ZWxsb3cnIDogWzMzLCAzOV1cbn07XG5cbi8vIERvbid0IHVzZSAnYmx1ZScgbm90IHZpc2libGUgb24gY21kLmV4ZVxuaW5zcGVjdC5zdHlsZXMgPSB7XG4gICdzcGVjaWFsJzogJ2N5YW4nLFxuICAnbnVtYmVyJzogJ3llbGxvdycsXG4gICdib29sZWFuJzogJ3llbGxvdycsXG4gICd1bmRlZmluZWQnOiAnZ3JleScsXG4gICdudWxsJzogJ2JvbGQnLFxuICAnc3RyaW5nJzogJ2dyZWVuJyxcbiAgJ2RhdGUnOiAnbWFnZW50YScsXG4gIC8vIFwibmFtZVwiOiBpbnRlbnRpb25hbGx5IG5vdCBzdHlsaW5nXG4gICdyZWdleHAnOiAncmVkJ1xufTtcblxuXG5mdW5jdGlvbiBzdHlsaXplV2l0aENvbG9yKHN0ciwgc3R5bGVUeXBlKSB7XG4gIHZhciBzdHlsZSA9IGluc3BlY3Quc3R5bGVzW3N0eWxlVHlwZV07XG5cbiAgaWYgKHN0eWxlKSB7XG4gICAgcmV0dXJuICdcXHUwMDFiWycgKyBpbnNwZWN0LmNvbG9yc1tzdHlsZV1bMF0gKyAnbScgKyBzdHIgK1xuICAgICAgICAgICAnXFx1MDAxYlsnICsgaW5zcGVjdC5jb2xvcnNbc3R5bGVdWzFdICsgJ20nO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBzdHI7XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBzdHlsaXplTm9Db2xvcihzdHIsIHN0eWxlVHlwZSkge1xuICByZXR1cm4gc3RyO1xufVxuXG5cbmZ1bmN0aW9uIGFycmF5VG9IYXNoKGFycmF5KSB7XG4gIHZhciBoYXNoID0ge307XG5cbiAgYXJyYXkuZm9yRWFjaChmdW5jdGlvbih2YWwsIGlkeCkge1xuICAgIGhhc2hbdmFsXSA9IHRydWU7XG4gIH0pO1xuXG4gIHJldHVybiBoYXNoO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFZhbHVlKGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcykge1xuICAvLyBQcm92aWRlIGEgaG9vayBmb3IgdXNlci1zcGVjaWZpZWQgaW5zcGVjdCBmdW5jdGlvbnMuXG4gIC8vIENoZWNrIHRoYXQgdmFsdWUgaXMgYW4gb2JqZWN0IHdpdGggYW4gaW5zcGVjdCBmdW5jdGlvbiBvbiBpdFxuICBpZiAoY3R4LmN1c3RvbUluc3BlY3QgJiZcbiAgICAgIHZhbHVlICYmXG4gICAgICBpc0Z1bmN0aW9uKHZhbHVlLmluc3BlY3QpICYmXG4gICAgICAvLyBGaWx0ZXIgb3V0IHRoZSB1dGlsIG1vZHVsZSwgaXQncyBpbnNwZWN0IGZ1bmN0aW9uIGlzIHNwZWNpYWxcbiAgICAgIHZhbHVlLmluc3BlY3QgIT09IGV4cG9ydHMuaW5zcGVjdCAmJlxuICAgICAgLy8gQWxzbyBmaWx0ZXIgb3V0IGFueSBwcm90b3R5cGUgb2JqZWN0cyB1c2luZyB0aGUgY2lyY3VsYXIgY2hlY2suXG4gICAgICAhKHZhbHVlLmNvbnN0cnVjdG9yICYmIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZSA9PT0gdmFsdWUpKSB7XG4gICAgdmFyIHJldCA9IHZhbHVlLmluc3BlY3QocmVjdXJzZVRpbWVzLCBjdHgpO1xuICAgIGlmICghaXNTdHJpbmcocmV0KSkge1xuICAgICAgcmV0ID0gZm9ybWF0VmFsdWUoY3R4LCByZXQsIHJlY3Vyc2VUaW1lcyk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvLyBQcmltaXRpdmUgdHlwZXMgY2Fubm90IGhhdmUgcHJvcGVydGllc1xuICB2YXIgcHJpbWl0aXZlID0gZm9ybWF0UHJpbWl0aXZlKGN0eCwgdmFsdWUpO1xuICBpZiAocHJpbWl0aXZlKSB7XG4gICAgcmV0dXJuIHByaW1pdGl2ZTtcbiAgfVxuXG4gIC8vIExvb2sgdXAgdGhlIGtleXMgb2YgdGhlIG9iamVjdC5cbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyh2YWx1ZSk7XG4gIHZhciB2aXNpYmxlS2V5cyA9IGFycmF5VG9IYXNoKGtleXMpO1xuXG4gIGlmIChjdHguc2hvd0hpZGRlbikge1xuICAgIGtleXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh2YWx1ZSk7XG4gIH1cblxuICAvLyBJRSBkb2Vzbid0IG1ha2UgZXJyb3IgZmllbGRzIG5vbi1lbnVtZXJhYmxlXG4gIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9pZS9kd3c1MnNidCh2PXZzLjk0KS5hc3B4XG4gIGlmIChpc0Vycm9yKHZhbHVlKVxuICAgICAgJiYgKGtleXMuaW5kZXhPZignbWVzc2FnZScpID49IDAgfHwga2V5cy5pbmRleE9mKCdkZXNjcmlwdGlvbicpID49IDApKSB7XG4gICAgcmV0dXJuIGZvcm1hdEVycm9yKHZhbHVlKTtcbiAgfVxuXG4gIC8vIFNvbWUgdHlwZSBvZiBvYmplY3Qgd2l0aG91dCBwcm9wZXJ0aWVzIGNhbiBiZSBzaG9ydGN1dHRlZC5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwKSB7XG4gICAgaWYgKGlzRnVuY3Rpb24odmFsdWUpKSB7XG4gICAgICB2YXIgbmFtZSA9IHZhbHVlLm5hbWUgPyAnOiAnICsgdmFsdWUubmFtZSA6ICcnO1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKCdbRnVuY3Rpb24nICsgbmFtZSArICddJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gICAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSksICdyZWdleHAnKTtcbiAgICB9XG4gICAgaWYgKGlzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShEYXRlLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSwgJ2RhdGUnKTtcbiAgICB9XG4gICAgaWYgKGlzRXJyb3IodmFsdWUpKSB7XG4gICAgICByZXR1cm4gZm9ybWF0RXJyb3IodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBiYXNlID0gJycsIGFycmF5ID0gZmFsc2UsIGJyYWNlcyA9IFsneycsICd9J107XG5cbiAgLy8gTWFrZSBBcnJheSBzYXkgdGhhdCB0aGV5IGFyZSBBcnJheVxuICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICBhcnJheSA9IHRydWU7XG4gICAgYnJhY2VzID0gWydbJywgJ10nXTtcbiAgfVxuXG4gIC8vIE1ha2UgZnVuY3Rpb25zIHNheSB0aGF0IHRoZXkgYXJlIGZ1bmN0aW9uc1xuICBpZiAoaXNGdW5jdGlvbih2YWx1ZSkpIHtcbiAgICB2YXIgbiA9IHZhbHVlLm5hbWUgPyAnOiAnICsgdmFsdWUubmFtZSA6ICcnO1xuICAgIGJhc2UgPSAnIFtGdW5jdGlvbicgKyBuICsgJ10nO1xuICB9XG5cbiAgLy8gTWFrZSBSZWdFeHBzIHNheSB0aGF0IHRoZXkgYXJlIFJlZ0V4cHNcbiAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgIGJhc2UgPSAnICcgKyBSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBkYXRlcyB3aXRoIHByb3BlcnRpZXMgZmlyc3Qgc2F5IHRoZSBkYXRlXG4gIGlmIChpc0RhdGUodmFsdWUpKSB7XG4gICAgYmFzZSA9ICcgJyArIERhdGUucHJvdG90eXBlLnRvVVRDU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBlcnJvciB3aXRoIG1lc3NhZ2UgZmlyc3Qgc2F5IHRoZSBlcnJvclxuICBpZiAoaXNFcnJvcih2YWx1ZSkpIHtcbiAgICBiYXNlID0gJyAnICsgZm9ybWF0RXJyb3IodmFsdWUpO1xuICB9XG5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwICYmICghYXJyYXkgfHwgdmFsdWUubGVuZ3RoID09IDApKSB7XG4gICAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyBicmFjZXNbMV07XG4gIH1cblxuICBpZiAocmVjdXJzZVRpbWVzIDwgMCkge1xuICAgIGlmIChpc1JlZ0V4cCh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpLCAncmVnZXhwJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZSgnW09iamVjdF0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuXG4gIGN0eC5zZWVuLnB1c2godmFsdWUpO1xuXG4gIHZhciBvdXRwdXQ7XG4gIGlmIChhcnJheSkge1xuICAgIG91dHB1dCA9IGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpO1xuICB9IGVsc2Uge1xuICAgIG91dHB1dCA9IGtleXMubWFwKGZ1bmN0aW9uKGtleSkge1xuICAgICAgcmV0dXJuIGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleSwgYXJyYXkpO1xuICAgIH0pO1xuICB9XG5cbiAgY3R4LnNlZW4ucG9wKCk7XG5cbiAgcmV0dXJuIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRQcmltaXRpdmUoY3R4LCB2YWx1ZSkge1xuICBpZiAoaXNVbmRlZmluZWQodmFsdWUpKVxuICAgIHJldHVybiBjdHguc3R5bGl6ZSgndW5kZWZpbmVkJywgJ3VuZGVmaW5lZCcpO1xuICBpZiAoaXNTdHJpbmcodmFsdWUpKSB7XG4gICAgdmFyIHNpbXBsZSA9ICdcXCcnICsgSlNPTi5zdHJpbmdpZnkodmFsdWUpLnJlcGxhY2UoL15cInxcIiQvZywgJycpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFxcXFwiL2csICdcIicpICsgJ1xcJyc7XG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKHNpbXBsZSwgJ3N0cmluZycpO1xuICB9XG4gIGlmIChpc051bWJlcih2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCcnICsgdmFsdWUsICdudW1iZXInKTtcbiAgaWYgKGlzQm9vbGVhbih2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCcnICsgdmFsdWUsICdib29sZWFuJyk7XG4gIC8vIEZvciBzb21lIHJlYXNvbiB0eXBlb2YgbnVsbCBpcyBcIm9iamVjdFwiLCBzbyBzcGVjaWFsIGNhc2UgaGVyZS5cbiAgaWYgKGlzTnVsbCh2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCdudWxsJywgJ251bGwnKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRFcnJvcih2YWx1ZSkge1xuICByZXR1cm4gJ1snICsgRXJyb3IucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpICsgJ10nO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpIHtcbiAgdmFyIG91dHB1dCA9IFtdO1xuICBmb3IgKHZhciBpID0gMCwgbCA9IHZhbHVlLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgIGlmIChoYXNPd25Qcm9wZXJ0eSh2YWx1ZSwgU3RyaW5nKGkpKSkge1xuICAgICAgb3V0cHV0LnB1c2goZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cyxcbiAgICAgICAgICBTdHJpbmcoaSksIHRydWUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0cHV0LnB1c2goJycpO1xuICAgIH1cbiAgfVxuICBrZXlzLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgaWYgKCFrZXkubWF0Y2goL15cXGQrJC8pKSB7XG4gICAgICBvdXRwdXQucHVzaChmb3JtYXRQcm9wZXJ0eShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLFxuICAgICAgICAgIGtleSwgdHJ1ZSkpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBvdXRwdXQ7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5LCBhcnJheSkge1xuICB2YXIgbmFtZSwgc3RyLCBkZXNjO1xuICBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih2YWx1ZSwga2V5KSB8fCB7IHZhbHVlOiB2YWx1ZVtrZXldIH07XG4gIGlmIChkZXNjLmdldCkge1xuICAgIGlmIChkZXNjLnNldCkge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tHZXR0ZXIvU2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbR2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChkZXNjLnNldCkge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tTZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gIH1cbiAgaWYgKCFoYXNPd25Qcm9wZXJ0eSh2aXNpYmxlS2V5cywga2V5KSkge1xuICAgIG5hbWUgPSAnWycgKyBrZXkgKyAnXSc7XG4gIH1cbiAgaWYgKCFzdHIpIHtcbiAgICBpZiAoY3R4LnNlZW4uaW5kZXhPZihkZXNjLnZhbHVlKSA8IDApIHtcbiAgICAgIGlmIChpc051bGwocmVjdXJzZVRpbWVzKSkge1xuICAgICAgICBzdHIgPSBmb3JtYXRWYWx1ZShjdHgsIGRlc2MudmFsdWUsIG51bGwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RyID0gZm9ybWF0VmFsdWUoY3R4LCBkZXNjLnZhbHVlLCByZWN1cnNlVGltZXMgLSAxKTtcbiAgICAgIH1cbiAgICAgIGlmIChzdHIuaW5kZXhPZignXFxuJykgPiAtMSkge1xuICAgICAgICBpZiAoYXJyYXkpIHtcbiAgICAgICAgICBzdHIgPSBzdHIuc3BsaXQoJ1xcbicpLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgICAgICByZXR1cm4gJyAgJyArIGxpbmU7XG4gICAgICAgICAgfSkuam9pbignXFxuJykuc3Vic3RyKDIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0ciA9ICdcXG4nICsgc3RyLnNwbGl0KCdcXG4nKS5tYXAoZnVuY3Rpb24obGluZSkge1xuICAgICAgICAgICAgcmV0dXJuICcgICAnICsgbGluZTtcbiAgICAgICAgICB9KS5qb2luKCdcXG4nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW0NpcmN1bGFyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9XG4gIGlmIChpc1VuZGVmaW5lZChuYW1lKSkge1xuICAgIGlmIChhcnJheSAmJiBrZXkubWF0Y2goL15cXGQrJC8pKSB7XG4gICAgICByZXR1cm4gc3RyO1xuICAgIH1cbiAgICBuYW1lID0gSlNPTi5zdHJpbmdpZnkoJycgKyBrZXkpO1xuICAgIGlmIChuYW1lLm1hdGNoKC9eXCIoW2EtekEtWl9dW2EtekEtWl8wLTldKilcIiQvKSkge1xuICAgICAgbmFtZSA9IG5hbWUuc3Vic3RyKDEsIG5hbWUubGVuZ3RoIC0gMik7XG4gICAgICBuYW1lID0gY3R4LnN0eWxpemUobmFtZSwgJ25hbWUnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmFtZSA9IG5hbWUucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcXCIvZywgJ1wiJylcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoLyheXCJ8XCIkKS9nLCBcIidcIik7XG4gICAgICBuYW1lID0gY3R4LnN0eWxpemUobmFtZSwgJ3N0cmluZycpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuYW1lICsgJzogJyArIHN0cjtcbn1cblxuXG5mdW5jdGlvbiByZWR1Y2VUb1NpbmdsZVN0cmluZyhvdXRwdXQsIGJhc2UsIGJyYWNlcykge1xuICB2YXIgbnVtTGluZXNFc3QgPSAwO1xuICB2YXIgbGVuZ3RoID0gb3V0cHV0LnJlZHVjZShmdW5jdGlvbihwcmV2LCBjdXIpIHtcbiAgICBudW1MaW5lc0VzdCsrO1xuICAgIGlmIChjdXIuaW5kZXhPZignXFxuJykgPj0gMCkgbnVtTGluZXNFc3QrKztcbiAgICByZXR1cm4gcHJldiArIGN1ci5yZXBsYWNlKC9cXHUwMDFiXFxbXFxkXFxkP20vZywgJycpLmxlbmd0aCArIDE7XG4gIH0sIDApO1xuXG4gIGlmIChsZW5ndGggPiA2MCkge1xuICAgIHJldHVybiBicmFjZXNbMF0gK1xuICAgICAgICAgICAoYmFzZSA9PT0gJycgPyAnJyA6IGJhc2UgKyAnXFxuICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgb3V0cHV0LmpvaW4oJyxcXG4gICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgYnJhY2VzWzFdO1xuICB9XG5cbiAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyAnICcgKyBvdXRwdXQuam9pbignLCAnKSArICcgJyArIGJyYWNlc1sxXTtcbn1cblxuXG4vLyBOT1RFOiBUaGVzZSB0eXBlIGNoZWNraW5nIGZ1bmN0aW9ucyBpbnRlbnRpb25hbGx5IGRvbid0IHVzZSBgaW5zdGFuY2VvZmBcbi8vIGJlY2F1c2UgaXQgaXMgZnJhZ2lsZSBhbmQgY2FuIGJlIGVhc2lseSBmYWtlZCB3aXRoIGBPYmplY3QuY3JlYXRlKClgLlxuZnVuY3Rpb24gaXNBcnJheShhcikge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShhcik7XG59XG5leHBvcnRzLmlzQXJyYXkgPSBpc0FycmF5O1xuXG5mdW5jdGlvbiBpc0Jvb2xlYW4oYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnYm9vbGVhbic7XG59XG5leHBvcnRzLmlzQm9vbGVhbiA9IGlzQm9vbGVhbjtcblxuZnVuY3Rpb24gaXNOdWxsKGFyZykge1xuICByZXR1cm4gYXJnID09PSBudWxsO1xufVxuZXhwb3J0cy5pc051bGwgPSBpc051bGw7XG5cbmZ1bmN0aW9uIGlzTnVsbE9yVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09IG51bGw7XG59XG5leHBvcnRzLmlzTnVsbE9yVW5kZWZpbmVkID0gaXNOdWxsT3JVbmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGlzTnVtYmVyKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ251bWJlcic7XG59XG5leHBvcnRzLmlzTnVtYmVyID0gaXNOdW1iZXI7XG5cbmZ1bmN0aW9uIGlzU3RyaW5nKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ3N0cmluZyc7XG59XG5leHBvcnRzLmlzU3RyaW5nID0gaXNTdHJpbmc7XG5cbmZ1bmN0aW9uIGlzU3ltYm9sKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCc7XG59XG5leHBvcnRzLmlzU3ltYm9sID0gaXNTeW1ib2w7XG5cbmZ1bmN0aW9uIGlzVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09PSB2b2lkIDA7XG59XG5leHBvcnRzLmlzVW5kZWZpbmVkID0gaXNVbmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGlzUmVnRXhwKHJlKSB7XG4gIHJldHVybiBpc09iamVjdChyZSkgJiYgb2JqZWN0VG9TdHJpbmcocmUpID09PSAnW29iamVjdCBSZWdFeHBdJztcbn1cbmV4cG9ydHMuaXNSZWdFeHAgPSBpc1JlZ0V4cDtcblxuZnVuY3Rpb24gaXNPYmplY3QoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnb2JqZWN0JyAmJiBhcmcgIT09IG51bGw7XG59XG5leHBvcnRzLmlzT2JqZWN0ID0gaXNPYmplY3Q7XG5cbmZ1bmN0aW9uIGlzRGF0ZShkKSB7XG4gIHJldHVybiBpc09iamVjdChkKSAmJiBvYmplY3RUb1N0cmluZyhkKSA9PT0gJ1tvYmplY3QgRGF0ZV0nO1xufVxuZXhwb3J0cy5pc0RhdGUgPSBpc0RhdGU7XG5cbmZ1bmN0aW9uIGlzRXJyb3IoZSkge1xuICByZXR1cm4gaXNPYmplY3QoZSkgJiZcbiAgICAgIChvYmplY3RUb1N0cmluZyhlKSA9PT0gJ1tvYmplY3QgRXJyb3JdJyB8fCBlIGluc3RhbmNlb2YgRXJyb3IpO1xufVxuZXhwb3J0cy5pc0Vycm9yID0gaXNFcnJvcjtcblxuZnVuY3Rpb24gaXNGdW5jdGlvbihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdmdW5jdGlvbic7XG59XG5leHBvcnRzLmlzRnVuY3Rpb24gPSBpc0Z1bmN0aW9uO1xuXG5mdW5jdGlvbiBpc1ByaW1pdGl2ZShhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PT0gbnVsbCB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ2Jvb2xlYW4nIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnbnVtYmVyJyB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ3N0cmluZycgfHxcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnIHx8ICAvLyBFUzYgc3ltYm9sXG4gICAgICAgICB0eXBlb2YgYXJnID09PSAndW5kZWZpbmVkJztcbn1cbmV4cG9ydHMuaXNQcmltaXRpdmUgPSBpc1ByaW1pdGl2ZTtcblxuZXhwb3J0cy5pc0J1ZmZlciA9IHJlcXVpcmUoJy4vc3VwcG9ydC9pc0J1ZmZlcicpO1xuXG5mdW5jdGlvbiBvYmplY3RUb1N0cmluZyhvKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobyk7XG59XG5cblxuZnVuY3Rpb24gcGFkKG4pIHtcbiAgcmV0dXJuIG4gPCAxMCA/ICcwJyArIG4udG9TdHJpbmcoMTApIDogbi50b1N0cmluZygxMCk7XG59XG5cblxudmFyIG1vbnRocyA9IFsnSmFuJywgJ0ZlYicsICdNYXInLCAnQXByJywgJ01heScsICdKdW4nLCAnSnVsJywgJ0F1ZycsICdTZXAnLFxuICAgICAgICAgICAgICAnT2N0JywgJ05vdicsICdEZWMnXTtcblxuLy8gMjYgRmViIDE2OjE5OjM0XG5mdW5jdGlvbiB0aW1lc3RhbXAoKSB7XG4gIHZhciBkID0gbmV3IERhdGUoKTtcbiAgdmFyIHRpbWUgPSBbcGFkKGQuZ2V0SG91cnMoKSksXG4gICAgICAgICAgICAgIHBhZChkLmdldE1pbnV0ZXMoKSksXG4gICAgICAgICAgICAgIHBhZChkLmdldFNlY29uZHMoKSldLmpvaW4oJzonKTtcbiAgcmV0dXJuIFtkLmdldERhdGUoKSwgbW9udGhzW2QuZ2V0TW9udGgoKV0sIHRpbWVdLmpvaW4oJyAnKTtcbn1cblxuXG4vLyBsb2cgaXMganVzdCBhIHRoaW4gd3JhcHBlciB0byBjb25zb2xlLmxvZyB0aGF0IHByZXBlbmRzIGEgdGltZXN0YW1wXG5leHBvcnRzLmxvZyA9IGZ1bmN0aW9uKCkge1xuICBjb25zb2xlLmxvZygnJXMgLSAlcycsIHRpbWVzdGFtcCgpLCBleHBvcnRzLmZvcm1hdC5hcHBseShleHBvcnRzLCBhcmd1bWVudHMpKTtcbn07XG5cblxuLyoqXG4gKiBJbmhlcml0IHRoZSBwcm90b3R5cGUgbWV0aG9kcyBmcm9tIG9uZSBjb25zdHJ1Y3RvciBpbnRvIGFub3RoZXIuXG4gKlxuICogVGhlIEZ1bmN0aW9uLnByb3RvdHlwZS5pbmhlcml0cyBmcm9tIGxhbmcuanMgcmV3cml0dGVuIGFzIGEgc3RhbmRhbG9uZVxuICogZnVuY3Rpb24gKG5vdCBvbiBGdW5jdGlvbi5wcm90b3R5cGUpLiBOT1RFOiBJZiB0aGlzIGZpbGUgaXMgdG8gYmUgbG9hZGVkXG4gKiBkdXJpbmcgYm9vdHN0cmFwcGluZyB0aGlzIGZ1bmN0aW9uIG5lZWRzIHRvIGJlIHJld3JpdHRlbiB1c2luZyBzb21lIG5hdGl2ZVxuICogZnVuY3Rpb25zIGFzIHByb3RvdHlwZSBzZXR1cCB1c2luZyBub3JtYWwgSmF2YVNjcmlwdCBkb2VzIG5vdCB3b3JrIGFzXG4gKiBleHBlY3RlZCBkdXJpbmcgYm9vdHN0cmFwcGluZyAoc2VlIG1pcnJvci5qcyBpbiByMTE0OTAzKS5cbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjdG9yIENvbnN0cnVjdG9yIGZ1bmN0aW9uIHdoaWNoIG5lZWRzIHRvIGluaGVyaXQgdGhlXG4gKiAgICAgcHJvdG90eXBlLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gc3VwZXJDdG9yIENvbnN0cnVjdG9yIGZ1bmN0aW9uIHRvIGluaGVyaXQgcHJvdG90eXBlIGZyb20uXG4gKi9cbmV4cG9ydHMuaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuXG5leHBvcnRzLl9leHRlbmQgPSBmdW5jdGlvbihvcmlnaW4sIGFkZCkge1xuICAvLyBEb24ndCBkbyBhbnl0aGluZyBpZiBhZGQgaXNuJ3QgYW4gb2JqZWN0XG4gIGlmICghYWRkIHx8ICFpc09iamVjdChhZGQpKSByZXR1cm4gb3JpZ2luO1xuXG4gIHZhciBrZXlzID0gT2JqZWN0LmtleXMoYWRkKTtcbiAgdmFyIGkgPSBrZXlzLmxlbmd0aDtcbiAgd2hpbGUgKGktLSkge1xuICAgIG9yaWdpbltrZXlzW2ldXSA9IGFkZFtrZXlzW2ldXTtcbiAgfVxuICByZXR1cm4gb3JpZ2luO1xufTtcblxuZnVuY3Rpb24gaGFzT3duUHJvcGVydHkob2JqLCBwcm9wKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKTtcbn1cbiIsIi8qIVxuXG4gZGlmZiB2Ny4wLjBcblxuQlNEIDMtQ2xhdXNlIExpY2Vuc2VcblxuQ29weXJpZ2h0IChjKSAyMDA5LTIwMTUsIEtldmluIERlY2tlciA8a3BkZWNrZXJAZ21haWwuY29tPlxuQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0XG5tb2RpZmljYXRpb24sIGFyZSBwZXJtaXR0ZWQgcHJvdmlkZWQgdGhhdCB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnMgYXJlIG1ldDpcblxuMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gICBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cblxuMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3JtIG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICAgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvblxuICAgYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG5cbjMuIE5laXRoZXIgdGhlIG5hbWUgb2YgdGhlIGNvcHlyaWdodCBob2xkZXIgbm9yIHRoZSBuYW1lcyBvZiBpdHNcbiAgIGNvbnRyaWJ1dG9ycyBtYXkgYmUgdXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMgZGVyaXZlZCBmcm9tXG4gICB0aGlzIHNvZnR3YXJlIHdpdGhvdXQgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLlxuXG5USElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIlxuQU5EIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRVxuSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXG5ESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQ09QWVJJR0hUIEhPTERFUiBPUiBDT05UUklCVVRPUlMgQkUgTElBQkxFXG5GT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwgT1IgQ09OU0VRVUVOVElBTFxuREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1JcblNFUlZJQ0VTOyBMT1NTIE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKSBIT1dFVkVSXG5DQVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLFxuT1IgVE9SVCAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0Vcbk9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG5cbkBsaWNlbnNlXG4qL1xuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG4gIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuICAoZ2xvYmFsID0gdHlwZW9mIGdsb2JhbFRoaXMgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsVGhpcyA6IGdsb2JhbCB8fCBzZWxmLCBmYWN0b3J5KGdsb2JhbC5EaWZmID0ge30pKTtcbn0pKHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbiAgZnVuY3Rpb24gRGlmZigpIHt9XG4gIERpZmYucHJvdG90eXBlID0ge1xuICAgIGRpZmY6IGZ1bmN0aW9uIGRpZmYob2xkU3RyaW5nLCBuZXdTdHJpbmcpIHtcbiAgICAgIHZhciBfb3B0aW9ucyR0aW1lb3V0O1xuICAgICAgdmFyIG9wdGlvbnMgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IHt9O1xuICAgICAgdmFyIGNhbGxiYWNrID0gb3B0aW9ucy5jYWxsYmFjaztcbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBjYWxsYmFjayA9IG9wdGlvbnM7XG4gICAgICAgIG9wdGlvbnMgPSB7fTtcbiAgICAgIH1cbiAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgIGZ1bmN0aW9uIGRvbmUodmFsdWUpIHtcbiAgICAgICAgdmFsdWUgPSBzZWxmLnBvc3RQcm9jZXNzKHZhbHVlLCBvcHRpb25zKTtcbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjYWxsYmFjayh2YWx1ZSk7XG4gICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIEFsbG93IHN1YmNsYXNzZXMgdG8gbWFzc2FnZSB0aGUgaW5wdXQgcHJpb3IgdG8gcnVubmluZ1xuICAgICAgb2xkU3RyaW5nID0gdGhpcy5jYXN0SW5wdXQob2xkU3RyaW5nLCBvcHRpb25zKTtcbiAgICAgIG5ld1N0cmluZyA9IHRoaXMuY2FzdElucHV0KG5ld1N0cmluZywgb3B0aW9ucyk7XG4gICAgICBvbGRTdHJpbmcgPSB0aGlzLnJlbW92ZUVtcHR5KHRoaXMudG9rZW5pemUob2xkU3RyaW5nLCBvcHRpb25zKSk7XG4gICAgICBuZXdTdHJpbmcgPSB0aGlzLnJlbW92ZUVtcHR5KHRoaXMudG9rZW5pemUobmV3U3RyaW5nLCBvcHRpb25zKSk7XG4gICAgICB2YXIgbmV3TGVuID0gbmV3U3RyaW5nLmxlbmd0aCxcbiAgICAgICAgb2xkTGVuID0gb2xkU3RyaW5nLmxlbmd0aDtcbiAgICAgIHZhciBlZGl0TGVuZ3RoID0gMTtcbiAgICAgIHZhciBtYXhFZGl0TGVuZ3RoID0gbmV3TGVuICsgb2xkTGVuO1xuICAgICAgaWYgKG9wdGlvbnMubWF4RWRpdExlbmd0aCAhPSBudWxsKSB7XG4gICAgICAgIG1heEVkaXRMZW5ndGggPSBNYXRoLm1pbihtYXhFZGl0TGVuZ3RoLCBvcHRpb25zLm1heEVkaXRMZW5ndGgpO1xuICAgICAgfVxuICAgICAgdmFyIG1heEV4ZWN1dGlvblRpbWUgPSAoX29wdGlvbnMkdGltZW91dCA9IG9wdGlvbnMudGltZW91dCkgIT09IG51bGwgJiYgX29wdGlvbnMkdGltZW91dCAhPT0gdm9pZCAwID8gX29wdGlvbnMkdGltZW91dCA6IEluZmluaXR5O1xuICAgICAgdmFyIGFib3J0QWZ0ZXJUaW1lc3RhbXAgPSBEYXRlLm5vdygpICsgbWF4RXhlY3V0aW9uVGltZTtcbiAgICAgIHZhciBiZXN0UGF0aCA9IFt7XG4gICAgICAgIG9sZFBvczogLTEsXG4gICAgICAgIGxhc3RDb21wb25lbnQ6IHVuZGVmaW5lZFxuICAgICAgfV07XG5cbiAgICAgIC8vIFNlZWQgZWRpdExlbmd0aCA9IDAsIGkuZS4gdGhlIGNvbnRlbnQgc3RhcnRzIHdpdGggdGhlIHNhbWUgdmFsdWVzXG4gICAgICB2YXIgbmV3UG9zID0gdGhpcy5leHRyYWN0Q29tbW9uKGJlc3RQYXRoWzBdLCBuZXdTdHJpbmcsIG9sZFN0cmluZywgMCwgb3B0aW9ucyk7XG4gICAgICBpZiAoYmVzdFBhdGhbMF0ub2xkUG9zICsgMSA+PSBvbGRMZW4gJiYgbmV3UG9zICsgMSA+PSBuZXdMZW4pIHtcbiAgICAgICAgLy8gSWRlbnRpdHkgcGVyIHRoZSBlcXVhbGl0eSBhbmQgdG9rZW5pemVyXG4gICAgICAgIHJldHVybiBkb25lKGJ1aWxkVmFsdWVzKHNlbGYsIGJlc3RQYXRoWzBdLmxhc3RDb21wb25lbnQsIG5ld1N0cmluZywgb2xkU3RyaW5nLCBzZWxmLnVzZUxvbmdlc3RUb2tlbikpO1xuICAgICAgfVxuXG4gICAgICAvLyBPbmNlIHdlIGhpdCB0aGUgcmlnaHQgZWRnZSBvZiB0aGUgZWRpdCBncmFwaCBvbiBzb21lIGRpYWdvbmFsIGssIHdlIGNhblxuICAgICAgLy8gZGVmaW5pdGVseSByZWFjaCB0aGUgZW5kIG9mIHRoZSBlZGl0IGdyYXBoIGluIG5vIG1vcmUgdGhhbiBrIGVkaXRzLCBzb1xuICAgICAgLy8gdGhlcmUncyBubyBwb2ludCBpbiBjb25zaWRlcmluZyBhbnkgbW92ZXMgdG8gZGlhZ29uYWwgaysxIGFueSBtb3JlIChmcm9tXG4gICAgICAvLyB3aGljaCB3ZSdyZSBndWFyYW50ZWVkIHRvIG5lZWQgYXQgbGVhc3QgaysxIG1vcmUgZWRpdHMpLlxuICAgICAgLy8gU2ltaWxhcmx5LCBvbmNlIHdlJ3ZlIHJlYWNoZWQgdGhlIGJvdHRvbSBvZiB0aGUgZWRpdCBncmFwaCwgdGhlcmUncyBub1xuICAgICAgLy8gcG9pbnQgY29uc2lkZXJpbmcgbW92ZXMgdG8gbG93ZXIgZGlhZ29uYWxzLlxuICAgICAgLy8gV2UgcmVjb3JkIHRoaXMgZmFjdCBieSBzZXR0aW5nIG1pbkRpYWdvbmFsVG9Db25zaWRlciBhbmRcbiAgICAgIC8vIG1heERpYWdvbmFsVG9Db25zaWRlciB0byBzb21lIGZpbml0ZSB2YWx1ZSBvbmNlIHdlJ3ZlIGhpdCB0aGUgZWRnZSBvZlxuICAgICAgLy8gdGhlIGVkaXQgZ3JhcGguXG4gICAgICAvLyBUaGlzIG9wdGltaXphdGlvbiBpcyBub3QgZmFpdGhmdWwgdG8gdGhlIG9yaWdpbmFsIGFsZ29yaXRobSBwcmVzZW50ZWQgaW5cbiAgICAgIC8vIE15ZXJzJ3MgcGFwZXIsIHdoaWNoIGluc3RlYWQgcG9pbnRsZXNzbHkgZXh0ZW5kcyBELXBhdGhzIG9mZiB0aGUgZW5kIG9mXG4gICAgICAvLyB0aGUgZWRpdCBncmFwaCAtIHNlZSBwYWdlIDcgb2YgTXllcnMncyBwYXBlciB3aGljaCBub3RlcyB0aGlzIHBvaW50XG4gICAgICAvLyBleHBsaWNpdGx5IGFuZCBpbGx1c3RyYXRlcyBpdCB3aXRoIGEgZGlhZ3JhbS4gVGhpcyBoYXMgbWFqb3IgcGVyZm9ybWFuY2VcbiAgICAgIC8vIGltcGxpY2F0aW9ucyBmb3Igc29tZSBjb21tb24gc2NlbmFyaW9zLiBGb3IgaW5zdGFuY2UsIHRvIGNvbXB1dGUgYSBkaWZmXG4gICAgICAvLyB3aGVyZSB0aGUgbmV3IHRleHQgc2ltcGx5IGFwcGVuZHMgZCBjaGFyYWN0ZXJzIG9uIHRoZSBlbmQgb2YgdGhlXG4gICAgICAvLyBvcmlnaW5hbCB0ZXh0IG9mIGxlbmd0aCBuLCB0aGUgdHJ1ZSBNeWVycyBhbGdvcml0aG0gd2lsbCB0YWtlIE8obitkXjIpXG4gICAgICAvLyB0aW1lIHdoaWxlIHRoaXMgb3B0aW1pemF0aW9uIG5lZWRzIG9ubHkgTyhuK2QpIHRpbWUuXG4gICAgICB2YXIgbWluRGlhZ29uYWxUb0NvbnNpZGVyID0gLUluZmluaXR5LFxuICAgICAgICBtYXhEaWFnb25hbFRvQ29uc2lkZXIgPSBJbmZpbml0eTtcblxuICAgICAgLy8gTWFpbiB3b3JrZXIgbWV0aG9kLiBjaGVja3MgYWxsIHBlcm11dGF0aW9ucyBvZiBhIGdpdmVuIGVkaXQgbGVuZ3RoIGZvciBhY2NlcHRhbmNlLlxuICAgICAgZnVuY3Rpb24gZXhlY0VkaXRMZW5ndGgoKSB7XG4gICAgICAgIGZvciAodmFyIGRpYWdvbmFsUGF0aCA9IE1hdGgubWF4KG1pbkRpYWdvbmFsVG9Db25zaWRlciwgLWVkaXRMZW5ndGgpOyBkaWFnb25hbFBhdGggPD0gTWF0aC5taW4obWF4RGlhZ29uYWxUb0NvbnNpZGVyLCBlZGl0TGVuZ3RoKTsgZGlhZ29uYWxQYXRoICs9IDIpIHtcbiAgICAgICAgICB2YXIgYmFzZVBhdGggPSB2b2lkIDA7XG4gICAgICAgICAgdmFyIHJlbW92ZVBhdGggPSBiZXN0UGF0aFtkaWFnb25hbFBhdGggLSAxXSxcbiAgICAgICAgICAgIGFkZFBhdGggPSBiZXN0UGF0aFtkaWFnb25hbFBhdGggKyAxXTtcbiAgICAgICAgICBpZiAocmVtb3ZlUGF0aCkge1xuICAgICAgICAgICAgLy8gTm8gb25lIGVsc2UgaXMgZ29pbmcgdG8gYXR0ZW1wdCB0byB1c2UgdGhpcyB2YWx1ZSwgY2xlYXIgaXRcbiAgICAgICAgICAgIGJlc3RQYXRoW2RpYWdvbmFsUGF0aCAtIDFdID0gdW5kZWZpbmVkO1xuICAgICAgICAgIH1cbiAgICAgICAgICB2YXIgY2FuQWRkID0gZmFsc2U7XG4gICAgICAgICAgaWYgKGFkZFBhdGgpIHtcbiAgICAgICAgICAgIC8vIHdoYXQgbmV3UG9zIHdpbGwgYmUgYWZ0ZXIgd2UgZG8gYW4gaW5zZXJ0aW9uOlxuICAgICAgICAgICAgdmFyIGFkZFBhdGhOZXdQb3MgPSBhZGRQYXRoLm9sZFBvcyAtIGRpYWdvbmFsUGF0aDtcbiAgICAgICAgICAgIGNhbkFkZCA9IGFkZFBhdGggJiYgMCA8PSBhZGRQYXRoTmV3UG9zICYmIGFkZFBhdGhOZXdQb3MgPCBuZXdMZW47XG4gICAgICAgICAgfVxuICAgICAgICAgIHZhciBjYW5SZW1vdmUgPSByZW1vdmVQYXRoICYmIHJlbW92ZVBhdGgub2xkUG9zICsgMSA8IG9sZExlbjtcbiAgICAgICAgICBpZiAoIWNhbkFkZCAmJiAhY2FuUmVtb3ZlKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGlzIHBhdGggaXMgYSB0ZXJtaW5hbCB0aGVuIHBydW5lXG4gICAgICAgICAgICBiZXN0UGF0aFtkaWFnb25hbFBhdGhdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gU2VsZWN0IHRoZSBkaWFnb25hbCB0aGF0IHdlIHdhbnQgdG8gYnJhbmNoIGZyb20uIFdlIHNlbGVjdCB0aGUgcHJpb3JcbiAgICAgICAgICAvLyBwYXRoIHdob3NlIHBvc2l0aW9uIGluIHRoZSBvbGQgc3RyaW5nIGlzIHRoZSBmYXJ0aGVzdCBmcm9tIHRoZSBvcmlnaW5cbiAgICAgICAgICAvLyBhbmQgZG9lcyBub3QgcGFzcyB0aGUgYm91bmRzIG9mIHRoZSBkaWZmIGdyYXBoXG4gICAgICAgICAgaWYgKCFjYW5SZW1vdmUgfHwgY2FuQWRkICYmIHJlbW92ZVBhdGgub2xkUG9zIDwgYWRkUGF0aC5vbGRQb3MpIHtcbiAgICAgICAgICAgIGJhc2VQYXRoID0gc2VsZi5hZGRUb1BhdGgoYWRkUGF0aCwgdHJ1ZSwgZmFsc2UsIDAsIG9wdGlvbnMpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBiYXNlUGF0aCA9IHNlbGYuYWRkVG9QYXRoKHJlbW92ZVBhdGgsIGZhbHNlLCB0cnVlLCAxLCBvcHRpb25zKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgbmV3UG9zID0gc2VsZi5leHRyYWN0Q29tbW9uKGJhc2VQYXRoLCBuZXdTdHJpbmcsIG9sZFN0cmluZywgZGlhZ29uYWxQYXRoLCBvcHRpb25zKTtcbiAgICAgICAgICBpZiAoYmFzZVBhdGgub2xkUG9zICsgMSA+PSBvbGRMZW4gJiYgbmV3UG9zICsgMSA+PSBuZXdMZW4pIHtcbiAgICAgICAgICAgIC8vIElmIHdlIGhhdmUgaGl0IHRoZSBlbmQgb2YgYm90aCBzdHJpbmdzLCB0aGVuIHdlIGFyZSBkb25lXG4gICAgICAgICAgICByZXR1cm4gZG9uZShidWlsZFZhbHVlcyhzZWxmLCBiYXNlUGF0aC5sYXN0Q29tcG9uZW50LCBuZXdTdHJpbmcsIG9sZFN0cmluZywgc2VsZi51c2VMb25nZXN0VG9rZW4pKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYmVzdFBhdGhbZGlhZ29uYWxQYXRoXSA9IGJhc2VQYXRoO1xuICAgICAgICAgICAgaWYgKGJhc2VQYXRoLm9sZFBvcyArIDEgPj0gb2xkTGVuKSB7XG4gICAgICAgICAgICAgIG1heERpYWdvbmFsVG9Db25zaWRlciA9IE1hdGgubWluKG1heERpYWdvbmFsVG9Db25zaWRlciwgZGlhZ29uYWxQYXRoIC0gMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobmV3UG9zICsgMSA+PSBuZXdMZW4pIHtcbiAgICAgICAgICAgICAgbWluRGlhZ29uYWxUb0NvbnNpZGVyID0gTWF0aC5tYXgobWluRGlhZ29uYWxUb0NvbnNpZGVyLCBkaWFnb25hbFBhdGggKyAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWRpdExlbmd0aCsrO1xuICAgICAgfVxuXG4gICAgICAvLyBQZXJmb3JtcyB0aGUgbGVuZ3RoIG9mIGVkaXQgaXRlcmF0aW9uLiBJcyBhIGJpdCBmdWdseSBhcyB0aGlzIGhhcyB0byBzdXBwb3J0IHRoZVxuICAgICAgLy8gc3luYyBhbmQgYXN5bmMgbW9kZSB3aGljaCBpcyBuZXZlciBmdW4uIExvb3BzIG92ZXIgZXhlY0VkaXRMZW5ndGggdW50aWwgYSB2YWx1ZVxuICAgICAgLy8gaXMgcHJvZHVjZWQsIG9yIHVudGlsIHRoZSBlZGl0IGxlbmd0aCBleGNlZWRzIG9wdGlvbnMubWF4RWRpdExlbmd0aCAoaWYgZ2l2ZW4pLFxuICAgICAgLy8gaW4gd2hpY2ggY2FzZSBpdCB3aWxsIHJldHVybiB1bmRlZmluZWQuXG4gICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgKGZ1bmN0aW9uIGV4ZWMoKSB7XG4gICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoZWRpdExlbmd0aCA+IG1heEVkaXRMZW5ndGggfHwgRGF0ZS5ub3coKSA+IGFib3J0QWZ0ZXJUaW1lc3RhbXApIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWV4ZWNFZGl0TGVuZ3RoKCkpIHtcbiAgICAgICAgICAgICAgZXhlYygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sIDApO1xuICAgICAgICB9KSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgd2hpbGUgKGVkaXRMZW5ndGggPD0gbWF4RWRpdExlbmd0aCAmJiBEYXRlLm5vdygpIDw9IGFib3J0QWZ0ZXJUaW1lc3RhbXApIHtcbiAgICAgICAgICB2YXIgcmV0ID0gZXhlY0VkaXRMZW5ndGgoKTtcbiAgICAgICAgICBpZiAocmV0KSB7XG4gICAgICAgICAgICByZXR1cm4gcmV0O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sXG4gICAgYWRkVG9QYXRoOiBmdW5jdGlvbiBhZGRUb1BhdGgocGF0aCwgYWRkZWQsIHJlbW92ZWQsIG9sZFBvc0luYywgb3B0aW9ucykge1xuICAgICAgdmFyIGxhc3QgPSBwYXRoLmxhc3RDb21wb25lbnQ7XG4gICAgICBpZiAobGFzdCAmJiAhb3B0aW9ucy5vbmVDaGFuZ2VQZXJUb2tlbiAmJiBsYXN0LmFkZGVkID09PSBhZGRlZCAmJiBsYXN0LnJlbW92ZWQgPT09IHJlbW92ZWQpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBvbGRQb3M6IHBhdGgub2xkUG9zICsgb2xkUG9zSW5jLFxuICAgICAgICAgIGxhc3RDb21wb25lbnQ6IHtcbiAgICAgICAgICAgIGNvdW50OiBsYXN0LmNvdW50ICsgMSxcbiAgICAgICAgICAgIGFkZGVkOiBhZGRlZCxcbiAgICAgICAgICAgIHJlbW92ZWQ6IHJlbW92ZWQsXG4gICAgICAgICAgICBwcmV2aW91c0NvbXBvbmVudDogbGFzdC5wcmV2aW91c0NvbXBvbmVudFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgb2xkUG9zOiBwYXRoLm9sZFBvcyArIG9sZFBvc0luYyxcbiAgICAgICAgICBsYXN0Q29tcG9uZW50OiB7XG4gICAgICAgICAgICBjb3VudDogMSxcbiAgICAgICAgICAgIGFkZGVkOiBhZGRlZCxcbiAgICAgICAgICAgIHJlbW92ZWQ6IHJlbW92ZWQsXG4gICAgICAgICAgICBwcmV2aW91c0NvbXBvbmVudDogbGFzdFxuICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGV4dHJhY3RDb21tb246IGZ1bmN0aW9uIGV4dHJhY3RDb21tb24oYmFzZVBhdGgsIG5ld1N0cmluZywgb2xkU3RyaW5nLCBkaWFnb25hbFBhdGgsIG9wdGlvbnMpIHtcbiAgICAgIHZhciBuZXdMZW4gPSBuZXdTdHJpbmcubGVuZ3RoLFxuICAgICAgICBvbGRMZW4gPSBvbGRTdHJpbmcubGVuZ3RoLFxuICAgICAgICBvbGRQb3MgPSBiYXNlUGF0aC5vbGRQb3MsXG4gICAgICAgIG5ld1BvcyA9IG9sZFBvcyAtIGRpYWdvbmFsUGF0aCxcbiAgICAgICAgY29tbW9uQ291bnQgPSAwO1xuICAgICAgd2hpbGUgKG5ld1BvcyArIDEgPCBuZXdMZW4gJiYgb2xkUG9zICsgMSA8IG9sZExlbiAmJiB0aGlzLmVxdWFscyhvbGRTdHJpbmdbb2xkUG9zICsgMV0sIG5ld1N0cmluZ1tuZXdQb3MgKyAxXSwgb3B0aW9ucykpIHtcbiAgICAgICAgbmV3UG9zKys7XG4gICAgICAgIG9sZFBvcysrO1xuICAgICAgICBjb21tb25Db3VudCsrO1xuICAgICAgICBpZiAob3B0aW9ucy5vbmVDaGFuZ2VQZXJUb2tlbikge1xuICAgICAgICAgIGJhc2VQYXRoLmxhc3RDb21wb25lbnQgPSB7XG4gICAgICAgICAgICBjb3VudDogMSxcbiAgICAgICAgICAgIHByZXZpb3VzQ29tcG9uZW50OiBiYXNlUGF0aC5sYXN0Q29tcG9uZW50LFxuICAgICAgICAgICAgYWRkZWQ6IGZhbHNlLFxuICAgICAgICAgICAgcmVtb3ZlZDogZmFsc2VcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoY29tbW9uQ291bnQgJiYgIW9wdGlvbnMub25lQ2hhbmdlUGVyVG9rZW4pIHtcbiAgICAgICAgYmFzZVBhdGgubGFzdENvbXBvbmVudCA9IHtcbiAgICAgICAgICBjb3VudDogY29tbW9uQ291bnQsXG4gICAgICAgICAgcHJldmlvdXNDb21wb25lbnQ6IGJhc2VQYXRoLmxhc3RDb21wb25lbnQsXG4gICAgICAgICAgYWRkZWQ6IGZhbHNlLFxuICAgICAgICAgIHJlbW92ZWQ6IGZhbHNlXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBiYXNlUGF0aC5vbGRQb3MgPSBvbGRQb3M7XG4gICAgICByZXR1cm4gbmV3UG9zO1xuICAgIH0sXG4gICAgZXF1YWxzOiBmdW5jdGlvbiBlcXVhbHMobGVmdCwgcmlnaHQsIG9wdGlvbnMpIHtcbiAgICAgIGlmIChvcHRpb25zLmNvbXBhcmF0b3IpIHtcbiAgICAgICAgcmV0dXJuIG9wdGlvbnMuY29tcGFyYXRvcihsZWZ0LCByaWdodCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbGVmdCA9PT0gcmlnaHQgfHwgb3B0aW9ucy5pZ25vcmVDYXNlICYmIGxlZnQudG9Mb3dlckNhc2UoKSA9PT0gcmlnaHQudG9Mb3dlckNhc2UoKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIHJlbW92ZUVtcHR5OiBmdW5jdGlvbiByZW1vdmVFbXB0eShhcnJheSkge1xuICAgICAgdmFyIHJldCA9IFtdO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoYXJyYXlbaV0pIHtcbiAgICAgICAgICByZXQucHVzaChhcnJheVtpXSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiByZXQ7XG4gICAgfSxcbiAgICBjYXN0SW5wdXQ6IGZ1bmN0aW9uIGNhc3RJbnB1dCh2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH0sXG4gICAgdG9rZW5pemU6IGZ1bmN0aW9uIHRva2VuaXplKHZhbHVlKSB7XG4gICAgICByZXR1cm4gQXJyYXkuZnJvbSh2YWx1ZSk7XG4gICAgfSxcbiAgICBqb2luOiBmdW5jdGlvbiBqb2luKGNoYXJzKSB7XG4gICAgICByZXR1cm4gY2hhcnMuam9pbignJyk7XG4gICAgfSxcbiAgICBwb3N0UHJvY2VzczogZnVuY3Rpb24gcG9zdFByb2Nlc3MoY2hhbmdlT2JqZWN0cykge1xuICAgICAgcmV0dXJuIGNoYW5nZU9iamVjdHM7XG4gICAgfVxuICB9O1xuICBmdW5jdGlvbiBidWlsZFZhbHVlcyhkaWZmLCBsYXN0Q29tcG9uZW50LCBuZXdTdHJpbmcsIG9sZFN0cmluZywgdXNlTG9uZ2VzdFRva2VuKSB7XG4gICAgLy8gRmlyc3Qgd2UgY29udmVydCBvdXIgbGlua2VkIGxpc3Qgb2YgY29tcG9uZW50cyBpbiByZXZlcnNlIG9yZGVyIHRvIGFuXG4gICAgLy8gYXJyYXkgaW4gdGhlIHJpZ2h0IG9yZGVyOlxuICAgIHZhciBjb21wb25lbnRzID0gW107XG4gICAgdmFyIG5leHRDb21wb25lbnQ7XG4gICAgd2hpbGUgKGxhc3RDb21wb25lbnQpIHtcbiAgICAgIGNvbXBvbmVudHMucHVzaChsYXN0Q29tcG9uZW50KTtcbiAgICAgIG5leHRDb21wb25lbnQgPSBsYXN0Q29tcG9uZW50LnByZXZpb3VzQ29tcG9uZW50O1xuICAgICAgZGVsZXRlIGxhc3RDb21wb25lbnQucHJldmlvdXNDb21wb25lbnQ7XG4gICAgICBsYXN0Q29tcG9uZW50ID0gbmV4dENvbXBvbmVudDtcbiAgICB9XG4gICAgY29tcG9uZW50cy5yZXZlcnNlKCk7XG4gICAgdmFyIGNvbXBvbmVudFBvcyA9IDAsXG4gICAgICBjb21wb25lbnRMZW4gPSBjb21wb25lbnRzLmxlbmd0aCxcbiAgICAgIG5ld1BvcyA9IDAsXG4gICAgICBvbGRQb3MgPSAwO1xuICAgIGZvciAoOyBjb21wb25lbnRQb3MgPCBjb21wb25lbnRMZW47IGNvbXBvbmVudFBvcysrKSB7XG4gICAgICB2YXIgY29tcG9uZW50ID0gY29tcG9uZW50c1tjb21wb25lbnRQb3NdO1xuICAgICAgaWYgKCFjb21wb25lbnQucmVtb3ZlZCkge1xuICAgICAgICBpZiAoIWNvbXBvbmVudC5hZGRlZCAmJiB1c2VMb25nZXN0VG9rZW4pIHtcbiAgICAgICAgICB2YXIgdmFsdWUgPSBuZXdTdHJpbmcuc2xpY2UobmV3UG9zLCBuZXdQb3MgKyBjb21wb25lbnQuY291bnQpO1xuICAgICAgICAgIHZhbHVlID0gdmFsdWUubWFwKGZ1bmN0aW9uICh2YWx1ZSwgaSkge1xuICAgICAgICAgICAgdmFyIG9sZFZhbHVlID0gb2xkU3RyaW5nW29sZFBvcyArIGldO1xuICAgICAgICAgICAgcmV0dXJuIG9sZFZhbHVlLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCA/IG9sZFZhbHVlIDogdmFsdWU7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgY29tcG9uZW50LnZhbHVlID0gZGlmZi5qb2luKHZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb21wb25lbnQudmFsdWUgPSBkaWZmLmpvaW4obmV3U3RyaW5nLnNsaWNlKG5ld1BvcywgbmV3UG9zICsgY29tcG9uZW50LmNvdW50KSk7XG4gICAgICAgIH1cbiAgICAgICAgbmV3UG9zICs9IGNvbXBvbmVudC5jb3VudDtcblxuICAgICAgICAvLyBDb21tb24gY2FzZVxuICAgICAgICBpZiAoIWNvbXBvbmVudC5hZGRlZCkge1xuICAgICAgICAgIG9sZFBvcyArPSBjb21wb25lbnQuY291bnQ7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbXBvbmVudC52YWx1ZSA9IGRpZmYuam9pbihvbGRTdHJpbmcuc2xpY2Uob2xkUG9zLCBvbGRQb3MgKyBjb21wb25lbnQuY291bnQpKTtcbiAgICAgICAgb2xkUG9zICs9IGNvbXBvbmVudC5jb3VudDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGNvbXBvbmVudHM7XG4gIH1cblxuICB2YXIgY2hhcmFjdGVyRGlmZiA9IG5ldyBEaWZmKCk7XG4gIGZ1bmN0aW9uIGRpZmZDaGFycyhvbGRTdHIsIG5ld1N0ciwgb3B0aW9ucykge1xuICAgIHJldHVybiBjaGFyYWN0ZXJEaWZmLmRpZmYob2xkU3RyLCBuZXdTdHIsIG9wdGlvbnMpO1xuICB9XG5cbiAgZnVuY3Rpb24gbG9uZ2VzdENvbW1vblByZWZpeChzdHIxLCBzdHIyKSB7XG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHN0cjEubGVuZ3RoICYmIGkgPCBzdHIyLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoc3RyMVtpXSAhPSBzdHIyW2ldKSB7XG4gICAgICAgIHJldHVybiBzdHIxLnNsaWNlKDAsIGkpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc3RyMS5zbGljZSgwLCBpKTtcbiAgfVxuICBmdW5jdGlvbiBsb25nZXN0Q29tbW9uU3VmZml4KHN0cjEsIHN0cjIpIHtcbiAgICB2YXIgaTtcblxuICAgIC8vIFVubGlrZSBsb25nZXN0Q29tbW9uUHJlZml4LCB3ZSBuZWVkIGEgc3BlY2lhbCBjYXNlIHRvIGhhbmRsZSBhbGwgc2NlbmFyaW9zXG4gICAgLy8gd2hlcmUgd2UgcmV0dXJuIHRoZSBlbXB0eSBzdHJpbmcgc2luY2Ugc3RyMS5zbGljZSgtMCkgd2lsbCByZXR1cm4gdGhlXG4gICAgLy8gZW50aXJlIHN0cmluZy5cbiAgICBpZiAoIXN0cjEgfHwgIXN0cjIgfHwgc3RyMVtzdHIxLmxlbmd0aCAtIDFdICE9IHN0cjJbc3RyMi5sZW5ndGggLSAxXSkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgc3RyMS5sZW5ndGggJiYgaSA8IHN0cjIubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChzdHIxW3N0cjEubGVuZ3RoIC0gKGkgKyAxKV0gIT0gc3RyMltzdHIyLmxlbmd0aCAtIChpICsgMSldKSB7XG4gICAgICAgIHJldHVybiBzdHIxLnNsaWNlKC1pKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHN0cjEuc2xpY2UoLWkpO1xuICB9XG4gIGZ1bmN0aW9uIHJlcGxhY2VQcmVmaXgoc3RyaW5nLCBvbGRQcmVmaXgsIG5ld1ByZWZpeCkge1xuICAgIGlmIChzdHJpbmcuc2xpY2UoMCwgb2xkUHJlZml4Lmxlbmd0aCkgIT0gb2xkUHJlZml4KSB7XG4gICAgICB0aHJvdyBFcnJvcihcInN0cmluZyBcIi5jb25jYXQoSlNPTi5zdHJpbmdpZnkoc3RyaW5nKSwgXCIgZG9lc24ndCBzdGFydCB3aXRoIHByZWZpeCBcIikuY29uY2F0KEpTT04uc3RyaW5naWZ5KG9sZFByZWZpeCksIFwiOyB0aGlzIGlzIGEgYnVnXCIpKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ld1ByZWZpeCArIHN0cmluZy5zbGljZShvbGRQcmVmaXgubGVuZ3RoKTtcbiAgfVxuICBmdW5jdGlvbiByZXBsYWNlU3VmZml4KHN0cmluZywgb2xkU3VmZml4LCBuZXdTdWZmaXgpIHtcbiAgICBpZiAoIW9sZFN1ZmZpeCkge1xuICAgICAgcmV0dXJuIHN0cmluZyArIG5ld1N1ZmZpeDtcbiAgICB9XG4gICAgaWYgKHN0cmluZy5zbGljZSgtb2xkU3VmZml4Lmxlbmd0aCkgIT0gb2xkU3VmZml4KSB7XG4gICAgICB0aHJvdyBFcnJvcihcInN0cmluZyBcIi5jb25jYXQoSlNPTi5zdHJpbmdpZnkoc3RyaW5nKSwgXCIgZG9lc24ndCBlbmQgd2l0aCBzdWZmaXggXCIpLmNvbmNhdChKU09OLnN0cmluZ2lmeShvbGRTdWZmaXgpLCBcIjsgdGhpcyBpcyBhIGJ1Z1wiKSk7XG4gICAgfVxuICAgIHJldHVybiBzdHJpbmcuc2xpY2UoMCwgLW9sZFN1ZmZpeC5sZW5ndGgpICsgbmV3U3VmZml4O1xuICB9XG4gIGZ1bmN0aW9uIHJlbW92ZVByZWZpeChzdHJpbmcsIG9sZFByZWZpeCkge1xuICAgIHJldHVybiByZXBsYWNlUHJlZml4KHN0cmluZywgb2xkUHJlZml4LCAnJyk7XG4gIH1cbiAgZnVuY3Rpb24gcmVtb3ZlU3VmZml4KHN0cmluZywgb2xkU3VmZml4KSB7XG4gICAgcmV0dXJuIHJlcGxhY2VTdWZmaXgoc3RyaW5nLCBvbGRTdWZmaXgsICcnKTtcbiAgfVxuICBmdW5jdGlvbiBtYXhpbXVtT3ZlcmxhcChzdHJpbmcxLCBzdHJpbmcyKSB7XG4gICAgcmV0dXJuIHN0cmluZzIuc2xpY2UoMCwgb3ZlcmxhcENvdW50KHN0cmluZzEsIHN0cmluZzIpKTtcbiAgfVxuXG4gIC8vIE5pY2tlZCBmcm9tIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS82MDQyMjg1My8xNzA5NTg3XG4gIGZ1bmN0aW9uIG92ZXJsYXBDb3VudChhLCBiKSB7XG4gICAgLy8gRGVhbCB3aXRoIGNhc2VzIHdoZXJlIHRoZSBzdHJpbmdzIGRpZmZlciBpbiBsZW5ndGhcbiAgICB2YXIgc3RhcnRBID0gMDtcbiAgICBpZiAoYS5sZW5ndGggPiBiLmxlbmd0aCkge1xuICAgICAgc3RhcnRBID0gYS5sZW5ndGggLSBiLmxlbmd0aDtcbiAgICB9XG4gICAgdmFyIGVuZEIgPSBiLmxlbmd0aDtcbiAgICBpZiAoYS5sZW5ndGggPCBiLmxlbmd0aCkge1xuICAgICAgZW5kQiA9IGEubGVuZ3RoO1xuICAgIH1cbiAgICAvLyBDcmVhdGUgYSBiYWNrLXJlZmVyZW5jZSBmb3IgZWFjaCBpbmRleFxuICAgIC8vICAgdGhhdCBzaG91bGQgYmUgZm9sbG93ZWQgaW4gY2FzZSBvZiBhIG1pc21hdGNoLlxuICAgIC8vICAgV2Ugb25seSBuZWVkIEIgdG8gbWFrZSB0aGVzZSByZWZlcmVuY2VzOlxuICAgIHZhciBtYXAgPSBBcnJheShlbmRCKTtcbiAgICB2YXIgayA9IDA7IC8vIEluZGV4IHRoYXQgbGFncyBiZWhpbmQgalxuICAgIG1hcFswXSA9IDA7XG4gICAgZm9yICh2YXIgaiA9IDE7IGogPCBlbmRCOyBqKyspIHtcbiAgICAgIGlmIChiW2pdID09IGJba10pIHtcbiAgICAgICAgbWFwW2pdID0gbWFwW2tdOyAvLyBza2lwIG92ZXIgdGhlIHNhbWUgY2hhcmFjdGVyIChvcHRpb25hbCBvcHRpbWlzYXRpb24pXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtYXBbal0gPSBrO1xuICAgICAgfVxuICAgICAgd2hpbGUgKGsgPiAwICYmIGJbal0gIT0gYltrXSkge1xuICAgICAgICBrID0gbWFwW2tdO1xuICAgICAgfVxuICAgICAgaWYgKGJbal0gPT0gYltrXSkge1xuICAgICAgICBrKys7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFBoYXNlIDI6IHVzZSB0aGVzZSByZWZlcmVuY2VzIHdoaWxlIGl0ZXJhdGluZyBvdmVyIEFcbiAgICBrID0gMDtcbiAgICBmb3IgKHZhciBpID0gc3RhcnRBOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgd2hpbGUgKGsgPiAwICYmIGFbaV0gIT0gYltrXSkge1xuICAgICAgICBrID0gbWFwW2tdO1xuICAgICAgfVxuICAgICAgaWYgKGFbaV0gPT0gYltrXSkge1xuICAgICAgICBrKys7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBrO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgc3RyaW5nIGNvbnNpc3RlbnRseSB1c2VzIFdpbmRvd3MgbGluZSBlbmRpbmdzLlxuICAgKi9cbiAgZnVuY3Rpb24gaGFzT25seVdpbkxpbmVFbmRpbmdzKHN0cmluZykge1xuICAgIHJldHVybiBzdHJpbmcuaW5jbHVkZXMoJ1xcclxcbicpICYmICFzdHJpbmcuc3RhcnRzV2l0aCgnXFxuJykgJiYgIXN0cmluZy5tYXRjaCgvW15cXHJdXFxuLyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0cnVlIGlmIHRoZSBzdHJpbmcgY29uc2lzdGVudGx5IHVzZXMgVW5peCBsaW5lIGVuZGluZ3MuXG4gICAqL1xuICBmdW5jdGlvbiBoYXNPbmx5VW5peExpbmVFbmRpbmdzKHN0cmluZykge1xuICAgIHJldHVybiAhc3RyaW5nLmluY2x1ZGVzKCdcXHJcXG4nKSAmJiBzdHJpbmcuaW5jbHVkZXMoJ1xcbicpO1xuICB9XG5cbiAgLy8gQmFzZWQgb24gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTGF0aW5fc2NyaXB0X2luX1VuaWNvZGVcbiAgLy9cbiAgLy8gUmFuZ2VzIGFuZCBleGNlcHRpb25zOlxuICAvLyBMYXRpbi0xIFN1cHBsZW1lbnQsIDAwODDigJMwMEZGXG4gIC8vICAtIFUrMDBENyAgw5cgTXVsdGlwbGljYXRpb24gc2lnblxuICAvLyAgLSBVKzAwRjcgIMO3IERpdmlzaW9uIHNpZ25cbiAgLy8gTGF0aW4gRXh0ZW5kZWQtQSwgMDEwMOKAkzAxN0ZcbiAgLy8gTGF0aW4gRXh0ZW5kZWQtQiwgMDE4MOKAkzAyNEZcbiAgLy8gSVBBIEV4dGVuc2lvbnMsIDAyNTDigJMwMkFGXG4gIC8vIFNwYWNpbmcgTW9kaWZpZXIgTGV0dGVycywgMDJCMOKAkzAyRkZcbiAgLy8gIC0gVSswMkM3ICDLhyAmIzcxMTsgIENhcm9uXG4gIC8vICAtIFUrMDJEOCAgy5ggJiM3Mjg7ICBCcmV2ZVxuICAvLyAgLSBVKzAyRDkgIMuZICYjNzI5OyAgRG90IEFib3ZlXG4gIC8vICAtIFUrMDJEQSAgy5ogJiM3MzA7ICBSaW5nIEFib3ZlXG4gIC8vICAtIFUrMDJEQiAgy5sgJiM3MzE7ICBPZ29uZWtcbiAgLy8gIC0gVSswMkRDICDLnCAmIzczMjsgIFNtYWxsIFRpbGRlXG4gIC8vICAtIFUrMDJERCAgy50gJiM3MzM7ICBEb3VibGUgQWN1dGUgQWNjZW50XG4gIC8vIExhdGluIEV4dGVuZGVkIEFkZGl0aW9uYWwsIDFFMDDigJMxRUZGXG4gIHZhciBleHRlbmRlZFdvcmRDaGFycyA9IFwiYS16QS1aMC05X1xcXFx1e0MwfS1cXFxcdXtGRn1cXFxcdXtEOH0tXFxcXHV7RjZ9XFxcXHV7Rjh9LVxcXFx1ezJDNn1cXFxcdXsyQzh9LVxcXFx1ezJEN31cXFxcdXsyREV9LVxcXFx1ezJGRn1cXFxcdXsxRTAwfS1cXFxcdXsxRUZGfVwiO1xuXG4gIC8vIEVhY2ggdG9rZW4gaXMgb25lIG9mIHRoZSBmb2xsb3dpbmc6XG4gIC8vIC0gQSBwdW5jdHVhdGlvbiBtYXJrIHBsdXMgdGhlIHN1cnJvdW5kaW5nIHdoaXRlc3BhY2VcbiAgLy8gLSBBIHdvcmQgcGx1cyB0aGUgc3Vycm91bmRpbmcgd2hpdGVzcGFjZVxuICAvLyAtIFB1cmUgd2hpdGVzcGFjZSAoYnV0IG9ubHkgaW4gdGhlIHNwZWNpYWwgY2FzZSB3aGVyZSB0aGlzIHRoZSBlbnRpcmUgdGV4dFxuICAvLyAgIGlzIGp1c3Qgd2hpdGVzcGFjZSlcbiAgLy9cbiAgLy8gV2UgaGF2ZSB0byBpbmNsdWRlIHN1cnJvdW5kaW5nIHdoaXRlc3BhY2UgaW4gdGhlIHRva2VucyBiZWNhdXNlIHRoZSB0d29cbiAgLy8gYWx0ZXJuYXRpdmUgYXBwcm9hY2hlcyBwcm9kdWNlIGhvcnJpYmx5IGJyb2tlbiByZXN1bHRzOlxuICAvLyAqIElmIHdlIGp1c3QgZGlzY2FyZCB0aGUgd2hpdGVzcGFjZSwgd2UgY2FuJ3QgZnVsbHkgcmVwcm9kdWNlIHRoZSBvcmlnaW5hbFxuICAvLyAgIHRleHQgZnJvbSB0aGUgc2VxdWVuY2Ugb2YgdG9rZW5zIGFuZCBhbnkgYXR0ZW1wdCB0byByZW5kZXIgdGhlIGRpZmYgd2lsbFxuICAvLyAgIGdldCB0aGUgd2hpdGVzcGFjZSB3cm9uZy5cbiAgLy8gKiBJZiB3ZSBoYXZlIHNlcGFyYXRlIHRva2VucyBmb3Igd2hpdGVzcGFjZSwgdGhlbiBpbiBhIHR5cGljYWwgdGV4dCBldmVyeVxuICAvLyAgIHNlY29uZCB0b2tlbiB3aWxsIGJlIGEgc2luZ2xlIHNwYWNlIGNoYXJhY3Rlci4gQnV0IHRoaXMgb2Z0ZW4gcmVzdWx0cyBpblxuICAvLyAgIHRoZSBvcHRpbWFsIGRpZmYgYmV0d2VlbiB0d28gdGV4dHMgYmVpbmcgYSBwZXJ2ZXJzZSBvbmUgdGhhdCBwcmVzZXJ2ZXNcbiAgLy8gICB0aGUgc3BhY2VzIGJldHdlZW4gd29yZHMgYnV0IGRlbGV0ZXMgYW5kIHJlaW5zZXJ0cyBhY3R1YWwgY29tbW9uIHdvcmRzLlxuICAvLyAgIFNlZSBodHRwczovL2dpdGh1Yi5jb20va3BkZWNrZXIvanNkaWZmL2lzc3Vlcy8xNjAjaXNzdWVjb21tZW50LTE4NjYwOTk2NDBcbiAgLy8gICBmb3IgYW4gZXhhbXBsZS5cbiAgLy9cbiAgLy8gS2VlcGluZyB0aGUgc3Vycm91bmRpbmcgd2hpdGVzcGFjZSBvZiBjb3Vyc2UgaGFzIGltcGxpY2F0aW9ucyBmb3IgLmVxdWFsc1xuICAvLyBhbmQgLmpvaW4sIG5vdCBqdXN0IC50b2tlbml6ZS5cblxuICAvLyBUaGlzIHJlZ2V4IGRvZXMgTk9UIGZ1bGx5IGltcGxlbWVudCB0aGUgdG9rZW5pemF0aW9uIHJ1bGVzIGRlc2NyaWJlZCBhYm92ZS5cbiAgLy8gSW5zdGVhZCwgaXQgZ2l2ZXMgcnVucyBvZiB3aGl0ZXNwYWNlIHRoZWlyIG93biBcInRva2VuXCIuIFRoZSB0b2tlbml6ZSBtZXRob2RcbiAgLy8gdGhlbiBoYW5kbGVzIHN0aXRjaGluZyB3aGl0ZXNwYWNlIHRva2VucyBvbnRvIGFkamFjZW50IHdvcmQgb3IgcHVuY3R1YXRpb25cbiAgLy8gdG9rZW5zLlxuICB2YXIgdG9rZW5pemVJbmNsdWRpbmdXaGl0ZXNwYWNlID0gbmV3IFJlZ0V4cChcIltcIi5jb25jYXQoZXh0ZW5kZWRXb3JkQ2hhcnMsIFwiXSt8XFxcXHMrfFteXCIpLmNvbmNhdChleHRlbmRlZFdvcmRDaGFycywgXCJdXCIpLCAndWcnKTtcbiAgdmFyIHdvcmREaWZmID0gbmV3IERpZmYoKTtcbiAgd29yZERpZmYuZXF1YWxzID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0LCBvcHRpb25zKSB7XG4gICAgaWYgKG9wdGlvbnMuaWdub3JlQ2FzZSkge1xuICAgICAgbGVmdCA9IGxlZnQudG9Mb3dlckNhc2UoKTtcbiAgICAgIHJpZ2h0ID0gcmlnaHQudG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gICAgcmV0dXJuIGxlZnQudHJpbSgpID09PSByaWdodC50cmltKCk7XG4gIH07XG4gIHdvcmREaWZmLnRva2VuaXplID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgdmFyIG9wdGlvbnMgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHt9O1xuICAgIHZhciBwYXJ0cztcbiAgICBpZiAob3B0aW9ucy5pbnRsU2VnbWVudGVyKSB7XG4gICAgICBpZiAob3B0aW9ucy5pbnRsU2VnbWVudGVyLnJlc29sdmVkT3B0aW9ucygpLmdyYW51bGFyaXR5ICE9ICd3b3JkJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBzZWdtZW50ZXIgcGFzc2VkIG11c3QgaGF2ZSBhIGdyYW51bGFyaXR5IG9mIFwid29yZFwiJyk7XG4gICAgICB9XG4gICAgICBwYXJ0cyA9IEFycmF5LmZyb20ob3B0aW9ucy5pbnRsU2VnbWVudGVyLnNlZ21lbnQodmFsdWUpLCBmdW5jdGlvbiAoc2VnbWVudCkge1xuICAgICAgICByZXR1cm4gc2VnbWVudC5zZWdtZW50O1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHBhcnRzID0gdmFsdWUubWF0Y2godG9rZW5pemVJbmNsdWRpbmdXaGl0ZXNwYWNlKSB8fCBbXTtcbiAgICB9XG4gICAgdmFyIHRva2VucyA9IFtdO1xuICAgIHZhciBwcmV2UGFydCA9IG51bGw7XG4gICAgcGFydHMuZm9yRWFjaChmdW5jdGlvbiAocGFydCkge1xuICAgICAgaWYgKC9cXHMvLnRlc3QocGFydCkpIHtcbiAgICAgICAgaWYgKHByZXZQYXJ0ID09IG51bGwpIHtcbiAgICAgICAgICB0b2tlbnMucHVzaChwYXJ0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0b2tlbnMucHVzaCh0b2tlbnMucG9wKCkgKyBwYXJ0KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICgvXFxzLy50ZXN0KHByZXZQYXJ0KSkge1xuICAgICAgICBpZiAodG9rZW5zW3Rva2Vucy5sZW5ndGggLSAxXSA9PSBwcmV2UGFydCkge1xuICAgICAgICAgIHRva2Vucy5wdXNoKHRva2Vucy5wb3AoKSArIHBhcnQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRva2Vucy5wdXNoKHByZXZQYXJ0ICsgcGFydCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRva2Vucy5wdXNoKHBhcnQpO1xuICAgICAgfVxuICAgICAgcHJldlBhcnQgPSBwYXJ0O1xuICAgIH0pO1xuICAgIHJldHVybiB0b2tlbnM7XG4gIH07XG4gIHdvcmREaWZmLmpvaW4gPSBmdW5jdGlvbiAodG9rZW5zKSB7XG4gICAgLy8gVG9rZW5zIGJlaW5nIGpvaW5lZCBoZXJlIHdpbGwgYWx3YXlzIGhhdmUgYXBwZWFyZWQgY29uc2VjdXRpdmVseSBpbiB0aGVcbiAgICAvLyBzYW1lIHRleHQsIHNvIHdlIGNhbiBzaW1wbHkgc3RyaXAgb2ZmIHRoZSBsZWFkaW5nIHdoaXRlc3BhY2UgZnJvbSBhbGwgdGhlXG4gICAgLy8gdG9rZW5zIGV4Y2VwdCB0aGUgZmlyc3QgKGFuZCBleGNlcHQgYW55IHdoaXRlc3BhY2Utb25seSB0b2tlbnMgLSBidXQgc3VjaFxuICAgIC8vIGEgdG9rZW4gd2lsbCBhbHdheXMgYmUgdGhlIGZpcnN0IGFuZCBvbmx5IHRva2VuIGFueXdheSkgYW5kIHRoZW4gam9pbiB0aGVtXG4gICAgLy8gYW5kIHRoZSB3aGl0ZXNwYWNlIGFyb3VuZCB3b3JkcyBhbmQgcHVuY3R1YXRpb24gd2lsbCBlbmQgdXAgY29ycmVjdC5cbiAgICByZXR1cm4gdG9rZW5zLm1hcChmdW5jdGlvbiAodG9rZW4sIGkpIHtcbiAgICAgIGlmIChpID09IDApIHtcbiAgICAgICAgcmV0dXJuIHRva2VuO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRva2VuLnJlcGxhY2UoL15cXHMrLywgJycpO1xuICAgICAgfVxuICAgIH0pLmpvaW4oJycpO1xuICB9O1xuICB3b3JkRGlmZi5wb3N0UHJvY2VzcyA9IGZ1bmN0aW9uIChjaGFuZ2VzLCBvcHRpb25zKSB7XG4gICAgaWYgKCFjaGFuZ2VzIHx8IG9wdGlvbnMub25lQ2hhbmdlUGVyVG9rZW4pIHtcbiAgICAgIHJldHVybiBjaGFuZ2VzO1xuICAgIH1cbiAgICB2YXIgbGFzdEtlZXAgPSBudWxsO1xuICAgIC8vIENoYW5nZSBvYmplY3RzIHJlcHJlc2VudGluZyBhbnkgaW5zZXJ0aW9uIG9yIGRlbGV0aW9uIHNpbmNlIHRoZSBsYXN0XG4gICAgLy8gXCJrZWVwXCIgY2hhbmdlIG9iamVjdC4gVGhlcmUgY2FuIGJlIGF0IG1vc3Qgb25lIG9mIGVhY2guXG4gICAgdmFyIGluc2VydGlvbiA9IG51bGw7XG4gICAgdmFyIGRlbGV0aW9uID0gbnVsbDtcbiAgICBjaGFuZ2VzLmZvckVhY2goZnVuY3Rpb24gKGNoYW5nZSkge1xuICAgICAgaWYgKGNoYW5nZS5hZGRlZCkge1xuICAgICAgICBpbnNlcnRpb24gPSBjaGFuZ2U7XG4gICAgICB9IGVsc2UgaWYgKGNoYW5nZS5yZW1vdmVkKSB7XG4gICAgICAgIGRlbGV0aW9uID0gY2hhbmdlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGluc2VydGlvbiB8fCBkZWxldGlvbikge1xuICAgICAgICAgIC8vIE1heSBiZSBmYWxzZSBhdCBzdGFydCBvZiB0ZXh0XG4gICAgICAgICAgZGVkdXBlV2hpdGVzcGFjZUluQ2hhbmdlT2JqZWN0cyhsYXN0S2VlcCwgZGVsZXRpb24sIGluc2VydGlvbiwgY2hhbmdlKTtcbiAgICAgICAgfVxuICAgICAgICBsYXN0S2VlcCA9IGNoYW5nZTtcbiAgICAgICAgaW5zZXJ0aW9uID0gbnVsbDtcbiAgICAgICAgZGVsZXRpb24gPSBudWxsO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmIChpbnNlcnRpb24gfHwgZGVsZXRpb24pIHtcbiAgICAgIGRlZHVwZVdoaXRlc3BhY2VJbkNoYW5nZU9iamVjdHMobGFzdEtlZXAsIGRlbGV0aW9uLCBpbnNlcnRpb24sIG51bGwpO1xuICAgIH1cbiAgICByZXR1cm4gY2hhbmdlcztcbiAgfTtcbiAgZnVuY3Rpb24gZGlmZldvcmRzKG9sZFN0ciwgbmV3U3RyLCBvcHRpb25zKSB7XG4gICAgLy8gVGhpcyBvcHRpb24gaGFzIG5ldmVyIGJlZW4gZG9jdW1lbnRlZCBhbmQgbmV2ZXIgd2lsbCBiZSAoaXQncyBjbGVhcmVyIHRvXG4gICAgLy8ganVzdCBjYWxsIGBkaWZmV29yZHNXaXRoU3BhY2VgIGRpcmVjdGx5IGlmIHlvdSBuZWVkIHRoYXQgYmVoYXZpb3IpLCBidXRcbiAgICAvLyBoYXMgZXhpc3RlZCBpbiBqc2RpZmYgZm9yIGEgbG9uZyB0aW1lLCBzbyB3ZSByZXRhaW4gc3VwcG9ydCBmb3IgaXQgaGVyZVxuICAgIC8vIGZvciB0aGUgc2FrZSBvZiBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eS5cbiAgICBpZiAoKG9wdGlvbnMgPT09IG51bGwgfHwgb3B0aW9ucyA9PT0gdm9pZCAwID8gdm9pZCAwIDogb3B0aW9ucy5pZ25vcmVXaGl0ZXNwYWNlKSAhPSBudWxsICYmICFvcHRpb25zLmlnbm9yZVdoaXRlc3BhY2UpIHtcbiAgICAgIHJldHVybiBkaWZmV29yZHNXaXRoU3BhY2Uob2xkU3RyLCBuZXdTdHIsIG9wdGlvbnMpO1xuICAgIH1cbiAgICByZXR1cm4gd29yZERpZmYuZGlmZihvbGRTdHIsIG5ld1N0ciwgb3B0aW9ucyk7XG4gIH1cbiAgZnVuY3Rpb24gZGVkdXBlV2hpdGVzcGFjZUluQ2hhbmdlT2JqZWN0cyhzdGFydEtlZXAsIGRlbGV0aW9uLCBpbnNlcnRpb24sIGVuZEtlZXApIHtcbiAgICAvLyBCZWZvcmUgcmV0dXJuaW5nLCB3ZSB0aWR5IHVwIHRoZSBsZWFkaW5nIGFuZCB0cmFpbGluZyB3aGl0ZXNwYWNlIG9mIHRoZVxuICAgIC8vIGNoYW5nZSBvYmplY3RzIHRvIGVsaW1pbmF0ZSBjYXNlcyB3aGVyZSB0cmFpbGluZyB3aGl0ZXNwYWNlIGluIG9uZSBvYmplY3RcbiAgICAvLyBpcyByZXBlYXRlZCBhcyBsZWFkaW5nIHdoaXRlc3BhY2UgaW4gdGhlIG5leHQuXG4gICAgLy8gQmVsb3cgYXJlIGV4YW1wbGVzIG9mIHRoZSBvdXRjb21lcyB3ZSB3YW50IGhlcmUgdG8gZXhwbGFpbiB0aGUgY29kZS5cbiAgICAvLyBJPWluc2VydCwgSz1rZWVwLCBEPWRlbGV0ZVxuICAgIC8vIDEuIGRpZmZpbmcgJ2ZvbyBiYXIgYmF6JyB2cyAnZm9vIGJheidcbiAgICAvLyAgICBQcmlvciB0byBjbGVhbnVwLCB3ZSBoYXZlIEs6J2ZvbyAnIEQ6JyBiYXIgJyBLOicgYmF6J1xuICAgIC8vICAgIEFmdGVyIGNsZWFudXAsIHdlIHdhbnQ6ICAgSzonZm9vICcgRDonYmFyICcgSzonYmF6J1xuICAgIC8vXG4gICAgLy8gMi4gRGlmZmluZyAnZm9vIGJhciBiYXonIHZzICdmb28gcXV4IGJheidcbiAgICAvLyAgICBQcmlvciB0byBjbGVhbnVwLCB3ZSBoYXZlIEs6J2ZvbyAnIEQ6JyBiYXIgJyBJOicgcXV4ICcgSzonIGJheidcbiAgICAvLyAgICBBZnRlciBjbGVhbnVwLCB3ZSB3YW50IEs6J2ZvbyAnIEQ6J2JhcicgSToncXV4JyBLOicgYmF6J1xuICAgIC8vXG4gICAgLy8gMy4gRGlmZmluZyAnZm9vXFxuYmFyIGJheicgdnMgJ2ZvbyBiYXonXG4gICAgLy8gICAgUHJpb3IgdG8gY2xlYW51cCwgd2UgaGF2ZSBLOidmb28gJyBEOidcXG5iYXIgJyBLOicgYmF6J1xuICAgIC8vICAgIEFmdGVyIGNsZWFudXAsIHdlIHdhbnQgSydmb28nIEQ6J1xcbmJhcicgSzonIGJheidcbiAgICAvL1xuICAgIC8vIDQuIERpZmZpbmcgJ2ZvbyBiYXonIHZzICdmb29cXG5iYXIgYmF6J1xuICAgIC8vICAgIFByaW9yIHRvIGNsZWFudXAsIHdlIGhhdmUgSzonZm9vXFxuJyBJOidcXG5iYXIgJyBLOicgYmF6J1xuICAgIC8vICAgIEFmdGVyIGNsZWFudXAsIHdlIGlkZWFsbHkgd2FudCBLJ2ZvbycgSTonXFxuYmFyJyBLOicgYmF6J1xuICAgIC8vICAgIGJ1dCBkb24ndCBhY3R1YWxseSBtYW5hZ2UgdGhpcyBjdXJyZW50bHkgKHRoZSBwcmUtY2xlYW51cCBjaGFuZ2VcbiAgICAvLyAgICBvYmplY3RzIGRvbid0IGNvbnRhaW4gZW5vdWdoIGluZm9ybWF0aW9uIHRvIG1ha2UgaXQgcG9zc2libGUpLlxuICAgIC8vXG4gICAgLy8gNS4gRGlmZmluZyAnZm9vICAgYmFyIGJheicgdnMgJ2ZvbyAgYmF6J1xuICAgIC8vICAgIFByaW9yIHRvIGNsZWFudXAsIHdlIGhhdmUgSzonZm9vICAnIEQ6JyAgIGJhciAnIEs6JyAgYmF6J1xuICAgIC8vICAgIEFmdGVyIGNsZWFudXAsIHdlIHdhbnQgSzonZm9vICAnIEQ6JyBiYXIgJyBLOidiYXonXG4gICAgLy9cbiAgICAvLyBPdXIgaGFuZGxpbmcgaXMgdW5hdm9pZGFibHkgaW1wZXJmZWN0IGluIHRoZSBjYXNlIHdoZXJlIHRoZXJlJ3MgYSBzaW5nbGVcbiAgICAvLyBpbmRlbCBiZXR3ZWVuIGtlZXBzIGFuZCB0aGUgd2hpdGVzcGFjZSBoYXMgY2hhbmdlZC4gRm9yIGluc3RhbmNlLCBjb25zaWRlclxuICAgIC8vIGRpZmZpbmcgJ2Zvb1xcdGJhclxcbmJheicgdnMgJ2ZvbyBiYXonLiBVbmxlc3Mgd2UgY3JlYXRlIGFuIGV4dHJhIGNoYW5nZVxuICAgIC8vIG9iamVjdCB0byByZXByZXNlbnQgdGhlIGluc2VydGlvbiBvZiB0aGUgc3BhY2UgY2hhcmFjdGVyICh3aGljaCBpc24ndCBldmVuXG4gICAgLy8gYSB0b2tlbiksIHdlIGhhdmUgbm8gd2F5IHRvIGF2b2lkIGxvc2luZyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgdGV4dHMnXG4gICAgLy8gb3JpZ2luYWwgd2hpdGVzcGFjZSBpbiB0aGUgcmVzdWx0IHdlIHJldHVybi4gU3RpbGwsIHdlIGRvIG91ciBiZXN0IHRvXG4gICAgLy8gb3V0cHV0IHNvbWV0aGluZyB0aGF0IHdpbGwgbG9vayBzZW5zaWJsZSBpZiB3ZSBlLmcuIHByaW50IGl0IHdpdGhcbiAgICAvLyBpbnNlcnRpb25zIGluIGdyZWVuIGFuZCBkZWxldGlvbnMgaW4gcmVkLlxuXG4gICAgLy8gQmV0d2VlbiB0d28gXCJrZWVwXCIgY2hhbmdlIG9iamVjdHMgKG9yIGJlZm9yZSB0aGUgZmlyc3Qgb3IgYWZ0ZXIgdGhlIGxhc3RcbiAgICAvLyBjaGFuZ2Ugb2JqZWN0KSwgd2UgY2FuIGhhdmUgZWl0aGVyOlxuICAgIC8vICogQSBcImRlbGV0ZVwiIGZvbGxvd2VkIGJ5IGFuIFwiaW5zZXJ0XCJcbiAgICAvLyAqIEp1c3QgYW4gXCJpbnNlcnRcIlxuICAgIC8vICogSnVzdCBhIFwiZGVsZXRlXCJcbiAgICAvLyBXZSBoYW5kbGUgdGhlIHRocmVlIGNhc2VzIHNlcGFyYXRlbHkuXG4gICAgaWYgKGRlbGV0aW9uICYmIGluc2VydGlvbikge1xuICAgICAgdmFyIG9sZFdzUHJlZml4ID0gZGVsZXRpb24udmFsdWUubWF0Y2goL15cXHMqLylbMF07XG4gICAgICB2YXIgb2xkV3NTdWZmaXggPSBkZWxldGlvbi52YWx1ZS5tYXRjaCgvXFxzKiQvKVswXTtcbiAgICAgIHZhciBuZXdXc1ByZWZpeCA9IGluc2VydGlvbi52YWx1ZS5tYXRjaCgvXlxccyovKVswXTtcbiAgICAgIHZhciBuZXdXc1N1ZmZpeCA9IGluc2VydGlvbi52YWx1ZS5tYXRjaCgvXFxzKiQvKVswXTtcbiAgICAgIGlmIChzdGFydEtlZXApIHtcbiAgICAgICAgdmFyIGNvbW1vbldzUHJlZml4ID0gbG9uZ2VzdENvbW1vblByZWZpeChvbGRXc1ByZWZpeCwgbmV3V3NQcmVmaXgpO1xuICAgICAgICBzdGFydEtlZXAudmFsdWUgPSByZXBsYWNlU3VmZml4KHN0YXJ0S2VlcC52YWx1ZSwgbmV3V3NQcmVmaXgsIGNvbW1vbldzUHJlZml4KTtcbiAgICAgICAgZGVsZXRpb24udmFsdWUgPSByZW1vdmVQcmVmaXgoZGVsZXRpb24udmFsdWUsIGNvbW1vbldzUHJlZml4KTtcbiAgICAgICAgaW5zZXJ0aW9uLnZhbHVlID0gcmVtb3ZlUHJlZml4KGluc2VydGlvbi52YWx1ZSwgY29tbW9uV3NQcmVmaXgpO1xuICAgICAgfVxuICAgICAgaWYgKGVuZEtlZXApIHtcbiAgICAgICAgdmFyIGNvbW1vbldzU3VmZml4ID0gbG9uZ2VzdENvbW1vblN1ZmZpeChvbGRXc1N1ZmZpeCwgbmV3V3NTdWZmaXgpO1xuICAgICAgICBlbmRLZWVwLnZhbHVlID0gcmVwbGFjZVByZWZpeChlbmRLZWVwLnZhbHVlLCBuZXdXc1N1ZmZpeCwgY29tbW9uV3NTdWZmaXgpO1xuICAgICAgICBkZWxldGlvbi52YWx1ZSA9IHJlbW92ZVN1ZmZpeChkZWxldGlvbi52YWx1ZSwgY29tbW9uV3NTdWZmaXgpO1xuICAgICAgICBpbnNlcnRpb24udmFsdWUgPSByZW1vdmVTdWZmaXgoaW5zZXJ0aW9uLnZhbHVlLCBjb21tb25Xc1N1ZmZpeCk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChpbnNlcnRpb24pIHtcbiAgICAgIC8vIFRoZSB3aGl0ZXNwYWNlcyBhbGwgcmVmbGVjdCB3aGF0IHdhcyBpbiB0aGUgbmV3IHRleHQgcmF0aGVyIHRoYW5cbiAgICAgIC8vIHRoZSBvbGQsIHNvIHdlIGVzc2VudGlhbGx5IGhhdmUgbm8gaW5mb3JtYXRpb24gYWJvdXQgd2hpdGVzcGFjZVxuICAgICAgLy8gaW5zZXJ0aW9uIG9yIGRlbGV0aW9uLiBXZSBqdXN0IHdhbnQgdG8gZGVkdXBlIHRoZSB3aGl0ZXNwYWNlLlxuICAgICAgLy8gV2UgZG8gdGhhdCBieSBoYXZpbmcgZWFjaCBjaGFuZ2Ugb2JqZWN0IGtlZXAgaXRzIHRyYWlsaW5nXG4gICAgICAvLyB3aGl0ZXNwYWNlIGFuZCBkZWxldGluZyBkdXBsaWNhdGUgbGVhZGluZyB3aGl0ZXNwYWNlIHdoZXJlXG4gICAgICAvLyBwcmVzZW50LlxuICAgICAgaWYgKHN0YXJ0S2VlcCkge1xuICAgICAgICBpbnNlcnRpb24udmFsdWUgPSBpbnNlcnRpb24udmFsdWUucmVwbGFjZSgvXlxccyovLCAnJyk7XG4gICAgICB9XG4gICAgICBpZiAoZW5kS2VlcCkge1xuICAgICAgICBlbmRLZWVwLnZhbHVlID0gZW5kS2VlcC52YWx1ZS5yZXBsYWNlKC9eXFxzKi8sICcnKTtcbiAgICAgIH1cbiAgICAgIC8vIG90aGVyd2lzZSB3ZSd2ZSBnb3QgYSBkZWxldGlvbiBhbmQgbm8gaW5zZXJ0aW9uXG4gICAgfSBlbHNlIGlmIChzdGFydEtlZXAgJiYgZW5kS2VlcCkge1xuICAgICAgdmFyIG5ld1dzRnVsbCA9IGVuZEtlZXAudmFsdWUubWF0Y2goL15cXHMqLylbMF0sXG4gICAgICAgIGRlbFdzU3RhcnQgPSBkZWxldGlvbi52YWx1ZS5tYXRjaCgvXlxccyovKVswXSxcbiAgICAgICAgZGVsV3NFbmQgPSBkZWxldGlvbi52YWx1ZS5tYXRjaCgvXFxzKiQvKVswXTtcblxuICAgICAgLy8gQW55IHdoaXRlc3BhY2UgdGhhdCBjb21lcyBzdHJhaWdodCBhZnRlciBzdGFydEtlZXAgaW4gYm90aCB0aGUgb2xkIGFuZFxuICAgICAgLy8gbmV3IHRleHRzLCBhc3NpZ24gdG8gc3RhcnRLZWVwIGFuZCByZW1vdmUgZnJvbSB0aGUgZGVsZXRpb24uXG4gICAgICB2YXIgbmV3V3NTdGFydCA9IGxvbmdlc3RDb21tb25QcmVmaXgobmV3V3NGdWxsLCBkZWxXc1N0YXJ0KTtcbiAgICAgIGRlbGV0aW9uLnZhbHVlID0gcmVtb3ZlUHJlZml4KGRlbGV0aW9uLnZhbHVlLCBuZXdXc1N0YXJ0KTtcblxuICAgICAgLy8gQW55IHdoaXRlc3BhY2UgdGhhdCBjb21lcyBzdHJhaWdodCBiZWZvcmUgZW5kS2VlcCBpbiBib3RoIHRoZSBvbGQgYW5kXG4gICAgICAvLyBuZXcgdGV4dHMsIGFuZCBoYXNuJ3QgYWxyZWFkeSBiZWVuIGFzc2lnbmVkIHRvIHN0YXJ0S2VlcCwgYXNzaWduIHRvXG4gICAgICAvLyBlbmRLZWVwIGFuZCByZW1vdmUgZnJvbSB0aGUgZGVsZXRpb24uXG4gICAgICB2YXIgbmV3V3NFbmQgPSBsb25nZXN0Q29tbW9uU3VmZml4KHJlbW92ZVByZWZpeChuZXdXc0Z1bGwsIG5ld1dzU3RhcnQpLCBkZWxXc0VuZCk7XG4gICAgICBkZWxldGlvbi52YWx1ZSA9IHJlbW92ZVN1ZmZpeChkZWxldGlvbi52YWx1ZSwgbmV3V3NFbmQpO1xuICAgICAgZW5kS2VlcC52YWx1ZSA9IHJlcGxhY2VQcmVmaXgoZW5kS2VlcC52YWx1ZSwgbmV3V3NGdWxsLCBuZXdXc0VuZCk7XG5cbiAgICAgIC8vIElmIHRoZXJlJ3MgYW55IHdoaXRlc3BhY2UgZnJvbSB0aGUgbmV3IHRleHQgdGhhdCBIQVNOJ1QgYWxyZWFkeSBiZWVuXG4gICAgICAvLyBhc3NpZ25lZCwgYXNzaWduIGl0IHRvIHRoZSBzdGFydDpcbiAgICAgIHN0YXJ0S2VlcC52YWx1ZSA9IHJlcGxhY2VTdWZmaXgoc3RhcnRLZWVwLnZhbHVlLCBuZXdXc0Z1bGwsIG5ld1dzRnVsbC5zbGljZSgwLCBuZXdXc0Z1bGwubGVuZ3RoIC0gbmV3V3NFbmQubGVuZ3RoKSk7XG4gICAgfSBlbHNlIGlmIChlbmRLZWVwKSB7XG4gICAgICAvLyBXZSBhcmUgYXQgdGhlIHN0YXJ0IG9mIHRoZSB0ZXh0LiBQcmVzZXJ2ZSBhbGwgdGhlIHdoaXRlc3BhY2Ugb25cbiAgICAgIC8vIGVuZEtlZXAsIGFuZCBqdXN0IHJlbW92ZSB3aGl0ZXNwYWNlIGZyb20gdGhlIGVuZCBvZiBkZWxldGlvbiB0byB0aGVcbiAgICAgIC8vIGV4dGVudCB0aGF0IGl0IG92ZXJsYXBzIHdpdGggdGhlIHN0YXJ0IG9mIGVuZEtlZXAuXG4gICAgICB2YXIgZW5kS2VlcFdzUHJlZml4ID0gZW5kS2VlcC52YWx1ZS5tYXRjaCgvXlxccyovKVswXTtcbiAgICAgIHZhciBkZWxldGlvbldzU3VmZml4ID0gZGVsZXRpb24udmFsdWUubWF0Y2goL1xccyokLylbMF07XG4gICAgICB2YXIgb3ZlcmxhcCA9IG1heGltdW1PdmVybGFwKGRlbGV0aW9uV3NTdWZmaXgsIGVuZEtlZXBXc1ByZWZpeCk7XG4gICAgICBkZWxldGlvbi52YWx1ZSA9IHJlbW92ZVN1ZmZpeChkZWxldGlvbi52YWx1ZSwgb3ZlcmxhcCk7XG4gICAgfSBlbHNlIGlmIChzdGFydEtlZXApIHtcbiAgICAgIC8vIFdlIGFyZSBhdCB0aGUgRU5EIG9mIHRoZSB0ZXh0LiBQcmVzZXJ2ZSBhbGwgdGhlIHdoaXRlc3BhY2Ugb25cbiAgICAgIC8vIHN0YXJ0S2VlcCwgYW5kIGp1c3QgcmVtb3ZlIHdoaXRlc3BhY2UgZnJvbSB0aGUgc3RhcnQgb2YgZGVsZXRpb24gdG9cbiAgICAgIC8vIHRoZSBleHRlbnQgdGhhdCBpdCBvdmVybGFwcyB3aXRoIHRoZSBlbmQgb2Ygc3RhcnRLZWVwLlxuICAgICAgdmFyIHN0YXJ0S2VlcFdzU3VmZml4ID0gc3RhcnRLZWVwLnZhbHVlLm1hdGNoKC9cXHMqJC8pWzBdO1xuICAgICAgdmFyIGRlbGV0aW9uV3NQcmVmaXggPSBkZWxldGlvbi52YWx1ZS5tYXRjaCgvXlxccyovKVswXTtcbiAgICAgIHZhciBfb3ZlcmxhcCA9IG1heGltdW1PdmVybGFwKHN0YXJ0S2VlcFdzU3VmZml4LCBkZWxldGlvbldzUHJlZml4KTtcbiAgICAgIGRlbGV0aW9uLnZhbHVlID0gcmVtb3ZlUHJlZml4KGRlbGV0aW9uLnZhbHVlLCBfb3ZlcmxhcCk7XG4gICAgfVxuICB9XG4gIHZhciB3b3JkV2l0aFNwYWNlRGlmZiA9IG5ldyBEaWZmKCk7XG4gIHdvcmRXaXRoU3BhY2VEaWZmLnRva2VuaXplID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgLy8gU2xpZ2h0bHkgZGlmZmVyZW50IHRvIHRoZSB0b2tlbml6ZUluY2x1ZGluZ1doaXRlc3BhY2UgcmVnZXggdXNlZCBhYm92ZSBpblxuICAgIC8vIHRoYXQgdGhpcyBvbmUgdHJlYXRzIGVhY2ggaW5kaXZpZHVhbCBuZXdsaW5lIGFzIGEgZGlzdGluY3QgdG9rZW5zLCByYXRoZXJcbiAgICAvLyB0aGFuIG1lcmdpbmcgdGhlbSBpbnRvIG90aGVyIHN1cnJvdW5kaW5nIHdoaXRlc3BhY2UuIFRoaXMgd2FzIHJlcXVlc3RlZFxuICAgIC8vIGluIGh0dHBzOi8vZ2l0aHViLmNvbS9rcGRlY2tlci9qc2RpZmYvaXNzdWVzLzE4MCAmXG4gICAgLy8gICAgaHR0cHM6Ly9naXRodWIuY29tL2twZGVja2VyL2pzZGlmZi9pc3N1ZXMvMjExXG4gICAgdmFyIHJlZ2V4ID0gbmV3IFJlZ0V4cChcIihcXFxccj9cXFxcbil8W1wiLmNvbmNhdChleHRlbmRlZFdvcmRDaGFycywgXCJdK3xbXlxcXFxTXFxcXG5cXFxccl0rfFteXCIpLmNvbmNhdChleHRlbmRlZFdvcmRDaGFycywgXCJdXCIpLCAndWcnKTtcbiAgICByZXR1cm4gdmFsdWUubWF0Y2gocmVnZXgpIHx8IFtdO1xuICB9O1xuICBmdW5jdGlvbiBkaWZmV29yZHNXaXRoU3BhY2Uob2xkU3RyLCBuZXdTdHIsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gd29yZFdpdGhTcGFjZURpZmYuZGlmZihvbGRTdHIsIG5ld1N0ciwgb3B0aW9ucyk7XG4gIH1cblxuICBmdW5jdGlvbiBnZW5lcmF0ZU9wdGlvbnMob3B0aW9ucywgZGVmYXVsdHMpIHtcbiAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGRlZmF1bHRzLmNhbGxiYWNrID0gb3B0aW9ucztcbiAgICB9IGVsc2UgaWYgKG9wdGlvbnMpIHtcbiAgICAgIGZvciAodmFyIG5hbWUgaW4gb3B0aW9ucykge1xuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgICBpZiAob3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShuYW1lKSkge1xuICAgICAgICAgIGRlZmF1bHRzW25hbWVdID0gb3B0aW9uc1tuYW1lXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGVmYXVsdHM7XG4gIH1cblxuICB2YXIgbGluZURpZmYgPSBuZXcgRGlmZigpO1xuICBsaW5lRGlmZi50b2tlbml6ZSA9IGZ1bmN0aW9uICh2YWx1ZSwgb3B0aW9ucykge1xuICAgIGlmIChvcHRpb25zLnN0cmlwVHJhaWxpbmdDcikge1xuICAgICAgLy8gcmVtb3ZlIG9uZSBcXHIgYmVmb3JlIFxcbiB0byBtYXRjaCBHTlUgZGlmZidzIC0tc3RyaXAtdHJhaWxpbmctY3IgYmVoYXZpb3JcbiAgICAgIHZhbHVlID0gdmFsdWUucmVwbGFjZSgvXFxyXFxuL2csICdcXG4nKTtcbiAgICB9XG4gICAgdmFyIHJldExpbmVzID0gW10sXG4gICAgICBsaW5lc0FuZE5ld2xpbmVzID0gdmFsdWUuc3BsaXQoLyhcXG58XFxyXFxuKS8pO1xuXG4gICAgLy8gSWdub3JlIHRoZSBmaW5hbCBlbXB0eSB0b2tlbiB0aGF0IG9jY3VycyBpZiB0aGUgc3RyaW5nIGVuZHMgd2l0aCBhIG5ldyBsaW5lXG4gICAgaWYgKCFsaW5lc0FuZE5ld2xpbmVzW2xpbmVzQW5kTmV3bGluZXMubGVuZ3RoIC0gMV0pIHtcbiAgICAgIGxpbmVzQW5kTmV3bGluZXMucG9wKCk7XG4gICAgfVxuXG4gICAgLy8gTWVyZ2UgdGhlIGNvbnRlbnQgYW5kIGxpbmUgc2VwYXJhdG9ycyBpbnRvIHNpbmdsZSB0b2tlbnNcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpbmVzQW5kTmV3bGluZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBsaW5lID0gbGluZXNBbmROZXdsaW5lc1tpXTtcbiAgICAgIGlmIChpICUgMiAmJiAhb3B0aW9ucy5uZXdsaW5lSXNUb2tlbikge1xuICAgICAgICByZXRMaW5lc1tyZXRMaW5lcy5sZW5ndGggLSAxXSArPSBsaW5lO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0TGluZXMucHVzaChsaW5lKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJldExpbmVzO1xuICB9O1xuICBsaW5lRGlmZi5lcXVhbHMgPSBmdW5jdGlvbiAobGVmdCwgcmlnaHQsIG9wdGlvbnMpIHtcbiAgICAvLyBJZiB3ZSdyZSBpZ25vcmluZyB3aGl0ZXNwYWNlLCB3ZSBuZWVkIHRvIG5vcm1hbGlzZSBsaW5lcyBieSBzdHJpcHBpbmdcbiAgICAvLyB3aGl0ZXNwYWNlIGJlZm9yZSBjaGVja2luZyBlcXVhbGl0eS4gKFRoaXMgaGFzIGFuIGFubm95aW5nIGludGVyYWN0aW9uXG4gICAgLy8gd2l0aCBuZXdsaW5lSXNUb2tlbiB0aGF0IHJlcXVpcmVzIHNwZWNpYWwgaGFuZGxpbmc6IGlmIG5ld2xpbmVzIGdldCB0aGVpclxuICAgIC8vIG93biB0b2tlbiwgdGhlbiB3ZSBET04nVCB3YW50IHRvIHRyaW0gdGhlICpuZXdsaW5lKiB0b2tlbnMgZG93biB0byBlbXB0eVxuICAgIC8vIHN0cmluZ3MsIHNpbmNlIHRoaXMgd291bGQgY2F1c2UgdXMgdG8gdHJlYXQgd2hpdGVzcGFjZS1vbmx5IGxpbmUgY29udGVudFxuICAgIC8vIGFzIGVxdWFsIHRvIGEgc2VwYXJhdG9yIGJldHdlZW4gbGluZXMsIHdoaWNoIHdvdWxkIGJlIHdlaXJkIGFuZFxuICAgIC8vIGluY29uc2lzdGVudCB3aXRoIHRoZSBkb2N1bWVudGVkIGJlaGF2aW9yIG9mIHRoZSBvcHRpb25zLilcbiAgICBpZiAob3B0aW9ucy5pZ25vcmVXaGl0ZXNwYWNlKSB7XG4gICAgICBpZiAoIW9wdGlvbnMubmV3bGluZUlzVG9rZW4gfHwgIWxlZnQuaW5jbHVkZXMoJ1xcbicpKSB7XG4gICAgICAgIGxlZnQgPSBsZWZ0LnRyaW0oKTtcbiAgICAgIH1cbiAgICAgIGlmICghb3B0aW9ucy5uZXdsaW5lSXNUb2tlbiB8fCAhcmlnaHQuaW5jbHVkZXMoJ1xcbicpKSB7XG4gICAgICAgIHJpZ2h0ID0gcmlnaHQudHJpbSgpO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5pZ25vcmVOZXdsaW5lQXRFb2YgJiYgIW9wdGlvbnMubmV3bGluZUlzVG9rZW4pIHtcbiAgICAgIGlmIChsZWZ0LmVuZHNXaXRoKCdcXG4nKSkge1xuICAgICAgICBsZWZ0ID0gbGVmdC5zbGljZSgwLCAtMSk7XG4gICAgICB9XG4gICAgICBpZiAocmlnaHQuZW5kc1dpdGgoJ1xcbicpKSB7XG4gICAgICAgIHJpZ2h0ID0gcmlnaHQuc2xpY2UoMCwgLTEpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gRGlmZi5wcm90b3R5cGUuZXF1YWxzLmNhbGwodGhpcywgbGVmdCwgcmlnaHQsIG9wdGlvbnMpO1xuICB9O1xuICBmdW5jdGlvbiBkaWZmTGluZXMob2xkU3RyLCBuZXdTdHIsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIGxpbmVEaWZmLmRpZmYob2xkU3RyLCBuZXdTdHIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIC8vIEtlcHQgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LiBUaGlzIGlzIGEgcmF0aGVyIGFyYml0cmFyeSB3cmFwcGVyIG1ldGhvZFxuICAvLyB0aGF0IGp1c3QgY2FsbHMgYGRpZmZMaW5lc2Agd2l0aCBgaWdub3JlV2hpdGVzcGFjZTogdHJ1ZWAuIEl0J3MgY29uZnVzaW5nIHRvXG4gIC8vIGhhdmUgdHdvIHdheXMgdG8gZG8gZXhhY3RseSB0aGUgc2FtZSB0aGluZyBpbiB0aGUgQVBJLCBzbyB3ZSBubyBsb25nZXJcbiAgLy8gZG9jdW1lbnQgdGhpcyBvbmUgKGxpYnJhcnkgdXNlcnMgc2hvdWxkIGV4cGxpY2l0bHkgdXNlIGBkaWZmTGluZXNgIHdpdGhcbiAgLy8gYGlnbm9yZVdoaXRlc3BhY2U6IHRydWVgIGluc3RlYWQpIGJ1dCB3ZSBrZWVwIGl0IGFyb3VuZCB0byBtYWludGFpblxuICAvLyBjb21wYXRpYmlsaXR5IHdpdGggY29kZSB0aGF0IHVzZWQgb2xkIHZlcnNpb25zLlxuICBmdW5jdGlvbiBkaWZmVHJpbW1lZExpbmVzKG9sZFN0ciwgbmV3U3RyLCBjYWxsYmFjaykge1xuICAgIHZhciBvcHRpb25zID0gZ2VuZXJhdGVPcHRpb25zKGNhbGxiYWNrLCB7XG4gICAgICBpZ25vcmVXaGl0ZXNwYWNlOiB0cnVlXG4gICAgfSk7XG4gICAgcmV0dXJuIGxpbmVEaWZmLmRpZmYob2xkU3RyLCBuZXdTdHIsIG9wdGlvbnMpO1xuICB9XG5cbiAgdmFyIHNlbnRlbmNlRGlmZiA9IG5ldyBEaWZmKCk7XG4gIHNlbnRlbmNlRGlmZi50b2tlbml6ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5zcGxpdCgvKFxcUy4rP1suIT9dKSg/PVxccyt8JCkvKTtcbiAgfTtcbiAgZnVuY3Rpb24gZGlmZlNlbnRlbmNlcyhvbGRTdHIsIG5ld1N0ciwgY2FsbGJhY2spIHtcbiAgICByZXR1cm4gc2VudGVuY2VEaWZmLmRpZmYob2xkU3RyLCBuZXdTdHIsIGNhbGxiYWNrKTtcbiAgfVxuXG4gIHZhciBjc3NEaWZmID0gbmV3IERpZmYoKTtcbiAgY3NzRGlmZi50b2tlbml6ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5zcGxpdCgvKFt7fTo7LF18XFxzKykvKTtcbiAgfTtcbiAgZnVuY3Rpb24gZGlmZkNzcyhvbGRTdHIsIG5ld1N0ciwgY2FsbGJhY2spIHtcbiAgICByZXR1cm4gY3NzRGlmZi5kaWZmKG9sZFN0ciwgbmV3U3RyLCBjYWxsYmFjayk7XG4gIH1cblxuICBmdW5jdGlvbiBvd25LZXlzKGUsIHIpIHtcbiAgICB2YXIgdCA9IE9iamVjdC5rZXlzKGUpO1xuICAgIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKSB7XG4gICAgICB2YXIgbyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMoZSk7XG4gICAgICByICYmIChvID0gby5maWx0ZXIoZnVuY3Rpb24gKHIpIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoZSwgcikuZW51bWVyYWJsZTtcbiAgICAgIH0pKSwgdC5wdXNoLmFwcGx5KHQsIG8pO1xuICAgIH1cbiAgICByZXR1cm4gdDtcbiAgfVxuICBmdW5jdGlvbiBfb2JqZWN0U3ByZWFkMihlKSB7XG4gICAgZm9yICh2YXIgciA9IDE7IHIgPCBhcmd1bWVudHMubGVuZ3RoOyByKyspIHtcbiAgICAgIHZhciB0ID0gbnVsbCAhPSBhcmd1bWVudHNbcl0gPyBhcmd1bWVudHNbcl0gOiB7fTtcbiAgICAgIHIgJSAyID8gb3duS2V5cyhPYmplY3QodCksICEwKS5mb3JFYWNoKGZ1bmN0aW9uIChyKSB7XG4gICAgICAgIF9kZWZpbmVQcm9wZXJ0eShlLCByLCB0W3JdKTtcbiAgICAgIH0pIDogT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcnMgPyBPYmplY3QuZGVmaW5lUHJvcGVydGllcyhlLCBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9ycyh0KSkgOiBvd25LZXlzKE9iamVjdCh0KSkuZm9yRWFjaChmdW5jdGlvbiAocikge1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoZSwgciwgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih0LCByKSk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGU7XG4gIH1cbiAgZnVuY3Rpb24gX3RvUHJpbWl0aXZlKHQsIHIpIHtcbiAgICBpZiAoXCJvYmplY3RcIiAhPSB0eXBlb2YgdCB8fCAhdCkgcmV0dXJuIHQ7XG4gICAgdmFyIGUgPSB0W1N5bWJvbC50b1ByaW1pdGl2ZV07XG4gICAgaWYgKHZvaWQgMCAhPT0gZSkge1xuICAgICAgdmFyIGkgPSBlLmNhbGwodCwgciB8fCBcImRlZmF1bHRcIik7XG4gICAgICBpZiAoXCJvYmplY3RcIiAhPSB0eXBlb2YgaSkgcmV0dXJuIGk7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQEB0b1ByaW1pdGl2ZSBtdXN0IHJldHVybiBhIHByaW1pdGl2ZSB2YWx1ZS5cIik7XG4gICAgfVxuICAgIHJldHVybiAoXCJzdHJpbmdcIiA9PT0gciA/IFN0cmluZyA6IE51bWJlcikodCk7XG4gIH1cbiAgZnVuY3Rpb24gX3RvUHJvcGVydHlLZXkodCkge1xuICAgIHZhciBpID0gX3RvUHJpbWl0aXZlKHQsIFwic3RyaW5nXCIpO1xuICAgIHJldHVybiBcInN5bWJvbFwiID09IHR5cGVvZiBpID8gaSA6IGkgKyBcIlwiO1xuICB9XG4gIGZ1bmN0aW9uIF90eXBlb2Yobykge1xuICAgIFwiQGJhYmVsL2hlbHBlcnMgLSB0eXBlb2ZcIjtcblxuICAgIHJldHVybiBfdHlwZW9mID0gXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgJiYgXCJzeW1ib2xcIiA9PSB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID8gZnVuY3Rpb24gKG8pIHtcbiAgICAgIHJldHVybiB0eXBlb2YgbztcbiAgICB9IDogZnVuY3Rpb24gKG8pIHtcbiAgICAgIHJldHVybiBvICYmIFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgU3ltYm9sICYmIG8uY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvICE9PSBTeW1ib2wucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvO1xuICAgIH0sIF90eXBlb2Yobyk7XG4gIH1cbiAgZnVuY3Rpb24gX2RlZmluZVByb3BlcnR5KG9iaiwga2V5LCB2YWx1ZSkge1xuICAgIGtleSA9IF90b1Byb3BlcnR5S2V5KGtleSk7XG4gICAgaWYgKGtleSBpbiBvYmopIHtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleSwge1xuICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgd3JpdGFibGU6IHRydWVcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBvYmpba2V5XSA9IHZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gb2JqO1xuICB9XG4gIGZ1bmN0aW9uIF90b0NvbnN1bWFibGVBcnJheShhcnIpIHtcbiAgICByZXR1cm4gX2FycmF5V2l0aG91dEhvbGVzKGFycikgfHwgX2l0ZXJhYmxlVG9BcnJheShhcnIpIHx8IF91bnN1cHBvcnRlZEl0ZXJhYmxlVG9BcnJheShhcnIpIHx8IF9ub25JdGVyYWJsZVNwcmVhZCgpO1xuICB9XG4gIGZ1bmN0aW9uIF9hcnJheVdpdGhvdXRIb2xlcyhhcnIpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShhcnIpKSByZXR1cm4gX2FycmF5TGlrZVRvQXJyYXkoYXJyKTtcbiAgfVxuICBmdW5jdGlvbiBfaXRlcmFibGVUb0FycmF5KGl0ZXIpIHtcbiAgICBpZiAodHlwZW9mIFN5bWJvbCAhPT0gXCJ1bmRlZmluZWRcIiAmJiBpdGVyW1N5bWJvbC5pdGVyYXRvcl0gIT0gbnVsbCB8fCBpdGVyW1wiQEBpdGVyYXRvclwiXSAhPSBudWxsKSByZXR1cm4gQXJyYXkuZnJvbShpdGVyKTtcbiAgfVxuICBmdW5jdGlvbiBfdW5zdXBwb3J0ZWRJdGVyYWJsZVRvQXJyYXkobywgbWluTGVuKSB7XG4gICAgaWYgKCFvKSByZXR1cm47XG4gICAgaWYgKHR5cGVvZiBvID09PSBcInN0cmluZ1wiKSByZXR1cm4gX2FycmF5TGlrZVRvQXJyYXkobywgbWluTGVuKTtcbiAgICB2YXIgbiA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKS5zbGljZSg4LCAtMSk7XG4gICAgaWYgKG4gPT09IFwiT2JqZWN0XCIgJiYgby5jb25zdHJ1Y3RvcikgbiA9IG8uY29uc3RydWN0b3IubmFtZTtcbiAgICBpZiAobiA9PT0gXCJNYXBcIiB8fCBuID09PSBcIlNldFwiKSByZXR1cm4gQXJyYXkuZnJvbShvKTtcbiAgICBpZiAobiA9PT0gXCJBcmd1bWVudHNcIiB8fCAvXig/OlVpfEkpbnQoPzo4fDE2fDMyKSg/OkNsYW1wZWQpP0FycmF5JC8udGVzdChuKSkgcmV0dXJuIF9hcnJheUxpa2VUb0FycmF5KG8sIG1pbkxlbik7XG4gIH1cbiAgZnVuY3Rpb24gX2FycmF5TGlrZVRvQXJyYXkoYXJyLCBsZW4pIHtcbiAgICBpZiAobGVuID09IG51bGwgfHwgbGVuID4gYXJyLmxlbmd0aCkgbGVuID0gYXJyLmxlbmd0aDtcbiAgICBmb3IgKHZhciBpID0gMCwgYXJyMiA9IG5ldyBBcnJheShsZW4pOyBpIDwgbGVuOyBpKyspIGFycjJbaV0gPSBhcnJbaV07XG4gICAgcmV0dXJuIGFycjI7XG4gIH1cbiAgZnVuY3Rpb24gX25vbkl0ZXJhYmxlU3ByZWFkKCkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIGF0dGVtcHQgdG8gc3ByZWFkIG5vbi1pdGVyYWJsZSBpbnN0YW5jZS5cXG5JbiBvcmRlciB0byBiZSBpdGVyYWJsZSwgbm9uLWFycmF5IG9iamVjdHMgbXVzdCBoYXZlIGEgW1N5bWJvbC5pdGVyYXRvcl0oKSBtZXRob2QuXCIpO1xuICB9XG5cbiAgdmFyIGpzb25EaWZmID0gbmV3IERpZmYoKTtcbiAgLy8gRGlzY3JpbWluYXRlIGJldHdlZW4gdHdvIGxpbmVzIG9mIHByZXR0eS1wcmludGVkLCBzZXJpYWxpemVkIEpTT04gd2hlcmUgb25lIG9mIHRoZW0gaGFzIGFcbiAgLy8gZGFuZ2xpbmcgY29tbWEgYW5kIHRoZSBvdGhlciBkb2Vzbid0LiBUdXJucyBvdXQgaW5jbHVkaW5nIHRoZSBkYW5nbGluZyBjb21tYSB5aWVsZHMgdGhlIG5pY2VzdCBvdXRwdXQ6XG4gIGpzb25EaWZmLnVzZUxvbmdlc3RUb2tlbiA9IHRydWU7XG4gIGpzb25EaWZmLnRva2VuaXplID0gbGluZURpZmYudG9rZW5pemU7XG4gIGpzb25EaWZmLmNhc3RJbnB1dCA9IGZ1bmN0aW9uICh2YWx1ZSwgb3B0aW9ucykge1xuICAgIHZhciB1bmRlZmluZWRSZXBsYWNlbWVudCA9IG9wdGlvbnMudW5kZWZpbmVkUmVwbGFjZW1lbnQsXG4gICAgICBfb3B0aW9ucyRzdHJpbmdpZnlSZXAgPSBvcHRpb25zLnN0cmluZ2lmeVJlcGxhY2VyLFxuICAgICAgc3RyaW5naWZ5UmVwbGFjZXIgPSBfb3B0aW9ucyRzdHJpbmdpZnlSZXAgPT09IHZvaWQgMCA/IGZ1bmN0aW9uIChrLCB2KSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgdiA9PT0gJ3VuZGVmaW5lZCcgPyB1bmRlZmluZWRSZXBsYWNlbWVudCA6IHY7XG4gICAgICB9IDogX29wdGlvbnMkc3RyaW5naWZ5UmVwO1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnID8gdmFsdWUgOiBKU09OLnN0cmluZ2lmeShjYW5vbmljYWxpemUodmFsdWUsIG51bGwsIG51bGwsIHN0cmluZ2lmeVJlcGxhY2VyKSwgc3RyaW5naWZ5UmVwbGFjZXIsICcgICcpO1xuICB9O1xuICBqc29uRGlmZi5lcXVhbHMgPSBmdW5jdGlvbiAobGVmdCwgcmlnaHQsIG9wdGlvbnMpIHtcbiAgICByZXR1cm4gRGlmZi5wcm90b3R5cGUuZXF1YWxzLmNhbGwoanNvbkRpZmYsIGxlZnQucmVwbGFjZSgvLChbXFxyXFxuXSkvZywgJyQxJyksIHJpZ2h0LnJlcGxhY2UoLywoW1xcclxcbl0pL2csICckMScpLCBvcHRpb25zKTtcbiAgfTtcbiAgZnVuY3Rpb24gZGlmZkpzb24ob2xkT2JqLCBuZXdPYmosIG9wdGlvbnMpIHtcbiAgICByZXR1cm4ganNvbkRpZmYuZGlmZihvbGRPYmosIG5ld09iaiwgb3B0aW9ucyk7XG4gIH1cblxuICAvLyBUaGlzIGZ1bmN0aW9uIGhhbmRsZXMgdGhlIHByZXNlbmNlIG9mIGNpcmN1bGFyIHJlZmVyZW5jZXMgYnkgYmFpbGluZyBvdXQgd2hlbiBlbmNvdW50ZXJpbmcgYW5cbiAgLy8gb2JqZWN0IHRoYXQgaXMgYWxyZWFkeSBvbiB0aGUgXCJzdGFja1wiIG9mIGl0ZW1zIGJlaW5nIHByb2Nlc3NlZC4gQWNjZXB0cyBhbiBvcHRpb25hbCByZXBsYWNlclxuICBmdW5jdGlvbiBjYW5vbmljYWxpemUob2JqLCBzdGFjaywgcmVwbGFjZW1lbnRTdGFjaywgcmVwbGFjZXIsIGtleSkge1xuICAgIHN0YWNrID0gc3RhY2sgfHwgW107XG4gICAgcmVwbGFjZW1lbnRTdGFjayA9IHJlcGxhY2VtZW50U3RhY2sgfHwgW107XG4gICAgaWYgKHJlcGxhY2VyKSB7XG4gICAgICBvYmogPSByZXBsYWNlcihrZXksIG9iaik7XG4gICAgfVxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCBzdGFjay5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgaWYgKHN0YWNrW2ldID09PSBvYmopIHtcbiAgICAgICAgcmV0dXJuIHJlcGxhY2VtZW50U3RhY2tbaV07XG4gICAgICB9XG4gICAgfVxuICAgIHZhciBjYW5vbmljYWxpemVkT2JqO1xuICAgIGlmICgnW29iamVjdCBBcnJheV0nID09PSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKSkge1xuICAgICAgc3RhY2sucHVzaChvYmopO1xuICAgICAgY2Fub25pY2FsaXplZE9iaiA9IG5ldyBBcnJheShvYmoubGVuZ3RoKTtcbiAgICAgIHJlcGxhY2VtZW50U3RhY2sucHVzaChjYW5vbmljYWxpemVkT2JqKTtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCBvYmoubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgY2Fub25pY2FsaXplZE9ialtpXSA9IGNhbm9uaWNhbGl6ZShvYmpbaV0sIHN0YWNrLCByZXBsYWNlbWVudFN0YWNrLCByZXBsYWNlciwga2V5KTtcbiAgICAgIH1cbiAgICAgIHN0YWNrLnBvcCgpO1xuICAgICAgcmVwbGFjZW1lbnRTdGFjay5wb3AoKTtcbiAgICAgIHJldHVybiBjYW5vbmljYWxpemVkT2JqO1xuICAgIH1cbiAgICBpZiAob2JqICYmIG9iai50b0pTT04pIHtcbiAgICAgIG9iaiA9IG9iai50b0pTT04oKTtcbiAgICB9XG4gICAgaWYgKF90eXBlb2Yob2JqKSA9PT0gJ29iamVjdCcgJiYgb2JqICE9PSBudWxsKSB7XG4gICAgICBzdGFjay5wdXNoKG9iaik7XG4gICAgICBjYW5vbmljYWxpemVkT2JqID0ge307XG4gICAgICByZXBsYWNlbWVudFN0YWNrLnB1c2goY2Fub25pY2FsaXplZE9iaik7XG4gICAgICB2YXIgc29ydGVkS2V5cyA9IFtdLFxuICAgICAgICBfa2V5O1xuICAgICAgZm9yIChfa2V5IGluIG9iaikge1xuICAgICAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgZWxzZSAqL1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgX2tleSkpIHtcbiAgICAgICAgICBzb3J0ZWRLZXlzLnB1c2goX2tleSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHNvcnRlZEtleXMuc29ydCgpO1xuICAgICAgZm9yIChpID0gMDsgaSA8IHNvcnRlZEtleXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgX2tleSA9IHNvcnRlZEtleXNbaV07XG4gICAgICAgIGNhbm9uaWNhbGl6ZWRPYmpbX2tleV0gPSBjYW5vbmljYWxpemUob2JqW19rZXldLCBzdGFjaywgcmVwbGFjZW1lbnRTdGFjaywgcmVwbGFjZXIsIF9rZXkpO1xuICAgICAgfVxuICAgICAgc3RhY2sucG9wKCk7XG4gICAgICByZXBsYWNlbWVudFN0YWNrLnBvcCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjYW5vbmljYWxpemVkT2JqID0gb2JqO1xuICAgIH1cbiAgICByZXR1cm4gY2Fub25pY2FsaXplZE9iajtcbiAgfVxuXG4gIHZhciBhcnJheURpZmYgPSBuZXcgRGlmZigpO1xuICBhcnJheURpZmYudG9rZW5pemUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUuc2xpY2UoKTtcbiAgfTtcbiAgYXJyYXlEaWZmLmpvaW4gPSBhcnJheURpZmYucmVtb3ZlRW1wdHkgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH07XG4gIGZ1bmN0aW9uIGRpZmZBcnJheXMob2xkQXJyLCBuZXdBcnIsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIGFycmF5RGlmZi5kaWZmKG9sZEFyciwgbmV3QXJyLCBjYWxsYmFjayk7XG4gIH1cblxuICBmdW5jdGlvbiB1bml4VG9XaW4ocGF0Y2gpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShwYXRjaCkpIHtcbiAgICAgIHJldHVybiBwYXRjaC5tYXAodW5peFRvV2luKTtcbiAgICB9XG4gICAgcmV0dXJuIF9vYmplY3RTcHJlYWQyKF9vYmplY3RTcHJlYWQyKHt9LCBwYXRjaCksIHt9LCB7XG4gICAgICBodW5rczogcGF0Y2guaHVua3MubWFwKGZ1bmN0aW9uIChodW5rKSB7XG4gICAgICAgIHJldHVybiBfb2JqZWN0U3ByZWFkMihfb2JqZWN0U3ByZWFkMih7fSwgaHVuayksIHt9LCB7XG4gICAgICAgICAgbGluZXM6IGh1bmsubGluZXMubWFwKGZ1bmN0aW9uIChsaW5lLCBpKSB7XG4gICAgICAgICAgICB2YXIgX2h1bmskbGluZXM7XG4gICAgICAgICAgICByZXR1cm4gbGluZS5zdGFydHNXaXRoKCdcXFxcJykgfHwgbGluZS5lbmRzV2l0aCgnXFxyJykgfHwgKF9odW5rJGxpbmVzID0gaHVuay5saW5lc1tpICsgMV0pICE9PSBudWxsICYmIF9odW5rJGxpbmVzICE9PSB2b2lkIDAgJiYgX2h1bmskbGluZXMuc3RhcnRzV2l0aCgnXFxcXCcpID8gbGluZSA6IGxpbmUgKyAnXFxyJztcbiAgICAgICAgICB9KVxuICAgICAgICB9KTtcbiAgICAgIH0pXG4gICAgfSk7XG4gIH1cbiAgZnVuY3Rpb24gd2luVG9Vbml4KHBhdGNoKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkocGF0Y2gpKSB7XG4gICAgICByZXR1cm4gcGF0Y2gubWFwKHdpblRvVW5peCk7XG4gICAgfVxuICAgIHJldHVybiBfb2JqZWN0U3ByZWFkMihfb2JqZWN0U3ByZWFkMih7fSwgcGF0Y2gpLCB7fSwge1xuICAgICAgaHVua3M6IHBhdGNoLmh1bmtzLm1hcChmdW5jdGlvbiAoaHVuaykge1xuICAgICAgICByZXR1cm4gX29iamVjdFNwcmVhZDIoX29iamVjdFNwcmVhZDIoe30sIGh1bmspLCB7fSwge1xuICAgICAgICAgIGxpbmVzOiBodW5rLmxpbmVzLm1hcChmdW5jdGlvbiAobGluZSkge1xuICAgICAgICAgICAgcmV0dXJuIGxpbmUuZW5kc1dpdGgoJ1xccicpID8gbGluZS5zdWJzdHJpbmcoMCwgbGluZS5sZW5ndGggLSAxKSA6IGxpbmU7XG4gICAgICAgICAgfSlcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgcGF0Y2ggY29uc2lzdGVudGx5IHVzZXMgVW5peCBsaW5lIGVuZGluZ3MgKG9yIG9ubHkgaW52b2x2ZXMgb25lIGxpbmUgYW5kIGhhc1xuICAgKiBubyBsaW5lIGVuZGluZ3MpLlxuICAgKi9cbiAgZnVuY3Rpb24gaXNVbml4KHBhdGNoKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHBhdGNoKSkge1xuICAgICAgcGF0Y2ggPSBbcGF0Y2hdO1xuICAgIH1cbiAgICByZXR1cm4gIXBhdGNoLnNvbWUoZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgICByZXR1cm4gaW5kZXguaHVua3Muc29tZShmdW5jdGlvbiAoaHVuaykge1xuICAgICAgICByZXR1cm4gaHVuay5saW5lcy5zb21lKGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgICAgcmV0dXJuICFsaW5lLnN0YXJ0c1dpdGgoJ1xcXFwnKSAmJiBsaW5lLmVuZHNXaXRoKCdcXHInKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHBhdGNoIHVzZXMgV2luZG93cyBsaW5lIGVuZGluZ3MgYW5kIG9ubHkgV2luZG93cyBsaW5lIGVuZGluZ3MuXG4gICAqL1xuICBmdW5jdGlvbiBpc1dpbihwYXRjaCkge1xuICAgIGlmICghQXJyYXkuaXNBcnJheShwYXRjaCkpIHtcbiAgICAgIHBhdGNoID0gW3BhdGNoXTtcbiAgICB9XG4gICAgcmV0dXJuIHBhdGNoLnNvbWUoZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgICByZXR1cm4gaW5kZXguaHVua3Muc29tZShmdW5jdGlvbiAoaHVuaykge1xuICAgICAgICByZXR1cm4gaHVuay5saW5lcy5zb21lKGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICAgICAgcmV0dXJuIGxpbmUuZW5kc1dpdGgoJ1xccicpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pICYmIHBhdGNoLmV2ZXJ5KGZ1bmN0aW9uIChpbmRleCkge1xuICAgICAgcmV0dXJuIGluZGV4Lmh1bmtzLmV2ZXJ5KGZ1bmN0aW9uIChodW5rKSB7XG4gICAgICAgIHJldHVybiBodW5rLmxpbmVzLmV2ZXJ5KGZ1bmN0aW9uIChsaW5lLCBpKSB7XG4gICAgICAgICAgdmFyIF9odW5rJGxpbmVzMjtcbiAgICAgICAgICByZXR1cm4gbGluZS5zdGFydHNXaXRoKCdcXFxcJykgfHwgbGluZS5lbmRzV2l0aCgnXFxyJykgfHwgKChfaHVuayRsaW5lczIgPSBodW5rLmxpbmVzW2kgKyAxXSkgPT09IG51bGwgfHwgX2h1bmskbGluZXMyID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfaHVuayRsaW5lczIuc3RhcnRzV2l0aCgnXFxcXCcpKTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlUGF0Y2godW5pRGlmZikge1xuICAgIHZhciBkaWZmc3RyID0gdW5pRGlmZi5zcGxpdCgvXFxuLyksXG4gICAgICBsaXN0ID0gW10sXG4gICAgICBpID0gMDtcbiAgICBmdW5jdGlvbiBwYXJzZUluZGV4KCkge1xuICAgICAgdmFyIGluZGV4ID0ge307XG4gICAgICBsaXN0LnB1c2goaW5kZXgpO1xuXG4gICAgICAvLyBQYXJzZSBkaWZmIG1ldGFkYXRhXG4gICAgICB3aGlsZSAoaSA8IGRpZmZzdHIubGVuZ3RoKSB7XG4gICAgICAgIHZhciBsaW5lID0gZGlmZnN0cltpXTtcblxuICAgICAgICAvLyBGaWxlIGhlYWRlciBmb3VuZCwgZW5kIHBhcnNpbmcgZGlmZiBtZXRhZGF0YVxuICAgICAgICBpZiAoL14oXFwtXFwtXFwtfFxcK1xcK1xcK3xAQClcXHMvLnRlc3QobGluZSkpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERpZmYgaW5kZXhcbiAgICAgICAgdmFyIGhlYWRlciA9IC9eKD86SW5kZXg6fGRpZmYoPzogLXIgXFx3KykrKVxccysoLis/KVxccyokLy5leGVjKGxpbmUpO1xuICAgICAgICBpZiAoaGVhZGVyKSB7XG4gICAgICAgICAgaW5kZXguaW5kZXggPSBoZWFkZXJbMV07XG4gICAgICAgIH1cbiAgICAgICAgaSsrO1xuICAgICAgfVxuXG4gICAgICAvLyBQYXJzZSBmaWxlIGhlYWRlcnMgaWYgdGhleSBhcmUgZGVmaW5lZC4gVW5pZmllZCBkaWZmIHJlcXVpcmVzIHRoZW0sIGJ1dFxuICAgICAgLy8gdGhlcmUncyBubyB0ZWNobmljYWwgaXNzdWVzIHRvIGhhdmUgYW4gaXNvbGF0ZWQgaHVuayB3aXRob3V0IGZpbGUgaGVhZGVyXG4gICAgICBwYXJzZUZpbGVIZWFkZXIoaW5kZXgpO1xuICAgICAgcGFyc2VGaWxlSGVhZGVyKGluZGV4KTtcblxuICAgICAgLy8gUGFyc2UgaHVua3NcbiAgICAgIGluZGV4Lmh1bmtzID0gW107XG4gICAgICB3aGlsZSAoaSA8IGRpZmZzdHIubGVuZ3RoKSB7XG4gICAgICAgIHZhciBfbGluZSA9IGRpZmZzdHJbaV07XG4gICAgICAgIGlmICgvXihJbmRleDpcXHN8ZGlmZlxcc3xcXC1cXC1cXC1cXHN8XFwrXFwrXFwrXFxzfD09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0pLy50ZXN0KF9saW5lKSkge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9IGVsc2UgaWYgKC9eQEAvLnRlc3QoX2xpbmUpKSB7XG4gICAgICAgICAgaW5kZXguaHVua3MucHVzaChwYXJzZUh1bmsoKSk7XG4gICAgICAgIH0gZWxzZSBpZiAoX2xpbmUpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gbGluZSAnICsgKGkgKyAxKSArICcgJyArIEpTT04uc3RyaW5naWZ5KF9saW5lKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaSsrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gUGFyc2VzIHRoZSAtLS0gYW5kICsrKyBoZWFkZXJzLCBpZiBub25lIGFyZSBmb3VuZCwgbm8gbGluZXNcbiAgICAvLyBhcmUgY29uc3VtZWQuXG4gICAgZnVuY3Rpb24gcGFyc2VGaWxlSGVhZGVyKGluZGV4KSB7XG4gICAgICB2YXIgZmlsZUhlYWRlciA9IC9eKC0tLXxcXCtcXCtcXCspXFxzKyguKilcXHI/JC8uZXhlYyhkaWZmc3RyW2ldKTtcbiAgICAgIGlmIChmaWxlSGVhZGVyKSB7XG4gICAgICAgIHZhciBrZXlQcmVmaXggPSBmaWxlSGVhZGVyWzFdID09PSAnLS0tJyA/ICdvbGQnIDogJ25ldyc7XG4gICAgICAgIHZhciBkYXRhID0gZmlsZUhlYWRlclsyXS5zcGxpdCgnXFx0JywgMik7XG4gICAgICAgIHZhciBmaWxlTmFtZSA9IGRhdGFbMF0ucmVwbGFjZSgvXFxcXFxcXFwvZywgJ1xcXFwnKTtcbiAgICAgICAgaWYgKC9eXCIuKlwiJC8udGVzdChmaWxlTmFtZSkpIHtcbiAgICAgICAgICBmaWxlTmFtZSA9IGZpbGVOYW1lLnN1YnN0cigxLCBmaWxlTmFtZS5sZW5ndGggLSAyKTtcbiAgICAgICAgfVxuICAgICAgICBpbmRleFtrZXlQcmVmaXggKyAnRmlsZU5hbWUnXSA9IGZpbGVOYW1lO1xuICAgICAgICBpbmRleFtrZXlQcmVmaXggKyAnSGVhZGVyJ10gPSAoZGF0YVsxXSB8fCAnJykudHJpbSgpO1xuICAgICAgICBpKys7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gUGFyc2VzIGEgaHVua1xuICAgIC8vIFRoaXMgYXNzdW1lcyB0aGF0IHdlIGFyZSBhdCB0aGUgc3RhcnQgb2YgYSBodW5rLlxuICAgIGZ1bmN0aW9uIHBhcnNlSHVuaygpIHtcbiAgICAgIHZhciBjaHVua0hlYWRlckluZGV4ID0gaSxcbiAgICAgICAgY2h1bmtIZWFkZXJMaW5lID0gZGlmZnN0cltpKytdLFxuICAgICAgICBjaHVua0hlYWRlciA9IGNodW5rSGVhZGVyTGluZS5zcGxpdCgvQEAgLShcXGQrKSg/OiwoXFxkKykpPyBcXCsoXFxkKykoPzosKFxcZCspKT8gQEAvKTtcbiAgICAgIHZhciBodW5rID0ge1xuICAgICAgICBvbGRTdGFydDogK2NodW5rSGVhZGVyWzFdLFxuICAgICAgICBvbGRMaW5lczogdHlwZW9mIGNodW5rSGVhZGVyWzJdID09PSAndW5kZWZpbmVkJyA/IDEgOiArY2h1bmtIZWFkZXJbMl0sXG4gICAgICAgIG5ld1N0YXJ0OiArY2h1bmtIZWFkZXJbM10sXG4gICAgICAgIG5ld0xpbmVzOiB0eXBlb2YgY2h1bmtIZWFkZXJbNF0gPT09ICd1bmRlZmluZWQnID8gMSA6ICtjaHVua0hlYWRlcls0XSxcbiAgICAgICAgbGluZXM6IFtdXG4gICAgICB9O1xuXG4gICAgICAvLyBVbmlmaWVkIERpZmYgRm9ybWF0IHF1aXJrOiBJZiB0aGUgY2h1bmsgc2l6ZSBpcyAwLFxuICAgICAgLy8gdGhlIGZpcnN0IG51bWJlciBpcyBvbmUgbG93ZXIgdGhhbiBvbmUgd291bGQgZXhwZWN0LlxuICAgICAgLy8gaHR0cHM6Ly93d3cuYXJ0aW1hLmNvbS93ZWJsb2dzL3ZpZXdwb3N0LmpzcD90aHJlYWQ9MTY0MjkzXG4gICAgICBpZiAoaHVuay5vbGRMaW5lcyA9PT0gMCkge1xuICAgICAgICBodW5rLm9sZFN0YXJ0ICs9IDE7XG4gICAgICB9XG4gICAgICBpZiAoaHVuay5uZXdMaW5lcyA9PT0gMCkge1xuICAgICAgICBodW5rLm5ld1N0YXJ0ICs9IDE7XG4gICAgICB9XG4gICAgICB2YXIgYWRkQ291bnQgPSAwLFxuICAgICAgICByZW1vdmVDb3VudCA9IDA7XG4gICAgICBmb3IgKDsgaSA8IGRpZmZzdHIubGVuZ3RoICYmIChyZW1vdmVDb3VudCA8IGh1bmsub2xkTGluZXMgfHwgYWRkQ291bnQgPCBodW5rLm5ld0xpbmVzIHx8IChfZGlmZnN0ciRpID0gZGlmZnN0cltpXSkgIT09IG51bGwgJiYgX2RpZmZzdHIkaSAhPT0gdm9pZCAwICYmIF9kaWZmc3RyJGkuc3RhcnRzV2l0aCgnXFxcXCcpKTsgaSsrKSB7XG4gICAgICAgIHZhciBfZGlmZnN0ciRpO1xuICAgICAgICB2YXIgb3BlcmF0aW9uID0gZGlmZnN0cltpXS5sZW5ndGggPT0gMCAmJiBpICE9IGRpZmZzdHIubGVuZ3RoIC0gMSA/ICcgJyA6IGRpZmZzdHJbaV1bMF07XG4gICAgICAgIGlmIChvcGVyYXRpb24gPT09ICcrJyB8fCBvcGVyYXRpb24gPT09ICctJyB8fCBvcGVyYXRpb24gPT09ICcgJyB8fCBvcGVyYXRpb24gPT09ICdcXFxcJykge1xuICAgICAgICAgIGh1bmsubGluZXMucHVzaChkaWZmc3RyW2ldKTtcbiAgICAgICAgICBpZiAob3BlcmF0aW9uID09PSAnKycpIHtcbiAgICAgICAgICAgIGFkZENvdW50Kys7XG4gICAgICAgICAgfSBlbHNlIGlmIChvcGVyYXRpb24gPT09ICctJykge1xuICAgICAgICAgICAgcmVtb3ZlQ291bnQrKztcbiAgICAgICAgICB9IGVsc2UgaWYgKG9wZXJhdGlvbiA9PT0gJyAnKSB7XG4gICAgICAgICAgICBhZGRDb3VudCsrO1xuICAgICAgICAgICAgcmVtb3ZlQ291bnQrKztcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSHVuayBhdCBsaW5lIFwiLmNvbmNhdChjaHVua0hlYWRlckluZGV4ICsgMSwgXCIgY29udGFpbmVkIGludmFsaWQgbGluZSBcIikuY29uY2F0KGRpZmZzdHJbaV0pKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBIYW5kbGUgdGhlIGVtcHR5IGJsb2NrIGNvdW50IGNhc2VcbiAgICAgIGlmICghYWRkQ291bnQgJiYgaHVuay5uZXdMaW5lcyA9PT0gMSkge1xuICAgICAgICBodW5rLm5ld0xpbmVzID0gMDtcbiAgICAgIH1cbiAgICAgIGlmICghcmVtb3ZlQ291bnQgJiYgaHVuay5vbGRMaW5lcyA9PT0gMSkge1xuICAgICAgICBodW5rLm9sZExpbmVzID0gMDtcbiAgICAgIH1cblxuICAgICAgLy8gUGVyZm9ybSBzYW5pdHkgY2hlY2tpbmdcbiAgICAgIGlmIChhZGRDb3VudCAhPT0gaHVuay5uZXdMaW5lcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0FkZGVkIGxpbmUgY291bnQgZGlkIG5vdCBtYXRjaCBmb3IgaHVuayBhdCBsaW5lICcgKyAoY2h1bmtIZWFkZXJJbmRleCArIDEpKTtcbiAgICAgIH1cbiAgICAgIGlmIChyZW1vdmVDb3VudCAhPT0gaHVuay5vbGRMaW5lcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlbW92ZWQgbGluZSBjb3VudCBkaWQgbm90IG1hdGNoIGZvciBodW5rIGF0IGxpbmUgJyArIChjaHVua0hlYWRlckluZGV4ICsgMSkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGh1bms7XG4gICAgfVxuICAgIHdoaWxlIChpIDwgZGlmZnN0ci5sZW5ndGgpIHtcbiAgICAgIHBhcnNlSW5kZXgoKTtcbiAgICB9XG4gICAgcmV0dXJuIGxpc3Q7XG4gIH1cblxuICAvLyBJdGVyYXRvciB0aGF0IHRyYXZlcnNlcyBpbiB0aGUgcmFuZ2Ugb2YgW21pbiwgbWF4XSwgc3RlcHBpbmdcbiAgLy8gYnkgZGlzdGFuY2UgZnJvbSBhIGdpdmVuIHN0YXJ0IHBvc2l0aW9uLiBJLmUuIGZvciBbMCwgNF0sIHdpdGhcbiAgLy8gc3RhcnQgb2YgMiwgdGhpcyB3aWxsIGl0ZXJhdGUgMiwgMywgMSwgNCwgMC5cbiAgZnVuY3Rpb24gZGlzdGFuY2VJdGVyYXRvciAoc3RhcnQsIG1pbkxpbmUsIG1heExpbmUpIHtcbiAgICB2YXIgd2FudEZvcndhcmQgPSB0cnVlLFxuICAgICAgYmFja3dhcmRFeGhhdXN0ZWQgPSBmYWxzZSxcbiAgICAgIGZvcndhcmRFeGhhdXN0ZWQgPSBmYWxzZSxcbiAgICAgIGxvY2FsT2Zmc2V0ID0gMTtcbiAgICByZXR1cm4gZnVuY3Rpb24gaXRlcmF0b3IoKSB7XG4gICAgICBpZiAod2FudEZvcndhcmQgJiYgIWZvcndhcmRFeGhhdXN0ZWQpIHtcbiAgICAgICAgaWYgKGJhY2t3YXJkRXhoYXVzdGVkKSB7XG4gICAgICAgICAgbG9jYWxPZmZzZXQrKztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB3YW50Rm9yd2FyZCA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgdHJ5aW5nIHRvIGZpdCBiZXlvbmQgdGV4dCBsZW5ndGgsIGFuZCBpZiBub3QsIGNoZWNrIGl0IGZpdHNcbiAgICAgICAgLy8gYWZ0ZXIgb2Zmc2V0IGxvY2F0aW9uIChvciBkZXNpcmVkIGxvY2F0aW9uIG9uIGZpcnN0IGl0ZXJhdGlvbilcbiAgICAgICAgaWYgKHN0YXJ0ICsgbG9jYWxPZmZzZXQgPD0gbWF4TGluZSkge1xuICAgICAgICAgIHJldHVybiBzdGFydCArIGxvY2FsT2Zmc2V0O1xuICAgICAgICB9XG4gICAgICAgIGZvcndhcmRFeGhhdXN0ZWQgPSB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKCFiYWNrd2FyZEV4aGF1c3RlZCkge1xuICAgICAgICBpZiAoIWZvcndhcmRFeGhhdXN0ZWQpIHtcbiAgICAgICAgICB3YW50Rm9yd2FyZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayBpZiB0cnlpbmcgdG8gZml0IGJlZm9yZSB0ZXh0IGJlZ2lubmluZywgYW5kIGlmIG5vdCwgY2hlY2sgaXQgZml0c1xuICAgICAgICAvLyBiZWZvcmUgb2Zmc2V0IGxvY2F0aW9uXG4gICAgICAgIGlmIChtaW5MaW5lIDw9IHN0YXJ0IC0gbG9jYWxPZmZzZXQpIHtcbiAgICAgICAgICByZXR1cm4gc3RhcnQgLSBsb2NhbE9mZnNldCsrO1xuICAgICAgICB9XG4gICAgICAgIGJhY2t3YXJkRXhoYXVzdGVkID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIGl0ZXJhdG9yKCk7XG4gICAgICB9XG5cbiAgICAgIC8vIFdlIHRyaWVkIHRvIGZpdCBodW5rIGJlZm9yZSB0ZXh0IGJlZ2lubmluZyBhbmQgYmV5b25kIHRleHQgbGVuZ3RoLCB0aGVuXG4gICAgICAvLyBodW5rIGNhbid0IGZpdCBvbiB0aGUgdGV4dC4gUmV0dXJuIHVuZGVmaW5lZFxuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiBhcHBseVBhdGNoKHNvdXJjZSwgdW5pRGlmZikge1xuICAgIHZhciBvcHRpb25zID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiB7fTtcbiAgICBpZiAodHlwZW9mIHVuaURpZmYgPT09ICdzdHJpbmcnKSB7XG4gICAgICB1bmlEaWZmID0gcGFyc2VQYXRjaCh1bmlEaWZmKTtcbiAgICB9XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodW5pRGlmZikpIHtcbiAgICAgIGlmICh1bmlEaWZmLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdhcHBseVBhdGNoIG9ubHkgd29ya3Mgd2l0aCBhIHNpbmdsZSBpbnB1dC4nKTtcbiAgICAgIH1cbiAgICAgIHVuaURpZmYgPSB1bmlEaWZmWzBdO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy5hdXRvQ29udmVydExpbmVFbmRpbmdzIHx8IG9wdGlvbnMuYXV0b0NvbnZlcnRMaW5lRW5kaW5ncyA9PSBudWxsKSB7XG4gICAgICBpZiAoaGFzT25seVdpbkxpbmVFbmRpbmdzKHNvdXJjZSkgJiYgaXNVbml4KHVuaURpZmYpKSB7XG4gICAgICAgIHVuaURpZmYgPSB1bml4VG9XaW4odW5pRGlmZik7XG4gICAgICB9IGVsc2UgaWYgKGhhc09ubHlVbml4TGluZUVuZGluZ3Moc291cmNlKSAmJiBpc1dpbih1bmlEaWZmKSkge1xuICAgICAgICB1bmlEaWZmID0gd2luVG9Vbml4KHVuaURpZmYpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFwcGx5IHRoZSBkaWZmIHRvIHRoZSBpbnB1dFxuICAgIHZhciBsaW5lcyA9IHNvdXJjZS5zcGxpdCgnXFxuJyksXG4gICAgICBodW5rcyA9IHVuaURpZmYuaHVua3MsXG4gICAgICBjb21wYXJlTGluZSA9IG9wdGlvbnMuY29tcGFyZUxpbmUgfHwgZnVuY3Rpb24gKGxpbmVOdW1iZXIsIGxpbmUsIG9wZXJhdGlvbiwgcGF0Y2hDb250ZW50KSB7XG4gICAgICAgIHJldHVybiBsaW5lID09PSBwYXRjaENvbnRlbnQ7XG4gICAgICB9LFxuICAgICAgZnV6ekZhY3RvciA9IG9wdGlvbnMuZnV6ekZhY3RvciB8fCAwLFxuICAgICAgbWluTGluZSA9IDA7XG4gICAgaWYgKGZ1enpGYWN0b3IgPCAwIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKGZ1enpGYWN0b3IpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2Z1enpGYWN0b3IgbXVzdCBiZSBhIG5vbi1uZWdhdGl2ZSBpbnRlZ2VyJyk7XG4gICAgfVxuXG4gICAgLy8gU3BlY2lhbCBjYXNlIGZvciBlbXB0eSBwYXRjaC5cbiAgICBpZiAoIWh1bmtzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9XG5cbiAgICAvLyBCZWZvcmUgYW55dGhpbmcgZWxzZSwgaGFuZGxlIEVPRk5MIGluc2VydGlvbi9yZW1vdmFsLiBJZiB0aGUgcGF0Y2ggdGVsbHMgdXMgdG8gbWFrZSBhIGNoYW5nZVxuICAgIC8vIHRvIHRoZSBFT0ZOTCB0aGF0IGlzIHJlZHVuZGFudC9pbXBvc3NpYmxlIC0gaS5lLiB0byByZW1vdmUgYSBuZXdsaW5lIHRoYXQncyBub3QgdGhlcmUsIG9yIGFkZCBhXG4gICAgLy8gbmV3bGluZSB0aGF0IGFscmVhZHkgZXhpc3RzIC0gdGhlbiB3ZSBlaXRoZXIgcmV0dXJuIGZhbHNlIGFuZCBmYWlsIHRvIGFwcGx5IHRoZSBwYXRjaCAoaWZcbiAgICAvLyBmdXp6RmFjdG9yIGlzIDApIG9yIHNpbXBseSBpZ25vcmUgdGhlIHByb2JsZW0gYW5kIGRvIG5vdGhpbmcgKGlmIGZ1enpGYWN0b3IgaXMgPjApLlxuICAgIC8vIElmIHdlIGRvIG5lZWQgdG8gcmVtb3ZlL2FkZCBhIG5ld2xpbmUgYXQgRU9GLCB0aGlzIHdpbGwgYWx3YXlzIGJlIGluIHRoZSBmaW5hbCBodW5rOlxuICAgIHZhciBwcmV2TGluZSA9ICcnLFxuICAgICAgcmVtb3ZlRU9GTkwgPSBmYWxzZSxcbiAgICAgIGFkZEVPRk5MID0gZmFsc2U7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBodW5rc1todW5rcy5sZW5ndGggLSAxXS5saW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGxpbmUgPSBodW5rc1todW5rcy5sZW5ndGggLSAxXS5saW5lc1tpXTtcbiAgICAgIGlmIChsaW5lWzBdID09ICdcXFxcJykge1xuICAgICAgICBpZiAocHJldkxpbmVbMF0gPT0gJysnKSB7XG4gICAgICAgICAgcmVtb3ZlRU9GTkwgPSB0cnVlO1xuICAgICAgICB9IGVsc2UgaWYgKHByZXZMaW5lWzBdID09ICctJykge1xuICAgICAgICAgIGFkZEVPRk5MID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcHJldkxpbmUgPSBsaW5lO1xuICAgIH1cbiAgICBpZiAocmVtb3ZlRU9GTkwpIHtcbiAgICAgIGlmIChhZGRFT0ZOTCkge1xuICAgICAgICAvLyBUaGlzIG1lYW5zIHRoZSBmaW5hbCBsaW5lIGdldHMgY2hhbmdlZCBidXQgZG9lc24ndCBoYXZlIGEgdHJhaWxpbmcgbmV3bGluZSBpbiBlaXRoZXIgdGhlXG4gICAgICAgIC8vIG9yaWdpbmFsIG9yIHBhdGNoZWQgdmVyc2lvbi4gSW4gdGhhdCBjYXNlLCB3ZSBkbyBub3RoaW5nIGlmIGZ1enpGYWN0b3IgPiAwLCBhbmQgaWZcbiAgICAgICAgLy8gZnV6ekZhY3RvciBpcyAwLCB3ZSBzaW1wbHkgdmFsaWRhdGUgdGhhdCB0aGUgc291cmNlIGZpbGUgaGFzIG5vIHRyYWlsaW5nIG5ld2xpbmUuXG4gICAgICAgIGlmICghZnV6ekZhY3RvciAmJiBsaW5lc1tsaW5lcy5sZW5ndGggLSAxXSA9PSAnJykge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChsaW5lc1tsaW5lcy5sZW5ndGggLSAxXSA9PSAnJykge1xuICAgICAgICBsaW5lcy5wb3AoKTtcbiAgICAgIH0gZWxzZSBpZiAoIWZ1enpGYWN0b3IpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoYWRkRU9GTkwpIHtcbiAgICAgIGlmIChsaW5lc1tsaW5lcy5sZW5ndGggLSAxXSAhPSAnJykge1xuICAgICAgICBsaW5lcy5wdXNoKCcnKTtcbiAgICAgIH0gZWxzZSBpZiAoIWZ1enpGYWN0b3IpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyBpZiB0aGUgaHVuayBjYW4gYmUgbWFkZSB0byBmaXQgYXQgdGhlIHByb3ZpZGVkIGxvY2F0aW9uIHdpdGggYXQgbW9zdCBgbWF4RXJyb3JzYFxuICAgICAqIGluc2VydGlvbnMsIHN1YnN0aXR1dGlvbnMsIG9yIGRlbGV0aW9ucywgd2hpbGUgZW5zdXJpbmcgYWxzbyB0aGF0OlxuICAgICAqIC0gbGluZXMgZGVsZXRlZCBpbiB0aGUgaHVuayBtYXRjaCBleGFjdGx5LCBhbmRcbiAgICAgKiAtIHdoZXJldmVyIGFuIGluc2VydGlvbiBvcGVyYXRpb24gb3IgYmxvY2sgb2YgaW5zZXJ0aW9uIG9wZXJhdGlvbnMgYXBwZWFycyBpbiB0aGUgaHVuaywgdGhlXG4gICAgICogICBpbW1lZGlhdGVseSBwcmVjZWRpbmcgYW5kIGZvbGxvd2luZyBsaW5lcyBvZiBjb250ZXh0IG1hdGNoIGV4YWN0bHlcbiAgICAgKlxuICAgICAqIGB0b1Bvc2Agc2hvdWxkIGJlIHNldCBzdWNoIHRoYXQgbGluZXNbdG9Qb3NdIGlzIG1lYW50IHRvIG1hdGNoIGh1bmtMaW5lc1swXS5cbiAgICAgKlxuICAgICAqIElmIHRoZSBodW5rIGNhbiBiZSBhcHBsaWVkLCByZXR1cm5zIGFuIG9iamVjdCB3aXRoIHByb3BlcnRpZXMgYG9sZExpbmVMYXN0SWAgYW5kXG4gICAgICogYHJlcGxhY2VtZW50TGluZXNgLiBPdGhlcndpc2UsIHJldHVybnMgbnVsbC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBhcHBseUh1bmsoaHVua0xpbmVzLCB0b1BvcywgbWF4RXJyb3JzKSB7XG4gICAgICB2YXIgaHVua0xpbmVzSSA9IGFyZ3VtZW50cy5sZW5ndGggPiAzICYmIGFyZ3VtZW50c1szXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzNdIDogMDtcbiAgICAgIHZhciBsYXN0Q29udGV4dExpbmVNYXRjaGVkID0gYXJndW1lbnRzLmxlbmd0aCA+IDQgJiYgYXJndW1lbnRzWzRdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbNF0gOiB0cnVlO1xuICAgICAgdmFyIHBhdGNoZWRMaW5lcyA9IGFyZ3VtZW50cy5sZW5ndGggPiA1ICYmIGFyZ3VtZW50c1s1XSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzVdIDogW107XG4gICAgICB2YXIgcGF0Y2hlZExpbmVzTGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aCA+IDYgJiYgYXJndW1lbnRzWzZdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbNl0gOiAwO1xuICAgICAgdmFyIG5Db25zZWN1dGl2ZU9sZENvbnRleHRMaW5lcyA9IDA7XG4gICAgICB2YXIgbmV4dENvbnRleHRMaW5lTXVzdE1hdGNoID0gZmFsc2U7XG4gICAgICBmb3IgKDsgaHVua0xpbmVzSSA8IGh1bmtMaW5lcy5sZW5ndGg7IGh1bmtMaW5lc0krKykge1xuICAgICAgICB2YXIgaHVua0xpbmUgPSBodW5rTGluZXNbaHVua0xpbmVzSV0sXG4gICAgICAgICAgb3BlcmF0aW9uID0gaHVua0xpbmUubGVuZ3RoID4gMCA/IGh1bmtMaW5lWzBdIDogJyAnLFxuICAgICAgICAgIGNvbnRlbnQgPSBodW5rTGluZS5sZW5ndGggPiAwID8gaHVua0xpbmUuc3Vic3RyKDEpIDogaHVua0xpbmU7XG4gICAgICAgIGlmIChvcGVyYXRpb24gPT09ICctJykge1xuICAgICAgICAgIGlmIChjb21wYXJlTGluZSh0b1BvcyArIDEsIGxpbmVzW3RvUG9zXSwgb3BlcmF0aW9uLCBjb250ZW50KSkge1xuICAgICAgICAgICAgdG9Qb3MrKztcbiAgICAgICAgICAgIG5Db25zZWN1dGl2ZU9sZENvbnRleHRMaW5lcyA9IDA7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghbWF4RXJyb3JzIHx8IGxpbmVzW3RvUG9zXSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcGF0Y2hlZExpbmVzW3BhdGNoZWRMaW5lc0xlbmd0aF0gPSBsaW5lc1t0b1Bvc107XG4gICAgICAgICAgICByZXR1cm4gYXBwbHlIdW5rKGh1bmtMaW5lcywgdG9Qb3MgKyAxLCBtYXhFcnJvcnMgLSAxLCBodW5rTGluZXNJLCBmYWxzZSwgcGF0Y2hlZExpbmVzLCBwYXRjaGVkTGluZXNMZW5ndGggKyAxKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9wZXJhdGlvbiA9PT0gJysnKSB7XG4gICAgICAgICAgaWYgKCFsYXN0Q29udGV4dExpbmVNYXRjaGVkKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcGF0Y2hlZExpbmVzW3BhdGNoZWRMaW5lc0xlbmd0aF0gPSBjb250ZW50O1xuICAgICAgICAgIHBhdGNoZWRMaW5lc0xlbmd0aCsrO1xuICAgICAgICAgIG5Db25zZWN1dGl2ZU9sZENvbnRleHRMaW5lcyA9IDA7XG4gICAgICAgICAgbmV4dENvbnRleHRMaW5lTXVzdE1hdGNoID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob3BlcmF0aW9uID09PSAnICcpIHtcbiAgICAgICAgICBuQ29uc2VjdXRpdmVPbGRDb250ZXh0TGluZXMrKztcbiAgICAgICAgICBwYXRjaGVkTGluZXNbcGF0Y2hlZExpbmVzTGVuZ3RoXSA9IGxpbmVzW3RvUG9zXTtcbiAgICAgICAgICBpZiAoY29tcGFyZUxpbmUodG9Qb3MgKyAxLCBsaW5lc1t0b1Bvc10sIG9wZXJhdGlvbiwgY29udGVudCkpIHtcbiAgICAgICAgICAgIHBhdGNoZWRMaW5lc0xlbmd0aCsrO1xuICAgICAgICAgICAgbGFzdENvbnRleHRMaW5lTWF0Y2hlZCA9IHRydWU7XG4gICAgICAgICAgICBuZXh0Q29udGV4dExpbmVNdXN0TWF0Y2ggPSBmYWxzZTtcbiAgICAgICAgICAgIHRvUG9zKys7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChuZXh0Q29udGV4dExpbmVNdXN0TWF0Y2ggfHwgIW1heEVycm9ycykge1xuICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ29uc2lkZXIgMyBwb3NzaWJpbGl0aWVzIGluIHNlcXVlbmNlOlxuICAgICAgICAgICAgLy8gMS4gbGluZXMgY29udGFpbnMgYSAqc3Vic3RpdHV0aW9uKiBub3QgaW5jbHVkZWQgaW4gdGhlIHBhdGNoIGNvbnRleHQsIG9yXG4gICAgICAgICAgICAvLyAyLiBsaW5lcyBjb250YWlucyBhbiAqaW5zZXJ0aW9uKiBub3QgaW5jbHVkZWQgaW4gdGhlIHBhdGNoIGNvbnRleHQsIG9yXG4gICAgICAgICAgICAvLyAzLiBsaW5lcyBjb250YWlucyBhICpkZWxldGlvbiogbm90IGluY2x1ZGVkIGluIHRoZSBwYXRjaCBjb250ZXh0XG4gICAgICAgICAgICAvLyBUaGUgZmlyc3QgdHdvIG9wdGlvbnMgYXJlIG9mIGNvdXJzZSBvbmx5IHBvc3NpYmxlIGlmIHRoZSBsaW5lIGZyb20gbGluZXMgaXMgbm9uLW51bGwgLVxuICAgICAgICAgICAgLy8gaS5lLiBvbmx5IG9wdGlvbiAzIGlzIHBvc3NpYmxlIGlmIHdlJ3ZlIG92ZXJydW4gdGhlIGVuZCBvZiB0aGUgb2xkIGZpbGUuXG4gICAgICAgICAgICByZXR1cm4gbGluZXNbdG9Qb3NdICYmIChhcHBseUh1bmsoaHVua0xpbmVzLCB0b1BvcyArIDEsIG1heEVycm9ycyAtIDEsIGh1bmtMaW5lc0kgKyAxLCBmYWxzZSwgcGF0Y2hlZExpbmVzLCBwYXRjaGVkTGluZXNMZW5ndGggKyAxKSB8fCBhcHBseUh1bmsoaHVua0xpbmVzLCB0b1BvcyArIDEsIG1heEVycm9ycyAtIDEsIGh1bmtMaW5lc0ksIGZhbHNlLCBwYXRjaGVkTGluZXMsIHBhdGNoZWRMaW5lc0xlbmd0aCArIDEpKSB8fCBhcHBseUh1bmsoaHVua0xpbmVzLCB0b1BvcywgbWF4RXJyb3JzIC0gMSwgaHVua0xpbmVzSSArIDEsIGZhbHNlLCBwYXRjaGVkTGluZXMsIHBhdGNoZWRMaW5lc0xlbmd0aCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIEJlZm9yZSByZXR1cm5pbmcsIHRyaW0gYW55IHVubW9kaWZpZWQgY29udGV4dCBsaW5lcyBvZmYgdGhlIGVuZCBvZiBwYXRjaGVkTGluZXMgYW5kIHJlZHVjZVxuICAgICAgLy8gdG9Qb3MgKGFuZCB0aHVzIG9sZExpbmVMYXN0SSkgYWNjb3JkaW5nbHkuIFRoaXMgYWxsb3dzIGxhdGVyIGh1bmtzIHRvIGJlIGFwcGxpZWQgdG8gYSByZWdpb25cbiAgICAgIC8vIHRoYXQgc3RhcnRzIGluIHRoaXMgaHVuaydzIHRyYWlsaW5nIGNvbnRleHQuXG4gICAgICBwYXRjaGVkTGluZXNMZW5ndGggLT0gbkNvbnNlY3V0aXZlT2xkQ29udGV4dExpbmVzO1xuICAgICAgdG9Qb3MgLT0gbkNvbnNlY3V0aXZlT2xkQ29udGV4dExpbmVzO1xuICAgICAgcGF0Y2hlZExpbmVzLmxlbmd0aCA9IHBhdGNoZWRMaW5lc0xlbmd0aDtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHBhdGNoZWRMaW5lczogcGF0Y2hlZExpbmVzLFxuICAgICAgICBvbGRMaW5lTGFzdEk6IHRvUG9zIC0gMVxuICAgICAgfTtcbiAgICB9XG4gICAgdmFyIHJlc3VsdExpbmVzID0gW107XG5cbiAgICAvLyBTZWFyY2ggYmVzdCBmaXQgb2Zmc2V0cyBmb3IgZWFjaCBodW5rIGJhc2VkIG9uIHRoZSBwcmV2aW91cyBvbmVzXG4gICAgdmFyIHByZXZIdW5rT2Zmc2V0ID0gMDtcbiAgICBmb3IgKHZhciBfaSA9IDA7IF9pIDwgaHVua3MubGVuZ3RoOyBfaSsrKSB7XG4gICAgICB2YXIgaHVuayA9IGh1bmtzW19pXTtcbiAgICAgIHZhciBodW5rUmVzdWx0ID0gdm9pZCAwO1xuICAgICAgdmFyIG1heExpbmUgPSBsaW5lcy5sZW5ndGggLSBodW5rLm9sZExpbmVzICsgZnV6ekZhY3RvcjtcbiAgICAgIHZhciB0b1BvcyA9IHZvaWQgMDtcbiAgICAgIGZvciAodmFyIG1heEVycm9ycyA9IDA7IG1heEVycm9ycyA8PSBmdXp6RmFjdG9yOyBtYXhFcnJvcnMrKykge1xuICAgICAgICB0b1BvcyA9IGh1bmsub2xkU3RhcnQgKyBwcmV2SHVua09mZnNldCAtIDE7XG4gICAgICAgIHZhciBpdGVyYXRvciA9IGRpc3RhbmNlSXRlcmF0b3IodG9Qb3MsIG1pbkxpbmUsIG1heExpbmUpO1xuICAgICAgICBmb3IgKDsgdG9Qb3MgIT09IHVuZGVmaW5lZDsgdG9Qb3MgPSBpdGVyYXRvcigpKSB7XG4gICAgICAgICAgaHVua1Jlc3VsdCA9IGFwcGx5SHVuayhodW5rLmxpbmVzLCB0b1BvcywgbWF4RXJyb3JzKTtcbiAgICAgICAgICBpZiAoaHVua1Jlc3VsdCkge1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChodW5rUmVzdWx0KSB7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICghaHVua1Jlc3VsdCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIC8vIENvcHkgZXZlcnl0aGluZyBmcm9tIHRoZSBlbmQgb2Ygd2hlcmUgd2UgYXBwbGllZCB0aGUgbGFzdCBodW5rIHRvIHRoZSBzdGFydCBvZiB0aGlzIGh1bmtcbiAgICAgIGZvciAodmFyIF9pMiA9IG1pbkxpbmU7IF9pMiA8IHRvUG9zOyBfaTIrKykge1xuICAgICAgICByZXN1bHRMaW5lcy5wdXNoKGxpbmVzW19pMl0pO1xuICAgICAgfVxuXG4gICAgICAvLyBBZGQgdGhlIGxpbmVzIHByb2R1Y2VkIGJ5IGFwcGx5aW5nIHRoZSBodW5rOlxuICAgICAgZm9yICh2YXIgX2kzID0gMDsgX2kzIDwgaHVua1Jlc3VsdC5wYXRjaGVkTGluZXMubGVuZ3RoOyBfaTMrKykge1xuICAgICAgICB2YXIgX2xpbmUgPSBodW5rUmVzdWx0LnBhdGNoZWRMaW5lc1tfaTNdO1xuICAgICAgICByZXN1bHRMaW5lcy5wdXNoKF9saW5lKTtcbiAgICAgIH1cblxuICAgICAgLy8gU2V0IGxvd2VyIHRleHQgbGltaXQgdG8gZW5kIG9mIHRoZSBjdXJyZW50IGh1bmssIHNvIG5leHQgb25lcyBkb24ndCB0cnlcbiAgICAgIC8vIHRvIGZpdCBvdmVyIGFscmVhZHkgcGF0Y2hlZCB0ZXh0XG4gICAgICBtaW5MaW5lID0gaHVua1Jlc3VsdC5vbGRMaW5lTGFzdEkgKyAxO1xuXG4gICAgICAvLyBOb3RlIHRoZSBvZmZzZXQgYmV0d2VlbiB3aGVyZSB0aGUgcGF0Y2ggc2FpZCB0aGUgaHVuayBzaG91bGQndmUgYXBwbGllZCBhbmQgd2hlcmUgd2VcbiAgICAgIC8vIGFwcGxpZWQgaXQsIHNvIHdlIGNhbiBhZGp1c3QgZnV0dXJlIGh1bmtzIGFjY29yZGluZ2x5OlxuICAgICAgcHJldkh1bmtPZmZzZXQgPSB0b1BvcyArIDEgLSBodW5rLm9sZFN0YXJ0O1xuICAgIH1cblxuICAgIC8vIENvcHkgb3ZlciB0aGUgcmVzdCBvZiB0aGUgbGluZXMgZnJvbSB0aGUgb2xkIHRleHRcbiAgICBmb3IgKHZhciBfaTQgPSBtaW5MaW5lOyBfaTQgPCBsaW5lcy5sZW5ndGg7IF9pNCsrKSB7XG4gICAgICByZXN1bHRMaW5lcy5wdXNoKGxpbmVzW19pNF0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0TGluZXMuam9pbignXFxuJyk7XG4gIH1cblxuICAvLyBXcmFwcGVyIHRoYXQgc3VwcG9ydHMgbXVsdGlwbGUgZmlsZSBwYXRjaGVzIHZpYSBjYWxsYmFja3MuXG4gIGZ1bmN0aW9uIGFwcGx5UGF0Y2hlcyh1bmlEaWZmLCBvcHRpb25zKSB7XG4gICAgaWYgKHR5cGVvZiB1bmlEaWZmID09PSAnc3RyaW5nJykge1xuICAgICAgdW5pRGlmZiA9IHBhcnNlUGF0Y2godW5pRGlmZik7XG4gICAgfVxuICAgIHZhciBjdXJyZW50SW5kZXggPSAwO1xuICAgIGZ1bmN0aW9uIHByb2Nlc3NJbmRleCgpIHtcbiAgICAgIHZhciBpbmRleCA9IHVuaURpZmZbY3VycmVudEluZGV4KytdO1xuICAgICAgaWYgKCFpbmRleCkge1xuICAgICAgICByZXR1cm4gb3B0aW9ucy5jb21wbGV0ZSgpO1xuICAgICAgfVxuICAgICAgb3B0aW9ucy5sb2FkRmlsZShpbmRleCwgZnVuY3Rpb24gKGVyciwgZGF0YSkge1xuICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIG9wdGlvbnMuY29tcGxldGUoZXJyKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdXBkYXRlZENvbnRlbnQgPSBhcHBseVBhdGNoKGRhdGEsIGluZGV4LCBvcHRpb25zKTtcbiAgICAgICAgb3B0aW9ucy5wYXRjaGVkKGluZGV4LCB1cGRhdGVkQ29udGVudCwgZnVuY3Rpb24gKGVycikge1xuICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmNvbXBsZXRlKGVycik7XG4gICAgICAgICAgfVxuICAgICAgICAgIHByb2Nlc3NJbmRleCgpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBwcm9jZXNzSW5kZXgoKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHN0cnVjdHVyZWRQYXRjaChvbGRGaWxlTmFtZSwgbmV3RmlsZU5hbWUsIG9sZFN0ciwgbmV3U3RyLCBvbGRIZWFkZXIsIG5ld0hlYWRlciwgb3B0aW9ucykge1xuICAgIGlmICghb3B0aW9ucykge1xuICAgICAgb3B0aW9ucyA9IHt9O1xuICAgIH1cbiAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIG9wdGlvbnMgPSB7XG4gICAgICAgIGNhbGxiYWNrOiBvcHRpb25zXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAodHlwZW9mIG9wdGlvbnMuY29udGV4dCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIG9wdGlvbnMuY29udGV4dCA9IDQ7XG4gICAgfVxuICAgIGlmIChvcHRpb25zLm5ld2xpbmVJc1Rva2VuKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ25ld2xpbmVJc1Rva2VuIG1heSBub3QgYmUgdXNlZCB3aXRoIHBhdGNoLWdlbmVyYXRpb24gZnVuY3Rpb25zLCBvbmx5IHdpdGggZGlmZmluZyBmdW5jdGlvbnMnKTtcbiAgICB9XG4gICAgaWYgKCFvcHRpb25zLmNhbGxiYWNrKSB7XG4gICAgICByZXR1cm4gZGlmZkxpbmVzUmVzdWx0VG9QYXRjaChkaWZmTGluZXMob2xkU3RyLCBuZXdTdHIsIG9wdGlvbnMpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIF9vcHRpb25zID0gb3B0aW9ucyxcbiAgICAgICAgX2NhbGxiYWNrID0gX29wdGlvbnMuY2FsbGJhY2s7XG4gICAgICBkaWZmTGluZXMob2xkU3RyLCBuZXdTdHIsIF9vYmplY3RTcHJlYWQyKF9vYmplY3RTcHJlYWQyKHt9LCBvcHRpb25zKSwge30sIHtcbiAgICAgICAgY2FsbGJhY2s6IGZ1bmN0aW9uIGNhbGxiYWNrKGRpZmYpIHtcbiAgICAgICAgICB2YXIgcGF0Y2ggPSBkaWZmTGluZXNSZXN1bHRUb1BhdGNoKGRpZmYpO1xuICAgICAgICAgIF9jYWxsYmFjayhwYXRjaCk7XG4gICAgICAgIH1cbiAgICAgIH0pKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZGlmZkxpbmVzUmVzdWx0VG9QYXRjaChkaWZmKSB7XG4gICAgICAvLyBTVEVQIDE6IEJ1aWxkIHVwIHRoZSBwYXRjaCB3aXRoIG5vIFwiXFwgTm8gbmV3bGluZSBhdCBlbmQgb2YgZmlsZVwiIGxpbmVzIGFuZCB3aXRoIHRoZSBhcnJheXNcbiAgICAgIC8vICAgICAgICAgb2YgbGluZXMgY29udGFpbmluZyB0cmFpbGluZyBuZXdsaW5lIGNoYXJhY3RlcnMuIFdlJ2xsIHRpZHkgdXAgbGF0ZXIuLi5cblxuICAgICAgaWYgKCFkaWZmKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGRpZmYucHVzaCh7XG4gICAgICAgIHZhbHVlOiAnJyxcbiAgICAgICAgbGluZXM6IFtdXG4gICAgICB9KTsgLy8gQXBwZW5kIGFuIGVtcHR5IHZhbHVlIHRvIG1ha2UgY2xlYW51cCBlYXNpZXJcblxuICAgICAgZnVuY3Rpb24gY29udGV4dExpbmVzKGxpbmVzKSB7XG4gICAgICAgIHJldHVybiBsaW5lcy5tYXAoZnVuY3Rpb24gKGVudHJ5KSB7XG4gICAgICAgICAgcmV0dXJuICcgJyArIGVudHJ5O1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICAgIHZhciBodW5rcyA9IFtdO1xuICAgICAgdmFyIG9sZFJhbmdlU3RhcnQgPSAwLFxuICAgICAgICBuZXdSYW5nZVN0YXJ0ID0gMCxcbiAgICAgICAgY3VyUmFuZ2UgPSBbXSxcbiAgICAgICAgb2xkTGluZSA9IDEsXG4gICAgICAgIG5ld0xpbmUgPSAxO1xuICAgICAgdmFyIF9sb29wID0gZnVuY3Rpb24gX2xvb3AoKSB7XG4gICAgICAgIHZhciBjdXJyZW50ID0gZGlmZltpXSxcbiAgICAgICAgICBsaW5lcyA9IGN1cnJlbnQubGluZXMgfHwgc3BsaXRMaW5lcyhjdXJyZW50LnZhbHVlKTtcbiAgICAgICAgY3VycmVudC5saW5lcyA9IGxpbmVzO1xuICAgICAgICBpZiAoY3VycmVudC5hZGRlZCB8fCBjdXJyZW50LnJlbW92ZWQpIHtcbiAgICAgICAgICB2YXIgX2N1clJhbmdlO1xuICAgICAgICAgIC8vIElmIHdlIGhhdmUgcHJldmlvdXMgY29udGV4dCwgc3RhcnQgd2l0aCB0aGF0XG4gICAgICAgICAgaWYgKCFvbGRSYW5nZVN0YXJ0KSB7XG4gICAgICAgICAgICB2YXIgcHJldiA9IGRpZmZbaSAtIDFdO1xuICAgICAgICAgICAgb2xkUmFuZ2VTdGFydCA9IG9sZExpbmU7XG4gICAgICAgICAgICBuZXdSYW5nZVN0YXJ0ID0gbmV3TGluZTtcbiAgICAgICAgICAgIGlmIChwcmV2KSB7XG4gICAgICAgICAgICAgIGN1clJhbmdlID0gb3B0aW9ucy5jb250ZXh0ID4gMCA/IGNvbnRleHRMaW5lcyhwcmV2LmxpbmVzLnNsaWNlKC1vcHRpb25zLmNvbnRleHQpKSA6IFtdO1xuICAgICAgICAgICAgICBvbGRSYW5nZVN0YXJ0IC09IGN1clJhbmdlLmxlbmd0aDtcbiAgICAgICAgICAgICAgbmV3UmFuZ2VTdGFydCAtPSBjdXJSYW5nZS5sZW5ndGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gT3V0cHV0IG91ciBjaGFuZ2VzXG4gICAgICAgICAgKF9jdXJSYW5nZSA9IGN1clJhbmdlKS5wdXNoLmFwcGx5KF9jdXJSYW5nZSwgX3RvQ29uc3VtYWJsZUFycmF5KGxpbmVzLm1hcChmdW5jdGlvbiAoZW50cnkpIHtcbiAgICAgICAgICAgIHJldHVybiAoY3VycmVudC5hZGRlZCA/ICcrJyA6ICctJykgKyBlbnRyeTtcbiAgICAgICAgICB9KSkpO1xuXG4gICAgICAgICAgLy8gVHJhY2sgdGhlIHVwZGF0ZWQgZmlsZSBwb3NpdGlvblxuICAgICAgICAgIGlmIChjdXJyZW50LmFkZGVkKSB7XG4gICAgICAgICAgICBuZXdMaW5lICs9IGxpbmVzLmxlbmd0aDtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb2xkTGluZSArPSBsaW5lcy5sZW5ndGg7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIElkZW50aWNhbCBjb250ZXh0IGxpbmVzLiBUcmFjayBsaW5lIGNoYW5nZXNcbiAgICAgICAgICBpZiAob2xkUmFuZ2VTdGFydCkge1xuICAgICAgICAgICAgLy8gQ2xvc2Ugb3V0IGFueSBjaGFuZ2VzIHRoYXQgaGF2ZSBiZWVuIG91dHB1dCAob3Igam9pbiBvdmVybGFwcGluZylcbiAgICAgICAgICAgIGlmIChsaW5lcy5sZW5ndGggPD0gb3B0aW9ucy5jb250ZXh0ICogMiAmJiBpIDwgZGlmZi5sZW5ndGggLSAyKSB7XG4gICAgICAgICAgICAgIHZhciBfY3VyUmFuZ2UyO1xuICAgICAgICAgICAgICAvLyBPdmVybGFwcGluZ1xuICAgICAgICAgICAgICAoX2N1clJhbmdlMiA9IGN1clJhbmdlKS5wdXNoLmFwcGx5KF9jdXJSYW5nZTIsIF90b0NvbnN1bWFibGVBcnJheShjb250ZXh0TGluZXMobGluZXMpKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB2YXIgX2N1clJhbmdlMztcbiAgICAgICAgICAgICAgLy8gZW5kIHRoZSByYW5nZSBhbmQgb3V0cHV0XG4gICAgICAgICAgICAgIHZhciBjb250ZXh0U2l6ZSA9IE1hdGgubWluKGxpbmVzLmxlbmd0aCwgb3B0aW9ucy5jb250ZXh0KTtcbiAgICAgICAgICAgICAgKF9jdXJSYW5nZTMgPSBjdXJSYW5nZSkucHVzaC5hcHBseShfY3VyUmFuZ2UzLCBfdG9Db25zdW1hYmxlQXJyYXkoY29udGV4dExpbmVzKGxpbmVzLnNsaWNlKDAsIGNvbnRleHRTaXplKSkpKTtcbiAgICAgICAgICAgICAgdmFyIF9odW5rID0ge1xuICAgICAgICAgICAgICAgIG9sZFN0YXJ0OiBvbGRSYW5nZVN0YXJ0LFxuICAgICAgICAgICAgICAgIG9sZExpbmVzOiBvbGRMaW5lIC0gb2xkUmFuZ2VTdGFydCArIGNvbnRleHRTaXplLFxuICAgICAgICAgICAgICAgIG5ld1N0YXJ0OiBuZXdSYW5nZVN0YXJ0LFxuICAgICAgICAgICAgICAgIG5ld0xpbmVzOiBuZXdMaW5lIC0gbmV3UmFuZ2VTdGFydCArIGNvbnRleHRTaXplLFxuICAgICAgICAgICAgICAgIGxpbmVzOiBjdXJSYW5nZVxuICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICBodW5rcy5wdXNoKF9odW5rKTtcbiAgICAgICAgICAgICAgb2xkUmFuZ2VTdGFydCA9IDA7XG4gICAgICAgICAgICAgIG5ld1JhbmdlU3RhcnQgPSAwO1xuICAgICAgICAgICAgICBjdXJSYW5nZSA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBvbGRMaW5lICs9IGxpbmVzLmxlbmd0aDtcbiAgICAgICAgICBuZXdMaW5lICs9IGxpbmVzLmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGlmZi5sZW5ndGg7IGkrKykge1xuICAgICAgICBfbG9vcCgpO1xuICAgICAgfVxuXG4gICAgICAvLyBTdGVwIDI6IGVsaW1pbmF0ZSB0aGUgdHJhaWxpbmcgYFxcbmAgZnJvbSBlYWNoIGxpbmUgb2YgZWFjaCBodW5rLCBhbmQsIHdoZXJlIG5lZWRlZCwgYWRkXG4gICAgICAvLyAgICAgICAgIFwiXFwgTm8gbmV3bGluZSBhdCBlbmQgb2YgZmlsZVwiLlxuICAgICAgZm9yICh2YXIgX2kgPSAwLCBfaHVua3MgPSBodW5rczsgX2kgPCBfaHVua3MubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgIHZhciBodW5rID0gX2h1bmtzW19pXTtcbiAgICAgICAgZm9yICh2YXIgX2kyID0gMDsgX2kyIDwgaHVuay5saW5lcy5sZW5ndGg7IF9pMisrKSB7XG4gICAgICAgICAgaWYgKGh1bmsubGluZXNbX2kyXS5lbmRzV2l0aCgnXFxuJykpIHtcbiAgICAgICAgICAgIGh1bmsubGluZXNbX2kyXSA9IGh1bmsubGluZXNbX2kyXS5zbGljZSgwLCAtMSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGh1bmsubGluZXMuc3BsaWNlKF9pMiArIDEsIDAsICdcXFxcIE5vIG5ld2xpbmUgYXQgZW5kIG9mIGZpbGUnKTtcbiAgICAgICAgICAgIF9pMisrOyAvLyBTa2lwIHRoZSBsaW5lIHdlIGp1c3QgYWRkZWQsIHRoZW4gY29udGludWUgaXRlcmF0aW5nXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4ge1xuICAgICAgICBvbGRGaWxlTmFtZTogb2xkRmlsZU5hbWUsXG4gICAgICAgIG5ld0ZpbGVOYW1lOiBuZXdGaWxlTmFtZSxcbiAgICAgICAgb2xkSGVhZGVyOiBvbGRIZWFkZXIsXG4gICAgICAgIG5ld0hlYWRlcjogbmV3SGVhZGVyLFxuICAgICAgICBodW5rczogaHVua3NcbiAgICAgIH07XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIGZvcm1hdFBhdGNoKGRpZmYpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShkaWZmKSkge1xuICAgICAgcmV0dXJuIGRpZmYubWFwKGZvcm1hdFBhdGNoKS5qb2luKCdcXG4nKTtcbiAgICB9XG4gICAgdmFyIHJldCA9IFtdO1xuICAgIGlmIChkaWZmLm9sZEZpbGVOYW1lID09IGRpZmYubmV3RmlsZU5hbWUpIHtcbiAgICAgIHJldC5wdXNoKCdJbmRleDogJyArIGRpZmYub2xkRmlsZU5hbWUpO1xuICAgIH1cbiAgICByZXQucHVzaCgnPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PScpO1xuICAgIHJldC5wdXNoKCctLS0gJyArIGRpZmYub2xkRmlsZU5hbWUgKyAodHlwZW9mIGRpZmYub2xkSGVhZGVyID09PSAndW5kZWZpbmVkJyA/ICcnIDogJ1xcdCcgKyBkaWZmLm9sZEhlYWRlcikpO1xuICAgIHJldC5wdXNoKCcrKysgJyArIGRpZmYubmV3RmlsZU5hbWUgKyAodHlwZW9mIGRpZmYubmV3SGVhZGVyID09PSAndW5kZWZpbmVkJyA/ICcnIDogJ1xcdCcgKyBkaWZmLm5ld0hlYWRlcikpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZGlmZi5odW5rcy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGh1bmsgPSBkaWZmLmh1bmtzW2ldO1xuICAgICAgLy8gVW5pZmllZCBEaWZmIEZvcm1hdCBxdWlyazogSWYgdGhlIGNodW5rIHNpemUgaXMgMCxcbiAgICAgIC8vIHRoZSBmaXJzdCBudW1iZXIgaXMgb25lIGxvd2VyIHRoYW4gb25lIHdvdWxkIGV4cGVjdC5cbiAgICAgIC8vIGh0dHBzOi8vd3d3LmFydGltYS5jb20vd2VibG9ncy92aWV3cG9zdC5qc3A/dGhyZWFkPTE2NDI5M1xuICAgICAgaWYgKGh1bmsub2xkTGluZXMgPT09IDApIHtcbiAgICAgICAgaHVuay5vbGRTdGFydCAtPSAxO1xuICAgICAgfVxuICAgICAgaWYgKGh1bmsubmV3TGluZXMgPT09IDApIHtcbiAgICAgICAgaHVuay5uZXdTdGFydCAtPSAxO1xuICAgICAgfVxuICAgICAgcmV0LnB1c2goJ0BAIC0nICsgaHVuay5vbGRTdGFydCArICcsJyArIGh1bmsub2xkTGluZXMgKyAnICsnICsgaHVuay5uZXdTdGFydCArICcsJyArIGh1bmsubmV3TGluZXMgKyAnIEBAJyk7XG4gICAgICByZXQucHVzaC5hcHBseShyZXQsIGh1bmsubGluZXMpO1xuICAgIH1cbiAgICByZXR1cm4gcmV0LmpvaW4oJ1xcbicpICsgJ1xcbic7XG4gIH1cbiAgZnVuY3Rpb24gY3JlYXRlVHdvRmlsZXNQYXRjaChvbGRGaWxlTmFtZSwgbmV3RmlsZU5hbWUsIG9sZFN0ciwgbmV3U3RyLCBvbGRIZWFkZXIsIG5ld0hlYWRlciwgb3B0aW9ucykge1xuICAgIHZhciBfb3B0aW9uczI7XG4gICAgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBvcHRpb25zID0ge1xuICAgICAgICBjYWxsYmFjazogb3B0aW9uc1xuICAgICAgfTtcbiAgICB9XG4gICAgaWYgKCEoKF9vcHRpb25zMiA9IG9wdGlvbnMpICE9PSBudWxsICYmIF9vcHRpb25zMiAhPT0gdm9pZCAwICYmIF9vcHRpb25zMi5jYWxsYmFjaykpIHtcbiAgICAgIHZhciBwYXRjaE9iaiA9IHN0cnVjdHVyZWRQYXRjaChvbGRGaWxlTmFtZSwgbmV3RmlsZU5hbWUsIG9sZFN0ciwgbmV3U3RyLCBvbGRIZWFkZXIsIG5ld0hlYWRlciwgb3B0aW9ucyk7XG4gICAgICBpZiAoIXBhdGNoT2JqKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBmb3JtYXRQYXRjaChwYXRjaE9iaik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBfb3B0aW9uczMgPSBvcHRpb25zLFxuICAgICAgICBfY2FsbGJhY2syID0gX29wdGlvbnMzLmNhbGxiYWNrO1xuICAgICAgc3RydWN0dXJlZFBhdGNoKG9sZEZpbGVOYW1lLCBuZXdGaWxlTmFtZSwgb2xkU3RyLCBuZXdTdHIsIG9sZEhlYWRlciwgbmV3SGVhZGVyLCBfb2JqZWN0U3ByZWFkMihfb2JqZWN0U3ByZWFkMih7fSwgb3B0aW9ucyksIHt9LCB7XG4gICAgICAgIGNhbGxiYWNrOiBmdW5jdGlvbiBjYWxsYmFjayhwYXRjaE9iaikge1xuICAgICAgICAgIGlmICghcGF0Y2hPYmopIHtcbiAgICAgICAgICAgIF9jYWxsYmFjazIoKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgX2NhbGxiYWNrMihmb3JtYXRQYXRjaChwYXRjaE9iaikpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSkpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBjcmVhdGVQYXRjaChmaWxlTmFtZSwgb2xkU3RyLCBuZXdTdHIsIG9sZEhlYWRlciwgbmV3SGVhZGVyLCBvcHRpb25zKSB7XG4gICAgcmV0dXJuIGNyZWF0ZVR3b0ZpbGVzUGF0Y2goZmlsZU5hbWUsIGZpbGVOYW1lLCBvbGRTdHIsIG5ld1N0ciwgb2xkSGVhZGVyLCBuZXdIZWFkZXIsIG9wdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNwbGl0IGB0ZXh0YCBpbnRvIGFuIGFycmF5IG9mIGxpbmVzLCBpbmNsdWRpbmcgdGhlIHRyYWlsaW5nIG5ld2xpbmUgY2hhcmFjdGVyICh3aGVyZSBwcmVzZW50KVxuICAgKi9cbiAgZnVuY3Rpb24gc3BsaXRMaW5lcyh0ZXh0KSB7XG4gICAgdmFyIGhhc1RyYWlsaW5nTmwgPSB0ZXh0LmVuZHNXaXRoKCdcXG4nKTtcbiAgICB2YXIgcmVzdWx0ID0gdGV4dC5zcGxpdCgnXFxuJykubWFwKGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICByZXR1cm4gbGluZSArICdcXG4nO1xuICAgIH0pO1xuICAgIGlmIChoYXNUcmFpbGluZ05sKSB7XG4gICAgICByZXN1bHQucG9wKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdC5wdXNoKHJlc3VsdC5wb3AoKS5zbGljZSgwLCAtMSkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gYXJyYXlFcXVhbChhLCBiKSB7XG4gICAgaWYgKGEubGVuZ3RoICE9PSBiLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gYXJyYXlTdGFydHNXaXRoKGEsIGIpO1xuICB9XG4gIGZ1bmN0aW9uIGFycmF5U3RhcnRzV2l0aChhcnJheSwgc3RhcnQpIHtcbiAgICBpZiAoc3RhcnQubGVuZ3RoID4gYXJyYXkubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RhcnQubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChzdGFydFtpXSAhPT0gYXJyYXlbaV0pIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNhbGNMaW5lQ291bnQoaHVuaykge1xuICAgIHZhciBfY2FsY09sZE5ld0xpbmVDb3VudCA9IGNhbGNPbGROZXdMaW5lQ291bnQoaHVuay5saW5lcyksXG4gICAgICBvbGRMaW5lcyA9IF9jYWxjT2xkTmV3TGluZUNvdW50Lm9sZExpbmVzLFxuICAgICAgbmV3TGluZXMgPSBfY2FsY09sZE5ld0xpbmVDb3VudC5uZXdMaW5lcztcbiAgICBpZiAob2xkTGluZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaHVuay5vbGRMaW5lcyA9IG9sZExpbmVzO1xuICAgIH0gZWxzZSB7XG4gICAgICBkZWxldGUgaHVuay5vbGRMaW5lcztcbiAgICB9XG4gICAgaWYgKG5ld0xpbmVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGh1bmsubmV3TGluZXMgPSBuZXdMaW5lcztcbiAgICB9IGVsc2Uge1xuICAgICAgZGVsZXRlIGh1bmsubmV3TGluZXM7XG4gICAgfVxuICB9XG4gIGZ1bmN0aW9uIG1lcmdlKG1pbmUsIHRoZWlycywgYmFzZSkge1xuICAgIG1pbmUgPSBsb2FkUGF0Y2gobWluZSwgYmFzZSk7XG4gICAgdGhlaXJzID0gbG9hZFBhdGNoKHRoZWlycywgYmFzZSk7XG4gICAgdmFyIHJldCA9IHt9O1xuXG4gICAgLy8gRm9yIGluZGV4IHdlIGp1c3QgbGV0IGl0IHBhc3MgdGhyb3VnaCBhcyBpdCBkb2Vzbid0IGhhdmUgYW55IG5lY2Vzc2FyeSBtZWFuaW5nLlxuICAgIC8vIExlYXZpbmcgc2FuaXR5IGNoZWNrcyBvbiB0aGlzIHRvIHRoZSBBUEkgY29uc3VtZXIgdGhhdCBtYXkga25vdyBtb3JlIGFib3V0IHRoZVxuICAgIC8vIG1lYW5pbmcgaW4gdGhlaXIgb3duIGNvbnRleHQuXG4gICAgaWYgKG1pbmUuaW5kZXggfHwgdGhlaXJzLmluZGV4KSB7XG4gICAgICByZXQuaW5kZXggPSBtaW5lLmluZGV4IHx8IHRoZWlycy5pbmRleDtcbiAgICB9XG4gICAgaWYgKG1pbmUubmV3RmlsZU5hbWUgfHwgdGhlaXJzLm5ld0ZpbGVOYW1lKSB7XG4gICAgICBpZiAoIWZpbGVOYW1lQ2hhbmdlZChtaW5lKSkge1xuICAgICAgICAvLyBObyBoZWFkZXIgb3Igbm8gY2hhbmdlIGluIG91cnMsIHVzZSB0aGVpcnMgKGFuZCBvdXJzIGlmIHRoZWlycyBkb2VzIG5vdCBleGlzdClcbiAgICAgICAgcmV0Lm9sZEZpbGVOYW1lID0gdGhlaXJzLm9sZEZpbGVOYW1lIHx8IG1pbmUub2xkRmlsZU5hbWU7XG4gICAgICAgIHJldC5uZXdGaWxlTmFtZSA9IHRoZWlycy5uZXdGaWxlTmFtZSB8fCBtaW5lLm5ld0ZpbGVOYW1lO1xuICAgICAgICByZXQub2xkSGVhZGVyID0gdGhlaXJzLm9sZEhlYWRlciB8fCBtaW5lLm9sZEhlYWRlcjtcbiAgICAgICAgcmV0Lm5ld0hlYWRlciA9IHRoZWlycy5uZXdIZWFkZXIgfHwgbWluZS5uZXdIZWFkZXI7XG4gICAgICB9IGVsc2UgaWYgKCFmaWxlTmFtZUNoYW5nZWQodGhlaXJzKSkge1xuICAgICAgICAvLyBObyBoZWFkZXIgb3Igbm8gY2hhbmdlIGluIHRoZWlycywgdXNlIG91cnNcbiAgICAgICAgcmV0Lm9sZEZpbGVOYW1lID0gbWluZS5vbGRGaWxlTmFtZTtcbiAgICAgICAgcmV0Lm5ld0ZpbGVOYW1lID0gbWluZS5uZXdGaWxlTmFtZTtcbiAgICAgICAgcmV0Lm9sZEhlYWRlciA9IG1pbmUub2xkSGVhZGVyO1xuICAgICAgICByZXQubmV3SGVhZGVyID0gbWluZS5uZXdIZWFkZXI7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBCb3RoIGNoYW5nZWQuLi4gZmlndXJlIGl0IG91dFxuICAgICAgICByZXQub2xkRmlsZU5hbWUgPSBzZWxlY3RGaWVsZChyZXQsIG1pbmUub2xkRmlsZU5hbWUsIHRoZWlycy5vbGRGaWxlTmFtZSk7XG4gICAgICAgIHJldC5uZXdGaWxlTmFtZSA9IHNlbGVjdEZpZWxkKHJldCwgbWluZS5uZXdGaWxlTmFtZSwgdGhlaXJzLm5ld0ZpbGVOYW1lKTtcbiAgICAgICAgcmV0Lm9sZEhlYWRlciA9IHNlbGVjdEZpZWxkKHJldCwgbWluZS5vbGRIZWFkZXIsIHRoZWlycy5vbGRIZWFkZXIpO1xuICAgICAgICByZXQubmV3SGVhZGVyID0gc2VsZWN0RmllbGQocmV0LCBtaW5lLm5ld0hlYWRlciwgdGhlaXJzLm5ld0hlYWRlcik7XG4gICAgICB9XG4gICAgfVxuICAgIHJldC5odW5rcyA9IFtdO1xuICAgIHZhciBtaW5lSW5kZXggPSAwLFxuICAgICAgdGhlaXJzSW5kZXggPSAwLFxuICAgICAgbWluZU9mZnNldCA9IDAsXG4gICAgICB0aGVpcnNPZmZzZXQgPSAwO1xuICAgIHdoaWxlIChtaW5lSW5kZXggPCBtaW5lLmh1bmtzLmxlbmd0aCB8fCB0aGVpcnNJbmRleCA8IHRoZWlycy5odW5rcy5sZW5ndGgpIHtcbiAgICAgIHZhciBtaW5lQ3VycmVudCA9IG1pbmUuaHVua3NbbWluZUluZGV4XSB8fCB7XG4gICAgICAgICAgb2xkU3RhcnQ6IEluZmluaXR5XG4gICAgICAgIH0sXG4gICAgICAgIHRoZWlyc0N1cnJlbnQgPSB0aGVpcnMuaHVua3NbdGhlaXJzSW5kZXhdIHx8IHtcbiAgICAgICAgICBvbGRTdGFydDogSW5maW5pdHlcbiAgICAgICAgfTtcbiAgICAgIGlmIChodW5rQmVmb3JlKG1pbmVDdXJyZW50LCB0aGVpcnNDdXJyZW50KSkge1xuICAgICAgICAvLyBUaGlzIHBhdGNoIGRvZXMgbm90IG92ZXJsYXAgd2l0aCBhbnkgb2YgdGhlIG90aGVycywgeWF5LlxuICAgICAgICByZXQuaHVua3MucHVzaChjbG9uZUh1bmsobWluZUN1cnJlbnQsIG1pbmVPZmZzZXQpKTtcbiAgICAgICAgbWluZUluZGV4Kys7XG4gICAgICAgIHRoZWlyc09mZnNldCArPSBtaW5lQ3VycmVudC5uZXdMaW5lcyAtIG1pbmVDdXJyZW50Lm9sZExpbmVzO1xuICAgICAgfSBlbHNlIGlmIChodW5rQmVmb3JlKHRoZWlyc0N1cnJlbnQsIG1pbmVDdXJyZW50KSkge1xuICAgICAgICAvLyBUaGlzIHBhdGNoIGRvZXMgbm90IG92ZXJsYXAgd2l0aCBhbnkgb2YgdGhlIG90aGVycywgeWF5LlxuICAgICAgICByZXQuaHVua3MucHVzaChjbG9uZUh1bmsodGhlaXJzQ3VycmVudCwgdGhlaXJzT2Zmc2V0KSk7XG4gICAgICAgIHRoZWlyc0luZGV4Kys7XG4gICAgICAgIG1pbmVPZmZzZXQgKz0gdGhlaXJzQ3VycmVudC5uZXdMaW5lcyAtIHRoZWlyc0N1cnJlbnQub2xkTGluZXM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBPdmVybGFwLCBtZXJnZSBhcyBiZXN0IHdlIGNhblxuICAgICAgICB2YXIgbWVyZ2VkSHVuayA9IHtcbiAgICAgICAgICBvbGRTdGFydDogTWF0aC5taW4obWluZUN1cnJlbnQub2xkU3RhcnQsIHRoZWlyc0N1cnJlbnQub2xkU3RhcnQpLFxuICAgICAgICAgIG9sZExpbmVzOiAwLFxuICAgICAgICAgIG5ld1N0YXJ0OiBNYXRoLm1pbihtaW5lQ3VycmVudC5uZXdTdGFydCArIG1pbmVPZmZzZXQsIHRoZWlyc0N1cnJlbnQub2xkU3RhcnQgKyB0aGVpcnNPZmZzZXQpLFxuICAgICAgICAgIG5ld0xpbmVzOiAwLFxuICAgICAgICAgIGxpbmVzOiBbXVxuICAgICAgICB9O1xuICAgICAgICBtZXJnZUxpbmVzKG1lcmdlZEh1bmssIG1pbmVDdXJyZW50Lm9sZFN0YXJ0LCBtaW5lQ3VycmVudC5saW5lcywgdGhlaXJzQ3VycmVudC5vbGRTdGFydCwgdGhlaXJzQ3VycmVudC5saW5lcyk7XG4gICAgICAgIHRoZWlyc0luZGV4Kys7XG4gICAgICAgIG1pbmVJbmRleCsrO1xuICAgICAgICByZXQuaHVua3MucHVzaChtZXJnZWRIdW5rKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuICBmdW5jdGlvbiBsb2FkUGF0Y2gocGFyYW0sIGJhc2UpIHtcbiAgICBpZiAodHlwZW9mIHBhcmFtID09PSAnc3RyaW5nJykge1xuICAgICAgaWYgKC9eQEAvbS50ZXN0KHBhcmFtKSB8fCAvXkluZGV4Oi9tLnRlc3QocGFyYW0pKSB7XG4gICAgICAgIHJldHVybiBwYXJzZVBhdGNoKHBhcmFtKVswXTtcbiAgICAgIH1cbiAgICAgIGlmICghYmFzZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ011c3QgcHJvdmlkZSBhIGJhc2UgcmVmZXJlbmNlIG9yIHBhc3MgaW4gYSBwYXRjaCcpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHN0cnVjdHVyZWRQYXRjaCh1bmRlZmluZWQsIHVuZGVmaW5lZCwgYmFzZSwgcGFyYW0pO1xuICAgIH1cbiAgICByZXR1cm4gcGFyYW07XG4gIH1cbiAgZnVuY3Rpb24gZmlsZU5hbWVDaGFuZ2VkKHBhdGNoKSB7XG4gICAgcmV0dXJuIHBhdGNoLm5ld0ZpbGVOYW1lICYmIHBhdGNoLm5ld0ZpbGVOYW1lICE9PSBwYXRjaC5vbGRGaWxlTmFtZTtcbiAgfVxuICBmdW5jdGlvbiBzZWxlY3RGaWVsZChpbmRleCwgbWluZSwgdGhlaXJzKSB7XG4gICAgaWYgKG1pbmUgPT09IHRoZWlycykge1xuICAgICAgcmV0dXJuIG1pbmU7XG4gICAgfSBlbHNlIHtcbiAgICAgIGluZGV4LmNvbmZsaWN0ID0gdHJ1ZTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG1pbmU6IG1pbmUsXG4gICAgICAgIHRoZWlyczogdGhlaXJzXG4gICAgICB9O1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBodW5rQmVmb3JlKHRlc3QsIGNoZWNrKSB7XG4gICAgcmV0dXJuIHRlc3Qub2xkU3RhcnQgPCBjaGVjay5vbGRTdGFydCAmJiB0ZXN0Lm9sZFN0YXJ0ICsgdGVzdC5vbGRMaW5lcyA8IGNoZWNrLm9sZFN0YXJ0O1xuICB9XG4gIGZ1bmN0aW9uIGNsb25lSHVuayhodW5rLCBvZmZzZXQpIHtcbiAgICByZXR1cm4ge1xuICAgICAgb2xkU3RhcnQ6IGh1bmsub2xkU3RhcnQsXG4gICAgICBvbGRMaW5lczogaHVuay5vbGRMaW5lcyxcbiAgICAgIG5ld1N0YXJ0OiBodW5rLm5ld1N0YXJ0ICsgb2Zmc2V0LFxuICAgICAgbmV3TGluZXM6IGh1bmsubmV3TGluZXMsXG4gICAgICBsaW5lczogaHVuay5saW5lc1xuICAgIH07XG4gIH1cbiAgZnVuY3Rpb24gbWVyZ2VMaW5lcyhodW5rLCBtaW5lT2Zmc2V0LCBtaW5lTGluZXMsIHRoZWlyT2Zmc2V0LCB0aGVpckxpbmVzKSB7XG4gICAgLy8gVGhpcyB3aWxsIGdlbmVyYWxseSByZXN1bHQgaW4gYSBjb25mbGljdGVkIGh1bmssIGJ1dCB0aGVyZSBhcmUgY2FzZXMgd2hlcmUgdGhlIGNvbnRleHRcbiAgICAvLyBpcyB0aGUgb25seSBvdmVybGFwIHdoZXJlIHdlIGNhbiBzdWNjZXNzZnVsbHkgbWVyZ2UgdGhlIGNvbnRlbnQgaGVyZS5cbiAgICB2YXIgbWluZSA9IHtcbiAgICAgICAgb2Zmc2V0OiBtaW5lT2Zmc2V0LFxuICAgICAgICBsaW5lczogbWluZUxpbmVzLFxuICAgICAgICBpbmRleDogMFxuICAgICAgfSxcbiAgICAgIHRoZWlyID0ge1xuICAgICAgICBvZmZzZXQ6IHRoZWlyT2Zmc2V0LFxuICAgICAgICBsaW5lczogdGhlaXJMaW5lcyxcbiAgICAgICAgaW5kZXg6IDBcbiAgICAgIH07XG5cbiAgICAvLyBIYW5kbGUgYW55IGxlYWRpbmcgY29udGVudFxuICAgIGluc2VydExlYWRpbmcoaHVuaywgbWluZSwgdGhlaXIpO1xuICAgIGluc2VydExlYWRpbmcoaHVuaywgdGhlaXIsIG1pbmUpO1xuXG4gICAgLy8gTm93IGluIHRoZSBvdmVybGFwIGNvbnRlbnQuIFNjYW4gdGhyb3VnaCBhbmQgc2VsZWN0IHRoZSBiZXN0IGNoYW5nZXMgZnJvbSBlYWNoLlxuICAgIHdoaWxlIChtaW5lLmluZGV4IDwgbWluZS5saW5lcy5sZW5ndGggJiYgdGhlaXIuaW5kZXggPCB0aGVpci5saW5lcy5sZW5ndGgpIHtcbiAgICAgIHZhciBtaW5lQ3VycmVudCA9IG1pbmUubGluZXNbbWluZS5pbmRleF0sXG4gICAgICAgIHRoZWlyQ3VycmVudCA9IHRoZWlyLmxpbmVzW3RoZWlyLmluZGV4XTtcbiAgICAgIGlmICgobWluZUN1cnJlbnRbMF0gPT09ICctJyB8fCBtaW5lQ3VycmVudFswXSA9PT0gJysnKSAmJiAodGhlaXJDdXJyZW50WzBdID09PSAnLScgfHwgdGhlaXJDdXJyZW50WzBdID09PSAnKycpKSB7XG4gICAgICAgIC8vIEJvdGggbW9kaWZpZWQgLi4uXG4gICAgICAgIG11dHVhbENoYW5nZShodW5rLCBtaW5lLCB0aGVpcik7XG4gICAgICB9IGVsc2UgaWYgKG1pbmVDdXJyZW50WzBdID09PSAnKycgJiYgdGhlaXJDdXJyZW50WzBdID09PSAnICcpIHtcbiAgICAgICAgdmFyIF9odW5rJGxpbmVzO1xuICAgICAgICAvLyBNaW5lIGluc2VydGVkXG4gICAgICAgIChfaHVuayRsaW5lcyA9IGh1bmsubGluZXMpLnB1c2guYXBwbHkoX2h1bmskbGluZXMsIF90b0NvbnN1bWFibGVBcnJheShjb2xsZWN0Q2hhbmdlKG1pbmUpKSk7XG4gICAgICB9IGVsc2UgaWYgKHRoZWlyQ3VycmVudFswXSA9PT0gJysnICYmIG1pbmVDdXJyZW50WzBdID09PSAnICcpIHtcbiAgICAgICAgdmFyIF9odW5rJGxpbmVzMjtcbiAgICAgICAgLy8gVGhlaXJzIGluc2VydGVkXG4gICAgICAgIChfaHVuayRsaW5lczIgPSBodW5rLmxpbmVzKS5wdXNoLmFwcGx5KF9odW5rJGxpbmVzMiwgX3RvQ29uc3VtYWJsZUFycmF5KGNvbGxlY3RDaGFuZ2UodGhlaXIpKSk7XG4gICAgICB9IGVsc2UgaWYgKG1pbmVDdXJyZW50WzBdID09PSAnLScgJiYgdGhlaXJDdXJyZW50WzBdID09PSAnICcpIHtcbiAgICAgICAgLy8gTWluZSByZW1vdmVkIG9yIGVkaXRlZFxuICAgICAgICByZW1vdmFsKGh1bmssIG1pbmUsIHRoZWlyKTtcbiAgICAgIH0gZWxzZSBpZiAodGhlaXJDdXJyZW50WzBdID09PSAnLScgJiYgbWluZUN1cnJlbnRbMF0gPT09ICcgJykge1xuICAgICAgICAvLyBUaGVpciByZW1vdmVkIG9yIGVkaXRlZFxuICAgICAgICByZW1vdmFsKGh1bmssIHRoZWlyLCBtaW5lLCB0cnVlKTtcbiAgICAgIH0gZWxzZSBpZiAobWluZUN1cnJlbnQgPT09IHRoZWlyQ3VycmVudCkge1xuICAgICAgICAvLyBDb250ZXh0IGlkZW50aXR5XG4gICAgICAgIGh1bmsubGluZXMucHVzaChtaW5lQ3VycmVudCk7XG4gICAgICAgIG1pbmUuaW5kZXgrKztcbiAgICAgICAgdGhlaXIuaW5kZXgrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIENvbnRleHQgbWlzbWF0Y2hcbiAgICAgICAgY29uZmxpY3QoaHVuaywgY29sbGVjdENoYW5nZShtaW5lKSwgY29sbGVjdENoYW5nZSh0aGVpcikpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIE5vdyBwdXNoIGFueXRoaW5nIHRoYXQgbWF5IGJlIHJlbWFpbmluZ1xuICAgIGluc2VydFRyYWlsaW5nKGh1bmssIG1pbmUpO1xuICAgIGluc2VydFRyYWlsaW5nKGh1bmssIHRoZWlyKTtcbiAgICBjYWxjTGluZUNvdW50KGh1bmspO1xuICB9XG4gIGZ1bmN0aW9uIG11dHVhbENoYW5nZShodW5rLCBtaW5lLCB0aGVpcikge1xuICAgIHZhciBteUNoYW5nZXMgPSBjb2xsZWN0Q2hhbmdlKG1pbmUpLFxuICAgICAgdGhlaXJDaGFuZ2VzID0gY29sbGVjdENoYW5nZSh0aGVpcik7XG4gICAgaWYgKGFsbFJlbW92ZXMobXlDaGFuZ2VzKSAmJiBhbGxSZW1vdmVzKHRoZWlyQ2hhbmdlcykpIHtcbiAgICAgIC8vIFNwZWNpYWwgY2FzZSBmb3IgcmVtb3ZlIGNoYW5nZXMgdGhhdCBhcmUgc3VwZXJzZXRzIG9mIG9uZSBhbm90aGVyXG4gICAgICBpZiAoYXJyYXlTdGFydHNXaXRoKG15Q2hhbmdlcywgdGhlaXJDaGFuZ2VzKSAmJiBza2lwUmVtb3ZlU3VwZXJzZXQodGhlaXIsIG15Q2hhbmdlcywgbXlDaGFuZ2VzLmxlbmd0aCAtIHRoZWlyQ2hhbmdlcy5sZW5ndGgpKSB7XG4gICAgICAgIHZhciBfaHVuayRsaW5lczM7XG4gICAgICAgIChfaHVuayRsaW5lczMgPSBodW5rLmxpbmVzKS5wdXNoLmFwcGx5KF9odW5rJGxpbmVzMywgX3RvQ29uc3VtYWJsZUFycmF5KG15Q2hhbmdlcykpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9IGVsc2UgaWYgKGFycmF5U3RhcnRzV2l0aCh0aGVpckNoYW5nZXMsIG15Q2hhbmdlcykgJiYgc2tpcFJlbW92ZVN1cGVyc2V0KG1pbmUsIHRoZWlyQ2hhbmdlcywgdGhlaXJDaGFuZ2VzLmxlbmd0aCAtIG15Q2hhbmdlcy5sZW5ndGgpKSB7XG4gICAgICAgIHZhciBfaHVuayRsaW5lczQ7XG4gICAgICAgIChfaHVuayRsaW5lczQgPSBodW5rLmxpbmVzKS5wdXNoLmFwcGx5KF9odW5rJGxpbmVzNCwgX3RvQ29uc3VtYWJsZUFycmF5KHRoZWlyQ2hhbmdlcykpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChhcnJheUVxdWFsKG15Q2hhbmdlcywgdGhlaXJDaGFuZ2VzKSkge1xuICAgICAgdmFyIF9odW5rJGxpbmVzNTtcbiAgICAgIChfaHVuayRsaW5lczUgPSBodW5rLmxpbmVzKS5wdXNoLmFwcGx5KF9odW5rJGxpbmVzNSwgX3RvQ29uc3VtYWJsZUFycmF5KG15Q2hhbmdlcykpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25mbGljdChodW5rLCBteUNoYW5nZXMsIHRoZWlyQ2hhbmdlcyk7XG4gIH1cbiAgZnVuY3Rpb24gcmVtb3ZhbChodW5rLCBtaW5lLCB0aGVpciwgc3dhcCkge1xuICAgIHZhciBteUNoYW5nZXMgPSBjb2xsZWN0Q2hhbmdlKG1pbmUpLFxuICAgICAgdGhlaXJDaGFuZ2VzID0gY29sbGVjdENvbnRleHQodGhlaXIsIG15Q2hhbmdlcyk7XG4gICAgaWYgKHRoZWlyQ2hhbmdlcy5tZXJnZWQpIHtcbiAgICAgIHZhciBfaHVuayRsaW5lczY7XG4gICAgICAoX2h1bmskbGluZXM2ID0gaHVuay5saW5lcykucHVzaC5hcHBseShfaHVuayRsaW5lczYsIF90b0NvbnN1bWFibGVBcnJheSh0aGVpckNoYW5nZXMubWVyZ2VkKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbmZsaWN0KGh1bmssIHN3YXAgPyB0aGVpckNoYW5nZXMgOiBteUNoYW5nZXMsIHN3YXAgPyBteUNoYW5nZXMgOiB0aGVpckNoYW5nZXMpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBjb25mbGljdChodW5rLCBtaW5lLCB0aGVpcikge1xuICAgIGh1bmsuY29uZmxpY3QgPSB0cnVlO1xuICAgIGh1bmsubGluZXMucHVzaCh7XG4gICAgICBjb25mbGljdDogdHJ1ZSxcbiAgICAgIG1pbmU6IG1pbmUsXG4gICAgICB0aGVpcnM6IHRoZWlyXG4gICAgfSk7XG4gIH1cbiAgZnVuY3Rpb24gaW5zZXJ0TGVhZGluZyhodW5rLCBpbnNlcnQsIHRoZWlyKSB7XG4gICAgd2hpbGUgKGluc2VydC5vZmZzZXQgPCB0aGVpci5vZmZzZXQgJiYgaW5zZXJ0LmluZGV4IDwgaW5zZXJ0LmxpbmVzLmxlbmd0aCkge1xuICAgICAgdmFyIGxpbmUgPSBpbnNlcnQubGluZXNbaW5zZXJ0LmluZGV4KytdO1xuICAgICAgaHVuay5saW5lcy5wdXNoKGxpbmUpO1xuICAgICAgaW5zZXJ0Lm9mZnNldCsrO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBpbnNlcnRUcmFpbGluZyhodW5rLCBpbnNlcnQpIHtcbiAgICB3aGlsZSAoaW5zZXJ0LmluZGV4IDwgaW5zZXJ0LmxpbmVzLmxlbmd0aCkge1xuICAgICAgdmFyIGxpbmUgPSBpbnNlcnQubGluZXNbaW5zZXJ0LmluZGV4KytdO1xuICAgICAgaHVuay5saW5lcy5wdXNoKGxpbmUpO1xuICAgIH1cbiAgfVxuICBmdW5jdGlvbiBjb2xsZWN0Q2hhbmdlKHN0YXRlKSB7XG4gICAgdmFyIHJldCA9IFtdLFxuICAgICAgb3BlcmF0aW9uID0gc3RhdGUubGluZXNbc3RhdGUuaW5kZXhdWzBdO1xuICAgIHdoaWxlIChzdGF0ZS5pbmRleCA8IHN0YXRlLmxpbmVzLmxlbmd0aCkge1xuICAgICAgdmFyIGxpbmUgPSBzdGF0ZS5saW5lc1tzdGF0ZS5pbmRleF07XG5cbiAgICAgIC8vIEdyb3VwIGFkZGl0aW9ucyB0aGF0IGFyZSBpbW1lZGlhdGVseSBhZnRlciBzdWJ0cmFjdGlvbnMgYW5kIHRyZWF0IHRoZW0gYXMgb25lIFwiYXRvbWljXCIgbW9kaWZ5IGNoYW5nZS5cbiAgICAgIGlmIChvcGVyYXRpb24gPT09ICctJyAmJiBsaW5lWzBdID09PSAnKycpIHtcbiAgICAgICAgb3BlcmF0aW9uID0gJysnO1xuICAgICAgfVxuICAgICAgaWYgKG9wZXJhdGlvbiA9PT0gbGluZVswXSkge1xuICAgICAgICByZXQucHVzaChsaW5lKTtcbiAgICAgICAgc3RhdGUuaW5kZXgrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmV0O1xuICB9XG4gIGZ1bmN0aW9uIGNvbGxlY3RDb250ZXh0KHN0YXRlLCBtYXRjaENoYW5nZXMpIHtcbiAgICB2YXIgY2hhbmdlcyA9IFtdLFxuICAgICAgbWVyZ2VkID0gW10sXG4gICAgICBtYXRjaEluZGV4ID0gMCxcbiAgICAgIGNvbnRleHRDaGFuZ2VzID0gZmFsc2UsXG4gICAgICBjb25mbGljdGVkID0gZmFsc2U7XG4gICAgd2hpbGUgKG1hdGNoSW5kZXggPCBtYXRjaENoYW5nZXMubGVuZ3RoICYmIHN0YXRlLmluZGV4IDwgc3RhdGUubGluZXMubGVuZ3RoKSB7XG4gICAgICB2YXIgY2hhbmdlID0gc3RhdGUubGluZXNbc3RhdGUuaW5kZXhdLFxuICAgICAgICBtYXRjaCA9IG1hdGNoQ2hhbmdlc1ttYXRjaEluZGV4XTtcblxuICAgICAgLy8gT25jZSB3ZSd2ZSBoaXQgb3VyIGFkZCwgdGhlbiB3ZSBhcmUgZG9uZVxuICAgICAgaWYgKG1hdGNoWzBdID09PSAnKycpIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjb250ZXh0Q2hhbmdlcyA9IGNvbnRleHRDaGFuZ2VzIHx8IGNoYW5nZVswXSAhPT0gJyAnO1xuICAgICAgbWVyZ2VkLnB1c2gobWF0Y2gpO1xuICAgICAgbWF0Y2hJbmRleCsrO1xuXG4gICAgICAvLyBDb25zdW1lIGFueSBhZGRpdGlvbnMgaW4gdGhlIG90aGVyIGJsb2NrIGFzIGEgY29uZmxpY3QgdG8gYXR0ZW1wdFxuICAgICAgLy8gdG8gcHVsbCBpbiB0aGUgcmVtYWluaW5nIGNvbnRleHQgYWZ0ZXIgdGhpc1xuICAgICAgaWYgKGNoYW5nZVswXSA9PT0gJysnKSB7XG4gICAgICAgIGNvbmZsaWN0ZWQgPSB0cnVlO1xuICAgICAgICB3aGlsZSAoY2hhbmdlWzBdID09PSAnKycpIHtcbiAgICAgICAgICBjaGFuZ2VzLnB1c2goY2hhbmdlKTtcbiAgICAgICAgICBjaGFuZ2UgPSBzdGF0ZS5saW5lc1srK3N0YXRlLmluZGV4XTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKG1hdGNoLnN1YnN0cigxKSA9PT0gY2hhbmdlLnN1YnN0cigxKSkge1xuICAgICAgICBjaGFuZ2VzLnB1c2goY2hhbmdlKTtcbiAgICAgICAgc3RhdGUuaW5kZXgrKztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbmZsaWN0ZWQgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoKG1hdGNoQ2hhbmdlc1ttYXRjaEluZGV4XSB8fCAnJylbMF0gPT09ICcrJyAmJiBjb250ZXh0Q2hhbmdlcykge1xuICAgICAgY29uZmxpY3RlZCA9IHRydWU7XG4gICAgfVxuICAgIGlmIChjb25mbGljdGVkKSB7XG4gICAgICByZXR1cm4gY2hhbmdlcztcbiAgICB9XG4gICAgd2hpbGUgKG1hdGNoSW5kZXggPCBtYXRjaENoYW5nZXMubGVuZ3RoKSB7XG4gICAgICBtZXJnZWQucHVzaChtYXRjaENoYW5nZXNbbWF0Y2hJbmRleCsrXSk7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBtZXJnZWQ6IG1lcmdlZCxcbiAgICAgIGNoYW5nZXM6IGNoYW5nZXNcbiAgICB9O1xuICB9XG4gIGZ1bmN0aW9uIGFsbFJlbW92ZXMoY2hhbmdlcykge1xuICAgIHJldHVybiBjaGFuZ2VzLnJlZHVjZShmdW5jdGlvbiAocHJldiwgY2hhbmdlKSB7XG4gICAgICByZXR1cm4gcHJldiAmJiBjaGFuZ2VbMF0gPT09ICctJztcbiAgICB9LCB0cnVlKTtcbiAgfVxuICBmdW5jdGlvbiBza2lwUmVtb3ZlU3VwZXJzZXQoc3RhdGUsIHJlbW92ZUNoYW5nZXMsIGRlbHRhKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBkZWx0YTsgaSsrKSB7XG4gICAgICB2YXIgY2hhbmdlQ29udGVudCA9IHJlbW92ZUNoYW5nZXNbcmVtb3ZlQ2hhbmdlcy5sZW5ndGggLSBkZWx0YSArIGldLnN1YnN0cigxKTtcbiAgICAgIGlmIChzdGF0ZS5saW5lc1tzdGF0ZS5pbmRleCArIGldICE9PSAnICcgKyBjaGFuZ2VDb250ZW50KSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgc3RhdGUuaW5kZXggKz0gZGVsdGE7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgZnVuY3Rpb24gY2FsY09sZE5ld0xpbmVDb3VudChsaW5lcykge1xuICAgIHZhciBvbGRMaW5lcyA9IDA7XG4gICAgdmFyIG5ld0xpbmVzID0gMDtcbiAgICBsaW5lcy5mb3JFYWNoKGZ1bmN0aW9uIChsaW5lKSB7XG4gICAgICBpZiAodHlwZW9mIGxpbmUgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHZhciBteUNvdW50ID0gY2FsY09sZE5ld0xpbmVDb3VudChsaW5lLm1pbmUpO1xuICAgICAgICB2YXIgdGhlaXJDb3VudCA9IGNhbGNPbGROZXdMaW5lQ291bnQobGluZS50aGVpcnMpO1xuICAgICAgICBpZiAob2xkTGluZXMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgIGlmIChteUNvdW50Lm9sZExpbmVzID09PSB0aGVpckNvdW50Lm9sZExpbmVzKSB7XG4gICAgICAgICAgICBvbGRMaW5lcyArPSBteUNvdW50Lm9sZExpbmVzO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvbGRMaW5lcyA9IHVuZGVmaW5lZDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5ld0xpbmVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBpZiAobXlDb3VudC5uZXdMaW5lcyA9PT0gdGhlaXJDb3VudC5uZXdMaW5lcykge1xuICAgICAgICAgICAgbmV3TGluZXMgKz0gbXlDb3VudC5uZXdMaW5lcztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmV3TGluZXMgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAobmV3TGluZXMgIT09IHVuZGVmaW5lZCAmJiAobGluZVswXSA9PT0gJysnIHx8IGxpbmVbMF0gPT09ICcgJykpIHtcbiAgICAgICAgICBuZXdMaW5lcysrO1xuICAgICAgICB9XG4gICAgICAgIGlmIChvbGRMaW5lcyAhPT0gdW5kZWZpbmVkICYmIChsaW5lWzBdID09PSAnLScgfHwgbGluZVswXSA9PT0gJyAnKSkge1xuICAgICAgICAgIG9sZExpbmVzKys7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4ge1xuICAgICAgb2xkTGluZXM6IG9sZExpbmVzLFxuICAgICAgbmV3TGluZXM6IG5ld0xpbmVzXG4gICAgfTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJldmVyc2VQYXRjaChzdHJ1Y3R1cmVkUGF0Y2gpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShzdHJ1Y3R1cmVkUGF0Y2gpKSB7XG4gICAgICByZXR1cm4gc3RydWN0dXJlZFBhdGNoLm1hcChyZXZlcnNlUGF0Y2gpLnJldmVyc2UoKTtcbiAgICB9XG4gICAgcmV0dXJuIF9vYmplY3RTcHJlYWQyKF9vYmplY3RTcHJlYWQyKHt9LCBzdHJ1Y3R1cmVkUGF0Y2gpLCB7fSwge1xuICAgICAgb2xkRmlsZU5hbWU6IHN0cnVjdHVyZWRQYXRjaC5uZXdGaWxlTmFtZSxcbiAgICAgIG9sZEhlYWRlcjogc3RydWN0dXJlZFBhdGNoLm5ld0hlYWRlcixcbiAgICAgIG5ld0ZpbGVOYW1lOiBzdHJ1Y3R1cmVkUGF0Y2gub2xkRmlsZU5hbWUsXG4gICAgICBuZXdIZWFkZXI6IHN0cnVjdHVyZWRQYXRjaC5vbGRIZWFkZXIsXG4gICAgICBodW5rczogc3RydWN0dXJlZFBhdGNoLmh1bmtzLm1hcChmdW5jdGlvbiAoaHVuaykge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG9sZExpbmVzOiBodW5rLm5ld0xpbmVzLFxuICAgICAgICAgIG9sZFN0YXJ0OiBodW5rLm5ld1N0YXJ0LFxuICAgICAgICAgIG5ld0xpbmVzOiBodW5rLm9sZExpbmVzLFxuICAgICAgICAgIG5ld1N0YXJ0OiBodW5rLm9sZFN0YXJ0LFxuICAgICAgICAgIGxpbmVzOiBodW5rLmxpbmVzLm1hcChmdW5jdGlvbiAobCkge1xuICAgICAgICAgICAgaWYgKGwuc3RhcnRzV2l0aCgnLScpKSB7XG4gICAgICAgICAgICAgIHJldHVybiBcIitcIi5jb25jYXQobC5zbGljZSgxKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobC5zdGFydHNXaXRoKCcrJykpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIFwiLVwiLmNvbmNhdChsLnNsaWNlKDEpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBsO1xuICAgICAgICAgIH0pXG4gICAgICAgIH07XG4gICAgICB9KVxuICAgIH0pO1xuICB9XG5cbiAgLy8gU2VlOiBodHRwOi8vY29kZS5nb29nbGUuY29tL3AvZ29vZ2xlLWRpZmYtbWF0Y2gtcGF0Y2gvd2lraS9BUElcbiAgZnVuY3Rpb24gY29udmVydENoYW5nZXNUb0RNUChjaGFuZ2VzKSB7XG4gICAgdmFyIHJldCA9IFtdLFxuICAgICAgY2hhbmdlLFxuICAgICAgb3BlcmF0aW9uO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hhbmdlcy5sZW5ndGg7IGkrKykge1xuICAgICAgY2hhbmdlID0gY2hhbmdlc1tpXTtcbiAgICAgIGlmIChjaGFuZ2UuYWRkZWQpIHtcbiAgICAgICAgb3BlcmF0aW9uID0gMTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhbmdlLnJlbW92ZWQpIHtcbiAgICAgICAgb3BlcmF0aW9uID0gLTE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcGVyYXRpb24gPSAwO1xuICAgICAgfVxuICAgICAgcmV0LnB1c2goW29wZXJhdGlvbiwgY2hhbmdlLnZhbHVlXSk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICBmdW5jdGlvbiBjb252ZXJ0Q2hhbmdlc1RvWE1MKGNoYW5nZXMpIHtcbiAgICB2YXIgcmV0ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGFuZ2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhbmdlID0gY2hhbmdlc1tpXTtcbiAgICAgIGlmIChjaGFuZ2UuYWRkZWQpIHtcbiAgICAgICAgcmV0LnB1c2goJzxpbnM+Jyk7XG4gICAgICB9IGVsc2UgaWYgKGNoYW5nZS5yZW1vdmVkKSB7XG4gICAgICAgIHJldC5wdXNoKCc8ZGVsPicpO1xuICAgICAgfVxuICAgICAgcmV0LnB1c2goZXNjYXBlSFRNTChjaGFuZ2UudmFsdWUpKTtcbiAgICAgIGlmIChjaGFuZ2UuYWRkZWQpIHtcbiAgICAgICAgcmV0LnB1c2goJzwvaW5zPicpO1xuICAgICAgfSBlbHNlIGlmIChjaGFuZ2UucmVtb3ZlZCkge1xuICAgICAgICByZXQucHVzaCgnPC9kZWw+Jyk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXQuam9pbignJyk7XG4gIH1cbiAgZnVuY3Rpb24gZXNjYXBlSFRNTChzKSB7XG4gICAgdmFyIG4gPSBzO1xuICAgIG4gPSBuLnJlcGxhY2UoLyYvZywgJyZhbXA7Jyk7XG4gICAgbiA9IG4ucmVwbGFjZSgvPC9nLCAnJmx0OycpO1xuICAgIG4gPSBuLnJlcGxhY2UoLz4vZywgJyZndDsnKTtcbiAgICBuID0gbi5yZXBsYWNlKC9cIi9nLCAnJnF1b3Q7Jyk7XG4gICAgcmV0dXJuIG47XG4gIH1cblxuICBleHBvcnRzLkRpZmYgPSBEaWZmO1xuICBleHBvcnRzLmFwcGx5UGF0Y2ggPSBhcHBseVBhdGNoO1xuICBleHBvcnRzLmFwcGx5UGF0Y2hlcyA9IGFwcGx5UGF0Y2hlcztcbiAgZXhwb3J0cy5jYW5vbmljYWxpemUgPSBjYW5vbmljYWxpemU7XG4gIGV4cG9ydHMuY29udmVydENoYW5nZXNUb0RNUCA9IGNvbnZlcnRDaGFuZ2VzVG9ETVA7XG4gIGV4cG9ydHMuY29udmVydENoYW5nZXNUb1hNTCA9IGNvbnZlcnRDaGFuZ2VzVG9YTUw7XG4gIGV4cG9ydHMuY3JlYXRlUGF0Y2ggPSBjcmVhdGVQYXRjaDtcbiAgZXhwb3J0cy5jcmVhdGVUd29GaWxlc1BhdGNoID0gY3JlYXRlVHdvRmlsZXNQYXRjaDtcbiAgZXhwb3J0cy5kaWZmQXJyYXlzID0gZGlmZkFycmF5cztcbiAgZXhwb3J0cy5kaWZmQ2hhcnMgPSBkaWZmQ2hhcnM7XG4gIGV4cG9ydHMuZGlmZkNzcyA9IGRpZmZDc3M7XG4gIGV4cG9ydHMuZGlmZkpzb24gPSBkaWZmSnNvbjtcbiAgZXhwb3J0cy5kaWZmTGluZXMgPSBkaWZmTGluZXM7XG4gIGV4cG9ydHMuZGlmZlNlbnRlbmNlcyA9IGRpZmZTZW50ZW5jZXM7XG4gIGV4cG9ydHMuZGlmZlRyaW1tZWRMaW5lcyA9IGRpZmZUcmltbWVkTGluZXM7XG4gIGV4cG9ydHMuZGlmZldvcmRzID0gZGlmZldvcmRzO1xuICBleHBvcnRzLmRpZmZXb3Jkc1dpdGhTcGFjZSA9IGRpZmZXb3Jkc1dpdGhTcGFjZTtcbiAgZXhwb3J0cy5mb3JtYXRQYXRjaCA9IGZvcm1hdFBhdGNoO1xuICBleHBvcnRzLm1lcmdlID0gbWVyZ2U7XG4gIGV4cG9ydHMucGFyc2VQYXRjaCA9IHBhcnNlUGF0Y2g7XG4gIGV4cG9ydHMucmV2ZXJzZVBhdGNoID0gcmV2ZXJzZVBhdGNoO1xuICBleHBvcnRzLnN0cnVjdHVyZWRQYXRjaCA9IHN0cnVjdHVyZWRQYXRjaDtcblxufSkpO1xuIiwiLyoqXG4gKiBsb2Rhc2ggKEN1c3RvbSBCdWlsZCkgPGh0dHBzOi8vbG9kYXNoLmNvbS8+XG4gKiBCdWlsZDogYGxvZGFzaCBtb2R1bGFyaXplIGV4cG9ydHM9XCJucG1cIiAtbyAuL2BcbiAqIENvcHlyaWdodCBqUXVlcnkgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzIDxodHRwczovL2pxdWVyeS5vcmcvPlxuICogUmVsZWFzZWQgdW5kZXIgTUlUIGxpY2Vuc2UgPGh0dHBzOi8vbG9kYXNoLmNvbS9saWNlbnNlPlxuICogQmFzZWQgb24gVW5kZXJzY29yZS5qcyAxLjguMyA8aHR0cDovL3VuZGVyc2NvcmVqcy5vcmcvTElDRU5TRT5cbiAqIENvcHlyaWdodCBKZXJlbXkgQXNoa2VuYXMsIERvY3VtZW50Q2xvdWQgYW5kIEludmVzdGlnYXRpdmUgUmVwb3J0ZXJzICYgRWRpdG9yc1xuICovXG5cbi8qKiBVc2VkIGFzIHRoZSBgVHlwZUVycm9yYCBtZXNzYWdlIGZvciBcIkZ1bmN0aW9uc1wiIG1ldGhvZHMuICovXG52YXIgRlVOQ19FUlJPUl9URVhUID0gJ0V4cGVjdGVkIGEgZnVuY3Rpb24nO1xuXG4vKiogVXNlZCB0byBzdGFuZC1pbiBmb3IgYHVuZGVmaW5lZGAgaGFzaCB2YWx1ZXMuICovXG52YXIgSEFTSF9VTkRFRklORUQgPSAnX19sb2Rhc2hfaGFzaF91bmRlZmluZWRfXyc7XG5cbi8qKiBVc2VkIGFzIHJlZmVyZW5jZXMgZm9yIHZhcmlvdXMgYE51bWJlcmAgY29uc3RhbnRzLiAqL1xudmFyIElORklOSVRZID0gMSAvIDA7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBmdW5jVGFnID0gJ1tvYmplY3QgRnVuY3Rpb25dJyxcbiAgICBnZW5UYWcgPSAnW29iamVjdCBHZW5lcmF0b3JGdW5jdGlvbl0nLFxuICAgIHN5bWJvbFRhZyA9ICdbb2JqZWN0IFN5bWJvbF0nO1xuXG4vKiogVXNlZCB0byBtYXRjaCBwcm9wZXJ0eSBuYW1lcyB3aXRoaW4gcHJvcGVydHkgcGF0aHMuICovXG52YXIgcmVJc0RlZXBQcm9wID0gL1xcLnxcXFsoPzpbXltcXF1dKnwoW1wiJ10pKD86KD8hXFwxKVteXFxcXF18XFxcXC4pKj9cXDEpXFxdLyxcbiAgICByZUlzUGxhaW5Qcm9wID0gL15cXHcqJC8sXG4gICAgcmVMZWFkaW5nRG90ID0gL15cXC4vLFxuICAgIHJlUHJvcE5hbWUgPSAvW14uW1xcXV0rfFxcWyg/OigtP1xcZCsoPzpcXC5cXGQrKT8pfChbXCInXSkoKD86KD8hXFwyKVteXFxcXF18XFxcXC4pKj8pXFwyKVxcXXwoPz0oPzpcXC58XFxbXFxdKSg/OlxcLnxcXFtcXF18JCkpL2c7XG5cbi8qKlxuICogVXNlZCB0byBtYXRjaCBgUmVnRXhwYFxuICogW3N5bnRheCBjaGFyYWN0ZXJzXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1wYXR0ZXJucykuXG4gKi9cbnZhciByZVJlZ0V4cENoYXIgPSAvW1xcXFxeJC4qKz8oKVtcXF17fXxdL2c7XG5cbi8qKiBVc2VkIHRvIG1hdGNoIGJhY2tzbGFzaGVzIGluIHByb3BlcnR5IHBhdGhzLiAqL1xudmFyIHJlRXNjYXBlQ2hhciA9IC9cXFxcKFxcXFwpPy9nO1xuXG4vKiogVXNlZCB0byBkZXRlY3QgaG9zdCBjb25zdHJ1Y3RvcnMgKFNhZmFyaSkuICovXG52YXIgcmVJc0hvc3RDdG9yID0gL15cXFtvYmplY3QgLis/Q29uc3RydWN0b3JcXF0kLztcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBnbG9iYWxgIGZyb20gTm9kZS5qcy4gKi9cbnZhciBmcmVlR2xvYmFsID0gdHlwZW9mIGdsb2JhbCA9PSAnb2JqZWN0JyAmJiBnbG9iYWwgJiYgZ2xvYmFsLk9iamVjdCA9PT0gT2JqZWN0ICYmIGdsb2JhbDtcblxuLyoqIERldGVjdCBmcmVlIHZhcmlhYmxlIGBzZWxmYC4gKi9cbnZhciBmcmVlU2VsZiA9IHR5cGVvZiBzZWxmID09ICdvYmplY3QnICYmIHNlbGYgJiYgc2VsZi5PYmplY3QgPT09IE9iamVjdCAmJiBzZWxmO1xuXG4vKiogVXNlZCBhcyBhIHJlZmVyZW5jZSB0byB0aGUgZ2xvYmFsIG9iamVjdC4gKi9cbnZhciByb290ID0gZnJlZUdsb2JhbCB8fCBmcmVlU2VsZiB8fCBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpO1xuXG4vKipcbiAqIEdldHMgdGhlIHZhbHVlIGF0IGBrZXlgIG9mIGBvYmplY3RgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gW29iamVjdF0gVGhlIG9iamVjdCB0byBxdWVyeS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIHByb3BlcnR5IHZhbHVlLlxuICovXG5mdW5jdGlvbiBnZXRWYWx1ZShvYmplY3QsIGtleSkge1xuICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyB1bmRlZmluZWQgOiBvYmplY3Rba2V5XTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIGhvc3Qgb2JqZWN0IGluIElFIDwgOS5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIGhvc3Qgb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGlzSG9zdE9iamVjdCh2YWx1ZSkge1xuICAvLyBNYW55IGhvc3Qgb2JqZWN0cyBhcmUgYE9iamVjdGAgb2JqZWN0cyB0aGF0IGNhbiBjb2VyY2UgdG8gc3RyaW5nc1xuICAvLyBkZXNwaXRlIGhhdmluZyBpbXByb3Blcmx5IGRlZmluZWQgYHRvU3RyaW5nYCBtZXRob2RzLlxuICB2YXIgcmVzdWx0ID0gZmFsc2U7XG4gIGlmICh2YWx1ZSAhPSBudWxsICYmIHR5cGVvZiB2YWx1ZS50b1N0cmluZyAhPSAnZnVuY3Rpb24nKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9ICEhKHZhbHVlICsgJycpO1xuICAgIH0gY2F0Y2ggKGUpIHt9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqIFVzZWQgZm9yIGJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIGFycmF5UHJvdG8gPSBBcnJheS5wcm90b3R5cGUsXG4gICAgZnVuY1Byb3RvID0gRnVuY3Rpb24ucHJvdG90eXBlLFxuICAgIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IG92ZXJyZWFjaGluZyBjb3JlLWpzIHNoaW1zLiAqL1xudmFyIGNvcmVKc0RhdGEgPSByb290WydfX2NvcmUtanNfc2hhcmVkX18nXTtcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IG1ldGhvZHMgbWFzcXVlcmFkaW5nIGFzIG5hdGl2ZS4gKi9cbnZhciBtYXNrU3JjS2V5ID0gKGZ1bmN0aW9uKCkge1xuICB2YXIgdWlkID0gL1teLl0rJC8uZXhlYyhjb3JlSnNEYXRhICYmIGNvcmVKc0RhdGEua2V5cyAmJiBjb3JlSnNEYXRhLmtleXMuSUVfUFJPVE8gfHwgJycpO1xuICByZXR1cm4gdWlkID8gKCdTeW1ib2woc3JjKV8xLicgKyB1aWQpIDogJyc7XG59KCkpO1xuXG4vKiogVXNlZCB0byByZXNvbHZlIHRoZSBkZWNvbXBpbGVkIHNvdXJjZSBvZiBmdW5jdGlvbnMuICovXG52YXIgZnVuY1RvU3RyaW5nID0gZnVuY1Byb3RvLnRvU3RyaW5nO1xuXG4vKiogVXNlZCB0byBjaGVjayBvYmplY3RzIGZvciBvd24gcHJvcGVydGllcy4gKi9cbnZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4vKipcbiAqIFVzZWQgdG8gcmVzb2x2ZSB0aGVcbiAqIFtgdG9TdHJpbmdUYWdgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1vYmplY3QucHJvdG90eXBlLnRvc3RyaW5nKVxuICogb2YgdmFsdWVzLlxuICovXG52YXIgb2JqZWN0VG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IGlmIGEgbWV0aG9kIGlzIG5hdGl2ZS4gKi9cbnZhciByZUlzTmF0aXZlID0gUmVnRXhwKCdeJyArXG4gIGZ1bmNUb1N0cmluZy5jYWxsKGhhc093blByb3BlcnR5KS5yZXBsYWNlKHJlUmVnRXhwQ2hhciwgJ1xcXFwkJicpXG4gIC5yZXBsYWNlKC9oYXNPd25Qcm9wZXJ0eXwoZnVuY3Rpb24pLio/KD89XFxcXFxcKCl8IGZvciAuKz8oPz1cXFxcXFxdKS9nLCAnJDEuKj8nKSArICckJ1xuKTtcblxuLyoqIEJ1aWx0LWluIHZhbHVlIHJlZmVyZW5jZXMuICovXG52YXIgU3ltYm9sID0gcm9vdC5TeW1ib2wsXG4gICAgc3BsaWNlID0gYXJyYXlQcm90by5zcGxpY2U7XG5cbi8qIEJ1aWx0LWluIG1ldGhvZCByZWZlcmVuY2VzIHRoYXQgYXJlIHZlcmlmaWVkIHRvIGJlIG5hdGl2ZS4gKi9cbnZhciBNYXAgPSBnZXROYXRpdmUocm9vdCwgJ01hcCcpLFxuICAgIG5hdGl2ZUNyZWF0ZSA9IGdldE5hdGl2ZShPYmplY3QsICdjcmVhdGUnKTtcblxuLyoqIFVzZWQgdG8gY29udmVydCBzeW1ib2xzIHRvIHByaW1pdGl2ZXMgYW5kIHN0cmluZ3MuICovXG52YXIgc3ltYm9sUHJvdG8gPSBTeW1ib2wgPyBTeW1ib2wucHJvdG90eXBlIDogdW5kZWZpbmVkLFxuICAgIHN5bWJvbFRvU3RyaW5nID0gc3ltYm9sUHJvdG8gPyBzeW1ib2xQcm90by50b1N0cmluZyA6IHVuZGVmaW5lZDtcblxuLyoqXG4gKiBDcmVhdGVzIGEgaGFzaCBvYmplY3QuXG4gKlxuICogQHByaXZhdGVcbiAqIEBjb25zdHJ1Y3RvclxuICogQHBhcmFtIHtBcnJheX0gW2VudHJpZXNdIFRoZSBrZXktdmFsdWUgcGFpcnMgdG8gY2FjaGUuXG4gKi9cbmZ1bmN0aW9uIEhhc2goZW50cmllcykge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIGxlbmd0aCA9IGVudHJpZXMgPyBlbnRyaWVzLmxlbmd0aCA6IDA7XG5cbiAgdGhpcy5jbGVhcigpO1xuICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgIHZhciBlbnRyeSA9IGVudHJpZXNbaW5kZXhdO1xuICAgIHRoaXMuc2V0KGVudHJ5WzBdLCBlbnRyeVsxXSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZW1vdmVzIGFsbCBrZXktdmFsdWUgZW50cmllcyBmcm9tIHRoZSBoYXNoLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBjbGVhclxuICogQG1lbWJlck9mIEhhc2hcbiAqL1xuZnVuY3Rpb24gaGFzaENsZWFyKCkge1xuICB0aGlzLl9fZGF0YV9fID0gbmF0aXZlQ3JlYXRlID8gbmF0aXZlQ3JlYXRlKG51bGwpIDoge307XG59XG5cbi8qKlxuICogUmVtb3ZlcyBga2V5YCBhbmQgaXRzIHZhbHVlIGZyb20gdGhlIGhhc2guXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIGRlbGV0ZVxuICogQG1lbWJlck9mIEhhc2hcbiAqIEBwYXJhbSB7T2JqZWN0fSBoYXNoIFRoZSBoYXNoIHRvIG1vZGlmeS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gcmVtb3ZlLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBlbnRyeSB3YXMgcmVtb3ZlZCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBoYXNoRGVsZXRlKGtleSkge1xuICByZXR1cm4gdGhpcy5oYXMoa2V5KSAmJiBkZWxldGUgdGhpcy5fX2RhdGFfX1trZXldO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIGhhc2ggdmFsdWUgZm9yIGBrZXlgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBnZXRcbiAqIEBtZW1iZXJPZiBIYXNoXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIGdldC5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBlbnRyeSB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gaGFzaEdldChrZXkpIHtcbiAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICBpZiAobmF0aXZlQ3JlYXRlKSB7XG4gICAgdmFyIHJlc3VsdCA9IGRhdGFba2V5XTtcbiAgICByZXR1cm4gcmVzdWx0ID09PSBIQVNIX1VOREVGSU5FRCA/IHVuZGVmaW5lZCA6IHJlc3VsdDtcbiAgfVxuICByZXR1cm4gaGFzT3duUHJvcGVydHkuY2FsbChkYXRhLCBrZXkpID8gZGF0YVtrZXldIDogdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIGhhc2ggdmFsdWUgZm9yIGBrZXlgIGV4aXN0cy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgaGFzXG4gKiBAbWVtYmVyT2YgSGFzaFxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBlbnRyeSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbiBlbnRyeSBmb3IgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGhhc2hIYXMoa2V5KSB7XG4gIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXztcbiAgcmV0dXJuIG5hdGl2ZUNyZWF0ZSA/IGRhdGFba2V5XSAhPT0gdW5kZWZpbmVkIDogaGFzT3duUHJvcGVydHkuY2FsbChkYXRhLCBrZXkpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIGhhc2ggYGtleWAgdG8gYHZhbHVlYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgc2V0XG4gKiBAbWVtYmVyT2YgSGFzaFxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBzZXQuXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBoYXNoIGluc3RhbmNlLlxuICovXG5mdW5jdGlvbiBoYXNoU2V0KGtleSwgdmFsdWUpIHtcbiAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fO1xuICBkYXRhW2tleV0gPSAobmF0aXZlQ3JlYXRlICYmIHZhbHVlID09PSB1bmRlZmluZWQpID8gSEFTSF9VTkRFRklORUQgOiB2YWx1ZTtcbiAgcmV0dXJuIHRoaXM7XG59XG5cbi8vIEFkZCBtZXRob2RzIHRvIGBIYXNoYC5cbkhhc2gucHJvdG90eXBlLmNsZWFyID0gaGFzaENsZWFyO1xuSGFzaC5wcm90b3R5cGVbJ2RlbGV0ZSddID0gaGFzaERlbGV0ZTtcbkhhc2gucHJvdG90eXBlLmdldCA9IGhhc2hHZXQ7XG5IYXNoLnByb3RvdHlwZS5oYXMgPSBoYXNoSGFzO1xuSGFzaC5wcm90b3R5cGUuc2V0ID0gaGFzaFNldDtcblxuLyoqXG4gKiBDcmVhdGVzIGFuIGxpc3QgY2FjaGUgb2JqZWN0LlxuICpcbiAqIEBwcml2YXRlXG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7QXJyYXl9IFtlbnRyaWVzXSBUaGUga2V5LXZhbHVlIHBhaXJzIHRvIGNhY2hlLlxuICovXG5mdW5jdGlvbiBMaXN0Q2FjaGUoZW50cmllcykge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIGxlbmd0aCA9IGVudHJpZXMgPyBlbnRyaWVzLmxlbmd0aCA6IDA7XG5cbiAgdGhpcy5jbGVhcigpO1xuICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgIHZhciBlbnRyeSA9IGVudHJpZXNbaW5kZXhdO1xuICAgIHRoaXMuc2V0KGVudHJ5WzBdLCBlbnRyeVsxXSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZW1vdmVzIGFsbCBrZXktdmFsdWUgZW50cmllcyBmcm9tIHRoZSBsaXN0IGNhY2hlLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBjbGVhclxuICogQG1lbWJlck9mIExpc3RDYWNoZVxuICovXG5mdW5jdGlvbiBsaXN0Q2FjaGVDbGVhcigpIHtcbiAgdGhpcy5fX2RhdGFfXyA9IFtdO1xufVxuXG4vKipcbiAqIFJlbW92ZXMgYGtleWAgYW5kIGl0cyB2YWx1ZSBmcm9tIHRoZSBsaXN0IGNhY2hlLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBkZWxldGVcbiAqIEBtZW1iZXJPZiBMaXN0Q2FjaGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gcmVtb3ZlLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBlbnRyeSB3YXMgcmVtb3ZlZCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBsaXN0Q2FjaGVEZWxldGUoa2V5KSB7XG4gIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXyxcbiAgICAgIGluZGV4ID0gYXNzb2NJbmRleE9mKGRhdGEsIGtleSk7XG5cbiAgaWYgKGluZGV4IDwgMCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICB2YXIgbGFzdEluZGV4ID0gZGF0YS5sZW5ndGggLSAxO1xuICBpZiAoaW5kZXggPT0gbGFzdEluZGV4KSB7XG4gICAgZGF0YS5wb3AoKTtcbiAgfSBlbHNlIHtcbiAgICBzcGxpY2UuY2FsbChkYXRhLCBpbmRleCwgMSk7XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgbGlzdCBjYWNoZSB2YWx1ZSBmb3IgYGtleWAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBuYW1lIGdldFxuICogQG1lbWJlck9mIExpc3RDYWNoZVxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBnZXQuXG4gKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZW50cnkgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIGxpc3RDYWNoZUdldChrZXkpIHtcbiAgdmFyIGRhdGEgPSB0aGlzLl9fZGF0YV9fLFxuICAgICAgaW5kZXggPSBhc3NvY0luZGV4T2YoZGF0YSwga2V5KTtcblxuICByZXR1cm4gaW5kZXggPCAwID8gdW5kZWZpbmVkIDogZGF0YVtpbmRleF1bMV07XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGEgbGlzdCBjYWNoZSB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBoYXNcbiAqIEBtZW1iZXJPZiBMaXN0Q2FjaGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgZW50cnkgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYW4gZW50cnkgZm9yIGBrZXlgIGV4aXN0cywgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBsaXN0Q2FjaGVIYXMoa2V5KSB7XG4gIHJldHVybiBhc3NvY0luZGV4T2YodGhpcy5fX2RhdGFfXywga2V5KSA+IC0xO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIGxpc3QgY2FjaGUgYGtleWAgdG8gYHZhbHVlYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgc2V0XG4gKiBAbWVtYmVyT2YgTGlzdENhY2hlXG4gKiBAcGFyYW0ge3N0cmluZ30ga2V5IFRoZSBrZXkgb2YgdGhlIHZhbHVlIHRvIHNldC5cbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHNldC5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGxpc3QgY2FjaGUgaW5zdGFuY2UuXG4gKi9cbmZ1bmN0aW9uIGxpc3RDYWNoZVNldChrZXksIHZhbHVlKSB7XG4gIHZhciBkYXRhID0gdGhpcy5fX2RhdGFfXyxcbiAgICAgIGluZGV4ID0gYXNzb2NJbmRleE9mKGRhdGEsIGtleSk7XG5cbiAgaWYgKGluZGV4IDwgMCkge1xuICAgIGRhdGEucHVzaChba2V5LCB2YWx1ZV0pO1xuICB9IGVsc2Uge1xuICAgIGRhdGFbaW5kZXhdWzFdID0gdmFsdWU7XG4gIH1cbiAgcmV0dXJuIHRoaXM7XG59XG5cbi8vIEFkZCBtZXRob2RzIHRvIGBMaXN0Q2FjaGVgLlxuTGlzdENhY2hlLnByb3RvdHlwZS5jbGVhciA9IGxpc3RDYWNoZUNsZWFyO1xuTGlzdENhY2hlLnByb3RvdHlwZVsnZGVsZXRlJ10gPSBsaXN0Q2FjaGVEZWxldGU7XG5MaXN0Q2FjaGUucHJvdG90eXBlLmdldCA9IGxpc3RDYWNoZUdldDtcbkxpc3RDYWNoZS5wcm90b3R5cGUuaGFzID0gbGlzdENhY2hlSGFzO1xuTGlzdENhY2hlLnByb3RvdHlwZS5zZXQgPSBsaXN0Q2FjaGVTZXQ7XG5cbi8qKlxuICogQ3JlYXRlcyBhIG1hcCBjYWNoZSBvYmplY3QgdG8gc3RvcmUga2V5LXZhbHVlIHBhaXJzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAY29uc3RydWN0b3JcbiAqIEBwYXJhbSB7QXJyYXl9IFtlbnRyaWVzXSBUaGUga2V5LXZhbHVlIHBhaXJzIHRvIGNhY2hlLlxuICovXG5mdW5jdGlvbiBNYXBDYWNoZShlbnRyaWVzKSB7XG4gIHZhciBpbmRleCA9IC0xLFxuICAgICAgbGVuZ3RoID0gZW50cmllcyA/IGVudHJpZXMubGVuZ3RoIDogMDtcblxuICB0aGlzLmNsZWFyKCk7XG4gIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgdmFyIGVudHJ5ID0gZW50cmllc1tpbmRleF07XG4gICAgdGhpcy5zZXQoZW50cnlbMF0sIGVudHJ5WzFdKTtcbiAgfVxufVxuXG4vKipcbiAqIFJlbW92ZXMgYWxsIGtleS12YWx1ZSBlbnRyaWVzIGZyb20gdGhlIG1hcC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgY2xlYXJcbiAqIEBtZW1iZXJPZiBNYXBDYWNoZVxuICovXG5mdW5jdGlvbiBtYXBDYWNoZUNsZWFyKCkge1xuICB0aGlzLl9fZGF0YV9fID0ge1xuICAgICdoYXNoJzogbmV3IEhhc2gsXG4gICAgJ21hcCc6IG5ldyAoTWFwIHx8IExpc3RDYWNoZSksXG4gICAgJ3N0cmluZyc6IG5ldyBIYXNoXG4gIH07XG59XG5cbi8qKlxuICogUmVtb3ZlcyBga2V5YCBhbmQgaXRzIHZhbHVlIGZyb20gdGhlIG1hcC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQG5hbWUgZGVsZXRlXG4gKiBAbWVtYmVyT2YgTWFwQ2FjaGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgdmFsdWUgdG8gcmVtb3ZlLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSBlbnRyeSB3YXMgcmVtb3ZlZCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBtYXBDYWNoZURlbGV0ZShrZXkpIHtcbiAgcmV0dXJuIGdldE1hcERhdGEodGhpcywga2V5KVsnZGVsZXRlJ10oa2V5KTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBtYXAgdmFsdWUgZm9yIGBrZXlgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBnZXRcbiAqIEBtZW1iZXJPZiBNYXBDYWNoZVxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBnZXQuXG4gKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgZW50cnkgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIG1hcENhY2hlR2V0KGtleSkge1xuICByZXR1cm4gZ2V0TWFwRGF0YSh0aGlzLCBrZXkpLmdldChrZXkpO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBhIG1hcCB2YWx1ZSBmb3IgYGtleWAgZXhpc3RzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBoYXNcbiAqIEBtZW1iZXJPZiBNYXBDYWNoZVxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBlbnRyeSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhbiBlbnRyeSBmb3IgYGtleWAgZXhpc3RzLCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIG1hcENhY2hlSGFzKGtleSkge1xuICByZXR1cm4gZ2V0TWFwRGF0YSh0aGlzLCBrZXkpLmhhcyhrZXkpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIG1hcCBga2V5YCB0byBgdmFsdWVgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAbmFtZSBzZXRcbiAqIEBtZW1iZXJPZiBNYXBDYWNoZVxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSB2YWx1ZSB0byBzZXQuXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZXQuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBtYXAgY2FjaGUgaW5zdGFuY2UuXG4gKi9cbmZ1bmN0aW9uIG1hcENhY2hlU2V0KGtleSwgdmFsdWUpIHtcbiAgZ2V0TWFwRGF0YSh0aGlzLCBrZXkpLnNldChrZXksIHZhbHVlKTtcbiAgcmV0dXJuIHRoaXM7XG59XG5cbi8vIEFkZCBtZXRob2RzIHRvIGBNYXBDYWNoZWAuXG5NYXBDYWNoZS5wcm90b3R5cGUuY2xlYXIgPSBtYXBDYWNoZUNsZWFyO1xuTWFwQ2FjaGUucHJvdG90eXBlWydkZWxldGUnXSA9IG1hcENhY2hlRGVsZXRlO1xuTWFwQ2FjaGUucHJvdG90eXBlLmdldCA9IG1hcENhY2hlR2V0O1xuTWFwQ2FjaGUucHJvdG90eXBlLmhhcyA9IG1hcENhY2hlSGFzO1xuTWFwQ2FjaGUucHJvdG90eXBlLnNldCA9IG1hcENhY2hlU2V0O1xuXG4vKipcbiAqIEdldHMgdGhlIGluZGV4IGF0IHdoaWNoIHRoZSBga2V5YCBpcyBmb3VuZCBpbiBgYXJyYXlgIG9mIGtleS12YWx1ZSBwYWlycy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGluc3BlY3QuXG4gKiBAcGFyYW0geyp9IGtleSBUaGUga2V5IHRvIHNlYXJjaCBmb3IuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICovXG5mdW5jdGlvbiBhc3NvY0luZGV4T2YoYXJyYXksIGtleSkge1xuICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICBpZiAoZXEoYXJyYXlbbGVuZ3RoXVswXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxlbmd0aDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIC0xO1xufVxuXG4vKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmdldGAgd2l0aG91dCBzdXBwb3J0IGZvciBkZWZhdWx0IHZhbHVlcy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICogQHBhcmFtIHtBcnJheXxzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXNvbHZlZCB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gYmFzZUdldChvYmplY3QsIHBhdGgpIHtcbiAgcGF0aCA9IGlzS2V5KHBhdGgsIG9iamVjdCkgPyBbcGF0aF0gOiBjYXN0UGF0aChwYXRoKTtcblxuICB2YXIgaW5kZXggPSAwLFxuICAgICAgbGVuZ3RoID0gcGF0aC5sZW5ndGg7XG5cbiAgd2hpbGUgKG9iamVjdCAhPSBudWxsICYmIGluZGV4IDwgbGVuZ3RoKSB7XG4gICAgb2JqZWN0ID0gb2JqZWN0W3RvS2V5KHBhdGhbaW5kZXgrK10pXTtcbiAgfVxuICByZXR1cm4gKGluZGV4ICYmIGluZGV4ID09IGxlbmd0aCkgPyBvYmplY3QgOiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNOYXRpdmVgIHdpdGhvdXQgYmFkIHNoaW0gY2hlY2tzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgbmF0aXZlIGZ1bmN0aW9uLFxuICogIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gYmFzZUlzTmF0aXZlKHZhbHVlKSB7XG4gIGlmICghaXNPYmplY3QodmFsdWUpIHx8IGlzTWFza2VkKHZhbHVlKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICB2YXIgcGF0dGVybiA9IChpc0Z1bmN0aW9uKHZhbHVlKSB8fCBpc0hvc3RPYmplY3QodmFsdWUpKSA/IHJlSXNOYXRpdmUgOiByZUlzSG9zdEN0b3I7XG4gIHJldHVybiBwYXR0ZXJuLnRlc3QodG9Tb3VyY2UodmFsdWUpKTtcbn1cblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy50b1N0cmluZ2Agd2hpY2ggZG9lc24ndCBjb252ZXJ0IG51bGxpc2hcbiAqIHZhbHVlcyB0byBlbXB0eSBzdHJpbmdzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwcm9jZXNzLlxuICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgc3RyaW5nLlxuICovXG5mdW5jdGlvbiBiYXNlVG9TdHJpbmcodmFsdWUpIHtcbiAgLy8gRXhpdCBlYXJseSBmb3Igc3RyaW5ncyB0byBhdm9pZCBhIHBlcmZvcm1hbmNlIGhpdCBpbiBzb21lIGVudmlyb25tZW50cy5cbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PSAnc3RyaW5nJykge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuICBpZiAoaXNTeW1ib2wodmFsdWUpKSB7XG4gICAgcmV0dXJuIHN5bWJvbFRvU3RyaW5nID8gc3ltYm9sVG9TdHJpbmcuY2FsbCh2YWx1ZSkgOiAnJztcbiAgfVxuICB2YXIgcmVzdWx0ID0gKHZhbHVlICsgJycpO1xuICByZXR1cm4gKHJlc3VsdCA9PSAnMCcgJiYgKDEgLyB2YWx1ZSkgPT0gLUlORklOSVRZKSA/ICctMCcgOiByZXN1bHQ7XG59XG5cbi8qKlxuICogQ2FzdHMgYHZhbHVlYCB0byBhIHBhdGggYXJyYXkgaWYgaXQncyBub3Qgb25lLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBpbnNwZWN0LlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBjYXN0IHByb3BlcnR5IHBhdGggYXJyYXkuXG4gKi9cbmZ1bmN0aW9uIGNhc3RQYXRoKHZhbHVlKSB7XG4gIHJldHVybiBpc0FycmF5KHZhbHVlKSA/IHZhbHVlIDogc3RyaW5nVG9QYXRoKHZhbHVlKTtcbn1cblxuLyoqXG4gKiBHZXRzIHRoZSBkYXRhIGZvciBgbWFwYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG1hcCBUaGUgbWFwIHRvIHF1ZXJ5LlxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUgcmVmZXJlbmNlIGtleS5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBtYXAgZGF0YS5cbiAqL1xuZnVuY3Rpb24gZ2V0TWFwRGF0YShtYXAsIGtleSkge1xuICB2YXIgZGF0YSA9IG1hcC5fX2RhdGFfXztcbiAgcmV0dXJuIGlzS2V5YWJsZShrZXkpXG4gICAgPyBkYXRhW3R5cGVvZiBrZXkgPT0gJ3N0cmluZycgPyAnc3RyaW5nJyA6ICdoYXNoJ11cbiAgICA6IGRhdGEubWFwO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIG5hdGl2ZSBmdW5jdGlvbiBhdCBga2V5YCBvZiBgb2JqZWN0YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBtZXRob2QgdG8gZ2V0LlxuICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGZ1bmN0aW9uIGlmIGl0J3MgbmF0aXZlLCBlbHNlIGB1bmRlZmluZWRgLlxuICovXG5mdW5jdGlvbiBnZXROYXRpdmUob2JqZWN0LCBrZXkpIHtcbiAgdmFyIHZhbHVlID0gZ2V0VmFsdWUob2JqZWN0LCBrZXkpO1xuICByZXR1cm4gYmFzZUlzTmF0aXZlKHZhbHVlKSA/IHZhbHVlIDogdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgcHJvcGVydHkgbmFtZSBhbmQgbm90IGEgcHJvcGVydHkgcGF0aC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcGFyYW0ge09iamVjdH0gW29iamVjdF0gVGhlIG9iamVjdCB0byBxdWVyeSBrZXlzIG9uLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBwcm9wZXJ0eSBuYW1lLCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGlzS2V5KHZhbHVlLCBvYmplY3QpIHtcbiAgaWYgKGlzQXJyYXkodmFsdWUpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuICBpZiAodHlwZSA9PSAnbnVtYmVyJyB8fCB0eXBlID09ICdzeW1ib2wnIHx8IHR5cGUgPT0gJ2Jvb2xlYW4nIHx8XG4gICAgICB2YWx1ZSA9PSBudWxsIHx8IGlzU3ltYm9sKHZhbHVlKSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiByZUlzUGxhaW5Qcm9wLnRlc3QodmFsdWUpIHx8ICFyZUlzRGVlcFByb3AudGVzdCh2YWx1ZSkgfHxcbiAgICAob2JqZWN0ICE9IG51bGwgJiYgdmFsdWUgaW4gT2JqZWN0KG9iamVjdCkpO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIHN1aXRhYmxlIGZvciB1c2UgYXMgdW5pcXVlIG9iamVjdCBrZXkuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgc3VpdGFibGUsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gaXNLZXlhYmxlKHZhbHVlKSB7XG4gIHZhciB0eXBlID0gdHlwZW9mIHZhbHVlO1xuICByZXR1cm4gKHR5cGUgPT0gJ3N0cmluZycgfHwgdHlwZSA9PSAnbnVtYmVyJyB8fCB0eXBlID09ICdzeW1ib2wnIHx8IHR5cGUgPT0gJ2Jvb2xlYW4nKVxuICAgID8gKHZhbHVlICE9PSAnX19wcm90b19fJylcbiAgICA6ICh2YWx1ZSA9PT0gbnVsbCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGBmdW5jYCBoYXMgaXRzIHNvdXJjZSBtYXNrZWQuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGBmdW5jYCBpcyBtYXNrZWQsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gaXNNYXNrZWQoZnVuYykge1xuICByZXR1cm4gISFtYXNrU3JjS2V5ICYmIChtYXNrU3JjS2V5IGluIGZ1bmMpO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIGBzdHJpbmdgIHRvIGEgcHJvcGVydHkgcGF0aCBhcnJheS5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZyBUaGUgc3RyaW5nIHRvIGNvbnZlcnQuXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHByb3BlcnR5IHBhdGggYXJyYXkuXG4gKi9cbnZhciBzdHJpbmdUb1BhdGggPSBtZW1vaXplKGZ1bmN0aW9uKHN0cmluZykge1xuICBzdHJpbmcgPSB0b1N0cmluZyhzdHJpbmcpO1xuXG4gIHZhciByZXN1bHQgPSBbXTtcbiAgaWYgKHJlTGVhZGluZ0RvdC50ZXN0KHN0cmluZykpIHtcbiAgICByZXN1bHQucHVzaCgnJyk7XG4gIH1cbiAgc3RyaW5nLnJlcGxhY2UocmVQcm9wTmFtZSwgZnVuY3Rpb24obWF0Y2gsIG51bWJlciwgcXVvdGUsIHN0cmluZykge1xuICAgIHJlc3VsdC5wdXNoKHF1b3RlID8gc3RyaW5nLnJlcGxhY2UocmVFc2NhcGVDaGFyLCAnJDEnKSA6IChudW1iZXIgfHwgbWF0Y2gpKTtcbiAgfSk7XG4gIHJldHVybiByZXN1bHQ7XG59KTtcblxuLyoqXG4gKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGEgc3RyaW5nIGtleSBpZiBpdCdzIG5vdCBhIHN0cmluZyBvciBzeW1ib2wuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGluc3BlY3QuXG4gKiBAcmV0dXJucyB7c3RyaW5nfHN5bWJvbH0gUmV0dXJucyB0aGUga2V5LlxuICovXG5mdW5jdGlvbiB0b0tleSh2YWx1ZSkge1xuICBpZiAodHlwZW9mIHZhbHVlID09ICdzdHJpbmcnIHx8IGlzU3ltYm9sKHZhbHVlKSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuICB2YXIgcmVzdWx0ID0gKHZhbHVlICsgJycpO1xuICByZXR1cm4gKHJlc3VsdCA9PSAnMCcgJiYgKDEgLyB2YWx1ZSkgPT0gLUlORklOSVRZKSA/ICctMCcgOiByZXN1bHQ7XG59XG5cbi8qKlxuICogQ29udmVydHMgYGZ1bmNgIHRvIGl0cyBzb3VyY2UgY29kZS5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcHJvY2Vzcy5cbiAqIEByZXR1cm5zIHtzdHJpbmd9IFJldHVybnMgdGhlIHNvdXJjZSBjb2RlLlxuICovXG5mdW5jdGlvbiB0b1NvdXJjZShmdW5jKSB7XG4gIGlmIChmdW5jICE9IG51bGwpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGZ1bmNUb1N0cmluZy5jYWxsKGZ1bmMpO1xuICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiAoZnVuYyArICcnKTtcbiAgICB9IGNhdGNoIChlKSB7fVxuICB9XG4gIHJldHVybiAnJztcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBtZW1vaXplcyB0aGUgcmVzdWx0IG9mIGBmdW5jYC4gSWYgYHJlc29sdmVyYCBpc1xuICogcHJvdmlkZWQsIGl0IGRldGVybWluZXMgdGhlIGNhY2hlIGtleSBmb3Igc3RvcmluZyB0aGUgcmVzdWx0IGJhc2VkIG9uIHRoZVxuICogYXJndW1lbnRzIHByb3ZpZGVkIHRvIHRoZSBtZW1vaXplZCBmdW5jdGlvbi4gQnkgZGVmYXVsdCwgdGhlIGZpcnN0IGFyZ3VtZW50XG4gKiBwcm92aWRlZCB0byB0aGUgbWVtb2l6ZWQgZnVuY3Rpb24gaXMgdXNlZCBhcyB0aGUgbWFwIGNhY2hlIGtleS4gVGhlIGBmdW5jYFxuICogaXMgaW52b2tlZCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiB0aGUgbWVtb2l6ZWQgZnVuY3Rpb24uXG4gKlxuICogKipOb3RlOioqIFRoZSBjYWNoZSBpcyBleHBvc2VkIGFzIHRoZSBgY2FjaGVgIHByb3BlcnR5IG9uIHRoZSBtZW1vaXplZFxuICogZnVuY3Rpb24uIEl0cyBjcmVhdGlvbiBtYXkgYmUgY3VzdG9taXplZCBieSByZXBsYWNpbmcgdGhlIGBfLm1lbW9pemUuQ2FjaGVgXG4gKiBjb25zdHJ1Y3RvciB3aXRoIG9uZSB3aG9zZSBpbnN0YW5jZXMgaW1wbGVtZW50IHRoZVxuICogW2BNYXBgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1wcm9wZXJ0aWVzLW9mLXRoZS1tYXAtcHJvdG90eXBlLW9iamVjdClcbiAqIG1ldGhvZCBpbnRlcmZhY2Ugb2YgYGRlbGV0ZWAsIGBnZXRgLCBgaGFzYCwgYW5kIGBzZXRgLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBjYXRlZ29yeSBGdW5jdGlvblxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gaGF2ZSBpdHMgb3V0cHV0IG1lbW9pemVkLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW3Jlc29sdmVyXSBUaGUgZnVuY3Rpb24gdG8gcmVzb2x2ZSB0aGUgY2FjaGUga2V5LlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgbWVtb2l6ZWQgZnVuY3Rpb24uXG4gKiBAZXhhbXBsZVxuICpcbiAqIHZhciBvYmplY3QgPSB7ICdhJzogMSwgJ2InOiAyIH07XG4gKiB2YXIgb3RoZXIgPSB7ICdjJzogMywgJ2QnOiA0IH07XG4gKlxuICogdmFyIHZhbHVlcyA9IF8ubWVtb2l6ZShfLnZhbHVlcyk7XG4gKiB2YWx1ZXMob2JqZWN0KTtcbiAqIC8vID0+IFsxLCAyXVxuICpcbiAqIHZhbHVlcyhvdGhlcik7XG4gKiAvLyA9PiBbMywgNF1cbiAqXG4gKiBvYmplY3QuYSA9IDI7XG4gKiB2YWx1ZXMob2JqZWN0KTtcbiAqIC8vID0+IFsxLCAyXVxuICpcbiAqIC8vIE1vZGlmeSB0aGUgcmVzdWx0IGNhY2hlLlxuICogdmFsdWVzLmNhY2hlLnNldChvYmplY3QsIFsnYScsICdiJ10pO1xuICogdmFsdWVzKG9iamVjdCk7XG4gKiAvLyA9PiBbJ2EnLCAnYiddXG4gKlxuICogLy8gUmVwbGFjZSBgXy5tZW1vaXplLkNhY2hlYC5cbiAqIF8ubWVtb2l6ZS5DYWNoZSA9IFdlYWtNYXA7XG4gKi9cbmZ1bmN0aW9uIG1lbW9pemUoZnVuYywgcmVzb2x2ZXIpIHtcbiAgaWYgKHR5cGVvZiBmdW5jICE9ICdmdW5jdGlvbicgfHwgKHJlc29sdmVyICYmIHR5cGVvZiByZXNvbHZlciAhPSAnZnVuY3Rpb24nKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgfVxuICB2YXIgbWVtb2l6ZWQgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgYXJncyA9IGFyZ3VtZW50cyxcbiAgICAgICAga2V5ID0gcmVzb2x2ZXIgPyByZXNvbHZlci5hcHBseSh0aGlzLCBhcmdzKSA6IGFyZ3NbMF0sXG4gICAgICAgIGNhY2hlID0gbWVtb2l6ZWQuY2FjaGU7XG5cbiAgICBpZiAoY2FjaGUuaGFzKGtleSkpIHtcbiAgICAgIHJldHVybiBjYWNoZS5nZXQoa2V5KTtcbiAgICB9XG4gICAgdmFyIHJlc3VsdCA9IGZ1bmMuYXBwbHkodGhpcywgYXJncyk7XG4gICAgbWVtb2l6ZWQuY2FjaGUgPSBjYWNoZS5zZXQoa2V5LCByZXN1bHQpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG4gIG1lbW9pemVkLmNhY2hlID0gbmV3IChtZW1vaXplLkNhY2hlIHx8IE1hcENhY2hlKTtcbiAgcmV0dXJuIG1lbW9pemVkO1xufVxuXG4vLyBBc3NpZ24gY2FjaGUgdG8gYF8ubWVtb2l6ZWAuXG5tZW1vaXplLkNhY2hlID0gTWFwQ2FjaGU7XG5cbi8qKlxuICogUGVyZm9ybXMgYVxuICogW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNy4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAqIGNvbXBhcmlzb24gYmV0d2VlbiB0d28gdmFsdWVzIHRvIGRldGVybWluZSBpZiB0aGV5IGFyZSBlcXVpdmFsZW50LlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjb21wYXJlLlxuICogQHBhcmFtIHsqfSBvdGhlciBUaGUgb3RoZXIgdmFsdWUgdG8gY29tcGFyZS5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgdmFsdWVzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIHZhciBvYmplY3QgPSB7ICdhJzogMSB9O1xuICogdmFyIG90aGVyID0geyAnYSc6IDEgfTtcbiAqXG4gKiBfLmVxKG9iamVjdCwgb2JqZWN0KTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmVxKG9iamVjdCwgb3RoZXIpO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmVxKCdhJywgJ2EnKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmVxKCdhJywgT2JqZWN0KCdhJykpO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmVxKE5hTiwgTmFOKTtcbiAqIC8vID0+IHRydWVcbiAqL1xuZnVuY3Rpb24gZXEodmFsdWUsIG90aGVyKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gb3RoZXIgfHwgKHZhbHVlICE9PSB2YWx1ZSAmJiBvdGhlciAhPT0gb3RoZXIpO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYW4gYEFycmF5YCBvYmplY3QuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAwLjEuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYW4gYXJyYXksIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc0FycmF5KFsxLCAyLCAzXSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc0FycmF5KGRvY3VtZW50LmJvZHkuY2hpbGRyZW4pO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmlzQXJyYXkoJ2FiYycpO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmlzQXJyYXkoXy5ub29wKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbnZhciBpc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYEZ1bmN0aW9uYCBvYmplY3QuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSAwLjEuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBmdW5jdGlvbiwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzRnVuY3Rpb24oXyk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc0Z1bmN0aW9uKC9hYmMvKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzRnVuY3Rpb24odmFsdWUpIHtcbiAgLy8gVGhlIHVzZSBvZiBgT2JqZWN0I3RvU3RyaW5nYCBhdm9pZHMgaXNzdWVzIHdpdGggdGhlIGB0eXBlb2ZgIG9wZXJhdG9yXG4gIC8vIGluIFNhZmFyaSA4LTkgd2hpY2ggcmV0dXJucyAnb2JqZWN0JyBmb3IgdHlwZWQgYXJyYXkgYW5kIG90aGVyIGNvbnN0cnVjdG9ycy5cbiAgdmFyIHRhZyA9IGlzT2JqZWN0KHZhbHVlKSA/IG9iamVjdFRvU3RyaW5nLmNhbGwodmFsdWUpIDogJyc7XG4gIHJldHVybiB0YWcgPT0gZnVuY1RhZyB8fCB0YWcgPT0gZ2VuVGFnO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIHRoZVxuICogW2xhbmd1YWdlIHR5cGVdKGh0dHA6Ly93d3cuZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1lY21hc2NyaXB0LWxhbmd1YWdlLXR5cGVzKVxuICogb2YgYE9iamVjdGAuIChlLmcuIGFycmF5cywgZnVuY3Rpb25zLCBvYmplY3RzLCByZWdleGVzLCBgbmV3IE51bWJlcigwKWAsIGFuZCBgbmV3IFN0cmluZygnJylgKVxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzT2JqZWN0KHt9KTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0KFsxLCAyLCAzXSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdChfLm5vb3ApO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3QobnVsbCk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc09iamVjdCh2YWx1ZSkge1xuICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcbiAgcmV0dXJuICEhdmFsdWUgJiYgKHR5cGUgPT0gJ29iamVjdCcgfHwgdHlwZSA9PSAnZnVuY3Rpb24nKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBvYmplY3QtbGlrZS4gQSB2YWx1ZSBpcyBvYmplY3QtbGlrZSBpZiBpdCdzIG5vdCBgbnVsbGBcbiAqIGFuZCBoYXMgYSBgdHlwZW9mYCByZXN1bHQgb2YgXCJvYmplY3RcIi5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMC4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBvYmplY3QtbGlrZSwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZSh7fSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdExpa2UoWzEsIDIsIDNdKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZShfLm5vb3ApO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZShudWxsKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzT2JqZWN0TGlrZSh2YWx1ZSkge1xuICByZXR1cm4gISF2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT0gJ29iamVjdCc7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBTeW1ib2xgIHByaW1pdGl2ZSBvciBvYmplY3QuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBzeW1ib2wsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc1N5bWJvbChTeW1ib2wuaXRlcmF0b3IpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNTeW1ib2woJ2FiYycpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNTeW1ib2wodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnc3ltYm9sJyB8fFxuICAgIChpc09iamVjdExpa2UodmFsdWUpICYmIG9iamVjdFRvU3RyaW5nLmNhbGwodmFsdWUpID09IHN5bWJvbFRhZyk7XG59XG5cbi8qKlxuICogQ29udmVydHMgYHZhbHVlYCB0byBhIHN0cmluZy4gQW4gZW1wdHkgc3RyaW5nIGlzIHJldHVybmVkIGZvciBgbnVsbGBcbiAqIGFuZCBgdW5kZWZpbmVkYCB2YWx1ZXMuIFRoZSBzaWduIG9mIGAtMGAgaXMgcHJlc2VydmVkLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgNC4wLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwcm9jZXNzLlxuICogQHJldHVybnMge3N0cmluZ30gUmV0dXJucyB0aGUgc3RyaW5nLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLnRvU3RyaW5nKG51bGwpO1xuICogLy8gPT4gJydcbiAqXG4gKiBfLnRvU3RyaW5nKC0wKTtcbiAqIC8vID0+ICctMCdcbiAqXG4gKiBfLnRvU3RyaW5nKFsxLCAyLCAzXSk7XG4gKiAvLyA9PiAnMSwyLDMnXG4gKi9cbmZ1bmN0aW9uIHRvU3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PSBudWxsID8gJycgOiBiYXNlVG9TdHJpbmcodmFsdWUpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIHZhbHVlIGF0IGBwYXRoYCBvZiBgb2JqZWN0YC4gSWYgdGhlIHJlc29sdmVkIHZhbHVlIGlzXG4gKiBgdW5kZWZpbmVkYCwgdGhlIGBkZWZhdWx0VmFsdWVgIGlzIHJldHVybmVkIGluIGl0cyBwbGFjZS5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDMuNy4wXG4gKiBAY2F0ZWdvcnkgT2JqZWN0XG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICogQHBhcmFtIHsqfSBbZGVmYXVsdFZhbHVlXSBUaGUgdmFsdWUgcmV0dXJuZWQgZm9yIGB1bmRlZmluZWRgIHJlc29sdmVkIHZhbHVlcy5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSByZXNvbHZlZCB2YWx1ZS5cbiAqIEBleGFtcGxlXG4gKlxuICogdmFyIG9iamVjdCA9IHsgJ2EnOiBbeyAnYic6IHsgJ2MnOiAzIH0gfV0gfTtcbiAqXG4gKiBfLmdldChvYmplY3QsICdhWzBdLmIuYycpO1xuICogLy8gPT4gM1xuICpcbiAqIF8uZ2V0KG9iamVjdCwgWydhJywgJzAnLCAnYicsICdjJ10pO1xuICogLy8gPT4gM1xuICpcbiAqIF8uZ2V0KG9iamVjdCwgJ2EuYi5jJywgJ2RlZmF1bHQnKTtcbiAqIC8vID0+ICdkZWZhdWx0J1xuICovXG5mdW5jdGlvbiBnZXQob2JqZWN0LCBwYXRoLCBkZWZhdWx0VmFsdWUpIHtcbiAgdmFyIHJlc3VsdCA9IG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogYmFzZUdldChvYmplY3QsIHBhdGgpO1xuICByZXR1cm4gcmVzdWx0ID09PSB1bmRlZmluZWQgPyBkZWZhdWx0VmFsdWUgOiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0O1xuIiwiJ3VzZSBzdHJpY3QnO1xubW9kdWxlLmV4cG9ydHMgPSB7XG5cdHN0ZG91dDogZmFsc2UsXG5cdHN0ZGVycjogZmFsc2Vcbn07XG4iLCIoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuXHR0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgPyBtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoKSA6XG5cdHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShmYWN0b3J5KSA6XG5cdChnbG9iYWwudHlwZURldGVjdCA9IGZhY3RvcnkoKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoKSB7ICd1c2Ugc3RyaWN0JztcblxuLyogIVxuICogdHlwZS1kZXRlY3RcbiAqIENvcHlyaWdodChjKSAyMDEzIGpha2UgbHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cbnZhciBwcm9taXNlRXhpc3RzID0gdHlwZW9mIFByb21pc2UgPT09ICdmdW5jdGlvbic7XG5cbi8qIGVzbGludC1kaXNhYmxlIG5vLXVuZGVmICovXG52YXIgZ2xvYmFsT2JqZWN0ID0gdHlwZW9mIHNlbGYgPT09ICdvYmplY3QnID8gc2VsZiA6IGdsb2JhbDsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBpZC1ibGFja2xpc3RcblxudmFyIHN5bWJvbEV4aXN0cyA9IHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnO1xudmFyIG1hcEV4aXN0cyA9IHR5cGVvZiBNYXAgIT09ICd1bmRlZmluZWQnO1xudmFyIHNldEV4aXN0cyA9IHR5cGVvZiBTZXQgIT09ICd1bmRlZmluZWQnO1xudmFyIHdlYWtNYXBFeGlzdHMgPSB0eXBlb2YgV2Vha01hcCAhPT0gJ3VuZGVmaW5lZCc7XG52YXIgd2Vha1NldEV4aXN0cyA9IHR5cGVvZiBXZWFrU2V0ICE9PSAndW5kZWZpbmVkJztcbnZhciBkYXRhVmlld0V4aXN0cyA9IHR5cGVvZiBEYXRhVmlldyAhPT0gJ3VuZGVmaW5lZCc7XG52YXIgc3ltYm9sSXRlcmF0b3JFeGlzdHMgPSBzeW1ib2xFeGlzdHMgJiYgdHlwZW9mIFN5bWJvbC5pdGVyYXRvciAhPT0gJ3VuZGVmaW5lZCc7XG52YXIgc3ltYm9sVG9TdHJpbmdUYWdFeGlzdHMgPSBzeW1ib2xFeGlzdHMgJiYgdHlwZW9mIFN5bWJvbC50b1N0cmluZ1RhZyAhPT0gJ3VuZGVmaW5lZCc7XG52YXIgc2V0RW50cmllc0V4aXN0cyA9IHNldEV4aXN0cyAmJiB0eXBlb2YgU2V0LnByb3RvdHlwZS5lbnRyaWVzID09PSAnZnVuY3Rpb24nO1xudmFyIG1hcEVudHJpZXNFeGlzdHMgPSBtYXBFeGlzdHMgJiYgdHlwZW9mIE1hcC5wcm90b3R5cGUuZW50cmllcyA9PT0gJ2Z1bmN0aW9uJztcbnZhciBzZXRJdGVyYXRvclByb3RvdHlwZSA9IHNldEVudHJpZXNFeGlzdHMgJiYgT2JqZWN0LmdldFByb3RvdHlwZU9mKG5ldyBTZXQoKS5lbnRyaWVzKCkpO1xudmFyIG1hcEl0ZXJhdG9yUHJvdG90eXBlID0gbWFwRW50cmllc0V4aXN0cyAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YobmV3IE1hcCgpLmVudHJpZXMoKSk7XG52YXIgYXJyYXlJdGVyYXRvckV4aXN0cyA9IHN5bWJvbEl0ZXJhdG9yRXhpc3RzICYmIHR5cGVvZiBBcnJheS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9PT0gJ2Z1bmN0aW9uJztcbnZhciBhcnJheUl0ZXJhdG9yUHJvdG90eXBlID0gYXJyYXlJdGVyYXRvckV4aXN0cyAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YoW11bU3ltYm9sLml0ZXJhdG9yXSgpKTtcbnZhciBzdHJpbmdJdGVyYXRvckV4aXN0cyA9IHN5bWJvbEl0ZXJhdG9yRXhpc3RzICYmIHR5cGVvZiBTdHJpbmcucHJvdG90eXBlW1N5bWJvbC5pdGVyYXRvcl0gPT09ICdmdW5jdGlvbic7XG52YXIgc3RyaW5nSXRlcmF0b3JQcm90b3R5cGUgPSBzdHJpbmdJdGVyYXRvckV4aXN0cyAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YoJydbU3ltYm9sLml0ZXJhdG9yXSgpKTtcbnZhciB0b1N0cmluZ0xlZnRTbGljZUxlbmd0aCA9IDg7XG52YXIgdG9TdHJpbmdSaWdodFNsaWNlTGVuZ3RoID0gLTE7XG4vKipcbiAqICMjIyB0eXBlT2YgKG9iailcbiAqXG4gKiBVc2VzIGBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nYCB0byBkZXRlcm1pbmUgdGhlIHR5cGUgb2YgYW4gb2JqZWN0LFxuICogbm9ybWFsaXNpbmcgYmVoYXZpb3VyIGFjcm9zcyBlbmdpbmUgdmVyc2lvbnMgJiB3ZWxsIG9wdGltaXNlZC5cbiAqXG4gKiBAcGFyYW0ge01peGVkfSBvYmplY3RcbiAqIEByZXR1cm4ge1N0cmluZ30gb2JqZWN0IHR5cGVcbiAqIEBhcGkgcHVibGljXG4gKi9cbmZ1bmN0aW9uIHR5cGVEZXRlY3Qob2JqKSB7XG4gIC8qICEgU3BlZWQgb3B0aW1pc2F0aW9uXG4gICAqIFByZTpcbiAgICogICBzdHJpbmcgbGl0ZXJhbCAgICAgeCAzLDAzOSwwMzUgb3BzL3NlYyDCsTEuNjIlICg3OCBydW5zIHNhbXBsZWQpXG4gICAqICAgYm9vbGVhbiBsaXRlcmFsICAgIHggMSw0MjQsMTM4IG9wcy9zZWMgwrE0LjU0JSAoNzUgcnVucyBzYW1wbGVkKVxuICAgKiAgIG51bWJlciBsaXRlcmFsICAgICB4IDEsNjUzLDE1MyBvcHMvc2VjIMKxMS45MSUgKDgyIHJ1bnMgc2FtcGxlZClcbiAgICogICB1bmRlZmluZWQgICAgICAgICAgeCA5LDk3OCw2NjAgb3BzL3NlYyDCsTEuOTIlICg3NSBydW5zIHNhbXBsZWQpXG4gICAqICAgZnVuY3Rpb24gICAgICAgICAgIHggMiw1NTYsNzY5IG9wcy9zZWMgwrExLjczJSAoNzcgcnVucyBzYW1wbGVkKVxuICAgKiBQb3N0OlxuICAgKiAgIHN0cmluZyBsaXRlcmFsICAgICB4IDM4LDU2NCw3OTYgb3BzL3NlYyDCsTEuMTUlICg3OSBydW5zIHNhbXBsZWQpXG4gICAqICAgYm9vbGVhbiBsaXRlcmFsICAgIHggMzEsMTQ4LDk0MCBvcHMvc2VjIMKxMS4xMCUgKDc5IHJ1bnMgc2FtcGxlZClcbiAgICogICBudW1iZXIgbGl0ZXJhbCAgICAgeCAzMiw2NzksMzMwIG9wcy9zZWMgwrExLjkwJSAoNzggcnVucyBzYW1wbGVkKVxuICAgKiAgIHVuZGVmaW5lZCAgICAgICAgICB4IDMyLDM2MywzNjggb3BzL3NlYyDCsTEuMDclICg4MiBydW5zIHNhbXBsZWQpXG4gICAqICAgZnVuY3Rpb24gICAgICAgICAgIHggMzEsMjk2LDg3MCBvcHMvc2VjIMKxMC45NiUgKDgzIHJ1bnMgc2FtcGxlZClcbiAgICovXG4gIHZhciB0eXBlb2ZPYmogPSB0eXBlb2Ygb2JqO1xuICBpZiAodHlwZW9mT2JqICE9PSAnb2JqZWN0Jykge1xuICAgIHJldHVybiB0eXBlb2ZPYmo7XG4gIH1cblxuICAvKiAhIFNwZWVkIG9wdGltaXNhdGlvblxuICAgKiBQcmU6XG4gICAqICAgbnVsbCAgICAgICAgICAgICAgIHggMjgsNjQ1LDc2NSBvcHMvc2VjIMKxMS4xNyUgKDgyIHJ1bnMgc2FtcGxlZClcbiAgICogUG9zdDpcbiAgICogICBudWxsICAgICAgICAgICAgICAgeCAzNiw0MjgsOTYyIG9wcy9zZWMgwrExLjM3JSAoODQgcnVucyBzYW1wbGVkKVxuICAgKi9cbiAgaWYgKG9iaiA9PT0gbnVsbCkge1xuICAgIHJldHVybiAnbnVsbCc7XG4gIH1cblxuICAvKiAhIFNwZWMgQ29uZm9ybWFuY2VcbiAgICogVGVzdDogYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh3aW5kb3cpYGBcbiAgICogIC0gTm9kZSA9PT0gXCJbb2JqZWN0IGdsb2JhbF1cIlxuICAgKiAgLSBDaHJvbWUgPT09IFwiW29iamVjdCBnbG9iYWxdXCJcbiAgICogIC0gRmlyZWZveCA9PT0gXCJbb2JqZWN0IFdpbmRvd11cIlxuICAgKiAgLSBQaGFudG9tSlMgPT09IFwiW29iamVjdCBXaW5kb3ddXCJcbiAgICogIC0gU2FmYXJpID09PSBcIltvYmplY3QgV2luZG93XVwiXG4gICAqICAtIElFIDExID09PSBcIltvYmplY3QgV2luZG93XVwiXG4gICAqICAtIElFIEVkZ2UgPT09IFwiW29iamVjdCBXaW5kb3ddXCJcbiAgICogVGVzdDogYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh0aGlzKWBgXG4gICAqICAtIENocm9tZSBXb3JrZXIgPT09IFwiW29iamVjdCBnbG9iYWxdXCJcbiAgICogIC0gRmlyZWZveCBXb3JrZXIgPT09IFwiW29iamVjdCBEZWRpY2F0ZWRXb3JrZXJHbG9iYWxTY29wZV1cIlxuICAgKiAgLSBTYWZhcmkgV29ya2VyID09PSBcIltvYmplY3QgRGVkaWNhdGVkV29ya2VyR2xvYmFsU2NvcGVdXCJcbiAgICogIC0gSUUgMTEgV29ya2VyID09PSBcIltvYmplY3QgV29ya2VyR2xvYmFsU2NvcGVdXCJcbiAgICogIC0gSUUgRWRnZSBXb3JrZXIgPT09IFwiW29iamVjdCBXb3JrZXJHbG9iYWxTY29wZV1cIlxuICAgKi9cbiAgaWYgKG9iaiA9PT0gZ2xvYmFsT2JqZWN0KSB7XG4gICAgcmV0dXJuICdnbG9iYWwnO1xuICB9XG5cbiAgLyogISBTcGVlZCBvcHRpbWlzYXRpb25cbiAgICogUHJlOlxuICAgKiAgIGFycmF5IGxpdGVyYWwgICAgICB4IDIsODg4LDM1MiBvcHMvc2VjIMKxMC42NyUgKDgyIHJ1bnMgc2FtcGxlZClcbiAgICogUG9zdDpcbiAgICogICBhcnJheSBsaXRlcmFsICAgICAgeCAyMiw0NzksNjUwIG9wcy9zZWMgwrEwLjk2JSAoODEgcnVucyBzYW1wbGVkKVxuICAgKi9cbiAgaWYgKFxuICAgIEFycmF5LmlzQXJyYXkob2JqKSAmJlxuICAgIChzeW1ib2xUb1N0cmluZ1RhZ0V4aXN0cyA9PT0gZmFsc2UgfHwgIShTeW1ib2wudG9TdHJpbmdUYWcgaW4gb2JqKSlcbiAgKSB7XG4gICAgcmV0dXJuICdBcnJheSc7XG4gIH1cblxuICAvLyBOb3QgY2FjaGluZyBleGlzdGVuY2Ugb2YgYHdpbmRvd2AgYW5kIHJlbGF0ZWQgcHJvcGVydGllcyBkdWUgdG8gcG90ZW50aWFsXG4gIC8vIGZvciBgd2luZG93YCB0byBiZSB1bnNldCBiZWZvcmUgdGVzdHMgaW4gcXVhc2ktYnJvd3NlciBlbnZpcm9ubWVudHMuXG4gIGlmICh0eXBlb2Ygd2luZG93ID09PSAnb2JqZWN0JyAmJiB3aW5kb3cgIT09IG51bGwpIHtcbiAgICAvKiAhIFNwZWMgQ29uZm9ybWFuY2VcbiAgICAgKiAoaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2UvYnJvd3NlcnMuaHRtbCNsb2NhdGlvbilcbiAgICAgKiBXaGF0V0cgSFRNTCQ3LjcuMyAtIFRoZSBgTG9jYXRpb25gIGludGVyZmFjZVxuICAgICAqIFRlc3Q6IGBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwod2luZG93LmxvY2F0aW9uKWBgXG4gICAgICogIC0gSUUgPD0xMSA9PT0gXCJbb2JqZWN0IE9iamVjdF1cIlxuICAgICAqICAtIElFIEVkZ2UgPD0xMyA9PT0gXCJbb2JqZWN0IE9iamVjdF1cIlxuICAgICAqL1xuICAgIGlmICh0eXBlb2Ygd2luZG93LmxvY2F0aW9uID09PSAnb2JqZWN0JyAmJiBvYmogPT09IHdpbmRvdy5sb2NhdGlvbikge1xuICAgICAgcmV0dXJuICdMb2NhdGlvbic7XG4gICAgfVxuXG4gICAgLyogISBTcGVjIENvbmZvcm1hbmNlXG4gICAgICogKGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvI2RvY3VtZW50KVxuICAgICAqIFdoYXRXRyBIVE1MJDMuMS4xIC0gVGhlIGBEb2N1bWVudGAgb2JqZWN0XG4gICAgICogTm90ZTogTW9zdCBicm93c2VycyBjdXJyZW50bHkgYWRoZXIgdG8gdGhlIFczQyBET00gTGV2ZWwgMiBzcGVjXG4gICAgICogICAgICAgKGh0dHBzOi8vd3d3LnczLm9yZy9UUi9ET00tTGV2ZWwtMi1IVE1ML2h0bWwuaHRtbCNJRC0yNjgwOTI2OClcbiAgICAgKiAgICAgICB3aGljaCBzdWdnZXN0cyB0aGF0IGJyb3dzZXJzIHNob3VsZCB1c2UgSFRNTFRhYmxlQ2VsbEVsZW1lbnQgZm9yXG4gICAgICogICAgICAgYm90aCBURCBhbmQgVEggZWxlbWVudHMuIFdoYXRXRyBzZXBhcmF0ZXMgdGhlc2UuXG4gICAgICogICAgICAgV2hhdFdHIEhUTUwgc3RhdGVzOlxuICAgICAqICAgICAgICAgPiBGb3IgaGlzdG9yaWNhbCByZWFzb25zLCBXaW5kb3cgb2JqZWN0cyBtdXN0IGFsc28gaGF2ZSBhXG4gICAgICogICAgICAgICA+IHdyaXRhYmxlLCBjb25maWd1cmFibGUsIG5vbi1lbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVkXG4gICAgICogICAgICAgICA+IEhUTUxEb2N1bWVudCB3aG9zZSB2YWx1ZSBpcyB0aGUgRG9jdW1lbnQgaW50ZXJmYWNlIG9iamVjdC5cbiAgICAgKiBUZXN0OiBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGRvY3VtZW50KWBgXG4gICAgICogIC0gQ2hyb21lID09PSBcIltvYmplY3QgSFRNTERvY3VtZW50XVwiXG4gICAgICogIC0gRmlyZWZveCA9PT0gXCJbb2JqZWN0IEhUTUxEb2N1bWVudF1cIlxuICAgICAqICAtIFNhZmFyaSA9PT0gXCJbb2JqZWN0IEhUTUxEb2N1bWVudF1cIlxuICAgICAqICAtIElFIDw9MTAgPT09IFwiW29iamVjdCBEb2N1bWVudF1cIlxuICAgICAqICAtIElFIDExID09PSBcIltvYmplY3QgSFRNTERvY3VtZW50XVwiXG4gICAgICogIC0gSUUgRWRnZSA8PTEzID09PSBcIltvYmplY3QgSFRNTERvY3VtZW50XVwiXG4gICAgICovXG4gICAgaWYgKHR5cGVvZiB3aW5kb3cuZG9jdW1lbnQgPT09ICdvYmplY3QnICYmIG9iaiA9PT0gd2luZG93LmRvY3VtZW50KSB7XG4gICAgICByZXR1cm4gJ0RvY3VtZW50JztcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIHdpbmRvdy5uYXZpZ2F0b3IgPT09ICdvYmplY3QnKSB7XG4gICAgICAvKiAhIFNwZWMgQ29uZm9ybWFuY2VcbiAgICAgICAqIChodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS93ZWJhcHBhcGlzLmh0bWwjbWltZXR5cGVhcnJheSlcbiAgICAgICAqIFdoYXRXRyBIVE1MJDguNi4xLjUgLSBQbHVnaW5zIC0gSW50ZXJmYWNlIE1pbWVUeXBlQXJyYXlcbiAgICAgICAqIFRlc3Q6IGBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobmF2aWdhdG9yLm1pbWVUeXBlcylgYFxuICAgICAgICogIC0gSUUgPD0xMCA9PT0gXCJbb2JqZWN0IE1TTWltZVR5cGVzQ29sbGVjdGlvbl1cIlxuICAgICAgICovXG4gICAgICBpZiAodHlwZW9mIHdpbmRvdy5uYXZpZ2F0b3IubWltZVR5cGVzID09PSAnb2JqZWN0JyAmJlxuICAgICAgICAgIG9iaiA9PT0gd2luZG93Lm5hdmlnYXRvci5taW1lVHlwZXMpIHtcbiAgICAgICAgcmV0dXJuICdNaW1lVHlwZUFycmF5JztcbiAgICAgIH1cblxuICAgICAgLyogISBTcGVjIENvbmZvcm1hbmNlXG4gICAgICAgKiAoaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2Uvd2ViYXBwYXBpcy5odG1sI3BsdWdpbmFycmF5KVxuICAgICAgICogV2hhdFdHIEhUTUwkOC42LjEuNSAtIFBsdWdpbnMgLSBJbnRlcmZhY2UgUGx1Z2luQXJyYXlcbiAgICAgICAqIFRlc3Q6IGBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobmF2aWdhdG9yLnBsdWdpbnMpYGBcbiAgICAgICAqICAtIElFIDw9MTAgPT09IFwiW29iamVjdCBNU1BsdWdpbnNDb2xsZWN0aW9uXVwiXG4gICAgICAgKi9cbiAgICAgIGlmICh0eXBlb2Ygd2luZG93Lm5hdmlnYXRvci5wbHVnaW5zID09PSAnb2JqZWN0JyAmJlxuICAgICAgICAgIG9iaiA9PT0gd2luZG93Lm5hdmlnYXRvci5wbHVnaW5zKSB7XG4gICAgICAgIHJldHVybiAnUGx1Z2luQXJyYXknO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICgodHlwZW9mIHdpbmRvdy5IVE1MRWxlbWVudCA9PT0gJ2Z1bmN0aW9uJyB8fFxuICAgICAgICB0eXBlb2Ygd2luZG93LkhUTUxFbGVtZW50ID09PSAnb2JqZWN0JykgJiZcbiAgICAgICAgb2JqIGluc3RhbmNlb2Ygd2luZG93LkhUTUxFbGVtZW50KSB7XG4gICAgICAvKiAhIFNwZWMgQ29uZm9ybWFuY2VcbiAgICAgICogKGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3dlYmFwcGFwaXMuaHRtbCNwbHVnaW5hcnJheSlcbiAgICAgICogV2hhdFdHIEhUTUwkNC40LjQgLSBUaGUgYGJsb2NrcXVvdGVgIGVsZW1lbnQgLSBJbnRlcmZhY2UgYEhUTUxRdW90ZUVsZW1lbnRgXG4gICAgICAqIFRlc3Q6IGBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYmxvY2txdW90ZScpKWBgXG4gICAgICAqICAtIElFIDw9MTAgPT09IFwiW29iamVjdCBIVE1MQmxvY2tFbGVtZW50XVwiXG4gICAgICAqL1xuICAgICAgaWYgKG9iai50YWdOYW1lID09PSAnQkxPQ0tRVU9URScpIHtcbiAgICAgICAgcmV0dXJuICdIVE1MUXVvdGVFbGVtZW50JztcbiAgICAgIH1cblxuICAgICAgLyogISBTcGVjIENvbmZvcm1hbmNlXG4gICAgICAgKiAoaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy8jaHRtbHRhYmxlZGF0YWNlbGxlbGVtZW50KVxuICAgICAgICogV2hhdFdHIEhUTUwkNC45LjkgLSBUaGUgYHRkYCBlbGVtZW50IC0gSW50ZXJmYWNlIGBIVE1MVGFibGVEYXRhQ2VsbEVsZW1lbnRgXG4gICAgICAgKiBOb3RlOiBNb3N0IGJyb3dzZXJzIGN1cnJlbnRseSBhZGhlciB0byB0aGUgVzNDIERPTSBMZXZlbCAyIHNwZWNcbiAgICAgICAqICAgICAgIChodHRwczovL3d3dy53My5vcmcvVFIvRE9NLUxldmVsLTItSFRNTC9odG1sLmh0bWwjSUQtODI5MTUwNzUpXG4gICAgICAgKiAgICAgICB3aGljaCBzdWdnZXN0cyB0aGF0IGJyb3dzZXJzIHNob3VsZCB1c2UgSFRNTFRhYmxlQ2VsbEVsZW1lbnQgZm9yXG4gICAgICAgKiAgICAgICBib3RoIFREIGFuZCBUSCBlbGVtZW50cy4gV2hhdFdHIHNlcGFyYXRlcyB0aGVzZS5cbiAgICAgICAqIFRlc3Q6IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd0ZCcpKVxuICAgICAgICogIC0gQ2hyb21lID09PSBcIltvYmplY3QgSFRNTFRhYmxlQ2VsbEVsZW1lbnRdXCJcbiAgICAgICAqICAtIEZpcmVmb3ggPT09IFwiW29iamVjdCBIVE1MVGFibGVDZWxsRWxlbWVudF1cIlxuICAgICAgICogIC0gU2FmYXJpID09PSBcIltvYmplY3QgSFRNTFRhYmxlQ2VsbEVsZW1lbnRdXCJcbiAgICAgICAqL1xuICAgICAgaWYgKG9iai50YWdOYW1lID09PSAnVEQnKSB7XG4gICAgICAgIHJldHVybiAnSFRNTFRhYmxlRGF0YUNlbGxFbGVtZW50JztcbiAgICAgIH1cblxuICAgICAgLyogISBTcGVjIENvbmZvcm1hbmNlXG4gICAgICAgKiAoaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy8jaHRtbHRhYmxlaGVhZGVyY2VsbGVsZW1lbnQpXG4gICAgICAgKiBXaGF0V0cgSFRNTCQ0LjkuOSAtIFRoZSBgdGRgIGVsZW1lbnQgLSBJbnRlcmZhY2UgYEhUTUxUYWJsZUhlYWRlckNlbGxFbGVtZW50YFxuICAgICAgICogTm90ZTogTW9zdCBicm93c2VycyBjdXJyZW50bHkgYWRoZXIgdG8gdGhlIFczQyBET00gTGV2ZWwgMiBzcGVjXG4gICAgICAgKiAgICAgICAoaHR0cHM6Ly93d3cudzMub3JnL1RSL0RPTS1MZXZlbC0yLUhUTUwvaHRtbC5odG1sI0lELTgyOTE1MDc1KVxuICAgICAgICogICAgICAgd2hpY2ggc3VnZ2VzdHMgdGhhdCBicm93c2VycyBzaG91bGQgdXNlIEhUTUxUYWJsZUNlbGxFbGVtZW50IGZvclxuICAgICAgICogICAgICAgYm90aCBURCBhbmQgVEggZWxlbWVudHMuIFdoYXRXRyBzZXBhcmF0ZXMgdGhlc2UuXG4gICAgICAgKiBUZXN0OiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndGgnKSlcbiAgICAgICAqICAtIENocm9tZSA9PT0gXCJbb2JqZWN0IEhUTUxUYWJsZUNlbGxFbGVtZW50XVwiXG4gICAgICAgKiAgLSBGaXJlZm94ID09PSBcIltvYmplY3QgSFRNTFRhYmxlQ2VsbEVsZW1lbnRdXCJcbiAgICAgICAqICAtIFNhZmFyaSA9PT0gXCJbb2JqZWN0IEhUTUxUYWJsZUNlbGxFbGVtZW50XVwiXG4gICAgICAgKi9cbiAgICAgIGlmIChvYmoudGFnTmFtZSA9PT0gJ1RIJykge1xuICAgICAgICByZXR1cm4gJ0hUTUxUYWJsZUhlYWRlckNlbGxFbGVtZW50JztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKiAhIFNwZWVkIG9wdGltaXNhdGlvblxuICAqIFByZTpcbiAgKiAgIEZsb2F0NjRBcnJheSAgICAgICB4IDYyNSw2NDQgb3BzL3NlYyDCsTEuNTglICg4MCBydW5zIHNhbXBsZWQpXG4gICogICBGbG9hdDMyQXJyYXkgICAgICAgeCAxLDI3OSw4NTIgb3BzL3NlYyDCsTIuOTElICg3NyBydW5zIHNhbXBsZWQpXG4gICogICBVaW50MzJBcnJheSAgICAgICAgeCAxLDE3OCwxODUgb3BzL3NlYyDCsTEuOTUlICg4MyBydW5zIHNhbXBsZWQpXG4gICogICBVaW50MTZBcnJheSAgICAgICAgeCAxLDAwOCwzODAgb3BzL3NlYyDCsTIuMjUlICg4MCBydW5zIHNhbXBsZWQpXG4gICogICBVaW50OEFycmF5ICAgICAgICAgeCAxLDEyOCwwNDAgb3BzL3NlYyDCsTIuMTElICg4MSBydW5zIHNhbXBsZWQpXG4gICogICBJbnQzMkFycmF5ICAgICAgICAgeCAxLDE3MCwxMTkgb3BzL3NlYyDCsTIuODglICg4MCBydW5zIHNhbXBsZWQpXG4gICogICBJbnQxNkFycmF5ICAgICAgICAgeCAxLDE3NiwzNDggb3BzL3NlYyDCsTUuNzklICg4NiBydW5zIHNhbXBsZWQpXG4gICogICBJbnQ4QXJyYXkgICAgICAgICAgeCAxLDA1OCw3MDcgb3BzL3NlYyDCsTQuOTQlICg3NyBydW5zIHNhbXBsZWQpXG4gICogICBVaW50OENsYW1wZWRBcnJheSAgeCAxLDExMCw2MzMgb3BzL3NlYyDCsTQuMjAlICg4MCBydW5zIHNhbXBsZWQpXG4gICogUG9zdDpcbiAgKiAgIEZsb2F0NjRBcnJheSAgICAgICB4IDcsMTA1LDY3MSBvcHMvc2VjIMKxMTMuNDclICg2NCBydW5zIHNhbXBsZWQpXG4gICogICBGbG9hdDMyQXJyYXkgICAgICAgeCA1LDg4Nyw5MTIgb3BzL3NlYyDCsTEuNDYlICg4MiBydW5zIHNhbXBsZWQpXG4gICogICBVaW50MzJBcnJheSAgICAgICAgeCA2LDQ5MSw2NjEgb3BzL3NlYyDCsTEuNzYlICg3OSBydW5zIHNhbXBsZWQpXG4gICogICBVaW50MTZBcnJheSAgICAgICAgeCA2LDU1OSw3OTUgb3BzL3NlYyDCsTEuNjclICg4MiBydW5zIHNhbXBsZWQpXG4gICogICBVaW50OEFycmF5ICAgICAgICAgeCA2LDQ2Myw5NjYgb3BzL3NlYyDCsTEuNDMlICg4NSBydW5zIHNhbXBsZWQpXG4gICogICBJbnQzMkFycmF5ICAgICAgICAgeCA1LDY0MSw4NDEgb3BzL3NlYyDCsTMuNDklICg4MSBydW5zIHNhbXBsZWQpXG4gICogICBJbnQxNkFycmF5ICAgICAgICAgeCA2LDU4Myw1MTEgb3BzL3NlYyDCsTEuOTglICg4MCBydW5zIHNhbXBsZWQpXG4gICogICBJbnQ4QXJyYXkgICAgICAgICAgeCA2LDYwNiwwNzggb3BzL3NlYyDCsTEuNzQlICg4MSBydW5zIHNhbXBsZWQpXG4gICogICBVaW50OENsYW1wZWRBcnJheSAgeCA2LDYwMiwyMjQgb3BzL3NlYyDCsTEuNzclICg4MyBydW5zIHNhbXBsZWQpXG4gICovXG4gIHZhciBzdHJpbmdUYWcgPSAoc3ltYm9sVG9TdHJpbmdUYWdFeGlzdHMgJiYgb2JqW1N5bWJvbC50b1N0cmluZ1RhZ10pO1xuICBpZiAodHlwZW9mIHN0cmluZ1RhZyA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gc3RyaW5nVGFnO1xuICB9XG5cbiAgdmFyIG9ialByb3RvdHlwZSA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihvYmopO1xuICAvKiAhIFNwZWVkIG9wdGltaXNhdGlvblxuICAqIFByZTpcbiAgKiAgIHJlZ2V4IGxpdGVyYWwgICAgICB4IDEsNzcyLDM4NSBvcHMvc2VjIMKxMS44NSUgKDc3IHJ1bnMgc2FtcGxlZClcbiAgKiAgIHJlZ2V4IGNvbnN0cnVjdG9yICB4IDIsMTQzLDYzNCBvcHMvc2VjIMKxMi40NiUgKDc4IHJ1bnMgc2FtcGxlZClcbiAgKiBQb3N0OlxuICAqICAgcmVnZXggbGl0ZXJhbCAgICAgIHggMyw5MjgsMDA5IG9wcy9zZWMgwrEwLjY1JSAoNzggcnVucyBzYW1wbGVkKVxuICAqICAgcmVnZXggY29uc3RydWN0b3IgIHggMyw5MzEsMTA4IG9wcy9zZWMgwrEwLjU4JSAoODQgcnVucyBzYW1wbGVkKVxuICAqL1xuICBpZiAob2JqUHJvdG90eXBlID09PSBSZWdFeHAucHJvdG90eXBlKSB7XG4gICAgcmV0dXJuICdSZWdFeHAnO1xuICB9XG5cbiAgLyogISBTcGVlZCBvcHRpbWlzYXRpb25cbiAgKiBQcmU6XG4gICogICBkYXRlICAgICAgICAgICAgICAgeCAyLDEzMCwwNzQgb3BzL3NlYyDCsTQuNDIlICg2OCBydW5zIHNhbXBsZWQpXG4gICogUG9zdDpcbiAgKiAgIGRhdGUgICAgICAgICAgICAgICB4IDMsOTUzLDc3OSBvcHMvc2VjIMKxMS4zNSUgKDc3IHJ1bnMgc2FtcGxlZClcbiAgKi9cbiAgaWYgKG9ialByb3RvdHlwZSA9PT0gRGF0ZS5wcm90b3R5cGUpIHtcbiAgICByZXR1cm4gJ0RhdGUnO1xuICB9XG5cbiAgLyogISBTcGVjIENvbmZvcm1hbmNlXG4gICAqIChodHRwOi8vd3d3LmVjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wL2luZGV4Lmh0bWwjc2VjLXByb21pc2UucHJvdG90eXBlLUBAdG9zdHJpbmd0YWcpXG4gICAqIEVTNiQyNS40LjUuNCAtIFByb21pc2UucHJvdG90eXBlW0BAdG9TdHJpbmdUYWddIHNob3VsZCBiZSBcIlByb21pc2VcIjpcbiAgICogVGVzdDogYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChQcm9taXNlLnJlc29sdmUoKSlgYFxuICAgKiAgLSBDaHJvbWUgPD00NyA9PT0gXCJbb2JqZWN0IE9iamVjdF1cIlxuICAgKiAgLSBFZGdlIDw9MjAgPT09IFwiW29iamVjdCBPYmplY3RdXCJcbiAgICogIC0gRmlyZWZveCAyOS1MYXRlc3QgPT09IFwiW29iamVjdCBQcm9taXNlXVwiXG4gICAqICAtIFNhZmFyaSA3LjEtTGF0ZXN0ID09PSBcIltvYmplY3QgUHJvbWlzZV1cIlxuICAgKi9cbiAgaWYgKHByb21pc2VFeGlzdHMgJiYgb2JqUHJvdG90eXBlID09PSBQcm9taXNlLnByb3RvdHlwZSkge1xuICAgIHJldHVybiAnUHJvbWlzZSc7XG4gIH1cblxuICAvKiAhIFNwZWVkIG9wdGltaXNhdGlvblxuICAqIFByZTpcbiAgKiAgIHNldCAgICAgICAgICAgICAgICB4IDIsMjIyLDE4NiBvcHMvc2VjIMKxMS4zMSUgKDgyIHJ1bnMgc2FtcGxlZClcbiAgKiBQb3N0OlxuICAqICAgc2V0ICAgICAgICAgICAgICAgIHggNCw1NDUsODc5IG9wcy9zZWMgwrExLjEzJSAoODMgcnVucyBzYW1wbGVkKVxuICAqL1xuICBpZiAoc2V0RXhpc3RzICYmIG9ialByb3RvdHlwZSA9PT0gU2V0LnByb3RvdHlwZSkge1xuICAgIHJldHVybiAnU2V0JztcbiAgfVxuXG4gIC8qICEgU3BlZWQgb3B0aW1pc2F0aW9uXG4gICogUHJlOlxuICAqICAgbWFwICAgICAgICAgICAgICAgIHggMiwzOTYsODQyIG9wcy9zZWMgwrExLjU5JSAoODEgcnVucyBzYW1wbGVkKVxuICAqIFBvc3Q6XG4gICogICBtYXAgICAgICAgICAgICAgICAgeCA0LDE4Myw5NDUgb3BzL3NlYyDCsTYuNTklICg4MiBydW5zIHNhbXBsZWQpXG4gICovXG4gIGlmIChtYXBFeGlzdHMgJiYgb2JqUHJvdG90eXBlID09PSBNYXAucHJvdG90eXBlKSB7XG4gICAgcmV0dXJuICdNYXAnO1xuICB9XG5cbiAgLyogISBTcGVlZCBvcHRpbWlzYXRpb25cbiAgKiBQcmU6XG4gICogICB3ZWFrc2V0ICAgICAgICAgICAgeCAxLDMyMywyMjAgb3BzL3NlYyDCsTIuMTclICg3NiBydW5zIHNhbXBsZWQpXG4gICogUG9zdDpcbiAgKiAgIHdlYWtzZXQgICAgICAgICAgICB4IDQsMjM3LDUxMCBvcHMvc2VjIMKxMi4wMSUgKDc3IHJ1bnMgc2FtcGxlZClcbiAgKi9cbiAgaWYgKHdlYWtTZXRFeGlzdHMgJiYgb2JqUHJvdG90eXBlID09PSBXZWFrU2V0LnByb3RvdHlwZSkge1xuICAgIHJldHVybiAnV2Vha1NldCc7XG4gIH1cblxuICAvKiAhIFNwZWVkIG9wdGltaXNhdGlvblxuICAqIFByZTpcbiAgKiAgIHdlYWttYXAgICAgICAgICAgICB4IDEsNTAwLDI2MCBvcHMvc2VjIMKxMi4wMiUgKDc4IHJ1bnMgc2FtcGxlZClcbiAgKiBQb3N0OlxuICAqICAgd2Vha21hcCAgICAgICAgICAgIHggMyw4ODEsMzg0IG9wcy9zZWMgwrExLjQ1JSAoODIgcnVucyBzYW1wbGVkKVxuICAqL1xuICBpZiAod2Vha01hcEV4aXN0cyAmJiBvYmpQcm90b3R5cGUgPT09IFdlYWtNYXAucHJvdG90eXBlKSB7XG4gICAgcmV0dXJuICdXZWFrTWFwJztcbiAgfVxuXG4gIC8qICEgU3BlYyBDb25mb3JtYW5jZVxuICAgKiAoaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC9pbmRleC5odG1sI3NlYy1kYXRhdmlldy5wcm90b3R5cGUtQEB0b3N0cmluZ3RhZylcbiAgICogRVM2JDI0LjIuNC4yMSAtIERhdGFWaWV3LnByb3RvdHlwZVtAQHRvU3RyaW5nVGFnXSBzaG91bGQgYmUgXCJEYXRhVmlld1wiOlxuICAgKiBUZXN0OiBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG5ldyBEYXRhVmlldyhuZXcgQXJyYXlCdWZmZXIoMSkpKWBgXG4gICAqICAtIEVkZ2UgPD0xMyA9PT0gXCJbb2JqZWN0IE9iamVjdF1cIlxuICAgKi9cbiAgaWYgKGRhdGFWaWV3RXhpc3RzICYmIG9ialByb3RvdHlwZSA9PT0gRGF0YVZpZXcucHJvdG90eXBlKSB7XG4gICAgcmV0dXJuICdEYXRhVmlldyc7XG4gIH1cblxuICAvKiAhIFNwZWMgQ29uZm9ybWFuY2VcbiAgICogKGh0dHA6Ly93d3cuZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvaW5kZXguaHRtbCNzZWMtJW1hcGl0ZXJhdG9ycHJvdG90eXBlJS1AQHRvc3RyaW5ndGFnKVxuICAgKiBFUzYkMjMuMS41LjIuMiAtICVNYXBJdGVyYXRvclByb3RvdHlwZSVbQEB0b1N0cmluZ1RhZ10gc2hvdWxkIGJlIFwiTWFwIEl0ZXJhdG9yXCI6XG4gICAqIFRlc3Q6IGBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobmV3IE1hcCgpLmVudHJpZXMoKSlgYFxuICAgKiAgLSBFZGdlIDw9MTMgPT09IFwiW29iamVjdCBPYmplY3RdXCJcbiAgICovXG4gIGlmIChtYXBFeGlzdHMgJiYgb2JqUHJvdG90eXBlID09PSBtYXBJdGVyYXRvclByb3RvdHlwZSkge1xuICAgIHJldHVybiAnTWFwIEl0ZXJhdG9yJztcbiAgfVxuXG4gIC8qICEgU3BlYyBDb25mb3JtYW5jZVxuICAgKiAoaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC9pbmRleC5odG1sI3NlYy0lc2V0aXRlcmF0b3Jwcm90b3R5cGUlLUBAdG9zdHJpbmd0YWcpXG4gICAqIEVTNiQyMy4yLjUuMi4yIC0gJVNldEl0ZXJhdG9yUHJvdG90eXBlJVtAQHRvU3RyaW5nVGFnXSBzaG91bGQgYmUgXCJTZXQgSXRlcmF0b3JcIjpcbiAgICogVGVzdDogYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChuZXcgU2V0KCkuZW50cmllcygpKWBgXG4gICAqICAtIEVkZ2UgPD0xMyA9PT0gXCJbb2JqZWN0IE9iamVjdF1cIlxuICAgKi9cbiAgaWYgKHNldEV4aXN0cyAmJiBvYmpQcm90b3R5cGUgPT09IHNldEl0ZXJhdG9yUHJvdG90eXBlKSB7XG4gICAgcmV0dXJuICdTZXQgSXRlcmF0b3InO1xuICB9XG5cbiAgLyogISBTcGVjIENvbmZvcm1hbmNlXG4gICAqIChodHRwOi8vd3d3LmVjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wL2luZGV4Lmh0bWwjc2VjLSVhcnJheWl0ZXJhdG9ycHJvdG90eXBlJS1AQHRvc3RyaW5ndGFnKVxuICAgKiBFUzYkMjIuMS41LjIuMiAtICVBcnJheUl0ZXJhdG9yUHJvdG90eXBlJVtAQHRvU3RyaW5nVGFnXSBzaG91bGQgYmUgXCJBcnJheSBJdGVyYXRvclwiOlxuICAgKiBUZXN0OiBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKFtdW1N5bWJvbC5pdGVyYXRvcl0oKSlgYFxuICAgKiAgLSBFZGdlIDw9MTMgPT09IFwiW29iamVjdCBPYmplY3RdXCJcbiAgICovXG4gIGlmIChhcnJheUl0ZXJhdG9yRXhpc3RzICYmIG9ialByb3RvdHlwZSA9PT0gYXJyYXlJdGVyYXRvclByb3RvdHlwZSkge1xuICAgIHJldHVybiAnQXJyYXkgSXRlcmF0b3InO1xuICB9XG5cbiAgLyogISBTcGVjIENvbmZvcm1hbmNlXG4gICAqIChodHRwOi8vd3d3LmVjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wL2luZGV4Lmh0bWwjc2VjLSVzdHJpbmdpdGVyYXRvcnByb3RvdHlwZSUtQEB0b3N0cmluZ3RhZylcbiAgICogRVM2JDIxLjEuNS4yLjIgLSAlU3RyaW5nSXRlcmF0b3JQcm90b3R5cGUlW0BAdG9TdHJpbmdUYWddIHNob3VsZCBiZSBcIlN0cmluZyBJdGVyYXRvclwiOlxuICAgKiBUZXN0OiBgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKCcnW1N5bWJvbC5pdGVyYXRvcl0oKSlgYFxuICAgKiAgLSBFZGdlIDw9MTMgPT09IFwiW29iamVjdCBPYmplY3RdXCJcbiAgICovXG4gIGlmIChzdHJpbmdJdGVyYXRvckV4aXN0cyAmJiBvYmpQcm90b3R5cGUgPT09IHN0cmluZ0l0ZXJhdG9yUHJvdG90eXBlKSB7XG4gICAgcmV0dXJuICdTdHJpbmcgSXRlcmF0b3InO1xuICB9XG5cbiAgLyogISBTcGVlZCBvcHRpbWlzYXRpb25cbiAgKiBQcmU6XG4gICogICBvYmplY3QgZnJvbSBudWxsICAgeCAyLDQyNCwzMjAgb3BzL3NlYyDCsTEuNjclICg3NiBydW5zIHNhbXBsZWQpXG4gICogUG9zdDpcbiAgKiAgIG9iamVjdCBmcm9tIG51bGwgICB4IDUsODM4LDAwMCBvcHMvc2VjIMKxMC45OSUgKDg0IHJ1bnMgc2FtcGxlZClcbiAgKi9cbiAgaWYgKG9ialByb3RvdHlwZSA9PT0gbnVsbCkge1xuICAgIHJldHVybiAnT2JqZWN0JztcbiAgfVxuXG4gIHJldHVybiBPYmplY3RcbiAgICAucHJvdG90eXBlXG4gICAgLnRvU3RyaW5nXG4gICAgLmNhbGwob2JqKVxuICAgIC5zbGljZSh0b1N0cmluZ0xlZnRTbGljZUxlbmd0aCwgdG9TdHJpbmdSaWdodFNsaWNlTGVuZ3RoKTtcbn1cblxucmV0dXJuIHR5cGVEZXRlY3Q7XG5cbn0pKSk7XG4iXX0= |