diff --git a/.github/workflows/deploy-nest-dev.yml b/.github/workflows/deploy-nest-dev.yml index 329530b8..d9afabed 100644 --- a/.github/workflows/deploy-nest-dev.yml +++ b/.github/workflows/deploy-nest-dev.yml @@ -24,6 +24,10 @@ jobs: DATABASE_PASSWORD_DEV: ${{ secrets.DATABASE_PASSWORD_DEV }} DATABASE_ROOT_PASSWORD_DEV: ${{ secrets.DATABASE_ROOT_PASSWORD_DEV }} REDIS_HOST_DEV: ${{ secrets.REDIS_HOST_DEV }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_BEDROCK_RESUME_EVALUATION_FLOW_ID: ${{ secrets.AWS_BEDROCK_RESUME_EVALUATION_FLOW_ID }} + AWS_BEDROCK_RESUME_EVALUATION_FLOW_ALIAS_ID: ${{ secrets.AWS_BEDROCK_RESUME_EVALUATION_FLOW_ALIAS_ID }} run: | cd /home/ubuntu diff --git a/.github/workflows/deploy-nest-prod.yml b/.github/workflows/deploy-nest-prod.yml index 6d5d49b1..87f56c28 100644 --- a/.github/workflows/deploy-nest-prod.yml +++ b/.github/workflows/deploy-nest-prod.yml @@ -29,6 +29,10 @@ jobs: DATABASE_PASSWORD_PROD: ${{ secrets.DATABASE_PASSWORD_PROD }} DATABASE_ROOT_PASSWORD_PROD: ${{ secrets.DATABASE_ROOT_PASSWORD_PROD }} REDIS_HOST_PROD: ${{ secrets.REDIS_HOST_PROD }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_BEDROCK_RESUME_EVALUATION_FLOW_ID: ${{ secrets.AWS_BEDROCK_RESUME_EVALUATION_FLOW_ID }} + AWS_BEDROCK_RESUME_EVALUATION_FLOW_ALIAS_ID: ${{ secrets.AWS_BEDROCK_RESUME_EVALUATION_FLOW_ALIAS_ID }} run: | cd /home/ubuntu sudo chmod 666 /var/run/docker.sock diff --git a/apps/client/Dockerfile b/apps/client/Dockerfile index dac3cd3e..34780269 100644 --- a/apps/client/Dockerfile +++ b/apps/client/Dockerfile @@ -16,8 +16,12 @@ ARG SENTRY_AUTH_TOKEN ARG NEXT_PUBLIC_GOOGLE_CLIENT_ID ARG NEXT_PUBLIC_CDN_BASE_URL ARG NEXT_PUBLIC_V2_API_BASE_URL +ARG NEXT_PUBLIC_V3_API_BASE_URL +ARG NEXT_PUBLIC_GRAPHQL_URL ARG NEXT_PUBLIC_NOTIFICATION_API_BASE_URL ENV NEXT_PUBLIC_V2_API_BASE_URL=$NEXT_PUBLIC_V2_API_BASE_URL +ENV NEXT_PUBLIC_V3_API_BASE_URL=$NEXT_PUBLIC_V3_API_BASE_URL +ENV NEXT_PUBLIC_GRAPHQL_URL=$NEXT_PUBLIC_GRAPHQL_URL ENV NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL ENV NEXT_PUBLIC_POSTHOG_KEY=$NEXT_PUBLIC_POSTHOG_KEY diff --git a/apps/client/env.d.ts b/apps/client/env.d.ts index 15598be7..10a6aad1 100644 --- a/apps/client/env.d.ts +++ b/apps/client/env.d.ts @@ -1,12 +1,16 @@ declare const process: { env: { + ANALYZE: string; + CI: string; SENTRY_AUTH_TOKEN: string; NEXT_PUBLIC_POSTHOG_KEY: string; NEXT_PUBLIC_POSTHOG_HOST: string; NEXT_PUBLIC_BASE_URL: string; NEXT_PUBLIC_NOTIFICATION_API_BASE_URL: string; + NEXT_PUBLIC_GRAPHQL_URL: string; NEXT_PUBLIC_API_BASE_URL: string; NEXT_PUBLIC_V2_API_BASE_URL: string; + NEXT_PUBLIC_V3_API_BASE_URL: string; NEXT_PUBLIC_CDN_BASE_URL: string; NEXT_PUBLIC_GOOGLE_CLIENT_ID: string; }; diff --git a/apps/client/jest.config.js b/apps/client/jest.config.js index 3f19811f..a259f506 100644 --- a/apps/client/jest.config.js +++ b/apps/client/jest.config.js @@ -29,7 +29,13 @@ const config = { "!/out/**", "!/.next/**", "!/*.config.js", - "!/coverage/**" + "!/coverage/**", + "!/next.lock/**" + ], + coveragePathIgnorePatterns: [ + "/node_modules/", + "/next.lock/", + "https://cdn.jsdelivr.net/" ], setupFilesAfterEnv: ["/jest.setup.ts"], testPathIgnorePatterns: ["/node_modules/", "/.next/"], diff --git a/apps/client/next.config.ts b/apps/client/next.config.ts index f69f2997..75f31e80 100644 --- a/apps/client/next.config.ts +++ b/apps/client/next.config.ts @@ -29,7 +29,8 @@ const nextConfig: NextConfig = { experimental: { webpackMemoryOptimizations: true, webpackBuildWorker: true, - preloadEntriesOnStart: true + preloadEntriesOnStart: true, + urlImports: ["https://cdn.jsdelivr.net/"] } }; diff --git a/apps/client/next.lock/data/https_cdn.jsdelivr.net/npm_pdf-parse_latest_dist_browser_pdf-parse.es_46eba81c18ac1b2cfc93.js b/apps/client/next.lock/data/https_cdn.jsdelivr.net/npm_pdf-parse_latest_dist_browser_pdf-parse.es_46eba81c18ac1b2cfc93.js new file mode 100644 index 00000000..3c5f61db --- /dev/null +++ b/apps/client/next.lock/data/https_cdn.jsdelivr.net/npm_pdf-parse_latest_dist_browser_pdf-parse.es_46eba81c18ac1b2cfc93.js @@ -0,0 +1,31527 @@ +var __typeError = (msg) => { + throw TypeError(msg); +}; +var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg); +var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); +var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); +var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value); +var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method); +var __privateWrapper = (obj, member, setter, getter) => ({ + set _(value) { + __privateSet(obj, member, value, setter); + }, + get _() { + return __privateGet(obj, member, getter); + } +}); +var _capability, _messageHandler, _port, _webWorker, _fakeWorkerId, _isWorkerDisabled, _workerPorts, _PDFWorker_instances, resolve_fn, initializeFromPort_fn, initialize_fn, setupFakeWorker_fn, _PDFWorker_static, mainThreadWorkerMessageHandler_get; +var __webpack_modules__ = { + /***/ + 34: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var isCallable = __webpack_require__2(4901); + module2.exports = function(it) { + return typeof it == "object" ? it !== null : isCallable(it); + }; + }) + ), + /***/ + 81: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var call = __webpack_require__2(9565); + var aCallable = __webpack_require__2(9306); + var anObject = __webpack_require__2(8551); + var tryToString = __webpack_require__2(6823); + var getIteratorMethod = __webpack_require__2(851); + var $TypeError = TypeError; + module2.exports = function(argument, usingIterator) { + var iteratorMethod = arguments.length < 2 ? getIteratorMethod(argument) : usingIterator; + if (aCallable(iteratorMethod)) return anObject(call(iteratorMethod, argument)); + throw new $TypeError(tryToString(argument) + " is not iterable"); + }; + }) + ), + /***/ + 116: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var call = __webpack_require__2(9565); + var iterate = __webpack_require__2(2652); + var aCallable = __webpack_require__2(9306); + var anObject = __webpack_require__2(8551); + var getIteratorDirect = __webpack_require__2(1767); + var iteratorClose = __webpack_require__2(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + var findWithoutClosingOnEarlyError = iteratorHelperWithoutClosingOnEarlyError("find", TypeError); + $({ target: "Iterator", proto: true, real: true, forced: findWithoutClosingOnEarlyError }, { + find: function find(predicate) { + anObject(this); + try { + aCallable(predicate); + } catch (error) { + iteratorClose(this, "throw", error); + } + if (findWithoutClosingOnEarlyError) return call(findWithoutClosingOnEarlyError, this, predicate); + var record = getIteratorDirect(this); + var counter = 0; + return iterate(record, function(value, stop) { + if (predicate(value, counter++)) return stop(value); + }, { IS_RECORD: true, INTERRUPTED: true }).result; + } + }); + }) + ), + /***/ + 283: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(9504); + var fails = __webpack_require__2(9039); + var isCallable = __webpack_require__2(4901); + var hasOwn = __webpack_require__2(9297); + var DESCRIPTORS = __webpack_require__2(3724); + var CONFIGURABLE_FUNCTION_NAME = __webpack_require__2(350).CONFIGURABLE; + var inspectSource = __webpack_require__2(3706); + var InternalStateModule = __webpack_require__2(1181); + var enforceInternalState = InternalStateModule.enforce; + var getInternalState = InternalStateModule.get; + var $String = String; + var defineProperty = Object.defineProperty; + var stringSlice = uncurryThis("".slice); + var replace = uncurryThis("".replace); + var join = uncurryThis([].join); + var CONFIGURABLE_LENGTH = DESCRIPTORS && !fails(function() { + return defineProperty(function() { + }, "length", { value: 8 }).length !== 8; + }); + var TEMPLATE = String(String).split("String"); + var makeBuiltIn = module2.exports = function(value, name, options) { + if (stringSlice($String(name), 0, 7) === "Symbol(") { + name = "[" + replace($String(name), /^Symbol\(([^)]*)\).*$/, "$1") + "]"; + } + if (options && options.getter) name = "get " + name; + if (options && options.setter) name = "set " + name; + if (!hasOwn(value, "name") || CONFIGURABLE_FUNCTION_NAME && value.name !== name) { + if (DESCRIPTORS) defineProperty(value, "name", { value: name, configurable: true }); + else value.name = name; + } + if (CONFIGURABLE_LENGTH && options && hasOwn(options, "arity") && value.length !== options.arity) { + defineProperty(value, "length", { value: options.arity }); + } + try { + if (options && hasOwn(options, "constructor") && options.constructor) { + if (DESCRIPTORS) defineProperty(value, "prototype", { writable: false }); + } else if (value.prototype) value.prototype = void 0; + } catch (error) { + } + var state = enforceInternalState(value); + if (!hasOwn(state, "source")) { + state.source = join(TEMPLATE, typeof name == "string" ? name : ""); + } + return value; + }; + Function.prototype.toString = makeBuiltIn(function toString() { + return isCallable(this) && getInternalState(this).source || inspectSource(this); + }, "toString"); + }) + ), + /***/ + 350: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var DESCRIPTORS = __webpack_require__2(3724); + var hasOwn = __webpack_require__2(9297); + var FunctionPrototype = Function.prototype; + var getDescriptor = DESCRIPTORS && Object.getOwnPropertyDescriptor; + var EXISTS = hasOwn(FunctionPrototype, "name"); + var PROPER = EXISTS && (function something() { + }).name === "something"; + var CONFIGURABLE = EXISTS && (!DESCRIPTORS || DESCRIPTORS && getDescriptor(FunctionPrototype, "name").configurable); + module2.exports = { + EXISTS, + PROPER, + CONFIGURABLE + }; + }) + ), + /***/ + 397: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var getBuiltIn = __webpack_require__2(7751); + module2.exports = getBuiltIn("document", "documentElement"); + }) + ), + /***/ + 421: ( + /***/ + ((module2) => { + module2.exports = {}; + }) + ), + /***/ + 456: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var globalThis2 = __webpack_require__2(4576); + var uncurryThis = __webpack_require__2(9504); + var anUint8Array = __webpack_require__2(4154); + var notDetached = __webpack_require__2(5169); + var numberToString = uncurryThis(1.1.toString); + var Uint8Array2 = globalThis2.Uint8Array; + var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toHex || !(function() { + try { + var target = new Uint8Array2([255, 255, 255, 255, 255, 255, 255, 255]); + return target.toHex() === "ffffffffffffffff"; + } catch (error) { + return false; + } + })(); + if (Uint8Array2) $({ target: "Uint8Array", proto: true, forced: INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS }, { + toHex: function toHex() { + anUint8Array(this); + notDetached(this.buffer); + var result = ""; + for (var i = 0, length = this.length; i < length; i++) { + var hex = numberToString(this[i], 16); + result += hex.length === 1 ? "0" + hex : hex; + } + return result; + } + }); + }) + ), + /***/ + 507: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var call = __webpack_require__2(9565); + module2.exports = function(record, fn, ITERATOR_INSTEAD_OF_RECORD) { + var iterator = ITERATOR_INSTEAD_OF_RECORD ? record : record.iterator; + var next = record.next; + var step, result; + while (!(step = call(next, iterator)).done) { + result = fn(step.value); + if (result !== void 0) return result; + } + }; + }) + ), + /***/ + 531: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var call = __webpack_require__2(9565); + var aCallable = __webpack_require__2(9306); + var anObject = __webpack_require__2(8551); + var getIteratorDirect = __webpack_require__2(1767); + var getIteratorFlattenable = __webpack_require__2(8646); + var createIteratorProxy = __webpack_require__2(9462); + var iteratorClose = __webpack_require__2(9539); + var IS_PURE = __webpack_require__2(6395); + var iteratorHelperThrowsOnInvalidIterator = __webpack_require__2(684); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + var FLAT_MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR = !IS_PURE && !iteratorHelperThrowsOnInvalidIterator("flatMap", function() { + }); + var flatMapWithoutClosingOnEarlyError = !IS_PURE && !FLAT_MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR && iteratorHelperWithoutClosingOnEarlyError("flatMap", TypeError); + var FORCED = IS_PURE || FLAT_MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR || flatMapWithoutClosingOnEarlyError; + var IteratorProxy = createIteratorProxy(function() { + var iterator = this.iterator; + var mapper = this.mapper; + var result, inner; + while (true) { + if (inner = this.inner) try { + result = anObject(call(inner.next, inner.iterator)); + if (!result.done) return result.value; + this.inner = null; + } catch (error) { + iteratorClose(iterator, "throw", error); + } + result = anObject(call(this.next, iterator)); + if (this.done = !!result.done) return; + try { + this.inner = getIteratorFlattenable(mapper(result.value, this.counter++), false); + } catch (error) { + iteratorClose(iterator, "throw", error); + } + } + }); + $({ target: "Iterator", proto: true, real: true, forced: FORCED }, { + flatMap: function flatMap(mapper) { + anObject(this); + try { + aCallable(mapper); + } catch (error) { + iteratorClose(this, "throw", error); + } + if (flatMapWithoutClosingOnEarlyError) return call(flatMapWithoutClosingOnEarlyError, this, mapper); + return new IteratorProxy(getIteratorDirect(this), { + mapper, + inner: null + }); + } + }); + }) + ), + /***/ + 616: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var fails = __webpack_require__2(9039); + module2.exports = !fails(function() { + var test = (function() { + }).bind(); + return typeof test != "function" || test.hasOwnProperty("prototype"); + }); + }) + ), + /***/ + 655: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var classof = __webpack_require__2(6955); + var $String = String; + module2.exports = function(argument) { + if (classof(argument) === "Symbol") throw new TypeError("Cannot convert a Symbol value to a string"); + return $String(argument); + }; + }) + ), + /***/ + 679: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var isPrototypeOf = __webpack_require__2(1625); + var $TypeError = TypeError; + module2.exports = function(it, Prototype) { + if (isPrototypeOf(Prototype, it)) return it; + throw new $TypeError("Incorrect invocation"); + }; + }) + ), + /***/ + 684: ( + /***/ + ((module2) => { + module2.exports = function(methodName, argument) { + var method = typeof Iterator == "function" && Iterator.prototype[methodName]; + if (method) try { + method.call({ next: null }, argument).next(); + } catch (error) { + return true; + } + }; + }) + ), + /***/ + 741: ( + /***/ + ((module2) => { + var ceil2 = Math.ceil; + var floor2 = Math.floor; + module2.exports = Math.trunc || function trunc(x) { + var n = +x; + return (n > 0 ? floor2 : ceil2)(n); + }; + }) + ), + /***/ + 757: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var getBuiltIn = __webpack_require__2(7751); + var isCallable = __webpack_require__2(4901); + var isPrototypeOf = __webpack_require__2(1625); + var USE_SYMBOL_AS_UID = __webpack_require__2(7040); + var $Object = Object; + module2.exports = USE_SYMBOL_AS_UID ? function(it) { + return typeof it == "symbol"; + } : function(it) { + var $Symbol = getBuiltIn("Symbol"); + return isCallable($Symbol) && isPrototypeOf($Symbol.prototype, $Object(it)); + }; + }) + ), + /***/ + 851: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var classof = __webpack_require__2(6955); + var getMethod = __webpack_require__2(5966); + var isNullOrUndefined = __webpack_require__2(4117); + var Iterators = __webpack_require__2(6269); + var wellKnownSymbol = __webpack_require__2(8227); + var ITERATOR = wellKnownSymbol("iterator"); + module2.exports = function(it) { + if (!isNullOrUndefined(it)) return getMethod(it, ITERATOR) || getMethod(it, "@@iterator") || Iterators[classof(it)]; + }; + }) + ), + /***/ + 944: ( + /***/ + ((module2) => { + var $TypeError = TypeError; + module2.exports = function(options) { + var alphabet = options && options.alphabet; + if (alphabet === void 0 || alphabet === "base64" || alphabet === "base64url") return alphabet || "base64"; + throw new $TypeError("Incorrect `alphabet` option"); + }; + }) + ), + /***/ + 1072: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var internalObjectKeys = __webpack_require__2(1828); + var enumBugKeys = __webpack_require__2(8727); + module2.exports = Object.keys || function keys(O) { + return internalObjectKeys(O, enumBugKeys); + }; + }) + ), + /***/ + 1103: ( + /***/ + ((module2) => { + module2.exports = function(exec) { + try { + return { error: false, value: exec() }; + } catch (error) { + return { error: true, value: error }; + } + }; + }) + ), + /***/ + 1108: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var classof = __webpack_require__2(6955); + module2.exports = function(it) { + var klass = classof(it); + return klass === "BigInt64Array" || klass === "BigUint64Array"; + }; + }) + ), + /***/ + 1148: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var call = __webpack_require__2(9565); + var iterate = __webpack_require__2(2652); + var aCallable = __webpack_require__2(9306); + var anObject = __webpack_require__2(8551); + var getIteratorDirect = __webpack_require__2(1767); + var iteratorClose = __webpack_require__2(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + var everyWithoutClosingOnEarlyError = iteratorHelperWithoutClosingOnEarlyError("every", TypeError); + $({ target: "Iterator", proto: true, real: true, forced: everyWithoutClosingOnEarlyError }, { + every: function every(predicate) { + anObject(this); + try { + aCallable(predicate); + } catch (error) { + iteratorClose(this, "throw", error); + } + if (everyWithoutClosingOnEarlyError) return call(everyWithoutClosingOnEarlyError, this, predicate); + var record = getIteratorDirect(this); + var counter = 0; + return !iterate(record, function(value, stop) { + if (!predicate(value, counter++)) return stop(); + }, { IS_RECORD: true, INTERRUPTED: true }).stopped; + } + }); + }) + ), + /***/ + 1181: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var NATIVE_WEAK_MAP = __webpack_require__2(8622); + var globalThis2 = __webpack_require__2(4576); + var isObject = __webpack_require__2(34); + var createNonEnumerableProperty = __webpack_require__2(6699); + var hasOwn = __webpack_require__2(9297); + var shared = __webpack_require__2(7629); + var sharedKey = __webpack_require__2(6119); + var hiddenKeys = __webpack_require__2(421); + var OBJECT_ALREADY_INITIALIZED = "Object already initialized"; + var TypeError2 = globalThis2.TypeError; + var WeakMap2 = globalThis2.WeakMap; + var set, get, has; + var enforce = function(it) { + return has(it) ? get(it) : set(it, {}); + }; + var getterFor = function(TYPE) { + return function(it) { + var state; + if (!isObject(it) || (state = get(it)).type !== TYPE) { + throw new TypeError2("Incompatible receiver, " + TYPE + " required"); + } + return state; + }; + }; + if (NATIVE_WEAK_MAP || shared.state) { + var store = shared.state || (shared.state = new WeakMap2()); + store.get = store.get; + store.has = store.has; + store.set = store.set; + set = function(it, metadata) { + if (store.has(it)) throw new TypeError2(OBJECT_ALREADY_INITIALIZED); + metadata.facade = it; + store.set(it, metadata); + return metadata; + }; + get = function(it) { + return store.get(it) || {}; + }; + has = function(it) { + return store.has(it); + }; + } else { + var STATE = sharedKey("state"); + hiddenKeys[STATE] = true; + set = function(it, metadata) { + if (hasOwn(it, STATE)) throw new TypeError2(OBJECT_ALREADY_INITIALIZED); + metadata.facade = it; + createNonEnumerableProperty(it, STATE, metadata); + return metadata; + }; + get = function(it) { + return hasOwn(it, STATE) ? it[STATE] : {}; + }; + has = function(it) { + return hasOwn(it, STATE); + }; + } + module2.exports = { + set, + get, + has, + enforce, + getterFor + }; + }) + ), + /***/ + 1291: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var trunc = __webpack_require__2(741); + module2.exports = function(argument) { + var number = +argument; + return number !== number || number === 0 ? 0 : trunc(number); + }; + }) + ), + /***/ + 1385: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var iteratorClose = __webpack_require__2(9539); + module2.exports = function(iters, kind, value) { + for (var i = iters.length - 1; i >= 0; i--) { + if (iters[i] === void 0) continue; + try { + value = iteratorClose(iters[i].iterator, kind, value); + } catch (error) { + kind = "throw"; + value = error; + } + } + if (kind === "throw") throw value; + return value; + }; + }) + ), + /***/ + 1548: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var fails = __webpack_require__2(9039); + var V8 = __webpack_require__2(9519); + var ENVIRONMENT = __webpack_require__2(4215); + var structuredClone2 = globalThis2.structuredClone; + module2.exports = !!structuredClone2 && !fails(function() { + if (ENVIRONMENT === "DENO" && V8 > 92 || ENVIRONMENT === "NODE" && V8 > 94 || ENVIRONMENT === "BROWSER" && V8 > 97) return false; + var buffer = new ArrayBuffer(8); + var clone = structuredClone2(buffer, { transfer: [buffer] }); + return buffer.byteLength !== 0 || clone.byteLength !== 8; + }); + }) + ), + /***/ + 1549: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + __webpack_require__2(6632); + }) + ), + /***/ + 1625: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(9504); + module2.exports = uncurryThis({}.isPrototypeOf); + }) + ), + /***/ + 1689: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var globalThis2 = __webpack_require__2(4576); + var apply = __webpack_require__2(8745); + var slice = __webpack_require__2(7680); + var newPromiseCapabilityModule = __webpack_require__2(6043); + var aCallable = __webpack_require__2(9306); + var perform = __webpack_require__2(1103); + var Promise2 = globalThis2.Promise; + var ACCEPT_ARGUMENTS = false; + var FORCED = !Promise2 || !Promise2["try"] || perform(function() { + Promise2["try"](function(argument) { + ACCEPT_ARGUMENTS = argument === 8; + }, 8); + }).error || !ACCEPT_ARGUMENTS; + $({ target: "Promise", stat: true, forced: FORCED }, { + "try": function(callbackfn) { + var args = arguments.length > 1 ? slice(arguments, 1) : []; + var promiseCapability = newPromiseCapabilityModule.f(this); + var result = perform(function() { + return apply(aCallable(callbackfn), void 0, args); + }); + (result.error ? promiseCapability.reject : promiseCapability.resolve)(result.value); + return promiseCapability.promise; + } + }); + }) + ), + /***/ + 1698: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var union = __webpack_require__2(4204); + var setMethodGetKeysBeforeCloning = __webpack_require__2(9835); + var setMethodAcceptSetLike = __webpack_require__2(4916); + var FORCED = !setMethodAcceptSetLike("union") || !setMethodGetKeysBeforeCloning("union"); + $({ target: "Set", proto: true, real: true, forced: FORCED }, { + union + }); + }) + ), + /***/ + 1701: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var call = __webpack_require__2(9565); + var aCallable = __webpack_require__2(9306); + var anObject = __webpack_require__2(8551); + var getIteratorDirect = __webpack_require__2(1767); + var createIteratorProxy = __webpack_require__2(9462); + var callWithSafeIterationClosing = __webpack_require__2(6319); + var iteratorClose = __webpack_require__2(9539); + var iteratorHelperThrowsOnInvalidIterator = __webpack_require__2(684); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + var IS_PURE = __webpack_require__2(6395); + var MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR = !IS_PURE && !iteratorHelperThrowsOnInvalidIterator("map", function() { + }); + var mapWithoutClosingOnEarlyError = !IS_PURE && !MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR && iteratorHelperWithoutClosingOnEarlyError("map", TypeError); + var FORCED = IS_PURE || MAP_WITHOUT_THROWING_ON_INVALID_ITERATOR || mapWithoutClosingOnEarlyError; + var IteratorProxy = createIteratorProxy(function() { + var iterator = this.iterator; + var result = anObject(call(this.next, iterator)); + var done = this.done = !!result.done; + if (!done) return callWithSafeIterationClosing(iterator, this.mapper, [result.value, this.counter++], true); + }); + $({ target: "Iterator", proto: true, real: true, forced: FORCED }, { + map: function map(mapper) { + anObject(this); + try { + aCallable(mapper); + } catch (error) { + iteratorClose(this, "throw", error); + } + if (mapWithoutClosingOnEarlyError) return call(mapWithoutClosingOnEarlyError, this, mapper); + return new IteratorProxy(getIteratorDirect(this), { + mapper + }); + } + }); + }) + ), + /***/ + 1767: ( + /***/ + ((module2) => { + module2.exports = function(obj) { + return { + iterator: obj, + next: obj.next, + done: false + }; + }; + }) + ), + /***/ + 1828: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(9504); + var hasOwn = __webpack_require__2(9297); + var toIndexedObject = __webpack_require__2(5397); + var indexOf = __webpack_require__2(9617).indexOf; + var hiddenKeys = __webpack_require__2(421); + var push = uncurryThis([].push); + module2.exports = function(object, names) { + var O = toIndexedObject(object); + var i = 0; + var result = []; + var key; + for (key in O) !hasOwn(hiddenKeys, key) && hasOwn(O, key) && push(result, key); + while (names.length > i) if (hasOwn(O, key = names[i++])) { + ~indexOf(result, key) || push(result, key); + } + return result; + }; + }) + ), + /***/ + 2106: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var makeBuiltIn = __webpack_require__2(283); + var defineProperty = __webpack_require__2(4913); + module2.exports = function(target, name, descriptor) { + if (descriptor.get) makeBuiltIn(descriptor.get, name, { getter: true }); + if (descriptor.set) makeBuiltIn(descriptor.set, name, { setter: true }); + return defineProperty.f(target, name, descriptor); + }; + }) + ), + /***/ + 2140: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var wellKnownSymbol = __webpack_require__2(8227); + var TO_STRING_TAG = wellKnownSymbol("toStringTag"); + var test = {}; + test[TO_STRING_TAG] = "z"; + module2.exports = String(test) === "[object z]"; + }) + ), + /***/ + 2195: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(9504); + var toString = uncurryThis({}.toString); + var stringSlice = uncurryThis("".slice); + module2.exports = function(it) { + return stringSlice(toString(it), 8, -1); + }; + }) + ), + /***/ + 2211: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var fails = __webpack_require__2(9039); + module2.exports = !fails(function() { + function F() { + } + F.prototype.constructor = null; + return Object.getPrototypeOf(new F()) !== F.prototype; + }); + }) + ), + /***/ + 2303: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var uncurryThis = __webpack_require__2(9504); + var Uint8Array2 = globalThis2.Uint8Array; + var SyntaxError2 = globalThis2.SyntaxError; + var parseInt2 = globalThis2.parseInt; + var min = Math.min; + var NOT_HEX = /[^\da-f]/i; + var exec = uncurryThis(NOT_HEX.exec); + var stringSlice = uncurryThis("".slice); + module2.exports = function(string, into) { + var stringLength = string.length; + if (stringLength % 2 !== 0) throw new SyntaxError2("String should be an even number of characters"); + var maxLength = into ? min(into.length, stringLength / 2) : stringLength / 2; + var bytes = into || new Uint8Array2(maxLength); + var read = 0; + var written = 0; + while (written < maxLength) { + var hexits = stringSlice(string, read, read += 2); + if (exec(NOT_HEX, hexits)) throw new SyntaxError2("String should only contain hex characters"); + bytes[written++] = parseInt2(hexits, 16); + } + return { bytes, read }; + }; + }) + ), + /***/ + 2360: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var anObject = __webpack_require__2(8551); + var definePropertiesModule = __webpack_require__2(6801); + var enumBugKeys = __webpack_require__2(8727); + var hiddenKeys = __webpack_require__2(421); + var html = __webpack_require__2(397); + var documentCreateElement = __webpack_require__2(4055); + var sharedKey = __webpack_require__2(6119); + var GT = ">"; + var LT = "<"; + var PROTOTYPE = "prototype"; + var SCRIPT = "script"; + var IE_PROTO = sharedKey("IE_PROTO"); + var EmptyConstructor = function() { + }; + var scriptTag = function(content) { + return LT + SCRIPT + GT + content + LT + "/" + SCRIPT + GT; + }; + var NullProtoObjectViaActiveX = function(activeXDocument2) { + activeXDocument2.write(scriptTag("")); + activeXDocument2.close(); + var temp = activeXDocument2.parentWindow.Object; + activeXDocument2 = null; + return temp; + }; + var NullProtoObjectViaIFrame = function() { + var iframe = documentCreateElement("iframe"); + var JS = "java" + SCRIPT + ":"; + var iframeDocument; + iframe.style.display = "none"; + html.appendChild(iframe); + iframe.src = String(JS); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write(scriptTag("document.F=Object")); + iframeDocument.close(); + return iframeDocument.F; + }; + var activeXDocument; + var NullProtoObject = function() { + try { + activeXDocument = new ActiveXObject("htmlfile"); + } catch (error) { + } + NullProtoObject = typeof document != "undefined" ? document.domain && activeXDocument ? NullProtoObjectViaActiveX(activeXDocument) : NullProtoObjectViaIFrame() : NullProtoObjectViaActiveX(activeXDocument); + var length = enumBugKeys.length; + while (length--) delete NullProtoObject[PROTOTYPE][enumBugKeys[length]]; + return NullProtoObject(); + }; + hiddenKeys[IE_PROTO] = true; + module2.exports = Object.create || function create(O, Properties) { + var result; + if (O !== null) { + EmptyConstructor[PROTOTYPE] = anObject(O); + result = new EmptyConstructor(); + EmptyConstructor[PROTOTYPE] = null; + result[IE_PROTO] = O; + } else result = NullProtoObject(); + return Properties === void 0 ? result : definePropertiesModule.f(result, Properties); + }; + }) + ), + /***/ + 2475: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var isSupersetOf = __webpack_require__2(8527); + var setMethodAcceptSetLike = __webpack_require__2(4916); + var INCORRECT = !setMethodAcceptSetLike("isSupersetOf", function(result) { + return !result; + }); + $({ target: "Set", proto: true, real: true, forced: INCORRECT }, { + isSupersetOf + }); + }) + ), + /***/ + 2489: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var call = __webpack_require__2(9565); + var aCallable = __webpack_require__2(9306); + var anObject = __webpack_require__2(8551); + var getIteratorDirect = __webpack_require__2(1767); + var createIteratorProxy = __webpack_require__2(9462); + var callWithSafeIterationClosing = __webpack_require__2(6319); + var IS_PURE = __webpack_require__2(6395); + var iteratorClose = __webpack_require__2(9539); + var iteratorHelperThrowsOnInvalidIterator = __webpack_require__2(684); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + var FILTER_WITHOUT_THROWING_ON_INVALID_ITERATOR = !IS_PURE && !iteratorHelperThrowsOnInvalidIterator("filter", function() { + }); + var filterWithoutClosingOnEarlyError = !IS_PURE && !FILTER_WITHOUT_THROWING_ON_INVALID_ITERATOR && iteratorHelperWithoutClosingOnEarlyError("filter", TypeError); + var FORCED = IS_PURE || FILTER_WITHOUT_THROWING_ON_INVALID_ITERATOR || filterWithoutClosingOnEarlyError; + var IteratorProxy = createIteratorProxy(function() { + var iterator = this.iterator; + var predicate = this.predicate; + var next = this.next; + var result, done, value; + while (true) { + result = anObject(call(next, iterator)); + done = this.done = !!result.done; + if (done) return; + value = result.value; + if (callWithSafeIterationClosing(iterator, predicate, [value, this.counter++], true)) return value; + } + }); + $({ target: "Iterator", proto: true, real: true, forced: FORCED }, { + filter: function filter(predicate) { + anObject(this); + try { + aCallable(predicate); + } catch (error) { + iteratorClose(this, "throw", error); + } + if (filterWithoutClosingOnEarlyError) return call(filterWithoutClosingOnEarlyError, this, predicate); + return new IteratorProxy(getIteratorDirect(this), { + predicate + }); + } + }); + }) + ), + /***/ + 2529: ( + /***/ + ((module2) => { + module2.exports = function(value, done) { + return { value, done }; + }; + }) + ), + /***/ + 2603: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var toString = __webpack_require__2(655); + module2.exports = function(argument, $default) { + return argument === void 0 ? arguments.length < 2 ? "" : $default : toString(argument); + }; + }) + ), + /***/ + 2652: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var bind = __webpack_require__2(6080); + var call = __webpack_require__2(9565); + var anObject = __webpack_require__2(8551); + var tryToString = __webpack_require__2(6823); + var isArrayIteratorMethod = __webpack_require__2(4209); + var lengthOfArrayLike = __webpack_require__2(6198); + var isPrototypeOf = __webpack_require__2(1625); + var getIterator = __webpack_require__2(81); + var getIteratorMethod = __webpack_require__2(851); + var iteratorClose = __webpack_require__2(9539); + var $TypeError = TypeError; + var Result = function(stopped, result) { + this.stopped = stopped; + this.result = result; + }; + var ResultPrototype = Result.prototype; + module2.exports = function(iterable, unboundFunction, options) { + var that = options && options.that; + var AS_ENTRIES = !!(options && options.AS_ENTRIES); + var IS_RECORD = !!(options && options.IS_RECORD); + var IS_ITERATOR = !!(options && options.IS_ITERATOR); + var INTERRUPTED = !!(options && options.INTERRUPTED); + var fn = bind(unboundFunction, that); + var iterator, iterFn, index, length, result, next, step; + var stop = function(condition) { + if (iterator) iteratorClose(iterator, "normal"); + return new Result(true, condition); + }; + var callFn = function(value) { + if (AS_ENTRIES) { + anObject(value); + return INTERRUPTED ? fn(value[0], value[1], stop) : fn(value[0], value[1]); + } + return INTERRUPTED ? fn(value, stop) : fn(value); + }; + if (IS_RECORD) { + iterator = iterable.iterator; + } else if (IS_ITERATOR) { + iterator = iterable; + } else { + iterFn = getIteratorMethod(iterable); + if (!iterFn) throw new $TypeError(tryToString(iterable) + " is not iterable"); + if (isArrayIteratorMethod(iterFn)) { + for (index = 0, length = lengthOfArrayLike(iterable); length > index; index++) { + result = callFn(iterable[index]); + if (result && isPrototypeOf(ResultPrototype, result)) return result; + } + return new Result(false); + } + iterator = getIterator(iterable, iterFn); + } + next = IS_RECORD ? iterable.next : iterator.next; + while (!(step = call(next, iterator)).done) { + try { + result = callFn(step.value); + } catch (error) { + iteratorClose(iterator, "throw", error); + } + if (typeof result == "object" && result && isPrototypeOf(ResultPrototype, result)) return result; + } + return new Result(false); + }; + }) + ), + /***/ + 2777: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var call = __webpack_require__2(9565); + var isObject = __webpack_require__2(34); + var isSymbol = __webpack_require__2(757); + var getMethod = __webpack_require__2(5966); + var ordinaryToPrimitive = __webpack_require__2(4270); + var wellKnownSymbol = __webpack_require__2(8227); + var $TypeError = TypeError; + var TO_PRIMITIVE = wellKnownSymbol("toPrimitive"); + module2.exports = function(input, pref) { + if (!isObject(input) || isSymbol(input)) return input; + var exoticToPrim = getMethod(input, TO_PRIMITIVE); + var result; + if (exoticToPrim) { + if (pref === void 0) pref = "default"; + result = call(exoticToPrim, input, pref); + if (!isObject(result) || isSymbol(result)) return result; + throw new $TypeError("Can't convert object to primitive value"); + } + if (pref === void 0) pref = "number"; + return ordinaryToPrimitive(input, pref); + }; + }) + ), + /***/ + 2787: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var hasOwn = __webpack_require__2(9297); + var isCallable = __webpack_require__2(4901); + var toObject = __webpack_require__2(8981); + var sharedKey = __webpack_require__2(6119); + var CORRECT_PROTOTYPE_GETTER = __webpack_require__2(2211); + var IE_PROTO = sharedKey("IE_PROTO"); + var $Object = Object; + var ObjectPrototype = $Object.prototype; + module2.exports = CORRECT_PROTOTYPE_GETTER ? $Object.getPrototypeOf : function(O) { + var object = toObject(O); + if (hasOwn(object, IE_PROTO)) return object[IE_PROTO]; + var constructor = object.constructor; + if (isCallable(constructor) && object instanceof constructor) { + return constructor.prototype; + } + return object instanceof $Object ? ObjectPrototype : null; + }; + }) + ), + /***/ + 2796: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var fails = __webpack_require__2(9039); + var isCallable = __webpack_require__2(4901); + var replacement = /#|\.prototype\./; + var isForced = function(feature, detection) { + var value = data[normalize(feature)]; + return value === POLYFILL ? true : value === NATIVE ? false : isCallable(detection) ? fails(detection) : !!detection; + }; + var normalize = isForced.normalize = function(string) { + return String(string).replace(replacement, ".").toLowerCase(); + }; + var data = isForced.data = {}; + var NATIVE = isForced.NATIVE = "N"; + var POLYFILL = isForced.POLYFILL = "P"; + module2.exports = isForced; + }) + ), + /***/ + 2804: ( + /***/ + ((module2) => { + var commonAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + var base64Alphabet = commonAlphabet + "+/"; + var base64UrlAlphabet = commonAlphabet + "-_"; + var inverse = function(characters) { + var result = {}; + var index = 0; + for (; index < 64; index++) result[characters.charAt(index)] = index; + return result; + }; + module2.exports = { + i2c: base64Alphabet, + c2i: inverse(base64Alphabet), + i2cUrl: base64UrlAlphabet, + c2iUrl: inverse(base64UrlAlphabet) + }; + }) + ), + /***/ + 2812: ( + /***/ + ((module2) => { + var $TypeError = TypeError; + module2.exports = function(passed, required) { + if (passed < required) throw new $TypeError("Not enough arguments"); + return passed; + }; + }) + ), + /***/ + 2839: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var navigator2 = globalThis2.navigator; + var userAgent = navigator2 && navigator2.userAgent; + module2.exports = userAgent ? String(userAgent) : ""; + }) + ), + /***/ + 2967: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThisAccessor = __webpack_require__2(6706); + var isObject = __webpack_require__2(34); + var requireObjectCoercible = __webpack_require__2(7750); + var aPossiblePrototype = __webpack_require__2(3506); + module2.exports = Object.setPrototypeOf || ("__proto__" in {} ? (function() { + var CORRECT_SETTER = false; + var test = {}; + var setter; + try { + setter = uncurryThisAccessor(Object.prototype, "__proto__", "set"); + setter(test, []); + CORRECT_SETTER = test instanceof Array; + } catch (error) { + } + return function setPrototypeOf(O, proto) { + requireObjectCoercible(O); + aPossiblePrototype(proto); + if (!isObject(O)) return O; + if (CORRECT_SETTER) setter(O, proto); + else O.__proto__ = proto; + return O; + }; + })() : void 0); + }) + ), + /***/ + 3068: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var uncurryThis = __webpack_require__2(9504); + var iterate = __webpack_require__2(2652); + var $RangeError = RangeError; + var $TypeError = TypeError; + var $Infinity = Infinity; + var $NaN = NaN; + var abs = Math.abs; + var pow = Math.pow; + var push = uncurryThis([].push); + var POW_2_1023 = pow(2, 1023); + var MAX_SAFE_INTEGER = pow(2, 53) - 1; + var MAX_DOUBLE = Number.MAX_VALUE; + var MAX_ULP = pow(2, 971); + var NOT_A_NUMBER = {}; + var MINUS_INFINITY = {}; + var PLUS_INFINITY = {}; + var MINUS_ZERO = {}; + var FINITE = {}; + var twosum = function(x, y) { + var hi = x + y; + var lo = y - (hi - x); + return { hi, lo }; + }; + $({ target: "Math", stat: true }, { + // eslint-disable-next-line max-statements -- ok + sumPrecise: function sumPrecise(items) { + var numbers = []; + var count = 0; + var state = MINUS_ZERO; + iterate(items, function(n2) { + if (++count >= MAX_SAFE_INTEGER) throw new $RangeError("Maximum allowed index exceeded"); + if (typeof n2 != "number") throw new $TypeError("Value is not a number"); + if (state !== NOT_A_NUMBER) { + if (n2 !== n2) state = NOT_A_NUMBER; + else if (n2 === $Infinity) state = state === MINUS_INFINITY ? NOT_A_NUMBER : PLUS_INFINITY; + else if (n2 === -$Infinity) state = state === PLUS_INFINITY ? NOT_A_NUMBER : MINUS_INFINITY; + else if ((n2 !== 0 || 1 / n2 === $Infinity) && (state === MINUS_ZERO || state === FINITE)) { + state = FINITE; + push(numbers, n2); + } + } + }); + switch (state) { + case NOT_A_NUMBER: + return $NaN; + case MINUS_INFINITY: + return -$Infinity; + case PLUS_INFINITY: + return $Infinity; + case MINUS_ZERO: + return -0; + } + var partials = []; + var overflow = 0; + var x, y, sum, hi, lo, tmp; + for (var i = 0; i < numbers.length; i++) { + x = numbers[i]; + var actuallyUsedPartials = 0; + for (var j = 0; j < partials.length; j++) { + y = partials[j]; + if (abs(x) < abs(y)) { + tmp = x; + x = y; + y = tmp; + } + sum = twosum(x, y); + hi = sum.hi; + lo = sum.lo; + if (abs(hi) === $Infinity) { + var sign = hi === $Infinity ? 1 : -1; + overflow += sign; + x = x - sign * POW_2_1023 - sign * POW_2_1023; + if (abs(x) < abs(y)) { + tmp = x; + x = y; + y = tmp; + } + sum = twosum(x, y); + hi = sum.hi; + lo = sum.lo; + } + if (lo !== 0) partials[actuallyUsedPartials++] = lo; + x = hi; + } + partials.length = actuallyUsedPartials; + if (x !== 0) push(partials, x); + } + var n = partials.length - 1; + hi = 0; + lo = 0; + if (overflow !== 0) { + var next = n >= 0 ? partials[n] : 0; + n--; + if (abs(overflow) > 1 || overflow > 0 && next > 0 || overflow < 0 && next < 0) { + return overflow > 0 ? $Infinity : -$Infinity; + } + sum = twosum(overflow * POW_2_1023, next / 2); + hi = sum.hi; + lo = sum.lo; + lo *= 2; + if (abs(2 * hi) === $Infinity) { + if (hi > 0) { + return hi === POW_2_1023 && lo === -(MAX_ULP / 2) && n >= 0 && partials[n] < 0 ? MAX_DOUBLE : $Infinity; + } + return hi === -POW_2_1023 && lo === MAX_ULP / 2 && n >= 0 && partials[n] > 0 ? -MAX_DOUBLE : -$Infinity; + } + if (lo !== 0) { + partials[++n] = lo; + lo = 0; + } + hi *= 2; + } + while (n >= 0) { + sum = twosum(hi, partials[n--]); + hi = sum.hi; + lo = sum.lo; + if (lo !== 0) break; + } + if (n >= 0 && (lo < 0 && partials[n] < 0 || lo > 0 && partials[n] > 0)) { + y = lo * 2; + x = hi + y; + if (y === x - hi) hi = x; + } + return hi; + } + }); + }) + ), + /***/ + 3167: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var isCallable = __webpack_require__2(4901); + var isObject = __webpack_require__2(34); + var setPrototypeOf = __webpack_require__2(2967); + module2.exports = function($this, dummy, Wrapper) { + var NewTarget, NewTargetPrototype; + if ( + // it can work only with native `setPrototypeOf` + setPrototypeOf && // we haven't completely correct pre-ES6 way for getting `new.target`, so use this + isCallable(NewTarget = dummy.constructor) && NewTarget !== Wrapper && isObject(NewTargetPrototype = NewTarget.prototype) && NewTargetPrototype !== Wrapper.prototype + ) setPrototypeOf($this, NewTargetPrototype); + return $this; + }; + }) + ), + /***/ + 3238: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var NATIVE_ARRAY_BUFFER = __webpack_require__2(7811); + var arrayBufferByteLength = __webpack_require__2(7394); + var DataView2 = globalThis2.DataView; + module2.exports = function(O) { + if (!NATIVE_ARRAY_BUFFER || arrayBufferByteLength(O) !== 0) return false; + try { + new DataView2(O); + return false; + } catch (error) { + return true; + } + }; + }) + ), + /***/ + 3392: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(9504); + var id = 0; + var postfix = Math.random(); + var toString = uncurryThis(1.1.toString); + module2.exports = function(key) { + return "Symbol(" + (key === void 0 ? "" : key) + ")_" + toString(++id + postfix, 36); + }; + }) + ), + /***/ + 3440: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var aSet = __webpack_require__2(7080); + var SetHelpers = __webpack_require__2(4402); + var clone = __webpack_require__2(9286); + var size = __webpack_require__2(5170); + var getSetRecord = __webpack_require__2(3789); + var iterateSet = __webpack_require__2(8469); + var iterateSimple = __webpack_require__2(507); + var has = SetHelpers.has; + var remove = SetHelpers.remove; + module2.exports = function difference(other) { + var O = aSet(this); + var otherRec = getSetRecord(other); + var result = clone(O); + if (size(O) <= otherRec.size) iterateSet(O, function(e) { + if (otherRec.includes(e)) remove(result, e); + }); + else iterateSimple(otherRec.getIterator(), function(e) { + if (has(result, e)) remove(result, e); + }); + return result; + }; + }) + ), + /***/ + 3463: ( + /***/ + ((module2) => { + var $TypeError = TypeError; + module2.exports = function(argument) { + if (typeof argument == "string") return argument; + throw new $TypeError("Argument is not a string"); + }; + }) + ), + /***/ + 3506: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var isPossiblePrototype = __webpack_require__2(3925); + var $String = String; + var $TypeError = TypeError; + module2.exports = function(argument) { + if (isPossiblePrototype(argument)) return argument; + throw new $TypeError("Can't set " + $String(argument) + " as a prototype"); + }; + }) + ), + /***/ + 3579: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var call = __webpack_require__2(9565); + var iterate = __webpack_require__2(2652); + var aCallable = __webpack_require__2(9306); + var anObject = __webpack_require__2(8551); + var getIteratorDirect = __webpack_require__2(1767); + var iteratorClose = __webpack_require__2(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + var someWithoutClosingOnEarlyError = iteratorHelperWithoutClosingOnEarlyError("some", TypeError); + $({ target: "Iterator", proto: true, real: true, forced: someWithoutClosingOnEarlyError }, { + some: function some(predicate) { + anObject(this); + try { + aCallable(predicate); + } catch (error) { + iteratorClose(this, "throw", error); + } + if (someWithoutClosingOnEarlyError) return call(someWithoutClosingOnEarlyError, this, predicate); + var record = getIteratorDirect(this); + var counter = 0; + return iterate(record, function(value, stop) { + if (predicate(value, counter++)) return stop(); + }, { IS_RECORD: true, INTERRUPTED: true }).stopped; + } + }); + }) + ), + /***/ + 3650: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var aSet = __webpack_require__2(7080); + var SetHelpers = __webpack_require__2(4402); + var clone = __webpack_require__2(9286); + var getSetRecord = __webpack_require__2(3789); + var iterateSimple = __webpack_require__2(507); + var add = SetHelpers.add; + var has = SetHelpers.has; + var remove = SetHelpers.remove; + module2.exports = function symmetricDifference(other) { + var O = aSet(this); + var keysIter = getSetRecord(other).getIterator(); + var result = clone(O); + iterateSimple(keysIter, function(e) { + if (has(O, e)) remove(result, e); + else add(result, e); + }); + return result; + }; + }) + ), + /***/ + 3706: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(9504); + var isCallable = __webpack_require__2(4901); + var store = __webpack_require__2(7629); + var functionToString = uncurryThis(Function.toString); + if (!isCallable(store.inspectSource)) { + store.inspectSource = function(it) { + return functionToString(it); + }; + } + module2.exports = store.inspectSource; + }) + ), + /***/ + 3717: ( + /***/ + ((__unused_webpack_module, exports) => { + exports.f = Object.getOwnPropertySymbols; + }) + ), + /***/ + 3724: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var fails = __webpack_require__2(9039); + module2.exports = !fails(function() { + return Object.defineProperty({}, 1, { get: function() { + return 7; + } })[1] !== 7; + }); + }) + ), + /***/ + 3789: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var aCallable = __webpack_require__2(9306); + var anObject = __webpack_require__2(8551); + var call = __webpack_require__2(9565); + var toIntegerOrInfinity = __webpack_require__2(1291); + var getIteratorDirect = __webpack_require__2(1767); + var INVALID_SIZE = "Invalid size"; + var $RangeError = RangeError; + var $TypeError = TypeError; + var max = Math.max; + var SetRecord = function(set, intSize) { + this.set = set; + this.size = max(intSize, 0); + this.has = aCallable(set.has); + this.keys = aCallable(set.keys); + }; + SetRecord.prototype = { + getIterator: function() { + return getIteratorDirect(anObject(call(this.keys, this.set))); + }, + includes: function(it) { + return call(this.has, this.set, it); + } + }; + module2.exports = function(obj) { + anObject(obj); + var numSize = +obj.size; + if (numSize !== numSize) throw new $TypeError(INVALID_SIZE); + var intSize = toIntegerOrInfinity(numSize); + if (intSize < 0) throw new $RangeError(INVALID_SIZE); + return new SetRecord(obj, intSize); + }; + }) + ), + /***/ + 3838: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var aSet = __webpack_require__2(7080); + var size = __webpack_require__2(5170); + var iterate = __webpack_require__2(8469); + var getSetRecord = __webpack_require__2(3789); + module2.exports = function isSubsetOf(other) { + var O = aSet(this); + var otherRec = getSetRecord(other); + if (size(O) > otherRec.size) return false; + return iterate(O, function(e) { + if (!otherRec.includes(e)) return false; + }, true) !== false; + }; + }) + ), + /***/ + 3853: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var isDisjointFrom = __webpack_require__2(4449); + var setMethodAcceptSetLike = __webpack_require__2(4916); + var INCORRECT = !setMethodAcceptSetLike("isDisjointFrom", function(result) { + return !result; + }); + $({ target: "Set", proto: true, real: true, forced: INCORRECT }, { + isDisjointFrom + }); + }) + ), + /***/ + 3925: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var isObject = __webpack_require__2(34); + module2.exports = function(argument) { + return isObject(argument) || argument === null; + }; + }) + ), + /***/ + 3972: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var isObject = __webpack_require__2(34); + var $String = String; + var $TypeError = TypeError; + module2.exports = function(argument) { + if (argument === void 0 || isObject(argument)) return argument; + throw new $TypeError($String(argument) + " is not an object or undefined"); + }; + }) + ), + /***/ + 4055: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var isObject = __webpack_require__2(34); + var document2 = globalThis2.document; + var EXISTS = isObject(document2) && isObject(document2.createElement); + module2.exports = function(it) { + return EXISTS ? document2.createElement(it) : {}; + }; + }) + ), + /***/ + 4114: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var toObject = __webpack_require__2(8981); + var lengthOfArrayLike = __webpack_require__2(6198); + var setArrayLength = __webpack_require__2(4527); + var doesNotExceedSafeInteger = __webpack_require__2(6837); + var fails = __webpack_require__2(9039); + var INCORRECT_TO_LENGTH = fails(function() { + return [].push.call({ length: 4294967296 }, 1) !== 4294967297; + }); + var properErrorOnNonWritableLength = function() { + try { + Object.defineProperty([], "length", { writable: false }).push(); + } catch (error) { + return error instanceof TypeError; + } + }; + var FORCED = INCORRECT_TO_LENGTH || !properErrorOnNonWritableLength(); + $({ target: "Array", proto: true, arity: 1, forced: FORCED }, { + // eslint-disable-next-line no-unused-vars -- required for `.length` + push: function push(item) { + var O = toObject(this); + var len = lengthOfArrayLike(O); + var argCount = arguments.length; + doesNotExceedSafeInteger(len + argCount); + for (var i = 0; i < argCount; i++) { + O[len] = arguments[i]; + len++; + } + setArrayLength(O, len); + return len; + } + }); + }) + ), + /***/ + 4117: ( + /***/ + ((module2) => { + module2.exports = function(it) { + return it === null || it === void 0; + }; + }) + ), + /***/ + 4149: ( + /***/ + ((module2) => { + var $RangeError = RangeError; + module2.exports = function(it) { + if (it === it) return it; + throw new $RangeError("NaN is not allowed"); + }; + }) + ), + /***/ + 4154: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var classof = __webpack_require__2(6955); + var $TypeError = TypeError; + module2.exports = function(argument) { + if (classof(argument) === "Uint8Array") return argument; + throw new $TypeError("Argument is not an Uint8Array"); + }; + }) + ), + /***/ + 4204: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var aSet = __webpack_require__2(7080); + var add = __webpack_require__2(4402).add; + var clone = __webpack_require__2(9286); + var getSetRecord = __webpack_require__2(3789); + var iterateSimple = __webpack_require__2(507); + module2.exports = function union(other) { + var O = aSet(this); + var keysIter = getSetRecord(other).getIterator(); + var result = clone(O); + iterateSimple(keysIter, function(it) { + add(result, it); + }); + return result; + }; + }) + ), + /***/ + 4209: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var wellKnownSymbol = __webpack_require__2(8227); + var Iterators = __webpack_require__2(6269); + var ITERATOR = wellKnownSymbol("iterator"); + var ArrayPrototype = Array.prototype; + module2.exports = function(it) { + return it !== void 0 && (Iterators.Array === it || ArrayPrototype[ITERATOR] === it); + }; + }) + ), + /***/ + 4215: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var userAgent = __webpack_require__2(2839); + var classof = __webpack_require__2(2195); + var userAgentStartsWith = function(string) { + return userAgent.slice(0, string.length) === string; + }; + module2.exports = (function() { + if (userAgentStartsWith("Bun/")) return "BUN"; + if (userAgentStartsWith("Cloudflare-Workers")) return "CLOUDFLARE"; + if (userAgentStartsWith("Deno/")) return "DENO"; + if (userAgentStartsWith("Node.js/")) return "NODE"; + if (globalThis2.Bun && typeof Bun.version == "string") return "BUN"; + if (globalThis2.Deno && typeof Deno.version == "object") return "DENO"; + if (classof(globalThis2.process) === "process") return "NODE"; + if (globalThis2.window && globalThis2.document) return "BROWSER"; + return "REST"; + })(); + }) + ), + /***/ + 4226: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var globalThis2 = __webpack_require__2(4576); + var aString = __webpack_require__2(3463); + var anUint8Array = __webpack_require__2(4154); + var notDetached = __webpack_require__2(5169); + var $fromHex = __webpack_require__2(2303); + if (globalThis2.Uint8Array) $({ target: "Uint8Array", proto: true }, { + setFromHex: function setFromHex(string) { + anUint8Array(this); + aString(string); + notDetached(this.buffer); + var read = $fromHex(string, this).read; + return { read, written: read / 2 }; + } + }); + }) + ), + /***/ + 4235: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + __webpack_require__2(3068); + }) + ), + /***/ + 4270: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var call = __webpack_require__2(9565); + var isCallable = __webpack_require__2(4901); + var isObject = __webpack_require__2(34); + var $TypeError = TypeError; + module2.exports = function(input, pref) { + var fn, val; + if (pref === "string" && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val; + if (isCallable(fn = input.valueOf) && !isObject(val = call(fn, input))) return val; + if (pref !== "string" && isCallable(fn = input.toString) && !isObject(val = call(fn, input))) return val; + throw new $TypeError("Can't convert object to primitive value"); + }; + }) + ), + /***/ + 4376: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var classof = __webpack_require__2(2195); + module2.exports = Array.isArray || function isArray(argument) { + return classof(argument) === "Array"; + }; + }) + ), + /***/ + 4402: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(9504); + var SetPrototype = Set.prototype; + module2.exports = { + // eslint-disable-next-line es/no-set -- safe + Set, + add: uncurryThis(SetPrototype.add), + has: uncurryThis(SetPrototype.has), + remove: uncurryThis(SetPrototype["delete"]), + proto: SetPrototype + }; + }) + ), + /***/ + 4449: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var aSet = __webpack_require__2(7080); + var has = __webpack_require__2(4402).has; + var size = __webpack_require__2(5170); + var getSetRecord = __webpack_require__2(3789); + var iterateSet = __webpack_require__2(8469); + var iterateSimple = __webpack_require__2(507); + var iteratorClose = __webpack_require__2(9539); + module2.exports = function isDisjointFrom(other) { + var O = aSet(this); + var otherRec = getSetRecord(other); + if (size(O) <= otherRec.size) return iterateSet(O, function(e) { + if (otherRec.includes(e)) return false; + }, true) !== false; + var iterator = otherRec.getIterator(); + return iterateSimple(iterator, function(e) { + if (has(O, e)) return iteratorClose(iterator, "normal", false); + }) !== false; + }; + }) + ), + /***/ + 4483: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var getBuiltInNodeModule = __webpack_require__2(9429); + var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__2(1548); + var structuredClone2 = globalThis2.structuredClone; + var $ArrayBuffer = globalThis2.ArrayBuffer; + var $MessageChannel = globalThis2.MessageChannel; + var detach = false; + var WorkerThreads, channel, buffer, $detach; + if (PROPER_STRUCTURED_CLONE_TRANSFER) { + detach = function(transferable) { + structuredClone2(transferable, { transfer: [transferable] }); + }; + } else if ($ArrayBuffer) try { + if (!$MessageChannel) { + WorkerThreads = getBuiltInNodeModule("worker_threads"); + if (WorkerThreads) $MessageChannel = WorkerThreads.MessageChannel; + } + if ($MessageChannel) { + channel = new $MessageChannel(); + buffer = new $ArrayBuffer(2); + $detach = function(transferable) { + channel.port1.postMessage(null, [transferable]); + }; + if (buffer.byteLength === 2) { + $detach(buffer); + if (buffer.byteLength === 0) detach = $detach; + } + } + } catch (error) { + } + module2.exports = detach; + }) + ), + /***/ + 4495: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var V8_VERSION = __webpack_require__2(9519); + var fails = __webpack_require__2(9039); + var globalThis2 = __webpack_require__2(4576); + var $String = globalThis2.String; + module2.exports = !!Object.getOwnPropertySymbols && !fails(function() { + var symbol = Symbol("symbol detection"); + return !$String(symbol) || !(Object(symbol) instanceof Symbol) || // Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances + !Symbol.sham && V8_VERSION && V8_VERSION < 41; + }); + }) + ), + /***/ + 4527: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var DESCRIPTORS = __webpack_require__2(3724); + var isArray = __webpack_require__2(4376); + var $TypeError = TypeError; + var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + var SILENT_ON_NON_WRITABLE_LENGTH_SET = DESCRIPTORS && !(function() { + if (this !== void 0) return true; + try { + Object.defineProperty([], "length", { writable: false }).length = 1; + } catch (error) { + return error instanceof TypeError; + } + })(); + module2.exports = SILENT_ON_NON_WRITABLE_LENGTH_SET ? function(O, length) { + if (isArray(O) && !getOwnPropertyDescriptor(O, "length").writable) { + throw new $TypeError("Cannot set read only .length"); + } + return O.length = length; + } : function(O, length) { + return O.length = length; + }; + }) + ), + /***/ + 4549: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + module2.exports = function(METHOD_NAME, ExpectedError) { + var Iterator2 = globalThis2.Iterator; + var IteratorPrototype = Iterator2 && Iterator2.prototype; + var method = IteratorPrototype && IteratorPrototype[METHOD_NAME]; + var CLOSED = false; + if (method) try { + method.call({ + next: function() { + return { done: true }; + }, + "return": function() { + CLOSED = true; + } + }, -1); + } catch (error) { + if (!(error instanceof ExpectedError)) CLOSED = false; + } + if (!CLOSED) return method; + }; + }) + ), + /***/ + 4576: ( + /***/ + (function(module2) { + var check = function(it) { + return it && it.Math === Math && it; + }; + module2.exports = // eslint-disable-next-line es/no-global-this -- safe + check(typeof globalThis == "object" && globalThis) || check(typeof window == "object" && window) || // eslint-disable-next-line no-restricted-globals -- safe + check(typeof self == "object" && self) || check(typeof global == "object" && global) || check(typeof this == "object" && this) || // eslint-disable-next-line no-new-func -- fallback + /* @__PURE__ */ (function() { + return this; + })() || Function("return this")(); + }) + ), + /***/ + 4603: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var defineBuiltIn = __webpack_require__2(6840); + var uncurryThis = __webpack_require__2(9504); + var toString = __webpack_require__2(655); + var validateArgumentsLength = __webpack_require__2(2812); + var $URLSearchParams = URLSearchParams; + var URLSearchParamsPrototype = $URLSearchParams.prototype; + var append = uncurryThis(URLSearchParamsPrototype.append); + var $delete = uncurryThis(URLSearchParamsPrototype["delete"]); + var forEach = uncurryThis(URLSearchParamsPrototype.forEach); + var push = uncurryThis([].push); + var params = new $URLSearchParams("a=1&a=2&b=3"); + params["delete"]("a", 1); + params["delete"]("b", void 0); + if (params + "" !== "a=2") { + defineBuiltIn(URLSearchParamsPrototype, "delete", function(name) { + var length = arguments.length; + var $value = length < 2 ? void 0 : arguments[1]; + if (length && $value === void 0) return $delete(this, name); + var entries = []; + forEach(this, function(v, k) { + push(entries, { key: k, value: v }); + }); + validateArgumentsLength(length, 1); + var key = toString(name); + var value = toString($value); + var index = 0; + var dindex = 0; + var found = false; + var entriesLength = entries.length; + var entry; + while (index < entriesLength) { + entry = entries[index++]; + if (found || entry.key === key) { + found = true; + $delete(this, entry.key); + } else dindex++; + } + while (dindex < entriesLength) { + entry = entries[dindex++]; + if (!(entry.key === key && entry.value === value)) append(this, entry.key, entry.value); + } + }, { enumerable: true, unsafe: true }); + } + }) + ), + /***/ + 4628: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var newPromiseCapabilityModule = __webpack_require__2(6043); + $({ target: "Promise", stat: true }, { + withResolvers: function withResolvers() { + var promiseCapability = newPromiseCapabilityModule.f(this); + return { + promise: promiseCapability.promise, + resolve: promiseCapability.resolve, + reject: promiseCapability.reject + }; + } + }); + }) + ), + /***/ + 4644: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var NATIVE_ARRAY_BUFFER = __webpack_require__2(7811); + var DESCRIPTORS = __webpack_require__2(3724); + var globalThis2 = __webpack_require__2(4576); + var isCallable = __webpack_require__2(4901); + var isObject = __webpack_require__2(34); + var hasOwn = __webpack_require__2(9297); + var classof = __webpack_require__2(6955); + var tryToString = __webpack_require__2(6823); + var createNonEnumerableProperty = __webpack_require__2(6699); + var defineBuiltIn = __webpack_require__2(6840); + var defineBuiltInAccessor = __webpack_require__2(2106); + var isPrototypeOf = __webpack_require__2(1625); + var getPrototypeOf = __webpack_require__2(2787); + var setPrototypeOf = __webpack_require__2(2967); + var wellKnownSymbol = __webpack_require__2(8227); + var uid = __webpack_require__2(3392); + var InternalStateModule = __webpack_require__2(1181); + var enforceInternalState = InternalStateModule.enforce; + var getInternalState = InternalStateModule.get; + var Int8Array2 = globalThis2.Int8Array; + var Int8ArrayPrototype = Int8Array2 && Int8Array2.prototype; + var Uint8ClampedArray2 = globalThis2.Uint8ClampedArray; + var Uint8ClampedArrayPrototype = Uint8ClampedArray2 && Uint8ClampedArray2.prototype; + var TypedArray = Int8Array2 && getPrototypeOf(Int8Array2); + var TypedArrayPrototype = Int8ArrayPrototype && getPrototypeOf(Int8ArrayPrototype); + var ObjectPrototype = Object.prototype; + var TypeError2 = globalThis2.TypeError; + var TO_STRING_TAG = wellKnownSymbol("toStringTag"); + var TYPED_ARRAY_TAG = uid("TYPED_ARRAY_TAG"); + var TYPED_ARRAY_CONSTRUCTOR = "TypedArrayConstructor"; + var NATIVE_ARRAY_BUFFER_VIEWS = NATIVE_ARRAY_BUFFER && !!setPrototypeOf && classof(globalThis2.opera) !== "Opera"; + var TYPED_ARRAY_TAG_REQUIRED = false; + var NAME, Constructor, Prototype; + var TypedArrayConstructorsList = { + Int8Array: 1, + Uint8Array: 1, + Uint8ClampedArray: 1, + Int16Array: 2, + Uint16Array: 2, + Int32Array: 4, + Uint32Array: 4, + Float32Array: 4, + Float64Array: 8 + }; + var BigIntArrayConstructorsList = { + BigInt64Array: 8, + BigUint64Array: 8 + }; + var isView = function isView2(it) { + if (!isObject(it)) return false; + var klass = classof(it); + return klass === "DataView" || hasOwn(TypedArrayConstructorsList, klass) || hasOwn(BigIntArrayConstructorsList, klass); + }; + var getTypedArrayConstructor = function(it) { + var proto = getPrototypeOf(it); + if (!isObject(proto)) return; + var state = getInternalState(proto); + return state && hasOwn(state, TYPED_ARRAY_CONSTRUCTOR) ? state[TYPED_ARRAY_CONSTRUCTOR] : getTypedArrayConstructor(proto); + }; + var isTypedArray = function(it) { + if (!isObject(it)) return false; + var klass = classof(it); + return hasOwn(TypedArrayConstructorsList, klass) || hasOwn(BigIntArrayConstructorsList, klass); + }; + var aTypedArray = function(it) { + if (isTypedArray(it)) return it; + throw new TypeError2("Target is not a typed array"); + }; + var aTypedArrayConstructor = function(C) { + if (isCallable(C) && (!setPrototypeOf || isPrototypeOf(TypedArray, C))) return C; + throw new TypeError2(tryToString(C) + " is not a typed array constructor"); + }; + var exportTypedArrayMethod = function(KEY, property, forced, options) { + if (!DESCRIPTORS) return; + if (forced) for (var ARRAY in TypedArrayConstructorsList) { + var TypedArrayConstructor = globalThis2[ARRAY]; + if (TypedArrayConstructor && hasOwn(TypedArrayConstructor.prototype, KEY)) try { + delete TypedArrayConstructor.prototype[KEY]; + } catch (error) { + try { + TypedArrayConstructor.prototype[KEY] = property; + } catch (error2) { + } + } + } + if (!TypedArrayPrototype[KEY] || forced) { + defineBuiltIn(TypedArrayPrototype, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && Int8ArrayPrototype[KEY] || property, options); + } + }; + var exportTypedArrayStaticMethod = function(KEY, property, forced) { + var ARRAY, TypedArrayConstructor; + if (!DESCRIPTORS) return; + if (setPrototypeOf) { + if (forced) for (ARRAY in TypedArrayConstructorsList) { + TypedArrayConstructor = globalThis2[ARRAY]; + if (TypedArrayConstructor && hasOwn(TypedArrayConstructor, KEY)) try { + delete TypedArrayConstructor[KEY]; + } catch (error) { + } + } + if (!TypedArray[KEY] || forced) { + try { + return defineBuiltIn(TypedArray, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && TypedArray[KEY] || property); + } catch (error) { + } + } else return; + } + for (ARRAY in TypedArrayConstructorsList) { + TypedArrayConstructor = globalThis2[ARRAY]; + if (TypedArrayConstructor && (!TypedArrayConstructor[KEY] || forced)) { + defineBuiltIn(TypedArrayConstructor, KEY, property); + } + } + }; + for (NAME in TypedArrayConstructorsList) { + Constructor = globalThis2[NAME]; + Prototype = Constructor && Constructor.prototype; + if (Prototype) enforceInternalState(Prototype)[TYPED_ARRAY_CONSTRUCTOR] = Constructor; + else NATIVE_ARRAY_BUFFER_VIEWS = false; + } + for (NAME in BigIntArrayConstructorsList) { + Constructor = globalThis2[NAME]; + Prototype = Constructor && Constructor.prototype; + if (Prototype) enforceInternalState(Prototype)[TYPED_ARRAY_CONSTRUCTOR] = Constructor; + } + if (!NATIVE_ARRAY_BUFFER_VIEWS || !isCallable(TypedArray) || TypedArray === Function.prototype) { + TypedArray = function TypedArray2() { + throw new TypeError2("Incorrect invocation"); + }; + if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) { + if (globalThis2[NAME]) setPrototypeOf(globalThis2[NAME], TypedArray); + } + } + if (!NATIVE_ARRAY_BUFFER_VIEWS || !TypedArrayPrototype || TypedArrayPrototype === ObjectPrototype) { + TypedArrayPrototype = TypedArray.prototype; + if (NATIVE_ARRAY_BUFFER_VIEWS) for (NAME in TypedArrayConstructorsList) { + if (globalThis2[NAME]) setPrototypeOf(globalThis2[NAME].prototype, TypedArrayPrototype); + } + } + if (NATIVE_ARRAY_BUFFER_VIEWS && getPrototypeOf(Uint8ClampedArrayPrototype) !== TypedArrayPrototype) { + setPrototypeOf(Uint8ClampedArrayPrototype, TypedArrayPrototype); + } + if (DESCRIPTORS && !hasOwn(TypedArrayPrototype, TO_STRING_TAG)) { + TYPED_ARRAY_TAG_REQUIRED = true; + defineBuiltInAccessor(TypedArrayPrototype, TO_STRING_TAG, { + configurable: true, + get: function() { + return isObject(this) ? this[TYPED_ARRAY_TAG] : void 0; + } + }); + for (NAME in TypedArrayConstructorsList) if (globalThis2[NAME]) { + createNonEnumerableProperty(globalThis2[NAME], TYPED_ARRAY_TAG, NAME); + } + } + module2.exports = { + NATIVE_ARRAY_BUFFER_VIEWS, + TYPED_ARRAY_TAG: TYPED_ARRAY_TAG_REQUIRED && TYPED_ARRAY_TAG, + aTypedArray, + aTypedArrayConstructor, + exportTypedArrayMethod, + exportTypedArrayStaticMethod, + getTypedArrayConstructor, + isView, + isTypedArray, + TypedArray, + TypedArrayPrototype + }; + }) + ), + /***/ + 4659: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var DESCRIPTORS = __webpack_require__2(3724); + var definePropertyModule = __webpack_require__2(4913); + var createPropertyDescriptor = __webpack_require__2(6980); + module2.exports = function(object, key, value) { + if (DESCRIPTORS) definePropertyModule.f(object, key, createPropertyDescriptor(0, value)); + else object[key] = value; + }; + }) + ), + /***/ + 4901: ( + /***/ + ((module2) => { + var documentAll = typeof document == "object" && document.all; + module2.exports = typeof documentAll == "undefined" && documentAll !== void 0 ? function(argument) { + return typeof argument == "function" || argument === documentAll; + } : function(argument) { + return typeof argument == "function"; + }; + }) + ), + /***/ + 4913: ( + /***/ + ((__unused_webpack_module, exports, __webpack_require__2) => { + var DESCRIPTORS = __webpack_require__2(3724); + var IE8_DOM_DEFINE = __webpack_require__2(5917); + var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__2(8686); + var anObject = __webpack_require__2(8551); + var toPropertyKey = __webpack_require__2(6969); + var $TypeError = TypeError; + var $defineProperty = Object.defineProperty; + var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + var ENUMERABLE = "enumerable"; + var CONFIGURABLE = "configurable"; + var WRITABLE = "writable"; + exports.f = DESCRIPTORS ? V8_PROTOTYPE_DEFINE_BUG ? function defineProperty(O, P, Attributes) { + anObject(O); + P = toPropertyKey(P); + anObject(Attributes); + if (typeof O === "function" && P === "prototype" && "value" in Attributes && WRITABLE in Attributes && !Attributes[WRITABLE]) { + var current = $getOwnPropertyDescriptor(O, P); + if (current && current[WRITABLE]) { + O[P] = Attributes.value; + Attributes = { + configurable: CONFIGURABLE in Attributes ? Attributes[CONFIGURABLE] : current[CONFIGURABLE], + enumerable: ENUMERABLE in Attributes ? Attributes[ENUMERABLE] : current[ENUMERABLE], + writable: false + }; + } + } + return $defineProperty(O, P, Attributes); + } : $defineProperty : function defineProperty(O, P, Attributes) { + anObject(O); + P = toPropertyKey(P); + anObject(Attributes); + if (IE8_DOM_DEFINE) try { + return $defineProperty(O, P, Attributes); + } catch (error) { + } + if ("get" in Attributes || "set" in Attributes) throw new $TypeError("Accessors not supported"); + if ("value" in Attributes) O[P] = Attributes.value; + return O; + }; + }) + ), + /***/ + 4916: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var getBuiltIn = __webpack_require__2(7751); + var createSetLike = function(size) { + return { + size, + has: function() { + return false; + }, + keys: function() { + return { + next: function() { + return { done: true }; + } + }; + } + }; + }; + var createSetLikeWithInfinitySize = function(size) { + return { + size, + has: function() { + return true; + }, + keys: function() { + throw new Error("e"); + } + }; + }; + module2.exports = function(name, callback) { + var Set2 = getBuiltIn("Set"); + try { + new Set2()[name](createSetLike(0)); + try { + new Set2()[name](createSetLike(-1)); + return false; + } catch (error2) { + if (!callback) return true; + try { + new Set2()[name](createSetLikeWithInfinitySize(-Infinity)); + return false; + } catch (error) { + var set = new Set2(); + set.add(1); + set.add(2); + return callback(set[name](createSetLikeWithInfinitySize(Infinity))); + } + } + } catch (error) { + return false; + } + }; + }) + ), + /***/ + 4972: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var call = __webpack_require__2(9565); + var anObject = __webpack_require__2(8551); + var getIteratorDirect = __webpack_require__2(1767); + var notANaN = __webpack_require__2(4149); + var toPositiveInteger = __webpack_require__2(9590); + var createIteratorProxy = __webpack_require__2(9462); + var iteratorClose = __webpack_require__2(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + var IS_PURE = __webpack_require__2(6395); + var takeWithoutClosingOnEarlyError = !IS_PURE && iteratorHelperWithoutClosingOnEarlyError("take", RangeError); + var IteratorProxy = createIteratorProxy(function() { + var iterator = this.iterator; + if (!this.remaining--) { + this.done = true; + return iteratorClose(iterator, "normal", void 0); + } + var result = anObject(call(this.next, iterator)); + var done = this.done = !!result.done; + if (!done) return result.value; + }); + $({ target: "Iterator", proto: true, real: true, forced: IS_PURE || takeWithoutClosingOnEarlyError }, { + take: function take(limit) { + anObject(this); + var remaining; + try { + remaining = toPositiveInteger(notANaN(+limit)); + } catch (error) { + iteratorClose(this, "throw", error); + } + if (takeWithoutClosingOnEarlyError) return call(takeWithoutClosingOnEarlyError, this, remaining); + return new IteratorProxy(getIteratorDirect(this), { + remaining + }); + } + }); + }) + ), + /***/ + 4979: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var globalThis2 = __webpack_require__2(4576); + var getBuiltIn = __webpack_require__2(7751); + var createPropertyDescriptor = __webpack_require__2(6980); + var defineProperty = __webpack_require__2(4913).f; + var hasOwn = __webpack_require__2(9297); + var anInstance = __webpack_require__2(679); + var inheritIfRequired = __webpack_require__2(3167); + var normalizeStringArgument = __webpack_require__2(2603); + var DOMExceptionConstants = __webpack_require__2(5002); + var clearErrorStack = __webpack_require__2(8574); + var DESCRIPTORS = __webpack_require__2(3724); + var IS_PURE = __webpack_require__2(6395); + var DOM_EXCEPTION = "DOMException"; + var Error2 = getBuiltIn("Error"); + var NativeDOMException = getBuiltIn(DOM_EXCEPTION); + var $DOMException = function DOMException() { + anInstance(this, DOMExceptionPrototype); + var argumentsLength = arguments.length; + var message = normalizeStringArgument(argumentsLength < 1 ? void 0 : arguments[0]); + var name = normalizeStringArgument(argumentsLength < 2 ? void 0 : arguments[1], "Error"); + var that = new NativeDOMException(message, name); + var error = new Error2(message); + error.name = DOM_EXCEPTION; + defineProperty(that, "stack", createPropertyDescriptor(1, clearErrorStack(error.stack, 1))); + inheritIfRequired(that, this, $DOMException); + return that; + }; + var DOMExceptionPrototype = $DOMException.prototype = NativeDOMException.prototype; + var ERROR_HAS_STACK = "stack" in new Error2(DOM_EXCEPTION); + var DOM_EXCEPTION_HAS_STACK = "stack" in new NativeDOMException(1, 2); + var descriptor = NativeDOMException && DESCRIPTORS && Object.getOwnPropertyDescriptor(globalThis2, DOM_EXCEPTION); + var BUGGY_DESCRIPTOR = !!descriptor && !(descriptor.writable && descriptor.configurable); + var FORCED_CONSTRUCTOR = ERROR_HAS_STACK && !BUGGY_DESCRIPTOR && !DOM_EXCEPTION_HAS_STACK; + $({ global: true, constructor: true, forced: IS_PURE || FORCED_CONSTRUCTOR }, { + // TODO: fix export logic + DOMException: FORCED_CONSTRUCTOR ? $DOMException : NativeDOMException + }); + var PolyfilledDOMException = getBuiltIn(DOM_EXCEPTION); + var PolyfilledDOMExceptionPrototype = PolyfilledDOMException.prototype; + if (PolyfilledDOMExceptionPrototype.constructor !== PolyfilledDOMException) { + if (!IS_PURE) { + defineProperty(PolyfilledDOMExceptionPrototype, "constructor", createPropertyDescriptor(1, PolyfilledDOMException)); + } + for (var key in DOMExceptionConstants) if (hasOwn(DOMExceptionConstants, key)) { + var constant = DOMExceptionConstants[key]; + var constantName = constant.s; + if (!hasOwn(PolyfilledDOMException, constantName)) { + defineProperty(PolyfilledDOMException, constantName, createPropertyDescriptor(6, constant.c)); + } + } + } + }) + ), + /***/ + 5002: ( + /***/ + ((module2) => { + module2.exports = { + IndexSizeError: { s: "INDEX_SIZE_ERR", c: 1, m: 1 }, + DOMStringSizeError: { s: "DOMSTRING_SIZE_ERR", c: 2, m: 0 }, + HierarchyRequestError: { s: "HIERARCHY_REQUEST_ERR", c: 3, m: 1 }, + WrongDocumentError: { s: "WRONG_DOCUMENT_ERR", c: 4, m: 1 }, + InvalidCharacterError: { s: "INVALID_CHARACTER_ERR", c: 5, m: 1 }, + NoDataAllowedError: { s: "NO_DATA_ALLOWED_ERR", c: 6, m: 0 }, + NoModificationAllowedError: { s: "NO_MODIFICATION_ALLOWED_ERR", c: 7, m: 1 }, + NotFoundError: { s: "NOT_FOUND_ERR", c: 8, m: 1 }, + NotSupportedError: { s: "NOT_SUPPORTED_ERR", c: 9, m: 1 }, + InUseAttributeError: { s: "INUSE_ATTRIBUTE_ERR", c: 10, m: 1 }, + InvalidStateError: { s: "INVALID_STATE_ERR", c: 11, m: 1 }, + SyntaxError: { s: "SYNTAX_ERR", c: 12, m: 1 }, + InvalidModificationError: { s: "INVALID_MODIFICATION_ERR", c: 13, m: 1 }, + NamespaceError: { s: "NAMESPACE_ERR", c: 14, m: 1 }, + InvalidAccessError: { s: "INVALID_ACCESS_ERR", c: 15, m: 1 }, + ValidationError: { s: "VALIDATION_ERR", c: 16, m: 0 }, + TypeMismatchError: { s: "TYPE_MISMATCH_ERR", c: 17, m: 1 }, + SecurityError: { s: "SECURITY_ERR", c: 18, m: 1 }, + NetworkError: { s: "NETWORK_ERR", c: 19, m: 1 }, + AbortError: { s: "ABORT_ERR", c: 20, m: 1 }, + URLMismatchError: { s: "URL_MISMATCH_ERR", c: 21, m: 1 }, + QuotaExceededError: { s: "QUOTA_EXCEEDED_ERR", c: 22, m: 1 }, + TimeoutError: { s: "TIMEOUT_ERR", c: 23, m: 1 }, + InvalidNodeTypeError: { s: "INVALID_NODE_TYPE_ERR", c: 24, m: 1 }, + DataCloneError: { s: "DATA_CLONE_ERR", c: 25, m: 1 } + }; + }) + ), + /***/ + 5024: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var symmetricDifference = __webpack_require__2(3650); + var setMethodGetKeysBeforeCloning = __webpack_require__2(9835); + var setMethodAcceptSetLike = __webpack_require__2(4916); + var FORCED = !setMethodAcceptSetLike("symmetricDifference") || !setMethodGetKeysBeforeCloning("symmetricDifference"); + $({ target: "Set", proto: true, real: true, forced: FORCED }, { + symmetricDifference + }); + }) + ), + /***/ + 5031: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var getBuiltIn = __webpack_require__2(7751); + var uncurryThis = __webpack_require__2(9504); + var getOwnPropertyNamesModule = __webpack_require__2(8480); + var getOwnPropertySymbolsModule = __webpack_require__2(3717); + var anObject = __webpack_require__2(8551); + var concat = uncurryThis([].concat); + module2.exports = getBuiltIn("Reflect", "ownKeys") || function ownKeys(it) { + var keys = getOwnPropertyNamesModule.f(anObject(it)); + var getOwnPropertySymbols = getOwnPropertySymbolsModule.f; + return getOwnPropertySymbols ? concat(keys, getOwnPropertySymbols(it)) : keys; + }; + }) + ), + /***/ + 5169: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var isDetached = __webpack_require__2(3238); + var $TypeError = TypeError; + module2.exports = function(it) { + if (isDetached(it)) throw new $TypeError("ArrayBuffer is detached"); + return it; + }; + }) + ), + /***/ + 5170: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThisAccessor = __webpack_require__2(6706); + var SetHelpers = __webpack_require__2(4402); + module2.exports = uncurryThisAccessor(SetHelpers.proto, "size", "get") || function(set) { + return set.size; + }; + }) + ), + /***/ + 5213: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var globalThis2 = __webpack_require__2(4576); + var arrayFromConstructorAndList = __webpack_require__2(5370); + var $fromBase64 = __webpack_require__2(9143); + var Uint8Array2 = globalThis2.Uint8Array; + var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.fromBase64 || !(function() { + try { + Uint8Array2.fromBase64("a"); + return; + } catch (error) { + } + try { + Uint8Array2.fromBase64("", null); + } catch (error) { + return true; + } + })(); + if (Uint8Array2) $({ target: "Uint8Array", stat: true, forced: INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS }, { + fromBase64: function fromBase64(string) { + var result = $fromBase64(string, arguments.length > 1 ? arguments[1] : void 0, null, 9007199254740991); + return arrayFromConstructorAndList(Uint8Array2, result.bytes); + } + }); + }) + ), + /***/ + 5370: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var lengthOfArrayLike = __webpack_require__2(6198); + module2.exports = function(Constructor, list, $length) { + var index = 0; + var length = arguments.length > 2 ? $length : lengthOfArrayLike(list); + var result = new Constructor(length); + while (length > index) result[index] = list[index++]; + return result; + }; + }) + ), + /***/ + 5397: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var IndexedObject = __webpack_require__2(7055); + var requireObjectCoercible = __webpack_require__2(7750); + module2.exports = function(it) { + return IndexedObject(requireObjectCoercible(it)); + }; + }) + ), + /***/ + 5610: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var toIntegerOrInfinity = __webpack_require__2(1291); + var max = Math.max; + var min = Math.min; + module2.exports = function(index, length) { + var integer = toIntegerOrInfinity(index); + return integer < 0 ? max(integer + length, 0) : min(integer, length); + }; + }) + ), + /***/ + 5623: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + __webpack_require__2(456); + }) + ), + /***/ + 5636: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var uncurryThis = __webpack_require__2(9504); + var uncurryThisAccessor = __webpack_require__2(6706); + var toIndex = __webpack_require__2(7696); + var notDetached = __webpack_require__2(5169); + var arrayBufferByteLength = __webpack_require__2(7394); + var detachTransferable = __webpack_require__2(4483); + var PROPER_STRUCTURED_CLONE_TRANSFER = __webpack_require__2(1548); + var structuredClone2 = globalThis2.structuredClone; + var ArrayBuffer2 = globalThis2.ArrayBuffer; + var DataView2 = globalThis2.DataView; + var min = Math.min; + var ArrayBufferPrototype = ArrayBuffer2.prototype; + var DataViewPrototype = DataView2.prototype; + var slice = uncurryThis(ArrayBufferPrototype.slice); + var isResizable = uncurryThisAccessor(ArrayBufferPrototype, "resizable", "get"); + var maxByteLength = uncurryThisAccessor(ArrayBufferPrototype, "maxByteLength", "get"); + var getInt8 = uncurryThis(DataViewPrototype.getInt8); + var setInt8 = uncurryThis(DataViewPrototype.setInt8); + module2.exports = (PROPER_STRUCTURED_CLONE_TRANSFER || detachTransferable) && function(arrayBuffer, newLength, preserveResizability) { + var byteLength = arrayBufferByteLength(arrayBuffer); + var newByteLength = newLength === void 0 ? byteLength : toIndex(newLength); + var fixedLength = !isResizable || !isResizable(arrayBuffer); + var newBuffer; + notDetached(arrayBuffer); + if (PROPER_STRUCTURED_CLONE_TRANSFER) { + arrayBuffer = structuredClone2(arrayBuffer, { transfer: [arrayBuffer] }); + if (byteLength === newByteLength && (preserveResizability || fixedLength)) return arrayBuffer; + } + if (byteLength >= newByteLength && (!preserveResizability || fixedLength)) { + newBuffer = slice(arrayBuffer, 0, newByteLength); + } else { + var options = preserveResizability && !fixedLength && maxByteLength ? { maxByteLength: maxByteLength(arrayBuffer) } : void 0; + newBuffer = new ArrayBuffer2(newByteLength, options); + var a = new DataView2(arrayBuffer); + var b = new DataView2(newBuffer); + var copyLength = min(newByteLength, byteLength); + for (var i = 0; i < copyLength; i++) setInt8(b, i, getInt8(a, i)); + } + if (!PROPER_STRUCTURED_CLONE_TRANSFER) detachTransferable(arrayBuffer); + return newBuffer; + }; + }) + ), + /***/ + 5745: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var store = __webpack_require__2(7629); + module2.exports = function(key, value) { + return store[key] || (store[key] = value || {}); + }; + }) + ), + /***/ + 5781: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var getBuiltIn = __webpack_require__2(7751); + var validateArgumentsLength = __webpack_require__2(2812); + var toString = __webpack_require__2(655); + var USE_NATIVE_URL = __webpack_require__2(7416); + var URL2 = getBuiltIn("URL"); + $({ target: "URL", stat: true, forced: !USE_NATIVE_URL }, { + parse: function parse(url) { + var length = validateArgumentsLength(arguments.length, 1); + var urlString = toString(url); + var base = length < 2 || arguments[1] === void 0 ? void 0 : toString(arguments[1]); + try { + return new URL2(urlString, base); + } catch (error) { + return null; + } + } + }); + }) + ), + /***/ + 5854: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var toPrimitive = __webpack_require__2(2777); + var $TypeError = TypeError; + module2.exports = function(argument) { + var prim = toPrimitive(argument, "number"); + if (typeof prim == "number") throw new $TypeError("Can't convert number to bigint"); + return BigInt(prim); + }; + }) + ), + /***/ + 5876: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var isSubsetOf = __webpack_require__2(3838); + var setMethodAcceptSetLike = __webpack_require__2(4916); + var INCORRECT = !setMethodAcceptSetLike("isSubsetOf", function(result) { + return result; + }); + $({ target: "Set", proto: true, real: true, forced: INCORRECT }, { + isSubsetOf + }); + }) + ), + /***/ + 5917: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var DESCRIPTORS = __webpack_require__2(3724); + var fails = __webpack_require__2(9039); + var createElement = __webpack_require__2(4055); + module2.exports = !DESCRIPTORS && !fails(function() { + return Object.defineProperty(createElement("div"), "a", { + get: function() { + return 7; + } + }).a !== 7; + }); + }) + ), + /***/ + 5966: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var aCallable = __webpack_require__2(9306); + var isNullOrUndefined = __webpack_require__2(4117); + module2.exports = function(V, P) { + var func = V[P]; + return isNullOrUndefined(func) ? void 0 : aCallable(func); + }; + }) + ), + /***/ + 6043: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var aCallable = __webpack_require__2(9306); + var $TypeError = TypeError; + var PromiseCapability = function(C) { + var resolve, reject; + this.promise = new C(function($$resolve, $$reject) { + if (resolve !== void 0 || reject !== void 0) throw new $TypeError("Bad Promise constructor"); + resolve = $$resolve; + reject = $$reject; + }); + this.resolve = aCallable(resolve); + this.reject = aCallable(reject); + }; + module2.exports.f = function(C) { + return new PromiseCapability(C); + }; + }) + ), + /***/ + 6080: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(7476); + var aCallable = __webpack_require__2(9306); + var NATIVE_BIND = __webpack_require__2(616); + var bind = uncurryThis(uncurryThis.bind); + module2.exports = function(fn, that) { + aCallable(fn); + return that === void 0 ? fn : NATIVE_BIND ? bind(fn, that) : function() { + return fn.apply(that, arguments); + }; + }; + }) + ), + /***/ + 6119: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var shared = __webpack_require__2(5745); + var uid = __webpack_require__2(3392); + var keys = shared("keys"); + module2.exports = function(key) { + return keys[key] || (keys[key] = uid(key)); + }; + }) + ), + /***/ + 6193: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var ENVIRONMENT = __webpack_require__2(4215); + module2.exports = ENVIRONMENT === "NODE"; + }) + ), + /***/ + 6198: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var toLength = __webpack_require__2(8014); + module2.exports = function(obj) { + return toLength(obj.length); + }; + }) + ), + /***/ + 6269: ( + /***/ + ((module2) => { + module2.exports = {}; + }) + ), + /***/ + 6279: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var defineBuiltIn = __webpack_require__2(6840); + module2.exports = function(target, src, options) { + for (var key in src) defineBuiltIn(target, key, src[key], options); + return target; + }; + }) + ), + /***/ + 6319: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var anObject = __webpack_require__2(8551); + var iteratorClose = __webpack_require__2(9539); + module2.exports = function(iterator, fn, value, ENTRIES) { + try { + return ENTRIES ? fn(anObject(value)[0], value[1]) : fn(value); + } catch (error) { + iteratorClose(iterator, "throw", error); + } + }; + }) + ), + /***/ + 6395: ( + /***/ + ((module2) => { + module2.exports = false; + }) + ), + /***/ + 6518: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var getOwnPropertyDescriptor = __webpack_require__2(7347).f; + var createNonEnumerableProperty = __webpack_require__2(6699); + var defineBuiltIn = __webpack_require__2(6840); + var defineGlobalProperty = __webpack_require__2(9433); + var copyConstructorProperties = __webpack_require__2(7740); + var isForced = __webpack_require__2(2796); + module2.exports = function(options, source) { + var TARGET = options.target; + var GLOBAL = options.global; + var STATIC = options.stat; + var FORCED, target, key, targetProperty, sourceProperty, descriptor; + if (GLOBAL) { + target = globalThis2; + } else if (STATIC) { + target = globalThis2[TARGET] || defineGlobalProperty(TARGET, {}); + } else { + target = globalThis2[TARGET] && globalThis2[TARGET].prototype; + } + if (target) for (key in source) { + sourceProperty = source[key]; + if (options.dontCallGetSet) { + descriptor = getOwnPropertyDescriptor(target, key); + targetProperty = descriptor && descriptor.value; + } else targetProperty = target[key]; + FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? "." : "#") + key, options.forced); + if (!FORCED && targetProperty !== void 0) { + if (typeof sourceProperty == typeof targetProperty) continue; + copyConstructorProperties(sourceProperty, targetProperty); + } + if (options.sham || targetProperty && targetProperty.sham) { + createNonEnumerableProperty(sourceProperty, "sham", true); + } + defineBuiltIn(target, key, sourceProperty, options); + } + }; + }) + ), + /***/ + 6573: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var DESCRIPTORS = __webpack_require__2(3724); + var defineBuiltInAccessor = __webpack_require__2(2106); + var isDetached = __webpack_require__2(3238); + var ArrayBufferPrototype = ArrayBuffer.prototype; + if (DESCRIPTORS && !("detached" in ArrayBufferPrototype)) { + defineBuiltInAccessor(ArrayBufferPrototype, "detached", { + configurable: true, + get: function detached() { + return isDetached(this); + } + }); + } + }) + ), + /***/ + 6632: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var globalThis2 = __webpack_require__2(4576); + var $fromBase64 = __webpack_require__2(9143); + var anUint8Array = __webpack_require__2(4154); + var Uint8Array2 = globalThis2.Uint8Array; + var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.setFromBase64 || !(function() { + var target = new Uint8Array2([255, 255, 255, 255, 255]); + try { + target.setFromBase64("", null); + return; + } catch (error) { + } + try { + target.setFromBase64("a"); + return; + } catch (error) { + } + try { + target.setFromBase64("MjYyZg==="); + } catch (error) { + return target[0] === 50 && target[1] === 54 && target[2] === 50 && target[3] === 255 && target[4] === 255; + } + })(); + if (Uint8Array2) $({ target: "Uint8Array", proto: true, forced: INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS }, { + setFromBase64: function setFromBase64(string) { + anUint8Array(this); + var result = $fromBase64(string, arguments.length > 1 ? arguments[1] : void 0, this, this.length); + return { read: result.read, written: result.written }; + } + }); + }) + ), + /***/ + 6699: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var DESCRIPTORS = __webpack_require__2(3724); + var definePropertyModule = __webpack_require__2(4913); + var createPropertyDescriptor = __webpack_require__2(6980); + module2.exports = DESCRIPTORS ? function(object, key, value) { + return definePropertyModule.f(object, key, createPropertyDescriptor(1, value)); + } : function(object, key, value) { + object[key] = value; + return object; + }; + }) + ), + /***/ + 6706: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(9504); + var aCallable = __webpack_require__2(9306); + module2.exports = function(object, key, method) { + try { + return uncurryThis(aCallable(Object.getOwnPropertyDescriptor(object, key)[method])); + } catch (error) { + } + }; + }) + ), + /***/ + 6801: ( + /***/ + ((__unused_webpack_module, exports, __webpack_require__2) => { + var DESCRIPTORS = __webpack_require__2(3724); + var V8_PROTOTYPE_DEFINE_BUG = __webpack_require__2(8686); + var definePropertyModule = __webpack_require__2(4913); + var anObject = __webpack_require__2(8551); + var toIndexedObject = __webpack_require__2(5397); + var objectKeys = __webpack_require__2(1072); + exports.f = DESCRIPTORS && !V8_PROTOTYPE_DEFINE_BUG ? Object.defineProperties : function defineProperties(O, Properties) { + anObject(O); + var props = toIndexedObject(Properties); + var keys = objectKeys(Properties); + var length = keys.length; + var index = 0; + var key; + while (length > index) definePropertyModule.f(O, key = keys[index++], props[key]); + return O; + }; + }) + ), + /***/ + 6823: ( + /***/ + ((module2) => { + var $String = String; + module2.exports = function(argument) { + try { + return $String(argument); + } catch (error) { + return "Object"; + } + }; + }) + ), + /***/ + 6837: ( + /***/ + ((module2) => { + var $TypeError = TypeError; + var MAX_SAFE_INTEGER = 9007199254740991; + module2.exports = function(it) { + if (it > MAX_SAFE_INTEGER) throw $TypeError("Maximum allowed index exceeded"); + return it; + }; + }) + ), + /***/ + 6840: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var isCallable = __webpack_require__2(4901); + var definePropertyModule = __webpack_require__2(4913); + var makeBuiltIn = __webpack_require__2(283); + var defineGlobalProperty = __webpack_require__2(9433); + module2.exports = function(O, key, value, options) { + if (!options) options = {}; + var simple = options.enumerable; + var name = options.name !== void 0 ? options.name : key; + if (isCallable(value)) makeBuiltIn(value, name, options); + if (options.global) { + if (simple) O[key] = value; + else defineGlobalProperty(key, value); + } else { + try { + if (!options.unsafe) delete O[key]; + else if (O[key]) simple = true; + } catch (error) { + } + if (simple) O[key] = value; + else definePropertyModule.f(O, key, { + value, + enumerable: false, + configurable: !options.nonConfigurable, + writable: !options.nonWritable + }); + } + return O; + }; + }) + ), + /***/ + 6955: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var TO_STRING_TAG_SUPPORT = __webpack_require__2(2140); + var isCallable = __webpack_require__2(4901); + var classofRaw = __webpack_require__2(2195); + var wellKnownSymbol = __webpack_require__2(8227); + var TO_STRING_TAG = wellKnownSymbol("toStringTag"); + var $Object = Object; + var CORRECT_ARGUMENTS = classofRaw(/* @__PURE__ */ (function() { + return arguments; + })()) === "Arguments"; + var tryGet = function(it, key) { + try { + return it[key]; + } catch (error) { + } + }; + module2.exports = TO_STRING_TAG_SUPPORT ? classofRaw : function(it) { + var O, tag, result; + return it === void 0 ? "Undefined" : it === null ? "Null" : typeof (tag = tryGet(O = $Object(it), TO_STRING_TAG)) == "string" ? tag : CORRECT_ARGUMENTS ? classofRaw(O) : (result = classofRaw(O)) === "Object" && isCallable(O.callee) ? "Arguments" : result; + }; + }) + ), + /***/ + 6969: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var toPrimitive = __webpack_require__2(2777); + var isSymbol = __webpack_require__2(757); + module2.exports = function(argument) { + var key = toPrimitive(argument, "string"); + return isSymbol(key) ? key : key + ""; + }; + }) + ), + /***/ + 6980: ( + /***/ + ((module2) => { + module2.exports = function(bitmap, value) { + return { + enumerable: !(bitmap & 1), + configurable: !(bitmap & 2), + writable: !(bitmap & 4), + value + }; + }; + }) + ), + /***/ + 7040: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var NATIVE_SYMBOL = __webpack_require__2(4495); + module2.exports = NATIVE_SYMBOL && !Symbol.sham && typeof Symbol.iterator == "symbol"; + }) + ), + /***/ + 7055: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(9504); + var fails = __webpack_require__2(9039); + var classof = __webpack_require__2(2195); + var $Object = Object; + var split = uncurryThis("".split); + module2.exports = fails(function() { + return !$Object("z").propertyIsEnumerable(0); + }) ? function(it) { + return classof(it) === "String" ? split(it, "") : $Object(it); + } : $Object; + }) + ), + /***/ + 7080: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var has = __webpack_require__2(4402).has; + module2.exports = function(it) { + has(it); + return it; + }; + }) + ), + /***/ + 7347: ( + /***/ + ((__unused_webpack_module, exports, __webpack_require__2) => { + var DESCRIPTORS = __webpack_require__2(3724); + var call = __webpack_require__2(9565); + var propertyIsEnumerableModule = __webpack_require__2(8773); + var createPropertyDescriptor = __webpack_require__2(6980); + var toIndexedObject = __webpack_require__2(5397); + var toPropertyKey = __webpack_require__2(6969); + var hasOwn = __webpack_require__2(9297); + var IE8_DOM_DEFINE = __webpack_require__2(5917); + var $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + exports.f = DESCRIPTORS ? $getOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) { + O = toIndexedObject(O); + P = toPropertyKey(P); + if (IE8_DOM_DEFINE) try { + return $getOwnPropertyDescriptor(O, P); + } catch (error) { + } + if (hasOwn(O, P)) return createPropertyDescriptor(!call(propertyIsEnumerableModule.f, O, P), O[P]); + }; + }) + ), + /***/ + 7394: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var uncurryThisAccessor = __webpack_require__2(6706); + var classof = __webpack_require__2(2195); + var ArrayBuffer2 = globalThis2.ArrayBuffer; + var TypeError2 = globalThis2.TypeError; + module2.exports = ArrayBuffer2 && uncurryThisAccessor(ArrayBuffer2.prototype, "byteLength", "get") || function(O) { + if (classof(O) !== "ArrayBuffer") throw new TypeError2("ArrayBuffer expected"); + return O.byteLength; + }; + }) + ), + /***/ + 7416: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var fails = __webpack_require__2(9039); + var wellKnownSymbol = __webpack_require__2(8227); + var DESCRIPTORS = __webpack_require__2(3724); + var IS_PURE = __webpack_require__2(6395); + var ITERATOR = wellKnownSymbol("iterator"); + module2.exports = !fails(function() { + var url = new URL("b?a=1&b=2&c=3", "https://a"); + var params = url.searchParams; + var params2 = new URLSearchParams("a=1&a=2&b=3"); + var result = ""; + url.pathname = "c%20d"; + params.forEach(function(value, key) { + params["delete"]("b"); + result += key + value; + }); + params2["delete"]("a", 2); + params2["delete"]("b", void 0); + return IS_PURE && (!url.toJSON || !params2.has("a", 1) || params2.has("a", 2) || !params2.has("a", void 0) || params2.has("b")) || !params.size && (IS_PURE || !DESCRIPTORS) || !params.sort || url.href !== "https://a/c%20d?a=1&c=3" || params.get("c") !== "3" || String(new URLSearchParams("?a=1")) !== "a=1" || !params[ITERATOR] || new URL("https://a@b").username !== "a" || new URLSearchParams(new URLSearchParams("a=b")).get("a") !== "b" || new URL("https://тест").host !== "xn--e1aybc" || new URL("https://a#б").hash !== "#%D0%B1" || result !== "a1c3" || new URL("https://x", void 0).host !== "x"; + }); + }) + ), + /***/ + 7476: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var classofRaw = __webpack_require__2(2195); + var uncurryThis = __webpack_require__2(9504); + module2.exports = function(fn) { + if (classofRaw(fn) === "Function") return uncurryThis(fn); + }; + }) + ), + /***/ + 7566: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var defineBuiltIn = __webpack_require__2(6840); + var uncurryThis = __webpack_require__2(9504); + var toString = __webpack_require__2(655); + var validateArgumentsLength = __webpack_require__2(2812); + var $URLSearchParams = URLSearchParams; + var URLSearchParamsPrototype = $URLSearchParams.prototype; + var getAll = uncurryThis(URLSearchParamsPrototype.getAll); + var $has = uncurryThis(URLSearchParamsPrototype.has); + var params = new $URLSearchParams("a=1"); + if (params.has("a", 2) || !params.has("a", void 0)) { + defineBuiltIn(URLSearchParamsPrototype, "has", function has(name) { + var length = arguments.length; + var $value = length < 2 ? void 0 : arguments[1]; + if (length && $value === void 0) return $has(this, name); + var values = getAll(this, name); + validateArgumentsLength(length, 1); + var value = toString($value); + var index = 0; + while (index < values.length) { + if (values[index++] === value) return true; + } + return false; + }, { enumerable: true, unsafe: true }); + } + }) + ), + /***/ + 7588: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var call = __webpack_require__2(9565); + var iterate = __webpack_require__2(2652); + var aCallable = __webpack_require__2(9306); + var anObject = __webpack_require__2(8551); + var getIteratorDirect = __webpack_require__2(1767); + var iteratorClose = __webpack_require__2(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + var forEachWithoutClosingOnEarlyError = iteratorHelperWithoutClosingOnEarlyError("forEach", TypeError); + $({ target: "Iterator", proto: true, real: true, forced: forEachWithoutClosingOnEarlyError }, { + forEach: function forEach(fn) { + anObject(this); + try { + aCallable(fn); + } catch (error) { + iteratorClose(this, "throw", error); + } + if (forEachWithoutClosingOnEarlyError) return call(forEachWithoutClosingOnEarlyError, this, fn); + var record = getIteratorDirect(this); + var counter = 0; + iterate(record, function(value) { + fn(value, counter++); + }, { IS_RECORD: true }); + } + }); + }) + ), + /***/ + 7629: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var IS_PURE = __webpack_require__2(6395); + var globalThis2 = __webpack_require__2(4576); + var defineGlobalProperty = __webpack_require__2(9433); + var SHARED = "__core-js_shared__"; + var store = module2.exports = globalThis2[SHARED] || defineGlobalProperty(SHARED, {}); + (store.versions || (store.versions = [])).push({ + version: "3.45.1", + mode: IS_PURE ? "pure" : "global", + copyright: "© 2014-2025 Denis Pushkarev (zloirock.ru)", + license: "https://github.com/zloirock/core-js/blob/v3.45.1/LICENSE", + source: "https://github.com/zloirock/core-js" + }); + }) + ), + /***/ + 7642: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var difference = __webpack_require__2(3440); + var fails = __webpack_require__2(9039); + var setMethodAcceptSetLike = __webpack_require__2(4916); + var SET_LIKE_INCORRECT_BEHAVIOR = !setMethodAcceptSetLike("difference", function(result) { + return result.size === 0; + }); + var FORCED = SET_LIKE_INCORRECT_BEHAVIOR || fails(function() { + var setLike = { + size: 1, + has: function() { + return true; + }, + keys: function() { + var index = 0; + return { + next: function() { + var done = index++ > 1; + if (baseSet.has(1)) baseSet.clear(); + return { done, value: 2 }; + } + }; + } + }; + var baseSet = /* @__PURE__ */ new Set([1, 2, 3, 4]); + return baseSet.difference(setLike).size !== 3; + }); + $({ target: "Set", proto: true, real: true, forced: FORCED }, { + difference + }); + }) + ), + /***/ + 7657: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var fails = __webpack_require__2(9039); + var isCallable = __webpack_require__2(4901); + var isObject = __webpack_require__2(34); + var create = __webpack_require__2(2360); + var getPrototypeOf = __webpack_require__2(2787); + var defineBuiltIn = __webpack_require__2(6840); + var wellKnownSymbol = __webpack_require__2(8227); + var IS_PURE = __webpack_require__2(6395); + var ITERATOR = wellKnownSymbol("iterator"); + var BUGGY_SAFARI_ITERATORS = false; + var IteratorPrototype, PrototypeOfArrayIteratorPrototype, arrayIterator; + if ([].keys) { + arrayIterator = [].keys(); + if (!("next" in arrayIterator)) BUGGY_SAFARI_ITERATORS = true; + else { + PrototypeOfArrayIteratorPrototype = getPrototypeOf(getPrototypeOf(arrayIterator)); + if (PrototypeOfArrayIteratorPrototype !== Object.prototype) IteratorPrototype = PrototypeOfArrayIteratorPrototype; + } + } + var NEW_ITERATOR_PROTOTYPE = !isObject(IteratorPrototype) || fails(function() { + var test = {}; + return IteratorPrototype[ITERATOR].call(test) !== test; + }); + if (NEW_ITERATOR_PROTOTYPE) IteratorPrototype = {}; + else if (IS_PURE) IteratorPrototype = create(IteratorPrototype); + if (!isCallable(IteratorPrototype[ITERATOR])) { + defineBuiltIn(IteratorPrototype, ITERATOR, function() { + return this; + }); + } + module2.exports = { + IteratorPrototype, + BUGGY_SAFARI_ITERATORS + }; + }) + ), + /***/ + 7680: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(9504); + module2.exports = uncurryThis([].slice); + }) + ), + /***/ + 7696: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var toIntegerOrInfinity = __webpack_require__2(1291); + var toLength = __webpack_require__2(8014); + var $RangeError = RangeError; + module2.exports = function(it) { + if (it === void 0) return 0; + var number = toIntegerOrInfinity(it); + var length = toLength(number); + if (number !== length) throw new $RangeError("Wrong length or index"); + return length; + }; + }) + ), + /***/ + 7740: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var hasOwn = __webpack_require__2(9297); + var ownKeys = __webpack_require__2(5031); + var getOwnPropertyDescriptorModule = __webpack_require__2(7347); + var definePropertyModule = __webpack_require__2(4913); + module2.exports = function(target, source, exceptions) { + var keys = ownKeys(source); + var defineProperty = definePropertyModule.f; + var getOwnPropertyDescriptor = getOwnPropertyDescriptorModule.f; + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + if (!hasOwn(target, key) && !(exceptions && hasOwn(exceptions, key))) { + defineProperty(target, key, getOwnPropertyDescriptor(source, key)); + } + } + }; + }) + ), + /***/ + 7750: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var isNullOrUndefined = __webpack_require__2(4117); + var $TypeError = TypeError; + module2.exports = function(it) { + if (isNullOrUndefined(it)) throw new $TypeError("Can't call method on " + it); + return it; + }; + }) + ), + /***/ + 7751: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var isCallable = __webpack_require__2(4901); + var aFunction = function(argument) { + return isCallable(argument) ? argument : void 0; + }; + module2.exports = function(namespace, method) { + return arguments.length < 2 ? aFunction(globalThis2[namespace]) : globalThis2[namespace] && globalThis2[namespace][method]; + }; + }) + ), + /***/ + 7811: ( + /***/ + ((module2) => { + module2.exports = typeof ArrayBuffer != "undefined" && typeof DataView != "undefined"; + }) + ), + /***/ + 7936: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var $transfer = __webpack_require__2(5636); + if ($transfer) $({ target: "ArrayBuffer", proto: true }, { + transferToFixedLength: function transferToFixedLength() { + return $transfer(this, arguments.length ? arguments[0] : void 0, false); + } + }); + }) + ), + /***/ + 8004: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var fails = __webpack_require__2(9039); + var intersection = __webpack_require__2(8750); + var setMethodAcceptSetLike = __webpack_require__2(4916); + var INCORRECT = !setMethodAcceptSetLike("intersection", function(result) { + return result.size === 2 && result.has(1) && result.has(2); + }) || fails(function() { + return String(Array.from((/* @__PURE__ */ new Set([1, 2, 3])).intersection(/* @__PURE__ */ new Set([3, 2])))) !== "3,2"; + }); + $({ target: "Set", proto: true, real: true, forced: INCORRECT }, { + intersection + }); + }) + ), + /***/ + 8014: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var toIntegerOrInfinity = __webpack_require__2(1291); + var min = Math.min; + module2.exports = function(argument) { + var len = toIntegerOrInfinity(argument); + return len > 0 ? min(len, 9007199254740991) : 0; + }; + }) + ), + /***/ + 8100: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var $transfer = __webpack_require__2(5636); + if ($transfer) $({ target: "ArrayBuffer", proto: true }, { + transfer: function transfer() { + return $transfer(this, arguments.length ? arguments[0] : void 0, true); + } + }); + }) + ), + /***/ + 8111: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var globalThis2 = __webpack_require__2(4576); + var anInstance = __webpack_require__2(679); + var anObject = __webpack_require__2(8551); + var isCallable = __webpack_require__2(4901); + var getPrototypeOf = __webpack_require__2(2787); + var defineBuiltInAccessor = __webpack_require__2(2106); + var createProperty = __webpack_require__2(4659); + var fails = __webpack_require__2(9039); + var hasOwn = __webpack_require__2(9297); + var wellKnownSymbol = __webpack_require__2(8227); + var IteratorPrototype = __webpack_require__2(7657).IteratorPrototype; + var DESCRIPTORS = __webpack_require__2(3724); + var IS_PURE = __webpack_require__2(6395); + var CONSTRUCTOR = "constructor"; + var ITERATOR = "Iterator"; + var TO_STRING_TAG = wellKnownSymbol("toStringTag"); + var $TypeError = TypeError; + var NativeIterator = globalThis2[ITERATOR]; + var FORCED = IS_PURE || !isCallable(NativeIterator) || NativeIterator.prototype !== IteratorPrototype || !fails(function() { + NativeIterator({}); + }); + var IteratorConstructor = function Iterator2() { + anInstance(this, IteratorPrototype); + if (getPrototypeOf(this) === IteratorPrototype) throw new $TypeError("Abstract class Iterator not directly constructable"); + }; + var defineIteratorPrototypeAccessor = function(key, value) { + if (DESCRIPTORS) { + defineBuiltInAccessor(IteratorPrototype, key, { + configurable: true, + get: function() { + return value; + }, + set: function(replacement) { + anObject(this); + if (this === IteratorPrototype) throw new $TypeError("You can't redefine this property"); + if (hasOwn(this, key)) this[key] = replacement; + else createProperty(this, key, replacement); + } + }); + } else IteratorPrototype[key] = value; + }; + if (!hasOwn(IteratorPrototype, TO_STRING_TAG)) defineIteratorPrototypeAccessor(TO_STRING_TAG, ITERATOR); + if (FORCED || !hasOwn(IteratorPrototype, CONSTRUCTOR) || IteratorPrototype[CONSTRUCTOR] === Object) { + defineIteratorPrototypeAccessor(CONSTRUCTOR, IteratorConstructor); + } + IteratorConstructor.prototype = IteratorPrototype; + $({ global: true, constructor: true, forced: FORCED }, { + Iterator: IteratorConstructor + }); + }) + ), + /***/ + 8227: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var shared = __webpack_require__2(5745); + var hasOwn = __webpack_require__2(9297); + var uid = __webpack_require__2(3392); + var NATIVE_SYMBOL = __webpack_require__2(4495); + var USE_SYMBOL_AS_UID = __webpack_require__2(7040); + var Symbol2 = globalThis2.Symbol; + var WellKnownSymbolsStore = shared("wks"); + var createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol2["for"] || Symbol2 : Symbol2 && Symbol2.withoutSetter || uid; + module2.exports = function(name) { + if (!hasOwn(WellKnownSymbolsStore, name)) { + WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn(Symbol2, name) ? Symbol2[name] : createWellKnownSymbol("Symbol." + name); + } + return WellKnownSymbolsStore[name]; + }; + }) + ), + /***/ + 8235: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(9504); + var hasOwn = __webpack_require__2(9297); + var $SyntaxError = SyntaxError; + var $parseInt = parseInt; + var fromCharCode = String.fromCharCode; + var at = uncurryThis("".charAt); + var slice = uncurryThis("".slice); + var exec = uncurryThis(/./.exec); + var codePoints = { + '\\"': '"', + "\\\\": "\\", + "\\/": "/", + "\\b": "\b", + "\\f": "\f", + "\\n": "\n", + "\\r": "\r", + "\\t": " " + }; + var IS_4_HEX_DIGITS = /^[\da-f]{4}$/i; + var IS_C0_CONTROL_CODE = /^[\u0000-\u001F]$/; + module2.exports = function(source, i) { + var unterminated = true; + var value = ""; + while (i < source.length) { + var chr = at(source, i); + if (chr === "\\") { + var twoChars = slice(source, i, i + 2); + if (hasOwn(codePoints, twoChars)) { + value += codePoints[twoChars]; + i += 2; + } else if (twoChars === "\\u") { + i += 2; + var fourHexDigits = slice(source, i, i + 4); + if (!exec(IS_4_HEX_DIGITS, fourHexDigits)) throw new $SyntaxError("Bad Unicode escape at: " + i); + value += fromCharCode($parseInt(fourHexDigits, 16)); + i += 4; + } else throw new $SyntaxError('Unknown escape sequence: "' + twoChars + '"'); + } else if (chr === '"') { + unterminated = false; + i++; + break; + } else { + if (exec(IS_C0_CONTROL_CODE, chr)) throw new $SyntaxError("Bad control character in string literal at: " + i); + value += chr; + i++; + } + } + if (unterminated) throw new $SyntaxError("Unterminated string at: " + i); + return { value, end: i }; + }; + }) + ), + /***/ + 8237: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var iterate = __webpack_require__2(2652); + var aCallable = __webpack_require__2(9306); + var anObject = __webpack_require__2(8551); + var getIteratorDirect = __webpack_require__2(1767); + var iteratorClose = __webpack_require__2(9539); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + var apply = __webpack_require__2(8745); + var fails = __webpack_require__2(9039); + var $TypeError = TypeError; + var FAILS_ON_INITIAL_UNDEFINED = fails(function() { + [].keys().reduce(function() { + }, void 0); + }); + var reduceWithoutClosingOnEarlyError = !FAILS_ON_INITIAL_UNDEFINED && iteratorHelperWithoutClosingOnEarlyError("reduce", $TypeError); + $({ target: "Iterator", proto: true, real: true, forced: FAILS_ON_INITIAL_UNDEFINED || reduceWithoutClosingOnEarlyError }, { + reduce: function reduce(reducer) { + anObject(this); + try { + aCallable(reducer); + } catch (error) { + iteratorClose(this, "throw", error); + } + var noInitial = arguments.length < 2; + var accumulator = noInitial ? void 0 : arguments[1]; + if (reduceWithoutClosingOnEarlyError) { + return apply(reduceWithoutClosingOnEarlyError, this, noInitial ? [reducer] : [reducer, accumulator]); + } + var record = getIteratorDirect(this); + var counter = 0; + iterate(record, function(value) { + if (noInitial) { + noInitial = false; + accumulator = value; + } else { + accumulator = reducer(accumulator, value, counter); + } + counter++; + }, { IS_RECORD: true }); + if (noInitial) throw new $TypeError("Reduce of empty iterator with no initial value"); + return accumulator; + } + }); + }) + ), + /***/ + 8335: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var DESCRIPTORS = __webpack_require__2(3724); + var globalThis2 = __webpack_require__2(4576); + var getBuiltIn = __webpack_require__2(7751); + var uncurryThis = __webpack_require__2(9504); + var call = __webpack_require__2(9565); + var isCallable = __webpack_require__2(4901); + var isObject = __webpack_require__2(34); + var isArray = __webpack_require__2(4376); + var hasOwn = __webpack_require__2(9297); + var toString = __webpack_require__2(655); + var lengthOfArrayLike = __webpack_require__2(6198); + var createProperty = __webpack_require__2(4659); + var fails = __webpack_require__2(9039); + var parseJSONString = __webpack_require__2(8235); + var NATIVE_SYMBOL = __webpack_require__2(4495); + var JSON2 = globalThis2.JSON; + var Number2 = globalThis2.Number; + var SyntaxError2 = globalThis2.SyntaxError; + var nativeParse = JSON2 && JSON2.parse; + var enumerableOwnProperties = getBuiltIn("Object", "keys"); + var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + var at = uncurryThis("".charAt); + var slice = uncurryThis("".slice); + var exec = uncurryThis(/./.exec); + var push = uncurryThis([].push); + var IS_DIGIT = /^\d$/; + var IS_NON_ZERO_DIGIT = /^[1-9]$/; + var IS_NUMBER_START = /^[\d-]$/; + var IS_WHITESPACE = /^[\t\n\r ]$/; + var PRIMITIVE = 0; + var OBJECT = 1; + var $parse = function(source, reviver) { + source = toString(source); + var context = new Context(source, 0); + var root = context.parse(); + var value = root.value; + var endIndex = context.skip(IS_WHITESPACE, root.end); + if (endIndex < source.length) { + throw new SyntaxError2('Unexpected extra character: "' + at(source, endIndex) + '" after the parsed data at: ' + endIndex); + } + return isCallable(reviver) ? internalize({ "": value }, "", reviver, root) : value; + }; + var internalize = function(holder, name, reviver, node) { + var val = holder[name]; + var unmodified = node && val === node.value; + var context = unmodified && typeof node.source == "string" ? { source: node.source } : {}; + var elementRecordsLen, keys, len, i, P; + if (isObject(val)) { + var nodeIsArray = isArray(val); + var nodes = unmodified ? node.nodes : nodeIsArray ? [] : {}; + if (nodeIsArray) { + elementRecordsLen = nodes.length; + len = lengthOfArrayLike(val); + for (i = 0; i < len; i++) { + internalizeProperty(val, i, internalize(val, "" + i, reviver, i < elementRecordsLen ? nodes[i] : void 0)); + } + } else { + keys = enumerableOwnProperties(val); + len = lengthOfArrayLike(keys); + for (i = 0; i < len; i++) { + P = keys[i]; + internalizeProperty(val, P, internalize(val, P, reviver, hasOwn(nodes, P) ? nodes[P] : void 0)); + } + } + } + return call(reviver, holder, name, val, context); + }; + var internalizeProperty = function(object, key, value) { + if (DESCRIPTORS) { + var descriptor = getOwnPropertyDescriptor(object, key); + if (descriptor && !descriptor.configurable) return; + } + if (value === void 0) delete object[key]; + else createProperty(object, key, value); + }; + var Node2 = function(value, end, source, nodes) { + this.value = value; + this.end = end; + this.source = source; + this.nodes = nodes; + }; + var Context = function(source, index) { + this.source = source; + this.index = index; + }; + Context.prototype = { + fork: function(nextIndex) { + return new Context(this.source, nextIndex); + }, + parse: function() { + var source = this.source; + var i = this.skip(IS_WHITESPACE, this.index); + var fork = this.fork(i); + var chr = at(source, i); + if (exec(IS_NUMBER_START, chr)) return fork.number(); + switch (chr) { + case "{": + return fork.object(); + case "[": + return fork.array(); + case '"': + return fork.string(); + case "t": + return fork.keyword(true); + case "f": + return fork.keyword(false); + case "n": + return fork.keyword(null); + } + throw new SyntaxError2('Unexpected character: "' + chr + '" at: ' + i); + }, + node: function(type, value, start, end, nodes) { + return new Node2(value, end, type ? null : slice(this.source, start, end), nodes); + }, + object: function() { + var source = this.source; + var i = this.index + 1; + var expectKeypair = false; + var object = {}; + var nodes = {}; + while (i < source.length) { + i = this.until(['"', "}"], i); + if (at(source, i) === "}" && !expectKeypair) { + i++; + break; + } + var result = this.fork(i).string(); + var key = result.value; + i = result.end; + i = this.until([":"], i) + 1; + i = this.skip(IS_WHITESPACE, i); + result = this.fork(i).parse(); + createProperty(nodes, key, result); + createProperty(object, key, result.value); + i = this.until([",", "}"], result.end); + var chr = at(source, i); + if (chr === ",") { + expectKeypair = true; + i++; + } else if (chr === "}") { + i++; + break; + } + } + return this.node(OBJECT, object, this.index, i, nodes); + }, + array: function() { + var source = this.source; + var i = this.index + 1; + var expectElement = false; + var array = []; + var nodes = []; + while (i < source.length) { + i = this.skip(IS_WHITESPACE, i); + if (at(source, i) === "]" && !expectElement) { + i++; + break; + } + var result = this.fork(i).parse(); + push(nodes, result); + push(array, result.value); + i = this.until([",", "]"], result.end); + if (at(source, i) === ",") { + expectElement = true; + i++; + } else if (at(source, i) === "]") { + i++; + break; + } + } + return this.node(OBJECT, array, this.index, i, nodes); + }, + string: function() { + var index = this.index; + var parsed = parseJSONString(this.source, this.index + 1); + return this.node(PRIMITIVE, parsed.value, index, parsed.end); + }, + number: function() { + var source = this.source; + var startIndex = this.index; + var i = startIndex; + if (at(source, i) === "-") i++; + if (at(source, i) === "0") i++; + else if (exec(IS_NON_ZERO_DIGIT, at(source, i))) i = this.skip(IS_DIGIT, i + 1); + else throw new SyntaxError2("Failed to parse number at: " + i); + if (at(source, i) === ".") i = this.skip(IS_DIGIT, i + 1); + if (at(source, i) === "e" || at(source, i) === "E") { + i++; + if (at(source, i) === "+" || at(source, i) === "-") i++; + var exponentStartIndex = i; + i = this.skip(IS_DIGIT, i); + if (exponentStartIndex === i) throw new SyntaxError2("Failed to parse number's exponent value at: " + i); + } + return this.node(PRIMITIVE, Number2(slice(source, startIndex, i)), startIndex, i); + }, + keyword: function(value) { + var keyword = "" + value; + var index = this.index; + var endIndex = index + keyword.length; + if (slice(this.source, index, endIndex) !== keyword) throw new SyntaxError2("Failed to parse value at: " + index); + return this.node(PRIMITIVE, value, index, endIndex); + }, + skip: function(regex, i) { + var source = this.source; + for (; i < source.length; i++) if (!exec(regex, at(source, i))) break; + return i; + }, + until: function(array, i) { + i = this.skip(IS_WHITESPACE, i); + var chr = at(this.source, i); + for (var j = 0; j < array.length; j++) if (array[j] === chr) return i; + throw new SyntaxError2('Unexpected character: "' + chr + '" at: ' + i); + } + }; + var NO_SOURCE_SUPPORT = fails(function() { + var unsafeInt = "9007199254740993"; + var source; + nativeParse(unsafeInt, function(key, value, context) { + source = context.source; + }); + return source !== unsafeInt; + }); + var PROPER_BASE_PARSE = NATIVE_SYMBOL && !fails(function() { + return 1 / nativeParse("-0 ") !== -Infinity; + }); + $({ target: "JSON", stat: true, forced: NO_SOURCE_SUPPORT }, { + parse: function parse(text, reviver) { + return PROPER_BASE_PARSE && !isCallable(reviver) ? nativeParse(text) : $parse(text, reviver); + } + }); + }) + ), + /***/ + 8469: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(9504); + var iterateSimple = __webpack_require__2(507); + var SetHelpers = __webpack_require__2(4402); + var Set2 = SetHelpers.Set; + var SetPrototype = SetHelpers.proto; + var forEach = uncurryThis(SetPrototype.forEach); + var keys = uncurryThis(SetPrototype.keys); + var next = keys(new Set2()).next; + module2.exports = function(set, fn, interruptible) { + return interruptible ? iterateSimple({ iterator: keys(set), next }, fn) : forEach(set, fn); + }; + }) + ), + /***/ + 8480: ( + /***/ + ((__unused_webpack_module, exports, __webpack_require__2) => { + var internalObjectKeys = __webpack_require__2(1828); + var enumBugKeys = __webpack_require__2(8727); + var hiddenKeys = enumBugKeys.concat("length", "prototype"); + exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { + return internalObjectKeys(O, hiddenKeys); + }; + }) + ), + /***/ + 8527: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var aSet = __webpack_require__2(7080); + var has = __webpack_require__2(4402).has; + var size = __webpack_require__2(5170); + var getSetRecord = __webpack_require__2(3789); + var iterateSimple = __webpack_require__2(507); + var iteratorClose = __webpack_require__2(9539); + module2.exports = function isSupersetOf(other) { + var O = aSet(this); + var otherRec = getSetRecord(other); + if (size(O) < otherRec.size) return false; + var iterator = otherRec.getIterator(); + return iterateSimple(iterator, function(e) { + if (!has(O, e)) return iteratorClose(iterator, "normal", false); + }) !== false; + }; + }) + ), + /***/ + 8551: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var isObject = __webpack_require__2(34); + var $String = String; + var $TypeError = TypeError; + module2.exports = function(argument) { + if (isObject(argument)) return argument; + throw new $TypeError($String(argument) + " is not an object"); + }; + }) + ), + /***/ + 8574: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(9504); + var $Error = Error; + var replace = uncurryThis("".replace); + var TEST = (function(arg) { + return String(new $Error(arg).stack); + })("zxcasd"); + var V8_OR_CHAKRA_STACK_ENTRY = /\n\s*at [^:]*:[^\n]*/; + var IS_V8_OR_CHAKRA_STACK = V8_OR_CHAKRA_STACK_ENTRY.test(TEST); + module2.exports = function(stack, dropEntries) { + if (IS_V8_OR_CHAKRA_STACK && typeof stack == "string" && !$Error.prepareStackTrace) { + while (dropEntries--) stack = replace(stack, V8_OR_CHAKRA_STACK_ENTRY, ""); + } + return stack; + }; + }) + ), + /***/ + 8622: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var isCallable = __webpack_require__2(4901); + var WeakMap2 = globalThis2.WeakMap; + module2.exports = isCallable(WeakMap2) && /native code/.test(String(WeakMap2)); + }) + ), + /***/ + 8646: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var call = __webpack_require__2(9565); + var anObject = __webpack_require__2(8551); + var getIteratorDirect = __webpack_require__2(1767); + var getIteratorMethod = __webpack_require__2(851); + module2.exports = function(obj, stringHandling) { + if (!stringHandling || typeof obj !== "string") anObject(obj); + var method = getIteratorMethod(obj); + return getIteratorDirect(anObject(method !== void 0 ? call(method, obj) : obj)); + }; + }) + ), + /***/ + 8686: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var DESCRIPTORS = __webpack_require__2(3724); + var fails = __webpack_require__2(9039); + module2.exports = DESCRIPTORS && fails(function() { + return Object.defineProperty(function() { + }, "prototype", { + value: 42, + writable: false + }).prototype !== 42; + }); + }) + ), + /***/ + 8721: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var DESCRIPTORS = __webpack_require__2(3724); + var uncurryThis = __webpack_require__2(9504); + var defineBuiltInAccessor = __webpack_require__2(2106); + var URLSearchParamsPrototype = URLSearchParams.prototype; + var forEach = uncurryThis(URLSearchParamsPrototype.forEach); + if (DESCRIPTORS && !("size" in URLSearchParamsPrototype)) { + defineBuiltInAccessor(URLSearchParamsPrototype, "size", { + get: function size() { + var count = 0; + forEach(this, function() { + count++; + }); + return count; + }, + configurable: true, + enumerable: true + }); + } + }) + ), + /***/ + 8727: ( + /***/ + ((module2) => { + module2.exports = [ + "constructor", + "hasOwnProperty", + "isPrototypeOf", + "propertyIsEnumerable", + "toLocaleString", + "toString", + "valueOf" + ]; + }) + ), + /***/ + 8745: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var NATIVE_BIND = __webpack_require__2(616); + var FunctionPrototype = Function.prototype; + var apply = FunctionPrototype.apply; + var call = FunctionPrototype.call; + module2.exports = typeof Reflect == "object" && Reflect.apply || (NATIVE_BIND ? call.bind(apply) : function() { + return call.apply(apply, arguments); + }); + }) + ), + /***/ + 8750: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var aSet = __webpack_require__2(7080); + var SetHelpers = __webpack_require__2(4402); + var size = __webpack_require__2(5170); + var getSetRecord = __webpack_require__2(3789); + var iterateSet = __webpack_require__2(8469); + var iterateSimple = __webpack_require__2(507); + var Set2 = SetHelpers.Set; + var add = SetHelpers.add; + var has = SetHelpers.has; + module2.exports = function intersection(other) { + var O = aSet(this); + var otherRec = getSetRecord(other); + var result = new Set2(); + if (size(O) > otherRec.size) { + iterateSimple(otherRec.getIterator(), function(e) { + if (has(O, e)) add(result, e); + }); + } else { + iterateSet(O, function(e) { + if (otherRec.includes(e)) add(result, e); + }); + } + return result; + }; + }) + ), + /***/ + 8773: ( + /***/ + ((__unused_webpack_module, exports) => { + var $propertyIsEnumerable = {}.propertyIsEnumerable; + var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + var NASHORN_BUG = getOwnPropertyDescriptor && !$propertyIsEnumerable.call({ 1: 2 }, 1); + exports.f = NASHORN_BUG ? function propertyIsEnumerable(V) { + var descriptor = getOwnPropertyDescriptor(this, V); + return !!descriptor && descriptor.enumerable; + } : $propertyIsEnumerable; + }) + ), + /***/ + 8981: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var requireObjectCoercible = __webpack_require__2(7750); + var $Object = Object; + module2.exports = function(argument) { + return $Object(requireObjectCoercible(argument)); + }; + }) + ), + /***/ + 9039: ( + /***/ + ((module2) => { + module2.exports = function(exec) { + try { + return !!exec(); + } catch (error) { + return true; + } + }; + }) + ), + /***/ + 9143: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var uncurryThis = __webpack_require__2(9504); + var anObjectOrUndefined = __webpack_require__2(3972); + var aString = __webpack_require__2(3463); + var hasOwn = __webpack_require__2(9297); + var base64Map = __webpack_require__2(2804); + var getAlphabetOption = __webpack_require__2(944); + var notDetached = __webpack_require__2(5169); + var base64Alphabet = base64Map.c2i; + var base64UrlAlphabet = base64Map.c2iUrl; + var SyntaxError2 = globalThis2.SyntaxError; + var TypeError2 = globalThis2.TypeError; + var at = uncurryThis("".charAt); + var skipAsciiWhitespace = function(string, index) { + var length = string.length; + for (; index < length; index++) { + var chr = at(string, index); + if (chr !== " " && chr !== " " && chr !== "\n" && chr !== "\f" && chr !== "\r") break; + } + return index; + }; + var decodeBase64Chunk = function(chunk, alphabet, throwOnExtraBits) { + var chunkLength = chunk.length; + if (chunkLength < 4) { + chunk += chunkLength === 2 ? "AA" : "A"; + } + var triplet = (alphabet[at(chunk, 0)] << 18) + (alphabet[at(chunk, 1)] << 12) + (alphabet[at(chunk, 2)] << 6) + alphabet[at(chunk, 3)]; + var chunkBytes = [ + triplet >> 16 & 255, + triplet >> 8 & 255, + triplet & 255 + ]; + if (chunkLength === 2) { + if (throwOnExtraBits && chunkBytes[1] !== 0) { + throw new SyntaxError2("Extra bits"); + } + return [chunkBytes[0]]; + } + if (chunkLength === 3) { + if (throwOnExtraBits && chunkBytes[2] !== 0) { + throw new SyntaxError2("Extra bits"); + } + return [chunkBytes[0], chunkBytes[1]]; + } + return chunkBytes; + }; + var writeBytes = function(bytes, elements, written) { + var elementsLength = elements.length; + for (var index = 0; index < elementsLength; index++) { + bytes[written + index] = elements[index]; + } + return written + elementsLength; + }; + module2.exports = function(string, options, into, maxLength) { + aString(string); + anObjectOrUndefined(options); + var alphabet = getAlphabetOption(options) === "base64" ? base64Alphabet : base64UrlAlphabet; + var lastChunkHandling = options ? options.lastChunkHandling : void 0; + if (lastChunkHandling === void 0) lastChunkHandling = "loose"; + if (lastChunkHandling !== "loose" && lastChunkHandling !== "strict" && lastChunkHandling !== "stop-before-partial") { + throw new TypeError2("Incorrect `lastChunkHandling` option"); + } + if (into) notDetached(into.buffer); + var stringLength = string.length; + var bytes = into || []; + var written = 0; + var read = 0; + var chunk = ""; + var index = 0; + if (maxLength) while (true) { + index = skipAsciiWhitespace(string, index); + if (index === stringLength) { + if (chunk.length > 0) { + if (lastChunkHandling === "stop-before-partial") { + break; + } + if (lastChunkHandling === "loose") { + if (chunk.length === 1) { + throw new SyntaxError2("Malformed padding: exactly one additional character"); + } + written = writeBytes(bytes, decodeBase64Chunk(chunk, alphabet, false), written); + } else { + throw new SyntaxError2("Missing padding"); + } + } + read = stringLength; + break; + } + var chr = at(string, index); + ++index; + if (chr === "=") { + if (chunk.length < 2) { + throw new SyntaxError2("Padding is too early"); + } + index = skipAsciiWhitespace(string, index); + if (chunk.length === 2) { + if (index === stringLength) { + if (lastChunkHandling === "stop-before-partial") { + break; + } + throw new SyntaxError2("Malformed padding: only one ="); + } + if (at(string, index) === "=") { + ++index; + index = skipAsciiWhitespace(string, index); + } + } + if (index < stringLength) { + throw new SyntaxError2("Unexpected character after padding"); + } + written = writeBytes(bytes, decodeBase64Chunk(chunk, alphabet, lastChunkHandling === "strict"), written); + read = stringLength; + break; + } + if (!hasOwn(alphabet, chr)) { + throw new SyntaxError2("Unexpected character"); + } + var remainingBytes = maxLength - written; + if (remainingBytes === 1 && chunk.length === 2 || remainingBytes === 2 && chunk.length === 3) { + break; + } + chunk += chr; + if (chunk.length === 4) { + written = writeBytes(bytes, decodeBase64Chunk(chunk, alphabet, false), written); + chunk = ""; + read = index; + if (written === maxLength) { + break; + } + } + } + return { bytes, read, written }; + }; + }) + ), + /***/ + 9286: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var SetHelpers = __webpack_require__2(4402); + var iterate = __webpack_require__2(8469); + var Set2 = SetHelpers.Set; + var add = SetHelpers.add; + module2.exports = function(set) { + var result = new Set2(); + iterate(set, function(it) { + add(result, it); + }); + return result; + }; + }) + ), + /***/ + 9297: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var uncurryThis = __webpack_require__2(9504); + var toObject = __webpack_require__2(8981); + var hasOwnProperty = uncurryThis({}.hasOwnProperty); + module2.exports = Object.hasOwn || function hasOwn(it, key) { + return hasOwnProperty(toObject(it), key); + }; + }) + ), + /***/ + 9306: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var isCallable = __webpack_require__2(4901); + var tryToString = __webpack_require__2(6823); + var $TypeError = TypeError; + module2.exports = function(argument) { + if (isCallable(argument)) return argument; + throw new $TypeError(tryToString(argument) + " is not a function"); + }; + }) + ), + /***/ + 9314: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var call = __webpack_require__2(9565); + var anObject = __webpack_require__2(8551); + var getIteratorDirect = __webpack_require__2(1767); + var notANaN = __webpack_require__2(4149); + var toPositiveInteger = __webpack_require__2(9590); + var iteratorClose = __webpack_require__2(9539); + var createIteratorProxy = __webpack_require__2(9462); + var iteratorHelperThrowsOnInvalidIterator = __webpack_require__2(684); + var iteratorHelperWithoutClosingOnEarlyError = __webpack_require__2(4549); + var IS_PURE = __webpack_require__2(6395); + var DROP_WITHOUT_THROWING_ON_INVALID_ITERATOR = !IS_PURE && !iteratorHelperThrowsOnInvalidIterator("drop", 0); + var dropWithoutClosingOnEarlyError = !IS_PURE && !DROP_WITHOUT_THROWING_ON_INVALID_ITERATOR && iteratorHelperWithoutClosingOnEarlyError("drop", RangeError); + var FORCED = IS_PURE || DROP_WITHOUT_THROWING_ON_INVALID_ITERATOR || dropWithoutClosingOnEarlyError; + var IteratorProxy = createIteratorProxy(function() { + var iterator = this.iterator; + var next = this.next; + var result, done; + while (this.remaining) { + this.remaining--; + result = anObject(call(next, iterator)); + done = this.done = !!result.done; + if (done) return; + } + result = anObject(call(next, iterator)); + done = this.done = !!result.done; + if (!done) return result.value; + }); + $({ target: "Iterator", proto: true, real: true, forced: FORCED }, { + drop: function drop(limit) { + anObject(this); + var remaining; + try { + remaining = toPositiveInteger(notANaN(+limit)); + } catch (error) { + iteratorClose(this, "throw", error); + } + if (dropWithoutClosingOnEarlyError) return call(dropWithoutClosingOnEarlyError, this, remaining); + return new IteratorProxy(getIteratorDirect(this), { + remaining + }); + } + }); + }) + ), + /***/ + 9429: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var IS_NODE = __webpack_require__2(6193); + module2.exports = function(name) { + if (IS_NODE) { + try { + return globalThis2.process.getBuiltinModule(name); + } catch (error) { + } + try { + return Function('return require("' + name + '")')(); + } catch (error) { + } + } + }; + }) + ), + /***/ + 9432: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + __webpack_require__2(5213); + }) + ), + /***/ + 9433: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var defineProperty = Object.defineProperty; + module2.exports = function(key, value) { + try { + defineProperty(globalThis2, key, { value, configurable: true, writable: true }); + } catch (error) { + globalThis2[key] = value; + } + return value; + }; + }) + ), + /***/ + 9462: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var call = __webpack_require__2(9565); + var create = __webpack_require__2(2360); + var createNonEnumerableProperty = __webpack_require__2(6699); + var defineBuiltIns = __webpack_require__2(6279); + var wellKnownSymbol = __webpack_require__2(8227); + var InternalStateModule = __webpack_require__2(1181); + var getMethod = __webpack_require__2(5966); + var IteratorPrototype = __webpack_require__2(7657).IteratorPrototype; + var createIterResultObject = __webpack_require__2(2529); + var iteratorClose = __webpack_require__2(9539); + var iteratorCloseAll = __webpack_require__2(1385); + var TO_STRING_TAG = wellKnownSymbol("toStringTag"); + var ITERATOR_HELPER = "IteratorHelper"; + var WRAP_FOR_VALID_ITERATOR = "WrapForValidIterator"; + var NORMAL = "normal"; + var THROW = "throw"; + var setInternalState = InternalStateModule.set; + var createIteratorProxyPrototype = function(IS_ITERATOR) { + var getInternalState = InternalStateModule.getterFor(IS_ITERATOR ? WRAP_FOR_VALID_ITERATOR : ITERATOR_HELPER); + return defineBuiltIns(create(IteratorPrototype), { + next: function next() { + var state = getInternalState(this); + if (IS_ITERATOR) return state.nextHandler(); + if (state.done) return createIterResultObject(void 0, true); + try { + var result = state.nextHandler(); + return state.returnHandlerResult ? result : createIterResultObject(result, state.done); + } catch (error) { + state.done = true; + throw error; + } + }, + "return": function() { + var state = getInternalState(this); + var iterator = state.iterator; + state.done = true; + if (IS_ITERATOR) { + var returnMethod = getMethod(iterator, "return"); + return returnMethod ? call(returnMethod, iterator) : createIterResultObject(void 0, true); + } + if (state.inner) try { + iteratorClose(state.inner.iterator, NORMAL); + } catch (error) { + return iteratorClose(iterator, THROW, error); + } + if (state.openIters) try { + iteratorCloseAll(state.openIters, NORMAL); + } catch (error) { + return iteratorClose(iterator, THROW, error); + } + if (iterator) iteratorClose(iterator, NORMAL); + return createIterResultObject(void 0, true); + } + }); + }; + var WrapForValidIteratorPrototype = createIteratorProxyPrototype(true); + var IteratorHelperPrototype = createIteratorProxyPrototype(false); + createNonEnumerableProperty(IteratorHelperPrototype, TO_STRING_TAG, "Iterator Helper"); + module2.exports = function(nextHandler, IS_ITERATOR, RETURN_HANDLER_RESULT) { + var IteratorProxy = function Iterator2(record, state) { + if (state) { + state.iterator = record.iterator; + state.next = record.next; + } else state = record; + state.type = IS_ITERATOR ? WRAP_FOR_VALID_ITERATOR : ITERATOR_HELPER; + state.returnHandlerResult = !!RETURN_HANDLER_RESULT; + state.nextHandler = nextHandler; + state.counter = 0; + state.done = false; + setInternalState(this, state); + }; + IteratorProxy.prototype = IS_ITERATOR ? WrapForValidIteratorPrototype : IteratorHelperPrototype; + return IteratorProxy; + }; + }) + ), + /***/ + 9486: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var $ = __webpack_require__2(6518); + var globalThis2 = __webpack_require__2(4576); + var uncurryThis = __webpack_require__2(9504); + var anObjectOrUndefined = __webpack_require__2(3972); + var anUint8Array = __webpack_require__2(4154); + var notDetached = __webpack_require__2(5169); + var base64Map = __webpack_require__2(2804); + var getAlphabetOption = __webpack_require__2(944); + var base64Alphabet = base64Map.i2c; + var base64UrlAlphabet = base64Map.i2cUrl; + var charAt = uncurryThis("".charAt); + var Uint8Array2 = globalThis2.Uint8Array; + var INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS = !Uint8Array2 || !Uint8Array2.prototype.toBase64 || !(function() { + try { + var target = new Uint8Array2(); + target.toBase64(null); + } catch (error) { + return true; + } + })(); + if (Uint8Array2) $({ target: "Uint8Array", proto: true, forced: INCORRECT_BEHAVIOR_OR_DOESNT_EXISTS }, { + toBase64: function toBase64() { + var array = anUint8Array(this); + var options = arguments.length ? anObjectOrUndefined(arguments[0]) : void 0; + var alphabet = getAlphabetOption(options) === "base64" ? base64Alphabet : base64UrlAlphabet; + var omitPadding = !!options && !!options.omitPadding; + notDetached(this.buffer); + var result = ""; + var i = 0; + var length = array.length; + var triplet; + var at = function(shift) { + return charAt(alphabet, triplet >> 6 * shift & 63); + }; + for (; i + 2 < length; i += 3) { + triplet = (array[i] << 16) + (array[i + 1] << 8) + array[i + 2]; + result += at(3) + at(2) + at(1) + at(0); + } + if (i + 2 === length) { + triplet = (array[i] << 16) + (array[i + 1] << 8); + result += at(3) + at(2) + at(1) + (omitPadding ? "" : "="); + } else if (i + 1 === length) { + triplet = array[i] << 16; + result += at(3) + at(2) + (omitPadding ? "" : "=="); + } + return result; + } + }); + }) + ), + /***/ + 9504: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var NATIVE_BIND = __webpack_require__2(616); + var FunctionPrototype = Function.prototype; + var call = FunctionPrototype.call; + var uncurryThisWithBind = NATIVE_BIND && FunctionPrototype.bind.bind(call, call); + module2.exports = NATIVE_BIND ? uncurryThisWithBind : function(fn) { + return function() { + return call.apply(fn, arguments); + }; + }; + }) + ), + /***/ + 9519: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var globalThis2 = __webpack_require__2(4576); + var userAgent = __webpack_require__2(2839); + var process2 = globalThis2.process; + var Deno2 = globalThis2.Deno; + var versions = process2 && process2.versions || Deno2 && Deno2.version; + var v8 = versions && versions.v8; + var match, version2; + if (v8) { + match = v8.split("."); + version2 = match[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1]); + } + if (!version2 && userAgent) { + match = userAgent.match(/Edge\/(\d+)/); + if (!match || match[1] >= 74) { + match = userAgent.match(/Chrome\/(\d+)/); + if (match) version2 = +match[1]; + } + } + module2.exports = version2; + }) + ), + /***/ + 9539: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var call = __webpack_require__2(9565); + var anObject = __webpack_require__2(8551); + var getMethod = __webpack_require__2(5966); + module2.exports = function(iterator, kind, value) { + var innerResult, innerError; + anObject(iterator); + try { + innerResult = getMethod(iterator, "return"); + if (!innerResult) { + if (kind === "throw") throw value; + return value; + } + innerResult = call(innerResult, iterator); + } catch (error) { + innerError = true; + innerResult = error; + } + if (kind === "throw") throw value; + if (innerError) throw innerResult; + anObject(innerResult); + return value; + }; + }) + ), + /***/ + 9565: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var NATIVE_BIND = __webpack_require__2(616); + var call = Function.prototype.call; + module2.exports = NATIVE_BIND ? call.bind(call) : function() { + return call.apply(call, arguments); + }; + }) + ), + /***/ + 9577: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + var arrayWith = __webpack_require__2(9928); + var ArrayBufferViewCore = __webpack_require__2(4644); + var isBigIntArray = __webpack_require__2(1108); + var toIntegerOrInfinity = __webpack_require__2(1291); + var toBigInt = __webpack_require__2(5854); + var aTypedArray = ArrayBufferViewCore.aTypedArray; + var getTypedArrayConstructor = ArrayBufferViewCore.getTypedArrayConstructor; + var exportTypedArrayMethod = ArrayBufferViewCore.exportTypedArrayMethod; + var PROPER_ORDER = (function() { + try { + new Int8Array(1)["with"](2, { valueOf: function() { + throw 8; + } }); + } catch (error) { + return error === 8; + } + })(); + var THROW_ON_NEGATIVE_FRACTIONAL_INDEX = PROPER_ORDER && (function() { + try { + new Int8Array(1)["with"](-0.5, 1); + } catch (error) { + return true; + } + })(); + exportTypedArrayMethod("with", { "with": function(index, value) { + var O = aTypedArray(this); + var relativeIndex = toIntegerOrInfinity(index); + var actualValue = isBigIntArray(O) ? toBigInt(value) : +value; + return arrayWith(O, getTypedArrayConstructor(O), relativeIndex, actualValue); + } }["with"], !PROPER_ORDER || THROW_ON_NEGATIVE_FRACTIONAL_INDEX); + }) + ), + /***/ + 9590: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var toIntegerOrInfinity = __webpack_require__2(1291); + var $RangeError = RangeError; + module2.exports = function(it) { + var result = toIntegerOrInfinity(it); + if (result < 0) throw new $RangeError("The argument can't be less than 0"); + return result; + }; + }) + ), + /***/ + 9617: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var toIndexedObject = __webpack_require__2(5397); + var toAbsoluteIndex = __webpack_require__2(5610); + var lengthOfArrayLike = __webpack_require__2(6198); + var createMethod = function(IS_INCLUDES) { + return function($this, el, fromIndex) { + var O = toIndexedObject($this); + var length = lengthOfArrayLike(O); + if (length === 0) return !IS_INCLUDES && -1; + var index = toAbsoluteIndex(fromIndex, length); + var value; + if (IS_INCLUDES && el !== el) while (length > index) { + value = O[index++]; + if (value !== value) return true; + } + else for (; length > index; index++) { + if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0; + } + return !IS_INCLUDES && -1; + }; + }; + module2.exports = { + // `Array.prototype.includes` method + // https://tc39.es/ecma262/#sec-array.prototype.includes + includes: createMethod(true), + // `Array.prototype.indexOf` method + // https://tc39.es/ecma262/#sec-array.prototype.indexof + indexOf: createMethod(false) + }; + }) + ), + /***/ + 9631: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + __webpack_require__2(9486); + }) + ), + /***/ + 9797: ( + /***/ + ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__2) => { + __webpack_require__2(4226); + }) + ), + /***/ + 9835: ( + /***/ + ((module2) => { + module2.exports = function(METHOD_NAME) { + try { + var baseSet = /* @__PURE__ */ new Set(); + var setLike = { + size: 0, + has: function() { + return true; + }, + keys: function() { + return Object.defineProperty({}, "next", { + get: function() { + baseSet.clear(); + baseSet.add(4); + return function() { + return { done: true }; + }; + } + }); + } + }; + var result = baseSet[METHOD_NAME](setLike); + return result.size === 1 && result.values().next().value === 4; + } catch (error) { + return false; + } + }; + }) + ), + /***/ + 9928: ( + /***/ + ((module2, __unused_webpack_exports, __webpack_require__2) => { + var lengthOfArrayLike = __webpack_require__2(6198); + var toIntegerOrInfinity = __webpack_require__2(1291); + var $RangeError = RangeError; + module2.exports = function(O, C, index, value) { + var len = lengthOfArrayLike(O); + var relativeIndex = toIntegerOrInfinity(index); + var actualIndex = relativeIndex < 0 ? len + relativeIndex : relativeIndex; + if (actualIndex >= len || actualIndex < 0) throw new $RangeError("Incorrect index"); + var A = new C(len); + var k = 0; + for (; k < len; k++) A[k] = k === actualIndex ? value : O[k]; + return A; + }; + }) + ) + /******/ +}; +var __webpack_module_cache__ = {}; +function __webpack_require__(moduleId) { + var cachedModule = __webpack_module_cache__[moduleId]; + if (cachedModule !== void 0) { + return cachedModule.exports; + } + var module2 = __webpack_module_cache__[moduleId] = { + /******/ + // no module.id needed + /******/ + // no module.loaded needed + /******/ + exports: {} + /******/ + }; + __webpack_modules__[moduleId].call(module2.exports, module2, module2.exports, __webpack_require__); + return module2.exports; +} +(() => { + __webpack_require__.d = (exports, definition) => { + for (var key in definition) { + if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { + Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); + } + } + }; +})(); +(() => { + __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop); +})(); +__webpack_require__(4114); +__webpack_require__(6573); +__webpack_require__(8100); +__webpack_require__(7936); +__webpack_require__(8111); +__webpack_require__(8237); +__webpack_require__(1689); +__webpack_require__(9577); +__webpack_require__(4235); +__webpack_require__(9432); +__webpack_require__(1549); +__webpack_require__(9797); +__webpack_require__(9631); +__webpack_require__(5623); +__webpack_require__(4979); +__webpack_require__(5781); +const isNodeJS = typeof process === "object" && process + "" === "[object process]" && !process.versions.nw && !(process.versions.electron && process.type && process.type !== "browser"); +const FONT_IDENTITY_MATRIX = [1e-3, 0, 0, 1e-3, 0, 0]; +const LINE_FACTOR = 1.35; +const RenderingIntentFlag = { + ANY: 1, + DISPLAY: 2, + PRINT: 4, + ANNOTATIONS_FORMS: 16, + ANNOTATIONS_STORAGE: 32, + ANNOTATIONS_DISABLE: 64, + IS_EDITING: 128, + OPLIST: 256 +}; +const AnnotationMode = { + DISABLE: 0, + ENABLE: 1, + ENABLE_FORMS: 2, + ENABLE_STORAGE: 3 +}; +const AnnotationEditorPrefix = "pdfjs_internal_editor_"; +const AnnotationEditorType = { + DISABLE: -1, + NONE: 0, + FREETEXT: 3, + HIGHLIGHT: 9, + STAMP: 13, + INK: 15, + POPUP: 16, + SIGNATURE: 101, + COMMENT: 102 +}; +const AnnotationEditorParamsType = { + RESIZE: 1, + CREATE: 2, + FREETEXT_SIZE: 11, + FREETEXT_COLOR: 12, + FREETEXT_OPACITY: 13, + INK_COLOR: 21, + INK_THICKNESS: 22, + INK_OPACITY: 23, + HIGHLIGHT_COLOR: 31, + HIGHLIGHT_THICKNESS: 32, + HIGHLIGHT_FREE: 33, + HIGHLIGHT_SHOW_ALL: 34, + DRAW_STEP: 41 +}; +const PermissionFlag = { + PRINT: 4, + MODIFY_CONTENTS: 8, + COPY: 16, + MODIFY_ANNOTATIONS: 32, + FILL_INTERACTIVE_FORMS: 256, + COPY_FOR_ACCESSIBILITY: 512, + ASSEMBLE: 1024, + PRINT_HIGH_QUALITY: 2048 +}; +const TextRenderingMode = { + FILL: 0, + STROKE: 1, + FILL_STROKE: 2, + INVISIBLE: 3, + FILL_STROKE_MASK: 3, + ADD_TO_PATH_FLAG: 4 +}; +const util_ImageKind = { + GRAYSCALE_1BPP: 1, + RGB_24BPP: 2, + RGBA_32BPP: 3 +}; +const AnnotationType = { + TEXT: 1, + LINK: 2, + FREETEXT: 3, + LINE: 4, + SQUARE: 5, + CIRCLE: 6, + POLYGON: 7, + POLYLINE: 8, + HIGHLIGHT: 9, + UNDERLINE: 10, + SQUIGGLY: 11, + STRIKEOUT: 12, + STAMP: 13, + CARET: 14, + INK: 15, + POPUP: 16, + FILEATTACHMENT: 17, + SOUND: 18, + MOVIE: 19, + WIDGET: 20, + SCREEN: 21, + PRINTERMARK: 22, + TRAPNET: 23, + WATERMARK: 24, + THREED: 25, + REDACT: 26 +}; +const AnnotationBorderStyleType = { + SOLID: 1, + DASHED: 2, + BEVELED: 3, + INSET: 4, + UNDERLINE: 5 +}; +const VerbosityLevel = { + ERRORS: 0, + WARNINGS: 1, + INFOS: 5 +}; +const OPS = { + dependency: 1, + setLineWidth: 2, + setLineCap: 3, + setLineJoin: 4, + setMiterLimit: 5, + setDash: 6, + setRenderingIntent: 7, + setFlatness: 8, + setGState: 9, + save: 10, + restore: 11, + transform: 12, + moveTo: 13, + lineTo: 14, + curveTo: 15, + curveTo2: 16, + curveTo3: 17, + closePath: 18, + rectangle: 19, + stroke: 20, + closeStroke: 21, + fill: 22, + eoFill: 23, + fillStroke: 24, + eoFillStroke: 25, + closeFillStroke: 26, + closeEOFillStroke: 27, + endPath: 28, + clip: 29, + eoClip: 30, + beginText: 31, + endText: 32, + setCharSpacing: 33, + setWordSpacing: 34, + setHScale: 35, + setLeading: 36, + setFont: 37, + setTextRenderingMode: 38, + setTextRise: 39, + moveText: 40, + setLeadingMoveText: 41, + setTextMatrix: 42, + nextLine: 43, + showText: 44, + showSpacedText: 45, + nextLineShowText: 46, + nextLineSetSpacingShowText: 47, + setCharWidth: 48, + setCharWidthAndBounds: 49, + setStrokeColorSpace: 50, + setFillColorSpace: 51, + setStrokeColor: 52, + setStrokeColorN: 53, + setFillColor: 54, + setFillColorN: 55, + setStrokeGray: 56, + setFillGray: 57, + setStrokeRGBColor: 58, + setFillRGBColor: 59, + setStrokeCMYKColor: 60, + setFillCMYKColor: 61, + shadingFill: 62, + beginInlineImage: 63, + beginImageData: 64, + endInlineImage: 65, + paintXObject: 66, + markPoint: 67, + markPointProps: 68, + beginMarkedContent: 69, + beginMarkedContentProps: 70, + endMarkedContent: 71, + beginCompat: 72, + endCompat: 73, + paintFormXObjectBegin: 74, + paintFormXObjectEnd: 75, + beginGroup: 76, + endGroup: 77, + beginAnnotation: 80, + endAnnotation: 81, + paintImageMaskXObject: 83, + paintImageMaskXObjectGroup: 84, + paintImageXObject: 85, + paintInlineImageXObject: 86, + paintInlineImageXObjectGroup: 87, + paintImageXObjectRepeat: 88, + paintImageMaskXObjectRepeat: 89, + paintSolidColorImageMask: 90, + constructPath: 91, + setStrokeTransparent: 92, + setFillTransparent: 93, + rawFillPath: 94 +}; +const DrawOPS = { + moveTo: 0, + lineTo: 1, + curveTo: 2, + closePath: 3 +}; +const PasswordResponses = { + NEED_PASSWORD: 1, + INCORRECT_PASSWORD: 2 +}; +let verbosity = VerbosityLevel.WARNINGS; +function setVerbosityLevel(level) { + if (Number.isInteger(level)) { + verbosity = level; + } +} +function getVerbosityLevel() { + return verbosity; +} +function info(msg) { + if (verbosity >= VerbosityLevel.INFOS) { + console.info(`Info: ${msg}`); + } +} +function warn(msg) { + if (verbosity >= VerbosityLevel.WARNINGS) { + console.warn(`Warning: ${msg}`); + } +} +function unreachable(msg) { + throw new Error(msg); +} +function assert(cond, msg) { + if (!cond) { + unreachable(msg); + } +} +function _isValidProtocol(url) { + switch (url?.protocol) { + case "http:": + case "https:": + case "ftp:": + case "mailto:": + case "tel:": + return true; + default: + return false; + } +} +function createValidAbsoluteUrl(url, baseUrl = null, options = null) { + if (!url) { + return null; + } + if (options && typeof url === "string") { + if (options.addDefaultProtocol && url.startsWith("www.")) { + const dots = url.match(/\./g); + if (dots?.length >= 2) { + url = `http://${url}`; + } + } + if (options.tryConvertEncoding) { + try { + url = stringToUTF8String(url); + } catch { + } + } + } + const absoluteUrl = baseUrl ? URL.parse(url, baseUrl) : URL.parse(url); + return _isValidProtocol(absoluteUrl) ? absoluteUrl : null; +} +function updateUrlHash(url, hash, allowRel = false) { + const res = URL.parse(url); + if (res) { + res.hash = hash; + return res.href; + } + if (allowRel && createValidAbsoluteUrl(url, "http://example.com")) { + return url.split("#", 1)[0] + `${hash ? `#${hash}` : ""}`; + } + return ""; +} +function shadow(obj, prop, value, nonSerializable = false) { + Object.defineProperty(obj, prop, { + value, + enumerable: !nonSerializable, + configurable: true, + writable: false + }); + return value; +} +const BaseException = (function BaseExceptionClosure() { + function BaseException2(message, name) { + this.message = message; + this.name = name; + } + BaseException2.prototype = new Error(); + BaseException2.constructor = BaseException2; + return BaseException2; +})(); +class PasswordException extends BaseException { + constructor(msg, code) { + super(msg, "PasswordException"); + this.code = code; + } +} +class UnknownErrorException extends BaseException { + constructor(msg, details) { + super(msg, "UnknownErrorException"); + this.details = details; + } +} +class InvalidPDFException extends BaseException { + constructor(msg) { + super(msg, "InvalidPDFException"); + } +} +class ResponseException extends BaseException { + constructor(msg, status, missing) { + super(msg, "ResponseException"); + this.status = status; + this.missing = missing; + } +} +class FormatError extends BaseException { + constructor(msg) { + super(msg, "FormatError"); + } +} +class AbortException extends BaseException { + constructor(msg) { + super(msg, "AbortException"); + } +} +function bytesToString(bytes) { + if (typeof bytes !== "object" || bytes?.length === void 0) { + unreachable("Invalid argument for bytesToString"); + } + const length = bytes.length; + const MAX_ARGUMENT_COUNT = 8192; + if (length < MAX_ARGUMENT_COUNT) { + return String.fromCharCode.apply(null, bytes); + } + const strBuf = []; + for (let i = 0; i < length; i += MAX_ARGUMENT_COUNT) { + const chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length); + const chunk = bytes.subarray(i, chunkEnd); + strBuf.push(String.fromCharCode.apply(null, chunk)); + } + return strBuf.join(""); +} +function stringToBytes(str) { + if (typeof str !== "string") { + unreachable("Invalid argument for stringToBytes"); + } + const length = str.length; + const bytes = new Uint8Array(length); + for (let i = 0; i < length; ++i) { + bytes[i] = str.charCodeAt(i) & 255; + } + return bytes; +} +function string32(value) { + return String.fromCharCode(value >> 24 & 255, value >> 16 & 255, value >> 8 & 255, value & 255); +} +function isLittleEndian() { + const buffer8 = new Uint8Array(4); + buffer8[0] = 1; + const view32 = new Uint32Array(buffer8.buffer, 0, 1); + return view32[0] === 1; +} +function isEvalSupported() { + try { + new Function(""); + return true; + } catch { + return false; + } +} +class util_FeatureTest { + static get isLittleEndian() { + return shadow(this, "isLittleEndian", isLittleEndian()); + } + static get isEvalSupported() { + return shadow(this, "isEvalSupported", isEvalSupported()); + } + static get isOffscreenCanvasSupported() { + return shadow(this, "isOffscreenCanvasSupported", typeof OffscreenCanvas !== "undefined"); + } + static get isImageDecoderSupported() { + return shadow(this, "isImageDecoderSupported", typeof ImageDecoder !== "undefined"); + } + static get platform() { + const { + platform, + userAgent + } = navigator; + return shadow(this, "platform", { + isAndroid: userAgent.includes("Android"), + isLinux: platform.includes("Linux"), + isMac: platform.includes("Mac"), + isWindows: platform.includes("Win"), + isFirefox: userAgent.includes("Firefox") + }); + } + static get isCSSRoundSupported() { + return shadow(this, "isCSSRoundSupported", globalThis.CSS?.supports?.("width: round(1.5px, 1px)")); + } +} +const hexNumbers = Array.from(Array(256).keys(), (n) => n.toString(16).padStart(2, "0")); +class Util { + static makeHexColor(r, g, b) { + return `#${hexNumbers[r]}${hexNumbers[g]}${hexNumbers[b]}`; + } + static domMatrixToTransform(dm) { + return [dm.a, dm.b, dm.c, dm.d, dm.e, dm.f]; + } + static scaleMinMax(transform, minMax) { + let temp; + if (transform[0]) { + if (transform[0] < 0) { + temp = minMax[0]; + minMax[0] = minMax[2]; + minMax[2] = temp; + } + minMax[0] *= transform[0]; + minMax[2] *= transform[0]; + if (transform[3] < 0) { + temp = minMax[1]; + minMax[1] = minMax[3]; + minMax[3] = temp; + } + minMax[1] *= transform[3]; + minMax[3] *= transform[3]; + } else { + temp = minMax[0]; + minMax[0] = minMax[1]; + minMax[1] = temp; + temp = minMax[2]; + minMax[2] = minMax[3]; + minMax[3] = temp; + if (transform[1] < 0) { + temp = minMax[1]; + minMax[1] = minMax[3]; + minMax[3] = temp; + } + minMax[1] *= transform[1]; + minMax[3] *= transform[1]; + if (transform[2] < 0) { + temp = minMax[0]; + minMax[0] = minMax[2]; + minMax[2] = temp; + } + minMax[0] *= transform[2]; + minMax[2] *= transform[2]; + } + minMax[0] += transform[4]; + minMax[1] += transform[5]; + minMax[2] += transform[4]; + minMax[3] += transform[5]; + } + static transform(m1, m2) { + return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]]; + } + static multiplyByDOMMatrix(m, md) { + return [m[0] * md.a + m[2] * md.b, m[1] * md.a + m[3] * md.b, m[0] * md.c + m[2] * md.d, m[1] * md.c + m[3] * md.d, m[0] * md.e + m[2] * md.f + m[4], m[1] * md.e + m[3] * md.f + m[5]]; + } + static applyTransform(p, m, pos = 0) { + const p0 = p[pos]; + const p1 = p[pos + 1]; + p[pos] = p0 * m[0] + p1 * m[2] + m[4]; + p[pos + 1] = p0 * m[1] + p1 * m[3] + m[5]; + } + static applyTransformToBezier(p, transform, pos = 0) { + const m0 = transform[0]; + const m1 = transform[1]; + const m2 = transform[2]; + const m3 = transform[3]; + const m4 = transform[4]; + const m5 = transform[5]; + for (let i = 0; i < 6; i += 2) { + const pI = p[pos + i]; + const pI1 = p[pos + i + 1]; + p[pos + i] = pI * m0 + pI1 * m2 + m4; + p[pos + i + 1] = pI * m1 + pI1 * m3 + m5; + } + } + static applyInverseTransform(p, m) { + const p0 = p[0]; + const p1 = p[1]; + const d = m[0] * m[3] - m[1] * m[2]; + p[0] = (p0 * m[3] - p1 * m[2] + m[2] * m[5] - m[4] * m[3]) / d; + p[1] = (-p0 * m[1] + p1 * m[0] + m[4] * m[1] - m[5] * m[0]) / d; + } + static axialAlignedBoundingBox(rect, transform, output) { + const m0 = transform[0]; + const m1 = transform[1]; + const m2 = transform[2]; + const m3 = transform[3]; + const m4 = transform[4]; + const m5 = transform[5]; + const r0 = rect[0]; + const r1 = rect[1]; + const r2 = rect[2]; + const r3 = rect[3]; + let a0 = m0 * r0 + m4; + let a2 = a0; + let a1 = m0 * r2 + m4; + let a3 = a1; + let b0 = m3 * r1 + m5; + let b2 = b0; + let b1 = m3 * r3 + m5; + let b3 = b1; + if (m1 !== 0 || m2 !== 0) { + const m1r0 = m1 * r0; + const m1r2 = m1 * r2; + const m2r1 = m2 * r1; + const m2r3 = m2 * r3; + a0 += m2r1; + a3 += m2r1; + a1 += m2r3; + a2 += m2r3; + b0 += m1r0; + b3 += m1r0; + b1 += m1r2; + b2 += m1r2; + } + output[0] = Math.min(output[0], a0, a1, a2, a3); + output[1] = Math.min(output[1], b0, b1, b2, b3); + output[2] = Math.max(output[2], a0, a1, a2, a3); + output[3] = Math.max(output[3], b0, b1, b2, b3); + } + static inverseTransform(m) { + const d = m[0] * m[3] - m[1] * m[2]; + return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d]; + } + static singularValueDecompose2dScale(matrix, output) { + const m0 = matrix[0]; + const m1 = matrix[1]; + const m2 = matrix[2]; + const m3 = matrix[3]; + const a = m0 ** 2 + m1 ** 2; + const b = m0 * m2 + m1 * m3; + const c = m2 ** 2 + m3 ** 2; + const first = (a + c) / 2; + const second = Math.sqrt(first ** 2 - (a * c - b ** 2)); + output[0] = Math.sqrt(first + second || 1); + output[1] = Math.sqrt(first - second || 1); + } + static normalizeRect(rect) { + const r = rect.slice(0); + if (rect[0] > rect[2]) { + r[0] = rect[2]; + r[2] = rect[0]; + } + if (rect[1] > rect[3]) { + r[1] = rect[3]; + r[3] = rect[1]; + } + return r; + } + static intersect(rect1, rect2) { + const xLow = Math.max(Math.min(rect1[0], rect1[2]), Math.min(rect2[0], rect2[2])); + const xHigh = Math.min(Math.max(rect1[0], rect1[2]), Math.max(rect2[0], rect2[2])); + if (xLow > xHigh) { + return null; + } + const yLow = Math.max(Math.min(rect1[1], rect1[3]), Math.min(rect2[1], rect2[3])); + const yHigh = Math.min(Math.max(rect1[1], rect1[3]), Math.max(rect2[1], rect2[3])); + if (yLow > yHigh) { + return null; + } + return [xLow, yLow, xHigh, yHigh]; + } + static pointBoundingBox(x, y, minMax) { + minMax[0] = Math.min(minMax[0], x); + minMax[1] = Math.min(minMax[1], y); + minMax[2] = Math.max(minMax[2], x); + minMax[3] = Math.max(minMax[3], y); + } + static rectBoundingBox(x0, y0, x1, y1, minMax) { + minMax[0] = Math.min(minMax[0], x0, x1); + minMax[1] = Math.min(minMax[1], y0, y1); + minMax[2] = Math.max(minMax[2], x0, x1); + minMax[3] = Math.max(minMax[3], y0, y1); + } + static #getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, t, minMax) { + if (t <= 0 || t >= 1) { + return; + } + const mt = 1 - t; + const tt = t * t; + const ttt = tt * t; + const x = mt * (mt * (mt * x0 + 3 * t * x1) + 3 * tt * x2) + ttt * x3; + const y = mt * (mt * (mt * y0 + 3 * t * y1) + 3 * tt * y2) + ttt * y3; + minMax[0] = Math.min(minMax[0], x); + minMax[1] = Math.min(minMax[1], y); + minMax[2] = Math.max(minMax[2], x); + minMax[3] = Math.max(minMax[3], y); + } + static #getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, a, b, c, minMax) { + if (Math.abs(a) < 1e-12) { + if (Math.abs(b) >= 1e-12) { + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, -c / b, minMax); + } + return; + } + const delta = b ** 2 - 4 * c * a; + if (delta < 0) { + return; + } + const sqrtDelta = Math.sqrt(delta); + const a2 = 2 * a; + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b + sqrtDelta) / a2, minMax); + this.#getExtremumOnCurve(x0, x1, x2, x3, y0, y1, y2, y3, (-b - sqrtDelta) / a2, minMax); + } + static bezierBoundingBox(x0, y0, x1, y1, x2, y2, x3, y3, minMax) { + minMax[0] = Math.min(minMax[0], x0, x3); + minMax[1] = Math.min(minMax[1], y0, y3); + minMax[2] = Math.max(minMax[2], x0, x3); + minMax[3] = Math.max(minMax[3], y0, y3); + this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-x0 + 3 * (x1 - x2) + x3), 6 * (x0 - 2 * x1 + x2), 3 * (x1 - x0), minMax); + this.#getExtremum(x0, x1, x2, x3, y0, y1, y2, y3, 3 * (-y0 + 3 * (y1 - y2) + y3), 6 * (y0 - 2 * y1 + y2), 3 * (y1 - y0), minMax); + } +} +function stringToUTF8String(str) { + return decodeURIComponent(escape(str)); +} +let NormalizeRegex = null; +let NormalizationMap = null; +function normalizeUnicode(str) { + if (!NormalizeRegex) { + NormalizeRegex = /([\u00a0\u00b5\u037e\u0eb3\u2000-\u200a\u202f\u2126\ufb00-\ufb04\ufb06\ufb20-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufba1\ufba4-\ufba9\ufbae-\ufbb1\ufbd3-\ufbdc\ufbde-\ufbe7\ufbea-\ufbf8\ufbfc-\ufbfd\ufc00-\ufc5d\ufc64-\ufcf1\ufcf5-\ufd3d\ufd88\ufdf4\ufdfa-\ufdfb\ufe71\ufe77\ufe79\ufe7b\ufe7d]+)|(\ufb05+)/gu; + NormalizationMap = /* @__PURE__ */ new Map([["ſt", "ſt"]]); + } + return str.replaceAll(NormalizeRegex, (_, p1, p2) => p1 ? p1.normalize("NFKC") : NormalizationMap.get(p2)); +} +function getUuid() { + if (typeof crypto.randomUUID === "function") { + return crypto.randomUUID(); + } + const buf = new Uint8Array(32); + crypto.getRandomValues(buf); + return bytesToString(buf); +} +const AnnotationPrefix = "pdfjs_internal_id_"; +function _isValidExplicitDest(validRef, validName, dest) { + if (!Array.isArray(dest) || dest.length < 2) { + return false; + } + const [page, zoom, ...args] = dest; + if (!validRef(page) && !Number.isInteger(page)) { + return false; + } + if (!validName(zoom)) { + return false; + } + const argsLen = args.length; + let allowNull = true; + switch (zoom.name) { + case "XYZ": + if (argsLen < 2 || argsLen > 3) { + return false; + } + break; + case "Fit": + case "FitB": + return argsLen === 0; + case "FitH": + case "FitBH": + case "FitV": + case "FitBV": + if (argsLen > 1) { + return false; + } + break; + case "FitR": + if (argsLen !== 4) { + return false; + } + allowNull = false; + break; + default: + return false; + } + for (const arg of args) { + if (typeof arg === "number" || allowNull && arg === null) { + continue; + } + return false; + } + return true; +} +function MathClamp(v, min, max) { + return Math.min(Math.max(v, min), max); +} +function toBase64Util(arr) { + if (Uint8Array.prototype.toBase64) { + return arr.toBase64(); + } + return btoa(bytesToString(arr)); +} +function fromBase64Util(str) { + if (Uint8Array.fromBase64) { + return Uint8Array.fromBase64(str); + } + return stringToBytes(atob(str)); +} +if (typeof Math.sumPrecise !== "function") { + Math.sumPrecise = function(numbers) { + return numbers.reduce((a, b) => a + b, 0); + }; +} +if (typeof AbortSignal.any !== "function") { + AbortSignal.any = function(iterable) { + const ac = new AbortController(); + const { + signal + } = ac; + for (const s of iterable) { + if (s.aborted) { + ac.abort(s.reason); + return signal; + } + } + for (const s of iterable) { + s.addEventListener("abort", () => { + ac.abort(s.reason); + }, { + signal + }); + } + return signal; + }; +} +__webpack_require__(1701); +__webpack_require__(4603); +__webpack_require__(7566); +__webpack_require__(8721); +class XfaText { + static textContent(xfa) { + const items = []; + const output = { + items, + styles: /* @__PURE__ */ Object.create(null) + }; + function walk(node) { + if (!node) { + return; + } + let str = null; + const name = node.name; + if (name === "#text") { + str = node.value; + } else if (!XfaText.shouldBuildText(name)) { + return; + } else if (node?.attributes?.textContent) { + str = node.attributes.textContent; + } else if (node.value) { + str = node.value; + } + if (str !== null) { + items.push({ + str + }); + } + if (!node.children) { + return; + } + for (const child of node.children) { + walk(child); + } + } + walk(xfa); + return output; + } + static shouldBuildText(name) { + return !(name === "textarea" || name === "input" || name === "option" || name === "select"); + } +} +class XfaLayer { + static setupStorage(html, id, element, storage, intent) { + const storedData = storage.getValue(id, { + value: null + }); + switch (element.name) { + case "textarea": + if (storedData.value !== null) { + html.textContent = storedData.value; + } + if (intent === "print") { + break; + } + html.addEventListener("input", (event) => { + storage.setValue(id, { + value: event.target.value + }); + }); + break; + case "input": + if (element.attributes.type === "radio" || element.attributes.type === "checkbox") { + if (storedData.value === element.attributes.xfaOn) { + html.setAttribute("checked", true); + } else if (storedData.value === element.attributes.xfaOff) { + html.removeAttribute("checked"); + } + if (intent === "print") { + break; + } + html.addEventListener("change", (event) => { + storage.setValue(id, { + value: event.target.checked ? event.target.getAttribute("xfaOn") : event.target.getAttribute("xfaOff") + }); + }); + } else { + if (storedData.value !== null) { + html.setAttribute("value", storedData.value); + } + if (intent === "print") { + break; + } + html.addEventListener("input", (event) => { + storage.setValue(id, { + value: event.target.value + }); + }); + } + break; + case "select": + if (storedData.value !== null) { + html.setAttribute("value", storedData.value); + for (const option of element.children) { + if (option.attributes.value === storedData.value) { + option.attributes.selected = true; + } else if (option.attributes.hasOwnProperty("selected")) { + delete option.attributes.selected; + } + } + } + html.addEventListener("input", (event) => { + const options = event.target.options; + const value = options.selectedIndex === -1 ? "" : options[options.selectedIndex].value; + storage.setValue(id, { + value + }); + }); + break; + } + } + static setAttributes({ + html, + element, + storage = null, + intent, + linkService + }) { + const { + attributes + } = element; + const isHTMLAnchorElement = html instanceof HTMLAnchorElement; + if (attributes.type === "radio") { + attributes.name = `${attributes.name}-${intent}`; + } + for (const [key, value] of Object.entries(attributes)) { + if (value === null || value === void 0) { + continue; + } + switch (key) { + case "class": + if (value.length) { + html.setAttribute(key, value.join(" ")); + } + break; + case "dataId": + break; + case "id": + html.setAttribute("data-element-id", value); + break; + case "style": + Object.assign(html.style, value); + break; + case "textContent": + html.textContent = value; + break; + default: + if (!isHTMLAnchorElement || key !== "href" && key !== "newWindow") { + html.setAttribute(key, value); + } + } + } + if (isHTMLAnchorElement) { + linkService.addLinkAttributes(html, attributes.href, attributes.newWindow); + } + if (storage && attributes.dataId) { + this.setupStorage(html, attributes.dataId, element, storage); + } + } + static render(parameters) { + const storage = parameters.annotationStorage; + const linkService = parameters.linkService; + const root = parameters.xfaHtml; + const intent = parameters.intent || "display"; + const rootHtml = document.createElement(root.name); + if (root.attributes) { + this.setAttributes({ + html: rootHtml, + element: root, + intent, + linkService + }); + } + const isNotForRichText = intent !== "richText"; + const rootDiv = parameters.div; + rootDiv.append(rootHtml); + if (parameters.viewport) { + const transform = `matrix(${parameters.viewport.transform.join(",")})`; + rootDiv.style.transform = transform; + } + if (isNotForRichText) { + rootDiv.setAttribute("class", "xfaLayer xfaFont"); + } + const textDivs = []; + if (root.children.length === 0) { + if (root.value) { + const node = document.createTextNode(root.value); + rootHtml.append(node); + if (isNotForRichText && XfaText.shouldBuildText(root.name)) { + textDivs.push(node); + } + } + return { + textDivs + }; + } + const stack = [[root, -1, rootHtml]]; + while (stack.length > 0) { + const [parent, i, html] = stack.at(-1); + if (i + 1 === parent.children.length) { + stack.pop(); + continue; + } + const child = parent.children[++stack.at(-1)[1]]; + if (child === null) { + continue; + } + const { + name + } = child; + if (name === "#text") { + const node = document.createTextNode(child.value); + textDivs.push(node); + html.append(node); + continue; + } + const childHtml = child?.attributes?.xmlns ? document.createElementNS(child.attributes.xmlns, name) : document.createElement(name); + html.append(childHtml); + if (child.attributes) { + this.setAttributes({ + html: childHtml, + element: child, + storage, + intent, + linkService + }); + } + if (child.children?.length > 0) { + stack.push([child, -1, childHtml]); + } else if (child.value) { + const node = document.createTextNode(child.value); + if (isNotForRichText && XfaText.shouldBuildText(name)) { + textDivs.push(node); + } + childHtml.append(node); + } + } + for (const el of rootDiv.querySelectorAll(".xfaNonInteractive input, .xfaNonInteractive textarea")) { + el.setAttribute("readOnly", true); + } + return { + textDivs + }; + } + static update(parameters) { + const transform = `matrix(${parameters.viewport.transform.join(",")})`; + parameters.div.style.transform = transform; + parameters.div.hidden = false; + } +} +const SVG_NS = "http://www.w3.org/2000/svg"; +class PixelsPerInch { + static CSS = 96; + static PDF = 72; + static PDF_TO_CSS_UNITS = this.CSS / this.PDF; +} +async function fetchData(url, type = "text") { + if (isValidFetchUrl(url, document.baseURI)) { + const response = await fetch(url); + if (!response.ok) { + throw new Error(response.statusText); + } + switch (type) { + case "arraybuffer": + return response.arrayBuffer(); + case "blob": + return response.blob(); + case "json": + return response.json(); + } + return response.text(); + } + return new Promise((resolve, reject) => { + const request = new XMLHttpRequest(); + request.open("GET", url, true); + request.responseType = type; + request.onreadystatechange = () => { + if (request.readyState !== XMLHttpRequest.DONE) { + return; + } + if (request.status === 200 || request.status === 0) { + switch (type) { + case "arraybuffer": + case "blob": + case "json": + resolve(request.response); + return; + } + resolve(request.responseText); + return; + } + reject(new Error(request.statusText)); + }; + request.send(null); + }); +} +class PageViewport { + constructor({ + viewBox, + userUnit, + scale, + rotation, + offsetX = 0, + offsetY = 0, + dontFlip = false + }) { + this.viewBox = viewBox; + this.userUnit = userUnit; + this.scale = scale; + this.rotation = rotation; + this.offsetX = offsetX; + this.offsetY = offsetY; + scale *= userUnit; + const centerX = (viewBox[2] + viewBox[0]) / 2; + const centerY = (viewBox[3] + viewBox[1]) / 2; + let rotateA, rotateB, rotateC, rotateD; + rotation %= 360; + if (rotation < 0) { + rotation += 360; + } + switch (rotation) { + case 180: + rotateA = -1; + rotateB = 0; + rotateC = 0; + rotateD = 1; + break; + case 90: + rotateA = 0; + rotateB = 1; + rotateC = 1; + rotateD = 0; + break; + case 270: + rotateA = 0; + rotateB = -1; + rotateC = -1; + rotateD = 0; + break; + case 0: + rotateA = 1; + rotateB = 0; + rotateC = 0; + rotateD = -1; + break; + default: + throw new Error("PageViewport: Invalid rotation, must be a multiple of 90 degrees."); + } + if (dontFlip) { + rotateC = -rotateC; + rotateD = -rotateD; + } + let offsetCanvasX, offsetCanvasY; + let width, height; + if (rotateA === 0) { + offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX; + offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY; + width = (viewBox[3] - viewBox[1]) * scale; + height = (viewBox[2] - viewBox[0]) * scale; + } else { + offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX; + offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY; + width = (viewBox[2] - viewBox[0]) * scale; + height = (viewBox[3] - viewBox[1]) * scale; + } + this.transform = [rotateA * scale, rotateB * scale, rotateC * scale, rotateD * scale, offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY]; + this.width = width; + this.height = height; + } + get rawDims() { + const dims = this.viewBox; + return shadow(this, "rawDims", { + pageWidth: dims[2] - dims[0], + pageHeight: dims[3] - dims[1], + pageX: dims[0], + pageY: dims[1] + }); + } + clone({ + scale = this.scale, + rotation = this.rotation, + offsetX = this.offsetX, + offsetY = this.offsetY, + dontFlip = false + } = {}) { + return new PageViewport({ + viewBox: this.viewBox.slice(), + userUnit: this.userUnit, + scale, + rotation, + offsetX, + offsetY, + dontFlip + }); + } + convertToViewportPoint(x, y) { + const p = [x, y]; + Util.applyTransform(p, this.transform); + return p; + } + convertToViewportRectangle(rect) { + const topLeft = [rect[0], rect[1]]; + Util.applyTransform(topLeft, this.transform); + const bottomRight = [rect[2], rect[3]]; + Util.applyTransform(bottomRight, this.transform); + return [topLeft[0], topLeft[1], bottomRight[0], bottomRight[1]]; + } + convertToPdfPoint(x, y) { + const p = [x, y]; + Util.applyInverseTransform(p, this.transform); + return p; + } +} +class RenderingCancelledException extends BaseException { + constructor(msg, extraDelay = 0) { + super(msg, "RenderingCancelledException"); + this.extraDelay = extraDelay; + } +} +function isDataScheme(url) { + const ii = url.length; + let i = 0; + while (i < ii && url[i].trim() === "") { + i++; + } + return url.substring(i, i + 5).toLowerCase() === "data:"; +} +function isPdfFile(filename) { + return typeof filename === "string" && /\.pdf$/i.test(filename); +} +function getFilenameFromUrl(url) { + [url] = url.split(/[#?]/, 1); + return url.substring(url.lastIndexOf("/") + 1); +} +function getPdfFilenameFromUrl(url, defaultFilename = "document.pdf") { + if (typeof url !== "string") { + return defaultFilename; + } + if (isDataScheme(url)) { + warn('getPdfFilenameFromUrl: ignore "data:"-URL for performance reasons.'); + return defaultFilename; + } + const getURL = (urlString) => { + try { + return new URL(urlString); + } catch { + try { + return new URL(decodeURIComponent(urlString)); + } catch { + try { + return new URL(urlString, "https://foo.bar"); + } catch { + try { + return new URL(decodeURIComponent(urlString), "https://foo.bar"); + } catch { + return null; + } + } + } + } + }; + const newURL = getURL(url); + if (!newURL) { + return defaultFilename; + } + const decode = (name) => { + try { + let decoded = decodeURIComponent(name); + if (decoded.includes("/")) { + decoded = decoded.split("/").at(-1); + if (decoded.test(/^\.pdf$/i)) { + return decoded; + } + return name; + } + return decoded; + } catch { + return name; + } + }; + const pdfRegex = /\.pdf$/i; + const filename = newURL.pathname.split("/").at(-1); + if (pdfRegex.test(filename)) { + return decode(filename); + } + if (newURL.searchParams.size > 0) { + const values = Array.from(newURL.searchParams.values()).reverse(); + for (const value of values) { + if (pdfRegex.test(value)) { + return decode(value); + } + } + const keys = Array.from(newURL.searchParams.keys()).reverse(); + for (const key of keys) { + if (pdfRegex.test(key)) { + return decode(key); + } + } + } + if (newURL.hash) { + const reFilename = /[^/?#=]+\.pdf\b(?!.*\.pdf\b)/i; + const hashFilename = reFilename.exec(newURL.hash); + if (hashFilename) { + return decode(hashFilename[0]); + } + } + return defaultFilename; +} +class StatTimer { + started = /* @__PURE__ */ Object.create(null); + times = []; + time(name) { + if (name in this.started) { + warn(`Timer is already running for ${name}`); + } + this.started[name] = Date.now(); + } + timeEnd(name) { + if (!(name in this.started)) { + warn(`Timer has not been started for ${name}`); + } + this.times.push({ + name, + start: this.started[name], + end: Date.now() + }); + delete this.started[name]; + } + toString() { + const outBuf = []; + let longest = 0; + for (const { + name + } of this.times) { + longest = Math.max(name.length, longest); + } + for (const { + name, + start, + end + } of this.times) { + outBuf.push(`${name.padEnd(longest)} ${end - start}ms +`); + } + return outBuf.join(""); + } +} +function isValidFetchUrl(url, baseUrl) { + const res = baseUrl ? URL.parse(url, baseUrl) : URL.parse(url); + return res?.protocol === "http:" || res?.protocol === "https:"; +} +function noContextMenu(e) { + e.preventDefault(); +} +function stopEvent(e) { + e.preventDefault(); + e.stopPropagation(); +} +function deprecated(details) { + console.log("Deprecated API usage: " + details); +} +class PDFDateString { + static #regex; + static toDateObject(input) { + if (input instanceof Date) { + return input; + } + if (!input || typeof input !== "string") { + return null; + } + this.#regex ||= new RegExp("^D:(\\d{4})(\\d{2})?(\\d{2})?(\\d{2})?(\\d{2})?(\\d{2})?([Z|+|-])?(\\d{2})?'?(\\d{2})?'?"); + const matches = this.#regex.exec(input); + if (!matches) { + return null; + } + const year = parseInt(matches[1], 10); + let month = parseInt(matches[2], 10); + month = month >= 1 && month <= 12 ? month - 1 : 0; + let day = parseInt(matches[3], 10); + day = day >= 1 && day <= 31 ? day : 1; + let hour = parseInt(matches[4], 10); + hour = hour >= 0 && hour <= 23 ? hour : 0; + let minute = parseInt(matches[5], 10); + minute = minute >= 0 && minute <= 59 ? minute : 0; + let second = parseInt(matches[6], 10); + second = second >= 0 && second <= 59 ? second : 0; + const universalTimeRelation = matches[7] || "Z"; + let offsetHour = parseInt(matches[8], 10); + offsetHour = offsetHour >= 0 && offsetHour <= 23 ? offsetHour : 0; + let offsetMinute = parseInt(matches[9], 10) || 0; + offsetMinute = offsetMinute >= 0 && offsetMinute <= 59 ? offsetMinute : 0; + if (universalTimeRelation === "-") { + hour += offsetHour; + minute += offsetMinute; + } else if (universalTimeRelation === "+") { + hour -= offsetHour; + minute -= offsetMinute; + } + return new Date(Date.UTC(year, month, day, hour, minute, second)); + } +} +function getXfaPageViewport(xfaPage, { + scale = 1, + rotation = 0 +}) { + const { + width, + height + } = xfaPage.attributes.style; + const viewBox = [0, 0, parseInt(width), parseInt(height)]; + return new PageViewport({ + viewBox, + userUnit: 1, + scale, + rotation + }); +} +function getRGB(color) { + if (color.startsWith("#")) { + const colorRGB = parseInt(color.slice(1), 16); + return [(colorRGB & 16711680) >> 16, (colorRGB & 65280) >> 8, colorRGB & 255]; + } + if (color.startsWith("rgb(")) { + return color.slice(4, -1).split(",").map((x) => parseInt(x)); + } + if (color.startsWith("rgba(")) { + return color.slice(5, -1).split(",").map((x) => parseInt(x)).slice(0, 3); + } + warn(`Not a valid color format: "${color}"`); + return [0, 0, 0]; +} +function getColorValues(colors) { + const span = document.createElement("span"); + span.style.visibility = "hidden"; + span.style.colorScheme = "only light"; + document.body.append(span); + for (const name of colors.keys()) { + span.style.color = name; + const computedColor = window.getComputedStyle(span).color; + colors.set(name, getRGB(computedColor)); + } + span.remove(); +} +function getCurrentTransform(ctx) { + const { + a, + b, + c, + d, + e, + f + } = ctx.getTransform(); + return [a, b, c, d, e, f]; +} +function getCurrentTransformInverse(ctx) { + const { + a, + b, + c, + d, + e, + f + } = ctx.getTransform().invertSelf(); + return [a, b, c, d, e, f]; +} +function setLayerDimensions(div, viewport, mustFlip = false, mustRotate = true) { + if (viewport instanceof PageViewport) { + const { + pageWidth, + pageHeight + } = viewport.rawDims; + const { + style + } = div; + const useRound = util_FeatureTest.isCSSRoundSupported; + const w = `var(--total-scale-factor) * ${pageWidth}px`, h = `var(--total-scale-factor) * ${pageHeight}px`; + const widthStr = useRound ? `round(down, ${w}, var(--scale-round-x))` : `calc(${w})`, heightStr = useRound ? `round(down, ${h}, var(--scale-round-y))` : `calc(${h})`; + if (!mustFlip || viewport.rotation % 180 === 0) { + style.width = widthStr; + style.height = heightStr; + } else { + style.width = heightStr; + style.height = widthStr; + } + } + if (mustRotate) { + div.setAttribute("data-main-rotation", viewport.rotation); + } +} +class OutputScale { + constructor() { + const { + pixelRatio + } = OutputScale; + this.sx = pixelRatio; + this.sy = pixelRatio; + } + get scaled() { + return this.sx !== 1 || this.sy !== 1; + } + get symmetric() { + return this.sx === this.sy; + } + limitCanvas(width, height, maxPixels, maxDim, capAreaFactor = -1) { + let maxAreaScale = Infinity, maxWidthScale = Infinity, maxHeightScale = Infinity; + maxPixels = OutputScale.capPixels(maxPixels, capAreaFactor); + if (maxPixels > 0) { + maxAreaScale = Math.sqrt(maxPixels / (width * height)); + } + if (maxDim !== -1) { + maxWidthScale = maxDim / width; + maxHeightScale = maxDim / height; + } + const maxScale = Math.min(maxAreaScale, maxWidthScale, maxHeightScale); + if (this.sx > maxScale || this.sy > maxScale) { + this.sx = maxScale; + this.sy = maxScale; + return true; + } + return false; + } + static get pixelRatio() { + return globalThis.devicePixelRatio || 1; + } + static capPixels(maxPixels, capAreaFactor) { + if (capAreaFactor >= 0) { + const winPixels = Math.ceil(window.screen.availWidth * window.screen.availHeight * this.pixelRatio ** 2 * (1 + capAreaFactor / 100)); + return maxPixels > 0 ? Math.min(maxPixels, winPixels) : winPixels; + } + return maxPixels; + } +} +const SupportedImageMimeTypes = ["image/apng", "image/avif", "image/bmp", "image/gif", "image/jpeg", "image/png", "image/svg+xml", "image/webp", "image/x-icon"]; +class ColorScheme { + static get isDarkMode() { + return shadow(this, "isDarkMode", !!window?.matchMedia?.("(prefers-color-scheme: dark)").matches); + } +} +class CSSConstants { + static get commentForegroundColor() { + const element = document.createElement("span"); + element.classList.add("comment", "sidebar"); + const { + style + } = element; + style.width = style.height = "0"; + style.display = "none"; + style.color = "var(--comment-fg-color)"; + document.body.append(element); + const { + color + } = window.getComputedStyle(element); + element.remove(); + return shadow(this, "commentForegroundColor", getRGB(color)); + } +} +function applyOpacity(r, g, b, opacity) { + opacity = Math.min(Math.max(opacity ?? 1, 0), 1); + const white = 255 * (1 - opacity); + r = Math.round(r * opacity + white); + g = Math.round(g * opacity + white); + b = Math.round(b * opacity + white); + return [r, g, b]; +} +function RGBToHSL(rgb, output) { + const r = rgb[0] / 255; + const g = rgb[1] / 255; + const b = rgb[2] / 255; + const max = Math.max(r, g, b); + const min = Math.min(r, g, b); + const l = (max + min) / 2; + if (max === min) { + output[0] = output[1] = 0; + } else { + const d = max - min; + output[1] = l < 0.5 ? d / (max + min) : d / (2 - max - min); + switch (max) { + case r: + output[0] = ((g - b) / d + (g < b ? 6 : 0)) * 60; + break; + case g: + output[0] = ((b - r) / d + 2) * 60; + break; + case b: + output[0] = ((r - g) / d + 4) * 60; + break; + } + } + output[2] = l; +} +function HSLToRGB(hsl, output) { + const h = hsl[0]; + const s = hsl[1]; + const l = hsl[2]; + const c = (1 - Math.abs(2 * l - 1)) * s; + const x = c * (1 - Math.abs(h / 60 % 2 - 1)); + const m = l - c / 2; + switch (Math.floor(h / 60)) { + case 0: + output[0] = c + m; + output[1] = x + m; + output[2] = m; + break; + case 1: + output[0] = x + m; + output[1] = c + m; + output[2] = m; + break; + case 2: + output[0] = m; + output[1] = c + m; + output[2] = x + m; + break; + case 3: + output[0] = m; + output[1] = x + m; + output[2] = c + m; + break; + case 4: + output[0] = x + m; + output[1] = m; + output[2] = c + m; + break; + case 5: + case 6: + output[0] = c + m; + output[1] = m; + output[2] = x + m; + break; + } +} +function computeLuminance(x) { + return x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4; +} +function contrastRatio(hsl1, hsl2, output) { + HSLToRGB(hsl1, output); + output.map(computeLuminance); + const lum1 = 0.2126 * output[0] + 0.7152 * output[1] + 0.0722 * output[2]; + HSLToRGB(hsl2, output); + output.map(computeLuminance); + const lum2 = 0.2126 * output[0] + 0.7152 * output[1] + 0.0722 * output[2]; + return lum1 > lum2 ? (lum1 + 0.05) / (lum2 + 0.05) : (lum2 + 0.05) / (lum1 + 0.05); +} +const contrastCache = /* @__PURE__ */ new Map(); +function findContrastColor(baseColor, fixedColor) { + const key = baseColor[0] + baseColor[1] * 256 + baseColor[2] * 65536 + fixedColor[0] * 16777216 + fixedColor[1] * 4294967296 + fixedColor[2] * 1099511627776; + let cachedValue = contrastCache.get(key); + if (cachedValue) { + return cachedValue; + } + const array = new Float32Array(9); + const output = array.subarray(0, 3); + const baseHSL = array.subarray(3, 6); + RGBToHSL(baseColor, baseHSL); + const fixedHSL = array.subarray(6, 9); + RGBToHSL(fixedColor, fixedHSL); + const isFixedColorDark = fixedHSL[2] < 0.5; + const minContrast = isFixedColorDark ? 12 : 4.5; + baseHSL[2] = isFixedColorDark ? Math.sqrt(baseHSL[2]) : 1 - Math.sqrt(1 - baseHSL[2]); + if (contrastRatio(baseHSL, fixedHSL, output) < minContrast) { + let start, end; + if (isFixedColorDark) { + start = baseHSL[2]; + end = 1; + } else { + start = 0; + end = baseHSL[2]; + } + const PRECISION = 5e-3; + while (end - start > PRECISION) { + const mid = baseHSL[2] = (start + end) / 2; + if (isFixedColorDark === contrastRatio(baseHSL, fixedHSL, output) < minContrast) { + start = mid; + } else { + end = mid; + } + } + baseHSL[2] = isFixedColorDark ? end : start; + } + HSLToRGB(baseHSL, output); + cachedValue = Util.makeHexColor(Math.round(output[0] * 255), Math.round(output[1] * 255), Math.round(output[2] * 255)); + contrastCache.set(key, cachedValue); + return cachedValue; +} +function renderRichText({ + html, + dir, + className +}, container) { + const fragment = document.createDocumentFragment(); + if (typeof html === "string") { + const p = document.createElement("p"); + p.dir = dir || "auto"; + const lines = html.split(/(?:\r\n?|\n)/); + for (let i = 0, ii = lines.length; i < ii; ++i) { + const line = lines[i]; + p.append(document.createTextNode(line)); + if (i < ii - 1) { + p.append(document.createElement("br")); + } + } + fragment.append(p); + } else { + XfaLayer.render({ + xfaHtml: html, + div: fragment, + intent: "richText" + }); + } + fragment.firstChild.classList.add("richText", className); + container.append(fragment); +} +__webpack_require__(4972); +__webpack_require__(4628); +__webpack_require__(7642); +__webpack_require__(8004); +__webpack_require__(3853); +__webpack_require__(5876); +__webpack_require__(2475); +__webpack_require__(5024); +__webpack_require__(1698); +__webpack_require__(9314); +__webpack_require__(1148); +__webpack_require__(3579); +__webpack_require__(8335); +class EditorToolbar { + #toolbar = null; + #colorPicker = null; + #editor; + #buttons = null; + #altText = null; + #comment = null; + #commentButtonDivider = null; + #signatureDescriptionButton = null; + static #l10nRemove = null; + constructor(editor) { + this.#editor = editor; + EditorToolbar.#l10nRemove ||= Object.freeze({ + freetext: "pdfjs-editor-remove-freetext-button", + highlight: "pdfjs-editor-remove-highlight-button", + ink: "pdfjs-editor-remove-ink-button", + stamp: "pdfjs-editor-remove-stamp-button", + signature: "pdfjs-editor-remove-signature-button" + }); + } + render() { + const editToolbar = this.#toolbar = document.createElement("div"); + editToolbar.classList.add("editToolbar", "hidden"); + editToolbar.setAttribute("role", "toolbar"); + const signal = this.#editor._uiManager._signal; + if (signal instanceof AbortSignal && !signal.aborted) { + editToolbar.addEventListener("contextmenu", noContextMenu, { + signal + }); + editToolbar.addEventListener("pointerdown", EditorToolbar.#pointerDown, { + signal + }); + } + const buttons = this.#buttons = document.createElement("div"); + buttons.className = "buttons"; + editToolbar.append(buttons); + const position = this.#editor.toolbarPosition; + if (position) { + const { + style + } = editToolbar; + const x = this.#editor._uiManager.direction === "ltr" ? 1 - position[0] : position[0]; + style.insetInlineEnd = `${100 * x}%`; + style.top = `calc(${100 * position[1]}% + var(--editor-toolbar-vert-offset))`; + } + return editToolbar; + } + get div() { + return this.#toolbar; + } + static #pointerDown(e) { + e.stopPropagation(); + } + #focusIn(e) { + this.#editor._focusEventsAllowed = false; + stopEvent(e); + } + #focusOut(e) { + this.#editor._focusEventsAllowed = true; + stopEvent(e); + } + #addListenersToElement(element) { + const signal = this.#editor._uiManager._signal; + if (!(signal instanceof AbortSignal) || signal.aborted) { + return false; + } + element.addEventListener("focusin", this.#focusIn.bind(this), { + capture: true, + signal + }); + element.addEventListener("focusout", this.#focusOut.bind(this), { + capture: true, + signal + }); + element.addEventListener("contextmenu", noContextMenu, { + signal + }); + return true; + } + hide() { + this.#toolbar.classList.add("hidden"); + this.#colorPicker?.hideDropdown(); + } + show() { + this.#toolbar.classList.remove("hidden"); + this.#altText?.shown(); + this.#comment?.shown(); + } + addDeleteButton() { + const { + editorType, + _uiManager + } = this.#editor; + const button = document.createElement("button"); + button.classList.add("basic", "deleteButton"); + button.tabIndex = 0; + button.setAttribute("data-l10n-id", EditorToolbar.#l10nRemove[editorType]); + if (this.#addListenersToElement(button)) { + button.addEventListener("click", (e) => { + _uiManager.delete(); + }, { + signal: _uiManager._signal + }); + } + this.#buttons.append(button); + } + get #divider() { + const divider = document.createElement("div"); + divider.className = "divider"; + return divider; + } + async addAltText(altText) { + const button = await altText.render(); + this.#addListenersToElement(button); + this.#buttons.append(button, this.#divider); + this.#altText = altText; + } + addComment(comment, beforeElement = null) { + if (this.#comment) { + return; + } + const button = comment.renderForToolbar(); + if (!button) { + return; + } + this.#addListenersToElement(button); + const divider = this.#commentButtonDivider = this.#divider; + if (!beforeElement) { + this.#buttons.append(button, divider); + } else { + this.#buttons.insertBefore(button, beforeElement); + this.#buttons.insertBefore(divider, beforeElement); + } + this.#comment = comment; + comment.toolbar = this; + } + addColorPicker(colorPicker) { + if (this.#colorPicker) { + return; + } + this.#colorPicker = colorPicker; + const button = colorPicker.renderButton(); + this.#addListenersToElement(button); + this.#buttons.append(button, this.#divider); + } + async addEditSignatureButton(signatureManager) { + const button = this.#signatureDescriptionButton = await signatureManager.renderEditButton(this.#editor); + this.#addListenersToElement(button); + this.#buttons.append(button, this.#divider); + } + removeButton(name) { + switch (name) { + case "comment": + this.#comment?.removeToolbarCommentButton(); + this.#comment = null; + this.#commentButtonDivider?.remove(); + this.#commentButtonDivider = null; + break; + } + } + async addButton(name, tool) { + switch (name) { + case "colorPicker": + this.addColorPicker(tool); + break; + case "altText": + await this.addAltText(tool); + break; + case "editSignature": + await this.addEditSignatureButton(tool); + break; + case "delete": + this.addDeleteButton(); + break; + case "comment": + this.addComment(tool); + break; + } + } + async addButtonBefore(name, tool, beforeSelector) { + const beforeElement = this.#buttons.querySelector(beforeSelector); + if (!beforeElement) { + return; + } + if (name === "comment") { + this.addComment(tool, beforeElement); + } + } + updateEditSignatureButton(description) { + if (this.#signatureDescriptionButton) { + this.#signatureDescriptionButton.title = description; + } + } + remove() { + this.#toolbar.remove(); + this.#colorPicker?.destroy(); + this.#colorPicker = null; + } +} +class FloatingToolbar { + #buttons = null; + #toolbar = null; + #uiManager; + constructor(uiManager) { + this.#uiManager = uiManager; + } + #render() { + const editToolbar = this.#toolbar = document.createElement("div"); + editToolbar.className = "editToolbar"; + editToolbar.setAttribute("role", "toolbar"); + const signal = this.#uiManager._signal; + if (signal instanceof AbortSignal && !signal.aborted) { + editToolbar.addEventListener("contextmenu", noContextMenu, { + signal + }); + } + const buttons = this.#buttons = document.createElement("div"); + buttons.className = "buttons"; + editToolbar.append(buttons); + if (this.#uiManager.hasCommentManager()) { + this.#makeButton("commentButton", `pdfjs-comment-floating-button`, "pdfjs-comment-floating-button-label", () => { + this.#uiManager.commentSelection("floating_button"); + }); + } + this.#makeButton("highlightButton", `pdfjs-highlight-floating-button1`, "pdfjs-highlight-floating-button-label", () => { + this.#uiManager.highlightSelection("floating_button"); + }); + return editToolbar; + } + #getLastPoint(boxes, isLTR) { + let lastY = 0; + let lastX = 0; + for (const box of boxes) { + const y = box.y + box.height; + if (y < lastY) { + continue; + } + const x = box.x + (isLTR ? box.width : 0); + if (y > lastY) { + lastX = x; + lastY = y; + continue; + } + if (isLTR) { + if (x > lastX) { + lastX = x; + } + } else if (x < lastX) { + lastX = x; + } + } + return [isLTR ? 1 - lastX : lastX, lastY]; + } + show(parent, boxes, isLTR) { + const [x, y] = this.#getLastPoint(boxes, isLTR); + const { + style + } = this.#toolbar ||= this.#render(); + parent.append(this.#toolbar); + style.insetInlineEnd = `${100 * x}%`; + style.top = `calc(${100 * y}% + var(--editor-toolbar-vert-offset))`; + } + hide() { + this.#toolbar.remove(); + } + #makeButton(buttonClass, l10nId, labelL10nId, clickHandler) { + const button = document.createElement("button"); + button.classList.add("basic", buttonClass); + button.tabIndex = 0; + button.setAttribute("data-l10n-id", l10nId); + const span = document.createElement("span"); + button.append(span); + span.className = "visuallyHidden"; + span.setAttribute("data-l10n-id", labelL10nId); + const signal = this.#uiManager._signal; + if (signal instanceof AbortSignal && !signal.aborted) { + button.addEventListener("contextmenu", noContextMenu, { + signal + }); + button.addEventListener("click", clickHandler, { + signal + }); + } + this.#buttons.append(button); + } +} +function bindEvents(obj, element, names) { + for (const name of names) { + element.addEventListener(name, obj[name].bind(obj)); + } +} +class IdManager { + #id = 0; + get id() { + return `${AnnotationEditorPrefix}${this.#id++}`; + } +} +class ImageManager { + #baseId = getUuid(); + #id = 0; + #cache = null; + static get _isSVGFittingCanvas() { + const svg = `data:image/svg+xml;charset=UTF-8,`; + const canvas = new OffscreenCanvas(1, 3); + const ctx = canvas.getContext("2d", { + willReadFrequently: true + }); + const image = new Image(); + image.src = svg; + const promise = image.decode().then(() => { + ctx.drawImage(image, 0, 0, 1, 1, 0, 0, 1, 3); + return new Uint32Array(ctx.getImageData(0, 0, 1, 1).data.buffer)[0] === 0; + }); + return shadow(this, "_isSVGFittingCanvas", promise); + } + async #get(key, rawData) { + this.#cache ||= /* @__PURE__ */ new Map(); + let data = this.#cache.get(key); + if (data === null) { + return null; + } + if (data?.bitmap) { + data.refCounter += 1; + return data; + } + try { + data ||= { + bitmap: null, + id: `image_${this.#baseId}_${this.#id++}`, + refCounter: 0, + isSvg: false + }; + let image; + if (typeof rawData === "string") { + data.url = rawData; + image = await fetchData(rawData, "blob"); + } else if (rawData instanceof File) { + image = data.file = rawData; + } else if (rawData instanceof Blob) { + image = rawData; + } + if (image.type === "image/svg+xml") { + const mustRemoveAspectRatioPromise = ImageManager._isSVGFittingCanvas; + const fileReader = new FileReader(); + const imageElement = new Image(); + const imagePromise = new Promise((resolve, reject) => { + imageElement.onload = () => { + data.bitmap = imageElement; + data.isSvg = true; + resolve(); + }; + fileReader.onload = async () => { + const url = data.svgUrl = fileReader.result; + imageElement.src = await mustRemoveAspectRatioPromise ? `${url}#svgView(preserveAspectRatio(none))` : url; + }; + imageElement.onerror = fileReader.onerror = reject; + }); + fileReader.readAsDataURL(image); + await imagePromise; + } else { + data.bitmap = await createImageBitmap(image); + } + data.refCounter = 1; + } catch (e) { + warn(e); + data = null; + } + this.#cache.set(key, data); + if (data) { + this.#cache.set(data.id, data); + } + return data; + } + async getFromFile(file) { + const { + lastModified, + name, + size, + type + } = file; + return this.#get(`${lastModified}_${name}_${size}_${type}`, file); + } + async getFromUrl(url) { + return this.#get(url, url); + } + async getFromBlob(id, blobPromise) { + const blob = await blobPromise; + return this.#get(id, blob); + } + async getFromId(id) { + this.#cache ||= /* @__PURE__ */ new Map(); + const data = this.#cache.get(id); + if (!data) { + return null; + } + if (data.bitmap) { + data.refCounter += 1; + return data; + } + if (data.file) { + return this.getFromFile(data.file); + } + if (data.blobPromise) { + const { + blobPromise + } = data; + delete data.blobPromise; + return this.getFromBlob(data.id, blobPromise); + } + return this.getFromUrl(data.url); + } + getFromCanvas(id, canvas) { + this.#cache ||= /* @__PURE__ */ new Map(); + let data = this.#cache.get(id); + if (data?.bitmap) { + data.refCounter += 1; + return data; + } + const offscreen = new OffscreenCanvas(canvas.width, canvas.height); + const ctx = offscreen.getContext("2d"); + ctx.drawImage(canvas, 0, 0); + data = { + bitmap: offscreen.transferToImageBitmap(), + id: `image_${this.#baseId}_${this.#id++}`, + refCounter: 1, + isSvg: false + }; + this.#cache.set(id, data); + this.#cache.set(data.id, data); + return data; + } + getSvgUrl(id) { + const data = this.#cache.get(id); + if (!data?.isSvg) { + return null; + } + return data.svgUrl; + } + deleteId(id) { + this.#cache ||= /* @__PURE__ */ new Map(); + const data = this.#cache.get(id); + if (!data) { + return; + } + data.refCounter -= 1; + if (data.refCounter !== 0) { + return; + } + const { + bitmap + } = data; + if (!data.url && !data.file) { + const canvas = new OffscreenCanvas(bitmap.width, bitmap.height); + const ctx = canvas.getContext("bitmaprenderer"); + ctx.transferFromImageBitmap(bitmap); + data.blobPromise = canvas.convertToBlob(); + } + bitmap.close?.(); + data.bitmap = null; + } + isValidId(id) { + return id.startsWith(`image_${this.#baseId}_`); + } +} +class CommandManager { + #commands = []; + #locked = false; + #maxSize; + #position = -1; + constructor(maxSize = 128) { + this.#maxSize = maxSize; + } + add({ + cmd, + undo, + post, + mustExec, + type = NaN, + overwriteIfSameType = false, + keepUndo = false + }) { + if (mustExec) { + cmd(); + } + if (this.#locked) { + return; + } + const save = { + cmd, + undo, + post, + type + }; + if (this.#position === -1) { + if (this.#commands.length > 0) { + this.#commands.length = 0; + } + this.#position = 0; + this.#commands.push(save); + return; + } + if (overwriteIfSameType && this.#commands[this.#position].type === type) { + if (keepUndo) { + save.undo = this.#commands[this.#position].undo; + } + this.#commands[this.#position] = save; + return; + } + const next = this.#position + 1; + if (next === this.#maxSize) { + this.#commands.splice(0, 1); + } else { + this.#position = next; + if (next < this.#commands.length) { + this.#commands.splice(next); + } + } + this.#commands.push(save); + } + undo() { + if (this.#position === -1) { + return; + } + this.#locked = true; + const { + undo, + post + } = this.#commands[this.#position]; + undo(); + post?.(); + this.#locked = false; + this.#position -= 1; + } + redo() { + if (this.#position < this.#commands.length - 1) { + this.#position += 1; + this.#locked = true; + const { + cmd, + post + } = this.#commands[this.#position]; + cmd(); + post?.(); + this.#locked = false; + } + } + hasSomethingToUndo() { + return this.#position !== -1; + } + hasSomethingToRedo() { + return this.#position < this.#commands.length - 1; + } + cleanType(type) { + if (this.#position === -1) { + return; + } + for (let i = this.#position; i >= 0; i--) { + if (this.#commands[i].type !== type) { + this.#commands.splice(i + 1, this.#position - i); + this.#position = i; + return; + } + } + this.#commands.length = 0; + this.#position = -1; + } + destroy() { + this.#commands = null; + } +} +class KeyboardManager { + constructor(callbacks) { + this.buffer = []; + this.callbacks = /* @__PURE__ */ new Map(); + this.allKeys = /* @__PURE__ */ new Set(); + const { + isMac + } = util_FeatureTest.platform; + for (const [keys, callback, options = {}] of callbacks) { + for (const key of keys) { + const isMacKey = key.startsWith("mac+"); + if (isMac && isMacKey) { + this.callbacks.set(key.slice(4), { + callback, + options + }); + this.allKeys.add(key.split("+").at(-1)); + } else if (!isMac && !isMacKey) { + this.callbacks.set(key, { + callback, + options + }); + this.allKeys.add(key.split("+").at(-1)); + } + } + } + } + #serialize(event) { + if (event.altKey) { + this.buffer.push("alt"); + } + if (event.ctrlKey) { + this.buffer.push("ctrl"); + } + if (event.metaKey) { + this.buffer.push("meta"); + } + if (event.shiftKey) { + this.buffer.push("shift"); + } + this.buffer.push(event.key); + const str = this.buffer.join("+"); + this.buffer.length = 0; + return str; + } + exec(self2, event) { + if (!this.allKeys.has(event.key)) { + return; + } + const info2 = this.callbacks.get(this.#serialize(event)); + if (!info2) { + return; + } + const { + callback, + options: { + bubbles = false, + args = [], + checker = null + } + } = info2; + if (checker && !checker(self2, event)) { + return; + } + callback.bind(self2, ...args, event)(); + if (!bubbles) { + stopEvent(event); + } + } +} +class ColorManager { + static _colorsMapping = /* @__PURE__ */ new Map([["CanvasText", [0, 0, 0]], ["Canvas", [255, 255, 255]]]); + get _colors() { + const colors = /* @__PURE__ */ new Map([["CanvasText", null], ["Canvas", null]]); + getColorValues(colors); + return shadow(this, "_colors", colors); + } + convert(color) { + const rgb = getRGB(color); + if (!window.matchMedia("(forced-colors: active)").matches) { + return rgb; + } + for (const [name, RGB] of this._colors) { + if (RGB.every((x, i) => x === rgb[i])) { + return ColorManager._colorsMapping.get(name); + } + } + return rgb; + } + getHexCode(name) { + const rgb = this._colors.get(name); + if (!rgb) { + return name; + } + return Util.makeHexColor(...rgb); + } +} +class AnnotationEditorUIManager { + #abortController = new AbortController(); + #activeEditor = null; + #allEditableAnnotations = null; + #allEditors = /* @__PURE__ */ new Map(); + #allLayers = /* @__PURE__ */ new Map(); + #altTextManager = null; + #annotationStorage = null; + #changedExistingAnnotations = null; + #commandManager = new CommandManager(); + #commentManager = null; + #copyPasteAC = null; + #currentDrawingSession = null; + #currentPageIndex = 0; + #deletedAnnotationsElementIds = /* @__PURE__ */ new Set(); + #draggingEditors = null; + #editorTypes = null; + #editorsToRescale = /* @__PURE__ */ new Set(); + _editorUndoBar = null; + #enableHighlightFloatingButton = false; + #enableUpdatedAddImage = false; + #enableNewAltTextWhenAddingImage = false; + #filterFactory = null; + #focusMainContainerTimeoutId = null; + #focusManagerAC = null; + #highlightColors = null; + #highlightWhenShiftUp = false; + #floatingToolbar = null; + #idManager = new IdManager(); + #isEnabled = false; + #isPointerDown = false; + #isWaiting = false; + #keyboardManagerAC = null; + #lastActiveElement = null; + #mainHighlightColorPicker = null; + #missingCanvases = null; + #mlManager = null; + #mode = AnnotationEditorType.NONE; + #selectedEditors = /* @__PURE__ */ new Set(); + #selectedTextNode = null; + #signatureManager = null; + #pageColors = null; + #showAllStates = null; + #pdfDocument = null; + #previousStates = { + isEditing: false, + isEmpty: true, + hasSomethingToUndo: false, + hasSomethingToRedo: false, + hasSelectedEditor: false, + hasSelectedText: false + }; + #translation = [0, 0]; + #translationTimeoutId = null; + #container = null; + #viewer = null; + #viewerAlert = null; + #updateModeCapability = null; + static TRANSLATE_SMALL = 1; + static TRANSLATE_BIG = 10; + static get _keyboardManager() { + const proto = AnnotationEditorUIManager.prototype; + const arrowChecker = (self2) => self2.#container.contains(document.activeElement) && document.activeElement.tagName !== "BUTTON" && self2.hasSomethingToControl(); + const textInputChecker = (_self, { + target: el + }) => { + if (el instanceof HTMLInputElement) { + const { + type + } = el; + return type !== "text" && type !== "number"; + } + return true; + }; + const small = this.TRANSLATE_SMALL; + const big = this.TRANSLATE_BIG; + return shadow(this, "_keyboardManager", new KeyboardManager([[["ctrl+a", "mac+meta+a"], proto.selectAll, { + checker: textInputChecker + }], [["ctrl+z", "mac+meta+z"], proto.undo, { + checker: textInputChecker + }], [["ctrl+y", "ctrl+shift+z", "mac+meta+shift+z", "ctrl+shift+Z", "mac+meta+shift+Z"], proto.redo, { + checker: textInputChecker + }], [["Backspace", "alt+Backspace", "ctrl+Backspace", "shift+Backspace", "mac+Backspace", "mac+alt+Backspace", "mac+ctrl+Backspace", "Delete", "ctrl+Delete", "shift+Delete", "mac+Delete"], proto.delete, { + checker: textInputChecker + }], [["Enter", "mac+Enter"], proto.addNewEditorFromKeyboard, { + checker: (self2, { + target: el + }) => !(el instanceof HTMLButtonElement) && self2.#container.contains(el) && !self2.isEnterHandled + }], [[" ", "mac+ "], proto.addNewEditorFromKeyboard, { + checker: (self2, { + target: el + }) => !(el instanceof HTMLButtonElement) && self2.#container.contains(document.activeElement) + }], [["Escape", "mac+Escape"], proto.unselectAll], [["ArrowLeft", "mac+ArrowLeft"], proto.translateSelectedEditors, { + args: [-small, 0], + checker: arrowChecker + }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], proto.translateSelectedEditors, { + args: [-big, 0], + checker: arrowChecker + }], [["ArrowRight", "mac+ArrowRight"], proto.translateSelectedEditors, { + args: [small, 0], + checker: arrowChecker + }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], proto.translateSelectedEditors, { + args: [big, 0], + checker: arrowChecker + }], [["ArrowUp", "mac+ArrowUp"], proto.translateSelectedEditors, { + args: [0, -small], + checker: arrowChecker + }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], proto.translateSelectedEditors, { + args: [0, -big], + checker: arrowChecker + }], [["ArrowDown", "mac+ArrowDown"], proto.translateSelectedEditors, { + args: [0, small], + checker: arrowChecker + }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], proto.translateSelectedEditors, { + args: [0, big], + checker: arrowChecker + }]])); + } + constructor(container, viewer, viewerAlert, altTextManager, commentManager, signatureManager, eventBus, pdfDocument, pageColors, highlightColors, enableHighlightFloatingButton, enableUpdatedAddImage, enableNewAltTextWhenAddingImage, mlManager, editorUndoBar, supportsPinchToZoom) { + const signal = this._signal = this.#abortController.signal; + this.#container = container; + this.#viewer = viewer; + this.#viewerAlert = viewerAlert; + this.#altTextManager = altTextManager; + this.#commentManager = commentManager; + this.#signatureManager = signatureManager; + this.#pdfDocument = pdfDocument; + this._eventBus = eventBus; + eventBus._on("editingaction", this.onEditingAction.bind(this), { + signal + }); + eventBus._on("pagechanging", this.onPageChanging.bind(this), { + signal + }); + eventBus._on("scalechanging", this.onScaleChanging.bind(this), { + signal + }); + eventBus._on("rotationchanging", this.onRotationChanging.bind(this), { + signal + }); + eventBus._on("setpreference", this.onSetPreference.bind(this), { + signal + }); + eventBus._on("switchannotationeditorparams", (evt) => this.updateParams(evt.type, evt.value), { + signal + }); + window.addEventListener("pointerdown", () => { + this.#isPointerDown = true; + }, { + capture: true, + signal + }); + window.addEventListener("pointerup", () => { + this.#isPointerDown = false; + }, { + capture: true, + signal + }); + this.#addSelectionListener(); + this.#addDragAndDropListeners(); + this.#addKeyboardManager(); + this.#annotationStorage = pdfDocument.annotationStorage; + this.#filterFactory = pdfDocument.filterFactory; + this.#pageColors = pageColors; + this.#highlightColors = highlightColors || null; + this.#enableHighlightFloatingButton = enableHighlightFloatingButton; + this.#enableUpdatedAddImage = enableUpdatedAddImage; + this.#enableNewAltTextWhenAddingImage = enableNewAltTextWhenAddingImage; + this.#mlManager = mlManager || null; + this.viewParameters = { + realScale: PixelsPerInch.PDF_TO_CSS_UNITS, + rotation: 0 + }; + this.isShiftKeyDown = false; + this._editorUndoBar = editorUndoBar || null; + this._supportsPinchToZoom = supportsPinchToZoom !== false; + commentManager?.setSidebarUiManager(this); + } + destroy() { + this.#updateModeCapability?.resolve(); + this.#updateModeCapability = null; + this.#abortController?.abort(); + this.#abortController = null; + this._signal = null; + for (const layer of this.#allLayers.values()) { + layer.destroy(); + } + this.#allLayers.clear(); + this.#allEditors.clear(); + this.#editorsToRescale.clear(); + this.#missingCanvases?.clear(); + this.#activeEditor = null; + this.#selectedEditors.clear(); + this.#commandManager.destroy(); + this.#altTextManager?.destroy(); + this.#commentManager?.destroy(); + this.#signatureManager?.destroy(); + this.#floatingToolbar?.hide(); + this.#floatingToolbar = null; + this.#mainHighlightColorPicker?.destroy(); + this.#mainHighlightColorPicker = null; + this.#allEditableAnnotations = null; + if (this.#focusMainContainerTimeoutId) { + clearTimeout(this.#focusMainContainerTimeoutId); + this.#focusMainContainerTimeoutId = null; + } + if (this.#translationTimeoutId) { + clearTimeout(this.#translationTimeoutId); + this.#translationTimeoutId = null; + } + this._editorUndoBar?.destroy(); + this.#pdfDocument = null; + } + combinedSignal(ac) { + return AbortSignal.any([this._signal, ac.signal]); + } + get mlManager() { + return this.#mlManager; + } + get useNewAltTextFlow() { + return this.#enableUpdatedAddImage; + } + get useNewAltTextWhenAddingImage() { + return this.#enableNewAltTextWhenAddingImage; + } + get hcmFilter() { + return shadow(this, "hcmFilter", this.#pageColors ? this.#filterFactory.addHCMFilter(this.#pageColors.foreground, this.#pageColors.background) : "none"); + } + get direction() { + return shadow(this, "direction", getComputedStyle(this.#container).direction); + } + get _highlightColors() { + return shadow(this, "_highlightColors", this.#highlightColors ? new Map(this.#highlightColors.split(",").map((pair) => { + pair = pair.split("=").map((x) => x.trim()); + pair[1] = pair[1].toUpperCase(); + return pair; + })) : null); + } + get highlightColors() { + const { + _highlightColors + } = this; + if (!_highlightColors) { + return shadow(this, "highlightColors", null); + } + const map = /* @__PURE__ */ new Map(); + const hasHCM = !!this.#pageColors; + for (const [name, color] of _highlightColors) { + const isNameForHCM = name.endsWith("_HCM"); + if (hasHCM && isNameForHCM) { + map.set(name.replace("_HCM", ""), color); + continue; + } + if (!hasHCM && !isNameForHCM) { + map.set(name, color); + } + } + return shadow(this, "highlightColors", map); + } + get highlightColorNames() { + return shadow(this, "highlightColorNames", this.highlightColors ? new Map(Array.from(this.highlightColors, (e) => e.reverse())) : null); + } + getNonHCMColor(color) { + if (!this._highlightColors) { + return color; + } + const colorName = this.highlightColorNames.get(color); + return this._highlightColors.get(colorName) || color; + } + getNonHCMColorName(color) { + return this.highlightColorNames.get(color) || color; + } + setCurrentDrawingSession(layer) { + if (layer) { + this.unselectAll(); + this.disableUserSelect(true); + } else { + this.disableUserSelect(false); + } + this.#currentDrawingSession = layer; + } + setMainHighlightColorPicker(colorPicker) { + this.#mainHighlightColorPicker = colorPicker; + } + editAltText(editor, firstTime = false) { + this.#altTextManager?.editAltText(this, editor, firstTime); + } + hasCommentManager() { + return !!this.#commentManager; + } + editComment(editor, posX, posY, options) { + this.#commentManager?.showDialog(this, editor, posX, posY, options); + } + selectComment(pageIndex, uid) { + const layer = this.#allLayers.get(pageIndex); + const editor = layer?.getEditorByUID(uid); + editor?.toggleComment(true, true); + } + updateComment(editor) { + this.#commentManager?.updateComment(editor.getData()); + } + updatePopupColor(editor) { + this.#commentManager?.updatePopupColor(editor); + } + removeComment(editor) { + this.#commentManager?.removeComments([editor.uid]); + } + toggleComment(editor, isSelected, visibility = void 0) { + this.#commentManager?.toggleCommentPopup(editor, isSelected, visibility); + } + makeCommentColor(color, opacity) { + return color && this.#commentManager?.makeCommentColor(color, opacity) || null; + } + getCommentDialogElement() { + return this.#commentManager?.dialogElement || null; + } + async waitForEditorsRendered(pageNumber) { + if (this.#allLayers.has(pageNumber - 1)) { + return; + } + const { + resolve, + promise + } = Promise.withResolvers(); + const onEditorsRendered = (evt) => { + if (evt.pageNumber === pageNumber) { + this._eventBus._off("editorsrendered", onEditorsRendered); + resolve(); + } + }; + this._eventBus.on("editorsrendered", onEditorsRendered); + await promise; + } + getSignature(editor) { + this.#signatureManager?.getSignature({ + uiManager: this, + editor + }); + } + get signatureManager() { + return this.#signatureManager; + } + switchToMode(mode, callback) { + this._eventBus.on("annotationeditormodechanged", callback, { + once: true, + signal: this._signal + }); + this._eventBus.dispatch("showannotationeditorui", { + source: this, + mode + }); + } + setPreference(name, value) { + this._eventBus.dispatch("setpreference", { + source: this, + name, + value + }); + } + onSetPreference({ + name, + value + }) { + switch (name) { + case "enableNewAltTextWhenAddingImage": + this.#enableNewAltTextWhenAddingImage = value; + break; + } + } + onPageChanging({ + pageNumber + }) { + this.#currentPageIndex = pageNumber - 1; + } + focusMainContainer() { + this.#container.focus(); + } + findParent(x, y) { + for (const layer of this.#allLayers.values()) { + const { + x: layerX, + y: layerY, + width, + height + } = layer.div.getBoundingClientRect(); + if (x >= layerX && x <= layerX + width && y >= layerY && y <= layerY + height) { + return layer; + } + } + return null; + } + disableUserSelect(value = false) { + this.#viewer.classList.toggle("noUserSelect", value); + } + addShouldRescale(editor) { + this.#editorsToRescale.add(editor); + } + removeShouldRescale(editor) { + this.#editorsToRescale.delete(editor); + } + onScaleChanging({ + scale + }) { + this.commitOrRemove(); + this.viewParameters.realScale = scale * PixelsPerInch.PDF_TO_CSS_UNITS; + for (const editor of this.#editorsToRescale) { + editor.onScaleChanging(); + } + this.#currentDrawingSession?.onScaleChanging(); + } + onRotationChanging({ + pagesRotation + }) { + this.commitOrRemove(); + this.viewParameters.rotation = pagesRotation; + } + #getAnchorElementForSelection({ + anchorNode + }) { + return anchorNode.nodeType === Node.TEXT_NODE ? anchorNode.parentElement : anchorNode; + } + #getLayerForTextLayer(textLayer) { + const { + currentLayer + } = this; + if (currentLayer.hasTextLayer(textLayer)) { + return currentLayer; + } + for (const layer of this.#allLayers.values()) { + if (layer.hasTextLayer(textLayer)) { + return layer; + } + } + return null; + } + highlightSelection(methodOfCreation = "", comment = false) { + const selection = document.getSelection(); + if (!selection || selection.isCollapsed) { + return; + } + const { + anchorNode, + anchorOffset, + focusNode, + focusOffset + } = selection; + const text = selection.toString(); + const anchorElement = this.#getAnchorElementForSelection(selection); + const textLayer = anchorElement.closest(".textLayer"); + const boxes = this.getSelectionBoxes(textLayer); + if (!boxes) { + return; + } + selection.empty(); + const layer = this.#getLayerForTextLayer(textLayer); + const isNoneMode = this.#mode === AnnotationEditorType.NONE; + const callback = () => { + const editor = layer?.createAndAddNewEditor({ + x: 0, + y: 0 + }, false, { + methodOfCreation, + boxes, + anchorNode, + anchorOffset, + focusNode, + focusOffset, + text + }); + if (isNoneMode) { + this.showAllEditors("highlight", true, true); + } + if (comment) { + editor?.editComment(); + } + }; + if (isNoneMode) { + this.switchToMode(AnnotationEditorType.HIGHLIGHT, callback); + return; + } + callback(); + } + commentSelection(methodOfCreation = "") { + this.highlightSelection(methodOfCreation, true); + } + #displayFloatingToolbar() { + const selection = document.getSelection(); + if (!selection || selection.isCollapsed) { + return; + } + const anchorElement = this.#getAnchorElementForSelection(selection); + const textLayer = anchorElement.closest(".textLayer"); + const boxes = this.getSelectionBoxes(textLayer); + if (!boxes) { + return; + } + this.#floatingToolbar ||= new FloatingToolbar(this); + this.#floatingToolbar.show(textLayer, boxes, this.direction === "ltr"); + } + getAndRemoveDataFromAnnotationStorage(annotationId) { + if (!this.#annotationStorage) { + return null; + } + const key = `${AnnotationEditorPrefix}${annotationId}`; + const storedValue = this.#annotationStorage.getRawValue(key); + if (storedValue) { + this.#annotationStorage.remove(key); + } + return storedValue; + } + addToAnnotationStorage(editor) { + if (!editor.isEmpty() && this.#annotationStorage && !this.#annotationStorage.has(editor.id)) { + this.#annotationStorage.setValue(editor.id, editor); + } + } + a11yAlert(messageId, args = null) { + const viewerAlert = this.#viewerAlert; + if (!viewerAlert) { + return; + } + viewerAlert.setAttribute("data-l10n-id", messageId); + if (args) { + viewerAlert.setAttribute("data-l10n-args", JSON.stringify(args)); + } else { + viewerAlert.removeAttribute("data-l10n-args"); + } + } + #selectionChange() { + const selection = document.getSelection(); + if (!selection || selection.isCollapsed) { + if (this.#selectedTextNode) { + this.#floatingToolbar?.hide(); + this.#selectedTextNode = null; + this.#dispatchUpdateStates({ + hasSelectedText: false + }); + } + return; + } + const { + anchorNode + } = selection; + if (anchorNode === this.#selectedTextNode) { + return; + } + const anchorElement = this.#getAnchorElementForSelection(selection); + const textLayer = anchorElement.closest(".textLayer"); + if (!textLayer) { + if (this.#selectedTextNode) { + this.#floatingToolbar?.hide(); + this.#selectedTextNode = null; + this.#dispatchUpdateStates({ + hasSelectedText: false + }); + } + return; + } + this.#floatingToolbar?.hide(); + this.#selectedTextNode = anchorNode; + this.#dispatchUpdateStates({ + hasSelectedText: true + }); + if (this.#mode !== AnnotationEditorType.HIGHLIGHT && this.#mode !== AnnotationEditorType.NONE) { + return; + } + if (this.#mode === AnnotationEditorType.HIGHLIGHT) { + this.showAllEditors("highlight", true, true); + } + this.#highlightWhenShiftUp = this.isShiftKeyDown; + if (!this.isShiftKeyDown) { + const activeLayer = this.#mode === AnnotationEditorType.HIGHLIGHT ? this.#getLayerForTextLayer(textLayer) : null; + activeLayer?.toggleDrawing(); + if (this.#isPointerDown) { + const ac = new AbortController(); + const signal = this.combinedSignal(ac); + const pointerup = (e) => { + if (e.type === "pointerup" && e.button !== 0) { + return; + } + ac.abort(); + activeLayer?.toggleDrawing(true); + if (e.type === "pointerup") { + this.#onSelectEnd("main_toolbar"); + } + }; + window.addEventListener("pointerup", pointerup, { + signal + }); + window.addEventListener("blur", pointerup, { + signal + }); + } else { + activeLayer?.toggleDrawing(true); + this.#onSelectEnd("main_toolbar"); + } + } + } + #onSelectEnd(methodOfCreation = "") { + if (this.#mode === AnnotationEditorType.HIGHLIGHT) { + this.highlightSelection(methodOfCreation); + } else if (this.#enableHighlightFloatingButton) { + this.#displayFloatingToolbar(); + } + } + #addSelectionListener() { + document.addEventListener("selectionchange", this.#selectionChange.bind(this), { + signal: this._signal + }); + } + #addFocusManager() { + if (this.#focusManagerAC) { + return; + } + this.#focusManagerAC = new AbortController(); + const signal = this.combinedSignal(this.#focusManagerAC); + window.addEventListener("focus", this.focus.bind(this), { + signal + }); + window.addEventListener("blur", this.blur.bind(this), { + signal + }); + } + #removeFocusManager() { + this.#focusManagerAC?.abort(); + this.#focusManagerAC = null; + } + blur() { + this.isShiftKeyDown = false; + if (this.#highlightWhenShiftUp) { + this.#highlightWhenShiftUp = false; + this.#onSelectEnd("main_toolbar"); + } + if (!this.hasSelection) { + return; + } + const { + activeElement + } = document; + for (const editor of this.#selectedEditors) { + if (editor.div.contains(activeElement)) { + this.#lastActiveElement = [editor, activeElement]; + editor._focusEventsAllowed = false; + break; + } + } + } + focus() { + if (!this.#lastActiveElement) { + return; + } + const [lastEditor, lastActiveElement] = this.#lastActiveElement; + this.#lastActiveElement = null; + lastActiveElement.addEventListener("focusin", () => { + lastEditor._focusEventsAllowed = true; + }, { + once: true, + signal: this._signal + }); + lastActiveElement.focus(); + } + #addKeyboardManager() { + if (this.#keyboardManagerAC) { + return; + } + this.#keyboardManagerAC = new AbortController(); + const signal = this.combinedSignal(this.#keyboardManagerAC); + window.addEventListener("keydown", this.keydown.bind(this), { + signal + }); + window.addEventListener("keyup", this.keyup.bind(this), { + signal + }); + } + #removeKeyboardManager() { + this.#keyboardManagerAC?.abort(); + this.#keyboardManagerAC = null; + } + #addCopyPasteListeners() { + if (this.#copyPasteAC) { + return; + } + this.#copyPasteAC = new AbortController(); + const signal = this.combinedSignal(this.#copyPasteAC); + document.addEventListener("copy", this.copy.bind(this), { + signal + }); + document.addEventListener("cut", this.cut.bind(this), { + signal + }); + document.addEventListener("paste", this.paste.bind(this), { + signal + }); + } + #removeCopyPasteListeners() { + this.#copyPasteAC?.abort(); + this.#copyPasteAC = null; + } + #addDragAndDropListeners() { + const signal = this._signal; + document.addEventListener("dragover", this.dragOver.bind(this), { + signal + }); + document.addEventListener("drop", this.drop.bind(this), { + signal + }); + } + addEditListeners() { + this.#addKeyboardManager(); + this.#addCopyPasteListeners(); + } + removeEditListeners() { + this.#removeKeyboardManager(); + this.#removeCopyPasteListeners(); + } + dragOver(event) { + for (const { + type + } of event.dataTransfer.items) { + for (const editorType of this.#editorTypes) { + if (editorType.isHandlingMimeForPasting(type)) { + event.dataTransfer.dropEffect = "copy"; + event.preventDefault(); + return; + } + } + } + } + drop(event) { + for (const item of event.dataTransfer.items) { + for (const editorType of this.#editorTypes) { + if (editorType.isHandlingMimeForPasting(item.type)) { + editorType.paste(item, this.currentLayer); + event.preventDefault(); + return; + } + } + } + } + copy(event) { + event.preventDefault(); + this.#activeEditor?.commitOrRemove(); + if (!this.hasSelection) { + return; + } + const editors = []; + for (const editor of this.#selectedEditors) { + const serialized = editor.serialize(true); + if (serialized) { + editors.push(serialized); + } + } + if (editors.length === 0) { + return; + } + event.clipboardData.setData("application/pdfjs", JSON.stringify(editors)); + } + cut(event) { + this.copy(event); + this.delete(); + } + async paste(event) { + event.preventDefault(); + const { + clipboardData + } = event; + for (const item of clipboardData.items) { + for (const editorType of this.#editorTypes) { + if (editorType.isHandlingMimeForPasting(item.type)) { + editorType.paste(item, this.currentLayer); + return; + } + } + } + let data = clipboardData.getData("application/pdfjs"); + if (!data) { + return; + } + try { + data = JSON.parse(data); + } catch (ex) { + warn(`paste: "${ex.message}".`); + return; + } + if (!Array.isArray(data)) { + return; + } + this.unselectAll(); + const layer = this.currentLayer; + try { + const newEditors = []; + for (const editor of data) { + const deserializedEditor = await layer.deserialize(editor); + if (!deserializedEditor) { + return; + } + newEditors.push(deserializedEditor); + } + const cmd = () => { + for (const editor of newEditors) { + this.#addEditorToLayer(editor); + } + this.#selectEditors(newEditors); + }; + const undo = () => { + for (const editor of newEditors) { + editor.remove(); + } + }; + this.addCommands({ + cmd, + undo, + mustExec: true + }); + } catch (ex) { + warn(`paste: "${ex.message}".`); + } + } + keydown(event) { + if (!this.isShiftKeyDown && event.key === "Shift") { + this.isShiftKeyDown = true; + } + if (this.#mode !== AnnotationEditorType.NONE && !this.isEditorHandlingKeyboard) { + AnnotationEditorUIManager._keyboardManager.exec(this, event); + } + } + keyup(event) { + if (this.isShiftKeyDown && event.key === "Shift") { + this.isShiftKeyDown = false; + if (this.#highlightWhenShiftUp) { + this.#highlightWhenShiftUp = false; + this.#onSelectEnd("main_toolbar"); + } + } + } + onEditingAction({ + name + }) { + switch (name) { + case "undo": + case "redo": + case "delete": + case "selectAll": + this[name](); + break; + case "highlightSelection": + this.highlightSelection("context_menu"); + break; + case "commentSelection": + this.commentSelection("context_menu"); + break; + } + } + #dispatchUpdateStates(details) { + const hasChanged = Object.entries(details).some(([key, value]) => this.#previousStates[key] !== value); + if (hasChanged) { + this._eventBus.dispatch("annotationeditorstateschanged", { + source: this, + details: Object.assign(this.#previousStates, details) + }); + if (this.#mode === AnnotationEditorType.HIGHLIGHT && details.hasSelectedEditor === false) { + this.#dispatchUpdateUI([[AnnotationEditorParamsType.HIGHLIGHT_FREE, true]]); + } + } + } + #dispatchUpdateUI(details) { + this._eventBus.dispatch("annotationeditorparamschanged", { + source: this, + details + }); + } + setEditingState(isEditing) { + if (isEditing) { + this.#addFocusManager(); + this.#addCopyPasteListeners(); + this.#dispatchUpdateStates({ + isEditing: this.#mode !== AnnotationEditorType.NONE, + isEmpty: this.#isEmpty(), + hasSomethingToUndo: this.#commandManager.hasSomethingToUndo(), + hasSomethingToRedo: this.#commandManager.hasSomethingToRedo(), + hasSelectedEditor: false + }); + } else { + this.#removeFocusManager(); + this.#removeCopyPasteListeners(); + this.#dispatchUpdateStates({ + isEditing: false + }); + this.disableUserSelect(false); + } + } + registerEditorTypes(types) { + if (this.#editorTypes) { + return; + } + this.#editorTypes = types; + for (const editorType of this.#editorTypes) { + this.#dispatchUpdateUI(editorType.defaultPropertiesToUpdate); + } + } + getId() { + return this.#idManager.id; + } + get currentLayer() { + return this.#allLayers.get(this.#currentPageIndex); + } + getLayer(pageIndex) { + return this.#allLayers.get(pageIndex); + } + get currentPageIndex() { + return this.#currentPageIndex; + } + addLayer(layer) { + this.#allLayers.set(layer.pageIndex, layer); + if (this.#isEnabled) { + layer.enable(); + } else { + layer.disable(); + } + } + removeLayer(layer) { + this.#allLayers.delete(layer.pageIndex); + } + async updateMode(mode, editId = null, isFromKeyboard = false, mustEnterInEditMode = false, editComment = false) { + if (this.#mode === mode) { + return; + } + if (this.#updateModeCapability) { + await this.#updateModeCapability.promise; + if (!this.#updateModeCapability) { + return; + } + } + this.#updateModeCapability = Promise.withResolvers(); + this.#currentDrawingSession?.commitOrRemove(); + if (this.#mode === AnnotationEditorType.POPUP) { + this.#commentManager?.hideSidebar(); + } + this.#commentManager?.destroyPopup(); + this.#mode = mode; + if (mode === AnnotationEditorType.NONE) { + this.setEditingState(false); + this.#disableAll(); + for (const editor of this.#allEditors.values()) { + editor.hideStandaloneCommentButton(); + } + this._editorUndoBar?.hide(); + this.toggleComment(null); + this.#updateModeCapability.resolve(); + return; + } + for (const editor of this.#allEditors.values()) { + editor.addStandaloneCommentButton(); + } + if (mode === AnnotationEditorType.SIGNATURE) { + await this.#signatureManager?.loadSignatures(); + } + this.setEditingState(true); + await this.#enableAll(); + this.unselectAll(); + for (const layer of this.#allLayers.values()) { + layer.updateMode(mode); + } + if (mode === AnnotationEditorType.POPUP) { + this.#allEditableAnnotations ||= await this.#pdfDocument.getAnnotationsByType(new Set(this.#editorTypes.map((editorClass) => editorClass._editorType))); + const elementIds = /* @__PURE__ */ new Set(); + const allComments = []; + for (const editor of this.#allEditors.values()) { + const { + annotationElementId, + hasComment, + deleted + } = editor; + if (annotationElementId) { + elementIds.add(annotationElementId); + } + if (hasComment && !deleted) { + allComments.push(editor.getData()); + } + } + for (const annotation of this.#allEditableAnnotations) { + const { + id, + popupRef, + contentsObj + } = annotation; + if (popupRef && contentsObj?.str && !elementIds.has(id) && !this.#deletedAnnotationsElementIds.has(id)) { + allComments.push(annotation); + } + } + this.#commentManager?.showSidebar(allComments); + } + if (!editId) { + if (isFromKeyboard) { + this.addNewEditorFromKeyboard(); + } + this.#updateModeCapability.resolve(); + return; + } + for (const editor of this.#allEditors.values()) { + if (editor.uid === editId) { + this.setSelected(editor); + if (editComment) { + editor.editComment(); + } else if (mustEnterInEditMode) { + editor.enterInEditMode(); + } else { + editor.focus(); + } + } else { + editor.unselect(); + } + } + this.#updateModeCapability.resolve(); + } + addNewEditorFromKeyboard() { + if (this.currentLayer.canCreateNewEmptyEditor()) { + this.currentLayer.addNewEditor(); + } + } + updateToolbar(options) { + if (options.mode === this.#mode) { + return; + } + this._eventBus.dispatch("switchannotationeditormode", { + source: this, + ...options + }); + } + updateParams(type, value) { + if (!this.#editorTypes) { + return; + } + switch (type) { + case AnnotationEditorParamsType.CREATE: + this.currentLayer.addNewEditor(value); + return; + case AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL: + this._eventBus.dispatch("reporttelemetry", { + source: this, + details: { + type: "editing", + data: { + type: "highlight", + action: "toggle_visibility" + } + } + }); + (this.#showAllStates ||= /* @__PURE__ */ new Map()).set(type, value); + this.showAllEditors("highlight", value); + break; + } + if (this.hasSelection) { + for (const editor of this.#selectedEditors) { + editor.updateParams(type, value); + } + } else { + for (const editorType of this.#editorTypes) { + editorType.updateDefaultParams(type, value); + } + } + } + showAllEditors(type, visible, updateButton = false) { + for (const editor of this.#allEditors.values()) { + if (editor.editorType === type) { + editor.show(visible); + } + } + const state = this.#showAllStates?.get(AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL) ?? true; + if (state !== visible) { + this.#dispatchUpdateUI([[AnnotationEditorParamsType.HIGHLIGHT_SHOW_ALL, visible]]); + } + } + enableWaiting(mustWait = false) { + if (this.#isWaiting === mustWait) { + return; + } + this.#isWaiting = mustWait; + for (const layer of this.#allLayers.values()) { + if (mustWait) { + layer.disableClick(); + } else { + layer.enableClick(); + } + layer.div.classList.toggle("waiting", mustWait); + } + } + async #enableAll() { + if (!this.#isEnabled) { + this.#isEnabled = true; + const promises = []; + for (const layer of this.#allLayers.values()) { + promises.push(layer.enable()); + } + await Promise.all(promises); + for (const editor of this.#allEditors.values()) { + editor.enable(); + } + } + } + #disableAll() { + this.unselectAll(); + if (this.#isEnabled) { + this.#isEnabled = false; + for (const layer of this.#allLayers.values()) { + layer.disable(); + } + for (const editor of this.#allEditors.values()) { + editor.disable(); + } + } + } + *getEditors(pageIndex) { + for (const editor of this.#allEditors.values()) { + if (editor.pageIndex === pageIndex) { + yield editor; + } + } + } + getEditor(id) { + return this.#allEditors.get(id); + } + addEditor(editor) { + this.#allEditors.set(editor.id, editor); + } + removeEditor(editor) { + if (editor.div.contains(document.activeElement)) { + if (this.#focusMainContainerTimeoutId) { + clearTimeout(this.#focusMainContainerTimeoutId); + } + this.#focusMainContainerTimeoutId = setTimeout(() => { + this.focusMainContainer(); + this.#focusMainContainerTimeoutId = null; + }, 0); + } + this.#allEditors.delete(editor.id); + if (editor.annotationElementId) { + this.#missingCanvases?.delete(editor.annotationElementId); + } + this.unselect(editor); + if (!editor.annotationElementId || !this.#deletedAnnotationsElementIds.has(editor.annotationElementId)) { + this.#annotationStorage?.remove(editor.id); + } + } + addDeletedAnnotationElement(editor) { + this.#deletedAnnotationsElementIds.add(editor.annotationElementId); + this.addChangedExistingAnnotation(editor); + editor.deleted = true; + } + isDeletedAnnotationElement(annotationElementId) { + return this.#deletedAnnotationsElementIds.has(annotationElementId); + } + removeDeletedAnnotationElement(editor) { + this.#deletedAnnotationsElementIds.delete(editor.annotationElementId); + this.removeChangedExistingAnnotation(editor); + editor.deleted = false; + } + #addEditorToLayer(editor) { + const layer = this.#allLayers.get(editor.pageIndex); + if (layer) { + layer.addOrRebuild(editor); + } else { + this.addEditor(editor); + this.addToAnnotationStorage(editor); + } + } + setActiveEditor(editor) { + if (this.#activeEditor === editor) { + return; + } + this.#activeEditor = editor; + if (editor) { + this.#dispatchUpdateUI(editor.propertiesToUpdate); + } + } + get #lastSelectedEditor() { + let ed = null; + for (ed of this.#selectedEditors) { + } + return ed; + } + updateUI(editor) { + if (this.#lastSelectedEditor === editor) { + this.#dispatchUpdateUI(editor.propertiesToUpdate); + } + } + updateUIForDefaultProperties(editorType) { + this.#dispatchUpdateUI(editorType.defaultPropertiesToUpdate); + } + toggleSelected(editor) { + if (this.#selectedEditors.has(editor)) { + this.#selectedEditors.delete(editor); + editor.unselect(); + this.#dispatchUpdateStates({ + hasSelectedEditor: this.hasSelection + }); + return; + } + this.#selectedEditors.add(editor); + editor.select(); + this.#dispatchUpdateUI(editor.propertiesToUpdate); + this.#dispatchUpdateStates({ + hasSelectedEditor: true + }); + } + setSelected(editor) { + this.updateToolbar({ + mode: editor.mode, + editId: editor.id + }); + this.#currentDrawingSession?.commitOrRemove(); + for (const ed of this.#selectedEditors) { + if (ed !== editor) { + ed.unselect(); + } + } + this.#selectedEditors.clear(); + this.#selectedEditors.add(editor); + editor.select(); + this.#dispatchUpdateUI(editor.propertiesToUpdate); + this.#dispatchUpdateStates({ + hasSelectedEditor: true + }); + } + isSelected(editor) { + return this.#selectedEditors.has(editor); + } + get firstSelectedEditor() { + return this.#selectedEditors.values().next().value; + } + unselect(editor) { + editor.unselect(); + this.#selectedEditors.delete(editor); + this.#dispatchUpdateStates({ + hasSelectedEditor: this.hasSelection + }); + } + get hasSelection() { + return this.#selectedEditors.size !== 0; + } + get isEnterHandled() { + return this.#selectedEditors.size === 1 && this.firstSelectedEditor.isEnterHandled; + } + undo() { + this.#commandManager.undo(); + this.#dispatchUpdateStates({ + hasSomethingToUndo: this.#commandManager.hasSomethingToUndo(), + hasSomethingToRedo: true, + isEmpty: this.#isEmpty() + }); + this._editorUndoBar?.hide(); + } + redo() { + this.#commandManager.redo(); + this.#dispatchUpdateStates({ + hasSomethingToUndo: true, + hasSomethingToRedo: this.#commandManager.hasSomethingToRedo(), + isEmpty: this.#isEmpty() + }); + } + addCommands(params) { + this.#commandManager.add(params); + this.#dispatchUpdateStates({ + hasSomethingToUndo: true, + hasSomethingToRedo: false, + isEmpty: this.#isEmpty() + }); + } + cleanUndoStack(type) { + this.#commandManager.cleanType(type); + } + #isEmpty() { + if (this.#allEditors.size === 0) { + return true; + } + if (this.#allEditors.size === 1) { + for (const editor of this.#allEditors.values()) { + return editor.isEmpty(); + } + } + return false; + } + delete() { + this.commitOrRemove(); + const drawingEditor = this.currentLayer?.endDrawingSession(true); + if (!this.hasSelection && !drawingEditor) { + return; + } + const editors = drawingEditor ? [drawingEditor] : [...this.#selectedEditors]; + const cmd = () => { + this._editorUndoBar?.show(undo, editors.length === 1 ? editors[0].editorType : editors.length); + for (const editor of editors) { + editor.remove(); + } + }; + const undo = () => { + for (const editor of editors) { + this.#addEditorToLayer(editor); + } + }; + this.addCommands({ + cmd, + undo, + mustExec: true + }); + } + commitOrRemove() { + this.#activeEditor?.commitOrRemove(); + } + hasSomethingToControl() { + return this.#activeEditor || this.hasSelection; + } + #selectEditors(editors) { + for (const editor of this.#selectedEditors) { + editor.unselect(); + } + this.#selectedEditors.clear(); + for (const editor of editors) { + if (editor.isEmpty()) { + continue; + } + this.#selectedEditors.add(editor); + editor.select(); + } + this.#dispatchUpdateStates({ + hasSelectedEditor: this.hasSelection + }); + } + selectAll() { + for (const editor of this.#selectedEditors) { + editor.commit(); + } + this.#selectEditors(this.#allEditors.values()); + } + unselectAll() { + if (this.#activeEditor) { + this.#activeEditor.commitOrRemove(); + if (this.#mode !== AnnotationEditorType.NONE) { + return; + } + } + if (this.#currentDrawingSession?.commitOrRemove()) { + return; + } + if (!this.hasSelection) { + return; + } + for (const editor of this.#selectedEditors) { + editor.unselect(); + } + this.#selectedEditors.clear(); + this.#dispatchUpdateStates({ + hasSelectedEditor: false + }); + } + translateSelectedEditors(x, y, noCommit = false) { + if (!noCommit) { + this.commitOrRemove(); + } + if (!this.hasSelection) { + return; + } + this.#translation[0] += x; + this.#translation[1] += y; + const [totalX, totalY] = this.#translation; + const editors = [...this.#selectedEditors]; + const TIME_TO_WAIT = 1e3; + if (this.#translationTimeoutId) { + clearTimeout(this.#translationTimeoutId); + } + this.#translationTimeoutId = setTimeout(() => { + this.#translationTimeoutId = null; + this.#translation[0] = this.#translation[1] = 0; + this.addCommands({ + cmd: () => { + for (const editor of editors) { + if (this.#allEditors.has(editor.id)) { + editor.translateInPage(totalX, totalY); + editor.translationDone(); + } + } + }, + undo: () => { + for (const editor of editors) { + if (this.#allEditors.has(editor.id)) { + editor.translateInPage(-totalX, -totalY); + editor.translationDone(); + } + } + }, + mustExec: false + }); + }, TIME_TO_WAIT); + for (const editor of editors) { + editor.translateInPage(x, y); + editor.translationDone(); + } + } + setUpDragSession() { + if (!this.hasSelection) { + return; + } + this.disableUserSelect(true); + this.#draggingEditors = /* @__PURE__ */ new Map(); + for (const editor of this.#selectedEditors) { + this.#draggingEditors.set(editor, { + savedX: editor.x, + savedY: editor.y, + savedPageIndex: editor.pageIndex, + newX: 0, + newY: 0, + newPageIndex: -1 + }); + } + } + endDragSession() { + if (!this.#draggingEditors) { + return false; + } + this.disableUserSelect(false); + const map = this.#draggingEditors; + this.#draggingEditors = null; + let mustBeAddedInUndoStack = false; + for (const [{ + x, + y, + pageIndex + }, value] of map) { + value.newX = x; + value.newY = y; + value.newPageIndex = pageIndex; + mustBeAddedInUndoStack ||= x !== value.savedX || y !== value.savedY || pageIndex !== value.savedPageIndex; + } + if (!mustBeAddedInUndoStack) { + return false; + } + const move = (editor, x, y, pageIndex) => { + if (this.#allEditors.has(editor.id)) { + const parent = this.#allLayers.get(pageIndex); + if (parent) { + editor._setParentAndPosition(parent, x, y); + } else { + editor.pageIndex = pageIndex; + editor.x = x; + editor.y = y; + } + } + }; + this.addCommands({ + cmd: () => { + for (const [editor, { + newX, + newY, + newPageIndex + }] of map) { + move(editor, newX, newY, newPageIndex); + } + }, + undo: () => { + for (const [editor, { + savedX, + savedY, + savedPageIndex + }] of map) { + move(editor, savedX, savedY, savedPageIndex); + } + }, + mustExec: true + }); + return true; + } + dragSelectedEditors(tx, ty) { + if (!this.#draggingEditors) { + return; + } + for (const editor of this.#draggingEditors.keys()) { + editor.drag(tx, ty); + } + } + rebuild(editor) { + if (editor.parent === null) { + const parent = this.getLayer(editor.pageIndex); + if (parent) { + parent.changeParent(editor); + parent.addOrRebuild(editor); + } else { + this.addEditor(editor); + this.addToAnnotationStorage(editor); + editor.rebuild(); + } + } else { + editor.parent.addOrRebuild(editor); + } + } + get isEditorHandlingKeyboard() { + return this.getActive()?.shouldGetKeyboardEvents() || this.#selectedEditors.size === 1 && this.firstSelectedEditor.shouldGetKeyboardEvents(); + } + isActive(editor) { + return this.#activeEditor === editor; + } + getActive() { + return this.#activeEditor; + } + getMode() { + return this.#mode; + } + isEditingMode() { + return this.#mode !== AnnotationEditorType.NONE; + } + get imageManager() { + return shadow(this, "imageManager", new ImageManager()); + } + getSelectionBoxes(textLayer) { + if (!textLayer) { + return null; + } + const selection = document.getSelection(); + for (let i = 0, ii = selection.rangeCount; i < ii; i++) { + if (!textLayer.contains(selection.getRangeAt(i).commonAncestorContainer)) { + return null; + } + } + const { + x: layerX, + y: layerY, + width: parentWidth, + height: parentHeight + } = textLayer.getBoundingClientRect(); + let rotator; + switch (textLayer.getAttribute("data-main-rotation")) { + case "90": + rotator = (x, y, w, h) => ({ + x: (y - layerY) / parentHeight, + y: 1 - (x + w - layerX) / parentWidth, + width: h / parentHeight, + height: w / parentWidth + }); + break; + case "180": + rotator = (x, y, w, h) => ({ + x: 1 - (x + w - layerX) / parentWidth, + y: 1 - (y + h - layerY) / parentHeight, + width: w / parentWidth, + height: h / parentHeight + }); + break; + case "270": + rotator = (x, y, w, h) => ({ + x: 1 - (y + h - layerY) / parentHeight, + y: (x - layerX) / parentWidth, + width: h / parentHeight, + height: w / parentWidth + }); + break; + default: + rotator = (x, y, w, h) => ({ + x: (x - layerX) / parentWidth, + y: (y - layerY) / parentHeight, + width: w / parentWidth, + height: h / parentHeight + }); + break; + } + const boxes = []; + for (let i = 0, ii = selection.rangeCount; i < ii; i++) { + const range = selection.getRangeAt(i); + if (range.collapsed) { + continue; + } + for (const { + x, + y, + width, + height + } of range.getClientRects()) { + if (width === 0 || height === 0) { + continue; + } + boxes.push(rotator(x, y, width, height)); + } + } + return boxes.length === 0 ? null : boxes; + } + addChangedExistingAnnotation({ + annotationElementId, + id + }) { + (this.#changedExistingAnnotations ||= /* @__PURE__ */ new Map()).set(annotationElementId, id); + } + removeChangedExistingAnnotation({ + annotationElementId + }) { + this.#changedExistingAnnotations?.delete(annotationElementId); + } + renderAnnotationElement(annotation) { + const editorId = this.#changedExistingAnnotations?.get(annotation.data.id); + if (!editorId) { + return; + } + const editor = this.#annotationStorage.getRawValue(editorId); + if (!editor) { + return; + } + if (this.#mode === AnnotationEditorType.NONE && !editor.hasBeenModified) { + return; + } + editor.renderAnnotationElement(annotation); + } + setMissingCanvas(annotationId, annotationElementId, canvas) { + const editor = this.#missingCanvases?.get(annotationId); + if (!editor) { + return; + } + editor.setCanvas(annotationElementId, canvas); + this.#missingCanvases.delete(annotationId); + } + addMissingCanvas(annotationId, editor) { + (this.#missingCanvases ||= /* @__PURE__ */ new Map()).set(annotationId, editor); + } +} +class AltText { + #altText = null; + #altTextDecorative = false; + #altTextButton = null; + #altTextButtonLabel = null; + #altTextTooltip = null; + #altTextTooltipTimeout = null; + #altTextWasFromKeyBoard = false; + #badge = null; + #editor = null; + #guessedText = null; + #textWithDisclaimer = null; + #useNewAltTextFlow = false; + static #l10nNewButton = null; + static _l10n = null; + constructor(editor) { + this.#editor = editor; + this.#useNewAltTextFlow = editor._uiManager.useNewAltTextFlow; + AltText.#l10nNewButton ||= Object.freeze({ + added: "pdfjs-editor-new-alt-text-added-button", + "added-label": "pdfjs-editor-new-alt-text-added-button-label", + missing: "pdfjs-editor-new-alt-text-missing-button", + "missing-label": "pdfjs-editor-new-alt-text-missing-button-label", + review: "pdfjs-editor-new-alt-text-to-review-button", + "review-label": "pdfjs-editor-new-alt-text-to-review-button-label" + }); + } + static initialize(l10n) { + AltText._l10n ??= l10n; + } + async render() { + const altText = this.#altTextButton = document.createElement("button"); + altText.className = "altText"; + altText.tabIndex = "0"; + const label = this.#altTextButtonLabel = document.createElement("span"); + altText.append(label); + if (this.#useNewAltTextFlow) { + altText.classList.add("new"); + altText.setAttribute("data-l10n-id", AltText.#l10nNewButton.missing); + label.setAttribute("data-l10n-id", AltText.#l10nNewButton["missing-label"]); + } else { + altText.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-button"); + label.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-button-label"); + } + const signal = this.#editor._uiManager._signal; + altText.addEventListener("contextmenu", noContextMenu, { + signal + }); + altText.addEventListener("pointerdown", (event) => event.stopPropagation(), { + signal + }); + const onClick = (event) => { + event.preventDefault(); + this.#editor._uiManager.editAltText(this.#editor); + if (this.#useNewAltTextFlow) { + this.#editor._reportTelemetry({ + action: "pdfjs.image.alt_text.image_status_label_clicked", + data: { + label: this.#label + } + }); + } + }; + altText.addEventListener("click", onClick, { + capture: true, + signal + }); + altText.addEventListener("keydown", (event) => { + if (event.target === altText && event.key === "Enter") { + this.#altTextWasFromKeyBoard = true; + onClick(event); + } + }, { + signal + }); + await this.#setState(); + return altText; + } + get #label() { + return this.#altText && "added" || this.#altText === null && this.guessedText && "review" || "missing"; + } + finish() { + if (!this.#altTextButton) { + return; + } + this.#altTextButton.focus({ + focusVisible: this.#altTextWasFromKeyBoard + }); + this.#altTextWasFromKeyBoard = false; + } + isEmpty() { + if (this.#useNewAltTextFlow) { + return this.#altText === null; + } + return !this.#altText && !this.#altTextDecorative; + } + hasData() { + if (this.#useNewAltTextFlow) { + return this.#altText !== null || !!this.#guessedText; + } + return this.isEmpty(); + } + get guessedText() { + return this.#guessedText; + } + async setGuessedText(guessedText) { + if (this.#altText !== null) { + return; + } + this.#guessedText = guessedText; + this.#textWithDisclaimer = await AltText._l10n.get("pdfjs-editor-new-alt-text-generated-alt-text-with-disclaimer", { + generatedAltText: guessedText + }); + this.#setState(); + } + toggleAltTextBadge(visibility = false) { + if (!this.#useNewAltTextFlow || this.#altText) { + this.#badge?.remove(); + this.#badge = null; + return; + } + if (!this.#badge) { + const badge = this.#badge = document.createElement("div"); + badge.className = "noAltTextBadge"; + this.#editor.div.append(badge); + } + this.#badge.classList.toggle("hidden", !visibility); + } + serialize(isForCopying) { + let altText = this.#altText; + if (!isForCopying && this.#guessedText === altText) { + altText = this.#textWithDisclaimer; + } + return { + altText, + decorative: this.#altTextDecorative, + guessedText: this.#guessedText, + textWithDisclaimer: this.#textWithDisclaimer + }; + } + get data() { + return { + altText: this.#altText, + decorative: this.#altTextDecorative + }; + } + set data({ + altText, + decorative, + guessedText, + textWithDisclaimer, + cancel = false + }) { + if (guessedText) { + this.#guessedText = guessedText; + this.#textWithDisclaimer = textWithDisclaimer; + } + if (this.#altText === altText && this.#altTextDecorative === decorative) { + return; + } + if (!cancel) { + this.#altText = altText; + this.#altTextDecorative = decorative; + } + this.#setState(); + } + toggle(enabled = false) { + if (!this.#altTextButton) { + return; + } + if (!enabled && this.#altTextTooltipTimeout) { + clearTimeout(this.#altTextTooltipTimeout); + this.#altTextTooltipTimeout = null; + } + this.#altTextButton.disabled = !enabled; + } + shown() { + this.#editor._reportTelemetry({ + action: "pdfjs.image.alt_text.image_status_label_displayed", + data: { + label: this.#label + } + }); + } + destroy() { + this.#altTextButton?.remove(); + this.#altTextButton = null; + this.#altTextButtonLabel = null; + this.#altTextTooltip = null; + this.#badge?.remove(); + this.#badge = null; + } + async #setState() { + const button = this.#altTextButton; + if (!button) { + return; + } + if (this.#useNewAltTextFlow) { + button.classList.toggle("done", !!this.#altText); + button.setAttribute("data-l10n-id", AltText.#l10nNewButton[this.#label]); + this.#altTextButtonLabel?.setAttribute("data-l10n-id", AltText.#l10nNewButton[`${this.#label}-label`]); + if (!this.#altText) { + this.#altTextTooltip?.remove(); + return; + } + } else { + if (!this.#altText && !this.#altTextDecorative) { + button.classList.remove("done"); + this.#altTextTooltip?.remove(); + return; + } + button.classList.add("done"); + button.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-edit-button"); + } + let tooltip = this.#altTextTooltip; + if (!tooltip) { + this.#altTextTooltip = tooltip = document.createElement("span"); + tooltip.className = "tooltip"; + tooltip.setAttribute("role", "tooltip"); + tooltip.id = `alt-text-tooltip-${this.#editor.id}`; + const DELAY_TO_SHOW_TOOLTIP = 100; + const signal = this.#editor._uiManager._signal; + signal.addEventListener("abort", () => { + clearTimeout(this.#altTextTooltipTimeout); + this.#altTextTooltipTimeout = null; + }, { + once: true + }); + button.addEventListener("mouseenter", () => { + this.#altTextTooltipTimeout = setTimeout(() => { + this.#altTextTooltipTimeout = null; + this.#altTextTooltip.classList.add("show"); + this.#editor._reportTelemetry({ + action: "alt_text_tooltip" + }); + }, DELAY_TO_SHOW_TOOLTIP); + }, { + signal + }); + button.addEventListener("mouseleave", () => { + if (this.#altTextTooltipTimeout) { + clearTimeout(this.#altTextTooltipTimeout); + this.#altTextTooltipTimeout = null; + } + this.#altTextTooltip?.classList.remove("show"); + }, { + signal + }); + } + if (this.#altTextDecorative) { + tooltip.setAttribute("data-l10n-id", "pdfjs-editor-alt-text-decorative-tooltip"); + } else { + tooltip.removeAttribute("data-l10n-id"); + tooltip.textContent = this.#altText; + } + if (!tooltip.parentNode) { + button.append(tooltip); + } + const element = this.#editor.getElementForAltText(); + element?.setAttribute("aria-describedby", tooltip.id); + } +} +class Comment { + #commentStandaloneButton = null; + #commentToolbarButton = null; + #commentWasFromKeyBoard = false; + #editor = null; + #initialText = null; + #richText = null; + #text = null; + #date = null; + #deleted = false; + #popupPosition = null; + constructor(editor) { + this.#editor = editor; + } + renderForToolbar() { + const button = this.#commentToolbarButton = document.createElement("button"); + button.className = "comment"; + return this.#render(button, false); + } + renderForStandalone() { + const button = this.#commentStandaloneButton = document.createElement("button"); + button.className = "annotationCommentButton"; + const position = this.#editor.commentButtonPosition; + if (position) { + const { + style + } = button; + style.insetInlineEnd = `calc(${100 * (this.#editor._uiManager.direction === "ltr" ? 1 - position[0] : position[0])}% - var(--comment-button-dim))`; + style.top = `calc(${100 * position[1]}% - var(--comment-button-dim))`; + const color = this.#editor.commentButtonColor; + if (color) { + style.backgroundColor = color; + } + } + return this.#render(button, true); + } + focusButton() { + setTimeout(() => { + (this.#commentStandaloneButton ?? this.#commentToolbarButton)?.focus(); + }, 0); + } + onUpdatedColor() { + if (!this.#commentStandaloneButton) { + return; + } + const color = this.#editor.commentButtonColor; + if (color) { + this.#commentStandaloneButton.style.backgroundColor = color; + } + this.#editor._uiManager.updatePopupColor(this.#editor); + } + get commentButtonWidth() { + return (this.#commentStandaloneButton?.getBoundingClientRect().width ?? 0) / this.#editor.parent.boundingClientRect.width; + } + get commentPopupPositionInLayer() { + if (this.#popupPosition) { + return this.#popupPosition; + } + if (!this.#commentStandaloneButton) { + return null; + } + const { + x, + y, + height + } = this.#commentStandaloneButton.getBoundingClientRect(); + const { + x: parentX, + y: parentY, + width: parentWidth, + height: parentHeight + } = this.#editor.parent.boundingClientRect; + return [(x - parentX) / parentWidth, (y + height - parentY) / parentHeight]; + } + set commentPopupPositionInLayer(pos) { + this.#popupPosition = pos; + } + hasDefaultPopupPosition() { + return this.#popupPosition === null; + } + removeStandaloneCommentButton() { + this.#commentStandaloneButton?.remove(); + this.#commentStandaloneButton = null; + } + removeToolbarCommentButton() { + this.#commentToolbarButton?.remove(); + this.#commentToolbarButton = null; + } + setCommentButtonStates({ + selected, + hasPopup + }) { + if (!this.#commentStandaloneButton) { + return; + } + this.#commentStandaloneButton.classList.toggle("selected", selected); + this.#commentStandaloneButton.ariaExpanded = hasPopup; + } + #render(comment, isStandalone) { + if (!this.#editor._uiManager.hasCommentManager()) { + return null; + } + comment.tabIndex = "0"; + comment.ariaHasPopup = "dialog"; + if (isStandalone) { + comment.ariaControls = "commentPopup"; + comment.setAttribute("data-l10n-id", "pdfjs-show-comment-button"); + } else { + comment.ariaControlsElements = [this.#editor._uiManager.getCommentDialogElement()]; + comment.setAttribute("data-l10n-id", "pdfjs-editor-edit-comment-button"); + } + const signal = this.#editor._uiManager._signal; + if (!(signal instanceof AbortSignal) || signal.aborted) { + return comment; + } + comment.addEventListener("contextmenu", noContextMenu, { + signal + }); + if (isStandalone) { + comment.addEventListener("focusin", (e) => { + this.#editor._focusEventsAllowed = false; + stopEvent(e); + }, { + capture: true, + signal + }); + comment.addEventListener("focusout", (e) => { + this.#editor._focusEventsAllowed = true; + stopEvent(e); + }, { + capture: true, + signal + }); + } + comment.addEventListener("pointerdown", (event) => event.stopPropagation(), { + signal + }); + const onClick = (event) => { + event.preventDefault(); + if (comment === this.#commentToolbarButton) { + this.edit(); + } else { + this.#editor.toggleComment(true); + } + }; + comment.addEventListener("click", onClick, { + capture: true, + signal + }); + comment.addEventListener("keydown", (event) => { + if (event.target === comment && event.key === "Enter") { + this.#commentWasFromKeyBoard = true; + onClick(event); + } + }, { + signal + }); + comment.addEventListener("pointerenter", () => { + this.#editor.toggleComment(false, true); + }, { + signal + }); + comment.addEventListener("pointerleave", () => { + this.#editor.toggleComment(false, false); + }, { + signal + }); + return comment; + } + edit(options) { + const position = this.commentPopupPositionInLayer; + let posX, posY; + if (position) { + [posX, posY] = position; + } else { + [posX, posY] = this.#editor.commentButtonPosition; + const { + width, + height, + x, + y + } = this.#editor; + posX = x + posX * width; + posY = y + posY * height; + } + const parentDimensions = this.#editor.parent.boundingClientRect; + const { + x: parentX, + y: parentY, + width: parentWidth, + height: parentHeight + } = parentDimensions; + this.#editor._uiManager.editComment(this.#editor, parentX + posX * parentWidth, parentY + posY * parentHeight, { + ...options, + parentDimensions + }); + } + finish() { + if (!this.#commentToolbarButton) { + return; + } + this.#commentToolbarButton.focus({ + focusVisible: this.#commentWasFromKeyBoard + }); + this.#commentWasFromKeyBoard = false; + } + isDeleted() { + return this.#deleted || this.#text === ""; + } + isEmpty() { + return this.#text === null; + } + hasBeenEdited() { + return this.isDeleted() || this.#text !== this.#initialText; + } + serialize() { + return this.data; + } + get data() { + return { + text: this.#text, + richText: this.#richText, + date: this.#date, + deleted: this.isDeleted() + }; + } + set data(text) { + if (text !== this.#text) { + this.#richText = null; + } + if (text === null) { + this.#text = ""; + this.#deleted = true; + return; + } + this.#text = text; + this.#date = /* @__PURE__ */ new Date(); + this.#deleted = false; + } + setInitialText(text, richText = null) { + this.#initialText = text; + this.data = text; + this.#date = null; + this.#richText = richText; + } + shown() { + } + destroy() { + this.#commentToolbarButton?.remove(); + this.#commentToolbarButton = null; + this.#commentStandaloneButton?.remove(); + this.#commentStandaloneButton = null; + this.#text = ""; + this.#richText = null; + this.#date = null; + this.#editor = null; + this.#commentWasFromKeyBoard = false; + this.#deleted = false; + } +} +class TouchManager { + #container; + #isPinching = false; + #isPinchingStopped = null; + #isPinchingDisabled; + #onPinchStart; + #onPinching; + #onPinchEnd; + #pointerDownAC = null; + #signal; + #touchInfo = null; + #touchManagerAC; + #touchMoveAC = null; + constructor({ + container, + isPinchingDisabled = null, + isPinchingStopped = null, + onPinchStart = null, + onPinching = null, + onPinchEnd = null, + signal + }) { + this.#container = container; + this.#isPinchingStopped = isPinchingStopped; + this.#isPinchingDisabled = isPinchingDisabled; + this.#onPinchStart = onPinchStart; + this.#onPinching = onPinching; + this.#onPinchEnd = onPinchEnd; + this.#touchManagerAC = new AbortController(); + this.#signal = AbortSignal.any([signal, this.#touchManagerAC.signal]); + container.addEventListener("touchstart", this.#onTouchStart.bind(this), { + passive: false, + signal: this.#signal + }); + } + get MIN_TOUCH_DISTANCE_TO_PINCH() { + return 35 / OutputScale.pixelRatio; + } + #onTouchStart(evt) { + if (this.#isPinchingDisabled?.()) { + return; + } + if (evt.touches.length === 1) { + if (this.#pointerDownAC) { + return; + } + const pointerDownAC = this.#pointerDownAC = new AbortController(); + const signal = AbortSignal.any([this.#signal, pointerDownAC.signal]); + const container = this.#container; + const opts = { + capture: true, + signal, + passive: false + }; + const cancelPointerDown = (e) => { + if (e.pointerType === "touch") { + this.#pointerDownAC?.abort(); + this.#pointerDownAC = null; + } + }; + container.addEventListener("pointerdown", (e) => { + if (e.pointerType === "touch") { + stopEvent(e); + cancelPointerDown(e); + } + }, opts); + container.addEventListener("pointerup", cancelPointerDown, opts); + container.addEventListener("pointercancel", cancelPointerDown, opts); + return; + } + if (!this.#touchMoveAC) { + this.#touchMoveAC = new AbortController(); + const signal = AbortSignal.any([this.#signal, this.#touchMoveAC.signal]); + const container = this.#container; + const opt = { + signal, + capture: false, + passive: false + }; + container.addEventListener("touchmove", this.#onTouchMove.bind(this), opt); + const onTouchEnd = this.#onTouchEnd.bind(this); + container.addEventListener("touchend", onTouchEnd, opt); + container.addEventListener("touchcancel", onTouchEnd, opt); + opt.capture = true; + container.addEventListener("pointerdown", stopEvent, opt); + container.addEventListener("pointermove", stopEvent, opt); + container.addEventListener("pointercancel", stopEvent, opt); + container.addEventListener("pointerup", stopEvent, opt); + this.#onPinchStart?.(); + } + stopEvent(evt); + if (evt.touches.length !== 2 || this.#isPinchingStopped?.()) { + this.#touchInfo = null; + return; + } + let [touch0, touch1] = evt.touches; + if (touch0.identifier > touch1.identifier) { + [touch0, touch1] = [touch1, touch0]; + } + this.#touchInfo = { + touch0X: touch0.screenX, + touch0Y: touch0.screenY, + touch1X: touch1.screenX, + touch1Y: touch1.screenY + }; + } + #onTouchMove(evt) { + if (!this.#touchInfo || evt.touches.length !== 2) { + return; + } + stopEvent(evt); + let [touch0, touch1] = evt.touches; + if (touch0.identifier > touch1.identifier) { + [touch0, touch1] = [touch1, touch0]; + } + const { + screenX: screen0X, + screenY: screen0Y + } = touch0; + const { + screenX: screen1X, + screenY: screen1Y + } = touch1; + const touchInfo = this.#touchInfo; + const { + touch0X: pTouch0X, + touch0Y: pTouch0Y, + touch1X: pTouch1X, + touch1Y: pTouch1Y + } = touchInfo; + const prevGapX = pTouch1X - pTouch0X; + const prevGapY = pTouch1Y - pTouch0Y; + const currGapX = screen1X - screen0X; + const currGapY = screen1Y - screen0Y; + const distance = Math.hypot(currGapX, currGapY) || 1; + const pDistance = Math.hypot(prevGapX, prevGapY) || 1; + if (!this.#isPinching && Math.abs(pDistance - distance) <= TouchManager.MIN_TOUCH_DISTANCE_TO_PINCH) { + return; + } + touchInfo.touch0X = screen0X; + touchInfo.touch0Y = screen0Y; + touchInfo.touch1X = screen1X; + touchInfo.touch1Y = screen1Y; + if (!this.#isPinching) { + this.#isPinching = true; + return; + } + const origin = [(screen0X + screen1X) / 2, (screen0Y + screen1Y) / 2]; + this.#onPinching?.(origin, pDistance, distance); + } + #onTouchEnd(evt) { + if (evt.touches.length >= 2) { + return; + } + if (this.#touchMoveAC) { + this.#touchMoveAC.abort(); + this.#touchMoveAC = null; + this.#onPinchEnd?.(); + } + if (!this.#touchInfo) { + return; + } + stopEvent(evt); + this.#touchInfo = null; + this.#isPinching = false; + } + destroy() { + this.#touchManagerAC?.abort(); + this.#touchManagerAC = null; + this.#pointerDownAC?.abort(); + this.#pointerDownAC = null; + } +} +class AnnotationEditor { + #accessibilityData = null; + #allResizerDivs = null; + #altText = null; + #comment = null; + #commentStandaloneButton = null; + #disabled = false; + #dragPointerId = null; + #dragPointerType = ""; + #resizersDiv = null; + #lastPointerCoords = null; + #savedDimensions = null; + #fakeAnnotation = null; + #focusAC = null; + #focusedResizerName = ""; + #hasBeenClicked = false; + #initialRect = null; + #isEditing = false; + #isInEditMode = false; + #isResizerEnabledForKeyboard = false; + #moveInDOMTimeout = null; + #prevDragX = 0; + #prevDragY = 0; + #telemetryTimeouts = null; + #touchManager = null; + isSelected = false; + _isCopy = false; + _editToolbar = null; + _initialOptions = /* @__PURE__ */ Object.create(null); + _initialData = null; + _isVisible = true; + _uiManager = null; + _focusEventsAllowed = true; + static _l10n = null; + static _l10nResizer = null; + #isDraggable = false; + #zIndex = AnnotationEditor._zIndex++; + static _borderLineWidth = -1; + static _colorManager = new ColorManager(); + static _zIndex = 1; + static _telemetryTimeout = 1e3; + static get _resizerKeyboardManager() { + const resize = AnnotationEditor.prototype._resizeWithKeyboard; + const small = AnnotationEditorUIManager.TRANSLATE_SMALL; + const big = AnnotationEditorUIManager.TRANSLATE_BIG; + return shadow(this, "_resizerKeyboardManager", new KeyboardManager([[["ArrowLeft", "mac+ArrowLeft"], resize, { + args: [-small, 0] + }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], resize, { + args: [-big, 0] + }], [["ArrowRight", "mac+ArrowRight"], resize, { + args: [small, 0] + }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], resize, { + args: [big, 0] + }], [["ArrowUp", "mac+ArrowUp"], resize, { + args: [0, -small] + }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], resize, { + args: [0, -big] + }], [["ArrowDown", "mac+ArrowDown"], resize, { + args: [0, small] + }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], resize, { + args: [0, big] + }], [["Escape", "mac+Escape"], AnnotationEditor.prototype._stopResizingWithKeyboard]])); + } + constructor(parameters) { + this.parent = parameters.parent; + this.id = parameters.id; + this.width = this.height = null; + this.pageIndex = parameters.parent.pageIndex; + this.name = parameters.name; + this.div = null; + this._uiManager = parameters.uiManager; + this.annotationElementId = null; + this._willKeepAspectRatio = false; + this._initialOptions.isCentered = parameters.isCentered; + this._structTreeParentId = null; + this.annotationElementId = parameters.annotationElementId || null; + this.creationDate = parameters.creationDate || /* @__PURE__ */ new Date(); + this.modificationDate = parameters.modificationDate || null; + const { + rotation, + rawDims: { + pageWidth, + pageHeight, + pageX, + pageY + } + } = this.parent.viewport; + this.rotation = rotation; + this.pageRotation = (360 + rotation - this._uiManager.viewParameters.rotation) % 360; + this.pageDimensions = [pageWidth, pageHeight]; + this.pageTranslation = [pageX, pageY]; + const [width, height] = this.parentDimensions; + this.x = parameters.x / width; + this.y = parameters.y / height; + this.isAttachedToDOM = false; + this.deleted = false; + } + get editorType() { + return Object.getPrototypeOf(this).constructor._type; + } + get mode() { + return Object.getPrototypeOf(this).constructor._editorType; + } + static get isDrawer() { + return false; + } + static get _defaultLineColor() { + return shadow(this, "_defaultLineColor", this._colorManager.getHexCode("CanvasText")); + } + static deleteAnnotationElement(editor) { + const fakeEditor = new FakeEditor({ + id: editor.parent.getNextId(), + parent: editor.parent, + uiManager: editor._uiManager + }); + fakeEditor.annotationElementId = editor.annotationElementId; + fakeEditor.deleted = true; + fakeEditor._uiManager.addToAnnotationStorage(fakeEditor); + } + static initialize(l10n, _uiManager) { + AnnotationEditor._l10n ??= l10n; + AnnotationEditor._l10nResizer ||= Object.freeze({ + topLeft: "pdfjs-editor-resizer-top-left", + topMiddle: "pdfjs-editor-resizer-top-middle", + topRight: "pdfjs-editor-resizer-top-right", + middleRight: "pdfjs-editor-resizer-middle-right", + bottomRight: "pdfjs-editor-resizer-bottom-right", + bottomMiddle: "pdfjs-editor-resizer-bottom-middle", + bottomLeft: "pdfjs-editor-resizer-bottom-left", + middleLeft: "pdfjs-editor-resizer-middle-left" + }); + if (AnnotationEditor._borderLineWidth !== -1) { + return; + } + const style = getComputedStyle(document.documentElement); + AnnotationEditor._borderLineWidth = parseFloat(style.getPropertyValue("--outline-width")) || 0; + } + static updateDefaultParams(_type, _value) { + } + static get defaultPropertiesToUpdate() { + return []; + } + static isHandlingMimeForPasting(mime) { + return false; + } + static paste(item, parent) { + unreachable("Not implemented"); + } + get propertiesToUpdate() { + return []; + } + get _isDraggable() { + return this.#isDraggable; + } + set _isDraggable(value) { + this.#isDraggable = value; + this.div?.classList.toggle("draggable", value); + } + get uid() { + return this.annotationElementId || this.id; + } + get isEnterHandled() { + return true; + } + center() { + const [pageWidth, pageHeight] = this.pageDimensions; + switch (this.parentRotation) { + case 90: + this.x -= this.height * pageHeight / (pageWidth * 2); + this.y += this.width * pageWidth / (pageHeight * 2); + break; + case 180: + this.x += this.width / 2; + this.y += this.height / 2; + break; + case 270: + this.x += this.height * pageHeight / (pageWidth * 2); + this.y -= this.width * pageWidth / (pageHeight * 2); + break; + default: + this.x -= this.width / 2; + this.y -= this.height / 2; + break; + } + this.fixAndSetPosition(); + } + addCommands(params) { + this._uiManager.addCommands(params); + } + get currentLayer() { + return this._uiManager.currentLayer; + } + setInBackground() { + this.div.style.zIndex = 0; + } + setInForeground() { + this.div.style.zIndex = this.#zIndex; + } + setParent(parent) { + if (parent !== null) { + this.pageIndex = parent.pageIndex; + this.pageDimensions = parent.pageDimensions; + } else { + this.#stopResizing(); + this.#fakeAnnotation?.remove(); + this.#fakeAnnotation = null; + } + this.parent = parent; + } + focusin(event) { + if (!this._focusEventsAllowed) { + return; + } + if (!this.#hasBeenClicked) { + this.parent.setSelected(this); + } else { + this.#hasBeenClicked = false; + } + } + focusout(event) { + if (!this._focusEventsAllowed) { + return; + } + if (!this.isAttachedToDOM) { + return; + } + const target = event.relatedTarget; + if (target?.closest(`#${this.id}`)) { + return; + } + event.preventDefault(); + if (!this.parent?.isMultipleSelection) { + this.commitOrRemove(); + } + } + commitOrRemove() { + if (this.isEmpty()) { + this.remove(); + } else { + this.commit(); + } + } + commit() { + if (!this.isInEditMode()) { + return; + } + this.addToAnnotationStorage(); + } + addToAnnotationStorage() { + this._uiManager.addToAnnotationStorage(this); + } + setAt(x, y, tx, ty) { + const [width, height] = this.parentDimensions; + [tx, ty] = this.screenToPageTranslation(tx, ty); + this.x = (x + tx) / width; + this.y = (y + ty) / height; + this.fixAndSetPosition(); + } + _moveAfterPaste(baseX, baseY) { + const [parentWidth, parentHeight] = this.parentDimensions; + this.setAt(baseX * parentWidth, baseY * parentHeight, this.width * parentWidth, this.height * parentHeight); + this._onTranslated(); + } + #translate([width, height], x, y) { + [x, y] = this.screenToPageTranslation(x, y); + this.x += x / width; + this.y += y / height; + this._onTranslating(this.x, this.y); + this.fixAndSetPosition(); + } + translate(x, y) { + this.#translate(this.parentDimensions, x, y); + } + translateInPage(x, y) { + this.#initialRect ||= [this.x, this.y, this.width, this.height]; + this.#translate(this.pageDimensions, x, y); + this.div.scrollIntoView({ + block: "nearest" + }); + } + translationDone() { + this._onTranslated(this.x, this.y); + } + drag(tx, ty) { + this.#initialRect ||= [this.x, this.y, this.width, this.height]; + const { + div, + parentDimensions: [parentWidth, parentHeight] + } = this; + this.x += tx / parentWidth; + this.y += ty / parentHeight; + if (this.parent && (this.x < 0 || this.x > 1 || this.y < 0 || this.y > 1)) { + const { + x: x2, + y: y2 + } = this.div.getBoundingClientRect(); + if (this.parent.findNewParent(this, x2, y2)) { + this.x -= Math.floor(this.x); + this.y -= Math.floor(this.y); + } + } + let { + x, + y + } = this; + const [bx, by] = this.getBaseTranslation(); + x += bx; + y += by; + const { + style + } = div; + style.left = `${(100 * x).toFixed(2)}%`; + style.top = `${(100 * y).toFixed(2)}%`; + this._onTranslating(x, y); + div.scrollIntoView({ + block: "nearest" + }); + } + _onTranslating(x, y) { + } + _onTranslated(x, y) { + } + get _hasBeenMoved() { + return !!this.#initialRect && (this.#initialRect[0] !== this.x || this.#initialRect[1] !== this.y); + } + get _hasBeenResized() { + return !!this.#initialRect && (this.#initialRect[2] !== this.width || this.#initialRect[3] !== this.height); + } + getBaseTranslation() { + const [parentWidth, parentHeight] = this.parentDimensions; + const { + _borderLineWidth + } = AnnotationEditor; + const x = _borderLineWidth / parentWidth; + const y = _borderLineWidth / parentHeight; + switch (this.rotation) { + case 90: + return [-x, y]; + case 180: + return [x, y]; + case 270: + return [x, -y]; + default: + return [-x, -y]; + } + } + get _mustFixPosition() { + return true; + } + fixAndSetPosition(rotation = this.rotation) { + const { + div: { + style + }, + pageDimensions: [pageWidth, pageHeight] + } = this; + let { + x, + y, + width, + height + } = this; + width *= pageWidth; + height *= pageHeight; + x *= pageWidth; + y *= pageHeight; + if (this._mustFixPosition) { + switch (rotation) { + case 0: + x = MathClamp(x, 0, pageWidth - width); + y = MathClamp(y, 0, pageHeight - height); + break; + case 90: + x = MathClamp(x, 0, pageWidth - height); + y = MathClamp(y, width, pageHeight); + break; + case 180: + x = MathClamp(x, width, pageWidth); + y = MathClamp(y, height, pageHeight); + break; + case 270: + x = MathClamp(x, height, pageWidth); + y = MathClamp(y, 0, pageHeight - width); + break; + } + } + this.x = x /= pageWidth; + this.y = y /= pageHeight; + const [bx, by] = this.getBaseTranslation(); + x += bx; + y += by; + style.left = `${(100 * x).toFixed(2)}%`; + style.top = `${(100 * y).toFixed(2)}%`; + this.moveInDOM(); + } + static #rotatePoint(x, y, angle) { + switch (angle) { + case 90: + return [y, -x]; + case 180: + return [-x, -y]; + case 270: + return [-y, x]; + default: + return [x, y]; + } + } + screenToPageTranslation(x, y) { + return AnnotationEditor.#rotatePoint(x, y, this.parentRotation); + } + pageTranslationToScreen(x, y) { + return AnnotationEditor.#rotatePoint(x, y, 360 - this.parentRotation); + } + #getRotationMatrix(rotation) { + switch (rotation) { + case 90: { + const [pageWidth, pageHeight] = this.pageDimensions; + return [0, -pageWidth / pageHeight, pageHeight / pageWidth, 0]; + } + case 180: + return [-1, 0, 0, -1]; + case 270: { + const [pageWidth, pageHeight] = this.pageDimensions; + return [0, pageWidth / pageHeight, -pageHeight / pageWidth, 0]; + } + default: + return [1, 0, 0, 1]; + } + } + get parentScale() { + return this._uiManager.viewParameters.realScale; + } + get parentRotation() { + return (this._uiManager.viewParameters.rotation + this.pageRotation) % 360; + } + get parentDimensions() { + const { + parentScale, + pageDimensions: [pageWidth, pageHeight] + } = this; + return [pageWidth * parentScale, pageHeight * parentScale]; + } + setDims() { + const { + div: { + style + }, + width, + height + } = this; + style.width = `${(100 * width).toFixed(2)}%`; + style.height = `${(100 * height).toFixed(2)}%`; + } + getInitialTranslation() { + return [0, 0]; + } + #createResizers() { + if (this.#resizersDiv) { + return; + } + this.#resizersDiv = document.createElement("div"); + this.#resizersDiv.classList.add("resizers"); + const classes = this._willKeepAspectRatio ? ["topLeft", "topRight", "bottomRight", "bottomLeft"] : ["topLeft", "topMiddle", "topRight", "middleRight", "bottomRight", "bottomMiddle", "bottomLeft", "middleLeft"]; + const signal = this._uiManager._signal; + for (const name of classes) { + const div = document.createElement("div"); + this.#resizersDiv.append(div); + div.classList.add("resizer", name); + div.setAttribute("data-resizer-name", name); + div.addEventListener("pointerdown", this.#resizerPointerdown.bind(this, name), { + signal + }); + div.addEventListener("contextmenu", noContextMenu, { + signal + }); + div.tabIndex = -1; + } + this.div.prepend(this.#resizersDiv); + } + #resizerPointerdown(name, event) { + event.preventDefault(); + const { + isMac + } = util_FeatureTest.platform; + if (event.button !== 0 || event.ctrlKey && isMac) { + return; + } + this.#altText?.toggle(false); + const savedDraggable = this._isDraggable; + this._isDraggable = false; + this.#lastPointerCoords = [event.screenX, event.screenY]; + const ac = new AbortController(); + const signal = this._uiManager.combinedSignal(ac); + this.parent.togglePointerEvents(false); + window.addEventListener("pointermove", this.#resizerPointermove.bind(this, name), { + passive: true, + capture: true, + signal + }); + window.addEventListener("touchmove", stopEvent, { + passive: false, + signal + }); + window.addEventListener("contextmenu", noContextMenu, { + signal + }); + this.#savedDimensions = { + savedX: this.x, + savedY: this.y, + savedWidth: this.width, + savedHeight: this.height + }; + const savedParentCursor = this.parent.div.style.cursor; + const savedCursor = this.div.style.cursor; + this.div.style.cursor = this.parent.div.style.cursor = window.getComputedStyle(event.target).cursor; + const pointerUpCallback = () => { + ac.abort(); + this.parent.togglePointerEvents(true); + this.#altText?.toggle(true); + this._isDraggable = savedDraggable; + this.parent.div.style.cursor = savedParentCursor; + this.div.style.cursor = savedCursor; + this.#addResizeToUndoStack(); + }; + window.addEventListener("pointerup", pointerUpCallback, { + signal + }); + window.addEventListener("blur", pointerUpCallback, { + signal + }); + } + #resize(x, y, width, height) { + this.width = width; + this.height = height; + this.x = x; + this.y = y; + this.setDims(); + this.fixAndSetPosition(); + this._onResized(); + } + _onResized() { + } + #addResizeToUndoStack() { + if (!this.#savedDimensions) { + return; + } + const { + savedX, + savedY, + savedWidth, + savedHeight + } = this.#savedDimensions; + this.#savedDimensions = null; + const newX = this.x; + const newY = this.y; + const newWidth = this.width; + const newHeight = this.height; + if (newX === savedX && newY === savedY && newWidth === savedWidth && newHeight === savedHeight) { + return; + } + this.addCommands({ + cmd: this.#resize.bind(this, newX, newY, newWidth, newHeight), + undo: this.#resize.bind(this, savedX, savedY, savedWidth, savedHeight), + mustExec: true + }); + } + static _round(x) { + return Math.round(x * 1e4) / 1e4; + } + #resizerPointermove(name, event) { + const [parentWidth, parentHeight] = this.parentDimensions; + const savedX = this.x; + const savedY = this.y; + const savedWidth = this.width; + const savedHeight = this.height; + const minWidth = AnnotationEditor.MIN_SIZE / parentWidth; + const minHeight = AnnotationEditor.MIN_SIZE / parentHeight; + const rotationMatrix = this.#getRotationMatrix(this.rotation); + const transf = (x, y) => [rotationMatrix[0] * x + rotationMatrix[2] * y, rotationMatrix[1] * x + rotationMatrix[3] * y]; + const invRotationMatrix = this.#getRotationMatrix(360 - this.rotation); + const invTransf = (x, y) => [invRotationMatrix[0] * x + invRotationMatrix[2] * y, invRotationMatrix[1] * x + invRotationMatrix[3] * y]; + let getPoint; + let getOpposite; + let isDiagonal = false; + let isHorizontal = false; + switch (name) { + case "topLeft": + isDiagonal = true; + getPoint = (w, h) => [0, 0]; + getOpposite = (w, h) => [w, h]; + break; + case "topMiddle": + getPoint = (w, h) => [w / 2, 0]; + getOpposite = (w, h) => [w / 2, h]; + break; + case "topRight": + isDiagonal = true; + getPoint = (w, h) => [w, 0]; + getOpposite = (w, h) => [0, h]; + break; + case "middleRight": + isHorizontal = true; + getPoint = (w, h) => [w, h / 2]; + getOpposite = (w, h) => [0, h / 2]; + break; + case "bottomRight": + isDiagonal = true; + getPoint = (w, h) => [w, h]; + getOpposite = (w, h) => [0, 0]; + break; + case "bottomMiddle": + getPoint = (w, h) => [w / 2, h]; + getOpposite = (w, h) => [w / 2, 0]; + break; + case "bottomLeft": + isDiagonal = true; + getPoint = (w, h) => [0, h]; + getOpposite = (w, h) => [w, 0]; + break; + case "middleLeft": + isHorizontal = true; + getPoint = (w, h) => [0, h / 2]; + getOpposite = (w, h) => [w, h / 2]; + break; + } + const point = getPoint(savedWidth, savedHeight); + const oppositePoint = getOpposite(savedWidth, savedHeight); + let transfOppositePoint = transf(...oppositePoint); + const oppositeX = AnnotationEditor._round(savedX + transfOppositePoint[0]); + const oppositeY = AnnotationEditor._round(savedY + transfOppositePoint[1]); + let ratioX = 1; + let ratioY = 1; + let deltaX, deltaY; + if (!event.fromKeyboard) { + const { + screenX, + screenY + } = event; + const [lastScreenX, lastScreenY] = this.#lastPointerCoords; + [deltaX, deltaY] = this.screenToPageTranslation(screenX - lastScreenX, screenY - lastScreenY); + this.#lastPointerCoords[0] = screenX; + this.#lastPointerCoords[1] = screenY; + } else { + ({ + deltaX, + deltaY + } = event); + } + [deltaX, deltaY] = invTransf(deltaX / parentWidth, deltaY / parentHeight); + if (isDiagonal) { + const oldDiag = Math.hypot(savedWidth, savedHeight); + ratioX = ratioY = Math.max(Math.min(Math.hypot(oppositePoint[0] - point[0] - deltaX, oppositePoint[1] - point[1] - deltaY) / oldDiag, 1 / savedWidth, 1 / savedHeight), minWidth / savedWidth, minHeight / savedHeight); + } else if (isHorizontal) { + ratioX = MathClamp(Math.abs(oppositePoint[0] - point[0] - deltaX), minWidth, 1) / savedWidth; + } else { + ratioY = MathClamp(Math.abs(oppositePoint[1] - point[1] - deltaY), minHeight, 1) / savedHeight; + } + const newWidth = AnnotationEditor._round(savedWidth * ratioX); + const newHeight = AnnotationEditor._round(savedHeight * ratioY); + transfOppositePoint = transf(...getOpposite(newWidth, newHeight)); + const newX = oppositeX - transfOppositePoint[0]; + const newY = oppositeY - transfOppositePoint[1]; + this.#initialRect ||= [this.x, this.y, this.width, this.height]; + this.width = newWidth; + this.height = newHeight; + this.x = newX; + this.y = newY; + this.setDims(); + this.fixAndSetPosition(); + this._onResizing(); + } + _onResizing() { + } + altTextFinish() { + this.#altText?.finish(); + } + get toolbarButtons() { + return null; + } + async addEditToolbar() { + if (this._editToolbar || this.#isInEditMode) { + return this._editToolbar; + } + this._editToolbar = new EditorToolbar(this); + this.div.append(this._editToolbar.render()); + const { + toolbarButtons + } = this; + if (toolbarButtons) { + for (const [name, tool] of toolbarButtons) { + await this._editToolbar.addButton(name, tool); + } + } + if (!this.hasComment) { + this._editToolbar.addButton("comment", this.addCommentButton()); + } + this._editToolbar.addButton("delete"); + return this._editToolbar; + } + addCommentButtonInToolbar() { + this._editToolbar?.addButtonBefore("comment", this.addCommentButton(), ".deleteButton"); + } + removeCommentButtonFromToolbar() { + this._editToolbar?.removeButton("comment"); + } + removeEditToolbar() { + this._editToolbar?.remove(); + this._editToolbar = null; + this.#altText?.destroy(); + } + addContainer(container) { + const editToolbarDiv = this._editToolbar?.div; + if (editToolbarDiv) { + editToolbarDiv.before(container); + } else { + this.div.append(container); + } + } + getClientDimensions() { + return this.div.getBoundingClientRect(); + } + createAltText() { + if (!this.#altText) { + AltText.initialize(AnnotationEditor._l10n); + this.#altText = new AltText(this); + if (this.#accessibilityData) { + this.#altText.data = this.#accessibilityData; + this.#accessibilityData = null; + } + } + return this.#altText; + } + get altTextData() { + return this.#altText?.data; + } + set altTextData(data) { + if (!this.#altText) { + return; + } + this.#altText.data = data; + } + get guessedAltText() { + return this.#altText?.guessedText; + } + async setGuessedAltText(text) { + await this.#altText?.setGuessedText(text); + } + serializeAltText(isForCopying) { + return this.#altText?.serialize(isForCopying); + } + hasAltText() { + return !!this.#altText && !this.#altText.isEmpty(); + } + hasAltTextData() { + return this.#altText?.hasData() ?? false; + } + focusCommentButton() { + this.#comment?.focusButton(); + } + addCommentButton() { + return this.#comment ||= new Comment(this); + } + addStandaloneCommentButton() { + if (this.#commentStandaloneButton) { + if (this._uiManager.isEditingMode()) { + this.#commentStandaloneButton.classList.remove("hidden"); + } + return; + } + if (!this.hasComment) { + return; + } + this.#commentStandaloneButton = this.#comment.renderForStandalone(); + this.div.append(this.#commentStandaloneButton); + } + removeStandaloneCommentButton() { + this.#comment.removeStandaloneCommentButton(); + this.#commentStandaloneButton = null; + } + hideStandaloneCommentButton() { + this.#commentStandaloneButton?.classList.add("hidden"); + } + get comment() { + const { + data: { + richText, + text, + date, + deleted + } + } = this.#comment; + return { + text, + richText, + date, + deleted, + color: this.getNonHCMColor(), + opacity: this.opacity ?? 1 + }; + } + set comment(text) { + this.#comment ||= new Comment(this); + this.#comment.data = text; + if (this.hasComment) { + this.removeCommentButtonFromToolbar(); + this.addStandaloneCommentButton(); + this._uiManager.updateComment(this); + } else { + this.addCommentButtonInToolbar(); + this.removeStandaloneCommentButton(); + this._uiManager.removeComment(this); + } + } + setCommentData({ + comment, + popupRef, + richText + }) { + if (!popupRef) { + return; + } + this.#comment ||= new Comment(this); + this.#comment.setInitialText(comment, richText); + if (!this.annotationElementId) { + return; + } + const storedData = this._uiManager.getAndRemoveDataFromAnnotationStorage(this.annotationElementId); + if (storedData) { + this.updateFromAnnotationLayer(storedData); + } + } + get hasEditedComment() { + return this.#comment?.hasBeenEdited(); + } + get hasDeletedComment() { + return this.#comment?.isDeleted(); + } + get hasComment() { + return !!this.#comment && !this.#comment.isEmpty() && !this.#comment.isDeleted(); + } + async editComment(options) { + this.#comment ||= new Comment(this); + this.#comment.edit(options); + } + toggleComment(isSelected, visibility = void 0) { + if (this.hasComment) { + this._uiManager.toggleComment(this, isSelected, visibility); + } + } + setSelectedCommentButton(selected) { + this.#comment.setSelectedButton(selected); + } + addComment(serialized) { + if (this.hasEditedComment) { + const DEFAULT_POPUP_WIDTH = 180; + const DEFAULT_POPUP_HEIGHT = 100; + const [, , , trY] = serialized.rect; + const [pageWidth] = this.pageDimensions; + const [pageX] = this.pageTranslation; + const blX = pageX + pageWidth + 1; + const blY = trY - DEFAULT_POPUP_HEIGHT; + const trX = blX + DEFAULT_POPUP_WIDTH; + serialized.popup = { + contents: this.comment.text, + deleted: this.comment.deleted, + rect: [blX, blY, trX, trY] + }; + } + } + updateFromAnnotationLayer({ + popup: { + contents, + deleted + } + }) { + this.#comment.data = deleted ? null : contents; + } + get parentBoundingClientRect() { + return this.parent.boundingClientRect; + } + render() { + const div = this.div = document.createElement("div"); + div.setAttribute("data-editor-rotation", (360 - this.rotation) % 360); + div.className = this.name; + div.setAttribute("id", this.id); + div.tabIndex = this.#disabled ? -1 : 0; + div.setAttribute("role", "application"); + if (this.defaultL10nId) { + div.setAttribute("data-l10n-id", this.defaultL10nId); + } + if (!this._isVisible) { + div.classList.add("hidden"); + } + this.setInForeground(); + this.#addFocusListeners(); + const [parentWidth, parentHeight] = this.parentDimensions; + if (this.parentRotation % 180 !== 0) { + div.style.maxWidth = `${(100 * parentHeight / parentWidth).toFixed(2)}%`; + div.style.maxHeight = `${(100 * parentWidth / parentHeight).toFixed(2)}%`; + } + const [tx, ty] = this.getInitialTranslation(); + this.translate(tx, ty); + bindEvents(this, div, ["keydown", "pointerdown", "dblclick"]); + if (this.isResizable && this._uiManager._supportsPinchToZoom) { + this.#touchManager ||= new TouchManager({ + container: div, + isPinchingDisabled: () => !this.isSelected, + onPinchStart: this.#touchPinchStartCallback.bind(this), + onPinching: this.#touchPinchCallback.bind(this), + onPinchEnd: this.#touchPinchEndCallback.bind(this), + signal: this._uiManager._signal + }); + } + this.addStandaloneCommentButton(); + this._uiManager._editorUndoBar?.hide(); + return div; + } + #touchPinchStartCallback() { + this.#savedDimensions = { + savedX: this.x, + savedY: this.y, + savedWidth: this.width, + savedHeight: this.height + }; + this.#altText?.toggle(false); + this.parent.togglePointerEvents(false); + } + #touchPinchCallback(_origin, prevDistance, distance) { + const slowDownFactor = 0.7; + let factor = slowDownFactor * (distance / prevDistance) + 1 - slowDownFactor; + if (factor === 1) { + return; + } + const rotationMatrix = this.#getRotationMatrix(this.rotation); + const transf = (x, y) => [rotationMatrix[0] * x + rotationMatrix[2] * y, rotationMatrix[1] * x + rotationMatrix[3] * y]; + const [parentWidth, parentHeight] = this.parentDimensions; + const savedX = this.x; + const savedY = this.y; + const savedWidth = this.width; + const savedHeight = this.height; + const minWidth = AnnotationEditor.MIN_SIZE / parentWidth; + const minHeight = AnnotationEditor.MIN_SIZE / parentHeight; + factor = Math.max(Math.min(factor, 1 / savedWidth, 1 / savedHeight), minWidth / savedWidth, minHeight / savedHeight); + const newWidth = AnnotationEditor._round(savedWidth * factor); + const newHeight = AnnotationEditor._round(savedHeight * factor); + if (newWidth === savedWidth && newHeight === savedHeight) { + return; + } + this.#initialRect ||= [savedX, savedY, savedWidth, savedHeight]; + const transfCenterPoint = transf(savedWidth / 2, savedHeight / 2); + const centerX = AnnotationEditor._round(savedX + transfCenterPoint[0]); + const centerY = AnnotationEditor._round(savedY + transfCenterPoint[1]); + const newTransfCenterPoint = transf(newWidth / 2, newHeight / 2); + this.x = centerX - newTransfCenterPoint[0]; + this.y = centerY - newTransfCenterPoint[1]; + this.width = newWidth; + this.height = newHeight; + this.setDims(); + this.fixAndSetPosition(); + this._onResizing(); + } + #touchPinchEndCallback() { + this.#altText?.toggle(true); + this.parent.togglePointerEvents(true); + this.#addResizeToUndoStack(); + } + pointerdown(event) { + const { + isMac + } = util_FeatureTest.platform; + if (event.button !== 0 || event.ctrlKey && isMac) { + event.preventDefault(); + return; + } + this.#hasBeenClicked = true; + if (this._isDraggable) { + this.#setUpDragSession(event); + return; + } + this.#selectOnPointerEvent(event); + } + #selectOnPointerEvent(event) { + const { + isMac + } = util_FeatureTest.platform; + if (event.ctrlKey && !isMac || event.shiftKey || event.metaKey && isMac) { + this.parent.toggleSelected(this); + } else { + this.parent.setSelected(this); + } + } + #setUpDragSession(event) { + const { + isSelected + } = this; + this._uiManager.setUpDragSession(); + let hasDraggingStarted = false; + const ac = new AbortController(); + const signal = this._uiManager.combinedSignal(ac); + const opts = { + capture: true, + passive: false, + signal + }; + const cancelDrag = (e) => { + ac.abort(); + this.#dragPointerId = null; + this.#hasBeenClicked = false; + if (!this._uiManager.endDragSession()) { + this.#selectOnPointerEvent(e); + } + if (hasDraggingStarted) { + this._onStopDragging(); + } + }; + if (isSelected) { + this.#prevDragX = event.clientX; + this.#prevDragY = event.clientY; + this.#dragPointerId = event.pointerId; + this.#dragPointerType = event.pointerType; + window.addEventListener("pointermove", (e) => { + if (!hasDraggingStarted) { + hasDraggingStarted = true; + this._uiManager.toggleComment(this, true, false); + this._onStartDragging(); + } + const { + clientX: x, + clientY: y, + pointerId + } = e; + if (pointerId !== this.#dragPointerId) { + stopEvent(e); + return; + } + const [tx, ty] = this.screenToPageTranslation(x - this.#prevDragX, y - this.#prevDragY); + this.#prevDragX = x; + this.#prevDragY = y; + this._uiManager.dragSelectedEditors(tx, ty); + }, opts); + window.addEventListener("touchmove", stopEvent, opts); + window.addEventListener("pointerdown", (e) => { + if (e.pointerType === this.#dragPointerType) { + if (this.#touchManager || e.isPrimary) { + cancelDrag(e); + } + } + stopEvent(e); + }, opts); + } + const pointerUpCallback = (e) => { + if (!this.#dragPointerId || this.#dragPointerId === e.pointerId) { + cancelDrag(e); + return; + } + stopEvent(e); + }; + window.addEventListener("pointerup", pointerUpCallback, { + signal + }); + window.addEventListener("blur", pointerUpCallback, { + signal + }); + } + _onStartDragging() { + } + _onStopDragging() { + } + moveInDOM() { + if (this.#moveInDOMTimeout) { + clearTimeout(this.#moveInDOMTimeout); + } + this.#moveInDOMTimeout = setTimeout(() => { + this.#moveInDOMTimeout = null; + this.parent?.moveEditorInDOM(this); + }, 0); + } + _setParentAndPosition(parent, x, y) { + parent.changeParent(this); + this.x = x; + this.y = y; + this.fixAndSetPosition(); + this._onTranslated(); + } + getRect(tx, ty, rotation = this.rotation) { + const scale = this.parentScale; + const [pageWidth, pageHeight] = this.pageDimensions; + const [pageX, pageY] = this.pageTranslation; + const shiftX = tx / scale; + const shiftY = ty / scale; + const x = this.x * pageWidth; + const y = this.y * pageHeight; + const width = this.width * pageWidth; + const height = this.height * pageHeight; + switch (rotation) { + case 0: + return [x + shiftX + pageX, pageHeight - y - shiftY - height + pageY, x + shiftX + width + pageX, pageHeight - y - shiftY + pageY]; + case 90: + return [x + shiftY + pageX, pageHeight - y + shiftX + pageY, x + shiftY + height + pageX, pageHeight - y + shiftX + width + pageY]; + case 180: + return [x - shiftX - width + pageX, pageHeight - y + shiftY + pageY, x - shiftX + pageX, pageHeight - y + shiftY + height + pageY]; + case 270: + return [x - shiftY - height + pageX, pageHeight - y - shiftX - width + pageY, x - shiftY + pageX, pageHeight - y - shiftX + pageY]; + default: + throw new Error("Invalid rotation"); + } + } + getRectInCurrentCoords(rect, pageHeight) { + const [x1, y1, x2, y2] = rect; + const width = x2 - x1; + const height = y2 - y1; + switch (this.rotation) { + case 0: + return [x1, pageHeight - y2, width, height]; + case 90: + return [x1, pageHeight - y1, height, width]; + case 180: + return [x2, pageHeight - y1, width, height]; + case 270: + return [x2, pageHeight - y2, height, width]; + default: + throw new Error("Invalid rotation"); + } + } + getPDFRect() { + return this.getRect(0, 0); + } + getNonHCMColor() { + return this.color && AnnotationEditor._colorManager.convert(this._uiManager.getNonHCMColor(this.color)); + } + onUpdatedColor() { + this.#comment?.onUpdatedColor(); + } + getData() { + const { + comment: { + text: str, + color, + date, + opacity, + deleted, + richText + }, + uid: id, + pageIndex, + creationDate, + modificationDate + } = this; + return { + id, + pageIndex, + rect: this.getPDFRect(), + richText, + contentsObj: { + str + }, + creationDate, + modificationDate: date || modificationDate, + popupRef: !deleted, + color, + opacity + }; + } + onceAdded(focus) { + } + isEmpty() { + return false; + } + enableEditMode() { + if (this.isInEditMode()) { + return false; + } + this.parent.setEditingState(false); + this.#isInEditMode = true; + return true; + } + disableEditMode() { + if (!this.isInEditMode()) { + return false; + } + this.parent.setEditingState(true); + this.#isInEditMode = false; + return true; + } + isInEditMode() { + return this.#isInEditMode; + } + shouldGetKeyboardEvents() { + return this.#isResizerEnabledForKeyboard; + } + needsToBeRebuilt() { + return this.div && !this.isAttachedToDOM; + } + get isOnScreen() { + const { + top, + left, + bottom, + right + } = this.getClientDimensions(); + const { + innerHeight, + innerWidth + } = window; + return left < innerWidth && right > 0 && top < innerHeight && bottom > 0; + } + #addFocusListeners() { + if (this.#focusAC || !this.div) { + return; + } + this.#focusAC = new AbortController(); + const signal = this._uiManager.combinedSignal(this.#focusAC); + this.div.addEventListener("focusin", this.focusin.bind(this), { + signal + }); + this.div.addEventListener("focusout", this.focusout.bind(this), { + signal + }); + } + rebuild() { + this.#addFocusListeners(); + } + rotate(_angle) { + } + resize() { + } + serializeDeleted() { + return { + id: this.annotationElementId, + deleted: true, + pageIndex: this.pageIndex, + popupRef: this._initialData?.popupRef || "" + }; + } + serialize(isForCopying = false, context = null) { + return { + annotationType: this.mode, + pageIndex: this.pageIndex, + rect: this.getPDFRect(), + rotation: this.rotation, + structTreeParentId: this._structTreeParentId, + popupRef: this._initialData?.popupRef || "" + }; + } + static async deserialize(data, parent, uiManager) { + const editor = new this.prototype.constructor({ + parent, + id: parent.getNextId(), + uiManager, + annotationElementId: data.annotationElementId, + creationDate: data.creationDate, + modificationDate: data.modificationDate + }); + editor.rotation = data.rotation; + editor.#accessibilityData = data.accessibilityData; + editor._isCopy = data.isCopy || false; + const [pageWidth, pageHeight] = editor.pageDimensions; + const [x, y, width, height] = editor.getRectInCurrentCoords(data.rect, pageHeight); + editor.x = x / pageWidth; + editor.y = y / pageHeight; + editor.width = width / pageWidth; + editor.height = height / pageHeight; + return editor; + } + get hasBeenModified() { + return !!this.annotationElementId && (this.deleted || this.serialize() !== null); + } + remove() { + this.#focusAC?.abort(); + this.#focusAC = null; + if (!this.isEmpty()) { + this.commit(); + } + if (this.parent) { + this.parent.remove(this); + } else { + this._uiManager.removeEditor(this); + } + if (this.#moveInDOMTimeout) { + clearTimeout(this.#moveInDOMTimeout); + this.#moveInDOMTimeout = null; + } + this.#stopResizing(); + this.removeEditToolbar(); + if (this.#telemetryTimeouts) { + for (const timeout of this.#telemetryTimeouts.values()) { + clearTimeout(timeout); + } + this.#telemetryTimeouts = null; + } + this.parent = null; + this.#touchManager?.destroy(); + this.#touchManager = null; + } + get isResizable() { + return false; + } + makeResizable() { + if (this.isResizable) { + this.#createResizers(); + this.#resizersDiv.classList.remove("hidden"); + } + } + get toolbarPosition() { + return null; + } + get commentButtonPosition() { + return this._uiManager.direction === "ltr" ? [1, 0] : [0, 0]; + } + get commentButtonPositionInPage() { + const { + commentButtonPosition: [posX, posY] + } = this; + const [blX, blY, trX, trY] = this.getPDFRect(); + return [AnnotationEditor._round(blX + (trX - blX) * posX), AnnotationEditor._round(blY + (trY - blY) * (1 - posY))]; + } + get commentButtonColor() { + return this._uiManager.makeCommentColor(this.getNonHCMColor(), this.opacity); + } + get commentPopupPosition() { + return this.#comment.commentPopupPositionInLayer; + } + set commentPopupPosition(pos) { + this.#comment.commentPopupPositionInLayer = pos; + } + hasDefaultPopupPosition() { + return this.#comment.hasDefaultPopupPosition(); + } + get commentButtonWidth() { + return this.#comment.commentButtonWidth; + } + get elementBeforePopup() { + return this.div; + } + setCommentButtonStates(options) { + this.#comment.setCommentButtonStates(options); + } + keydown(event) { + if (!this.isResizable || event.target !== this.div || event.key !== "Enter") { + return; + } + this._uiManager.setSelected(this); + this.#savedDimensions = { + savedX: this.x, + savedY: this.y, + savedWidth: this.width, + savedHeight: this.height + }; + const children = this.#resizersDiv.children; + if (!this.#allResizerDivs) { + this.#allResizerDivs = Array.from(children); + const boundResizerKeydown = this.#resizerKeydown.bind(this); + const boundResizerBlur = this.#resizerBlur.bind(this); + const signal = this._uiManager._signal; + for (const div of this.#allResizerDivs) { + const name = div.getAttribute("data-resizer-name"); + div.setAttribute("role", "spinbutton"); + div.addEventListener("keydown", boundResizerKeydown, { + signal + }); + div.addEventListener("blur", boundResizerBlur, { + signal + }); + div.addEventListener("focus", this.#resizerFocus.bind(this, name), { + signal + }); + div.setAttribute("data-l10n-id", AnnotationEditor._l10nResizer[name]); + } + } + const first = this.#allResizerDivs[0]; + let firstPosition = 0; + for (const div of children) { + if (div === first) { + break; + } + firstPosition++; + } + const nextFirstPosition = (360 - this.rotation + this.parentRotation) % 360 / 90 * (this.#allResizerDivs.length / 4); + if (nextFirstPosition !== firstPosition) { + if (nextFirstPosition < firstPosition) { + for (let i2 = 0; i2 < firstPosition - nextFirstPosition; i2++) { + this.#resizersDiv.append(this.#resizersDiv.firstChild); + } + } else if (nextFirstPosition > firstPosition) { + for (let i2 = 0; i2 < nextFirstPosition - firstPosition; i2++) { + this.#resizersDiv.firstChild.before(this.#resizersDiv.lastChild); + } + } + let i = 0; + for (const child of children) { + const div = this.#allResizerDivs[i++]; + const name = div.getAttribute("data-resizer-name"); + child.setAttribute("data-l10n-id", AnnotationEditor._l10nResizer[name]); + } + } + this.#setResizerTabIndex(0); + this.#isResizerEnabledForKeyboard = true; + this.#resizersDiv.firstChild.focus({ + focusVisible: true + }); + event.preventDefault(); + event.stopImmediatePropagation(); + } + #resizerKeydown(event) { + AnnotationEditor._resizerKeyboardManager.exec(this, event); + } + #resizerBlur(event) { + if (this.#isResizerEnabledForKeyboard && event.relatedTarget?.parentNode !== this.#resizersDiv) { + this.#stopResizing(); + } + } + #resizerFocus(name) { + this.#focusedResizerName = this.#isResizerEnabledForKeyboard ? name : ""; + } + #setResizerTabIndex(value) { + if (!this.#allResizerDivs) { + return; + } + for (const div of this.#allResizerDivs) { + div.tabIndex = value; + } + } + _resizeWithKeyboard(x, y) { + if (!this.#isResizerEnabledForKeyboard) { + return; + } + this.#resizerPointermove(this.#focusedResizerName, { + deltaX: x, + deltaY: y, + fromKeyboard: true + }); + } + #stopResizing() { + this.#isResizerEnabledForKeyboard = false; + this.#setResizerTabIndex(-1); + this.#addResizeToUndoStack(); + } + _stopResizingWithKeyboard() { + this.#stopResizing(); + this.div.focus(); + } + select() { + if (this.isSelected && this._editToolbar) { + this._editToolbar.show(); + return; + } + this.isSelected = true; + this.makeResizable(); + this.div?.classList.add("selectedEditor"); + if (!this._editToolbar) { + this.addEditToolbar().then(() => { + if (this.div?.classList.contains("selectedEditor")) { + this._editToolbar?.show(); + } + }); + return; + } + this._editToolbar?.show(); + this.#altText?.toggleAltTextBadge(false); + } + focus() { + if (this.div && !this.div.contains(document.activeElement)) { + setTimeout(() => this.div?.focus({ + preventScroll: true + }), 0); + } + } + unselect() { + if (!this.isSelected) { + return; + } + this.isSelected = false; + this.#resizersDiv?.classList.add("hidden"); + this.div?.classList.remove("selectedEditor"); + if (this.div?.contains(document.activeElement)) { + this._uiManager.currentLayer.div.focus({ + preventScroll: true + }); + } + this._editToolbar?.hide(); + this.#altText?.toggleAltTextBadge(true); + if (this.hasComment) { + this._uiManager.toggleComment(this, false, false); + } + } + updateParams(type, value) { + } + disableEditing() { + } + enableEditing() { + } + get canChangeContent() { + return false; + } + enterInEditMode() { + if (!this.canChangeContent) { + return; + } + this.enableEditMode(); + this.div.focus(); + } + dblclick(event) { + if (event.target.nodeName === "BUTTON") { + return; + } + this.enterInEditMode(); + this.parent.updateToolbar({ + mode: this.constructor._editorType, + editId: this.id + }); + } + getElementForAltText() { + return this.div; + } + get contentDiv() { + return this.div; + } + get isEditing() { + return this.#isEditing; + } + set isEditing(value) { + this.#isEditing = value; + if (!this.parent) { + return; + } + if (value) { + this.parent.setSelected(this); + this.parent.setActiveEditor(this); + } else { + this.parent.setActiveEditor(null); + } + } + static get MIN_SIZE() { + return 16; + } + static canCreateNewEmptyEditor() { + return true; + } + get telemetryInitialData() { + return { + action: "added" + }; + } + get telemetryFinalData() { + return null; + } + _reportTelemetry(data, mustWait = false) { + if (mustWait) { + this.#telemetryTimeouts ||= /* @__PURE__ */ new Map(); + const { + action + } = data; + let timeout = this.#telemetryTimeouts.get(action); + if (timeout) { + clearTimeout(timeout); + } + timeout = setTimeout(() => { + this._reportTelemetry(data); + this.#telemetryTimeouts.delete(action); + if (this.#telemetryTimeouts.size === 0) { + this.#telemetryTimeouts = null; + } + }, AnnotationEditor._telemetryTimeout); + this.#telemetryTimeouts.set(action, timeout); + return; + } + data.type ||= this.editorType; + this._uiManager._eventBus.dispatch("reporttelemetry", { + source: this, + details: { + type: "editing", + data + } + }); + } + show(visible = this._isVisible) { + this.div.classList.toggle("hidden", !visible); + this._isVisible = visible; + } + enable() { + if (this.div) { + this.div.tabIndex = 0; + } + this.#disabled = false; + } + disable() { + if (this.div) { + this.div.tabIndex = -1; + } + this.#disabled = true; + } + updateFakeAnnotationElement(annotationLayer) { + if (!this.#fakeAnnotation && !this.deleted) { + this.#fakeAnnotation = annotationLayer.addFakeAnnotation(this); + return; + } + if (this.deleted) { + this.#fakeAnnotation.remove(); + this.#fakeAnnotation = null; + return; + } + if (this.hasEditedComment || this._hasBeenMoved || this._hasBeenResized) { + this.#fakeAnnotation.updateEdited({ + rect: this.getPDFRect(), + popup: this.comment + }); + } + } + renderAnnotationElement(annotation) { + if (this.deleted) { + annotation.hide(); + return null; + } + let content = annotation.container.querySelector(".annotationContent"); + if (!content) { + content = document.createElement("div"); + content.classList.add("annotationContent", this.editorType); + annotation.container.prepend(content); + } else if (content.nodeName === "CANVAS") { + const canvas = content; + content = document.createElement("div"); + content.classList.add("annotationContent", this.editorType); + canvas.before(content); + } + return content; + } + resetAnnotationElement(annotation) { + const { + firstChild + } = annotation.container; + if (firstChild?.nodeName === "DIV" && firstChild.classList.contains("annotationContent")) { + firstChild.remove(); + } + } +} +class FakeEditor extends AnnotationEditor { + constructor(params) { + super(params); + this.annotationElementId = params.annotationElementId; + this.deleted = true; + } + serialize() { + return this.serializeDeleted(); + } +} +const SEED = 3285377520; +const MASK_HIGH = 4294901760; +const MASK_LOW = 65535; +class MurmurHash3_64 { + constructor(seed) { + this.h1 = seed ? seed & 4294967295 : SEED; + this.h2 = seed ? seed & 4294967295 : SEED; + } + update(input) { + let data, length; + if (typeof input === "string") { + data = new Uint8Array(input.length * 2); + length = 0; + for (let i = 0, ii = input.length; i < ii; i++) { + const code = input.charCodeAt(i); + if (code <= 255) { + data[length++] = code; + } else { + data[length++] = code >>> 8; + data[length++] = code & 255; + } + } + } else if (ArrayBuffer.isView(input)) { + data = input.slice(); + length = data.byteLength; + } else { + throw new Error("Invalid data format, must be a string or TypedArray."); + } + const blockCounts = length >> 2; + const tailLength = length - blockCounts * 4; + const dataUint32 = new Uint32Array(data.buffer, 0, blockCounts); + let k1 = 0, k2 = 0; + let h1 = this.h1, h2 = this.h2; + const C1 = 3432918353, C2 = 461845907; + const C1_LOW = C1 & MASK_LOW, C2_LOW = C2 & MASK_LOW; + for (let i = 0; i < blockCounts; i++) { + if (i & 1) { + k1 = dataUint32[i]; + k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW; + k1 = k1 << 15 | k1 >>> 17; + k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW; + h1 ^= k1; + h1 = h1 << 13 | h1 >>> 19; + h1 = h1 * 5 + 3864292196; + } else { + k2 = dataUint32[i]; + k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW; + k2 = k2 << 15 | k2 >>> 17; + k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW; + h2 ^= k2; + h2 = h2 << 13 | h2 >>> 19; + h2 = h2 * 5 + 3864292196; + } + } + k1 = 0; + switch (tailLength) { + case 3: + k1 ^= data[blockCounts * 4 + 2] << 16; + case 2: + k1 ^= data[blockCounts * 4 + 1] << 8; + case 1: + k1 ^= data[blockCounts * 4]; + k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW; + k1 = k1 << 15 | k1 >>> 17; + k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW; + if (blockCounts & 1) { + h1 ^= k1; + } else { + h2 ^= k1; + } + } + this.h1 = h1; + this.h2 = h2; + } + hexdigest() { + let h1 = this.h1, h2 = this.h2; + h1 ^= h2 >>> 1; + h1 = h1 * 3981806797 & MASK_HIGH | h1 * 36045 & MASK_LOW; + h2 = h2 * 4283543511 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 2950163797 & MASK_HIGH) >>> 16; + h1 ^= h2 >>> 1; + h1 = h1 * 444984403 & MASK_HIGH | h1 * 60499 & MASK_LOW; + h2 = h2 * 3301882366 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 3120437893 & MASK_HIGH) >>> 16; + h1 ^= h2 >>> 1; + return (h1 >>> 0).toString(16).padStart(8, "0") + (h2 >>> 0).toString(16).padStart(8, "0"); + } +} +const SerializableEmpty = Object.freeze({ + map: null, + hash: "", + transfer: void 0 +}); +class AnnotationStorage { + #modified = false; + #modifiedIds = null; + #editorsMap = null; + #storage = /* @__PURE__ */ new Map(); + constructor() { + this.onSetModified = null; + this.onResetModified = null; + this.onAnnotationEditor = null; + } + getValue(key, defaultValue) { + const value = this.#storage.get(key); + if (value === void 0) { + return defaultValue; + } + return Object.assign(defaultValue, value); + } + getRawValue(key) { + return this.#storage.get(key); + } + remove(key) { + const storedValue = this.#storage.get(key); + if (storedValue === void 0) { + return; + } + if (storedValue instanceof AnnotationEditor) { + this.#editorsMap.delete(storedValue.annotationElementId); + } + this.#storage.delete(key); + if (this.#storage.size === 0) { + this.resetModified(); + } + if (typeof this.onAnnotationEditor === "function") { + for (const value of this.#storage.values()) { + if (value instanceof AnnotationEditor) { + return; + } + } + this.onAnnotationEditor(null); + } + } + setValue(key, value) { + const obj = this.#storage.get(key); + let modified = false; + if (obj !== void 0) { + for (const [entry, val] of Object.entries(value)) { + if (obj[entry] !== val) { + modified = true; + obj[entry] = val; + } + } + } else { + modified = true; + this.#storage.set(key, value); + } + if (modified) { + this.#setModified(); + } + if (value instanceof AnnotationEditor) { + (this.#editorsMap ||= /* @__PURE__ */ new Map()).set(value.annotationElementId, value); + if (typeof this.onAnnotationEditor === "function") { + this.onAnnotationEditor(value.constructor._type); + } + } + } + has(key) { + return this.#storage.has(key); + } + get size() { + return this.#storage.size; + } + #setModified() { + if (!this.#modified) { + this.#modified = true; + if (typeof this.onSetModified === "function") { + this.onSetModified(); + } + } + } + resetModified() { + if (this.#modified) { + this.#modified = false; + if (typeof this.onResetModified === "function") { + this.onResetModified(); + } + } + } + get print() { + return new PrintAnnotationStorage(this); + } + get serializable() { + if (this.#storage.size === 0) { + return SerializableEmpty; + } + const map = /* @__PURE__ */ new Map(), hash = new MurmurHash3_64(), transfer = []; + const context = /* @__PURE__ */ Object.create(null); + let hasBitmap = false; + for (const [key, val] of this.#storage) { + const serialized = val instanceof AnnotationEditor ? val.serialize(false, context) : val; + if (serialized) { + map.set(key, serialized); + hash.update(`${key}:${JSON.stringify(serialized)}`); + hasBitmap ||= !!serialized.bitmap; + } + } + if (hasBitmap) { + for (const value of map.values()) { + if (value.bitmap) { + transfer.push(value.bitmap); + } + } + } + return map.size > 0 ? { + map, + hash: hash.hexdigest(), + transfer + } : SerializableEmpty; + } + get editorStats() { + let stats = null; + const typeToEditor = /* @__PURE__ */ new Map(); + let numberOfEditedComments = 0; + let numberOfDeletedComments = 0; + for (const value of this.#storage.values()) { + if (!(value instanceof AnnotationEditor)) { + if (value.popup) { + if (value.popup.deleted) { + numberOfDeletedComments += 1; + } else { + numberOfEditedComments += 1; + } + } + continue; + } + if (value.isCommentDeleted) { + numberOfDeletedComments += 1; + } else if (value.hasEditedComment) { + numberOfEditedComments += 1; + } + const editorStats = value.telemetryFinalData; + if (!editorStats) { + continue; + } + const { + type + } = editorStats; + if (!typeToEditor.has(type)) { + typeToEditor.set(type, Object.getPrototypeOf(value).constructor); + } + stats ||= /* @__PURE__ */ Object.create(null); + const map = stats[type] ||= /* @__PURE__ */ new Map(); + for (const [key, val] of Object.entries(editorStats)) { + if (key === "type") { + continue; + } + let counters = map.get(key); + if (!counters) { + counters = /* @__PURE__ */ new Map(); + map.set(key, counters); + } + const count = counters.get(val) ?? 0; + counters.set(val, count + 1); + } + } + if (numberOfDeletedComments > 0 || numberOfEditedComments > 0) { + stats ||= /* @__PURE__ */ Object.create(null); + stats.comments = { + deleted: numberOfDeletedComments, + edited: numberOfEditedComments + }; + } + if (!stats) { + return null; + } + for (const [type, editor] of typeToEditor) { + stats[type] = editor.computeTelemetryFinalData(stats[type]); + } + return stats; + } + resetModifiedIds() { + this.#modifiedIds = null; + } + updateEditor(annotationId, data) { + const value = this.#editorsMap?.get(annotationId); + if (value) { + value.updateFromAnnotationLayer(data); + return true; + } + return false; + } + getEditor(annotationId) { + return this.#editorsMap?.get(annotationId) || null; + } + get modifiedIds() { + if (this.#modifiedIds) { + return this.#modifiedIds; + } + const ids = []; + if (this.#editorsMap) { + for (const value of this.#editorsMap.values()) { + if (!value.serialize()) { + continue; + } + ids.push(value.annotationElementId); + } + } + return this.#modifiedIds = { + ids: new Set(ids), + hash: ids.join(",") + }; + } + [Symbol.iterator]() { + return this.#storage.entries(); + } +} +class PrintAnnotationStorage extends AnnotationStorage { + #serializable; + constructor(parent) { + super(); + const { + map, + hash, + transfer + } = parent.serializable; + const clone = structuredClone(map, transfer ? { + transfer + } : null); + this.#serializable = { + map: clone, + hash, + transfer + }; + } + get print() { + unreachable("Should not call PrintAnnotationStorage.print"); + } + get serializable() { + return this.#serializable; + } + get modifiedIds() { + return shadow(this, "modifiedIds", { + ids: /* @__PURE__ */ new Set(), + hash: "" + }); + } +} +class FontLoader { + #systemFonts = /* @__PURE__ */ new Set(); + constructor({ + ownerDocument = globalThis.document, + styleElement = null + }) { + this._document = ownerDocument; + this.nativeFontFaces = /* @__PURE__ */ new Set(); + this.styleElement = null; + this.loadingRequests = []; + this.loadTestFontId = 0; + } + addNativeFontFace(nativeFontFace) { + this.nativeFontFaces.add(nativeFontFace); + this._document.fonts.add(nativeFontFace); + } + removeNativeFontFace(nativeFontFace) { + this.nativeFontFaces.delete(nativeFontFace); + this._document.fonts.delete(nativeFontFace); + } + insertRule(rule) { + if (!this.styleElement) { + this.styleElement = this._document.createElement("style"); + this._document.documentElement.getElementsByTagName("head")[0].append(this.styleElement); + } + const styleSheet = this.styleElement.sheet; + styleSheet.insertRule(rule, styleSheet.cssRules.length); + } + clear() { + for (const nativeFontFace of this.nativeFontFaces) { + this._document.fonts.delete(nativeFontFace); + } + this.nativeFontFaces.clear(); + this.#systemFonts.clear(); + if (this.styleElement) { + this.styleElement.remove(); + this.styleElement = null; + } + } + async loadSystemFont({ + systemFontInfo: info2, + disableFontFace, + _inspectFont + }) { + if (!info2 || this.#systemFonts.has(info2.loadedName)) { + return; + } + assert(!disableFontFace, "loadSystemFont shouldn't be called when `disableFontFace` is set."); + if (this.isFontLoadingAPISupported) { + const { + loadedName, + src, + style + } = info2; + const fontFace = new FontFace(loadedName, src, style); + this.addNativeFontFace(fontFace); + try { + await fontFace.load(); + this.#systemFonts.add(loadedName); + _inspectFont?.(info2); + } catch { + warn(`Cannot load system font: ${info2.baseFontName}, installing it could help to improve PDF rendering.`); + this.removeNativeFontFace(fontFace); + } + return; + } + unreachable("Not implemented: loadSystemFont without the Font Loading API."); + } + async bind(font) { + if (font.attached || font.missingFile && !font.systemFontInfo) { + return; + } + font.attached = true; + if (font.systemFontInfo) { + await this.loadSystemFont(font); + return; + } + if (this.isFontLoadingAPISupported) { + const nativeFontFace = font.createNativeFontFace(); + if (nativeFontFace) { + this.addNativeFontFace(nativeFontFace); + try { + await nativeFontFace.loaded; + } catch (ex) { + warn(`Failed to load font '${nativeFontFace.family}': '${ex}'.`); + font.disableFontFace = true; + throw ex; + } + } + return; + } + const rule = font.createFontFaceRule(); + if (rule) { + this.insertRule(rule); + if (this.isSyncFontLoadingSupported) { + return; + } + await new Promise((resolve) => { + const request = this._queueLoadingCallback(resolve); + this._prepareFontLoadEvent(font, request); + }); + } + } + get isFontLoadingAPISupported() { + const hasFonts = !!this._document?.fonts; + return shadow(this, "isFontLoadingAPISupported", hasFonts); + } + get isSyncFontLoadingSupported() { + return shadow(this, "isSyncFontLoadingSupported", isNodeJS || util_FeatureTest.platform.isFirefox); + } + _queueLoadingCallback(callback) { + function completeRequest() { + assert(!request.done, "completeRequest() cannot be called twice."); + request.done = true; + while (loadingRequests.length > 0 && loadingRequests[0].done) { + const otherRequest = loadingRequests.shift(); + setTimeout(otherRequest.callback, 0); + } + } + const { + loadingRequests + } = this; + const request = { + done: false, + complete: completeRequest, + callback + }; + loadingRequests.push(request); + return request; + } + get _loadTestFont() { + const testFont = atob("T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQAFQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAAALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgAAAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACMAooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4DIP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAAAAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUAAQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgABAAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABYAAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAAAC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAAAAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQACAQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTjFQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA=="); + return shadow(this, "_loadTestFont", testFont); + } + _prepareFontLoadEvent(font, request) { + function int32(data2, offset) { + return data2.charCodeAt(offset) << 24 | data2.charCodeAt(offset + 1) << 16 | data2.charCodeAt(offset + 2) << 8 | data2.charCodeAt(offset + 3) & 255; + } + function spliceString(s, offset, remove, insert) { + const chunk1 = s.substring(0, offset); + const chunk2 = s.substring(offset + remove); + return chunk1 + insert + chunk2; + } + let i, ii; + const canvas = this._document.createElement("canvas"); + canvas.width = 1; + canvas.height = 1; + const ctx = canvas.getContext("2d"); + let called = 0; + function isFontReady(name, callback) { + if (++called > 30) { + warn("Load test font never loaded."); + callback(); + return; + } + ctx.font = "30px " + name; + ctx.fillText(".", 0, 20); + const imageData = ctx.getImageData(0, 0, 1, 1); + if (imageData.data[3] > 0) { + callback(); + return; + } + setTimeout(isFontReady.bind(null, name, callback)); + } + const loadTestFontId = `lt${Date.now()}${this.loadTestFontId++}`; + let data = this._loadTestFont; + const COMMENT_OFFSET = 976; + data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length, loadTestFontId); + const CFF_CHECKSUM_OFFSET = 16; + const XXXX_VALUE = 1482184792; + let checksum = int32(data, CFF_CHECKSUM_OFFSET); + for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) { + checksum = checksum - XXXX_VALUE + int32(loadTestFontId, i) | 0; + } + if (i < loadTestFontId.length) { + checksum = checksum - XXXX_VALUE + int32(loadTestFontId + "XXX", i) | 0; + } + data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, string32(checksum)); + const url = `url(data:font/opentype;base64,${btoa(data)});`; + const rule = `@font-face {font-family:"${loadTestFontId}";src:${url}}`; + this.insertRule(rule); + const div = this._document.createElement("div"); + div.style.visibility = "hidden"; + div.style.width = div.style.height = "10px"; + div.style.position = "absolute"; + div.style.top = div.style.left = "0px"; + for (const name of [font.loadedName, loadTestFontId]) { + const span = this._document.createElement("span"); + span.textContent = "Hi"; + span.style.fontFamily = name; + div.append(span); + } + this._document.body.append(div); + isFontReady(loadTestFontId, () => { + div.remove(); + request.complete(); + }); + } +} +class FontFaceObject { + #fontData; + constructor(translatedData, inspectFont = null, extra, charProcOperatorList) { + this.compiledGlyphs = /* @__PURE__ */ Object.create(null); + this.#fontData = translatedData; + this._inspectFont = inspectFont; + if (extra) { + Object.assign(this, extra); + } + if (charProcOperatorList) { + this.charProcOperatorList = charProcOperatorList; + } + } + createNativeFontFace() { + if (!this.data || this.disableFontFace) { + return null; + } + let nativeFontFace; + if (!this.cssFontInfo) { + nativeFontFace = new FontFace(this.loadedName, this.data, {}); + } else { + const css = { + weight: this.cssFontInfo.fontWeight + }; + if (this.cssFontInfo.italicAngle) { + css.style = `oblique ${this.cssFontInfo.italicAngle}deg`; + } + nativeFontFace = new FontFace(this.cssFontInfo.fontFamily, this.data, css); + } + this._inspectFont?.(this); + return nativeFontFace; + } + createFontFaceRule() { + if (!this.data || this.disableFontFace) { + return null; + } + const url = `url(data:${this.mimetype};base64,${toBase64Util(this.data)});`; + let rule; + if (!this.cssFontInfo) { + rule = `@font-face {font-family:"${this.loadedName}";src:${url}}`; + } else { + let css = `font-weight: ${this.cssFontInfo.fontWeight};`; + if (this.cssFontInfo.italicAngle) { + css += `font-style: oblique ${this.cssFontInfo.italicAngle}deg;`; + } + rule = `@font-face {font-family:"${this.cssFontInfo.fontFamily}";${css}src:${url}}`; + } + this._inspectFont?.(this, url); + return rule; + } + getPathGenerator(objs, character) { + if (this.compiledGlyphs[character] !== void 0) { + return this.compiledGlyphs[character]; + } + const objId = this.loadedName + "_path_" + character; + let cmds; + try { + cmds = objs.get(objId); + } catch (ex) { + warn(`getPathGenerator - ignoring character: "${ex}".`); + } + const path = new Path2D(cmds || ""); + if (!this.fontExtraProperties) { + objs.delete(objId); + } + return this.compiledGlyphs[character] = path; + } + get black() { + return this.#fontData.black; + } + get bold() { + return this.#fontData.bold; + } + get disableFontFace() { + return this.#fontData.disableFontFace ?? false; + } + get fontExtraProperties() { + return this.#fontData.fontExtraProperties ?? false; + } + get isInvalidPDFjsFont() { + return this.#fontData.isInvalidPDFjsFont; + } + get isType3Font() { + return this.#fontData.isType3Font; + } + get italic() { + return this.#fontData.italic; + } + get missingFile() { + return this.#fontData.missingFile; + } + get remeasure() { + return this.#fontData.remeasure; + } + get vertical() { + return this.#fontData.vertical; + } + get ascent() { + return this.#fontData.ascent; + } + get defaultWidth() { + return this.#fontData.defaultWidth; + } + get descent() { + return this.#fontData.descent; + } + get bbox() { + return this.#fontData.bbox; + } + get fontMatrix() { + return this.#fontData.fontMatrix; + } + get fallbackName() { + return this.#fontData.fallbackName; + } + get loadedName() { + return this.#fontData.loadedName; + } + get mimetype() { + return this.#fontData.mimetype; + } + get name() { + return this.#fontData.name; + } + get data() { + return this.#fontData.data; + } + clearData() { + this.#fontData.clearData(); + } + get cssFontInfo() { + return this.#fontData.cssFontInfo; + } + get systemFontInfo() { + return this.#fontData.systemFontInfo; + } + get defaultVMetrics() { + return this.#fontData.defaultVMetrics; + } +} +function getUrlProp(val) { + if (val instanceof URL) { + return val.href; + } + if (typeof val === "string") { + if (isNodeJS) { + return val; + } + const url = URL.parse(val, window.location); + if (url) { + return url.href; + } + } + throw new Error("Invalid PDF url data: either string or URL-object is expected in the url property."); +} +function getDataProp(val) { + if (isNodeJS && typeof Buffer !== "undefined" && val instanceof Buffer) { + throw new Error("Please provide binary data as `Uint8Array`, rather than `Buffer`."); + } + if (val instanceof Uint8Array && val.byteLength === val.buffer.byteLength) { + return val; + } + if (typeof val === "string") { + return stringToBytes(val); + } + if (val instanceof ArrayBuffer || ArrayBuffer.isView(val) || typeof val === "object" && !isNaN(val?.length)) { + return new Uint8Array(val); + } + throw new Error("Invalid PDF binary data: either TypedArray, string, or array-like object is expected in the data property."); +} +function getFactoryUrlProp(val) { + if (typeof val !== "string") { + return null; + } + if (val.endsWith("/")) { + return val; + } + throw new Error(`Invalid factory url: "${val}" must include trailing slash.`); +} +const isRefProxy = (v) => typeof v === "object" && Number.isInteger(v?.num) && v.num >= 0 && Number.isInteger(v?.gen) && v.gen >= 0; +const isNameProxy = (v) => typeof v === "object" && typeof v?.name === "string"; +const isValidExplicitDest = _isValidExplicitDest.bind(null, isRefProxy, isNameProxy); +class LoopbackPort { + #listeners = /* @__PURE__ */ new Map(); + #deferred = Promise.resolve(); + postMessage(obj, transfer) { + const event = { + data: structuredClone(obj, transfer ? { + transfer + } : null) + }; + this.#deferred.then(() => { + for (const [listener] of this.#listeners) { + listener.call(this, event); + } + }); + } + addEventListener(name, listener, options = null) { + let rmAbort = null; + if (options?.signal instanceof AbortSignal) { + const { + signal + } = options; + if (signal.aborted) { + warn("LoopbackPort - cannot use an `aborted` signal."); + return; + } + const onAbort = () => this.removeEventListener(name, listener); + rmAbort = () => signal.removeEventListener("abort", onAbort); + signal.addEventListener("abort", onAbort); + } + this.#listeners.set(listener, rmAbort); + } + removeEventListener(name, listener) { + const rmAbort = this.#listeners.get(listener); + rmAbort?.(); + this.#listeners.delete(listener); + } + terminate() { + for (const [, rmAbort] of this.#listeners) { + rmAbort?.(); + } + this.#listeners.clear(); + } +} +const CallbackKind = { + DATA: 1, + ERROR: 2 +}; +const StreamKind = { + CANCEL: 1, + CANCEL_COMPLETE: 2, + CLOSE: 3, + ENQUEUE: 4, + ERROR: 5, + PULL: 6, + PULL_COMPLETE: 7, + START_COMPLETE: 8 +}; +function onFn() { +} +function wrapReason(ex) { + if (ex instanceof AbortException || ex instanceof InvalidPDFException || ex instanceof PasswordException || ex instanceof ResponseException || ex instanceof UnknownErrorException) { + return ex; + } + if (!(ex instanceof Error || typeof ex === "object" && ex !== null)) { + unreachable('wrapReason: Expected "reason" to be a (possibly cloned) Error.'); + } + switch (ex.name) { + case "AbortException": + return new AbortException(ex.message); + case "InvalidPDFException": + return new InvalidPDFException(ex.message); + case "PasswordException": + return new PasswordException(ex.message, ex.code); + case "ResponseException": + return new ResponseException(ex.message, ex.status, ex.missing); + case "UnknownErrorException": + return new UnknownErrorException(ex.message, ex.details); + } + return new UnknownErrorException(ex.message, ex.toString()); +} +class MessageHandler { + #messageAC = new AbortController(); + constructor(sourceName, targetName, comObj) { + this.sourceName = sourceName; + this.targetName = targetName; + this.comObj = comObj; + this.callbackId = 1; + this.streamId = 1; + this.streamSinks = /* @__PURE__ */ Object.create(null); + this.streamControllers = /* @__PURE__ */ Object.create(null); + this.callbackCapabilities = /* @__PURE__ */ Object.create(null); + this.actionHandler = /* @__PURE__ */ Object.create(null); + comObj.addEventListener("message", this.#onMessage.bind(this), { + signal: this.#messageAC.signal + }); + } + #onMessage({ + data + }) { + if (data.targetName !== this.sourceName) { + return; + } + if (data.stream) { + this.#processStreamMessage(data); + return; + } + if (data.callback) { + const callbackId = data.callbackId; + const capability = this.callbackCapabilities[callbackId]; + if (!capability) { + throw new Error(`Cannot resolve callback ${callbackId}`); + } + delete this.callbackCapabilities[callbackId]; + if (data.callback === CallbackKind.DATA) { + capability.resolve(data.data); + } else if (data.callback === CallbackKind.ERROR) { + capability.reject(wrapReason(data.reason)); + } else { + throw new Error("Unexpected callback case"); + } + return; + } + const action = this.actionHandler[data.action]; + if (!action) { + throw new Error(`Unknown action from worker: ${data.action}`); + } + if (data.callbackId) { + const sourceName = this.sourceName, targetName = data.sourceName, comObj = this.comObj; + Promise.try(action, data.data).then(function(result) { + comObj.postMessage({ + sourceName, + targetName, + callback: CallbackKind.DATA, + callbackId: data.callbackId, + data: result + }); + }, function(reason) { + comObj.postMessage({ + sourceName, + targetName, + callback: CallbackKind.ERROR, + callbackId: data.callbackId, + reason: wrapReason(reason) + }); + }); + return; + } + if (data.streamId) { + this.#createStreamSink(data); + return; + } + action(data.data); + } + on(actionName, handler) { + const ah = this.actionHandler; + if (ah[actionName]) { + throw new Error(`There is already an actionName called "${actionName}"`); + } + ah[actionName] = handler; + } + send(actionName, data, transfers) { + this.comObj.postMessage({ + sourceName: this.sourceName, + targetName: this.targetName, + action: actionName, + data + }, transfers); + } + sendWithPromise(actionName, data, transfers) { + const callbackId = this.callbackId++; + const capability = Promise.withResolvers(); + this.callbackCapabilities[callbackId] = capability; + try { + this.comObj.postMessage({ + sourceName: this.sourceName, + targetName: this.targetName, + action: actionName, + callbackId, + data + }, transfers); + } catch (ex) { + capability.reject(ex); + } + return capability.promise; + } + sendWithStream(actionName, data, queueingStrategy, transfers) { + const streamId = this.streamId++, sourceName = this.sourceName, targetName = this.targetName, comObj = this.comObj; + return new ReadableStream({ + start: (controller) => { + const startCapability = Promise.withResolvers(); + this.streamControllers[streamId] = { + controller, + startCall: startCapability, + pullCall: null, + cancelCall: null, + isClosed: false + }; + comObj.postMessage({ + sourceName, + targetName, + action: actionName, + streamId, + data, + desiredSize: controller.desiredSize + }, transfers); + return startCapability.promise; + }, + pull: (controller) => { + const pullCapability = Promise.withResolvers(); + this.streamControllers[streamId].pullCall = pullCapability; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL, + streamId, + desiredSize: controller.desiredSize + }); + return pullCapability.promise; + }, + cancel: (reason) => { + assert(reason instanceof Error, "cancel must have a valid reason"); + const cancelCapability = Promise.withResolvers(); + this.streamControllers[streamId].cancelCall = cancelCapability; + this.streamControllers[streamId].isClosed = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CANCEL, + streamId, + reason: wrapReason(reason) + }); + return cancelCapability.promise; + } + }, queueingStrategy); + } + #createStreamSink(data) { + const streamId = data.streamId, sourceName = this.sourceName, targetName = data.sourceName, comObj = this.comObj; + const self2 = this, action = this.actionHandler[data.action]; + const streamSink = { + enqueue(chunk, size = 1, transfers) { + if (this.isCancelled) { + return; + } + const lastDesiredSize = this.desiredSize; + this.desiredSize -= size; + if (lastDesiredSize > 0 && this.desiredSize <= 0) { + this.sinkCapability = Promise.withResolvers(); + this.ready = this.sinkCapability.promise; + } + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.ENQUEUE, + streamId, + chunk + }, transfers); + }, + close() { + if (this.isCancelled) { + return; + } + this.isCancelled = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CLOSE, + streamId + }); + delete self2.streamSinks[streamId]; + }, + error(reason) { + assert(reason instanceof Error, "error must have a valid reason"); + if (this.isCancelled) { + return; + } + this.isCancelled = true; + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.ERROR, + streamId, + reason: wrapReason(reason) + }); + }, + sinkCapability: Promise.withResolvers(), + onPull: null, + onCancel: null, + isCancelled: false, + desiredSize: data.desiredSize, + ready: null + }; + streamSink.sinkCapability.resolve(); + streamSink.ready = streamSink.sinkCapability.promise; + this.streamSinks[streamId] = streamSink; + Promise.try(action, data.data, streamSink).then(function() { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.START_COMPLETE, + streamId, + success: true + }); + }, function(reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.START_COMPLETE, + streamId, + reason: wrapReason(reason) + }); + }); + } + #processStreamMessage(data) { + const streamId = data.streamId, sourceName = this.sourceName, targetName = data.sourceName, comObj = this.comObj; + const streamController = this.streamControllers[streamId], streamSink = this.streamSinks[streamId]; + switch (data.stream) { + case StreamKind.START_COMPLETE: + if (data.success) { + streamController.startCall.resolve(); + } else { + streamController.startCall.reject(wrapReason(data.reason)); + } + break; + case StreamKind.PULL_COMPLETE: + if (data.success) { + streamController.pullCall.resolve(); + } else { + streamController.pullCall.reject(wrapReason(data.reason)); + } + break; + case StreamKind.PULL: + if (!streamSink) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL_COMPLETE, + streamId, + success: true + }); + break; + } + if (streamSink.desiredSize <= 0 && data.desiredSize > 0) { + streamSink.sinkCapability.resolve(); + } + streamSink.desiredSize = data.desiredSize; + Promise.try(streamSink.onPull || onFn).then(function() { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL_COMPLETE, + streamId, + success: true + }); + }, function(reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.PULL_COMPLETE, + streamId, + reason: wrapReason(reason) + }); + }); + break; + case StreamKind.ENQUEUE: + assert(streamController, "enqueue should have stream controller"); + if (streamController.isClosed) { + break; + } + streamController.controller.enqueue(data.chunk); + break; + case StreamKind.CLOSE: + assert(streamController, "close should have stream controller"); + if (streamController.isClosed) { + break; + } + streamController.isClosed = true; + streamController.controller.close(); + this.#deleteStreamController(streamController, streamId); + break; + case StreamKind.ERROR: + assert(streamController, "error should have stream controller"); + streamController.controller.error(wrapReason(data.reason)); + this.#deleteStreamController(streamController, streamId); + break; + case StreamKind.CANCEL_COMPLETE: + if (data.success) { + streamController.cancelCall.resolve(); + } else { + streamController.cancelCall.reject(wrapReason(data.reason)); + } + this.#deleteStreamController(streamController, streamId); + break; + case StreamKind.CANCEL: + if (!streamSink) { + break; + } + const dataReason = wrapReason(data.reason); + Promise.try(streamSink.onCancel || onFn, dataReason).then(function() { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CANCEL_COMPLETE, + streamId, + success: true + }); + }, function(reason) { + comObj.postMessage({ + sourceName, + targetName, + stream: StreamKind.CANCEL_COMPLETE, + streamId, + reason: wrapReason(reason) + }); + }); + streamSink.sinkCapability.reject(dataReason); + streamSink.isCancelled = true; + delete this.streamSinks[streamId]; + break; + default: + throw new Error("Unexpected stream case"); + } + } + async #deleteStreamController(streamController, streamId) { + await Promise.allSettled([streamController.startCall?.promise, streamController.pullCall?.promise, streamController.cancelCall?.promise]); + delete this.streamControllers[streamId]; + } + destroy() { + this.#messageAC?.abort(); + this.#messageAC = null; + } +} +class BaseCanvasFactory { + #enableHWA = false; + constructor({ + enableHWA = false + }) { + this.#enableHWA = enableHWA; + } + create(width, height) { + if (width <= 0 || height <= 0) { + throw new Error("Invalid canvas size"); + } + const canvas = this._createCanvas(width, height); + return { + canvas, + context: canvas.getContext("2d", { + willReadFrequently: !this.#enableHWA + }) + }; + } + reset(canvasAndContext, width, height) { + if (!canvasAndContext.canvas) { + throw new Error("Canvas is not specified"); + } + if (width <= 0 || height <= 0) { + throw new Error("Invalid canvas size"); + } + canvasAndContext.canvas.width = width; + canvasAndContext.canvas.height = height; + } + destroy(canvasAndContext) { + if (!canvasAndContext.canvas) { + throw new Error("Canvas is not specified"); + } + canvasAndContext.canvas.width = 0; + canvasAndContext.canvas.height = 0; + canvasAndContext.canvas = null; + canvasAndContext.context = null; + } + _createCanvas(width, height) { + unreachable("Abstract method `_createCanvas` called."); + } +} +class DOMCanvasFactory extends BaseCanvasFactory { + constructor({ + ownerDocument = globalThis.document, + enableHWA = false + }) { + super({ + enableHWA + }); + this._document = ownerDocument; + } + _createCanvas(width, height) { + const canvas = this._document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + return canvas; + } +} +class BaseCMapReaderFactory { + constructor({ + baseUrl = null, + isCompressed = true + }) { + this.baseUrl = baseUrl; + this.isCompressed = isCompressed; + } + async fetch({ + name + }) { + if (!this.baseUrl) { + throw new Error("Ensure that the `cMapUrl` and `cMapPacked` API parameters are provided."); + } + if (!name) { + throw new Error("CMap name must be specified."); + } + const url = this.baseUrl + name + (this.isCompressed ? ".bcmap" : ""); + return this._fetch(url).then((cMapData) => ({ + cMapData, + isCompressed: this.isCompressed + })).catch((reason) => { + throw new Error(`Unable to load ${this.isCompressed ? "binary " : ""}CMap at: ${url}`); + }); + } + async _fetch(url) { + unreachable("Abstract method `_fetch` called."); + } +} +class DOMCMapReaderFactory extends BaseCMapReaderFactory { + async _fetch(url) { + const data = await fetchData(url, this.isCompressed ? "arraybuffer" : "text"); + return data instanceof ArrayBuffer ? new Uint8Array(data) : stringToBytes(data); + } +} +__webpack_require__(2489); +class BaseFilterFactory { + addFilter(maps) { + return "none"; + } + addHCMFilter(fgColor, bgColor) { + return "none"; + } + addAlphaFilter(map) { + return "none"; + } + addLuminosityFilter(map) { + return "none"; + } + addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) { + return "none"; + } + destroy(keepHCM = false) { + } +} +class DOMFilterFactory extends BaseFilterFactory { + #baseUrl; + #_cache; + #_defs; + #docId; + #document; + #_hcmCache; + #id = 0; + constructor({ + docId, + ownerDocument = globalThis.document + }) { + super(); + this.#docId = docId; + this.#document = ownerDocument; + } + get #cache() { + return this.#_cache ||= /* @__PURE__ */ new Map(); + } + get #hcmCache() { + return this.#_hcmCache ||= /* @__PURE__ */ new Map(); + } + get #defs() { + if (!this.#_defs) { + const div = this.#document.createElement("div"); + const { + style + } = div; + style.visibility = "hidden"; + style.contain = "strict"; + style.width = style.height = 0; + style.position = "absolute"; + style.top = style.left = 0; + style.zIndex = -1; + const svg = this.#document.createElementNS(SVG_NS, "svg"); + svg.setAttribute("width", 0); + svg.setAttribute("height", 0); + this.#_defs = this.#document.createElementNS(SVG_NS, "defs"); + div.append(svg); + svg.append(this.#_defs); + this.#document.body.append(div); + } + return this.#_defs; + } + #createTables(maps) { + if (maps.length === 1) { + const mapR2 = maps[0]; + const buffer = new Array(256); + for (let i = 0; i < 256; i++) { + buffer[i] = mapR2[i] / 255; + } + const table = buffer.join(","); + return [table, table, table]; + } + const [mapR, mapG, mapB] = maps; + const bufferR = new Array(256); + const bufferG = new Array(256); + const bufferB = new Array(256); + for (let i = 0; i < 256; i++) { + bufferR[i] = mapR[i] / 255; + bufferG[i] = mapG[i] / 255; + bufferB[i] = mapB[i] / 255; + } + return [bufferR.join(","), bufferG.join(","), bufferB.join(",")]; + } + #createUrl(id) { + if (this.#baseUrl === void 0) { + this.#baseUrl = ""; + const url = this.#document.URL; + if (url !== this.#document.baseURI) { + if (isDataScheme(url)) { + warn('#createUrl: ignore "data:"-URL for performance reasons.'); + } else { + this.#baseUrl = updateUrlHash(url, ""); + } + } + } + return `url(${this.#baseUrl}#${id})`; + } + addFilter(maps) { + if (!maps) { + return "none"; + } + let value = this.#cache.get(maps); + if (value) { + return value; + } + const [tableR, tableG, tableB] = this.#createTables(maps); + const key = maps.length === 1 ? tableR : `${tableR}${tableG}${tableB}`; + value = this.#cache.get(key); + if (value) { + this.#cache.set(maps, value); + return value; + } + const id = `g_${this.#docId}_transfer_map_${this.#id++}`; + const url = this.#createUrl(id); + this.#cache.set(maps, url); + this.#cache.set(key, url); + const filter = this.#createFilter(id); + this.#addTransferMapConversion(tableR, tableG, tableB, filter); + return url; + } + addHCMFilter(fgColor, bgColor) { + const key = `${fgColor}-${bgColor}`; + const filterName = "base"; + let info2 = this.#hcmCache.get(filterName); + if (info2?.key === key) { + return info2.url; + } + if (info2) { + info2.filter?.remove(); + info2.key = key; + info2.url = "none"; + info2.filter = null; + } else { + info2 = { + key, + url: "none", + filter: null + }; + this.#hcmCache.set(filterName, info2); + } + if (!fgColor || !bgColor) { + return info2.url; + } + const fgRGB = this.#getRGB(fgColor); + fgColor = Util.makeHexColor(...fgRGB); + const bgRGB = this.#getRGB(bgColor); + bgColor = Util.makeHexColor(...bgRGB); + this.#defs.style.color = ""; + if (fgColor === "#000000" && bgColor === "#ffffff" || fgColor === bgColor) { + return info2.url; + } + const map = new Array(256); + for (let i = 0; i <= 255; i++) { + const x = i / 255; + map[i] = x <= 0.03928 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4; + } + const table = map.join(","); + const id = `g_${this.#docId}_hcm_filter`; + const filter = info2.filter = this.#createFilter(id); + this.#addTransferMapConversion(table, table, table, filter); + this.#addGrayConversion(filter); + const getSteps = (c, n) => { + const start = fgRGB[c] / 255; + const end = bgRGB[c] / 255; + const arr = new Array(n + 1); + for (let i = 0; i <= n; i++) { + arr[i] = start + i / n * (end - start); + } + return arr.join(","); + }; + this.#addTransferMapConversion(getSteps(0, 5), getSteps(1, 5), getSteps(2, 5), filter); + info2.url = this.#createUrl(id); + return info2.url; + } + addAlphaFilter(map) { + let value = this.#cache.get(map); + if (value) { + return value; + } + const [tableA] = this.#createTables([map]); + const key = `alpha_${tableA}`; + value = this.#cache.get(key); + if (value) { + this.#cache.set(map, value); + return value; + } + const id = `g_${this.#docId}_alpha_map_${this.#id++}`; + const url = this.#createUrl(id); + this.#cache.set(map, url); + this.#cache.set(key, url); + const filter = this.#createFilter(id); + this.#addTransferMapAlphaConversion(tableA, filter); + return url; + } + addLuminosityFilter(map) { + let value = this.#cache.get(map || "luminosity"); + if (value) { + return value; + } + let tableA, key; + if (map) { + [tableA] = this.#createTables([map]); + key = `luminosity_${tableA}`; + } else { + key = "luminosity"; + } + value = this.#cache.get(key); + if (value) { + this.#cache.set(map, value); + return value; + } + const id = `g_${this.#docId}_luminosity_map_${this.#id++}`; + const url = this.#createUrl(id); + this.#cache.set(map, url); + this.#cache.set(key, url); + const filter = this.#createFilter(id); + this.#addLuminosityConversion(filter); + if (map) { + this.#addTransferMapAlphaConversion(tableA, filter); + } + return url; + } + addHighlightHCMFilter(filterName, fgColor, bgColor, newFgColor, newBgColor) { + const key = `${fgColor}-${bgColor}-${newFgColor}-${newBgColor}`; + let info2 = this.#hcmCache.get(filterName); + if (info2?.key === key) { + return info2.url; + } + if (info2) { + info2.filter?.remove(); + info2.key = key; + info2.url = "none"; + info2.filter = null; + } else { + info2 = { + key, + url: "none", + filter: null + }; + this.#hcmCache.set(filterName, info2); + } + if (!fgColor || !bgColor) { + return info2.url; + } + const [fgRGB, bgRGB] = [fgColor, bgColor].map(this.#getRGB.bind(this)); + let fgGray = Math.round(0.2126 * fgRGB[0] + 0.7152 * fgRGB[1] + 0.0722 * fgRGB[2]); + let bgGray = Math.round(0.2126 * bgRGB[0] + 0.7152 * bgRGB[1] + 0.0722 * bgRGB[2]); + let [newFgRGB, newBgRGB] = [newFgColor, newBgColor].map(this.#getRGB.bind(this)); + if (bgGray < fgGray) { + [fgGray, bgGray, newFgRGB, newBgRGB] = [bgGray, fgGray, newBgRGB, newFgRGB]; + } + this.#defs.style.color = ""; + const getSteps = (fg, bg, n) => { + const arr = new Array(256); + const step = (bgGray - fgGray) / n; + const newStart = fg / 255; + const newStep = (bg - fg) / (255 * n); + let prev = 0; + for (let i = 0; i <= n; i++) { + const k = Math.round(fgGray + i * step); + const value = newStart + i * newStep; + for (let j = prev; j <= k; j++) { + arr[j] = value; + } + prev = k + 1; + } + for (let i = prev; i < 256; i++) { + arr[i] = arr[prev - 1]; + } + return arr.join(","); + }; + const id = `g_${this.#docId}_hcm_${filterName}_filter`; + const filter = info2.filter = this.#createFilter(id); + this.#addGrayConversion(filter); + this.#addTransferMapConversion(getSteps(newFgRGB[0], newBgRGB[0], 5), getSteps(newFgRGB[1], newBgRGB[1], 5), getSteps(newFgRGB[2], newBgRGB[2], 5), filter); + info2.url = this.#createUrl(id); + return info2.url; + } + destroy(keepHCM = false) { + if (keepHCM && this.#_hcmCache?.size) { + return; + } + this.#_defs?.parentNode.parentNode.remove(); + this.#_defs = null; + this.#_cache?.clear(); + this.#_cache = null; + this.#_hcmCache?.clear(); + this.#_hcmCache = null; + this.#id = 0; + } + #addLuminosityConversion(filter) { + const feColorMatrix = this.#document.createElementNS(SVG_NS, "feColorMatrix"); + feColorMatrix.setAttribute("type", "matrix"); + feColorMatrix.setAttribute("values", "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0.59 0.11 0 0"); + filter.append(feColorMatrix); + } + #addGrayConversion(filter) { + const feColorMatrix = this.#document.createElementNS(SVG_NS, "feColorMatrix"); + feColorMatrix.setAttribute("type", "matrix"); + feColorMatrix.setAttribute("values", "0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0.2126 0.7152 0.0722 0 0 0 0 0 1 0"); + filter.append(feColorMatrix); + } + #createFilter(id) { + const filter = this.#document.createElementNS(SVG_NS, "filter"); + filter.setAttribute("color-interpolation-filters", "sRGB"); + filter.setAttribute("id", id); + this.#defs.append(filter); + return filter; + } + #appendFeFunc(feComponentTransfer, func, table) { + const feFunc = this.#document.createElementNS(SVG_NS, func); + feFunc.setAttribute("type", "discrete"); + feFunc.setAttribute("tableValues", table); + feComponentTransfer.append(feFunc); + } + #addTransferMapConversion(rTable, gTable, bTable, filter) { + const feComponentTransfer = this.#document.createElementNS(SVG_NS, "feComponentTransfer"); + filter.append(feComponentTransfer); + this.#appendFeFunc(feComponentTransfer, "feFuncR", rTable); + this.#appendFeFunc(feComponentTransfer, "feFuncG", gTable); + this.#appendFeFunc(feComponentTransfer, "feFuncB", bTable); + } + #addTransferMapAlphaConversion(aTable, filter) { + const feComponentTransfer = this.#document.createElementNS(SVG_NS, "feComponentTransfer"); + filter.append(feComponentTransfer); + this.#appendFeFunc(feComponentTransfer, "feFuncA", aTable); + } + #getRGB(color) { + this.#defs.style.color = color; + return getRGB(getComputedStyle(this.#defs).getPropertyValue("color")); + } +} +class BaseStandardFontDataFactory { + constructor({ + baseUrl = null + }) { + this.baseUrl = baseUrl; + } + async fetch({ + filename + }) { + if (!this.baseUrl) { + throw new Error("Ensure that the `standardFontDataUrl` API parameter is provided."); + } + if (!filename) { + throw new Error("Font filename must be specified."); + } + const url = `${this.baseUrl}${filename}`; + return this._fetch(url).catch((reason) => { + throw new Error(`Unable to load font data at: ${url}`); + }); + } + async _fetch(url) { + unreachable("Abstract method `_fetch` called."); + } +} +class DOMStandardFontDataFactory extends BaseStandardFontDataFactory { + async _fetch(url) { + const data = await fetchData(url, "arraybuffer"); + return new Uint8Array(data); + } +} +class BaseWasmFactory { + constructor({ + baseUrl = null + }) { + this.baseUrl = baseUrl; + } + async fetch({ + filename + }) { + if (!this.baseUrl) { + throw new Error("Ensure that the `wasmUrl` API parameter is provided."); + } + if (!filename) { + throw new Error("Wasm filename must be specified."); + } + const url = `${this.baseUrl}${filename}`; + return this._fetch(url).catch((reason) => { + throw new Error(`Unable to load wasm data at: ${url}`); + }); + } + async _fetch(url) { + unreachable("Abstract method `_fetch` called."); + } +} +class DOMWasmFactory extends BaseWasmFactory { + async _fetch(url) { + const data = await fetchData(url, "arraybuffer"); + return new Uint8Array(data); + } +} +if (isNodeJS) { + let canvas; + try { + const require2 = process.getBuiltinModule("module").createRequire(import.meta.url); + try { + canvas = require2("@napi-rs/canvas"); + } catch (ex) { + warn(`Cannot load "@napi-rs/canvas" package: "${ex}".`); + } + } catch (ex) { + warn(`Cannot access the \`require\` function: "${ex}".`); + } + if (!globalThis.DOMMatrix) { + if (canvas?.DOMMatrix) { + globalThis.DOMMatrix = canvas.DOMMatrix; + } else { + warn("Cannot polyfill `DOMMatrix`, rendering may be broken."); + } + } + if (!globalThis.ImageData) { + if (canvas?.ImageData) { + globalThis.ImageData = canvas.ImageData; + } else { + warn("Cannot polyfill `ImageData`, rendering may be broken."); + } + } + if (!globalThis.Path2D) { + if (canvas?.Path2D) { + globalThis.Path2D = canvas.Path2D; + } else { + warn("Cannot polyfill `Path2D`, rendering may be broken."); + } + } + if (!globalThis.navigator?.language) { + globalThis.navigator = { + language: "en-US", + platform: "", + userAgent: "" + }; + } +} +async function node_utils_fetchData(url) { + const fs = process.getBuiltinModule("fs"); + const data = await fs.promises.readFile(url); + return new Uint8Array(data); +} +class NodeFilterFactory extends BaseFilterFactory { +} +class NodeCanvasFactory extends BaseCanvasFactory { + _createCanvas(width, height) { + const require2 = process.getBuiltinModule("module").createRequire(import.meta.url); + const canvas = require2("@napi-rs/canvas"); + return canvas.createCanvas(width, height); + } +} +class NodeCMapReaderFactory extends BaseCMapReaderFactory { + async _fetch(url) { + return node_utils_fetchData(url); + } +} +class NodeStandardFontDataFactory extends BaseStandardFontDataFactory { + async _fetch(url) { + return node_utils_fetchData(url); + } +} +class NodeWasmFactory extends BaseWasmFactory { + async _fetch(url) { + return node_utils_fetchData(url); + } +} +__webpack_require__(7588); +const FORCED_DEPENDENCY_LABEL = "__forcedDependency"; +const { + floor, + ceil +} = Math; +function expandBBox(array, index, minX, minY, maxX, maxY) { + array[index * 4 + 0] = Math.min(array[index * 4 + 0], minX); + array[index * 4 + 1] = Math.min(array[index * 4 + 1], minY); + array[index * 4 + 2] = Math.max(array[index * 4 + 2], maxX); + array[index * 4 + 3] = Math.max(array[index * 4 + 3], maxY); +} +const EMPTY_BBOX = new Uint32Array(new Uint8Array([255, 255, 0, 0]).buffer)[0]; +class BBoxReader { + #bboxes; + #coords; + constructor(bboxes, coords) { + this.#bboxes = bboxes; + this.#coords = coords; + } + get length() { + return this.#bboxes.length; + } + isEmpty(i) { + return this.#bboxes[i] === EMPTY_BBOX; + } + minX(i) { + return this.#coords[i * 4 + 0] / 256; + } + minY(i) { + return this.#coords[i * 4 + 1] / 256; + } + maxX(i) { + return (this.#coords[i * 4 + 2] + 1) / 256; + } + maxY(i) { + return (this.#coords[i * 4 + 3] + 1) / 256; + } +} +const ensureDebugMetadata = (map, key) => { + if (!map) { + return void 0; + } + let value = map.get(key); + if (!value) { + value = { + dependencies: /* @__PURE__ */ new Set(), + isRenderingOperation: false + }; + map.set(key, value); + } + return value; +}; +class CanvasDependencyTracker { + #simple = { + __proto__: null + }; + #incremental = { + __proto__: null, + transform: [], + moveText: [], + sameLineText: [], + [FORCED_DEPENDENCY_LABEL]: [] + }; + #namedDependencies = /* @__PURE__ */ new Map(); + #savesStack = []; + #markedContentStack = []; + #baseTransformStack = [[1, 0, 0, 1, 0, 0]]; + #clipBox = [-Infinity, -Infinity, Infinity, Infinity]; + #pendingBBox = new Float64Array([Infinity, Infinity, -Infinity, -Infinity]); + #pendingBBoxIdx = -1; + #pendingDependencies = /* @__PURE__ */ new Set(); + #operations = /* @__PURE__ */ new Map(); + #fontBBoxTrustworthy = /* @__PURE__ */ new Map(); + #canvasWidth; + #canvasHeight; + #bboxesCoords; + #bboxes; + #debugMetadata; + constructor(canvas, operationsCount, recordDebugMetadata = false) { + this.#canvasWidth = canvas.width; + this.#canvasHeight = canvas.height; + this.#initializeBBoxes(operationsCount); + if (recordDebugMetadata) { + this.#debugMetadata = /* @__PURE__ */ new Map(); + } + } + growOperationsCount(operationsCount) { + if (operationsCount >= this.#bboxes.length) { + this.#initializeBBoxes(operationsCount, this.#bboxes); + } + } + #initializeBBoxes(operationsCount, oldBBoxes) { + const buffer = new ArrayBuffer(operationsCount * 4); + this.#bboxesCoords = new Uint8ClampedArray(buffer); + this.#bboxes = new Uint32Array(buffer); + if (oldBBoxes && oldBBoxes.length > 0) { + this.#bboxes.set(oldBBoxes); + this.#bboxes.fill(EMPTY_BBOX, oldBBoxes.length); + } else { + this.#bboxes.fill(EMPTY_BBOX); + } + } + save(opIdx) { + this.#simple = { + __proto__: this.#simple + }; + this.#incremental = { + __proto__: this.#incremental, + transform: { + __proto__: this.#incremental.transform + }, + moveText: { + __proto__: this.#incremental.moveText + }, + sameLineText: { + __proto__: this.#incremental.sameLineText + }, + [FORCED_DEPENDENCY_LABEL]: { + __proto__: this.#incremental[FORCED_DEPENDENCY_LABEL] + } + }; + this.#clipBox = { + __proto__: this.#clipBox + }; + this.#savesStack.push(opIdx); + return this; + } + restore(opIdx) { + const previous = Object.getPrototypeOf(this.#simple); + if (previous === null) { + return this; + } + this.#simple = previous; + this.#incremental = Object.getPrototypeOf(this.#incremental); + this.#clipBox = Object.getPrototypeOf(this.#clipBox); + const lastSave = this.#savesStack.pop(); + if (lastSave !== void 0) { + ensureDebugMetadata(this.#debugMetadata, opIdx)?.dependencies.add(lastSave); + this.#bboxes[opIdx] = this.#bboxes[lastSave]; + } + return this; + } + recordOpenMarker(idx) { + this.#savesStack.push(idx); + return this; + } + getOpenMarker() { + if (this.#savesStack.length === 0) { + return null; + } + return this.#savesStack.at(-1); + } + recordCloseMarker(opIdx) { + const lastSave = this.#savesStack.pop(); + if (lastSave !== void 0) { + ensureDebugMetadata(this.#debugMetadata, opIdx)?.dependencies.add(lastSave); + this.#bboxes[opIdx] = this.#bboxes[lastSave]; + } + return this; + } + beginMarkedContent(opIdx) { + this.#markedContentStack.push(opIdx); + return this; + } + endMarkedContent(opIdx) { + const lastSave = this.#markedContentStack.pop(); + if (lastSave !== void 0) { + ensureDebugMetadata(this.#debugMetadata, opIdx)?.dependencies.add(lastSave); + this.#bboxes[opIdx] = this.#bboxes[lastSave]; + } + return this; + } + pushBaseTransform(ctx) { + this.#baseTransformStack.push(Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1), ctx.getTransform())); + return this; + } + popBaseTransform() { + if (this.#baseTransformStack.length > 1) { + this.#baseTransformStack.pop(); + } + return this; + } + recordSimpleData(name, idx) { + this.#simple[name] = idx; + return this; + } + recordIncrementalData(name, idx) { + this.#incremental[name].push(idx); + return this; + } + resetIncrementalData(name, idx) { + this.#incremental[name].length = 0; + return this; + } + recordNamedData(name, idx) { + this.#namedDependencies.set(name, idx); + return this; + } + recordSimpleDataFromNamed(name, depName, fallbackIdx) { + this.#simple[name] = this.#namedDependencies.get(depName) ?? fallbackIdx; + } + recordFutureForcedDependency(name, idx) { + this.recordIncrementalData(FORCED_DEPENDENCY_LABEL, idx); + return this; + } + inheritSimpleDataAsFutureForcedDependencies(names) { + for (const name of names) { + if (name in this.#simple) { + this.recordFutureForcedDependency(name, this.#simple[name]); + } + } + return this; + } + inheritPendingDependenciesAsFutureForcedDependencies() { + for (const dep of this.#pendingDependencies) { + this.recordFutureForcedDependency(FORCED_DEPENDENCY_LABEL, dep); + } + return this; + } + resetBBox(idx) { + if (this.#pendingBBoxIdx !== idx) { + this.#pendingBBoxIdx = idx; + this.#pendingBBox[0] = Infinity; + this.#pendingBBox[1] = Infinity; + this.#pendingBBox[2] = -Infinity; + this.#pendingBBox[3] = -Infinity; + } + return this; + } + recordClipBox(idx, ctx, minX, maxX, minY, maxY) { + const transform = Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1), ctx.getTransform()); + const clipBox = [Infinity, Infinity, -Infinity, -Infinity]; + Util.axialAlignedBoundingBox([minX, minY, maxX, maxY], transform, clipBox); + const intersection = Util.intersect(this.#clipBox, clipBox); + if (intersection) { + this.#clipBox[0] = intersection[0]; + this.#clipBox[1] = intersection[1]; + this.#clipBox[2] = intersection[2]; + this.#clipBox[3] = intersection[3]; + } else { + this.#clipBox[0] = this.#clipBox[1] = Infinity; + this.#clipBox[2] = this.#clipBox[3] = -Infinity; + } + return this; + } + recordBBox(idx, ctx, minX, maxX, minY, maxY) { + const clipBox = this.#clipBox; + if (clipBox[0] === Infinity) { + return this; + } + const transform = Util.multiplyByDOMMatrix(this.#baseTransformStack.at(-1), ctx.getTransform()); + if (clipBox[0] === -Infinity) { + Util.axialAlignedBoundingBox([minX, minY, maxX, maxY], transform, this.#pendingBBox); + return this; + } + const bbox = [Infinity, Infinity, -Infinity, -Infinity]; + Util.axialAlignedBoundingBox([minX, minY, maxX, maxY], transform, bbox); + this.#pendingBBox[0] = Math.min(this.#pendingBBox[0], Math.max(bbox[0], clipBox[0])); + this.#pendingBBox[1] = Math.min(this.#pendingBBox[1], Math.max(bbox[1], clipBox[1])); + this.#pendingBBox[2] = Math.max(this.#pendingBBox[2], Math.min(bbox[2], clipBox[2])); + this.#pendingBBox[3] = Math.max(this.#pendingBBox[3], Math.min(bbox[3], clipBox[3])); + return this; + } + recordCharacterBBox(idx, ctx, font, scale = 1, x = 0, y = 0, getMeasure) { + const fontBBox = font.bbox; + let isBBoxTrustworthy; + let computedBBox; + if (fontBBox) { + isBBoxTrustworthy = fontBBox[2] !== fontBBox[0] && fontBBox[3] !== fontBBox[1] && this.#fontBBoxTrustworthy.get(font); + if (isBBoxTrustworthy !== false) { + computedBBox = [0, 0, 0, 0]; + Util.axialAlignedBoundingBox(fontBBox, font.fontMatrix, computedBBox); + if (scale !== 1 || x !== 0 || y !== 0) { + Util.scaleMinMax([scale, 0, 0, -scale, x, y], computedBBox); + } + if (isBBoxTrustworthy) { + return this.recordBBox(idx, ctx, computedBBox[0], computedBBox[2], computedBBox[1], computedBBox[3]); + } + } + } + if (!getMeasure) { + return this.recordFullPageBBox(idx); + } + const measure = getMeasure(); + if (fontBBox && computedBBox && isBBoxTrustworthy === void 0) { + isBBoxTrustworthy = computedBBox[0] <= x - measure.actualBoundingBoxLeft && computedBBox[2] >= x + measure.actualBoundingBoxRight && computedBBox[1] <= y - measure.actualBoundingBoxAscent && computedBBox[3] >= y + measure.actualBoundingBoxDescent; + this.#fontBBoxTrustworthy.set(font, isBBoxTrustworthy); + if (isBBoxTrustworthy) { + return this.recordBBox(idx, ctx, computedBBox[0], computedBBox[2], computedBBox[1], computedBBox[3]); + } + } + return this.recordBBox(idx, ctx, x - measure.actualBoundingBoxLeft, x + measure.actualBoundingBoxRight, y - measure.actualBoundingBoxAscent, y + measure.actualBoundingBoxDescent); + } + recordFullPageBBox(idx) { + this.#pendingBBox[0] = Math.max(0, this.#clipBox[0]); + this.#pendingBBox[1] = Math.max(0, this.#clipBox[1]); + this.#pendingBBox[2] = Math.min(this.#canvasWidth, this.#clipBox[2]); + this.#pendingBBox[3] = Math.min(this.#canvasHeight, this.#clipBox[3]); + return this; + } + getSimpleIndex(dependencyName) { + return this.#simple[dependencyName]; + } + recordDependencies(idx, dependencyNames) { + const pendingDependencies = this.#pendingDependencies; + const simple = this.#simple; + const incremental = this.#incremental; + for (const name of dependencyNames) { + if (name in this.#simple) { + pendingDependencies.add(simple[name]); + } else if (name in incremental) { + incremental[name].forEach(pendingDependencies.add, pendingDependencies); + } + } + return this; + } + recordNamedDependency(idx, name) { + if (this.#namedDependencies.has(name)) { + this.#pendingDependencies.add(this.#namedDependencies.get(name)); + } + return this; + } + recordOperation(idx, preserve = false) { + this.recordDependencies(idx, [FORCED_DEPENDENCY_LABEL]); + if (this.#debugMetadata) { + const metadata = ensureDebugMetadata(this.#debugMetadata, idx); + const { + dependencies + } = metadata; + this.#pendingDependencies.forEach(dependencies.add, dependencies); + this.#savesStack.forEach(dependencies.add, dependencies); + this.#markedContentStack.forEach(dependencies.add, dependencies); + dependencies.delete(idx); + metadata.isRenderingOperation = true; + } + if (this.#pendingBBoxIdx === idx) { + const minX = floor(this.#pendingBBox[0] * 256 / this.#canvasWidth); + const minY = floor(this.#pendingBBox[1] * 256 / this.#canvasHeight); + const maxX = ceil(this.#pendingBBox[2] * 256 / this.#canvasWidth); + const maxY = ceil(this.#pendingBBox[3] * 256 / this.#canvasHeight); + expandBBox(this.#bboxesCoords, idx, minX, minY, maxX, maxY); + for (const depIdx of this.#pendingDependencies) { + if (depIdx !== idx) { + expandBBox(this.#bboxesCoords, depIdx, minX, minY, maxX, maxY); + } + } + for (const saveIdx of this.#savesStack) { + if (saveIdx !== idx) { + expandBBox(this.#bboxesCoords, saveIdx, minX, minY, maxX, maxY); + } + } + for (const saveIdx of this.#markedContentStack) { + if (saveIdx !== idx) { + expandBBox(this.#bboxesCoords, saveIdx, minX, minY, maxX, maxY); + } + } + if (!preserve) { + this.#pendingDependencies.clear(); + this.#pendingBBoxIdx = -1; + } + } + return this; + } + recordShowTextOperation(idx, preserve = false) { + const deps = Array.from(this.#pendingDependencies); + this.recordOperation(idx, preserve); + this.recordIncrementalData("sameLineText", idx); + for (const dep of deps) { + this.recordIncrementalData("sameLineText", dep); + } + return this; + } + bboxToClipBoxDropOperation(idx, preserve = false) { + if (this.#pendingBBoxIdx === idx) { + this.#pendingBBoxIdx = -1; + this.#clipBox[0] = Math.max(this.#clipBox[0], this.#pendingBBox[0]); + this.#clipBox[1] = Math.max(this.#clipBox[1], this.#pendingBBox[1]); + this.#clipBox[2] = Math.min(this.#clipBox[2], this.#pendingBBox[2]); + this.#clipBox[3] = Math.min(this.#clipBox[3], this.#pendingBBox[3]); + if (!preserve) { + this.#pendingDependencies.clear(); + } + } + return this; + } + _takePendingDependencies() { + const pendingDependencies = this.#pendingDependencies; + this.#pendingDependencies = /* @__PURE__ */ new Set(); + return pendingDependencies; + } + _extractOperation(idx) { + const operation = this.#operations.get(idx); + this.#operations.delete(idx); + return operation; + } + _pushPendingDependencies(dependencies) { + for (const dep of dependencies) { + this.#pendingDependencies.add(dep); + } + } + take() { + this.#fontBBoxTrustworthy.clear(); + return new BBoxReader(this.#bboxes, this.#bboxesCoords); + } + takeDebugMetadata() { + return this.#debugMetadata; + } +} +class CanvasNestedDependencyTracker { + #dependencyTracker; + #opIdx; + #ignoreBBoxes; + #nestingLevel = 0; + #savesLevel = 0; + constructor(dependencyTracker, opIdx, ignoreBBoxes) { + if (dependencyTracker instanceof CanvasNestedDependencyTracker && dependencyTracker.#ignoreBBoxes === !!ignoreBBoxes) { + return dependencyTracker; + } + this.#dependencyTracker = dependencyTracker; + this.#opIdx = opIdx; + this.#ignoreBBoxes = !!ignoreBBoxes; + } + growOperationsCount() { + throw new Error("Unreachable"); + } + save(opIdx) { + this.#savesLevel++; + this.#dependencyTracker.save(this.#opIdx); + return this; + } + restore(opIdx) { + if (this.#savesLevel > 0) { + this.#dependencyTracker.restore(this.#opIdx); + this.#savesLevel--; + } + return this; + } + recordOpenMarker(idx) { + this.#nestingLevel++; + return this; + } + getOpenMarker() { + return this.#nestingLevel > 0 ? this.#opIdx : this.#dependencyTracker.getOpenMarker(); + } + recordCloseMarker(idx) { + this.#nestingLevel--; + return this; + } + beginMarkedContent(opIdx) { + return this; + } + endMarkedContent(opIdx) { + return this; + } + pushBaseTransform(ctx) { + this.#dependencyTracker.pushBaseTransform(ctx); + return this; + } + popBaseTransform() { + this.#dependencyTracker.popBaseTransform(); + return this; + } + recordSimpleData(name, idx) { + this.#dependencyTracker.recordSimpleData(name, this.#opIdx); + return this; + } + recordIncrementalData(name, idx) { + this.#dependencyTracker.recordIncrementalData(name, this.#opIdx); + return this; + } + resetIncrementalData(name, idx) { + this.#dependencyTracker.resetIncrementalData(name, this.#opIdx); + return this; + } + recordNamedData(name, idx) { + return this; + } + recordSimpleDataFromNamed(name, depName, fallbackIdx) { + this.#dependencyTracker.recordSimpleDataFromNamed(name, depName, this.#opIdx); + return this; + } + recordFutureForcedDependency(name, idx) { + this.#dependencyTracker.recordFutureForcedDependency(name, this.#opIdx); + return this; + } + inheritSimpleDataAsFutureForcedDependencies(names) { + this.#dependencyTracker.inheritSimpleDataAsFutureForcedDependencies(names); + return this; + } + inheritPendingDependenciesAsFutureForcedDependencies() { + this.#dependencyTracker.inheritPendingDependenciesAsFutureForcedDependencies(); + return this; + } + resetBBox(idx) { + if (!this.#ignoreBBoxes) { + this.#dependencyTracker.resetBBox(this.#opIdx); + } + return this; + } + recordClipBox(idx, ctx, minX, maxX, minY, maxY) { + if (!this.#ignoreBBoxes) { + this.#dependencyTracker.recordClipBox(this.#opIdx, ctx, minX, maxX, minY, maxY); + } + return this; + } + recordBBox(idx, ctx, minX, maxX, minY, maxY) { + if (!this.#ignoreBBoxes) { + this.#dependencyTracker.recordBBox(this.#opIdx, ctx, minX, maxX, minY, maxY); + } + return this; + } + recordCharacterBBox(idx, ctx, font, scale, x, y, getMeasure) { + if (!this.#ignoreBBoxes) { + this.#dependencyTracker.recordCharacterBBox(this.#opIdx, ctx, font, scale, x, y, getMeasure); + } + return this; + } + recordFullPageBBox(idx) { + if (!this.#ignoreBBoxes) { + this.#dependencyTracker.recordFullPageBBox(this.#opIdx); + } + return this; + } + getSimpleIndex(dependencyName) { + return this.#dependencyTracker.getSimpleIndex(dependencyName); + } + recordDependencies(idx, dependencyNames) { + this.#dependencyTracker.recordDependencies(this.#opIdx, dependencyNames); + return this; + } + recordNamedDependency(idx, name) { + this.#dependencyTracker.recordNamedDependency(this.#opIdx, name); + return this; + } + recordOperation(idx) { + this.#dependencyTracker.recordOperation(this.#opIdx, true); + return this; + } + recordShowTextOperation(idx) { + this.#dependencyTracker.recordShowTextOperation(this.#opIdx, true); + return this; + } + bboxToClipBoxDropOperation(idx) { + if (!this.#ignoreBBoxes) { + this.#dependencyTracker.bboxToClipBoxDropOperation(this.#opIdx, true); + } + return this; + } + take() { + throw new Error("Unreachable"); + } + takeDebugMetadata() { + throw new Error("Unreachable"); + } +} +const Dependencies = { + stroke: ["path", "transform", "filter", "strokeColor", "strokeAlpha", "lineWidth", "lineCap", "lineJoin", "miterLimit", "dash"], + fill: ["path", "transform", "filter", "fillColor", "fillAlpha", "globalCompositeOperation", "SMask"], + imageXObject: ["transform", "SMask", "filter", "fillAlpha", "strokeAlpha", "globalCompositeOperation"], + rawFillPath: ["filter", "fillColor", "fillAlpha"], + showText: ["transform", "leading", "charSpacing", "wordSpacing", "hScale", "textRise", "moveText", "textMatrix", "font", "fontObj", "filter", "fillColor", "textRenderingMode", "SMask", "fillAlpha", "strokeAlpha", "globalCompositeOperation", "sameLineText"], + transform: ["transform"], + transformAndFill: ["transform", "fillColor"] +}; +const PathType = { + FILL: "Fill", + STROKE: "Stroke", + SHADING: "Shading" +}; +function applyBoundingBox(ctx, bbox) { + if (!bbox) { + return; + } + const width = bbox[2] - bbox[0]; + const height = bbox[3] - bbox[1]; + const region = new Path2D(); + region.rect(bbox[0], bbox[1], width, height); + ctx.clip(region); +} +class BaseShadingPattern { + isModifyingCurrentTransform() { + return false; + } + getPattern() { + unreachable("Abstract method `getPattern` called."); + } +} +class RadialAxialShadingPattern extends BaseShadingPattern { + constructor(IR) { + super(); + this._type = IR[1]; + this._bbox = IR[2]; + this._colorStops = IR[3]; + this._p0 = IR[4]; + this._p1 = IR[5]; + this._r0 = IR[6]; + this._r1 = IR[7]; + this.matrix = null; + } + _createGradient(ctx) { + let grad; + if (this._type === "axial") { + grad = ctx.createLinearGradient(this._p0[0], this._p0[1], this._p1[0], this._p1[1]); + } else if (this._type === "radial") { + grad = ctx.createRadialGradient(this._p0[0], this._p0[1], this._r0, this._p1[0], this._p1[1], this._r1); + } + for (const colorStop of this._colorStops) { + grad.addColorStop(colorStop[0], colorStop[1]); + } + return grad; + } + getPattern(ctx, owner, inverse, pathType) { + let pattern; + if (pathType === PathType.STROKE || pathType === PathType.FILL) { + const ownerBBox = owner.current.getClippedPathBoundingBox(pathType, getCurrentTransform(ctx)) || [0, 0, 0, 0]; + const width = Math.ceil(ownerBBox[2] - ownerBBox[0]) || 1; + const height = Math.ceil(ownerBBox[3] - ownerBBox[1]) || 1; + const tmpCanvas = owner.cachedCanvases.getCanvas("pattern", width, height); + const tmpCtx = tmpCanvas.context; + tmpCtx.clearRect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height); + tmpCtx.beginPath(); + tmpCtx.rect(0, 0, tmpCtx.canvas.width, tmpCtx.canvas.height); + tmpCtx.translate(-ownerBBox[0], -ownerBBox[1]); + inverse = Util.transform(inverse, [1, 0, 0, 1, ownerBBox[0], ownerBBox[1]]); + tmpCtx.transform(...owner.baseTransform); + if (this.matrix) { + tmpCtx.transform(...this.matrix); + } + applyBoundingBox(tmpCtx, this._bbox); + tmpCtx.fillStyle = this._createGradient(tmpCtx); + tmpCtx.fill(); + pattern = ctx.createPattern(tmpCanvas.canvas, "no-repeat"); + const domMatrix = new DOMMatrix(inverse); + pattern.setTransform(domMatrix); + } else { + applyBoundingBox(ctx, this._bbox); + pattern = this._createGradient(ctx); + } + return pattern; + } +} +function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) { + const coords = context.coords, colors = context.colors; + const bytes = data.data, rowSize = data.width * 4; + let tmp; + if (coords[p1 + 1] > coords[p2 + 1]) { + tmp = p1; + p1 = p2; + p2 = tmp; + tmp = c1; + c1 = c2; + c2 = tmp; + } + if (coords[p2 + 1] > coords[p3 + 1]) { + tmp = p2; + p2 = p3; + p3 = tmp; + tmp = c2; + c2 = c3; + c3 = tmp; + } + if (coords[p1 + 1] > coords[p2 + 1]) { + tmp = p1; + p1 = p2; + p2 = tmp; + tmp = c1; + c1 = c2; + c2 = tmp; + } + const x1 = (coords[p1] + context.offsetX) * context.scaleX; + const y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY; + const x2 = (coords[p2] + context.offsetX) * context.scaleX; + const y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY; + const x3 = (coords[p3] + context.offsetX) * context.scaleX; + const y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY; + if (y1 >= y3) { + return; + } + const c1r = colors[c1], c1g = colors[c1 + 1], c1b = colors[c1 + 2]; + const c2r = colors[c2], c2g = colors[c2 + 1], c2b = colors[c2 + 2]; + const c3r = colors[c3], c3g = colors[c3 + 1], c3b = colors[c3 + 2]; + const minY = Math.round(y1), maxY = Math.round(y3); + let xa, car, cag, cab; + let xb, cbr, cbg, cbb; + for (let y = minY; y <= maxY; y++) { + if (y < y2) { + const k2 = y < y1 ? 0 : (y1 - y) / (y1 - y2); + xa = x1 - (x1 - x2) * k2; + car = c1r - (c1r - c2r) * k2; + cag = c1g - (c1g - c2g) * k2; + cab = c1b - (c1b - c2b) * k2; + } else { + let k2; + if (y > y3) { + k2 = 1; + } else if (y2 === y3) { + k2 = 0; + } else { + k2 = (y2 - y) / (y2 - y3); + } + xa = x2 - (x2 - x3) * k2; + car = c2r - (c2r - c3r) * k2; + cag = c2g - (c2g - c3g) * k2; + cab = c2b - (c2b - c3b) * k2; + } + let k; + if (y < y1) { + k = 0; + } else if (y > y3) { + k = 1; + } else { + k = (y1 - y) / (y1 - y3); + } + xb = x1 - (x1 - x3) * k; + cbr = c1r - (c1r - c3r) * k; + cbg = c1g - (c1g - c3g) * k; + cbb = c1b - (c1b - c3b) * k; + const x1_ = Math.round(Math.min(xa, xb)); + const x2_ = Math.round(Math.max(xa, xb)); + let j = rowSize * y + x1_ * 4; + for (let x = x1_; x <= x2_; x++) { + k = (xa - x) / (xa - xb); + if (k < 0) { + k = 0; + } else if (k > 1) { + k = 1; + } + bytes[j++] = car - (car - cbr) * k | 0; + bytes[j++] = cag - (cag - cbg) * k | 0; + bytes[j++] = cab - (cab - cbb) * k | 0; + bytes[j++] = 255; + } + } +} +function drawFigure(data, figure, context) { + const ps = figure.coords; + const cs = figure.colors; + let i, ii; + switch (figure.type) { + case "lattice": + const verticesPerRow = figure.verticesPerRow; + const rows = Math.floor(ps.length / verticesPerRow) - 1; + const cols = verticesPerRow - 1; + for (i = 0; i < rows; i++) { + let q = i * verticesPerRow; + for (let j = 0; j < cols; j++, q++) { + drawTriangle(data, context, ps[q], ps[q + 1], ps[q + verticesPerRow], cs[q], cs[q + 1], cs[q + verticesPerRow]); + drawTriangle(data, context, ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow], cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]); + } + } + break; + case "triangles": + for (i = 0, ii = ps.length; i < ii; i += 3) { + drawTriangle(data, context, ps[i], ps[i + 1], ps[i + 2], cs[i], cs[i + 1], cs[i + 2]); + } + break; + default: + throw new Error("illegal figure"); + } +} +class MeshShadingPattern extends BaseShadingPattern { + constructor(IR) { + super(); + this._coords = IR[2]; + this._colors = IR[3]; + this._figures = IR[4]; + this._bounds = IR[5]; + this._bbox = IR[6]; + this._background = IR[7]; + this.matrix = null; + } + _createMeshCanvas(combinedScale, backgroundColor, cachedCanvases) { + const EXPECTED_SCALE = 1.1; + const MAX_PATTERN_SIZE = 3e3; + const BORDER_SIZE = 2; + const offsetX = Math.floor(this._bounds[0]); + const offsetY = Math.floor(this._bounds[1]); + const boundsWidth = Math.ceil(this._bounds[2]) - offsetX; + const boundsHeight = Math.ceil(this._bounds[3]) - offsetY; + const width = Math.min(Math.ceil(Math.abs(boundsWidth * combinedScale[0] * EXPECTED_SCALE)), MAX_PATTERN_SIZE); + const height = Math.min(Math.ceil(Math.abs(boundsHeight * combinedScale[1] * EXPECTED_SCALE)), MAX_PATTERN_SIZE); + const scaleX = boundsWidth / width; + const scaleY = boundsHeight / height; + const context = { + coords: this._coords, + colors: this._colors, + offsetX: -offsetX, + offsetY: -offsetY, + scaleX: 1 / scaleX, + scaleY: 1 / scaleY + }; + const paddedWidth = width + BORDER_SIZE * 2; + const paddedHeight = height + BORDER_SIZE * 2; + const tmpCanvas = cachedCanvases.getCanvas("mesh", paddedWidth, paddedHeight); + const tmpCtx = tmpCanvas.context; + const data = tmpCtx.createImageData(width, height); + if (backgroundColor) { + const bytes = data.data; + for (let i = 0, ii = bytes.length; i < ii; i += 4) { + bytes[i] = backgroundColor[0]; + bytes[i + 1] = backgroundColor[1]; + bytes[i + 2] = backgroundColor[2]; + bytes[i + 3] = 255; + } + } + for (const figure of this._figures) { + drawFigure(data, figure, context); + } + tmpCtx.putImageData(data, BORDER_SIZE, BORDER_SIZE); + const canvas = tmpCanvas.canvas; + return { + canvas, + offsetX: offsetX - BORDER_SIZE * scaleX, + offsetY: offsetY - BORDER_SIZE * scaleY, + scaleX, + scaleY + }; + } + isModifyingCurrentTransform() { + return true; + } + getPattern(ctx, owner, inverse, pathType) { + applyBoundingBox(ctx, this._bbox); + const scale = new Float32Array(2); + if (pathType === PathType.SHADING) { + Util.singularValueDecompose2dScale(getCurrentTransform(ctx), scale); + } else if (this.matrix) { + Util.singularValueDecompose2dScale(this.matrix, scale); + const [matrixScaleX, matrixScaleY] = scale; + Util.singularValueDecompose2dScale(owner.baseTransform, scale); + scale[0] *= matrixScaleX; + scale[1] *= matrixScaleY; + } else { + Util.singularValueDecompose2dScale(owner.baseTransform, scale); + } + const temporaryPatternCanvas = this._createMeshCanvas(scale, pathType === PathType.SHADING ? null : this._background, owner.cachedCanvases); + if (pathType !== PathType.SHADING) { + ctx.setTransform(...owner.baseTransform); + if (this.matrix) { + ctx.transform(...this.matrix); + } + } + ctx.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY); + ctx.scale(temporaryPatternCanvas.scaleX, temporaryPatternCanvas.scaleY); + return ctx.createPattern(temporaryPatternCanvas.canvas, "no-repeat"); + } +} +class DummyShadingPattern extends BaseShadingPattern { + getPattern() { + return "hotpink"; + } +} +function getShadingPattern(IR) { + switch (IR[0]) { + case "RadialAxial": + return new RadialAxialShadingPattern(IR); + case "Mesh": + return new MeshShadingPattern(IR); + case "Dummy": + return new DummyShadingPattern(); + } + throw new Error(`Unknown IR type: ${IR[0]}`); +} +const PaintType = { + COLORED: 1, + UNCOLORED: 2 +}; +class TilingPattern { + static MAX_PATTERN_SIZE = 3e3; + constructor(IR, ctx, canvasGraphicsFactory, baseTransform) { + this.color = IR[1]; + this.operatorList = IR[2]; + this.matrix = IR[3]; + this.bbox = IR[4]; + this.xstep = IR[5]; + this.ystep = IR[6]; + this.paintType = IR[7]; + this.tilingType = IR[8]; + this.ctx = ctx; + this.canvasGraphicsFactory = canvasGraphicsFactory; + this.baseTransform = baseTransform; + } + createPatternCanvas(owner, opIdx) { + const { + bbox, + operatorList, + paintType, + tilingType, + color, + canvasGraphicsFactory + } = this; + let { + xstep, + ystep + } = this; + xstep = Math.abs(xstep); + ystep = Math.abs(ystep); + info("TilingType: " + tilingType); + const x0 = bbox[0], y0 = bbox[1], x1 = bbox[2], y1 = bbox[3]; + const width = x1 - x0; + const height = y1 - y0; + const scale = new Float32Array(2); + Util.singularValueDecompose2dScale(this.matrix, scale); + const [matrixScaleX, matrixScaleY] = scale; + Util.singularValueDecompose2dScale(this.baseTransform, scale); + const combinedScaleX = matrixScaleX * scale[0]; + const combinedScaleY = matrixScaleY * scale[1]; + let canvasWidth = width, canvasHeight = height, redrawHorizontally = false, redrawVertically = false; + const xScaledStep = Math.ceil(xstep * combinedScaleX); + const yScaledStep = Math.ceil(ystep * combinedScaleY); + const xScaledWidth = Math.ceil(width * combinedScaleX); + const yScaledHeight = Math.ceil(height * combinedScaleY); + if (xScaledStep >= xScaledWidth) { + canvasWidth = xstep; + } else { + redrawHorizontally = true; + } + if (yScaledStep >= yScaledHeight) { + canvasHeight = ystep; + } else { + redrawVertically = true; + } + const dimx = this.getSizeAndScale(canvasWidth, this.ctx.canvas.width, combinedScaleX); + const dimy = this.getSizeAndScale(canvasHeight, this.ctx.canvas.height, combinedScaleY); + const tmpCanvas = owner.cachedCanvases.getCanvas("pattern", dimx.size, dimy.size); + const tmpCtx = tmpCanvas.context; + const graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx, opIdx); + graphics.groupLevel = owner.groupLevel; + this.setFillAndStrokeStyleToContext(graphics, paintType, color); + tmpCtx.translate(-dimx.scale * x0, -dimy.scale * y0); + graphics.transform(0, dimx.scale, 0, 0, dimy.scale, 0, 0); + tmpCtx.save(); + graphics.dependencyTracker?.save(); + this.clipBbox(graphics, x0, y0, x1, y1); + graphics.baseTransform = getCurrentTransform(graphics.ctx); + graphics.executeOperatorList(operatorList); + graphics.endDrawing(); + graphics.dependencyTracker?.restore(); + tmpCtx.restore(); + if (redrawHorizontally || redrawVertically) { + const image = tmpCanvas.canvas; + if (redrawHorizontally) { + canvasWidth = xstep; + } + if (redrawVertically) { + canvasHeight = ystep; + } + const dimx2 = this.getSizeAndScale(canvasWidth, this.ctx.canvas.width, combinedScaleX); + const dimy2 = this.getSizeAndScale(canvasHeight, this.ctx.canvas.height, combinedScaleY); + const xSize = dimx2.size; + const ySize = dimy2.size; + const tmpCanvas2 = owner.cachedCanvases.getCanvas("pattern-workaround", xSize, ySize); + const tmpCtx2 = tmpCanvas2.context; + const ii = redrawHorizontally ? Math.floor(width / xstep) : 0; + const jj = redrawVertically ? Math.floor(height / ystep) : 0; + for (let i = 0; i <= ii; i++) { + for (let j = 0; j <= jj; j++) { + tmpCtx2.drawImage(image, xSize * i, ySize * j, xSize, ySize, 0, 0, xSize, ySize); + } + } + return { + canvas: tmpCanvas2.canvas, + scaleX: dimx2.scale, + scaleY: dimy2.scale, + offsetX: x0, + offsetY: y0 + }; + } + return { + canvas: tmpCanvas.canvas, + scaleX: dimx.scale, + scaleY: dimy.scale, + offsetX: x0, + offsetY: y0 + }; + } + getSizeAndScale(step, realOutputSize, scale) { + const maxSize = Math.max(TilingPattern.MAX_PATTERN_SIZE, realOutputSize); + let size = Math.ceil(step * scale); + if (size >= maxSize) { + size = maxSize; + } else { + scale = size / step; + } + return { + scale, + size + }; + } + clipBbox(graphics, x0, y0, x1, y1) { + const bboxWidth = x1 - x0; + const bboxHeight = y1 - y0; + graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight); + Util.axialAlignedBoundingBox([x0, y0, x1, y1], getCurrentTransform(graphics.ctx), graphics.current.minMax); + graphics.clip(); + graphics.endPath(); + } + setFillAndStrokeStyleToContext(graphics, paintType, color) { + const context = graphics.ctx, current = graphics.current; + switch (paintType) { + case PaintType.COLORED: + const { + fillStyle, + strokeStyle + } = this.ctx; + context.fillStyle = current.fillColor = fillStyle; + context.strokeStyle = current.strokeColor = strokeStyle; + break; + case PaintType.UNCOLORED: + context.fillStyle = context.strokeStyle = color; + current.fillColor = current.strokeColor = color; + break; + default: + throw new FormatError(`Unsupported paint type: ${paintType}`); + } + } + isModifyingCurrentTransform() { + return false; + } + getPattern(ctx, owner, inverse, pathType, opIdx) { + let matrix = inverse; + if (pathType !== PathType.SHADING) { + matrix = Util.transform(matrix, owner.baseTransform); + if (this.matrix) { + matrix = Util.transform(matrix, this.matrix); + } + } + const temporaryPatternCanvas = this.createPatternCanvas(owner, opIdx); + let domMatrix = new DOMMatrix(matrix); + domMatrix = domMatrix.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY); + domMatrix = domMatrix.scale(1 / temporaryPatternCanvas.scaleX, 1 / temporaryPatternCanvas.scaleY); + const pattern = ctx.createPattern(temporaryPatternCanvas.canvas, "repeat"); + pattern.setTransform(domMatrix); + return pattern; + } +} +function convertBlackAndWhiteToRGBA({ + src, + srcPos = 0, + dest, + width, + height, + nonBlackColor = 4294967295, + inverseDecode = false +}) { + const black = util_FeatureTest.isLittleEndian ? 4278190080 : 255; + const [zeroMapping, oneMapping] = inverseDecode ? [nonBlackColor, black] : [black, nonBlackColor]; + const widthInSource = width >> 3; + const widthRemainder = width & 7; + const srcLength = src.length; + dest = new Uint32Array(dest.buffer); + let destPos = 0; + for (let i = 0; i < height; i++) { + for (const max = srcPos + widthInSource; srcPos < max; srcPos++) { + const elem2 = srcPos < srcLength ? src[srcPos] : 255; + dest[destPos++] = elem2 & 128 ? oneMapping : zeroMapping; + dest[destPos++] = elem2 & 64 ? oneMapping : zeroMapping; + dest[destPos++] = elem2 & 32 ? oneMapping : zeroMapping; + dest[destPos++] = elem2 & 16 ? oneMapping : zeroMapping; + dest[destPos++] = elem2 & 8 ? oneMapping : zeroMapping; + dest[destPos++] = elem2 & 4 ? oneMapping : zeroMapping; + dest[destPos++] = elem2 & 2 ? oneMapping : zeroMapping; + dest[destPos++] = elem2 & 1 ? oneMapping : zeroMapping; + } + if (widthRemainder === 0) { + continue; + } + const elem = srcPos < srcLength ? src[srcPos++] : 255; + for (let j = 0; j < widthRemainder; j++) { + dest[destPos++] = elem & 1 << 7 - j ? oneMapping : zeroMapping; + } + } + return { + srcPos, + destPos + }; +} +const MIN_FONT_SIZE = 16; +const MAX_FONT_SIZE = 100; +const EXECUTION_TIME = 15; +const EXECUTION_STEPS = 10; +const FULL_CHUNK_HEIGHT = 16; +const SCALE_MATRIX = new DOMMatrix(); +const XY = new Float32Array(2); +const MIN_MAX_INIT = new Float32Array([Infinity, Infinity, -Infinity, -Infinity]); +function mirrorContextOperations(ctx, destCtx) { + if (ctx._removeMirroring) { + throw new Error("Context is already forwarding operations."); + } + ctx.__originalSave = ctx.save; + ctx.__originalRestore = ctx.restore; + ctx.__originalRotate = ctx.rotate; + ctx.__originalScale = ctx.scale; + ctx.__originalTranslate = ctx.translate; + ctx.__originalTransform = ctx.transform; + ctx.__originalSetTransform = ctx.setTransform; + ctx.__originalResetTransform = ctx.resetTransform; + ctx.__originalClip = ctx.clip; + ctx.__originalMoveTo = ctx.moveTo; + ctx.__originalLineTo = ctx.lineTo; + ctx.__originalBezierCurveTo = ctx.bezierCurveTo; + ctx.__originalRect = ctx.rect; + ctx.__originalClosePath = ctx.closePath; + ctx.__originalBeginPath = ctx.beginPath; + ctx._removeMirroring = () => { + ctx.save = ctx.__originalSave; + ctx.restore = ctx.__originalRestore; + ctx.rotate = ctx.__originalRotate; + ctx.scale = ctx.__originalScale; + ctx.translate = ctx.__originalTranslate; + ctx.transform = ctx.__originalTransform; + ctx.setTransform = ctx.__originalSetTransform; + ctx.resetTransform = ctx.__originalResetTransform; + ctx.clip = ctx.__originalClip; + ctx.moveTo = ctx.__originalMoveTo; + ctx.lineTo = ctx.__originalLineTo; + ctx.bezierCurveTo = ctx.__originalBezierCurveTo; + ctx.rect = ctx.__originalRect; + ctx.closePath = ctx.__originalClosePath; + ctx.beginPath = ctx.__originalBeginPath; + delete ctx._removeMirroring; + }; + ctx.save = function() { + destCtx.save(); + this.__originalSave(); + }; + ctx.restore = function() { + destCtx.restore(); + this.__originalRestore(); + }; + ctx.translate = function(x, y) { + destCtx.translate(x, y); + this.__originalTranslate(x, y); + }; + ctx.scale = function(x, y) { + destCtx.scale(x, y); + this.__originalScale(x, y); + }; + ctx.transform = function(a, b, c, d, e, f) { + destCtx.transform(a, b, c, d, e, f); + this.__originalTransform(a, b, c, d, e, f); + }; + ctx.setTransform = function(a, b, c, d, e, f) { + destCtx.setTransform(a, b, c, d, e, f); + this.__originalSetTransform(a, b, c, d, e, f); + }; + ctx.resetTransform = function() { + destCtx.resetTransform(); + this.__originalResetTransform(); + }; + ctx.rotate = function(angle) { + destCtx.rotate(angle); + this.__originalRotate(angle); + }; + ctx.clip = function(rule) { + destCtx.clip(rule); + this.__originalClip(rule); + }; + ctx.moveTo = function(x, y) { + destCtx.moveTo(x, y); + this.__originalMoveTo(x, y); + }; + ctx.lineTo = function(x, y) { + destCtx.lineTo(x, y); + this.__originalLineTo(x, y); + }; + ctx.bezierCurveTo = function(cp1x, cp1y, cp2x, cp2y, x, y) { + destCtx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); + this.__originalBezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); + }; + ctx.rect = function(x, y, width, height) { + destCtx.rect(x, y, width, height); + this.__originalRect(x, y, width, height); + }; + ctx.closePath = function() { + destCtx.closePath(); + this.__originalClosePath(); + }; + ctx.beginPath = function() { + destCtx.beginPath(); + this.__originalBeginPath(); + }; +} +class CachedCanvases { + constructor(canvasFactory) { + this.canvasFactory = canvasFactory; + this.cache = /* @__PURE__ */ Object.create(null); + } + getCanvas(id, width, height) { + let canvasEntry; + if (this.cache[id] !== void 0) { + canvasEntry = this.cache[id]; + this.canvasFactory.reset(canvasEntry, width, height); + } else { + canvasEntry = this.canvasFactory.create(width, height); + this.cache[id] = canvasEntry; + } + return canvasEntry; + } + delete(id) { + delete this.cache[id]; + } + clear() { + for (const id in this.cache) { + const canvasEntry = this.cache[id]; + this.canvasFactory.destroy(canvasEntry); + delete this.cache[id]; + } + } +} +function drawImageAtIntegerCoords(ctx, srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH) { + const [a, b, c, d, tx, ty] = getCurrentTransform(ctx); + if (b === 0 && c === 0) { + const tlX = destX * a + tx; + const rTlX = Math.round(tlX); + const tlY = destY * d + ty; + const rTlY = Math.round(tlY); + const brX = (destX + destW) * a + tx; + const rWidth = Math.abs(Math.round(brX) - rTlX) || 1; + const brY = (destY + destH) * d + ty; + const rHeight = Math.abs(Math.round(brY) - rTlY) || 1; + ctx.setTransform(Math.sign(a), 0, 0, Math.sign(d), rTlX, rTlY); + ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rWidth, rHeight); + ctx.setTransform(a, b, c, d, tx, ty); + return [rWidth, rHeight]; + } + if (a === 0 && d === 0) { + const tlX = destY * c + tx; + const rTlX = Math.round(tlX); + const tlY = destX * b + ty; + const rTlY = Math.round(tlY); + const brX = (destY + destH) * c + tx; + const rWidth = Math.abs(Math.round(brX) - rTlX) || 1; + const brY = (destX + destW) * b + ty; + const rHeight = Math.abs(Math.round(brY) - rTlY) || 1; + ctx.setTransform(0, Math.sign(b), Math.sign(c), 0, rTlX, rTlY); + ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, 0, 0, rHeight, rWidth); + ctx.setTransform(a, b, c, d, tx, ty); + return [rHeight, rWidth]; + } + ctx.drawImage(srcImg, srcX, srcY, srcW, srcH, destX, destY, destW, destH); + const scaleX = Math.hypot(a, b); + const scaleY = Math.hypot(c, d); + return [scaleX * destW, scaleY * destH]; +} +class CanvasExtraState { + alphaIsShape = false; + fontSize = 0; + fontSizeScale = 1; + textMatrix = null; + textMatrixScale = 1; + fontMatrix = FONT_IDENTITY_MATRIX; + leading = 0; + x = 0; + y = 0; + lineX = 0; + lineY = 0; + charSpacing = 0; + wordSpacing = 0; + textHScale = 1; + textRenderingMode = TextRenderingMode.FILL; + textRise = 0; + fillColor = "#000000"; + strokeColor = "#000000"; + patternFill = false; + patternStroke = false; + fillAlpha = 1; + strokeAlpha = 1; + lineWidth = 1; + activeSMask = null; + transferMaps = "none"; + constructor(width, height, preInit) { + preInit?.(this); + this.clipBox = new Float32Array([0, 0, width, height]); + this.minMax = MIN_MAX_INIT.slice(); + } + clone() { + const clone = Object.create(this); + clone.clipBox = this.clipBox.slice(); + clone.minMax = this.minMax.slice(); + return clone; + } + getPathBoundingBox(pathType = PathType.FILL, transform = null) { + const box = this.minMax.slice(); + if (pathType === PathType.STROKE) { + if (!transform) { + unreachable("Stroke bounding box must include transform."); + } + Util.singularValueDecompose2dScale(transform, XY); + const xStrokePad = XY[0] * this.lineWidth / 2; + const yStrokePad = XY[1] * this.lineWidth / 2; + box[0] -= xStrokePad; + box[1] -= yStrokePad; + box[2] += xStrokePad; + box[3] += yStrokePad; + } + return box; + } + updateClipFromPath() { + const intersect = Util.intersect(this.clipBox, this.getPathBoundingBox()); + this.startNewPathAndClipBox(intersect || [0, 0, 0, 0]); + } + isEmptyClip() { + return this.minMax[0] === Infinity; + } + startNewPathAndClipBox(box) { + this.clipBox.set(box, 0); + this.minMax.set(MIN_MAX_INIT, 0); + } + getClippedPathBoundingBox(pathType = PathType.FILL, transform = null) { + return Util.intersect(this.clipBox, this.getPathBoundingBox(pathType, transform)); + } +} +function putBinaryImageData(ctx, imgData) { + if (imgData instanceof ImageData) { + ctx.putImageData(imgData, 0, 0); + return; + } + const height = imgData.height, width = imgData.width; + const partialChunkHeight = height % FULL_CHUNK_HEIGHT; + const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT; + const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1; + const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT); + let srcPos = 0, destPos; + const src = imgData.data; + const dest = chunkImgData.data; + let i, j, thisChunkHeight, elemsInThisChunk; + if (imgData.kind === util_ImageKind.GRAYSCALE_1BPP) { + const srcLength = src.byteLength; + const dest32 = new Uint32Array(dest.buffer, 0, dest.byteLength >> 2); + const dest32DataLength = dest32.length; + const fullSrcDiff = width + 7 >> 3; + const white = 4294967295; + const black = util_FeatureTest.isLittleEndian ? 4278190080 : 255; + for (i = 0; i < totalChunks; i++) { + thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight; + destPos = 0; + for (j = 0; j < thisChunkHeight; j++) { + const srcDiff = srcLength - srcPos; + let k = 0; + const kEnd = srcDiff > fullSrcDiff ? width : srcDiff * 8 - 7; + const kEndUnrolled = kEnd & -8; + let mask = 0; + let srcByte = 0; + for (; k < kEndUnrolled; k += 8) { + srcByte = src[srcPos++]; + dest32[destPos++] = srcByte & 128 ? white : black; + dest32[destPos++] = srcByte & 64 ? white : black; + dest32[destPos++] = srcByte & 32 ? white : black; + dest32[destPos++] = srcByte & 16 ? white : black; + dest32[destPos++] = srcByte & 8 ? white : black; + dest32[destPos++] = srcByte & 4 ? white : black; + dest32[destPos++] = srcByte & 2 ? white : black; + dest32[destPos++] = srcByte & 1 ? white : black; + } + for (; k < kEnd; k++) { + if (mask === 0) { + srcByte = src[srcPos++]; + mask = 128; + } + dest32[destPos++] = srcByte & mask ? white : black; + mask >>= 1; + } + } + while (destPos < dest32DataLength) { + dest32[destPos++] = 0; + } + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } + } else if (imgData.kind === util_ImageKind.RGBA_32BPP) { + j = 0; + elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4; + for (i = 0; i < fullChunks; i++) { + dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk)); + srcPos += elemsInThisChunk; + ctx.putImageData(chunkImgData, 0, j); + j += FULL_CHUNK_HEIGHT; + } + if (i < totalChunks) { + elemsInThisChunk = width * partialChunkHeight * 4; + dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk)); + ctx.putImageData(chunkImgData, 0, j); + } + } else if (imgData.kind === util_ImageKind.RGB_24BPP) { + thisChunkHeight = FULL_CHUNK_HEIGHT; + elemsInThisChunk = width * thisChunkHeight; + for (i = 0; i < totalChunks; i++) { + if (i >= fullChunks) { + thisChunkHeight = partialChunkHeight; + elemsInThisChunk = width * thisChunkHeight; + } + destPos = 0; + for (j = elemsInThisChunk; j--; ) { + dest[destPos++] = src[srcPos++]; + dest[destPos++] = src[srcPos++]; + dest[destPos++] = src[srcPos++]; + dest[destPos++] = 255; + } + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } + } else { + throw new Error(`bad image kind: ${imgData.kind}`); + } +} +function putBinaryImageMask(ctx, imgData) { + if (imgData.bitmap) { + ctx.drawImage(imgData.bitmap, 0, 0); + return; + } + const height = imgData.height, width = imgData.width; + const partialChunkHeight = height % FULL_CHUNK_HEIGHT; + const fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT; + const totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1; + const chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT); + let srcPos = 0; + const src = imgData.data; + const dest = chunkImgData.data; + for (let i = 0; i < totalChunks; i++) { + const thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight; + ({ + srcPos + } = convertBlackAndWhiteToRGBA({ + src, + srcPos, + dest, + width, + height: thisChunkHeight, + nonBlackColor: 0 + })); + ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT); + } +} +function copyCtxState(sourceCtx, destCtx) { + const properties = ["strokeStyle", "fillStyle", "fillRule", "globalAlpha", "lineWidth", "lineCap", "lineJoin", "miterLimit", "globalCompositeOperation", "font", "filter"]; + for (const property of properties) { + if (sourceCtx[property] !== void 0) { + destCtx[property] = sourceCtx[property]; + } + } + if (sourceCtx.setLineDash !== void 0) { + destCtx.setLineDash(sourceCtx.getLineDash()); + destCtx.lineDashOffset = sourceCtx.lineDashOffset; + } +} +function resetCtxToDefault(ctx) { + ctx.strokeStyle = ctx.fillStyle = "#000000"; + ctx.fillRule = "nonzero"; + ctx.globalAlpha = 1; + ctx.lineWidth = 1; + ctx.lineCap = "butt"; + ctx.lineJoin = "miter"; + ctx.miterLimit = 10; + ctx.globalCompositeOperation = "source-over"; + ctx.font = "10px sans-serif"; + if (ctx.setLineDash !== void 0) { + ctx.setLineDash([]); + ctx.lineDashOffset = 0; + } + const { + filter + } = ctx; + if (filter !== "none" && filter !== "") { + ctx.filter = "none"; + } +} +function getImageSmoothingEnabled(transform, interpolate) { + if (interpolate) { + return true; + } + Util.singularValueDecompose2dScale(transform, XY); + const actualScale = Math.fround(OutputScale.pixelRatio * PixelsPerInch.PDF_TO_CSS_UNITS); + return XY[0] <= actualScale && XY[1] <= actualScale; +} +const LINE_CAP_STYLES = ["butt", "round", "square"]; +const LINE_JOIN_STYLES = ["miter", "round", "bevel"]; +const NORMAL_CLIP = {}; +const EO_CLIP = {}; +class CanvasGraphics { + constructor(canvasCtx, commonObjs, objs, canvasFactory, filterFactory, { + optionalContentConfig, + markedContentStack = null + }, annotationCanvasMap, pageColors, dependencyTracker) { + this.ctx = canvasCtx; + this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height); + this.stateStack = []; + this.pendingClip = null; + this.pendingEOFill = false; + this.res = null; + this.xobjs = null; + this.commonObjs = commonObjs; + this.objs = objs; + this.canvasFactory = canvasFactory; + this.filterFactory = filterFactory; + this.groupStack = []; + this.baseTransform = null; + this.baseTransformStack = []; + this.groupLevel = 0; + this.smaskStack = []; + this.smaskCounter = 0; + this.tempSMask = null; + this.suspendedCtx = null; + this.contentVisible = true; + this.markedContentStack = markedContentStack || []; + this.optionalContentConfig = optionalContentConfig; + this.cachedCanvases = new CachedCanvases(this.canvasFactory); + this.cachedPatterns = /* @__PURE__ */ new Map(); + this.annotationCanvasMap = annotationCanvasMap; + this.viewportScale = 1; + this.outputScaleX = 1; + this.outputScaleY = 1; + this.pageColors = pageColors; + this._cachedScaleForStroking = [-1, 0]; + this._cachedGetSinglePixelWidth = null; + this._cachedBitmapsMap = /* @__PURE__ */ new Map(); + this.dependencyTracker = dependencyTracker ?? null; + } + getObject(opIdx, data, fallback = null) { + if (typeof data === "string") { + this.dependencyTracker?.recordNamedDependency(opIdx, data); + return data.startsWith("g_") ? this.commonObjs.get(data) : this.objs.get(data); + } + return fallback; + } + beginDrawing({ + transform, + viewport, + transparency = false, + background = null + }) { + const width = this.ctx.canvas.width; + const height = this.ctx.canvas.height; + const savedFillStyle = this.ctx.fillStyle; + this.ctx.fillStyle = background || "#ffffff"; + this.ctx.fillRect(0, 0, width, height); + this.ctx.fillStyle = savedFillStyle; + if (transparency) { + const transparentCanvas = this.cachedCanvases.getCanvas("transparent", width, height); + this.compositeCtx = this.ctx; + this.transparentCanvas = transparentCanvas.canvas; + this.ctx = transparentCanvas.context; + this.ctx.save(); + this.ctx.transform(...getCurrentTransform(this.compositeCtx)); + } + this.ctx.save(); + resetCtxToDefault(this.ctx); + if (transform) { + this.ctx.transform(...transform); + this.outputScaleX = transform[0]; + this.outputScaleY = transform[0]; + } + this.ctx.transform(...viewport.transform); + this.viewportScale = viewport.scale; + this.baseTransform = getCurrentTransform(this.ctx); + } + executeOperatorList(operatorList, executionStartIdx, continueCallback, stepper, operationsFilter) { + const argsArray = operatorList.argsArray; + const fnArray = operatorList.fnArray; + let i = executionStartIdx || 0; + const argsArrayLen = argsArray.length; + if (argsArrayLen === i) { + return i; + } + const chunkOperations = argsArrayLen - i > EXECUTION_STEPS && typeof continueCallback === "function"; + const endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0; + let steps = 0; + const commonObjs = this.commonObjs; + const objs = this.objs; + let fnId, fnArgs; + while (true) { + if (stepper !== void 0 && i === stepper.nextBreakPoint) { + stepper.breakIt(i, continueCallback); + return i; + } + if (!operationsFilter || operationsFilter(i)) { + fnId = fnArray[i]; + fnArgs = argsArray[i] ?? null; + if (fnId !== OPS.dependency) { + if (fnArgs === null) { + this[fnId](i); + } else { + this[fnId](i, ...fnArgs); + } + } else { + for (const depObjId of fnArgs) { + this.dependencyTracker?.recordNamedData(depObjId, i); + const objsPool = depObjId.startsWith("g_") ? commonObjs : objs; + if (!objsPool.has(depObjId)) { + objsPool.get(depObjId, continueCallback); + return i; + } + } + } + } + i++; + if (i === argsArrayLen) { + return i; + } + if (chunkOperations && ++steps > EXECUTION_STEPS) { + if (Date.now() > endTime) { + continueCallback(); + return i; + } + steps = 0; + } + } + } + #restoreInitialState() { + while (this.stateStack.length || this.inSMaskMode) { + this.restore(); + } + this.current.activeSMask = null; + this.ctx.restore(); + if (this.transparentCanvas) { + this.ctx = this.compositeCtx; + this.ctx.save(); + this.ctx.setTransform(1, 0, 0, 1, 0, 0); + this.ctx.drawImage(this.transparentCanvas, 0, 0); + this.ctx.restore(); + this.transparentCanvas = null; + } + } + endDrawing() { + this.#restoreInitialState(); + this.cachedCanvases.clear(); + this.cachedPatterns.clear(); + for (const cache of this._cachedBitmapsMap.values()) { + for (const canvas of cache.values()) { + if (typeof HTMLCanvasElement !== "undefined" && canvas instanceof HTMLCanvasElement) { + canvas.width = canvas.height = 0; + } + } + cache.clear(); + } + this._cachedBitmapsMap.clear(); + this.#drawFilter(); + } + #drawFilter() { + if (this.pageColors) { + const hcmFilterId = this.filterFactory.addHCMFilter(this.pageColors.foreground, this.pageColors.background); + if (hcmFilterId !== "none") { + const savedFilter = this.ctx.filter; + this.ctx.filter = hcmFilterId; + this.ctx.drawImage(this.ctx.canvas, 0, 0); + this.ctx.filter = savedFilter; + } + } + } + _scaleImage(img, inverseTransform) { + const width = img.width ?? img.displayWidth; + const height = img.height ?? img.displayHeight; + let widthScale = Math.max(Math.hypot(inverseTransform[0], inverseTransform[1]), 1); + let heightScale = Math.max(Math.hypot(inverseTransform[2], inverseTransform[3]), 1); + let paintWidth = width, paintHeight = height; + let tmpCanvasId = "prescale1"; + let tmpCanvas, tmpCtx; + while (widthScale > 2 && paintWidth > 1 || heightScale > 2 && paintHeight > 1) { + let newWidth = paintWidth, newHeight = paintHeight; + if (widthScale > 2 && paintWidth > 1) { + newWidth = paintWidth >= 16384 ? Math.floor(paintWidth / 2) - 1 || 1 : Math.ceil(paintWidth / 2); + widthScale /= paintWidth / newWidth; + } + if (heightScale > 2 && paintHeight > 1) { + newHeight = paintHeight >= 16384 ? Math.floor(paintHeight / 2) - 1 || 1 : Math.ceil(paintHeight) / 2; + heightScale /= paintHeight / newHeight; + } + tmpCanvas = this.cachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight); + tmpCtx = tmpCanvas.context; + tmpCtx.clearRect(0, 0, newWidth, newHeight); + tmpCtx.drawImage(img, 0, 0, paintWidth, paintHeight, 0, 0, newWidth, newHeight); + img = tmpCanvas.canvas; + paintWidth = newWidth; + paintHeight = newHeight; + tmpCanvasId = tmpCanvasId === "prescale1" ? "prescale2" : "prescale1"; + } + return { + img, + paintWidth, + paintHeight + }; + } + _createMaskCanvas(opIdx, img) { + const ctx = this.ctx; + const { + width, + height + } = img; + const fillColor = this.current.fillColor; + const isPatternFill = this.current.patternFill; + const currentTransform = getCurrentTransform(ctx); + let cache, cacheKey, scaled, maskCanvas; + if ((img.bitmap || img.data) && img.count > 1) { + const mainKey = img.bitmap || img.data.buffer; + cacheKey = JSON.stringify(isPatternFill ? currentTransform : [currentTransform.slice(0, 4), fillColor]); + cache = this._cachedBitmapsMap.get(mainKey); + if (!cache) { + cache = /* @__PURE__ */ new Map(); + this._cachedBitmapsMap.set(mainKey, cache); + } + const cachedImage = cache.get(cacheKey); + if (cachedImage && !isPatternFill) { + const offsetX2 = Math.round(Math.min(currentTransform[0], currentTransform[2]) + currentTransform[4]); + const offsetY2 = Math.round(Math.min(currentTransform[1], currentTransform[3]) + currentTransform[5]); + this.dependencyTracker?.recordDependencies(opIdx, Dependencies.transformAndFill); + return { + canvas: cachedImage, + offsetX: offsetX2, + offsetY: offsetY2 + }; + } + scaled = cachedImage; + } + if (!scaled) { + maskCanvas = this.cachedCanvases.getCanvas("maskCanvas", width, height); + putBinaryImageMask(maskCanvas.context, img); + } + let maskToCanvas = Util.transform(currentTransform, [1 / width, 0, 0, -1 / height, 0, 0]); + maskToCanvas = Util.transform(maskToCanvas, [1, 0, 0, 1, 0, -height]); + const minMax = MIN_MAX_INIT.slice(); + Util.axialAlignedBoundingBox([0, 0, width, height], maskToCanvas, minMax); + const [minX, minY, maxX, maxY] = minMax; + const drawnWidth = Math.round(maxX - minX) || 1; + const drawnHeight = Math.round(maxY - minY) || 1; + const fillCanvas = this.cachedCanvases.getCanvas("fillCanvas", drawnWidth, drawnHeight); + const fillCtx = fillCanvas.context; + const offsetX = minX; + const offsetY = minY; + fillCtx.translate(-offsetX, -offsetY); + fillCtx.transform(...maskToCanvas); + if (!scaled) { + scaled = this._scaleImage(maskCanvas.canvas, getCurrentTransformInverse(fillCtx)); + scaled = scaled.img; + if (cache && isPatternFill) { + cache.set(cacheKey, scaled); + } + } + fillCtx.imageSmoothingEnabled = getImageSmoothingEnabled(getCurrentTransform(fillCtx), img.interpolate); + drawImageAtIntegerCoords(fillCtx, scaled, 0, 0, scaled.width, scaled.height, 0, 0, width, height); + fillCtx.globalCompositeOperation = "source-in"; + const inverse = Util.transform(getCurrentTransformInverse(fillCtx), [1, 0, 0, 1, -offsetX, -offsetY]); + fillCtx.fillStyle = isPatternFill ? fillColor.getPattern(ctx, this, inverse, PathType.FILL, opIdx) : fillColor; + fillCtx.fillRect(0, 0, width, height); + if (cache && !isPatternFill) { + this.cachedCanvases.delete("fillCanvas"); + cache.set(cacheKey, fillCanvas.canvas); + } + this.dependencyTracker?.recordDependencies(opIdx, Dependencies.transformAndFill); + return { + canvas: fillCanvas.canvas, + offsetX: Math.round(offsetX), + offsetY: Math.round(offsetY) + }; + } + setLineWidth(opIdx, width) { + this.dependencyTracker?.recordSimpleData("lineWidth", opIdx); + if (width !== this.current.lineWidth) { + this._cachedScaleForStroking[0] = -1; + } + this.current.lineWidth = width; + this.ctx.lineWidth = width; + } + setLineCap(opIdx, style) { + this.dependencyTracker?.recordSimpleData("lineCap", opIdx); + this.ctx.lineCap = LINE_CAP_STYLES[style]; + } + setLineJoin(opIdx, style) { + this.dependencyTracker?.recordSimpleData("lineJoin", opIdx); + this.ctx.lineJoin = LINE_JOIN_STYLES[style]; + } + setMiterLimit(opIdx, limit) { + this.dependencyTracker?.recordSimpleData("miterLimit", opIdx); + this.ctx.miterLimit = limit; + } + setDash(opIdx, dashArray, dashPhase) { + this.dependencyTracker?.recordSimpleData("dash", opIdx); + const ctx = this.ctx; + if (ctx.setLineDash !== void 0) { + ctx.setLineDash(dashArray); + ctx.lineDashOffset = dashPhase; + } + } + setRenderingIntent(opIdx, intent) { + } + setFlatness(opIdx, flatness) { + } + setGState(opIdx, states) { + for (const [key, value] of states) { + switch (key) { + case "LW": + this.setLineWidth(opIdx, value); + break; + case "LC": + this.setLineCap(opIdx, value); + break; + case "LJ": + this.setLineJoin(opIdx, value); + break; + case "ML": + this.setMiterLimit(opIdx, value); + break; + case "D": + this.setDash(opIdx, value[0], value[1]); + break; + case "RI": + this.setRenderingIntent(opIdx, value); + break; + case "FL": + this.setFlatness(opIdx, value); + break; + case "Font": + this.setFont(opIdx, value[0], value[1]); + break; + case "CA": + this.dependencyTracker?.recordSimpleData("strokeAlpha", opIdx); + this.current.strokeAlpha = value; + break; + case "ca": + this.dependencyTracker?.recordSimpleData("fillAlpha", opIdx); + this.ctx.globalAlpha = this.current.fillAlpha = value; + break; + case "BM": + this.dependencyTracker?.recordSimpleData("globalCompositeOperation", opIdx); + this.ctx.globalCompositeOperation = value; + break; + case "SMask": + this.dependencyTracker?.recordSimpleData("SMask", opIdx); + this.current.activeSMask = value ? this.tempSMask : null; + this.tempSMask = null; + this.checkSMaskState(); + break; + case "TR": + this.dependencyTracker?.recordSimpleData("filter", opIdx); + this.ctx.filter = this.current.transferMaps = this.filterFactory.addFilter(value); + break; + } + } + } + get inSMaskMode() { + return !!this.suspendedCtx; + } + checkSMaskState() { + const inSMaskMode = this.inSMaskMode; + if (this.current.activeSMask && !inSMaskMode) { + this.beginSMaskMode(); + } else if (!this.current.activeSMask && inSMaskMode) { + this.endSMaskMode(); + } + } + beginSMaskMode(opIdx) { + if (this.inSMaskMode) { + throw new Error("beginSMaskMode called while already in smask mode"); + } + const drawnWidth = this.ctx.canvas.width; + const drawnHeight = this.ctx.canvas.height; + const cacheId = "smaskGroupAt" + this.groupLevel; + const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight); + this.suspendedCtx = this.ctx; + const ctx = this.ctx = scratchCanvas.context; + ctx.setTransform(this.suspendedCtx.getTransform()); + copyCtxState(this.suspendedCtx, ctx); + mirrorContextOperations(ctx, this.suspendedCtx); + this.setGState(opIdx, [["BM", "source-over"]]); + } + endSMaskMode() { + if (!this.inSMaskMode) { + throw new Error("endSMaskMode called while not in smask mode"); + } + this.ctx._removeMirroring(); + copyCtxState(this.ctx, this.suspendedCtx); + this.ctx = this.suspendedCtx; + this.suspendedCtx = null; + } + compose(dirtyBox) { + if (!this.current.activeSMask) { + return; + } + if (!dirtyBox) { + dirtyBox = [0, 0, this.ctx.canvas.width, this.ctx.canvas.height]; + } else { + dirtyBox[0] = Math.floor(dirtyBox[0]); + dirtyBox[1] = Math.floor(dirtyBox[1]); + dirtyBox[2] = Math.ceil(dirtyBox[2]); + dirtyBox[3] = Math.ceil(dirtyBox[3]); + } + const smask = this.current.activeSMask; + const suspendedCtx = this.suspendedCtx; + this.composeSMask(suspendedCtx, smask, this.ctx, dirtyBox); + this.ctx.save(); + this.ctx.setTransform(1, 0, 0, 1, 0, 0); + this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height); + this.ctx.restore(); + } + composeSMask(ctx, smask, layerCtx, layerBox) { + const layerOffsetX = layerBox[0]; + const layerOffsetY = layerBox[1]; + const layerWidth = layerBox[2] - layerOffsetX; + const layerHeight = layerBox[3] - layerOffsetY; + if (layerWidth === 0 || layerHeight === 0) { + return; + } + this.genericComposeSMask(smask.context, layerCtx, layerWidth, layerHeight, smask.subtype, smask.backdrop, smask.transferMap, layerOffsetX, layerOffsetY, smask.offsetX, smask.offsetY); + ctx.save(); + ctx.globalAlpha = 1; + ctx.globalCompositeOperation = "source-over"; + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.drawImage(layerCtx.canvas, 0, 0); + ctx.restore(); + } + genericComposeSMask(maskCtx, layerCtx, width, height, subtype, backdrop, transferMap, layerOffsetX, layerOffsetY, maskOffsetX, maskOffsetY) { + let maskCanvas = maskCtx.canvas; + let maskX = layerOffsetX - maskOffsetX; + let maskY = layerOffsetY - maskOffsetY; + if (backdrop) { + if (maskX < 0 || maskY < 0 || maskX + width > maskCanvas.width || maskY + height > maskCanvas.height) { + const canvas = this.cachedCanvases.getCanvas("maskExtension", width, height); + const ctx = canvas.context; + ctx.drawImage(maskCanvas, -maskX, -maskY); + ctx.globalCompositeOperation = "destination-atop"; + ctx.fillStyle = backdrop; + ctx.fillRect(0, 0, width, height); + ctx.globalCompositeOperation = "source-over"; + maskCanvas = canvas.canvas; + maskX = maskY = 0; + } else { + maskCtx.save(); + maskCtx.globalAlpha = 1; + maskCtx.setTransform(1, 0, 0, 1, 0, 0); + const clip2 = new Path2D(); + clip2.rect(maskX, maskY, width, height); + maskCtx.clip(clip2); + maskCtx.globalCompositeOperation = "destination-atop"; + maskCtx.fillStyle = backdrop; + maskCtx.fillRect(maskX, maskY, width, height); + maskCtx.restore(); + } + } + layerCtx.save(); + layerCtx.globalAlpha = 1; + layerCtx.setTransform(1, 0, 0, 1, 0, 0); + if (subtype === "Alpha" && transferMap) { + layerCtx.filter = this.filterFactory.addAlphaFilter(transferMap); + } else if (subtype === "Luminosity") { + layerCtx.filter = this.filterFactory.addLuminosityFilter(transferMap); + } + const clip = new Path2D(); + clip.rect(layerOffsetX, layerOffsetY, width, height); + layerCtx.clip(clip); + layerCtx.globalCompositeOperation = "destination-in"; + layerCtx.drawImage(maskCanvas, maskX, maskY, width, height, layerOffsetX, layerOffsetY, width, height); + layerCtx.restore(); + } + save(opIdx) { + if (this.inSMaskMode) { + copyCtxState(this.ctx, this.suspendedCtx); + } + this.ctx.save(); + const old = this.current; + this.stateStack.push(old); + this.current = old.clone(); + this.dependencyTracker?.save(opIdx); + } + restore(opIdx) { + this.dependencyTracker?.restore(opIdx); + if (this.stateStack.length === 0) { + if (this.inSMaskMode) { + this.endSMaskMode(); + } + return; + } + this.current = this.stateStack.pop(); + this.ctx.restore(); + if (this.inSMaskMode) { + copyCtxState(this.suspendedCtx, this.ctx); + } + this.checkSMaskState(); + this.pendingClip = null; + this._cachedScaleForStroking[0] = -1; + this._cachedGetSinglePixelWidth = null; + } + transform(opIdx, a, b, c, d, e, f) { + this.dependencyTracker?.recordIncrementalData("transform", opIdx); + this.ctx.transform(a, b, c, d, e, f); + this._cachedScaleForStroking[0] = -1; + this._cachedGetSinglePixelWidth = null; + } + constructPath(opIdx, op, data, minMax) { + let [path] = data; + if (!minMax) { + path ||= data[0] = new Path2D(); + this[op](opIdx, path); + return; + } + if (this.dependencyTracker !== null) { + const outerExtraSize = op === OPS.stroke ? this.current.lineWidth / 2 : 0; + this.dependencyTracker.resetBBox(opIdx).recordBBox(opIdx, this.ctx, minMax[0] - outerExtraSize, minMax[2] + outerExtraSize, minMax[1] - outerExtraSize, minMax[3] + outerExtraSize).recordDependencies(opIdx, ["transform"]); + } + if (!(path instanceof Path2D)) { + const path2d = data[0] = new Path2D(); + for (let i = 0, ii = path.length; i < ii; ) { + switch (path[i++]) { + case DrawOPS.moveTo: + path2d.moveTo(path[i++], path[i++]); + break; + case DrawOPS.lineTo: + path2d.lineTo(path[i++], path[i++]); + break; + case DrawOPS.curveTo: + path2d.bezierCurveTo(path[i++], path[i++], path[i++], path[i++], path[i++], path[i++]); + break; + case DrawOPS.closePath: + path2d.closePath(); + break; + default: + warn(`Unrecognized drawing path operator: ${path[i - 1]}`); + break; + } + } + path = path2d; + } + Util.axialAlignedBoundingBox(minMax, getCurrentTransform(this.ctx), this.current.minMax); + this[op](opIdx, path); + this._pathStartIdx = opIdx; + } + closePath(opIdx) { + this.ctx.closePath(); + } + stroke(opIdx, path, consumePath = true) { + const ctx = this.ctx; + const strokeColor = this.current.strokeColor; + ctx.globalAlpha = this.current.strokeAlpha; + if (this.contentVisible) { + if (typeof strokeColor === "object" && strokeColor?.getPattern) { + const baseTransform = strokeColor.isModifyingCurrentTransform() ? ctx.getTransform() : null; + ctx.save(); + ctx.strokeStyle = strokeColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.STROKE, opIdx); + if (baseTransform) { + const newPath = new Path2D(); + newPath.addPath(path, ctx.getTransform().invertSelf().multiplySelf(baseTransform)); + path = newPath; + } + this.rescaleAndStroke(path, false); + ctx.restore(); + } else { + this.rescaleAndStroke(path, true); + } + } + this.dependencyTracker?.recordDependencies(opIdx, Dependencies.stroke); + if (consumePath) { + this.consumePath(opIdx, path, this.current.getClippedPathBoundingBox(PathType.STROKE, getCurrentTransform(this.ctx))); + } + ctx.globalAlpha = this.current.fillAlpha; + } + closeStroke(opIdx, path) { + this.stroke(opIdx, path); + } + fill(opIdx, path, consumePath = true) { + const ctx = this.ctx; + const fillColor = this.current.fillColor; + const isPatternFill = this.current.patternFill; + let needRestore = false; + if (isPatternFill) { + const baseTransform = fillColor.isModifyingCurrentTransform() ? ctx.getTransform() : null; + this.dependencyTracker?.save(opIdx); + ctx.save(); + ctx.fillStyle = fillColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.FILL, opIdx); + if (baseTransform) { + const newPath = new Path2D(); + newPath.addPath(path, ctx.getTransform().invertSelf().multiplySelf(baseTransform)); + path = newPath; + } + needRestore = true; + } + const intersect = this.current.getClippedPathBoundingBox(); + if (this.contentVisible && intersect !== null) { + if (this.pendingEOFill) { + ctx.fill(path, "evenodd"); + this.pendingEOFill = false; + } else { + ctx.fill(path); + } + } + this.dependencyTracker?.recordDependencies(opIdx, Dependencies.fill); + if (needRestore) { + ctx.restore(); + this.dependencyTracker?.restore(opIdx); + } + if (consumePath) { + this.consumePath(opIdx, path, intersect); + } + } + eoFill(opIdx, path) { + this.pendingEOFill = true; + this.fill(opIdx, path); + } + fillStroke(opIdx, path) { + this.fill(opIdx, path, false); + this.stroke(opIdx, path, false); + this.consumePath(opIdx, path); + } + eoFillStroke(opIdx, path) { + this.pendingEOFill = true; + this.fillStroke(opIdx, path); + } + closeFillStroke(opIdx, path) { + this.fillStroke(opIdx, path); + } + closeEOFillStroke(opIdx, path) { + this.pendingEOFill = true; + this.fillStroke(opIdx, path); + } + endPath(opIdx, path) { + this.consumePath(opIdx, path); + } + rawFillPath(opIdx, path) { + this.ctx.fill(path); + this.dependencyTracker?.recordDependencies(opIdx, Dependencies.rawFillPath).recordOperation(opIdx); + } + clip(opIdx) { + this.dependencyTracker?.recordFutureForcedDependency("clipMode", opIdx); + this.pendingClip = NORMAL_CLIP; + } + eoClip(opIdx) { + this.dependencyTracker?.recordFutureForcedDependency("clipMode", opIdx); + this.pendingClip = EO_CLIP; + } + beginText(opIdx) { + this.current.textMatrix = null; + this.current.textMatrixScale = 1; + this.current.x = this.current.lineX = 0; + this.current.y = this.current.lineY = 0; + this.dependencyTracker?.recordOpenMarker(opIdx).resetIncrementalData("sameLineText").resetIncrementalData("moveText", opIdx); + } + endText(opIdx) { + const paths = this.pendingTextPaths; + const ctx = this.ctx; + if (this.dependencyTracker) { + const { + dependencyTracker + } = this; + if (paths !== void 0) { + dependencyTracker.recordFutureForcedDependency("textClip", dependencyTracker.getOpenMarker()).recordFutureForcedDependency("textClip", opIdx); + } + dependencyTracker.recordCloseMarker(opIdx); + } + if (paths !== void 0) { + const newPath = new Path2D(); + const invTransf = ctx.getTransform().invertSelf(); + for (const { + transform, + x, + y, + fontSize, + path + } of paths) { + if (!path) { + continue; + } + newPath.addPath(path, new DOMMatrix(transform).preMultiplySelf(invTransf).translate(x, y).scale(fontSize, -fontSize)); + } + ctx.clip(newPath); + } + delete this.pendingTextPaths; + } + setCharSpacing(opIdx, spacing) { + this.dependencyTracker?.recordSimpleData("charSpacing", opIdx); + this.current.charSpacing = spacing; + } + setWordSpacing(opIdx, spacing) { + this.dependencyTracker?.recordSimpleData("wordSpacing", opIdx); + this.current.wordSpacing = spacing; + } + setHScale(opIdx, scale) { + this.dependencyTracker?.recordSimpleData("hScale", opIdx); + this.current.textHScale = scale / 100; + } + setLeading(opIdx, leading) { + this.dependencyTracker?.recordSimpleData("leading", opIdx); + this.current.leading = -leading; + } + setFont(opIdx, fontRefName, size) { + this.dependencyTracker?.recordSimpleData("font", opIdx).recordSimpleDataFromNamed("fontObj", fontRefName, opIdx); + const fontObj = this.commonObjs.get(fontRefName); + const current = this.current; + if (!fontObj) { + throw new Error(`Can't find font for ${fontRefName}`); + } + current.fontMatrix = fontObj.fontMatrix || FONT_IDENTITY_MATRIX; + if (current.fontMatrix[0] === 0 || current.fontMatrix[3] === 0) { + warn("Invalid font matrix for font " + fontRefName); + } + if (size < 0) { + size = -size; + current.fontDirection = -1; + } else { + current.fontDirection = 1; + } + this.current.font = fontObj; + this.current.fontSize = size; + if (fontObj.isType3Font) { + return; + } + const name = fontObj.loadedName || "sans-serif"; + const typeface = fontObj.systemFontInfo?.css || `"${name}", ${fontObj.fallbackName}`; + let bold = "normal"; + if (fontObj.black) { + bold = "900"; + } else if (fontObj.bold) { + bold = "bold"; + } + const italic = fontObj.italic ? "italic" : "normal"; + let browserFontSize = size; + if (size < MIN_FONT_SIZE) { + browserFontSize = MIN_FONT_SIZE; + } else if (size > MAX_FONT_SIZE) { + browserFontSize = MAX_FONT_SIZE; + } + this.current.fontSizeScale = size / browserFontSize; + this.ctx.font = `${italic} ${bold} ${browserFontSize}px ${typeface}`; + } + setTextRenderingMode(opIdx, mode) { + this.dependencyTracker?.recordSimpleData("textRenderingMode", opIdx); + this.current.textRenderingMode = mode; + } + setTextRise(opIdx, rise) { + this.dependencyTracker?.recordSimpleData("textRise", opIdx); + this.current.textRise = rise; + } + moveText(opIdx, x, y) { + this.dependencyTracker?.resetIncrementalData("sameLineText").recordIncrementalData("moveText", opIdx); + this.current.x = this.current.lineX += x; + this.current.y = this.current.lineY += y; + } + setLeadingMoveText(opIdx, x, y) { + this.setLeading(opIdx, -y); + this.moveText(opIdx, x, y); + } + setTextMatrix(opIdx, matrix) { + this.dependencyTracker?.recordSimpleData("textMatrix", opIdx); + const { + current + } = this; + current.textMatrix = matrix; + current.textMatrixScale = Math.hypot(matrix[0], matrix[1]); + current.x = current.lineX = 0; + current.y = current.lineY = 0; + } + nextLine(opIdx) { + this.moveText(opIdx, 0, this.current.leading); + this.dependencyTracker?.recordIncrementalData("moveText", this.dependencyTracker.getSimpleIndex("leading") ?? opIdx); + } + #getScaledPath(path, currentTransform, transform) { + const newPath = new Path2D(); + newPath.addPath(path, new DOMMatrix(transform).invertSelf().multiplySelf(currentTransform)); + return newPath; + } + paintChar(opIdx, character, x, y, patternFillTransform, patternStrokeTransform) { + const ctx = this.ctx; + const current = this.current; + const font = current.font; + const textRenderingMode = current.textRenderingMode; + const fontSize = current.fontSize / current.fontSizeScale; + const fillStrokeMode = textRenderingMode & TextRenderingMode.FILL_STROKE_MASK; + const isAddToPathSet = !!(textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG); + const patternFill = current.patternFill && !font.missingFile; + const patternStroke = current.patternStroke && !font.missingFile; + let path; + if ((font.disableFontFace || isAddToPathSet || patternFill || patternStroke) && !font.missingFile) { + path = font.getPathGenerator(this.commonObjs, character); + } + if (path && (font.disableFontFace || patternFill || patternStroke)) { + ctx.save(); + ctx.translate(x, y); + ctx.scale(fontSize, -fontSize); + this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, font); + let currentTransform; + if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) { + if (patternFillTransform) { + currentTransform = ctx.getTransform(); + ctx.setTransform(...patternFillTransform); + const scaledPath = this.#getScaledPath(path, currentTransform, patternFillTransform); + ctx.fill(scaledPath); + } else { + ctx.fill(path); + } + } + if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) { + if (patternStrokeTransform) { + currentTransform ||= ctx.getTransform(); + ctx.setTransform(...patternStrokeTransform); + const { + a, + b, + c, + d + } = currentTransform; + const invPatternTransform = Util.inverseTransform(patternStrokeTransform); + const transf = Util.transform([a, b, c, d, 0, 0], invPatternTransform); + Util.singularValueDecompose2dScale(transf, XY); + ctx.lineWidth *= Math.max(XY[0], XY[1]) / fontSize; + ctx.stroke(this.#getScaledPath(path, currentTransform, patternStrokeTransform)); + } else { + ctx.lineWidth /= fontSize; + ctx.stroke(path); + } + } + ctx.restore(); + } else { + if (fillStrokeMode === TextRenderingMode.FILL || fillStrokeMode === TextRenderingMode.FILL_STROKE) { + ctx.fillText(character, x, y); + this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, font, fontSize, x, y, () => ctx.measureText(character)); + } + if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) { + if (this.dependencyTracker) { + this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, font, fontSize, x, y, () => ctx.measureText(character)).recordDependencies(opIdx, Dependencies.stroke); + } + ctx.strokeText(character, x, y); + } + } + if (isAddToPathSet) { + const paths = this.pendingTextPaths ||= []; + paths.push({ + transform: getCurrentTransform(ctx), + x, + y, + fontSize, + path + }); + this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, font, fontSize, x, y); + } + } + get isFontSubpixelAAEnabled() { + const { + context: ctx + } = this.cachedCanvases.getCanvas("isFontSubpixelAAEnabled", 10, 10); + ctx.scale(1.5, 1); + ctx.fillText("I", 0, 10); + const data = ctx.getImageData(0, 0, 10, 10).data; + let enabled = false; + for (let i = 3; i < data.length; i += 4) { + if (data[i] > 0 && data[i] < 255) { + enabled = true; + break; + } + } + return shadow(this, "isFontSubpixelAAEnabled", enabled); + } + showText(opIdx, glyphs) { + if (this.dependencyTracker) { + this.dependencyTracker.recordDependencies(opIdx, Dependencies.showText).resetBBox(opIdx); + if (this.current.textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG) { + this.dependencyTracker.recordFutureForcedDependency("textClip", opIdx).inheritPendingDependenciesAsFutureForcedDependencies(); + } + } + const current = this.current; + const font = current.font; + if (font.isType3Font) { + this.showType3Text(opIdx, glyphs); + this.dependencyTracker?.recordShowTextOperation(opIdx); + return void 0; + } + const fontSize = current.fontSize; + if (fontSize === 0) { + this.dependencyTracker?.recordOperation(opIdx); + return void 0; + } + const ctx = this.ctx; + const fontSizeScale = current.fontSizeScale; + const charSpacing = current.charSpacing; + const wordSpacing = current.wordSpacing; + const fontDirection = current.fontDirection; + const textHScale = current.textHScale * fontDirection; + const glyphsLength = glyphs.length; + const vertical = font.vertical; + const spacingDir = vertical ? 1 : -1; + const defaultVMetrics = font.defaultVMetrics; + const widthAdvanceScale = fontSize * current.fontMatrix[0]; + const simpleFillText = current.textRenderingMode === TextRenderingMode.FILL && !font.disableFontFace && !current.patternFill; + ctx.save(); + if (current.textMatrix) { + ctx.transform(...current.textMatrix); + } + ctx.translate(current.x, current.y + current.textRise); + if (fontDirection > 0) { + ctx.scale(textHScale, -1); + } else { + ctx.scale(textHScale, 1); + } + let patternFillTransform, patternStrokeTransform; + if (current.patternFill) { + ctx.save(); + const pattern = current.fillColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.FILL, opIdx); + patternFillTransform = getCurrentTransform(ctx); + ctx.restore(); + ctx.fillStyle = pattern; + } + if (current.patternStroke) { + ctx.save(); + const pattern = current.strokeColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.STROKE, opIdx); + patternStrokeTransform = getCurrentTransform(ctx); + ctx.restore(); + ctx.strokeStyle = pattern; + } + let lineWidth = current.lineWidth; + const scale = current.textMatrixScale; + if (scale === 0 || lineWidth === 0) { + const fillStrokeMode = current.textRenderingMode & TextRenderingMode.FILL_STROKE_MASK; + if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) { + lineWidth = this.getSinglePixelWidth(); + } + } else { + lineWidth /= scale; + } + if (fontSizeScale !== 1) { + ctx.scale(fontSizeScale, fontSizeScale); + lineWidth /= fontSizeScale; + } + ctx.lineWidth = lineWidth; + if (font.isInvalidPDFjsFont) { + const chars = []; + let width = 0; + for (const glyph of glyphs) { + chars.push(glyph.unicode); + width += glyph.width; + } + const joinedChars = chars.join(""); + ctx.fillText(joinedChars, 0, 0); + if (this.dependencyTracker !== null) { + const measure = ctx.measureText(joinedChars); + this.dependencyTracker.recordBBox(opIdx, this.ctx, -measure.actualBoundingBoxLeft, measure.actualBoundingBoxRight, -measure.actualBoundingBoxAscent, measure.actualBoundingBoxDescent).recordShowTextOperation(opIdx); + } + current.x += width * widthAdvanceScale * textHScale; + ctx.restore(); + this.compose(); + return void 0; + } + let x = 0, i; + for (i = 0; i < glyphsLength; ++i) { + const glyph = glyphs[i]; + if (typeof glyph === "number") { + x += spacingDir * glyph * fontSize / 1e3; + continue; + } + let restoreNeeded = false; + const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing; + const character = glyph.fontChar; + const accent = glyph.accent; + let scaledX, scaledY; + let width = glyph.width; + if (vertical) { + const vmetric = glyph.vmetric || defaultVMetrics; + const vx = -(glyph.vmetric ? vmetric[1] : width * 0.5) * widthAdvanceScale; + const vy = vmetric[2] * widthAdvanceScale; + width = vmetric ? -vmetric[0] : width; + scaledX = vx / fontSizeScale; + scaledY = (x + vy) / fontSizeScale; + } else { + scaledX = x / fontSizeScale; + scaledY = 0; + } + let measure; + if (font.remeasure && width > 0) { + measure = ctx.measureText(character); + const measuredWidth = measure.width * 1e3 / fontSize * fontSizeScale; + if (width < measuredWidth && this.isFontSubpixelAAEnabled) { + const characterScaleX = width / measuredWidth; + restoreNeeded = true; + ctx.save(); + ctx.scale(characterScaleX, 1); + scaledX /= characterScaleX; + } else if (width !== measuredWidth) { + scaledX += (width - measuredWidth) / 2e3 * fontSize / fontSizeScale; + } + } + if (this.contentVisible && (glyph.isInFont || font.missingFile)) { + if (simpleFillText && !accent) { + ctx.fillText(character, scaledX, scaledY); + this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, measure ? { + bbox: null + } : font, fontSize / fontSizeScale, scaledX, scaledY, () => measure ?? ctx.measureText(character)); + } else { + this.paintChar(opIdx, character, scaledX, scaledY, patternFillTransform, patternStrokeTransform); + if (accent) { + const scaledAccentX = scaledX + fontSize * accent.offset.x / fontSizeScale; + const scaledAccentY = scaledY - fontSize * accent.offset.y / fontSizeScale; + this.paintChar(opIdx, accent.fontChar, scaledAccentX, scaledAccentY, patternFillTransform, patternStrokeTransform); + } + } + } + const charWidth = vertical ? width * widthAdvanceScale - spacing * fontDirection : width * widthAdvanceScale + spacing * fontDirection; + x += charWidth; + if (restoreNeeded) { + ctx.restore(); + } + } + if (vertical) { + current.y -= x; + } else { + current.x += x * textHScale; + } + ctx.restore(); + this.compose(); + this.dependencyTracker?.recordShowTextOperation(opIdx); + return void 0; + } + showType3Text(opIdx, glyphs) { + const ctx = this.ctx; + const current = this.current; + const font = current.font; + const fontSize = current.fontSize; + const fontDirection = current.fontDirection; + const spacingDir = font.vertical ? 1 : -1; + const charSpacing = current.charSpacing; + const wordSpacing = current.wordSpacing; + const textHScale = current.textHScale * fontDirection; + const fontMatrix = current.fontMatrix || FONT_IDENTITY_MATRIX; + const glyphsLength = glyphs.length; + const isTextInvisible = current.textRenderingMode === TextRenderingMode.INVISIBLE; + let i, glyph, width, spacingLength; + if (isTextInvisible || fontSize === 0) { + return; + } + this._cachedScaleForStroking[0] = -1; + this._cachedGetSinglePixelWidth = null; + ctx.save(); + if (current.textMatrix) { + ctx.transform(...current.textMatrix); + } + ctx.translate(current.x, current.y + current.textRise); + ctx.scale(textHScale, fontDirection); + const dependencyTracker = this.dependencyTracker; + this.dependencyTracker = dependencyTracker ? new CanvasNestedDependencyTracker(dependencyTracker, opIdx) : null; + for (i = 0; i < glyphsLength; ++i) { + glyph = glyphs[i]; + if (typeof glyph === "number") { + spacingLength = spacingDir * glyph * fontSize / 1e3; + this.ctx.translate(spacingLength, 0); + current.x += spacingLength * textHScale; + continue; + } + const spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing; + const operatorList = font.charProcOperatorList[glyph.operatorListId]; + if (!operatorList) { + warn(`Type3 character "${glyph.operatorListId}" is not available.`); + } else if (this.contentVisible) { + this.save(); + ctx.scale(fontSize, fontSize); + ctx.transform(...fontMatrix); + this.executeOperatorList(operatorList); + this.restore(); + } + const p = [glyph.width, 0]; + Util.applyTransform(p, fontMatrix); + width = p[0] * fontSize + spacing; + ctx.translate(width, 0); + current.x += width * textHScale; + } + ctx.restore(); + if (dependencyTracker) { + this.dependencyTracker = dependencyTracker; + } + } + setCharWidth(opIdx, xWidth, yWidth) { + } + setCharWidthAndBounds(opIdx, xWidth, yWidth, llx, lly, urx, ury) { + const clip = new Path2D(); + clip.rect(llx, lly, urx - llx, ury - lly); + this.ctx.clip(clip); + this.dependencyTracker?.recordBBox(opIdx, this.ctx, llx, urx, lly, ury).recordClipBox(opIdx, this.ctx, llx, urx, lly, ury); + this.endPath(opIdx); + } + getColorN_Pattern(opIdx, IR) { + let pattern; + if (IR[0] === "TilingPattern") { + const baseTransform = this.baseTransform || getCurrentTransform(this.ctx); + const canvasGraphicsFactory = { + createCanvasGraphics: (ctx, renderingOpIdx) => new CanvasGraphics(ctx, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, { + optionalContentConfig: this.optionalContentConfig, + markedContentStack: this.markedContentStack + }, void 0, void 0, this.dependencyTracker ? new CanvasNestedDependencyTracker(this.dependencyTracker, renderingOpIdx, true) : null) + }; + pattern = new TilingPattern(IR, this.ctx, canvasGraphicsFactory, baseTransform); + } else { + pattern = this._getPattern(opIdx, IR[1], IR[2]); + } + return pattern; + } + setStrokeColorN(opIdx, ...args) { + this.dependencyTracker?.recordSimpleData("strokeColor", opIdx); + this.current.strokeColor = this.getColorN_Pattern(opIdx, args); + this.current.patternStroke = true; + } + setFillColorN(opIdx, ...args) { + this.dependencyTracker?.recordSimpleData("fillColor", opIdx); + this.current.fillColor = this.getColorN_Pattern(opIdx, args); + this.current.patternFill = true; + } + setStrokeRGBColor(opIdx, color) { + this.dependencyTracker?.recordSimpleData("strokeColor", opIdx); + this.ctx.strokeStyle = this.current.strokeColor = color; + this.current.patternStroke = false; + } + setStrokeTransparent(opIdx) { + this.dependencyTracker?.recordSimpleData("strokeColor", opIdx); + this.ctx.strokeStyle = this.current.strokeColor = "transparent"; + this.current.patternStroke = false; + } + setFillRGBColor(opIdx, color) { + this.dependencyTracker?.recordSimpleData("fillColor", opIdx); + this.ctx.fillStyle = this.current.fillColor = color; + this.current.patternFill = false; + } + setFillTransparent(opIdx) { + this.dependencyTracker?.recordSimpleData("fillColor", opIdx); + this.ctx.fillStyle = this.current.fillColor = "transparent"; + this.current.patternFill = false; + } + _getPattern(opIdx, objId, matrix = null) { + let pattern; + if (this.cachedPatterns.has(objId)) { + pattern = this.cachedPatterns.get(objId); + } else { + pattern = getShadingPattern(this.getObject(opIdx, objId)); + this.cachedPatterns.set(objId, pattern); + } + if (matrix) { + pattern.matrix = matrix; + } + return pattern; + } + shadingFill(opIdx, objId) { + if (!this.contentVisible) { + return; + } + const ctx = this.ctx; + this.save(opIdx); + const pattern = this._getPattern(opIdx, objId); + ctx.fillStyle = pattern.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.SHADING, opIdx); + const inv = getCurrentTransformInverse(ctx); + if (inv) { + const { + width, + height + } = ctx.canvas; + const minMax = MIN_MAX_INIT.slice(); + Util.axialAlignedBoundingBox([0, 0, width, height], inv, minMax); + const [x0, y0, x1, y1] = minMax; + this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0); + } else { + this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10); + } + this.dependencyTracker?.resetBBox(opIdx).recordFullPageBBox(opIdx).recordDependencies(opIdx, Dependencies.transform).recordDependencies(opIdx, Dependencies.fill).recordOperation(opIdx); + this.compose(this.current.getClippedPathBoundingBox()); + this.restore(opIdx); + } + beginInlineImage() { + unreachable("Should not call beginInlineImage"); + } + beginImageData() { + unreachable("Should not call beginImageData"); + } + paintFormXObjectBegin(opIdx, matrix, bbox) { + if (!this.contentVisible) { + return; + } + this.save(opIdx); + this.baseTransformStack.push(this.baseTransform); + if (matrix) { + this.transform(opIdx, ...matrix); + } + this.baseTransform = getCurrentTransform(this.ctx); + if (bbox) { + Util.axialAlignedBoundingBox(bbox, this.baseTransform, this.current.minMax); + const [x0, y0, x1, y1] = bbox; + const clip = new Path2D(); + clip.rect(x0, y0, x1 - x0, y1 - y0); + this.ctx.clip(clip); + this.dependencyTracker?.recordClipBox(opIdx, this.ctx, x0, x1, y0, y1); + this.endPath(opIdx); + } + } + paintFormXObjectEnd(opIdx) { + if (!this.contentVisible) { + return; + } + this.restore(opIdx); + this.baseTransform = this.baseTransformStack.pop(); + } + beginGroup(opIdx, group) { + if (!this.contentVisible) { + return; + } + this.save(opIdx); + if (this.inSMaskMode) { + this.endSMaskMode(); + this.current.activeSMask = null; + } + const currentCtx = this.ctx; + if (!group.isolated) { + info("TODO: Support non-isolated groups."); + } + if (group.knockout) { + warn("Knockout groups not supported."); + } + const currentTransform = getCurrentTransform(currentCtx); + if (group.matrix) { + currentCtx.transform(...group.matrix); + } + if (!group.bbox) { + throw new Error("Bounding box is required."); + } + let bounds = MIN_MAX_INIT.slice(); + Util.axialAlignedBoundingBox(group.bbox, getCurrentTransform(currentCtx), bounds); + const canvasBounds = [0, 0, currentCtx.canvas.width, currentCtx.canvas.height]; + bounds = Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0]; + const offsetX = Math.floor(bounds[0]); + const offsetY = Math.floor(bounds[1]); + const drawnWidth = Math.max(Math.ceil(bounds[2]) - offsetX, 1); + const drawnHeight = Math.max(Math.ceil(bounds[3]) - offsetY, 1); + this.current.startNewPathAndClipBox([0, 0, drawnWidth, drawnHeight]); + let cacheId = "groupAt" + this.groupLevel; + if (group.smask) { + cacheId += "_smask_" + this.smaskCounter++ % 2; + } + const scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight); + const groupCtx = scratchCanvas.context; + groupCtx.translate(-offsetX, -offsetY); + groupCtx.transform(...currentTransform); + let clip = new Path2D(); + const [x0, y0, x1, y1] = group.bbox; + clip.rect(x0, y0, x1 - x0, y1 - y0); + if (group.matrix) { + const path = new Path2D(); + path.addPath(clip, new DOMMatrix(group.matrix)); + clip = path; + } + groupCtx.clip(clip); + if (group.smask) { + this.smaskStack.push({ + canvas: scratchCanvas.canvas, + context: groupCtx, + offsetX, + offsetY, + subtype: group.smask.subtype, + backdrop: group.smask.backdrop, + transferMap: group.smask.transferMap || null, + startTransformInverse: null + }); + } + if (!group.smask || this.dependencyTracker) { + currentCtx.setTransform(1, 0, 0, 1, 0, 0); + currentCtx.translate(offsetX, offsetY); + currentCtx.save(); + } + copyCtxState(currentCtx, groupCtx); + this.ctx = groupCtx; + this.dependencyTracker?.inheritSimpleDataAsFutureForcedDependencies(["fillAlpha", "strokeAlpha", "globalCompositeOperation"]).pushBaseTransform(currentCtx); + this.setGState(opIdx, [["BM", "source-over"], ["ca", 1], ["CA", 1]]); + this.groupStack.push(currentCtx); + this.groupLevel++; + } + endGroup(opIdx, group) { + if (!this.contentVisible) { + return; + } + this.groupLevel--; + const groupCtx = this.ctx; + const ctx = this.groupStack.pop(); + this.ctx = ctx; + this.ctx.imageSmoothingEnabled = false; + this.dependencyTracker?.popBaseTransform(); + if (group.smask) { + this.tempSMask = this.smaskStack.pop(); + this.restore(opIdx); + if (this.dependencyTracker) { + this.ctx.restore(); + } + } else { + this.ctx.restore(); + const currentMtx = getCurrentTransform(this.ctx); + this.restore(opIdx); + this.ctx.save(); + this.ctx.setTransform(...currentMtx); + const dirtyBox = MIN_MAX_INIT.slice(); + Util.axialAlignedBoundingBox([0, 0, groupCtx.canvas.width, groupCtx.canvas.height], currentMtx, dirtyBox); + this.ctx.drawImage(groupCtx.canvas, 0, 0); + this.ctx.restore(); + this.compose(dirtyBox); + } + } + beginAnnotation(opIdx, id, rect, transform, matrix, hasOwnCanvas) { + this.#restoreInitialState(); + resetCtxToDefault(this.ctx); + this.ctx.save(); + this.save(opIdx); + if (this.baseTransform) { + this.ctx.setTransform(...this.baseTransform); + } + if (rect) { + const width = rect[2] - rect[0]; + const height = rect[3] - rect[1]; + if (hasOwnCanvas && this.annotationCanvasMap) { + transform = transform.slice(); + transform[4] -= rect[0]; + transform[5] -= rect[1]; + rect = rect.slice(); + rect[0] = rect[1] = 0; + rect[2] = width; + rect[3] = height; + Util.singularValueDecompose2dScale(getCurrentTransform(this.ctx), XY); + const { + viewportScale + } = this; + const canvasWidth = Math.ceil(width * this.outputScaleX * viewportScale); + const canvasHeight = Math.ceil(height * this.outputScaleY * viewportScale); + this.annotationCanvas = this.canvasFactory.create(canvasWidth, canvasHeight); + const { + canvas, + context + } = this.annotationCanvas; + this.annotationCanvasMap.set(id, canvas); + this.annotationCanvas.savedCtx = this.ctx; + this.ctx = context; + this.ctx.save(); + this.ctx.setTransform(XY[0], 0, 0, -XY[1], 0, height * XY[1]); + resetCtxToDefault(this.ctx); + } else { + resetCtxToDefault(this.ctx); + this.endPath(opIdx); + const clip = new Path2D(); + clip.rect(rect[0], rect[1], width, height); + this.ctx.clip(clip); + } + } + this.current = new CanvasExtraState(this.ctx.canvas.width, this.ctx.canvas.height); + this.transform(opIdx, ...transform); + this.transform(opIdx, ...matrix); + } + endAnnotation(opIdx) { + if (this.annotationCanvas) { + this.ctx.restore(); + this.#drawFilter(); + this.ctx = this.annotationCanvas.savedCtx; + delete this.annotationCanvas.savedCtx; + delete this.annotationCanvas; + } + } + paintImageMaskXObject(opIdx, img) { + if (!this.contentVisible) { + return; + } + const count = img.count; + img = this.getObject(opIdx, img.data, img); + img.count = count; + const ctx = this.ctx; + const mask = this._createMaskCanvas(opIdx, img); + const maskCanvas = mask.canvas; + ctx.save(); + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.drawImage(maskCanvas, mask.offsetX, mask.offsetY); + this.dependencyTracker?.resetBBox(opIdx).recordBBox(opIdx, this.ctx, mask.offsetX, mask.offsetX + maskCanvas.width, mask.offsetY, mask.offsetY + maskCanvas.height).recordOperation(opIdx); + ctx.restore(); + this.compose(); + } + paintImageMaskXObjectRepeat(opIdx, img, scaleX, skewX = 0, skewY = 0, scaleY, positions) { + if (!this.contentVisible) { + return; + } + img = this.getObject(opIdx, img.data, img); + const ctx = this.ctx; + ctx.save(); + const currentTransform = getCurrentTransform(ctx); + ctx.transform(scaleX, skewX, skewY, scaleY, 0, 0); + const mask = this._createMaskCanvas(opIdx, img); + ctx.setTransform(1, 0, 0, 1, mask.offsetX - currentTransform[4], mask.offsetY - currentTransform[5]); + this.dependencyTracker?.resetBBox(opIdx); + for (let i = 0, ii = positions.length; i < ii; i += 2) { + const trans = Util.transform(currentTransform, [scaleX, skewX, skewY, scaleY, positions[i], positions[i + 1]]); + ctx.drawImage(mask.canvas, trans[4], trans[5]); + this.dependencyTracker?.recordBBox(opIdx, this.ctx, trans[4], trans[4] + mask.canvas.width, trans[5], trans[5] + mask.canvas.height); + } + ctx.restore(); + this.compose(); + this.dependencyTracker?.recordOperation(opIdx); + } + paintImageMaskXObjectGroup(opIdx, images) { + if (!this.contentVisible) { + return; + } + const ctx = this.ctx; + const fillColor = this.current.fillColor; + const isPatternFill = this.current.patternFill; + this.dependencyTracker?.resetBBox(opIdx).recordDependencies(opIdx, Dependencies.transformAndFill); + for (const image of images) { + const { + data, + width, + height, + transform + } = image; + const maskCanvas = this.cachedCanvases.getCanvas("maskCanvas", width, height); + const maskCtx = maskCanvas.context; + maskCtx.save(); + const img = this.getObject(opIdx, data, image); + putBinaryImageMask(maskCtx, img); + maskCtx.globalCompositeOperation = "source-in"; + maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this, getCurrentTransformInverse(ctx), PathType.FILL, opIdx) : fillColor; + maskCtx.fillRect(0, 0, width, height); + maskCtx.restore(); + ctx.save(); + ctx.transform(...transform); + ctx.scale(1, -1); + drawImageAtIntegerCoords(ctx, maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1); + this.dependencyTracker?.recordBBox(opIdx, ctx, 0, width, 0, height); + ctx.restore(); + } + this.compose(); + this.dependencyTracker?.recordOperation(opIdx); + } + paintImageXObject(opIdx, objId) { + if (!this.contentVisible) { + return; + } + const imgData = this.getObject(opIdx, objId); + if (!imgData) { + warn("Dependent image isn't ready yet"); + return; + } + this.paintInlineImageXObject(opIdx, imgData); + } + paintImageXObjectRepeat(opIdx, objId, scaleX, scaleY, positions) { + if (!this.contentVisible) { + return; + } + const imgData = this.getObject(opIdx, objId); + if (!imgData) { + warn("Dependent image isn't ready yet"); + return; + } + const width = imgData.width; + const height = imgData.height; + const map = []; + for (let i = 0, ii = positions.length; i < ii; i += 2) { + map.push({ + transform: [scaleX, 0, 0, scaleY, positions[i], positions[i + 1]], + x: 0, + y: 0, + w: width, + h: height + }); + } + this.paintInlineImageXObjectGroup(opIdx, imgData, map); + } + applyTransferMapsToCanvas(ctx) { + if (this.current.transferMaps !== "none") { + ctx.filter = this.current.transferMaps; + ctx.drawImage(ctx.canvas, 0, 0); + ctx.filter = "none"; + } + return ctx.canvas; + } + applyTransferMapsToBitmap(imgData) { + if (this.current.transferMaps === "none") { + return imgData.bitmap; + } + const { + bitmap, + width, + height + } = imgData; + const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", width, height); + const tmpCtx = tmpCanvas.context; + tmpCtx.filter = this.current.transferMaps; + tmpCtx.drawImage(bitmap, 0, 0); + tmpCtx.filter = "none"; + return tmpCanvas.canvas; + } + paintInlineImageXObject(opIdx, imgData) { + if (!this.contentVisible) { + return; + } + const width = imgData.width; + const height = imgData.height; + const ctx = this.ctx; + this.save(opIdx); + const { + filter + } = ctx; + if (filter !== "none" && filter !== "") { + ctx.filter = "none"; + } + ctx.scale(1 / width, -1 / height); + let imgToPaint; + if (imgData.bitmap) { + imgToPaint = this.applyTransferMapsToBitmap(imgData); + } else if (typeof HTMLElement === "function" && imgData instanceof HTMLElement || !imgData.data) { + imgToPaint = imgData; + } else { + const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", width, height); + const tmpCtx = tmpCanvas.context; + putBinaryImageData(tmpCtx, imgData); + imgToPaint = this.applyTransferMapsToCanvas(tmpCtx); + } + const scaled = this._scaleImage(imgToPaint, getCurrentTransformInverse(ctx)); + ctx.imageSmoothingEnabled = getImageSmoothingEnabled(getCurrentTransform(ctx), imgData.interpolate); + this.dependencyTracker?.resetBBox(opIdx).recordBBox(opIdx, ctx, 0, width, -height, 0).recordDependencies(opIdx, Dependencies.imageXObject).recordOperation(opIdx); + drawImageAtIntegerCoords(ctx, scaled.img, 0, 0, scaled.paintWidth, scaled.paintHeight, 0, -height, width, height); + this.compose(); + this.restore(opIdx); + } + paintInlineImageXObjectGroup(opIdx, imgData, map) { + if (!this.contentVisible) { + return; + } + const ctx = this.ctx; + let imgToPaint; + if (imgData.bitmap) { + imgToPaint = imgData.bitmap; + } else { + const w = imgData.width; + const h = imgData.height; + const tmpCanvas = this.cachedCanvases.getCanvas("inlineImage", w, h); + const tmpCtx = tmpCanvas.context; + putBinaryImageData(tmpCtx, imgData); + imgToPaint = this.applyTransferMapsToCanvas(tmpCtx); + } + this.dependencyTracker?.resetBBox(opIdx); + for (const entry of map) { + ctx.save(); + ctx.transform(...entry.transform); + ctx.scale(1, -1); + drawImageAtIntegerCoords(ctx, imgToPaint, entry.x, entry.y, entry.w, entry.h, 0, -1, 1, 1); + this.dependencyTracker?.recordBBox(opIdx, ctx, 0, 1, -1, 0); + ctx.restore(); + } + this.dependencyTracker?.recordOperation(opIdx); + this.compose(); + } + paintSolidColorImageMask(opIdx) { + if (!this.contentVisible) { + return; + } + this.dependencyTracker?.resetBBox(opIdx).recordBBox(opIdx, this.ctx, 0, 1, 0, 1).recordDependencies(opIdx, Dependencies.fill).recordOperation(opIdx); + this.ctx.fillRect(0, 0, 1, 1); + this.compose(); + } + markPoint(opIdx, tag) { + } + markPointProps(opIdx, tag, properties) { + } + beginMarkedContent(opIdx, tag) { + this.dependencyTracker?.beginMarkedContent(opIdx); + this.markedContentStack.push({ + visible: true + }); + } + beginMarkedContentProps(opIdx, tag, properties) { + this.dependencyTracker?.beginMarkedContent(opIdx); + if (tag === "OC") { + this.markedContentStack.push({ + visible: this.optionalContentConfig.isVisible(properties) + }); + } else { + this.markedContentStack.push({ + visible: true + }); + } + this.contentVisible = this.isContentVisible(); + } + endMarkedContent(opIdx) { + this.dependencyTracker?.endMarkedContent(opIdx); + this.markedContentStack.pop(); + this.contentVisible = this.isContentVisible(); + } + beginCompat(opIdx) { + } + endCompat(opIdx) { + } + consumePath(opIdx, path, clipBox) { + const isEmpty = this.current.isEmptyClip(); + if (this.pendingClip) { + this.current.updateClipFromPath(); + } + if (!this.pendingClip) { + this.compose(clipBox); + } + const ctx = this.ctx; + if (this.pendingClip) { + if (!isEmpty) { + if (this.pendingClip === EO_CLIP) { + ctx.clip(path, "evenodd"); + } else { + ctx.clip(path); + } + } + this.pendingClip = null; + this.dependencyTracker?.bboxToClipBoxDropOperation(opIdx).recordFutureForcedDependency("clipPath", opIdx); + } else { + this.dependencyTracker?.recordOperation(opIdx); + } + this.current.startNewPathAndClipBox(this.current.clipBox); + } + getSinglePixelWidth() { + if (!this._cachedGetSinglePixelWidth) { + const m = getCurrentTransform(this.ctx); + if (m[1] === 0 && m[2] === 0) { + this._cachedGetSinglePixelWidth = 1 / Math.min(Math.abs(m[0]), Math.abs(m[3])); + } else { + const absDet = Math.abs(m[0] * m[3] - m[2] * m[1]); + const normX = Math.hypot(m[0], m[2]); + const normY = Math.hypot(m[1], m[3]); + this._cachedGetSinglePixelWidth = Math.max(normX, normY) / absDet; + } + } + return this._cachedGetSinglePixelWidth; + } + getScaleForStroking() { + if (this._cachedScaleForStroking[0] === -1) { + const { + lineWidth + } = this.current; + const { + a, + b, + c, + d + } = this.ctx.getTransform(); + let scaleX, scaleY; + if (b === 0 && c === 0) { + const normX = Math.abs(a); + const normY = Math.abs(d); + if (normX === normY) { + if (lineWidth === 0) { + scaleX = scaleY = 1 / normX; + } else { + const scaledLineWidth = normX * lineWidth; + scaleX = scaleY = scaledLineWidth < 1 ? 1 / scaledLineWidth : 1; + } + } else if (lineWidth === 0) { + scaleX = 1 / normX; + scaleY = 1 / normY; + } else { + const scaledXLineWidth = normX * lineWidth; + const scaledYLineWidth = normY * lineWidth; + scaleX = scaledXLineWidth < 1 ? 1 / scaledXLineWidth : 1; + scaleY = scaledYLineWidth < 1 ? 1 / scaledYLineWidth : 1; + } + } else { + const absDet = Math.abs(a * d - b * c); + const normX = Math.hypot(a, b); + const normY = Math.hypot(c, d); + if (lineWidth === 0) { + scaleX = normY / absDet; + scaleY = normX / absDet; + } else { + const baseArea = lineWidth * absDet; + scaleX = normY > baseArea ? normY / baseArea : 1; + scaleY = normX > baseArea ? normX / baseArea : 1; + } + } + this._cachedScaleForStroking[0] = scaleX; + this._cachedScaleForStroking[1] = scaleY; + } + return this._cachedScaleForStroking; + } + rescaleAndStroke(path, saveRestore) { + const { + ctx, + current: { + lineWidth + } + } = this; + const [scaleX, scaleY] = this.getScaleForStroking(); + if (scaleX === scaleY) { + ctx.lineWidth = (lineWidth || 1) * scaleX; + ctx.stroke(path); + return; + } + const dashes = ctx.getLineDash(); + if (saveRestore) { + ctx.save(); + } + ctx.scale(scaleX, scaleY); + SCALE_MATRIX.a = 1 / scaleX; + SCALE_MATRIX.d = 1 / scaleY; + const newPath = new Path2D(); + newPath.addPath(path, SCALE_MATRIX); + if (dashes.length > 0) { + const scale = Math.max(scaleX, scaleY); + ctx.setLineDash(dashes.map((x) => x / scale)); + ctx.lineDashOffset /= scale; + } + ctx.lineWidth = lineWidth || 1; + ctx.stroke(newPath); + if (saveRestore) { + ctx.restore(); + } + } + isContentVisible() { + for (let i = this.markedContentStack.length - 1; i >= 0; i--) { + if (!this.markedContentStack[i].visible) { + return false; + } + } + return true; + } +} +for (const op in OPS) { + if (CanvasGraphics.prototype[op] !== void 0) { + CanvasGraphics.prototype[OPS[op]] = CanvasGraphics.prototype[op]; + } +} +class CssFontInfo { + #buffer; + #view; + #decoder; + static strings = ["fontFamily", "fontWeight", "italicAngle"]; + static write(info2) { + const encoder = new TextEncoder(); + const encodedStrings = {}; + let stringsLength = 0; + for (const prop of CssFontInfo.strings) { + const encoded = encoder.encode(info2[prop]); + encodedStrings[prop] = encoded; + stringsLength += 4 + encoded.length; + } + const buffer = new ArrayBuffer(stringsLength); + const data = new Uint8Array(buffer); + const view = new DataView(buffer); + let offset = 0; + for (const prop of CssFontInfo.strings) { + const encoded = encodedStrings[prop]; + const length = encoded.length; + view.setUint32(offset, length); + data.set(encoded, offset + 4); + offset += 4 + length; + } + assert(offset === buffer.byteLength, "CssFontInfo.write: Buffer overflow"); + return buffer; + } + constructor(buffer) { + this.#buffer = buffer; + this.#view = new DataView(this.#buffer); + this.#decoder = new TextDecoder(); + } + #readString(index) { + assert(index < CssFontInfo.strings.length, "Invalid string index"); + let offset = 0; + for (let i = 0; i < index; i++) { + offset += this.#view.getUint32(offset) + 4; + } + const length = this.#view.getUint32(offset); + return this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, length)); + } + get fontFamily() { + return this.#readString(0); + } + get fontWeight() { + return this.#readString(1); + } + get italicAngle() { + return this.#readString(2); + } +} +class SystemFontInfo { + #buffer; + #view; + #decoder; + static strings = ["css", "loadedName", "baseFontName", "src"]; + static write(info2) { + const encoder = new TextEncoder(); + const encodedStrings = {}; + let stringsLength = 0; + for (const prop of SystemFontInfo.strings) { + const encoded = encoder.encode(info2[prop]); + encodedStrings[prop] = encoded; + stringsLength += 4 + encoded.length; + } + stringsLength += 4; + let encodedStyleStyle, encodedStyleWeight, lengthEstimate = 1 + stringsLength; + if (info2.style) { + encodedStyleStyle = encoder.encode(info2.style.style); + encodedStyleWeight = encoder.encode(info2.style.weight); + lengthEstimate += 4 + encodedStyleStyle.length + 4 + encodedStyleWeight.length; + } + const buffer = new ArrayBuffer(lengthEstimate); + const data = new Uint8Array(buffer); + const view = new DataView(buffer); + let offset = 0; + view.setUint8(offset++, info2.guessFallback ? 1 : 0); + view.setUint32(offset, 0); + offset += 4; + stringsLength = 0; + for (const prop of SystemFontInfo.strings) { + const encoded = encodedStrings[prop]; + const length = encoded.length; + stringsLength += 4 + length; + view.setUint32(offset, length); + data.set(encoded, offset + 4); + offset += 4 + length; + } + view.setUint32(offset - stringsLength - 4, stringsLength); + if (info2.style) { + view.setUint32(offset, encodedStyleStyle.length); + data.set(encodedStyleStyle, offset + 4); + offset += 4 + encodedStyleStyle.length; + view.setUint32(offset, encodedStyleWeight.length); + data.set(encodedStyleWeight, offset + 4); + offset += 4 + encodedStyleWeight.length; + } + assert(offset <= buffer.byteLength, "SubstitionInfo.write: Buffer overflow"); + return buffer.transferToFixedLength(offset); + } + constructor(buffer) { + this.#buffer = buffer; + this.#view = new DataView(this.#buffer); + this.#decoder = new TextDecoder(); + } + get guessFallback() { + return this.#view.getUint8(0) !== 0; + } + #readString(index) { + assert(index < SystemFontInfo.strings.length, "Invalid string index"); + let offset = 5; + for (let i = 0; i < index; i++) { + offset += this.#view.getUint32(offset) + 4; + } + const length = this.#view.getUint32(offset); + return this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, length)); + } + get css() { + return this.#readString(0); + } + get loadedName() { + return this.#readString(1); + } + get baseFontName() { + return this.#readString(2); + } + get src() { + return this.#readString(3); + } + get style() { + let offset = 1; + offset += 4 + this.#view.getUint32(offset); + const styleLength = this.#view.getUint32(offset); + const style = this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, styleLength)); + offset += 4 + styleLength; + const weightLength = this.#view.getUint32(offset); + const weight = this.#decoder.decode(new Uint8Array(this.#buffer, offset + 4, weightLength)); + return { + style, + weight + }; + } +} +class FontInfo { + static bools = ["black", "bold", "disableFontFace", "fontExtraProperties", "isInvalidPDFjsFont", "isType3Font", "italic", "missingFile", "remeasure", "vertical"]; + static numbers = ["ascent", "defaultWidth", "descent"]; + static strings = ["fallbackName", "loadedName", "mimetype", "name"]; + static #OFFSET_NUMBERS = Math.ceil(this.bools.length * 2 / 8); + static #OFFSET_BBOX = this.#OFFSET_NUMBERS + this.numbers.length * 8; + static #OFFSET_FONT_MATRIX = this.#OFFSET_BBOX + 1 + 2 * 4; + static #OFFSET_DEFAULT_VMETRICS = this.#OFFSET_FONT_MATRIX + 1 + 8 * 6; + static #OFFSET_STRINGS = this.#OFFSET_DEFAULT_VMETRICS + 1 + 2 * 3; + #buffer; + #decoder; + #view; + constructor({ + data, + extra + }) { + this.#buffer = data; + this.#decoder = new TextDecoder(); + this.#view = new DataView(this.#buffer); + if (extra) { + Object.assign(this, extra); + } + } + #readBoolean(index) { + assert(index < FontInfo.bools.length, "Invalid boolean index"); + const byteOffset = Math.floor(index / 4); + const bitOffset = index * 2 % 8; + const value = this.#view.getUint8(byteOffset) >> bitOffset & 3; + return value === 0 ? void 0 : value === 2; + } + get black() { + return this.#readBoolean(0); + } + get bold() { + return this.#readBoolean(1); + } + get disableFontFace() { + return this.#readBoolean(2); + } + get fontExtraProperties() { + return this.#readBoolean(3); + } + get isInvalidPDFjsFont() { + return this.#readBoolean(4); + } + get isType3Font() { + return this.#readBoolean(5); + } + get italic() { + return this.#readBoolean(6); + } + get missingFile() { + return this.#readBoolean(7); + } + get remeasure() { + return this.#readBoolean(8); + } + get vertical() { + return this.#readBoolean(9); + } + #readNumber(index) { + assert(index < FontInfo.numbers.length, "Invalid number index"); + return this.#view.getFloat64(FontInfo.#OFFSET_NUMBERS + index * 8); + } + get ascent() { + return this.#readNumber(0); + } + get defaultWidth() { + return this.#readNumber(1); + } + get descent() { + return this.#readNumber(2); + } + get bbox() { + let offset = FontInfo.#OFFSET_BBOX; + const numCoords = this.#view.getUint8(offset); + if (numCoords === 0) { + return void 0; + } + offset += 1; + const bbox = []; + for (let i = 0; i < 4; i++) { + bbox.push(this.#view.getInt16(offset, true)); + offset += 2; + } + return bbox; + } + get fontMatrix() { + let offset = FontInfo.#OFFSET_FONT_MATRIX; + const numPoints = this.#view.getUint8(offset); + if (numPoints === 0) { + return void 0; + } + offset += 1; + const fontMatrix = []; + for (let i = 0; i < 6; i++) { + fontMatrix.push(this.#view.getFloat64(offset, true)); + offset += 8; + } + return fontMatrix; + } + get defaultVMetrics() { + let offset = FontInfo.#OFFSET_DEFAULT_VMETRICS; + const numMetrics = this.#view.getUint8(offset); + if (numMetrics === 0) { + return void 0; + } + offset += 1; + const defaultVMetrics = []; + for (let i = 0; i < 3; i++) { + defaultVMetrics.push(this.#view.getInt16(offset, true)); + offset += 2; + } + return defaultVMetrics; + } + #readString(index) { + assert(index < FontInfo.strings.length, "Invalid string index"); + let offset = FontInfo.#OFFSET_STRINGS + 4; + for (let i = 0; i < index; i++) { + offset += this.#view.getUint32(offset) + 4; + } + const length = this.#view.getUint32(offset); + const stringData = new Uint8Array(length); + stringData.set(new Uint8Array(this.#buffer, offset + 4, length)); + return this.#decoder.decode(stringData); + } + get fallbackName() { + return this.#readString(0); + } + get loadedName() { + return this.#readString(1); + } + get mimetype() { + return this.#readString(2); + } + get name() { + return this.#readString(3); + } + get data() { + let offset = FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + offset += 4 + systemFontInfoLength; + const cssFontInfoLength = this.#view.getUint32(offset); + offset += 4 + cssFontInfoLength; + const length = this.#view.getUint32(offset); + if (length === 0) { + return void 0; + } + return new Uint8Array(this.#buffer, offset + 4, length); + } + clearData() { + let offset = FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + offset += 4 + systemFontInfoLength; + const cssFontInfoLength = this.#view.getUint32(offset); + offset += 4 + cssFontInfoLength; + const length = this.#view.getUint32(offset); + const data = new Uint8Array(this.#buffer, offset + 4, length); + data.fill(0); + this.#view.setUint32(offset, 0); + } + get cssFontInfo() { + let offset = FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + offset += 4 + systemFontInfoLength; + const cssFontInfoLength = this.#view.getUint32(offset); + if (cssFontInfoLength === 0) { + return null; + } + const cssFontInfoData = new Uint8Array(cssFontInfoLength); + cssFontInfoData.set(new Uint8Array(this.#buffer, offset + 4, cssFontInfoLength)); + return new CssFontInfo(cssFontInfoData.buffer); + } + get systemFontInfo() { + let offset = FontInfo.#OFFSET_STRINGS; + const stringsLength = this.#view.getUint32(offset); + offset += 4 + stringsLength; + const systemFontInfoLength = this.#view.getUint32(offset); + if (systemFontInfoLength === 0) { + return null; + } + const systemFontInfoData = new Uint8Array(systemFontInfoLength); + systemFontInfoData.set(new Uint8Array(this.#buffer, offset + 4, systemFontInfoLength)); + return new SystemFontInfo(systemFontInfoData.buffer); + } + static write(font) { + const systemFontInfoBuffer = font.systemFontInfo ? SystemFontInfo.write(font.systemFontInfo) : null; + const cssFontInfoBuffer = font.cssFontInfo ? CssFontInfo.write(font.cssFontInfo) : null; + const encoder = new TextEncoder(); + const encodedStrings = {}; + let stringsLength = 0; + for (const prop of FontInfo.strings) { + encodedStrings[prop] = encoder.encode(font[prop]); + stringsLength += 4 + encodedStrings[prop].length; + } + const lengthEstimate = FontInfo.#OFFSET_STRINGS + 4 + stringsLength + 4 + (systemFontInfoBuffer ? systemFontInfoBuffer.byteLength : 0) + 4 + (cssFontInfoBuffer ? cssFontInfoBuffer.byteLength : 0) + 4 + (font.data ? font.data.length : 0); + const buffer = new ArrayBuffer(lengthEstimate); + const data = new Uint8Array(buffer); + const view = new DataView(buffer); + let offset = 0; + const numBools = FontInfo.bools.length; + let boolByte = 0, boolBit = 0; + for (let i = 0; i < numBools; i++) { + const value = font[FontInfo.bools[i]]; + const bits = value === void 0 ? 0 : value ? 2 : 1; + boolByte |= bits << boolBit; + boolBit += 2; + if (boolBit === 8 || i === numBools - 1) { + view.setUint8(offset++, boolByte); + boolByte = 0; + boolBit = 0; + } + } + assert(offset === FontInfo.#OFFSET_NUMBERS, "FontInfo.write: Boolean properties offset mismatch"); + for (const prop of FontInfo.numbers) { + view.setFloat64(offset, font[prop]); + offset += 8; + } + assert(offset === FontInfo.#OFFSET_BBOX, "FontInfo.write: Number properties offset mismatch"); + if (font.bbox) { + view.setUint8(offset++, 4); + for (const coord of font.bbox) { + view.setInt16(offset, coord, true); + offset += 2; + } + } else { + view.setUint8(offset++, 0); + offset += 2 * 4; + } + assert(offset === FontInfo.#OFFSET_FONT_MATRIX, "FontInfo.write: BBox properties offset mismatch"); + if (font.fontMatrix) { + view.setUint8(offset++, 6); + for (const point of font.fontMatrix) { + view.setFloat64(offset, point, true); + offset += 8; + } + } else { + view.setUint8(offset++, 0); + offset += 8 * 6; + } + assert(offset === FontInfo.#OFFSET_DEFAULT_VMETRICS, "FontInfo.write: FontMatrix properties offset mismatch"); + if (font.defaultVMetrics) { + view.setUint8(offset++, 1); + for (const metric of font.defaultVMetrics) { + view.setInt16(offset, metric, true); + offset += 2; + } + } else { + view.setUint8(offset++, 0); + offset += 3 * 2; + } + assert(offset === FontInfo.#OFFSET_STRINGS, "FontInfo.write: DefaultVMetrics properties offset mismatch"); + view.setUint32(FontInfo.#OFFSET_STRINGS, 0); + offset += 4; + for (const prop of FontInfo.strings) { + const encoded = encodedStrings[prop]; + const length = encoded.length; + view.setUint32(offset, length); + data.set(encoded, offset + 4); + offset += 4 + length; + } + view.setUint32(FontInfo.#OFFSET_STRINGS, offset - FontInfo.#OFFSET_STRINGS - 4); + if (!systemFontInfoBuffer) { + view.setUint32(offset, 0); + offset += 4; + } else { + const length = systemFontInfoBuffer.byteLength; + view.setUint32(offset, length); + assert(offset + 4 + length <= buffer.byteLength, "FontInfo.write: Buffer overflow at systemFontInfo"); + data.set(new Uint8Array(systemFontInfoBuffer), offset + 4); + offset += 4 + length; + } + if (!cssFontInfoBuffer) { + view.setUint32(offset, 0); + offset += 4; + } else { + const length = cssFontInfoBuffer.byteLength; + view.setUint32(offset, length); + assert(offset + 4 + length <= buffer.byteLength, "FontInfo.write: Buffer overflow at cssFontInfo"); + data.set(new Uint8Array(cssFontInfoBuffer), offset + 4); + offset += 4 + length; + } + if (font.data === void 0) { + view.setUint32(offset, 0); + offset += 4; + } else { + view.setUint32(offset, font.data.length); + data.set(font.data, offset + 4); + offset += 4 + font.data.length; + } + assert(offset <= buffer.byteLength, "FontInfo.write: Buffer overflow"); + return buffer.transferToFixedLength(offset); + } +} +class GlobalWorkerOptions { + static #port = null; + static #src = ""; + static get workerPort() { + return this.#port; + } + static set workerPort(val) { + if (!(typeof Worker !== "undefined" && val instanceof Worker) && val !== null) { + throw new Error("Invalid `workerPort` type."); + } + this.#port = val; + } + static get workerSrc() { + return this.#src; + } + static set workerSrc(val) { + if (typeof val !== "string") { + throw new Error("Invalid `workerSrc` type."); + } + this.#src = val; + } +} +class Metadata { + #map; + #data; + constructor({ + parsedData, + rawData + }) { + this.#map = parsedData; + this.#data = rawData; + } + getRaw() { + return this.#data; + } + get(name) { + return this.#map.get(name) ?? null; + } + [Symbol.iterator]() { + return this.#map.entries(); + } +} +const INTERNAL = Symbol("INTERNAL"); +class OptionalContentGroup { + #isDisplay = false; + #isPrint = false; + #userSet = false; + #visible = true; + constructor(renderingIntent, { + name, + intent, + usage, + rbGroups + }) { + this.#isDisplay = !!(renderingIntent & RenderingIntentFlag.DISPLAY); + this.#isPrint = !!(renderingIntent & RenderingIntentFlag.PRINT); + this.name = name; + this.intent = intent; + this.usage = usage; + this.rbGroups = rbGroups; + } + get visible() { + if (this.#userSet) { + return this.#visible; + } + if (!this.#visible) { + return false; + } + const { + print, + view + } = this.usage; + if (this.#isDisplay) { + return view?.viewState !== "OFF"; + } else if (this.#isPrint) { + return print?.printState !== "OFF"; + } + return true; + } + _setVisible(internal, visible, userSet = false) { + if (internal !== INTERNAL) { + unreachable("Internal method `_setVisible` called."); + } + this.#userSet = userSet; + this.#visible = visible; + } +} +class OptionalContentConfig { + #cachedGetHash = null; + #groups = /* @__PURE__ */ new Map(); + #initialHash = null; + #order = null; + constructor(data, renderingIntent = RenderingIntentFlag.DISPLAY) { + this.renderingIntent = renderingIntent; + this.name = null; + this.creator = null; + if (data === null) { + return; + } + this.name = data.name; + this.creator = data.creator; + this.#order = data.order; + for (const group of data.groups) { + this.#groups.set(group.id, new OptionalContentGroup(renderingIntent, group)); + } + if (data.baseState === "OFF") { + for (const group of this.#groups.values()) { + group._setVisible(INTERNAL, false); + } + } + for (const on of data.on) { + this.#groups.get(on)._setVisible(INTERNAL, true); + } + for (const off of data.off) { + this.#groups.get(off)._setVisible(INTERNAL, false); + } + this.#initialHash = this.getHash(); + } + #evaluateVisibilityExpression(array) { + const length = array.length; + if (length < 2) { + return true; + } + const operator = array[0]; + for (let i = 1; i < length; i++) { + const element = array[i]; + let state; + if (Array.isArray(element)) { + state = this.#evaluateVisibilityExpression(element); + } else if (this.#groups.has(element)) { + state = this.#groups.get(element).visible; + } else { + warn(`Optional content group not found: ${element}`); + return true; + } + switch (operator) { + case "And": + if (!state) { + return false; + } + break; + case "Or": + if (state) { + return true; + } + break; + case "Not": + return !state; + default: + return true; + } + } + return operator === "And"; + } + isVisible(group) { + if (this.#groups.size === 0) { + return true; + } + if (!group) { + info("Optional content group not defined."); + return true; + } + if (group.type === "OCG") { + if (!this.#groups.has(group.id)) { + warn(`Optional content group not found: ${group.id}`); + return true; + } + return this.#groups.get(group.id).visible; + } else if (group.type === "OCMD") { + if (group.expression) { + return this.#evaluateVisibilityExpression(group.expression); + } + if (!group.policy || group.policy === "AnyOn") { + for (const id of group.ids) { + if (!this.#groups.has(id)) { + warn(`Optional content group not found: ${id}`); + return true; + } + if (this.#groups.get(id).visible) { + return true; + } + } + return false; + } else if (group.policy === "AllOn") { + for (const id of group.ids) { + if (!this.#groups.has(id)) { + warn(`Optional content group not found: ${id}`); + return true; + } + if (!this.#groups.get(id).visible) { + return false; + } + } + return true; + } else if (group.policy === "AnyOff") { + for (const id of group.ids) { + if (!this.#groups.has(id)) { + warn(`Optional content group not found: ${id}`); + return true; + } + if (!this.#groups.get(id).visible) { + return true; + } + } + return false; + } else if (group.policy === "AllOff") { + for (const id of group.ids) { + if (!this.#groups.has(id)) { + warn(`Optional content group not found: ${id}`); + return true; + } + if (this.#groups.get(id).visible) { + return false; + } + } + return true; + } + warn(`Unknown optional content policy ${group.policy}.`); + return true; + } + warn(`Unknown group type ${group.type}.`); + return true; + } + setVisibility(id, visible = true, preserveRB = true) { + const group = this.#groups.get(id); + if (!group) { + warn(`Optional content group not found: ${id}`); + return; + } + if (preserveRB && visible && group.rbGroups.length) { + for (const rbGroup of group.rbGroups) { + for (const otherId of rbGroup) { + if (otherId !== id) { + this.#groups.get(otherId)?._setVisible(INTERNAL, false, true); + } + } + } + } + group._setVisible(INTERNAL, !!visible, true); + this.#cachedGetHash = null; + } + setOCGState({ + state, + preserveRB + }) { + let operator; + for (const elem of state) { + switch (elem) { + case "ON": + case "OFF": + case "Toggle": + operator = elem; + continue; + } + const group = this.#groups.get(elem); + if (!group) { + continue; + } + switch (operator) { + case "ON": + this.setVisibility(elem, true, preserveRB); + break; + case "OFF": + this.setVisibility(elem, false, preserveRB); + break; + case "Toggle": + this.setVisibility(elem, !group.visible, preserveRB); + break; + } + } + this.#cachedGetHash = null; + } + get hasInitialVisibility() { + return this.#initialHash === null || this.getHash() === this.#initialHash; + } + getOrder() { + if (!this.#groups.size) { + return null; + } + if (this.#order) { + return this.#order.slice(); + } + return [...this.#groups.keys()]; + } + getGroup(id) { + return this.#groups.get(id) || null; + } + getHash() { + if (this.#cachedGetHash !== null) { + return this.#cachedGetHash; + } + const hash = new MurmurHash3_64(); + for (const [id, group] of this.#groups) { + hash.update(`${id}:${group.visible}`); + } + return this.#cachedGetHash = hash.hexdigest(); + } + [Symbol.iterator]() { + return this.#groups.entries(); + } +} +class PDFDataTransportStream { + constructor(pdfDataRangeTransport, { + disableRange = false, + disableStream = false + }) { + assert(pdfDataRangeTransport, 'PDFDataTransportStream - missing required "pdfDataRangeTransport" argument.'); + const { + length, + initialData, + progressiveDone, + contentDispositionFilename + } = pdfDataRangeTransport; + this._queuedChunks = []; + this._progressiveDone = progressiveDone; + this._contentDispositionFilename = contentDispositionFilename; + if (initialData?.length > 0) { + const buffer = initialData instanceof Uint8Array && initialData.byteLength === initialData.buffer.byteLength ? initialData.buffer : new Uint8Array(initialData).buffer; + this._queuedChunks.push(buffer); + } + this._pdfDataRangeTransport = pdfDataRangeTransport; + this._isStreamingSupported = !disableStream; + this._isRangeSupported = !disableRange; + this._contentLength = length; + this._fullRequestReader = null; + this._rangeReaders = []; + pdfDataRangeTransport.addRangeListener((begin, chunk) => { + this._onReceiveData({ + begin, + chunk + }); + }); + pdfDataRangeTransport.addProgressListener((loaded, total) => { + this._onProgress({ + loaded, + total + }); + }); + pdfDataRangeTransport.addProgressiveReadListener((chunk) => { + this._onReceiveData({ + chunk + }); + }); + pdfDataRangeTransport.addProgressiveDoneListener(() => { + this._onProgressiveDone(); + }); + pdfDataRangeTransport.transportReady(); + } + _onReceiveData({ + begin, + chunk + }) { + const buffer = chunk instanceof Uint8Array && chunk.byteLength === chunk.buffer.byteLength ? chunk.buffer : new Uint8Array(chunk).buffer; + if (begin === void 0) { + if (this._fullRequestReader) { + this._fullRequestReader._enqueue(buffer); + } else { + this._queuedChunks.push(buffer); + } + } else { + const found = this._rangeReaders.some(function(rangeReader) { + if (rangeReader._begin !== begin) { + return false; + } + rangeReader._enqueue(buffer); + return true; + }); + assert(found, "_onReceiveData - no `PDFDataTransportStreamRangeReader` instance found."); + } + } + get _progressiveDataLength() { + return this._fullRequestReader?._loaded ?? 0; + } + _onProgress(evt) { + if (evt.total === void 0) { + this._rangeReaders[0]?.onProgress?.({ + loaded: evt.loaded + }); + } else { + this._fullRequestReader?.onProgress?.({ + loaded: evt.loaded, + total: evt.total + }); + } + } + _onProgressiveDone() { + this._fullRequestReader?.progressiveDone(); + this._progressiveDone = true; + } + _removeRangeReader(reader) { + const i = this._rangeReaders.indexOf(reader); + if (i >= 0) { + this._rangeReaders.splice(i, 1); + } + } + getFullReader() { + assert(!this._fullRequestReader, "PDFDataTransportStream.getFullReader can only be called once."); + const queuedChunks = this._queuedChunks; + this._queuedChunks = null; + return new PDFDataTransportStreamReader(this, queuedChunks, this._progressiveDone, this._contentDispositionFilename); + } + getRangeReader(begin, end) { + if (end <= this._progressiveDataLength) { + return null; + } + const reader = new PDFDataTransportStreamRangeReader(this, begin, end); + this._pdfDataRangeTransport.requestDataRange(begin, end); + this._rangeReaders.push(reader); + return reader; + } + cancelAllRequests(reason) { + this._fullRequestReader?.cancel(reason); + for (const reader of this._rangeReaders.slice(0)) { + reader.cancel(reason); + } + this._pdfDataRangeTransport.abort(); + } +} +class PDFDataTransportStreamReader { + constructor(stream, queuedChunks, progressiveDone = false, contentDispositionFilename = null) { + this._stream = stream; + this._done = progressiveDone || false; + this._filename = isPdfFile(contentDispositionFilename) ? contentDispositionFilename : null; + this._queuedChunks = queuedChunks || []; + this._loaded = 0; + for (const chunk of this._queuedChunks) { + this._loaded += chunk.byteLength; + } + this._requests = []; + this._headersReady = Promise.resolve(); + stream._fullRequestReader = this; + this.onProgress = null; + } + _enqueue(chunk) { + if (this._done) { + return; + } + if (this._requests.length > 0) { + const requestCapability = this._requests.shift(); + requestCapability.resolve({ + value: chunk, + done: false + }); + } else { + this._queuedChunks.push(chunk); + } + this._loaded += chunk.byteLength; + } + get headersReady() { + return this._headersReady; + } + get filename() { + return this._filename; + } + get isRangeSupported() { + return this._stream._isRangeSupported; + } + get isStreamingSupported() { + return this._stream._isStreamingSupported; + } + get contentLength() { + return this._stream._contentLength; + } + async read() { + if (this._queuedChunks.length > 0) { + const chunk = this._queuedChunks.shift(); + return { + value: chunk, + done: false + }; + } + if (this._done) { + return { + value: void 0, + done: true + }; + } + const requestCapability = Promise.withResolvers(); + this._requests.push(requestCapability); + return requestCapability.promise; + } + cancel(reason) { + this._done = true; + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: void 0, + done: true + }); + } + this._requests.length = 0; + } + progressiveDone() { + if (this._done) { + return; + } + this._done = true; + } +} +class PDFDataTransportStreamRangeReader { + constructor(stream, begin, end) { + this._stream = stream; + this._begin = begin; + this._end = end; + this._queuedChunk = null; + this._requests = []; + this._done = false; + this.onProgress = null; + } + _enqueue(chunk) { + if (this._done) { + return; + } + if (this._requests.length === 0) { + this._queuedChunk = chunk; + } else { + const requestsCapability = this._requests.shift(); + requestsCapability.resolve({ + value: chunk, + done: false + }); + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: void 0, + done: true + }); + } + this._requests.length = 0; + } + this._done = true; + this._stream._removeRangeReader(this); + } + get isStreamingSupported() { + return false; + } + async read() { + if (this._queuedChunk) { + const chunk = this._queuedChunk; + this._queuedChunk = null; + return { + value: chunk, + done: false + }; + } + if (this._done) { + return { + value: void 0, + done: true + }; + } + const requestCapability = Promise.withResolvers(); + this._requests.push(requestCapability); + return requestCapability.promise; + } + cancel(reason) { + this._done = true; + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: void 0, + done: true + }); + } + this._requests.length = 0; + this._stream._removeRangeReader(this); + } +} +function getFilenameFromContentDispositionHeader(contentDisposition) { + let needsEncodingFixup = true; + let tmp = toParamRegExp("filename\\*", "i").exec(contentDisposition); + if (tmp) { + tmp = tmp[1]; + let filename = rfc2616unquote(tmp); + filename = unescape(filename); + filename = rfc5987decode(filename); + filename = rfc2047decode(filename); + return fixupEncoding(filename); + } + tmp = rfc2231getparam(contentDisposition); + if (tmp) { + const filename = rfc2047decode(tmp); + return fixupEncoding(filename); + } + tmp = toParamRegExp("filename", "i").exec(contentDisposition); + if (tmp) { + tmp = tmp[1]; + let filename = rfc2616unquote(tmp); + filename = rfc2047decode(filename); + return fixupEncoding(filename); + } + function toParamRegExp(attributePattern, flags) { + return new RegExp("(?:^|;)\\s*" + attributePattern + '\\s*=\\s*([^";\\s][^;\\s]*|"(?:[^"\\\\]|\\\\"?)+"?)', flags); + } + function textdecode(encoding, value) { + if (encoding) { + if (!/^[\x00-\xFF]+$/.test(value)) { + return value; + } + try { + const decoder = new TextDecoder(encoding, { + fatal: true + }); + const buffer = stringToBytes(value); + value = decoder.decode(buffer); + needsEncodingFixup = false; + } catch { + } + } + return value; + } + function fixupEncoding(value) { + if (needsEncodingFixup && /[\x80-\xff]/.test(value)) { + value = textdecode("utf-8", value); + if (needsEncodingFixup) { + value = textdecode("iso-8859-1", value); + } + } + return value; + } + function rfc2231getparam(contentDispositionStr) { + const matches = []; + let match; + const iter = toParamRegExp("filename\\*((?!0\\d)\\d+)(\\*?)", "ig"); + while ((match = iter.exec(contentDispositionStr)) !== null) { + let [, n, quot, part] = match; + n = parseInt(n, 10); + if (n in matches) { + if (n === 0) { + break; + } + continue; + } + matches[n] = [quot, part]; + } + const parts = []; + for (let n = 0; n < matches.length; ++n) { + if (!(n in matches)) { + break; + } + let [quot, part] = matches[n]; + part = rfc2616unquote(part); + if (quot) { + part = unescape(part); + if (n === 0) { + part = rfc5987decode(part); + } + } + parts.push(part); + } + return parts.join(""); + } + function rfc2616unquote(value) { + if (value.startsWith('"')) { + const parts = value.slice(1).split('\\"'); + for (let i = 0; i < parts.length; ++i) { + const quotindex = parts[i].indexOf('"'); + if (quotindex !== -1) { + parts[i] = parts[i].slice(0, quotindex); + parts.length = i + 1; + } + parts[i] = parts[i].replaceAll(/\\(.)/g, "$1"); + } + value = parts.join('"'); + } + return value; + } + function rfc5987decode(extvalue) { + const encodingend = extvalue.indexOf("'"); + if (encodingend === -1) { + return extvalue; + } + const encoding = extvalue.slice(0, encodingend); + const langvalue = extvalue.slice(encodingend + 1); + const value = langvalue.replace(/^[^']*'/, ""); + return textdecode(encoding, value); + } + function rfc2047decode(value) { + if (!value.startsWith("=?") || /[\x00-\x19\x80-\xff]/.test(value)) { + return value; + } + return value.replaceAll(/=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g, function(matches, charset, encoding, text) { + if (encoding === "q" || encoding === "Q") { + text = text.replaceAll("_", " "); + text = text.replaceAll(/=([0-9a-fA-F]{2})/g, function(match, hex) { + return String.fromCharCode(parseInt(hex, 16)); + }); + return textdecode(charset, text); + } + try { + text = atob(text); + } catch { + } + return textdecode(charset, text); + }); + } + return ""; +} +function createHeaders(isHttp, httpHeaders) { + const headers = new Headers(); + if (!isHttp || !httpHeaders || typeof httpHeaders !== "object") { + return headers; + } + for (const key in httpHeaders) { + const val = httpHeaders[key]; + if (val !== void 0) { + headers.append(key, val); + } + } + return headers; +} +function getResponseOrigin(url) { + return URL.parse(url)?.origin ?? null; +} +function validateRangeRequestCapabilities({ + responseHeaders, + isHttp, + rangeChunkSize, + disableRange +}) { + const returnValues = { + allowRangeRequests: false, + suggestedLength: void 0 + }; + const length = parseInt(responseHeaders.get("Content-Length"), 10); + if (!Number.isInteger(length)) { + return returnValues; + } + returnValues.suggestedLength = length; + if (length <= 2 * rangeChunkSize) { + return returnValues; + } + if (disableRange || !isHttp) { + return returnValues; + } + if (responseHeaders.get("Accept-Ranges") !== "bytes") { + return returnValues; + } + const contentEncoding = responseHeaders.get("Content-Encoding") || "identity"; + if (contentEncoding !== "identity") { + return returnValues; + } + returnValues.allowRangeRequests = true; + return returnValues; +} +function extractFilenameFromHeader(responseHeaders) { + const contentDisposition = responseHeaders.get("Content-Disposition"); + if (contentDisposition) { + let filename = getFilenameFromContentDispositionHeader(contentDisposition); + if (filename.includes("%")) { + try { + filename = decodeURIComponent(filename); + } catch { + } + } + if (isPdfFile(filename)) { + return filename; + } + } + return null; +} +function createResponseError(status, url) { + return new ResponseException(`Unexpected server response (${status}) while retrieving PDF "${url}".`, status, status === 404 || status === 0 && url.startsWith("file:")); +} +function validateResponseStatus(status) { + return status === 200 || status === 206; +} +function createFetchOptions(headers, withCredentials, abortController) { + return { + method: "GET", + headers, + signal: abortController.signal, + mode: "cors", + credentials: withCredentials ? "include" : "same-origin", + redirect: "follow" + }; +} +function getArrayBuffer(val) { + if (val instanceof Uint8Array) { + return val.buffer; + } + if (val instanceof ArrayBuffer) { + return val; + } + warn(`getArrayBuffer - unexpected data format: ${val}`); + return new Uint8Array(val).buffer; +} +class PDFFetchStream { + _responseOrigin = null; + constructor(source) { + this.source = source; + this.isHttp = /^https?:/i.test(source.url); + this.headers = createHeaders(this.isHttp, source.httpHeaders); + this._fullRequestReader = null; + this._rangeRequestReaders = []; + } + get _progressiveDataLength() { + return this._fullRequestReader?._loaded ?? 0; + } + getFullReader() { + assert(!this._fullRequestReader, "PDFFetchStream.getFullReader can only be called once."); + this._fullRequestReader = new PDFFetchStreamReader(this); + return this._fullRequestReader; + } + getRangeReader(begin, end) { + if (end <= this._progressiveDataLength) { + return null; + } + const reader = new PDFFetchStreamRangeReader(this, begin, end); + this._rangeRequestReaders.push(reader); + return reader; + } + cancelAllRequests(reason) { + this._fullRequestReader?.cancel(reason); + for (const reader of this._rangeRequestReaders.slice(0)) { + reader.cancel(reason); + } + } +} +class PDFFetchStreamReader { + constructor(stream) { + this._stream = stream; + this._reader = null; + this._loaded = 0; + this._filename = null; + const source = stream.source; + this._withCredentials = source.withCredentials || false; + this._contentLength = source.length; + this._headersCapability = Promise.withResolvers(); + this._disableRange = source.disableRange || false; + this._rangeChunkSize = source.rangeChunkSize; + if (!this._rangeChunkSize && !this._disableRange) { + this._disableRange = true; + } + this._abortController = new AbortController(); + this._isStreamingSupported = !source.disableStream; + this._isRangeSupported = !source.disableRange; + const headers = new Headers(stream.headers); + const url = source.url; + fetch(url, createFetchOptions(headers, this._withCredentials, this._abortController)).then((response) => { + stream._responseOrigin = getResponseOrigin(response.url); + if (!validateResponseStatus(response.status)) { + throw createResponseError(response.status, url); + } + this._reader = response.body.getReader(); + this._headersCapability.resolve(); + const responseHeaders = response.headers; + const { + allowRangeRequests, + suggestedLength + } = validateRangeRequestCapabilities({ + responseHeaders, + isHttp: stream.isHttp, + rangeChunkSize: this._rangeChunkSize, + disableRange: this._disableRange + }); + this._isRangeSupported = allowRangeRequests; + this._contentLength = suggestedLength || this._contentLength; + this._filename = extractFilenameFromHeader(responseHeaders); + if (!this._isStreamingSupported && this._isRangeSupported) { + this.cancel(new AbortException("Streaming is disabled.")); + } + }).catch(this._headersCapability.reject); + this.onProgress = null; + } + get headersReady() { + return this._headersCapability.promise; + } + get filename() { + return this._filename; + } + get contentLength() { + return this._contentLength; + } + get isRangeSupported() { + return this._isRangeSupported; + } + get isStreamingSupported() { + return this._isStreamingSupported; + } + async read() { + await this._headersCapability.promise; + const { + value, + done + } = await this._reader.read(); + if (done) { + return { + value, + done + }; + } + this._loaded += value.byteLength; + this.onProgress?.({ + loaded: this._loaded, + total: this._contentLength + }); + return { + value: getArrayBuffer(value), + done: false + }; + } + cancel(reason) { + this._reader?.cancel(reason); + this._abortController.abort(); + } +} +class PDFFetchStreamRangeReader { + constructor(stream, begin, end) { + this._stream = stream; + this._reader = null; + this._loaded = 0; + const source = stream.source; + this._withCredentials = source.withCredentials || false; + this._readCapability = Promise.withResolvers(); + this._isStreamingSupported = !source.disableStream; + this._abortController = new AbortController(); + const headers = new Headers(stream.headers); + headers.append("Range", `bytes=${begin}-${end - 1}`); + const url = source.url; + fetch(url, createFetchOptions(headers, this._withCredentials, this._abortController)).then((response) => { + const responseOrigin = getResponseOrigin(response.url); + if (responseOrigin !== stream._responseOrigin) { + throw new Error(`Expected range response-origin "${responseOrigin}" to match "${stream._responseOrigin}".`); + } + if (!validateResponseStatus(response.status)) { + throw createResponseError(response.status, url); + } + this._readCapability.resolve(); + this._reader = response.body.getReader(); + }).catch(this._readCapability.reject); + this.onProgress = null; + } + get isStreamingSupported() { + return this._isStreamingSupported; + } + async read() { + await this._readCapability.promise; + const { + value, + done + } = await this._reader.read(); + if (done) { + return { + value, + done + }; + } + this._loaded += value.byteLength; + this.onProgress?.({ + loaded: this._loaded + }); + return { + value: getArrayBuffer(value), + done: false + }; + } + cancel(reason) { + this._reader?.cancel(reason); + this._abortController.abort(); + } +} +const OK_RESPONSE = 200; +const PARTIAL_CONTENT_RESPONSE = 206; +function network_getArrayBuffer(xhr) { + const data = xhr.response; + if (typeof data !== "string") { + return data; + } + return stringToBytes(data).buffer; +} +class NetworkManager { + _responseOrigin = null; + constructor({ + url, + httpHeaders, + withCredentials + }) { + this.url = url; + this.isHttp = /^https?:/i.test(url); + this.headers = createHeaders(this.isHttp, httpHeaders); + this.withCredentials = withCredentials || false; + this.currXhrId = 0; + this.pendingRequests = /* @__PURE__ */ Object.create(null); + } + request(args) { + const xhr = new XMLHttpRequest(); + const xhrId = this.currXhrId++; + const pendingRequest = this.pendingRequests[xhrId] = { + xhr + }; + xhr.open("GET", this.url); + xhr.withCredentials = this.withCredentials; + for (const [key, val] of this.headers) { + xhr.setRequestHeader(key, val); + } + if (this.isHttp && "begin" in args && "end" in args) { + xhr.setRequestHeader("Range", `bytes=${args.begin}-${args.end - 1}`); + pendingRequest.expectedStatus = PARTIAL_CONTENT_RESPONSE; + } else { + pendingRequest.expectedStatus = OK_RESPONSE; + } + xhr.responseType = "arraybuffer"; + assert(args.onError, "Expected `onError` callback to be provided."); + xhr.onerror = () => { + args.onError(xhr.status); + }; + xhr.onreadystatechange = this.onStateChange.bind(this, xhrId); + xhr.onprogress = this.onProgress.bind(this, xhrId); + pendingRequest.onHeadersReceived = args.onHeadersReceived; + pendingRequest.onDone = args.onDone; + pendingRequest.onError = args.onError; + pendingRequest.onProgress = args.onProgress; + xhr.send(null); + return xhrId; + } + onProgress(xhrId, evt) { + const pendingRequest = this.pendingRequests[xhrId]; + if (!pendingRequest) { + return; + } + pendingRequest.onProgress?.(evt); + } + onStateChange(xhrId, evt) { + const pendingRequest = this.pendingRequests[xhrId]; + if (!pendingRequest) { + return; + } + const xhr = pendingRequest.xhr; + if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) { + pendingRequest.onHeadersReceived(); + delete pendingRequest.onHeadersReceived; + } + if (xhr.readyState !== 4) { + return; + } + if (!(xhrId in this.pendingRequests)) { + return; + } + delete this.pendingRequests[xhrId]; + if (xhr.status === 0 && this.isHttp) { + pendingRequest.onError(xhr.status); + return; + } + const xhrStatus = xhr.status || OK_RESPONSE; + const ok_response_on_range_request = xhrStatus === OK_RESPONSE && pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE; + if (!ok_response_on_range_request && xhrStatus !== pendingRequest.expectedStatus) { + pendingRequest.onError(xhr.status); + return; + } + const chunk = network_getArrayBuffer(xhr); + if (xhrStatus === PARTIAL_CONTENT_RESPONSE) { + const rangeHeader = xhr.getResponseHeader("Content-Range"); + const matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader); + if (matches) { + pendingRequest.onDone({ + begin: parseInt(matches[1], 10), + chunk + }); + } else { + warn(`Missing or invalid "Content-Range" header.`); + pendingRequest.onError(0); + } + } else if (chunk) { + pendingRequest.onDone({ + begin: 0, + chunk + }); + } else { + pendingRequest.onError(xhr.status); + } + } + getRequestXhr(xhrId) { + return this.pendingRequests[xhrId].xhr; + } + isPendingRequest(xhrId) { + return xhrId in this.pendingRequests; + } + abortRequest(xhrId) { + const xhr = this.pendingRequests[xhrId].xhr; + delete this.pendingRequests[xhrId]; + xhr.abort(); + } +} +class PDFNetworkStream { + constructor(source) { + this._source = source; + this._manager = new NetworkManager(source); + this._rangeChunkSize = source.rangeChunkSize; + this._fullRequestReader = null; + this._rangeRequestReaders = []; + } + _onRangeRequestReaderClosed(reader) { + const i = this._rangeRequestReaders.indexOf(reader); + if (i >= 0) { + this._rangeRequestReaders.splice(i, 1); + } + } + getFullReader() { + assert(!this._fullRequestReader, "PDFNetworkStream.getFullReader can only be called once."); + this._fullRequestReader = new PDFNetworkStreamFullRequestReader(this._manager, this._source); + return this._fullRequestReader; + } + getRangeReader(begin, end) { + const reader = new PDFNetworkStreamRangeRequestReader(this._manager, begin, end); + reader.onClosed = this._onRangeRequestReaderClosed.bind(this); + this._rangeRequestReaders.push(reader); + return reader; + } + cancelAllRequests(reason) { + this._fullRequestReader?.cancel(reason); + for (const reader of this._rangeRequestReaders.slice(0)) { + reader.cancel(reason); + } + } +} +class PDFNetworkStreamFullRequestReader { + constructor(manager, source) { + this._manager = manager; + this._url = source.url; + this._fullRequestId = manager.request({ + onHeadersReceived: this._onHeadersReceived.bind(this), + onDone: this._onDone.bind(this), + onError: this._onError.bind(this), + onProgress: this._onProgress.bind(this) + }); + this._headersCapability = Promise.withResolvers(); + this._disableRange = source.disableRange || false; + this._contentLength = source.length; + this._rangeChunkSize = source.rangeChunkSize; + if (!this._rangeChunkSize && !this._disableRange) { + this._disableRange = true; + } + this._isStreamingSupported = false; + this._isRangeSupported = false; + this._cachedChunks = []; + this._requests = []; + this._done = false; + this._storedError = void 0; + this._filename = null; + this.onProgress = null; + } + _onHeadersReceived() { + const fullRequestXhrId = this._fullRequestId; + const fullRequestXhr = this._manager.getRequestXhr(fullRequestXhrId); + this._manager._responseOrigin = getResponseOrigin(fullRequestXhr.responseURL); + const rawResponseHeaders = fullRequestXhr.getAllResponseHeaders(); + const responseHeaders = new Headers(rawResponseHeaders ? rawResponseHeaders.trimStart().replace(/[^\S ]+$/, "").split(/[\r\n]+/).map((x) => { + const [key, ...val] = x.split(": "); + return [key, val.join(": ")]; + }) : []); + const { + allowRangeRequests, + suggestedLength + } = validateRangeRequestCapabilities({ + responseHeaders, + isHttp: this._manager.isHttp, + rangeChunkSize: this._rangeChunkSize, + disableRange: this._disableRange + }); + if (allowRangeRequests) { + this._isRangeSupported = true; + } + this._contentLength = suggestedLength || this._contentLength; + this._filename = extractFilenameFromHeader(responseHeaders); + if (this._isRangeSupported) { + this._manager.abortRequest(fullRequestXhrId); + } + this._headersCapability.resolve(); + } + _onDone(data) { + if (data) { + if (this._requests.length > 0) { + const requestCapability = this._requests.shift(); + requestCapability.resolve({ + value: data.chunk, + done: false + }); + } else { + this._cachedChunks.push(data.chunk); + } + } + this._done = true; + if (this._cachedChunks.length > 0) { + return; + } + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: void 0, + done: true + }); + } + this._requests.length = 0; + } + _onError(status) { + this._storedError = createResponseError(status, this._url); + this._headersCapability.reject(this._storedError); + for (const requestCapability of this._requests) { + requestCapability.reject(this._storedError); + } + this._requests.length = 0; + this._cachedChunks.length = 0; + } + _onProgress(evt) { + this.onProgress?.({ + loaded: evt.loaded, + total: evt.lengthComputable ? evt.total : this._contentLength + }); + } + get filename() { + return this._filename; + } + get isRangeSupported() { + return this._isRangeSupported; + } + get isStreamingSupported() { + return this._isStreamingSupported; + } + get contentLength() { + return this._contentLength; + } + get headersReady() { + return this._headersCapability.promise; + } + async read() { + await this._headersCapability.promise; + if (this._storedError) { + throw this._storedError; + } + if (this._cachedChunks.length > 0) { + const chunk = this._cachedChunks.shift(); + return { + value: chunk, + done: false + }; + } + if (this._done) { + return { + value: void 0, + done: true + }; + } + const requestCapability = Promise.withResolvers(); + this._requests.push(requestCapability); + return requestCapability.promise; + } + cancel(reason) { + this._done = true; + this._headersCapability.reject(reason); + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: void 0, + done: true + }); + } + this._requests.length = 0; + if (this._manager.isPendingRequest(this._fullRequestId)) { + this._manager.abortRequest(this._fullRequestId); + } + this._fullRequestReader = null; + } +} +class PDFNetworkStreamRangeRequestReader { + constructor(manager, begin, end) { + this._manager = manager; + this._url = manager.url; + this._requestId = manager.request({ + begin, + end, + onHeadersReceived: this._onHeadersReceived.bind(this), + onDone: this._onDone.bind(this), + onError: this._onError.bind(this), + onProgress: this._onProgress.bind(this) + }); + this._requests = []; + this._queuedChunk = null; + this._done = false; + this._storedError = void 0; + this.onProgress = null; + this.onClosed = null; + } + _onHeadersReceived() { + const responseOrigin = getResponseOrigin(this._manager.getRequestXhr(this._requestId)?.responseURL); + if (responseOrigin !== this._manager._responseOrigin) { + this._storedError = new Error(`Expected range response-origin "${responseOrigin}" to match "${this._manager._responseOrigin}".`); + this._onError(0); + } + } + _close() { + this.onClosed?.(this); + } + _onDone(data) { + const chunk = data.chunk; + if (this._requests.length > 0) { + const requestCapability = this._requests.shift(); + requestCapability.resolve({ + value: chunk, + done: false + }); + } else { + this._queuedChunk = chunk; + } + this._done = true; + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: void 0, + done: true + }); + } + this._requests.length = 0; + this._close(); + } + _onError(status) { + this._storedError ??= createResponseError(status, this._url); + for (const requestCapability of this._requests) { + requestCapability.reject(this._storedError); + } + this._requests.length = 0; + this._queuedChunk = null; + } + _onProgress(evt) { + if (!this.isStreamingSupported) { + this.onProgress?.({ + loaded: evt.loaded + }); + } + } + get isStreamingSupported() { + return false; + } + async read() { + if (this._storedError) { + throw this._storedError; + } + if (this._queuedChunk !== null) { + const chunk = this._queuedChunk; + this._queuedChunk = null; + return { + value: chunk, + done: false + }; + } + if (this._done) { + return { + value: void 0, + done: true + }; + } + const requestCapability = Promise.withResolvers(); + this._requests.push(requestCapability); + return requestCapability.promise; + } + cancel(reason) { + this._done = true; + for (const requestCapability of this._requests) { + requestCapability.resolve({ + value: void 0, + done: true + }); + } + this._requests.length = 0; + if (this._manager.isPendingRequest(this._requestId)) { + this._manager.abortRequest(this._requestId); + } + this._close(); + } +} +const urlRegex = /^[a-z][a-z0-9\-+.]+:/i; +function parseUrlOrPath(sourceUrl) { + if (urlRegex.test(sourceUrl)) { + return new URL(sourceUrl); + } + const url = process.getBuiltinModule("url"); + return new URL(url.pathToFileURL(sourceUrl)); +} +class PDFNodeStream { + constructor(source) { + this.source = source; + this.url = parseUrlOrPath(source.url); + assert(this.url.protocol === "file:", "PDFNodeStream only supports file:// URLs."); + this._fullRequestReader = null; + this._rangeRequestReaders = []; + } + get _progressiveDataLength() { + return this._fullRequestReader?._loaded ?? 0; + } + getFullReader() { + assert(!this._fullRequestReader, "PDFNodeStream.getFullReader can only be called once."); + this._fullRequestReader = new PDFNodeStreamFsFullReader(this); + return this._fullRequestReader; + } + getRangeReader(start, end) { + if (end <= this._progressiveDataLength) { + return null; + } + const rangeReader = new PDFNodeStreamFsRangeReader(this, start, end); + this._rangeRequestReaders.push(rangeReader); + return rangeReader; + } + cancelAllRequests(reason) { + this._fullRequestReader?.cancel(reason); + for (const reader of this._rangeRequestReaders.slice(0)) { + reader.cancel(reason); + } + } +} +class PDFNodeStreamFsFullReader { + constructor(stream) { + this._url = stream.url; + this._done = false; + this._storedError = null; + this.onProgress = null; + const source = stream.source; + this._contentLength = source.length; + this._loaded = 0; + this._filename = null; + this._disableRange = source.disableRange || false; + this._rangeChunkSize = source.rangeChunkSize; + if (!this._rangeChunkSize && !this._disableRange) { + this._disableRange = true; + } + this._isStreamingSupported = !source.disableStream; + this._isRangeSupported = !source.disableRange; + this._readableStream = null; + this._readCapability = Promise.withResolvers(); + this._headersCapability = Promise.withResolvers(); + const fs = process.getBuiltinModule("fs"); + fs.promises.lstat(this._url).then((stat) => { + this._contentLength = stat.size; + this._setReadableStream(fs.createReadStream(this._url)); + this._headersCapability.resolve(); + }, (error) => { + if (error.code === "ENOENT") { + error = createResponseError(0, this._url.href); + } + this._storedError = error; + this._headersCapability.reject(error); + }); + } + get headersReady() { + return this._headersCapability.promise; + } + get filename() { + return this._filename; + } + get contentLength() { + return this._contentLength; + } + get isRangeSupported() { + return this._isRangeSupported; + } + get isStreamingSupported() { + return this._isStreamingSupported; + } + async read() { + await this._readCapability.promise; + if (this._done) { + return { + value: void 0, + done: true + }; + } + if (this._storedError) { + throw this._storedError; + } + const chunk = this._readableStream.read(); + if (chunk === null) { + this._readCapability = Promise.withResolvers(); + return this.read(); + } + this._loaded += chunk.length; + this.onProgress?.({ + loaded: this._loaded, + total: this._contentLength + }); + const buffer = new Uint8Array(chunk).buffer; + return { + value: buffer, + done: false + }; + } + cancel(reason) { + if (!this._readableStream) { + this._error(reason); + return; + } + this._readableStream.destroy(reason); + } + _error(reason) { + this._storedError = reason; + this._readCapability.resolve(); + } + _setReadableStream(readableStream) { + this._readableStream = readableStream; + readableStream.on("readable", () => { + this._readCapability.resolve(); + }); + readableStream.on("end", () => { + readableStream.destroy(); + this._done = true; + this._readCapability.resolve(); + }); + readableStream.on("error", (reason) => { + this._error(reason); + }); + if (!this._isStreamingSupported && this._isRangeSupported) { + this._error(new AbortException("streaming is disabled")); + } + if (this._storedError) { + this._readableStream.destroy(this._storedError); + } + } +} +class PDFNodeStreamFsRangeReader { + constructor(stream, start, end) { + this._url = stream.url; + this._done = false; + this._storedError = null; + this.onProgress = null; + this._loaded = 0; + this._readableStream = null; + this._readCapability = Promise.withResolvers(); + const source = stream.source; + this._isStreamingSupported = !source.disableStream; + const fs = process.getBuiltinModule("fs"); + this._setReadableStream(fs.createReadStream(this._url, { + start, + end: end - 1 + })); + } + get isStreamingSupported() { + return this._isStreamingSupported; + } + async read() { + await this._readCapability.promise; + if (this._done) { + return { + value: void 0, + done: true + }; + } + if (this._storedError) { + throw this._storedError; + } + const chunk = this._readableStream.read(); + if (chunk === null) { + this._readCapability = Promise.withResolvers(); + return this.read(); + } + this._loaded += chunk.length; + this.onProgress?.({ + loaded: this._loaded + }); + const buffer = new Uint8Array(chunk).buffer; + return { + value: buffer, + done: false + }; + } + cancel(reason) { + if (!this._readableStream) { + this._error(reason); + return; + } + this._readableStream.destroy(reason); + } + _error(reason) { + this._storedError = reason; + this._readCapability.resolve(); + } + _setReadableStream(readableStream) { + this._readableStream = readableStream; + readableStream.on("readable", () => { + this._readCapability.resolve(); + }); + readableStream.on("end", () => { + readableStream.destroy(); + this._done = true; + this._readCapability.resolve(); + }); + readableStream.on("error", (reason) => { + this._error(reason); + }); + if (this._storedError) { + this._readableStream.destroy(this._storedError); + } + } +} +const INITIAL_DATA = Symbol("INITIAL_DATA"); +class PDFObjects { + #objs = /* @__PURE__ */ Object.create(null); + #ensureObj(objId) { + return this.#objs[objId] ||= { + ...Promise.withResolvers(), + data: INITIAL_DATA + }; + } + get(objId, callback = null) { + if (callback) { + const obj2 = this.#ensureObj(objId); + obj2.promise.then(() => callback(obj2.data)); + return null; + } + const obj = this.#objs[objId]; + if (!obj || obj.data === INITIAL_DATA) { + throw new Error(`Requesting object that isn't resolved yet ${objId}.`); + } + return obj.data; + } + has(objId) { + const obj = this.#objs[objId]; + return !!obj && obj.data !== INITIAL_DATA; + } + delete(objId) { + const obj = this.#objs[objId]; + if (!obj || obj.data === INITIAL_DATA) { + return false; + } + delete this.#objs[objId]; + return true; + } + resolve(objId, data = null) { + const obj = this.#ensureObj(objId); + obj.data = data; + obj.resolve(); + } + clear() { + for (const objId in this.#objs) { + const { + data + } = this.#objs[objId]; + data?.bitmap?.close(); + } + this.#objs = /* @__PURE__ */ Object.create(null); + } + *[Symbol.iterator]() { + for (const objId in this.#objs) { + const { + data + } = this.#objs[objId]; + if (data === INITIAL_DATA) { + continue; + } + yield [objId, data]; + } + } +} +const MAX_TEXT_DIVS_TO_RENDER = 1e5; +const DEFAULT_FONT_SIZE = 30; +class TextLayer { + #capability = Promise.withResolvers(); + #container = null; + #disableProcessItems = false; + #fontInspectorEnabled = !!globalThis.FontInspector?.enabled; + #lang = null; + #layoutTextParams = null; + #pageHeight = 0; + #pageWidth = 0; + #reader = null; + #rootContainer = null; + #rotation = 0; + #scale = 0; + #styleCache = /* @__PURE__ */ Object.create(null); + #textContentItemsStr = []; + #textContentSource = null; + #textDivs = []; + #textDivProperties = /* @__PURE__ */ new WeakMap(); + #transform = null; + static #ascentCache = /* @__PURE__ */ new Map(); + static #canvasContexts = /* @__PURE__ */ new Map(); + static #canvasCtxFonts = /* @__PURE__ */ new WeakMap(); + static #minFontSize = null; + static #pendingTextLayers = /* @__PURE__ */ new Set(); + constructor({ + textContentSource, + container, + viewport + }) { + if (textContentSource instanceof ReadableStream) { + this.#textContentSource = textContentSource; + } else if (typeof textContentSource === "object") { + this.#textContentSource = new ReadableStream({ + start(controller) { + controller.enqueue(textContentSource); + controller.close(); + } + }); + } else { + throw new Error('No "textContentSource" parameter specified.'); + } + this.#container = this.#rootContainer = container; + this.#scale = viewport.scale * OutputScale.pixelRatio; + this.#rotation = viewport.rotation; + this.#layoutTextParams = { + div: null, + properties: null, + ctx: null + }; + const { + pageWidth, + pageHeight, + pageX, + pageY + } = viewport.rawDims; + this.#transform = [1, 0, 0, -1, -pageX, pageY + pageHeight]; + this.#pageWidth = pageWidth; + this.#pageHeight = pageHeight; + TextLayer.#ensureMinFontSizeComputed(); + setLayerDimensions(container, viewport); + this.#capability.promise.finally(() => { + TextLayer.#pendingTextLayers.delete(this); + this.#layoutTextParams = null; + this.#styleCache = null; + }).catch(() => { + }); + } + static get fontFamilyMap() { + const { + isWindows, + isFirefox + } = util_FeatureTest.platform; + return shadow(this, "fontFamilyMap", /* @__PURE__ */ new Map([["sans-serif", `${isWindows && isFirefox ? "Calibri, " : ""}sans-serif`], ["monospace", `${isWindows && isFirefox ? "Lucida Console, " : ""}monospace`]])); + } + render() { + const pump = () => { + this.#reader.read().then(({ + value, + done + }) => { + if (done) { + this.#capability.resolve(); + return; + } + this.#lang ??= value.lang; + Object.assign(this.#styleCache, value.styles); + this.#processItems(value.items); + pump(); + }, this.#capability.reject); + }; + this.#reader = this.#textContentSource.getReader(); + TextLayer.#pendingTextLayers.add(this); + pump(); + return this.#capability.promise; + } + update({ + viewport, + onBefore = null + }) { + const scale = viewport.scale * OutputScale.pixelRatio; + const rotation = viewport.rotation; + if (rotation !== this.#rotation) { + onBefore?.(); + this.#rotation = rotation; + setLayerDimensions(this.#rootContainer, { + rotation + }); + } + if (scale !== this.#scale) { + onBefore?.(); + this.#scale = scale; + const params = { + div: null, + properties: null, + ctx: TextLayer.#getCtx(this.#lang) + }; + for (const div of this.#textDivs) { + params.properties = this.#textDivProperties.get(div); + params.div = div; + this.#layout(params); + } + } + } + cancel() { + const abortEx = new AbortException("TextLayer task cancelled."); + this.#reader?.cancel(abortEx).catch(() => { + }); + this.#reader = null; + this.#capability.reject(abortEx); + } + get textDivs() { + return this.#textDivs; + } + get textContentItemsStr() { + return this.#textContentItemsStr; + } + #processItems(items) { + if (this.#disableProcessItems) { + return; + } + this.#layoutTextParams.ctx ??= TextLayer.#getCtx(this.#lang); + const textDivs = this.#textDivs, textContentItemsStr = this.#textContentItemsStr; + for (const item of items) { + if (textDivs.length > MAX_TEXT_DIVS_TO_RENDER) { + warn("Ignoring additional textDivs for performance reasons."); + this.#disableProcessItems = true; + return; + } + if (item.str === void 0) { + if (item.type === "beginMarkedContentProps" || item.type === "beginMarkedContent") { + const parent = this.#container; + this.#container = document.createElement("span"); + this.#container.classList.add("markedContent"); + if (item.id) { + this.#container.setAttribute("id", `${item.id}`); + } + parent.append(this.#container); + } else if (item.type === "endMarkedContent") { + this.#container = this.#container.parentNode; + } + continue; + } + textContentItemsStr.push(item.str); + this.#appendText(item); + } + } + #appendText(geom) { + const textDiv = document.createElement("span"); + const textDivProperties = { + angle: 0, + canvasWidth: 0, + hasText: geom.str !== "", + hasEOL: geom.hasEOL, + fontSize: 0 + }; + this.#textDivs.push(textDiv); + const tx = Util.transform(this.#transform, geom.transform); + let angle = Math.atan2(tx[1], tx[0]); + const style = this.#styleCache[geom.fontName]; + if (style.vertical) { + angle += Math.PI / 2; + } + let fontFamily = this.#fontInspectorEnabled && style.fontSubstitution || style.fontFamily; + fontFamily = TextLayer.fontFamilyMap.get(fontFamily) || fontFamily; + const fontHeight = Math.hypot(tx[2], tx[3]); + const fontAscent = fontHeight * TextLayer.#getAscent(fontFamily, style, this.#lang); + let left, top; + if (angle === 0) { + left = tx[4]; + top = tx[5] - fontAscent; + } else { + left = tx[4] + fontAscent * Math.sin(angle); + top = tx[5] - fontAscent * Math.cos(angle); + } + const scaleFactorStr = "calc(var(--total-scale-factor) *"; + const divStyle = textDiv.style; + if (this.#container === this.#rootContainer) { + divStyle.left = `${(100 * left / this.#pageWidth).toFixed(2)}%`; + divStyle.top = `${(100 * top / this.#pageHeight).toFixed(2)}%`; + } else { + divStyle.left = `${scaleFactorStr}${left.toFixed(2)}px)`; + divStyle.top = `${scaleFactorStr}${top.toFixed(2)}px)`; + } + divStyle.fontSize = `${scaleFactorStr}${(TextLayer.#minFontSize * fontHeight).toFixed(2)}px)`; + divStyle.fontFamily = fontFamily; + textDivProperties.fontSize = fontHeight; + textDiv.setAttribute("role", "presentation"); + textDiv.textContent = geom.str; + textDiv.dir = geom.dir; + if (this.#fontInspectorEnabled) { + textDiv.dataset.fontName = style.fontSubstitutionLoadedName || geom.fontName; + } + if (angle !== 0) { + textDivProperties.angle = angle * (180 / Math.PI); + } + let shouldScaleText = false; + if (geom.str.length > 1) { + shouldScaleText = true; + } else if (geom.str !== " " && geom.transform[0] !== geom.transform[3]) { + const absScaleX = Math.abs(geom.transform[0]), absScaleY = Math.abs(geom.transform[3]); + if (absScaleX !== absScaleY && Math.max(absScaleX, absScaleY) / Math.min(absScaleX, absScaleY) > 1.5) { + shouldScaleText = true; + } + } + if (shouldScaleText) { + textDivProperties.canvasWidth = style.vertical ? geom.height : geom.width; + } + this.#textDivProperties.set(textDiv, textDivProperties); + this.#layoutTextParams.div = textDiv; + this.#layoutTextParams.properties = textDivProperties; + this.#layout(this.#layoutTextParams); + if (textDivProperties.hasText) { + this.#container.append(textDiv); + } + if (textDivProperties.hasEOL) { + const br = document.createElement("br"); + br.setAttribute("role", "presentation"); + this.#container.append(br); + } + } + #layout(params) { + const { + div, + properties, + ctx + } = params; + const { + style + } = div; + let transform = ""; + if (TextLayer.#minFontSize > 1) { + transform = `scale(${1 / TextLayer.#minFontSize})`; + } + if (properties.canvasWidth !== 0 && properties.hasText) { + const { + fontFamily + } = style; + const { + canvasWidth, + fontSize + } = properties; + TextLayer.#ensureCtxFont(ctx, fontSize * this.#scale, fontFamily); + const { + width + } = ctx.measureText(div.textContent); + if (width > 0) { + transform = `scaleX(${canvasWidth * this.#scale / width}) ${transform}`; + } + } + if (properties.angle !== 0) { + transform = `rotate(${properties.angle}deg) ${transform}`; + } + if (transform.length > 0) { + style.transform = transform; + } + } + static cleanup() { + if (this.#pendingTextLayers.size > 0) { + return; + } + this.#ascentCache.clear(); + for (const { + canvas + } of this.#canvasContexts.values()) { + canvas.remove(); + } + this.#canvasContexts.clear(); + } + static #getCtx(lang = null) { + let ctx = this.#canvasContexts.get(lang ||= ""); + if (!ctx) { + const canvas = document.createElement("canvas"); + canvas.className = "hiddenCanvasElement"; + canvas.lang = lang; + document.body.append(canvas); + ctx = canvas.getContext("2d", { + alpha: false, + willReadFrequently: true + }); + this.#canvasContexts.set(lang, ctx); + this.#canvasCtxFonts.set(ctx, { + size: 0, + family: "" + }); + } + return ctx; + } + static #ensureCtxFont(ctx, size, family) { + const cached = this.#canvasCtxFonts.get(ctx); + if (size === cached.size && family === cached.family) { + return; + } + ctx.font = `${size}px ${family}`; + cached.size = size; + cached.family = family; + } + static #ensureMinFontSizeComputed() { + if (this.#minFontSize !== null) { + return; + } + const div = document.createElement("div"); + div.style.opacity = 0; + div.style.lineHeight = 1; + div.style.fontSize = "1px"; + div.style.position = "absolute"; + div.textContent = "X"; + document.body.append(div); + this.#minFontSize = div.getBoundingClientRect().height; + div.remove(); + } + static #getAscent(fontFamily, style, lang) { + const cachedAscent = this.#ascentCache.get(fontFamily); + if (cachedAscent) { + return cachedAscent; + } + const ctx = this.#getCtx(lang); + ctx.canvas.width = ctx.canvas.height = DEFAULT_FONT_SIZE; + this.#ensureCtxFont(ctx, DEFAULT_FONT_SIZE, fontFamily); + const metrics = ctx.measureText(""); + const ascent = metrics.fontBoundingBoxAscent; + const descent = Math.abs(metrics.fontBoundingBoxDescent); + ctx.canvas.width = ctx.canvas.height = 0; + let ratio = 0.8; + if (ascent) { + ratio = ascent / (ascent + descent); + } else { + if (util_FeatureTest.platform.isFirefox) { + warn("Enable the `dom.textMetrics.fontBoundingBox.enabled` preference in `about:config` to improve TextLayer rendering."); + } + if (style.ascent) { + ratio = style.ascent; + } else if (style.descent) { + ratio = 1 + style.descent; + } + } + this.#ascentCache.set(fontFamily, ratio); + return ratio; + } +} +const RENDERING_CANCELLED_TIMEOUT = 100; +function getDocument(src = {}) { + if (typeof src === "string" || src instanceof URL) { + src = { + url: src + }; + } else if (src instanceof ArrayBuffer || ArrayBuffer.isView(src)) { + src = { + data: src + }; + } + const task = new PDFDocumentLoadingTask(); + const { + docId + } = task; + const url = src.url ? getUrlProp(src.url) : null; + const data = src.data ? getDataProp(src.data) : null; + const httpHeaders = src.httpHeaders || null; + const withCredentials = src.withCredentials === true; + const password = src.password ?? null; + const rangeTransport = src.range instanceof PDFDataRangeTransport ? src.range : null; + const rangeChunkSize = Number.isInteger(src.rangeChunkSize) && src.rangeChunkSize > 0 ? src.rangeChunkSize : 2 ** 16; + let worker = src.worker instanceof PDFWorker ? src.worker : null; + const verbosity2 = src.verbosity; + const docBaseUrl = typeof src.docBaseUrl === "string" && !isDataScheme(src.docBaseUrl) ? src.docBaseUrl : null; + const cMapUrl = getFactoryUrlProp(src.cMapUrl); + const cMapPacked = src.cMapPacked !== false; + const CMapReaderFactory = src.CMapReaderFactory || (isNodeJS ? NodeCMapReaderFactory : DOMCMapReaderFactory); + const iccUrl = getFactoryUrlProp(src.iccUrl); + const standardFontDataUrl = getFactoryUrlProp(src.standardFontDataUrl); + const StandardFontDataFactory = src.StandardFontDataFactory || (isNodeJS ? NodeStandardFontDataFactory : DOMStandardFontDataFactory); + const wasmUrl = getFactoryUrlProp(src.wasmUrl); + const WasmFactory = src.WasmFactory || (isNodeJS ? NodeWasmFactory : DOMWasmFactory); + const ignoreErrors = src.stopAtErrors !== true; + const maxImageSize = Number.isInteger(src.maxImageSize) && src.maxImageSize > -1 ? src.maxImageSize : -1; + const isEvalSupported2 = src.isEvalSupported !== false; + const isOffscreenCanvasSupported = typeof src.isOffscreenCanvasSupported === "boolean" ? src.isOffscreenCanvasSupported : !isNodeJS; + const isImageDecoderSupported = typeof src.isImageDecoderSupported === "boolean" ? src.isImageDecoderSupported : !isNodeJS && (util_FeatureTest.platform.isFirefox || !globalThis.chrome); + const canvasMaxAreaInBytes = Number.isInteger(src.canvasMaxAreaInBytes) ? src.canvasMaxAreaInBytes : -1; + const disableFontFace = typeof src.disableFontFace === "boolean" ? src.disableFontFace : isNodeJS; + const fontExtraProperties = src.fontExtraProperties === true; + const enableXfa = src.enableXfa === true; + const ownerDocument = src.ownerDocument || globalThis.document; + const disableRange = src.disableRange === true; + const disableStream = src.disableStream === true; + const disableAutoFetch = src.disableAutoFetch === true; + const pdfBug = src.pdfBug === true; + const CanvasFactory = src.CanvasFactory || (isNodeJS ? NodeCanvasFactory : DOMCanvasFactory); + const FilterFactory = src.FilterFactory || (isNodeJS ? NodeFilterFactory : DOMFilterFactory); + const enableHWA = src.enableHWA === true; + const useWasm = src.useWasm !== false; + const length = rangeTransport ? rangeTransport.length : src.length ?? NaN; + const useSystemFonts = typeof src.useSystemFonts === "boolean" ? src.useSystemFonts : !isNodeJS && !disableFontFace; + const useWorkerFetch = typeof src.useWorkerFetch === "boolean" ? src.useWorkerFetch : !!(CMapReaderFactory === DOMCMapReaderFactory && StandardFontDataFactory === DOMStandardFontDataFactory && WasmFactory === DOMWasmFactory && cMapUrl && standardFontDataUrl && wasmUrl && isValidFetchUrl(cMapUrl, document.baseURI) && isValidFetchUrl(standardFontDataUrl, document.baseURI) && isValidFetchUrl(wasmUrl, document.baseURI)); + const styleElement = null; + setVerbosityLevel(verbosity2); + const transportFactory = { + canvasFactory: new CanvasFactory({ + ownerDocument, + enableHWA + }), + filterFactory: new FilterFactory({ + docId, + ownerDocument + }), + cMapReaderFactory: useWorkerFetch ? null : new CMapReaderFactory({ + baseUrl: cMapUrl, + isCompressed: cMapPacked + }), + standardFontDataFactory: useWorkerFetch ? null : new StandardFontDataFactory({ + baseUrl: standardFontDataUrl + }), + wasmFactory: useWorkerFetch ? null : new WasmFactory({ + baseUrl: wasmUrl + }) + }; + if (!worker) { + worker = PDFWorker.create({ + verbosity: verbosity2, + port: GlobalWorkerOptions.workerPort + }); + task._worker = worker; + } + const docParams = { + docId, + apiVersion: "5.4.296", + data, + password, + disableAutoFetch, + rangeChunkSize, + length, + docBaseUrl, + enableXfa, + evaluatorOptions: { + maxImageSize, + disableFontFace, + ignoreErrors, + isEvalSupported: isEvalSupported2, + isOffscreenCanvasSupported, + isImageDecoderSupported, + canvasMaxAreaInBytes, + fontExtraProperties, + useSystemFonts, + useWasm, + useWorkerFetch, + cMapUrl, + iccUrl, + standardFontDataUrl, + wasmUrl + } + }; + const transportParams = { + ownerDocument, + pdfBug, + styleElement, + loadingParams: { + disableAutoFetch, + enableXfa + } + }; + worker.promise.then(function() { + if (task.destroyed) { + throw new Error("Loading aborted"); + } + if (worker.destroyed) { + throw new Error("Worker was destroyed"); + } + const workerIdPromise = worker.messageHandler.sendWithPromise("GetDocRequest", docParams, data ? [data.buffer] : null); + let networkStream; + if (rangeTransport) { + networkStream = new PDFDataTransportStream(rangeTransport, { + disableRange, + disableStream + }); + } else if (!data) { + if (!url) { + throw new Error("getDocument - no `url` parameter provided."); + } + const NetworkStream = isValidFetchUrl(url) ? PDFFetchStream : isNodeJS ? PDFNodeStream : PDFNetworkStream; + networkStream = new NetworkStream({ + url, + length, + httpHeaders, + withCredentials, + rangeChunkSize, + disableRange, + disableStream + }); + } + return workerIdPromise.then((workerId) => { + if (task.destroyed) { + throw new Error("Loading aborted"); + } + if (worker.destroyed) { + throw new Error("Worker was destroyed"); + } + const messageHandler = new MessageHandler(docId, workerId, worker.port); + const transport = new WorkerTransport(messageHandler, task, networkStream, transportParams, transportFactory, enableHWA); + task._transport = transport; + messageHandler.send("Ready", null); + }); + }).catch(task._capability.reject); + return task; +} +class PDFDocumentLoadingTask { + static #docId = 0; + _capability = Promise.withResolvers(); + _transport = null; + _worker = null; + docId = `d${PDFDocumentLoadingTask.#docId++}`; + destroyed = false; + onPassword = null; + onProgress = null; + get promise() { + return this._capability.promise; + } + async destroy() { + this.destroyed = true; + try { + if (this._worker?.port) { + this._worker._pendingDestroy = true; + } + await this._transport?.destroy(); + } catch (ex) { + if (this._worker?.port) { + delete this._worker._pendingDestroy; + } + throw ex; + } + this._transport = null; + this._worker?.destroy(); + this._worker = null; + } + async getData() { + return this._transport.getData(); + } +} +class PDFDataRangeTransport { + #capability = Promise.withResolvers(); + #progressiveDoneListeners = []; + #progressiveReadListeners = []; + #progressListeners = []; + #rangeListeners = []; + constructor(length, initialData, progressiveDone = false, contentDispositionFilename = null) { + this.length = length; + this.initialData = initialData; + this.progressiveDone = progressiveDone; + this.contentDispositionFilename = contentDispositionFilename; + } + addRangeListener(listener) { + this.#rangeListeners.push(listener); + } + addProgressListener(listener) { + this.#progressListeners.push(listener); + } + addProgressiveReadListener(listener) { + this.#progressiveReadListeners.push(listener); + } + addProgressiveDoneListener(listener) { + this.#progressiveDoneListeners.push(listener); + } + onDataRange(begin, chunk) { + for (const listener of this.#rangeListeners) { + listener(begin, chunk); + } + } + onDataProgress(loaded, total) { + this.#capability.promise.then(() => { + for (const listener of this.#progressListeners) { + listener(loaded, total); + } + }); + } + onDataProgressiveRead(chunk) { + this.#capability.promise.then(() => { + for (const listener of this.#progressiveReadListeners) { + listener(chunk); + } + }); + } + onDataProgressiveDone() { + this.#capability.promise.then(() => { + for (const listener of this.#progressiveDoneListeners) { + listener(); + } + }); + } + transportReady() { + this.#capability.resolve(); + } + requestDataRange(begin, end) { + unreachable("Abstract method PDFDataRangeTransport.requestDataRange"); + } + abort() { + } +} +class PDFDocumentProxy { + constructor(pdfInfo, transport) { + this._pdfInfo = pdfInfo; + this._transport = transport; + } + get annotationStorage() { + return this._transport.annotationStorage; + } + get canvasFactory() { + return this._transport.canvasFactory; + } + get filterFactory() { + return this._transport.filterFactory; + } + get numPages() { + return this._pdfInfo.numPages; + } + get fingerprints() { + return this._pdfInfo.fingerprints; + } + get isPureXfa() { + return shadow(this, "isPureXfa", !!this._transport._htmlForXfa); + } + get allXfaHtml() { + return this._transport._htmlForXfa; + } + getPage(pageNumber) { + return this._transport.getPage(pageNumber); + } + getPageIndex(ref) { + return this._transport.getPageIndex(ref); + } + getDestinations() { + return this._transport.getDestinations(); + } + getDestination(id) { + return this._transport.getDestination(id); + } + getPageLabels() { + return this._transport.getPageLabels(); + } + getPageLayout() { + return this._transport.getPageLayout(); + } + getPageMode() { + return this._transport.getPageMode(); + } + getViewerPreferences() { + return this._transport.getViewerPreferences(); + } + getOpenAction() { + return this._transport.getOpenAction(); + } + getAttachments() { + return this._transport.getAttachments(); + } + getAnnotationsByType(types, pageIndexesToSkip) { + return this._transport.getAnnotationsByType(types, pageIndexesToSkip); + } + getJSActions() { + return this._transport.getDocJSActions(); + } + getOutline() { + return this._transport.getOutline(); + } + getOptionalContentConfig({ + intent = "display" + } = {}) { + const { + renderingIntent + } = this._transport.getRenderingIntent(intent); + return this._transport.getOptionalContentConfig(renderingIntent); + } + getPermissions() { + return this._transport.getPermissions(); + } + getMetadata() { + return this._transport.getMetadata(); + } + getMarkInfo() { + return this._transport.getMarkInfo(); + } + getData() { + return this._transport.getData(); + } + saveDocument() { + return this._transport.saveDocument(); + } + getDownloadInfo() { + return this._transport.downloadInfoCapability.promise; + } + cleanup(keepLoadedFonts = false) { + return this._transport.startCleanup(keepLoadedFonts || this.isPureXfa); + } + destroy() { + return this.loadingTask.destroy(); + } + cachedPageNumber(ref) { + return this._transport.cachedPageNumber(ref); + } + get loadingParams() { + return this._transport.loadingParams; + } + get loadingTask() { + return this._transport.loadingTask; + } + getFieldObjects() { + return this._transport.getFieldObjects(); + } + hasJSActions() { + return this._transport.hasJSActions(); + } + getCalculationOrderIds() { + return this._transport.getCalculationOrderIds(); + } +} +class PDFPageProxy { + #pendingCleanup = false; + constructor(pageIndex, pageInfo, transport, pdfBug = false) { + this._pageIndex = pageIndex; + this._pageInfo = pageInfo; + this._transport = transport; + this._stats = pdfBug ? new StatTimer() : null; + this._pdfBug = pdfBug; + this.commonObjs = transport.commonObjs; + this.objs = new PDFObjects(); + this._intentStates = /* @__PURE__ */ new Map(); + this.destroyed = false; + this.recordedBBoxes = null; + } + get pageNumber() { + return this._pageIndex + 1; + } + get rotate() { + return this._pageInfo.rotate; + } + get ref() { + return this._pageInfo.ref; + } + get userUnit() { + return this._pageInfo.userUnit; + } + get view() { + return this._pageInfo.view; + } + getViewport({ + scale, + rotation = this.rotate, + offsetX = 0, + offsetY = 0, + dontFlip = false + } = {}) { + return new PageViewport({ + viewBox: this.view, + userUnit: this.userUnit, + scale, + rotation, + offsetX, + offsetY, + dontFlip + }); + } + getAnnotations({ + intent = "display" + } = {}) { + const { + renderingIntent + } = this._transport.getRenderingIntent(intent); + return this._transport.getAnnotations(this._pageIndex, renderingIntent); + } + getJSActions() { + return this._transport.getPageJSActions(this._pageIndex); + } + get filterFactory() { + return this._transport.filterFactory; + } + get isPureXfa() { + return shadow(this, "isPureXfa", !!this._transport._htmlForXfa); + } + async getXfa() { + return this._transport._htmlForXfa?.children[this._pageIndex] || null; + } + render({ + canvasContext, + canvas = canvasContext.canvas, + viewport, + intent = "display", + annotationMode = AnnotationMode.ENABLE, + transform = null, + background = null, + optionalContentConfigPromise = null, + annotationCanvasMap = null, + pageColors = null, + printAnnotationStorage = null, + isEditing = false, + recordOperations = false, + operationsFilter = null + }) { + this._stats?.time("Overall"); + const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage, isEditing); + const { + renderingIntent, + cacheKey + } = intentArgs; + this.#pendingCleanup = false; + optionalContentConfigPromise ||= this._transport.getOptionalContentConfig(renderingIntent); + let intentState = this._intentStates.get(cacheKey); + if (!intentState) { + intentState = /* @__PURE__ */ Object.create(null); + this._intentStates.set(cacheKey, intentState); + } + if (intentState.streamReaderCancelTimeout) { + clearTimeout(intentState.streamReaderCancelTimeout); + intentState.streamReaderCancelTimeout = null; + } + const intentPrint = !!(renderingIntent & RenderingIntentFlag.PRINT); + if (!intentState.displayReadyCapability) { + intentState.displayReadyCapability = Promise.withResolvers(); + intentState.operatorList = { + fnArray: [], + argsArray: [], + lastChunk: false, + separateAnnots: null + }; + this._stats?.time("Page Request"); + this._pumpOperatorList(intentArgs); + } + const recordForDebugger = Boolean(this._pdfBug && globalThis.StepperManager?.enabled); + const shouldRecordOperations = !this.recordedBBoxes && (recordOperations || recordForDebugger); + const complete = (error) => { + intentState.renderTasks.delete(internalRenderTask); + if (shouldRecordOperations) { + const recordedBBoxes = internalRenderTask.gfx?.dependencyTracker.take(); + if (recordedBBoxes) { + if (internalRenderTask.stepper) { + internalRenderTask.stepper.setOperatorBBoxes(recordedBBoxes, internalRenderTask.gfx.dependencyTracker.takeDebugMetadata()); + } + if (recordOperations) { + this.recordedBBoxes = recordedBBoxes; + } + } + } + if (intentPrint) { + this.#pendingCleanup = true; + } + this.#tryCleanup(); + if (error) { + internalRenderTask.capability.reject(error); + this._abortOperatorList({ + intentState, + reason: error instanceof Error ? error : new Error(error) + }); + } else { + internalRenderTask.capability.resolve(); + } + if (this._stats) { + this._stats.timeEnd("Rendering"); + this._stats.timeEnd("Overall"); + if (globalThis.Stats?.enabled) { + globalThis.Stats.add(this.pageNumber, this._stats); + } + } + }; + const internalRenderTask = new InternalRenderTask({ + callback: complete, + params: { + canvas, + canvasContext, + dependencyTracker: shouldRecordOperations ? new CanvasDependencyTracker(canvas, intentState.operatorList.length, recordForDebugger) : null, + viewport, + transform, + background + }, + objs: this.objs, + commonObjs: this.commonObjs, + annotationCanvasMap, + operatorList: intentState.operatorList, + pageIndex: this._pageIndex, + canvasFactory: this._transport.canvasFactory, + filterFactory: this._transport.filterFactory, + useRequestAnimationFrame: !intentPrint, + pdfBug: this._pdfBug, + pageColors, + enableHWA: this._transport.enableHWA, + operationsFilter + }); + (intentState.renderTasks ||= /* @__PURE__ */ new Set()).add(internalRenderTask); + const renderTask = internalRenderTask.task; + Promise.all([intentState.displayReadyCapability.promise, optionalContentConfigPromise]).then(([transparency, optionalContentConfig]) => { + if (this.destroyed) { + complete(); + return; + } + this._stats?.time("Rendering"); + if (!(optionalContentConfig.renderingIntent & renderingIntent)) { + throw new Error("Must use the same `intent`-argument when calling the `PDFPageProxy.render` and `PDFDocumentProxy.getOptionalContentConfig` methods."); + } + internalRenderTask.initializeGraphics({ + transparency, + optionalContentConfig + }); + internalRenderTask.operatorListChanged(); + }).catch(complete); + return renderTask; + } + getOperatorList({ + intent = "display", + annotationMode = AnnotationMode.ENABLE, + printAnnotationStorage = null, + isEditing = false + } = {}) { + function operatorListChanged() { + if (intentState.operatorList.lastChunk) { + intentState.opListReadCapability.resolve(intentState.operatorList); + intentState.renderTasks.delete(opListTask); + } + } + const intentArgs = this._transport.getRenderingIntent(intent, annotationMode, printAnnotationStorage, isEditing, true); + let intentState = this._intentStates.get(intentArgs.cacheKey); + if (!intentState) { + intentState = /* @__PURE__ */ Object.create(null); + this._intentStates.set(intentArgs.cacheKey, intentState); + } + let opListTask; + if (!intentState.opListReadCapability) { + opListTask = /* @__PURE__ */ Object.create(null); + opListTask.operatorListChanged = operatorListChanged; + intentState.opListReadCapability = Promise.withResolvers(); + (intentState.renderTasks ||= /* @__PURE__ */ new Set()).add(opListTask); + intentState.operatorList = { + fnArray: [], + argsArray: [], + lastChunk: false, + separateAnnots: null + }; + this._stats?.time("Page Request"); + this._pumpOperatorList(intentArgs); + } + return intentState.opListReadCapability.promise; + } + streamTextContent({ + includeMarkedContent = false, + disableNormalization = false + } = {}) { + const TEXT_CONTENT_CHUNK_SIZE = 100; + return this._transport.messageHandler.sendWithStream("GetTextContent", { + pageIndex: this._pageIndex, + includeMarkedContent: includeMarkedContent === true, + disableNormalization: disableNormalization === true + }, { + highWaterMark: TEXT_CONTENT_CHUNK_SIZE, + size(textContent) { + return textContent.items.length; + } + }); + } + getTextContent(params = {}) { + if (this._transport._htmlForXfa) { + return this.getXfa().then((xfa) => XfaText.textContent(xfa)); + } + const readableStream = this.streamTextContent(params); + return new Promise(function(resolve, reject) { + function pump() { + reader.read().then(function({ + value, + done + }) { + if (done) { + resolve(textContent); + return; + } + textContent.lang ??= value.lang; + Object.assign(textContent.styles, value.styles); + textContent.items.push(...value.items); + pump(); + }, reject); + } + const reader = readableStream.getReader(); + const textContent = { + items: [], + styles: /* @__PURE__ */ Object.create(null), + lang: null + }; + pump(); + }); + } + getStructTree() { + return this._transport.getStructTree(this._pageIndex); + } + _destroy() { + this.destroyed = true; + const waitOn = []; + for (const intentState of this._intentStates.values()) { + this._abortOperatorList({ + intentState, + reason: new Error("Page was destroyed."), + force: true + }); + if (intentState.opListReadCapability) { + continue; + } + for (const internalRenderTask of intentState.renderTasks) { + waitOn.push(internalRenderTask.completed); + internalRenderTask.cancel(); + } + } + this.objs.clear(); + this.#pendingCleanup = false; + return Promise.all(waitOn); + } + cleanup(resetStats = false) { + this.#pendingCleanup = true; + const success = this.#tryCleanup(); + if (resetStats && success) { + this._stats &&= new StatTimer(); + } + return success; + } + #tryCleanup() { + if (!this.#pendingCleanup || this.destroyed) { + return false; + } + for (const { + renderTasks, + operatorList + } of this._intentStates.values()) { + if (renderTasks.size > 0 || !operatorList.lastChunk) { + return false; + } + } + this._intentStates.clear(); + this.objs.clear(); + this.#pendingCleanup = false; + return true; + } + _startRenderPage(transparency, cacheKey) { + const intentState = this._intentStates.get(cacheKey); + if (!intentState) { + return; + } + this._stats?.timeEnd("Page Request"); + intentState.displayReadyCapability?.resolve(transparency); + } + _renderPageChunk(operatorListChunk, intentState) { + for (let i = 0, ii = operatorListChunk.length; i < ii; i++) { + intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]); + intentState.operatorList.argsArray.push(operatorListChunk.argsArray[i]); + } + intentState.operatorList.lastChunk = operatorListChunk.lastChunk; + intentState.operatorList.separateAnnots = operatorListChunk.separateAnnots; + for (const internalRenderTask of intentState.renderTasks) { + internalRenderTask.operatorListChanged(); + } + if (operatorListChunk.lastChunk) { + this.#tryCleanup(); + } + } + _pumpOperatorList({ + renderingIntent, + cacheKey, + annotationStorageSerializable, + modifiedIds + }) { + const { + map, + transfer + } = annotationStorageSerializable; + const readableStream = this._transport.messageHandler.sendWithStream("GetOperatorList", { + pageIndex: this._pageIndex, + intent: renderingIntent, + cacheKey, + annotationStorage: map, + modifiedIds + }, transfer); + const reader = readableStream.getReader(); + const intentState = this._intentStates.get(cacheKey); + intentState.streamReader = reader; + const pump = () => { + reader.read().then(({ + value, + done + }) => { + if (done) { + intentState.streamReader = null; + return; + } + if (this._transport.destroyed) { + return; + } + this._renderPageChunk(value, intentState); + pump(); + }, (reason) => { + intentState.streamReader = null; + if (this._transport.destroyed) { + return; + } + if (intentState.operatorList) { + intentState.operatorList.lastChunk = true; + for (const internalRenderTask of intentState.renderTasks) { + internalRenderTask.operatorListChanged(); + } + this.#tryCleanup(); + } + if (intentState.displayReadyCapability) { + intentState.displayReadyCapability.reject(reason); + } else if (intentState.opListReadCapability) { + intentState.opListReadCapability.reject(reason); + } else { + throw reason; + } + }); + }; + pump(); + } + _abortOperatorList({ + intentState, + reason, + force = false + }) { + if (!intentState.streamReader) { + return; + } + if (intentState.streamReaderCancelTimeout) { + clearTimeout(intentState.streamReaderCancelTimeout); + intentState.streamReaderCancelTimeout = null; + } + if (!force) { + if (intentState.renderTasks.size > 0) { + return; + } + if (reason instanceof RenderingCancelledException) { + let delay = RENDERING_CANCELLED_TIMEOUT; + if (reason.extraDelay > 0 && reason.extraDelay < 1e3) { + delay += reason.extraDelay; + } + intentState.streamReaderCancelTimeout = setTimeout(() => { + intentState.streamReaderCancelTimeout = null; + this._abortOperatorList({ + intentState, + reason, + force: true + }); + }, delay); + return; + } + } + intentState.streamReader.cancel(new AbortException(reason.message)).catch(() => { + }); + intentState.streamReader = null; + if (this._transport.destroyed) { + return; + } + for (const [curCacheKey, curIntentState] of this._intentStates) { + if (curIntentState === intentState) { + this._intentStates.delete(curCacheKey); + break; + } + } + this.cleanup(); + } + get stats() { + return this._stats; + } +} +const _PDFWorker = class _PDFWorker { + constructor({ + name = null, + port = null, + verbosity: verbosity2 = getVerbosityLevel() + } = {}) { + __privateAdd(this, _PDFWorker_instances); + __privateAdd(this, _capability, Promise.withResolvers()); + __privateAdd(this, _messageHandler, null); + __privateAdd(this, _port, null); + __privateAdd(this, _webWorker, null); + this.name = name; + this.destroyed = false; + this.verbosity = verbosity2; + if (port) { + if (__privateGet(_PDFWorker, _workerPorts).has(port)) { + throw new Error("Cannot use more than one PDFWorker per port."); + } + __privateGet(_PDFWorker, _workerPorts).set(port, this); + __privateMethod(this, _PDFWorker_instances, initializeFromPort_fn).call(this, port); + } else { + __privateMethod(this, _PDFWorker_instances, initialize_fn).call(this); + } + } + get promise() { + return __privateGet(this, _capability).promise; + } + get port() { + return __privateGet(this, _port); + } + get messageHandler() { + return __privateGet(this, _messageHandler); + } + destroy() { + this.destroyed = true; + __privateGet(this, _webWorker)?.terminate(); + __privateSet(this, _webWorker, null); + __privateGet(_PDFWorker, _workerPorts).delete(__privateGet(this, _port)); + __privateSet(this, _port, null); + __privateGet(this, _messageHandler)?.destroy(); + __privateSet(this, _messageHandler, null); + } + static create(params) { + const cachedPort = __privateGet(this, _workerPorts).get(params?.port); + if (cachedPort) { + if (cachedPort._pendingDestroy) { + throw new Error("PDFWorker.create - the worker is being destroyed.\nPlease remember to await `PDFDocumentLoadingTask.destroy()`-calls."); + } + return cachedPort; + } + return new _PDFWorker(params); + } + static get workerSrc() { + if (GlobalWorkerOptions.workerSrc) { + return GlobalWorkerOptions.workerSrc; + } + throw new Error('No "GlobalWorkerOptions.workerSrc" specified.'); + } + static get _setupFakeWorkerGlobal() { + const loader = async () => { + if (__privateGet(this, _PDFWorker_static, mainThreadWorkerMessageHandler_get)) { + return __privateGet(this, _PDFWorker_static, mainThreadWorkerMessageHandler_get); + } + const worker = await import( + /*webpackIgnore: true*/ + /*@vite-ignore*/ + this.workerSrc + ); + return worker.WorkerMessageHandler; + }; + return shadow(this, "_setupFakeWorkerGlobal", loader()); + } +}; +_capability = new WeakMap(); +_messageHandler = new WeakMap(); +_port = new WeakMap(); +_webWorker = new WeakMap(); +_fakeWorkerId = new WeakMap(); +_isWorkerDisabled = new WeakMap(); +_workerPorts = new WeakMap(); +_PDFWorker_instances = new WeakSet(); +resolve_fn = function() { + __privateGet(this, _capability).resolve(); + __privateGet(this, _messageHandler).send("configure", { + verbosity: this.verbosity + }); +}; +initializeFromPort_fn = function(port) { + __privateSet(this, _port, port); + __privateSet(this, _messageHandler, new MessageHandler("main", "worker", port)); + __privateGet(this, _messageHandler).on("ready", () => { + }); + __privateMethod(this, _PDFWorker_instances, resolve_fn).call(this); +}; +initialize_fn = function() { + if (__privateGet(_PDFWorker, _isWorkerDisabled) || __privateGet(_PDFWorker, _PDFWorker_static, mainThreadWorkerMessageHandler_get)) { + __privateMethod(this, _PDFWorker_instances, setupFakeWorker_fn).call(this); + return; + } + let { + workerSrc + } = _PDFWorker; + try { + if (!_PDFWorker._isSameOrigin(window.location, workerSrc)) { + workerSrc = _PDFWorker._createCDNWrapper(new URL(workerSrc, window.location).href); + } + const worker = new Worker(workerSrc, { + type: "module" + }); + const messageHandler = new MessageHandler("main", "worker", worker); + const terminateEarly = () => { + ac.abort(); + messageHandler.destroy(); + worker.terminate(); + if (this.destroyed) { + __privateGet(this, _capability).reject(new Error("Worker was destroyed")); + } else { + __privateMethod(this, _PDFWorker_instances, setupFakeWorker_fn).call(this); + } + }; + const ac = new AbortController(); + worker.addEventListener("error", () => { + if (!__privateGet(this, _webWorker)) { + terminateEarly(); + } + }, { + signal: ac.signal + }); + messageHandler.on("test", (data) => { + ac.abort(); + if (this.destroyed || !data) { + terminateEarly(); + return; + } + __privateSet(this, _messageHandler, messageHandler); + __privateSet(this, _port, worker); + __privateSet(this, _webWorker, worker); + __privateMethod(this, _PDFWorker_instances, resolve_fn).call(this); + }); + messageHandler.on("ready", (data) => { + ac.abort(); + if (this.destroyed) { + terminateEarly(); + return; + } + try { + sendTest(); + } catch { + __privateMethod(this, _PDFWorker_instances, setupFakeWorker_fn).call(this); + } + }); + const sendTest = () => { + const testObj = new Uint8Array(); + messageHandler.send("test", testObj, [testObj.buffer]); + }; + sendTest(); + return; + } catch { + info("The worker has been disabled."); + } + __privateMethod(this, _PDFWorker_instances, setupFakeWorker_fn).call(this); +}; +setupFakeWorker_fn = function() { + if (!__privateGet(_PDFWorker, _isWorkerDisabled)) { + warn("Setting up fake worker."); + __privateSet(_PDFWorker, _isWorkerDisabled, true); + } + _PDFWorker._setupFakeWorkerGlobal.then((WorkerMessageHandler) => { + if (this.destroyed) { + __privateGet(this, _capability).reject(new Error("Worker was destroyed")); + return; + } + const port = new LoopbackPort(); + __privateSet(this, _port, port); + const id = `fake${__privateWrapper(_PDFWorker, _fakeWorkerId)._++}`; + const workerHandler = new MessageHandler(id + "_worker", id, port); + WorkerMessageHandler.setup(workerHandler, port); + __privateSet(this, _messageHandler, new MessageHandler(id, id + "_worker", port)); + __privateMethod(this, _PDFWorker_instances, resolve_fn).call(this); + }).catch((reason) => { + __privateGet(this, _capability).reject(new Error(`Setting up fake worker failed: "${reason.message}".`)); + }); +}; +_PDFWorker_static = new WeakSet(); +mainThreadWorkerMessageHandler_get = function() { + try { + return globalThis.pdfjsWorker?.WorkerMessageHandler || null; + } catch { + return null; + } +}; +__privateAdd(_PDFWorker, _PDFWorker_static); +__privateAdd(_PDFWorker, _fakeWorkerId, 0); +__privateAdd(_PDFWorker, _isWorkerDisabled, false); +__privateAdd(_PDFWorker, _workerPorts, /* @__PURE__ */ new WeakMap()); +(() => { + if (isNodeJS) { + __privateSet(_PDFWorker, _isWorkerDisabled, true); + GlobalWorkerOptions.workerSrc ||= "./pdf.worker.mjs"; + } + _PDFWorker._isSameOrigin = (baseUrl, otherUrl) => { + const base = URL.parse(baseUrl); + if (!base?.origin || base.origin === "null") { + return false; + } + const other = new URL(otherUrl, base); + return base.origin === other.origin; + }; + _PDFWorker._createCDNWrapper = (url) => { + const wrapper = `await import("${url}");`; + return URL.createObjectURL(new Blob([wrapper], { + type: "text/javascript" + })); + }; + _PDFWorker.fromPort = (params) => { + deprecated("`PDFWorker.fromPort` - please use `PDFWorker.create` instead."); + if (!params?.port) { + throw new Error("PDFWorker.fromPort - invalid method signature."); + } + return _PDFWorker.create(params); + }; +})(); +let PDFWorker = _PDFWorker; +class WorkerTransport { + #methodPromises = /* @__PURE__ */ new Map(); + #pageCache = /* @__PURE__ */ new Map(); + #pagePromises = /* @__PURE__ */ new Map(); + #pageRefCache = /* @__PURE__ */ new Map(); + #passwordCapability = null; + constructor(messageHandler, loadingTask, networkStream, params, factory, enableHWA) { + this.messageHandler = messageHandler; + this.loadingTask = loadingTask; + this.commonObjs = new PDFObjects(); + this.fontLoader = new FontLoader({ + ownerDocument: params.ownerDocument, + styleElement: params.styleElement + }); + this.loadingParams = params.loadingParams; + this._params = params; + this.canvasFactory = factory.canvasFactory; + this.filterFactory = factory.filterFactory; + this.cMapReaderFactory = factory.cMapReaderFactory; + this.standardFontDataFactory = factory.standardFontDataFactory; + this.wasmFactory = factory.wasmFactory; + this.destroyed = false; + this.destroyCapability = null; + this._networkStream = networkStream; + this._fullReader = null; + this._lastProgress = null; + this.downloadInfoCapability = Promise.withResolvers(); + this.enableHWA = enableHWA; + this.setupMessageHandler(); + } + #cacheSimpleMethod(name, data = null) { + const cachedPromise = this.#methodPromises.get(name); + if (cachedPromise) { + return cachedPromise; + } + const promise = this.messageHandler.sendWithPromise(name, data); + this.#methodPromises.set(name, promise); + return promise; + } + get annotationStorage() { + return shadow(this, "annotationStorage", new AnnotationStorage()); + } + getRenderingIntent(intent, annotationMode = AnnotationMode.ENABLE, printAnnotationStorage = null, isEditing = false, isOpList = false) { + let renderingIntent = RenderingIntentFlag.DISPLAY; + let annotationStorageSerializable = SerializableEmpty; + switch (intent) { + case "any": + renderingIntent = RenderingIntentFlag.ANY; + break; + case "display": + break; + case "print": + renderingIntent = RenderingIntentFlag.PRINT; + break; + default: + warn(`getRenderingIntent - invalid intent: ${intent}`); + } + const annotationStorage = renderingIntent & RenderingIntentFlag.PRINT && printAnnotationStorage instanceof PrintAnnotationStorage ? printAnnotationStorage : this.annotationStorage; + switch (annotationMode) { + case AnnotationMode.DISABLE: + renderingIntent += RenderingIntentFlag.ANNOTATIONS_DISABLE; + break; + case AnnotationMode.ENABLE: + break; + case AnnotationMode.ENABLE_FORMS: + renderingIntent += RenderingIntentFlag.ANNOTATIONS_FORMS; + break; + case AnnotationMode.ENABLE_STORAGE: + renderingIntent += RenderingIntentFlag.ANNOTATIONS_STORAGE; + annotationStorageSerializable = annotationStorage.serializable; + break; + default: + warn(`getRenderingIntent - invalid annotationMode: ${annotationMode}`); + } + if (isEditing) { + renderingIntent += RenderingIntentFlag.IS_EDITING; + } + if (isOpList) { + renderingIntent += RenderingIntentFlag.OPLIST; + } + const { + ids: modifiedIds, + hash: modifiedIdsHash + } = annotationStorage.modifiedIds; + const cacheKeyBuf = [renderingIntent, annotationStorageSerializable.hash, modifiedIdsHash]; + return { + renderingIntent, + cacheKey: cacheKeyBuf.join("_"), + annotationStorageSerializable, + modifiedIds + }; + } + destroy() { + if (this.destroyCapability) { + return this.destroyCapability.promise; + } + this.destroyed = true; + this.destroyCapability = Promise.withResolvers(); + this.#passwordCapability?.reject(new Error("Worker was destroyed during onPassword callback")); + const waitOn = []; + for (const page of this.#pageCache.values()) { + waitOn.push(page._destroy()); + } + this.#pageCache.clear(); + this.#pagePromises.clear(); + this.#pageRefCache.clear(); + if (this.hasOwnProperty("annotationStorage")) { + this.annotationStorage.resetModified(); + } + const terminated = this.messageHandler.sendWithPromise("Terminate", null); + waitOn.push(terminated); + Promise.all(waitOn).then(() => { + this.commonObjs.clear(); + this.fontLoader.clear(); + this.#methodPromises.clear(); + this.filterFactory.destroy(); + TextLayer.cleanup(); + this._networkStream?.cancelAllRequests(new AbortException("Worker was terminated.")); + this.messageHandler?.destroy(); + this.messageHandler = null; + this.destroyCapability.resolve(); + }, this.destroyCapability.reject); + return this.destroyCapability.promise; + } + setupMessageHandler() { + const { + messageHandler, + loadingTask + } = this; + messageHandler.on("GetReader", (data, sink) => { + assert(this._networkStream, "GetReader - no `IPDFStream` instance available."); + this._fullReader = this._networkStream.getFullReader(); + this._fullReader.onProgress = (evt) => { + this._lastProgress = { + loaded: evt.loaded, + total: evt.total + }; + }; + sink.onPull = () => { + this._fullReader.read().then(function({ + value, + done + }) { + if (done) { + sink.close(); + return; + } + assert(value instanceof ArrayBuffer, "GetReader - expected an ArrayBuffer."); + sink.enqueue(new Uint8Array(value), 1, [value]); + }).catch((reason) => { + sink.error(reason); + }); + }; + sink.onCancel = (reason) => { + this._fullReader.cancel(reason); + sink.ready.catch((readyReason) => { + if (this.destroyed) { + return; + } + throw readyReason; + }); + }; + }); + messageHandler.on("ReaderHeadersReady", async (data) => { + await this._fullReader.headersReady; + const { + isStreamingSupported, + isRangeSupported, + contentLength + } = this._fullReader; + if (!isStreamingSupported || !isRangeSupported) { + if (this._lastProgress) { + loadingTask.onProgress?.(this._lastProgress); + } + this._fullReader.onProgress = (evt) => { + loadingTask.onProgress?.({ + loaded: evt.loaded, + total: evt.total + }); + }; + } + return { + isStreamingSupported, + isRangeSupported, + contentLength + }; + }); + messageHandler.on("GetRangeReader", (data, sink) => { + assert(this._networkStream, "GetRangeReader - no `IPDFStream` instance available."); + const rangeReader = this._networkStream.getRangeReader(data.begin, data.end); + if (!rangeReader) { + sink.close(); + return; + } + sink.onPull = () => { + rangeReader.read().then(function({ + value, + done + }) { + if (done) { + sink.close(); + return; + } + assert(value instanceof ArrayBuffer, "GetRangeReader - expected an ArrayBuffer."); + sink.enqueue(new Uint8Array(value), 1, [value]); + }).catch((reason) => { + sink.error(reason); + }); + }; + sink.onCancel = (reason) => { + rangeReader.cancel(reason); + sink.ready.catch((readyReason) => { + if (this.destroyed) { + return; + } + throw readyReason; + }); + }; + }); + messageHandler.on("GetDoc", ({ + pdfInfo + }) => { + this._numPages = pdfInfo.numPages; + this._htmlForXfa = pdfInfo.htmlForXfa; + delete pdfInfo.htmlForXfa; + loadingTask._capability.resolve(new PDFDocumentProxy(pdfInfo, this)); + }); + messageHandler.on("DocException", (ex) => { + loadingTask._capability.reject(wrapReason(ex)); + }); + messageHandler.on("PasswordRequest", (ex) => { + this.#passwordCapability = Promise.withResolvers(); + try { + if (!loadingTask.onPassword) { + throw wrapReason(ex); + } + const updatePassword = (password) => { + if (password instanceof Error) { + this.#passwordCapability.reject(password); + } else { + this.#passwordCapability.resolve({ + password + }); + } + }; + loadingTask.onPassword(updatePassword, ex.code); + } catch (err) { + this.#passwordCapability.reject(err); + } + return this.#passwordCapability.promise; + }); + messageHandler.on("DataLoaded", (data) => { + loadingTask.onProgress?.({ + loaded: data.length, + total: data.length + }); + this.downloadInfoCapability.resolve(data); + }); + messageHandler.on("StartRenderPage", (data) => { + if (this.destroyed) { + return; + } + const page = this.#pageCache.get(data.pageIndex); + page._startRenderPage(data.transparency, data.cacheKey); + }); + messageHandler.on("commonobj", ([id, type, exportedData]) => { + if (this.destroyed) { + return null; + } + if (this.commonObjs.has(id)) { + return null; + } + switch (type) { + case "Font": + if ("error" in exportedData) { + const exportedError = exportedData.error; + warn(`Error during font loading: ${exportedError}`); + this.commonObjs.resolve(id, exportedError); + break; + } + const fontData = new FontInfo(exportedData); + const inspectFont = this._params.pdfBug && globalThis.FontInspector?.enabled ? (font2, url) => globalThis.FontInspector.fontAdded(font2, url) : null; + const font = new FontFaceObject(fontData, inspectFont, exportedData.extra, exportedData.charProcOperatorList); + this.fontLoader.bind(font).catch(() => messageHandler.sendWithPromise("FontFallback", { + id + })).finally(() => { + if (!font.fontExtraProperties && font.data) { + font.clearData(); + } + this.commonObjs.resolve(id, font); + }); + break; + case "CopyLocalImage": + const { + imageRef + } = exportedData; + assert(imageRef, "The imageRef must be defined."); + for (const pageProxy of this.#pageCache.values()) { + for (const [, data] of pageProxy.objs) { + if (data?.ref !== imageRef) { + continue; + } + if (!data.dataLen) { + return null; + } + this.commonObjs.resolve(id, structuredClone(data)); + return data.dataLen; + } + } + break; + case "FontPath": + case "Image": + case "Pattern": + this.commonObjs.resolve(id, exportedData); + break; + default: + throw new Error(`Got unknown common object type ${type}`); + } + return null; + }); + messageHandler.on("obj", ([id, pageIndex, type, imageData]) => { + if (this.destroyed) { + return; + } + const pageProxy = this.#pageCache.get(pageIndex); + if (pageProxy.objs.has(id)) { + return; + } + if (pageProxy._intentStates.size === 0) { + imageData?.bitmap?.close(); + return; + } + switch (type) { + case "Image": + case "Pattern": + pageProxy.objs.resolve(id, imageData); + break; + default: + throw new Error(`Got unknown object type ${type}`); + } + }); + messageHandler.on("DocProgress", (data) => { + if (this.destroyed) { + return; + } + loadingTask.onProgress?.({ + loaded: data.loaded, + total: data.total + }); + }); + messageHandler.on("FetchBinaryData", async (data) => { + if (this.destroyed) { + throw new Error("Worker was destroyed."); + } + const factory = this[data.type]; + if (!factory) { + throw new Error(`${data.type} not initialized, see the \`useWorkerFetch\` parameter.`); + } + return factory.fetch(data); + }); + } + getData() { + return this.messageHandler.sendWithPromise("GetData", null); + } + saveDocument() { + if (this.annotationStorage.size <= 0) { + warn("saveDocument called while `annotationStorage` is empty, please use the getData-method instead."); + } + const { + map, + transfer + } = this.annotationStorage.serializable; + return this.messageHandler.sendWithPromise("SaveDocument", { + isPureXfa: !!this._htmlForXfa, + numPages: this._numPages, + annotationStorage: map, + filename: this._fullReader?.filename ?? null + }, transfer).finally(() => { + this.annotationStorage.resetModified(); + }); + } + getPage(pageNumber) { + if (!Number.isInteger(pageNumber) || pageNumber <= 0 || pageNumber > this._numPages) { + return Promise.reject(new Error("Invalid page request.")); + } + const pageIndex = pageNumber - 1, cachedPromise = this.#pagePromises.get(pageIndex); + if (cachedPromise) { + return cachedPromise; + } + const promise = this.messageHandler.sendWithPromise("GetPage", { + pageIndex + }).then((pageInfo) => { + if (this.destroyed) { + throw new Error("Transport destroyed"); + } + if (pageInfo.refStr) { + this.#pageRefCache.set(pageInfo.refStr, pageNumber); + } + const page = new PDFPageProxy(pageIndex, pageInfo, this, this._params.pdfBug); + this.#pageCache.set(pageIndex, page); + return page; + }); + this.#pagePromises.set(pageIndex, promise); + return promise; + } + getPageIndex(ref) { + if (!isRefProxy(ref)) { + return Promise.reject(new Error("Invalid pageIndex request.")); + } + return this.messageHandler.sendWithPromise("GetPageIndex", { + num: ref.num, + gen: ref.gen + }); + } + getAnnotations(pageIndex, intent) { + return this.messageHandler.sendWithPromise("GetAnnotations", { + pageIndex, + intent + }); + } + getFieldObjects() { + return this.#cacheSimpleMethod("GetFieldObjects"); + } + hasJSActions() { + return this.#cacheSimpleMethod("HasJSActions"); + } + getCalculationOrderIds() { + return this.messageHandler.sendWithPromise("GetCalculationOrderIds", null); + } + getDestinations() { + return this.messageHandler.sendWithPromise("GetDestinations", null); + } + getDestination(id) { + if (typeof id !== "string") { + return Promise.reject(new Error("Invalid destination request.")); + } + return this.messageHandler.sendWithPromise("GetDestination", { + id + }); + } + getPageLabels() { + return this.messageHandler.sendWithPromise("GetPageLabels", null); + } + getPageLayout() { + return this.messageHandler.sendWithPromise("GetPageLayout", null); + } + getPageMode() { + return this.messageHandler.sendWithPromise("GetPageMode", null); + } + getViewerPreferences() { + return this.messageHandler.sendWithPromise("GetViewerPreferences", null); + } + getOpenAction() { + return this.messageHandler.sendWithPromise("GetOpenAction", null); + } + getAttachments() { + return this.messageHandler.sendWithPromise("GetAttachments", null); + } + getAnnotationsByType(types, pageIndexesToSkip) { + return this.messageHandler.sendWithPromise("GetAnnotationsByType", { + types, + pageIndexesToSkip + }); + } + getDocJSActions() { + return this.#cacheSimpleMethod("GetDocJSActions"); + } + getPageJSActions(pageIndex) { + return this.messageHandler.sendWithPromise("GetPageJSActions", { + pageIndex + }); + } + getStructTree(pageIndex) { + return this.messageHandler.sendWithPromise("GetStructTree", { + pageIndex + }); + } + getOutline() { + return this.messageHandler.sendWithPromise("GetOutline", null); + } + getOptionalContentConfig(renderingIntent) { + return this.#cacheSimpleMethod("GetOptionalContentConfig").then((data) => new OptionalContentConfig(data, renderingIntent)); + } + getPermissions() { + return this.messageHandler.sendWithPromise("GetPermissions", null); + } + getMetadata() { + const name = "GetMetadata", cachedPromise = this.#methodPromises.get(name); + if (cachedPromise) { + return cachedPromise; + } + const promise = this.messageHandler.sendWithPromise(name, null).then((results) => ({ + info: results[0], + metadata: results[1] ? new Metadata(results[1]) : null, + contentDispositionFilename: this._fullReader?.filename ?? null, + contentLength: this._fullReader?.contentLength ?? null + })); + this.#methodPromises.set(name, promise); + return promise; + } + getMarkInfo() { + return this.messageHandler.sendWithPromise("GetMarkInfo", null); + } + async startCleanup(keepLoadedFonts = false) { + if (this.destroyed) { + return; + } + await this.messageHandler.sendWithPromise("Cleanup", null); + for (const page of this.#pageCache.values()) { + const cleanupSuccessful = page.cleanup(); + if (!cleanupSuccessful) { + throw new Error(`startCleanup: Page ${page.pageNumber} is currently rendering.`); + } + } + this.commonObjs.clear(); + if (!keepLoadedFonts) { + this.fontLoader.clear(); + } + this.#methodPromises.clear(); + this.filterFactory.destroy(true); + TextLayer.cleanup(); + } + cachedPageNumber(ref) { + if (!isRefProxy(ref)) { + return null; + } + const refStr = ref.gen === 0 ? `${ref.num}R` : `${ref.num}R${ref.gen}`; + return this.#pageRefCache.get(refStr) ?? null; + } +} +class RenderTask { + #internalRenderTask = null; + onContinue = null; + onError = null; + constructor(internalRenderTask) { + this.#internalRenderTask = internalRenderTask; + } + get promise() { + return this.#internalRenderTask.capability.promise; + } + cancel(extraDelay = 0) { + this.#internalRenderTask.cancel(null, extraDelay); + } + get separateAnnots() { + const { + separateAnnots + } = this.#internalRenderTask.operatorList; + if (!separateAnnots) { + return false; + } + const { + annotationCanvasMap + } = this.#internalRenderTask; + return separateAnnots.form || separateAnnots.canvas && annotationCanvasMap?.size > 0; + } +} +class InternalRenderTask { + #rAF = null; + static #canvasInUse = /* @__PURE__ */ new WeakSet(); + constructor({ + callback, + params, + objs, + commonObjs, + annotationCanvasMap, + operatorList, + pageIndex, + canvasFactory, + filterFactory, + useRequestAnimationFrame = false, + pdfBug = false, + pageColors = null, + enableHWA = false, + operationsFilter = null + }) { + this.callback = callback; + this.params = params; + this.objs = objs; + this.commonObjs = commonObjs; + this.annotationCanvasMap = annotationCanvasMap; + this.operatorListIdx = null; + this.operatorList = operatorList; + this._pageIndex = pageIndex; + this.canvasFactory = canvasFactory; + this.filterFactory = filterFactory; + this._pdfBug = pdfBug; + this.pageColors = pageColors; + this.running = false; + this.graphicsReadyCallback = null; + this.graphicsReady = false; + this._useRequestAnimationFrame = useRequestAnimationFrame === true && typeof window !== "undefined"; + this.cancelled = false; + this.capability = Promise.withResolvers(); + this.task = new RenderTask(this); + this._cancelBound = this.cancel.bind(this); + this._continueBound = this._continue.bind(this); + this._scheduleNextBound = this._scheduleNext.bind(this); + this._nextBound = this._next.bind(this); + this._canvas = params.canvas; + this._canvasContext = params.canvas ? null : params.canvasContext; + this._enableHWA = enableHWA; + this._dependencyTracker = params.dependencyTracker; + this._operationsFilter = operationsFilter; + } + get completed() { + return this.capability.promise.catch(function() { + }); + } + initializeGraphics({ + transparency = false, + optionalContentConfig + }) { + if (this.cancelled) { + return; + } + if (this._canvas) { + if (InternalRenderTask.#canvasInUse.has(this._canvas)) { + throw new Error("Cannot use the same canvas during multiple render() operations. Use different canvas or ensure previous operations were cancelled or completed."); + } + InternalRenderTask.#canvasInUse.add(this._canvas); + } + if (this._pdfBug && globalThis.StepperManager?.enabled) { + this.stepper = globalThis.StepperManager.create(this._pageIndex); + this.stepper.init(this.operatorList); + this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint(); + } + const { + viewport, + transform, + background, + dependencyTracker + } = this.params; + const canvasContext = this._canvasContext || this._canvas.getContext("2d", { + alpha: false, + willReadFrequently: !this._enableHWA + }); + this.gfx = new CanvasGraphics(canvasContext, this.commonObjs, this.objs, this.canvasFactory, this.filterFactory, { + optionalContentConfig + }, this.annotationCanvasMap, this.pageColors, dependencyTracker); + this.gfx.beginDrawing({ + transform, + viewport, + transparency, + background + }); + this.operatorListIdx = 0; + this.graphicsReady = true; + this.graphicsReadyCallback?.(); + } + cancel(error = null, extraDelay = 0) { + this.running = false; + this.cancelled = true; + this.gfx?.endDrawing(); + if (this.#rAF) { + window.cancelAnimationFrame(this.#rAF); + this.#rAF = null; + } + InternalRenderTask.#canvasInUse.delete(this._canvas); + error ||= new RenderingCancelledException(`Rendering cancelled, page ${this._pageIndex + 1}`, extraDelay); + this.callback(error); + this.task.onError?.(error); + } + operatorListChanged() { + if (!this.graphicsReady) { + this.graphicsReadyCallback ||= this._continueBound; + return; + } + this.gfx.dependencyTracker?.growOperationsCount(this.operatorList.fnArray.length); + this.stepper?.updateOperatorList(this.operatorList); + if (this.running) { + return; + } + this._continue(); + } + _continue() { + this.running = true; + if (this.cancelled) { + return; + } + if (this.task.onContinue) { + this.task.onContinue(this._scheduleNextBound); + } else { + this._scheduleNext(); + } + } + _scheduleNext() { + if (this._useRequestAnimationFrame) { + this.#rAF = window.requestAnimationFrame(() => { + this.#rAF = null; + this._nextBound().catch(this._cancelBound); + }); + } else { + Promise.resolve().then(this._nextBound).catch(this._cancelBound); + } + } + async _next() { + if (this.cancelled) { + return; + } + this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList, this.operatorListIdx, this._continueBound, this.stepper, this._operationsFilter); + if (this.operatorListIdx === this.operatorList.argsArray.length) { + this.running = false; + if (this.operatorList.lastChunk) { + this.gfx.endDrawing(); + InternalRenderTask.#canvasInUse.delete(this._canvas); + this.callback(); + } + } + } +} +const version = "5.4.296"; +const build = "f56dc8601"; +class ColorPicker { + #button = null; + #buttonSwatch = null; + #defaultColor; + #dropdown = null; + #dropdownWasFromKeyboard = false; + #isMainColorPicker = false; + #editor = null; + #eventBus; + #openDropdownAC = null; + #uiManager = null; + static #l10nColor = null; + static get _keyboardManager() { + return shadow(this, "_keyboardManager", new KeyboardManager([[["Escape", "mac+Escape"], ColorPicker.prototype._hideDropdownFromKeyboard], [[" ", "mac+ "], ColorPicker.prototype._colorSelectFromKeyboard], [["ArrowDown", "ArrowRight", "mac+ArrowDown", "mac+ArrowRight"], ColorPicker.prototype._moveToNext], [["ArrowUp", "ArrowLeft", "mac+ArrowUp", "mac+ArrowLeft"], ColorPicker.prototype._moveToPrevious], [["Home", "mac+Home"], ColorPicker.prototype._moveToBeginning], [["End", "mac+End"], ColorPicker.prototype._moveToEnd]])); + } + constructor({ + editor = null, + uiManager = null + }) { + if (editor) { + this.#isMainColorPicker = false; + this.#editor = editor; + } else { + this.#isMainColorPicker = true; + } + this.#uiManager = editor?._uiManager || uiManager; + this.#eventBus = this.#uiManager._eventBus; + this.#defaultColor = editor?.color?.toUpperCase() || this.#uiManager?.highlightColors.values().next().value || "#FFFF98"; + ColorPicker.#l10nColor ||= Object.freeze({ + blue: "pdfjs-editor-colorpicker-blue", + green: "pdfjs-editor-colorpicker-green", + pink: "pdfjs-editor-colorpicker-pink", + red: "pdfjs-editor-colorpicker-red", + yellow: "pdfjs-editor-colorpicker-yellow" + }); + } + renderButton() { + const button = this.#button = document.createElement("button"); + button.className = "colorPicker"; + button.tabIndex = "0"; + button.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-button"); + button.ariaHasPopup = "true"; + if (this.#editor) { + button.ariaControls = `${this.#editor.id}_colorpicker_dropdown`; + } + const signal = this.#uiManager._signal; + button.addEventListener("click", this.#openDropdown.bind(this), { + signal + }); + button.addEventListener("keydown", this.#keyDown.bind(this), { + signal + }); + const swatch = this.#buttonSwatch = document.createElement("span"); + swatch.className = "swatch"; + swatch.ariaHidden = "true"; + swatch.style.backgroundColor = this.#defaultColor; + button.append(swatch); + return button; + } + renderMainDropdown() { + const dropdown = this.#dropdown = this.#getDropdownRoot(); + dropdown.ariaOrientation = "horizontal"; + dropdown.ariaLabelledBy = "highlightColorPickerLabel"; + return dropdown; + } + #getDropdownRoot() { + const div = document.createElement("div"); + const signal = this.#uiManager._signal; + div.addEventListener("contextmenu", noContextMenu, { + signal + }); + div.className = "dropdown"; + div.role = "listbox"; + div.ariaMultiSelectable = "false"; + div.ariaOrientation = "vertical"; + div.setAttribute("data-l10n-id", "pdfjs-editor-colorpicker-dropdown"); + if (this.#editor) { + div.id = `${this.#editor.id}_colorpicker_dropdown`; + } + for (const [name, color] of this.#uiManager.highlightColors) { + const button = document.createElement("button"); + button.tabIndex = "0"; + button.role = "option"; + button.setAttribute("data-color", color); + button.title = name; + button.setAttribute("data-l10n-id", ColorPicker.#l10nColor[name]); + const swatch = document.createElement("span"); + button.append(swatch); + swatch.className = "swatch"; + swatch.style.backgroundColor = color; + button.ariaSelected = color === this.#defaultColor; + button.addEventListener("click", this.#colorSelect.bind(this, color), { + signal + }); + div.append(button); + } + div.addEventListener("keydown", this.#keyDown.bind(this), { + signal + }); + return div; + } + #colorSelect(color, event) { + event.stopPropagation(); + this.#eventBus.dispatch("switchannotationeditorparams", { + source: this, + type: AnnotationEditorParamsType.HIGHLIGHT_COLOR, + value: color + }); + this.updateColor(color); + } + _colorSelectFromKeyboard(event) { + if (event.target === this.#button) { + this.#openDropdown(event); + return; + } + const color = event.target.getAttribute("data-color"); + if (!color) { + return; + } + this.#colorSelect(color, event); + } + _moveToNext(event) { + if (!this.#isDropdownVisible) { + this.#openDropdown(event); + return; + } + if (event.target === this.#button) { + this.#dropdown.firstChild?.focus(); + return; + } + event.target.nextSibling?.focus(); + } + _moveToPrevious(event) { + if (event.target === this.#dropdown?.firstChild || event.target === this.#button) { + if (this.#isDropdownVisible) { + this._hideDropdownFromKeyboard(); + } + return; + } + if (!this.#isDropdownVisible) { + this.#openDropdown(event); + } + event.target.previousSibling?.focus(); + } + _moveToBeginning(event) { + if (!this.#isDropdownVisible) { + this.#openDropdown(event); + return; + } + this.#dropdown.firstChild?.focus(); + } + _moveToEnd(event) { + if (!this.#isDropdownVisible) { + this.#openDropdown(event); + return; + } + this.#dropdown.lastChild?.focus(); + } + #keyDown(event) { + ColorPicker._keyboardManager.exec(this, event); + } + #openDropdown(event) { + if (this.#isDropdownVisible) { + this.hideDropdown(); + return; + } + this.#dropdownWasFromKeyboard = event.detail === 0; + if (!this.#openDropdownAC) { + this.#openDropdownAC = new AbortController(); + window.addEventListener("pointerdown", this.#pointerDown.bind(this), { + signal: this.#uiManager.combinedSignal(this.#openDropdownAC) + }); + } + this.#button.ariaExpanded = "true"; + if (this.#dropdown) { + this.#dropdown.classList.remove("hidden"); + return; + } + const root = this.#dropdown = this.#getDropdownRoot(); + this.#button.append(root); + } + #pointerDown(event) { + if (this.#dropdown?.contains(event.target)) { + return; + } + this.hideDropdown(); + } + hideDropdown() { + this.#dropdown?.classList.add("hidden"); + this.#button.ariaExpanded = "false"; + this.#openDropdownAC?.abort(); + this.#openDropdownAC = null; + } + get #isDropdownVisible() { + return this.#dropdown && !this.#dropdown.classList.contains("hidden"); + } + _hideDropdownFromKeyboard() { + if (this.#isMainColorPicker) { + return; + } + if (!this.#isDropdownVisible) { + this.#editor?.unselect(); + return; + } + this.hideDropdown(); + this.#button.focus({ + preventScroll: true, + focusVisible: this.#dropdownWasFromKeyboard + }); + } + updateColor(color) { + if (this.#buttonSwatch) { + this.#buttonSwatch.style.backgroundColor = color; + } + if (!this.#dropdown) { + return; + } + const i = this.#uiManager.highlightColors.values(); + for (const child of this.#dropdown.children) { + child.ariaSelected = i.next().value === color.toUpperCase(); + } + } + destroy() { + this.#button?.remove(); + this.#button = null; + this.#buttonSwatch = null; + this.#dropdown?.remove(); + this.#dropdown = null; + } +} +class BasicColorPicker { + #input = null; + #editor = null; + #uiManager = null; + static #l10nColor = null; + constructor(editor) { + this.#editor = editor; + this.#uiManager = editor._uiManager; + BasicColorPicker.#l10nColor ||= Object.freeze({ + freetext: "pdfjs-editor-color-picker-free-text-input", + ink: "pdfjs-editor-color-picker-ink-input" + }); + } + renderButton() { + if (this.#input) { + return this.#input; + } + const { + editorType, + colorType, + colorValue + } = this.#editor; + const input = this.#input = document.createElement("input"); + input.type = "color"; + input.value = colorValue || "#000000"; + input.className = "basicColorPicker"; + input.tabIndex = 0; + input.setAttribute("data-l10n-id", BasicColorPicker.#l10nColor[editorType]); + input.addEventListener("input", () => { + this.#uiManager.updateParams(colorType, input.value); + }, { + signal: this.#uiManager._signal + }); + return input; + } + update(value) { + if (!this.#input) { + return; + } + this.#input.value = value; + } + destroy() { + this.#input?.remove(); + this.#input = null; + } + hideDropdown() { + } +} +__webpack_require__(116); +__webpack_require__(531); +function makeColorComp(n) { + return Math.floor(Math.max(0, Math.min(1, n)) * 255).toString(16).padStart(2, "0"); +} +function scaleAndClamp(x) { + return Math.max(0, Math.min(255, 255 * x)); +} +class ColorConverters { + static CMYK_G([c, y, m, k]) { + return ["G", 1 - Math.min(1, 0.3 * c + 0.59 * m + 0.11 * y + k)]; + } + static G_CMYK([g]) { + return ["CMYK", 0, 0, 0, 1 - g]; + } + static G_RGB([g]) { + return ["RGB", g, g, g]; + } + static G_rgb([g]) { + g = scaleAndClamp(g); + return [g, g, g]; + } + static G_HTML([g]) { + const G = makeColorComp(g); + return `#${G}${G}${G}`; + } + static RGB_G([r, g, b]) { + return ["G", 0.3 * r + 0.59 * g + 0.11 * b]; + } + static RGB_rgb(color) { + return color.map(scaleAndClamp); + } + static RGB_HTML(color) { + return `#${color.map(makeColorComp).join("")}`; + } + static T_HTML() { + return "#00000000"; + } + static T_rgb() { + return [null]; + } + static CMYK_RGB([c, y, m, k]) { + return ["RGB", 1 - Math.min(1, c + k), 1 - Math.min(1, m + k), 1 - Math.min(1, y + k)]; + } + static CMYK_rgb([c, y, m, k]) { + return [scaleAndClamp(1 - Math.min(1, c + k)), scaleAndClamp(1 - Math.min(1, m + k)), scaleAndClamp(1 - Math.min(1, y + k))]; + } + static CMYK_HTML(components) { + const rgb = this.CMYK_RGB(components).slice(1); + return this.RGB_HTML(rgb); + } + static RGB_CMYK([r, g, b]) { + const c = 1 - r; + const m = 1 - g; + const y = 1 - b; + const k = Math.min(c, m, y); + return ["CMYK", c, m, y, k]; + } +} +class BaseSVGFactory { + create(width, height, skipDimensions = false) { + if (width <= 0 || height <= 0) { + throw new Error("Invalid SVG dimensions"); + } + const svg = this._createSVG("svg:svg"); + svg.setAttribute("version", "1.1"); + if (!skipDimensions) { + svg.setAttribute("width", `${width}px`); + svg.setAttribute("height", `${height}px`); + } + svg.setAttribute("preserveAspectRatio", "none"); + svg.setAttribute("viewBox", `0 0 ${width} ${height}`); + return svg; + } + createElement(type) { + if (typeof type !== "string") { + throw new Error("Invalid SVG element type"); + } + return this._createSVG(type); + } + _createSVG(type) { + unreachable("Abstract method `_createSVG` called."); + } +} +class DOMSVGFactory extends BaseSVGFactory { + _createSVG(type) { + return document.createElementNS(SVG_NS, type); + } +} +const annotation_layer_DEFAULT_FONT_SIZE = 9; +const GetElementsByNameSet = /* @__PURE__ */ new WeakSet(); +const TIMEZONE_OFFSET = (/* @__PURE__ */ new Date()).getTimezoneOffset() * 60 * 1e3; +class AnnotationElementFactory { + static create(parameters) { + const subtype = parameters.data.annotationType; + switch (subtype) { + case AnnotationType.LINK: + return new LinkAnnotationElement(parameters); + case AnnotationType.TEXT: + return new TextAnnotationElement(parameters); + case AnnotationType.WIDGET: + const fieldType = parameters.data.fieldType; + switch (fieldType) { + case "Tx": + return new TextWidgetAnnotationElement(parameters); + case "Btn": + if (parameters.data.radioButton) { + return new RadioButtonWidgetAnnotationElement(parameters); + } else if (parameters.data.checkBox) { + return new CheckboxWidgetAnnotationElement(parameters); + } + return new PushButtonWidgetAnnotationElement(parameters); + case "Ch": + return new ChoiceWidgetAnnotationElement(parameters); + case "Sig": + return new SignatureWidgetAnnotationElement(parameters); + } + return new WidgetAnnotationElement(parameters); + case AnnotationType.POPUP: + return new PopupAnnotationElement(parameters); + case AnnotationType.FREETEXT: + return new FreeTextAnnotationElement(parameters); + case AnnotationType.LINE: + return new LineAnnotationElement(parameters); + case AnnotationType.SQUARE: + return new SquareAnnotationElement(parameters); + case AnnotationType.CIRCLE: + return new CircleAnnotationElement(parameters); + case AnnotationType.POLYLINE: + return new PolylineAnnotationElement(parameters); + case AnnotationType.CARET: + return new CaretAnnotationElement(parameters); + case AnnotationType.INK: + return new InkAnnotationElement(parameters); + case AnnotationType.POLYGON: + return new PolygonAnnotationElement(parameters); + case AnnotationType.HIGHLIGHT: + return new HighlightAnnotationElement(parameters); + case AnnotationType.UNDERLINE: + return new UnderlineAnnotationElement(parameters); + case AnnotationType.SQUIGGLY: + return new SquigglyAnnotationElement(parameters); + case AnnotationType.STRIKEOUT: + return new StrikeOutAnnotationElement(parameters); + case AnnotationType.STAMP: + return new StampAnnotationElement(parameters); + case AnnotationType.FILEATTACHMENT: + return new FileAttachmentAnnotationElement(parameters); + default: + return new AnnotationElement(parameters); + } + } +} +class AnnotationElement { + #updates = null; + #hasBorder = false; + #popupElement = null; + constructor(parameters, { + isRenderable = false, + ignoreBorder = false, + createQuadrilaterals = false + } = {}) { + this.isRenderable = isRenderable; + this.data = parameters.data; + this.layer = parameters.layer; + this.linkService = parameters.linkService; + this.downloadManager = parameters.downloadManager; + this.imageResourcesPath = parameters.imageResourcesPath; + this.renderForms = parameters.renderForms; + this.svgFactory = parameters.svgFactory; + this.annotationStorage = parameters.annotationStorage; + this.enableComment = parameters.enableComment; + this.enableScripting = parameters.enableScripting; + this.hasJSActions = parameters.hasJSActions; + this._fieldObjects = parameters.fieldObjects; + this.parent = parameters.parent; + if (isRenderable) { + this.container = this._createContainer(ignoreBorder); + } + if (createQuadrilaterals) { + this._createQuadrilaterals(); + } + } + static _hasPopupData({ + contentsObj, + richText + }) { + return !!(contentsObj?.str || richText?.str); + } + get _isEditable() { + return this.data.isEditable; + } + get hasPopupData() { + return AnnotationElement._hasPopupData(this.data) || this.enableComment && !!this.commentText; + } + get commentData() { + const { + data + } = this; + const editor = this.annotationStorage?.getEditor(data.id); + if (editor) { + return editor.getData(); + } + return data; + } + get hasCommentButton() { + return this.enableComment && this.hasPopupElement; + } + get commentButtonPosition() { + const editor = this.annotationStorage?.getEditor(this.data.id); + if (editor) { + return editor.commentButtonPositionInPage; + } + const { + quadPoints, + inkLists, + rect + } = this.data; + let maxX = -Infinity; + let maxY = -Infinity; + if (quadPoints?.length >= 8) { + for (let i = 0; i < quadPoints.length; i += 8) { + if (quadPoints[i + 1] > maxY) { + maxY = quadPoints[i + 1]; + maxX = quadPoints[i + 2]; + } else if (quadPoints[i + 1] === maxY) { + maxX = Math.max(maxX, quadPoints[i + 2]); + } + } + return [maxX, maxY]; + } + if (inkLists?.length >= 1) { + for (const inkList of inkLists) { + for (let i = 0, ii = inkList.length; i < ii; i += 2) { + if (inkList[i + 1] > maxY) { + maxY = inkList[i + 1]; + maxX = inkList[i]; + } else if (inkList[i + 1] === maxY) { + maxX = Math.max(maxX, inkList[i]); + } + } + } + if (maxX !== Infinity) { + return [maxX, maxY]; + } + } + if (rect) { + return [rect[2], rect[3]]; + } + return null; + } + _normalizePoint(point) { + const { + page: { + view + }, + viewport: { + rawDims: { + pageWidth, + pageHeight, + pageX, + pageY + } + } + } = this.parent; + point[1] = view[3] - point[1] + view[1]; + point[0] = 100 * (point[0] - pageX) / pageWidth; + point[1] = 100 * (point[1] - pageY) / pageHeight; + return point; + } + get commentText() { + const { + data + } = this; + return this.annotationStorage.getRawValue(`${AnnotationEditorPrefix}${data.id}`)?.popup?.contents || data.contentsObj?.str || ""; + } + set commentText(text) { + const { + data + } = this; + const popup = { + deleted: !text, + contents: text || "" + }; + if (!this.annotationStorage.updateEditor(data.id, { + popup + })) { + this.annotationStorage.setValue(`${AnnotationEditorPrefix}${data.id}`, { + id: data.id, + annotationType: data.annotationType, + pageIndex: this.parent.page._pageIndex, + popup, + popupRef: data.popupRef, + modificationDate: /* @__PURE__ */ new Date() + }); + } + if (!text) { + this.removePopup(); + } + } + removePopup() { + (this.#popupElement?.popup || this.popup)?.remove(); + this.#popupElement = this.popup = null; + } + updateEdited(params) { + if (!this.container) { + return; + } + if (params.rect) { + this.#updates ||= { + rect: this.data.rect.slice(0) + }; + } + const { + rect, + popup: newPopup + } = params; + if (rect) { + this.#setRectEdited(rect); + } + let popup = this.#popupElement?.popup || this.popup; + if (!popup && newPopup?.text) { + this._createPopup(newPopup); + popup = this.#popupElement.popup; + } + if (!popup) { + return; + } + popup.updateEdited(params); + if (newPopup?.deleted) { + popup.remove(); + this.#popupElement = null; + this.popup = null; + } + } + resetEdited() { + if (!this.#updates) { + return; + } + this.#setRectEdited(this.#updates.rect); + this.#popupElement?.popup.resetEdited(); + this.#updates = null; + } + #setRectEdited(rect) { + const { + container: { + style + }, + data: { + rect: currentRect, + rotation + }, + parent: { + viewport: { + rawDims: { + pageWidth, + pageHeight, + pageX, + pageY + } + } + } + } = this; + currentRect?.splice(0, 4, ...rect); + style.left = `${100 * (rect[0] - pageX) / pageWidth}%`; + style.top = `${100 * (pageHeight - rect[3] + pageY) / pageHeight}%`; + if (rotation === 0) { + style.width = `${100 * (rect[2] - rect[0]) / pageWidth}%`; + style.height = `${100 * (rect[3] - rect[1]) / pageHeight}%`; + } else { + this.setRotation(rotation); + } + } + _createContainer(ignoreBorder) { + const { + data, + parent: { + page, + viewport + } + } = this; + const container = document.createElement("section"); + container.setAttribute("data-annotation-id", data.id); + if (!(this instanceof WidgetAnnotationElement) && !(this instanceof LinkAnnotationElement)) { + container.tabIndex = 0; + } + const { + style + } = container; + style.zIndex = this.parent.zIndex; + this.parent.zIndex += 2; + if (data.alternativeText) { + container.title = data.alternativeText; + } + if (data.noRotate) { + container.classList.add("norotate"); + } + if (!data.rect || this instanceof PopupAnnotationElement) { + const { + rotation: rotation2 + } = data; + if (!data.hasOwnCanvas && rotation2 !== 0) { + this.setRotation(rotation2, container); + } + return container; + } + const { + width, + height + } = this; + if (!ignoreBorder && data.borderStyle.width > 0) { + style.borderWidth = `${data.borderStyle.width}px`; + const horizontalRadius = data.borderStyle.horizontalCornerRadius; + const verticalRadius = data.borderStyle.verticalCornerRadius; + if (horizontalRadius > 0 || verticalRadius > 0) { + const radius = `calc(${horizontalRadius}px * var(--total-scale-factor)) / calc(${verticalRadius}px * var(--total-scale-factor))`; + style.borderRadius = radius; + } else if (this instanceof RadioButtonWidgetAnnotationElement) { + const radius = `calc(${width}px * var(--total-scale-factor)) / calc(${height}px * var(--total-scale-factor))`; + style.borderRadius = radius; + } + switch (data.borderStyle.style) { + case AnnotationBorderStyleType.SOLID: + style.borderStyle = "solid"; + break; + case AnnotationBorderStyleType.DASHED: + style.borderStyle = "dashed"; + break; + case AnnotationBorderStyleType.BEVELED: + warn("Unimplemented border style: beveled"); + break; + case AnnotationBorderStyleType.INSET: + warn("Unimplemented border style: inset"); + break; + case AnnotationBorderStyleType.UNDERLINE: + style.borderBottomStyle = "solid"; + break; + } + const borderColor = data.borderColor || null; + if (borderColor) { + this.#hasBorder = true; + style.borderColor = Util.makeHexColor(borderColor[0] | 0, borderColor[1] | 0, borderColor[2] | 0); + } else { + style.borderWidth = 0; + } + } + const rect = Util.normalizeRect([data.rect[0], page.view[3] - data.rect[1] + page.view[1], data.rect[2], page.view[3] - data.rect[3] + page.view[1]]); + const { + pageWidth, + pageHeight, + pageX, + pageY + } = viewport.rawDims; + style.left = `${100 * (rect[0] - pageX) / pageWidth}%`; + style.top = `${100 * (rect[1] - pageY) / pageHeight}%`; + const { + rotation + } = data; + if (data.hasOwnCanvas || rotation === 0) { + style.width = `${100 * width / pageWidth}%`; + style.height = `${100 * height / pageHeight}%`; + } else { + this.setRotation(rotation, container); + } + return container; + } + setRotation(angle, container = this.container) { + if (!this.data.rect) { + return; + } + const { + pageWidth, + pageHeight + } = this.parent.viewport.rawDims; + let { + width, + height + } = this; + if (angle % 180 !== 0) { + [width, height] = [height, width]; + } + container.style.width = `${100 * width / pageWidth}%`; + container.style.height = `${100 * height / pageHeight}%`; + container.setAttribute("data-main-rotation", (360 - angle) % 360); + } + get _commonActions() { + const setColor = (jsName, styleName, event) => { + const color = event.detail[jsName]; + const colorType = color[0]; + const colorArray = color.slice(1); + event.target.style[styleName] = ColorConverters[`${colorType}_HTML`](colorArray); + this.annotationStorage.setValue(this.data.id, { + [styleName]: ColorConverters[`${colorType}_rgb`](colorArray) + }); + }; + return shadow(this, "_commonActions", { + display: (event) => { + const { + display + } = event.detail; + const hidden = display % 2 === 1; + this.container.style.visibility = hidden ? "hidden" : "visible"; + this.annotationStorage.setValue(this.data.id, { + noView: hidden, + noPrint: display === 1 || display === 2 + }); + }, + print: (event) => { + this.annotationStorage.setValue(this.data.id, { + noPrint: !event.detail.print + }); + }, + hidden: (event) => { + const { + hidden + } = event.detail; + this.container.style.visibility = hidden ? "hidden" : "visible"; + this.annotationStorage.setValue(this.data.id, { + noPrint: hidden, + noView: hidden + }); + }, + focus: (event) => { + setTimeout(() => event.target.focus({ + preventScroll: false + }), 0); + }, + userName: (event) => { + event.target.title = event.detail.userName; + }, + readonly: (event) => { + event.target.disabled = event.detail.readonly; + }, + required: (event) => { + this._setRequired(event.target, event.detail.required); + }, + bgColor: (event) => { + setColor("bgColor", "backgroundColor", event); + }, + fillColor: (event) => { + setColor("fillColor", "backgroundColor", event); + }, + fgColor: (event) => { + setColor("fgColor", "color", event); + }, + textColor: (event) => { + setColor("textColor", "color", event); + }, + borderColor: (event) => { + setColor("borderColor", "borderColor", event); + }, + strokeColor: (event) => { + setColor("strokeColor", "borderColor", event); + }, + rotation: (event) => { + const angle = event.detail.rotation; + this.setRotation(angle); + this.annotationStorage.setValue(this.data.id, { + rotation: angle + }); + } + }); + } + _dispatchEventFromSandbox(actions, jsEvent) { + const commonActions = this._commonActions; + for (const name of Object.keys(jsEvent.detail)) { + const action = actions[name] || commonActions[name]; + action?.(jsEvent); + } + } + _setDefaultPropertiesFromJS(element) { + if (!this.enableScripting) { + return; + } + const storedData = this.annotationStorage.getRawValue(this.data.id); + if (!storedData) { + return; + } + const commonActions = this._commonActions; + for (const [actionName, detail] of Object.entries(storedData)) { + const action = commonActions[actionName]; + if (action) { + const eventProxy = { + detail: { + [actionName]: detail + }, + target: element + }; + action(eventProxy); + delete storedData[actionName]; + } + } + } + _createQuadrilaterals() { + if (!this.container) { + return; + } + const { + quadPoints + } = this.data; + if (!quadPoints) { + return; + } + const [rectBlX, rectBlY, rectTrX, rectTrY] = this.data.rect.map((x) => Math.fround(x)); + if (quadPoints.length === 8) { + const [trX, trY, blX, blY] = quadPoints.subarray(2, 6); + if (rectTrX === trX && rectTrY === trY && rectBlX === blX && rectBlY === blY) { + return; + } + } + const { + style + } = this.container; + let svgBuffer; + if (this.#hasBorder) { + const { + borderColor, + borderWidth + } = style; + style.borderWidth = 0; + svgBuffer = ["url('data:image/svg+xml;utf8,", ``, ``]; + this.container.classList.add("hasBorder"); + } + const width = rectTrX - rectBlX; + const height = rectTrY - rectBlY; + const { + svgFactory + } = this; + const svg = svgFactory.createElement("svg"); + svg.classList.add("quadrilateralsContainer"); + svg.setAttribute("width", 0); + svg.setAttribute("height", 0); + svg.role = "none"; + const defs = svgFactory.createElement("defs"); + svg.append(defs); + const clipPath = svgFactory.createElement("clipPath"); + const id = `clippath_${this.data.id}`; + clipPath.setAttribute("id", id); + clipPath.setAttribute("clipPathUnits", "objectBoundingBox"); + defs.append(clipPath); + for (let i = 2, ii = quadPoints.length; i < ii; i += 8) { + const trX = quadPoints[i]; + const trY = quadPoints[i + 1]; + const blX = quadPoints[i + 2]; + const blY = quadPoints[i + 3]; + const rect = svgFactory.createElement("rect"); + const x = (blX - rectBlX) / width; + const y = (rectTrY - trY) / height; + const rectWidth = (trX - blX) / width; + const rectHeight = (trY - blY) / height; + rect.setAttribute("x", x); + rect.setAttribute("y", y); + rect.setAttribute("width", rectWidth); + rect.setAttribute("height", rectHeight); + clipPath.append(rect); + svgBuffer?.push(``); + } + if (this.#hasBorder) { + svgBuffer.push(`')`); + style.backgroundImage = svgBuffer.join(""); + } + this.container.append(svg); + this.container.style.clipPath = `url(#${id})`; + } + _createPopup(popupData = null) { + const { + data + } = this; + let contentsObj, modificationDate; + if (popupData) { + contentsObj = { + str: popupData.text + }; + modificationDate = popupData.date; + } else { + contentsObj = data.contentsObj; + modificationDate = data.modificationDate; + } + const popup = this.#popupElement = new PopupAnnotationElement({ + data: { + color: data.color, + titleObj: data.titleObj, + modificationDate, + contentsObj, + richText: data.richText, + parentRect: data.rect, + borderStyle: 0, + id: `popup_${data.id}`, + rotation: data.rotation, + noRotate: true + }, + linkService: this.linkService, + parent: this.parent, + elements: [this] + }); + if (!this.parent._commentManager) { + this.parent.div.append(popup.render()); + } + } + get hasPopupElement() { + return !!(this.#popupElement || this.popup || this.data.popupRef); + } + get extraPopupElement() { + return this.#popupElement; + } + render() { + unreachable("Abstract method `AnnotationElement.render` called"); + } + _getElementsByName(name, skipId = null) { + const fields = []; + if (this._fieldObjects) { + const fieldObj = this._fieldObjects[name]; + if (fieldObj) { + for (const { + page, + id, + exportValues + } of fieldObj) { + if (page === -1) { + continue; + } + if (id === skipId) { + continue; + } + const exportValue = typeof exportValues === "string" ? exportValues : null; + const domElement = document.querySelector(`[data-element-id="${id}"]`); + if (domElement && !GetElementsByNameSet.has(domElement)) { + warn(`_getElementsByName - element not allowed: ${id}`); + continue; + } + fields.push({ + id, + exportValue, + domElement + }); + } + } + return fields; + } + for (const domElement of document.getElementsByName(name)) { + const { + exportValue + } = domElement; + const id = domElement.getAttribute("data-element-id"); + if (id === skipId) { + continue; + } + if (!GetElementsByNameSet.has(domElement)) { + continue; + } + fields.push({ + id, + exportValue, + domElement + }); + } + return fields; + } + show() { + if (this.container) { + this.container.hidden = false; + } + this.popup?.maybeShow(); + } + hide() { + if (this.container) { + this.container.hidden = true; + } + this.popup?.forceHide(); + } + getElementsToTriggerPopup() { + return this.container; + } + addHighlightArea() { + const triggers = this.getElementsToTriggerPopup(); + if (Array.isArray(triggers)) { + for (const element of triggers) { + element.classList.add("highlightArea"); + } + } else { + triggers.classList.add("highlightArea"); + } + } + _editOnDoubleClick() { + if (!this._isEditable) { + return; + } + const { + annotationEditorType: mode, + data: { + id: editId + } + } = this; + this.container.addEventListener("dblclick", () => { + this.linkService.eventBus?.dispatch("switchannotationeditormode", { + source: this, + mode, + editId, + mustEnterInEditMode: true + }); + }); + } + get width() { + return this.data.rect[2] - this.data.rect[0]; + } + get height() { + return this.data.rect[3] - this.data.rect[1]; + } +} +class EditorAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + this.editor = parameters.editor; + } + render() { + this.container.className = "editorAnnotation"; + return this.container; + } + createOrUpdatePopup() { + const { + editor + } = this; + if (!editor.hasComment) { + return; + } + this._createPopup(editor.comment); + this.extraPopupElement.popup.renderCommentButton(); + } + get hasCommentButton() { + return this.enableComment && this.editor.hasComment; + } + get commentButtonPosition() { + return this.editor.commentButtonPositionInPage; + } + get commentText() { + return this.editor.comment.text; + } + set commentText(text) { + this.editor.comment = text; + if (!text) { + this.removePopup(); + } + } + get commentData() { + return this.editor.getData(); + } + remove() { + this.container.remove(); + this.container = null; + this.removePopup(); + } +} +class LinkAnnotationElement extends AnnotationElement { + constructor(parameters, options = null) { + super(parameters, { + isRenderable: true, + ignoreBorder: !!options?.ignoreBorder, + createQuadrilaterals: true + }); + this.isTooltipOnly = parameters.data.isTooltipOnly; + } + render() { + const { + data, + linkService + } = this; + const link = document.createElement("a"); + link.setAttribute("data-element-id", data.id); + let isBound = false; + if (data.url) { + linkService.addLinkAttributes(link, data.url, data.newWindow); + isBound = true; + } else if (data.action) { + this._bindNamedAction(link, data.action, data.overlaidText); + isBound = true; + } else if (data.attachment) { + this.#bindAttachment(link, data.attachment, data.overlaidText, data.attachmentDest); + isBound = true; + } else if (data.setOCGState) { + this.#bindSetOCGState(link, data.setOCGState, data.overlaidText); + isBound = true; + } else if (data.dest) { + this._bindLink(link, data.dest, data.overlaidText); + isBound = true; + } else { + if (data.actions && (data.actions.Action || data.actions["Mouse Up"] || data.actions["Mouse Down"]) && this.enableScripting && this.hasJSActions) { + this._bindJSAction(link, data); + isBound = true; + } + if (data.resetForm) { + this._bindResetFormAction(link, data.resetForm); + isBound = true; + } else if (this.isTooltipOnly && !isBound) { + this._bindLink(link, ""); + isBound = true; + } + } + this.container.classList.add("linkAnnotation"); + if (isBound) { + this.container.append(link); + } + return this.container; + } + #setInternalLink() { + this.container.setAttribute("data-internal-link", ""); + } + _bindLink(link, destination, overlaidText = "") { + link.href = this.linkService.getDestinationHash(destination); + link.onclick = () => { + if (destination) { + this.linkService.goToDestination(destination); + } + return false; + }; + if (destination || destination === "") { + this.#setInternalLink(); + } + if (overlaidText) { + link.title = overlaidText; + } + } + _bindNamedAction(link, action, overlaidText = "") { + link.href = this.linkService.getAnchorUrl(""); + link.onclick = () => { + this.linkService.executeNamedAction(action); + return false; + }; + if (overlaidText) { + link.title = overlaidText; + } + this.#setInternalLink(); + } + #bindAttachment(link, attachment, overlaidText = "", dest = null) { + link.href = this.linkService.getAnchorUrl(""); + if (attachment.description) { + link.title = attachment.description; + } else if (overlaidText) { + link.title = overlaidText; + } + link.onclick = () => { + this.downloadManager?.openOrDownloadData(attachment.content, attachment.filename, dest); + return false; + }; + this.#setInternalLink(); + } + #bindSetOCGState(link, action, overlaidText = "") { + link.href = this.linkService.getAnchorUrl(""); + link.onclick = () => { + this.linkService.executeSetOCGState(action); + return false; + }; + if (overlaidText) { + link.title = overlaidText; + } + this.#setInternalLink(); + } + _bindJSAction(link, data) { + link.href = this.linkService.getAnchorUrl(""); + const map = /* @__PURE__ */ new Map([["Action", "onclick"], ["Mouse Up", "onmouseup"], ["Mouse Down", "onmousedown"]]); + for (const name of Object.keys(data.actions)) { + const jsName = map.get(name); + if (!jsName) { + continue; + } + link[jsName] = () => { + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: data.id, + name + } + }); + return false; + }; + } + if (data.overlaidText) { + link.title = data.overlaidText; + } + if (!link.onclick) { + link.onclick = () => false; + } + this.#setInternalLink(); + } + _bindResetFormAction(link, resetForm) { + const otherClickAction = link.onclick; + if (!otherClickAction) { + link.href = this.linkService.getAnchorUrl(""); + } + this.#setInternalLink(); + if (!this._fieldObjects) { + warn(`_bindResetFormAction - "resetForm" action not supported, ensure that the \`fieldObjects\` parameter is provided.`); + if (!otherClickAction) { + link.onclick = () => false; + } + return; + } + link.onclick = () => { + otherClickAction?.(); + const { + fields: resetFormFields, + refs: resetFormRefs, + include + } = resetForm; + const allFields = []; + if (resetFormFields.length !== 0 || resetFormRefs.length !== 0) { + const fieldIds = new Set(resetFormRefs); + for (const fieldName of resetFormFields) { + const fields = this._fieldObjects[fieldName] || []; + for (const { + id + } of fields) { + fieldIds.add(id); + } + } + for (const fields of Object.values(this._fieldObjects)) { + for (const field of fields) { + if (fieldIds.has(field.id) === include) { + allFields.push(field); + } + } + } + } else { + for (const fields of Object.values(this._fieldObjects)) { + allFields.push(...fields); + } + } + const storage = this.annotationStorage; + const allIds = []; + for (const field of allFields) { + const { + id + } = field; + allIds.push(id); + switch (field.type) { + case "text": { + const value = field.defaultValue || ""; + storage.setValue(id, { + value + }); + break; + } + case "checkbox": + case "radiobutton": { + const value = field.defaultValue === field.exportValues; + storage.setValue(id, { + value + }); + break; + } + case "combobox": + case "listbox": { + const value = field.defaultValue || ""; + storage.setValue(id, { + value + }); + break; + } + default: + continue; + } + const domElement = document.querySelector(`[data-element-id="${id}"]`); + if (!domElement) { + continue; + } else if (!GetElementsByNameSet.has(domElement)) { + warn(`_bindResetFormAction - element not allowed: ${id}`); + continue; + } + domElement.dispatchEvent(new Event("resetform")); + } + if (this.enableScripting) { + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: "app", + ids: allIds, + name: "ResetForm" + } + }); + } + return false; + }; + } +} +class TextAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true + }); + } + render() { + this.container.classList.add("textAnnotation"); + const image = document.createElement("img"); + image.src = this.imageResourcesPath + "annotation-" + this.data.name.toLowerCase() + ".svg"; + image.setAttribute("data-l10n-id", "pdfjs-text-annotation-type"); + image.setAttribute("data-l10n-args", JSON.stringify({ + type: this.data.name + })); + if (!this.data.popupRef && this.hasPopupData) { + this._createPopup(); + } + this.container.append(image); + return this.container; + } +} +class WidgetAnnotationElement extends AnnotationElement { + render() { + return this.container; + } + showElementAndHideCanvas(element) { + if (this.data.hasOwnCanvas) { + if (element.previousSibling?.nodeName === "CANVAS") { + element.previousSibling.hidden = true; + } + element.hidden = false; + } + } + _getKeyModifier(event) { + return util_FeatureTest.platform.isMac ? event.metaKey : event.ctrlKey; + } + _setEventListener(element, elementData, baseName, eventName, valueGetter) { + if (baseName.includes("mouse")) { + element.addEventListener(baseName, (event) => { + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: this.data.id, + name: eventName, + value: valueGetter(event), + shift: event.shiftKey, + modifier: this._getKeyModifier(event) + } + }); + }); + } else { + element.addEventListener(baseName, (event) => { + if (baseName === "blur") { + if (!elementData.focused || !event.relatedTarget) { + return; + } + elementData.focused = false; + } else if (baseName === "focus") { + if (elementData.focused) { + return; + } + elementData.focused = true; + } + if (!valueGetter) { + return; + } + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id: this.data.id, + name: eventName, + value: valueGetter(event) + } + }); + }); + } + } + _setEventListeners(element, elementData, names, getter) { + for (const [baseName, eventName] of names) { + if (eventName === "Action" || this.data.actions?.[eventName]) { + if (eventName === "Focus" || eventName === "Blur") { + elementData ||= { + focused: false + }; + } + this._setEventListener(element, elementData, baseName, eventName, getter); + if (eventName === "Focus" && !this.data.actions?.Blur) { + this._setEventListener(element, elementData, "blur", "Blur", null); + } else if (eventName === "Blur" && !this.data.actions?.Focus) { + this._setEventListener(element, elementData, "focus", "Focus", null); + } + } + } + } + _setBackgroundColor(element) { + const color = this.data.backgroundColor || null; + element.style.backgroundColor = color === null ? "transparent" : Util.makeHexColor(color[0], color[1], color[2]); + } + _setTextStyle(element) { + const TEXT_ALIGNMENT = ["left", "center", "right"]; + const { + fontColor + } = this.data.defaultAppearanceData; + const fontSize = this.data.defaultAppearanceData.fontSize || annotation_layer_DEFAULT_FONT_SIZE; + const style = element.style; + let computedFontSize; + const BORDER_SIZE = 2; + const roundToOneDecimal = (x) => Math.round(10 * x) / 10; + if (this.data.multiLine) { + const height = Math.abs(this.data.rect[3] - this.data.rect[1] - BORDER_SIZE); + const numberOfLines = Math.round(height / (LINE_FACTOR * fontSize)) || 1; + const lineHeight = height / numberOfLines; + computedFontSize = Math.min(fontSize, roundToOneDecimal(lineHeight / LINE_FACTOR)); + } else { + const height = Math.abs(this.data.rect[3] - this.data.rect[1] - BORDER_SIZE); + computedFontSize = Math.min(fontSize, roundToOneDecimal(height / LINE_FACTOR)); + } + style.fontSize = `calc(${computedFontSize}px * var(--total-scale-factor))`; + style.color = Util.makeHexColor(fontColor[0], fontColor[1], fontColor[2]); + if (this.data.textAlignment !== null) { + style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment]; + } + } + _setRequired(element, isRequired) { + if (isRequired) { + element.setAttribute("required", true); + } else { + element.removeAttribute("required"); + } + element.setAttribute("aria-required", isRequired); + } +} +class TextWidgetAnnotationElement extends WidgetAnnotationElement { + constructor(parameters) { + const isRenderable = parameters.renderForms || parameters.data.hasOwnCanvas || !parameters.data.hasAppearance && !!parameters.data.fieldValue; + super(parameters, { + isRenderable + }); + } + setPropertyOnSiblings(base, key, value, keyInStorage) { + const storage = this.annotationStorage; + for (const element of this._getElementsByName(base.name, base.id)) { + if (element.domElement) { + element.domElement[key] = value; + } + storage.setValue(element.id, { + [keyInStorage]: value + }); + } + } + render() { + const storage = this.annotationStorage; + const id = this.data.id; + this.container.classList.add("textWidgetAnnotation"); + let element = null; + if (this.renderForms) { + const storedData = storage.getValue(id, { + value: this.data.fieldValue + }); + let textContent = storedData.value || ""; + const maxLen = storage.getValue(id, { + charLimit: this.data.maxLen + }).charLimit; + if (maxLen && textContent.length > maxLen) { + textContent = textContent.slice(0, maxLen); + } + let fieldFormattedValues = storedData.formattedValue || this.data.textContent?.join("\n") || null; + if (fieldFormattedValues && this.data.comb) { + fieldFormattedValues = fieldFormattedValues.replaceAll(/\s+/g, ""); + } + const elementData = { + userValue: textContent, + formattedValue: fieldFormattedValues, + lastCommittedValue: null, + commitKey: 1, + focused: false + }; + if (this.data.multiLine) { + element = document.createElement("textarea"); + element.textContent = fieldFormattedValues ?? textContent; + if (this.data.doNotScroll) { + element.style.overflowY = "hidden"; + } + } else { + element = document.createElement("input"); + element.type = this.data.password ? "password" : "text"; + element.setAttribute("value", fieldFormattedValues ?? textContent); + if (this.data.doNotScroll) { + element.style.overflowX = "hidden"; + } + } + if (this.data.hasOwnCanvas) { + element.hidden = true; + } + GetElementsByNameSet.add(element); + element.setAttribute("data-element-id", id); + element.disabled = this.data.readOnly; + element.name = this.data.fieldName; + element.tabIndex = 0; + const { + datetimeFormat, + datetimeType, + timeStep + } = this.data; + const hasDateOrTime = !!datetimeType && this.enableScripting; + if (datetimeFormat) { + element.title = datetimeFormat; + } + this._setRequired(element, this.data.required); + if (maxLen) { + element.maxLength = maxLen; + } + element.addEventListener("input", (event) => { + storage.setValue(id, { + value: event.target.value + }); + this.setPropertyOnSiblings(element, "value", event.target.value, "value"); + elementData.formattedValue = null; + }); + element.addEventListener("resetform", (event) => { + const defaultValue = this.data.defaultFieldValue ?? ""; + element.value = elementData.userValue = defaultValue; + elementData.formattedValue = null; + }); + let blurListener = (event) => { + const { + formattedValue + } = elementData; + if (formattedValue !== null && formattedValue !== void 0) { + event.target.value = formattedValue; + } + event.target.scrollLeft = 0; + }; + if (this.enableScripting && this.hasJSActions) { + element.addEventListener("focus", (event) => { + if (elementData.focused) { + return; + } + const { + target + } = event; + if (hasDateOrTime) { + target.type = datetimeType; + if (timeStep) { + target.step = timeStep; + } + } + if (elementData.userValue) { + const value = elementData.userValue; + if (hasDateOrTime) { + if (datetimeType === "time") { + const date = new Date(value); + const parts = [date.getHours(), date.getMinutes(), date.getSeconds()]; + target.value = parts.map((v) => v.toString().padStart(2, "0")).join(":"); + } else { + target.value = new Date(value - TIMEZONE_OFFSET).toISOString().split(datetimeType === "date" ? "T" : ".", 1)[0]; + } + } else { + target.value = value; + } + } + elementData.lastCommittedValue = target.value; + elementData.commitKey = 1; + if (!this.data.actions?.Focus) { + elementData.focused = true; + } + }); + element.addEventListener("updatefromsandbox", (jsEvent) => { + this.showElementAndHideCanvas(jsEvent.target); + const actions = { + value(event) { + elementData.userValue = event.detail.value ?? ""; + if (!hasDateOrTime) { + storage.setValue(id, { + value: elementData.userValue.toString() + }); + } + event.target.value = elementData.userValue; + }, + formattedValue(event) { + const { + formattedValue + } = event.detail; + elementData.formattedValue = formattedValue; + if (formattedValue !== null && formattedValue !== void 0 && event.target !== document.activeElement) { + event.target.value = formattedValue; + } + const data = { + formattedValue + }; + if (hasDateOrTime) { + data.value = formattedValue; + } + storage.setValue(id, data); + }, + selRange(event) { + event.target.setSelectionRange(...event.detail.selRange); + }, + charLimit: (event) => { + const { + charLimit + } = event.detail; + const { + target + } = event; + if (charLimit === 0) { + target.removeAttribute("maxLength"); + return; + } + target.setAttribute("maxLength", charLimit); + let value = elementData.userValue; + if (!value || value.length <= charLimit) { + return; + } + value = value.slice(0, charLimit); + target.value = elementData.userValue = value; + storage.setValue(id, { + value + }); + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value, + willCommit: true, + commitKey: 1, + selStart: target.selectionStart, + selEnd: target.selectionEnd + } + }); + } + }; + this._dispatchEventFromSandbox(actions, jsEvent); + }); + element.addEventListener("keydown", (event) => { + elementData.commitKey = 1; + let commitKey = -1; + if (event.key === "Escape") { + commitKey = 0; + } else if (event.key === "Enter" && !this.data.multiLine) { + commitKey = 2; + } else if (event.key === "Tab") { + elementData.commitKey = 3; + } + if (commitKey === -1) { + return; + } + const { + value + } = event.target; + if (elementData.lastCommittedValue === value) { + return; + } + elementData.lastCommittedValue = value; + elementData.userValue = value; + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value, + willCommit: true, + commitKey, + selStart: event.target.selectionStart, + selEnd: event.target.selectionEnd + } + }); + }); + const _blurListener = blurListener; + blurListener = null; + element.addEventListener("blur", (event) => { + if (!elementData.focused || !event.relatedTarget) { + return; + } + if (!this.data.actions?.Blur) { + elementData.focused = false; + } + const { + target + } = event; + let { + value + } = target; + if (hasDateOrTime) { + if (value && datetimeType === "time") { + const parts = value.split(":").map((v) => parseInt(v, 10)); + value = new Date(2e3, 0, 1, parts[0], parts[1], parts[2] || 0).valueOf(); + target.step = ""; + } else { + if (!value.includes("T")) { + value = `${value}T00:00`; + } + value = new Date(value).valueOf(); + } + target.type = "text"; + } + elementData.userValue = value; + if (elementData.lastCommittedValue !== value) { + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value, + willCommit: true, + commitKey: elementData.commitKey, + selStart: event.target.selectionStart, + selEnd: event.target.selectionEnd + } + }); + } + _blurListener(event); + }); + if (this.data.actions?.Keystroke) { + element.addEventListener("beforeinput", (event) => { + elementData.lastCommittedValue = null; + const { + data, + target + } = event; + const { + value, + selectionStart, + selectionEnd + } = target; + let selStart = selectionStart, selEnd = selectionEnd; + switch (event.inputType) { + case "deleteWordBackward": { + const match = value.substring(0, selectionStart).match(/\w*[^\w]*$/); + if (match) { + selStart -= match[0].length; + } + break; + } + case "deleteWordForward": { + const match = value.substring(selectionStart).match(/^[^\w]*\w*/); + if (match) { + selEnd += match[0].length; + } + break; + } + case "deleteContentBackward": + if (selectionStart === selectionEnd) { + selStart -= 1; + } + break; + case "deleteContentForward": + if (selectionStart === selectionEnd) { + selEnd += 1; + } + break; + } + event.preventDefault(); + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value, + change: data || "", + willCommit: false, + selStart, + selEnd + } + }); + }); + } + this._setEventListeners(element, elementData, [["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], (event) => event.target.value); + } + if (blurListener) { + element.addEventListener("blur", blurListener); + } + if (this.data.comb) { + const fieldWidth = this.data.rect[2] - this.data.rect[0]; + const combWidth = fieldWidth / maxLen; + element.classList.add("comb"); + element.style.letterSpacing = `calc(${combWidth}px * var(--total-scale-factor) - 1ch)`; + } + } else { + element = document.createElement("div"); + element.textContent = this.data.fieldValue; + element.style.verticalAlign = "middle"; + element.style.display = "table-cell"; + if (this.data.hasOwnCanvas) { + element.hidden = true; + } + } + this._setTextStyle(element); + this._setBackgroundColor(element); + this._setDefaultPropertiesFromJS(element); + this.container.append(element); + return this.container; + } +} +class SignatureWidgetAnnotationElement extends WidgetAnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: !!parameters.data.hasOwnCanvas + }); + } +} +class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: parameters.renderForms + }); + } + render() { + const storage = this.annotationStorage; + const data = this.data; + const id = data.id; + let value = storage.getValue(id, { + value: data.exportValue === data.fieldValue + }).value; + if (typeof value === "string") { + value = value !== "Off"; + storage.setValue(id, { + value + }); + } + this.container.classList.add("buttonWidgetAnnotation", "checkBox"); + const element = document.createElement("input"); + GetElementsByNameSet.add(element); + element.setAttribute("data-element-id", id); + element.disabled = data.readOnly; + this._setRequired(element, this.data.required); + element.type = "checkbox"; + element.name = data.fieldName; + if (value) { + element.setAttribute("checked", true); + } + element.setAttribute("exportValue", data.exportValue); + element.tabIndex = 0; + element.addEventListener("change", (event) => { + const { + name, + checked + } = event.target; + for (const checkbox of this._getElementsByName(name, id)) { + const curChecked = checked && checkbox.exportValue === data.exportValue; + if (checkbox.domElement) { + checkbox.domElement.checked = curChecked; + } + storage.setValue(checkbox.id, { + value: curChecked + }); + } + storage.setValue(id, { + value: checked + }); + }); + element.addEventListener("resetform", (event) => { + const defaultValue = data.defaultFieldValue || "Off"; + event.target.checked = defaultValue === data.exportValue; + }); + if (this.enableScripting && this.hasJSActions) { + element.addEventListener("updatefromsandbox", (jsEvent) => { + const actions = { + value(event) { + event.target.checked = event.detail.value !== "Off"; + storage.setValue(id, { + value: event.target.checked + }); + } + }; + this._dispatchEventFromSandbox(actions, jsEvent); + }); + this._setEventListeners(element, null, [["change", "Validate"], ["change", "Action"], ["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], (event) => event.target.checked); + } + this._setBackgroundColor(element); + this._setDefaultPropertiesFromJS(element); + this.container.append(element); + return this.container; + } +} +class RadioButtonWidgetAnnotationElement extends WidgetAnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: parameters.renderForms + }); + } + render() { + this.container.classList.add("buttonWidgetAnnotation", "radioButton"); + const storage = this.annotationStorage; + const data = this.data; + const id = data.id; + let value = storage.getValue(id, { + value: data.fieldValue === data.buttonValue + }).value; + if (typeof value === "string") { + value = value !== data.buttonValue; + storage.setValue(id, { + value + }); + } + if (value) { + for (const radio of this._getElementsByName(data.fieldName, id)) { + storage.setValue(radio.id, { + value: false + }); + } + } + const element = document.createElement("input"); + GetElementsByNameSet.add(element); + element.setAttribute("data-element-id", id); + element.disabled = data.readOnly; + this._setRequired(element, this.data.required); + element.type = "radio"; + element.name = data.fieldName; + if (value) { + element.setAttribute("checked", true); + } + element.tabIndex = 0; + element.addEventListener("change", (event) => { + const { + name, + checked + } = event.target; + for (const radio of this._getElementsByName(name, id)) { + storage.setValue(radio.id, { + value: false + }); + } + storage.setValue(id, { + value: checked + }); + }); + element.addEventListener("resetform", (event) => { + const defaultValue = data.defaultFieldValue; + event.target.checked = defaultValue !== null && defaultValue !== void 0 && defaultValue === data.buttonValue; + }); + if (this.enableScripting && this.hasJSActions) { + const pdfButtonValue = data.buttonValue; + element.addEventListener("updatefromsandbox", (jsEvent) => { + const actions = { + value: (event) => { + const checked = pdfButtonValue === event.detail.value; + for (const radio of this._getElementsByName(event.target.name)) { + const curChecked = checked && radio.id === id; + if (radio.domElement) { + radio.domElement.checked = curChecked; + } + storage.setValue(radio.id, { + value: curChecked + }); + } + } + }; + this._dispatchEventFromSandbox(actions, jsEvent); + }); + this._setEventListeners(element, null, [["change", "Validate"], ["change", "Action"], ["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"]], (event) => event.target.checked); + } + this._setBackgroundColor(element); + this._setDefaultPropertiesFromJS(element); + this.container.append(element); + return this.container; + } +} +class PushButtonWidgetAnnotationElement extends LinkAnnotationElement { + constructor(parameters) { + super(parameters, { + ignoreBorder: parameters.data.hasAppearance + }); + } + render() { + const container = super.render(); + container.classList.add("buttonWidgetAnnotation", "pushButton"); + const linkElement = container.lastChild; + if (this.enableScripting && this.hasJSActions && linkElement) { + this._setDefaultPropertiesFromJS(linkElement); + linkElement.addEventListener("updatefromsandbox", (jsEvent) => { + this._dispatchEventFromSandbox({}, jsEvent); + }); + } + return container; + } +} +class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: parameters.renderForms + }); + } + render() { + this.container.classList.add("choiceWidgetAnnotation"); + const storage = this.annotationStorage; + const id = this.data.id; + const storedData = storage.getValue(id, { + value: this.data.fieldValue + }); + const selectElement = document.createElement("select"); + GetElementsByNameSet.add(selectElement); + selectElement.setAttribute("data-element-id", id); + selectElement.disabled = this.data.readOnly; + this._setRequired(selectElement, this.data.required); + selectElement.name = this.data.fieldName; + selectElement.tabIndex = 0; + let addAnEmptyEntry = this.data.combo && this.data.options.length > 0; + if (!this.data.combo) { + selectElement.size = this.data.options.length; + if (this.data.multiSelect) { + selectElement.multiple = true; + } + } + selectElement.addEventListener("resetform", (event) => { + const defaultValue = this.data.defaultFieldValue; + for (const option of selectElement.options) { + option.selected = option.value === defaultValue; + } + }); + for (const option of this.data.options) { + const optionElement = document.createElement("option"); + optionElement.textContent = option.displayValue; + optionElement.value = option.exportValue; + if (storedData.value.includes(option.exportValue)) { + optionElement.setAttribute("selected", true); + addAnEmptyEntry = false; + } + selectElement.append(optionElement); + } + let removeEmptyEntry = null; + if (addAnEmptyEntry) { + const noneOptionElement = document.createElement("option"); + noneOptionElement.value = " "; + noneOptionElement.setAttribute("hidden", true); + noneOptionElement.setAttribute("selected", true); + selectElement.prepend(noneOptionElement); + removeEmptyEntry = () => { + noneOptionElement.remove(); + selectElement.removeEventListener("input", removeEmptyEntry); + removeEmptyEntry = null; + }; + selectElement.addEventListener("input", removeEmptyEntry); + } + const getValue = (isExport) => { + const name = isExport ? "value" : "textContent"; + const { + options, + multiple + } = selectElement; + if (!multiple) { + return options.selectedIndex === -1 ? null : options[options.selectedIndex][name]; + } + return Array.prototype.filter.call(options, (option) => option.selected).map((option) => option[name]); + }; + let selectedValues = getValue(false); + const getItems = (event) => { + const options = event.target.options; + return Array.prototype.map.call(options, (option) => ({ + displayValue: option.textContent, + exportValue: option.value + })); + }; + if (this.enableScripting && this.hasJSActions) { + selectElement.addEventListener("updatefromsandbox", (jsEvent) => { + const actions = { + value(event) { + removeEmptyEntry?.(); + const value = event.detail.value; + const values = new Set(Array.isArray(value) ? value : [value]); + for (const option of selectElement.options) { + option.selected = values.has(option.value); + } + storage.setValue(id, { + value: getValue(true) + }); + selectedValues = getValue(false); + }, + multipleSelection(event) { + selectElement.multiple = true; + }, + remove(event) { + const options = selectElement.options; + const index = event.detail.remove; + options[index].selected = false; + selectElement.remove(index); + if (options.length > 0) { + const i = Array.prototype.findIndex.call(options, (option) => option.selected); + if (i === -1) { + options[0].selected = true; + } + } + storage.setValue(id, { + value: getValue(true), + items: getItems(event) + }); + selectedValues = getValue(false); + }, + clear(event) { + while (selectElement.length !== 0) { + selectElement.remove(0); + } + storage.setValue(id, { + value: null, + items: [] + }); + selectedValues = getValue(false); + }, + insert(event) { + const { + index, + displayValue, + exportValue + } = event.detail.insert; + const selectChild = selectElement.children[index]; + const optionElement = document.createElement("option"); + optionElement.textContent = displayValue; + optionElement.value = exportValue; + if (selectChild) { + selectChild.before(optionElement); + } else { + selectElement.append(optionElement); + } + storage.setValue(id, { + value: getValue(true), + items: getItems(event) + }); + selectedValues = getValue(false); + }, + items(event) { + const { + items + } = event.detail; + while (selectElement.length !== 0) { + selectElement.remove(0); + } + for (const item of items) { + const { + displayValue, + exportValue + } = item; + const optionElement = document.createElement("option"); + optionElement.textContent = displayValue; + optionElement.value = exportValue; + selectElement.append(optionElement); + } + if (selectElement.options.length > 0) { + selectElement.options[0].selected = true; + } + storage.setValue(id, { + value: getValue(true), + items: getItems(event) + }); + selectedValues = getValue(false); + }, + indices(event) { + const indices = new Set(event.detail.indices); + for (const option of event.target.options) { + option.selected = indices.has(option.index); + } + storage.setValue(id, { + value: getValue(true) + }); + selectedValues = getValue(false); + }, + editable(event) { + event.target.disabled = !event.detail.editable; + } + }; + this._dispatchEventFromSandbox(actions, jsEvent); + }); + selectElement.addEventListener("input", (event) => { + const exportValue = getValue(true); + const change = getValue(false); + storage.setValue(id, { + value: exportValue + }); + event.preventDefault(); + this.linkService.eventBus?.dispatch("dispatcheventinsandbox", { + source: this, + detail: { + id, + name: "Keystroke", + value: selectedValues, + change, + changeEx: exportValue, + willCommit: false, + commitKey: 1, + keyDown: false + } + }); + }); + this._setEventListeners(selectElement, null, [["focus", "Focus"], ["blur", "Blur"], ["mousedown", "Mouse Down"], ["mouseenter", "Mouse Enter"], ["mouseleave", "Mouse Exit"], ["mouseup", "Mouse Up"], ["input", "Action"], ["input", "Validate"]], (event) => event.target.value); + } else { + selectElement.addEventListener("input", function(event) { + storage.setValue(id, { + value: getValue(true) + }); + }); + } + if (this.data.combo) { + this._setTextStyle(selectElement); + } + this._setBackgroundColor(selectElement); + this._setDefaultPropertiesFromJS(selectElement); + this.container.append(selectElement); + return this.container; + } +} +class PopupAnnotationElement extends AnnotationElement { + constructor(parameters) { + const { + data, + elements, + parent + } = parameters; + const hasCommentManager = !!parent._commentManager; + super(parameters, { + isRenderable: !hasCommentManager && AnnotationElement._hasPopupData(data) + }); + this.elements = elements; + if (hasCommentManager && AnnotationElement._hasPopupData(data)) { + const popup = this.popup = this.#createPopup(); + for (const element of elements) { + element.popup = popup; + } + } else { + this.popup = null; + } + } + #createPopup() { + return new PopupElement({ + container: this.container, + color: this.data.color, + titleObj: this.data.titleObj, + modificationDate: this.data.modificationDate || this.data.creationDate, + contentsObj: this.data.contentsObj, + richText: this.data.richText, + rect: this.data.rect, + parentRect: this.data.parentRect || null, + parent: this.parent, + elements: this.elements, + open: this.data.open, + commentManager: this.parent._commentManager + }); + } + render() { + const { + container + } = this; + container.classList.add("popupAnnotation"); + container.role = "comment"; + const popup = this.popup = this.#createPopup(); + const elementIds = []; + for (const element of this.elements) { + element.popup = popup; + element.container.ariaHasPopup = "dialog"; + elementIds.push(element.data.id); + element.addHighlightArea(); + } + this.container.setAttribute("aria-controls", elementIds.map((id) => `${AnnotationPrefix}${id}`).join(",")); + return this.container; + } +} +class PopupElement { + #commentManager = null; + #boundKeyDown = this.#keyDown.bind(this); + #boundHide = this.#hide.bind(this); + #boundShow = this.#show.bind(this); + #boundToggle = this.#toggle.bind(this); + #color = null; + #container = null; + #contentsObj = null; + #dateObj = null; + #elements = null; + #parent = null; + #parentRect = null; + #pinned = false; + #popup = null; + #popupAbortController = null; + #position = null; + #commentButton = null; + #commentButtonPosition = null; + #popupPosition = null; + #rect = null; + #richText = null; + #titleObj = null; + #updates = null; + #wasVisible = false; + #firstElement = null; + #commentText = null; + constructor({ + container, + color, + elements, + titleObj, + modificationDate, + contentsObj, + richText, + parent, + rect, + parentRect, + open, + commentManager = null + }) { + this.#container = container; + this.#titleObj = titleObj; + this.#contentsObj = contentsObj; + this.#richText = richText; + this.#parent = parent; + this.#color = color; + this.#rect = rect; + this.#parentRect = parentRect; + this.#elements = elements; + this.#commentManager = commentManager; + this.#firstElement = elements[0]; + this.#dateObj = PDFDateString.toDateObject(modificationDate); + this.trigger = elements.flatMap((e) => e.getElementsToTriggerPopup()); + if (commentManager) { + this.renderCommentButton(); + } else { + this.#addEventListeners(); + this.#container.hidden = true; + if (open) { + this.#toggle(); + } + } + } + #addEventListeners() { + if (this.#popupAbortController) { + return; + } + this.#popupAbortController = new AbortController(); + const { + signal + } = this.#popupAbortController; + for (const element of this.trigger) { + element.addEventListener("click", this.#boundToggle, { + signal + }); + element.addEventListener("pointerenter", this.#boundShow, { + signal + }); + element.addEventListener("pointerleave", this.#boundHide, { + signal + }); + element.classList.add("popupTriggerArea"); + } + for (const element of this.#elements) { + element.container?.addEventListener("keydown", this.#boundKeyDown, { + signal + }); + } + } + #setCommentButtonPosition() { + const element = this.#elements.find((e) => e.hasCommentButton); + if (!element) { + return; + } + this.#commentButtonPosition = element._normalizePoint(element.commentButtonPosition); + } + renderCommentButton() { + if (this.#commentButton) { + return; + } + if (!this.#commentButtonPosition) { + this.#setCommentButtonPosition(); + } + if (!this.#commentButtonPosition) { + return; + } + const { + signal + } = this.#popupAbortController = new AbortController(); + const hasOwnButton = !!this.#firstElement.extraPopupElement; + const togglePopup = () => { + this.#commentManager.toggleCommentPopup(this, true, void 0, !hasOwnButton); + }; + const showPopup = () => { + this.#commentManager.toggleCommentPopup(this, false, true, !hasOwnButton); + }; + const hidePopup = () => { + this.#commentManager.toggleCommentPopup(this, false, false); + }; + if (!hasOwnButton) { + const button = this.#commentButton = document.createElement("button"); + button.className = "annotationCommentButton"; + const parentContainer = this.#firstElement.container; + button.style.zIndex = parentContainer.style.zIndex + 1; + button.tabIndex = 0; + button.ariaHasPopup = "dialog"; + button.ariaControls = "commentPopup"; + button.setAttribute("data-l10n-id", "pdfjs-show-comment-button"); + this.#updateColor(); + this.#updateCommentButtonPosition(); + button.addEventListener("keydown", this.#boundKeyDown, { + signal + }); + button.addEventListener("click", togglePopup, { + signal + }); + button.addEventListener("pointerenter", showPopup, { + signal + }); + button.addEventListener("pointerleave", hidePopup, { + signal + }); + parentContainer.after(button); + } else { + this.#commentButton = this.#firstElement.container; + for (const element of this.trigger) { + element.ariaHasPopup = "dialog"; + element.ariaControls = "commentPopup"; + element.addEventListener("keydown", this.#boundKeyDown, { + signal + }); + element.addEventListener("click", togglePopup, { + signal + }); + element.addEventListener("pointerenter", showPopup, { + signal + }); + element.addEventListener("pointerleave", hidePopup, { + signal + }); + element.classList.add("popupTriggerArea"); + } + } + } + #updateCommentButtonPosition() { + if (this.#firstElement.extraPopupElement && !this.#firstElement.editor) { + return; + } + this.renderCommentButton(); + const [x, y] = this.#commentButtonPosition; + const { + style + } = this.#commentButton; + style.left = `calc(${x}%)`; + style.top = `calc(${y}% - var(--comment-button-dim))`; + } + #updateColor() { + if (this.#firstElement.extraPopupElement) { + return; + } + this.renderCommentButton(); + this.#commentButton.style.backgroundColor = this.commentButtonColor || ""; + } + get commentButtonColor() { + const { + color, + opacity + } = this.#firstElement.commentData; + if (!color) { + return null; + } + return this.#parent._commentManager.makeCommentColor(color, opacity); + } + focusCommentButton() { + setTimeout(() => { + this.#commentButton?.focus(); + }, 0); + } + getData() { + const { + richText, + color, + opacity, + creationDate, + modificationDate + } = this.#firstElement.commentData; + return { + contentsObj: { + str: this.comment + }, + richText, + color, + opacity, + creationDate, + modificationDate + }; + } + get elementBeforePopup() { + return this.#commentButton; + } + get comment() { + this.#commentText ||= this.#firstElement.commentText; + return this.#commentText; + } + set comment(text) { + if (text === this.comment) { + return; + } + this.#firstElement.commentText = this.#commentText = text; + } + get parentBoundingClientRect() { + return this.#firstElement.layer.getBoundingClientRect(); + } + setCommentButtonStates({ + selected, + hasPopup + }) { + if (!this.#commentButton) { + return; + } + this.#commentButton.classList.toggle("selected", selected); + this.#commentButton.ariaExpanded = hasPopup; + } + setSelectedCommentButton(selected) { + this.#commentButton.classList.toggle("selected", selected); + } + get commentPopupPosition() { + if (this.#popupPosition) { + return this.#popupPosition; + } + const { + x, + y, + height + } = this.#commentButton.getBoundingClientRect(); + const { + x: parentX, + y: parentY, + width: parentWidth, + height: parentHeight + } = this.#firstElement.layer.getBoundingClientRect(); + return [(x - parentX) / parentWidth, (y + height - parentY) / parentHeight]; + } + set commentPopupPosition(pos) { + this.#popupPosition = pos; + } + hasDefaultPopupPosition() { + return this.#popupPosition === null; + } + get commentButtonPosition() { + return this.#commentButtonPosition; + } + get commentButtonWidth() { + return this.#commentButton.getBoundingClientRect().width / this.parentBoundingClientRect.width; + } + editComment(options) { + const [posX, posY] = this.#popupPosition || this.commentButtonPosition.map((x) => x / 100); + const parentDimensions = this.parentBoundingClientRect; + const { + x: parentX, + y: parentY, + width: parentWidth, + height: parentHeight + } = parentDimensions; + this.#commentManager.showDialog(null, this, parentX + posX * parentWidth, parentY + posY * parentHeight, { + ...options, + parentDimensions + }); + } + render() { + if (this.#popup) { + return; + } + const popup = this.#popup = document.createElement("div"); + popup.className = "popup"; + if (this.#color) { + const baseColor = popup.style.outlineColor = Util.makeHexColor(...this.#color); + popup.style.backgroundColor = `color-mix(in srgb, ${baseColor} 30%, white)`; + } + const header = document.createElement("span"); + header.className = "header"; + if (this.#titleObj?.str) { + const title = document.createElement("span"); + title.className = "title"; + header.append(title); + ({ + dir: title.dir, + str: title.textContent + } = this.#titleObj); + } + popup.append(header); + if (this.#dateObj) { + const modificationDate = document.createElement("time"); + modificationDate.className = "popupDate"; + modificationDate.setAttribute("data-l10n-id", "pdfjs-annotation-date-time-string"); + modificationDate.setAttribute("data-l10n-args", JSON.stringify({ + dateObj: this.#dateObj.valueOf() + })); + modificationDate.dateTime = this.#dateObj.toISOString(); + header.append(modificationDate); + } + renderRichText({ + html: this.#html || this.#contentsObj.str, + dir: this.#contentsObj?.dir, + className: "popupContent" + }, popup); + this.#container.append(popup); + } + get #html() { + const richText = this.#richText; + const contentsObj = this.#contentsObj; + if (richText?.str && (!contentsObj?.str || contentsObj.str === richText.str)) { + return this.#richText.html || null; + } + return null; + } + get #fontSize() { + return this.#html?.attributes?.style?.fontSize || 0; + } + get #fontColor() { + return this.#html?.attributes?.style?.color || null; + } + #makePopupContent(text) { + const popupLines = []; + const popupContent = { + str: text, + html: { + name: "div", + attributes: { + dir: "auto" + }, + children: [{ + name: "p", + children: popupLines + }] + } + }; + const lineAttributes = { + style: { + color: this.#fontColor, + fontSize: this.#fontSize ? `calc(${this.#fontSize}px * var(--total-scale-factor))` : "" + } + }; + for (const line of text.split("\n")) { + popupLines.push({ + name: "span", + value: line, + attributes: lineAttributes + }); + } + return popupContent; + } + #keyDown(event) { + if (event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) { + return; + } + if (event.key === "Enter" || event.key === "Escape" && this.#pinned) { + this.#toggle(); + } + } + updateEdited({ + rect, + popup, + deleted + }) { + if (this.#commentManager) { + if (deleted) { + this.remove(); + this.#commentText = null; + } else if (popup) { + if (popup.deleted) { + this.remove(); + } else { + this.#updateColor(); + this.#commentText = popup.text; + } + } + if (rect) { + this.#commentButtonPosition = null; + this.#setCommentButtonPosition(); + this.#updateCommentButtonPosition(); + } + return; + } + if (deleted || popup?.deleted) { + this.remove(); + return; + } + this.#addEventListeners(); + this.#updates ||= { + contentsObj: this.#contentsObj, + richText: this.#richText + }; + if (rect) { + this.#position = null; + } + if (popup && popup.text) { + this.#richText = this.#makePopupContent(popup.text); + this.#dateObj = PDFDateString.toDateObject(popup.date); + this.#contentsObj = null; + } + this.#popup?.remove(); + this.#popup = null; + } + resetEdited() { + if (!this.#updates) { + return; + } + ({ + contentsObj: this.#contentsObj, + richText: this.#richText + } = this.#updates); + this.#updates = null; + this.#popup?.remove(); + this.#popup = null; + this.#position = null; + } + remove() { + this.#popupAbortController?.abort(); + this.#popupAbortController = null; + this.#popup?.remove(); + this.#popup = null; + this.#wasVisible = false; + this.#pinned = false; + this.#commentButton?.remove(); + this.#commentButton = null; + if (this.trigger) { + for (const element of this.trigger) { + element.classList.remove("popupTriggerArea"); + } + } + } + #setPosition() { + if (this.#position !== null) { + return; + } + const { + page: { + view + }, + viewport: { + rawDims: { + pageWidth, + pageHeight, + pageX, + pageY + } + } + } = this.#parent; + let useParentRect = !!this.#parentRect; + let rect = useParentRect ? this.#parentRect : this.#rect; + for (const element of this.#elements) { + if (!rect || Util.intersect(element.data.rect, rect) !== null) { + rect = element.data.rect; + useParentRect = true; + break; + } + } + const normalizedRect = Util.normalizeRect([rect[0], view[3] - rect[1] + view[1], rect[2], view[3] - rect[3] + view[1]]); + const HORIZONTAL_SPACE_AFTER_ANNOTATION = 5; + const parentWidth = useParentRect ? rect[2] - rect[0] + HORIZONTAL_SPACE_AFTER_ANNOTATION : 0; + const popupLeft = normalizedRect[0] + parentWidth; + const popupTop = normalizedRect[1]; + this.#position = [100 * (popupLeft - pageX) / pageWidth, 100 * (popupTop - pageY) / pageHeight]; + const { + style + } = this.#container; + style.left = `${this.#position[0]}%`; + style.top = `${this.#position[1]}%`; + } + #toggle() { + if (this.#commentManager) { + this.#commentManager.toggleCommentPopup(this, false); + return; + } + this.#pinned = !this.#pinned; + if (this.#pinned) { + this.#show(); + this.#container.addEventListener("click", this.#boundToggle); + this.#container.addEventListener("keydown", this.#boundKeyDown); + } else { + this.#hide(); + this.#container.removeEventListener("click", this.#boundToggle); + this.#container.removeEventListener("keydown", this.#boundKeyDown); + } + } + #show() { + if (!this.#popup) { + this.render(); + } + if (!this.isVisible) { + this.#setPosition(); + this.#container.hidden = false; + this.#container.style.zIndex = parseInt(this.#container.style.zIndex) + 1e3; + } else if (this.#pinned) { + this.#container.classList.add("focused"); + } + } + #hide() { + this.#container.classList.remove("focused"); + if (this.#pinned || !this.isVisible) { + return; + } + this.#container.hidden = true; + this.#container.style.zIndex = parseInt(this.#container.style.zIndex) - 1e3; + } + forceHide() { + this.#wasVisible = this.isVisible; + if (!this.#wasVisible) { + return; + } + this.#container.hidden = true; + } + maybeShow() { + if (this.#commentManager) { + return; + } + this.#addEventListeners(); + if (!this.#wasVisible) { + return; + } + if (!this.#popup) { + this.#show(); + } + this.#wasVisible = false; + this.#container.hidden = false; + } + get isVisible() { + if (this.#commentManager) { + return false; + } + return this.#container.hidden === false; + } +} +class FreeTextAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + this.textContent = parameters.data.textContent; + this.textPosition = parameters.data.textPosition; + this.annotationEditorType = AnnotationEditorType.FREETEXT; + } + render() { + this.container.classList.add("freeTextAnnotation"); + if (this.textContent) { + const content = document.createElement("div"); + content.classList.add("annotationTextContent"); + content.setAttribute("role", "comment"); + for (const line of this.textContent) { + const lineSpan = document.createElement("span"); + lineSpan.textContent = line; + content.append(lineSpan); + } + this.container.append(content); + } + if (!this.data.popupRef && this.hasPopupData) { + this._createPopup(); + } + this._editOnDoubleClick(); + return this.container; + } +} +class LineAnnotationElement extends AnnotationElement { + #line = null; + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + } + render() { + this.container.classList.add("lineAnnotation"); + const { + data, + width, + height + } = this; + const svg = this.svgFactory.create(width, height, true); + const line = this.#line = this.svgFactory.createElement("svg:line"); + line.setAttribute("x1", data.rect[2] - data.lineCoordinates[0]); + line.setAttribute("y1", data.rect[3] - data.lineCoordinates[1]); + line.setAttribute("x2", data.rect[2] - data.lineCoordinates[2]); + line.setAttribute("y2", data.rect[3] - data.lineCoordinates[3]); + line.setAttribute("stroke-width", data.borderStyle.width || 1); + line.setAttribute("stroke", "transparent"); + line.setAttribute("fill", "transparent"); + svg.append(line); + this.container.append(svg); + if (!data.popupRef && this.hasPopupData) { + this._createPopup(); + } + return this.container; + } + getElementsToTriggerPopup() { + return this.#line; + } + addHighlightArea() { + this.container.classList.add("highlightArea"); + } +} +class SquareAnnotationElement extends AnnotationElement { + #square = null; + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + } + render() { + this.container.classList.add("squareAnnotation"); + const { + data, + width, + height + } = this; + const svg = this.svgFactory.create(width, height, true); + const borderWidth = data.borderStyle.width; + const square = this.#square = this.svgFactory.createElement("svg:rect"); + square.setAttribute("x", borderWidth / 2); + square.setAttribute("y", borderWidth / 2); + square.setAttribute("width", width - borderWidth); + square.setAttribute("height", height - borderWidth); + square.setAttribute("stroke-width", borderWidth || 1); + square.setAttribute("stroke", "transparent"); + square.setAttribute("fill", "transparent"); + svg.append(square); + this.container.append(svg); + if (!data.popupRef && this.hasPopupData) { + this._createPopup(); + } + return this.container; + } + getElementsToTriggerPopup() { + return this.#square; + } + addHighlightArea() { + this.container.classList.add("highlightArea"); + } +} +class CircleAnnotationElement extends AnnotationElement { + #circle = null; + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + } + render() { + this.container.classList.add("circleAnnotation"); + const { + data, + width, + height + } = this; + const svg = this.svgFactory.create(width, height, true); + const borderWidth = data.borderStyle.width; + const circle = this.#circle = this.svgFactory.createElement("svg:ellipse"); + circle.setAttribute("cx", width / 2); + circle.setAttribute("cy", height / 2); + circle.setAttribute("rx", width / 2 - borderWidth / 2); + circle.setAttribute("ry", height / 2 - borderWidth / 2); + circle.setAttribute("stroke-width", borderWidth || 1); + circle.setAttribute("stroke", "transparent"); + circle.setAttribute("fill", "transparent"); + svg.append(circle); + this.container.append(svg); + if (!data.popupRef && this.hasPopupData) { + this._createPopup(); + } + return this.container; + } + getElementsToTriggerPopup() { + return this.#circle; + } + addHighlightArea() { + this.container.classList.add("highlightArea"); + } +} +class PolylineAnnotationElement extends AnnotationElement { + #polyline = null; + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + this.containerClassName = "polylineAnnotation"; + this.svgElementName = "svg:polyline"; + } + render() { + this.container.classList.add(this.containerClassName); + const { + data: { + rect, + vertices, + borderStyle, + popupRef + }, + width, + height + } = this; + if (!vertices) { + return this.container; + } + const svg = this.svgFactory.create(width, height, true); + let points = []; + for (let i = 0, ii = vertices.length; i < ii; i += 2) { + const x = vertices[i] - rect[0]; + const y = rect[3] - vertices[i + 1]; + points.push(`${x},${y}`); + } + points = points.join(" "); + const polyline = this.#polyline = this.svgFactory.createElement(this.svgElementName); + polyline.setAttribute("points", points); + polyline.setAttribute("stroke-width", borderStyle.width || 1); + polyline.setAttribute("stroke", "transparent"); + polyline.setAttribute("fill", "transparent"); + svg.append(polyline); + this.container.append(svg); + if (!popupRef && this.hasPopupData) { + this._createPopup(); + } + return this.container; + } + getElementsToTriggerPopup() { + return this.#polyline; + } + addHighlightArea() { + this.container.classList.add("highlightArea"); + } +} +class PolygonAnnotationElement extends PolylineAnnotationElement { + constructor(parameters) { + super(parameters); + this.containerClassName = "polygonAnnotation"; + this.svgElementName = "svg:polygon"; + } +} +class CaretAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + } + render() { + this.container.classList.add("caretAnnotation"); + if (!this.data.popupRef && this.hasPopupData) { + this._createPopup(); + } + return this.container; + } +} +class InkAnnotationElement extends AnnotationElement { + #polylinesGroupElement = null; + #polylines = []; + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + this.containerClassName = "inkAnnotation"; + this.svgElementName = "svg:polyline"; + this.annotationEditorType = this.data.it === "InkHighlight" ? AnnotationEditorType.HIGHLIGHT : AnnotationEditorType.INK; + } + #getTransform(rotation, rect) { + switch (rotation) { + case 90: + return { + transform: `rotate(90) translate(${-rect[0]},${rect[1]}) scale(1,-1)`, + width: rect[3] - rect[1], + height: rect[2] - rect[0] + }; + case 180: + return { + transform: `rotate(180) translate(${-rect[2]},${rect[1]}) scale(1,-1)`, + width: rect[2] - rect[0], + height: rect[3] - rect[1] + }; + case 270: + return { + transform: `rotate(270) translate(${-rect[2]},${rect[3]}) scale(1,-1)`, + width: rect[3] - rect[1], + height: rect[2] - rect[0] + }; + default: + return { + transform: `translate(${-rect[0]},${rect[3]}) scale(1,-1)`, + width: rect[2] - rect[0], + height: rect[3] - rect[1] + }; + } + } + render() { + this.container.classList.add(this.containerClassName); + const { + data: { + rect, + rotation, + inkLists, + borderStyle, + popupRef + } + } = this; + const { + transform, + width, + height + } = this.#getTransform(rotation, rect); + const svg = this.svgFactory.create(width, height, true); + const g = this.#polylinesGroupElement = this.svgFactory.createElement("svg:g"); + svg.append(g); + g.setAttribute("stroke-width", borderStyle.width || 1); + g.setAttribute("stroke-linecap", "round"); + g.setAttribute("stroke-linejoin", "round"); + g.setAttribute("stroke-miterlimit", 10); + g.setAttribute("stroke", "transparent"); + g.setAttribute("fill", "transparent"); + g.setAttribute("transform", transform); + for (let i = 0, ii = inkLists.length; i < ii; i++) { + const polyline = this.svgFactory.createElement(this.svgElementName); + this.#polylines.push(polyline); + polyline.setAttribute("points", inkLists[i].join(",")); + g.append(polyline); + } + if (!popupRef && this.hasPopupData) { + this._createPopup(); + } + this.container.append(svg); + this._editOnDoubleClick(); + return this.container; + } + updateEdited(params) { + super.updateEdited(params); + const { + thickness, + points, + rect + } = params; + const g = this.#polylinesGroupElement; + if (thickness >= 0) { + g.setAttribute("stroke-width", thickness || 1); + } + if (points) { + for (let i = 0, ii = this.#polylines.length; i < ii; i++) { + this.#polylines[i].setAttribute("points", points[i].join(",")); + } + } + if (rect) { + const { + transform, + width, + height + } = this.#getTransform(this.data.rotation, rect); + const root = g.parentElement; + root.setAttribute("viewBox", `0 0 ${width} ${height}`); + g.setAttribute("transform", transform); + } + } + getElementsToTriggerPopup() { + return this.#polylines; + } + addHighlightArea() { + this.container.classList.add("highlightArea"); + } +} +class HighlightAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true, + createQuadrilaterals: true + }); + this.annotationEditorType = AnnotationEditorType.HIGHLIGHT; + } + render() { + const { + data: { + overlaidText, + popupRef + } + } = this; + if (!popupRef && this.hasPopupData) { + this._createPopup(); + } + this.container.classList.add("highlightAnnotation"); + this._editOnDoubleClick(); + if (overlaidText) { + const mark = document.createElement("mark"); + mark.classList.add("overlaidText"); + mark.textContent = overlaidText; + this.container.append(mark); + } + return this.container; + } +} +class UnderlineAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true, + createQuadrilaterals: true + }); + } + render() { + const { + data: { + overlaidText, + popupRef + } + } = this; + if (!popupRef && this.hasPopupData) { + this._createPopup(); + } + this.container.classList.add("underlineAnnotation"); + if (overlaidText) { + const underline = document.createElement("u"); + underline.classList.add("overlaidText"); + underline.textContent = overlaidText; + this.container.append(underline); + } + return this.container; + } +} +class SquigglyAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true, + createQuadrilaterals: true + }); + } + render() { + const { + data: { + overlaidText, + popupRef + } + } = this; + if (!popupRef && this.hasPopupData) { + this._createPopup(); + } + this.container.classList.add("squigglyAnnotation"); + if (overlaidText) { + const underline = document.createElement("u"); + underline.classList.add("overlaidText"); + underline.textContent = overlaidText; + this.container.append(underline); + } + return this.container; + } +} +class StrikeOutAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true, + createQuadrilaterals: true + }); + } + render() { + const { + data: { + overlaidText, + popupRef + } + } = this; + if (!popupRef && this.hasPopupData) { + this._createPopup(); + } + this.container.classList.add("strikeoutAnnotation"); + if (overlaidText) { + const strikeout = document.createElement("s"); + strikeout.classList.add("overlaidText"); + strikeout.textContent = overlaidText; + this.container.append(strikeout); + } + return this.container; + } +} +class StampAnnotationElement extends AnnotationElement { + constructor(parameters) { + super(parameters, { + isRenderable: true, + ignoreBorder: true + }); + this.annotationEditorType = AnnotationEditorType.STAMP; + } + render() { + this.container.classList.add("stampAnnotation"); + this.container.setAttribute("role", "img"); + if (!this.data.popupRef && this.hasPopupData) { + this._createPopup(); + } + this._editOnDoubleClick(); + return this.container; + } +} +class FileAttachmentAnnotationElement extends AnnotationElement { + #trigger = null; + constructor(parameters) { + super(parameters, { + isRenderable: true + }); + const { + file + } = this.data; + this.filename = file.filename; + this.content = file.content; + this.linkService.eventBus?.dispatch("fileattachmentannotation", { + source: this, + ...file + }); + } + render() { + this.container.classList.add("fileAttachmentAnnotation"); + const { + container, + data + } = this; + let trigger; + if (data.hasAppearance || data.fillAlpha === 0) { + trigger = document.createElement("div"); + } else { + trigger = document.createElement("img"); + trigger.src = `${this.imageResourcesPath}annotation-${/paperclip/i.test(data.name) ? "paperclip" : "pushpin"}.svg`; + if (data.fillAlpha && data.fillAlpha < 1) { + trigger.style = `filter: opacity(${Math.round(data.fillAlpha * 100)}%);`; + } + } + trigger.addEventListener("dblclick", this.#download.bind(this)); + this.#trigger = trigger; + const { + isMac + } = util_FeatureTest.platform; + container.addEventListener("keydown", (evt) => { + if (evt.key === "Enter" && (isMac ? evt.metaKey : evt.ctrlKey)) { + this.#download(); + } + }); + if (!data.popupRef && this.hasPopupData) { + this._createPopup(); + } else { + trigger.classList.add("popupTriggerArea"); + } + container.append(trigger); + return container; + } + getElementsToTriggerPopup() { + return this.#trigger; + } + addHighlightArea() { + this.container.classList.add("highlightArea"); + } + #download() { + this.downloadManager?.openOrDownloadData(this.content, this.filename); + } +} +class AnnotationLayer { + #accessibilityManager = null; + #annotationCanvasMap = null; + #annotationStorage = null; + #editableAnnotations = /* @__PURE__ */ new Map(); + #structTreeLayer = null; + #linkService = null; + constructor({ + div, + accessibilityManager, + annotationCanvasMap, + annotationEditorUIManager, + page, + viewport, + structTreeLayer, + commentManager, + linkService, + annotationStorage + }) { + this.div = div; + this.#accessibilityManager = accessibilityManager; + this.#annotationCanvasMap = annotationCanvasMap; + this.#structTreeLayer = structTreeLayer || null; + this.#linkService = linkService || null; + this.#annotationStorage = annotationStorage || new AnnotationStorage(); + this.page = page; + this.viewport = viewport; + this.zIndex = 0; + this._annotationEditorUIManager = annotationEditorUIManager; + this._commentManager = commentManager || null; + } + hasEditableAnnotations() { + return this.#editableAnnotations.size > 0; + } + async #appendElement(element, id, popupElements) { + const contentElement = element.firstChild || element; + const annotationId = contentElement.id = `${AnnotationPrefix}${id}`; + const ariaAttributes = await this.#structTreeLayer?.getAriaAttributes(annotationId); + if (ariaAttributes) { + for (const [key, value] of ariaAttributes) { + contentElement.setAttribute(key, value); + } + } + if (popupElements) { + popupElements.at(-1).container.after(element); + } else { + this.div.append(element); + this.#accessibilityManager?.moveElementInDOM(this.div, element, contentElement, false); + } + } + async render(params) { + const { + annotations + } = params; + const layer = this.div; + setLayerDimensions(layer, this.viewport); + const popupToElements = /* @__PURE__ */ new Map(); + const elementParams = { + data: null, + layer, + linkService: this.#linkService, + downloadManager: params.downloadManager, + imageResourcesPath: params.imageResourcesPath || "", + renderForms: params.renderForms !== false, + svgFactory: new DOMSVGFactory(), + annotationStorage: this.#annotationStorage, + enableComment: params.enableComment === true, + enableScripting: params.enableScripting === true, + hasJSActions: params.hasJSActions, + fieldObjects: params.fieldObjects, + parent: this, + elements: null + }; + for (const data of annotations) { + if (data.noHTML) { + continue; + } + const isPopupAnnotation = data.annotationType === AnnotationType.POPUP; + if (!isPopupAnnotation) { + if (data.rect[2] === data.rect[0] || data.rect[3] === data.rect[1]) { + continue; + } + } else { + const elements = popupToElements.get(data.id); + if (!elements) { + continue; + } + elementParams.elements = elements; + } + elementParams.data = data; + const element = AnnotationElementFactory.create(elementParams); + if (!element.isRenderable) { + continue; + } + if (!isPopupAnnotation && data.popupRef) { + const elements = popupToElements.get(data.popupRef); + if (!elements) { + popupToElements.set(data.popupRef, [element]); + } else { + elements.push(element); + } + } + const rendered = element.render(); + if (data.hidden) { + rendered.style.visibility = "hidden"; + } + await this.#appendElement(rendered, data.id, elementParams.elements); + element.extraPopupElement?.popup?.renderCommentButton(); + if (element._isEditable) { + this.#editableAnnotations.set(element.data.id, element); + this._annotationEditorUIManager?.renderAnnotationElement(element); + } + } + this.#setAnnotationCanvasMap(); + } + async addLinkAnnotations(annotations) { + const elementParams = { + data: null, + layer: this.div, + linkService: this.#linkService, + svgFactory: new DOMSVGFactory(), + parent: this + }; + for (const data of annotations) { + data.borderStyle ||= AnnotationLayer._defaultBorderStyle; + elementParams.data = data; + const element = AnnotationElementFactory.create(elementParams); + if (!element.isRenderable) { + continue; + } + const rendered = element.render(); + await this.#appendElement(rendered, data.id, null); + } + } + update({ + viewport + }) { + const layer = this.div; + this.viewport = viewport; + setLayerDimensions(layer, { + rotation: viewport.rotation + }); + this.#setAnnotationCanvasMap(); + layer.hidden = false; + } + #setAnnotationCanvasMap() { + if (!this.#annotationCanvasMap) { + return; + } + const layer = this.div; + for (const [id, canvas] of this.#annotationCanvasMap) { + const element = layer.querySelector(`[data-annotation-id="${id}"]`); + if (!element) { + continue; + } + canvas.className = "annotationContent"; + const { + firstChild + } = element; + if (!firstChild) { + element.append(canvas); + } else if (firstChild.nodeName === "CANVAS") { + firstChild.replaceWith(canvas); + } else if (!firstChild.classList.contains("annotationContent")) { + firstChild.before(canvas); + } else { + firstChild.after(canvas); + } + const editableAnnotation = this.#editableAnnotations.get(id); + if (!editableAnnotation) { + continue; + } + if (editableAnnotation._hasNoCanvas) { + this._annotationEditorUIManager?.setMissingCanvas(id, element.id, canvas); + editableAnnotation._hasNoCanvas = false; + } else { + editableAnnotation.canvas = canvas; + } + } + this.#annotationCanvasMap.clear(); + } + getEditableAnnotations() { + return Array.from(this.#editableAnnotations.values()); + } + getEditableAnnotation(id) { + return this.#editableAnnotations.get(id); + } + addFakeAnnotation(editor) { + const { + div + } = this; + const { + id, + rotation + } = editor; + const element = new EditorAnnotationElement({ + data: { + id, + rect: editor.getPDFRect(), + rotation + }, + editor, + layer: div, + parent: this, + enableComment: !!this._commentManager, + linkService: this.#linkService, + annotationStorage: this.#annotationStorage + }); + const htmlElement = element.render(); + div.append(htmlElement); + this.#accessibilityManager?.moveElementInDOM(div, htmlElement, htmlElement, false); + element.createOrUpdatePopup(); + return element; + } + static get _defaultBorderStyle() { + return shadow(this, "_defaultBorderStyle", Object.freeze({ + width: 1, + rawWidth: 1, + style: AnnotationBorderStyleType.SOLID, + dashArray: [3], + horizontalCornerRadius: 0, + verticalCornerRadius: 0 + })); + } +} +const EOL_PATTERN = /\r\n?|\n/g; +class FreeTextEditor extends AnnotationEditor { + #content = ""; + #editorDivId = `${this.id}-editor`; + #editModeAC = null; + #fontSize; + _colorPicker = null; + static _freeTextDefaultContent = ""; + static _internalPadding = 0; + static _defaultColor = null; + static _defaultFontSize = 10; + static get _keyboardManager() { + const proto = FreeTextEditor.prototype; + const arrowChecker = (self2) => self2.isEmpty(); + const small = AnnotationEditorUIManager.TRANSLATE_SMALL; + const big = AnnotationEditorUIManager.TRANSLATE_BIG; + return shadow(this, "_keyboardManager", new KeyboardManager([[["ctrl+s", "mac+meta+s", "ctrl+p", "mac+meta+p"], proto.commitOrRemove, { + bubbles: true + }], [["ctrl+Enter", "mac+meta+Enter", "Escape", "mac+Escape"], proto.commitOrRemove], [["ArrowLeft", "mac+ArrowLeft"], proto._translateEmpty, { + args: [-small, 0], + checker: arrowChecker + }], [["ctrl+ArrowLeft", "mac+shift+ArrowLeft"], proto._translateEmpty, { + args: [-big, 0], + checker: arrowChecker + }], [["ArrowRight", "mac+ArrowRight"], proto._translateEmpty, { + args: [small, 0], + checker: arrowChecker + }], [["ctrl+ArrowRight", "mac+shift+ArrowRight"], proto._translateEmpty, { + args: [big, 0], + checker: arrowChecker + }], [["ArrowUp", "mac+ArrowUp"], proto._translateEmpty, { + args: [0, -small], + checker: arrowChecker + }], [["ctrl+ArrowUp", "mac+shift+ArrowUp"], proto._translateEmpty, { + args: [0, -big], + checker: arrowChecker + }], [["ArrowDown", "mac+ArrowDown"], proto._translateEmpty, { + args: [0, small], + checker: arrowChecker + }], [["ctrl+ArrowDown", "mac+shift+ArrowDown"], proto._translateEmpty, { + args: [0, big], + checker: arrowChecker + }]])); + } + static _type = "freetext"; + static _editorType = AnnotationEditorType.FREETEXT; + constructor(params) { + super({ + ...params, + name: "freeTextEditor" + }); + this.color = params.color || FreeTextEditor._defaultColor || AnnotationEditor._defaultLineColor; + this.#fontSize = params.fontSize || FreeTextEditor._defaultFontSize; + if (!this.annotationElementId) { + this._uiManager.a11yAlert("pdfjs-editor-freetext-added-alert"); + } + } + static initialize(l10n, uiManager) { + AnnotationEditor.initialize(l10n, uiManager); + const style = getComputedStyle(document.documentElement); + this._internalPadding = parseFloat(style.getPropertyValue("--freetext-padding")); + } + static updateDefaultParams(type, value) { + switch (type) { + case AnnotationEditorParamsType.FREETEXT_SIZE: + FreeTextEditor._defaultFontSize = value; + break; + case AnnotationEditorParamsType.FREETEXT_COLOR: + FreeTextEditor._defaultColor = value; + break; + } + } + updateParams(type, value) { + switch (type) { + case AnnotationEditorParamsType.FREETEXT_SIZE: + this.#updateFontSize(value); + break; + case AnnotationEditorParamsType.FREETEXT_COLOR: + this.#updateColor(value); + break; + } + } + static get defaultPropertiesToUpdate() { + return [[AnnotationEditorParamsType.FREETEXT_SIZE, FreeTextEditor._defaultFontSize], [AnnotationEditorParamsType.FREETEXT_COLOR, FreeTextEditor._defaultColor || AnnotationEditor._defaultLineColor]]; + } + get propertiesToUpdate() { + return [[AnnotationEditorParamsType.FREETEXT_SIZE, this.#fontSize], [AnnotationEditorParamsType.FREETEXT_COLOR, this.color]]; + } + get toolbarButtons() { + this._colorPicker ||= new BasicColorPicker(this); + return [["colorPicker", this._colorPicker]]; + } + get colorType() { + return AnnotationEditorParamsType.FREETEXT_COLOR; + } + #updateFontSize(fontSize) { + const setFontsize = (size) => { + this.editorDiv.style.fontSize = `calc(${size}px * var(--total-scale-factor))`; + this.translate(0, -(size - this.#fontSize) * this.parentScale); + this.#fontSize = size; + this.#setEditorDimensions(); + }; + const savedFontsize = this.#fontSize; + this.addCommands({ + cmd: setFontsize.bind(this, fontSize), + undo: setFontsize.bind(this, savedFontsize), + post: this._uiManager.updateUI.bind(this._uiManager, this), + mustExec: true, + type: AnnotationEditorParamsType.FREETEXT_SIZE, + overwriteIfSameType: true, + keepUndo: true + }); + } + onUpdatedColor() { + this.editorDiv.style.color = this.color; + this._colorPicker?.update(this.color); + super.onUpdatedColor(); + } + #updateColor(color) { + const setColor = (col) => { + this.color = col; + this.onUpdatedColor(); + }; + const savedColor = this.color; + this.addCommands({ + cmd: setColor.bind(this, color), + undo: setColor.bind(this, savedColor), + post: this._uiManager.updateUI.bind(this._uiManager, this), + mustExec: true, + type: AnnotationEditorParamsType.FREETEXT_COLOR, + overwriteIfSameType: true, + keepUndo: true + }); + } + _translateEmpty(x, y) { + this._uiManager.translateSelectedEditors(x, y, true); + } + getInitialTranslation() { + const scale = this.parentScale; + return [-FreeTextEditor._internalPadding * scale, -(FreeTextEditor._internalPadding + this.#fontSize) * scale]; + } + rebuild() { + if (!this.parent) { + return; + } + super.rebuild(); + if (this.div === null) { + return; + } + if (!this.isAttachedToDOM) { + this.parent.add(this); + } + } + enableEditMode() { + if (!super.enableEditMode()) { + return false; + } + this.overlayDiv.classList.remove("enabled"); + this.editorDiv.contentEditable = true; + this._isDraggable = false; + this.div.removeAttribute("aria-activedescendant"); + this.#editModeAC = new AbortController(); + const signal = this._uiManager.combinedSignal(this.#editModeAC); + this.editorDiv.addEventListener("keydown", this.editorDivKeydown.bind(this), { + signal + }); + this.editorDiv.addEventListener("focus", this.editorDivFocus.bind(this), { + signal + }); + this.editorDiv.addEventListener("blur", this.editorDivBlur.bind(this), { + signal + }); + this.editorDiv.addEventListener("input", this.editorDivInput.bind(this), { + signal + }); + this.editorDiv.addEventListener("paste", this.editorDivPaste.bind(this), { + signal + }); + return true; + } + disableEditMode() { + if (!super.disableEditMode()) { + return false; + } + this.overlayDiv.classList.add("enabled"); + this.editorDiv.contentEditable = false; + this.div.setAttribute("aria-activedescendant", this.#editorDivId); + this._isDraggable = true; + this.#editModeAC?.abort(); + this.#editModeAC = null; + this.div.focus({ + preventScroll: true + }); + this.isEditing = false; + this.parent.div.classList.add("freetextEditing"); + return true; + } + focusin(event) { + if (!this._focusEventsAllowed) { + return; + } + super.focusin(event); + if (event.target !== this.editorDiv) { + this.editorDiv.focus(); + } + } + onceAdded(focus) { + if (this.width) { + return; + } + this.enableEditMode(); + if (focus) { + this.editorDiv.focus(); + } + if (this._initialOptions?.isCentered) { + this.center(); + } + this._initialOptions = null; + } + isEmpty() { + return !this.editorDiv || this.editorDiv.innerText.trim() === ""; + } + remove() { + this.isEditing = false; + if (this.parent) { + this.parent.setEditingState(true); + this.parent.div.classList.add("freetextEditing"); + } + super.remove(); + } + #extractText() { + const buffer = []; + this.editorDiv.normalize(); + let prevChild = null; + for (const child of this.editorDiv.childNodes) { + if (prevChild?.nodeType === Node.TEXT_NODE && child.nodeName === "BR") { + continue; + } + buffer.push(FreeTextEditor.#getNodeContent(child)); + prevChild = child; + } + return buffer.join("\n"); + } + #setEditorDimensions() { + const [parentWidth, parentHeight] = this.parentDimensions; + let rect; + if (this.isAttachedToDOM) { + rect = this.div.getBoundingClientRect(); + } else { + const { + currentLayer, + div + } = this; + const savedDisplay = div.style.display; + const savedVisibility = div.classList.contains("hidden"); + div.classList.remove("hidden"); + div.style.display = "hidden"; + currentLayer.div.append(this.div); + rect = div.getBoundingClientRect(); + div.remove(); + div.style.display = savedDisplay; + div.classList.toggle("hidden", savedVisibility); + } + if (this.rotation % 180 === this.parentRotation % 180) { + this.width = rect.width / parentWidth; + this.height = rect.height / parentHeight; + } else { + this.width = rect.height / parentWidth; + this.height = rect.width / parentHeight; + } + this.fixAndSetPosition(); + } + commit() { + if (!this.isInEditMode()) { + return; + } + super.commit(); + this.disableEditMode(); + const savedText = this.#content; + const newText = this.#content = this.#extractText().trimEnd(); + if (savedText === newText) { + return; + } + const setText = (text) => { + this.#content = text; + if (!text) { + this.remove(); + return; + } + this.#setContent(); + this._uiManager.rebuild(this); + this.#setEditorDimensions(); + }; + this.addCommands({ + cmd: () => { + setText(newText); + }, + undo: () => { + setText(savedText); + }, + mustExec: false + }); + this.#setEditorDimensions(); + } + shouldGetKeyboardEvents() { + return this.isInEditMode(); + } + enterInEditMode() { + this.enableEditMode(); + this.editorDiv.focus(); + } + keydown(event) { + if (event.target === this.div && event.key === "Enter") { + this.enterInEditMode(); + event.preventDefault(); + } + } + editorDivKeydown(event) { + FreeTextEditor._keyboardManager.exec(this, event); + } + editorDivFocus(event) { + this.isEditing = true; + } + editorDivBlur(event) { + this.isEditing = false; + } + editorDivInput(event) { + this.parent.div.classList.toggle("freetextEditing", this.isEmpty()); + } + disableEditing() { + this.editorDiv.setAttribute("role", "comment"); + this.editorDiv.removeAttribute("aria-multiline"); + } + enableEditing() { + this.editorDiv.setAttribute("role", "textbox"); + this.editorDiv.setAttribute("aria-multiline", true); + } + get canChangeContent() { + return true; + } + render() { + if (this.div) { + return this.div; + } + let baseX, baseY; + if (this._isCopy || this.annotationElementId) { + baseX = this.x; + baseY = this.y; + } + super.render(); + this.editorDiv = document.createElement("div"); + this.editorDiv.className = "internal"; + this.editorDiv.setAttribute("id", this.#editorDivId); + this.editorDiv.setAttribute("data-l10n-id", "pdfjs-free-text2"); + this.editorDiv.setAttribute("data-l10n-attrs", "default-content"); + this.enableEditing(); + this.editorDiv.contentEditable = true; + const { + style + } = this.editorDiv; + style.fontSize = `calc(${this.#fontSize}px * var(--total-scale-factor))`; + style.color = this.color; + this.div.append(this.editorDiv); + this.overlayDiv = document.createElement("div"); + this.overlayDiv.classList.add("overlay", "enabled"); + this.div.append(this.overlayDiv); + if (this._isCopy || this.annotationElementId) { + const [parentWidth, parentHeight] = this.parentDimensions; + if (this.annotationElementId) { + const { + position + } = this._initialData; + let [tx, ty] = this.getInitialTranslation(); + [tx, ty] = this.pageTranslationToScreen(tx, ty); + const [pageWidth, pageHeight] = this.pageDimensions; + const [pageX, pageY] = this.pageTranslation; + let posX, posY; + switch (this.rotation) { + case 0: + posX = baseX + (position[0] - pageX) / pageWidth; + posY = baseY + this.height - (position[1] - pageY) / pageHeight; + break; + case 90: + posX = baseX + (position[0] - pageX) / pageWidth; + posY = baseY - (position[1] - pageY) / pageHeight; + [tx, ty] = [ty, -tx]; + break; + case 180: + posX = baseX - this.width + (position[0] - pageX) / pageWidth; + posY = baseY - (position[1] - pageY) / pageHeight; + [tx, ty] = [-tx, -ty]; + break; + case 270: + posX = baseX + (position[0] - pageX - this.height * pageHeight) / pageWidth; + posY = baseY + (position[1] - pageY - this.width * pageWidth) / pageHeight; + [tx, ty] = [-ty, tx]; + break; + } + this.setAt(posX * parentWidth, posY * parentHeight, tx, ty); + } else { + this._moveAfterPaste(baseX, baseY); + } + this.#setContent(); + this._isDraggable = true; + this.editorDiv.contentEditable = false; + } else { + this._isDraggable = false; + this.editorDiv.contentEditable = true; + } + return this.div; + } + static #getNodeContent(node) { + return (node.nodeType === Node.TEXT_NODE ? node.nodeValue : node.innerText).replaceAll(EOL_PATTERN, ""); + } + editorDivPaste(event) { + const clipboardData = event.clipboardData || window.clipboardData; + const { + types + } = clipboardData; + if (types.length === 1 && types[0] === "text/plain") { + return; + } + event.preventDefault(); + const paste = FreeTextEditor.#deserializeContent(clipboardData.getData("text") || "").replaceAll(EOL_PATTERN, "\n"); + if (!paste) { + return; + } + const selection = window.getSelection(); + if (!selection.rangeCount) { + return; + } + this.editorDiv.normalize(); + selection.deleteFromDocument(); + const range = selection.getRangeAt(0); + if (!paste.includes("\n")) { + range.insertNode(document.createTextNode(paste)); + this.editorDiv.normalize(); + selection.collapseToStart(); + return; + } + const { + startContainer, + startOffset + } = range; + const bufferBefore = []; + const bufferAfter = []; + if (startContainer.nodeType === Node.TEXT_NODE) { + const parent = startContainer.parentElement; + bufferAfter.push(startContainer.nodeValue.slice(startOffset).replaceAll(EOL_PATTERN, "")); + if (parent !== this.editorDiv) { + let buffer = bufferBefore; + for (const child of this.editorDiv.childNodes) { + if (child === parent) { + buffer = bufferAfter; + continue; + } + buffer.push(FreeTextEditor.#getNodeContent(child)); + } + } + bufferBefore.push(startContainer.nodeValue.slice(0, startOffset).replaceAll(EOL_PATTERN, "")); + } else if (startContainer === this.editorDiv) { + let buffer = bufferBefore; + let i = 0; + for (const child of this.editorDiv.childNodes) { + if (i++ === startOffset) { + buffer = bufferAfter; + } + buffer.push(FreeTextEditor.#getNodeContent(child)); + } + } + this.#content = `${bufferBefore.join("\n")}${paste}${bufferAfter.join("\n")}`; + this.#setContent(); + const newRange = new Range(); + let beforeLength = Math.sumPrecise(bufferBefore.map((line) => line.length)); + for (const { + firstChild + } of this.editorDiv.childNodes) { + if (firstChild.nodeType === Node.TEXT_NODE) { + const length = firstChild.nodeValue.length; + if (beforeLength <= length) { + newRange.setStart(firstChild, beforeLength); + newRange.setEnd(firstChild, beforeLength); + break; + } + beforeLength -= length; + } + } + selection.removeAllRanges(); + selection.addRange(newRange); + } + #setContent() { + this.editorDiv.replaceChildren(); + if (!this.#content) { + return; + } + for (const line of this.#content.split("\n")) { + const div = document.createElement("div"); + div.append(line ? document.createTextNode(line) : document.createElement("br")); + this.editorDiv.append(div); + } + } + #serializeContent() { + return this.#content.replaceAll(" ", " "); + } + static #deserializeContent(content) { + return content.replaceAll(" ", " "); + } + get contentDiv() { + return this.editorDiv; + } + getPDFRect() { + const padding = FreeTextEditor._internalPadding * this.parentScale; + return this.getRect(padding, padding); + } + static async deserialize(data, parent, uiManager) { + let initialData = null; + if (data instanceof FreeTextAnnotationElement) { + const { + data: { + defaultAppearanceData: { + fontSize, + fontColor + }, + rect, + rotation, + id, + popupRef, + richText, + contentsObj, + creationDate, + modificationDate + }, + textContent, + textPosition, + parent: { + page: { + pageNumber + } + } + } = data; + if (!textContent || textContent.length === 0) { + return null; + } + initialData = data = { + annotationType: AnnotationEditorType.FREETEXT, + color: Array.from(fontColor), + fontSize, + value: textContent.join("\n"), + position: textPosition, + pageIndex: pageNumber - 1, + rect: rect.slice(0), + rotation, + annotationElementId: id, + id, + deleted: false, + popupRef, + comment: contentsObj?.str || null, + richText, + creationDate, + modificationDate + }; + } + const editor = await super.deserialize(data, parent, uiManager); + editor.#fontSize = data.fontSize; + editor.color = Util.makeHexColor(...data.color); + editor.#content = FreeTextEditor.#deserializeContent(data.value); + editor._initialData = initialData; + if (data.comment) { + editor.setCommentData(data); + } + return editor; + } + serialize(isForCopying = false) { + if (this.isEmpty()) { + return null; + } + if (this.deleted) { + return this.serializeDeleted(); + } + const color = AnnotationEditor._colorManager.convert(this.isAttachedToDOM ? getComputedStyle(this.editorDiv).color : this.color); + const serialized = Object.assign(super.serialize(isForCopying), { + color, + fontSize: this.#fontSize, + value: this.#serializeContent() + }); + this.addComment(serialized); + if (isForCopying) { + serialized.isCopy = true; + return serialized; + } + if (this.annotationElementId && !this.#hasElementChanged(serialized)) { + return null; + } + serialized.id = this.annotationElementId; + return serialized; + } + #hasElementChanged(serialized) { + const { + value, + fontSize, + color, + pageIndex + } = this._initialData; + return this.hasEditedComment || this._hasBeenMoved || serialized.value !== value || serialized.fontSize !== fontSize || serialized.color.some((c, i) => c !== color[i]) || serialized.pageIndex !== pageIndex; + } + renderAnnotationElement(annotation) { + const content = super.renderAnnotationElement(annotation); + if (!content) { + return null; + } + const { + style + } = content; + style.fontSize = `calc(${this.#fontSize}px * var(--total-scale-factor))`; + style.color = this.color; + content.replaceChildren(); + for (const line of this.#content.split("\n")) { + const div = document.createElement("div"); + div.append(line ? document.createTextNode(line) : document.createElement("br")); + content.append(div); + } + annotation.updateEdited({ + rect: this.getPDFRect(), + popup: this._uiManager.hasCommentManager() || this.hasEditedComment ? this.comment : { + text: this.#content + } + }); + return content; + } + resetAnnotationElement(annotation) { + super.resetAnnotationElement(annotation); + annotation.resetEdited(); + } +} +class Outline { + static PRECISION = 1e-4; + toSVGPath() { + unreachable("Abstract method `toSVGPath` must be implemented."); + } + get box() { + unreachable("Abstract getter `box` must be implemented."); + } + serialize(_bbox, _rotation) { + unreachable("Abstract method `serialize` must be implemented."); + } + static _rescale(src, tx, ty, sx, sy, dest) { + dest ||= new Float32Array(src.length); + for (let i = 0, ii = src.length; i < ii; i += 2) { + dest[i] = tx + src[i] * sx; + dest[i + 1] = ty + src[i + 1] * sy; + } + return dest; + } + static _rescaleAndSwap(src, tx, ty, sx, sy, dest) { + dest ||= new Float32Array(src.length); + for (let i = 0, ii = src.length; i < ii; i += 2) { + dest[i] = tx + src[i + 1] * sx; + dest[i + 1] = ty + src[i] * sy; + } + return dest; + } + static _translate(src, tx, ty, dest) { + dest ||= new Float32Array(src.length); + for (let i = 0, ii = src.length; i < ii; i += 2) { + dest[i] = tx + src[i]; + dest[i + 1] = ty + src[i + 1]; + } + return dest; + } + static svgRound(x) { + return Math.round(x * 1e4); + } + static _normalizePoint(x, y, parentWidth, parentHeight, rotation) { + switch (rotation) { + case 90: + return [1 - y / parentWidth, x / parentHeight]; + case 180: + return [1 - x / parentWidth, 1 - y / parentHeight]; + case 270: + return [y / parentWidth, 1 - x / parentHeight]; + default: + return [x / parentWidth, y / parentHeight]; + } + } + static _normalizePagePoint(x, y, rotation) { + switch (rotation) { + case 90: + return [1 - y, x]; + case 180: + return [1 - x, 1 - y]; + case 270: + return [y, 1 - x]; + default: + return [x, y]; + } + } + static createBezierPoints(x1, y1, x2, y2, x3, y3) { + return [(x1 + 5 * x2) / 6, (y1 + 5 * y2) / 6, (5 * x2 + x3) / 6, (5 * y2 + y3) / 6, (x2 + x3) / 2, (y2 + y3) / 2]; + } +} +class FreeDrawOutliner { + #box; + #bottom = []; + #innerMargin; + #isLTR; + #top = []; + #last = new Float32Array(18); + #lastX; + #lastY; + #min; + #min_dist; + #scaleFactor; + #thickness; + #points = []; + static #MIN_DIST = 8; + static #MIN_DIFF = 2; + static #MIN = FreeDrawOutliner.#MIN_DIST + FreeDrawOutliner.#MIN_DIFF; + constructor({ + x, + y + }, box, scaleFactor, thickness, isLTR, innerMargin = 0) { + this.#box = box; + this.#thickness = thickness * scaleFactor; + this.#isLTR = isLTR; + this.#last.set([NaN, NaN, NaN, NaN, x, y], 6); + this.#innerMargin = innerMargin; + this.#min_dist = FreeDrawOutliner.#MIN_DIST * scaleFactor; + this.#min = FreeDrawOutliner.#MIN * scaleFactor; + this.#scaleFactor = scaleFactor; + this.#points.push(x, y); + } + isEmpty() { + return isNaN(this.#last[8]); + } + #getLastCoords() { + const lastTop = this.#last.subarray(4, 6); + const lastBottom = this.#last.subarray(16, 18); + const [x, y, width, height] = this.#box; + return [(this.#lastX + (lastTop[0] - lastBottom[0]) / 2 - x) / width, (this.#lastY + (lastTop[1] - lastBottom[1]) / 2 - y) / height, (this.#lastX + (lastBottom[0] - lastTop[0]) / 2 - x) / width, (this.#lastY + (lastBottom[1] - lastTop[1]) / 2 - y) / height]; + } + add({ + x, + y + }) { + this.#lastX = x; + this.#lastY = y; + const [layerX, layerY, layerWidth, layerHeight] = this.#box; + let [x1, y1, x2, y2] = this.#last.subarray(8, 12); + const diffX = x - x2; + const diffY = y - y2; + const d = Math.hypot(diffX, diffY); + if (d < this.#min) { + return false; + } + const diffD = d - this.#min_dist; + const K = diffD / d; + const shiftX = K * diffX; + const shiftY = K * diffY; + let x0 = x1; + let y0 = y1; + x1 = x2; + y1 = y2; + x2 += shiftX; + y2 += shiftY; + this.#points?.push(x, y); + const nX = -shiftY / diffD; + const nY = shiftX / diffD; + const thX = nX * this.#thickness; + const thY = nY * this.#thickness; + this.#last.set(this.#last.subarray(2, 8), 0); + this.#last.set([x2 + thX, y2 + thY], 4); + this.#last.set(this.#last.subarray(14, 18), 12); + this.#last.set([x2 - thX, y2 - thY], 16); + if (isNaN(this.#last[6])) { + if (this.#top.length === 0) { + this.#last.set([x1 + thX, y1 + thY], 2); + this.#top.push(NaN, NaN, NaN, NaN, (x1 + thX - layerX) / layerWidth, (y1 + thY - layerY) / layerHeight); + this.#last.set([x1 - thX, y1 - thY], 14); + this.#bottom.push(NaN, NaN, NaN, NaN, (x1 - thX - layerX) / layerWidth, (y1 - thY - layerY) / layerHeight); + } + this.#last.set([x0, y0, x1, y1, x2, y2], 6); + return !this.isEmpty(); + } + this.#last.set([x0, y0, x1, y1, x2, y2], 6); + const angle = Math.abs(Math.atan2(y0 - y1, x0 - x1) - Math.atan2(shiftY, shiftX)); + if (angle < Math.PI / 2) { + [x1, y1, x2, y2] = this.#last.subarray(2, 6); + this.#top.push(NaN, NaN, NaN, NaN, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight); + [x1, y1, x0, y0] = this.#last.subarray(14, 18); + this.#bottom.push(NaN, NaN, NaN, NaN, ((x0 + x1) / 2 - layerX) / layerWidth, ((y0 + y1) / 2 - layerY) / layerHeight); + return true; + } + [x0, y0, x1, y1, x2, y2] = this.#last.subarray(0, 6); + this.#top.push(((x0 + 5 * x1) / 6 - layerX) / layerWidth, ((y0 + 5 * y1) / 6 - layerY) / layerHeight, ((5 * x1 + x2) / 6 - layerX) / layerWidth, ((5 * y1 + y2) / 6 - layerY) / layerHeight, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight); + [x2, y2, x1, y1, x0, y0] = this.#last.subarray(12, 18); + this.#bottom.push(((x0 + 5 * x1) / 6 - layerX) / layerWidth, ((y0 + 5 * y1) / 6 - layerY) / layerHeight, ((5 * x1 + x2) / 6 - layerX) / layerWidth, ((5 * y1 + y2) / 6 - layerY) / layerHeight, ((x1 + x2) / 2 - layerX) / layerWidth, ((y1 + y2) / 2 - layerY) / layerHeight); + return true; + } + toSVGPath() { + if (this.isEmpty()) { + return ""; + } + const top = this.#top; + const bottom = this.#bottom; + if (isNaN(this.#last[6]) && !this.isEmpty()) { + return this.#toSVGPathTwoPoints(); + } + const buffer = []; + buffer.push(`M${top[4]} ${top[5]}`); + for (let i = 6; i < top.length; i += 6) { + if (isNaN(top[i])) { + buffer.push(`L${top[i + 4]} ${top[i + 5]}`); + } else { + buffer.push(`C${top[i]} ${top[i + 1]} ${top[i + 2]} ${top[i + 3]} ${top[i + 4]} ${top[i + 5]}`); + } + } + this.#toSVGPathEnd(buffer); + for (let i = bottom.length - 6; i >= 6; i -= 6) { + if (isNaN(bottom[i])) { + buffer.push(`L${bottom[i + 4]} ${bottom[i + 5]}`); + } else { + buffer.push(`C${bottom[i]} ${bottom[i + 1]} ${bottom[i + 2]} ${bottom[i + 3]} ${bottom[i + 4]} ${bottom[i + 5]}`); + } + } + this.#toSVGPathStart(buffer); + return buffer.join(" "); + } + #toSVGPathTwoPoints() { + const [x, y, width, height] = this.#box; + const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords(); + return `M${(this.#last[2] - x) / width} ${(this.#last[3] - y) / height} L${(this.#last[4] - x) / width} ${(this.#last[5] - y) / height} L${lastTopX} ${lastTopY} L${lastBottomX} ${lastBottomY} L${(this.#last[16] - x) / width} ${(this.#last[17] - y) / height} L${(this.#last[14] - x) / width} ${(this.#last[15] - y) / height} Z`; + } + #toSVGPathStart(buffer) { + const bottom = this.#bottom; + buffer.push(`L${bottom[4]} ${bottom[5]} Z`); + } + #toSVGPathEnd(buffer) { + const [x, y, width, height] = this.#box; + const lastTop = this.#last.subarray(4, 6); + const lastBottom = this.#last.subarray(16, 18); + const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords(); + buffer.push(`L${(lastTop[0] - x) / width} ${(lastTop[1] - y) / height} L${lastTopX} ${lastTopY} L${lastBottomX} ${lastBottomY} L${(lastBottom[0] - x) / width} ${(lastBottom[1] - y) / height}`); + } + newFreeDrawOutline(outline, points, box, scaleFactor, innerMargin, isLTR) { + return new FreeDrawOutline(outline, points, box, scaleFactor, innerMargin, isLTR); + } + getOutlines() { + const top = this.#top; + const bottom = this.#bottom; + const last = this.#last; + const [layerX, layerY, layerWidth, layerHeight] = this.#box; + const points = new Float32Array((this.#points?.length ?? 0) + 2); + for (let i = 0, ii = points.length - 2; i < ii; i += 2) { + points[i] = (this.#points[i] - layerX) / layerWidth; + points[i + 1] = (this.#points[i + 1] - layerY) / layerHeight; + } + points[points.length - 2] = (this.#lastX - layerX) / layerWidth; + points[points.length - 1] = (this.#lastY - layerY) / layerHeight; + if (isNaN(last[6]) && !this.isEmpty()) { + return this.#getOutlineTwoPoints(points); + } + const outline = new Float32Array(this.#top.length + 24 + this.#bottom.length); + let N = top.length; + for (let i = 0; i < N; i += 2) { + if (isNaN(top[i])) { + outline[i] = outline[i + 1] = NaN; + continue; + } + outline[i] = top[i]; + outline[i + 1] = top[i + 1]; + } + N = this.#getOutlineEnd(outline, N); + for (let i = bottom.length - 6; i >= 6; i -= 6) { + for (let j = 0; j < 6; j += 2) { + if (isNaN(bottom[i + j])) { + outline[N] = outline[N + 1] = NaN; + N += 2; + continue; + } + outline[N] = bottom[i + j]; + outline[N + 1] = bottom[i + j + 1]; + N += 2; + } + } + this.#getOutlineStart(outline, N); + return this.newFreeDrawOutline(outline, points, this.#box, this.#scaleFactor, this.#innerMargin, this.#isLTR); + } + #getOutlineTwoPoints(points) { + const last = this.#last; + const [layerX, layerY, layerWidth, layerHeight] = this.#box; + const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords(); + const outline = new Float32Array(36); + outline.set([NaN, NaN, NaN, NaN, (last[2] - layerX) / layerWidth, (last[3] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[4] - layerX) / layerWidth, (last[5] - layerY) / layerHeight, NaN, NaN, NaN, NaN, lastTopX, lastTopY, NaN, NaN, NaN, NaN, lastBottomX, lastBottomY, NaN, NaN, NaN, NaN, (last[16] - layerX) / layerWidth, (last[17] - layerY) / layerHeight, NaN, NaN, NaN, NaN, (last[14] - layerX) / layerWidth, (last[15] - layerY) / layerHeight], 0); + return this.newFreeDrawOutline(outline, points, this.#box, this.#scaleFactor, this.#innerMargin, this.#isLTR); + } + #getOutlineStart(outline, pos) { + const bottom = this.#bottom; + outline.set([NaN, NaN, NaN, NaN, bottom[4], bottom[5]], pos); + return pos += 6; + } + #getOutlineEnd(outline, pos) { + const lastTop = this.#last.subarray(4, 6); + const lastBottom = this.#last.subarray(16, 18); + const [layerX, layerY, layerWidth, layerHeight] = this.#box; + const [lastTopX, lastTopY, lastBottomX, lastBottomY] = this.#getLastCoords(); + outline.set([NaN, NaN, NaN, NaN, (lastTop[0] - layerX) / layerWidth, (lastTop[1] - layerY) / layerHeight, NaN, NaN, NaN, NaN, lastTopX, lastTopY, NaN, NaN, NaN, NaN, lastBottomX, lastBottomY, NaN, NaN, NaN, NaN, (lastBottom[0] - layerX) / layerWidth, (lastBottom[1] - layerY) / layerHeight], pos); + return pos += 24; + } +} +class FreeDrawOutline extends Outline { + #box; + #bbox = new Float32Array(4); + #innerMargin; + #isLTR; + #points; + #scaleFactor; + #outline; + constructor(outline, points, box, scaleFactor, innerMargin, isLTR) { + super(); + this.#outline = outline; + this.#points = points; + this.#box = box; + this.#scaleFactor = scaleFactor; + this.#innerMargin = innerMargin; + this.#isLTR = isLTR; + this.firstPoint = [NaN, NaN]; + this.lastPoint = [NaN, NaN]; + this.#computeMinMax(isLTR); + const [x, y, width, height] = this.#bbox; + for (let i = 0, ii = outline.length; i < ii; i += 2) { + outline[i] = (outline[i] - x) / width; + outline[i + 1] = (outline[i + 1] - y) / height; + } + for (let i = 0, ii = points.length; i < ii; i += 2) { + points[i] = (points[i] - x) / width; + points[i + 1] = (points[i + 1] - y) / height; + } + } + toSVGPath() { + const buffer = [`M${this.#outline[4]} ${this.#outline[5]}`]; + for (let i = 6, ii = this.#outline.length; i < ii; i += 6) { + if (isNaN(this.#outline[i])) { + buffer.push(`L${this.#outline[i + 4]} ${this.#outline[i + 5]}`); + continue; + } + buffer.push(`C${this.#outline[i]} ${this.#outline[i + 1]} ${this.#outline[i + 2]} ${this.#outline[i + 3]} ${this.#outline[i + 4]} ${this.#outline[i + 5]}`); + } + buffer.push("Z"); + return buffer.join(" "); + } + serialize([blX, blY, trX, trY], rotation) { + const width = trX - blX; + const height = trY - blY; + let outline; + let points; + switch (rotation) { + case 0: + outline = Outline._rescale(this.#outline, blX, trY, width, -height); + points = Outline._rescale(this.#points, blX, trY, width, -height); + break; + case 90: + outline = Outline._rescaleAndSwap(this.#outline, blX, blY, width, height); + points = Outline._rescaleAndSwap(this.#points, blX, blY, width, height); + break; + case 180: + outline = Outline._rescale(this.#outline, trX, blY, -width, height); + points = Outline._rescale(this.#points, trX, blY, -width, height); + break; + case 270: + outline = Outline._rescaleAndSwap(this.#outline, trX, trY, -width, -height); + points = Outline._rescaleAndSwap(this.#points, trX, trY, -width, -height); + break; + } + return { + outline: Array.from(outline), + points: [Array.from(points)] + }; + } + #computeMinMax(isLTR) { + const outline = this.#outline; + let lastX = outline[4]; + let lastY = outline[5]; + const minMax = [lastX, lastY, lastX, lastY]; + let firstPointX = lastX; + let firstPointY = lastY; + let lastPointX = lastX; + let lastPointY = lastY; + const ltrCallback = isLTR ? Math.max : Math.min; + const bezierBbox = new Float32Array(4); + for (let i = 6, ii = outline.length; i < ii; i += 6) { + const x = outline[i + 4], y = outline[i + 5]; + if (isNaN(outline[i])) { + Util.pointBoundingBox(x, y, minMax); + if (firstPointY > y) { + firstPointX = x; + firstPointY = y; + } else if (firstPointY === y) { + firstPointX = ltrCallback(firstPointX, x); + } + if (lastPointY < y) { + lastPointX = x; + lastPointY = y; + } else if (lastPointY === y) { + lastPointX = ltrCallback(lastPointX, x); + } + } else { + bezierBbox[0] = bezierBbox[1] = Infinity; + bezierBbox[2] = bezierBbox[3] = -Infinity; + Util.bezierBoundingBox(lastX, lastY, ...outline.slice(i, i + 6), bezierBbox); + Util.rectBoundingBox(bezierBbox[0], bezierBbox[1], bezierBbox[2], bezierBbox[3], minMax); + if (firstPointY > bezierBbox[1]) { + firstPointX = bezierBbox[0]; + firstPointY = bezierBbox[1]; + } else if (firstPointY === bezierBbox[1]) { + firstPointX = ltrCallback(firstPointX, bezierBbox[0]); + } + if (lastPointY < bezierBbox[3]) { + lastPointX = bezierBbox[2]; + lastPointY = bezierBbox[3]; + } else if (lastPointY === bezierBbox[3]) { + lastPointX = ltrCallback(lastPointX, bezierBbox[2]); + } + } + lastX = x; + lastY = y; + } + const bbox = this.#bbox; + bbox[0] = minMax[0] - this.#innerMargin; + bbox[1] = minMax[1] - this.#innerMargin; + bbox[2] = minMax[2] - minMax[0] + 2 * this.#innerMargin; + bbox[3] = minMax[3] - minMax[1] + 2 * this.#innerMargin; + this.firstPoint = [firstPointX, firstPointY]; + this.lastPoint = [lastPointX, lastPointY]; + } + get box() { + return this.#bbox; + } + newOutliner(point, box, scaleFactor, thickness, isLTR, innerMargin = 0) { + return new FreeDrawOutliner(point, box, scaleFactor, thickness, isLTR, innerMargin); + } + getNewOutline(thickness, innerMargin) { + const [x, y, width, height] = this.#bbox; + const [layerX, layerY, layerWidth, layerHeight] = this.#box; + const sx = width * layerWidth; + const sy = height * layerHeight; + const tx = x * layerWidth + layerX; + const ty = y * layerHeight + layerY; + const outliner = this.newOutliner({ + x: this.#points[0] * sx + tx, + y: this.#points[1] * sy + ty + }, this.#box, this.#scaleFactor, thickness, this.#isLTR, innerMargin ?? this.#innerMargin); + for (let i = 2; i < this.#points.length; i += 2) { + outliner.add({ + x: this.#points[i] * sx + tx, + y: this.#points[i + 1] * sy + ty + }); + } + return outliner.getOutlines(); + } +} +class HighlightOutliner { + #box; + #firstPoint; + #lastPoint; + #verticalEdges = []; + #intervals = []; + constructor(boxes, borderWidth = 0, innerMargin = 0, isLTR = true) { + const minMax = [Infinity, Infinity, -Infinity, -Infinity]; + const EPSILON = 10 ** -4; + for (const { + x, + y, + width, + height + } of boxes) { + const x1 = Math.floor((x - borderWidth) / EPSILON) * EPSILON; + const x2 = Math.ceil((x + width + borderWidth) / EPSILON) * EPSILON; + const y1 = Math.floor((y - borderWidth) / EPSILON) * EPSILON; + const y2 = Math.ceil((y + height + borderWidth) / EPSILON) * EPSILON; + const left = [x1, y1, y2, true]; + const right = [x2, y1, y2, false]; + this.#verticalEdges.push(left, right); + Util.rectBoundingBox(x1, y1, x2, y2, minMax); + } + const bboxWidth = minMax[2] - minMax[0] + 2 * innerMargin; + const bboxHeight = minMax[3] - minMax[1] + 2 * innerMargin; + const shiftedMinX = minMax[0] - innerMargin; + const shiftedMinY = minMax[1] - innerMargin; + let firstPointX = isLTR ? -Infinity : Infinity; + let firstPointY = Infinity; + const lastEdge = this.#verticalEdges.at(isLTR ? -1 : -2); + const lastPoint = [lastEdge[0], lastEdge[2]]; + for (const edge of this.#verticalEdges) { + const [x, y1, y2, left] = edge; + if (!left && isLTR) { + if (y1 < firstPointY) { + firstPointY = y1; + firstPointX = x; + } else if (y1 === firstPointY) { + firstPointX = Math.max(firstPointX, x); + } + } else if (left && !isLTR) { + if (y1 < firstPointY) { + firstPointY = y1; + firstPointX = x; + } else if (y1 === firstPointY) { + firstPointX = Math.min(firstPointX, x); + } + } + edge[0] = (x - shiftedMinX) / bboxWidth; + edge[1] = (y1 - shiftedMinY) / bboxHeight; + edge[2] = (y2 - shiftedMinY) / bboxHeight; + } + this.#box = new Float32Array([shiftedMinX, shiftedMinY, bboxWidth, bboxHeight]); + this.#firstPoint = [firstPointX, firstPointY]; + this.#lastPoint = lastPoint; + } + getOutlines() { + this.#verticalEdges.sort((a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2]); + const outlineVerticalEdges = []; + for (const edge of this.#verticalEdges) { + if (edge[3]) { + outlineVerticalEdges.push(...this.#breakEdge(edge)); + this.#insert(edge); + } else { + this.#remove(edge); + outlineVerticalEdges.push(...this.#breakEdge(edge)); + } + } + return this.#getOutlines(outlineVerticalEdges); + } + #getOutlines(outlineVerticalEdges) { + const edges = []; + const allEdges = /* @__PURE__ */ new Set(); + for (const edge of outlineVerticalEdges) { + const [x, y1, y2] = edge; + edges.push([x, y1, edge], [x, y2, edge]); + } + edges.sort((a, b) => a[1] - b[1] || a[0] - b[0]); + for (let i = 0, ii = edges.length; i < ii; i += 2) { + const edge1 = edges[i][2]; + const edge2 = edges[i + 1][2]; + edge1.push(edge2); + edge2.push(edge1); + allEdges.add(edge1); + allEdges.add(edge2); + } + const outlines = []; + let outline; + while (allEdges.size > 0) { + const edge = allEdges.values().next().value; + let [x, y1, y2, edge1, edge2] = edge; + allEdges.delete(edge); + let lastPointX = x; + let lastPointY = y1; + outline = [x, y2]; + outlines.push(outline); + while (true) { + let e; + if (allEdges.has(edge1)) { + e = edge1; + } else if (allEdges.has(edge2)) { + e = edge2; + } else { + break; + } + allEdges.delete(e); + [x, y1, y2, edge1, edge2] = e; + if (lastPointX !== x) { + outline.push(lastPointX, lastPointY, x, lastPointY === y1 ? y1 : y2); + lastPointX = x; + } + lastPointY = lastPointY === y1 ? y2 : y1; + } + outline.push(lastPointX, lastPointY); + } + return new HighlightOutline(outlines, this.#box, this.#firstPoint, this.#lastPoint); + } + #binarySearch(y) { + const array = this.#intervals; + let start = 0; + let end = array.length - 1; + while (start <= end) { + const middle = start + end >> 1; + const y1 = array[middle][0]; + if (y1 === y) { + return middle; + } + if (y1 < y) { + start = middle + 1; + } else { + end = middle - 1; + } + } + return end + 1; + } + #insert([, y1, y2]) { + const index = this.#binarySearch(y1); + this.#intervals.splice(index, 0, [y1, y2]); + } + #remove([, y1, y2]) { + const index = this.#binarySearch(y1); + for (let i = index; i < this.#intervals.length; i++) { + const [start, end] = this.#intervals[i]; + if (start !== y1) { + break; + } + if (start === y1 && end === y2) { + this.#intervals.splice(i, 1); + return; + } + } + for (let i = index - 1; i >= 0; i--) { + const [start, end] = this.#intervals[i]; + if (start !== y1) { + break; + } + if (start === y1 && end === y2) { + this.#intervals.splice(i, 1); + return; + } + } + } + #breakEdge(edge) { + const [x, y1, y2] = edge; + const results = [[x, y1, y2]]; + const index = this.#binarySearch(y2); + for (let i = 0; i < index; i++) { + const [start, end] = this.#intervals[i]; + for (let j = 0, jj = results.length; j < jj; j++) { + const [, y3, y4] = results[j]; + if (end <= y3 || y4 <= start) { + continue; + } + if (y3 >= start) { + if (y4 > end) { + results[j][1] = end; + } else { + if (jj === 1) { + return []; + } + results.splice(j, 1); + j--; + jj--; + } + continue; + } + results[j][2] = start; + if (y4 > end) { + results.push([x, end, y4]); + } + } + } + return results; + } +} +class HighlightOutline extends Outline { + #box; + #outlines; + constructor(outlines, box, firstPoint, lastPoint) { + super(); + this.#outlines = outlines; + this.#box = box; + this.firstPoint = firstPoint; + this.lastPoint = lastPoint; + } + toSVGPath() { + const buffer = []; + for (const polygon of this.#outlines) { + let [prevX, prevY] = polygon; + buffer.push(`M${prevX} ${prevY}`); + for (let i = 2; i < polygon.length; i += 2) { + const x = polygon[i]; + const y = polygon[i + 1]; + if (x === prevX) { + buffer.push(`V${y}`); + prevY = y; + } else if (y === prevY) { + buffer.push(`H${x}`); + prevX = x; + } + } + buffer.push("Z"); + } + return buffer.join(" "); + } + serialize([blX, blY, trX, trY], _rotation) { + const outlines = []; + const width = trX - blX; + const height = trY - blY; + for (const outline of this.#outlines) { + const points = new Array(outline.length); + for (let i = 0; i < outline.length; i += 2) { + points[i] = blX + outline[i] * width; + points[i + 1] = trY - outline[i + 1] * height; + } + outlines.push(points); + } + return outlines; + } + get box() { + return this.#box; + } + get classNamesForOutlining() { + return ["highlightOutline"]; + } +} +class FreeHighlightOutliner extends FreeDrawOutliner { + newFreeDrawOutline(outline, points, box, scaleFactor, innerMargin, isLTR) { + return new FreeHighlightOutline(outline, points, box, scaleFactor, innerMargin, isLTR); + } +} +class FreeHighlightOutline extends FreeDrawOutline { + newOutliner(point, box, scaleFactor, thickness, isLTR, innerMargin = 0) { + return new FreeHighlightOutliner(point, box, scaleFactor, thickness, isLTR, innerMargin); + } +} +class HighlightEditor extends AnnotationEditor { + #anchorNode = null; + #anchorOffset = 0; + #boxes; + #clipPathId = null; + #colorPicker = null; + #focusOutlines = null; + #focusNode = null; + #focusOffset = 0; + #highlightDiv = null; + #highlightOutlines = null; + #id = null; + #isFreeHighlight = false; + #firstPoint = null; + #lastPoint = null; + #outlineId = null; + #text = ""; + #thickness; + #methodOfCreation = ""; + static _defaultColor = null; + static _defaultOpacity = 1; + static _defaultThickness = 12; + static _type = "highlight"; + static _editorType = AnnotationEditorType.HIGHLIGHT; + static _freeHighlightId = -1; + static _freeHighlight = null; + static _freeHighlightClipId = ""; + static get _keyboardManager() { + const proto = HighlightEditor.prototype; + return shadow(this, "_keyboardManager", new KeyboardManager([[["ArrowLeft", "mac+ArrowLeft"], proto._moveCaret, { + args: [0] + }], [["ArrowRight", "mac+ArrowRight"], proto._moveCaret, { + args: [1] + }], [["ArrowUp", "mac+ArrowUp"], proto._moveCaret, { + args: [2] + }], [["ArrowDown", "mac+ArrowDown"], proto._moveCaret, { + args: [3] + }]])); + } + constructor(params) { + super({ + ...params, + name: "highlightEditor" + }); + this.color = params.color || HighlightEditor._defaultColor; + this.#thickness = params.thickness || HighlightEditor._defaultThickness; + this.opacity = params.opacity || HighlightEditor._defaultOpacity; + this.#boxes = params.boxes || null; + this.#methodOfCreation = params.methodOfCreation || ""; + this.#text = params.text || ""; + this._isDraggable = false; + this.defaultL10nId = "pdfjs-editor-highlight-editor"; + if (params.highlightId > -1) { + this.#isFreeHighlight = true; + this.#createFreeOutlines(params); + this.#addToDrawLayer(); + } else if (this.#boxes) { + this.#anchorNode = params.anchorNode; + this.#anchorOffset = params.anchorOffset; + this.#focusNode = params.focusNode; + this.#focusOffset = params.focusOffset; + this.#createOutlines(); + this.#addToDrawLayer(); + this.rotate(this.rotation); + } + if (!this.annotationElementId) { + this._uiManager.a11yAlert("pdfjs-editor-highlight-added-alert"); + } + } + get telemetryInitialData() { + return { + action: "added", + type: this.#isFreeHighlight ? "free_highlight" : "highlight", + color: this._uiManager.getNonHCMColorName(this.color), + thickness: this.#thickness, + methodOfCreation: this.#methodOfCreation + }; + } + get telemetryFinalData() { + return { + type: "highlight", + color: this._uiManager.getNonHCMColorName(this.color) + }; + } + static computeTelemetryFinalData(data) { + return { + numberOfColors: data.get("color").size + }; + } + #createOutlines() { + const outliner = new HighlightOutliner(this.#boxes, 1e-3); + this.#highlightOutlines = outliner.getOutlines(); + [this.x, this.y, this.width, this.height] = this.#highlightOutlines.box; + const outlinerForOutline = new HighlightOutliner(this.#boxes, 25e-4, 1e-3, this._uiManager.direction === "ltr"); + this.#focusOutlines = outlinerForOutline.getOutlines(); + const { + firstPoint + } = this.#highlightOutlines; + this.#firstPoint = [(firstPoint[0] - this.x) / this.width, (firstPoint[1] - this.y) / this.height]; + const { + lastPoint + } = this.#focusOutlines; + this.#lastPoint = [(lastPoint[0] - this.x) / this.width, (lastPoint[1] - this.y) / this.height]; + } + #createFreeOutlines({ + highlightOutlines, + highlightId, + clipPathId + }) { + this.#highlightOutlines = highlightOutlines; + const extraThickness = 1.5; + this.#focusOutlines = highlightOutlines.getNewOutline(this.#thickness / 2 + extraThickness, 25e-4); + if (highlightId >= 0) { + this.#id = highlightId; + this.#clipPathId = clipPathId; + this.parent.drawLayer.finalizeDraw(highlightId, { + bbox: highlightOutlines.box, + path: { + d: highlightOutlines.toSVGPath() + } + }); + this.#outlineId = this.parent.drawLayer.drawOutline({ + rootClass: { + highlightOutline: true, + free: true + }, + bbox: this.#focusOutlines.box, + path: { + d: this.#focusOutlines.toSVGPath() + } + }, true); + } else if (this.parent) { + const angle = this.parent.viewport.rotation; + this.parent.drawLayer.updateProperties(this.#id, { + bbox: HighlightEditor.#rotateBbox(this.#highlightOutlines.box, (angle - this.rotation + 360) % 360), + path: { + d: highlightOutlines.toSVGPath() + } + }); + this.parent.drawLayer.updateProperties(this.#outlineId, { + bbox: HighlightEditor.#rotateBbox(this.#focusOutlines.box, angle), + path: { + d: this.#focusOutlines.toSVGPath() + } + }); + } + const [x, y, width, height] = highlightOutlines.box; + switch (this.rotation) { + case 0: + this.x = x; + this.y = y; + this.width = width; + this.height = height; + break; + case 90: { + const [pageWidth, pageHeight] = this.parentDimensions; + this.x = y; + this.y = 1 - x; + this.width = width * pageHeight / pageWidth; + this.height = height * pageWidth / pageHeight; + break; + } + case 180: + this.x = 1 - x; + this.y = 1 - y; + this.width = width; + this.height = height; + break; + case 270: { + const [pageWidth, pageHeight] = this.parentDimensions; + this.x = 1 - y; + this.y = x; + this.width = width * pageHeight / pageWidth; + this.height = height * pageWidth / pageHeight; + break; + } + } + const { + firstPoint + } = highlightOutlines; + this.#firstPoint = [(firstPoint[0] - x) / width, (firstPoint[1] - y) / height]; + const { + lastPoint + } = this.#focusOutlines; + this.#lastPoint = [(lastPoint[0] - x) / width, (lastPoint[1] - y) / height]; + } + static initialize(l10n, uiManager) { + AnnotationEditor.initialize(l10n, uiManager); + HighlightEditor._defaultColor ||= uiManager.highlightColors?.values().next().value || "#fff066"; + } + static updateDefaultParams(type, value) { + switch (type) { + case AnnotationEditorParamsType.HIGHLIGHT_COLOR: + HighlightEditor._defaultColor = value; + break; + case AnnotationEditorParamsType.HIGHLIGHT_THICKNESS: + HighlightEditor._defaultThickness = value; + break; + } + } + translateInPage(x, y) { + } + get toolbarPosition() { + return this.#lastPoint; + } + get commentButtonPosition() { + return this.#firstPoint; + } + updateParams(type, value) { + switch (type) { + case AnnotationEditorParamsType.HIGHLIGHT_COLOR: + this.#updateColor(value); + break; + case AnnotationEditorParamsType.HIGHLIGHT_THICKNESS: + this.#updateThickness(value); + break; + } + } + static get defaultPropertiesToUpdate() { + return [[AnnotationEditorParamsType.HIGHLIGHT_COLOR, HighlightEditor._defaultColor], [AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, HighlightEditor._defaultThickness]]; + } + get propertiesToUpdate() { + return [[AnnotationEditorParamsType.HIGHLIGHT_COLOR, this.color || HighlightEditor._defaultColor], [AnnotationEditorParamsType.HIGHLIGHT_THICKNESS, this.#thickness || HighlightEditor._defaultThickness], [AnnotationEditorParamsType.HIGHLIGHT_FREE, this.#isFreeHighlight]]; + } + onUpdatedColor() { + this.parent?.drawLayer.updateProperties(this.#id, { + root: { + fill: this.color, + "fill-opacity": this.opacity + } + }); + this.#colorPicker?.updateColor(this.color); + super.onUpdatedColor(); + } + #updateColor(color) { + const setColorAndOpacity = (col, opa) => { + this.color = col; + this.opacity = opa; + this.onUpdatedColor(); + }; + const savedColor = this.color; + const savedOpacity = this.opacity; + this.addCommands({ + cmd: setColorAndOpacity.bind(this, color, HighlightEditor._defaultOpacity), + undo: setColorAndOpacity.bind(this, savedColor, savedOpacity), + post: this._uiManager.updateUI.bind(this._uiManager, this), + mustExec: true, + type: AnnotationEditorParamsType.HIGHLIGHT_COLOR, + overwriteIfSameType: true, + keepUndo: true + }); + this._reportTelemetry({ + action: "color_changed", + color: this._uiManager.getNonHCMColorName(color) + }, true); + } + #updateThickness(thickness) { + const savedThickness = this.#thickness; + const setThickness = (th) => { + this.#thickness = th; + this.#changeThickness(th); + }; + this.addCommands({ + cmd: setThickness.bind(this, thickness), + undo: setThickness.bind(this, savedThickness), + post: this._uiManager.updateUI.bind(this._uiManager, this), + mustExec: true, + type: AnnotationEditorParamsType.INK_THICKNESS, + overwriteIfSameType: true, + keepUndo: true + }); + this._reportTelemetry({ + action: "thickness_changed", + thickness + }, true); + } + get toolbarButtons() { + if (this._uiManager.highlightColors) { + const colorPicker = this.#colorPicker = new ColorPicker({ + editor: this + }); + return [["colorPicker", colorPicker]]; + } + return super.toolbarButtons; + } + disableEditing() { + super.disableEditing(); + this.div.classList.toggle("disabled", true); + } + enableEditing() { + super.enableEditing(); + this.div.classList.toggle("disabled", false); + } + fixAndSetPosition() { + return super.fixAndSetPosition(this.#getRotation()); + } + getBaseTranslation() { + return [0, 0]; + } + getRect(tx, ty) { + return super.getRect(tx, ty, this.#getRotation()); + } + onceAdded(focus) { + if (!this.annotationElementId) { + this.parent.addUndoableEditor(this); + } + if (focus) { + this.div.focus(); + } + } + remove() { + this.#cleanDrawLayer(); + this._reportTelemetry({ + action: "deleted" + }); + super.remove(); + } + rebuild() { + if (!this.parent) { + return; + } + super.rebuild(); + if (this.div === null) { + return; + } + this.#addToDrawLayer(); + if (!this.isAttachedToDOM) { + this.parent.add(this); + } + } + setParent(parent) { + let mustBeSelected = false; + if (this.parent && !parent) { + this.#cleanDrawLayer(); + } else if (parent) { + this.#addToDrawLayer(parent); + mustBeSelected = !this.parent && this.div?.classList.contains("selectedEditor"); + } + super.setParent(parent); + this.show(this._isVisible); + if (mustBeSelected) { + this.select(); + } + } + #changeThickness(thickness) { + if (!this.#isFreeHighlight) { + return; + } + this.#createFreeOutlines({ + highlightOutlines: this.#highlightOutlines.getNewOutline(thickness / 2) + }); + this.fixAndSetPosition(); + this.setDims(this.width, this.height); + } + #cleanDrawLayer() { + if (this.#id === null || !this.parent) { + return; + } + this.parent.drawLayer.remove(this.#id); + this.#id = null; + this.parent.drawLayer.remove(this.#outlineId); + this.#outlineId = null; + } + #addToDrawLayer(parent = this.parent) { + if (this.#id !== null) { + return; + } + ({ + id: this.#id, + clipPathId: this.#clipPathId + } = parent.drawLayer.draw({ + bbox: this.#highlightOutlines.box, + root: { + viewBox: "0 0 1 1", + fill: this.color, + "fill-opacity": this.opacity + }, + rootClass: { + highlight: true, + free: this.#isFreeHighlight + }, + path: { + d: this.#highlightOutlines.toSVGPath() + } + }, false, true)); + this.#outlineId = parent.drawLayer.drawOutline({ + rootClass: { + highlightOutline: true, + free: this.#isFreeHighlight + }, + bbox: this.#focusOutlines.box, + path: { + d: this.#focusOutlines.toSVGPath() + } + }, this.#isFreeHighlight); + if (this.#highlightDiv) { + this.#highlightDiv.style.clipPath = this.#clipPathId; + } + } + static #rotateBbox([x, y, width, height], angle) { + switch (angle) { + case 90: + return [1 - y - height, x, height, width]; + case 180: + return [1 - x - width, 1 - y - height, width, height]; + case 270: + return [y, 1 - x - width, height, width]; + } + return [x, y, width, height]; + } + rotate(angle) { + const { + drawLayer + } = this.parent; + let box; + if (this.#isFreeHighlight) { + angle = (angle - this.rotation + 360) % 360; + box = HighlightEditor.#rotateBbox(this.#highlightOutlines.box, angle); + } else { + box = HighlightEditor.#rotateBbox([this.x, this.y, this.width, this.height], angle); + } + drawLayer.updateProperties(this.#id, { + bbox: box, + root: { + "data-main-rotation": angle + } + }); + drawLayer.updateProperties(this.#outlineId, { + bbox: HighlightEditor.#rotateBbox(this.#focusOutlines.box, angle), + root: { + "data-main-rotation": angle + } + }); + } + render() { + if (this.div) { + return this.div; + } + const div = super.render(); + if (this.#text) { + div.setAttribute("aria-label", this.#text); + div.setAttribute("role", "mark"); + } + if (this.#isFreeHighlight) { + div.classList.add("free"); + } else { + this.div.addEventListener("keydown", this.#keydown.bind(this), { + signal: this._uiManager._signal + }); + } + const highlightDiv = this.#highlightDiv = document.createElement("div"); + div.append(highlightDiv); + highlightDiv.setAttribute("aria-hidden", "true"); + highlightDiv.className = "internal"; + highlightDiv.style.clipPath = this.#clipPathId; + this.setDims(this.width, this.height); + bindEvents(this, this.#highlightDiv, ["pointerover", "pointerleave"]); + this.enableEditing(); + return div; + } + pointerover() { + if (!this.isSelected) { + this.parent?.drawLayer.updateProperties(this.#outlineId, { + rootClass: { + hovered: true + } + }); + } + } + pointerleave() { + if (!this.isSelected) { + this.parent?.drawLayer.updateProperties(this.#outlineId, { + rootClass: { + hovered: false + } + }); + } + } + #keydown(event) { + HighlightEditor._keyboardManager.exec(this, event); + } + _moveCaret(direction) { + this.parent.unselect(this); + switch (direction) { + case 0: + case 2: + this.#setCaret(true); + break; + case 1: + case 3: + this.#setCaret(false); + break; + } + } + #setCaret(start) { + if (!this.#anchorNode) { + return; + } + const selection = window.getSelection(); + if (start) { + selection.setPosition(this.#anchorNode, this.#anchorOffset); + } else { + selection.setPosition(this.#focusNode, this.#focusOffset); + } + } + select() { + super.select(); + if (!this.#outlineId) { + return; + } + this.parent?.drawLayer.updateProperties(this.#outlineId, { + rootClass: { + hovered: false, + selected: true + } + }); + } + unselect() { + super.unselect(); + if (!this.#outlineId) { + return; + } + this.parent?.drawLayer.updateProperties(this.#outlineId, { + rootClass: { + selected: false + } + }); + if (!this.#isFreeHighlight) { + this.#setCaret(false); + } + } + get _mustFixPosition() { + return !this.#isFreeHighlight; + } + show(visible = this._isVisible) { + super.show(visible); + if (this.parent) { + this.parent.drawLayer.updateProperties(this.#id, { + rootClass: { + hidden: !visible + } + }); + this.parent.drawLayer.updateProperties(this.#outlineId, { + rootClass: { + hidden: !visible + } + }); + } + } + #getRotation() { + return this.#isFreeHighlight ? this.rotation : 0; + } + #serializeBoxes() { + if (this.#isFreeHighlight) { + return null; + } + const [pageWidth, pageHeight] = this.pageDimensions; + const [pageX, pageY] = this.pageTranslation; + const boxes = this.#boxes; + const quadPoints = new Float32Array(boxes.length * 8); + let i = 0; + for (const { + x, + y, + width, + height + } of boxes) { + const sx = x * pageWidth + pageX; + const sy = (1 - y) * pageHeight + pageY; + quadPoints[i] = quadPoints[i + 4] = sx; + quadPoints[i + 1] = quadPoints[i + 3] = sy; + quadPoints[i + 2] = quadPoints[i + 6] = sx + width * pageWidth; + quadPoints[i + 5] = quadPoints[i + 7] = sy - height * pageHeight; + i += 8; + } + return quadPoints; + } + #serializeOutlines(rect) { + return this.#highlightOutlines.serialize(rect, this.#getRotation()); + } + static startHighlighting(parent, isLTR, { + target: textLayer, + x, + y + }) { + const { + x: layerX, + y: layerY, + width: parentWidth, + height: parentHeight + } = textLayer.getBoundingClientRect(); + const ac = new AbortController(); + const signal = parent.combinedSignal(ac); + const pointerUpCallback = (e) => { + ac.abort(); + this.#endHighlight(parent, e); + }; + window.addEventListener("blur", pointerUpCallback, { + signal + }); + window.addEventListener("pointerup", pointerUpCallback, { + signal + }); + window.addEventListener("pointerdown", stopEvent, { + capture: true, + passive: false, + signal + }); + window.addEventListener("contextmenu", noContextMenu, { + signal + }); + textLayer.addEventListener("pointermove", this.#highlightMove.bind(this, parent), { + signal + }); + this._freeHighlight = new FreeHighlightOutliner({ + x, + y + }, [layerX, layerY, parentWidth, parentHeight], parent.scale, this._defaultThickness / 2, isLTR, 1e-3); + ({ + id: this._freeHighlightId, + clipPathId: this._freeHighlightClipId + } = parent.drawLayer.draw({ + bbox: [0, 0, 1, 1], + root: { + viewBox: "0 0 1 1", + fill: this._defaultColor, + "fill-opacity": this._defaultOpacity + }, + rootClass: { + highlight: true, + free: true + }, + path: { + d: this._freeHighlight.toSVGPath() + } + }, true, true)); + } + static #highlightMove(parent, event) { + if (this._freeHighlight.add(event)) { + parent.drawLayer.updateProperties(this._freeHighlightId, { + path: { + d: this._freeHighlight.toSVGPath() + } + }); + } + } + static #endHighlight(parent, event) { + if (!this._freeHighlight.isEmpty()) { + parent.createAndAddNewEditor(event, false, { + highlightId: this._freeHighlightId, + highlightOutlines: this._freeHighlight.getOutlines(), + clipPathId: this._freeHighlightClipId, + methodOfCreation: "main_toolbar" + }); + } else { + parent.drawLayer.remove(this._freeHighlightId); + } + this._freeHighlightId = -1; + this._freeHighlight = null; + this._freeHighlightClipId = ""; + } + static async deserialize(data, parent, uiManager) { + let initialData = null; + if (data instanceof HighlightAnnotationElement) { + const { + data: { + quadPoints: quadPoints2, + rect, + rotation, + id, + color: color2, + opacity: opacity2, + popupRef, + richText, + contentsObj, + creationDate, + modificationDate + }, + parent: { + page: { + pageNumber + } + } + } = data; + initialData = data = { + annotationType: AnnotationEditorType.HIGHLIGHT, + color: Array.from(color2), + opacity: opacity2, + quadPoints: quadPoints2, + boxes: null, + pageIndex: pageNumber - 1, + rect: rect.slice(0), + rotation, + annotationElementId: id, + id, + deleted: false, + popupRef, + richText, + comment: contentsObj?.str || null, + creationDate, + modificationDate + }; + } else if (data instanceof InkAnnotationElement) { + const { + data: { + inkLists: inkLists2, + rect, + rotation, + id, + color: color2, + borderStyle: { + rawWidth: thickness + }, + popupRef, + richText, + contentsObj, + creationDate, + modificationDate + }, + parent: { + page: { + pageNumber + } + } + } = data; + initialData = data = { + annotationType: AnnotationEditorType.HIGHLIGHT, + color: Array.from(color2), + thickness, + inkLists: inkLists2, + boxes: null, + pageIndex: pageNumber - 1, + rect: rect.slice(0), + rotation, + annotationElementId: id, + id, + deleted: false, + popupRef, + richText, + comment: contentsObj?.str || null, + creationDate, + modificationDate + }; + } + const { + color, + quadPoints, + inkLists, + opacity + } = data; + const editor = await super.deserialize(data, parent, uiManager); + editor.color = Util.makeHexColor(...color); + editor.opacity = opacity || 1; + if (inkLists) { + editor.#thickness = data.thickness; + } + editor._initialData = initialData; + if (data.comment) { + editor.setCommentData(data); + } + const [pageWidth, pageHeight] = editor.pageDimensions; + const [pageX, pageY] = editor.pageTranslation; + if (quadPoints) { + const boxes = editor.#boxes = []; + for (let i = 0; i < quadPoints.length; i += 8) { + boxes.push({ + x: (quadPoints[i] - pageX) / pageWidth, + y: 1 - (quadPoints[i + 1] - pageY) / pageHeight, + width: (quadPoints[i + 2] - quadPoints[i]) / pageWidth, + height: (quadPoints[i + 1] - quadPoints[i + 5]) / pageHeight + }); + } + editor.#createOutlines(); + editor.#addToDrawLayer(); + editor.rotate(editor.rotation); + } else if (inkLists) { + editor.#isFreeHighlight = true; + const points = inkLists[0]; + const point = { + x: points[0] - pageX, + y: pageHeight - (points[1] - pageY) + }; + const outliner = new FreeHighlightOutliner(point, [0, 0, pageWidth, pageHeight], 1, editor.#thickness / 2, true, 1e-3); + for (let i = 0, ii = points.length; i < ii; i += 2) { + point.x = points[i] - pageX; + point.y = pageHeight - (points[i + 1] - pageY); + outliner.add(point); + } + const { + id, + clipPathId + } = parent.drawLayer.draw({ + bbox: [0, 0, 1, 1], + root: { + viewBox: "0 0 1 1", + fill: editor.color, + "fill-opacity": editor._defaultOpacity + }, + rootClass: { + highlight: true, + free: true + }, + path: { + d: outliner.toSVGPath() + } + }, true, true); + editor.#createFreeOutlines({ + highlightOutlines: outliner.getOutlines(), + highlightId: id, + clipPathId + }); + editor.#addToDrawLayer(); + editor.rotate(editor.parentRotation); + } + return editor; + } + serialize(isForCopying = false) { + if (this.isEmpty() || isForCopying) { + return null; + } + if (this.deleted) { + return this.serializeDeleted(); + } + const color = AnnotationEditor._colorManager.convert(this._uiManager.getNonHCMColor(this.color)); + const serialized = super.serialize(isForCopying); + Object.assign(serialized, { + color, + opacity: this.opacity, + thickness: this.#thickness, + quadPoints: this.#serializeBoxes(), + outlines: this.#serializeOutlines(serialized.rect) + }); + this.addComment(serialized); + if (this.annotationElementId && !this.#hasElementChanged(serialized)) { + return null; + } + serialized.id = this.annotationElementId; + return serialized; + } + #hasElementChanged(serialized) { + const { + color + } = this._initialData; + return this.hasEditedComment || serialized.color.some((c, i) => c !== color[i]); + } + renderAnnotationElement(annotation) { + if (this.deleted) { + annotation.hide(); + return null; + } + annotation.updateEdited({ + rect: this.getPDFRect(), + popup: this.comment + }); + return null; + } + static canCreateNewEmptyEditor() { + return false; + } +} +class DrawingOptions { + #svgProperties = /* @__PURE__ */ Object.create(null); + updateProperty(name, value) { + this[name] = value; + this.updateSVGProperty(name, value); + } + updateProperties(properties) { + if (!properties) { + return; + } + for (const [name, value] of Object.entries(properties)) { + if (!name.startsWith("_")) { + this.updateProperty(name, value); + } + } + } + updateSVGProperty(name, value) { + this.#svgProperties[name] = value; + } + toSVGProperties() { + const root = this.#svgProperties; + this.#svgProperties = /* @__PURE__ */ Object.create(null); + return { + root + }; + } + reset() { + this.#svgProperties = /* @__PURE__ */ Object.create(null); + } + updateAll(options = this) { + this.updateProperties(options); + } + clone() { + unreachable("Not implemented"); + } +} +class DrawingEditor extends AnnotationEditor { + #drawOutlines = null; + #mustBeCommitted; + _colorPicker = null; + _drawId = null; + static _currentDrawId = -1; + static _currentParent = null; + static #currentDraw = null; + static #currentDrawingAC = null; + static #currentDrawingOptions = null; + static #currentPointerId = NaN; + static #currentPointerType = null; + static #currentPointerIds = null; + static #currentMoveTimestamp = NaN; + static _INNER_MARGIN = 3; + constructor(params) { + super(params); + this.#mustBeCommitted = params.mustBeCommitted || false; + this._addOutlines(params); + } + onUpdatedColor() { + this._colorPicker?.update(this.color); + super.onUpdatedColor(); + } + _addOutlines(params) { + if (params.drawOutlines) { + this.#createDrawOutlines(params); + this.#addToDrawLayer(); + } + } + #createDrawOutlines({ + drawOutlines, + drawId, + drawingOptions + }) { + this.#drawOutlines = drawOutlines; + this._drawingOptions ||= drawingOptions; + if (!this.annotationElementId) { + this._uiManager.a11yAlert(`pdfjs-editor-${this.editorType}-added-alert`); + } + if (drawId >= 0) { + this._drawId = drawId; + this.parent.drawLayer.finalizeDraw(drawId, drawOutlines.defaultProperties); + } else { + this._drawId = this.#createDrawing(drawOutlines, this.parent); + } + this.#updateBbox(drawOutlines.box); + } + #createDrawing(drawOutlines, parent) { + const { + id + } = parent.drawLayer.draw(DrawingEditor._mergeSVGProperties(this._drawingOptions.toSVGProperties(), drawOutlines.defaultSVGProperties), false, false); + return id; + } + static _mergeSVGProperties(p1, p2) { + const p1Keys = new Set(Object.keys(p1)); + for (const [key, value] of Object.entries(p2)) { + if (p1Keys.has(key)) { + Object.assign(p1[key], value); + } else { + p1[key] = value; + } + } + return p1; + } + static getDefaultDrawingOptions(_options) { + unreachable("Not implemented"); + } + static get typesMap() { + unreachable("Not implemented"); + } + static get isDrawer() { + return true; + } + static get supportMultipleDrawings() { + return false; + } + static updateDefaultParams(type, value) { + const propertyName = this.typesMap.get(type); + if (propertyName) { + this._defaultDrawingOptions.updateProperty(propertyName, value); + } + if (this._currentParent) { + DrawingEditor.#currentDraw.updateProperty(propertyName, value); + this._currentParent.drawLayer.updateProperties(this._currentDrawId, this._defaultDrawingOptions.toSVGProperties()); + } + } + updateParams(type, value) { + const propertyName = this.constructor.typesMap.get(type); + if (propertyName) { + this._updateProperty(type, propertyName, value); + } + } + static get defaultPropertiesToUpdate() { + const properties = []; + const options = this._defaultDrawingOptions; + for (const [type, name] of this.typesMap) { + properties.push([type, options[name]]); + } + return properties; + } + get propertiesToUpdate() { + const properties = []; + const { + _drawingOptions + } = this; + for (const [type, name] of this.constructor.typesMap) { + properties.push([type, _drawingOptions[name]]); + } + return properties; + } + _updateProperty(type, name, value) { + const options = this._drawingOptions; + const savedValue = options[name]; + const setter = (val) => { + options.updateProperty(name, val); + const bbox = this.#drawOutlines.updateProperty(name, val); + if (bbox) { + this.#updateBbox(bbox); + } + this.parent?.drawLayer.updateProperties(this._drawId, options.toSVGProperties()); + if (type === this.colorType) { + this.onUpdatedColor(); + } + }; + this.addCommands({ + cmd: setter.bind(this, value), + undo: setter.bind(this, savedValue), + post: this._uiManager.updateUI.bind(this._uiManager, this), + mustExec: true, + type, + overwriteIfSameType: true, + keepUndo: true + }); + } + _onResizing() { + this.parent?.drawLayer.updateProperties(this._drawId, DrawingEditor._mergeSVGProperties(this.#drawOutlines.getPathResizingSVGProperties(this.#convertToDrawSpace()), { + bbox: this.#rotateBox() + })); + } + _onResized() { + this.parent?.drawLayer.updateProperties(this._drawId, DrawingEditor._mergeSVGProperties(this.#drawOutlines.getPathResizedSVGProperties(this.#convertToDrawSpace()), { + bbox: this.#rotateBox() + })); + } + _onTranslating(_x, _y) { + this.parent?.drawLayer.updateProperties(this._drawId, { + bbox: this.#rotateBox() + }); + } + _onTranslated() { + this.parent?.drawLayer.updateProperties(this._drawId, DrawingEditor._mergeSVGProperties(this.#drawOutlines.getPathTranslatedSVGProperties(this.#convertToDrawSpace(), this.parentDimensions), { + bbox: this.#rotateBox() + })); + } + _onStartDragging() { + this.parent?.drawLayer.updateProperties(this._drawId, { + rootClass: { + moving: true + } + }); + } + _onStopDragging() { + this.parent?.drawLayer.updateProperties(this._drawId, { + rootClass: { + moving: false + } + }); + } + commit() { + super.commit(); + this.disableEditMode(); + this.disableEditing(); + } + disableEditing() { + super.disableEditing(); + this.div.classList.toggle("disabled", true); + } + enableEditing() { + super.enableEditing(); + this.div.classList.toggle("disabled", false); + } + getBaseTranslation() { + return [0, 0]; + } + get isResizable() { + return true; + } + onceAdded(focus) { + if (!this.annotationElementId) { + this.parent.addUndoableEditor(this); + } + this._isDraggable = true; + if (this.#mustBeCommitted) { + this.#mustBeCommitted = false; + this.commit(); + this.parent.setSelected(this); + if (focus && this.isOnScreen) { + this.div.focus(); + } + } + } + remove() { + this.#cleanDrawLayer(); + super.remove(); + } + rebuild() { + if (!this.parent) { + return; + } + super.rebuild(); + if (this.div === null) { + return; + } + this.#addToDrawLayer(); + this.#updateBbox(this.#drawOutlines.box); + if (!this.isAttachedToDOM) { + this.parent.add(this); + } + } + setParent(parent) { + let mustBeSelected = false; + if (this.parent && !parent) { + this._uiManager.removeShouldRescale(this); + this.#cleanDrawLayer(); + } else if (parent) { + this._uiManager.addShouldRescale(this); + this.#addToDrawLayer(parent); + mustBeSelected = !this.parent && this.div?.classList.contains("selectedEditor"); + } + super.setParent(parent); + if (mustBeSelected) { + this.select(); + } + } + #cleanDrawLayer() { + if (this._drawId === null || !this.parent) { + return; + } + this.parent.drawLayer.remove(this._drawId); + this._drawId = null; + this._drawingOptions.reset(); + } + #addToDrawLayer(parent = this.parent) { + if (this._drawId !== null && this.parent === parent) { + return; + } + if (this._drawId !== null) { + this.parent.drawLayer.updateParent(this._drawId, parent.drawLayer); + return; + } + this._drawingOptions.updateAll(); + this._drawId = this.#createDrawing(this.#drawOutlines, parent); + } + #convertToParentSpace([x, y, width, height]) { + const { + parentDimensions: [pW, pH], + rotation + } = this; + switch (rotation) { + case 90: + return [y, 1 - x, width * (pH / pW), height * (pW / pH)]; + case 180: + return [1 - x, 1 - y, width, height]; + case 270: + return [1 - y, x, width * (pH / pW), height * (pW / pH)]; + default: + return [x, y, width, height]; + } + } + #convertToDrawSpace() { + const { + x, + y, + width, + height, + parentDimensions: [pW, pH], + rotation + } = this; + switch (rotation) { + case 90: + return [1 - y, x, width * (pW / pH), height * (pH / pW)]; + case 180: + return [1 - x, 1 - y, width, height]; + case 270: + return [y, 1 - x, width * (pW / pH), height * (pH / pW)]; + default: + return [x, y, width, height]; + } + } + #updateBbox(bbox) { + [this.x, this.y, this.width, this.height] = this.#convertToParentSpace(bbox); + if (this.div) { + this.fixAndSetPosition(); + this.setDims(); + } + this._onResized(); + } + #rotateBox() { + const { + x, + y, + width, + height, + rotation, + parentRotation, + parentDimensions: [pW, pH] + } = this; + switch ((rotation * 4 + parentRotation) / 90) { + case 1: + return [1 - y - height, x, height, width]; + case 2: + return [1 - x - width, 1 - y - height, width, height]; + case 3: + return [y, 1 - x - width, height, width]; + case 4: + return [x, y - width * (pW / pH), height * (pH / pW), width * (pW / pH)]; + case 5: + return [1 - y, x, width * (pW / pH), height * (pH / pW)]; + case 6: + return [1 - x - height * (pH / pW), 1 - y, height * (pH / pW), width * (pW / pH)]; + case 7: + return [y - width * (pW / pH), 1 - x - height * (pH / pW), width * (pW / pH), height * (pH / pW)]; + case 8: + return [x - width, y - height, width, height]; + case 9: + return [1 - y, x - width, height, width]; + case 10: + return [1 - x, 1 - y, width, height]; + case 11: + return [y - height, 1 - x, height, width]; + case 12: + return [x - height * (pH / pW), y, height * (pH / pW), width * (pW / pH)]; + case 13: + return [1 - y - width * (pW / pH), x - height * (pH / pW), width * (pW / pH), height * (pH / pW)]; + case 14: + return [1 - x, 1 - y - width * (pW / pH), height * (pH / pW), width * (pW / pH)]; + case 15: + return [y, 1 - x, width * (pW / pH), height * (pH / pW)]; + default: + return [x, y, width, height]; + } + } + rotate() { + if (!this.parent) { + return; + } + this.parent.drawLayer.updateProperties(this._drawId, DrawingEditor._mergeSVGProperties({ + bbox: this.#rotateBox() + }, this.#drawOutlines.updateRotation((this.parentRotation - this.rotation + 360) % 360))); + } + onScaleChanging() { + if (!this.parent) { + return; + } + this.#updateBbox(this.#drawOutlines.updateParentDimensions(this.parentDimensions, this.parent.scale)); + } + static onScaleChangingWhenDrawing() { + } + render() { + if (this.div) { + return this.div; + } + let baseX, baseY; + if (this._isCopy) { + baseX = this.x; + baseY = this.y; + } + const div = super.render(); + div.classList.add("draw"); + const drawDiv = document.createElement("div"); + div.append(drawDiv); + drawDiv.setAttribute("aria-hidden", "true"); + drawDiv.className = "internal"; + this.setDims(); + this._uiManager.addShouldRescale(this); + this.disableEditing(); + if (this._isCopy) { + this._moveAfterPaste(baseX, baseY); + } + return div; + } + static createDrawerInstance(_x, _y, _parentWidth, _parentHeight, _rotation) { + unreachable("Not implemented"); + } + static startDrawing(parent, uiManager, _isLTR, event) { + const { + target, + offsetX: x, + offsetY: y, + pointerId, + pointerType + } = event; + if (DrawingEditor.#currentPointerType && DrawingEditor.#currentPointerType !== pointerType) { + return; + } + const { + viewport: { + rotation + } + } = parent; + const { + width: parentWidth, + height: parentHeight + } = target.getBoundingClientRect(); + const ac = DrawingEditor.#currentDrawingAC = new AbortController(); + const signal = parent.combinedSignal(ac); + DrawingEditor.#currentPointerId ||= pointerId; + DrawingEditor.#currentPointerType ??= pointerType; + window.addEventListener("pointerup", (e) => { + if (DrawingEditor.#currentPointerId === e.pointerId) { + this._endDraw(e); + } else { + DrawingEditor.#currentPointerIds?.delete(e.pointerId); + } + }, { + signal + }); + window.addEventListener("pointercancel", (e) => { + if (DrawingEditor.#currentPointerId === e.pointerId) { + this._currentParent.endDrawingSession(); + } else { + DrawingEditor.#currentPointerIds?.delete(e.pointerId); + } + }, { + signal + }); + window.addEventListener("pointerdown", (e) => { + if (DrawingEditor.#currentPointerType !== e.pointerType) { + return; + } + (DrawingEditor.#currentPointerIds ||= /* @__PURE__ */ new Set()).add(e.pointerId); + if (DrawingEditor.#currentDraw.isCancellable()) { + DrawingEditor.#currentDraw.removeLastElement(); + if (DrawingEditor.#currentDraw.isEmpty()) { + this._currentParent.endDrawingSession(true); + } else { + this._endDraw(null); + } + } + }, { + capture: true, + passive: false, + signal + }); + window.addEventListener("contextmenu", noContextMenu, { + signal + }); + target.addEventListener("pointermove", this._drawMove.bind(this), { + signal + }); + target.addEventListener("touchmove", (e) => { + if (e.timeStamp === DrawingEditor.#currentMoveTimestamp) { + stopEvent(e); + } + }, { + signal + }); + parent.toggleDrawing(); + uiManager._editorUndoBar?.hide(); + if (DrawingEditor.#currentDraw) { + parent.drawLayer.updateProperties(this._currentDrawId, DrawingEditor.#currentDraw.startNew(x, y, parentWidth, parentHeight, rotation)); + return; + } + uiManager.updateUIForDefaultProperties(this); + DrawingEditor.#currentDraw = this.createDrawerInstance(x, y, parentWidth, parentHeight, rotation); + DrawingEditor.#currentDrawingOptions = this.getDefaultDrawingOptions(); + this._currentParent = parent; + ({ + id: this._currentDrawId + } = parent.drawLayer.draw(this._mergeSVGProperties(DrawingEditor.#currentDrawingOptions.toSVGProperties(), DrawingEditor.#currentDraw.defaultSVGProperties), true, false)); + } + static _drawMove(event) { + DrawingEditor.#currentMoveTimestamp = -1; + if (!DrawingEditor.#currentDraw) { + return; + } + const { + offsetX, + offsetY, + pointerId + } = event; + if (DrawingEditor.#currentPointerId !== pointerId) { + return; + } + if (DrawingEditor.#currentPointerIds?.size >= 1) { + this._endDraw(event); + return; + } + this._currentParent.drawLayer.updateProperties(this._currentDrawId, DrawingEditor.#currentDraw.add(offsetX, offsetY)); + DrawingEditor.#currentMoveTimestamp = event.timeStamp; + stopEvent(event); + } + static _cleanup(all) { + if (all) { + this._currentDrawId = -1; + this._currentParent = null; + DrawingEditor.#currentDraw = null; + DrawingEditor.#currentDrawingOptions = null; + DrawingEditor.#currentPointerType = null; + DrawingEditor.#currentMoveTimestamp = NaN; + } + if (DrawingEditor.#currentDrawingAC) { + DrawingEditor.#currentDrawingAC.abort(); + DrawingEditor.#currentDrawingAC = null; + DrawingEditor.#currentPointerId = NaN; + DrawingEditor.#currentPointerIds = null; + } + } + static _endDraw(event) { + const parent = this._currentParent; + if (!parent) { + return; + } + parent.toggleDrawing(true); + this._cleanup(false); + if (event?.target === parent.div) { + parent.drawLayer.updateProperties(this._currentDrawId, DrawingEditor.#currentDraw.end(event.offsetX, event.offsetY)); + } + if (this.supportMultipleDrawings) { + const draw = DrawingEditor.#currentDraw; + const drawId = this._currentDrawId; + const lastElement = draw.getLastElement(); + parent.addCommands({ + cmd: () => { + parent.drawLayer.updateProperties(drawId, draw.setLastElement(lastElement)); + }, + undo: () => { + parent.drawLayer.updateProperties(drawId, draw.removeLastElement()); + }, + mustExec: false, + type: AnnotationEditorParamsType.DRAW_STEP + }); + return; + } + this.endDrawing(false); + } + static endDrawing(isAborted) { + const parent = this._currentParent; + if (!parent) { + return null; + } + parent.toggleDrawing(true); + parent.cleanUndoStack(AnnotationEditorParamsType.DRAW_STEP); + if (!DrawingEditor.#currentDraw.isEmpty()) { + const { + pageDimensions: [pageWidth, pageHeight], + scale + } = parent; + const editor = parent.createAndAddNewEditor({ + offsetX: 0, + offsetY: 0 + }, false, { + drawId: this._currentDrawId, + drawOutlines: DrawingEditor.#currentDraw.getOutlines(pageWidth * scale, pageHeight * scale, scale, this._INNER_MARGIN), + drawingOptions: DrawingEditor.#currentDrawingOptions, + mustBeCommitted: !isAborted + }); + this._cleanup(true); + return editor; + } + parent.drawLayer.remove(this._currentDrawId); + this._cleanup(true); + return null; + } + createDrawingOptions(_data) { + } + static deserializeDraw(_pageX, _pageY, _pageWidth, _pageHeight, _innerWidth, _data) { + unreachable("Not implemented"); + } + static async deserialize(data, parent, uiManager) { + const { + rawDims: { + pageWidth, + pageHeight, + pageX, + pageY + } + } = parent.viewport; + const drawOutlines = this.deserializeDraw(pageX, pageY, pageWidth, pageHeight, this._INNER_MARGIN, data); + const editor = await super.deserialize(data, parent, uiManager); + editor.createDrawingOptions(data); + editor.#createDrawOutlines({ + drawOutlines + }); + editor.#addToDrawLayer(); + editor.onScaleChanging(); + editor.rotate(); + return editor; + } + serializeDraw(isForCopying) { + const [pageX, pageY] = this.pageTranslation; + const [pageWidth, pageHeight] = this.pageDimensions; + return this.#drawOutlines.serialize([pageX, pageY, pageWidth, pageHeight], isForCopying); + } + renderAnnotationElement(annotation) { + annotation.updateEdited({ + rect: this.getPDFRect() + }); + return null; + } + static canCreateNewEmptyEditor() { + return false; + } +} +class InkDrawOutliner { + #last = new Float64Array(6); + #line; + #lines; + #rotation; + #thickness; + #points; + #lastSVGPath = ""; + #lastIndex = 0; + #outlines = new InkDrawOutline(); + #parentWidth; + #parentHeight; + constructor(x, y, parentWidth, parentHeight, rotation, thickness) { + this.#parentWidth = parentWidth; + this.#parentHeight = parentHeight; + this.#rotation = rotation; + this.#thickness = thickness; + [x, y] = this.#normalizePoint(x, y); + const line = this.#line = [NaN, NaN, NaN, NaN, x, y]; + this.#points = [x, y]; + this.#lines = [{ + line, + points: this.#points + }]; + this.#last.set(line, 0); + } + updateProperty(name, value) { + if (name === "stroke-width") { + this.#thickness = value; + } + } + #normalizePoint(x, y) { + return Outline._normalizePoint(x, y, this.#parentWidth, this.#parentHeight, this.#rotation); + } + isEmpty() { + return !this.#lines || this.#lines.length === 0; + } + isCancellable() { + return this.#points.length <= 10; + } + add(x, y) { + [x, y] = this.#normalizePoint(x, y); + const [x1, y1, x2, y2] = this.#last.subarray(2, 6); + const diffX = x - x2; + const diffY = y - y2; + const d = Math.hypot(this.#parentWidth * diffX, this.#parentHeight * diffY); + if (d <= 2) { + return null; + } + this.#points.push(x, y); + if (isNaN(x1)) { + this.#last.set([x2, y2, x, y], 2); + this.#line.push(NaN, NaN, NaN, NaN, x, y); + return { + path: { + d: this.toSVGPath() + } + }; + } + if (isNaN(this.#last[0])) { + this.#line.splice(6, 6); + } + this.#last.set([x1, y1, x2, y2, x, y], 0); + this.#line.push(...Outline.createBezierPoints(x1, y1, x2, y2, x, y)); + return { + path: { + d: this.toSVGPath() + } + }; + } + end(x, y) { + const change = this.add(x, y); + if (change) { + return change; + } + if (this.#points.length === 2) { + return { + path: { + d: this.toSVGPath() + } + }; + } + return null; + } + startNew(x, y, parentWidth, parentHeight, rotation) { + this.#parentWidth = parentWidth; + this.#parentHeight = parentHeight; + this.#rotation = rotation; + [x, y] = this.#normalizePoint(x, y); + const line = this.#line = [NaN, NaN, NaN, NaN, x, y]; + this.#points = [x, y]; + const last = this.#lines.at(-1); + if (last) { + last.line = new Float32Array(last.line); + last.points = new Float32Array(last.points); + } + this.#lines.push({ + line, + points: this.#points + }); + this.#last.set(line, 0); + this.#lastIndex = 0; + this.toSVGPath(); + return null; + } + getLastElement() { + return this.#lines.at(-1); + } + setLastElement(element) { + if (!this.#lines) { + return this.#outlines.setLastElement(element); + } + this.#lines.push(element); + this.#line = element.line; + this.#points = element.points; + this.#lastIndex = 0; + return { + path: { + d: this.toSVGPath() + } + }; + } + removeLastElement() { + if (!this.#lines) { + return this.#outlines.removeLastElement(); + } + this.#lines.pop(); + this.#lastSVGPath = ""; + for (let i = 0, ii = this.#lines.length; i < ii; i++) { + const { + line, + points + } = this.#lines[i]; + this.#line = line; + this.#points = points; + this.#lastIndex = 0; + this.toSVGPath(); + } + return { + path: { + d: this.#lastSVGPath + } + }; + } + toSVGPath() { + const firstX = Outline.svgRound(this.#line[4]); + const firstY = Outline.svgRound(this.#line[5]); + if (this.#points.length === 2) { + this.#lastSVGPath = `${this.#lastSVGPath} M ${firstX} ${firstY} Z`; + return this.#lastSVGPath; + } + if (this.#points.length <= 6) { + const i = this.#lastSVGPath.lastIndexOf("M"); + this.#lastSVGPath = `${this.#lastSVGPath.slice(0, i)} M ${firstX} ${firstY}`; + this.#lastIndex = 6; + } + if (this.#points.length === 4) { + const secondX = Outline.svgRound(this.#line[10]); + const secondY = Outline.svgRound(this.#line[11]); + this.#lastSVGPath = `${this.#lastSVGPath} L ${secondX} ${secondY}`; + this.#lastIndex = 12; + return this.#lastSVGPath; + } + const buffer = []; + if (this.#lastIndex === 0) { + buffer.push(`M ${firstX} ${firstY}`); + this.#lastIndex = 6; + } + for (let i = this.#lastIndex, ii = this.#line.length; i < ii; i += 6) { + const [c1x, c1y, c2x, c2y, x, y] = this.#line.slice(i, i + 6).map(Outline.svgRound); + buffer.push(`C${c1x} ${c1y} ${c2x} ${c2y} ${x} ${y}`); + } + this.#lastSVGPath += buffer.join(" "); + this.#lastIndex = this.#line.length; + return this.#lastSVGPath; + } + getOutlines(parentWidth, parentHeight, scale, innerMargin) { + const last = this.#lines.at(-1); + last.line = new Float32Array(last.line); + last.points = new Float32Array(last.points); + this.#outlines.build(this.#lines, parentWidth, parentHeight, scale, this.#rotation, this.#thickness, innerMargin); + this.#last = null; + this.#line = null; + this.#lines = null; + this.#lastSVGPath = null; + return this.#outlines; + } + get defaultSVGProperties() { + return { + root: { + viewBox: "0 0 10000 10000" + }, + rootClass: { + draw: true + }, + bbox: [0, 0, 1, 1] + }; + } +} +class InkDrawOutline extends Outline { + #bbox; + #currentRotation = 0; + #innerMargin; + #lines; + #parentWidth; + #parentHeight; + #parentScale; + #rotation; + #thickness; + build(lines, parentWidth, parentHeight, parentScale, rotation, thickness, innerMargin) { + this.#parentWidth = parentWidth; + this.#parentHeight = parentHeight; + this.#parentScale = parentScale; + this.#rotation = rotation; + this.#thickness = thickness; + this.#innerMargin = innerMargin ?? 0; + this.#lines = lines; + this.#computeBbox(); + } + get thickness() { + return this.#thickness; + } + setLastElement(element) { + this.#lines.push(element); + return { + path: { + d: this.toSVGPath() + } + }; + } + removeLastElement() { + this.#lines.pop(); + return { + path: { + d: this.toSVGPath() + } + }; + } + toSVGPath() { + const buffer = []; + for (const { + line + } of this.#lines) { + buffer.push(`M${Outline.svgRound(line[4])} ${Outline.svgRound(line[5])}`); + if (line.length === 6) { + buffer.push("Z"); + continue; + } + if (line.length === 12 && isNaN(line[6])) { + buffer.push(`L${Outline.svgRound(line[10])} ${Outline.svgRound(line[11])}`); + continue; + } + for (let i = 6, ii = line.length; i < ii; i += 6) { + const [c1x, c1y, c2x, c2y, x, y] = line.subarray(i, i + 6).map(Outline.svgRound); + buffer.push(`C${c1x} ${c1y} ${c2x} ${c2y} ${x} ${y}`); + } + } + return buffer.join(""); + } + serialize([pageX, pageY, pageWidth, pageHeight], isForCopying) { + const serializedLines = []; + const serializedPoints = []; + const [x, y, width, height] = this.#getBBoxWithNoMargin(); + let tx, ty, sx, sy, x1, y1, x2, y2, rescaleFn; + switch (this.#rotation) { + case 0: + rescaleFn = Outline._rescale; + tx = pageX; + ty = pageY + pageHeight; + sx = pageWidth; + sy = -pageHeight; + x1 = pageX + x * pageWidth; + y1 = pageY + (1 - y - height) * pageHeight; + x2 = pageX + (x + width) * pageWidth; + y2 = pageY + (1 - y) * pageHeight; + break; + case 90: + rescaleFn = Outline._rescaleAndSwap; + tx = pageX; + ty = pageY; + sx = pageWidth; + sy = pageHeight; + x1 = pageX + y * pageWidth; + y1 = pageY + x * pageHeight; + x2 = pageX + (y + height) * pageWidth; + y2 = pageY + (x + width) * pageHeight; + break; + case 180: + rescaleFn = Outline._rescale; + tx = pageX + pageWidth; + ty = pageY; + sx = -pageWidth; + sy = pageHeight; + x1 = pageX + (1 - x - width) * pageWidth; + y1 = pageY + y * pageHeight; + x2 = pageX + (1 - x) * pageWidth; + y2 = pageY + (y + height) * pageHeight; + break; + case 270: + rescaleFn = Outline._rescaleAndSwap; + tx = pageX + pageWidth; + ty = pageY + pageHeight; + sx = -pageWidth; + sy = -pageHeight; + x1 = pageX + (1 - y - height) * pageWidth; + y1 = pageY + (1 - x - width) * pageHeight; + x2 = pageX + (1 - y) * pageWidth; + y2 = pageY + (1 - x) * pageHeight; + break; + } + for (const { + line, + points + } of this.#lines) { + serializedLines.push(rescaleFn(line, tx, ty, sx, sy, isForCopying ? new Array(line.length) : null)); + serializedPoints.push(rescaleFn(points, tx, ty, sx, sy, isForCopying ? new Array(points.length) : null)); + } + return { + lines: serializedLines, + points: serializedPoints, + rect: [x1, y1, x2, y2] + }; + } + static deserialize(pageX, pageY, pageWidth, pageHeight, innerMargin, { + paths: { + lines, + points + }, + rotation, + thickness + }) { + const newLines = []; + let tx, ty, sx, sy, rescaleFn; + switch (rotation) { + case 0: + rescaleFn = Outline._rescale; + tx = -pageX / pageWidth; + ty = pageY / pageHeight + 1; + sx = 1 / pageWidth; + sy = -1 / pageHeight; + break; + case 90: + rescaleFn = Outline._rescaleAndSwap; + tx = -pageY / pageHeight; + ty = -pageX / pageWidth; + sx = 1 / pageHeight; + sy = 1 / pageWidth; + break; + case 180: + rescaleFn = Outline._rescale; + tx = pageX / pageWidth + 1; + ty = -pageY / pageHeight; + sx = -1 / pageWidth; + sy = 1 / pageHeight; + break; + case 270: + rescaleFn = Outline._rescaleAndSwap; + tx = pageY / pageHeight + 1; + ty = pageX / pageWidth + 1; + sx = -1 / pageHeight; + sy = -1 / pageWidth; + break; + } + if (!lines) { + lines = []; + for (const point of points) { + const len = point.length; + if (len === 2) { + lines.push(new Float32Array([NaN, NaN, NaN, NaN, point[0], point[1]])); + continue; + } + if (len === 4) { + lines.push(new Float32Array([NaN, NaN, NaN, NaN, point[0], point[1], NaN, NaN, NaN, NaN, point[2], point[3]])); + continue; + } + const line = new Float32Array(3 * (len - 2)); + lines.push(line); + let [x1, y1, x2, y2] = point.subarray(0, 4); + line.set([NaN, NaN, NaN, NaN, x1, y1], 0); + for (let i = 4; i < len; i += 2) { + const x = point[i]; + const y = point[i + 1]; + line.set(Outline.createBezierPoints(x1, y1, x2, y2, x, y), (i - 2) * 3); + [x1, y1, x2, y2] = [x2, y2, x, y]; + } + } + } + for (let i = 0, ii = lines.length; i < ii; i++) { + newLines.push({ + line: rescaleFn(lines[i].map((x) => x ?? NaN), tx, ty, sx, sy), + points: rescaleFn(points[i].map((x) => x ?? NaN), tx, ty, sx, sy) + }); + } + const outlines = new this.prototype.constructor(); + outlines.build(newLines, pageWidth, pageHeight, 1, rotation, thickness, innerMargin); + return outlines; + } + #getMarginComponents(thickness = this.#thickness) { + const margin = this.#innerMargin + thickness / 2 * this.#parentScale; + return this.#rotation % 180 === 0 ? [margin / this.#parentWidth, margin / this.#parentHeight] : [margin / this.#parentHeight, margin / this.#parentWidth]; + } + #getBBoxWithNoMargin() { + const [x, y, width, height] = this.#bbox; + const [marginX, marginY] = this.#getMarginComponents(0); + return [x + marginX, y + marginY, width - 2 * marginX, height - 2 * marginY]; + } + #computeBbox() { + const bbox = this.#bbox = new Float32Array([Infinity, Infinity, -Infinity, -Infinity]); + for (const { + line + } of this.#lines) { + if (line.length <= 12) { + for (let i = 4, ii = line.length; i < ii; i += 6) { + Util.pointBoundingBox(line[i], line[i + 1], bbox); + } + continue; + } + let lastX = line[4], lastY = line[5]; + for (let i = 6, ii = line.length; i < ii; i += 6) { + const [c1x, c1y, c2x, c2y, x, y] = line.subarray(i, i + 6); + Util.bezierBoundingBox(lastX, lastY, c1x, c1y, c2x, c2y, x, y, bbox); + lastX = x; + lastY = y; + } + } + const [marginX, marginY] = this.#getMarginComponents(); + bbox[0] = MathClamp(bbox[0] - marginX, 0, 1); + bbox[1] = MathClamp(bbox[1] - marginY, 0, 1); + bbox[2] = MathClamp(bbox[2] + marginX, 0, 1); + bbox[3] = MathClamp(bbox[3] + marginY, 0, 1); + bbox[2] -= bbox[0]; + bbox[3] -= bbox[1]; + } + get box() { + return this.#bbox; + } + updateProperty(name, value) { + if (name === "stroke-width") { + return this.#updateThickness(value); + } + return null; + } + #updateThickness(thickness) { + const [oldMarginX, oldMarginY] = this.#getMarginComponents(); + this.#thickness = thickness; + const [newMarginX, newMarginY] = this.#getMarginComponents(); + const [diffMarginX, diffMarginY] = [newMarginX - oldMarginX, newMarginY - oldMarginY]; + const bbox = this.#bbox; + bbox[0] -= diffMarginX; + bbox[1] -= diffMarginY; + bbox[2] += 2 * diffMarginX; + bbox[3] += 2 * diffMarginY; + return bbox; + } + updateParentDimensions([width, height], scale) { + const [oldMarginX, oldMarginY] = this.#getMarginComponents(); + this.#parentWidth = width; + this.#parentHeight = height; + this.#parentScale = scale; + const [newMarginX, newMarginY] = this.#getMarginComponents(); + const diffMarginX = newMarginX - oldMarginX; + const diffMarginY = newMarginY - oldMarginY; + const bbox = this.#bbox; + bbox[0] -= diffMarginX; + bbox[1] -= diffMarginY; + bbox[2] += 2 * diffMarginX; + bbox[3] += 2 * diffMarginY; + return bbox; + } + updateRotation(rotation) { + this.#currentRotation = rotation; + return { + path: { + transform: this.rotationTransform + } + }; + } + get viewBox() { + return this.#bbox.map(Outline.svgRound).join(" "); + } + get defaultProperties() { + const [x, y] = this.#bbox; + return { + root: { + viewBox: this.viewBox + }, + path: { + "transform-origin": `${Outline.svgRound(x)} ${Outline.svgRound(y)}` + } + }; + } + get rotationTransform() { + const [, , width, height] = this.#bbox; + let a = 0, b = 0, c = 0, d = 0, e = 0, f = 0; + switch (this.#currentRotation) { + case 90: + b = height / width; + c = -width / height; + e = width; + break; + case 180: + a = -1; + d = -1; + e = width; + f = height; + break; + case 270: + b = -height / width; + c = width / height; + f = height; + break; + default: + return ""; + } + return `matrix(${a} ${b} ${c} ${d} ${Outline.svgRound(e)} ${Outline.svgRound(f)})`; + } + getPathResizingSVGProperties([newX, newY, newWidth, newHeight]) { + const [marginX, marginY] = this.#getMarginComponents(); + const [x, y, width, height] = this.#bbox; + if (Math.abs(width - marginX) <= Outline.PRECISION || Math.abs(height - marginY) <= Outline.PRECISION) { + const tx = newX + newWidth / 2 - (x + width / 2); + const ty = newY + newHeight / 2 - (y + height / 2); + return { + path: { + "transform-origin": `${Outline.svgRound(newX)} ${Outline.svgRound(newY)}`, + transform: `${this.rotationTransform} translate(${tx} ${ty})` + } + }; + } + const s1x = (newWidth - 2 * marginX) / (width - 2 * marginX); + const s1y = (newHeight - 2 * marginY) / (height - 2 * marginY); + const s2x = width / newWidth; + const s2y = height / newHeight; + return { + path: { + "transform-origin": `${Outline.svgRound(x)} ${Outline.svgRound(y)}`, + transform: `${this.rotationTransform} scale(${s2x} ${s2y}) translate(${Outline.svgRound(marginX)} ${Outline.svgRound(marginY)}) scale(${s1x} ${s1y}) translate(${Outline.svgRound(-marginX)} ${Outline.svgRound(-marginY)})` + } + }; + } + getPathResizedSVGProperties([newX, newY, newWidth, newHeight]) { + const [marginX, marginY] = this.#getMarginComponents(); + const bbox = this.#bbox; + const [x, y, width, height] = bbox; + bbox[0] = newX; + bbox[1] = newY; + bbox[2] = newWidth; + bbox[3] = newHeight; + if (Math.abs(width - marginX) <= Outline.PRECISION || Math.abs(height - marginY) <= Outline.PRECISION) { + const tx2 = newX + newWidth / 2 - (x + width / 2); + const ty2 = newY + newHeight / 2 - (y + height / 2); + for (const { + line, + points + } of this.#lines) { + Outline._translate(line, tx2, ty2, line); + Outline._translate(points, tx2, ty2, points); + } + return { + root: { + viewBox: this.viewBox + }, + path: { + "transform-origin": `${Outline.svgRound(newX)} ${Outline.svgRound(newY)}`, + transform: this.rotationTransform || null, + d: this.toSVGPath() + } + }; + } + const s1x = (newWidth - 2 * marginX) / (width - 2 * marginX); + const s1y = (newHeight - 2 * marginY) / (height - 2 * marginY); + const tx = -s1x * (x + marginX) + newX + marginX; + const ty = -s1y * (y + marginY) + newY + marginY; + if (s1x !== 1 || s1y !== 1 || tx !== 0 || ty !== 0) { + for (const { + line, + points + } of this.#lines) { + Outline._rescale(line, tx, ty, s1x, s1y, line); + Outline._rescale(points, tx, ty, s1x, s1y, points); + } + } + return { + root: { + viewBox: this.viewBox + }, + path: { + "transform-origin": `${Outline.svgRound(newX)} ${Outline.svgRound(newY)}`, + transform: this.rotationTransform || null, + d: this.toSVGPath() + } + }; + } + getPathTranslatedSVGProperties([newX, newY], parentDimensions) { + const [newParentWidth, newParentHeight] = parentDimensions; + const bbox = this.#bbox; + const tx = newX - bbox[0]; + const ty = newY - bbox[1]; + if (this.#parentWidth === newParentWidth && this.#parentHeight === newParentHeight) { + for (const { + line, + points + } of this.#lines) { + Outline._translate(line, tx, ty, line); + Outline._translate(points, tx, ty, points); + } + } else { + const sx = this.#parentWidth / newParentWidth; + const sy = this.#parentHeight / newParentHeight; + this.#parentWidth = newParentWidth; + this.#parentHeight = newParentHeight; + for (const { + line, + points + } of this.#lines) { + Outline._rescale(line, tx, ty, sx, sy, line); + Outline._rescale(points, tx, ty, sx, sy, points); + } + bbox[2] *= sx; + bbox[3] *= sy; + } + bbox[0] = newX; + bbox[1] = newY; + return { + root: { + viewBox: this.viewBox + }, + path: { + d: this.toSVGPath(), + "transform-origin": `${Outline.svgRound(newX)} ${Outline.svgRound(newY)}` + } + }; + } + get defaultSVGProperties() { + const bbox = this.#bbox; + return { + root: { + viewBox: this.viewBox + }, + rootClass: { + draw: true + }, + path: { + d: this.toSVGPath(), + "transform-origin": `${Outline.svgRound(bbox[0])} ${Outline.svgRound(bbox[1])}`, + transform: this.rotationTransform || null + }, + bbox + }; + } +} +class InkDrawingOptions extends DrawingOptions { + constructor(viewerParameters) { + super(); + this._viewParameters = viewerParameters; + super.updateProperties({ + fill: "none", + stroke: AnnotationEditor._defaultLineColor, + "stroke-opacity": 1, + "stroke-width": 1, + "stroke-linecap": "round", + "stroke-linejoin": "round", + "stroke-miterlimit": 10 + }); + } + updateSVGProperty(name, value) { + if (name === "stroke-width") { + value ??= this["stroke-width"]; + value *= this._viewParameters.realScale; + } + super.updateSVGProperty(name, value); + } + clone() { + const clone = new InkDrawingOptions(this._viewParameters); + clone.updateAll(this); + return clone; + } +} +class InkEditor extends DrawingEditor { + static _type = "ink"; + static _editorType = AnnotationEditorType.INK; + static _defaultDrawingOptions = null; + constructor(params) { + super({ + ...params, + name: "inkEditor" + }); + this._willKeepAspectRatio = true; + this.defaultL10nId = "pdfjs-editor-ink-editor"; + } + static initialize(l10n, uiManager) { + AnnotationEditor.initialize(l10n, uiManager); + this._defaultDrawingOptions = new InkDrawingOptions(uiManager.viewParameters); + } + static getDefaultDrawingOptions(options) { + const clone = this._defaultDrawingOptions.clone(); + clone.updateProperties(options); + return clone; + } + static get supportMultipleDrawings() { + return true; + } + static get typesMap() { + return shadow(this, "typesMap", /* @__PURE__ */ new Map([[AnnotationEditorParamsType.INK_THICKNESS, "stroke-width"], [AnnotationEditorParamsType.INK_COLOR, "stroke"], [AnnotationEditorParamsType.INK_OPACITY, "stroke-opacity"]])); + } + static createDrawerInstance(x, y, parentWidth, parentHeight, rotation) { + return new InkDrawOutliner(x, y, parentWidth, parentHeight, rotation, this._defaultDrawingOptions["stroke-width"]); + } + static deserializeDraw(pageX, pageY, pageWidth, pageHeight, innerMargin, data) { + return InkDrawOutline.deserialize(pageX, pageY, pageWidth, pageHeight, innerMargin, data); + } + static async deserialize(data, parent, uiManager) { + let initialData = null; + if (data instanceof InkAnnotationElement) { + const { + data: { + inkLists, + rect, + rotation, + id, + color, + opacity, + borderStyle: { + rawWidth: thickness + }, + popupRef, + richText, + contentsObj, + creationDate, + modificationDate + }, + parent: { + page: { + pageNumber + } + } + } = data; + initialData = data = { + annotationType: AnnotationEditorType.INK, + color: Array.from(color), + thickness, + opacity, + paths: { + points: inkLists + }, + boxes: null, + pageIndex: pageNumber - 1, + rect: rect.slice(0), + rotation, + annotationElementId: id, + id, + deleted: false, + popupRef, + richText, + comment: contentsObj?.str || null, + creationDate, + modificationDate + }; + } + const editor = await super.deserialize(data, parent, uiManager); + editor._initialData = initialData; + if (data.comment) { + editor.setCommentData(data); + } + return editor; + } + get toolbarButtons() { + this._colorPicker ||= new BasicColorPicker(this); + return [["colorPicker", this._colorPicker]]; + } + get colorType() { + return AnnotationEditorParamsType.INK_COLOR; + } + get color() { + return this._drawingOptions.stroke; + } + get opacity() { + return this._drawingOptions["stroke-opacity"]; + } + onScaleChanging() { + if (!this.parent) { + return; + } + super.onScaleChanging(); + const { + _drawId, + _drawingOptions, + parent + } = this; + _drawingOptions.updateSVGProperty("stroke-width"); + parent.drawLayer.updateProperties(_drawId, _drawingOptions.toSVGProperties()); + } + static onScaleChangingWhenDrawing() { + const parent = this._currentParent; + if (!parent) { + return; + } + super.onScaleChangingWhenDrawing(); + this._defaultDrawingOptions.updateSVGProperty("stroke-width"); + parent.drawLayer.updateProperties(this._currentDrawId, this._defaultDrawingOptions.toSVGProperties()); + } + createDrawingOptions({ + color, + thickness, + opacity + }) { + this._drawingOptions = InkEditor.getDefaultDrawingOptions({ + stroke: Util.makeHexColor(...color), + "stroke-width": thickness, + "stroke-opacity": opacity + }); + } + serialize(isForCopying = false) { + if (this.isEmpty()) { + return null; + } + if (this.deleted) { + return this.serializeDeleted(); + } + const { + lines, + points + } = this.serializeDraw(isForCopying); + const { + _drawingOptions: { + stroke, + "stroke-opacity": opacity, + "stroke-width": thickness + } + } = this; + const serialized = Object.assign(super.serialize(isForCopying), { + color: AnnotationEditor._colorManager.convert(stroke), + opacity, + thickness, + paths: { + lines, + points + } + }); + this.addComment(serialized); + if (isForCopying) { + serialized.isCopy = true; + return serialized; + } + if (this.annotationElementId && !this.#hasElementChanged(serialized)) { + return null; + } + serialized.id = this.annotationElementId; + return serialized; + } + #hasElementChanged(serialized) { + const { + color, + thickness, + opacity, + pageIndex + } = this._initialData; + return this.hasEditedComment || this._hasBeenMoved || this._hasBeenResized || serialized.color.some((c, i) => c !== color[i]) || serialized.thickness !== thickness || serialized.opacity !== opacity || serialized.pageIndex !== pageIndex; + } + renderAnnotationElement(annotation) { + if (this.deleted) { + annotation.hide(); + return null; + } + const { + points, + rect + } = this.serializeDraw(false); + annotation.updateEdited({ + rect, + thickness: this._drawingOptions["stroke-width"], + points, + popup: this.comment + }); + return null; + } +} +class ContourDrawOutline extends InkDrawOutline { + toSVGPath() { + let path = super.toSVGPath(); + if (!path.endsWith("Z")) { + path += "Z"; + } + return path; + } +} +const BASE_HEADER_LENGTH = 8; +const POINTS_PROPERTIES_NUMBER = 3; +class SignatureExtractor { + static #PARAMETERS = { + maxDim: 512, + sigmaSFactor: 0.02, + sigmaR: 25, + kernelSize: 16 + }; + static #neighborIndexToId(i0, j0, i, j) { + i -= i0; + j -= j0; + if (i === 0) { + return j > 0 ? 0 : 4; + } + if (i === 1) { + return j + 6; + } + return 2 - j; + } + static #neighborIdToIndex = new Int32Array([0, 1, -1, 1, -1, 0, -1, -1, 0, -1, 1, -1, 1, 0, 1, 1]); + static #clockwiseNonZero(buf, width, i0, j0, i, j, offset) { + const id = this.#neighborIndexToId(i0, j0, i, j); + for (let k = 0; k < 8; k++) { + const kk = (-k + id - offset + 16) % 8; + const shiftI = this.#neighborIdToIndex[2 * kk]; + const shiftJ = this.#neighborIdToIndex[2 * kk + 1]; + if (buf[(i0 + shiftI) * width + (j0 + shiftJ)] !== 0) { + return kk; + } + } + return -1; + } + static #counterClockwiseNonZero(buf, width, i0, j0, i, j, offset) { + const id = this.#neighborIndexToId(i0, j0, i, j); + for (let k = 0; k < 8; k++) { + const kk = (k + id + offset + 16) % 8; + const shiftI = this.#neighborIdToIndex[2 * kk]; + const shiftJ = this.#neighborIdToIndex[2 * kk + 1]; + if (buf[(i0 + shiftI) * width + (j0 + shiftJ)] !== 0) { + return kk; + } + } + return -1; + } + static #findContours(buf, width, height, threshold) { + const N = buf.length; + const types = new Int32Array(N); + for (let i = 0; i < N; i++) { + types[i] = buf[i] <= threshold ? 1 : 0; + } + for (let i = 1; i < height - 1; i++) { + types[i * width] = types[i * width + width - 1] = 0; + } + for (let i = 0; i < width; i++) { + types[i] = types[width * height - 1 - i] = 0; + } + let nbd = 1; + let lnbd; + const contours = []; + for (let i = 1; i < height - 1; i++) { + lnbd = 1; + for (let j = 1; j < width - 1; j++) { + const ij = i * width + j; + const pix = types[ij]; + if (pix === 0) { + continue; + } + let i2 = i; + let j2 = j; + if (pix === 1 && types[ij - 1] === 0) { + nbd += 1; + j2 -= 1; + } else if (pix >= 1 && types[ij + 1] === 0) { + nbd += 1; + j2 += 1; + if (pix > 1) { + lnbd = pix; + } + } else { + if (pix !== 1) { + lnbd = Math.abs(pix); + } + continue; + } + const points = [j, i]; + const isHole = j2 === j + 1; + const contour = { + isHole, + points, + id: nbd, + parent: 0 + }; + contours.push(contour); + let contour0; + for (const c of contours) { + if (c.id === lnbd) { + contour0 = c; + break; + } + } + if (!contour0) { + contour.parent = isHole ? lnbd : 0; + } else if (contour0.isHole) { + contour.parent = isHole ? contour0.parent : lnbd; + } else { + contour.parent = isHole ? lnbd : contour0.parent; + } + const k = this.#clockwiseNonZero(types, width, i, j, i2, j2, 0); + if (k === -1) { + types[ij] = -nbd; + if (types[ij] !== 1) { + lnbd = Math.abs(types[ij]); + } + continue; + } + let shiftI = this.#neighborIdToIndex[2 * k]; + let shiftJ = this.#neighborIdToIndex[2 * k + 1]; + const i1 = i + shiftI; + const j1 = j + shiftJ; + i2 = i1; + j2 = j1; + let i3 = i; + let j3 = j; + while (true) { + const kk = this.#counterClockwiseNonZero(types, width, i3, j3, i2, j2, 1); + shiftI = this.#neighborIdToIndex[2 * kk]; + shiftJ = this.#neighborIdToIndex[2 * kk + 1]; + const i4 = i3 + shiftI; + const j4 = j3 + shiftJ; + points.push(j4, i4); + const ij3 = i3 * width + j3; + if (types[ij3 + 1] === 0) { + types[ij3] = -nbd; + } else if (types[ij3] === 1) { + types[ij3] = nbd; + } + if (i4 === i && j4 === j && i3 === i1 && j3 === j1) { + if (types[ij] !== 1) { + lnbd = Math.abs(types[ij]); + } + break; + } else { + i2 = i3; + j2 = j3; + i3 = i4; + j3 = j4; + } + } + } + } + return contours; + } + static #douglasPeuckerHelper(points, start, end, output) { + if (end - start <= 4) { + for (let i = start; i < end - 2; i += 2) { + output.push(points[i], points[i + 1]); + } + return; + } + const ax = points[start]; + const ay = points[start + 1]; + const abx = points[end - 4] - ax; + const aby = points[end - 3] - ay; + const dist = Math.hypot(abx, aby); + const nabx = abx / dist; + const naby = aby / dist; + const aa = nabx * ay - naby * ax; + const m = aby / abx; + const invS = 1 / dist; + const phi = Math.atan(m); + const cosPhi = Math.cos(phi); + const sinPhi = Math.sin(phi); + const tmax = invS * (Math.abs(cosPhi) + Math.abs(sinPhi)); + const poly = invS * (1 - tmax + tmax ** 2); + const partialPhi = Math.max(Math.atan(Math.abs(sinPhi + cosPhi) * poly), Math.atan(Math.abs(sinPhi - cosPhi) * poly)); + let dmax = 0; + let index = start; + for (let i = start + 2; i < end - 2; i += 2) { + const d = Math.abs(aa - nabx * points[i + 1] + naby * points[i]); + if (d > dmax) { + index = i; + dmax = d; + } + } + if (dmax > (dist * partialPhi) ** 2) { + this.#douglasPeuckerHelper(points, start, index + 2, output); + this.#douglasPeuckerHelper(points, index, end, output); + } else { + output.push(ax, ay); + } + } + static #douglasPeucker(points) { + const output = []; + const len = points.length; + this.#douglasPeuckerHelper(points, 0, len, output); + output.push(points[len - 2], points[len - 1]); + return output.length <= 4 ? null : output; + } + static #bilateralFilter(buf, width, height, sigmaS, sigmaR, kernelSize) { + const kernel = new Float32Array(kernelSize ** 2); + const sigmaS2 = -2 * sigmaS ** 2; + const halfSize = kernelSize >> 1; + for (let i = 0; i < kernelSize; i++) { + const x = (i - halfSize) ** 2; + for (let j = 0; j < kernelSize; j++) { + kernel[i * kernelSize + j] = Math.exp((x + (j - halfSize) ** 2) / sigmaS2); + } + } + const rangeValues = new Float32Array(256); + const sigmaR2 = -2 * sigmaR ** 2; + for (let i = 0; i < 256; i++) { + rangeValues[i] = Math.exp(i ** 2 / sigmaR2); + } + const N = buf.length; + const out = new Uint8Array(N); + const histogram = new Uint32Array(256); + for (let i = 0; i < height; i++) { + for (let j = 0; j < width; j++) { + const ij = i * width + j; + const center = buf[ij]; + let sum = 0; + let norm = 0; + for (let k = 0; k < kernelSize; k++) { + const y = i + k - halfSize; + if (y < 0 || y >= height) { + continue; + } + for (let l = 0; l < kernelSize; l++) { + const x = j + l - halfSize; + if (x < 0 || x >= width) { + continue; + } + const neighbour = buf[y * width + x]; + const w = kernel[k * kernelSize + l] * rangeValues[Math.abs(neighbour - center)]; + sum += neighbour * w; + norm += w; + } + } + const pix = out[ij] = Math.round(sum / norm); + histogram[pix]++; + } + } + return [out, histogram]; + } + static #getHistogram(buf) { + const histogram = new Uint32Array(256); + for (const g of buf) { + histogram[g]++; + } + return histogram; + } + static #toUint8(buf) { + const N = buf.length; + const out = new Uint8ClampedArray(N >> 2); + let max = -Infinity; + let min = Infinity; + for (let i = 0, ii = out.length; i < ii; i++) { + const pix = out[i] = buf[i << 2]; + max = Math.max(max, pix); + min = Math.min(min, pix); + } + const ratio = 255 / (max - min); + for (let i = 0, ii = out.length; i < ii; i++) { + out[i] = (out[i] - min) * ratio; + } + return out; + } + static #guessThreshold(histogram) { + let i; + let M = -Infinity; + let L = -Infinity; + const min = histogram.findIndex((v) => v !== 0); + let pos = min; + let spos = min; + for (i = min; i < 256; i++) { + const v = histogram[i]; + if (v > M) { + if (i - pos > L) { + L = i - pos; + spos = i - 1; + } + M = v; + pos = i; + } + } + for (i = spos - 1; i >= 0; i--) { + if (histogram[i] > histogram[i + 1]) { + break; + } + } + return i; + } + static #getGrayPixels(bitmap) { + const originalBitmap = bitmap; + const { + width, + height + } = bitmap; + const { + maxDim + } = this.#PARAMETERS; + let newWidth = width; + let newHeight = height; + if (width > maxDim || height > maxDim) { + let prevWidth = width; + let prevHeight = height; + let steps = Math.log2(Math.max(width, height) / maxDim); + const isteps = Math.floor(steps); + steps = steps === isteps ? isteps - 1 : isteps; + for (let i = 0; i < steps; i++) { + newWidth = Math.ceil(prevWidth / 2); + newHeight = Math.ceil(prevHeight / 2); + const offscreen2 = new OffscreenCanvas(newWidth, newHeight); + const ctx2 = offscreen2.getContext("2d"); + ctx2.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight); + prevWidth = newWidth; + prevHeight = newHeight; + if (bitmap !== originalBitmap) { + bitmap.close(); + } + bitmap = offscreen2.transferToImageBitmap(); + } + const ratio = Math.min(maxDim / newWidth, maxDim / newHeight); + newWidth = Math.round(newWidth * ratio); + newHeight = Math.round(newHeight * ratio); + } + const offscreen = new OffscreenCanvas(newWidth, newHeight); + const ctx = offscreen.getContext("2d", { + willReadFrequently: true + }); + ctx.fillStyle = "white"; + ctx.fillRect(0, 0, newWidth, newHeight); + ctx.filter = "grayscale(1)"; + ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, newWidth, newHeight); + const grayImage = ctx.getImageData(0, 0, newWidth, newHeight).data; + const uint8Buf = this.#toUint8(grayImage); + return [uint8Buf, newWidth, newHeight]; + } + static extractContoursFromText(text, { + fontFamily, + fontStyle, + fontWeight + }, pageWidth, pageHeight, rotation, innerMargin) { + let canvas = new OffscreenCanvas(1, 1); + let ctx = canvas.getContext("2d", { + alpha: false + }); + const fontSize = 200; + const font = ctx.font = `${fontStyle} ${fontWeight} ${fontSize}px ${fontFamily}`; + const { + actualBoundingBoxLeft, + actualBoundingBoxRight, + actualBoundingBoxAscent, + actualBoundingBoxDescent, + fontBoundingBoxAscent, + fontBoundingBoxDescent, + width + } = ctx.measureText(text); + const SCALE = 1.5; + const canvasWidth = Math.ceil(Math.max(Math.abs(actualBoundingBoxLeft) + Math.abs(actualBoundingBoxRight) || 0, width) * SCALE); + const canvasHeight = Math.ceil(Math.max(Math.abs(actualBoundingBoxAscent) + Math.abs(actualBoundingBoxDescent) || fontSize, Math.abs(fontBoundingBoxAscent) + Math.abs(fontBoundingBoxDescent) || fontSize) * SCALE); + canvas = new OffscreenCanvas(canvasWidth, canvasHeight); + ctx = canvas.getContext("2d", { + alpha: true, + willReadFrequently: true + }); + ctx.font = font; + ctx.filter = "grayscale(1)"; + ctx.fillStyle = "white"; + ctx.fillRect(0, 0, canvasWidth, canvasHeight); + ctx.fillStyle = "black"; + ctx.fillText(text, canvasWidth * (SCALE - 1) / 2, canvasHeight * (3 - SCALE) / 2); + const uint8Buf = this.#toUint8(ctx.getImageData(0, 0, canvasWidth, canvasHeight).data); + const histogram = this.#getHistogram(uint8Buf); + const threshold = this.#guessThreshold(histogram); + const contourList = this.#findContours(uint8Buf, canvasWidth, canvasHeight, threshold); + return this.processDrawnLines({ + lines: { + curves: contourList, + width: canvasWidth, + height: canvasHeight + }, + pageWidth, + pageHeight, + rotation, + innerMargin, + mustSmooth: true, + areContours: true + }); + } + static process(bitmap, pageWidth, pageHeight, rotation, innerMargin) { + const [uint8Buf, width, height] = this.#getGrayPixels(bitmap); + const [buffer, histogram] = this.#bilateralFilter(uint8Buf, width, height, Math.hypot(width, height) * this.#PARAMETERS.sigmaSFactor, this.#PARAMETERS.sigmaR, this.#PARAMETERS.kernelSize); + const threshold = this.#guessThreshold(histogram); + const contourList = this.#findContours(buffer, width, height, threshold); + return this.processDrawnLines({ + lines: { + curves: contourList, + width, + height + }, + pageWidth, + pageHeight, + rotation, + innerMargin, + mustSmooth: true, + areContours: true + }); + } + static processDrawnLines({ + lines, + pageWidth, + pageHeight, + rotation, + innerMargin, + mustSmooth, + areContours + }) { + if (rotation % 180 !== 0) { + [pageWidth, pageHeight] = [pageHeight, pageWidth]; + } + const { + curves, + width, + height + } = lines; + const thickness = lines.thickness ?? 0; + const linesAndPoints = []; + const ratio = Math.min(pageWidth / width, pageHeight / height); + const xScale = ratio / pageWidth; + const yScale = ratio / pageHeight; + const newCurves = []; + for (const { + points + } of curves) { + const reducedPoints = mustSmooth ? this.#douglasPeucker(points) : points; + if (!reducedPoints) { + continue; + } + newCurves.push(reducedPoints); + const len = reducedPoints.length; + const newPoints = new Float32Array(len); + const line = new Float32Array(3 * (len === 2 ? 2 : len - 2)); + linesAndPoints.push({ + line, + points: newPoints + }); + if (len === 2) { + newPoints[0] = reducedPoints[0] * xScale; + newPoints[1] = reducedPoints[1] * yScale; + line.set([NaN, NaN, NaN, NaN, newPoints[0], newPoints[1]], 0); + continue; + } + let [x1, y1, x2, y2] = reducedPoints; + x1 *= xScale; + y1 *= yScale; + x2 *= xScale; + y2 *= yScale; + newPoints.set([x1, y1, x2, y2], 0); + line.set([NaN, NaN, NaN, NaN, x1, y1], 0); + for (let i = 4; i < len; i += 2) { + const x = newPoints[i] = reducedPoints[i] * xScale; + const y = newPoints[i + 1] = reducedPoints[i + 1] * yScale; + line.set(Outline.createBezierPoints(x1, y1, x2, y2, x, y), (i - 2) * 3); + [x1, y1, x2, y2] = [x2, y2, x, y]; + } + } + if (linesAndPoints.length === 0) { + return null; + } + const outline = areContours ? new ContourDrawOutline() : new InkDrawOutline(); + outline.build(linesAndPoints, pageWidth, pageHeight, 1, rotation, areContours ? 0 : thickness, innerMargin); + return { + outline, + newCurves, + areContours, + thickness, + width, + height + }; + } + static async compressSignature({ + outlines, + areContours, + thickness, + width, + height + }) { + let minDiff = Infinity; + let maxDiff = -Infinity; + let outlinesLength = 0; + for (const points of outlines) { + outlinesLength += points.length; + for (let i = 2, ii = points.length; i < ii; i++) { + const dx = points[i] - points[i - 2]; + minDiff = Math.min(minDiff, dx); + maxDiff = Math.max(maxDiff, dx); + } + } + let bufferType; + if (minDiff >= -128 && maxDiff <= 127) { + bufferType = Int8Array; + } else if (minDiff >= -32768 && maxDiff <= 32767) { + bufferType = Int16Array; + } else { + bufferType = Int32Array; + } + const len = outlines.length; + const headerLength = BASE_HEADER_LENGTH + POINTS_PROPERTIES_NUMBER * len; + const header = new Uint32Array(headerLength); + let offset = 0; + header[offset++] = headerLength * Uint32Array.BYTES_PER_ELEMENT + (outlinesLength - 2 * len) * bufferType.BYTES_PER_ELEMENT; + header[offset++] = 0; + header[offset++] = width; + header[offset++] = height; + header[offset++] = areContours ? 0 : 1; + header[offset++] = Math.max(0, Math.floor(thickness ?? 0)); + header[offset++] = len; + header[offset++] = bufferType.BYTES_PER_ELEMENT; + for (const points of outlines) { + header[offset++] = points.length - 2; + header[offset++] = points[0]; + header[offset++] = points[1]; + } + const cs = new CompressionStream("deflate-raw"); + const writer = cs.writable.getWriter(); + await writer.ready; + writer.write(header); + const BufferCtor = bufferType.prototype.constructor; + for (const points of outlines) { + const diffs = new BufferCtor(points.length - 2); + for (let i = 2, ii = points.length; i < ii; i++) { + diffs[i - 2] = points[i] - points[i - 2]; + } + writer.write(diffs); + } + writer.close(); + const buf = await new Response(cs.readable).arrayBuffer(); + const bytes = new Uint8Array(buf); + return toBase64Util(bytes); + } + static async decompressSignature(signatureData) { + try { + const bytes = fromBase64Util(signatureData); + const { + readable, + writable + } = new DecompressionStream("deflate-raw"); + const writer = writable.getWriter(); + await writer.ready; + writer.write(bytes).then(async () => { + await writer.ready; + await writer.close(); + }).catch(() => { + }); + let data = null; + let offset = 0; + for await (const chunk of readable) { + data ||= new Uint8Array(new Uint32Array(chunk.buffer, 0, 4)[0]); + data.set(chunk, offset); + offset += chunk.length; + } + const header = new Uint32Array(data.buffer, 0, data.length >> 2); + const version2 = header[1]; + if (version2 !== 0) { + throw new Error(`Invalid version: ${version2}`); + } + const width = header[2]; + const height = header[3]; + const areContours = header[4] === 0; + const thickness = header[5]; + const numberOfDrawings = header[6]; + const bufferType = header[7]; + const outlines = []; + const diffsOffset = (BASE_HEADER_LENGTH + POINTS_PROPERTIES_NUMBER * numberOfDrawings) * Uint32Array.BYTES_PER_ELEMENT; + let diffs; + switch (bufferType) { + case Int8Array.BYTES_PER_ELEMENT: + diffs = new Int8Array(data.buffer, diffsOffset); + break; + case Int16Array.BYTES_PER_ELEMENT: + diffs = new Int16Array(data.buffer, diffsOffset); + break; + case Int32Array.BYTES_PER_ELEMENT: + diffs = new Int32Array(data.buffer, diffsOffset); + break; + } + offset = 0; + for (let i = 0; i < numberOfDrawings; i++) { + const len = header[POINTS_PROPERTIES_NUMBER * i + BASE_HEADER_LENGTH]; + const points = new Float32Array(len + 2); + outlines.push(points); + for (let j = 0; j < POINTS_PROPERTIES_NUMBER - 1; j++) { + points[j] = header[POINTS_PROPERTIES_NUMBER * i + BASE_HEADER_LENGTH + j + 1]; + } + for (let j = 0; j < len; j++) { + points[j + 2] = points[j] + diffs[offset++]; + } + } + return { + areContours, + thickness, + outlines, + width, + height + }; + } catch (e) { + warn(`decompressSignature: ${e}`); + return null; + } + } +} +class SignatureOptions extends DrawingOptions { + constructor() { + super(); + super.updateProperties({ + fill: AnnotationEditor._defaultLineColor, + "stroke-width": 0 + }); + } + clone() { + const clone = new SignatureOptions(); + clone.updateAll(this); + return clone; + } +} +class DrawnSignatureOptions extends InkDrawingOptions { + constructor(viewerParameters) { + super(viewerParameters); + super.updateProperties({ + stroke: AnnotationEditor._defaultLineColor, + "stroke-width": 1 + }); + } + clone() { + const clone = new DrawnSignatureOptions(this._viewParameters); + clone.updateAll(this); + return clone; + } +} +class SignatureEditor extends DrawingEditor { + #isExtracted = false; + #description = null; + #signatureData = null; + #signatureUUID = null; + static _type = "signature"; + static _editorType = AnnotationEditorType.SIGNATURE; + static _defaultDrawingOptions = null; + constructor(params) { + super({ + ...params, + mustBeCommitted: true, + name: "signatureEditor" + }); + this._willKeepAspectRatio = true; + this.#signatureData = params.signatureData || null; + this.#description = null; + this.defaultL10nId = "pdfjs-editor-signature-editor1"; + } + static initialize(l10n, uiManager) { + AnnotationEditor.initialize(l10n, uiManager); + this._defaultDrawingOptions = new SignatureOptions(); + this._defaultDrawnSignatureOptions = new DrawnSignatureOptions(uiManager.viewParameters); + } + static getDefaultDrawingOptions(options) { + const clone = this._defaultDrawingOptions.clone(); + clone.updateProperties(options); + return clone; + } + static get supportMultipleDrawings() { + return false; + } + static get typesMap() { + return shadow(this, "typesMap", /* @__PURE__ */ new Map()); + } + static get isDrawer() { + return false; + } + get telemetryFinalData() { + return { + type: "signature", + hasDescription: !!this.#description + }; + } + static computeTelemetryFinalData(data) { + const hasDescriptionStats = data.get("hasDescription"); + return { + hasAltText: hasDescriptionStats.get(true) ?? 0, + hasNoAltText: hasDescriptionStats.get(false) ?? 0 + }; + } + get isResizable() { + return true; + } + onScaleChanging() { + if (this._drawId === null) { + return; + } + super.onScaleChanging(); + } + render() { + if (this.div) { + return this.div; + } + let baseX, baseY; + const { + _isCopy + } = this; + if (_isCopy) { + this._isCopy = false; + baseX = this.x; + baseY = this.y; + } + super.render(); + if (this._drawId === null) { + if (this.#signatureData) { + const { + lines, + mustSmooth, + areContours, + description, + uuid, + heightInPage + } = this.#signatureData; + const { + rawDims: { + pageWidth, + pageHeight + }, + rotation + } = this.parent.viewport; + const outline = SignatureExtractor.processDrawnLines({ + lines, + pageWidth, + pageHeight, + rotation, + innerMargin: SignatureEditor._INNER_MARGIN, + mustSmooth, + areContours + }); + this.addSignature(outline, heightInPage, description, uuid); + } else { + this.div.setAttribute("data-l10n-args", JSON.stringify({ + description: "" + })); + this.div.hidden = true; + this._uiManager.getSignature(this); + } + } else { + this.div.setAttribute("data-l10n-args", JSON.stringify({ + description: this.#description || "" + })); + } + if (_isCopy) { + this._isCopy = true; + this._moveAfterPaste(baseX, baseY); + } + return this.div; + } + setUuid(uuid) { + this.#signatureUUID = uuid; + this.addEditToolbar(); + } + getUuid() { + return this.#signatureUUID; + } + get description() { + return this.#description; + } + set description(description) { + this.#description = description; + if (!this.div) { + return; + } + this.div.setAttribute("data-l10n-args", JSON.stringify({ + description + })); + super.addEditToolbar().then((toolbar) => { + toolbar?.updateEditSignatureButton(description); + }); + } + getSignaturePreview() { + const { + newCurves, + areContours, + thickness, + width, + height + } = this.#signatureData; + const maxDim = Math.max(width, height); + const outlineData = SignatureExtractor.processDrawnLines({ + lines: { + curves: newCurves.map((points) => ({ + points + })), + thickness, + width, + height + }, + pageWidth: maxDim, + pageHeight: maxDim, + rotation: 0, + innerMargin: 0, + mustSmooth: false, + areContours + }); + return { + areContours, + outline: outlineData.outline + }; + } + get toolbarButtons() { + if (this._uiManager.signatureManager) { + return [["editSignature", this._uiManager.signatureManager]]; + } + return super.toolbarButtons; + } + addSignature(data, heightInPage, description, uuid) { + const { + x: savedX, + y: savedY + } = this; + const { + outline + } = this.#signatureData = data; + this.#isExtracted = outline instanceof ContourDrawOutline; + this.description = description; + let drawingOptions; + if (this.#isExtracted) { + drawingOptions = SignatureEditor.getDefaultDrawingOptions(); + } else { + drawingOptions = SignatureEditor._defaultDrawnSignatureOptions.clone(); + drawingOptions.updateProperties({ + "stroke-width": outline.thickness + }); + } + this._addOutlines({ + drawOutlines: outline, + drawingOptions + }); + const [, pageHeight] = this.pageDimensions; + let newHeight = heightInPage / pageHeight; + newHeight = newHeight >= 1 ? 0.5 : newHeight; + this.width *= newHeight / this.height; + if (this.width >= 1) { + newHeight *= 0.9 / this.width; + this.width = 0.9; + } + this.height = newHeight; + this.setDims(); + this.x = savedX; + this.y = savedY; + this.center(); + this._onResized(); + this.onScaleChanging(); + this.rotate(); + this._uiManager.addToAnnotationStorage(this); + this.setUuid(uuid); + this._reportTelemetry({ + action: "pdfjs.signature.inserted", + data: { + hasBeenSaved: !!uuid, + hasDescription: !!description + } + }); + this.div.hidden = false; + } + getFromImage(bitmap) { + const { + rawDims: { + pageWidth, + pageHeight + }, + rotation + } = this.parent.viewport; + return SignatureExtractor.process(bitmap, pageWidth, pageHeight, rotation, SignatureEditor._INNER_MARGIN); + } + getFromText(text, fontInfo) { + const { + rawDims: { + pageWidth, + pageHeight + }, + rotation + } = this.parent.viewport; + return SignatureExtractor.extractContoursFromText(text, fontInfo, pageWidth, pageHeight, rotation, SignatureEditor._INNER_MARGIN); + } + getDrawnSignature(curves) { + const { + rawDims: { + pageWidth, + pageHeight + }, + rotation + } = this.parent.viewport; + return SignatureExtractor.processDrawnLines({ + lines: curves, + pageWidth, + pageHeight, + rotation, + innerMargin: SignatureEditor._INNER_MARGIN, + mustSmooth: false, + areContours: false + }); + } + createDrawingOptions({ + areContours, + thickness + }) { + if (areContours) { + this._drawingOptions = SignatureEditor.getDefaultDrawingOptions(); + } else { + this._drawingOptions = SignatureEditor._defaultDrawnSignatureOptions.clone(); + this._drawingOptions.updateProperties({ + "stroke-width": thickness + }); + } + } + serialize(isForCopying = false) { + if (this.isEmpty()) { + return null; + } + const { + lines, + points + } = this.serializeDraw(isForCopying); + const { + _drawingOptions: { + "stroke-width": thickness + } + } = this; + const serialized = Object.assign(super.serialize(isForCopying), { + isSignature: true, + areContours: this.#isExtracted, + color: [0, 0, 0], + thickness: this.#isExtracted ? 0 : thickness + }); + this.addComment(serialized); + if (isForCopying) { + serialized.paths = { + lines, + points + }; + serialized.uuid = this.#signatureUUID; + serialized.isCopy = true; + } else { + serialized.lines = lines; + } + if (this.#description) { + serialized.accessibilityData = { + type: "Figure", + alt: this.#description + }; + } + return serialized; + } + static deserializeDraw(pageX, pageY, pageWidth, pageHeight, innerMargin, data) { + if (data.areContours) { + return ContourDrawOutline.deserialize(pageX, pageY, pageWidth, pageHeight, innerMargin, data); + } + return InkDrawOutline.deserialize(pageX, pageY, pageWidth, pageHeight, innerMargin, data); + } + static async deserialize(data, parent, uiManager) { + const editor = await super.deserialize(data, parent, uiManager); + editor.#isExtracted = data.areContours; + editor.description = data.accessibilityData?.alt || ""; + editor.#signatureUUID = data.uuid; + return editor; + } +} +class StampEditor extends AnnotationEditor { + #bitmap = null; + #bitmapId = null; + #bitmapPromise = null; + #bitmapUrl = null; + #bitmapFile = null; + #bitmapFileName = ""; + #canvas = null; + #missingCanvas = false; + #resizeTimeoutId = null; + #isSvg = false; + #hasBeenAddedInUndoStack = false; + static _type = "stamp"; + static _editorType = AnnotationEditorType.STAMP; + constructor(params) { + super({ + ...params, + name: "stampEditor" + }); + this.#bitmapUrl = params.bitmapUrl; + this.#bitmapFile = params.bitmapFile; + this.defaultL10nId = "pdfjs-editor-stamp-editor"; + } + static initialize(l10n, uiManager) { + AnnotationEditor.initialize(l10n, uiManager); + } + static isHandlingMimeForPasting(mime) { + return SupportedImageMimeTypes.includes(mime); + } + static paste(item, parent) { + parent.pasteEditor({ + mode: AnnotationEditorType.STAMP + }, { + bitmapFile: item.getAsFile() + }); + } + altTextFinish() { + if (this._uiManager.useNewAltTextFlow) { + this.div.hidden = false; + } + super.altTextFinish(); + } + get telemetryFinalData() { + return { + type: "stamp", + hasAltText: !!this.altTextData?.altText + }; + } + static computeTelemetryFinalData(data) { + const hasAltTextStats = data.get("hasAltText"); + return { + hasAltText: hasAltTextStats.get(true) ?? 0, + hasNoAltText: hasAltTextStats.get(false) ?? 0 + }; + } + #getBitmapFetched(data, fromId = false) { + if (!data) { + this.remove(); + return; + } + this.#bitmap = data.bitmap; + if (!fromId) { + this.#bitmapId = data.id; + this.#isSvg = data.isSvg; + } + if (data.file) { + this.#bitmapFileName = data.file.name; + } + this.#createCanvas(); + } + #getBitmapDone() { + this.#bitmapPromise = null; + this._uiManager.enableWaiting(false); + if (!this.#canvas) { + return; + } + if (this._uiManager.useNewAltTextWhenAddingImage && this._uiManager.useNewAltTextFlow && this.#bitmap) { + this.addEditToolbar().then(() => { + this._editToolbar.hide(); + this._uiManager.editAltText(this, true); + }); + return; + } + if (!this._uiManager.useNewAltTextWhenAddingImage && this._uiManager.useNewAltTextFlow && this.#bitmap) { + this._reportTelemetry({ + action: "pdfjs.image.image_added", + data: { + alt_text_modal: false, + alt_text_type: "empty" + } + }); + try { + this.mlGuessAltText(); + } catch { + } + } + this.div.focus(); + } + async mlGuessAltText(imageData = null, updateAltTextData = true) { + if (this.hasAltTextData()) { + return null; + } + const { + mlManager + } = this._uiManager; + if (!mlManager) { + throw new Error("No ML."); + } + if (!await mlManager.isEnabledFor("altText")) { + throw new Error("ML isn't enabled for alt text."); + } + const { + data, + width, + height + } = imageData || this.copyCanvas(null, null, true).imageData; + const response = await mlManager.guess({ + name: "altText", + request: { + data, + width, + height, + channels: data.length / (width * height) + } + }); + if (!response) { + throw new Error("No response from the AI service."); + } + if (response.error) { + throw new Error("Error from the AI service."); + } + if (response.cancel) { + return null; + } + if (!response.output) { + throw new Error("No valid response from the AI service."); + } + const altText = response.output; + await this.setGuessedAltText(altText); + if (updateAltTextData && !this.hasAltTextData()) { + this.altTextData = { + alt: altText, + decorative: false + }; + } + return altText; + } + #getBitmap() { + if (this.#bitmapId) { + this._uiManager.enableWaiting(true); + this._uiManager.imageManager.getFromId(this.#bitmapId).then((data) => this.#getBitmapFetched(data, true)).finally(() => this.#getBitmapDone()); + return; + } + if (this.#bitmapUrl) { + const url = this.#bitmapUrl; + this.#bitmapUrl = null; + this._uiManager.enableWaiting(true); + this.#bitmapPromise = this._uiManager.imageManager.getFromUrl(url).then((data) => this.#getBitmapFetched(data)).finally(() => this.#getBitmapDone()); + return; + } + if (this.#bitmapFile) { + const file = this.#bitmapFile; + this.#bitmapFile = null; + this._uiManager.enableWaiting(true); + this.#bitmapPromise = this._uiManager.imageManager.getFromFile(file).then((data) => this.#getBitmapFetched(data)).finally(() => this.#getBitmapDone()); + return; + } + const input = document.createElement("input"); + input.type = "file"; + input.accept = SupportedImageMimeTypes.join(","); + const signal = this._uiManager._signal; + this.#bitmapPromise = new Promise((resolve) => { + input.addEventListener("change", async () => { + if (!input.files || input.files.length === 0) { + this.remove(); + } else { + this._uiManager.enableWaiting(true); + const data = await this._uiManager.imageManager.getFromFile(input.files[0]); + this._reportTelemetry({ + action: "pdfjs.image.image_selected", + data: { + alt_text_modal: this._uiManager.useNewAltTextFlow + } + }); + this.#getBitmapFetched(data); + } + resolve(); + }, { + signal + }); + input.addEventListener("cancel", () => { + this.remove(); + resolve(); + }, { + signal + }); + }).finally(() => this.#getBitmapDone()); + input.click(); + } + remove() { + if (this.#bitmapId) { + this.#bitmap = null; + this._uiManager.imageManager.deleteId(this.#bitmapId); + this.#canvas?.remove(); + this.#canvas = null; + if (this.#resizeTimeoutId) { + clearTimeout(this.#resizeTimeoutId); + this.#resizeTimeoutId = null; + } + } + super.remove(); + } + rebuild() { + if (!this.parent) { + if (this.#bitmapId) { + this.#getBitmap(); + } + return; + } + super.rebuild(); + if (this.div === null) { + return; + } + if (this.#bitmapId && this.#canvas === null) { + this.#getBitmap(); + } + if (!this.isAttachedToDOM) { + this.parent.add(this); + } + } + onceAdded(focus) { + this._isDraggable = true; + if (focus) { + this.div.focus(); + } + } + isEmpty() { + return !(this.#bitmapPromise || this.#bitmap || this.#bitmapUrl || this.#bitmapFile || this.#bitmapId || this.#missingCanvas); + } + get toolbarButtons() { + return [["altText", this.createAltText()]]; + } + get isResizable() { + return true; + } + render() { + if (this.div) { + return this.div; + } + let baseX, baseY; + if (this._isCopy) { + baseX = this.x; + baseY = this.y; + } + super.render(); + this.div.hidden = true; + this.createAltText(); + if (!this.#missingCanvas) { + if (this.#bitmap) { + this.#createCanvas(); + } else { + this.#getBitmap(); + } + } + if (this._isCopy) { + this._moveAfterPaste(baseX, baseY); + } + this._uiManager.addShouldRescale(this); + return this.div; + } + setCanvas(annotationElementId, canvas) { + const { + id: bitmapId, + bitmap + } = this._uiManager.imageManager.getFromCanvas(annotationElementId, canvas); + canvas.remove(); + if (bitmapId && this._uiManager.imageManager.isValidId(bitmapId)) { + this.#bitmapId = bitmapId; + if (bitmap) { + this.#bitmap = bitmap; + } + this.#missingCanvas = false; + this.#createCanvas(); + } + } + _onResized() { + this.onScaleChanging(); + } + onScaleChanging() { + if (!this.parent) { + return; + } + if (this.#resizeTimeoutId !== null) { + clearTimeout(this.#resizeTimeoutId); + } + const TIME_TO_WAIT = 200; + this.#resizeTimeoutId = setTimeout(() => { + this.#resizeTimeoutId = null; + this.#drawBitmap(); + }, TIME_TO_WAIT); + } + #createCanvas() { + const { + div + } = this; + let { + width, + height + } = this.#bitmap; + const [pageWidth, pageHeight] = this.pageDimensions; + const MAX_RATIO = 0.75; + if (this.width) { + width = this.width * pageWidth; + height = this.height * pageHeight; + } else if (width > MAX_RATIO * pageWidth || height > MAX_RATIO * pageHeight) { + const factor = Math.min(MAX_RATIO * pageWidth / width, MAX_RATIO * pageHeight / height); + width *= factor; + height *= factor; + } + this._uiManager.enableWaiting(false); + const canvas = this.#canvas = document.createElement("canvas"); + canvas.setAttribute("role", "img"); + this.addContainer(canvas); + this.width = width / pageWidth; + this.height = height / pageHeight; + this.setDims(); + if (this._initialOptions?.isCentered) { + this.center(); + } else { + this.fixAndSetPosition(); + } + this._initialOptions = null; + if (!this._uiManager.useNewAltTextWhenAddingImage || !this._uiManager.useNewAltTextFlow || this.annotationElementId) { + div.hidden = false; + } + this.#drawBitmap(); + if (!this.#hasBeenAddedInUndoStack) { + this.parent.addUndoableEditor(this); + this.#hasBeenAddedInUndoStack = true; + } + this._reportTelemetry({ + action: "inserted_image" + }); + if (this.#bitmapFileName) { + this.div.setAttribute("aria-description", this.#bitmapFileName); + } + if (!this.annotationElementId) { + this._uiManager.a11yAlert("pdfjs-editor-stamp-added-alert"); + } + } + copyCanvas(maxDataDimension, maxPreviewDimension, createImageData = false) { + if (!maxDataDimension) { + maxDataDimension = 224; + } + const { + width: bitmapWidth, + height: bitmapHeight + } = this.#bitmap; + const outputScale = new OutputScale(); + let bitmap = this.#bitmap; + let width = bitmapWidth, height = bitmapHeight; + let canvas = null; + if (maxPreviewDimension) { + if (bitmapWidth > maxPreviewDimension || bitmapHeight > maxPreviewDimension) { + const ratio = Math.min(maxPreviewDimension / bitmapWidth, maxPreviewDimension / bitmapHeight); + width = Math.floor(bitmapWidth * ratio); + height = Math.floor(bitmapHeight * ratio); + } + canvas = document.createElement("canvas"); + const scaledWidth = canvas.width = Math.ceil(width * outputScale.sx); + const scaledHeight = canvas.height = Math.ceil(height * outputScale.sy); + if (!this.#isSvg) { + bitmap = this.#scaleBitmap(scaledWidth, scaledHeight); + } + const ctx = canvas.getContext("2d"); + ctx.filter = this._uiManager.hcmFilter; + let white = "white", black = "#cfcfd8"; + if (this._uiManager.hcmFilter !== "none") { + black = "black"; + } else if (ColorScheme.isDarkMode) { + white = "#8f8f9d"; + black = "#42414d"; + } + const boxDim = 15; + const boxDimWidth = boxDim * outputScale.sx; + const boxDimHeight = boxDim * outputScale.sy; + const pattern = new OffscreenCanvas(boxDimWidth * 2, boxDimHeight * 2); + const patternCtx = pattern.getContext("2d"); + patternCtx.fillStyle = white; + patternCtx.fillRect(0, 0, boxDimWidth * 2, boxDimHeight * 2); + patternCtx.fillStyle = black; + patternCtx.fillRect(0, 0, boxDimWidth, boxDimHeight); + patternCtx.fillRect(boxDimWidth, boxDimHeight, boxDimWidth, boxDimHeight); + ctx.fillStyle = ctx.createPattern(pattern, "repeat"); + ctx.fillRect(0, 0, scaledWidth, scaledHeight); + ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, scaledWidth, scaledHeight); + } + let imageData = null; + if (createImageData) { + let dataWidth, dataHeight; + if (outputScale.symmetric && bitmap.width < maxDataDimension && bitmap.height < maxDataDimension) { + dataWidth = bitmap.width; + dataHeight = bitmap.height; + } else { + bitmap = this.#bitmap; + if (bitmapWidth > maxDataDimension || bitmapHeight > maxDataDimension) { + const ratio = Math.min(maxDataDimension / bitmapWidth, maxDataDimension / bitmapHeight); + dataWidth = Math.floor(bitmapWidth * ratio); + dataHeight = Math.floor(bitmapHeight * ratio); + if (!this.#isSvg) { + bitmap = this.#scaleBitmap(dataWidth, dataHeight); + } + } + } + const offscreen = new OffscreenCanvas(dataWidth, dataHeight); + const offscreenCtx = offscreen.getContext("2d", { + willReadFrequently: true + }); + offscreenCtx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, dataWidth, dataHeight); + imageData = { + width: dataWidth, + height: dataHeight, + data: offscreenCtx.getImageData(0, 0, dataWidth, dataHeight).data + }; + } + return { + canvas, + width, + height, + imageData + }; + } + #scaleBitmap(width, height) { + const { + width: bitmapWidth, + height: bitmapHeight + } = this.#bitmap; + let newWidth = bitmapWidth; + let newHeight = bitmapHeight; + let bitmap = this.#bitmap; + while (newWidth > 2 * width || newHeight > 2 * height) { + const prevWidth = newWidth; + const prevHeight = newHeight; + if (newWidth > 2 * width) { + newWidth = newWidth >= 16384 ? Math.floor(newWidth / 2) - 1 : Math.ceil(newWidth / 2); + } + if (newHeight > 2 * height) { + newHeight = newHeight >= 16384 ? Math.floor(newHeight / 2) - 1 : Math.ceil(newHeight / 2); + } + const offscreen = new OffscreenCanvas(newWidth, newHeight); + const ctx = offscreen.getContext("2d"); + ctx.drawImage(bitmap, 0, 0, prevWidth, prevHeight, 0, 0, newWidth, newHeight); + bitmap = offscreen.transferToImageBitmap(); + } + return bitmap; + } + #drawBitmap() { + const [parentWidth, parentHeight] = this.parentDimensions; + const { + width, + height + } = this; + const outputScale = new OutputScale(); + const scaledWidth = Math.ceil(width * parentWidth * outputScale.sx); + const scaledHeight = Math.ceil(height * parentHeight * outputScale.sy); + const canvas = this.#canvas; + if (!canvas || canvas.width === scaledWidth && canvas.height === scaledHeight) { + return; + } + canvas.width = scaledWidth; + canvas.height = scaledHeight; + const bitmap = this.#isSvg ? this.#bitmap : this.#scaleBitmap(scaledWidth, scaledHeight); + const ctx = canvas.getContext("2d"); + ctx.filter = this._uiManager.hcmFilter; + ctx.drawImage(bitmap, 0, 0, bitmap.width, bitmap.height, 0, 0, scaledWidth, scaledHeight); + } + #serializeBitmap(toUrl) { + if (toUrl) { + if (this.#isSvg) { + const url = this._uiManager.imageManager.getSvgUrl(this.#bitmapId); + if (url) { + return url; + } + } + const canvas = document.createElement("canvas"); + ({ + width: canvas.width, + height: canvas.height + } = this.#bitmap); + const ctx = canvas.getContext("2d"); + ctx.drawImage(this.#bitmap, 0, 0); + return canvas.toDataURL(); + } + if (this.#isSvg) { + const [pageWidth, pageHeight] = this.pageDimensions; + const width = Math.round(this.width * pageWidth * PixelsPerInch.PDF_TO_CSS_UNITS); + const height = Math.round(this.height * pageHeight * PixelsPerInch.PDF_TO_CSS_UNITS); + const offscreen = new OffscreenCanvas(width, height); + const ctx = offscreen.getContext("2d"); + ctx.drawImage(this.#bitmap, 0, 0, this.#bitmap.width, this.#bitmap.height, 0, 0, width, height); + return offscreen.transferToImageBitmap(); + } + return structuredClone(this.#bitmap); + } + static async deserialize(data, parent, uiManager) { + let initialData = null; + let missingCanvas = false; + if (data instanceof StampAnnotationElement) { + const { + data: { + rect: rect2, + rotation, + id, + structParent, + popupRef, + richText, + contentsObj, + creationDate, + modificationDate + }, + container, + parent: { + page: { + pageNumber + } + }, + canvas + } = data; + let bitmapId2, bitmap2; + if (canvas) { + delete data.canvas; + ({ + id: bitmapId2, + bitmap: bitmap2 + } = uiManager.imageManager.getFromCanvas(container.id, canvas)); + canvas.remove(); + } else { + missingCanvas = true; + data._hasNoCanvas = true; + } + const altText = (await parent._structTree.getAriaAttributes(`${AnnotationPrefix}${id}`))?.get("aria-label") || ""; + initialData = data = { + annotationType: AnnotationEditorType.STAMP, + bitmapId: bitmapId2, + bitmap: bitmap2, + pageIndex: pageNumber - 1, + rect: rect2.slice(0), + rotation, + annotationElementId: id, + id, + deleted: false, + accessibilityData: { + decorative: false, + altText + }, + isSvg: false, + structParent, + popupRef, + richText, + comment: contentsObj?.str || null, + creationDate, + modificationDate + }; + } + const editor = await super.deserialize(data, parent, uiManager); + const { + rect, + bitmap, + bitmapUrl, + bitmapId, + isSvg, + accessibilityData + } = data; + if (missingCanvas) { + uiManager.addMissingCanvas(data.id, editor); + editor.#missingCanvas = true; + } else if (bitmapId && uiManager.imageManager.isValidId(bitmapId)) { + editor.#bitmapId = bitmapId; + if (bitmap) { + editor.#bitmap = bitmap; + } + } else { + editor.#bitmapUrl = bitmapUrl; + } + editor.#isSvg = isSvg; + const [parentWidth, parentHeight] = editor.pageDimensions; + editor.width = (rect[2] - rect[0]) / parentWidth; + editor.height = (rect[3] - rect[1]) / parentHeight; + if (accessibilityData) { + editor.altTextData = accessibilityData; + } + editor._initialData = initialData; + if (data.comment) { + editor.setCommentData(data); + } + editor.#hasBeenAddedInUndoStack = !!initialData; + return editor; + } + serialize(isForCopying = false, context = null) { + if (this.isEmpty()) { + return null; + } + if (this.deleted) { + return this.serializeDeleted(); + } + const serialized = Object.assign(super.serialize(isForCopying), { + bitmapId: this.#bitmapId, + isSvg: this.#isSvg + }); + this.addComment(serialized); + if (isForCopying) { + serialized.bitmapUrl = this.#serializeBitmap(true); + serialized.accessibilityData = this.serializeAltText(true); + serialized.isCopy = true; + return serialized; + } + const { + decorative, + altText + } = this.serializeAltText(false); + if (!decorative && altText) { + serialized.accessibilityData = { + type: "Figure", + alt: altText + }; + } + if (this.annotationElementId) { + const changes = this.#hasElementChanged(serialized); + if (changes.isSame) { + return null; + } + if (changes.isSameAltText) { + delete serialized.accessibilityData; + } else { + serialized.accessibilityData.structParent = this._initialData.structParent ?? -1; + } + serialized.id = this.annotationElementId; + delete serialized.bitmapId; + return serialized; + } + if (context === null) { + return serialized; + } + context.stamps ||= /* @__PURE__ */ new Map(); + const area = this.#isSvg ? (serialized.rect[2] - serialized.rect[0]) * (serialized.rect[3] - serialized.rect[1]) : null; + if (!context.stamps.has(this.#bitmapId)) { + context.stamps.set(this.#bitmapId, { + area, + serialized + }); + serialized.bitmap = this.#serializeBitmap(false); + } else if (this.#isSvg) { + const prevData = context.stamps.get(this.#bitmapId); + if (area > prevData.area) { + prevData.area = area; + prevData.serialized.bitmap.close(); + prevData.serialized.bitmap = this.#serializeBitmap(false); + } + } + return serialized; + } + #hasElementChanged(serialized) { + const { + pageIndex, + accessibilityData: { + altText + } + } = this._initialData; + const isSamePageIndex = serialized.pageIndex === pageIndex; + const isSameAltText = (serialized.accessibilityData?.alt || "") === altText; + return { + isSame: !this.hasEditedComment && !this._hasBeenMoved && !this._hasBeenResized && isSamePageIndex && isSameAltText, + isSameAltText + }; + } + renderAnnotationElement(annotation) { + if (this.deleted) { + annotation.hide(); + return null; + } + annotation.updateEdited({ + rect: this.getPDFRect(), + popup: this.comment + }); + return null; + } +} +class AnnotationEditorLayer { + #accessibilityManager; + #allowClick = false; + #annotationLayer = null; + #clickAC = null; + #editorFocusTimeoutId = null; + #editors = /* @__PURE__ */ new Map(); + #hadPointerDown = false; + #isDisabling = false; + #isEnabling = false; + #drawingAC = null; + #focusedElement = null; + #textLayer = null; + #textSelectionAC = null; + #textLayerDblClickAC = null; + #lastPointerDownTimestamp = -1; + #uiManager; + static _initialized = false; + static #editorTypes = new Map([FreeTextEditor, InkEditor, StampEditor, HighlightEditor, SignatureEditor].map((type) => [type._editorType, type])); + constructor({ + uiManager, + pageIndex, + div, + structTreeLayer, + accessibilityManager, + annotationLayer, + drawLayer, + textLayer, + viewport, + l10n + }) { + const editorTypes = [...AnnotationEditorLayer.#editorTypes.values()]; + if (!AnnotationEditorLayer._initialized) { + AnnotationEditorLayer._initialized = true; + for (const editorType of editorTypes) { + editorType.initialize(l10n, uiManager); + } + } + uiManager.registerEditorTypes(editorTypes); + this.#uiManager = uiManager; + this.pageIndex = pageIndex; + this.div = div; + this.#accessibilityManager = accessibilityManager; + this.#annotationLayer = annotationLayer; + this.viewport = viewport; + this.#textLayer = textLayer; + this.drawLayer = drawLayer; + this._structTree = structTreeLayer; + this.#uiManager.addLayer(this); + } + get isEmpty() { + return this.#editors.size === 0; + } + get isInvisible() { + return this.isEmpty && this.#uiManager.getMode() === AnnotationEditorType.NONE; + } + updateToolbar(options) { + this.#uiManager.updateToolbar(options); + } + updateMode(mode = this.#uiManager.getMode()) { + this.#cleanup(); + switch (mode) { + case AnnotationEditorType.NONE: + this.div.classList.toggle("nonEditing", true); + this.disableTextSelection(); + this.togglePointerEvents(false); + this.toggleAnnotationLayerPointerEvents(true); + this.disableClick(); + return; + case AnnotationEditorType.INK: + this.disableTextSelection(); + this.togglePointerEvents(true); + this.enableClick(); + break; + case AnnotationEditorType.HIGHLIGHT: + this.enableTextSelection(); + this.togglePointerEvents(false); + this.disableClick(); + break; + default: + this.disableTextSelection(); + this.togglePointerEvents(true); + this.enableClick(); + } + this.toggleAnnotationLayerPointerEvents(false); + const { + classList + } = this.div; + classList.toggle("nonEditing", false); + if (mode === AnnotationEditorType.POPUP) { + classList.toggle("commentEditing", true); + } else { + classList.toggle("commentEditing", false); + for (const editorType of AnnotationEditorLayer.#editorTypes.values()) { + classList.toggle(`${editorType._type}Editing`, mode === editorType._editorType); + } + } + this.div.hidden = false; + } + hasTextLayer(textLayer) { + return textLayer === this.#textLayer?.div; + } + setEditingState(isEditing) { + this.#uiManager.setEditingState(isEditing); + } + addCommands(params) { + this.#uiManager.addCommands(params); + } + cleanUndoStack(type) { + this.#uiManager.cleanUndoStack(type); + } + toggleDrawing(enabled = false) { + this.div.classList.toggle("drawing", !enabled); + } + togglePointerEvents(enabled = false) { + this.div.classList.toggle("disabled", !enabled); + } + toggleAnnotationLayerPointerEvents(enabled = false) { + this.#annotationLayer?.div.classList.toggle("disabled", !enabled); + } + get #allEditorsIterator() { + return this.#editors.size !== 0 ? this.#editors.values() : this.#uiManager.getEditors(this.pageIndex); + } + async enable() { + this.#isEnabling = true; + this.div.tabIndex = 0; + this.togglePointerEvents(true); + this.div.classList.toggle("nonEditing", false); + this.#textLayerDblClickAC?.abort(); + this.#textLayerDblClickAC = null; + const annotationElementIds = /* @__PURE__ */ new Set(); + for (const editor of this.#allEditorsIterator) { + editor.enableEditing(); + editor.show(true); + if (editor.annotationElementId) { + this.#uiManager.removeChangedExistingAnnotation(editor); + annotationElementIds.add(editor.annotationElementId); + } + } + const annotationLayer = this.#annotationLayer; + if (annotationLayer) { + for (const editable of annotationLayer.getEditableAnnotations()) { + editable.hide(); + if (this.#uiManager.isDeletedAnnotationElement(editable.data.id)) { + continue; + } + if (annotationElementIds.has(editable.data.id)) { + continue; + } + const editor = await this.deserialize(editable); + if (!editor) { + continue; + } + this.addOrRebuild(editor); + editor.enableEditing(); + } + } + this.#isEnabling = false; + this.#uiManager._eventBus.dispatch("editorsrendered", { + source: this, + pageNumber: this.pageIndex + 1 + }); + } + disable() { + this.#isDisabling = true; + this.div.tabIndex = -1; + this.togglePointerEvents(false); + this.div.classList.toggle("nonEditing", true); + if (this.#textLayer && !this.#textLayerDblClickAC) { + this.#textLayerDblClickAC = new AbortController(); + const signal = this.#uiManager.combinedSignal(this.#textLayerDblClickAC); + this.#textLayer.div.addEventListener("pointerdown", (e) => { + const DBL_CLICK_THRESHOLD = 500; + const { + clientX, + clientY, + timeStamp + } = e; + const lastPointerDownTimestamp = this.#lastPointerDownTimestamp; + if (timeStamp - lastPointerDownTimestamp > DBL_CLICK_THRESHOLD) { + this.#lastPointerDownTimestamp = timeStamp; + return; + } + this.#lastPointerDownTimestamp = -1; + const { + classList: classList2 + } = this.div; + classList2.toggle("getElements", true); + const elements = document.elementsFromPoint(clientX, clientY); + classList2.toggle("getElements", false); + if (!this.div.contains(elements[0])) { + return; + } + let id; + const regex = new RegExp(`^${AnnotationEditorPrefix}[0-9]+$`); + for (const element of elements) { + if (regex.test(element.id)) { + id = element.id; + break; + } + } + if (!id) { + return; + } + const editor = this.#editors.get(id); + if (editor?.annotationElementId === null) { + e.stopPropagation(); + e.preventDefault(); + editor.dblclick(e); + } + }, { + signal, + capture: true + }); + } + const annotationLayer = this.#annotationLayer; + if (annotationLayer) { + const changedAnnotations = /* @__PURE__ */ new Map(); + const resetAnnotations = /* @__PURE__ */ new Map(); + for (const editor of this.#allEditorsIterator) { + editor.disableEditing(); + if (!editor.annotationElementId) { + editor.updateFakeAnnotationElement(annotationLayer); + continue; + } + if (editor.serialize() !== null) { + changedAnnotations.set(editor.annotationElementId, editor); + continue; + } else { + resetAnnotations.set(editor.annotationElementId, editor); + } + this.getEditableAnnotation(editor.annotationElementId)?.show(); + editor.remove(); + } + const editables = annotationLayer.getEditableAnnotations(); + for (const editable of editables) { + const { + id + } = editable.data; + if (this.#uiManager.isDeletedAnnotationElement(id)) { + editable.updateEdited({ + deleted: true + }); + continue; + } + let editor = resetAnnotations.get(id); + if (editor) { + editor.resetAnnotationElement(editable); + editor.show(false); + editable.show(); + continue; + } + editor = changedAnnotations.get(id); + if (editor) { + this.#uiManager.addChangedExistingAnnotation(editor); + if (editor.renderAnnotationElement(editable)) { + editor.show(false); + } + } + editable.show(); + } + } + this.#cleanup(); + if (this.isEmpty) { + this.div.hidden = true; + } + const { + classList + } = this.div; + for (const editorType of AnnotationEditorLayer.#editorTypes.values()) { + classList.remove(`${editorType._type}Editing`); + } + this.disableTextSelection(); + this.toggleAnnotationLayerPointerEvents(true); + this.#isDisabling = false; + } + getEditableAnnotation(id) { + return this.#annotationLayer?.getEditableAnnotation(id) || null; + } + setActiveEditor(editor) { + const currentActive = this.#uiManager.getActive(); + if (currentActive === editor) { + return; + } + this.#uiManager.setActiveEditor(editor); + } + enableTextSelection() { + this.div.tabIndex = -1; + if (this.#textLayer?.div && !this.#textSelectionAC) { + this.#textSelectionAC = new AbortController(); + const signal = this.#uiManager.combinedSignal(this.#textSelectionAC); + this.#textLayer.div.addEventListener("pointerdown", this.#textLayerPointerDown.bind(this), { + signal + }); + this.#textLayer.div.classList.add("highlighting"); + } + } + disableTextSelection() { + this.div.tabIndex = 0; + if (this.#textLayer?.div && this.#textSelectionAC) { + this.#textSelectionAC.abort(); + this.#textSelectionAC = null; + this.#textLayer.div.classList.remove("highlighting"); + } + } + #textLayerPointerDown(event) { + this.#uiManager.unselectAll(); + const { + target + } = event; + if (target === this.#textLayer.div || (target.getAttribute("role") === "img" || target.classList.contains("endOfContent")) && this.#textLayer.div.contains(target)) { + const { + isMac + } = util_FeatureTest.platform; + if (event.button !== 0 || event.ctrlKey && isMac) { + return; + } + this.#uiManager.showAllEditors("highlight", true, true); + this.#textLayer.div.classList.add("free"); + this.toggleDrawing(); + HighlightEditor.startHighlighting(this, this.#uiManager.direction === "ltr", { + target: this.#textLayer.div, + x: event.x, + y: event.y + }); + this.#textLayer.div.addEventListener("pointerup", () => { + this.#textLayer.div.classList.remove("free"); + this.toggleDrawing(true); + }, { + once: true, + signal: this.#uiManager._signal + }); + event.preventDefault(); + } + } + enableClick() { + if (this.#clickAC) { + return; + } + this.#clickAC = new AbortController(); + const signal = this.#uiManager.combinedSignal(this.#clickAC); + this.div.addEventListener("pointerdown", this.pointerdown.bind(this), { + signal + }); + const pointerup = this.pointerup.bind(this); + this.div.addEventListener("pointerup", pointerup, { + signal + }); + this.div.addEventListener("pointercancel", pointerup, { + signal + }); + } + disableClick() { + this.#clickAC?.abort(); + this.#clickAC = null; + } + attach(editor) { + this.#editors.set(editor.id, editor); + const { + annotationElementId + } = editor; + if (annotationElementId && this.#uiManager.isDeletedAnnotationElement(annotationElementId)) { + this.#uiManager.removeDeletedAnnotationElement(editor); + } + } + detach(editor) { + this.#editors.delete(editor.id); + this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv); + if (!this.#isDisabling && editor.annotationElementId) { + this.#uiManager.addDeletedAnnotationElement(editor); + } + } + remove(editor) { + this.detach(editor); + this.#uiManager.removeEditor(editor); + editor.div.remove(); + editor.isAttachedToDOM = false; + } + changeParent(editor) { + if (editor.parent === this) { + return; + } + if (editor.parent && editor.annotationElementId) { + this.#uiManager.addDeletedAnnotationElement(editor.annotationElementId); + AnnotationEditor.deleteAnnotationElement(editor); + editor.annotationElementId = null; + } + this.attach(editor); + editor.parent?.detach(editor); + editor.setParent(this); + if (editor.div && editor.isAttachedToDOM) { + editor.div.remove(); + this.div.append(editor.div); + } + } + add(editor) { + if (editor.parent === this && editor.isAttachedToDOM) { + return; + } + this.changeParent(editor); + this.#uiManager.addEditor(editor); + this.attach(editor); + if (!editor.isAttachedToDOM) { + const div = editor.render(); + this.div.append(div); + editor.isAttachedToDOM = true; + } + editor.fixAndSetPosition(); + editor.onceAdded(!this.#isEnabling); + this.#uiManager.addToAnnotationStorage(editor); + editor._reportTelemetry(editor.telemetryInitialData); + } + moveEditorInDOM(editor) { + if (!editor.isAttachedToDOM) { + return; + } + const { + activeElement + } = document; + if (editor.div.contains(activeElement) && !this.#editorFocusTimeoutId) { + editor._focusEventsAllowed = false; + this.#editorFocusTimeoutId = setTimeout(() => { + this.#editorFocusTimeoutId = null; + if (!editor.div.contains(document.activeElement)) { + editor.div.addEventListener("focusin", () => { + editor._focusEventsAllowed = true; + }, { + once: true, + signal: this.#uiManager._signal + }); + activeElement.focus(); + } else { + editor._focusEventsAllowed = true; + } + }, 0); + } + editor._structTreeParentId = this.#accessibilityManager?.moveElementInDOM(this.div, editor.div, editor.contentDiv, true); + } + addOrRebuild(editor) { + if (editor.needsToBeRebuilt()) { + editor.parent ||= this; + editor.rebuild(); + editor.show(); + } else { + this.add(editor); + } + } + addUndoableEditor(editor) { + const cmd = () => editor._uiManager.rebuild(editor); + const undo = () => { + editor.remove(); + }; + this.addCommands({ + cmd, + undo, + mustExec: false + }); + } + getEditorByUID(uid) { + for (const editor of this.#editors.values()) { + if (editor.uid === uid) { + return editor; + } + } + return null; + } + getNextId() { + return this.#uiManager.getId(); + } + get #currentEditorType() { + return AnnotationEditorLayer.#editorTypes.get(this.#uiManager.getMode()); + } + combinedSignal(ac) { + return this.#uiManager.combinedSignal(ac); + } + #createNewEditor(params) { + const editorType = this.#currentEditorType; + return editorType ? new editorType.prototype.constructor(params) : null; + } + canCreateNewEmptyEditor() { + return this.#currentEditorType?.canCreateNewEmptyEditor(); + } + async pasteEditor(options, params) { + this.updateToolbar(options); + await this.#uiManager.updateMode(options.mode); + const { + offsetX, + offsetY + } = this.#getCenterPoint(); + const id = this.getNextId(); + const editor = this.#createNewEditor({ + parent: this, + id, + x: offsetX, + y: offsetY, + uiManager: this.#uiManager, + isCentered: true, + ...params + }); + if (editor) { + this.add(editor); + } + } + async deserialize(data) { + return await AnnotationEditorLayer.#editorTypes.get(data.annotationType ?? data.annotationEditorType)?.deserialize(data, this, this.#uiManager) || null; + } + createAndAddNewEditor(event, isCentered, data = {}) { + const id = this.getNextId(); + const editor = this.#createNewEditor({ + parent: this, + id, + x: event.offsetX, + y: event.offsetY, + uiManager: this.#uiManager, + isCentered, + ...data + }); + if (editor) { + this.add(editor); + } + return editor; + } + get boundingClientRect() { + return this.div.getBoundingClientRect(); + } + #getCenterPoint() { + const { + x, + y, + width, + height + } = this.boundingClientRect; + const tlX = Math.max(0, x); + const tlY = Math.max(0, y); + const brX = Math.min(window.innerWidth, x + width); + const brY = Math.min(window.innerHeight, y + height); + const centerX = (tlX + brX) / 2 - x; + const centerY = (tlY + brY) / 2 - y; + const [offsetX, offsetY] = this.viewport.rotation % 180 === 0 ? [centerX, centerY] : [centerY, centerX]; + return { + offsetX, + offsetY + }; + } + addNewEditor(data = {}) { + this.createAndAddNewEditor(this.#getCenterPoint(), true, data); + } + setSelected(editor) { + this.#uiManager.setSelected(editor); + } + toggleSelected(editor) { + this.#uiManager.toggleSelected(editor); + } + unselect(editor) { + this.#uiManager.unselect(editor); + } + pointerup(event) { + const { + isMac + } = util_FeatureTest.platform; + if (event.button !== 0 || event.ctrlKey && isMac) { + return; + } + if (event.target !== this.div) { + return; + } + if (!this.#hadPointerDown) { + return; + } + this.#hadPointerDown = false; + if (this.#currentEditorType?.isDrawer && this.#currentEditorType.supportMultipleDrawings) { + return; + } + if (!this.#allowClick) { + this.#allowClick = true; + return; + } + const currentMode = this.#uiManager.getMode(); + if (currentMode === AnnotationEditorType.STAMP || currentMode === AnnotationEditorType.SIGNATURE) { + this.#uiManager.unselectAll(); + return; + } + this.createAndAddNewEditor(event, false); + } + pointerdown(event) { + if (this.#uiManager.getMode() === AnnotationEditorType.HIGHLIGHT) { + this.enableTextSelection(); + } + if (this.#hadPointerDown) { + this.#hadPointerDown = false; + return; + } + const { + isMac + } = util_FeatureTest.platform; + if (event.button !== 0 || event.ctrlKey && isMac) { + return; + } + if (event.target !== this.div) { + return; + } + this.#hadPointerDown = true; + if (this.#currentEditorType?.isDrawer) { + this.startDrawingSession(event); + return; + } + const editor = this.#uiManager.getActive(); + this.#allowClick = !editor || editor.isEmpty(); + } + startDrawingSession(event) { + this.div.focus({ + preventScroll: true + }); + if (this.#drawingAC) { + this.#currentEditorType.startDrawing(this, this.#uiManager, false, event); + return; + } + this.#uiManager.setCurrentDrawingSession(this); + this.#drawingAC = new AbortController(); + const signal = this.#uiManager.combinedSignal(this.#drawingAC); + this.div.addEventListener("blur", ({ + relatedTarget + }) => { + if (relatedTarget && !this.div.contains(relatedTarget)) { + this.#focusedElement = null; + this.commitOrRemove(); + } + }, { + signal + }); + this.#currentEditorType.startDrawing(this, this.#uiManager, false, event); + } + pause(on) { + if (on) { + const { + activeElement + } = document; + if (this.div.contains(activeElement)) { + this.#focusedElement = activeElement; + } + return; + } + if (this.#focusedElement) { + setTimeout(() => { + this.#focusedElement?.focus(); + this.#focusedElement = null; + }, 0); + } + } + endDrawingSession(isAborted = false) { + if (!this.#drawingAC) { + return null; + } + this.#uiManager.setCurrentDrawingSession(null); + this.#drawingAC.abort(); + this.#drawingAC = null; + this.#focusedElement = null; + return this.#currentEditorType.endDrawing(isAborted); + } + findNewParent(editor, x, y) { + const layer = this.#uiManager.findParent(x, y); + if (layer === null || layer === this) { + return false; + } + layer.changeParent(editor); + return true; + } + commitOrRemove() { + if (this.#drawingAC) { + this.endDrawingSession(); + return true; + } + return false; + } + onScaleChanging() { + if (!this.#drawingAC) { + return; + } + this.#currentEditorType.onScaleChangingWhenDrawing(this); + } + destroy() { + this.commitOrRemove(); + if (this.#uiManager.getActive()?.parent === this) { + this.#uiManager.commitOrRemove(); + this.#uiManager.setActiveEditor(null); + } + if (this.#editorFocusTimeoutId) { + clearTimeout(this.#editorFocusTimeoutId); + this.#editorFocusTimeoutId = null; + } + for (const editor of this.#editors.values()) { + this.#accessibilityManager?.removePointerInTextLayer(editor.contentDiv); + editor.setParent(null); + editor.isAttachedToDOM = false; + editor.div.remove(); + } + this.div = null; + this.#editors.clear(); + this.#uiManager.removeLayer(this); + } + #cleanup() { + for (const editor of this.#editors.values()) { + if (editor.isEmpty()) { + editor.remove(); + } + } + } + render({ + viewport + }) { + this.viewport = viewport; + setLayerDimensions(this.div, viewport); + for (const editor of this.#uiManager.getEditors(this.pageIndex)) { + this.add(editor); + editor.rebuild(); + } + this.updateMode(); + } + update({ + viewport + }) { + this.#uiManager.commitOrRemove(); + this.#cleanup(); + const oldRotation = this.viewport.rotation; + const rotation = viewport.rotation; + this.viewport = viewport; + setLayerDimensions(this.div, { + rotation + }); + if (oldRotation !== rotation) { + for (const editor of this.#editors.values()) { + editor.rotate(rotation); + } + } + } + get pageDimensions() { + const { + pageWidth, + pageHeight + } = this.viewport.rawDims; + return [pageWidth, pageHeight]; + } + get scale() { + return this.#uiManager.viewParameters.realScale; + } +} +class DrawLayer { + #parent = null; + #mapping = /* @__PURE__ */ new Map(); + #toUpdate = /* @__PURE__ */ new Map(); + static #id = 0; + constructor({ + pageIndex + }) { + this.pageIndex = pageIndex; + } + setParent(parent) { + if (!this.#parent) { + this.#parent = parent; + return; + } + if (this.#parent !== parent) { + if (this.#mapping.size > 0) { + for (const root of this.#mapping.values()) { + root.remove(); + parent.append(root); + } + } + this.#parent = parent; + } + } + static get _svgFactory() { + return shadow(this, "_svgFactory", new DOMSVGFactory()); + } + static #setBox(element, [x, y, width, height]) { + const { + style + } = element; + style.top = `${100 * y}%`; + style.left = `${100 * x}%`; + style.width = `${100 * width}%`; + style.height = `${100 * height}%`; + } + #createSVG() { + const svg = DrawLayer._svgFactory.create(1, 1, true); + this.#parent.append(svg); + svg.setAttribute("aria-hidden", true); + return svg; + } + #createClipPath(defs, pathId) { + const clipPath = DrawLayer._svgFactory.createElement("clipPath"); + defs.append(clipPath); + const clipPathId = `clip_${pathId}`; + clipPath.setAttribute("id", clipPathId); + clipPath.setAttribute("clipPathUnits", "objectBoundingBox"); + const clipPathUse = DrawLayer._svgFactory.createElement("use"); + clipPath.append(clipPathUse); + clipPathUse.setAttribute("href", `#${pathId}`); + clipPathUse.classList.add("clip"); + return clipPathId; + } + #updateProperties(element, properties) { + for (const [key, value] of Object.entries(properties)) { + if (value === null) { + element.removeAttribute(key); + } else { + element.setAttribute(key, value); + } + } + } + draw(properties, isPathUpdatable = false, hasClip = false) { + const id = DrawLayer.#id++; + const root = this.#createSVG(); + const defs = DrawLayer._svgFactory.createElement("defs"); + root.append(defs); + const path = DrawLayer._svgFactory.createElement("path"); + defs.append(path); + const pathId = `path_p${this.pageIndex}_${id}`; + path.setAttribute("id", pathId); + path.setAttribute("vector-effect", "non-scaling-stroke"); + if (isPathUpdatable) { + this.#toUpdate.set(id, path); + } + const clipPathId = hasClip ? this.#createClipPath(defs, pathId) : null; + const use = DrawLayer._svgFactory.createElement("use"); + root.append(use); + use.setAttribute("href", `#${pathId}`); + this.updateProperties(root, properties); + this.#mapping.set(id, root); + return { + id, + clipPathId: `url(#${clipPathId})` + }; + } + drawOutline(properties, mustRemoveSelfIntersections) { + const id = DrawLayer.#id++; + const root = this.#createSVG(); + const defs = DrawLayer._svgFactory.createElement("defs"); + root.append(defs); + const path = DrawLayer._svgFactory.createElement("path"); + defs.append(path); + const pathId = `path_p${this.pageIndex}_${id}`; + path.setAttribute("id", pathId); + path.setAttribute("vector-effect", "non-scaling-stroke"); + let maskId; + if (mustRemoveSelfIntersections) { + const mask = DrawLayer._svgFactory.createElement("mask"); + defs.append(mask); + maskId = `mask_p${this.pageIndex}_${id}`; + mask.setAttribute("id", maskId); + mask.setAttribute("maskUnits", "objectBoundingBox"); + const rect = DrawLayer._svgFactory.createElement("rect"); + mask.append(rect); + rect.setAttribute("width", "1"); + rect.setAttribute("height", "1"); + rect.setAttribute("fill", "white"); + const use = DrawLayer._svgFactory.createElement("use"); + mask.append(use); + use.setAttribute("href", `#${pathId}`); + use.setAttribute("stroke", "none"); + use.setAttribute("fill", "black"); + use.setAttribute("fill-rule", "nonzero"); + use.classList.add("mask"); + } + const use1 = DrawLayer._svgFactory.createElement("use"); + root.append(use1); + use1.setAttribute("href", `#${pathId}`); + if (maskId) { + use1.setAttribute("mask", `url(#${maskId})`); + } + const use2 = use1.cloneNode(); + root.append(use2); + use1.classList.add("mainOutline"); + use2.classList.add("secondaryOutline"); + this.updateProperties(root, properties); + this.#mapping.set(id, root); + return id; + } + finalizeDraw(id, properties) { + this.#toUpdate.delete(id); + this.updateProperties(id, properties); + } + updateProperties(elementOrId, properties) { + if (!properties) { + return; + } + const { + root, + bbox, + rootClass, + path + } = properties; + const element = typeof elementOrId === "number" ? this.#mapping.get(elementOrId) : elementOrId; + if (!element) { + return; + } + if (root) { + this.#updateProperties(element, root); + } + if (bbox) { + DrawLayer.#setBox(element, bbox); + } + if (rootClass) { + const { + classList + } = element; + for (const [className, value] of Object.entries(rootClass)) { + classList.toggle(className, value); + } + } + if (path) { + const defs = element.firstChild; + const pathElement = defs.firstChild; + this.#updateProperties(pathElement, path); + } + } + updateParent(id, layer) { + if (layer === this) { + return; + } + const root = this.#mapping.get(id); + if (!root) { + return; + } + layer.#parent.append(root); + this.#mapping.delete(id); + layer.#mapping.set(id, root); + } + remove(id) { + this.#toUpdate.delete(id); + if (this.#parent === null) { + return; + } + this.#mapping.get(id).remove(); + this.#mapping.delete(id); + } + destroy() { + this.#parent = null; + for (const root of this.#mapping.values()) { + root.remove(); + } + this.#mapping.clear(); + this.#toUpdate.clear(); + } +} +{ + globalThis._pdfjsTestingUtils = { + HighlightOutliner + }; +} +globalThis.pdfjsLib = { + AbortException, + AnnotationEditorLayer, + AnnotationEditorParamsType, + AnnotationEditorType, + AnnotationEditorUIManager, + AnnotationLayer, + AnnotationMode, + AnnotationType, + applyOpacity, + build, + ColorPicker, + createValidAbsoluteUrl, + CSSConstants, + DOMSVGFactory, + DrawLayer, + FeatureTest: util_FeatureTest, + fetchData, + findContrastColor, + getDocument, + getFilenameFromUrl, + getPdfFilenameFromUrl, + getRGB, + getUuid, + getXfaPageViewport, + GlobalWorkerOptions, + ImageKind: util_ImageKind, + InvalidPDFException, + isDataScheme, + isPdfFile, + isValidExplicitDest, + MathClamp, + noContextMenu, + normalizeUnicode, + OPS, + OutputScale, + PasswordResponses, + PDFDataRangeTransport, + PDFDateString, + PDFWorker, + PermissionFlag, + PixelsPerInch, + RenderingCancelledException, + renderRichText, + ResponseException, + setLayerDimensions, + shadow, + SignatureExtractor, + stopEvent, + SupportedImageMimeTypes, + TextLayer, + TouchManager, + updateUrlHash, + Util, + VerbosityLevel, + version, + XfaLayer +}; +const pdfjs = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ + __proto__: null, + AbortException, + AnnotationEditorLayer, + AnnotationEditorParamsType, + AnnotationEditorType, + AnnotationEditorUIManager, + AnnotationLayer, + AnnotationMode, + AnnotationType, + CSSConstants, + ColorPicker, + DOMSVGFactory, + DrawLayer, + FeatureTest: util_FeatureTest, + GlobalWorkerOptions, + ImageKind: util_ImageKind, + InvalidPDFException, + MathClamp, + OPS, + OutputScale, + PDFDataRangeTransport, + PDFDateString, + PDFWorker, + PasswordResponses, + PermissionFlag, + PixelsPerInch, + RenderingCancelledException, + ResponseException, + SignatureExtractor, + SupportedImageMimeTypes, + TextLayer, + TouchManager, + Util, + VerbosityLevel, + XfaLayer, + applyOpacity, + build, + createValidAbsoluteUrl, + fetchData, + findContrastColor, + getDocument, + getFilenameFromUrl, + getPdfFilenameFromUrl, + getRGB, + getUuid, + getXfaPageViewport, + isDataScheme, + isPdfFile, + isValidExplicitDest, + noContextMenu, + normalizeUnicode, + renderRichText, + setLayerDimensions, + shadow, + stopEvent, + updateUrlHash, + version +}, Symbol.toStringTag, { value: "Module" })); +const pdf_worker = "data:text/javascript;base64,LyoqCiAqIEBsaWNzdGFydCBUaGUgZm9sbG93aW5nIGlzIHRoZSBlbnRpcmUgbGljZW5zZSBub3RpY2UgZm9yIHRoZQogKiBKYXZhU2NyaXB0IGNvZGUgaW4gdGhpcyBwYWdlCiAqCiAqIENvcHlyaWdodCAyMDI0IE1vemlsbGEgRm91bmRhdGlvbgogKgogKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLgogKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKICoKICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAogKgogKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICJBUyBJUyIgQkFTSVMsCiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLgogKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLgogKgogKiBAbGljZW5kIFRoZSBhYm92ZSBpcyB0aGUgZW50aXJlIGxpY2Vuc2Ugbm90aWNlIGZvciB0aGUKICogSmF2YVNjcmlwdCBjb2RlIGluIHRoaXMgcGFnZQogKi8KCi8qKgogKiBwZGZqc1ZlcnNpb24gPSA1LjQuMjk2CiAqIHBkZmpzQnVpbGQgPSBmNTZkYzg2MDEKICovCi8qKioqKiovIHZhciBfX3dlYnBhY2tfbW9kdWxlc19fID0gKHsKCi8qKiovIDM0OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGlzQ2FsbGFibGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MDEpOwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHsKICByZXR1cm4gdHlwZW9mIGl0ID09ICdvYmplY3QnID8gaXQgIT09IG51bGwgOiBpc0NhbGxhYmxlKGl0KTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDgxOgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGNhbGwgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1NjUpOwp2YXIgYUNhbGxhYmxlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5MzA2KTsKdmFyIGFuT2JqZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4NTUxKTsKdmFyIHRyeVRvU3RyaW5nID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2ODIzKTsKdmFyIGdldEl0ZXJhdG9yTWV0aG9kID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4NTEpOwoKdmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7Cgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcmd1bWVudCwgdXNpbmdJdGVyYXRvcikgewogIHZhciBpdGVyYXRvck1ldGhvZCA9IGFyZ3VtZW50cy5sZW5ndGggPCAyID8gZ2V0SXRlcmF0b3JNZXRob2QoYXJndW1lbnQpIDogdXNpbmdJdGVyYXRvcjsKICBpZiAoYUNhbGxhYmxlKGl0ZXJhdG9yTWV0aG9kKSkgcmV0dXJuIGFuT2JqZWN0KGNhbGwoaXRlcmF0b3JNZXRob2QsIGFyZ3VtZW50KSk7CiAgdGhyb3cgbmV3ICRUeXBlRXJyb3IodHJ5VG9TdHJpbmcoYXJndW1lbnQpICsgJyBpcyBub3QgaXRlcmFibGUnKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDExNjoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgY2FsbCA9IF9fd2VicGFja19yZXF1aXJlX18oOTU2NSk7CnZhciBpdGVyYXRlID0gX193ZWJwYWNrX3JlcXVpcmVfXygyNjUyKTsKdmFyIGFDYWxsYWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oOTMwNik7CnZhciBhbk9iamVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oODU1MSk7CnZhciBnZXRJdGVyYXRvckRpcmVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oMTc2Nyk7CnZhciBpdGVyYXRvckNsb3NlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTM5KTsKdmFyIGl0ZXJhdG9ySGVscGVyV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ1NDkpOwoKdmFyIGZpbmRXaXRob3V0Q2xvc2luZ09uRWFybHlFcnJvciA9IGl0ZXJhdG9ySGVscGVyV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IoJ2ZpbmQnLCBUeXBlRXJyb3IpOwoKLy8gYEl0ZXJhdG9yLnByb3RvdHlwZS5maW5kYCBtZXRob2QKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1pdGVyYXRvci5wcm90b3R5cGUuZmluZAokKHsgdGFyZ2V0OiAnSXRlcmF0b3InLCBwcm90bzogdHJ1ZSwgcmVhbDogdHJ1ZSwgZm9yY2VkOiBmaW5kV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IgfSwgewogIGZpbmQ6IGZ1bmN0aW9uIGZpbmQocHJlZGljYXRlKSB7CiAgICBhbk9iamVjdCh0aGlzKTsKICAgIHRyeSB7CiAgICAgIGFDYWxsYWJsZShwcmVkaWNhdGUpOwogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgaXRlcmF0b3JDbG9zZSh0aGlzLCAndGhyb3cnLCBlcnJvcik7CiAgICB9CgogICAgaWYgKGZpbmRXaXRob3V0Q2xvc2luZ09uRWFybHlFcnJvcikgcmV0dXJuIGNhbGwoZmluZFdpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yLCB0aGlzLCBwcmVkaWNhdGUpOwoKICAgIHZhciByZWNvcmQgPSBnZXRJdGVyYXRvckRpcmVjdCh0aGlzKTsKICAgIHZhciBjb3VudGVyID0gMDsKICAgIHJldHVybiBpdGVyYXRlKHJlY29yZCwgZnVuY3Rpb24gKHZhbHVlLCBzdG9wKSB7CiAgICAgIGlmIChwcmVkaWNhdGUodmFsdWUsIGNvdW50ZXIrKykpIHJldHVybiBzdG9wKHZhbHVlKTsKICAgIH0sIHsgSVNfUkVDT1JEOiB0cnVlLCBJTlRFUlJVUFRFRDogdHJ1ZSB9KS5yZXN1bHQ7CiAgfQp9KTsKCgovKioqLyB9KSwKCi8qKiovIDI4MzoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciB1bmN1cnJ5VGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oOTUwNCk7CnZhciBmYWlscyA9IF9fd2VicGFja19yZXF1aXJlX18oOTAzOSk7CnZhciBpc0NhbGxhYmxlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0OTAxKTsKdmFyIGhhc093biA9IF9fd2VicGFja19yZXF1aXJlX18oOTI5Nyk7CnZhciBERVNDUklQVE9SUyA9IF9fd2VicGFja19yZXF1aXJlX18oMzcyNCk7CnZhciBDT05GSUdVUkFCTEVfRlVOQ1RJT05fTkFNRSA9IChfX3dlYnBhY2tfcmVxdWlyZV9fKDM1MCkuQ09ORklHVVJBQkxFKTsKdmFyIGluc3BlY3RTb3VyY2UgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM3MDYpOwp2YXIgSW50ZXJuYWxTdGF0ZU1vZHVsZSA9IF9fd2VicGFja19yZXF1aXJlX18oMTE4MSk7Cgp2YXIgZW5mb3JjZUludGVybmFsU3RhdGUgPSBJbnRlcm5hbFN0YXRlTW9kdWxlLmVuZm9yY2U7CnZhciBnZXRJbnRlcm5hbFN0YXRlID0gSW50ZXJuYWxTdGF0ZU1vZHVsZS5nZXQ7CnZhciAkU3RyaW5nID0gU3RyaW5nOwovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tb2JqZWN0LWRlZmluZXByb3BlcnR5IC0tIHNhZmUKdmFyIGRlZmluZVByb3BlcnR5ID0gT2JqZWN0LmRlZmluZVByb3BlcnR5Owp2YXIgc3RyaW5nU2xpY2UgPSB1bmN1cnJ5VGhpcygnJy5zbGljZSk7CnZhciByZXBsYWNlID0gdW5jdXJyeVRoaXMoJycucmVwbGFjZSk7CnZhciBqb2luID0gdW5jdXJyeVRoaXMoW10uam9pbik7Cgp2YXIgQ09ORklHVVJBQkxFX0xFTkdUSCA9IERFU0NSSVBUT1JTICYmICFmYWlscyhmdW5jdGlvbiAoKSB7CiAgcmV0dXJuIGRlZmluZVByb3BlcnR5KGZ1bmN0aW9uICgpIHsgLyogZW1wdHkgKi8gfSwgJ2xlbmd0aCcsIHsgdmFsdWU6IDggfSkubGVuZ3RoICE9PSA4Owp9KTsKCnZhciBURU1QTEFURSA9IFN0cmluZyhTdHJpbmcpLnNwbGl0KCdTdHJpbmcnKTsKCnZhciBtYWtlQnVpbHRJbiA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHZhbHVlLCBuYW1lLCBvcHRpb25zKSB7CiAgaWYgKHN0cmluZ1NsaWNlKCRTdHJpbmcobmFtZSksIDAsIDcpID09PSAnU3ltYm9sKCcpIHsKICAgIG5hbWUgPSAnWycgKyByZXBsYWNlKCRTdHJpbmcobmFtZSksIC9eU3ltYm9sXCgoW14pXSopXCkuKiQvLCAnJDEnKSArICddJzsKICB9CiAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy5nZXR0ZXIpIG5hbWUgPSAnZ2V0ICcgKyBuYW1lOwogIGlmIChvcHRpb25zICYmIG9wdGlvbnMuc2V0dGVyKSBuYW1lID0gJ3NldCAnICsgbmFtZTsKICBpZiAoIWhhc093bih2YWx1ZSwgJ25hbWUnKSB8fCAoQ09ORklHVVJBQkxFX0ZVTkNUSU9OX05BTUUgJiYgdmFsdWUubmFtZSAhPT0gbmFtZSkpIHsKICAgIGlmIChERVNDUklQVE9SUykgZGVmaW5lUHJvcGVydHkodmFsdWUsICduYW1lJywgeyB2YWx1ZTogbmFtZSwgY29uZmlndXJhYmxlOiB0cnVlIH0pOwogICAgZWxzZSB2YWx1ZS5uYW1lID0gbmFtZTsKICB9CiAgaWYgKENPTkZJR1VSQUJMRV9MRU5HVEggJiYgb3B0aW9ucyAmJiBoYXNPd24ob3B0aW9ucywgJ2FyaXR5JykgJiYgdmFsdWUubGVuZ3RoICE9PSBvcHRpb25zLmFyaXR5KSB7CiAgICBkZWZpbmVQcm9wZXJ0eSh2YWx1ZSwgJ2xlbmd0aCcsIHsgdmFsdWU6IG9wdGlvbnMuYXJpdHkgfSk7CiAgfQogIHRyeSB7CiAgICBpZiAob3B0aW9ucyAmJiBoYXNPd24ob3B0aW9ucywgJ2NvbnN0cnVjdG9yJykgJiYgb3B0aW9ucy5jb25zdHJ1Y3RvcikgewogICAgICBpZiAoREVTQ1JJUFRPUlMpIGRlZmluZVByb3BlcnR5KHZhbHVlLCAncHJvdG90eXBlJywgeyB3cml0YWJsZTogZmFsc2UgfSk7CiAgICAvLyBpbiBWOCB+IENocm9tZSA1MywgcHJvdG90eXBlcyBvZiBzb21lIG1ldGhvZHMsIGxpa2UgYEFycmF5LnByb3RvdHlwZS52YWx1ZXNgLCBhcmUgbm9uLXdyaXRhYmxlCiAgICB9IGVsc2UgaWYgKHZhbHVlLnByb3RvdHlwZSkgdmFsdWUucHJvdG90eXBlID0gdW5kZWZpbmVkOwogIH0gY2F0Y2ggKGVycm9yKSB7IC8qIGVtcHR5ICovIH0KICB2YXIgc3RhdGUgPSBlbmZvcmNlSW50ZXJuYWxTdGF0ZSh2YWx1ZSk7CiAgaWYgKCFoYXNPd24oc3RhdGUsICdzb3VyY2UnKSkgewogICAgc3RhdGUuc291cmNlID0gam9pbihURU1QTEFURSwgdHlwZW9mIG5hbWUgPT0gJ3N0cmluZycgPyBuYW1lIDogJycpOwogIH0gcmV0dXJuIHZhbHVlOwp9OwoKLy8gYWRkIGZha2UgRnVuY3Rpb24jdG9TdHJpbmcgZm9yIGNvcnJlY3Qgd29yayB3cmFwcGVkIG1ldGhvZHMgLyBjb25zdHJ1Y3RvcnMgd2l0aCBtZXRob2RzIGxpa2UgTG9EYXNoIGlzTmF0aXZlCi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1leHRlbmQtbmF0aXZlIC0tIHJlcXVpcmVkCkZ1bmN0aW9uLnByb3RvdHlwZS50b1N0cmluZyA9IG1ha2VCdWlsdEluKGZ1bmN0aW9uIHRvU3RyaW5nKCkgewogIHJldHVybiBpc0NhbGxhYmxlKHRoaXMpICYmIGdldEludGVybmFsU3RhdGUodGhpcykuc291cmNlIHx8IGluc3BlY3RTb3VyY2UodGhpcyk7Cn0sICd0b1N0cmluZycpOwoKCi8qKiovIH0pLAoKLyoqKi8gMzUwOgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIERFU0NSSVBUT1JTID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNzI0KTsKdmFyIGhhc093biA9IF9fd2VicGFja19yZXF1aXJlX18oOTI5Nyk7Cgp2YXIgRnVuY3Rpb25Qcm90b3R5cGUgPSBGdW5jdGlvbi5wcm90b3R5cGU7Ci8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZ2V0b3ducHJvcGVydHlkZXNjcmlwdG9yIC0tIHNhZmUKdmFyIGdldERlc2NyaXB0b3IgPSBERVNDUklQVE9SUyAmJiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yOwoKdmFyIEVYSVNUUyA9IGhhc093bihGdW5jdGlvblByb3RvdHlwZSwgJ25hbWUnKTsKLy8gYWRkaXRpb25hbCBwcm90ZWN0aW9uIGZyb20gbWluaWZpZWQgLyBtYW5nbGVkIC8gZHJvcHBlZCBmdW5jdGlvbiBuYW1lcwp2YXIgUFJPUEVSID0gRVhJU1RTICYmIChmdW5jdGlvbiBzb21ldGhpbmcoKSB7IC8qIGVtcHR5ICovIH0pLm5hbWUgPT09ICdzb21ldGhpbmcnOwp2YXIgQ09ORklHVVJBQkxFID0gRVhJU1RTICYmICghREVTQ1JJUFRPUlMgfHwgKERFU0NSSVBUT1JTICYmIGdldERlc2NyaXB0b3IoRnVuY3Rpb25Qcm90b3R5cGUsICduYW1lJykuY29uZmlndXJhYmxlKSk7Cgptb2R1bGUuZXhwb3J0cyA9IHsKICBFWElTVFM6IEVYSVNUUywKICBQUk9QRVI6IFBST1BFUiwKICBDT05GSUdVUkFCTEU6IENPTkZJR1VSQUJMRQp9OwoKCi8qKiovIH0pLAoKLyoqKi8gMzk3OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGdldEJ1aWx0SW4gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDc3NTEpOwoKbW9kdWxlLmV4cG9ydHMgPSBnZXRCdWlsdEluKCdkb2N1bWVudCcsICdkb2N1bWVudEVsZW1lbnQnKTsKCgovKioqLyB9KSwKCi8qKiovIDQyMToKLyoqKi8gKChtb2R1bGUpID0+IHsKCgptb2R1bGUuZXhwb3J0cyA9IHt9OwoKCi8qKiovIH0pLAoKLyoqKi8gNDU2OgovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgJCA9IF9fd2VicGFja19yZXF1aXJlX18oNjUxOCk7CnZhciBnbG9iYWxUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0NTc2KTsKdmFyIHVuY3VycnlUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTA0KTsKdmFyIGFuVWludDhBcnJheSA9IF9fd2VicGFja19yZXF1aXJlX18oNDE1NCk7CnZhciBub3REZXRhY2hlZCA9IF9fd2VicGFja19yZXF1aXJlX18oNTE2OSk7Cgp2YXIgbnVtYmVyVG9TdHJpbmcgPSB1bmN1cnJ5VGhpcygxLjEudG9TdHJpbmcpOwoKdmFyIFVpbnQ4QXJyYXkgPSBnbG9iYWxUaGlzLlVpbnQ4QXJyYXk7Cgp2YXIgSU5DT1JSRUNUX0JFSEFWSU9SX09SX0RPRVNOVF9FWElTVFMgPSAhVWludDhBcnJheSB8fCAhVWludDhBcnJheS5wcm90b3R5cGUudG9IZXggfHwgIShmdW5jdGlvbiAoKSB7CiAgdHJ5IHsKICAgIHZhciB0YXJnZXQgPSBuZXcgVWludDhBcnJheShbMjU1LCAyNTUsIDI1NSwgMjU1LCAyNTUsIDI1NSwgMjU1LCAyNTVdKTsKICAgIHJldHVybiB0YXJnZXQudG9IZXgoKSA9PT0gJ2ZmZmZmZmZmZmZmZmZmZmYnOwogIH0gY2F0Y2ggKGVycm9yKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQp9KSgpOwoKLy8gYFVpbnQ4QXJyYXkucHJvdG90eXBlLnRvSGV4YCBtZXRob2QKLy8gaHR0cHM6Ly9naXRodWIuY29tL3RjMzkvcHJvcG9zYWwtYXJyYXlidWZmZXItYmFzZTY0CmlmIChVaW50OEFycmF5KSAkKHsgdGFyZ2V0OiAnVWludDhBcnJheScsIHByb3RvOiB0cnVlLCBmb3JjZWQ6IElOQ09SUkVDVF9CRUhBVklPUl9PUl9ET0VTTlRfRVhJU1RTIH0sIHsKICB0b0hleDogZnVuY3Rpb24gdG9IZXgoKSB7CiAgICBhblVpbnQ4QXJyYXkodGhpcyk7CiAgICBub3REZXRhY2hlZCh0aGlzLmJ1ZmZlcik7CiAgICB2YXIgcmVzdWx0ID0gJyc7CiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gdGhpcy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICB2YXIgaGV4ID0gbnVtYmVyVG9TdHJpbmcodGhpc1tpXSwgMTYpOwogICAgICByZXN1bHQgKz0gaGV4Lmxlbmd0aCA9PT0gMSA/ICcwJyArIGhleCA6IGhleDsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQp9KTsKCgovKioqLyB9KSwKCi8qKiovIDUwNzoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBjYWxsID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTY1KTsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHJlY29yZCwgZm4sIElURVJBVE9SX0lOU1RFQURfT0ZfUkVDT1JEKSB7CiAgdmFyIGl0ZXJhdG9yID0gSVRFUkFUT1JfSU5TVEVBRF9PRl9SRUNPUkQgPyByZWNvcmQgOiByZWNvcmQuaXRlcmF0b3I7CiAgdmFyIG5leHQgPSByZWNvcmQubmV4dDsKICB2YXIgc3RlcCwgcmVzdWx0OwogIHdoaWxlICghKHN0ZXAgPSBjYWxsKG5leHQsIGl0ZXJhdG9yKSkuZG9uZSkgewogICAgcmVzdWx0ID0gZm4oc3RlcC52YWx1ZSk7CiAgICBpZiAocmVzdWx0ICE9PSB1bmRlZmluZWQpIHJldHVybiByZXN1bHQ7CiAgfQp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNTMxOgovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgJCA9IF9fd2VicGFja19yZXF1aXJlX18oNjUxOCk7CnZhciBjYWxsID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTY1KTsKdmFyIGFDYWxsYWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oOTMwNik7CnZhciBhbk9iamVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oODU1MSk7CnZhciBnZXRJdGVyYXRvckRpcmVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oMTc2Nyk7CnZhciBnZXRJdGVyYXRvckZsYXR0ZW5hYmxlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4NjQ2KTsKdmFyIGNyZWF0ZUl0ZXJhdG9yUHJveHkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk0NjIpOwp2YXIgaXRlcmF0b3JDbG9zZSA9IF9fd2VicGFja19yZXF1aXJlX18oOTUzOSk7CnZhciBJU19QVVJFID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2Mzk1KTsKdmFyIGl0ZXJhdG9ySGVscGVyVGhyb3dzT25JbnZhbGlkSXRlcmF0b3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY4NCk7CnZhciBpdGVyYXRvckhlbHBlcldpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0NTQ5KTsKCnZhciBGTEFUX01BUF9XSVRIT1VUX1RIUk9XSU5HX09OX0lOVkFMSURfSVRFUkFUT1IgPSAhSVNfUFVSRQogICYmICFpdGVyYXRvckhlbHBlclRocm93c09uSW52YWxpZEl0ZXJhdG9yKCdmbGF0TWFwJywgZnVuY3Rpb24gKCkgeyAvKiBlbXB0eSAqLyB9KTsKdmFyIGZsYXRNYXBXaXRob3V0Q2xvc2luZ09uRWFybHlFcnJvciA9ICFJU19QVVJFICYmICFGTEFUX01BUF9XSVRIT1VUX1RIUk9XSU5HX09OX0lOVkFMSURfSVRFUkFUT1IKICAmJiBpdGVyYXRvckhlbHBlcldpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yKCdmbGF0TWFwJywgVHlwZUVycm9yKTsKCnZhciBGT1JDRUQgPSBJU19QVVJFIHx8IEZMQVRfTUFQX1dJVEhPVVRfVEhST1dJTkdfT05fSU5WQUxJRF9JVEVSQVRPUiB8fCBmbGF0TWFwV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3I7Cgp2YXIgSXRlcmF0b3JQcm94eSA9IGNyZWF0ZUl0ZXJhdG9yUHJveHkoZnVuY3Rpb24gKCkgewogIHZhciBpdGVyYXRvciA9IHRoaXMuaXRlcmF0b3I7CiAgdmFyIG1hcHBlciA9IHRoaXMubWFwcGVyOwogIHZhciByZXN1bHQsIGlubmVyOwoKICB3aGlsZSAodHJ1ZSkgewogICAgaWYgKGlubmVyID0gdGhpcy5pbm5lcikgdHJ5IHsKICAgICAgcmVzdWx0ID0gYW5PYmplY3QoY2FsbChpbm5lci5uZXh0LCBpbm5lci5pdGVyYXRvcikpOwogICAgICBpZiAoIXJlc3VsdC5kb25lKSByZXR1cm4gcmVzdWx0LnZhbHVlOwogICAgICB0aGlzLmlubmVyID0gbnVsbDsKICAgIH0gY2F0Y2ggKGVycm9yKSB7IGl0ZXJhdG9yQ2xvc2UoaXRlcmF0b3IsICd0aHJvdycsIGVycm9yKTsgfQoKICAgIHJlc3VsdCA9IGFuT2JqZWN0KGNhbGwodGhpcy5uZXh0LCBpdGVyYXRvcikpOwoKICAgIGlmICh0aGlzLmRvbmUgPSAhIXJlc3VsdC5kb25lKSByZXR1cm47CgogICAgdHJ5IHsKICAgICAgdGhpcy5pbm5lciA9IGdldEl0ZXJhdG9yRmxhdHRlbmFibGUobWFwcGVyKHJlc3VsdC52YWx1ZSwgdGhpcy5jb3VudGVyKyspLCBmYWxzZSk7CiAgICB9IGNhdGNoIChlcnJvcikgeyBpdGVyYXRvckNsb3NlKGl0ZXJhdG9yLCAndGhyb3cnLCBlcnJvcik7IH0KICB9Cn0pOwoKLy8gYEl0ZXJhdG9yLnByb3RvdHlwZS5mbGF0TWFwYCBtZXRob2QKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1pdGVyYXRvci5wcm90b3R5cGUuZmxhdG1hcAokKHsgdGFyZ2V0OiAnSXRlcmF0b3InLCBwcm90bzogdHJ1ZSwgcmVhbDogdHJ1ZSwgZm9yY2VkOiBGT1JDRUQgfSwgewogIGZsYXRNYXA6IGZ1bmN0aW9uIGZsYXRNYXAobWFwcGVyKSB7CiAgICBhbk9iamVjdCh0aGlzKTsKICAgIHRyeSB7CiAgICAgIGFDYWxsYWJsZShtYXBwZXIpOwogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgaXRlcmF0b3JDbG9zZSh0aGlzLCAndGhyb3cnLCBlcnJvcik7CiAgICB9CgogICAgaWYgKGZsYXRNYXBXaXRob3V0Q2xvc2luZ09uRWFybHlFcnJvcikgcmV0dXJuIGNhbGwoZmxhdE1hcFdpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yLCB0aGlzLCBtYXBwZXIpOwoKICAgIHJldHVybiBuZXcgSXRlcmF0b3JQcm94eShnZXRJdGVyYXRvckRpcmVjdCh0aGlzKSwgewogICAgICBtYXBwZXI6IG1hcHBlciwKICAgICAgaW5uZXI6IG51bGwKICAgIH0pOwogIH0KfSk7CgoKLyoqKi8gfSksCgovKioqLyA2MTY6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgZmFpbHMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDkwMzkpOwoKbW9kdWxlLmV4cG9ydHMgPSAhZmFpbHMoZnVuY3Rpb24gKCkgewogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1mdW5jdGlvbi1wcm90b3R5cGUtYmluZCAtLSBzYWZlCiAgdmFyIHRlc3QgPSAoZnVuY3Rpb24gKCkgeyAvKiBlbXB0eSAqLyB9KS5iaW5kKCk7CiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXByb3RvdHlwZS1idWlsdGlucyAtLSBzYWZlCiAgcmV0dXJuIHR5cGVvZiB0ZXN0ICE9ICdmdW5jdGlvbicgfHwgdGVzdC5oYXNPd25Qcm9wZXJ0eSgncHJvdG90eXBlJyk7Cn0pOwoKCi8qKiovIH0pLAoKLyoqKi8gNjU1OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGNsYXNzb2YgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY5NTUpOwoKdmFyICRTdHJpbmcgPSBTdHJpbmc7Cgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcmd1bWVudCkgewogIGlmIChjbGFzc29mKGFyZ3VtZW50KSA9PT0gJ1N5bWJvbCcpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0Nhbm5vdCBjb252ZXJ0IGEgU3ltYm9sIHZhbHVlIHRvIGEgc3RyaW5nJyk7CiAgcmV0dXJuICRTdHJpbmcoYXJndW1lbnQpOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNjc5OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGlzUHJvdG90eXBlT2YgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDE2MjUpOwoKdmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7Cgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCwgUHJvdG90eXBlKSB7CiAgaWYgKGlzUHJvdG90eXBlT2YoUHJvdG90eXBlLCBpdCkpIHJldHVybiBpdDsKICB0aHJvdyBuZXcgJFR5cGVFcnJvcignSW5jb3JyZWN0IGludm9jYXRpb24nKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDY4NDoKLyoqKi8gKChtb2R1bGUpID0+IHsKCgovLyBTaG91bGQgdGhyb3cgYW4gZXJyb3Igb24gaW52YWxpZCBpdGVyYXRvcgovLyBodHRwczovL2lzc3Vlcy5jaHJvbWl1bS5vcmcvaXNzdWVzLzMzNjgzOTExNQptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChtZXRob2ROYW1lLCBhcmd1bWVudCkgewogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1pdGVyYXRvciAtLSByZXF1aXJlZCBmb3IgdGVzdGluZwogIHZhciBtZXRob2QgPSB0eXBlb2YgSXRlcmF0b3IgPT0gJ2Z1bmN0aW9uJyAmJiBJdGVyYXRvci5wcm90b3R5cGVbbWV0aG9kTmFtZV07CiAgaWYgKG1ldGhvZCkgdHJ5IHsKICAgIG1ldGhvZC5jYWxsKHsgbmV4dDogbnVsbCB9LCBhcmd1bWVudCkubmV4dCgpOwogIH0gY2F0Y2ggKGVycm9yKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn07CgoKLyoqKi8gfSksCgovKioqLyA3NDE6Ci8qKiovICgobW9kdWxlKSA9PiB7CgoKdmFyIGNlaWwgPSBNYXRoLmNlaWw7CnZhciBmbG9vciA9IE1hdGguZmxvb3I7CgovLyBgTWF0aC50cnVuY2AgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtbWF0aC50cnVuYwovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tbWF0aC10cnVuYyAtLSBzYWZlCm1vZHVsZS5leHBvcnRzID0gTWF0aC50cnVuYyB8fCBmdW5jdGlvbiB0cnVuYyh4KSB7CiAgdmFyIG4gPSAreDsKICByZXR1cm4gKG4gPiAwID8gZmxvb3IgOiBjZWlsKShuKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDc1NzoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBnZXRCdWlsdEluID0gX193ZWJwYWNrX3JlcXVpcmVfXyg3NzUxKTsKdmFyIGlzQ2FsbGFibGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MDEpOwp2YXIgaXNQcm90b3R5cGVPZiA9IF9fd2VicGFja19yZXF1aXJlX18oMTYyNSk7CnZhciBVU0VfU1lNQk9MX0FTX1VJRCA9IF9fd2VicGFja19yZXF1aXJlX18oNzA0MCk7Cgp2YXIgJE9iamVjdCA9IE9iamVjdDsKCm1vZHVsZS5leHBvcnRzID0gVVNFX1NZTUJPTF9BU19VSUQgPyBmdW5jdGlvbiAoaXQpIHsKICByZXR1cm4gdHlwZW9mIGl0ID09ICdzeW1ib2wnOwp9IDogZnVuY3Rpb24gKGl0KSB7CiAgdmFyICRTeW1ib2wgPSBnZXRCdWlsdEluKCdTeW1ib2wnKTsKICByZXR1cm4gaXNDYWxsYWJsZSgkU3ltYm9sKSAmJiBpc1Byb3RvdHlwZU9mKCRTeW1ib2wucHJvdG90eXBlLCAkT2JqZWN0KGl0KSk7Cn07CgoKLyoqKi8gfSksCgovKioqLyA4NTE6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgY2xhc3NvZiA9IF9fd2VicGFja19yZXF1aXJlX18oNjk1NSk7CnZhciBnZXRNZXRob2QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDU5NjYpOwp2YXIgaXNOdWxsT3JVbmRlZmluZWQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQxMTcpOwp2YXIgSXRlcmF0b3JzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2MjY5KTsKdmFyIHdlbGxLbm93blN5bWJvbCA9IF9fd2VicGFja19yZXF1aXJlX18oODIyNyk7Cgp2YXIgSVRFUkFUT1IgPSB3ZWxsS25vd25TeW1ib2woJ2l0ZXJhdG9yJyk7Cgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkgewogIGlmICghaXNOdWxsT3JVbmRlZmluZWQoaXQpKSByZXR1cm4gZ2V0TWV0aG9kKGl0LCBJVEVSQVRPUikKICAgIHx8IGdldE1ldGhvZChpdCwgJ0BAaXRlcmF0b3InKQogICAgfHwgSXRlcmF0b3JzW2NsYXNzb2YoaXQpXTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDk0NDoKLyoqKi8gKChtb2R1bGUpID0+IHsKCgp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9wdGlvbnMpIHsKICB2YXIgYWxwaGFiZXQgPSBvcHRpb25zICYmIG9wdGlvbnMuYWxwaGFiZXQ7CiAgaWYgKGFscGhhYmV0ID09PSB1bmRlZmluZWQgfHwgYWxwaGFiZXQgPT09ICdiYXNlNjQnIHx8IGFscGhhYmV0ID09PSAnYmFzZTY0dXJsJykgcmV0dXJuIGFscGhhYmV0IHx8ICdiYXNlNjQnOwogIHRocm93IG5ldyAkVHlwZUVycm9yKCdJbmNvcnJlY3QgYGFscGhhYmV0YCBvcHRpb24nKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDEwNzI6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgaW50ZXJuYWxPYmplY3RLZXlzID0gX193ZWJwYWNrX3JlcXVpcmVfXygxODI4KTsKdmFyIGVudW1CdWdLZXlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4NzI3KTsKCi8vIGBPYmplY3Qua2V5c2AgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LmtleXMKLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1rZXlzIC0tIHNhZmUKbW9kdWxlLmV4cG9ydHMgPSBPYmplY3Qua2V5cyB8fCBmdW5jdGlvbiBrZXlzKE8pIHsKICByZXR1cm4gaW50ZXJuYWxPYmplY3RLZXlzKE8sIGVudW1CdWdLZXlzKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDExMDM6Ci8qKiovICgobW9kdWxlKSA9PiB7CgoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZXhlYykgewogIHRyeSB7CiAgICByZXR1cm4geyBlcnJvcjogZmFsc2UsIHZhbHVlOiBleGVjKCkgfTsKICB9IGNhdGNoIChlcnJvcikgewogICAgcmV0dXJuIHsgZXJyb3I6IHRydWUsIHZhbHVlOiBlcnJvciB9OwogIH0KfTsKCgovKioqLyB9KSwKCi8qKiovIDExMDg6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgY2xhc3NvZiA9IF9fd2VicGFja19yZXF1aXJlX18oNjk1NSk7Cgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkgewogIHZhciBrbGFzcyA9IGNsYXNzb2YoaXQpOwogIHJldHVybiBrbGFzcyA9PT0gJ0JpZ0ludDY0QXJyYXknIHx8IGtsYXNzID09PSAnQmlnVWludDY0QXJyYXknOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gMTE0ODoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgY2FsbCA9IF9fd2VicGFja19yZXF1aXJlX18oOTU2NSk7CnZhciBpdGVyYXRlID0gX193ZWJwYWNrX3JlcXVpcmVfXygyNjUyKTsKdmFyIGFDYWxsYWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oOTMwNik7CnZhciBhbk9iamVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oODU1MSk7CnZhciBnZXRJdGVyYXRvckRpcmVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oMTc2Nyk7CnZhciBpdGVyYXRvckNsb3NlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTM5KTsKdmFyIGl0ZXJhdG9ySGVscGVyV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ1NDkpOwoKdmFyIGV2ZXJ5V2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IgPSBpdGVyYXRvckhlbHBlcldpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yKCdldmVyeScsIFR5cGVFcnJvcik7CgovLyBgSXRlcmF0b3IucHJvdG90eXBlLmV2ZXJ5YCBtZXRob2QKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1pdGVyYXRvci5wcm90b3R5cGUuZXZlcnkKJCh7IHRhcmdldDogJ0l0ZXJhdG9yJywgcHJvdG86IHRydWUsIHJlYWw6IHRydWUsIGZvcmNlZDogZXZlcnlXaXRob3V0Q2xvc2luZ09uRWFybHlFcnJvciB9LCB7CiAgZXZlcnk6IGZ1bmN0aW9uIGV2ZXJ5KHByZWRpY2F0ZSkgewogICAgYW5PYmplY3QodGhpcyk7CiAgICB0cnkgewogICAgICBhQ2FsbGFibGUocHJlZGljYXRlKTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgIGl0ZXJhdG9yQ2xvc2UodGhpcywgJ3Rocm93JywgZXJyb3IpOwogICAgfQoKICAgIGlmIChldmVyeVdpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yKSByZXR1cm4gY2FsbChldmVyeVdpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yLCB0aGlzLCBwcmVkaWNhdGUpOwoKICAgIHZhciByZWNvcmQgPSBnZXRJdGVyYXRvckRpcmVjdCh0aGlzKTsKICAgIHZhciBjb3VudGVyID0gMDsKICAgIHJldHVybiAhaXRlcmF0ZShyZWNvcmQsIGZ1bmN0aW9uICh2YWx1ZSwgc3RvcCkgewogICAgICBpZiAoIXByZWRpY2F0ZSh2YWx1ZSwgY291bnRlcisrKSkgcmV0dXJuIHN0b3AoKTsKICAgIH0sIHsgSVNfUkVDT1JEOiB0cnVlLCBJTlRFUlJVUFRFRDogdHJ1ZSB9KS5zdG9wcGVkOwogIH0KfSk7CgoKLyoqKi8gfSksCgovKioqLyAxMTgxOgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIE5BVElWRV9XRUFLX01BUCA9IF9fd2VicGFja19yZXF1aXJlX18oODYyMik7CnZhciBnbG9iYWxUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0NTc2KTsKdmFyIGlzT2JqZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNCk7CnZhciBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY2OTkpOwp2YXIgaGFzT3duID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5Mjk3KTsKdmFyIHNoYXJlZCA9IF9fd2VicGFja19yZXF1aXJlX18oNzYyOSk7CnZhciBzaGFyZWRLZXkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDYxMTkpOwp2YXIgaGlkZGVuS2V5cyA9IF9fd2VicGFja19yZXF1aXJlX18oNDIxKTsKCnZhciBPQkpFQ1RfQUxSRUFEWV9JTklUSUFMSVpFRCA9ICdPYmplY3QgYWxyZWFkeSBpbml0aWFsaXplZCc7CnZhciBUeXBlRXJyb3IgPSBnbG9iYWxUaGlzLlR5cGVFcnJvcjsKdmFyIFdlYWtNYXAgPSBnbG9iYWxUaGlzLldlYWtNYXA7CnZhciBzZXQsIGdldCwgaGFzOwoKdmFyIGVuZm9yY2UgPSBmdW5jdGlvbiAoaXQpIHsKICByZXR1cm4gaGFzKGl0KSA/IGdldChpdCkgOiBzZXQoaXQsIHt9KTsKfTsKCnZhciBnZXR0ZXJGb3IgPSBmdW5jdGlvbiAoVFlQRSkgewogIHJldHVybiBmdW5jdGlvbiAoaXQpIHsKICAgIHZhciBzdGF0ZTsKICAgIGlmICghaXNPYmplY3QoaXQpIHx8IChzdGF0ZSA9IGdldChpdCkpLnR5cGUgIT09IFRZUEUpIHsKICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignSW5jb21wYXRpYmxlIHJlY2VpdmVyLCAnICsgVFlQRSArICcgcmVxdWlyZWQnKTsKICAgIH0gcmV0dXJuIHN0YXRlOwogIH07Cn07CgppZiAoTkFUSVZFX1dFQUtfTUFQIHx8IHNoYXJlZC5zdGF0ZSkgewogIHZhciBzdG9yZSA9IHNoYXJlZC5zdGF0ZSB8fCAoc2hhcmVkLnN0YXRlID0gbmV3IFdlYWtNYXAoKSk7CiAgLyogZXNsaW50LWRpc2FibGUgbm8tc2VsZi1hc3NpZ24gLS0gcHJvdG90eXBlIG1ldGhvZHMgcHJvdGVjdGlvbiAqLwogIHN0b3JlLmdldCA9IHN0b3JlLmdldDsKICBzdG9yZS5oYXMgPSBzdG9yZS5oYXM7CiAgc3RvcmUuc2V0ID0gc3RvcmUuc2V0OwogIC8qIGVzbGludC1lbmFibGUgbm8tc2VsZi1hc3NpZ24gLS0gcHJvdG90eXBlIG1ldGhvZHMgcHJvdGVjdGlvbiAqLwogIHNldCA9IGZ1bmN0aW9uIChpdCwgbWV0YWRhdGEpIHsKICAgIGlmIChzdG9yZS5oYXMoaXQpKSB0aHJvdyBuZXcgVHlwZUVycm9yKE9CSkVDVF9BTFJFQURZX0lOSVRJQUxJWkVEKTsKICAgIG1ldGFkYXRhLmZhY2FkZSA9IGl0OwogICAgc3RvcmUuc2V0KGl0LCBtZXRhZGF0YSk7CiAgICByZXR1cm4gbWV0YWRhdGE7CiAgfTsKICBnZXQgPSBmdW5jdGlvbiAoaXQpIHsKICAgIHJldHVybiBzdG9yZS5nZXQoaXQpIHx8IHt9OwogIH07CiAgaGFzID0gZnVuY3Rpb24gKGl0KSB7CiAgICByZXR1cm4gc3RvcmUuaGFzKGl0KTsKICB9Owp9IGVsc2UgewogIHZhciBTVEFURSA9IHNoYXJlZEtleSgnc3RhdGUnKTsKICBoaWRkZW5LZXlzW1NUQVRFXSA9IHRydWU7CiAgc2V0ID0gZnVuY3Rpb24gKGl0LCBtZXRhZGF0YSkgewogICAgaWYgKGhhc093bihpdCwgU1RBVEUpKSB0aHJvdyBuZXcgVHlwZUVycm9yKE9CSkVDVF9BTFJFQURZX0lOSVRJQUxJWkVEKTsKICAgIG1ldGFkYXRhLmZhY2FkZSA9IGl0OwogICAgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KGl0LCBTVEFURSwgbWV0YWRhdGEpOwogICAgcmV0dXJuIG1ldGFkYXRhOwogIH07CiAgZ2V0ID0gZnVuY3Rpb24gKGl0KSB7CiAgICByZXR1cm4gaGFzT3duKGl0LCBTVEFURSkgPyBpdFtTVEFURV0gOiB7fTsKICB9OwogIGhhcyA9IGZ1bmN0aW9uIChpdCkgewogICAgcmV0dXJuIGhhc093bihpdCwgU1RBVEUpOwogIH07Cn0KCm1vZHVsZS5leHBvcnRzID0gewogIHNldDogc2V0LAogIGdldDogZ2V0LAogIGhhczogaGFzLAogIGVuZm9yY2U6IGVuZm9yY2UsCiAgZ2V0dGVyRm9yOiBnZXR0ZXJGb3IKfTsKCgovKioqLyB9KSwKCi8qKiovIDEyOTE6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgdHJ1bmMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDc0MSk7CgovLyBgVG9JbnRlZ2VyT3JJbmZpbml0eWAgYWJzdHJhY3Qgb3BlcmF0aW9uCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtdG9pbnRlZ2Vyb3JpbmZpbml0eQptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcmd1bWVudCkgewogIHZhciBudW1iZXIgPSArYXJndW1lbnQ7CiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXNlbGYtY29tcGFyZSAtLSBOYU4gY2hlY2sKICByZXR1cm4gbnVtYmVyICE9PSBudW1iZXIgfHwgbnVtYmVyID09PSAwID8gMCA6IHRydW5jKG51bWJlcik7Cn07CgoKLyoqKi8gfSksCgovKioqLyAxMzg1OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGl0ZXJhdG9yQ2xvc2UgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1MzkpOwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXRlcnMsIGtpbmQsIHZhbHVlKSB7CiAgZm9yICh2YXIgaSA9IGl0ZXJzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICBpZiAoaXRlcnNbaV0gPT09IHVuZGVmaW5lZCkgY29udGludWU7CiAgICB0cnkgewogICAgICB2YWx1ZSA9IGl0ZXJhdG9yQ2xvc2UoaXRlcnNbaV0uaXRlcmF0b3IsIGtpbmQsIHZhbHVlKTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgIGtpbmQgPSAndGhyb3cnOwogICAgICB2YWx1ZSA9IGVycm9yOwogICAgfQogIH0KICBpZiAoa2luZCA9PT0gJ3Rocm93JykgdGhyb3cgdmFsdWU7CiAgcmV0dXJuIHZhbHVlOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gMTU0ODoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBnbG9iYWxUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0NTc2KTsKdmFyIGZhaWxzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5MDM5KTsKdmFyIFY4ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTE5KTsKdmFyIEVOVklST05NRU5UID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0MjE1KTsKCnZhciBzdHJ1Y3R1cmVkQ2xvbmUgPSBnbG9iYWxUaGlzLnN0cnVjdHVyZWRDbG9uZTsKCm1vZHVsZS5leHBvcnRzID0gISFzdHJ1Y3R1cmVkQ2xvbmUgJiYgIWZhaWxzKGZ1bmN0aW9uICgpIHsKICAvLyBwcmV2ZW50IFY4IEFycmF5QnVmZmVyRGV0YWNoaW5nIHByb3RlY3RvciBjZWxsIGludmFsaWRhdGlvbiBhbmQgcGVyZm9ybWFuY2UgZGVncmFkYXRpb24KICAvLyBodHRwczovL2dpdGh1Yi5jb20vemxvaXJvY2svY29yZS1qcy9pc3N1ZXMvNjc5CiAgaWYgKChFTlZJUk9OTUVOVCA9PT0gJ0RFTk8nICYmIFY4ID4gOTIpIHx8IChFTlZJUk9OTUVOVCA9PT0gJ05PREUnICYmIFY4ID4gOTQpIHx8IChFTlZJUk9OTUVOVCA9PT0gJ0JST1dTRVInICYmIFY4ID4gOTcpKSByZXR1cm4gZmFsc2U7CiAgdmFyIGJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcig4KTsKICB2YXIgY2xvbmUgPSBzdHJ1Y3R1cmVkQ2xvbmUoYnVmZmVyLCB7IHRyYW5zZmVyOiBbYnVmZmVyXSB9KTsKICByZXR1cm4gYnVmZmVyLmJ5dGVMZW5ndGggIT09IDAgfHwgY2xvbmUuYnl0ZUxlbmd0aCAhPT0gODsKfSk7CgoKLyoqKi8gfSksCgovKioqLyAxNTQ5OgovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgovLyBUT0RPOiBSZW1vdmUgZnJvbSBgY29yZS1qc0A0YApfX3dlYnBhY2tfcmVxdWlyZV9fKDY2MzIpOwoKCi8qKiovIH0pLAoKLyoqKi8gMTYyNToKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciB1bmN1cnJ5VGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oOTUwNCk7Cgptb2R1bGUuZXhwb3J0cyA9IHVuY3VycnlUaGlzKHt9LmlzUHJvdG90eXBlT2YpOwoKCi8qKiovIH0pLAoKLyoqKi8gMTY4OToKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciBhcHBseSA9IF9fd2VicGFja19yZXF1aXJlX18oODc0NSk7CnZhciBzbGljZSA9IF9fd2VicGFja19yZXF1aXJlX18oNzY4MCk7CnZhciBuZXdQcm9taXNlQ2FwYWJpbGl0eU1vZHVsZSA9IF9fd2VicGFja19yZXF1aXJlX18oNjA0Myk7CnZhciBhQ2FsbGFibGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDkzMDYpOwp2YXIgcGVyZm9ybSA9IF9fd2VicGFja19yZXF1aXJlX18oMTEwMyk7Cgp2YXIgUHJvbWlzZSA9IGdsb2JhbFRoaXMuUHJvbWlzZTsKCnZhciBBQ0NFUFRfQVJHVU1FTlRTID0gZmFsc2U7Ci8vIEF2b2lkaW5nIHRoZSB1c2Ugb2YgcG9seWZpbGxzIG9mIHRoZSBwcmV2aW91cyBpdGVyYXRpb24gb2YgdGhpcyBwcm9wb3NhbAovLyB0aGF0IGRvZXMgbm90IGFjY2VwdCBhcmd1bWVudHMgb2YgdGhlIGNhbGxiYWNrCnZhciBGT1JDRUQgPSAhUHJvbWlzZSB8fCAhUHJvbWlzZVsndHJ5J10gfHwgcGVyZm9ybShmdW5jdGlvbiAoKSB7CiAgUHJvbWlzZVsndHJ5J10oZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiAgICBBQ0NFUFRfQVJHVU1FTlRTID0gYXJndW1lbnQgPT09IDg7CiAgfSwgOCk7Cn0pLmVycm9yIHx8ICFBQ0NFUFRfQVJHVU1FTlRTOwoKLy8gYFByb21pc2UudHJ5YCBtZXRob2QKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1wcm9taXNlLnRyeQokKHsgdGFyZ2V0OiAnUHJvbWlzZScsIHN0YXQ6IHRydWUsIGZvcmNlZDogRk9SQ0VEIH0sIHsKICAndHJ5JzogZnVuY3Rpb24gKGNhbGxiYWNrZm4gLyogLCAuLi5hcmdzICovKSB7CiAgICB2YXIgYXJncyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxID8gc2xpY2UoYXJndW1lbnRzLCAxKSA6IFtdOwogICAgdmFyIHByb21pc2VDYXBhYmlsaXR5ID0gbmV3UHJvbWlzZUNhcGFiaWxpdHlNb2R1bGUuZih0aGlzKTsKICAgIHZhciByZXN1bHQgPSBwZXJmb3JtKGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIGFwcGx5KGFDYWxsYWJsZShjYWxsYmFja2ZuKSwgdW5kZWZpbmVkLCBhcmdzKTsKICAgIH0pOwogICAgKHJlc3VsdC5lcnJvciA/IHByb21pc2VDYXBhYmlsaXR5LnJlamVjdCA6IHByb21pc2VDYXBhYmlsaXR5LnJlc29sdmUpKHJlc3VsdC52YWx1ZSk7CiAgICByZXR1cm4gcHJvbWlzZUNhcGFiaWxpdHkucHJvbWlzZTsKICB9Cn0pOwoKCi8qKiovIH0pLAoKLyoqKi8gMTY5ODoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgdW5pb24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQyMDQpOwp2YXIgc2V0TWV0aG9kR2V0S2V5c0JlZm9yZUNsb25pbmcgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk4MzUpOwp2YXIgc2V0TWV0aG9kQWNjZXB0U2V0TGlrZSA9IF9fd2VicGFja19yZXF1aXJlX18oNDkxNik7Cgp2YXIgRk9SQ0VEID0gIXNldE1ldGhvZEFjY2VwdFNldExpa2UoJ3VuaW9uJykgfHwgIXNldE1ldGhvZEdldEtleXNCZWZvcmVDbG9uaW5nKCd1bmlvbicpOwoKLy8gYFNldC5wcm90b3R5cGUudW5pb25gIG1ldGhvZAovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXNldC5wcm90b3R5cGUudW5pb24KJCh7IHRhcmdldDogJ1NldCcsIHByb3RvOiB0cnVlLCByZWFsOiB0cnVlLCBmb3JjZWQ6IEZPUkNFRCB9LCB7CiAgdW5pb246IHVuaW9uCn0pOwoKCi8qKiovIH0pLAoKLyoqKi8gMTcwMToKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgY2FsbCA9IF9fd2VicGFja19yZXF1aXJlX18oOTU2NSk7CnZhciBhQ2FsbGFibGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDkzMDYpOwp2YXIgYW5PYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg1NTEpOwp2YXIgZ2V0SXRlcmF0b3JEaXJlY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDE3NjcpOwp2YXIgY3JlYXRlSXRlcmF0b3JQcm94eSA9IF9fd2VicGFja19yZXF1aXJlX18oOTQ2Mik7CnZhciBjYWxsV2l0aFNhZmVJdGVyYXRpb25DbG9zaW5nID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2MzE5KTsKdmFyIGl0ZXJhdG9yQ2xvc2UgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1MzkpOwp2YXIgaXRlcmF0b3JIZWxwZXJUaHJvd3NPbkludmFsaWRJdGVyYXRvciA9IF9fd2VicGFja19yZXF1aXJlX18oNjg0KTsKdmFyIGl0ZXJhdG9ySGVscGVyV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ1NDkpOwp2YXIgSVNfUFVSRSA9IF9fd2VicGFja19yZXF1aXJlX18oNjM5NSk7Cgp2YXIgTUFQX1dJVEhPVVRfVEhST1dJTkdfT05fSU5WQUxJRF9JVEVSQVRPUiA9ICFJU19QVVJFICYmICFpdGVyYXRvckhlbHBlclRocm93c09uSW52YWxpZEl0ZXJhdG9yKCdtYXAnLCBmdW5jdGlvbiAoKSB7IC8qIGVtcHR5ICovIH0pOwp2YXIgbWFwV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IgPSAhSVNfUFVSRSAmJiAhTUFQX1dJVEhPVVRfVEhST1dJTkdfT05fSU5WQUxJRF9JVEVSQVRPUgogICYmIGl0ZXJhdG9ySGVscGVyV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IoJ21hcCcsIFR5cGVFcnJvcik7Cgp2YXIgRk9SQ0VEID0gSVNfUFVSRSB8fCBNQVBfV0lUSE9VVF9USFJPV0lOR19PTl9JTlZBTElEX0lURVJBVE9SIHx8IG1hcFdpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yOwoKdmFyIEl0ZXJhdG9yUHJveHkgPSBjcmVhdGVJdGVyYXRvclByb3h5KGZ1bmN0aW9uICgpIHsKICB2YXIgaXRlcmF0b3IgPSB0aGlzLml0ZXJhdG9yOwogIHZhciByZXN1bHQgPSBhbk9iamVjdChjYWxsKHRoaXMubmV4dCwgaXRlcmF0b3IpKTsKICB2YXIgZG9uZSA9IHRoaXMuZG9uZSA9ICEhcmVzdWx0LmRvbmU7CiAgaWYgKCFkb25lKSByZXR1cm4gY2FsbFdpdGhTYWZlSXRlcmF0aW9uQ2xvc2luZyhpdGVyYXRvciwgdGhpcy5tYXBwZXIsIFtyZXN1bHQudmFsdWUsIHRoaXMuY291bnRlcisrXSwgdHJ1ZSk7Cn0pOwoKLy8gYEl0ZXJhdG9yLnByb3RvdHlwZS5tYXBgIG1ldGhvZAovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWl0ZXJhdG9yLnByb3RvdHlwZS5tYXAKJCh7IHRhcmdldDogJ0l0ZXJhdG9yJywgcHJvdG86IHRydWUsIHJlYWw6IHRydWUsIGZvcmNlZDogRk9SQ0VEIH0sIHsKICBtYXA6IGZ1bmN0aW9uIG1hcChtYXBwZXIpIHsKICAgIGFuT2JqZWN0KHRoaXMpOwogICAgdHJ5IHsKICAgICAgYUNhbGxhYmxlKG1hcHBlcik7CiAgICB9IGNhdGNoIChlcnJvcikgewogICAgICBpdGVyYXRvckNsb3NlKHRoaXMsICd0aHJvdycsIGVycm9yKTsKICAgIH0KCiAgICBpZiAobWFwV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IpIHJldHVybiBjYWxsKG1hcFdpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yLCB0aGlzLCBtYXBwZXIpOwoKICAgIHJldHVybiBuZXcgSXRlcmF0b3JQcm94eShnZXRJdGVyYXRvckRpcmVjdCh0aGlzKSwgewogICAgICBtYXBwZXI6IG1hcHBlcgogICAgfSk7CiAgfQp9KTsKCgovKioqLyB9KSwKCi8qKiovIDE3Njc6Ci8qKiovICgobW9kdWxlKSA9PiB7CgoKLy8gYEdldEl0ZXJhdG9yRGlyZWN0KG9iailgIGFic3RyYWN0IG9wZXJhdGlvbgovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWdldGl0ZXJhdG9yZGlyZWN0Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9iaikgewogIHJldHVybiB7CiAgICBpdGVyYXRvcjogb2JqLAogICAgbmV4dDogb2JqLm5leHQsCiAgICBkb25lOiBmYWxzZQogIH07Cn07CgoKLyoqKi8gfSksCgovKioqLyAxODA2OgovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgJCA9IF9fd2VicGFja19yZXF1aXJlX18oNjUxOCk7CnZhciBhbk9iamVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oODU1MSk7CnZhciBpdGVyYXRlID0gX193ZWJwYWNrX3JlcXVpcmVfXygyNjUyKTsKdmFyIGdldEl0ZXJhdG9yRGlyZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXygxNzY3KTsKCnZhciBwdXNoID0gW10ucHVzaDsKCi8vIGBJdGVyYXRvci5wcm90b3R5cGUudG9BcnJheWAgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtaXRlcmF0b3IucHJvdG90eXBlLnRvYXJyYXkKJCh7IHRhcmdldDogJ0l0ZXJhdG9yJywgcHJvdG86IHRydWUsIHJlYWw6IHRydWUgfSwgewogIHRvQXJyYXk6IGZ1bmN0aW9uIHRvQXJyYXkoKSB7CiAgICB2YXIgcmVzdWx0ID0gW107CiAgICBpdGVyYXRlKGdldEl0ZXJhdG9yRGlyZWN0KGFuT2JqZWN0KHRoaXMpKSwgcHVzaCwgeyB0aGF0OiByZXN1bHQsIElTX1JFQ09SRDogdHJ1ZSB9KTsKICAgIHJldHVybiByZXN1bHQ7CiAgfQp9KTsKCgovKioqLyB9KSwKCi8qKiovIDE4Mjg6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgdW5jdXJyeVRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1MDQpOwp2YXIgaGFzT3duID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5Mjk3KTsKdmFyIHRvSW5kZXhlZE9iamVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oNTM5Nyk7CnZhciBpbmRleE9mID0gKF9fd2VicGFja19yZXF1aXJlX18oOTYxNykuaW5kZXhPZik7CnZhciBoaWRkZW5LZXlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0MjEpOwoKdmFyIHB1c2ggPSB1bmN1cnJ5VGhpcyhbXS5wdXNoKTsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9iamVjdCwgbmFtZXMpIHsKICB2YXIgTyA9IHRvSW5kZXhlZE9iamVjdChvYmplY3QpOwogIHZhciBpID0gMDsKICB2YXIgcmVzdWx0ID0gW107CiAgdmFyIGtleTsKICBmb3IgKGtleSBpbiBPKSAhaGFzT3duKGhpZGRlbktleXMsIGtleSkgJiYgaGFzT3duKE8sIGtleSkgJiYgcHVzaChyZXN1bHQsIGtleSk7CiAgLy8gRG9uJ3QgZW51bSBidWcgJiBoaWRkZW4ga2V5cwogIHdoaWxlIChuYW1lcy5sZW5ndGggPiBpKSBpZiAoaGFzT3duKE8sIGtleSA9IG5hbWVzW2krK10pKSB7CiAgICB+aW5kZXhPZihyZXN1bHQsIGtleSkgfHwgcHVzaChyZXN1bHQsIGtleSk7CiAgfQogIHJldHVybiByZXN1bHQ7Cn07CgoKLyoqKi8gfSksCgovKioqLyAyMTA2OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIG1ha2VCdWlsdEluID0gX193ZWJwYWNrX3JlcXVpcmVfXygyODMpOwp2YXIgZGVmaW5lUHJvcGVydHkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MTMpOwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodGFyZ2V0LCBuYW1lLCBkZXNjcmlwdG9yKSB7CiAgaWYgKGRlc2NyaXB0b3IuZ2V0KSBtYWtlQnVpbHRJbihkZXNjcmlwdG9yLmdldCwgbmFtZSwgeyBnZXR0ZXI6IHRydWUgfSk7CiAgaWYgKGRlc2NyaXB0b3Iuc2V0KSBtYWtlQnVpbHRJbihkZXNjcmlwdG9yLnNldCwgbmFtZSwgeyBzZXR0ZXI6IHRydWUgfSk7CiAgcmV0dXJuIGRlZmluZVByb3BlcnR5LmYodGFyZ2V0LCBuYW1lLCBkZXNjcmlwdG9yKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDIxNDA6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgd2VsbEtub3duU3ltYm9sID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4MjI3KTsKCnZhciBUT19TVFJJTkdfVEFHID0gd2VsbEtub3duU3ltYm9sKCd0b1N0cmluZ1RhZycpOwp2YXIgdGVzdCA9IHt9OwoKdGVzdFtUT19TVFJJTkdfVEFHXSA9ICd6JzsKCm1vZHVsZS5leHBvcnRzID0gU3RyaW5nKHRlc3QpID09PSAnW29iamVjdCB6XSc7CgoKLyoqKi8gfSksCgovKioqLyAyMTk1OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIHVuY3VycnlUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTA0KTsKCnZhciB0b1N0cmluZyA9IHVuY3VycnlUaGlzKHt9LnRvU3RyaW5nKTsKdmFyIHN0cmluZ1NsaWNlID0gdW5jdXJyeVRoaXMoJycuc2xpY2UpOwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHsKICByZXR1cm4gc3RyaW5nU2xpY2UodG9TdHJpbmcoaXQpLCA4LCAtMSk7Cn07CgoKLyoqKi8gfSksCgovKioqLyAyMjExOgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGZhaWxzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5MDM5KTsKCm1vZHVsZS5leHBvcnRzID0gIWZhaWxzKGZ1bmN0aW9uICgpIHsKICBmdW5jdGlvbiBGKCkgeyAvKiBlbXB0eSAqLyB9CiAgRi5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBudWxsOwogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZ2V0cHJvdG90eXBlb2YgLS0gcmVxdWlyZWQgZm9yIHRlc3RpbmcKICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKG5ldyBGKCkpICE9PSBGLnByb3RvdHlwZTsKfSk7CgoKLyoqKi8gfSksCgovKioqLyAyMzAzOgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGdsb2JhbFRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ1NzYpOwp2YXIgdW5jdXJyeVRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1MDQpOwoKdmFyIFVpbnQ4QXJyYXkgPSBnbG9iYWxUaGlzLlVpbnQ4QXJyYXk7CnZhciBTeW50YXhFcnJvciA9IGdsb2JhbFRoaXMuU3ludGF4RXJyb3I7CnZhciBwYXJzZUludCA9IGdsb2JhbFRoaXMucGFyc2VJbnQ7CnZhciBtaW4gPSBNYXRoLm1pbjsKdmFyIE5PVF9IRVggPSAvW15cZGEtZl0vaTsKdmFyIGV4ZWMgPSB1bmN1cnJ5VGhpcyhOT1RfSEVYLmV4ZWMpOwp2YXIgc3RyaW5nU2xpY2UgPSB1bmN1cnJ5VGhpcygnJy5zbGljZSk7Cgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChzdHJpbmcsIGludG8pIHsKICB2YXIgc3RyaW5nTGVuZ3RoID0gc3RyaW5nLmxlbmd0aDsKICBpZiAoc3RyaW5nTGVuZ3RoICUgMiAhPT0gMCkgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdTdHJpbmcgc2hvdWxkIGJlIGFuIGV2ZW4gbnVtYmVyIG9mIGNoYXJhY3RlcnMnKTsKICB2YXIgbWF4TGVuZ3RoID0gaW50byA/IG1pbihpbnRvLmxlbmd0aCwgc3RyaW5nTGVuZ3RoIC8gMikgOiBzdHJpbmdMZW5ndGggLyAyOwogIHZhciBieXRlcyA9IGludG8gfHwgbmV3IFVpbnQ4QXJyYXkobWF4TGVuZ3RoKTsKICB2YXIgcmVhZCA9IDA7CiAgdmFyIHdyaXR0ZW4gPSAwOwogIHdoaWxlICh3cml0dGVuIDwgbWF4TGVuZ3RoKSB7CiAgICB2YXIgaGV4aXRzID0gc3RyaW5nU2xpY2Uoc3RyaW5nLCByZWFkLCByZWFkICs9IDIpOwogICAgaWYgKGV4ZWMoTk9UX0hFWCwgaGV4aXRzKSkgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdTdHJpbmcgc2hvdWxkIG9ubHkgY29udGFpbiBoZXggY2hhcmFjdGVycycpOwogICAgYnl0ZXNbd3JpdHRlbisrXSA9IHBhcnNlSW50KGhleGl0cywgMTYpOwogIH0KICByZXR1cm4geyBieXRlczogYnl0ZXMsIHJlYWQ6IHJlYWQgfTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDIzNjA6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgovKiBnbG9iYWwgQWN0aXZlWE9iamVjdCAtLSBvbGQgSUUsIFdTSCAqLwp2YXIgYW5PYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg1NTEpOwp2YXIgZGVmaW5lUHJvcGVydGllc01vZHVsZSA9IF9fd2VicGFja19yZXF1aXJlX18oNjgwMSk7CnZhciBlbnVtQnVnS2V5cyA9IF9fd2VicGFja19yZXF1aXJlX18oODcyNyk7CnZhciBoaWRkZW5LZXlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0MjEpOwp2YXIgaHRtbCA9IF9fd2VicGFja19yZXF1aXJlX18oMzk3KTsKdmFyIGRvY3VtZW50Q3JlYXRlRWxlbWVudCA9IF9fd2VicGFja19yZXF1aXJlX18oNDA1NSk7CnZhciBzaGFyZWRLZXkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDYxMTkpOwoKdmFyIEdUID0gJz4nOwp2YXIgTFQgPSAnPCc7CnZhciBQUk9UT1RZUEUgPSAncHJvdG90eXBlJzsKdmFyIFNDUklQVCA9ICdzY3JpcHQnOwp2YXIgSUVfUFJPVE8gPSBzaGFyZWRLZXkoJ0lFX1BST1RPJyk7Cgp2YXIgRW1wdHlDb25zdHJ1Y3RvciA9IGZ1bmN0aW9uICgpIHsgLyogZW1wdHkgKi8gfTsKCnZhciBzY3JpcHRUYWcgPSBmdW5jdGlvbiAoY29udGVudCkgewogIHJldHVybiBMVCArIFNDUklQVCArIEdUICsgY29udGVudCArIExUICsgJy8nICsgU0NSSVBUICsgR1Q7Cn07CgovLyBDcmVhdGUgb2JqZWN0IHdpdGggZmFrZSBgbnVsbGAgcHJvdG90eXBlOiB1c2UgQWN0aXZlWCBPYmplY3Qgd2l0aCBjbGVhcmVkIHByb3RvdHlwZQp2YXIgTnVsbFByb3RvT2JqZWN0VmlhQWN0aXZlWCA9IGZ1bmN0aW9uIChhY3RpdmVYRG9jdW1lbnQpIHsKICBhY3RpdmVYRG9jdW1lbnQud3JpdGUoc2NyaXB0VGFnKCcnKSk7CiAgYWN0aXZlWERvY3VtZW50LmNsb3NlKCk7CiAgdmFyIHRlbXAgPSBhY3RpdmVYRG9jdW1lbnQucGFyZW50V2luZG93Lk9iamVjdDsKICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdXNlbGVzcy1hc3NpZ25tZW50IC0tIGF2b2lkIG1lbW9yeSBsZWFrCiAgYWN0aXZlWERvY3VtZW50ID0gbnVsbDsKICByZXR1cm4gdGVtcDsKfTsKCi8vIENyZWF0ZSBvYmplY3Qgd2l0aCBmYWtlIGBudWxsYCBwcm90b3R5cGU6IHVzZSBpZnJhbWUgT2JqZWN0IHdpdGggY2xlYXJlZCBwcm90b3R5cGUKdmFyIE51bGxQcm90b09iamVjdFZpYUlGcmFtZSA9IGZ1bmN0aW9uICgpIHsKICAvLyBUaHJhc2gsIHdhc3RlIGFuZCBzb2RvbXk6IElFIEdDIGJ1ZwogIHZhciBpZnJhbWUgPSBkb2N1bWVudENyZWF0ZUVsZW1lbnQoJ2lmcmFtZScpOwogIHZhciBKUyA9ICdqYXZhJyArIFNDUklQVCArICc6JzsKICB2YXIgaWZyYW1lRG9jdW1lbnQ7CiAgaWZyYW1lLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7CiAgaHRtbC5hcHBlbmRDaGlsZChpZnJhbWUpOwogIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS96bG9pcm9jay9jb3JlLWpzL2lzc3Vlcy80NzUKICBpZnJhbWUuc3JjID0gU3RyaW5nKEpTKTsKICBpZnJhbWVEb2N1bWVudCA9IGlmcmFtZS5jb250ZW50V2luZG93LmRvY3VtZW50OwogIGlmcmFtZURvY3VtZW50Lm9wZW4oKTsKICBpZnJhbWVEb2N1bWVudC53cml0ZShzY3JpcHRUYWcoJ2RvY3VtZW50LkY9T2JqZWN0JykpOwogIGlmcmFtZURvY3VtZW50LmNsb3NlKCk7CiAgcmV0dXJuIGlmcmFtZURvY3VtZW50LkY7Cn07CgovLyBDaGVjayBmb3IgZG9jdW1lbnQuZG9tYWluIGFuZCBhY3RpdmUgeCBzdXBwb3J0Ci8vIE5vIG5lZWQgdG8gdXNlIGFjdGl2ZSB4IGFwcHJvYWNoIHdoZW4gZG9jdW1lbnQuZG9tYWluIGlzIG5vdCBzZXQKLy8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9lcy1zaGltcy9lczUtc2hpbS9pc3N1ZXMvMTUwCi8vIHZhcmlhdGlvbiBvZiBodHRwczovL2dpdGh1Yi5jb20va2l0Y2FtYnJpZGdlL2VzNS1zaGltL2NvbW1pdC80ZjczOGFjMDY2MzQ2Ci8vIGF2b2lkIElFIEdDIGJ1Zwp2YXIgYWN0aXZlWERvY3VtZW50Owp2YXIgTnVsbFByb3RvT2JqZWN0ID0gZnVuY3Rpb24gKCkgewogIHRyeSB7CiAgICBhY3RpdmVYRG9jdW1lbnQgPSBuZXcgQWN0aXZlWE9iamVjdCgnaHRtbGZpbGUnKTsKICB9IGNhdGNoIChlcnJvcikgeyAvKiBpZ25vcmUgKi8gfQogIE51bGxQcm90b09iamVjdCA9IHR5cGVvZiBkb2N1bWVudCAhPSAndW5kZWZpbmVkJwogICAgPyBkb2N1bWVudC5kb21haW4gJiYgYWN0aXZlWERvY3VtZW50CiAgICAgID8gTnVsbFByb3RvT2JqZWN0VmlhQWN0aXZlWChhY3RpdmVYRG9jdW1lbnQpIC8vIG9sZCBJRQogICAgICA6IE51bGxQcm90b09iamVjdFZpYUlGcmFtZSgpCiAgICA6IE51bGxQcm90b09iamVjdFZpYUFjdGl2ZVgoYWN0aXZlWERvY3VtZW50KTsgLy8gV1NICiAgdmFyIGxlbmd0aCA9IGVudW1CdWdLZXlzLmxlbmd0aDsKICB3aGlsZSAobGVuZ3RoLS0pIGRlbGV0ZSBOdWxsUHJvdG9PYmplY3RbUFJPVE9UWVBFXVtlbnVtQnVnS2V5c1tsZW5ndGhdXTsKICByZXR1cm4gTnVsbFByb3RvT2JqZWN0KCk7Cn07CgpoaWRkZW5LZXlzW0lFX1BST1RPXSA9IHRydWU7CgovLyBgT2JqZWN0LmNyZWF0ZWAgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtb2JqZWN0LmNyZWF0ZQovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tb2JqZWN0LWNyZWF0ZSAtLSBzYWZlCm1vZHVsZS5leHBvcnRzID0gT2JqZWN0LmNyZWF0ZSB8fCBmdW5jdGlvbiBjcmVhdGUoTywgUHJvcGVydGllcykgewogIHZhciByZXN1bHQ7CiAgaWYgKE8gIT09IG51bGwpIHsKICAgIEVtcHR5Q29uc3RydWN0b3JbUFJPVE9UWVBFXSA9IGFuT2JqZWN0KE8pOwogICAgcmVzdWx0ID0gbmV3IEVtcHR5Q29uc3RydWN0b3IoKTsKICAgIEVtcHR5Q29uc3RydWN0b3JbUFJPVE9UWVBFXSA9IG51bGw7CiAgICAvLyBhZGQgIl9fcHJvdG9fXyIgZm9yIE9iamVjdC5nZXRQcm90b3R5cGVPZiBwb2x5ZmlsbAogICAgcmVzdWx0W0lFX1BST1RPXSA9IE87CiAgfSBlbHNlIHJlc3VsdCA9IE51bGxQcm90b09iamVjdCgpOwogIHJldHVybiBQcm9wZXJ0aWVzID09PSB1bmRlZmluZWQgPyByZXN1bHQgOiBkZWZpbmVQcm9wZXJ0aWVzTW9kdWxlLmYocmVzdWx0LCBQcm9wZXJ0aWVzKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDI0NzU6Ci8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciAkID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2NTE4KTsKdmFyIGlzU3VwZXJzZXRPZiA9IF9fd2VicGFja19yZXF1aXJlX18oODUyNyk7CnZhciBzZXRNZXRob2RBY2NlcHRTZXRMaWtlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0OTE2KTsKCnZhciBJTkNPUlJFQ1QgPSAhc2V0TWV0aG9kQWNjZXB0U2V0TGlrZSgnaXNTdXBlcnNldE9mJywgZnVuY3Rpb24gKHJlc3VsdCkgewogIHJldHVybiAhcmVzdWx0Owp9KTsKCi8vIGBTZXQucHJvdG90eXBlLmlzU3VwZXJzZXRPZmAgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc2V0LnByb3RvdHlwZS5pc3N1cGVyc2V0b2YKJCh7IHRhcmdldDogJ1NldCcsIHByb3RvOiB0cnVlLCByZWFsOiB0cnVlLCBmb3JjZWQ6IElOQ09SUkVDVCB9LCB7CiAgaXNTdXBlcnNldE9mOiBpc1N1cGVyc2V0T2YKfSk7CgoKLyoqKi8gfSksCgovKioqLyAyNDg5OgovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgJCA9IF9fd2VicGFja19yZXF1aXJlX18oNjUxOCk7CnZhciBjYWxsID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTY1KTsKdmFyIGFDYWxsYWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oOTMwNik7CnZhciBhbk9iamVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oODU1MSk7CnZhciBnZXRJdGVyYXRvckRpcmVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oMTc2Nyk7CnZhciBjcmVhdGVJdGVyYXRvclByb3h5ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NDYyKTsKdmFyIGNhbGxXaXRoU2FmZUl0ZXJhdGlvbkNsb3NpbmcgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDYzMTkpOwp2YXIgSVNfUFVSRSA9IF9fd2VicGFja19yZXF1aXJlX18oNjM5NSk7CnZhciBpdGVyYXRvckNsb3NlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTM5KTsKdmFyIGl0ZXJhdG9ySGVscGVyVGhyb3dzT25JbnZhbGlkSXRlcmF0b3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY4NCk7CnZhciBpdGVyYXRvckhlbHBlcldpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0NTQ5KTsKCnZhciBGSUxURVJfV0lUSE9VVF9USFJPV0lOR19PTl9JTlZBTElEX0lURVJBVE9SID0gIUlTX1BVUkUgJiYgIWl0ZXJhdG9ySGVscGVyVGhyb3dzT25JbnZhbGlkSXRlcmF0b3IoJ2ZpbHRlcicsIGZ1bmN0aW9uICgpIHsgLyogZW1wdHkgKi8gfSk7CnZhciBmaWx0ZXJXaXRob3V0Q2xvc2luZ09uRWFybHlFcnJvciA9ICFJU19QVVJFICYmICFGSUxURVJfV0lUSE9VVF9USFJPV0lOR19PTl9JTlZBTElEX0lURVJBVE9SCiAgJiYgaXRlcmF0b3JIZWxwZXJXaXRob3V0Q2xvc2luZ09uRWFybHlFcnJvcignZmlsdGVyJywgVHlwZUVycm9yKTsKCnZhciBGT1JDRUQgPSBJU19QVVJFIHx8IEZJTFRFUl9XSVRIT1VUX1RIUk9XSU5HX09OX0lOVkFMSURfSVRFUkFUT1IgfHwgZmlsdGVyV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3I7Cgp2YXIgSXRlcmF0b3JQcm94eSA9IGNyZWF0ZUl0ZXJhdG9yUHJveHkoZnVuY3Rpb24gKCkgewogIHZhciBpdGVyYXRvciA9IHRoaXMuaXRlcmF0b3I7CiAgdmFyIHByZWRpY2F0ZSA9IHRoaXMucHJlZGljYXRlOwogIHZhciBuZXh0ID0gdGhpcy5uZXh0OwogIHZhciByZXN1bHQsIGRvbmUsIHZhbHVlOwogIHdoaWxlICh0cnVlKSB7CiAgICByZXN1bHQgPSBhbk9iamVjdChjYWxsKG5leHQsIGl0ZXJhdG9yKSk7CiAgICBkb25lID0gdGhpcy5kb25lID0gISFyZXN1bHQuZG9uZTsKICAgIGlmIChkb25lKSByZXR1cm47CiAgICB2YWx1ZSA9IHJlc3VsdC52YWx1ZTsKICAgIGlmIChjYWxsV2l0aFNhZmVJdGVyYXRpb25DbG9zaW5nKGl0ZXJhdG9yLCBwcmVkaWNhdGUsIFt2YWx1ZSwgdGhpcy5jb3VudGVyKytdLCB0cnVlKSkgcmV0dXJuIHZhbHVlOwogIH0KfSk7CgovLyBgSXRlcmF0b3IucHJvdG90eXBlLmZpbHRlcmAgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtaXRlcmF0b3IucHJvdG90eXBlLmZpbHRlcgokKHsgdGFyZ2V0OiAnSXRlcmF0b3InLCBwcm90bzogdHJ1ZSwgcmVhbDogdHJ1ZSwgZm9yY2VkOiBGT1JDRUQgfSwgewogIGZpbHRlcjogZnVuY3Rpb24gZmlsdGVyKHByZWRpY2F0ZSkgewogICAgYW5PYmplY3QodGhpcyk7CiAgICB0cnkgewogICAgICBhQ2FsbGFibGUocHJlZGljYXRlKTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgIGl0ZXJhdG9yQ2xvc2UodGhpcywgJ3Rocm93JywgZXJyb3IpOwogICAgfQoKICAgIGlmIChmaWx0ZXJXaXRob3V0Q2xvc2luZ09uRWFybHlFcnJvcikgcmV0dXJuIGNhbGwoZmlsdGVyV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IsIHRoaXMsIHByZWRpY2F0ZSk7CgogICAgcmV0dXJuIG5ldyBJdGVyYXRvclByb3h5KGdldEl0ZXJhdG9yRGlyZWN0KHRoaXMpLCB7CiAgICAgIHByZWRpY2F0ZTogcHJlZGljYXRlCiAgICB9KTsKICB9Cn0pOwoKCi8qKiovIH0pLAoKLyoqKi8gMjUyOToKLyoqKi8gKChtb2R1bGUpID0+IHsKCgovLyBgQ3JlYXRlSXRlclJlc3VsdE9iamVjdGAgYWJzdHJhY3Qgb3BlcmF0aW9uCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtY3JlYXRlaXRlcnJlc3VsdG9iamVjdAptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh2YWx1ZSwgZG9uZSkgewogIHJldHVybiB7IHZhbHVlOiB2YWx1ZSwgZG9uZTogZG9uZSB9Owp9OwoKCi8qKiovIH0pLAoKLyoqKi8gMjYwMzoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciB0b1N0cmluZyA9IF9fd2VicGFja19yZXF1aXJlX18oNjU1KTsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50LCAkZGVmYXVsdCkgewogIHJldHVybiBhcmd1bWVudCA9PT0gdW5kZWZpbmVkID8gYXJndW1lbnRzLmxlbmd0aCA8IDIgPyAnJyA6ICRkZWZhdWx0IDogdG9TdHJpbmcoYXJndW1lbnQpOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gMjY1MjoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBiaW5kID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2MDgwKTsKdmFyIGNhbGwgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1NjUpOwp2YXIgYW5PYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg1NTEpOwp2YXIgdHJ5VG9TdHJpbmcgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY4MjMpOwp2YXIgaXNBcnJheUl0ZXJhdG9yTWV0aG9kID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0MjA5KTsKdmFyIGxlbmd0aE9mQXJyYXlMaWtlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2MTk4KTsKdmFyIGlzUHJvdG90eXBlT2YgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDE2MjUpOwp2YXIgZ2V0SXRlcmF0b3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDgxKTsKdmFyIGdldEl0ZXJhdG9yTWV0aG9kID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4NTEpOwp2YXIgaXRlcmF0b3JDbG9zZSA9IF9fd2VicGFja19yZXF1aXJlX18oOTUzOSk7Cgp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKCnZhciBSZXN1bHQgPSBmdW5jdGlvbiAoc3RvcHBlZCwgcmVzdWx0KSB7CiAgdGhpcy5zdG9wcGVkID0gc3RvcHBlZDsKICB0aGlzLnJlc3VsdCA9IHJlc3VsdDsKfTsKCnZhciBSZXN1bHRQcm90b3R5cGUgPSBSZXN1bHQucHJvdG90eXBlOwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXRlcmFibGUsIHVuYm91bmRGdW5jdGlvbiwgb3B0aW9ucykgewogIHZhciB0aGF0ID0gb3B0aW9ucyAmJiBvcHRpb25zLnRoYXQ7CiAgdmFyIEFTX0VOVFJJRVMgPSAhIShvcHRpb25zICYmIG9wdGlvbnMuQVNfRU5UUklFUyk7CiAgdmFyIElTX1JFQ09SRCA9ICEhKG9wdGlvbnMgJiYgb3B0aW9ucy5JU19SRUNPUkQpOwogIHZhciBJU19JVEVSQVRPUiA9ICEhKG9wdGlvbnMgJiYgb3B0aW9ucy5JU19JVEVSQVRPUik7CiAgdmFyIElOVEVSUlVQVEVEID0gISEob3B0aW9ucyAmJiBvcHRpb25zLklOVEVSUlVQVEVEKTsKICB2YXIgZm4gPSBiaW5kKHVuYm91bmRGdW5jdGlvbiwgdGhhdCk7CiAgdmFyIGl0ZXJhdG9yLCBpdGVyRm4sIGluZGV4LCBsZW5ndGgsIHJlc3VsdCwgbmV4dCwgc3RlcDsKCiAgdmFyIHN0b3AgPSBmdW5jdGlvbiAoY29uZGl0aW9uKSB7CiAgICBpZiAoaXRlcmF0b3IpIGl0ZXJhdG9yQ2xvc2UoaXRlcmF0b3IsICdub3JtYWwnKTsKICAgIHJldHVybiBuZXcgUmVzdWx0KHRydWUsIGNvbmRpdGlvbik7CiAgfTsKCiAgdmFyIGNhbGxGbiA9IGZ1bmN0aW9uICh2YWx1ZSkgewogICAgaWYgKEFTX0VOVFJJRVMpIHsKICAgICAgYW5PYmplY3QodmFsdWUpOwogICAgICByZXR1cm4gSU5URVJSVVBURUQgPyBmbih2YWx1ZVswXSwgdmFsdWVbMV0sIHN0b3ApIDogZm4odmFsdWVbMF0sIHZhbHVlWzFdKTsKICAgIH0gcmV0dXJuIElOVEVSUlVQVEVEID8gZm4odmFsdWUsIHN0b3ApIDogZm4odmFsdWUpOwogIH07CgogIGlmIChJU19SRUNPUkQpIHsKICAgIGl0ZXJhdG9yID0gaXRlcmFibGUuaXRlcmF0b3I7CiAgfSBlbHNlIGlmIChJU19JVEVSQVRPUikgewogICAgaXRlcmF0b3IgPSBpdGVyYWJsZTsKICB9IGVsc2UgewogICAgaXRlckZuID0gZ2V0SXRlcmF0b3JNZXRob2QoaXRlcmFibGUpOwogICAgaWYgKCFpdGVyRm4pIHRocm93IG5ldyAkVHlwZUVycm9yKHRyeVRvU3RyaW5nKGl0ZXJhYmxlKSArICcgaXMgbm90IGl0ZXJhYmxlJyk7CiAgICAvLyBvcHRpbWlzYXRpb24gZm9yIGFycmF5IGl0ZXJhdG9ycwogICAgaWYgKGlzQXJyYXlJdGVyYXRvck1ldGhvZChpdGVyRm4pKSB7CiAgICAgIGZvciAoaW5kZXggPSAwLCBsZW5ndGggPSBsZW5ndGhPZkFycmF5TGlrZShpdGVyYWJsZSk7IGxlbmd0aCA+IGluZGV4OyBpbmRleCsrKSB7CiAgICAgICAgcmVzdWx0ID0gY2FsbEZuKGl0ZXJhYmxlW2luZGV4XSk7CiAgICAgICAgaWYgKHJlc3VsdCAmJiBpc1Byb3RvdHlwZU9mKFJlc3VsdFByb3RvdHlwZSwgcmVzdWx0KSkgcmV0dXJuIHJlc3VsdDsKICAgICAgfSByZXR1cm4gbmV3IFJlc3VsdChmYWxzZSk7CiAgICB9CiAgICBpdGVyYXRvciA9IGdldEl0ZXJhdG9yKGl0ZXJhYmxlLCBpdGVyRm4pOwogIH0KCiAgbmV4dCA9IElTX1JFQ09SRCA/IGl0ZXJhYmxlLm5leHQgOiBpdGVyYXRvci5uZXh0OwogIHdoaWxlICghKHN0ZXAgPSBjYWxsKG5leHQsIGl0ZXJhdG9yKSkuZG9uZSkgewogICAgdHJ5IHsKICAgICAgcmVzdWx0ID0gY2FsbEZuKHN0ZXAudmFsdWUpOwogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgaXRlcmF0b3JDbG9zZShpdGVyYXRvciwgJ3Rocm93JywgZXJyb3IpOwogICAgfQogICAgaWYgKHR5cGVvZiByZXN1bHQgPT0gJ29iamVjdCcgJiYgcmVzdWx0ICYmIGlzUHJvdG90eXBlT2YoUmVzdWx0UHJvdG90eXBlLCByZXN1bHQpKSByZXR1cm4gcmVzdWx0OwogIH0gcmV0dXJuIG5ldyBSZXN1bHQoZmFsc2UpOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gMjc3NzoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBjYWxsID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTY1KTsKdmFyIGlzT2JqZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNCk7CnZhciBpc1N5bWJvbCA9IF9fd2VicGFja19yZXF1aXJlX18oNzU3KTsKdmFyIGdldE1ldGhvZCA9IF9fd2VicGFja19yZXF1aXJlX18oNTk2Nik7CnZhciBvcmRpbmFyeVRvUHJpbWl0aXZlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0MjcwKTsKdmFyIHdlbGxLbm93blN5bWJvbCA9IF9fd2VicGFja19yZXF1aXJlX18oODIyNyk7Cgp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKdmFyIFRPX1BSSU1JVElWRSA9IHdlbGxLbm93blN5bWJvbCgndG9QcmltaXRpdmUnKTsKCi8vIGBUb1ByaW1pdGl2ZWAgYWJzdHJhY3Qgb3BlcmF0aW9uCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtdG9wcmltaXRpdmUKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaW5wdXQsIHByZWYpIHsKICBpZiAoIWlzT2JqZWN0KGlucHV0KSB8fCBpc1N5bWJvbChpbnB1dCkpIHJldHVybiBpbnB1dDsKICB2YXIgZXhvdGljVG9QcmltID0gZ2V0TWV0aG9kKGlucHV0LCBUT19QUklNSVRJVkUpOwogIHZhciByZXN1bHQ7CiAgaWYgKGV4b3RpY1RvUHJpbSkgewogICAgaWYgKHByZWYgPT09IHVuZGVmaW5lZCkgcHJlZiA9ICdkZWZhdWx0JzsKICAgIHJlc3VsdCA9IGNhbGwoZXhvdGljVG9QcmltLCBpbnB1dCwgcHJlZik7CiAgICBpZiAoIWlzT2JqZWN0KHJlc3VsdCkgfHwgaXNTeW1ib2wocmVzdWx0KSkgcmV0dXJuIHJlc3VsdDsKICAgIHRocm93IG5ldyAkVHlwZUVycm9yKCJDYW4ndCBjb252ZXJ0IG9iamVjdCB0byBwcmltaXRpdmUgdmFsdWUiKTsKICB9CiAgaWYgKHByZWYgPT09IHVuZGVmaW5lZCkgcHJlZiA9ICdudW1iZXInOwogIHJldHVybiBvcmRpbmFyeVRvUHJpbWl0aXZlKGlucHV0LCBwcmVmKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDI3ODc6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgaGFzT3duID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5Mjk3KTsKdmFyIGlzQ2FsbGFibGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MDEpOwp2YXIgdG9PYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg5ODEpOwp2YXIgc2hhcmVkS2V5ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2MTE5KTsKdmFyIENPUlJFQ1RfUFJPVE9UWVBFX0dFVFRFUiA9IF9fd2VicGFja19yZXF1aXJlX18oMjIxMSk7Cgp2YXIgSUVfUFJPVE8gPSBzaGFyZWRLZXkoJ0lFX1BST1RPJyk7CnZhciAkT2JqZWN0ID0gT2JqZWN0Owp2YXIgT2JqZWN0UHJvdG90eXBlID0gJE9iamVjdC5wcm90b3R5cGU7CgovLyBgT2JqZWN0LmdldFByb3RvdHlwZU9mYCBtZXRob2QKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1vYmplY3QuZ2V0cHJvdG90eXBlb2YKLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1nZXRwcm90b3R5cGVvZiAtLSBzYWZlCm1vZHVsZS5leHBvcnRzID0gQ09SUkVDVF9QUk9UT1RZUEVfR0VUVEVSID8gJE9iamVjdC5nZXRQcm90b3R5cGVPZiA6IGZ1bmN0aW9uIChPKSB7CiAgdmFyIG9iamVjdCA9IHRvT2JqZWN0KE8pOwogIGlmIChoYXNPd24ob2JqZWN0LCBJRV9QUk9UTykpIHJldHVybiBvYmplY3RbSUVfUFJPVE9dOwogIHZhciBjb25zdHJ1Y3RvciA9IG9iamVjdC5jb25zdHJ1Y3RvcjsKICBpZiAoaXNDYWxsYWJsZShjb25zdHJ1Y3RvcikgJiYgb2JqZWN0IGluc3RhbmNlb2YgY29uc3RydWN0b3IpIHsKICAgIHJldHVybiBjb25zdHJ1Y3Rvci5wcm90b3R5cGU7CiAgfSByZXR1cm4gb2JqZWN0IGluc3RhbmNlb2YgJE9iamVjdCA/IE9iamVjdFByb3RvdHlwZSA6IG51bGw7Cn07CgoKLyoqKi8gfSksCgovKioqLyAyNzk2OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGZhaWxzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5MDM5KTsKdmFyIGlzQ2FsbGFibGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MDEpOwoKdmFyIHJlcGxhY2VtZW50ID0gLyN8XC5wcm90b3R5cGVcLi87Cgp2YXIgaXNGb3JjZWQgPSBmdW5jdGlvbiAoZmVhdHVyZSwgZGV0ZWN0aW9uKSB7CiAgdmFyIHZhbHVlID0gZGF0YVtub3JtYWxpemUoZmVhdHVyZSldOwogIHJldHVybiB2YWx1ZSA9PT0gUE9MWUZJTEwgPyB0cnVlCiAgICA6IHZhbHVlID09PSBOQVRJVkUgPyBmYWxzZQogICAgOiBpc0NhbGxhYmxlKGRldGVjdGlvbikgPyBmYWlscyhkZXRlY3Rpb24pCiAgICA6ICEhZGV0ZWN0aW9uOwp9OwoKdmFyIG5vcm1hbGl6ZSA9IGlzRm9yY2VkLm5vcm1hbGl6ZSA9IGZ1bmN0aW9uIChzdHJpbmcpIHsKICByZXR1cm4gU3RyaW5nKHN0cmluZykucmVwbGFjZShyZXBsYWNlbWVudCwgJy4nKS50b0xvd2VyQ2FzZSgpOwp9OwoKdmFyIGRhdGEgPSBpc0ZvcmNlZC5kYXRhID0ge307CnZhciBOQVRJVkUgPSBpc0ZvcmNlZC5OQVRJVkUgPSAnTic7CnZhciBQT0xZRklMTCA9IGlzRm9yY2VkLlBPTFlGSUxMID0gJ1AnOwoKbW9kdWxlLmV4cG9ydHMgPSBpc0ZvcmNlZDsKCgovKioqLyB9KSwKCi8qKiovIDI4MDQ6Ci8qKiovICgobW9kdWxlKSA9PiB7CgoKdmFyIGNvbW1vbkFscGhhYmV0ID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5JzsKdmFyIGJhc2U2NEFscGhhYmV0ID0gY29tbW9uQWxwaGFiZXQgKyAnKy8nOwp2YXIgYmFzZTY0VXJsQWxwaGFiZXQgPSBjb21tb25BbHBoYWJldCArICctXyc7Cgp2YXIgaW52ZXJzZSA9IGZ1bmN0aW9uIChjaGFyYWN0ZXJzKSB7CiAgLy8gVE9ETzogdXNlIGBPYmplY3QuY3JlYXRlKG51bGwpYCBpbiBgY29yZS1qc0A0YAogIHZhciByZXN1bHQgPSB7fTsKICB2YXIgaW5kZXggPSAwOwogIGZvciAoOyBpbmRleCA8IDY0OyBpbmRleCsrKSByZXN1bHRbY2hhcmFjdGVycy5jaGFyQXQoaW5kZXgpXSA9IGluZGV4OwogIHJldHVybiByZXN1bHQ7Cn07Cgptb2R1bGUuZXhwb3J0cyA9IHsKICBpMmM6IGJhc2U2NEFscGhhYmV0LAogIGMyaTogaW52ZXJzZShiYXNlNjRBbHBoYWJldCksCiAgaTJjVXJsOiBiYXNlNjRVcmxBbHBoYWJldCwKICBjMmlVcmw6IGludmVyc2UoYmFzZTY0VXJsQWxwaGFiZXQpCn07CgoKLyoqKi8gfSksCgovKioqLyAyODEyOgovKioqLyAoKG1vZHVsZSkgPT4gewoKCnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yOwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAocGFzc2VkLCByZXF1aXJlZCkgewogIGlmIChwYXNzZWQgPCByZXF1aXJlZCkgdGhyb3cgbmV3ICRUeXBlRXJyb3IoJ05vdCBlbm91Z2ggYXJndW1lbnRzJyk7CiAgcmV0dXJuIHBhc3NlZDsKfTsKCgovKioqLyB9KSwKCi8qKiovIDI4Mzk6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7Cgp2YXIgbmF2aWdhdG9yID0gZ2xvYmFsVGhpcy5uYXZpZ2F0b3I7CnZhciB1c2VyQWdlbnQgPSBuYXZpZ2F0b3IgJiYgbmF2aWdhdG9yLnVzZXJBZ2VudDsKCm1vZHVsZS5leHBvcnRzID0gdXNlckFnZW50ID8gU3RyaW5nKHVzZXJBZ2VudCkgOiAnJzsKCgovKioqLyB9KSwKCi8qKiovIDI5Njc6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgovKiBlc2xpbnQtZGlzYWJsZSBuby1wcm90byAtLSBzYWZlICovCnZhciB1bmN1cnJ5VGhpc0FjY2Vzc29yID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2NzA2KTsKdmFyIGlzT2JqZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNCk7CnZhciByZXF1aXJlT2JqZWN0Q29lcmNpYmxlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg3NzUwKTsKdmFyIGFQb3NzaWJsZVByb3RvdHlwZSA9IF9fd2VicGFja19yZXF1aXJlX18oMzUwNik7CgovLyBgT2JqZWN0LnNldFByb3RvdHlwZU9mYCBtZXRob2QKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1vYmplY3Quc2V0cHJvdG90eXBlb2YKLy8gV29ya3Mgd2l0aCBfX3Byb3RvX18gb25seS4gT2xkIHY4IGNhbid0IHdvcmsgd2l0aCBudWxsIHByb3RvIG9iamVjdHMuCi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3Qtc2V0cHJvdG90eXBlb2YgLS0gc2FmZQptb2R1bGUuZXhwb3J0cyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fCAoJ19fcHJvdG9fXycgaW4ge30gPyBmdW5jdGlvbiAoKSB7CiAgdmFyIENPUlJFQ1RfU0VUVEVSID0gZmFsc2U7CiAgdmFyIHRlc3QgPSB7fTsKICB2YXIgc2V0dGVyOwogIHRyeSB7CiAgICBzZXR0ZXIgPSB1bmN1cnJ5VGhpc0FjY2Vzc29yKE9iamVjdC5wcm90b3R5cGUsICdfX3Byb3RvX18nLCAnc2V0Jyk7CiAgICBzZXR0ZXIodGVzdCwgW10pOwogICAgQ09SUkVDVF9TRVRURVIgPSB0ZXN0IGluc3RhbmNlb2YgQXJyYXk7CiAgfSBjYXRjaCAoZXJyb3IpIHsgLyogZW1wdHkgKi8gfQogIHJldHVybiBmdW5jdGlvbiBzZXRQcm90b3R5cGVPZihPLCBwcm90bykgewogICAgcmVxdWlyZU9iamVjdENvZXJjaWJsZShPKTsKICAgIGFQb3NzaWJsZVByb3RvdHlwZShwcm90byk7CiAgICBpZiAoIWlzT2JqZWN0KE8pKSByZXR1cm4gTzsKICAgIGlmIChDT1JSRUNUX1NFVFRFUikgc2V0dGVyKE8sIHByb3RvKTsKICAgIGVsc2UgTy5fX3Byb3RvX18gPSBwcm90bzsKICAgIHJldHVybiBPOwogIH07Cn0oKSA6IHVuZGVmaW5lZCk7CgoKLyoqKi8gfSksCgovKioqLyAzMDY4OgovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgovLyBiYXNlZCBvbiBTaGV3Y2h1aydzIGFsZ29yaXRobSBmb3IgZXhhY3RseSBmbG9hdGluZyBwb2ludCBhZGRpdGlvbgovLyBhZGFwdGVkIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL3RjMzkvcHJvcG9zYWwtbWF0aC1zdW0vYmxvYi8zNTEzZDU4MzIzYTFhZTI1NTYwZTg3MDBhYTUyOTQ1MDBjNmM5Mjg3L3BvbHlmaWxsL3BvbHlmaWxsLm1qcwp2YXIgJCA9IF9fd2VicGFja19yZXF1aXJlX18oNjUxOCk7CnZhciB1bmN1cnJ5VGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oOTUwNCk7CnZhciBpdGVyYXRlID0gX193ZWJwYWNrX3JlcXVpcmVfXygyNjUyKTsKCnZhciAkUmFuZ2VFcnJvciA9IFJhbmdlRXJyb3I7CnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yOwp2YXIgJEluZmluaXR5ID0gSW5maW5pdHk7CnZhciAkTmFOID0gTmFOOwp2YXIgYWJzID0gTWF0aC5hYnM7CnZhciBwb3cgPSBNYXRoLnBvdzsKdmFyIHB1c2ggPSB1bmN1cnJ5VGhpcyhbXS5wdXNoKTsKCnZhciBQT1dfMl8xMDIzID0gcG93KDIsIDEwMjMpOwp2YXIgTUFYX1NBRkVfSU5URUdFUiA9IHBvdygyLCA1MykgLSAxOyAvLyAyICoqIDUzIC0gMSA9PT0gOTAwNzE5OTI1NDc0MDk5Mgp2YXIgTUFYX0RPVUJMRSA9IE51bWJlci5NQVhfVkFMVUU7IC8vIDIgKiogMTAyNCAtIDIgKiogKDEwMjMgLSA1MikgPT09IDEuNzk3NjkzMTM0ODYyMzE1NzA4MTVlKzMwOAp2YXIgTUFYX1VMUCA9IHBvdygyLCA5NzEpOyAvLyAyICoqICgxMDIzIC0gNTIpID09PSAxLjk5NTg0MDMwOTUzNDcxOTgxMTY2ZSsyOTIKCnZhciBOT1RfQV9OVU1CRVIgPSB7fTsKdmFyIE1JTlVTX0lORklOSVRZID0ge307CnZhciBQTFVTX0lORklOSVRZID0ge307CnZhciBNSU5VU19aRVJPID0ge307CnZhciBGSU5JVEUgPSB7fTsKCi8vIHByZXJlcXVpc2l0ZTogYWJzKHgpID49IGFicyh5KQp2YXIgdHdvc3VtID0gZnVuY3Rpb24gKHgsIHkpIHsKICB2YXIgaGkgPSB4ICsgeTsKICB2YXIgbG8gPSB5IC0gKGhpIC0geCk7CiAgcmV0dXJuIHsgaGk6IGhpLCBsbzogbG8gfTsKfTsKCi8vIGBNYXRoLnN1bVByZWNpc2VgIG1ldGhvZAovLyBodHRwczovL2dpdGh1Yi5jb20vdGMzOS9wcm9wb3NhbC1tYXRoLXN1bQokKHsgdGFyZ2V0OiAnTWF0aCcsIHN0YXQ6IHRydWUgfSwgewogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBtYXgtc3RhdGVtZW50cyAtLSBvawogIHN1bVByZWNpc2U6IGZ1bmN0aW9uIHN1bVByZWNpc2UoaXRlbXMpIHsKICAgIHZhciBudW1iZXJzID0gW107CiAgICB2YXIgY291bnQgPSAwOwogICAgdmFyIHN0YXRlID0gTUlOVVNfWkVSTzsKCiAgICBpdGVyYXRlKGl0ZW1zLCBmdW5jdGlvbiAobikgewogICAgICBpZiAoKytjb3VudCA+PSBNQVhfU0FGRV9JTlRFR0VSKSB0aHJvdyBuZXcgJFJhbmdlRXJyb3IoJ01heGltdW0gYWxsb3dlZCBpbmRleCBleGNlZWRlZCcpOwogICAgICBpZiAodHlwZW9mIG4gIT0gJ251bWJlcicpIHRocm93IG5ldyAkVHlwZUVycm9yKCdWYWx1ZSBpcyBub3QgYSBudW1iZXInKTsKICAgICAgaWYgKHN0YXRlICE9PSBOT1RfQV9OVU1CRVIpIHsKICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2VsZi1jb21wYXJlIC0tIE5hTiBjaGVjawogICAgICAgIGlmIChuICE9PSBuKSBzdGF0ZSA9IE5PVF9BX05VTUJFUjsKICAgICAgICBlbHNlIGlmIChuID09PSAkSW5maW5pdHkpIHN0YXRlID0gc3RhdGUgPT09IE1JTlVTX0lORklOSVRZID8gTk9UX0FfTlVNQkVSIDogUExVU19JTkZJTklUWTsKICAgICAgICBlbHNlIGlmIChuID09PSAtJEluZmluaXR5KSBzdGF0ZSA9IHN0YXRlID09PSBQTFVTX0lORklOSVRZID8gTk9UX0FfTlVNQkVSIDogTUlOVVNfSU5GSU5JVFk7CiAgICAgICAgZWxzZSBpZiAoKG4gIT09IDAgfHwgKDEgLyBuKSA9PT0gJEluZmluaXR5KSAmJiAoc3RhdGUgPT09IE1JTlVTX1pFUk8gfHwgc3RhdGUgPT09IEZJTklURSkpIHsKICAgICAgICAgIHN0YXRlID0gRklOSVRFOwogICAgICAgICAgcHVzaChudW1iZXJzLCBuKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0pOwoKICAgIHN3aXRjaCAoc3RhdGUpIHsKICAgICAgY2FzZSBOT1RfQV9OVU1CRVI6IHJldHVybiAkTmFOOwogICAgICBjYXNlIE1JTlVTX0lORklOSVRZOiByZXR1cm4gLSRJbmZpbml0eTsKICAgICAgY2FzZSBQTFVTX0lORklOSVRZOiByZXR1cm4gJEluZmluaXR5OwogICAgICBjYXNlIE1JTlVTX1pFUk86IHJldHVybiAtMDsKICAgIH0KCiAgICB2YXIgcGFydGlhbHMgPSBbXTsKICAgIHZhciBvdmVyZmxvdyA9IDA7IC8vIGNvbmNlcHR1YWxseSAyICoqIDEwMjQgdGltZXMgdGhpcyB2YWx1ZTsgdGhlIGZpbmFsIHBhcnRpYWwgaXMgYmlhc2VkIGJ5IHRoaXMgYW1vdW50CiAgICB2YXIgeCwgeSwgc3VtLCBoaSwgbG8sIHRtcDsKCiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG51bWJlcnMubGVuZ3RoOyBpKyspIHsKICAgICAgeCA9IG51bWJlcnNbaV07CiAgICAgIHZhciBhY3R1YWxseVVzZWRQYXJ0aWFscyA9IDA7CiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgcGFydGlhbHMubGVuZ3RoOyBqKyspIHsKICAgICAgICB5ID0gcGFydGlhbHNbal07CiAgICAgICAgaWYgKGFicyh4KSA8IGFicyh5KSkgewogICAgICAgICAgdG1wID0geDsKICAgICAgICAgIHggPSB5OwogICAgICAgICAgeSA9IHRtcDsKICAgICAgICB9CiAgICAgICAgc3VtID0gdHdvc3VtKHgsIHkpOwogICAgICAgIGhpID0gc3VtLmhpOwogICAgICAgIGxvID0gc3VtLmxvOwogICAgICAgIGlmIChhYnMoaGkpID09PSAkSW5maW5pdHkpIHsKICAgICAgICAgIHZhciBzaWduID0gaGkgPT09ICRJbmZpbml0eSA/IDEgOiAtMTsKICAgICAgICAgIG92ZXJmbG93ICs9IHNpZ247CgogICAgICAgICAgeCA9ICh4IC0gKHNpZ24gKiBQT1dfMl8xMDIzKSkgLSAoc2lnbiAqIFBPV18yXzEwMjMpOwogICAgICAgICAgaWYgKGFicyh4KSA8IGFicyh5KSkgewogICAgICAgICAgICB0bXAgPSB4OwogICAgICAgICAgICB4ID0geTsKICAgICAgICAgICAgeSA9IHRtcDsKICAgICAgICAgIH0KICAgICAgICAgIHN1bSA9IHR3b3N1bSh4LCB5KTsKICAgICAgICAgIGhpID0gc3VtLmhpOwogICAgICAgICAgbG8gPSBzdW0ubG87CiAgICAgICAgfQogICAgICAgIGlmIChsbyAhPT0gMCkgcGFydGlhbHNbYWN0dWFsbHlVc2VkUGFydGlhbHMrK10gPSBsbzsKICAgICAgICB4ID0gaGk7CiAgICAgIH0KICAgICAgcGFydGlhbHMubGVuZ3RoID0gYWN0dWFsbHlVc2VkUGFydGlhbHM7CiAgICAgIGlmICh4ICE9PSAwKSBwdXNoKHBhcnRpYWxzLCB4KTsKICAgIH0KCiAgICAvLyBjb21wdXRlIHRoZSBleGFjdCBzdW0gb2YgcGFydGlhbHMsIHN0b3BwaW5nIG9uY2Ugd2UgbG9zZSBwcmVjaXNpb24KICAgIHZhciBuID0gcGFydGlhbHMubGVuZ3RoIC0gMTsKICAgIGhpID0gMDsKICAgIGxvID0gMDsKCiAgICBpZiAob3ZlcmZsb3cgIT09IDApIHsKICAgICAgdmFyIG5leHQgPSBuID49IDAgPyBwYXJ0aWFsc1tuXSA6IDA7CiAgICAgIG4tLTsKICAgICAgaWYgKGFicyhvdmVyZmxvdykgPiAxIHx8IChvdmVyZmxvdyA+IDAgJiYgbmV4dCA+IDApIHx8IChvdmVyZmxvdyA8IDAgJiYgbmV4dCA8IDApKSB7CiAgICAgICAgcmV0dXJuIG92ZXJmbG93ID4gMCA/ICRJbmZpbml0eSA6IC0kSW5maW5pdHk7CiAgICAgIH0KICAgICAgLy8gaGVyZSB3ZSBhY3R1YWxseSBoYXZlIHRvIGRvIHRoZSBhcml0aG1ldGljCiAgICAgIC8vIGRyb3AgYSBmYWN0b3Igb2YgMiBzbyB3ZSBjYW4gZG8gaXQgd2l0aG91dCBvdmVyZmxvdwogICAgICAvLyBhc3NlcnQoYWJzKG92ZXJmbG93KSA9PT0gMSkKICAgICAgc3VtID0gdHdvc3VtKG92ZXJmbG93ICogUE9XXzJfMTAyMywgbmV4dCAvIDIpOwogICAgICBoaSA9IHN1bS5oaTsKICAgICAgbG8gPSBzdW0ubG87CiAgICAgIGxvICo9IDI7CiAgICAgIGlmIChhYnMoMiAqIGhpKSA9PT0gJEluZmluaXR5KSB7CiAgICAgICAgLy8gcm91bmRpbmcgdG8gdGhlIG1heGltdW0gdmFsdWUKICAgICAgICBpZiAoaGkgPiAwKSB7CiAgICAgICAgICByZXR1cm4gKGhpID09PSBQT1dfMl8xMDIzICYmIGxvID09PSAtKE1BWF9VTFAgLyAyKSAmJiBuID49IDAgJiYgcGFydGlhbHNbbl0gPCAwKSA/IE1BWF9ET1VCTEUgOiAkSW5maW5pdHk7CiAgICAgICAgfSByZXR1cm4gKGhpID09PSAtUE9XXzJfMTAyMyAmJiBsbyA9PT0gKE1BWF9VTFAgLyAyKSAmJiBuID49IDAgJiYgcGFydGlhbHNbbl0gPiAwKSA/IC1NQVhfRE9VQkxFIDogLSRJbmZpbml0eTsKICAgICAgfQoKICAgICAgaWYgKGxvICE9PSAwKSB7CiAgICAgICAgcGFydGlhbHNbKytuXSA9IGxvOwogICAgICAgIGxvID0gMDsKICAgICAgfQoKICAgICAgaGkgKj0gMjsKICAgIH0KCiAgICB3aGlsZSAobiA+PSAwKSB7CiAgICAgIHN1bSA9IHR3b3N1bShoaSwgcGFydGlhbHNbbi0tXSk7CiAgICAgIGhpID0gc3VtLmhpOwogICAgICBsbyA9IHN1bS5sbzsKICAgICAgaWYgKGxvICE9PSAwKSBicmVhazsKICAgIH0KCiAgICBpZiAobiA+PSAwICYmICgobG8gPCAwICYmIHBhcnRpYWxzW25dIDwgMCkgfHwgKGxvID4gMCAmJiBwYXJ0aWFsc1tuXSA+IDApKSkgewogICAgICB5ID0gbG8gKiAyOwogICAgICB4ID0gaGkgKyB5OwogICAgICBpZiAoeSA9PT0geCAtIGhpKSBoaSA9IHg7CiAgICB9CgogICAgcmV0dXJuIGhpOwogIH0KfSk7CgoKLyoqKi8gfSksCgovKioqLyAzMTY3OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGlzQ2FsbGFibGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MDEpOwp2YXIgaXNPYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM0KTsKdmFyIHNldFByb3RvdHlwZU9mID0gX193ZWJwYWNrX3JlcXVpcmVfXygyOTY3KTsKCi8vIG1ha2VzIHN1YmNsYXNzaW5nIHdvcmsgY29ycmVjdCBmb3Igd3JhcHBlZCBidWlsdC1pbnMKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoJHRoaXMsIGR1bW15LCBXcmFwcGVyKSB7CiAgdmFyIE5ld1RhcmdldCwgTmV3VGFyZ2V0UHJvdG90eXBlOwogIGlmICgKICAgIC8vIGl0IGNhbiB3b3JrIG9ubHkgd2l0aCBuYXRpdmUgYHNldFByb3RvdHlwZU9mYAogICAgc2V0UHJvdG90eXBlT2YgJiYKICAgIC8vIHdlIGhhdmVuJ3QgY29tcGxldGVseSBjb3JyZWN0IHByZS1FUzYgd2F5IGZvciBnZXR0aW5nIGBuZXcudGFyZ2V0YCwgc28gdXNlIHRoaXMKICAgIGlzQ2FsbGFibGUoTmV3VGFyZ2V0ID0gZHVtbXkuY29uc3RydWN0b3IpICYmCiAgICBOZXdUYXJnZXQgIT09IFdyYXBwZXIgJiYKICAgIGlzT2JqZWN0KE5ld1RhcmdldFByb3RvdHlwZSA9IE5ld1RhcmdldC5wcm90b3R5cGUpICYmCiAgICBOZXdUYXJnZXRQcm90b3R5cGUgIT09IFdyYXBwZXIucHJvdG90eXBlCiAgKSBzZXRQcm90b3R5cGVPZigkdGhpcywgTmV3VGFyZ2V0UHJvdG90eXBlKTsKICByZXR1cm4gJHRoaXM7Cn07CgoKLyoqKi8gfSksCgovKioqLyAzMjM4OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGdsb2JhbFRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ1NzYpOwp2YXIgTkFUSVZFX0FSUkFZX0JVRkZFUiA9IF9fd2VicGFja19yZXF1aXJlX18oNzgxMSk7CnZhciBhcnJheUJ1ZmZlckJ5dGVMZW5ndGggPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDczOTQpOwoKdmFyIERhdGFWaWV3ID0gZ2xvYmFsVGhpcy5EYXRhVmlldzsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKE8pIHsKICBpZiAoIU5BVElWRV9BUlJBWV9CVUZGRVIgfHwgYXJyYXlCdWZmZXJCeXRlTGVuZ3RoKE8pICE9PSAwKSByZXR1cm4gZmFsc2U7CiAgdHJ5IHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1uZXcgLS0gdGhyb3dlcgogICAgbmV3IERhdGFWaWV3KE8pOwogICAgcmV0dXJuIGZhbHNlOwogIH0gY2F0Y2ggKGVycm9yKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn07CgoKLyoqKi8gfSksCgovKioqLyAzMzkyOgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIHVuY3VycnlUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTA0KTsKCnZhciBpZCA9IDA7CnZhciBwb3N0Zml4ID0gTWF0aC5yYW5kb20oKTsKdmFyIHRvU3RyaW5nID0gdW5jdXJyeVRoaXMoMS4xLnRvU3RyaW5nKTsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSkgewogIHJldHVybiAnU3ltYm9sKCcgKyAoa2V5ID09PSB1bmRlZmluZWQgPyAnJyA6IGtleSkgKyAnKV8nICsgdG9TdHJpbmcoKytpZCArIHBvc3RmaXgsIDM2KTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDM0NDA6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgYVNldCA9IF9fd2VicGFja19yZXF1aXJlX18oNzA4MCk7CnZhciBTZXRIZWxwZXJzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0NDAyKTsKdmFyIGNsb25lID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5Mjg2KTsKdmFyIHNpemUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDUxNzApOwp2YXIgZ2V0U2V0UmVjb3JkID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNzg5KTsKdmFyIGl0ZXJhdGVTZXQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg0NjkpOwp2YXIgaXRlcmF0ZVNpbXBsZSA9IF9fd2VicGFja19yZXF1aXJlX18oNTA3KTsKCnZhciBoYXMgPSBTZXRIZWxwZXJzLmhhczsKdmFyIHJlbW92ZSA9IFNldEhlbHBlcnMucmVtb3ZlOwoKLy8gYFNldC5wcm90b3R5cGUuZGlmZmVyZW5jZWAgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc2V0LnByb3RvdHlwZS5kaWZmZXJlbmNlCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZGlmZmVyZW5jZShvdGhlcikgewogIHZhciBPID0gYVNldCh0aGlzKTsKICB2YXIgb3RoZXJSZWMgPSBnZXRTZXRSZWNvcmQob3RoZXIpOwogIHZhciByZXN1bHQgPSBjbG9uZShPKTsKICBpZiAoc2l6ZShPKSA8PSBvdGhlclJlYy5zaXplKSBpdGVyYXRlU2V0KE8sIGZ1bmN0aW9uIChlKSB7CiAgICBpZiAob3RoZXJSZWMuaW5jbHVkZXMoZSkpIHJlbW92ZShyZXN1bHQsIGUpOwogIH0pOwogIGVsc2UgaXRlcmF0ZVNpbXBsZShvdGhlclJlYy5nZXRJdGVyYXRvcigpLCBmdW5jdGlvbiAoZSkgewogICAgaWYgKGhhcyhyZXN1bHQsIGUpKSByZW1vdmUocmVzdWx0LCBlKTsKICB9KTsKICByZXR1cm4gcmVzdWx0Owp9OwoKCi8qKiovIH0pLAoKLyoqKi8gMzQ2MzoKLyoqKi8gKChtb2R1bGUpID0+IHsKCgp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiAgaWYgKHR5cGVvZiBhcmd1bWVudCA9PSAnc3RyaW5nJykgcmV0dXJuIGFyZ3VtZW50OwogIHRocm93IG5ldyAkVHlwZUVycm9yKCdBcmd1bWVudCBpcyBub3QgYSBzdHJpbmcnKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDM1MDY6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgaXNQb3NzaWJsZVByb3RvdHlwZSA9IF9fd2VicGFja19yZXF1aXJlX18oMzkyNSk7Cgp2YXIgJFN0cmluZyA9IFN0cmluZzsKdmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7Cgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcmd1bWVudCkgewogIGlmIChpc1Bvc3NpYmxlUHJvdG90eXBlKGFyZ3VtZW50KSkgcmV0dXJuIGFyZ3VtZW50OwogIHRocm93IG5ldyAkVHlwZUVycm9yKCJDYW4ndCBzZXQgIiArICRTdHJpbmcoYXJndW1lbnQpICsgJyBhcyBhIHByb3RvdHlwZScpOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gMzU3OToKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgY2FsbCA9IF9fd2VicGFja19yZXF1aXJlX18oOTU2NSk7CnZhciBpdGVyYXRlID0gX193ZWJwYWNrX3JlcXVpcmVfXygyNjUyKTsKdmFyIGFDYWxsYWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oOTMwNik7CnZhciBhbk9iamVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oODU1MSk7CnZhciBnZXRJdGVyYXRvckRpcmVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oMTc2Nyk7CnZhciBpdGVyYXRvckNsb3NlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTM5KTsKdmFyIGl0ZXJhdG9ySGVscGVyV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ1NDkpOwoKdmFyIHNvbWVXaXRob3V0Q2xvc2luZ09uRWFybHlFcnJvciA9IGl0ZXJhdG9ySGVscGVyV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IoJ3NvbWUnLCBUeXBlRXJyb3IpOwoKLy8gYEl0ZXJhdG9yLnByb3RvdHlwZS5zb21lYCBtZXRob2QKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1pdGVyYXRvci5wcm90b3R5cGUuc29tZQokKHsgdGFyZ2V0OiAnSXRlcmF0b3InLCBwcm90bzogdHJ1ZSwgcmVhbDogdHJ1ZSwgZm9yY2VkOiBzb21lV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IgfSwgewogIHNvbWU6IGZ1bmN0aW9uIHNvbWUocHJlZGljYXRlKSB7CiAgICBhbk9iamVjdCh0aGlzKTsKICAgIHRyeSB7CiAgICAgIGFDYWxsYWJsZShwcmVkaWNhdGUpOwogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgaXRlcmF0b3JDbG9zZSh0aGlzLCAndGhyb3cnLCBlcnJvcik7CiAgICB9CgogICAgaWYgKHNvbWVXaXRob3V0Q2xvc2luZ09uRWFybHlFcnJvcikgcmV0dXJuIGNhbGwoc29tZVdpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yLCB0aGlzLCBwcmVkaWNhdGUpOwoKICAgIHZhciByZWNvcmQgPSBnZXRJdGVyYXRvckRpcmVjdCh0aGlzKTsKICAgIHZhciBjb3VudGVyID0gMDsKICAgIHJldHVybiBpdGVyYXRlKHJlY29yZCwgZnVuY3Rpb24gKHZhbHVlLCBzdG9wKSB7CiAgICAgIGlmIChwcmVkaWNhdGUodmFsdWUsIGNvdW50ZXIrKykpIHJldHVybiBzdG9wKCk7CiAgICB9LCB7IElTX1JFQ09SRDogdHJ1ZSwgSU5URVJSVVBURUQ6IHRydWUgfSkuc3RvcHBlZDsKICB9Cn0pOwoKCi8qKiovIH0pLAoKLyoqKi8gMzYxMToKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciBkZWZpbmVCdWlsdEluQWNjZXNzb3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDIxMDYpOwp2YXIgREVTQ1JJUFRPUlMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM3MjQpOwoKdmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7Ci8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZGVmaW5lcHJvcGVydHkgLS0gc2FmZQp2YXIgZGVmaW5lUHJvcGVydHkgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7CnZhciBJTkNPUlJFQ1RfVkFMVUUgPSBnbG9iYWxUaGlzLnNlbGYgIT09IGdsb2JhbFRoaXM7CgovLyBgc2VsZmAgZ2V0dGVyCi8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3dpbmRvdy1vYmplY3QuaHRtbCNkb20tc2VsZgp0cnkgewogIGlmIChERVNDUklQVE9SUykgewogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1nZXRvd25wcm9wZXJ0eWRlc2NyaXB0b3IgLS0gc2FmZQogICAgdmFyIGRlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGdsb2JhbFRoaXMsICdzZWxmJyk7CiAgICAvLyBzb21lIGVuZ2luZXMgaGF2ZSBgc2VsZmAsIGJ1dCB3aXRoIGluY29ycmVjdCBkZXNjcmlwdG9yCiAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vZGVub2xhbmQvZGVuby9pc3N1ZXMvMTU3NjUKICAgIGlmIChJTkNPUlJFQ1RfVkFMVUUgfHwgIWRlc2NyaXB0b3IgfHwgIWRlc2NyaXB0b3IuZ2V0IHx8ICFkZXNjcmlwdG9yLmVudW1lcmFibGUpIHsKICAgICAgZGVmaW5lQnVpbHRJbkFjY2Vzc29yKGdsb2JhbFRoaXMsICdzZWxmJywgewogICAgICAgIGdldDogZnVuY3Rpb24gc2VsZigpIHsKICAgICAgICAgIHJldHVybiBnbG9iYWxUaGlzOwogICAgICAgIH0sCiAgICAgICAgc2V0OiBmdW5jdGlvbiBzZWxmKHZhbHVlKSB7CiAgICAgICAgICBpZiAodGhpcyAhPT0gZ2xvYmFsVGhpcykgdGhyb3cgbmV3ICRUeXBlRXJyb3IoJ0lsbGVnYWwgaW52b2NhdGlvbicpOwogICAgICAgICAgZGVmaW5lUHJvcGVydHkoZ2xvYmFsVGhpcywgJ3NlbGYnLCB7CiAgICAgICAgICAgIHZhbHVlOiB2YWx1ZSwKICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsCiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZQogICAgICAgICAgfSk7CiAgICAgICAgfSwKICAgICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZQogICAgICB9KTsKICAgIH0KICB9IGVsc2UgJCh7IGdsb2JhbDogdHJ1ZSwgc2ltcGxlOiB0cnVlLCBmb3JjZWQ6IElOQ09SUkVDVF9WQUxVRSB9LCB7CiAgICBzZWxmOiBnbG9iYWxUaGlzCiAgfSk7Cn0gY2F0Y2ggKGVycm9yKSB7IC8qIGVtcHR5ICovIH0KCgovKioqLyB9KSwKCi8qKiovIDM2NTA6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgYVNldCA9IF9fd2VicGFja19yZXF1aXJlX18oNzA4MCk7CnZhciBTZXRIZWxwZXJzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0NDAyKTsKdmFyIGNsb25lID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5Mjg2KTsKdmFyIGdldFNldFJlY29yZCA9IF9fd2VicGFja19yZXF1aXJlX18oMzc4OSk7CnZhciBpdGVyYXRlU2ltcGxlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg1MDcpOwoKdmFyIGFkZCA9IFNldEhlbHBlcnMuYWRkOwp2YXIgaGFzID0gU2V0SGVscGVycy5oYXM7CnZhciByZW1vdmUgPSBTZXRIZWxwZXJzLnJlbW92ZTsKCi8vIGBTZXQucHJvdG90eXBlLnN5bW1ldHJpY0RpZmZlcmVuY2VgIG1ldGhvZAovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXNldC5wcm90b3R5cGUuc3ltbWV0cmljZGlmZmVyZW5jZQptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHN5bW1ldHJpY0RpZmZlcmVuY2Uob3RoZXIpIHsKICB2YXIgTyA9IGFTZXQodGhpcyk7CiAgdmFyIGtleXNJdGVyID0gZ2V0U2V0UmVjb3JkKG90aGVyKS5nZXRJdGVyYXRvcigpOwogIHZhciByZXN1bHQgPSBjbG9uZShPKTsKICBpdGVyYXRlU2ltcGxlKGtleXNJdGVyLCBmdW5jdGlvbiAoZSkgewogICAgaWYgKGhhcyhPLCBlKSkgcmVtb3ZlKHJlc3VsdCwgZSk7CiAgICBlbHNlIGFkZChyZXN1bHQsIGUpOwogIH0pOwogIHJldHVybiByZXN1bHQ7Cn07CgoKLyoqKi8gfSksCgovKioqLyAzNzA2OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIHVuY3VycnlUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTA0KTsKdmFyIGlzQ2FsbGFibGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MDEpOwp2YXIgc3RvcmUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDc2MjkpOwoKdmFyIGZ1bmN0aW9uVG9TdHJpbmcgPSB1bmN1cnJ5VGhpcyhGdW5jdGlvbi50b1N0cmluZyk7CgovLyB0aGlzIGhlbHBlciBicm9rZW4gaW4gYGNvcmUtanNAMy40LjEtMy40LjRgLCBzbyB3ZSBjYW4ndCB1c2UgYHNoYXJlZGAgaGVscGVyCmlmICghaXNDYWxsYWJsZShzdG9yZS5pbnNwZWN0U291cmNlKSkgewogIHN0b3JlLmluc3BlY3RTb3VyY2UgPSBmdW5jdGlvbiAoaXQpIHsKICAgIHJldHVybiBmdW5jdGlvblRvU3RyaW5nKGl0KTsKICB9Owp9Cgptb2R1bGUuZXhwb3J0cyA9IHN0b3JlLmluc3BlY3RTb3VyY2U7CgoKLyoqKi8gfSksCgovKioqLyAzNzE3OgovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBleHBvcnRzKSA9PiB7CgoKLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1nZXRvd25wcm9wZXJ0eXN5bWJvbHMgLS0gc2FmZQpleHBvcnRzLmYgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzOwoKCi8qKiovIH0pLAoKLyoqKi8gMzcyNDoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBmYWlscyA9IF9fd2VicGFja19yZXF1aXJlX18oOTAzOSk7CgovLyBEZXRlY3QgSUU4J3MgaW5jb21wbGV0ZSBkZWZpbmVQcm9wZXJ0eSBpbXBsZW1lbnRhdGlvbgptb2R1bGUuZXhwb3J0cyA9ICFmYWlscyhmdW5jdGlvbiAoKSB7CiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1kZWZpbmVwcm9wZXJ0eSAtLSByZXF1aXJlZCBmb3IgdGVzdGluZwogIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sIDEsIHsgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiA3OyB9IH0pWzFdICE9PSA3Owp9KTsKCgovKioqLyB9KSwKCi8qKiovIDM3ODk6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgYUNhbGxhYmxlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5MzA2KTsKdmFyIGFuT2JqZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4NTUxKTsKdmFyIGNhbGwgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1NjUpOwp2YXIgdG9JbnRlZ2VyT3JJbmZpbml0eSA9IF9fd2VicGFja19yZXF1aXJlX18oMTI5MSk7CnZhciBnZXRJdGVyYXRvckRpcmVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oMTc2Nyk7Cgp2YXIgSU5WQUxJRF9TSVpFID0gJ0ludmFsaWQgc2l6ZSc7CnZhciAkUmFuZ2VFcnJvciA9IFJhbmdlRXJyb3I7CnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yOwp2YXIgbWF4ID0gTWF0aC5tYXg7Cgp2YXIgU2V0UmVjb3JkID0gZnVuY3Rpb24gKHNldCwgaW50U2l6ZSkgewogIHRoaXMuc2V0ID0gc2V0OwogIHRoaXMuc2l6ZSA9IG1heChpbnRTaXplLCAwKTsKICB0aGlzLmhhcyA9IGFDYWxsYWJsZShzZXQuaGFzKTsKICB0aGlzLmtleXMgPSBhQ2FsbGFibGUoc2V0LmtleXMpOwp9OwoKU2V0UmVjb3JkLnByb3RvdHlwZSA9IHsKICBnZXRJdGVyYXRvcjogZnVuY3Rpb24gKCkgewogICAgcmV0dXJuIGdldEl0ZXJhdG9yRGlyZWN0KGFuT2JqZWN0KGNhbGwodGhpcy5rZXlzLCB0aGlzLnNldCkpKTsKICB9LAogIGluY2x1ZGVzOiBmdW5jdGlvbiAoaXQpIHsKICAgIHJldHVybiBjYWxsKHRoaXMuaGFzLCB0aGlzLnNldCwgaXQpOwogIH0KfTsKCi8vIGBHZXRTZXRSZWNvcmRgIGFic3RyYWN0IG9wZXJhdGlvbgovLyBodHRwczovL3RjMzkuZXMvcHJvcG9zYWwtc2V0LW1ldGhvZHMvI3NlYy1nZXRzZXRyZWNvcmQKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqKSB7CiAgYW5PYmplY3Qob2JqKTsKICB2YXIgbnVtU2l6ZSA9ICtvYmouc2l6ZTsKICAvLyBOT1RFOiBJZiBzaXplIGlzIHVuZGVmaW5lZCwgdGhlbiBudW1TaXplIHdpbGwgYmUgTmFOCiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXNlbGYtY29tcGFyZSAtLSBOYU4gY2hlY2sKICBpZiAobnVtU2l6ZSAhPT0gbnVtU2l6ZSkgdGhyb3cgbmV3ICRUeXBlRXJyb3IoSU5WQUxJRF9TSVpFKTsKICB2YXIgaW50U2l6ZSA9IHRvSW50ZWdlck9ySW5maW5pdHkobnVtU2l6ZSk7CiAgaWYgKGludFNpemUgPCAwKSB0aHJvdyBuZXcgJFJhbmdlRXJyb3IoSU5WQUxJRF9TSVpFKTsKICByZXR1cm4gbmV3IFNldFJlY29yZChvYmosIGludFNpemUpOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gMzgzODoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBhU2V0ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg3MDgwKTsKdmFyIHNpemUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDUxNzApOwp2YXIgaXRlcmF0ZSA9IF9fd2VicGFja19yZXF1aXJlX18oODQ2OSk7CnZhciBnZXRTZXRSZWNvcmQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM3ODkpOwoKLy8gYFNldC5wcm90b3R5cGUuaXNTdWJzZXRPZmAgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc2V0LnByb3RvdHlwZS5pc3N1YnNldG9mCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNTdWJzZXRPZihvdGhlcikgewogIHZhciBPID0gYVNldCh0aGlzKTsKICB2YXIgb3RoZXJSZWMgPSBnZXRTZXRSZWNvcmQob3RoZXIpOwogIGlmIChzaXplKE8pID4gb3RoZXJSZWMuc2l6ZSkgcmV0dXJuIGZhbHNlOwogIHJldHVybiBpdGVyYXRlKE8sIGZ1bmN0aW9uIChlKSB7CiAgICBpZiAoIW90aGVyUmVjLmluY2x1ZGVzKGUpKSByZXR1cm4gZmFsc2U7CiAgfSwgdHJ1ZSkgIT09IGZhbHNlOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gMzg1MzoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgaXNEaXNqb2ludEZyb20gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ0NDkpOwp2YXIgc2V0TWV0aG9kQWNjZXB0U2V0TGlrZSA9IF9fd2VicGFja19yZXF1aXJlX18oNDkxNik7Cgp2YXIgSU5DT1JSRUNUID0gIXNldE1ldGhvZEFjY2VwdFNldExpa2UoJ2lzRGlzam9pbnRGcm9tJywgZnVuY3Rpb24gKHJlc3VsdCkgewogIHJldHVybiAhcmVzdWx0Owp9KTsKCi8vIGBTZXQucHJvdG90eXBlLmlzRGlzam9pbnRGcm9tYCBtZXRob2QKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1zZXQucHJvdG90eXBlLmlzZGlzam9pbnRmcm9tCiQoeyB0YXJnZXQ6ICdTZXQnLCBwcm90bzogdHJ1ZSwgcmVhbDogdHJ1ZSwgZm9yY2VkOiBJTkNPUlJFQ1QgfSwgewogIGlzRGlzam9pbnRGcm9tOiBpc0Rpc2pvaW50RnJvbQp9KTsKCgovKioqLyB9KSwKCi8qKiovIDM5MjU6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgaXNPYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM0KTsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiAgcmV0dXJuIGlzT2JqZWN0KGFyZ3VtZW50KSB8fCBhcmd1bWVudCA9PT0gbnVsbDsKfTsKCgovKioqLyB9KSwKCi8qKiovIDM5NzI6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgaXNPYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM0KTsKCnZhciAkU3RyaW5nID0gU3RyaW5nOwp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiAgaWYgKGFyZ3VtZW50ID09PSB1bmRlZmluZWQgfHwgaXNPYmplY3QoYXJndW1lbnQpKSByZXR1cm4gYXJndW1lbnQ7CiAgdGhyb3cgbmV3ICRUeXBlRXJyb3IoJFN0cmluZyhhcmd1bWVudCkgKyAnIGlzIG5vdCBhbiBvYmplY3Qgb3IgdW5kZWZpbmVkJyk7Cn07CgoKLyoqKi8gfSksCgovKioqLyA0MDU1OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGdsb2JhbFRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ1NzYpOwp2YXIgaXNPYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM0KTsKCnZhciBkb2N1bWVudCA9IGdsb2JhbFRoaXMuZG9jdW1lbnQ7Ci8vIHR5cGVvZiBkb2N1bWVudC5jcmVhdGVFbGVtZW50IGlzICdvYmplY3QnIGluIG9sZCBJRQp2YXIgRVhJU1RTID0gaXNPYmplY3QoZG9jdW1lbnQpICYmIGlzT2JqZWN0KGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQpOwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHsKICByZXR1cm4gRVhJU1RTID8gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChpdCkgOiB7fTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDQxMTQ6Ci8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciAkID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2NTE4KTsKdmFyIHRvT2JqZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4OTgxKTsKdmFyIGxlbmd0aE9mQXJyYXlMaWtlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2MTk4KTsKdmFyIHNldEFycmF5TGVuZ3RoID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0NTI3KTsKdmFyIGRvZXNOb3RFeGNlZWRTYWZlSW50ZWdlciA9IF9fd2VicGFja19yZXF1aXJlX18oNjgzNyk7CnZhciBmYWlscyA9IF9fd2VicGFja19yZXF1aXJlX18oOTAzOSk7Cgp2YXIgSU5DT1JSRUNUX1RPX0xFTkdUSCA9IGZhaWxzKGZ1bmN0aW9uICgpIHsKICByZXR1cm4gW10ucHVzaC5jYWxsKHsgbGVuZ3RoOiAweDEwMDAwMDAwMCB9LCAxKSAhPT0gNDI5NDk2NzI5NzsKfSk7CgovLyBWOCA8PSAxMjEgYW5kIFNhZmFyaSA8PSAxNS40OyBGRiA8IDIzIHRocm93cyBJbnRlcm5hbEVycm9yCi8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTEyNjgxCnZhciBwcm9wZXJFcnJvck9uTm9uV3JpdGFibGVMZW5ndGggPSBmdW5jdGlvbiAoKSB7CiAgdHJ5IHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZGVmaW5lcHJvcGVydHkgLS0gc2FmZQogICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFtdLCAnbGVuZ3RoJywgeyB3cml0YWJsZTogZmFsc2UgfSkucHVzaCgpOwogIH0gY2F0Y2ggKGVycm9yKSB7CiAgICByZXR1cm4gZXJyb3IgaW5zdGFuY2VvZiBUeXBlRXJyb3I7CiAgfQp9OwoKdmFyIEZPUkNFRCA9IElOQ09SUkVDVF9UT19MRU5HVEggfHwgIXByb3BlckVycm9yT25Ob25Xcml0YWJsZUxlbmd0aCgpOwoKLy8gYEFycmF5LnByb3RvdHlwZS5wdXNoYCBtZXRob2QKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUucHVzaAokKHsgdGFyZ2V0OiAnQXJyYXknLCBwcm90bzogdHJ1ZSwgYXJpdHk6IDEsIGZvcmNlZDogRk9SQ0VEIH0sIHsKICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tdW51c2VkLXZhcnMgLS0gcmVxdWlyZWQgZm9yIGAubGVuZ3RoYAogIHB1c2g6IGZ1bmN0aW9uIHB1c2goaXRlbSkgewogICAgdmFyIE8gPSB0b09iamVjdCh0aGlzKTsKICAgIHZhciBsZW4gPSBsZW5ndGhPZkFycmF5TGlrZShPKTsKICAgIHZhciBhcmdDb3VudCA9IGFyZ3VtZW50cy5sZW5ndGg7CiAgICBkb2VzTm90RXhjZWVkU2FmZUludGVnZXIobGVuICsgYXJnQ291bnQpOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmdDb3VudDsgaSsrKSB7CiAgICAgIE9bbGVuXSA9IGFyZ3VtZW50c1tpXTsKICAgICAgbGVuKys7CiAgICB9CiAgICBzZXRBcnJheUxlbmd0aChPLCBsZW4pOwogICAgcmV0dXJuIGxlbjsKICB9Cn0pOwoKCi8qKiovIH0pLAoKLyoqKi8gNDExNzoKLyoqKi8gKChtb2R1bGUpID0+IHsKCgovLyB3ZSBjYW4ndCB1c2UganVzdCBgaXQgPT0gbnVsbGAgc2luY2Ugb2YgYGRvY3VtZW50LmFsbGAgc3BlY2lhbCBjYXNlCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtSXNIVE1MRERBLWludGVybmFsLXNsb3QtYWVjCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7CiAgcmV0dXJuIGl0ID09PSBudWxsIHx8IGl0ID09PSB1bmRlZmluZWQ7Cn07CgoKLyoqKi8gfSksCgovKioqLyA0MTU0OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGNsYXNzb2YgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY5NTUpOwoKdmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7CgovLyBQZXJmb3JtID8gUmVxdWlyZUludGVybmFsU2xvdChhcmd1bWVudCwgW1tUeXBlZEFycmF5TmFtZV1dKQovLyBJZiBhcmd1bWVudC5bW1R5cGVkQXJyYXlOYW1lXV0gaXMgbm90ICJVaW50OEFycmF5IiwgdGhyb3cgYSBUeXBlRXJyb3IgZXhjZXB0aW9uCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiAgaWYgKGNsYXNzb2YoYXJndW1lbnQpID09PSAnVWludDhBcnJheScpIHJldHVybiBhcmd1bWVudDsKICB0aHJvdyBuZXcgJFR5cGVFcnJvcignQXJndW1lbnQgaXMgbm90IGFuIFVpbnQ4QXJyYXknKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDQyMDQ6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgYVNldCA9IF9fd2VicGFja19yZXF1aXJlX18oNzA4MCk7CnZhciBhZGQgPSAoX193ZWJwYWNrX3JlcXVpcmVfXyg0NDAyKS5hZGQpOwp2YXIgY2xvbmUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDkyODYpOwp2YXIgZ2V0U2V0UmVjb3JkID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNzg5KTsKdmFyIGl0ZXJhdGVTaW1wbGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDUwNyk7CgovLyBgU2V0LnByb3RvdHlwZS51bmlvbmAgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc2V0LnByb3RvdHlwZS51bmlvbgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHVuaW9uKG90aGVyKSB7CiAgdmFyIE8gPSBhU2V0KHRoaXMpOwogIHZhciBrZXlzSXRlciA9IGdldFNldFJlY29yZChvdGhlcikuZ2V0SXRlcmF0b3IoKTsKICB2YXIgcmVzdWx0ID0gY2xvbmUoTyk7CiAgaXRlcmF0ZVNpbXBsZShrZXlzSXRlciwgZnVuY3Rpb24gKGl0KSB7CiAgICBhZGQocmVzdWx0LCBpdCk7CiAgfSk7CiAgcmV0dXJuIHJlc3VsdDsKfTsKCgovKioqLyB9KSwKCi8qKiovIDQyMDk6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgd2VsbEtub3duU3ltYm9sID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4MjI3KTsKdmFyIEl0ZXJhdG9ycyA9IF9fd2VicGFja19yZXF1aXJlX18oNjI2OSk7Cgp2YXIgSVRFUkFUT1IgPSB3ZWxsS25vd25TeW1ib2woJ2l0ZXJhdG9yJyk7CnZhciBBcnJheVByb3RvdHlwZSA9IEFycmF5LnByb3RvdHlwZTsKCi8vIGNoZWNrIG9uIGRlZmF1bHQgQXJyYXkgaXRlcmF0b3IKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHsKICByZXR1cm4gaXQgIT09IHVuZGVmaW5lZCAmJiAoSXRlcmF0b3JzLkFycmF5ID09PSBpdCB8fCBBcnJheVByb3RvdHlwZVtJVEVSQVRPUl0gPT09IGl0KTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDQyMTU6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgovKiBnbG9iYWwgQnVuLCBEZW5vIC0tIGRldGVjdGlvbiAqLwp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciB1c2VyQWdlbnQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDI4MzkpOwp2YXIgY2xhc3NvZiA9IF9fd2VicGFja19yZXF1aXJlX18oMjE5NSk7Cgp2YXIgdXNlckFnZW50U3RhcnRzV2l0aCA9IGZ1bmN0aW9uIChzdHJpbmcpIHsKICByZXR1cm4gdXNlckFnZW50LnNsaWNlKDAsIHN0cmluZy5sZW5ndGgpID09PSBzdHJpbmc7Cn07Cgptb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiAoKSB7CiAgaWYgKHVzZXJBZ2VudFN0YXJ0c1dpdGgoJ0J1bi8nKSkgcmV0dXJuICdCVU4nOwogIGlmICh1c2VyQWdlbnRTdGFydHNXaXRoKCdDbG91ZGZsYXJlLVdvcmtlcnMnKSkgcmV0dXJuICdDTE9VREZMQVJFJzsKICBpZiAodXNlckFnZW50U3RhcnRzV2l0aCgnRGVuby8nKSkgcmV0dXJuICdERU5PJzsKICBpZiAodXNlckFnZW50U3RhcnRzV2l0aCgnTm9kZS5qcy8nKSkgcmV0dXJuICdOT0RFJzsKICBpZiAoZ2xvYmFsVGhpcy5CdW4gJiYgdHlwZW9mIEJ1bi52ZXJzaW9uID09ICdzdHJpbmcnKSByZXR1cm4gJ0JVTic7CiAgaWYgKGdsb2JhbFRoaXMuRGVubyAmJiB0eXBlb2YgRGVuby52ZXJzaW9uID09ICdvYmplY3QnKSByZXR1cm4gJ0RFTk8nOwogIGlmIChjbGFzc29mKGdsb2JhbFRoaXMucHJvY2VzcykgPT09ICdwcm9jZXNzJykgcmV0dXJuICdOT0RFJzsKICBpZiAoZ2xvYmFsVGhpcy53aW5kb3cgJiYgZ2xvYmFsVGhpcy5kb2N1bWVudCkgcmV0dXJuICdCUk9XU0VSJzsKICByZXR1cm4gJ1JFU1QnOwp9KSgpOwoKCi8qKiovIH0pLAoKLyoqKi8gNDIyNjoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciBhU3RyaW5nID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNDYzKTsKdmFyIGFuVWludDhBcnJheSA9IF9fd2VicGFja19yZXF1aXJlX18oNDE1NCk7CnZhciBub3REZXRhY2hlZCA9IF9fd2VicGFja19yZXF1aXJlX18oNTE2OSk7CnZhciAkZnJvbUhleCA9IF9fd2VicGFja19yZXF1aXJlX18oMjMwMyk7CgovLyBgVWludDhBcnJheS5wcm90b3R5cGUuc2V0RnJvbUhleGAgbWV0aG9kCi8vIGh0dHBzOi8vZ2l0aHViLmNvbS90YzM5L3Byb3Bvc2FsLWFycmF5YnVmZmVyLWJhc2U2NAppZiAoZ2xvYmFsVGhpcy5VaW50OEFycmF5KSAkKHsgdGFyZ2V0OiAnVWludDhBcnJheScsIHByb3RvOiB0cnVlIH0sIHsKICBzZXRGcm9tSGV4OiBmdW5jdGlvbiBzZXRGcm9tSGV4KHN0cmluZykgewogICAgYW5VaW50OEFycmF5KHRoaXMpOwogICAgYVN0cmluZyhzdHJpbmcpOwogICAgbm90RGV0YWNoZWQodGhpcy5idWZmZXIpOwogICAgdmFyIHJlYWQgPSAkZnJvbUhleChzdHJpbmcsIHRoaXMpLnJlYWQ7CiAgICByZXR1cm4geyByZWFkOiByZWFkLCB3cml0dGVuOiByZWFkIC8gMiB9OwogIH0KfSk7CgoKLyoqKi8gfSksCgovKioqLyA0MjM1OgovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgovLyBUT0RPOiBSZW1vdmUgZnJvbSBgY29yZS1qc0A0YApfX3dlYnBhY2tfcmVxdWlyZV9fKDMwNjgpOwoKCi8qKiovIH0pLAoKLyoqKi8gNDI3MDoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBjYWxsID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTY1KTsKdmFyIGlzQ2FsbGFibGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MDEpOwp2YXIgaXNPYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM0KTsKCnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yOwoKLy8gYE9yZGluYXJ5VG9QcmltaXRpdmVgIGFic3RyYWN0IG9wZXJhdGlvbgovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9yZGluYXJ5dG9wcmltaXRpdmUKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaW5wdXQsIHByZWYpIHsKICB2YXIgZm4sIHZhbDsKICBpZiAocHJlZiA9PT0gJ3N0cmluZycgJiYgaXNDYWxsYWJsZShmbiA9IGlucHV0LnRvU3RyaW5nKSAmJiAhaXNPYmplY3QodmFsID0gY2FsbChmbiwgaW5wdXQpKSkgcmV0dXJuIHZhbDsKICBpZiAoaXNDYWxsYWJsZShmbiA9IGlucHV0LnZhbHVlT2YpICYmICFpc09iamVjdCh2YWwgPSBjYWxsKGZuLCBpbnB1dCkpKSByZXR1cm4gdmFsOwogIGlmIChwcmVmICE9PSAnc3RyaW5nJyAmJiBpc0NhbGxhYmxlKGZuID0gaW5wdXQudG9TdHJpbmcpICYmICFpc09iamVjdCh2YWwgPSBjYWxsKGZuLCBpbnB1dCkpKSByZXR1cm4gdmFsOwogIHRocm93IG5ldyAkVHlwZUVycm9yKCJDYW4ndCBjb252ZXJ0IG9iamVjdCB0byBwcmltaXRpdmUgdmFsdWUiKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDQzNzY6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgY2xhc3NvZiA9IF9fd2VicGFja19yZXF1aXJlX18oMjE5NSk7CgovLyBgSXNBcnJheWAgYWJzdHJhY3Qgb3BlcmF0aW9uCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtaXNhcnJheQovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tYXJyYXktaXNhcnJheSAtLSBzYWZlCm1vZHVsZS5leHBvcnRzID0gQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbiBpc0FycmF5KGFyZ3VtZW50KSB7CiAgcmV0dXJuIGNsYXNzb2YoYXJndW1lbnQpID09PSAnQXJyYXknOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNDQwMjoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciB1bmN1cnJ5VGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oOTUwNCk7CgovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tc2V0IC0tIHNhZmUKdmFyIFNldFByb3RvdHlwZSA9IFNldC5wcm90b3R5cGU7Cgptb2R1bGUuZXhwb3J0cyA9IHsKICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tc2V0IC0tIHNhZmUKICBTZXQ6IFNldCwKICBhZGQ6IHVuY3VycnlUaGlzKFNldFByb3RvdHlwZS5hZGQpLAogIGhhczogdW5jdXJyeVRoaXMoU2V0UHJvdG90eXBlLmhhcyksCiAgcmVtb3ZlOiB1bmN1cnJ5VGhpcyhTZXRQcm90b3R5cGVbJ2RlbGV0ZSddKSwKICBwcm90bzogU2V0UHJvdG90eXBlCn07CgoKLyoqKi8gfSksCgovKioqLyA0NDQ5OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGFTZXQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDcwODApOwp2YXIgaGFzID0gKF9fd2VicGFja19yZXF1aXJlX18oNDQwMikuaGFzKTsKdmFyIHNpemUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDUxNzApOwp2YXIgZ2V0U2V0UmVjb3JkID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNzg5KTsKdmFyIGl0ZXJhdGVTZXQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg0NjkpOwp2YXIgaXRlcmF0ZVNpbXBsZSA9IF9fd2VicGFja19yZXF1aXJlX18oNTA3KTsKdmFyIGl0ZXJhdG9yQ2xvc2UgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1MzkpOwoKLy8gYFNldC5wcm90b3R5cGUuaXNEaXNqb2ludEZyb21gIG1ldGhvZAovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXNldC5wcm90b3R5cGUuaXNkaXNqb2ludGZyb20KbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc0Rpc2pvaW50RnJvbShvdGhlcikgewogIHZhciBPID0gYVNldCh0aGlzKTsKICB2YXIgb3RoZXJSZWMgPSBnZXRTZXRSZWNvcmQob3RoZXIpOwogIGlmIChzaXplKE8pIDw9IG90aGVyUmVjLnNpemUpIHJldHVybiBpdGVyYXRlU2V0KE8sIGZ1bmN0aW9uIChlKSB7CiAgICBpZiAob3RoZXJSZWMuaW5jbHVkZXMoZSkpIHJldHVybiBmYWxzZTsKICB9LCB0cnVlKSAhPT0gZmFsc2U7CiAgdmFyIGl0ZXJhdG9yID0gb3RoZXJSZWMuZ2V0SXRlcmF0b3IoKTsKICByZXR1cm4gaXRlcmF0ZVNpbXBsZShpdGVyYXRvciwgZnVuY3Rpb24gKGUpIHsKICAgIGlmIChoYXMoTywgZSkpIHJldHVybiBpdGVyYXRvckNsb3NlKGl0ZXJhdG9yLCAnbm9ybWFsJywgZmFsc2UpOwogIH0pICE9PSBmYWxzZTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDQ0ODM6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciBnZXRCdWlsdEluTm9kZU1vZHVsZSA9IF9fd2VicGFja19yZXF1aXJlX18oOTQyOSk7CnZhciBQUk9QRVJfU1RSVUNUVVJFRF9DTE9ORV9UUkFOU0ZFUiA9IF9fd2VicGFja19yZXF1aXJlX18oMTU0OCk7Cgp2YXIgc3RydWN0dXJlZENsb25lID0gZ2xvYmFsVGhpcy5zdHJ1Y3R1cmVkQ2xvbmU7CnZhciAkQXJyYXlCdWZmZXIgPSBnbG9iYWxUaGlzLkFycmF5QnVmZmVyOwp2YXIgJE1lc3NhZ2VDaGFubmVsID0gZ2xvYmFsVGhpcy5NZXNzYWdlQ2hhbm5lbDsKdmFyIGRldGFjaCA9IGZhbHNlOwp2YXIgV29ya2VyVGhyZWFkcywgY2hhbm5lbCwgYnVmZmVyLCAkZGV0YWNoOwoKaWYgKFBST1BFUl9TVFJVQ1RVUkVEX0NMT05FX1RSQU5TRkVSKSB7CiAgZGV0YWNoID0gZnVuY3Rpb24gKHRyYW5zZmVyYWJsZSkgewogICAgc3RydWN0dXJlZENsb25lKHRyYW5zZmVyYWJsZSwgeyB0cmFuc2ZlcjogW3RyYW5zZmVyYWJsZV0gfSk7CiAgfTsKfSBlbHNlIGlmICgkQXJyYXlCdWZmZXIpIHRyeSB7CiAgaWYgKCEkTWVzc2FnZUNoYW5uZWwpIHsKICAgIFdvcmtlclRocmVhZHMgPSBnZXRCdWlsdEluTm9kZU1vZHVsZSgnd29ya2VyX3RocmVhZHMnKTsKICAgIGlmIChXb3JrZXJUaHJlYWRzKSAkTWVzc2FnZUNoYW5uZWwgPSBXb3JrZXJUaHJlYWRzLk1lc3NhZ2VDaGFubmVsOwogIH0KCiAgaWYgKCRNZXNzYWdlQ2hhbm5lbCkgewogICAgY2hhbm5lbCA9IG5ldyAkTWVzc2FnZUNoYW5uZWwoKTsKICAgIGJ1ZmZlciA9IG5ldyAkQXJyYXlCdWZmZXIoMik7CgogICAgJGRldGFjaCA9IGZ1bmN0aW9uICh0cmFuc2ZlcmFibGUpIHsKICAgICAgY2hhbm5lbC5wb3J0MS5wb3N0TWVzc2FnZShudWxsLCBbdHJhbnNmZXJhYmxlXSk7CiAgICB9OwoKICAgIGlmIChidWZmZXIuYnl0ZUxlbmd0aCA9PT0gMikgewogICAgICAkZGV0YWNoKGJ1ZmZlcik7CiAgICAgIGlmIChidWZmZXIuYnl0ZUxlbmd0aCA9PT0gMCkgZGV0YWNoID0gJGRldGFjaDsKICAgIH0KICB9Cn0gY2F0Y2ggKGVycm9yKSB7IC8qIGVtcHR5ICovIH0KCm1vZHVsZS5leHBvcnRzID0gZGV0YWNoOwoKCi8qKiovIH0pLAoKLyoqKi8gNDQ5NToKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCi8qIGVzbGludC1kaXNhYmxlIGVzL25vLXN5bWJvbCAtLSByZXF1aXJlZCBmb3IgdGVzdGluZyAqLwp2YXIgVjhfVkVSU0lPTiA9IF9fd2VicGFja19yZXF1aXJlX18oOTUxOSk7CnZhciBmYWlscyA9IF9fd2VicGFja19yZXF1aXJlX18oOTAzOSk7CnZhciBnbG9iYWxUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0NTc2KTsKCnZhciAkU3RyaW5nID0gZ2xvYmFsVGhpcy5TdHJpbmc7CgovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tb2JqZWN0LWdldG93bnByb3BlcnR5c3ltYm9scyAtLSByZXF1aXJlZCBmb3IgdGVzdGluZwptb2R1bGUuZXhwb3J0cyA9ICEhT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyAmJiAhZmFpbHMoZnVuY3Rpb24gKCkgewogIHZhciBzeW1ib2wgPSBTeW1ib2woJ3N5bWJvbCBkZXRlY3Rpb24nKTsKICAvLyBDaHJvbWUgMzggU3ltYm9sIGhhcyBpbmNvcnJlY3QgdG9TdHJpbmcgY29udmVyc2lvbgogIC8vIGBnZXQtb3duLXByb3BlcnR5LXN5bWJvbHNgIHBvbHlmaWxsIHN5bWJvbHMgY29udmVydGVkIHRvIG9iamVjdCBhcmUgbm90IFN5bWJvbCBpbnN0YW5jZXMKICAvLyBuYjogRG8gbm90IGNhbGwgYFN0cmluZ2AgZGlyZWN0bHkgdG8gYXZvaWQgdGhpcyBiZWluZyBvcHRpbWl6ZWQgb3V0IHRvIGBzeW1ib2wrJydgIHdoaWNoIHdpbGwsCiAgLy8gb2YgY291cnNlLCBmYWlsLgogIHJldHVybiAhJFN0cmluZyhzeW1ib2wpIHx8ICEoT2JqZWN0KHN5bWJvbCkgaW5zdGFuY2VvZiBTeW1ib2wpIHx8CiAgICAvLyBDaHJvbWUgMzgtNDAgc3ltYm9scyBhcmUgbm90IGluaGVyaXRlZCBmcm9tIERPTSBjb2xsZWN0aW9ucyBwcm90b3R5cGVzIHRvIGluc3RhbmNlcwogICAgIVN5bWJvbC5zaGFtICYmIFY4X1ZFUlNJT04gJiYgVjhfVkVSU0lPTiA8IDQxOwp9KTsKCgovKioqLyB9KSwKCi8qKiovIDQ1Mjc6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgREVTQ1JJUFRPUlMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM3MjQpOwp2YXIgaXNBcnJheSA9IF9fd2VicGFja19yZXF1aXJlX18oNDM3Nik7Cgp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1nZXRvd25wcm9wZXJ0eWRlc2NyaXB0b3IgLS0gc2FmZQp2YXIgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcjsKCi8vIFNhZmFyaSA8IDEzIGRvZXMgbm90IHRocm93IGFuIGVycm9yIGluIHRoaXMgY2FzZQp2YXIgU0lMRU5UX09OX05PTl9XUklUQUJMRV9MRU5HVEhfU0VUID0gREVTQ1JJUFRPUlMgJiYgIWZ1bmN0aW9uICgpIHsKICAvLyBtYWtlcyBubyBzZW5zZSB3aXRob3V0IHByb3BlciBzdHJpY3QgbW9kZSBzdXBwb3J0CiAgaWYgKHRoaXMgIT09IHVuZGVmaW5lZCkgcmV0dXJuIHRydWU7CiAgdHJ5IHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZGVmaW5lcHJvcGVydHkgLS0gc2FmZQogICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFtdLCAnbGVuZ3RoJywgeyB3cml0YWJsZTogZmFsc2UgfSkubGVuZ3RoID0gMTsKICB9IGNhdGNoIChlcnJvcikgewogICAgcmV0dXJuIGVycm9yIGluc3RhbmNlb2YgVHlwZUVycm9yOwogIH0KfSgpOwoKbW9kdWxlLmV4cG9ydHMgPSBTSUxFTlRfT05fTk9OX1dSSVRBQkxFX0xFTkdUSF9TRVQgPyBmdW5jdGlvbiAoTywgbGVuZ3RoKSB7CiAgaWYgKGlzQXJyYXkoTykgJiYgIWdldE93blByb3BlcnR5RGVzY3JpcHRvcihPLCAnbGVuZ3RoJykud3JpdGFibGUpIHsKICAgIHRocm93IG5ldyAkVHlwZUVycm9yKCdDYW5ub3Qgc2V0IHJlYWQgb25seSAubGVuZ3RoJyk7CiAgfSByZXR1cm4gTy5sZW5ndGggPSBsZW5ndGg7Cn0gOiBmdW5jdGlvbiAoTywgbGVuZ3RoKSB7CiAgcmV0dXJuIE8ubGVuZ3RoID0gbGVuZ3RoOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNDU0OToKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBnbG9iYWxUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0NTc2KTsKCi8vIGh0dHBzOi8vZ2l0aHViLmNvbS90YzM5L2VjbWEyNjIvcHVsbC8zNDY3Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKE1FVEhPRF9OQU1FLCBFeHBlY3RlZEVycm9yKSB7CiAgdmFyIEl0ZXJhdG9yID0gZ2xvYmFsVGhpcy5JdGVyYXRvcjsKICB2YXIgSXRlcmF0b3JQcm90b3R5cGUgPSBJdGVyYXRvciAmJiBJdGVyYXRvci5wcm90b3R5cGU7CiAgdmFyIG1ldGhvZCA9IEl0ZXJhdG9yUHJvdG90eXBlICYmIEl0ZXJhdG9yUHJvdG90eXBlW01FVEhPRF9OQU1FXTsKCiAgdmFyIENMT1NFRCA9IGZhbHNlOwoKICBpZiAobWV0aG9kKSB0cnkgewogICAgbWV0aG9kLmNhbGwoewogICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7IHJldHVybiB7IGRvbmU6IHRydWUgfTsgfSwKICAgICAgJ3JldHVybic6IGZ1bmN0aW9uICgpIHsgQ0xPU0VEID0gdHJ1ZTsgfQogICAgfSwgLTEpOwogIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAvLyBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MjkxMTk1CiAgICBpZiAoIShlcnJvciBpbnN0YW5jZW9mIEV4cGVjdGVkRXJyb3IpKSBDTE9TRUQgPSBmYWxzZTsKICB9CgogIGlmICghQ0xPU0VEKSByZXR1cm4gbWV0aG9kOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNDU3NjoKLyoqKi8gKGZ1bmN0aW9uKG1vZHVsZSkgewoKCnZhciBjaGVjayA9IGZ1bmN0aW9uIChpdCkgewogIHJldHVybiBpdCAmJiBpdC5NYXRoID09PSBNYXRoICYmIGl0Owp9OwoKLy8gaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvaXNzdWVzLzg2I2lzc3VlY29tbWVudC0xMTU3NTkwMjgKbW9kdWxlLmV4cG9ydHMgPQogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1nbG9iYWwtdGhpcyAtLSBzYWZlCiAgY2hlY2sodHlwZW9mIGdsb2JhbFRoaXMgPT0gJ29iamVjdCcgJiYgZ2xvYmFsVGhpcykgfHwKICBjaGVjayh0eXBlb2Ygd2luZG93ID09ICdvYmplY3QnICYmIHdpbmRvdykgfHwKICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcmVzdHJpY3RlZC1nbG9iYWxzIC0tIHNhZmUKICBjaGVjayh0eXBlb2Ygc2VsZiA9PSAnb2JqZWN0JyAmJiBzZWxmKSB8fAogIGNoZWNrKHR5cGVvZiBnbG9iYWwgPT0gJ29iamVjdCcgJiYgZ2xvYmFsKSB8fAogIGNoZWNrKHR5cGVvZiB0aGlzID09ICdvYmplY3QnICYmIHRoaXMpIHx8CiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLW5ldy1mdW5jIC0tIGZhbGxiYWNrCiAgKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0pKCkgfHwgRnVuY3Rpb24oJ3JldHVybiB0aGlzJykoKTsKCgovKioqLyB9KSwKCi8qKiovIDQ2MDM6Ci8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBkZWZpbmVCdWlsdEluID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2ODQwKTsKdmFyIHVuY3VycnlUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTA0KTsKdmFyIHRvU3RyaW5nID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2NTUpOwp2YXIgdmFsaWRhdGVBcmd1bWVudHNMZW5ndGggPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDI4MTIpOwoKdmFyICRVUkxTZWFyY2hQYXJhbXMgPSBVUkxTZWFyY2hQYXJhbXM7CnZhciBVUkxTZWFyY2hQYXJhbXNQcm90b3R5cGUgPSAkVVJMU2VhcmNoUGFyYW1zLnByb3RvdHlwZTsKdmFyIGFwcGVuZCA9IHVuY3VycnlUaGlzKFVSTFNlYXJjaFBhcmFtc1Byb3RvdHlwZS5hcHBlbmQpOwp2YXIgJGRlbGV0ZSA9IHVuY3VycnlUaGlzKFVSTFNlYXJjaFBhcmFtc1Byb3RvdHlwZVsnZGVsZXRlJ10pOwp2YXIgZm9yRWFjaCA9IHVuY3VycnlUaGlzKFVSTFNlYXJjaFBhcmFtc1Byb3RvdHlwZS5mb3JFYWNoKTsKdmFyIHB1c2ggPSB1bmN1cnJ5VGhpcyhbXS5wdXNoKTsKdmFyIHBhcmFtcyA9IG5ldyAkVVJMU2VhcmNoUGFyYW1zKCdhPTEmYT0yJmI9MycpOwoKcGFyYW1zWydkZWxldGUnXSgnYScsIDEpOwovLyBgdW5kZWZpbmVkYCBjYXNlIGlzIGEgQ2hyb21pdW0gMTE3IGJ1ZwovLyBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvdjgvaXNzdWVzL2RldGFpbD9pZD0xNDIyMgpwYXJhbXNbJ2RlbGV0ZSddKCdiJywgdW5kZWZpbmVkKTsKCmlmIChwYXJhbXMgKyAnJyAhPT0gJ2E9MicpIHsKICBkZWZpbmVCdWlsdEluKFVSTFNlYXJjaFBhcmFtc1Byb3RvdHlwZSwgJ2RlbGV0ZScsIGZ1bmN0aW9uIChuYW1lIC8qICwgdmFsdWUgKi8pIHsKICAgIHZhciBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoOwogICAgdmFyICR2YWx1ZSA9IGxlbmd0aCA8IDIgPyB1bmRlZmluZWQgOiBhcmd1bWVudHNbMV07CiAgICBpZiAobGVuZ3RoICYmICR2YWx1ZSA9PT0gdW5kZWZpbmVkKSByZXR1cm4gJGRlbGV0ZSh0aGlzLCBuYW1lKTsKICAgIHZhciBlbnRyaWVzID0gW107CiAgICBmb3JFYWNoKHRoaXMsIGZ1bmN0aW9uICh2LCBrKSB7IC8vIGFsc28gdmFsaWRhdGVzIGB0aGlzYAogICAgICBwdXNoKGVudHJpZXMsIHsga2V5OiBrLCB2YWx1ZTogdiB9KTsKICAgIH0pOwogICAgdmFsaWRhdGVBcmd1bWVudHNMZW5ndGgobGVuZ3RoLCAxKTsKICAgIHZhciBrZXkgPSB0b1N0cmluZyhuYW1lKTsKICAgIHZhciB2YWx1ZSA9IHRvU3RyaW5nKCR2YWx1ZSk7CiAgICB2YXIgaW5kZXggPSAwOwogICAgdmFyIGRpbmRleCA9IDA7CiAgICB2YXIgZm91bmQgPSBmYWxzZTsKICAgIHZhciBlbnRyaWVzTGVuZ3RoID0gZW50cmllcy5sZW5ndGg7CiAgICB2YXIgZW50cnk7CiAgICB3aGlsZSAoaW5kZXggPCBlbnRyaWVzTGVuZ3RoKSB7CiAgICAgIGVudHJ5ID0gZW50cmllc1tpbmRleCsrXTsKICAgICAgaWYgKGZvdW5kIHx8IGVudHJ5LmtleSA9PT0ga2V5KSB7CiAgICAgICAgZm91bmQgPSB0cnVlOwogICAgICAgICRkZWxldGUodGhpcywgZW50cnkua2V5KTsKICAgICAgfSBlbHNlIGRpbmRleCsrOwogICAgfQogICAgd2hpbGUgKGRpbmRleCA8IGVudHJpZXNMZW5ndGgpIHsKICAgICAgZW50cnkgPSBlbnRyaWVzW2RpbmRleCsrXTsKICAgICAgaWYgKCEoZW50cnkua2V5ID09PSBrZXkgJiYgZW50cnkudmFsdWUgPT09IHZhbHVlKSkgYXBwZW5kKHRoaXMsIGVudHJ5LmtleSwgZW50cnkudmFsdWUpOwogICAgfQogIH0sIHsgZW51bWVyYWJsZTogdHJ1ZSwgdW5zYWZlOiB0cnVlIH0pOwp9CgoKLyoqKi8gfSksCgovKioqLyA0NjI4OgovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgJCA9IF9fd2VicGFja19yZXF1aXJlX18oNjUxOCk7CnZhciBuZXdQcm9taXNlQ2FwYWJpbGl0eU1vZHVsZSA9IF9fd2VicGFja19yZXF1aXJlX18oNjA0Myk7CgovLyBgUHJvbWlzZS53aXRoUmVzb2x2ZXJzYCBtZXRob2QKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1wcm9taXNlLndpdGhSZXNvbHZlcnMKJCh7IHRhcmdldDogJ1Byb21pc2UnLCBzdGF0OiB0cnVlIH0sIHsKICB3aXRoUmVzb2x2ZXJzOiBmdW5jdGlvbiB3aXRoUmVzb2x2ZXJzKCkgewogICAgdmFyIHByb21pc2VDYXBhYmlsaXR5ID0gbmV3UHJvbWlzZUNhcGFiaWxpdHlNb2R1bGUuZih0aGlzKTsKICAgIHJldHVybiB7CiAgICAgIHByb21pc2U6IHByb21pc2VDYXBhYmlsaXR5LnByb21pc2UsCiAgICAgIHJlc29sdmU6IHByb21pc2VDYXBhYmlsaXR5LnJlc29sdmUsCiAgICAgIHJlamVjdDogcHJvbWlzZUNhcGFiaWxpdHkucmVqZWN0CiAgICB9OwogIH0KfSk7CgoKLyoqKi8gfSksCgovKioqLyA0NjQ0OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIE5BVElWRV9BUlJBWV9CVUZGRVIgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDc4MTEpOwp2YXIgREVTQ1JJUFRPUlMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM3MjQpOwp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciBpc0NhbGxhYmxlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0OTAxKTsKdmFyIGlzT2JqZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNCk7CnZhciBoYXNPd24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDkyOTcpOwp2YXIgY2xhc3NvZiA9IF9fd2VicGFja19yZXF1aXJlX18oNjk1NSk7CnZhciB0cnlUb1N0cmluZyA9IF9fd2VicGFja19yZXF1aXJlX18oNjgyMyk7CnZhciBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY2OTkpOwp2YXIgZGVmaW5lQnVpbHRJbiA9IF9fd2VicGFja19yZXF1aXJlX18oNjg0MCk7CnZhciBkZWZpbmVCdWlsdEluQWNjZXNzb3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDIxMDYpOwp2YXIgaXNQcm90b3R5cGVPZiA9IF9fd2VicGFja19yZXF1aXJlX18oMTYyNSk7CnZhciBnZXRQcm90b3R5cGVPZiA9IF9fd2VicGFja19yZXF1aXJlX18oMjc4Nyk7CnZhciBzZXRQcm90b3R5cGVPZiA9IF9fd2VicGFja19yZXF1aXJlX18oMjk2Nyk7CnZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDgyMjcpOwp2YXIgdWlkID0gX193ZWJwYWNrX3JlcXVpcmVfXygzMzkyKTsKdmFyIEludGVybmFsU3RhdGVNb2R1bGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDExODEpOwoKdmFyIGVuZm9yY2VJbnRlcm5hbFN0YXRlID0gSW50ZXJuYWxTdGF0ZU1vZHVsZS5lbmZvcmNlOwp2YXIgZ2V0SW50ZXJuYWxTdGF0ZSA9IEludGVybmFsU3RhdGVNb2R1bGUuZ2V0Owp2YXIgSW50OEFycmF5ID0gZ2xvYmFsVGhpcy5JbnQ4QXJyYXk7CnZhciBJbnQ4QXJyYXlQcm90b3R5cGUgPSBJbnQ4QXJyYXkgJiYgSW50OEFycmF5LnByb3RvdHlwZTsKdmFyIFVpbnQ4Q2xhbXBlZEFycmF5ID0gZ2xvYmFsVGhpcy5VaW50OENsYW1wZWRBcnJheTsKdmFyIFVpbnQ4Q2xhbXBlZEFycmF5UHJvdG90eXBlID0gVWludDhDbGFtcGVkQXJyYXkgJiYgVWludDhDbGFtcGVkQXJyYXkucHJvdG90eXBlOwp2YXIgVHlwZWRBcnJheSA9IEludDhBcnJheSAmJiBnZXRQcm90b3R5cGVPZihJbnQ4QXJyYXkpOwp2YXIgVHlwZWRBcnJheVByb3RvdHlwZSA9IEludDhBcnJheVByb3RvdHlwZSAmJiBnZXRQcm90b3R5cGVPZihJbnQ4QXJyYXlQcm90b3R5cGUpOwp2YXIgT2JqZWN0UHJvdG90eXBlID0gT2JqZWN0LnByb3RvdHlwZTsKdmFyIFR5cGVFcnJvciA9IGdsb2JhbFRoaXMuVHlwZUVycm9yOwoKdmFyIFRPX1NUUklOR19UQUcgPSB3ZWxsS25vd25TeW1ib2woJ3RvU3RyaW5nVGFnJyk7CnZhciBUWVBFRF9BUlJBWV9UQUcgPSB1aWQoJ1RZUEVEX0FSUkFZX1RBRycpOwp2YXIgVFlQRURfQVJSQVlfQ09OU1RSVUNUT1IgPSAnVHlwZWRBcnJheUNvbnN0cnVjdG9yJzsKLy8gRml4aW5nIG5hdGl2ZSB0eXBlZCBhcnJheXMgaW4gT3BlcmEgUHJlc3RvIGNyYXNoZXMgdGhlIGJyb3dzZXIsIHNlZSAjNTk1CnZhciBOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTID0gTkFUSVZFX0FSUkFZX0JVRkZFUiAmJiAhIXNldFByb3RvdHlwZU9mICYmIGNsYXNzb2YoZ2xvYmFsVGhpcy5vcGVyYSkgIT09ICdPcGVyYSc7CnZhciBUWVBFRF9BUlJBWV9UQUdfUkVRVUlSRUQgPSBmYWxzZTsKdmFyIE5BTUUsIENvbnN0cnVjdG9yLCBQcm90b3R5cGU7Cgp2YXIgVHlwZWRBcnJheUNvbnN0cnVjdG9yc0xpc3QgPSB7CiAgSW50OEFycmF5OiAxLAogIFVpbnQ4QXJyYXk6IDEsCiAgVWludDhDbGFtcGVkQXJyYXk6IDEsCiAgSW50MTZBcnJheTogMiwKICBVaW50MTZBcnJheTogMiwKICBJbnQzMkFycmF5OiA0LAogIFVpbnQzMkFycmF5OiA0LAogIEZsb2F0MzJBcnJheTogNCwKICBGbG9hdDY0QXJyYXk6IDgKfTsKCnZhciBCaWdJbnRBcnJheUNvbnN0cnVjdG9yc0xpc3QgPSB7CiAgQmlnSW50NjRBcnJheTogOCwKICBCaWdVaW50NjRBcnJheTogOAp9OwoKdmFyIGlzVmlldyA9IGZ1bmN0aW9uIGlzVmlldyhpdCkgewogIGlmICghaXNPYmplY3QoaXQpKSByZXR1cm4gZmFsc2U7CiAgdmFyIGtsYXNzID0gY2xhc3NvZihpdCk7CiAgcmV0dXJuIGtsYXNzID09PSAnRGF0YVZpZXcnCiAgICB8fCBoYXNPd24oVHlwZWRBcnJheUNvbnN0cnVjdG9yc0xpc3QsIGtsYXNzKQogICAgfHwgaGFzT3duKEJpZ0ludEFycmF5Q29uc3RydWN0b3JzTGlzdCwga2xhc3MpOwp9OwoKdmFyIGdldFR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IGZ1bmN0aW9uIChpdCkgewogIHZhciBwcm90byA9IGdldFByb3RvdHlwZU9mKGl0KTsKICBpZiAoIWlzT2JqZWN0KHByb3RvKSkgcmV0dXJuOwogIHZhciBzdGF0ZSA9IGdldEludGVybmFsU3RhdGUocHJvdG8pOwogIHJldHVybiAoc3RhdGUgJiYgaGFzT3duKHN0YXRlLCBUWVBFRF9BUlJBWV9DT05TVFJVQ1RPUikpID8gc3RhdGVbVFlQRURfQVJSQVlfQ09OU1RSVUNUT1JdIDogZ2V0VHlwZWRBcnJheUNvbnN0cnVjdG9yKHByb3RvKTsKfTsKCnZhciBpc1R5cGVkQXJyYXkgPSBmdW5jdGlvbiAoaXQpIHsKICBpZiAoIWlzT2JqZWN0KGl0KSkgcmV0dXJuIGZhbHNlOwogIHZhciBrbGFzcyA9IGNsYXNzb2YoaXQpOwogIHJldHVybiBoYXNPd24oVHlwZWRBcnJheUNvbnN0cnVjdG9yc0xpc3QsIGtsYXNzKQogICAgfHwgaGFzT3duKEJpZ0ludEFycmF5Q29uc3RydWN0b3JzTGlzdCwga2xhc3MpOwp9OwoKdmFyIGFUeXBlZEFycmF5ID0gZnVuY3Rpb24gKGl0KSB7CiAgaWYgKGlzVHlwZWRBcnJheShpdCkpIHJldHVybiBpdDsKICB0aHJvdyBuZXcgVHlwZUVycm9yKCdUYXJnZXQgaXMgbm90IGEgdHlwZWQgYXJyYXknKTsKfTsKCnZhciBhVHlwZWRBcnJheUNvbnN0cnVjdG9yID0gZnVuY3Rpb24gKEMpIHsKICBpZiAoaXNDYWxsYWJsZShDKSAmJiAoIXNldFByb3RvdHlwZU9mIHx8IGlzUHJvdG90eXBlT2YoVHlwZWRBcnJheSwgQykpKSByZXR1cm4gQzsKICB0aHJvdyBuZXcgVHlwZUVycm9yKHRyeVRvU3RyaW5nKEMpICsgJyBpcyBub3QgYSB0eXBlZCBhcnJheSBjb25zdHJ1Y3RvcicpOwp9OwoKdmFyIGV4cG9ydFR5cGVkQXJyYXlNZXRob2QgPSBmdW5jdGlvbiAoS0VZLCBwcm9wZXJ0eSwgZm9yY2VkLCBvcHRpb25zKSB7CiAgaWYgKCFERVNDUklQVE9SUykgcmV0dXJuOwogIGlmIChmb3JjZWQpIGZvciAodmFyIEFSUkFZIGluIFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnNMaXN0KSB7CiAgICB2YXIgVHlwZWRBcnJheUNvbnN0cnVjdG9yID0gZ2xvYmFsVGhpc1tBUlJBWV07CiAgICBpZiAoVHlwZWRBcnJheUNvbnN0cnVjdG9yICYmIGhhc093bihUeXBlZEFycmF5Q29uc3RydWN0b3IucHJvdG90eXBlLCBLRVkpKSB0cnkgewogICAgICBkZWxldGUgVHlwZWRBcnJheUNvbnN0cnVjdG9yLnByb3RvdHlwZVtLRVldOwogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgLy8gb2xkIFdlYktpdCBidWcgLSBzb21lIG1ldGhvZHMgYXJlIG5vbi1jb25maWd1cmFibGUKICAgICAgdHJ5IHsKICAgICAgICBUeXBlZEFycmF5Q29uc3RydWN0b3IucHJvdG90eXBlW0tFWV0gPSBwcm9wZXJ0eTsKICAgICAgfSBjYXRjaCAoZXJyb3IyKSB7IC8qIGVtcHR5ICovIH0KICAgIH0KICB9CiAgaWYgKCFUeXBlZEFycmF5UHJvdG90eXBlW0tFWV0gfHwgZm9yY2VkKSB7CiAgICBkZWZpbmVCdWlsdEluKFR5cGVkQXJyYXlQcm90b3R5cGUsIEtFWSwgZm9yY2VkID8gcHJvcGVydHkKICAgICAgOiBOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTICYmIEludDhBcnJheVByb3RvdHlwZVtLRVldIHx8IHByb3BlcnR5LCBvcHRpb25zKTsKICB9Cn07Cgp2YXIgZXhwb3J0VHlwZWRBcnJheVN0YXRpY01ldGhvZCA9IGZ1bmN0aW9uIChLRVksIHByb3BlcnR5LCBmb3JjZWQpIHsKICB2YXIgQVJSQVksIFR5cGVkQXJyYXlDb25zdHJ1Y3RvcjsKICBpZiAoIURFU0NSSVBUT1JTKSByZXR1cm47CiAgaWYgKHNldFByb3RvdHlwZU9mKSB7CiAgICBpZiAoZm9yY2VkKSBmb3IgKEFSUkFZIGluIFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnNMaXN0KSB7CiAgICAgIFR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IGdsb2JhbFRoaXNbQVJSQVldOwogICAgICBpZiAoVHlwZWRBcnJheUNvbnN0cnVjdG9yICYmIGhhc093bihUeXBlZEFycmF5Q29uc3RydWN0b3IsIEtFWSkpIHRyeSB7CiAgICAgICAgZGVsZXRlIFR5cGVkQXJyYXlDb25zdHJ1Y3RvcltLRVldOwogICAgICB9IGNhdGNoIChlcnJvcikgeyAvKiBlbXB0eSAqLyB9CiAgICB9CiAgICBpZiAoIVR5cGVkQXJyYXlbS0VZXSB8fCBmb3JjZWQpIHsKICAgICAgLy8gVjggfiBDaHJvbWUgNDktNTAgYCVUeXBlZEFycmF5JWAgbWV0aG9kcyBhcmUgbm9uLXdyaXRhYmxlIG5vbi1jb25maWd1cmFibGUKICAgICAgdHJ5IHsKICAgICAgICByZXR1cm4gZGVmaW5lQnVpbHRJbihUeXBlZEFycmF5LCBLRVksIGZvcmNlZCA/IHByb3BlcnR5IDogTkFUSVZFX0FSUkFZX0JVRkZFUl9WSUVXUyAmJiBUeXBlZEFycmF5W0tFWV0gfHwgcHJvcGVydHkpOwogICAgICB9IGNhdGNoIChlcnJvcikgeyAvKiBlbXB0eSAqLyB9CiAgICB9IGVsc2UgcmV0dXJuOwogIH0KICBmb3IgKEFSUkFZIGluIFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnNMaXN0KSB7CiAgICBUeXBlZEFycmF5Q29uc3RydWN0b3IgPSBnbG9iYWxUaGlzW0FSUkFZXTsKICAgIGlmIChUeXBlZEFycmF5Q29uc3RydWN0b3IgJiYgKCFUeXBlZEFycmF5Q29uc3RydWN0b3JbS0VZXSB8fCBmb3JjZWQpKSB7CiAgICAgIGRlZmluZUJ1aWx0SW4oVHlwZWRBcnJheUNvbnN0cnVjdG9yLCBLRVksIHByb3BlcnR5KTsKICAgIH0KICB9Cn07Cgpmb3IgKE5BTUUgaW4gVHlwZWRBcnJheUNvbnN0cnVjdG9yc0xpc3QpIHsKICBDb25zdHJ1Y3RvciA9IGdsb2JhbFRoaXNbTkFNRV07CiAgUHJvdG90eXBlID0gQ29uc3RydWN0b3IgJiYgQ29uc3RydWN0b3IucHJvdG90eXBlOwogIGlmIChQcm90b3R5cGUpIGVuZm9yY2VJbnRlcm5hbFN0YXRlKFByb3RvdHlwZSlbVFlQRURfQVJSQVlfQ09OU1RSVUNUT1JdID0gQ29uc3RydWN0b3I7CiAgZWxzZSBOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTID0gZmFsc2U7Cn0KCmZvciAoTkFNRSBpbiBCaWdJbnRBcnJheUNvbnN0cnVjdG9yc0xpc3QpIHsKICBDb25zdHJ1Y3RvciA9IGdsb2JhbFRoaXNbTkFNRV07CiAgUHJvdG90eXBlID0gQ29uc3RydWN0b3IgJiYgQ29uc3RydWN0b3IucHJvdG90eXBlOwogIGlmIChQcm90b3R5cGUpIGVuZm9yY2VJbnRlcm5hbFN0YXRlKFByb3RvdHlwZSlbVFlQRURfQVJSQVlfQ09OU1RSVUNUT1JdID0gQ29uc3RydWN0b3I7Cn0KCi8vIFdlYktpdCBidWcgLSB0eXBlZCBhcnJheXMgY29uc3RydWN0b3JzIHByb3RvdHlwZSBpcyBPYmplY3QucHJvdG90eXBlCmlmICghTkFUSVZFX0FSUkFZX0JVRkZFUl9WSUVXUyB8fCAhaXNDYWxsYWJsZShUeXBlZEFycmF5KSB8fCBUeXBlZEFycmF5ID09PSBGdW5jdGlvbi5wcm90b3R5cGUpIHsKICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2hhZG93IC0tIHNhZmUKICBUeXBlZEFycmF5ID0gZnVuY3Rpb24gVHlwZWRBcnJheSgpIHsKICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0luY29ycmVjdCBpbnZvY2F0aW9uJyk7CiAgfTsKICBpZiAoTkFUSVZFX0FSUkFZX0JVRkZFUl9WSUVXUykgZm9yIChOQU1FIGluIFR5cGVkQXJyYXlDb25zdHJ1Y3RvcnNMaXN0KSB7CiAgICBpZiAoZ2xvYmFsVGhpc1tOQU1FXSkgc2V0UHJvdG90eXBlT2YoZ2xvYmFsVGhpc1tOQU1FXSwgVHlwZWRBcnJheSk7CiAgfQp9CgppZiAoIU5BVElWRV9BUlJBWV9CVUZGRVJfVklFV1MgfHwgIVR5cGVkQXJyYXlQcm90b3R5cGUgfHwgVHlwZWRBcnJheVByb3RvdHlwZSA9PT0gT2JqZWN0UHJvdG90eXBlKSB7CiAgVHlwZWRBcnJheVByb3RvdHlwZSA9IFR5cGVkQXJyYXkucHJvdG90eXBlOwogIGlmIChOQVRJVkVfQVJSQVlfQlVGRkVSX1ZJRVdTKSBmb3IgKE5BTUUgaW4gVHlwZWRBcnJheUNvbnN0cnVjdG9yc0xpc3QpIHsKICAgIGlmIChnbG9iYWxUaGlzW05BTUVdKSBzZXRQcm90b3R5cGVPZihnbG9iYWxUaGlzW05BTUVdLnByb3RvdHlwZSwgVHlwZWRBcnJheVByb3RvdHlwZSk7CiAgfQp9CgovLyBXZWJLaXQgYnVnIC0gb25lIG1vcmUgb2JqZWN0IGluIFVpbnQ4Q2xhbXBlZEFycmF5IHByb3RvdHlwZSBjaGFpbgppZiAoTkFUSVZFX0FSUkFZX0JVRkZFUl9WSUVXUyAmJiBnZXRQcm90b3R5cGVPZihVaW50OENsYW1wZWRBcnJheVByb3RvdHlwZSkgIT09IFR5cGVkQXJyYXlQcm90b3R5cGUpIHsKICBzZXRQcm90b3R5cGVPZihVaW50OENsYW1wZWRBcnJheVByb3RvdHlwZSwgVHlwZWRBcnJheVByb3RvdHlwZSk7Cn0KCmlmIChERVNDUklQVE9SUyAmJiAhaGFzT3duKFR5cGVkQXJyYXlQcm90b3R5cGUsIFRPX1NUUklOR19UQUcpKSB7CiAgVFlQRURfQVJSQVlfVEFHX1JFUVVJUkVEID0gdHJ1ZTsKICBkZWZpbmVCdWlsdEluQWNjZXNzb3IoVHlwZWRBcnJheVByb3RvdHlwZSwgVE9fU1RSSU5HX1RBRywgewogICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgZ2V0OiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiBpc09iamVjdCh0aGlzKSA/IHRoaXNbVFlQRURfQVJSQVlfVEFHXSA6IHVuZGVmaW5lZDsKICAgIH0KICB9KTsKICBmb3IgKE5BTUUgaW4gVHlwZWRBcnJheUNvbnN0cnVjdG9yc0xpc3QpIGlmIChnbG9iYWxUaGlzW05BTUVdKSB7CiAgICBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkoZ2xvYmFsVGhpc1tOQU1FXSwgVFlQRURfQVJSQVlfVEFHLCBOQU1FKTsKICB9Cn0KCm1vZHVsZS5leHBvcnRzID0gewogIE5BVElWRV9BUlJBWV9CVUZGRVJfVklFV1M6IE5BVElWRV9BUlJBWV9CVUZGRVJfVklFV1MsCiAgVFlQRURfQVJSQVlfVEFHOiBUWVBFRF9BUlJBWV9UQUdfUkVRVUlSRUQgJiYgVFlQRURfQVJSQVlfVEFHLAogIGFUeXBlZEFycmF5OiBhVHlwZWRBcnJheSwKICBhVHlwZWRBcnJheUNvbnN0cnVjdG9yOiBhVHlwZWRBcnJheUNvbnN0cnVjdG9yLAogIGV4cG9ydFR5cGVkQXJyYXlNZXRob2Q6IGV4cG9ydFR5cGVkQXJyYXlNZXRob2QsCiAgZXhwb3J0VHlwZWRBcnJheVN0YXRpY01ldGhvZDogZXhwb3J0VHlwZWRBcnJheVN0YXRpY01ldGhvZCwKICBnZXRUeXBlZEFycmF5Q29uc3RydWN0b3I6IGdldFR5cGVkQXJyYXlDb25zdHJ1Y3RvciwKICBpc1ZpZXc6IGlzVmlldywKICBpc1R5cGVkQXJyYXk6IGlzVHlwZWRBcnJheSwKICBUeXBlZEFycmF5OiBUeXBlZEFycmF5LAogIFR5cGVkQXJyYXlQcm90b3R5cGU6IFR5cGVkQXJyYXlQcm90b3R5cGUKfTsKCgovKioqLyB9KSwKCi8qKiovIDQ2NTk6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgREVTQ1JJUFRPUlMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM3MjQpOwp2YXIgZGVmaW5lUHJvcGVydHlNb2R1bGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MTMpOwp2YXIgY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2OTgwKTsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9iamVjdCwga2V5LCB2YWx1ZSkgewogIGlmIChERVNDUklQVE9SUykgZGVmaW5lUHJvcGVydHlNb2R1bGUuZihvYmplY3QsIGtleSwgY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yKDAsIHZhbHVlKSk7CiAgZWxzZSBvYmplY3Rba2V5XSA9IHZhbHVlOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNDkwMToKLyoqKi8gKChtb2R1bGUpID0+IHsKCgovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLUlzSFRNTEREQS1pbnRlcm5hbC1zbG90CnZhciBkb2N1bWVudEFsbCA9IHR5cGVvZiBkb2N1bWVudCA9PSAnb2JqZWN0JyAmJiBkb2N1bWVudC5hbGw7CgovLyBgSXNDYWxsYWJsZWAgYWJzdHJhY3Qgb3BlcmF0aW9uCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtaXNjYWxsYWJsZQovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgdW5pY29ybi9uby10eXBlb2YtdW5kZWZpbmVkIC0tIHJlcXVpcmVkIGZvciB0ZXN0aW5nCm1vZHVsZS5leHBvcnRzID0gdHlwZW9mIGRvY3VtZW50QWxsID09ICd1bmRlZmluZWQnICYmIGRvY3VtZW50QWxsICE9PSB1bmRlZmluZWQgPyBmdW5jdGlvbiAoYXJndW1lbnQpIHsKICByZXR1cm4gdHlwZW9mIGFyZ3VtZW50ID09ICdmdW5jdGlvbicgfHwgYXJndW1lbnQgPT09IGRvY3VtZW50QWxsOwp9IDogZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiAgcmV0dXJuIHR5cGVvZiBhcmd1bWVudCA9PSAnZnVuY3Rpb24nOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNDkxMzoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBERVNDUklQVE9SUyA9IF9fd2VicGFja19yZXF1aXJlX18oMzcyNCk7CnZhciBJRThfRE9NX0RFRklORSA9IF9fd2VicGFja19yZXF1aXJlX18oNTkxNyk7CnZhciBWOF9QUk9UT1RZUEVfREVGSU5FX0JVRyA9IF9fd2VicGFja19yZXF1aXJlX18oODY4Nik7CnZhciBhbk9iamVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oODU1MSk7CnZhciB0b1Byb3BlcnR5S2V5ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2OTY5KTsKCnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yOwovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tb2JqZWN0LWRlZmluZXByb3BlcnR5IC0tIHNhZmUKdmFyICRkZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTsKLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1nZXRvd25wcm9wZXJ0eWRlc2NyaXB0b3IgLS0gc2FmZQp2YXIgJGdldE93blByb3BlcnR5RGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7CnZhciBFTlVNRVJBQkxFID0gJ2VudW1lcmFibGUnOwp2YXIgQ09ORklHVVJBQkxFID0gJ2NvbmZpZ3VyYWJsZSc7CnZhciBXUklUQUJMRSA9ICd3cml0YWJsZSc7CgovLyBgT2JqZWN0LmRlZmluZVByb3BlcnR5YCBtZXRob2QKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1vYmplY3QuZGVmaW5lcHJvcGVydHkKZXhwb3J0cy5mID0gREVTQ1JJUFRPUlMgPyBWOF9QUk9UT1RZUEVfREVGSU5FX0JVRyA/IGZ1bmN0aW9uIGRlZmluZVByb3BlcnR5KE8sIFAsIEF0dHJpYnV0ZXMpIHsKICBhbk9iamVjdChPKTsKICBQID0gdG9Qcm9wZXJ0eUtleShQKTsKICBhbk9iamVjdChBdHRyaWJ1dGVzKTsKICBpZiAodHlwZW9mIE8gPT09ICdmdW5jdGlvbicgJiYgUCA9PT0gJ3Byb3RvdHlwZScgJiYgJ3ZhbHVlJyBpbiBBdHRyaWJ1dGVzICYmIFdSSVRBQkxFIGluIEF0dHJpYnV0ZXMgJiYgIUF0dHJpYnV0ZXNbV1JJVEFCTEVdKSB7CiAgICB2YXIgY3VycmVudCA9ICRnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoTywgUCk7CiAgICBpZiAoY3VycmVudCAmJiBjdXJyZW50W1dSSVRBQkxFXSkgewogICAgICBPW1BdID0gQXR0cmlidXRlcy52YWx1ZTsKICAgICAgQXR0cmlidXRlcyA9IHsKICAgICAgICBjb25maWd1cmFibGU6IENPTkZJR1VSQUJMRSBpbiBBdHRyaWJ1dGVzID8gQXR0cmlidXRlc1tDT05GSUdVUkFCTEVdIDogY3VycmVudFtDT05GSUdVUkFCTEVdLAogICAgICAgIGVudW1lcmFibGU6IEVOVU1FUkFCTEUgaW4gQXR0cmlidXRlcyA/IEF0dHJpYnV0ZXNbRU5VTUVSQUJMRV0gOiBjdXJyZW50W0VOVU1FUkFCTEVdLAogICAgICAgIHdyaXRhYmxlOiBmYWxzZQogICAgICB9OwogICAgfQogIH0gcmV0dXJuICRkZWZpbmVQcm9wZXJ0eShPLCBQLCBBdHRyaWJ1dGVzKTsKfSA6ICRkZWZpbmVQcm9wZXJ0eSA6IGZ1bmN0aW9uIGRlZmluZVByb3BlcnR5KE8sIFAsIEF0dHJpYnV0ZXMpIHsKICBhbk9iamVjdChPKTsKICBQID0gdG9Qcm9wZXJ0eUtleShQKTsKICBhbk9iamVjdChBdHRyaWJ1dGVzKTsKICBpZiAoSUU4X0RPTV9ERUZJTkUpIHRyeSB7CiAgICByZXR1cm4gJGRlZmluZVByb3BlcnR5KE8sIFAsIEF0dHJpYnV0ZXMpOwogIH0gY2F0Y2ggKGVycm9yKSB7IC8qIGVtcHR5ICovIH0KICBpZiAoJ2dldCcgaW4gQXR0cmlidXRlcyB8fCAnc2V0JyBpbiBBdHRyaWJ1dGVzKSB0aHJvdyBuZXcgJFR5cGVFcnJvcignQWNjZXNzb3JzIG5vdCBzdXBwb3J0ZWQnKTsKICBpZiAoJ3ZhbHVlJyBpbiBBdHRyaWJ1dGVzKSBPW1BdID0gQXR0cmlidXRlcy52YWx1ZTsKICByZXR1cm4gTzsKfTsKCgovKioqLyB9KSwKCi8qKiovIDQ5MTY6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgZ2V0QnVpbHRJbiA9IF9fd2VicGFja19yZXF1aXJlX18oNzc1MSk7Cgp2YXIgY3JlYXRlU2V0TGlrZSA9IGZ1bmN0aW9uIChzaXplKSB7CiAgcmV0dXJuIHsKICAgIHNpemU6IHNpemUsCiAgICBoYXM6IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfSwKICAgIGtleXM6IGZ1bmN0aW9uICgpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICByZXR1cm4geyBkb25lOiB0cnVlIH07CiAgICAgICAgfQogICAgICB9OwogICAgfQogIH07Cn07Cgp2YXIgY3JlYXRlU2V0TGlrZVdpdGhJbmZpbml0eVNpemUgPSBmdW5jdGlvbiAoc2l6ZSkgewogIHJldHVybiB7CiAgICBzaXplOiBzaXplLAogICAgaGFzOiBmdW5jdGlvbiAoKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfSwKICAgIGtleXM6IGZ1bmN0aW9uICgpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdlJyk7CiAgICB9CiAgfTsKfTsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG5hbWUsIGNhbGxiYWNrKSB7CiAgdmFyIFNldCA9IGdldEJ1aWx0SW4oJ1NldCcpOwogIHRyeSB7CiAgICBuZXcgU2V0KClbbmFtZV0oY3JlYXRlU2V0TGlrZSgwKSk7CiAgICB0cnkgewogICAgICAvLyBsYXRlIHNwZWMgY2hhbmdlLCBlYXJseSBXZWJLaXQgfiBTYWZhcmkgMTcgaW1wbGVtZW50YXRpb24gZG9lcyBub3QgcGFzcyBpdAogICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vdGMzOS9wcm9wb3NhbC1zZXQtbWV0aG9kcy9wdWxsLzg4CiAgICAgIC8vIGFsc28gY292ZXJlZCBlbmdpbmVzIHdpdGgKICAgICAgLy8gaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTI3MjY3OQogICAgICBuZXcgU2V0KClbbmFtZV0oY3JlYXRlU2V0TGlrZSgtMSkpOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9IGNhdGNoIChlcnJvcjIpIHsKICAgICAgaWYgKCFjYWxsYmFjaykgcmV0dXJuIHRydWU7CiAgICAgIC8vIGVhcmx5IFY4IGltcGxlbWVudGF0aW9uIGJ1ZwogICAgICAvLyBodHRwczovL2lzc3Vlcy5jaHJvbWl1bS5vcmcvaXNzdWVzLzM1MTMzMjYzNAogICAgICB0cnkgewogICAgICAgIG5ldyBTZXQoKVtuYW1lXShjcmVhdGVTZXRMaWtlV2l0aEluZmluaXR5U2l6ZSgtSW5maW5pdHkpKTsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgdmFyIHNldCA9IG5ldyBTZXQoKTsKICAgICAgICBzZXQuYWRkKDEpOwogICAgICAgIHNldC5hZGQoMik7CiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKHNldFtuYW1lXShjcmVhdGVTZXRMaWtlV2l0aEluZmluaXR5U2l6ZShJbmZpbml0eSkpKTsKICAgICAgfQogICAgfQogIH0gY2F0Y2ggKGVycm9yKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNDk3OToKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciBnZXRCdWlsdEluID0gX193ZWJwYWNrX3JlcXVpcmVfXyg3NzUxKTsKdmFyIGNyZWF0ZVByb3BlcnR5RGVzY3JpcHRvciA9IF9fd2VicGFja19yZXF1aXJlX18oNjk4MCk7CnZhciBkZWZpbmVQcm9wZXJ0eSA9IChfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MTMpLmYpOwp2YXIgaGFzT3duID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5Mjk3KTsKdmFyIGFuSW5zdGFuY2UgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY3OSk7CnZhciBpbmhlcml0SWZSZXF1aXJlZCA9IF9fd2VicGFja19yZXF1aXJlX18oMzE2Nyk7CnZhciBub3JtYWxpemVTdHJpbmdBcmd1bWVudCA9IF9fd2VicGFja19yZXF1aXJlX18oMjYwMyk7CnZhciBET01FeGNlcHRpb25Db25zdGFudHMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDUwMDIpOwp2YXIgY2xlYXJFcnJvclN0YWNrID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4NTc0KTsKdmFyIERFU0NSSVBUT1JTID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNzI0KTsKdmFyIElTX1BVUkUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDYzOTUpOwoKdmFyIERPTV9FWENFUFRJT04gPSAnRE9NRXhjZXB0aW9uJzsKdmFyIEVycm9yID0gZ2V0QnVpbHRJbignRXJyb3InKTsKdmFyIE5hdGl2ZURPTUV4Y2VwdGlvbiA9IGdldEJ1aWx0SW4oRE9NX0VYQ0VQVElPTik7Cgp2YXIgJERPTUV4Y2VwdGlvbiA9IGZ1bmN0aW9uIERPTUV4Y2VwdGlvbigpIHsKICBhbkluc3RhbmNlKHRoaXMsIERPTUV4Y2VwdGlvblByb3RvdHlwZSk7CiAgdmFyIGFyZ3VtZW50c0xlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7CiAgdmFyIG1lc3NhZ2UgPSBub3JtYWxpemVTdHJpbmdBcmd1bWVudChhcmd1bWVudHNMZW5ndGggPCAxID8gdW5kZWZpbmVkIDogYXJndW1lbnRzWzBdKTsKICB2YXIgbmFtZSA9IG5vcm1hbGl6ZVN0cmluZ0FyZ3VtZW50KGFyZ3VtZW50c0xlbmd0aCA8IDIgPyB1bmRlZmluZWQgOiBhcmd1bWVudHNbMV0sICdFcnJvcicpOwogIHZhciB0aGF0ID0gbmV3IE5hdGl2ZURPTUV4Y2VwdGlvbihtZXNzYWdlLCBuYW1lKTsKICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IobWVzc2FnZSk7CiAgZXJyb3IubmFtZSA9IERPTV9FWENFUFRJT047CiAgZGVmaW5lUHJvcGVydHkodGhhdCwgJ3N0YWNrJywgY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yKDEsIGNsZWFyRXJyb3JTdGFjayhlcnJvci5zdGFjaywgMSkpKTsKICBpbmhlcml0SWZSZXF1aXJlZCh0aGF0LCB0aGlzLCAkRE9NRXhjZXB0aW9uKTsKICByZXR1cm4gdGhhdDsKfTsKCnZhciBET01FeGNlcHRpb25Qcm90b3R5cGUgPSAkRE9NRXhjZXB0aW9uLnByb3RvdHlwZSA9IE5hdGl2ZURPTUV4Y2VwdGlvbi5wcm90b3R5cGU7Cgp2YXIgRVJST1JfSEFTX1NUQUNLID0gJ3N0YWNrJyBpbiBuZXcgRXJyb3IoRE9NX0VYQ0VQVElPTik7CnZhciBET01fRVhDRVBUSU9OX0hBU19TVEFDSyA9ICdzdGFjaycgaW4gbmV3IE5hdGl2ZURPTUV4Y2VwdGlvbigxLCAyKTsKCi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZ2V0b3ducHJvcGVydHlkZXNjcmlwdG9yIC0tIHNhZmUKdmFyIGRlc2NyaXB0b3IgPSBOYXRpdmVET01FeGNlcHRpb24gJiYgREVTQ1JJUFRPUlMgJiYgT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihnbG9iYWxUaGlzLCBET01fRVhDRVBUSU9OKTsKCi8vIEJ1biB+IDAuMS4xIERPTUV4Y2VwdGlvbiBoYXZlIGluY29ycmVjdCBkZXNjcmlwdG9yIGFuZCB3ZSBjYW4ndCByZWRlZmluZSBpdAovLyBodHRwczovL2dpdGh1Yi5jb20vSmFycmVkLVN1bW5lci9idW4vaXNzdWVzLzM5OQp2YXIgQlVHR1lfREVTQ1JJUFRPUiA9ICEhZGVzY3JpcHRvciAmJiAhKGRlc2NyaXB0b3Iud3JpdGFibGUgJiYgZGVzY3JpcHRvci5jb25maWd1cmFibGUpOwoKdmFyIEZPUkNFRF9DT05TVFJVQ1RPUiA9IEVSUk9SX0hBU19TVEFDSyAmJiAhQlVHR1lfREVTQ1JJUFRPUiAmJiAhRE9NX0VYQ0VQVElPTl9IQVNfU1RBQ0s7CgovLyBgRE9NRXhjZXB0aW9uYCBjb25zdHJ1Y3RvciBwYXRjaCBmb3IgYC5zdGFja2Agd2hlcmUgaXQncyByZXF1aXJlZAovLyBodHRwczovL3dlYmlkbC5zcGVjLndoYXR3Zy5vcmcvI2VzLURPTUV4Y2VwdGlvbi1zcGVjaWFsbmVzcwokKHsgZ2xvYmFsOiB0cnVlLCBjb25zdHJ1Y3RvcjogdHJ1ZSwgZm9yY2VkOiBJU19QVVJFIHx8IEZPUkNFRF9DT05TVFJVQ1RPUiB9LCB7IC8vIFRPRE86IGZpeCBleHBvcnQgbG9naWMKICBET01FeGNlcHRpb246IEZPUkNFRF9DT05TVFJVQ1RPUiA/ICRET01FeGNlcHRpb24gOiBOYXRpdmVET01FeGNlcHRpb24KfSk7Cgp2YXIgUG9seWZpbGxlZERPTUV4Y2VwdGlvbiA9IGdldEJ1aWx0SW4oRE9NX0VYQ0VQVElPTik7CnZhciBQb2x5ZmlsbGVkRE9NRXhjZXB0aW9uUHJvdG90eXBlID0gUG9seWZpbGxlZERPTUV4Y2VwdGlvbi5wcm90b3R5cGU7CgppZiAoUG9seWZpbGxlZERPTUV4Y2VwdGlvblByb3RvdHlwZS5jb25zdHJ1Y3RvciAhPT0gUG9seWZpbGxlZERPTUV4Y2VwdGlvbikgewogIGlmICghSVNfUFVSRSkgewogICAgZGVmaW5lUHJvcGVydHkoUG9seWZpbGxlZERPTUV4Y2VwdGlvblByb3RvdHlwZSwgJ2NvbnN0cnVjdG9yJywgY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yKDEsIFBvbHlmaWxsZWRET01FeGNlcHRpb24pKTsKICB9CgogIGZvciAodmFyIGtleSBpbiBET01FeGNlcHRpb25Db25zdGFudHMpIGlmIChoYXNPd24oRE9NRXhjZXB0aW9uQ29uc3RhbnRzLCBrZXkpKSB7CiAgICB2YXIgY29uc3RhbnQgPSBET01FeGNlcHRpb25Db25zdGFudHNba2V5XTsKICAgIHZhciBjb25zdGFudE5hbWUgPSBjb25zdGFudC5zOwogICAgaWYgKCFoYXNPd24oUG9seWZpbGxlZERPTUV4Y2VwdGlvbiwgY29uc3RhbnROYW1lKSkgewogICAgICBkZWZpbmVQcm9wZXJ0eShQb2x5ZmlsbGVkRE9NRXhjZXB0aW9uLCBjb25zdGFudE5hbWUsIGNyZWF0ZVByb3BlcnR5RGVzY3JpcHRvcig2LCBjb25zdGFudC5jKSk7CiAgICB9CiAgfQp9CgoKLyoqKi8gfSksCgovKioqLyA1MDAyOgovKioqLyAoKG1vZHVsZSkgPT4gewoKCm1vZHVsZS5leHBvcnRzID0gewogIEluZGV4U2l6ZUVycm9yOiB7IHM6ICdJTkRFWF9TSVpFX0VSUicsIGM6IDEsIG06IDEgfSwKICBET01TdHJpbmdTaXplRXJyb3I6IHsgczogJ0RPTVNUUklOR19TSVpFX0VSUicsIGM6IDIsIG06IDAgfSwKICBIaWVyYXJjaHlSZXF1ZXN0RXJyb3I6IHsgczogJ0hJRVJBUkNIWV9SRVFVRVNUX0VSUicsIGM6IDMsIG06IDEgfSwKICBXcm9uZ0RvY3VtZW50RXJyb3I6IHsgczogJ1dST05HX0RPQ1VNRU5UX0VSUicsIGM6IDQsIG06IDEgfSwKICBJbnZhbGlkQ2hhcmFjdGVyRXJyb3I6IHsgczogJ0lOVkFMSURfQ0hBUkFDVEVSX0VSUicsIGM6IDUsIG06IDEgfSwKICBOb0RhdGFBbGxvd2VkRXJyb3I6IHsgczogJ05PX0RBVEFfQUxMT1dFRF9FUlInLCBjOiA2LCBtOiAwIH0sCiAgTm9Nb2RpZmljYXRpb25BbGxvd2VkRXJyb3I6IHsgczogJ05PX01PRElGSUNBVElPTl9BTExPV0VEX0VSUicsIGM6IDcsIG06IDEgfSwKICBOb3RGb3VuZEVycm9yOiB7IHM6ICdOT1RfRk9VTkRfRVJSJywgYzogOCwgbTogMSB9LAogIE5vdFN1cHBvcnRlZEVycm9yOiB7IHM6ICdOT1RfU1VQUE9SVEVEX0VSUicsIGM6IDksIG06IDEgfSwKICBJblVzZUF0dHJpYnV0ZUVycm9yOiB7IHM6ICdJTlVTRV9BVFRSSUJVVEVfRVJSJywgYzogMTAsIG06IDEgfSwKICBJbnZhbGlkU3RhdGVFcnJvcjogeyBzOiAnSU5WQUxJRF9TVEFURV9FUlInLCBjOiAxMSwgbTogMSB9LAogIFN5bnRheEVycm9yOiB7IHM6ICdTWU5UQVhfRVJSJywgYzogMTIsIG06IDEgfSwKICBJbnZhbGlkTW9kaWZpY2F0aW9uRXJyb3I6IHsgczogJ0lOVkFMSURfTU9ESUZJQ0FUSU9OX0VSUicsIGM6IDEzLCBtOiAxIH0sCiAgTmFtZXNwYWNlRXJyb3I6IHsgczogJ05BTUVTUEFDRV9FUlInLCBjOiAxNCwgbTogMSB9LAogIEludmFsaWRBY2Nlc3NFcnJvcjogeyBzOiAnSU5WQUxJRF9BQ0NFU1NfRVJSJywgYzogMTUsIG06IDEgfSwKICBWYWxpZGF0aW9uRXJyb3I6IHsgczogJ1ZBTElEQVRJT05fRVJSJywgYzogMTYsIG06IDAgfSwKICBUeXBlTWlzbWF0Y2hFcnJvcjogeyBzOiAnVFlQRV9NSVNNQVRDSF9FUlInLCBjOiAxNywgbTogMSB9LAogIFNlY3VyaXR5RXJyb3I6IHsgczogJ1NFQ1VSSVRZX0VSUicsIGM6IDE4LCBtOiAxIH0sCiAgTmV0d29ya0Vycm9yOiB7IHM6ICdORVRXT1JLX0VSUicsIGM6IDE5LCBtOiAxIH0sCiAgQWJvcnRFcnJvcjogeyBzOiAnQUJPUlRfRVJSJywgYzogMjAsIG06IDEgfSwKICBVUkxNaXNtYXRjaEVycm9yOiB7IHM6ICdVUkxfTUlTTUFUQ0hfRVJSJywgYzogMjEsIG06IDEgfSwKICBRdW90YUV4Y2VlZGVkRXJyb3I6IHsgczogJ1FVT1RBX0VYQ0VFREVEX0VSUicsIGM6IDIyLCBtOiAxIH0sCiAgVGltZW91dEVycm9yOiB7IHM6ICdUSU1FT1VUX0VSUicsIGM6IDIzLCBtOiAxIH0sCiAgSW52YWxpZE5vZGVUeXBlRXJyb3I6IHsgczogJ0lOVkFMSURfTk9ERV9UWVBFX0VSUicsIGM6IDI0LCBtOiAxIH0sCiAgRGF0YUNsb25lRXJyb3I6IHsgczogJ0RBVEFfQ0xPTkVfRVJSJywgYzogMjUsIG06IDEgfQp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNTAyNDoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgc3ltbWV0cmljRGlmZmVyZW5jZSA9IF9fd2VicGFja19yZXF1aXJlX18oMzY1MCk7CnZhciBzZXRNZXRob2RHZXRLZXlzQmVmb3JlQ2xvbmluZyA9IF9fd2VicGFja19yZXF1aXJlX18oOTgzNSk7CnZhciBzZXRNZXRob2RBY2NlcHRTZXRMaWtlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0OTE2KTsKCnZhciBGT1JDRUQgPSAhc2V0TWV0aG9kQWNjZXB0U2V0TGlrZSgnc3ltbWV0cmljRGlmZmVyZW5jZScpIHx8ICFzZXRNZXRob2RHZXRLZXlzQmVmb3JlQ2xvbmluZygnc3ltbWV0cmljRGlmZmVyZW5jZScpOwoKLy8gYFNldC5wcm90b3R5cGUuc3ltbWV0cmljRGlmZmVyZW5jZWAgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc2V0LnByb3RvdHlwZS5zeW1tZXRyaWNkaWZmZXJlbmNlCiQoeyB0YXJnZXQ6ICdTZXQnLCBwcm90bzogdHJ1ZSwgcmVhbDogdHJ1ZSwgZm9yY2VkOiBGT1JDRUQgfSwgewogIHN5bW1ldHJpY0RpZmZlcmVuY2U6IHN5bW1ldHJpY0RpZmZlcmVuY2UKfSk7CgoKLyoqKi8gfSksCgovKioqLyA1MDMxOgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGdldEJ1aWx0SW4gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDc3NTEpOwp2YXIgdW5jdXJyeVRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1MDQpOwp2YXIgZ2V0T3duUHJvcGVydHlOYW1lc01vZHVsZSA9IF9fd2VicGFja19yZXF1aXJlX18oODQ4MCk7CnZhciBnZXRPd25Qcm9wZXJ0eVN5bWJvbHNNb2R1bGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM3MTcpOwp2YXIgYW5PYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg1NTEpOwoKdmFyIGNvbmNhdCA9IHVuY3VycnlUaGlzKFtdLmNvbmNhdCk7CgovLyBhbGwgb2JqZWN0IGtleXMsIGluY2x1ZGVzIG5vbi1lbnVtZXJhYmxlIGFuZCBzeW1ib2xzCm1vZHVsZS5leHBvcnRzID0gZ2V0QnVpbHRJbignUmVmbGVjdCcsICdvd25LZXlzJykgfHwgZnVuY3Rpb24gb3duS2V5cyhpdCkgewogIHZhciBrZXlzID0gZ2V0T3duUHJvcGVydHlOYW1lc01vZHVsZS5mKGFuT2JqZWN0KGl0KSk7CiAgdmFyIGdldE93blByb3BlcnR5U3ltYm9scyA9IGdldE93blByb3BlcnR5U3ltYm9sc01vZHVsZS5mOwogIHJldHVybiBnZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPyBjb25jYXQoa2V5cywgZ2V0T3duUHJvcGVydHlTeW1ib2xzKGl0KSkgOiBrZXlzOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNTE2OToKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBpc0RldGFjaGVkID0gX193ZWJwYWNrX3JlcXVpcmVfXygzMjM4KTsKCnZhciAkVHlwZUVycm9yID0gVHlwZUVycm9yOwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHsKICBpZiAoaXNEZXRhY2hlZChpdCkpIHRocm93IG5ldyAkVHlwZUVycm9yKCdBcnJheUJ1ZmZlciBpcyBkZXRhY2hlZCcpOwogIHJldHVybiBpdDsKfTsKCgovKioqLyB9KSwKCi8qKiovIDUxNzA6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgdW5jdXJyeVRoaXNBY2Nlc3NvciA9IF9fd2VicGFja19yZXF1aXJlX18oNjcwNik7CnZhciBTZXRIZWxwZXJzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0NDAyKTsKCm1vZHVsZS5leHBvcnRzID0gdW5jdXJyeVRoaXNBY2Nlc3NvcihTZXRIZWxwZXJzLnByb3RvLCAnc2l6ZScsICdnZXQnKSB8fCBmdW5jdGlvbiAoc2V0KSB7CiAgcmV0dXJuIHNldC5zaXplOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNTIxMzoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciBhcnJheUZyb21Db25zdHJ1Y3RvckFuZExpc3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDUzNzApOwp2YXIgJGZyb21CYXNlNjQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDkxNDMpOwoKdmFyIFVpbnQ4QXJyYXkgPSBnbG9iYWxUaGlzLlVpbnQ4QXJyYXk7Cgp2YXIgSU5DT1JSRUNUX0JFSEFWSU9SX09SX0RPRVNOVF9FWElTVFMgPSAhVWludDhBcnJheSB8fCAhVWludDhBcnJheS5mcm9tQmFzZTY0IHx8ICFmdW5jdGlvbiAoKSB7CiAgLy8gV2Via2l0IG5vdCB0aHJvdyBhbiBlcnJvciBvbiBvZGQgbGVuZ3RoIHN0cmluZwogIHRyeSB7CiAgICBVaW50OEFycmF5LmZyb21CYXNlNjQoJ2EnKTsKICAgIHJldHVybjsKICB9IGNhdGNoIChlcnJvcikgeyAvKiBlbXB0eSAqLyB9CiAgdHJ5IHsKICAgIFVpbnQ4QXJyYXkuZnJvbUJhc2U2NCgnJywgbnVsbCk7CiAgfSBjYXRjaCAoZXJyb3IpIHsKICAgIHJldHVybiB0cnVlOwogIH0KfSgpOwoKLy8gYFVpbnQ4QXJyYXkuZnJvbUJhc2U2NGAgbWV0aG9kCi8vIGh0dHBzOi8vZ2l0aHViLmNvbS90YzM5L3Byb3Bvc2FsLWFycmF5YnVmZmVyLWJhc2U2NAppZiAoVWludDhBcnJheSkgJCh7IHRhcmdldDogJ1VpbnQ4QXJyYXknLCBzdGF0OiB0cnVlLCBmb3JjZWQ6IElOQ09SUkVDVF9CRUhBVklPUl9PUl9ET0VTTlRfRVhJU1RTIH0sIHsKICBmcm9tQmFzZTY0OiBmdW5jdGlvbiBmcm9tQmFzZTY0KHN0cmluZyAvKiAsIG9wdGlvbnMgKi8pIHsKICAgIHZhciByZXN1bHQgPSAkZnJvbUJhc2U2NChzdHJpbmcsIGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogdW5kZWZpbmVkLCBudWxsLCAweDFGRkZGRkZGRkZGRkZGKTsKICAgIHJldHVybiBhcnJheUZyb21Db25zdHJ1Y3RvckFuZExpc3QoVWludDhBcnJheSwgcmVzdWx0LmJ5dGVzKTsKICB9Cn0pOwoKCi8qKiovIH0pLAoKLyoqKi8gNTM3MDoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBsZW5ndGhPZkFycmF5TGlrZSA9IF9fd2VicGFja19yZXF1aXJlX18oNjE5OCk7Cgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgbGlzdCwgJGxlbmd0aCkgewogIHZhciBpbmRleCA9IDA7CiAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyID8gJGxlbmd0aCA6IGxlbmd0aE9mQXJyYXlMaWtlKGxpc3QpOwogIHZhciByZXN1bHQgPSBuZXcgQ29uc3RydWN0b3IobGVuZ3RoKTsKICB3aGlsZSAobGVuZ3RoID4gaW5kZXgpIHJlc3VsdFtpbmRleF0gPSBsaXN0W2luZGV4KytdOwogIHJldHVybiByZXN1bHQ7Cn07CgoKLyoqKi8gfSksCgovKioqLyA1Mzk3OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKLy8gdG9PYmplY3Qgd2l0aCBmYWxsYmFjayBmb3Igbm9uLWFycmF5LWxpa2UgRVMzIHN0cmluZ3MKdmFyIEluZGV4ZWRPYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDcwNTUpOwp2YXIgcmVxdWlyZU9iamVjdENvZXJjaWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oNzc1MCk7Cgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkgewogIHJldHVybiBJbmRleGVkT2JqZWN0KHJlcXVpcmVPYmplY3RDb2VyY2libGUoaXQpKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDU2MTA6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgdG9JbnRlZ2VyT3JJbmZpbml0eSA9IF9fd2VicGFja19yZXF1aXJlX18oMTI5MSk7Cgp2YXIgbWF4ID0gTWF0aC5tYXg7CnZhciBtaW4gPSBNYXRoLm1pbjsKCi8vIEhlbHBlciBmb3IgYSBwb3B1bGFyIHJlcGVhdGluZyBjYXNlIG9mIHRoZSBzcGVjOgovLyBMZXQgaW50ZWdlciBiZSA/IFRvSW50ZWdlcihpbmRleCkuCi8vIElmIGludGVnZXIgPCAwLCBsZXQgcmVzdWx0IGJlIG1heCgobGVuZ3RoICsgaW50ZWdlciksIDApOyBlbHNlIGxldCByZXN1bHQgYmUgbWluKGludGVnZXIsIGxlbmd0aCkuCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGluZGV4LCBsZW5ndGgpIHsKICB2YXIgaW50ZWdlciA9IHRvSW50ZWdlck9ySW5maW5pdHkoaW5kZXgpOwogIHJldHVybiBpbnRlZ2VyIDwgMCA/IG1heChpbnRlZ2VyICsgbGVuZ3RoLCAwKSA6IG1pbihpbnRlZ2VyLCBsZW5ndGgpOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNTYyMzoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKLy8gVE9ETzogUmVtb3ZlIGZyb20gYGNvcmUtanNANGAKX193ZWJwYWNrX3JlcXVpcmVfXyg0NTYpOwoKCi8qKiovIH0pLAoKLyoqKi8gNTYzNjoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBnbG9iYWxUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0NTc2KTsKdmFyIHVuY3VycnlUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTA0KTsKdmFyIHVuY3VycnlUaGlzQWNjZXNzb3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY3MDYpOwp2YXIgdG9JbmRleCA9IF9fd2VicGFja19yZXF1aXJlX18oNzY5Nik7CnZhciBub3REZXRhY2hlZCA9IF9fd2VicGFja19yZXF1aXJlX18oNTE2OSk7CnZhciBhcnJheUJ1ZmZlckJ5dGVMZW5ndGggPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDczOTQpOwp2YXIgZGV0YWNoVHJhbnNmZXJhYmxlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0NDgzKTsKdmFyIFBST1BFUl9TVFJVQ1RVUkVEX0NMT05FX1RSQU5TRkVSID0gX193ZWJwYWNrX3JlcXVpcmVfXygxNTQ4KTsKCnZhciBzdHJ1Y3R1cmVkQ2xvbmUgPSBnbG9iYWxUaGlzLnN0cnVjdHVyZWRDbG9uZTsKdmFyIEFycmF5QnVmZmVyID0gZ2xvYmFsVGhpcy5BcnJheUJ1ZmZlcjsKdmFyIERhdGFWaWV3ID0gZ2xvYmFsVGhpcy5EYXRhVmlldzsKdmFyIG1pbiA9IE1hdGgubWluOwp2YXIgQXJyYXlCdWZmZXJQcm90b3R5cGUgPSBBcnJheUJ1ZmZlci5wcm90b3R5cGU7CnZhciBEYXRhVmlld1Byb3RvdHlwZSA9IERhdGFWaWV3LnByb3RvdHlwZTsKdmFyIHNsaWNlID0gdW5jdXJyeVRoaXMoQXJyYXlCdWZmZXJQcm90b3R5cGUuc2xpY2UpOwp2YXIgaXNSZXNpemFibGUgPSB1bmN1cnJ5VGhpc0FjY2Vzc29yKEFycmF5QnVmZmVyUHJvdG90eXBlLCAncmVzaXphYmxlJywgJ2dldCcpOwp2YXIgbWF4Qnl0ZUxlbmd0aCA9IHVuY3VycnlUaGlzQWNjZXNzb3IoQXJyYXlCdWZmZXJQcm90b3R5cGUsICdtYXhCeXRlTGVuZ3RoJywgJ2dldCcpOwp2YXIgZ2V0SW50OCA9IHVuY3VycnlUaGlzKERhdGFWaWV3UHJvdG90eXBlLmdldEludDgpOwp2YXIgc2V0SW50OCA9IHVuY3VycnlUaGlzKERhdGFWaWV3UHJvdG90eXBlLnNldEludDgpOwoKbW9kdWxlLmV4cG9ydHMgPSAoUFJPUEVSX1NUUlVDVFVSRURfQ0xPTkVfVFJBTlNGRVIgfHwgZGV0YWNoVHJhbnNmZXJhYmxlKSAmJiBmdW5jdGlvbiAoYXJyYXlCdWZmZXIsIG5ld0xlbmd0aCwgcHJlc2VydmVSZXNpemFiaWxpdHkpIHsKICB2YXIgYnl0ZUxlbmd0aCA9IGFycmF5QnVmZmVyQnl0ZUxlbmd0aChhcnJheUJ1ZmZlcik7CiAgdmFyIG5ld0J5dGVMZW5ndGggPSBuZXdMZW5ndGggPT09IHVuZGVmaW5lZCA/IGJ5dGVMZW5ndGggOiB0b0luZGV4KG5ld0xlbmd0aCk7CiAgdmFyIGZpeGVkTGVuZ3RoID0gIWlzUmVzaXphYmxlIHx8ICFpc1Jlc2l6YWJsZShhcnJheUJ1ZmZlcik7CiAgdmFyIG5ld0J1ZmZlcjsKICBub3REZXRhY2hlZChhcnJheUJ1ZmZlcik7CiAgaWYgKFBST1BFUl9TVFJVQ1RVUkVEX0NMT05FX1RSQU5TRkVSKSB7CiAgICBhcnJheUJ1ZmZlciA9IHN0cnVjdHVyZWRDbG9uZShhcnJheUJ1ZmZlciwgeyB0cmFuc2ZlcjogW2FycmF5QnVmZmVyXSB9KTsKICAgIGlmIChieXRlTGVuZ3RoID09PSBuZXdCeXRlTGVuZ3RoICYmIChwcmVzZXJ2ZVJlc2l6YWJpbGl0eSB8fCBmaXhlZExlbmd0aCkpIHJldHVybiBhcnJheUJ1ZmZlcjsKICB9CiAgaWYgKGJ5dGVMZW5ndGggPj0gbmV3Qnl0ZUxlbmd0aCAmJiAoIXByZXNlcnZlUmVzaXphYmlsaXR5IHx8IGZpeGVkTGVuZ3RoKSkgewogICAgbmV3QnVmZmVyID0gc2xpY2UoYXJyYXlCdWZmZXIsIDAsIG5ld0J5dGVMZW5ndGgpOwogIH0gZWxzZSB7CiAgICB2YXIgb3B0aW9ucyA9IHByZXNlcnZlUmVzaXphYmlsaXR5ICYmICFmaXhlZExlbmd0aCAmJiBtYXhCeXRlTGVuZ3RoID8geyBtYXhCeXRlTGVuZ3RoOiBtYXhCeXRlTGVuZ3RoKGFycmF5QnVmZmVyKSB9IDogdW5kZWZpbmVkOwogICAgbmV3QnVmZmVyID0gbmV3IEFycmF5QnVmZmVyKG5ld0J5dGVMZW5ndGgsIG9wdGlvbnMpOwogICAgdmFyIGEgPSBuZXcgRGF0YVZpZXcoYXJyYXlCdWZmZXIpOwogICAgdmFyIGIgPSBuZXcgRGF0YVZpZXcobmV3QnVmZmVyKTsKICAgIHZhciBjb3B5TGVuZ3RoID0gbWluKG5ld0J5dGVMZW5ndGgsIGJ5dGVMZW5ndGgpOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3B5TGVuZ3RoOyBpKyspIHNldEludDgoYiwgaSwgZ2V0SW50OChhLCBpKSk7CiAgfQogIGlmICghUFJPUEVSX1NUUlVDVFVSRURfQ0xPTkVfVFJBTlNGRVIpIGRldGFjaFRyYW5zZmVyYWJsZShhcnJheUJ1ZmZlcik7CiAgcmV0dXJuIG5ld0J1ZmZlcjsKfTsKCgovKioqLyB9KSwKCi8qKiovIDU3NDU6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgc3RvcmUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDc2MjkpOwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkgewogIHJldHVybiBzdG9yZVtrZXldIHx8IChzdG9yZVtrZXldID0gdmFsdWUgfHwge30pOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNTc4MToKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgZ2V0QnVpbHRJbiA9IF9fd2VicGFja19yZXF1aXJlX18oNzc1MSk7CnZhciB2YWxpZGF0ZUFyZ3VtZW50c0xlbmd0aCA9IF9fd2VicGFja19yZXF1aXJlX18oMjgxMik7CnZhciB0b1N0cmluZyA9IF9fd2VicGFja19yZXF1aXJlX18oNjU1KTsKdmFyIFVTRV9OQVRJVkVfVVJMID0gX193ZWJwYWNrX3JlcXVpcmVfXyg3NDE2KTsKCnZhciBVUkwgPSBnZXRCdWlsdEluKCdVUkwnKTsKCi8vIGBVUkwucGFyc2VgIG1ldGhvZAovLyBodHRwczovL3VybC5zcGVjLndoYXR3Zy5vcmcvI2RvbS11cmwtY2FucGFyc2UKJCh7IHRhcmdldDogJ1VSTCcsIHN0YXQ6IHRydWUsIGZvcmNlZDogIVVTRV9OQVRJVkVfVVJMIH0sIHsKICBwYXJzZTogZnVuY3Rpb24gcGFyc2UodXJsKSB7CiAgICB2YXIgbGVuZ3RoID0gdmFsaWRhdGVBcmd1bWVudHNMZW5ndGgoYXJndW1lbnRzLmxlbmd0aCwgMSk7CiAgICB2YXIgdXJsU3RyaW5nID0gdG9TdHJpbmcodXJsKTsKICAgIHZhciBiYXNlID0gbGVuZ3RoIDwgMiB8fCBhcmd1bWVudHNbMV0gPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IHRvU3RyaW5nKGFyZ3VtZW50c1sxXSk7CiAgICB0cnkgewogICAgICByZXR1cm4gbmV3IFVSTCh1cmxTdHJpbmcsIGJhc2UpOwogICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgfQp9KTsKCgovKioqLyB9KSwKCi8qKiovIDU4NTQ6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgdG9QcmltaXRpdmUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDI3NzcpOwoKdmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7CgovLyBgVG9CaWdJbnRgIGFic3RyYWN0IG9wZXJhdGlvbgovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXRvYmlnaW50Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiAgdmFyIHByaW0gPSB0b1ByaW1pdGl2ZShhcmd1bWVudCwgJ251bWJlcicpOwogIGlmICh0eXBlb2YgcHJpbSA9PSAnbnVtYmVyJykgdGhyb3cgbmV3ICRUeXBlRXJyb3IoIkNhbid0IGNvbnZlcnQgbnVtYmVyIHRvIGJpZ2ludCIpOwogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1iaWdpbnQgLS0gc2FmZQogIHJldHVybiBCaWdJbnQocHJpbSk7Cn07CgoKLyoqKi8gfSksCgovKioqLyA1ODc2OgovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgJCA9IF9fd2VicGFja19yZXF1aXJlX18oNjUxOCk7CnZhciBpc1N1YnNldE9mID0gX193ZWJwYWNrX3JlcXVpcmVfXygzODM4KTsKdmFyIHNldE1ldGhvZEFjY2VwdFNldExpa2UgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MTYpOwoKdmFyIElOQ09SUkVDVCA9ICFzZXRNZXRob2RBY2NlcHRTZXRMaWtlKCdpc1N1YnNldE9mJywgZnVuY3Rpb24gKHJlc3VsdCkgewogIHJldHVybiByZXN1bHQ7Cn0pOwoKLy8gYFNldC5wcm90b3R5cGUuaXNTdWJzZXRPZmAgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc2V0LnByb3RvdHlwZS5pc3N1YnNldG9mCiQoeyB0YXJnZXQ6ICdTZXQnLCBwcm90bzogdHJ1ZSwgcmVhbDogdHJ1ZSwgZm9yY2VkOiBJTkNPUlJFQ1QgfSwgewogIGlzU3Vic2V0T2Y6IGlzU3Vic2V0T2YKfSk7CgoKLyoqKi8gfSksCgovKioqLyA1OTE3OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIERFU0NSSVBUT1JTID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNzI0KTsKdmFyIGZhaWxzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5MDM5KTsKdmFyIGNyZWF0ZUVsZW1lbnQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQwNTUpOwoKLy8gVGhhbmtzIHRvIElFOCBmb3IgaXRzIGZ1bm55IGRlZmluZVByb3BlcnR5Cm1vZHVsZS5leHBvcnRzID0gIURFU0NSSVBUT1JTICYmICFmYWlscyhmdW5jdGlvbiAoKSB7CiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1kZWZpbmVwcm9wZXJ0eSAtLSByZXF1aXJlZCBmb3IgdGVzdGluZwogIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoY3JlYXRlRWxlbWVudCgnZGl2JyksICdhJywgewogICAgZ2V0OiBmdW5jdGlvbiAoKSB7IHJldHVybiA3OyB9CiAgfSkuYSAhPT0gNzsKfSk7CgoKLyoqKi8gfSksCgovKioqLyA1OTY2OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGFDYWxsYWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oOTMwNik7CnZhciBpc051bGxPclVuZGVmaW5lZCA9IF9fd2VicGFja19yZXF1aXJlX18oNDExNyk7CgovLyBgR2V0TWV0aG9kYCBhYnN0cmFjdCBvcGVyYXRpb24KLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1nZXRtZXRob2QKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoViwgUCkgewogIHZhciBmdW5jID0gVltQXTsKICByZXR1cm4gaXNOdWxsT3JVbmRlZmluZWQoZnVuYykgPyB1bmRlZmluZWQgOiBhQ2FsbGFibGUoZnVuYyk7Cn07CgoKLyoqKi8gfSksCgovKioqLyA2MDQzOgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGFDYWxsYWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oOTMwNik7Cgp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKCnZhciBQcm9taXNlQ2FwYWJpbGl0eSA9IGZ1bmN0aW9uIChDKSB7CiAgdmFyIHJlc29sdmUsIHJlamVjdDsKICB0aGlzLnByb21pc2UgPSBuZXcgQyhmdW5jdGlvbiAoJCRyZXNvbHZlLCAkJHJlamVjdCkgewogICAgaWYgKHJlc29sdmUgIT09IHVuZGVmaW5lZCB8fCByZWplY3QgIT09IHVuZGVmaW5lZCkgdGhyb3cgbmV3ICRUeXBlRXJyb3IoJ0JhZCBQcm9taXNlIGNvbnN0cnVjdG9yJyk7CiAgICByZXNvbHZlID0gJCRyZXNvbHZlOwogICAgcmVqZWN0ID0gJCRyZWplY3Q7CiAgfSk7CiAgdGhpcy5yZXNvbHZlID0gYUNhbGxhYmxlKHJlc29sdmUpOwogIHRoaXMucmVqZWN0ID0gYUNhbGxhYmxlKHJlamVjdCk7Cn07CgovLyBgTmV3UHJvbWlzZUNhcGFiaWxpdHlgIGFic3RyYWN0IG9wZXJhdGlvbgovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW5ld3Byb21pc2VjYXBhYmlsaXR5Cm1vZHVsZS5leHBvcnRzLmYgPSBmdW5jdGlvbiAoQykgewogIHJldHVybiBuZXcgUHJvbWlzZUNhcGFiaWxpdHkoQyk7Cn07CgoKLyoqKi8gfSksCgovKioqLyA2MDgwOgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIHVuY3VycnlUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg3NDc2KTsKdmFyIGFDYWxsYWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oOTMwNik7CnZhciBOQVRJVkVfQklORCA9IF9fd2VicGFja19yZXF1aXJlX18oNjE2KTsKCnZhciBiaW5kID0gdW5jdXJyeVRoaXModW5jdXJyeVRoaXMuYmluZCk7CgovLyBvcHRpb25hbCAvIHNpbXBsZSBjb250ZXh0IGJpbmRpbmcKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZm4sIHRoYXQpIHsKICBhQ2FsbGFibGUoZm4pOwogIHJldHVybiB0aGF0ID09PSB1bmRlZmluZWQgPyBmbiA6IE5BVElWRV9CSU5EID8gYmluZChmbiwgdGhhdCkgOiBmdW5jdGlvbiAoLyogLi4uYXJncyAqLykgewogICAgcmV0dXJuIGZuLmFwcGx5KHRoYXQsIGFyZ3VtZW50cyk7CiAgfTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDYxMTk6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgc2hhcmVkID0gX193ZWJwYWNrX3JlcXVpcmVfXyg1NzQ1KTsKdmFyIHVpZCA9IF9fd2VicGFja19yZXF1aXJlX18oMzM5Mik7Cgp2YXIga2V5cyA9IHNoYXJlZCgna2V5cycpOwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoa2V5KSB7CiAgcmV0dXJuIGtleXNba2V5XSB8fCAoa2V5c1trZXldID0gdWlkKGtleSkpOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNjE5MzoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBFTlZJUk9OTUVOVCA9IF9fd2VicGFja19yZXF1aXJlX18oNDIxNSk7Cgptb2R1bGUuZXhwb3J0cyA9IEVOVklST05NRU5UID09PSAnTk9ERSc7CgoKLyoqKi8gfSksCgovKioqLyA2MTk4OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIHRvTGVuZ3RoID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4MDE0KTsKCi8vIGBMZW5ndGhPZkFycmF5TGlrZWAgYWJzdHJhY3Qgb3BlcmF0aW9uCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtbGVuZ3Rob2ZhcnJheWxpa2UKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqKSB7CiAgcmV0dXJuIHRvTGVuZ3RoKG9iai5sZW5ndGgpOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNjI2OToKLyoqKi8gKChtb2R1bGUpID0+IHsKCgptb2R1bGUuZXhwb3J0cyA9IHt9OwoKCi8qKiovIH0pLAoKLyoqKi8gNjI3OToKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBkZWZpbmVCdWlsdEluID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2ODQwKTsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHRhcmdldCwgc3JjLCBvcHRpb25zKSB7CiAgZm9yICh2YXIga2V5IGluIHNyYykgZGVmaW5lQnVpbHRJbih0YXJnZXQsIGtleSwgc3JjW2tleV0sIG9wdGlvbnMpOwogIHJldHVybiB0YXJnZXQ7Cn07CgoKLyoqKi8gfSksCgovKioqLyA2MzE5OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGFuT2JqZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4NTUxKTsKdmFyIGl0ZXJhdG9yQ2xvc2UgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1MzkpOwoKLy8gY2FsbCBzb21ldGhpbmcgb24gaXRlcmF0b3Igc3RlcCB3aXRoIHNhZmUgY2xvc2luZyBvbiBlcnJvcgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdGVyYXRvciwgZm4sIHZhbHVlLCBFTlRSSUVTKSB7CiAgdHJ5IHsKICAgIHJldHVybiBFTlRSSUVTID8gZm4oYW5PYmplY3QodmFsdWUpWzBdLCB2YWx1ZVsxXSkgOiBmbih2YWx1ZSk7CiAgfSBjYXRjaCAoZXJyb3IpIHsKICAgIGl0ZXJhdG9yQ2xvc2UoaXRlcmF0b3IsICd0aHJvdycsIGVycm9yKTsKICB9Cn07CgoKLyoqKi8gfSksCgovKioqLyA2Mzk1OgovKioqLyAoKG1vZHVsZSkgPT4gewoKCm1vZHVsZS5leHBvcnRzID0gZmFsc2U7CgoKLyoqKi8gfSksCgovKioqLyA2NTE4OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGdsb2JhbFRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ1NzYpOwp2YXIgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID0gKF9fd2VicGFja19yZXF1aXJlX18oNzM0NykuZik7CnZhciBjcmVhdGVOb25FbnVtZXJhYmxlUHJvcGVydHkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY2OTkpOwp2YXIgZGVmaW5lQnVpbHRJbiA9IF9fd2VicGFja19yZXF1aXJlX18oNjg0MCk7CnZhciBkZWZpbmVHbG9iYWxQcm9wZXJ0eSA9IF9fd2VicGFja19yZXF1aXJlX18oOTQzMyk7CnZhciBjb3B5Q29uc3RydWN0b3JQcm9wZXJ0aWVzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg3NzQwKTsKdmFyIGlzRm9yY2VkID0gX193ZWJwYWNrX3JlcXVpcmVfXygyNzk2KTsKCi8qCiAgb3B0aW9ucy50YXJnZXQgICAgICAgICAtIG5hbWUgb2YgdGhlIHRhcmdldCBvYmplY3QKICBvcHRpb25zLmdsb2JhbCAgICAgICAgIC0gdGFyZ2V0IGlzIHRoZSBnbG9iYWwgb2JqZWN0CiAgb3B0aW9ucy5zdGF0ICAgICAgICAgICAtIGV4cG9ydCBhcyBzdGF0aWMgbWV0aG9kcyBvZiB0YXJnZXQKICBvcHRpb25zLnByb3RvICAgICAgICAgIC0gZXhwb3J0IGFzIHByb3RvdHlwZSBtZXRob2RzIG9mIHRhcmdldAogIG9wdGlvbnMucmVhbCAgICAgICAgICAgLSByZWFsIHByb3RvdHlwZSBtZXRob2QgZm9yIHRoZSBgcHVyZWAgdmVyc2lvbgogIG9wdGlvbnMuZm9yY2VkICAgICAgICAgLSBleHBvcnQgZXZlbiBpZiB0aGUgbmF0aXZlIGZlYXR1cmUgaXMgYXZhaWxhYmxlCiAgb3B0aW9ucy5iaW5kICAgICAgICAgICAtIGJpbmQgbWV0aG9kcyB0byB0aGUgdGFyZ2V0LCByZXF1aXJlZCBmb3IgdGhlIGBwdXJlYCB2ZXJzaW9uCiAgb3B0aW9ucy53cmFwICAgICAgICAgICAtIHdyYXAgY29uc3RydWN0b3JzIHRvIHByZXZlbnRpbmcgZ2xvYmFsIHBvbGx1dGlvbiwgcmVxdWlyZWQgZm9yIHRoZSBgcHVyZWAgdmVyc2lvbgogIG9wdGlvbnMudW5zYWZlICAgICAgICAgLSB1c2UgdGhlIHNpbXBsZSBhc3NpZ25tZW50IG9mIHByb3BlcnR5IGluc3RlYWQgb2YgZGVsZXRlICsgZGVmaW5lUHJvcGVydHkKICBvcHRpb25zLnNoYW0gICAgICAgICAgIC0gYWRkIGEgZmxhZyB0byBub3QgY29tcGxldGVseSBmdWxsIHBvbHlmaWxscwogIG9wdGlvbnMuZW51bWVyYWJsZSAgICAgLSBleHBvcnQgYXMgZW51bWVyYWJsZSBwcm9wZXJ0eQogIG9wdGlvbnMuZG9udENhbGxHZXRTZXQgLSBwcmV2ZW50IGNhbGxpbmcgYSBnZXR0ZXIgb24gdGFyZ2V0CiAgb3B0aW9ucy5uYW1lICAgICAgICAgICAtIHRoZSAubmFtZSBvZiB0aGUgZnVuY3Rpb24gaWYgaXQgZG9lcyBub3QgbWF0Y2ggdGhlIGtleQoqLwptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvcHRpb25zLCBzb3VyY2UpIHsKICB2YXIgVEFSR0VUID0gb3B0aW9ucy50YXJnZXQ7CiAgdmFyIEdMT0JBTCA9IG9wdGlvbnMuZ2xvYmFsOwogIHZhciBTVEFUSUMgPSBvcHRpb25zLnN0YXQ7CiAgdmFyIEZPUkNFRCwgdGFyZ2V0LCBrZXksIHRhcmdldFByb3BlcnR5LCBzb3VyY2VQcm9wZXJ0eSwgZGVzY3JpcHRvcjsKICBpZiAoR0xPQkFMKSB7CiAgICB0YXJnZXQgPSBnbG9iYWxUaGlzOwogIH0gZWxzZSBpZiAoU1RBVElDKSB7CiAgICB0YXJnZXQgPSBnbG9iYWxUaGlzW1RBUkdFVF0gfHwgZGVmaW5lR2xvYmFsUHJvcGVydHkoVEFSR0VULCB7fSk7CiAgfSBlbHNlIHsKICAgIHRhcmdldCA9IGdsb2JhbFRoaXNbVEFSR0VUXSAmJiBnbG9iYWxUaGlzW1RBUkdFVF0ucHJvdG90eXBlOwogIH0KICBpZiAodGFyZ2V0KSBmb3IgKGtleSBpbiBzb3VyY2UpIHsKICAgIHNvdXJjZVByb3BlcnR5ID0gc291cmNlW2tleV07CiAgICBpZiAob3B0aW9ucy5kb250Q2FsbEdldFNldCkgewogICAgICBkZXNjcmlwdG9yID0gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KTsKICAgICAgdGFyZ2V0UHJvcGVydHkgPSBkZXNjcmlwdG9yICYmIGRlc2NyaXB0b3IudmFsdWU7CiAgICB9IGVsc2UgdGFyZ2V0UHJvcGVydHkgPSB0YXJnZXRba2V5XTsKICAgIEZPUkNFRCA9IGlzRm9yY2VkKEdMT0JBTCA/IGtleSA6IFRBUkdFVCArIChTVEFUSUMgPyAnLicgOiAnIycpICsga2V5LCBvcHRpb25zLmZvcmNlZCk7CiAgICAvLyBjb250YWluZWQgaW4gdGFyZ2V0CiAgICBpZiAoIUZPUkNFRCAmJiB0YXJnZXRQcm9wZXJ0eSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIGlmICh0eXBlb2Ygc291cmNlUHJvcGVydHkgPT0gdHlwZW9mIHRhcmdldFByb3BlcnR5KSBjb250aW51ZTsKICAgICAgY29weUNvbnN0cnVjdG9yUHJvcGVydGllcyhzb3VyY2VQcm9wZXJ0eSwgdGFyZ2V0UHJvcGVydHkpOwogICAgfQogICAgLy8gYWRkIGEgZmxhZyB0byBub3QgY29tcGxldGVseSBmdWxsIHBvbHlmaWxscwogICAgaWYgKG9wdGlvbnMuc2hhbSB8fCAodGFyZ2V0UHJvcGVydHkgJiYgdGFyZ2V0UHJvcGVydHkuc2hhbSkpIHsKICAgICAgY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KHNvdXJjZVByb3BlcnR5LCAnc2hhbScsIHRydWUpOwogICAgfQogICAgZGVmaW5lQnVpbHRJbih0YXJnZXQsIGtleSwgc291cmNlUHJvcGVydHksIG9wdGlvbnMpOwogIH0KfTsKCgovKioqLyB9KSwKCi8qKiovIDY1NzM6Ci8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBERVNDUklQVE9SUyA9IF9fd2VicGFja19yZXF1aXJlX18oMzcyNCk7CnZhciBkZWZpbmVCdWlsdEluQWNjZXNzb3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDIxMDYpOwp2YXIgaXNEZXRhY2hlZCA9IF9fd2VicGFja19yZXF1aXJlX18oMzIzOCk7Cgp2YXIgQXJyYXlCdWZmZXJQcm90b3R5cGUgPSBBcnJheUJ1ZmZlci5wcm90b3R5cGU7CgovLyBgQXJyYXlCdWZmZXIucHJvdG90eXBlLmRldGFjaGVkYCBnZXR0ZXIKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1nZXQtYXJyYXlidWZmZXIucHJvdG90eXBlLmRldGFjaGVkCmlmIChERVNDUklQVE9SUyAmJiAhKCdkZXRhY2hlZCcgaW4gQXJyYXlCdWZmZXJQcm90b3R5cGUpKSB7CiAgZGVmaW5lQnVpbHRJbkFjY2Vzc29yKEFycmF5QnVmZmVyUHJvdG90eXBlLCAnZGV0YWNoZWQnLCB7CiAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICBnZXQ6IGZ1bmN0aW9uIGRldGFjaGVkKCkgewogICAgICByZXR1cm4gaXNEZXRhY2hlZCh0aGlzKTsKICAgIH0KICB9KTsKfQoKCi8qKiovIH0pLAoKLyoqKi8gNjYzMjoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciAkZnJvbUJhc2U2NCA9IF9fd2VicGFja19yZXF1aXJlX18oOTE0Myk7CnZhciBhblVpbnQ4QXJyYXkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQxNTQpOwoKdmFyIFVpbnQ4QXJyYXkgPSBnbG9iYWxUaGlzLlVpbnQ4QXJyYXk7Cgp2YXIgSU5DT1JSRUNUX0JFSEFWSU9SX09SX0RPRVNOVF9FWElTVFMgPSAhVWludDhBcnJheSB8fCAhVWludDhBcnJheS5wcm90b3R5cGUuc2V0RnJvbUJhc2U2NCB8fCAhZnVuY3Rpb24gKCkgewogIHZhciB0YXJnZXQgPSBuZXcgVWludDhBcnJheShbMjU1LCAyNTUsIDI1NSwgMjU1LCAyNTVdKTsKICB0cnkgewogICAgdGFyZ2V0LnNldEZyb21CYXNlNjQoJycsIG51bGwpOwogICAgcmV0dXJuOwogIH0gY2F0Y2ggKGVycm9yKSB7IC8qIGVtcHR5ICovIH0KICAvLyBXZWJraXQgbm90IHRocm93IGFuIGVycm9yIG9uIG9kZCBsZW5ndGggc3RyaW5nCiAgdHJ5IHsKICAgIHRhcmdldC5zZXRGcm9tQmFzZTY0KCdhJyk7CiAgICByZXR1cm47CiAgfSBjYXRjaCAoZXJyb3IpIHsgLyogZW1wdHkgKi8gfQogIHRyeSB7CiAgICB0YXJnZXQuc2V0RnJvbUJhc2U2NCgnTWpZeVpnPT09Jyk7CiAgfSBjYXRjaCAoZXJyb3IpIHsKICAgIHJldHVybiB0YXJnZXRbMF0gPT09IDUwICYmIHRhcmdldFsxXSA9PT0gNTQgJiYgdGFyZ2V0WzJdID09PSA1MCAmJiB0YXJnZXRbM10gPT09IDI1NSAmJiB0YXJnZXRbNF0gPT09IDI1NTsKICB9Cn0oKTsKCi8vIGBVaW50OEFycmF5LnByb3RvdHlwZS5zZXRGcm9tQmFzZTY0YCBtZXRob2QKLy8gaHR0cHM6Ly9naXRodWIuY29tL3RjMzkvcHJvcG9zYWwtYXJyYXlidWZmZXItYmFzZTY0CmlmIChVaW50OEFycmF5KSAkKHsgdGFyZ2V0OiAnVWludDhBcnJheScsIHByb3RvOiB0cnVlLCBmb3JjZWQ6IElOQ09SUkVDVF9CRUhBVklPUl9PUl9ET0VTTlRfRVhJU1RTIH0sIHsKICBzZXRGcm9tQmFzZTY0OiBmdW5jdGlvbiBzZXRGcm9tQmFzZTY0KHN0cmluZyAvKiAsIG9wdGlvbnMgKi8pIHsKICAgIGFuVWludDhBcnJheSh0aGlzKTsKCiAgICB2YXIgcmVzdWx0ID0gJGZyb21CYXNlNjQoc3RyaW5nLCBhcmd1bWVudHMubGVuZ3RoID4gMSA/IGFyZ3VtZW50c1sxXSA6IHVuZGVmaW5lZCwgdGhpcywgdGhpcy5sZW5ndGgpOwoKICAgIHJldHVybiB7IHJlYWQ6IHJlc3VsdC5yZWFkLCB3cml0dGVuOiByZXN1bHQud3JpdHRlbiB9OwogIH0KfSk7CgoKLyoqKi8gfSksCgovKioqLyA2Njk5OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIERFU0NSSVBUT1JTID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNzI0KTsKdmFyIGRlZmluZVByb3BlcnR5TW9kdWxlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0OTEzKTsKdmFyIGNyZWF0ZVByb3BlcnR5RGVzY3JpcHRvciA9IF9fd2VicGFja19yZXF1aXJlX18oNjk4MCk7Cgptb2R1bGUuZXhwb3J0cyA9IERFU0NSSVBUT1JTID8gZnVuY3Rpb24gKG9iamVjdCwga2V5LCB2YWx1ZSkgewogIHJldHVybiBkZWZpbmVQcm9wZXJ0eU1vZHVsZS5mKG9iamVjdCwga2V5LCBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IoMSwgdmFsdWUpKTsKfSA6IGZ1bmN0aW9uIChvYmplY3QsIGtleSwgdmFsdWUpIHsKICBvYmplY3Rba2V5XSA9IHZhbHVlOwogIHJldHVybiBvYmplY3Q7Cn07CgoKLyoqKi8gfSksCgovKioqLyA2NzA2OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIHVuY3VycnlUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTA0KTsKdmFyIGFDYWxsYWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oOTMwNik7Cgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmplY3QsIGtleSwgbWV0aG9kKSB7CiAgdHJ5IHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZ2V0b3ducHJvcGVydHlkZXNjcmlwdG9yIC0tIHNhZmUKICAgIHJldHVybiB1bmN1cnJ5VGhpcyhhQ2FsbGFibGUoT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIGtleSlbbWV0aG9kXSkpOwogIH0gY2F0Y2ggKGVycm9yKSB7IC8qIGVtcHR5ICovIH0KfTsKCgovKioqLyB9KSwKCi8qKiovIDY4MDE6Ci8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgREVTQ1JJUFRPUlMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM3MjQpOwp2YXIgVjhfUFJPVE9UWVBFX0RFRklORV9CVUcgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg2ODYpOwp2YXIgZGVmaW5lUHJvcGVydHlNb2R1bGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MTMpOwp2YXIgYW5PYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg1NTEpOwp2YXIgdG9JbmRleGVkT2JqZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg1Mzk3KTsKdmFyIG9iamVjdEtleXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDEwNzIpOwoKLy8gYE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzYCBtZXRob2QKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1vYmplY3QuZGVmaW5lcHJvcGVydGllcwovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tb2JqZWN0LWRlZmluZXByb3BlcnRpZXMgLS0gc2FmZQpleHBvcnRzLmYgPSBERVNDUklQVE9SUyAmJiAhVjhfUFJPVE9UWVBFX0RFRklORV9CVUcgPyBPYmplY3QuZGVmaW5lUHJvcGVydGllcyA6IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXMoTywgUHJvcGVydGllcykgewogIGFuT2JqZWN0KE8pOwogIHZhciBwcm9wcyA9IHRvSW5kZXhlZE9iamVjdChQcm9wZXJ0aWVzKTsKICB2YXIga2V5cyA9IG9iamVjdEtleXMoUHJvcGVydGllcyk7CiAgdmFyIGxlbmd0aCA9IGtleXMubGVuZ3RoOwogIHZhciBpbmRleCA9IDA7CiAgdmFyIGtleTsKICB3aGlsZSAobGVuZ3RoID4gaW5kZXgpIGRlZmluZVByb3BlcnR5TW9kdWxlLmYoTywga2V5ID0ga2V5c1tpbmRleCsrXSwgcHJvcHNba2V5XSk7CiAgcmV0dXJuIE87Cn07CgoKLyoqKi8gfSksCgovKioqLyA2ODIzOgovKioqLyAoKG1vZHVsZSkgPT4gewoKCnZhciAkU3RyaW5nID0gU3RyaW5nOwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHsKICB0cnkgewogICAgcmV0dXJuICRTdHJpbmcoYXJndW1lbnQpOwogIH0gY2F0Y2ggKGVycm9yKSB7CiAgICByZXR1cm4gJ09iamVjdCc7CiAgfQp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNjgzNzoKLyoqKi8gKChtb2R1bGUpID0+IHsKCgp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKdmFyIE1BWF9TQUZFX0lOVEVHRVIgPSAweDFGRkZGRkZGRkZGRkZGOyAvLyAyICoqIDUzIC0gMSA9PSA5MDA3MTk5MjU0NzQwOTkxCgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkgewogIGlmIChpdCA+IE1BWF9TQUZFX0lOVEVHRVIpIHRocm93ICRUeXBlRXJyb3IoJ01heGltdW0gYWxsb3dlZCBpbmRleCBleGNlZWRlZCcpOwogIHJldHVybiBpdDsKfTsKCgovKioqLyB9KSwKCi8qKiovIDY4NDA6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgaXNDYWxsYWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oNDkwMSk7CnZhciBkZWZpbmVQcm9wZXJ0eU1vZHVsZSA9IF9fd2VicGFja19yZXF1aXJlX18oNDkxMyk7CnZhciBtYWtlQnVpbHRJbiA9IF9fd2VicGFja19yZXF1aXJlX18oMjgzKTsKdmFyIGRlZmluZUdsb2JhbFByb3BlcnR5ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NDMzKTsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKE8sIGtleSwgdmFsdWUsIG9wdGlvbnMpIHsKICBpZiAoIW9wdGlvbnMpIG9wdGlvbnMgPSB7fTsKICB2YXIgc2ltcGxlID0gb3B0aW9ucy5lbnVtZXJhYmxlOwogIHZhciBuYW1lID0gb3B0aW9ucy5uYW1lICE9PSB1bmRlZmluZWQgPyBvcHRpb25zLm5hbWUgOiBrZXk7CiAgaWYgKGlzQ2FsbGFibGUodmFsdWUpKSBtYWtlQnVpbHRJbih2YWx1ZSwgbmFtZSwgb3B0aW9ucyk7CiAgaWYgKG9wdGlvbnMuZ2xvYmFsKSB7CiAgICBpZiAoc2ltcGxlKSBPW2tleV0gPSB2YWx1ZTsKICAgIGVsc2UgZGVmaW5lR2xvYmFsUHJvcGVydHkoa2V5LCB2YWx1ZSk7CiAgfSBlbHNlIHsKICAgIHRyeSB7CiAgICAgIGlmICghb3B0aW9ucy51bnNhZmUpIGRlbGV0ZSBPW2tleV07CiAgICAgIGVsc2UgaWYgKE9ba2V5XSkgc2ltcGxlID0gdHJ1ZTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7IC8qIGVtcHR5ICovIH0KICAgIGlmIChzaW1wbGUpIE9ba2V5XSA9IHZhbHVlOwogICAgZWxzZSBkZWZpbmVQcm9wZXJ0eU1vZHVsZS5mKE8sIGtleSwgewogICAgICB2YWx1ZTogdmFsdWUsCiAgICAgIGVudW1lcmFibGU6IGZhbHNlLAogICAgICBjb25maWd1cmFibGU6ICFvcHRpb25zLm5vbkNvbmZpZ3VyYWJsZSwKICAgICAgd3JpdGFibGU6ICFvcHRpb25zLm5vbldyaXRhYmxlCiAgICB9KTsKICB9IHJldHVybiBPOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNjk1NToKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBUT19TVFJJTkdfVEFHX1NVUFBPUlQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDIxNDApOwp2YXIgaXNDYWxsYWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oNDkwMSk7CnZhciBjbGFzc29mUmF3ID0gX193ZWJwYWNrX3JlcXVpcmVfXygyMTk1KTsKdmFyIHdlbGxLbm93blN5bWJvbCA9IF9fd2VicGFja19yZXF1aXJlX18oODIyNyk7Cgp2YXIgVE9fU1RSSU5HX1RBRyA9IHdlbGxLbm93blN5bWJvbCgndG9TdHJpbmdUYWcnKTsKdmFyICRPYmplY3QgPSBPYmplY3Q7CgovLyBFUzMgd3JvbmcgaGVyZQp2YXIgQ09SUkVDVF9BUkdVTUVOVFMgPSBjbGFzc29mUmF3KGZ1bmN0aW9uICgpIHsgcmV0dXJuIGFyZ3VtZW50czsgfSgpKSA9PT0gJ0FyZ3VtZW50cyc7CgovLyBmYWxsYmFjayBmb3IgSUUxMSBTY3JpcHQgQWNjZXNzIERlbmllZCBlcnJvcgp2YXIgdHJ5R2V0ID0gZnVuY3Rpb24gKGl0LCBrZXkpIHsKICB0cnkgewogICAgcmV0dXJuIGl0W2tleV07CiAgfSBjYXRjaCAoZXJyb3IpIHsgLyogZW1wdHkgKi8gfQp9OwoKLy8gZ2V0dGluZyB0YWcgZnJvbSBFUzYrIGBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nYAptb2R1bGUuZXhwb3J0cyA9IFRPX1NUUklOR19UQUdfU1VQUE9SVCA/IGNsYXNzb2ZSYXcgOiBmdW5jdGlvbiAoaXQpIHsKICB2YXIgTywgdGFnLCByZXN1bHQ7CiAgcmV0dXJuIGl0ID09PSB1bmRlZmluZWQgPyAnVW5kZWZpbmVkJyA6IGl0ID09PSBudWxsID8gJ051bGwnCiAgICAvLyBAQHRvU3RyaW5nVGFnIGNhc2UKICAgIDogdHlwZW9mICh0YWcgPSB0cnlHZXQoTyA9ICRPYmplY3QoaXQpLCBUT19TVFJJTkdfVEFHKSkgPT0gJ3N0cmluZycgPyB0YWcKICAgIC8vIGJ1aWx0aW5UYWcgY2FzZQogICAgOiBDT1JSRUNUX0FSR1VNRU5UUyA/IGNsYXNzb2ZSYXcoTykKICAgIC8vIEVTMyBhcmd1bWVudHMgZmFsbGJhY2sKICAgIDogKHJlc3VsdCA9IGNsYXNzb2ZSYXcoTykpID09PSAnT2JqZWN0JyAmJiBpc0NhbGxhYmxlKE8uY2FsbGVlKSA/ICdBcmd1bWVudHMnIDogcmVzdWx0Owp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNjk2OToKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciB0b1ByaW1pdGl2ZSA9IF9fd2VicGFja19yZXF1aXJlX18oMjc3Nyk7CnZhciBpc1N5bWJvbCA9IF9fd2VicGFja19yZXF1aXJlX18oNzU3KTsKCi8vIGBUb1Byb3BlcnR5S2V5YCBhYnN0cmFjdCBvcGVyYXRpb24KLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy10b3Byb3BlcnR5a2V5Cm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFyZ3VtZW50KSB7CiAgdmFyIGtleSA9IHRvUHJpbWl0aXZlKGFyZ3VtZW50LCAnc3RyaW5nJyk7CiAgcmV0dXJuIGlzU3ltYm9sKGtleSkgPyBrZXkgOiBrZXkgKyAnJzsKfTsKCgovKioqLyB9KSwKCi8qKiovIDY5ODA6Ci8qKiovICgobW9kdWxlKSA9PiB7CgoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYml0bWFwLCB2YWx1ZSkgewogIHJldHVybiB7CiAgICBlbnVtZXJhYmxlOiAhKGJpdG1hcCAmIDEpLAogICAgY29uZmlndXJhYmxlOiAhKGJpdG1hcCAmIDIpLAogICAgd3JpdGFibGU6ICEoYml0bWFwICYgNCksCiAgICB2YWx1ZTogdmFsdWUKICB9Owp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNzA0MDoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCi8qIGVzbGludC1kaXNhYmxlIGVzL25vLXN5bWJvbCAtLSByZXF1aXJlZCBmb3IgdGVzdGluZyAqLwp2YXIgTkFUSVZFX1NZTUJPTCA9IF9fd2VicGFja19yZXF1aXJlX18oNDQ5NSk7Cgptb2R1bGUuZXhwb3J0cyA9IE5BVElWRV9TWU1CT0wgJiYKICAhU3ltYm9sLnNoYW0gJiYKICB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09ICdzeW1ib2wnOwoKCi8qKiovIH0pLAoKLyoqKi8gNzA1NToKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciB1bmN1cnJ5VGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oOTUwNCk7CnZhciBmYWlscyA9IF9fd2VicGFja19yZXF1aXJlX18oOTAzOSk7CnZhciBjbGFzc29mID0gX193ZWJwYWNrX3JlcXVpcmVfXygyMTk1KTsKCnZhciAkT2JqZWN0ID0gT2JqZWN0Owp2YXIgc3BsaXQgPSB1bmN1cnJ5VGhpcygnJy5zcGxpdCk7CgovLyBmYWxsYmFjayBmb3Igbm9uLWFycmF5LWxpa2UgRVMzIGFuZCBub24tZW51bWVyYWJsZSBvbGQgVjggc3RyaW5ncwptb2R1bGUuZXhwb3J0cyA9IGZhaWxzKGZ1bmN0aW9uICgpIHsKICAvLyB0aHJvd3MgYW4gZXJyb3IgaW4gcmhpbm8sIHNlZSBodHRwczovL2dpdGh1Yi5jb20vbW96aWxsYS9yaGluby9pc3N1ZXMvMzQ2CiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXByb3RvdHlwZS1idWlsdGlucyAtLSBzYWZlCiAgcmV0dXJuICEkT2JqZWN0KCd6JykucHJvcGVydHlJc0VudW1lcmFibGUoMCk7Cn0pID8gZnVuY3Rpb24gKGl0KSB7CiAgcmV0dXJuIGNsYXNzb2YoaXQpID09PSAnU3RyaW5nJyA/IHNwbGl0KGl0LCAnJykgOiAkT2JqZWN0KGl0KTsKfSA6ICRPYmplY3Q7CgoKLyoqKi8gfSksCgovKioqLyA3MDgwOgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGhhcyA9IChfX3dlYnBhY2tfcmVxdWlyZV9fKDQ0MDIpLmhhcyk7CgovLyBQZXJmb3JtID8gUmVxdWlyZUludGVybmFsU2xvdChNLCBbW1NldERhdGFdXSkKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHsKICBoYXMoaXQpOwogIHJldHVybiBpdDsKfTsKCgovKioqLyB9KSwKCi8qKiovIDczNDc6Ci8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgREVTQ1JJUFRPUlMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM3MjQpOwp2YXIgY2FsbCA9IF9fd2VicGFja19yZXF1aXJlX18oOTU2NSk7CnZhciBwcm9wZXJ0eUlzRW51bWVyYWJsZU1vZHVsZSA9IF9fd2VicGFja19yZXF1aXJlX18oODc3Myk7CnZhciBjcmVhdGVQcm9wZXJ0eURlc2NyaXB0b3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY5ODApOwp2YXIgdG9JbmRleGVkT2JqZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg1Mzk3KTsKdmFyIHRvUHJvcGVydHlLZXkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY5NjkpOwp2YXIgaGFzT3duID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5Mjk3KTsKdmFyIElFOF9ET01fREVGSU5FID0gX193ZWJwYWNrX3JlcXVpcmVfXyg1OTE3KTsKCi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZ2V0b3ducHJvcGVydHlkZXNjcmlwdG9yIC0tIHNhZmUKdmFyICRnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yOwoKLy8gYE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JgIG1ldGhvZAovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5nZXRvd25wcm9wZXJ0eWRlc2NyaXB0b3IKZXhwb3J0cy5mID0gREVTQ1JJUFRPUlMgPyAkZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yIDogZnVuY3Rpb24gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKE8sIFApIHsKICBPID0gdG9JbmRleGVkT2JqZWN0KE8pOwogIFAgPSB0b1Byb3BlcnR5S2V5KFApOwogIGlmIChJRThfRE9NX0RFRklORSkgdHJ5IHsKICAgIHJldHVybiAkZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKE8sIFApOwogIH0gY2F0Y2ggKGVycm9yKSB7IC8qIGVtcHR5ICovIH0KICBpZiAoaGFzT3duKE8sIFApKSByZXR1cm4gY3JlYXRlUHJvcGVydHlEZXNjcmlwdG9yKCFjYWxsKHByb3BlcnR5SXNFbnVtZXJhYmxlTW9kdWxlLmYsIE8sIFApLCBPW1BdKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDczOTQ6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciB1bmN1cnJ5VGhpc0FjY2Vzc29yID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2NzA2KTsKdmFyIGNsYXNzb2YgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDIxOTUpOwoKdmFyIEFycmF5QnVmZmVyID0gZ2xvYmFsVGhpcy5BcnJheUJ1ZmZlcjsKdmFyIFR5cGVFcnJvciA9IGdsb2JhbFRoaXMuVHlwZUVycm9yOwoKLy8gSW5jbHVkZXMKLy8gLSBQZXJmb3JtID8gUmVxdWlyZUludGVybmFsU2xvdChPLCBbW0FycmF5QnVmZmVyRGF0YV1dKS4KLy8gLSBJZiBJc1NoYXJlZEFycmF5QnVmZmVyKE8pIGlzIHRydWUsIHRocm93IGEgVHlwZUVycm9yIGV4Y2VwdGlvbi4KbW9kdWxlLmV4cG9ydHMgPSBBcnJheUJ1ZmZlciAmJiB1bmN1cnJ5VGhpc0FjY2Vzc29yKEFycmF5QnVmZmVyLnByb3RvdHlwZSwgJ2J5dGVMZW5ndGgnLCAnZ2V0JykgfHwgZnVuY3Rpb24gKE8pIHsKICBpZiAoY2xhc3NvZihPKSAhPT0gJ0FycmF5QnVmZmVyJykgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJyYXlCdWZmZXIgZXhwZWN0ZWQnKTsKICByZXR1cm4gTy5ieXRlTGVuZ3RoOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNzQxNjoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBmYWlscyA9IF9fd2VicGFja19yZXF1aXJlX18oOTAzOSk7CnZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDgyMjcpOwp2YXIgREVTQ1JJUFRPUlMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM3MjQpOwp2YXIgSVNfUFVSRSA9IF9fd2VicGFja19yZXF1aXJlX18oNjM5NSk7Cgp2YXIgSVRFUkFUT1IgPSB3ZWxsS25vd25TeW1ib2woJ2l0ZXJhdG9yJyk7Cgptb2R1bGUuZXhwb3J0cyA9ICFmYWlscyhmdW5jdGlvbiAoKSB7CiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHVuaWNvcm4vcmVsYXRpdmUtdXJsLXN0eWxlIC0tIHJlcXVpcmVkIGZvciB0ZXN0aW5nCiAgdmFyIHVybCA9IG5ldyBVUkwoJ2I/YT0xJmI9MiZjPTMnLCAnaHR0cHM6Ly9hJyk7CiAgdmFyIHBhcmFtcyA9IHVybC5zZWFyY2hQYXJhbXM7CiAgdmFyIHBhcmFtczIgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKCdhPTEmYT0yJmI9MycpOwogIHZhciByZXN1bHQgPSAnJzsKICB1cmwucGF0aG5hbWUgPSAnYyUyMGQnOwogIHBhcmFtcy5mb3JFYWNoKGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7CiAgICBwYXJhbXNbJ2RlbGV0ZSddKCdiJyk7CiAgICByZXN1bHQgKz0ga2V5ICsgdmFsdWU7CiAgfSk7CiAgcGFyYW1zMlsnZGVsZXRlJ10oJ2EnLCAyKTsKICAvLyBgdW5kZWZpbmVkYCBjYXNlIGlzIGEgQ2hyb21pdW0gMTE3IGJ1ZwogIC8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTE0MjIyCiAgcGFyYW1zMlsnZGVsZXRlJ10oJ2InLCB1bmRlZmluZWQpOwogIHJldHVybiAoSVNfUFVSRSAmJiAoIXVybC50b0pTT04gfHwgIXBhcmFtczIuaGFzKCdhJywgMSkgfHwgcGFyYW1zMi5oYXMoJ2EnLCAyKSB8fCAhcGFyYW1zMi5oYXMoJ2EnLCB1bmRlZmluZWQpIHx8IHBhcmFtczIuaGFzKCdiJykpKQogICAgfHwgKCFwYXJhbXMuc2l6ZSAmJiAoSVNfUFVSRSB8fCAhREVTQ1JJUFRPUlMpKQogICAgfHwgIXBhcmFtcy5zb3J0CiAgICB8fCB1cmwuaHJlZiAhPT0gJ2h0dHBzOi8vYS9jJTIwZD9hPTEmYz0zJwogICAgfHwgcGFyYW1zLmdldCgnYycpICE9PSAnMycKICAgIHx8IFN0cmluZyhuZXcgVVJMU2VhcmNoUGFyYW1zKCc/YT0xJykpICE9PSAnYT0xJwogICAgfHwgIXBhcmFtc1tJVEVSQVRPUl0KICAgIC8vIHRocm93cyBpbiBFZGdlCiAgICB8fCBuZXcgVVJMKCdodHRwczovL2FAYicpLnVzZXJuYW1lICE9PSAnYScKICAgIHx8IG5ldyBVUkxTZWFyY2hQYXJhbXMobmV3IFVSTFNlYXJjaFBhcmFtcygnYT1iJykpLmdldCgnYScpICE9PSAnYicKICAgIC8vIG5vdCBwdW55Y29kZWQgaW4gRWRnZQogICAgfHwgbmV3IFVSTCgnaHR0cHM6Ly/RgtC10YHRgicpLmhvc3QgIT09ICd4bi0tZTFheWJjJwogICAgLy8gbm90IGVzY2FwZWQgaW4gQ2hyb21lIDYyLQogICAgfHwgbmV3IFVSTCgnaHR0cHM6Ly9hI9CxJykuaGFzaCAhPT0gJyMlRDAlQjEnCiAgICAvLyBmYWlscyBpbiBDaHJvbWUgNjYtCiAgICB8fCByZXN1bHQgIT09ICdhMWMzJwogICAgLy8gdGhyb3dzIGluIFNhZmFyaQogICAgfHwgbmV3IFVSTCgnaHR0cHM6Ly94JywgdW5kZWZpbmVkKS5ob3N0ICE9PSAneCc7Cn0pOwoKCi8qKiovIH0pLAoKLyoqKi8gNzQ3NjoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBjbGFzc29mUmF3ID0gX193ZWJwYWNrX3JlcXVpcmVfXygyMTk1KTsKdmFyIHVuY3VycnlUaGlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTA0KTsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGZuKSB7CiAgLy8gTmFzaG9ybiBidWc6CiAgLy8gICBodHRwczovL2dpdGh1Yi5jb20vemxvaXJvY2svY29yZS1qcy9pc3N1ZXMvMTEyOAogIC8vICAgaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMvaXNzdWVzLzExMzAKICBpZiAoY2xhc3NvZlJhdyhmbikgPT09ICdGdW5jdGlvbicpIHJldHVybiB1bmN1cnJ5VGhpcyhmbik7Cn07CgoKLyoqKi8gfSksCgovKioqLyA3NTY2OgovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgZGVmaW5lQnVpbHRJbiA9IF9fd2VicGFja19yZXF1aXJlX18oNjg0MCk7CnZhciB1bmN1cnJ5VGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oOTUwNCk7CnZhciB0b1N0cmluZyA9IF9fd2VicGFja19yZXF1aXJlX18oNjU1KTsKdmFyIHZhbGlkYXRlQXJndW1lbnRzTGVuZ3RoID0gX193ZWJwYWNrX3JlcXVpcmVfXygyODEyKTsKCnZhciAkVVJMU2VhcmNoUGFyYW1zID0gVVJMU2VhcmNoUGFyYW1zOwp2YXIgVVJMU2VhcmNoUGFyYW1zUHJvdG90eXBlID0gJFVSTFNlYXJjaFBhcmFtcy5wcm90b3R5cGU7CnZhciBnZXRBbGwgPSB1bmN1cnJ5VGhpcyhVUkxTZWFyY2hQYXJhbXNQcm90b3R5cGUuZ2V0QWxsKTsKdmFyICRoYXMgPSB1bmN1cnJ5VGhpcyhVUkxTZWFyY2hQYXJhbXNQcm90b3R5cGUuaGFzKTsKdmFyIHBhcmFtcyA9IG5ldyAkVVJMU2VhcmNoUGFyYW1zKCdhPTEnKTsKCi8vIGB1bmRlZmluZWRgIGNhc2UgaXMgYSBDaHJvbWl1bSAxMTcgYnVnCi8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTE0MjIyCmlmIChwYXJhbXMuaGFzKCdhJywgMikgfHwgIXBhcmFtcy5oYXMoJ2EnLCB1bmRlZmluZWQpKSB7CiAgZGVmaW5lQnVpbHRJbihVUkxTZWFyY2hQYXJhbXNQcm90b3R5cGUsICdoYXMnLCBmdW5jdGlvbiBoYXMobmFtZSAvKiAsIHZhbHVlICovKSB7CiAgICB2YXIgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aDsKICAgIHZhciAkdmFsdWUgPSBsZW5ndGggPCAyID8gdW5kZWZpbmVkIDogYXJndW1lbnRzWzFdOwogICAgaWYgKGxlbmd0aCAmJiAkdmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuICRoYXModGhpcywgbmFtZSk7CiAgICB2YXIgdmFsdWVzID0gZ2V0QWxsKHRoaXMsIG5hbWUpOyAvLyBhbHNvIHZhbGlkYXRlcyBgdGhpc2AKICAgIHZhbGlkYXRlQXJndW1lbnRzTGVuZ3RoKGxlbmd0aCwgMSk7CiAgICB2YXIgdmFsdWUgPSB0b1N0cmluZygkdmFsdWUpOwogICAgdmFyIGluZGV4ID0gMDsKICAgIHdoaWxlIChpbmRleCA8IHZhbHVlcy5sZW5ndGgpIHsKICAgICAgaWYgKHZhbHVlc1tpbmRleCsrXSA9PT0gdmFsdWUpIHJldHVybiB0cnVlOwogICAgfSByZXR1cm4gZmFsc2U7CiAgfSwgeyBlbnVtZXJhYmxlOiB0cnVlLCB1bnNhZmU6IHRydWUgfSk7Cn0KCgovKioqLyB9KSwKCi8qKiovIDc1ODg6Ci8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciAkID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2NTE4KTsKdmFyIGNhbGwgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1NjUpOwp2YXIgaXRlcmF0ZSA9IF9fd2VicGFja19yZXF1aXJlX18oMjY1Mik7CnZhciBhQ2FsbGFibGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDkzMDYpOwp2YXIgYW5PYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg1NTEpOwp2YXIgZ2V0SXRlcmF0b3JEaXJlY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDE3NjcpOwp2YXIgaXRlcmF0b3JDbG9zZSA9IF9fd2VicGFja19yZXF1aXJlX18oOTUzOSk7CnZhciBpdGVyYXRvckhlbHBlcldpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0NTQ5KTsKCnZhciBmb3JFYWNoV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IgPSBpdGVyYXRvckhlbHBlcldpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yKCdmb3JFYWNoJywgVHlwZUVycm9yKTsKCi8vIGBJdGVyYXRvci5wcm90b3R5cGUuZm9yRWFjaGAgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtaXRlcmF0b3IucHJvdG90eXBlLmZvcmVhY2gKJCh7IHRhcmdldDogJ0l0ZXJhdG9yJywgcHJvdG86IHRydWUsIHJlYWw6IHRydWUsIGZvcmNlZDogZm9yRWFjaFdpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yIH0sIHsKICBmb3JFYWNoOiBmdW5jdGlvbiBmb3JFYWNoKGZuKSB7CiAgICBhbk9iamVjdCh0aGlzKTsKICAgIHRyeSB7CiAgICAgIGFDYWxsYWJsZShmbik7CiAgICB9IGNhdGNoIChlcnJvcikgewogICAgICBpdGVyYXRvckNsb3NlKHRoaXMsICd0aHJvdycsIGVycm9yKTsKICAgIH0KCiAgICBpZiAoZm9yRWFjaFdpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yKSByZXR1cm4gY2FsbChmb3JFYWNoV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IsIHRoaXMsIGZuKTsKCiAgICB2YXIgcmVjb3JkID0gZ2V0SXRlcmF0b3JEaXJlY3QodGhpcyk7CiAgICB2YXIgY291bnRlciA9IDA7CiAgICBpdGVyYXRlKHJlY29yZCwgZnVuY3Rpb24gKHZhbHVlKSB7CiAgICAgIGZuKHZhbHVlLCBjb3VudGVyKyspOwogICAgfSwgeyBJU19SRUNPUkQ6IHRydWUgfSk7CiAgfQp9KTsKCgovKioqLyB9KSwKCi8qKiovIDc1OTQ6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciBmYWlscyA9IF9fd2VicGFja19yZXF1aXJlX18oOTAzOSk7CgovLyBiYWJlbC1taW5pZnkgYW5kIENsb3N1cmUgQ29tcGlsZXIgdHJhbnNwaWxlcyBSZWdFeHAoJy4nLCAnZCcpIC0+IC8uL2QgYW5kIGl0IGNhdXNlcyBTeW50YXhFcnJvcgp2YXIgUmVnRXhwID0gZ2xvYmFsVGhpcy5SZWdFeHA7Cgp2YXIgRkxBR1NfR0VUVEVSX0lTX0NPUlJFQ1QgPSAhZmFpbHMoZnVuY3Rpb24gKCkgewogIHZhciBJTkRJQ0VTX1NVUFBPUlQgPSB0cnVlOwogIHRyeSB7CiAgICBSZWdFeHAoJy4nLCAnZCcpOwogIH0gY2F0Y2ggKGVycm9yKSB7CiAgICBJTkRJQ0VTX1NVUFBPUlQgPSBmYWxzZTsKICB9CgogIHZhciBPID0ge307CiAgLy8gbW9kZXJuIFY4IGJ1ZwogIHZhciBjYWxscyA9ICcnOwogIHZhciBleHBlY3RlZCA9IElORElDRVNfU1VQUE9SVCA/ICdkZ2ltc3knIDogJ2dpbXN5JzsKCiAgdmFyIGFkZEdldHRlciA9IGZ1bmN0aW9uIChrZXksIGNocikgewogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1kZWZpbmVwcm9wZXJ0eSAtLSBzYWZlCiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoTywga2V5LCB7IGdldDogZnVuY3Rpb24gKCkgewogICAgICBjYWxscyArPSBjaHI7CiAgICAgIHJldHVybiB0cnVlOwogICAgfSB9KTsKICB9OwoKICB2YXIgcGFpcnMgPSB7CiAgICBkb3RBbGw6ICdzJywKICAgIGdsb2JhbDogJ2cnLAogICAgaWdub3JlQ2FzZTogJ2knLAogICAgbXVsdGlsaW5lOiAnbScsCiAgICBzdGlja3k6ICd5JwogIH07CgogIGlmIChJTkRJQ0VTX1NVUFBPUlQpIHBhaXJzLmhhc0luZGljZXMgPSAnZCc7CgogIGZvciAodmFyIGtleSBpbiBwYWlycykgYWRkR2V0dGVyKGtleSwgcGFpcnNba2V5XSk7CgogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZ2V0b3ducHJvcGVydHlkZXNjcmlwdG9yIC0tIHNhZmUKICB2YXIgcmVzdWx0ID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihSZWdFeHAucHJvdG90eXBlLCAnZmxhZ3MnKS5nZXQuY2FsbChPKTsKCiAgcmV0dXJuIHJlc3VsdCAhPT0gZXhwZWN0ZWQgfHwgY2FsbHMgIT09IGV4cGVjdGVkOwp9KTsKCm1vZHVsZS5leHBvcnRzID0geyBjb3JyZWN0OiBGTEFHU19HRVRURVJfSVNfQ09SUkVDVCB9OwoKCi8qKiovIH0pLAoKLyoqKi8gNzYyOToKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBJU19QVVJFID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2Mzk1KTsKdmFyIGdsb2JhbFRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ1NzYpOwp2YXIgZGVmaW5lR2xvYmFsUHJvcGVydHkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk0MzMpOwoKdmFyIFNIQVJFRCA9ICdfX2NvcmUtanNfc2hhcmVkX18nOwp2YXIgc3RvcmUgPSBtb2R1bGUuZXhwb3J0cyA9IGdsb2JhbFRoaXNbU0hBUkVEXSB8fCBkZWZpbmVHbG9iYWxQcm9wZXJ0eShTSEFSRUQsIHt9KTsKCihzdG9yZS52ZXJzaW9ucyB8fCAoc3RvcmUudmVyc2lvbnMgPSBbXSkpLnB1c2goewogIHZlcnNpb246ICczLjQ1LjEnLAogIG1vZGU6IElTX1BVUkUgPyAncHVyZScgOiAnZ2xvYmFsJywKICBjb3B5cmlnaHQ6ICfCqSAyMDE0LTIwMjUgRGVuaXMgUHVzaGthcmV2ICh6bG9pcm9jay5ydSknLAogIGxpY2Vuc2U6ICdodHRwczovL2dpdGh1Yi5jb20vemxvaXJvY2svY29yZS1qcy9ibG9iL3YzLjQ1LjEvTElDRU5TRScsCiAgc291cmNlOiAnaHR0cHM6Ly9naXRodWIuY29tL3psb2lyb2NrL2NvcmUtanMnCn0pOwoKCi8qKiovIH0pLAoKLyoqKi8gNzY0MjoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgZGlmZmVyZW5jZSA9IF9fd2VicGFja19yZXF1aXJlX18oMzQ0MCk7CnZhciBmYWlscyA9IF9fd2VicGFja19yZXF1aXJlX18oOTAzOSk7CnZhciBzZXRNZXRob2RBY2NlcHRTZXRMaWtlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0OTE2KTsKCnZhciBTRVRfTElLRV9JTkNPUlJFQ1RfQkVIQVZJT1IgPSAhc2V0TWV0aG9kQWNjZXB0U2V0TGlrZSgnZGlmZmVyZW5jZScsIGZ1bmN0aW9uIChyZXN1bHQpIHsKICByZXR1cm4gcmVzdWx0LnNpemUgPT09IDA7Cn0pOwoKdmFyIEZPUkNFRCA9IFNFVF9MSUtFX0lOQ09SUkVDVF9CRUhBVklPUiB8fCBmYWlscyhmdW5jdGlvbiAoKSB7CiAgLy8gaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTI4ODU5NQogIHZhciBzZXRMaWtlID0gewogICAgc2l6ZTogMSwKICAgIGhhczogZnVuY3Rpb24gKCkgeyByZXR1cm4gdHJ1ZTsgfSwKICAgIGtleXM6IGZ1bmN0aW9uICgpIHsKICAgICAgdmFyIGluZGV4ID0gMDsKICAgICAgcmV0dXJuIHsKICAgICAgICBuZXh0OiBmdW5jdGlvbiAoKSB7CiAgICAgICAgICB2YXIgZG9uZSA9IGluZGV4KysgPiAxOwogICAgICAgICAgaWYgKGJhc2VTZXQuaGFzKDEpKSBiYXNlU2V0LmNsZWFyKCk7CiAgICAgICAgICByZXR1cm4geyBkb25lOiBkb25lLCB2YWx1ZTogMiB9OwogICAgICAgIH0KICAgICAgfTsKICAgIH0KICB9OwogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1zZXQgLS0gdGVzdGluZwogIHZhciBiYXNlU2V0ID0gbmV3IFNldChbMSwgMiwgMywgNF0pOwogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1zZXQtcHJvdG90eXBlLWRpZmZlcmVuY2UgLS0gdGVzdGluZwogIHJldHVybiBiYXNlU2V0LmRpZmZlcmVuY2Uoc2V0TGlrZSkuc2l6ZSAhPT0gMzsKfSk7CgovLyBgU2V0LnByb3RvdHlwZS5kaWZmZXJlbmNlYCBtZXRob2QKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1zZXQucHJvdG90eXBlLmRpZmZlcmVuY2UKJCh7IHRhcmdldDogJ1NldCcsIHByb3RvOiB0cnVlLCByZWFsOiB0cnVlLCBmb3JjZWQ6IEZPUkNFRCB9LCB7CiAgZGlmZmVyZW5jZTogZGlmZmVyZW5jZQp9KTsKCgovKioqLyB9KSwKCi8qKiovIDc2NTc6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgZmFpbHMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDkwMzkpOwp2YXIgaXNDYWxsYWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oNDkwMSk7CnZhciBpc09iamVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oMzQpOwp2YXIgY3JlYXRlID0gX193ZWJwYWNrX3JlcXVpcmVfXygyMzYwKTsKdmFyIGdldFByb3RvdHlwZU9mID0gX193ZWJwYWNrX3JlcXVpcmVfXygyNzg3KTsKdmFyIGRlZmluZUJ1aWx0SW4gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY4NDApOwp2YXIgd2VsbEtub3duU3ltYm9sID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4MjI3KTsKdmFyIElTX1BVUkUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDYzOTUpOwoKdmFyIElURVJBVE9SID0gd2VsbEtub3duU3ltYm9sKCdpdGVyYXRvcicpOwp2YXIgQlVHR1lfU0FGQVJJX0lURVJBVE9SUyA9IGZhbHNlOwoKLy8gYCVJdGVyYXRvclByb3RvdHlwZSVgIG9iamVjdAovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLSVpdGVyYXRvcnByb3RvdHlwZSUtb2JqZWN0CnZhciBJdGVyYXRvclByb3RvdHlwZSwgUHJvdG90eXBlT2ZBcnJheUl0ZXJhdG9yUHJvdG90eXBlLCBhcnJheUl0ZXJhdG9yOwoKLyogZXNsaW50LWRpc2FibGUgZXMvbm8tYXJyYXktcHJvdG90eXBlLWtleXMgLS0gc2FmZSAqLwppZiAoW10ua2V5cykgewogIGFycmF5SXRlcmF0b3IgPSBbXS5rZXlzKCk7CiAgLy8gU2FmYXJpIDggaGFzIGJ1Z2d5IGl0ZXJhdG9ycyB3L28gYG5leHRgCiAgaWYgKCEoJ25leHQnIGluIGFycmF5SXRlcmF0b3IpKSBCVUdHWV9TQUZBUklfSVRFUkFUT1JTID0gdHJ1ZTsKICBlbHNlIHsKICAgIFByb3RvdHlwZU9mQXJyYXlJdGVyYXRvclByb3RvdHlwZSA9IGdldFByb3RvdHlwZU9mKGdldFByb3RvdHlwZU9mKGFycmF5SXRlcmF0b3IpKTsKICAgIGlmIChQcm90b3R5cGVPZkFycmF5SXRlcmF0b3JQcm90b3R5cGUgIT09IE9iamVjdC5wcm90b3R5cGUpIEl0ZXJhdG9yUHJvdG90eXBlID0gUHJvdG90eXBlT2ZBcnJheUl0ZXJhdG9yUHJvdG90eXBlOwogIH0KfQoKdmFyIE5FV19JVEVSQVRPUl9QUk9UT1RZUEUgPSAhaXNPYmplY3QoSXRlcmF0b3JQcm90b3R5cGUpIHx8IGZhaWxzKGZ1bmN0aW9uICgpIHsKICB2YXIgdGVzdCA9IHt9OwogIC8vIEZGNDQtIGxlZ2FjeSBpdGVyYXRvcnMgY2FzZQogIHJldHVybiBJdGVyYXRvclByb3RvdHlwZVtJVEVSQVRPUl0uY2FsbCh0ZXN0KSAhPT0gdGVzdDsKfSk7CgppZiAoTkVXX0lURVJBVE9SX1BST1RPVFlQRSkgSXRlcmF0b3JQcm90b3R5cGUgPSB7fTsKZWxzZSBpZiAoSVNfUFVSRSkgSXRlcmF0b3JQcm90b3R5cGUgPSBjcmVhdGUoSXRlcmF0b3JQcm90b3R5cGUpOwoKLy8gYCVJdGVyYXRvclByb3RvdHlwZSVbQEBpdGVyYXRvcl0oKWAgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtJWl0ZXJhdG9ycHJvdG90eXBlJS1AQGl0ZXJhdG9yCmlmICghaXNDYWxsYWJsZShJdGVyYXRvclByb3RvdHlwZVtJVEVSQVRPUl0pKSB7CiAgZGVmaW5lQnVpbHRJbihJdGVyYXRvclByb3RvdHlwZSwgSVRFUkFUT1IsIGZ1bmN0aW9uICgpIHsKICAgIHJldHVybiB0aGlzOwogIH0pOwp9Cgptb2R1bGUuZXhwb3J0cyA9IHsKICBJdGVyYXRvclByb3RvdHlwZTogSXRlcmF0b3JQcm90b3R5cGUsCiAgQlVHR1lfU0FGQVJJX0lURVJBVE9SUzogQlVHR1lfU0FGQVJJX0lURVJBVE9SUwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNzY4MDoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciB1bmN1cnJ5VGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oOTUwNCk7Cgptb2R1bGUuZXhwb3J0cyA9IHVuY3VycnlUaGlzKFtdLnNsaWNlKTsKCgovKioqLyB9KSwKCi8qKiovIDc2OTY6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgdG9JbnRlZ2VyT3JJbmZpbml0eSA9IF9fd2VicGFja19yZXF1aXJlX18oMTI5MSk7CnZhciB0b0xlbmd0aCA9IF9fd2VicGFja19yZXF1aXJlX18oODAxNCk7Cgp2YXIgJFJhbmdlRXJyb3IgPSBSYW5nZUVycm9yOwoKLy8gYFRvSW5kZXhgIGFic3RyYWN0IG9wZXJhdGlvbgovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLXRvaW5kZXgKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHsKICBpZiAoaXQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIDA7CiAgdmFyIG51bWJlciA9IHRvSW50ZWdlck9ySW5maW5pdHkoaXQpOwogIHZhciBsZW5ndGggPSB0b0xlbmd0aChudW1iZXIpOwogIGlmIChudW1iZXIgIT09IGxlbmd0aCkgdGhyb3cgbmV3ICRSYW5nZUVycm9yKCdXcm9uZyBsZW5ndGggb3IgaW5kZXgnKTsKICByZXR1cm4gbGVuZ3RoOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gNzc0MDoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBoYXNPd24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDkyOTcpOwp2YXIgb3duS2V5cyA9IF9fd2VicGFja19yZXF1aXJlX18oNTAzMSk7CnZhciBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JNb2R1bGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDczNDcpOwp2YXIgZGVmaW5lUHJvcGVydHlNb2R1bGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MTMpOwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAodGFyZ2V0LCBzb3VyY2UsIGV4Y2VwdGlvbnMpIHsKICB2YXIga2V5cyA9IG93bktleXMoc291cmNlKTsKICB2YXIgZGVmaW5lUHJvcGVydHkgPSBkZWZpbmVQcm9wZXJ0eU1vZHVsZS5mOwogIHZhciBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgPSBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3JNb2R1bGUuZjsKICBmb3IgKHZhciBpID0gMDsgaSA8IGtleXMubGVuZ3RoOyBpKyspIHsKICAgIHZhciBrZXkgPSBrZXlzW2ldOwogICAgaWYgKCFoYXNPd24odGFyZ2V0LCBrZXkpICYmICEoZXhjZXB0aW9ucyAmJiBoYXNPd24oZXhjZXB0aW9ucywga2V5KSkpIHsKICAgICAgZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIGdldE93blByb3BlcnR5RGVzY3JpcHRvcihzb3VyY2UsIGtleSkpOwogICAgfQogIH0KfTsKCgovKioqLyB9KSwKCi8qKiovIDc3NTA6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgaXNOdWxsT3JVbmRlZmluZWQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQxMTcpOwoKdmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7CgovLyBgUmVxdWlyZU9iamVjdENvZXJjaWJsZWAgYWJzdHJhY3Qgb3BlcmF0aW9uCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtcmVxdWlyZW9iamVjdGNvZXJjaWJsZQptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkgewogIGlmIChpc051bGxPclVuZGVmaW5lZChpdCkpIHRocm93IG5ldyAkVHlwZUVycm9yKCJDYW4ndCBjYWxsIG1ldGhvZCBvbiAiICsgaXQpOwogIHJldHVybiBpdDsKfTsKCgovKioqLyB9KSwKCi8qKiovIDc3NTE6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciBpc0NhbGxhYmxlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0OTAxKTsKCnZhciBhRnVuY3Rpb24gPSBmdW5jdGlvbiAoYXJndW1lbnQpIHsKICByZXR1cm4gaXNDYWxsYWJsZShhcmd1bWVudCkgPyBhcmd1bWVudCA6IHVuZGVmaW5lZDsKfTsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG5hbWVzcGFjZSwgbWV0aG9kKSB7CiAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggPCAyID8gYUZ1bmN0aW9uKGdsb2JhbFRoaXNbbmFtZXNwYWNlXSkgOiBnbG9iYWxUaGlzW25hbWVzcGFjZV0gJiYgZ2xvYmFsVGhpc1tuYW1lc3BhY2VdW21ldGhvZF07Cn07CgoKLyoqKi8gfSksCgovKioqLyA3ODExOgovKioqLyAoKG1vZHVsZSkgPT4gewoKCi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby10eXBlZC1hcnJheXMgLS0gc2FmZQptb2R1bGUuZXhwb3J0cyA9IHR5cGVvZiBBcnJheUJ1ZmZlciAhPSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgRGF0YVZpZXcgIT0gJ3VuZGVmaW5lZCc7CgoKLyoqKi8gfSksCgovKioqLyA3OTM2OgovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgJCA9IF9fd2VicGFja19yZXF1aXJlX18oNjUxOCk7CnZhciAkdHJhbnNmZXIgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDU2MzYpOwoKLy8gYEFycmF5QnVmZmVyLnByb3RvdHlwZS50cmFuc2ZlclRvRml4ZWRMZW5ndGhgIG1ldGhvZAovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5YnVmZmVyLnByb3RvdHlwZS50cmFuc2ZlcnRvZml4ZWRsZW5ndGgKaWYgKCR0cmFuc2ZlcikgJCh7IHRhcmdldDogJ0FycmF5QnVmZmVyJywgcHJvdG86IHRydWUgfSwgewogIHRyYW5zZmVyVG9GaXhlZExlbmd0aDogZnVuY3Rpb24gdHJhbnNmZXJUb0ZpeGVkTGVuZ3RoKCkgewogICAgcmV0dXJuICR0cmFuc2Zlcih0aGlzLCBhcmd1bWVudHMubGVuZ3RoID8gYXJndW1lbnRzWzBdIDogdW5kZWZpbmVkLCBmYWxzZSk7CiAgfQp9KTsKCgovKioqLyB9KSwKCi8qKiovIDc5Nzk6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgYW5PYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg1NTEpOwoKLy8gYFJlZ0V4cC5wcm90b3R5cGUuZmxhZ3NgIGdldHRlciBpbXBsZW1lbnRhdGlvbgovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWdldC1yZWdleHAucHJvdG90eXBlLmZsYWdzCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkgewogIHZhciB0aGF0ID0gYW5PYmplY3QodGhpcyk7CiAgdmFyIHJlc3VsdCA9ICcnOwogIGlmICh0aGF0Lmhhc0luZGljZXMpIHJlc3VsdCArPSAnZCc7CiAgaWYgKHRoYXQuZ2xvYmFsKSByZXN1bHQgKz0gJ2cnOwogIGlmICh0aGF0Lmlnbm9yZUNhc2UpIHJlc3VsdCArPSAnaSc7CiAgaWYgKHRoYXQubXVsdGlsaW5lKSByZXN1bHQgKz0gJ20nOwogIGlmICh0aGF0LmRvdEFsbCkgcmVzdWx0ICs9ICdzJzsKICBpZiAodGhhdC51bmljb2RlKSByZXN1bHQgKz0gJ3UnOwogIGlmICh0aGF0LnVuaWNvZGVTZXRzKSByZXN1bHQgKz0gJ3YnOwogIGlmICh0aGF0LnN0aWNreSkgcmVzdWx0ICs9ICd5JzsKICByZXR1cm4gcmVzdWx0Owp9OwoKCi8qKiovIH0pLAoKLyoqKi8gODAwNDoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgZmFpbHMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDkwMzkpOwp2YXIgaW50ZXJzZWN0aW9uID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4NzUwKTsKdmFyIHNldE1ldGhvZEFjY2VwdFNldExpa2UgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MTYpOwoKdmFyIElOQ09SUkVDVCA9ICFzZXRNZXRob2RBY2NlcHRTZXRMaWtlKCdpbnRlcnNlY3Rpb24nLCBmdW5jdGlvbiAocmVzdWx0KSB7CiAgcmV0dXJuIHJlc3VsdC5zaXplID09PSAyICYmIHJlc3VsdC5oYXMoMSkgJiYgcmVzdWx0LmhhcygyKTsKfSkgfHwgZmFpbHMoZnVuY3Rpb24gKCkgewogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1hcnJheS1mcm9tLCBlcy9uby1zZXQsIGVzL25vLXNldC1wcm90b3R5cGUtaW50ZXJzZWN0aW9uIC0tIHRlc3RpbmcKICByZXR1cm4gU3RyaW5nKEFycmF5LmZyb20obmV3IFNldChbMSwgMiwgM10pLmludGVyc2VjdGlvbihuZXcgU2V0KFszLCAyXSkpKSkgIT09ICczLDInOwp9KTsKCi8vIGBTZXQucHJvdG90eXBlLmludGVyc2VjdGlvbmAgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc2V0LnByb3RvdHlwZS5pbnRlcnNlY3Rpb24KJCh7IHRhcmdldDogJ1NldCcsIHByb3RvOiB0cnVlLCByZWFsOiB0cnVlLCBmb3JjZWQ6IElOQ09SUkVDVCB9LCB7CiAgaW50ZXJzZWN0aW9uOiBpbnRlcnNlY3Rpb24KfSk7CgoKLyoqKi8gfSksCgovKioqLyA4MDE0OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIHRvSW50ZWdlck9ySW5maW5pdHkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDEyOTEpOwoKdmFyIG1pbiA9IE1hdGgubWluOwoKLy8gYFRvTGVuZ3RoYCBhYnN0cmFjdCBvcGVyYXRpb24KLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy10b2xlbmd0aAptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcmd1bWVudCkgewogIHZhciBsZW4gPSB0b0ludGVnZXJPckluZmluaXR5KGFyZ3VtZW50KTsKICByZXR1cm4gbGVuID4gMCA/IG1pbihsZW4sIDB4MUZGRkZGRkZGRkZGRkYpIDogMDsgLy8gMiAqKiA1MyAtIDEgPT0gOTAwNzE5OTI1NDc0MDk5MQp9OwoKCi8qKiovIH0pLAoKLyoqKi8gODEwMDoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgJHRyYW5zZmVyID0gX193ZWJwYWNrX3JlcXVpcmVfXyg1NjM2KTsKCi8vIGBBcnJheUJ1ZmZlci5wcm90b3R5cGUudHJhbnNmZXJgIG1ldGhvZAovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5YnVmZmVyLnByb3RvdHlwZS50cmFuc2ZlcgppZiAoJHRyYW5zZmVyKSAkKHsgdGFyZ2V0OiAnQXJyYXlCdWZmZXInLCBwcm90bzogdHJ1ZSB9LCB7CiAgdHJhbnNmZXI6IGZ1bmN0aW9uIHRyYW5zZmVyKCkgewogICAgcmV0dXJuICR0cmFuc2Zlcih0aGlzLCBhcmd1bWVudHMubGVuZ3RoID8gYXJndW1lbnRzWzBdIDogdW5kZWZpbmVkLCB0cnVlKTsKICB9Cn0pOwoKCi8qKiovIH0pLAoKLyoqKi8gODExMToKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciBhbkluc3RhbmNlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2NzkpOwp2YXIgYW5PYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg1NTEpOwp2YXIgaXNDYWxsYWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oNDkwMSk7CnZhciBnZXRQcm90b3R5cGVPZiA9IF9fd2VicGFja19yZXF1aXJlX18oMjc4Nyk7CnZhciBkZWZpbmVCdWlsdEluQWNjZXNzb3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDIxMDYpOwp2YXIgY3JlYXRlUHJvcGVydHkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ2NTkpOwp2YXIgZmFpbHMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDkwMzkpOwp2YXIgaGFzT3duID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5Mjk3KTsKdmFyIHdlbGxLbm93blN5bWJvbCA9IF9fd2VicGFja19yZXF1aXJlX18oODIyNyk7CnZhciBJdGVyYXRvclByb3RvdHlwZSA9IChfX3dlYnBhY2tfcmVxdWlyZV9fKDc2NTcpLkl0ZXJhdG9yUHJvdG90eXBlKTsKdmFyIERFU0NSSVBUT1JTID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNzI0KTsKdmFyIElTX1BVUkUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDYzOTUpOwoKdmFyIENPTlNUUlVDVE9SID0gJ2NvbnN0cnVjdG9yJzsKdmFyIElURVJBVE9SID0gJ0l0ZXJhdG9yJzsKdmFyIFRPX1NUUklOR19UQUcgPSB3ZWxsS25vd25TeW1ib2woJ3RvU3RyaW5nVGFnJyk7Cgp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKdmFyIE5hdGl2ZUl0ZXJhdG9yID0gZ2xvYmFsVGhpc1tJVEVSQVRPUl07CgovLyBGRjU2LSBoYXZlIG5vbi1zdGFuZGFyZCBnbG9iYWwgaGVscGVyIGBJdGVyYXRvcmAKdmFyIEZPUkNFRCA9IElTX1BVUkUKICB8fCAhaXNDYWxsYWJsZShOYXRpdmVJdGVyYXRvcikKICB8fCBOYXRpdmVJdGVyYXRvci5wcm90b3R5cGUgIT09IEl0ZXJhdG9yUHJvdG90eXBlCiAgLy8gRkY0NC0gbm9uLXN0YW5kYXJkIGBJdGVyYXRvcmAgcGFzc2VzIHByZXZpb3VzIHRlc3RzCiAgfHwgIWZhaWxzKGZ1bmN0aW9uICgpIHsgTmF0aXZlSXRlcmF0b3Ioe30pOyB9KTsKCnZhciBJdGVyYXRvckNvbnN0cnVjdG9yID0gZnVuY3Rpb24gSXRlcmF0b3IoKSB7CiAgYW5JbnN0YW5jZSh0aGlzLCBJdGVyYXRvclByb3RvdHlwZSk7CiAgaWYgKGdldFByb3RvdHlwZU9mKHRoaXMpID09PSBJdGVyYXRvclByb3RvdHlwZSkgdGhyb3cgbmV3ICRUeXBlRXJyb3IoJ0Fic3RyYWN0IGNsYXNzIEl0ZXJhdG9yIG5vdCBkaXJlY3RseSBjb25zdHJ1Y3RhYmxlJyk7Cn07Cgp2YXIgZGVmaW5lSXRlcmF0b3JQcm90b3R5cGVBY2Nlc3NvciA9IGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7CiAgaWYgKERFU0NSSVBUT1JTKSB7CiAgICBkZWZpbmVCdWlsdEluQWNjZXNzb3IoSXRlcmF0b3JQcm90b3R5cGUsIGtleSwgewogICAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiB2YWx1ZTsKICAgICAgfSwKICAgICAgc2V0OiBmdW5jdGlvbiAocmVwbGFjZW1lbnQpIHsKICAgICAgICBhbk9iamVjdCh0aGlzKTsKICAgICAgICBpZiAodGhpcyA9PT0gSXRlcmF0b3JQcm90b3R5cGUpIHRocm93IG5ldyAkVHlwZUVycm9yKCJZb3UgY2FuJ3QgcmVkZWZpbmUgdGhpcyBwcm9wZXJ0eSIpOwogICAgICAgIGlmIChoYXNPd24odGhpcywga2V5KSkgdGhpc1trZXldID0gcmVwbGFjZW1lbnQ7CiAgICAgICAgZWxzZSBjcmVhdGVQcm9wZXJ0eSh0aGlzLCBrZXksIHJlcGxhY2VtZW50KTsKICAgICAgfQogICAgfSk7CiAgfSBlbHNlIEl0ZXJhdG9yUHJvdG90eXBlW2tleV0gPSB2YWx1ZTsKfTsKCmlmICghaGFzT3duKEl0ZXJhdG9yUHJvdG90eXBlLCBUT19TVFJJTkdfVEFHKSkgZGVmaW5lSXRlcmF0b3JQcm90b3R5cGVBY2Nlc3NvcihUT19TVFJJTkdfVEFHLCBJVEVSQVRPUik7CgppZiAoRk9SQ0VEIHx8ICFoYXNPd24oSXRlcmF0b3JQcm90b3R5cGUsIENPTlNUUlVDVE9SKSB8fCBJdGVyYXRvclByb3RvdHlwZVtDT05TVFJVQ1RPUl0gPT09IE9iamVjdCkgewogIGRlZmluZUl0ZXJhdG9yUHJvdG90eXBlQWNjZXNzb3IoQ09OU1RSVUNUT1IsIEl0ZXJhdG9yQ29uc3RydWN0b3IpOwp9CgpJdGVyYXRvckNvbnN0cnVjdG9yLnByb3RvdHlwZSA9IEl0ZXJhdG9yUHJvdG90eXBlOwoKLy8gYEl0ZXJhdG9yYCBjb25zdHJ1Y3RvcgovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWl0ZXJhdG9yCiQoeyBnbG9iYWw6IHRydWUsIGNvbnN0cnVjdG9yOiB0cnVlLCBmb3JjZWQ6IEZPUkNFRCB9LCB7CiAgSXRlcmF0b3I6IEl0ZXJhdG9yQ29uc3RydWN0b3IKfSk7CgoKLyoqKi8gfSksCgovKioqLyA4MjI3OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGdsb2JhbFRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ1NzYpOwp2YXIgc2hhcmVkID0gX193ZWJwYWNrX3JlcXVpcmVfXyg1NzQ1KTsKdmFyIGhhc093biA9IF9fd2VicGFja19yZXF1aXJlX18oOTI5Nyk7CnZhciB1aWQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDMzOTIpOwp2YXIgTkFUSVZFX1NZTUJPTCA9IF9fd2VicGFja19yZXF1aXJlX18oNDQ5NSk7CnZhciBVU0VfU1lNQk9MX0FTX1VJRCA9IF9fd2VicGFja19yZXF1aXJlX18oNzA0MCk7Cgp2YXIgU3ltYm9sID0gZ2xvYmFsVGhpcy5TeW1ib2w7CnZhciBXZWxsS25vd25TeW1ib2xzU3RvcmUgPSBzaGFyZWQoJ3drcycpOwp2YXIgY3JlYXRlV2VsbEtub3duU3ltYm9sID0gVVNFX1NZTUJPTF9BU19VSUQgPyBTeW1ib2xbJ2ZvciddIHx8IFN5bWJvbCA6IFN5bWJvbCAmJiBTeW1ib2wud2l0aG91dFNldHRlciB8fCB1aWQ7Cgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChuYW1lKSB7CiAgaWYgKCFoYXNPd24oV2VsbEtub3duU3ltYm9sc1N0b3JlLCBuYW1lKSkgewogICAgV2VsbEtub3duU3ltYm9sc1N0b3JlW25hbWVdID0gTkFUSVZFX1NZTUJPTCAmJiBoYXNPd24oU3ltYm9sLCBuYW1lKQogICAgICA/IFN5bWJvbFtuYW1lXQogICAgICA6IGNyZWF0ZVdlbGxLbm93blN5bWJvbCgnU3ltYm9sLicgKyBuYW1lKTsKICB9IHJldHVybiBXZWxsS25vd25TeW1ib2xzU3RvcmVbbmFtZV07Cn07CgoKLyoqKi8gfSksCgovKioqLyA4MjM3OgovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgJCA9IF9fd2VicGFja19yZXF1aXJlX18oNjUxOCk7CnZhciBpdGVyYXRlID0gX193ZWJwYWNrX3JlcXVpcmVfXygyNjUyKTsKdmFyIGFDYWxsYWJsZSA9IF9fd2VicGFja19yZXF1aXJlX18oOTMwNik7CnZhciBhbk9iamVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oODU1MSk7CnZhciBnZXRJdGVyYXRvckRpcmVjdCA9IF9fd2VicGFja19yZXF1aXJlX18oMTc2Nyk7CnZhciBpdGVyYXRvckNsb3NlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTM5KTsKdmFyIGl0ZXJhdG9ySGVscGVyV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ1NDkpOwp2YXIgYXBwbHkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg3NDUpOwp2YXIgZmFpbHMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDkwMzkpOwoKdmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7CgovLyBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MjkxNjUxCnZhciBGQUlMU19PTl9JTklUSUFMX1VOREVGSU5FRCA9IGZhaWxzKGZ1bmN0aW9uICgpIHsKICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8taXRlcmF0b3ItcHJvdG90eXBlLXJlZHVjZSwgZXMvbm8tYXJyYXktcHJvdG90eXBlLWtleXMsIGFycmF5LWNhbGxiYWNrLXJldHVybiAtLSByZXF1aXJlZCBmb3IgdGVzdGluZwogIFtdLmtleXMoKS5yZWR1Y2UoZnVuY3Rpb24gKCkgeyAvKiBlbXB0eSAqLyB9LCB1bmRlZmluZWQpOwp9KTsKCnZhciByZWR1Y2VXaXRob3V0Q2xvc2luZ09uRWFybHlFcnJvciA9ICFGQUlMU19PTl9JTklUSUFMX1VOREVGSU5FRCAmJiBpdGVyYXRvckhlbHBlcldpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yKCdyZWR1Y2UnLCAkVHlwZUVycm9yKTsKCi8vIGBJdGVyYXRvci5wcm90b3R5cGUucmVkdWNlYCBtZXRob2QKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1pdGVyYXRvci5wcm90b3R5cGUucmVkdWNlCiQoeyB0YXJnZXQ6ICdJdGVyYXRvcicsIHByb3RvOiB0cnVlLCByZWFsOiB0cnVlLCBmb3JjZWQ6IEZBSUxTX09OX0lOSVRJQUxfVU5ERUZJTkVEIHx8IHJlZHVjZVdpdGhvdXRDbG9zaW5nT25FYXJseUVycm9yIH0sIHsKICByZWR1Y2U6IGZ1bmN0aW9uIHJlZHVjZShyZWR1Y2VyIC8qICwgaW5pdGlhbFZhbHVlICovKSB7CiAgICBhbk9iamVjdCh0aGlzKTsKICAgIHRyeSB7CiAgICAgIGFDYWxsYWJsZShyZWR1Y2VyKTsKICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgIGl0ZXJhdG9yQ2xvc2UodGhpcywgJ3Rocm93JywgZXJyb3IpOwogICAgfQoKICAgIHZhciBub0luaXRpYWwgPSBhcmd1bWVudHMubGVuZ3RoIDwgMjsKICAgIHZhciBhY2N1bXVsYXRvciA9IG5vSW5pdGlhbCA/IHVuZGVmaW5lZCA6IGFyZ3VtZW50c1sxXTsKICAgIGlmIChyZWR1Y2VXaXRob3V0Q2xvc2luZ09uRWFybHlFcnJvcikgewogICAgICByZXR1cm4gYXBwbHkocmVkdWNlV2l0aG91dENsb3NpbmdPbkVhcmx5RXJyb3IsIHRoaXMsIG5vSW5pdGlhbCA/IFtyZWR1Y2VyXSA6IFtyZWR1Y2VyLCBhY2N1bXVsYXRvcl0pOwogICAgfQogICAgdmFyIHJlY29yZCA9IGdldEl0ZXJhdG9yRGlyZWN0KHRoaXMpOwogICAgdmFyIGNvdW50ZXIgPSAwOwogICAgaXRlcmF0ZShyZWNvcmQsIGZ1bmN0aW9uICh2YWx1ZSkgewogICAgICBpZiAobm9Jbml0aWFsKSB7CiAgICAgICAgbm9Jbml0aWFsID0gZmFsc2U7CiAgICAgICAgYWNjdW11bGF0b3IgPSB2YWx1ZTsKICAgICAgfSBlbHNlIHsKICAgICAgICBhY2N1bXVsYXRvciA9IHJlZHVjZXIoYWNjdW11bGF0b3IsIHZhbHVlLCBjb3VudGVyKTsKICAgICAgfQogICAgICBjb3VudGVyKys7CiAgICB9LCB7IElTX1JFQ09SRDogdHJ1ZSB9KTsKICAgIGlmIChub0luaXRpYWwpIHRocm93IG5ldyAkVHlwZUVycm9yKCdSZWR1Y2Ugb2YgZW1wdHkgaXRlcmF0b3Igd2l0aCBubyBpbml0aWFsIHZhbHVlJyk7CiAgICByZXR1cm4gYWNjdW11bGF0b3I7CiAgfQp9KTsKCgovKioqLyB9KSwKCi8qKiovIDg0Njk6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgdW5jdXJyeVRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1MDQpOwp2YXIgaXRlcmF0ZVNpbXBsZSA9IF9fd2VicGFja19yZXF1aXJlX18oNTA3KTsKdmFyIFNldEhlbHBlcnMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ0MDIpOwoKdmFyIFNldCA9IFNldEhlbHBlcnMuU2V0Owp2YXIgU2V0UHJvdG90eXBlID0gU2V0SGVscGVycy5wcm90bzsKdmFyIGZvckVhY2ggPSB1bmN1cnJ5VGhpcyhTZXRQcm90b3R5cGUuZm9yRWFjaCk7CnZhciBrZXlzID0gdW5jdXJyeVRoaXMoU2V0UHJvdG90eXBlLmtleXMpOwp2YXIgbmV4dCA9IGtleXMobmV3IFNldCgpKS5uZXh0OwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoc2V0LCBmbiwgaW50ZXJydXB0aWJsZSkgewogIHJldHVybiBpbnRlcnJ1cHRpYmxlID8gaXRlcmF0ZVNpbXBsZSh7IGl0ZXJhdG9yOiBrZXlzKHNldCksIG5leHQ6IG5leHQgfSwgZm4pIDogZm9yRWFjaChzZXQsIGZuKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDg0ODA6Ci8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIGV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgaW50ZXJuYWxPYmplY3RLZXlzID0gX193ZWJwYWNrX3JlcXVpcmVfXygxODI4KTsKdmFyIGVudW1CdWdLZXlzID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4NzI3KTsKCnZhciBoaWRkZW5LZXlzID0gZW51bUJ1Z0tleXMuY29uY2F0KCdsZW5ndGgnLCAncHJvdG90eXBlJyk7CgovLyBgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXNgIG1ldGhvZAovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLW9iamVjdC5nZXRvd25wcm9wZXJ0eW5hbWVzCi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1vYmplY3QtZ2V0b3ducHJvcGVydHluYW1lcyAtLSBzYWZlCmV4cG9ydHMuZiA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzIHx8IGZ1bmN0aW9uIGdldE93blByb3BlcnR5TmFtZXMoTykgewogIHJldHVybiBpbnRlcm5hbE9iamVjdEtleXMoTywgaGlkZGVuS2V5cyk7Cn07CgoKLyoqKi8gfSksCgovKioqLyA4NTI3OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGFTZXQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDcwODApOwp2YXIgaGFzID0gKF9fd2VicGFja19yZXF1aXJlX18oNDQwMikuaGFzKTsKdmFyIHNpemUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDUxNzApOwp2YXIgZ2V0U2V0UmVjb3JkID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNzg5KTsKdmFyIGl0ZXJhdGVTaW1wbGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDUwNyk7CnZhciBpdGVyYXRvckNsb3NlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTM5KTsKCi8vIGBTZXQucHJvdG90eXBlLmlzU3VwZXJzZXRPZmAgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc2V0LnByb3RvdHlwZS5pc3N1cGVyc2V0b2YKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc1N1cGVyc2V0T2Yob3RoZXIpIHsKICB2YXIgTyA9IGFTZXQodGhpcyk7CiAgdmFyIG90aGVyUmVjID0gZ2V0U2V0UmVjb3JkKG90aGVyKTsKICBpZiAoc2l6ZShPKSA8IG90aGVyUmVjLnNpemUpIHJldHVybiBmYWxzZTsKICB2YXIgaXRlcmF0b3IgPSBvdGhlclJlYy5nZXRJdGVyYXRvcigpOwogIHJldHVybiBpdGVyYXRlU2ltcGxlKGl0ZXJhdG9yLCBmdW5jdGlvbiAoZSkgewogICAgaWYgKCFoYXMoTywgZSkpIHJldHVybiBpdGVyYXRvckNsb3NlKGl0ZXJhdG9yLCAnbm9ybWFsJywgZmFsc2UpOwogIH0pICE9PSBmYWxzZTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDg1NTE6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgaXNPYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM0KTsKCnZhciAkU3RyaW5nID0gU3RyaW5nOwp2YXIgJFR5cGVFcnJvciA9IFR5cGVFcnJvcjsKCi8vIGBBc3NlcnQ6IFR5cGUoYXJndW1lbnQpIGlzIE9iamVjdGAKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoYXJndW1lbnQpIHsKICBpZiAoaXNPYmplY3QoYXJndW1lbnQpKSByZXR1cm4gYXJndW1lbnQ7CiAgdGhyb3cgbmV3ICRUeXBlRXJyb3IoJFN0cmluZyhhcmd1bWVudCkgKyAnIGlzIG5vdCBhbiBvYmplY3QnKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDg1NzQ6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgdW5jdXJyeVRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1MDQpOwoKdmFyICRFcnJvciA9IEVycm9yOwp2YXIgcmVwbGFjZSA9IHVuY3VycnlUaGlzKCcnLnJlcGxhY2UpOwoKdmFyIFRFU1QgPSAoZnVuY3Rpb24gKGFyZykgeyByZXR1cm4gU3RyaW5nKG5ldyAkRXJyb3IoYXJnKS5zdGFjayk7IH0pKCd6eGNhc2QnKTsKLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHJlZG9zL25vLXZ1bG5lcmFibGUsIHNvbmFyanMvc2xvdy1yZWdleCAtLSBzYWZlCnZhciBWOF9PUl9DSEFLUkFfU1RBQ0tfRU5UUlkgPSAvXG5ccyphdCBbXjpdKjpbXlxuXSovOwp2YXIgSVNfVjhfT1JfQ0hBS1JBX1NUQUNLID0gVjhfT1JfQ0hBS1JBX1NUQUNLX0VOVFJZLnRlc3QoVEVTVCk7Cgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChzdGFjaywgZHJvcEVudHJpZXMpIHsKICBpZiAoSVNfVjhfT1JfQ0hBS1JBX1NUQUNLICYmIHR5cGVvZiBzdGFjayA9PSAnc3RyaW5nJyAmJiAhJEVycm9yLnByZXBhcmVTdGFja1RyYWNlKSB7CiAgICB3aGlsZSAoZHJvcEVudHJpZXMtLSkgc3RhY2sgPSByZXBsYWNlKHN0YWNrLCBWOF9PUl9DSEFLUkFfU1RBQ0tfRU5UUlksICcnKTsKICB9IHJldHVybiBzdGFjazsKfTsKCgovKioqLyB9KSwKCi8qKiovIDg2MjI6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciBpc0NhbGxhYmxlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0OTAxKTsKCnZhciBXZWFrTWFwID0gZ2xvYmFsVGhpcy5XZWFrTWFwOwoKbW9kdWxlLmV4cG9ydHMgPSBpc0NhbGxhYmxlKFdlYWtNYXApICYmIC9uYXRpdmUgY29kZS8udGVzdChTdHJpbmcoV2Vha01hcCkpOwoKCi8qKiovIH0pLAoKLyoqKi8gODY0NjoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBjYWxsID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5NTY1KTsKdmFyIGFuT2JqZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4NTUxKTsKdmFyIGdldEl0ZXJhdG9yRGlyZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXygxNzY3KTsKdmFyIGdldEl0ZXJhdG9yTWV0aG9kID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4NTEpOwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqLCBzdHJpbmdIYW5kbGluZykgewogIGlmICghc3RyaW5nSGFuZGxpbmcgfHwgdHlwZW9mIG9iaiAhPT0gJ3N0cmluZycpIGFuT2JqZWN0KG9iaik7CiAgdmFyIG1ldGhvZCA9IGdldEl0ZXJhdG9yTWV0aG9kKG9iaik7CiAgcmV0dXJuIGdldEl0ZXJhdG9yRGlyZWN0KGFuT2JqZWN0KG1ldGhvZCAhPT0gdW5kZWZpbmVkID8gY2FsbChtZXRob2QsIG9iaikgOiBvYmopKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDg2ODY6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgREVTQ1JJUFRPUlMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM3MjQpOwp2YXIgZmFpbHMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDkwMzkpOwoKLy8gVjggfiBDaHJvbWUgMzYtCi8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTMzMzQKbW9kdWxlLmV4cG9ydHMgPSBERVNDUklQVE9SUyAmJiBmYWlscyhmdW5jdGlvbiAoKSB7CiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1kZWZpbmVwcm9wZXJ0eSAtLSByZXF1aXJlZCBmb3IgdGVzdGluZwogIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoZnVuY3Rpb24gKCkgeyAvKiBlbXB0eSAqLyB9LCAncHJvdG90eXBlJywgewogICAgdmFsdWU6IDQyLAogICAgd3JpdGFibGU6IGZhbHNlCiAgfSkucHJvdG90eXBlICE9PSA0MjsKfSk7CgoKLyoqKi8gfSksCgovKioqLyA4NzIxOgovKioqLyAoKF9fdW51c2VkX3dlYnBhY2tfbW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgREVTQ1JJUFRPUlMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM3MjQpOwp2YXIgdW5jdXJyeVRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1MDQpOwp2YXIgZGVmaW5lQnVpbHRJbkFjY2Vzc29yID0gX193ZWJwYWNrX3JlcXVpcmVfXygyMTA2KTsKCnZhciBVUkxTZWFyY2hQYXJhbXNQcm90b3R5cGUgPSBVUkxTZWFyY2hQYXJhbXMucHJvdG90eXBlOwp2YXIgZm9yRWFjaCA9IHVuY3VycnlUaGlzKFVSTFNlYXJjaFBhcmFtc1Byb3RvdHlwZS5mb3JFYWNoKTsKCi8vIGBVUkxTZWFyY2hQYXJhbXMucHJvdG90eXBlLnNpemVgIGdldHRlcgovLyBodHRwczovL2dpdGh1Yi5jb20vd2hhdHdnL3VybC9wdWxsLzczNAppZiAoREVTQ1JJUFRPUlMgJiYgISgnc2l6ZScgaW4gVVJMU2VhcmNoUGFyYW1zUHJvdG90eXBlKSkgewogIGRlZmluZUJ1aWx0SW5BY2Nlc3NvcihVUkxTZWFyY2hQYXJhbXNQcm90b3R5cGUsICdzaXplJywgewogICAgZ2V0OiBmdW5jdGlvbiBzaXplKCkgewogICAgICB2YXIgY291bnQgPSAwOwogICAgICBmb3JFYWNoKHRoaXMsIGZ1bmN0aW9uICgpIHsgY291bnQrKzsgfSk7CiAgICAgIHJldHVybiBjb3VudDsKICAgIH0sCiAgICBjb25maWd1cmFibGU6IHRydWUsCiAgICBlbnVtZXJhYmxlOiB0cnVlCiAgfSk7Cn0KCgovKioqLyB9KSwKCi8qKiovIDg3Mjc6Ci8qKiovICgobW9kdWxlKSA9PiB7CgoKLy8gSUU4LSBkb24ndCBlbnVtIGJ1ZyBrZXlzCm1vZHVsZS5leHBvcnRzID0gWwogICdjb25zdHJ1Y3RvcicsCiAgJ2hhc093blByb3BlcnR5JywKICAnaXNQcm90b3R5cGVPZicsCiAgJ3Byb3BlcnR5SXNFbnVtZXJhYmxlJywKICAndG9Mb2NhbGVTdHJpbmcnLAogICd0b1N0cmluZycsCiAgJ3ZhbHVlT2YnCl07CgoKLyoqKi8gfSksCgovKioqLyA4NzQ1OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIE5BVElWRV9CSU5EID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2MTYpOwoKdmFyIEZ1bmN0aW9uUHJvdG90eXBlID0gRnVuY3Rpb24ucHJvdG90eXBlOwp2YXIgYXBwbHkgPSBGdW5jdGlvblByb3RvdHlwZS5hcHBseTsKdmFyIGNhbGwgPSBGdW5jdGlvblByb3RvdHlwZS5jYWxsOwoKLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLWZ1bmN0aW9uLXByb3RvdHlwZS1iaW5kLCBlcy9uby1yZWZsZWN0IC0tIHNhZmUKbW9kdWxlLmV4cG9ydHMgPSB0eXBlb2YgUmVmbGVjdCA9PSAnb2JqZWN0JyAmJiBSZWZsZWN0LmFwcGx5IHx8IChOQVRJVkVfQklORCA/IGNhbGwuYmluZChhcHBseSkgOiBmdW5jdGlvbiAoKSB7CiAgcmV0dXJuIGNhbGwuYXBwbHkoYXBwbHksIGFyZ3VtZW50cyk7Cn0pOwoKCi8qKiovIH0pLAoKLyoqKi8gODc1MDoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBhU2V0ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg3MDgwKTsKdmFyIFNldEhlbHBlcnMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ0MDIpOwp2YXIgc2l6ZSA9IF9fd2VicGFja19yZXF1aXJlX18oNTE3MCk7CnZhciBnZXRTZXRSZWNvcmQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM3ODkpOwp2YXIgaXRlcmF0ZVNldCA9IF9fd2VicGFja19yZXF1aXJlX18oODQ2OSk7CnZhciBpdGVyYXRlU2ltcGxlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg1MDcpOwoKdmFyIFNldCA9IFNldEhlbHBlcnMuU2V0Owp2YXIgYWRkID0gU2V0SGVscGVycy5hZGQ7CnZhciBoYXMgPSBTZXRIZWxwZXJzLmhhczsKCi8vIGBTZXQucHJvdG90eXBlLmludGVyc2VjdGlvbmAgbWV0aG9kCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtc2V0LnByb3RvdHlwZS5pbnRlcnNlY3Rpb24KbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbnRlcnNlY3Rpb24ob3RoZXIpIHsKICB2YXIgTyA9IGFTZXQodGhpcyk7CiAgdmFyIG90aGVyUmVjID0gZ2V0U2V0UmVjb3JkKG90aGVyKTsKICB2YXIgcmVzdWx0ID0gbmV3IFNldCgpOwoKICBpZiAoc2l6ZShPKSA+IG90aGVyUmVjLnNpemUpIHsKICAgIGl0ZXJhdGVTaW1wbGUob3RoZXJSZWMuZ2V0SXRlcmF0b3IoKSwgZnVuY3Rpb24gKGUpIHsKICAgICAgaWYgKGhhcyhPLCBlKSkgYWRkKHJlc3VsdCwgZSk7CiAgICB9KTsKICB9IGVsc2UgewogICAgaXRlcmF0ZVNldChPLCBmdW5jdGlvbiAoZSkgewogICAgICBpZiAob3RoZXJSZWMuaW5jbHVkZXMoZSkpIGFkZChyZXN1bHQsIGUpOwogICAgfSk7CiAgfQoKICByZXR1cm4gcmVzdWx0Owp9OwoKCi8qKiovIH0pLAoKLyoqKi8gODc3MzoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgZXhwb3J0cykgPT4gewoKCnZhciAkcHJvcGVydHlJc0VudW1lcmFibGUgPSB7fS5wcm9wZXJ0eUlzRW51bWVyYWJsZTsKLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1nZXRvd25wcm9wZXJ0eWRlc2NyaXB0b3IgLS0gc2FmZQp2YXIgZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcjsKCi8vIE5hc2hvcm4gfiBKREs4IGJ1Zwp2YXIgTkFTSE9STl9CVUcgPSBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IgJiYgISRwcm9wZXJ0eUlzRW51bWVyYWJsZS5jYWxsKHsgMTogMiB9LCAxKTsKCi8vIGBPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlYCBtZXRob2QgaW1wbGVtZW50YXRpb24KLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1vYmplY3QucHJvdG90eXBlLnByb3BlcnR5aXNlbnVtZXJhYmxlCmV4cG9ydHMuZiA9IE5BU0hPUk5fQlVHID8gZnVuY3Rpb24gcHJvcGVydHlJc0VudW1lcmFibGUoVikgewogIHZhciBkZXNjcmlwdG9yID0gZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRoaXMsIFYpOwogIHJldHVybiAhIWRlc2NyaXB0b3IgJiYgZGVzY3JpcHRvci5lbnVtZXJhYmxlOwp9IDogJHByb3BlcnR5SXNFbnVtZXJhYmxlOwoKCi8qKiovIH0pLAoKLyoqKi8gODk4MToKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciByZXF1aXJlT2JqZWN0Q29lcmNpYmxlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg3NzUwKTsKCnZhciAkT2JqZWN0ID0gT2JqZWN0OwoKLy8gYFRvT2JqZWN0YCBhYnN0cmFjdCBvcGVyYXRpb24KLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy10b29iamVjdAptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcmd1bWVudCkgewogIHJldHVybiAkT2JqZWN0KHJlcXVpcmVPYmplY3RDb2VyY2libGUoYXJndW1lbnQpKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDkwMzk6Ci8qKiovICgobW9kdWxlKSA9PiB7CgoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZXhlYykgewogIHRyeSB7CiAgICByZXR1cm4gISFleGVjKCk7CiAgfSBjYXRjaCAoZXJyb3IpIHsKICAgIHJldHVybiB0cnVlOwogIH0KfTsKCgovKioqLyB9KSwKCi8qKiovIDkxNDM6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciB1bmN1cnJ5VGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oOTUwNCk7CnZhciBhbk9iamVjdE9yVW5kZWZpbmVkID0gX193ZWJwYWNrX3JlcXVpcmVfXygzOTcyKTsKdmFyIGFTdHJpbmcgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDM0NjMpOwp2YXIgaGFzT3duID0gX193ZWJwYWNrX3JlcXVpcmVfXyg5Mjk3KTsKdmFyIGJhc2U2NE1hcCA9IF9fd2VicGFja19yZXF1aXJlX18oMjgwNCk7CnZhciBnZXRBbHBoYWJldE9wdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oOTQ0KTsKdmFyIG5vdERldGFjaGVkID0gX193ZWJwYWNrX3JlcXVpcmVfXyg1MTY5KTsKCnZhciBiYXNlNjRBbHBoYWJldCA9IGJhc2U2NE1hcC5jMmk7CnZhciBiYXNlNjRVcmxBbHBoYWJldCA9IGJhc2U2NE1hcC5jMmlVcmw7Cgp2YXIgU3ludGF4RXJyb3IgPSBnbG9iYWxUaGlzLlN5bnRheEVycm9yOwp2YXIgVHlwZUVycm9yID0gZ2xvYmFsVGhpcy5UeXBlRXJyb3I7CnZhciBhdCA9IHVuY3VycnlUaGlzKCcnLmNoYXJBdCk7Cgp2YXIgc2tpcEFzY2lpV2hpdGVzcGFjZSA9IGZ1bmN0aW9uIChzdHJpbmcsIGluZGV4KSB7CiAgdmFyIGxlbmd0aCA9IHN0cmluZy5sZW5ndGg7CiAgZm9yICg7aW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHsKICAgIHZhciBjaHIgPSBhdChzdHJpbmcsIGluZGV4KTsKICAgIGlmIChjaHIgIT09ICcgJyAmJiBjaHIgIT09ICdcdCcgJiYgY2hyICE9PSAnXG4nICYmIGNociAhPT0gJ1xmJyAmJiBjaHIgIT09ICdccicpIGJyZWFrOwogIH0gcmV0dXJuIGluZGV4Owp9OwoKdmFyIGRlY29kZUJhc2U2NENodW5rID0gZnVuY3Rpb24gKGNodW5rLCBhbHBoYWJldCwgdGhyb3dPbkV4dHJhQml0cykgewogIHZhciBjaHVua0xlbmd0aCA9IGNodW5rLmxlbmd0aDsKCiAgaWYgKGNodW5rTGVuZ3RoIDwgNCkgewogICAgY2h1bmsgKz0gY2h1bmtMZW5ndGggPT09IDIgPyAnQUEnIDogJ0EnOwogIH0KCiAgdmFyIHRyaXBsZXQgPSAoYWxwaGFiZXRbYXQoY2h1bmssIDApXSA8PCAxOCkKICAgICsgKGFscGhhYmV0W2F0KGNodW5rLCAxKV0gPDwgMTIpCiAgICArIChhbHBoYWJldFthdChjaHVuaywgMildIDw8IDYpCiAgICArIGFscGhhYmV0W2F0KGNodW5rLCAzKV07CgogIHZhciBjaHVua0J5dGVzID0gWwogICAgKHRyaXBsZXQgPj4gMTYpICYgMjU1LAogICAgKHRyaXBsZXQgPj4gOCkgJiAyNTUsCiAgICB0cmlwbGV0ICYgMjU1CiAgXTsKCiAgaWYgKGNodW5rTGVuZ3RoID09PSAyKSB7CiAgICBpZiAodGhyb3dPbkV4dHJhQml0cyAmJiBjaHVua0J5dGVzWzFdICE9PSAwKSB7CiAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcignRXh0cmEgYml0cycpOwogICAgfQogICAgcmV0dXJuIFtjaHVua0J5dGVzWzBdXTsKICB9CgogIGlmIChjaHVua0xlbmd0aCA9PT0gMykgewogICAgaWYgKHRocm93T25FeHRyYUJpdHMgJiYgY2h1bmtCeXRlc1syXSAhPT0gMCkgewogICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ0V4dHJhIGJpdHMnKTsKICAgIH0KICAgIHJldHVybiBbY2h1bmtCeXRlc1swXSwgY2h1bmtCeXRlc1sxXV07CiAgfQoKICByZXR1cm4gY2h1bmtCeXRlczsKfTsKCnZhciB3cml0ZUJ5dGVzID0gZnVuY3Rpb24gKGJ5dGVzLCBlbGVtZW50cywgd3JpdHRlbikgewogIHZhciBlbGVtZW50c0xlbmd0aCA9IGVsZW1lbnRzLmxlbmd0aDsKICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgZWxlbWVudHNMZW5ndGg7IGluZGV4KyspIHsKICAgIGJ5dGVzW3dyaXR0ZW4gKyBpbmRleF0gPSBlbGVtZW50c1tpbmRleF07CiAgfQogIHJldHVybiB3cml0dGVuICsgZWxlbWVudHNMZW5ndGg7Cn07CgovKiBlc2xpbnQtZGlzYWJsZSBtYXgtc3RhdGVtZW50cywgbWF4LWRlcHRoIC0tIFRPRE8gKi8KbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoc3RyaW5nLCBvcHRpb25zLCBpbnRvLCBtYXhMZW5ndGgpIHsKICBhU3RyaW5nKHN0cmluZyk7CiAgYW5PYmplY3RPclVuZGVmaW5lZChvcHRpb25zKTsKICB2YXIgYWxwaGFiZXQgPSBnZXRBbHBoYWJldE9wdGlvbihvcHRpb25zKSA9PT0gJ2Jhc2U2NCcgPyBiYXNlNjRBbHBoYWJldCA6IGJhc2U2NFVybEFscGhhYmV0OwogIHZhciBsYXN0Q2h1bmtIYW5kbGluZyA9IG9wdGlvbnMgPyBvcHRpb25zLmxhc3RDaHVua0hhbmRsaW5nIDogdW5kZWZpbmVkOwoKICBpZiAobGFzdENodW5rSGFuZGxpbmcgPT09IHVuZGVmaW5lZCkgbGFzdENodW5rSGFuZGxpbmcgPSAnbG9vc2UnOwoKICBpZiAobGFzdENodW5rSGFuZGxpbmcgIT09ICdsb29zZScgJiYgbGFzdENodW5rSGFuZGxpbmcgIT09ICdzdHJpY3QnICYmIGxhc3RDaHVua0hhbmRsaW5nICE9PSAnc3RvcC1iZWZvcmUtcGFydGlhbCcpIHsKICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0luY29ycmVjdCBgbGFzdENodW5rSGFuZGxpbmdgIG9wdGlvbicpOwogIH0KCiAgaWYgKGludG8pIG5vdERldGFjaGVkKGludG8uYnVmZmVyKTsKCiAgdmFyIHN0cmluZ0xlbmd0aCA9IHN0cmluZy5sZW5ndGg7CiAgdmFyIGJ5dGVzID0gaW50byB8fCBbXTsKICB2YXIgd3JpdHRlbiA9IDA7CiAgdmFyIHJlYWQgPSAwOwogIHZhciBjaHVuayA9ICcnOwogIHZhciBpbmRleCA9IDA7CgogIGlmIChtYXhMZW5ndGgpIHdoaWxlICh0cnVlKSB7CiAgICBpbmRleCA9IHNraXBBc2NpaVdoaXRlc3BhY2Uoc3RyaW5nLCBpbmRleCk7CiAgICBpZiAoaW5kZXggPT09IHN0cmluZ0xlbmd0aCkgewogICAgICBpZiAoY2h1bmsubGVuZ3RoID4gMCkgewogICAgICAgIGlmIChsYXN0Q2h1bmtIYW5kbGluZyA9PT0gJ3N0b3AtYmVmb3JlLXBhcnRpYWwnKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgaWYgKGxhc3RDaHVua0hhbmRsaW5nID09PSAnbG9vc2UnKSB7CiAgICAgICAgICBpZiAoY2h1bmsubGVuZ3RoID09PSAxKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBTeW50YXhFcnJvcignTWFsZm9ybWVkIHBhZGRpbmc6IGV4YWN0bHkgb25lIGFkZGl0aW9uYWwgY2hhcmFjdGVyJyk7CiAgICAgICAgICB9CiAgICAgICAgICB3cml0dGVuID0gd3JpdGVCeXRlcyhieXRlcywgZGVjb2RlQmFzZTY0Q2h1bmsoY2h1bmssIGFscGhhYmV0LCBmYWxzZSksIHdyaXR0ZW4pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ01pc3NpbmcgcGFkZGluZycpOwogICAgICAgIH0KICAgICAgfQogICAgICByZWFkID0gc3RyaW5nTGVuZ3RoOwogICAgICBicmVhazsKICAgIH0KICAgIHZhciBjaHIgPSBhdChzdHJpbmcsIGluZGV4KTsKICAgICsraW5kZXg7CiAgICBpZiAoY2hyID09PSAnPScpIHsKICAgICAgaWYgKGNodW5rLmxlbmd0aCA8IDIpIHsKICAgICAgICB0aHJvdyBuZXcgU3ludGF4RXJyb3IoJ1BhZGRpbmcgaXMgdG9vIGVhcmx5Jyk7CiAgICAgIH0KICAgICAgaW5kZXggPSBza2lwQXNjaWlXaGl0ZXNwYWNlKHN0cmluZywgaW5kZXgpOwogICAgICBpZiAoY2h1bmsubGVuZ3RoID09PSAyKSB7CiAgICAgICAgaWYgKGluZGV4ID09PSBzdHJpbmdMZW5ndGgpIHsKICAgICAgICAgIGlmIChsYXN0Q2h1bmtIYW5kbGluZyA9PT0gJ3N0b3AtYmVmb3JlLXBhcnRpYWwnKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdNYWxmb3JtZWQgcGFkZGluZzogb25seSBvbmUgPScpOwogICAgICAgIH0KICAgICAgICBpZiAoYXQoc3RyaW5nLCBpbmRleCkgPT09ICc9JykgewogICAgICAgICAgKytpbmRleDsKICAgICAgICAgIGluZGV4ID0gc2tpcEFzY2lpV2hpdGVzcGFjZShzdHJpbmcsIGluZGV4KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGluZGV4IDwgc3RyaW5nTGVuZ3RoKSB7CiAgICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdVbmV4cGVjdGVkIGNoYXJhY3RlciBhZnRlciBwYWRkaW5nJyk7CiAgICAgIH0KICAgICAgd3JpdHRlbiA9IHdyaXRlQnl0ZXMoYnl0ZXMsIGRlY29kZUJhc2U2NENodW5rKGNodW5rLCBhbHBoYWJldCwgbGFzdENodW5rSGFuZGxpbmcgPT09ICdzdHJpY3QnKSwgd3JpdHRlbik7CiAgICAgIHJlYWQgPSBzdHJpbmdMZW5ndGg7CiAgICAgIGJyZWFrOwogICAgfQogICAgaWYgKCFoYXNPd24oYWxwaGFiZXQsIGNocikpIHsKICAgICAgdGhyb3cgbmV3IFN5bnRheEVycm9yKCdVbmV4cGVjdGVkIGNoYXJhY3RlcicpOwogICAgfQogICAgdmFyIHJlbWFpbmluZ0J5dGVzID0gbWF4TGVuZ3RoIC0gd3JpdHRlbjsKICAgIGlmIChyZW1haW5pbmdCeXRlcyA9PT0gMSAmJiBjaHVuay5sZW5ndGggPT09IDIgfHwgcmVtYWluaW5nQnl0ZXMgPT09IDIgJiYgY2h1bmsubGVuZ3RoID09PSAzKSB7CiAgICAgIC8vIHNwZWNpYWwgY2FzZTogd2UgY2FuIGZpdCBleGFjdGx5IHRoZSBudW1iZXIgb2YgYnl0ZXMgY3VycmVudGx5IHJlcHJlc2VudGVkIGJ5IGNodW5rLCBzbyB3ZSB3ZXJlIGp1c3QgY2hlY2tpbmcgZm9yIGA9YAogICAgICBicmVhazsKICAgIH0KCiAgICBjaHVuayArPSBjaHI7CiAgICBpZiAoY2h1bmsubGVuZ3RoID09PSA0KSB7CiAgICAgIHdyaXR0ZW4gPSB3cml0ZUJ5dGVzKGJ5dGVzLCBkZWNvZGVCYXNlNjRDaHVuayhjaHVuaywgYWxwaGFiZXQsIGZhbHNlKSwgd3JpdHRlbik7CiAgICAgIGNodW5rID0gJyc7CiAgICAgIHJlYWQgPSBpbmRleDsKICAgICAgaWYgKHdyaXR0ZW4gPT09IG1heExlbmd0aCkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQoKICByZXR1cm4geyBieXRlczogYnl0ZXMsIHJlYWQ6IHJlYWQsIHdyaXR0ZW46IHdyaXR0ZW4gfTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDkyODY6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgU2V0SGVscGVycyA9IF9fd2VicGFja19yZXF1aXJlX18oNDQwMik7CnZhciBpdGVyYXRlID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4NDY5KTsKCnZhciBTZXQgPSBTZXRIZWxwZXJzLlNldDsKdmFyIGFkZCA9IFNldEhlbHBlcnMuYWRkOwoKbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoc2V0KSB7CiAgdmFyIHJlc3VsdCA9IG5ldyBTZXQoKTsKICBpdGVyYXRlKHNldCwgZnVuY3Rpb24gKGl0KSB7CiAgICBhZGQocmVzdWx0LCBpdCk7CiAgfSk7CiAgcmV0dXJuIHJlc3VsdDsKfTsKCgovKioqLyB9KSwKCi8qKiovIDkyOTc6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgdW5jdXJyeVRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1MDQpOwp2YXIgdG9PYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg5ODEpOwoKdmFyIGhhc093blByb3BlcnR5ID0gdW5jdXJyeVRoaXMoe30uaGFzT3duUHJvcGVydHkpOwoKLy8gYEhhc093blByb3BlcnR5YCBhYnN0cmFjdCBvcGVyYXRpb24KLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1oYXNvd25wcm9wZXJ0eQovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tb2JqZWN0LWhhc293biAtLSBzYWZlCm1vZHVsZS5leHBvcnRzID0gT2JqZWN0Lmhhc093biB8fCBmdW5jdGlvbiBoYXNPd24oaXQsIGtleSkgewogIHJldHVybiBoYXNPd25Qcm9wZXJ0eSh0b09iamVjdChpdCksIGtleSk7Cn07CgoKLyoqKi8gfSksCgovKioqLyA5MzA2OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGlzQ2FsbGFibGUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ5MDEpOwp2YXIgdHJ5VG9TdHJpbmcgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY4MjMpOwoKdmFyICRUeXBlRXJyb3IgPSBUeXBlRXJyb3I7CgovLyBgQXNzZXJ0OiBJc0NhbGxhYmxlKGFyZ3VtZW50KSBpcyB0cnVlYAptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhcmd1bWVudCkgewogIGlmIChpc0NhbGxhYmxlKGFyZ3VtZW50KSkgcmV0dXJuIGFyZ3VtZW50OwogIHRocm93IG5ldyAkVHlwZUVycm9yKHRyeVRvU3RyaW5nKGFyZ3VtZW50KSArICcgaXMgbm90IGEgZnVuY3Rpb24nKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDk0Mjk6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciBJU19OT0RFID0gX193ZWJwYWNrX3JlcXVpcmVfXyg2MTkzKTsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG5hbWUpIHsKICBpZiAoSVNfTk9ERSkgewogICAgdHJ5IHsKICAgICAgcmV0dXJuIGdsb2JhbFRoaXMucHJvY2Vzcy5nZXRCdWlsdGluTW9kdWxlKG5hbWUpOwogICAgfSBjYXRjaCAoZXJyb3IpIHsgLyogZW1wdHkgKi8gfQogICAgdHJ5IHsKICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLW5ldy1mdW5jIC0tIHNhZmUKICAgICAgcmV0dXJuIEZ1bmN0aW9uKCdyZXR1cm4gcmVxdWlyZSgiJyArIG5hbWUgKyAnIiknKSgpOwogICAgfSBjYXRjaCAoZXJyb3IpIHsgLyogZW1wdHkgKi8gfQogIH0KfTsKCgovKioqLyB9KSwKCi8qKiovIDk0MzI6Ci8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCi8vIFRPRE86IFJlbW92ZSBmcm9tIGBjb3JlLWpzQDRgCl9fd2VicGFja19yZXF1aXJlX18oNTIxMyk7CgoKLyoqKi8gfSksCgovKioqLyA5NDMzOgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGdsb2JhbFRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ1NzYpOwoKLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1kZWZpbmVwcm9wZXJ0eSAtLSBzYWZlCnZhciBkZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eTsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSwgdmFsdWUpIHsKICB0cnkgewogICAgZGVmaW5lUHJvcGVydHkoZ2xvYmFsVGhpcywga2V5LCB7IHZhbHVlOiB2YWx1ZSwgY29uZmlndXJhYmxlOiB0cnVlLCB3cml0YWJsZTogdHJ1ZSB9KTsKICB9IGNhdGNoIChlcnJvcikgewogICAgZ2xvYmFsVGhpc1trZXldID0gdmFsdWU7CiAgfSByZXR1cm4gdmFsdWU7Cn07CgoKLyoqKi8gfSksCgovKioqLyA5NDYyOgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGNhbGwgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1NjUpOwp2YXIgY3JlYXRlID0gX193ZWJwYWNrX3JlcXVpcmVfXygyMzYwKTsKdmFyIGNyZWF0ZU5vbkVudW1lcmFibGVQcm9wZXJ0eSA9IF9fd2VicGFja19yZXF1aXJlX18oNjY5OSk7CnZhciBkZWZpbmVCdWlsdElucyA9IF9fd2VicGFja19yZXF1aXJlX18oNjI3OSk7CnZhciB3ZWxsS25vd25TeW1ib2wgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDgyMjcpOwp2YXIgSW50ZXJuYWxTdGF0ZU1vZHVsZSA9IF9fd2VicGFja19yZXF1aXJlX18oMTE4MSk7CnZhciBnZXRNZXRob2QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDU5NjYpOwp2YXIgSXRlcmF0b3JQcm90b3R5cGUgPSAoX193ZWJwYWNrX3JlcXVpcmVfXyg3NjU3KS5JdGVyYXRvclByb3RvdHlwZSk7CnZhciBjcmVhdGVJdGVyUmVzdWx0T2JqZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXygyNTI5KTsKdmFyIGl0ZXJhdG9yQ2xvc2UgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1MzkpOwp2YXIgaXRlcmF0b3JDbG9zZUFsbCA9IF9fd2VicGFja19yZXF1aXJlX18oMTM4NSk7Cgp2YXIgVE9fU1RSSU5HX1RBRyA9IHdlbGxLbm93blN5bWJvbCgndG9TdHJpbmdUYWcnKTsKdmFyIElURVJBVE9SX0hFTFBFUiA9ICdJdGVyYXRvckhlbHBlcic7CnZhciBXUkFQX0ZPUl9WQUxJRF9JVEVSQVRPUiA9ICdXcmFwRm9yVmFsaWRJdGVyYXRvcic7CnZhciBOT1JNQUwgPSAnbm9ybWFsJzsKdmFyIFRIUk9XID0gJ3Rocm93JzsKdmFyIHNldEludGVybmFsU3RhdGUgPSBJbnRlcm5hbFN0YXRlTW9kdWxlLnNldDsKCnZhciBjcmVhdGVJdGVyYXRvclByb3h5UHJvdG90eXBlID0gZnVuY3Rpb24gKElTX0lURVJBVE9SKSB7CiAgdmFyIGdldEludGVybmFsU3RhdGUgPSBJbnRlcm5hbFN0YXRlTW9kdWxlLmdldHRlckZvcihJU19JVEVSQVRPUiA/IFdSQVBfRk9SX1ZBTElEX0lURVJBVE9SIDogSVRFUkFUT1JfSEVMUEVSKTsKCiAgcmV0dXJuIGRlZmluZUJ1aWx0SW5zKGNyZWF0ZShJdGVyYXRvclByb3RvdHlwZSksIHsKICAgIG5leHQ6IGZ1bmN0aW9uIG5leHQoKSB7CiAgICAgIHZhciBzdGF0ZSA9IGdldEludGVybmFsU3RhdGUodGhpcyk7CiAgICAgIC8vIGZvciBzaW1wbGlmaWNhdGlvbjoKICAgICAgLy8gICBmb3IgYCVXcmFwRm9yVmFsaWRJdGVyYXRvclByb3RvdHlwZSUubmV4dGAgb3Igd2l0aCBgc3RhdGUucmV0dXJuSGFuZGxlclJlc3VsdGAgb3VyIGBuZXh0SGFuZGxlcmAgcmV0dXJucyBgSXRlclJlc3VsdE9iamVjdGAKICAgICAgLy8gICBmb3IgYCVJdGVyYXRvckhlbHBlclByb3RvdHlwZSUubmV4dGAgLSBqdXN0IGEgdmFsdWUKICAgICAgaWYgKElTX0lURVJBVE9SKSByZXR1cm4gc3RhdGUubmV4dEhhbmRsZXIoKTsKICAgICAgaWYgKHN0YXRlLmRvbmUpIHJldHVybiBjcmVhdGVJdGVyUmVzdWx0T2JqZWN0KHVuZGVmaW5lZCwgdHJ1ZSk7CiAgICAgIHRyeSB7CiAgICAgICAgdmFyIHJlc3VsdCA9IHN0YXRlLm5leHRIYW5kbGVyKCk7CiAgICAgICAgcmV0dXJuIHN0YXRlLnJldHVybkhhbmRsZXJSZXN1bHQgPyByZXN1bHQgOiBjcmVhdGVJdGVyUmVzdWx0T2JqZWN0KHJlc3VsdCwgc3RhdGUuZG9uZSk7CiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7CiAgICAgICAgc3RhdGUuZG9uZSA9IHRydWU7CiAgICAgICAgdGhyb3cgZXJyb3I7CiAgICAgIH0KICAgIH0sCiAgICAncmV0dXJuJzogZnVuY3Rpb24gKCkgewogICAgICB2YXIgc3RhdGUgPSBnZXRJbnRlcm5hbFN0YXRlKHRoaXMpOwogICAgICB2YXIgaXRlcmF0b3IgPSBzdGF0ZS5pdGVyYXRvcjsKICAgICAgc3RhdGUuZG9uZSA9IHRydWU7CiAgICAgIGlmIChJU19JVEVSQVRPUikgewogICAgICAgIHZhciByZXR1cm5NZXRob2QgPSBnZXRNZXRob2QoaXRlcmF0b3IsICdyZXR1cm4nKTsKICAgICAgICByZXR1cm4gcmV0dXJuTWV0aG9kID8gY2FsbChyZXR1cm5NZXRob2QsIGl0ZXJhdG9yKSA6IGNyZWF0ZUl0ZXJSZXN1bHRPYmplY3QodW5kZWZpbmVkLCB0cnVlKTsKICAgICAgfQogICAgICBpZiAoc3RhdGUuaW5uZXIpIHRyeSB7CiAgICAgICAgaXRlcmF0b3JDbG9zZShzdGF0ZS5pbm5lci5pdGVyYXRvciwgTk9STUFMKTsKICAgICAgfSBjYXRjaCAoZXJyb3IpIHsKICAgICAgICByZXR1cm4gaXRlcmF0b3JDbG9zZShpdGVyYXRvciwgVEhST1csIGVycm9yKTsKICAgICAgfQogICAgICBpZiAoc3RhdGUub3Blbkl0ZXJzKSB0cnkgewogICAgICAgIGl0ZXJhdG9yQ2xvc2VBbGwoc3RhdGUub3Blbkl0ZXJzLCBOT1JNQUwpOwogICAgICB9IGNhdGNoIChlcnJvcikgewogICAgICAgIHJldHVybiBpdGVyYXRvckNsb3NlKGl0ZXJhdG9yLCBUSFJPVywgZXJyb3IpOwogICAgICB9CiAgICAgIGlmIChpdGVyYXRvcikgaXRlcmF0b3JDbG9zZShpdGVyYXRvciwgTk9STUFMKTsKICAgICAgcmV0dXJuIGNyZWF0ZUl0ZXJSZXN1bHRPYmplY3QodW5kZWZpbmVkLCB0cnVlKTsKICAgIH0KICB9KTsKfTsKCnZhciBXcmFwRm9yVmFsaWRJdGVyYXRvclByb3RvdHlwZSA9IGNyZWF0ZUl0ZXJhdG9yUHJveHlQcm90b3R5cGUodHJ1ZSk7CnZhciBJdGVyYXRvckhlbHBlclByb3RvdHlwZSA9IGNyZWF0ZUl0ZXJhdG9yUHJveHlQcm90b3R5cGUoZmFsc2UpOwoKY3JlYXRlTm9uRW51bWVyYWJsZVByb3BlcnR5KEl0ZXJhdG9ySGVscGVyUHJvdG90eXBlLCBUT19TVFJJTkdfVEFHLCAnSXRlcmF0b3IgSGVscGVyJyk7Cgptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChuZXh0SGFuZGxlciwgSVNfSVRFUkFUT1IsIFJFVFVSTl9IQU5ETEVSX1JFU1VMVCkgewogIHZhciBJdGVyYXRvclByb3h5ID0gZnVuY3Rpb24gSXRlcmF0b3IocmVjb3JkLCBzdGF0ZSkgewogICAgaWYgKHN0YXRlKSB7CiAgICAgIHN0YXRlLml0ZXJhdG9yID0gcmVjb3JkLml0ZXJhdG9yOwogICAgICBzdGF0ZS5uZXh0ID0gcmVjb3JkLm5leHQ7CiAgICB9IGVsc2Ugc3RhdGUgPSByZWNvcmQ7CiAgICBzdGF0ZS50eXBlID0gSVNfSVRFUkFUT1IgPyBXUkFQX0ZPUl9WQUxJRF9JVEVSQVRPUiA6IElURVJBVE9SX0hFTFBFUjsKICAgIHN0YXRlLnJldHVybkhhbmRsZXJSZXN1bHQgPSAhIVJFVFVSTl9IQU5ETEVSX1JFU1VMVDsKICAgIHN0YXRlLm5leHRIYW5kbGVyID0gbmV4dEhhbmRsZXI7CiAgICBzdGF0ZS5jb3VudGVyID0gMDsKICAgIHN0YXRlLmRvbmUgPSBmYWxzZTsKICAgIHNldEludGVybmFsU3RhdGUodGhpcywgc3RhdGUpOwogIH07CgogIEl0ZXJhdG9yUHJveHkucHJvdG90eXBlID0gSVNfSVRFUkFUT1IgPyBXcmFwRm9yVmFsaWRJdGVyYXRvclByb3RvdHlwZSA6IEl0ZXJhdG9ySGVscGVyUHJvdG90eXBlOwoKICByZXR1cm4gSXRlcmF0b3JQcm94eTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDk0Nzk6Ci8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBERVNDUklQVE9SUyA9IF9fd2VicGFja19yZXF1aXJlX18oMzcyNCk7CnZhciBkZWZpbmVCdWlsdEluQWNjZXNzb3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDIxMDYpOwp2YXIgcmVnRXhwRmxhZ3NEZXRlY3Rpb24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDc1OTQpOwp2YXIgcmVnRXhwRmxhZ3NHZXR0ZXJJbXBsZW1lbnRhdGlvbiA9IF9fd2VicGFja19yZXF1aXJlX18oNzk3OSk7CgovLyBgUmVnRXhwLnByb3RvdHlwZS5mbGFnc2AgZ2V0dGVyCi8vIGh0dHBzOi8vdGMzOS5lcy9lY21hMjYyLyNzZWMtZ2V0LXJlZ2V4cC5wcm90b3R5cGUuZmxhZ3MKaWYgKERFU0NSSVBUT1JTICYmICFyZWdFeHBGbGFnc0RldGVjdGlvbi5jb3JyZWN0KSB7CiAgZGVmaW5lQnVpbHRJbkFjY2Vzc29yKFJlZ0V4cC5wcm90b3R5cGUsICdmbGFncycsIHsKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgIGdldDogcmVnRXhwRmxhZ3NHZXR0ZXJJbXBsZW1lbnRhdGlvbgogIH0pOwoKICByZWdFeHBGbGFnc0RldGVjdGlvbi5jb3JyZWN0ID0gdHJ1ZTsKfQoKCi8qKiovIH0pLAoKLyoqKi8gOTQ4NjoKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyICQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1MTgpOwp2YXIgZ2xvYmFsVGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oNDU3Nik7CnZhciB1bmN1cnJ5VGhpcyA9IF9fd2VicGFja19yZXF1aXJlX18oOTUwNCk7CnZhciBhbk9iamVjdE9yVW5kZWZpbmVkID0gX193ZWJwYWNrX3JlcXVpcmVfXygzOTcyKTsKdmFyIGFuVWludDhBcnJheSA9IF9fd2VicGFja19yZXF1aXJlX18oNDE1NCk7CnZhciBub3REZXRhY2hlZCA9IF9fd2VicGFja19yZXF1aXJlX18oNTE2OSk7CnZhciBiYXNlNjRNYXAgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDI4MDQpOwp2YXIgZ2V0QWxwaGFiZXRPcHRpb24gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk0NCk7Cgp2YXIgYmFzZTY0QWxwaGFiZXQgPSBiYXNlNjRNYXAuaTJjOwp2YXIgYmFzZTY0VXJsQWxwaGFiZXQgPSBiYXNlNjRNYXAuaTJjVXJsOwoKdmFyIGNoYXJBdCA9IHVuY3VycnlUaGlzKCcnLmNoYXJBdCk7Cgp2YXIgVWludDhBcnJheSA9IGdsb2JhbFRoaXMuVWludDhBcnJheTsKCnZhciBJTkNPUlJFQ1RfQkVIQVZJT1JfT1JfRE9FU05UX0VYSVNUUyA9ICFVaW50OEFycmF5IHx8ICFVaW50OEFycmF5LnByb3RvdHlwZS50b0Jhc2U2NCB8fCAhZnVuY3Rpb24gKCkgewogIHRyeSB7CiAgICB2YXIgdGFyZ2V0ID0gbmV3IFVpbnQ4QXJyYXkoKTsKICAgIHRhcmdldC50b0Jhc2U2NChudWxsKTsKICB9IGNhdGNoIChlcnJvcikgewogICAgcmV0dXJuIHRydWU7CiAgfQp9KCk7CgovLyBgVWludDhBcnJheS5wcm90b3R5cGUudG9CYXNlNjRgIG1ldGhvZAovLyBodHRwczovL2dpdGh1Yi5jb20vdGMzOS9wcm9wb3NhbC1hcnJheWJ1ZmZlci1iYXNlNjQKaWYgKFVpbnQ4QXJyYXkpICQoeyB0YXJnZXQ6ICdVaW50OEFycmF5JywgcHJvdG86IHRydWUsIGZvcmNlZDogSU5DT1JSRUNUX0JFSEFWSU9SX09SX0RPRVNOVF9FWElTVFMgfSwgewogIHRvQmFzZTY0OiBmdW5jdGlvbiB0b0Jhc2U2NCgvKiBvcHRpb25zICovKSB7CiAgICB2YXIgYXJyYXkgPSBhblVpbnQ4QXJyYXkodGhpcyk7CiAgICB2YXIgb3B0aW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPyBhbk9iamVjdE9yVW5kZWZpbmVkKGFyZ3VtZW50c1swXSkgOiB1bmRlZmluZWQ7CiAgICB2YXIgYWxwaGFiZXQgPSBnZXRBbHBoYWJldE9wdGlvbihvcHRpb25zKSA9PT0gJ2Jhc2U2NCcgPyBiYXNlNjRBbHBoYWJldCA6IGJhc2U2NFVybEFscGhhYmV0OwogICAgdmFyIG9taXRQYWRkaW5nID0gISFvcHRpb25zICYmICEhb3B0aW9ucy5vbWl0UGFkZGluZzsKICAgIG5vdERldGFjaGVkKHRoaXMuYnVmZmVyKTsKCiAgICB2YXIgcmVzdWx0ID0gJyc7CiAgICB2YXIgaSA9IDA7CiAgICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoOwogICAgdmFyIHRyaXBsZXQ7CgogICAgdmFyIGF0ID0gZnVuY3Rpb24gKHNoaWZ0KSB7CiAgICAgIHJldHVybiBjaGFyQXQoYWxwaGFiZXQsICh0cmlwbGV0ID4+ICg2ICogc2hpZnQpKSAmIDYzKTsKICAgIH07CgogICAgZm9yICg7IGkgKyAyIDwgbGVuZ3RoOyBpICs9IDMpIHsKICAgICAgdHJpcGxldCA9IChhcnJheVtpXSA8PCAxNikgKyAoYXJyYXlbaSArIDFdIDw8IDgpICsgYXJyYXlbaSArIDJdOwogICAgICByZXN1bHQgKz0gYXQoMykgKyBhdCgyKSArIGF0KDEpICsgYXQoMCk7CiAgICB9CiAgICBpZiAoaSArIDIgPT09IGxlbmd0aCkgewogICAgICB0cmlwbGV0ID0gKGFycmF5W2ldIDw8IDE2KSArIChhcnJheVtpICsgMV0gPDwgOCk7CiAgICAgIHJlc3VsdCArPSBhdCgzKSArIGF0KDIpICsgYXQoMSkgKyAob21pdFBhZGRpbmcgPyAnJyA6ICc9Jyk7CiAgICB9IGVsc2UgaWYgKGkgKyAxID09PSBsZW5ndGgpIHsKICAgICAgdHJpcGxldCA9IGFycmF5W2ldIDw8IDE2OwogICAgICByZXN1bHQgKz0gYXQoMykgKyBhdCgyKSArIChvbWl0UGFkZGluZyA/ICcnIDogJz09Jyk7CiAgICB9CgogICAgcmV0dXJuIHJlc3VsdDsKICB9Cn0pOwoKCi8qKiovIH0pLAoKLyoqKi8gOTUwNDoKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBOQVRJVkVfQklORCA9IF9fd2VicGFja19yZXF1aXJlX18oNjE2KTsKCnZhciBGdW5jdGlvblByb3RvdHlwZSA9IEZ1bmN0aW9uLnByb3RvdHlwZTsKdmFyIGNhbGwgPSBGdW5jdGlvblByb3RvdHlwZS5jYWxsOwovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tZnVuY3Rpb24tcHJvdG90eXBlLWJpbmQgLS0gc2FmZQp2YXIgdW5jdXJyeVRoaXNXaXRoQmluZCA9IE5BVElWRV9CSU5EICYmIEZ1bmN0aW9uUHJvdG90eXBlLmJpbmQuYmluZChjYWxsLCBjYWxsKTsKCm1vZHVsZS5leHBvcnRzID0gTkFUSVZFX0JJTkQgPyB1bmN1cnJ5VGhpc1dpdGhCaW5kIDogZnVuY3Rpb24gKGZuKSB7CiAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgIHJldHVybiBjYWxsLmFwcGx5KGZuLCBhcmd1bWVudHMpOwogIH07Cn07CgoKLyoqKi8gfSksCgovKioqLyA5NTE5OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGdsb2JhbFRoaXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ1NzYpOwp2YXIgdXNlckFnZW50ID0gX193ZWJwYWNrX3JlcXVpcmVfXygyODM5KTsKCnZhciBwcm9jZXNzID0gZ2xvYmFsVGhpcy5wcm9jZXNzOwp2YXIgRGVubyA9IGdsb2JhbFRoaXMuRGVubzsKdmFyIHZlcnNpb25zID0gcHJvY2VzcyAmJiBwcm9jZXNzLnZlcnNpb25zIHx8IERlbm8gJiYgRGVuby52ZXJzaW9uOwp2YXIgdjggPSB2ZXJzaW9ucyAmJiB2ZXJzaW9ucy52ODsKdmFyIG1hdGNoLCB2ZXJzaW9uOwoKaWYgKHY4KSB7CiAgbWF0Y2ggPSB2OC5zcGxpdCgnLicpOwogIC8vIGluIG9sZCBDaHJvbWUsIHZlcnNpb25zIG9mIFY4IGlzbid0IFY4ID0gQ2hyb21lIC8gMTAKICAvLyBidXQgdGhlaXIgY29ycmVjdCB2ZXJzaW9ucyBhcmUgbm90IGludGVyZXN0aW5nIGZvciB1cwogIHZlcnNpb24gPSBtYXRjaFswXSA+IDAgJiYgbWF0Y2hbMF0gPCA0ID8gMSA6ICsobWF0Y2hbMF0gKyBtYXRjaFsxXSk7Cn0KCi8vIEJyb3dzZXJGUyBOb2RlSlMgYHByb2Nlc3NgIHBvbHlmaWxsIGluY29ycmVjdGx5IHNldCBgLnY4YCB0byBgMC4wYAovLyBzbyBjaGVjayBgdXNlckFnZW50YCBldmVuIGlmIGAudjhgIGV4aXN0cywgYnV0IDAKaWYgKCF2ZXJzaW9uICYmIHVzZXJBZ2VudCkgewogIG1hdGNoID0gdXNlckFnZW50Lm1hdGNoKC9FZGdlXC8oXGQrKS8pOwogIGlmICghbWF0Y2ggfHwgbWF0Y2hbMV0gPj0gNzQpIHsKICAgIG1hdGNoID0gdXNlckFnZW50Lm1hdGNoKC9DaHJvbWVcLyhcZCspLyk7CiAgICBpZiAobWF0Y2gpIHZlcnNpb24gPSArbWF0Y2hbMV07CiAgfQp9Cgptb2R1bGUuZXhwb3J0cyA9IHZlcnNpb247CgoKLyoqKi8gfSksCgovKioqLyA5NTM5OgovKioqLyAoKG1vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKdmFyIGNhbGwgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1NjUpOwp2YXIgYW5PYmplY3QgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg1NTEpOwp2YXIgZ2V0TWV0aG9kID0gX193ZWJwYWNrX3JlcXVpcmVfXyg1OTY2KTsKCm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0ZXJhdG9yLCBraW5kLCB2YWx1ZSkgewogIHZhciBpbm5lclJlc3VsdCwgaW5uZXJFcnJvcjsKICBhbk9iamVjdChpdGVyYXRvcik7CiAgdHJ5IHsKICAgIGlubmVyUmVzdWx0ID0gZ2V0TWV0aG9kKGl0ZXJhdG9yLCAncmV0dXJuJyk7CiAgICBpZiAoIWlubmVyUmVzdWx0KSB7CiAgICAgIGlmIChraW5kID09PSAndGhyb3cnKSB0aHJvdyB2YWx1ZTsKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQogICAgaW5uZXJSZXN1bHQgPSBjYWxsKGlubmVyUmVzdWx0LCBpdGVyYXRvcik7CiAgfSBjYXRjaCAoZXJyb3IpIHsKICAgIGlubmVyRXJyb3IgPSB0cnVlOwogICAgaW5uZXJSZXN1bHQgPSBlcnJvcjsKICB9CiAgaWYgKGtpbmQgPT09ICd0aHJvdycpIHRocm93IHZhbHVlOwogIGlmIChpbm5lckVycm9yKSB0aHJvdyBpbm5lclJlc3VsdDsKICBhbk9iamVjdChpbm5lclJlc3VsdCk7CiAgcmV0dXJuIHZhbHVlOwp9OwoKCi8qKiovIH0pLAoKLyoqKi8gOTU2NToKLyoqKi8gKChtb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBOQVRJVkVfQklORCA9IF9fd2VicGFja19yZXF1aXJlX18oNjE2KTsKCnZhciBjYWxsID0gRnVuY3Rpb24ucHJvdG90eXBlLmNhbGw7Ci8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBlcy9uby1mdW5jdGlvbi1wcm90b3R5cGUtYmluZCAtLSBzYWZlCm1vZHVsZS5leHBvcnRzID0gTkFUSVZFX0JJTkQgPyBjYWxsLmJpbmQoY2FsbCkgOiBmdW5jdGlvbiAoKSB7CiAgcmV0dXJuIGNhbGwuYXBwbHkoY2FsbCwgYXJndW1lbnRzKTsKfTsKCgovKioqLyB9KSwKCi8qKiovIDk1Nzc6Ci8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCnZhciBhcnJheVdpdGggPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk5MjgpOwp2YXIgQXJyYXlCdWZmZXJWaWV3Q29yZSA9IF9fd2VicGFja19yZXF1aXJlX18oNDY0NCk7CnZhciBpc0JpZ0ludEFycmF5ID0gX193ZWJwYWNrX3JlcXVpcmVfXygxMTA4KTsKdmFyIHRvSW50ZWdlck9ySW5maW5pdHkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDEyOTEpOwp2YXIgdG9CaWdJbnQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDU4NTQpOwoKdmFyIGFUeXBlZEFycmF5ID0gQXJyYXlCdWZmZXJWaWV3Q29yZS5hVHlwZWRBcnJheTsKdmFyIGdldFR5cGVkQXJyYXlDb25zdHJ1Y3RvciA9IEFycmF5QnVmZmVyVmlld0NvcmUuZ2V0VHlwZWRBcnJheUNvbnN0cnVjdG9yOwp2YXIgZXhwb3J0VHlwZWRBcnJheU1ldGhvZCA9IEFycmF5QnVmZmVyVmlld0NvcmUuZXhwb3J0VHlwZWRBcnJheU1ldGhvZDsKCnZhciBQUk9QRVJfT1JERVIgPSBmdW5jdGlvbiAoKSB7CiAgdHJ5IHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby10aHJvdy1saXRlcmFsLCBlcy9uby10eXBlZC1hcnJheXMsIGVzL25vLWFycmF5LXByb3RvdHlwZS13aXRoIC0tIHJlcXVpcmVkIGZvciB0ZXN0aW5nCiAgICBuZXcgSW50OEFycmF5KDEpWyd3aXRoJ10oMiwgeyB2YWx1ZU9mOiBmdW5jdGlvbiAoKSB7IHRocm93IDg7IH0gfSk7CiAgfSBjYXRjaCAoZXJyb3IpIHsKICAgIC8vIHNvbWUgZWFybHkgaW1wbGVtZW50YXRpb25zLCBsaWtlIFdlYktpdCwgZG9lcyBub3QgZm9sbG93IHRoZSBmaW5hbCBzZW1hbnRpYwogICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3RjMzkvcHJvcG9zYWwtY2hhbmdlLWFycmF5LWJ5LWNvcHkvcHVsbC84NgogICAgcmV0dXJuIGVycm9yID09PSA4OwogIH0KfSgpOwoKLy8gQnVnIGluIFdlYktpdC4gSXQgc2hvdWxkIHRydW5jYXRlIGEgbmVnYXRpdmUgZnJhY3Rpb25hbCBpbmRleCB0byB6ZXJvLCBidXQgaW5zdGVhZCB0aHJvd3MgYW4gZXJyb3IKdmFyIFRIUk9XX09OX05FR0FUSVZFX0ZSQUNUSU9OQUxfSU5ERVggPSBQUk9QRVJfT1JERVIgJiYgZnVuY3Rpb24gKCkgewogIHRyeSB7CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tdHlwZWQtYXJyYXlzLCBlcy9uby1hcnJheS1wcm90b3R5cGUtd2l0aCAtLSByZXF1aXJlZCBmb3IgdGVzdGluZwogICAgbmV3IEludDhBcnJheSgxKVsnd2l0aCddKC0wLjUsIDEpOwogIH0gY2F0Y2ggKGVycm9yKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0oKTsKCi8vIGAlVHlwZWRBcnJheSUucHJvdG90eXBlLndpdGhgIG1ldGhvZAovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLSV0eXBlZGFycmF5JS5wcm90b3R5cGUud2l0aApleHBvcnRUeXBlZEFycmF5TWV0aG9kKCd3aXRoJywgeyAnd2l0aCc6IGZ1bmN0aW9uIChpbmRleCwgdmFsdWUpIHsKICB2YXIgTyA9IGFUeXBlZEFycmF5KHRoaXMpOwogIHZhciByZWxhdGl2ZUluZGV4ID0gdG9JbnRlZ2VyT3JJbmZpbml0eShpbmRleCk7CiAgdmFyIGFjdHVhbFZhbHVlID0gaXNCaWdJbnRBcnJheShPKSA/IHRvQmlnSW50KHZhbHVlKSA6ICt2YWx1ZTsKICByZXR1cm4gYXJyYXlXaXRoKE8sIGdldFR5cGVkQXJyYXlDb25zdHJ1Y3RvcihPKSwgcmVsYXRpdmVJbmRleCwgYWN0dWFsVmFsdWUpOwp9IH1bJ3dpdGgnXSwgIVBST1BFUl9PUkRFUiB8fCBUSFJPV19PTl9ORUdBVElWRV9GUkFDVElPTkFMX0lOREVYKTsKCgovKioqLyB9KSwKCi8qKiovIDk2MTc6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgdG9JbmRleGVkT2JqZWN0ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg1Mzk3KTsKdmFyIHRvQWJzb2x1dGVJbmRleCA9IF9fd2VicGFja19yZXF1aXJlX18oNTYxMCk7CnZhciBsZW5ndGhPZkFycmF5TGlrZSA9IF9fd2VicGFja19yZXF1aXJlX18oNjE5OCk7CgovLyBgQXJyYXkucHJvdG90eXBlLnsgaW5kZXhPZiwgaW5jbHVkZXMgfWAgbWV0aG9kcyBpbXBsZW1lbnRhdGlvbgp2YXIgY3JlYXRlTWV0aG9kID0gZnVuY3Rpb24gKElTX0lOQ0xVREVTKSB7CiAgcmV0dXJuIGZ1bmN0aW9uICgkdGhpcywgZWwsIGZyb21JbmRleCkgewogICAgdmFyIE8gPSB0b0luZGV4ZWRPYmplY3QoJHRoaXMpOwogICAgdmFyIGxlbmd0aCA9IGxlbmd0aE9mQXJyYXlMaWtlKE8pOwogICAgaWYgKGxlbmd0aCA9PT0gMCkgcmV0dXJuICFJU19JTkNMVURFUyAmJiAtMTsKICAgIHZhciBpbmRleCA9IHRvQWJzb2x1dGVJbmRleChmcm9tSW5kZXgsIGxlbmd0aCk7CiAgICB2YXIgdmFsdWU7CiAgICAvLyBBcnJheSNpbmNsdWRlcyB1c2VzIFNhbWVWYWx1ZVplcm8gZXF1YWxpdHkgYWxnb3JpdGhtCiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tc2VsZi1jb21wYXJlIC0tIE5hTiBjaGVjawogICAgaWYgKElTX0lOQ0xVREVTICYmIGVsICE9PSBlbCkgd2hpbGUgKGxlbmd0aCA+IGluZGV4KSB7CiAgICAgIHZhbHVlID0gT1tpbmRleCsrXTsKICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXNlbGYtY29tcGFyZSAtLSBOYU4gY2hlY2sKICAgICAgaWYgKHZhbHVlICE9PSB2YWx1ZSkgcmV0dXJuIHRydWU7CiAgICAvLyBBcnJheSNpbmRleE9mIGlnbm9yZXMgaG9sZXMsIEFycmF5I2luY2x1ZGVzIC0gbm90CiAgICB9IGVsc2UgZm9yICg7bGVuZ3RoID4gaW5kZXg7IGluZGV4KyspIHsKICAgICAgaWYgKChJU19JTkNMVURFUyB8fCBpbmRleCBpbiBPKSAmJiBPW2luZGV4XSA9PT0gZWwpIHJldHVybiBJU19JTkNMVURFUyB8fCBpbmRleCB8fCAwOwogICAgfSByZXR1cm4gIUlTX0lOQ0xVREVTICYmIC0xOwogIH07Cn07Cgptb2R1bGUuZXhwb3J0cyA9IHsKICAvLyBgQXJyYXkucHJvdG90eXBlLmluY2x1ZGVzYCBtZXRob2QKICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5pbmNsdWRlcwogIGluY2x1ZGVzOiBjcmVhdGVNZXRob2QodHJ1ZSksCiAgLy8gYEFycmF5LnByb3RvdHlwZS5pbmRleE9mYCBtZXRob2QKICAvLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLWFycmF5LnByb3RvdHlwZS5pbmRleG9mCiAgaW5kZXhPZjogY3JlYXRlTWV0aG9kKGZhbHNlKQp9OwoKCi8qKiovIH0pLAoKLyoqKi8gOTYzMToKLyoqKi8gKChfX3VudXNlZF93ZWJwYWNrX21vZHVsZSwgX191bnVzZWRfd2VicGFja19leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSA9PiB7CgoKLy8gVE9ETzogUmVtb3ZlIGZyb20gYGNvcmUtanNANGAKX193ZWJwYWNrX3JlcXVpcmVfXyg5NDg2KTsKCgovKioqLyB9KSwKCi8qKiovIDk3OTc6Ci8qKiovICgoX191bnVzZWRfd2VicGFja19tb2R1bGUsIF9fdW51c2VkX3dlYnBhY2tfZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXykgPT4gewoKCi8vIFRPRE86IFJlbW92ZSBmcm9tIGBjb3JlLWpzQDRgCl9fd2VicGFja19yZXF1aXJlX18oNDIyNik7CgoKLyoqKi8gfSksCgovKioqLyA5ODM1OgovKioqLyAoKG1vZHVsZSkgPT4gewoKCi8vIFNob3VsZCBnZXQgaXRlcmF0b3IgcmVjb3JkIG9mIGEgc2V0LWxpa2Ugb2JqZWN0IGJlZm9yZSBjbG9uaW5nIHRoaXMKLy8gaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTI4OTQzMAptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChNRVRIT0RfTkFNRSkgewogIHRyeSB7CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZXMvbm8tc2V0IC0tIG5lZWRlZCBmb3IgdGVzdAogICAgdmFyIGJhc2VTZXQgPSBuZXcgU2V0KCk7CiAgICB2YXIgc2V0TGlrZSA9IHsKICAgICAgc2l6ZTogMCwKICAgICAgaGFzOiBmdW5jdGlvbiAoKSB7IHJldHVybiB0cnVlOyB9LAogICAgICBrZXlzOiBmdW5jdGlvbiAoKSB7CiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGVzL25vLW9iamVjdC1kZWZpbmVwcm9wZXJ0eSAtLSBuZWVkZWQgZm9yIHRlc3QKICAgICAgICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KHt9LCAnbmV4dCcsIHsKICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkgewogICAgICAgICAgICBiYXNlU2V0LmNsZWFyKCk7CiAgICAgICAgICAgIGJhc2VTZXQuYWRkKDQpOwogICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgICAgICAgIHJldHVybiB7IGRvbmU6IHRydWUgfTsKICAgICAgICAgICAgfTsKICAgICAgICAgIH0KICAgICAgICB9KTsKICAgICAgfQogICAgfTsKICAgIHZhciByZXN1bHQgPSBiYXNlU2V0W01FVEhPRF9OQU1FXShzZXRMaWtlKTsKCiAgICByZXR1cm4gcmVzdWx0LnNpemUgPT09IDEgJiYgcmVzdWx0LnZhbHVlcygpLm5leHQoKS52YWx1ZSA9PT0gNDsKICB9IGNhdGNoIChlcnJvcikgewogICAgcmV0dXJuIGZhbHNlOwogIH0KfTsKCgovKioqLyB9KSwKCi8qKiovIDk5Mjg6Ci8qKiovICgobW9kdWxlLCBfX3VudXNlZF93ZWJwYWNrX2V4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pID0+IHsKCgp2YXIgbGVuZ3RoT2ZBcnJheUxpa2UgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDYxOTgpOwp2YXIgdG9JbnRlZ2VyT3JJbmZpbml0eSA9IF9fd2VicGFja19yZXF1aXJlX18oMTI5MSk7Cgp2YXIgJFJhbmdlRXJyb3IgPSBSYW5nZUVycm9yOwoKLy8gaHR0cHM6Ly90YzM5LmVzL2VjbWEyNjIvI3NlYy1hcnJheS5wcm90b3R5cGUud2l0aAovLyBodHRwczovL3RjMzkuZXMvZWNtYTI2Mi8jc2VjLSV0eXBlZGFycmF5JS5wcm90b3R5cGUud2l0aAptb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChPLCBDLCBpbmRleCwgdmFsdWUpIHsKICB2YXIgbGVuID0gbGVuZ3RoT2ZBcnJheUxpa2UoTyk7CiAgdmFyIHJlbGF0aXZlSW5kZXggPSB0b0ludGVnZXJPckluZmluaXR5KGluZGV4KTsKICB2YXIgYWN0dWFsSW5kZXggPSByZWxhdGl2ZUluZGV4IDwgMCA/IGxlbiArIHJlbGF0aXZlSW5kZXggOiByZWxhdGl2ZUluZGV4OwogIGlmIChhY3R1YWxJbmRleCA+PSBsZW4gfHwgYWN0dWFsSW5kZXggPCAwKSB0aHJvdyBuZXcgJFJhbmdlRXJyb3IoJ0luY29ycmVjdCBpbmRleCcpOwogIHZhciBBID0gbmV3IEMobGVuKTsKICB2YXIgayA9IDA7CiAgZm9yICg7IGsgPCBsZW47IGsrKykgQVtrXSA9IGsgPT09IGFjdHVhbEluZGV4ID8gdmFsdWUgOiBPW2tdOwogIHJldHVybiBBOwp9OwoKCi8qKiovIH0pCgovKioqKioqLyB9KTsKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KLyoqKioqKi8gLy8gVGhlIG1vZHVsZSBjYWNoZQovKioqKioqLyB2YXIgX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fID0ge307Ci8qKioqKiovIAovKioqKioqLyAvLyBUaGUgcmVxdWlyZSBmdW5jdGlvbgovKioqKioqLyBmdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7Ci8qKioqKiovIAkvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGUKLyoqKioqKi8gCXZhciBjYWNoZWRNb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdOwovKioqKioqLyAJaWYgKGNhY2hlZE1vZHVsZSAhPT0gdW5kZWZpbmVkKSB7Ci8qKioqKiovIAkJcmV0dXJuIGNhY2hlZE1vZHVsZS5leHBvcnRzOwovKioqKioqLyAJfQovKioqKioqLyAJLy8gQ3JlYXRlIGEgbmV3IG1vZHVsZSAoYW5kIHB1dCBpdCBpbnRvIHRoZSBjYWNoZSkKLyoqKioqKi8gCXZhciBtb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdID0gewovKioqKioqLyAJCS8vIG5vIG1vZHVsZS5pZCBuZWVkZWQKLyoqKioqKi8gCQkvLyBubyBtb2R1bGUubG9hZGVkIG5lZWRlZAovKioqKioqLyAJCWV4cG9ydHM6IHt9Ci8qKioqKiovIAl9OwovKioqKioqLyAKLyoqKioqKi8gCS8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvbgovKioqKioqLyAJX193ZWJwYWNrX21vZHVsZXNfX1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7Ci8qKioqKiovIAovKioqKioqLyAJLy8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGUKLyoqKioqKi8gCXJldHVybiBtb2R1bGUuZXhwb3J0czsKLyoqKioqKi8gfQovKioqKioqLyAKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi8KLyoqKioqKi8gLyogd2VicGFjay9ydW50aW1lL2RlZmluZSBwcm9wZXJ0eSBnZXR0ZXJzICovCi8qKioqKiovICgoKSA9PiB7Ci8qKioqKiovIAkvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9ucyBmb3IgaGFybW9ueSBleHBvcnRzCi8qKioqKiovIAlfX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSAoZXhwb3J0cywgZGVmaW5pdGlvbikgPT4gewovKioqKioqLyAJCWZvcih2YXIga2V5IGluIGRlZmluaXRpb24pIHsKLyoqKioqKi8gCQkJaWYoX193ZWJwYWNrX3JlcXVpcmVfXy5vKGRlZmluaXRpb24sIGtleSkgJiYgIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBrZXkpKSB7Ci8qKioqKiovIAkJCQlPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywga2V5LCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZGVmaW5pdGlvbltrZXldIH0pOwovKioqKioqLyAJCQl9Ci8qKioqKiovIAkJfQovKioqKioqLyAJfTsKLyoqKioqKi8gfSkoKTsKLyoqKioqKi8gCi8qKioqKiovIC8qIHdlYnBhY2svcnVudGltZS9oYXNPd25Qcm9wZXJ0eSBzaG9ydGhhbmQgKi8KLyoqKioqKi8gKCgpID0+IHsKLyoqKioqKi8gCV9fd2VicGFja19yZXF1aXJlX18ubyA9IChvYmosIHByb3ApID0+IChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKSkKLyoqKioqKi8gfSkoKTsKLyoqKioqKi8gCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCnZhciBfX3dlYnBhY2tfZXhwb3J0c19fID0ge307CgovLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5hcnJheS5wdXNoLmpzCnZhciBlc19hcnJheV9wdXNoID0gX193ZWJwYWNrX3JlcXVpcmVfXyg0MTE0KTsKLy8gRVhURVJOQUwgTU9EVUxFOiAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuYXJyYXktYnVmZmVyLmRldGFjaGVkLmpzCnZhciBlc19hcnJheV9idWZmZXJfZGV0YWNoZWQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDY1NzMpOwovLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5hcnJheS1idWZmZXIudHJhbnNmZXIuanMKdmFyIGVzX2FycmF5X2J1ZmZlcl90cmFuc2ZlciA9IF9fd2VicGFja19yZXF1aXJlX18oODEwMCk7Ci8vIEVYVEVSTkFMIE1PRFVMRTogLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLmFycmF5LWJ1ZmZlci50cmFuc2Zlci10by1maXhlZC1sZW5ndGguanMKdmFyIGVzX2FycmF5X2J1ZmZlcl90cmFuc2Zlcl90b19maXhlZF9sZW5ndGggPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDc5MzYpOwovLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5pdGVyYXRvci5jb25zdHJ1Y3Rvci5qcwp2YXIgZXNfaXRlcmF0b3JfY29uc3RydWN0b3IgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDgxMTEpOwovLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5pdGVyYXRvci5maWx0ZXIuanMKdmFyIGVzX2l0ZXJhdG9yX2ZpbHRlciA9IF9fd2VicGFja19yZXF1aXJlX18oMjQ4OSk7Ci8vIEVYVEVSTkFMIE1PRFVMRTogLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLml0ZXJhdG9yLm1hcC5qcwp2YXIgZXNfaXRlcmF0b3JfbWFwID0gX193ZWJwYWNrX3JlcXVpcmVfXygxNzAxKTsKLy8gRVhURVJOQUwgTU9EVUxFOiAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuaXRlcmF0b3Iuc29tZS5qcwp2YXIgZXNfaXRlcmF0b3Jfc29tZSA9IF9fd2VicGFja19yZXF1aXJlX18oMzU3OSk7Ci8vIEVYVEVSTkFMIE1PRFVMRTogLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLnByb21pc2Uud2l0aC1yZXNvbHZlcnMuanMKdmFyIGVzX3Byb21pc2Vfd2l0aF9yZXNvbHZlcnMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQ2MjgpOwovLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5zZXQuZGlmZmVyZW5jZS52Mi5qcwp2YXIgZXNfc2V0X2RpZmZlcmVuY2VfdjIgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDc2NDIpOwovLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5zZXQuaW50ZXJzZWN0aW9uLnYyLmpzCnZhciBlc19zZXRfaW50ZXJzZWN0aW9uX3YyID0gX193ZWJwYWNrX3JlcXVpcmVfXyg4MDA0KTsKLy8gRVhURVJOQUwgTU9EVUxFOiAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuc2V0LmlzLWRpc2pvaW50LWZyb20udjIuanMKdmFyIGVzX3NldF9pc19kaXNqb2ludF9mcm9tX3YyID0gX193ZWJwYWNrX3JlcXVpcmVfXygzODUzKTsKLy8gRVhURVJOQUwgTU9EVUxFOiAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuc2V0LmlzLXN1YnNldC1vZi52Mi5qcwp2YXIgZXNfc2V0X2lzX3N1YnNldF9vZl92MiA9IF9fd2VicGFja19yZXF1aXJlX18oNTg3Nik7Ci8vIEVYVEVSTkFMIE1PRFVMRTogLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLnNldC5pcy1zdXBlcnNldC1vZi52Mi5qcwp2YXIgZXNfc2V0X2lzX3N1cGVyc2V0X29mX3YyID0gX193ZWJwYWNrX3JlcXVpcmVfXygyNDc1KTsKLy8gRVhURVJOQUwgTU9EVUxFOiAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuc2V0LnN5bW1ldHJpYy1kaWZmZXJlbmNlLnYyLmpzCnZhciBlc19zZXRfc3ltbWV0cmljX2RpZmZlcmVuY2VfdjIgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDUwMjQpOwovLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5zZXQudW5pb24udjIuanMKdmFyIGVzX3NldF91bmlvbl92MiA9IF9fd2VicGFja19yZXF1aXJlX18oMTY5OCk7Ci8vIEVYVEVSTkFMIE1PRFVMRTogLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLnR5cGVkLWFycmF5LndpdGguanMKdmFyIGVzX3R5cGVkX2FycmF5X3dpdGggPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk1NzcpOwovLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lc25leHQudWludDgtYXJyYXkuc2V0LWZyb20tYmFzZTY0LmpzCnZhciBlc25leHRfdWludDhfYXJyYXlfc2V0X2Zyb21fYmFzZTY0ID0gX193ZWJwYWNrX3JlcXVpcmVfXygxNTQ5KTsKLy8gRVhURVJOQUwgTU9EVUxFOiAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXNuZXh0LnVpbnQ4LWFycmF5LnNldC1mcm9tLWhleC5qcwp2YXIgZXNuZXh0X3VpbnQ4X2FycmF5X3NldF9mcm9tX2hleCA9IF9fd2VicGFja19yZXF1aXJlX18oOTc5Nyk7Ci8vIEVYVEVSTkFMIE1PRFVMRTogLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzbmV4dC51aW50OC1hcnJheS50by1iYXNlNjQuanMKdmFyIGVzbmV4dF91aW50OF9hcnJheV90b19iYXNlNjQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk2MzEpOwovLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lc25leHQudWludDgtYXJyYXkudG8taGV4LmpzCnZhciBlc25leHRfdWludDhfYXJyYXlfdG9faGV4ID0gX193ZWJwYWNrX3JlcXVpcmVfXyg1NjIzKTsKLy8gRVhURVJOQUwgTU9EVUxFOiAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvd2ViLnNlbGYuanMKdmFyIHdlYl9zZWxmID0gX193ZWJwYWNrX3JlcXVpcmVfXygzNjExKTsKLy8gRVhURVJOQUwgTU9EVUxFOiAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuaXRlcmF0b3IucmVkdWNlLmpzCnZhciBlc19pdGVyYXRvcl9yZWR1Y2UgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDgyMzcpOwovLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5wcm9taXNlLnRyeS5qcwp2YXIgZXNfcHJvbWlzZV90cnkgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDE2ODkpOwovLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lc25leHQubWF0aC5zdW0tcHJlY2lzZS5qcwp2YXIgZXNuZXh0X21hdGhfc3VtX3ByZWNpc2UgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDQyMzUpOwovLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lc25leHQudWludDgtYXJyYXkuZnJvbS1iYXNlNjQuanMKdmFyIGVzbmV4dF91aW50OF9hcnJheV9mcm9tX2Jhc2U2NCA9IF9fd2VicGFja19yZXF1aXJlX18oOTQzMik7Ci8vIEVYVEVSTkFMIE1PRFVMRTogLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL3dlYi5kb20tZXhjZXB0aW9uLnN0YWNrLmpzCnZhciB3ZWJfZG9tX2V4Y2VwdGlvbl9zdGFjayA9IF9fd2VicGFja19yZXF1aXJlX18oNDk3OSk7Ci8vIEVYVEVSTkFMIE1PRFVMRTogLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL3dlYi51cmwucGFyc2UuanMKdmFyIHdlYl91cmxfcGFyc2UgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDU3ODEpOwo7Ly8gLi9zcmMvc2hhcmVkL3V0aWwuanMKCgoKCgoKCgoKCgoKCgoKCmNvbnN0IGlzTm9kZUpTID0gdHlwZW9mIHByb2Nlc3MgPT09ICJvYmplY3QiICYmIHByb2Nlc3MgKyAiIiA9PT0gIltvYmplY3QgcHJvY2Vzc10iICYmICFwcm9jZXNzLnZlcnNpb25zLm53ICYmICEocHJvY2Vzcy52ZXJzaW9ucy5lbGVjdHJvbiAmJiBwcm9jZXNzLnR5cGUgJiYgcHJvY2Vzcy50eXBlICE9PSAiYnJvd3NlciIpOwpjb25zdCBGT05UX0lERU5USVRZX01BVFJJWCA9IFswLjAwMSwgMCwgMCwgMC4wMDEsIDAsIDBdOwpjb25zdCBMSU5FX0ZBQ1RPUiA9IDEuMzU7CmNvbnN0IExJTkVfREVTQ0VOVF9GQUNUT1IgPSAwLjM1Owpjb25zdCBCQVNFTElORV9GQUNUT1IgPSBMSU5FX0RFU0NFTlRfRkFDVE9SIC8gTElORV9GQUNUT1I7CmNvbnN0IFJlbmRlcmluZ0ludGVudEZsYWcgPSB7CiAgQU5ZOiAweDAxLAogIERJU1BMQVk6IDB4MDIsCiAgUFJJTlQ6IDB4MDQsCiAgU0FWRTogMHgwOCwKICBBTk5PVEFUSU9OU19GT1JNUzogMHgxMCwKICBBTk5PVEFUSU9OU19TVE9SQUdFOiAweDIwLAogIEFOTk9UQVRJT05TX0RJU0FCTEU6IDB4NDAsCiAgSVNfRURJVElORzogMHg4MCwKICBPUExJU1Q6IDB4MTAwCn07CmNvbnN0IEFubm90YXRpb25Nb2RlID0gewogIERJU0FCTEU6IDAsCiAgRU5BQkxFOiAxLAogIEVOQUJMRV9GT1JNUzogMiwKICBFTkFCTEVfU1RPUkFHRTogMwp9Owpjb25zdCBBbm5vdGF0aW9uRWRpdG9yUHJlZml4ID0gInBkZmpzX2ludGVybmFsX2VkaXRvcl8iOwpjb25zdCBBbm5vdGF0aW9uRWRpdG9yVHlwZSA9IHsKICBESVNBQkxFOiAtMSwKICBOT05FOiAwLAogIEZSRUVURVhUOiAzLAogIEhJR0hMSUdIVDogOSwKICBTVEFNUDogMTMsCiAgSU5LOiAxNSwKICBQT1BVUDogMTYsCiAgU0lHTkFUVVJFOiAxMDEsCiAgQ09NTUVOVDogMTAyCn07CmNvbnN0IEFubm90YXRpb25FZGl0b3JQYXJhbXNUeXBlID0gewogIFJFU0laRTogMSwKICBDUkVBVEU6IDIsCiAgRlJFRVRFWFRfU0laRTogMTEsCiAgRlJFRVRFWFRfQ09MT1I6IDEyLAogIEZSRUVURVhUX09QQUNJVFk6IDEzLAogIElOS19DT0xPUjogMjEsCiAgSU5LX1RISUNLTkVTUzogMjIsCiAgSU5LX09QQUNJVFk6IDIzLAogIEhJR0hMSUdIVF9DT0xPUjogMzEsCiAgSElHSExJR0hUX1RISUNLTkVTUzogMzIsCiAgSElHSExJR0hUX0ZSRUU6IDMzLAogIEhJR0hMSUdIVF9TSE9XX0FMTDogMzQsCiAgRFJBV19TVEVQOiA0MQp9Owpjb25zdCBQZXJtaXNzaW9uRmxhZyA9IHsKICBQUklOVDogMHgwNCwKICBNT0RJRllfQ09OVEVOVFM6IDB4MDgsCiAgQ09QWTogMHgxMCwKICBNT0RJRllfQU5OT1RBVElPTlM6IDB4MjAsCiAgRklMTF9JTlRFUkFDVElWRV9GT1JNUzogMHgxMDAsCiAgQ09QWV9GT1JfQUNDRVNTSUJJTElUWTogMHgyMDAsCiAgQVNTRU1CTEU6IDB4NDAwLAogIFBSSU5UX0hJR0hfUVVBTElUWTogMHg4MDAKfTsKY29uc3QgVGV4dFJlbmRlcmluZ01vZGUgPSB7CiAgRklMTDogMCwKICBTVFJPS0U6IDEsCiAgRklMTF9TVFJPS0U6IDIsCiAgSU5WSVNJQkxFOiAzLAogIEZJTExfQUREX1RPX1BBVEg6IDQsCiAgU1RST0tFX0FERF9UT19QQVRIOiA1LAogIEZJTExfU1RST0tFX0FERF9UT19QQVRIOiA2LAogIEFERF9UT19QQVRIOiA3LAogIEZJTExfU1RST0tFX01BU0s6IDMsCiAgQUREX1RPX1BBVEhfRkxBRzogNAp9Owpjb25zdCBJbWFnZUtpbmQgPSB7CiAgR1JBWVNDQUxFXzFCUFA6IDEsCiAgUkdCXzI0QlBQOiAyLAogIFJHQkFfMzJCUFA6IDMKfTsKY29uc3QgQW5ub3RhdGlvblR5cGUgPSB7CiAgVEVYVDogMSwKICBMSU5LOiAyLAogIEZSRUVURVhUOiAzLAogIExJTkU6IDQsCiAgU1FVQVJFOiA1LAogIENJUkNMRTogNiwKICBQT0xZR09OOiA3LAogIFBPTFlMSU5FOiA4LAogIEhJR0hMSUdIVDogOSwKICBVTkRFUkxJTkU6IDEwLAogIFNRVUlHR0xZOiAxMSwKICBTVFJJS0VPVVQ6IDEyLAogIFNUQU1QOiAxMywKICBDQVJFVDogMTQsCiAgSU5LOiAxNSwKICBQT1BVUDogMTYsCiAgRklMRUFUVEFDSE1FTlQ6IDE3LAogIFNPVU5EOiAxOCwKICBNT1ZJRTogMTksCiAgV0lER0VUOiAyMCwKICBTQ1JFRU46IDIxLAogIFBSSU5URVJNQVJLOiAyMiwKICBUUkFQTkVUOiAyMywKICBXQVRFUk1BUks6IDI0LAogIFRIUkVFRDogMjUsCiAgUkVEQUNUOiAyNgp9Owpjb25zdCBBbm5vdGF0aW9uUmVwbHlUeXBlID0gewogIEdST1VQOiAiR3JvdXAiLAogIFJFUExZOiAiUiIKfTsKY29uc3QgQW5ub3RhdGlvbkZsYWcgPSB7CiAgSU5WSVNJQkxFOiAweDAxLAogIEhJRERFTjogMHgwMiwKICBQUklOVDogMHgwNCwKICBOT1pPT006IDB4MDgsCiAgTk9ST1RBVEU6IDB4MTAsCiAgTk9WSUVXOiAweDIwLAogIFJFQURPTkxZOiAweDQwLAogIExPQ0tFRDogMHg4MCwKICBUT0dHTEVOT1ZJRVc6IDB4MTAwLAogIExPQ0tFRENPTlRFTlRTOiAweDIwMAp9Owpjb25zdCBBbm5vdGF0aW9uRmllbGRGbGFnID0gewogIFJFQURPTkxZOiAweDAwMDAwMDEsCiAgUkVRVUlSRUQ6IDB4MDAwMDAwMiwKICBOT0VYUE9SVDogMHgwMDAwMDA0LAogIE1VTFRJTElORTogMHgwMDAxMDAwLAogIFBBU1NXT1JEOiAweDAwMDIwMDAsCiAgTk9UT0dHTEVUT09GRjogMHgwMDA0MDAwLAogIFJBRElPOiAweDAwMDgwMDAsCiAgUFVTSEJVVFRPTjogMHgwMDEwMDAwLAogIENPTUJPOiAweDAwMjAwMDAsCiAgRURJVDogMHgwMDQwMDAwLAogIFNPUlQ6IDB4MDA4MDAwMCwKICBGSUxFU0VMRUNUOiAweDAxMDAwMDAsCiAgTVVMVElTRUxFQ1Q6IDB4MDIwMDAwMCwKICBET05PVFNQRUxMQ0hFQ0s6IDB4MDQwMDAwMCwKICBET05PVFNDUk9MTDogMHgwODAwMDAwLAogIENPTUI6IDB4MTAwMDAwMCwKICBSSUNIVEVYVDogMHgyMDAwMDAwLAogIFJBRElPU0lOVU5JU09OOiAweDIwMDAwMDAsCiAgQ09NTUlUT05TRUxDSEFOR0U6IDB4NDAwMDAwMAp9Owpjb25zdCBBbm5vdGF0aW9uQm9yZGVyU3R5bGVUeXBlID0gewogIFNPTElEOiAxLAogIERBU0hFRDogMiwKICBCRVZFTEVEOiAzLAogIElOU0VUOiA0LAogIFVOREVSTElORTogNQp9Owpjb25zdCBBbm5vdGF0aW9uQWN0aW9uRXZlbnRUeXBlID0gewogIEU6ICJNb3VzZSBFbnRlciIsCiAgWDogIk1vdXNlIEV4aXQiLAogIEQ6ICJNb3VzZSBEb3duIiwKICBVOiAiTW91c2UgVXAiLAogIEZvOiAiRm9jdXMiLAogIEJsOiAiQmx1ciIsCiAgUE86ICJQYWdlT3BlbiIsCiAgUEM6ICJQYWdlQ2xvc2UiLAogIFBWOiAiUGFnZVZpc2libGUiLAogIFBJOiAiUGFnZUludmlzaWJsZSIsCiAgSzogIktleXN0cm9rZSIsCiAgRjogIkZvcm1hdCIsCiAgVjogIlZhbGlkYXRlIiwKICBDOiAiQ2FsY3VsYXRlIgp9Owpjb25zdCBEb2N1bWVudEFjdGlvbkV2ZW50VHlwZSA9IHsKICBXQzogIldpbGxDbG9zZSIsCiAgV1M6ICJXaWxsU2F2ZSIsCiAgRFM6ICJEaWRTYXZlIiwKICBXUDogIldpbGxQcmludCIsCiAgRFA6ICJEaWRQcmludCIKfTsKY29uc3QgUGFnZUFjdGlvbkV2ZW50VHlwZSA9IHsKICBPOiAiUGFnZU9wZW4iLAogIEM6ICJQYWdlQ2xvc2UiCn07CmNvbnN0IFZlcmJvc2l0eUxldmVsID0gewogIEVSUk9SUzogMCwKICBXQVJOSU5HUzogMSwKICBJTkZPUzogNQp9Owpjb25zdCBPUFMgPSB7CiAgZGVwZW5kZW5jeTogMSwKICBzZXRMaW5lV2lkdGg6IDIsCiAgc2V0TGluZUNhcDogMywKICBzZXRMaW5lSm9pbjogNCwKICBzZXRNaXRlckxpbWl0OiA1LAogIHNldERhc2g6IDYsCiAgc2V0UmVuZGVyaW5nSW50ZW50OiA3LAogIHNldEZsYXRuZXNzOiA4LAogIHNldEdTdGF0ZTogOSwKICBzYXZlOiAxMCwKICByZXN0b3JlOiAxMSwKICB0cmFuc2Zvcm06IDEyLAogIG1vdmVUbzogMTMsCiAgbGluZVRvOiAxNCwKICBjdXJ2ZVRvOiAxNSwKICBjdXJ2ZVRvMjogMTYsCiAgY3VydmVUbzM6IDE3LAogIGNsb3NlUGF0aDogMTgsCiAgcmVjdGFuZ2xlOiAxOSwKICBzdHJva2U6IDIwLAogIGNsb3NlU3Ryb2tlOiAyMSwKICBmaWxsOiAyMiwKICBlb0ZpbGw6IDIzLAogIGZpbGxTdHJva2U6IDI0LAogIGVvRmlsbFN0cm9rZTogMjUsCiAgY2xvc2VGaWxsU3Ryb2tlOiAyNiwKICBjbG9zZUVPRmlsbFN0cm9rZTogMjcsCiAgZW5kUGF0aDogMjgsCiAgY2xpcDogMjksCiAgZW9DbGlwOiAzMCwKICBiZWdpblRleHQ6IDMxLAogIGVuZFRleHQ6IDMyLAogIHNldENoYXJTcGFjaW5nOiAzMywKICBzZXRXb3JkU3BhY2luZzogMzQsCiAgc2V0SFNjYWxlOiAzNSwKICBzZXRMZWFkaW5nOiAzNiwKICBzZXRGb250OiAzNywKICBzZXRUZXh0UmVuZGVyaW5nTW9kZTogMzgsCiAgc2V0VGV4dFJpc2U6IDM5LAogIG1vdmVUZXh0OiA0MCwKICBzZXRMZWFkaW5nTW92ZVRleHQ6IDQxLAogIHNldFRleHRNYXRyaXg6IDQyLAogIG5leHRMaW5lOiA0MywKICBzaG93VGV4dDogNDQsCiAgc2hvd1NwYWNlZFRleHQ6IDQ1LAogIG5leHRMaW5lU2hvd1RleHQ6IDQ2LAogIG5leHRMaW5lU2V0U3BhY2luZ1Nob3dUZXh0OiA0NywKICBzZXRDaGFyV2lkdGg6IDQ4LAogIHNldENoYXJXaWR0aEFuZEJvdW5kczogNDksCiAgc2V0U3Ryb2tlQ29sb3JTcGFjZTogNTAsCiAgc2V0RmlsbENvbG9yU3BhY2U6IDUxLAogIHNldFN0cm9rZUNvbG9yOiA1MiwKICBzZXRTdHJva2VDb2xvck46IDUzLAogIHNldEZpbGxDb2xvcjogNTQsCiAgc2V0RmlsbENvbG9yTjogNTUsCiAgc2V0U3Ryb2tlR3JheTogNTYsCiAgc2V0RmlsbEdyYXk6IDU3LAogIHNldFN0cm9rZVJHQkNvbG9yOiA1OCwKICBzZXRGaWxsUkdCQ29sb3I6IDU5LAogIHNldFN0cm9rZUNNWUtDb2xvcjogNjAsCiAgc2V0RmlsbENNWUtDb2xvcjogNjEsCiAgc2hhZGluZ0ZpbGw6IDYyLAogIGJlZ2luSW5saW5lSW1hZ2U6IDYzLAogIGJlZ2luSW1hZ2VEYXRhOiA2NCwKICBlbmRJbmxpbmVJbWFnZTogNjUsCiAgcGFpbnRYT2JqZWN0OiA2NiwKICBtYXJrUG9pbnQ6IDY3LAogIG1hcmtQb2ludFByb3BzOiA2OCwKICBiZWdpbk1hcmtlZENvbnRlbnQ6IDY5LAogIGJlZ2luTWFya2VkQ29udGVudFByb3BzOiA3MCwKICBlbmRNYXJrZWRDb250ZW50OiA3MSwKICBiZWdpbkNvbXBhdDogNzIsCiAgZW5kQ29tcGF0OiA3MywKICBwYWludEZvcm1YT2JqZWN0QmVnaW46IDc0LAogIHBhaW50Rm9ybVhPYmplY3RFbmQ6IDc1LAogIGJlZ2luR3JvdXA6IDc2LAogIGVuZEdyb3VwOiA3NywKICBiZWdpbkFubm90YXRpb246IDgwLAogIGVuZEFubm90YXRpb246IDgxLAogIHBhaW50SW1hZ2VNYXNrWE9iamVjdDogODMsCiAgcGFpbnRJbWFnZU1hc2tYT2JqZWN0R3JvdXA6IDg0LAogIHBhaW50SW1hZ2VYT2JqZWN0OiA4NSwKICBwYWludElubGluZUltYWdlWE9iamVjdDogODYsCiAgcGFpbnRJbmxpbmVJbWFnZVhPYmplY3RHcm91cDogODcsCiAgcGFpbnRJbWFnZVhPYmplY3RSZXBlYXQ6IDg4LAogIHBhaW50SW1hZ2VNYXNrWE9iamVjdFJlcGVhdDogODksCiAgcGFpbnRTb2xpZENvbG9ySW1hZ2VNYXNrOiA5MCwKICBjb25zdHJ1Y3RQYXRoOiA5MSwKICBzZXRTdHJva2VUcmFuc3BhcmVudDogOTIsCiAgc2V0RmlsbFRyYW5zcGFyZW50OiA5MywKICByYXdGaWxsUGF0aDogOTQKfTsKY29uc3QgRHJhd09QUyA9IHsKICBtb3ZlVG86IDAsCiAgbGluZVRvOiAxLAogIGN1cnZlVG86IDIsCiAgY2xvc2VQYXRoOiAzCn07CmNvbnN0IFBhc3N3b3JkUmVzcG9uc2VzID0gewogIE5FRURfUEFTU1dPUkQ6IDEsCiAgSU5DT1JSRUNUX1BBU1NXT1JEOiAyCn07CmxldCB2ZXJib3NpdHkgPSBWZXJib3NpdHlMZXZlbC5XQVJOSU5HUzsKZnVuY3Rpb24gc2V0VmVyYm9zaXR5TGV2ZWwobGV2ZWwpIHsKICBpZiAoTnVtYmVyLmlzSW50ZWdlcihsZXZlbCkpIHsKICAgIHZlcmJvc2l0eSA9IGxldmVsOwogIH0KfQpmdW5jdGlvbiBnZXRWZXJib3NpdHlMZXZlbCgpIHsKICByZXR1cm4gdmVyYm9zaXR5Owp9CmZ1bmN0aW9uIGluZm8obXNnKSB7CiAgaWYgKHZlcmJvc2l0eSA+PSBWZXJib3NpdHlMZXZlbC5JTkZPUykgewogICAgY29uc29sZS5pbmZvKGBJbmZvOiAke21zZ31gKTsKICB9Cn0KZnVuY3Rpb24gd2Fybihtc2cpIHsKICBpZiAodmVyYm9zaXR5ID49IFZlcmJvc2l0eUxldmVsLldBUk5JTkdTKSB7CiAgICBjb25zb2xlLndhcm4oYFdhcm5pbmc6ICR7bXNnfWApOwogIH0KfQpmdW5jdGlvbiB1bnJlYWNoYWJsZShtc2cpIHsKICB0aHJvdyBuZXcgRXJyb3IobXNnKTsKfQpmdW5jdGlvbiBhc3NlcnQoY29uZCwgbXNnKSB7CiAgaWYgKCFjb25kKSB7CiAgICB1bnJlYWNoYWJsZShtc2cpOwogIH0KfQpmdW5jdGlvbiBfaXNWYWxpZFByb3RvY29sKHVybCkgewogIHN3aXRjaCAodXJsPy5wcm90b2NvbCkgewogICAgY2FzZSAiaHR0cDoiOgogICAgY2FzZSAiaHR0cHM6IjoKICAgIGNhc2UgImZ0cDoiOgogICAgY2FzZSAibWFpbHRvOiI6CiAgICBjYXNlICJ0ZWw6IjoKICAgICAgcmV0dXJuIHRydWU7CiAgICBkZWZhdWx0OgogICAgICByZXR1cm4gZmFsc2U7CiAgfQp9CmZ1bmN0aW9uIGNyZWF0ZVZhbGlkQWJzb2x1dGVVcmwodXJsLCBiYXNlVXJsID0gbnVsbCwgb3B0aW9ucyA9IG51bGwpIHsKICBpZiAoIXVybCkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGlmIChvcHRpb25zICYmIHR5cGVvZiB1cmwgPT09ICJzdHJpbmciKSB7CiAgICBpZiAob3B0aW9ucy5hZGREZWZhdWx0UHJvdG9jb2wgJiYgdXJsLnN0YXJ0c1dpdGgoInd3dy4iKSkgewogICAgICBjb25zdCBkb3RzID0gdXJsLm1hdGNoKC9cLi9nKTsKICAgICAgaWYgKGRvdHM/Lmxlbmd0aCA+PSAyKSB7CiAgICAgICAgdXJsID0gYGh0dHA6Ly8ke3VybH1gOwogICAgICB9CiAgICB9CiAgICBpZiAob3B0aW9ucy50cnlDb252ZXJ0RW5jb2RpbmcpIHsKICAgICAgdHJ5IHsKICAgICAgICB1cmwgPSBzdHJpbmdUb1VURjhTdHJpbmcodXJsKTsKICAgICAgfSBjYXRjaCB7fQogICAgfQogIH0KICBjb25zdCBhYnNvbHV0ZVVybCA9IGJhc2VVcmwgPyBVUkwucGFyc2UodXJsLCBiYXNlVXJsKSA6IFVSTC5wYXJzZSh1cmwpOwogIHJldHVybiBfaXNWYWxpZFByb3RvY29sKGFic29sdXRlVXJsKSA/IGFic29sdXRlVXJsIDogbnVsbDsKfQpmdW5jdGlvbiB1cGRhdGVVcmxIYXNoKHVybCwgaGFzaCwgYWxsb3dSZWwgPSBmYWxzZSkgewogIGNvbnN0IHJlcyA9IFVSTC5wYXJzZSh1cmwpOwogIGlmIChyZXMpIHsKICAgIHJlcy5oYXNoID0gaGFzaDsKICAgIHJldHVybiByZXMuaHJlZjsKICB9CiAgaWYgKGFsbG93UmVsICYmIGNyZWF0ZVZhbGlkQWJzb2x1dGVVcmwodXJsLCAiaHR0cDovL2V4YW1wbGUuY29tIikpIHsKICAgIHJldHVybiB1cmwuc3BsaXQoIiMiLCAxKVswXSArIGAke2hhc2ggPyBgIyR7aGFzaH1gIDogIiJ9YDsKICB9CiAgcmV0dXJuICIiOwp9CmZ1bmN0aW9uIHNoYWRvdyhvYmosIHByb3AsIHZhbHVlLCBub25TZXJpYWxpemFibGUgPSBmYWxzZSkgewogIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIHByb3AsIHsKICAgIHZhbHVlLAogICAgZW51bWVyYWJsZTogIW5vblNlcmlhbGl6YWJsZSwKICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwKICAgIHdyaXRhYmxlOiBmYWxzZQogIH0pOwogIHJldHVybiB2YWx1ZTsKfQpjb25zdCBCYXNlRXhjZXB0aW9uID0gZnVuY3Rpb24gQmFzZUV4Y2VwdGlvbkNsb3N1cmUoKSB7CiAgZnVuY3Rpb24gQmFzZUV4Y2VwdGlvbihtZXNzYWdlLCBuYW1lKSB7CiAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlOwogICAgdGhpcy5uYW1lID0gbmFtZTsKICB9CiAgQmFzZUV4Y2VwdGlvbi5wcm90b3R5cGUgPSBuZXcgRXJyb3IoKTsKICBCYXNlRXhjZXB0aW9uLmNvbnN0cnVjdG9yID0gQmFzZUV4Y2VwdGlvbjsKICByZXR1cm4gQmFzZUV4Y2VwdGlvbjsKfSgpOwpjbGFzcyBQYXNzd29yZEV4Y2VwdGlvbiBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZywgY29kZSkgewogICAgc3VwZXIobXNnLCAiUGFzc3dvcmRFeGNlcHRpb24iKTsKICAgIHRoaXMuY29kZSA9IGNvZGU7CiAgfQp9CmNsYXNzIFVua25vd25FcnJvckV4Y2VwdGlvbiBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZywgZGV0YWlscykgewogICAgc3VwZXIobXNnLCAiVW5rbm93bkVycm9yRXhjZXB0aW9uIik7CiAgICB0aGlzLmRldGFpbHMgPSBkZXRhaWxzOwogIH0KfQpjbGFzcyBJbnZhbGlkUERGRXhjZXB0aW9uIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnKSB7CiAgICBzdXBlcihtc2csICJJbnZhbGlkUERGRXhjZXB0aW9uIik7CiAgfQp9CmNsYXNzIFJlc3BvbnNlRXhjZXB0aW9uIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnLCBzdGF0dXMsIG1pc3NpbmcpIHsKICAgIHN1cGVyKG1zZywgIlJlc3BvbnNlRXhjZXB0aW9uIik7CiAgICB0aGlzLnN0YXR1cyA9IHN0YXR1czsKICAgIHRoaXMubWlzc2luZyA9IG1pc3Npbmc7CiAgfQp9CmNsYXNzIEZvcm1hdEVycm9yIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnKSB7CiAgICBzdXBlcihtc2csICJGb3JtYXRFcnJvciIpOwogIH0KfQpjbGFzcyBBYm9ydEV4Y2VwdGlvbiBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZykgewogICAgc3VwZXIobXNnLCAiQWJvcnRFeGNlcHRpb24iKTsKICB9Cn0KZnVuY3Rpb24gYnl0ZXNUb1N0cmluZyhieXRlcykgewogIGlmICh0eXBlb2YgYnl0ZXMgIT09ICJvYmplY3QiIHx8IGJ5dGVzPy5sZW5ndGggPT09IHVuZGVmaW5lZCkgewogICAgdW5yZWFjaGFibGUoIkludmFsaWQgYXJndW1lbnQgZm9yIGJ5dGVzVG9TdHJpbmciKTsKICB9CiAgY29uc3QgbGVuZ3RoID0gYnl0ZXMubGVuZ3RoOwogIGNvbnN0IE1BWF9BUkdVTUVOVF9DT1VOVCA9IDgxOTI7CiAgaWYgKGxlbmd0aCA8IE1BWF9BUkdVTUVOVF9DT1VOVCkgewogICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgYnl0ZXMpOwogIH0KICBjb25zdCBzdHJCdWYgPSBbXTsKICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSBNQVhfQVJHVU1FTlRfQ09VTlQpIHsKICAgIGNvbnN0IGNodW5rRW5kID0gTWF0aC5taW4oaSArIE1BWF9BUkdVTUVOVF9DT1VOVCwgbGVuZ3RoKTsKICAgIGNvbnN0IGNodW5rID0gYnl0ZXMuc3ViYXJyYXkoaSwgY2h1bmtFbmQpOwogICAgc3RyQnVmLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBjaHVuaykpOwogIH0KICByZXR1cm4gc3RyQnVmLmpvaW4oIiIpOwp9CmZ1bmN0aW9uIHN0cmluZ1RvQnl0ZXMoc3RyKSB7CiAgaWYgKHR5cGVvZiBzdHIgIT09ICJzdHJpbmciKSB7CiAgICB1bnJlYWNoYWJsZSgiSW52YWxpZCBhcmd1bWVudCBmb3Igc3RyaW5nVG9CeXRlcyIpOwogIH0KICBjb25zdCBsZW5ndGggPSBzdHIubGVuZ3RoOwogIGNvbnN0IGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkobGVuZ3RoKTsKICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICBieXRlc1tpXSA9IHN0ci5jaGFyQ29kZUF0KGkpICYgMHhmZjsKICB9CiAgcmV0dXJuIGJ5dGVzOwp9CmZ1bmN0aW9uIHN0cmluZzMyKHZhbHVlKSB7CiAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUodmFsdWUgPj4gMjQgJiAweGZmLCB2YWx1ZSA+PiAxNiAmIDB4ZmYsIHZhbHVlID4+IDggJiAweGZmLCB2YWx1ZSAmIDB4ZmYpOwp9CmZ1bmN0aW9uIG9iamVjdFNpemUob2JqKSB7CiAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaikubGVuZ3RoOwp9CmZ1bmN0aW9uIGlzTGl0dGxlRW5kaWFuKCkgewogIGNvbnN0IGJ1ZmZlcjggPSBuZXcgVWludDhBcnJheSg0KTsKICBidWZmZXI4WzBdID0gMTsKICBjb25zdCB2aWV3MzIgPSBuZXcgVWludDMyQXJyYXkoYnVmZmVyOC5idWZmZXIsIDAsIDEpOwogIHJldHVybiB2aWV3MzJbMF0gPT09IDE7Cn0KZnVuY3Rpb24gaXNFdmFsU3VwcG9ydGVkKCkgewogIHRyeSB7CiAgICBuZXcgRnVuY3Rpb24oIiIpOwogICAgcmV0dXJuIHRydWU7CiAgfSBjYXRjaCB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQp9CmNsYXNzIEZlYXR1cmVUZXN0IHsKICBzdGF0aWMgZ2V0IGlzTGl0dGxlRW5kaWFuKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiaXNMaXR0bGVFbmRpYW4iLCBpc0xpdHRsZUVuZGlhbigpKTsKICB9CiAgc3RhdGljIGdldCBpc0V2YWxTdXBwb3J0ZWQoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJpc0V2YWxTdXBwb3J0ZWQiLCBpc0V2YWxTdXBwb3J0ZWQoKSk7CiAgfQogIHN0YXRpYyBnZXQgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCIsIHR5cGVvZiBPZmZzY3JlZW5DYW52YXMgIT09ICJ1bmRlZmluZWQiKTsKICB9CiAgc3RhdGljIGdldCBpc0ltYWdlRGVjb2RlclN1cHBvcnRlZCgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgImlzSW1hZ2VEZWNvZGVyU3VwcG9ydGVkIiwgdHlwZW9mIEltYWdlRGVjb2RlciAhPT0gInVuZGVmaW5lZCIpOwogIH0KICBzdGF0aWMgZ2V0IHBsYXRmb3JtKCkgewogICAgY29uc3QgewogICAgICBwbGF0Zm9ybSwKICAgICAgdXNlckFnZW50CiAgICB9ID0gbmF2aWdhdG9yOwogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAicGxhdGZvcm0iLCB7CiAgICAgIGlzQW5kcm9pZDogdXNlckFnZW50LmluY2x1ZGVzKCJBbmRyb2lkIiksCiAgICAgIGlzTGludXg6IHBsYXRmb3JtLmluY2x1ZGVzKCJMaW51eCIpLAogICAgICBpc01hYzogcGxhdGZvcm0uaW5jbHVkZXMoIk1hYyIpLAogICAgICBpc1dpbmRvd3M6IHBsYXRmb3JtLmluY2x1ZGVzKCJXaW4iKSwKICAgICAgaXNGaXJlZm94OiB1c2VyQWdlbnQuaW5jbHVkZXMoIkZpcmVmb3giKQogICAgfSk7CiAgfQogIHN0YXRpYyBnZXQgaXNDU1NSb3VuZFN1cHBvcnRlZCgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgImlzQ1NTUm91bmRTdXBwb3J0ZWQiLCBnbG9iYWxUaGlzLkNTUz8uc3VwcG9ydHM/Ligid2lkdGg6IHJvdW5kKDEuNXB4LCAxcHgpIikpOwogIH0KfQpjb25zdCBoZXhOdW1iZXJzID0gQXJyYXkuZnJvbShBcnJheSgyNTYpLmtleXMoKSwgbiA9PiBuLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCAiMCIpKTsKY2xhc3MgVXRpbCB7CiAgc3RhdGljIG1ha2VIZXhDb2xvcihyLCBnLCBiKSB7CiAgICByZXR1cm4gYCMke2hleE51bWJlcnNbcl19JHtoZXhOdW1iZXJzW2ddfSR7aGV4TnVtYmVyc1tiXX1gOwogIH0KICBzdGF0aWMgZG9tTWF0cml4VG9UcmFuc2Zvcm0oZG0pIHsKICAgIHJldHVybiBbZG0uYSwgZG0uYiwgZG0uYywgZG0uZCwgZG0uZSwgZG0uZl07CiAgfQogIHN0YXRpYyBzY2FsZU1pbk1heCh0cmFuc2Zvcm0sIG1pbk1heCkgewogICAgbGV0IHRlbXA7CiAgICBpZiAodHJhbnNmb3JtWzBdKSB7CiAgICAgIGlmICh0cmFuc2Zvcm1bMF0gPCAwKSB7CiAgICAgICAgdGVtcCA9IG1pbk1heFswXTsKICAgICAgICBtaW5NYXhbMF0gPSBtaW5NYXhbMl07CiAgICAgICAgbWluTWF4WzJdID0gdGVtcDsKICAgICAgfQogICAgICBtaW5NYXhbMF0gKj0gdHJhbnNmb3JtWzBdOwogICAgICBtaW5NYXhbMl0gKj0gdHJhbnNmb3JtWzBdOwogICAgICBpZiAodHJhbnNmb3JtWzNdIDwgMCkgewogICAgICAgIHRlbXAgPSBtaW5NYXhbMV07CiAgICAgICAgbWluTWF4WzFdID0gbWluTWF4WzNdOwogICAgICAgIG1pbk1heFszXSA9IHRlbXA7CiAgICAgIH0KICAgICAgbWluTWF4WzFdICo9IHRyYW5zZm9ybVszXTsKICAgICAgbWluTWF4WzNdICo9IHRyYW5zZm9ybVszXTsKICAgIH0gZWxzZSB7CiAgICAgIHRlbXAgPSBtaW5NYXhbMF07CiAgICAgIG1pbk1heFswXSA9IG1pbk1heFsxXTsKICAgICAgbWluTWF4WzFdID0gdGVtcDsKICAgICAgdGVtcCA9IG1pbk1heFsyXTsKICAgICAgbWluTWF4WzJdID0gbWluTWF4WzNdOwogICAgICBtaW5NYXhbM10gPSB0ZW1wOwogICAgICBpZiAodHJhbnNmb3JtWzFdIDwgMCkgewogICAgICAgIHRlbXAgPSBtaW5NYXhbMV07CiAgICAgICAgbWluTWF4WzFdID0gbWluTWF4WzNdOwogICAgICAgIG1pbk1heFszXSA9IHRlbXA7CiAgICAgIH0KICAgICAgbWluTWF4WzFdICo9IHRyYW5zZm9ybVsxXTsKICAgICAgbWluTWF4WzNdICo9IHRyYW5zZm9ybVsxXTsKICAgICAgaWYgKHRyYW5zZm9ybVsyXSA8IDApIHsKICAgICAgICB0ZW1wID0gbWluTWF4WzBdOwogICAgICAgIG1pbk1heFswXSA9IG1pbk1heFsyXTsKICAgICAgICBtaW5NYXhbMl0gPSB0ZW1wOwogICAgICB9CiAgICAgIG1pbk1heFswXSAqPSB0cmFuc2Zvcm1bMl07CiAgICAgIG1pbk1heFsyXSAqPSB0cmFuc2Zvcm1bMl07CiAgICB9CiAgICBtaW5NYXhbMF0gKz0gdHJhbnNmb3JtWzRdOwogICAgbWluTWF4WzFdICs9IHRyYW5zZm9ybVs1XTsKICAgIG1pbk1heFsyXSArPSB0cmFuc2Zvcm1bNF07CiAgICBtaW5NYXhbM10gKz0gdHJhbnNmb3JtWzVdOwogIH0KICBzdGF0aWMgdHJhbnNmb3JtKG0xLCBtMikgewogICAgcmV0dXJuIFttMVswXSAqIG0yWzBdICsgbTFbMl0gKiBtMlsxXSwgbTFbMV0gKiBtMlswXSArIG0xWzNdICogbTJbMV0sIG0xWzBdICogbTJbMl0gKyBtMVsyXSAqIG0yWzNdLCBtMVsxXSAqIG0yWzJdICsgbTFbM10gKiBtMlszXSwgbTFbMF0gKiBtMls0XSArIG0xWzJdICogbTJbNV0gKyBtMVs0XSwgbTFbMV0gKiBtMls0XSArIG0xWzNdICogbTJbNV0gKyBtMVs1XV07CiAgfQogIHN0YXRpYyBtdWx0aXBseUJ5RE9NTWF0cml4KG0sIG1kKSB7CiAgICByZXR1cm4gW21bMF0gKiBtZC5hICsgbVsyXSAqIG1kLmIsIG1bMV0gKiBtZC5hICsgbVszXSAqIG1kLmIsIG1bMF0gKiBtZC5jICsgbVsyXSAqIG1kLmQsIG1bMV0gKiBtZC5jICsgbVszXSAqIG1kLmQsIG1bMF0gKiBtZC5lICsgbVsyXSAqIG1kLmYgKyBtWzRdLCBtWzFdICogbWQuZSArIG1bM10gKiBtZC5mICsgbVs1XV07CiAgfQogIHN0YXRpYyBhcHBseVRyYW5zZm9ybShwLCBtLCBwb3MgPSAwKSB7CiAgICBjb25zdCBwMCA9IHBbcG9zXTsKICAgIGNvbnN0IHAxID0gcFtwb3MgKyAxXTsKICAgIHBbcG9zXSA9IHAwICogbVswXSArIHAxICogbVsyXSArIG1bNF07CiAgICBwW3BvcyArIDFdID0gcDAgKiBtWzFdICsgcDEgKiBtWzNdICsgbVs1XTsKICB9CiAgc3RhdGljIGFwcGx5VHJhbnNmb3JtVG9CZXppZXIocCwgdHJhbnNmb3JtLCBwb3MgPSAwKSB7CiAgICBjb25zdCBtMCA9IHRyYW5zZm9ybVswXTsKICAgIGNvbnN0IG0xID0gdHJhbnNmb3JtWzFdOwogICAgY29uc3QgbTIgPSB0cmFuc2Zvcm1bMl07CiAgICBjb25zdCBtMyA9IHRyYW5zZm9ybVszXTsKICAgIGNvbnN0IG00ID0gdHJhbnNmb3JtWzRdOwogICAgY29uc3QgbTUgPSB0cmFuc2Zvcm1bNV07CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDY7IGkgKz0gMikgewogICAgICBjb25zdCBwSSA9IHBbcG9zICsgaV07CiAgICAgIGNvbnN0IHBJMSA9IHBbcG9zICsgaSArIDFdOwogICAgICBwW3BvcyArIGldID0gcEkgKiBtMCArIHBJMSAqIG0yICsgbTQ7CiAgICAgIHBbcG9zICsgaSArIDFdID0gcEkgKiBtMSArIHBJMSAqIG0zICsgbTU7CiAgICB9CiAgfQogIHN0YXRpYyBhcHBseUludmVyc2VUcmFuc2Zvcm0ocCwgbSkgewogICAgY29uc3QgcDAgPSBwWzBdOwogICAgY29uc3QgcDEgPSBwWzFdOwogICAgY29uc3QgZCA9IG1bMF0gKiBtWzNdIC0gbVsxXSAqIG1bMl07CiAgICBwWzBdID0gKHAwICogbVszXSAtIHAxICogbVsyXSArIG1bMl0gKiBtWzVdIC0gbVs0XSAqIG1bM10pIC8gZDsKICAgIHBbMV0gPSAoLXAwICogbVsxXSArIHAxICogbVswXSArIG1bNF0gKiBtWzFdIC0gbVs1XSAqIG1bMF0pIC8gZDsKICB9CiAgc3RhdGljIGF4aWFsQWxpZ25lZEJvdW5kaW5nQm94KHJlY3QsIHRyYW5zZm9ybSwgb3V0cHV0KSB7CiAgICBjb25zdCBtMCA9IHRyYW5zZm9ybVswXTsKICAgIGNvbnN0IG0xID0gdHJhbnNmb3JtWzFdOwogICAgY29uc3QgbTIgPSB0cmFuc2Zvcm1bMl07CiAgICBjb25zdCBtMyA9IHRyYW5zZm9ybVszXTsKICAgIGNvbnN0IG00ID0gdHJhbnNmb3JtWzRdOwogICAgY29uc3QgbTUgPSB0cmFuc2Zvcm1bNV07CiAgICBjb25zdCByMCA9IHJlY3RbMF07CiAgICBjb25zdCByMSA9IHJlY3RbMV07CiAgICBjb25zdCByMiA9IHJlY3RbMl07CiAgICBjb25zdCByMyA9IHJlY3RbM107CiAgICBsZXQgYTAgPSBtMCAqIHIwICsgbTQ7CiAgICBsZXQgYTIgPSBhMDsKICAgIGxldCBhMSA9IG0wICogcjIgKyBtNDsKICAgIGxldCBhMyA9IGExOwogICAgbGV0IGIwID0gbTMgKiByMSArIG01OwogICAgbGV0IGIyID0gYjA7CiAgICBsZXQgYjEgPSBtMyAqIHIzICsgbTU7CiAgICBsZXQgYjMgPSBiMTsKICAgIGlmIChtMSAhPT0gMCB8fCBtMiAhPT0gMCkgewogICAgICBjb25zdCBtMXIwID0gbTEgKiByMDsKICAgICAgY29uc3QgbTFyMiA9IG0xICogcjI7CiAgICAgIGNvbnN0IG0ycjEgPSBtMiAqIHIxOwogICAgICBjb25zdCBtMnIzID0gbTIgKiByMzsKICAgICAgYTAgKz0gbTJyMTsKICAgICAgYTMgKz0gbTJyMTsKICAgICAgYTEgKz0gbTJyMzsKICAgICAgYTIgKz0gbTJyMzsKICAgICAgYjAgKz0gbTFyMDsKICAgICAgYjMgKz0gbTFyMDsKICAgICAgYjEgKz0gbTFyMjsKICAgICAgYjIgKz0gbTFyMjsKICAgIH0KICAgIG91dHB1dFswXSA9IE1hdGgubWluKG91dHB1dFswXSwgYTAsIGExLCBhMiwgYTMpOwogICAgb3V0cHV0WzFdID0gTWF0aC5taW4ob3V0cHV0WzFdLCBiMCwgYjEsIGIyLCBiMyk7CiAgICBvdXRwdXRbMl0gPSBNYXRoLm1heChvdXRwdXRbMl0sIGEwLCBhMSwgYTIsIGEzKTsKICAgIG91dHB1dFszXSA9IE1hdGgubWF4KG91dHB1dFszXSwgYjAsIGIxLCBiMiwgYjMpOwogIH0KICBzdGF0aWMgaW52ZXJzZVRyYW5zZm9ybShtKSB7CiAgICBjb25zdCBkID0gbVswXSAqIG1bM10gLSBtWzFdICogbVsyXTsKICAgIHJldHVybiBbbVszXSAvIGQsIC1tWzFdIC8gZCwgLW1bMl0gLyBkLCBtWzBdIC8gZCwgKG1bMl0gKiBtWzVdIC0gbVs0XSAqIG1bM10pIC8gZCwgKG1bNF0gKiBtWzFdIC0gbVs1XSAqIG1bMF0pIC8gZF07CiAgfQogIHN0YXRpYyBzaW5ndWxhclZhbHVlRGVjb21wb3NlMmRTY2FsZShtYXRyaXgsIG91dHB1dCkgewogICAgY29uc3QgbTAgPSBtYXRyaXhbMF07CiAgICBjb25zdCBtMSA9IG1hdHJpeFsxXTsKICAgIGNvbnN0IG0yID0gbWF0cml4WzJdOwogICAgY29uc3QgbTMgPSBtYXRyaXhbM107CiAgICBjb25zdCBhID0gbTAgKiogMiArIG0xICoqIDI7CiAgICBjb25zdCBiID0gbTAgKiBtMiArIG0xICogbTM7CiAgICBjb25zdCBjID0gbTIgKiogMiArIG0zICoqIDI7CiAgICBjb25zdCBmaXJzdCA9IChhICsgYykgLyAyOwogICAgY29uc3Qgc2Vjb25kID0gTWF0aC5zcXJ0KGZpcnN0ICoqIDIgLSAoYSAqIGMgLSBiICoqIDIpKTsKICAgIG91dHB1dFswXSA9IE1hdGguc3FydChmaXJzdCArIHNlY29uZCB8fCAxKTsKICAgIG91dHB1dFsxXSA9IE1hdGguc3FydChmaXJzdCAtIHNlY29uZCB8fCAxKTsKICB9CiAgc3RhdGljIG5vcm1hbGl6ZVJlY3QocmVjdCkgewogICAgY29uc3QgciA9IHJlY3Quc2xpY2UoMCk7CiAgICBpZiAocmVjdFswXSA+IHJlY3RbMl0pIHsKICAgICAgclswXSA9IHJlY3RbMl07CiAgICAgIHJbMl0gPSByZWN0WzBdOwogICAgfQogICAgaWYgKHJlY3RbMV0gPiByZWN0WzNdKSB7CiAgICAgIHJbMV0gPSByZWN0WzNdOwogICAgICByWzNdID0gcmVjdFsxXTsKICAgIH0KICAgIHJldHVybiByOwogIH0KICBzdGF0aWMgaW50ZXJzZWN0KHJlY3QxLCByZWN0MikgewogICAgY29uc3QgeExvdyA9IE1hdGgubWF4KE1hdGgubWluKHJlY3QxWzBdLCByZWN0MVsyXSksIE1hdGgubWluKHJlY3QyWzBdLCByZWN0MlsyXSkpOwogICAgY29uc3QgeEhpZ2ggPSBNYXRoLm1pbihNYXRoLm1heChyZWN0MVswXSwgcmVjdDFbMl0pLCBNYXRoLm1heChyZWN0MlswXSwgcmVjdDJbMl0pKTsKICAgIGlmICh4TG93ID4geEhpZ2gpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCB5TG93ID0gTWF0aC5tYXgoTWF0aC5taW4ocmVjdDFbMV0sIHJlY3QxWzNdKSwgTWF0aC5taW4ocmVjdDJbMV0sIHJlY3QyWzNdKSk7CiAgICBjb25zdCB5SGlnaCA9IE1hdGgubWluKE1hdGgubWF4KHJlY3QxWzFdLCByZWN0MVszXSksIE1hdGgubWF4KHJlY3QyWzFdLCByZWN0MlszXSkpOwogICAgaWYgKHlMb3cgPiB5SGlnaCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIHJldHVybiBbeExvdywgeUxvdywgeEhpZ2gsIHlIaWdoXTsKICB9CiAgc3RhdGljIHBvaW50Qm91bmRpbmdCb3goeCwgeSwgbWluTWF4KSB7CiAgICBtaW5NYXhbMF0gPSBNYXRoLm1pbihtaW5NYXhbMF0sIHgpOwogICAgbWluTWF4WzFdID0gTWF0aC5taW4obWluTWF4WzFdLCB5KTsKICAgIG1pbk1heFsyXSA9IE1hdGgubWF4KG1pbk1heFsyXSwgeCk7CiAgICBtaW5NYXhbM10gPSBNYXRoLm1heChtaW5NYXhbM10sIHkpOwogIH0KICBzdGF0aWMgcmVjdEJvdW5kaW5nQm94KHgwLCB5MCwgeDEsIHkxLCBtaW5NYXgpIHsKICAgIG1pbk1heFswXSA9IE1hdGgubWluKG1pbk1heFswXSwgeDAsIHgxKTsKICAgIG1pbk1heFsxXSA9IE1hdGgubWluKG1pbk1heFsxXSwgeTAsIHkxKTsKICAgIG1pbk1heFsyXSA9IE1hdGgubWF4KG1pbk1heFsyXSwgeDAsIHgxKTsKICAgIG1pbk1heFszXSA9IE1hdGgubWF4KG1pbk1heFszXSwgeTAsIHkxKTsKICB9CiAgc3RhdGljICNnZXRFeHRyZW11bU9uQ3VydmUoeDAsIHgxLCB4MiwgeDMsIHkwLCB5MSwgeTIsIHkzLCB0LCBtaW5NYXgpIHsKICAgIGlmICh0IDw9IDAgfHwgdCA+PSAxKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IG10ID0gMSAtIHQ7CiAgICBjb25zdCB0dCA9IHQgKiB0OwogICAgY29uc3QgdHR0ID0gdHQgKiB0OwogICAgY29uc3QgeCA9IG10ICogKG10ICogKG10ICogeDAgKyAzICogdCAqIHgxKSArIDMgKiB0dCAqIHgyKSArIHR0dCAqIHgzOwogICAgY29uc3QgeSA9IG10ICogKG10ICogKG10ICogeTAgKyAzICogdCAqIHkxKSArIDMgKiB0dCAqIHkyKSArIHR0dCAqIHkzOwogICAgbWluTWF4WzBdID0gTWF0aC5taW4obWluTWF4WzBdLCB4KTsKICAgIG1pbk1heFsxXSA9IE1hdGgubWluKG1pbk1heFsxXSwgeSk7CiAgICBtaW5NYXhbMl0gPSBNYXRoLm1heChtaW5NYXhbMl0sIHgpOwogICAgbWluTWF4WzNdID0gTWF0aC5tYXgobWluTWF4WzNdLCB5KTsKICB9CiAgc3RhdGljICNnZXRFeHRyZW11bSh4MCwgeDEsIHgyLCB4MywgeTAsIHkxLCB5MiwgeTMsIGEsIGIsIGMsIG1pbk1heCkgewogICAgaWYgKE1hdGguYWJzKGEpIDwgMWUtMTIpIHsKICAgICAgaWYgKE1hdGguYWJzKGIpID49IDFlLTEyKSB7CiAgICAgICAgdGhpcy4jZ2V0RXh0cmVtdW1PbkN1cnZlKHgwLCB4MSwgeDIsIHgzLCB5MCwgeTEsIHkyLCB5MywgLWMgLyBiLCBtaW5NYXgpOwogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGRlbHRhID0gYiAqKiAyIC0gNCAqIGMgKiBhOwogICAgaWYgKGRlbHRhIDwgMCkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBzcXJ0RGVsdGEgPSBNYXRoLnNxcnQoZGVsdGEpOwogICAgY29uc3QgYTIgPSAyICogYTsKICAgIHRoaXMuI2dldEV4dHJlbXVtT25DdXJ2ZSh4MCwgeDEsIHgyLCB4MywgeTAsIHkxLCB5MiwgeTMsICgtYiArIHNxcnREZWx0YSkgLyBhMiwgbWluTWF4KTsKICAgIHRoaXMuI2dldEV4dHJlbXVtT25DdXJ2ZSh4MCwgeDEsIHgyLCB4MywgeTAsIHkxLCB5MiwgeTMsICgtYiAtIHNxcnREZWx0YSkgLyBhMiwgbWluTWF4KTsKICB9CiAgc3RhdGljIGJlemllckJvdW5kaW5nQm94KHgwLCB5MCwgeDEsIHkxLCB4MiwgeTIsIHgzLCB5MywgbWluTWF4KSB7CiAgICBtaW5NYXhbMF0gPSBNYXRoLm1pbihtaW5NYXhbMF0sIHgwLCB4Myk7CiAgICBtaW5NYXhbMV0gPSBNYXRoLm1pbihtaW5NYXhbMV0sIHkwLCB5Myk7CiAgICBtaW5NYXhbMl0gPSBNYXRoLm1heChtaW5NYXhbMl0sIHgwLCB4Myk7CiAgICBtaW5NYXhbM10gPSBNYXRoLm1heChtaW5NYXhbM10sIHkwLCB5Myk7CiAgICB0aGlzLiNnZXRFeHRyZW11bSh4MCwgeDEsIHgyLCB4MywgeTAsIHkxLCB5MiwgeTMsIDMgKiAoLXgwICsgMyAqICh4MSAtIHgyKSArIHgzKSwgNiAqICh4MCAtIDIgKiB4MSArIHgyKSwgMyAqICh4MSAtIHgwKSwgbWluTWF4KTsKICAgIHRoaXMuI2dldEV4dHJlbXVtKHgwLCB4MSwgeDIsIHgzLCB5MCwgeTEsIHkyLCB5MywgMyAqICgteTAgKyAzICogKHkxIC0geTIpICsgeTMpLCA2ICogKHkwIC0gMiAqIHkxICsgeTIpLCAzICogKHkxIC0geTApLCBtaW5NYXgpOwogIH0KfQpjb25zdCBQREZTdHJpbmdUcmFuc2xhdGVUYWJsZSA9IFswLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAweDJkOCwgMHgyYzcsIDB4MmM2LCAweDJkOSwgMHgyZGQsIDB4MmRiLCAweDJkYSwgMHgyZGMsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDB4MjAyMiwgMHgyMDIwLCAweDIwMjEsIDB4MjAyNiwgMHgyMDE0LCAweDIwMTMsIDB4MTkyLCAweDIwNDQsIDB4MjAzOSwgMHgyMDNhLCAweDIyMTIsIDB4MjAzMCwgMHgyMDFlLCAweDIwMWMsIDB4MjAxZCwgMHgyMDE4LCAweDIwMTksIDB4MjAxYSwgMHgyMTIyLCAweGZiMDEsIDB4ZmIwMiwgMHgxNDEsIDB4MTUyLCAweDE2MCwgMHgxNzgsIDB4MTdkLCAweDEzMSwgMHgxNDIsIDB4MTUzLCAweDE2MSwgMHgxN2UsIDAsIDB4MjBhY107CmZ1bmN0aW9uIHN0cmluZ1RvUERGU3RyaW5nKHN0ciwga2VlcEVzY2FwZVNlcXVlbmNlID0gZmFsc2UpIHsKICBpZiAoc3RyWzBdID49ICJceEVGIikgewogICAgbGV0IGVuY29kaW5nOwogICAgaWYgKHN0clswXSA9PT0gIlx4RkUiICYmIHN0clsxXSA9PT0gIlx4RkYiKSB7CiAgICAgIGVuY29kaW5nID0gInV0Zi0xNmJlIjsKICAgICAgaWYgKHN0ci5sZW5ndGggJSAyID09PSAxKSB7CiAgICAgICAgc3RyID0gc3RyLnNsaWNlKDAsIC0xKTsKICAgICAgfQogICAgfSBlbHNlIGlmIChzdHJbMF0gPT09ICJceEZGIiAmJiBzdHJbMV0gPT09ICJceEZFIikgewogICAgICBlbmNvZGluZyA9ICJ1dGYtMTZsZSI7CiAgICAgIGlmIChzdHIubGVuZ3RoICUgMiA9PT0gMSkgewogICAgICAgIHN0ciA9IHN0ci5zbGljZSgwLCAtMSk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoc3RyWzBdID09PSAiXHhFRiIgJiYgc3RyWzFdID09PSAiXHhCQiIgJiYgc3RyWzJdID09PSAiXHhCRiIpIHsKICAgICAgZW5jb2RpbmcgPSAidXRmLTgiOwogICAgfQogICAgaWYgKGVuY29kaW5nKSB7CiAgICAgIHRyeSB7CiAgICAgICAgY29uc3QgZGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcihlbmNvZGluZywgewogICAgICAgICAgZmF0YWw6IHRydWUKICAgICAgICB9KTsKICAgICAgICBjb25zdCBidWZmZXIgPSBzdHJpbmdUb0J5dGVzKHN0cik7CiAgICAgICAgY29uc3QgZGVjb2RlZCA9IGRlY29kZXIuZGVjb2RlKGJ1ZmZlcik7CiAgICAgICAgaWYgKGtlZXBFc2NhcGVTZXF1ZW5jZSB8fCAhZGVjb2RlZC5pbmNsdWRlcygiXHgxYiIpKSB7CiAgICAgICAgICByZXR1cm4gZGVjb2RlZDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGRlY29kZWQucmVwbGFjZUFsbCgvXHgxYlteXHgxYl0qKD86XHgxYnwkKS9nLCAiIik7CiAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgd2Fybihgc3RyaW5nVG9QREZTdHJpbmc6ICIke2V4fSIuYCk7CiAgICAgIH0KICAgIH0KICB9CiAgY29uc3Qgc3RyQnVmID0gW107CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gc3RyLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IGNoYXJDb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7CiAgICBpZiAoIWtlZXBFc2NhcGVTZXF1ZW5jZSAmJiBjaGFyQ29kZSA9PT0gMHgxYikgewogICAgICB3aGlsZSAoKytpIDwgaWkgJiYgc3RyLmNoYXJDb2RlQXQoaSkgIT09IDB4MWIpIHt9CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgY29uc3QgY29kZSA9IFBERlN0cmluZ1RyYW5zbGF0ZVRhYmxlW2NoYXJDb2RlXTsKICAgIHN0ckJ1Zi5wdXNoKGNvZGUgPyBTdHJpbmcuZnJvbUNoYXJDb2RlKGNvZGUpIDogc3RyLmNoYXJBdChpKSk7CiAgfQogIHJldHVybiBzdHJCdWYuam9pbigiIik7Cn0KZnVuY3Rpb24gc3RyaW5nVG9VVEY4U3RyaW5nKHN0cikgewogIHJldHVybiBkZWNvZGVVUklDb21wb25lbnQoZXNjYXBlKHN0cikpOwp9CmZ1bmN0aW9uIHV0ZjhTdHJpbmdUb1N0cmluZyhzdHIpIHsKICByZXR1cm4gdW5lc2NhcGUoZW5jb2RlVVJJQ29tcG9uZW50KHN0cikpOwp9CmZ1bmN0aW9uIGlzQXJyYXlFcXVhbChhcnIxLCBhcnIyKSB7CiAgaWYgKGFycjEubGVuZ3RoICE9PSBhcnIyLmxlbmd0aCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBmb3IgKGxldCBpID0gMCwgaWkgPSBhcnIxLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGlmIChhcnIxW2ldICE9PSBhcnIyW2ldKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICB9CiAgcmV0dXJuIHRydWU7Cn0KZnVuY3Rpb24gZ2V0TW9kaWZpY2F0aW9uRGF0ZShkYXRlID0gbmV3IERhdGUoKSkgewogIGlmICghKGRhdGUgaW5zdGFuY2VvZiBEYXRlKSkgewogICAgZGF0ZSA9IG5ldyBEYXRlKGRhdGUpOwogIH0KICBjb25zdCBidWZmZXIgPSBbZGF0ZS5nZXRVVENGdWxsWWVhcigpLnRvU3RyaW5nKCksIChkYXRlLmdldFVUQ01vbnRoKCkgKyAxKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsICIwIiksIGRhdGUuZ2V0VVRDRGF0ZSgpLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgIjAiKSwgZGF0ZS5nZXRVVENIb3VycygpLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgIjAiKSwgZGF0ZS5nZXRVVENNaW51dGVzKCkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCAiMCIpLCBkYXRlLmdldFVUQ1NlY29uZHMoKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsICIwIildOwogIHJldHVybiBidWZmZXIuam9pbigiIik7Cn0KbGV0IE5vcm1hbGl6ZVJlZ2V4ID0gbnVsbDsKbGV0IE5vcm1hbGl6YXRpb25NYXAgPSBudWxsOwpmdW5jdGlvbiBub3JtYWxpemVVbmljb2RlKHN0cikgewogIGlmICghTm9ybWFsaXplUmVnZXgpIHsKICAgIE5vcm1hbGl6ZVJlZ2V4ID0gLyhbXHUwMGEwXHUwMGI1XHUwMzdlXHUwZWIzXHUyMDAwLVx1MjAwYVx1MjAyZlx1MjEyNlx1ZmIwMC1cdWZiMDRcdWZiMDZcdWZiMjAtXHVmYjM2XHVmYjM4LVx1ZmIzY1x1ZmIzZVx1ZmI0MC1cdWZiNDFcdWZiNDMtXHVmYjQ0XHVmYjQ2LVx1ZmJhMVx1ZmJhNC1cdWZiYTlcdWZiYWUtXHVmYmIxXHVmYmQzLVx1ZmJkY1x1ZmJkZS1cdWZiZTdcdWZiZWEtXHVmYmY4XHVmYmZjLVx1ZmJmZFx1ZmMwMC1cdWZjNWRcdWZjNjQtXHVmY2YxXHVmY2Y1LVx1ZmQzZFx1ZmQ4OFx1ZmRmNFx1ZmRmYS1cdWZkZmJcdWZlNzFcdWZlNzdcdWZlNzlcdWZlN2JcdWZlN2RdKyl8KFx1ZmIwNSspL2d1OwogICAgTm9ybWFsaXphdGlvbk1hcCA9IG5ldyBNYXAoW1si76yFIiwgIsW/dCJdXSk7CiAgfQogIHJldHVybiBzdHIucmVwbGFjZUFsbChOb3JtYWxpemVSZWdleCwgKF8sIHAxLCBwMikgPT4gcDEgPyBwMS5ub3JtYWxpemUoIk5GS0MiKSA6IE5vcm1hbGl6YXRpb25NYXAuZ2V0KHAyKSk7Cn0KZnVuY3Rpb24gZ2V0VXVpZCgpIHsKICBpZiAodHlwZW9mIGNyeXB0by5yYW5kb21VVUlEID09PSAiZnVuY3Rpb24iKSB7CiAgICByZXR1cm4gY3J5cHRvLnJhbmRvbVVVSUQoKTsKICB9CiAgY29uc3QgYnVmID0gbmV3IFVpbnQ4QXJyYXkoMzIpOwogIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMoYnVmKTsKICByZXR1cm4gYnl0ZXNUb1N0cmluZyhidWYpOwp9CmNvbnN0IEFubm90YXRpb25QcmVmaXggPSAicGRmanNfaW50ZXJuYWxfaWRfIjsKZnVuY3Rpb24gX2lzVmFsaWRFeHBsaWNpdERlc3QodmFsaWRSZWYsIHZhbGlkTmFtZSwgZGVzdCkgewogIGlmICghQXJyYXkuaXNBcnJheShkZXN0KSB8fCBkZXN0Lmxlbmd0aCA8IDIpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgY29uc3QgW3BhZ2UsIHpvb20sIC4uLmFyZ3NdID0gZGVzdDsKICBpZiAoIXZhbGlkUmVmKHBhZ2UpICYmICFOdW1iZXIuaXNJbnRlZ2VyKHBhZ2UpKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGlmICghdmFsaWROYW1lKHpvb20pKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGNvbnN0IGFyZ3NMZW4gPSBhcmdzLmxlbmd0aDsKICBsZXQgYWxsb3dOdWxsID0gdHJ1ZTsKICBzd2l0Y2ggKHpvb20ubmFtZSkgewogICAgY2FzZSAiWFlaIjoKICAgICAgaWYgKGFyZ3NMZW4gPCAyIHx8IGFyZ3NMZW4gPiAzKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGJyZWFrOwogICAgY2FzZSAiRml0IjoKICAgIGNhc2UgIkZpdEIiOgogICAgICByZXR1cm4gYXJnc0xlbiA9PT0gMDsKICAgIGNhc2UgIkZpdEgiOgogICAgY2FzZSAiRml0QkgiOgogICAgY2FzZSAiRml0ViI6CiAgICBjYXNlICJGaXRCViI6CiAgICAgIGlmIChhcmdzTGVuID4gMSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBicmVhazsKICAgIGNhc2UgIkZpdFIiOgogICAgICBpZiAoYXJnc0xlbiAhPT0gNCkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBhbGxvd051bGwgPSBmYWxzZTsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICByZXR1cm4gZmFsc2U7CiAgfQogIGZvciAoY29uc3QgYXJnIG9mIGFyZ3MpIHsKICAgIGlmICh0eXBlb2YgYXJnID09PSAibnVtYmVyIiB8fCBhbGxvd051bGwgJiYgYXJnID09PSBudWxsKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwogIH0KICByZXR1cm4gdHJ1ZTsKfQpmdW5jdGlvbiBNYXRoQ2xhbXAodiwgbWluLCBtYXgpIHsKICByZXR1cm4gTWF0aC5taW4oTWF0aC5tYXgodiwgbWluKSwgbWF4KTsKfQpmdW5jdGlvbiB0b0hleFV0aWwoYXJyKSB7CiAgaWYgKFVpbnQ4QXJyYXkucHJvdG90eXBlLnRvSGV4KSB7CiAgICByZXR1cm4gYXJyLnRvSGV4KCk7CiAgfQogIHJldHVybiBBcnJheS5mcm9tKGFyciwgbnVtID0+IGhleE51bWJlcnNbbnVtXSkuam9pbigiIik7Cn0KZnVuY3Rpb24gdG9CYXNlNjRVdGlsKGFycikgewogIGlmIChVaW50OEFycmF5LnByb3RvdHlwZS50b0Jhc2U2NCkgewogICAgcmV0dXJuIGFyci50b0Jhc2U2NCgpOwogIH0KICByZXR1cm4gYnRvYShieXRlc1RvU3RyaW5nKGFycikpOwp9CmZ1bmN0aW9uIGZyb21CYXNlNjRVdGlsKHN0cikgewogIGlmIChVaW50OEFycmF5LmZyb21CYXNlNjQpIHsKICAgIHJldHVybiBVaW50OEFycmF5LmZyb21CYXNlNjQoc3RyKTsKICB9CiAgcmV0dXJuIHN0cmluZ1RvQnl0ZXMoYXRvYihzdHIpKTsKfQppZiAodHlwZW9mIE1hdGguc3VtUHJlY2lzZSAhPT0gImZ1bmN0aW9uIikgewogIE1hdGguc3VtUHJlY2lzZSA9IGZ1bmN0aW9uIChudW1iZXJzKSB7CiAgICByZXR1cm4gbnVtYmVycy5yZWR1Y2UoKGEsIGIpID0+IGEgKyBiLCAwKTsKICB9Owp9CmlmICh0eXBlb2YgQWJvcnRTaWduYWwuYW55ICE9PSAiZnVuY3Rpb24iKSB7CiAgQWJvcnRTaWduYWwuYW55ID0gZnVuY3Rpb24gKGl0ZXJhYmxlKSB7CiAgICBjb25zdCBhYyA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTsKICAgIGNvbnN0IHsKICAgICAgc2lnbmFsCiAgICB9ID0gYWM7CiAgICBmb3IgKGNvbnN0IHMgb2YgaXRlcmFibGUpIHsKICAgICAgaWYgKHMuYWJvcnRlZCkgewogICAgICAgIGFjLmFib3J0KHMucmVhc29uKTsKICAgICAgICByZXR1cm4gc2lnbmFsOwogICAgICB9CiAgICB9CiAgICBmb3IgKGNvbnN0IHMgb2YgaXRlcmFibGUpIHsKICAgICAgcy5hZGRFdmVudExpc3RlbmVyKCJhYm9ydCIsICgpID0+IHsKICAgICAgICBhYy5hYm9ydChzLnJlYXNvbik7CiAgICAgIH0sIHsKICAgICAgICBzaWduYWwKICAgICAgfSk7CiAgICB9CiAgICByZXR1cm4gc2lnbmFsOwogIH07Cn0KCi8vIEVYVEVSTkFMIE1PRFVMRTogLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLml0ZXJhdG9yLmV2ZXJ5LmpzCnZhciBlc19pdGVyYXRvcl9ldmVyeSA9IF9fd2VicGFja19yZXF1aXJlX18oMTE0OCk7CjsvLyAuL3NyYy9jb3JlL3ByaW1pdGl2ZXMuanMKCgoKCgoKCgoKY29uc3QgQ0lSQ1VMQVJfUkVGID0gU3ltYm9sKCJDSVJDVUxBUl9SRUYiKTsKY29uc3QgRU9GID0gU3ltYm9sKCJFT0YiKTsKbGV0IENtZENhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKbGV0IE5hbWVDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CmxldCBSZWZDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CmZ1bmN0aW9uIGNsZWFyUHJpbWl0aXZlQ2FjaGVzKCkgewogIENtZENhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICBOYW1lQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIFJlZkNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKfQpjbGFzcyBOYW1lIHsKICBjb25zdHJ1Y3RvcihuYW1lKSB7CiAgICB0aGlzLm5hbWUgPSBuYW1lOwogIH0KICBzdGF0aWMgZ2V0KG5hbWUpIHsKICAgIHJldHVybiBOYW1lQ2FjaGVbbmFtZV0gfHw9IG5ldyBOYW1lKG5hbWUpOwogIH0KfQpjbGFzcyBDbWQgewogIGNvbnN0cnVjdG9yKGNtZCkgewogICAgdGhpcy5jbWQgPSBjbWQ7CiAgfQogIHN0YXRpYyBnZXQoY21kKSB7CiAgICByZXR1cm4gQ21kQ2FjaGVbY21kXSB8fD0gbmV3IENtZChjbWQpOwogIH0KfQpjb25zdCBub25TZXJpYWxpemFibGUgPSBmdW5jdGlvbiBub25TZXJpYWxpemFibGVDbG9zdXJlKCkgewogIHJldHVybiBub25TZXJpYWxpemFibGU7Cn07CmNsYXNzIERpY3QgewogIGNvbnN0cnVjdG9yKHhyZWYgPSBudWxsKSB7CiAgICB0aGlzLl9tYXAgPSBuZXcgTWFwKCk7CiAgICB0aGlzLnhyZWYgPSB4cmVmOwogICAgdGhpcy5vYmpJZCA9IG51bGw7CiAgICB0aGlzLnN1cHByZXNzRW5jcnlwdGlvbiA9IGZhbHNlOwogICAgdGhpcy5fX25vblNlcmlhbGl6YWJsZV9fID0gbm9uU2VyaWFsaXphYmxlOwogIH0KICBhc3NpZ25YcmVmKG5ld1hyZWYpIHsKICAgIHRoaXMueHJlZiA9IG5ld1hyZWY7CiAgfQogIGdldCBzaXplKCkgewogICAgcmV0dXJuIHRoaXMuX21hcC5zaXplOwogIH0KICBnZXQoa2V5MSwga2V5Miwga2V5MykgewogICAgbGV0IHZhbHVlID0gdGhpcy5fbWFwLmdldChrZXkxKTsKICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkICYmIGtleTIgIT09IHVuZGVmaW5lZCkgewogICAgICB2YWx1ZSA9IHRoaXMuX21hcC5nZXQoa2V5Mik7CiAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkICYmIGtleTMgIT09IHVuZGVmaW5lZCkgewogICAgICAgIHZhbHVlID0gdGhpcy5fbWFwLmdldChrZXkzKTsKICAgICAgfQogICAgfQogICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgUmVmICYmIHRoaXMueHJlZikgewogICAgICByZXR1cm4gdGhpcy54cmVmLmZldGNoKHZhbHVlLCB0aGlzLnN1cHByZXNzRW5jcnlwdGlvbik7CiAgICB9CiAgICByZXR1cm4gdmFsdWU7CiAgfQogIGFzeW5jIGdldEFzeW5jKGtleTEsIGtleTIsIGtleTMpIHsKICAgIGxldCB2YWx1ZSA9IHRoaXMuX21hcC5nZXQoa2V5MSk7CiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiBrZXkyICE9PSB1bmRlZmluZWQpIHsKICAgICAgdmFsdWUgPSB0aGlzLl9tYXAuZ2V0KGtleTIpOwogICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiBrZXkzICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB2YWx1ZSA9IHRoaXMuX21hcC5nZXQoa2V5Myk7CiAgICAgIH0KICAgIH0KICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFJlZiAmJiB0aGlzLnhyZWYpIHsKICAgICAgcmV0dXJuIHRoaXMueHJlZi5mZXRjaEFzeW5jKHZhbHVlLCB0aGlzLnN1cHByZXNzRW5jcnlwdGlvbik7CiAgICB9CiAgICByZXR1cm4gdmFsdWU7CiAgfQogIGdldEFycmF5KGtleTEsIGtleTIsIGtleTMpIHsKICAgIGxldCB2YWx1ZSA9IHRoaXMuX21hcC5nZXQoa2V5MSk7CiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiBrZXkyICE9PSB1bmRlZmluZWQpIHsKICAgICAgdmFsdWUgPSB0aGlzLl9tYXAuZ2V0KGtleTIpOwogICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCAmJiBrZXkzICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB2YWx1ZSA9IHRoaXMuX21hcC5nZXQoa2V5Myk7CiAgICAgIH0KICAgIH0KICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFJlZiAmJiB0aGlzLnhyZWYpIHsKICAgICAgdmFsdWUgPSB0aGlzLnhyZWYuZmV0Y2godmFsdWUsIHRoaXMuc3VwcHJlc3NFbmNyeXB0aW9uKTsKICAgIH0KICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkgewogICAgICB2YWx1ZSA9IHZhbHVlLnNsaWNlKCk7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHZhbHVlLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBpZiAodmFsdWVbaV0gaW5zdGFuY2VvZiBSZWYgJiYgdGhpcy54cmVmKSB7CiAgICAgICAgICB2YWx1ZVtpXSA9IHRoaXMueHJlZi5mZXRjaCh2YWx1ZVtpXSwgdGhpcy5zdXBwcmVzc0VuY3J5cHRpb24pOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIHZhbHVlOwogIH0KICBnZXRSYXcoa2V5KSB7CiAgICByZXR1cm4gdGhpcy5fbWFwLmdldChrZXkpOwogIH0KICBnZXRLZXlzKCkgewogICAgcmV0dXJuIFsuLi50aGlzLl9tYXAua2V5cygpXTsKICB9CiAgZ2V0UmF3VmFsdWVzKCkgewogICAgcmV0dXJuIFsuLi50aGlzLl9tYXAudmFsdWVzKCldOwogIH0KICBzZXQoa2V5LCB2YWx1ZSkgewogICAgdGhpcy5fbWFwLnNldChrZXksIHZhbHVlKTsKICB9CiAgc2V0SWZOb3RFeGlzdHMoa2V5LCB2YWx1ZSkgewogICAgaWYgKCF0aGlzLmhhcyhrZXkpKSB7CiAgICAgIHRoaXMuc2V0KGtleSwgdmFsdWUpOwogICAgfQogIH0KICBzZXRJZk51bWJlcihrZXksIHZhbHVlKSB7CiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAibnVtYmVyIikgewogICAgICB0aGlzLnNldChrZXksIHZhbHVlKTsKICAgIH0KICB9CiAgc2V0SWZBcnJheShrZXksIHZhbHVlKSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkgfHwgQXJyYXlCdWZmZXIuaXNWaWV3KHZhbHVlKSkgewogICAgICB0aGlzLnNldChrZXksIHZhbHVlKTsKICAgIH0KICB9CiAgc2V0SWZEZWZpbmVkKGtleSwgdmFsdWUpIHsKICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsKSB7CiAgICAgIHRoaXMuc2V0KGtleSwgdmFsdWUpOwogICAgfQogIH0KICBzZXRJZk5hbWUoa2V5LCB2YWx1ZSkgewogICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gInN0cmluZyIpIHsKICAgICAgdGhpcy5zZXQoa2V5LCBOYW1lLmdldCh2YWx1ZSkpOwogICAgfSBlbHNlIGlmICh2YWx1ZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgdGhpcy5zZXQoa2V5LCB2YWx1ZSk7CiAgICB9CiAgfQogIGhhcyhrZXkpIHsKICAgIHJldHVybiB0aGlzLl9tYXAuaGFzKGtleSk7CiAgfQogICpbU3ltYm9sLml0ZXJhdG9yXSgpIHsKICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIHRoaXMuX21hcCkgewogICAgICB5aWVsZCBba2V5LCB2YWx1ZSBpbnN0YW5jZW9mIFJlZiAmJiB0aGlzLnhyZWYgPyB0aGlzLnhyZWYuZmV0Y2godmFsdWUsIHRoaXMuc3VwcHJlc3NFbmNyeXB0aW9uKSA6IHZhbHVlXTsKICAgIH0KICB9CiAgc3RhdGljIGdldCBlbXB0eSgpIHsKICAgIGNvbnN0IGVtcHR5RGljdCA9IG5ldyBEaWN0KG51bGwpOwogICAgZW1wdHlEaWN0LnNldCA9IChrZXksIHZhbHVlKSA9PiB7CiAgICAgIHVucmVhY2hhYmxlKCJTaG91bGQgbm90IGNhbGwgYHNldGAgb24gdGhlIGVtcHR5IGRpY3Rpb25hcnkuIik7CiAgICB9OwogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiZW1wdHkiLCBlbXB0eURpY3QpOwogIH0KICBzdGF0aWMgbWVyZ2UoewogICAgeHJlZiwKICAgIGRpY3RBcnJheSwKICAgIG1lcmdlU3ViRGljdHMgPSBmYWxzZQogIH0pIHsKICAgIGNvbnN0IG1lcmdlZERpY3QgPSBuZXcgRGljdCh4cmVmKSwKICAgICAgcHJvcGVydGllcyA9IG5ldyBNYXAoKTsKICAgIGZvciAoY29uc3QgZGljdCBvZiBkaWN0QXJyYXkpIHsKICAgICAgaWYgKCEoZGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgZGljdC5fbWFwKSB7CiAgICAgICAgbGV0IHByb3BlcnR5ID0gcHJvcGVydGllcy5nZXQoa2V5KTsKICAgICAgICBpZiAocHJvcGVydHkgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgcHJvcGVydHkgPSBbXTsKICAgICAgICAgIHByb3BlcnRpZXMuc2V0KGtleSwgcHJvcGVydHkpOwogICAgICAgIH0gZWxzZSBpZiAoIW1lcmdlU3ViRGljdHMgfHwgISh2YWx1ZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgcHJvcGVydHkucHVzaCh2YWx1ZSk7CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgW25hbWUsIHZhbHVlc10gb2YgcHJvcGVydGllcykgewogICAgICBpZiAodmFsdWVzLmxlbmd0aCA9PT0gMSB8fCAhKHZhbHVlc1swXSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgbWVyZ2VkRGljdC5fbWFwLnNldChuYW1lLCB2YWx1ZXNbMF0pOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IHN1YkRpY3QgPSBuZXcgRGljdCh4cmVmKTsKICAgICAgZm9yIChjb25zdCBkaWN0IG9mIHZhbHVlcykgewogICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIGRpY3QuX21hcCkgewogICAgICAgICAgaWYgKCFzdWJEaWN0Ll9tYXAuaGFzKGtleSkpIHsKICAgICAgICAgICAgc3ViRGljdC5fbWFwLnNldChrZXksIHZhbHVlKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKHN1YkRpY3Quc2l6ZSA+IDApIHsKICAgICAgICBtZXJnZWREaWN0Ll9tYXAuc2V0KG5hbWUsIHN1YkRpY3QpOwogICAgICB9CiAgICB9CiAgICBwcm9wZXJ0aWVzLmNsZWFyKCk7CiAgICByZXR1cm4gbWVyZ2VkRGljdC5zaXplID4gMCA/IG1lcmdlZERpY3QgOiBEaWN0LmVtcHR5OwogIH0KICBjbG9uZSgpIHsKICAgIGNvbnN0IGRpY3QgPSBuZXcgRGljdCh0aGlzLnhyZWYpOwogICAgZm9yIChjb25zdCBrZXkgb2YgdGhpcy5nZXRLZXlzKCkpIHsKICAgICAgZGljdC5zZXQoa2V5LCB0aGlzLmdldFJhdyhrZXkpKTsKICAgIH0KICAgIHJldHVybiBkaWN0OwogIH0KICBkZWxldGUoa2V5KSB7CiAgICB0aGlzLl9tYXAuZGVsZXRlKGtleSk7CiAgfQp9CmNsYXNzIFJlZiB7CiAgY29uc3RydWN0b3IobnVtLCBnZW4pIHsKICAgIHRoaXMubnVtID0gbnVtOwogICAgdGhpcy5nZW4gPSBnZW47CiAgfQogIHRvU3RyaW5nKCkgewogICAgaWYgKHRoaXMuZ2VuID09PSAwKSB7CiAgICAgIHJldHVybiBgJHt0aGlzLm51bX1SYDsKICAgIH0KICAgIHJldHVybiBgJHt0aGlzLm51bX1SJHt0aGlzLmdlbn1gOwogIH0KICBzdGF0aWMgZnJvbVN0cmluZyhzdHIpIHsKICAgIGNvbnN0IHJlZiA9IFJlZkNhY2hlW3N0cl07CiAgICBpZiAocmVmKSB7CiAgICAgIHJldHVybiByZWY7CiAgICB9CiAgICBjb25zdCBtID0gL14oXGQrKVIoXGQqKSQvLmV4ZWMoc3RyKTsKICAgIGlmICghbSB8fCBtWzFdID09PSAiMCIpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICByZXR1cm4gUmVmQ2FjaGVbc3RyXSA9IG5ldyBSZWYocGFyc2VJbnQobVsxXSksICFtWzJdID8gMCA6IHBhcnNlSW50KG1bMl0pKTsKICB9CiAgc3RhdGljIGdldChudW0sIGdlbikgewogICAgY29uc3Qga2V5ID0gZ2VuID09PSAwID8gYCR7bnVtfVJgIDogYCR7bnVtfVIke2dlbn1gOwogICAgcmV0dXJuIFJlZkNhY2hlW2tleV0gfHw9IG5ldyBSZWYobnVtLCBnZW4pOwogIH0KfQpjbGFzcyBSZWZTZXQgewogIGNvbnN0cnVjdG9yKHBhcmVudCA9IG51bGwpIHsKICAgIHRoaXMuX3NldCA9IG5ldyBTZXQocGFyZW50Py5fc2V0KTsKICB9CiAgaGFzKHJlZikgewogICAgcmV0dXJuIHRoaXMuX3NldC5oYXMocmVmLnRvU3RyaW5nKCkpOwogIH0KICBwdXQocmVmKSB7CiAgICB0aGlzLl9zZXQuYWRkKHJlZi50b1N0cmluZygpKTsKICB9CiAgcmVtb3ZlKHJlZikgewogICAgdGhpcy5fc2V0LmRlbGV0ZShyZWYudG9TdHJpbmcoKSk7CiAgfQogIFtTeW1ib2wuaXRlcmF0b3JdKCkgewogICAgcmV0dXJuIHRoaXMuX3NldC52YWx1ZXMoKTsKICB9CiAgY2xlYXIoKSB7CiAgICB0aGlzLl9zZXQuY2xlYXIoKTsKICB9Cn0KY2xhc3MgUmVmU2V0Q2FjaGUgewogIGNvbnN0cnVjdG9yKCkgewogICAgdGhpcy5fbWFwID0gbmV3IE1hcCgpOwogIH0KICBnZXQgc2l6ZSgpIHsKICAgIHJldHVybiB0aGlzLl9tYXAuc2l6ZTsKICB9CiAgZ2V0KHJlZikgewogICAgcmV0dXJuIHRoaXMuX21hcC5nZXQocmVmLnRvU3RyaW5nKCkpOwogIH0KICBoYXMocmVmKSB7CiAgICByZXR1cm4gdGhpcy5fbWFwLmhhcyhyZWYudG9TdHJpbmcoKSk7CiAgfQogIHB1dChyZWYsIG9iaikgewogICAgdGhpcy5fbWFwLnNldChyZWYudG9TdHJpbmcoKSwgb2JqKTsKICB9CiAgcHV0QWxpYXMocmVmLCBhbGlhc1JlZikgewogICAgdGhpcy5fbWFwLnNldChyZWYudG9TdHJpbmcoKSwgdGhpcy5nZXQoYWxpYXNSZWYpKTsKICB9CiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7CiAgICByZXR1cm4gdGhpcy5fbWFwLnZhbHVlcygpOwogIH0KICBjbGVhcigpIHsKICAgIHRoaXMuX21hcC5jbGVhcigpOwogIH0KICAqdmFsdWVzKCkgewogICAgeWllbGQqIHRoaXMuX21hcC52YWx1ZXMoKTsKICB9CiAgKml0ZW1zKCkgewogICAgZm9yIChjb25zdCBbcmVmLCB2YWx1ZV0gb2YgdGhpcy5fbWFwKSB7CiAgICAgIHlpZWxkIFtSZWYuZnJvbVN0cmluZyhyZWYpLCB2YWx1ZV07CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGlzTmFtZSh2LCBuYW1lKSB7CiAgcmV0dXJuIHYgaW5zdGFuY2VvZiBOYW1lICYmIChuYW1lID09PSB1bmRlZmluZWQgfHwgdi5uYW1lID09PSBuYW1lKTsKfQpmdW5jdGlvbiBpc0NtZCh2LCBjbWQpIHsKICByZXR1cm4gdiBpbnN0YW5jZW9mIENtZCAmJiAoY21kID09PSB1bmRlZmluZWQgfHwgdi5jbWQgPT09IGNtZCk7Cn0KZnVuY3Rpb24gaXNEaWN0KHYsIHR5cGUpIHsKICByZXR1cm4gdiBpbnN0YW5jZW9mIERpY3QgJiYgKHR5cGUgPT09IHVuZGVmaW5lZCB8fCBpc05hbWUodi5nZXQoIlR5cGUiKSwgdHlwZSkpOwp9CmZ1bmN0aW9uIGlzUmVmc0VxdWFsKHYxLCB2MikgewogIHJldHVybiB2MS5udW0gPT09IHYyLm51bSAmJiB2MS5nZW4gPT09IHYyLmdlbjsKfQoKOy8vIC4vc3JjL2NvcmUvYmFzZV9zdHJlYW0uanMKCmNsYXNzIEJhc2VTdHJlYW0gewogIGdldCBsZW5ndGgoKSB7CiAgICB1bnJlYWNoYWJsZSgiQWJzdHJhY3QgZ2V0dGVyIGBsZW5ndGhgIGFjY2Vzc2VkIik7CiAgfQogIGdldCBpc0VtcHR5KCkgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IGdldHRlciBgaXNFbXB0eWAgYWNjZXNzZWQiKTsKICB9CiAgZ2V0IGlzRGF0YUxvYWRlZCgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgImlzRGF0YUxvYWRlZCIsIHRydWUpOwogIH0KICBnZXRCeXRlKCkgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgZ2V0Qnl0ZWAgY2FsbGVkIik7CiAgfQogIGdldEJ5dGVzKGxlbmd0aCkgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgZ2V0Qnl0ZXNgIGNhbGxlZCIpOwogIH0KICBhc3luYyBnZXRJbWFnZURhdGEobGVuZ3RoLCBkZWNvZGVyT3B0aW9ucykgewogICAgcmV0dXJuIHRoaXMuZ2V0Qnl0ZXMobGVuZ3RoLCBkZWNvZGVyT3B0aW9ucyk7CiAgfQogIGFzeW5jIGFzeW5jR2V0Qnl0ZXMoKSB7CiAgICB1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGBhc3luY0dldEJ5dGVzYCBjYWxsZWQiKTsKICB9CiAgZ2V0IGlzQXN5bmMoKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGdldCBpc0FzeW5jRGVjb2RlcigpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgZ2V0IGNhbkFzeW5jRGVjb2RlSW1hZ2VGcm9tQnVmZmVyKCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBhc3luYyBnZXRUcmFuc2ZlcmFibGVJbWFnZSgpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBwZWVrQnl0ZSgpIHsKICAgIGNvbnN0IHBlZWtlZEJ5dGUgPSB0aGlzLmdldEJ5dGUoKTsKICAgIGlmIChwZWVrZWRCeXRlICE9PSAtMSkgewogICAgICB0aGlzLnBvcy0tOwogICAgfQogICAgcmV0dXJuIHBlZWtlZEJ5dGU7CiAgfQogIHBlZWtCeXRlcyhsZW5ndGgpIHsKICAgIGNvbnN0IGJ5dGVzID0gdGhpcy5nZXRCeXRlcyhsZW5ndGgpOwogICAgdGhpcy5wb3MgLT0gYnl0ZXMubGVuZ3RoOwogICAgcmV0dXJuIGJ5dGVzOwogIH0KICBnZXRVaW50MTYoKSB7CiAgICBjb25zdCBiMCA9IHRoaXMuZ2V0Qnl0ZSgpOwogICAgY29uc3QgYjEgPSB0aGlzLmdldEJ5dGUoKTsKICAgIGlmIChiMCA9PT0gLTEgfHwgYjEgPT09IC0xKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIHJldHVybiAoYjAgPDwgOCkgKyBiMTsKICB9CiAgZ2V0SW50MzIoKSB7CiAgICBjb25zdCBiMCA9IHRoaXMuZ2V0Qnl0ZSgpOwogICAgY29uc3QgYjEgPSB0aGlzLmdldEJ5dGUoKTsKICAgIGNvbnN0IGIyID0gdGhpcy5nZXRCeXRlKCk7CiAgICBjb25zdCBiMyA9IHRoaXMuZ2V0Qnl0ZSgpOwogICAgcmV0dXJuIChiMCA8PCAyNCkgKyAoYjEgPDwgMTYpICsgKGIyIDw8IDgpICsgYjM7CiAgfQogIGdldEJ5dGVSYW5nZShiZWdpbiwgZW5kKSB7CiAgICB1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGBnZXRCeXRlUmFuZ2VgIGNhbGxlZCIpOwogIH0KICBnZXRTdHJpbmcobGVuZ3RoKSB7CiAgICByZXR1cm4gYnl0ZXNUb1N0cmluZyh0aGlzLmdldEJ5dGVzKGxlbmd0aCkpOwogIH0KICBza2lwKG4pIHsKICAgIHRoaXMucG9zICs9IG4gfHwgMTsKICB9CiAgcmVzZXQoKSB7CiAgICB1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGByZXNldGAgY2FsbGVkIik7CiAgfQogIG1vdmVTdGFydCgpIHsKICAgIHVucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYG1vdmVTdGFydGAgY2FsbGVkIik7CiAgfQogIG1ha2VTdWJTdHJlYW0oc3RhcnQsIGxlbmd0aCwgZGljdCA9IG51bGwpIHsKICAgIHVucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYG1ha2VTdWJTdHJlYW1gIGNhbGxlZCIpOwogIH0KICBnZXRCYXNlU3RyZWFtcygpIHsKICAgIHJldHVybiBudWxsOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvY29yZV91dGlscy5qcwoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKY29uc3QgUERGX1ZFUlNJT05fUkVHRVhQID0gL15bMS05XVwuXGQkLzsKY29uc3QgTUFYX0lOVF8zMiA9IDIgKiogMzEgLSAxOwpjb25zdCBNSU5fSU5UXzMyID0gLSgyICoqIDMxKTsKY29uc3QgSURFTlRJVFlfTUFUUklYID0gWzEsIDAsIDAsIDEsIDAsIDBdOwpjb25zdCBSRVNPVVJDRVNfS0VZU19PUEVSQVRPUl9MSVNUID0gWyJDb2xvclNwYWNlIiwgIkV4dEdTdGF0ZSIsICJGb250IiwgIlBhdHRlcm4iLCAiUHJvcGVydGllcyIsICJTaGFkaW5nIiwgIlhPYmplY3QiXTsKY29uc3QgUkVTT1VSQ0VTX0tFWVNfVEVYVF9DT05URU5UID0gWyJFeHRHU3RhdGUiLCAiRm9udCIsICJQcm9wZXJ0aWVzIiwgIlhPYmplY3QiXTsKZnVuY3Rpb24gZ2V0TG9va3VwVGFibGVGYWN0b3J5KGluaXRpYWxpemVyKSB7CiAgbGV0IGxvb2t1cDsKICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgaWYgKGluaXRpYWxpemVyKSB7CiAgICAgIGxvb2t1cCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIGluaXRpYWxpemVyKGxvb2t1cCk7CiAgICAgIGluaXRpYWxpemVyID0gbnVsbDsKICAgIH0KICAgIHJldHVybiBsb29rdXA7CiAgfTsKfQpjbGFzcyBNaXNzaW5nRGF0YUV4Y2VwdGlvbiBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKGJlZ2luLCBlbmQpIHsKICAgIHN1cGVyKGBNaXNzaW5nIGRhdGEgWyR7YmVnaW59LCAke2VuZH0pYCwgIk1pc3NpbmdEYXRhRXhjZXB0aW9uIik7CiAgICB0aGlzLmJlZ2luID0gYmVnaW47CiAgICB0aGlzLmVuZCA9IGVuZDsKICB9Cn0KY2xhc3MgUGFyc2VyRU9GRXhjZXB0aW9uIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnKSB7CiAgICBzdXBlcihtc2csICJQYXJzZXJFT0ZFeGNlcHRpb24iKTsKICB9Cn0KY2xhc3MgWFJlZkVudHJ5RXhjZXB0aW9uIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnKSB7CiAgICBzdXBlcihtc2csICJYUmVmRW50cnlFeGNlcHRpb24iKTsKICB9Cn0KY2xhc3MgWFJlZlBhcnNlRXhjZXB0aW9uIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnKSB7CiAgICBzdXBlcihtc2csICJYUmVmUGFyc2VFeGNlcHRpb24iKTsKICB9Cn0KZnVuY3Rpb24gYXJyYXlCdWZmZXJzVG9CeXRlcyhhcnIpIHsKICBjb25zdCBsZW5ndGggPSBhcnIubGVuZ3RoOwogIGlmIChsZW5ndGggPT09IDApIHsKICAgIHJldHVybiBuZXcgVWludDhBcnJheSgwKTsKICB9CiAgaWYgKGxlbmd0aCA9PT0gMSkgewogICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGFyclswXSk7CiAgfQogIGxldCBkYXRhTGVuZ3RoID0gMDsKICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICBkYXRhTGVuZ3RoICs9IGFycltpXS5ieXRlTGVuZ3RoOwogIH0KICBjb25zdCBkYXRhID0gbmV3IFVpbnQ4QXJyYXkoZGF0YUxlbmd0aCk7CiAgbGV0IHBvcyA9IDA7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgY29uc3QgaXRlbSA9IG5ldyBVaW50OEFycmF5KGFycltpXSk7CiAgICBkYXRhLnNldChpdGVtLCBwb3MpOwogICAgcG9zICs9IGl0ZW0uYnl0ZUxlbmd0aDsKICB9CiAgcmV0dXJuIGRhdGE7Cn0KYXN5bmMgZnVuY3Rpb24gZmV0Y2hCaW5hcnlEYXRhKHVybCkgewogIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsKTsKICBpZiAoIXJlc3BvbnNlLm9rKSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoYEZhaWxlZCB0byBmZXRjaCBmaWxlICIke3VybH0iIHdpdGggIiR7cmVzcG9uc2Uuc3RhdHVzVGV4dH0iLmApOwogIH0KICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYXdhaXQgcmVzcG9uc2UuYXJyYXlCdWZmZXIoKSk7Cn0KZnVuY3Rpb24gZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7CiAgZGljdCwKICBrZXksCiAgZ2V0QXJyYXkgPSBmYWxzZSwKICBzdG9wV2hlbkZvdW5kID0gdHJ1ZQp9KSB7CiAgbGV0IHZhbHVlczsKICBjb25zdCB2aXNpdGVkID0gbmV3IFJlZlNldCgpOwogIHdoaWxlIChkaWN0IGluc3RhbmNlb2YgRGljdCAmJiAhKGRpY3Qub2JqSWQgJiYgdmlzaXRlZC5oYXMoZGljdC5vYmpJZCkpKSB7CiAgICBpZiAoZGljdC5vYmpJZCkgewogICAgICB2aXNpdGVkLnB1dChkaWN0Lm9iaklkKTsKICAgIH0KICAgIGNvbnN0IHZhbHVlID0gZ2V0QXJyYXkgPyBkaWN0LmdldEFycmF5KGtleSkgOiBkaWN0LmdldChrZXkpOwogICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHsKICAgICAgaWYgKHN0b3BXaGVuRm91bmQpIHsKICAgICAgICByZXR1cm4gdmFsdWU7CiAgICAgIH0KICAgICAgKHZhbHVlcyB8fD0gW10pLnB1c2godmFsdWUpOwogICAgfQogICAgZGljdCA9IGRpY3QuZ2V0KCJQYXJlbnQiKTsKICB9CiAgcmV0dXJuIHZhbHVlczsKfQpmdW5jdGlvbiBnZXRQYXJlbnRUb1VwZGF0ZShkaWN0LCByZWYsIHhyZWYpIHsKICBjb25zdCB2aXNpdGVkID0gbmV3IFJlZlNldCgpOwogIGNvbnN0IGZpcnN0RGljdCA9IGRpY3Q7CiAgY29uc3QgcmVzdWx0ID0gewogICAgZGljdDogbnVsbCwKICAgIHJlZjogbnVsbAogIH07CiAgd2hpbGUgKGRpY3QgaW5zdGFuY2VvZiBEaWN0ICYmICF2aXNpdGVkLmhhcyhyZWYpKSB7CiAgICB2aXNpdGVkLnB1dChyZWYpOwogICAgaWYgKGRpY3QuaGFzKCJUIikpIHsKICAgICAgYnJlYWs7CiAgICB9CiAgICByZWYgPSBkaWN0LmdldFJhdygiUGFyZW50Iik7CiAgICBpZiAoIShyZWYgaW5zdGFuY2VvZiBSZWYpKSB7CiAgICAgIHJldHVybiByZXN1bHQ7CiAgICB9CiAgICBkaWN0ID0geHJlZi5mZXRjaChyZWYpOwogIH0KICBpZiAoZGljdCBpbnN0YW5jZW9mIERpY3QgJiYgZGljdCAhPT0gZmlyc3REaWN0KSB7CiAgICByZXN1bHQuZGljdCA9IGRpY3Q7CiAgICByZXN1bHQucmVmID0gcmVmOwogIH0KICByZXR1cm4gcmVzdWx0Owp9CmNvbnN0IFJPTUFOX05VTUJFUl9NQVAgPSBbIiIsICJDIiwgIkNDIiwgIkNDQyIsICJDRCIsICJEIiwgIkRDIiwgIkRDQyIsICJEQ0NDIiwgIkNNIiwgIiIsICJYIiwgIlhYIiwgIlhYWCIsICJYTCIsICJMIiwgIkxYIiwgIkxYWCIsICJMWFhYIiwgIlhDIiwgIiIsICJJIiwgIklJIiwgIklJSSIsICJJViIsICJWIiwgIlZJIiwgIlZJSSIsICJWSUlJIiwgIklYIl07CmZ1bmN0aW9uIHRvUm9tYW5OdW1lcmFscyhudW1iZXIsIGxvd2VyQ2FzZSA9IGZhbHNlKSB7CiAgYXNzZXJ0KE51bWJlci5pc0ludGVnZXIobnVtYmVyKSAmJiBudW1iZXIgPiAwLCAiVGhlIG51bWJlciBzaG91bGQgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyLiIpOwogIGNvbnN0IHJvbWFuID0gIk0iLnJlcGVhdChudW1iZXIgLyAxMDAwIHwgMCkgKyBST01BTl9OVU1CRVJfTUFQW251bWJlciAlIDEwMDAgLyAxMDAgfCAwXSArIFJPTUFOX05VTUJFUl9NQVBbMTAgKyAobnVtYmVyICUgMTAwIC8gMTAgfCAwKV0gKyBST01BTl9OVU1CRVJfTUFQWzIwICsgbnVtYmVyICUgMTBdOwogIHJldHVybiBsb3dlckNhc2UgPyByb21hbi50b0xvd2VyQ2FzZSgpIDogcm9tYW47Cn0KZnVuY3Rpb24gbG9nMih4KSB7CiAgcmV0dXJuIHggPiAwID8gTWF0aC5jZWlsKE1hdGgubG9nMih4KSkgOiAwOwp9CmZ1bmN0aW9uIHJlYWRJbnQ4KGRhdGEsIG9mZnNldCkgewogIHJldHVybiBkYXRhW29mZnNldF0gPDwgMjQgPj4gMjQ7Cn0KZnVuY3Rpb24gcmVhZEludDE2KGRhdGEsIG9mZnNldCkgewogIHJldHVybiAoZGF0YVtvZmZzZXRdIDw8IDI0IHwgZGF0YVtvZmZzZXQgKyAxXSA8PCAxNikgPj4gMTY7Cn0KZnVuY3Rpb24gcmVhZFVpbnQxNihkYXRhLCBvZmZzZXQpIHsKICByZXR1cm4gZGF0YVtvZmZzZXRdIDw8IDggfCBkYXRhW29mZnNldCArIDFdOwp9CmZ1bmN0aW9uIHJlYWRVaW50MzIoZGF0YSwgb2Zmc2V0KSB7CiAgcmV0dXJuIChkYXRhW29mZnNldF0gPDwgMjQgfCBkYXRhW29mZnNldCArIDFdIDw8IDE2IHwgZGF0YVtvZmZzZXQgKyAyXSA8PCA4IHwgZGF0YVtvZmZzZXQgKyAzXSkgPj4+IDA7Cn0KZnVuY3Rpb24gaXNXaGl0ZVNwYWNlKGNoKSB7CiAgcmV0dXJuIGNoID09PSAweDIwIHx8IGNoID09PSAweDA5IHx8IGNoID09PSAweDBkIHx8IGNoID09PSAweDBhOwp9CmZ1bmN0aW9uIGlzQm9vbGVhbkFycmF5KGFyciwgbGVuKSB7CiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoYXJyKSAmJiAobGVuID09PSBudWxsIHx8IGFyci5sZW5ndGggPT09IGxlbikgJiYgYXJyLmV2ZXJ5KHggPT4gdHlwZW9mIHggPT09ICJib29sZWFuIik7Cn0KZnVuY3Rpb24gaXNOdW1iZXJBcnJheShhcnIsIGxlbikgewogIGlmIChBcnJheS5pc0FycmF5KGFycikpIHsKICAgIHJldHVybiAobGVuID09PSBudWxsIHx8IGFyci5sZW5ndGggPT09IGxlbikgJiYgYXJyLmV2ZXJ5KHggPT4gdHlwZW9mIHggPT09ICJudW1iZXIiKTsKICB9CiAgcmV0dXJuIEFycmF5QnVmZmVyLmlzVmlldyhhcnIpICYmICEoYXJyIGluc3RhbmNlb2YgQmlnSW50NjRBcnJheSB8fCBhcnIgaW5zdGFuY2VvZiBCaWdVaW50NjRBcnJheSkgJiYgKGxlbiA9PT0gbnVsbCB8fCBhcnIubGVuZ3RoID09PSBsZW4pOwp9CmZ1bmN0aW9uIGxvb2t1cE1hdHJpeChhcnIsIGZhbGxiYWNrKSB7CiAgcmV0dXJuIGlzTnVtYmVyQXJyYXkoYXJyLCA2KSA/IGFyciA6IGZhbGxiYWNrOwp9CmZ1bmN0aW9uIGxvb2t1cFJlY3QoYXJyLCBmYWxsYmFjaykgewogIHJldHVybiBpc051bWJlckFycmF5KGFyciwgNCkgPyBhcnIgOiBmYWxsYmFjazsKfQpmdW5jdGlvbiBsb29rdXBOb3JtYWxSZWN0KGFyciwgZmFsbGJhY2spIHsKICByZXR1cm4gaXNOdW1iZXJBcnJheShhcnIsIDQpID8gVXRpbC5ub3JtYWxpemVSZWN0KGFycikgOiBmYWxsYmFjazsKfQpmdW5jdGlvbiBwYXJzZVhGQVBhdGgocGF0aCkgewogIGNvbnN0IHBvc2l0aW9uUGF0dGVybiA9IC8oLispXFsoXGQrKVxdJC87CiAgcmV0dXJuIHBhdGguc3BsaXQoIi4iKS5tYXAoY29tcG9uZW50ID0+IHsKICAgIGNvbnN0IG0gPSBjb21wb25lbnQubWF0Y2gocG9zaXRpb25QYXR0ZXJuKTsKICAgIGlmIChtKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgbmFtZTogbVsxXSwKICAgICAgICBwb3M6IHBhcnNlSW50KG1bMl0sIDEwKQogICAgICB9OwogICAgfQogICAgcmV0dXJuIHsKICAgICAgbmFtZTogY29tcG9uZW50LAogICAgICBwb3M6IDAKICAgIH07CiAgfSk7Cn0KZnVuY3Rpb24gZXNjYXBlUERGTmFtZShzdHIpIHsKICBjb25zdCBidWZmZXIgPSBbXTsKICBsZXQgc3RhcnQgPSAwOwogIGZvciAobGV0IGkgPSAwLCBpaSA9IHN0ci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBjb25zdCBjaGFyID0gc3RyLmNoYXJDb2RlQXQoaSk7CiAgICBpZiAoY2hhciA8IDB4MjEgfHwgY2hhciA+IDB4N2UgfHwgY2hhciA9PT0gMHgyMyB8fCBjaGFyID09PSAweDI4IHx8IGNoYXIgPT09IDB4MjkgfHwgY2hhciA9PT0gMHgzYyB8fCBjaGFyID09PSAweDNlIHx8IGNoYXIgPT09IDB4NWIgfHwgY2hhciA9PT0gMHg1ZCB8fCBjaGFyID09PSAweDdiIHx8IGNoYXIgPT09IDB4N2QgfHwgY2hhciA9PT0gMHgyZiB8fCBjaGFyID09PSAweDI1KSB7CiAgICAgIGlmIChzdGFydCA8IGkpIHsKICAgICAgICBidWZmZXIucHVzaChzdHIuc3Vic3RyaW5nKHN0YXJ0LCBpKSk7CiAgICAgIH0KICAgICAgYnVmZmVyLnB1c2goYCMke2NoYXIudG9TdHJpbmcoMTYpfWApOwogICAgICBzdGFydCA9IGkgKyAxOwogICAgfQogIH0KICBpZiAoYnVmZmVyLmxlbmd0aCA9PT0gMCkgewogICAgcmV0dXJuIHN0cjsKICB9CiAgaWYgKHN0YXJ0IDwgc3RyLmxlbmd0aCkgewogICAgYnVmZmVyLnB1c2goc3RyLnN1YnN0cmluZyhzdGFydCwgc3RyLmxlbmd0aCkpOwogIH0KICByZXR1cm4gYnVmZmVyLmpvaW4oIiIpOwp9CmZ1bmN0aW9uIGVzY2FwZVN0cmluZyhzdHIpIHsKICByZXR1cm4gc3RyLnJlcGxhY2VBbGwoLyhbKClcXFxuXHJdKS9nLCBtYXRjaCA9PiB7CiAgICBpZiAobWF0Y2ggPT09ICJcbiIpIHsKICAgICAgcmV0dXJuICJcXG4iOwogICAgfSBlbHNlIGlmIChtYXRjaCA9PT0gIlxyIikgewogICAgICByZXR1cm4gIlxcciI7CiAgICB9CiAgICByZXR1cm4gYFxcJHttYXRjaH1gOwogIH0pOwp9CmZ1bmN0aW9uIF9jb2xsZWN0SlMoZW50cnksIHhyZWYsIGxpc3QsIHBhcmVudHMpIHsKICBpZiAoIWVudHJ5KSB7CiAgICByZXR1cm47CiAgfQogIGxldCBwYXJlbnQgPSBudWxsOwogIGlmIChlbnRyeSBpbnN0YW5jZW9mIFJlZikgewogICAgaWYgKHBhcmVudHMuaGFzKGVudHJ5KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBwYXJlbnQgPSBlbnRyeTsKICAgIHBhcmVudHMucHV0KHBhcmVudCk7CiAgICBlbnRyeSA9IHhyZWYuZmV0Y2goZW50cnkpOwogIH0KICBpZiAoQXJyYXkuaXNBcnJheShlbnRyeSkpIHsKICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBlbnRyeSkgewogICAgICBfY29sbGVjdEpTKGVsZW1lbnQsIHhyZWYsIGxpc3QsIHBhcmVudHMpOwogICAgfQogIH0gZWxzZSBpZiAoZW50cnkgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICBpZiAoaXNOYW1lKGVudHJ5LmdldCgiUyIpLCAiSmF2YVNjcmlwdCIpKSB7CiAgICAgIGNvbnN0IGpzID0gZW50cnkuZ2V0KCJKUyIpOwogICAgICBsZXQgY29kZTsKICAgICAgaWYgKGpzIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICAgIGNvZGUgPSBqcy5nZXRTdHJpbmcoKTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2YganMgPT09ICJzdHJpbmciKSB7CiAgICAgICAgY29kZSA9IGpzOwogICAgICB9CiAgICAgIGNvZGUgJiY9IHN0cmluZ1RvUERGU3RyaW5nKGNvZGUsIHRydWUpLnJlcGxhY2VBbGwoIlx4MDAiLCAiIik7CiAgICAgIGlmIChjb2RlKSB7CiAgICAgICAgbGlzdC5wdXNoKGNvZGUudHJpbSgpKTsKICAgICAgfQogICAgfQogICAgX2NvbGxlY3RKUyhlbnRyeS5nZXRSYXcoIk5leHQiKSwgeHJlZiwgbGlzdCwgcGFyZW50cyk7CiAgfQogIGlmIChwYXJlbnQpIHsKICAgIHBhcmVudHMucmVtb3ZlKHBhcmVudCk7CiAgfQp9CmZ1bmN0aW9uIGNvbGxlY3RBY3Rpb25zKHhyZWYsIGRpY3QsIGV2ZW50VHlwZSkgewogIGNvbnN0IGFjdGlvbnMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIGNvbnN0IGFkZGl0aW9uYWxBY3Rpb25zRGljdHMgPSBnZXRJbmhlcml0YWJsZVByb3BlcnR5KHsKICAgIGRpY3QsCiAgICBrZXk6ICJBQSIsCiAgICBzdG9wV2hlbkZvdW5kOiBmYWxzZQogIH0pOwogIGlmIChhZGRpdGlvbmFsQWN0aW9uc0RpY3RzKSB7CiAgICBmb3IgKGxldCBpID0gYWRkaXRpb25hbEFjdGlvbnNEaWN0cy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkgewogICAgICBjb25zdCBhZGRpdGlvbmFsQWN0aW9ucyA9IGFkZGl0aW9uYWxBY3Rpb25zRGljdHNbaV07CiAgICAgIGlmICghKGFkZGl0aW9uYWxBY3Rpb25zIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBmb3IgKGNvbnN0IGtleSBvZiBhZGRpdGlvbmFsQWN0aW9ucy5nZXRLZXlzKCkpIHsKICAgICAgICBjb25zdCBhY3Rpb24gPSBldmVudFR5cGVba2V5XTsKICAgICAgICBpZiAoIWFjdGlvbikgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGFjdGlvbkRpY3QgPSBhZGRpdGlvbmFsQWN0aW9ucy5nZXRSYXcoa2V5KTsKICAgICAgICBjb25zdCBwYXJlbnRzID0gbmV3IFJlZlNldCgpOwogICAgICAgIGNvbnN0IGxpc3QgPSBbXTsKICAgICAgICBfY29sbGVjdEpTKGFjdGlvbkRpY3QsIHhyZWYsIGxpc3QsIHBhcmVudHMpOwogICAgICAgIGlmIChsaXN0Lmxlbmd0aCA+IDApIHsKICAgICAgICAgIGFjdGlvbnNbYWN0aW9uXSA9IGxpc3Q7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQogIGlmIChkaWN0LmhhcygiQSIpKSB7CiAgICBjb25zdCBhY3Rpb25EaWN0ID0gZGljdC5nZXQoIkEiKTsKICAgIGNvbnN0IHBhcmVudHMgPSBuZXcgUmVmU2V0KCk7CiAgICBjb25zdCBsaXN0ID0gW107CiAgICBfY29sbGVjdEpTKGFjdGlvbkRpY3QsIHhyZWYsIGxpc3QsIHBhcmVudHMpOwogICAgaWYgKGxpc3QubGVuZ3RoID4gMCkgewogICAgICBhY3Rpb25zLkFjdGlvbiA9IGxpc3Q7CiAgICB9CiAgfQogIHJldHVybiBvYmplY3RTaXplKGFjdGlvbnMpID4gMCA/IGFjdGlvbnMgOiBudWxsOwp9CmNvbnN0IFhNTEVudGl0aWVzID0gewogIDB4M2M6ICImbHQ7IiwKICAweDNlOiAiJmd0OyIsCiAgMHgyNjogIiZhbXA7IiwKICAweDIyOiAiJnF1b3Q7IiwKICAweDI3OiAiJmFwb3M7Igp9OwpmdW5jdGlvbiogY29kZVBvaW50SXRlcihzdHIpIHsKICBmb3IgKGxldCBpID0gMCwgaWkgPSBzdHIubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgY29uc3QgY2hhciA9IHN0ci5jb2RlUG9pbnRBdChpKTsKICAgIGlmIChjaGFyID4gMHhkN2ZmICYmIChjaGFyIDwgMHhlMDAwIHx8IGNoYXIgPiAweGZmZmQpKSB7CiAgICAgIGkrKzsKICAgIH0KICAgIHlpZWxkIGNoYXI7CiAgfQp9CmZ1bmN0aW9uIGVuY29kZVRvWG1sU3RyaW5nKHN0cikgewogIGNvbnN0IGJ1ZmZlciA9IFtdOwogIGxldCBzdGFydCA9IDA7CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gc3RyLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IGNoYXIgPSBzdHIuY29kZVBvaW50QXQoaSk7CiAgICBpZiAoMHgyMCA8PSBjaGFyICYmIGNoYXIgPD0gMHg3ZSkgewogICAgICBjb25zdCBlbnRpdHkgPSBYTUxFbnRpdGllc1tjaGFyXTsKICAgICAgaWYgKGVudGl0eSkgewogICAgICAgIGlmIChzdGFydCA8IGkpIHsKICAgICAgICAgIGJ1ZmZlci5wdXNoKHN0ci5zdWJzdHJpbmcoc3RhcnQsIGkpKTsKICAgICAgICB9CiAgICAgICAgYnVmZmVyLnB1c2goZW50aXR5KTsKICAgICAgICBzdGFydCA9IGkgKyAxOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBpZiAoc3RhcnQgPCBpKSB7CiAgICAgICAgYnVmZmVyLnB1c2goc3RyLnN1YnN0cmluZyhzdGFydCwgaSkpOwogICAgICB9CiAgICAgIGJ1ZmZlci5wdXNoKGAmI3gke2NoYXIudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCl9O2ApOwogICAgICBpZiAoY2hhciA+IDB4ZDdmZiAmJiAoY2hhciA8IDB4ZTAwMCB8fCBjaGFyID4gMHhmZmZkKSkgewogICAgICAgIGkrKzsKICAgICAgfQogICAgICBzdGFydCA9IGkgKyAxOwogICAgfQogIH0KICBpZiAoYnVmZmVyLmxlbmd0aCA9PT0gMCkgewogICAgcmV0dXJuIHN0cjsKICB9CiAgaWYgKHN0YXJ0IDwgc3RyLmxlbmd0aCkgewogICAgYnVmZmVyLnB1c2goc3RyLnN1YnN0cmluZyhzdGFydCwgc3RyLmxlbmd0aCkpOwogIH0KICByZXR1cm4gYnVmZmVyLmpvaW4oIiIpOwp9CmZ1bmN0aW9uIHZhbGlkYXRlRm9udE5hbWUoZm9udEZhbWlseSwgbXVzdFdhcm4gPSBmYWxzZSkgewogIGNvbnN0IG0gPSAvXigifCcpLiooInwnKSQvLmV4ZWMoZm9udEZhbWlseSk7CiAgaWYgKG0gJiYgbVsxXSA9PT0gbVsyXSkgewogICAgY29uc3QgcmUgPSBuZXcgUmVnRXhwKGBbXlxcXFxdJHttWzFdfWApOwogICAgaWYgKHJlLnRlc3QoZm9udEZhbWlseS5zbGljZSgxLCAtMSkpKSB7CiAgICAgIGlmIChtdXN0V2FybikgewogICAgICAgIHdhcm4oYEZvbnRGYW1pbHkgY29udGFpbnMgdW5lc2NhcGVkICR7bVsxXX06ICR7Zm9udEZhbWlseX0uYCk7CiAgICAgIH0KICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogIH0gZWxzZSB7CiAgICBmb3IgKGNvbnN0IGlkZW50IG9mIGZvbnRGYW1pbHkuc3BsaXQoL1sgXHRdKy8pKSB7CiAgICAgIGlmICgvXihcZHwoLShcZHwtKSkpLy50ZXN0KGlkZW50KSB8fCAhL15bXHctXFxdKyQvLnRlc3QoaWRlbnQpKSB7CiAgICAgICAgaWYgKG11c3RXYXJuKSB7CiAgICAgICAgICB3YXJuKGBGb250RmFtaWx5IGNvbnRhaW5zIGludmFsaWQgPGN1c3RvbS1pZGVudD46ICR7Zm9udEZhbWlseX0uYCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgfQogIH0KICByZXR1cm4gdHJ1ZTsKfQpmdW5jdGlvbiB2YWxpZGF0ZUNTU0ZvbnQoY3NzRm9udEluZm8pIHsKICBjb25zdCBERUZBVUxUX0NTU19GT05UX09CTElRVUUgPSAiMTQiOwogIGNvbnN0IERFRkFVTFRfQ1NTX0ZPTlRfV0VJR0hUID0gIjQwMCI7CiAgY29uc3QgQ1NTX0ZPTlRfV0VJR0hUX1ZBTFVFUyA9IG5ldyBTZXQoWyIxMDAiLCAiMjAwIiwgIjMwMCIsICI0MDAiLCAiNTAwIiwgIjYwMCIsICI3MDAiLCAiODAwIiwgIjkwMCIsICIxMDAwIiwgIm5vcm1hbCIsICJib2xkIiwgImJvbGRlciIsICJsaWdodGVyIl0pOwogIGNvbnN0IHsKICAgIGZvbnRGYW1pbHksCiAgICBmb250V2VpZ2h0LAogICAgaXRhbGljQW5nbGUKICB9ID0gY3NzRm9udEluZm87CiAgaWYgKCF2YWxpZGF0ZUZvbnROYW1lKGZvbnRGYW1pbHksIHRydWUpKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGNvbnN0IHdlaWdodCA9IGZvbnRXZWlnaHQgPyBmb250V2VpZ2h0LnRvU3RyaW5nKCkgOiAiIjsKICBjc3NGb250SW5mby5mb250V2VpZ2h0ID0gQ1NTX0ZPTlRfV0VJR0hUX1ZBTFVFUy5oYXMod2VpZ2h0KSA/IHdlaWdodCA6IERFRkFVTFRfQ1NTX0ZPTlRfV0VJR0hUOwogIGNvbnN0IGFuZ2xlID0gcGFyc2VGbG9hdChpdGFsaWNBbmdsZSk7CiAgY3NzRm9udEluZm8uaXRhbGljQW5nbGUgPSBpc05hTihhbmdsZSkgfHwgYW5nbGUgPCAtOTAgfHwgYW5nbGUgPiA5MCA/IERFRkFVTFRfQ1NTX0ZPTlRfT0JMSVFVRSA6IGl0YWxpY0FuZ2xlLnRvU3RyaW5nKCk7CiAgcmV0dXJuIHRydWU7Cn0KZnVuY3Rpb24gcmVjb3ZlckpzVVJMKHN0cikgewogIGNvbnN0IFVSTF9PUEVOX01FVEhPRFMgPSBbImFwcC5sYXVuY2hVUkwiLCAid2luZG93Lm9wZW4iLCAieGZhLmhvc3QuZ290b1VSTCJdOwogIGNvbnN0IHJlZ2V4ID0gbmV3IFJlZ0V4cCgiXlxccyooIiArIFVSTF9PUEVOX01FVEhPRFMuam9pbigifCIpLnJlcGxhY2VBbGwoIi4iLCAiXFwuIikgKyAiKVxcKCg/Oid8XCIpKFteJ1wiXSopKD86J3xcIikoPzosXFxzKihcXHcrKVxcKXxcXCkpIiwgImkiKTsKICBjb25zdCBqc1VybCA9IHJlZ2V4LmV4ZWMoc3RyKTsKICBpZiAoanNVcmw/LlsyXSkgewogICAgcmV0dXJuIHsKICAgICAgdXJsOiBqc1VybFsyXSwKICAgICAgbmV3V2luZG93OiBqc1VybFsxXSA9PT0gImFwcC5sYXVuY2hVUkwiICYmIGpzVXJsWzNdID09PSAidHJ1ZSIKICAgIH07CiAgfQogIHJldHVybiBudWxsOwp9CmZ1bmN0aW9uIG51bWJlclRvU3RyaW5nKHZhbHVlKSB7CiAgaWYgKE51bWJlci5pc0ludGVnZXIodmFsdWUpKSB7CiAgICByZXR1cm4gdmFsdWUudG9TdHJpbmcoKTsKICB9CiAgY29uc3Qgcm91bmRlZFZhbHVlID0gTWF0aC5yb3VuZCh2YWx1ZSAqIDEwMCk7CiAgaWYgKHJvdW5kZWRWYWx1ZSAlIDEwMCA9PT0gMCkgewogICAgcmV0dXJuIChyb3VuZGVkVmFsdWUgLyAxMDApLnRvU3RyaW5nKCk7CiAgfQogIGlmIChyb3VuZGVkVmFsdWUgJSAxMCA9PT0gMCkgewogICAgcmV0dXJuIHZhbHVlLnRvRml4ZWQoMSk7CiAgfQogIHJldHVybiB2YWx1ZS50b0ZpeGVkKDIpOwp9CmZ1bmN0aW9uIGdldE5ld0Fubm90YXRpb25zTWFwKGFubm90YXRpb25TdG9yYWdlKSB7CiAgaWYgKCFhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGNvbnN0IG5ld0Fubm90YXRpb25zQnlQYWdlID0gbmV3IE1hcCgpOwogIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBpZiAoIWtleS5zdGFydHNXaXRoKEFubm90YXRpb25FZGl0b3JQcmVmaXgpKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgbGV0IGFubm90YXRpb25zID0gbmV3QW5ub3RhdGlvbnNCeVBhZ2UuZ2V0KHZhbHVlLnBhZ2VJbmRleCk7CiAgICBpZiAoIWFubm90YXRpb25zKSB7CiAgICAgIGFubm90YXRpb25zID0gW107CiAgICAgIG5ld0Fubm90YXRpb25zQnlQYWdlLnNldCh2YWx1ZS5wYWdlSW5kZXgsIGFubm90YXRpb25zKTsKICAgIH0KICAgIGFubm90YXRpb25zLnB1c2godmFsdWUpOwogIH0KICByZXR1cm4gbmV3QW5ub3RhdGlvbnNCeVBhZ2Uuc2l6ZSA+IDAgPyBuZXdBbm5vdGF0aW9uc0J5UGFnZSA6IG51bGw7Cn0KZnVuY3Rpb24gc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRShzdHIpIHsKICBpZiAoc3RyID09PSBudWxsIHx8IHN0ciA9PT0gdW5kZWZpbmVkKSB7CiAgICByZXR1cm4gc3RyOwogIH0KICByZXR1cm4gaXNBc2NpaShzdHIpID8gc3RyIDogc3RyaW5nVG9VVEYxNlN0cmluZyhzdHIsIHRydWUpOwp9CmZ1bmN0aW9uIGlzQXNjaWkoc3RyKSB7CiAgaWYgKHR5cGVvZiBzdHIgIT09ICJzdHJpbmciKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIHJldHVybiAhc3RyIHx8IC9eW1x4MDAtXHg3Rl0qJC8udGVzdChzdHIpOwp9CmZ1bmN0aW9uIHN0cmluZ1RvVVRGMTZIZXhTdHJpbmcoc3RyKSB7CiAgY29uc3QgYnVmID0gW107CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gc3RyLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IGNoYXIgPSBzdHIuY2hhckNvZGVBdChpKTsKICAgIGJ1Zi5wdXNoKGhleE51bWJlcnNbY2hhciA+PiA4ICYgMHhmZl0sIGhleE51bWJlcnNbY2hhciAmIDB4ZmZdKTsKICB9CiAgcmV0dXJuIGJ1Zi5qb2luKCIiKTsKfQpmdW5jdGlvbiBzdHJpbmdUb1VURjE2U3RyaW5nKHN0ciwgYmlnRW5kaWFuID0gZmFsc2UpIHsKICBjb25zdCBidWYgPSBbXTsKICBpZiAoYmlnRW5kaWFuKSB7CiAgICBidWYucHVzaCgiXHhGRVx4RkYiKTsKICB9CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gc3RyLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IGNoYXIgPSBzdHIuY2hhckNvZGVBdChpKTsKICAgIGJ1Zi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoY2hhciA+PiA4ICYgMHhmZiksIFN0cmluZy5mcm9tQ2hhckNvZGUoY2hhciAmIDB4ZmYpKTsKICB9CiAgcmV0dXJuIGJ1Zi5qb2luKCIiKTsKfQpmdW5jdGlvbiBnZXRSb3RhdGlvbk1hdHJpeChyb3RhdGlvbiwgd2lkdGgsIGhlaWdodCkgewogIHN3aXRjaCAocm90YXRpb24pIHsKICAgIGNhc2UgOTA6CiAgICAgIHJldHVybiBbMCwgMSwgLTEsIDAsIHdpZHRoLCAwXTsKICAgIGNhc2UgMTgwOgogICAgICByZXR1cm4gWy0xLCAwLCAwLCAtMSwgd2lkdGgsIGhlaWdodF07CiAgICBjYXNlIDI3MDoKICAgICAgcmV0dXJuIFswLCAtMSwgMSwgMCwgMCwgaGVpZ2h0XTsKICAgIGRlZmF1bHQ6CiAgICAgIHRocm93IG5ldyBFcnJvcigiSW52YWxpZCByb3RhdGlvbiIpOwogIH0KfQpmdW5jdGlvbiBnZXRTaXplSW5CeXRlcyh4KSB7CiAgcmV0dXJuIE1hdGguY2VpbChNYXRoLmNlaWwoTWF0aC5sb2cyKDEgKyB4KSkgLyA4KTsKfQoKLy8gRVhURVJOQUwgTU9EVUxFOiAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvd2ViLnVybC1zZWFyY2gtcGFyYW1zLmRlbGV0ZS5qcwp2YXIgd2ViX3VybF9zZWFyY2hfcGFyYW1zX2RlbGV0ZSA9IF9fd2VicGFja19yZXF1aXJlX18oNDYwMyk7Ci8vIEVYVEVSTkFMIE1PRFVMRTogLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL3dlYi51cmwtc2VhcmNoLXBhcmFtcy5oYXMuanMKdmFyIHdlYl91cmxfc2VhcmNoX3BhcmFtc19oYXMgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDc1NjYpOwovLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy93ZWIudXJsLXNlYXJjaC1wYXJhbXMuc2l6ZS5qcwp2YXIgd2ViX3VybF9zZWFyY2hfcGFyYW1zX3NpemUgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDg3MjEpOwo7Ly8gLi9leHRlcm5hbC9xY21zL3FjbXNfdXRpbHMuanMKCgoKCgoKCgpjbGFzcyBRQ01TIHsKICBzdGF0aWMgI21lbW9yeUFycmF5ID0gbnVsbDsKICBzdGF0aWMgX21lbW9yeSA9IG51bGw7CiAgc3RhdGljIF9tdXN0QWRkQWxwaGEgPSBmYWxzZTsKICBzdGF0aWMgX2Rlc3RCdWZmZXIgPSBudWxsOwogIHN0YXRpYyBfZGVzdE9mZnNldCA9IDA7CiAgc3RhdGljIF9kZXN0TGVuZ3RoID0gMDsKICBzdGF0aWMgX2Nzc0NvbG9yID0gIiI7CiAgc3RhdGljIF9tYWtlSGV4Q29sb3IgPSBudWxsOwogIHN0YXRpYyBnZXQgX21lbW9yeUFycmF5KCkgewogICAgY29uc3QgYXJyYXkgPSB0aGlzLiNtZW1vcnlBcnJheTsKICAgIGlmIChhcnJheT8uYnl0ZUxlbmd0aCkgewogICAgICByZXR1cm4gYXJyYXk7CiAgICB9CiAgICByZXR1cm4gdGhpcy4jbWVtb3J5QXJyYXkgPSBuZXcgVWludDhBcnJheSh0aGlzLl9tZW1vcnkuYnVmZmVyKTsKICB9Cn0KZnVuY3Rpb24gY29weV9yZXN1bHQocHRyLCBsZW4pIHsKICBjb25zdCB7CiAgICBfbXVzdEFkZEFscGhhLAogICAgX2Rlc3RCdWZmZXIsCiAgICBfZGVzdE9mZnNldCwKICAgIF9kZXN0TGVuZ3RoLAogICAgX21lbW9yeUFycmF5CiAgfSA9IFFDTVM7CiAgaWYgKGxlbiA9PT0gX2Rlc3RMZW5ndGgpIHsKICAgIF9kZXN0QnVmZmVyLnNldChfbWVtb3J5QXJyYXkuc3ViYXJyYXkocHRyLCBwdHIgKyBsZW4pLCBfZGVzdE9mZnNldCk7CiAgICByZXR1cm47CiAgfQogIGlmIChfbXVzdEFkZEFscGhhKSB7CiAgICBmb3IgKGxldCBpID0gcHRyLCBpaSA9IHB0ciArIGxlbiwgaiA9IF9kZXN0T2Zmc2V0OyBpIDwgaWk7IGkgKz0gMywgaiArPSA0KSB7CiAgICAgIF9kZXN0QnVmZmVyW2pdID0gX21lbW9yeUFycmF5W2ldOwogICAgICBfZGVzdEJ1ZmZlcltqICsgMV0gPSBfbWVtb3J5QXJyYXlbaSArIDFdOwogICAgICBfZGVzdEJ1ZmZlcltqICsgMl0gPSBfbWVtb3J5QXJyYXlbaSArIDJdOwogICAgICBfZGVzdEJ1ZmZlcltqICsgM10gPSAyNTU7CiAgICB9CiAgfSBlbHNlIHsKICAgIGZvciAobGV0IGkgPSBwdHIsIGlpID0gcHRyICsgbGVuLCBqID0gX2Rlc3RPZmZzZXQ7IGkgPCBpaTsgaSArPSAzLCBqICs9IDQpIHsKICAgICAgX2Rlc3RCdWZmZXJbal0gPSBfbWVtb3J5QXJyYXlbaV07CiAgICAgIF9kZXN0QnVmZmVyW2ogKyAxXSA9IF9tZW1vcnlBcnJheVtpICsgMV07CiAgICAgIF9kZXN0QnVmZmVyW2ogKyAyXSA9IF9tZW1vcnlBcnJheVtpICsgMl07CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGNvcHlfcmdiKHB0cikgewogIGNvbnN0IHsKICAgIF9kZXN0QnVmZmVyLAogICAgX2Rlc3RPZmZzZXQsCiAgICBfbWVtb3J5QXJyYXkKICB9ID0gUUNNUzsKICBfZGVzdEJ1ZmZlcltfZGVzdE9mZnNldF0gPSBfbWVtb3J5QXJyYXlbcHRyXTsKICBfZGVzdEJ1ZmZlcltfZGVzdE9mZnNldCArIDFdID0gX21lbW9yeUFycmF5W3B0ciArIDFdOwogIF9kZXN0QnVmZmVyW19kZXN0T2Zmc2V0ICsgMl0gPSBfbWVtb3J5QXJyYXlbcHRyICsgMl07Cn0KZnVuY3Rpb24gbWFrZV9jc3NSR0IocHRyKSB7CiAgY29uc3QgewogICAgX21lbW9yeUFycmF5CiAgfSA9IFFDTVM7CiAgUUNNUy5fY3NzQ29sb3IgPSBRQ01TLl9tYWtlSGV4Q29sb3IoX21lbW9yeUFycmF5W3B0cl0sIF9tZW1vcnlBcnJheVtwdHIgKyAxXSwgX21lbW9yeUFycmF5W3B0ciArIDJdKTsKfQoKOy8vIC4vZXh0ZXJuYWwvcWNtcy9xY21zLmpzCgoKCgoKCgoKCgoKCmxldCB3YXNtOwpjb25zdCBjYWNoZWRUZXh0RGVjb2RlciA9IHR5cGVvZiBUZXh0RGVjb2RlciAhPT0gJ3VuZGVmaW5lZCcgPyBuZXcgVGV4dERlY29kZXIoJ3V0Zi04JywgewogIGlnbm9yZUJPTTogdHJ1ZSwKICBmYXRhbDogdHJ1ZQp9KSA6IHsKICBkZWNvZGU6ICgpID0+IHsKICAgIHRocm93IEVycm9yKCdUZXh0RGVjb2RlciBub3QgYXZhaWxhYmxlJyk7CiAgfQp9OwppZiAodHlwZW9mIFRleHREZWNvZGVyICE9PSAndW5kZWZpbmVkJykgewogIGNhY2hlZFRleHREZWNvZGVyLmRlY29kZSgpOwp9CjsKbGV0IGNhY2hlZFVpbnQ4QXJyYXlNZW1vcnkwID0gbnVsbDsKZnVuY3Rpb24gZ2V0VWludDhBcnJheU1lbW9yeTAoKSB7CiAgaWYgKGNhY2hlZFVpbnQ4QXJyYXlNZW1vcnkwID09PSBudWxsIHx8IGNhY2hlZFVpbnQ4QXJyYXlNZW1vcnkwLmJ5dGVMZW5ndGggPT09IDApIHsKICAgIGNhY2hlZFVpbnQ4QXJyYXlNZW1vcnkwID0gbmV3IFVpbnQ4QXJyYXkod2FzbS5tZW1vcnkuYnVmZmVyKTsKICB9CiAgcmV0dXJuIGNhY2hlZFVpbnQ4QXJyYXlNZW1vcnkwOwp9CmZ1bmN0aW9uIGdldFN0cmluZ0Zyb21XYXNtMChwdHIsIGxlbikgewogIHB0ciA9IHB0ciA+Pj4gMDsKICByZXR1cm4gY2FjaGVkVGV4dERlY29kZXIuZGVjb2RlKGdldFVpbnQ4QXJyYXlNZW1vcnkwKCkuc3ViYXJyYXkocHRyLCBwdHIgKyBsZW4pKTsKfQpsZXQgV0FTTV9WRUNUT1JfTEVOID0gMDsKZnVuY3Rpb24gcGFzc0FycmF5OFRvV2FzbTAoYXJnLCBtYWxsb2MpIHsKICBjb25zdCBwdHIgPSBtYWxsb2MoYXJnLmxlbmd0aCAqIDEsIDEpID4+PiAwOwogIGdldFVpbnQ4QXJyYXlNZW1vcnkwKCkuc2V0KGFyZywgcHRyIC8gMSk7CiAgV0FTTV9WRUNUT1JfTEVOID0gYXJnLmxlbmd0aDsKICByZXR1cm4gcHRyOwp9CmZ1bmN0aW9uIHFjbXNfY29udmVydF9hcnJheSh0cmFuc2Zvcm1lciwgc3JjKSB7CiAgY29uc3QgcHRyMCA9IHBhc3NBcnJheThUb1dhc20wKHNyYywgd2FzbS5fX3diaW5kZ2VuX21hbGxvYyk7CiAgY29uc3QgbGVuMCA9IFdBU01fVkVDVE9SX0xFTjsKICB3YXNtLnFjbXNfY29udmVydF9hcnJheSh0cmFuc2Zvcm1lciwgcHRyMCwgbGVuMCk7Cn0KZnVuY3Rpb24gcWNtc19jb252ZXJ0X29uZSh0cmFuc2Zvcm1lciwgc3JjLCBjc3MpIHsKICB3YXNtLnFjbXNfY29udmVydF9vbmUodHJhbnNmb3JtZXIsIHNyYywgY3NzKTsKfQpmdW5jdGlvbiBxY21zX2NvbnZlcnRfdGhyZWUodHJhbnNmb3JtZXIsIHNyYzEsIHNyYzIsIHNyYzMsIGNzcykgewogIHdhc20ucWNtc19jb252ZXJ0X3RocmVlKHRyYW5zZm9ybWVyLCBzcmMxLCBzcmMyLCBzcmMzLCBjc3MpOwp9CmZ1bmN0aW9uIHFjbXNfY29udmVydF9mb3VyKHRyYW5zZm9ybWVyLCBzcmMxLCBzcmMyLCBzcmMzLCBzcmM0LCBjc3MpIHsKICB3YXNtLnFjbXNfY29udmVydF9mb3VyKHRyYW5zZm9ybWVyLCBzcmMxLCBzcmMyLCBzcmMzLCBzcmM0LCBjc3MpOwp9CmZ1bmN0aW9uIHFjbXNfdHJhbnNmb3JtZXJfZnJvbV9tZW1vcnkobWVtLCBpbl90eXBlLCBpbnRlbnQpIHsKICBjb25zdCBwdHIwID0gcGFzc0FycmF5OFRvV2FzbTAobWVtLCB3YXNtLl9fd2JpbmRnZW5fbWFsbG9jKTsKICBjb25zdCBsZW4wID0gV0FTTV9WRUNUT1JfTEVOOwogIGNvbnN0IHJldCA9IHdhc20ucWNtc190cmFuc2Zvcm1lcl9mcm9tX21lbW9yeShwdHIwLCBsZW4wLCBpbl90eXBlLCBpbnRlbnQpOwogIHJldHVybiByZXQgPj4+IDA7Cn0KZnVuY3Rpb24gcWNtc19kcm9wX3RyYW5zZm9ybWVyKHRyYW5zZm9ybWVyKSB7CiAgd2FzbS5xY21zX2Ryb3BfdHJhbnNmb3JtZXIodHJhbnNmb3JtZXIpOwp9CmNvbnN0IERhdGFUeXBlID0gT2JqZWN0LmZyZWV6ZSh7CiAgUkdCODogMCwKICAiMCI6ICJSR0I4IiwKICBSR0JBODogMSwKICAiMSI6ICJSR0JBOCIsCiAgQkdSQTg6IDIsCiAgIjIiOiAiQkdSQTgiLAogIEdyYXk4OiAzLAogICIzIjogIkdyYXk4IiwKICBHcmF5QTg6IDQsCiAgIjQiOiAiR3JheUE4IiwKICBDTVlLOiA1LAogICI1IjogIkNNWUsiCn0pOwpjb25zdCBJbnRlbnQgPSBPYmplY3QuZnJlZXplKHsKICBQZXJjZXB0dWFsOiAwLAogICIwIjogIlBlcmNlcHR1YWwiLAogIFJlbGF0aXZlQ29sb3JpbWV0cmljOiAxLAogICIxIjogIlJlbGF0aXZlQ29sb3JpbWV0cmljIiwKICBTYXR1cmF0aW9uOiAyLAogICIyIjogIlNhdHVyYXRpb24iLAogIEFic29sdXRlQ29sb3JpbWV0cmljOiAzLAogICIzIjogIkFic29sdXRlQ29sb3JpbWV0cmljIgp9KTsKYXN5bmMgZnVuY3Rpb24gX193YmdfbG9hZChtb2R1bGUsIGltcG9ydHMpIHsKICBpZiAodHlwZW9mIFJlc3BvbnNlID09PSAnZnVuY3Rpb24nICYmIG1vZHVsZSBpbnN0YW5jZW9mIFJlc3BvbnNlKSB7CiAgICBpZiAodHlwZW9mIFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nID09PSAnZnVuY3Rpb24nKSB7CiAgICAgIHRyeSB7CiAgICAgICAgcmV0dXJuIGF3YWl0IFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nKG1vZHVsZSwgaW1wb3J0cyk7CiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAobW9kdWxlLmhlYWRlcnMuZ2V0KCdDb250ZW50LVR5cGUnKSAhPSAnYXBwbGljYXRpb24vd2FzbScpIHsKICAgICAgICAgIGNvbnNvbGUud2FybigiYFdlYkFzc2VtYmx5Lmluc3RhbnRpYXRlU3RyZWFtaW5nYCBmYWlsZWQgYmVjYXVzZSB5b3VyIHNlcnZlciBkb2VzIG5vdCBzZXJ2ZSBXYXNtIHdpdGggYGFwcGxpY2F0aW9uL3dhc21gIE1JTUUgdHlwZS4gRmFsbGluZyBiYWNrIHRvIGBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZWAgd2hpY2ggaXMgc2xvd2VyLiBPcmlnaW5hbCBlcnJvcjpcbiIsIGUpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aHJvdyBlOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgY29uc3QgYnl0ZXMgPSBhd2FpdCBtb2R1bGUuYXJyYXlCdWZmZXIoKTsKICAgIHJldHVybiBhd2FpdCBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZShieXRlcywgaW1wb3J0cyk7CiAgfSBlbHNlIHsKICAgIGNvbnN0IGluc3RhbmNlID0gYXdhaXQgV2ViQXNzZW1ibHkuaW5zdGFudGlhdGUobW9kdWxlLCBpbXBvcnRzKTsKICAgIGlmIChpbnN0YW5jZSBpbnN0YW5jZW9mIFdlYkFzc2VtYmx5Lkluc3RhbmNlKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgaW5zdGFuY2UsCiAgICAgICAgbW9kdWxlCiAgICAgIH07CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gaW5zdGFuY2U7CiAgICB9CiAgfQp9CmZ1bmN0aW9uIF9fd2JnX2dldF9pbXBvcnRzKCkgewogIGNvbnN0IGltcG9ydHMgPSB7fTsKICBpbXBvcnRzLndiZyA9IHt9OwogIGltcG9ydHMud2JnLl9fd2JnX2NvcHlyZXN1bHRfYjA4ZWU3ZDI3M2YyOTVkZCA9IGZ1bmN0aW9uIChhcmcwLCBhcmcxKSB7CiAgICBjb3B5X3Jlc3VsdChhcmcwID4+PiAwLCBhcmcxID4+PiAwKTsKICB9OwogIGltcG9ydHMud2JnLl9fd2JnX2NvcHlyZ2JfZDYwY2UxN2JiMDVkOWI2NyA9IGZ1bmN0aW9uIChhcmcwKSB7CiAgICBjb3B5X3JnYihhcmcwID4+PiAwKTsKICB9OwogIGltcG9ydHMud2JnLl9fd2JnX21ha2Vjc3NSR0JfODkzYmYwY2Q5ZmRiMzAyZCA9IGZ1bmN0aW9uIChhcmcwKSB7CiAgICBtYWtlX2Nzc1JHQihhcmcwID4+PiAwKTsKICB9OwogIGltcG9ydHMud2JnLl9fd2JpbmRnZW5faW5pdF9leHRlcm5yZWZfdGFibGUgPSBmdW5jdGlvbiAoKSB7CiAgICBjb25zdCB0YWJsZSA9IHdhc20uX193YmluZGdlbl9leHBvcnRfMDsKICAgIGNvbnN0IG9mZnNldCA9IHRhYmxlLmdyb3coNCk7CiAgICB0YWJsZS5zZXQoMCwgdW5kZWZpbmVkKTsKICAgIHRhYmxlLnNldChvZmZzZXQgKyAwLCB1bmRlZmluZWQpOwogICAgdGFibGUuc2V0KG9mZnNldCArIDEsIG51bGwpOwogICAgdGFibGUuc2V0KG9mZnNldCArIDIsIHRydWUpOwogICAgdGFibGUuc2V0KG9mZnNldCArIDMsIGZhbHNlKTsKICB9OwogIGltcG9ydHMud2JnLl9fd2JpbmRnZW5fdGhyb3cgPSBmdW5jdGlvbiAoYXJnMCwgYXJnMSkgewogICAgdGhyb3cgbmV3IEVycm9yKGdldFN0cmluZ0Zyb21XYXNtMChhcmcwLCBhcmcxKSk7CiAgfTsKICByZXR1cm4gaW1wb3J0czsKfQpmdW5jdGlvbiBfX3diZ19pbml0X21lbW9yeShpbXBvcnRzLCBtZW1vcnkpIHt9CmZ1bmN0aW9uIF9fd2JnX2ZpbmFsaXplX2luaXQoaW5zdGFuY2UsIG1vZHVsZSkgewogIHdhc20gPSBpbnN0YW5jZS5leHBvcnRzOwogIF9fd2JnX2luaXQuX193YmluZGdlbl93YXNtX21vZHVsZSA9IG1vZHVsZTsKICBjYWNoZWRVaW50OEFycmF5TWVtb3J5MCA9IG51bGw7CiAgd2FzbS5fX3diaW5kZ2VuX3N0YXJ0KCk7CiAgcmV0dXJuIHdhc207Cn0KZnVuY3Rpb24gaW5pdFN5bmMobW9kdWxlKSB7CiAgaWYgKHdhc20gIT09IHVuZGVmaW5lZCkgcmV0dXJuIHdhc207CiAgaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnKSB7CiAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKG1vZHVsZSkgPT09IE9iamVjdC5wcm90b3R5cGUpIHsKICAgICAgKHsKICAgICAgICBtb2R1bGUKICAgICAgfSA9IG1vZHVsZSk7CiAgICB9IGVsc2UgewogICAgICBjb25zb2xlLndhcm4oJ3VzaW5nIGRlcHJlY2F0ZWQgcGFyYW1ldGVycyBmb3IgYGluaXRTeW5jKClgOyBwYXNzIGEgc2luZ2xlIG9iamVjdCBpbnN0ZWFkJyk7CiAgICB9CiAgfQogIGNvbnN0IGltcG9ydHMgPSBfX3diZ19nZXRfaW1wb3J0cygpOwogIF9fd2JnX2luaXRfbWVtb3J5KGltcG9ydHMpOwogIGlmICghKG1vZHVsZSBpbnN0YW5jZW9mIFdlYkFzc2VtYmx5Lk1vZHVsZSkpIHsKICAgIG1vZHVsZSA9IG5ldyBXZWJBc3NlbWJseS5Nb2R1bGUobW9kdWxlKTsKICB9CiAgY29uc3QgaW5zdGFuY2UgPSBuZXcgV2ViQXNzZW1ibHkuSW5zdGFuY2UobW9kdWxlLCBpbXBvcnRzKTsKICByZXR1cm4gX193YmdfZmluYWxpemVfaW5pdChpbnN0YW5jZSwgbW9kdWxlKTsKfQphc3luYyBmdW5jdGlvbiBfX3diZ19pbml0KG1vZHVsZV9vcl9wYXRoKSB7CiAgaWYgKHdhc20gIT09IHVuZGVmaW5lZCkgcmV0dXJuIHdhc207CiAgaWYgKHR5cGVvZiBtb2R1bGVfb3JfcGF0aCAhPT0gJ3VuZGVmaW5lZCcpIHsKICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YobW9kdWxlX29yX3BhdGgpID09PSBPYmplY3QucHJvdG90eXBlKSB7CiAgICAgICh7CiAgICAgICAgbW9kdWxlX29yX3BhdGgKICAgICAgfSA9IG1vZHVsZV9vcl9wYXRoKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnNvbGUud2FybigndXNpbmcgZGVwcmVjYXRlZCBwYXJhbWV0ZXJzIGZvciB0aGUgaW5pdGlhbGl6YXRpb24gZnVuY3Rpb247IHBhc3MgYSBzaW5nbGUgb2JqZWN0IGluc3RlYWQnKTsKICAgIH0KICB9CiAgY29uc3QgaW1wb3J0cyA9IF9fd2JnX2dldF9pbXBvcnRzKCk7CiAgaWYgKHR5cGVvZiBtb2R1bGVfb3JfcGF0aCA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIFJlcXVlc3QgPT09ICdmdW5jdGlvbicgJiYgbW9kdWxlX29yX3BhdGggaW5zdGFuY2VvZiBSZXF1ZXN0IHx8IHR5cGVvZiBVUkwgPT09ICdmdW5jdGlvbicgJiYgbW9kdWxlX29yX3BhdGggaW5zdGFuY2VvZiBVUkwpIHsKICAgIG1vZHVsZV9vcl9wYXRoID0gZmV0Y2gobW9kdWxlX29yX3BhdGgpOwogIH0KICBfX3diZ19pbml0X21lbW9yeShpbXBvcnRzKTsKICBjb25zdCB7CiAgICBpbnN0YW5jZSwKICAgIG1vZHVsZQogIH0gPSBhd2FpdCBfX3diZ19sb2FkKGF3YWl0IG1vZHVsZV9vcl9wYXRoLCBpbXBvcnRzKTsKICByZXR1cm4gX193YmdfZmluYWxpemVfaW5pdChpbnN0YW5jZSwgbW9kdWxlKTsKfQoKLyogaGFybW9ueSBkZWZhdWx0IGV4cG9ydCAqLyBjb25zdCBxY21zID0gKCgvKiB1bnVzZWQgcHVyZSBleHByZXNzaW9uIG9yIHN1cGVyICovIG51bGwgJiYgKF9fd2JnX2luaXQpKSk7CjsvLyAuL3NyYy9jb3JlL2NvbG9yc3BhY2UuanMKCgoKCgoKCgoKCmZ1bmN0aW9uIHJlc2l6ZVJnYkltYWdlKHNyYywgZGVzdCwgdzEsIGgxLCB3MiwgaDIsIGFscGhhMDEpIHsKICBjb25zdCBDT01QT05FTlRTID0gMzsKICBhbHBoYTAxID0gYWxwaGEwMSAhPT0gMSA/IDAgOiBhbHBoYTAxOwogIGNvbnN0IHhSYXRpbyA9IHcxIC8gdzI7CiAgY29uc3QgeVJhdGlvID0gaDEgLyBoMjsKICBsZXQgbmV3SW5kZXggPSAwLAogICAgb2xkSW5kZXg7CiAgY29uc3QgeFNjYWxlZCA9IG5ldyBVaW50MTZBcnJheSh3Mik7CiAgY29uc3QgdzFTY2FubGluZSA9IHcxICogQ09NUE9ORU5UUzsKICBmb3IgKGxldCBpID0gMDsgaSA8IHcyOyBpKyspIHsKICAgIHhTY2FsZWRbaV0gPSBNYXRoLmZsb29yKGkgKiB4UmF0aW8pICogQ09NUE9ORU5UUzsKICB9CiAgZm9yIChsZXQgaSA9IDA7IGkgPCBoMjsgaSsrKSB7CiAgICBjb25zdCBweSA9IE1hdGguZmxvb3IoaSAqIHlSYXRpbykgKiB3MVNjYW5saW5lOwogICAgZm9yIChsZXQgaiA9IDA7IGogPCB3MjsgaisrKSB7CiAgICAgIG9sZEluZGV4ID0gcHkgKyB4U2NhbGVkW2pdOwogICAgICBkZXN0W25ld0luZGV4KytdID0gc3JjW29sZEluZGV4KytdOwogICAgICBkZXN0W25ld0luZGV4KytdID0gc3JjW29sZEluZGV4KytdOwogICAgICBkZXN0W25ld0luZGV4KytdID0gc3JjW29sZEluZGV4KytdOwogICAgICBuZXdJbmRleCArPSBhbHBoYTAxOwogICAgfQogIH0KfQpmdW5jdGlvbiByZXNpemVSZ2JhSW1hZ2Uoc3JjLCBkZXN0LCB3MSwgaDEsIHcyLCBoMiwgYWxwaGEwMSkgewogIGNvbnN0IHhSYXRpbyA9IHcxIC8gdzI7CiAgY29uc3QgeVJhdGlvID0gaDEgLyBoMjsKICBsZXQgbmV3SW5kZXggPSAwOwogIGNvbnN0IHhTY2FsZWQgPSBuZXcgVWludDE2QXJyYXkodzIpOwogIGlmIChhbHBoYTAxID09PSAxKSB7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHcyOyBpKyspIHsKICAgICAgeFNjYWxlZFtpXSA9IE1hdGguZmxvb3IoaSAqIHhSYXRpbyk7CiAgICB9CiAgICBjb25zdCBzcmMzMiA9IG5ldyBVaW50MzJBcnJheShzcmMuYnVmZmVyKTsKICAgIGNvbnN0IGRlc3QzMiA9IG5ldyBVaW50MzJBcnJheShkZXN0LmJ1ZmZlcik7CiAgICBjb25zdCByZ2JNYXNrID0gRmVhdHVyZVRlc3QuaXNMaXR0bGVFbmRpYW4gPyAweDAwZmZmZmZmIDogMHhmZmZmZmYwMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaDI7IGkrKykgewogICAgICBjb25zdCBidWYgPSBzcmMzMi5zdWJhcnJheShNYXRoLmZsb29yKGkgKiB5UmF0aW8pICogdzEpOwogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHcyOyBqKyspIHsKICAgICAgICBkZXN0MzJbbmV3SW5kZXgrK10gfD0gYnVmW3hTY2FsZWRbal1dICYgcmdiTWFzazsKICAgICAgfQogICAgfQogIH0gZWxzZSB7CiAgICBjb25zdCBDT01QT05FTlRTID0gNDsKICAgIGNvbnN0IHcxU2NhbmxpbmUgPSB3MSAqIENPTVBPTkVOVFM7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHcyOyBpKyspIHsKICAgICAgeFNjYWxlZFtpXSA9IE1hdGguZmxvb3IoaSAqIHhSYXRpbykgKiBDT01QT05FTlRTOwogICAgfQogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBoMjsgaSsrKSB7CiAgICAgIGNvbnN0IGJ1ZiA9IHNyYy5zdWJhcnJheShNYXRoLmZsb29yKGkgKiB5UmF0aW8pICogdzFTY2FubGluZSk7CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgdzI7IGorKykgewogICAgICAgIGNvbnN0IG9sZEluZGV4ID0geFNjYWxlZFtqXTsKICAgICAgICBkZXN0W25ld0luZGV4KytdID0gYnVmW29sZEluZGV4XTsKICAgICAgICBkZXN0W25ld0luZGV4KytdID0gYnVmW29sZEluZGV4ICsgMV07CiAgICAgICAgZGVzdFtuZXdJbmRleCsrXSA9IGJ1ZltvbGRJbmRleCArIDJdOwogICAgICB9CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGNvcHlSZ2JhSW1hZ2Uoc3JjLCBkZXN0LCBhbHBoYTAxKSB7CiAgaWYgKGFscGhhMDEgPT09IDEpIHsKICAgIGNvbnN0IHNyYzMyID0gbmV3IFVpbnQzMkFycmF5KHNyYy5idWZmZXIpOwogICAgY29uc3QgZGVzdDMyID0gbmV3IFVpbnQzMkFycmF5KGRlc3QuYnVmZmVyKTsKICAgIGNvbnN0IHJnYk1hc2sgPSBGZWF0dXJlVGVzdC5pc0xpdHRsZUVuZGlhbiA/IDB4MDBmZmZmZmYgOiAweGZmZmZmZjAwOwogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gc3JjMzIubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBkZXN0MzJbaV0gfD0gc3JjMzJbaV0gJiByZ2JNYXNrOwogICAgfQogIH0gZWxzZSB7CiAgICBsZXQgaiA9IDA7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBzcmMubGVuZ3RoOyBpIDwgaWk7IGkgKz0gNCkgewogICAgICBkZXN0W2orK10gPSBzcmNbaV07CiAgICAgIGRlc3RbaisrXSA9IHNyY1tpICsgMV07CiAgICAgIGRlc3RbaisrXSA9IHNyY1tpICsgMl07CiAgICB9CiAgfQp9CmNsYXNzIENvbG9yU3BhY2UgewogIHN0YXRpYyAjcmdiQnVmID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KDMpOwogIGNvbnN0cnVjdG9yKG5hbWUsIG51bUNvbXBzKSB7CiAgICB0aGlzLm5hbWUgPSBuYW1lOwogICAgdGhpcy5udW1Db21wcyA9IG51bUNvbXBzOwogIH0KICBnZXRSZ2Ioc3JjLCBzcmNPZmZzZXQsIG91dHB1dCA9IG5ldyBVaW50OENsYW1wZWRBcnJheSgzKSkgewogICAgdGhpcy5nZXRSZ2JJdGVtKHNyYywgc3JjT2Zmc2V0LCBvdXRwdXQsIDApOwogICAgcmV0dXJuIG91dHB1dDsKICB9CiAgZ2V0UmdiSGV4KHNyYywgc3JjT2Zmc2V0KSB7CiAgICBjb25zdCBidWZmZXIgPSB0aGlzLmdldFJnYihzcmMsIHNyY09mZnNldCwgQ29sb3JTcGFjZS4jcmdiQnVmKTsKICAgIHJldHVybiBVdGlsLm1ha2VIZXhDb2xvcihidWZmZXJbMF0sIGJ1ZmZlclsxXSwgYnVmZmVyWzJdKTsKICB9CiAgZ2V0UmdiSXRlbShzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgdW5yZWFjaGFibGUoIlNob3VsZCBub3QgY2FsbCBDb2xvclNwYWNlLmdldFJnYkl0ZW0iKTsKICB9CiAgZ2V0UmdiQnVmZmVyKHNyYywgc3JjT2Zmc2V0LCBjb3VudCwgZGVzdCwgZGVzdE9mZnNldCwgYml0cywgYWxwaGEwMSkgewogICAgdW5yZWFjaGFibGUoIlNob3VsZCBub3QgY2FsbCBDb2xvclNwYWNlLmdldFJnYkJ1ZmZlciIpOwogIH0KICBnZXRPdXRwdXRMZW5ndGgoaW5wdXRMZW5ndGgsIGFscGhhMDEpIHsKICAgIHVucmVhY2hhYmxlKCJTaG91bGQgbm90IGNhbGwgQ29sb3JTcGFjZS5nZXRPdXRwdXRMZW5ndGgiKTsKICB9CiAgaXNQYXNzdGhyb3VnaChiaXRzKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGlzRGVmYXVsdERlY29kZShkZWNvZGVNYXAsIGJwYykgewogICAgcmV0dXJuIENvbG9yU3BhY2UuaXNEZWZhdWx0RGVjb2RlKGRlY29kZU1hcCwgdGhpcy5udW1Db21wcyk7CiAgfQogIGZpbGxSZ2IoZGVzdCwgb3JpZ2luYWxXaWR0aCwgb3JpZ2luYWxIZWlnaHQsIHdpZHRoLCBoZWlnaHQsIGFjdHVhbEhlaWdodCwgYnBjLCBjb21wcywgYWxwaGEwMSkgewogICAgY29uc3QgY291bnQgPSBvcmlnaW5hbFdpZHRoICogb3JpZ2luYWxIZWlnaHQ7CiAgICBsZXQgcmdiQnVmID0gbnVsbDsKICAgIGNvbnN0IG51bUNvbXBvbmVudENvbG9ycyA9IDEgPDwgYnBjOwogICAgY29uc3QgbmVlZHNSZXNpemluZyA9IG9yaWdpbmFsSGVpZ2h0ICE9PSBoZWlnaHQgfHwgb3JpZ2luYWxXaWR0aCAhPT0gd2lkdGg7CiAgICBpZiAodGhpcy5pc1Bhc3N0aHJvdWdoKGJwYykpIHsKICAgICAgcmdiQnVmID0gY29tcHM7CiAgICB9IGVsc2UgaWYgKHRoaXMubnVtQ29tcHMgPT09IDEgJiYgY291bnQgPiBudW1Db21wb25lbnRDb2xvcnMgJiYgdGhpcy5uYW1lICE9PSAiRGV2aWNlR3JheSIgJiYgdGhpcy5uYW1lICE9PSAiRGV2aWNlUkdCIikgewogICAgICBjb25zdCBhbGxDb2xvcnMgPSBicGMgPD0gOCA/IG5ldyBVaW50OEFycmF5KG51bUNvbXBvbmVudENvbG9ycykgOiBuZXcgVWludDE2QXJyYXkobnVtQ29tcG9uZW50Q29sb3JzKTsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1Db21wb25lbnRDb2xvcnM7IGkrKykgewogICAgICAgIGFsbENvbG9yc1tpXSA9IGk7CiAgICAgIH0KICAgICAgY29uc3QgY29sb3JNYXAgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkobnVtQ29tcG9uZW50Q29sb3JzICogMyk7CiAgICAgIHRoaXMuZ2V0UmdiQnVmZmVyKGFsbENvbG9ycywgMCwgbnVtQ29tcG9uZW50Q29sb3JzLCBjb2xvck1hcCwgMCwgYnBjLCAwKTsKICAgICAgaWYgKCFuZWVkc1Jlc2l6aW5nKSB7CiAgICAgICAgbGV0IGRlc3RQb3MgPSAwOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7ICsraSkgewogICAgICAgICAgY29uc3Qga2V5ID0gY29tcHNbaV0gKiAzOwogICAgICAgICAgZGVzdFtkZXN0UG9zKytdID0gY29sb3JNYXBba2V5XTsKICAgICAgICAgIGRlc3RbZGVzdFBvcysrXSA9IGNvbG9yTWFwW2tleSArIDFdOwogICAgICAgICAgZGVzdFtkZXN0UG9zKytdID0gY29sb3JNYXBba2V5ICsgMl07CiAgICAgICAgICBkZXN0UG9zICs9IGFscGhhMDE7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHJnYkJ1ZiA9IG5ldyBVaW50OEFycmF5KGNvdW50ICogMyk7CiAgICAgICAgbGV0IHJnYlBvcyA9IDA7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgKytpKSB7CiAgICAgICAgICBjb25zdCBrZXkgPSBjb21wc1tpXSAqIDM7CiAgICAgICAgICByZ2JCdWZbcmdiUG9zKytdID0gY29sb3JNYXBba2V5XTsKICAgICAgICAgIHJnYkJ1ZltyZ2JQb3MrK10gPSBjb2xvck1hcFtrZXkgKyAxXTsKICAgICAgICAgIHJnYkJ1ZltyZ2JQb3MrK10gPSBjb2xvck1hcFtrZXkgKyAyXTsKICAgICAgICB9CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoIW5lZWRzUmVzaXppbmcpIHsKICAgICAgdGhpcy5nZXRSZ2JCdWZmZXIoY29tcHMsIDAsIHdpZHRoICogYWN0dWFsSGVpZ2h0LCBkZXN0LCAwLCBicGMsIGFscGhhMDEpOwogICAgfSBlbHNlIHsKICAgICAgcmdiQnVmID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGNvdW50ICogMyk7CiAgICAgIHRoaXMuZ2V0UmdiQnVmZmVyKGNvbXBzLCAwLCBjb3VudCwgcmdiQnVmLCAwLCBicGMsIDApOwogICAgfQogICAgaWYgKHJnYkJ1ZikgewogICAgICBpZiAobmVlZHNSZXNpemluZykgewogICAgICAgIHJlc2l6ZVJnYkltYWdlKHJnYkJ1ZiwgZGVzdCwgb3JpZ2luYWxXaWR0aCwgb3JpZ2luYWxIZWlnaHQsIHdpZHRoLCBoZWlnaHQsIGFscGhhMDEpOwogICAgICB9IGVsc2UgewogICAgICAgIGxldCBkZXN0UG9zID0gMCwKICAgICAgICAgIHJnYlBvcyA9IDA7CiAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gd2lkdGggKiBhY3R1YWxIZWlnaHQ7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICBkZXN0W2Rlc3RQb3MrK10gPSByZ2JCdWZbcmdiUG9zKytdOwogICAgICAgICAgZGVzdFtkZXN0UG9zKytdID0gcmdiQnVmW3JnYlBvcysrXTsKICAgICAgICAgIGRlc3RbZGVzdFBvcysrXSA9IHJnYkJ1ZltyZ2JQb3MrK107CiAgICAgICAgICBkZXN0UG9zICs9IGFscGhhMDE7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQogIGdldCB1c2VzWmVyb1RvT25lUmFuZ2UoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJ1c2VzWmVyb1RvT25lUmFuZ2UiLCB0cnVlKTsKICB9CiAgc3RhdGljIGlzRGVmYXVsdERlY29kZShkZWNvZGUsIG51bUNvbXBzKSB7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGVjb2RlKSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmIChudW1Db21wcyAqIDIgIT09IGRlY29kZS5sZW5ndGgpIHsKICAgICAgd2FybigiVGhlIGRlY29kZSBtYXAgaXMgbm90IHRoZSBjb3JyZWN0IGxlbmd0aCIpOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGRlY29kZS5sZW5ndGg7IGkgPCBpaTsgaSArPSAyKSB7CiAgICAgIGlmIChkZWNvZGVbaV0gIT09IDAgfHwgZGVjb2RlW2kgKyAxXSAhPT0gMSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHRydWU7CiAgfQp9CmNsYXNzIEFsdGVybmF0ZUNTIGV4dGVuZHMgQ29sb3JTcGFjZSB7CiAgY29uc3RydWN0b3IobnVtQ29tcHMsIGJhc2UsIHRpbnRGbikgewogICAgc3VwZXIoIkFsdGVybmF0ZSIsIG51bUNvbXBzKTsKICAgIHRoaXMuYmFzZSA9IGJhc2U7CiAgICB0aGlzLnRpbnRGbiA9IHRpbnRGbjsKICAgIHRoaXMudG1wQnVmID0gbmV3IEZsb2F0MzJBcnJheShiYXNlLm51bUNvbXBzKTsKICB9CiAgZ2V0UmdiSXRlbShzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgY29uc3QgdG1wQnVmID0gdGhpcy50bXBCdWY7CiAgICB0aGlzLnRpbnRGbihzcmMsIHNyY09mZnNldCwgdG1wQnVmLCAwKTsKICAgIHRoaXMuYmFzZS5nZXRSZ2JJdGVtKHRtcEJ1ZiwgMCwgZGVzdCwgZGVzdE9mZnNldCk7CiAgfQogIGdldFJnYkJ1ZmZlcihzcmMsIHNyY09mZnNldCwgY291bnQsIGRlc3QsIGRlc3RPZmZzZXQsIGJpdHMsIGFscGhhMDEpIHsKICAgIGNvbnN0IHRpbnRGbiA9IHRoaXMudGludEZuOwogICAgY29uc3QgYmFzZSA9IHRoaXMuYmFzZTsKICAgIGNvbnN0IHNjYWxlID0gMSAvICgoMSA8PCBiaXRzKSAtIDEpOwogICAgY29uc3QgYmFzZU51bUNvbXBzID0gYmFzZS5udW1Db21wczsKICAgIGNvbnN0IHVzZXNaZXJvVG9PbmVSYW5nZSA9IGJhc2UudXNlc1plcm9Ub09uZVJhbmdlOwogICAgY29uc3QgaXNQYXNzdGhyb3VnaCA9IChiYXNlLmlzUGFzc3Rocm91Z2goOCkgfHwgIXVzZXNaZXJvVG9PbmVSYW5nZSkgJiYgYWxwaGEwMSA9PT0gMDsKICAgIGxldCBwb3MgPSBpc1Bhc3N0aHJvdWdoID8gZGVzdE9mZnNldCA6IDA7CiAgICBjb25zdCBiYXNlQnVmID0gaXNQYXNzdGhyb3VnaCA/IGRlc3QgOiBuZXcgVWludDhDbGFtcGVkQXJyYXkoYmFzZU51bUNvbXBzICogY291bnQpOwogICAgY29uc3QgbnVtQ29tcHMgPSB0aGlzLm51bUNvbXBzOwogICAgY29uc3Qgc2NhbGVkID0gbmV3IEZsb2F0MzJBcnJheShudW1Db21wcyk7CiAgICBjb25zdCB0aW50ZWQgPSBuZXcgRmxvYXQzMkFycmF5KGJhc2VOdW1Db21wcyk7CiAgICBsZXQgaSwgajsKICAgIGZvciAoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgIGZvciAoaiA9IDA7IGogPCBudW1Db21wczsgaisrKSB7CiAgICAgICAgc2NhbGVkW2pdID0gc3JjW3NyY09mZnNldCsrXSAqIHNjYWxlOwogICAgICB9CiAgICAgIHRpbnRGbihzY2FsZWQsIDAsIHRpbnRlZCwgMCk7CiAgICAgIGlmICh1c2VzWmVyb1RvT25lUmFuZ2UpIHsKICAgICAgICBmb3IgKGogPSAwOyBqIDwgYmFzZU51bUNvbXBzOyBqKyspIHsKICAgICAgICAgIGJhc2VCdWZbcG9zKytdID0gdGludGVkW2pdICogMjU1OwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBiYXNlLmdldFJnYkl0ZW0odGludGVkLCAwLCBiYXNlQnVmLCBwb3MpOwogICAgICAgIHBvcyArPSBiYXNlTnVtQ29tcHM7CiAgICAgIH0KICAgIH0KICAgIGlmICghaXNQYXNzdGhyb3VnaCkgewogICAgICBiYXNlLmdldFJnYkJ1ZmZlcihiYXNlQnVmLCAwLCBjb3VudCwgZGVzdCwgZGVzdE9mZnNldCwgOCwgYWxwaGEwMSk7CiAgICB9CiAgfQogIGdldE91dHB1dExlbmd0aChpbnB1dExlbmd0aCwgYWxwaGEwMSkgewogICAgcmV0dXJuIHRoaXMuYmFzZS5nZXRPdXRwdXRMZW5ndGgoaW5wdXRMZW5ndGggKiB0aGlzLmJhc2UubnVtQ29tcHMgLyB0aGlzLm51bUNvbXBzLCBhbHBoYTAxKTsKICB9Cn0KY2xhc3MgUGF0dGVybkNTIGV4dGVuZHMgQ29sb3JTcGFjZSB7CiAgY29uc3RydWN0b3IoYmFzZUNTKSB7CiAgICBzdXBlcigiUGF0dGVybiIsIG51bGwpOwogICAgdGhpcy5iYXNlID0gYmFzZUNTOwogIH0KICBpc0RlZmF1bHREZWNvZGUoZGVjb2RlTWFwLCBicGMpIHsKICAgIHVucmVhY2hhYmxlKCJTaG91bGQgbm90IGNhbGwgUGF0dGVybkNTLmlzRGVmYXVsdERlY29kZSIpOwogIH0KfQpjbGFzcyBJbmRleGVkQ1MgZXh0ZW5kcyBDb2xvclNwYWNlIHsKICBjb25zdHJ1Y3RvcihiYXNlLCBoaWdoVmFsLCBsb29rdXApIHsKICAgIHN1cGVyKCJJbmRleGVkIiwgMSk7CiAgICB0aGlzLmJhc2UgPSBiYXNlOwogICAgdGhpcy5oaWdoVmFsID0gaGlnaFZhbDsKICAgIGNvbnN0IGxlbmd0aCA9IGJhc2UubnVtQ29tcHMgKiAoaGlnaFZhbCArIDEpOwogICAgdGhpcy5sb29rdXAgPSBuZXcgVWludDhBcnJheShsZW5ndGgpOwogICAgaWYgKGxvb2t1cCBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgY29uc3QgYnl0ZXMgPSBsb29rdXAuZ2V0Qnl0ZXMobGVuZ3RoKTsKICAgICAgdGhpcy5sb29rdXAuc2V0KGJ5dGVzKTsKICAgIH0gZWxzZSBpZiAodHlwZW9mIGxvb2t1cCA9PT0gInN0cmluZyIpIHsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgIHRoaXMubG9va3VwW2ldID0gbG9va3VwLmNoYXJDb2RlQXQoaSkgJiAweGZmOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEluZGV4ZWRDUyAtIHVucmVjb2duaXplZCBsb29rdXAgdGFibGU6ICR7bG9va3VwfWApOwogICAgfQogIH0KICBnZXRSZ2JJdGVtKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICBjb25zdCB7CiAgICAgIGJhc2UsCiAgICAgIGhpZ2hWYWwsCiAgICAgIGxvb2t1cAogICAgfSA9IHRoaXM7CiAgICBjb25zdCBzdGFydCA9IE1hdGhDbGFtcChNYXRoLnJvdW5kKHNyY1tzcmNPZmZzZXRdKSwgMCwgaGlnaFZhbCkgKiBiYXNlLm51bUNvbXBzOwogICAgYmFzZS5nZXRSZ2JCdWZmZXIobG9va3VwLCBzdGFydCwgMSwgZGVzdCwgZGVzdE9mZnNldCwgOCwgMCk7CiAgfQogIGdldFJnYkJ1ZmZlcihzcmMsIHNyY09mZnNldCwgY291bnQsIGRlc3QsIGRlc3RPZmZzZXQsIGJpdHMsIGFscGhhMDEpIHsKICAgIGNvbnN0IHsKICAgICAgYmFzZSwKICAgICAgaGlnaFZhbCwKICAgICAgbG9va3VwCiAgICB9ID0gdGhpczsKICAgIGNvbnN0IHsKICAgICAgbnVtQ29tcHMKICAgIH0gPSBiYXNlOwogICAgY29uc3Qgb3V0cHV0RGVsdGEgPSBiYXNlLmdldE91dHB1dExlbmd0aChudW1Db21wcywgYWxwaGEwMSk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyArK2kpIHsKICAgICAgY29uc3QgbG9va3VwUG9zID0gTWF0aENsYW1wKE1hdGgucm91bmQoc3JjW3NyY09mZnNldCsrXSksIDAsIGhpZ2hWYWwpICogbnVtQ29tcHM7CiAgICAgIGJhc2UuZ2V0UmdiQnVmZmVyKGxvb2t1cCwgbG9va3VwUG9zLCAxLCBkZXN0LCBkZXN0T2Zmc2V0LCA4LCBhbHBoYTAxKTsKICAgICAgZGVzdE9mZnNldCArPSBvdXRwdXREZWx0YTsKICAgIH0KICB9CiAgZ2V0T3V0cHV0TGVuZ3RoKGlucHV0TGVuZ3RoLCBhbHBoYTAxKSB7CiAgICByZXR1cm4gdGhpcy5iYXNlLmdldE91dHB1dExlbmd0aChpbnB1dExlbmd0aCAqIHRoaXMuYmFzZS5udW1Db21wcywgYWxwaGEwMSk7CiAgfQogIGlzRGVmYXVsdERlY29kZShkZWNvZGVNYXAsIGJwYykgewogICAgaWYgKCFBcnJheS5pc0FycmF5KGRlY29kZU1hcCkpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBpZiAoZGVjb2RlTWFwLmxlbmd0aCAhPT0gMikgewogICAgICB3YXJuKCJEZWNvZGUgbWFwIGxlbmd0aCBpcyBub3QgY29ycmVjdCIpOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihicGMpIHx8IGJwYyA8IDEpIHsKICAgICAgd2FybigiQml0cyBwZXIgY29tcG9uZW50IGlzIG5vdCBjb3JyZWN0Iik7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgcmV0dXJuIGRlY29kZU1hcFswXSA9PT0gMCAmJiBkZWNvZGVNYXBbMV0gPT09ICgxIDw8IGJwYykgLSAxOwogIH0KfQpjbGFzcyBEZXZpY2VHcmF5Q1MgZXh0ZW5kcyBDb2xvclNwYWNlIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHN1cGVyKCJEZXZpY2VHcmF5IiwgMSk7CiAgfQogIGdldFJnYkl0ZW0oc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgIGNvbnN0IGMgPSBzcmNbc3JjT2Zmc2V0XSAqIDI1NTsKICAgIGRlc3RbZGVzdE9mZnNldF0gPSBkZXN0W2Rlc3RPZmZzZXQgKyAxXSA9IGRlc3RbZGVzdE9mZnNldCArIDJdID0gYzsKICB9CiAgZ2V0UmdiQnVmZmVyKHNyYywgc3JjT2Zmc2V0LCBjb3VudCwgZGVzdCwgZGVzdE9mZnNldCwgYml0cywgYWxwaGEwMSkgewogICAgY29uc3Qgc2NhbGUgPSAyNTUgLyAoKDEgPDwgYml0cykgLSAxKTsKICAgIGxldCBqID0gc3JjT2Zmc2V0LAogICAgICBxID0gZGVzdE9mZnNldDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7ICsraSkgewogICAgICBjb25zdCBjID0gc2NhbGUgKiBzcmNbaisrXTsKICAgICAgZGVzdFtxKytdID0gYzsKICAgICAgZGVzdFtxKytdID0gYzsKICAgICAgZGVzdFtxKytdID0gYzsKICAgICAgcSArPSBhbHBoYTAxOwogICAgfQogIH0KICBnZXRPdXRwdXRMZW5ndGgoaW5wdXRMZW5ndGgsIGFscGhhMDEpIHsKICAgIHJldHVybiBpbnB1dExlbmd0aCAqICgzICsgYWxwaGEwMSk7CiAgfQp9CmNsYXNzIERldmljZVJnYkNTIGV4dGVuZHMgQ29sb3JTcGFjZSB7CiAgY29uc3RydWN0b3IoKSB7CiAgICBzdXBlcigiRGV2aWNlUkdCIiwgMyk7CiAgfQogIGdldFJnYkl0ZW0oc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgIGRlc3RbZGVzdE9mZnNldF0gPSBzcmNbc3JjT2Zmc2V0XSAqIDI1NTsKICAgIGRlc3RbZGVzdE9mZnNldCArIDFdID0gc3JjW3NyY09mZnNldCArIDFdICogMjU1OwogICAgZGVzdFtkZXN0T2Zmc2V0ICsgMl0gPSBzcmNbc3JjT2Zmc2V0ICsgMl0gKiAyNTU7CiAgfQogIGdldFJnYkJ1ZmZlcihzcmMsIHNyY09mZnNldCwgY291bnQsIGRlc3QsIGRlc3RPZmZzZXQsIGJpdHMsIGFscGhhMDEpIHsKICAgIGlmIChiaXRzID09PSA4ICYmIGFscGhhMDEgPT09IDApIHsKICAgICAgZGVzdC5zZXQoc3JjLnN1YmFycmF5KHNyY09mZnNldCwgc3JjT2Zmc2V0ICsgY291bnQgKiAzKSwgZGVzdE9mZnNldCk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHNjYWxlID0gMjU1IC8gKCgxIDw8IGJpdHMpIC0gMSk7CiAgICBsZXQgaiA9IHNyY09mZnNldCwKICAgICAgcSA9IGRlc3RPZmZzZXQ7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyArK2kpIHsKICAgICAgZGVzdFtxKytdID0gc2NhbGUgKiBzcmNbaisrXTsKICAgICAgZGVzdFtxKytdID0gc2NhbGUgKiBzcmNbaisrXTsKICAgICAgZGVzdFtxKytdID0gc2NhbGUgKiBzcmNbaisrXTsKICAgICAgcSArPSBhbHBoYTAxOwogICAgfQogIH0KICBnZXRPdXRwdXRMZW5ndGgoaW5wdXRMZW5ndGgsIGFscGhhMDEpIHsKICAgIHJldHVybiBpbnB1dExlbmd0aCAqICgzICsgYWxwaGEwMSkgLyAzIHwgMDsKICB9CiAgaXNQYXNzdGhyb3VnaChiaXRzKSB7CiAgICByZXR1cm4gYml0cyA9PT0gODsKICB9Cn0KY2xhc3MgRGV2aWNlUmdiYUNTIGV4dGVuZHMgQ29sb3JTcGFjZSB7CiAgY29uc3RydWN0b3IoKSB7CiAgICBzdXBlcigiRGV2aWNlUkdCQSIsIDQpOwogIH0KICBnZXRPdXRwdXRMZW5ndGgoaW5wdXRMZW5ndGgsIF9hbHBoYTAxKSB7CiAgICByZXR1cm4gaW5wdXRMZW5ndGggKiA0OwogIH0KICBpc1Bhc3N0aHJvdWdoKGJpdHMpIHsKICAgIHJldHVybiBiaXRzID09PSA4OwogIH0KICBmaWxsUmdiKGRlc3QsIG9yaWdpbmFsV2lkdGgsIG9yaWdpbmFsSGVpZ2h0LCB3aWR0aCwgaGVpZ2h0LCBhY3R1YWxIZWlnaHQsIGJwYywgY29tcHMsIGFscGhhMDEpIHsKICAgIGlmIChvcmlnaW5hbEhlaWdodCAhPT0gaGVpZ2h0IHx8IG9yaWdpbmFsV2lkdGggIT09IHdpZHRoKSB7CiAgICAgIHJlc2l6ZVJnYmFJbWFnZShjb21wcywgZGVzdCwgb3JpZ2luYWxXaWR0aCwgb3JpZ2luYWxIZWlnaHQsIHdpZHRoLCBoZWlnaHQsIGFscGhhMDEpOwogICAgfSBlbHNlIHsKICAgICAgY29weVJnYmFJbWFnZShjb21wcywgZGVzdCwgYWxwaGEwMSk7CiAgICB9CiAgfQp9CmNsYXNzIERldmljZUNteWtDUyBleHRlbmRzIENvbG9yU3BhY2UgewogIGNvbnN0cnVjdG9yKCkgewogICAgc3VwZXIoIkRldmljZUNNWUsiLCA0KTsKICB9CiAgI3RvUmdiKHNyYywgc3JjT2Zmc2V0LCBzcmNTY2FsZSwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgY29uc3QgYyA9IHNyY1tzcmNPZmZzZXRdICogc3JjU2NhbGU7CiAgICBjb25zdCBtID0gc3JjW3NyY09mZnNldCArIDFdICogc3JjU2NhbGU7CiAgICBjb25zdCB5ID0gc3JjW3NyY09mZnNldCArIDJdICogc3JjU2NhbGU7CiAgICBjb25zdCBrID0gc3JjW3NyY09mZnNldCArIDNdICogc3JjU2NhbGU7CiAgICBkZXN0W2Rlc3RPZmZzZXRdID0gMjU1ICsgYyAqICgtNC4zODczMzIzODQ2MDk5ODggKiBjICsgNTQuNDg2MTUxOTQxODkxNzYgKiBtICsgMTguODIyOTA1MDIxNjUzMDIgKiB5ICsgMjEyLjI1NjYyNDUxNjM5NTg1ICogayArIC0yODUuMjMzMTAyNjEzNzAwNCkgKyBtICogKDEuNzE0OTc2MzQ3NzM2MjEzNCAqIG0gLSA1LjYwOTY3MzY5MDQwNDczMTUgKiB5ICsgLTE3Ljg3Mzg3MDg2MTQxNTQ0NCAqIGsgLSA1LjQ5NzAwNjQyNzE5NjM2NikgKyB5ICogKC0yLjUyMTczNDAxMzE2ODMwMzMgKiB5IC0gMjEuMjQ4OTIzMzM3MzUzMDczICogayArIDE3LjUxMTkyNzA4NDE4MTMpICsgayAqICgtMjEuODYxMjIxNDc0NjM2MDUgKiBrIC0gMTg5LjQ4MTgwODM1OTIyNzQ3KTsKICAgIGRlc3RbZGVzdE9mZnNldCArIDFdID0gMjU1ICsgYyAqICg4Ljg0MTA0MTQyMjAzNjE0OSAqIGMgKyA2MC4xMTgwMjcwNDU1OTczNjYgKiBtICsgNi44NzE0MjU1OTIwNDkwMDcgKiB5ICsgMzEuMTU5MTAwMTMwMDU1OTIyICogayArIC03OS4yOTcwODQ0ODE2NTQ4KSArIG0gKiAoLTE1LjMxMDM2MTMwNjk2NzgxNyAqIG0gKyAxNy41NzUyNTEyNjExMDk0ODIgKiB5ICsgMTMxLjM1MjUwOTEyNDkzOTc2ICogayAtIDE5MC45NDUzMzAyNTg4OTUxKSArIHkgKiAoNC40NDQzMzkxMDI4NTI3MzkgKiB5ICsgOS44NjMyODYxNDkzNDA1ICogayAtIDI0Ljg2NzQxNTgyNTU1ODc4KSArIGsgKiAoLTIwLjczNzMyNTQ3MTE4MTAzNCAqIGsgLSAxODcuODA0NTM3MDk3MTk1NzgpOwogICAgZGVzdFtkZXN0T2Zmc2V0ICsgMl0gPSAyNTUgKyBjICogKDAuODg0MjUyMjQzMDAwMzI5NiAqIGMgKyA4LjA3ODY3NzUwMzExMjkyOCAqIG0gKyAzMC44OTk3ODMwOTcwMzcyOSAqIHkgLSAwLjIzODgzMjM4Njg5MTc4OTM0ICogayArIC0xNC4xODM1NzY3OTk2NzMyODYpICsgbSAqICgxMC40OTU5MzI3MzQzMjA3MiAqIG0gKyA2My4wMjM3ODQ5NDc1NDA1MiAqIHkgKyA1MC42MDY5NTc2NTYzNjA3MzQgKiBrIC0gMTEyLjIzODg0MjUzNzE5MjQ4KSArIHkgKiAoMC4wMzI5NjA0MTExNDg3MzIxNyAqIHkgKyAxMTUuNjAzODQ0NDk2NDY2NDEgKiBrICsgLTE5My41ODIwOTM1Njg2MTUwNSkgKyBrICogKC0yMi4zMzgxNjgwNzMwOTg4NiAqIGsgLSAxODAuMTI2MTM5NzQ3MDgzNjcpOwogIH0KICBnZXRSZ2JJdGVtKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICB0aGlzLiN0b1JnYihzcmMsIHNyY09mZnNldCwgMSwgZGVzdCwgZGVzdE9mZnNldCk7CiAgfQogIGdldFJnYkJ1ZmZlcihzcmMsIHNyY09mZnNldCwgY291bnQsIGRlc3QsIGRlc3RPZmZzZXQsIGJpdHMsIGFscGhhMDEpIHsKICAgIGNvbnN0IHNjYWxlID0gMSAvICgoMSA8PCBiaXRzKSAtIDEpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgIHRoaXMuI3RvUmdiKHNyYywgc3JjT2Zmc2V0LCBzY2FsZSwgZGVzdCwgZGVzdE9mZnNldCk7CiAgICAgIHNyY09mZnNldCArPSA0OwogICAgICBkZXN0T2Zmc2V0ICs9IDMgKyBhbHBoYTAxOwogICAgfQogIH0KICBnZXRPdXRwdXRMZW5ndGgoaW5wdXRMZW5ndGgsIGFscGhhMDEpIHsKICAgIHJldHVybiBpbnB1dExlbmd0aCAvIDQgKiAoMyArIGFscGhhMDEpIHwgMDsKICB9Cn0KY2xhc3MgQ2FsR3JheUNTIGV4dGVuZHMgQ29sb3JTcGFjZSB7CiAgY29uc3RydWN0b3Iod2hpdGVQb2ludCwgYmxhY2tQb2ludCwgZ2FtbWEpIHsKICAgIHN1cGVyKCJDYWxHcmF5IiwgMSk7CiAgICBpZiAoIXdoaXRlUG9pbnQpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJXaGl0ZVBvaW50IG1pc3NpbmcgLSByZXF1aXJlZCBmb3IgY29sb3Igc3BhY2UgQ2FsR3JheSIpOwogICAgfQogICAgW3RoaXMuWFcsIHRoaXMuWVcsIHRoaXMuWlddID0gd2hpdGVQb2ludDsKICAgIFt0aGlzLlhCLCB0aGlzLllCLCB0aGlzLlpCXSA9IGJsYWNrUG9pbnQgfHwgWzAsIDAsIDBdOwogICAgdGhpcy5HID0gZ2FtbWEgfHwgMTsKICAgIGlmICh0aGlzLlhXIDwgMCB8fCB0aGlzLlpXIDwgMCB8fCB0aGlzLllXICE9PSAxKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBXaGl0ZVBvaW50IGNvbXBvbmVudHMgZm9yICR7dGhpcy5uYW1lfSwgbm8gZmFsbGJhY2sgYXZhaWxhYmxlYCk7CiAgICB9CiAgICBpZiAodGhpcy5YQiA8IDAgfHwgdGhpcy5ZQiA8IDAgfHwgdGhpcy5aQiA8IDApIHsKICAgICAgaW5mbyhgSW52YWxpZCBCbGFja1BvaW50IGZvciAke3RoaXMubmFtZX0sIGZhbGxpbmcgYmFjayB0byBkZWZhdWx0LmApOwogICAgICB0aGlzLlhCID0gdGhpcy5ZQiA9IHRoaXMuWkIgPSAwOwogICAgfQogICAgaWYgKHRoaXMuWEIgIT09IDAgfHwgdGhpcy5ZQiAhPT0gMCB8fCB0aGlzLlpCICE9PSAwKSB7CiAgICAgIHdhcm4oYCR7dGhpcy5uYW1lfSwgQmxhY2tQb2ludDogWEI6ICR7dGhpcy5YQn0sIFlCOiAke3RoaXMuWUJ9LCBgICsgYFpCOiAke3RoaXMuWkJ9LCBvbmx5IGRlZmF1bHQgdmFsdWVzIGFyZSBzdXBwb3J0ZWQuYCk7CiAgICB9CiAgICBpZiAodGhpcy5HIDwgMSkgewogICAgICBpbmZvKGBJbnZhbGlkIEdhbW1hOiAke3RoaXMuR30gZm9yICR7dGhpcy5uYW1lfSwgZmFsbGluZyBiYWNrIHRvIGRlZmF1bHQuYCk7CiAgICAgIHRoaXMuRyA9IDE7CiAgICB9CiAgfQogICN0b1JnYihzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCwgc2NhbGUpIHsKICAgIGNvbnN0IEEgPSBzcmNbc3JjT2Zmc2V0XSAqIHNjYWxlOwogICAgY29uc3QgQUcgPSBBICoqIHRoaXMuRzsKICAgIGNvbnN0IEwgPSB0aGlzLllXICogQUc7CiAgICBjb25zdCB2YWwgPSBNYXRoLm1heCgyOTUuOCAqIEwgKiogMC4zMzMzMzMzMzMzMzMzMzMzIC0gNDAuOCwgMCk7CiAgICBkZXN0W2Rlc3RPZmZzZXRdID0gdmFsOwogICAgZGVzdFtkZXN0T2Zmc2V0ICsgMV0gPSB2YWw7CiAgICBkZXN0W2Rlc3RPZmZzZXQgKyAyXSA9IHZhbDsKICB9CiAgZ2V0UmdiSXRlbShzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgdGhpcy4jdG9SZ2Ioc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQsIDEpOwogIH0KICBnZXRSZ2JCdWZmZXIoc3JjLCBzcmNPZmZzZXQsIGNvdW50LCBkZXN0LCBkZXN0T2Zmc2V0LCBiaXRzLCBhbHBoYTAxKSB7CiAgICBjb25zdCBzY2FsZSA9IDEgLyAoKDEgPDwgYml0cykgLSAxKTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7ICsraSkgewogICAgICB0aGlzLiN0b1JnYihzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCwgc2NhbGUpOwogICAgICBzcmNPZmZzZXQgKz0gMTsKICAgICAgZGVzdE9mZnNldCArPSAzICsgYWxwaGEwMTsKICAgIH0KICB9CiAgZ2V0T3V0cHV0TGVuZ3RoKGlucHV0TGVuZ3RoLCBhbHBoYTAxKSB7CiAgICByZXR1cm4gaW5wdXRMZW5ndGggKiAoMyArIGFscGhhMDEpOwogIH0KfQpjbGFzcyBDYWxSR0JDUyBleHRlbmRzIENvbG9yU3BhY2UgewogIHN0YXRpYyAjQlJBREZPUkRfU0NBTEVfTUFUUklYID0gbmV3IEZsb2F0MzJBcnJheShbMC44OTUxLCAwLjI2NjQsIC0wLjE2MTQsIC0wLjc1MDIsIDEuNzEzNSwgMC4wMzY3LCAwLjAzODksIC0wLjA2ODUsIDEuMDI5Nl0pOwogIHN0YXRpYyAjQlJBREZPUkRfU0NBTEVfSU5WRVJTRV9NQVRSSVggPSBuZXcgRmxvYXQzMkFycmF5KFswLjk4Njk5MjksIC0wLjE0NzA1NDMsIDAuMTU5OTYyNywgMC40MzIzMDUzLCAwLjUxODM2MDMsIDAuMDQ5MjkxMiwgLTAuMDA4NTI4NywgMC4wNDAwNDI4LCAwLjk2ODQ4NjddKTsKICBzdGF0aWMgI1NSR0JfRDY1X1hZWl9UT19SR0JfTUFUUklYID0gbmV3IEZsb2F0MzJBcnJheShbMy4yNDA0NTQyLCAtMS41MzcxMzg1LCAtMC40OTg1MzE0LCAtMC45NjkyNjYwLCAxLjg3NjAxMDgsIDAuMDQxNTU2MCwgMC4wNTU2NDM0LCAtMC4yMDQwMjU5LCAxLjA1NzIyNTJdKTsKICBzdGF0aWMgI0ZMQVRfV0hJVEVQT0lOVF9NQVRSSVggPSBuZXcgRmxvYXQzMkFycmF5KFsxLCAxLCAxXSk7CiAgc3RhdGljICN0ZW1wTm9ybWFsaXplTWF0cml4ID0gbmV3IEZsb2F0MzJBcnJheSgzKTsKICBzdGF0aWMgI3RlbXBDb252ZXJ0TWF0cml4MSA9IG5ldyBGbG9hdDMyQXJyYXkoMyk7CiAgc3RhdGljICN0ZW1wQ29udmVydE1hdHJpeDIgPSBuZXcgRmxvYXQzMkFycmF5KDMpOwogIHN0YXRpYyAjREVDT0RFX0xfQ09OU1RBTlQgPSAoKDggKyAxNikgLyAxMTYpICoqIDMgLyA4LjA7CiAgY29uc3RydWN0b3Iod2hpdGVQb2ludCwgYmxhY2tQb2ludCwgZ2FtbWEsIG1hdHJpeCkgewogICAgc3VwZXIoIkNhbFJHQiIsIDMpOwogICAgaWYgKCF3aGl0ZVBvaW50KSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiV2hpdGVQb2ludCBtaXNzaW5nIC0gcmVxdWlyZWQgZm9yIGNvbG9yIHNwYWNlIENhbFJHQiIpOwogICAgfQogICAgY29uc3QgW1hXLCBZVywgWlddID0gdGhpcy53aGl0ZVBvaW50ID0gd2hpdGVQb2ludDsKICAgIGNvbnN0IFtYQiwgWUIsIFpCXSA9IHRoaXMuYmxhY2tQb2ludCA9IGJsYWNrUG9pbnQgfHwgbmV3IEZsb2F0MzJBcnJheSgzKTsKICAgIFt0aGlzLkdSLCB0aGlzLkdHLCB0aGlzLkdCXSA9IGdhbW1hIHx8IG5ldyBGbG9hdDMyQXJyYXkoWzEsIDEsIDFdKTsKICAgIFt0aGlzLk1YQSwgdGhpcy5NWUEsIHRoaXMuTVpBLCB0aGlzLk1YQiwgdGhpcy5NWUIsIHRoaXMuTVpCLCB0aGlzLk1YQywgdGhpcy5NWUMsIHRoaXMuTVpDXSA9IG1hdHJpeCB8fCBuZXcgRmxvYXQzMkFycmF5KFsxLCAwLCAwLCAwLCAxLCAwLCAwLCAwLCAxXSk7CiAgICBpZiAoWFcgPCAwIHx8IFpXIDwgMCB8fCBZVyAhPT0gMSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgV2hpdGVQb2ludCBjb21wb25lbnRzIGZvciAke3RoaXMubmFtZX0sIG5vIGZhbGxiYWNrIGF2YWlsYWJsZWApOwogICAgfQogICAgaWYgKFhCIDwgMCB8fCBZQiA8IDAgfHwgWkIgPCAwKSB7CiAgICAgIGluZm8oYEludmFsaWQgQmxhY2tQb2ludCBmb3IgJHt0aGlzLm5hbWV9IFske1hCfSwgJHtZQn0sICR7WkJ9XSwgYCArICJmYWxsaW5nIGJhY2sgdG8gZGVmYXVsdC4iKTsKICAgICAgdGhpcy5ibGFja1BvaW50ID0gbmV3IEZsb2F0MzJBcnJheSgzKTsKICAgIH0KICAgIGlmICh0aGlzLkdSIDwgMCB8fCB0aGlzLkdHIDwgMCB8fCB0aGlzLkdCIDwgMCkgewogICAgICBpbmZvKGBJbnZhbGlkIEdhbW1hIFske3RoaXMuR1J9LCAke3RoaXMuR0d9LCAke3RoaXMuR0J9XSBmb3IgYCArIGAke3RoaXMubmFtZX0sIGZhbGxpbmcgYmFjayB0byBkZWZhdWx0LmApOwogICAgICB0aGlzLkdSID0gdGhpcy5HRyA9IHRoaXMuR0IgPSAxOwogICAgfQogIH0KICAjbWF0cml4UHJvZHVjdChhLCBiLCByZXN1bHQpIHsKICAgIHJlc3VsdFswXSA9IGFbMF0gKiBiWzBdICsgYVsxXSAqIGJbMV0gKyBhWzJdICogYlsyXTsKICAgIHJlc3VsdFsxXSA9IGFbM10gKiBiWzBdICsgYVs0XSAqIGJbMV0gKyBhWzVdICogYlsyXTsKICAgIHJlc3VsdFsyXSA9IGFbNl0gKiBiWzBdICsgYVs3XSAqIGJbMV0gKyBhWzhdICogYlsyXTsKICB9CiAgI3RvRmxhdChzb3VyY2VXaGl0ZVBvaW50LCBMTVMsIHJlc3VsdCkgewogICAgcmVzdWx0WzBdID0gTE1TWzBdICogMSAvIHNvdXJjZVdoaXRlUG9pbnRbMF07CiAgICByZXN1bHRbMV0gPSBMTVNbMV0gKiAxIC8gc291cmNlV2hpdGVQb2ludFsxXTsKICAgIHJlc3VsdFsyXSA9IExNU1syXSAqIDEgLyBzb3VyY2VXaGl0ZVBvaW50WzJdOwogIH0KICAjdG9ENjUoc291cmNlV2hpdGVQb2ludCwgTE1TLCByZXN1bHQpIHsKICAgIGNvbnN0IEQ2NVggPSAwLjk1MDQ3OwogICAgY29uc3QgRDY1WSA9IDE7CiAgICBjb25zdCBENjVaID0gMS4wODg4MzsKICAgIHJlc3VsdFswXSA9IExNU1swXSAqIEQ2NVggLyBzb3VyY2VXaGl0ZVBvaW50WzBdOwogICAgcmVzdWx0WzFdID0gTE1TWzFdICogRDY1WSAvIHNvdXJjZVdoaXRlUG9pbnRbMV07CiAgICByZXN1bHRbMl0gPSBMTVNbMl0gKiBENjVaIC8gc291cmNlV2hpdGVQb2ludFsyXTsKICB9CiAgI3NSR0JUcmFuc2ZlckZ1bmN0aW9uKGNvbG9yKSB7CiAgICBpZiAoY29sb3IgPD0gMC4wMDMxMzA4KSB7CiAgICAgIHJldHVybiBNYXRoQ2xhbXAoMTIuOTIgKiBjb2xvciwgMCwgMSk7CiAgICB9CiAgICBpZiAoY29sb3IgPj0gMC45OTU1NDUyNSkgewogICAgICByZXR1cm4gMTsKICAgIH0KICAgIHJldHVybiBNYXRoQ2xhbXAoKDEgKyAwLjA1NSkgKiBjb2xvciAqKiAoMSAvIDIuNCkgLSAwLjA1NSwgMCwgMSk7CiAgfQogICNkZWNvZGVMKEwpIHsKICAgIGlmIChMIDwgMCkgewogICAgICByZXR1cm4gLXRoaXMuI2RlY29kZUwoLUwpOwogICAgfQogICAgaWYgKEwgPiA4LjApIHsKICAgICAgcmV0dXJuICgoTCArIDE2KSAvIDExNikgKiogMzsKICAgIH0KICAgIHJldHVybiBMICogQ2FsUkdCQ1MuI0RFQ09ERV9MX0NPTlNUQU5UOwogIH0KICAjY29tcGVuc2F0ZUJsYWNrUG9pbnQoc291cmNlQmxhY2tQb2ludCwgWFlaX0ZsYXQsIHJlc3VsdCkgewogICAgaWYgKHNvdXJjZUJsYWNrUG9pbnRbMF0gPT09IDAgJiYgc291cmNlQmxhY2tQb2ludFsxXSA9PT0gMCAmJiBzb3VyY2VCbGFja1BvaW50WzJdID09PSAwKSB7CiAgICAgIHJlc3VsdFswXSA9IFhZWl9GbGF0WzBdOwogICAgICByZXN1bHRbMV0gPSBYWVpfRmxhdFsxXTsKICAgICAgcmVzdWx0WzJdID0gWFlaX0ZsYXRbMl07CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHplcm9EZWNvZGVMID0gdGhpcy4jZGVjb2RlTCgwKTsKICAgIGNvbnN0IFhfRFNUID0gemVyb0RlY29kZUw7CiAgICBjb25zdCBYX1NSQyA9IHRoaXMuI2RlY29kZUwoc291cmNlQmxhY2tQb2ludFswXSk7CiAgICBjb25zdCBZX0RTVCA9IHplcm9EZWNvZGVMOwogICAgY29uc3QgWV9TUkMgPSB0aGlzLiNkZWNvZGVMKHNvdXJjZUJsYWNrUG9pbnRbMV0pOwogICAgY29uc3QgWl9EU1QgPSB6ZXJvRGVjb2RlTDsKICAgIGNvbnN0IFpfU1JDID0gdGhpcy4jZGVjb2RlTChzb3VyY2VCbGFja1BvaW50WzJdKTsKICAgIGNvbnN0IFhfU2NhbGUgPSAoMSAtIFhfRFNUKSAvICgxIC0gWF9TUkMpOwogICAgY29uc3QgWF9PZmZzZXQgPSAxIC0gWF9TY2FsZTsKICAgIGNvbnN0IFlfU2NhbGUgPSAoMSAtIFlfRFNUKSAvICgxIC0gWV9TUkMpOwogICAgY29uc3QgWV9PZmZzZXQgPSAxIC0gWV9TY2FsZTsKICAgIGNvbnN0IFpfU2NhbGUgPSAoMSAtIFpfRFNUKSAvICgxIC0gWl9TUkMpOwogICAgY29uc3QgWl9PZmZzZXQgPSAxIC0gWl9TY2FsZTsKICAgIHJlc3VsdFswXSA9IFhZWl9GbGF0WzBdICogWF9TY2FsZSArIFhfT2Zmc2V0OwogICAgcmVzdWx0WzFdID0gWFlaX0ZsYXRbMV0gKiBZX1NjYWxlICsgWV9PZmZzZXQ7CiAgICByZXN1bHRbMl0gPSBYWVpfRmxhdFsyXSAqIFpfU2NhbGUgKyBaX09mZnNldDsKICB9CiAgI25vcm1hbGl6ZVdoaXRlUG9pbnRUb0ZsYXQoc291cmNlV2hpdGVQb2ludCwgWFlaX0luLCByZXN1bHQpIHsKICAgIGlmIChzb3VyY2VXaGl0ZVBvaW50WzBdID09PSAxICYmIHNvdXJjZVdoaXRlUG9pbnRbMl0gPT09IDEpIHsKICAgICAgcmVzdWx0WzBdID0gWFlaX0luWzBdOwogICAgICByZXN1bHRbMV0gPSBYWVpfSW5bMV07CiAgICAgIHJlc3VsdFsyXSA9IFhZWl9JblsyXTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgTE1TID0gcmVzdWx0OwogICAgdGhpcy4jbWF0cml4UHJvZHVjdChDYWxSR0JDUy4jQlJBREZPUkRfU0NBTEVfTUFUUklYLCBYWVpfSW4sIExNUyk7CiAgICBjb25zdCBMTVNfRmxhdCA9IENhbFJHQkNTLiN0ZW1wTm9ybWFsaXplTWF0cml4OwogICAgdGhpcy4jdG9GbGF0KHNvdXJjZVdoaXRlUG9pbnQsIExNUywgTE1TX0ZsYXQpOwogICAgdGhpcy4jbWF0cml4UHJvZHVjdChDYWxSR0JDUy4jQlJBREZPUkRfU0NBTEVfSU5WRVJTRV9NQVRSSVgsIExNU19GbGF0LCByZXN1bHQpOwogIH0KICAjbm9ybWFsaXplV2hpdGVQb2ludFRvRDY1KHNvdXJjZVdoaXRlUG9pbnQsIFhZWl9JbiwgcmVzdWx0KSB7CiAgICBjb25zdCBMTVMgPSByZXN1bHQ7CiAgICB0aGlzLiNtYXRyaXhQcm9kdWN0KENhbFJHQkNTLiNCUkFERk9SRF9TQ0FMRV9NQVRSSVgsIFhZWl9JbiwgTE1TKTsKICAgIGNvbnN0IExNU19ENjUgPSBDYWxSR0JDUy4jdGVtcE5vcm1hbGl6ZU1hdHJpeDsKICAgIHRoaXMuI3RvRDY1KHNvdXJjZVdoaXRlUG9pbnQsIExNUywgTE1TX0Q2NSk7CiAgICB0aGlzLiNtYXRyaXhQcm9kdWN0KENhbFJHQkNTLiNCUkFERk9SRF9TQ0FMRV9JTlZFUlNFX01BVFJJWCwgTE1TX0Q2NSwgcmVzdWx0KTsKICB9CiAgI3RvUmdiKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0LCBzY2FsZSkgewogICAgY29uc3QgQSA9IE1hdGhDbGFtcChzcmNbc3JjT2Zmc2V0XSAqIHNjYWxlLCAwLCAxKTsKICAgIGNvbnN0IEIgPSBNYXRoQ2xhbXAoc3JjW3NyY09mZnNldCArIDFdICogc2NhbGUsIDAsIDEpOwogICAgY29uc3QgQyA9IE1hdGhDbGFtcChzcmNbc3JjT2Zmc2V0ICsgMl0gKiBzY2FsZSwgMCwgMSk7CiAgICBjb25zdCBBR1IgPSBBID09PSAxID8gMSA6IEEgKiogdGhpcy5HUjsKICAgIGNvbnN0IEJHRyA9IEIgPT09IDEgPyAxIDogQiAqKiB0aGlzLkdHOwogICAgY29uc3QgQ0dCID0gQyA9PT0gMSA/IDEgOiBDICoqIHRoaXMuR0I7CiAgICBjb25zdCBYID0gdGhpcy5NWEEgKiBBR1IgKyB0aGlzLk1YQiAqIEJHRyArIHRoaXMuTVhDICogQ0dCOwogICAgY29uc3QgWSA9IHRoaXMuTVlBICogQUdSICsgdGhpcy5NWUIgKiBCR0cgKyB0aGlzLk1ZQyAqIENHQjsKICAgIGNvbnN0IFogPSB0aGlzLk1aQSAqIEFHUiArIHRoaXMuTVpCICogQkdHICsgdGhpcy5NWkMgKiBDR0I7CiAgICBjb25zdCBYWVogPSBDYWxSR0JDUy4jdGVtcENvbnZlcnRNYXRyaXgxOwogICAgWFlaWzBdID0gWDsKICAgIFhZWlsxXSA9IFk7CiAgICBYWVpbMl0gPSBaOwogICAgY29uc3QgWFlaX0ZsYXQgPSBDYWxSR0JDUy4jdGVtcENvbnZlcnRNYXRyaXgyOwogICAgdGhpcy4jbm9ybWFsaXplV2hpdGVQb2ludFRvRmxhdCh0aGlzLndoaXRlUG9pbnQsIFhZWiwgWFlaX0ZsYXQpOwogICAgY29uc3QgWFlaX0JsYWNrID0gQ2FsUkdCQ1MuI3RlbXBDb252ZXJ0TWF0cml4MTsKICAgIHRoaXMuI2NvbXBlbnNhdGVCbGFja1BvaW50KHRoaXMuYmxhY2tQb2ludCwgWFlaX0ZsYXQsIFhZWl9CbGFjayk7CiAgICBjb25zdCBYWVpfRDY1ID0gQ2FsUkdCQ1MuI3RlbXBDb252ZXJ0TWF0cml4MjsKICAgIHRoaXMuI25vcm1hbGl6ZVdoaXRlUG9pbnRUb0Q2NShDYWxSR0JDUy4jRkxBVF9XSElURVBPSU5UX01BVFJJWCwgWFlaX0JsYWNrLCBYWVpfRDY1KTsKICAgIGNvbnN0IFNSR0IgPSBDYWxSR0JDUy4jdGVtcENvbnZlcnRNYXRyaXgxOwogICAgdGhpcy4jbWF0cml4UHJvZHVjdChDYWxSR0JDUy4jU1JHQl9ENjVfWFlaX1RPX1JHQl9NQVRSSVgsIFhZWl9ENjUsIFNSR0IpOwogICAgZGVzdFtkZXN0T2Zmc2V0XSA9IHRoaXMuI3NSR0JUcmFuc2ZlckZ1bmN0aW9uKFNSR0JbMF0pICogMjU1OwogICAgZGVzdFtkZXN0T2Zmc2V0ICsgMV0gPSB0aGlzLiNzUkdCVHJhbnNmZXJGdW5jdGlvbihTUkdCWzFdKSAqIDI1NTsKICAgIGRlc3RbZGVzdE9mZnNldCArIDJdID0gdGhpcy4jc1JHQlRyYW5zZmVyRnVuY3Rpb24oU1JHQlsyXSkgKiAyNTU7CiAgfQogIGdldFJnYkl0ZW0oc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgIHRoaXMuI3RvUmdiKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0LCAxKTsKICB9CiAgZ2V0UmdiQnVmZmVyKHNyYywgc3JjT2Zmc2V0LCBjb3VudCwgZGVzdCwgZGVzdE9mZnNldCwgYml0cywgYWxwaGEwMSkgewogICAgY29uc3Qgc2NhbGUgPSAxIC8gKCgxIDw8IGJpdHMpIC0gMSk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyArK2kpIHsKICAgICAgdGhpcy4jdG9SZ2Ioc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQsIHNjYWxlKTsKICAgICAgc3JjT2Zmc2V0ICs9IDM7CiAgICAgIGRlc3RPZmZzZXQgKz0gMyArIGFscGhhMDE7CiAgICB9CiAgfQogIGdldE91dHB1dExlbmd0aChpbnB1dExlbmd0aCwgYWxwaGEwMSkgewogICAgcmV0dXJuIGlucHV0TGVuZ3RoICogKDMgKyBhbHBoYTAxKSAvIDMgfCAwOwogIH0KfQpjbGFzcyBMYWJDUyBleHRlbmRzIENvbG9yU3BhY2UgewogIGNvbnN0cnVjdG9yKHdoaXRlUG9pbnQsIGJsYWNrUG9pbnQsIHJhbmdlKSB7CiAgICBzdXBlcigiTGFiIiwgMyk7CiAgICBpZiAoIXdoaXRlUG9pbnQpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJXaGl0ZVBvaW50IG1pc3NpbmcgLSByZXF1aXJlZCBmb3IgY29sb3Igc3BhY2UgTGFiIik7CiAgICB9CiAgICBbdGhpcy5YVywgdGhpcy5ZVywgdGhpcy5aV10gPSB3aGl0ZVBvaW50OwogICAgW3RoaXMuYW1pbiwgdGhpcy5hbWF4LCB0aGlzLmJtaW4sIHRoaXMuYm1heF0gPSByYW5nZSB8fCBbLTEwMCwgMTAwLCAtMTAwLCAxMDBdOwogICAgW3RoaXMuWEIsIHRoaXMuWUIsIHRoaXMuWkJdID0gYmxhY2tQb2ludCB8fCBbMCwgMCwgMF07CiAgICBpZiAodGhpcy5YVyA8IDAgfHwgdGhpcy5aVyA8IDAgfHwgdGhpcy5ZVyAhPT0gMSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgV2hpdGVQb2ludCBjb21wb25lbnRzLCBubyBmYWxsYmFjayBhdmFpbGFibGUiKTsKICAgIH0KICAgIGlmICh0aGlzLlhCIDwgMCB8fCB0aGlzLllCIDwgMCB8fCB0aGlzLlpCIDwgMCkgewogICAgICBpbmZvKCJJbnZhbGlkIEJsYWNrUG9pbnQsIGZhbGxpbmcgYmFjayB0byBkZWZhdWx0Iik7CiAgICAgIHRoaXMuWEIgPSB0aGlzLllCID0gdGhpcy5aQiA9IDA7CiAgICB9CiAgICBpZiAodGhpcy5hbWluID4gdGhpcy5hbWF4IHx8IHRoaXMuYm1pbiA+IHRoaXMuYm1heCkgewogICAgICBpbmZvKCJJbnZhbGlkIFJhbmdlLCBmYWxsaW5nIGJhY2sgdG8gZGVmYXVsdHMiKTsKICAgICAgdGhpcy5hbWluID0gLTEwMDsKICAgICAgdGhpcy5hbWF4ID0gMTAwOwogICAgICB0aGlzLmJtaW4gPSAtMTAwOwogICAgICB0aGlzLmJtYXggPSAxMDA7CiAgICB9CiAgfQogICNmbl9nKHgpIHsKICAgIHJldHVybiB4ID49IDYgLyAyOSA/IHggKiogMyA6IDEwOCAvIDg0MSAqICh4IC0gNCAvIDI5KTsKICB9CiAgI2RlY29kZSh2YWx1ZSwgaGlnaDEsIGxvdzIsIGhpZ2gyKSB7CiAgICByZXR1cm4gbG93MiArIHZhbHVlICogKGhpZ2gyIC0gbG93MikgLyBoaWdoMTsKICB9CiAgI3RvUmdiKHNyYywgc3JjT2Zmc2V0LCBtYXhWYWwsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgIGxldCBMcyA9IHNyY1tzcmNPZmZzZXRdOwogICAgbGV0IGFzID0gc3JjW3NyY09mZnNldCArIDFdOwogICAgbGV0IGJzID0gc3JjW3NyY09mZnNldCArIDJdOwogICAgaWYgKG1heFZhbCAhPT0gZmFsc2UpIHsKICAgICAgTHMgPSB0aGlzLiNkZWNvZGUoTHMsIG1heFZhbCwgMCwgMTAwKTsKICAgICAgYXMgPSB0aGlzLiNkZWNvZGUoYXMsIG1heFZhbCwgdGhpcy5hbWluLCB0aGlzLmFtYXgpOwogICAgICBicyA9IHRoaXMuI2RlY29kZShicywgbWF4VmFsLCB0aGlzLmJtaW4sIHRoaXMuYm1heCk7CiAgICB9CiAgICBpZiAoYXMgPiB0aGlzLmFtYXgpIHsKICAgICAgYXMgPSB0aGlzLmFtYXg7CiAgICB9IGVsc2UgaWYgKGFzIDwgdGhpcy5hbWluKSB7CiAgICAgIGFzID0gdGhpcy5hbWluOwogICAgfQogICAgaWYgKGJzID4gdGhpcy5ibWF4KSB7CiAgICAgIGJzID0gdGhpcy5ibWF4OwogICAgfSBlbHNlIGlmIChicyA8IHRoaXMuYm1pbikgewogICAgICBicyA9IHRoaXMuYm1pbjsKICAgIH0KICAgIGNvbnN0IE0gPSAoTHMgKyAxNikgLyAxMTY7CiAgICBjb25zdCBMID0gTSArIGFzIC8gNTAwOwogICAgY29uc3QgTiA9IE0gLSBicyAvIDIwMDsKICAgIGNvbnN0IFggPSB0aGlzLlhXICogdGhpcy4jZm5fZyhMKTsKICAgIGNvbnN0IFkgPSB0aGlzLllXICogdGhpcy4jZm5fZyhNKTsKICAgIGNvbnN0IFogPSB0aGlzLlpXICogdGhpcy4jZm5fZyhOKTsKICAgIGxldCByLCBnLCBiOwogICAgaWYgKHRoaXMuWlcgPCAxKSB7CiAgICAgIHIgPSBYICogMy4xMzM5ICsgWSAqIC0xLjYxNyArIFogKiAtMC40OTA2OwogICAgICBnID0gWCAqIC0wLjk3ODUgKyBZICogMS45MTYgKyBaICogMC4wMzMzOwogICAgICBiID0gWCAqIDAuMDcyICsgWSAqIC0wLjIyOSArIFogKiAxLjQwNTc7CiAgICB9IGVsc2UgewogICAgICByID0gWCAqIDMuMjQwNiArIFkgKiAtMS41MzcyICsgWiAqIC0wLjQ5ODY7CiAgICAgIGcgPSBYICogLTAuOTY4OSArIFkgKiAxLjg3NTggKyBaICogMC4wNDE1OwogICAgICBiID0gWCAqIDAuMDU1NyArIFkgKiAtMC4yMDQgKyBaICogMS4wNTc7CiAgICB9CiAgICBkZXN0W2Rlc3RPZmZzZXRdID0gTWF0aC5zcXJ0KHIpICogMjU1OwogICAgZGVzdFtkZXN0T2Zmc2V0ICsgMV0gPSBNYXRoLnNxcnQoZykgKiAyNTU7CiAgICBkZXN0W2Rlc3RPZmZzZXQgKyAyXSA9IE1hdGguc3FydChiKSAqIDI1NTsKICB9CiAgZ2V0UmdiSXRlbShzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgdGhpcy4jdG9SZ2Ioc3JjLCBzcmNPZmZzZXQsIGZhbHNlLCBkZXN0LCBkZXN0T2Zmc2V0KTsKICB9CiAgZ2V0UmdiQnVmZmVyKHNyYywgc3JjT2Zmc2V0LCBjb3VudCwgZGVzdCwgZGVzdE9mZnNldCwgYml0cywgYWxwaGEwMSkgewogICAgY29uc3QgbWF4VmFsID0gKDEgPDwgYml0cykgLSAxOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgIHRoaXMuI3RvUmdiKHNyYywgc3JjT2Zmc2V0LCBtYXhWYWwsIGRlc3QsIGRlc3RPZmZzZXQpOwogICAgICBzcmNPZmZzZXQgKz0gMzsKICAgICAgZGVzdE9mZnNldCArPSAzICsgYWxwaGEwMTsKICAgIH0KICB9CiAgZ2V0T3V0cHV0TGVuZ3RoKGlucHV0TGVuZ3RoLCBhbHBoYTAxKSB7CiAgICByZXR1cm4gaW5wdXRMZW5ndGggKiAoMyArIGFscGhhMDEpIC8gMyB8IDA7CiAgfQogIGlzRGVmYXVsdERlY29kZShkZWNvZGVNYXAsIGJwYykgewogICAgcmV0dXJuIHRydWU7CiAgfQogIGdldCB1c2VzWmVyb1RvT25lUmFuZ2UoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJ1c2VzWmVyb1RvT25lUmFuZ2UiLCBmYWxzZSk7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9pY2NfY29sb3JzcGFjZS5qcwoKCgoKCgoKCgoKCgpmdW5jdGlvbiBmZXRjaFN5bmModXJsKSB7CiAgY29uc3QgeGhyID0gbmV3IFhNTEh0dHBSZXF1ZXN0KCk7CiAgeGhyLm9wZW4oIkdFVCIsIHVybCwgZmFsc2UpOwogIHhoci5yZXNwb25zZVR5cGUgPSAiYXJyYXlidWZmZXIiOwogIHhoci5zZW5kKG51bGwpOwogIHJldHVybiB4aHIucmVzcG9uc2U7Cn0KY2xhc3MgSWNjQ29sb3JTcGFjZSBleHRlbmRzIENvbG9yU3BhY2UgewogICN0cmFuc2Zvcm1lcjsKICAjY29udmVydFBpeGVsOwogIHN0YXRpYyAjdXNlV2FzbSA9IHRydWU7CiAgc3RhdGljICN3YXNtVXJsID0gbnVsbDsKICBzdGF0aWMgI2ZpbmFsaXplciA9IG51bGw7CiAgY29uc3RydWN0b3IoaWNjUHJvZmlsZSwgbmFtZSwgbnVtQ29tcHMpIHsKICAgIGlmICghSWNjQ29sb3JTcGFjZS5pc1VzYWJsZSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIk5vIElDQyBjb2xvciBzcGFjZSBzdXBwb3J0Iik7CiAgICB9CiAgICBzdXBlcihuYW1lLCBudW1Db21wcyk7CiAgICBsZXQgaW5UeXBlOwogICAgc3dpdGNoIChudW1Db21wcykgewogICAgICBjYXNlIDE6CiAgICAgICAgaW5UeXBlID0gRGF0YVR5cGUuR3JheTg7CiAgICAgICAgdGhpcy4jY29udmVydFBpeGVsID0gKHNyYywgc3JjT2Zmc2V0LCBjc3MpID0+IHFjbXNfY29udmVydF9vbmUodGhpcy4jdHJhbnNmb3JtZXIsIHNyY1tzcmNPZmZzZXRdICogMjU1LCBjc3MpOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDM6CiAgICAgICAgaW5UeXBlID0gRGF0YVR5cGUuUkdCODsKICAgICAgICB0aGlzLiNjb252ZXJ0UGl4ZWwgPSAoc3JjLCBzcmNPZmZzZXQsIGNzcykgPT4gcWNtc19jb252ZXJ0X3RocmVlKHRoaXMuI3RyYW5zZm9ybWVyLCBzcmNbc3JjT2Zmc2V0XSAqIDI1NSwgc3JjW3NyY09mZnNldCArIDFdICogMjU1LCBzcmNbc3JjT2Zmc2V0ICsgMl0gKiAyNTUsIGNzcyk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgNDoKICAgICAgICBpblR5cGUgPSBEYXRhVHlwZS5DTVlLOwogICAgICAgIHRoaXMuI2NvbnZlcnRQaXhlbCA9IChzcmMsIHNyY09mZnNldCwgY3NzKSA9PiBxY21zX2NvbnZlcnRfZm91cih0aGlzLiN0cmFuc2Zvcm1lciwgc3JjW3NyY09mZnNldF0gKiAyNTUsIHNyY1tzcmNPZmZzZXQgKyAxXSAqIDI1NSwgc3JjW3NyY09mZnNldCArIDJdICogMjU1LCBzcmNbc3JjT2Zmc2V0ICsgM10gKiAyNTUsIGNzcyk7CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCBudW1iZXIgb2YgY29tcG9uZW50czogJHtudW1Db21wc31gKTsKICAgIH0KICAgIHRoaXMuI3RyYW5zZm9ybWVyID0gcWNtc190cmFuc2Zvcm1lcl9mcm9tX21lbW9yeShpY2NQcm9maWxlLCBpblR5cGUsIEludGVudC5QZXJjZXB0dWFsKTsKICAgIGlmICghdGhpcy4jdHJhbnNmb3JtZXIpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJGYWlsZWQgdG8gY3JlYXRlIElDQyBjb2xvciBzcGFjZSIpOwogICAgfQogICAgSWNjQ29sb3JTcGFjZS4jZmluYWxpemVyIHx8PSBuZXcgRmluYWxpemF0aW9uUmVnaXN0cnkodHJhbnNmb3JtZXIgPT4gewogICAgICBxY21zX2Ryb3BfdHJhbnNmb3JtZXIodHJhbnNmb3JtZXIpOwogICAgfSk7CiAgICBJY2NDb2xvclNwYWNlLiNmaW5hbGl6ZXIucmVnaXN0ZXIodGhpcywgdGhpcy4jdHJhbnNmb3JtZXIpOwogIH0KICBnZXRSZ2JIZXgoc3JjLCBzcmNPZmZzZXQpIHsKICAgIHRoaXMuI2NvbnZlcnRQaXhlbChzcmMsIHNyY09mZnNldCwgdHJ1ZSk7CiAgICByZXR1cm4gUUNNUy5fY3NzQ29sb3I7CiAgfQogIGdldFJnYkl0ZW0oc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgIFFDTVMuX2Rlc3RCdWZmZXIgPSBkZXN0OwogICAgUUNNUy5fZGVzdE9mZnNldCA9IGRlc3RPZmZzZXQ7CiAgICBRQ01TLl9kZXN0TGVuZ3RoID0gMzsKICAgIHRoaXMuI2NvbnZlcnRQaXhlbChzcmMsIHNyY09mZnNldCwgZmFsc2UpOwogICAgUUNNUy5fZGVzdEJ1ZmZlciA9IG51bGw7CiAgfQogIGdldFJnYkJ1ZmZlcihzcmMsIHNyY09mZnNldCwgY291bnQsIGRlc3QsIGRlc3RPZmZzZXQsIGJpdHMsIGFscGhhMDEpIHsKICAgIHNyYyA9IHNyYy5zdWJhcnJheShzcmNPZmZzZXQsIHNyY09mZnNldCArIGNvdW50ICogdGhpcy5udW1Db21wcyk7CiAgICBpZiAoYml0cyAhPT0gOCkgewogICAgICBjb25zdCBzY2FsZSA9IDI1NSAvICgoMSA8PCBiaXRzKSAtIDEpOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBzcmMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIHNyY1tpXSAqPSBzY2FsZTsKICAgICAgfQogICAgfQogICAgUUNNUy5fbXVzdEFkZEFscGhhID0gYWxwaGEwMSAmJiBkZXN0LmJ1ZmZlciA9PT0gc3JjLmJ1ZmZlcjsKICAgIFFDTVMuX2Rlc3RCdWZmZXIgPSBkZXN0OwogICAgUUNNUy5fZGVzdE9mZnNldCA9IGRlc3RPZmZzZXQ7CiAgICBRQ01TLl9kZXN0TGVuZ3RoID0gY291bnQgKiAoMyArIGFscGhhMDEpOwogICAgcWNtc19jb252ZXJ0X2FycmF5KHRoaXMuI3RyYW5zZm9ybWVyLCBzcmMpOwogICAgUUNNUy5fbXVzdEFkZEFscGhhID0gZmFsc2U7CiAgICBRQ01TLl9kZXN0QnVmZmVyID0gbnVsbDsKICB9CiAgZ2V0T3V0cHV0TGVuZ3RoKGlucHV0TGVuZ3RoLCBhbHBoYTAxKSB7CiAgICByZXR1cm4gaW5wdXRMZW5ndGggLyB0aGlzLm51bUNvbXBzICogKDMgKyBhbHBoYTAxKSB8IDA7CiAgfQogIHN0YXRpYyBzZXRPcHRpb25zKHsKICAgIHVzZVdhc20sCiAgICB1c2VXb3JrZXJGZXRjaCwKICAgIHdhc21VcmwKICB9KSB7CiAgICBpZiAoIXVzZVdvcmtlckZldGNoKSB7CiAgICAgIHRoaXMuI3VzZVdhc20gPSBmYWxzZTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy4jdXNlV2FzbSA9IHVzZVdhc207CiAgICB0aGlzLiN3YXNtVXJsID0gd2FzbVVybDsKICB9CiAgc3RhdGljIGdldCBpc1VzYWJsZSgpIHsKICAgIGxldCBpc1VzYWJsZSA9IGZhbHNlOwogICAgaWYgKHRoaXMuI3VzZVdhc20pIHsKICAgICAgaWYgKHRoaXMuI3dhc21VcmwpIHsKICAgICAgICB0cnkgewogICAgICAgICAgdGhpcy5fbW9kdWxlID0gaW5pdFN5bmMoewogICAgICAgICAgICBtb2R1bGU6IGZldGNoU3luYyhgJHt0aGlzLiN3YXNtVXJsfXFjbXNfYmcud2FzbWApCiAgICAgICAgICB9KTsKICAgICAgICAgIGlzVXNhYmxlID0gISF0aGlzLl9tb2R1bGU7CiAgICAgICAgICBRQ01TLl9tZW1vcnkgPSB0aGlzLl9tb2R1bGUubWVtb3J5OwogICAgICAgICAgUUNNUy5fbWFrZUhleENvbG9yID0gVXRpbC5tYWtlSGV4Q29sb3I7CiAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgd2FybihgSUNDQmFzZWQgY29sb3Igc3BhY2U6ICIke2V9Ii5gKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgd2FybigiTm8gSUNDIGNvbG9yIHNwYWNlIHN1cHBvcnQgZHVlIHRvIG1pc3NpbmcgYHdhc21VcmxgIEFQSSBvcHRpb24iKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiaXNVc2FibGUiLCBpc1VzYWJsZSk7CiAgfQp9CmNsYXNzIENteWtJQ0NCYXNlZENTIGV4dGVuZHMgSWNjQ29sb3JTcGFjZSB7CiAgc3RhdGljICNpY2NVcmw7CiAgY29uc3RydWN0b3IoKSB7CiAgICBjb25zdCBpY2NQcm9maWxlID0gbmV3IFVpbnQ4QXJyYXkoZmV0Y2hTeW5jKGAke0NteWtJQ0NCYXNlZENTLiNpY2NVcmx9Q0dBVFMwMDFDb21wYXQtdjItbWljcm8uaWNjYCkpOwogICAgc3VwZXIoaWNjUHJvZmlsZSwgIkRldmljZUNNWUsiLCA0KTsKICB9CiAgc3RhdGljIHNldE9wdGlvbnMoewogICAgaWNjVXJsCiAgfSkgewogICAgdGhpcy4jaWNjVXJsID0gaWNjVXJsOwogIH0KICBzdGF0aWMgZ2V0IGlzVXNhYmxlKCkgewogICAgbGV0IGlzVXNhYmxlID0gZmFsc2U7CiAgICBpZiAoSWNjQ29sb3JTcGFjZS5pc1VzYWJsZSkgewogICAgICBpZiAodGhpcy4jaWNjVXJsKSB7CiAgICAgICAgaXNVc2FibGUgPSB0cnVlOwogICAgICB9IGVsc2UgewogICAgICAgIHdhcm4oIk5vIENNWUsgSUNDIHByb2ZpbGUgc3VwcG9ydCBkdWUgdG8gbWlzc2luZyBgaWNjVXJsYCBBUEkgb3B0aW9uIik7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgImlzVXNhYmxlIiwgaXNVc2FibGUpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvc3RyZWFtLmpzCgoKCgoKCgoKCgpjbGFzcyBTdHJlYW0gZXh0ZW5kcyBCYXNlU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihhcnJheUJ1ZmZlciwgc3RhcnQsIGxlbmd0aCwgZGljdCkgewogICAgc3VwZXIoKTsKICAgIHRoaXMuYnl0ZXMgPSBhcnJheUJ1ZmZlciBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkgPyBhcnJheUJ1ZmZlciA6IG5ldyBVaW50OEFycmF5KGFycmF5QnVmZmVyKTsKICAgIHRoaXMuc3RhcnQgPSBzdGFydCB8fCAwOwogICAgdGhpcy5wb3MgPSB0aGlzLnN0YXJ0OwogICAgdGhpcy5lbmQgPSBzdGFydCArIGxlbmd0aCB8fCB0aGlzLmJ5dGVzLmxlbmd0aDsKICAgIHRoaXMuZGljdCA9IGRpY3Q7CiAgfQogIGdldCBsZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5lbmQgLSB0aGlzLnN0YXJ0OwogIH0KICBnZXQgaXNFbXB0eSgpIHsKICAgIHJldHVybiB0aGlzLmxlbmd0aCA9PT0gMDsKICB9CiAgZ2V0Qnl0ZSgpIHsKICAgIGlmICh0aGlzLnBvcyA+PSB0aGlzLmVuZCkgewogICAgICByZXR1cm4gLTE7CiAgICB9CiAgICByZXR1cm4gdGhpcy5ieXRlc1t0aGlzLnBvcysrXTsKICB9CiAgZ2V0Qnl0ZXMobGVuZ3RoKSB7CiAgICBjb25zdCBieXRlcyA9IHRoaXMuYnl0ZXM7CiAgICBjb25zdCBwb3MgPSB0aGlzLnBvczsKICAgIGNvbnN0IHN0ckVuZCA9IHRoaXMuZW5kOwogICAgaWYgKCFsZW5ndGgpIHsKICAgICAgcmV0dXJuIGJ5dGVzLnN1YmFycmF5KHBvcywgc3RyRW5kKTsKICAgIH0KICAgIGxldCBlbmQgPSBwb3MgKyBsZW5ndGg7CiAgICBpZiAoZW5kID4gc3RyRW5kKSB7CiAgICAgIGVuZCA9IHN0ckVuZDsKICAgIH0KICAgIHRoaXMucG9zID0gZW5kOwogICAgcmV0dXJuIGJ5dGVzLnN1YmFycmF5KHBvcywgZW5kKTsKICB9CiAgZ2V0Qnl0ZVJhbmdlKGJlZ2luLCBlbmQpIHsKICAgIGlmIChiZWdpbiA8IDApIHsKICAgICAgYmVnaW4gPSAwOwogICAgfQogICAgaWYgKGVuZCA+IHRoaXMuZW5kKSB7CiAgICAgIGVuZCA9IHRoaXMuZW5kOwogICAgfQogICAgcmV0dXJuIHRoaXMuYnl0ZXMuc3ViYXJyYXkoYmVnaW4sIGVuZCk7CiAgfQogIHJlc2V0KCkgewogICAgdGhpcy5wb3MgPSB0aGlzLnN0YXJ0OwogIH0KICBtb3ZlU3RhcnQoKSB7CiAgICB0aGlzLnN0YXJ0ID0gdGhpcy5wb3M7CiAgfQogIG1ha2VTdWJTdHJlYW0oc3RhcnQsIGxlbmd0aCwgZGljdCA9IG51bGwpIHsKICAgIHJldHVybiBuZXcgU3RyZWFtKHRoaXMuYnl0ZXMuYnVmZmVyLCBzdGFydCwgbGVuZ3RoLCBkaWN0KTsKICB9Cn0KY2xhc3MgU3RyaW5nU3RyZWFtIGV4dGVuZHMgU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihzdHIpIHsKICAgIHN1cGVyKHN0cmluZ1RvQnl0ZXMoc3RyKSk7CiAgfQp9CmNsYXNzIE51bGxTdHJlYW0gZXh0ZW5kcyBTdHJlYW0gewogIGNvbnN0cnVjdG9yKCkgewogICAgc3VwZXIobmV3IFVpbnQ4QXJyYXkoMCkpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvY2h1bmtlZF9zdHJlYW0uanMKCgoKCgoKCgoKCgoKCgoKCgoKCgpjbGFzcyBDaHVua2VkU3RyZWFtIGV4dGVuZHMgU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihsZW5ndGgsIGNodW5rU2l6ZSwgbWFuYWdlcikgewogICAgc3VwZXIobmV3IFVpbnQ4QXJyYXkobGVuZ3RoKSwgMCwgbGVuZ3RoLCBudWxsKTsKICAgIHRoaXMuY2h1bmtTaXplID0gY2h1bmtTaXplOwogICAgdGhpcy5fbG9hZGVkQ2h1bmtzID0gbmV3IFNldCgpOwogICAgdGhpcy5udW1DaHVua3MgPSBNYXRoLmNlaWwobGVuZ3RoIC8gY2h1bmtTaXplKTsKICAgIHRoaXMubWFuYWdlciA9IG1hbmFnZXI7CiAgICB0aGlzLnByb2dyZXNzaXZlRGF0YUxlbmd0aCA9IDA7CiAgICB0aGlzLmxhc3RTdWNjZXNzZnVsRW5zdXJlQnl0ZUNodW5rID0gLTE7CiAgfQogIGdldE1pc3NpbmdDaHVua3MoKSB7CiAgICBjb25zdCBjaHVua3MgPSBbXTsKICAgIGZvciAobGV0IGNodW5rID0gMCwgbiA9IHRoaXMubnVtQ2h1bmtzOyBjaHVuayA8IG47ICsrY2h1bmspIHsKICAgICAgaWYgKCF0aGlzLl9sb2FkZWRDaHVua3MuaGFzKGNodW5rKSkgewogICAgICAgIGNodW5rcy5wdXNoKGNodW5rKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGNodW5rczsKICB9CiAgZ2V0IG51bUNodW5rc0xvYWRlZCgpIHsKICAgIHJldHVybiB0aGlzLl9sb2FkZWRDaHVua3Muc2l6ZTsKICB9CiAgZ2V0IGlzRGF0YUxvYWRlZCgpIHsKICAgIHJldHVybiB0aGlzLm51bUNodW5rc0xvYWRlZCA9PT0gdGhpcy5udW1DaHVua3M7CiAgfQogIG9uUmVjZWl2ZURhdGEoYmVnaW4sIGNodW5rKSB7CiAgICBjb25zdCBjaHVua1NpemUgPSB0aGlzLmNodW5rU2l6ZTsKICAgIGlmIChiZWdpbiAlIGNodW5rU2l6ZSAhPT0gMCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoYEJhZCBiZWdpbiBvZmZzZXQ6ICR7YmVnaW59YCk7CiAgICB9CiAgICBjb25zdCBlbmQgPSBiZWdpbiArIGNodW5rLmJ5dGVMZW5ndGg7CiAgICBpZiAoZW5kICUgY2h1bmtTaXplICE9PSAwICYmIGVuZCAhPT0gdGhpcy5ieXRlcy5sZW5ndGgpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKGBCYWQgZW5kIG9mZnNldDogJHtlbmR9YCk7CiAgICB9CiAgICB0aGlzLmJ5dGVzLnNldChuZXcgVWludDhBcnJheShjaHVuayksIGJlZ2luKTsKICAgIGNvbnN0IGJlZ2luQ2h1bmsgPSBNYXRoLmZsb29yKGJlZ2luIC8gY2h1bmtTaXplKTsKICAgIGNvbnN0IGVuZENodW5rID0gTWF0aC5mbG9vcigoZW5kIC0gMSkgLyBjaHVua1NpemUpICsgMTsKICAgIGZvciAobGV0IGN1ckNodW5rID0gYmVnaW5DaHVuazsgY3VyQ2h1bmsgPCBlbmRDaHVuazsgKytjdXJDaHVuaykgewogICAgICB0aGlzLl9sb2FkZWRDaHVua3MuYWRkKGN1ckNodW5rKTsKICAgIH0KICB9CiAgb25SZWNlaXZlUHJvZ3Jlc3NpdmVEYXRhKGRhdGEpIHsKICAgIGxldCBwb3NpdGlvbiA9IHRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoOwogICAgY29uc3QgYmVnaW5DaHVuayA9IE1hdGguZmxvb3IocG9zaXRpb24gLyB0aGlzLmNodW5rU2l6ZSk7CiAgICB0aGlzLmJ5dGVzLnNldChuZXcgVWludDhBcnJheShkYXRhKSwgcG9zaXRpb24pOwogICAgcG9zaXRpb24gKz0gZGF0YS5ieXRlTGVuZ3RoOwogICAgdGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGggPSBwb3NpdGlvbjsKICAgIGNvbnN0IGVuZENodW5rID0gcG9zaXRpb24gPj0gdGhpcy5lbmQgPyB0aGlzLm51bUNodW5rcyA6IE1hdGguZmxvb3IocG9zaXRpb24gLyB0aGlzLmNodW5rU2l6ZSk7CiAgICBmb3IgKGxldCBjdXJDaHVuayA9IGJlZ2luQ2h1bms7IGN1ckNodW5rIDwgZW5kQ2h1bms7ICsrY3VyQ2h1bmspIHsKICAgICAgdGhpcy5fbG9hZGVkQ2h1bmtzLmFkZChjdXJDaHVuayk7CiAgICB9CiAgfQogIGVuc3VyZUJ5dGUocG9zKSB7CiAgICBpZiAocG9zIDwgdGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGgpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgY2h1bmsgPSBNYXRoLmZsb29yKHBvcyAvIHRoaXMuY2h1bmtTaXplKTsKICAgIGlmIChjaHVuayA+IHRoaXMubnVtQ2h1bmtzKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmIChjaHVuayA9PT0gdGhpcy5sYXN0U3VjY2Vzc2Z1bEVuc3VyZUJ5dGVDaHVuaykgewogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoIXRoaXMuX2xvYWRlZENodW5rcy5oYXMoY2h1bmspKSB7CiAgICAgIHRocm93IG5ldyBNaXNzaW5nRGF0YUV4Y2VwdGlvbihwb3MsIHBvcyArIDEpOwogICAgfQogICAgdGhpcy5sYXN0U3VjY2Vzc2Z1bEVuc3VyZUJ5dGVDaHVuayA9IGNodW5rOwogIH0KICBlbnN1cmVSYW5nZShiZWdpbiwgZW5kKSB7CiAgICBpZiAoYmVnaW4gPj0gZW5kKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmIChlbmQgPD0gdGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGgpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgYmVnaW5DaHVuayA9IE1hdGguZmxvb3IoYmVnaW4gLyB0aGlzLmNodW5rU2l6ZSk7CiAgICBpZiAoYmVnaW5DaHVuayA+IHRoaXMubnVtQ2h1bmtzKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGVuZENodW5rID0gTWF0aC5taW4oTWF0aC5mbG9vcigoZW5kIC0gMSkgLyB0aGlzLmNodW5rU2l6ZSkgKyAxLCB0aGlzLm51bUNodW5rcyk7CiAgICBmb3IgKGxldCBjaHVuayA9IGJlZ2luQ2h1bms7IGNodW5rIDwgZW5kQ2h1bms7ICsrY2h1bmspIHsKICAgICAgaWYgKCF0aGlzLl9sb2FkZWRDaHVua3MuaGFzKGNodW5rKSkgewogICAgICAgIHRocm93IG5ldyBNaXNzaW5nRGF0YUV4Y2VwdGlvbihiZWdpbiwgZW5kKTsKICAgICAgfQogICAgfQogIH0KICBuZXh0RW1wdHlDaHVuayhiZWdpbkNodW5rKSB7CiAgICBjb25zdCBudW1DaHVua3MgPSB0aGlzLm51bUNodW5rczsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtQ2h1bmtzOyArK2kpIHsKICAgICAgY29uc3QgY2h1bmsgPSAoYmVnaW5DaHVuayArIGkpICUgbnVtQ2h1bmtzOwogICAgICBpZiAoIXRoaXMuX2xvYWRlZENodW5rcy5oYXMoY2h1bmspKSB7CiAgICAgICAgcmV0dXJuIGNodW5rOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgaGFzQ2h1bmsoY2h1bmspIHsKICAgIHJldHVybiB0aGlzLl9sb2FkZWRDaHVua3MuaGFzKGNodW5rKTsKICB9CiAgZ2V0Qnl0ZSgpIHsKICAgIGNvbnN0IHBvcyA9IHRoaXMucG9zOwogICAgaWYgKHBvcyA+PSB0aGlzLmVuZCkgewogICAgICByZXR1cm4gLTE7CiAgICB9CiAgICBpZiAocG9zID49IHRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoKSB7CiAgICAgIHRoaXMuZW5zdXJlQnl0ZShwb3MpOwogICAgfQogICAgcmV0dXJuIHRoaXMuYnl0ZXNbdGhpcy5wb3MrK107CiAgfQogIGdldEJ5dGVzKGxlbmd0aCkgewogICAgY29uc3QgYnl0ZXMgPSB0aGlzLmJ5dGVzOwogICAgY29uc3QgcG9zID0gdGhpcy5wb3M7CiAgICBjb25zdCBzdHJFbmQgPSB0aGlzLmVuZDsKICAgIGlmICghbGVuZ3RoKSB7CiAgICAgIGlmIChzdHJFbmQgPiB0aGlzLnByb2dyZXNzaXZlRGF0YUxlbmd0aCkgewogICAgICAgIHRoaXMuZW5zdXJlUmFuZ2UocG9zLCBzdHJFbmQpOwogICAgICB9CiAgICAgIHJldHVybiBieXRlcy5zdWJhcnJheShwb3MsIHN0ckVuZCk7CiAgICB9CiAgICBsZXQgZW5kID0gcG9zICsgbGVuZ3RoOwogICAgaWYgKGVuZCA+IHN0ckVuZCkgewogICAgICBlbmQgPSBzdHJFbmQ7CiAgICB9CiAgICBpZiAoZW5kID4gdGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGgpIHsKICAgICAgdGhpcy5lbnN1cmVSYW5nZShwb3MsIGVuZCk7CiAgICB9CiAgICB0aGlzLnBvcyA9IGVuZDsKICAgIHJldHVybiBieXRlcy5zdWJhcnJheShwb3MsIGVuZCk7CiAgfQogIGdldEJ5dGVSYW5nZShiZWdpbiwgZW5kKSB7CiAgICBpZiAoYmVnaW4gPCAwKSB7CiAgICAgIGJlZ2luID0gMDsKICAgIH0KICAgIGlmIChlbmQgPiB0aGlzLmVuZCkgewogICAgICBlbmQgPSB0aGlzLmVuZDsKICAgIH0KICAgIGlmIChlbmQgPiB0aGlzLnByb2dyZXNzaXZlRGF0YUxlbmd0aCkgewogICAgICB0aGlzLmVuc3VyZVJhbmdlKGJlZ2luLCBlbmQpOwogICAgfQogICAgcmV0dXJuIHRoaXMuYnl0ZXMuc3ViYXJyYXkoYmVnaW4sIGVuZCk7CiAgfQogIG1ha2VTdWJTdHJlYW0oc3RhcnQsIGxlbmd0aCwgZGljdCA9IG51bGwpIHsKICAgIGlmIChsZW5ndGgpIHsKICAgICAgaWYgKHN0YXJ0ICsgbGVuZ3RoID4gdGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGgpIHsKICAgICAgICB0aGlzLmVuc3VyZVJhbmdlKHN0YXJ0LCBzdGFydCArIGxlbmd0aCk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoc3RhcnQgPj0gdGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGgpIHsKICAgICAgdGhpcy5lbnN1cmVCeXRlKHN0YXJ0KTsKICAgIH0KICAgIGZ1bmN0aW9uIENodW5rZWRTdHJlYW1TdWJzdHJlYW0oKSB7fQogICAgQ2h1bmtlZFN0cmVhbVN1YnN0cmVhbS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHRoaXMpOwogICAgQ2h1bmtlZFN0cmVhbVN1YnN0cmVhbS5wcm90b3R5cGUuZ2V0TWlzc2luZ0NodW5rcyA9IGZ1bmN0aW9uICgpIHsKICAgICAgY29uc3QgY2h1bmtTaXplID0gdGhpcy5jaHVua1NpemU7CiAgICAgIGNvbnN0IGJlZ2luQ2h1bmsgPSBNYXRoLmZsb29yKHRoaXMuc3RhcnQgLyBjaHVua1NpemUpOwogICAgICBjb25zdCBlbmRDaHVuayA9IE1hdGguZmxvb3IoKHRoaXMuZW5kIC0gMSkgLyBjaHVua1NpemUpICsgMTsKICAgICAgY29uc3QgbWlzc2luZ0NodW5rcyA9IFtdOwogICAgICBmb3IgKGxldCBjaHVuayA9IGJlZ2luQ2h1bms7IGNodW5rIDwgZW5kQ2h1bms7ICsrY2h1bmspIHsKICAgICAgICBpZiAoIXRoaXMuX2xvYWRlZENodW5rcy5oYXMoY2h1bmspKSB7CiAgICAgICAgICBtaXNzaW5nQ2h1bmtzLnB1c2goY2h1bmspOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gbWlzc2luZ0NodW5rczsKICAgIH07CiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQ2h1bmtlZFN0cmVhbVN1YnN0cmVhbS5wcm90b3R5cGUsICJpc0RhdGFMb2FkZWQiLCB7CiAgICAgIGdldCgpIHsKICAgICAgICBpZiAodGhpcy5udW1DaHVua3NMb2FkZWQgPT09IHRoaXMubnVtQ2h1bmtzKSB7CiAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TWlzc2luZ0NodW5rcygpLmxlbmd0aCA9PT0gMDsKICAgICAgfSwKICAgICAgY29uZmlndXJhYmxlOiB0cnVlCiAgICB9KTsKICAgIGNvbnN0IHN1YlN0cmVhbSA9IG5ldyBDaHVua2VkU3RyZWFtU3Vic3RyZWFtKCk7CiAgICBzdWJTdHJlYW0ucG9zID0gc3ViU3RyZWFtLnN0YXJ0ID0gc3RhcnQ7CiAgICBzdWJTdHJlYW0uZW5kID0gc3RhcnQgKyBsZW5ndGggfHwgdGhpcy5lbmQ7CiAgICBzdWJTdHJlYW0uZGljdCA9IGRpY3Q7CiAgICByZXR1cm4gc3ViU3RyZWFtOwogIH0KICBnZXRCYXNlU3RyZWFtcygpIHsKICAgIHJldHVybiBbdGhpc107CiAgfQp9CmNsYXNzIENodW5rZWRTdHJlYW1NYW5hZ2VyIHsKICBjb25zdHJ1Y3RvcihwZGZOZXR3b3JrU3RyZWFtLCBhcmdzKSB7CiAgICB0aGlzLmxlbmd0aCA9IGFyZ3MubGVuZ3RoOwogICAgdGhpcy5jaHVua1NpemUgPSBhcmdzLnJhbmdlQ2h1bmtTaXplOwogICAgdGhpcy5zdHJlYW0gPSBuZXcgQ2h1bmtlZFN0cmVhbSh0aGlzLmxlbmd0aCwgdGhpcy5jaHVua1NpemUsIHRoaXMpOwogICAgdGhpcy5wZGZOZXR3b3JrU3RyZWFtID0gcGRmTmV0d29ya1N0cmVhbTsKICAgIHRoaXMuZGlzYWJsZUF1dG9GZXRjaCA9IGFyZ3MuZGlzYWJsZUF1dG9GZXRjaDsKICAgIHRoaXMubXNnSGFuZGxlciA9IGFyZ3MubXNnSGFuZGxlcjsKICAgIHRoaXMuY3VyclJlcXVlc3RJZCA9IDA7CiAgICB0aGlzLl9jaHVua3NOZWVkZWRCeVJlcXVlc3QgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9yZXF1ZXN0c0J5Q2h1bmsgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9wcm9taXNlc0J5UmVxdWVzdCA9IG5ldyBNYXAoKTsKICAgIHRoaXMucHJvZ3Jlc3NpdmVEYXRhTGVuZ3RoID0gMDsKICAgIHRoaXMuYWJvcnRlZCA9IGZhbHNlOwogICAgdGhpcy5fbG9hZGVkU3RyZWFtQ2FwYWJpbGl0eSA9IFByb21pc2Uud2l0aFJlc29sdmVycygpOwogIH0KICBzZW5kUmVxdWVzdChiZWdpbiwgZW5kKSB7CiAgICBjb25zdCByYW5nZVJlYWRlciA9IHRoaXMucGRmTmV0d29ya1N0cmVhbS5nZXRSYW5nZVJlYWRlcihiZWdpbiwgZW5kKTsKICAgIGlmICghcmFuZ2VSZWFkZXIuaXNTdHJlYW1pbmdTdXBwb3J0ZWQpIHsKICAgICAgcmFuZ2VSZWFkZXIub25Qcm9ncmVzcyA9IHRoaXMub25Qcm9ncmVzcy5iaW5kKHRoaXMpOwogICAgfQogICAgbGV0IGNodW5rcyA9IFtdLAogICAgICBsb2FkZWQgPSAwOwogICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHsKICAgICAgY29uc3QgcmVhZENodW5rID0gKHsKICAgICAgICB2YWx1ZSwKICAgICAgICBkb25lCiAgICAgIH0pID0+IHsKICAgICAgICB0cnkgewogICAgICAgICAgaWYgKGRvbmUpIHsKICAgICAgICAgICAgY29uc3QgY2h1bmtEYXRhID0gYXJyYXlCdWZmZXJzVG9CeXRlcyhjaHVua3MpOwogICAgICAgICAgICBjaHVua3MgPSBudWxsOwogICAgICAgICAgICByZXNvbHZlKGNodW5rRGF0YSk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KICAgICAgICAgIGxvYWRlZCArPSB2YWx1ZS5ieXRlTGVuZ3RoOwogICAgICAgICAgaWYgKHJhbmdlUmVhZGVyLmlzU3RyZWFtaW5nU3VwcG9ydGVkKSB7CiAgICAgICAgICAgIHRoaXMub25Qcm9ncmVzcyh7CiAgICAgICAgICAgICAgbG9hZGVkCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgY2h1bmtzLnB1c2godmFsdWUpOwogICAgICAgICAgcmFuZ2VSZWFkZXIucmVhZCgpLnRoZW4ocmVhZENodW5rLCByZWplY3QpOwogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgIHJlamVjdChlKTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIHJhbmdlUmVhZGVyLnJlYWQoKS50aGVuKHJlYWRDaHVuaywgcmVqZWN0KTsKICAgIH0pLnRoZW4oZGF0YSA9PiB7CiAgICAgIGlmICh0aGlzLmFib3J0ZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGhpcy5vblJlY2VpdmVEYXRhKHsKICAgICAgICBjaHVuazogZGF0YSwKICAgICAgICBiZWdpbgogICAgICB9KTsKICAgIH0pOwogIH0KICByZXF1ZXN0QWxsQ2h1bmtzKG5vRmV0Y2ggPSBmYWxzZSkgewogICAgaWYgKCFub0ZldGNoKSB7CiAgICAgIGNvbnN0IG1pc3NpbmdDaHVua3MgPSB0aGlzLnN0cmVhbS5nZXRNaXNzaW5nQ2h1bmtzKCk7CiAgICAgIHRoaXMuX3JlcXVlc3RDaHVua3MobWlzc2luZ0NodW5rcyk7CiAgICB9CiAgICByZXR1cm4gdGhpcy5fbG9hZGVkU3RyZWFtQ2FwYWJpbGl0eS5wcm9taXNlOwogIH0KICBfcmVxdWVzdENodW5rcyhjaHVua3MpIHsKICAgIGNvbnN0IHJlcXVlc3RJZCA9IHRoaXMuY3VyclJlcXVlc3RJZCsrOwogICAgY29uc3QgY2h1bmtzTmVlZGVkID0gbmV3IFNldCgpOwogICAgdGhpcy5fY2h1bmtzTmVlZGVkQnlSZXF1ZXN0LnNldChyZXF1ZXN0SWQsIGNodW5rc05lZWRlZCk7CiAgICBmb3IgKGNvbnN0IGNodW5rIG9mIGNodW5rcykgewogICAgICBpZiAoIXRoaXMuc3RyZWFtLmhhc0NodW5rKGNodW5rKSkgewogICAgICAgIGNodW5rc05lZWRlZC5hZGQoY2h1bmspOwogICAgICB9CiAgICB9CiAgICBpZiAoY2h1bmtzTmVlZGVkLnNpemUgPT09IDApIHsKICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpOwogICAgfQogICAgY29uc3QgY2FwYWJpbGl0eSA9IFByb21pc2Uud2l0aFJlc29sdmVycygpOwogICAgdGhpcy5fcHJvbWlzZXNCeVJlcXVlc3Quc2V0KHJlcXVlc3RJZCwgY2FwYWJpbGl0eSk7CiAgICBjb25zdCBjaHVua3NUb1JlcXVlc3QgPSBbXTsKICAgIGZvciAoY29uc3QgY2h1bmsgb2YgY2h1bmtzTmVlZGVkKSB7CiAgICAgIGxldCByZXF1ZXN0SWRzID0gdGhpcy5fcmVxdWVzdHNCeUNodW5rLmdldChjaHVuayk7CiAgICAgIGlmICghcmVxdWVzdElkcykgewogICAgICAgIHJlcXVlc3RJZHMgPSBbXTsKICAgICAgICB0aGlzLl9yZXF1ZXN0c0J5Q2h1bmsuc2V0KGNodW5rLCByZXF1ZXN0SWRzKTsKICAgICAgICBjaHVua3NUb1JlcXVlc3QucHVzaChjaHVuayk7CiAgICAgIH0KICAgICAgcmVxdWVzdElkcy5wdXNoKHJlcXVlc3RJZCk7CiAgICB9CiAgICBpZiAoY2h1bmtzVG9SZXF1ZXN0Lmxlbmd0aCA+IDApIHsKICAgICAgY29uc3QgZ3JvdXBlZENodW5rc1RvUmVxdWVzdCA9IHRoaXMuZ3JvdXBDaHVua3MoY2h1bmtzVG9SZXF1ZXN0KTsKICAgICAgZm9yIChjb25zdCBncm91cGVkQ2h1bmsgb2YgZ3JvdXBlZENodW5rc1RvUmVxdWVzdCkgewogICAgICAgIGNvbnN0IGJlZ2luID0gZ3JvdXBlZENodW5rLmJlZ2luQ2h1bmsgKiB0aGlzLmNodW5rU2l6ZTsKICAgICAgICBjb25zdCBlbmQgPSBNYXRoLm1pbihncm91cGVkQ2h1bmsuZW5kQ2h1bmsgKiB0aGlzLmNodW5rU2l6ZSwgdGhpcy5sZW5ndGgpOwogICAgICAgIHRoaXMuc2VuZFJlcXVlc3QoYmVnaW4sIGVuZCkuY2F0Y2goY2FwYWJpbGl0eS5yZWplY3QpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gY2FwYWJpbGl0eS5wcm9taXNlLmNhdGNoKHJlYXNvbiA9PiB7CiAgICAgIGlmICh0aGlzLmFib3J0ZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGhyb3cgcmVhc29uOwogICAgfSk7CiAgfQogIGdldFN0cmVhbSgpIHsKICAgIHJldHVybiB0aGlzLnN0cmVhbTsKICB9CiAgcmVxdWVzdFJhbmdlKGJlZ2luLCBlbmQpIHsKICAgIGVuZCA9IE1hdGgubWluKGVuZCwgdGhpcy5sZW5ndGgpOwogICAgY29uc3QgYmVnaW5DaHVuayA9IHRoaXMuZ2V0QmVnaW5DaHVuayhiZWdpbik7CiAgICBjb25zdCBlbmRDaHVuayA9IHRoaXMuZ2V0RW5kQ2h1bmsoZW5kKTsKICAgIGNvbnN0IGNodW5rcyA9IFtdOwogICAgZm9yIChsZXQgY2h1bmsgPSBiZWdpbkNodW5rOyBjaHVuayA8IGVuZENodW5rOyArK2NodW5rKSB7CiAgICAgIGNodW5rcy5wdXNoKGNodW5rKTsKICAgIH0KICAgIHJldHVybiB0aGlzLl9yZXF1ZXN0Q2h1bmtzKGNodW5rcyk7CiAgfQogIHJlcXVlc3RSYW5nZXMocmFuZ2VzID0gW10pIHsKICAgIGNvbnN0IGNodW5rc1RvUmVxdWVzdCA9IFtdOwogICAgZm9yIChjb25zdCByYW5nZSBvZiByYW5nZXMpIHsKICAgICAgY29uc3QgYmVnaW5DaHVuayA9IHRoaXMuZ2V0QmVnaW5DaHVuayhyYW5nZS5iZWdpbik7CiAgICAgIGNvbnN0IGVuZENodW5rID0gdGhpcy5nZXRFbmRDaHVuayhyYW5nZS5lbmQpOwogICAgICBmb3IgKGxldCBjaHVuayA9IGJlZ2luQ2h1bms7IGNodW5rIDwgZW5kQ2h1bms7ICsrY2h1bmspIHsKICAgICAgICBpZiAoIWNodW5rc1RvUmVxdWVzdC5pbmNsdWRlcyhjaHVuaykpIHsKICAgICAgICAgIGNodW5rc1RvUmVxdWVzdC5wdXNoKGNodW5rKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGNodW5rc1RvUmVxdWVzdC5zb3J0KChhLCBiKSA9PiBhIC0gYik7CiAgICByZXR1cm4gdGhpcy5fcmVxdWVzdENodW5rcyhjaHVua3NUb1JlcXVlc3QpOwogIH0KICBncm91cENodW5rcyhjaHVua3MpIHsKICAgIGNvbnN0IGdyb3VwZWRDaHVua3MgPSBbXTsKICAgIGxldCBiZWdpbkNodW5rID0gLTE7CiAgICBsZXQgcHJldkNodW5rID0gLTE7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBjaHVua3MubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgICBjb25zdCBjaHVuayA9IGNodW5rc1tpXTsKICAgICAgaWYgKGJlZ2luQ2h1bmsgPCAwKSB7CiAgICAgICAgYmVnaW5DaHVuayA9IGNodW5rOwogICAgICB9CiAgICAgIGlmIChwcmV2Q2h1bmsgPj0gMCAmJiBwcmV2Q2h1bmsgKyAxICE9PSBjaHVuaykgewogICAgICAgIGdyb3VwZWRDaHVua3MucHVzaCh7CiAgICAgICAgICBiZWdpbkNodW5rLAogICAgICAgICAgZW5kQ2h1bms6IHByZXZDaHVuayArIDEKICAgICAgICB9KTsKICAgICAgICBiZWdpbkNodW5rID0gY2h1bms7CiAgICAgIH0KICAgICAgaWYgKGkgKyAxID09PSBjaHVua3MubGVuZ3RoKSB7CiAgICAgICAgZ3JvdXBlZENodW5rcy5wdXNoKHsKICAgICAgICAgIGJlZ2luQ2h1bmssCiAgICAgICAgICBlbmRDaHVuazogY2h1bmsgKyAxCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgcHJldkNodW5rID0gY2h1bms7CiAgICB9CiAgICByZXR1cm4gZ3JvdXBlZENodW5rczsKICB9CiAgb25Qcm9ncmVzcyhhcmdzKSB7CiAgICB0aGlzLm1zZ0hhbmRsZXIuc2VuZCgiRG9jUHJvZ3Jlc3MiLCB7CiAgICAgIGxvYWRlZDogdGhpcy5zdHJlYW0ubnVtQ2h1bmtzTG9hZGVkICogdGhpcy5jaHVua1NpemUgKyBhcmdzLmxvYWRlZCwKICAgICAgdG90YWw6IHRoaXMubGVuZ3RoCiAgICB9KTsKICB9CiAgb25SZWNlaXZlRGF0YShhcmdzKSB7CiAgICBjb25zdCBjaHVuayA9IGFyZ3MuY2h1bms7CiAgICBjb25zdCBpc1Byb2dyZXNzaXZlID0gYXJncy5iZWdpbiA9PT0gdW5kZWZpbmVkOwogICAgY29uc3QgYmVnaW4gPSBpc1Byb2dyZXNzaXZlID8gdGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGggOiBhcmdzLmJlZ2luOwogICAgY29uc3QgZW5kID0gYmVnaW4gKyBjaHVuay5ieXRlTGVuZ3RoOwogICAgY29uc3QgYmVnaW5DaHVuayA9IE1hdGguZmxvb3IoYmVnaW4gLyB0aGlzLmNodW5rU2l6ZSk7CiAgICBjb25zdCBlbmRDaHVuayA9IGVuZCA8IHRoaXMubGVuZ3RoID8gTWF0aC5mbG9vcihlbmQgLyB0aGlzLmNodW5rU2l6ZSkgOiBNYXRoLmNlaWwoZW5kIC8gdGhpcy5jaHVua1NpemUpOwogICAgaWYgKGlzUHJvZ3Jlc3NpdmUpIHsKICAgICAgdGhpcy5zdHJlYW0ub25SZWNlaXZlUHJvZ3Jlc3NpdmVEYXRhKGNodW5rKTsKICAgICAgdGhpcy5wcm9ncmVzc2l2ZURhdGFMZW5ndGggPSBlbmQ7CiAgICB9IGVsc2UgewogICAgICB0aGlzLnN0cmVhbS5vblJlY2VpdmVEYXRhKGJlZ2luLCBjaHVuayk7CiAgICB9CiAgICBpZiAodGhpcy5zdHJlYW0uaXNEYXRhTG9hZGVkKSB7CiAgICAgIHRoaXMuX2xvYWRlZFN0cmVhbUNhcGFiaWxpdHkucmVzb2x2ZSh0aGlzLnN0cmVhbSk7CiAgICB9CiAgICBjb25zdCBsb2FkZWRSZXF1ZXN0cyA9IFtdOwogICAgZm9yIChsZXQgY3VyQ2h1bmsgPSBiZWdpbkNodW5rOyBjdXJDaHVuayA8IGVuZENodW5rOyArK2N1ckNodW5rKSB7CiAgICAgIGNvbnN0IHJlcXVlc3RJZHMgPSB0aGlzLl9yZXF1ZXN0c0J5Q2h1bmsuZ2V0KGN1ckNodW5rKTsKICAgICAgaWYgKCFyZXF1ZXN0SWRzKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgdGhpcy5fcmVxdWVzdHNCeUNodW5rLmRlbGV0ZShjdXJDaHVuayk7CiAgICAgIGZvciAoY29uc3QgcmVxdWVzdElkIG9mIHJlcXVlc3RJZHMpIHsKICAgICAgICBjb25zdCBjaHVua3NOZWVkZWQgPSB0aGlzLl9jaHVua3NOZWVkZWRCeVJlcXVlc3QuZ2V0KHJlcXVlc3RJZCk7CiAgICAgICAgaWYgKGNodW5rc05lZWRlZC5oYXMoY3VyQ2h1bmspKSB7CiAgICAgICAgICBjaHVua3NOZWVkZWQuZGVsZXRlKGN1ckNodW5rKTsKICAgICAgICB9CiAgICAgICAgaWYgKGNodW5rc05lZWRlZC5zaXplID4gMCkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGxvYWRlZFJlcXVlc3RzLnB1c2gocmVxdWVzdElkKTsKICAgICAgfQogICAgfQogICAgaWYgKCF0aGlzLmRpc2FibGVBdXRvRmV0Y2ggJiYgdGhpcy5fcmVxdWVzdHNCeUNodW5rLnNpemUgPT09IDApIHsKICAgICAgbGV0IG5leHRFbXB0eUNodW5rOwogICAgICBpZiAodGhpcy5zdHJlYW0ubnVtQ2h1bmtzTG9hZGVkID09PSAxKSB7CiAgICAgICAgY29uc3QgbGFzdENodW5rID0gdGhpcy5zdHJlYW0ubnVtQ2h1bmtzIC0gMTsKICAgICAgICBpZiAoIXRoaXMuc3RyZWFtLmhhc0NodW5rKGxhc3RDaHVuaykpIHsKICAgICAgICAgIG5leHRFbXB0eUNodW5rID0gbGFzdENodW5rOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBuZXh0RW1wdHlDaHVuayA9IHRoaXMuc3RyZWFtLm5leHRFbXB0eUNodW5rKGVuZENodW5rKTsKICAgICAgfQogICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihuZXh0RW1wdHlDaHVuaykpIHsKICAgICAgICB0aGlzLl9yZXF1ZXN0Q2h1bmtzKFtuZXh0RW1wdHlDaHVua10pOwogICAgICB9CiAgICB9CiAgICBmb3IgKGNvbnN0IHJlcXVlc3RJZCBvZiBsb2FkZWRSZXF1ZXN0cykgewogICAgICBjb25zdCBjYXBhYmlsaXR5ID0gdGhpcy5fcHJvbWlzZXNCeVJlcXVlc3QuZ2V0KHJlcXVlc3RJZCk7CiAgICAgIHRoaXMuX3Byb21pc2VzQnlSZXF1ZXN0LmRlbGV0ZShyZXF1ZXN0SWQpOwogICAgICBjYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgIH0KICAgIHRoaXMubXNnSGFuZGxlci5zZW5kKCJEb2NQcm9ncmVzcyIsIHsKICAgICAgbG9hZGVkOiB0aGlzLnN0cmVhbS5udW1DaHVua3NMb2FkZWQgKiB0aGlzLmNodW5rU2l6ZSwKICAgICAgdG90YWw6IHRoaXMubGVuZ3RoCiAgICB9KTsKICB9CiAgb25FcnJvcihlcnIpIHsKICAgIHRoaXMuX2xvYWRlZFN0cmVhbUNhcGFiaWxpdHkucmVqZWN0KGVycik7CiAgfQogIGdldEJlZ2luQ2h1bmsoYmVnaW4pIHsKICAgIHJldHVybiBNYXRoLmZsb29yKGJlZ2luIC8gdGhpcy5jaHVua1NpemUpOwogIH0KICBnZXRFbmRDaHVuayhlbmQpIHsKICAgIHJldHVybiBNYXRoLmZsb29yKChlbmQgLSAxKSAvIHRoaXMuY2h1bmtTaXplKSArIDE7CiAgfQogIGFib3J0KHJlYXNvbikgewogICAgdGhpcy5hYm9ydGVkID0gdHJ1ZTsKICAgIHRoaXMucGRmTmV0d29ya1N0cmVhbT8uY2FuY2VsQWxsUmVxdWVzdHMocmVhc29uKTsKICAgIGZvciAoY29uc3QgY2FwYWJpbGl0eSBvZiB0aGlzLl9wcm9taXNlc0J5UmVxdWVzdC52YWx1ZXMoKSkgewogICAgICBjYXBhYmlsaXR5LnJlamVjdChyZWFzb24pOwogICAgfQogIH0KfQoKOy8vIC4vc3JjL3NoYXJlZC9pbWFnZV91dGlscy5qcwoKCgoKCmZ1bmN0aW9uIGNvbnZlcnRUb1JHQkEocGFyYW1zKSB7CiAgc3dpdGNoIChwYXJhbXMua2luZCkgewogICAgY2FzZSBJbWFnZUtpbmQuR1JBWVNDQUxFXzFCUFA6CiAgICAgIHJldHVybiBjb252ZXJ0QmxhY2tBbmRXaGl0ZVRvUkdCQShwYXJhbXMpOwogICAgY2FzZSBJbWFnZUtpbmQuUkdCXzI0QlBQOgogICAgICByZXR1cm4gY29udmVydFJHQlRvUkdCQShwYXJhbXMpOwogIH0KICByZXR1cm4gbnVsbDsKfQpmdW5jdGlvbiBjb252ZXJ0QmxhY2tBbmRXaGl0ZVRvUkdCQSh7CiAgc3JjLAogIHNyY1BvcyA9IDAsCiAgZGVzdCwKICB3aWR0aCwKICBoZWlnaHQsCiAgbm9uQmxhY2tDb2xvciA9IDB4ZmZmZmZmZmYsCiAgaW52ZXJzZURlY29kZSA9IGZhbHNlCn0pIHsKICBjb25zdCBibGFjayA9IEZlYXR1cmVUZXN0LmlzTGl0dGxlRW5kaWFuID8gMHhmZjAwMDAwMCA6IDB4MDAwMDAwZmY7CiAgY29uc3QgW3plcm9NYXBwaW5nLCBvbmVNYXBwaW5nXSA9IGludmVyc2VEZWNvZGUgPyBbbm9uQmxhY2tDb2xvciwgYmxhY2tdIDogW2JsYWNrLCBub25CbGFja0NvbG9yXTsKICBjb25zdCB3aWR0aEluU291cmNlID0gd2lkdGggPj4gMzsKICBjb25zdCB3aWR0aFJlbWFpbmRlciA9IHdpZHRoICYgNzsKICBjb25zdCBzcmNMZW5ndGggPSBzcmMubGVuZ3RoOwogIGRlc3QgPSBuZXcgVWludDMyQXJyYXkoZGVzdC5idWZmZXIpOwogIGxldCBkZXN0UG9zID0gMDsKICBmb3IgKGxldCBpID0gMDsgaSA8IGhlaWdodDsgaSsrKSB7CiAgICBmb3IgKGNvbnN0IG1heCA9IHNyY1BvcyArIHdpZHRoSW5Tb3VyY2U7IHNyY1BvcyA8IG1heDsgc3JjUG9zKyspIHsKICAgICAgY29uc3QgZWxlbSA9IHNyY1BvcyA8IHNyY0xlbmd0aCA/IHNyY1tzcmNQb3NdIDogMjU1OwogICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMGIxMDAwMDAwMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMTAwMDAwMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMTAwMDAwID8gb25lTWFwcGluZyA6IHplcm9NYXBwaW5nOwogICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMGIxMDAwMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMTAwMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMTAwID8gb25lTWFwcGluZyA6IHplcm9NYXBwaW5nOwogICAgICBkZXN0W2Rlc3RQb3MrK10gPSBlbGVtICYgMGIxMCA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgICAgZGVzdFtkZXN0UG9zKytdID0gZWxlbSAmIDBiMSA/IG9uZU1hcHBpbmcgOiB6ZXJvTWFwcGluZzsKICAgIH0KICAgIGlmICh3aWR0aFJlbWFpbmRlciA9PT0gMCkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIGNvbnN0IGVsZW0gPSBzcmNQb3MgPCBzcmNMZW5ndGggPyBzcmNbc3JjUG9zKytdIDogMjU1OwogICAgZm9yIChsZXQgaiA9IDA7IGogPCB3aWR0aFJlbWFpbmRlcjsgaisrKSB7CiAgICAgIGRlc3RbZGVzdFBvcysrXSA9IGVsZW0gJiAxIDw8IDcgLSBqID8gb25lTWFwcGluZyA6IHplcm9NYXBwaW5nOwogICAgfQogIH0KICByZXR1cm4gewogICAgc3JjUG9zLAogICAgZGVzdFBvcwogIH07Cn0KZnVuY3Rpb24gY29udmVydFJHQlRvUkdCQSh7CiAgc3JjLAogIHNyY1BvcyA9IDAsCiAgZGVzdCwKICBkZXN0UG9zID0gMCwKICB3aWR0aCwKICBoZWlnaHQKfSkgewogIGxldCBpID0gMDsKICBjb25zdCBsZW4gPSB3aWR0aCAqIGhlaWdodCAqIDM7CiAgY29uc3QgbGVuMzIgPSBsZW4gPj4gMjsKICBjb25zdCBzcmMzMiA9IG5ldyBVaW50MzJBcnJheShzcmMuYnVmZmVyLCBzcmNQb3MsIGxlbjMyKTsKICBpZiAoRmVhdHVyZVRlc3QuaXNMaXR0bGVFbmRpYW4pIHsKICAgIGZvciAoOyBpIDwgbGVuMzIgLSAyOyBpICs9IDMsIGRlc3RQb3MgKz0gNCkgewogICAgICBjb25zdCBzMSA9IHNyYzMyW2ldOwogICAgICBjb25zdCBzMiA9IHNyYzMyW2kgKyAxXTsKICAgICAgY29uc3QgczMgPSBzcmMzMltpICsgMl07CiAgICAgIGRlc3RbZGVzdFBvc10gPSBzMSB8IDB4ZmYwMDAwMDA7CiAgICAgIGRlc3RbZGVzdFBvcyArIDFdID0gczEgPj4+IDI0IHwgczIgPDwgOCB8IDB4ZmYwMDAwMDA7CiAgICAgIGRlc3RbZGVzdFBvcyArIDJdID0gczIgPj4+IDE2IHwgczMgPDwgMTYgfCAweGZmMDAwMDAwOwogICAgICBkZXN0W2Rlc3RQb3MgKyAzXSA9IHMzID4+PiA4IHwgMHhmZjAwMDAwMDsKICAgIH0KICAgIGZvciAobGV0IGogPSBpICogNCwgamogPSBzcmNQb3MgKyBsZW47IGogPCBqajsgaiArPSAzKSB7CiAgICAgIGRlc3RbZGVzdFBvcysrXSA9IHNyY1tqXSB8IHNyY1tqICsgMV0gPDwgOCB8IHNyY1tqICsgMl0gPDwgMTYgfCAweGZmMDAwMDAwOwogICAgfQogIH0gZWxzZSB7CiAgICBmb3IgKDsgaSA8IGxlbjMyIC0gMjsgaSArPSAzLCBkZXN0UG9zICs9IDQpIHsKICAgICAgY29uc3QgczEgPSBzcmMzMltpXTsKICAgICAgY29uc3QgczIgPSBzcmMzMltpICsgMV07CiAgICAgIGNvbnN0IHMzID0gc3JjMzJbaSArIDJdOwogICAgICBkZXN0W2Rlc3RQb3NdID0gczEgfCAweGZmOwogICAgICBkZXN0W2Rlc3RQb3MgKyAxXSA9IHMxIDw8IDI0IHwgczIgPj4+IDggfCAweGZmOwogICAgICBkZXN0W2Rlc3RQb3MgKyAyXSA9IHMyIDw8IDE2IHwgczMgPj4+IDE2IHwgMHhmZjsKICAgICAgZGVzdFtkZXN0UG9zICsgM10gPSBzMyA8PCA4IHwgMHhmZjsKICAgIH0KICAgIGZvciAobGV0IGogPSBpICogNCwgamogPSBzcmNQb3MgKyBsZW47IGogPCBqajsgaiArPSAzKSB7CiAgICAgIGRlc3RbZGVzdFBvcysrXSA9IHNyY1tqXSA8PCAyNCB8IHNyY1tqICsgMV0gPDwgMTYgfCBzcmNbaiArIDJdIDw8IDggfCAweGZmOwogICAgfQogIH0KICByZXR1cm4gewogICAgc3JjUG9zOiBzcmNQb3MgKyBsZW4sCiAgICBkZXN0UG9zCiAgfTsKfQpmdW5jdGlvbiBncmF5VG9SR0JBKHNyYywgZGVzdCkgewogIGlmIChGZWF0dXJlVGVzdC5pc0xpdHRsZUVuZGlhbikgewogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gc3JjLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgZGVzdFtpXSA9IHNyY1tpXSAqIDB4MTAxMDEgfCAweGZmMDAwMDAwOwogICAgfQogIH0gZWxzZSB7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBzcmMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBkZXN0W2ldID0gc3JjW2ldICogMHgxMDEwMTAwIHwgMHgwMDAwMDBmZjsKICAgIH0KICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2ltYWdlX3Jlc2l6ZXIuanMKCgoKCgoKCgoKCgpjb25zdCBNSU5fSU1BR0VfRElNID0gMjA0ODsKY29uc3QgTUFYX0lNQUdFX0RJTSA9IDY1NTM3Owpjb25zdCBNQVhfRVJST1IgPSAxMjg7CmNsYXNzIEltYWdlUmVzaXplciB7CiAgc3RhdGljICNnb29kU3F1YXJlTGVuZ3RoID0gTUlOX0lNQUdFX0RJTTsKICBzdGF0aWMgI2lzSW1hZ2VEZWNvZGVyU3VwcG9ydGVkID0gRmVhdHVyZVRlc3QuaXNJbWFnZURlY29kZXJTdXBwb3J0ZWQ7CiAgY29uc3RydWN0b3IoaW1nRGF0YSwgaXNNYXNrKSB7CiAgICB0aGlzLl9pbWdEYXRhID0gaW1nRGF0YTsKICAgIHRoaXMuX2lzTWFzayA9IGlzTWFzazsKICB9CiAgc3RhdGljIGdldCBjYW5Vc2VJbWFnZURlY29kZXIoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJjYW5Vc2VJbWFnZURlY29kZXIiLCB0aGlzLiNpc0ltYWdlRGVjb2RlclN1cHBvcnRlZCA/IEltYWdlRGVjb2Rlci5pc1R5cGVTdXBwb3J0ZWQoImltYWdlL2JtcCIpIDogUHJvbWlzZS5yZXNvbHZlKGZhbHNlKSk7CiAgfQogIHN0YXRpYyBuZWVkc1RvQmVSZXNpemVkKHdpZHRoLCBoZWlnaHQpIHsKICAgIGlmICh3aWR0aCA8PSB0aGlzLiNnb29kU3F1YXJlTGVuZ3RoICYmIGhlaWdodCA8PSB0aGlzLiNnb29kU3F1YXJlTGVuZ3RoKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgTUFYX0RJTQogICAgfSA9IHRoaXM7CiAgICBpZiAod2lkdGggPiBNQVhfRElNIHx8IGhlaWdodCA+IE1BWF9ESU0pIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBjb25zdCBhcmVhID0gd2lkdGggKiBoZWlnaHQ7CiAgICBpZiAodGhpcy5faGFzTWF4QXJlYSkgewogICAgICByZXR1cm4gYXJlYSA+IHRoaXMuTUFYX0FSRUE7CiAgICB9CiAgICBpZiAoYXJlYSA8IHRoaXMuI2dvb2RTcXVhcmVMZW5ndGggKiogMikgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpcy5fYXJlR29vZERpbXMod2lkdGgsIGhlaWdodCkpIHsKICAgICAgdGhpcy4jZ29vZFNxdWFyZUxlbmd0aCA9IE1hdGgubWF4KHRoaXMuI2dvb2RTcXVhcmVMZW5ndGgsIE1hdGguZmxvb3IoTWF0aC5zcXJ0KHdpZHRoICogaGVpZ2h0KSkpOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICB0aGlzLiNnb29kU3F1YXJlTGVuZ3RoID0gdGhpcy5fZ3Vlc3NNYXgodGhpcy4jZ29vZFNxdWFyZUxlbmd0aCwgTUFYX0RJTSwgTUFYX0VSUk9SLCAwKTsKICAgIGNvbnN0IG1heEFyZWEgPSB0aGlzLk1BWF9BUkVBID0gdGhpcy4jZ29vZFNxdWFyZUxlbmd0aCAqKiAyOwogICAgcmV0dXJuIGFyZWEgPiBtYXhBcmVhOwogIH0KICBzdGF0aWMgZ2V0UmVkdWNlUG93ZXJGb3JKUFgod2lkdGgsIGhlaWdodCwgY29tcG9uZW50c0NvdW50KSB7CiAgICBjb25zdCBhcmVhID0gd2lkdGggKiBoZWlnaHQ7CiAgICBjb25zdCBtYXhKUFhBcmVhID0gMiAqKiAzMCAvIChjb21wb25lbnRzQ291bnQgKiA0KTsKICAgIGlmICghdGhpcy5uZWVkc1RvQmVSZXNpemVkKHdpZHRoLCBoZWlnaHQpKSB7CiAgICAgIGlmIChhcmVhID4gbWF4SlBYQXJlYSkgewogICAgICAgIHJldHVybiBNYXRoLmNlaWwoTWF0aC5sb2cyKGFyZWEgLyBtYXhKUFhBcmVhKSk7CiAgICAgIH0KICAgICAgcmV0dXJuIDA7CiAgICB9CiAgICBjb25zdCB7CiAgICAgIE1BWF9ESU0sCiAgICAgIE1BWF9BUkVBCiAgICB9ID0gdGhpczsKICAgIGNvbnN0IG1pbkZhY3RvciA9IE1hdGgubWF4KHdpZHRoIC8gTUFYX0RJTSwgaGVpZ2h0IC8gTUFYX0RJTSwgTWF0aC5zcXJ0KGFyZWEgLyBNYXRoLm1pbihtYXhKUFhBcmVhLCBNQVhfQVJFQSkpKTsKICAgIHJldHVybiBNYXRoLmNlaWwoTWF0aC5sb2cyKG1pbkZhY3RvcikpOwogIH0KICBzdGF0aWMgZ2V0IE1BWF9ESU0oKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJNQVhfRElNIiwgdGhpcy5fZ3Vlc3NNYXgoTUlOX0lNQUdFX0RJTSwgTUFYX0lNQUdFX0RJTSwgMCwgMSkpOwogIH0KICBzdGF0aWMgZ2V0IE1BWF9BUkVBKCkgewogICAgdGhpcy5faGFzTWF4QXJlYSA9IHRydWU7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJNQVhfQVJFQSIsIHRoaXMuX2d1ZXNzTWF4KHRoaXMuI2dvb2RTcXVhcmVMZW5ndGgsIHRoaXMuTUFYX0RJTSwgTUFYX0VSUk9SLCAwKSAqKiAyKTsKICB9CiAgc3RhdGljIHNldCBNQVhfQVJFQShhcmVhKSB7CiAgICBpZiAoYXJlYSA+PSAwKSB7CiAgICAgIHRoaXMuX2hhc01heEFyZWEgPSB0cnVlOwogICAgICBzaGFkb3codGhpcywgIk1BWF9BUkVBIiwgYXJlYSk7CiAgICB9CiAgfQogIHN0YXRpYyBzZXRPcHRpb25zKHsKICAgIGNhbnZhc01heEFyZWFJbkJ5dGVzID0gLTEsCiAgICBpc0ltYWdlRGVjb2RlclN1cHBvcnRlZCA9IGZhbHNlCiAgfSkgewogICAgaWYgKCF0aGlzLl9oYXNNYXhBcmVhKSB7CiAgICAgIHRoaXMuTUFYX0FSRUEgPSBjYW52YXNNYXhBcmVhSW5CeXRlcyA+PiAyOwogICAgfQogICAgdGhpcy4jaXNJbWFnZURlY29kZXJTdXBwb3J0ZWQgPSBpc0ltYWdlRGVjb2RlclN1cHBvcnRlZDsKICB9CiAgc3RhdGljIF9hcmVHb29kRGltcyh3aWR0aCwgaGVpZ2h0KSB7CiAgICB0cnkgewogICAgICBjb25zdCBjYW52YXMgPSBuZXcgT2Zmc2NyZWVuQ2FudmFzKHdpZHRoLCBoZWlnaHQpOwogICAgICBjb25zdCBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgiMmQiKTsKICAgICAgY3R4LmZpbGxSZWN0KDAsIDAsIDEsIDEpOwogICAgICBjb25zdCBvcGFjaXR5ID0gY3R4LmdldEltYWdlRGF0YSgwLCAwLCAxLCAxKS5kYXRhWzNdOwogICAgICBjYW52YXMud2lkdGggPSBjYW52YXMuaGVpZ2h0ID0gMTsKICAgICAgcmV0dXJuIG9wYWNpdHkgIT09IDA7CiAgICB9IGNhdGNoIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogIH0KICBzdGF0aWMgX2d1ZXNzTWF4KHN0YXJ0LCBlbmQsIHRvbGVyYW5jZSwgZGVmYXVsdEhlaWdodCkgewogICAgd2hpbGUgKHN0YXJ0ICsgdG9sZXJhbmNlICsgMSA8IGVuZCkgewogICAgICBjb25zdCBtaWRkbGUgPSBNYXRoLmZsb29yKChzdGFydCArIGVuZCkgLyAyKTsKICAgICAgY29uc3QgaGVpZ2h0ID0gZGVmYXVsdEhlaWdodCB8fCBtaWRkbGU7CiAgICAgIGlmICh0aGlzLl9hcmVHb29kRGltcyhtaWRkbGUsIGhlaWdodCkpIHsKICAgICAgICBzdGFydCA9IG1pZGRsZTsKICAgICAgfSBlbHNlIHsKICAgICAgICBlbmQgPSBtaWRkbGU7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzdGFydDsKICB9CiAgc3RhdGljIGFzeW5jIGNyZWF0ZUltYWdlKGltZ0RhdGEsIGlzTWFzayA9IGZhbHNlKSB7CiAgICByZXR1cm4gbmV3IEltYWdlUmVzaXplcihpbWdEYXRhLCBpc01hc2spLl9jcmVhdGVJbWFnZSgpOwogIH0KICBhc3luYyBfY3JlYXRlSW1hZ2UoKSB7CiAgICBjb25zdCB7CiAgICAgIF9pbWdEYXRhOiBpbWdEYXRhCiAgICB9ID0gdGhpczsKICAgIGNvbnN0IHsKICAgICAgd2lkdGgsCiAgICAgIGhlaWdodAogICAgfSA9IGltZ0RhdGE7CiAgICBpZiAod2lkdGggKiBoZWlnaHQgKiA0ID4gTUFYX0lOVF8zMikgewogICAgICBjb25zdCByZXN1bHQgPSB0aGlzLiNyZXNjYWxlSW1hZ2VEYXRhKCk7CiAgICAgIGlmIChyZXN1bHQpIHsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CiAgICB9CiAgICBjb25zdCBkYXRhID0gdGhpcy5fZW5jb2RlQk1QKCk7CiAgICBsZXQgZGVjb2RlciwgaW1hZ2VQcm9taXNlOwogICAgaWYgKGF3YWl0IEltYWdlUmVzaXplci5jYW5Vc2VJbWFnZURlY29kZXIpIHsKICAgICAgZGVjb2RlciA9IG5ldyBJbWFnZURlY29kZXIoewogICAgICAgIGRhdGEsCiAgICAgICAgdHlwZTogImltYWdlL2JtcCIsCiAgICAgICAgcHJlZmVyQW5pbWF0aW9uOiBmYWxzZSwKICAgICAgICB0cmFuc2ZlcjogW2RhdGEuYnVmZmVyXQogICAgICB9KTsKICAgICAgaW1hZ2VQcm9taXNlID0gZGVjb2Rlci5kZWNvZGUoKS5jYXRjaChyZWFzb24gPT4gewogICAgICAgIHdhcm4oYEJNUCBpbWFnZSBkZWNvZGluZyBmYWlsZWQ6ICR7cmVhc29ufWApOwogICAgICAgIHJldHVybiBjcmVhdGVJbWFnZUJpdG1hcChuZXcgQmxvYihbdGhpcy5fZW5jb2RlQk1QKCkuYnVmZmVyXSwgewogICAgICAgICAgdHlwZTogImltYWdlL2JtcCIKICAgICAgICB9KSk7CiAgICAgIH0pLmZpbmFsbHkoKCkgPT4gewogICAgICAgIGRlY29kZXIuY2xvc2UoKTsKICAgICAgfSk7CiAgICB9IGVsc2UgewogICAgICBpbWFnZVByb21pc2UgPSBjcmVhdGVJbWFnZUJpdG1hcChuZXcgQmxvYihbZGF0YS5idWZmZXJdLCB7CiAgICAgICAgdHlwZTogImltYWdlL2JtcCIKICAgICAgfSkpOwogICAgfQogICAgY29uc3QgewogICAgICBNQVhfQVJFQSwKICAgICAgTUFYX0RJTQogICAgfSA9IEltYWdlUmVzaXplcjsKICAgIGNvbnN0IG1pbkZhY3RvciA9IE1hdGgubWF4KHdpZHRoIC8gTUFYX0RJTSwgaGVpZ2h0IC8gTUFYX0RJTSwgTWF0aC5zcXJ0KHdpZHRoICogaGVpZ2h0IC8gTUFYX0FSRUEpKTsKICAgIGNvbnN0IGZpcnN0RmFjdG9yID0gTWF0aC5tYXgobWluRmFjdG9yLCAyKTsKICAgIGNvbnN0IGZhY3RvciA9IE1hdGgucm91bmQoMTAgKiAobWluRmFjdG9yICsgMS4yNSkpIC8gMTAgLyBmaXJzdEZhY3RvcjsKICAgIGNvbnN0IE4gPSBNYXRoLmZsb29yKE1hdGgubG9nMihmYWN0b3IpKTsKICAgIGNvbnN0IHN0ZXBzID0gbmV3IEFycmF5KE4gKyAyKS5maWxsKDIpOwogICAgc3RlcHNbMF0gPSBmaXJzdEZhY3RvcjsKICAgIHN0ZXBzLnNwbGljZSgtMSwgMSwgZmFjdG9yIC8gKDEgPDwgTikpOwogICAgbGV0IG5ld1dpZHRoID0gd2lkdGg7CiAgICBsZXQgbmV3SGVpZ2h0ID0gaGVpZ2h0OwogICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgaW1hZ2VQcm9taXNlOwogICAgbGV0IGJpdG1hcCA9IHJlc3VsdC5pbWFnZSB8fCByZXN1bHQ7CiAgICBmb3IgKGNvbnN0IHN0ZXAgb2Ygc3RlcHMpIHsKICAgICAgY29uc3QgcHJldldpZHRoID0gbmV3V2lkdGg7CiAgICAgIGNvbnN0IHByZXZIZWlnaHQgPSBuZXdIZWlnaHQ7CiAgICAgIG5ld1dpZHRoID0gTWF0aC5mbG9vcihuZXdXaWR0aCAvIHN0ZXApIC0gMTsKICAgICAgbmV3SGVpZ2h0ID0gTWF0aC5mbG9vcihuZXdIZWlnaHQgLyBzdGVwKSAtIDE7CiAgICAgIGNvbnN0IGNhbnZhcyA9IG5ldyBPZmZzY3JlZW5DYW52YXMobmV3V2lkdGgsIG5ld0hlaWdodCk7CiAgICAgIGNvbnN0IGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCIyZCIpOwogICAgICBjdHguZHJhd0ltYWdlKGJpdG1hcCwgMCwgMCwgcHJldldpZHRoLCBwcmV2SGVpZ2h0LCAwLCAwLCBuZXdXaWR0aCwgbmV3SGVpZ2h0KTsKICAgICAgYml0bWFwLmNsb3NlKCk7CiAgICAgIGJpdG1hcCA9IGNhbnZhcy50cmFuc2ZlclRvSW1hZ2VCaXRtYXAoKTsKICAgIH0KICAgIGltZ0RhdGEuZGF0YSA9IG51bGw7CiAgICBpbWdEYXRhLmJpdG1hcCA9IGJpdG1hcDsKICAgIGltZ0RhdGEud2lkdGggPSBuZXdXaWR0aDsKICAgIGltZ0RhdGEuaGVpZ2h0ID0gbmV3SGVpZ2h0OwogICAgcmV0dXJuIGltZ0RhdGE7CiAgfQogICNyZXNjYWxlSW1hZ2VEYXRhKCkgewogICAgY29uc3QgewogICAgICBfaW1nRGF0YTogaW1nRGF0YQogICAgfSA9IHRoaXM7CiAgICBjb25zdCB7CiAgICAgIGRhdGEsCiAgICAgIHdpZHRoLAogICAgICBoZWlnaHQsCiAgICAgIGtpbmQKICAgIH0gPSBpbWdEYXRhOwogICAgY29uc3QgcmdiYVNpemUgPSB3aWR0aCAqIGhlaWdodCAqIDQ7CiAgICBjb25zdCBLID0gTWF0aC5jZWlsKE1hdGgubG9nMihyZ2JhU2l6ZSAvIE1BWF9JTlRfMzIpKTsKICAgIGNvbnN0IG5ld1dpZHRoID0gd2lkdGggPj4gSzsKICAgIGNvbnN0IG5ld0hlaWdodCA9IGhlaWdodCA+PiBLOwogICAgbGV0IHJnYmFEYXRhOwogICAgbGV0IG1heEhlaWdodCA9IGhlaWdodDsKICAgIHRyeSB7CiAgICAgIHJnYmFEYXRhID0gbmV3IFVpbnQ4QXJyYXkocmdiYVNpemUpOwogICAgfSBjYXRjaCB7CiAgICAgIGxldCBuID0gTWF0aC5mbG9vcihNYXRoLmxvZzIocmdiYVNpemUgKyAxKSk7CiAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHJnYmFEYXRhID0gbmV3IFVpbnQ4QXJyYXkoMiAqKiBuIC0gMSk7CiAgICAgICAgICBicmVhazsKICAgICAgICB9IGNhdGNoIHsKICAgICAgICAgIG4gLT0gMTsKICAgICAgICB9CiAgICAgIH0KICAgICAgbWF4SGVpZ2h0ID0gTWF0aC5mbG9vcigoMiAqKiBuIC0gMSkgLyAod2lkdGggKiA0KSk7CiAgICAgIGNvbnN0IG5ld1NpemUgPSB3aWR0aCAqIG1heEhlaWdodCAqIDQ7CiAgICAgIGlmIChuZXdTaXplIDwgcmdiYURhdGEubGVuZ3RoKSB7CiAgICAgICAgcmdiYURhdGEgPSBuZXcgVWludDhBcnJheShuZXdTaXplKTsKICAgICAgfQogICAgfQogICAgY29uc3Qgc3JjMzIgPSBuZXcgVWludDMyQXJyYXkocmdiYURhdGEuYnVmZmVyKTsKICAgIGNvbnN0IGRlc3QzMiA9IG5ldyBVaW50MzJBcnJheShuZXdXaWR0aCAqIG5ld0hlaWdodCk7CiAgICBsZXQgc3JjUG9zID0gMDsKICAgIGxldCBuZXdJbmRleCA9IDA7CiAgICBjb25zdCBzdGVwID0gTWF0aC5jZWlsKGhlaWdodCAvIG1heEhlaWdodCk7CiAgICBjb25zdCByZW1haW5kZXIgPSBoZWlnaHQgJSBtYXhIZWlnaHQgPT09IDAgPyBoZWlnaHQgOiBoZWlnaHQgJSBtYXhIZWlnaHQ7CiAgICBmb3IgKGxldCBrID0gMDsgayA8IHN0ZXA7IGsrKykgewogICAgICBjb25zdCBoID0gayA8IHN0ZXAgLSAxID8gbWF4SGVpZ2h0IDogcmVtYWluZGVyOwogICAgICAoewogICAgICAgIHNyY1BvcwogICAgICB9ID0gY29udmVydFRvUkdCQSh7CiAgICAgICAga2luZCwKICAgICAgICBzcmM6IGRhdGEsCiAgICAgICAgZGVzdDogc3JjMzIsCiAgICAgICAgd2lkdGgsCiAgICAgICAgaGVpZ2h0OiBoLAogICAgICAgIGludmVyc2VEZWNvZGU6IHRoaXMuX2lzTWFzaywKICAgICAgICBzcmNQb3MKICAgICAgfSkpOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBoID4+IEs7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29uc3QgYnVmID0gc3JjMzIuc3ViYXJyYXkoKGkgPDwgSykgKiB3aWR0aCk7CiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBuZXdXaWR0aDsgaisrKSB7CiAgICAgICAgICBkZXN0MzJbbmV3SW5kZXgrK10gPSBidWZbaiA8PCBLXTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChJbWFnZVJlc2l6ZXIubmVlZHNUb0JlUmVzaXplZChuZXdXaWR0aCwgbmV3SGVpZ2h0KSkgewogICAgICBpbWdEYXRhLmRhdGEgPSBkZXN0MzI7CiAgICAgIGltZ0RhdGEud2lkdGggPSBuZXdXaWR0aDsKICAgICAgaW1nRGF0YS5oZWlnaHQgPSBuZXdIZWlnaHQ7CiAgICAgIGltZ0RhdGEua2luZCA9IEltYWdlS2luZC5SR0JBXzMyQlBQOwogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IGNhbnZhcyA9IG5ldyBPZmZzY3JlZW5DYW52YXMobmV3V2lkdGgsIG5ld0hlaWdodCk7CiAgICBjb25zdCBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgiMmQiLCB7CiAgICAgIHdpbGxSZWFkRnJlcXVlbnRseTogdHJ1ZQogICAgfSk7CiAgICBjdHgucHV0SW1hZ2VEYXRhKG5ldyBJbWFnZURhdGEobmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGRlc3QzMi5idWZmZXIpLCBuZXdXaWR0aCwgbmV3SGVpZ2h0KSwgMCwgMCk7CiAgICBpbWdEYXRhLmRhdGEgPSBudWxsOwogICAgaW1nRGF0YS5iaXRtYXAgPSBjYW52YXMudHJhbnNmZXJUb0ltYWdlQml0bWFwKCk7CiAgICBpbWdEYXRhLndpZHRoID0gbmV3V2lkdGg7CiAgICBpbWdEYXRhLmhlaWdodCA9IG5ld0hlaWdodDsKICAgIHJldHVybiBpbWdEYXRhOwogIH0KICBfZW5jb2RlQk1QKCkgewogICAgY29uc3QgewogICAgICB3aWR0aCwKICAgICAgaGVpZ2h0LAogICAgICBraW5kCiAgICB9ID0gdGhpcy5faW1nRGF0YTsKICAgIGxldCBkYXRhID0gdGhpcy5faW1nRGF0YS5kYXRhOwogICAgbGV0IGJpdFBlclBpeGVsOwogICAgbGV0IGNvbG9yVGFibGUgPSBuZXcgVWludDhBcnJheSgwKTsKICAgIGxldCBtYXNrVGFibGUgPSBjb2xvclRhYmxlOwogICAgbGV0IGNvbXByZXNzaW9uID0gMDsKICAgIHN3aXRjaCAoa2luZCkgewogICAgICBjYXNlIEltYWdlS2luZC5HUkFZU0NBTEVfMUJQUDoKICAgICAgICB7CiAgICAgICAgICBiaXRQZXJQaXhlbCA9IDE7CiAgICAgICAgICBjb2xvclRhYmxlID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5faXNNYXNrID8gWzI1NSwgMjU1LCAyNTUsIDI1NSwgMCwgMCwgMCwgMF0gOiBbMCwgMCwgMCwgMCwgMjU1LCAyNTUsIDI1NSwgMjU1XSk7CiAgICAgICAgICBjb25zdCByb3dMZW4gPSB3aWR0aCArIDcgPj4gMzsKICAgICAgICAgIGNvbnN0IHJvd1NpemUgPSByb3dMZW4gKyAzICYgLTQ7CiAgICAgICAgICBpZiAocm93TGVuICE9PSByb3dTaXplKSB7CiAgICAgICAgICAgIGNvbnN0IG5ld0RhdGEgPSBuZXcgVWludDhBcnJheShyb3dTaXplICogaGVpZ2h0KTsKICAgICAgICAgICAgbGV0IGsgPSAwOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBoZWlnaHQgKiByb3dMZW47IGkgPCBpaTsgaSArPSByb3dMZW4sIGsgKz0gcm93U2l6ZSkgewogICAgICAgICAgICAgIG5ld0RhdGEuc2V0KGRhdGEuc3ViYXJyYXkoaSwgaSArIHJvd0xlbiksIGspOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRhdGEgPSBuZXdEYXRhOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICBjYXNlIEltYWdlS2luZC5SR0JfMjRCUFA6CiAgICAgICAgewogICAgICAgICAgYml0UGVyUGl4ZWwgPSAyNDsKICAgICAgICAgIGlmICh3aWR0aCAmIDMpIHsKICAgICAgICAgICAgY29uc3Qgcm93TGVuID0gMyAqIHdpZHRoOwogICAgICAgICAgICBjb25zdCByb3dTaXplID0gcm93TGVuICsgMyAmIC00OwogICAgICAgICAgICBjb25zdCBleHRyYUxlbiA9IHJvd1NpemUgLSByb3dMZW47CiAgICAgICAgICAgIGNvbnN0IG5ld0RhdGEgPSBuZXcgVWludDhBcnJheShyb3dTaXplICogaGVpZ2h0KTsKICAgICAgICAgICAgbGV0IGsgPSAwOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBoZWlnaHQgKiByb3dMZW47IGkgPCBpaTsgaSArPSByb3dMZW4pIHsKICAgICAgICAgICAgICBjb25zdCByb3cgPSBkYXRhLnN1YmFycmF5KGksIGkgKyByb3dMZW4pOwogICAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgcm93TGVuOyBqICs9IDMpIHsKICAgICAgICAgICAgICAgIG5ld0RhdGFbaysrXSA9IHJvd1tqICsgMl07CiAgICAgICAgICAgICAgICBuZXdEYXRhW2srK10gPSByb3dbaiArIDFdOwogICAgICAgICAgICAgICAgbmV3RGF0YVtrKytdID0gcm93W2pdOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBrICs9IGV4dHJhTGVuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRhdGEgPSBuZXdEYXRhOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZGF0YS5sZW5ndGg7IGkgPCBpaTsgaSArPSAzKSB7CiAgICAgICAgICAgICAgY29uc3QgdG1wID0gZGF0YVtpXTsKICAgICAgICAgICAgICBkYXRhW2ldID0gZGF0YVtpICsgMl07CiAgICAgICAgICAgICAgZGF0YVtpICsgMl0gPSB0bXA7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgY2FzZSBJbWFnZUtpbmQuUkdCQV8zMkJQUDoKICAgICAgICBiaXRQZXJQaXhlbCA9IDMyOwogICAgICAgIGNvbXByZXNzaW9uID0gMzsKICAgICAgICBtYXNrVGFibGUgPSBuZXcgVWludDhBcnJheSg0ICsgNCArIDQgKyA0ICsgNTIpOwogICAgICAgIGNvbnN0IHZpZXcgPSBuZXcgRGF0YVZpZXcobWFza1RhYmxlLmJ1ZmZlcik7CiAgICAgICAgaWYgKEZlYXR1cmVUZXN0LmlzTGl0dGxlRW5kaWFuKSB7CiAgICAgICAgICB2aWV3LnNldFVpbnQzMigwLCAweDAwMDAwMGZmLCB0cnVlKTsKICAgICAgICAgIHZpZXcuc2V0VWludDMyKDQsIDB4MDAwMGZmMDAsIHRydWUpOwogICAgICAgICAgdmlldy5zZXRVaW50MzIoOCwgMHgwMGZmMDAwMCwgdHJ1ZSk7CiAgICAgICAgICB2aWV3LnNldFVpbnQzMigxMiwgMHhmZjAwMDAwMCwgdHJ1ZSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHZpZXcuc2V0VWludDMyKDAsIDB4ZmYwMDAwMDAsIHRydWUpOwogICAgICAgICAgdmlldy5zZXRVaW50MzIoNCwgMHgwMGZmMDAwMCwgdHJ1ZSk7CiAgICAgICAgICB2aWV3LnNldFVpbnQzMig4LCAweDAwMDBmZjAwLCB0cnVlKTsKICAgICAgICAgIHZpZXcuc2V0VWludDMyKDEyLCAweDAwMDAwMGZmLCB0cnVlKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJpbnZhbGlkIGZvcm1hdCIpOwogICAgfQogICAgbGV0IGkgPSAwOwogICAgY29uc3QgaGVhZGVyTGVuZ3RoID0gNDAgKyBtYXNrVGFibGUubGVuZ3RoOwogICAgY29uc3QgZmlsZUxlbmd0aCA9IDE0ICsgaGVhZGVyTGVuZ3RoICsgY29sb3JUYWJsZS5sZW5ndGggKyBkYXRhLmxlbmd0aDsKICAgIGNvbnN0IGJtcERhdGEgPSBuZXcgVWludDhBcnJheShmaWxlTGVuZ3RoKTsKICAgIGNvbnN0IHZpZXcgPSBuZXcgRGF0YVZpZXcoYm1wRGF0YS5idWZmZXIpOwogICAgdmlldy5zZXRVaW50MTYoaSwgMHg0ZDQyLCB0cnVlKTsKICAgIGkgKz0gMjsKICAgIHZpZXcuc2V0VWludDMyKGksIGZpbGVMZW5ndGgsIHRydWUpOwogICAgaSArPSA0OwogICAgdmlldy5zZXRVaW50MzIoaSwgMCwgdHJ1ZSk7CiAgICBpICs9IDQ7CiAgICB2aWV3LnNldFVpbnQzMihpLCAxNCArIGhlYWRlckxlbmd0aCArIGNvbG9yVGFibGUubGVuZ3RoLCB0cnVlKTsKICAgIGkgKz0gNDsKICAgIHZpZXcuc2V0VWludDMyKGksIGhlYWRlckxlbmd0aCwgdHJ1ZSk7CiAgICBpICs9IDQ7CiAgICB2aWV3LnNldEludDMyKGksIHdpZHRoLCB0cnVlKTsKICAgIGkgKz0gNDsKICAgIHZpZXcuc2V0SW50MzIoaSwgLWhlaWdodCwgdHJ1ZSk7CiAgICBpICs9IDQ7CiAgICB2aWV3LnNldFVpbnQxNihpLCAxLCB0cnVlKTsKICAgIGkgKz0gMjsKICAgIHZpZXcuc2V0VWludDE2KGksIGJpdFBlclBpeGVsLCB0cnVlKTsKICAgIGkgKz0gMjsKICAgIHZpZXcuc2V0VWludDMyKGksIGNvbXByZXNzaW9uLCB0cnVlKTsKICAgIGkgKz0gNDsKICAgIHZpZXcuc2V0VWludDMyKGksIDAsIHRydWUpOwogICAgaSArPSA0OwogICAgdmlldy5zZXRJbnQzMihpLCAwLCB0cnVlKTsKICAgIGkgKz0gNDsKICAgIHZpZXcuc2V0SW50MzIoaSwgMCwgdHJ1ZSk7CiAgICBpICs9IDQ7CiAgICB2aWV3LnNldFVpbnQzMihpLCBjb2xvclRhYmxlLmxlbmd0aCAvIDQsIHRydWUpOwogICAgaSArPSA0OwogICAgdmlldy5zZXRVaW50MzIoaSwgMCwgdHJ1ZSk7CiAgICBpICs9IDQ7CiAgICBibXBEYXRhLnNldChtYXNrVGFibGUsIGkpOwogICAgaSArPSBtYXNrVGFibGUubGVuZ3RoOwogICAgYm1wRGF0YS5zZXQoY29sb3JUYWJsZSwgaSk7CiAgICBpICs9IGNvbG9yVGFibGUubGVuZ3RoOwogICAgYm1wRGF0YS5zZXQoZGF0YSwgaSk7CiAgICByZXR1cm4gYm1wRGF0YTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2RlY29kZV9zdHJlYW0uanMKCgoKCgoKCgoKCgoKCmNvbnN0IGVtcHR5QnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoMCk7CmNsYXNzIERlY29kZVN0cmVhbSBleHRlbmRzIEJhc2VTdHJlYW0gewogIGNvbnN0cnVjdG9yKG1heWJlTWluQnVmZmVyTGVuZ3RoKSB7CiAgICBzdXBlcigpOwogICAgdGhpcy5fcmF3TWluQnVmZmVyTGVuZ3RoID0gbWF5YmVNaW5CdWZmZXJMZW5ndGggfHwgMDsKICAgIHRoaXMucG9zID0gMDsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gMDsKICAgIHRoaXMuZW9mID0gZmFsc2U7CiAgICB0aGlzLmJ1ZmZlciA9IGVtcHR5QnVmZmVyOwogICAgdGhpcy5taW5CdWZmZXJMZW5ndGggPSA1MTI7CiAgICBpZiAobWF5YmVNaW5CdWZmZXJMZW5ndGgpIHsKICAgICAgd2hpbGUgKHRoaXMubWluQnVmZmVyTGVuZ3RoIDwgbWF5YmVNaW5CdWZmZXJMZW5ndGgpIHsKICAgICAgICB0aGlzLm1pbkJ1ZmZlckxlbmd0aCAqPSAyOwogICAgICB9CiAgICB9CiAgfQogIGdldCBpc0VtcHR5KCkgewogICAgd2hpbGUgKCF0aGlzLmVvZiAmJiB0aGlzLmJ1ZmZlckxlbmd0aCA9PT0gMCkgewogICAgICB0aGlzLnJlYWRCbG9jaygpOwogICAgfQogICAgcmV0dXJuIHRoaXMuYnVmZmVyTGVuZ3RoID09PSAwOwogIH0KICBlbnN1cmVCdWZmZXIocmVxdWVzdGVkKSB7CiAgICBjb25zdCBidWZmZXIgPSB0aGlzLmJ1ZmZlcjsKICAgIGlmIChyZXF1ZXN0ZWQgPD0gYnVmZmVyLmJ5dGVMZW5ndGgpIHsKICAgICAgcmV0dXJuIGJ1ZmZlcjsKICAgIH0KICAgIGxldCBzaXplID0gdGhpcy5taW5CdWZmZXJMZW5ndGg7CiAgICB3aGlsZSAoc2l6ZSA8IHJlcXVlc3RlZCkgewogICAgICBzaXplICo9IDI7CiAgICB9CiAgICBjb25zdCBidWZmZXIyID0gbmV3IFVpbnQ4QXJyYXkoc2l6ZSk7CiAgICBidWZmZXIyLnNldChidWZmZXIpOwogICAgcmV0dXJuIHRoaXMuYnVmZmVyID0gYnVmZmVyMjsKICB9CiAgZ2V0Qnl0ZSgpIHsKICAgIGNvbnN0IHBvcyA9IHRoaXMucG9zOwogICAgd2hpbGUgKHRoaXMuYnVmZmVyTGVuZ3RoIDw9IHBvcykgewogICAgICBpZiAodGhpcy5lb2YpIHsKICAgICAgICByZXR1cm4gLTE7CiAgICAgIH0KICAgICAgdGhpcy5yZWFkQmxvY2soKTsKICAgIH0KICAgIHJldHVybiB0aGlzLmJ1ZmZlclt0aGlzLnBvcysrXTsKICB9CiAgZ2V0Qnl0ZXMobGVuZ3RoLCBkZWNvZGVyT3B0aW9ucyA9IG51bGwpIHsKICAgIGNvbnN0IHBvcyA9IHRoaXMucG9zOwogICAgbGV0IGVuZDsKICAgIGlmIChsZW5ndGgpIHsKICAgICAgdGhpcy5lbnN1cmVCdWZmZXIocG9zICsgbGVuZ3RoKTsKICAgICAgZW5kID0gcG9zICsgbGVuZ3RoOwogICAgICB3aGlsZSAoIXRoaXMuZW9mICYmIHRoaXMuYnVmZmVyTGVuZ3RoIDwgZW5kKSB7CiAgICAgICAgdGhpcy5yZWFkQmxvY2soZGVjb2Rlck9wdGlvbnMpOwogICAgICB9CiAgICAgIGNvbnN0IGJ1ZkVuZCA9IHRoaXMuYnVmZmVyTGVuZ3RoOwogICAgICBpZiAoZW5kID4gYnVmRW5kKSB7CiAgICAgICAgZW5kID0gYnVmRW5kOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB3aGlsZSAoIXRoaXMuZW9mKSB7CiAgICAgICAgdGhpcy5yZWFkQmxvY2soZGVjb2Rlck9wdGlvbnMpOwogICAgICB9CiAgICAgIGVuZCA9IHRoaXMuYnVmZmVyTGVuZ3RoOwogICAgfQogICAgdGhpcy5wb3MgPSBlbmQ7CiAgICByZXR1cm4gdGhpcy5idWZmZXIuc3ViYXJyYXkocG9zLCBlbmQpOwogIH0KICBhc3luYyBnZXRJbWFnZURhdGEobGVuZ3RoLCBkZWNvZGVyT3B0aW9ucykgewogICAgaWYgKCF0aGlzLmNhbkFzeW5jRGVjb2RlSW1hZ2VGcm9tQnVmZmVyKSB7CiAgICAgIGlmICh0aGlzLmlzQXN5bmNEZWNvZGVyKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZGVjb2RlSW1hZ2UobnVsbCwgZGVjb2Rlck9wdGlvbnMpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLmdldEJ5dGVzKGxlbmd0aCwgZGVjb2Rlck9wdGlvbnMpOwogICAgfQogICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMuc3RyZWFtLmFzeW5jR2V0Qnl0ZXMoKTsKICAgIHJldHVybiB0aGlzLmRlY29kZUltYWdlKGRhdGEsIGRlY29kZXJPcHRpb25zKTsKICB9CiAgcmVzZXQoKSB7CiAgICB0aGlzLnBvcyA9IDA7CiAgfQogIG1ha2VTdWJTdHJlYW0oc3RhcnQsIGxlbmd0aCwgZGljdCA9IG51bGwpIHsKICAgIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCkgewogICAgICB3aGlsZSAoIXRoaXMuZW9mKSB7CiAgICAgICAgdGhpcy5yZWFkQmxvY2soKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgY29uc3QgZW5kID0gc3RhcnQgKyBsZW5ndGg7CiAgICAgIHdoaWxlICh0aGlzLmJ1ZmZlckxlbmd0aCA8PSBlbmQgJiYgIXRoaXMuZW9mKSB7CiAgICAgICAgdGhpcy5yZWFkQmxvY2soKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIG5ldyBTdHJlYW0odGhpcy5idWZmZXIsIHN0YXJ0LCBsZW5ndGgsIGRpY3QpOwogIH0KICBnZXRCYXNlU3RyZWFtcygpIHsKICAgIHJldHVybiB0aGlzLnN0ciA/IHRoaXMuc3RyLmdldEJhc2VTdHJlYW1zKCkgOiBudWxsOwogIH0KfQpjbGFzcyBTdHJlYW1zU2VxdWVuY2VTdHJlYW0gZXh0ZW5kcyBEZWNvZGVTdHJlYW0gewogIGNvbnN0cnVjdG9yKHN0cmVhbXMsIG9uRXJyb3IgPSBudWxsKSB7CiAgICBzdHJlYW1zID0gc3RyZWFtcy5maWx0ZXIocyA9PiBzIGluc3RhbmNlb2YgQmFzZVN0cmVhbSk7CiAgICBsZXQgbWF5YmVMZW5ndGggPSAwOwogICAgZm9yIChjb25zdCBzdHJlYW0gb2Ygc3RyZWFtcykgewogICAgICBtYXliZUxlbmd0aCArPSBzdHJlYW0gaW5zdGFuY2VvZiBEZWNvZGVTdHJlYW0gPyBzdHJlYW0uX3Jhd01pbkJ1ZmZlckxlbmd0aCA6IHN0cmVhbS5sZW5ndGg7CiAgICB9CiAgICBzdXBlcihtYXliZUxlbmd0aCk7CiAgICB0aGlzLnN0cmVhbXMgPSBzdHJlYW1zOwogICAgdGhpcy5fb25FcnJvciA9IG9uRXJyb3I7CiAgfQogIHJlYWRCbG9jaygpIHsKICAgIGNvbnN0IHN0cmVhbXMgPSB0aGlzLnN0cmVhbXM7CiAgICBpZiAoc3RyZWFtcy5sZW5ndGggPT09IDApIHsKICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBzdHJlYW0gPSBzdHJlYW1zLnNoaWZ0KCk7CiAgICBsZXQgY2h1bms7CiAgICB0cnkgewogICAgICBjaHVuayA9IHN0cmVhbS5nZXRCeXRlcygpOwogICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgIGlmICh0aGlzLl9vbkVycm9yKSB7CiAgICAgICAgdGhpcy5fb25FcnJvcihyZWFzb24sIHN0cmVhbS5kaWN0Py5vYmpJZCk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIHRocm93IHJlYXNvbjsKICAgIH0KICAgIGNvbnN0IGJ1ZmZlckxlbmd0aCA9IHRoaXMuYnVmZmVyTGVuZ3RoOwogICAgY29uc3QgbmV3TGVuZ3RoID0gYnVmZmVyTGVuZ3RoICsgY2h1bmsubGVuZ3RoOwogICAgY29uc3QgYnVmZmVyID0gdGhpcy5lbnN1cmVCdWZmZXIobmV3TGVuZ3RoKTsKICAgIGJ1ZmZlci5zZXQoY2h1bmssIGJ1ZmZlckxlbmd0aCk7CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IG5ld0xlbmd0aDsKICB9CiAgZ2V0QmFzZVN0cmVhbXMoKSB7CiAgICBjb25zdCBiYXNlU3RyZWFtc0J1ZiA9IFtdOwogICAgZm9yIChjb25zdCBzdHJlYW0gb2YgdGhpcy5zdHJlYW1zKSB7CiAgICAgIGNvbnN0IGJhc2VTdHJlYW1zID0gc3RyZWFtLmdldEJhc2VTdHJlYW1zKCk7CiAgICAgIGlmIChiYXNlU3RyZWFtcykgewogICAgICAgIGJhc2VTdHJlYW1zQnVmLnB1c2goLi4uYmFzZVN0cmVhbXMpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gYmFzZVN0cmVhbXNCdWYubGVuZ3RoID4gMCA/IGJhc2VTdHJlYW1zQnVmIDogbnVsbDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2NvbG9yc3BhY2VfdXRpbHMuanMKCgoKCgpjbGFzcyBDb2xvclNwYWNlVXRpbHMgewogIHN0YXRpYyBwYXJzZSh7CiAgICBjcywKICAgIHhyZWYsCiAgICByZXNvdXJjZXMgPSBudWxsLAogICAgcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUsCiAgICBhc3luY0lmTm90Q2FjaGVkID0gZmFsc2UKICB9KSB7CiAgICBjb25zdCBvcHRpb25zID0gewogICAgICB4cmVmLAogICAgICByZXNvdXJjZXMsCiAgICAgIHBkZkZ1bmN0aW9uRmFjdG9yeSwKICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgfTsKICAgIGxldCBjc05hbWUsIGNzUmVmLCBwYXJzZWRDUzsKICAgIGlmIChjcyBpbnN0YW5jZW9mIFJlZikgewogICAgICBjc1JlZiA9IGNzOwogICAgICBjb25zdCBjYWNoZWRDUyA9IGdsb2JhbENvbG9yU3BhY2VDYWNoZS5nZXRCeVJlZihjc1JlZikgfHwgbG9jYWxDb2xvclNwYWNlQ2FjaGUuZ2V0QnlSZWYoY3NSZWYpOwogICAgICBpZiAoY2FjaGVkQ1MpIHsKICAgICAgICByZXR1cm4gY2FjaGVkQ1M7CiAgICAgIH0KICAgICAgY3MgPSB4cmVmLmZldGNoKGNzKTsKICAgIH0KICAgIGlmIChjcyBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgY3NOYW1lID0gY3MubmFtZTsKICAgICAgY29uc3QgY2FjaGVkQ1MgPSBsb2NhbENvbG9yU3BhY2VDYWNoZS5nZXRCeU5hbWUoY3NOYW1lKTsKICAgICAgaWYgKGNhY2hlZENTKSB7CiAgICAgICAgcmV0dXJuIGNhY2hlZENTOwogICAgICB9CiAgICB9CiAgICB0cnkgewogICAgICBwYXJzZWRDUyA9IHRoaXMuI3BhcnNlKGNzLCBvcHRpb25zKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChhc3luY0lmTm90Q2FjaGVkICYmICEoZXggaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikpIHsKICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXgpOwogICAgICB9CiAgICAgIHRocm93IGV4OwogICAgfQogICAgaWYgKGNzTmFtZSB8fCBjc1JlZikgewogICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZS5zZXQoY3NOYW1lLCBjc1JlZiwgcGFyc2VkQ1MpOwogICAgICBpZiAoY3NSZWYpIHsKICAgICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGUuc2V0KG51bGwsIGNzUmVmLCBwYXJzZWRDUyk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBhc3luY0lmTm90Q2FjaGVkID8gUHJvbWlzZS5yZXNvbHZlKHBhcnNlZENTKSA6IHBhcnNlZENTOwogIH0KICBzdGF0aWMgI3N1YlBhcnNlKGNzLCBvcHRpb25zKSB7CiAgICBjb25zdCB7CiAgICAgIGdsb2JhbENvbG9yU3BhY2VDYWNoZQogICAgfSA9IG9wdGlvbnM7CiAgICBsZXQgY3NSZWY7CiAgICBpZiAoY3MgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgY3NSZWYgPSBjczsKICAgICAgY29uc3QgY2FjaGVkQ1MgPSBnbG9iYWxDb2xvclNwYWNlQ2FjaGUuZ2V0QnlSZWYoY3NSZWYpOwogICAgICBpZiAoY2FjaGVkQ1MpIHsKICAgICAgICByZXR1cm4gY2FjaGVkQ1M7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHBhcnNlZENTID0gdGhpcy4jcGFyc2UoY3MsIG9wdGlvbnMpOwogICAgaWYgKGNzUmVmKSB7CiAgICAgIGdsb2JhbENvbG9yU3BhY2VDYWNoZS5zZXQobnVsbCwgY3NSZWYsIHBhcnNlZENTKTsKICAgIH0KICAgIHJldHVybiBwYXJzZWRDUzsKICB9CiAgc3RhdGljICNwYXJzZShjcywgb3B0aW9ucykgewogICAgY29uc3QgewogICAgICB4cmVmLAogICAgICByZXNvdXJjZXMsCiAgICAgIHBkZkZ1bmN0aW9uRmFjdG9yeSwKICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlCiAgICB9ID0gb3B0aW9uczsKICAgIGNzID0geHJlZi5mZXRjaElmUmVmKGNzKTsKICAgIGlmIChjcyBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgc3dpdGNoIChjcy5uYW1lKSB7CiAgICAgICAgY2FzZSAiRyI6CiAgICAgICAgY2FzZSAiRGV2aWNlR3JheSI6CiAgICAgICAgICByZXR1cm4gdGhpcy5ncmF5OwogICAgICAgIGNhc2UgIlJHQiI6CiAgICAgICAgY2FzZSAiRGV2aWNlUkdCIjoKICAgICAgICAgIHJldHVybiB0aGlzLnJnYjsKICAgICAgICBjYXNlICJEZXZpY2VSR0JBIjoKICAgICAgICAgIHJldHVybiB0aGlzLnJnYmE7CiAgICAgICAgY2FzZSAiQ01ZSyI6CiAgICAgICAgY2FzZSAiRGV2aWNlQ01ZSyI6CiAgICAgICAgICByZXR1cm4gdGhpcy5jbXlrOwogICAgICAgIGNhc2UgIlBhdHRlcm4iOgogICAgICAgICAgcmV0dXJuIG5ldyBQYXR0ZXJuQ1MobnVsbCk7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIGlmIChyZXNvdXJjZXMgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgICAgICAgIGNvbnN0IGNvbG9yU3BhY2VzID0gcmVzb3VyY2VzLmdldCgiQ29sb3JTcGFjZSIpOwogICAgICAgICAgICBpZiAoY29sb3JTcGFjZXMgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgICAgICAgICAgY29uc3QgcmVzb3VyY2VzQ1MgPSBjb2xvclNwYWNlcy5nZXQoY3MubmFtZSk7CiAgICAgICAgICAgICAgaWYgKHJlc291cmNlc0NTKSB7CiAgICAgICAgICAgICAgICBpZiAocmVzb3VyY2VzQ1MgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLiNwYXJzZShyZXNvdXJjZXNDUywgb3B0aW9ucyk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjcyA9IHJlc291cmNlc0NTOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICB3YXJuKGBVbnJlY29nbml6ZWQgQ29sb3JTcGFjZTogJHtjcy5uYW1lfWApOwogICAgICAgICAgcmV0dXJuIHRoaXMuZ3JheTsKICAgICAgfQogICAgfQogICAgaWYgKEFycmF5LmlzQXJyYXkoY3MpKSB7CiAgICAgIGNvbnN0IG1vZGUgPSB4cmVmLmZldGNoSWZSZWYoY3NbMF0pLm5hbWU7CiAgICAgIGxldCBwYXJhbXMsIG51bUNvbXBzLCBiYXNlQ1MsIHdoaXRlUG9pbnQsIGJsYWNrUG9pbnQsIGdhbW1hOwogICAgICBzd2l0Y2ggKG1vZGUpIHsKICAgICAgICBjYXNlICJHIjoKICAgICAgICBjYXNlICJEZXZpY2VHcmF5IjoKICAgICAgICAgIHJldHVybiB0aGlzLmdyYXk7CiAgICAgICAgY2FzZSAiUkdCIjoKICAgICAgICBjYXNlICJEZXZpY2VSR0IiOgogICAgICAgICAgcmV0dXJuIHRoaXMucmdiOwogICAgICAgIGNhc2UgIkNNWUsiOgogICAgICAgIGNhc2UgIkRldmljZUNNWUsiOgogICAgICAgICAgcmV0dXJuIHRoaXMuY215azsKICAgICAgICBjYXNlICJDYWxHcmF5IjoKICAgICAgICAgIHBhcmFtcyA9IHhyZWYuZmV0Y2hJZlJlZihjc1sxXSk7CiAgICAgICAgICB3aGl0ZVBvaW50ID0gcGFyYW1zLmdldEFycmF5KCJXaGl0ZVBvaW50Iik7CiAgICAgICAgICBibGFja1BvaW50ID0gcGFyYW1zLmdldEFycmF5KCJCbGFja1BvaW50Iik7CiAgICAgICAgICBnYW1tYSA9IHBhcmFtcy5nZXQoIkdhbW1hIik7CiAgICAgICAgICByZXR1cm4gbmV3IENhbEdyYXlDUyh3aGl0ZVBvaW50LCBibGFja1BvaW50LCBnYW1tYSk7CiAgICAgICAgY2FzZSAiQ2FsUkdCIjoKICAgICAgICAgIHBhcmFtcyA9IHhyZWYuZmV0Y2hJZlJlZihjc1sxXSk7CiAgICAgICAgICB3aGl0ZVBvaW50ID0gcGFyYW1zLmdldEFycmF5KCJXaGl0ZVBvaW50Iik7CiAgICAgICAgICBibGFja1BvaW50ID0gcGFyYW1zLmdldEFycmF5KCJCbGFja1BvaW50Iik7CiAgICAgICAgICBnYW1tYSA9IHBhcmFtcy5nZXRBcnJheSgiR2FtbWEiKTsKICAgICAgICAgIGNvbnN0IG1hdHJpeCA9IHBhcmFtcy5nZXRBcnJheSgiTWF0cml4Iik7CiAgICAgICAgICByZXR1cm4gbmV3IENhbFJHQkNTKHdoaXRlUG9pbnQsIGJsYWNrUG9pbnQsIGdhbW1hLCBtYXRyaXgpOwogICAgICAgIGNhc2UgIklDQ0Jhc2VkIjoKICAgICAgICAgIGNvbnN0IGlzUmVmID0gY3NbMV0gaW5zdGFuY2VvZiBSZWY7CiAgICAgICAgICBpZiAoaXNSZWYpIHsKICAgICAgICAgICAgY29uc3QgY2FjaGVkQ1MgPSBnbG9iYWxDb2xvclNwYWNlQ2FjaGUuZ2V0QnlSZWYoY3NbMV0pOwogICAgICAgICAgICBpZiAoY2FjaGVkQ1MpIHsKICAgICAgICAgICAgICByZXR1cm4gY2FjaGVkQ1M7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IHN0cmVhbSA9IHhyZWYuZmV0Y2hJZlJlZihjc1sxXSk7CiAgICAgICAgICBjb25zdCBkaWN0ID0gc3RyZWFtLmRpY3Q7CiAgICAgICAgICBudW1Db21wcyA9IGRpY3QuZ2V0KCJOIik7CiAgICAgICAgICBpZiAoSWNjQ29sb3JTcGFjZS5pc1VzYWJsZSkgewogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgIGNvbnN0IGljY0NTID0gbmV3IEljY0NvbG9yU3BhY2Uoc3RyZWFtLmdldEJ5dGVzKCksICJJQ0NCYXNlZCIsIG51bUNvbXBzKTsKICAgICAgICAgICAgICBpZiAoaXNSZWYpIHsKICAgICAgICAgICAgICAgIGdsb2JhbENvbG9yU3BhY2VDYWNoZS5zZXQobnVsbCwgY3NbMV0sIGljY0NTKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIGljY0NTOwogICAgICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBleDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgd2FybihgSUNDQmFzZWQgY29sb3Igc3BhY2UgKCR7Y3NbMV19KTogIiR7ZXh9Ii5gKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgY29uc3QgYWx0UmF3ID0gZGljdC5nZXRSYXcoIkFsdGVybmF0ZSIpOwogICAgICAgICAgaWYgKGFsdFJhdykgewogICAgICAgICAgICBjb25zdCBhbHRDUyA9IHRoaXMuI3N1YlBhcnNlKGFsdFJhdywgb3B0aW9ucyk7CiAgICAgICAgICAgIGlmIChhbHRDUy5udW1Db21wcyA9PT0gbnVtQ29tcHMpIHsKICAgICAgICAgICAgICByZXR1cm4gYWx0Q1M7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgd2FybigiSUNDQmFzZWQgY29sb3Igc3BhY2U6IElnbm9yaW5nIGluY29ycmVjdCAvQWx0ZXJuYXRlIGVudHJ5LiIpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKG51bUNvbXBzID09PSAxKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLmdyYXk7CiAgICAgICAgICB9IGVsc2UgaWYgKG51bUNvbXBzID09PSAzKSB7CiAgICAgICAgICAgIHJldHVybiB0aGlzLnJnYjsKICAgICAgICAgIH0gZWxzZSBpZiAobnVtQ29tcHMgPT09IDQpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuY215azsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIlBhdHRlcm4iOgogICAgICAgICAgYmFzZUNTID0gY3NbMV0gfHwgbnVsbDsKICAgICAgICAgIGlmIChiYXNlQ1MpIHsKICAgICAgICAgICAgYmFzZUNTID0gdGhpcy4jc3ViUGFyc2UoYmFzZUNTLCBvcHRpb25zKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBuZXcgUGF0dGVybkNTKGJhc2VDUyk7CiAgICAgICAgY2FzZSAiSSI6CiAgICAgICAgY2FzZSAiSW5kZXhlZCI6CiAgICAgICAgICBiYXNlQ1MgPSB0aGlzLiNzdWJQYXJzZShjc1sxXSwgb3B0aW9ucyk7CiAgICAgICAgICBjb25zdCBoaVZhbCA9IE1hdGhDbGFtcCh4cmVmLmZldGNoSWZSZWYoY3NbMl0pLCAwLCAyNTUpOwogICAgICAgICAgY29uc3QgbG9va3VwID0geHJlZi5mZXRjaElmUmVmKGNzWzNdKTsKICAgICAgICAgIHJldHVybiBuZXcgSW5kZXhlZENTKGJhc2VDUywgaGlWYWwsIGxvb2t1cCk7CiAgICAgICAgY2FzZSAiU2VwYXJhdGlvbiI6CiAgICAgICAgY2FzZSAiRGV2aWNlTiI6CiAgICAgICAgICBjb25zdCBuYW1lID0geHJlZi5mZXRjaElmUmVmKGNzWzFdKTsKICAgICAgICAgIG51bUNvbXBzID0gQXJyYXkuaXNBcnJheShuYW1lKSA/IG5hbWUubGVuZ3RoIDogMTsKICAgICAgICAgIGJhc2VDUyA9IHRoaXMuI3N1YlBhcnNlKGNzWzJdLCBvcHRpb25zKTsKICAgICAgICAgIGNvbnN0IHRpbnRGbiA9IHBkZkZ1bmN0aW9uRmFjdG9yeS5jcmVhdGUoY3NbM10pOwogICAgICAgICAgcmV0dXJuIG5ldyBBbHRlcm5hdGVDUyhudW1Db21wcywgYmFzZUNTLCB0aW50Rm4pOwogICAgICAgIGNhc2UgIkxhYiI6CiAgICAgICAgICBwYXJhbXMgPSB4cmVmLmZldGNoSWZSZWYoY3NbMV0pOwogICAgICAgICAgd2hpdGVQb2ludCA9IHBhcmFtcy5nZXRBcnJheSgiV2hpdGVQb2ludCIpOwogICAgICAgICAgYmxhY2tQb2ludCA9IHBhcmFtcy5nZXRBcnJheSgiQmxhY2tQb2ludCIpOwogICAgICAgICAgY29uc3QgcmFuZ2UgPSBwYXJhbXMuZ2V0QXJyYXkoIlJhbmdlIik7CiAgICAgICAgICByZXR1cm4gbmV3IExhYkNTKHdoaXRlUG9pbnQsIGJsYWNrUG9pbnQsIHJhbmdlKTsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgd2FybihgVW5pbXBsZW1lbnRlZCBDb2xvclNwYWNlIG9iamVjdDogJHttb2RlfWApOwogICAgICAgICAgcmV0dXJuIHRoaXMuZ3JheTsKICAgICAgfQogICAgfQogICAgd2FybihgVW5yZWNvZ25pemVkIENvbG9yU3BhY2Ugb2JqZWN0OiAke2NzfWApOwogICAgcmV0dXJuIHRoaXMuZ3JheTsKICB9CiAgc3RhdGljIGdldCBncmF5KCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiZ3JheSIsIG5ldyBEZXZpY2VHcmF5Q1MoKSk7CiAgfQogIHN0YXRpYyBnZXQgcmdiKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAicmdiIiwgbmV3IERldmljZVJnYkNTKCkpOwogIH0KICBzdGF0aWMgZ2V0IHJnYmEoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJyZ2JhIiwgbmV3IERldmljZVJnYmFDUygpKTsKICB9CiAgc3RhdGljIGdldCBjbXlrKCkgewogICAgaWYgKENteWtJQ0NCYXNlZENTLmlzVXNhYmxlKSB7CiAgICAgIHRyeSB7CiAgICAgICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiY215ayIsIG5ldyBDbXlrSUNDQmFzZWRDUygpKTsKICAgICAgfSBjYXRjaCB7CiAgICAgICAgd2FybigiQ01ZSyBmYWxsYmFjazogRGV2aWNlQ01ZSyIpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJjbXlrIiwgbmV3IERldmljZUNteWtDUygpKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2pwZy5qcwoKCgoKCgoKCgoKCgoKCmNsYXNzIEpwZWdFcnJvciBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZykgewogICAgc3VwZXIobXNnLCAiSnBlZ0Vycm9yIik7CiAgfQp9CmNsYXNzIEROTE1hcmtlckVycm9yIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobWVzc2FnZSwgc2NhbkxpbmVzKSB7CiAgICBzdXBlcihtZXNzYWdlLCAiRE5MTWFya2VyRXJyb3IiKTsKICAgIHRoaXMuc2NhbkxpbmVzID0gc2NhbkxpbmVzOwogIH0KfQpjbGFzcyBFT0lNYXJrZXJFcnJvciBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZykgewogICAgc3VwZXIobXNnLCAiRU9JTWFya2VyRXJyb3IiKTsKICB9Cn0KY29uc3QgZGN0WmlnWmFnID0gbmV3IFVpbnQ4QXJyYXkoWzAsIDEsIDgsIDE2LCA5LCAyLCAzLCAxMCwgMTcsIDI0LCAzMiwgMjUsIDE4LCAxMSwgNCwgNSwgMTIsIDE5LCAyNiwgMzMsIDQwLCA0OCwgNDEsIDM0LCAyNywgMjAsIDEzLCA2LCA3LCAxNCwgMjEsIDI4LCAzNSwgNDIsIDQ5LCA1NiwgNTcsIDUwLCA0MywgMzYsIDI5LCAyMiwgMTUsIDIzLCAzMCwgMzcsIDQ0LCA1MSwgNTgsIDU5LCA1MiwgNDUsIDM4LCAzMSwgMzksIDQ2LCA1MywgNjAsIDYxLCA1NCwgNDcsIDU1LCA2MiwgNjNdKTsKY29uc3QgZGN0Q29zMSA9IDQwMTc7CmNvbnN0IGRjdFNpbjEgPSA3OTk7CmNvbnN0IGRjdENvczMgPSAzNDA2Owpjb25zdCBkY3RTaW4zID0gMjI3NjsKY29uc3QgZGN0Q29zNiA9IDE1Njc7CmNvbnN0IGRjdFNpbjYgPSAzNzg0Owpjb25zdCBkY3RTcXJ0MiA9IDU3OTM7CmNvbnN0IGRjdFNxcnQxZDIgPSAyODk2OwpmdW5jdGlvbiBidWlsZEh1ZmZtYW5UYWJsZShjb2RlTGVuZ3RocywgdmFsdWVzKSB7CiAgbGV0IGsgPSAwLAogICAgaSwKICAgIGosCiAgICBsZW5ndGggPSAxNjsKICB3aGlsZSAobGVuZ3RoID4gMCAmJiAhY29kZUxlbmd0aHNbbGVuZ3RoIC0gMV0pIHsKICAgIGxlbmd0aC0tOwogIH0KICBjb25zdCBjb2RlID0gW3sKICAgIGNoaWxkcmVuOiBbXSwKICAgIGluZGV4OiAwCiAgfV07CiAgbGV0IHAgPSBjb2RlWzBdLAogICAgcTsKICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgIGZvciAoaiA9IDA7IGogPCBjb2RlTGVuZ3Roc1tpXTsgaisrKSB7CiAgICAgIHAgPSBjb2RlLnBvcCgpOwogICAgICBwLmNoaWxkcmVuW3AuaW5kZXhdID0gdmFsdWVzW2tdOwogICAgICB3aGlsZSAocC5pbmRleCA+IDApIHsKICAgICAgICBwID0gY29kZS5wb3AoKTsKICAgICAgfQogICAgICBwLmluZGV4Kys7CiAgICAgIGNvZGUucHVzaChwKTsKICAgICAgd2hpbGUgKGNvZGUubGVuZ3RoIDw9IGkpIHsKICAgICAgICBjb2RlLnB1c2gocSA9IHsKICAgICAgICAgIGNoaWxkcmVuOiBbXSwKICAgICAgICAgIGluZGV4OiAwCiAgICAgICAgfSk7CiAgICAgICAgcC5jaGlsZHJlbltwLmluZGV4XSA9IHEuY2hpbGRyZW47CiAgICAgICAgcCA9IHE7CiAgICAgIH0KICAgICAgaysrOwogICAgfQogICAgaWYgKGkgKyAxIDwgbGVuZ3RoKSB7CiAgICAgIGNvZGUucHVzaChxID0gewogICAgICAgIGNoaWxkcmVuOiBbXSwKICAgICAgICBpbmRleDogMAogICAgICB9KTsKICAgICAgcC5jaGlsZHJlbltwLmluZGV4XSA9IHEuY2hpbGRyZW47CiAgICAgIHAgPSBxOwogICAgfQogIH0KICByZXR1cm4gY29kZVswXS5jaGlsZHJlbjsKfQpmdW5jdGlvbiBnZXRCbG9ja0J1ZmZlck9mZnNldChjb21wb25lbnQsIHJvdywgY29sKSB7CiAgcmV0dXJuIDY0ICogKChjb21wb25lbnQuYmxvY2tzUGVyTGluZSArIDEpICogcm93ICsgY29sKTsKfQpmdW5jdGlvbiBkZWNvZGVTY2FuKGRhdGEsIG9mZnNldCwgZnJhbWUsIGNvbXBvbmVudHMsIHJlc2V0SW50ZXJ2YWwsIHNwZWN0cmFsU3RhcnQsIHNwZWN0cmFsRW5kLCBzdWNjZXNzaXZlUHJldiwgc3VjY2Vzc2l2ZSwgcGFyc2VETkxNYXJrZXIgPSBmYWxzZSkgewogIGNvbnN0IG1jdXNQZXJMaW5lID0gZnJhbWUubWN1c1BlckxpbmU7CiAgY29uc3QgcHJvZ3Jlc3NpdmUgPSBmcmFtZS5wcm9ncmVzc2l2ZTsKICBjb25zdCBzdGFydE9mZnNldCA9IG9mZnNldDsKICBsZXQgYml0c0RhdGEgPSAwLAogICAgYml0c0NvdW50ID0gMDsKICBmdW5jdGlvbiByZWFkQml0KCkgewogICAgaWYgKGJpdHNDb3VudCA+IDApIHsKICAgICAgYml0c0NvdW50LS07CiAgICAgIHJldHVybiBiaXRzRGF0YSA+PiBiaXRzQ291bnQgJiAxOwogICAgfQogICAgYml0c0RhdGEgPSBkYXRhW29mZnNldCsrXTsKICAgIGlmIChiaXRzRGF0YSA9PT0gMHhmZikgewogICAgICBjb25zdCBuZXh0Qnl0ZSA9IGRhdGFbb2Zmc2V0KytdOwogICAgICBpZiAobmV4dEJ5dGUpIHsKICAgICAgICBpZiAobmV4dEJ5dGUgPT09IDB4ZGMgJiYgcGFyc2VETkxNYXJrZXIpIHsKICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgY29uc3Qgc2NhbkxpbmVzID0gcmVhZFVpbnQxNihkYXRhLCBvZmZzZXQpOwogICAgICAgICAgb2Zmc2V0ICs9IDI7CiAgICAgICAgICBpZiAoc2NhbkxpbmVzID4gMCAmJiBzY2FuTGluZXMgIT09IGZyYW1lLnNjYW5MaW5lcykgewogICAgICAgICAgICB0aHJvdyBuZXcgRE5MTWFya2VyRXJyb3IoIkZvdW5kIEROTCBtYXJrZXIgKDB4RkZEQykgd2hpbGUgcGFyc2luZyBzY2FuIGRhdGEiLCBzY2FuTGluZXMpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAobmV4dEJ5dGUgPT09IDB4ZDkpIHsKICAgICAgICAgIGlmIChwYXJzZUROTE1hcmtlcikgewogICAgICAgICAgICBjb25zdCBtYXliZVNjYW5MaW5lcyA9IGJsb2NrUm93ICogKGZyYW1lLnByZWNpc2lvbiA9PT0gOCA/IDggOiAwKTsKICAgICAgICAgICAgaWYgKG1heWJlU2NhbkxpbmVzID4gMCAmJiBNYXRoLnJvdW5kKGZyYW1lLnNjYW5MaW5lcyAvIG1heWJlU2NhbkxpbmVzKSA+PSA1KSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEROTE1hcmtlckVycm9yKCJGb3VuZCBFT0kgbWFya2VyICgweEZGRDkpIHdoaWxlIHBhcnNpbmcgc2NhbiBkYXRhLCAiICsgInBvc3NpYmx5IGNhdXNlZCBieSBpbmNvcnJlY3QgYHNjYW5MaW5lc2AgcGFyYW1ldGVyIiwgbWF5YmVTY2FuTGluZXMpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICB0aHJvdyBuZXcgRU9JTWFya2VyRXJyb3IoIkZvdW5kIEVPSSBtYXJrZXIgKDB4RkZEOSkgd2hpbGUgcGFyc2luZyBzY2FuIGRhdGEiKTsKICAgICAgICB9CiAgICAgICAgdGhyb3cgbmV3IEpwZWdFcnJvcihgdW5leHBlY3RlZCBtYXJrZXIgJHsoYml0c0RhdGEgPDwgOCB8IG5leHRCeXRlKS50b1N0cmluZygxNil9YCk7CiAgICAgIH0KICAgIH0KICAgIGJpdHNDb3VudCA9IDc7CiAgICByZXR1cm4gYml0c0RhdGEgPj4+IDc7CiAgfQogIGZ1bmN0aW9uIGRlY29kZUh1ZmZtYW4odHJlZSkgewogICAgbGV0IG5vZGUgPSB0cmVlOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgbm9kZSA9IG5vZGVbcmVhZEJpdCgpXTsKICAgICAgc3dpdGNoICh0eXBlb2Ygbm9kZSkgewogICAgICAgIGNhc2UgIm51bWJlciI6CiAgICAgICAgICByZXR1cm4gbm9kZTsKICAgICAgICBjYXNlICJvYmplY3QiOgogICAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgdGhyb3cgbmV3IEpwZWdFcnJvcigiaW52YWxpZCBodWZmbWFuIHNlcXVlbmNlIik7CiAgICB9CiAgfQogIGZ1bmN0aW9uIHJlY2VpdmUobGVuZ3RoKSB7CiAgICBsZXQgbiA9IDA7CiAgICB3aGlsZSAobGVuZ3RoID4gMCkgewogICAgICBuID0gbiA8PCAxIHwgcmVhZEJpdCgpOwogICAgICBsZW5ndGgtLTsKICAgIH0KICAgIHJldHVybiBuOwogIH0KICBmdW5jdGlvbiByZWNlaXZlQW5kRXh0ZW5kKGxlbmd0aCkgewogICAgaWYgKGxlbmd0aCA9PT0gMSkgewogICAgICByZXR1cm4gcmVhZEJpdCgpID09PSAxID8gMSA6IC0xOwogICAgfQogICAgY29uc3QgbiA9IHJlY2VpdmUobGVuZ3RoKTsKICAgIGlmIChuID49IDEgPDwgbGVuZ3RoIC0gMSkgewogICAgICByZXR1cm4gbjsKICAgIH0KICAgIHJldHVybiBuICsgKC0xIDw8IGxlbmd0aCkgKyAxOwogIH0KICBmdW5jdGlvbiBkZWNvZGVCYXNlbGluZShjb21wb25lbnQsIGJsb2NrT2Zmc2V0KSB7CiAgICBjb25zdCB0ID0gZGVjb2RlSHVmZm1hbihjb21wb25lbnQuaHVmZm1hblRhYmxlREMpOwogICAgY29uc3QgZGlmZiA9IHQgPT09IDAgPyAwIDogcmVjZWl2ZUFuZEV4dGVuZCh0KTsKICAgIGNvbXBvbmVudC5ibG9ja0RhdGFbYmxvY2tPZmZzZXRdID0gY29tcG9uZW50LnByZWQgKz0gZGlmZjsKICAgIGxldCBrID0gMTsKICAgIHdoaWxlIChrIDwgNjQpIHsKICAgICAgY29uc3QgcnMgPSBkZWNvZGVIdWZmbWFuKGNvbXBvbmVudC5odWZmbWFuVGFibGVBQyk7CiAgICAgIGNvbnN0IHMgPSBycyAmIDE1LAogICAgICAgIHIgPSBycyA+PiA0OwogICAgICBpZiAocyA9PT0gMCkgewogICAgICAgIGlmIChyIDwgMTUpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBrICs9IDE2OwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGsgKz0gcjsKICAgICAgY29uc3QgeiA9IGRjdFppZ1phZ1trXTsKICAgICAgY29tcG9uZW50LmJsb2NrRGF0YVtibG9ja09mZnNldCArIHpdID0gcmVjZWl2ZUFuZEV4dGVuZChzKTsKICAgICAgaysrOwogICAgfQogIH0KICBmdW5jdGlvbiBkZWNvZGVEQ0ZpcnN0KGNvbXBvbmVudCwgYmxvY2tPZmZzZXQpIHsKICAgIGNvbnN0IHQgPSBkZWNvZGVIdWZmbWFuKGNvbXBvbmVudC5odWZmbWFuVGFibGVEQyk7CiAgICBjb25zdCBkaWZmID0gdCA9PT0gMCA/IDAgOiByZWNlaXZlQW5kRXh0ZW5kKHQpIDw8IHN1Y2Nlc3NpdmU7CiAgICBjb21wb25lbnQuYmxvY2tEYXRhW2Jsb2NrT2Zmc2V0XSA9IGNvbXBvbmVudC5wcmVkICs9IGRpZmY7CiAgfQogIGZ1bmN0aW9uIGRlY29kZURDU3VjY2Vzc2l2ZShjb21wb25lbnQsIGJsb2NrT2Zmc2V0KSB7CiAgICBjb21wb25lbnQuYmxvY2tEYXRhW2Jsb2NrT2Zmc2V0XSB8PSByZWFkQml0KCkgPDwgc3VjY2Vzc2l2ZTsKICB9CiAgbGV0IGVvYnJ1biA9IDA7CiAgZnVuY3Rpb24gZGVjb2RlQUNGaXJzdChjb21wb25lbnQsIGJsb2NrT2Zmc2V0KSB7CiAgICBpZiAoZW9icnVuID4gMCkgewogICAgICBlb2JydW4tLTsKICAgICAgcmV0dXJuOwogICAgfQogICAgbGV0IGsgPSBzcGVjdHJhbFN0YXJ0OwogICAgY29uc3QgZSA9IHNwZWN0cmFsRW5kOwogICAgd2hpbGUgKGsgPD0gZSkgewogICAgICBjb25zdCBycyA9IGRlY29kZUh1ZmZtYW4oY29tcG9uZW50Lmh1ZmZtYW5UYWJsZUFDKTsKICAgICAgY29uc3QgcyA9IHJzICYgMTUsCiAgICAgICAgciA9IHJzID4+IDQ7CiAgICAgIGlmIChzID09PSAwKSB7CiAgICAgICAgaWYgKHIgPCAxNSkgewogICAgICAgICAgZW9icnVuID0gcmVjZWl2ZShyKSArICgxIDw8IHIpIC0gMTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBrICs9IDE2OwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGsgKz0gcjsKICAgICAgY29uc3QgeiA9IGRjdFppZ1phZ1trXTsKICAgICAgY29tcG9uZW50LmJsb2NrRGF0YVtibG9ja09mZnNldCArIHpdID0gcmVjZWl2ZUFuZEV4dGVuZChzKSAqICgxIDw8IHN1Y2Nlc3NpdmUpOwogICAgICBrKys7CiAgICB9CiAgfQogIGxldCBzdWNjZXNzaXZlQUNTdGF0ZSA9IDAsCiAgICBzdWNjZXNzaXZlQUNOZXh0VmFsdWU7CiAgZnVuY3Rpb24gZGVjb2RlQUNTdWNjZXNzaXZlKGNvbXBvbmVudCwgYmxvY2tPZmZzZXQpIHsKICAgIGxldCBrID0gc3BlY3RyYWxTdGFydDsKICAgIGNvbnN0IGUgPSBzcGVjdHJhbEVuZDsKICAgIGxldCByID0gMDsKICAgIGxldCBzOwogICAgbGV0IHJzOwogICAgd2hpbGUgKGsgPD0gZSkgewogICAgICBjb25zdCBvZmZzZXRaID0gYmxvY2tPZmZzZXQgKyBkY3RaaWdaYWdba107CiAgICAgIGNvbnN0IHNpZ24gPSBjb21wb25lbnQuYmxvY2tEYXRhW29mZnNldFpdIDwgMCA/IC0xIDogMTsKICAgICAgc3dpdGNoIChzdWNjZXNzaXZlQUNTdGF0ZSkgewogICAgICAgIGNhc2UgMDoKICAgICAgICAgIHJzID0gZGVjb2RlSHVmZm1hbihjb21wb25lbnQuaHVmZm1hblRhYmxlQUMpOwogICAgICAgICAgcyA9IHJzICYgMTU7CiAgICAgICAgICByID0gcnMgPj4gNDsKICAgICAgICAgIGlmIChzID09PSAwKSB7CiAgICAgICAgICAgIGlmIChyIDwgMTUpIHsKICAgICAgICAgICAgICBlb2JydW4gPSByZWNlaXZlKHIpICsgKDEgPDwgcik7CiAgICAgICAgICAgICAgc3VjY2Vzc2l2ZUFDU3RhdGUgPSA0OwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHIgPSAxNjsKICAgICAgICAgICAgICBzdWNjZXNzaXZlQUNTdGF0ZSA9IDE7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGlmIChzICE9PSAxKSB7CiAgICAgICAgICAgICAgdGhyb3cgbmV3IEpwZWdFcnJvcigiaW52YWxpZCBBQ24gZW5jb2RpbmciKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdWNjZXNzaXZlQUNOZXh0VmFsdWUgPSByZWNlaXZlQW5kRXh0ZW5kKHMpOwogICAgICAgICAgICBzdWNjZXNzaXZlQUNTdGF0ZSA9IHIgPyAyIDogMzsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIGNhc2UgMToKICAgICAgICBjYXNlIDI6CiAgICAgICAgICBpZiAoY29tcG9uZW50LmJsb2NrRGF0YVtvZmZzZXRaXSkgewogICAgICAgICAgICBjb21wb25lbnQuYmxvY2tEYXRhW29mZnNldFpdICs9IHNpZ24gKiAocmVhZEJpdCgpIDw8IHN1Y2Nlc3NpdmUpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgci0tOwogICAgICAgICAgICBpZiAociA9PT0gMCkgewogICAgICAgICAgICAgIHN1Y2Nlc3NpdmVBQ1N0YXRlID0gc3VjY2Vzc2l2ZUFDU3RhdGUgPT09IDIgPyAzIDogMDsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAzOgogICAgICAgICAgaWYgKGNvbXBvbmVudC5ibG9ja0RhdGFbb2Zmc2V0Wl0pIHsKICAgICAgICAgICAgY29tcG9uZW50LmJsb2NrRGF0YVtvZmZzZXRaXSArPSBzaWduICogKHJlYWRCaXQoKSA8PCBzdWNjZXNzaXZlKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGNvbXBvbmVudC5ibG9ja0RhdGFbb2Zmc2V0Wl0gPSBzdWNjZXNzaXZlQUNOZXh0VmFsdWUgPDwgc3VjY2Vzc2l2ZTsKICAgICAgICAgICAgc3VjY2Vzc2l2ZUFDU3RhdGUgPSAwOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA0OgogICAgICAgICAgaWYgKGNvbXBvbmVudC5ibG9ja0RhdGFbb2Zmc2V0Wl0pIHsKICAgICAgICAgICAgY29tcG9uZW50LmJsb2NrRGF0YVtvZmZzZXRaXSArPSBzaWduICogKHJlYWRCaXQoKSA8PCBzdWNjZXNzaXZlKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGsrKzsKICAgIH0KICAgIGlmIChzdWNjZXNzaXZlQUNTdGF0ZSA9PT0gNCkgewogICAgICBlb2JydW4tLTsKICAgICAgaWYgKGVvYnJ1biA9PT0gMCkgewogICAgICAgIHN1Y2Nlc3NpdmVBQ1N0YXRlID0gMDsKICAgICAgfQogICAgfQogIH0KICBsZXQgYmxvY2tSb3cgPSAwOwogIGZ1bmN0aW9uIGRlY29kZU1jdShjb21wb25lbnQsIGRlY29kZSwgbWN1LCByb3csIGNvbCkgewogICAgY29uc3QgbWN1Um93ID0gbWN1IC8gbWN1c1BlckxpbmUgfCAwOwogICAgY29uc3QgbWN1Q29sID0gbWN1ICUgbWN1c1BlckxpbmU7CiAgICBibG9ja1JvdyA9IG1jdVJvdyAqIGNvbXBvbmVudC52ICsgcm93OwogICAgY29uc3QgYmxvY2tDb2wgPSBtY3VDb2wgKiBjb21wb25lbnQuaCArIGNvbDsKICAgIGNvbnN0IGJsb2NrT2Zmc2V0ID0gZ2V0QmxvY2tCdWZmZXJPZmZzZXQoY29tcG9uZW50LCBibG9ja1JvdywgYmxvY2tDb2wpOwogICAgZGVjb2RlKGNvbXBvbmVudCwgYmxvY2tPZmZzZXQpOwogIH0KICBmdW5jdGlvbiBkZWNvZGVCbG9jayhjb21wb25lbnQsIGRlY29kZSwgbWN1KSB7CiAgICBibG9ja1JvdyA9IG1jdSAvIGNvbXBvbmVudC5ibG9ja3NQZXJMaW5lIHwgMDsKICAgIGNvbnN0IGJsb2NrQ29sID0gbWN1ICUgY29tcG9uZW50LmJsb2Nrc1BlckxpbmU7CiAgICBjb25zdCBibG9ja09mZnNldCA9IGdldEJsb2NrQnVmZmVyT2Zmc2V0KGNvbXBvbmVudCwgYmxvY2tSb3csIGJsb2NrQ29sKTsKICAgIGRlY29kZShjb21wb25lbnQsIGJsb2NrT2Zmc2V0KTsKICB9CiAgY29uc3QgY29tcG9uZW50c0xlbmd0aCA9IGNvbXBvbmVudHMubGVuZ3RoOwogIGxldCBjb21wb25lbnQsIGksIGosIGssIG47CiAgbGV0IGRlY29kZUZuOwogIGlmIChwcm9ncmVzc2l2ZSkgewogICAgaWYgKHNwZWN0cmFsU3RhcnQgPT09IDApIHsKICAgICAgZGVjb2RlRm4gPSBzdWNjZXNzaXZlUHJldiA9PT0gMCA/IGRlY29kZURDRmlyc3QgOiBkZWNvZGVEQ1N1Y2Nlc3NpdmU7CiAgICB9IGVsc2UgewogICAgICBkZWNvZGVGbiA9IHN1Y2Nlc3NpdmVQcmV2ID09PSAwID8gZGVjb2RlQUNGaXJzdCA6IGRlY29kZUFDU3VjY2Vzc2l2ZTsKICAgIH0KICB9IGVsc2UgewogICAgZGVjb2RlRm4gPSBkZWNvZGVCYXNlbGluZTsKICB9CiAgbGV0IG1jdSA9IDAsCiAgICBmaWxlTWFya2VyOwogIGNvbnN0IG1jdUV4cGVjdGVkID0gY29tcG9uZW50c0xlbmd0aCA9PT0gMSA/IGNvbXBvbmVudHNbMF0uYmxvY2tzUGVyTGluZSAqIGNvbXBvbmVudHNbMF0uYmxvY2tzUGVyQ29sdW1uIDogbWN1c1BlckxpbmUgKiBmcmFtZS5tY3VzUGVyQ29sdW1uOwogIGxldCBoLCB2OwogIHdoaWxlIChtY3UgPD0gbWN1RXhwZWN0ZWQpIHsKICAgIGNvbnN0IG1jdVRvUmVhZCA9IHJlc2V0SW50ZXJ2YWwgPyBNYXRoLm1pbihtY3VFeHBlY3RlZCAtIG1jdSwgcmVzZXRJbnRlcnZhbCkgOiBtY3VFeHBlY3RlZDsKICAgIGlmIChtY3VUb1JlYWQgPiAwKSB7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBjb21wb25lbnRzTGVuZ3RoOyBpKyspIHsKICAgICAgICBjb21wb25lbnRzW2ldLnByZWQgPSAwOwogICAgICB9CiAgICAgIGVvYnJ1biA9IDA7CiAgICAgIGlmIChjb21wb25lbnRzTGVuZ3RoID09PSAxKSB7CiAgICAgICAgY29tcG9uZW50ID0gY29tcG9uZW50c1swXTsKICAgICAgICBmb3IgKG4gPSAwOyBuIDwgbWN1VG9SZWFkOyBuKyspIHsKICAgICAgICAgIGRlY29kZUJsb2NrKGNvbXBvbmVudCwgZGVjb2RlRm4sIG1jdSk7CiAgICAgICAgICBtY3UrKzsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yIChuID0gMDsgbiA8IG1jdVRvUmVhZDsgbisrKSB7CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29tcG9uZW50c0xlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGNvbXBvbmVudCA9IGNvbXBvbmVudHNbaV07CiAgICAgICAgICAgIGggPSBjb21wb25lbnQuaDsKICAgICAgICAgICAgdiA9IGNvbXBvbmVudC52OwogICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgdjsgaisrKSB7CiAgICAgICAgICAgICAgZm9yIChrID0gMDsgayA8IGg7IGsrKykgewogICAgICAgICAgICAgICAgZGVjb2RlTWN1KGNvbXBvbmVudCwgZGVjb2RlRm4sIG1jdSwgaiwgayk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBtY3UrKzsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGJpdHNDb3VudCA9IDA7CiAgICBmaWxlTWFya2VyID0gZmluZE5leHRGaWxlTWFya2VyKGRhdGEsIG9mZnNldCk7CiAgICBpZiAoIWZpbGVNYXJrZXIpIHsKICAgICAgYnJlYWs7CiAgICB9CiAgICBpZiAoZmlsZU1hcmtlci5pbnZhbGlkKSB7CiAgICAgIGNvbnN0IHBhcnRpYWxNc2cgPSBtY3VUb1JlYWQgPiAwID8gInVuZXhwZWN0ZWQiIDogImV4Y2Vzc2l2ZSI7CiAgICAgIHdhcm4oYGRlY29kZVNjYW4gLSAke3BhcnRpYWxNc2d9IE1DVSBkYXRhLCBjdXJyZW50IG1hcmtlciBpczogJHtmaWxlTWFya2VyLmludmFsaWR9YCk7CiAgICAgIG9mZnNldCA9IGZpbGVNYXJrZXIub2Zmc2V0OwogICAgfQogICAgaWYgKGZpbGVNYXJrZXIubWFya2VyID49IDB4ZmZkMCAmJiBmaWxlTWFya2VyLm1hcmtlciA8PSAweGZmZDcpIHsKICAgICAgb2Zmc2V0ICs9IDI7CiAgICB9IGVsc2UgewogICAgICBicmVhazsKICAgIH0KICB9CiAgcmV0dXJuIG9mZnNldCAtIHN0YXJ0T2Zmc2V0Owp9CmZ1bmN0aW9uIHF1YW50aXplQW5kSW52ZXJzZShjb21wb25lbnQsIGJsb2NrQnVmZmVyT2Zmc2V0LCBwKSB7CiAgY29uc3QgcXQgPSBjb21wb25lbnQucXVhbnRpemF0aW9uVGFibGUsCiAgICBibG9ja0RhdGEgPSBjb21wb25lbnQuYmxvY2tEYXRhOwogIGxldCB2MCwgdjEsIHYyLCB2MywgdjQsIHY1LCB2Niwgdjc7CiAgbGV0IHAwLCBwMSwgcDIsIHAzLCBwNCwgcDUsIHA2LCBwNzsKICBsZXQgdDsKICBpZiAoIXF0KSB7CiAgICB0aHJvdyBuZXcgSnBlZ0Vycm9yKCJtaXNzaW5nIHJlcXVpcmVkIFF1YW50aXphdGlvbiBUYWJsZS4iKTsKICB9CiAgZm9yIChsZXQgcm93ID0gMDsgcm93IDwgNjQ7IHJvdyArPSA4KSB7CiAgICBwMCA9IGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIHJvd107CiAgICBwMSA9IGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIHJvdyArIDFdOwogICAgcDIgPSBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyByb3cgKyAyXTsKICAgIHAzID0gYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgcm93ICsgM107CiAgICBwNCA9IGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIHJvdyArIDRdOwogICAgcDUgPSBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyByb3cgKyA1XTsKICAgIHA2ID0gYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgcm93ICsgNl07CiAgICBwNyA9IGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIHJvdyArIDddOwogICAgcDAgKj0gcXRbcm93XTsKICAgIGlmICgocDEgfCBwMiB8IHAzIHwgcDQgfCBwNSB8IHA2IHwgcDcpID09PSAwKSB7CiAgICAgIHQgPSBkY3RTcXJ0MiAqIHAwICsgNTEyID4+IDEwOwogICAgICBwW3Jvd10gPSB0OwogICAgICBwW3JvdyArIDFdID0gdDsKICAgICAgcFtyb3cgKyAyXSA9IHQ7CiAgICAgIHBbcm93ICsgM10gPSB0OwogICAgICBwW3JvdyArIDRdID0gdDsKICAgICAgcFtyb3cgKyA1XSA9IHQ7CiAgICAgIHBbcm93ICsgNl0gPSB0OwogICAgICBwW3JvdyArIDddID0gdDsKICAgICAgY29udGludWU7CiAgICB9CiAgICBwMSAqPSBxdFtyb3cgKyAxXTsKICAgIHAyICo9IHF0W3JvdyArIDJdOwogICAgcDMgKj0gcXRbcm93ICsgM107CiAgICBwNCAqPSBxdFtyb3cgKyA0XTsKICAgIHA1ICo9IHF0W3JvdyArIDVdOwogICAgcDYgKj0gcXRbcm93ICsgNl07CiAgICBwNyAqPSBxdFtyb3cgKyA3XTsKICAgIHYwID0gZGN0U3FydDIgKiBwMCArIDEyOCA+PiA4OwogICAgdjEgPSBkY3RTcXJ0MiAqIHA0ICsgMTI4ID4+IDg7CiAgICB2MiA9IHAyOwogICAgdjMgPSBwNjsKICAgIHY0ID0gZGN0U3FydDFkMiAqIChwMSAtIHA3KSArIDEyOCA+PiA4OwogICAgdjcgPSBkY3RTcXJ0MWQyICogKHAxICsgcDcpICsgMTI4ID4+IDg7CiAgICB2NSA9IHAzIDw8IDQ7CiAgICB2NiA9IHA1IDw8IDQ7CiAgICB2MCA9IHYwICsgdjEgKyAxID4+IDE7CiAgICB2MSA9IHYwIC0gdjE7CiAgICB0ID0gdjIgKiBkY3RTaW42ICsgdjMgKiBkY3RDb3M2ICsgMTI4ID4+IDg7CiAgICB2MiA9IHYyICogZGN0Q29zNiAtIHYzICogZGN0U2luNiArIDEyOCA+PiA4OwogICAgdjMgPSB0OwogICAgdjQgPSB2NCArIHY2ICsgMSA+PiAxOwogICAgdjYgPSB2NCAtIHY2OwogICAgdjcgPSB2NyArIHY1ICsgMSA+PiAxOwogICAgdjUgPSB2NyAtIHY1OwogICAgdjAgPSB2MCArIHYzICsgMSA+PiAxOwogICAgdjMgPSB2MCAtIHYzOwogICAgdjEgPSB2MSArIHYyICsgMSA+PiAxOwogICAgdjIgPSB2MSAtIHYyOwogICAgdCA9IHY0ICogZGN0U2luMyArIHY3ICogZGN0Q29zMyArIDIwNDggPj4gMTI7CiAgICB2NCA9IHY0ICogZGN0Q29zMyAtIHY3ICogZGN0U2luMyArIDIwNDggPj4gMTI7CiAgICB2NyA9IHQ7CiAgICB0ID0gdjUgKiBkY3RTaW4xICsgdjYgKiBkY3RDb3MxICsgMjA0OCA+PiAxMjsKICAgIHY1ID0gdjUgKiBkY3RDb3MxIC0gdjYgKiBkY3RTaW4xICsgMjA0OCA+PiAxMjsKICAgIHY2ID0gdDsKICAgIHBbcm93XSA9IHYwICsgdjc7CiAgICBwW3JvdyArIDddID0gdjAgLSB2NzsKICAgIHBbcm93ICsgMV0gPSB2MSArIHY2OwogICAgcFtyb3cgKyA2XSA9IHYxIC0gdjY7CiAgICBwW3JvdyArIDJdID0gdjIgKyB2NTsKICAgIHBbcm93ICsgNV0gPSB2MiAtIHY1OwogICAgcFtyb3cgKyAzXSA9IHYzICsgdjQ7CiAgICBwW3JvdyArIDRdID0gdjMgLSB2NDsKICB9CiAgZm9yIChsZXQgY29sID0gMDsgY29sIDwgODsgKytjb2wpIHsKICAgIHAwID0gcFtjb2xdOwogICAgcDEgPSBwW2NvbCArIDhdOwogICAgcDIgPSBwW2NvbCArIDE2XTsKICAgIHAzID0gcFtjb2wgKyAyNF07CiAgICBwNCA9IHBbY29sICsgMzJdOwogICAgcDUgPSBwW2NvbCArIDQwXTsKICAgIHA2ID0gcFtjb2wgKyA0OF07CiAgICBwNyA9IHBbY29sICsgNTZdOwogICAgaWYgKChwMSB8IHAyIHwgcDMgfCBwNCB8IHA1IHwgcDYgfCBwNykgPT09IDApIHsKICAgICAgdCA9IGRjdFNxcnQyICogcDAgKyA4MTkyID4+IDE0OwogICAgICBpZiAodCA8IC0yMDQwKSB7CiAgICAgICAgdCA9IDA7CiAgICAgIH0gZWxzZSBpZiAodCA+PSAyMDI0KSB7CiAgICAgICAgdCA9IDI1NTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0ID0gdCArIDIwNTYgPj4gNDsKICAgICAgfQogICAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2xdID0gdDsKICAgICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sICsgOF0gPSB0OwogICAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyAxNl0gPSB0OwogICAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyAyNF0gPSB0OwogICAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyAzMl0gPSB0OwogICAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyA0MF0gPSB0OwogICAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyA0OF0gPSB0OwogICAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyA1Nl0gPSB0OwogICAgICBjb250aW51ZTsKICAgIH0KICAgIHYwID0gZGN0U3FydDIgKiBwMCArIDIwNDggPj4gMTI7CiAgICB2MSA9IGRjdFNxcnQyICogcDQgKyAyMDQ4ID4+IDEyOwogICAgdjIgPSBwMjsKICAgIHYzID0gcDY7CiAgICB2NCA9IGRjdFNxcnQxZDIgKiAocDEgLSBwNykgKyAyMDQ4ID4+IDEyOwogICAgdjcgPSBkY3RTcXJ0MWQyICogKHAxICsgcDcpICsgMjA0OCA+PiAxMjsKICAgIHY1ID0gcDM7CiAgICB2NiA9IHA1OwogICAgdjAgPSAodjAgKyB2MSArIDEgPj4gMSkgKyA0MTEyOwogICAgdjEgPSB2MCAtIHYxOwogICAgdCA9IHYyICogZGN0U2luNiArIHYzICogZGN0Q29zNiArIDIwNDggPj4gMTI7CiAgICB2MiA9IHYyICogZGN0Q29zNiAtIHYzICogZGN0U2luNiArIDIwNDggPj4gMTI7CiAgICB2MyA9IHQ7CiAgICB2NCA9IHY0ICsgdjYgKyAxID4+IDE7CiAgICB2NiA9IHY0IC0gdjY7CiAgICB2NyA9IHY3ICsgdjUgKyAxID4+IDE7CiAgICB2NSA9IHY3IC0gdjU7CiAgICB2MCA9IHYwICsgdjMgKyAxID4+IDE7CiAgICB2MyA9IHYwIC0gdjM7CiAgICB2MSA9IHYxICsgdjIgKyAxID4+IDE7CiAgICB2MiA9IHYxIC0gdjI7CiAgICB0ID0gdjQgKiBkY3RTaW4zICsgdjcgKiBkY3RDb3MzICsgMjA0OCA+PiAxMjsKICAgIHY0ID0gdjQgKiBkY3RDb3MzIC0gdjcgKiBkY3RTaW4zICsgMjA0OCA+PiAxMjsKICAgIHY3ID0gdDsKICAgIHQgPSB2NSAqIGRjdFNpbjEgKyB2NiAqIGRjdENvczEgKyAyMDQ4ID4+IDEyOwogICAgdjUgPSB2NSAqIGRjdENvczEgLSB2NiAqIGRjdFNpbjEgKyAyMDQ4ID4+IDEyOwogICAgdjYgPSB0OwogICAgcDAgPSB2MCArIHY3OwogICAgcDcgPSB2MCAtIHY3OwogICAgcDEgPSB2MSArIHY2OwogICAgcDYgPSB2MSAtIHY2OwogICAgcDIgPSB2MiArIHY1OwogICAgcDUgPSB2MiAtIHY1OwogICAgcDMgPSB2MyArIHY0OwogICAgcDQgPSB2MyAtIHY0OwogICAgaWYgKHAwIDwgMTYpIHsKICAgICAgcDAgPSAwOwogICAgfSBlbHNlIGlmIChwMCA+PSA0MDgwKSB7CiAgICAgIHAwID0gMjU1OwogICAgfSBlbHNlIHsKICAgICAgcDAgPj49IDQ7CiAgICB9CiAgICBpZiAocDEgPCAxNikgewogICAgICBwMSA9IDA7CiAgICB9IGVsc2UgaWYgKHAxID49IDQwODApIHsKICAgICAgcDEgPSAyNTU7CiAgICB9IGVsc2UgewogICAgICBwMSA+Pj0gNDsKICAgIH0KICAgIGlmIChwMiA8IDE2KSB7CiAgICAgIHAyID0gMDsKICAgIH0gZWxzZSBpZiAocDIgPj0gNDA4MCkgewogICAgICBwMiA9IDI1NTsKICAgIH0gZWxzZSB7CiAgICAgIHAyID4+PSA0OwogICAgfQogICAgaWYgKHAzIDwgMTYpIHsKICAgICAgcDMgPSAwOwogICAgfSBlbHNlIGlmIChwMyA+PSA0MDgwKSB7CiAgICAgIHAzID0gMjU1OwogICAgfSBlbHNlIHsKICAgICAgcDMgPj49IDQ7CiAgICB9CiAgICBpZiAocDQgPCAxNikgewogICAgICBwNCA9IDA7CiAgICB9IGVsc2UgaWYgKHA0ID49IDQwODApIHsKICAgICAgcDQgPSAyNTU7CiAgICB9IGVsc2UgewogICAgICBwNCA+Pj0gNDsKICAgIH0KICAgIGlmIChwNSA8IDE2KSB7CiAgICAgIHA1ID0gMDsKICAgIH0gZWxzZSBpZiAocDUgPj0gNDA4MCkgewogICAgICBwNSA9IDI1NTsKICAgIH0gZWxzZSB7CiAgICAgIHA1ID4+PSA0OwogICAgfQogICAgaWYgKHA2IDwgMTYpIHsKICAgICAgcDYgPSAwOwogICAgfSBlbHNlIGlmIChwNiA+PSA0MDgwKSB7CiAgICAgIHA2ID0gMjU1OwogICAgfSBlbHNlIHsKICAgICAgcDYgPj49IDQ7CiAgICB9CiAgICBpZiAocDcgPCAxNikgewogICAgICBwNyA9IDA7CiAgICB9IGVsc2UgaWYgKHA3ID49IDQwODApIHsKICAgICAgcDcgPSAyNTU7CiAgICB9IGVsc2UgewogICAgICBwNyA+Pj0gNDsKICAgIH0KICAgIGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIGNvbF0gPSBwMDsKICAgIGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIGNvbCArIDhdID0gcDE7CiAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyAxNl0gPSBwMjsKICAgIGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIGNvbCArIDI0XSA9IHAzOwogICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sICsgMzJdID0gcDQ7CiAgICBibG9ja0RhdGFbYmxvY2tCdWZmZXJPZmZzZXQgKyBjb2wgKyA0MF0gPSBwNTsKICAgIGJsb2NrRGF0YVtibG9ja0J1ZmZlck9mZnNldCArIGNvbCArIDQ4XSA9IHA2OwogICAgYmxvY2tEYXRhW2Jsb2NrQnVmZmVyT2Zmc2V0ICsgY29sICsgNTZdID0gcDc7CiAgfQp9CmZ1bmN0aW9uIGJ1aWxkQ29tcG9uZW50RGF0YShmcmFtZSwgY29tcG9uZW50KSB7CiAgY29uc3QgYmxvY2tzUGVyTGluZSA9IGNvbXBvbmVudC5ibG9ja3NQZXJMaW5lOwogIGNvbnN0IGJsb2Nrc1BlckNvbHVtbiA9IGNvbXBvbmVudC5ibG9ja3NQZXJDb2x1bW47CiAgY29uc3QgY29tcHV0YXRpb25CdWZmZXIgPSBuZXcgSW50MTZBcnJheSg2NCk7CiAgZm9yIChsZXQgYmxvY2tSb3cgPSAwOyBibG9ja1JvdyA8IGJsb2Nrc1BlckNvbHVtbjsgYmxvY2tSb3crKykgewogICAgZm9yIChsZXQgYmxvY2tDb2wgPSAwOyBibG9ja0NvbCA8IGJsb2Nrc1BlckxpbmU7IGJsb2NrQ29sKyspIHsKICAgICAgY29uc3Qgb2Zmc2V0ID0gZ2V0QmxvY2tCdWZmZXJPZmZzZXQoY29tcG9uZW50LCBibG9ja1JvdywgYmxvY2tDb2wpOwogICAgICBxdWFudGl6ZUFuZEludmVyc2UoY29tcG9uZW50LCBvZmZzZXQsIGNvbXB1dGF0aW9uQnVmZmVyKTsKICAgIH0KICB9CiAgcmV0dXJuIGNvbXBvbmVudC5ibG9ja0RhdGE7Cn0KZnVuY3Rpb24gZmluZE5leHRGaWxlTWFya2VyKGRhdGEsIGN1cnJlbnRQb3MsIHN0YXJ0UG9zID0gY3VycmVudFBvcykgewogIGNvbnN0IG1heFBvcyA9IGRhdGEubGVuZ3RoIC0gMTsKICBsZXQgbmV3UG9zID0gc3RhcnRQb3MgPCBjdXJyZW50UG9zID8gc3RhcnRQb3MgOiBjdXJyZW50UG9zOwogIGlmIChjdXJyZW50UG9zID49IG1heFBvcykgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGNvbnN0IGN1cnJlbnRNYXJrZXIgPSByZWFkVWludDE2KGRhdGEsIGN1cnJlbnRQb3MpOwogIGlmIChjdXJyZW50TWFya2VyID49IDB4ZmZjMCAmJiBjdXJyZW50TWFya2VyIDw9IDB4ZmZmZSkgewogICAgcmV0dXJuIHsKICAgICAgaW52YWxpZDogbnVsbCwKICAgICAgbWFya2VyOiBjdXJyZW50TWFya2VyLAogICAgICBvZmZzZXQ6IGN1cnJlbnRQb3MKICAgIH07CiAgfQogIGxldCBuZXdNYXJrZXIgPSByZWFkVWludDE2KGRhdGEsIG5ld1Bvcyk7CiAgd2hpbGUgKCEobmV3TWFya2VyID49IDB4ZmZjMCAmJiBuZXdNYXJrZXIgPD0gMHhmZmZlKSkgewogICAgaWYgKCsrbmV3UG9zID49IG1heFBvcykgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIG5ld01hcmtlciA9IHJlYWRVaW50MTYoZGF0YSwgbmV3UG9zKTsKICB9CiAgcmV0dXJuIHsKICAgIGludmFsaWQ6IGN1cnJlbnRNYXJrZXIudG9TdHJpbmcoMTYpLAogICAgbWFya2VyOiBuZXdNYXJrZXIsCiAgICBvZmZzZXQ6IG5ld1BvcwogIH07Cn0KZnVuY3Rpb24gcHJlcGFyZUNvbXBvbmVudHMoZnJhbWUpIHsKICBjb25zdCBtY3VzUGVyTGluZSA9IE1hdGguY2VpbChmcmFtZS5zYW1wbGVzUGVyTGluZSAvIDggLyBmcmFtZS5tYXhIKTsKICBjb25zdCBtY3VzUGVyQ29sdW1uID0gTWF0aC5jZWlsKGZyYW1lLnNjYW5MaW5lcyAvIDggLyBmcmFtZS5tYXhWKTsKICBmb3IgKGNvbnN0IGNvbXBvbmVudCBvZiBmcmFtZS5jb21wb25lbnRzKSB7CiAgICBjb25zdCBibG9ja3NQZXJMaW5lID0gTWF0aC5jZWlsKE1hdGguY2VpbChmcmFtZS5zYW1wbGVzUGVyTGluZSAvIDgpICogY29tcG9uZW50LmggLyBmcmFtZS5tYXhIKTsKICAgIGNvbnN0IGJsb2Nrc1BlckNvbHVtbiA9IE1hdGguY2VpbChNYXRoLmNlaWwoZnJhbWUuc2NhbkxpbmVzIC8gOCkgKiBjb21wb25lbnQudiAvIGZyYW1lLm1heFYpOwogICAgY29uc3QgYmxvY2tzUGVyTGluZUZvck1jdSA9IG1jdXNQZXJMaW5lICogY29tcG9uZW50Lmg7CiAgICBjb25zdCBibG9ja3NQZXJDb2x1bW5Gb3JNY3UgPSBtY3VzUGVyQ29sdW1uICogY29tcG9uZW50LnY7CiAgICBjb25zdCBibG9ja3NCdWZmZXJTaXplID0gNjQgKiBibG9ja3NQZXJDb2x1bW5Gb3JNY3UgKiAoYmxvY2tzUGVyTGluZUZvck1jdSArIDEpOwogICAgY29tcG9uZW50LmJsb2NrRGF0YSA9IG5ldyBJbnQxNkFycmF5KGJsb2Nrc0J1ZmZlclNpemUpOwogICAgY29tcG9uZW50LmJsb2Nrc1BlckxpbmUgPSBibG9ja3NQZXJMaW5lOwogICAgY29tcG9uZW50LmJsb2Nrc1BlckNvbHVtbiA9IGJsb2Nrc1BlckNvbHVtbjsKICB9CiAgZnJhbWUubWN1c1BlckxpbmUgPSBtY3VzUGVyTGluZTsKICBmcmFtZS5tY3VzUGVyQ29sdW1uID0gbWN1c1BlckNvbHVtbjsKfQpmdW5jdGlvbiByZWFkRGF0YUJsb2NrKGRhdGEsIG9mZnNldCkgewogIGNvbnN0IGxlbmd0aCA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KTsKICBvZmZzZXQgKz0gMjsKICBsZXQgZW5kT2Zmc2V0ID0gb2Zmc2V0ICsgbGVuZ3RoIC0gMjsKICBjb25zdCBmaWxlTWFya2VyID0gZmluZE5leHRGaWxlTWFya2VyKGRhdGEsIGVuZE9mZnNldCwgb2Zmc2V0KTsKICBpZiAoZmlsZU1hcmtlcj8uaW52YWxpZCkgewogICAgd2FybigicmVhZERhdGFCbG9jayAtIGluY29ycmVjdCBsZW5ndGgsIGN1cnJlbnQgbWFya2VyIGlzOiAiICsgZmlsZU1hcmtlci5pbnZhbGlkKTsKICAgIGVuZE9mZnNldCA9IGZpbGVNYXJrZXIub2Zmc2V0OwogIH0KICBjb25zdCBhcnJheSA9IGRhdGEuc3ViYXJyYXkob2Zmc2V0LCBlbmRPZmZzZXQpOwogIHJldHVybiB7CiAgICBhcHBEYXRhOiBhcnJheSwKICAgIG9sZE9mZnNldDogb2Zmc2V0LAogICAgbmV3T2Zmc2V0OiBvZmZzZXQgKyBhcnJheS5sZW5ndGgKICB9Owp9CmZ1bmN0aW9uIHNraXBEYXRhKGRhdGEsIG9mZnNldCkgewogIGNvbnN0IGxlbmd0aCA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KTsKICBvZmZzZXQgKz0gMjsKICBjb25zdCBlbmRPZmZzZXQgPSBvZmZzZXQgKyBsZW5ndGggLSAyOwogIGNvbnN0IGZpbGVNYXJrZXIgPSBmaW5kTmV4dEZpbGVNYXJrZXIoZGF0YSwgZW5kT2Zmc2V0LCBvZmZzZXQpOwogIGlmIChmaWxlTWFya2VyPy5pbnZhbGlkKSB7CiAgICByZXR1cm4gZmlsZU1hcmtlci5vZmZzZXQ7CiAgfQogIHJldHVybiBlbmRPZmZzZXQ7Cn0KY2xhc3MgSnBlZ0ltYWdlIHsKICBjb25zdHJ1Y3Rvcih7CiAgICBkZWNvZGVUcmFuc2Zvcm0gPSBudWxsLAogICAgY29sb3JUcmFuc2Zvcm0gPSAtMQogIH0gPSB7fSkgewogICAgdGhpcy5fZGVjb2RlVHJhbnNmb3JtID0gZGVjb2RlVHJhbnNmb3JtOwogICAgdGhpcy5fY29sb3JUcmFuc2Zvcm0gPSBjb2xvclRyYW5zZm9ybTsKICB9CiAgc3RhdGljIGNhblVzZUltYWdlRGVjb2RlcihkYXRhLCBjb2xvclRyYW5zZm9ybSA9IC0xKSB7CiAgICBsZXQgZXhpZk9mZnNldHMgPSBudWxsOwogICAgbGV0IG9mZnNldCA9IDA7CiAgICBsZXQgbnVtQ29tcG9uZW50cyA9IG51bGw7CiAgICBsZXQgZmlsZU1hcmtlciA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KTsKICAgIG9mZnNldCArPSAyOwogICAgaWYgKGZpbGVNYXJrZXIgIT09IDB4ZmZkOCkgewogICAgICB0aHJvdyBuZXcgSnBlZ0Vycm9yKCJTT0kgbm90IGZvdW5kIik7CiAgICB9CiAgICBmaWxlTWFya2VyID0gcmVhZFVpbnQxNihkYXRhLCBvZmZzZXQpOwogICAgb2Zmc2V0ICs9IDI7CiAgICBtYXJrZXJMb29wOiB3aGlsZSAoZmlsZU1hcmtlciAhPT0gMHhmZmQ5KSB7CiAgICAgIHN3aXRjaCAoZmlsZU1hcmtlcikgewogICAgICAgIGNhc2UgMHhmZmUxOgogICAgICAgICAgY29uc3QgewogICAgICAgICAgICBhcHBEYXRhLAogICAgICAgICAgICBvbGRPZmZzZXQsCiAgICAgICAgICAgIG5ld09mZnNldAogICAgICAgICAgfSA9IHJlYWREYXRhQmxvY2soZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIG9mZnNldCA9IG5ld09mZnNldDsKICAgICAgICAgIGlmIChhcHBEYXRhWzBdID09PSAweDQ1ICYmIGFwcERhdGFbMV0gPT09IDB4NzggJiYgYXBwRGF0YVsyXSA9PT0gMHg2OSAmJiBhcHBEYXRhWzNdID09PSAweDY2ICYmIGFwcERhdGFbNF0gPT09IDAgJiYgYXBwRGF0YVs1XSA9PT0gMCkgewogICAgICAgICAgICBpZiAoZXhpZk9mZnNldHMpIHsKICAgICAgICAgICAgICB0aHJvdyBuZXcgSnBlZ0Vycm9yKCJEdXBsaWNhdGUgRVhJRi1ibG9ja3MgZm91bmQuIik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZXhpZk9mZnNldHMgPSB7CiAgICAgICAgICAgICAgZXhpZlN0YXJ0OiBvbGRPZmZzZXQgKyA2LAogICAgICAgICAgICAgIGV4aWZFbmQ6IG5ld09mZnNldAogICAgICAgICAgICB9OwogICAgICAgICAgfQogICAgICAgICAgZmlsZU1hcmtlciA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgY2FzZSAweGZmYzA6CiAgICAgICAgY2FzZSAweGZmYzE6CiAgICAgICAgY2FzZSAweGZmYzI6CiAgICAgICAgICBudW1Db21wb25lbnRzID0gZGF0YVtvZmZzZXQgKyAoMiArIDEgKyAyICsgMildOwogICAgICAgICAgYnJlYWsgbWFya2VyTG9vcDsKICAgICAgICBjYXNlIDB4ZmZmZjoKICAgICAgICAgIGlmIChkYXRhW29mZnNldF0gIT09IDB4ZmYpIHsKICAgICAgICAgICAgb2Zmc2V0LS07CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBvZmZzZXQgPSBza2lwRGF0YShkYXRhLCBvZmZzZXQpOwogICAgICBmaWxlTWFya2VyID0gcmVhZFVpbnQxNihkYXRhLCBvZmZzZXQpOwogICAgICBvZmZzZXQgKz0gMjsKICAgIH0KICAgIGlmIChudW1Db21wb25lbnRzID09PSA0KSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgaWYgKG51bUNvbXBvbmVudHMgPT09IDMgJiYgY29sb3JUcmFuc2Zvcm0gPT09IDApIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICByZXR1cm4gZXhpZk9mZnNldHMgfHwge307CiAgfQogIHBhcnNlKGRhdGEsIHsKICAgIGRubFNjYW5MaW5lcyA9IG51bGwKICB9ID0ge30pIHsKICAgIGxldCBvZmZzZXQgPSAwOwogICAgbGV0IGpmaWYgPSBudWxsOwogICAgbGV0IGFkb2JlID0gbnVsbDsKICAgIGxldCBmcmFtZSwgcmVzZXRJbnRlcnZhbDsKICAgIGxldCBudW1TT1NNYXJrZXJzID0gMDsKICAgIGNvbnN0IHF1YW50aXphdGlvblRhYmxlcyA9IFtdOwogICAgY29uc3QgaHVmZm1hblRhYmxlc0FDID0gW10sCiAgICAgIGh1ZmZtYW5UYWJsZXNEQyA9IFtdOwogICAgbGV0IGZpbGVNYXJrZXIgPSByZWFkVWludDE2KGRhdGEsIG9mZnNldCk7CiAgICBvZmZzZXQgKz0gMjsKICAgIGlmIChmaWxlTWFya2VyICE9PSAweGZmZDgpIHsKICAgICAgdGhyb3cgbmV3IEpwZWdFcnJvcigiU09JIG5vdCBmb3VuZCIpOwogICAgfQogICAgZmlsZU1hcmtlciA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KTsKICAgIG9mZnNldCArPSAyOwogICAgbWFya2VyTG9vcDogd2hpbGUgKGZpbGVNYXJrZXIgIT09IDB4ZmZkOSkgewogICAgICBsZXQgaSwgaiwgbDsKICAgICAgc3dpdGNoIChmaWxlTWFya2VyKSB7CiAgICAgICAgY2FzZSAweGZmZTA6CiAgICAgICAgY2FzZSAweGZmZTE6CiAgICAgICAgY2FzZSAweGZmZTI6CiAgICAgICAgY2FzZSAweGZmZTM6CiAgICAgICAgY2FzZSAweGZmZTQ6CiAgICAgICAgY2FzZSAweGZmZTU6CiAgICAgICAgY2FzZSAweGZmZTY6CiAgICAgICAgY2FzZSAweGZmZTc6CiAgICAgICAgY2FzZSAweGZmZTg6CiAgICAgICAgY2FzZSAweGZmZTk6CiAgICAgICAgY2FzZSAweGZmZWE6CiAgICAgICAgY2FzZSAweGZmZWI6CiAgICAgICAgY2FzZSAweGZmZWM6CiAgICAgICAgY2FzZSAweGZmZWQ6CiAgICAgICAgY2FzZSAweGZmZWU6CiAgICAgICAgY2FzZSAweGZmZWY6CiAgICAgICAgY2FzZSAweGZmZmU6CiAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgIGFwcERhdGEsCiAgICAgICAgICAgIG5ld09mZnNldAogICAgICAgICAgfSA9IHJlYWREYXRhQmxvY2soZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIG9mZnNldCA9IG5ld09mZnNldDsKICAgICAgICAgIGlmIChmaWxlTWFya2VyID09PSAweGZmZTApIHsKICAgICAgICAgICAgaWYgKGFwcERhdGFbMF0gPT09IDB4NGEgJiYgYXBwRGF0YVsxXSA9PT0gMHg0NiAmJiBhcHBEYXRhWzJdID09PSAweDQ5ICYmIGFwcERhdGFbM10gPT09IDB4NDYgJiYgYXBwRGF0YVs0XSA9PT0gMCkgewogICAgICAgICAgICAgIGpmaWYgPSB7CiAgICAgICAgICAgICAgICB2ZXJzaW9uOiB7CiAgICAgICAgICAgICAgICAgIG1ham9yOiBhcHBEYXRhWzVdLAogICAgICAgICAgICAgICAgICBtaW5vcjogYXBwRGF0YVs2XQogICAgICAgICAgICAgICAgfSwKICAgICAgICAgICAgICAgIGRlbnNpdHlVbml0czogYXBwRGF0YVs3XSwKICAgICAgICAgICAgICAgIHhEZW5zaXR5OiBhcHBEYXRhWzhdIDw8IDggfCBhcHBEYXRhWzldLAogICAgICAgICAgICAgICAgeURlbnNpdHk6IGFwcERhdGFbMTBdIDw8IDggfCBhcHBEYXRhWzExXSwKICAgICAgICAgICAgICAgIHRodW1iV2lkdGg6IGFwcERhdGFbMTJdLAogICAgICAgICAgICAgICAgdGh1bWJIZWlnaHQ6IGFwcERhdGFbMTNdLAogICAgICAgICAgICAgICAgdGh1bWJEYXRhOiBhcHBEYXRhLnN1YmFycmF5KDE0LCAxNCArIDMgKiBhcHBEYXRhWzEyXSAqIGFwcERhdGFbMTNdKQogICAgICAgICAgICAgIH07CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChmaWxlTWFya2VyID09PSAweGZmZWUpIHsKICAgICAgICAgICAgaWYgKGFwcERhdGFbMF0gPT09IDB4NDEgJiYgYXBwRGF0YVsxXSA9PT0gMHg2NCAmJiBhcHBEYXRhWzJdID09PSAweDZmICYmIGFwcERhdGFbM10gPT09IDB4NjIgJiYgYXBwRGF0YVs0XSA9PT0gMHg2NSkgewogICAgICAgICAgICAgIGFkb2JlID0gewogICAgICAgICAgICAgICAgdmVyc2lvbjogYXBwRGF0YVs1XSA8PCA4IHwgYXBwRGF0YVs2XSwKICAgICAgICAgICAgICAgIGZsYWdzMDogYXBwRGF0YVs3XSA8PCA4IHwgYXBwRGF0YVs4XSwKICAgICAgICAgICAgICAgIGZsYWdzMTogYXBwRGF0YVs5XSA8PCA4IHwgYXBwRGF0YVsxMF0sCiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Db2RlOiBhcHBEYXRhWzExXQogICAgICAgICAgICAgIH07CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMHhmZmRiOgogICAgICAgICAgY29uc3QgcXVhbnRpemF0aW9uVGFibGVzTGVuZ3RoID0gcmVhZFVpbnQxNihkYXRhLCBvZmZzZXQpOwogICAgICAgICAgb2Zmc2V0ICs9IDI7CiAgICAgICAgICBjb25zdCBxdWFudGl6YXRpb25UYWJsZXNFbmQgPSBxdWFudGl6YXRpb25UYWJsZXNMZW5ndGggKyBvZmZzZXQgLSAyOwogICAgICAgICAgbGV0IHo7CiAgICAgICAgICB3aGlsZSAob2Zmc2V0IDwgcXVhbnRpemF0aW9uVGFibGVzRW5kKSB7CiAgICAgICAgICAgIGNvbnN0IHF1YW50aXphdGlvblRhYmxlU3BlYyA9IGRhdGFbb2Zmc2V0KytdOwogICAgICAgICAgICBjb25zdCB0YWJsZURhdGEgPSBuZXcgVWludDE2QXJyYXkoNjQpOwogICAgICAgICAgICBpZiAocXVhbnRpemF0aW9uVGFibGVTcGVjID4+IDQgPT09IDApIHsKICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgNjQ7IGorKykgewogICAgICAgICAgICAgICAgeiA9IGRjdFppZ1phZ1tqXTsKICAgICAgICAgICAgICAgIHRhYmxlRGF0YVt6XSA9IGRhdGFbb2Zmc2V0KytdOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIGlmIChxdWFudGl6YXRpb25UYWJsZVNwZWMgPj4gNCA9PT0gMSkgewogICAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCA2NDsgaisrKSB7CiAgICAgICAgICAgICAgICB6ID0gZGN0WmlnWmFnW2pdOwogICAgICAgICAgICAgICAgdGFibGVEYXRhW3pdID0gcmVhZFVpbnQxNihkYXRhLCBvZmZzZXQpOwogICAgICAgICAgICAgICAgb2Zmc2V0ICs9IDI7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRocm93IG5ldyBKcGVnRXJyb3IoIkRRVCAtIGludmFsaWQgdGFibGUgc3BlYyIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHF1YW50aXphdGlvblRhYmxlc1txdWFudGl6YXRpb25UYWJsZVNwZWMgJiAxNV0gPSB0YWJsZURhdGE7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4ZmZjMDoKICAgICAgICBjYXNlIDB4ZmZjMToKICAgICAgICBjYXNlIDB4ZmZjMjoKICAgICAgICAgIGlmIChmcmFtZSkgewogICAgICAgICAgICB0aHJvdyBuZXcgSnBlZ0Vycm9yKCJPbmx5IHNpbmdsZSBmcmFtZSBKUEVHcyBzdXBwb3J0ZWQiKTsKICAgICAgICAgIH0KICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgZnJhbWUgPSB7fTsKICAgICAgICAgIGZyYW1lLmV4dGVuZGVkID0gZmlsZU1hcmtlciA9PT0gMHhmZmMxOwogICAgICAgICAgZnJhbWUucHJvZ3Jlc3NpdmUgPSBmaWxlTWFya2VyID09PSAweGZmYzI7CiAgICAgICAgICBmcmFtZS5wcmVjaXNpb24gPSBkYXRhW29mZnNldCsrXTsKICAgICAgICAgIGNvbnN0IHNvZlNjYW5MaW5lcyA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KTsKICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgZnJhbWUuc2NhbkxpbmVzID0gZG5sU2NhbkxpbmVzIHx8IHNvZlNjYW5MaW5lczsKICAgICAgICAgIGZyYW1lLnNhbXBsZXNQZXJMaW5lID0gcmVhZFVpbnQxNihkYXRhLCBvZmZzZXQpOwogICAgICAgICAgb2Zmc2V0ICs9IDI7CiAgICAgICAgICBmcmFtZS5jb21wb25lbnRzID0gW107CiAgICAgICAgICBmcmFtZS5jb21wb25lbnRJZHMgPSB7fTsKICAgICAgICAgIGNvbnN0IGNvbXBvbmVudHNDb3VudCA9IGRhdGFbb2Zmc2V0KytdOwogICAgICAgICAgbGV0IG1heEggPSAwLAogICAgICAgICAgICBtYXhWID0gMDsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb21wb25lbnRzQ291bnQ7IGkrKykgewogICAgICAgICAgICBjb25zdCBjb21wb25lbnRJZCA9IGRhdGFbb2Zmc2V0XTsKICAgICAgICAgICAgY29uc3QgaCA9IGRhdGFbb2Zmc2V0ICsgMV0gPj4gNDsKICAgICAgICAgICAgY29uc3QgdiA9IGRhdGFbb2Zmc2V0ICsgMV0gJiAxNTsKICAgICAgICAgICAgaWYgKG1heEggPCBoKSB7CiAgICAgICAgICAgICAgbWF4SCA9IGg7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKG1heFYgPCB2KSB7CiAgICAgICAgICAgICAgbWF4ViA9IHY7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgcUlkID0gZGF0YVtvZmZzZXQgKyAyXTsKICAgICAgICAgICAgbCA9IGZyYW1lLmNvbXBvbmVudHMucHVzaCh7CiAgICAgICAgICAgICAgaCwKICAgICAgICAgICAgICB2LAogICAgICAgICAgICAgIHF1YW50aXphdGlvbklkOiBxSWQsCiAgICAgICAgICAgICAgcXVhbnRpemF0aW9uVGFibGU6IG51bGwKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGZyYW1lLmNvbXBvbmVudElkc1tjb21wb25lbnRJZF0gPSBsIC0gMTsKICAgICAgICAgICAgb2Zmc2V0ICs9IDM7CiAgICAgICAgICB9CiAgICAgICAgICBmcmFtZS5tYXhIID0gbWF4SDsKICAgICAgICAgIGZyYW1lLm1heFYgPSBtYXhWOwogICAgICAgICAgcHJlcGFyZUNvbXBvbmVudHMoZnJhbWUpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGZmYzQ6CiAgICAgICAgICBjb25zdCBodWZmbWFuTGVuZ3RoID0gcmVhZFVpbnQxNihkYXRhLCBvZmZzZXQpOwogICAgICAgICAgb2Zmc2V0ICs9IDI7CiAgICAgICAgICBmb3IgKGkgPSAyOyBpIDwgaHVmZm1hbkxlbmd0aDspIHsKICAgICAgICAgICAgY29uc3QgaHVmZm1hblRhYmxlU3BlYyA9IGRhdGFbb2Zmc2V0KytdOwogICAgICAgICAgICBjb25zdCBjb2RlTGVuZ3RocyA9IG5ldyBVaW50OEFycmF5KDE2KTsKICAgICAgICAgICAgbGV0IGNvZGVMZW5ndGhTdW0gPSAwOwogICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgMTY7IGorKywgb2Zmc2V0KyspIHsKICAgICAgICAgICAgICBjb2RlTGVuZ3RoU3VtICs9IGNvZGVMZW5ndGhzW2pdID0gZGF0YVtvZmZzZXRdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGh1ZmZtYW5WYWx1ZXMgPSBuZXcgVWludDhBcnJheShjb2RlTGVuZ3RoU3VtKTsKICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IGNvZGVMZW5ndGhTdW07IGorKywgb2Zmc2V0KyspIHsKICAgICAgICAgICAgICBodWZmbWFuVmFsdWVzW2pdID0gZGF0YVtvZmZzZXRdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGkgKz0gMTcgKyBjb2RlTGVuZ3RoU3VtOwogICAgICAgICAgICAoaHVmZm1hblRhYmxlU3BlYyA+PiA0ID09PSAwID8gaHVmZm1hblRhYmxlc0RDIDogaHVmZm1hblRhYmxlc0FDKVtodWZmbWFuVGFibGVTcGVjICYgMTVdID0gYnVpbGRIdWZmbWFuVGFibGUoY29kZUxlbmd0aHMsIGh1ZmZtYW5WYWx1ZXMpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGZmZGQ6CiAgICAgICAgICBvZmZzZXQgKz0gMjsKICAgICAgICAgIHJlc2V0SW50ZXJ2YWwgPSByZWFkVWludDE2KGRhdGEsIG9mZnNldCk7CiAgICAgICAgICBvZmZzZXQgKz0gMjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMHhmZmRhOgogICAgICAgICAgY29uc3QgcGFyc2VETkxNYXJrZXIgPSArK251bVNPU01hcmtlcnMgPT09IDEgJiYgIWRubFNjYW5MaW5lczsKICAgICAgICAgIG9mZnNldCArPSAyOwogICAgICAgICAgY29uc3Qgc2VsZWN0b3JzQ291bnQgPSBkYXRhW29mZnNldCsrXSwKICAgICAgICAgICAgY29tcG9uZW50cyA9IFtdOwogICAgICAgICAgZm9yIChpID0gMDsgaSA8IHNlbGVjdG9yc0NvdW50OyBpKyspIHsKICAgICAgICAgICAgY29uc3QgaW5kZXggPSBkYXRhW29mZnNldCsrXTsKICAgICAgICAgICAgY29uc3QgY29tcG9uZW50SW5kZXggPSBmcmFtZS5jb21wb25lbnRJZHNbaW5kZXhdOwogICAgICAgICAgICBjb25zdCBjb21wb25lbnQgPSBmcmFtZS5jb21wb25lbnRzW2NvbXBvbmVudEluZGV4XTsKICAgICAgICAgICAgY29tcG9uZW50LmluZGV4ID0gaW5kZXg7CiAgICAgICAgICAgIGNvbnN0IHRhYmxlU3BlYyA9IGRhdGFbb2Zmc2V0KytdOwogICAgICAgICAgICBjb21wb25lbnQuaHVmZm1hblRhYmxlREMgPSBodWZmbWFuVGFibGVzRENbdGFibGVTcGVjID4+IDRdOwogICAgICAgICAgICBjb21wb25lbnQuaHVmZm1hblRhYmxlQUMgPSBodWZmbWFuVGFibGVzQUNbdGFibGVTcGVjICYgMTVdOwogICAgICAgICAgICBjb21wb25lbnRzLnB1c2goY29tcG9uZW50KTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IHNwZWN0cmFsU3RhcnQgPSBkYXRhW29mZnNldCsrXSwKICAgICAgICAgICAgc3BlY3RyYWxFbmQgPSBkYXRhW29mZnNldCsrXSwKICAgICAgICAgICAgc3VjY2Vzc2l2ZUFwcHJveGltYXRpb24gPSBkYXRhW29mZnNldCsrXTsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGNvbnN0IHByb2Nlc3NlZCA9IGRlY29kZVNjYW4oZGF0YSwgb2Zmc2V0LCBmcmFtZSwgY29tcG9uZW50cywgcmVzZXRJbnRlcnZhbCwgc3BlY3RyYWxTdGFydCwgc3BlY3RyYWxFbmQsIHN1Y2Nlc3NpdmVBcHByb3hpbWF0aW9uID4+IDQsIHN1Y2Nlc3NpdmVBcHByb3hpbWF0aW9uICYgMTUsIHBhcnNlRE5MTWFya2VyKTsKICAgICAgICAgICAgb2Zmc2V0ICs9IHByb2Nlc3NlZDsKICAgICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIEROTE1hcmtlckVycm9yKSB7CiAgICAgICAgICAgICAgd2FybihgJHtleC5tZXNzYWdlfSAtLSBhdHRlbXB0aW5nIHRvIHJlLXBhcnNlIHRoZSBKUEVHIGltYWdlLmApOwogICAgICAgICAgICAgIHJldHVybiB0aGlzLnBhcnNlKGRhdGEsIHsKICAgICAgICAgICAgICAgIGRubFNjYW5MaW5lczogZXguc2NhbkxpbmVzCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoZXggaW5zdGFuY2VvZiBFT0lNYXJrZXJFcnJvcikgewogICAgICAgICAgICAgIHdhcm4oYCR7ZXgubWVzc2FnZX0gLS0gaWdub3JpbmcgdGhlIHJlc3Qgb2YgdGhlIGltYWdlIGRhdGEuYCk7CiAgICAgICAgICAgICAgYnJlYWsgbWFya2VyTG9vcDsKICAgICAgICAgICAgfQogICAgICAgICAgICB0aHJvdyBleDsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMHhmZmRjOgogICAgICAgICAgb2Zmc2V0ICs9IDQ7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4ZmZmZjoKICAgICAgICAgIGlmIChkYXRhW29mZnNldF0gIT09IDB4ZmYpIHsKICAgICAgICAgICAgb2Zmc2V0LS07CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgY29uc3QgbmV4dEZpbGVNYXJrZXIgPSBmaW5kTmV4dEZpbGVNYXJrZXIoZGF0YSwgb2Zmc2V0IC0gMiwgb2Zmc2V0IC0gMyk7CiAgICAgICAgICBpZiAobmV4dEZpbGVNYXJrZXI/LmludmFsaWQpIHsKICAgICAgICAgICAgd2FybigiSnBlZ0ltYWdlLnBhcnNlIC0gdW5leHBlY3RlZCBkYXRhLCBjdXJyZW50IG1hcmtlciBpczogIiArIG5leHRGaWxlTWFya2VyLmludmFsaWQpOwogICAgICAgICAgICBvZmZzZXQgPSBuZXh0RmlsZU1hcmtlci5vZmZzZXQ7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCFuZXh0RmlsZU1hcmtlciB8fCBvZmZzZXQgPj0gZGF0YS5sZW5ndGggLSAxKSB7CiAgICAgICAgICAgIHdhcm4oIkpwZWdJbWFnZS5wYXJzZSAtIHJlYWNoZWQgdGhlIGVuZCBvZiB0aGUgaW1hZ2UgZGF0YSAiICsgIndpdGhvdXQgZmluZGluZyBhbiBFT0kgbWFya2VyICgweEZGRDkpLiIpOwogICAgICAgICAgICBicmVhayBtYXJrZXJMb29wOwogICAgICAgICAgfQogICAgICAgICAgdGhyb3cgbmV3IEpwZWdFcnJvcigiSnBlZ0ltYWdlLnBhcnNlIC0gdW5rbm93biBtYXJrZXI6ICIgKyBmaWxlTWFya2VyLnRvU3RyaW5nKDE2KSk7CiAgICAgIH0KICAgICAgZmlsZU1hcmtlciA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0KTsKICAgICAgb2Zmc2V0ICs9IDI7CiAgICB9CiAgICBpZiAoIWZyYW1lKSB7CiAgICAgIHRocm93IG5ldyBKcGVnRXJyb3IoIkpwZWdJbWFnZS5wYXJzZSAtIG5vIGZyYW1lIGRhdGEgZm91bmQuIik7CiAgICB9CiAgICB0aGlzLndpZHRoID0gZnJhbWUuc2FtcGxlc1BlckxpbmU7CiAgICB0aGlzLmhlaWdodCA9IGZyYW1lLnNjYW5MaW5lczsKICAgIHRoaXMuamZpZiA9IGpmaWY7CiAgICB0aGlzLmFkb2JlID0gYWRvYmU7CiAgICB0aGlzLmNvbXBvbmVudHMgPSBbXTsKICAgIGZvciAoY29uc3QgY29tcG9uZW50IG9mIGZyYW1lLmNvbXBvbmVudHMpIHsKICAgICAgY29uc3QgcXVhbnRpemF0aW9uVGFibGUgPSBxdWFudGl6YXRpb25UYWJsZXNbY29tcG9uZW50LnF1YW50aXphdGlvbklkXTsKICAgICAgaWYgKHF1YW50aXphdGlvblRhYmxlKSB7CiAgICAgICAgY29tcG9uZW50LnF1YW50aXphdGlvblRhYmxlID0gcXVhbnRpemF0aW9uVGFibGU7CiAgICAgIH0KICAgICAgdGhpcy5jb21wb25lbnRzLnB1c2goewogICAgICAgIGluZGV4OiBjb21wb25lbnQuaW5kZXgsCiAgICAgICAgb3V0cHV0OiBidWlsZENvbXBvbmVudERhdGEoZnJhbWUsIGNvbXBvbmVudCksCiAgICAgICAgc2NhbGVYOiBjb21wb25lbnQuaCAvIGZyYW1lLm1heEgsCiAgICAgICAgc2NhbGVZOiBjb21wb25lbnQudiAvIGZyYW1lLm1heFYsCiAgICAgICAgYmxvY2tzUGVyTGluZTogY29tcG9uZW50LmJsb2Nrc1BlckxpbmUsCiAgICAgICAgYmxvY2tzUGVyQ29sdW1uOiBjb21wb25lbnQuYmxvY2tzUGVyQ29sdW1uCiAgICAgIH0pOwogICAgfQogICAgdGhpcy5udW1Db21wb25lbnRzID0gdGhpcy5jb21wb25lbnRzLmxlbmd0aDsKICAgIHJldHVybiB1bmRlZmluZWQ7CiAgfQogIF9nZXRMaW5lYXJpemVkQmxvY2tEYXRhKHdpZHRoLCBoZWlnaHQsIGlzU291cmNlUERGID0gZmFsc2UpIHsKICAgIGNvbnN0IHNjYWxlWCA9IHRoaXMud2lkdGggLyB3aWR0aCwKICAgICAgc2NhbGVZID0gdGhpcy5oZWlnaHQgLyBoZWlnaHQ7CiAgICBsZXQgY29tcG9uZW50LCBjb21wb25lbnRTY2FsZVgsIGNvbXBvbmVudFNjYWxlWSwgYmxvY2tzUGVyU2NhbmxpbmU7CiAgICBsZXQgeCwgeSwgaSwgaiwgazsKICAgIGxldCBpbmRleDsKICAgIGxldCBvZmZzZXQgPSAwOwogICAgbGV0IG91dHB1dDsKICAgIGNvbnN0IG51bUNvbXBvbmVudHMgPSB0aGlzLmNvbXBvbmVudHMubGVuZ3RoOwogICAgY29uc3QgZGF0YUxlbmd0aCA9IHdpZHRoICogaGVpZ2h0ICogbnVtQ29tcG9uZW50czsKICAgIGNvbnN0IGRhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoZGF0YUxlbmd0aCk7CiAgICBjb25zdCB4U2NhbGVCbG9ja09mZnNldCA9IG5ldyBVaW50MzJBcnJheSh3aWR0aCk7CiAgICBjb25zdCBtYXNrM0xTQiA9IDB4ZmZmZmZmZjg7CiAgICBsZXQgbGFzdENvbXBvbmVudFNjYWxlWDsKICAgIGZvciAoaSA9IDA7IGkgPCBudW1Db21wb25lbnRzOyBpKyspIHsKICAgICAgY29tcG9uZW50ID0gdGhpcy5jb21wb25lbnRzW2ldOwogICAgICBjb21wb25lbnRTY2FsZVggPSBjb21wb25lbnQuc2NhbGVYICogc2NhbGVYOwogICAgICBjb21wb25lbnRTY2FsZVkgPSBjb21wb25lbnQuc2NhbGVZICogc2NhbGVZOwogICAgICBvZmZzZXQgPSBpOwogICAgICBvdXRwdXQgPSBjb21wb25lbnQub3V0cHV0OwogICAgICBibG9ja3NQZXJTY2FubGluZSA9IGNvbXBvbmVudC5ibG9ja3NQZXJMaW5lICsgMSA8PCAzOwogICAgICBpZiAoY29tcG9uZW50U2NhbGVYICE9PSBsYXN0Q29tcG9uZW50U2NhbGVYKSB7CiAgICAgICAgZm9yICh4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHsKICAgICAgICAgIGogPSAwIHwgeCAqIGNvbXBvbmVudFNjYWxlWDsKICAgICAgICAgIHhTY2FsZUJsb2NrT2Zmc2V0W3hdID0gKGogJiBtYXNrM0xTQikgPDwgMyB8IGogJiA3OwogICAgICAgIH0KICAgICAgICBsYXN0Q29tcG9uZW50U2NhbGVYID0gY29tcG9uZW50U2NhbGVYOwogICAgICB9CiAgICAgIGZvciAoeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykgewogICAgICAgIGogPSAwIHwgeSAqIGNvbXBvbmVudFNjYWxlWTsKICAgICAgICBpbmRleCA9IGJsb2Nrc1BlclNjYW5saW5lICogKGogJiBtYXNrM0xTQikgfCAoaiAmIDcpIDw8IDM7CiAgICAgICAgZm9yICh4ID0gMDsgeCA8IHdpZHRoOyB4KyspIHsKICAgICAgICAgIGRhdGFbb2Zmc2V0XSA9IG91dHB1dFtpbmRleCArIHhTY2FsZUJsb2NrT2Zmc2V0W3hdXTsKICAgICAgICAgIG9mZnNldCArPSBudW1Db21wb25lbnRzOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgbGV0IHRyYW5zZm9ybSA9IHRoaXMuX2RlY29kZVRyYW5zZm9ybTsKICAgIGlmICghaXNTb3VyY2VQREYgJiYgbnVtQ29tcG9uZW50cyA9PT0gNCAmJiAhdHJhbnNmb3JtKSB7CiAgICAgIHRyYW5zZm9ybSA9IG5ldyBJbnQzMkFycmF5KFstMjU2LCAyNTUsIC0yNTYsIDI1NSwgLTI1NiwgMjU1LCAtMjU2LCAyNTVdKTsKICAgIH0KICAgIGlmICh0cmFuc2Zvcm0pIHsKICAgICAgZm9yIChpID0gMDsgaSA8IGRhdGFMZW5ndGg7KSB7CiAgICAgICAgZm9yIChqID0gMCwgayA9IDA7IGogPCBudW1Db21wb25lbnRzOyBqKyssIGkrKywgayArPSAyKSB7CiAgICAgICAgICBkYXRhW2ldID0gKGRhdGFbaV0gKiB0cmFuc2Zvcm1ba10gPj4gOCkgKyB0cmFuc2Zvcm1bayArIDFdOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIGRhdGE7CiAgfQogIGdldCBfaXNDb2xvckNvbnZlcnNpb25OZWVkZWQoKSB7CiAgICBpZiAodGhpcy5hZG9iZSkgewogICAgICByZXR1cm4gISF0aGlzLmFkb2JlLnRyYW5zZm9ybUNvZGU7CiAgICB9CiAgICBpZiAodGhpcy5udW1Db21wb25lbnRzID09PSAzKSB7CiAgICAgIGlmICh0aGlzLl9jb2xvclRyYW5zZm9ybSA9PT0gMCkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfSBlbHNlIGlmICh0aGlzLmNvbXBvbmVudHNbMF0uaW5kZXggPT09IDB4NTIgJiYgdGhpcy5jb21wb25lbnRzWzFdLmluZGV4ID09PSAweDQ3ICYmIHRoaXMuY29tcG9uZW50c1syXS5pbmRleCA9PT0gMHg0MikgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmICh0aGlzLl9jb2xvclRyYW5zZm9ybSA9PT0gMSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKICB9CiAgX2NvbnZlcnRZY2NUb1JnYihkYXRhKSB7CiAgICBsZXQgWSwgQ2IsIENyOwogICAgZm9yIChsZXQgaSA9IDAsIGxlbmd0aCA9IGRhdGEubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpICs9IDMpIHsKICAgICAgWSA9IGRhdGFbaV07CiAgICAgIENiID0gZGF0YVtpICsgMV07CiAgICAgIENyID0gZGF0YVtpICsgMl07CiAgICAgIGRhdGFbaV0gPSBZIC0gMTc5LjQ1NiArIDEuNDAyICogQ3I7CiAgICAgIGRhdGFbaSArIDFdID0gWSArIDEzNS40NTkgLSAwLjM0NCAqIENiIC0gMC43MTQgKiBDcjsKICAgICAgZGF0YVtpICsgMl0gPSBZIC0gMjI2LjgxNiArIDEuNzcyICogQ2I7CiAgICB9CiAgICByZXR1cm4gZGF0YTsKICB9CiAgX2NvbnZlcnRZY2NUb1JnYmEoZGF0YSwgb3V0KSB7CiAgICBmb3IgKGxldCBpID0gMCwgaiA9IDAsIGxlbmd0aCA9IGRhdGEubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpICs9IDMsIGogKz0gNCkgewogICAgICBjb25zdCBZID0gZGF0YVtpXTsKICAgICAgY29uc3QgQ2IgPSBkYXRhW2kgKyAxXTsKICAgICAgY29uc3QgQ3IgPSBkYXRhW2kgKyAyXTsKICAgICAgb3V0W2pdID0gWSAtIDE3OS40NTYgKyAxLjQwMiAqIENyOwogICAgICBvdXRbaiArIDFdID0gWSArIDEzNS40NTkgLSAwLjM0NCAqIENiIC0gMC43MTQgKiBDcjsKICAgICAgb3V0W2ogKyAyXSA9IFkgLSAyMjYuODE2ICsgMS43NzIgKiBDYjsKICAgICAgb3V0W2ogKyAzXSA9IDI1NTsKICAgIH0KICAgIHJldHVybiBvdXQ7CiAgfQogIF9jb252ZXJ0WWNja1RvUmdiKGRhdGEpIHsKICAgIHRoaXMuX2NvbnZlcnRZY2NrVG9DbXlrKGRhdGEpOwogICAgcmV0dXJuIHRoaXMuX2NvbnZlcnRDbXlrVG9SZ2IoZGF0YSk7CiAgfQogIF9jb252ZXJ0WWNja1RvUmdiYShkYXRhKSB7CiAgICB0aGlzLl9jb252ZXJ0WWNja1RvQ215ayhkYXRhKTsKICAgIHJldHVybiB0aGlzLl9jb252ZXJ0Q215a1RvUmdiYShkYXRhKTsKICB9CiAgX2NvbnZlcnRZY2NrVG9DbXlrKGRhdGEpIHsKICAgIGxldCBZLCBDYiwgQ3I7CiAgICBmb3IgKGxldCBpID0gMCwgbGVuZ3RoID0gZGF0YS5sZW5ndGg7IGkgPCBsZW5ndGg7IGkgKz0gNCkgewogICAgICBZID0gZGF0YVtpXTsKICAgICAgQ2IgPSBkYXRhW2kgKyAxXTsKICAgICAgQ3IgPSBkYXRhW2kgKyAyXTsKICAgICAgZGF0YVtpXSA9IDQzNC40NTYgLSBZIC0gMS40MDIgKiBDcjsKICAgICAgZGF0YVtpICsgMV0gPSAxMTkuNTQxIC0gWSArIDAuMzQ0ICogQ2IgKyAwLjcxNCAqIENyOwogICAgICBkYXRhW2kgKyAyXSA9IDQ4MS44MTYgLSBZIC0gMS43NzIgKiBDYjsKICAgIH0KICAgIHJldHVybiBkYXRhOwogIH0KICBfY29udmVydENteWtUb1JnYihkYXRhKSB7CiAgICBjb25zdCBjb3VudCA9IGRhdGEubGVuZ3RoIC8gNDsKICAgIENvbG9yU3BhY2VVdGlscy5jbXlrLmdldFJnYkJ1ZmZlcihkYXRhLCAwLCBjb3VudCwgZGF0YSwgMCwgOCwgMCk7CiAgICByZXR1cm4gZGF0YS5zdWJhcnJheSgwLCBjb3VudCAqIDMpOwogIH0KICBfY29udmVydENteWtUb1JnYmEoZGF0YSkgewogICAgQ29sb3JTcGFjZVV0aWxzLmNteWsuZ2V0UmdiQnVmZmVyKGRhdGEsIDAsIGRhdGEubGVuZ3RoIC8gNCwgZGF0YSwgMCwgOCwgMSk7CiAgICBpZiAoQ29sb3JTcGFjZVV0aWxzLmNteWsgaW5zdGFuY2VvZiBEZXZpY2VDbXlrQ1MpIHsKICAgICAgZm9yIChsZXQgaSA9IDMsIGlpID0gZGF0YS5sZW5ndGg7IGkgPCBpaTsgaSArPSA0KSB7CiAgICAgICAgZGF0YVtpXSA9IDI1NTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGRhdGE7CiAgfQogIGdldERhdGEoewogICAgd2lkdGgsCiAgICBoZWlnaHQsCiAgICBmb3JjZVJHQkEgPSBmYWxzZSwKICAgIGZvcmNlUkdCID0gZmFsc2UsCiAgICBpc1NvdXJjZVBERiA9IGZhbHNlCiAgfSkgewogICAgaWYgKHRoaXMubnVtQ29tcG9uZW50cyA+IDQpIHsKICAgICAgdGhyb3cgbmV3IEpwZWdFcnJvcigiVW5zdXBwb3J0ZWQgY29sb3IgbW9kZSIpOwogICAgfQogICAgY29uc3QgZGF0YSA9IHRoaXMuX2dldExpbmVhcml6ZWRCbG9ja0RhdGEod2lkdGgsIGhlaWdodCwgaXNTb3VyY2VQREYpOwogICAgaWYgKHRoaXMubnVtQ29tcG9uZW50cyA9PT0gMSAmJiAoZm9yY2VSR0JBIHx8IGZvcmNlUkdCKSkgewogICAgICBjb25zdCBsZW4gPSBkYXRhLmxlbmd0aCAqIChmb3JjZVJHQkEgPyA0IDogMyk7CiAgICAgIGNvbnN0IHJnYmFEYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGxlbik7CiAgICAgIGxldCBvZmZzZXQgPSAwOwogICAgICBpZiAoZm9yY2VSR0JBKSB7CiAgICAgICAgZ3JheVRvUkdCQShkYXRhLCBuZXcgVWludDMyQXJyYXkocmdiYURhdGEuYnVmZmVyKSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yIChjb25zdCBncmF5Q29sb3Igb2YgZGF0YSkgewogICAgICAgICAgcmdiYURhdGFbb2Zmc2V0KytdID0gZ3JheUNvbG9yOwogICAgICAgICAgcmdiYURhdGFbb2Zmc2V0KytdID0gZ3JheUNvbG9yOwogICAgICAgICAgcmdiYURhdGFbb2Zmc2V0KytdID0gZ3JheUNvbG9yOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gcmdiYURhdGE7CiAgICB9IGVsc2UgaWYgKHRoaXMubnVtQ29tcG9uZW50cyA9PT0gMyAmJiB0aGlzLl9pc0NvbG9yQ29udmVyc2lvbk5lZWRlZCkgewogICAgICBpZiAoZm9yY2VSR0JBKSB7CiAgICAgICAgY29uc3QgcmdiYURhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoZGF0YS5sZW5ndGggLyAzICogNCk7CiAgICAgICAgcmV0dXJuIHRoaXMuX2NvbnZlcnRZY2NUb1JnYmEoZGF0YSwgcmdiYURhdGEpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLl9jb252ZXJ0WWNjVG9SZ2IoZGF0YSk7CiAgICB9IGVsc2UgaWYgKHRoaXMubnVtQ29tcG9uZW50cyA9PT0gNCkgewogICAgICBpZiAodGhpcy5faXNDb2xvckNvbnZlcnNpb25OZWVkZWQpIHsKICAgICAgICBpZiAoZm9yY2VSR0JBKSB7CiAgICAgICAgICByZXR1cm4gdGhpcy5fY29udmVydFljY2tUb1JnYmEoZGF0YSk7CiAgICAgICAgfQogICAgICAgIGlmIChmb3JjZVJHQikgewogICAgICAgICAgcmV0dXJuIHRoaXMuX2NvbnZlcnRZY2NrVG9SZ2IoZGF0YSk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzLl9jb252ZXJ0WWNja1RvQ215ayhkYXRhKTsKICAgICAgfSBlbHNlIGlmIChmb3JjZVJHQkEpIHsKICAgICAgICByZXR1cm4gdGhpcy5fY29udmVydENteWtUb1JnYmEoZGF0YSk7CiAgICAgIH0gZWxzZSBpZiAoZm9yY2VSR0IpIHsKICAgICAgICByZXR1cm4gdGhpcy5fY29udmVydENteWtUb1JnYihkYXRhKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGRhdGE7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9qcGVnX3N0cmVhbS5qcwoKCgoKCgoKCmNsYXNzIEpwZWdTdHJlYW0gZXh0ZW5kcyBEZWNvZGVTdHJlYW0gewogIHN0YXRpYyAjaXNJbWFnZURlY29kZXJTdXBwb3J0ZWQgPSBGZWF0dXJlVGVzdC5pc0ltYWdlRGVjb2RlclN1cHBvcnRlZDsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIG1heWJlTGVuZ3RoLCBwYXJhbXMpIHsKICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtOwogICAgdGhpcy5kaWN0ID0gc3RyZWFtLmRpY3Q7CiAgICB0aGlzLm1heWJlTGVuZ3RoID0gbWF5YmVMZW5ndGg7CiAgICB0aGlzLnBhcmFtcyA9IHBhcmFtczsKICB9CiAgc3RhdGljIGdldCBjYW5Vc2VJbWFnZURlY29kZXIoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJjYW5Vc2VJbWFnZURlY29kZXIiLCB0aGlzLiNpc0ltYWdlRGVjb2RlclN1cHBvcnRlZCA/IEltYWdlRGVjb2Rlci5pc1R5cGVTdXBwb3J0ZWQoImltYWdlL2pwZWciKSA6IFByb21pc2UucmVzb2x2ZShmYWxzZSkpOwogIH0KICBzdGF0aWMgc2V0T3B0aW9ucyh7CiAgICBpc0ltYWdlRGVjb2RlclN1cHBvcnRlZCA9IGZhbHNlCiAgfSkgewogICAgdGhpcy4jaXNJbWFnZURlY29kZXJTdXBwb3J0ZWQgPSBpc0ltYWdlRGVjb2RlclN1cHBvcnRlZDsKICB9CiAgZ2V0IGJ5dGVzKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiYnl0ZXMiLCB0aGlzLnN0cmVhbS5nZXRCeXRlcyh0aGlzLm1heWJlTGVuZ3RoKSk7CiAgfQogIGVuc3VyZUJ1ZmZlcihyZXF1ZXN0ZWQpIHt9CiAgcmVhZEJsb2NrKCkgewogICAgdGhpcy5kZWNvZGVJbWFnZSgpOwogIH0KICBnZXQganBlZ09wdGlvbnMoKSB7CiAgICBjb25zdCBqcGVnT3B0aW9ucyA9IHsKICAgICAgZGVjb2RlVHJhbnNmb3JtOiB1bmRlZmluZWQsCiAgICAgIGNvbG9yVHJhbnNmb3JtOiB1bmRlZmluZWQKICAgIH07CiAgICBjb25zdCBkZWNvZGVBcnIgPSB0aGlzLmRpY3QuZ2V0QXJyYXkoIkQiLCAiRGVjb2RlIik7CiAgICBpZiAoKHRoaXMuZm9yY2VSR0JBIHx8IHRoaXMuZm9yY2VSR0IpICYmIEFycmF5LmlzQXJyYXkoZGVjb2RlQXJyKSkgewogICAgICBjb25zdCBiaXRzUGVyQ29tcG9uZW50ID0gdGhpcy5kaWN0LmdldCgiQlBDIiwgIkJpdHNQZXJDb21wb25lbnQiKSB8fCA4OwogICAgICBjb25zdCBkZWNvZGVBcnJMZW5ndGggPSBkZWNvZGVBcnIubGVuZ3RoOwogICAgICBjb25zdCB0cmFuc2Zvcm0gPSBuZXcgSW50MzJBcnJheShkZWNvZGVBcnJMZW5ndGgpOwogICAgICBsZXQgdHJhbnNmb3JtTmVlZGVkID0gZmFsc2U7CiAgICAgIGNvbnN0IG1heFZhbHVlID0gKDEgPDwgYml0c1BlckNvbXBvbmVudCkgLSAxOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGRlY29kZUFyckxlbmd0aDsgaSArPSAyKSB7CiAgICAgICAgdHJhbnNmb3JtW2ldID0gKGRlY29kZUFycltpICsgMV0gLSBkZWNvZGVBcnJbaV0pICogMjU2IHwgMDsKICAgICAgICB0cmFuc2Zvcm1baSArIDFdID0gZGVjb2RlQXJyW2ldICogbWF4VmFsdWUgfCAwOwogICAgICAgIGlmICh0cmFuc2Zvcm1baV0gIT09IDI1NiB8fCB0cmFuc2Zvcm1baSArIDFdICE9PSAwKSB7CiAgICAgICAgICB0cmFuc2Zvcm1OZWVkZWQgPSB0cnVlOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAodHJhbnNmb3JtTmVlZGVkKSB7CiAgICAgICAganBlZ09wdGlvbnMuZGVjb2RlVHJhbnNmb3JtID0gdHJhbnNmb3JtOwogICAgICB9CiAgICB9CiAgICBpZiAodGhpcy5wYXJhbXMgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgIGNvbnN0IGNvbG9yVHJhbnNmb3JtID0gdGhpcy5wYXJhbXMuZ2V0KCJDb2xvclRyYW5zZm9ybSIpOwogICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihjb2xvclRyYW5zZm9ybSkpIHsKICAgICAgICBqcGVnT3B0aW9ucy5jb2xvclRyYW5zZm9ybSA9IGNvbG9yVHJhbnNmb3JtOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJqcGVnT3B0aW9ucyIsIGpwZWdPcHRpb25zKTsKICB9CiAgI3NraXBVc2VsZXNzQnl0ZXMoZGF0YSkgewogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZGF0YS5sZW5ndGggLSAxOyBpIDwgaWk7IGkrKykgewogICAgICBpZiAoZGF0YVtpXSA9PT0gMHhmZiAmJiBkYXRhW2kgKyAxXSA9PT0gMHhkOCkgewogICAgICAgIGlmIChpID4gMCkgewogICAgICAgICAgZGF0YSA9IGRhdGEuc3ViYXJyYXkoaSk7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gZGF0YTsKICB9CiAgZGVjb2RlSW1hZ2UoYnl0ZXMpIHsKICAgIGlmICh0aGlzLmVvZikgewogICAgICByZXR1cm4gdGhpcy5idWZmZXI7CiAgICB9CiAgICBieXRlcyA9IHRoaXMuI3NraXBVc2VsZXNzQnl0ZXMoYnl0ZXMgfHwgdGhpcy5ieXRlcyk7CiAgICBjb25zdCBqcGVnSW1hZ2UgPSBuZXcgSnBlZ0ltYWdlKHRoaXMuanBlZ09wdGlvbnMpOwogICAganBlZ0ltYWdlLnBhcnNlKGJ5dGVzKTsKICAgIGNvbnN0IGRhdGEgPSBqcGVnSW1hZ2UuZ2V0RGF0YSh7CiAgICAgIHdpZHRoOiB0aGlzLmRyYXdXaWR0aCwKICAgICAgaGVpZ2h0OiB0aGlzLmRyYXdIZWlnaHQsCiAgICAgIGZvcmNlUkdCQTogdGhpcy5mb3JjZVJHQkEsCiAgICAgIGZvcmNlUkdCOiB0aGlzLmZvcmNlUkdCLAogICAgICBpc1NvdXJjZVBERjogdHJ1ZQogICAgfSk7CiAgICB0aGlzLmJ1ZmZlciA9IGRhdGE7CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IGRhdGEubGVuZ3RoOwogICAgdGhpcy5lb2YgPSB0cnVlOwogICAgcmV0dXJuIHRoaXMuYnVmZmVyOwogIH0KICBnZXQgY2FuQXN5bmNEZWNvZGVJbWFnZUZyb21CdWZmZXIoKSB7CiAgICByZXR1cm4gdGhpcy5zdHJlYW0uaXNBc3luYzsKICB9CiAgYXN5bmMgZ2V0VHJhbnNmZXJhYmxlSW1hZ2UoKSB7CiAgICBpZiAoIShhd2FpdCBKcGVnU3RyZWFtLmNhblVzZUltYWdlRGVjb2RlcikpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCBqcGVnT3B0aW9ucyA9IHRoaXMuanBlZ09wdGlvbnM7CiAgICBpZiAoanBlZ09wdGlvbnMuZGVjb2RlVHJhbnNmb3JtKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgbGV0IGRlY29kZXI7CiAgICB0cnkgewogICAgICBjb25zdCBieXRlcyA9IHRoaXMuY2FuQXN5bmNEZWNvZGVJbWFnZUZyb21CdWZmZXIgJiYgKGF3YWl0IHRoaXMuc3RyZWFtLmFzeW5jR2V0Qnl0ZXMoKSkgfHwgdGhpcy5ieXRlczsKICAgICAgaWYgKCFieXRlcykgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGxldCBkYXRhID0gdGhpcy4jc2tpcFVzZWxlc3NCeXRlcyhieXRlcyk7CiAgICAgIGNvbnN0IHVzZUltYWdlRGVjb2RlciA9IEpwZWdJbWFnZS5jYW5Vc2VJbWFnZURlY29kZXIoZGF0YSwganBlZ09wdGlvbnMuY29sb3JUcmFuc2Zvcm0pOwogICAgICBpZiAoIXVzZUltYWdlRGVjb2RlcikgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGlmICh1c2VJbWFnZURlY29kZXIuZXhpZlN0YXJ0KSB7CiAgICAgICAgZGF0YSA9IGRhdGEuc2xpY2UoKTsKICAgICAgICBkYXRhLmZpbGwoMHgwMCwgdXNlSW1hZ2VEZWNvZGVyLmV4aWZTdGFydCwgdXNlSW1hZ2VEZWNvZGVyLmV4aWZFbmQpOwogICAgICB9CiAgICAgIGRlY29kZXIgPSBuZXcgSW1hZ2VEZWNvZGVyKHsKICAgICAgICBkYXRhLAogICAgICAgIHR5cGU6ICJpbWFnZS9qcGVnIiwKICAgICAgICBwcmVmZXJBbmltYXRpb246IGZhbHNlCiAgICAgIH0pOwogICAgICByZXR1cm4gKGF3YWl0IGRlY29kZXIuZGVjb2RlKCkpLmltYWdlOwogICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgIHdhcm4oYGdldFRyYW5zZmVyYWJsZUltYWdlIC0gZmFpbGVkOiAiJHtyZWFzb259Ii5gKTsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9IGZpbmFsbHkgewogICAgICBkZWNvZGVyPy5jbG9zZSgpOwogICAgfQogIH0KfQoKOy8vIC4vZXh0ZXJuYWwvb3BlbmpwZWcvb3BlbmpwZWcuanMKCgoKCgoKCgoKCgoKYXN5bmMgZnVuY3Rpb24gT3BlbkpQRUcobW9kdWxlQXJnID0ge30pIHsKICB2YXIgbW9kdWxlUnRuOwogIHZhciBNb2R1bGUgPSBtb2R1bGVBcmc7CiAgdmFyIEVOVklST05NRU5UX0lTX1dFQiA9IHRydWU7CiAgdmFyIEVOVklST05NRU5UX0lTX1dPUktFUiA9IGZhbHNlOwogIHZhciBhcmd1bWVudHNfID0gW107CiAgdmFyIHRoaXNQcm9ncmFtID0gIi4vdGhpcy5wcm9ncmFtIjsKICB2YXIgcXVpdF8gPSAoc3RhdHVzLCB0b1Rocm93KSA9PiB7CiAgICB0aHJvdyB0b1Rocm93OwogIH07CiAgdmFyIF9zY3JpcHROYW1lID0gaW1wb3J0Lm1ldGEudXJsOwogIHZhciBzY3JpcHREaXJlY3RvcnkgPSAiIjsKICB2YXIgcmVhZEFzeW5jLCByZWFkQmluYXJ5OwogIGlmIChFTlZJUk9OTUVOVF9JU19XRUIgfHwgRU5WSVJPTk1FTlRfSVNfV09SS0VSKSB7CiAgICB0cnkgewogICAgICBzY3JpcHREaXJlY3RvcnkgPSBuZXcgVVJMKCIuIiwgX3NjcmlwdE5hbWUpLmhyZWY7CiAgICB9IGNhdGNoIHt9CiAgICByZWFkQXN5bmMgPSBhc3luYyB1cmwgPT4gewogICAgICB2YXIgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh1cmwsIHsKICAgICAgICBjcmVkZW50aWFsczogInNhbWUtb3JpZ2luIgogICAgICB9KTsKICAgICAgaWYgKHJlc3BvbnNlLm9rKSB7CiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmFycmF5QnVmZmVyKCk7CiAgICAgIH0KICAgICAgdGhyb3cgbmV3IEVycm9yKHJlc3BvbnNlLnN0YXR1cyArICIgOiAiICsgcmVzcG9uc2UudXJsKTsKICAgIH07CiAgfSBlbHNlIHt9CiAgdmFyIG91dCA9IGNvbnNvbGUubG9nLmJpbmQoY29uc29sZSk7CiAgdmFyIGVyciA9IGNvbnNvbGUuZXJyb3IuYmluZChjb25zb2xlKTsKICB2YXIgd2FzbUJpbmFyeTsKICB2YXIgQUJPUlQgPSBmYWxzZTsKICB2YXIgRVhJVFNUQVRVUzsKICB2YXIgcmVhZHlQcm9taXNlUmVzb2x2ZSwgcmVhZHlQcm9taXNlUmVqZWN0OwogIHZhciB3YXNtTWVtb3J5OwogIHZhciBIRUFQOCwgSEVBUFU4LCBIRUFQMTYsIEhFQVBVMTYsIEhFQVAzMiwgSEVBUFUzMiwgSEVBUEYzMiwgSEVBUEY2NDsKICB2YXIgSEVBUDY0LCBIRUFQVTY0OwogIHZhciBydW50aW1lSW5pdGlhbGl6ZWQgPSBmYWxzZTsKICBmdW5jdGlvbiB1cGRhdGVNZW1vcnlWaWV3cygpIHsKICAgIHZhciBiID0gd2FzbU1lbW9yeS5idWZmZXI7CiAgICBIRUFQOCA9IG5ldyBJbnQ4QXJyYXkoYik7CiAgICBIRUFQMTYgPSBuZXcgSW50MTZBcnJheShiKTsKICAgIEhFQVBVOCA9IG5ldyBVaW50OEFycmF5KGIpOwogICAgSEVBUFUxNiA9IG5ldyBVaW50MTZBcnJheShiKTsKICAgIEhFQVAzMiA9IG5ldyBJbnQzMkFycmF5KGIpOwogICAgSEVBUFUzMiA9IG5ldyBVaW50MzJBcnJheShiKTsKICAgIEhFQVBGMzIgPSBuZXcgRmxvYXQzMkFycmF5KGIpOwogICAgSEVBUEY2NCA9IG5ldyBGbG9hdDY0QXJyYXkoYik7CiAgICBIRUFQNjQgPSBuZXcgQmlnSW50NjRBcnJheShiKTsKICAgIEhFQVBVNjQgPSBuZXcgQmlnVWludDY0QXJyYXkoYik7CiAgfQogIGZ1bmN0aW9uIHByZVJ1bigpIHsKICAgIGlmIChNb2R1bGVbInByZVJ1biJdKSB7CiAgICAgIGlmICh0eXBlb2YgTW9kdWxlWyJwcmVSdW4iXSA9PSAiZnVuY3Rpb24iKSBNb2R1bGVbInByZVJ1biJdID0gW01vZHVsZVsicHJlUnVuIl1dOwogICAgICB3aGlsZSAoTW9kdWxlWyJwcmVSdW4iXS5sZW5ndGgpIHsKICAgICAgICBhZGRPblByZVJ1bihNb2R1bGVbInByZVJ1biJdLnNoaWZ0KCkpOwogICAgICB9CiAgICB9CiAgICBjYWxsUnVudGltZUNhbGxiYWNrcyhvblByZVJ1bnMpOwogIH0KICBmdW5jdGlvbiBpbml0UnVudGltZSgpIHsKICAgIHJ1bnRpbWVJbml0aWFsaXplZCA9IHRydWU7CiAgICB3YXNtRXhwb3J0c1sicyJdKCk7CiAgfQogIGZ1bmN0aW9uIHBvc3RSdW4oKSB7CiAgICBpZiAoTW9kdWxlWyJwb3N0UnVuIl0pIHsKICAgICAgaWYgKHR5cGVvZiBNb2R1bGVbInBvc3RSdW4iXSA9PSAiZnVuY3Rpb24iKSBNb2R1bGVbInBvc3RSdW4iXSA9IFtNb2R1bGVbInBvc3RSdW4iXV07CiAgICAgIHdoaWxlIChNb2R1bGVbInBvc3RSdW4iXS5sZW5ndGgpIHsKICAgICAgICBhZGRPblBvc3RSdW4oTW9kdWxlWyJwb3N0UnVuIl0uc2hpZnQoKSk7CiAgICAgIH0KICAgIH0KICAgIGNhbGxSdW50aW1lQ2FsbGJhY2tzKG9uUG9zdFJ1bnMpOwogIH0KICBmdW5jdGlvbiBhYm9ydCh3aGF0KSB7CiAgICBNb2R1bGVbIm9uQWJvcnQiXT8uKHdoYXQpOwogICAgd2hhdCA9ICJBYm9ydGVkKCIgKyB3aGF0ICsgIikiOwogICAgZXJyKHdoYXQpOwogICAgQUJPUlQgPSB0cnVlOwogICAgd2hhdCArPSAiLiBCdWlsZCB3aXRoIC1zQVNTRVJUSU9OUyBmb3IgbW9yZSBpbmZvLiI7CiAgICB2YXIgZSA9IG5ldyBXZWJBc3NlbWJseS5SdW50aW1lRXJyb3Iod2hhdCk7CiAgICByZWFkeVByb21pc2VSZWplY3Q/LihlKTsKICAgIHRocm93IGU7CiAgfQogIHZhciB3YXNtQmluYXJ5RmlsZTsKICBmdW5jdGlvbiBnZXRXYXNtSW1wb3J0cygpIHsKICAgIHJldHVybiB7CiAgICAgIGE6IHdhc21JbXBvcnRzCiAgICB9OwogIH0KICBhc3luYyBmdW5jdGlvbiBjcmVhdGVXYXNtKCkgewogICAgZnVuY3Rpb24gcmVjZWl2ZUluc3RhbmNlKGluc3RhbmNlLCBtb2R1bGUpIHsKICAgICAgd2FzbUV4cG9ydHMgPSBpbnN0YW5jZS5leHBvcnRzOwogICAgICB3YXNtTWVtb3J5ID0gd2FzbUV4cG9ydHNbInIiXTsKICAgICAgdXBkYXRlTWVtb3J5Vmlld3MoKTsKICAgICAgYXNzaWduV2FzbUV4cG9ydHMod2FzbUV4cG9ydHMpOwogICAgICByZXR1cm4gd2FzbUV4cG9ydHM7CiAgICB9CiAgICB2YXIgaW5mbyA9IGdldFdhc21JbXBvcnRzKCk7CiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gewogICAgICBNb2R1bGVbImluc3RhbnRpYXRlV2FzbSJdKGluZm8sIChtb2QsIGluc3QpID0+IHsKICAgICAgICByZXNvbHZlKHJlY2VpdmVJbnN0YW5jZShtb2QsIGluc3QpKTsKICAgICAgfSk7CiAgICB9KTsKICB9CiAgY2xhc3MgRXhpdFN0YXR1cyB7CiAgICBuYW1lID0gIkV4aXRTdGF0dXMiOwogICAgY29uc3RydWN0b3Ioc3RhdHVzKSB7CiAgICAgIHRoaXMubWVzc2FnZSA9IGBQcm9ncmFtIHRlcm1pbmF0ZWQgd2l0aCBleGl0KCR7c3RhdHVzfSlgOwogICAgICB0aGlzLnN0YXR1cyA9IHN0YXR1czsKICAgIH0KICB9CiAgdmFyIGNhbGxSdW50aW1lQ2FsbGJhY2tzID0gY2FsbGJhY2tzID0+IHsKICAgIHdoaWxlIChjYWxsYmFja3MubGVuZ3RoID4gMCkgewogICAgICBjYWxsYmFja3Muc2hpZnQoKShNb2R1bGUpOwogICAgfQogIH07CiAgdmFyIG9uUG9zdFJ1bnMgPSBbXTsKICB2YXIgYWRkT25Qb3N0UnVuID0gY2IgPT4gb25Qb3N0UnVucy5wdXNoKGNiKTsKICB2YXIgb25QcmVSdW5zID0gW107CiAgdmFyIGFkZE9uUHJlUnVuID0gY2IgPT4gb25QcmVSdW5zLnB1c2goY2IpOwogIHZhciBub0V4aXRSdW50aW1lID0gdHJ1ZTsKICB2YXIgX19hYm9ydF9qcyA9ICgpID0+IGFib3J0KCIiKTsKICB2YXIgcnVudGltZUtlZXBhbGl2ZUNvdW50ZXIgPSAwOwogIHZhciBfX2Vtc2NyaXB0ZW5fcnVudGltZV9rZWVwYWxpdmVfY2xlYXIgPSAoKSA9PiB7CiAgICBub0V4aXRSdW50aW1lID0gZmFsc2U7CiAgICBydW50aW1lS2VlcGFsaXZlQ291bnRlciA9IDA7CiAgfTsKICB2YXIgdGltZXJzID0ge307CiAgdmFyIGhhbmRsZUV4Y2VwdGlvbiA9IGUgPT4gewogICAgaWYgKGUgaW5zdGFuY2VvZiBFeGl0U3RhdHVzIHx8IGUgPT0gInVud2luZCIpIHsKICAgICAgcmV0dXJuIEVYSVRTVEFUVVM7CiAgICB9CiAgICBxdWl0XygxLCBlKTsKICB9OwogIHZhciBrZWVwUnVudGltZUFsaXZlID0gKCkgPT4gbm9FeGl0UnVudGltZSB8fCBydW50aW1lS2VlcGFsaXZlQ291bnRlciA+IDA7CiAgdmFyIF9wcm9jX2V4aXQgPSBjb2RlID0+IHsKICAgIEVYSVRTVEFUVVMgPSBjb2RlOwogICAgaWYgKCFrZWVwUnVudGltZUFsaXZlKCkpIHsKICAgICAgTW9kdWxlWyJvbkV4aXQiXT8uKGNvZGUpOwogICAgICBBQk9SVCA9IHRydWU7CiAgICB9CiAgICBxdWl0Xyhjb2RlLCBuZXcgRXhpdFN0YXR1cyhjb2RlKSk7CiAgfTsKICB2YXIgZXhpdEpTID0gKHN0YXR1cywgaW1wbGljaXQpID0+IHsKICAgIEVYSVRTVEFUVVMgPSBzdGF0dXM7CiAgICBfcHJvY19leGl0KHN0YXR1cyk7CiAgfTsKICB2YXIgX2V4aXQgPSBleGl0SlM7CiAgdmFyIG1heWJlRXhpdCA9ICgpID0+IHsKICAgIGlmICgha2VlcFJ1bnRpbWVBbGl2ZSgpKSB7CiAgICAgIHRyeSB7CiAgICAgICAgX2V4aXQoRVhJVFNUQVRVUyk7CiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBoYW5kbGVFeGNlcHRpb24oZSk7CiAgICAgIH0KICAgIH0KICB9OwogIHZhciBjYWxsVXNlckNhbGxiYWNrID0gZnVuYyA9PiB7CiAgICBpZiAoQUJPUlQpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdHJ5IHsKICAgICAgZnVuYygpOwogICAgICBtYXliZUV4aXQoKTsKICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgaGFuZGxlRXhjZXB0aW9uKGUpOwogICAgfQogIH07CiAgdmFyIF9lbXNjcmlwdGVuX2dldF9ub3cgPSAoKSA9PiBwZXJmb3JtYW5jZS5ub3coKTsKICB2YXIgX19zZXRpdGltZXJfanMgPSAod2hpY2gsIHRpbWVvdXRfbXMpID0+IHsKICAgIGlmICh0aW1lcnNbd2hpY2hdKSB7CiAgICAgIGNsZWFyVGltZW91dCh0aW1lcnNbd2hpY2hdLmlkKTsKICAgICAgZGVsZXRlIHRpbWVyc1t3aGljaF07CiAgICB9CiAgICBpZiAoIXRpbWVvdXRfbXMpIHJldHVybiAwOwogICAgdmFyIGlkID0gc2V0VGltZW91dCgoKSA9PiB7CiAgICAgIGRlbGV0ZSB0aW1lcnNbd2hpY2hdOwogICAgICBjYWxsVXNlckNhbGxiYWNrKCgpID0+IF9fZW1zY3JpcHRlbl90aW1lb3V0KHdoaWNoLCBfZW1zY3JpcHRlbl9nZXRfbm93KCkpKTsKICAgIH0sIHRpbWVvdXRfbXMpOwogICAgdGltZXJzW3doaWNoXSA9IHsKICAgICAgaWQsCiAgICAgIHRpbWVvdXRfbXMKICAgIH07CiAgICByZXR1cm4gMDsKICB9OwogIGZ1bmN0aW9uIF9jb3B5X3BpeGVsc18xKGNvbXBHX3B0ciwgbmJfcGl4ZWxzKSB7CiAgICBjb21wR19wdHIgPj49IDI7CiAgICBjb25zdCBpbWFnZURhdGEgPSBNb2R1bGUuaW1hZ2VEYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KG5iX3BpeGVscyk7CiAgICBjb25zdCBjb21wRyA9IEhFQVAzMi5zdWJhcnJheShjb21wR19wdHIsIGNvbXBHX3B0ciArIG5iX3BpeGVscyk7CiAgICBpbWFnZURhdGEuc2V0KGNvbXBHKTsKICB9CiAgZnVuY3Rpb24gX2NvcHlfcGl4ZWxzXzMoY29tcFJfcHRyLCBjb21wR19wdHIsIGNvbXBCX3B0ciwgbmJfcGl4ZWxzKSB7CiAgICBjb21wUl9wdHIgPj49IDI7CiAgICBjb21wR19wdHIgPj49IDI7CiAgICBjb21wQl9wdHIgPj49IDI7CiAgICBjb25zdCBpbWFnZURhdGEgPSBNb2R1bGUuaW1hZ2VEYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KG5iX3BpeGVscyAqIDMpOwogICAgY29uc3QgY29tcFIgPSBIRUFQMzIuc3ViYXJyYXkoY29tcFJfcHRyLCBjb21wUl9wdHIgKyBuYl9waXhlbHMpOwogICAgY29uc3QgY29tcEcgPSBIRUFQMzIuc3ViYXJyYXkoY29tcEdfcHRyLCBjb21wR19wdHIgKyBuYl9waXhlbHMpOwogICAgY29uc3QgY29tcEIgPSBIRUFQMzIuc3ViYXJyYXkoY29tcEJfcHRyLCBjb21wQl9wdHIgKyBuYl9waXhlbHMpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuYl9waXhlbHM7IGkrKykgewogICAgICBpbWFnZURhdGFbMyAqIGldID0gY29tcFJbaV07CiAgICAgIGltYWdlRGF0YVszICogaSArIDFdID0gY29tcEdbaV07CiAgICAgIGltYWdlRGF0YVszICogaSArIDJdID0gY29tcEJbaV07CiAgICB9CiAgfQogIGZ1bmN0aW9uIF9jb3B5X3BpeGVsc180KGNvbXBSX3B0ciwgY29tcEdfcHRyLCBjb21wQl9wdHIsIGNvbXBBX3B0ciwgbmJfcGl4ZWxzKSB7CiAgICBjb21wUl9wdHIgPj49IDI7CiAgICBjb21wR19wdHIgPj49IDI7CiAgICBjb21wQl9wdHIgPj49IDI7CiAgICBjb21wQV9wdHIgPj49IDI7CiAgICBjb25zdCBpbWFnZURhdGEgPSBNb2R1bGUuaW1hZ2VEYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KG5iX3BpeGVscyAqIDQpOwogICAgY29uc3QgY29tcFIgPSBIRUFQMzIuc3ViYXJyYXkoY29tcFJfcHRyLCBjb21wUl9wdHIgKyBuYl9waXhlbHMpOwogICAgY29uc3QgY29tcEcgPSBIRUFQMzIuc3ViYXJyYXkoY29tcEdfcHRyLCBjb21wR19wdHIgKyBuYl9waXhlbHMpOwogICAgY29uc3QgY29tcEIgPSBIRUFQMzIuc3ViYXJyYXkoY29tcEJfcHRyLCBjb21wQl9wdHIgKyBuYl9waXhlbHMpOwogICAgY29uc3QgY29tcEEgPSBIRUFQMzIuc3ViYXJyYXkoY29tcEFfcHRyLCBjb21wQV9wdHIgKyBuYl9waXhlbHMpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuYl9waXhlbHM7IGkrKykgewogICAgICBpbWFnZURhdGFbNCAqIGldID0gY29tcFJbaV07CiAgICAgIGltYWdlRGF0YVs0ICogaSArIDFdID0gY29tcEdbaV07CiAgICAgIGltYWdlRGF0YVs0ICogaSArIDJdID0gY29tcEJbaV07CiAgICAgIGltYWdlRGF0YVs0ICogaSArIDNdID0gY29tcEFbaV07CiAgICB9CiAgfQogIHZhciBnZXRIZWFwTWF4ID0gKCkgPT4gMjE0NzQ4MzY0ODsKICB2YXIgYWxpZ25NZW1vcnkgPSAoc2l6ZSwgYWxpZ25tZW50KSA9PiBNYXRoLmNlaWwoc2l6ZSAvIGFsaWdubWVudCkgKiBhbGlnbm1lbnQ7CiAgdmFyIGdyb3dNZW1vcnkgPSBzaXplID0+IHsKICAgIHZhciBvbGRIZWFwU2l6ZSA9IHdhc21NZW1vcnkuYnVmZmVyLmJ5dGVMZW5ndGg7CiAgICB2YXIgcGFnZXMgPSAoc2l6ZSAtIG9sZEhlYXBTaXplICsgNjU1MzUpIC8gNjU1MzYgfCAwOwogICAgdHJ5IHsKICAgICAgd2FzbU1lbW9yeS5ncm93KHBhZ2VzKTsKICAgICAgdXBkYXRlTWVtb3J5Vmlld3MoKTsKICAgICAgcmV0dXJuIDE7CiAgICB9IGNhdGNoIChlKSB7fQogIH07CiAgdmFyIF9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwID0gcmVxdWVzdGVkU2l6ZSA9PiB7CiAgICB2YXIgb2xkU2l6ZSA9IEhFQVBVOC5sZW5ndGg7CiAgICByZXF1ZXN0ZWRTaXplID4+Pj0gMDsKICAgIHZhciBtYXhIZWFwU2l6ZSA9IGdldEhlYXBNYXgoKTsKICAgIGlmIChyZXF1ZXN0ZWRTaXplID4gbWF4SGVhcFNpemUpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgZm9yICh2YXIgY3V0RG93biA9IDE7IGN1dERvd24gPD0gNDsgY3V0RG93biAqPSAyKSB7CiAgICAgIHZhciBvdmVyR3Jvd25IZWFwU2l6ZSA9IG9sZFNpemUgKiAoMSArIC4yIC8gY3V0RG93bik7CiAgICAgIG92ZXJHcm93bkhlYXBTaXplID0gTWF0aC5taW4ob3Zlckdyb3duSGVhcFNpemUsIHJlcXVlc3RlZFNpemUgKyAxMDA2NjMyOTYpOwogICAgICB2YXIgbmV3U2l6ZSA9IE1hdGgubWluKG1heEhlYXBTaXplLCBhbGlnbk1lbW9yeShNYXRoLm1heChyZXF1ZXN0ZWRTaXplLCBvdmVyR3Jvd25IZWFwU2l6ZSksIDY1NTM2KSk7CiAgICAgIHZhciByZXBsYWNlbWVudCA9IGdyb3dNZW1vcnkobmV3U2l6ZSk7CiAgICAgIGlmIChyZXBsYWNlbWVudCkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gZmFsc2U7CiAgfTsKICB2YXIgRU5WID0ge307CiAgdmFyIGdldEV4ZWN1dGFibGVOYW1lID0gKCkgPT4gdGhpc1Byb2dyYW0gfHwgIi4vdGhpcy5wcm9ncmFtIjsKICB2YXIgZ2V0RW52U3RyaW5ncyA9ICgpID0+IHsKICAgIGlmICghZ2V0RW52U3RyaW5ncy5zdHJpbmdzKSB7CiAgICAgIHZhciBsYW5nID0gKHR5cGVvZiBuYXZpZ2F0b3IgPT0gIm9iamVjdCIgJiYgbmF2aWdhdG9yLmxhbmd1YWdlIHx8ICJDIikucmVwbGFjZSgiLSIsICJfIikgKyAiLlVURi04IjsKICAgICAgdmFyIGVudiA9IHsKICAgICAgICBVU0VSOiAid2ViX3VzZXIiLAogICAgICAgIExPR05BTUU6ICJ3ZWJfdXNlciIsCiAgICAgICAgUEFUSDogIi8iLAogICAgICAgIFBXRDogIi8iLAogICAgICAgIEhPTUU6ICIvaG9tZS93ZWJfdXNlciIsCiAgICAgICAgTEFORzogbGFuZywKICAgICAgICBfOiBnZXRFeGVjdXRhYmxlTmFtZSgpCiAgICAgIH07CiAgICAgIGZvciAodmFyIHggaW4gRU5WKSB7CiAgICAgICAgaWYgKEVOVlt4XSA9PT0gdW5kZWZpbmVkKSBkZWxldGUgZW52W3hdO2Vsc2UgZW52W3hdID0gRU5WW3hdOwogICAgICB9CiAgICAgIHZhciBzdHJpbmdzID0gW107CiAgICAgIGZvciAodmFyIHggaW4gZW52KSB7CiAgICAgICAgc3RyaW5ncy5wdXNoKGAke3h9PSR7ZW52W3hdfWApOwogICAgICB9CiAgICAgIGdldEVudlN0cmluZ3Muc3RyaW5ncyA9IHN0cmluZ3M7CiAgICB9CiAgICByZXR1cm4gZ2V0RW52U3RyaW5ncy5zdHJpbmdzOwogIH07CiAgdmFyIHN0cmluZ1RvVVRGOEFycmF5ID0gKHN0ciwgaGVhcCwgb3V0SWR4LCBtYXhCeXRlc1RvV3JpdGUpID0+IHsKICAgIGlmICghKG1heEJ5dGVzVG9Xcml0ZSA+IDApKSByZXR1cm4gMDsKICAgIHZhciBzdGFydElkeCA9IG91dElkeDsKICAgIHZhciBlbmRJZHggPSBvdXRJZHggKyBtYXhCeXRlc1RvV3JpdGUgLSAxOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyArK2kpIHsKICAgICAgdmFyIHUgPSBzdHIuY29kZVBvaW50QXQoaSk7CiAgICAgIGlmICh1IDw9IDEyNykgewogICAgICAgIGlmIChvdXRJZHggPj0gZW5kSWR4KSBicmVhazsKICAgICAgICBoZWFwW291dElkeCsrXSA9IHU7CiAgICAgIH0gZWxzZSBpZiAodSA8PSAyMDQ3KSB7CiAgICAgICAgaWYgKG91dElkeCArIDEgPj0gZW5kSWR4KSBicmVhazsKICAgICAgICBoZWFwW291dElkeCsrXSA9IDE5MiB8IHUgPj4gNjsKICAgICAgICBoZWFwW291dElkeCsrXSA9IDEyOCB8IHUgJiA2MzsKICAgICAgfSBlbHNlIGlmICh1IDw9IDY1NTM1KSB7CiAgICAgICAgaWYgKG91dElkeCArIDIgPj0gZW5kSWR4KSBicmVhazsKICAgICAgICBoZWFwW291dElkeCsrXSA9IDIyNCB8IHUgPj4gMTI7CiAgICAgICAgaGVhcFtvdXRJZHgrK10gPSAxMjggfCB1ID4+IDYgJiA2MzsKICAgICAgICBoZWFwW291dElkeCsrXSA9IDEyOCB8IHUgJiA2MzsKICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAob3V0SWR4ICsgMyA+PSBlbmRJZHgpIGJyZWFrOwogICAgICAgIGhlYXBbb3V0SWR4KytdID0gMjQwIHwgdSA+PiAxODsKICAgICAgICBoZWFwW291dElkeCsrXSA9IDEyOCB8IHUgPj4gMTIgJiA2MzsKICAgICAgICBoZWFwW291dElkeCsrXSA9IDEyOCB8IHUgPj4gNiAmIDYzOwogICAgICAgIGhlYXBbb3V0SWR4KytdID0gMTI4IHwgdSAmIDYzOwogICAgICAgIGkrKzsKICAgICAgfQogICAgfQogICAgaGVhcFtvdXRJZHhdID0gMDsKICAgIHJldHVybiBvdXRJZHggLSBzdGFydElkeDsKICB9OwogIHZhciBzdHJpbmdUb1VURjggPSAoc3RyLCBvdXRQdHIsIG1heEJ5dGVzVG9Xcml0ZSkgPT4gc3RyaW5nVG9VVEY4QXJyYXkoc3RyLCBIRUFQVTgsIG91dFB0ciwgbWF4Qnl0ZXNUb1dyaXRlKTsKICB2YXIgX2Vudmlyb25fZ2V0ID0gKF9fZW52aXJvbiwgZW52aXJvbl9idWYpID0+IHsKICAgIHZhciBidWZTaXplID0gMDsKICAgIHZhciBlbnZwID0gMDsKICAgIGZvciAodmFyIHN0cmluZyBvZiBnZXRFbnZTdHJpbmdzKCkpIHsKICAgICAgdmFyIHB0ciA9IGVudmlyb25fYnVmICsgYnVmU2l6ZTsKICAgICAgSEVBUFUzMltfX2Vudmlyb24gKyBlbnZwID4+IDJdID0gcHRyOwogICAgICBidWZTaXplICs9IHN0cmluZ1RvVVRGOChzdHJpbmcsIHB0ciwgSW5maW5pdHkpICsgMTsKICAgICAgZW52cCArPSA0OwogICAgfQogICAgcmV0dXJuIDA7CiAgfTsKICB2YXIgbGVuZ3RoQnl0ZXNVVEY4ID0gc3RyID0+IHsKICAgIHZhciBsZW4gPSAwOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyArK2kpIHsKICAgICAgdmFyIGMgPSBzdHIuY2hhckNvZGVBdChpKTsKICAgICAgaWYgKGMgPD0gMTI3KSB7CiAgICAgICAgbGVuKys7CiAgICAgIH0gZWxzZSBpZiAoYyA8PSAyMDQ3KSB7CiAgICAgICAgbGVuICs9IDI7CiAgICAgIH0gZWxzZSBpZiAoYyA+PSA1NTI5NiAmJiBjIDw9IDU3MzQzKSB7CiAgICAgICAgbGVuICs9IDQ7CiAgICAgICAgKytpOwogICAgICB9IGVsc2UgewogICAgICAgIGxlbiArPSAzOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbGVuOwogIH07CiAgdmFyIF9lbnZpcm9uX3NpemVzX2dldCA9IChwZW52aXJvbl9jb3VudCwgcGVudmlyb25fYnVmX3NpemUpID0+IHsKICAgIHZhciBzdHJpbmdzID0gZ2V0RW52U3RyaW5ncygpOwogICAgSEVBUFUzMltwZW52aXJvbl9jb3VudCA+PiAyXSA9IHN0cmluZ3MubGVuZ3RoOwogICAgdmFyIGJ1ZlNpemUgPSAwOwogICAgZm9yICh2YXIgc3RyaW5nIG9mIHN0cmluZ3MpIHsKICAgICAgYnVmU2l6ZSArPSBsZW5ndGhCeXRlc1VURjgoc3RyaW5nKSArIDE7CiAgICB9CiAgICBIRUFQVTMyW3BlbnZpcm9uX2J1Zl9zaXplID4+IDJdID0gYnVmU2l6ZTsKICAgIHJldHVybiAwOwogIH07CiAgdmFyIElOVDUzX01BWCA9IDkwMDcxOTkyNTQ3NDA5OTI7CiAgdmFyIElOVDUzX01JTiA9IC05MDA3MTk5MjU0NzQwOTkyOwogIHZhciBiaWdpbnRUb0k1M0NoZWNrZWQgPSBudW0gPT4gbnVtIDwgSU5UNTNfTUlOIHx8IG51bSA+IElOVDUzX01BWCA/IE5hTiA6IE51bWJlcihudW0pOwogIGZ1bmN0aW9uIF9mZF9zZWVrKGZkLCBvZmZzZXQsIHdoZW5jZSwgbmV3T2Zmc2V0KSB7CiAgICBvZmZzZXQgPSBiaWdpbnRUb0k1M0NoZWNrZWQob2Zmc2V0KTsKICAgIHJldHVybiA3MDsKICB9CiAgdmFyIHByaW50Q2hhckJ1ZmZlcnMgPSBbbnVsbCwgW10sIFtdXTsKICB2YXIgVVRGOERlY29kZXIgPSB0eXBlb2YgVGV4dERlY29kZXIgIT0gInVuZGVmaW5lZCIgPyBuZXcgVGV4dERlY29kZXIoKSA6IHVuZGVmaW5lZDsKICB2YXIgZmluZFN0cmluZ0VuZCA9IChoZWFwT3JBcnJheSwgaWR4LCBtYXhCeXRlc1RvUmVhZCwgaWdub3JlTnVsKSA9PiB7CiAgICB2YXIgbWF4SWR4ID0gaWR4ICsgbWF4Qnl0ZXNUb1JlYWQ7CiAgICBpZiAoaWdub3JlTnVsKSByZXR1cm4gbWF4SWR4OwogICAgd2hpbGUgKGhlYXBPckFycmF5W2lkeF0gJiYgIShpZHggPj0gbWF4SWR4KSkgKytpZHg7CiAgICByZXR1cm4gaWR4OwogIH07CiAgdmFyIFVURjhBcnJheVRvU3RyaW5nID0gKGhlYXBPckFycmF5LCBpZHggPSAwLCBtYXhCeXRlc1RvUmVhZCwgaWdub3JlTnVsKSA9PiB7CiAgICB2YXIgZW5kUHRyID0gZmluZFN0cmluZ0VuZChoZWFwT3JBcnJheSwgaWR4LCBtYXhCeXRlc1RvUmVhZCwgaWdub3JlTnVsKTsKICAgIGlmIChlbmRQdHIgLSBpZHggPiAxNiAmJiBoZWFwT3JBcnJheS5idWZmZXIgJiYgVVRGOERlY29kZXIpIHsKICAgICAgcmV0dXJuIFVURjhEZWNvZGVyLmRlY29kZShoZWFwT3JBcnJheS5zdWJhcnJheShpZHgsIGVuZFB0cikpOwogICAgfQogICAgdmFyIHN0ciA9ICIiOwogICAgd2hpbGUgKGlkeCA8IGVuZFB0cikgewogICAgICB2YXIgdTAgPSBoZWFwT3JBcnJheVtpZHgrK107CiAgICAgIGlmICghKHUwICYgMTI4KSkgewogICAgICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHUwKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICB2YXIgdTEgPSBoZWFwT3JBcnJheVtpZHgrK10gJiA2MzsKICAgICAgaWYgKCh1MCAmIDIyNCkgPT0gMTkyKSB7CiAgICAgICAgc3RyICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKHUwICYgMzEpIDw8IDYgfCB1MSk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgdmFyIHUyID0gaGVhcE9yQXJyYXlbaWR4KytdICYgNjM7CiAgICAgIGlmICgodTAgJiAyNDApID09IDIyNCkgewogICAgICAgIHUwID0gKHUwICYgMTUpIDw8IDEyIHwgdTEgPDwgNiB8IHUyOwogICAgICB9IGVsc2UgewogICAgICAgIHUwID0gKHUwICYgNykgPDwgMTggfCB1MSA8PCAxMiB8IHUyIDw8IDYgfCBoZWFwT3JBcnJheVtpZHgrK10gJiA2MzsKICAgICAgfQogICAgICBpZiAodTAgPCA2NTUzNikgewogICAgICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHUwKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YXIgY2ggPSB1MCAtIDY1NTM2OwogICAgICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDU1Mjk2IHwgY2ggPj4gMTAsIDU2MzIwIHwgY2ggJiAxMDIzKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHN0cjsKICB9OwogIHZhciBwcmludENoYXIgPSAoc3RyZWFtLCBjdXJyKSA9PiB7CiAgICB2YXIgYnVmZmVyID0gcHJpbnRDaGFyQnVmZmVyc1tzdHJlYW1dOwogICAgaWYgKGN1cnIgPT09IDAgfHwgY3VyciA9PT0gMTApIHsKICAgICAgKHN0cmVhbSA9PT0gMSA/IG91dCA6IGVycikoVVRGOEFycmF5VG9TdHJpbmcoYnVmZmVyKSk7CiAgICAgIGJ1ZmZlci5sZW5ndGggPSAwOwogICAgfSBlbHNlIHsKICAgICAgYnVmZmVyLnB1c2goY3Vycik7CiAgICB9CiAgfTsKICB2YXIgVVRGOFRvU3RyaW5nID0gKHB0ciwgbWF4Qnl0ZXNUb1JlYWQsIGlnbm9yZU51bCkgPT4gcHRyID8gVVRGOEFycmF5VG9TdHJpbmcoSEVBUFU4LCBwdHIsIG1heEJ5dGVzVG9SZWFkLCBpZ25vcmVOdWwpIDogIiI7CiAgdmFyIF9mZF93cml0ZSA9IChmZCwgaW92LCBpb3ZjbnQsIHBudW0pID0+IHsKICAgIHZhciBudW0gPSAwOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpb3ZjbnQ7IGkrKykgewogICAgICB2YXIgcHRyID0gSEVBUFUzMltpb3YgPj4gMl07CiAgICAgIHZhciBsZW4gPSBIRUFQVTMyW2lvdiArIDQgPj4gMl07CiAgICAgIGlvdiArPSA4OwogICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGxlbjsgaisrKSB7CiAgICAgICAgcHJpbnRDaGFyKGZkLCBIRUFQVThbcHRyICsgal0pOwogICAgICB9CiAgICAgIG51bSArPSBsZW47CiAgICB9CiAgICBIRUFQVTMyW3BudW0gPj4gMl0gPSBudW07CiAgICByZXR1cm4gMDsKICB9OwogIGZ1bmN0aW9uIF9ncmF5X3RvX3JnYmEoY29tcEdfcHRyLCBuYl9waXhlbHMpIHsKICAgIGNvbXBHX3B0ciA+Pj0gMjsKICAgIGNvbnN0IGltYWdlRGF0YSA9IE1vZHVsZS5pbWFnZURhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkobmJfcGl4ZWxzICogNCk7CiAgICBjb25zdCBjb21wRyA9IEhFQVAzMi5zdWJhcnJheShjb21wR19wdHIsIGNvbXBHX3B0ciArIG5iX3BpeGVscyk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5iX3BpeGVsczsgaSsrKSB7CiAgICAgIGltYWdlRGF0YVs0ICogaV0gPSBpbWFnZURhdGFbNCAqIGkgKyAxXSA9IGltYWdlRGF0YVs0ICogaSArIDJdID0gY29tcEdbaV07CiAgICAgIGltYWdlRGF0YVs0ICogaSArIDNdID0gMjU1OwogICAgfQogIH0KICBmdW5jdGlvbiBfZ3JheWFfdG9fcmdiYShjb21wR19wdHIsIGNvbXBBX3B0ciwgbmJfcGl4ZWxzKSB7CiAgICBjb21wR19wdHIgPj49IDI7CiAgICBjb21wQV9wdHIgPj49IDI7CiAgICBjb25zdCBpbWFnZURhdGEgPSBNb2R1bGUuaW1hZ2VEYXRhID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KG5iX3BpeGVscyAqIDQpOwogICAgY29uc3QgY29tcEcgPSBIRUFQMzIuc3ViYXJyYXkoY29tcEdfcHRyLCBjb21wR19wdHIgKyBuYl9waXhlbHMpOwogICAgY29uc3QgY29tcEEgPSBIRUFQMzIuc3ViYXJyYXkoY29tcEFfcHRyLCBjb21wQV9wdHIgKyBuYl9waXhlbHMpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuYl9waXhlbHM7IGkrKykgewogICAgICBpbWFnZURhdGFbNCAqIGldID0gaW1hZ2VEYXRhWzQgKiBpICsgMV0gPSBpbWFnZURhdGFbNCAqIGkgKyAyXSA9IGNvbXBHW2ldOwogICAgICBpbWFnZURhdGFbNCAqIGkgKyAzXSA9IGNvbXBBW2ldOwogICAgfQogIH0KICBmdW5jdGlvbiBfanNQcmludFdhcm5pbmcobWVzc2FnZV9wdHIpIHsKICAgIGNvbnN0IG1lc3NhZ2UgPSBVVEY4VG9TdHJpbmcobWVzc2FnZV9wdHIpOwogICAgKE1vZHVsZS53YXJuIHx8IGNvbnNvbGUud2FybikoYE9wZW5KUEVHOiAke21lc3NhZ2V9YCk7CiAgfQogIGZ1bmN0aW9uIF9yZ2JfdG9fcmdiYShjb21wUl9wdHIsIGNvbXBHX3B0ciwgY29tcEJfcHRyLCBuYl9waXhlbHMpIHsKICAgIGNvbXBSX3B0ciA+Pj0gMjsKICAgIGNvbXBHX3B0ciA+Pj0gMjsKICAgIGNvbXBCX3B0ciA+Pj0gMjsKICAgIGNvbnN0IGltYWdlRGF0YSA9IE1vZHVsZS5pbWFnZURhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkobmJfcGl4ZWxzICogNCk7CiAgICBjb25zdCBjb21wUiA9IEhFQVAzMi5zdWJhcnJheShjb21wUl9wdHIsIGNvbXBSX3B0ciArIG5iX3BpeGVscyk7CiAgICBjb25zdCBjb21wRyA9IEhFQVAzMi5zdWJhcnJheShjb21wR19wdHIsIGNvbXBHX3B0ciArIG5iX3BpeGVscyk7CiAgICBjb25zdCBjb21wQiA9IEhFQVAzMi5zdWJhcnJheShjb21wQl9wdHIsIGNvbXBCX3B0ciArIG5iX3BpeGVscyk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG5iX3BpeGVsczsgaSsrKSB7CiAgICAgIGltYWdlRGF0YVs0ICogaV0gPSBjb21wUltpXTsKICAgICAgaW1hZ2VEYXRhWzQgKiBpICsgMV0gPSBjb21wR1tpXTsKICAgICAgaW1hZ2VEYXRhWzQgKiBpICsgMl0gPSBjb21wQltpXTsKICAgICAgaW1hZ2VEYXRhWzQgKiBpICsgM10gPSAyNTU7CiAgICB9CiAgfQogIGZ1bmN0aW9uIF9zdG9yZUVycm9yTWVzc2FnZShtZXNzYWdlX3B0cikgewogICAgY29uc3QgbWVzc2FnZSA9IFVURjhUb1N0cmluZyhtZXNzYWdlX3B0cik7CiAgICBpZiAoIU1vZHVsZS5lcnJvck1lc3NhZ2VzKSB7CiAgICAgIE1vZHVsZS5lcnJvck1lc3NhZ2VzID0gbWVzc2FnZTsKICAgIH0gZWxzZSB7CiAgICAgIE1vZHVsZS5lcnJvck1lc3NhZ2VzICs9ICJcbiIgKyBtZXNzYWdlOwogICAgfQogIH0KICB2YXIgd3JpdGVBcnJheVRvTWVtb3J5ID0gKGFycmF5LCBidWZmZXIpID0+IHsKICAgIEhFQVA4LnNldChhcnJheSwgYnVmZmVyKTsKICB9OwogIGlmIChNb2R1bGVbIm5vRXhpdFJ1bnRpbWUiXSkgbm9FeGl0UnVudGltZSA9IE1vZHVsZVsibm9FeGl0UnVudGltZSJdOwogIGlmIChNb2R1bGVbInByaW50Il0pIG91dCA9IE1vZHVsZVsicHJpbnQiXTsKICBpZiAoTW9kdWxlWyJwcmludEVyciJdKSBlcnIgPSBNb2R1bGVbInByaW50RXJyIl07CiAgaWYgKE1vZHVsZVsid2FzbUJpbmFyeSJdKSB3YXNtQmluYXJ5ID0gTW9kdWxlWyJ3YXNtQmluYXJ5Il07CiAgaWYgKE1vZHVsZVsiYXJndW1lbnRzIl0pIGFyZ3VtZW50c18gPSBNb2R1bGVbImFyZ3VtZW50cyJdOwogIGlmIChNb2R1bGVbInRoaXNQcm9ncmFtIl0pIHRoaXNQcm9ncmFtID0gTW9kdWxlWyJ0aGlzUHJvZ3JhbSJdOwogIGlmIChNb2R1bGVbInByZUluaXQiXSkgewogICAgaWYgKHR5cGVvZiBNb2R1bGVbInByZUluaXQiXSA9PSAiZnVuY3Rpb24iKSBNb2R1bGVbInByZUluaXQiXSA9IFtNb2R1bGVbInByZUluaXQiXV07CiAgICB3aGlsZSAoTW9kdWxlWyJwcmVJbml0Il0ubGVuZ3RoID4gMCkgewogICAgICBNb2R1bGVbInByZUluaXQiXS5zaGlmdCgpKCk7CiAgICB9CiAgfQogIE1vZHVsZVsid3JpdGVBcnJheVRvTWVtb3J5Il0gPSB3cml0ZUFycmF5VG9NZW1vcnk7CiAgdmFyIF9tYWxsb2MsIF9mcmVlLCBfanAyX2RlY29kZSwgX19lbXNjcmlwdGVuX3RpbWVvdXQ7CiAgZnVuY3Rpb24gYXNzaWduV2FzbUV4cG9ydHMod2FzbUV4cG9ydHMpIHsKICAgIE1vZHVsZVsiX21hbGxvYyJdID0gX21hbGxvYyA9IHdhc21FeHBvcnRzWyJ0Il07CiAgICBNb2R1bGVbIl9mcmVlIl0gPSBfZnJlZSA9IHdhc21FeHBvcnRzWyJ1Il07CiAgICBNb2R1bGVbIl9qcDJfZGVjb2RlIl0gPSBfanAyX2RlY29kZSA9IHdhc21FeHBvcnRzWyJ2Il07CiAgICBfX2Vtc2NyaXB0ZW5fdGltZW91dCA9IHdhc21FeHBvcnRzWyJ3Il07CiAgfQogIHZhciB3YXNtSW1wb3J0cyA9IHsKICAgIGs6IF9fYWJvcnRfanMsCiAgICBqOiBfX2Vtc2NyaXB0ZW5fcnVudGltZV9rZWVwYWxpdmVfY2xlYXIsCiAgICBsOiBfX3NldGl0aW1lcl9qcywKICAgIGY6IF9jb3B5X3BpeGVsc18xLAogICAgZTogX2NvcHlfcGl4ZWxzXzMsCiAgICBkOiBfY29weV9waXhlbHNfNCwKICAgIG06IF9lbXNjcmlwdGVuX3Jlc2l6ZV9oZWFwLAogICAgbzogX2Vudmlyb25fZ2V0LAogICAgcDogX2Vudmlyb25fc2l6ZXNfZ2V0LAogICAgbjogX2ZkX3NlZWssCiAgICBiOiBfZmRfd3JpdGUsCiAgICBxOiBfZ3JheV90b19yZ2JhLAogICAgaDogX2dyYXlhX3RvX3JnYmEsCiAgICBjOiBfanNQcmludFdhcm5pbmcsCiAgICBpOiBfcHJvY19leGl0LAogICAgZzogX3JnYl90b19yZ2JhLAogICAgYTogX3N0b3JlRXJyb3JNZXNzYWdlCiAgfTsKICBmdW5jdGlvbiBydW4oKSB7CiAgICBwcmVSdW4oKTsKICAgIGZ1bmN0aW9uIGRvUnVuKCkgewogICAgICBNb2R1bGVbImNhbGxlZFJ1biJdID0gdHJ1ZTsKICAgICAgaWYgKEFCT1JUKSByZXR1cm47CiAgICAgIGluaXRSdW50aW1lKCk7CiAgICAgIHJlYWR5UHJvbWlzZVJlc29sdmU/LihNb2R1bGUpOwogICAgICBNb2R1bGVbIm9uUnVudGltZUluaXRpYWxpemVkIl0/LigpOwogICAgICBwb3N0UnVuKCk7CiAgICB9CiAgICBpZiAoTW9kdWxlWyJzZXRTdGF0dXMiXSkgewogICAgICBNb2R1bGVbInNldFN0YXR1cyJdKCJSdW5uaW5nLi4uIik7CiAgICAgIHNldFRpbWVvdXQoKCkgPT4gewogICAgICAgIHNldFRpbWVvdXQoKCkgPT4gTW9kdWxlWyJzZXRTdGF0dXMiXSgiIiksIDEpOwogICAgICAgIGRvUnVuKCk7CiAgICAgIH0sIDEpOwogICAgfSBlbHNlIHsKICAgICAgZG9SdW4oKTsKICAgIH0KICB9CiAgdmFyIHdhc21FeHBvcnRzOwogIHdhc21FeHBvcnRzID0gYXdhaXQgY3JlYXRlV2FzbSgpOwogIHJ1bigpOwogIGlmIChydW50aW1lSW5pdGlhbGl6ZWQpIHsKICAgIG1vZHVsZVJ0biA9IE1vZHVsZTsKICB9IGVsc2UgewogICAgbW9kdWxlUnRuID0gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4gewogICAgICByZWFkeVByb21pc2VSZXNvbHZlID0gcmVzb2x2ZTsKICAgICAgcmVhZHlQcm9taXNlUmVqZWN0ID0gcmVqZWN0OwogICAgfSk7CiAgfQogIHJldHVybiBtb2R1bGVSdG47Cn0KLyogaGFybW9ueSBkZWZhdWx0IGV4cG9ydCAqLyBjb25zdCBvcGVuanBlZyA9IChPcGVuSlBFRyk7CjsvLyAuL3NyYy9jb3JlL2pweC5qcwoKCgoKCgoKCgpjbGFzcyBKcHhFcnJvciBleHRlbmRzIEJhc2VFeGNlcHRpb24gewogIGNvbnN0cnVjdG9yKG1zZykgewogICAgc3VwZXIobXNnLCAiSnB4RXJyb3IiKTsKICB9Cn0KY2xhc3MgSnB4SW1hZ2UgewogIHN0YXRpYyAjYnVmZmVyID0gbnVsbDsKICBzdGF0aWMgI2hhbmRsZXIgPSBudWxsOwogIHN0YXRpYyAjbW9kdWxlUHJvbWlzZSA9IG51bGw7CiAgc3RhdGljICN1c2VXYXNtID0gdHJ1ZTsKICBzdGF0aWMgI3VzZVdvcmtlckZldGNoID0gdHJ1ZTsKICBzdGF0aWMgI3dhc21VcmwgPSBudWxsOwogIHN0YXRpYyBzZXRPcHRpb25zKHsKICAgIGhhbmRsZXIsCiAgICB1c2VXYXNtLAogICAgdXNlV29ya2VyRmV0Y2gsCiAgICB3YXNtVXJsCiAgfSkgewogICAgdGhpcy4jdXNlV2FzbSA9IHVzZVdhc207CiAgICB0aGlzLiN1c2VXb3JrZXJGZXRjaCA9IHVzZVdvcmtlckZldGNoOwogICAgdGhpcy4jd2FzbVVybCA9IHdhc21Vcmw7CiAgICBpZiAoIXVzZVdvcmtlckZldGNoKSB7CiAgICAgIHRoaXMuI2hhbmRsZXIgPSBoYW5kbGVyOwogICAgfQogIH0KICBzdGF0aWMgYXN5bmMgI2dldEpzTW9kdWxlKGZhbGxiYWNrQ2FsbGJhY2spIHsKICAgIGNvbnN0IHBhdGggPSBgJHt0aGlzLiN3YXNtVXJsfW9wZW5qcGVnX25vd2FzbV9mYWxsYmFjay5qc2A7CiAgICBsZXQgaW5zdGFuY2UgPSBudWxsOwogICAgdHJ5IHsKICAgICAgY29uc3QgbW9kID0gYXdhaXQgaW1wb3J0KAogICAgICAvKndlYnBhY2tJZ25vcmU6IHRydWUqLwogICAgICAvKkB2aXRlLWlnbm9yZSovCiAgICAgIHBhdGgpOwogICAgICBpbnN0YW5jZSA9IG1vZC5kZWZhdWx0KCk7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIHdhcm4oYEpweEltYWdlI2dldEpzTW9kdWxlOiAke2V9YCk7CiAgICB9CiAgICBmYWxsYmFja0NhbGxiYWNrKGluc3RhbmNlKTsKICB9CiAgc3RhdGljIGFzeW5jICNpbnN0YW50aWF0ZVdhc20oZmFsbGJhY2tDYWxsYmFjaywgaW1wb3J0cywgc3VjY2Vzc0NhbGxiYWNrKSB7CiAgICBjb25zdCBmaWxlbmFtZSA9ICJvcGVuanBlZy53YXNtIjsKICAgIHRyeSB7CiAgICAgIGlmICghdGhpcy4jYnVmZmVyKSB7CiAgICAgICAgaWYgKHRoaXMuI3VzZVdvcmtlckZldGNoKSB7CiAgICAgICAgICB0aGlzLiNidWZmZXIgPSBhd2FpdCBmZXRjaEJpbmFyeURhdGEoYCR7dGhpcy4jd2FzbVVybH0ke2ZpbGVuYW1lfWApOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aGlzLiNidWZmZXIgPSBhd2FpdCB0aGlzLiNoYW5kbGVyLnNlbmRXaXRoUHJvbWlzZSgiRmV0Y2hCaW5hcnlEYXRhIiwgewogICAgICAgICAgICB0eXBlOiAid2FzbUZhY3RvcnkiLAogICAgICAgICAgICBmaWxlbmFtZQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGNvbnN0IHJlc3VsdHMgPSBhd2FpdCBXZWJBc3NlbWJseS5pbnN0YW50aWF0ZSh0aGlzLiNidWZmZXIsIGltcG9ydHMpOwogICAgICByZXR1cm4gc3VjY2Vzc0NhbGxiYWNrKHJlc3VsdHMuaW5zdGFuY2UpOwogICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgIHdhcm4oYEpweEltYWdlI2luc3RhbnRpYXRlV2FzbTogJHtyZWFzb259YCk7CiAgICAgIHRoaXMuI2dldEpzTW9kdWxlKGZhbGxiYWNrQ2FsbGJhY2spOwogICAgICByZXR1cm4gbnVsbDsKICAgIH0gZmluYWxseSB7CiAgICAgIHRoaXMuI2hhbmRsZXIgPSBudWxsOwogICAgfQogIH0KICBzdGF0aWMgYXN5bmMgZGVjb2RlKGJ5dGVzLCB7CiAgICBudW1Db21wb25lbnRzID0gNCwKICAgIGlzSW5kZXhlZENvbG9ybWFwID0gZmFsc2UsCiAgICBzbWFza0luRGF0YSA9IGZhbHNlLAogICAgcmVkdWNlUG93ZXIgPSAwCiAgfSA9IHt9KSB7CiAgICBpZiAoIXRoaXMuI21vZHVsZVByb21pc2UpIHsKICAgICAgY29uc3QgewogICAgICAgIHByb21pc2UsCiAgICAgICAgcmVzb2x2ZQogICAgICB9ID0gUHJvbWlzZS53aXRoUmVzb2x2ZXJzKCk7CiAgICAgIGNvbnN0IHByb21pc2VzID0gW3Byb21pc2VdOwogICAgICBpZiAoIXRoaXMuI3VzZVdhc20pIHsKICAgICAgICB0aGlzLiNnZXRKc01vZHVsZShyZXNvbHZlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBwcm9taXNlcy5wdXNoKG9wZW5qcGVnKHsKICAgICAgICAgIHdhcm46IHdhcm4sCiAgICAgICAgICBpbnN0YW50aWF0ZVdhc206IHRoaXMuI2luc3RhbnRpYXRlV2FzbS5iaW5kKHRoaXMsIHJlc29sdmUpCiAgICAgICAgfSkpOwogICAgICB9CiAgICAgIHRoaXMuI21vZHVsZVByb21pc2UgPSBQcm9taXNlLnJhY2UocHJvbWlzZXMpOwogICAgfQogICAgY29uc3QgbW9kdWxlID0gYXdhaXQgdGhpcy4jbW9kdWxlUHJvbWlzZTsKICAgIGlmICghbW9kdWxlKSB7CiAgICAgIHRocm93IG5ldyBKcHhFcnJvcigiT3BlbkpQRUcgZmFpbGVkIHRvIGluaXRpYWxpemUiKTsKICAgIH0KICAgIGxldCBwdHI7CiAgICB0cnkgewogICAgICBjb25zdCBzaXplID0gYnl0ZXMubGVuZ3RoOwogICAgICBwdHIgPSBtb2R1bGUuX21hbGxvYyhzaXplKTsKICAgICAgbW9kdWxlLndyaXRlQXJyYXlUb01lbW9yeShieXRlcywgcHRyKTsKICAgICAgY29uc3QgcmV0ID0gbW9kdWxlLl9qcDJfZGVjb2RlKHB0ciwgc2l6ZSwgbnVtQ29tcG9uZW50cyA+IDAgPyBudW1Db21wb25lbnRzIDogMCwgISFpc0luZGV4ZWRDb2xvcm1hcCwgISFzbWFza0luRGF0YSwgcmVkdWNlUG93ZXIpOwogICAgICBpZiAocmV0KSB7CiAgICAgICAgY29uc3QgewogICAgICAgICAgZXJyb3JNZXNzYWdlcwogICAgICAgIH0gPSBtb2R1bGU7CiAgICAgICAgaWYgKGVycm9yTWVzc2FnZXMpIHsKICAgICAgICAgIGRlbGV0ZSBtb2R1bGUuZXJyb3JNZXNzYWdlczsKICAgICAgICAgIHRocm93IG5ldyBKcHhFcnJvcihlcnJvck1lc3NhZ2VzKTsKICAgICAgICB9CiAgICAgICAgdGhyb3cgbmV3IEpweEVycm9yKCJVbmtub3duIGVycm9yIik7CiAgICAgIH0KICAgICAgY29uc3QgewogICAgICAgIGltYWdlRGF0YQogICAgICB9ID0gbW9kdWxlOwogICAgICBtb2R1bGUuaW1hZ2VEYXRhID0gbnVsbDsKICAgICAgcmV0dXJuIGltYWdlRGF0YTsKICAgIH0gZmluYWxseSB7CiAgICAgIGlmIChwdHIpIHsKICAgICAgICBtb2R1bGUuX2ZyZWUocHRyKTsKICAgICAgfQogICAgfQogIH0KICBzdGF0aWMgY2xlYW51cCgpIHsKICAgIHRoaXMuI21vZHVsZVByb21pc2UgPSBudWxsOwogIH0KICBzdGF0aWMgcGFyc2VJbWFnZVByb3BlcnRpZXMoc3RyZWFtKSB7CiAgICBsZXQgbmV3Qnl0ZSA9IHN0cmVhbS5nZXRCeXRlKCk7CiAgICB3aGlsZSAobmV3Qnl0ZSA+PSAwKSB7CiAgICAgIGNvbnN0IG9sZEJ5dGUgPSBuZXdCeXRlOwogICAgICBuZXdCeXRlID0gc3RyZWFtLmdldEJ5dGUoKTsKICAgICAgY29uc3QgY29kZSA9IG9sZEJ5dGUgPDwgOCB8IG5ld0J5dGU7CiAgICAgIGlmIChjb2RlID09PSAweGZmNTEpIHsKICAgICAgICBzdHJlYW0uc2tpcCg0KTsKICAgICAgICBjb25zdCBYc2l6ID0gc3RyZWFtLmdldEludDMyKCkgPj4+IDA7CiAgICAgICAgY29uc3QgWXNpeiA9IHN0cmVhbS5nZXRJbnQzMigpID4+PiAwOwogICAgICAgIGNvbnN0IFhPc2l6ID0gc3RyZWFtLmdldEludDMyKCkgPj4+IDA7CiAgICAgICAgY29uc3QgWU9zaXogPSBzdHJlYW0uZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgICBzdHJlYW0uc2tpcCgxNik7CiAgICAgICAgY29uc3QgQ3NpeiA9IHN0cmVhbS5nZXRVaW50MTYoKTsKICAgICAgICByZXR1cm4gewogICAgICAgICAgd2lkdGg6IFhzaXogLSBYT3NpeiwKICAgICAgICAgIGhlaWdodDogWXNpeiAtIFlPc2l6LAogICAgICAgICAgYml0c1BlckNvbXBvbmVudDogOCwKICAgICAgICAgIGNvbXBvbmVudHNDb3VudDogQ3NpegogICAgICAgIH07CiAgICAgIH0KICAgIH0KICAgIHRocm93IG5ldyBKcHhFcnJvcigiTm8gc2l6ZSBtYXJrZXIgZm91bmQgaW4gSlBYIHN0cmVhbSIpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvb3BlcmF0b3JfbGlzdC5qcwoKCgoKCgoKCgoKCgoKCgoKCmZ1bmN0aW9uIGFkZFN0YXRlKHBhcmVudFN0YXRlLCBwYXR0ZXJuLCBjaGVja0ZuLCBpdGVyYXRlRm4sIHByb2Nlc3NGbikgewogIGxldCBzdGF0ZSA9IHBhcmVudFN0YXRlOwogIGZvciAobGV0IGkgPSAwLCBpaSA9IHBhdHRlcm4ubGVuZ3RoIC0gMTsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IGl0ZW0gPSBwYXR0ZXJuW2ldOwogICAgc3RhdGUgPSBzdGF0ZVtpdGVtXSB8fD0gW107CiAgfQogIHN0YXRlW3BhdHRlcm4uYXQoLTEpXSA9IHsKICAgIGNoZWNrRm4sCiAgICBpdGVyYXRlRm4sCiAgICBwcm9jZXNzRm4KICB9Owp9CmNvbnN0IEluaXRpYWxTdGF0ZSA9IFtdOwphZGRTdGF0ZShJbml0aWFsU3RhdGUsIFtPUFMuc2F2ZSwgT1BTLnRyYW5zZm9ybSwgT1BTLnBhaW50SW5saW5lSW1hZ2VYT2JqZWN0LCBPUFMucmVzdG9yZV0sIG51bGwsIGZ1bmN0aW9uIGl0ZXJhdGVJbmxpbmVJbWFnZUdyb3VwKGNvbnRleHQsIGkpIHsKICBjb25zdCBmbkFycmF5ID0gY29udGV4dC5mbkFycmF5OwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjb250ZXh0LmlDdXJyIC0gMzsKICBjb25zdCBwb3MgPSAoaSAtIGlGaXJzdFNhdmUpICUgNDsKICBzd2l0Y2ggKHBvcykgewogICAgY2FzZSAwOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gT1BTLnNhdmU7CiAgICBjYXNlIDE6CiAgICAgIHJldHVybiBmbkFycmF5W2ldID09PSBPUFMudHJhbnNmb3JtOwogICAgY2FzZSAyOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gT1BTLnBhaW50SW5saW5lSW1hZ2VYT2JqZWN0OwogICAgY2FzZSAzOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gT1BTLnJlc3RvcmU7CiAgfQogIHRocm93IG5ldyBFcnJvcihgaXRlcmF0ZUlubGluZUltYWdlR3JvdXAgLSBpbnZhbGlkIHBvczogJHtwb3N9YCk7Cn0sIGZ1bmN0aW9uIGZvdW5kSW5saW5lSW1hZ2VHcm91cChjb250ZXh0LCBpKSB7CiAgY29uc3QgTUlOX0lNQUdFU19JTl9JTkxJTkVfSU1BR0VTX0JMT0NLID0gMTA7CiAgY29uc3QgTUFYX0lNQUdFU19JTl9JTkxJTkVfSU1BR0VTX0JMT0NLID0gMjAwOwogIGNvbnN0IE1BWF9XSURUSCA9IDEwMDA7CiAgY29uc3QgSU1BR0VfUEFERElORyA9IDE7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheSwKICAgIGFyZ3NBcnJheSA9IGNvbnRleHQuYXJnc0FycmF5OwogIGNvbnN0IGN1cnIgPSBjb250ZXh0LmlDdXJyOwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjdXJyIC0gMzsKICBjb25zdCBpRmlyc3RUcmFuc2Zvcm0gPSBjdXJyIC0gMjsKICBjb25zdCBpRmlyc3RQSUlYTyA9IGN1cnIgLSAxOwogIGNvbnN0IGNvdW50ID0gTWF0aC5taW4oTWF0aC5mbG9vcigoaSAtIGlGaXJzdFNhdmUpIC8gNCksIE1BWF9JTUFHRVNfSU5fSU5MSU5FX0lNQUdFU19CTE9DSyk7CiAgaWYgKGNvdW50IDwgTUlOX0lNQUdFU19JTl9JTkxJTkVfSU1BR0VTX0JMT0NLKSB7CiAgICByZXR1cm4gaSAtIChpIC0gaUZpcnN0U2F2ZSkgJSA0OwogIH0KICBsZXQgbWF4WCA9IDA7CiAgY29uc3QgbWFwID0gW107CiAgbGV0IG1heExpbmVIZWlnaHQgPSAwOwogIGxldCBjdXJyZW50WCA9IElNQUdFX1BBRERJTkcsCiAgICBjdXJyZW50WSA9IElNQUdFX1BBRERJTkc7CiAgZm9yIChsZXQgcSA9IDA7IHEgPCBjb3VudDsgcSsrKSB7CiAgICBjb25zdCB0cmFuc2Zvcm0gPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtICsgKHEgPDwgMildOwogICAgY29uc3QgaW1nID0gYXJnc0FycmF5W2lGaXJzdFBJSVhPICsgKHEgPDwgMildWzBdOwogICAgaWYgKGN1cnJlbnRYICsgaW1nLndpZHRoID4gTUFYX1dJRFRIKSB7CiAgICAgIG1heFggPSBNYXRoLm1heChtYXhYLCBjdXJyZW50WCk7CiAgICAgIGN1cnJlbnRZICs9IG1heExpbmVIZWlnaHQgKyAyICogSU1BR0VfUEFERElORzsKICAgICAgY3VycmVudFggPSAwOwogICAgICBtYXhMaW5lSGVpZ2h0ID0gMDsKICAgIH0KICAgIG1hcC5wdXNoKHsKICAgICAgdHJhbnNmb3JtLAogICAgICB4OiBjdXJyZW50WCwKICAgICAgeTogY3VycmVudFksCiAgICAgIHc6IGltZy53aWR0aCwKICAgICAgaDogaW1nLmhlaWdodAogICAgfSk7CiAgICBjdXJyZW50WCArPSBpbWcud2lkdGggKyAyICogSU1BR0VfUEFERElORzsKICAgIG1heExpbmVIZWlnaHQgPSBNYXRoLm1heChtYXhMaW5lSGVpZ2h0LCBpbWcuaGVpZ2h0KTsKICB9CiAgY29uc3QgaW1nV2lkdGggPSBNYXRoLm1heChtYXhYLCBjdXJyZW50WCkgKyBJTUFHRV9QQURESU5HOwogIGNvbnN0IGltZ0hlaWdodCA9IGN1cnJlbnRZICsgbWF4TGluZUhlaWdodCArIElNQUdFX1BBRERJTkc7CiAgY29uc3QgaW1nRGF0YSA9IG5ldyBVaW50OEFycmF5KGltZ1dpZHRoICogaW1nSGVpZ2h0ICogNCk7CiAgY29uc3QgaW1nUm93U2l6ZSA9IGltZ1dpZHRoIDw8IDI7CiAgZm9yIChsZXQgcSA9IDA7IHEgPCBjb3VudDsgcSsrKSB7CiAgICBjb25zdCBkYXRhID0gYXJnc0FycmF5W2lGaXJzdFBJSVhPICsgKHEgPDwgMildWzBdLmRhdGE7CiAgICBjb25zdCByb3dTaXplID0gbWFwW3FdLncgPDwgMjsKICAgIGxldCBkYXRhT2Zmc2V0ID0gMDsKICAgIGxldCBvZmZzZXQgPSBtYXBbcV0ueCArIG1hcFtxXS55ICogaW1nV2lkdGggPDwgMjsKICAgIGltZ0RhdGEuc2V0KGRhdGEuc3ViYXJyYXkoMCwgcm93U2l6ZSksIG9mZnNldCAtIGltZ1Jvd1NpemUpOwogICAgZm9yIChsZXQgayA9IDAsIGtrID0gbWFwW3FdLmg7IGsgPCBrazsgaysrKSB7CiAgICAgIGltZ0RhdGEuc2V0KGRhdGEuc3ViYXJyYXkoZGF0YU9mZnNldCwgZGF0YU9mZnNldCArIHJvd1NpemUpLCBvZmZzZXQpOwogICAgICBkYXRhT2Zmc2V0ICs9IHJvd1NpemU7CiAgICAgIG9mZnNldCArPSBpbWdSb3dTaXplOwogICAgfQogICAgaW1nRGF0YS5zZXQoZGF0YS5zdWJhcnJheShkYXRhT2Zmc2V0IC0gcm93U2l6ZSwgZGF0YU9mZnNldCksIG9mZnNldCk7CiAgICB3aGlsZSAob2Zmc2V0ID49IDApIHsKICAgICAgZGF0YVtvZmZzZXQgLSA0XSA9IGRhdGFbb2Zmc2V0XTsKICAgICAgZGF0YVtvZmZzZXQgLSAzXSA9IGRhdGFbb2Zmc2V0ICsgMV07CiAgICAgIGRhdGFbb2Zmc2V0IC0gMl0gPSBkYXRhW29mZnNldCArIDJdOwogICAgICBkYXRhW29mZnNldCAtIDFdID0gZGF0YVtvZmZzZXQgKyAzXTsKICAgICAgZGF0YVtvZmZzZXQgKyByb3dTaXplXSA9IGRhdGFbb2Zmc2V0ICsgcm93U2l6ZSAtIDRdOwogICAgICBkYXRhW29mZnNldCArIHJvd1NpemUgKyAxXSA9IGRhdGFbb2Zmc2V0ICsgcm93U2l6ZSAtIDNdOwogICAgICBkYXRhW29mZnNldCArIHJvd1NpemUgKyAyXSA9IGRhdGFbb2Zmc2V0ICsgcm93U2l6ZSAtIDJdOwogICAgICBkYXRhW29mZnNldCArIHJvd1NpemUgKyAzXSA9IGRhdGFbb2Zmc2V0ICsgcm93U2l6ZSAtIDFdOwogICAgICBvZmZzZXQgLT0gaW1nUm93U2l6ZTsKICAgIH0KICB9CiAgY29uc3QgaW1nID0gewogICAgd2lkdGg6IGltZ1dpZHRoLAogICAgaGVpZ2h0OiBpbWdIZWlnaHQKICB9OwogIGlmIChjb250ZXh0LmlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKSB7CiAgICBjb25zdCBjYW52YXMgPSBuZXcgT2Zmc2NyZWVuQ2FudmFzKGltZ1dpZHRoLCBpbWdIZWlnaHQpOwogICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIik7CiAgICBjdHgucHV0SW1hZ2VEYXRhKG5ldyBJbWFnZURhdGEobmV3IFVpbnQ4Q2xhbXBlZEFycmF5KGltZ0RhdGEuYnVmZmVyKSwgaW1nV2lkdGgsIGltZ0hlaWdodCksIDAsIDApOwogICAgaW1nLmJpdG1hcCA9IGNhbnZhcy50cmFuc2ZlclRvSW1hZ2VCaXRtYXAoKTsKICAgIGltZy5kYXRhID0gbnVsbDsKICB9IGVsc2UgewogICAgaW1nLmtpbmQgPSBJbWFnZUtpbmQuUkdCQV8zMkJQUDsKICAgIGltZy5kYXRhID0gaW1nRGF0YTsKICB9CiAgZm5BcnJheS5zcGxpY2UoaUZpcnN0U2F2ZSwgY291bnQgKiA0LCBPUFMucGFpbnRJbmxpbmVJbWFnZVhPYmplY3RHcm91cCk7CiAgYXJnc0FycmF5LnNwbGljZShpRmlyc3RTYXZlLCBjb3VudCAqIDQsIFtpbWcsIG1hcF0pOwogIHJldHVybiBpRmlyc3RTYXZlICsgMTsKfSk7CmFkZFN0YXRlKEluaXRpYWxTdGF0ZSwgW09QUy5zYXZlLCBPUFMudHJhbnNmb3JtLCBPUFMucGFpbnRJbWFnZU1hc2tYT2JqZWN0LCBPUFMucmVzdG9yZV0sIG51bGwsIGZ1bmN0aW9uIGl0ZXJhdGVJbWFnZU1hc2tHcm91cChjb250ZXh0LCBpKSB7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheTsKICBjb25zdCBpRmlyc3RTYXZlID0gY29udGV4dC5pQ3VyciAtIDM7CiAgY29uc3QgcG9zID0gKGkgLSBpRmlyc3RTYXZlKSAlIDQ7CiAgc3dpdGNoIChwb3MpIHsKICAgIGNhc2UgMDoKICAgICAgcmV0dXJuIGZuQXJyYXlbaV0gPT09IE9QUy5zYXZlOwogICAgY2FzZSAxOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gT1BTLnRyYW5zZm9ybTsKICAgIGNhc2UgMjoKICAgICAgcmV0dXJuIGZuQXJyYXlbaV0gPT09IE9QUy5wYWludEltYWdlTWFza1hPYmplY3Q7CiAgICBjYXNlIDM6CiAgICAgIHJldHVybiBmbkFycmF5W2ldID09PSBPUFMucmVzdG9yZTsKICB9CiAgdGhyb3cgbmV3IEVycm9yKGBpdGVyYXRlSW1hZ2VNYXNrR3JvdXAgLSBpbnZhbGlkIHBvczogJHtwb3N9YCk7Cn0sIGZ1bmN0aW9uIGZvdW5kSW1hZ2VNYXNrR3JvdXAoY29udGV4dCwgaSkgewogIGNvbnN0IE1JTl9JTUFHRVNfSU5fTUFTS1NfQkxPQ0sgPSAxMDsKICBjb25zdCBNQVhfSU1BR0VTX0lOX01BU0tTX0JMT0NLID0gMTAwOwogIGNvbnN0IE1BWF9TQU1FX0lNQUdFU19JTl9NQVNLU19CTE9DSyA9IDEwMDA7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheSwKICAgIGFyZ3NBcnJheSA9IGNvbnRleHQuYXJnc0FycmF5OwogIGNvbnN0IGN1cnIgPSBjb250ZXh0LmlDdXJyOwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjdXJyIC0gMzsKICBjb25zdCBpRmlyc3RUcmFuc2Zvcm0gPSBjdXJyIC0gMjsKICBjb25zdCBpRmlyc3RQSU1YTyA9IGN1cnIgLSAxOwogIGxldCBjb3VudCA9IE1hdGguZmxvb3IoKGkgLSBpRmlyc3RTYXZlKSAvIDQpOwogIGlmIChjb3VudCA8IE1JTl9JTUFHRVNfSU5fTUFTS1NfQkxPQ0spIHsKICAgIHJldHVybiBpIC0gKGkgLSBpRmlyc3RTYXZlKSAlIDQ7CiAgfQogIGxldCBpc1NhbWVJbWFnZSA9IGZhbHNlOwogIGxldCBpVHJhbnNmb3JtLCB0cmFuc2Zvcm1BcmdzOwogIGNvbnN0IGZpcnN0UElNWE9BcmcwID0gYXJnc0FycmF5W2lGaXJzdFBJTVhPXVswXTsKICBjb25zdCBmaXJzdFRyYW5zZm9ybUFyZzAgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVswXSwKICAgIGZpcnN0VHJhbnNmb3JtQXJnMSA9IGFyZ3NBcnJheVtpRmlyc3RUcmFuc2Zvcm1dWzFdLAogICAgZmlyc3RUcmFuc2Zvcm1BcmcyID0gYXJnc0FycmF5W2lGaXJzdFRyYW5zZm9ybV1bMl0sCiAgICBmaXJzdFRyYW5zZm9ybUFyZzMgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVszXTsKICBpZiAoZmlyc3RUcmFuc2Zvcm1BcmcxID09PSBmaXJzdFRyYW5zZm9ybUFyZzIpIHsKICAgIGlzU2FtZUltYWdlID0gdHJ1ZTsKICAgIGlUcmFuc2Zvcm0gPSBpRmlyc3RUcmFuc2Zvcm0gKyA0OwogICAgbGV0IGlQSU1YTyA9IGlGaXJzdFBJTVhPICsgNDsKICAgIGZvciAobGV0IHEgPSAxOyBxIDwgY291bnQ7IHErKywgaVRyYW5zZm9ybSArPSA0LCBpUElNWE8gKz0gNCkgewogICAgICB0cmFuc2Zvcm1BcmdzID0gYXJnc0FycmF5W2lUcmFuc2Zvcm1dOwogICAgICBpZiAoYXJnc0FycmF5W2lQSU1YT11bMF0gIT09IGZpcnN0UElNWE9BcmcwIHx8IHRyYW5zZm9ybUFyZ3NbMF0gIT09IGZpcnN0VHJhbnNmb3JtQXJnMCB8fCB0cmFuc2Zvcm1BcmdzWzFdICE9PSBmaXJzdFRyYW5zZm9ybUFyZzEgfHwgdHJhbnNmb3JtQXJnc1syXSAhPT0gZmlyc3RUcmFuc2Zvcm1BcmcyIHx8IHRyYW5zZm9ybUFyZ3NbM10gIT09IGZpcnN0VHJhbnNmb3JtQXJnMykgewogICAgICAgIGlmIChxIDwgTUlOX0lNQUdFU19JTl9NQVNLU19CTE9DSykgewogICAgICAgICAgaXNTYW1lSW1hZ2UgPSBmYWxzZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY291bnQgPSBxOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogIH0KICBpZiAoaXNTYW1lSW1hZ2UpIHsKICAgIGNvdW50ID0gTWF0aC5taW4oY291bnQsIE1BWF9TQU1FX0lNQUdFU19JTl9NQVNLU19CTE9DSyk7CiAgICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KGNvdW50ICogMik7CiAgICBpVHJhbnNmb3JtID0gaUZpcnN0VHJhbnNmb3JtOwogICAgZm9yIChsZXQgcSA9IDA7IHEgPCBjb3VudDsgcSsrLCBpVHJhbnNmb3JtICs9IDQpIHsKICAgICAgdHJhbnNmb3JtQXJncyA9IGFyZ3NBcnJheVtpVHJhbnNmb3JtXTsKICAgICAgcG9zaXRpb25zW3EgPDwgMV0gPSB0cmFuc2Zvcm1BcmdzWzRdOwogICAgICBwb3NpdGlvbnNbKHEgPDwgMSkgKyAxXSA9IHRyYW5zZm9ybUFyZ3NbNV07CiAgICB9CiAgICBmbkFycmF5LnNwbGljZShpRmlyc3RTYXZlLCBjb3VudCAqIDQsIE9QUy5wYWludEltYWdlTWFza1hPYmplY3RSZXBlYXQpOwogICAgYXJnc0FycmF5LnNwbGljZShpRmlyc3RTYXZlLCBjb3VudCAqIDQsIFtmaXJzdFBJTVhPQXJnMCwgZmlyc3RUcmFuc2Zvcm1BcmcwLCBmaXJzdFRyYW5zZm9ybUFyZzEsIGZpcnN0VHJhbnNmb3JtQXJnMiwgZmlyc3RUcmFuc2Zvcm1BcmczLCBwb3NpdGlvbnNdKTsKICB9IGVsc2UgewogICAgY291bnQgPSBNYXRoLm1pbihjb3VudCwgTUFYX0lNQUdFU19JTl9NQVNLU19CTE9DSyk7CiAgICBjb25zdCBpbWFnZXMgPSBbXTsKICAgIGZvciAobGV0IHEgPSAwOyBxIDwgY291bnQ7IHErKykgewogICAgICB0cmFuc2Zvcm1BcmdzID0gYXJnc0FycmF5W2lGaXJzdFRyYW5zZm9ybSArIChxIDw8IDIpXTsKICAgICAgY29uc3QgbWFza1BhcmFtcyA9IGFyZ3NBcnJheVtpRmlyc3RQSU1YTyArIChxIDw8IDIpXVswXTsKICAgICAgaW1hZ2VzLnB1c2goewogICAgICAgIGRhdGE6IG1hc2tQYXJhbXMuZGF0YSwKICAgICAgICB3aWR0aDogbWFza1BhcmFtcy53aWR0aCwKICAgICAgICBoZWlnaHQ6IG1hc2tQYXJhbXMuaGVpZ2h0LAogICAgICAgIGludGVycG9sYXRlOiBtYXNrUGFyYW1zLmludGVycG9sYXRlLAogICAgICAgIGNvdW50OiBtYXNrUGFyYW1zLmNvdW50LAogICAgICAgIHRyYW5zZm9ybTogdHJhbnNmb3JtQXJncwogICAgICB9KTsKICAgIH0KICAgIGZuQXJyYXkuc3BsaWNlKGlGaXJzdFNhdmUsIGNvdW50ICogNCwgT1BTLnBhaW50SW1hZ2VNYXNrWE9iamVjdEdyb3VwKTsKICAgIGFyZ3NBcnJheS5zcGxpY2UoaUZpcnN0U2F2ZSwgY291bnQgKiA0LCBbaW1hZ2VzXSk7CiAgfQogIHJldHVybiBpRmlyc3RTYXZlICsgMTsKfSk7CmFkZFN0YXRlKEluaXRpYWxTdGF0ZSwgW09QUy5zYXZlLCBPUFMudHJhbnNmb3JtLCBPUFMucGFpbnRJbWFnZVhPYmplY3QsIE9QUy5yZXN0b3JlXSwgZnVuY3Rpb24gKGNvbnRleHQpIHsKICBjb25zdCBhcmdzQXJyYXkgPSBjb250ZXh0LmFyZ3NBcnJheTsKICBjb25zdCBpRmlyc3RUcmFuc2Zvcm0gPSBjb250ZXh0LmlDdXJyIC0gMjsKICByZXR1cm4gYXJnc0FycmF5W2lGaXJzdFRyYW5zZm9ybV1bMV0gPT09IDAgJiYgYXJnc0FycmF5W2lGaXJzdFRyYW5zZm9ybV1bMl0gPT09IDA7Cn0sIGZ1bmN0aW9uIGl0ZXJhdGVJbWFnZUdyb3VwKGNvbnRleHQsIGkpIHsKICBjb25zdCBmbkFycmF5ID0gY29udGV4dC5mbkFycmF5LAogICAgYXJnc0FycmF5ID0gY29udGV4dC5hcmdzQXJyYXk7CiAgY29uc3QgaUZpcnN0U2F2ZSA9IGNvbnRleHQuaUN1cnIgLSAzOwogIGNvbnN0IHBvcyA9IChpIC0gaUZpcnN0U2F2ZSkgJSA0OwogIHN3aXRjaCAocG9zKSB7CiAgICBjYXNlIDA6CiAgICAgIHJldHVybiBmbkFycmF5W2ldID09PSBPUFMuc2F2ZTsKICAgIGNhc2UgMToKICAgICAgaWYgKGZuQXJyYXlbaV0gIT09IE9QUy50cmFuc2Zvcm0pIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgY29uc3QgaUZpcnN0VHJhbnNmb3JtID0gY29udGV4dC5pQ3VyciAtIDI7CiAgICAgIGNvbnN0IGZpcnN0VHJhbnNmb3JtQXJnMCA9IGFyZ3NBcnJheVtpRmlyc3RUcmFuc2Zvcm1dWzBdOwogICAgICBjb25zdCBmaXJzdFRyYW5zZm9ybUFyZzMgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVszXTsKICAgICAgaWYgKGFyZ3NBcnJheVtpXVswXSAhPT0gZmlyc3RUcmFuc2Zvcm1BcmcwIHx8IGFyZ3NBcnJheVtpXVsxXSAhPT0gMCB8fCBhcmdzQXJyYXlbaV1bMl0gIT09IDAgfHwgYXJnc0FycmF5W2ldWzNdICE9PSBmaXJzdFRyYW5zZm9ybUFyZzMpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgcmV0dXJuIHRydWU7CiAgICBjYXNlIDI6CiAgICAgIGlmIChmbkFycmF5W2ldICE9PSBPUFMucGFpbnRJbWFnZVhPYmplY3QpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgY29uc3QgaUZpcnN0UElYTyA9IGNvbnRleHQuaUN1cnIgLSAxOwogICAgICBjb25zdCBmaXJzdFBJWE9BcmcwID0gYXJnc0FycmF5W2lGaXJzdFBJWE9dWzBdOwogICAgICBpZiAoYXJnc0FycmF5W2ldWzBdICE9PSBmaXJzdFBJWE9BcmcwKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIHJldHVybiB0cnVlOwogICAgY2FzZSAzOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gT1BTLnJlc3RvcmU7CiAgfQogIHRocm93IG5ldyBFcnJvcihgaXRlcmF0ZUltYWdlR3JvdXAgLSBpbnZhbGlkIHBvczogJHtwb3N9YCk7Cn0sIGZ1bmN0aW9uIChjb250ZXh0LCBpKSB7CiAgY29uc3QgTUlOX0lNQUdFU19JTl9CTE9DSyA9IDM7CiAgY29uc3QgTUFYX0lNQUdFU19JTl9CTE9DSyA9IDEwMDA7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheSwKICAgIGFyZ3NBcnJheSA9IGNvbnRleHQuYXJnc0FycmF5OwogIGNvbnN0IGN1cnIgPSBjb250ZXh0LmlDdXJyOwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjdXJyIC0gMzsKICBjb25zdCBpRmlyc3RUcmFuc2Zvcm0gPSBjdXJyIC0gMjsKICBjb25zdCBpRmlyc3RQSVhPID0gY3VyciAtIDE7CiAgY29uc3QgZmlyc3RQSVhPQXJnMCA9IGFyZ3NBcnJheVtpRmlyc3RQSVhPXVswXTsKICBjb25zdCBmaXJzdFRyYW5zZm9ybUFyZzAgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVswXTsKICBjb25zdCBmaXJzdFRyYW5zZm9ybUFyZzMgPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXVszXTsKICBjb25zdCBjb3VudCA9IE1hdGgubWluKE1hdGguZmxvb3IoKGkgLSBpRmlyc3RTYXZlKSAvIDQpLCBNQVhfSU1BR0VTX0lOX0JMT0NLKTsKICBpZiAoY291bnQgPCBNSU5fSU1BR0VTX0lOX0JMT0NLKSB7CiAgICByZXR1cm4gaSAtIChpIC0gaUZpcnN0U2F2ZSkgJSA0OwogIH0KICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KGNvdW50ICogMik7CiAgbGV0IGlUcmFuc2Zvcm0gPSBpRmlyc3RUcmFuc2Zvcm07CiAgZm9yIChsZXQgcSA9IDA7IHEgPCBjb3VudDsgcSsrLCBpVHJhbnNmb3JtICs9IDQpIHsKICAgIGNvbnN0IHRyYW5zZm9ybUFyZ3MgPSBhcmdzQXJyYXlbaVRyYW5zZm9ybV07CiAgICBwb3NpdGlvbnNbcSA8PCAxXSA9IHRyYW5zZm9ybUFyZ3NbNF07CiAgICBwb3NpdGlvbnNbKHEgPDwgMSkgKyAxXSA9IHRyYW5zZm9ybUFyZ3NbNV07CiAgfQogIGNvbnN0IGFyZ3MgPSBbZmlyc3RQSVhPQXJnMCwgZmlyc3RUcmFuc2Zvcm1BcmcwLCBmaXJzdFRyYW5zZm9ybUFyZzMsIHBvc2l0aW9uc107CiAgZm5BcnJheS5zcGxpY2UoaUZpcnN0U2F2ZSwgY291bnQgKiA0LCBPUFMucGFpbnRJbWFnZVhPYmplY3RSZXBlYXQpOwogIGFyZ3NBcnJheS5zcGxpY2UoaUZpcnN0U2F2ZSwgY291bnQgKiA0LCBhcmdzKTsKICByZXR1cm4gaUZpcnN0U2F2ZSArIDE7Cn0pOwphZGRTdGF0ZShJbml0aWFsU3RhdGUsIFtPUFMuYmVnaW5UZXh0LCBPUFMuc2V0Rm9udCwgT1BTLnNldFRleHRNYXRyaXgsIE9QUy5zaG93VGV4dCwgT1BTLmVuZFRleHRdLCBudWxsLCBmdW5jdGlvbiBpdGVyYXRlU2hvd1RleHRHcm91cChjb250ZXh0LCBpKSB7CiAgY29uc3QgZm5BcnJheSA9IGNvbnRleHQuZm5BcnJheSwKICAgIGFyZ3NBcnJheSA9IGNvbnRleHQuYXJnc0FycmF5OwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjb250ZXh0LmlDdXJyIC0gNDsKICBjb25zdCBwb3MgPSAoaSAtIGlGaXJzdFNhdmUpICUgNTsKICBzd2l0Y2ggKHBvcykgewogICAgY2FzZSAwOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gT1BTLmJlZ2luVGV4dDsKICAgIGNhc2UgMToKICAgICAgcmV0dXJuIGZuQXJyYXlbaV0gPT09IE9QUy5zZXRGb250OwogICAgY2FzZSAyOgogICAgICByZXR1cm4gZm5BcnJheVtpXSA9PT0gT1BTLnNldFRleHRNYXRyaXg7CiAgICBjYXNlIDM6CiAgICAgIGlmIChmbkFycmF5W2ldICE9PSBPUFMuc2hvd1RleHQpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgY29uc3QgaUZpcnN0U2V0Rm9udCA9IGNvbnRleHQuaUN1cnIgLSAzOwogICAgICBjb25zdCBmaXJzdFNldEZvbnRBcmcwID0gYXJnc0FycmF5W2lGaXJzdFNldEZvbnRdWzBdOwogICAgICBjb25zdCBmaXJzdFNldEZvbnRBcmcxID0gYXJnc0FycmF5W2lGaXJzdFNldEZvbnRdWzFdOwogICAgICBpZiAoYXJnc0FycmF5W2ldWzBdICE9PSBmaXJzdFNldEZvbnRBcmcwIHx8IGFyZ3NBcnJheVtpXVsxXSAhPT0gZmlyc3RTZXRGb250QXJnMSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICByZXR1cm4gdHJ1ZTsKICAgIGNhc2UgNDoKICAgICAgcmV0dXJuIGZuQXJyYXlbaV0gPT09IE9QUy5lbmRUZXh0OwogIH0KICB0aHJvdyBuZXcgRXJyb3IoYGl0ZXJhdGVTaG93VGV4dEdyb3VwIC0gaW52YWxpZCBwb3M6ICR7cG9zfWApOwp9LCBmdW5jdGlvbiAoY29udGV4dCwgaSkgewogIGNvbnN0IE1JTl9DSEFSU19JTl9CTE9DSyA9IDM7CiAgY29uc3QgTUFYX0NIQVJTX0lOX0JMT0NLID0gMTAwMDsKICBjb25zdCBmbkFycmF5ID0gY29udGV4dC5mbkFycmF5LAogICAgYXJnc0FycmF5ID0gY29udGV4dC5hcmdzQXJyYXk7CiAgY29uc3QgY3VyciA9IGNvbnRleHQuaUN1cnI7CiAgY29uc3QgaUZpcnN0QmVnaW5UZXh0ID0gY3VyciAtIDQ7CiAgY29uc3QgaUZpcnN0U2V0Rm9udCA9IGN1cnIgLSAzOwogIGNvbnN0IGlGaXJzdFNldFRleHRNYXRyaXggPSBjdXJyIC0gMjsKICBjb25zdCBpRmlyc3RTaG93VGV4dCA9IGN1cnIgLSAxOwogIGNvbnN0IGlGaXJzdEVuZFRleHQgPSBjdXJyOwogIGNvbnN0IGZpcnN0U2V0Rm9udEFyZzAgPSBhcmdzQXJyYXlbaUZpcnN0U2V0Rm9udF1bMF07CiAgY29uc3QgZmlyc3RTZXRGb250QXJnMSA9IGFyZ3NBcnJheVtpRmlyc3RTZXRGb250XVsxXTsKICBsZXQgY291bnQgPSBNYXRoLm1pbihNYXRoLmZsb29yKChpIC0gaUZpcnN0QmVnaW5UZXh0KSAvIDUpLCBNQVhfQ0hBUlNfSU5fQkxPQ0spOwogIGlmIChjb3VudCA8IE1JTl9DSEFSU19JTl9CTE9DSykgewogICAgcmV0dXJuIGkgLSAoaSAtIGlGaXJzdEJlZ2luVGV4dCkgJSA1OwogIH0KICBsZXQgaUZpcnN0ID0gaUZpcnN0QmVnaW5UZXh0OwogIGlmIChpRmlyc3RCZWdpblRleHQgPj0gNCAmJiBmbkFycmF5W2lGaXJzdEJlZ2luVGV4dCAtIDRdID09PSBmbkFycmF5W2lGaXJzdFNldEZvbnRdICYmIGZuQXJyYXlbaUZpcnN0QmVnaW5UZXh0IC0gM10gPT09IGZuQXJyYXlbaUZpcnN0U2V0VGV4dE1hdHJpeF0gJiYgZm5BcnJheVtpRmlyc3RCZWdpblRleHQgLSAyXSA9PT0gZm5BcnJheVtpRmlyc3RTaG93VGV4dF0gJiYgZm5BcnJheVtpRmlyc3RCZWdpblRleHQgLSAxXSA9PT0gZm5BcnJheVtpRmlyc3RFbmRUZXh0XSAmJiBhcmdzQXJyYXlbaUZpcnN0QmVnaW5UZXh0IC0gNF1bMF0gPT09IGZpcnN0U2V0Rm9udEFyZzAgJiYgYXJnc0FycmF5W2lGaXJzdEJlZ2luVGV4dCAtIDRdWzFdID09PSBmaXJzdFNldEZvbnRBcmcxKSB7CiAgICBjb3VudCsrOwogICAgaUZpcnN0IC09IDU7CiAgfQogIGxldCBpRW5kVGV4dCA9IGlGaXJzdCArIDQ7CiAgZm9yIChsZXQgcSA9IDE7IHEgPCBjb3VudDsgcSsrKSB7CiAgICBmbkFycmF5LnNwbGljZShpRW5kVGV4dCwgMyk7CiAgICBhcmdzQXJyYXkuc3BsaWNlKGlFbmRUZXh0LCAzKTsKICAgIGlFbmRUZXh0ICs9IDI7CiAgfQogIHJldHVybiBpRW5kVGV4dCArIDE7Cn0pOwphZGRTdGF0ZShJbml0aWFsU3RhdGUsIFtPUFMuc2F2ZSwgT1BTLnRyYW5zZm9ybSwgT1BTLmNvbnN0cnVjdFBhdGgsIE9QUy5yZXN0b3JlXSwgY29udGV4dCA9PiB7CiAgY29uc3QgYXJnc0FycmF5ID0gY29udGV4dC5hcmdzQXJyYXk7CiAgY29uc3QgaUZpcnN0Q29uc3RydWN0UGF0aCA9IGNvbnRleHQuaUN1cnIgLSAxOwogIGNvbnN0IG9wID0gYXJnc0FycmF5W2lGaXJzdENvbnN0cnVjdFBhdGhdWzBdOwogIGlmIChvcCAhPT0gT1BTLnN0cm9rZSAmJiBvcCAhPT0gT1BTLmNsb3NlU3Ryb2tlICYmIG9wICE9PSBPUFMuZmlsbFN0cm9rZSAmJiBvcCAhPT0gT1BTLmVvRmlsbFN0cm9rZSAmJiBvcCAhPT0gT1BTLmNsb3NlRmlsbFN0cm9rZSAmJiBvcCAhPT0gT1BTLmNsb3NlRU9GaWxsU3Ryb2tlKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgY29uc3QgaUZpcnN0VHJhbnNmb3JtID0gY29udGV4dC5pQ3VyciAtIDI7CiAgY29uc3QgdHJhbnNmb3JtID0gYXJnc0FycmF5W2lGaXJzdFRyYW5zZm9ybV07CiAgcmV0dXJuIHRyYW5zZm9ybVswXSA9PT0gMSAmJiB0cmFuc2Zvcm1bMV0gPT09IDAgJiYgdHJhbnNmb3JtWzJdID09PSAwICYmIHRyYW5zZm9ybVszXSA9PT0gMTsKfSwgKCkgPT4gZmFsc2UsIChjb250ZXh0LCBpKSA9PiB7CiAgY29uc3QgewogICAgZm5BcnJheSwKICAgIGFyZ3NBcnJheQogIH0gPSBjb250ZXh0OwogIGNvbnN0IGN1cnIgPSBjb250ZXh0LmlDdXJyOwogIGNvbnN0IGlGaXJzdFNhdmUgPSBjdXJyIC0gMzsKICBjb25zdCBpRmlyc3RUcmFuc2Zvcm0gPSBjdXJyIC0gMjsKICBjb25zdCBpRmlyc3RDb25zdHJ1Y3RQYXRoID0gY3VyciAtIDE7CiAgY29uc3QgYXJncyA9IGFyZ3NBcnJheVtpRmlyc3RDb25zdHJ1Y3RQYXRoXTsKICBjb25zdCB0cmFuc2Zvcm0gPSBhcmdzQXJyYXlbaUZpcnN0VHJhbnNmb3JtXTsKICBjb25zdCBbLCBbYnVmZmVyXSwgbWluTWF4XSA9IGFyZ3M7CiAgaWYgKG1pbk1heCkgewogICAgVXRpbC5zY2FsZU1pbk1heCh0cmFuc2Zvcm0sIG1pbk1heCk7CiAgICBmb3IgKGxldCBrID0gMCwga2sgPSBidWZmZXIubGVuZ3RoOyBrIDwga2s7KSB7CiAgICAgIHN3aXRjaCAoYnVmZmVyW2srK10pIHsKICAgICAgICBjYXNlIERyYXdPUFMubW92ZVRvOgogICAgICAgIGNhc2UgRHJhd09QUy5saW5lVG86CiAgICAgICAgICBVdGlsLmFwcGx5VHJhbnNmb3JtKGJ1ZmZlciwgdHJhbnNmb3JtLCBrKTsKICAgICAgICAgIGsgKz0gMjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgRHJhd09QUy5jdXJ2ZVRvOgogICAgICAgICAgVXRpbC5hcHBseVRyYW5zZm9ybVRvQmV6aWVyKGJ1ZmZlciwgdHJhbnNmb3JtLCBrKTsKICAgICAgICAgIGsgKz0gNjsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQogIGZuQXJyYXkuc3BsaWNlKGlGaXJzdFNhdmUsIDQsIE9QUy5jb25zdHJ1Y3RQYXRoKTsKICBhcmdzQXJyYXkuc3BsaWNlKGlGaXJzdFNhdmUsIDQsIGFyZ3MpOwogIHJldHVybiBpRmlyc3RTYXZlICsgMTsKfSk7CmNsYXNzIE51bGxPcHRpbWl6ZXIgewogIGNvbnN0cnVjdG9yKHF1ZXVlKSB7CiAgICB0aGlzLnF1ZXVlID0gcXVldWU7CiAgfQogIF9vcHRpbWl6ZSgpIHt9CiAgcHVzaChmbiwgYXJncykgewogICAgdGhpcy5xdWV1ZS5mbkFycmF5LnB1c2goZm4pOwogICAgdGhpcy5xdWV1ZS5hcmdzQXJyYXkucHVzaChhcmdzKTsKICAgIHRoaXMuX29wdGltaXplKCk7CiAgfQogIGZsdXNoKCkge30KICByZXNldCgpIHt9Cn0KY2xhc3MgUXVldWVPcHRpbWl6ZXIgZXh0ZW5kcyBOdWxsT3B0aW1pemVyIHsKICBjb25zdHJ1Y3RvcihxdWV1ZSkgewogICAgc3VwZXIocXVldWUpOwogICAgdGhpcy5zdGF0ZSA9IG51bGw7CiAgICB0aGlzLmNvbnRleHQgPSB7CiAgICAgIGlDdXJyOiAwLAogICAgICBmbkFycmF5OiBxdWV1ZS5mbkFycmF5LAogICAgICBhcmdzQXJyYXk6IHF1ZXVlLmFyZ3NBcnJheSwKICAgICAgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQ6IE9wZXJhdG9yTGlzdC5pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZAogICAgfTsKICAgIHRoaXMubWF0Y2ggPSBudWxsOwogICAgdGhpcy5sYXN0UHJvY2Vzc2VkID0gMDsKICB9CiAgX29wdGltaXplKCkgewogICAgY29uc3QgZm5BcnJheSA9IHRoaXMucXVldWUuZm5BcnJheTsKICAgIGxldCBpID0gdGhpcy5sYXN0UHJvY2Vzc2VkLAogICAgICBpaSA9IGZuQXJyYXkubGVuZ3RoOwogICAgbGV0IHN0YXRlID0gdGhpcy5zdGF0ZTsKICAgIGxldCBtYXRjaCA9IHRoaXMubWF0Y2g7CiAgICBpZiAoIXN0YXRlICYmICFtYXRjaCAmJiBpICsgMSA9PT0gaWkgJiYgIUluaXRpYWxTdGF0ZVtmbkFycmF5W2ldXSkgewogICAgICB0aGlzLmxhc3RQcm9jZXNzZWQgPSBpaTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgY29udGV4dCA9IHRoaXMuY29udGV4dDsKICAgIHdoaWxlIChpIDwgaWkpIHsKICAgICAgaWYgKG1hdGNoKSB7CiAgICAgICAgY29uc3QgaXRlcmF0ZSA9ICgwLCBtYXRjaC5pdGVyYXRlRm4pKGNvbnRleHQsIGkpOwogICAgICAgIGlmIChpdGVyYXRlKSB7CiAgICAgICAgICBpKys7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaSA9ICgwLCBtYXRjaC5wcm9jZXNzRm4pKGNvbnRleHQsIGkgKyAxKTsKICAgICAgICBpaSA9IGZuQXJyYXkubGVuZ3RoOwogICAgICAgIG1hdGNoID0gbnVsbDsKICAgICAgICBzdGF0ZSA9IG51bGw7CiAgICAgICAgaWYgKGkgPj0gaWkpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgICBzdGF0ZSA9IChzdGF0ZSB8fCBJbml0aWFsU3RhdGUpW2ZuQXJyYXlbaV1dOwogICAgICBpZiAoIXN0YXRlIHx8IEFycmF5LmlzQXJyYXkoc3RhdGUpKSB7CiAgICAgICAgaSsrOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnRleHQuaUN1cnIgPSBpOwogICAgICBpKys7CiAgICAgIGlmIChzdGF0ZS5jaGVja0ZuICYmICEoMCwgc3RhdGUuY2hlY2tGbikoY29udGV4dCkpIHsKICAgICAgICBzdGF0ZSA9IG51bGw7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgbWF0Y2ggPSBzdGF0ZTsKICAgICAgc3RhdGUgPSBudWxsOwogICAgfQogICAgdGhpcy5zdGF0ZSA9IHN0YXRlOwogICAgdGhpcy5tYXRjaCA9IG1hdGNoOwogICAgdGhpcy5sYXN0UHJvY2Vzc2VkID0gaTsKICB9CiAgZmx1c2goKSB7CiAgICB3aGlsZSAodGhpcy5tYXRjaCkgewogICAgICBjb25zdCBsZW5ndGggPSB0aGlzLnF1ZXVlLmZuQXJyYXkubGVuZ3RoOwogICAgICB0aGlzLmxhc3RQcm9jZXNzZWQgPSAoMCwgdGhpcy5tYXRjaC5wcm9jZXNzRm4pKHRoaXMuY29udGV4dCwgbGVuZ3RoKTsKICAgICAgdGhpcy5tYXRjaCA9IG51bGw7CiAgICAgIHRoaXMuc3RhdGUgPSBudWxsOwogICAgICB0aGlzLl9vcHRpbWl6ZSgpOwogICAgfQogIH0KICByZXNldCgpIHsKICAgIHRoaXMuc3RhdGUgPSBudWxsOwogICAgdGhpcy5tYXRjaCA9IG51bGw7CiAgICB0aGlzLmxhc3RQcm9jZXNzZWQgPSAwOwogIH0KfQpjbGFzcyBPcGVyYXRvckxpc3QgewogIHN0YXRpYyBDSFVOS19TSVpFID0gMTAwMDsKICBzdGF0aWMgQ0hVTktfU0laRV9BQk9VVCA9IHRoaXMuQ0hVTktfU0laRSAtIDU7CiAgc3RhdGljIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkID0gZmFsc2U7CiAgY29uc3RydWN0b3IoaW50ZW50ID0gMCwgc3RyZWFtU2luaykgewogICAgdGhpcy5fc3RyZWFtU2luayA9IHN0cmVhbVNpbms7CiAgICB0aGlzLmZuQXJyYXkgPSBbXTsKICAgIHRoaXMuYXJnc0FycmF5ID0gW107CiAgICB0aGlzLm9wdGltaXplciA9IHN0cmVhbVNpbmsgJiYgIShpbnRlbnQgJiBSZW5kZXJpbmdJbnRlbnRGbGFnLk9QTElTVCkgPyBuZXcgUXVldWVPcHRpbWl6ZXIodGhpcykgOiBuZXcgTnVsbE9wdGltaXplcih0aGlzKTsKICAgIHRoaXMuZGVwZW5kZW5jaWVzID0gbmV3IFNldCgpOwogICAgdGhpcy5fdG90YWxMZW5ndGggPSAwOwogICAgdGhpcy53ZWlnaHQgPSAwOwogICAgdGhpcy5fcmVzb2x2ZWQgPSBzdHJlYW1TaW5rID8gbnVsbCA6IFByb21pc2UucmVzb2x2ZSgpOwogIH0KICBzdGF0aWMgc2V0T3B0aW9ucyh7CiAgICBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZAogIH0pIHsKICAgIHRoaXMuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgPSBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZDsKICB9CiAgZ2V0IGxlbmd0aCgpIHsKICAgIHJldHVybiB0aGlzLmFyZ3NBcnJheS5sZW5ndGg7CiAgfQogIGdldCByZWFkeSgpIHsKICAgIHJldHVybiB0aGlzLl9yZXNvbHZlZCB8fCB0aGlzLl9zdHJlYW1TaW5rLnJlYWR5OwogIH0KICBnZXQgdG90YWxMZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5fdG90YWxMZW5ndGggKyB0aGlzLmxlbmd0aDsKICB9CiAgYWRkT3AoZm4sIGFyZ3MpIHsKICAgIHRoaXMub3B0aW1pemVyLnB1c2goZm4sIGFyZ3MpOwogICAgdGhpcy53ZWlnaHQrKzsKICAgIGlmICh0aGlzLl9zdHJlYW1TaW5rKSB7CiAgICAgIGlmICh0aGlzLndlaWdodCA+PSBPcGVyYXRvckxpc3QuQ0hVTktfU0laRSkgewogICAgICAgIHRoaXMuZmx1c2goKTsKICAgICAgfSBlbHNlIGlmICh0aGlzLndlaWdodCA+PSBPcGVyYXRvckxpc3QuQ0hVTktfU0laRV9BQk9VVCAmJiAoZm4gPT09IE9QUy5yZXN0b3JlIHx8IGZuID09PSBPUFMuZW5kVGV4dCkpIHsKICAgICAgICB0aGlzLmZsdXNoKCk7CiAgICAgIH0KICAgIH0KICB9CiAgYWRkSW1hZ2VPcHMoZm4sIGFyZ3MsIG9wdGlvbmFsQ29udGVudCwgaGFzTWFzayA9IGZhbHNlKSB7CiAgICBpZiAoaGFzTWFzaykgewogICAgICB0aGlzLmFkZE9wKE9QUy5zYXZlKTsKICAgICAgdGhpcy5hZGRPcChPUFMuc2V0R1N0YXRlLCBbW1siU01hc2siLCBmYWxzZV1dXSk7CiAgICB9CiAgICBpZiAob3B0aW9uYWxDb250ZW50ICE9PSB1bmRlZmluZWQpIHsKICAgICAgdGhpcy5hZGRPcChPUFMuYmVnaW5NYXJrZWRDb250ZW50UHJvcHMsIFsiT0MiLCBvcHRpb25hbENvbnRlbnRdKTsKICAgIH0KICAgIHRoaXMuYWRkT3AoZm4sIGFyZ3MpOwogICAgaWYgKG9wdGlvbmFsQ29udGVudCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHRoaXMuYWRkT3AoT1BTLmVuZE1hcmtlZENvbnRlbnQsIFtdKTsKICAgIH0KICAgIGlmIChoYXNNYXNrKSB7CiAgICAgIHRoaXMuYWRkT3AoT1BTLnJlc3RvcmUpOwogICAgfQogIH0KICBhZGREZXBlbmRlbmN5KGRlcGVuZGVuY3kpIHsKICAgIGlmICh0aGlzLmRlcGVuZGVuY2llcy5oYXMoZGVwZW5kZW5jeSkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5kZXBlbmRlbmNpZXMuYWRkKGRlcGVuZGVuY3kpOwogICAgdGhpcy5hZGRPcChPUFMuZGVwZW5kZW5jeSwgW2RlcGVuZGVuY3ldKTsKICB9CiAgYWRkRGVwZW5kZW5jaWVzKGRlcGVuZGVuY2llcykgewogICAgZm9yIChjb25zdCBkZXBlbmRlbmN5IG9mIGRlcGVuZGVuY2llcykgewogICAgICB0aGlzLmFkZERlcGVuZGVuY3koZGVwZW5kZW5jeSk7CiAgICB9CiAgfQogIGFkZE9wTGlzdChvcExpc3QpIHsKICAgIGlmICghKG9wTGlzdCBpbnN0YW5jZW9mIE9wZXJhdG9yTGlzdCkpIHsKICAgICAgd2FybignYWRkT3BMaXN0IC0gaWdub3JpbmcgaW52YWxpZCAib3BMaXN0IiBwYXJhbWV0ZXIuJyk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGZvciAoY29uc3QgZGVwZW5kZW5jeSBvZiBvcExpc3QuZGVwZW5kZW5jaWVzKSB7CiAgICAgIHRoaXMuZGVwZW5kZW5jaWVzLmFkZChkZXBlbmRlbmN5KTsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IG9wTGlzdC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIHRoaXMuYWRkT3Aob3BMaXN0LmZuQXJyYXlbaV0sIG9wTGlzdC5hcmdzQXJyYXlbaV0pOwogICAgfQogIH0KICBnZXRJUigpIHsKICAgIHJldHVybiB7CiAgICAgIGZuQXJyYXk6IHRoaXMuZm5BcnJheSwKICAgICAgYXJnc0FycmF5OiB0aGlzLmFyZ3NBcnJheSwKICAgICAgbGVuZ3RoOiB0aGlzLmxlbmd0aAogICAgfTsKICB9CiAgZ2V0IF90cmFuc2ZlcnMoKSB7CiAgICBjb25zdCB0cmFuc2ZlcnMgPSBbXTsKICAgIGNvbnN0IHsKICAgICAgZm5BcnJheSwKICAgICAgYXJnc0FycmF5LAogICAgICBsZW5ndGgKICAgIH0gPSB0aGlzOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICBzd2l0Y2ggKGZuQXJyYXlbaV0pIHsKICAgICAgICBjYXNlIE9QUy5wYWludElubGluZUltYWdlWE9iamVjdDoKICAgICAgICBjYXNlIE9QUy5wYWludElubGluZUltYWdlWE9iamVjdEdyb3VwOgogICAgICAgIGNhc2UgT1BTLnBhaW50SW1hZ2VNYXNrWE9iamVjdDoKICAgICAgICAgIHsKICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgIGJpdG1hcCwKICAgICAgICAgICAgICBkYXRhCiAgICAgICAgICAgIH0gPSBhcmdzQXJyYXlbaV1bMF07CiAgICAgICAgICAgIGlmIChiaXRtYXAgfHwgZGF0YT8uYnVmZmVyKSB7CiAgICAgICAgICAgICAgdHJhbnNmZXJzLnB1c2goYml0bWFwIHx8IGRhdGEuYnVmZmVyKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICBjYXNlIE9QUy5jb25zdHJ1Y3RQYXRoOgogICAgICAgICAgewogICAgICAgICAgICBjb25zdCBbLCBbZGF0YV0sIG1pbk1heF0gPSBhcmdzQXJyYXlbaV07CiAgICAgICAgICAgIGlmIChkYXRhKSB7CiAgICAgICAgICAgICAgdHJhbnNmZXJzLnB1c2goZGF0YS5idWZmZXIsIG1pbk1heC5idWZmZXIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIGNhc2UgT1BTLnBhaW50Rm9ybVhPYmplY3RCZWdpbjoKICAgICAgICAgIGNvbnN0IFttYXRyaXgsIGJib3hdID0gYXJnc0FycmF5W2ldOwogICAgICAgICAgaWYgKG1hdHJpeCkgewogICAgICAgICAgICB0cmFuc2ZlcnMucHVzaChtYXRyaXguYnVmZmVyKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChiYm94KSB7CiAgICAgICAgICAgIHRyYW5zZmVycy5wdXNoKGJib3guYnVmZmVyKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgT1BTLnNldFRleHRNYXRyaXg6CiAgICAgICAgICB0cmFuc2ZlcnMucHVzaChhcmdzQXJyYXlbaV1bMF0uYnVmZmVyKTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdHJhbnNmZXJzOwogIH0KICBmbHVzaChsYXN0Q2h1bmsgPSBmYWxzZSwgc2VwYXJhdGVBbm5vdHMgPSBudWxsKSB7CiAgICB0aGlzLm9wdGltaXplci5mbHVzaCgpOwogICAgY29uc3QgbGVuZ3RoID0gdGhpcy5sZW5ndGg7CiAgICB0aGlzLl90b3RhbExlbmd0aCArPSBsZW5ndGg7CiAgICB0aGlzLl9zdHJlYW1TaW5rLmVucXVldWUoewogICAgICBmbkFycmF5OiB0aGlzLmZuQXJyYXksCiAgICAgIGFyZ3NBcnJheTogdGhpcy5hcmdzQXJyYXksCiAgICAgIGxhc3RDaHVuaywKICAgICAgc2VwYXJhdGVBbm5vdHMsCiAgICAgIGxlbmd0aAogICAgfSwgMSwgdGhpcy5fdHJhbnNmZXJzKTsKICAgIHRoaXMuZGVwZW5kZW5jaWVzLmNsZWFyKCk7CiAgICB0aGlzLmZuQXJyYXkubGVuZ3RoID0gMDsKICAgIHRoaXMuYXJnc0FycmF5Lmxlbmd0aCA9IDA7CiAgICB0aGlzLndlaWdodCA9IDA7CiAgICB0aGlzLm9wdGltaXplci5yZXNldCgpOwogIH0KfQoKLy8gRVhURVJOQUwgTU9EVUxFOiAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMuaXRlcmF0b3IuZmluZC5qcwp2YXIgZXNfaXRlcmF0b3JfZmluZCA9IF9fd2VicGFja19yZXF1aXJlX18oMTE2KTsKLy8gRVhURVJOQUwgTU9EVUxFOiAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL21vZHVsZXMvZXMucmVnZXhwLmZsYWdzLmpzCnZhciBlc19yZWdleHBfZmxhZ3MgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDk0NzkpOwovLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbW9kdWxlcy9lcy5pdGVyYXRvci5mb3ItZWFjaC5qcwp2YXIgZXNfaXRlcmF0b3JfZm9yX2VhY2ggPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDc1ODgpOwo7Ly8gLi9zcmMvY29yZS9iaW5hcnlfY21hcC5qcwoKCgoKCgoKCgpmdW5jdGlvbiBoZXhUb0ludChhLCBzaXplKSB7CiAgbGV0IG4gPSAwOwogIGZvciAobGV0IGkgPSAwOyBpIDw9IHNpemU7IGkrKykgewogICAgbiA9IG4gPDwgOCB8IGFbaV07CiAgfQogIHJldHVybiBuID4+PiAwOwp9CmZ1bmN0aW9uIGhleFRvU3RyKGEsIHNpemUpIHsKICBpZiAoc2l6ZSA9PT0gMSkgewogICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoYVswXSwgYVsxXSk7CiAgfQogIGlmIChzaXplID09PSAzKSB7CiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShhWzBdLCBhWzFdLCBhWzJdLCBhWzNdKTsKICB9CiAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoLi4uYS5zdWJhcnJheSgwLCBzaXplICsgMSkpOwp9CmZ1bmN0aW9uIGFkZEhleChhLCBiLCBzaXplKSB7CiAgbGV0IGMgPSAwOwogIGZvciAobGV0IGkgPSBzaXplOyBpID49IDA7IGktLSkgewogICAgYyArPSBhW2ldICsgYltpXTsKICAgIGFbaV0gPSBjICYgMjU1OwogICAgYyA+Pj0gODsKICB9Cn0KZnVuY3Rpb24gaW5jSGV4KGEsIHNpemUpIHsKICBsZXQgYyA9IDE7CiAgZm9yIChsZXQgaSA9IHNpemU7IGkgPj0gMCAmJiBjID4gMDsgaS0tKSB7CiAgICBjICs9IGFbaV07CiAgICBhW2ldID0gYyAmIDI1NTsKICAgIGMgPj49IDg7CiAgfQp9CmNvbnN0IE1BWF9OVU1fU0laRSA9IDE2Owpjb25zdCBNQVhfRU5DT0RFRF9OVU1fU0laRSA9IDE5OwpjbGFzcyBCaW5hcnlDTWFwU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihkYXRhKSB7CiAgICB0aGlzLmJ1ZmZlciA9IGRhdGE7CiAgICB0aGlzLnBvcyA9IDA7CiAgICB0aGlzLmVuZCA9IGRhdGEubGVuZ3RoOwogICAgdGhpcy50bXBCdWYgPSBuZXcgVWludDhBcnJheShNQVhfRU5DT0RFRF9OVU1fU0laRSk7CiAgfQogIHJlYWRCeXRlKCkgewogICAgaWYgKHRoaXMucG9zID49IHRoaXMuZW5kKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIHJldHVybiB0aGlzLmJ1ZmZlclt0aGlzLnBvcysrXTsKICB9CiAgcmVhZE51bWJlcigpIHsKICAgIGxldCBuID0gMDsKICAgIGxldCBsYXN0OwogICAgZG8gewogICAgICBjb25zdCBiID0gdGhpcy5yZWFkQnl0ZSgpOwogICAgICBpZiAoYiA8IDApIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoInVuZXhwZWN0ZWQgRU9GIGluIGJjbWFwIik7CiAgICAgIH0KICAgICAgbGFzdCA9ICEoYiAmIDB4ODApOwogICAgICBuID0gbiA8PCA3IHwgYiAmIDB4N2Y7CiAgICB9IHdoaWxlICghbGFzdCk7CiAgICByZXR1cm4gbjsKICB9CiAgcmVhZFNpZ25lZCgpIHsKICAgIGNvbnN0IG4gPSB0aGlzLnJlYWROdW1iZXIoKTsKICAgIHJldHVybiBuICYgMSA/IH4obiA+Pj4gMSkgOiBuID4+PiAxOwogIH0KICByZWFkSGV4KG51bSwgc2l6ZSkgewogICAgbnVtLnNldCh0aGlzLmJ1ZmZlci5zdWJhcnJheSh0aGlzLnBvcywgdGhpcy5wb3MgKyBzaXplICsgMSkpOwogICAgdGhpcy5wb3MgKz0gc2l6ZSArIDE7CiAgfQogIHJlYWRIZXhOdW1iZXIobnVtLCBzaXplKSB7CiAgICBsZXQgbGFzdDsKICAgIGNvbnN0IHN0YWNrID0gdGhpcy50bXBCdWY7CiAgICBsZXQgc3AgPSAwOwogICAgZG8gewogICAgICBjb25zdCBiID0gdGhpcy5yZWFkQnl0ZSgpOwogICAgICBpZiAoYiA8IDApIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoInVuZXhwZWN0ZWQgRU9GIGluIGJjbWFwIik7CiAgICAgIH0KICAgICAgbGFzdCA9ICEoYiAmIDB4ODApOwogICAgICBzdGFja1tzcCsrXSA9IGIgJiAweDdmOwogICAgfSB3aGlsZSAoIWxhc3QpOwogICAgbGV0IGkgPSBzaXplLAogICAgICBidWZmZXIgPSAwLAogICAgICBidWZmZXJTaXplID0gMDsKICAgIHdoaWxlIChpID49IDApIHsKICAgICAgd2hpbGUgKGJ1ZmZlclNpemUgPCA4ICYmIHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgICBidWZmZXIgfD0gc3RhY2tbLS1zcF0gPDwgYnVmZmVyU2l6ZTsKICAgICAgICBidWZmZXJTaXplICs9IDc7CiAgICAgIH0KICAgICAgbnVtW2ldID0gYnVmZmVyICYgMjU1OwogICAgICBpLS07CiAgICAgIGJ1ZmZlciA+Pj0gODsKICAgICAgYnVmZmVyU2l6ZSAtPSA4OwogICAgfQogIH0KICByZWFkSGV4U2lnbmVkKG51bSwgc2l6ZSkgewogICAgdGhpcy5yZWFkSGV4TnVtYmVyKG51bSwgc2l6ZSk7CiAgICBjb25zdCBzaWduID0gbnVtW3NpemVdICYgMSA/IDI1NSA6IDA7CiAgICBsZXQgYyA9IDA7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8PSBzaXplOyBpKyspIHsKICAgICAgYyA9IChjICYgMSkgPDwgOCB8IG51bVtpXTsKICAgICAgbnVtW2ldID0gYyA+PiAxIF4gc2lnbjsKICAgIH0KICB9CiAgcmVhZFN0cmluZygpIHsKICAgIGNvbnN0IGxlbiA9IHRoaXMucmVhZE51bWJlcigpLAogICAgICBidWYgPSBuZXcgQXJyYXkobGVuKTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpKyspIHsKICAgICAgYnVmW2ldID0gdGhpcy5yZWFkTnVtYmVyKCk7CiAgICB9CiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSguLi5idWYpOwogIH0KfQpjbGFzcyBCaW5hcnlDTWFwUmVhZGVyIHsKICBhc3luYyBwcm9jZXNzKGRhdGEsIGNNYXAsIGV4dGVuZCkgewogICAgY29uc3Qgc3RyZWFtID0gbmV3IEJpbmFyeUNNYXBTdHJlYW0oZGF0YSk7CiAgICBjb25zdCBoZWFkZXIgPSBzdHJlYW0ucmVhZEJ5dGUoKTsKICAgIGNNYXAudmVydGljYWwgPSAhIShoZWFkZXIgJiAxKTsKICAgIGxldCB1c2VDTWFwID0gbnVsbDsKICAgIGNvbnN0IHN0YXJ0ID0gbmV3IFVpbnQ4QXJyYXkoTUFYX05VTV9TSVpFKTsKICAgIGNvbnN0IGVuZCA9IG5ldyBVaW50OEFycmF5KE1BWF9OVU1fU0laRSk7CiAgICBjb25zdCBjaGFyID0gbmV3IFVpbnQ4QXJyYXkoTUFYX05VTV9TSVpFKTsKICAgIGNvbnN0IGNoYXJDb2RlID0gbmV3IFVpbnQ4QXJyYXkoTUFYX05VTV9TSVpFKTsKICAgIGNvbnN0IHRtcCA9IG5ldyBVaW50OEFycmF5KE1BWF9OVU1fU0laRSk7CiAgICBsZXQgY29kZTsKICAgIGxldCBiOwogICAgd2hpbGUgKChiID0gc3RyZWFtLnJlYWRCeXRlKCkpID49IDApIHsKICAgICAgY29uc3QgdHlwZSA9IGIgPj4gNTsKICAgICAgaWYgKHR5cGUgPT09IDcpIHsKICAgICAgICBzd2l0Y2ggKGIgJiAweDFmKSB7CiAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgIHN0cmVhbS5yZWFkU3RyaW5nKCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICB1c2VDTWFwID0gc3RyZWFtLnJlYWRTdHJpbmcoKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IHNlcXVlbmNlID0gISEoYiAmIDB4MTApOwogICAgICBjb25zdCBkYXRhU2l6ZSA9IGIgJiAxNTsKICAgICAgaWYgKGRhdGFTaXplICsgMSA+IE1BWF9OVU1fU0laRSkgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiQmluYXJ5Q01hcFJlYWRlci5wcm9jZXNzOiBJbnZhbGlkIGRhdGFTaXplLiIpOwogICAgICB9CiAgICAgIGNvbnN0IHVjczJEYXRhU2l6ZSA9IDE7CiAgICAgIGNvbnN0IHN1Yml0ZW1zQ291bnQgPSBzdHJlYW0ucmVhZE51bWJlcigpOwogICAgICBzd2l0Y2ggKHR5cGUpIHsKICAgICAgICBjYXNlIDA6CiAgICAgICAgICBzdHJlYW0ucmVhZEhleChzdGFydCwgZGF0YVNpemUpOwogICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoZW5kLCBkYXRhU2l6ZSk7CiAgICAgICAgICBhZGRIZXgoZW5kLCBzdGFydCwgZGF0YVNpemUpOwogICAgICAgICAgY01hcC5hZGRDb2Rlc3BhY2VSYW5nZShkYXRhU2l6ZSArIDEsIGhleFRvSW50KHN0YXJ0LCBkYXRhU2l6ZSksIGhleFRvSW50KGVuZCwgZGF0YVNpemUpKTsKICAgICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgc3ViaXRlbXNDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGluY0hleChlbmQsIGRhdGFTaXplKTsKICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoc3RhcnQsIGRhdGFTaXplKTsKICAgICAgICAgICAgYWRkSGV4KHN0YXJ0LCBlbmQsIGRhdGFTaXplKTsKICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoZW5kLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIGFkZEhleChlbmQsIHN0YXJ0LCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIGNNYXAuYWRkQ29kZXNwYWNlUmFuZ2UoZGF0YVNpemUgKyAxLCBoZXhUb0ludChzdGFydCwgZGF0YVNpemUpLCBoZXhUb0ludChlbmQsIGRhdGFTaXplKSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDE6CiAgICAgICAgICBzdHJlYW0ucmVhZEhleChzdGFydCwgZGF0YVNpemUpOwogICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoZW5kLCBkYXRhU2l6ZSk7CiAgICAgICAgICBhZGRIZXgoZW5kLCBzdGFydCwgZGF0YVNpemUpOwogICAgICAgICAgc3RyZWFtLnJlYWROdW1iZXIoKTsKICAgICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgc3ViaXRlbXNDb3VudDsgaSsrKSB7CiAgICAgICAgICAgIGluY0hleChlbmQsIGRhdGFTaXplKTsKICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoc3RhcnQsIGRhdGFTaXplKTsKICAgICAgICAgICAgYWRkSGV4KHN0YXJ0LCBlbmQsIGRhdGFTaXplKTsKICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoZW5kLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIGFkZEhleChlbmQsIHN0YXJ0LCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIHN0cmVhbS5yZWFkTnVtYmVyKCk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI6CiAgICAgICAgICBzdHJlYW0ucmVhZEhleChjaGFyLCBkYXRhU2l6ZSk7CiAgICAgICAgICBjb2RlID0gc3RyZWFtLnJlYWROdW1iZXIoKTsKICAgICAgICAgIGNNYXAubWFwT25lKGhleFRvSW50KGNoYXIsIGRhdGFTaXplKSwgY29kZSk7CiAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHN1Yml0ZW1zQ291bnQ7IGkrKykgewogICAgICAgICAgICBpbmNIZXgoY2hhciwgZGF0YVNpemUpOwogICAgICAgICAgICBpZiAoIXNlcXVlbmNlKSB7CiAgICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIodG1wLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgICAgYWRkSGV4KGNoYXIsIHRtcCwgZGF0YVNpemUpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvZGUgPSBzdHJlYW0ucmVhZFNpZ25lZCgpICsgKGNvZGUgKyAxKTsKICAgICAgICAgICAgY01hcC5tYXBPbmUoaGV4VG9JbnQoY2hhciwgZGF0YVNpemUpLCBjb2RlKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMzoKICAgICAgICAgIHN0cmVhbS5yZWFkSGV4KHN0YXJ0LCBkYXRhU2l6ZSk7CiAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcihlbmQsIGRhdGFTaXplKTsKICAgICAgICAgIGFkZEhleChlbmQsIHN0YXJ0LCBkYXRhU2l6ZSk7CiAgICAgICAgICBjb2RlID0gc3RyZWFtLnJlYWROdW1iZXIoKTsKICAgICAgICAgIGNNYXAubWFwQ2lkUmFuZ2UoaGV4VG9JbnQoc3RhcnQsIGRhdGFTaXplKSwgaGV4VG9JbnQoZW5kLCBkYXRhU2l6ZSksIGNvZGUpOwogICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBzdWJpdGVtc0NvdW50OyBpKyspIHsKICAgICAgICAgICAgaW5jSGV4KGVuZCwgZGF0YVNpemUpOwogICAgICAgICAgICBpZiAoIXNlcXVlbmNlKSB7CiAgICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoc3RhcnQsIGRhdGFTaXplKTsKICAgICAgICAgICAgICBhZGRIZXgoc3RhcnQsIGVuZCwgZGF0YVNpemUpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHN0YXJ0LnNldChlbmQpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN0cmVhbS5yZWFkSGV4TnVtYmVyKGVuZCwgZGF0YVNpemUpOwogICAgICAgICAgICBhZGRIZXgoZW5kLCBzdGFydCwgZGF0YVNpemUpOwogICAgICAgICAgICBjb2RlID0gc3RyZWFtLnJlYWROdW1iZXIoKTsKICAgICAgICAgICAgY01hcC5tYXBDaWRSYW5nZShoZXhUb0ludChzdGFydCwgZGF0YVNpemUpLCBoZXhUb0ludChlbmQsIGRhdGFTaXplKSwgY29kZSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDQ6CiAgICAgICAgICBzdHJlYW0ucmVhZEhleChjaGFyLCB1Y3MyRGF0YVNpemUpOwogICAgICAgICAgc3RyZWFtLnJlYWRIZXgoY2hhckNvZGUsIGRhdGFTaXplKTsKICAgICAgICAgIGNNYXAubWFwT25lKGhleFRvSW50KGNoYXIsIHVjczJEYXRhU2l6ZSksIGhleFRvU3RyKGNoYXJDb2RlLCBkYXRhU2l6ZSkpOwogICAgICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBzdWJpdGVtc0NvdW50OyBpKyspIHsKICAgICAgICAgICAgaW5jSGV4KGNoYXIsIHVjczJEYXRhU2l6ZSk7CiAgICAgICAgICAgIGlmICghc2VxdWVuY2UpIHsKICAgICAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcih0bXAsIHVjczJEYXRhU2l6ZSk7CiAgICAgICAgICAgICAgYWRkSGV4KGNoYXIsIHRtcCwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpbmNIZXgoY2hhckNvZGUsIGRhdGFTaXplKTsKICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhTaWduZWQodG1wLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIGFkZEhleChjaGFyQ29kZSwgdG1wLCBkYXRhU2l6ZSk7CiAgICAgICAgICAgIGNNYXAubWFwT25lKGhleFRvSW50KGNoYXIsIHVjczJEYXRhU2l6ZSksIGhleFRvU3RyKGNoYXJDb2RlLCBkYXRhU2l6ZSkpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA1OgogICAgICAgICAgc3RyZWFtLnJlYWRIZXgoc3RhcnQsIHVjczJEYXRhU2l6ZSk7CiAgICAgICAgICBzdHJlYW0ucmVhZEhleE51bWJlcihlbmQsIHVjczJEYXRhU2l6ZSk7CiAgICAgICAgICBhZGRIZXgoZW5kLCBzdGFydCwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgIHN0cmVhbS5yZWFkSGV4KGNoYXJDb2RlLCBkYXRhU2l6ZSk7CiAgICAgICAgICBjTWFwLm1hcEJmUmFuZ2UoaGV4VG9JbnQoc3RhcnQsIHVjczJEYXRhU2l6ZSksIGhleFRvSW50KGVuZCwgdWNzMkRhdGFTaXplKSwgaGV4VG9TdHIoY2hhckNvZGUsIGRhdGFTaXplKSk7CiAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHN1Yml0ZW1zQ291bnQ7IGkrKykgewogICAgICAgICAgICBpbmNIZXgoZW5kLCB1Y3MyRGF0YVNpemUpOwogICAgICAgICAgICBpZiAoIXNlcXVlbmNlKSB7CiAgICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoc3RhcnQsIHVjczJEYXRhU2l6ZSk7CiAgICAgICAgICAgICAgYWRkSGV4KHN0YXJ0LCBlbmQsIHVjczJEYXRhU2l6ZSk7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgc3RhcnQuc2V0KGVuZCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXhOdW1iZXIoZW5kLCB1Y3MyRGF0YVNpemUpOwogICAgICAgICAgICBhZGRIZXgoZW5kLCBzdGFydCwgdWNzMkRhdGFTaXplKTsKICAgICAgICAgICAgc3RyZWFtLnJlYWRIZXgoY2hhckNvZGUsIGRhdGFTaXplKTsKICAgICAgICAgICAgY01hcC5tYXBCZlJhbmdlKGhleFRvSW50KHN0YXJ0LCB1Y3MyRGF0YVNpemUpLCBoZXhUb0ludChlbmQsIHVjczJEYXRhU2l6ZSksIGhleFRvU3RyKGNoYXJDb2RlLCBkYXRhU2l6ZSkpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgQmluYXJ5Q01hcFJlYWRlci5wcm9jZXNzIC0gdW5rbm93biB0eXBlOiAke3R5cGV9YCk7CiAgICAgIH0KICAgIH0KICAgIGlmICh1c2VDTWFwKSB7CiAgICAgIHJldHVybiBleHRlbmQodXNlQ01hcCk7CiAgICB9CiAgICByZXR1cm4gY01hcDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2FzY2lpXzg1X3N0cmVhbS5qcwoKCgoKCgoKCgoKY2xhc3MgQXNjaWk4NVN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyLCBtYXliZUxlbmd0aCkgewogICAgaWYgKG1heWJlTGVuZ3RoKSB7CiAgICAgIG1heWJlTGVuZ3RoICo9IDAuODsKICAgIH0KICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIHRoaXMuc3RyID0gc3RyOwogICAgdGhpcy5kaWN0ID0gc3RyLmRpY3Q7CiAgICB0aGlzLmlucHV0ID0gbmV3IFVpbnQ4QXJyYXkoNSk7CiAgfQogIHJlYWRCbG9jaygpIHsKICAgIGNvbnN0IFRJTERBX0NIQVIgPSAweDdlOwogICAgY29uc3QgWl9MT1dFUl9DSEFSID0gMHg3YTsKICAgIGNvbnN0IEVPRiA9IC0xOwogICAgY29uc3Qgc3RyID0gdGhpcy5zdHI7CiAgICBsZXQgYyA9IHN0ci5nZXRCeXRlKCk7CiAgICB3aGlsZSAoaXNXaGl0ZVNwYWNlKGMpKSB7CiAgICAgIGMgPSBzdHIuZ2V0Qnl0ZSgpOwogICAgfQogICAgaWYgKGMgPT09IEVPRiB8fCBjID09PSBUSUxEQV9DSEFSKSB7CiAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgYnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXJMZW5ndGg7CiAgICBsZXQgYnVmZmVyLCBpOwogICAgaWYgKGMgPT09IFpfTE9XRVJfQ0hBUikgewogICAgICBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcihidWZmZXJMZW5ndGggKyA0KTsKICAgICAgZm9yIChpID0gMDsgaSA8IDQ7ICsraSkgewogICAgICAgIGJ1ZmZlcltidWZmZXJMZW5ndGggKyBpXSA9IDA7CiAgICAgIH0KICAgICAgdGhpcy5idWZmZXJMZW5ndGggKz0gNDsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IGlucHV0ID0gdGhpcy5pbnB1dDsKICAgICAgaW5wdXRbMF0gPSBjOwogICAgICBmb3IgKGkgPSAxOyBpIDwgNTsgKytpKSB7CiAgICAgICAgYyA9IHN0ci5nZXRCeXRlKCk7CiAgICAgICAgd2hpbGUgKGlzV2hpdGVTcGFjZShjKSkgewogICAgICAgICAgYyA9IHN0ci5nZXRCeXRlKCk7CiAgICAgICAgfQogICAgICAgIGlucHV0W2ldID0gYzsKICAgICAgICBpZiAoYyA9PT0gRU9GIHx8IGMgPT09IFRJTERBX0NIQVIpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgICBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcihidWZmZXJMZW5ndGggKyBpIC0gMSk7CiAgICAgIHRoaXMuYnVmZmVyTGVuZ3RoICs9IGkgLSAxOwogICAgICBpZiAoaSA8IDUpIHsKICAgICAgICBmb3IgKDsgaSA8IDU7ICsraSkgewogICAgICAgICAgaW5wdXRbaV0gPSAweDIxICsgODQ7CiAgICAgICAgfQogICAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgfQogICAgICBsZXQgdCA9IDA7CiAgICAgIGZvciAoaSA9IDA7IGkgPCA1OyArK2kpIHsKICAgICAgICB0ID0gdCAqIDg1ICsgKGlucHV0W2ldIC0gMHgyMSk7CiAgICAgIH0KICAgICAgZm9yIChpID0gMzsgaSA+PSAwOyAtLWkpIHsKICAgICAgICBidWZmZXJbYnVmZmVyTGVuZ3RoICsgaV0gPSB0ICYgMHhmZjsKICAgICAgICB0ID4+PSA4OwogICAgICB9CiAgICB9CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9hc2NpaV9oZXhfc3RyZWFtLmpzCgpjbGFzcyBBc2NpaUhleFN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyLCBtYXliZUxlbmd0aCkgewogICAgaWYgKG1heWJlTGVuZ3RoKSB7CiAgICAgIG1heWJlTGVuZ3RoICo9IDAuNTsKICAgIH0KICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIHRoaXMuc3RyID0gc3RyOwogICAgdGhpcy5kaWN0ID0gc3RyLmRpY3Q7CiAgICB0aGlzLmZpcnN0RGlnaXQgPSAtMTsKICB9CiAgcmVhZEJsb2NrKCkgewogICAgY29uc3QgVVBTVFJFQU1fQkxPQ0tfU0laRSA9IDgwMDA7CiAgICBjb25zdCBieXRlcyA9IHRoaXMuc3RyLmdldEJ5dGVzKFVQU1RSRUFNX0JMT0NLX1NJWkUpOwogICAgaWYgKCFieXRlcy5sZW5ndGgpIHsKICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBtYXhEZWNvZGVMZW5ndGggPSBieXRlcy5sZW5ndGggKyAxID4+IDE7CiAgICBjb25zdCBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcih0aGlzLmJ1ZmZlckxlbmd0aCArIG1heERlY29kZUxlbmd0aCk7CiAgICBsZXQgYnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXJMZW5ndGg7CiAgICBsZXQgZmlyc3REaWdpdCA9IHRoaXMuZmlyc3REaWdpdDsKICAgIGZvciAoY29uc3QgY2ggb2YgYnl0ZXMpIHsKICAgICAgbGV0IGRpZ2l0OwogICAgICBpZiAoY2ggPj0gMHgzMCAmJiBjaCA8PSAweDM5KSB7CiAgICAgICAgZGlnaXQgPSBjaCAmIDB4MGY7CiAgICAgIH0gZWxzZSBpZiAoY2ggPj0gMHg0MSAmJiBjaCA8PSAweDQ2IHx8IGNoID49IDB4NjEgJiYgY2ggPD0gMHg2NikgewogICAgICAgIGRpZ2l0ID0gKGNoICYgMHgwZikgKyA5OwogICAgICB9IGVsc2UgaWYgKGNoID09PSAweDNlKSB7CiAgICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICAgIGJyZWFrOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChmaXJzdERpZ2l0IDwgMCkgewogICAgICAgIGZpcnN0RGlnaXQgPSBkaWdpdDsKICAgICAgfSBlbHNlIHsKICAgICAgICBidWZmZXJbYnVmZmVyTGVuZ3RoKytdID0gZmlyc3REaWdpdCA8PCA0IHwgZGlnaXQ7CiAgICAgICAgZmlyc3REaWdpdCA9IC0xOwogICAgICB9CiAgICB9CiAgICBpZiAoZmlyc3REaWdpdCA+PSAwICYmIHRoaXMuZW9mKSB7CiAgICAgIGJ1ZmZlcltidWZmZXJMZW5ndGgrK10gPSBmaXJzdERpZ2l0IDw8IDQ7CiAgICAgIGZpcnN0RGlnaXQgPSAtMTsKICAgIH0KICAgIHRoaXMuZmlyc3REaWdpdCA9IGZpcnN0RGlnaXQ7CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IGJ1ZmZlckxlbmd0aDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2NjaXR0LmpzCgoKCgoKY29uc3QgY2NpdHRFT0wgPSAtMjsKY29uc3QgY2NpdHRFT0YgPSAtMTsKY29uc3QgdHdvRGltUGFzcyA9IDA7CmNvbnN0IHR3b0RpbUhvcml6ID0gMTsKY29uc3QgdHdvRGltVmVydDAgPSAyOwpjb25zdCB0d29EaW1WZXJ0UjEgPSAzOwpjb25zdCB0d29EaW1WZXJ0TDEgPSA0Owpjb25zdCB0d29EaW1WZXJ0UjIgPSA1Owpjb25zdCB0d29EaW1WZXJ0TDIgPSA2Owpjb25zdCB0d29EaW1WZXJ0UjMgPSA3Owpjb25zdCB0d29EaW1WZXJ0TDMgPSA4Owpjb25zdCB0d29EaW1UYWJsZSA9IFtbLTEsIC0xXSwgWy0xLCAtMV0sIFs3LCB0d29EaW1WZXJ0TDNdLCBbNywgdHdvRGltVmVydFIzXSwgWzYsIHR3b0RpbVZlcnRMMl0sIFs2LCB0d29EaW1WZXJ0TDJdLCBbNiwgdHdvRGltVmVydFIyXSwgWzYsIHR3b0RpbVZlcnRSMl0sIFs0LCB0d29EaW1QYXNzXSwgWzQsIHR3b0RpbVBhc3NdLCBbNCwgdHdvRGltUGFzc10sIFs0LCB0d29EaW1QYXNzXSwgWzQsIHR3b0RpbVBhc3NdLCBbNCwgdHdvRGltUGFzc10sIFs0LCB0d29EaW1QYXNzXSwgWzQsIHR3b0RpbVBhc3NdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltSG9yaXpdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRMMV0sIFszLCB0d29EaW1WZXJ0TDFdLCBbMywgdHdvRGltVmVydEwxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFszLCB0d29EaW1WZXJ0UjFdLCBbMywgdHdvRGltVmVydFIxXSwgWzMsIHR3b0RpbVZlcnRSMV0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF0sIFsxLCB0d29EaW1WZXJ0MF1dOwpjb25zdCB3aGl0ZVRhYmxlMSA9IFtbLTEsIC0xXSwgWzEyLCBjY2l0dEVPTF0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWzExLCAxNzkyXSwgWzExLCAxNzkyXSwgWzEyLCAxOTg0XSwgWzEyLCAyMDQ4XSwgWzEyLCAyMTEyXSwgWzEyLCAyMTc2XSwgWzEyLCAyMjQwXSwgWzEyLCAyMzA0XSwgWzExLCAxODU2XSwgWzExLCAxODU2XSwgWzExLCAxOTIwXSwgWzExLCAxOTIwXSwgWzEyLCAyMzY4XSwgWzEyLCAyNDMyXSwgWzEyLCAyNDk2XSwgWzEyLCAyNTYwXV07CmNvbnN0IHdoaXRlVGFibGUyID0gW1stMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbOCwgMjldLCBbOCwgMjldLCBbOCwgMzBdLCBbOCwgMzBdLCBbOCwgNDVdLCBbOCwgNDVdLCBbOCwgNDZdLCBbOCwgNDZdLCBbNywgMjJdLCBbNywgMjJdLCBbNywgMjJdLCBbNywgMjJdLCBbNywgMjNdLCBbNywgMjNdLCBbNywgMjNdLCBbNywgMjNdLCBbOCwgNDddLCBbOCwgNDddLCBbOCwgNDhdLCBbOCwgNDhdLCBbNiwgMTNdLCBbNiwgMTNdLCBbNiwgMTNdLCBbNiwgMTNdLCBbNiwgMTNdLCBbNiwgMTNdLCBbNiwgMTNdLCBbNiwgMTNdLCBbNywgMjBdLCBbNywgMjBdLCBbNywgMjBdLCBbNywgMjBdLCBbOCwgMzNdLCBbOCwgMzNdLCBbOCwgMzRdLCBbOCwgMzRdLCBbOCwgMzVdLCBbOCwgMzVdLCBbOCwgMzZdLCBbOCwgMzZdLCBbOCwgMzddLCBbOCwgMzddLCBbOCwgMzhdLCBbOCwgMzhdLCBbNywgMTldLCBbNywgMTldLCBbNywgMTldLCBbNywgMTldLCBbOCwgMzFdLCBbOCwgMzFdLCBbOCwgMzJdLCBbOCwgMzJdLCBbNiwgMV0sIFs2LCAxXSwgWzYsIDFdLCBbNiwgMV0sIFs2LCAxXSwgWzYsIDFdLCBbNiwgMV0sIFs2LCAxXSwgWzYsIDEyXSwgWzYsIDEyXSwgWzYsIDEyXSwgWzYsIDEyXSwgWzYsIDEyXSwgWzYsIDEyXSwgWzYsIDEyXSwgWzYsIDEyXSwgWzgsIDUzXSwgWzgsIDUzXSwgWzgsIDU0XSwgWzgsIDU0XSwgWzcsIDI2XSwgWzcsIDI2XSwgWzcsIDI2XSwgWzcsIDI2XSwgWzgsIDM5XSwgWzgsIDM5XSwgWzgsIDQwXSwgWzgsIDQwXSwgWzgsIDQxXSwgWzgsIDQxXSwgWzgsIDQyXSwgWzgsIDQyXSwgWzgsIDQzXSwgWzgsIDQzXSwgWzgsIDQ0XSwgWzgsIDQ0XSwgWzcsIDIxXSwgWzcsIDIxXSwgWzcsIDIxXSwgWzcsIDIxXSwgWzcsIDI4XSwgWzcsIDI4XSwgWzcsIDI4XSwgWzcsIDI4XSwgWzgsIDYxXSwgWzgsIDYxXSwgWzgsIDYyXSwgWzgsIDYyXSwgWzgsIDYzXSwgWzgsIDYzXSwgWzgsIDBdLCBbOCwgMF0sIFs4LCAzMjBdLCBbOCwgMzIwXSwgWzgsIDM4NF0sIFs4LCAzODRdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTBdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNSwgMTFdLCBbNywgMjddLCBbNywgMjddLCBbNywgMjddLCBbNywgMjddLCBbOCwgNTldLCBbOCwgNTldLCBbOCwgNjBdLCBbOCwgNjBdLCBbOSwgMTQ3Ml0sIFs5LCAxNTM2XSwgWzksIDE2MDBdLCBbOSwgMTcyOF0sIFs3LCAxOF0sIFs3LCAxOF0sIFs3LCAxOF0sIFs3LCAxOF0sIFs3LCAyNF0sIFs3LCAyNF0sIFs3LCAyNF0sIFs3LCAyNF0sIFs4LCA0OV0sIFs4LCA0OV0sIFs4LCA1MF0sIFs4LCA1MF0sIFs4LCA1MV0sIFs4LCA1MV0sIFs4LCA1Ml0sIFs4LCA1Ml0sIFs3LCAyNV0sIFs3LCAyNV0sIFs3LCAyNV0sIFs3LCAyNV0sIFs4LCA1NV0sIFs4LCA1NV0sIFs4LCA1Nl0sIFs4LCA1Nl0sIFs4LCA1N10sIFs4LCA1N10sIFs4LCA1OF0sIFs4LCA1OF0sIFs2LCAxOTJdLCBbNiwgMTkyXSwgWzYsIDE5Ml0sIFs2LCAxOTJdLCBbNiwgMTkyXSwgWzYsIDE5Ml0sIFs2LCAxOTJdLCBbNiwgMTkyXSwgWzYsIDE2NjRdLCBbNiwgMTY2NF0sIFs2LCAxNjY0XSwgWzYsIDE2NjRdLCBbNiwgMTY2NF0sIFs2LCAxNjY0XSwgWzYsIDE2NjRdLCBbNiwgMTY2NF0sIFs4LCA0NDhdLCBbOCwgNDQ4XSwgWzgsIDUxMl0sIFs4LCA1MTJdLCBbOSwgNzA0XSwgWzksIDc2OF0sIFs4LCA2NDBdLCBbOCwgNjQwXSwgWzgsIDU3Nl0sIFs4LCA1NzZdLCBbOSwgODMyXSwgWzksIDg5Nl0sIFs5LCA5NjBdLCBbOSwgMTAyNF0sIFs5LCAxMDg4XSwgWzksIDExNTJdLCBbOSwgMTIxNl0sIFs5LCAxMjgwXSwgWzksIDEzNDRdLCBbOSwgMTQwOF0sIFs3LCAyNTZdLCBbNywgMjU2XSwgWzcsIDI1Nl0sIFs3LCAyNTZdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDJdLCBbNCwgMl0sIFs0LCAyXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs0LCAzXSwgWzQsIDNdLCBbNCwgM10sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgMTI4XSwgWzUsIDEyOF0sIFs1LCAxMjhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA4XSwgWzUsIDhdLCBbNSwgOF0sIFs1LCA5XSwgWzUsIDldLCBbNSwgOV0sIFs1LCA5XSwgWzUsIDldLCBbNSwgOV0sIFs1LCA5XSwgWzUsIDldLCBbNSwgOV0sIFs1LCA5XSwgWzUsIDldLCBbNSwgOV0sIFs1LCA5XSwgWzUsIDldLCBbNSwgOV0sIFs1LCA5XSwgWzYsIDE2XSwgWzYsIDE2XSwgWzYsIDE2XSwgWzYsIDE2XSwgWzYsIDE2XSwgWzYsIDE2XSwgWzYsIDE2XSwgWzYsIDE2XSwgWzYsIDE3XSwgWzYsIDE3XSwgWzYsIDE3XSwgWzYsIDE3XSwgWzYsIDE3XSwgWzYsIDE3XSwgWzYsIDE3XSwgWzYsIDE3XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA0XSwgWzQsIDRdLCBbNCwgNF0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbNiwgMTRdLCBbNiwgMTRdLCBbNiwgMTRdLCBbNiwgMTRdLCBbNiwgMTRdLCBbNiwgMTRdLCBbNiwgMTRdLCBbNiwgMTRdLCBbNiwgMTVdLCBbNiwgMTVdLCBbNiwgMTVdLCBbNiwgMTVdLCBbNiwgMTVdLCBbNiwgMTVdLCBbNiwgMTVdLCBbNiwgMTVdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNSwgNjRdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN10sIFs0LCA3XSwgWzQsIDddLCBbNCwgN11dOwpjb25zdCBibGFja1RhYmxlMSA9IFtbLTEsIC0xXSwgWy0xLCAtMV0sIFsxMiwgY2NpdHRFT0xdLCBbMTIsIGNjaXR0RU9MXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFsxMSwgMTc5Ml0sIFsxMSwgMTc5Ml0sIFsxMSwgMTc5Ml0sIFsxMSwgMTc5Ml0sIFsxMiwgMTk4NF0sIFsxMiwgMTk4NF0sIFsxMiwgMjA0OF0sIFsxMiwgMjA0OF0sIFsxMiwgMjExMl0sIFsxMiwgMjExMl0sIFsxMiwgMjE3Nl0sIFsxMiwgMjE3Nl0sIFsxMiwgMjI0MF0sIFsxMiwgMjI0MF0sIFsxMiwgMjMwNF0sIFsxMiwgMjMwNF0sIFsxMSwgMTg1Nl0sIFsxMSwgMTg1Nl0sIFsxMSwgMTg1Nl0sIFsxMSwgMTg1Nl0sIFsxMSwgMTkyMF0sIFsxMSwgMTkyMF0sIFsxMSwgMTkyMF0sIFsxMSwgMTkyMF0sIFsxMiwgMjM2OF0sIFsxMiwgMjM2OF0sIFsxMiwgMjQzMl0sIFsxMiwgMjQzMl0sIFsxMiwgMjQ5Nl0sIFsxMiwgMjQ5Nl0sIFsxMiwgMjU2MF0sIFsxMiwgMjU2MF0sIFsxMCwgMThdLCBbMTAsIDE4XSwgWzEwLCAxOF0sIFsxMCwgMThdLCBbMTAsIDE4XSwgWzEwLCAxOF0sIFsxMCwgMThdLCBbMTAsIDE4XSwgWzEyLCA1Ml0sIFsxMiwgNTJdLCBbMTMsIDY0MF0sIFsxMywgNzA0XSwgWzEzLCA3NjhdLCBbMTMsIDgzMl0sIFsxMiwgNTVdLCBbMTIsIDU1XSwgWzEyLCA1Nl0sIFsxMiwgNTZdLCBbMTMsIDEyODBdLCBbMTMsIDEzNDRdLCBbMTMsIDE0MDhdLCBbMTMsIDE0NzJdLCBbMTIsIDU5XSwgWzEyLCA1OV0sIFsxMiwgNjBdLCBbMTIsIDYwXSwgWzEzLCAxNTM2XSwgWzEzLCAxNjAwXSwgWzExLCAyNF0sIFsxMSwgMjRdLCBbMTEsIDI0XSwgWzExLCAyNF0sIFsxMSwgMjVdLCBbMTEsIDI1XSwgWzExLCAyNV0sIFsxMSwgMjVdLCBbMTMsIDE2NjRdLCBbMTMsIDE3MjhdLCBbMTIsIDMyMF0sIFsxMiwgMzIwXSwgWzEyLCAzODRdLCBbMTIsIDM4NF0sIFsxMiwgNDQ4XSwgWzEyLCA0NDhdLCBbMTMsIDUxMl0sIFsxMywgNTc2XSwgWzEyLCA1M10sIFsxMiwgNTNdLCBbMTIsIDU0XSwgWzEyLCA1NF0sIFsxMywgODk2XSwgWzEzLCA5NjBdLCBbMTMsIDEwMjRdLCBbMTMsIDEwODhdLCBbMTMsIDExNTJdLCBbMTMsIDEyMTZdLCBbMTAsIDY0XSwgWzEwLCA2NF0sIFsxMCwgNjRdLCBbMTAsIDY0XSwgWzEwLCA2NF0sIFsxMCwgNjRdLCBbMTAsIDY0XSwgWzEwLCA2NF1dOwpjb25zdCBibGFja1RhYmxlMiA9IFtbOCwgMTNdLCBbOCwgMTNdLCBbOCwgMTNdLCBbOCwgMTNdLCBbOCwgMTNdLCBbOCwgMTNdLCBbOCwgMTNdLCBbOCwgMTNdLCBbOCwgMTNdLCBbOCwgMTNdLCBbOCwgMTNdLCBbOCwgMTNdLCBbOCwgMTNdLCBbOCwgMTNdLCBbOCwgMTNdLCBbOCwgMTNdLCBbMTEsIDIzXSwgWzExLCAyM10sIFsxMiwgNTBdLCBbMTIsIDUxXSwgWzEyLCA0NF0sIFsxMiwgNDVdLCBbMTIsIDQ2XSwgWzEyLCA0N10sIFsxMiwgNTddLCBbMTIsIDU4XSwgWzEyLCA2MV0sIFsxMiwgMjU2XSwgWzEwLCAxNl0sIFsxMCwgMTZdLCBbMTAsIDE2XSwgWzEwLCAxNl0sIFsxMCwgMTddLCBbMTAsIDE3XSwgWzEwLCAxN10sIFsxMCwgMTddLCBbMTIsIDQ4XSwgWzEyLCA0OV0sIFsxMiwgNjJdLCBbMTIsIDYzXSwgWzEyLCAzMF0sIFsxMiwgMzFdLCBbMTIsIDMyXSwgWzEyLCAzM10sIFsxMiwgNDBdLCBbMTIsIDQxXSwgWzExLCAyMl0sIFsxMSwgMjJdLCBbOCwgMTRdLCBbOCwgMTRdLCBbOCwgMTRdLCBbOCwgMTRdLCBbOCwgMTRdLCBbOCwgMTRdLCBbOCwgMTRdLCBbOCwgMTRdLCBbOCwgMTRdLCBbOCwgMTRdLCBbOCwgMTRdLCBbOCwgMTRdLCBbOCwgMTRdLCBbOCwgMTRdLCBbOCwgMTRdLCBbOCwgMTRdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTBdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbNywgMTFdLCBbOSwgMTVdLCBbOSwgMTVdLCBbOSwgMTVdLCBbOSwgMTVdLCBbOSwgMTVdLCBbOSwgMTVdLCBbOSwgMTVdLCBbOSwgMTVdLCBbMTIsIDEyOF0sIFsxMiwgMTkyXSwgWzEyLCAyNl0sIFsxMiwgMjddLCBbMTIsIDI4XSwgWzEyLCAyOV0sIFsxMSwgMTldLCBbMTEsIDE5XSwgWzExLCAyMF0sIFsxMSwgMjBdLCBbMTIsIDM0XSwgWzEyLCAzNV0sIFsxMiwgMzZdLCBbMTIsIDM3XSwgWzEyLCAzOF0sIFsxMiwgMzldLCBbMTEsIDIxXSwgWzExLCAyMV0sIFsxMiwgNDJdLCBbMTIsIDQzXSwgWzEwLCAwXSwgWzEwLCAwXSwgWzEwLCAwXSwgWzEwLCAwXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXSwgWzcsIDEyXV07CmNvbnN0IGJsYWNrVGFibGUzID0gW1stMSwgLTFdLCBbLTEsIC0xXSwgWy0xLCAtMV0sIFstMSwgLTFdLCBbNiwgOV0sIFs2LCA4XSwgWzUsIDddLCBbNSwgN10sIFs0LCA2XSwgWzQsIDZdLCBbNCwgNl0sIFs0LCA2XSwgWzQsIDVdLCBbNCwgNV0sIFs0LCA1XSwgWzQsIDVdLCBbMywgMV0sIFszLCAxXSwgWzMsIDFdLCBbMywgMV0sIFszLCAxXSwgWzMsIDFdLCBbMywgMV0sIFszLCAxXSwgWzMsIDRdLCBbMywgNF0sIFszLCA0XSwgWzMsIDRdLCBbMywgNF0sIFszLCA0XSwgWzMsIDRdLCBbMywgNF0sIFsyLCAzXSwgWzIsIDNdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDNdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDNdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDNdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDNdLCBbMiwgM10sIFsyLCAzXSwgWzIsIDJdLCBbMiwgMl0sIFsyLCAyXSwgWzIsIDJdLCBbMiwgMl0sIFsyLCAyXSwgWzIsIDJdLCBbMiwgMl0sIFsyLCAyXSwgWzIsIDJdLCBbMiwgMl0sIFsyLCAyXSwgWzIsIDJdLCBbMiwgMl0sIFsyLCAyXSwgWzIsIDJdXTsKY2xhc3MgQ0NJVFRGYXhEZWNvZGVyIHsKICBjb25zdHJ1Y3Rvcihzb3VyY2UsIG9wdGlvbnMgPSB7fSkgewogICAgaWYgKHR5cGVvZiBzb3VyY2U/Lm5leHQgIT09ICJmdW5jdGlvbiIpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdDQ0lUVEZheERlY29kZXIgLSBpbnZhbGlkICJzb3VyY2UiIHBhcmFtZXRlci4nKTsKICAgIH0KICAgIHRoaXMuc291cmNlID0gc291cmNlOwogICAgdGhpcy5lb2YgPSBmYWxzZTsKICAgIHRoaXMuZW5jb2RpbmcgPSBvcHRpb25zLksgfHwgMDsKICAgIHRoaXMuZW9saW5lID0gb3B0aW9ucy5FbmRPZkxpbmUgfHwgZmFsc2U7CiAgICB0aGlzLmJ5dGVBbGlnbiA9IG9wdGlvbnMuRW5jb2RlZEJ5dGVBbGlnbiB8fCBmYWxzZTsKICAgIHRoaXMuY29sdW1ucyA9IG9wdGlvbnMuQ29sdW1ucyB8fCAxNzI4OwogICAgdGhpcy5yb3dzID0gb3B0aW9ucy5Sb3dzIHx8IDA7CiAgICB0aGlzLmVvYmxvY2sgPSBvcHRpb25zLkVuZE9mQmxvY2sgPz8gdHJ1ZTsKICAgIHRoaXMuYmxhY2sgPSBvcHRpb25zLkJsYWNrSXMxIHx8IGZhbHNlOwogICAgdGhpcy5jb2RpbmdMaW5lID0gbmV3IFVpbnQzMkFycmF5KHRoaXMuY29sdW1ucyArIDEpOwogICAgdGhpcy5yZWZMaW5lID0gbmV3IFVpbnQzMkFycmF5KHRoaXMuY29sdW1ucyArIDIpOwogICAgdGhpcy5jb2RpbmdMaW5lWzBdID0gdGhpcy5jb2x1bW5zOwogICAgdGhpcy5jb2RpbmdQb3MgPSAwOwogICAgdGhpcy5yb3cgPSAwOwogICAgdGhpcy5uZXh0TGluZTJEID0gdGhpcy5lbmNvZGluZyA8IDA7CiAgICB0aGlzLmlucHV0Qml0cyA9IDA7CiAgICB0aGlzLmlucHV0QnVmID0gMDsKICAgIHRoaXMub3V0cHV0Qml0cyA9IDA7CiAgICB0aGlzLnJvd3NEb25lID0gZmFsc2U7CiAgICBsZXQgY29kZTE7CiAgICB3aGlsZSAoKGNvZGUxID0gdGhpcy5fbG9va0JpdHMoMTIpKSA9PT0gMCkgewogICAgICB0aGlzLl9lYXRCaXRzKDEpOwogICAgfQogICAgaWYgKGNvZGUxID09PSAxKSB7CiAgICAgIHRoaXMuX2VhdEJpdHMoMTIpOwogICAgfQogICAgaWYgKHRoaXMuZW5jb2RpbmcgPiAwKSB7CiAgICAgIHRoaXMubmV4dExpbmUyRCA9ICF0aGlzLl9sb29rQml0cygxKTsKICAgICAgdGhpcy5fZWF0Qml0cygxKTsKICAgIH0KICB9CiAgcmVhZE5leHRDaGFyKCkgewogICAgaWYgKHRoaXMuZW9mKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIGNvbnN0IHJlZkxpbmUgPSB0aGlzLnJlZkxpbmU7CiAgICBjb25zdCBjb2RpbmdMaW5lID0gdGhpcy5jb2RpbmdMaW5lOwogICAgY29uc3QgY29sdW1ucyA9IHRoaXMuY29sdW1uczsKICAgIGxldCByZWZQb3MsIGJsYWNrUGl4ZWxzLCBiaXRzLCBpOwogICAgaWYgKHRoaXMub3V0cHV0Qml0cyA9PT0gMCkgewogICAgICBpZiAodGhpcy5yb3dzRG9uZSkgewogICAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgfQogICAgICBpZiAodGhpcy5lb2YpIHsKICAgICAgICByZXR1cm4gLTE7CiAgICAgIH0KICAgICAgdGhpcy5lcnIgPSBmYWxzZTsKICAgICAgbGV0IGNvZGUxLCBjb2RlMiwgY29kZTM7CiAgICAgIGlmICh0aGlzLm5leHRMaW5lMkQpIHsKICAgICAgICBmb3IgKGkgPSAwOyBjb2RpbmdMaW5lW2ldIDwgY29sdW1uczsgKytpKSB7CiAgICAgICAgICByZWZMaW5lW2ldID0gY29kaW5nTGluZVtpXTsKICAgICAgICB9CiAgICAgICAgcmVmTGluZVtpKytdID0gY29sdW1uczsKICAgICAgICByZWZMaW5lW2ldID0gY29sdW1uczsKICAgICAgICBjb2RpbmdMaW5lWzBdID0gMDsKICAgICAgICB0aGlzLmNvZGluZ1BvcyA9IDA7CiAgICAgICAgcmVmUG9zID0gMDsKICAgICAgICBibGFja1BpeGVscyA9IDA7CiAgICAgICAgd2hpbGUgKGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgY29kZTEgPSB0aGlzLl9nZXRUd29EaW1Db2RlKCk7CiAgICAgICAgICBzd2l0Y2ggKGNvZGUxKSB7CiAgICAgICAgICAgIGNhc2UgdHdvRGltUGFzczoKICAgICAgICAgICAgICB0aGlzLl9hZGRQaXhlbHMocmVmTGluZVtyZWZQb3MgKyAxXSwgYmxhY2tQaXhlbHMpOwogICAgICAgICAgICAgIGlmIChyZWZMaW5lW3JlZlBvcyArIDFdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgcmVmUG9zICs9IDI7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIHR3b0RpbUhvcml6OgogICAgICAgICAgICAgIGNvZGUxID0gY29kZTIgPSAwOwogICAgICAgICAgICAgIGlmIChibGFja1BpeGVscykgewogICAgICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgICAgICBjb2RlMSArPSBjb2RlMyA9IHRoaXMuX2dldEJsYWNrQ29kZSgpOwogICAgICAgICAgICAgICAgfSB3aGlsZSAoY29kZTMgPj0gNjQpOwogICAgICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgICAgICBjb2RlMiArPSBjb2RlMyA9IHRoaXMuX2dldFdoaXRlQ29kZSgpOwogICAgICAgICAgICAgICAgfSB3aGlsZSAoY29kZTMgPj0gNjQpOwogICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgICAgIGNvZGUxICs9IGNvZGUzID0gdGhpcy5fZ2V0V2hpdGVDb2RlKCk7CiAgICAgICAgICAgICAgICB9IHdoaWxlIChjb2RlMyA+PSA2NCk7CiAgICAgICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgICAgIGNvZGUyICs9IGNvZGUzID0gdGhpcy5fZ2V0QmxhY2tDb2RlKCk7CiAgICAgICAgICAgICAgICB9IHdoaWxlIChjb2RlMyA+PSA2NCk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRoaXMuX2FkZFBpeGVscyhjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSArIGNvZGUxLCBibGFja1BpeGVscyk7CiAgICAgICAgICAgICAgaWYgKGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgdGhpcy5fYWRkUGl4ZWxzKGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdICsgY29kZTIsIGJsYWNrUGl4ZWxzIF4gMSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHdoaWxlIChyZWZMaW5lW3JlZlBvc10gPD0gY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gJiYgcmVmTGluZVtyZWZQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgcmVmUG9zICs9IDI7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIHR3b0RpbVZlcnRSMzoKICAgICAgICAgICAgICB0aGlzLl9hZGRQaXhlbHMocmVmTGluZVtyZWZQb3NdICsgMywgYmxhY2tQaXhlbHMpOwogICAgICAgICAgICAgIGJsYWNrUGl4ZWxzIF49IDE7CiAgICAgICAgICAgICAgaWYgKGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgKytyZWZQb3M7CiAgICAgICAgICAgICAgICB3aGlsZSAocmVmTGluZVtyZWZQb3NdIDw9IGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdICYmIHJlZkxpbmVbcmVmUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgICAgcmVmUG9zICs9IDI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIHR3b0RpbVZlcnRSMjoKICAgICAgICAgICAgICB0aGlzLl9hZGRQaXhlbHMocmVmTGluZVtyZWZQb3NdICsgMiwgYmxhY2tQaXhlbHMpOwogICAgICAgICAgICAgIGJsYWNrUGl4ZWxzIF49IDE7CiAgICAgICAgICAgICAgaWYgKGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgKytyZWZQb3M7CiAgICAgICAgICAgICAgICB3aGlsZSAocmVmTGluZVtyZWZQb3NdIDw9IGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdICYmIHJlZkxpbmVbcmVmUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgICAgcmVmUG9zICs9IDI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIHR3b0RpbVZlcnRSMToKICAgICAgICAgICAgICB0aGlzLl9hZGRQaXhlbHMocmVmTGluZVtyZWZQb3NdICsgMSwgYmxhY2tQaXhlbHMpOwogICAgICAgICAgICAgIGJsYWNrUGl4ZWxzIF49IDE7CiAgICAgICAgICAgICAgaWYgKGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgKytyZWZQb3M7CiAgICAgICAgICAgICAgICB3aGlsZSAocmVmTGluZVtyZWZQb3NdIDw9IGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdICYmIHJlZkxpbmVbcmVmUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgICAgcmVmUG9zICs9IDI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIHR3b0RpbVZlcnQwOgogICAgICAgICAgICAgIHRoaXMuX2FkZFBpeGVscyhyZWZMaW5lW3JlZlBvc10sIGJsYWNrUGl4ZWxzKTsKICAgICAgICAgICAgICBibGFja1BpeGVscyBePSAxOwogICAgICAgICAgICAgIGlmIChjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgICsrcmVmUG9zOwogICAgICAgICAgICAgICAgd2hpbGUgKHJlZkxpbmVbcmVmUG9zXSA8PSBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSAmJiByZWZMaW5lW3JlZlBvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICAgIHJlZlBvcyArPSAyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSB0d29EaW1WZXJ0TDM6CiAgICAgICAgICAgICAgdGhpcy5fYWRkUGl4ZWxzTmVnKHJlZkxpbmVbcmVmUG9zXSAtIDMsIGJsYWNrUGl4ZWxzKTsKICAgICAgICAgICAgICBibGFja1BpeGVscyBePSAxOwogICAgICAgICAgICAgIGlmIChjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgIGlmIChyZWZQb3MgPiAwKSB7CiAgICAgICAgICAgICAgICAgIC0tcmVmUG9zOwogICAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgICAgKytyZWZQb3M7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB3aGlsZSAocmVmTGluZVtyZWZQb3NdIDw9IGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdICYmIHJlZkxpbmVbcmVmUG9zXSA8IGNvbHVtbnMpIHsKICAgICAgICAgICAgICAgICAgcmVmUG9zICs9IDI7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIHR3b0RpbVZlcnRMMjoKICAgICAgICAgICAgICB0aGlzLl9hZGRQaXhlbHNOZWcocmVmTGluZVtyZWZQb3NdIC0gMiwgYmxhY2tQaXhlbHMpOwogICAgICAgICAgICAgIGJsYWNrUGl4ZWxzIF49IDE7CiAgICAgICAgICAgICAgaWYgKGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgaWYgKHJlZlBvcyA+IDApIHsKICAgICAgICAgICAgICAgICAgLS1yZWZQb3M7CiAgICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgICArK3JlZlBvczsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHdoaWxlIChyZWZMaW5lW3JlZlBvc10gPD0gY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gJiYgcmVmTGluZVtyZWZQb3NdIDwgY29sdW1ucykgewogICAgICAgICAgICAgICAgICByZWZQb3MgKz0gMjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgdHdvRGltVmVydEwxOgogICAgICAgICAgICAgIHRoaXMuX2FkZFBpeGVsc05lZyhyZWZMaW5lW3JlZlBvc10gLSAxLCBibGFja1BpeGVscyk7CiAgICAgICAgICAgICAgYmxhY2tQaXhlbHMgXj0gMTsKICAgICAgICAgICAgICBpZiAoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICBpZiAocmVmUG9zID4gMCkgewogICAgICAgICAgICAgICAgICAtLXJlZlBvczsKICAgICAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICAgICsrcmVmUG9zOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgd2hpbGUgKHJlZkxpbmVbcmVmUG9zXSA8PSBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zXSAmJiByZWZMaW5lW3JlZlBvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgICAgICAgIHJlZlBvcyArPSAyOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSBjY2l0dEVPRjoKICAgICAgICAgICAgICB0aGlzLl9hZGRQaXhlbHMoY29sdW1ucywgMCk7CiAgICAgICAgICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgIGluZm8oImJhZCAyZCBjb2RlIik7CiAgICAgICAgICAgICAgdGhpcy5fYWRkUGl4ZWxzKGNvbHVtbnMsIDApOwogICAgICAgICAgICAgIHRoaXMuZXJyID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29kaW5nTGluZVswXSA9IDA7CiAgICAgICAgdGhpcy5jb2RpbmdQb3MgPSAwOwogICAgICAgIGJsYWNrUGl4ZWxzID0gMDsKICAgICAgICB3aGlsZSAoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICBjb2RlMSA9IDA7CiAgICAgICAgICBpZiAoYmxhY2tQaXhlbHMpIHsKICAgICAgICAgICAgZG8gewogICAgICAgICAgICAgIGNvZGUxICs9IGNvZGUzID0gdGhpcy5fZ2V0QmxhY2tDb2RlKCk7CiAgICAgICAgICAgIH0gd2hpbGUgKGNvZGUzID49IDY0KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGRvIHsKICAgICAgICAgICAgICBjb2RlMSArPSBjb2RlMyA9IHRoaXMuX2dldFdoaXRlQ29kZSgpOwogICAgICAgICAgICB9IHdoaWxlIChjb2RlMyA+PSA2NCk7CiAgICAgICAgICB9CiAgICAgICAgICB0aGlzLl9hZGRQaXhlbHMoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gKyBjb2RlMSwgYmxhY2tQaXhlbHMpOwogICAgICAgICAgYmxhY2tQaXhlbHMgXj0gMTsKICAgICAgICB9CiAgICAgIH0KICAgICAgbGV0IGdvdEVPTCA9IGZhbHNlOwogICAgICBpZiAodGhpcy5ieXRlQWxpZ24pIHsKICAgICAgICB0aGlzLmlucHV0Qml0cyAmPSB+NzsKICAgICAgfQogICAgICBpZiAoIXRoaXMuZW9ibG9jayAmJiB0aGlzLnJvdyA9PT0gdGhpcy5yb3dzIC0gMSkgewogICAgICAgIHRoaXMucm93c0RvbmUgPSB0cnVlOwogICAgICB9IGVsc2UgewogICAgICAgIGNvZGUxID0gdGhpcy5fbG9va0JpdHMoMTIpOwogICAgICAgIGlmICh0aGlzLmVvbGluZSkgewogICAgICAgICAgd2hpbGUgKGNvZGUxICE9PSBjY2l0dEVPRiAmJiBjb2RlMSAhPT0gMSkgewogICAgICAgICAgICB0aGlzLl9lYXRCaXRzKDEpOwogICAgICAgICAgICBjb2RlMSA9IHRoaXMuX2xvb2tCaXRzKDEyKTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgd2hpbGUgKGNvZGUxID09PSAwKSB7CiAgICAgICAgICAgIHRoaXMuX2VhdEJpdHMoMSk7CiAgICAgICAgICAgIGNvZGUxID0gdGhpcy5fbG9va0JpdHMoMTIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoY29kZTEgPT09IDEpIHsKICAgICAgICAgIHRoaXMuX2VhdEJpdHMoMTIpOwogICAgICAgICAgZ290RU9MID0gdHJ1ZTsKICAgICAgICB9IGVsc2UgaWYgKGNvZGUxID09PSBjY2l0dEVPRikgewogICAgICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoIXRoaXMuZW9mICYmIHRoaXMuZW5jb2RpbmcgPiAwICYmICF0aGlzLnJvd3NEb25lKSB7CiAgICAgICAgdGhpcy5uZXh0TGluZTJEID0gIXRoaXMuX2xvb2tCaXRzKDEpOwogICAgICAgIHRoaXMuX2VhdEJpdHMoMSk7CiAgICAgIH0KICAgICAgaWYgKHRoaXMuZW9ibG9jayAmJiBnb3RFT0wgJiYgdGhpcy5ieXRlQWxpZ24pIHsKICAgICAgICBjb2RlMSA9IHRoaXMuX2xvb2tCaXRzKDEyKTsKICAgICAgICBpZiAoY29kZTEgPT09IDEpIHsKICAgICAgICAgIHRoaXMuX2VhdEJpdHMoMTIpOwogICAgICAgICAgaWYgKHRoaXMuZW5jb2RpbmcgPiAwKSB7CiAgICAgICAgICAgIHRoaXMuX2xvb2tCaXRzKDEpOwogICAgICAgICAgICB0aGlzLl9lYXRCaXRzKDEpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHRoaXMuZW5jb2RpbmcgPj0gMCkgewogICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNDsgKytpKSB7CiAgICAgICAgICAgICAgY29kZTEgPSB0aGlzLl9sb29rQml0cygxMik7CiAgICAgICAgICAgICAgaWYgKGNvZGUxICE9PSAxKSB7CiAgICAgICAgICAgICAgICBpbmZvKCJiYWQgcnRjIGNvZGU6ICIgKyBjb2RlMSk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRoaXMuX2VhdEJpdHMoMTIpOwogICAgICAgICAgICAgIGlmICh0aGlzLmVuY29kaW5nID4gMCkgewogICAgICAgICAgICAgICAgdGhpcy5fbG9va0JpdHMoMSk7CiAgICAgICAgICAgICAgICB0aGlzLl9lYXRCaXRzKDEpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmICh0aGlzLmVyciAmJiB0aGlzLmVvbGluZSkgewogICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICBjb2RlMSA9IHRoaXMuX2xvb2tCaXRzKDEzKTsKICAgICAgICAgIGlmIChjb2RlMSA9PT0gY2NpdHRFT0YpIHsKICAgICAgICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICAgICAgICByZXR1cm4gLTE7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoY29kZTEgPj4gMSA9PT0gMSkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuX2VhdEJpdHMoMSk7CiAgICAgICAgfQogICAgICAgIHRoaXMuX2VhdEJpdHMoMTIpOwogICAgICAgIGlmICh0aGlzLmVuY29kaW5nID4gMCkgewogICAgICAgICAgdGhpcy5fZWF0Qml0cygxKTsKICAgICAgICAgIHRoaXMubmV4dExpbmUyRCA9ICEoY29kZTEgJiAxKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgdGhpcy5vdXRwdXRCaXRzID0gY29kaW5nTGluZVswXSA+IDAgPyBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zID0gMF0gOiBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zID0gMV07CiAgICAgIHRoaXMucm93Kys7CiAgICB9CiAgICBsZXQgYzsKICAgIGlmICh0aGlzLm91dHB1dEJpdHMgPj0gOCkgewogICAgICBjID0gdGhpcy5jb2RpbmdQb3MgJiAxID8gMCA6IDB4ZmY7CiAgICAgIHRoaXMub3V0cHV0Qml0cyAtPSA4OwogICAgICBpZiAodGhpcy5vdXRwdXRCaXRzID09PSAwICYmIGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdIDwgY29sdW1ucykgewogICAgICAgIHRoaXMuY29kaW5nUG9zKys7CiAgICAgICAgdGhpcy5vdXRwdXRCaXRzID0gY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gLSBjb2RpbmdMaW5lW3RoaXMuY29kaW5nUG9zIC0gMV07CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGJpdHMgPSA4OwogICAgICBjID0gMDsKICAgICAgZG8gewogICAgICAgIGlmICh0eXBlb2YgdGhpcy5vdXRwdXRCaXRzICE9PSAibnVtYmVyIikgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCdJbnZhbGlkIC9DQ0lUVEZheERlY29kZSBkYXRhLCAib3V0cHV0Qml0cyIgbXVzdCBiZSBhIG51bWJlci4nKTsKICAgICAgICB9CiAgICAgICAgaWYgKHRoaXMub3V0cHV0Qml0cyA+IGJpdHMpIHsKICAgICAgICAgIGMgPDw9IGJpdHM7CiAgICAgICAgICBpZiAoISh0aGlzLmNvZGluZ1BvcyAmIDEpKSB7CiAgICAgICAgICAgIGMgfD0gMHhmZiA+PiA4IC0gYml0czsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMub3V0cHV0Qml0cyAtPSBiaXRzOwogICAgICAgICAgYml0cyA9IDA7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGMgPDw9IHRoaXMub3V0cHV0Qml0czsKICAgICAgICAgIGlmICghKHRoaXMuY29kaW5nUG9zICYgMSkpIHsKICAgICAgICAgICAgYyB8PSAweGZmID4+IDggLSB0aGlzLm91dHB1dEJpdHM7CiAgICAgICAgICB9CiAgICAgICAgICBiaXRzIC09IHRoaXMub3V0cHV0Qml0czsKICAgICAgICAgIHRoaXMub3V0cHV0Qml0cyA9IDA7CiAgICAgICAgICBpZiAoY29kaW5nTGluZVt0aGlzLmNvZGluZ1Bvc10gPCBjb2x1bW5zKSB7CiAgICAgICAgICAgIHRoaXMuY29kaW5nUG9zKys7CiAgICAgICAgICAgIHRoaXMub3V0cHV0Qml0cyA9IGNvZGluZ0xpbmVbdGhpcy5jb2RpbmdQb3NdIC0gY29kaW5nTGluZVt0aGlzLmNvZGluZ1BvcyAtIDFdOwogICAgICAgICAgfSBlbHNlIGlmIChiaXRzID4gMCkgewogICAgICAgICAgICBjIDw8PSBiaXRzOwogICAgICAgICAgICBiaXRzID0gMDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gd2hpbGUgKGJpdHMpOwogICAgfQogICAgaWYgKHRoaXMuYmxhY2spIHsKICAgICAgYyBePSAweGZmOwogICAgfQogICAgcmV0dXJuIGM7CiAgfQogIF9hZGRQaXhlbHMoYTEsIGJsYWNrUGl4ZWxzKSB7CiAgICBjb25zdCBjb2RpbmdMaW5lID0gdGhpcy5jb2RpbmdMaW5lOwogICAgbGV0IGNvZGluZ1BvcyA9IHRoaXMuY29kaW5nUG9zOwogICAgaWYgKGExID4gY29kaW5nTGluZVtjb2RpbmdQb3NdKSB7CiAgICAgIGlmIChhMSA+IHRoaXMuY29sdW1ucykgewogICAgICAgIGluZm8oInJvdyBpcyB3cm9uZyBsZW5ndGgiKTsKICAgICAgICB0aGlzLmVyciA9IHRydWU7CiAgICAgICAgYTEgPSB0aGlzLmNvbHVtbnM7CiAgICAgIH0KICAgICAgaWYgKGNvZGluZ1BvcyAmIDEgXiBibGFja1BpeGVscykgewogICAgICAgICsrY29kaW5nUG9zOwogICAgICB9CiAgICAgIGNvZGluZ0xpbmVbY29kaW5nUG9zXSA9IGExOwogICAgfQogICAgdGhpcy5jb2RpbmdQb3MgPSBjb2RpbmdQb3M7CiAgfQogIF9hZGRQaXhlbHNOZWcoYTEsIGJsYWNrUGl4ZWxzKSB7CiAgICBjb25zdCBjb2RpbmdMaW5lID0gdGhpcy5jb2RpbmdMaW5lOwogICAgbGV0IGNvZGluZ1BvcyA9IHRoaXMuY29kaW5nUG9zOwogICAgaWYgKGExID4gY29kaW5nTGluZVtjb2RpbmdQb3NdKSB7CiAgICAgIGlmIChhMSA+IHRoaXMuY29sdW1ucykgewogICAgICAgIGluZm8oInJvdyBpcyB3cm9uZyBsZW5ndGgiKTsKICAgICAgICB0aGlzLmVyciA9IHRydWU7CiAgICAgICAgYTEgPSB0aGlzLmNvbHVtbnM7CiAgICAgIH0KICAgICAgaWYgKGNvZGluZ1BvcyAmIDEgXiBibGFja1BpeGVscykgewogICAgICAgICsrY29kaW5nUG9zOwogICAgICB9CiAgICAgIGNvZGluZ0xpbmVbY29kaW5nUG9zXSA9IGExOwogICAgfSBlbHNlIGlmIChhMSA8IGNvZGluZ0xpbmVbY29kaW5nUG9zXSkgewogICAgICBpZiAoYTEgPCAwKSB7CiAgICAgICAgaW5mbygiaW52YWxpZCBjb2RlIik7CiAgICAgICAgdGhpcy5lcnIgPSB0cnVlOwogICAgICAgIGExID0gMDsKICAgICAgfQogICAgICB3aGlsZSAoY29kaW5nUG9zID4gMCAmJiBhMSA8IGNvZGluZ0xpbmVbY29kaW5nUG9zIC0gMV0pIHsKICAgICAgICAtLWNvZGluZ1BvczsKICAgICAgfQogICAgICBjb2RpbmdMaW5lW2NvZGluZ1Bvc10gPSBhMTsKICAgIH0KICAgIHRoaXMuY29kaW5nUG9zID0gY29kaW5nUG9zOwogIH0KICBfZmluZFRhYmxlQ29kZShzdGFydCwgZW5kLCB0YWJsZSwgbGltaXQpIHsKICAgIGNvbnN0IGxpbWl0VmFsdWUgPSBsaW1pdCB8fCAwOwogICAgZm9yIChsZXQgaSA9IHN0YXJ0OyBpIDw9IGVuZDsgKytpKSB7CiAgICAgIGxldCBjb2RlID0gdGhpcy5fbG9va0JpdHMoaSk7CiAgICAgIGlmIChjb2RlID09PSBjY2l0dEVPRikgewogICAgICAgIHJldHVybiBbdHJ1ZSwgMSwgZmFsc2VdOwogICAgICB9CiAgICAgIGlmIChpIDwgZW5kKSB7CiAgICAgICAgY29kZSA8PD0gZW5kIC0gaTsKICAgICAgfQogICAgICBpZiAoIWxpbWl0VmFsdWUgfHwgY29kZSA+PSBsaW1pdFZhbHVlKSB7CiAgICAgICAgY29uc3QgcCA9IHRhYmxlW2NvZGUgLSBsaW1pdFZhbHVlXTsKICAgICAgICBpZiAocFswXSA9PT0gaSkgewogICAgICAgICAgdGhpcy5fZWF0Qml0cyhpKTsKICAgICAgICAgIHJldHVybiBbdHJ1ZSwgcFsxXSwgdHJ1ZV07CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gW2ZhbHNlLCAwLCBmYWxzZV07CiAgfQogIF9nZXRUd29EaW1Db2RlKCkgewogICAgbGV0IGNvZGUgPSAwOwogICAgbGV0IHA7CiAgICBpZiAodGhpcy5lb2Jsb2NrKSB7CiAgICAgIGNvZGUgPSB0aGlzLl9sb29rQml0cyg3KTsKICAgICAgcCA9IHR3b0RpbVRhYmxlW2NvZGVdOwogICAgICBpZiAocD8uWzBdID4gMCkgewogICAgICAgIHRoaXMuX2VhdEJpdHMocFswXSk7CiAgICAgICAgcmV0dXJuIHBbMV07CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuX2ZpbmRUYWJsZUNvZGUoMSwgNywgdHdvRGltVGFibGUpOwogICAgICBpZiAocmVzdWx0WzBdICYmIHJlc3VsdFsyXSkgewogICAgICAgIHJldHVybiByZXN1bHRbMV07CiAgICAgIH0KICAgIH0KICAgIGluZm8oIkJhZCB0d28gZGltIGNvZGUiKTsKICAgIHJldHVybiBjY2l0dEVPRjsKICB9CiAgX2dldFdoaXRlQ29kZSgpIHsKICAgIGxldCBjb2RlID0gMDsKICAgIGxldCBwOwogICAgaWYgKHRoaXMuZW9ibG9jaykgewogICAgICBjb2RlID0gdGhpcy5fbG9va0JpdHMoMTIpOwogICAgICBpZiAoY29kZSA9PT0gY2NpdHRFT0YpIHsKICAgICAgICByZXR1cm4gMTsKICAgICAgfQogICAgICBwID0gY29kZSA+PiA1ID09PSAwID8gd2hpdGVUYWJsZTFbY29kZV0gOiB3aGl0ZVRhYmxlMltjb2RlID4+IDNdOwogICAgICBpZiAocFswXSA+IDApIHsKICAgICAgICB0aGlzLl9lYXRCaXRzKHBbMF0pOwogICAgICAgIHJldHVybiBwWzFdOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBsZXQgcmVzdWx0ID0gdGhpcy5fZmluZFRhYmxlQ29kZSgxLCA5LCB3aGl0ZVRhYmxlMik7CiAgICAgIGlmIChyZXN1bHRbMF0pIHsKICAgICAgICByZXR1cm4gcmVzdWx0WzFdOwogICAgICB9CiAgICAgIHJlc3VsdCA9IHRoaXMuX2ZpbmRUYWJsZUNvZGUoMTEsIDEyLCB3aGl0ZVRhYmxlMSk7CiAgICAgIGlmIChyZXN1bHRbMF0pIHsKICAgICAgICByZXR1cm4gcmVzdWx0WzFdOwogICAgICB9CiAgICB9CiAgICBpbmZvKCJiYWQgd2hpdGUgY29kZSIpOwogICAgdGhpcy5fZWF0Qml0cygxKTsKICAgIHJldHVybiAxOwogIH0KICBfZ2V0QmxhY2tDb2RlKCkgewogICAgbGV0IGNvZGUsIHA7CiAgICBpZiAodGhpcy5lb2Jsb2NrKSB7CiAgICAgIGNvZGUgPSB0aGlzLl9sb29rQml0cygxMyk7CiAgICAgIGlmIChjb2RlID09PSBjY2l0dEVPRikgewogICAgICAgIHJldHVybiAxOwogICAgICB9CiAgICAgIGlmIChjb2RlID4+IDcgPT09IDApIHsKICAgICAgICBwID0gYmxhY2tUYWJsZTFbY29kZV07CiAgICAgIH0gZWxzZSBpZiAoY29kZSA+PiA5ID09PSAwICYmIGNvZGUgPj4gNyAhPT0gMCkgewogICAgICAgIHAgPSBibGFja1RhYmxlMlsoY29kZSA+PiAxKSAtIDY0XTsKICAgICAgfSBlbHNlIHsKICAgICAgICBwID0gYmxhY2tUYWJsZTNbY29kZSA+PiA3XTsKICAgICAgfQogICAgICBpZiAocFswXSA+IDApIHsKICAgICAgICB0aGlzLl9lYXRCaXRzKHBbMF0pOwogICAgICAgIHJldHVybiBwWzFdOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBsZXQgcmVzdWx0ID0gdGhpcy5fZmluZFRhYmxlQ29kZSgyLCA2LCBibGFja1RhYmxlMyk7CiAgICAgIGlmIChyZXN1bHRbMF0pIHsKICAgICAgICByZXR1cm4gcmVzdWx0WzFdOwogICAgICB9CiAgICAgIHJlc3VsdCA9IHRoaXMuX2ZpbmRUYWJsZUNvZGUoNywgMTIsIGJsYWNrVGFibGUyLCA2NCk7CiAgICAgIGlmIChyZXN1bHRbMF0pIHsKICAgICAgICByZXR1cm4gcmVzdWx0WzFdOwogICAgICB9CiAgICAgIHJlc3VsdCA9IHRoaXMuX2ZpbmRUYWJsZUNvZGUoMTAsIDEzLCBibGFja1RhYmxlMSk7CiAgICAgIGlmIChyZXN1bHRbMF0pIHsKICAgICAgICByZXR1cm4gcmVzdWx0WzFdOwogICAgICB9CiAgICB9CiAgICBpbmZvKCJiYWQgYmxhY2sgY29kZSIpOwogICAgdGhpcy5fZWF0Qml0cygxKTsKICAgIHJldHVybiAxOwogIH0KICBfbG9va0JpdHMobikgewogICAgbGV0IGM7CiAgICB3aGlsZSAodGhpcy5pbnB1dEJpdHMgPCBuKSB7CiAgICAgIGlmICgoYyA9IHRoaXMuc291cmNlLm5leHQoKSkgPT09IC0xKSB7CiAgICAgICAgaWYgKHRoaXMuaW5wdXRCaXRzID09PSAwKSB7CiAgICAgICAgICByZXR1cm4gY2NpdHRFT0Y7CiAgICAgICAgfQogICAgICAgIHJldHVybiB0aGlzLmlucHV0QnVmIDw8IG4gLSB0aGlzLmlucHV0Qml0cyAmIDB4ZmZmZiA+PiAxNiAtIG47CiAgICAgIH0KICAgICAgdGhpcy5pbnB1dEJ1ZiA9IHRoaXMuaW5wdXRCdWYgPDwgOCB8IGM7CiAgICAgIHRoaXMuaW5wdXRCaXRzICs9IDg7CiAgICB9CiAgICByZXR1cm4gdGhpcy5pbnB1dEJ1ZiA+PiB0aGlzLmlucHV0Qml0cyAtIG4gJiAweGZmZmYgPj4gMTYgLSBuOwogIH0KICBfZWF0Qml0cyhuKSB7CiAgICBpZiAoKHRoaXMuaW5wdXRCaXRzIC09IG4pIDwgMCkgewogICAgICB0aGlzLmlucHV0Qml0cyA9IDA7CiAgICB9CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9jY2l0dF9zdHJlYW0uanMKCgoKY2xhc3MgQ0NJVFRGYXhTdHJlYW0gZXh0ZW5kcyBEZWNvZGVTdHJlYW0gewogIGNvbnN0cnVjdG9yKHN0ciwgbWF5YmVMZW5ndGgsIHBhcmFtcykgewogICAgc3VwZXIobWF5YmVMZW5ndGgpOwogICAgdGhpcy5zdHIgPSBzdHI7CiAgICB0aGlzLmRpY3QgPSBzdHIuZGljdDsKICAgIGlmICghKHBhcmFtcyBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHBhcmFtcyA9IERpY3QuZW1wdHk7CiAgICB9CiAgICBjb25zdCBzb3VyY2UgPSB7CiAgICAgIG5leHQoKSB7CiAgICAgICAgcmV0dXJuIHN0ci5nZXRCeXRlKCk7CiAgICAgIH0KICAgIH07CiAgICB0aGlzLmNjaXR0RmF4RGVjb2RlciA9IG5ldyBDQ0lUVEZheERlY29kZXIoc291cmNlLCB7CiAgICAgIEs6IHBhcmFtcy5nZXQoIksiKSwKICAgICAgRW5kT2ZMaW5lOiBwYXJhbXMuZ2V0KCJFbmRPZkxpbmUiKSwKICAgICAgRW5jb2RlZEJ5dGVBbGlnbjogcGFyYW1zLmdldCgiRW5jb2RlZEJ5dGVBbGlnbiIpLAogICAgICBDb2x1bW5zOiBwYXJhbXMuZ2V0KCJDb2x1bW5zIiksCiAgICAgIFJvd3M6IHBhcmFtcy5nZXQoIlJvd3MiKSwKICAgICAgRW5kT2ZCbG9jazogcGFyYW1zLmdldCgiRW5kT2ZCbG9jayIpLAogICAgICBCbGFja0lzMTogcGFyYW1zLmdldCgiQmxhY2tJczEiKQogICAgfSk7CiAgfQogIHJlYWRCbG9jaygpIHsKICAgIHdoaWxlICghdGhpcy5lb2YpIHsKICAgICAgY29uc3QgYyA9IHRoaXMuY2NpdHRGYXhEZWNvZGVyLnJlYWROZXh0Q2hhcigpOwogICAgICBpZiAoYyA9PT0gLTEpIHsKICAgICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIHRoaXMuZW5zdXJlQnVmZmVyKHRoaXMuYnVmZmVyTGVuZ3RoICsgMSk7CiAgICAgIHRoaXMuYnVmZmVyW3RoaXMuYnVmZmVyTGVuZ3RoKytdID0gYzsKICAgIH0KICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2ZsYXRlX3N0cmVhbS5qcwoKCgoKCgoKCgoKCgpjb25zdCBjb2RlTGVuQ29kZU1hcCA9IG5ldyBJbnQzMkFycmF5KFsxNiwgMTcsIDE4LCAwLCA4LCA3LCA5LCA2LCAxMCwgNSwgMTEsIDQsIDEyLCAzLCAxMywgMiwgMTQsIDEsIDE1XSk7CmNvbnN0IGxlbmd0aERlY29kZSA9IG5ldyBJbnQzMkFycmF5KFsweDAwMDAzLCAweDAwMDA0LCAweDAwMDA1LCAweDAwMDA2LCAweDAwMDA3LCAweDAwMDA4LCAweDAwMDA5LCAweDAwMDBhLCAweDEwMDBiLCAweDEwMDBkLCAweDEwMDBmLCAweDEwMDExLCAweDIwMDEzLCAweDIwMDE3LCAweDIwMDFiLCAweDIwMDFmLCAweDMwMDIzLCAweDMwMDJiLCAweDMwMDMzLCAweDMwMDNiLCAweDQwMDQzLCAweDQwMDUzLCAweDQwMDYzLCAweDQwMDczLCAweDUwMDgzLCAweDUwMGEzLCAweDUwMGMzLCAweDUwMGUzLCAweDAwMTAyLCAweDAwMTAyLCAweDAwMTAyXSk7CmNvbnN0IGRpc3REZWNvZGUgPSBuZXcgSW50MzJBcnJheShbMHgwMDAwMSwgMHgwMDAwMiwgMHgwMDAwMywgMHgwMDAwNCwgMHgxMDAwNSwgMHgxMDAwNywgMHgyMDAwOSwgMHgyMDAwZCwgMHgzMDAxMSwgMHgzMDAxOSwgMHg0MDAyMSwgMHg0MDAzMSwgMHg1MDA0MSwgMHg1MDA2MSwgMHg2MDA4MSwgMHg2MDBjMSwgMHg3MDEwMSwgMHg3MDE4MSwgMHg4MDIwMSwgMHg4MDMwMSwgMHg5MDQwMSwgMHg5MDYwMSwgMHhhMDgwMSwgMHhhMGMwMSwgMHhiMTAwMSwgMHhiMTgwMSwgMHhjMjAwMSwgMHhjMzAwMSwgMHhkNDAwMSwgMHhkNjAwMV0pOwpjb25zdCBmaXhlZExpdENvZGVUYWIgPSBbbmV3IEludDMyQXJyYXkoWzB4NzAxMDAsIDB4ODAwNTAsIDB4ODAwMTAsIDB4ODAxMTgsIDB4NzAxMTAsIDB4ODAwNzAsIDB4ODAwMzAsIDB4OTAwYzAsIDB4NzAxMDgsIDB4ODAwNjAsIDB4ODAwMjAsIDB4OTAwYTAsIDB4ODAwMDAsIDB4ODAwODAsIDB4ODAwNDAsIDB4OTAwZTAsIDB4NzAxMDQsIDB4ODAwNTgsIDB4ODAwMTgsIDB4OTAwOTAsIDB4NzAxMTQsIDB4ODAwNzgsIDB4ODAwMzgsIDB4OTAwZDAsIDB4NzAxMGMsIDB4ODAwNjgsIDB4ODAwMjgsIDB4OTAwYjAsIDB4ODAwMDgsIDB4ODAwODgsIDB4ODAwNDgsIDB4OTAwZjAsIDB4NzAxMDIsIDB4ODAwNTQsIDB4ODAwMTQsIDB4ODAxMWMsIDB4NzAxMTIsIDB4ODAwNzQsIDB4ODAwMzQsIDB4OTAwYzgsIDB4NzAxMGEsIDB4ODAwNjQsIDB4ODAwMjQsIDB4OTAwYTgsIDB4ODAwMDQsIDB4ODAwODQsIDB4ODAwNDQsIDB4OTAwZTgsIDB4NzAxMDYsIDB4ODAwNWMsIDB4ODAwMWMsIDB4OTAwOTgsIDB4NzAxMTYsIDB4ODAwN2MsIDB4ODAwM2MsIDB4OTAwZDgsIDB4NzAxMGUsIDB4ODAwNmMsIDB4ODAwMmMsIDB4OTAwYjgsIDB4ODAwMGMsIDB4ODAwOGMsIDB4ODAwNGMsIDB4OTAwZjgsIDB4NzAxMDEsIDB4ODAwNTIsIDB4ODAwMTIsIDB4ODAxMWEsIDB4NzAxMTEsIDB4ODAwNzIsIDB4ODAwMzIsIDB4OTAwYzQsIDB4NzAxMDksIDB4ODAwNjIsIDB4ODAwMjIsIDB4OTAwYTQsIDB4ODAwMDIsIDB4ODAwODIsIDB4ODAwNDIsIDB4OTAwZTQsIDB4NzAxMDUsIDB4ODAwNWEsIDB4ODAwMWEsIDB4OTAwOTQsIDB4NzAxMTUsIDB4ODAwN2EsIDB4ODAwM2EsIDB4OTAwZDQsIDB4NzAxMGQsIDB4ODAwNmEsIDB4ODAwMmEsIDB4OTAwYjQsIDB4ODAwMGEsIDB4ODAwOGEsIDB4ODAwNGEsIDB4OTAwZjQsIDB4NzAxMDMsIDB4ODAwNTYsIDB4ODAwMTYsIDB4ODAxMWUsIDB4NzAxMTMsIDB4ODAwNzYsIDB4ODAwMzYsIDB4OTAwY2MsIDB4NzAxMGIsIDB4ODAwNjYsIDB4ODAwMjYsIDB4OTAwYWMsIDB4ODAwMDYsIDB4ODAwODYsIDB4ODAwNDYsIDB4OTAwZWMsIDB4NzAxMDcsIDB4ODAwNWUsIDB4ODAwMWUsIDB4OTAwOWMsIDB4NzAxMTcsIDB4ODAwN2UsIDB4ODAwM2UsIDB4OTAwZGMsIDB4NzAxMGYsIDB4ODAwNmUsIDB4ODAwMmUsIDB4OTAwYmMsIDB4ODAwMGUsIDB4ODAwOGUsIDB4ODAwNGUsIDB4OTAwZmMsIDB4NzAxMDAsIDB4ODAwNTEsIDB4ODAwMTEsIDB4ODAxMTksIDB4NzAxMTAsIDB4ODAwNzEsIDB4ODAwMzEsIDB4OTAwYzIsIDB4NzAxMDgsIDB4ODAwNjEsIDB4ODAwMjEsIDB4OTAwYTIsIDB4ODAwMDEsIDB4ODAwODEsIDB4ODAwNDEsIDB4OTAwZTIsIDB4NzAxMDQsIDB4ODAwNTksIDB4ODAwMTksIDB4OTAwOTIsIDB4NzAxMTQsIDB4ODAwNzksIDB4ODAwMzksIDB4OTAwZDIsIDB4NzAxMGMsIDB4ODAwNjksIDB4ODAwMjksIDB4OTAwYjIsIDB4ODAwMDksIDB4ODAwODksIDB4ODAwNDksIDB4OTAwZjIsIDB4NzAxMDIsIDB4ODAwNTUsIDB4ODAwMTUsIDB4ODAxMWQsIDB4NzAxMTIsIDB4ODAwNzUsIDB4ODAwMzUsIDB4OTAwY2EsIDB4NzAxMGEsIDB4ODAwNjUsIDB4ODAwMjUsIDB4OTAwYWEsIDB4ODAwMDUsIDB4ODAwODUsIDB4ODAwNDUsIDB4OTAwZWEsIDB4NzAxMDYsIDB4ODAwNWQsIDB4ODAwMWQsIDB4OTAwOWEsIDB4NzAxMTYsIDB4ODAwN2QsIDB4ODAwM2QsIDB4OTAwZGEsIDB4NzAxMGUsIDB4ODAwNmQsIDB4ODAwMmQsIDB4OTAwYmEsIDB4ODAwMGQsIDB4ODAwOGQsIDB4ODAwNGQsIDB4OTAwZmEsIDB4NzAxMDEsIDB4ODAwNTMsIDB4ODAwMTMsIDB4ODAxMWIsIDB4NzAxMTEsIDB4ODAwNzMsIDB4ODAwMzMsIDB4OTAwYzYsIDB4NzAxMDksIDB4ODAwNjMsIDB4ODAwMjMsIDB4OTAwYTYsIDB4ODAwMDMsIDB4ODAwODMsIDB4ODAwNDMsIDB4OTAwZTYsIDB4NzAxMDUsIDB4ODAwNWIsIDB4ODAwMWIsIDB4OTAwOTYsIDB4NzAxMTUsIDB4ODAwN2IsIDB4ODAwM2IsIDB4OTAwZDYsIDB4NzAxMGQsIDB4ODAwNmIsIDB4ODAwMmIsIDB4OTAwYjYsIDB4ODAwMGIsIDB4ODAwOGIsIDB4ODAwNGIsIDB4OTAwZjYsIDB4NzAxMDMsIDB4ODAwNTcsIDB4ODAwMTcsIDB4ODAxMWYsIDB4NzAxMTMsIDB4ODAwNzcsIDB4ODAwMzcsIDB4OTAwY2UsIDB4NzAxMGIsIDB4ODAwNjcsIDB4ODAwMjcsIDB4OTAwYWUsIDB4ODAwMDcsIDB4ODAwODcsIDB4ODAwNDcsIDB4OTAwZWUsIDB4NzAxMDcsIDB4ODAwNWYsIDB4ODAwMWYsIDB4OTAwOWUsIDB4NzAxMTcsIDB4ODAwN2YsIDB4ODAwM2YsIDB4OTAwZGUsIDB4NzAxMGYsIDB4ODAwNmYsIDB4ODAwMmYsIDB4OTAwYmUsIDB4ODAwMGYsIDB4ODAwOGYsIDB4ODAwNGYsIDB4OTAwZmUsIDB4NzAxMDAsIDB4ODAwNTAsIDB4ODAwMTAsIDB4ODAxMTgsIDB4NzAxMTAsIDB4ODAwNzAsIDB4ODAwMzAsIDB4OTAwYzEsIDB4NzAxMDgsIDB4ODAwNjAsIDB4ODAwMjAsIDB4OTAwYTEsIDB4ODAwMDAsIDB4ODAwODAsIDB4ODAwNDAsIDB4OTAwZTEsIDB4NzAxMDQsIDB4ODAwNTgsIDB4ODAwMTgsIDB4OTAwOTEsIDB4NzAxMTQsIDB4ODAwNzgsIDB4ODAwMzgsIDB4OTAwZDEsIDB4NzAxMGMsIDB4ODAwNjgsIDB4ODAwMjgsIDB4OTAwYjEsIDB4ODAwMDgsIDB4ODAwODgsIDB4ODAwNDgsIDB4OTAwZjEsIDB4NzAxMDIsIDB4ODAwNTQsIDB4ODAwMTQsIDB4ODAxMWMsIDB4NzAxMTIsIDB4ODAwNzQsIDB4ODAwMzQsIDB4OTAwYzksIDB4NzAxMGEsIDB4ODAwNjQsIDB4ODAwMjQsIDB4OTAwYTksIDB4ODAwMDQsIDB4ODAwODQsIDB4ODAwNDQsIDB4OTAwZTksIDB4NzAxMDYsIDB4ODAwNWMsIDB4ODAwMWMsIDB4OTAwOTksIDB4NzAxMTYsIDB4ODAwN2MsIDB4ODAwM2MsIDB4OTAwZDksIDB4NzAxMGUsIDB4ODAwNmMsIDB4ODAwMmMsIDB4OTAwYjksIDB4ODAwMGMsIDB4ODAwOGMsIDB4ODAwNGMsIDB4OTAwZjksIDB4NzAxMDEsIDB4ODAwNTIsIDB4ODAwMTIsIDB4ODAxMWEsIDB4NzAxMTEsIDB4ODAwNzIsIDB4ODAwMzIsIDB4OTAwYzUsIDB4NzAxMDksIDB4ODAwNjIsIDB4ODAwMjIsIDB4OTAwYTUsIDB4ODAwMDIsIDB4ODAwODIsIDB4ODAwNDIsIDB4OTAwZTUsIDB4NzAxMDUsIDB4ODAwNWEsIDB4ODAwMWEsIDB4OTAwOTUsIDB4NzAxMTUsIDB4ODAwN2EsIDB4ODAwM2EsIDB4OTAwZDUsIDB4NzAxMGQsIDB4ODAwNmEsIDB4ODAwMmEsIDB4OTAwYjUsIDB4ODAwMGEsIDB4ODAwOGEsIDB4ODAwNGEsIDB4OTAwZjUsIDB4NzAxMDMsIDB4ODAwNTYsIDB4ODAwMTYsIDB4ODAxMWUsIDB4NzAxMTMsIDB4ODAwNzYsIDB4ODAwMzYsIDB4OTAwY2QsIDB4NzAxMGIsIDB4ODAwNjYsIDB4ODAwMjYsIDB4OTAwYWQsIDB4ODAwMDYsIDB4ODAwODYsIDB4ODAwNDYsIDB4OTAwZWQsIDB4NzAxMDcsIDB4ODAwNWUsIDB4ODAwMWUsIDB4OTAwOWQsIDB4NzAxMTcsIDB4ODAwN2UsIDB4ODAwM2UsIDB4OTAwZGQsIDB4NzAxMGYsIDB4ODAwNmUsIDB4ODAwMmUsIDB4OTAwYmQsIDB4ODAwMGUsIDB4ODAwOGUsIDB4ODAwNGUsIDB4OTAwZmQsIDB4NzAxMDAsIDB4ODAwNTEsIDB4ODAwMTEsIDB4ODAxMTksIDB4NzAxMTAsIDB4ODAwNzEsIDB4ODAwMzEsIDB4OTAwYzMsIDB4NzAxMDgsIDB4ODAwNjEsIDB4ODAwMjEsIDB4OTAwYTMsIDB4ODAwMDEsIDB4ODAwODEsIDB4ODAwNDEsIDB4OTAwZTMsIDB4NzAxMDQsIDB4ODAwNTksIDB4ODAwMTksIDB4OTAwOTMsIDB4NzAxMTQsIDB4ODAwNzksIDB4ODAwMzksIDB4OTAwZDMsIDB4NzAxMGMsIDB4ODAwNjksIDB4ODAwMjksIDB4OTAwYjMsIDB4ODAwMDksIDB4ODAwODksIDB4ODAwNDksIDB4OTAwZjMsIDB4NzAxMDIsIDB4ODAwNTUsIDB4ODAwMTUsIDB4ODAxMWQsIDB4NzAxMTIsIDB4ODAwNzUsIDB4ODAwMzUsIDB4OTAwY2IsIDB4NzAxMGEsIDB4ODAwNjUsIDB4ODAwMjUsIDB4OTAwYWIsIDB4ODAwMDUsIDB4ODAwODUsIDB4ODAwNDUsIDB4OTAwZWIsIDB4NzAxMDYsIDB4ODAwNWQsIDB4ODAwMWQsIDB4OTAwOWIsIDB4NzAxMTYsIDB4ODAwN2QsIDB4ODAwM2QsIDB4OTAwZGIsIDB4NzAxMGUsIDB4ODAwNmQsIDB4ODAwMmQsIDB4OTAwYmIsIDB4ODAwMGQsIDB4ODAwOGQsIDB4ODAwNGQsIDB4OTAwZmIsIDB4NzAxMDEsIDB4ODAwNTMsIDB4ODAwMTMsIDB4ODAxMWIsIDB4NzAxMTEsIDB4ODAwNzMsIDB4ODAwMzMsIDB4OTAwYzcsIDB4NzAxMDksIDB4ODAwNjMsIDB4ODAwMjMsIDB4OTAwYTcsIDB4ODAwMDMsIDB4ODAwODMsIDB4ODAwNDMsIDB4OTAwZTcsIDB4NzAxMDUsIDB4ODAwNWIsIDB4ODAwMWIsIDB4OTAwOTcsIDB4NzAxMTUsIDB4ODAwN2IsIDB4ODAwM2IsIDB4OTAwZDcsIDB4NzAxMGQsIDB4ODAwNmIsIDB4ODAwMmIsIDB4OTAwYjcsIDB4ODAwMGIsIDB4ODAwOGIsIDB4ODAwNGIsIDB4OTAwZjcsIDB4NzAxMDMsIDB4ODAwNTcsIDB4ODAwMTcsIDB4ODAxMWYsIDB4NzAxMTMsIDB4ODAwNzcsIDB4ODAwMzcsIDB4OTAwY2YsIDB4NzAxMGIsIDB4ODAwNjcsIDB4ODAwMjcsIDB4OTAwYWYsIDB4ODAwMDcsIDB4ODAwODcsIDB4ODAwNDcsIDB4OTAwZWYsIDB4NzAxMDcsIDB4ODAwNWYsIDB4ODAwMWYsIDB4OTAwOWYsIDB4NzAxMTcsIDB4ODAwN2YsIDB4ODAwM2YsIDB4OTAwZGYsIDB4NzAxMGYsIDB4ODAwNmYsIDB4ODAwMmYsIDB4OTAwYmYsIDB4ODAwMGYsIDB4ODAwOGYsIDB4ODAwNGYsIDB4OTAwZmZdKSwgOV07CmNvbnN0IGZpeGVkRGlzdENvZGVUYWIgPSBbbmV3IEludDMyQXJyYXkoWzB4NTAwMDAsIDB4NTAwMTAsIDB4NTAwMDgsIDB4NTAwMTgsIDB4NTAwMDQsIDB4NTAwMTQsIDB4NTAwMGMsIDB4NTAwMWMsIDB4NTAwMDIsIDB4NTAwMTIsIDB4NTAwMGEsIDB4NTAwMWEsIDB4NTAwMDYsIDB4NTAwMTYsIDB4NTAwMGUsIDB4MDAwMDAsIDB4NTAwMDEsIDB4NTAwMTEsIDB4NTAwMDksIDB4NTAwMTksIDB4NTAwMDUsIDB4NTAwMTUsIDB4NTAwMGQsIDB4NTAwMWQsIDB4NTAwMDMsIDB4NTAwMTMsIDB4NTAwMGIsIDB4NTAwMWIsIDB4NTAwMDcsIDB4NTAwMTcsIDB4NTAwMGYsIDB4MDAwMDBdKSwgNV07CmNsYXNzIEZsYXRlU3RyZWFtIGV4dGVuZHMgRGVjb2RlU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihzdHIsIG1heWJlTGVuZ3RoKSB7CiAgICBzdXBlcihtYXliZUxlbmd0aCk7CiAgICB0aGlzLnN0ciA9IHN0cjsKICAgIHRoaXMuZGljdCA9IHN0ci5kaWN0OwogICAgY29uc3QgY21mID0gc3RyLmdldEJ5dGUoKTsKICAgIGNvbnN0IGZsZyA9IHN0ci5nZXRCeXRlKCk7CiAgICBpZiAoY21mID09PSAtMSB8fCBmbGcgPT09IC0xKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBoZWFkZXIgaW4gZmxhdGUgc3RyZWFtOiAke2NtZn0sICR7ZmxnfWApOwogICAgfQogICAgaWYgKChjbWYgJiAweDBmKSAhPT0gMHgwOCkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYFVua25vd24gY29tcHJlc3Npb24gbWV0aG9kIGluIGZsYXRlIHN0cmVhbTogJHtjbWZ9LCAke2ZsZ31gKTsKICAgIH0KICAgIGlmICgoKGNtZiA8PCA4KSArIGZsZykgJSAzMSAhPT0gMCkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEJhZCBGQ0hFQ0sgaW4gZmxhdGUgc3RyZWFtOiAke2NtZn0sICR7ZmxnfWApOwogICAgfQogICAgaWYgKGZsZyAmIDB4MjApIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBGRElDVCBiaXQgc2V0IGluIGZsYXRlIHN0cmVhbTogJHtjbWZ9LCAke2ZsZ31gKTsKICAgIH0KICAgIHRoaXMuY29kZVNpemUgPSAwOwogICAgdGhpcy5jb2RlQnVmID0gMDsKICB9CiAgYXN5bmMgZ2V0SW1hZ2VEYXRhKGxlbmd0aCwgX2RlY29kZXJPcHRpb25zKSB7CiAgICBjb25zdCBkYXRhID0gYXdhaXQgdGhpcy5hc3luY0dldEJ5dGVzKCk7CiAgICBpZiAoIWRhdGEpIHsKICAgICAgcmV0dXJuIHRoaXMuZ2V0Qnl0ZXMobGVuZ3RoKTsKICAgIH0KICAgIGlmIChkYXRhLmxlbmd0aCA8PSBsZW5ndGgpIHsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9CiAgICByZXR1cm4gZGF0YS5zdWJhcnJheSgwLCBsZW5ndGgpOwogIH0KICBhc3luYyBhc3luY0dldEJ5dGVzKCkgewogICAgdGhpcy5zdHIucmVzZXQoKTsKICAgIGNvbnN0IGJ5dGVzID0gdGhpcy5zdHIuZ2V0Qnl0ZXMoKTsKICAgIHRyeSB7CiAgICAgIGNvbnN0IHsKICAgICAgICByZWFkYWJsZSwKICAgICAgICB3cml0YWJsZQogICAgICB9ID0gbmV3IERlY29tcHJlc3Npb25TdHJlYW0oImRlZmxhdGUiKTsKICAgICAgY29uc3Qgd3JpdGVyID0gd3JpdGFibGUuZ2V0V3JpdGVyKCk7CiAgICAgIGF3YWl0IHdyaXRlci5yZWFkeTsKICAgICAgd3JpdGVyLndyaXRlKGJ5dGVzKS50aGVuKGFzeW5jICgpID0+IHsKICAgICAgICBhd2FpdCB3cml0ZXIucmVhZHk7CiAgICAgICAgYXdhaXQgd3JpdGVyLmNsb3NlKCk7CiAgICAgIH0pLmNhdGNoKCgpID0+IHt9KTsKICAgICAgY29uc3QgY2h1bmtzID0gW107CiAgICAgIGxldCB0b3RhbExlbmd0aCA9IDA7CiAgICAgIGZvciBhd2FpdCAoY29uc3QgY2h1bmsgb2YgcmVhZGFibGUpIHsKICAgICAgICBjaHVua3MucHVzaChjaHVuayk7CiAgICAgICAgdG90YWxMZW5ndGggKz0gY2h1bmsuYnl0ZUxlbmd0aDsKICAgICAgfQogICAgICBjb25zdCBkYXRhID0gbmV3IFVpbnQ4QXJyYXkodG90YWxMZW5ndGgpOwogICAgICBsZXQgb2Zmc2V0ID0gMDsKICAgICAgZm9yIChjb25zdCBjaHVuayBvZiBjaHVua3MpIHsKICAgICAgICBkYXRhLnNldChjaHVuaywgb2Zmc2V0KTsKICAgICAgICBvZmZzZXQgKz0gY2h1bmsuYnl0ZUxlbmd0aDsKICAgICAgfQogICAgICByZXR1cm4gZGF0YTsKICAgIH0gY2F0Y2ggewogICAgICB0aGlzLnN0ciA9IG5ldyBTdHJlYW0oYnl0ZXMsIDIsIGJ5dGVzLmxlbmd0aCwgdGhpcy5zdHIuZGljdCk7CiAgICAgIHRoaXMucmVzZXQoKTsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgfQogIGdldCBpc0FzeW5jKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIGdldEJpdHMoYml0cykgewogICAgY29uc3Qgc3RyID0gdGhpcy5zdHI7CiAgICBsZXQgY29kZVNpemUgPSB0aGlzLmNvZGVTaXplOwogICAgbGV0IGNvZGVCdWYgPSB0aGlzLmNvZGVCdWY7CiAgICBsZXQgYjsKICAgIHdoaWxlIChjb2RlU2l6ZSA8IGJpdHMpIHsKICAgICAgaWYgKChiID0gc3RyLmdldEJ5dGUoKSkgPT09IC0xKSB7CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJCYWQgZW5jb2RpbmcgaW4gZmxhdGUgc3RyZWFtIik7CiAgICAgIH0KICAgICAgY29kZUJ1ZiB8PSBiIDw8IGNvZGVTaXplOwogICAgICBjb2RlU2l6ZSArPSA4OwogICAgfQogICAgYiA9IGNvZGVCdWYgJiAoMSA8PCBiaXRzKSAtIDE7CiAgICB0aGlzLmNvZGVCdWYgPSBjb2RlQnVmID4+IGJpdHM7CiAgICB0aGlzLmNvZGVTaXplID0gY29kZVNpemUgLT0gYml0czsKICAgIHJldHVybiBiOwogIH0KICBnZXRDb2RlKHRhYmxlKSB7CiAgICBjb25zdCBzdHIgPSB0aGlzLnN0cjsKICAgIGNvbnN0IGNvZGVzID0gdGFibGVbMF07CiAgICBjb25zdCBtYXhMZW4gPSB0YWJsZVsxXTsKICAgIGxldCBjb2RlU2l6ZSA9IHRoaXMuY29kZVNpemU7CiAgICBsZXQgY29kZUJ1ZiA9IHRoaXMuY29kZUJ1ZjsKICAgIGxldCBiOwogICAgd2hpbGUgKGNvZGVTaXplIDwgbWF4TGVuKSB7CiAgICAgIGlmICgoYiA9IHN0ci5nZXRCeXRlKCkpID09PSAtMSkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGNvZGVCdWYgfD0gYiA8PCBjb2RlU2l6ZTsKICAgICAgY29kZVNpemUgKz0gODsKICAgIH0KICAgIGNvbnN0IGNvZGUgPSBjb2Rlc1tjb2RlQnVmICYgKDEgPDwgbWF4TGVuKSAtIDFdOwogICAgY29uc3QgY29kZUxlbiA9IGNvZGUgPj4gMTY7CiAgICBjb25zdCBjb2RlVmFsID0gY29kZSAmIDB4ZmZmZjsKICAgIGlmIChjb2RlTGVuIDwgMSB8fCBjb2RlU2l6ZSA8IGNvZGVMZW4pIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJCYWQgZW5jb2RpbmcgaW4gZmxhdGUgc3RyZWFtIik7CiAgICB9CiAgICB0aGlzLmNvZGVCdWYgPSBjb2RlQnVmID4+IGNvZGVMZW47CiAgICB0aGlzLmNvZGVTaXplID0gY29kZVNpemUgLSBjb2RlTGVuOwogICAgcmV0dXJuIGNvZGVWYWw7CiAgfQogIGdlbmVyYXRlSHVmZm1hblRhYmxlKGxlbmd0aHMpIHsKICAgIGNvbnN0IG4gPSBsZW5ndGhzLmxlbmd0aDsKICAgIGxldCBtYXhMZW4gPSAwOwogICAgbGV0IGk7CiAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpKSB7CiAgICAgIGlmIChsZW5ndGhzW2ldID4gbWF4TGVuKSB7CiAgICAgICAgbWF4TGVuID0gbGVuZ3Roc1tpXTsKICAgICAgfQogICAgfQogICAgY29uc3Qgc2l6ZSA9IDEgPDwgbWF4TGVuOwogICAgY29uc3QgY29kZXMgPSBuZXcgSW50MzJBcnJheShzaXplKTsKICAgIGZvciAobGV0IGxlbiA9IDEsIGNvZGUgPSAwLCBza2lwID0gMjsgbGVuIDw9IG1heExlbjsgKytsZW4sIGNvZGUgPDw9IDEsIHNraXAgPDw9IDEpIHsKICAgICAgZm9yIChsZXQgdmFsID0gMDsgdmFsIDwgbjsgKyt2YWwpIHsKICAgICAgICBpZiAobGVuZ3Roc1t2YWxdID09PSBsZW4pIHsKICAgICAgICAgIGxldCBjb2RlMiA9IDA7CiAgICAgICAgICBsZXQgdCA9IGNvZGU7CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyArK2kpIHsKICAgICAgICAgICAgY29kZTIgPSBjb2RlMiA8PCAxIHwgdCAmIDE7CiAgICAgICAgICAgIHQgPj49IDE7CiAgICAgICAgICB9CiAgICAgICAgICBmb3IgKGkgPSBjb2RlMjsgaSA8IHNpemU7IGkgKz0gc2tpcCkgewogICAgICAgICAgICBjb2Rlc1tpXSA9IGxlbiA8PCAxNiB8IHZhbDsKICAgICAgICAgIH0KICAgICAgICAgICsrY29kZTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBbY29kZXMsIG1heExlbl07CiAgfQogICNlbmRzU3RyZWFtT25FcnJvcihlcnIpIHsKICAgIGluZm8oZXJyKTsKICAgIHRoaXMuZW9mID0gdHJ1ZTsKICB9CiAgcmVhZEJsb2NrKCkgewogICAgbGV0IGJ1ZmZlciwgaGRyLCBsZW47CiAgICBjb25zdCBzdHIgPSB0aGlzLnN0cjsKICAgIHRyeSB7CiAgICAgIGhkciA9IHRoaXMuZ2V0Qml0cygzKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIHRoaXMuI2VuZHNTdHJlYW1PbkVycm9yKGV4Lm1lc3NhZ2UpOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoaGRyICYgMSkgewogICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICB9CiAgICBoZHIgPj49IDE7CiAgICBpZiAoaGRyID09PSAwKSB7CiAgICAgIGxldCBiOwogICAgICBpZiAoKGIgPSBzdHIuZ2V0Qnl0ZSgpKSA9PT0gLTEpIHsKICAgICAgICB0aGlzLiNlbmRzU3RyZWFtT25FcnJvcigiQmFkIGJsb2NrIGhlYWRlciBpbiBmbGF0ZSBzdHJlYW0iKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgbGV0IGJsb2NrTGVuID0gYjsKICAgICAgaWYgKChiID0gc3RyLmdldEJ5dGUoKSkgPT09IC0xKSB7CiAgICAgICAgdGhpcy4jZW5kc1N0cmVhbU9uRXJyb3IoIkJhZCBibG9jayBoZWFkZXIgaW4gZmxhdGUgc3RyZWFtIik7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGJsb2NrTGVuIHw9IGIgPDwgODsKICAgICAgaWYgKChiID0gc3RyLmdldEJ5dGUoKSkgPT09IC0xKSB7CiAgICAgICAgdGhpcy4jZW5kc1N0cmVhbU9uRXJyb3IoIkJhZCBibG9jayBoZWFkZXIgaW4gZmxhdGUgc3RyZWFtIik7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGxldCBjaGVjayA9IGI7CiAgICAgIGlmICgoYiA9IHN0ci5nZXRCeXRlKCkpID09PSAtMSkgewogICAgICAgIHRoaXMuI2VuZHNTdHJlYW1PbkVycm9yKCJCYWQgYmxvY2sgaGVhZGVyIGluIGZsYXRlIHN0cmVhbSIpOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBjaGVjayB8PSBiIDw8IDg7CiAgICAgIGlmIChjaGVjayAhPT0gKH5ibG9ja0xlbiAmIDB4ZmZmZikgJiYgKGJsb2NrTGVuICE9PSAwIHx8IGNoZWNrICE9PSAwKSkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiQmFkIHVuY29tcHJlc3NlZCBibG9jayBsZW5ndGggaW4gZmxhdGUgc3RyZWFtIik7CiAgICAgIH0KICAgICAgdGhpcy5jb2RlQnVmID0gMDsKICAgICAgdGhpcy5jb2RlU2l6ZSA9IDA7CiAgICAgIGNvbnN0IGJ1ZmZlckxlbmd0aCA9IHRoaXMuYnVmZmVyTGVuZ3RoLAogICAgICAgIGVuZCA9IGJ1ZmZlckxlbmd0aCArIGJsb2NrTGVuOwogICAgICBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcihlbmQpOwogICAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IGVuZDsKICAgICAgaWYgKGJsb2NrTGVuID09PSAwKSB7CiAgICAgICAgaWYgKHN0ci5wZWVrQnl0ZSgpID09PSAtMSkgewogICAgICAgICAgdGhpcy5lb2YgPSB0cnVlOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBibG9jayA9IHN0ci5nZXRCeXRlcyhibG9ja0xlbik7CiAgICAgICAgYnVmZmVyLnNldChibG9jaywgYnVmZmVyTGVuZ3RoKTsKICAgICAgICBpZiAoYmxvY2subGVuZ3RoIDwgYmxvY2tMZW4pIHsKICAgICAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuOwogICAgfQogICAgbGV0IGxpdENvZGVUYWJsZTsKICAgIGxldCBkaXN0Q29kZVRhYmxlOwogICAgaWYgKGhkciA9PT0gMSkgewogICAgICBsaXRDb2RlVGFibGUgPSBmaXhlZExpdENvZGVUYWI7CiAgICAgIGRpc3RDb2RlVGFibGUgPSBmaXhlZERpc3RDb2RlVGFiOwogICAgfSBlbHNlIGlmIChoZHIgPT09IDIpIHsKICAgICAgY29uc3QgbnVtTGl0Q29kZXMgPSB0aGlzLmdldEJpdHMoNSkgKyAyNTc7CiAgICAgIGNvbnN0IG51bURpc3RDb2RlcyA9IHRoaXMuZ2V0Qml0cyg1KSArIDE7CiAgICAgIGNvbnN0IG51bUNvZGVMZW5Db2RlcyA9IHRoaXMuZ2V0Qml0cyg0KSArIDQ7CiAgICAgIGNvbnN0IGNvZGVMZW5Db2RlTGVuZ3RocyA9IG5ldyBVaW50OEFycmF5KGNvZGVMZW5Db2RlTWFwLmxlbmd0aCk7CiAgICAgIGxldCBpOwogICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtQ29kZUxlbkNvZGVzOyArK2kpIHsKICAgICAgICBjb2RlTGVuQ29kZUxlbmd0aHNbY29kZUxlbkNvZGVNYXBbaV1dID0gdGhpcy5nZXRCaXRzKDMpOwogICAgICB9CiAgICAgIGNvbnN0IGNvZGVMZW5Db2RlVGFiID0gdGhpcy5nZW5lcmF0ZUh1ZmZtYW5UYWJsZShjb2RlTGVuQ29kZUxlbmd0aHMpOwogICAgICBsZW4gPSAwOwogICAgICBpID0gMDsKICAgICAgY29uc3QgY29kZXMgPSBudW1MaXRDb2RlcyArIG51bURpc3RDb2RlczsKICAgICAgY29uc3QgY29kZUxlbmd0aHMgPSBuZXcgVWludDhBcnJheShjb2Rlcyk7CiAgICAgIGxldCBiaXRzTGVuZ3RoLCBiaXRzT2Zmc2V0LCB3aGF0OwogICAgICB3aGlsZSAoaSA8IGNvZGVzKSB7CiAgICAgICAgY29uc3QgY29kZSA9IHRoaXMuZ2V0Q29kZShjb2RlTGVuQ29kZVRhYik7CiAgICAgICAgaWYgKGNvZGUgPT09IDE2KSB7CiAgICAgICAgICBiaXRzTGVuZ3RoID0gMjsKICAgICAgICAgIGJpdHNPZmZzZXQgPSAzOwogICAgICAgICAgd2hhdCA9IGxlbjsKICAgICAgICB9IGVsc2UgaWYgKGNvZGUgPT09IDE3KSB7CiAgICAgICAgICBiaXRzTGVuZ3RoID0gMzsKICAgICAgICAgIGJpdHNPZmZzZXQgPSAzOwogICAgICAgICAgd2hhdCA9IGxlbiA9IDA7CiAgICAgICAgfSBlbHNlIGlmIChjb2RlID09PSAxOCkgewogICAgICAgICAgYml0c0xlbmd0aCA9IDc7CiAgICAgICAgICBiaXRzT2Zmc2V0ID0gMTE7CiAgICAgICAgICB3aGF0ID0gbGVuID0gMDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29kZUxlbmd0aHNbaSsrXSA9IGxlbiA9IGNvZGU7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgbGV0IHJlcGVhdExlbmd0aCA9IHRoaXMuZ2V0Qml0cyhiaXRzTGVuZ3RoKSArIGJpdHNPZmZzZXQ7CiAgICAgICAgd2hpbGUgKHJlcGVhdExlbmd0aC0tID4gMCkgewogICAgICAgICAgY29kZUxlbmd0aHNbaSsrXSA9IHdoYXQ7CiAgICAgICAgfQogICAgICB9CiAgICAgIGxpdENvZGVUYWJsZSA9IHRoaXMuZ2VuZXJhdGVIdWZmbWFuVGFibGUoY29kZUxlbmd0aHMuc3ViYXJyYXkoMCwgbnVtTGl0Q29kZXMpKTsKICAgICAgZGlzdENvZGVUYWJsZSA9IHRoaXMuZ2VuZXJhdGVIdWZmbWFuVGFibGUoY29kZUxlbmd0aHMuc3ViYXJyYXkobnVtTGl0Q29kZXMsIGNvZGVzKSk7CiAgICB9IGVsc2UgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVua25vd24gYmxvY2sgdHlwZSBpbiBmbGF0ZSBzdHJlYW0iKTsKICAgIH0KICAgIGJ1ZmZlciA9IHRoaXMuYnVmZmVyOwogICAgbGV0IGxpbWl0ID0gYnVmZmVyID8gYnVmZmVyLmxlbmd0aCA6IDA7CiAgICBsZXQgcG9zID0gdGhpcy5idWZmZXJMZW5ndGg7CiAgICB3aGlsZSAodHJ1ZSkgewogICAgICBsZXQgY29kZTEgPSB0aGlzLmdldENvZGUobGl0Q29kZVRhYmxlKTsKICAgICAgaWYgKGNvZGUxIDwgMjU2KSB7CiAgICAgICAgaWYgKHBvcyArIDEgPj0gbGltaXQpIHsKICAgICAgICAgIGJ1ZmZlciA9IHRoaXMuZW5zdXJlQnVmZmVyKHBvcyArIDEpOwogICAgICAgICAgbGltaXQgPSBidWZmZXIubGVuZ3RoOwogICAgICAgIH0KICAgICAgICBidWZmZXJbcG9zKytdID0gY29kZTE7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGNvZGUxID09PSAyNTYpIHsKICAgICAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IHBvczsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgY29kZTEgLT0gMjU3OwogICAgICBjb2RlMSA9IGxlbmd0aERlY29kZVtjb2RlMV07CiAgICAgIGxldCBjb2RlMiA9IGNvZGUxID4+IDE2OwogICAgICBpZiAoY29kZTIgPiAwKSB7CiAgICAgICAgY29kZTIgPSB0aGlzLmdldEJpdHMoY29kZTIpOwogICAgICB9CiAgICAgIGxlbiA9IChjb2RlMSAmIDB4ZmZmZikgKyBjb2RlMjsKICAgICAgY29kZTEgPSB0aGlzLmdldENvZGUoZGlzdENvZGVUYWJsZSk7CiAgICAgIGNvZGUxID0gZGlzdERlY29kZVtjb2RlMV07CiAgICAgIGNvZGUyID0gY29kZTEgPj4gMTY7CiAgICAgIGlmIChjb2RlMiA+IDApIHsKICAgICAgICBjb2RlMiA9IHRoaXMuZ2V0Qml0cyhjb2RlMik7CiAgICAgIH0KICAgICAgY29uc3QgZGlzdCA9IChjb2RlMSAmIDB4ZmZmZikgKyBjb2RlMjsKICAgICAgaWYgKHBvcyArIGxlbiA+PSBsaW1pdCkgewogICAgICAgIGJ1ZmZlciA9IHRoaXMuZW5zdXJlQnVmZmVyKHBvcyArIGxlbik7CiAgICAgICAgbGltaXQgPSBidWZmZXIubGVuZ3RoOwogICAgICB9CiAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgbGVuOyArK2ssICsrcG9zKSB7CiAgICAgICAgYnVmZmVyW3Bvc10gPSBidWZmZXJbcG9zIC0gZGlzdF07CiAgICAgIH0KICAgIH0KICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2FyaXRobWV0aWNfZGVjb2Rlci5qcwpjb25zdCBRZVRhYmxlID0gW3sKICBxZTogMHg1NjAxLAogIG5tcHM6IDEsCiAgbmxwczogMSwKICBzd2l0Y2hGbGFnOiAxCn0sIHsKICBxZTogMHgzNDAxLAogIG5tcHM6IDIsCiAgbmxwczogNiwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgxODAxLAogIG5tcHM6IDMsCiAgbmxwczogOSwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwYWMxLAogIG5tcHM6IDQsCiAgbmxwczogMTIsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDUyMSwKICBubXBzOiA1LAogIG5scHM6IDI5LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDAyMjEsCiAgbm1wczogMzgsCiAgbmxwczogMzMsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4NTYwMSwKICBubXBzOiA3LAogIG5scHM6IDYsCiAgc3dpdGNoRmxhZzogMQp9LCB7CiAgcWU6IDB4NTQwMSwKICBubXBzOiA4LAogIG5scHM6IDE0LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDQ4MDEsCiAgbm1wczogOSwKICBubHBzOiAxNCwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgzODAxLAogIG5tcHM6IDEwLAogIG5scHM6IDE0LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDMwMDEsCiAgbm1wczogMTEsCiAgbmxwczogMTcsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MjQwMSwKICBubXBzOiAxMiwKICBubHBzOiAxOCwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgxYzAxLAogIG5tcHM6IDEzLAogIG5scHM6IDIwLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDE2MDEsCiAgbm1wczogMjksCiAgbmxwczogMjEsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4NTYwMSwKICBubXBzOiAxNSwKICBubHBzOiAxNCwKICBzd2l0Y2hGbGFnOiAxCn0sIHsKICBxZTogMHg1NDAxLAogIG5tcHM6IDE2LAogIG5scHM6IDE0LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDUxMDEsCiAgbm1wczogMTcsCiAgbmxwczogMTUsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4NDgwMSwKICBubXBzOiAxOCwKICBubHBzOiAxNiwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgzODAxLAogIG5tcHM6IDE5LAogIG5scHM6IDE3LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDM0MDEsCiAgbm1wczogMjAsCiAgbmxwczogMTgsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MzAwMSwKICBubXBzOiAyMSwKICBubHBzOiAxOSwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgyODAxLAogIG5tcHM6IDIyLAogIG5scHM6IDE5LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDI0MDEsCiAgbm1wczogMjMsCiAgbmxwczogMjAsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MjIwMSwKICBubXBzOiAyNCwKICBubHBzOiAyMSwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgxYzAxLAogIG5tcHM6IDI1LAogIG5scHM6IDIyLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDE4MDEsCiAgbm1wczogMjYsCiAgbmxwczogMjMsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MTYwMSwKICBubXBzOiAyNywKICBubHBzOiAyNCwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgxNDAxLAogIG5tcHM6IDI4LAogIG5scHM6IDI1LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDEyMDEsCiAgbm1wczogMjksCiAgbmxwczogMjYsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MTEwMSwKICBubXBzOiAzMCwKICBubHBzOiAyNywKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwYWMxLAogIG5tcHM6IDMxLAogIG5scHM6IDI4LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDA5YzEsCiAgbm1wczogMzIsCiAgbmxwczogMjksCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDhhMSwKICBubXBzOiAzMywKICBubHBzOiAzMCwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwNTIxLAogIG5tcHM6IDM0LAogIG5scHM6IDMxLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDA0NDEsCiAgbm1wczogMzUsCiAgbmxwczogMzIsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDJhMSwKICBubXBzOiAzNiwKICBubHBzOiAzMywKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwMjIxLAogIG5tcHM6IDM3LAogIG5scHM6IDM0LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDAxNDEsCiAgbm1wczogMzgsCiAgbmxwczogMzUsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDExMSwKICBubXBzOiAzOSwKICBubHBzOiAzNiwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwMDg1LAogIG5tcHM6IDQwLAogIG5scHM6IDM3LAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDAwNDksCiAgbm1wczogNDEsCiAgbmxwczogMzgsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDAyNSwKICBubXBzOiA0MiwKICBubHBzOiAzOSwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwMDE1LAogIG5tcHM6IDQzLAogIG5scHM6IDQwLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDAwMDksCiAgbm1wczogNDQsCiAgbmxwczogNDEsCiAgc3dpdGNoRmxhZzogMAp9LCB7CiAgcWU6IDB4MDAwNSwKICBubXBzOiA0NSwKICBubHBzOiA0MiwKICBzd2l0Y2hGbGFnOiAwCn0sIHsKICBxZTogMHgwMDAxLAogIG5tcHM6IDQ1LAogIG5scHM6IDQzLAogIHN3aXRjaEZsYWc6IDAKfSwgewogIHFlOiAweDU2MDEsCiAgbm1wczogNDYsCiAgbmxwczogNDYsCiAgc3dpdGNoRmxhZzogMAp9XTsKY2xhc3MgQXJpdGhtZXRpY0RlY29kZXIgewogIGNvbnN0cnVjdG9yKGRhdGEsIHN0YXJ0LCBlbmQpIHsKICAgIHRoaXMuZGF0YSA9IGRhdGE7CiAgICB0aGlzLmJwID0gc3RhcnQ7CiAgICB0aGlzLmRhdGFFbmQgPSBlbmQ7CiAgICB0aGlzLmNoaWdoID0gZGF0YVtzdGFydF07CiAgICB0aGlzLmNsb3cgPSAwOwogICAgdGhpcy5ieXRlSW4oKTsKICAgIHRoaXMuY2hpZ2ggPSB0aGlzLmNoaWdoIDw8IDcgJiAweGZmZmYgfCB0aGlzLmNsb3cgPj4gOSAmIDB4N2Y7CiAgICB0aGlzLmNsb3cgPSB0aGlzLmNsb3cgPDwgNyAmIDB4ZmZmZjsKICAgIHRoaXMuY3QgLT0gNzsKICAgIHRoaXMuYSA9IDB4ODAwMDsKICB9CiAgYnl0ZUluKCkgewogICAgY29uc3QgZGF0YSA9IHRoaXMuZGF0YTsKICAgIGxldCBicCA9IHRoaXMuYnA7CiAgICBpZiAoZGF0YVticF0gPT09IDB4ZmYpIHsKICAgICAgaWYgKGRhdGFbYnAgKyAxXSA+IDB4OGYpIHsKICAgICAgICB0aGlzLmNsb3cgKz0gMHhmZjAwOwogICAgICAgIHRoaXMuY3QgPSA4OwogICAgICB9IGVsc2UgewogICAgICAgIGJwKys7CiAgICAgICAgdGhpcy5jbG93ICs9IGRhdGFbYnBdIDw8IDk7CiAgICAgICAgdGhpcy5jdCA9IDc7CiAgICAgICAgdGhpcy5icCA9IGJwOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBicCsrOwogICAgICB0aGlzLmNsb3cgKz0gYnAgPCB0aGlzLmRhdGFFbmQgPyBkYXRhW2JwXSA8PCA4IDogMHhmZjAwOwogICAgICB0aGlzLmN0ID0gODsKICAgICAgdGhpcy5icCA9IGJwOwogICAgfQogICAgaWYgKHRoaXMuY2xvdyA+IDB4ZmZmZikgewogICAgICB0aGlzLmNoaWdoICs9IHRoaXMuY2xvdyA+PiAxNjsKICAgICAgdGhpcy5jbG93ICY9IDB4ZmZmZjsKICAgIH0KICB9CiAgcmVhZEJpdChjb250ZXh0cywgcG9zKSB7CiAgICBsZXQgY3hfaW5kZXggPSBjb250ZXh0c1twb3NdID4+IDEsCiAgICAgIGN4X21wcyA9IGNvbnRleHRzW3Bvc10gJiAxOwogICAgY29uc3QgcWVUYWJsZUljeCA9IFFlVGFibGVbY3hfaW5kZXhdOwogICAgY29uc3QgcWVJY3ggPSBxZVRhYmxlSWN4LnFlOwogICAgbGV0IGQ7CiAgICBsZXQgYSA9IHRoaXMuYSAtIHFlSWN4OwogICAgaWYgKHRoaXMuY2hpZ2ggPCBxZUljeCkgewogICAgICBpZiAoYSA8IHFlSWN4KSB7CiAgICAgICAgYSA9IHFlSWN4OwogICAgICAgIGQgPSBjeF9tcHM7CiAgICAgICAgY3hfaW5kZXggPSBxZVRhYmxlSWN4Lm5tcHM7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYSA9IHFlSWN4OwogICAgICAgIGQgPSAxIF4gY3hfbXBzOwogICAgICAgIGlmIChxZVRhYmxlSWN4LnN3aXRjaEZsYWcgPT09IDEpIHsKICAgICAgICAgIGN4X21wcyA9IGQ7CiAgICAgICAgfQogICAgICAgIGN4X2luZGV4ID0gcWVUYWJsZUljeC5ubHBzOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzLmNoaWdoIC09IHFlSWN4OwogICAgICBpZiAoKGEgJiAweDgwMDApICE9PSAwKSB7CiAgICAgICAgdGhpcy5hID0gYTsKICAgICAgICByZXR1cm4gY3hfbXBzOwogICAgICB9CiAgICAgIGlmIChhIDwgcWVJY3gpIHsKICAgICAgICBkID0gMSBeIGN4X21wczsKICAgICAgICBpZiAocWVUYWJsZUljeC5zd2l0Y2hGbGFnID09PSAxKSB7CiAgICAgICAgICBjeF9tcHMgPSBkOwogICAgICAgIH0KICAgICAgICBjeF9pbmRleCA9IHFlVGFibGVJY3gubmxwczsKICAgICAgfSBlbHNlIHsKICAgICAgICBkID0gY3hfbXBzOwogICAgICAgIGN4X2luZGV4ID0gcWVUYWJsZUljeC5ubXBzOwogICAgICB9CiAgICB9CiAgICBkbyB7CiAgICAgIGlmICh0aGlzLmN0ID09PSAwKSB7CiAgICAgICAgdGhpcy5ieXRlSW4oKTsKICAgICAgfQogICAgICBhIDw8PSAxOwogICAgICB0aGlzLmNoaWdoID0gdGhpcy5jaGlnaCA8PCAxICYgMHhmZmZmIHwgdGhpcy5jbG93ID4+IDE1ICYgMTsKICAgICAgdGhpcy5jbG93ID0gdGhpcy5jbG93IDw8IDEgJiAweGZmZmY7CiAgICAgIHRoaXMuY3QtLTsKICAgIH0gd2hpbGUgKChhICYgMHg4MDAwKSA9PT0gMCk7CiAgICB0aGlzLmEgPSBhOwogICAgY29udGV4dHNbcG9zXSA9IGN4X2luZGV4IDw8IDEgfCBjeF9tcHM7CiAgICByZXR1cm4gZDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2piaWcyLmpzCgoKCgoKCgoKCgoKCgpjbGFzcyBKYmlnMkVycm9yIGV4dGVuZHMgQmFzZUV4Y2VwdGlvbiB7CiAgY29uc3RydWN0b3IobXNnKSB7CiAgICBzdXBlcihtc2csICJKYmlnMkVycm9yIik7CiAgfQp9CmNsYXNzIENvbnRleHRDYWNoZSB7CiAgZ2V0Q29udGV4dHMoaWQpIHsKICAgIGlmIChpZCBpbiB0aGlzKSB7CiAgICAgIHJldHVybiB0aGlzW2lkXTsKICAgIH0KICAgIHJldHVybiB0aGlzW2lkXSA9IG5ldyBJbnQ4QXJyYXkoMSA8PCAxNik7CiAgfQp9CmNsYXNzIERlY29kaW5nQ29udGV4dCB7CiAgY29uc3RydWN0b3IoZGF0YSwgc3RhcnQsIGVuZCkgewogICAgdGhpcy5kYXRhID0gZGF0YTsKICAgIHRoaXMuc3RhcnQgPSBzdGFydDsKICAgIHRoaXMuZW5kID0gZW5kOwogIH0KICBnZXQgZGVjb2RlcigpIHsKICAgIGNvbnN0IGRlY29kZXIgPSBuZXcgQXJpdGhtZXRpY0RlY29kZXIodGhpcy5kYXRhLCB0aGlzLnN0YXJ0LCB0aGlzLmVuZCk7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJkZWNvZGVyIiwgZGVjb2Rlcik7CiAgfQogIGdldCBjb250ZXh0Q2FjaGUoKSB7CiAgICBjb25zdCBjYWNoZSA9IG5ldyBDb250ZXh0Q2FjaGUoKTsKICAgIHJldHVybiBzaGFkb3codGhpcywgImNvbnRleHRDYWNoZSIsIGNhY2hlKTsKICB9Cn0KZnVuY3Rpb24gZGVjb2RlSW50ZWdlcihjb250ZXh0Q2FjaGUsIHByb2NlZHVyZSwgZGVjb2RlcikgewogIGNvbnN0IGNvbnRleHRzID0gY29udGV4dENhY2hlLmdldENvbnRleHRzKHByb2NlZHVyZSk7CiAgbGV0IHByZXYgPSAxOwogIGZ1bmN0aW9uIHJlYWRCaXRzKGxlbmd0aCkgewogICAgbGV0IHYgPSAwOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICBjb25zdCBiaXQgPSBkZWNvZGVyLnJlYWRCaXQoY29udGV4dHMsIHByZXYpOwogICAgICBwcmV2ID0gcHJldiA8IDI1NiA/IHByZXYgPDwgMSB8IGJpdCA6IChwcmV2IDw8IDEgfCBiaXQpICYgNTExIHwgMjU2OwogICAgICB2ID0gdiA8PCAxIHwgYml0OwogICAgfQogICAgcmV0dXJuIHYgPj4+IDA7CiAgfQogIGNvbnN0IHNpZ24gPSByZWFkQml0cygxKTsKICBjb25zdCB2YWx1ZSA9IHJlYWRCaXRzKDEpID8gcmVhZEJpdHMoMSkgPyByZWFkQml0cygxKSA/IHJlYWRCaXRzKDEpID8gcmVhZEJpdHMoMSkgPyByZWFkQml0cygzMikgKyA0NDM2IDogcmVhZEJpdHMoMTIpICsgMzQwIDogcmVhZEJpdHMoOCkgKyA4NCA6IHJlYWRCaXRzKDYpICsgMjAgOiByZWFkQml0cyg0KSArIDQgOiByZWFkQml0cygyKTsKICBsZXQgc2lnbmVkVmFsdWU7CiAgaWYgKHNpZ24gPT09IDApIHsKICAgIHNpZ25lZFZhbHVlID0gdmFsdWU7CiAgfSBlbHNlIGlmICh2YWx1ZSA+IDApIHsKICAgIHNpZ25lZFZhbHVlID0gLXZhbHVlOwogIH0KICBpZiAoc2lnbmVkVmFsdWUgPj0gTUlOX0lOVF8zMiAmJiBzaWduZWRWYWx1ZSA8PSBNQVhfSU5UXzMyKSB7CiAgICByZXR1cm4gc2lnbmVkVmFsdWU7CiAgfQogIHJldHVybiBudWxsOwp9CmZ1bmN0aW9uIGRlY29kZUlBSUQoY29udGV4dENhY2hlLCBkZWNvZGVyLCBjb2RlTGVuZ3RoKSB7CiAgY29uc3QgY29udGV4dHMgPSBjb250ZXh0Q2FjaGUuZ2V0Q29udGV4dHMoIklBSUQiKTsKICBsZXQgcHJldiA9IDE7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb2RlTGVuZ3RoOyBpKyspIHsKICAgIGNvbnN0IGJpdCA9IGRlY29kZXIucmVhZEJpdChjb250ZXh0cywgcHJldik7CiAgICBwcmV2ID0gcHJldiA8PCAxIHwgYml0OwogIH0KICBpZiAoY29kZUxlbmd0aCA8IDMxKSB7CiAgICByZXR1cm4gcHJldiAmICgxIDw8IGNvZGVMZW5ndGgpIC0gMTsKICB9CiAgcmV0dXJuIHByZXYgJiAweDdmZmZmZmZmOwp9CmNvbnN0IFNlZ21lbnRUeXBlcyA9IFsiU3ltYm9sRGljdGlvbmFyeSIsIG51bGwsIG51bGwsIG51bGwsICJJbnRlcm1lZGlhdGVUZXh0UmVnaW9uIiwgbnVsbCwgIkltbWVkaWF0ZVRleHRSZWdpb24iLCAiSW1tZWRpYXRlTG9zc2xlc3NUZXh0UmVnaW9uIiwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgIlBhdHRlcm5EaWN0aW9uYXJ5IiwgbnVsbCwgbnVsbCwgbnVsbCwgIkludGVybWVkaWF0ZUhhbGZ0b25lUmVnaW9uIiwgbnVsbCwgIkltbWVkaWF0ZUhhbGZ0b25lUmVnaW9uIiwgIkltbWVkaWF0ZUxvc3NsZXNzSGFsZnRvbmVSZWdpb24iLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCBudWxsLCAiSW50ZXJtZWRpYXRlR2VuZXJpY1JlZ2lvbiIsIG51bGwsICJJbW1lZGlhdGVHZW5lcmljUmVnaW9uIiwgIkltbWVkaWF0ZUxvc3NsZXNzR2VuZXJpY1JlZ2lvbiIsICJJbnRlcm1lZGlhdGVHZW5lcmljUmVmaW5lbWVudFJlZ2lvbiIsIG51bGwsICJJbW1lZGlhdGVHZW5lcmljUmVmaW5lbWVudFJlZ2lvbiIsICJJbW1lZGlhdGVMb3NzbGVzc0dlbmVyaWNSZWZpbmVtZW50UmVnaW9uIiwgbnVsbCwgbnVsbCwgbnVsbCwgbnVsbCwgIlBhZ2VJbmZvcm1hdGlvbiIsICJFbmRPZlBhZ2UiLCAiRW5kT2ZTdHJpcGUiLCAiRW5kT2ZGaWxlIiwgIlByb2ZpbGVzIiwgIlRhYmxlcyIsIG51bGwsIG51bGwsIG51bGwsIG51bGwsIG51bGwsIG51bGwsIG51bGwsIG51bGwsICJFeHRlbnNpb24iXTsKY29uc3QgQ29kaW5nVGVtcGxhdGVzID0gW1t7CiAgeDogLTEsCiAgeTogLTIKfSwgewogIHg6IDAsCiAgeTogLTIKfSwgewogIHg6IDEsCiAgeTogLTIKfSwgewogIHg6IC0yLAogIHk6IC0xCn0sIHsKICB4OiAtMSwKICB5OiAtMQp9LCB7CiAgeDogMCwKICB5OiAtMQp9LCB7CiAgeDogMSwKICB5OiAtMQp9LCB7CiAgeDogMiwKICB5OiAtMQp9LCB7CiAgeDogLTQsCiAgeTogMAp9LCB7CiAgeDogLTMsCiAgeTogMAp9LCB7CiAgeDogLTIsCiAgeTogMAp9LCB7CiAgeDogLTEsCiAgeTogMAp9XSwgW3sKICB4OiAtMSwKICB5OiAtMgp9LCB7CiAgeDogMCwKICB5OiAtMgp9LCB7CiAgeDogMSwKICB5OiAtMgp9LCB7CiAgeDogMiwKICB5OiAtMgp9LCB7CiAgeDogLTIsCiAgeTogLTEKfSwgewogIHg6IC0xLAogIHk6IC0xCn0sIHsKICB4OiAwLAogIHk6IC0xCn0sIHsKICB4OiAxLAogIHk6IC0xCn0sIHsKICB4OiAyLAogIHk6IC0xCn0sIHsKICB4OiAtMywKICB5OiAwCn0sIHsKICB4OiAtMiwKICB5OiAwCn0sIHsKICB4OiAtMSwKICB5OiAwCn1dLCBbewogIHg6IC0xLAogIHk6IC0yCn0sIHsKICB4OiAwLAogIHk6IC0yCn0sIHsKICB4OiAxLAogIHk6IC0yCn0sIHsKICB4OiAtMiwKICB5OiAtMQp9LCB7CiAgeDogLTEsCiAgeTogLTEKfSwgewogIHg6IDAsCiAgeTogLTEKfSwgewogIHg6IDEsCiAgeTogLTEKfSwgewogIHg6IC0yLAogIHk6IDAKfSwgewogIHg6IC0xLAogIHk6IDAKfV0sIFt7CiAgeDogLTMsCiAgeTogLTEKfSwgewogIHg6IC0yLAogIHk6IC0xCn0sIHsKICB4OiAtMSwKICB5OiAtMQp9LCB7CiAgeDogMCwKICB5OiAtMQp9LCB7CiAgeDogMSwKICB5OiAtMQp9LCB7CiAgeDogLTQsCiAgeTogMAp9LCB7CiAgeDogLTMsCiAgeTogMAp9LCB7CiAgeDogLTIsCiAgeTogMAp9LCB7CiAgeDogLTEsCiAgeTogMAp9XV07CmNvbnN0IFJlZmluZW1lbnRUZW1wbGF0ZXMgPSBbewogIGNvZGluZzogW3sKICAgIHg6IDAsCiAgICB5OiAtMQogIH0sIHsKICAgIHg6IDEsCiAgICB5OiAtMQogIH0sIHsKICAgIHg6IC0xLAogICAgeTogMAogIH1dLAogIHJlZmVyZW5jZTogW3sKICAgIHg6IDAsCiAgICB5OiAtMQogIH0sIHsKICAgIHg6IDEsCiAgICB5OiAtMQogIH0sIHsKICAgIHg6IC0xLAogICAgeTogMAogIH0sIHsKICAgIHg6IDAsCiAgICB5OiAwCiAgfSwgewogICAgeDogMSwKICAgIHk6IDAKICB9LCB7CiAgICB4OiAtMSwKICAgIHk6IDEKICB9LCB7CiAgICB4OiAwLAogICAgeTogMQogIH0sIHsKICAgIHg6IDEsCiAgICB5OiAxCiAgfV0KfSwgewogIGNvZGluZzogW3sKICAgIHg6IC0xLAogICAgeTogLTEKICB9LCB7CiAgICB4OiAwLAogICAgeTogLTEKICB9LCB7CiAgICB4OiAxLAogICAgeTogLTEKICB9LCB7CiAgICB4OiAtMSwKICAgIHk6IDAKICB9XSwKICByZWZlcmVuY2U6IFt7CiAgICB4OiAwLAogICAgeTogLTEKICB9LCB7CiAgICB4OiAtMSwKICAgIHk6IDAKICB9LCB7CiAgICB4OiAwLAogICAgeTogMAogIH0sIHsKICAgIHg6IDEsCiAgICB5OiAwCiAgfSwgewogICAgeDogMCwKICAgIHk6IDEKICB9LCB7CiAgICB4OiAxLAogICAgeTogMQogIH1dCn1dOwpjb25zdCBSZXVzZWRDb250ZXh0cyA9IFsweDliMjUsIDB4MDc5NSwgMHgwMGU1LCAweDAxOTVdOwpjb25zdCBSZWZpbmVtZW50UmV1c2VkQ29udGV4dHMgPSBbMHgwMDIwLCAweDAwMDhdOwpmdW5jdGlvbiBkZWNvZGVCaXRtYXBUZW1wbGF0ZTAod2lkdGgsIGhlaWdodCwgZGVjb2RpbmdDb250ZXh0KSB7CiAgY29uc3QgZGVjb2RlciA9IGRlY29kaW5nQ29udGV4dC5kZWNvZGVyOwogIGNvbnN0IGNvbnRleHRzID0gZGVjb2RpbmdDb250ZXh0LmNvbnRleHRDYWNoZS5nZXRDb250ZXh0cygiR0IiKTsKICBjb25zdCBiaXRtYXAgPSBbXTsKICBsZXQgY29udGV4dExhYmVsLCBpLCBqLCBwaXhlbCwgcm93LCByb3cxLCByb3cyOwogIGNvbnN0IE9MRF9QSVhFTF9NQVNLID0gMHg3YmY3OwogIGZvciAoaSA9IDA7IGkgPCBoZWlnaHQ7IGkrKykgewogICAgcm93ID0gYml0bWFwW2ldID0gbmV3IFVpbnQ4QXJyYXkod2lkdGgpOwogICAgcm93MSA9IGkgPCAxID8gcm93IDogYml0bWFwW2kgLSAxXTsKICAgIHJvdzIgPSBpIDwgMiA/IHJvdyA6IGJpdG1hcFtpIC0gMl07CiAgICBjb250ZXh0TGFiZWwgPSByb3cyWzBdIDw8IDEzIHwgcm93MlsxXSA8PCAxMiB8IHJvdzJbMl0gPDwgMTEgfCByb3cxWzBdIDw8IDcgfCByb3cxWzFdIDw8IDYgfCByb3cxWzJdIDw8IDUgfCByb3cxWzNdIDw8IDQ7CiAgICBmb3IgKGogPSAwOyBqIDwgd2lkdGg7IGorKykgewogICAgICByb3dbal0gPSBwaXhlbCA9IGRlY29kZXIucmVhZEJpdChjb250ZXh0cywgY29udGV4dExhYmVsKTsKICAgICAgY29udGV4dExhYmVsID0gKGNvbnRleHRMYWJlbCAmIE9MRF9QSVhFTF9NQVNLKSA8PCAxIHwgKGogKyAzIDwgd2lkdGggPyByb3cyW2ogKyAzXSA8PCAxMSA6IDApIHwgKGogKyA0IDwgd2lkdGggPyByb3cxW2ogKyA0XSA8PCA0IDogMCkgfCBwaXhlbDsKICAgIH0KICB9CiAgcmV0dXJuIGJpdG1hcDsKfQpmdW5jdGlvbiBkZWNvZGVCaXRtYXAobW1yLCB3aWR0aCwgaGVpZ2h0LCB0ZW1wbGF0ZUluZGV4LCBwcmVkaWN0aW9uLCBza2lwLCBhdCwgZGVjb2RpbmdDb250ZXh0KSB7CiAgaWYgKG1tcikgewogICAgY29uc3QgaW5wdXQgPSBuZXcgUmVhZGVyKGRlY29kaW5nQ29udGV4dC5kYXRhLCBkZWNvZGluZ0NvbnRleHQuc3RhcnQsIGRlY29kaW5nQ29udGV4dC5lbmQpOwogICAgcmV0dXJuIGRlY29kZU1NUkJpdG1hcChpbnB1dCwgd2lkdGgsIGhlaWdodCwgZmFsc2UpOwogIH0KICBpZiAodGVtcGxhdGVJbmRleCA9PT0gMCAmJiAhc2tpcCAmJiAhcHJlZGljdGlvbiAmJiBhdC5sZW5ndGggPT09IDQgJiYgYXRbMF0ueCA9PT0gMyAmJiBhdFswXS55ID09PSAtMSAmJiBhdFsxXS54ID09PSAtMyAmJiBhdFsxXS55ID09PSAtMSAmJiBhdFsyXS54ID09PSAyICYmIGF0WzJdLnkgPT09IC0yICYmIGF0WzNdLnggPT09IC0yICYmIGF0WzNdLnkgPT09IC0yKSB7CiAgICByZXR1cm4gZGVjb2RlQml0bWFwVGVtcGxhdGUwKHdpZHRoLCBoZWlnaHQsIGRlY29kaW5nQ29udGV4dCk7CiAgfQogIGNvbnN0IHVzZXNraXAgPSAhIXNraXA7CiAgY29uc3QgdGVtcGxhdGUgPSBDb2RpbmdUZW1wbGF0ZXNbdGVtcGxhdGVJbmRleF0uY29uY2F0KGF0KTsKICB0ZW1wbGF0ZS5zb3J0KChhLCBiKSA9PiBhLnkgLSBiLnkgfHwgYS54IC0gYi54KTsKICBjb25zdCB0ZW1wbGF0ZUxlbmd0aCA9IHRlbXBsYXRlLmxlbmd0aDsKICBjb25zdCB0ZW1wbGF0ZVggPSBuZXcgSW50OEFycmF5KHRlbXBsYXRlTGVuZ3RoKTsKICBjb25zdCB0ZW1wbGF0ZVkgPSBuZXcgSW50OEFycmF5KHRlbXBsYXRlTGVuZ3RoKTsKICBjb25zdCBjaGFuZ2luZ1RlbXBsYXRlRW50cmllcyA9IFtdOwogIGxldCByZXVzZU1hc2sgPSAwLAogICAgbWluWCA9IDAsCiAgICBtYXhYID0gMCwKICAgIG1pblkgPSAwOwogIGxldCBjLCBrOwogIGZvciAoayA9IDA7IGsgPCB0ZW1wbGF0ZUxlbmd0aDsgaysrKSB7CiAgICB0ZW1wbGF0ZVhba10gPSB0ZW1wbGF0ZVtrXS54OwogICAgdGVtcGxhdGVZW2tdID0gdGVtcGxhdGVba10ueTsKICAgIG1pblggPSBNYXRoLm1pbihtaW5YLCB0ZW1wbGF0ZVtrXS54KTsKICAgIG1heFggPSBNYXRoLm1heChtYXhYLCB0ZW1wbGF0ZVtrXS54KTsKICAgIG1pblkgPSBNYXRoLm1pbihtaW5ZLCB0ZW1wbGF0ZVtrXS55KTsKICAgIGlmIChrIDwgdGVtcGxhdGVMZW5ndGggLSAxICYmIHRlbXBsYXRlW2tdLnkgPT09IHRlbXBsYXRlW2sgKyAxXS55ICYmIHRlbXBsYXRlW2tdLnggPT09IHRlbXBsYXRlW2sgKyAxXS54IC0gMSkgewogICAgICByZXVzZU1hc2sgfD0gMSA8PCB0ZW1wbGF0ZUxlbmd0aCAtIDEgLSBrOwogICAgfSBlbHNlIHsKICAgICAgY2hhbmdpbmdUZW1wbGF0ZUVudHJpZXMucHVzaChrKTsKICAgIH0KICB9CiAgY29uc3QgY2hhbmdpbmdFbnRyaWVzTGVuZ3RoID0gY2hhbmdpbmdUZW1wbGF0ZUVudHJpZXMubGVuZ3RoOwogIGNvbnN0IGNoYW5naW5nVGVtcGxhdGVYID0gbmV3IEludDhBcnJheShjaGFuZ2luZ0VudHJpZXNMZW5ndGgpOwogIGNvbnN0IGNoYW5naW5nVGVtcGxhdGVZID0gbmV3IEludDhBcnJheShjaGFuZ2luZ0VudHJpZXNMZW5ndGgpOwogIGNvbnN0IGNoYW5naW5nVGVtcGxhdGVCaXQgPSBuZXcgVWludDE2QXJyYXkoY2hhbmdpbmdFbnRyaWVzTGVuZ3RoKTsKICBmb3IgKGMgPSAwOyBjIDwgY2hhbmdpbmdFbnRyaWVzTGVuZ3RoOyBjKyspIHsKICAgIGsgPSBjaGFuZ2luZ1RlbXBsYXRlRW50cmllc1tjXTsKICAgIGNoYW5naW5nVGVtcGxhdGVYW2NdID0gdGVtcGxhdGVba10ueDsKICAgIGNoYW5naW5nVGVtcGxhdGVZW2NdID0gdGVtcGxhdGVba10ueTsKICAgIGNoYW5naW5nVGVtcGxhdGVCaXRbY10gPSAxIDw8IHRlbXBsYXRlTGVuZ3RoIC0gMSAtIGs7CiAgfQogIGNvbnN0IHNiYl9sZWZ0ID0gLW1pblg7CiAgY29uc3Qgc2JiX3RvcCA9IC1taW5ZOwogIGNvbnN0IHNiYl9yaWdodCA9IHdpZHRoIC0gbWF4WDsKICBjb25zdCBwc2V1ZG9QaXhlbENvbnRleHQgPSBSZXVzZWRDb250ZXh0c1t0ZW1wbGF0ZUluZGV4XTsKICBsZXQgcm93ID0gbmV3IFVpbnQ4QXJyYXkod2lkdGgpOwogIGNvbnN0IGJpdG1hcCA9IFtdOwogIGNvbnN0IGRlY29kZXIgPSBkZWNvZGluZ0NvbnRleHQuZGVjb2RlcjsKICBjb25zdCBjb250ZXh0cyA9IGRlY29kaW5nQ29udGV4dC5jb250ZXh0Q2FjaGUuZ2V0Q29udGV4dHMoIkdCIik7CiAgbGV0IGx0cCA9IDAsCiAgICBqLAogICAgaTAsCiAgICBqMCwKICAgIGNvbnRleHRMYWJlbCA9IDAsCiAgICBiaXQsCiAgICBzaGlmdDsKICBmb3IgKGxldCBpID0gMDsgaSA8IGhlaWdodDsgaSsrKSB7CiAgICBpZiAocHJlZGljdGlvbikgewogICAgICBjb25zdCBzbHRwID0gZGVjb2Rlci5yZWFkQml0KGNvbnRleHRzLCBwc2V1ZG9QaXhlbENvbnRleHQpOwogICAgICBsdHAgXj0gc2x0cDsKICAgICAgaWYgKGx0cCkgewogICAgICAgIGJpdG1hcC5wdXNoKHJvdyk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgIH0KICAgIHJvdyA9IG5ldyBVaW50OEFycmF5KHJvdyk7CiAgICBiaXRtYXAucHVzaChyb3cpOwogICAgZm9yIChqID0gMDsgaiA8IHdpZHRoOyBqKyspIHsKICAgICAgaWYgKHVzZXNraXAgJiYgc2tpcFtpXVtqXSkgewogICAgICAgIHJvd1tqXSA9IDA7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKGogPj0gc2JiX2xlZnQgJiYgaiA8IHNiYl9yaWdodCAmJiBpID49IHNiYl90b3ApIHsKICAgICAgICBjb250ZXh0TGFiZWwgPSBjb250ZXh0TGFiZWwgPDwgMSAmIHJldXNlTWFzazsKICAgICAgICBmb3IgKGsgPSAwOyBrIDwgY2hhbmdpbmdFbnRyaWVzTGVuZ3RoOyBrKyspIHsKICAgICAgICAgIGkwID0gaSArIGNoYW5naW5nVGVtcGxhdGVZW2tdOwogICAgICAgICAgajAgPSBqICsgY2hhbmdpbmdUZW1wbGF0ZVhba107CiAgICAgICAgICBiaXQgPSBiaXRtYXBbaTBdW2owXTsKICAgICAgICAgIGlmIChiaXQpIHsKICAgICAgICAgICAgYml0ID0gY2hhbmdpbmdUZW1wbGF0ZUJpdFtrXTsKICAgICAgICAgICAgY29udGV4dExhYmVsIHw9IGJpdDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29udGV4dExhYmVsID0gMDsKICAgICAgICBzaGlmdCA9IHRlbXBsYXRlTGVuZ3RoIC0gMTsKICAgICAgICBmb3IgKGsgPSAwOyBrIDwgdGVtcGxhdGVMZW5ndGg7IGsrKywgc2hpZnQtLSkgewogICAgICAgICAgajAgPSBqICsgdGVtcGxhdGVYW2tdOwogICAgICAgICAgaWYgKGowID49IDAgJiYgajAgPCB3aWR0aCkgewogICAgICAgICAgICBpMCA9IGkgKyB0ZW1wbGF0ZVlba107CiAgICAgICAgICAgIGlmIChpMCA+PSAwKSB7CiAgICAgICAgICAgICAgYml0ID0gYml0bWFwW2kwXVtqMF07CiAgICAgICAgICAgICAgaWYgKGJpdCkgewogICAgICAgICAgICAgICAgY29udGV4dExhYmVsIHw9IGJpdCA8PCBzaGlmdDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgcGl4ZWwgPSBkZWNvZGVyLnJlYWRCaXQoY29udGV4dHMsIGNvbnRleHRMYWJlbCk7CiAgICAgIHJvd1tqXSA9IHBpeGVsOwogICAgfQogIH0KICByZXR1cm4gYml0bWFwOwp9CmZ1bmN0aW9uIGRlY29kZVJlZmluZW1lbnQod2lkdGgsIGhlaWdodCwgdGVtcGxhdGVJbmRleCwgcmVmZXJlbmNlQml0bWFwLCBvZmZzZXRYLCBvZmZzZXRZLCBwcmVkaWN0aW9uLCBhdCwgZGVjb2RpbmdDb250ZXh0KSB7CiAgbGV0IGNvZGluZ1RlbXBsYXRlID0gUmVmaW5lbWVudFRlbXBsYXRlc1t0ZW1wbGF0ZUluZGV4XS5jb2Rpbmc7CiAgaWYgKHRlbXBsYXRlSW5kZXggPT09IDApIHsKICAgIGNvZGluZ1RlbXBsYXRlID0gY29kaW5nVGVtcGxhdGUuY29uY2F0KFthdFswXV0pOwogIH0KICBjb25zdCBjb2RpbmdUZW1wbGF0ZUxlbmd0aCA9IGNvZGluZ1RlbXBsYXRlLmxlbmd0aDsKICBjb25zdCBjb2RpbmdUZW1wbGF0ZVggPSBuZXcgSW50MzJBcnJheShjb2RpbmdUZW1wbGF0ZUxlbmd0aCk7CiAgY29uc3QgY29kaW5nVGVtcGxhdGVZID0gbmV3IEludDMyQXJyYXkoY29kaW5nVGVtcGxhdGVMZW5ndGgpOwogIGxldCBrOwogIGZvciAoayA9IDA7IGsgPCBjb2RpbmdUZW1wbGF0ZUxlbmd0aDsgaysrKSB7CiAgICBjb2RpbmdUZW1wbGF0ZVhba10gPSBjb2RpbmdUZW1wbGF0ZVtrXS54OwogICAgY29kaW5nVGVtcGxhdGVZW2tdID0gY29kaW5nVGVtcGxhdGVba10ueTsKICB9CiAgbGV0IHJlZmVyZW5jZVRlbXBsYXRlID0gUmVmaW5lbWVudFRlbXBsYXRlc1t0ZW1wbGF0ZUluZGV4XS5yZWZlcmVuY2U7CiAgaWYgKHRlbXBsYXRlSW5kZXggPT09IDApIHsKICAgIHJlZmVyZW5jZVRlbXBsYXRlID0gcmVmZXJlbmNlVGVtcGxhdGUuY29uY2F0KFthdFsxXV0pOwogIH0KICBjb25zdCByZWZlcmVuY2VUZW1wbGF0ZUxlbmd0aCA9IHJlZmVyZW5jZVRlbXBsYXRlLmxlbmd0aDsKICBjb25zdCByZWZlcmVuY2VUZW1wbGF0ZVggPSBuZXcgSW50MzJBcnJheShyZWZlcmVuY2VUZW1wbGF0ZUxlbmd0aCk7CiAgY29uc3QgcmVmZXJlbmNlVGVtcGxhdGVZID0gbmV3IEludDMyQXJyYXkocmVmZXJlbmNlVGVtcGxhdGVMZW5ndGgpOwogIGZvciAoayA9IDA7IGsgPCByZWZlcmVuY2VUZW1wbGF0ZUxlbmd0aDsgaysrKSB7CiAgICByZWZlcmVuY2VUZW1wbGF0ZVhba10gPSByZWZlcmVuY2VUZW1wbGF0ZVtrXS54OwogICAgcmVmZXJlbmNlVGVtcGxhdGVZW2tdID0gcmVmZXJlbmNlVGVtcGxhdGVba10ueTsKICB9CiAgY29uc3QgcmVmZXJlbmNlV2lkdGggPSByZWZlcmVuY2VCaXRtYXBbMF0ubGVuZ3RoOwogIGNvbnN0IHJlZmVyZW5jZUhlaWdodCA9IHJlZmVyZW5jZUJpdG1hcC5sZW5ndGg7CiAgY29uc3QgcHNldWRvUGl4ZWxDb250ZXh0ID0gUmVmaW5lbWVudFJldXNlZENvbnRleHRzW3RlbXBsYXRlSW5kZXhdOwogIGNvbnN0IGJpdG1hcCA9IFtdOwogIGNvbnN0IGRlY29kZXIgPSBkZWNvZGluZ0NvbnRleHQuZGVjb2RlcjsKICBjb25zdCBjb250ZXh0cyA9IGRlY29kaW5nQ29udGV4dC5jb250ZXh0Q2FjaGUuZ2V0Q29udGV4dHMoIkdSIik7CiAgbGV0IGx0cCA9IDA7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCBoZWlnaHQ7IGkrKykgewogICAgaWYgKHByZWRpY3Rpb24pIHsKICAgICAgY29uc3Qgc2x0cCA9IGRlY29kZXIucmVhZEJpdChjb250ZXh0cywgcHNldWRvUGl4ZWxDb250ZXh0KTsKICAgICAgbHRwIF49IHNsdHA7CiAgICAgIGlmIChsdHApIHsKICAgICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigicHJlZGljdGlvbiBpcyBub3Qgc3VwcG9ydGVkIik7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHJvdyA9IG5ldyBVaW50OEFycmF5KHdpZHRoKTsKICAgIGJpdG1hcC5wdXNoKHJvdyk7CiAgICBmb3IgKGxldCBqID0gMDsgaiA8IHdpZHRoOyBqKyspIHsKICAgICAgbGV0IGkwLCBqMDsKICAgICAgbGV0IGNvbnRleHRMYWJlbCA9IDA7CiAgICAgIGZvciAoayA9IDA7IGsgPCBjb2RpbmdUZW1wbGF0ZUxlbmd0aDsgaysrKSB7CiAgICAgICAgaTAgPSBpICsgY29kaW5nVGVtcGxhdGVZW2tdOwogICAgICAgIGowID0gaiArIGNvZGluZ1RlbXBsYXRlWFtrXTsKICAgICAgICBpZiAoaTAgPCAwIHx8IGowIDwgMCB8fCBqMCA+PSB3aWR0aCkgewogICAgICAgICAgY29udGV4dExhYmVsIDw8PSAxOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb250ZXh0TGFiZWwgPSBjb250ZXh0TGFiZWwgPDwgMSB8IGJpdG1hcFtpMF1bajBdOwogICAgICAgIH0KICAgICAgfQogICAgICBmb3IgKGsgPSAwOyBrIDwgcmVmZXJlbmNlVGVtcGxhdGVMZW5ndGg7IGsrKykgewogICAgICAgIGkwID0gaSArIHJlZmVyZW5jZVRlbXBsYXRlWVtrXSAtIG9mZnNldFk7CiAgICAgICAgajAgPSBqICsgcmVmZXJlbmNlVGVtcGxhdGVYW2tdIC0gb2Zmc2V0WDsKICAgICAgICBpZiAoaTAgPCAwIHx8IGkwID49IHJlZmVyZW5jZUhlaWdodCB8fCBqMCA8IDAgfHwgajAgPj0gcmVmZXJlbmNlV2lkdGgpIHsKICAgICAgICAgIGNvbnRleHRMYWJlbCA8PD0gMTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29udGV4dExhYmVsID0gY29udGV4dExhYmVsIDw8IDEgfCByZWZlcmVuY2VCaXRtYXBbaTBdW2owXTsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgcGl4ZWwgPSBkZWNvZGVyLnJlYWRCaXQoY29udGV4dHMsIGNvbnRleHRMYWJlbCk7CiAgICAgIHJvd1tqXSA9IHBpeGVsOwogICAgfQogIH0KICByZXR1cm4gYml0bWFwOwp9CmZ1bmN0aW9uIGRlY29kZVN5bWJvbERpY3Rpb25hcnkoaHVmZm1hbiwgcmVmaW5lbWVudCwgc3ltYm9scywgbnVtYmVyT2ZOZXdTeW1ib2xzLCBudW1iZXJPZkV4cG9ydGVkU3ltYm9scywgaHVmZm1hblRhYmxlcywgdGVtcGxhdGVJbmRleCwgYXQsIHJlZmluZW1lbnRUZW1wbGF0ZUluZGV4LCByZWZpbmVtZW50QXQsIGRlY29kaW5nQ29udGV4dCwgaHVmZm1hbklucHV0KSB7CiAgaWYgKGh1ZmZtYW4gJiYgcmVmaW5lbWVudCkgewogICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoInN5bWJvbCByZWZpbmVtZW50IHdpdGggSHVmZm1hbiBpcyBub3Qgc3VwcG9ydGVkIik7CiAgfQogIGNvbnN0IG5ld1N5bWJvbHMgPSBbXTsKICBsZXQgY3VycmVudEhlaWdodCA9IDA7CiAgbGV0IHN5bWJvbENvZGVMZW5ndGggPSBsb2cyKHN5bWJvbHMubGVuZ3RoICsgbnVtYmVyT2ZOZXdTeW1ib2xzKTsKICBjb25zdCBkZWNvZGVyID0gZGVjb2RpbmdDb250ZXh0LmRlY29kZXI7CiAgY29uc3QgY29udGV4dENhY2hlID0gZGVjb2RpbmdDb250ZXh0LmNvbnRleHRDYWNoZTsKICBsZXQgdGFibGVCMSwgc3ltYm9sV2lkdGhzOwogIGlmIChodWZmbWFuKSB7CiAgICB0YWJsZUIxID0gZ2V0U3RhbmRhcmRUYWJsZSgxKTsKICAgIHN5bWJvbFdpZHRocyA9IFtdOwogICAgc3ltYm9sQ29kZUxlbmd0aCA9IE1hdGgubWF4KHN5bWJvbENvZGVMZW5ndGgsIDEpOwogIH0KICB3aGlsZSAobmV3U3ltYm9scy5sZW5ndGggPCBudW1iZXJPZk5ld1N5bWJvbHMpIHsKICAgIGNvbnN0IGRlbHRhSGVpZ2h0ID0gaHVmZm1hbiA/IGh1ZmZtYW5UYWJsZXMudGFibGVEZWx0YUhlaWdodC5kZWNvZGUoaHVmZm1hbklucHV0KSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFESCIsIGRlY29kZXIpOwogICAgY3VycmVudEhlaWdodCArPSBkZWx0YUhlaWdodDsKICAgIGxldCBjdXJyZW50V2lkdGggPSAwLAogICAgICB0b3RhbFdpZHRoID0gMDsKICAgIGNvbnN0IGZpcnN0U3ltYm9sID0gaHVmZm1hbiA/IHN5bWJvbFdpZHRocy5sZW5ndGggOiAwOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgY29uc3QgZGVsdGFXaWR0aCA9IGh1ZmZtYW4gPyBodWZmbWFuVGFibGVzLnRhYmxlRGVsdGFXaWR0aC5kZWNvZGUoaHVmZm1hbklucHV0KSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFEVyIsIGRlY29kZXIpOwogICAgICBpZiAoZGVsdGFXaWR0aCA9PT0gbnVsbCkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGN1cnJlbnRXaWR0aCArPSBkZWx0YVdpZHRoOwogICAgICB0b3RhbFdpZHRoICs9IGN1cnJlbnRXaWR0aDsKICAgICAgbGV0IGJpdG1hcDsKICAgICAgaWYgKHJlZmluZW1lbnQpIHsKICAgICAgICBjb25zdCBudW1iZXJPZkluc3RhbmNlcyA9IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFBSSIsIGRlY29kZXIpOwogICAgICAgIGlmIChudW1iZXJPZkluc3RhbmNlcyA+IDEpIHsKICAgICAgICAgIGJpdG1hcCA9IGRlY29kZVRleHRSZWdpb24oaHVmZm1hbiwgcmVmaW5lbWVudCwgY3VycmVudFdpZHRoLCBjdXJyZW50SGVpZ2h0LCAwLCBudW1iZXJPZkluc3RhbmNlcywgMSwgc3ltYm9scy5jb25jYXQobmV3U3ltYm9scyksIHN5bWJvbENvZGVMZW5ndGgsIDAsIDAsIDEsIDAsIGh1ZmZtYW5UYWJsZXMsIHJlZmluZW1lbnRUZW1wbGF0ZUluZGV4LCByZWZpbmVtZW50QXQsIGRlY29kaW5nQ29udGV4dCwgMCwgaHVmZm1hbklucHV0KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3Qgc3ltYm9sSWQgPSBkZWNvZGVJQUlEKGNvbnRleHRDYWNoZSwgZGVjb2Rlciwgc3ltYm9sQ29kZUxlbmd0aCk7CiAgICAgICAgICBjb25zdCByZHggPSBkZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBUkRYIiwgZGVjb2Rlcik7CiAgICAgICAgICBjb25zdCByZHkgPSBkZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBUkRZIiwgZGVjb2Rlcik7CiAgICAgICAgICBjb25zdCBzeW1ib2wgPSBzeW1ib2xJZCA8IHN5bWJvbHMubGVuZ3RoID8gc3ltYm9sc1tzeW1ib2xJZF0gOiBuZXdTeW1ib2xzW3N5bWJvbElkIC0gc3ltYm9scy5sZW5ndGhdOwogICAgICAgICAgYml0bWFwID0gZGVjb2RlUmVmaW5lbWVudChjdXJyZW50V2lkdGgsIGN1cnJlbnRIZWlnaHQsIHJlZmluZW1lbnRUZW1wbGF0ZUluZGV4LCBzeW1ib2wsIHJkeCwgcmR5LCBmYWxzZSwgcmVmaW5lbWVudEF0LCBkZWNvZGluZ0NvbnRleHQpOwogICAgICAgIH0KICAgICAgICBuZXdTeW1ib2xzLnB1c2goYml0bWFwKTsKICAgICAgfSBlbHNlIGlmIChodWZmbWFuKSB7CiAgICAgICAgc3ltYm9sV2lkdGhzLnB1c2goY3VycmVudFdpZHRoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBiaXRtYXAgPSBkZWNvZGVCaXRtYXAoZmFsc2UsIGN1cnJlbnRXaWR0aCwgY3VycmVudEhlaWdodCwgdGVtcGxhdGVJbmRleCwgZmFsc2UsIG51bGwsIGF0LCBkZWNvZGluZ0NvbnRleHQpOwogICAgICAgIG5ld1N5bWJvbHMucHVzaChiaXRtYXApOwogICAgICB9CiAgICB9CiAgICBpZiAoaHVmZm1hbiAmJiAhcmVmaW5lbWVudCkgewogICAgICBjb25zdCBiaXRtYXBTaXplID0gaHVmZm1hblRhYmxlcy50YWJsZUJpdG1hcFNpemUuZGVjb2RlKGh1ZmZtYW5JbnB1dCk7CiAgICAgIGh1ZmZtYW5JbnB1dC5ieXRlQWxpZ24oKTsKICAgICAgbGV0IGNvbGxlY3RpdmVCaXRtYXA7CiAgICAgIGlmIChiaXRtYXBTaXplID09PSAwKSB7CiAgICAgICAgY29sbGVjdGl2ZUJpdG1hcCA9IHJlYWRVbmNvbXByZXNzZWRCaXRtYXAoaHVmZm1hbklucHV0LCB0b3RhbFdpZHRoLCBjdXJyZW50SGVpZ2h0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBvcmlnaW5hbEVuZCA9IGh1ZmZtYW5JbnB1dC5lbmQ7CiAgICAgICAgY29uc3QgYml0bWFwRW5kID0gaHVmZm1hbklucHV0LnBvc2l0aW9uICsgYml0bWFwU2l6ZTsKICAgICAgICBodWZmbWFuSW5wdXQuZW5kID0gYml0bWFwRW5kOwogICAgICAgIGNvbGxlY3RpdmVCaXRtYXAgPSBkZWNvZGVNTVJCaXRtYXAoaHVmZm1hbklucHV0LCB0b3RhbFdpZHRoLCBjdXJyZW50SGVpZ2h0LCBmYWxzZSk7CiAgICAgICAgaHVmZm1hbklucHV0LmVuZCA9IG9yaWdpbmFsRW5kOwogICAgICAgIGh1ZmZtYW5JbnB1dC5wb3NpdGlvbiA9IGJpdG1hcEVuZDsKICAgICAgfQogICAgICBjb25zdCBudW1iZXJPZlN5bWJvbHNEZWNvZGVkID0gc3ltYm9sV2lkdGhzLmxlbmd0aDsKICAgICAgaWYgKGZpcnN0U3ltYm9sID09PSBudW1iZXJPZlN5bWJvbHNEZWNvZGVkIC0gMSkgewogICAgICAgIG5ld1N5bWJvbHMucHVzaChjb2xsZWN0aXZlQml0bWFwKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBsZXQgaSwKICAgICAgICAgIHksCiAgICAgICAgICB4TWluID0gMCwKICAgICAgICAgIHhNYXgsCiAgICAgICAgICBiaXRtYXBXaWR0aCwKICAgICAgICAgIHN5bWJvbEJpdG1hcDsKICAgICAgICBmb3IgKGkgPSBmaXJzdFN5bWJvbDsgaSA8IG51bWJlck9mU3ltYm9sc0RlY29kZWQ7IGkrKykgewogICAgICAgICAgYml0bWFwV2lkdGggPSBzeW1ib2xXaWR0aHNbaV07CiAgICAgICAgICB4TWF4ID0geE1pbiArIGJpdG1hcFdpZHRoOwogICAgICAgICAgc3ltYm9sQml0bWFwID0gW107CiAgICAgICAgICBmb3IgKHkgPSAwOyB5IDwgY3VycmVudEhlaWdodDsgeSsrKSB7CiAgICAgICAgICAgIHN5bWJvbEJpdG1hcC5wdXNoKGNvbGxlY3RpdmVCaXRtYXBbeV0uc3ViYXJyYXkoeE1pbiwgeE1heCkpOwogICAgICAgICAgfQogICAgICAgICAgbmV3U3ltYm9scy5wdXNoKHN5bWJvbEJpdG1hcCk7CiAgICAgICAgICB4TWluID0geE1heDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgY29uc3QgZXhwb3J0ZWRTeW1ib2xzID0gW10sCiAgICBmbGFncyA9IFtdOwogIGxldCBjdXJyZW50RmxhZyA9IGZhbHNlLAogICAgaSwKICAgIGlpOwogIGNvbnN0IHRvdGFsU3ltYm9sc0xlbmd0aCA9IHN5bWJvbHMubGVuZ3RoICsgbnVtYmVyT2ZOZXdTeW1ib2xzOwogIHdoaWxlIChmbGFncy5sZW5ndGggPCB0b3RhbFN5bWJvbHNMZW5ndGgpIHsKICAgIGxldCBydW5MZW5ndGggPSBodWZmbWFuID8gdGFibGVCMS5kZWNvZGUoaHVmZm1hbklucHV0KSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFFWCIsIGRlY29kZXIpOwogICAgd2hpbGUgKHJ1bkxlbmd0aC0tKSB7CiAgICAgIGZsYWdzLnB1c2goY3VycmVudEZsYWcpOwogICAgfQogICAgY3VycmVudEZsYWcgPSAhY3VycmVudEZsYWc7CiAgfQogIGZvciAoaSA9IDAsIGlpID0gc3ltYm9scy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBpZiAoZmxhZ3NbaV0pIHsKICAgICAgZXhwb3J0ZWRTeW1ib2xzLnB1c2goc3ltYm9sc1tpXSk7CiAgICB9CiAgfQogIGZvciAobGV0IGogPSAwOyBqIDwgbnVtYmVyT2ZOZXdTeW1ib2xzOyBpKyssIGorKykgewogICAgaWYgKGZsYWdzW2ldKSB7CiAgICAgIGV4cG9ydGVkU3ltYm9scy5wdXNoKG5ld1N5bWJvbHNbal0pOwogICAgfQogIH0KICByZXR1cm4gZXhwb3J0ZWRTeW1ib2xzOwp9CmZ1bmN0aW9uIGRlY29kZVRleHRSZWdpb24oaHVmZm1hbiwgcmVmaW5lbWVudCwgd2lkdGgsIGhlaWdodCwgZGVmYXVsdFBpeGVsVmFsdWUsIG51bWJlck9mU3ltYm9sSW5zdGFuY2VzLCBzdHJpcFNpemUsIGlucHV0U3ltYm9scywgc3ltYm9sQ29kZUxlbmd0aCwgdHJhbnNwb3NlZCwgZHNPZmZzZXQsIHJlZmVyZW5jZUNvcm5lciwgY29tYmluYXRpb25PcGVyYXRvciwgaHVmZm1hblRhYmxlcywgcmVmaW5lbWVudFRlbXBsYXRlSW5kZXgsIHJlZmluZW1lbnRBdCwgZGVjb2RpbmdDb250ZXh0LCBsb2dTdHJpcFNpemUsIGh1ZmZtYW5JbnB1dCkgewogIGlmIChodWZmbWFuICYmIHJlZmluZW1lbnQpIHsKICAgIHRocm93IG5ldyBKYmlnMkVycm9yKCJyZWZpbmVtZW50IHdpdGggSHVmZm1hbiBpcyBub3Qgc3VwcG9ydGVkIik7CiAgfQogIGNvbnN0IGJpdG1hcCA9IFtdOwogIGxldCBpLCByb3c7CiAgZm9yIChpID0gMDsgaSA8IGhlaWdodDsgaSsrKSB7CiAgICByb3cgPSBuZXcgVWludDhBcnJheSh3aWR0aCk7CiAgICBpZiAoZGVmYXVsdFBpeGVsVmFsdWUpIHsKICAgICAgcm93LmZpbGwoZGVmYXVsdFBpeGVsVmFsdWUpOwogICAgfQogICAgYml0bWFwLnB1c2gocm93KTsKICB9CiAgY29uc3QgZGVjb2RlciA9IGRlY29kaW5nQ29udGV4dC5kZWNvZGVyOwogIGNvbnN0IGNvbnRleHRDYWNoZSA9IGRlY29kaW5nQ29udGV4dC5jb250ZXh0Q2FjaGU7CiAgbGV0IHN0cmlwVCA9IGh1ZmZtYW4gPyAtaHVmZm1hblRhYmxlcy50YWJsZURlbHRhVC5kZWNvZGUoaHVmZm1hbklucHV0KSA6IC1kZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBRFQiLCBkZWNvZGVyKTsKICBsZXQgZmlyc3RTID0gMDsKICBpID0gMDsKICB3aGlsZSAoaSA8IG51bWJlck9mU3ltYm9sSW5zdGFuY2VzKSB7CiAgICBjb25zdCBkZWx0YVQgPSBodWZmbWFuID8gaHVmZm1hblRhYmxlcy50YWJsZURlbHRhVC5kZWNvZGUoaHVmZm1hbklucHV0KSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFEVCIsIGRlY29kZXIpOwogICAgc3RyaXBUICs9IGRlbHRhVDsKICAgIGNvbnN0IGRlbHRhRmlyc3RTID0gaHVmZm1hbiA/IGh1ZmZtYW5UYWJsZXMudGFibGVGaXJzdFMuZGVjb2RlKGh1ZmZtYW5JbnB1dCkgOiBkZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBRlMiLCBkZWNvZGVyKTsKICAgIGZpcnN0UyArPSBkZWx0YUZpcnN0UzsKICAgIGxldCBjdXJyZW50UyA9IGZpcnN0UzsKICAgIGRvIHsKICAgICAgbGV0IGN1cnJlbnRUID0gMDsKICAgICAgaWYgKHN0cmlwU2l6ZSA+IDEpIHsKICAgICAgICBjdXJyZW50VCA9IGh1ZmZtYW4gPyBodWZmbWFuSW5wdXQucmVhZEJpdHMobG9nU3RyaXBTaXplKSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFJVCIsIGRlY29kZXIpOwogICAgICB9CiAgICAgIGNvbnN0IHQgPSBzdHJpcFNpemUgKiBzdHJpcFQgKyBjdXJyZW50VDsKICAgICAgY29uc3Qgc3ltYm9sSWQgPSBodWZmbWFuID8gaHVmZm1hblRhYmxlcy5zeW1ib2xJRFRhYmxlLmRlY29kZShodWZmbWFuSW5wdXQpIDogZGVjb2RlSUFJRChjb250ZXh0Q2FjaGUsIGRlY29kZXIsIHN5bWJvbENvZGVMZW5ndGgpOwogICAgICBjb25zdCBhcHBseVJlZmluZW1lbnQgPSByZWZpbmVtZW50ICYmIChodWZmbWFuID8gaHVmZm1hbklucHV0LnJlYWRCaXQoKSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFSSSIsIGRlY29kZXIpKTsKICAgICAgbGV0IHN5bWJvbEJpdG1hcCA9IGlucHV0U3ltYm9sc1tzeW1ib2xJZF07CiAgICAgIGxldCBzeW1ib2xXaWR0aCA9IHN5bWJvbEJpdG1hcFswXS5sZW5ndGg7CiAgICAgIGxldCBzeW1ib2xIZWlnaHQgPSBzeW1ib2xCaXRtYXAubGVuZ3RoOwogICAgICBpZiAoYXBwbHlSZWZpbmVtZW50KSB7CiAgICAgICAgY29uc3QgcmR3ID0gZGVjb2RlSW50ZWdlcihjb250ZXh0Q2FjaGUsICJJQVJEVyIsIGRlY29kZXIpOwogICAgICAgIGNvbnN0IHJkaCA9IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFSREgiLCBkZWNvZGVyKTsKICAgICAgICBjb25zdCByZHggPSBkZWNvZGVJbnRlZ2VyKGNvbnRleHRDYWNoZSwgIklBUkRYIiwgZGVjb2Rlcik7CiAgICAgICAgY29uc3QgcmR5ID0gZGVjb2RlSW50ZWdlcihjb250ZXh0Q2FjaGUsICJJQVJEWSIsIGRlY29kZXIpOwogICAgICAgIHN5bWJvbFdpZHRoICs9IHJkdzsKICAgICAgICBzeW1ib2xIZWlnaHQgKz0gcmRoOwogICAgICAgIHN5bWJvbEJpdG1hcCA9IGRlY29kZVJlZmluZW1lbnQoc3ltYm9sV2lkdGgsIHN5bWJvbEhlaWdodCwgcmVmaW5lbWVudFRlbXBsYXRlSW5kZXgsIHN5bWJvbEJpdG1hcCwgKHJkdyA+PiAxKSArIHJkeCwgKHJkaCA+PiAxKSArIHJkeSwgZmFsc2UsIHJlZmluZW1lbnRBdCwgZGVjb2RpbmdDb250ZXh0KTsKICAgICAgfQogICAgICBsZXQgaW5jcmVtZW50ID0gMDsKICAgICAgaWYgKCF0cmFuc3Bvc2VkKSB7CiAgICAgICAgaWYgKHJlZmVyZW5jZUNvcm5lciA+IDEpIHsKICAgICAgICAgIGN1cnJlbnRTICs9IHN5bWJvbFdpZHRoIC0gMTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaW5jcmVtZW50ID0gc3ltYm9sV2lkdGggLSAxOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmICghKHJlZmVyZW5jZUNvcm5lciAmIDEpKSB7CiAgICAgICAgY3VycmVudFMgKz0gc3ltYm9sSGVpZ2h0IC0gMTsKICAgICAgfSBlbHNlIHsKICAgICAgICBpbmNyZW1lbnQgPSBzeW1ib2xIZWlnaHQgLSAxOwogICAgICB9CiAgICAgIGNvbnN0IG9mZnNldFQgPSB0IC0gKHJlZmVyZW5jZUNvcm5lciAmIDEgPyAwIDogc3ltYm9sSGVpZ2h0IC0gMSk7CiAgICAgIGNvbnN0IG9mZnNldFMgPSBjdXJyZW50UyAtIChyZWZlcmVuY2VDb3JuZXIgJiAyID8gc3ltYm9sV2lkdGggLSAxIDogMCk7CiAgICAgIGxldCBzMiwgdDIsIHN5bWJvbFJvdzsKICAgICAgaWYgKHRyYW5zcG9zZWQpIHsKICAgICAgICBmb3IgKHMyID0gMDsgczIgPCBzeW1ib2xIZWlnaHQ7IHMyKyspIHsKICAgICAgICAgIHJvdyA9IGJpdG1hcFtvZmZzZXRTICsgczJdOwogICAgICAgICAgaWYgKCFyb3cpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBzeW1ib2xSb3cgPSBzeW1ib2xCaXRtYXBbczJdOwogICAgICAgICAgY29uc3QgbWF4V2lkdGggPSBNYXRoLm1pbih3aWR0aCAtIG9mZnNldFQsIHN5bWJvbFdpZHRoKTsKICAgICAgICAgIHN3aXRjaCAoY29tYmluYXRpb25PcGVyYXRvcikgewogICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgZm9yICh0MiA9IDA7IHQyIDwgbWF4V2lkdGg7IHQyKyspIHsKICAgICAgICAgICAgICAgIHJvd1tvZmZzZXRUICsgdDJdIHw9IHN5bWJvbFJvd1t0Ml07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgZm9yICh0MiA9IDA7IHQyIDwgbWF4V2lkdGg7IHQyKyspIHsKICAgICAgICAgICAgICAgIHJvd1tvZmZzZXRUICsgdDJdIF49IHN5bWJvbFJvd1t0Ml07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgIHRocm93IG5ldyBKYmlnMkVycm9yKGBvcGVyYXRvciAke2NvbWJpbmF0aW9uT3BlcmF0b3J9IGlzIG5vdCBzdXBwb3J0ZWRgKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yICh0MiA9IDA7IHQyIDwgc3ltYm9sSGVpZ2h0OyB0MisrKSB7CiAgICAgICAgICByb3cgPSBiaXRtYXBbb2Zmc2V0VCArIHQyXTsKICAgICAgICAgIGlmICghcm93KSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgc3ltYm9sUm93ID0gc3ltYm9sQml0bWFwW3QyXTsKICAgICAgICAgIHN3aXRjaCAoY29tYmluYXRpb25PcGVyYXRvcikgewogICAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgICAgZm9yIChzMiA9IDA7IHMyIDwgc3ltYm9sV2lkdGg7IHMyKyspIHsKICAgICAgICAgICAgICAgIHJvd1tvZmZzZXRTICsgczJdIHw9IHN5bWJvbFJvd1tzMl07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgZm9yIChzMiA9IDA7IHMyIDwgc3ltYm9sV2lkdGg7IHMyKyspIHsKICAgICAgICAgICAgICAgIHJvd1tvZmZzZXRTICsgczJdIF49IHN5bWJvbFJvd1tzMl07CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgIHRocm93IG5ldyBKYmlnMkVycm9yKGBvcGVyYXRvciAke2NvbWJpbmF0aW9uT3BlcmF0b3J9IGlzIG5vdCBzdXBwb3J0ZWRgKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgaSsrOwogICAgICBjb25zdCBkZWx0YVMgPSBodWZmbWFuID8gaHVmZm1hblRhYmxlcy50YWJsZURlbHRhUy5kZWNvZGUoaHVmZm1hbklucHV0KSA6IGRlY29kZUludGVnZXIoY29udGV4dENhY2hlLCAiSUFEUyIsIGRlY29kZXIpOwogICAgICBpZiAoZGVsdGFTID09PSBudWxsKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY3VycmVudFMgKz0gaW5jcmVtZW50ICsgZGVsdGFTICsgZHNPZmZzZXQ7CiAgICB9IHdoaWxlICh0cnVlKTsKICB9CiAgcmV0dXJuIGJpdG1hcDsKfQpmdW5jdGlvbiBkZWNvZGVQYXR0ZXJuRGljdGlvbmFyeShtbXIsIHBhdHRlcm5XaWR0aCwgcGF0dGVybkhlaWdodCwgbWF4UGF0dGVybkluZGV4LCB0ZW1wbGF0ZSwgZGVjb2RpbmdDb250ZXh0KSB7CiAgY29uc3QgYXQgPSBbXTsKICBpZiAoIW1tcikgewogICAgYXQucHVzaCh7CiAgICAgIHg6IC1wYXR0ZXJuV2lkdGgsCiAgICAgIHk6IDAKICAgIH0pOwogICAgaWYgKHRlbXBsYXRlID09PSAwKSB7CiAgICAgIGF0LnB1c2goewogICAgICAgIHg6IC0zLAogICAgICAgIHk6IC0xCiAgICAgIH0sIHsKICAgICAgICB4OiAyLAogICAgICAgIHk6IC0yCiAgICAgIH0sIHsKICAgICAgICB4OiAtMiwKICAgICAgICB5OiAtMgogICAgICB9KTsKICAgIH0KICB9CiAgY29uc3QgY29sbGVjdGl2ZVdpZHRoID0gKG1heFBhdHRlcm5JbmRleCArIDEpICogcGF0dGVybldpZHRoOwogIGNvbnN0IGNvbGxlY3RpdmVCaXRtYXAgPSBkZWNvZGVCaXRtYXAobW1yLCBjb2xsZWN0aXZlV2lkdGgsIHBhdHRlcm5IZWlnaHQsIHRlbXBsYXRlLCBmYWxzZSwgbnVsbCwgYXQsIGRlY29kaW5nQ29udGV4dCk7CiAgY29uc3QgcGF0dGVybnMgPSBbXTsKICBmb3IgKGxldCBpID0gMDsgaSA8PSBtYXhQYXR0ZXJuSW5kZXg7IGkrKykgewogICAgY29uc3QgcGF0dGVybkJpdG1hcCA9IFtdOwogICAgY29uc3QgeE1pbiA9IHBhdHRlcm5XaWR0aCAqIGk7CiAgICBjb25zdCB4TWF4ID0geE1pbiArIHBhdHRlcm5XaWR0aDsKICAgIGZvciAobGV0IHkgPSAwOyB5IDwgcGF0dGVybkhlaWdodDsgeSsrKSB7CiAgICAgIHBhdHRlcm5CaXRtYXAucHVzaChjb2xsZWN0aXZlQml0bWFwW3ldLnN1YmFycmF5KHhNaW4sIHhNYXgpKTsKICAgIH0KICAgIHBhdHRlcm5zLnB1c2gocGF0dGVybkJpdG1hcCk7CiAgfQogIHJldHVybiBwYXR0ZXJuczsKfQpmdW5jdGlvbiBkZWNvZGVIYWxmdG9uZVJlZ2lvbihtbXIsIHBhdHRlcm5zLCB0ZW1wbGF0ZSwgcmVnaW9uV2lkdGgsIHJlZ2lvbkhlaWdodCwgZGVmYXVsdFBpeGVsVmFsdWUsIGVuYWJsZVNraXAsIGNvbWJpbmF0aW9uT3BlcmF0b3IsIGdyaWRXaWR0aCwgZ3JpZEhlaWdodCwgZ3JpZE9mZnNldFgsIGdyaWRPZmZzZXRZLCBncmlkVmVjdG9yWCwgZ3JpZFZlY3RvclksIGRlY29kaW5nQ29udGV4dCkgewogIGNvbnN0IHNraXAgPSBudWxsOwogIGlmIChlbmFibGVTa2lwKSB7CiAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigic2tpcCBpcyBub3Qgc3VwcG9ydGVkIik7CiAgfQogIGlmIChjb21iaW5hdGlvbk9wZXJhdG9yICE9PSAwKSB7CiAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcihgb3BlcmF0b3IgIiR7Y29tYmluYXRpb25PcGVyYXRvcn0iIGlzIG5vdCBzdXBwb3J0ZWQgaW4gaGFsZnRvbmUgcmVnaW9uYCk7CiAgfQogIGNvbnN0IHJlZ2lvbkJpdG1hcCA9IFtdOwogIGxldCBpLCBqLCByb3c7CiAgZm9yIChpID0gMDsgaSA8IHJlZ2lvbkhlaWdodDsgaSsrKSB7CiAgICByb3cgPSBuZXcgVWludDhBcnJheShyZWdpb25XaWR0aCk7CiAgICBpZiAoZGVmYXVsdFBpeGVsVmFsdWUpIHsKICAgICAgcm93LmZpbGwoZGVmYXVsdFBpeGVsVmFsdWUpOwogICAgfQogICAgcmVnaW9uQml0bWFwLnB1c2gocm93KTsKICB9CiAgY29uc3QgbnVtYmVyT2ZQYXR0ZXJucyA9IHBhdHRlcm5zLmxlbmd0aDsKICBjb25zdCBwYXR0ZXJuMCA9IHBhdHRlcm5zWzBdOwogIGNvbnN0IHBhdHRlcm5XaWR0aCA9IHBhdHRlcm4wWzBdLmxlbmd0aCwKICAgIHBhdHRlcm5IZWlnaHQgPSBwYXR0ZXJuMC5sZW5ndGg7CiAgY29uc3QgYml0c1BlclZhbHVlID0gbG9nMihudW1iZXJPZlBhdHRlcm5zKTsKICBjb25zdCBhdCA9IFtdOwogIGlmICghbW1yKSB7CiAgICBhdC5wdXNoKHsKICAgICAgeDogdGVtcGxhdGUgPD0gMSA/IDMgOiAyLAogICAgICB5OiAtMQogICAgfSk7CiAgICBpZiAodGVtcGxhdGUgPT09IDApIHsKICAgICAgYXQucHVzaCh7CiAgICAgICAgeDogLTMsCiAgICAgICAgeTogLTEKICAgICAgfSwgewogICAgICAgIHg6IDIsCiAgICAgICAgeTogLTIKICAgICAgfSwgewogICAgICAgIHg6IC0yLAogICAgICAgIHk6IC0yCiAgICAgIH0pOwogICAgfQogIH0KICBjb25zdCBncmF5U2NhbGVCaXRQbGFuZXMgPSBbXTsKICBsZXQgbW1ySW5wdXQsIGJpdG1hcDsKICBpZiAobW1yKSB7CiAgICBtbXJJbnB1dCA9IG5ldyBSZWFkZXIoZGVjb2RpbmdDb250ZXh0LmRhdGEsIGRlY29kaW5nQ29udGV4dC5zdGFydCwgZGVjb2RpbmdDb250ZXh0LmVuZCk7CiAgfQogIGZvciAoaSA9IGJpdHNQZXJWYWx1ZSAtIDE7IGkgPj0gMDsgaS0tKSB7CiAgICBpZiAobW1yKSB7CiAgICAgIGJpdG1hcCA9IGRlY29kZU1NUkJpdG1hcChtbXJJbnB1dCwgZ3JpZFdpZHRoLCBncmlkSGVpZ2h0LCB0cnVlKTsKICAgIH0gZWxzZSB7CiAgICAgIGJpdG1hcCA9IGRlY29kZUJpdG1hcChmYWxzZSwgZ3JpZFdpZHRoLCBncmlkSGVpZ2h0LCB0ZW1wbGF0ZSwgZmFsc2UsIHNraXAsIGF0LCBkZWNvZGluZ0NvbnRleHQpOwogICAgfQogICAgZ3JheVNjYWxlQml0UGxhbmVzW2ldID0gYml0bWFwOwogIH0KICBsZXQgbWcsIG5nLCBiaXQsIHBhdHRlcm5JbmRleCwgcGF0dGVybkJpdG1hcCwgeCwgeSwgcGF0dGVyblJvdywgcmVnaW9uUm93OwogIGZvciAobWcgPSAwOyBtZyA8IGdyaWRIZWlnaHQ7IG1nKyspIHsKICAgIGZvciAobmcgPSAwOyBuZyA8IGdyaWRXaWR0aDsgbmcrKykgewogICAgICBiaXQgPSAwOwogICAgICBwYXR0ZXJuSW5kZXggPSAwOwogICAgICBmb3IgKGogPSBiaXRzUGVyVmFsdWUgLSAxOyBqID49IDA7IGotLSkgewogICAgICAgIGJpdCBePSBncmF5U2NhbGVCaXRQbGFuZXNbal1bbWddW25nXTsKICAgICAgICBwYXR0ZXJuSW5kZXggfD0gYml0IDw8IGo7CiAgICAgIH0KICAgICAgcGF0dGVybkJpdG1hcCA9IHBhdHRlcm5zW3BhdHRlcm5JbmRleF07CiAgICAgIHggPSBncmlkT2Zmc2V0WCArIG1nICogZ3JpZFZlY3RvclkgKyBuZyAqIGdyaWRWZWN0b3JYID4+IDg7CiAgICAgIHkgPSBncmlkT2Zmc2V0WSArIG1nICogZ3JpZFZlY3RvclggLSBuZyAqIGdyaWRWZWN0b3JZID4+IDg7CiAgICAgIGlmICh4ID49IDAgJiYgeCArIHBhdHRlcm5XaWR0aCA8PSByZWdpb25XaWR0aCAmJiB5ID49IDAgJiYgeSArIHBhdHRlcm5IZWlnaHQgPD0gcmVnaW9uSGVpZ2h0KSB7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHBhdHRlcm5IZWlnaHQ7IGkrKykgewogICAgICAgICAgcmVnaW9uUm93ID0gcmVnaW9uQml0bWFwW3kgKyBpXTsKICAgICAgICAgIHBhdHRlcm5Sb3cgPSBwYXR0ZXJuQml0bWFwW2ldOwogICAgICAgICAgZm9yIChqID0gMDsgaiA8IHBhdHRlcm5XaWR0aDsgaisrKSB7CiAgICAgICAgICAgIHJlZ2lvblJvd1t4ICsgal0gfD0gcGF0dGVyblJvd1tqXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbGV0IHJlZ2lvblgsIHJlZ2lvblk7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHBhdHRlcm5IZWlnaHQ7IGkrKykgewogICAgICAgICAgcmVnaW9uWSA9IHkgKyBpOwogICAgICAgICAgaWYgKHJlZ2lvblkgPCAwIHx8IHJlZ2lvblkgPj0gcmVnaW9uSGVpZ2h0KSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgcmVnaW9uUm93ID0gcmVnaW9uQml0bWFwW3JlZ2lvblldOwogICAgICAgICAgcGF0dGVyblJvdyA9IHBhdHRlcm5CaXRtYXBbaV07CiAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgcGF0dGVybldpZHRoOyBqKyspIHsKICAgICAgICAgICAgcmVnaW9uWCA9IHggKyBqOwogICAgICAgICAgICBpZiAocmVnaW9uWCA+PSAwICYmIHJlZ2lvblggPCByZWdpb25XaWR0aCkgewogICAgICAgICAgICAgIHJlZ2lvblJvd1tyZWdpb25YXSB8PSBwYXR0ZXJuUm93W2pdOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQogIHJldHVybiByZWdpb25CaXRtYXA7Cn0KZnVuY3Rpb24gcmVhZFNlZ21lbnRIZWFkZXIoZGF0YSwgc3RhcnQpIHsKICBjb25zdCBzZWdtZW50SGVhZGVyID0ge307CiAgc2VnbWVudEhlYWRlci5udW1iZXIgPSByZWFkVWludDMyKGRhdGEsIHN0YXJ0KTsKICBjb25zdCBmbGFncyA9IGRhdGFbc3RhcnQgKyA0XTsKICBjb25zdCBzZWdtZW50VHlwZSA9IGZsYWdzICYgMHgzZjsKICBpZiAoIVNlZ21lbnRUeXBlc1tzZWdtZW50VHlwZV0pIHsKICAgIHRocm93IG5ldyBKYmlnMkVycm9yKCJpbnZhbGlkIHNlZ21lbnQgdHlwZTogIiArIHNlZ21lbnRUeXBlKTsKICB9CiAgc2VnbWVudEhlYWRlci50eXBlID0gc2VnbWVudFR5cGU7CiAgc2VnbWVudEhlYWRlci50eXBlTmFtZSA9IFNlZ21lbnRUeXBlc1tzZWdtZW50VHlwZV07CiAgc2VnbWVudEhlYWRlci5kZWZlcnJlZE5vblJldGFpbiA9ICEhKGZsYWdzICYgMHg4MCk7CiAgY29uc3QgcGFnZUFzc29jaWF0aW9uRmllbGRTaXplID0gISEoZmxhZ3MgJiAweDQwKTsKICBjb25zdCByZWZlcnJlZEZsYWdzID0gZGF0YVtzdGFydCArIDVdOwogIGxldCByZWZlcnJlZFRvQ291bnQgPSByZWZlcnJlZEZsYWdzID4+IDUgJiA3OwogIGNvbnN0IHJldGFpbkJpdHMgPSBbcmVmZXJyZWRGbGFncyAmIDMxXTsKICBsZXQgcG9zaXRpb24gPSBzdGFydCArIDY7CiAgaWYgKHJlZmVycmVkRmxhZ3MgPT09IDcpIHsKICAgIHJlZmVycmVkVG9Db3VudCA9IHJlYWRVaW50MzIoZGF0YSwgcG9zaXRpb24gLSAxKSAmIDB4MWZmZmZmZmY7CiAgICBwb3NpdGlvbiArPSAzOwogICAgbGV0IGJ5dGVzID0gcmVmZXJyZWRUb0NvdW50ICsgNyA+PiAzOwogICAgcmV0YWluQml0c1swXSA9IGRhdGFbcG9zaXRpb24rK107CiAgICB3aGlsZSAoLS1ieXRlcyA+IDApIHsKICAgICAgcmV0YWluQml0cy5wdXNoKGRhdGFbcG9zaXRpb24rK10pOwogICAgfQogIH0gZWxzZSBpZiAocmVmZXJyZWRGbGFncyA9PT0gNSB8fCByZWZlcnJlZEZsYWdzID09PSA2KSB7CiAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCByZWZlcnJlZC10byBmbGFncyIpOwogIH0KICBzZWdtZW50SGVhZGVyLnJldGFpbkJpdHMgPSByZXRhaW5CaXRzOwogIGxldCByZWZlcnJlZFRvU2VnbWVudE51bWJlclNpemUgPSA0OwogIGlmIChzZWdtZW50SGVhZGVyLm51bWJlciA8PSAyNTYpIHsKICAgIHJlZmVycmVkVG9TZWdtZW50TnVtYmVyU2l6ZSA9IDE7CiAgfSBlbHNlIGlmIChzZWdtZW50SGVhZGVyLm51bWJlciA8PSA2NTUzNikgewogICAgcmVmZXJyZWRUb1NlZ21lbnROdW1iZXJTaXplID0gMjsKICB9CiAgY29uc3QgcmVmZXJyZWRUbyA9IFtdOwogIGxldCBpLCBpaTsKICBmb3IgKGkgPSAwOyBpIDwgcmVmZXJyZWRUb0NvdW50OyBpKyspIHsKICAgIGxldCBudW1iZXI7CiAgICBpZiAocmVmZXJyZWRUb1NlZ21lbnROdW1iZXJTaXplID09PSAxKSB7CiAgICAgIG51bWJlciA9IGRhdGFbcG9zaXRpb25dOwogICAgfSBlbHNlIGlmIChyZWZlcnJlZFRvU2VnbWVudE51bWJlclNpemUgPT09IDIpIHsKICAgICAgbnVtYmVyID0gcmVhZFVpbnQxNihkYXRhLCBwb3NpdGlvbik7CiAgICB9IGVsc2UgewogICAgICBudW1iZXIgPSByZWFkVWludDMyKGRhdGEsIHBvc2l0aW9uKTsKICAgIH0KICAgIHJlZmVycmVkVG8ucHVzaChudW1iZXIpOwogICAgcG9zaXRpb24gKz0gcmVmZXJyZWRUb1NlZ21lbnROdW1iZXJTaXplOwogIH0KICBzZWdtZW50SGVhZGVyLnJlZmVycmVkVG8gPSByZWZlcnJlZFRvOwogIGlmICghcGFnZUFzc29jaWF0aW9uRmllbGRTaXplKSB7CiAgICBzZWdtZW50SGVhZGVyLnBhZ2VBc3NvY2lhdGlvbiA9IGRhdGFbcG9zaXRpb24rK107CiAgfSBlbHNlIHsKICAgIHNlZ21lbnRIZWFkZXIucGFnZUFzc29jaWF0aW9uID0gcmVhZFVpbnQzMihkYXRhLCBwb3NpdGlvbik7CiAgICBwb3NpdGlvbiArPSA0OwogIH0KICBzZWdtZW50SGVhZGVyLmxlbmd0aCA9IHJlYWRVaW50MzIoZGF0YSwgcG9zaXRpb24pOwogIHBvc2l0aW9uICs9IDQ7CiAgaWYgKHNlZ21lbnRIZWFkZXIubGVuZ3RoID09PSAweGZmZmZmZmZmKSB7CiAgICBpZiAoc2VnbWVudFR5cGUgPT09IDM4KSB7CiAgICAgIGNvbnN0IGdlbmVyaWNSZWdpb25JbmZvID0gcmVhZFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbihkYXRhLCBwb3NpdGlvbik7CiAgICAgIGNvbnN0IGdlbmVyaWNSZWdpb25TZWdtZW50RmxhZ3MgPSBkYXRhW3Bvc2l0aW9uICsgUmVnaW9uU2VnbWVudEluZm9ybWF0aW9uRmllbGRMZW5ndGhdOwogICAgICBjb25zdCBnZW5lcmljUmVnaW9uTW1yID0gISEoZ2VuZXJpY1JlZ2lvblNlZ21lbnRGbGFncyAmIDEpOwogICAgICBjb25zdCBzZWFyY2hQYXR0ZXJuTGVuZ3RoID0gNjsKICAgICAgY29uc3Qgc2VhcmNoUGF0dGVybiA9IG5ldyBVaW50OEFycmF5KHNlYXJjaFBhdHRlcm5MZW5ndGgpOwogICAgICBpZiAoIWdlbmVyaWNSZWdpb25NbXIpIHsKICAgICAgICBzZWFyY2hQYXR0ZXJuWzBdID0gMHhmZjsKICAgICAgICBzZWFyY2hQYXR0ZXJuWzFdID0gMHhhYzsKICAgICAgfQogICAgICBzZWFyY2hQYXR0ZXJuWzJdID0gZ2VuZXJpY1JlZ2lvbkluZm8uaGVpZ2h0ID4+PiAyNCAmIDB4ZmY7CiAgICAgIHNlYXJjaFBhdHRlcm5bM10gPSBnZW5lcmljUmVnaW9uSW5mby5oZWlnaHQgPj4gMTYgJiAweGZmOwogICAgICBzZWFyY2hQYXR0ZXJuWzRdID0gZ2VuZXJpY1JlZ2lvbkluZm8uaGVpZ2h0ID4+IDggJiAweGZmOwogICAgICBzZWFyY2hQYXR0ZXJuWzVdID0gZ2VuZXJpY1JlZ2lvbkluZm8uaGVpZ2h0ICYgMHhmZjsKICAgICAgZm9yIChpID0gcG9zaXRpb24sIGlpID0gZGF0YS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgbGV0IGogPSAwOwogICAgICAgIHdoaWxlIChqIDwgc2VhcmNoUGF0dGVybkxlbmd0aCAmJiBzZWFyY2hQYXR0ZXJuW2pdID09PSBkYXRhW2kgKyBqXSkgewogICAgICAgICAgaisrOwogICAgICAgIH0KICAgICAgICBpZiAoaiA9PT0gc2VhcmNoUGF0dGVybkxlbmd0aCkgewogICAgICAgICAgc2VnbWVudEhlYWRlci5sZW5ndGggPSBpICsgc2VhcmNoUGF0dGVybkxlbmd0aDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoc2VnbWVudEhlYWRlci5sZW5ndGggPT09IDB4ZmZmZmZmZmYpIHsKICAgICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigic2VnbWVudCBlbmQgd2FzIG5vdCBmb3VuZCIpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCB1bmtub3duIHNlZ21lbnQgbGVuZ3RoIik7CiAgICB9CiAgfQogIHNlZ21lbnRIZWFkZXIuaGVhZGVyRW5kID0gcG9zaXRpb247CiAgcmV0dXJuIHNlZ21lbnRIZWFkZXI7Cn0KZnVuY3Rpb24gcmVhZFNlZ21lbnRzKGhlYWRlciwgZGF0YSwgc3RhcnQsIGVuZCkgewogIGNvbnN0IHNlZ21lbnRzID0gW107CiAgbGV0IHBvc2l0aW9uID0gc3RhcnQ7CiAgd2hpbGUgKHBvc2l0aW9uIDwgZW5kKSB7CiAgICBjb25zdCBzZWdtZW50SGVhZGVyID0gcmVhZFNlZ21lbnRIZWFkZXIoZGF0YSwgcG9zaXRpb24pOwogICAgcG9zaXRpb24gPSBzZWdtZW50SGVhZGVyLmhlYWRlckVuZDsKICAgIGNvbnN0IHNlZ21lbnQgPSB7CiAgICAgIGhlYWRlcjogc2VnbWVudEhlYWRlciwKICAgICAgZGF0YQogICAgfTsKICAgIGlmICghaGVhZGVyLnJhbmRvbUFjY2VzcykgewogICAgICBzZWdtZW50LnN0YXJ0ID0gcG9zaXRpb247CiAgICAgIHBvc2l0aW9uICs9IHNlZ21lbnRIZWFkZXIubGVuZ3RoOwogICAgICBzZWdtZW50LmVuZCA9IHBvc2l0aW9uOwogICAgfQogICAgc2VnbWVudHMucHVzaChzZWdtZW50KTsKICAgIGlmIChzZWdtZW50SGVhZGVyLnR5cGUgPT09IDUxKSB7CiAgICAgIGJyZWFrOwogICAgfQogIH0KICBpZiAoaGVhZGVyLnJhbmRvbUFjY2VzcykgewogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gc2VnbWVudHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBzZWdtZW50c1tpXS5zdGFydCA9IHBvc2l0aW9uOwogICAgICBwb3NpdGlvbiArPSBzZWdtZW50c1tpXS5oZWFkZXIubGVuZ3RoOwogICAgICBzZWdtZW50c1tpXS5lbmQgPSBwb3NpdGlvbjsKICAgIH0KICB9CiAgcmV0dXJuIHNlZ21lbnRzOwp9CmZ1bmN0aW9uIHJlYWRSZWdpb25TZWdtZW50SW5mb3JtYXRpb24oZGF0YSwgc3RhcnQpIHsKICByZXR1cm4gewogICAgd2lkdGg6IHJlYWRVaW50MzIoZGF0YSwgc3RhcnQpLAogICAgaGVpZ2h0OiByZWFkVWludDMyKGRhdGEsIHN0YXJ0ICsgNCksCiAgICB4OiByZWFkVWludDMyKGRhdGEsIHN0YXJ0ICsgOCksCiAgICB5OiByZWFkVWludDMyKGRhdGEsIHN0YXJ0ICsgMTIpLAogICAgY29tYmluYXRpb25PcGVyYXRvcjogZGF0YVtzdGFydCArIDE2XSAmIDcKICB9Owp9CmNvbnN0IFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbkZpZWxkTGVuZ3RoID0gMTc7CmZ1bmN0aW9uIHByb2Nlc3NTZWdtZW50KHNlZ21lbnQsIHZpc2l0b3IpIHsKICBjb25zdCBoZWFkZXIgPSBzZWdtZW50LmhlYWRlcjsKICBjb25zdCBkYXRhID0gc2VnbWVudC5kYXRhLAogICAgZW5kID0gc2VnbWVudC5lbmQ7CiAgbGV0IHBvc2l0aW9uID0gc2VnbWVudC5zdGFydDsKICBsZXQgYXJncywgYXQsIGksIGF0TGVuZ3RoOwogIHN3aXRjaCAoaGVhZGVyLnR5cGUpIHsKICAgIGNhc2UgMDoKICAgICAgY29uc3QgZGljdGlvbmFyeSA9IHt9OwogICAgICBjb25zdCBkaWN0aW9uYXJ5RmxhZ3MgPSByZWFkVWludDE2KGRhdGEsIHBvc2l0aW9uKTsKICAgICAgZGljdGlvbmFyeS5odWZmbWFuID0gISEoZGljdGlvbmFyeUZsYWdzICYgMSk7CiAgICAgIGRpY3Rpb25hcnkucmVmaW5lbWVudCA9ICEhKGRpY3Rpb25hcnlGbGFncyAmIDIpOwogICAgICBkaWN0aW9uYXJ5Lmh1ZmZtYW5ESFNlbGVjdG9yID0gZGljdGlvbmFyeUZsYWdzID4+IDIgJiAzOwogICAgICBkaWN0aW9uYXJ5Lmh1ZmZtYW5EV1NlbGVjdG9yID0gZGljdGlvbmFyeUZsYWdzID4+IDQgJiAzOwogICAgICBkaWN0aW9uYXJ5LmJpdG1hcFNpemVTZWxlY3RvciA9IGRpY3Rpb25hcnlGbGFncyA+PiA2ICYgMTsKICAgICAgZGljdGlvbmFyeS5hZ2dyZWdhdGlvbkluc3RhbmNlc1NlbGVjdG9yID0gZGljdGlvbmFyeUZsYWdzID4+IDcgJiAxOwogICAgICBkaWN0aW9uYXJ5LmJpdG1hcENvZGluZ0NvbnRleHRVc2VkID0gISEoZGljdGlvbmFyeUZsYWdzICYgMjU2KTsKICAgICAgZGljdGlvbmFyeS5iaXRtYXBDb2RpbmdDb250ZXh0UmV0YWluZWQgPSAhIShkaWN0aW9uYXJ5RmxhZ3MgJiA1MTIpOwogICAgICBkaWN0aW9uYXJ5LnRlbXBsYXRlID0gZGljdGlvbmFyeUZsYWdzID4+IDEwICYgMzsKICAgICAgZGljdGlvbmFyeS5yZWZpbmVtZW50VGVtcGxhdGUgPSBkaWN0aW9uYXJ5RmxhZ3MgPj4gMTIgJiAxOwogICAgICBwb3NpdGlvbiArPSAyOwogICAgICBpZiAoIWRpY3Rpb25hcnkuaHVmZm1hbikgewogICAgICAgIGF0TGVuZ3RoID0gZGljdGlvbmFyeS50ZW1wbGF0ZSA9PT0gMCA/IDQgOiAxOwogICAgICAgIGF0ID0gW107CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGF0TGVuZ3RoOyBpKyspIHsKICAgICAgICAgIGF0LnB1c2goewogICAgICAgICAgICB4OiByZWFkSW50OChkYXRhLCBwb3NpdGlvbiksCiAgICAgICAgICAgIHk6IHJlYWRJbnQ4KGRhdGEsIHBvc2l0aW9uICsgMSkKICAgICAgICAgIH0pOwogICAgICAgICAgcG9zaXRpb24gKz0gMjsKICAgICAgICB9CiAgICAgICAgZGljdGlvbmFyeS5hdCA9IGF0OwogICAgICB9CiAgICAgIGlmIChkaWN0aW9uYXJ5LnJlZmluZW1lbnQgJiYgIWRpY3Rpb25hcnkucmVmaW5lbWVudFRlbXBsYXRlKSB7CiAgICAgICAgYXQgPSBbXTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMjsgaSsrKSB7CiAgICAgICAgICBhdC5wdXNoKHsKICAgICAgICAgICAgeDogcmVhZEludDgoZGF0YSwgcG9zaXRpb24pLAogICAgICAgICAgICB5OiByZWFkSW50OChkYXRhLCBwb3NpdGlvbiArIDEpCiAgICAgICAgICB9KTsKICAgICAgICAgIHBvc2l0aW9uICs9IDI7CiAgICAgICAgfQogICAgICAgIGRpY3Rpb25hcnkucmVmaW5lbWVudEF0ID0gYXQ7CiAgICAgIH0KICAgICAgZGljdGlvbmFyeS5udW1iZXJPZkV4cG9ydGVkU3ltYm9scyA9IHJlYWRVaW50MzIoZGF0YSwgcG9zaXRpb24pOwogICAgICBwb3NpdGlvbiArPSA0OwogICAgICBkaWN0aW9uYXJ5Lm51bWJlck9mTmV3U3ltYm9scyA9IHJlYWRVaW50MzIoZGF0YSwgcG9zaXRpb24pOwogICAgICBwb3NpdGlvbiArPSA0OwogICAgICBhcmdzID0gW2RpY3Rpb25hcnksIGhlYWRlci5udW1iZXIsIGhlYWRlci5yZWZlcnJlZFRvLCBkYXRhLCBwb3NpdGlvbiwgZW5kXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDY6CiAgICBjYXNlIDc6CiAgICAgIGNvbnN0IHRleHRSZWdpb24gPSB7fTsKICAgICAgdGV4dFJlZ2lvbi5pbmZvID0gcmVhZFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbihkYXRhLCBwb3NpdGlvbik7CiAgICAgIHBvc2l0aW9uICs9IFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbkZpZWxkTGVuZ3RoOwogICAgICBjb25zdCB0ZXh0UmVnaW9uU2VnbWVudEZsYWdzID0gcmVhZFVpbnQxNihkYXRhLCBwb3NpdGlvbik7CiAgICAgIHBvc2l0aW9uICs9IDI7CiAgICAgIHRleHRSZWdpb24uaHVmZm1hbiA9ICEhKHRleHRSZWdpb25TZWdtZW50RmxhZ3MgJiAxKTsKICAgICAgdGV4dFJlZ2lvbi5yZWZpbmVtZW50ID0gISEodGV4dFJlZ2lvblNlZ21lbnRGbGFncyAmIDIpOwogICAgICB0ZXh0UmVnaW9uLmxvZ1N0cmlwU2l6ZSA9IHRleHRSZWdpb25TZWdtZW50RmxhZ3MgPj4gMiAmIDM7CiAgICAgIHRleHRSZWdpb24uc3RyaXBTaXplID0gMSA8PCB0ZXh0UmVnaW9uLmxvZ1N0cmlwU2l6ZTsKICAgICAgdGV4dFJlZ2lvbi5yZWZlcmVuY2VDb3JuZXIgPSB0ZXh0UmVnaW9uU2VnbWVudEZsYWdzID4+IDQgJiAzOwogICAgICB0ZXh0UmVnaW9uLnRyYW5zcG9zZWQgPSAhISh0ZXh0UmVnaW9uU2VnbWVudEZsYWdzICYgNjQpOwogICAgICB0ZXh0UmVnaW9uLmNvbWJpbmF0aW9uT3BlcmF0b3IgPSB0ZXh0UmVnaW9uU2VnbWVudEZsYWdzID4+IDcgJiAzOwogICAgICB0ZXh0UmVnaW9uLmRlZmF1bHRQaXhlbFZhbHVlID0gdGV4dFJlZ2lvblNlZ21lbnRGbGFncyA+PiA5ICYgMTsKICAgICAgdGV4dFJlZ2lvbi5kc09mZnNldCA9IHRleHRSZWdpb25TZWdtZW50RmxhZ3MgPDwgMTcgPj4gMjc7CiAgICAgIHRleHRSZWdpb24ucmVmaW5lbWVudFRlbXBsYXRlID0gdGV4dFJlZ2lvblNlZ21lbnRGbGFncyA+PiAxNSAmIDE7CiAgICAgIGlmICh0ZXh0UmVnaW9uLmh1ZmZtYW4pIHsKICAgICAgICBjb25zdCB0ZXh0UmVnaW9uSHVmZm1hbkZsYWdzID0gcmVhZFVpbnQxNihkYXRhLCBwb3NpdGlvbik7CiAgICAgICAgcG9zaXRpb24gKz0gMjsKICAgICAgICB0ZXh0UmVnaW9uLmh1ZmZtYW5GUyA9IHRleHRSZWdpb25IdWZmbWFuRmxhZ3MgJiAzOwogICAgICAgIHRleHRSZWdpb24uaHVmZm1hbkRTID0gdGV4dFJlZ2lvbkh1ZmZtYW5GbGFncyA+PiAyICYgMzsKICAgICAgICB0ZXh0UmVnaW9uLmh1ZmZtYW5EVCA9IHRleHRSZWdpb25IdWZmbWFuRmxhZ3MgPj4gNCAmIDM7CiAgICAgICAgdGV4dFJlZ2lvbi5odWZmbWFuUmVmaW5lbWVudERXID0gdGV4dFJlZ2lvbkh1ZmZtYW5GbGFncyA+PiA2ICYgMzsKICAgICAgICB0ZXh0UmVnaW9uLmh1ZmZtYW5SZWZpbmVtZW50REggPSB0ZXh0UmVnaW9uSHVmZm1hbkZsYWdzID4+IDggJiAzOwogICAgICAgIHRleHRSZWdpb24uaHVmZm1hblJlZmluZW1lbnREWCA9IHRleHRSZWdpb25IdWZmbWFuRmxhZ3MgPj4gMTAgJiAzOwogICAgICAgIHRleHRSZWdpb24uaHVmZm1hblJlZmluZW1lbnREWSA9IHRleHRSZWdpb25IdWZmbWFuRmxhZ3MgPj4gMTIgJiAzOwogICAgICAgIHRleHRSZWdpb24uaHVmZm1hblJlZmluZW1lbnRTaXplU2VsZWN0b3IgPSAhISh0ZXh0UmVnaW9uSHVmZm1hbkZsYWdzICYgMHg0MDAwKTsKICAgICAgfQogICAgICBpZiAodGV4dFJlZ2lvbi5yZWZpbmVtZW50ICYmICF0ZXh0UmVnaW9uLnJlZmluZW1lbnRUZW1wbGF0ZSkgewogICAgICAgIGF0ID0gW107CiAgICAgICAgZm9yIChpID0gMDsgaSA8IDI7IGkrKykgewogICAgICAgICAgYXQucHVzaCh7CiAgICAgICAgICAgIHg6IHJlYWRJbnQ4KGRhdGEsIHBvc2l0aW9uKSwKICAgICAgICAgICAgeTogcmVhZEludDgoZGF0YSwgcG9zaXRpb24gKyAxKQogICAgICAgICAgfSk7CiAgICAgICAgICBwb3NpdGlvbiArPSAyOwogICAgICAgIH0KICAgICAgICB0ZXh0UmVnaW9uLnJlZmluZW1lbnRBdCA9IGF0OwogICAgICB9CiAgICAgIHRleHRSZWdpb24ubnVtYmVyT2ZTeW1ib2xJbnN0YW5jZXMgPSByZWFkVWludDMyKGRhdGEsIHBvc2l0aW9uKTsKICAgICAgcG9zaXRpb24gKz0gNDsKICAgICAgYXJncyA9IFt0ZXh0UmVnaW9uLCBoZWFkZXIucmVmZXJyZWRUbywgZGF0YSwgcG9zaXRpb24sIGVuZF07CiAgICAgIGJyZWFrOwogICAgY2FzZSAxNjoKICAgICAgY29uc3QgcGF0dGVybkRpY3Rpb25hcnkgPSB7fTsKICAgICAgY29uc3QgcGF0dGVybkRpY3Rpb25hcnlGbGFncyA9IGRhdGFbcG9zaXRpb24rK107CiAgICAgIHBhdHRlcm5EaWN0aW9uYXJ5Lm1tciA9ICEhKHBhdHRlcm5EaWN0aW9uYXJ5RmxhZ3MgJiAxKTsKICAgICAgcGF0dGVybkRpY3Rpb25hcnkudGVtcGxhdGUgPSBwYXR0ZXJuRGljdGlvbmFyeUZsYWdzID4+IDEgJiAzOwogICAgICBwYXR0ZXJuRGljdGlvbmFyeS5wYXR0ZXJuV2lkdGggPSBkYXRhW3Bvc2l0aW9uKytdOwogICAgICBwYXR0ZXJuRGljdGlvbmFyeS5wYXR0ZXJuSGVpZ2h0ID0gZGF0YVtwb3NpdGlvbisrXTsKICAgICAgcGF0dGVybkRpY3Rpb25hcnkubWF4UGF0dGVybkluZGV4ID0gcmVhZFVpbnQzMihkYXRhLCBwb3NpdGlvbik7CiAgICAgIHBvc2l0aW9uICs9IDQ7CiAgICAgIGFyZ3MgPSBbcGF0dGVybkRpY3Rpb25hcnksIGhlYWRlci5udW1iZXIsIGRhdGEsIHBvc2l0aW9uLCBlbmRdOwogICAgICBicmVhazsKICAgIGNhc2UgMjI6CiAgICBjYXNlIDIzOgogICAgICBjb25zdCBoYWxmdG9uZVJlZ2lvbiA9IHt9OwogICAgICBoYWxmdG9uZVJlZ2lvbi5pbmZvID0gcmVhZFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbihkYXRhLCBwb3NpdGlvbik7CiAgICAgIHBvc2l0aW9uICs9IFJlZ2lvblNlZ21lbnRJbmZvcm1hdGlvbkZpZWxkTGVuZ3RoOwogICAgICBjb25zdCBoYWxmdG9uZVJlZ2lvbkZsYWdzID0gZGF0YVtwb3NpdGlvbisrXTsKICAgICAgaGFsZnRvbmVSZWdpb24ubW1yID0gISEoaGFsZnRvbmVSZWdpb25GbGFncyAmIDEpOwogICAgICBoYWxmdG9uZVJlZ2lvbi50ZW1wbGF0ZSA9IGhhbGZ0b25lUmVnaW9uRmxhZ3MgPj4gMSAmIDM7CiAgICAgIGhhbGZ0b25lUmVnaW9uLmVuYWJsZVNraXAgPSAhIShoYWxmdG9uZVJlZ2lvbkZsYWdzICYgOCk7CiAgICAgIGhhbGZ0b25lUmVnaW9uLmNvbWJpbmF0aW9uT3BlcmF0b3IgPSBoYWxmdG9uZVJlZ2lvbkZsYWdzID4+IDQgJiA3OwogICAgICBoYWxmdG9uZVJlZ2lvbi5kZWZhdWx0UGl4ZWxWYWx1ZSA9IGhhbGZ0b25lUmVnaW9uRmxhZ3MgPj4gNyAmIDE7CiAgICAgIGhhbGZ0b25lUmVnaW9uLmdyaWRXaWR0aCA9IHJlYWRVaW50MzIoZGF0YSwgcG9zaXRpb24pOwogICAgICBwb3NpdGlvbiArPSA0OwogICAgICBoYWxmdG9uZVJlZ2lvbi5ncmlkSGVpZ2h0ID0gcmVhZFVpbnQzMihkYXRhLCBwb3NpdGlvbik7CiAgICAgIHBvc2l0aW9uICs9IDQ7CiAgICAgIGhhbGZ0b25lUmVnaW9uLmdyaWRPZmZzZXRYID0gcmVhZFVpbnQzMihkYXRhLCBwb3NpdGlvbikgJiAweGZmZmZmZmZmOwogICAgICBwb3NpdGlvbiArPSA0OwogICAgICBoYWxmdG9uZVJlZ2lvbi5ncmlkT2Zmc2V0WSA9IHJlYWRVaW50MzIoZGF0YSwgcG9zaXRpb24pICYgMHhmZmZmZmZmZjsKICAgICAgcG9zaXRpb24gKz0gNDsKICAgICAgaGFsZnRvbmVSZWdpb24uZ3JpZFZlY3RvclggPSByZWFkVWludDE2KGRhdGEsIHBvc2l0aW9uKTsKICAgICAgcG9zaXRpb24gKz0gMjsKICAgICAgaGFsZnRvbmVSZWdpb24uZ3JpZFZlY3RvclkgPSByZWFkVWludDE2KGRhdGEsIHBvc2l0aW9uKTsKICAgICAgcG9zaXRpb24gKz0gMjsKICAgICAgYXJncyA9IFtoYWxmdG9uZVJlZ2lvbiwgaGVhZGVyLnJlZmVycmVkVG8sIGRhdGEsIHBvc2l0aW9uLCBlbmRdOwogICAgICBicmVhazsKICAgIGNhc2UgMzg6CiAgICBjYXNlIDM5OgogICAgICBjb25zdCBnZW5lcmljUmVnaW9uID0ge307CiAgICAgIGdlbmVyaWNSZWdpb24uaW5mbyA9IHJlYWRSZWdpb25TZWdtZW50SW5mb3JtYXRpb24oZGF0YSwgcG9zaXRpb24pOwogICAgICBwb3NpdGlvbiArPSBSZWdpb25TZWdtZW50SW5mb3JtYXRpb25GaWVsZExlbmd0aDsKICAgICAgY29uc3QgZ2VuZXJpY1JlZ2lvblNlZ21lbnRGbGFncyA9IGRhdGFbcG9zaXRpb24rK107CiAgICAgIGdlbmVyaWNSZWdpb24ubW1yID0gISEoZ2VuZXJpY1JlZ2lvblNlZ21lbnRGbGFncyAmIDEpOwogICAgICBnZW5lcmljUmVnaW9uLnRlbXBsYXRlID0gZ2VuZXJpY1JlZ2lvblNlZ21lbnRGbGFncyA+PiAxICYgMzsKICAgICAgZ2VuZXJpY1JlZ2lvbi5wcmVkaWN0aW9uID0gISEoZ2VuZXJpY1JlZ2lvblNlZ21lbnRGbGFncyAmIDgpOwogICAgICBpZiAoIWdlbmVyaWNSZWdpb24ubW1yKSB7CiAgICAgICAgYXRMZW5ndGggPSBnZW5lcmljUmVnaW9uLnRlbXBsYXRlID09PSAwID8gNCA6IDE7CiAgICAgICAgYXQgPSBbXTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgYXRMZW5ndGg7IGkrKykgewogICAgICAgICAgYXQucHVzaCh7CiAgICAgICAgICAgIHg6IHJlYWRJbnQ4KGRhdGEsIHBvc2l0aW9uKSwKICAgICAgICAgICAgeTogcmVhZEludDgoZGF0YSwgcG9zaXRpb24gKyAxKQogICAgICAgICAgfSk7CiAgICAgICAgICBwb3NpdGlvbiArPSAyOwogICAgICAgIH0KICAgICAgICBnZW5lcmljUmVnaW9uLmF0ID0gYXQ7CiAgICAgIH0KICAgICAgYXJncyA9IFtnZW5lcmljUmVnaW9uLCBkYXRhLCBwb3NpdGlvbiwgZW5kXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDQ4OgogICAgICBjb25zdCBwYWdlSW5mbyA9IHsKICAgICAgICB3aWR0aDogcmVhZFVpbnQzMihkYXRhLCBwb3NpdGlvbiksCiAgICAgICAgaGVpZ2h0OiByZWFkVWludDMyKGRhdGEsIHBvc2l0aW9uICsgNCksCiAgICAgICAgcmVzb2x1dGlvblg6IHJlYWRVaW50MzIoZGF0YSwgcG9zaXRpb24gKyA4KSwKICAgICAgICByZXNvbHV0aW9uWTogcmVhZFVpbnQzMihkYXRhLCBwb3NpdGlvbiArIDEyKQogICAgICB9OwogICAgICBpZiAocGFnZUluZm8uaGVpZ2h0ID09PSAweGZmZmZmZmZmKSB7CiAgICAgICAgZGVsZXRlIHBhZ2VJbmZvLmhlaWdodDsKICAgICAgfQogICAgICBjb25zdCBwYWdlU2VnbWVudEZsYWdzID0gZGF0YVtwb3NpdGlvbiArIDE2XTsKICAgICAgcmVhZFVpbnQxNihkYXRhLCBwb3NpdGlvbiArIDE3KTsKICAgICAgcGFnZUluZm8ubG9zc2xlc3MgPSAhIShwYWdlU2VnbWVudEZsYWdzICYgMSk7CiAgICAgIHBhZ2VJbmZvLnJlZmluZW1lbnQgPSAhIShwYWdlU2VnbWVudEZsYWdzICYgMik7CiAgICAgIHBhZ2VJbmZvLmRlZmF1bHRQaXhlbFZhbHVlID0gcGFnZVNlZ21lbnRGbGFncyA+PiAyICYgMTsKICAgICAgcGFnZUluZm8uY29tYmluYXRpb25PcGVyYXRvciA9IHBhZ2VTZWdtZW50RmxhZ3MgPj4gMyAmIDM7CiAgICAgIHBhZ2VJbmZvLnJlcXVpcmVzQnVmZmVyID0gISEocGFnZVNlZ21lbnRGbGFncyAmIDMyKTsKICAgICAgcGFnZUluZm8uY29tYmluYXRpb25PcGVyYXRvck92ZXJyaWRlID0gISEocGFnZVNlZ21lbnRGbGFncyAmIDY0KTsKICAgICAgYXJncyA9IFtwYWdlSW5mb107CiAgICAgIGJyZWFrOwogICAgY2FzZSA0OToKICAgICAgYnJlYWs7CiAgICBjYXNlIDUwOgogICAgICBicmVhazsKICAgIGNhc2UgNTE6CiAgICAgIGJyZWFrOwogICAgY2FzZSA1MzoKICAgICAgYXJncyA9IFtoZWFkZXIubnVtYmVyLCBkYXRhLCBwb3NpdGlvbiwgZW5kXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDYyOgogICAgICBicmVhazsKICAgIGRlZmF1bHQ6CiAgICAgIHRocm93IG5ldyBKYmlnMkVycm9yKGBzZWdtZW50IHR5cGUgJHtoZWFkZXIudHlwZU5hbWV9KCR7aGVhZGVyLnR5cGV9KSBpcyBub3QgaW1wbGVtZW50ZWRgKTsKICB9CiAgY29uc3QgY2FsbGJhY2tOYW1lID0gIm9uIiArIGhlYWRlci50eXBlTmFtZTsKICBpZiAoY2FsbGJhY2tOYW1lIGluIHZpc2l0b3IpIHsKICAgIHZpc2l0b3JbY2FsbGJhY2tOYW1lXS5hcHBseSh2aXNpdG9yLCBhcmdzKTsKICB9Cn0KZnVuY3Rpb24gcHJvY2Vzc1NlZ21lbnRzKHNlZ21lbnRzLCB2aXNpdG9yKSB7CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gc2VnbWVudHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgcHJvY2Vzc1NlZ21lbnQoc2VnbWVudHNbaV0sIHZpc2l0b3IpOwogIH0KfQpmdW5jdGlvbiBwYXJzZUpiaWcyQ2h1bmtzKGNodW5rcykgewogIGNvbnN0IHZpc2l0b3IgPSBuZXcgU2ltcGxlU2VnbWVudFZpc2l0b3IoKTsKICBmb3IgKGxldCBpID0gMCwgaWkgPSBjaHVua3MubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgY29uc3QgY2h1bmsgPSBjaHVua3NbaV07CiAgICBjb25zdCBzZWdtZW50cyA9IHJlYWRTZWdtZW50cyh7fSwgY2h1bmsuZGF0YSwgY2h1bmsuc3RhcnQsIGNodW5rLmVuZCk7CiAgICBwcm9jZXNzU2VnbWVudHMoc2VnbWVudHMsIHZpc2l0b3IpOwogIH0KICByZXR1cm4gdmlzaXRvci5idWZmZXI7Cn0KY2xhc3MgU2ltcGxlU2VnbWVudFZpc2l0b3IgewogIG9uUGFnZUluZm9ybWF0aW9uKGluZm8pIHsKICAgIHRoaXMuY3VycmVudFBhZ2VJbmZvID0gaW5mbzsKICAgIGNvbnN0IHJvd1NpemUgPSBpbmZvLndpZHRoICsgNyA+PiAzOwogICAgY29uc3QgYnVmZmVyID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHJvd1NpemUgKiBpbmZvLmhlaWdodCk7CiAgICBpZiAoaW5mby5kZWZhdWx0UGl4ZWxWYWx1ZSkgewogICAgICBidWZmZXIuZmlsbCgweGZmKTsKICAgIH0KICAgIHRoaXMuYnVmZmVyID0gYnVmZmVyOwogIH0KICBkcmF3Qml0bWFwKHJlZ2lvbkluZm8sIGJpdG1hcCkgewogICAgY29uc3QgcGFnZUluZm8gPSB0aGlzLmN1cnJlbnRQYWdlSW5mbzsKICAgIGNvbnN0IHdpZHRoID0gcmVnaW9uSW5mby53aWR0aCwKICAgICAgaGVpZ2h0ID0gcmVnaW9uSW5mby5oZWlnaHQ7CiAgICBjb25zdCByb3dTaXplID0gcGFnZUluZm8ud2lkdGggKyA3ID4+IDM7CiAgICBjb25zdCBjb21iaW5hdGlvbk9wZXJhdG9yID0gcGFnZUluZm8uY29tYmluYXRpb25PcGVyYXRvck92ZXJyaWRlID8gcmVnaW9uSW5mby5jb21iaW5hdGlvbk9wZXJhdG9yIDogcGFnZUluZm8uY29tYmluYXRpb25PcGVyYXRvcjsKICAgIGNvbnN0IGJ1ZmZlciA9IHRoaXMuYnVmZmVyOwogICAgY29uc3QgbWFzazAgPSAxMjggPj4gKHJlZ2lvbkluZm8ueCAmIDcpOwogICAgbGV0IG9mZnNldDAgPSByZWdpb25JbmZvLnkgKiByb3dTaXplICsgKHJlZ2lvbkluZm8ueCA+PiAzKTsKICAgIGxldCBpLCBqLCBtYXNrLCBvZmZzZXQ7CiAgICBzd2l0Y2ggKGNvbWJpbmF0aW9uT3BlcmF0b3IpIHsKICAgICAgY2FzZSAwOgogICAgICAgIGZvciAoaSA9IDA7IGkgPCBoZWlnaHQ7IGkrKykgewogICAgICAgICAgbWFzayA9IG1hc2swOwogICAgICAgICAgb2Zmc2V0ID0gb2Zmc2V0MDsKICAgICAgICAgIGZvciAoaiA9IDA7IGogPCB3aWR0aDsgaisrKSB7CiAgICAgICAgICAgIGlmIChiaXRtYXBbaV1bal0pIHsKICAgICAgICAgICAgICBidWZmZXJbb2Zmc2V0XSB8PSBtYXNrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIG1hc2sgPj49IDE7CiAgICAgICAgICAgIGlmICghbWFzaykgewogICAgICAgICAgICAgIG1hc2sgPSAxMjg7CiAgICAgICAgICAgICAgb2Zmc2V0Kys7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIG9mZnNldDAgKz0gcm93U2l6ZTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMjoKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgaGVpZ2h0OyBpKyspIHsKICAgICAgICAgIG1hc2sgPSBtYXNrMDsKICAgICAgICAgIG9mZnNldCA9IG9mZnNldDA7CiAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgd2lkdGg7IGorKykgewogICAgICAgICAgICBpZiAoYml0bWFwW2ldW2pdKSB7CiAgICAgICAgICAgICAgYnVmZmVyW29mZnNldF0gXj0gbWFzazsKICAgICAgICAgICAgfQogICAgICAgICAgICBtYXNrID4+PSAxOwogICAgICAgICAgICBpZiAoIW1hc2spIHsKICAgICAgICAgICAgICBtYXNrID0gMTI4OwogICAgICAgICAgICAgIG9mZnNldCsrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBvZmZzZXQwICs9IHJvd1NpemU7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHRocm93IG5ldyBKYmlnMkVycm9yKGBvcGVyYXRvciAke2NvbWJpbmF0aW9uT3BlcmF0b3J9IGlzIG5vdCBzdXBwb3J0ZWRgKTsKICAgIH0KICB9CiAgb25JbW1lZGlhdGVHZW5lcmljUmVnaW9uKHJlZ2lvbiwgZGF0YSwgc3RhcnQsIGVuZCkgewogICAgY29uc3QgcmVnaW9uSW5mbyA9IHJlZ2lvbi5pbmZvOwogICAgY29uc3QgZGVjb2RpbmdDb250ZXh0ID0gbmV3IERlY29kaW5nQ29udGV4dChkYXRhLCBzdGFydCwgZW5kKTsKICAgIGNvbnN0IGJpdG1hcCA9IGRlY29kZUJpdG1hcChyZWdpb24ubW1yLCByZWdpb25JbmZvLndpZHRoLCByZWdpb25JbmZvLmhlaWdodCwgcmVnaW9uLnRlbXBsYXRlLCByZWdpb24ucHJlZGljdGlvbiwgbnVsbCwgcmVnaW9uLmF0LCBkZWNvZGluZ0NvbnRleHQpOwogICAgdGhpcy5kcmF3Qml0bWFwKHJlZ2lvbkluZm8sIGJpdG1hcCk7CiAgfQogIG9uSW1tZWRpYXRlTG9zc2xlc3NHZW5lcmljUmVnaW9uKCkgewogICAgdGhpcy5vbkltbWVkaWF0ZUdlbmVyaWNSZWdpb24oLi4uYXJndW1lbnRzKTsKICB9CiAgb25TeW1ib2xEaWN0aW9uYXJ5KGRpY3Rpb25hcnksIGN1cnJlbnRTZWdtZW50LCByZWZlcnJlZFNlZ21lbnRzLCBkYXRhLCBzdGFydCwgZW5kKSB7CiAgICBsZXQgaHVmZm1hblRhYmxlcywgaHVmZm1hbklucHV0OwogICAgaWYgKGRpY3Rpb25hcnkuaHVmZm1hbikgewogICAgICBodWZmbWFuVGFibGVzID0gZ2V0U3ltYm9sRGljdGlvbmFyeUh1ZmZtYW5UYWJsZXMoZGljdGlvbmFyeSwgcmVmZXJyZWRTZWdtZW50cywgdGhpcy5jdXN0b21UYWJsZXMpOwogICAgICBodWZmbWFuSW5wdXQgPSBuZXcgUmVhZGVyKGRhdGEsIHN0YXJ0LCBlbmQpOwogICAgfQogICAgbGV0IHN5bWJvbHMgPSB0aGlzLnN5bWJvbHM7CiAgICBpZiAoIXN5bWJvbHMpIHsKICAgICAgdGhpcy5zeW1ib2xzID0gc3ltYm9scyA9IHt9OwogICAgfQogICAgY29uc3QgaW5wdXRTeW1ib2xzID0gW107CiAgICBmb3IgKGNvbnN0IHJlZmVycmVkU2VnbWVudCBvZiByZWZlcnJlZFNlZ21lbnRzKSB7CiAgICAgIGNvbnN0IHJlZmVycmVkU3ltYm9scyA9IHN5bWJvbHNbcmVmZXJyZWRTZWdtZW50XTsKICAgICAgaWYgKHJlZmVycmVkU3ltYm9scykgewogICAgICAgIGlucHV0U3ltYm9scy5wdXNoKC4uLnJlZmVycmVkU3ltYm9scyk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGRlY29kaW5nQ29udGV4dCA9IG5ldyBEZWNvZGluZ0NvbnRleHQoZGF0YSwgc3RhcnQsIGVuZCk7CiAgICBzeW1ib2xzW2N1cnJlbnRTZWdtZW50XSA9IGRlY29kZVN5bWJvbERpY3Rpb25hcnkoZGljdGlvbmFyeS5odWZmbWFuLCBkaWN0aW9uYXJ5LnJlZmluZW1lbnQsIGlucHV0U3ltYm9scywgZGljdGlvbmFyeS5udW1iZXJPZk5ld1N5bWJvbHMsIGRpY3Rpb25hcnkubnVtYmVyT2ZFeHBvcnRlZFN5bWJvbHMsIGh1ZmZtYW5UYWJsZXMsIGRpY3Rpb25hcnkudGVtcGxhdGUsIGRpY3Rpb25hcnkuYXQsIGRpY3Rpb25hcnkucmVmaW5lbWVudFRlbXBsYXRlLCBkaWN0aW9uYXJ5LnJlZmluZW1lbnRBdCwgZGVjb2RpbmdDb250ZXh0LCBodWZmbWFuSW5wdXQpOwogIH0KICBvbkltbWVkaWF0ZVRleHRSZWdpb24ocmVnaW9uLCByZWZlcnJlZFNlZ21lbnRzLCBkYXRhLCBzdGFydCwgZW5kKSB7CiAgICBjb25zdCByZWdpb25JbmZvID0gcmVnaW9uLmluZm87CiAgICBsZXQgaHVmZm1hblRhYmxlcywgaHVmZm1hbklucHV0OwogICAgY29uc3Qgc3ltYm9scyA9IHRoaXMuc3ltYm9sczsKICAgIGNvbnN0IGlucHV0U3ltYm9scyA9IFtdOwogICAgZm9yIChjb25zdCByZWZlcnJlZFNlZ21lbnQgb2YgcmVmZXJyZWRTZWdtZW50cykgewogICAgICBjb25zdCByZWZlcnJlZFN5bWJvbHMgPSBzeW1ib2xzW3JlZmVycmVkU2VnbWVudF07CiAgICAgIGlmIChyZWZlcnJlZFN5bWJvbHMpIHsKICAgICAgICBpbnB1dFN5bWJvbHMucHVzaCguLi5yZWZlcnJlZFN5bWJvbHMpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBzeW1ib2xDb2RlTGVuZ3RoID0gbG9nMihpbnB1dFN5bWJvbHMubGVuZ3RoKTsKICAgIGlmIChyZWdpb24uaHVmZm1hbikgewogICAgICBodWZmbWFuSW5wdXQgPSBuZXcgUmVhZGVyKGRhdGEsIHN0YXJ0LCBlbmQpOwogICAgICBodWZmbWFuVGFibGVzID0gZ2V0VGV4dFJlZ2lvbkh1ZmZtYW5UYWJsZXMocmVnaW9uLCByZWZlcnJlZFNlZ21lbnRzLCB0aGlzLmN1c3RvbVRhYmxlcywgaW5wdXRTeW1ib2xzLmxlbmd0aCwgaHVmZm1hbklucHV0KTsKICAgIH0KICAgIGNvbnN0IGRlY29kaW5nQ29udGV4dCA9IG5ldyBEZWNvZGluZ0NvbnRleHQoZGF0YSwgc3RhcnQsIGVuZCk7CiAgICBjb25zdCBiaXRtYXAgPSBkZWNvZGVUZXh0UmVnaW9uKHJlZ2lvbi5odWZmbWFuLCByZWdpb24ucmVmaW5lbWVudCwgcmVnaW9uSW5mby53aWR0aCwgcmVnaW9uSW5mby5oZWlnaHQsIHJlZ2lvbi5kZWZhdWx0UGl4ZWxWYWx1ZSwgcmVnaW9uLm51bWJlck9mU3ltYm9sSW5zdGFuY2VzLCByZWdpb24uc3RyaXBTaXplLCBpbnB1dFN5bWJvbHMsIHN5bWJvbENvZGVMZW5ndGgsIHJlZ2lvbi50cmFuc3Bvc2VkLCByZWdpb24uZHNPZmZzZXQsIHJlZ2lvbi5yZWZlcmVuY2VDb3JuZXIsIHJlZ2lvbi5jb21iaW5hdGlvbk9wZXJhdG9yLCBodWZmbWFuVGFibGVzLCByZWdpb24ucmVmaW5lbWVudFRlbXBsYXRlLCByZWdpb24ucmVmaW5lbWVudEF0LCBkZWNvZGluZ0NvbnRleHQsIHJlZ2lvbi5sb2dTdHJpcFNpemUsIGh1ZmZtYW5JbnB1dCk7CiAgICB0aGlzLmRyYXdCaXRtYXAocmVnaW9uSW5mbywgYml0bWFwKTsKICB9CiAgb25JbW1lZGlhdGVMb3NzbGVzc1RleHRSZWdpb24oKSB7CiAgICB0aGlzLm9uSW1tZWRpYXRlVGV4dFJlZ2lvbiguLi5hcmd1bWVudHMpOwogIH0KICBvblBhdHRlcm5EaWN0aW9uYXJ5KGRpY3Rpb25hcnksIGN1cnJlbnRTZWdtZW50LCBkYXRhLCBzdGFydCwgZW5kKSB7CiAgICBsZXQgcGF0dGVybnMgPSB0aGlzLnBhdHRlcm5zOwogICAgaWYgKCFwYXR0ZXJucykgewogICAgICB0aGlzLnBhdHRlcm5zID0gcGF0dGVybnMgPSB7fTsKICAgIH0KICAgIGNvbnN0IGRlY29kaW5nQ29udGV4dCA9IG5ldyBEZWNvZGluZ0NvbnRleHQoZGF0YSwgc3RhcnQsIGVuZCk7CiAgICBwYXR0ZXJuc1tjdXJyZW50U2VnbWVudF0gPSBkZWNvZGVQYXR0ZXJuRGljdGlvbmFyeShkaWN0aW9uYXJ5Lm1tciwgZGljdGlvbmFyeS5wYXR0ZXJuV2lkdGgsIGRpY3Rpb25hcnkucGF0dGVybkhlaWdodCwgZGljdGlvbmFyeS5tYXhQYXR0ZXJuSW5kZXgsIGRpY3Rpb25hcnkudGVtcGxhdGUsIGRlY29kaW5nQ29udGV4dCk7CiAgfQogIG9uSW1tZWRpYXRlSGFsZnRvbmVSZWdpb24ocmVnaW9uLCByZWZlcnJlZFNlZ21lbnRzLCBkYXRhLCBzdGFydCwgZW5kKSB7CiAgICBjb25zdCBwYXR0ZXJucyA9IHRoaXMucGF0dGVybnNbcmVmZXJyZWRTZWdtZW50c1swXV07CiAgICBjb25zdCByZWdpb25JbmZvID0gcmVnaW9uLmluZm87CiAgICBjb25zdCBkZWNvZGluZ0NvbnRleHQgPSBuZXcgRGVjb2RpbmdDb250ZXh0KGRhdGEsIHN0YXJ0LCBlbmQpOwogICAgY29uc3QgYml0bWFwID0gZGVjb2RlSGFsZnRvbmVSZWdpb24ocmVnaW9uLm1tciwgcGF0dGVybnMsIHJlZ2lvbi50ZW1wbGF0ZSwgcmVnaW9uSW5mby53aWR0aCwgcmVnaW9uSW5mby5oZWlnaHQsIHJlZ2lvbi5kZWZhdWx0UGl4ZWxWYWx1ZSwgcmVnaW9uLmVuYWJsZVNraXAsIHJlZ2lvbi5jb21iaW5hdGlvbk9wZXJhdG9yLCByZWdpb24uZ3JpZFdpZHRoLCByZWdpb24uZ3JpZEhlaWdodCwgcmVnaW9uLmdyaWRPZmZzZXRYLCByZWdpb24uZ3JpZE9mZnNldFksIHJlZ2lvbi5ncmlkVmVjdG9yWCwgcmVnaW9uLmdyaWRWZWN0b3JZLCBkZWNvZGluZ0NvbnRleHQpOwogICAgdGhpcy5kcmF3Qml0bWFwKHJlZ2lvbkluZm8sIGJpdG1hcCk7CiAgfQogIG9uSW1tZWRpYXRlTG9zc2xlc3NIYWxmdG9uZVJlZ2lvbigpIHsKICAgIHRoaXMub25JbW1lZGlhdGVIYWxmdG9uZVJlZ2lvbiguLi5hcmd1bWVudHMpOwogIH0KICBvblRhYmxlcyhjdXJyZW50U2VnbWVudCwgZGF0YSwgc3RhcnQsIGVuZCkgewogICAgbGV0IGN1c3RvbVRhYmxlcyA9IHRoaXMuY3VzdG9tVGFibGVzOwogICAgaWYgKCFjdXN0b21UYWJsZXMpIHsKICAgICAgdGhpcy5jdXN0b21UYWJsZXMgPSBjdXN0b21UYWJsZXMgPSB7fTsKICAgIH0KICAgIGN1c3RvbVRhYmxlc1tjdXJyZW50U2VnbWVudF0gPSBkZWNvZGVUYWJsZXNTZWdtZW50KGRhdGEsIHN0YXJ0LCBlbmQpOwogIH0KfQpjbGFzcyBIdWZmbWFuTGluZSB7CiAgY29uc3RydWN0b3IobGluZURhdGEpIHsKICAgIGlmIChsaW5lRGF0YS5sZW5ndGggPT09IDIpIHsKICAgICAgdGhpcy5pc09PQiA9IHRydWU7CiAgICAgIHRoaXMucmFuZ2VMb3cgPSAwOwogICAgICB0aGlzLnByZWZpeExlbmd0aCA9IGxpbmVEYXRhWzBdOwogICAgICB0aGlzLnJhbmdlTGVuZ3RoID0gMDsKICAgICAgdGhpcy5wcmVmaXhDb2RlID0gbGluZURhdGFbMV07CiAgICAgIHRoaXMuaXNMb3dlclJhbmdlID0gZmFsc2U7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmlzT09CID0gZmFsc2U7CiAgICAgIHRoaXMucmFuZ2VMb3cgPSBsaW5lRGF0YVswXTsKICAgICAgdGhpcy5wcmVmaXhMZW5ndGggPSBsaW5lRGF0YVsxXTsKICAgICAgdGhpcy5yYW5nZUxlbmd0aCA9IGxpbmVEYXRhWzJdOwogICAgICB0aGlzLnByZWZpeENvZGUgPSBsaW5lRGF0YVszXTsKICAgICAgdGhpcy5pc0xvd2VyUmFuZ2UgPSBsaW5lRGF0YVs0XSA9PT0gImxvd2VyIjsKICAgIH0KICB9Cn0KY2xhc3MgSHVmZm1hblRyZWVOb2RlIHsKICBjb25zdHJ1Y3RvcihsaW5lKSB7CiAgICB0aGlzLmNoaWxkcmVuID0gW107CiAgICBpZiAobGluZSkgewogICAgICB0aGlzLmlzTGVhZiA9IHRydWU7CiAgICAgIHRoaXMucmFuZ2VMZW5ndGggPSBsaW5lLnJhbmdlTGVuZ3RoOwogICAgICB0aGlzLnJhbmdlTG93ID0gbGluZS5yYW5nZUxvdzsKICAgICAgdGhpcy5pc0xvd2VyUmFuZ2UgPSBsaW5lLmlzTG93ZXJSYW5nZTsKICAgICAgdGhpcy5pc09PQiA9IGxpbmUuaXNPT0I7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmlzTGVhZiA9IGZhbHNlOwogICAgfQogIH0KICBidWlsZFRyZWUobGluZSwgc2hpZnQpIHsKICAgIGNvbnN0IGJpdCA9IGxpbmUucHJlZml4Q29kZSA+PiBzaGlmdCAmIDE7CiAgICBpZiAoc2hpZnQgPD0gMCkgewogICAgICB0aGlzLmNoaWxkcmVuW2JpdF0gPSBuZXcgSHVmZm1hblRyZWVOb2RlKGxpbmUpOwogICAgfSBlbHNlIHsKICAgICAgbGV0IG5vZGUgPSB0aGlzLmNoaWxkcmVuW2JpdF07CiAgICAgIGlmICghbm9kZSkgewogICAgICAgIHRoaXMuY2hpbGRyZW5bYml0XSA9IG5vZGUgPSBuZXcgSHVmZm1hblRyZWVOb2RlKG51bGwpOwogICAgICB9CiAgICAgIG5vZGUuYnVpbGRUcmVlKGxpbmUsIHNoaWZ0IC0gMSk7CiAgICB9CiAgfQogIGRlY29kZU5vZGUocmVhZGVyKSB7CiAgICBpZiAodGhpcy5pc0xlYWYpIHsKICAgICAgaWYgKHRoaXMuaXNPT0IpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBjb25zdCBodE9mZnNldCA9IHJlYWRlci5yZWFkQml0cyh0aGlzLnJhbmdlTGVuZ3RoKTsKICAgICAgcmV0dXJuIHRoaXMucmFuZ2VMb3cgKyAodGhpcy5pc0xvd2VyUmFuZ2UgPyAtaHRPZmZzZXQgOiBodE9mZnNldCk7CiAgICB9CiAgICBjb25zdCBub2RlID0gdGhpcy5jaGlsZHJlbltyZWFkZXIucmVhZEJpdCgpXTsKICAgIGlmICghbm9kZSkgewogICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCBIdWZmbWFuIGRhdGEiKTsKICAgIH0KICAgIHJldHVybiBub2RlLmRlY29kZU5vZGUocmVhZGVyKTsKICB9Cn0KY2xhc3MgSHVmZm1hblRhYmxlIHsKICBjb25zdHJ1Y3RvcihsaW5lcywgcHJlZml4Q29kZXNEb25lKSB7CiAgICBpZiAoIXByZWZpeENvZGVzRG9uZSkgewogICAgICB0aGlzLmFzc2lnblByZWZpeENvZGVzKGxpbmVzKTsKICAgIH0KICAgIHRoaXMucm9vdE5vZGUgPSBuZXcgSHVmZm1hblRyZWVOb2RlKG51bGwpOwogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gbGluZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCBsaW5lID0gbGluZXNbaV07CiAgICAgIGlmIChsaW5lLnByZWZpeExlbmd0aCA+IDApIHsKICAgICAgICB0aGlzLnJvb3ROb2RlLmJ1aWxkVHJlZShsaW5lLCBsaW5lLnByZWZpeExlbmd0aCAtIDEpOwogICAgICB9CiAgICB9CiAgfQogIGRlY29kZShyZWFkZXIpIHsKICAgIHJldHVybiB0aGlzLnJvb3ROb2RlLmRlY29kZU5vZGUocmVhZGVyKTsKICB9CiAgYXNzaWduUHJlZml4Q29kZXMobGluZXMpIHsKICAgIGNvbnN0IGxpbmVzTGVuZ3RoID0gbGluZXMubGVuZ3RoOwogICAgbGV0IHByZWZpeExlbmd0aE1heCA9IDA7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzTGVuZ3RoOyBpKyspIHsKICAgICAgcHJlZml4TGVuZ3RoTWF4ID0gTWF0aC5tYXgocHJlZml4TGVuZ3RoTWF4LCBsaW5lc1tpXS5wcmVmaXhMZW5ndGgpOwogICAgfQogICAgY29uc3QgaGlzdG9ncmFtID0gbmV3IFVpbnQzMkFycmF5KHByZWZpeExlbmd0aE1heCArIDEpOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaW5lc0xlbmd0aDsgaSsrKSB7CiAgICAgIGhpc3RvZ3JhbVtsaW5lc1tpXS5wcmVmaXhMZW5ndGhdKys7CiAgICB9CiAgICBsZXQgY3VycmVudExlbmd0aCA9IDEsCiAgICAgIGZpcnN0Q29kZSA9IDAsCiAgICAgIGN1cnJlbnRDb2RlLAogICAgICBjdXJyZW50VGVtcCwKICAgICAgbGluZTsKICAgIGhpc3RvZ3JhbVswXSA9IDA7CiAgICB3aGlsZSAoY3VycmVudExlbmd0aCA8PSBwcmVmaXhMZW5ndGhNYXgpIHsKICAgICAgZmlyc3RDb2RlID0gZmlyc3RDb2RlICsgaGlzdG9ncmFtW2N1cnJlbnRMZW5ndGggLSAxXSA8PCAxOwogICAgICBjdXJyZW50Q29kZSA9IGZpcnN0Q29kZTsKICAgICAgY3VycmVudFRlbXAgPSAwOwogICAgICB3aGlsZSAoY3VycmVudFRlbXAgPCBsaW5lc0xlbmd0aCkgewogICAgICAgIGxpbmUgPSBsaW5lc1tjdXJyZW50VGVtcF07CiAgICAgICAgaWYgKGxpbmUucHJlZml4TGVuZ3RoID09PSBjdXJyZW50TGVuZ3RoKSB7CiAgICAgICAgICBsaW5lLnByZWZpeENvZGUgPSBjdXJyZW50Q29kZTsKICAgICAgICAgIGN1cnJlbnRDb2RlKys7CiAgICAgICAgfQogICAgICAgIGN1cnJlbnRUZW1wKys7CiAgICAgIH0KICAgICAgY3VycmVudExlbmd0aCsrOwogICAgfQogIH0KfQpmdW5jdGlvbiBkZWNvZGVUYWJsZXNTZWdtZW50KGRhdGEsIHN0YXJ0LCBlbmQpIHsKICBjb25zdCBmbGFncyA9IGRhdGFbc3RhcnRdOwogIGNvbnN0IGxvd2VzdFZhbHVlID0gcmVhZFVpbnQzMihkYXRhLCBzdGFydCArIDEpICYgMHhmZmZmZmZmZjsKICBjb25zdCBoaWdoZXN0VmFsdWUgPSByZWFkVWludDMyKGRhdGEsIHN0YXJ0ICsgNSkgJiAweGZmZmZmZmZmOwogIGNvbnN0IHJlYWRlciA9IG5ldyBSZWFkZXIoZGF0YSwgc3RhcnQgKyA5LCBlbmQpOwogIGNvbnN0IHByZWZpeFNpemVCaXRzID0gKGZsYWdzID4+IDEgJiA3KSArIDE7CiAgY29uc3QgcmFuZ2VTaXplQml0cyA9IChmbGFncyA+PiA0ICYgNykgKyAxOwogIGNvbnN0IGxpbmVzID0gW107CiAgbGV0IHByZWZpeExlbmd0aCwKICAgIHJhbmdlTGVuZ3RoLAogICAgY3VycmVudFJhbmdlTG93ID0gbG93ZXN0VmFsdWU7CiAgZG8gewogICAgcHJlZml4TGVuZ3RoID0gcmVhZGVyLnJlYWRCaXRzKHByZWZpeFNpemVCaXRzKTsKICAgIHJhbmdlTGVuZ3RoID0gcmVhZGVyLnJlYWRCaXRzKHJhbmdlU2l6ZUJpdHMpOwogICAgbGluZXMucHVzaChuZXcgSHVmZm1hbkxpbmUoW2N1cnJlbnRSYW5nZUxvdywgcHJlZml4TGVuZ3RoLCByYW5nZUxlbmd0aCwgMF0pKTsKICAgIGN1cnJlbnRSYW5nZUxvdyArPSAxIDw8IHJhbmdlTGVuZ3RoOwogIH0gd2hpbGUgKGN1cnJlbnRSYW5nZUxvdyA8IGhpZ2hlc3RWYWx1ZSk7CiAgcHJlZml4TGVuZ3RoID0gcmVhZGVyLnJlYWRCaXRzKHByZWZpeFNpemVCaXRzKTsKICBsaW5lcy5wdXNoKG5ldyBIdWZmbWFuTGluZShbbG93ZXN0VmFsdWUgLSAxLCBwcmVmaXhMZW5ndGgsIDMyLCAwLCAibG93ZXIiXSkpOwogIHByZWZpeExlbmd0aCA9IHJlYWRlci5yZWFkQml0cyhwcmVmaXhTaXplQml0cyk7CiAgbGluZXMucHVzaChuZXcgSHVmZm1hbkxpbmUoW2hpZ2hlc3RWYWx1ZSwgcHJlZml4TGVuZ3RoLCAzMiwgMF0pKTsKICBpZiAoZmxhZ3MgJiAxKSB7CiAgICBwcmVmaXhMZW5ndGggPSByZWFkZXIucmVhZEJpdHMocHJlZml4U2l6ZUJpdHMpOwogICAgbGluZXMucHVzaChuZXcgSHVmZm1hbkxpbmUoW3ByZWZpeExlbmd0aCwgMF0pKTsKICB9CiAgcmV0dXJuIG5ldyBIdWZmbWFuVGFibGUobGluZXMsIGZhbHNlKTsKfQpjb25zdCBzdGFuZGFyZFRhYmxlc0NhY2hlID0ge307CmZ1bmN0aW9uIGdldFN0YW5kYXJkVGFibGUobnVtYmVyKSB7CiAgbGV0IHRhYmxlID0gc3RhbmRhcmRUYWJsZXNDYWNoZVtudW1iZXJdOwogIGlmICh0YWJsZSkgewogICAgcmV0dXJuIHRhYmxlOwogIH0KICBsZXQgbGluZXM7CiAgc3dpdGNoIChudW1iZXIpIHsKICAgIGNhc2UgMToKICAgICAgbGluZXMgPSBbWzAsIDEsIDQsIDB4MF0sIFsxNiwgMiwgOCwgMHgyXSwgWzI3MiwgMywgMTYsIDB4Nl0sIFs2NTgwOCwgMywgMzIsIDB4N11dOwogICAgICBicmVhazsKICAgIGNhc2UgMjoKICAgICAgbGluZXMgPSBbWzAsIDEsIDAsIDB4MF0sIFsxLCAyLCAwLCAweDJdLCBbMiwgMywgMCwgMHg2XSwgWzMsIDQsIDMsIDB4ZV0sIFsxMSwgNSwgNiwgMHgxZV0sIFs3NSwgNiwgMzIsIDB4M2VdLCBbNiwgMHgzZl1dOwogICAgICBicmVhazsKICAgIGNhc2UgMzoKICAgICAgbGluZXMgPSBbWy0yNTYsIDgsIDgsIDB4ZmVdLCBbMCwgMSwgMCwgMHgwXSwgWzEsIDIsIDAsIDB4Ml0sIFsyLCAzLCAwLCAweDZdLCBbMywgNCwgMywgMHhlXSwgWzExLCA1LCA2LCAweDFlXSwgWy0yNTcsIDgsIDMyLCAweGZmLCAibG93ZXIiXSwgWzc1LCA3LCAzMiwgMHg3ZV0sIFs2LCAweDNlXV07CiAgICAgIGJyZWFrOwogICAgY2FzZSA0OgogICAgICBsaW5lcyA9IFtbMSwgMSwgMCwgMHgwXSwgWzIsIDIsIDAsIDB4Ml0sIFszLCAzLCAwLCAweDZdLCBbNCwgNCwgMywgMHhlXSwgWzEyLCA1LCA2LCAweDFlXSwgWzc2LCA1LCAzMiwgMHgxZl1dOwogICAgICBicmVhazsKICAgIGNhc2UgNToKICAgICAgbGluZXMgPSBbWy0yNTUsIDcsIDgsIDB4N2VdLCBbMSwgMSwgMCwgMHgwXSwgWzIsIDIsIDAsIDB4Ml0sIFszLCAzLCAwLCAweDZdLCBbNCwgNCwgMywgMHhlXSwgWzEyLCA1LCA2LCAweDFlXSwgWy0yNTYsIDcsIDMyLCAweDdmLCAibG93ZXIiXSwgWzc2LCA2LCAzMiwgMHgzZV1dOwogICAgICBicmVhazsKICAgIGNhc2UgNjoKICAgICAgbGluZXMgPSBbWy0yMDQ4LCA1LCAxMCwgMHgxY10sIFstMTAyNCwgNCwgOSwgMHg4XSwgWy01MTIsIDQsIDgsIDB4OV0sIFstMjU2LCA0LCA3LCAweGFdLCBbLTEyOCwgNSwgNiwgMHgxZF0sIFstNjQsIDUsIDUsIDB4MWVdLCBbLTMyLCA0LCA1LCAweGJdLCBbMCwgMiwgNywgMHgwXSwgWzEyOCwgMywgNywgMHgyXSwgWzI1NiwgMywgOCwgMHgzXSwgWzUxMiwgNCwgOSwgMHhjXSwgWzEwMjQsIDQsIDEwLCAweGRdLCBbLTIwNDksIDYsIDMyLCAweDNlLCAibG93ZXIiXSwgWzIwNDgsIDYsIDMyLCAweDNmXV07CiAgICAgIGJyZWFrOwogICAgY2FzZSA3OgogICAgICBsaW5lcyA9IFtbLTEwMjQsIDQsIDksIDB4OF0sIFstNTEyLCAzLCA4LCAweDBdLCBbLTI1NiwgNCwgNywgMHg5XSwgWy0xMjgsIDUsIDYsIDB4MWFdLCBbLTY0LCA1LCA1LCAweDFiXSwgWy0zMiwgNCwgNSwgMHhhXSwgWzAsIDQsIDUsIDB4Yl0sIFszMiwgNSwgNSwgMHgxY10sIFs2NCwgNSwgNiwgMHgxZF0sIFsxMjgsIDQsIDcsIDB4Y10sIFsyNTYsIDMsIDgsIDB4MV0sIFs1MTIsIDMsIDksIDB4Ml0sIFsxMDI0LCAzLCAxMCwgMHgzXSwgWy0xMDI1LCA1LCAzMiwgMHgxZSwgImxvd2VyIl0sIFsyMDQ4LCA1LCAzMiwgMHgxZl1dOwogICAgICBicmVhazsKICAgIGNhc2UgODoKICAgICAgbGluZXMgPSBbWy0xNSwgOCwgMywgMHhmY10sIFstNywgOSwgMSwgMHgxZmNdLCBbLTUsIDgsIDEsIDB4ZmRdLCBbLTMsIDksIDAsIDB4MWZkXSwgWy0yLCA3LCAwLCAweDdjXSwgWy0xLCA0LCAwLCAweGFdLCBbMCwgMiwgMSwgMHgwXSwgWzIsIDUsIDAsIDB4MWFdLCBbMywgNiwgMCwgMHgzYV0sIFs0LCAzLCA0LCAweDRdLCBbMjAsIDYsIDEsIDB4M2JdLCBbMjIsIDQsIDQsIDB4Yl0sIFszOCwgNCwgNSwgMHhjXSwgWzcwLCA1LCA2LCAweDFiXSwgWzEzNCwgNSwgNywgMHgxY10sIFsyNjIsIDYsIDcsIDB4M2NdLCBbMzkwLCA3LCA4LCAweDdkXSwgWzY0NiwgNiwgMTAsIDB4M2RdLCBbLTE2LCA5LCAzMiwgMHgxZmUsICJsb3dlciJdLCBbMTY3MCwgOSwgMzIsIDB4MWZmXSwgWzIsIDB4MV1dOwogICAgICBicmVhazsKICAgIGNhc2UgOToKICAgICAgbGluZXMgPSBbWy0zMSwgOCwgNCwgMHhmY10sIFstMTUsIDksIDIsIDB4MWZjXSwgWy0xMSwgOCwgMiwgMHhmZF0sIFstNywgOSwgMSwgMHgxZmRdLCBbLTUsIDcsIDEsIDB4N2NdLCBbLTMsIDQsIDEsIDB4YV0sIFstMSwgMywgMSwgMHgyXSwgWzEsIDMsIDEsIDB4M10sIFszLCA1LCAxLCAweDFhXSwgWzUsIDYsIDEsIDB4M2FdLCBbNywgMywgNSwgMHg0XSwgWzM5LCA2LCAyLCAweDNiXSwgWzQzLCA0LCA1LCAweGJdLCBbNzUsIDQsIDYsIDB4Y10sIFsxMzksIDUsIDcsIDB4MWJdLCBbMjY3LCA1LCA4LCAweDFjXSwgWzUyMywgNiwgOCwgMHgzY10sIFs3NzksIDcsIDksIDB4N2RdLCBbMTI5MSwgNiwgMTEsIDB4M2RdLCBbLTMyLCA5LCAzMiwgMHgxZmUsICJsb3dlciJdLCBbMzMzOSwgOSwgMzIsIDB4MWZmXSwgWzIsIDB4MF1dOwogICAgICBicmVhazsKICAgIGNhc2UgMTA6CiAgICAgIGxpbmVzID0gW1stMjEsIDcsIDQsIDB4N2FdLCBbLTUsIDgsIDAsIDB4ZmNdLCBbLTQsIDcsIDAsIDB4N2JdLCBbLTMsIDUsIDAsIDB4MThdLCBbLTIsIDIsIDIsIDB4MF0sIFsyLCA1LCAwLCAweDE5XSwgWzMsIDYsIDAsIDB4MzZdLCBbNCwgNywgMCwgMHg3Y10sIFs1LCA4LCAwLCAweGZkXSwgWzYsIDIsIDYsIDB4MV0sIFs3MCwgNSwgNSwgMHgxYV0sIFsxMDIsIDYsIDUsIDB4MzddLCBbMTM0LCA2LCA2LCAweDM4XSwgWzE5OCwgNiwgNywgMHgzOV0sIFszMjYsIDYsIDgsIDB4M2FdLCBbNTgyLCA2LCA5LCAweDNiXSwgWzEwOTQsIDYsIDEwLCAweDNjXSwgWzIxMTgsIDcsIDExLCAweDdkXSwgWy0yMiwgOCwgMzIsIDB4ZmUsICJsb3dlciJdLCBbNDE2NiwgOCwgMzIsIDB4ZmZdLCBbMiwgMHgyXV07CiAgICAgIGJyZWFrOwogICAgY2FzZSAxMToKICAgICAgbGluZXMgPSBbWzEsIDEsIDAsIDB4MF0sIFsyLCAyLCAxLCAweDJdLCBbNCwgNCwgMCwgMHhjXSwgWzUsIDQsIDEsIDB4ZF0sIFs3LCA1LCAxLCAweDFjXSwgWzksIDUsIDIsIDB4MWRdLCBbMTMsIDYsIDIsIDB4M2NdLCBbMTcsIDcsIDIsIDB4N2FdLCBbMjEsIDcsIDMsIDB4N2JdLCBbMjksIDcsIDQsIDB4N2NdLCBbNDUsIDcsIDUsIDB4N2RdLCBbNzcsIDcsIDYsIDB4N2VdLCBbMTQxLCA3LCAzMiwgMHg3Zl1dOwogICAgICBicmVhazsKICAgIGNhc2UgMTI6CiAgICAgIGxpbmVzID0gW1sxLCAxLCAwLCAweDBdLCBbMiwgMiwgMCwgMHgyXSwgWzMsIDMsIDEsIDB4Nl0sIFs1LCA1LCAwLCAweDFjXSwgWzYsIDUsIDEsIDB4MWRdLCBbOCwgNiwgMSwgMHgzY10sIFsxMCwgNywgMCwgMHg3YV0sIFsxMSwgNywgMSwgMHg3Yl0sIFsxMywgNywgMiwgMHg3Y10sIFsxNywgNywgMywgMHg3ZF0sIFsyNSwgNywgNCwgMHg3ZV0sIFs0MSwgOCwgNSwgMHhmZV0sIFs3MywgOCwgMzIsIDB4ZmZdXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDEzOgogICAgICBsaW5lcyA9IFtbMSwgMSwgMCwgMHgwXSwgWzIsIDMsIDAsIDB4NF0sIFszLCA0LCAwLCAweGNdLCBbNCwgNSwgMCwgMHgxY10sIFs1LCA0LCAxLCAweGRdLCBbNywgMywgMywgMHg1XSwgWzE1LCA2LCAxLCAweDNhXSwgWzE3LCA2LCAyLCAweDNiXSwgWzIxLCA2LCAzLCAweDNjXSwgWzI5LCA2LCA0LCAweDNkXSwgWzQ1LCA2LCA1LCAweDNlXSwgWzc3LCA3LCA2LCAweDdlXSwgWzE0MSwgNywgMzIsIDB4N2ZdXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDE0OgogICAgICBsaW5lcyA9IFtbLTIsIDMsIDAsIDB4NF0sIFstMSwgMywgMCwgMHg1XSwgWzAsIDEsIDAsIDB4MF0sIFsxLCAzLCAwLCAweDZdLCBbMiwgMywgMCwgMHg3XV07CiAgICAgIGJyZWFrOwogICAgY2FzZSAxNToKICAgICAgbGluZXMgPSBbWy0yNCwgNywgNCwgMHg3Y10sIFstOCwgNiwgMiwgMHgzY10sIFstNCwgNSwgMSwgMHgxY10sIFstMiwgNCwgMCwgMHhjXSwgWy0xLCAzLCAwLCAweDRdLCBbMCwgMSwgMCwgMHgwXSwgWzEsIDMsIDAsIDB4NV0sIFsyLCA0LCAwLCAweGRdLCBbMywgNSwgMSwgMHgxZF0sIFs1LCA2LCAyLCAweDNkXSwgWzksIDcsIDQsIDB4N2RdLCBbLTI1LCA3LCAzMiwgMHg3ZSwgImxvd2VyIl0sIFsyNSwgNywgMzIsIDB4N2ZdXTsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcihgc3RhbmRhcmQgdGFibGUgQi4ke251bWJlcn0gZG9lcyBub3QgZXhpc3RgKTsKICB9CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gbGluZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgbGluZXNbaV0gPSBuZXcgSHVmZm1hbkxpbmUobGluZXNbaV0pOwogIH0KICB0YWJsZSA9IG5ldyBIdWZmbWFuVGFibGUobGluZXMsIHRydWUpOwogIHN0YW5kYXJkVGFibGVzQ2FjaGVbbnVtYmVyXSA9IHRhYmxlOwogIHJldHVybiB0YWJsZTsKfQpjbGFzcyBSZWFkZXIgewogIGNvbnN0cnVjdG9yKGRhdGEsIHN0YXJ0LCBlbmQpIHsKICAgIHRoaXMuZGF0YSA9IGRhdGE7CiAgICB0aGlzLnN0YXJ0ID0gc3RhcnQ7CiAgICB0aGlzLmVuZCA9IGVuZDsKICAgIHRoaXMucG9zaXRpb24gPSBzdGFydDsKICAgIHRoaXMuc2hpZnQgPSAtMTsKICAgIHRoaXMuY3VycmVudEJ5dGUgPSAwOwogIH0KICByZWFkQml0KCkgewogICAgaWYgKHRoaXMuc2hpZnQgPCAwKSB7CiAgICAgIGlmICh0aGlzLnBvc2l0aW9uID49IHRoaXMuZW5kKSB7CiAgICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoImVuZCBvZiBkYXRhIHdoaWxlIHJlYWRpbmcgYml0Iik7CiAgICAgIH0KICAgICAgdGhpcy5jdXJyZW50Qnl0ZSA9IHRoaXMuZGF0YVt0aGlzLnBvc2l0aW9uKytdOwogICAgICB0aGlzLnNoaWZ0ID0gNzsKICAgIH0KICAgIGNvbnN0IGJpdCA9IHRoaXMuY3VycmVudEJ5dGUgPj4gdGhpcy5zaGlmdCAmIDE7CiAgICB0aGlzLnNoaWZ0LS07CiAgICByZXR1cm4gYml0OwogIH0KICByZWFkQml0cyhudW1CaXRzKSB7CiAgICBsZXQgcmVzdWx0ID0gMCwKICAgICAgaTsKICAgIGZvciAoaSA9IG51bUJpdHMgLSAxOyBpID49IDA7IGktLSkgewogICAgICByZXN1bHQgfD0gdGhpcy5yZWFkQml0KCkgPDwgaTsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQogIGJ5dGVBbGlnbigpIHsKICAgIHRoaXMuc2hpZnQgPSAtMTsKICB9CiAgbmV4dCgpIHsKICAgIGlmICh0aGlzLnBvc2l0aW9uID49IHRoaXMuZW5kKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIHJldHVybiB0aGlzLmRhdGFbdGhpcy5wb3NpdGlvbisrXTsKICB9Cn0KZnVuY3Rpb24gZ2V0Q3VzdG9tSHVmZm1hblRhYmxlKGluZGV4LCByZWZlcnJlZFRvLCBjdXN0b21UYWJsZXMpIHsKICBsZXQgY3VycmVudEluZGV4ID0gMDsKICBmb3IgKGxldCBpID0gMCwgaWkgPSByZWZlcnJlZFRvLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IHRhYmxlID0gY3VzdG9tVGFibGVzW3JlZmVycmVkVG9baV1dOwogICAgaWYgKHRhYmxlKSB7CiAgICAgIGlmIChpbmRleCA9PT0gY3VycmVudEluZGV4KSB7CiAgICAgICAgcmV0dXJuIHRhYmxlOwogICAgICB9CiAgICAgIGN1cnJlbnRJbmRleCsrOwogICAgfQogIH0KICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiY2FuJ3QgZmluZCBjdXN0b20gSHVmZm1hbiB0YWJsZSIpOwp9CmZ1bmN0aW9uIGdldFRleHRSZWdpb25IdWZmbWFuVGFibGVzKHRleHRSZWdpb24sIHJlZmVycmVkVG8sIGN1c3RvbVRhYmxlcywgbnVtYmVyT2ZTeW1ib2xzLCByZWFkZXIpIHsKICBjb25zdCBjb2RlcyA9IFtdOwogIGZvciAobGV0IGkgPSAwOyBpIDw9IDM0OyBpKyspIHsKICAgIGNvbnN0IGNvZGVMZW5ndGggPSByZWFkZXIucmVhZEJpdHMoNCk7CiAgICBjb2Rlcy5wdXNoKG5ldyBIdWZmbWFuTGluZShbaSwgY29kZUxlbmd0aCwgMCwgMF0pKTsKICB9CiAgY29uc3QgcnVuQ29kZXNUYWJsZSA9IG5ldyBIdWZmbWFuVGFibGUoY29kZXMsIGZhbHNlKTsKICBjb2Rlcy5sZW5ndGggPSAwOwogIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZTeW1ib2xzOykgewogICAgY29uc3QgY29kZUxlbmd0aCA9IHJ1bkNvZGVzVGFibGUuZGVjb2RlKHJlYWRlcik7CiAgICBpZiAoY29kZUxlbmd0aCA+PSAzMikgewogICAgICBsZXQgcmVwZWF0ZWRMZW5ndGgsIG51bWJlck9mUmVwZWF0cywgajsKICAgICAgc3dpdGNoIChjb2RlTGVuZ3RoKSB7CiAgICAgICAgY2FzZSAzMjoKICAgICAgICAgIGlmIChpID09PSAwKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBKYmlnMkVycm9yKCJubyBwcmV2aW91cyB2YWx1ZSBpbiBzeW1ib2wgSUQgdGFibGUiKTsKICAgICAgICAgIH0KICAgICAgICAgIG51bWJlck9mUmVwZWF0cyA9IHJlYWRlci5yZWFkQml0cygyKSArIDM7CiAgICAgICAgICByZXBlYXRlZExlbmd0aCA9IGNvZGVzW2kgLSAxXS5wcmVmaXhMZW5ndGg7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDMzOgogICAgICAgICAgbnVtYmVyT2ZSZXBlYXRzID0gcmVhZGVyLnJlYWRCaXRzKDMpICsgMzsKICAgICAgICAgIHJlcGVhdGVkTGVuZ3RoID0gMDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMzQ6CiAgICAgICAgICBudW1iZXJPZlJlcGVhdHMgPSByZWFkZXIucmVhZEJpdHMoNykgKyAxMTsKICAgICAgICAgIHJlcGVhdGVkTGVuZ3RoID0gMDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCBjb2RlIGxlbmd0aCBpbiBzeW1ib2wgSUQgdGFibGUiKTsKICAgICAgfQogICAgICBmb3IgKGogPSAwOyBqIDwgbnVtYmVyT2ZSZXBlYXRzOyBqKyspIHsKICAgICAgICBjb2Rlcy5wdXNoKG5ldyBIdWZmbWFuTGluZShbaSwgcmVwZWF0ZWRMZW5ndGgsIDAsIDBdKSk7CiAgICAgICAgaSsrOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb2Rlcy5wdXNoKG5ldyBIdWZmbWFuTGluZShbaSwgY29kZUxlbmd0aCwgMCwgMF0pKTsKICAgICAgaSsrOwogICAgfQogIH0KICByZWFkZXIuYnl0ZUFsaWduKCk7CiAgY29uc3Qgc3ltYm9sSURUYWJsZSA9IG5ldyBIdWZmbWFuVGFibGUoY29kZXMsIGZhbHNlKTsKICBsZXQgY3VzdG9tSW5kZXggPSAwLAogICAgdGFibGVGaXJzdFMsCiAgICB0YWJsZURlbHRhUywKICAgIHRhYmxlRGVsdGFUOwogIHN3aXRjaCAodGV4dFJlZ2lvbi5odWZmbWFuRlMpIHsKICAgIGNhc2UgMDoKICAgIGNhc2UgMToKICAgICAgdGFibGVGaXJzdFMgPSBnZXRTdGFuZGFyZFRhYmxlKHRleHRSZWdpb24uaHVmZm1hbkZTICsgNik7CiAgICAgIGJyZWFrOwogICAgY2FzZSAzOgogICAgICB0YWJsZUZpcnN0UyA9IGdldEN1c3RvbUh1ZmZtYW5UYWJsZShjdXN0b21JbmRleCwgcmVmZXJyZWRUbywgY3VzdG9tVGFibGVzKTsKICAgICAgY3VzdG9tSW5kZXgrKzsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCBIdWZmbWFuIEZTIHNlbGVjdG9yIik7CiAgfQogIHN3aXRjaCAodGV4dFJlZ2lvbi5odWZmbWFuRFMpIHsKICAgIGNhc2UgMDoKICAgIGNhc2UgMToKICAgIGNhc2UgMjoKICAgICAgdGFibGVEZWx0YVMgPSBnZXRTdGFuZGFyZFRhYmxlKHRleHRSZWdpb24uaHVmZm1hbkRTICsgOCk7CiAgICAgIGJyZWFrOwogICAgY2FzZSAzOgogICAgICB0YWJsZURlbHRhUyA9IGdldEN1c3RvbUh1ZmZtYW5UYWJsZShjdXN0b21JbmRleCwgcmVmZXJyZWRUbywgY3VzdG9tVGFibGVzKTsKICAgICAgY3VzdG9tSW5kZXgrKzsKICAgICAgYnJlYWs7CiAgICBkZWZhdWx0OgogICAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigiaW52YWxpZCBIdWZmbWFuIERTIHNlbGVjdG9yIik7CiAgfQogIHN3aXRjaCAodGV4dFJlZ2lvbi5odWZmbWFuRFQpIHsKICAgIGNhc2UgMDoKICAgIGNhc2UgMToKICAgIGNhc2UgMjoKICAgICAgdGFibGVEZWx0YVQgPSBnZXRTdGFuZGFyZFRhYmxlKHRleHRSZWdpb24uaHVmZm1hbkRUICsgMTEpOwogICAgICBicmVhazsKICAgIGNhc2UgMzoKICAgICAgdGFibGVEZWx0YVQgPSBnZXRDdXN0b21IdWZmbWFuVGFibGUoY3VzdG9tSW5kZXgsIHJlZmVycmVkVG8sIGN1c3RvbVRhYmxlcyk7CiAgICAgIGN1c3RvbUluZGV4Kys7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgSHVmZm1hbiBEVCBzZWxlY3RvciIpOwogIH0KICBpZiAodGV4dFJlZ2lvbi5yZWZpbmVtZW50KSB7CiAgICB0aHJvdyBuZXcgSmJpZzJFcnJvcigicmVmaW5lbWVudCB3aXRoIEh1ZmZtYW4gaXMgbm90IHN1cHBvcnRlZCIpOwogIH0KICByZXR1cm4gewogICAgc3ltYm9sSURUYWJsZSwKICAgIHRhYmxlRmlyc3RTLAogICAgdGFibGVEZWx0YVMsCiAgICB0YWJsZURlbHRhVAogIH07Cn0KZnVuY3Rpb24gZ2V0U3ltYm9sRGljdGlvbmFyeUh1ZmZtYW5UYWJsZXMoZGljdGlvbmFyeSwgcmVmZXJyZWRUbywgY3VzdG9tVGFibGVzKSB7CiAgbGV0IGN1c3RvbUluZGV4ID0gMCwKICAgIHRhYmxlRGVsdGFIZWlnaHQsCiAgICB0YWJsZURlbHRhV2lkdGg7CiAgc3dpdGNoIChkaWN0aW9uYXJ5Lmh1ZmZtYW5ESFNlbGVjdG9yKSB7CiAgICBjYXNlIDA6CiAgICBjYXNlIDE6CiAgICAgIHRhYmxlRGVsdGFIZWlnaHQgPSBnZXRTdGFuZGFyZFRhYmxlKGRpY3Rpb25hcnkuaHVmZm1hbkRIU2VsZWN0b3IgKyA0KTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDM6CiAgICAgIHRhYmxlRGVsdGFIZWlnaHQgPSBnZXRDdXN0b21IdWZmbWFuVGFibGUoY3VzdG9tSW5kZXgsIHJlZmVycmVkVG8sIGN1c3RvbVRhYmxlcyk7CiAgICAgIGN1c3RvbUluZGV4Kys7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgSHVmZm1hbiBESCBzZWxlY3RvciIpOwogIH0KICBzd2l0Y2ggKGRpY3Rpb25hcnkuaHVmZm1hbkRXU2VsZWN0b3IpIHsKICAgIGNhc2UgMDoKICAgIGNhc2UgMToKICAgICAgdGFibGVEZWx0YVdpZHRoID0gZ2V0U3RhbmRhcmRUYWJsZShkaWN0aW9uYXJ5Lmh1ZmZtYW5EV1NlbGVjdG9yICsgMik7CiAgICAgIGJyZWFrOwogICAgY2FzZSAzOgogICAgICB0YWJsZURlbHRhV2lkdGggPSBnZXRDdXN0b21IdWZmbWFuVGFibGUoY3VzdG9tSW5kZXgsIHJlZmVycmVkVG8sIGN1c3RvbVRhYmxlcyk7CiAgICAgIGN1c3RvbUluZGV4Kys7CiAgICAgIGJyZWFrOwogICAgZGVmYXVsdDoKICAgICAgdGhyb3cgbmV3IEpiaWcyRXJyb3IoImludmFsaWQgSHVmZm1hbiBEVyBzZWxlY3RvciIpOwogIH0KICBsZXQgdGFibGVCaXRtYXBTaXplLCB0YWJsZUFnZ3JlZ2F0ZUluc3RhbmNlczsKICBpZiAoZGljdGlvbmFyeS5iaXRtYXBTaXplU2VsZWN0b3IpIHsKICAgIHRhYmxlQml0bWFwU2l6ZSA9IGdldEN1c3RvbUh1ZmZtYW5UYWJsZShjdXN0b21JbmRleCwgcmVmZXJyZWRUbywgY3VzdG9tVGFibGVzKTsKICAgIGN1c3RvbUluZGV4Kys7CiAgfSBlbHNlIHsKICAgIHRhYmxlQml0bWFwU2l6ZSA9IGdldFN0YW5kYXJkVGFibGUoMSk7CiAgfQogIGlmIChkaWN0aW9uYXJ5LmFnZ3JlZ2F0aW9uSW5zdGFuY2VzU2VsZWN0b3IpIHsKICAgIHRhYmxlQWdncmVnYXRlSW5zdGFuY2VzID0gZ2V0Q3VzdG9tSHVmZm1hblRhYmxlKGN1c3RvbUluZGV4LCByZWZlcnJlZFRvLCBjdXN0b21UYWJsZXMpOwogIH0gZWxzZSB7CiAgICB0YWJsZUFnZ3JlZ2F0ZUluc3RhbmNlcyA9IGdldFN0YW5kYXJkVGFibGUoMSk7CiAgfQogIHJldHVybiB7CiAgICB0YWJsZURlbHRhSGVpZ2h0LAogICAgdGFibGVEZWx0YVdpZHRoLAogICAgdGFibGVCaXRtYXBTaXplLAogICAgdGFibGVBZ2dyZWdhdGVJbnN0YW5jZXMKICB9Owp9CmZ1bmN0aW9uIHJlYWRVbmNvbXByZXNzZWRCaXRtYXAocmVhZGVyLCB3aWR0aCwgaGVpZ2h0KSB7CiAgY29uc3QgYml0bWFwID0gW107CiAgZm9yIChsZXQgeSA9IDA7IHkgPCBoZWlnaHQ7IHkrKykgewogICAgY29uc3Qgcm93ID0gbmV3IFVpbnQ4QXJyYXkod2lkdGgpOwogICAgYml0bWFwLnB1c2gocm93KTsKICAgIGZvciAobGV0IHggPSAwOyB4IDwgd2lkdGg7IHgrKykgewogICAgICByb3dbeF0gPSByZWFkZXIucmVhZEJpdCgpOwogICAgfQogICAgcmVhZGVyLmJ5dGVBbGlnbigpOwogIH0KICByZXR1cm4gYml0bWFwOwp9CmZ1bmN0aW9uIGRlY29kZU1NUkJpdG1hcChpbnB1dCwgd2lkdGgsIGhlaWdodCwgZW5kT2ZCbG9jaykgewogIGNvbnN0IHBhcmFtcyA9IHsKICAgIEs6IC0xLAogICAgQ29sdW1uczogd2lkdGgsCiAgICBSb3dzOiBoZWlnaHQsCiAgICBCbGFja0lzMTogdHJ1ZSwKICAgIEVuZE9mQmxvY2s6IGVuZE9mQmxvY2sKICB9OwogIGNvbnN0IGRlY29kZXIgPSBuZXcgQ0NJVFRGYXhEZWNvZGVyKGlucHV0LCBwYXJhbXMpOwogIGNvbnN0IGJpdG1hcCA9IFtdOwogIGxldCBjdXJyZW50Qnl0ZSwKICAgIGVvZiA9IGZhbHNlOwogIGZvciAobGV0IHkgPSAwOyB5IDwgaGVpZ2h0OyB5KyspIHsKICAgIGNvbnN0IHJvdyA9IG5ldyBVaW50OEFycmF5KHdpZHRoKTsKICAgIGJpdG1hcC5wdXNoKHJvdyk7CiAgICBsZXQgc2hpZnQgPSAtMTsKICAgIGZvciAobGV0IHggPSAwOyB4IDwgd2lkdGg7IHgrKykgewogICAgICBpZiAoc2hpZnQgPCAwKSB7CiAgICAgICAgY3VycmVudEJ5dGUgPSBkZWNvZGVyLnJlYWROZXh0Q2hhcigpOwogICAgICAgIGlmIChjdXJyZW50Qnl0ZSA9PT0gLTEpIHsKICAgICAgICAgIGN1cnJlbnRCeXRlID0gMDsKICAgICAgICAgIGVvZiA9IHRydWU7CiAgICAgICAgfQogICAgICAgIHNoaWZ0ID0gNzsKICAgICAgfQogICAgICByb3dbeF0gPSBjdXJyZW50Qnl0ZSA+PiBzaGlmdCAmIDE7CiAgICAgIHNoaWZ0LS07CiAgICB9CiAgfQogIGlmIChlbmRPZkJsb2NrICYmICFlb2YpIHsKICAgIGNvbnN0IGxvb2tGb3JFT0ZMaW1pdCA9IDU7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxvb2tGb3JFT0ZMaW1pdDsgaSsrKSB7CiAgICAgIGlmIChkZWNvZGVyLnJlYWROZXh0Q2hhcigpID09PSAtMSkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiBiaXRtYXA7Cn0KY2xhc3MgSmJpZzJJbWFnZSB7CiAgcGFyc2VDaHVua3MoY2h1bmtzKSB7CiAgICByZXR1cm4gcGFyc2VKYmlnMkNodW5rcyhjaHVua3MpOwogIH0KICBwYXJzZShkYXRhKSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoIk5vdCBpbXBsZW1lbnRlZDogSmJpZzJJbWFnZS5wYXJzZSIpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvamJpZzJfc3RyZWFtLmpzCgoKCgoKCmNsYXNzIEpiaWcyU3RyZWFtIGV4dGVuZHMgRGVjb2RlU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIG1heWJlTGVuZ3RoLCBwYXJhbXMpIHsKICAgIHN1cGVyKG1heWJlTGVuZ3RoKTsKICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtOwogICAgdGhpcy5kaWN0ID0gc3RyZWFtLmRpY3Q7CiAgICB0aGlzLm1heWJlTGVuZ3RoID0gbWF5YmVMZW5ndGg7CiAgICB0aGlzLnBhcmFtcyA9IHBhcmFtczsKICB9CiAgZ2V0IGJ5dGVzKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiYnl0ZXMiLCB0aGlzLnN0cmVhbS5nZXRCeXRlcyh0aGlzLm1heWJlTGVuZ3RoKSk7CiAgfQogIGVuc3VyZUJ1ZmZlcihyZXF1ZXN0ZWQpIHt9CiAgcmVhZEJsb2NrKCkgewogICAgdGhpcy5kZWNvZGVJbWFnZSgpOwogIH0KICBkZWNvZGVJbWFnZShieXRlcykgewogICAgaWYgKHRoaXMuZW9mKSB7CiAgICAgIHJldHVybiB0aGlzLmJ1ZmZlcjsKICAgIH0KICAgIGJ5dGVzIHx8PSB0aGlzLmJ5dGVzOwogICAgY29uc3QgamJpZzJJbWFnZSA9IG5ldyBKYmlnMkltYWdlKCk7CiAgICBjb25zdCBjaHVua3MgPSBbXTsKICAgIGlmICh0aGlzLnBhcmFtcyBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgY29uc3QgZ2xvYmFsc1N0cmVhbSA9IHRoaXMucGFyYW1zLmdldCgiSkJJRzJHbG9iYWxzIik7CiAgICAgIGlmIChnbG9iYWxzU3RyZWFtIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICAgIGNvbnN0IGdsb2JhbHMgPSBnbG9iYWxzU3RyZWFtLmdldEJ5dGVzKCk7CiAgICAgICAgY2h1bmtzLnB1c2goewogICAgICAgICAgZGF0YTogZ2xvYmFscywKICAgICAgICAgIHN0YXJ0OiAwLAogICAgICAgICAgZW5kOiBnbG9iYWxzLmxlbmd0aAogICAgICAgIH0pOwogICAgICB9CiAgICB9CiAgICBjaHVua3MucHVzaCh7CiAgICAgIGRhdGE6IGJ5dGVzLAogICAgICBzdGFydDogMCwKICAgICAgZW5kOiBieXRlcy5sZW5ndGgKICAgIH0pOwogICAgY29uc3QgZGF0YSA9IGpiaWcySW1hZ2UucGFyc2VDaHVua3MoY2h1bmtzKTsKICAgIGNvbnN0IGRhdGFMZW5ndGggPSBkYXRhLmxlbmd0aDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZGF0YUxlbmd0aDsgaSsrKSB7CiAgICAgIGRhdGFbaV0gXj0gMHhmZjsKICAgIH0KICAgIHRoaXMuYnVmZmVyID0gZGF0YTsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gZGF0YUxlbmd0aDsKICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgIHJldHVybiB0aGlzLmJ1ZmZlcjsKICB9CiAgZ2V0IGNhbkFzeW5jRGVjb2RlSW1hZ2VGcm9tQnVmZmVyKCkgewogICAgcmV0dXJuIHRoaXMuc3RyZWFtLmlzQXN5bmM7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9qcHhfc3RyZWFtLmpzCgoKCmNsYXNzIEpweFN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyZWFtLCBtYXliZUxlbmd0aCwgcGFyYW1zKSB7CiAgICBzdXBlcihtYXliZUxlbmd0aCk7CiAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTsKICAgIHRoaXMuZGljdCA9IHN0cmVhbS5kaWN0OwogICAgdGhpcy5tYXliZUxlbmd0aCA9IG1heWJlTGVuZ3RoOwogICAgdGhpcy5wYXJhbXMgPSBwYXJhbXM7CiAgfQogIGdldCBieXRlcygpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgImJ5dGVzIiwgdGhpcy5zdHJlYW0uZ2V0Qnl0ZXModGhpcy5tYXliZUxlbmd0aCkpOwogIH0KICBlbnN1cmVCdWZmZXIocmVxdWVzdGVkKSB7fQogIHJlYWRCbG9jayhkZWNvZGVyT3B0aW9ucykgewogICAgdW5yZWFjaGFibGUoIkpweFN0cmVhbS5yZWFkQmxvY2siKTsKICB9CiAgZ2V0IGlzQXN5bmNEZWNvZGVyKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIGFzeW5jIGRlY29kZUltYWdlKGJ5dGVzLCBkZWNvZGVyT3B0aW9ucykgewogICAgaWYgKHRoaXMuZW9mKSB7CiAgICAgIHJldHVybiB0aGlzLmJ1ZmZlcjsKICAgIH0KICAgIGJ5dGVzIHx8PSB0aGlzLmJ5dGVzOwogICAgdGhpcy5idWZmZXIgPSBhd2FpdCBKcHhJbWFnZS5kZWNvZGUoYnl0ZXMsIGRlY29kZXJPcHRpb25zKTsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXIubGVuZ3RoOwogICAgdGhpcy5lb2YgPSB0cnVlOwogICAgcmV0dXJuIHRoaXMuYnVmZmVyOwogIH0KICBnZXQgY2FuQXN5bmNEZWNvZGVJbWFnZUZyb21CdWZmZXIoKSB7CiAgICByZXR1cm4gdGhpcy5zdHJlYW0uaXNBc3luYzsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2x6d19zdHJlYW0uanMKCgoKCgoKCgoKY2xhc3MgTFpXU3RyZWFtIGV4dGVuZHMgRGVjb2RlU3RyZWFtIHsKICBjb25zdHJ1Y3RvcihzdHIsIG1heWJlTGVuZ3RoLCBlYXJseUNoYW5nZSkgewogICAgc3VwZXIobWF5YmVMZW5ndGgpOwogICAgdGhpcy5zdHIgPSBzdHI7CiAgICB0aGlzLmRpY3QgPSBzdHIuZGljdDsKICAgIHRoaXMuY2FjaGVkRGF0YSA9IDA7CiAgICB0aGlzLmJpdHNDYWNoZWQgPSAwOwogICAgY29uc3QgbWF4THp3RGljdGlvbmFyeVNpemUgPSA0MDk2OwogICAgY29uc3QgbHp3U3RhdGUgPSB7CiAgICAgIGVhcmx5Q2hhbmdlLAogICAgICBjb2RlTGVuZ3RoOiA5LAogICAgICBuZXh0Q29kZTogMjU4LAogICAgICBkaWN0aW9uYXJ5VmFsdWVzOiBuZXcgVWludDhBcnJheShtYXhMendEaWN0aW9uYXJ5U2l6ZSksCiAgICAgIGRpY3Rpb25hcnlMZW5ndGhzOiBuZXcgVWludDE2QXJyYXkobWF4THp3RGljdGlvbmFyeVNpemUpLAogICAgICBkaWN0aW9uYXJ5UHJldkNvZGVzOiBuZXcgVWludDE2QXJyYXkobWF4THp3RGljdGlvbmFyeVNpemUpLAogICAgICBjdXJyZW50U2VxdWVuY2U6IG5ldyBVaW50OEFycmF5KG1heEx6d0RpY3Rpb25hcnlTaXplKSwKICAgICAgY3VycmVudFNlcXVlbmNlTGVuZ3RoOiAwCiAgICB9OwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCAyNTY7ICsraSkgewogICAgICBsendTdGF0ZS5kaWN0aW9uYXJ5VmFsdWVzW2ldID0gaTsKICAgICAgbHp3U3RhdGUuZGljdGlvbmFyeUxlbmd0aHNbaV0gPSAxOwogICAgfQogICAgdGhpcy5sendTdGF0ZSA9IGx6d1N0YXRlOwogIH0KICByZWFkQml0cyhuKSB7CiAgICBsZXQgYml0c0NhY2hlZCA9IHRoaXMuYml0c0NhY2hlZDsKICAgIGxldCBjYWNoZWREYXRhID0gdGhpcy5jYWNoZWREYXRhOwogICAgd2hpbGUgKGJpdHNDYWNoZWQgPCBuKSB7CiAgICAgIGNvbnN0IGMgPSB0aGlzLnN0ci5nZXRCeXRlKCk7CiAgICAgIGlmIChjID09PSAtMSkgewogICAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBjYWNoZWREYXRhID0gY2FjaGVkRGF0YSA8PCA4IHwgYzsKICAgICAgYml0c0NhY2hlZCArPSA4OwogICAgfQogICAgdGhpcy5iaXRzQ2FjaGVkID0gYml0c0NhY2hlZCAtPSBuOwogICAgdGhpcy5jYWNoZWREYXRhID0gY2FjaGVkRGF0YTsKICAgIHRoaXMubGFzdENvZGUgPSBudWxsOwogICAgcmV0dXJuIGNhY2hlZERhdGEgPj4+IGJpdHNDYWNoZWQgJiAoMSA8PCBuKSAtIDE7CiAgfQogIHJlYWRCbG9jaygpIHsKICAgIGNvbnN0IGJsb2NrU2l6ZSA9IDUxMiwKICAgICAgZGVjb2RlZFNpemVEZWx0YSA9IGJsb2NrU2l6ZTsKICAgIGxldCBlc3RpbWF0ZWREZWNvZGVkU2l6ZSA9IGJsb2NrU2l6ZSAqIDI7CiAgICBsZXQgaSwgaiwgcTsKICAgIGNvbnN0IGx6d1N0YXRlID0gdGhpcy5sendTdGF0ZTsKICAgIGlmICghbHp3U3RhdGUpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgZWFybHlDaGFuZ2UgPSBsendTdGF0ZS5lYXJseUNoYW5nZTsKICAgIGxldCBuZXh0Q29kZSA9IGx6d1N0YXRlLm5leHRDb2RlOwogICAgY29uc3QgZGljdGlvbmFyeVZhbHVlcyA9IGx6d1N0YXRlLmRpY3Rpb25hcnlWYWx1ZXM7CiAgICBjb25zdCBkaWN0aW9uYXJ5TGVuZ3RocyA9IGx6d1N0YXRlLmRpY3Rpb25hcnlMZW5ndGhzOwogICAgY29uc3QgZGljdGlvbmFyeVByZXZDb2RlcyA9IGx6d1N0YXRlLmRpY3Rpb25hcnlQcmV2Q29kZXM7CiAgICBsZXQgY29kZUxlbmd0aCA9IGx6d1N0YXRlLmNvZGVMZW5ndGg7CiAgICBsZXQgcHJldkNvZGUgPSBsendTdGF0ZS5wcmV2Q29kZTsKICAgIGNvbnN0IGN1cnJlbnRTZXF1ZW5jZSA9IGx6d1N0YXRlLmN1cnJlbnRTZXF1ZW5jZTsKICAgIGxldCBjdXJyZW50U2VxdWVuY2VMZW5ndGggPSBsendTdGF0ZS5jdXJyZW50U2VxdWVuY2VMZW5ndGg7CiAgICBsZXQgZGVjb2RlZExlbmd0aCA9IDA7CiAgICBsZXQgY3VycmVudEJ1ZmZlckxlbmd0aCA9IHRoaXMuYnVmZmVyTGVuZ3RoOwogICAgbGV0IGJ1ZmZlciA9IHRoaXMuZW5zdXJlQnVmZmVyKHRoaXMuYnVmZmVyTGVuZ3RoICsgZXN0aW1hdGVkRGVjb2RlZFNpemUpOwogICAgZm9yIChpID0gMDsgaSA8IGJsb2NrU2l6ZTsgaSsrKSB7CiAgICAgIGNvbnN0IGNvZGUgPSB0aGlzLnJlYWRCaXRzKGNvZGVMZW5ndGgpOwogICAgICBjb25zdCBoYXNQcmV2ID0gY3VycmVudFNlcXVlbmNlTGVuZ3RoID4gMDsKICAgICAgaWYgKGNvZGUgPCAyNTYpIHsKICAgICAgICBjdXJyZW50U2VxdWVuY2VbMF0gPSBjb2RlOwogICAgICAgIGN1cnJlbnRTZXF1ZW5jZUxlbmd0aCA9IDE7CiAgICAgIH0gZWxzZSBpZiAoY29kZSA+PSAyNTgpIHsKICAgICAgICBpZiAoY29kZSA8IG5leHRDb2RlKSB7CiAgICAgICAgICBjdXJyZW50U2VxdWVuY2VMZW5ndGggPSBkaWN0aW9uYXJ5TGVuZ3Roc1tjb2RlXTsKICAgICAgICAgIGZvciAoaiA9IGN1cnJlbnRTZXF1ZW5jZUxlbmd0aCAtIDEsIHEgPSBjb2RlOyBqID49IDA7IGotLSkgewogICAgICAgICAgICBjdXJyZW50U2VxdWVuY2Vbal0gPSBkaWN0aW9uYXJ5VmFsdWVzW3FdOwogICAgICAgICAgICBxID0gZGljdGlvbmFyeVByZXZDb2Rlc1txXTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgewogICAgICAgICAgY3VycmVudFNlcXVlbmNlW2N1cnJlbnRTZXF1ZW5jZUxlbmd0aCsrXSA9IGN1cnJlbnRTZXF1ZW5jZVswXTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoY29kZSA9PT0gMjU2KSB7CiAgICAgICAgY29kZUxlbmd0aCA9IDk7CiAgICAgICAgbmV4dENvZGUgPSAyNTg7CiAgICAgICAgY3VycmVudFNlcXVlbmNlTGVuZ3RoID0gMDsKICAgICAgICBjb250aW51ZTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgICAgZGVsZXRlIHRoaXMubHp3U3RhdGU7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKGhhc1ByZXYpIHsKICAgICAgICBkaWN0aW9uYXJ5UHJldkNvZGVzW25leHRDb2RlXSA9IHByZXZDb2RlOwogICAgICAgIGRpY3Rpb25hcnlMZW5ndGhzW25leHRDb2RlXSA9IGRpY3Rpb25hcnlMZW5ndGhzW3ByZXZDb2RlXSArIDE7CiAgICAgICAgZGljdGlvbmFyeVZhbHVlc1tuZXh0Q29kZV0gPSBjdXJyZW50U2VxdWVuY2VbMF07CiAgICAgICAgbmV4dENvZGUrKzsKICAgICAgICBjb2RlTGVuZ3RoID0gbmV4dENvZGUgKyBlYXJseUNoYW5nZSAmIG5leHRDb2RlICsgZWFybHlDaGFuZ2UgLSAxID8gY29kZUxlbmd0aCA6IE1hdGgubWluKE1hdGgubG9nKG5leHRDb2RlICsgZWFybHlDaGFuZ2UpIC8gMC42OTMxNDcxODA1NTk5NDUzICsgMSwgMTIpIHwgMDsKICAgICAgfQogICAgICBwcmV2Q29kZSA9IGNvZGU7CiAgICAgIGRlY29kZWRMZW5ndGggKz0gY3VycmVudFNlcXVlbmNlTGVuZ3RoOwogICAgICBpZiAoZXN0aW1hdGVkRGVjb2RlZFNpemUgPCBkZWNvZGVkTGVuZ3RoKSB7CiAgICAgICAgZG8gewogICAgICAgICAgZXN0aW1hdGVkRGVjb2RlZFNpemUgKz0gZGVjb2RlZFNpemVEZWx0YTsKICAgICAgICB9IHdoaWxlIChlc3RpbWF0ZWREZWNvZGVkU2l6ZSA8IGRlY29kZWRMZW5ndGgpOwogICAgICAgIGJ1ZmZlciA9IHRoaXMuZW5zdXJlQnVmZmVyKHRoaXMuYnVmZmVyTGVuZ3RoICsgZXN0aW1hdGVkRGVjb2RlZFNpemUpOwogICAgICB9CiAgICAgIGZvciAoaiA9IDA7IGogPCBjdXJyZW50U2VxdWVuY2VMZW5ndGg7IGorKykgewogICAgICAgIGJ1ZmZlcltjdXJyZW50QnVmZmVyTGVuZ3RoKytdID0gY3VycmVudFNlcXVlbmNlW2pdOwogICAgICB9CiAgICB9CiAgICBsendTdGF0ZS5uZXh0Q29kZSA9IG5leHRDb2RlOwogICAgbHp3U3RhdGUuY29kZUxlbmd0aCA9IGNvZGVMZW5ndGg7CiAgICBsendTdGF0ZS5wcmV2Q29kZSA9IHByZXZDb2RlOwogICAgbHp3U3RhdGUuY3VycmVudFNlcXVlbmNlTGVuZ3RoID0gY3VycmVudFNlcXVlbmNlTGVuZ3RoOwogICAgdGhpcy5idWZmZXJMZW5ndGggPSBjdXJyZW50QnVmZmVyTGVuZ3RoOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvcHJlZGljdG9yX3N0cmVhbS5qcwoKCgoKCgoKCgoKCmNsYXNzIFByZWRpY3RvclN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyLCBtYXliZUxlbmd0aCwgcGFyYW1zKSB7CiAgICBzdXBlcihtYXliZUxlbmd0aCk7CiAgICBpZiAoIShwYXJhbXMgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm4gc3RyOwogICAgfQogICAgY29uc3QgcHJlZGljdG9yID0gdGhpcy5wcmVkaWN0b3IgPSBwYXJhbXMuZ2V0KCJQcmVkaWN0b3IiKSB8fCAxOwogICAgaWYgKHByZWRpY3RvciA8PSAxKSB7CiAgICAgIHJldHVybiBzdHI7CiAgICB9CiAgICBpZiAocHJlZGljdG9yICE9PSAyICYmIChwcmVkaWN0b3IgPCAxMCB8fCBwcmVkaWN0b3IgPiAxNSkpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBVbnN1cHBvcnRlZCBwcmVkaWN0b3I6ICR7cHJlZGljdG9yfWApOwogICAgfQogICAgdGhpcy5yZWFkQmxvY2sgPSBwcmVkaWN0b3IgPT09IDIgPyB0aGlzLnJlYWRCbG9ja1RpZmYgOiB0aGlzLnJlYWRCbG9ja1BuZzsKICAgIHRoaXMuc3RyID0gc3RyOwogICAgdGhpcy5kaWN0ID0gc3RyLmRpY3Q7CiAgICBjb25zdCBjb2xvcnMgPSB0aGlzLmNvbG9ycyA9IHBhcmFtcy5nZXQoIkNvbG9ycyIpIHx8IDE7CiAgICBjb25zdCBiaXRzID0gdGhpcy5iaXRzID0gcGFyYW1zLmdldCgiQlBDIiwgIkJpdHNQZXJDb21wb25lbnQiKSB8fCA4OwogICAgY29uc3QgY29sdW1ucyA9IHRoaXMuY29sdW1ucyA9IHBhcmFtcy5nZXQoIkNvbHVtbnMiKSB8fCAxOwogICAgdGhpcy5waXhCeXRlcyA9IGNvbG9ycyAqIGJpdHMgKyA3ID4+IDM7CiAgICB0aGlzLnJvd0J5dGVzID0gY29sdW1ucyAqIGNvbG9ycyAqIGJpdHMgKyA3ID4+IDM7CiAgICByZXR1cm4gdGhpczsKICB9CiAgcmVhZEJsb2NrVGlmZigpIHsKICAgIGNvbnN0IHJvd0J5dGVzID0gdGhpcy5yb3dCeXRlczsKICAgIGNvbnN0IGJ1ZmZlckxlbmd0aCA9IHRoaXMuYnVmZmVyTGVuZ3RoOwogICAgY29uc3QgYnVmZmVyID0gdGhpcy5lbnN1cmVCdWZmZXIoYnVmZmVyTGVuZ3RoICsgcm93Qnl0ZXMpOwogICAgY29uc3QgYml0cyA9IHRoaXMuYml0czsKICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuY29sb3JzOwogICAgY29uc3QgcmF3Qnl0ZXMgPSB0aGlzLnN0ci5nZXRCeXRlcyhyb3dCeXRlcyk7CiAgICB0aGlzLmVvZiA9ICFyYXdCeXRlcy5sZW5ndGg7CiAgICBpZiAodGhpcy5lb2YpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgbGV0IGluYnVmID0gMCwKICAgICAgb3V0YnVmID0gMDsKICAgIGxldCBpbmJpdHMgPSAwLAogICAgICBvdXRiaXRzID0gMDsKICAgIGxldCBwb3MgPSBidWZmZXJMZW5ndGg7CiAgICBsZXQgaTsKICAgIGlmIChiaXRzID09PSAxICYmIGNvbG9ycyA9PT0gMSkgewogICAgICBmb3IgKGkgPSAwOyBpIDwgcm93Qnl0ZXM7ICsraSkgewogICAgICAgIGxldCBjID0gcmF3Qnl0ZXNbaV0gXiBpbmJ1ZjsKICAgICAgICBjIF49IGMgPj4gMTsKICAgICAgICBjIF49IGMgPj4gMjsKICAgICAgICBjIF49IGMgPj4gNDsKICAgICAgICBpbmJ1ZiA9IChjICYgMSkgPDwgNzsKICAgICAgICBidWZmZXJbcG9zKytdID0gYzsKICAgICAgfQogICAgfSBlbHNlIGlmIChiaXRzID09PSA4KSB7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBjb2xvcnM7ICsraSkgewogICAgICAgIGJ1ZmZlcltwb3MrK10gPSByYXdCeXRlc1tpXTsKICAgICAgfQogICAgICBmb3IgKDsgaSA8IHJvd0J5dGVzOyArK2kpIHsKICAgICAgICBidWZmZXJbcG9zXSA9IGJ1ZmZlcltwb3MgLSBjb2xvcnNdICsgcmF3Qnl0ZXNbaV07CiAgICAgICAgcG9zKys7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoYml0cyA9PT0gMTYpIHsKICAgICAgY29uc3QgYnl0ZXNQZXJQaXhlbCA9IGNvbG9ycyAqIDI7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBieXRlc1BlclBpeGVsOyArK2kpIHsKICAgICAgICBidWZmZXJbcG9zKytdID0gcmF3Qnl0ZXNbaV07CiAgICAgIH0KICAgICAgZm9yICg7IGkgPCByb3dCeXRlczsgaSArPSAyKSB7CiAgICAgICAgY29uc3Qgc3VtID0gKChyYXdCeXRlc1tpXSAmIDB4ZmYpIDw8IDgpICsgKHJhd0J5dGVzW2kgKyAxXSAmIDB4ZmYpICsgKChidWZmZXJbcG9zIC0gYnl0ZXNQZXJQaXhlbF0gJiAweGZmKSA8PCA4KSArIChidWZmZXJbcG9zIC0gYnl0ZXNQZXJQaXhlbCArIDFdICYgMHhmZik7CiAgICAgICAgYnVmZmVyW3BvcysrXSA9IHN1bSA+PiA4ICYgMHhmZjsKICAgICAgICBidWZmZXJbcG9zKytdID0gc3VtICYgMHhmZjsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgY29uc3QgY29tcEFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoY29sb3JzICsgMSk7CiAgICAgIGNvbnN0IGJpdE1hc2sgPSAoMSA8PCBiaXRzKSAtIDE7CiAgICAgIGxldCBqID0gMCwKICAgICAgICBrID0gYnVmZmVyTGVuZ3RoOwogICAgICBjb25zdCBjb2x1bW5zID0gdGhpcy5jb2x1bW5zOwogICAgICBmb3IgKGkgPSAwOyBpIDwgY29sdW1uczsgKytpKSB7CiAgICAgICAgZm9yIChsZXQga2sgPSAwOyBrayA8IGNvbG9yczsgKytraykgewogICAgICAgICAgaWYgKGluYml0cyA8IGJpdHMpIHsKICAgICAgICAgICAgaW5idWYgPSBpbmJ1ZiA8PCA4IHwgcmF3Qnl0ZXNbaisrXSAmIDB4ZmY7CiAgICAgICAgICAgIGluYml0cyArPSA4OwogICAgICAgICAgfQogICAgICAgICAgY29tcEFycmF5W2trXSA9IGNvbXBBcnJheVtra10gKyAoaW5idWYgPj4gaW5iaXRzIC0gYml0cykgJiBiaXRNYXNrOwogICAgICAgICAgaW5iaXRzIC09IGJpdHM7CiAgICAgICAgICBvdXRidWYgPSBvdXRidWYgPDwgYml0cyB8IGNvbXBBcnJheVtra107CiAgICAgICAgICBvdXRiaXRzICs9IGJpdHM7CiAgICAgICAgICBpZiAob3V0Yml0cyA+PSA4KSB7CiAgICAgICAgICAgIGJ1ZmZlcltrKytdID0gb3V0YnVmID4+IG91dGJpdHMgLSA4ICYgMHhmZjsKICAgICAgICAgICAgb3V0Yml0cyAtPSA4OwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBpZiAob3V0Yml0cyA+IDApIHsKICAgICAgICBidWZmZXJbaysrXSA9IChvdXRidWYgPDwgOCAtIG91dGJpdHMpICsgKGluYnVmICYgKDEgPDwgOCAtIG91dGJpdHMpIC0gMSk7CiAgICAgIH0KICAgIH0KICAgIHRoaXMuYnVmZmVyTGVuZ3RoICs9IHJvd0J5dGVzOwogIH0KICByZWFkQmxvY2tQbmcoKSB7CiAgICBjb25zdCByb3dCeXRlcyA9IHRoaXMucm93Qnl0ZXM7CiAgICBjb25zdCBwaXhCeXRlcyA9IHRoaXMucGl4Qnl0ZXM7CiAgICBjb25zdCBwcmVkaWN0b3IgPSB0aGlzLnN0ci5nZXRCeXRlKCk7CiAgICBjb25zdCByYXdCeXRlcyA9IHRoaXMuc3RyLmdldEJ5dGVzKHJvd0J5dGVzKTsKICAgIHRoaXMuZW9mID0gIXJhd0J5dGVzLmxlbmd0aDsKICAgIGlmICh0aGlzLmVvZikgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBidWZmZXJMZW5ndGggPSB0aGlzLmJ1ZmZlckxlbmd0aDsKICAgIGNvbnN0IGJ1ZmZlciA9IHRoaXMuZW5zdXJlQnVmZmVyKGJ1ZmZlckxlbmd0aCArIHJvd0J5dGVzKTsKICAgIGxldCBwcmV2Um93ID0gYnVmZmVyLnN1YmFycmF5KGJ1ZmZlckxlbmd0aCAtIHJvd0J5dGVzLCBidWZmZXJMZW5ndGgpOwogICAgaWYgKHByZXZSb3cubGVuZ3RoID09PSAwKSB7CiAgICAgIHByZXZSb3cgPSBuZXcgVWludDhBcnJheShyb3dCeXRlcyk7CiAgICB9CiAgICBsZXQgaSwKICAgICAgaiA9IGJ1ZmZlckxlbmd0aCwKICAgICAgdXAsCiAgICAgIGM7CiAgICBzd2l0Y2ggKHByZWRpY3RvcikgewogICAgICBjYXNlIDA6CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHJvd0J5dGVzOyArK2kpIHsKICAgICAgICAgIGJ1ZmZlcltqKytdID0gcmF3Qnl0ZXNbaV07CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDE6CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHBpeEJ5dGVzOyArK2kpIHsKICAgICAgICAgIGJ1ZmZlcltqKytdID0gcmF3Qnl0ZXNbaV07CiAgICAgICAgfQogICAgICAgIGZvciAoOyBpIDwgcm93Qnl0ZXM7ICsraSkgewogICAgICAgICAgYnVmZmVyW2pdID0gYnVmZmVyW2ogLSBwaXhCeXRlc10gKyByYXdCeXRlc1tpXSAmIDB4ZmY7CiAgICAgICAgICBqKys7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDI6CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHJvd0J5dGVzOyArK2kpIHsKICAgICAgICAgIGJ1ZmZlcltqKytdID0gcHJldlJvd1tpXSArIHJhd0J5dGVzW2ldICYgMHhmZjsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMzoKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcGl4Qnl0ZXM7ICsraSkgewogICAgICAgICAgYnVmZmVyW2orK10gPSAocHJldlJvd1tpXSA+PiAxKSArIHJhd0J5dGVzW2ldOwogICAgICAgIH0KICAgICAgICBmb3IgKDsgaSA8IHJvd0J5dGVzOyArK2kpIHsKICAgICAgICAgIGJ1ZmZlcltqXSA9IChwcmV2Um93W2ldICsgYnVmZmVyW2ogLSBwaXhCeXRlc10gPj4gMSkgKyByYXdCeXRlc1tpXSAmIDB4ZmY7CiAgICAgICAgICBqKys7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDQ6CiAgICAgICAgZm9yIChpID0gMDsgaSA8IHBpeEJ5dGVzOyArK2kpIHsKICAgICAgICAgIHVwID0gcHJldlJvd1tpXTsKICAgICAgICAgIGMgPSByYXdCeXRlc1tpXTsKICAgICAgICAgIGJ1ZmZlcltqKytdID0gdXAgKyBjOwogICAgICAgIH0KICAgICAgICBmb3IgKDsgaSA8IHJvd0J5dGVzOyArK2kpIHsKICAgICAgICAgIHVwID0gcHJldlJvd1tpXTsKICAgICAgICAgIGNvbnN0IHVwTGVmdCA9IHByZXZSb3dbaSAtIHBpeEJ5dGVzXTsKICAgICAgICAgIGNvbnN0IGxlZnQgPSBidWZmZXJbaiAtIHBpeEJ5dGVzXTsKICAgICAgICAgIGNvbnN0IHAgPSBsZWZ0ICsgdXAgLSB1cExlZnQ7CiAgICAgICAgICBsZXQgcGEgPSBwIC0gbGVmdDsKICAgICAgICAgIGlmIChwYSA8IDApIHsKICAgICAgICAgICAgcGEgPSAtcGE7CiAgICAgICAgICB9CiAgICAgICAgICBsZXQgcGIgPSBwIC0gdXA7CiAgICAgICAgICBpZiAocGIgPCAwKSB7CiAgICAgICAgICAgIHBiID0gLXBiOwogICAgICAgICAgfQogICAgICAgICAgbGV0IHBjID0gcCAtIHVwTGVmdDsKICAgICAgICAgIGlmIChwYyA8IDApIHsKICAgICAgICAgICAgcGMgPSAtcGM7CiAgICAgICAgICB9CiAgICAgICAgICBjID0gcmF3Qnl0ZXNbaV07CiAgICAgICAgICBpZiAocGEgPD0gcGIgJiYgcGEgPD0gcGMpIHsKICAgICAgICAgICAgYnVmZmVyW2orK10gPSBsZWZ0ICsgYzsKICAgICAgICAgIH0gZWxzZSBpZiAocGIgPD0gcGMpIHsKICAgICAgICAgICAgYnVmZmVyW2orK10gPSB1cCArIGM7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBidWZmZXJbaisrXSA9IHVwTGVmdCArIGM7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgVW5zdXBwb3J0ZWQgcHJlZGljdG9yOiAke3ByZWRpY3Rvcn1gKTsKICAgIH0KICAgIHRoaXMuYnVmZmVyTGVuZ3RoICs9IHJvd0J5dGVzOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvcnVuX2xlbmd0aF9zdHJlYW0uanMKCmNsYXNzIFJ1bkxlbmd0aFN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyLCBtYXliZUxlbmd0aCkgewogICAgc3VwZXIobWF5YmVMZW5ndGgpOwogICAgdGhpcy5zdHIgPSBzdHI7CiAgICB0aGlzLmRpY3QgPSBzdHIuZGljdDsKICB9CiAgcmVhZEJsb2NrKCkgewogICAgY29uc3QgcmVwZWF0SGVhZGVyID0gdGhpcy5zdHIuZ2V0Qnl0ZXMoMik7CiAgICBpZiAoIXJlcGVhdEhlYWRlciB8fCByZXBlYXRIZWFkZXIubGVuZ3RoIDwgMiB8fCByZXBlYXRIZWFkZXJbMF0gPT09IDEyOCkgewogICAgICB0aGlzLmVvZiA9IHRydWU7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGxldCBidWZmZXI7CiAgICBsZXQgYnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXJMZW5ndGg7CiAgICBsZXQgbiA9IHJlcGVhdEhlYWRlclswXTsKICAgIGlmIChuIDwgMTI4KSB7CiAgICAgIGJ1ZmZlciA9IHRoaXMuZW5zdXJlQnVmZmVyKGJ1ZmZlckxlbmd0aCArIG4gKyAxKTsKICAgICAgYnVmZmVyW2J1ZmZlckxlbmd0aCsrXSA9IHJlcGVhdEhlYWRlclsxXTsKICAgICAgaWYgKG4gPiAwKSB7CiAgICAgICAgY29uc3Qgc291cmNlID0gdGhpcy5zdHIuZ2V0Qnl0ZXMobik7CiAgICAgICAgYnVmZmVyLnNldChzb3VyY2UsIGJ1ZmZlckxlbmd0aCk7CiAgICAgICAgYnVmZmVyTGVuZ3RoICs9IG47CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIG4gPSAyNTcgLSBuOwogICAgICBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcihidWZmZXJMZW5ndGggKyBuICsgMSk7CiAgICAgIGJ1ZmZlci5maWxsKHJlcGVhdEhlYWRlclsxXSwgYnVmZmVyTGVuZ3RoLCBidWZmZXJMZW5ndGggKyBuKTsKICAgICAgYnVmZmVyTGVuZ3RoICs9IG47CiAgICB9CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IGJ1ZmZlckxlbmd0aDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3BhcnNlci5qcwoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKY29uc3QgTUFYX0xFTkdUSF9UT19DQUNIRSA9IDEwMDA7CmZ1bmN0aW9uIGdldElubGluZUltYWdlQ2FjaGVLZXkoYnl0ZXMpIHsKICBjb25zdCBzdHJCdWYgPSBbXSwKICAgIGlpID0gYnl0ZXMubGVuZ3RoOwogIGxldCBpID0gMDsKICB3aGlsZSAoaSA8IGlpIC0gMSkgewogICAgc3RyQnVmLnB1c2goYnl0ZXNbaSsrXSA8PCA4IHwgYnl0ZXNbaSsrXSk7CiAgfQogIGlmIChpIDwgaWkpIHsKICAgIHN0ckJ1Zi5wdXNoKGJ5dGVzW2ldKTsKICB9CiAgcmV0dXJuIGlpICsgIl8iICsgU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBzdHJCdWYpOwp9CmNsYXNzIFBhcnNlciB7CiAgY29uc3RydWN0b3IoewogICAgbGV4ZXIsCiAgICB4cmVmLAogICAgYWxsb3dTdHJlYW1zID0gZmFsc2UsCiAgICByZWNvdmVyeU1vZGUgPSBmYWxzZQogIH0pIHsKICAgIHRoaXMubGV4ZXIgPSBsZXhlcjsKICAgIHRoaXMueHJlZiA9IHhyZWY7CiAgICB0aGlzLmFsbG93U3RyZWFtcyA9IGFsbG93U3RyZWFtczsKICAgIHRoaXMucmVjb3ZlcnlNb2RlID0gcmVjb3ZlcnlNb2RlOwogICAgdGhpcy5pbWFnZUNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHRoaXMuX2ltYWdlSWQgPSAwOwogICAgdGhpcy5yZWZpbGwoKTsKICB9CiAgcmVmaWxsKCkgewogICAgdGhpcy5idWYxID0gdGhpcy5sZXhlci5nZXRPYmooKTsKICAgIHRoaXMuYnVmMiA9IHRoaXMubGV4ZXIuZ2V0T2JqKCk7CiAgfQogIHNoaWZ0KCkgewogICAgaWYgKHRoaXMuYnVmMiBpbnN0YW5jZW9mIENtZCAmJiB0aGlzLmJ1ZjIuY21kID09PSAiSUQiKSB7CiAgICAgIHRoaXMuYnVmMSA9IHRoaXMuYnVmMjsKICAgICAgdGhpcy5idWYyID0gbnVsbDsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuYnVmMSA9IHRoaXMuYnVmMjsKICAgICAgdGhpcy5idWYyID0gdGhpcy5sZXhlci5nZXRPYmooKTsKICAgIH0KICB9CiAgdHJ5U2hpZnQoKSB7CiAgICB0cnkgewogICAgICB0aGlzLnNoaWZ0KCk7CiAgICAgIHJldHVybiB0cnVlOwogICAgfSBjYXRjaCAoZSkgewogICAgICBpZiAoZSBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZTsKICAgICAgfQogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgfQogIGdldE9iaihjaXBoZXJUcmFuc2Zvcm0gPSBudWxsKSB7CiAgICBjb25zdCBidWYxID0gdGhpcy5idWYxOwogICAgdGhpcy5zaGlmdCgpOwogICAgaWYgKGJ1ZjEgaW5zdGFuY2VvZiBDbWQpIHsKICAgICAgc3dpdGNoIChidWYxLmNtZCkgewogICAgICAgIGNhc2UgIkJJIjoKICAgICAgICAgIHJldHVybiB0aGlzLm1ha2VJbmxpbmVJbWFnZShjaXBoZXJUcmFuc2Zvcm0pOwogICAgICAgIGNhc2UgIlsiOgogICAgICAgICAgY29uc3QgYXJyYXkgPSBbXTsKICAgICAgICAgIHdoaWxlICghaXNDbWQodGhpcy5idWYxLCAiXSIpICYmIHRoaXMuYnVmMSAhPT0gRU9GKSB7CiAgICAgICAgICAgIGFycmF5LnB1c2godGhpcy5nZXRPYmooY2lwaGVyVHJhbnNmb3JtKSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodGhpcy5idWYxID09PSBFT0YpIHsKICAgICAgICAgICAgaWYgKHRoaXMucmVjb3ZlcnlNb2RlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGFycmF5OwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRocm93IG5ldyBQYXJzZXJFT0ZFeGNlcHRpb24oIkVuZCBvZiBmaWxlIGluc2lkZSBhcnJheS4iKTsKICAgICAgICAgIH0KICAgICAgICAgIHRoaXMuc2hpZnQoKTsKICAgICAgICAgIHJldHVybiBhcnJheTsKICAgICAgICBjYXNlICI8PCI6CiAgICAgICAgICBjb25zdCBkaWN0ID0gbmV3IERpY3QodGhpcy54cmVmKTsKICAgICAgICAgIHdoaWxlICghaXNDbWQodGhpcy5idWYxLCAiPj4iKSAmJiB0aGlzLmJ1ZjEgIT09IEVPRikgewogICAgICAgICAgICBpZiAoISh0aGlzLmJ1ZjEgaW5zdGFuY2VvZiBOYW1lKSkgewogICAgICAgICAgICAgIGluZm8oIk1hbGZvcm1lZCBkaWN0aW9uYXJ5OiBrZXkgbXVzdCBiZSBhIG5hbWUgb2JqZWN0Iik7CiAgICAgICAgICAgICAgdGhpcy5zaGlmdCgpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGtleSA9IHRoaXMuYnVmMS5uYW1lOwogICAgICAgICAgICB0aGlzLnNoaWZ0KCk7CiAgICAgICAgICAgIGlmICh0aGlzLmJ1ZjEgPT09IEVPRikgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRpY3Quc2V0KGtleSwgdGhpcy5nZXRPYmooY2lwaGVyVHJhbnNmb3JtKSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodGhpcy5idWYxID09PSBFT0YpIHsKICAgICAgICAgICAgaWYgKHRoaXMucmVjb3ZlcnlNb2RlKSB7CiAgICAgICAgICAgICAgcmV0dXJuIGRpY3Q7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhyb3cgbmV3IFBhcnNlckVPRkV4Y2VwdGlvbigiRW5kIG9mIGZpbGUgaW5zaWRlIGRpY3Rpb25hcnkuIik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoaXNDbWQodGhpcy5idWYyLCAic3RyZWFtIikpIHsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWxsb3dTdHJlYW1zID8gdGhpcy5tYWtlU3RyZWFtKGRpY3QsIGNpcGhlclRyYW5zZm9ybSkgOiBkaWN0OwogICAgICAgICAgfQogICAgICAgICAgdGhpcy5zaGlmdCgpOwogICAgICAgICAgcmV0dXJuIGRpY3Q7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHJldHVybiBidWYxOwogICAgICB9CiAgICB9CiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihidWYxKSkgewogICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcih0aGlzLmJ1ZjEpICYmIGlzQ21kKHRoaXMuYnVmMiwgIlIiKSkgewogICAgICAgIGNvbnN0IHJlZiA9IFJlZi5nZXQoYnVmMSwgdGhpcy5idWYxKTsKICAgICAgICB0aGlzLnNoaWZ0KCk7CiAgICAgICAgdGhpcy5zaGlmdCgpOwogICAgICAgIHJldHVybiByZWY7CiAgICAgIH0KICAgICAgcmV0dXJuIGJ1ZjE7CiAgICB9CiAgICBpZiAodHlwZW9mIGJ1ZjEgPT09ICJzdHJpbmciKSB7CiAgICAgIGlmIChjaXBoZXJUcmFuc2Zvcm0pIHsKICAgICAgICByZXR1cm4gY2lwaGVyVHJhbnNmb3JtLmRlY3J5cHRTdHJpbmcoYnVmMSk7CiAgICAgIH0KICAgICAgcmV0dXJuIGJ1ZjE7CiAgICB9CiAgICByZXR1cm4gYnVmMTsKICB9CiAgZmluZERlZmF1bHRJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKSB7CiAgICBjb25zdCBFID0gMHg0NSwKICAgICAgSSA9IDB4NDksCiAgICAgIFNQQUNFID0gMHgyMCwKICAgICAgTEYgPSAweGEsCiAgICAgIENSID0gMHhkLAogICAgICBOVUwgPSAweDA7CiAgICBjb25zdCB7CiAgICAgICAga25vd25Db21tYW5kcwogICAgICB9ID0gdGhpcy5sZXhlciwKICAgICAgc3RhcnRQb3MgPSBzdHJlYW0ucG9zLAogICAgICBuID0gMTU7CiAgICBsZXQgc3RhdGUgPSAwLAogICAgICBjaCwKICAgICAgbWF5YmVFSVBvczsKICAgIHdoaWxlICgoY2ggPSBzdHJlYW0uZ2V0Qnl0ZSgpKSAhPT0gLTEpIHsKICAgICAgaWYgKHN0YXRlID09PSAwKSB7CiAgICAgICAgc3RhdGUgPSBjaCA9PT0gRSA/IDEgOiAwOwogICAgICB9IGVsc2UgaWYgKHN0YXRlID09PSAxKSB7CiAgICAgICAgc3RhdGUgPSBjaCA9PT0gSSA/IDIgOiAwOwogICAgICB9IGVsc2UgewogICAgICAgIGlmIChjaCA9PT0gU1BBQ0UgfHwgY2ggPT09IExGIHx8IGNoID09PSBDUikgewogICAgICAgICAgbWF5YmVFSVBvcyA9IHN0cmVhbS5wb3M7CiAgICAgICAgICBjb25zdCBmb2xsb3dpbmdCeXRlcyA9IHN0cmVhbS5wZWVrQnl0ZXMobik7CiAgICAgICAgICBjb25zdCBpaSA9IGZvbGxvd2luZ0J5dGVzLmxlbmd0aDsKICAgICAgICAgIGlmIChpaSA9PT0gMCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgICBjaCA9IGZvbGxvd2luZ0J5dGVzW2ldOwogICAgICAgICAgICBpZiAoY2ggPT09IE5VTCAmJiBmb2xsb3dpbmdCeXRlc1tpICsgMV0gIT09IE5VTCkgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChjaCAhPT0gTEYgJiYgY2ggIT09IENSICYmIChjaCA8IFNQQUNFIHx8IGNoID4gMHg3ZikpIHsKICAgICAgICAgICAgICBzdGF0ZSA9IDA7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChzdGF0ZSAhPT0gMikgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICgha25vd25Db21tYW5kcykgewogICAgICAgICAgICB3YXJuKCJmaW5kRGVmYXVsdElubGluZVN0cmVhbUVuZCAtIGBsZXhlci5rbm93bkNvbW1hbmRzYCBpcyB1bmRlZmluZWQuIik7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgdG1wTGV4ZXIgPSBuZXcgTGV4ZXIobmV3IFN0cmVhbShzdHJlYW0ucGVla0J5dGVzKDUgKiBuKSksIGtub3duQ29tbWFuZHMpOwogICAgICAgICAgdG1wTGV4ZXIuX2hleFN0cmluZ1dhcm4gPSAoKSA9PiB7fTsKICAgICAgICAgIGxldCBudW1BcmdzID0gMDsKICAgICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICAgIGNvbnN0IG5leHRPYmogPSB0bXBMZXhlci5nZXRPYmooKTsKICAgICAgICAgICAgaWYgKG5leHRPYmogPT09IEVPRikgewogICAgICAgICAgICAgIHN0YXRlID0gMDsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAobmV4dE9iaiBpbnN0YW5jZW9mIENtZCkgewogICAgICAgICAgICAgIGNvbnN0IGtub3duQ29tbWFuZCA9IGtub3duQ29tbWFuZHNbbmV4dE9iai5jbWRdOwogICAgICAgICAgICAgIGlmICgha25vd25Db21tYW5kKSB7CiAgICAgICAgICAgICAgICBzdGF0ZSA9IDA7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9IGVsc2UgaWYgKGtub3duQ29tbWFuZC52YXJpYWJsZUFyZ3MgPyBudW1BcmdzIDw9IGtub3duQ29tbWFuZC5udW1BcmdzIDogbnVtQXJncyA9PT0ga25vd25Db21tYW5kLm51bUFyZ3MpIHsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBudW1BcmdzID0gMDsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBudW1BcmdzKys7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoc3RhdGUgPT09IDIpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN0YXRlID0gMDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChjaCA9PT0gLTEpIHsKICAgICAgd2FybigiZmluZERlZmF1bHRJbmxpbmVTdHJlYW1FbmQ6ICIgKyAiUmVhY2hlZCB0aGUgZW5kIG9mIHRoZSBzdHJlYW0gd2l0aG91dCBmaW5kaW5nIGEgdmFsaWQgRUkgbWFya2VyIik7CiAgICAgIGlmIChtYXliZUVJUG9zKSB7CiAgICAgICAgd2FybignLi4uIHRyeWluZyB0byByZWNvdmVyIGJ5IHVzaW5nIHRoZSBsYXN0ICJFSSIgb2NjdXJyZW5jZS4nKTsKICAgICAgICBzdHJlYW0uc2tpcCgtKHN0cmVhbS5wb3MgLSBtYXliZUVJUG9zKSk7CiAgICAgIH0KICAgIH0KICAgIGxldCBlbmRPZmZzZXQgPSA0OwogICAgc3RyZWFtLnNraXAoLWVuZE9mZnNldCk7CiAgICBjaCA9IHN0cmVhbS5wZWVrQnl0ZSgpOwogICAgc3RyZWFtLnNraXAoZW5kT2Zmc2V0KTsKICAgIGlmICghaXNXaGl0ZVNwYWNlKGNoKSkgewogICAgICBlbmRPZmZzZXQtLTsKICAgIH0KICAgIHJldHVybiBzdHJlYW0ucG9zIC0gZW5kT2Zmc2V0IC0gc3RhcnRQb3M7CiAgfQogIGZpbmREQ1REZWNvZGVJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKSB7CiAgICBjb25zdCBzdGFydFBvcyA9IHN0cmVhbS5wb3M7CiAgICBsZXQgZm91bmRFT0kgPSBmYWxzZSwKICAgICAgYiwKICAgICAgbWFya2VyTGVuZ3RoOwogICAgd2hpbGUgKChiID0gc3RyZWFtLmdldEJ5dGUoKSkgIT09IC0xKSB7CiAgICAgIGlmIChiICE9PSAweGZmKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgc3dpdGNoIChzdHJlYW0uZ2V0Qnl0ZSgpKSB7CiAgICAgICAgY2FzZSAweDAwOgogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGZmOgogICAgICAgICAgc3RyZWFtLnNraXAoLTEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGQ5OgogICAgICAgICAgZm91bmRFT0kgPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweGMwOgogICAgICAgIGNhc2UgMHhjMToKICAgICAgICBjYXNlIDB4YzI6CiAgICAgICAgY2FzZSAweGMzOgogICAgICAgIGNhc2UgMHhjNToKICAgICAgICBjYXNlIDB4YzY6CiAgICAgICAgY2FzZSAweGM3OgogICAgICAgIGNhc2UgMHhjOToKICAgICAgICBjYXNlIDB4Y2E6CiAgICAgICAgY2FzZSAweGNiOgogICAgICAgIGNhc2UgMHhjZDoKICAgICAgICBjYXNlIDB4Y2U6CiAgICAgICAgY2FzZSAweGNmOgogICAgICAgIGNhc2UgMHhjNDoKICAgICAgICBjYXNlIDB4Y2M6CiAgICAgICAgY2FzZSAweGRhOgogICAgICAgIGNhc2UgMHhkYjoKICAgICAgICBjYXNlIDB4ZGM6CiAgICAgICAgY2FzZSAweGRkOgogICAgICAgIGNhc2UgMHhkZToKICAgICAgICBjYXNlIDB4ZGY6CiAgICAgICAgY2FzZSAweGUwOgogICAgICAgIGNhc2UgMHhlMToKICAgICAgICBjYXNlIDB4ZTI6CiAgICAgICAgY2FzZSAweGUzOgogICAgICAgIGNhc2UgMHhlNDoKICAgICAgICBjYXNlIDB4ZTU6CiAgICAgICAgY2FzZSAweGU2OgogICAgICAgIGNhc2UgMHhlNzoKICAgICAgICBjYXNlIDB4ZTg6CiAgICAgICAgY2FzZSAweGU5OgogICAgICAgIGNhc2UgMHhlYToKICAgICAgICBjYXNlIDB4ZWI6CiAgICAgICAgY2FzZSAweGVjOgogICAgICAgIGNhc2UgMHhlZDoKICAgICAgICBjYXNlIDB4ZWU6CiAgICAgICAgY2FzZSAweGVmOgogICAgICAgIGNhc2UgMHhmZToKICAgICAgICAgIG1hcmtlckxlbmd0aCA9IHN0cmVhbS5nZXRVaW50MTYoKTsKICAgICAgICAgIGlmIChtYXJrZXJMZW5ndGggPiAyKSB7CiAgICAgICAgICAgIHN0cmVhbS5za2lwKG1hcmtlckxlbmd0aCAtIDIpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgc3RyZWFtLnNraXAoLTIpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKGZvdW5kRU9JKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGxlbmd0aCA9IHN0cmVhbS5wb3MgLSBzdGFydFBvczsKICAgIGlmIChiID09PSAtMSkgewogICAgICB3YXJuKCJJbmxpbmUgRENURGVjb2RlIGltYWdlIHN0cmVhbTogIiArICJFT0kgbWFya2VyIG5vdCBmb3VuZCwgc2VhcmNoaW5nIGZvciAvRUkvIGluc3RlYWQuIik7CiAgICAgIHN0cmVhbS5za2lwKC1sZW5ndGgpOwogICAgICByZXR1cm4gdGhpcy5maW5kRGVmYXVsdElubGluZVN0cmVhbUVuZChzdHJlYW0pOwogICAgfQogICAgdGhpcy5pbmxpbmVTdHJlYW1Ta2lwRUkoc3RyZWFtKTsKICAgIHJldHVybiBsZW5ndGg7CiAgfQogIGZpbmRBU0NJSTg1RGVjb2RlSW5saW5lU3RyZWFtRW5kKHN0cmVhbSkgewogICAgY29uc3QgVElMREUgPSAweDdlLAogICAgICBHVCA9IDB4M2U7CiAgICBjb25zdCBzdGFydFBvcyA9IHN0cmVhbS5wb3M7CiAgICBsZXQgY2g7CiAgICB3aGlsZSAoKGNoID0gc3RyZWFtLmdldEJ5dGUoKSkgIT09IC0xKSB7CiAgICAgIGlmIChjaCA9PT0gVElMREUpIHsKICAgICAgICBjb25zdCB0aWxkZVBvcyA9IHN0cmVhbS5wb3M7CiAgICAgICAgY2ggPSBzdHJlYW0ucGVla0J5dGUoKTsKICAgICAgICB3aGlsZSAoaXNXaGl0ZVNwYWNlKGNoKSkgewogICAgICAgICAgc3RyZWFtLnNraXAoKTsKICAgICAgICAgIGNoID0gc3RyZWFtLnBlZWtCeXRlKCk7CiAgICAgICAgfQogICAgICAgIGlmIChjaCA9PT0gR1QpIHsKICAgICAgICAgIHN0cmVhbS5za2lwKCk7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgaWYgKHN0cmVhbS5wb3MgPiB0aWxkZVBvcykgewogICAgICAgICAgY29uc3QgbWF5YmVFSSA9IHN0cmVhbS5wZWVrQnl0ZXMoMik7CiAgICAgICAgICBpZiAobWF5YmVFSVswXSA9PT0gMHg0NSAmJiBtYXliZUVJWzFdID09PSAweDQ5KSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfQogICAgY29uc3QgbGVuZ3RoID0gc3RyZWFtLnBvcyAtIHN0YXJ0UG9zOwogICAgaWYgKGNoID09PSAtMSkgewogICAgICB3YXJuKCJJbmxpbmUgQVNDSUk4NURlY29kZSBpbWFnZSBzdHJlYW06ICIgKyAiRU9EIG1hcmtlciBub3QgZm91bmQsIHNlYXJjaGluZyBmb3IgL0VJLyBpbnN0ZWFkLiIpOwogICAgICBzdHJlYW0uc2tpcCgtbGVuZ3RoKTsKICAgICAgcmV0dXJuIHRoaXMuZmluZERlZmF1bHRJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKTsKICAgIH0KICAgIHRoaXMuaW5saW5lU3RyZWFtU2tpcEVJKHN0cmVhbSk7CiAgICByZXR1cm4gbGVuZ3RoOwogIH0KICBmaW5kQVNDSUlIZXhEZWNvZGVJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKSB7CiAgICBjb25zdCBHVCA9IDB4M2U7CiAgICBjb25zdCBzdGFydFBvcyA9IHN0cmVhbS5wb3M7CiAgICBsZXQgY2g7CiAgICB3aGlsZSAoKGNoID0gc3RyZWFtLmdldEJ5dGUoKSkgIT09IC0xKSB7CiAgICAgIGlmIChjaCA9PT0gR1QpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgY29uc3QgbGVuZ3RoID0gc3RyZWFtLnBvcyAtIHN0YXJ0UG9zOwogICAgaWYgKGNoID09PSAtMSkgewogICAgICB3YXJuKCJJbmxpbmUgQVNDSUlIZXhEZWNvZGUgaW1hZ2Ugc3RyZWFtOiAiICsgIkVPRCBtYXJrZXIgbm90IGZvdW5kLCBzZWFyY2hpbmcgZm9yIC9FSS8gaW5zdGVhZC4iKTsKICAgICAgc3RyZWFtLnNraXAoLWxlbmd0aCk7CiAgICAgIHJldHVybiB0aGlzLmZpbmREZWZhdWx0SW5saW5lU3RyZWFtRW5kKHN0cmVhbSk7CiAgICB9CiAgICB0aGlzLmlubGluZVN0cmVhbVNraXBFSShzdHJlYW0pOwogICAgcmV0dXJuIGxlbmd0aDsKICB9CiAgaW5saW5lU3RyZWFtU2tpcEVJKHN0cmVhbSkgewogICAgY29uc3QgRSA9IDB4NDUsCiAgICAgIEkgPSAweDQ5OwogICAgbGV0IHN0YXRlID0gMCwKICAgICAgY2g7CiAgICB3aGlsZSAoKGNoID0gc3RyZWFtLmdldEJ5dGUoKSkgIT09IC0xKSB7CiAgICAgIGlmIChzdGF0ZSA9PT0gMCkgewogICAgICAgIHN0YXRlID0gY2ggPT09IEUgPyAxIDogMDsKICAgICAgfSBlbHNlIGlmIChzdGF0ZSA9PT0gMSkgewogICAgICAgIHN0YXRlID0gY2ggPT09IEkgPyAyIDogMDsKICAgICAgfSBlbHNlIGlmIChzdGF0ZSA9PT0gMikgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQogIG1ha2VJbmxpbmVJbWFnZShjaXBoZXJUcmFuc2Zvcm0pIHsKICAgIGNvbnN0IGxleGVyID0gdGhpcy5sZXhlcjsKICAgIGNvbnN0IHN0cmVhbSA9IGxleGVyLnN0cmVhbTsKICAgIGNvbnN0IGRpY3RNYXAgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgbGV0IGRpY3RMZW5ndGg7CiAgICB3aGlsZSAoIWlzQ21kKHRoaXMuYnVmMSwgIklEIikgJiYgdGhpcy5idWYxICE9PSBFT0YpIHsKICAgICAgaWYgKCEodGhpcy5idWYxIGluc3RhbmNlb2YgTmFtZSkpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkRpY3Rpb25hcnkga2V5IG11c3QgYmUgYSBuYW1lIG9iamVjdCIpOwogICAgICB9CiAgICAgIGNvbnN0IGtleSA9IHRoaXMuYnVmMS5uYW1lOwogICAgICB0aGlzLnNoaWZ0KCk7CiAgICAgIGlmICh0aGlzLmJ1ZjEgPT09IEVPRikgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGRpY3RNYXBba2V5XSA9IHRoaXMuZ2V0T2JqKGNpcGhlclRyYW5zZm9ybSk7CiAgICB9CiAgICBpZiAobGV4ZXIuYmVnaW5JbmxpbmVJbWFnZVBvcyAhPT0gLTEpIHsKICAgICAgZGljdExlbmd0aCA9IHN0cmVhbS5wb3MgLSBsZXhlci5iZWdpbklubGluZUltYWdlUG9zOwogICAgfQogICAgY29uc3QgZmlsdGVyID0gdGhpcy54cmVmLmZldGNoSWZSZWYoZGljdE1hcC5GIHx8IGRpY3RNYXAuRmlsdGVyKTsKICAgIGxldCBmaWx0ZXJOYW1lOwogICAgaWYgKGZpbHRlciBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgZmlsdGVyTmFtZSA9IGZpbHRlci5uYW1lOwogICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGZpbHRlcikpIHsKICAgICAgY29uc3QgZmlsdGVyWmVybyA9IHRoaXMueHJlZi5mZXRjaElmUmVmKGZpbHRlclswXSk7CiAgICAgIGlmIChmaWx0ZXJaZXJvIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgIGZpbHRlck5hbWUgPSBmaWx0ZXJaZXJvLm5hbWU7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHN0YXJ0UG9zID0gc3RyZWFtLnBvczsKICAgIGxldCBsZW5ndGg7CiAgICBzd2l0Y2ggKGZpbHRlck5hbWUpIHsKICAgICAgY2FzZSAiRENUIjoKICAgICAgY2FzZSAiRENURGVjb2RlIjoKICAgICAgICBsZW5ndGggPSB0aGlzLmZpbmREQ1REZWNvZGVJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiQTg1IjoKICAgICAgY2FzZSAiQVNDSUk4NURlY29kZSI6CiAgICAgICAgbGVuZ3RoID0gdGhpcy5maW5kQVNDSUk4NURlY29kZUlubGluZVN0cmVhbUVuZChzdHJlYW0pOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJBSHgiOgogICAgICBjYXNlICJBU0NJSUhleERlY29kZSI6CiAgICAgICAgbGVuZ3RoID0gdGhpcy5maW5kQVNDSUlIZXhEZWNvZGVJbmxpbmVTdHJlYW1FbmQoc3RyZWFtKTsKICAgICAgICBicmVhazsKICAgICAgZGVmYXVsdDoKICAgICAgICBsZW5ndGggPSB0aGlzLmZpbmREZWZhdWx0SW5saW5lU3RyZWFtRW5kKHN0cmVhbSk7CiAgICB9CiAgICBsZXQgY2FjaGVLZXk7CiAgICBpZiAobGVuZ3RoIDwgTUFYX0xFTkdUSF9UT19DQUNIRSAmJiBkaWN0TGVuZ3RoID4gMCkgewogICAgICBjb25zdCBpbml0aWFsU3RyZWFtUG9zID0gc3RyZWFtLnBvczsKICAgICAgc3RyZWFtLnBvcyA9IGxleGVyLmJlZ2luSW5saW5lSW1hZ2VQb3M7CiAgICAgIGNhY2hlS2V5ID0gZ2V0SW5saW5lSW1hZ2VDYWNoZUtleShzdHJlYW0uZ2V0Qnl0ZXMoZGljdExlbmd0aCArIGxlbmd0aCkpOwogICAgICBzdHJlYW0ucG9zID0gaW5pdGlhbFN0cmVhbVBvczsKICAgICAgY29uc3QgY2FjaGVFbnRyeSA9IHRoaXMuaW1hZ2VDYWNoZVtjYWNoZUtleV07CiAgICAgIGlmIChjYWNoZUVudHJ5ICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB0aGlzLmJ1ZjIgPSBDbWQuZ2V0KCJFSSIpOwogICAgICAgIHRoaXMuc2hpZnQoKTsKICAgICAgICBjYWNoZUVudHJ5LnJlc2V0KCk7CiAgICAgICAgcmV0dXJuIGNhY2hlRW50cnk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGRpY3QgPSBuZXcgRGljdCh0aGlzLnhyZWYpOwogICAgZm9yIChjb25zdCBrZXkgaW4gZGljdE1hcCkgewogICAgICBkaWN0LnNldChrZXksIGRpY3RNYXBba2V5XSk7CiAgICB9CiAgICBsZXQgaW1hZ2VTdHJlYW0gPSBzdHJlYW0ubWFrZVN1YlN0cmVhbShzdGFydFBvcywgbGVuZ3RoLCBkaWN0KTsKICAgIGlmIChjaXBoZXJUcmFuc2Zvcm0pIHsKICAgICAgaW1hZ2VTdHJlYW0gPSBjaXBoZXJUcmFuc2Zvcm0uY3JlYXRlU3RyZWFtKGltYWdlU3RyZWFtLCBsZW5ndGgpOwogICAgfQogICAgaW1hZ2VTdHJlYW0gPSB0aGlzLmZpbHRlcihpbWFnZVN0cmVhbSwgZGljdCwgbGVuZ3RoKTsKICAgIGltYWdlU3RyZWFtLmRpY3QgPSBkaWN0OwogICAgaWYgKGNhY2hlS2V5ICE9PSB1bmRlZmluZWQpIHsKICAgICAgaW1hZ2VTdHJlYW0uY2FjaGVLZXkgPSBgaW5saW5lX2ltZ18keysrdGhpcy5faW1hZ2VJZH1gOwogICAgICB0aGlzLmltYWdlQ2FjaGVbY2FjaGVLZXldID0gaW1hZ2VTdHJlYW07CiAgICB9CiAgICB0aGlzLmJ1ZjIgPSBDbWQuZ2V0KCJFSSIpOwogICAgdGhpcy5zaGlmdCgpOwogICAgcmV0dXJuIGltYWdlU3RyZWFtOwogIH0KICAjZmluZFN0cmVhbUxlbmd0aChzdGFydFBvcykgewogICAgY29uc3QgewogICAgICBzdHJlYW0KICAgIH0gPSB0aGlzLmxleGVyOwogICAgc3RyZWFtLnBvcyA9IHN0YXJ0UG9zOwogICAgY29uc3QgU0NBTl9CTE9DS19MRU5HVEggPSAyMDQ4OwogICAgY29uc3Qgc2lnbmF0dXJlTGVuZ3RoID0gImVuZHN0cmVhbSIubGVuZ3RoOwogICAgY29uc3QgRU5EX1NJR05BVFVSRSA9IG5ldyBVaW50OEFycmF5KFsweDY1LCAweDZlLCAweDY0XSk7CiAgICBjb25zdCBlbmRMZW5ndGggPSBFTkRfU0lHTkFUVVJFLmxlbmd0aDsKICAgIGNvbnN0IFBBUlRJQUxfU0lHTkFUVVJFID0gW25ldyBVaW50OEFycmF5KFsweDczLCAweDc0LCAweDcyLCAweDY1LCAweDYxLCAweDZkXSksIG5ldyBVaW50OEFycmF5KFsweDczLCAweDc0LCAweDY1LCAweDYxLCAweDZkXSksIG5ldyBVaW50OEFycmF5KFsweDczLCAweDc0LCAweDcyLCAweDY1LCAweDYxXSldOwogICAgY29uc3Qgbm9ybWFsTGVuZ3RoID0gc2lnbmF0dXJlTGVuZ3RoIC0gZW5kTGVuZ3RoOwogICAgd2hpbGUgKHN0cmVhbS5wb3MgPCBzdHJlYW0uZW5kKSB7CiAgICAgIGNvbnN0IHNjYW5CeXRlcyA9IHN0cmVhbS5wZWVrQnl0ZXMoU0NBTl9CTE9DS19MRU5HVEgpOwogICAgICBjb25zdCBzY2FuTGVuZ3RoID0gc2NhbkJ5dGVzLmxlbmd0aCAtIHNpZ25hdHVyZUxlbmd0aDsKICAgICAgaWYgKHNjYW5MZW5ndGggPD0gMCkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGxldCBwb3MgPSAwOwogICAgICB3aGlsZSAocG9zIDwgc2Nhbkxlbmd0aCkgewogICAgICAgIGxldCBqID0gMDsKICAgICAgICB3aGlsZSAoaiA8IGVuZExlbmd0aCAmJiBzY2FuQnl0ZXNbcG9zICsgal0gPT09IEVORF9TSUdOQVRVUkVbal0pIHsKICAgICAgICAgIGorKzsKICAgICAgICB9CiAgICAgICAgaWYgKGogPj0gZW5kTGVuZ3RoKSB7CiAgICAgICAgICBsZXQgZm91bmQgPSBmYWxzZTsKICAgICAgICAgIGZvciAoY29uc3QgcGFydCBvZiBQQVJUSUFMX1NJR05BVFVSRSkgewogICAgICAgICAgICBjb25zdCBwYXJ0TGVuID0gcGFydC5sZW5ndGg7CiAgICAgICAgICAgIGxldCBrID0gMDsKICAgICAgICAgICAgd2hpbGUgKGsgPCBwYXJ0TGVuICYmIHNjYW5CeXRlc1twb3MgKyBqICsga10gPT09IHBhcnRba10pIHsKICAgICAgICAgICAgICBrKys7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGsgPj0gbm9ybWFsTGVuZ3RoKSB7CiAgICAgICAgICAgICAgZm91bmQgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChrID49IHBhcnRMZW4pIHsKICAgICAgICAgICAgICBjb25zdCBsYXN0Qnl0ZSA9IHNjYW5CeXRlc1twb3MgKyBqICsga107CiAgICAgICAgICAgICAgaWYgKGlzV2hpdGVTcGFjZShsYXN0Qnl0ZSkpIHsKICAgICAgICAgICAgICAgIGluZm8oYEZvdW5kICIke2J5dGVzVG9TdHJpbmcoWy4uLkVORF9TSUdOQVRVUkUsIC4uLnBhcnRdKX0iIHdoZW4gYCArICJzZWFyY2hpbmcgZm9yIGVuZHN0cmVhbSBjb21tYW5kLiIpOwogICAgICAgICAgICAgICAgZm91bmQgPSB0cnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgaWYgKGZvdW5kKSB7CiAgICAgICAgICAgIHN0cmVhbS5wb3MgKz0gcG9zOwogICAgICAgICAgICByZXR1cm4gc3RyZWFtLnBvcyAtIHN0YXJ0UG9zOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBwb3MrKzsKICAgICAgfQogICAgICBzdHJlYW0ucG9zICs9IHNjYW5MZW5ndGg7CiAgICB9CiAgICByZXR1cm4gLTE7CiAgfQogIG1ha2VTdHJlYW0oZGljdCwgY2lwaGVyVHJhbnNmb3JtKSB7CiAgICBjb25zdCBsZXhlciA9IHRoaXMubGV4ZXI7CiAgICBsZXQgc3RyZWFtID0gbGV4ZXIuc3RyZWFtOwogICAgbGV4ZXIuc2tpcFRvTmV4dExpbmUoKTsKICAgIGNvbnN0IHN0YXJ0UG9zID0gc3RyZWFtLnBvcyAtIDE7CiAgICBsZXQgbGVuZ3RoID0gZGljdC5nZXQoIkxlbmd0aCIpOwogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGxlbmd0aCkpIHsKICAgICAgaW5mbyhgQmFkIGxlbmd0aCAiJHtsZW5ndGggJiYgbGVuZ3RoLnRvU3RyaW5nKCl9IiBpbiBzdHJlYW0uYCk7CiAgICAgIGxlbmd0aCA9IDA7CiAgICB9CiAgICBzdHJlYW0ucG9zID0gc3RhcnRQb3MgKyBsZW5ndGg7CiAgICBsZXhlci5uZXh0Q2hhcigpOwogICAgaWYgKHRoaXMudHJ5U2hpZnQoKSAmJiBpc0NtZCh0aGlzLmJ1ZjIsICJlbmRzdHJlYW0iKSkgewogICAgICB0aGlzLnNoaWZ0KCk7CiAgICB9IGVsc2UgewogICAgICBsZW5ndGggPSB0aGlzLiNmaW5kU3RyZWFtTGVuZ3RoKHN0YXJ0UG9zKTsKICAgICAgaWYgKGxlbmd0aCA8IDApIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIk1pc3NpbmcgZW5kc3RyZWFtIGNvbW1hbmQuIik7CiAgICAgIH0KICAgICAgbGV4ZXIubmV4dENoYXIoKTsKICAgICAgdGhpcy5zaGlmdCgpOwogICAgICB0aGlzLnNoaWZ0KCk7CiAgICB9CiAgICB0aGlzLnNoaWZ0KCk7CiAgICBzdHJlYW0gPSBzdHJlYW0ubWFrZVN1YlN0cmVhbShzdGFydFBvcywgbGVuZ3RoLCBkaWN0KTsKICAgIGlmIChjaXBoZXJUcmFuc2Zvcm0pIHsKICAgICAgc3RyZWFtID0gY2lwaGVyVHJhbnNmb3JtLmNyZWF0ZVN0cmVhbShzdHJlYW0sIGxlbmd0aCk7CiAgICB9CiAgICBzdHJlYW0gPSB0aGlzLmZpbHRlcihzdHJlYW0sIGRpY3QsIGxlbmd0aCk7CiAgICBzdHJlYW0uZGljdCA9IGRpY3Q7CiAgICByZXR1cm4gc3RyZWFtOwogIH0KICBmaWx0ZXIoc3RyZWFtLCBkaWN0LCBsZW5ndGgpIHsKICAgIGxldCBmaWx0ZXIgPSBkaWN0LmdldCgiRiIsICJGaWx0ZXIiKTsKICAgIGxldCBwYXJhbXMgPSBkaWN0LmdldCgiRFAiLCAiRGVjb2RlUGFybXMiKTsKICAgIGlmIChmaWx0ZXIgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KHBhcmFtcykpIHsKICAgICAgICB3YXJuKCIvRGVjb2RlUGFybXMgc2hvdWxkIG5vdCBiZSBhbiBBcnJheSwgd2hlbiAvRmlsdGVyIGlzIGEgTmFtZS4iKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5tYWtlRmlsdGVyKHN0cmVhbSwgZmlsdGVyLm5hbWUsIGxlbmd0aCwgcGFyYW1zKTsKICAgIH0KICAgIGxldCBtYXliZUxlbmd0aCA9IGxlbmd0aDsKICAgIGlmIChBcnJheS5pc0FycmF5KGZpbHRlcikpIHsKICAgICAgY29uc3QgZmlsdGVyQXJyYXkgPSBmaWx0ZXI7CiAgICAgIGNvbnN0IHBhcmFtc0FycmF5ID0gcGFyYW1zOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBmaWx0ZXJBcnJheS5sZW5ndGg7IGkgPCBpaTsgKytpKSB7CiAgICAgICAgZmlsdGVyID0gdGhpcy54cmVmLmZldGNoSWZSZWYoZmlsdGVyQXJyYXlbaV0pOwogICAgICAgIGlmICghKGZpbHRlciBpbnN0YW5jZW9mIE5hbWUpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEJhZCBmaWx0ZXIgbmFtZSAiJHtmaWx0ZXJ9ImApOwogICAgICAgIH0KICAgICAgICBwYXJhbXMgPSBudWxsOwogICAgICAgIGlmIChBcnJheS5pc0FycmF5KHBhcmFtc0FycmF5KSAmJiBpIGluIHBhcmFtc0FycmF5KSB7CiAgICAgICAgICBwYXJhbXMgPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihwYXJhbXNBcnJheVtpXSk7CiAgICAgICAgfQogICAgICAgIHN0cmVhbSA9IHRoaXMubWFrZUZpbHRlcihzdHJlYW0sIGZpbHRlci5uYW1lLCBtYXliZUxlbmd0aCwgcGFyYW1zKTsKICAgICAgICBtYXliZUxlbmd0aCA9IG51bGw7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzdHJlYW07CiAgfQogIG1ha2VGaWx0ZXIoc3RyZWFtLCBuYW1lLCBtYXliZUxlbmd0aCwgcGFyYW1zKSB7CiAgICBpZiAobWF5YmVMZW5ndGggPT09IDApIHsKICAgICAgd2FybihgRW1wdHkgIiR7bmFtZX0iIHN0cmVhbS5gKTsKICAgICAgcmV0dXJuIG5ldyBOdWxsU3RyZWFtKCk7CiAgICB9CiAgICB0cnkgewogICAgICBzd2l0Y2ggKG5hbWUpIHsKICAgICAgICBjYXNlICJGbCI6CiAgICAgICAgY2FzZSAiRmxhdGVEZWNvZGUiOgogICAgICAgICAgaWYgKHBhcmFtcykgewogICAgICAgICAgICByZXR1cm4gbmV3IFByZWRpY3RvclN0cmVhbShuZXcgRmxhdGVTdHJlYW0oc3RyZWFtLCBtYXliZUxlbmd0aCksIG1heWJlTGVuZ3RoLCBwYXJhbXMpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIG5ldyBGbGF0ZVN0cmVhbShzdHJlYW0sIG1heWJlTGVuZ3RoKTsKICAgICAgICBjYXNlICJMWlciOgogICAgICAgIGNhc2UgIkxaV0RlY29kZSI6CiAgICAgICAgICBsZXQgZWFybHlDaGFuZ2UgPSAxOwogICAgICAgICAgaWYgKHBhcmFtcykgewogICAgICAgICAgICBpZiAocGFyYW1zLmhhcygiRWFybHlDaGFuZ2UiKSkgewogICAgICAgICAgICAgIGVhcmx5Q2hhbmdlID0gcGFyYW1zLmdldCgiRWFybHlDaGFuZ2UiKTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gbmV3IFByZWRpY3RvclN0cmVhbShuZXcgTFpXU3RyZWFtKHN0cmVhbSwgbWF5YmVMZW5ndGgsIGVhcmx5Q2hhbmdlKSwgbWF5YmVMZW5ndGgsIHBhcmFtcyk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gbmV3IExaV1N0cmVhbShzdHJlYW0sIG1heWJlTGVuZ3RoLCBlYXJseUNoYW5nZSk7CiAgICAgICAgY2FzZSAiRENUIjoKICAgICAgICBjYXNlICJEQ1REZWNvZGUiOgogICAgICAgICAgcmV0dXJuIG5ldyBKcGVnU3RyZWFtKHN0cmVhbSwgbWF5YmVMZW5ndGgsIHBhcmFtcyk7CiAgICAgICAgY2FzZSAiSlBYIjoKICAgICAgICBjYXNlICJKUFhEZWNvZGUiOgogICAgICAgICAgcmV0dXJuIG5ldyBKcHhTdHJlYW0oc3RyZWFtLCBtYXliZUxlbmd0aCwgcGFyYW1zKTsKICAgICAgICBjYXNlICJBODUiOgogICAgICAgIGNhc2UgIkFTQ0lJODVEZWNvZGUiOgogICAgICAgICAgcmV0dXJuIG5ldyBBc2NpaTg1U3RyZWFtKHN0cmVhbSwgbWF5YmVMZW5ndGgpOwogICAgICAgIGNhc2UgIkFIeCI6CiAgICAgICAgY2FzZSAiQVNDSUlIZXhEZWNvZGUiOgogICAgICAgICAgcmV0dXJuIG5ldyBBc2NpaUhleFN0cmVhbShzdHJlYW0sIG1heWJlTGVuZ3RoKTsKICAgICAgICBjYXNlICJDQ0YiOgogICAgICAgIGNhc2UgIkNDSVRURmF4RGVjb2RlIjoKICAgICAgICAgIHJldHVybiBuZXcgQ0NJVFRGYXhTdHJlYW0oc3RyZWFtLCBtYXliZUxlbmd0aCwgcGFyYW1zKTsKICAgICAgICBjYXNlICJSTCI6CiAgICAgICAgY2FzZSAiUnVuTGVuZ3RoRGVjb2RlIjoKICAgICAgICAgIHJldHVybiBuZXcgUnVuTGVuZ3RoU3RyZWFtKHN0cmVhbSwgbWF5YmVMZW5ndGgpOwogICAgICAgIGNhc2UgIkpCSUcyRGVjb2RlIjoKICAgICAgICAgIHJldHVybiBuZXcgSmJpZzJTdHJlYW0oc3RyZWFtLCBtYXliZUxlbmd0aCwgcGFyYW1zKTsKICAgICAgfQogICAgICB3YXJuKGBGaWx0ZXIgIiR7bmFtZX0iIGlzIG5vdCBzdXBwb3J0ZWQuYCk7CiAgICAgIHJldHVybiBzdHJlYW07CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoZXggaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIHdhcm4oYEludmFsaWQgc3RyZWFtOiAiJHtleH0iYCk7CiAgICAgIHJldHVybiBuZXcgTnVsbFN0cmVhbSgpOwogICAgfQogIH0KfQpjb25zdCBzcGVjaWFsQ2hhcnMgPSBbMSwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMSwgMSwgMCwgMSwgMSwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMSwgMCwgMCwgMCwgMCwgMiwgMCwgMCwgMiwgMiwgMCwgMCwgMCwgMCwgMCwgMiwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMiwgMCwgMiwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMiwgMCwgMiwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMiwgMCwgMiwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMCwgMF07CmZ1bmN0aW9uIHRvSGV4RGlnaXQoY2gpIHsKICBpZiAoY2ggPj0gMHgzMCAmJiBjaCA8PSAweDM5KSB7CiAgICByZXR1cm4gY2ggJiAweDBmOwogIH0KICBpZiAoY2ggPj0gMHg0MSAmJiBjaCA8PSAweDQ2IHx8IGNoID49IDB4NjEgJiYgY2ggPD0gMHg2NikgewogICAgcmV0dXJuIChjaCAmIDB4MGYpICsgOTsKICB9CiAgcmV0dXJuIC0xOwp9CmNsYXNzIExleGVyIHsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIGtub3duQ29tbWFuZHMgPSBudWxsKSB7CiAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTsKICAgIHRoaXMubmV4dENoYXIoKTsKICAgIHRoaXMuc3RyQnVmID0gW107CiAgICB0aGlzLmtub3duQ29tbWFuZHMgPSBrbm93bkNvbW1hbmRzOwogICAgdGhpcy5faGV4U3RyaW5nTnVtV2FybiA9IDA7CiAgICB0aGlzLmJlZ2luSW5saW5lSW1hZ2VQb3MgPSAtMTsKICB9CiAgbmV4dENoYXIoKSB7CiAgICByZXR1cm4gdGhpcy5jdXJyZW50Q2hhciA9IHRoaXMuc3RyZWFtLmdldEJ5dGUoKTsKICB9CiAgcGVla0NoYXIoKSB7CiAgICByZXR1cm4gdGhpcy5zdHJlYW0ucGVla0J5dGUoKTsKICB9CiAgZ2V0TnVtYmVyKCkgewogICAgbGV0IGNoID0gdGhpcy5jdXJyZW50Q2hhcjsKICAgIGxldCBlTm90YXRpb24gPSBmYWxzZTsKICAgIGxldCBkaXZpZGVCeSA9IDA7CiAgICBsZXQgc2lnbiA9IDE7CiAgICBpZiAoY2ggPT09IDB4MmQpIHsKICAgICAgc2lnbiA9IC0xOwogICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgaWYgKGNoID09PSAweDJkKSB7CiAgICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4MmIpIHsKICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICB9CiAgICBpZiAoY2ggPT09IDB4MGEgfHwgY2ggPT09IDB4MGQpIHsKICAgICAgZG8gewogICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICB9IHdoaWxlIChjaCA9PT0gMHgwYSB8fCBjaCA9PT0gMHgwZCk7CiAgICB9CiAgICBpZiAoY2ggPT09IDB4MmUpIHsKICAgICAgZGl2aWRlQnkgPSAxMDsKICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICB9CiAgICBpZiAoY2ggPCAweDMwIHx8IGNoID4gMHgzOSkgewogICAgICBjb25zdCBtc2cgPSBgSW52YWxpZCBudW1iZXI6ICR7U3RyaW5nLmZyb21DaGFyQ29kZShjaCl9IChjaGFyQ29kZSAke2NofSlgOwogICAgICBpZiAoaXNXaGl0ZVNwYWNlKGNoKSB8fCBjaCA9PT0gMHgyOCB8fCBjaCA9PT0gMHgzYyB8fCBjaCA9PT0gLTEpIHsKICAgICAgICBpbmZvKGBMZXhlci5nZXROdW1iZXIgLSAiJHttc2d9Ii5gKTsKICAgICAgICByZXR1cm4gMDsKICAgICAgfQogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IobXNnKTsKICAgIH0KICAgIGxldCBiYXNlVmFsdWUgPSBjaCAtIDB4MzA7CiAgICBsZXQgcG93ZXJWYWx1ZSA9IDA7CiAgICBsZXQgcG93ZXJWYWx1ZVNpZ24gPSAxOwogICAgd2hpbGUgKChjaCA9IHRoaXMubmV4dENoYXIoKSkgPj0gMCkgewogICAgICBpZiAoY2ggPj0gMHgzMCAmJiBjaCA8PSAweDM5KSB7CiAgICAgICAgY29uc3QgY3VycmVudERpZ2l0ID0gY2ggLSAweDMwOwogICAgICAgIGlmIChlTm90YXRpb24pIHsKICAgICAgICAgIHBvd2VyVmFsdWUgPSBwb3dlclZhbHVlICogMTAgKyBjdXJyZW50RGlnaXQ7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmIChkaXZpZGVCeSAhPT0gMCkgewogICAgICAgICAgICBkaXZpZGVCeSAqPSAxMDsKICAgICAgICAgIH0KICAgICAgICAgIGJhc2VWYWx1ZSA9IGJhc2VWYWx1ZSAqIDEwICsgY3VycmVudERpZ2l0OwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChjaCA9PT0gMHgyZSkgewogICAgICAgIGlmIChkaXZpZGVCeSA9PT0gMCkgewogICAgICAgICAgZGl2aWRlQnkgPSAxOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4MmQpIHsKICAgICAgICB3YXJuKCJCYWRseSBmb3JtYXR0ZWQgbnVtYmVyOiBtaW51cyBzaWduIGluIHRoZSBtaWRkbGUiKTsKICAgICAgfSBlbHNlIGlmIChjaCA9PT0gMHg0NSB8fCBjaCA9PT0gMHg2NSkgewogICAgICAgIGNoID0gdGhpcy5wZWVrQ2hhcigpOwogICAgICAgIGlmIChjaCA9PT0gMHgyYiB8fCBjaCA9PT0gMHgyZCkgewogICAgICAgICAgcG93ZXJWYWx1ZVNpZ24gPSBjaCA9PT0gMHgyZCA/IC0xIDogMTsKICAgICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICB9IGVsc2UgaWYgKGNoIDwgMHgzMCB8fCBjaCA+IDB4MzkpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBlTm90YXRpb24gPSB0cnVlOwogICAgICB9IGVsc2UgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBpZiAoZGl2aWRlQnkgIT09IDApIHsKICAgICAgYmFzZVZhbHVlIC89IGRpdmlkZUJ5OwogICAgfQogICAgaWYgKGVOb3RhdGlvbikgewogICAgICBiYXNlVmFsdWUgKj0gMTAgKiogKHBvd2VyVmFsdWVTaWduICogcG93ZXJWYWx1ZSk7CiAgICB9CiAgICByZXR1cm4gc2lnbiAqIGJhc2VWYWx1ZTsKICB9CiAgZ2V0U3RyaW5nKCkgewogICAgbGV0IG51bVBhcmVuID0gMTsKICAgIGxldCBkb25lID0gZmFsc2U7CiAgICBjb25zdCBzdHJCdWYgPSB0aGlzLnN0ckJ1ZjsKICAgIHN0ckJ1Zi5sZW5ndGggPSAwOwogICAgbGV0IGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgbGV0IGNoYXJCdWZmZXJlZCA9IGZhbHNlOwogICAgICBzd2l0Y2ggKGNoIHwgMCkgewogICAgICAgIGNhc2UgLTE6CiAgICAgICAgICB3YXJuKCJVbnRlcm1pbmF0ZWQgc3RyaW5nIik7CiAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMHgyODoKICAgICAgICAgICsrbnVtUGFyZW47CiAgICAgICAgICBzdHJCdWYucHVzaCgiKCIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweDI5OgogICAgICAgICAgaWYgKC0tbnVtUGFyZW4gPT09IDApIHsKICAgICAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgICBkb25lID0gdHJ1ZTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKCIpIik7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4NWM6CiAgICAgICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgICAgIHN3aXRjaCAoY2gpIHsKICAgICAgICAgICAgY2FzZSAtMToKICAgICAgICAgICAgICB3YXJuKCJVbnRlcm1pbmF0ZWQgc3RyaW5nIik7CiAgICAgICAgICAgICAgZG9uZSA9IHRydWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMHg2ZToKICAgICAgICAgICAgICBzdHJCdWYucHVzaCgiXG4iKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAweDcyOgogICAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKCJcciIpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDB4NzQ6CiAgICAgICAgICAgICAgc3RyQnVmLnB1c2goIlx0Iik7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMHg2MjoKICAgICAgICAgICAgICBzdHJCdWYucHVzaCgiXGIiKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAweDY2OgogICAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKCJcZiIpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDB4NWM6CiAgICAgICAgICAgIGNhc2UgMHgyODoKICAgICAgICAgICAgY2FzZSAweDI5OgogICAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAweDMwOgogICAgICAgICAgICBjYXNlIDB4MzE6CiAgICAgICAgICAgIGNhc2UgMHgzMjoKICAgICAgICAgICAgY2FzZSAweDMzOgogICAgICAgICAgICBjYXNlIDB4MzQ6CiAgICAgICAgICAgIGNhc2UgMHgzNToKICAgICAgICAgICAgY2FzZSAweDM2OgogICAgICAgICAgICBjYXNlIDB4Mzc6CiAgICAgICAgICAgICAgbGV0IHggPSBjaCAmIDB4MGY7CiAgICAgICAgICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgICAgICAgY2hhckJ1ZmZlcmVkID0gdHJ1ZTsKICAgICAgICAgICAgICBpZiAoY2ggPj0gMHgzMCAmJiBjaCA8PSAweDM3KSB7CiAgICAgICAgICAgICAgICB4ID0gKHggPDwgMykgKyAoY2ggJiAweDBmKTsKICAgICAgICAgICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgICAgICAgaWYgKGNoID49IDB4MzAgJiYgY2ggPD0gMHgzNykgewogICAgICAgICAgICAgICAgICBjaGFyQnVmZmVyZWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgeCA9ICh4IDw8IDMpICsgKGNoICYgMHgwZik7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoeCkpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDB4MGQ6CiAgICAgICAgICAgICAgaWYgKHRoaXMucGVla0NoYXIoKSA9PT0gMHgwYSkgewogICAgICAgICAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAweDBhOgogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgIHN0ckJ1Zi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICBzdHJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKSk7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpZiAoZG9uZSkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGlmICghY2hhckJ1ZmZlcmVkKSB7CiAgICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzdHJCdWYuam9pbigiIik7CiAgfQogIGdldE5hbWUoKSB7CiAgICBsZXQgY2gsIHByZXZpb3VzQ2g7CiAgICBjb25zdCBzdHJCdWYgPSB0aGlzLnN0ckJ1ZjsKICAgIHN0ckJ1Zi5sZW5ndGggPSAwOwogICAgd2hpbGUgKChjaCA9IHRoaXMubmV4dENoYXIoKSkgPj0gMCAmJiAhc3BlY2lhbENoYXJzW2NoXSkgewogICAgICBpZiAoY2ggPT09IDB4MjMpIHsKICAgICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgICBpZiAoc3BlY2lhbENoYXJzW2NoXSkgewogICAgICAgICAgd2FybigiTGV4ZXJfZ2V0TmFtZTogIiArICJOVU1CRVIgU0lHTiAoIykgc2hvdWxkIGJlIGZvbGxvd2VkIGJ5IGEgaGV4YWRlY2ltYWwgbnVtYmVyLiIpOwogICAgICAgICAgc3RyQnVmLnB1c2goIiMiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjb25zdCB4ID0gdG9IZXhEaWdpdChjaCk7CiAgICAgICAgaWYgKHggIT09IC0xKSB7CiAgICAgICAgICBwcmV2aW91c0NoID0gY2g7CiAgICAgICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgICAgIGNvbnN0IHgyID0gdG9IZXhEaWdpdChjaCk7CiAgICAgICAgICBpZiAoeDIgPT09IC0xKSB7CiAgICAgICAgICAgIHdhcm4oYExleGVyX2dldE5hbWU6IElsbGVnYWwgZGlnaXQgKCR7U3RyaW5nLmZyb21DaGFyQ29kZShjaCl9KSBgICsgImluIGhleGFkZWNpbWFsIG51bWJlci4iKTsKICAgICAgICAgICAgc3RyQnVmLnB1c2goIiMiLCBTdHJpbmcuZnJvbUNoYXJDb2RlKHByZXZpb3VzQ2gpKTsKICAgICAgICAgICAgaWYgKHNwZWNpYWxDaGFyc1tjaF0pIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdHJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKSk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgc3RyQnVmLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZSh4IDw8IDQgfCB4MikpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdHJCdWYucHVzaCgiIyIsIFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgc3RyQnVmLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShjaCkpOwogICAgICB9CiAgICB9CiAgICBpZiAoc3RyQnVmLmxlbmd0aCA+IDEyNykgewogICAgICB3YXJuKGBOYW1lIHRva2VuIGlzIGxvbmdlciB0aGFuIGFsbG93ZWQgYnkgdGhlIHNwZWM6ICR7c3RyQnVmLmxlbmd0aH1gKTsKICAgIH0KICAgIHJldHVybiBOYW1lLmdldChzdHJCdWYuam9pbigiIikpOwogIH0KICBfaGV4U3RyaW5nV2FybihjaCkgewogICAgY29uc3QgTUFYX0hFWF9TVFJJTkdfTlVNX1dBUk4gPSA1OwogICAgaWYgKHRoaXMuX2hleFN0cmluZ051bVdhcm4rKyA9PT0gTUFYX0hFWF9TVFJJTkdfTlVNX1dBUk4pIHsKICAgICAgd2FybigiZ2V0SGV4U3RyaW5nIC0gaWdub3JpbmcgYWRkaXRpb25hbCBpbnZhbGlkIGNoYXJhY3RlcnMuIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh0aGlzLl9oZXhTdHJpbmdOdW1XYXJuID4gTUFYX0hFWF9TVFJJTkdfTlVNX1dBUk4pIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgd2FybihgZ2V0SGV4U3RyaW5nIC0gaWdub3JpbmcgaW52YWxpZCBjaGFyYWN0ZXI6ICR7Y2h9YCk7CiAgfQogIGdldEhleFN0cmluZygpIHsKICAgIGNvbnN0IHN0ckJ1ZiA9IHRoaXMuc3RyQnVmOwogICAgc3RyQnVmLmxlbmd0aCA9IDA7CiAgICBsZXQgY2ggPSB0aGlzLmN1cnJlbnRDaGFyOwogICAgbGV0IGZpcnN0RGlnaXQgPSAtMSwKICAgICAgZGlnaXQgPSAtMTsKICAgIHRoaXMuX2hleFN0cmluZ051bVdhcm4gPSAwOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgaWYgKGNoIDwgMCkgewogICAgICAgIHdhcm4oIlVudGVybWluYXRlZCBoZXggc3RyaW5nIik7CiAgICAgICAgYnJlYWs7CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4M2UpIHsKICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0gZWxzZSBpZiAoc3BlY2lhbENoYXJzW2NoXSA9PT0gMSkgewogICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9IGVsc2UgewogICAgICAgIGRpZ2l0ID0gdG9IZXhEaWdpdChjaCk7CiAgICAgICAgaWYgKGRpZ2l0ID09PSAtMSkgewogICAgICAgICAgdGhpcy5faGV4U3RyaW5nV2FybihjaCk7CiAgICAgICAgfSBlbHNlIGlmIChmaXJzdERpZ2l0ID09PSAtMSkgewogICAgICAgICAgZmlyc3REaWdpdCA9IGRpZ2l0OwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdHJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGZpcnN0RGlnaXQgPDwgNCB8IGRpZ2l0KSk7CiAgICAgICAgICBmaXJzdERpZ2l0ID0gLTE7CiAgICAgICAgfQogICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICB9CiAgICB9CiAgICBpZiAoZmlyc3REaWdpdCAhPT0gLTEpIHsKICAgICAgc3RyQnVmLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShmaXJzdERpZ2l0IDw8IDQpKTsKICAgIH0KICAgIHJldHVybiBzdHJCdWYuam9pbigiIik7CiAgfQogIGdldE9iaigpIHsKICAgIGxldCBjb21tZW50ID0gZmFsc2U7CiAgICBsZXQgY2ggPSB0aGlzLmN1cnJlbnRDaGFyOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgaWYgKGNoIDwgMCkgewogICAgICAgIHJldHVybiBFT0Y7CiAgICAgIH0KICAgICAgaWYgKGNvbW1lbnQpIHsKICAgICAgICBpZiAoY2ggPT09IDB4MGEgfHwgY2ggPT09IDB4MGQpIHsKICAgICAgICAgIGNvbW1lbnQgPSBmYWxzZTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4MjUpIHsKICAgICAgICBjb21tZW50ID0gdHJ1ZTsKICAgICAgfSBlbHNlIGlmIChzcGVjaWFsQ2hhcnNbY2hdICE9PSAxKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICB9CiAgICBzd2l0Y2ggKGNoIHwgMCkgewogICAgICBjYXNlIDB4MzA6CiAgICAgIGNhc2UgMHgzMToKICAgICAgY2FzZSAweDMyOgogICAgICBjYXNlIDB4MzM6CiAgICAgIGNhc2UgMHgzNDoKICAgICAgY2FzZSAweDM1OgogICAgICBjYXNlIDB4MzY6CiAgICAgIGNhc2UgMHgzNzoKICAgICAgY2FzZSAweDM4OgogICAgICBjYXNlIDB4Mzk6CiAgICAgIGNhc2UgMHgyYjoKICAgICAgY2FzZSAweDJkOgogICAgICBjYXNlIDB4MmU6CiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0TnVtYmVyKCk7CiAgICAgIGNhc2UgMHgyODoKICAgICAgICByZXR1cm4gdGhpcy5nZXRTdHJpbmcoKTsKICAgICAgY2FzZSAweDJmOgogICAgICAgIHJldHVybiB0aGlzLmdldE5hbWUoKTsKICAgICAgY2FzZSAweDViOgogICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICByZXR1cm4gQ21kLmdldCgiWyIpOwogICAgICBjYXNlIDB4NWQ6CiAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgIHJldHVybiBDbWQuZ2V0KCJdIik7CiAgICAgIGNhc2UgMHgzYzoKICAgICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgICBpZiAoY2ggPT09IDB4M2MpIHsKICAgICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICAgIHJldHVybiBDbWQuZ2V0KCI8PCIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpcy5nZXRIZXhTdHJpbmcoKTsKICAgICAgY2FzZSAweDNlOgogICAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgICAgIGlmIChjaCA9PT0gMHgzZSkgewogICAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgcmV0dXJuIENtZC5nZXQoIj4+Iik7CiAgICAgICAgfQogICAgICAgIHJldHVybiBDbWQuZ2V0KCI+Iik7CiAgICAgIGNhc2UgMHg3YjoKICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgcmV0dXJuIENtZC5nZXQoInsiKTsKICAgICAgY2FzZSAweDdkOgogICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICByZXR1cm4gQ21kLmdldCgifSIpOwogICAgICBjYXNlIDB4Mjk6CiAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSWxsZWdhbCBjaGFyYWN0ZXI6ICR7Y2h9YCk7CiAgICB9CiAgICBsZXQgc3RyID0gU3RyaW5nLmZyb21DaGFyQ29kZShjaCk7CiAgICBpZiAoY2ggPCAweDIwIHx8IGNoID4gMHg3ZikgewogICAgICBjb25zdCBuZXh0Q2ggPSB0aGlzLnBlZWtDaGFyKCk7CiAgICAgIGlmIChuZXh0Q2ggPj0gMHgyMCAmJiBuZXh0Q2ggPD0gMHg3ZikgewogICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICByZXR1cm4gQ21kLmdldChzdHIpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBrbm93bkNvbW1hbmRzID0gdGhpcy5rbm93bkNvbW1hbmRzOwogICAgbGV0IGtub3duQ29tbWFuZEZvdW5kID0ga25vd25Db21tYW5kcz8uW3N0cl0gIT09IHVuZGVmaW5lZDsKICAgIHdoaWxlICgoY2ggPSB0aGlzLm5leHRDaGFyKCkpID49IDAgJiYgIXNwZWNpYWxDaGFyc1tjaF0pIHsKICAgICAgY29uc3QgcG9zc2libGVDb21tYW5kID0gc3RyICsgU3RyaW5nLmZyb21DaGFyQ29kZShjaCk7CiAgICAgIGlmIChrbm93bkNvbW1hbmRGb3VuZCAmJiBrbm93bkNvbW1hbmRzW3Bvc3NpYmxlQ29tbWFuZF0gPT09IHVuZGVmaW5lZCkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGlmIChzdHIubGVuZ3RoID09PSAxMjgpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYENvbW1hbmQgdG9rZW4gdG9vIGxvbmc6ICR7c3RyLmxlbmd0aH1gKTsKICAgICAgfQogICAgICBzdHIgPSBwb3NzaWJsZUNvbW1hbmQ7CiAgICAgIGtub3duQ29tbWFuZEZvdW5kID0ga25vd25Db21tYW5kcz8uW3N0cl0gIT09IHVuZGVmaW5lZDsKICAgIH0KICAgIGlmIChzdHIgPT09ICJ0cnVlIikgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmIChzdHIgPT09ICJmYWxzZSIpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKHN0ciA9PT0gIm51bGwiKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgaWYgKHN0ciA9PT0gIkJJIikgewogICAgICB0aGlzLmJlZ2luSW5saW5lSW1hZ2VQb3MgPSB0aGlzLnN0cmVhbS5wb3M7CiAgICB9CiAgICByZXR1cm4gQ21kLmdldChzdHIpOwogIH0KICBza2lwVG9OZXh0TGluZSgpIHsKICAgIGxldCBjaCA9IHRoaXMuY3VycmVudENoYXI7CiAgICB3aGlsZSAoY2ggPj0gMCkgewogICAgICBpZiAoY2ggPT09IDB4MGQpIHsKICAgICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgICAgICBpZiAoY2ggPT09IDB4MGEpIHsKICAgICAgICAgIHRoaXMubmV4dENoYXIoKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4MGEpIHsKICAgICAgICB0aGlzLm5leHRDaGFyKCk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY2ggPSB0aGlzLm5leHRDaGFyKCk7CiAgICB9CiAgfQp9CmNsYXNzIExpbmVhcml6YXRpb24gewogIHN0YXRpYyBjcmVhdGUoc3RyZWFtKSB7CiAgICBmdW5jdGlvbiBnZXRJbnQobGluRGljdCwgbmFtZSwgYWxsb3daZXJvVmFsdWUgPSBmYWxzZSkgewogICAgICBjb25zdCBvYmogPSBsaW5EaWN0LmdldChuYW1lKTsKICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIob2JqKSAmJiAoYWxsb3daZXJvVmFsdWUgPyBvYmogPj0gMCA6IG9iaiA+IDApKSB7CiAgICAgICAgcmV0dXJuIG9iajsKICAgICAgfQogICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZSAiJHtuYW1lfSIgcGFyYW1ldGVyIGluIHRoZSBsaW5lYXJpemF0aW9uIGAgKyAiZGljdGlvbmFyeSBpcyBpbnZhbGlkLiIpOwogICAgfQogICAgZnVuY3Rpb24gZ2V0SGludHMobGluRGljdCkgewogICAgICBjb25zdCBoaW50cyA9IGxpbkRpY3QuZ2V0KCJIIik7CiAgICAgIGxldCBoaW50c0xlbmd0aDsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkoaGludHMpICYmICgoaGludHNMZW5ndGggPSBoaW50cy5sZW5ndGgpID09PSAyIHx8IGhpbnRzTGVuZ3RoID09PSA0KSkgewogICAgICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCBoaW50c0xlbmd0aDsgaW5kZXgrKykgewogICAgICAgICAgY29uc3QgaGludCA9IGhpbnRzW2luZGV4XTsKICAgICAgICAgIGlmICghKE51bWJlci5pc0ludGVnZXIoaGludCkgJiYgaGludCA+IDApKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSGludCAoJHtpbmRleH0pIGluIHRoZSBsaW5lYXJpemF0aW9uIGRpY3Rpb25hcnkgaXMgaW52YWxpZC5gKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIGhpbnRzOwogICAgICB9CiAgICAgIHRocm93IG5ldyBFcnJvcigiSGludCBhcnJheSBpbiB0aGUgbGluZWFyaXphdGlvbiBkaWN0aW9uYXJ5IGlzIGludmFsaWQuIik7CiAgICB9CiAgICBjb25zdCBwYXJzZXIgPSBuZXcgUGFyc2VyKHsKICAgICAgbGV4ZXI6IG5ldyBMZXhlcihzdHJlYW0pLAogICAgICB4cmVmOiBudWxsCiAgICB9KTsKICAgIGNvbnN0IG9iajEgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICBjb25zdCBvYmoyID0gcGFyc2VyLmdldE9iaigpOwogICAgY29uc3Qgb2JqMyA9IHBhcnNlci5nZXRPYmooKTsKICAgIGNvbnN0IGxpbkRpY3QgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICBsZXQgb2JqLCBsZW5ndGg7CiAgICBpZiAoIShOdW1iZXIuaXNJbnRlZ2VyKG9iajEpICYmIE51bWJlci5pc0ludGVnZXIob2JqMikgJiYgaXNDbWQob2JqMywgIm9iaiIpICYmIGxpbkRpY3QgaW5zdGFuY2VvZiBEaWN0ICYmIHR5cGVvZiAob2JqID0gbGluRGljdC5nZXQoIkxpbmVhcml6ZWQiKSkgPT09ICJudW1iZXIiICYmIG9iaiA+IDApKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfSBlbHNlIGlmICgobGVuZ3RoID0gZ2V0SW50KGxpbkRpY3QsICJMIikpICE9PSBzdHJlYW0ubGVuZ3RoKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlICJMIiBwYXJhbWV0ZXIgaW4gdGhlIGxpbmVhcml6YXRpb24gZGljdGlvbmFyeSAnICsgImRvZXMgbm90IGVxdWFsIHRoZSBzdHJlYW0gbGVuZ3RoLiIpOwogICAgfQogICAgcmV0dXJuIHsKICAgICAgbGVuZ3RoLAogICAgICBoaW50czogZ2V0SGludHMobGluRGljdCksCiAgICAgIG9iamVjdE51bWJlckZpcnN0OiBnZXRJbnQobGluRGljdCwgIk8iKSwKICAgICAgZW5kRmlyc3Q6IGdldEludChsaW5EaWN0LCAiRSIpLAogICAgICBudW1QYWdlczogZ2V0SW50KGxpbkRpY3QsICJOIiksCiAgICAgIG1haW5YUmVmRW50cmllc09mZnNldDogZ2V0SW50KGxpbkRpY3QsICJUIiksCiAgICAgIHBhZ2VGaXJzdDogbGluRGljdC5oYXMoIlAiKSA/IGdldEludChsaW5EaWN0LCAiUCIsIHRydWUpIDogMAogICAgfTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2NtYXAuanMKCgoKCgoKCgoKCmNvbnN0IEJVSUxUX0lOX0NNQVBTID0gWyJBZG9iZS1HQjEtVUNTMiIsICJBZG9iZS1DTlMxLVVDUzIiLCAiQWRvYmUtSmFwYW4xLVVDUzIiLCAiQWRvYmUtS29yZWExLVVDUzIiLCAiNzgtRVVDLUgiLCAiNzgtRVVDLVYiLCAiNzgtSCIsICI3OC1SS1NKLUgiLCAiNzgtUktTSi1WIiwgIjc4LVYiLCAiNzhtcy1SS1NKLUgiLCAiNzhtcy1SS1NKLVYiLCAiODNwdi1SS1NKLUgiLCAiOTBtcy1SS1NKLUgiLCAiOTBtcy1SS1NKLVYiLCAiOTBtc3AtUktTSi1IIiwgIjkwbXNwLVJLU0otViIsICI5MHB2LVJLU0otSCIsICI5MHB2LVJLU0otViIsICJBZGQtSCIsICJBZGQtUktTSi1IIiwgIkFkZC1SS1NKLVYiLCAiQWRkLVYiLCAiQWRvYmUtQ05TMS0wIiwgIkFkb2JlLUNOUzEtMSIsICJBZG9iZS1DTlMxLTIiLCAiQWRvYmUtQ05TMS0zIiwgIkFkb2JlLUNOUzEtNCIsICJBZG9iZS1DTlMxLTUiLCAiQWRvYmUtQ05TMS02IiwgIkFkb2JlLUdCMS0wIiwgIkFkb2JlLUdCMS0xIiwgIkFkb2JlLUdCMS0yIiwgIkFkb2JlLUdCMS0zIiwgIkFkb2JlLUdCMS00IiwgIkFkb2JlLUdCMS01IiwgIkFkb2JlLUphcGFuMS0wIiwgIkFkb2JlLUphcGFuMS0xIiwgIkFkb2JlLUphcGFuMS0yIiwgIkFkb2JlLUphcGFuMS0zIiwgIkFkb2JlLUphcGFuMS00IiwgIkFkb2JlLUphcGFuMS01IiwgIkFkb2JlLUphcGFuMS02IiwgIkFkb2JlLUtvcmVhMS0wIiwgIkFkb2JlLUtvcmVhMS0xIiwgIkFkb2JlLUtvcmVhMS0yIiwgIkI1LUgiLCAiQjUtViIsICJCNXBjLUgiLCAiQjVwYy1WIiwgIkNOUy1FVUMtSCIsICJDTlMtRVVDLVYiLCAiQ05TMS1IIiwgIkNOUzEtViIsICJDTlMyLUgiLCAiQ05TMi1WIiwgIkVUSEstQjUtSCIsICJFVEhLLUI1LVYiLCAiRVRlbi1CNS1IIiwgIkVUZW4tQjUtViIsICJFVGVubXMtQjUtSCIsICJFVGVubXMtQjUtViIsICJFVUMtSCIsICJFVUMtViIsICJFeHQtSCIsICJFeHQtUktTSi1IIiwgIkV4dC1SS1NKLVYiLCAiRXh0LVYiLCAiR0ItRVVDLUgiLCAiR0ItRVVDLVYiLCAiR0ItSCIsICJHQi1WIiwgIkdCSy1FVUMtSCIsICJHQkstRVVDLVYiLCAiR0JLMkstSCIsICJHQksySy1WIiwgIkdCS3AtRVVDLUgiLCAiR0JLcC1FVUMtViIsICJHQlQtRVVDLUgiLCAiR0JULUVVQy1WIiwgIkdCVC1IIiwgIkdCVC1WIiwgIkdCVHBjLUVVQy1IIiwgIkdCVHBjLUVVQy1WIiwgIkdCcGMtRVVDLUgiLCAiR0JwYy1FVUMtViIsICJIIiwgIkhLZGxhLUI1LUgiLCAiSEtkbGEtQjUtViIsICJIS2RsYi1CNS1IIiwgIkhLZGxiLUI1LVYiLCAiSEtnY2NzLUI1LUgiLCAiSEtnY2NzLUI1LVYiLCAiSEttMzE0LUI1LUgiLCAiSEttMzE0LUI1LVYiLCAiSEttNDcxLUI1LUgiLCAiSEttNDcxLUI1LVYiLCAiSEtzY3MtQjUtSCIsICJIS3Njcy1CNS1WIiwgIkhhbmtha3UiLCAiSGlyYWdhbmEiLCAiS1NDLUVVQy1IIiwgIktTQy1FVUMtViIsICJLU0MtSCIsICJLU0MtSm9oYWItSCIsICJLU0MtSm9oYWItViIsICJLU0MtViIsICJLU0Ntcy1VSEMtSCIsICJLU0Ntcy1VSEMtSFctSCIsICJLU0Ntcy1VSEMtSFctViIsICJLU0Ntcy1VSEMtViIsICJLU0NwYy1FVUMtSCIsICJLU0NwYy1FVUMtViIsICJLYXRha2FuYSIsICJOV1AtSCIsICJOV1AtViIsICJSS1NKLUgiLCAiUktTSi1WIiwgIlJvbWFuIiwgIlVuaUNOUy1VQ1MyLUgiLCAiVW5pQ05TLVVDUzItViIsICJVbmlDTlMtVVRGMTYtSCIsICJVbmlDTlMtVVRGMTYtViIsICJVbmlDTlMtVVRGMzItSCIsICJVbmlDTlMtVVRGMzItViIsICJVbmlDTlMtVVRGOC1IIiwgIlVuaUNOUy1VVEY4LVYiLCAiVW5pR0ItVUNTMi1IIiwgIlVuaUdCLVVDUzItViIsICJVbmlHQi1VVEYxNi1IIiwgIlVuaUdCLVVURjE2LVYiLCAiVW5pR0ItVVRGMzItSCIsICJVbmlHQi1VVEYzMi1WIiwgIlVuaUdCLVVURjgtSCIsICJVbmlHQi1VVEY4LVYiLCAiVW5pSklTLVVDUzItSCIsICJVbmlKSVMtVUNTMi1IVy1IIiwgIlVuaUpJUy1VQ1MyLUhXLVYiLCAiVW5pSklTLVVDUzItViIsICJVbmlKSVMtVVRGMTYtSCIsICJVbmlKSVMtVVRGMTYtViIsICJVbmlKSVMtVVRGMzItSCIsICJVbmlKSVMtVVRGMzItViIsICJVbmlKSVMtVVRGOC1IIiwgIlVuaUpJUy1VVEY4LVYiLCAiVW5pSklTMjAwNC1VVEYxNi1IIiwgIlVuaUpJUzIwMDQtVVRGMTYtViIsICJVbmlKSVMyMDA0LVVURjMyLUgiLCAiVW5pSklTMjAwNC1VVEYzMi1WIiwgIlVuaUpJUzIwMDQtVVRGOC1IIiwgIlVuaUpJUzIwMDQtVVRGOC1WIiwgIlVuaUpJU1Byby1VQ1MyLUhXLVYiLCAiVW5pSklTUHJvLVVDUzItViIsICJVbmlKSVNQcm8tVVRGOC1WIiwgIlVuaUpJU1gwMjEzLVVURjMyLUgiLCAiVW5pSklTWDAyMTMtVVRGMzItViIsICJVbmlKSVNYMDIxMzIwMDQtVVRGMzItSCIsICJVbmlKSVNYMDIxMzIwMDQtVVRGMzItViIsICJVbmlLUy1VQ1MyLUgiLCAiVW5pS1MtVUNTMi1WIiwgIlVuaUtTLVVURjE2LUgiLCAiVW5pS1MtVVRGMTYtViIsICJVbmlLUy1VVEYzMi1IIiwgIlVuaUtTLVVURjMyLVYiLCAiVW5pS1MtVVRGOC1IIiwgIlVuaUtTLVVURjgtViIsICJWIiwgIldQLVN5bWJvbCJdOwpjb25zdCBNQVhfTUFQX1JBTkdFID0gMiAqKiAyNCAtIDE7CmNsYXNzIENNYXAgewogIGNvbnN0cnVjdG9yKGJ1aWx0SW5DTWFwID0gZmFsc2UpIHsKICAgIHRoaXMuY29kZXNwYWNlUmFuZ2VzID0gW1tdLCBbXSwgW10sIFtdXTsKICAgIHRoaXMubnVtQ29kZXNwYWNlUmFuZ2VzID0gMDsKICAgIHRoaXMuX21hcCA9IFtdOwogICAgdGhpcy5uYW1lID0gIiI7CiAgICB0aGlzLnZlcnRpY2FsID0gZmFsc2U7CiAgICB0aGlzLnVzZUNNYXAgPSBudWxsOwogICAgdGhpcy5idWlsdEluQ01hcCA9IGJ1aWx0SW5DTWFwOwogIH0KICBhZGRDb2Rlc3BhY2VSYW5nZShuLCBsb3csIGhpZ2gpIHsKICAgIHRoaXMuY29kZXNwYWNlUmFuZ2VzW24gLSAxXS5wdXNoKGxvdywgaGlnaCk7CiAgICB0aGlzLm51bUNvZGVzcGFjZVJhbmdlcysrOwogIH0KICBtYXBDaWRSYW5nZShsb3csIGhpZ2gsIGRzdExvdykgewogICAgaWYgKGhpZ2ggLSBsb3cgPiBNQVhfTUFQX1JBTkdFKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigibWFwQ2lkUmFuZ2UgLSBpZ25vcmluZyBkYXRhIGFib3ZlIE1BWF9NQVBfUkFOR0UuIik7CiAgICB9CiAgICB3aGlsZSAobG93IDw9IGhpZ2gpIHsKICAgICAgdGhpcy5fbWFwW2xvdysrXSA9IGRzdExvdysrOwogICAgfQogIH0KICBtYXBCZlJhbmdlKGxvdywgaGlnaCwgZHN0TG93KSB7CiAgICBpZiAoaGlnaCAtIGxvdyA+IE1BWF9NQVBfUkFOR0UpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJtYXBCZlJhbmdlIC0gaWdub3JpbmcgZGF0YSBhYm92ZSBNQVhfTUFQX1JBTkdFLiIpOwogICAgfQogICAgY29uc3QgbGFzdEJ5dGUgPSBkc3RMb3cubGVuZ3RoIC0gMTsKICAgIHdoaWxlIChsb3cgPD0gaGlnaCkgewogICAgICB0aGlzLl9tYXBbbG93KytdID0gZHN0TG93OwogICAgICBjb25zdCBuZXh0Q2hhckNvZGUgPSBkc3RMb3cuY2hhckNvZGVBdChsYXN0Qnl0ZSkgKyAxOwogICAgICBpZiAobmV4dENoYXJDb2RlID4gMHhmZikgewogICAgICAgIGRzdExvdyA9IGRzdExvdy5zdWJzdHJpbmcoMCwgbGFzdEJ5dGUgLSAxKSArIFN0cmluZy5mcm9tQ2hhckNvZGUoZHN0TG93LmNoYXJDb2RlQXQobGFzdEJ5dGUgLSAxKSArIDEpICsgIlx4MDAiOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGRzdExvdyA9IGRzdExvdy5zdWJzdHJpbmcoMCwgbGFzdEJ5dGUpICsgU3RyaW5nLmZyb21DaGFyQ29kZShuZXh0Q2hhckNvZGUpOwogICAgfQogIH0KICBtYXBCZlJhbmdlVG9BcnJheShsb3csIGhpZ2gsIGFycmF5KSB7CiAgICBpZiAoaGlnaCAtIGxvdyA+IE1BWF9NQVBfUkFOR0UpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJtYXBCZlJhbmdlVG9BcnJheSAtIGlnbm9yaW5nIGRhdGEgYWJvdmUgTUFYX01BUF9SQU5HRS4iKTsKICAgIH0KICAgIGNvbnN0IGlpID0gYXJyYXkubGVuZ3RoOwogICAgbGV0IGkgPSAwOwogICAgd2hpbGUgKGxvdyA8PSBoaWdoICYmIGkgPCBpaSkgewogICAgICB0aGlzLl9tYXBbbG93XSA9IGFycmF5W2krK107CiAgICAgICsrbG93OwogICAgfQogIH0KICBtYXBPbmUoc3JjLCBkc3QpIHsKICAgIHRoaXMuX21hcFtzcmNdID0gZHN0OwogIH0KICBsb29rdXAoY29kZSkgewogICAgcmV0dXJuIHRoaXMuX21hcFtjb2RlXTsKICB9CiAgY29udGFpbnMoY29kZSkgewogICAgcmV0dXJuIHRoaXMuX21hcFtjb2RlXSAhPT0gdW5kZWZpbmVkOwogIH0KICBmb3JFYWNoKGNhbGxiYWNrKSB7CiAgICBjb25zdCBtYXAgPSB0aGlzLl9tYXA7CiAgICBjb25zdCBsZW5ndGggPSBtYXAubGVuZ3RoOwogICAgaWYgKGxlbmd0aCA8PSAweDEwMDAwKSB7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICBpZiAobWFwW2ldICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGNhbGxiYWNrKGksIG1hcFtpXSk7CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICBmb3IgKGNvbnN0IGkgaW4gbWFwKSB7CiAgICAgICAgY2FsbGJhY2soaSwgbWFwW2ldKTsKICAgICAgfQogICAgfQogIH0KICBjaGFyQ29kZU9mKHZhbHVlKSB7CiAgICBjb25zdCBtYXAgPSB0aGlzLl9tYXA7CiAgICBpZiAobWFwLmxlbmd0aCA8PSAweDEwMDAwKSB7CiAgICAgIHJldHVybiBtYXAuaW5kZXhPZih2YWx1ZSk7CiAgICB9CiAgICBmb3IgKGNvbnN0IGNoYXJDb2RlIGluIG1hcCkgewogICAgICBpZiAobWFwW2NoYXJDb2RlXSA9PT0gdmFsdWUpIHsKICAgICAgICByZXR1cm4gY2hhckNvZGUgfCAwOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gLTE7CiAgfQogIGdldE1hcCgpIHsKICAgIHJldHVybiB0aGlzLl9tYXA7CiAgfQogIHJlYWRDaGFyQ29kZShzdHIsIG9mZnNldCwgb3V0KSB7CiAgICBsZXQgYyA9IDA7CiAgICBjb25zdCBjb2Rlc3BhY2VSYW5nZXMgPSB0aGlzLmNvZGVzcGFjZVJhbmdlczsKICAgIGZvciAobGV0IG4gPSAwLCBubiA9IGNvZGVzcGFjZVJhbmdlcy5sZW5ndGg7IG4gPCBubjsgbisrKSB7CiAgICAgIGMgPSAoYyA8PCA4IHwgc3RyLmNoYXJDb2RlQXQob2Zmc2V0ICsgbikpID4+PiAwOwogICAgICBjb25zdCBjb2Rlc3BhY2VSYW5nZSA9IGNvZGVzcGFjZVJhbmdlc1tuXTsKICAgICAgZm9yIChsZXQgayA9IDAsIGtrID0gY29kZXNwYWNlUmFuZ2UubGVuZ3RoOyBrIDwga2s7KSB7CiAgICAgICAgY29uc3QgbG93ID0gY29kZXNwYWNlUmFuZ2VbaysrXTsKICAgICAgICBjb25zdCBoaWdoID0gY29kZXNwYWNlUmFuZ2VbaysrXTsKICAgICAgICBpZiAoYyA+PSBsb3cgJiYgYyA8PSBoaWdoKSB7CiAgICAgICAgICBvdXQuY2hhcmNvZGUgPSBjOwogICAgICAgICAgb3V0Lmxlbmd0aCA9IG4gKyAxOwogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgb3V0LmNoYXJjb2RlID0gMDsKICAgIG91dC5sZW5ndGggPSAxOwogIH0KICBnZXRDaGFyQ29kZUxlbmd0aChjaGFyQ29kZSkgewogICAgY29uc3QgY29kZXNwYWNlUmFuZ2VzID0gdGhpcy5jb2Rlc3BhY2VSYW5nZXM7CiAgICBmb3IgKGxldCBuID0gMCwgbm4gPSBjb2Rlc3BhY2VSYW5nZXMubGVuZ3RoOyBuIDwgbm47IG4rKykgewogICAgICBjb25zdCBjb2Rlc3BhY2VSYW5nZSA9IGNvZGVzcGFjZVJhbmdlc1tuXTsKICAgICAgZm9yIChsZXQgayA9IDAsIGtrID0gY29kZXNwYWNlUmFuZ2UubGVuZ3RoOyBrIDwga2s7KSB7CiAgICAgICAgY29uc3QgbG93ID0gY29kZXNwYWNlUmFuZ2VbaysrXTsKICAgICAgICBjb25zdCBoaWdoID0gY29kZXNwYWNlUmFuZ2VbaysrXTsKICAgICAgICBpZiAoY2hhckNvZGUgPj0gbG93ICYmIGNoYXJDb2RlIDw9IGhpZ2gpIHsKICAgICAgICAgIHJldHVybiBuICsgMTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiAxOwogIH0KICBnZXQgbGVuZ3RoKCkgewogICAgcmV0dXJuIHRoaXMuX21hcC5sZW5ndGg7CiAgfQogIGdldCBpc0lkZW50aXR5Q01hcCgpIHsKICAgIGlmICghKHRoaXMubmFtZSA9PT0gIklkZW50aXR5LUgiIHx8IHRoaXMubmFtZSA9PT0gIklkZW50aXR5LVYiKSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpcy5fbWFwLmxlbmd0aCAhPT0gMHgxMDAwMCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDB4MTAwMDA7IGkrKykgewogICAgICBpZiAodGhpcy5fbWFwW2ldICE9PSBpKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KY2xhc3MgSWRlbnRpdHlDTWFwIGV4dGVuZHMgQ01hcCB7CiAgY29uc3RydWN0b3IodmVydGljYWwsIG4pIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLnZlcnRpY2FsID0gdmVydGljYWw7CiAgICB0aGlzLmFkZENvZGVzcGFjZVJhbmdlKG4sIDAsIDB4ZmZmZik7CiAgfQogIG1hcENpZFJhbmdlKGxvdywgaGlnaCwgZHN0TG93KSB7CiAgICB1bnJlYWNoYWJsZSgic2hvdWxkIG5vdCBjYWxsIG1hcENpZFJhbmdlIik7CiAgfQogIG1hcEJmUmFuZ2UobG93LCBoaWdoLCBkc3RMb3cpIHsKICAgIHVucmVhY2hhYmxlKCJzaG91bGQgbm90IGNhbGwgbWFwQmZSYW5nZSIpOwogIH0KICBtYXBCZlJhbmdlVG9BcnJheShsb3csIGhpZ2gsIGFycmF5KSB7CiAgICB1bnJlYWNoYWJsZSgic2hvdWxkIG5vdCBjYWxsIG1hcEJmUmFuZ2VUb0FycmF5Iik7CiAgfQogIG1hcE9uZShzcmMsIGRzdCkgewogICAgdW5yZWFjaGFibGUoInNob3VsZCBub3QgY2FsbCBtYXBDaWRPbmUiKTsKICB9CiAgbG9va3VwKGNvZGUpIHsKICAgIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKGNvZGUpICYmIGNvZGUgPD0gMHhmZmZmID8gY29kZSA6IHVuZGVmaW5lZDsKICB9CiAgY29udGFpbnMoY29kZSkgewogICAgcmV0dXJuIE51bWJlci5pc0ludGVnZXIoY29kZSkgJiYgY29kZSA8PSAweGZmZmY7CiAgfQogIGZvckVhY2goY2FsbGJhY2spIHsKICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IDB4ZmZmZjsgaSsrKSB7CiAgICAgIGNhbGxiYWNrKGksIGkpOwogICAgfQogIH0KICBjaGFyQ29kZU9mKHZhbHVlKSB7CiAgICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcih2YWx1ZSkgJiYgdmFsdWUgPD0gMHhmZmZmID8gdmFsdWUgOiAtMTsKICB9CiAgZ2V0TWFwKCkgewogICAgY29uc3QgbWFwID0gbmV3IEFycmF5KDB4MTAwMDApOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gMHhmZmZmOyBpKyspIHsKICAgICAgbWFwW2ldID0gaTsKICAgIH0KICAgIHJldHVybiBtYXA7CiAgfQogIGdldCBsZW5ndGgoKSB7CiAgICByZXR1cm4gMHgxMDAwMDsKICB9CiAgZ2V0IGlzSWRlbnRpdHlDTWFwKCkgewogICAgdW5yZWFjaGFibGUoInNob3VsZCBub3QgYWNjZXNzIC5pc0lkZW50aXR5Q01hcCIpOwogIH0KfQpmdW5jdGlvbiBzdHJUb0ludChzdHIpIHsKICBsZXQgYSA9IDA7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHsKICAgIGEgPSBhIDw8IDggfCBzdHIuY2hhckNvZGVBdChpKTsKICB9CiAgcmV0dXJuIGEgPj4+IDA7Cn0KZnVuY3Rpb24gZXhwZWN0U3RyaW5nKG9iaikgewogIGlmICh0eXBlb2Ygb2JqICE9PSAic3RyaW5nIikgewogICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJNYWxmb3JtZWQgQ01hcDogZXhwZWN0ZWQgc3RyaW5nLiIpOwogIH0KfQpmdW5jdGlvbiBleHBlY3RJbnQob2JqKSB7CiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKG9iaikpIHsKICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiTWFsZm9ybWVkIENNYXA6IGV4cGVjdGVkIGludC4iKTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VCZkNoYXIoY01hcCwgbGV4ZXIpIHsKICB3aGlsZSAodHJ1ZSkgewogICAgbGV0IG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgaWYgKG9iaiA9PT0gRU9GKSB7CiAgICAgIGJyZWFrOwogICAgfQogICAgaWYgKGlzQ21kKG9iaiwgImVuZGJmY2hhciIpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGV4cGVjdFN0cmluZyhvYmopOwogICAgY29uc3Qgc3JjID0gc3RyVG9JbnQob2JqKTsKICAgIG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgZXhwZWN0U3RyaW5nKG9iaik7CiAgICBjb25zdCBkc3QgPSBvYmo7CiAgICBjTWFwLm1hcE9uZShzcmMsIGRzdCk7CiAgfQp9CmZ1bmN0aW9uIHBhcnNlQmZSYW5nZShjTWFwLCBsZXhlcikgewogIHdoaWxlICh0cnVlKSB7CiAgICBsZXQgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICBpZiAob2JqID09PSBFT0YpIHsKICAgICAgYnJlYWs7CiAgICB9CiAgICBpZiAoaXNDbWQob2JqLCAiZW5kYmZyYW5nZSIpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGV4cGVjdFN0cmluZyhvYmopOwogICAgY29uc3QgbG93ID0gc3RyVG9JbnQob2JqKTsKICAgIG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgZXhwZWN0U3RyaW5nKG9iaik7CiAgICBjb25zdCBoaWdoID0gc3RyVG9JbnQob2JqKTsKICAgIG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgaWYgKE51bWJlci5pc0ludGVnZXIob2JqKSB8fCB0eXBlb2Ygb2JqID09PSAic3RyaW5nIikgewogICAgICBjb25zdCBkc3RMb3cgPSBOdW1iZXIuaXNJbnRlZ2VyKG9iaikgPyBTdHJpbmcuZnJvbUNoYXJDb2RlKG9iaikgOiBvYmo7CiAgICAgIGNNYXAubWFwQmZSYW5nZShsb3csIGhpZ2gsIGRzdExvdyk7CiAgICB9IGVsc2UgaWYgKGlzQ21kKG9iaiwgIlsiKSkgewogICAgICBvYmogPSBsZXhlci5nZXRPYmooKTsKICAgICAgY29uc3QgYXJyYXkgPSBbXTsKICAgICAgd2hpbGUgKCFpc0NtZChvYmosICJdIikgJiYgb2JqICE9PSBFT0YpIHsKICAgICAgICBhcnJheS5wdXNoKG9iaik7CiAgICAgICAgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICAgIH0KICAgICAgY01hcC5tYXBCZlJhbmdlVG9BcnJheShsb3csIGhpZ2gsIGFycmF5KTsKICAgIH0gZWxzZSB7CiAgICAgIGJyZWFrOwogICAgfQogIH0KICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgYmYgcmFuZ2UuIik7Cn0KZnVuY3Rpb24gcGFyc2VDaWRDaGFyKGNNYXAsIGxleGVyKSB7CiAgd2hpbGUgKHRydWUpIHsKICAgIGxldCBvYmogPSBsZXhlci5nZXRPYmooKTsKICAgIGlmIChvYmogPT09IEVPRikgewogICAgICBicmVhazsKICAgIH0KICAgIGlmIChpc0NtZChvYmosICJlbmRjaWRjaGFyIikpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgZXhwZWN0U3RyaW5nKG9iaik7CiAgICBjb25zdCBzcmMgPSBzdHJUb0ludChvYmopOwogICAgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICBleHBlY3RJbnQob2JqKTsKICAgIGNvbnN0IGRzdCA9IG9iajsKICAgIGNNYXAubWFwT25lKHNyYywgZHN0KTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VDaWRSYW5nZShjTWFwLCBsZXhlcikgewogIHdoaWxlICh0cnVlKSB7CiAgICBsZXQgb2JqID0gbGV4ZXIuZ2V0T2JqKCk7CiAgICBpZiAob2JqID09PSBFT0YpIHsKICAgICAgYnJlYWs7CiAgICB9CiAgICBpZiAoaXNDbWQob2JqLCAiZW5kY2lkcmFuZ2UiKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBleHBlY3RTdHJpbmcob2JqKTsKICAgIGNvbnN0IGxvdyA9IHN0clRvSW50KG9iaik7CiAgICBvYmogPSBsZXhlci5nZXRPYmooKTsKICAgIGV4cGVjdFN0cmluZyhvYmopOwogICAgY29uc3QgaGlnaCA9IHN0clRvSW50KG9iaik7CiAgICBvYmogPSBsZXhlci5nZXRPYmooKTsKICAgIGV4cGVjdEludChvYmopOwogICAgY29uc3QgZHN0TG93ID0gb2JqOwogICAgY01hcC5tYXBDaWRSYW5nZShsb3csIGhpZ2gsIGRzdExvdyk7CiAgfQp9CmZ1bmN0aW9uIHBhcnNlQ29kZXNwYWNlUmFuZ2UoY01hcCwgbGV4ZXIpIHsKICB3aGlsZSAodHJ1ZSkgewogICAgbGV0IG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgaWYgKG9iaiA9PT0gRU9GKSB7CiAgICAgIGJyZWFrOwogICAgfQogICAgaWYgKGlzQ21kKG9iaiwgImVuZGNvZGVzcGFjZXJhbmdlIikpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKHR5cGVvZiBvYmogIT09ICJzdHJpbmciKSB7CiAgICAgIGJyZWFrOwogICAgfQogICAgY29uc3QgbG93ID0gc3RyVG9JbnQob2JqKTsKICAgIG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgaWYgKHR5cGVvZiBvYmogIT09ICJzdHJpbmciKSB7CiAgICAgIGJyZWFrOwogICAgfQogICAgY29uc3QgaGlnaCA9IHN0clRvSW50KG9iaik7CiAgICBjTWFwLmFkZENvZGVzcGFjZVJhbmdlKG9iai5sZW5ndGgsIGxvdywgaGlnaCk7CiAgfQogIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBjb2Rlc3BhY2UgcmFuZ2UuIik7Cn0KZnVuY3Rpb24gcGFyc2VXTW9kZShjTWFwLCBsZXhlcikgewogIGNvbnN0IG9iaiA9IGxleGVyLmdldE9iaigpOwogIGlmIChOdW1iZXIuaXNJbnRlZ2VyKG9iaikpIHsKICAgIGNNYXAudmVydGljYWwgPSAhIW9iajsKICB9Cn0KZnVuY3Rpb24gcGFyc2VDTWFwTmFtZShjTWFwLCBsZXhlcikgewogIGNvbnN0IG9iaiA9IGxleGVyLmdldE9iaigpOwogIGlmIChvYmogaW5zdGFuY2VvZiBOYW1lKSB7CiAgICBjTWFwLm5hbWUgPSBvYmoubmFtZTsKICB9Cn0KYXN5bmMgZnVuY3Rpb24gcGFyc2VDTWFwKGNNYXAsIGxleGVyLCBmZXRjaEJ1aWx0SW5DTWFwLCB1c2VDTWFwKSB7CiAgbGV0IHByZXZpb3VzLCBlbWJlZGRlZFVzZUNNYXA7CiAgb2JqTG9vcDogd2hpbGUgKHRydWUpIHsKICAgIHRyeSB7CiAgICAgIGNvbnN0IG9iaiA9IGxleGVyLmdldE9iaigpOwogICAgICBpZiAob2JqID09PSBFT0YpIHsKICAgICAgICBicmVhazsKICAgICAgfSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgaWYgKG9iai5uYW1lID09PSAiV01vZGUiKSB7CiAgICAgICAgICBwYXJzZVdNb2RlKGNNYXAsIGxleGVyKTsKICAgICAgICB9IGVsc2UgaWYgKG9iai5uYW1lID09PSAiQ01hcE5hbWUiKSB7CiAgICAgICAgICBwYXJzZUNNYXBOYW1lKGNNYXAsIGxleGVyKTsKICAgICAgICB9CiAgICAgICAgcHJldmlvdXMgPSBvYmo7CiAgICAgIH0gZWxzZSBpZiAob2JqIGluc3RhbmNlb2YgQ21kKSB7CiAgICAgICAgc3dpdGNoIChvYmouY21kKSB7CiAgICAgICAgICBjYXNlICJlbmRjbWFwIjoKICAgICAgICAgICAgYnJlYWsgb2JqTG9vcDsKICAgICAgICAgIGNhc2UgInVzZWNtYXAiOgogICAgICAgICAgICBpZiAocHJldmlvdXMgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgICAgZW1iZWRkZWRVc2VDTWFwID0gcHJldmlvdXMubmFtZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgImJlZ2luY29kZXNwYWNlcmFuZ2UiOgogICAgICAgICAgICBwYXJzZUNvZGVzcGFjZVJhbmdlKGNNYXAsIGxleGVyKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICJiZWdpbmJmY2hhciI6CiAgICAgICAgICAgIHBhcnNlQmZDaGFyKGNNYXAsIGxleGVyKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICJiZWdpbmNpZGNoYXIiOgogICAgICAgICAgICBwYXJzZUNpZENoYXIoY01hcCwgbGV4ZXIpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgImJlZ2luYmZyYW5nZSI6CiAgICAgICAgICAgIHBhcnNlQmZSYW5nZShjTWFwLCBsZXhlcik7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAiYmVnaW5jaWRyYW5nZSI6CiAgICAgICAgICAgIHBhcnNlQ2lkUmFuZ2UoY01hcCwgbGV4ZXIpOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgd2FybigiSW52YWxpZCBjTWFwIGRhdGE6ICIgKyBleCk7CiAgICAgIGNvbnRpbnVlOwogICAgfQogIH0KICBpZiAoIXVzZUNNYXAgJiYgZW1iZWRkZWRVc2VDTWFwKSB7CiAgICB1c2VDTWFwID0gZW1iZWRkZWRVc2VDTWFwOwogIH0KICBpZiAodXNlQ01hcCkgewogICAgcmV0dXJuIGV4dGVuZENNYXAoY01hcCwgZmV0Y2hCdWlsdEluQ01hcCwgdXNlQ01hcCk7CiAgfQogIHJldHVybiBjTWFwOwp9CmFzeW5jIGZ1bmN0aW9uIGV4dGVuZENNYXAoY01hcCwgZmV0Y2hCdWlsdEluQ01hcCwgdXNlQ01hcCkgewogIGNNYXAudXNlQ01hcCA9IGF3YWl0IGNyZWF0ZUJ1aWx0SW5DTWFwKHVzZUNNYXAsIGZldGNoQnVpbHRJbkNNYXApOwogIGlmIChjTWFwLm51bUNvZGVzcGFjZVJhbmdlcyA9PT0gMCkgewogICAgY29uc3QgdXNlQ29kZXNwYWNlUmFuZ2VzID0gY01hcC51c2VDTWFwLmNvZGVzcGFjZVJhbmdlczsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdXNlQ29kZXNwYWNlUmFuZ2VzLmxlbmd0aDsgaSsrKSB7CiAgICAgIGNNYXAuY29kZXNwYWNlUmFuZ2VzW2ldID0gdXNlQ29kZXNwYWNlUmFuZ2VzW2ldLnNsaWNlKCk7CiAgICB9CiAgICBjTWFwLm51bUNvZGVzcGFjZVJhbmdlcyA9IGNNYXAudXNlQ01hcC5udW1Db2Rlc3BhY2VSYW5nZXM7CiAgfQogIGNNYXAudXNlQ01hcC5mb3JFYWNoKGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7CiAgICBpZiAoIWNNYXAuY29udGFpbnMoa2V5KSkgewogICAgICBjTWFwLm1hcE9uZShrZXksIHZhbHVlKTsKICAgIH0KICB9KTsKICByZXR1cm4gY01hcDsKfQphc3luYyBmdW5jdGlvbiBjcmVhdGVCdWlsdEluQ01hcChuYW1lLCBmZXRjaEJ1aWx0SW5DTWFwKSB7CiAgaWYgKG5hbWUgPT09ICJJZGVudGl0eS1IIikgewogICAgcmV0dXJuIG5ldyBJZGVudGl0eUNNYXAoZmFsc2UsIDIpOwogIH0gZWxzZSBpZiAobmFtZSA9PT0gIklkZW50aXR5LVYiKSB7CiAgICByZXR1cm4gbmV3IElkZW50aXR5Q01hcCh0cnVlLCAyKTsKICB9CiAgaWYgKCFCVUlMVF9JTl9DTUFQUy5pbmNsdWRlcyhuYW1lKSkgewogICAgdGhyb3cgbmV3IEVycm9yKCJVbmtub3duIENNYXAgbmFtZTogIiArIG5hbWUpOwogIH0KICBpZiAoIWZldGNoQnVpbHRJbkNNYXApIHsKICAgIHRocm93IG5ldyBFcnJvcigiQnVpbHQtaW4gQ01hcCBwYXJhbWV0ZXJzIGFyZSBub3QgcHJvdmlkZWQuIik7CiAgfQogIGNvbnN0IHsKICAgIGNNYXBEYXRhLAogICAgaXNDb21wcmVzc2VkCiAgfSA9IGF3YWl0IGZldGNoQnVpbHRJbkNNYXAobmFtZSk7CiAgY29uc3QgY01hcCA9IG5ldyBDTWFwKHRydWUpOwogIGlmIChpc0NvbXByZXNzZWQpIHsKICAgIHJldHVybiBuZXcgQmluYXJ5Q01hcFJlYWRlcigpLnByb2Nlc3MoY01hcERhdGEsIGNNYXAsIHVzZUNNYXAgPT4gZXh0ZW5kQ01hcChjTWFwLCBmZXRjaEJ1aWx0SW5DTWFwLCB1c2VDTWFwKSk7CiAgfQogIGNvbnN0IGxleGVyID0gbmV3IExleGVyKG5ldyBTdHJlYW0oY01hcERhdGEpKTsKICByZXR1cm4gcGFyc2VDTWFwKGNNYXAsIGxleGVyLCBmZXRjaEJ1aWx0SW5DTWFwLCBudWxsKTsKfQpjbGFzcyBDTWFwRmFjdG9yeSB7CiAgc3RhdGljIGFzeW5jIGNyZWF0ZSh7CiAgICBlbmNvZGluZywKICAgIGZldGNoQnVpbHRJbkNNYXAsCiAgICB1c2VDTWFwCiAgfSkgewogICAgaWYgKGVuY29kaW5nIGluc3RhbmNlb2YgTmFtZSkgewogICAgICByZXR1cm4gY3JlYXRlQnVpbHRJbkNNYXAoZW5jb2RpbmcubmFtZSwgZmV0Y2hCdWlsdEluQ01hcCk7CiAgICB9IGVsc2UgaWYgKGVuY29kaW5nIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICBjb25zdCBwYXJzZWRDTWFwID0gYXdhaXQgcGFyc2VDTWFwKG5ldyBDTWFwKCksIG5ldyBMZXhlcihlbmNvZGluZyksIGZldGNoQnVpbHRJbkNNYXAsIHVzZUNNYXApOwogICAgICBpZiAocGFyc2VkQ01hcC5pc0lkZW50aXR5Q01hcCkgewogICAgICAgIHJldHVybiBjcmVhdGVCdWlsdEluQ01hcChwYXJzZWRDTWFwLm5hbWUsIGZldGNoQnVpbHRJbkNNYXApOwogICAgICB9CiAgICAgIHJldHVybiBwYXJzZWRDTWFwOwogICAgfQogICAgdGhyb3cgbmV3IEVycm9yKCJFbmNvZGluZyByZXF1aXJlZC4iKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2VuY29kaW5ncy5qcwpjb25zdCBFeHBlcnRFbmNvZGluZyA9IFsiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJzcGFjZSIsICJleGNsYW1zbWFsbCIsICJIdW5nYXJ1bWxhdXRzbWFsbCIsICIiLCAiZG9sbGFyb2xkc3R5bGUiLCAiZG9sbGFyc3VwZXJpb3IiLCAiYW1wZXJzYW5kc21hbGwiLCAiQWN1dGVzbWFsbCIsICJwYXJlbmxlZnRzdXBlcmlvciIsICJwYXJlbnJpZ2h0c3VwZXJpb3IiLCAidHdvZG90ZW5sZWFkZXIiLCAib25lZG90ZW5sZWFkZXIiLCAiY29tbWEiLCAiaHlwaGVuIiwgInBlcmlvZCIsICJmcmFjdGlvbiIsICJ6ZXJvb2xkc3R5bGUiLCAib25lb2xkc3R5bGUiLCAidHdvb2xkc3R5bGUiLCAidGhyZWVvbGRzdHlsZSIsICJmb3Vyb2xkc3R5bGUiLCAiZml2ZW9sZHN0eWxlIiwgInNpeG9sZHN0eWxlIiwgInNldmVub2xkc3R5bGUiLCAiZWlnaHRvbGRzdHlsZSIsICJuaW5lb2xkc3R5bGUiLCAiY29sb24iLCAic2VtaWNvbG9uIiwgImNvbW1hc3VwZXJpb3IiLCAidGhyZWVxdWFydGVyc2VtZGFzaCIsICJwZXJpb2RzdXBlcmlvciIsICJxdWVzdGlvbnNtYWxsIiwgIiIsICJhc3VwZXJpb3IiLCAiYnN1cGVyaW9yIiwgImNlbnRzdXBlcmlvciIsICJkc3VwZXJpb3IiLCAiZXN1cGVyaW9yIiwgIiIsICIiLCAiIiwgImlzdXBlcmlvciIsICIiLCAiIiwgImxzdXBlcmlvciIsICJtc3VwZXJpb3IiLCAibnN1cGVyaW9yIiwgIm9zdXBlcmlvciIsICIiLCAiIiwgInJzdXBlcmlvciIsICJzc3VwZXJpb3IiLCAidHN1cGVyaW9yIiwgIiIsICJmZiIsICJmaSIsICJmbCIsICJmZmkiLCAiZmZsIiwgInBhcmVubGVmdGluZmVyaW9yIiwgIiIsICJwYXJlbnJpZ2h0aW5mZXJpb3IiLCAiQ2lyY3VtZmxleHNtYWxsIiwgImh5cGhlbnN1cGVyaW9yIiwgIkdyYXZlc21hbGwiLCAiQXNtYWxsIiwgIkJzbWFsbCIsICJDc21hbGwiLCAiRHNtYWxsIiwgIkVzbWFsbCIsICJGc21hbGwiLCAiR3NtYWxsIiwgIkhzbWFsbCIsICJJc21hbGwiLCAiSnNtYWxsIiwgIktzbWFsbCIsICJMc21hbGwiLCAiTXNtYWxsIiwgIk5zbWFsbCIsICJPc21hbGwiLCAiUHNtYWxsIiwgIlFzbWFsbCIsICJSc21hbGwiLCAiU3NtYWxsIiwgIlRzbWFsbCIsICJVc21hbGwiLCAiVnNtYWxsIiwgIldzbWFsbCIsICJYc21hbGwiLCAiWXNtYWxsIiwgIlpzbWFsbCIsICJjb2xvbm1vbmV0YXJ5IiwgIm9uZWZpdHRlZCIsICJydXBpYWgiLCAiVGlsZGVzbWFsbCIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiZXhjbGFtZG93bnNtYWxsIiwgImNlbnRvbGRzdHlsZSIsICJMc2xhc2hzbWFsbCIsICIiLCAiIiwgIlNjYXJvbnNtYWxsIiwgIlpjYXJvbnNtYWxsIiwgIkRpZXJlc2lzc21hbGwiLCAiQnJldmVzbWFsbCIsICJDYXJvbnNtYWxsIiwgIiIsICJEb3RhY2NlbnRzbWFsbCIsICIiLCAiIiwgIk1hY3JvbnNtYWxsIiwgIiIsICIiLCAiZmlndXJlZGFzaCIsICJoeXBoZW5pbmZlcmlvciIsICIiLCAiIiwgIk9nb25la3NtYWxsIiwgIlJpbmdzbWFsbCIsICJDZWRpbGxhc21hbGwiLCAiIiwgIiIsICIiLCAib25lcXVhcnRlciIsICJvbmVoYWxmIiwgInRocmVlcXVhcnRlcnMiLCAicXVlc3Rpb25kb3duc21hbGwiLCAib25lZWlnaHRoIiwgInRocmVlZWlnaHRocyIsICJmaXZlZWlnaHRocyIsICJzZXZlbmVpZ2h0aHMiLCAib25ldGhpcmQiLCAidHdvdGhpcmRzIiwgIiIsICIiLCAiemVyb3N1cGVyaW9yIiwgIm9uZXN1cGVyaW9yIiwgInR3b3N1cGVyaW9yIiwgInRocmVlc3VwZXJpb3IiLCAiZm91cnN1cGVyaW9yIiwgImZpdmVzdXBlcmlvciIsICJzaXhzdXBlcmlvciIsICJzZXZlbnN1cGVyaW9yIiwgImVpZ2h0c3VwZXJpb3IiLCAibmluZXN1cGVyaW9yIiwgInplcm9pbmZlcmlvciIsICJvbmVpbmZlcmlvciIsICJ0d29pbmZlcmlvciIsICJ0aHJlZWluZmVyaW9yIiwgImZvdXJpbmZlcmlvciIsICJmaXZlaW5mZXJpb3IiLCAic2l4aW5mZXJpb3IiLCAic2V2ZW5pbmZlcmlvciIsICJlaWdodGluZmVyaW9yIiwgIm5pbmVpbmZlcmlvciIsICJjZW50aW5mZXJpb3IiLCAiZG9sbGFyaW5mZXJpb3IiLCAicGVyaW9kaW5mZXJpb3IiLCAiY29tbWFpbmZlcmlvciIsICJBZ3JhdmVzbWFsbCIsICJBYWN1dGVzbWFsbCIsICJBY2lyY3VtZmxleHNtYWxsIiwgIkF0aWxkZXNtYWxsIiwgIkFkaWVyZXNpc3NtYWxsIiwgIkFyaW5nc21hbGwiLCAiQUVzbWFsbCIsICJDY2VkaWxsYXNtYWxsIiwgIkVncmF2ZXNtYWxsIiwgIkVhY3V0ZXNtYWxsIiwgIkVjaXJjdW1mbGV4c21hbGwiLCAiRWRpZXJlc2lzc21hbGwiLCAiSWdyYXZlc21hbGwiLCAiSWFjdXRlc21hbGwiLCAiSWNpcmN1bWZsZXhzbWFsbCIsICJJZGllcmVzaXNzbWFsbCIsICJFdGhzbWFsbCIsICJOdGlsZGVzbWFsbCIsICJPZ3JhdmVzbWFsbCIsICJPYWN1dGVzbWFsbCIsICJPY2lyY3VtZmxleHNtYWxsIiwgIk90aWxkZXNtYWxsIiwgIk9kaWVyZXNpc3NtYWxsIiwgIk9Fc21hbGwiLCAiT3NsYXNoc21hbGwiLCAiVWdyYXZlc21hbGwiLCAiVWFjdXRlc21hbGwiLCAiVWNpcmN1bWZsZXhzbWFsbCIsICJVZGllcmVzaXNzbWFsbCIsICJZYWN1dGVzbWFsbCIsICJUaG9ybnNtYWxsIiwgIllkaWVyZXNpc3NtYWxsIl07CmNvbnN0IE1hY0V4cGVydEVuY29kaW5nID0gWyIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgInNwYWNlIiwgImV4Y2xhbXNtYWxsIiwgIkh1bmdhcnVtbGF1dHNtYWxsIiwgImNlbnRvbGRzdHlsZSIsICJkb2xsYXJvbGRzdHlsZSIsICJkb2xsYXJzdXBlcmlvciIsICJhbXBlcnNhbmRzbWFsbCIsICJBY3V0ZXNtYWxsIiwgInBhcmVubGVmdHN1cGVyaW9yIiwgInBhcmVucmlnaHRzdXBlcmlvciIsICJ0d29kb3RlbmxlYWRlciIsICJvbmVkb3RlbmxlYWRlciIsICJjb21tYSIsICJoeXBoZW4iLCAicGVyaW9kIiwgImZyYWN0aW9uIiwgInplcm9vbGRzdHlsZSIsICJvbmVvbGRzdHlsZSIsICJ0d29vbGRzdHlsZSIsICJ0aHJlZW9sZHN0eWxlIiwgImZvdXJvbGRzdHlsZSIsICJmaXZlb2xkc3R5bGUiLCAic2l4b2xkc3R5bGUiLCAic2V2ZW5vbGRzdHlsZSIsICJlaWdodG9sZHN0eWxlIiwgIm5pbmVvbGRzdHlsZSIsICJjb2xvbiIsICJzZW1pY29sb24iLCAiIiwgInRocmVlcXVhcnRlcnNlbWRhc2giLCAiIiwgInF1ZXN0aW9uc21hbGwiLCAiIiwgIiIsICIiLCAiIiwgIkV0aHNtYWxsIiwgIiIsICIiLCAib25lcXVhcnRlciIsICJvbmVoYWxmIiwgInRocmVlcXVhcnRlcnMiLCAib25lZWlnaHRoIiwgInRocmVlZWlnaHRocyIsICJmaXZlZWlnaHRocyIsICJzZXZlbmVpZ2h0aHMiLCAib25ldGhpcmQiLCAidHdvdGhpcmRzIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgImZmIiwgImZpIiwgImZsIiwgImZmaSIsICJmZmwiLCAicGFyZW5sZWZ0aW5mZXJpb3IiLCAiIiwgInBhcmVucmlnaHRpbmZlcmlvciIsICJDaXJjdW1mbGV4c21hbGwiLCAiaHlwaGVuaW5mZXJpb3IiLCAiR3JhdmVzbWFsbCIsICJBc21hbGwiLCAiQnNtYWxsIiwgIkNzbWFsbCIsICJEc21hbGwiLCAiRXNtYWxsIiwgIkZzbWFsbCIsICJHc21hbGwiLCAiSHNtYWxsIiwgIklzbWFsbCIsICJKc21hbGwiLCAiS3NtYWxsIiwgIkxzbWFsbCIsICJNc21hbGwiLCAiTnNtYWxsIiwgIk9zbWFsbCIsICJQc21hbGwiLCAiUXNtYWxsIiwgIlJzbWFsbCIsICJTc21hbGwiLCAiVHNtYWxsIiwgIlVzbWFsbCIsICJWc21hbGwiLCAiV3NtYWxsIiwgIlhzbWFsbCIsICJZc21hbGwiLCAiWnNtYWxsIiwgImNvbG9ubW9uZXRhcnkiLCAib25lZml0dGVkIiwgInJ1cGlhaCIsICJUaWxkZXNtYWxsIiwgIiIsICIiLCAiYXN1cGVyaW9yIiwgImNlbnRzdXBlcmlvciIsICIiLCAiIiwgIiIsICIiLCAiQWFjdXRlc21hbGwiLCAiQWdyYXZlc21hbGwiLCAiQWNpcmN1bWZsZXhzbWFsbCIsICJBZGllcmVzaXNzbWFsbCIsICJBdGlsZGVzbWFsbCIsICJBcmluZ3NtYWxsIiwgIkNjZWRpbGxhc21hbGwiLCAiRWFjdXRlc21hbGwiLCAiRWdyYXZlc21hbGwiLCAiRWNpcmN1bWZsZXhzbWFsbCIsICJFZGllcmVzaXNzbWFsbCIsICJJYWN1dGVzbWFsbCIsICJJZ3JhdmVzbWFsbCIsICJJY2lyY3VtZmxleHNtYWxsIiwgIklkaWVyZXNpc3NtYWxsIiwgIk50aWxkZXNtYWxsIiwgIk9hY3V0ZXNtYWxsIiwgIk9ncmF2ZXNtYWxsIiwgIk9jaXJjdW1mbGV4c21hbGwiLCAiT2RpZXJlc2lzc21hbGwiLCAiT3RpbGRlc21hbGwiLCAiVWFjdXRlc21hbGwiLCAiVWdyYXZlc21hbGwiLCAiVWNpcmN1bWZsZXhzbWFsbCIsICJVZGllcmVzaXNzbWFsbCIsICIiLCAiZWlnaHRzdXBlcmlvciIsICJmb3VyaW5mZXJpb3IiLCAidGhyZWVpbmZlcmlvciIsICJzaXhpbmZlcmlvciIsICJlaWdodGluZmVyaW9yIiwgInNldmVuaW5mZXJpb3IiLCAiU2Nhcm9uc21hbGwiLCAiIiwgImNlbnRpbmZlcmlvciIsICJ0d29pbmZlcmlvciIsICIiLCAiRGllcmVzaXNzbWFsbCIsICIiLCAiQ2Fyb25zbWFsbCIsICJvc3VwZXJpb3IiLCAiZml2ZWluZmVyaW9yIiwgIiIsICJjb21tYWluZmVyaW9yIiwgInBlcmlvZGluZmVyaW9yIiwgIllhY3V0ZXNtYWxsIiwgIiIsICJkb2xsYXJpbmZlcmlvciIsICIiLCAiIiwgIlRob3Juc21hbGwiLCAiIiwgIm5pbmVpbmZlcmlvciIsICJ6ZXJvaW5mZXJpb3IiLCAiWmNhcm9uc21hbGwiLCAiQUVzbWFsbCIsICJPc2xhc2hzbWFsbCIsICJxdWVzdGlvbmRvd25zbWFsbCIsICJvbmVpbmZlcmlvciIsICJMc2xhc2hzbWFsbCIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJDZWRpbGxhc21hbGwiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJPRXNtYWxsIiwgImZpZ3VyZWRhc2giLCAiaHlwaGVuc3VwZXJpb3IiLCAiIiwgIiIsICIiLCAiIiwgImV4Y2xhbWRvd25zbWFsbCIsICIiLCAiWWRpZXJlc2lzc21hbGwiLCAiIiwgIm9uZXN1cGVyaW9yIiwgInR3b3N1cGVyaW9yIiwgInRocmVlc3VwZXJpb3IiLCAiZm91cnN1cGVyaW9yIiwgImZpdmVzdXBlcmlvciIsICJzaXhzdXBlcmlvciIsICJzZXZlbnN1cGVyaW9yIiwgIm5pbmVzdXBlcmlvciIsICJ6ZXJvc3VwZXJpb3IiLCAiIiwgImVzdXBlcmlvciIsICJyc3VwZXJpb3IiLCAidHN1cGVyaW9yIiwgIiIsICIiLCAiaXN1cGVyaW9yIiwgInNzdXBlcmlvciIsICJkc3VwZXJpb3IiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJsc3VwZXJpb3IiLCAiT2dvbmVrc21hbGwiLCAiQnJldmVzbWFsbCIsICJNYWNyb25zbWFsbCIsICJic3VwZXJpb3IiLCAibnN1cGVyaW9yIiwgIm1zdXBlcmlvciIsICJjb21tYXN1cGVyaW9yIiwgInBlcmlvZHN1cGVyaW9yIiwgIkRvdGFjY2VudHNtYWxsIiwgIlJpbmdzbWFsbCIsICIiLCAiIiwgIiIsICIiXTsKY29uc3QgTWFjUm9tYW5FbmNvZGluZyA9IFsiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJzcGFjZSIsICJleGNsYW0iLCAicXVvdGVkYmwiLCAibnVtYmVyc2lnbiIsICJkb2xsYXIiLCAicGVyY2VudCIsICJhbXBlcnNhbmQiLCAicXVvdGVzaW5nbGUiLCAicGFyZW5sZWZ0IiwgInBhcmVucmlnaHQiLCAiYXN0ZXJpc2siLCAicGx1cyIsICJjb21tYSIsICJoeXBoZW4iLCAicGVyaW9kIiwgInNsYXNoIiwgInplcm8iLCAib25lIiwgInR3byIsICJ0aHJlZSIsICJmb3VyIiwgImZpdmUiLCAic2l4IiwgInNldmVuIiwgImVpZ2h0IiwgIm5pbmUiLCAiY29sb24iLCAic2VtaWNvbG9uIiwgImxlc3MiLCAiZXF1YWwiLCAiZ3JlYXRlciIsICJxdWVzdGlvbiIsICJhdCIsICJBIiwgIkIiLCAiQyIsICJEIiwgIkUiLCAiRiIsICJHIiwgIkgiLCAiSSIsICJKIiwgIksiLCAiTCIsICJNIiwgIk4iLCAiTyIsICJQIiwgIlEiLCAiUiIsICJTIiwgIlQiLCAiVSIsICJWIiwgIlciLCAiWCIsICJZIiwgIloiLCAiYnJhY2tldGxlZnQiLCAiYmFja3NsYXNoIiwgImJyYWNrZXRyaWdodCIsICJhc2NpaWNpcmN1bSIsICJ1bmRlcnNjb3JlIiwgImdyYXZlIiwgImEiLCAiYiIsICJjIiwgImQiLCAiZSIsICJmIiwgImciLCAiaCIsICJpIiwgImoiLCAiayIsICJsIiwgIm0iLCAibiIsICJvIiwgInAiLCAicSIsICJyIiwgInMiLCAidCIsICJ1IiwgInYiLCAidyIsICJ4IiwgInkiLCAieiIsICJicmFjZWxlZnQiLCAiYmFyIiwgImJyYWNlcmlnaHQiLCAiYXNjaWl0aWxkZSIsICIiLCAiQWRpZXJlc2lzIiwgIkFyaW5nIiwgIkNjZWRpbGxhIiwgIkVhY3V0ZSIsICJOdGlsZGUiLCAiT2RpZXJlc2lzIiwgIlVkaWVyZXNpcyIsICJhYWN1dGUiLCAiYWdyYXZlIiwgImFjaXJjdW1mbGV4IiwgImFkaWVyZXNpcyIsICJhdGlsZGUiLCAiYXJpbmciLCAiY2NlZGlsbGEiLCAiZWFjdXRlIiwgImVncmF2ZSIsICJlY2lyY3VtZmxleCIsICJlZGllcmVzaXMiLCAiaWFjdXRlIiwgImlncmF2ZSIsICJpY2lyY3VtZmxleCIsICJpZGllcmVzaXMiLCAibnRpbGRlIiwgIm9hY3V0ZSIsICJvZ3JhdmUiLCAib2NpcmN1bWZsZXgiLCAib2RpZXJlc2lzIiwgIm90aWxkZSIsICJ1YWN1dGUiLCAidWdyYXZlIiwgInVjaXJjdW1mbGV4IiwgInVkaWVyZXNpcyIsICJkYWdnZXIiLCAiZGVncmVlIiwgImNlbnQiLCAic3RlcmxpbmciLCAic2VjdGlvbiIsICJidWxsZXQiLCAicGFyYWdyYXBoIiwgImdlcm1hbmRibHMiLCAicmVnaXN0ZXJlZCIsICJjb3B5cmlnaHQiLCAidHJhZGVtYXJrIiwgImFjdXRlIiwgImRpZXJlc2lzIiwgIm5vdGVxdWFsIiwgIkFFIiwgIk9zbGFzaCIsICJpbmZpbml0eSIsICJwbHVzbWludXMiLCAibGVzc2VxdWFsIiwgImdyZWF0ZXJlcXVhbCIsICJ5ZW4iLCAibXUiLCAicGFydGlhbGRpZmYiLCAic3VtbWF0aW9uIiwgInByb2R1Y3QiLCAicGkiLCAiaW50ZWdyYWwiLCAib3JkZmVtaW5pbmUiLCAib3JkbWFzY3VsaW5lIiwgIk9tZWdhIiwgImFlIiwgIm9zbGFzaCIsICJxdWVzdGlvbmRvd24iLCAiZXhjbGFtZG93biIsICJsb2dpY2Fsbm90IiwgInJhZGljYWwiLCAiZmxvcmluIiwgImFwcHJveGVxdWFsIiwgIkRlbHRhIiwgImd1aWxsZW1vdGxlZnQiLCAiZ3VpbGxlbW90cmlnaHQiLCAiZWxsaXBzaXMiLCAic3BhY2UiLCAiQWdyYXZlIiwgIkF0aWxkZSIsICJPdGlsZGUiLCAiT0UiLCAib2UiLCAiZW5kYXNoIiwgImVtZGFzaCIsICJxdW90ZWRibGxlZnQiLCAicXVvdGVkYmxyaWdodCIsICJxdW90ZWxlZnQiLCAicXVvdGVyaWdodCIsICJkaXZpZGUiLCAibG96ZW5nZSIsICJ5ZGllcmVzaXMiLCAiWWRpZXJlc2lzIiwgImZyYWN0aW9uIiwgImN1cnJlbmN5IiwgImd1aWxzaW5nbGxlZnQiLCAiZ3VpbHNpbmdscmlnaHQiLCAiZmkiLCAiZmwiLCAiZGFnZ2VyZGJsIiwgInBlcmlvZGNlbnRlcmVkIiwgInF1b3Rlc2luZ2xiYXNlIiwgInF1b3RlZGJsYmFzZSIsICJwZXJ0aG91c2FuZCIsICJBY2lyY3VtZmxleCIsICJFY2lyY3VtZmxleCIsICJBYWN1dGUiLCAiRWRpZXJlc2lzIiwgIkVncmF2ZSIsICJJYWN1dGUiLCAiSWNpcmN1bWZsZXgiLCAiSWRpZXJlc2lzIiwgIklncmF2ZSIsICJPYWN1dGUiLCAiT2NpcmN1bWZsZXgiLCAiYXBwbGUiLCAiT2dyYXZlIiwgIlVhY3V0ZSIsICJVY2lyY3VtZmxleCIsICJVZ3JhdmUiLCAiZG90bGVzc2kiLCAiY2lyY3VtZmxleCIsICJ0aWxkZSIsICJtYWNyb24iLCAiYnJldmUiLCAiZG90YWNjZW50IiwgInJpbmciLCAiY2VkaWxsYSIsICJodW5nYXJ1bWxhdXQiLCAib2dvbmVrIiwgImNhcm9uIl07CmNvbnN0IFN0YW5kYXJkRW5jb2RpbmcgPSBbIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAic3BhY2UiLCAiZXhjbGFtIiwgInF1b3RlZGJsIiwgIm51bWJlcnNpZ24iLCAiZG9sbGFyIiwgInBlcmNlbnQiLCAiYW1wZXJzYW5kIiwgInF1b3RlcmlnaHQiLCAicGFyZW5sZWZ0IiwgInBhcmVucmlnaHQiLCAiYXN0ZXJpc2siLCAicGx1cyIsICJjb21tYSIsICJoeXBoZW4iLCAicGVyaW9kIiwgInNsYXNoIiwgInplcm8iLCAib25lIiwgInR3byIsICJ0aHJlZSIsICJmb3VyIiwgImZpdmUiLCAic2l4IiwgInNldmVuIiwgImVpZ2h0IiwgIm5pbmUiLCAiY29sb24iLCAic2VtaWNvbG9uIiwgImxlc3MiLCAiZXF1YWwiLCAiZ3JlYXRlciIsICJxdWVzdGlvbiIsICJhdCIsICJBIiwgIkIiLCAiQyIsICJEIiwgIkUiLCAiRiIsICJHIiwgIkgiLCAiSSIsICJKIiwgIksiLCAiTCIsICJNIiwgIk4iLCAiTyIsICJQIiwgIlEiLCAiUiIsICJTIiwgIlQiLCAiVSIsICJWIiwgIlciLCAiWCIsICJZIiwgIloiLCAiYnJhY2tldGxlZnQiLCAiYmFja3NsYXNoIiwgImJyYWNrZXRyaWdodCIsICJhc2NpaWNpcmN1bSIsICJ1bmRlcnNjb3JlIiwgInF1b3RlbGVmdCIsICJhIiwgImIiLCAiYyIsICJkIiwgImUiLCAiZiIsICJnIiwgImgiLCAiaSIsICJqIiwgImsiLCAibCIsICJtIiwgIm4iLCAibyIsICJwIiwgInEiLCAiciIsICJzIiwgInQiLCAidSIsICJ2IiwgInciLCAieCIsICJ5IiwgInoiLCAiYnJhY2VsZWZ0IiwgImJhciIsICJicmFjZXJpZ2h0IiwgImFzY2lpdGlsZGUiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgImV4Y2xhbWRvd24iLCAiY2VudCIsICJzdGVybGluZyIsICJmcmFjdGlvbiIsICJ5ZW4iLCAiZmxvcmluIiwgInNlY3Rpb24iLCAiY3VycmVuY3kiLCAicXVvdGVzaW5nbGUiLCAicXVvdGVkYmxsZWZ0IiwgImd1aWxsZW1vdGxlZnQiLCAiZ3VpbHNpbmdsbGVmdCIsICJndWlsc2luZ2xyaWdodCIsICJmaSIsICJmbCIsICIiLCAiZW5kYXNoIiwgImRhZ2dlciIsICJkYWdnZXJkYmwiLCAicGVyaW9kY2VudGVyZWQiLCAiIiwgInBhcmFncmFwaCIsICJidWxsZXQiLCAicXVvdGVzaW5nbGJhc2UiLCAicXVvdGVkYmxiYXNlIiwgInF1b3RlZGJscmlnaHQiLCAiZ3VpbGxlbW90cmlnaHQiLCAiZWxsaXBzaXMiLCAicGVydGhvdXNhbmQiLCAiIiwgInF1ZXN0aW9uZG93biIsICIiLCAiZ3JhdmUiLCAiYWN1dGUiLCAiY2lyY3VtZmxleCIsICJ0aWxkZSIsICJtYWNyb24iLCAiYnJldmUiLCAiZG90YWNjZW50IiwgImRpZXJlc2lzIiwgIiIsICJyaW5nIiwgImNlZGlsbGEiLCAiIiwgImh1bmdhcnVtbGF1dCIsICJvZ29uZWsiLCAiY2Fyb24iLCAiZW1kYXNoIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJBRSIsICIiLCAib3JkZmVtaW5pbmUiLCAiIiwgIiIsICIiLCAiIiwgIkxzbGFzaCIsICJPc2xhc2giLCAiT0UiLCAib3JkbWFzY3VsaW5lIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiYWUiLCAiIiwgIiIsICIiLCAiZG90bGVzc2kiLCAiIiwgIiIsICJsc2xhc2giLCAib3NsYXNoIiwgIm9lIiwgImdlcm1hbmRibHMiLCAiIiwgIiIsICIiLCAiIl07CmNvbnN0IFdpbkFuc2lFbmNvZGluZyA9IFsiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJzcGFjZSIsICJleGNsYW0iLCAicXVvdGVkYmwiLCAibnVtYmVyc2lnbiIsICJkb2xsYXIiLCAicGVyY2VudCIsICJhbXBlcnNhbmQiLCAicXVvdGVzaW5nbGUiLCAicGFyZW5sZWZ0IiwgInBhcmVucmlnaHQiLCAiYXN0ZXJpc2siLCAicGx1cyIsICJjb21tYSIsICJoeXBoZW4iLCAicGVyaW9kIiwgInNsYXNoIiwgInplcm8iLCAib25lIiwgInR3byIsICJ0aHJlZSIsICJmb3VyIiwgImZpdmUiLCAic2l4IiwgInNldmVuIiwgImVpZ2h0IiwgIm5pbmUiLCAiY29sb24iLCAic2VtaWNvbG9uIiwgImxlc3MiLCAiZXF1YWwiLCAiZ3JlYXRlciIsICJxdWVzdGlvbiIsICJhdCIsICJBIiwgIkIiLCAiQyIsICJEIiwgIkUiLCAiRiIsICJHIiwgIkgiLCAiSSIsICJKIiwgIksiLCAiTCIsICJNIiwgIk4iLCAiTyIsICJQIiwgIlEiLCAiUiIsICJTIiwgIlQiLCAiVSIsICJWIiwgIlciLCAiWCIsICJZIiwgIloiLCAiYnJhY2tldGxlZnQiLCAiYmFja3NsYXNoIiwgImJyYWNrZXRyaWdodCIsICJhc2NpaWNpcmN1bSIsICJ1bmRlcnNjb3JlIiwgImdyYXZlIiwgImEiLCAiYiIsICJjIiwgImQiLCAiZSIsICJmIiwgImciLCAiaCIsICJpIiwgImoiLCAiayIsICJsIiwgIm0iLCAibiIsICJvIiwgInAiLCAicSIsICJyIiwgInMiLCAidCIsICJ1IiwgInYiLCAidyIsICJ4IiwgInkiLCAieiIsICJicmFjZWxlZnQiLCAiYmFyIiwgImJyYWNlcmlnaHQiLCAiYXNjaWl0aWxkZSIsICJidWxsZXQiLCAiRXVybyIsICJidWxsZXQiLCAicXVvdGVzaW5nbGJhc2UiLCAiZmxvcmluIiwgInF1b3RlZGJsYmFzZSIsICJlbGxpcHNpcyIsICJkYWdnZXIiLCAiZGFnZ2VyZGJsIiwgImNpcmN1bWZsZXgiLCAicGVydGhvdXNhbmQiLCAiU2Nhcm9uIiwgImd1aWxzaW5nbGxlZnQiLCAiT0UiLCAiYnVsbGV0IiwgIlpjYXJvbiIsICJidWxsZXQiLCAiYnVsbGV0IiwgInF1b3RlbGVmdCIsICJxdW90ZXJpZ2h0IiwgInF1b3RlZGJsbGVmdCIsICJxdW90ZWRibHJpZ2h0IiwgImJ1bGxldCIsICJlbmRhc2giLCAiZW1kYXNoIiwgInRpbGRlIiwgInRyYWRlbWFyayIsICJzY2Fyb24iLCAiZ3VpbHNpbmdscmlnaHQiLCAib2UiLCAiYnVsbGV0IiwgInpjYXJvbiIsICJZZGllcmVzaXMiLCAic3BhY2UiLCAiZXhjbGFtZG93biIsICJjZW50IiwgInN0ZXJsaW5nIiwgImN1cnJlbmN5IiwgInllbiIsICJicm9rZW5iYXIiLCAic2VjdGlvbiIsICJkaWVyZXNpcyIsICJjb3B5cmlnaHQiLCAib3JkZmVtaW5pbmUiLCAiZ3VpbGxlbW90bGVmdCIsICJsb2dpY2Fsbm90IiwgImh5cGhlbiIsICJyZWdpc3RlcmVkIiwgIm1hY3JvbiIsICJkZWdyZWUiLCAicGx1c21pbnVzIiwgInR3b3N1cGVyaW9yIiwgInRocmVlc3VwZXJpb3IiLCAiYWN1dGUiLCAibXUiLCAicGFyYWdyYXBoIiwgInBlcmlvZGNlbnRlcmVkIiwgImNlZGlsbGEiLCAib25lc3VwZXJpb3IiLCAib3JkbWFzY3VsaW5lIiwgImd1aWxsZW1vdHJpZ2h0IiwgIm9uZXF1YXJ0ZXIiLCAib25laGFsZiIsICJ0aHJlZXF1YXJ0ZXJzIiwgInF1ZXN0aW9uZG93biIsICJBZ3JhdmUiLCAiQWFjdXRlIiwgIkFjaXJjdW1mbGV4IiwgIkF0aWxkZSIsICJBZGllcmVzaXMiLCAiQXJpbmciLCAiQUUiLCAiQ2NlZGlsbGEiLCAiRWdyYXZlIiwgIkVhY3V0ZSIsICJFY2lyY3VtZmxleCIsICJFZGllcmVzaXMiLCAiSWdyYXZlIiwgIklhY3V0ZSIsICJJY2lyY3VtZmxleCIsICJJZGllcmVzaXMiLCAiRXRoIiwgIk50aWxkZSIsICJPZ3JhdmUiLCAiT2FjdXRlIiwgIk9jaXJjdW1mbGV4IiwgIk90aWxkZSIsICJPZGllcmVzaXMiLCAibXVsdGlwbHkiLCAiT3NsYXNoIiwgIlVncmF2ZSIsICJVYWN1dGUiLCAiVWNpcmN1bWZsZXgiLCAiVWRpZXJlc2lzIiwgIllhY3V0ZSIsICJUaG9ybiIsICJnZXJtYW5kYmxzIiwgImFncmF2ZSIsICJhYWN1dGUiLCAiYWNpcmN1bWZsZXgiLCAiYXRpbGRlIiwgImFkaWVyZXNpcyIsICJhcmluZyIsICJhZSIsICJjY2VkaWxsYSIsICJlZ3JhdmUiLCAiZWFjdXRlIiwgImVjaXJjdW1mbGV4IiwgImVkaWVyZXNpcyIsICJpZ3JhdmUiLCAiaWFjdXRlIiwgImljaXJjdW1mbGV4IiwgImlkaWVyZXNpcyIsICJldGgiLCAibnRpbGRlIiwgIm9ncmF2ZSIsICJvYWN1dGUiLCAib2NpcmN1bWZsZXgiLCAib3RpbGRlIiwgIm9kaWVyZXNpcyIsICJkaXZpZGUiLCAib3NsYXNoIiwgInVncmF2ZSIsICJ1YWN1dGUiLCAidWNpcmN1bWZsZXgiLCAidWRpZXJlc2lzIiwgInlhY3V0ZSIsICJ0aG9ybiIsICJ5ZGllcmVzaXMiXTsKY29uc3QgU3ltYm9sU2V0RW5jb2RpbmcgPSBbIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAic3BhY2UiLCAiZXhjbGFtIiwgInVuaXZlcnNhbCIsICJudW1iZXJzaWduIiwgImV4aXN0ZW50aWFsIiwgInBlcmNlbnQiLCAiYW1wZXJzYW5kIiwgInN1Y2h0aGF0IiwgInBhcmVubGVmdCIsICJwYXJlbnJpZ2h0IiwgImFzdGVyaXNrbWF0aCIsICJwbHVzIiwgImNvbW1hIiwgIm1pbnVzIiwgInBlcmlvZCIsICJzbGFzaCIsICJ6ZXJvIiwgIm9uZSIsICJ0d28iLCAidGhyZWUiLCAiZm91ciIsICJmaXZlIiwgInNpeCIsICJzZXZlbiIsICJlaWdodCIsICJuaW5lIiwgImNvbG9uIiwgInNlbWljb2xvbiIsICJsZXNzIiwgImVxdWFsIiwgImdyZWF0ZXIiLCAicXVlc3Rpb24iLCAiY29uZ3J1ZW50IiwgIkFscGhhIiwgIkJldGEiLCAiQ2hpIiwgIkRlbHRhIiwgIkVwc2lsb24iLCAiUGhpIiwgIkdhbW1hIiwgIkV0YSIsICJJb3RhIiwgInRoZXRhMSIsICJLYXBwYSIsICJMYW1iZGEiLCAiTXUiLCAiTnUiLCAiT21pY3JvbiIsICJQaSIsICJUaGV0YSIsICJSaG8iLCAiU2lnbWEiLCAiVGF1IiwgIlVwc2lsb24iLCAic2lnbWExIiwgIk9tZWdhIiwgIlhpIiwgIlBzaSIsICJaZXRhIiwgImJyYWNrZXRsZWZ0IiwgInRoZXJlZm9yZSIsICJicmFja2V0cmlnaHQiLCAicGVycGVuZGljdWxhciIsICJ1bmRlcnNjb3JlIiwgInJhZGljYWxleCIsICJhbHBoYSIsICJiZXRhIiwgImNoaSIsICJkZWx0YSIsICJlcHNpbG9uIiwgInBoaSIsICJnYW1tYSIsICJldGEiLCAiaW90YSIsICJwaGkxIiwgImthcHBhIiwgImxhbWJkYSIsICJtdSIsICJudSIsICJvbWljcm9uIiwgInBpIiwgInRoZXRhIiwgInJobyIsICJzaWdtYSIsICJ0YXUiLCAidXBzaWxvbiIsICJvbWVnYTEiLCAib21lZ2EiLCAieGkiLCAicHNpIiwgInpldGEiLCAiYnJhY2VsZWZ0IiwgImJhciIsICJicmFjZXJpZ2h0IiwgInNpbWlsYXIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiRXVybyIsICJVcHNpbG9uMSIsICJtaW51dGUiLCAibGVzc2VxdWFsIiwgImZyYWN0aW9uIiwgImluZmluaXR5IiwgImZsb3JpbiIsICJjbHViIiwgImRpYW1vbmQiLCAiaGVhcnQiLCAic3BhZGUiLCAiYXJyb3dib3RoIiwgImFycm93bGVmdCIsICJhcnJvd3VwIiwgImFycm93cmlnaHQiLCAiYXJyb3dkb3duIiwgImRlZ3JlZSIsICJwbHVzbWludXMiLCAic2Vjb25kIiwgImdyZWF0ZXJlcXVhbCIsICJtdWx0aXBseSIsICJwcm9wb3J0aW9uYWwiLCAicGFydGlhbGRpZmYiLCAiYnVsbGV0IiwgImRpdmlkZSIsICJub3RlcXVhbCIsICJlcXVpdmFsZW5jZSIsICJhcHByb3hlcXVhbCIsICJlbGxpcHNpcyIsICJhcnJvd3ZlcnRleCIsICJhcnJvd2hvcml6ZXgiLCAiY2FycmlhZ2VyZXR1cm4iLCAiYWxlcGgiLCAiSWZyYWt0dXIiLCAiUmZyYWt0dXIiLCAid2VpZXJzdHJhc3MiLCAiY2lyY2xlbXVsdGlwbHkiLCAiY2lyY2xlcGx1cyIsICJlbXB0eXNldCIsICJpbnRlcnNlY3Rpb24iLCAidW5pb24iLCAicHJvcGVyc3VwZXJzZXQiLCAicmVmbGV4c3VwZXJzZXQiLCAibm90c3Vic2V0IiwgInByb3BlcnN1YnNldCIsICJyZWZsZXhzdWJzZXQiLCAiZWxlbWVudCIsICJub3RlbGVtZW50IiwgImFuZ2xlIiwgImdyYWRpZW50IiwgInJlZ2lzdGVyc2VyaWYiLCAiY29weXJpZ2h0c2VyaWYiLCAidHJhZGVtYXJrc2VyaWYiLCAicHJvZHVjdCIsICJyYWRpY2FsIiwgImRvdG1hdGgiLCAibG9naWNhbG5vdCIsICJsb2dpY2FsYW5kIiwgImxvZ2ljYWxvciIsICJhcnJvd2RibGJvdGgiLCAiYXJyb3dkYmxsZWZ0IiwgImFycm93ZGJsdXAiLCAiYXJyb3dkYmxyaWdodCIsICJhcnJvd2RibGRvd24iLCAibG96ZW5nZSIsICJhbmdsZWxlZnQiLCAicmVnaXN0ZXJzYW5zIiwgImNvcHlyaWdodHNhbnMiLCAidHJhZGVtYXJrc2FucyIsICJzdW1tYXRpb24iLCAicGFyZW5sZWZ0dHAiLCAicGFyZW5sZWZ0ZXgiLCAicGFyZW5sZWZ0YnQiLCAiYnJhY2tldGxlZnR0cCIsICJicmFja2V0bGVmdGV4IiwgImJyYWNrZXRsZWZ0YnQiLCAiYnJhY2VsZWZ0dHAiLCAiYnJhY2VsZWZ0bWlkIiwgImJyYWNlbGVmdGJ0IiwgImJyYWNlZXgiLCAiIiwgImFuZ2xlcmlnaHQiLCAiaW50ZWdyYWwiLCAiaW50ZWdyYWx0cCIsICJpbnRlZ3JhbGV4IiwgImludGVncmFsYnQiLCAicGFyZW5yaWdodHRwIiwgInBhcmVucmlnaHRleCIsICJwYXJlbnJpZ2h0YnQiLCAiYnJhY2tldHJpZ2h0dHAiLCAiYnJhY2tldHJpZ2h0ZXgiLCAiYnJhY2tldHJpZ2h0YnQiLCAiYnJhY2VyaWdodHRwIiwgImJyYWNlcmlnaHRtaWQiLCAiYnJhY2VyaWdodGJ0IiwgIiJdOwpjb25zdCBaYXBmRGluZ2JhdHNFbmNvZGluZyA9IFsiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJzcGFjZSIsICJhMSIsICJhMiIsICJhMjAyIiwgImEzIiwgImE0IiwgImE1IiwgImExMTkiLCAiYTExOCIsICJhMTE3IiwgImExMSIsICJhMTIiLCAiYTEzIiwgImExNCIsICJhMTUiLCAiYTE2IiwgImExMDUiLCAiYTE3IiwgImExOCIsICJhMTkiLCAiYTIwIiwgImEyMSIsICJhMjIiLCAiYTIzIiwgImEyNCIsICJhMjUiLCAiYTI2IiwgImEyNyIsICJhMjgiLCAiYTYiLCAiYTciLCAiYTgiLCAiYTkiLCAiYTEwIiwgImEyOSIsICJhMzAiLCAiYTMxIiwgImEzMiIsICJhMzMiLCAiYTM0IiwgImEzNSIsICJhMzYiLCAiYTM3IiwgImEzOCIsICJhMzkiLCAiYTQwIiwgImE0MSIsICJhNDIiLCAiYTQzIiwgImE0NCIsICJhNDUiLCAiYTQ2IiwgImE0NyIsICJhNDgiLCAiYTQ5IiwgImE1MCIsICJhNTEiLCAiYTUyIiwgImE1MyIsICJhNTQiLCAiYTU1IiwgImE1NiIsICJhNTciLCAiYTU4IiwgImE1OSIsICJhNjAiLCAiYTYxIiwgImE2MiIsICJhNjMiLCAiYTY0IiwgImE2NSIsICJhNjYiLCAiYTY3IiwgImE2OCIsICJhNjkiLCAiYTcwIiwgImE3MSIsICJhNzIiLCAiYTczIiwgImE3NCIsICJhMjAzIiwgImE3NSIsICJhMjA0IiwgImE3NiIsICJhNzciLCAiYTc4IiwgImE3OSIsICJhODEiLCAiYTgyIiwgImE4MyIsICJhODQiLCAiYTk3IiwgImE5OCIsICJhOTkiLCAiYTEwMCIsICIiLCAiYTg5IiwgImE5MCIsICJhOTMiLCAiYTk0IiwgImE5MSIsICJhOTIiLCAiYTIwNSIsICJhODUiLCAiYTIwNiIsICJhODYiLCAiYTg3IiwgImE4OCIsICJhOTUiLCAiYTk2IiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICIiLCAiIiwgIiIsICJhMTAxIiwgImExMDIiLCAiYTEwMyIsICJhMTA0IiwgImExMDYiLCAiYTEwNyIsICJhMTA4IiwgImExMTIiLCAiYTExMSIsICJhMTEwIiwgImExMDkiLCAiYTEyMCIsICJhMTIxIiwgImExMjIiLCAiYTEyMyIsICJhMTI0IiwgImExMjUiLCAiYTEyNiIsICJhMTI3IiwgImExMjgiLCAiYTEyOSIsICJhMTMwIiwgImExMzEiLCAiYTEzMiIsICJhMTMzIiwgImExMzQiLCAiYTEzNSIsICJhMTM2IiwgImExMzciLCAiYTEzOCIsICJhMTM5IiwgImExNDAiLCAiYTE0MSIsICJhMTQyIiwgImExNDMiLCAiYTE0NCIsICJhMTQ1IiwgImExNDYiLCAiYTE0NyIsICJhMTQ4IiwgImExNDkiLCAiYTE1MCIsICJhMTUxIiwgImExNTIiLCAiYTE1MyIsICJhMTU0IiwgImExNTUiLCAiYTE1NiIsICJhMTU3IiwgImExNTgiLCAiYTE1OSIsICJhMTYwIiwgImExNjEiLCAiYTE2MyIsICJhMTY0IiwgImExOTYiLCAiYTE2NSIsICJhMTkyIiwgImExNjYiLCAiYTE2NyIsICJhMTY4IiwgImExNjkiLCAiYTE3MCIsICJhMTcxIiwgImExNzIiLCAiYTE3MyIsICJhMTYyIiwgImExNzQiLCAiYTE3NSIsICJhMTc2IiwgImExNzciLCAiYTE3OCIsICJhMTc5IiwgImExOTMiLCAiYTE4MCIsICJhMTk5IiwgImExODEiLCAiYTIwMCIsICJhMTgyIiwgIiIsICJhMjAxIiwgImExODMiLCAiYTE4NCIsICJhMTk3IiwgImExODUiLCAiYTE5NCIsICJhMTk4IiwgImExODYiLCAiYTE5NSIsICJhMTg3IiwgImExODgiLCAiYTE4OSIsICJhMTkwIiwgImExOTEiLCAiIl07CmZ1bmN0aW9uIGdldEVuY29kaW5nKGVuY29kaW5nTmFtZSkgewogIHN3aXRjaCAoZW5jb2RpbmdOYW1lKSB7CiAgICBjYXNlICJXaW5BbnNpRW5jb2RpbmciOgogICAgICByZXR1cm4gV2luQW5zaUVuY29kaW5nOwogICAgY2FzZSAiU3RhbmRhcmRFbmNvZGluZyI6CiAgICAgIHJldHVybiBTdGFuZGFyZEVuY29kaW5nOwogICAgY2FzZSAiTWFjUm9tYW5FbmNvZGluZyI6CiAgICAgIHJldHVybiBNYWNSb21hbkVuY29kaW5nOwogICAgY2FzZSAiU3ltYm9sU2V0RW5jb2RpbmciOgogICAgICByZXR1cm4gU3ltYm9sU2V0RW5jb2Rpbmc7CiAgICBjYXNlICJaYXBmRGluZ2JhdHNFbmNvZGluZyI6CiAgICAgIHJldHVybiBaYXBmRGluZ2JhdHNFbmNvZGluZzsKICAgIGNhc2UgIkV4cGVydEVuY29kaW5nIjoKICAgICAgcmV0dXJuIEV4cGVydEVuY29kaW5nOwogICAgY2FzZSAiTWFjRXhwZXJ0RW5jb2RpbmciOgogICAgICByZXR1cm4gTWFjRXhwZXJ0RW5jb2Rpbmc7CiAgICBkZWZhdWx0OgogICAgICByZXR1cm4gbnVsbDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2dseXBobGlzdC5qcwoKY29uc3QgZ2V0R2x5cGhzVW5pY29kZSA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogIHQuQSA9IDB4MDA0MTsKICB0LkFFID0gMHgwMGM2OwogIHQuQUVhY3V0ZSA9IDB4MDFmYzsKICB0LkFFbWFjcm9uID0gMHgwMWUyOwogIHQuQUVzbWFsbCA9IDB4ZjdlNjsKICB0LkFhY3V0ZSA9IDB4MDBjMTsKICB0LkFhY3V0ZXNtYWxsID0gMHhmN2UxOwogIHQuQWJyZXZlID0gMHgwMTAyOwogIHQuQWJyZXZlYWN1dGUgPSAweDFlYWU7CiAgdC5BYnJldmVjeXJpbGxpYyA9IDB4MDRkMDsKICB0LkFicmV2ZWRvdGJlbG93ID0gMHgxZWI2OwogIHQuQWJyZXZlZ3JhdmUgPSAweDFlYjA7CiAgdC5BYnJldmVob29rYWJvdmUgPSAweDFlYjI7CiAgdC5BYnJldmV0aWxkZSA9IDB4MWViNDsKICB0LkFjYXJvbiA9IDB4MDFjZDsKICB0LkFjaXJjbGUgPSAweDI0YjY7CiAgdC5BY2lyY3VtZmxleCA9IDB4MDBjMjsKICB0LkFjaXJjdW1mbGV4YWN1dGUgPSAweDFlYTQ7CiAgdC5BY2lyY3VtZmxleGRvdGJlbG93ID0gMHgxZWFjOwogIHQuQWNpcmN1bWZsZXhncmF2ZSA9IDB4MWVhNjsKICB0LkFjaXJjdW1mbGV4aG9va2Fib3ZlID0gMHgxZWE4OwogIHQuQWNpcmN1bWZsZXhzbWFsbCA9IDB4ZjdlMjsKICB0LkFjaXJjdW1mbGV4dGlsZGUgPSAweDFlYWE7CiAgdC5BY3V0ZSA9IDB4ZjZjOTsKICB0LkFjdXRlc21hbGwgPSAweGY3YjQ7CiAgdC5BY3lyaWxsaWMgPSAweDA0MTA7CiAgdC5BZGJsZ3JhdmUgPSAweDAyMDA7CiAgdC5BZGllcmVzaXMgPSAweDAwYzQ7CiAgdC5BZGllcmVzaXNjeXJpbGxpYyA9IDB4MDRkMjsKICB0LkFkaWVyZXNpc21hY3JvbiA9IDB4MDFkZTsKICB0LkFkaWVyZXNpc3NtYWxsID0gMHhmN2U0OwogIHQuQWRvdGJlbG93ID0gMHgxZWEwOwogIHQuQWRvdG1hY3JvbiA9IDB4MDFlMDsKICB0LkFncmF2ZSA9IDB4MDBjMDsKICB0LkFncmF2ZXNtYWxsID0gMHhmN2UwOwogIHQuQWhvb2thYm92ZSA9IDB4MWVhMjsKICB0LkFpZWN5cmlsbGljID0gMHgwNGQ0OwogIHQuQWludmVydGVkYnJldmUgPSAweDAyMDI7CiAgdC5BbHBoYSA9IDB4MDM5MTsKICB0LkFscGhhdG9ub3MgPSAweDAzODY7CiAgdC5BbWFjcm9uID0gMHgwMTAwOwogIHQuQW1vbm9zcGFjZSA9IDB4ZmYyMTsKICB0LkFvZ29uZWsgPSAweDAxMDQ7CiAgdC5BcmluZyA9IDB4MDBjNTsKICB0LkFyaW5nYWN1dGUgPSAweDAxZmE7CiAgdC5BcmluZ2JlbG93ID0gMHgxZTAwOwogIHQuQXJpbmdzbWFsbCA9IDB4ZjdlNTsKICB0LkFzbWFsbCA9IDB4Zjc2MTsKICB0LkF0aWxkZSA9IDB4MDBjMzsKICB0LkF0aWxkZXNtYWxsID0gMHhmN2UzOwogIHQuQXliYXJtZW5pYW4gPSAweDA1MzE7CiAgdC5CID0gMHgwMDQyOwogIHQuQmNpcmNsZSA9IDB4MjRiNzsKICB0LkJkb3RhY2NlbnQgPSAweDFlMDI7CiAgdC5CZG90YmVsb3cgPSAweDFlMDQ7CiAgdC5CZWN5cmlsbGljID0gMHgwNDExOwogIHQuQmVuYXJtZW5pYW4gPSAweDA1MzI7CiAgdC5CZXRhID0gMHgwMzkyOwogIHQuQmhvb2sgPSAweDAxODE7CiAgdC5CbGluZWJlbG93ID0gMHgxZTA2OwogIHQuQm1vbm9zcGFjZSA9IDB4ZmYyMjsKICB0LkJyZXZlc21hbGwgPSAweGY2ZjQ7CiAgdC5Cc21hbGwgPSAweGY3NjI7CiAgdC5CdG9wYmFyID0gMHgwMTgyOwogIHQuQyA9IDB4MDA0MzsKICB0LkNhYXJtZW5pYW4gPSAweDA1M2U7CiAgdC5DYWN1dGUgPSAweDAxMDY7CiAgdC5DYXJvbiA9IDB4ZjZjYTsKICB0LkNhcm9uc21hbGwgPSAweGY2ZjU7CiAgdC5DY2Fyb24gPSAweDAxMGM7CiAgdC5DY2VkaWxsYSA9IDB4MDBjNzsKICB0LkNjZWRpbGxhYWN1dGUgPSAweDFlMDg7CiAgdC5DY2VkaWxsYXNtYWxsID0gMHhmN2U3OwogIHQuQ2NpcmNsZSA9IDB4MjRiODsKICB0LkNjaXJjdW1mbGV4ID0gMHgwMTA4OwogIHQuQ2RvdCA9IDB4MDEwYTsKICB0LkNkb3RhY2NlbnQgPSAweDAxMGE7CiAgdC5DZWRpbGxhc21hbGwgPSAweGY3Yjg7CiAgdC5DaGFhcm1lbmlhbiA9IDB4MDU0OTsKICB0LkNoZWFia2hhc2lhbmN5cmlsbGljID0gMHgwNGJjOwogIHQuQ2hlY3lyaWxsaWMgPSAweDA0Mjc7CiAgdC5DaGVkZXNjZW5kZXJhYmtoYXNpYW5jeXJpbGxpYyA9IDB4MDRiZTsKICB0LkNoZWRlc2NlbmRlcmN5cmlsbGljID0gMHgwNGI2OwogIHQuQ2hlZGllcmVzaXNjeXJpbGxpYyA9IDB4MDRmNDsKICB0LkNoZWhhcm1lbmlhbiA9IDB4MDU0MzsKICB0LkNoZWtoYWthc3NpYW5jeXJpbGxpYyA9IDB4MDRjYjsKICB0LkNoZXZlcnRpY2Fsc3Ryb2tlY3lyaWxsaWMgPSAweDA0Yjg7CiAgdC5DaGkgPSAweDAzYTc7CiAgdC5DaG9vayA9IDB4MDE4NzsKICB0LkNpcmN1bWZsZXhzbWFsbCA9IDB4ZjZmNjsKICB0LkNtb25vc3BhY2UgPSAweGZmMjM7CiAgdC5Db2FybWVuaWFuID0gMHgwNTUxOwogIHQuQ3NtYWxsID0gMHhmNzYzOwogIHQuRCA9IDB4MDA0NDsKICB0LkRaID0gMHgwMWYxOwogIHQuRFpjYXJvbiA9IDB4MDFjNDsKICB0LkRhYXJtZW5pYW4gPSAweDA1MzQ7CiAgdC5EYWZyaWNhbiA9IDB4MDE4OTsKICB0LkRjYXJvbiA9IDB4MDEwZTsKICB0LkRjZWRpbGxhID0gMHgxZTEwOwogIHQuRGNpcmNsZSA9IDB4MjRiOTsKICB0LkRjaXJjdW1mbGV4YmVsb3cgPSAweDFlMTI7CiAgdC5EY3JvYXQgPSAweDAxMTA7CiAgdC5EZG90YWNjZW50ID0gMHgxZTBhOwogIHQuRGRvdGJlbG93ID0gMHgxZTBjOwogIHQuRGVjeXJpbGxpYyA9IDB4MDQxNDsKICB0LkRlaWNvcHRpYyA9IDB4MDNlZTsKICB0LkRlbHRhID0gMHgyMjA2OwogIHQuRGVsdGFncmVlayA9IDB4MDM5NDsKICB0LkRob29rID0gMHgwMThhOwogIHQuRGllcmVzaXMgPSAweGY2Y2I7CiAgdC5EaWVyZXNpc0FjdXRlID0gMHhmNmNjOwogIHQuRGllcmVzaXNHcmF2ZSA9IDB4ZjZjZDsKICB0LkRpZXJlc2lzc21hbGwgPSAweGY3YTg7CiAgdC5EaWdhbW1hZ3JlZWsgPSAweDAzZGM7CiAgdC5EamVjeXJpbGxpYyA9IDB4MDQwMjsKICB0LkRsaW5lYmVsb3cgPSAweDFlMGU7CiAgdC5EbW9ub3NwYWNlID0gMHhmZjI0OwogIHQuRG90YWNjZW50c21hbGwgPSAweGY2Zjc7CiAgdC5Ec2xhc2ggPSAweDAxMTA7CiAgdC5Ec21hbGwgPSAweGY3NjQ7CiAgdC5EdG9wYmFyID0gMHgwMThiOwogIHQuRHogPSAweDAxZjI7CiAgdC5EemNhcm9uID0gMHgwMWM1OwogIHQuRHplYWJraGFzaWFuY3lyaWxsaWMgPSAweDA0ZTA7CiAgdC5EemVjeXJpbGxpYyA9IDB4MDQwNTsKICB0LkR6aGVjeXJpbGxpYyA9IDB4MDQwZjsKICB0LkUgPSAweDAwNDU7CiAgdC5FYWN1dGUgPSAweDAwYzk7CiAgdC5FYWN1dGVzbWFsbCA9IDB4ZjdlOTsKICB0LkVicmV2ZSA9IDB4MDExNDsKICB0LkVjYXJvbiA9IDB4MDExYTsKICB0LkVjZWRpbGxhYnJldmUgPSAweDFlMWM7CiAgdC5FY2hhcm1lbmlhbiA9IDB4MDUzNTsKICB0LkVjaXJjbGUgPSAweDI0YmE7CiAgdC5FY2lyY3VtZmxleCA9IDB4MDBjYTsKICB0LkVjaXJjdW1mbGV4YWN1dGUgPSAweDFlYmU7CiAgdC5FY2lyY3VtZmxleGJlbG93ID0gMHgxZTE4OwogIHQuRWNpcmN1bWZsZXhkb3RiZWxvdyA9IDB4MWVjNjsKICB0LkVjaXJjdW1mbGV4Z3JhdmUgPSAweDFlYzA7CiAgdC5FY2lyY3VtZmxleGhvb2thYm92ZSA9IDB4MWVjMjsKICB0LkVjaXJjdW1mbGV4c21hbGwgPSAweGY3ZWE7CiAgdC5FY2lyY3VtZmxleHRpbGRlID0gMHgxZWM0OwogIHQuRWN5cmlsbGljID0gMHgwNDA0OwogIHQuRWRibGdyYXZlID0gMHgwMjA0OwogIHQuRWRpZXJlc2lzID0gMHgwMGNiOwogIHQuRWRpZXJlc2lzc21hbGwgPSAweGY3ZWI7CiAgdC5FZG90ID0gMHgwMTE2OwogIHQuRWRvdGFjY2VudCA9IDB4MDExNjsKICB0LkVkb3RiZWxvdyA9IDB4MWViODsKICB0LkVmY3lyaWxsaWMgPSAweDA0MjQ7CiAgdC5FZ3JhdmUgPSAweDAwYzg7CiAgdC5FZ3JhdmVzbWFsbCA9IDB4ZjdlODsKICB0LkVoYXJtZW5pYW4gPSAweDA1Mzc7CiAgdC5FaG9va2Fib3ZlID0gMHgxZWJhOwogIHQuRWlnaHRyb21hbiA9IDB4MjE2NzsKICB0LkVpbnZlcnRlZGJyZXZlID0gMHgwMjA2OwogIHQuRWlvdGlmaWVkY3lyaWxsaWMgPSAweDA0NjQ7CiAgdC5FbGN5cmlsbGljID0gMHgwNDFiOwogIHQuRWxldmVucm9tYW4gPSAweDIxNmE7CiAgdC5FbWFjcm9uID0gMHgwMTEyOwogIHQuRW1hY3JvbmFjdXRlID0gMHgxZTE2OwogIHQuRW1hY3JvbmdyYXZlID0gMHgxZTE0OwogIHQuRW1jeXJpbGxpYyA9IDB4MDQxYzsKICB0LkVtb25vc3BhY2UgPSAweGZmMjU7CiAgdC5FbmN5cmlsbGljID0gMHgwNDFkOwogIHQuRW5kZXNjZW5kZXJjeXJpbGxpYyA9IDB4MDRhMjsKICB0LkVuZyA9IDB4MDE0YTsKICB0LkVuZ2hlY3lyaWxsaWMgPSAweDA0YTQ7CiAgdC5Fbmhvb2tjeXJpbGxpYyA9IDB4MDRjNzsKICB0LkVvZ29uZWsgPSAweDAxMTg7CiAgdC5Fb3BlbiA9IDB4MDE5MDsKICB0LkVwc2lsb24gPSAweDAzOTU7CiAgdC5FcHNpbG9udG9ub3MgPSAweDAzODg7CiAgdC5FcmN5cmlsbGljID0gMHgwNDIwOwogIHQuRXJldmVyc2VkID0gMHgwMThlOwogIHQuRXJldmVyc2VkY3lyaWxsaWMgPSAweDA0MmQ7CiAgdC5Fc2N5cmlsbGljID0gMHgwNDIxOwogIHQuRXNkZXNjZW5kZXJjeXJpbGxpYyA9IDB4MDRhYTsKICB0LkVzaCA9IDB4MDFhOTsKICB0LkVzbWFsbCA9IDB4Zjc2NTsKICB0LkV0YSA9IDB4MDM5NzsKICB0LkV0YXJtZW5pYW4gPSAweDA1Mzg7CiAgdC5FdGF0b25vcyA9IDB4MDM4OTsKICB0LkV0aCA9IDB4MDBkMDsKICB0LkV0aHNtYWxsID0gMHhmN2YwOwogIHQuRXRpbGRlID0gMHgxZWJjOwogIHQuRXRpbGRlYmVsb3cgPSAweDFlMWE7CiAgdC5FdXJvID0gMHgyMGFjOwogIHQuRXpoID0gMHgwMWI3OwogIHQuRXpoY2Fyb24gPSAweDAxZWU7CiAgdC5FemhyZXZlcnNlZCA9IDB4MDFiODsKICB0LkYgPSAweDAwNDY7CiAgdC5GY2lyY2xlID0gMHgyNGJiOwogIHQuRmRvdGFjY2VudCA9IDB4MWUxZTsKICB0LkZlaGFybWVuaWFuID0gMHgwNTU2OwogIHQuRmVpY29wdGljID0gMHgwM2U0OwogIHQuRmhvb2sgPSAweDAxOTE7CiAgdC5GaXRhY3lyaWxsaWMgPSAweDA0NzI7CiAgdC5GaXZlcm9tYW4gPSAweDIxNjQ7CiAgdC5GbW9ub3NwYWNlID0gMHhmZjI2OwogIHQuRm91cnJvbWFuID0gMHgyMTYzOwogIHQuRnNtYWxsID0gMHhmNzY2OwogIHQuRyA9IDB4MDA0NzsKICB0LkdCc3F1YXJlID0gMHgzMzg3OwogIHQuR2FjdXRlID0gMHgwMWY0OwogIHQuR2FtbWEgPSAweDAzOTM7CiAgdC5HYW1tYWFmcmljYW4gPSAweDAxOTQ7CiAgdC5HYW5naWFjb3B0aWMgPSAweDAzZWE7CiAgdC5HYnJldmUgPSAweDAxMWU7CiAgdC5HY2Fyb24gPSAweDAxZTY7CiAgdC5HY2VkaWxsYSA9IDB4MDEyMjsKICB0LkdjaXJjbGUgPSAweDI0YmM7CiAgdC5HY2lyY3VtZmxleCA9IDB4MDExYzsKICB0Lkdjb21tYWFjY2VudCA9IDB4MDEyMjsKICB0Lkdkb3QgPSAweDAxMjA7CiAgdC5HZG90YWNjZW50ID0gMHgwMTIwOwogIHQuR2VjeXJpbGxpYyA9IDB4MDQxMzsKICB0LkdoYWRhcm1lbmlhbiA9IDB4MDU0MjsKICB0LkdoZW1pZGRsZWhvb2tjeXJpbGxpYyA9IDB4MDQ5NDsKICB0LkdoZXN0cm9rZWN5cmlsbGljID0gMHgwNDkyOwogIHQuR2hldXB0dXJuY3lyaWxsaWMgPSAweDA0OTA7CiAgdC5HaG9vayA9IDB4MDE5MzsKICB0LkdpbWFybWVuaWFuID0gMHgwNTMzOwogIHQuR2plY3lyaWxsaWMgPSAweDA0MDM7CiAgdC5HbWFjcm9uID0gMHgxZTIwOwogIHQuR21vbm9zcGFjZSA9IDB4ZmYyNzsKICB0LkdyYXZlID0gMHhmNmNlOwogIHQuR3JhdmVzbWFsbCA9IDB4Zjc2MDsKICB0LkdzbWFsbCA9IDB4Zjc2NzsKICB0LkdzbWFsbGhvb2sgPSAweDAyOWI7CiAgdC5Hc3Ryb2tlID0gMHgwMWU0OwogIHQuSCA9IDB4MDA0ODsKICB0LkgxODUzMyA9IDB4MjVjZjsKICB0LkgxODU0MyA9IDB4MjVhYTsKICB0LkgxODU1MSA9IDB4MjVhYjsKICB0LkgyMjA3MyA9IDB4MjVhMTsKICB0LkhQc3F1YXJlID0gMHgzM2NiOwogIHQuSGFhYmtoYXNpYW5jeXJpbGxpYyA9IDB4MDRhODsKICB0LkhhZGVzY2VuZGVyY3lyaWxsaWMgPSAweDA0YjI7CiAgdC5IYXJkc2lnbmN5cmlsbGljID0gMHgwNDJhOwogIHQuSGJhciA9IDB4MDEyNjsKICB0LkhicmV2ZWJlbG93ID0gMHgxZTJhOwogIHQuSGNlZGlsbGEgPSAweDFlMjg7CiAgdC5IY2lyY2xlID0gMHgyNGJkOwogIHQuSGNpcmN1bWZsZXggPSAweDAxMjQ7CiAgdC5IZGllcmVzaXMgPSAweDFlMjY7CiAgdC5IZG90YWNjZW50ID0gMHgxZTIyOwogIHQuSGRvdGJlbG93ID0gMHgxZTI0OwogIHQuSG1vbm9zcGFjZSA9IDB4ZmYyODsKICB0LkhvYXJtZW5pYW4gPSAweDA1NDA7CiAgdC5Ib3JpY29wdGljID0gMHgwM2U4OwogIHQuSHNtYWxsID0gMHhmNzY4OwogIHQuSHVuZ2FydW1sYXV0ID0gMHhmNmNmOwogIHQuSHVuZ2FydW1sYXV0c21hbGwgPSAweGY2Zjg7CiAgdC5IenNxdWFyZSA9IDB4MzM5MDsKICB0LkkgPSAweDAwNDk7CiAgdC5JQWN5cmlsbGljID0gMHgwNDJmOwogIHQuSUogPSAweDAxMzI7CiAgdC5JVWN5cmlsbGljID0gMHgwNDJlOwogIHQuSWFjdXRlID0gMHgwMGNkOwogIHQuSWFjdXRlc21hbGwgPSAweGY3ZWQ7CiAgdC5JYnJldmUgPSAweDAxMmM7CiAgdC5JY2Fyb24gPSAweDAxY2Y7CiAgdC5JY2lyY2xlID0gMHgyNGJlOwogIHQuSWNpcmN1bWZsZXggPSAweDAwY2U7CiAgdC5JY2lyY3VtZmxleHNtYWxsID0gMHhmN2VlOwogIHQuSWN5cmlsbGljID0gMHgwNDA2OwogIHQuSWRibGdyYXZlID0gMHgwMjA4OwogIHQuSWRpZXJlc2lzID0gMHgwMGNmOwogIHQuSWRpZXJlc2lzYWN1dGUgPSAweDFlMmU7CiAgdC5JZGllcmVzaXNjeXJpbGxpYyA9IDB4MDRlNDsKICB0LklkaWVyZXNpc3NtYWxsID0gMHhmN2VmOwogIHQuSWRvdCA9IDB4MDEzMDsKICB0Lklkb3RhY2NlbnQgPSAweDAxMzA7CiAgdC5JZG90YmVsb3cgPSAweDFlY2E7CiAgdC5JZWJyZXZlY3lyaWxsaWMgPSAweDA0ZDY7CiAgdC5JZWN5cmlsbGljID0gMHgwNDE1OwogIHQuSWZyYWt0dXIgPSAweDIxMTE7CiAgdC5JZ3JhdmUgPSAweDAwY2M7CiAgdC5JZ3JhdmVzbWFsbCA9IDB4ZjdlYzsKICB0Lklob29rYWJvdmUgPSAweDFlYzg7CiAgdC5JaWN5cmlsbGljID0gMHgwNDE4OwogIHQuSWludmVydGVkYnJldmUgPSAweDAyMGE7CiAgdC5JaXNob3J0Y3lyaWxsaWMgPSAweDA0MTk7CiAgdC5JbWFjcm9uID0gMHgwMTJhOwogIHQuSW1hY3JvbmN5cmlsbGljID0gMHgwNGUyOwogIHQuSW1vbm9zcGFjZSA9IDB4ZmYyOTsKICB0LkluaWFybWVuaWFuID0gMHgwNTNiOwogIHQuSW9jeXJpbGxpYyA9IDB4MDQwMTsKICB0LklvZ29uZWsgPSAweDAxMmU7CiAgdC5Jb3RhID0gMHgwMzk5OwogIHQuSW90YWFmcmljYW4gPSAweDAxOTY7CiAgdC5Jb3RhZGllcmVzaXMgPSAweDAzYWE7CiAgdC5Jb3RhdG9ub3MgPSAweDAzOGE7CiAgdC5Jc21hbGwgPSAweGY3Njk7CiAgdC5Jc3Ryb2tlID0gMHgwMTk3OwogIHQuSXRpbGRlID0gMHgwMTI4OwogIHQuSXRpbGRlYmVsb3cgPSAweDFlMmM7CiAgdC5JemhpdHNhY3lyaWxsaWMgPSAweDA0NzQ7CiAgdC5JemhpdHNhZGJsZ3JhdmVjeXJpbGxpYyA9IDB4MDQ3NjsKICB0LkogPSAweDAwNGE7CiAgdC5KYWFybWVuaWFuID0gMHgwNTQxOwogIHQuSmNpcmNsZSA9IDB4MjRiZjsKICB0LkpjaXJjdW1mbGV4ID0gMHgwMTM0OwogIHQuSmVjeXJpbGxpYyA9IDB4MDQwODsKICB0LkpoZWhhcm1lbmlhbiA9IDB4MDU0YjsKICB0Lkptb25vc3BhY2UgPSAweGZmMmE7CiAgdC5Kc21hbGwgPSAweGY3NmE7CiAgdC5LID0gMHgwMDRiOwogIHQuS0JzcXVhcmUgPSAweDMzODU7CiAgdC5LS3NxdWFyZSA9IDB4MzNjZDsKICB0LkthYmFzaGtpcmN5cmlsbGljID0gMHgwNGEwOwogIHQuS2FjdXRlID0gMHgxZTMwOwogIHQuS2FjeXJpbGxpYyA9IDB4MDQxYTsKICB0LkthZGVzY2VuZGVyY3lyaWxsaWMgPSAweDA0OWE7CiAgdC5LYWhvb2tjeXJpbGxpYyA9IDB4MDRjMzsKICB0LkthcHBhID0gMHgwMzlhOwogIHQuS2FzdHJva2VjeXJpbGxpYyA9IDB4MDQ5ZTsKICB0LkthdmVydGljYWxzdHJva2VjeXJpbGxpYyA9IDB4MDQ5YzsKICB0LktjYXJvbiA9IDB4MDFlODsKICB0LktjZWRpbGxhID0gMHgwMTM2OwogIHQuS2NpcmNsZSA9IDB4MjRjMDsKICB0Lktjb21tYWFjY2VudCA9IDB4MDEzNjsKICB0Lktkb3RiZWxvdyA9IDB4MWUzMjsKICB0LktlaGFybWVuaWFuID0gMHgwNTU0OwogIHQuS2VuYXJtZW5pYW4gPSAweDA1M2Y7CiAgdC5LaGFjeXJpbGxpYyA9IDB4MDQyNTsKICB0LktoZWljb3B0aWMgPSAweDAzZTY7CiAgdC5LaG9vayA9IDB4MDE5ODsKICB0LktqZWN5cmlsbGljID0gMHgwNDBjOwogIHQuS2xpbmViZWxvdyA9IDB4MWUzNDsKICB0Lkttb25vc3BhY2UgPSAweGZmMmI7CiAgdC5Lb3BwYWN5cmlsbGljID0gMHgwNDgwOwogIHQuS29wcGFncmVlayA9IDB4MDNkZTsKICB0LktzaWN5cmlsbGljID0gMHgwNDZlOwogIHQuS3NtYWxsID0gMHhmNzZiOwogIHQuTCA9IDB4MDA0YzsKICB0LkxKID0gMHgwMWM3OwogIHQuTEwgPSAweGY2YmY7CiAgdC5MYWN1dGUgPSAweDAxMzk7CiAgdC5MYW1iZGEgPSAweDAzOWI7CiAgdC5MY2Fyb24gPSAweDAxM2Q7CiAgdC5MY2VkaWxsYSA9IDB4MDEzYjsKICB0LkxjaXJjbGUgPSAweDI0YzE7CiAgdC5MY2lyY3VtZmxleGJlbG93ID0gMHgxZTNjOwogIHQuTGNvbW1hYWNjZW50ID0gMHgwMTNiOwogIHQuTGRvdCA9IDB4MDEzZjsKICB0Lkxkb3RhY2NlbnQgPSAweDAxM2Y7CiAgdC5MZG90YmVsb3cgPSAweDFlMzY7CiAgdC5MZG90YmVsb3dtYWNyb24gPSAweDFlMzg7CiAgdC5MaXduYXJtZW5pYW4gPSAweDA1M2M7CiAgdC5MaiA9IDB4MDFjODsKICB0LkxqZWN5cmlsbGljID0gMHgwNDA5OwogIHQuTGxpbmViZWxvdyA9IDB4MWUzYTsKICB0Lkxtb25vc3BhY2UgPSAweGZmMmM7CiAgdC5Mc2xhc2ggPSAweDAxNDE7CiAgdC5Mc2xhc2hzbWFsbCA9IDB4ZjZmOTsKICB0LkxzbWFsbCA9IDB4Zjc2YzsKICB0Lk0gPSAweDAwNGQ7CiAgdC5NQnNxdWFyZSA9IDB4MzM4NjsKICB0Lk1hY3JvbiA9IDB4ZjZkMDsKICB0Lk1hY3JvbnNtYWxsID0gMHhmN2FmOwogIHQuTWFjdXRlID0gMHgxZTNlOwogIHQuTWNpcmNsZSA9IDB4MjRjMjsKICB0Lk1kb3RhY2NlbnQgPSAweDFlNDA7CiAgdC5NZG90YmVsb3cgPSAweDFlNDI7CiAgdC5NZW5hcm1lbmlhbiA9IDB4MDU0NDsKICB0Lk1tb25vc3BhY2UgPSAweGZmMmQ7CiAgdC5Nc21hbGwgPSAweGY3NmQ7CiAgdC5NdHVybmVkID0gMHgwMTljOwogIHQuTXUgPSAweDAzOWM7CiAgdC5OID0gMHgwMDRlOwogIHQuTkogPSAweDAxY2E7CiAgdC5OYWN1dGUgPSAweDAxNDM7CiAgdC5OY2Fyb24gPSAweDAxNDc7CiAgdC5OY2VkaWxsYSA9IDB4MDE0NTsKICB0Lk5jaXJjbGUgPSAweDI0YzM7CiAgdC5OY2lyY3VtZmxleGJlbG93ID0gMHgxZTRhOwogIHQuTmNvbW1hYWNjZW50ID0gMHgwMTQ1OwogIHQuTmRvdGFjY2VudCA9IDB4MWU0NDsKICB0Lk5kb3RiZWxvdyA9IDB4MWU0NjsKICB0Lk5ob29rbGVmdCA9IDB4MDE5ZDsKICB0Lk5pbmVyb21hbiA9IDB4MjE2ODsKICB0Lk5qID0gMHgwMWNiOwogIHQuTmplY3lyaWxsaWMgPSAweDA0MGE7CiAgdC5ObGluZWJlbG93ID0gMHgxZTQ4OwogIHQuTm1vbm9zcGFjZSA9IDB4ZmYyZTsKICB0Lk5vd2FybWVuaWFuID0gMHgwNTQ2OwogIHQuTnNtYWxsID0gMHhmNzZlOwogIHQuTnRpbGRlID0gMHgwMGQxOwogIHQuTnRpbGRlc21hbGwgPSAweGY3ZjE7CiAgdC5OdSA9IDB4MDM5ZDsKICB0Lk8gPSAweDAwNGY7CiAgdC5PRSA9IDB4MDE1MjsKICB0Lk9Fc21hbGwgPSAweGY2ZmE7CiAgdC5PYWN1dGUgPSAweDAwZDM7CiAgdC5PYWN1dGVzbWFsbCA9IDB4ZjdmMzsKICB0Lk9iYXJyZWRjeXJpbGxpYyA9IDB4MDRlODsKICB0Lk9iYXJyZWRkaWVyZXNpc2N5cmlsbGljID0gMHgwNGVhOwogIHQuT2JyZXZlID0gMHgwMTRlOwogIHQuT2Nhcm9uID0gMHgwMWQxOwogIHQuT2NlbnRlcmVkdGlsZGUgPSAweDAxOWY7CiAgdC5PY2lyY2xlID0gMHgyNGM0OwogIHQuT2NpcmN1bWZsZXggPSAweDAwZDQ7CiAgdC5PY2lyY3VtZmxleGFjdXRlID0gMHgxZWQwOwogIHQuT2NpcmN1bWZsZXhkb3RiZWxvdyA9IDB4MWVkODsKICB0Lk9jaXJjdW1mbGV4Z3JhdmUgPSAweDFlZDI7CiAgdC5PY2lyY3VtZmxleGhvb2thYm92ZSA9IDB4MWVkNDsKICB0Lk9jaXJjdW1mbGV4c21hbGwgPSAweGY3ZjQ7CiAgdC5PY2lyY3VtZmxleHRpbGRlID0gMHgxZWQ2OwogIHQuT2N5cmlsbGljID0gMHgwNDFlOwogIHQuT2RibGFjdXRlID0gMHgwMTUwOwogIHQuT2RibGdyYXZlID0gMHgwMjBjOwogIHQuT2RpZXJlc2lzID0gMHgwMGQ2OwogIHQuT2RpZXJlc2lzY3lyaWxsaWMgPSAweDA0ZTY7CiAgdC5PZGllcmVzaXNzbWFsbCA9IDB4ZjdmNjsKICB0Lk9kb3RiZWxvdyA9IDB4MWVjYzsKICB0Lk9nb25la3NtYWxsID0gMHhmNmZiOwogIHQuT2dyYXZlID0gMHgwMGQyOwogIHQuT2dyYXZlc21hbGwgPSAweGY3ZjI7CiAgdC5PaGFybWVuaWFuID0gMHgwNTU1OwogIHQuT2htID0gMHgyMTI2OwogIHQuT2hvb2thYm92ZSA9IDB4MWVjZTsKICB0Lk9ob3JuID0gMHgwMWEwOwogIHQuT2hvcm5hY3V0ZSA9IDB4MWVkYTsKICB0Lk9ob3JuZG90YmVsb3cgPSAweDFlZTI7CiAgdC5PaG9ybmdyYXZlID0gMHgxZWRjOwogIHQuT2hvcm5ob29rYWJvdmUgPSAweDFlZGU7CiAgdC5PaG9ybnRpbGRlID0gMHgxZWUwOwogIHQuT2h1bmdhcnVtbGF1dCA9IDB4MDE1MDsKICB0Lk9pID0gMHgwMWEyOwogIHQuT2ludmVydGVkYnJldmUgPSAweDAyMGU7CiAgdC5PbWFjcm9uID0gMHgwMTRjOwogIHQuT21hY3JvbmFjdXRlID0gMHgxZTUyOwogIHQuT21hY3JvbmdyYXZlID0gMHgxZTUwOwogIHQuT21lZ2EgPSAweDIxMjY7CiAgdC5PbWVnYWN5cmlsbGljID0gMHgwNDYwOwogIHQuT21lZ2FncmVlayA9IDB4MDNhOTsKICB0Lk9tZWdhcm91bmRjeXJpbGxpYyA9IDB4MDQ3YTsKICB0Lk9tZWdhdGl0bG9jeXJpbGxpYyA9IDB4MDQ3YzsKICB0Lk9tZWdhdG9ub3MgPSAweDAzOGY7CiAgdC5PbWljcm9uID0gMHgwMzlmOwogIHQuT21pY3JvbnRvbm9zID0gMHgwMzhjOwogIHQuT21vbm9zcGFjZSA9IDB4ZmYyZjsKICB0Lk9uZXJvbWFuID0gMHgyMTYwOwogIHQuT29nb25layA9IDB4MDFlYTsKICB0Lk9vZ29uZWttYWNyb24gPSAweDAxZWM7CiAgdC5Pb3BlbiA9IDB4MDE4NjsKICB0Lk9zbGFzaCA9IDB4MDBkODsKICB0Lk9zbGFzaGFjdXRlID0gMHgwMWZlOwogIHQuT3NsYXNoc21hbGwgPSAweGY3Zjg7CiAgdC5Pc21hbGwgPSAweGY3NmY7CiAgdC5Pc3Ryb2tlYWN1dGUgPSAweDAxZmU7CiAgdC5PdGN5cmlsbGljID0gMHgwNDdlOwogIHQuT3RpbGRlID0gMHgwMGQ1OwogIHQuT3RpbGRlYWN1dGUgPSAweDFlNGM7CiAgdC5PdGlsZGVkaWVyZXNpcyA9IDB4MWU0ZTsKICB0Lk90aWxkZXNtYWxsID0gMHhmN2Y1OwogIHQuUCA9IDB4MDA1MDsKICB0LlBhY3V0ZSA9IDB4MWU1NDsKICB0LlBjaXJjbGUgPSAweDI0YzU7CiAgdC5QZG90YWNjZW50ID0gMHgxZTU2OwogIHQuUGVjeXJpbGxpYyA9IDB4MDQxZjsKICB0LlBlaGFybWVuaWFuID0gMHgwNTRhOwogIHQuUGVtaWRkbGVob29rY3lyaWxsaWMgPSAweDA0YTY7CiAgdC5QaGkgPSAweDAzYTY7CiAgdC5QaG9vayA9IDB4MDFhNDsKICB0LlBpID0gMHgwM2EwOwogIHQuUGl3cmFybWVuaWFuID0gMHgwNTUzOwogIHQuUG1vbm9zcGFjZSA9IDB4ZmYzMDsKICB0LlBzaSA9IDB4MDNhODsKICB0LlBzaWN5cmlsbGljID0gMHgwNDcwOwogIHQuUHNtYWxsID0gMHhmNzcwOwogIHQuUSA9IDB4MDA1MTsKICB0LlFjaXJjbGUgPSAweDI0YzY7CiAgdC5RbW9ub3NwYWNlID0gMHhmZjMxOwogIHQuUXNtYWxsID0gMHhmNzcxOwogIHQuUiA9IDB4MDA1MjsKICB0LlJhYXJtZW5pYW4gPSAweDA1NGM7CiAgdC5SYWN1dGUgPSAweDAxNTQ7CiAgdC5SY2Fyb24gPSAweDAxNTg7CiAgdC5SY2VkaWxsYSA9IDB4MDE1NjsKICB0LlJjaXJjbGUgPSAweDI0Yzc7CiAgdC5SY29tbWFhY2NlbnQgPSAweDAxNTY7CiAgdC5SZGJsZ3JhdmUgPSAweDAyMTA7CiAgdC5SZG90YWNjZW50ID0gMHgxZTU4OwogIHQuUmRvdGJlbG93ID0gMHgxZTVhOwogIHQuUmRvdGJlbG93bWFjcm9uID0gMHgxZTVjOwogIHQuUmVoYXJtZW5pYW4gPSAweDA1NTA7CiAgdC5SZnJha3R1ciA9IDB4MjExYzsKICB0LlJobyA9IDB4MDNhMTsKICB0LlJpbmdzbWFsbCA9IDB4ZjZmYzsKICB0LlJpbnZlcnRlZGJyZXZlID0gMHgwMjEyOwogIHQuUmxpbmViZWxvdyA9IDB4MWU1ZTsKICB0LlJtb25vc3BhY2UgPSAweGZmMzI7CiAgdC5Sc21hbGwgPSAweGY3NzI7CiAgdC5Sc21hbGxpbnZlcnRlZCA9IDB4MDI4MTsKICB0LlJzbWFsbGludmVydGVkc3VwZXJpb3IgPSAweDAyYjY7CiAgdC5TID0gMHgwMDUzOwogIHQuU0YwMTAwMDAgPSAweDI1MGM7CiAgdC5TRjAyMDAwMCA9IDB4MjUxNDsKICB0LlNGMDMwMDAwID0gMHgyNTEwOwogIHQuU0YwNDAwMDAgPSAweDI1MTg7CiAgdC5TRjA1MDAwMCA9IDB4MjUzYzsKICB0LlNGMDYwMDAwID0gMHgyNTJjOwogIHQuU0YwNzAwMDAgPSAweDI1MzQ7CiAgdC5TRjA4MDAwMCA9IDB4MjUxYzsKICB0LlNGMDkwMDAwID0gMHgyNTI0OwogIHQuU0YxMDAwMDAgPSAweDI1MDA7CiAgdC5TRjExMDAwMCA9IDB4MjUwMjsKICB0LlNGMTkwMDAwID0gMHgyNTYxOwogIHQuU0YyMDAwMDAgPSAweDI1NjI7CiAgdC5TRjIxMDAwMCA9IDB4MjU1NjsKICB0LlNGMjIwMDAwID0gMHgyNTU1OwogIHQuU0YyMzAwMDAgPSAweDI1NjM7CiAgdC5TRjI0MDAwMCA9IDB4MjU1MTsKICB0LlNGMjUwMDAwID0gMHgyNTU3OwogIHQuU0YyNjAwMDAgPSAweDI1NWQ7CiAgdC5TRjI3MDAwMCA9IDB4MjU1YzsKICB0LlNGMjgwMDAwID0gMHgyNTViOwogIHQuU0YzNjAwMDAgPSAweDI1NWU7CiAgdC5TRjM3MDAwMCA9IDB4MjU1ZjsKICB0LlNGMzgwMDAwID0gMHgyNTVhOwogIHQuU0YzOTAwMDAgPSAweDI1NTQ7CiAgdC5TRjQwMDAwMCA9IDB4MjU2OTsKICB0LlNGNDEwMDAwID0gMHgyNTY2OwogIHQuU0Y0MjAwMDAgPSAweDI1NjA7CiAgdC5TRjQzMDAwMCA9IDB4MjU1MDsKICB0LlNGNDQwMDAwID0gMHgyNTZjOwogIHQuU0Y0NTAwMDAgPSAweDI1Njc7CiAgdC5TRjQ2MDAwMCA9IDB4MjU2ODsKICB0LlNGNDcwMDAwID0gMHgyNTY0OwogIHQuU0Y0ODAwMDAgPSAweDI1NjU7CiAgdC5TRjQ5MDAwMCA9IDB4MjU1OTsKICB0LlNGNTAwMDAwID0gMHgyNTU4OwogIHQuU0Y1MTAwMDAgPSAweDI1NTI7CiAgdC5TRjUyMDAwMCA9IDB4MjU1MzsKICB0LlNGNTMwMDAwID0gMHgyNTZiOwogIHQuU0Y1NDAwMDAgPSAweDI1NmE7CiAgdC5TYWN1dGUgPSAweDAxNWE7CiAgdC5TYWN1dGVkb3RhY2NlbnQgPSAweDFlNjQ7CiAgdC5TYW1waWdyZWVrID0gMHgwM2UwOwogIHQuU2Nhcm9uID0gMHgwMTYwOwogIHQuU2Nhcm9uZG90YWNjZW50ID0gMHgxZTY2OwogIHQuU2Nhcm9uc21hbGwgPSAweGY2ZmQ7CiAgdC5TY2VkaWxsYSA9IDB4MDE1ZTsKICB0LlNjaHdhID0gMHgwMThmOwogIHQuU2Nod2FjeXJpbGxpYyA9IDB4MDRkODsKICB0LlNjaHdhZGllcmVzaXNjeXJpbGxpYyA9IDB4MDRkYTsKICB0LlNjaXJjbGUgPSAweDI0Yzg7CiAgdC5TY2lyY3VtZmxleCA9IDB4MDE1YzsKICB0LlNjb21tYWFjY2VudCA9IDB4MDIxODsKICB0LlNkb3RhY2NlbnQgPSAweDFlNjA7CiAgdC5TZG90YmVsb3cgPSAweDFlNjI7CiAgdC5TZG90YmVsb3dkb3RhY2NlbnQgPSAweDFlNjg7CiAgdC5TZWhhcm1lbmlhbiA9IDB4MDU0ZDsKICB0LlNldmVucm9tYW4gPSAweDIxNjY7CiAgdC5TaGFhcm1lbmlhbiA9IDB4MDU0NzsKICB0LlNoYWN5cmlsbGljID0gMHgwNDI4OwogIHQuU2hjaGFjeXJpbGxpYyA9IDB4MDQyOTsKICB0LlNoZWljb3B0aWMgPSAweDAzZTI7CiAgdC5TaGhhY3lyaWxsaWMgPSAweDA0YmE7CiAgdC5TaGltYWNvcHRpYyA9IDB4MDNlYzsKICB0LlNpZ21hID0gMHgwM2EzOwogIHQuU2l4cm9tYW4gPSAweDIxNjU7CiAgdC5TbW9ub3NwYWNlID0gMHhmZjMzOwogIHQuU29mdHNpZ25jeXJpbGxpYyA9IDB4MDQyYzsKICB0LlNzbWFsbCA9IDB4Zjc3MzsKICB0LlN0aWdtYWdyZWVrID0gMHgwM2RhOwogIHQuVCA9IDB4MDA1NDsKICB0LlRhdSA9IDB4MDNhNDsKICB0LlRiYXIgPSAweDAxNjY7CiAgdC5UY2Fyb24gPSAweDAxNjQ7CiAgdC5UY2VkaWxsYSA9IDB4MDE2MjsKICB0LlRjaXJjbGUgPSAweDI0Yzk7CiAgdC5UY2lyY3VtZmxleGJlbG93ID0gMHgxZTcwOwogIHQuVGNvbW1hYWNjZW50ID0gMHgwMTYyOwogIHQuVGRvdGFjY2VudCA9IDB4MWU2YTsKICB0LlRkb3RiZWxvdyA9IDB4MWU2YzsKICB0LlRlY3lyaWxsaWMgPSAweDA0MjI7CiAgdC5UZWRlc2NlbmRlcmN5cmlsbGljID0gMHgwNGFjOwogIHQuVGVucm9tYW4gPSAweDIxNjk7CiAgdC5UZXRzZWN5cmlsbGljID0gMHgwNGI0OwogIHQuVGhldGEgPSAweDAzOTg7CiAgdC5UaG9vayA9IDB4MDFhYzsKICB0LlRob3JuID0gMHgwMGRlOwogIHQuVGhvcm5zbWFsbCA9IDB4ZjdmZTsKICB0LlRocmVlcm9tYW4gPSAweDIxNjI7CiAgdC5UaWxkZXNtYWxsID0gMHhmNmZlOwogIHQuVGl3bmFybWVuaWFuID0gMHgwNTRmOwogIHQuVGxpbmViZWxvdyA9IDB4MWU2ZTsKICB0LlRtb25vc3BhY2UgPSAweGZmMzQ7CiAgdC5Ub2FybWVuaWFuID0gMHgwNTM5OwogIHQuVG9uZWZpdmUgPSAweDAxYmM7CiAgdC5Ub25lc2l4ID0gMHgwMTg0OwogIHQuVG9uZXR3byA9IDB4MDFhNzsKICB0LlRyZXRyb2ZsZXhob29rID0gMHgwMWFlOwogIHQuVHNlY3lyaWxsaWMgPSAweDA0MjY7CiAgdC5Uc2hlY3lyaWxsaWMgPSAweDA0MGI7CiAgdC5Uc21hbGwgPSAweGY3NzQ7CiAgdC5Ud2VsdmVyb21hbiA9IDB4MjE2YjsKICB0LlR3b3JvbWFuID0gMHgyMTYxOwogIHQuVSA9IDB4MDA1NTsKICB0LlVhY3V0ZSA9IDB4MDBkYTsKICB0LlVhY3V0ZXNtYWxsID0gMHhmN2ZhOwogIHQuVWJyZXZlID0gMHgwMTZjOwogIHQuVWNhcm9uID0gMHgwMWQzOwogIHQuVWNpcmNsZSA9IDB4MjRjYTsKICB0LlVjaXJjdW1mbGV4ID0gMHgwMGRiOwogIHQuVWNpcmN1bWZsZXhiZWxvdyA9IDB4MWU3NjsKICB0LlVjaXJjdW1mbGV4c21hbGwgPSAweGY3ZmI7CiAgdC5VY3lyaWxsaWMgPSAweDA0MjM7CiAgdC5VZGJsYWN1dGUgPSAweDAxNzA7CiAgdC5VZGJsZ3JhdmUgPSAweDAyMTQ7CiAgdC5VZGllcmVzaXMgPSAweDAwZGM7CiAgdC5VZGllcmVzaXNhY3V0ZSA9IDB4MDFkNzsKICB0LlVkaWVyZXNpc2JlbG93ID0gMHgxZTcyOwogIHQuVWRpZXJlc2lzY2Fyb24gPSAweDAxZDk7CiAgdC5VZGllcmVzaXNjeXJpbGxpYyA9IDB4MDRmMDsKICB0LlVkaWVyZXNpc2dyYXZlID0gMHgwMWRiOwogIHQuVWRpZXJlc2lzbWFjcm9uID0gMHgwMWQ1OwogIHQuVWRpZXJlc2lzc21hbGwgPSAweGY3ZmM7CiAgdC5VZG90YmVsb3cgPSAweDFlZTQ7CiAgdC5VZ3JhdmUgPSAweDAwZDk7CiAgdC5VZ3JhdmVzbWFsbCA9IDB4ZjdmOTsKICB0LlVob29rYWJvdmUgPSAweDFlZTY7CiAgdC5VaG9ybiA9IDB4MDFhZjsKICB0LlVob3JuYWN1dGUgPSAweDFlZTg7CiAgdC5VaG9ybmRvdGJlbG93ID0gMHgxZWYwOwogIHQuVWhvcm5ncmF2ZSA9IDB4MWVlYTsKICB0LlVob3JuaG9va2Fib3ZlID0gMHgxZWVjOwogIHQuVWhvcm50aWxkZSA9IDB4MWVlZTsKICB0LlVodW5nYXJ1bWxhdXQgPSAweDAxNzA7CiAgdC5VaHVuZ2FydW1sYXV0Y3lyaWxsaWMgPSAweDA0ZjI7CiAgdC5VaW52ZXJ0ZWRicmV2ZSA9IDB4MDIxNjsKICB0LlVrY3lyaWxsaWMgPSAweDA0Nzg7CiAgdC5VbWFjcm9uID0gMHgwMTZhOwogIHQuVW1hY3JvbmN5cmlsbGljID0gMHgwNGVlOwogIHQuVW1hY3JvbmRpZXJlc2lzID0gMHgxZTdhOwogIHQuVW1vbm9zcGFjZSA9IDB4ZmYzNTsKICB0LlVvZ29uZWsgPSAweDAxNzI7CiAgdC5VcHNpbG9uID0gMHgwM2E1OwogIHQuVXBzaWxvbjEgPSAweDAzZDI7CiAgdC5VcHNpbG9uYWN1dGVob29rc3ltYm9sZ3JlZWsgPSAweDAzZDM7CiAgdC5VcHNpbG9uYWZyaWNhbiA9IDB4MDFiMTsKICB0LlVwc2lsb25kaWVyZXNpcyA9IDB4MDNhYjsKICB0LlVwc2lsb25kaWVyZXNpc2hvb2tzeW1ib2xncmVlayA9IDB4MDNkNDsKICB0LlVwc2lsb25ob29rc3ltYm9sID0gMHgwM2QyOwogIHQuVXBzaWxvbnRvbm9zID0gMHgwMzhlOwogIHQuVXJpbmcgPSAweDAxNmU7CiAgdC5Vc2hvcnRjeXJpbGxpYyA9IDB4MDQwZTsKICB0LlVzbWFsbCA9IDB4Zjc3NTsKICB0LlVzdHJhaWdodGN5cmlsbGljID0gMHgwNGFlOwogIHQuVXN0cmFpZ2h0c3Ryb2tlY3lyaWxsaWMgPSAweDA0YjA7CiAgdC5VdGlsZGUgPSAweDAxNjg7CiAgdC5VdGlsZGVhY3V0ZSA9IDB4MWU3ODsKICB0LlV0aWxkZWJlbG93ID0gMHgxZTc0OwogIHQuViA9IDB4MDA1NjsKICB0LlZjaXJjbGUgPSAweDI0Y2I7CiAgdC5WZG90YmVsb3cgPSAweDFlN2U7CiAgdC5WZWN5cmlsbGljID0gMHgwNDEyOwogIHQuVmV3YXJtZW5pYW4gPSAweDA1NGU7CiAgdC5WaG9vayA9IDB4MDFiMjsKICB0LlZtb25vc3BhY2UgPSAweGZmMzY7CiAgdC5Wb2FybWVuaWFuID0gMHgwNTQ4OwogIHQuVnNtYWxsID0gMHhmNzc2OwogIHQuVnRpbGRlID0gMHgxZTdjOwogIHQuVyA9IDB4MDA1NzsKICB0LldhY3V0ZSA9IDB4MWU4MjsKICB0LldjaXJjbGUgPSAweDI0Y2M7CiAgdC5XY2lyY3VtZmxleCA9IDB4MDE3NDsKICB0LldkaWVyZXNpcyA9IDB4MWU4NDsKICB0Lldkb3RhY2NlbnQgPSAweDFlODY7CiAgdC5XZG90YmVsb3cgPSAweDFlODg7CiAgdC5XZ3JhdmUgPSAweDFlODA7CiAgdC5XbW9ub3NwYWNlID0gMHhmZjM3OwogIHQuV3NtYWxsID0gMHhmNzc3OwogIHQuWCA9IDB4MDA1ODsKICB0LlhjaXJjbGUgPSAweDI0Y2Q7CiAgdC5YZGllcmVzaXMgPSAweDFlOGM7CiAgdC5YZG90YWNjZW50ID0gMHgxZThhOwogIHQuWGVoYXJtZW5pYW4gPSAweDA1M2Q7CiAgdC5YaSA9IDB4MDM5ZTsKICB0Llhtb25vc3BhY2UgPSAweGZmMzg7CiAgdC5Yc21hbGwgPSAweGY3Nzg7CiAgdC5ZID0gMHgwMDU5OwogIHQuWWFjdXRlID0gMHgwMGRkOwogIHQuWWFjdXRlc21hbGwgPSAweGY3ZmQ7CiAgdC5ZYXRjeXJpbGxpYyA9IDB4MDQ2MjsKICB0LlljaXJjbGUgPSAweDI0Y2U7CiAgdC5ZY2lyY3VtZmxleCA9IDB4MDE3NjsKICB0LllkaWVyZXNpcyA9IDB4MDE3ODsKICB0LllkaWVyZXNpc3NtYWxsID0gMHhmN2ZmOwogIHQuWWRvdGFjY2VudCA9IDB4MWU4ZTsKICB0Lllkb3RiZWxvdyA9IDB4MWVmNDsKICB0LlllcmljeXJpbGxpYyA9IDB4MDQyYjsKICB0LlllcnVkaWVyZXNpc2N5cmlsbGljID0gMHgwNGY4OwogIHQuWWdyYXZlID0gMHgxZWYyOwogIHQuWWhvb2sgPSAweDAxYjM7CiAgdC5ZaG9va2Fib3ZlID0gMHgxZWY2OwogIHQuWWlhcm1lbmlhbiA9IDB4MDU0NTsKICB0LllpY3lyaWxsaWMgPSAweDA0MDc7CiAgdC5ZaXduYXJtZW5pYW4gPSAweDA1NTI7CiAgdC5ZbW9ub3NwYWNlID0gMHhmZjM5OwogIHQuWXNtYWxsID0gMHhmNzc5OwogIHQuWXRpbGRlID0gMHgxZWY4OwogIHQuWXVzYmlnY3lyaWxsaWMgPSAweDA0NmE7CiAgdC5ZdXNiaWdpb3RpZmllZGN5cmlsbGljID0gMHgwNDZjOwogIHQuWXVzbGl0dGxlY3lyaWxsaWMgPSAweDA0NjY7CiAgdC5ZdXNsaXR0bGVpb3RpZmllZGN5cmlsbGljID0gMHgwNDY4OwogIHQuWiA9IDB4MDA1YTsKICB0LlphYXJtZW5pYW4gPSAweDA1MzY7CiAgdC5aYWN1dGUgPSAweDAxNzk7CiAgdC5aY2Fyb24gPSAweDAxN2Q7CiAgdC5aY2Fyb25zbWFsbCA9IDB4ZjZmZjsKICB0LlpjaXJjbGUgPSAweDI0Y2Y7CiAgdC5aY2lyY3VtZmxleCA9IDB4MWU5MDsKICB0Llpkb3QgPSAweDAxN2I7CiAgdC5aZG90YWNjZW50ID0gMHgwMTdiOwogIHQuWmRvdGJlbG93ID0gMHgxZTkyOwogIHQuWmVjeXJpbGxpYyA9IDB4MDQxNzsKICB0LlplZGVzY2VuZGVyY3lyaWxsaWMgPSAweDA0OTg7CiAgdC5aZWRpZXJlc2lzY3lyaWxsaWMgPSAweDA0ZGU7CiAgdC5aZXRhID0gMHgwMzk2OwogIHQuWmhlYXJtZW5pYW4gPSAweDA1M2E7CiAgdC5aaGVicmV2ZWN5cmlsbGljID0gMHgwNGMxOwogIHQuWmhlY3lyaWxsaWMgPSAweDA0MTY7CiAgdC5aaGVkZXNjZW5kZXJjeXJpbGxpYyA9IDB4MDQ5NjsKICB0LlpoZWRpZXJlc2lzY3lyaWxsaWMgPSAweDA0ZGM7CiAgdC5abGluZWJlbG93ID0gMHgxZTk0OwogIHQuWm1vbm9zcGFjZSA9IDB4ZmYzYTsKICB0LlpzbWFsbCA9IDB4Zjc3YTsKICB0LlpzdHJva2UgPSAweDAxYjU7CiAgdC5hID0gMHgwMDYxOwogIHQuYWFiZW5nYWxpID0gMHgwOTg2OwogIHQuYWFjdXRlID0gMHgwMGUxOwogIHQuYWFkZXZhID0gMHgwOTA2OwogIHQuYWFndWphcmF0aSA9IDB4MGE4NjsKICB0LmFhZ3VybXVraGkgPSAweDBhMDY7CiAgdC5hYW1hdHJhZ3VybXVraGkgPSAweDBhM2U7CiAgdC5hYXJ1c3F1YXJlID0gMHgzMzAzOwogIHQuYWF2b3dlbHNpZ25iZW5nYWxpID0gMHgwOWJlOwogIHQuYWF2b3dlbHNpZ25kZXZhID0gMHgwOTNlOwogIHQuYWF2b3dlbHNpZ25ndWphcmF0aSA9IDB4MGFiZTsKICB0LmFiYnJldmlhdGlvbm1hcmthcm1lbmlhbiA9IDB4MDU1ZjsKICB0LmFiYnJldmlhdGlvbnNpZ25kZXZhID0gMHgwOTcwOwogIHQuYWJlbmdhbGkgPSAweDA5ODU7CiAgdC5hYm9wb21vZm8gPSAweDMxMWE7CiAgdC5hYnJldmUgPSAweDAxMDM7CiAgdC5hYnJldmVhY3V0ZSA9IDB4MWVhZjsKICB0LmFicmV2ZWN5cmlsbGljID0gMHgwNGQxOwogIHQuYWJyZXZlZG90YmVsb3cgPSAweDFlYjc7CiAgdC5hYnJldmVncmF2ZSA9IDB4MWViMTsKICB0LmFicmV2ZWhvb2thYm92ZSA9IDB4MWViMzsKICB0LmFicmV2ZXRpbGRlID0gMHgxZWI1OwogIHQuYWNhcm9uID0gMHgwMWNlOwogIHQuYWNpcmNsZSA9IDB4MjRkMDsKICB0LmFjaXJjdW1mbGV4ID0gMHgwMGUyOwogIHQuYWNpcmN1bWZsZXhhY3V0ZSA9IDB4MWVhNTsKICB0LmFjaXJjdW1mbGV4ZG90YmVsb3cgPSAweDFlYWQ7CiAgdC5hY2lyY3VtZmxleGdyYXZlID0gMHgxZWE3OwogIHQuYWNpcmN1bWZsZXhob29rYWJvdmUgPSAweDFlYTk7CiAgdC5hY2lyY3VtZmxleHRpbGRlID0gMHgxZWFiOwogIHQuYWN1dGUgPSAweDAwYjQ7CiAgdC5hY3V0ZWJlbG93Y21iID0gMHgwMzE3OwogIHQuYWN1dGVjbWIgPSAweDAzMDE7CiAgdC5hY3V0ZWNvbWIgPSAweDAzMDE7CiAgdC5hY3V0ZWRldmEgPSAweDA5NTQ7CiAgdC5hY3V0ZWxvd21vZCA9IDB4MDJjZjsKICB0LmFjdXRldG9uZWNtYiA9IDB4MDM0MTsKICB0LmFjeXJpbGxpYyA9IDB4MDQzMDsKICB0LmFkYmxncmF2ZSA9IDB4MDIwMTsKICB0LmFkZGFrZ3VybXVraGkgPSAweDBhNzE7CiAgdC5hZGV2YSA9IDB4MDkwNTsKICB0LmFkaWVyZXNpcyA9IDB4MDBlNDsKICB0LmFkaWVyZXNpc2N5cmlsbGljID0gMHgwNGQzOwogIHQuYWRpZXJlc2lzbWFjcm9uID0gMHgwMWRmOwogIHQuYWRvdGJlbG93ID0gMHgxZWExOwogIHQuYWRvdG1hY3JvbiA9IDB4MDFlMTsKICB0LmFlID0gMHgwMGU2OwogIHQuYWVhY3V0ZSA9IDB4MDFmZDsKICB0LmFla29yZWFuID0gMHgzMTUwOwogIHQuYWVtYWNyb24gPSAweDAxZTM7CiAgdC5hZmlpMDAyMDggPSAweDIwMTU7CiAgdC5hZmlpMDg5NDEgPSAweDIwYTQ7CiAgdC5hZmlpMTAwMTcgPSAweDA0MTA7CiAgdC5hZmlpMTAwMTggPSAweDA0MTE7CiAgdC5hZmlpMTAwMTkgPSAweDA0MTI7CiAgdC5hZmlpMTAwMjAgPSAweDA0MTM7CiAgdC5hZmlpMTAwMjEgPSAweDA0MTQ7CiAgdC5hZmlpMTAwMjIgPSAweDA0MTU7CiAgdC5hZmlpMTAwMjMgPSAweDA0MDE7CiAgdC5hZmlpMTAwMjQgPSAweDA0MTY7CiAgdC5hZmlpMTAwMjUgPSAweDA0MTc7CiAgdC5hZmlpMTAwMjYgPSAweDA0MTg7CiAgdC5hZmlpMTAwMjcgPSAweDA0MTk7CiAgdC5hZmlpMTAwMjggPSAweDA0MWE7CiAgdC5hZmlpMTAwMjkgPSAweDA0MWI7CiAgdC5hZmlpMTAwMzAgPSAweDA0MWM7CiAgdC5hZmlpMTAwMzEgPSAweDA0MWQ7CiAgdC5hZmlpMTAwMzIgPSAweDA0MWU7CiAgdC5hZmlpMTAwMzMgPSAweDA0MWY7CiAgdC5hZmlpMTAwMzQgPSAweDA0MjA7CiAgdC5hZmlpMTAwMzUgPSAweDA0MjE7CiAgdC5hZmlpMTAwMzYgPSAweDA0MjI7CiAgdC5hZmlpMTAwMzcgPSAweDA0MjM7CiAgdC5hZmlpMTAwMzggPSAweDA0MjQ7CiAgdC5hZmlpMTAwMzkgPSAweDA0MjU7CiAgdC5hZmlpMTAwNDAgPSAweDA0MjY7CiAgdC5hZmlpMTAwNDEgPSAweDA0Mjc7CiAgdC5hZmlpMTAwNDIgPSAweDA0Mjg7CiAgdC5hZmlpMTAwNDMgPSAweDA0Mjk7CiAgdC5hZmlpMTAwNDQgPSAweDA0MmE7CiAgdC5hZmlpMTAwNDUgPSAweDA0MmI7CiAgdC5hZmlpMTAwNDYgPSAweDA0MmM7CiAgdC5hZmlpMTAwNDcgPSAweDA0MmQ7CiAgdC5hZmlpMTAwNDggPSAweDA0MmU7CiAgdC5hZmlpMTAwNDkgPSAweDA0MmY7CiAgdC5hZmlpMTAwNTAgPSAweDA0OTA7CiAgdC5hZmlpMTAwNTEgPSAweDA0MDI7CiAgdC5hZmlpMTAwNTIgPSAweDA0MDM7CiAgdC5hZmlpMTAwNTMgPSAweDA0MDQ7CiAgdC5hZmlpMTAwNTQgPSAweDA0MDU7CiAgdC5hZmlpMTAwNTUgPSAweDA0MDY7CiAgdC5hZmlpMTAwNTYgPSAweDA0MDc7CiAgdC5hZmlpMTAwNTcgPSAweDA0MDg7CiAgdC5hZmlpMTAwNTggPSAweDA0MDk7CiAgdC5hZmlpMTAwNTkgPSAweDA0MGE7CiAgdC5hZmlpMTAwNjAgPSAweDA0MGI7CiAgdC5hZmlpMTAwNjEgPSAweDA0MGM7CiAgdC5hZmlpMTAwNjIgPSAweDA0MGU7CiAgdC5hZmlpMTAwNjMgPSAweGY2YzQ7CiAgdC5hZmlpMTAwNjQgPSAweGY2YzU7CiAgdC5hZmlpMTAwNjUgPSAweDA0MzA7CiAgdC5hZmlpMTAwNjYgPSAweDA0MzE7CiAgdC5hZmlpMTAwNjcgPSAweDA0MzI7CiAgdC5hZmlpMTAwNjggPSAweDA0MzM7CiAgdC5hZmlpMTAwNjkgPSAweDA0MzQ7CiAgdC5hZmlpMTAwNzAgPSAweDA0MzU7CiAgdC5hZmlpMTAwNzEgPSAweDA0NTE7CiAgdC5hZmlpMTAwNzIgPSAweDA0MzY7CiAgdC5hZmlpMTAwNzMgPSAweDA0Mzc7CiAgdC5hZmlpMTAwNzQgPSAweDA0Mzg7CiAgdC5hZmlpMTAwNzUgPSAweDA0Mzk7CiAgdC5hZmlpMTAwNzYgPSAweDA0M2E7CiAgdC5hZmlpMTAwNzcgPSAweDA0M2I7CiAgdC5hZmlpMTAwNzggPSAweDA0M2M7CiAgdC5hZmlpMTAwNzkgPSAweDA0M2Q7CiAgdC5hZmlpMTAwODAgPSAweDA0M2U7CiAgdC5hZmlpMTAwODEgPSAweDA0M2Y7CiAgdC5hZmlpMTAwODIgPSAweDA0NDA7CiAgdC5hZmlpMTAwODMgPSAweDA0NDE7CiAgdC5hZmlpMTAwODQgPSAweDA0NDI7CiAgdC5hZmlpMTAwODUgPSAweDA0NDM7CiAgdC5hZmlpMTAwODYgPSAweDA0NDQ7CiAgdC5hZmlpMTAwODcgPSAweDA0NDU7CiAgdC5hZmlpMTAwODggPSAweDA0NDY7CiAgdC5hZmlpMTAwODkgPSAweDA0NDc7CiAgdC5hZmlpMTAwOTAgPSAweDA0NDg7CiAgdC5hZmlpMTAwOTEgPSAweDA0NDk7CiAgdC5hZmlpMTAwOTIgPSAweDA0NGE7CiAgdC5hZmlpMTAwOTMgPSAweDA0NGI7CiAgdC5hZmlpMTAwOTQgPSAweDA0NGM7CiAgdC5hZmlpMTAwOTUgPSAweDA0NGQ7CiAgdC5hZmlpMTAwOTYgPSAweDA0NGU7CiAgdC5hZmlpMTAwOTcgPSAweDA0NGY7CiAgdC5hZmlpMTAwOTggPSAweDA0OTE7CiAgdC5hZmlpMTAwOTkgPSAweDA0NTI7CiAgdC5hZmlpMTAxMDAgPSAweDA0NTM7CiAgdC5hZmlpMTAxMDEgPSAweDA0NTQ7CiAgdC5hZmlpMTAxMDIgPSAweDA0NTU7CiAgdC5hZmlpMTAxMDMgPSAweDA0NTY7CiAgdC5hZmlpMTAxMDQgPSAweDA0NTc7CiAgdC5hZmlpMTAxMDUgPSAweDA0NTg7CiAgdC5hZmlpMTAxMDYgPSAweDA0NTk7CiAgdC5hZmlpMTAxMDcgPSAweDA0NWE7CiAgdC5hZmlpMTAxMDggPSAweDA0NWI7CiAgdC5hZmlpMTAxMDkgPSAweDA0NWM7CiAgdC5hZmlpMTAxMTAgPSAweDA0NWU7CiAgdC5hZmlpMTAxNDUgPSAweDA0MGY7CiAgdC5hZmlpMTAxNDYgPSAweDA0NjI7CiAgdC5hZmlpMTAxNDcgPSAweDA0NzI7CiAgdC5hZmlpMTAxNDggPSAweDA0NzQ7CiAgdC5hZmlpMTAxOTIgPSAweGY2YzY7CiAgdC5hZmlpMTAxOTMgPSAweDA0NWY7CiAgdC5hZmlpMTAxOTQgPSAweDA0NjM7CiAgdC5hZmlpMTAxOTUgPSAweDA0NzM7CiAgdC5hZmlpMTAxOTYgPSAweDA0NzU7CiAgdC5hZmlpMTA4MzEgPSAweGY2Yzc7CiAgdC5hZmlpMTA4MzIgPSAweGY2Yzg7CiAgdC5hZmlpMTA4NDYgPSAweDA0ZDk7CiAgdC5hZmlpMjk5ID0gMHgyMDBlOwogIHQuYWZpaTMwMCA9IDB4MjAwZjsKICB0LmFmaWkzMDEgPSAweDIwMGQ7CiAgdC5hZmlpNTczODEgPSAweDA2NmE7CiAgdC5hZmlpNTczODggPSAweDA2MGM7CiAgdC5hZmlpNTczOTIgPSAweDA2NjA7CiAgdC5hZmlpNTczOTMgPSAweDA2NjE7CiAgdC5hZmlpNTczOTQgPSAweDA2NjI7CiAgdC5hZmlpNTczOTUgPSAweDA2NjM7CiAgdC5hZmlpNTczOTYgPSAweDA2NjQ7CiAgdC5hZmlpNTczOTcgPSAweDA2NjU7CiAgdC5hZmlpNTczOTggPSAweDA2NjY7CiAgdC5hZmlpNTczOTkgPSAweDA2Njc7CiAgdC5hZmlpNTc0MDAgPSAweDA2Njg7CiAgdC5hZmlpNTc0MDEgPSAweDA2Njk7CiAgdC5hZmlpNTc0MDMgPSAweDA2MWI7CiAgdC5hZmlpNTc0MDcgPSAweDA2MWY7CiAgdC5hZmlpNTc0MDkgPSAweDA2MjE7CiAgdC5hZmlpNTc0MTAgPSAweDA2MjI7CiAgdC5hZmlpNTc0MTEgPSAweDA2MjM7CiAgdC5hZmlpNTc0MTIgPSAweDA2MjQ7CiAgdC5hZmlpNTc0MTMgPSAweDA2MjU7CiAgdC5hZmlpNTc0MTQgPSAweDA2MjY7CiAgdC5hZmlpNTc0MTUgPSAweDA2Mjc7CiAgdC5hZmlpNTc0MTYgPSAweDA2Mjg7CiAgdC5hZmlpNTc0MTcgPSAweDA2Mjk7CiAgdC5hZmlpNTc0MTggPSAweDA2MmE7CiAgdC5hZmlpNTc0MTkgPSAweDA2MmI7CiAgdC5hZmlpNTc0MjAgPSAweDA2MmM7CiAgdC5hZmlpNTc0MjEgPSAweDA2MmQ7CiAgdC5hZmlpNTc0MjIgPSAweDA2MmU7CiAgdC5hZmlpNTc0MjMgPSAweDA2MmY7CiAgdC5hZmlpNTc0MjQgPSAweDA2MzA7CiAgdC5hZmlpNTc0MjUgPSAweDA2MzE7CiAgdC5hZmlpNTc0MjYgPSAweDA2MzI7CiAgdC5hZmlpNTc0MjcgPSAweDA2MzM7CiAgdC5hZmlpNTc0MjggPSAweDA2MzQ7CiAgdC5hZmlpNTc0MjkgPSAweDA2MzU7CiAgdC5hZmlpNTc0MzAgPSAweDA2MzY7CiAgdC5hZmlpNTc0MzEgPSAweDA2Mzc7CiAgdC5hZmlpNTc0MzIgPSAweDA2Mzg7CiAgdC5hZmlpNTc0MzMgPSAweDA2Mzk7CiAgdC5hZmlpNTc0MzQgPSAweDA2M2E7CiAgdC5hZmlpNTc0NDAgPSAweDA2NDA7CiAgdC5hZmlpNTc0NDEgPSAweDA2NDE7CiAgdC5hZmlpNTc0NDIgPSAweDA2NDI7CiAgdC5hZmlpNTc0NDMgPSAweDA2NDM7CiAgdC5hZmlpNTc0NDQgPSAweDA2NDQ7CiAgdC5hZmlpNTc0NDUgPSAweDA2NDU7CiAgdC5hZmlpNTc0NDYgPSAweDA2NDY7CiAgdC5hZmlpNTc0NDggPSAweDA2NDg7CiAgdC5hZmlpNTc0NDkgPSAweDA2NDk7CiAgdC5hZmlpNTc0NTAgPSAweDA2NGE7CiAgdC5hZmlpNTc0NTEgPSAweDA2NGI7CiAgdC5hZmlpNTc0NTIgPSAweDA2NGM7CiAgdC5hZmlpNTc0NTMgPSAweDA2NGQ7CiAgdC5hZmlpNTc0NTQgPSAweDA2NGU7CiAgdC5hZmlpNTc0NTUgPSAweDA2NGY7CiAgdC5hZmlpNTc0NTYgPSAweDA2NTA7CiAgdC5hZmlpNTc0NTcgPSAweDA2NTE7CiAgdC5hZmlpNTc0NTggPSAweDA2NTI7CiAgdC5hZmlpNTc0NzAgPSAweDA2NDc7CiAgdC5hZmlpNTc1MDUgPSAweDA2YTQ7CiAgdC5hZmlpNTc1MDYgPSAweDA2N2U7CiAgdC5hZmlpNTc1MDcgPSAweDA2ODY7CiAgdC5hZmlpNTc1MDggPSAweDA2OTg7CiAgdC5hZmlpNTc1MDkgPSAweDA2YWY7CiAgdC5hZmlpNTc1MTEgPSAweDA2Nzk7CiAgdC5hZmlpNTc1MTIgPSAweDA2ODg7CiAgdC5hZmlpNTc1MTMgPSAweDA2OTE7CiAgdC5hZmlpNTc1MTQgPSAweDA2YmE7CiAgdC5hZmlpNTc1MTkgPSAweDA2ZDI7CiAgdC5hZmlpNTc1MzQgPSAweDA2ZDU7CiAgdC5hZmlpNTc2MzYgPSAweDIwYWE7CiAgdC5hZmlpNTc2NDUgPSAweDA1YmU7CiAgdC5hZmlpNTc2NTggPSAweDA1YzM7CiAgdC5hZmlpNTc2NjQgPSAweDA1ZDA7CiAgdC5hZmlpNTc2NjUgPSAweDA1ZDE7CiAgdC5hZmlpNTc2NjYgPSAweDA1ZDI7CiAgdC5hZmlpNTc2NjcgPSAweDA1ZDM7CiAgdC5hZmlpNTc2NjggPSAweDA1ZDQ7CiAgdC5hZmlpNTc2NjkgPSAweDA1ZDU7CiAgdC5hZmlpNTc2NzAgPSAweDA1ZDY7CiAgdC5hZmlpNTc2NzEgPSAweDA1ZDc7CiAgdC5hZmlpNTc2NzIgPSAweDA1ZDg7CiAgdC5hZmlpNTc2NzMgPSAweDA1ZDk7CiAgdC5hZmlpNTc2NzQgPSAweDA1ZGE7CiAgdC5hZmlpNTc2NzUgPSAweDA1ZGI7CiAgdC5hZmlpNTc2NzYgPSAweDA1ZGM7CiAgdC5hZmlpNTc2NzcgPSAweDA1ZGQ7CiAgdC5hZmlpNTc2NzggPSAweDA1ZGU7CiAgdC5hZmlpNTc2NzkgPSAweDA1ZGY7CiAgdC5hZmlpNTc2ODAgPSAweDA1ZTA7CiAgdC5hZmlpNTc2ODEgPSAweDA1ZTE7CiAgdC5hZmlpNTc2ODIgPSAweDA1ZTI7CiAgdC5hZmlpNTc2ODMgPSAweDA1ZTM7CiAgdC5hZmlpNTc2ODQgPSAweDA1ZTQ7CiAgdC5hZmlpNTc2ODUgPSAweDA1ZTU7CiAgdC5hZmlpNTc2ODYgPSAweDA1ZTY7CiAgdC5hZmlpNTc2ODcgPSAweDA1ZTc7CiAgdC5hZmlpNTc2ODggPSAweDA1ZTg7CiAgdC5hZmlpNTc2ODkgPSAweDA1ZTk7CiAgdC5hZmlpNTc2OTAgPSAweDA1ZWE7CiAgdC5hZmlpNTc2OTQgPSAweGZiMmE7CiAgdC5hZmlpNTc2OTUgPSAweGZiMmI7CiAgdC5hZmlpNTc3MDAgPSAweGZiNGI7CiAgdC5hZmlpNTc3MDUgPSAweGZiMWY7CiAgdC5hZmlpNTc3MTYgPSAweDA1ZjA7CiAgdC5hZmlpNTc3MTcgPSAweDA1ZjE7CiAgdC5hZmlpNTc3MTggPSAweDA1ZjI7CiAgdC5hZmlpNTc3MjMgPSAweGZiMzU7CiAgdC5hZmlpNTc3OTMgPSAweDA1YjQ7CiAgdC5hZmlpNTc3OTQgPSAweDA1YjU7CiAgdC5hZmlpNTc3OTUgPSAweDA1YjY7CiAgdC5hZmlpNTc3OTYgPSAweDA1YmI7CiAgdC5hZmlpNTc3OTcgPSAweDA1Yjg7CiAgdC5hZmlpNTc3OTggPSAweDA1Yjc7CiAgdC5hZmlpNTc3OTkgPSAweDA1YjA7CiAgdC5hZmlpNTc4MDAgPSAweDA1YjI7CiAgdC5hZmlpNTc4MDEgPSAweDA1YjE7CiAgdC5hZmlpNTc4MDIgPSAweDA1YjM7CiAgdC5hZmlpNTc4MDMgPSAweDA1YzI7CiAgdC5hZmlpNTc4MDQgPSAweDA1YzE7CiAgdC5hZmlpNTc4MDYgPSAweDA1Yjk7CiAgdC5hZmlpNTc4MDcgPSAweDA1YmM7CiAgdC5hZmlpNTc4MzkgPSAweDA1YmQ7CiAgdC5hZmlpNTc4NDEgPSAweDA1YmY7CiAgdC5hZmlpNTc4NDIgPSAweDA1YzA7CiAgdC5hZmlpNTc5MjkgPSAweDAyYmM7CiAgdC5hZmlpNjEyNDggPSAweDIxMDU7CiAgdC5hZmlpNjEyODkgPSAweDIxMTM7CiAgdC5hZmlpNjEzNTIgPSAweDIxMTY7CiAgdC5hZmlpNjE1NzMgPSAweDIwMmM7CiAgdC5hZmlpNjE1NzQgPSAweDIwMmQ7CiAgdC5hZmlpNjE1NzUgPSAweDIwMmU7CiAgdC5hZmlpNjE2NjQgPSAweDIwMGM7CiAgdC5hZmlpNjMxNjcgPSAweDA2NmQ7CiAgdC5hZmlpNjQ5MzcgPSAweDAyYmQ7CiAgdC5hZ3JhdmUgPSAweDAwZTA7CiAgdC5hZ3VqYXJhdGkgPSAweDBhODU7CiAgdC5hZ3VybXVraGkgPSAweDBhMDU7CiAgdC5haGlyYWdhbmEgPSAweDMwNDI7CiAgdC5haG9va2Fib3ZlID0gMHgxZWEzOwogIHQuYWliZW5nYWxpID0gMHgwOTkwOwogIHQuYWlib3BvbW9mbyA9IDB4MzExZTsKICB0LmFpZGV2YSA9IDB4MDkxMDsKICB0LmFpZWN5cmlsbGljID0gMHgwNGQ1OwogIHQuYWlndWphcmF0aSA9IDB4MGE5MDsKICB0LmFpZ3VybXVraGkgPSAweDBhMTA7CiAgdC5haW1hdHJhZ3VybXVraGkgPSAweDBhNDg7CiAgdC5haW5hcmFiaWMgPSAweDA2Mzk7CiAgdC5haW5maW5hbGFyYWJpYyA9IDB4ZmVjYTsKICB0LmFpbmluaXRpYWxhcmFiaWMgPSAweGZlY2I7CiAgdC5haW5tZWRpYWxhcmFiaWMgPSAweGZlY2M7CiAgdC5haW52ZXJ0ZWRicmV2ZSA9IDB4MDIwMzsKICB0LmFpdm93ZWxzaWduYmVuZ2FsaSA9IDB4MDljODsKICB0LmFpdm93ZWxzaWduZGV2YSA9IDB4MDk0ODsKICB0LmFpdm93ZWxzaWduZ3VqYXJhdGkgPSAweDBhYzg7CiAgdC5ha2F0YWthbmEgPSAweDMwYTI7CiAgdC5ha2F0YWthbmFoYWxmd2lkdGggPSAweGZmNzE7CiAgdC5ha29yZWFuID0gMHgzMTRmOwogIHQuYWxlZiA9IDB4MDVkMDsKICB0LmFsZWZhcmFiaWMgPSAweDA2Mjc7CiAgdC5hbGVmZGFnZXNoaGVicmV3ID0gMHhmYjMwOwogIHQuYWxlZmZpbmFsYXJhYmljID0gMHhmZThlOwogIHQuYWxlZmhhbXphYWJvdmVhcmFiaWMgPSAweDA2MjM7CiAgdC5hbGVmaGFtemFhYm92ZWZpbmFsYXJhYmljID0gMHhmZTg0OwogIHQuYWxlZmhhbXphYmVsb3dhcmFiaWMgPSAweDA2MjU7CiAgdC5hbGVmaGFtemFiZWxvd2ZpbmFsYXJhYmljID0gMHhmZTg4OwogIHQuYWxlZmhlYnJldyA9IDB4MDVkMDsKICB0LmFsZWZsYW1lZGhlYnJldyA9IDB4ZmI0ZjsKICB0LmFsZWZtYWRkYWFib3ZlYXJhYmljID0gMHgwNjIyOwogIHQuYWxlZm1hZGRhYWJvdmVmaW5hbGFyYWJpYyA9IDB4ZmU4MjsKICB0LmFsZWZtYWtzdXJhYXJhYmljID0gMHgwNjQ5OwogIHQuYWxlZm1ha3N1cmFmaW5hbGFyYWJpYyA9IDB4ZmVmMDsKICB0LmFsZWZtYWtzdXJhaW5pdGlhbGFyYWJpYyA9IDB4ZmVmMzsKICB0LmFsZWZtYWtzdXJhbWVkaWFsYXJhYmljID0gMHhmZWY0OwogIHQuYWxlZnBhdGFoaGVicmV3ID0gMHhmYjJlOwogIHQuYWxlZnFhbWF0c2hlYnJldyA9IDB4ZmIyZjsKICB0LmFsZXBoID0gMHgyMTM1OwogIHQuYWxsZXF1YWwgPSAweDIyNGM7CiAgdC5hbHBoYSA9IDB4MDNiMTsKICB0LmFscGhhdG9ub3MgPSAweDAzYWM7CiAgdC5hbWFjcm9uID0gMHgwMTAxOwogIHQuYW1vbm9zcGFjZSA9IDB4ZmY0MTsKICB0LmFtcGVyc2FuZCA9IDB4MDAyNjsKICB0LmFtcGVyc2FuZG1vbm9zcGFjZSA9IDB4ZmYwNjsKICB0LmFtcGVyc2FuZHNtYWxsID0gMHhmNzI2OwogIHQuYW1zcXVhcmUgPSAweDMzYzI7CiAgdC5hbmJvcG9tb2ZvID0gMHgzMTIyOwogIHQuYW5nYm9wb21vZm8gPSAweDMxMjQ7CiAgdC5hbmdicmFja2V0bGVmdCA9IDB4MzAwODsKICB0LmFuZ2JyYWNrZXRyaWdodCA9IDB4MzAwOTsKICB0LmFuZ2toYW5raHV0aGFpID0gMHgwZTVhOwogIHQuYW5nbGUgPSAweDIyMjA7CiAgdC5hbmdsZWJyYWNrZXRsZWZ0ID0gMHgzMDA4OwogIHQuYW5nbGVicmFja2V0bGVmdHZlcnRpY2FsID0gMHhmZTNmOwogIHQuYW5nbGVicmFja2V0cmlnaHQgPSAweDMwMDk7CiAgdC5hbmdsZWJyYWNrZXRyaWdodHZlcnRpY2FsID0gMHhmZTQwOwogIHQuYW5nbGVsZWZ0ID0gMHgyMzI5OwogIHQuYW5nbGVyaWdodCA9IDB4MjMyYTsKICB0LmFuZ3N0cm9tID0gMHgyMTJiOwogIHQuYW5vdGVsZWlhID0gMHgwMzg3OwogIHQuYW51ZGF0dGFkZXZhID0gMHgwOTUyOwogIHQuYW51c3ZhcmFiZW5nYWxpID0gMHgwOTgyOwogIHQuYW51c3ZhcmFkZXZhID0gMHgwOTAyOwogIHQuYW51c3ZhcmFndWphcmF0aSA9IDB4MGE4MjsKICB0LmFvZ29uZWsgPSAweDAxMDU7CiAgdC5hcGFhdG9zcXVhcmUgPSAweDMzMDA7CiAgdC5hcGFyZW4gPSAweDI0OWM7CiAgdC5hcG9zdHJvcGhlYXJtZW5pYW4gPSAweDA1NWE7CiAgdC5hcG9zdHJvcGhlbW9kID0gMHgwMmJjOwogIHQuYXBwbGUgPSAweGY4ZmY7CiAgdC5hcHByb2FjaGVzID0gMHgyMjUwOwogIHQuYXBwcm94ZXF1YWwgPSAweDIyNDg7CiAgdC5hcHByb3hlcXVhbG9yaW1hZ2UgPSAweDIyNTI7CiAgdC5hcHByb3hpbWF0ZWx5ZXF1YWwgPSAweDIyNDU7CiAgdC5hcmFlYWVrb3JlYW4gPSAweDMxOGU7CiAgdC5hcmFlYWtvcmVhbiA9IDB4MzE4ZDsKICB0LmFyYyA9IDB4MjMxMjsKICB0LmFyaWdodGhhbGZyaW5nID0gMHgxZTlhOwogIHQuYXJpbmcgPSAweDAwZTU7CiAgdC5hcmluZ2FjdXRlID0gMHgwMWZiOwogIHQuYXJpbmdiZWxvdyA9IDB4MWUwMTsKICB0LmFycm93Ym90aCA9IDB4MjE5NDsKICB0LmFycm93ZGFzaGRvd24gPSAweDIxZTM7CiAgdC5hcnJvd2Rhc2hsZWZ0ID0gMHgyMWUwOwogIHQuYXJyb3dkYXNocmlnaHQgPSAweDIxZTI7CiAgdC5hcnJvd2Rhc2h1cCA9IDB4MjFlMTsKICB0LmFycm93ZGJsYm90aCA9IDB4MjFkNDsKICB0LmFycm93ZGJsZG93biA9IDB4MjFkMzsKICB0LmFycm93ZGJsbGVmdCA9IDB4MjFkMDsKICB0LmFycm93ZGJscmlnaHQgPSAweDIxZDI7CiAgdC5hcnJvd2RibHVwID0gMHgyMWQxOwogIHQuYXJyb3dkb3duID0gMHgyMTkzOwogIHQuYXJyb3dkb3dubGVmdCA9IDB4MjE5OTsKICB0LmFycm93ZG93bnJpZ2h0ID0gMHgyMTk4OwogIHQuYXJyb3dkb3dud2hpdGUgPSAweDIxZTk7CiAgdC5hcnJvd2hlYWRkb3dubW9kID0gMHgwMmM1OwogIHQuYXJyb3doZWFkbGVmdG1vZCA9IDB4MDJjMjsKICB0LmFycm93aGVhZHJpZ2h0bW9kID0gMHgwMmMzOwogIHQuYXJyb3doZWFkdXBtb2QgPSAweDAyYzQ7CiAgdC5hcnJvd2hvcml6ZXggPSAweGY4ZTc7CiAgdC5hcnJvd2xlZnQgPSAweDIxOTA7CiAgdC5hcnJvd2xlZnRkYmwgPSAweDIxZDA7CiAgdC5hcnJvd2xlZnRkYmxzdHJva2UgPSAweDIxY2Q7CiAgdC5hcnJvd2xlZnRvdmVycmlnaHQgPSAweDIxYzY7CiAgdC5hcnJvd2xlZnR3aGl0ZSA9IDB4MjFlNjsKICB0LmFycm93cmlnaHQgPSAweDIxOTI7CiAgdC5hcnJvd3JpZ2h0ZGJsc3Ryb2tlID0gMHgyMWNmOwogIHQuYXJyb3dyaWdodGhlYXZ5ID0gMHgyNzllOwogIHQuYXJyb3dyaWdodG92ZXJsZWZ0ID0gMHgyMWM0OwogIHQuYXJyb3dyaWdodHdoaXRlID0gMHgyMWU4OwogIHQuYXJyb3d0YWJsZWZ0ID0gMHgyMWU0OwogIHQuYXJyb3d0YWJyaWdodCA9IDB4MjFlNTsKICB0LmFycm93dXAgPSAweDIxOTE7CiAgdC5hcnJvd3VwZG4gPSAweDIxOTU7CiAgdC5hcnJvd3VwZG5ic2UgPSAweDIxYTg7CiAgdC5hcnJvd3VwZG93bmJhc2UgPSAweDIxYTg7CiAgdC5hcnJvd3VwbGVmdCA9IDB4MjE5NjsKICB0LmFycm93dXBsZWZ0b2Zkb3duID0gMHgyMWM1OwogIHQuYXJyb3d1cHJpZ2h0ID0gMHgyMTk3OwogIHQuYXJyb3d1cHdoaXRlID0gMHgyMWU3OwogIHQuYXJyb3d2ZXJ0ZXggPSAweGY4ZTY7CiAgdC5hc2NpaWNpcmN1bSA9IDB4MDA1ZTsKICB0LmFzY2lpY2lyY3VtbW9ub3NwYWNlID0gMHhmZjNlOwogIHQuYXNjaWl0aWxkZSA9IDB4MDA3ZTsKICB0LmFzY2lpdGlsZGVtb25vc3BhY2UgPSAweGZmNWU7CiAgdC5hc2NyaXB0ID0gMHgwMjUxOwogIHQuYXNjcmlwdHR1cm5lZCA9IDB4MDI1MjsKICB0LmFzbWFsbGhpcmFnYW5hID0gMHgzMDQxOwogIHQuYXNtYWxsa2F0YWthbmEgPSAweDMwYTE7CiAgdC5hc21hbGxrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY2NzsKICB0LmFzdGVyaXNrID0gMHgwMDJhOwogIHQuYXN0ZXJpc2thbHRvbmVhcmFiaWMgPSAweDA2NmQ7CiAgdC5hc3Rlcmlza2FyYWJpYyA9IDB4MDY2ZDsKICB0LmFzdGVyaXNrbWF0aCA9IDB4MjIxNzsKICB0LmFzdGVyaXNrbW9ub3NwYWNlID0gMHhmZjBhOwogIHQuYXN0ZXJpc2tzbWFsbCA9IDB4ZmU2MTsKICB0LmFzdGVyaXNtID0gMHgyMDQyOwogIHQuYXN1cGVyaW9yID0gMHhmNmU5OwogIHQuYXN5bXB0b3RpY2FsbHllcXVhbCA9IDB4MjI0MzsKICB0LmF0ID0gMHgwMDQwOwogIHQuYXRpbGRlID0gMHgwMGUzOwogIHQuYXRtb25vc3BhY2UgPSAweGZmMjA7CiAgdC5hdHNtYWxsID0gMHhmZTZiOwogIHQuYXR1cm5lZCA9IDB4MDI1MDsKICB0LmF1YmVuZ2FsaSA9IDB4MDk5NDsKICB0LmF1Ym9wb21vZm8gPSAweDMxMjA7CiAgdC5hdWRldmEgPSAweDA5MTQ7CiAgdC5hdWd1amFyYXRpID0gMHgwYTk0OwogIHQuYXVndXJtdWtoaSA9IDB4MGExNDsKICB0LmF1bGVuZ3RobWFya2JlbmdhbGkgPSAweDA5ZDc7CiAgdC5hdW1hdHJhZ3VybXVraGkgPSAweDBhNGM7CiAgdC5hdXZvd2Vsc2lnbmJlbmdhbGkgPSAweDA5Y2M7CiAgdC5hdXZvd2Vsc2lnbmRldmEgPSAweDA5NGM7CiAgdC5hdXZvd2Vsc2lnbmd1amFyYXRpID0gMHgwYWNjOwogIHQuYXZhZ3JhaGFkZXZhID0gMHgwOTNkOwogIHQuYXliYXJtZW5pYW4gPSAweDA1NjE7CiAgdC5heWluID0gMHgwNWUyOwogIHQuYXlpbmFsdG9uZWhlYnJldyA9IDB4ZmIyMDsKICB0LmF5aW5oZWJyZXcgPSAweDA1ZTI7CiAgdC5iID0gMHgwMDYyOwogIHQuYmFiZW5nYWxpID0gMHgwOWFjOwogIHQuYmFja3NsYXNoID0gMHgwMDVjOwogIHQuYmFja3NsYXNobW9ub3NwYWNlID0gMHhmZjNjOwogIHQuYmFkZXZhID0gMHgwOTJjOwogIHQuYmFndWphcmF0aSA9IDB4MGFhYzsKICB0LmJhZ3VybXVraGkgPSAweDBhMmM7CiAgdC5iYWhpcmFnYW5hID0gMHgzMDcwOwogIHQuYmFodHRoYWkgPSAweDBlM2Y7CiAgdC5iYWthdGFrYW5hID0gMHgzMGQwOwogIHQuYmFyID0gMHgwMDdjOwogIHQuYmFybW9ub3NwYWNlID0gMHhmZjVjOwogIHQuYmJvcG9tb2ZvID0gMHgzMTA1OwogIHQuYmNpcmNsZSA9IDB4MjRkMTsKICB0LmJkb3RhY2NlbnQgPSAweDFlMDM7CiAgdC5iZG90YmVsb3cgPSAweDFlMDU7CiAgdC5iZWFtZWRzaXh0ZWVudGhub3RlcyA9IDB4MjY2YzsKICB0LmJlY2F1c2UgPSAweDIyMzU7CiAgdC5iZWN5cmlsbGljID0gMHgwNDMxOwogIHQuYmVoYXJhYmljID0gMHgwNjI4OwogIHQuYmVoZmluYWxhcmFiaWMgPSAweGZlOTA7CiAgdC5iZWhpbml0aWFsYXJhYmljID0gMHhmZTkxOwogIHQuYmVoaXJhZ2FuYSA9IDB4MzA3OTsKICB0LmJlaG1lZGlhbGFyYWJpYyA9IDB4ZmU5MjsKICB0LmJlaG1lZW1pbml0aWFsYXJhYmljID0gMHhmYzlmOwogIHQuYmVobWVlbWlzb2xhdGVkYXJhYmljID0gMHhmYzA4OwogIHQuYmVobm9vbmZpbmFsYXJhYmljID0gMHhmYzZkOwogIHQuYmVrYXRha2FuYSA9IDB4MzBkOTsKICB0LmJlbmFybWVuaWFuID0gMHgwNTYyOwogIHQuYmV0ID0gMHgwNWQxOwogIHQuYmV0YSA9IDB4MDNiMjsKICB0LmJldGFzeW1ib2xncmVlayA9IDB4MDNkMDsKICB0LmJldGRhZ2VzaCA9IDB4ZmIzMTsKICB0LmJldGRhZ2VzaGhlYnJldyA9IDB4ZmIzMTsKICB0LmJldGhlYnJldyA9IDB4MDVkMTsKICB0LmJldHJhZmVoZWJyZXcgPSAweGZiNGM7CiAgdC5iaGFiZW5nYWxpID0gMHgwOWFkOwogIHQuYmhhZGV2YSA9IDB4MDkyZDsKICB0LmJoYWd1amFyYXRpID0gMHgwYWFkOwogIHQuYmhhZ3VybXVraGkgPSAweDBhMmQ7CiAgdC5iaG9vayA9IDB4MDI1MzsKICB0LmJpaGlyYWdhbmEgPSAweDMwNzM7CiAgdC5iaWthdGFrYW5hID0gMHgzMGQzOwogIHQuYmlsYWJpYWxjbGljayA9IDB4MDI5ODsKICB0LmJpbmRpZ3VybXVraGkgPSAweDBhMDI7CiAgdC5iaXJ1c3F1YXJlID0gMHgzMzMxOwogIHQuYmxhY2tjaXJjbGUgPSAweDI1Y2Y7CiAgdC5ibGFja2RpYW1vbmQgPSAweDI1YzY7CiAgdC5ibGFja2Rvd25wb2ludGluZ3RyaWFuZ2xlID0gMHgyNWJjOwogIHQuYmxhY2tsZWZ0cG9pbnRpbmdwb2ludGVyID0gMHgyNWM0OwogIHQuYmxhY2tsZWZ0cG9pbnRpbmd0cmlhbmdsZSA9IDB4MjVjMDsKICB0LmJsYWNrbGVudGljdWxhcmJyYWNrZXRsZWZ0ID0gMHgzMDEwOwogIHQuYmxhY2tsZW50aWN1bGFyYnJhY2tldGxlZnR2ZXJ0aWNhbCA9IDB4ZmUzYjsKICB0LmJsYWNrbGVudGljdWxhcmJyYWNrZXRyaWdodCA9IDB4MzAxMTsKICB0LmJsYWNrbGVudGljdWxhcmJyYWNrZXRyaWdodHZlcnRpY2FsID0gMHhmZTNjOwogIHQuYmxhY2tsb3dlcmxlZnR0cmlhbmdsZSA9IDB4MjVlMzsKICB0LmJsYWNrbG93ZXJyaWdodHRyaWFuZ2xlID0gMHgyNWUyOwogIHQuYmxhY2tyZWN0YW5nbGUgPSAweDI1YWM7CiAgdC5ibGFja3JpZ2h0cG9pbnRpbmdwb2ludGVyID0gMHgyNWJhOwogIHQuYmxhY2tyaWdodHBvaW50aW5ndHJpYW5nbGUgPSAweDI1YjY7CiAgdC5ibGFja3NtYWxsc3F1YXJlID0gMHgyNWFhOwogIHQuYmxhY2tzbWlsaW5nZmFjZSA9IDB4MjYzYjsKICB0LmJsYWNrc3F1YXJlID0gMHgyNWEwOwogIHQuYmxhY2tzdGFyID0gMHgyNjA1OwogIHQuYmxhY2t1cHBlcmxlZnR0cmlhbmdsZSA9IDB4MjVlNDsKICB0LmJsYWNrdXBwZXJyaWdodHRyaWFuZ2xlID0gMHgyNWU1OwogIHQuYmxhY2t1cHBvaW50aW5nc21hbGx0cmlhbmdsZSA9IDB4MjViNDsKICB0LmJsYWNrdXBwb2ludGluZ3RyaWFuZ2xlID0gMHgyNWIyOwogIHQuYmxhbmsgPSAweDI0MjM7CiAgdC5ibGluZWJlbG93ID0gMHgxZTA3OwogIHQuYmxvY2sgPSAweDI1ODg7CiAgdC5ibW9ub3NwYWNlID0gMHhmZjQyOwogIHQuYm9iYWltYWl0aGFpID0gMHgwZTFhOwogIHQuYm9oaXJhZ2FuYSA9IDB4MzA3YzsKICB0LmJva2F0YWthbmEgPSAweDMwZGM7CiAgdC5icGFyZW4gPSAweDI0OWQ7CiAgdC5icXNxdWFyZSA9IDB4MzNjMzsKICB0LmJyYWNlZXggPSAweGY4ZjQ7CiAgdC5icmFjZWxlZnQgPSAweDAwN2I7CiAgdC5icmFjZWxlZnRidCA9IDB4ZjhmMzsKICB0LmJyYWNlbGVmdG1pZCA9IDB4ZjhmMjsKICB0LmJyYWNlbGVmdG1vbm9zcGFjZSA9IDB4ZmY1YjsKICB0LmJyYWNlbGVmdHNtYWxsID0gMHhmZTViOwogIHQuYnJhY2VsZWZ0dHAgPSAweGY4ZjE7CiAgdC5icmFjZWxlZnR2ZXJ0aWNhbCA9IDB4ZmUzNzsKICB0LmJyYWNlcmlnaHQgPSAweDAwN2Q7CiAgdC5icmFjZXJpZ2h0YnQgPSAweGY4ZmU7CiAgdC5icmFjZXJpZ2h0bWlkID0gMHhmOGZkOwogIHQuYnJhY2VyaWdodG1vbm9zcGFjZSA9IDB4ZmY1ZDsKICB0LmJyYWNlcmlnaHRzbWFsbCA9IDB4ZmU1YzsKICB0LmJyYWNlcmlnaHR0cCA9IDB4ZjhmYzsKICB0LmJyYWNlcmlnaHR2ZXJ0aWNhbCA9IDB4ZmUzODsKICB0LmJyYWNrZXRsZWZ0ID0gMHgwMDViOwogIHQuYnJhY2tldGxlZnRidCA9IDB4ZjhmMDsKICB0LmJyYWNrZXRsZWZ0ZXggPSAweGY4ZWY7CiAgdC5icmFja2V0bGVmdG1vbm9zcGFjZSA9IDB4ZmYzYjsKICB0LmJyYWNrZXRsZWZ0dHAgPSAweGY4ZWU7CiAgdC5icmFja2V0cmlnaHQgPSAweDAwNWQ7CiAgdC5icmFja2V0cmlnaHRidCA9IDB4ZjhmYjsKICB0LmJyYWNrZXRyaWdodGV4ID0gMHhmOGZhOwogIHQuYnJhY2tldHJpZ2h0bW9ub3NwYWNlID0gMHhmZjNkOwogIHQuYnJhY2tldHJpZ2h0dHAgPSAweGY4Zjk7CiAgdC5icmV2ZSA9IDB4MDJkODsKICB0LmJyZXZlYmVsb3djbWIgPSAweDAzMmU7CiAgdC5icmV2ZWNtYiA9IDB4MDMwNjsKICB0LmJyZXZlaW52ZXJ0ZWRiZWxvd2NtYiA9IDB4MDMyZjsKICB0LmJyZXZlaW52ZXJ0ZWRjbWIgPSAweDAzMTE7CiAgdC5icmV2ZWludmVydGVkZG91YmxlY21iID0gMHgwMzYxOwogIHQuYnJpZGdlYmVsb3djbWIgPSAweDAzMmE7CiAgdC5icmlkZ2VpbnZlcnRlZGJlbG93Y21iID0gMHgwMzNhOwogIHQuYnJva2VuYmFyID0gMHgwMGE2OwogIHQuYnN0cm9rZSA9IDB4MDE4MDsKICB0LmJzdXBlcmlvciA9IDB4ZjZlYTsKICB0LmJ0b3BiYXIgPSAweDAxODM7CiAgdC5idWhpcmFnYW5hID0gMHgzMDc2OwogIHQuYnVrYXRha2FuYSA9IDB4MzBkNjsKICB0LmJ1bGxldCA9IDB4MjAyMjsKICB0LmJ1bGxldGludmVyc2UgPSAweDI1ZDg7CiAgdC5idWxsZXRvcGVyYXRvciA9IDB4MjIxOTsKICB0LmJ1bGxzZXllID0gMHgyNWNlOwogIHQuYyA9IDB4MDA2MzsKICB0LmNhYXJtZW5pYW4gPSAweDA1NmU7CiAgdC5jYWJlbmdhbGkgPSAweDA5OWE7CiAgdC5jYWN1dGUgPSAweDAxMDc7CiAgdC5jYWRldmEgPSAweDA5MWE7CiAgdC5jYWd1amFyYXRpID0gMHgwYTlhOwogIHQuY2FndXJtdWtoaSA9IDB4MGExYTsKICB0LmNhbHNxdWFyZSA9IDB4MzM4ODsKICB0LmNhbmRyYWJpbmR1YmVuZ2FsaSA9IDB4MDk4MTsKICB0LmNhbmRyYWJpbmR1Y21iID0gMHgwMzEwOwogIHQuY2FuZHJhYmluZHVkZXZhID0gMHgwOTAxOwogIHQuY2FuZHJhYmluZHVndWphcmF0aSA9IDB4MGE4MTsKICB0LmNhcHNsb2NrID0gMHgyMWVhOwogIHQuY2FyZW9mID0gMHgyMTA1OwogIHQuY2Fyb24gPSAweDAyYzc7CiAgdC5jYXJvbmJlbG93Y21iID0gMHgwMzJjOwogIHQuY2Fyb25jbWIgPSAweDAzMGM7CiAgdC5jYXJyaWFnZXJldHVybiA9IDB4MjFiNTsKICB0LmNib3BvbW9mbyA9IDB4MzExODsKICB0LmNjYXJvbiA9IDB4MDEwZDsKICB0LmNjZWRpbGxhID0gMHgwMGU3OwogIHQuY2NlZGlsbGFhY3V0ZSA9IDB4MWUwOTsKICB0LmNjaXJjbGUgPSAweDI0ZDI7CiAgdC5jY2lyY3VtZmxleCA9IDB4MDEwOTsKICB0LmNjdXJsID0gMHgwMjU1OwogIHQuY2RvdCA9IDB4MDEwYjsKICB0LmNkb3RhY2NlbnQgPSAweDAxMGI7CiAgdC5jZHNxdWFyZSA9IDB4MzNjNTsKICB0LmNlZGlsbGEgPSAweDAwYjg7CiAgdC5jZWRpbGxhY21iID0gMHgwMzI3OwogIHQuY2VudCA9IDB4MDBhMjsKICB0LmNlbnRpZ3JhZGUgPSAweDIxMDM7CiAgdC5jZW50aW5mZXJpb3IgPSAweGY2ZGY7CiAgdC5jZW50bW9ub3NwYWNlID0gMHhmZmUwOwogIHQuY2VudG9sZHN0eWxlID0gMHhmN2EyOwogIHQuY2VudHN1cGVyaW9yID0gMHhmNmUwOwogIHQuY2hhYXJtZW5pYW4gPSAweDA1Nzk7CiAgdC5jaGFiZW5nYWxpID0gMHgwOTliOwogIHQuY2hhZGV2YSA9IDB4MDkxYjsKICB0LmNoYWd1amFyYXRpID0gMHgwYTliOwogIHQuY2hhZ3VybXVraGkgPSAweDBhMWI7CiAgdC5jaGJvcG9tb2ZvID0gMHgzMTE0OwogIHQuY2hlYWJraGFzaWFuY3lyaWxsaWMgPSAweDA0YmQ7CiAgdC5jaGVja21hcmsgPSAweDI3MTM7CiAgdC5jaGVjeXJpbGxpYyA9IDB4MDQ0NzsKICB0LmNoZWRlc2NlbmRlcmFia2hhc2lhbmN5cmlsbGljID0gMHgwNGJmOwogIHQuY2hlZGVzY2VuZGVyY3lyaWxsaWMgPSAweDA0Yjc7CiAgdC5jaGVkaWVyZXNpc2N5cmlsbGljID0gMHgwNGY1OwogIHQuY2hlaGFybWVuaWFuID0gMHgwNTczOwogIHQuY2hla2hha2Fzc2lhbmN5cmlsbGljID0gMHgwNGNjOwogIHQuY2hldmVydGljYWxzdHJva2VjeXJpbGxpYyA9IDB4MDRiOTsKICB0LmNoaSA9IDB4MDNjNzsKICB0LmNoaWV1Y2hhY2lyY2xla29yZWFuID0gMHgzMjc3OwogIHQuY2hpZXVjaGFwYXJlbmtvcmVhbiA9IDB4MzIxNzsKICB0LmNoaWV1Y2hjaXJjbGVrb3JlYW4gPSAweDMyNjk7CiAgdC5jaGlldWNoa29yZWFuID0gMHgzMTRhOwogIHQuY2hpZXVjaHBhcmVua29yZWFuID0gMHgzMjA5OwogIHQuY2hvY2hhbmd0aGFpID0gMHgwZTBhOwogIHQuY2hvY2hhbnRoYWkgPSAweDBlMDg7CiAgdC5jaG9jaGluZ3RoYWkgPSAweDBlMDk7CiAgdC5jaG9jaG9ldGhhaSA9IDB4MGUwYzsKICB0LmNob29rID0gMHgwMTg4OwogIHQuY2lldWNhY2lyY2xla29yZWFuID0gMHgzMjc2OwogIHQuY2lldWNhcGFyZW5rb3JlYW4gPSAweDMyMTY7CiAgdC5jaWV1Y2NpcmNsZWtvcmVhbiA9IDB4MzI2ODsKICB0LmNpZXVja29yZWFuID0gMHgzMTQ4OwogIHQuY2lldWNwYXJlbmtvcmVhbiA9IDB4MzIwODsKICB0LmNpZXVjdXBhcmVua29yZWFuID0gMHgzMjFjOwogIHQuY2lyY2xlID0gMHgyNWNiOwogIHQuY2lyY2xlY29weXJ0ID0gMHgwMGE5OwogIHQuY2lyY2xlbXVsdGlwbHkgPSAweDIyOTc7CiAgdC5jaXJjbGVvdCA9IDB4MjI5OTsKICB0LmNpcmNsZXBsdXMgPSAweDIyOTU7CiAgdC5jaXJjbGVwb3N0YWxtYXJrID0gMHgzMDM2OwogIHQuY2lyY2xld2l0aGxlZnRoYWxmYmxhY2sgPSAweDI1ZDA7CiAgdC5jaXJjbGV3aXRocmlnaHRoYWxmYmxhY2sgPSAweDI1ZDE7CiAgdC5jaXJjdW1mbGV4ID0gMHgwMmM2OwogIHQuY2lyY3VtZmxleGJlbG93Y21iID0gMHgwMzJkOwogIHQuY2lyY3VtZmxleGNtYiA9IDB4MDMwMjsKICB0LmNsZWFyID0gMHgyMzI3OwogIHQuY2xpY2thbHZlb2xhciA9IDB4MDFjMjsKICB0LmNsaWNrZGVudGFsID0gMHgwMWMwOwogIHQuY2xpY2tsYXRlcmFsID0gMHgwMWMxOwogIHQuY2xpY2tyZXRyb2ZsZXggPSAweDAxYzM7CiAgdC5jbHViID0gMHgyNjYzOwogIHQuY2x1YnN1aXRibGFjayA9IDB4MjY2MzsKICB0LmNsdWJzdWl0d2hpdGUgPSAweDI2Njc7CiAgdC5jbWN1YmVkc3F1YXJlID0gMHgzM2E0OwogIHQuY21vbm9zcGFjZSA9IDB4ZmY0MzsKICB0LmNtc3F1YXJlZHNxdWFyZSA9IDB4MzNhMDsKICB0LmNvYXJtZW5pYW4gPSAweDA1ODE7CiAgdC5jb2xvbiA9IDB4MDAzYTsKICB0LmNvbG9ubW9uZXRhcnkgPSAweDIwYTE7CiAgdC5jb2xvbm1vbm9zcGFjZSA9IDB4ZmYxYTsKICB0LmNvbG9uc2lnbiA9IDB4MjBhMTsKICB0LmNvbG9uc21hbGwgPSAweGZlNTU7CiAgdC5jb2xvbnRyaWFuZ3VsYXJoYWxmbW9kID0gMHgwMmQxOwogIHQuY29sb250cmlhbmd1bGFybW9kID0gMHgwMmQwOwogIHQuY29tbWEgPSAweDAwMmM7CiAgdC5jb21tYWFib3ZlY21iID0gMHgwMzEzOwogIHQuY29tbWFhYm92ZXJpZ2h0Y21iID0gMHgwMzE1OwogIHQuY29tbWFhY2NlbnQgPSAweGY2YzM7CiAgdC5jb21tYWFyYWJpYyA9IDB4MDYwYzsKICB0LmNvbW1hYXJtZW5pYW4gPSAweDA1NWQ7CiAgdC5jb21tYWluZmVyaW9yID0gMHhmNmUxOwogIHQuY29tbWFtb25vc3BhY2UgPSAweGZmMGM7CiAgdC5jb21tYXJldmVyc2VkYWJvdmVjbWIgPSAweDAzMTQ7CiAgdC5jb21tYXJldmVyc2VkbW9kID0gMHgwMmJkOwogIHQuY29tbWFzbWFsbCA9IDB4ZmU1MDsKICB0LmNvbW1hc3VwZXJpb3IgPSAweGY2ZTI7CiAgdC5jb21tYXR1cm5lZGFib3ZlY21iID0gMHgwMzEyOwogIHQuY29tbWF0dXJuZWRtb2QgPSAweDAyYmI7CiAgdC5jb21wYXNzID0gMHgyNjNjOwogIHQuY29uZ3J1ZW50ID0gMHgyMjQ1OwogIHQuY29udG91cmludGVncmFsID0gMHgyMjJlOwogIHQuY29udHJvbCA9IDB4MjMwMzsKICB0LmNvbnRyb2xBQ0sgPSAweDAwMDY7CiAgdC5jb250cm9sQkVMID0gMHgwMDA3OwogIHQuY29udHJvbEJTID0gMHgwMDA4OwogIHQuY29udHJvbENBTiA9IDB4MDAxODsKICB0LmNvbnRyb2xDUiA9IDB4MDAwZDsKICB0LmNvbnRyb2xEQzEgPSAweDAwMTE7CiAgdC5jb250cm9sREMyID0gMHgwMDEyOwogIHQuY29udHJvbERDMyA9IDB4MDAxMzsKICB0LmNvbnRyb2xEQzQgPSAweDAwMTQ7CiAgdC5jb250cm9sREVMID0gMHgwMDdmOwogIHQuY29udHJvbERMRSA9IDB4MDAxMDsKICB0LmNvbnRyb2xFTSA9IDB4MDAxOTsKICB0LmNvbnRyb2xFTlEgPSAweDAwMDU7CiAgdC5jb250cm9sRU9UID0gMHgwMDA0OwogIHQuY29udHJvbEVTQyA9IDB4MDAxYjsKICB0LmNvbnRyb2xFVEIgPSAweDAwMTc7CiAgdC5jb250cm9sRVRYID0gMHgwMDAzOwogIHQuY29udHJvbEZGID0gMHgwMDBjOwogIHQuY29udHJvbEZTID0gMHgwMDFjOwogIHQuY29udHJvbEdTID0gMHgwMDFkOwogIHQuY29udHJvbEhUID0gMHgwMDA5OwogIHQuY29udHJvbExGID0gMHgwMDBhOwogIHQuY29udHJvbE5BSyA9IDB4MDAxNTsKICB0LmNvbnRyb2xOVUxMID0gMHgwMDAwOwogIHQuY29udHJvbFJTID0gMHgwMDFlOwogIHQuY29udHJvbFNJID0gMHgwMDBmOwogIHQuY29udHJvbFNPID0gMHgwMDBlOwogIHQuY29udHJvbFNPVCA9IDB4MDAwMjsKICB0LmNvbnRyb2xTVFggPSAweDAwMDE7CiAgdC5jb250cm9sU1VCID0gMHgwMDFhOwogIHQuY29udHJvbFNZTiA9IDB4MDAxNjsKICB0LmNvbnRyb2xVUyA9IDB4MDAxZjsKICB0LmNvbnRyb2xWVCA9IDB4MDAwYjsKICB0LmNvcHlyaWdodCA9IDB4MDBhOTsKICB0LmNvcHlyaWdodHNhbnMgPSAweGY4ZTk7CiAgdC5jb3B5cmlnaHRzZXJpZiA9IDB4ZjZkOTsKICB0LmNvcm5lcmJyYWNrZXRsZWZ0ID0gMHgzMDBjOwogIHQuY29ybmVyYnJhY2tldGxlZnRoYWxmd2lkdGggPSAweGZmNjI7CiAgdC5jb3JuZXJicmFja2V0bGVmdHZlcnRpY2FsID0gMHhmZTQxOwogIHQuY29ybmVyYnJhY2tldHJpZ2h0ID0gMHgzMDBkOwogIHQuY29ybmVyYnJhY2tldHJpZ2h0aGFsZndpZHRoID0gMHhmZjYzOwogIHQuY29ybmVyYnJhY2tldHJpZ2h0dmVydGljYWwgPSAweGZlNDI7CiAgdC5jb3Jwb3JhdGlvbnNxdWFyZSA9IDB4MzM3ZjsKICB0LmNvc3F1YXJlID0gMHgzM2M3OwogIHQuY292ZXJrZ3NxdWFyZSA9IDB4MzNjNjsKICB0LmNwYXJlbiA9IDB4MjQ5ZTsKICB0LmNydXplaXJvID0gMHgyMGEyOwogIHQuY3N0cmV0Y2hlZCA9IDB4MDI5NzsKICB0LmN1cmx5YW5kID0gMHgyMmNmOwogIHQuY3VybHlvciA9IDB4MjJjZTsKICB0LmN1cnJlbmN5ID0gMHgwMGE0OwogIHQuY3lyQnJldmUgPSAweGY2ZDE7CiAgdC5jeXJGbGV4ID0gMHhmNmQyOwogIHQuY3lyYnJldmUgPSAweGY2ZDQ7CiAgdC5jeXJmbGV4ID0gMHhmNmQ1OwogIHQuZCA9IDB4MDA2NDsKICB0LmRhYXJtZW5pYW4gPSAweDA1NjQ7CiAgdC5kYWJlbmdhbGkgPSAweDA5YTY7CiAgdC5kYWRhcmFiaWMgPSAweDA2MzY7CiAgdC5kYWRldmEgPSAweDA5MjY7CiAgdC5kYWRmaW5hbGFyYWJpYyA9IDB4ZmViZTsKICB0LmRhZGluaXRpYWxhcmFiaWMgPSAweGZlYmY7CiAgdC5kYWRtZWRpYWxhcmFiaWMgPSAweGZlYzA7CiAgdC5kYWdlc2ggPSAweDA1YmM7CiAgdC5kYWdlc2hoZWJyZXcgPSAweDA1YmM7CiAgdC5kYWdnZXIgPSAweDIwMjA7CiAgdC5kYWdnZXJkYmwgPSAweDIwMjE7CiAgdC5kYWd1amFyYXRpID0gMHgwYWE2OwogIHQuZGFndXJtdWtoaSA9IDB4MGEyNjsKICB0LmRhaGlyYWdhbmEgPSAweDMwNjA7CiAgdC5kYWthdGFrYW5hID0gMHgzMGMwOwogIHQuZGFsYXJhYmljID0gMHgwNjJmOwogIHQuZGFsZXQgPSAweDA1ZDM7CiAgdC5kYWxldGRhZ2VzaCA9IDB4ZmIzMzsKICB0LmRhbGV0ZGFnZXNoaGVicmV3ID0gMHhmYjMzOwogIHQuZGFsZXRoZWJyZXcgPSAweDA1ZDM7CiAgdC5kYWxmaW5hbGFyYWJpYyA9IDB4ZmVhYTsKICB0LmRhbW1hYXJhYmljID0gMHgwNjRmOwogIHQuZGFtbWFsb3dhcmFiaWMgPSAweDA2NGY7CiAgdC5kYW1tYXRhbmFsdG9uZWFyYWJpYyA9IDB4MDY0YzsKICB0LmRhbW1hdGFuYXJhYmljID0gMHgwNjRjOwogIHQuZGFuZGEgPSAweDA5NjQ7CiAgdC5kYXJnYWhlYnJldyA9IDB4MDVhNzsKICB0LmRhcmdhbGVmdGhlYnJldyA9IDB4MDVhNzsKICB0LmRhc2lhcG5ldW1hdGFjeXJpbGxpY2NtYiA9IDB4MDQ4NTsKICB0LmRibEdyYXZlID0gMHhmNmQzOwogIHQuZGJsYW5nbGVicmFja2V0bGVmdCA9IDB4MzAwYTsKICB0LmRibGFuZ2xlYnJhY2tldGxlZnR2ZXJ0aWNhbCA9IDB4ZmUzZDsKICB0LmRibGFuZ2xlYnJhY2tldHJpZ2h0ID0gMHgzMDBiOwogIHQuZGJsYW5nbGVicmFja2V0cmlnaHR2ZXJ0aWNhbCA9IDB4ZmUzZTsKICB0LmRibGFyY2hpbnZlcnRlZGJlbG93Y21iID0gMHgwMzJiOwogIHQuZGJsYXJyb3dsZWZ0ID0gMHgyMWQ0OwogIHQuZGJsYXJyb3dyaWdodCA9IDB4MjFkMjsKICB0LmRibGRhbmRhID0gMHgwOTY1OwogIHQuZGJsZ3JhdmUgPSAweGY2ZDY7CiAgdC5kYmxncmF2ZWNtYiA9IDB4MDMwZjsKICB0LmRibGludGVncmFsID0gMHgyMjJjOwogIHQuZGJsbG93bGluZSA9IDB4MjAxNzsKICB0LmRibGxvd2xpbmVjbWIgPSAweDAzMzM7CiAgdC5kYmxvdmVybGluZWNtYiA9IDB4MDMzZjsKICB0LmRibHByaW1lbW9kID0gMHgwMmJhOwogIHQuZGJsdmVydGljYWxiYXIgPSAweDIwMTY7CiAgdC5kYmx2ZXJ0aWNhbGxpbmVhYm92ZWNtYiA9IDB4MDMwZTsKICB0LmRib3BvbW9mbyA9IDB4MzEwOTsKICB0LmRic3F1YXJlID0gMHgzM2M4OwogIHQuZGNhcm9uID0gMHgwMTBmOwogIHQuZGNlZGlsbGEgPSAweDFlMTE7CiAgdC5kY2lyY2xlID0gMHgyNGQzOwogIHQuZGNpcmN1bWZsZXhiZWxvdyA9IDB4MWUxMzsKICB0LmRjcm9hdCA9IDB4MDExMTsKICB0LmRkYWJlbmdhbGkgPSAweDA5YTE7CiAgdC5kZGFkZXZhID0gMHgwOTIxOwogIHQuZGRhZ3VqYXJhdGkgPSAweDBhYTE7CiAgdC5kZGFndXJtdWtoaSA9IDB4MGEyMTsKICB0LmRkYWxhcmFiaWMgPSAweDA2ODg7CiAgdC5kZGFsZmluYWxhcmFiaWMgPSAweGZiODk7CiAgdC5kZGRoYWRldmEgPSAweDA5NWM7CiAgdC5kZGhhYmVuZ2FsaSA9IDB4MDlhMjsKICB0LmRkaGFkZXZhID0gMHgwOTIyOwogIHQuZGRoYWd1amFyYXRpID0gMHgwYWEyOwogIHQuZGRoYWd1cm11a2hpID0gMHgwYTIyOwogIHQuZGRvdGFjY2VudCA9IDB4MWUwYjsKICB0LmRkb3RiZWxvdyA9IDB4MWUwZDsKICB0LmRlY2ltYWxzZXBhcmF0b3JhcmFiaWMgPSAweDA2NmI7CiAgdC5kZWNpbWFsc2VwYXJhdG9ycGVyc2lhbiA9IDB4MDY2YjsKICB0LmRlY3lyaWxsaWMgPSAweDA0MzQ7CiAgdC5kZWdyZWUgPSAweDAwYjA7CiAgdC5kZWhpaGVicmV3ID0gMHgwNWFkOwogIHQuZGVoaXJhZ2FuYSA9IDB4MzA2NzsKICB0LmRlaWNvcHRpYyA9IDB4MDNlZjsKICB0LmRla2F0YWthbmEgPSAweDMwYzc7CiAgdC5kZWxldGVsZWZ0ID0gMHgyMzJiOwogIHQuZGVsZXRlcmlnaHQgPSAweDIzMjY7CiAgdC5kZWx0YSA9IDB4MDNiNDsKICB0LmRlbHRhdHVybmVkID0gMHgwMThkOwogIHQuZGVub21pbmF0b3JtaW51c29uZW51bWVyYXRvcmJlbmdhbGkgPSAweDA5Zjg7CiAgdC5kZXpoID0gMHgwMmE0OwogIHQuZGhhYmVuZ2FsaSA9IDB4MDlhNzsKICB0LmRoYWRldmEgPSAweDA5Mjc7CiAgdC5kaGFndWphcmF0aSA9IDB4MGFhNzsKICB0LmRoYWd1cm11a2hpID0gMHgwYTI3OwogIHQuZGhvb2sgPSAweDAyNTc7CiAgdC5kaWFseXRpa2F0b25vcyA9IDB4MDM4NTsKICB0LmRpYWx5dGlrYXRvbm9zY21iID0gMHgwMzQ0OwogIHQuZGlhbW9uZCA9IDB4MjY2NjsKICB0LmRpYW1vbmRzdWl0d2hpdGUgPSAweDI2NjI7CiAgdC5kaWVyZXNpcyA9IDB4MDBhODsKICB0LmRpZXJlc2lzYWN1dGUgPSAweGY2ZDc7CiAgdC5kaWVyZXNpc2JlbG93Y21iID0gMHgwMzI0OwogIHQuZGllcmVzaXNjbWIgPSAweDAzMDg7CiAgdC5kaWVyZXNpc2dyYXZlID0gMHhmNmQ4OwogIHQuZGllcmVzaXN0b25vcyA9IDB4MDM4NTsKICB0LmRpaGlyYWdhbmEgPSAweDMwNjI7CiAgdC5kaWthdGFrYW5hID0gMHgzMGMyOwogIHQuZGl0dG9tYXJrID0gMHgzMDAzOwogIHQuZGl2aWRlID0gMHgwMGY3OwogIHQuZGl2aWRlcyA9IDB4MjIyMzsKICB0LmRpdmlzaW9uc2xhc2ggPSAweDIyMTU7CiAgdC5kamVjeXJpbGxpYyA9IDB4MDQ1MjsKICB0LmRrc2hhZGUgPSAweDI1OTM7CiAgdC5kbGluZWJlbG93ID0gMHgxZTBmOwogIHQuZGxzcXVhcmUgPSAweDMzOTc7CiAgdC5kbWFjcm9uID0gMHgwMTExOwogIHQuZG1vbm9zcGFjZSA9IDB4ZmY0NDsKICB0LmRuYmxvY2sgPSAweDI1ODQ7CiAgdC5kb2NoYWRhdGhhaSA9IDB4MGUwZTsKICB0LmRvZGVrdGhhaSA9IDB4MGUxNDsKICB0LmRvaGlyYWdhbmEgPSAweDMwNjk7CiAgdC5kb2thdGFrYW5hID0gMHgzMGM5OwogIHQuZG9sbGFyID0gMHgwMDI0OwogIHQuZG9sbGFyaW5mZXJpb3IgPSAweGY2ZTM7CiAgdC5kb2xsYXJtb25vc3BhY2UgPSAweGZmMDQ7CiAgdC5kb2xsYXJvbGRzdHlsZSA9IDB4ZjcyNDsKICB0LmRvbGxhcnNtYWxsID0gMHhmZTY5OwogIHQuZG9sbGFyc3VwZXJpb3IgPSAweGY2ZTQ7CiAgdC5kb25nID0gMHgyMGFiOwogIHQuZG9ydXNxdWFyZSA9IDB4MzMyNjsKICB0LmRvdGFjY2VudCA9IDB4MDJkOTsKICB0LmRvdGFjY2VudGNtYiA9IDB4MDMwNzsKICB0LmRvdGJlbG93Y21iID0gMHgwMzIzOwogIHQuZG90YmVsb3djb21iID0gMHgwMzIzOwogIHQuZG90a2F0YWthbmEgPSAweDMwZmI7CiAgdC5kb3RsZXNzaSA9IDB4MDEzMTsKICB0LmRvdGxlc3NqID0gMHhmNmJlOwogIHQuZG90bGVzc2pzdHJva2Vob29rID0gMHgwMjg0OwogIHQuZG90bWF0aCA9IDB4MjJjNTsKICB0LmRvdHRlZGNpcmNsZSA9IDB4MjVjYzsKICB0LmRvdWJsZXlvZHBhdGFoID0gMHhmYjFmOwogIHQuZG91YmxleW9kcGF0YWhoZWJyZXcgPSAweGZiMWY7CiAgdC5kb3dudGFja2JlbG93Y21iID0gMHgwMzFlOwogIHQuZG93bnRhY2ttb2QgPSAweDAyZDU7CiAgdC5kcGFyZW4gPSAweDI0OWY7CiAgdC5kc3VwZXJpb3IgPSAweGY2ZWI7CiAgdC5kdGFpbCA9IDB4MDI1NjsKICB0LmR0b3BiYXIgPSAweDAxOGM7CiAgdC5kdWhpcmFnYW5hID0gMHgzMDY1OwogIHQuZHVrYXRha2FuYSA9IDB4MzBjNTsKICB0LmR6ID0gMHgwMWYzOwogIHQuZHphbHRvbmUgPSAweDAyYTM7CiAgdC5kemNhcm9uID0gMHgwMWM2OwogIHQuZHpjdXJsID0gMHgwMmE1OwogIHQuZHplYWJraGFzaWFuY3lyaWxsaWMgPSAweDA0ZTE7CiAgdC5kemVjeXJpbGxpYyA9IDB4MDQ1NTsKICB0LmR6aGVjeXJpbGxpYyA9IDB4MDQ1ZjsKICB0LmUgPSAweDAwNjU7CiAgdC5lYWN1dGUgPSAweDAwZTk7CiAgdC5lYXJ0aCA9IDB4MjY0MTsKICB0LmViZW5nYWxpID0gMHgwOThmOwogIHQuZWJvcG9tb2ZvID0gMHgzMTFjOwogIHQuZWJyZXZlID0gMHgwMTE1OwogIHQuZWNhbmRyYWRldmEgPSAweDA5MGQ7CiAgdC5lY2FuZHJhZ3VqYXJhdGkgPSAweDBhOGQ7CiAgdC5lY2FuZHJhdm93ZWxzaWduZGV2YSA9IDB4MDk0NTsKICB0LmVjYW5kcmF2b3dlbHNpZ25ndWphcmF0aSA9IDB4MGFjNTsKICB0LmVjYXJvbiA9IDB4MDExYjsKICB0LmVjZWRpbGxhYnJldmUgPSAweDFlMWQ7CiAgdC5lY2hhcm1lbmlhbiA9IDB4MDU2NTsKICB0LmVjaHlpd25hcm1lbmlhbiA9IDB4MDU4NzsKICB0LmVjaXJjbGUgPSAweDI0ZDQ7CiAgdC5lY2lyY3VtZmxleCA9IDB4MDBlYTsKICB0LmVjaXJjdW1mbGV4YWN1dGUgPSAweDFlYmY7CiAgdC5lY2lyY3VtZmxleGJlbG93ID0gMHgxZTE5OwogIHQuZWNpcmN1bWZsZXhkb3RiZWxvdyA9IDB4MWVjNzsKICB0LmVjaXJjdW1mbGV4Z3JhdmUgPSAweDFlYzE7CiAgdC5lY2lyY3VtZmxleGhvb2thYm92ZSA9IDB4MWVjMzsKICB0LmVjaXJjdW1mbGV4dGlsZGUgPSAweDFlYzU7CiAgdC5lY3lyaWxsaWMgPSAweDA0NTQ7CiAgdC5lZGJsZ3JhdmUgPSAweDAyMDU7CiAgdC5lZGV2YSA9IDB4MDkwZjsKICB0LmVkaWVyZXNpcyA9IDB4MDBlYjsKICB0LmVkb3QgPSAweDAxMTc7CiAgdC5lZG90YWNjZW50ID0gMHgwMTE3OwogIHQuZWRvdGJlbG93ID0gMHgxZWI5OwogIHQuZWVndXJtdWtoaSA9IDB4MGEwZjsKICB0LmVlbWF0cmFndXJtdWtoaSA9IDB4MGE0NzsKICB0LmVmY3lyaWxsaWMgPSAweDA0NDQ7CiAgdC5lZ3JhdmUgPSAweDAwZTg7CiAgdC5lZ3VqYXJhdGkgPSAweDBhOGY7CiAgdC5laGFybWVuaWFuID0gMHgwNTY3OwogIHQuZWhib3BvbW9mbyA9IDB4MzExZDsKICB0LmVoaXJhZ2FuYSA9IDB4MzA0ODsKICB0LmVob29rYWJvdmUgPSAweDFlYmI7CiAgdC5laWJvcG9tb2ZvID0gMHgzMTFmOwogIHQuZWlnaHQgPSAweDAwMzg7CiAgdC5laWdodGFyYWJpYyA9IDB4MDY2ODsKICB0LmVpZ2h0YmVuZ2FsaSA9IDB4MDllZTsKICB0LmVpZ2h0Y2lyY2xlID0gMHgyNDY3OwogIHQuZWlnaHRjaXJjbGVpbnZlcnNlc2Fuc3NlcmlmID0gMHgyNzkxOwogIHQuZWlnaHRkZXZhID0gMHgwOTZlOwogIHQuZWlnaHRlZW5jaXJjbGUgPSAweDI0NzE7CiAgdC5laWdodGVlbnBhcmVuID0gMHgyNDg1OwogIHQuZWlnaHRlZW5wZXJpb2QgPSAweDI0OTk7CiAgdC5laWdodGd1amFyYXRpID0gMHgwYWVlOwogIHQuZWlnaHRndXJtdWtoaSA9IDB4MGE2ZTsKICB0LmVpZ2h0aGFja2FyYWJpYyA9IDB4MDY2ODsKICB0LmVpZ2h0aGFuZ3pob3UgPSAweDMwMjg7CiAgdC5laWdodGhub3RlYmVhbWVkID0gMHgyNjZiOwogIHQuZWlnaHRpZGVvZ3JhcGhpY3BhcmVuID0gMHgzMjI3OwogIHQuZWlnaHRpbmZlcmlvciA9IDB4MjA4ODsKICB0LmVpZ2h0bW9ub3NwYWNlID0gMHhmZjE4OwogIHQuZWlnaHRvbGRzdHlsZSA9IDB4ZjczODsKICB0LmVpZ2h0cGFyZW4gPSAweDI0N2I7CiAgdC5laWdodHBlcmlvZCA9IDB4MjQ4ZjsKICB0LmVpZ2h0cGVyc2lhbiA9IDB4MDZmODsKICB0LmVpZ2h0cm9tYW4gPSAweDIxNzc7CiAgdC5laWdodHN1cGVyaW9yID0gMHgyMDc4OwogIHQuZWlnaHR0aGFpID0gMHgwZTU4OwogIHQuZWludmVydGVkYnJldmUgPSAweDAyMDc7CiAgdC5laW90aWZpZWRjeXJpbGxpYyA9IDB4MDQ2NTsKICB0LmVrYXRha2FuYSA9IDB4MzBhODsKICB0LmVrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY3NDsKICB0LmVrb25rYXJndXJtdWtoaSA9IDB4MGE3NDsKICB0LmVrb3JlYW4gPSAweDMxNTQ7CiAgdC5lbGN5cmlsbGljID0gMHgwNDNiOwogIHQuZWxlbWVudCA9IDB4MjIwODsKICB0LmVsZXZlbmNpcmNsZSA9IDB4MjQ2YTsKICB0LmVsZXZlbnBhcmVuID0gMHgyNDdlOwogIHQuZWxldmVucGVyaW9kID0gMHgyNDkyOwogIHQuZWxldmVucm9tYW4gPSAweDIxN2E7CiAgdC5lbGxpcHNpcyA9IDB4MjAyNjsKICB0LmVsbGlwc2lzdmVydGljYWwgPSAweDIyZWU7CiAgdC5lbWFjcm9uID0gMHgwMTEzOwogIHQuZW1hY3JvbmFjdXRlID0gMHgxZTE3OwogIHQuZW1hY3JvbmdyYXZlID0gMHgxZTE1OwogIHQuZW1jeXJpbGxpYyA9IDB4MDQzYzsKICB0LmVtZGFzaCA9IDB4MjAxNDsKICB0LmVtZGFzaHZlcnRpY2FsID0gMHhmZTMxOwogIHQuZW1vbm9zcGFjZSA9IDB4ZmY0NTsKICB0LmVtcGhhc2lzbWFya2FybWVuaWFuID0gMHgwNTViOwogIHQuZW1wdHlzZXQgPSAweDIyMDU7CiAgdC5lbmJvcG9tb2ZvID0gMHgzMTIzOwogIHQuZW5jeXJpbGxpYyA9IDB4MDQzZDsKICB0LmVuZGFzaCA9IDB4MjAxMzsKICB0LmVuZGFzaHZlcnRpY2FsID0gMHhmZTMyOwogIHQuZW5kZXNjZW5kZXJjeXJpbGxpYyA9IDB4MDRhMzsKICB0LmVuZyA9IDB4MDE0YjsKICB0LmVuZ2JvcG9tb2ZvID0gMHgzMTI1OwogIHQuZW5naGVjeXJpbGxpYyA9IDB4MDRhNTsKICB0LmVuaG9va2N5cmlsbGljID0gMHgwNGM4OwogIHQuZW5zcGFjZSA9IDB4MjAwMjsKICB0LmVvZ29uZWsgPSAweDAxMTk7CiAgdC5lb2tvcmVhbiA9IDB4MzE1MzsKICB0LmVvcGVuID0gMHgwMjViOwogIHQuZW9wZW5jbG9zZWQgPSAweDAyOWE7CiAgdC5lb3BlbnJldmVyc2VkID0gMHgwMjVjOwogIHQuZW9wZW5yZXZlcnNlZGNsb3NlZCA9IDB4MDI1ZTsKICB0LmVvcGVucmV2ZXJzZWRob29rID0gMHgwMjVkOwogIHQuZXBhcmVuID0gMHgyNGEwOwogIHQuZXBzaWxvbiA9IDB4MDNiNTsKICB0LmVwc2lsb250b25vcyA9IDB4MDNhZDsKICB0LmVxdWFsID0gMHgwMDNkOwogIHQuZXF1YWxtb25vc3BhY2UgPSAweGZmMWQ7CiAgdC5lcXVhbHNtYWxsID0gMHhmZTY2OwogIHQuZXF1YWxzdXBlcmlvciA9IDB4MjA3YzsKICB0LmVxdWl2YWxlbmNlID0gMHgyMjYxOwogIHQuZXJib3BvbW9mbyA9IDB4MzEyNjsKICB0LmVyY3lyaWxsaWMgPSAweDA0NDA7CiAgdC5lcmV2ZXJzZWQgPSAweDAyNTg7CiAgdC5lcmV2ZXJzZWRjeXJpbGxpYyA9IDB4MDQ0ZDsKICB0LmVzY3lyaWxsaWMgPSAweDA0NDE7CiAgdC5lc2Rlc2NlbmRlcmN5cmlsbGljID0gMHgwNGFiOwogIHQuZXNoID0gMHgwMjgzOwogIHQuZXNoY3VybCA9IDB4MDI4NjsKICB0LmVzaG9ydGRldmEgPSAweDA5MGU7CiAgdC5lc2hvcnR2b3dlbHNpZ25kZXZhID0gMHgwOTQ2OwogIHQuZXNocmV2ZXJzZWRsb29wID0gMHgwMWFhOwogIHQuZXNoc3F1YXRyZXZlcnNlZCA9IDB4MDI4NTsKICB0LmVzbWFsbGhpcmFnYW5hID0gMHgzMDQ3OwogIHQuZXNtYWxsa2F0YWthbmEgPSAweDMwYTc7CiAgdC5lc21hbGxrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY2YTsKICB0LmVzdGltYXRlZCA9IDB4MjEyZTsKICB0LmVzdXBlcmlvciA9IDB4ZjZlYzsKICB0LmV0YSA9IDB4MDNiNzsKICB0LmV0YXJtZW5pYW4gPSAweDA1Njg7CiAgdC5ldGF0b25vcyA9IDB4MDNhZTsKICB0LmV0aCA9IDB4MDBmMDsKICB0LmV0aWxkZSA9IDB4MWViZDsKICB0LmV0aWxkZWJlbG93ID0gMHgxZTFiOwogIHQuZXRuYWh0YWZvdWtoaGVicmV3ID0gMHgwNTkxOwogIHQuZXRuYWh0YWZvdWtobGVmdGhlYnJldyA9IDB4MDU5MTsKICB0LmV0bmFodGFoZWJyZXcgPSAweDA1OTE7CiAgdC5ldG5haHRhbGVmdGhlYnJldyA9IDB4MDU5MTsKICB0LmV0dXJuZWQgPSAweDAxZGQ7CiAgdC5ldWtvcmVhbiA9IDB4MzE2MTsKICB0LmV1cm8gPSAweDIwYWM7CiAgdC5ldm93ZWxzaWduYmVuZ2FsaSA9IDB4MDljNzsKICB0LmV2b3dlbHNpZ25kZXZhID0gMHgwOTQ3OwogIHQuZXZvd2Vsc2lnbmd1amFyYXRpID0gMHgwYWM3OwogIHQuZXhjbGFtID0gMHgwMDIxOwogIHQuZXhjbGFtYXJtZW5pYW4gPSAweDA1NWM7CiAgdC5leGNsYW1kYmwgPSAweDIwM2M7CiAgdC5leGNsYW1kb3duID0gMHgwMGExOwogIHQuZXhjbGFtZG93bnNtYWxsID0gMHhmN2ExOwogIHQuZXhjbGFtbW9ub3NwYWNlID0gMHhmZjAxOwogIHQuZXhjbGFtc21hbGwgPSAweGY3MjE7CiAgdC5leGlzdGVudGlhbCA9IDB4MjIwMzsKICB0LmV6aCA9IDB4MDI5MjsKICB0LmV6aGNhcm9uID0gMHgwMWVmOwogIHQuZXpoY3VybCA9IDB4MDI5MzsKICB0LmV6aHJldmVyc2VkID0gMHgwMWI5OwogIHQuZXpodGFpbCA9IDB4MDFiYTsKICB0LmYgPSAweDAwNjY7CiAgdC5mYWRldmEgPSAweDA5NWU7CiAgdC5mYWd1cm11a2hpID0gMHgwYTVlOwogIHQuZmFocmVuaGVpdCA9IDB4MjEwOTsKICB0LmZhdGhhYXJhYmljID0gMHgwNjRlOwogIHQuZmF0aGFsb3dhcmFiaWMgPSAweDA2NGU7CiAgdC5mYXRoYXRhbmFyYWJpYyA9IDB4MDY0YjsKICB0LmZib3BvbW9mbyA9IDB4MzEwODsKICB0LmZjaXJjbGUgPSAweDI0ZDU7CiAgdC5mZG90YWNjZW50ID0gMHgxZTFmOwogIHQuZmVoYXJhYmljID0gMHgwNjQxOwogIHQuZmVoYXJtZW5pYW4gPSAweDA1ODY7CiAgdC5mZWhmaW5hbGFyYWJpYyA9IDB4ZmVkMjsKICB0LmZlaGluaXRpYWxhcmFiaWMgPSAweGZlZDM7CiAgdC5mZWhtZWRpYWxhcmFiaWMgPSAweGZlZDQ7CiAgdC5mZWljb3B0aWMgPSAweDAzZTU7CiAgdC5mZW1hbGUgPSAweDI2NDA7CiAgdC5mZiA9IDB4ZmIwMDsKICB0LmZfZiA9IDB4ZmIwMDsKICB0LmZmaSA9IDB4ZmIwMzsKICB0LmZfZl9pID0gMHhmYjAzOwogIHQuZmZsID0gMHhmYjA0OwogIHQuZl9mX2wgPSAweGZiMDQ7CiAgdC5maSA9IDB4ZmIwMTsKICB0LmZfaSA9IDB4ZmIwMTsKICB0LmZpZnRlZW5jaXJjbGUgPSAweDI0NmU7CiAgdC5maWZ0ZWVucGFyZW4gPSAweDI0ODI7CiAgdC5maWZ0ZWVucGVyaW9kID0gMHgyNDk2OwogIHQuZmlndXJlZGFzaCA9IDB4MjAxMjsKICB0LmZpbGxlZGJveCA9IDB4MjVhMDsKICB0LmZpbGxlZHJlY3QgPSAweDI1YWM7CiAgdC5maW5hbGthZiA9IDB4MDVkYTsKICB0LmZpbmFsa2FmZGFnZXNoID0gMHhmYjNhOwogIHQuZmluYWxrYWZkYWdlc2hoZWJyZXcgPSAweGZiM2E7CiAgdC5maW5hbGthZmhlYnJldyA9IDB4MDVkYTsKICB0LmZpbmFsbWVtID0gMHgwNWRkOwogIHQuZmluYWxtZW1oZWJyZXcgPSAweDA1ZGQ7CiAgdC5maW5hbG51biA9IDB4MDVkZjsKICB0LmZpbmFsbnVuaGVicmV3ID0gMHgwNWRmOwogIHQuZmluYWxwZSA9IDB4MDVlMzsKICB0LmZpbmFscGVoZWJyZXcgPSAweDA1ZTM7CiAgdC5maW5hbHRzYWRpID0gMHgwNWU1OwogIHQuZmluYWx0c2FkaWhlYnJldyA9IDB4MDVlNTsKICB0LmZpcnN0dG9uZWNoaW5lc2UgPSAweDAyYzk7CiAgdC5maXNoZXllID0gMHgyNWM5OwogIHQuZml0YWN5cmlsbGljID0gMHgwNDczOwogIHQuZml2ZSA9IDB4MDAzNTsKICB0LmZpdmVhcmFiaWMgPSAweDA2NjU7CiAgdC5maXZlYmVuZ2FsaSA9IDB4MDllYjsKICB0LmZpdmVjaXJjbGUgPSAweDI0NjQ7CiAgdC5maXZlY2lyY2xlaW52ZXJzZXNhbnNzZXJpZiA9IDB4Mjc4ZTsKICB0LmZpdmVkZXZhID0gMHgwOTZiOwogIHQuZml2ZWVpZ2h0aHMgPSAweDIxNWQ7CiAgdC5maXZlZ3VqYXJhdGkgPSAweDBhZWI7CiAgdC5maXZlZ3VybXVraGkgPSAweDBhNmI7CiAgdC5maXZlaGFja2FyYWJpYyA9IDB4MDY2NTsKICB0LmZpdmVoYW5nemhvdSA9IDB4MzAyNTsKICB0LmZpdmVpZGVvZ3JhcGhpY3BhcmVuID0gMHgzMjI0OwogIHQuZml2ZWluZmVyaW9yID0gMHgyMDg1OwogIHQuZml2ZW1vbm9zcGFjZSA9IDB4ZmYxNTsKICB0LmZpdmVvbGRzdHlsZSA9IDB4ZjczNTsKICB0LmZpdmVwYXJlbiA9IDB4MjQ3ODsKICB0LmZpdmVwZXJpb2QgPSAweDI0OGM7CiAgdC5maXZlcGVyc2lhbiA9IDB4MDZmNTsKICB0LmZpdmVyb21hbiA9IDB4MjE3NDsKICB0LmZpdmVzdXBlcmlvciA9IDB4MjA3NTsKICB0LmZpdmV0aGFpID0gMHgwZTU1OwogIHQuZmwgPSAweGZiMDI7CiAgdC5mX2wgPSAweGZiMDI7CiAgdC5mbG9yaW4gPSAweDAxOTI7CiAgdC5mbW9ub3NwYWNlID0gMHhmZjQ2OwogIHQuZm1zcXVhcmUgPSAweDMzOTk7CiAgdC5mb2ZhbnRoYWkgPSAweDBlMWY7CiAgdC5mb2ZhdGhhaSA9IDB4MGUxZDsKICB0LmZvbmdtYW50aGFpID0gMHgwZTRmOwogIHQuZm9yYWxsID0gMHgyMjAwOwogIHQuZm91ciA9IDB4MDAzNDsKICB0LmZvdXJhcmFiaWMgPSAweDA2NjQ7CiAgdC5mb3VyYmVuZ2FsaSA9IDB4MDllYTsKICB0LmZvdXJjaXJjbGUgPSAweDI0NjM7CiAgdC5mb3VyY2lyY2xlaW52ZXJzZXNhbnNzZXJpZiA9IDB4Mjc4ZDsKICB0LmZvdXJkZXZhID0gMHgwOTZhOwogIHQuZm91cmd1amFyYXRpID0gMHgwYWVhOwogIHQuZm91cmd1cm11a2hpID0gMHgwYTZhOwogIHQuZm91cmhhY2thcmFiaWMgPSAweDA2NjQ7CiAgdC5mb3VyaGFuZ3pob3UgPSAweDMwMjQ7CiAgdC5mb3VyaWRlb2dyYXBoaWNwYXJlbiA9IDB4MzIyMzsKICB0LmZvdXJpbmZlcmlvciA9IDB4MjA4NDsKICB0LmZvdXJtb25vc3BhY2UgPSAweGZmMTQ7CiAgdC5mb3VybnVtZXJhdG9yYmVuZ2FsaSA9IDB4MDlmNzsKICB0LmZvdXJvbGRzdHlsZSA9IDB4ZjczNDsKICB0LmZvdXJwYXJlbiA9IDB4MjQ3NzsKICB0LmZvdXJwZXJpb2QgPSAweDI0OGI7CiAgdC5mb3VycGVyc2lhbiA9IDB4MDZmNDsKICB0LmZvdXJyb21hbiA9IDB4MjE3MzsKICB0LmZvdXJzdXBlcmlvciA9IDB4MjA3NDsKICB0LmZvdXJ0ZWVuY2lyY2xlID0gMHgyNDZkOwogIHQuZm91cnRlZW5wYXJlbiA9IDB4MjQ4MTsKICB0LmZvdXJ0ZWVucGVyaW9kID0gMHgyNDk1OwogIHQuZm91cnRoYWkgPSAweDBlNTQ7CiAgdC5mb3VydGh0b25lY2hpbmVzZSA9IDB4MDJjYjsKICB0LmZwYXJlbiA9IDB4MjRhMTsKICB0LmZyYWN0aW9uID0gMHgyMDQ0OwogIHQuZnJhbmMgPSAweDIwYTM7CiAgdC5nID0gMHgwMDY3OwogIHQuZ2FiZW5nYWxpID0gMHgwOTk3OwogIHQuZ2FjdXRlID0gMHgwMWY1OwogIHQuZ2FkZXZhID0gMHgwOTE3OwogIHQuZ2FmYXJhYmljID0gMHgwNmFmOwogIHQuZ2FmZmluYWxhcmFiaWMgPSAweGZiOTM7CiAgdC5nYWZpbml0aWFsYXJhYmljID0gMHhmYjk0OwogIHQuZ2FmbWVkaWFsYXJhYmljID0gMHhmYjk1OwogIHQuZ2FndWphcmF0aSA9IDB4MGE5NzsKICB0LmdhZ3VybXVraGkgPSAweDBhMTc7CiAgdC5nYWhpcmFnYW5hID0gMHgzMDRjOwogIHQuZ2FrYXRha2FuYSA9IDB4MzBhYzsKICB0LmdhbW1hID0gMHgwM2IzOwogIHQuZ2FtbWFsYXRpbnNtYWxsID0gMHgwMjYzOwogIHQuZ2FtbWFzdXBlcmlvciA9IDB4MDJlMDsKICB0LmdhbmdpYWNvcHRpYyA9IDB4MDNlYjsKICB0Lmdib3BvbW9mbyA9IDB4MzEwZDsKICB0LmdicmV2ZSA9IDB4MDExZjsKICB0LmdjYXJvbiA9IDB4MDFlNzsKICB0LmdjZWRpbGxhID0gMHgwMTIzOwogIHQuZ2NpcmNsZSA9IDB4MjRkNjsKICB0LmdjaXJjdW1mbGV4ID0gMHgwMTFkOwogIHQuZ2NvbW1hYWNjZW50ID0gMHgwMTIzOwogIHQuZ2RvdCA9IDB4MDEyMTsKICB0Lmdkb3RhY2NlbnQgPSAweDAxMjE7CiAgdC5nZWN5cmlsbGljID0gMHgwNDMzOwogIHQuZ2VoaXJhZ2FuYSA9IDB4MzA1MjsKICB0Lmdla2F0YWthbmEgPSAweDMwYjI7CiAgdC5nZW9tZXRyaWNhbGx5ZXF1YWwgPSAweDIyNTE7CiAgdC5nZXJlc2hhY2NlbnRoZWJyZXcgPSAweDA1OWM7CiAgdC5nZXJlc2hoZWJyZXcgPSAweDA1ZjM7CiAgdC5nZXJlc2htdXFkYW1oZWJyZXcgPSAweDA1OWQ7CiAgdC5nZXJtYW5kYmxzID0gMHgwMGRmOwogIHQuZ2Vyc2hheWltYWNjZW50aGVicmV3ID0gMHgwNTllOwogIHQuZ2Vyc2hheWltaGVicmV3ID0gMHgwNWY0OwogIHQuZ2V0YW1hcmsgPSAweDMwMTM7CiAgdC5naGFiZW5nYWxpID0gMHgwOTk4OwogIHQuZ2hhZGFybWVuaWFuID0gMHgwNTcyOwogIHQuZ2hhZGV2YSA9IDB4MDkxODsKICB0LmdoYWd1amFyYXRpID0gMHgwYTk4OwogIHQuZ2hhZ3VybXVraGkgPSAweDBhMTg7CiAgdC5naGFpbmFyYWJpYyA9IDB4MDYzYTsKICB0LmdoYWluZmluYWxhcmFiaWMgPSAweGZlY2U7CiAgdC5naGFpbmluaXRpYWxhcmFiaWMgPSAweGZlY2Y7CiAgdC5naGFpbm1lZGlhbGFyYWJpYyA9IDB4ZmVkMDsKICB0LmdoZW1pZGRsZWhvb2tjeXJpbGxpYyA9IDB4MDQ5NTsKICB0LmdoZXN0cm9rZWN5cmlsbGljID0gMHgwNDkzOwogIHQuZ2hldXB0dXJuY3lyaWxsaWMgPSAweDA0OTE7CiAgdC5naGhhZGV2YSA9IDB4MDk1YTsKICB0LmdoaGFndXJtdWtoaSA9IDB4MGE1YTsKICB0Lmdob29rID0gMHgwMjYwOwogIHQuZ2h6c3F1YXJlID0gMHgzMzkzOwogIHQuZ2loaXJhZ2FuYSA9IDB4MzA0ZTsKICB0Lmdpa2F0YWthbmEgPSAweDMwYWU7CiAgdC5naW1hcm1lbmlhbiA9IDB4MDU2MzsKICB0LmdpbWVsID0gMHgwNWQyOwogIHQuZ2ltZWxkYWdlc2ggPSAweGZiMzI7CiAgdC5naW1lbGRhZ2VzaGhlYnJldyA9IDB4ZmIzMjsKICB0LmdpbWVsaGVicmV3ID0gMHgwNWQyOwogIHQuZ2plY3lyaWxsaWMgPSAweDA0NTM7CiAgdC5nbG90dGFsaW52ZXJ0ZWRzdHJva2UgPSAweDAxYmU7CiAgdC5nbG90dGFsc3RvcCA9IDB4MDI5NDsKICB0Lmdsb3R0YWxzdG9waW52ZXJ0ZWQgPSAweDAyOTY7CiAgdC5nbG90dGFsc3RvcG1vZCA9IDB4MDJjMDsKICB0Lmdsb3R0YWxzdG9wcmV2ZXJzZWQgPSAweDAyOTU7CiAgdC5nbG90dGFsc3RvcHJldmVyc2VkbW9kID0gMHgwMmMxOwogIHQuZ2xvdHRhbHN0b3ByZXZlcnNlZHN1cGVyaW9yID0gMHgwMmU0OwogIHQuZ2xvdHRhbHN0b3BzdHJva2UgPSAweDAyYTE7CiAgdC5nbG90dGFsc3RvcHN0cm9rZXJldmVyc2VkID0gMHgwMmEyOwogIHQuZ21hY3JvbiA9IDB4MWUyMTsKICB0Lmdtb25vc3BhY2UgPSAweGZmNDc7CiAgdC5nb2hpcmFnYW5hID0gMHgzMDU0OwogIHQuZ29rYXRha2FuYSA9IDB4MzBiNDsKICB0LmdwYXJlbiA9IDB4MjRhMjsKICB0LmdwYXNxdWFyZSA9IDB4MzNhYzsKICB0LmdyYWRpZW50ID0gMHgyMjA3OwogIHQuZ3JhdmUgPSAweDAwNjA7CiAgdC5ncmF2ZWJlbG93Y21iID0gMHgwMzE2OwogIHQuZ3JhdmVjbWIgPSAweDAzMDA7CiAgdC5ncmF2ZWNvbWIgPSAweDAzMDA7CiAgdC5ncmF2ZWRldmEgPSAweDA5NTM7CiAgdC5ncmF2ZWxvd21vZCA9IDB4MDJjZTsKICB0LmdyYXZlbW9ub3NwYWNlID0gMHhmZjQwOwogIHQuZ3JhdmV0b25lY21iID0gMHgwMzQwOwogIHQuZ3JlYXRlciA9IDB4MDAzZTsKICB0LmdyZWF0ZXJlcXVhbCA9IDB4MjI2NTsKICB0LmdyZWF0ZXJlcXVhbG9ybGVzcyA9IDB4MjJkYjsKICB0LmdyZWF0ZXJtb25vc3BhY2UgPSAweGZmMWU7CiAgdC5ncmVhdGVyb3JlcXVpdmFsZW50ID0gMHgyMjczOwogIHQuZ3JlYXRlcm9ybGVzcyA9IDB4MjI3NzsKICB0LmdyZWF0ZXJvdmVyZXF1YWwgPSAweDIyNjc7CiAgdC5ncmVhdGVyc21hbGwgPSAweGZlNjU7CiAgdC5nc2NyaXB0ID0gMHgwMjYxOwogIHQuZ3N0cm9rZSA9IDB4MDFlNTsKICB0Lmd1aGlyYWdhbmEgPSAweDMwNTA7CiAgdC5ndWlsbGVtb3RsZWZ0ID0gMHgwMGFiOwogIHQuZ3VpbGxlbW90cmlnaHQgPSAweDAwYmI7CiAgdC5ndWlsc2luZ2xsZWZ0ID0gMHgyMDM5OwogIHQuZ3VpbHNpbmdscmlnaHQgPSAweDIwM2E7CiAgdC5ndWthdGFrYW5hID0gMHgzMGIwOwogIHQuZ3VyYW11c3F1YXJlID0gMHgzMzE4OwogIHQuZ3lzcXVhcmUgPSAweDMzYzk7CiAgdC5oID0gMHgwMDY4OwogIHQuaGFhYmtoYXNpYW5jeXJpbGxpYyA9IDB4MDRhOTsKICB0LmhhYWx0b25lYXJhYmljID0gMHgwNmMxOwogIHQuaGFiZW5nYWxpID0gMHgwOWI5OwogIHQuaGFkZXNjZW5kZXJjeXJpbGxpYyA9IDB4MDRiMzsKICB0LmhhZGV2YSA9IDB4MDkzOTsKICB0LmhhZ3VqYXJhdGkgPSAweDBhYjk7CiAgdC5oYWd1cm11a2hpID0gMHgwYTM5OwogIHQuaGFoYXJhYmljID0gMHgwNjJkOwogIHQuaGFoZmluYWxhcmFiaWMgPSAweGZlYTI7CiAgdC5oYWhpbml0aWFsYXJhYmljID0gMHhmZWEzOwogIHQuaGFoaXJhZ2FuYSA9IDB4MzA2ZjsKICB0LmhhaG1lZGlhbGFyYWJpYyA9IDB4ZmVhNDsKICB0LmhhaXR1c3F1YXJlID0gMHgzMzJhOwogIHQuaGFrYXRha2FuYSA9IDB4MzBjZjsKICB0Lmhha2F0YWthbmFoYWxmd2lkdGggPSAweGZmOGE7CiAgdC5oYWxhbnRndXJtdWtoaSA9IDB4MGE0ZDsKICB0LmhhbXphYXJhYmljID0gMHgwNjIxOwogIHQuaGFtemFsb3dhcmFiaWMgPSAweDA2MjE7CiAgdC5oYW5ndWxmaWxsZXIgPSAweDMxNjQ7CiAgdC5oYXJkc2lnbmN5cmlsbGljID0gMHgwNDRhOwogIHQuaGFycG9vbmxlZnRiYXJidXAgPSAweDIxYmM7CiAgdC5oYXJwb29ucmlnaHRiYXJidXAgPSAweDIxYzA7CiAgdC5oYXNxdWFyZSA9IDB4MzNjYTsKICB0LmhhdGFmcGF0YWggPSAweDA1YjI7CiAgdC5oYXRhZnBhdGFoMTYgPSAweDA1YjI7CiAgdC5oYXRhZnBhdGFoMjMgPSAweDA1YjI7CiAgdC5oYXRhZnBhdGFoMmYgPSAweDA1YjI7CiAgdC5oYXRhZnBhdGFoaGVicmV3ID0gMHgwNWIyOwogIHQuaGF0YWZwYXRhaG5hcnJvd2hlYnJldyA9IDB4MDViMjsKICB0LmhhdGFmcGF0YWhxdWFydGVyaGVicmV3ID0gMHgwNWIyOwogIHQuaGF0YWZwYXRhaHdpZGVoZWJyZXcgPSAweDA1YjI7CiAgdC5oYXRhZnFhbWF0cyA9IDB4MDViMzsKICB0LmhhdGFmcWFtYXRzMWIgPSAweDA1YjM7CiAgdC5oYXRhZnFhbWF0czI4ID0gMHgwNWIzOwogIHQuaGF0YWZxYW1hdHMzNCA9IDB4MDViMzsKICB0LmhhdGFmcWFtYXRzaGVicmV3ID0gMHgwNWIzOwogIHQuaGF0YWZxYW1hdHNuYXJyb3doZWJyZXcgPSAweDA1YjM7CiAgdC5oYXRhZnFhbWF0c3F1YXJ0ZXJoZWJyZXcgPSAweDA1YjM7CiAgdC5oYXRhZnFhbWF0c3dpZGVoZWJyZXcgPSAweDA1YjM7CiAgdC5oYXRhZnNlZ29sID0gMHgwNWIxOwogIHQuaGF0YWZzZWdvbDE3ID0gMHgwNWIxOwogIHQuaGF0YWZzZWdvbDI0ID0gMHgwNWIxOwogIHQuaGF0YWZzZWdvbDMwID0gMHgwNWIxOwogIHQuaGF0YWZzZWdvbGhlYnJldyA9IDB4MDViMTsKICB0LmhhdGFmc2Vnb2xuYXJyb3doZWJyZXcgPSAweDA1YjE7CiAgdC5oYXRhZnNlZ29scXVhcnRlcmhlYnJldyA9IDB4MDViMTsKICB0LmhhdGFmc2Vnb2x3aWRlaGVicmV3ID0gMHgwNWIxOwogIHQuaGJhciA9IDB4MDEyNzsKICB0Lmhib3BvbW9mbyA9IDB4MzEwZjsKICB0LmhicmV2ZWJlbG93ID0gMHgxZTJiOwogIHQuaGNlZGlsbGEgPSAweDFlMjk7CiAgdC5oY2lyY2xlID0gMHgyNGQ3OwogIHQuaGNpcmN1bWZsZXggPSAweDAxMjU7CiAgdC5oZGllcmVzaXMgPSAweDFlMjc7CiAgdC5oZG90YWNjZW50ID0gMHgxZTIzOwogIHQuaGRvdGJlbG93ID0gMHgxZTI1OwogIHQuaGUgPSAweDA1ZDQ7CiAgdC5oZWFydCA9IDB4MjY2NTsKICB0LmhlYXJ0c3VpdGJsYWNrID0gMHgyNjY1OwogIHQuaGVhcnRzdWl0d2hpdGUgPSAweDI2NjE7CiAgdC5oZWRhZ2VzaCA9IDB4ZmIzNDsKICB0LmhlZGFnZXNoaGVicmV3ID0gMHhmYjM0OwogIHQuaGVoYWx0b25lYXJhYmljID0gMHgwNmMxOwogIHQuaGVoYXJhYmljID0gMHgwNjQ3OwogIHQuaGVoZWJyZXcgPSAweDA1ZDQ7CiAgdC5oZWhmaW5hbGFsdG9uZWFyYWJpYyA9IDB4ZmJhNzsKICB0LmhlaGZpbmFsYWx0dHdvYXJhYmljID0gMHhmZWVhOwogIHQuaGVoZmluYWxhcmFiaWMgPSAweGZlZWE7CiAgdC5oZWhoYW16YWFib3ZlZmluYWxhcmFiaWMgPSAweGZiYTU7CiAgdC5oZWhoYW16YWFib3ZlaXNvbGF0ZWRhcmFiaWMgPSAweGZiYTQ7CiAgdC5oZWhpbml0aWFsYWx0b25lYXJhYmljID0gMHhmYmE4OwogIHQuaGVoaW5pdGlhbGFyYWJpYyA9IDB4ZmVlYjsKICB0LmhlaGlyYWdhbmEgPSAweDMwNzg7CiAgdC5oZWhtZWRpYWxhbHRvbmVhcmFiaWMgPSAweGZiYTk7CiAgdC5oZWhtZWRpYWxhcmFiaWMgPSAweGZlZWM7CiAgdC5oZWlzZWllcmFzcXVhcmUgPSAweDMzN2I7CiAgdC5oZWthdGFrYW5hID0gMHgzMGQ4OwogIHQuaGVrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY4ZDsKICB0Lmhla3V0YWFydXNxdWFyZSA9IDB4MzMzNjsKICB0Lmhlbmdob29rID0gMHgwMjY3OwogIHQuaGVydXR1c3F1YXJlID0gMHgzMzM5OwogIHQuaGV0ID0gMHgwNWQ3OwogIHQuaGV0aGVicmV3ID0gMHgwNWQ3OwogIHQuaGhvb2sgPSAweDAyNjY7CiAgdC5oaG9va3N1cGVyaW9yID0gMHgwMmIxOwogIHQuaGlldWhhY2lyY2xla29yZWFuID0gMHgzMjdiOwogIHQuaGlldWhhcGFyZW5rb3JlYW4gPSAweDMyMWI7CiAgdC5oaWV1aGNpcmNsZWtvcmVhbiA9IDB4MzI2ZDsKICB0LmhpZXVoa29yZWFuID0gMHgzMTRlOwogIHQuaGlldWhwYXJlbmtvcmVhbiA9IDB4MzIwZDsKICB0LmhpaGlyYWdhbmEgPSAweDMwNzI7CiAgdC5oaWthdGFrYW5hID0gMHgzMGQyOwogIHQuaGlrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY4YjsKICB0LmhpcmlxID0gMHgwNWI0OwogIHQuaGlyaXExNCA9IDB4MDViNDsKICB0LmhpcmlxMjEgPSAweDA1YjQ7CiAgdC5oaXJpcTJkID0gMHgwNWI0OwogIHQuaGlyaXFoZWJyZXcgPSAweDA1YjQ7CiAgdC5oaXJpcW5hcnJvd2hlYnJldyA9IDB4MDViNDsKICB0LmhpcmlxcXVhcnRlcmhlYnJldyA9IDB4MDViNDsKICB0Lmhpcmlxd2lkZWhlYnJldyA9IDB4MDViNDsKICB0LmhsaW5lYmVsb3cgPSAweDFlOTY7CiAgdC5obW9ub3NwYWNlID0gMHhmZjQ4OwogIHQuaG9hcm1lbmlhbiA9IDB4MDU3MDsKICB0LmhvaGlwdGhhaSA9IDB4MGUyYjsKICB0LmhvaGlyYWdhbmEgPSAweDMwN2I7CiAgdC5ob2thdGFrYW5hID0gMHgzMGRiOwogIHQuaG9rYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY4ZTsKICB0LmhvbGFtID0gMHgwNWI5OwogIHQuaG9sYW0xOSA9IDB4MDViOTsKICB0LmhvbGFtMjYgPSAweDA1Yjk7CiAgdC5ob2xhbTMyID0gMHgwNWI5OwogIHQuaG9sYW1oZWJyZXcgPSAweDA1Yjk7CiAgdC5ob2xhbW5hcnJvd2hlYnJldyA9IDB4MDViOTsKICB0LmhvbGFtcXVhcnRlcmhlYnJldyA9IDB4MDViOTsKICB0LmhvbGFtd2lkZWhlYnJldyA9IDB4MDViOTsKICB0Lmhvbm9raHVrdGhhaSA9IDB4MGUyZTsKICB0Lmhvb2thYm92ZWNvbWIgPSAweDAzMDk7CiAgdC5ob29rY21iID0gMHgwMzA5OwogIHQuaG9va3BhbGF0YWxpemVkYmVsb3djbWIgPSAweDAzMjE7CiAgdC5ob29rcmV0cm9mbGV4YmVsb3djbWIgPSAweDAzMjI7CiAgdC5ob29uc3F1YXJlID0gMHgzMzQyOwogIHQuaG9yaWNvcHRpYyA9IDB4MDNlOTsKICB0Lmhvcml6b250YWxiYXIgPSAweDIwMTU7CiAgdC5ob3JuY21iID0gMHgwMzFiOwogIHQuaG90c3ByaW5ncyA9IDB4MjY2ODsKICB0LmhvdXNlID0gMHgyMzAyOwogIHQuaHBhcmVuID0gMHgyNGEzOwogIHQuaHN1cGVyaW9yID0gMHgwMmIwOwogIHQuaHR1cm5lZCA9IDB4MDI2NTsKICB0Lmh1aGlyYWdhbmEgPSAweDMwNzU7CiAgdC5odWlpdG9zcXVhcmUgPSAweDMzMzM7CiAgdC5odWthdGFrYW5hID0gMHgzMGQ1OwogIHQuaHVrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY4YzsKICB0Lmh1bmdhcnVtbGF1dCA9IDB4MDJkZDsKICB0Lmh1bmdhcnVtbGF1dGNtYiA9IDB4MDMwYjsKICB0Lmh2ID0gMHgwMTk1OwogIHQuaHlwaGVuID0gMHgwMDJkOwogIHQuaHlwaGVuaW5mZXJpb3IgPSAweGY2ZTU7CiAgdC5oeXBoZW5tb25vc3BhY2UgPSAweGZmMGQ7CiAgdC5oeXBoZW5zbWFsbCA9IDB4ZmU2MzsKICB0Lmh5cGhlbnN1cGVyaW9yID0gMHhmNmU2OwogIHQuaHlwaGVudHdvID0gMHgyMDEwOwogIHQuaSA9IDB4MDA2OTsKICB0LmlhY3V0ZSA9IDB4MDBlZDsKICB0LmlhY3lyaWxsaWMgPSAweDA0NGY7CiAgdC5pYmVuZ2FsaSA9IDB4MDk4NzsKICB0Lmlib3BvbW9mbyA9IDB4MzEyNzsKICB0LmlicmV2ZSA9IDB4MDEyZDsKICB0LmljYXJvbiA9IDB4MDFkMDsKICB0LmljaXJjbGUgPSAweDI0ZDg7CiAgdC5pY2lyY3VtZmxleCA9IDB4MDBlZTsKICB0LmljeXJpbGxpYyA9IDB4MDQ1NjsKICB0LmlkYmxncmF2ZSA9IDB4MDIwOTsKICB0LmlkZW9ncmFwaGVhcnRoY2lyY2xlID0gMHgzMjhmOwogIHQuaWRlb2dyYXBoZmlyZWNpcmNsZSA9IDB4MzI4YjsKICB0LmlkZW9ncmFwaGljYWxsaWFuY2VwYXJlbiA9IDB4MzIzZjsKICB0LmlkZW9ncmFwaGljY2FsbHBhcmVuID0gMHgzMjNhOwogIHQuaWRlb2dyYXBoaWNjZW50cmVjaXJjbGUgPSAweDMyYTU7CiAgdC5pZGVvZ3JhcGhpY2Nsb3NlID0gMHgzMDA2OwogIHQuaWRlb2dyYXBoaWNjb21tYSA9IDB4MzAwMTsKICB0LmlkZW9ncmFwaGljY29tbWFsZWZ0ID0gMHhmZjY0OwogIHQuaWRlb2dyYXBoaWNjb25ncmF0dWxhdGlvbnBhcmVuID0gMHgzMjM3OwogIHQuaWRlb2dyYXBoaWNjb3JyZWN0Y2lyY2xlID0gMHgzMmEzOwogIHQuaWRlb2dyYXBoaWNlYXJ0aHBhcmVuID0gMHgzMjJmOwogIHQuaWRlb2dyYXBoaWNlbnRlcnByaXNlcGFyZW4gPSAweDMyM2Q7CiAgdC5pZGVvZ3JhcGhpY2V4Y2VsbGVudGNpcmNsZSA9IDB4MzI5ZDsKICB0LmlkZW9ncmFwaGljZmVzdGl2YWxwYXJlbiA9IDB4MzI0MDsKICB0LmlkZW9ncmFwaGljZmluYW5jaWFsY2lyY2xlID0gMHgzMjk2OwogIHQuaWRlb2dyYXBoaWNmaW5hbmNpYWxwYXJlbiA9IDB4MzIzNjsKICB0LmlkZW9ncmFwaGljZmlyZXBhcmVuID0gMHgzMjJiOwogIHQuaWRlb2dyYXBoaWNoYXZlcGFyZW4gPSAweDMyMzI7CiAgdC5pZGVvZ3JhcGhpY2hpZ2hjaXJjbGUgPSAweDMyYTQ7CiAgdC5pZGVvZ3JhcGhpY2l0ZXJhdGlvbm1hcmsgPSAweDMwMDU7CiAgdC5pZGVvZ3JhcGhpY2xhYm9yY2lyY2xlID0gMHgzMjk4OwogIHQuaWRlb2dyYXBoaWNsYWJvcnBhcmVuID0gMHgzMjM4OwogIHQuaWRlb2dyYXBoaWNsZWZ0Y2lyY2xlID0gMHgzMmE3OwogIHQuaWRlb2dyYXBoaWNsb3djaXJjbGUgPSAweDMyYTY7CiAgdC5pZGVvZ3JhcGhpY21lZGljaW5lY2lyY2xlID0gMHgzMmE5OwogIHQuaWRlb2dyYXBoaWNtZXRhbHBhcmVuID0gMHgzMjJlOwogIHQuaWRlb2dyYXBoaWNtb29ucGFyZW4gPSAweDMyMmE7CiAgdC5pZGVvZ3JhcGhpY25hbWVwYXJlbiA9IDB4MzIzNDsKICB0LmlkZW9ncmFwaGljcGVyaW9kID0gMHgzMDAyOwogIHQuaWRlb2dyYXBoaWNwcmludGNpcmNsZSA9IDB4MzI5ZTsKICB0LmlkZW9ncmFwaGljcmVhY2hwYXJlbiA9IDB4MzI0MzsKICB0LmlkZW9ncmFwaGljcmVwcmVzZW50cGFyZW4gPSAweDMyMzk7CiAgdC5pZGVvZ3JhcGhpY3Jlc291cmNlcGFyZW4gPSAweDMyM2U7CiAgdC5pZGVvZ3JhcGhpY3JpZ2h0Y2lyY2xlID0gMHgzMmE4OwogIHQuaWRlb2dyYXBoaWNzZWNyZXRjaXJjbGUgPSAweDMyOTk7CiAgdC5pZGVvZ3JhcGhpY3NlbGZwYXJlbiA9IDB4MzI0MjsKICB0LmlkZW9ncmFwaGljc29jaWV0eXBhcmVuID0gMHgzMjMzOwogIHQuaWRlb2dyYXBoaWNzcGFjZSA9IDB4MzAwMDsKICB0LmlkZW9ncmFwaGljc3BlY2lhbHBhcmVuID0gMHgzMjM1OwogIHQuaWRlb2dyYXBoaWNzdG9ja3BhcmVuID0gMHgzMjMxOwogIHQuaWRlb2dyYXBoaWNzdHVkeXBhcmVuID0gMHgzMjNiOwogIHQuaWRlb2dyYXBoaWNzdW5wYXJlbiA9IDB4MzIzMDsKICB0LmlkZW9ncmFwaGljc3VwZXJ2aXNlcGFyZW4gPSAweDMyM2M7CiAgdC5pZGVvZ3JhcGhpY3dhdGVycGFyZW4gPSAweDMyMmM7CiAgdC5pZGVvZ3JhcGhpY3dvb2RwYXJlbiA9IDB4MzIyZDsKICB0LmlkZW9ncmFwaGljemVybyA9IDB4MzAwNzsKICB0LmlkZW9ncmFwaG1ldGFsY2lyY2xlID0gMHgzMjhlOwogIHQuaWRlb2dyYXBobW9vbmNpcmNsZSA9IDB4MzI4YTsKICB0LmlkZW9ncmFwaG5hbWVjaXJjbGUgPSAweDMyOTQ7CiAgdC5pZGVvZ3JhcGhzdW5jaXJjbGUgPSAweDMyOTA7CiAgdC5pZGVvZ3JhcGh3YXRlcmNpcmNsZSA9IDB4MzI4YzsKICB0LmlkZW9ncmFwaHdvb2RjaXJjbGUgPSAweDMyOGQ7CiAgdC5pZGV2YSA9IDB4MDkwNzsKICB0LmlkaWVyZXNpcyA9IDB4MDBlZjsKICB0LmlkaWVyZXNpc2FjdXRlID0gMHgxZTJmOwogIHQuaWRpZXJlc2lzY3lyaWxsaWMgPSAweDA0ZTU7CiAgdC5pZG90YmVsb3cgPSAweDFlY2I7CiAgdC5pZWJyZXZlY3lyaWxsaWMgPSAweDA0ZDc7CiAgdC5pZWN5cmlsbGljID0gMHgwNDM1OwogIHQuaWV1bmdhY2lyY2xla29yZWFuID0gMHgzMjc1OwogIHQuaWV1bmdhcGFyZW5rb3JlYW4gPSAweDMyMTU7CiAgdC5pZXVuZ2NpcmNsZWtvcmVhbiA9IDB4MzI2NzsKICB0LmlldW5na29yZWFuID0gMHgzMTQ3OwogIHQuaWV1bmdwYXJlbmtvcmVhbiA9IDB4MzIwNzsKICB0LmlncmF2ZSA9IDB4MDBlYzsKICB0LmlndWphcmF0aSA9IDB4MGE4NzsKICB0LmlndXJtdWtoaSA9IDB4MGEwNzsKICB0LmloaXJhZ2FuYSA9IDB4MzA0NDsKICB0Lmlob29rYWJvdmUgPSAweDFlYzk7CiAgdC5paWJlbmdhbGkgPSAweDA5ODg7CiAgdC5paWN5cmlsbGljID0gMHgwNDM4OwogIHQuaWlkZXZhID0gMHgwOTA4OwogIHQuaWlndWphcmF0aSA9IDB4MGE4ODsKICB0LmlpZ3VybXVraGkgPSAweDBhMDg7CiAgdC5paW1hdHJhZ3VybXVraGkgPSAweDBhNDA7CiAgdC5paW52ZXJ0ZWRicmV2ZSA9IDB4MDIwYjsKICB0Lmlpc2hvcnRjeXJpbGxpYyA9IDB4MDQzOTsKICB0Lmlpdm93ZWxzaWduYmVuZ2FsaSA9IDB4MDljMDsKICB0Lmlpdm93ZWxzaWduZGV2YSA9IDB4MDk0MDsKICB0Lmlpdm93ZWxzaWduZ3VqYXJhdGkgPSAweDBhYzA7CiAgdC5paiA9IDB4MDEzMzsKICB0LmlrYXRha2FuYSA9IDB4MzBhNDsKICB0LmlrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY3MjsKICB0Lmlrb3JlYW4gPSAweDMxNjM7CiAgdC5pbGRlID0gMHgwMmRjOwogIHQuaWx1eWhlYnJldyA9IDB4MDVhYzsKICB0LmltYWNyb24gPSAweDAxMmI7CiAgdC5pbWFjcm9uY3lyaWxsaWMgPSAweDA0ZTM7CiAgdC5pbWFnZW9yYXBwcm94aW1hdGVseWVxdWFsID0gMHgyMjUzOwogIHQuaW1hdHJhZ3VybXVraGkgPSAweDBhM2Y7CiAgdC5pbW9ub3NwYWNlID0gMHhmZjQ5OwogIHQuaW5jcmVtZW50ID0gMHgyMjA2OwogIHQuaW5maW5pdHkgPSAweDIyMWU7CiAgdC5pbmlhcm1lbmlhbiA9IDB4MDU2YjsKICB0LmludGVncmFsID0gMHgyMjJiOwogIHQuaW50ZWdyYWxib3R0b20gPSAweDIzMjE7CiAgdC5pbnRlZ3JhbGJ0ID0gMHgyMzIxOwogIHQuaW50ZWdyYWxleCA9IDB4ZjhmNTsKICB0LmludGVncmFsdG9wID0gMHgyMzIwOwogIHQuaW50ZWdyYWx0cCA9IDB4MjMyMDsKICB0LmludGVyc2VjdGlvbiA9IDB4MjIyOTsKICB0LmludGlzcXVhcmUgPSAweDMzMDU7CiAgdC5pbnZidWxsZXQgPSAweDI1ZDg7CiAgdC5pbnZjaXJjbGUgPSAweDI1ZDk7CiAgdC5pbnZzbWlsZWZhY2UgPSAweDI2M2I7CiAgdC5pb2N5cmlsbGljID0gMHgwNDUxOwogIHQuaW9nb25layA9IDB4MDEyZjsKICB0LmlvdGEgPSAweDAzYjk7CiAgdC5pb3RhZGllcmVzaXMgPSAweDAzY2E7CiAgdC5pb3RhZGllcmVzaXN0b25vcyA9IDB4MDM5MDsKICB0LmlvdGFsYXRpbiA9IDB4MDI2OTsKICB0LmlvdGF0b25vcyA9IDB4MDNhZjsKICB0LmlwYXJlbiA9IDB4MjRhNDsKICB0LmlyaWd1cm11a2hpID0gMHgwYTcyOwogIHQuaXNtYWxsaGlyYWdhbmEgPSAweDMwNDM7CiAgdC5pc21hbGxrYXRha2FuYSA9IDB4MzBhMzsKICB0LmlzbWFsbGthdGFrYW5haGFsZndpZHRoID0gMHhmZjY4OwogIHQuaXNzaGFyYmVuZ2FsaSA9IDB4MDlmYTsKICB0LmlzdHJva2UgPSAweDAyNjg7CiAgdC5pc3VwZXJpb3IgPSAweGY2ZWQ7CiAgdC5pdGVyYXRpb25oaXJhZ2FuYSA9IDB4MzA5ZDsKICB0Lml0ZXJhdGlvbmthdGFrYW5hID0gMHgzMGZkOwogIHQuaXRpbGRlID0gMHgwMTI5OwogIHQuaXRpbGRlYmVsb3cgPSAweDFlMmQ7CiAgdC5pdWJvcG9tb2ZvID0gMHgzMTI5OwogIHQuaXVjeXJpbGxpYyA9IDB4MDQ0ZTsKICB0Lml2b3dlbHNpZ25iZW5nYWxpID0gMHgwOWJmOwogIHQuaXZvd2Vsc2lnbmRldmEgPSAweDA5M2Y7CiAgdC5pdm93ZWxzaWduZ3VqYXJhdGkgPSAweDBhYmY7CiAgdC5pemhpdHNhY3lyaWxsaWMgPSAweDA0NzU7CiAgdC5pemhpdHNhZGJsZ3JhdmVjeXJpbGxpYyA9IDB4MDQ3NzsKICB0LmogPSAweDAwNmE7CiAgdC5qYWFybWVuaWFuID0gMHgwNTcxOwogIHQuamFiZW5nYWxpID0gMHgwOTljOwogIHQuamFkZXZhID0gMHgwOTFjOwogIHQuamFndWphcmF0aSA9IDB4MGE5YzsKICB0LmphZ3VybXVraGkgPSAweDBhMWM7CiAgdC5qYm9wb21vZm8gPSAweDMxMTA7CiAgdC5qY2Fyb24gPSAweDAxZjA7CiAgdC5qY2lyY2xlID0gMHgyNGQ5OwogIHQuamNpcmN1bWZsZXggPSAweDAxMzU7CiAgdC5qY3Jvc3NlZHRhaWwgPSAweDAyOWQ7CiAgdC5qZG90bGVzc3N0cm9rZSA9IDB4MDI1ZjsKICB0LmplY3lyaWxsaWMgPSAweDA0NTg7CiAgdC5qZWVtYXJhYmljID0gMHgwNjJjOwogIHQuamVlbWZpbmFsYXJhYmljID0gMHhmZTllOwogIHQuamVlbWluaXRpYWxhcmFiaWMgPSAweGZlOWY7CiAgdC5qZWVtbWVkaWFsYXJhYmljID0gMHhmZWEwOwogIHQuamVoYXJhYmljID0gMHgwNjk4OwogIHQuamVoZmluYWxhcmFiaWMgPSAweGZiOGI7CiAgdC5qaGFiZW5nYWxpID0gMHgwOTlkOwogIHQuamhhZGV2YSA9IDB4MDkxZDsKICB0LmpoYWd1amFyYXRpID0gMHgwYTlkOwogIHQuamhhZ3VybXVraGkgPSAweDBhMWQ7CiAgdC5qaGVoYXJtZW5pYW4gPSAweDA1N2I7CiAgdC5qaXMgPSAweDMwMDQ7CiAgdC5qbW9ub3NwYWNlID0gMHhmZjRhOwogIHQuanBhcmVuID0gMHgyNGE1OwogIHQuanN1cGVyaW9yID0gMHgwMmIyOwogIHQuayA9IDB4MDA2YjsKICB0LmthYmFzaGtpcmN5cmlsbGljID0gMHgwNGExOwogIHQua2FiZW5nYWxpID0gMHgwOTk1OwogIHQua2FjdXRlID0gMHgxZTMxOwogIHQua2FjeXJpbGxpYyA9IDB4MDQzYTsKICB0LmthZGVzY2VuZGVyY3lyaWxsaWMgPSAweDA0OWI7CiAgdC5rYWRldmEgPSAweDA5MTU7CiAgdC5rYWYgPSAweDA1ZGI7CiAgdC5rYWZhcmFiaWMgPSAweDA2NDM7CiAgdC5rYWZkYWdlc2ggPSAweGZiM2I7CiAgdC5rYWZkYWdlc2hoZWJyZXcgPSAweGZiM2I7CiAgdC5rYWZmaW5hbGFyYWJpYyA9IDB4ZmVkYTsKICB0LmthZmhlYnJldyA9IDB4MDVkYjsKICB0LmthZmluaXRpYWxhcmFiaWMgPSAweGZlZGI7CiAgdC5rYWZtZWRpYWxhcmFiaWMgPSAweGZlZGM7CiAgdC5rYWZyYWZlaGVicmV3ID0gMHhmYjRkOwogIHQua2FndWphcmF0aSA9IDB4MGE5NTsKICB0LmthZ3VybXVraGkgPSAweDBhMTU7CiAgdC5rYWhpcmFnYW5hID0gMHgzMDRiOwogIHQua2Fob29rY3lyaWxsaWMgPSAweDA0YzQ7CiAgdC5rYWthdGFrYW5hID0gMHgzMGFiOwogIHQua2FrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY3NjsKICB0LmthcHBhID0gMHgwM2JhOwogIHQua2FwcGFzeW1ib2xncmVlayA9IDB4MDNmMDsKICB0LmthcHllb3VubWlldW1rb3JlYW4gPSAweDMxNzE7CiAgdC5rYXB5ZW91bnBoaWV1cGhrb3JlYW4gPSAweDMxODQ7CiAgdC5rYXB5ZW91bnBpZXVwa29yZWFuID0gMHgzMTc4OwogIHQua2FweWVvdW5zc2FuZ3BpZXVwa29yZWFuID0gMHgzMTc5OwogIHQua2Fyb3JpaXNxdWFyZSA9IDB4MzMwZDsKICB0Lmthc2hpZGFhdXRvYXJhYmljID0gMHgwNjQwOwogIHQua2FzaGlkYWF1dG9ub3NpZGViZWFyaW5nYXJhYmljID0gMHgwNjQwOwogIHQua2FzbWFsbGthdGFrYW5hID0gMHgzMGY1OwogIHQua2FzcXVhcmUgPSAweDMzODQ7CiAgdC5rYXNyYWFyYWJpYyA9IDB4MDY1MDsKICB0Lmthc3JhdGFuYXJhYmljID0gMHgwNjRkOwogIHQua2FzdHJva2VjeXJpbGxpYyA9IDB4MDQ5ZjsKICB0LmthdGFoaXJhcHJvbG9uZ21hcmtoYWxmd2lkdGggPSAweGZmNzA7CiAgdC5rYXZlcnRpY2Fsc3Ryb2tlY3lyaWxsaWMgPSAweDA0OWQ7CiAgdC5rYm9wb21vZm8gPSAweDMxMGU7CiAgdC5rY2Fsc3F1YXJlID0gMHgzMzg5OwogIHQua2Nhcm9uID0gMHgwMWU5OwogIHQua2NlZGlsbGEgPSAweDAxMzc7CiAgdC5rY2lyY2xlID0gMHgyNGRhOwogIHQua2NvbW1hYWNjZW50ID0gMHgwMTM3OwogIHQua2RvdGJlbG93ID0gMHgxZTMzOwogIHQua2VoYXJtZW5pYW4gPSAweDA1ODQ7CiAgdC5rZWhpcmFnYW5hID0gMHgzMDUxOwogIHQua2VrYXRha2FuYSA9IDB4MzBiMTsKICB0Lmtla2F0YWthbmFoYWxmd2lkdGggPSAweGZmNzk7CiAgdC5rZW5hcm1lbmlhbiA9IDB4MDU2ZjsKICB0Lmtlc21hbGxrYXRha2FuYSA9IDB4MzBmNjsKICB0LmtncmVlbmxhbmRpYyA9IDB4MDEzODsKICB0LmtoYWJlbmdhbGkgPSAweDA5OTY7CiAgdC5raGFjeXJpbGxpYyA9IDB4MDQ0NTsKICB0LmtoYWRldmEgPSAweDA5MTY7CiAgdC5raGFndWphcmF0aSA9IDB4MGE5NjsKICB0LmtoYWd1cm11a2hpID0gMHgwYTE2OwogIHQua2hhaGFyYWJpYyA9IDB4MDYyZTsKICB0LmtoYWhmaW5hbGFyYWJpYyA9IDB4ZmVhNjsKICB0LmtoYWhpbml0aWFsYXJhYmljID0gMHhmZWE3OwogIHQua2hhaG1lZGlhbGFyYWJpYyA9IDB4ZmVhODsKICB0LmtoZWljb3B0aWMgPSAweDAzZTc7CiAgdC5raGhhZGV2YSA9IDB4MDk1OTsKICB0LmtoaGFndXJtdWtoaSA9IDB4MGE1OTsKICB0LmtoaWV1a2hhY2lyY2xla29yZWFuID0gMHgzMjc4OwogIHQua2hpZXVraGFwYXJlbmtvcmVhbiA9IDB4MzIxODsKICB0LmtoaWV1a2hjaXJjbGVrb3JlYW4gPSAweDMyNmE7CiAgdC5raGlldWtoa29yZWFuID0gMHgzMTRiOwogIHQua2hpZXVraHBhcmVua29yZWFuID0gMHgzMjBhOwogIHQua2hva2hhaXRoYWkgPSAweDBlMDI7CiAgdC5raG9raG9udGhhaSA9IDB4MGUwNTsKICB0Lmtob2todWF0dGhhaSA9IDB4MGUwMzsKICB0Lmtob2tod2FpdGhhaSA9IDB4MGUwNDsKICB0Lmtob211dHRoYWkgPSAweDBlNWI7CiAgdC5raG9vayA9IDB4MDE5OTsKICB0Lmtob3Jha2hhbmd0aGFpID0gMHgwZTA2OwogIHQua2h6c3F1YXJlID0gMHgzMzkxOwogIHQua2loaXJhZ2FuYSA9IDB4MzA0ZDsKICB0Lmtpa2F0YWthbmEgPSAweDMwYWQ7CiAgdC5raWthdGFrYW5haGFsZndpZHRoID0gMHhmZjc3OwogIHQua2lyb2d1cmFtdXNxdWFyZSA9IDB4MzMxNTsKICB0Lmtpcm9tZWV0b3J1c3F1YXJlID0gMHgzMzE2OwogIHQua2lyb3NxdWFyZSA9IDB4MzMxNDsKICB0LmtpeWVva2FjaXJjbGVrb3JlYW4gPSAweDMyNmU7CiAgdC5raXllb2thcGFyZW5rb3JlYW4gPSAweDMyMGU7CiAgdC5raXllb2tjaXJjbGVrb3JlYW4gPSAweDMyNjA7CiAgdC5raXllb2trb3JlYW4gPSAweDMxMzE7CiAgdC5raXllb2twYXJlbmtvcmVhbiA9IDB4MzIwMDsKICB0LmtpeWVva3Npb3Nrb3JlYW4gPSAweDMxMzM7CiAgdC5ramVjeXJpbGxpYyA9IDB4MDQ1YzsKICB0LmtsaW5lYmVsb3cgPSAweDFlMzU7CiAgdC5rbHNxdWFyZSA9IDB4MzM5ODsKICB0LmttY3ViZWRzcXVhcmUgPSAweDMzYTY7CiAgdC5rbW9ub3NwYWNlID0gMHhmZjRiOwogIHQua21zcXVhcmVkc3F1YXJlID0gMHgzM2EyOwogIHQua29oaXJhZ2FuYSA9IDB4MzA1MzsKICB0LmtvaG1zcXVhcmUgPSAweDMzYzA7CiAgdC5rb2thaXRoYWkgPSAweDBlMDE7CiAgdC5rb2thdGFrYW5hID0gMHgzMGIzOwogIHQua29rYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY3YTsKICB0Lmtvb3Bvc3F1YXJlID0gMHgzMzFlOwogIHQua29wcGFjeXJpbGxpYyA9IDB4MDQ4MTsKICB0LmtvcmVhbnN0YW5kYXJkc3ltYm9sID0gMHgzMjdmOwogIHQua29yb25pc2NtYiA9IDB4MDM0MzsKICB0LmtwYXJlbiA9IDB4MjRhNjsKICB0LmtwYXNxdWFyZSA9IDB4MzNhYTsKICB0LmtzaWN5cmlsbGljID0gMHgwNDZmOwogIHQua3RzcXVhcmUgPSAweDMzY2Y7CiAgdC5rdHVybmVkID0gMHgwMjllOwogIHQua3VoaXJhZ2FuYSA9IDB4MzA0ZjsKICB0Lmt1a2F0YWthbmEgPSAweDMwYWY7CiAgdC5rdWthdGFrYW5haGFsZndpZHRoID0gMHhmZjc4OwogIHQua3ZzcXVhcmUgPSAweDMzYjg7CiAgdC5rd3NxdWFyZSA9IDB4MzNiZTsKICB0LmwgPSAweDAwNmM7CiAgdC5sYWJlbmdhbGkgPSAweDA5YjI7CiAgdC5sYWN1dGUgPSAweDAxM2E7CiAgdC5sYWRldmEgPSAweDA5MzI7CiAgdC5sYWd1amFyYXRpID0gMHgwYWIyOwogIHQubGFndXJtdWtoaSA9IDB4MGEzMjsKICB0Lmxha2toYW5neWFvdGhhaSA9IDB4MGU0NTsKICB0LmxhbWFsZWZmaW5hbGFyYWJpYyA9IDB4ZmVmYzsKICB0LmxhbWFsZWZoYW16YWFib3ZlZmluYWxhcmFiaWMgPSAweGZlZjg7CiAgdC5sYW1hbGVmaGFtemFhYm92ZWlzb2xhdGVkYXJhYmljID0gMHhmZWY3OwogIHQubGFtYWxlZmhhbXphYmVsb3dmaW5hbGFyYWJpYyA9IDB4ZmVmYTsKICB0LmxhbWFsZWZoYW16YWJlbG93aXNvbGF0ZWRhcmFiaWMgPSAweGZlZjk7CiAgdC5sYW1hbGVmaXNvbGF0ZWRhcmFiaWMgPSAweGZlZmI7CiAgdC5sYW1hbGVmbWFkZGFhYm92ZWZpbmFsYXJhYmljID0gMHhmZWY2OwogIHQubGFtYWxlZm1hZGRhYWJvdmVpc29sYXRlZGFyYWJpYyA9IDB4ZmVmNTsKICB0LmxhbWFyYWJpYyA9IDB4MDY0NDsKICB0LmxhbWJkYSA9IDB4MDNiYjsKICB0LmxhbWJkYXN0cm9rZSA9IDB4MDE5YjsKICB0LmxhbWVkID0gMHgwNWRjOwogIHQubGFtZWRkYWdlc2ggPSAweGZiM2M7CiAgdC5sYW1lZGRhZ2VzaGhlYnJldyA9IDB4ZmIzYzsKICB0LmxhbWVkaGVicmV3ID0gMHgwNWRjOwogIHQubGFtZmluYWxhcmFiaWMgPSAweGZlZGU7CiAgdC5sYW1oYWhpbml0aWFsYXJhYmljID0gMHhmY2NhOwogIHQubGFtaW5pdGlhbGFyYWJpYyA9IDB4ZmVkZjsKICB0LmxhbWplZW1pbml0aWFsYXJhYmljID0gMHhmY2M5OwogIHQubGFta2hhaGluaXRpYWxhcmFiaWMgPSAweGZjY2I7CiAgdC5sYW1sYW1oZWhpc29sYXRlZGFyYWJpYyA9IDB4ZmRmMjsKICB0LmxhbW1lZGlhbGFyYWJpYyA9IDB4ZmVlMDsKICB0LmxhbW1lZW1oYWhpbml0aWFsYXJhYmljID0gMHhmZDg4OwogIHQubGFtbWVlbWluaXRpYWxhcmFiaWMgPSAweGZjY2M7CiAgdC5sYXJnZWNpcmNsZSA9IDB4MjVlZjsKICB0LmxiYXIgPSAweDAxOWE7CiAgdC5sYmVsdCA9IDB4MDI2YzsKICB0Lmxib3BvbW9mbyA9IDB4MzEwYzsKICB0LmxjYXJvbiA9IDB4MDEzZTsKICB0LmxjZWRpbGxhID0gMHgwMTNjOwogIHQubGNpcmNsZSA9IDB4MjRkYjsKICB0LmxjaXJjdW1mbGV4YmVsb3cgPSAweDFlM2Q7CiAgdC5sY29tbWFhY2NlbnQgPSAweDAxM2M7CiAgdC5sZG90ID0gMHgwMTQwOwogIHQubGRvdGFjY2VudCA9IDB4MDE0MDsKICB0Lmxkb3RiZWxvdyA9IDB4MWUzNzsKICB0Lmxkb3RiZWxvd21hY3JvbiA9IDB4MWUzOTsKICB0LmxlZnRhbmdsZWFib3ZlY21iID0gMHgwMzFhOwogIHQubGVmdHRhY2tiZWxvd2NtYiA9IDB4MDMxODsKICB0Lmxlc3MgPSAweDAwM2M7CiAgdC5sZXNzZXF1YWwgPSAweDIyNjQ7CiAgdC5sZXNzZXF1YWxvcmdyZWF0ZXIgPSAweDIyZGE7CiAgdC5sZXNzbW9ub3NwYWNlID0gMHhmZjFjOwogIHQubGVzc29yZXF1aXZhbGVudCA9IDB4MjI3MjsKICB0Lmxlc3NvcmdyZWF0ZXIgPSAweDIyNzY7CiAgdC5sZXNzb3ZlcmVxdWFsID0gMHgyMjY2OwogIHQubGVzc3NtYWxsID0gMHhmZTY0OwogIHQubGV6aCA9IDB4MDI2ZTsKICB0LmxmYmxvY2sgPSAweDI1OGM7CiAgdC5saG9va3JldHJvZmxleCA9IDB4MDI2ZDsKICB0LmxpcmEgPSAweDIwYTQ7CiAgdC5saXduYXJtZW5pYW4gPSAweDA1NmM7CiAgdC5saiA9IDB4MDFjOTsKICB0LmxqZWN5cmlsbGljID0gMHgwNDU5OwogIHQubGwgPSAweGY2YzA7CiAgdC5sbGFkZXZhID0gMHgwOTMzOwogIHQubGxhZ3VqYXJhdGkgPSAweDBhYjM7CiAgdC5sbGluZWJlbG93ID0gMHgxZTNiOwogIHQubGxsYWRldmEgPSAweDA5MzQ7CiAgdC5sbHZvY2FsaWNiZW5nYWxpID0gMHgwOWUxOwogIHQubGx2b2NhbGljZGV2YSA9IDB4MDk2MTsKICB0Lmxsdm9jYWxpY3Zvd2Vsc2lnbmJlbmdhbGkgPSAweDA5ZTM7CiAgdC5sbHZvY2FsaWN2b3dlbHNpZ25kZXZhID0gMHgwOTYzOwogIHQubG1pZGRsZXRpbGRlID0gMHgwMjZiOwogIHQubG1vbm9zcGFjZSA9IDB4ZmY0YzsKICB0Lmxtc3F1YXJlID0gMHgzM2QwOwogIHQubG9jaHVsYXRoYWkgPSAweDBlMmM7CiAgdC5sb2dpY2FsYW5kID0gMHgyMjI3OwogIHQubG9naWNhbG5vdCA9IDB4MDBhYzsKICB0LmxvZ2ljYWxub3RyZXZlcnNlZCA9IDB4MjMxMDsKICB0LmxvZ2ljYWxvciA9IDB4MjIyODsKICB0LmxvbGluZ3RoYWkgPSAweDBlMjU7CiAgdC5sb25ncyA9IDB4MDE3ZjsKICB0Lmxvd2xpbmVjZW50ZXJsaW5lID0gMHhmZTRlOwogIHQubG93bGluZWNtYiA9IDB4MDMzMjsKICB0Lmxvd2xpbmVkYXNoZWQgPSAweGZlNGQ7CiAgdC5sb3plbmdlID0gMHgyNWNhOwogIHQubHBhcmVuID0gMHgyNGE3OwogIHQubHNsYXNoID0gMHgwMTQyOwogIHQubHNxdWFyZSA9IDB4MjExMzsKICB0LmxzdXBlcmlvciA9IDB4ZjZlZTsKICB0Lmx0c2hhZGUgPSAweDI1OTE7CiAgdC5sdXRoYWkgPSAweDBlMjY7CiAgdC5sdm9jYWxpY2JlbmdhbGkgPSAweDA5OGM7CiAgdC5sdm9jYWxpY2RldmEgPSAweDA5MGM7CiAgdC5sdm9jYWxpY3Zvd2Vsc2lnbmJlbmdhbGkgPSAweDA5ZTI7CiAgdC5sdm9jYWxpY3Zvd2Vsc2lnbmRldmEgPSAweDA5NjI7CiAgdC5seHNxdWFyZSA9IDB4MzNkMzsKICB0Lm0gPSAweDAwNmQ7CiAgdC5tYWJlbmdhbGkgPSAweDA5YWU7CiAgdC5tYWNyb24gPSAweDAwYWY7CiAgdC5tYWNyb25iZWxvd2NtYiA9IDB4MDMzMTsKICB0Lm1hY3JvbmNtYiA9IDB4MDMwNDsKICB0Lm1hY3Jvbmxvd21vZCA9IDB4MDJjZDsKICB0Lm1hY3Jvbm1vbm9zcGFjZSA9IDB4ZmZlMzsKICB0Lm1hY3V0ZSA9IDB4MWUzZjsKICB0Lm1hZGV2YSA9IDB4MDkyZTsKICB0Lm1hZ3VqYXJhdGkgPSAweDBhYWU7CiAgdC5tYWd1cm11a2hpID0gMHgwYTJlOwogIHQubWFoYXBha2hoZWJyZXcgPSAweDA1YTQ7CiAgdC5tYWhhcGFraGxlZnRoZWJyZXcgPSAweDA1YTQ7CiAgdC5tYWhpcmFnYW5hID0gMHgzMDdlOwogIHQubWFpY2hhdHRhd2Fsb3dsZWZ0dGhhaSA9IDB4Zjg5NTsKICB0Lm1haWNoYXR0YXdhbG93cmlnaHR0aGFpID0gMHhmODk0OwogIHQubWFpY2hhdHRhd2F0aGFpID0gMHgwZTRiOwogIHQubWFpY2hhdHRhd2F1cHBlcmxlZnR0aGFpID0gMHhmODkzOwogIHQubWFpZWtsb3dsZWZ0dGhhaSA9IDB4Zjg4YzsKICB0Lm1haWVrbG93cmlnaHR0aGFpID0gMHhmODhiOwogIHQubWFpZWt0aGFpID0gMHgwZTQ4OwogIHQubWFpZWt1cHBlcmxlZnR0aGFpID0gMHhmODhhOwogIHQubWFpaGFuYWthdGxlZnR0aGFpID0gMHhmODg0OwogIHQubWFpaGFuYWthdHRoYWkgPSAweDBlMzE7CiAgdC5tYWl0YWlraHVsZWZ0dGhhaSA9IDB4Zjg4OTsKICB0Lm1haXRhaWtodXRoYWkgPSAweDBlNDc7CiAgdC5tYWl0aG9sb3dsZWZ0dGhhaSA9IDB4Zjg4ZjsKICB0Lm1haXRob2xvd3JpZ2h0dGhhaSA9IDB4Zjg4ZTsKICB0Lm1haXRob3RoYWkgPSAweDBlNDk7CiAgdC5tYWl0aG91cHBlcmxlZnR0aGFpID0gMHhmODhkOwogIHQubWFpdHJpbG93bGVmdHRoYWkgPSAweGY4OTI7CiAgdC5tYWl0cmlsb3dyaWdodHRoYWkgPSAweGY4OTE7CiAgdC5tYWl0cml0aGFpID0gMHgwZTRhOwogIHQubWFpdHJpdXBwZXJsZWZ0dGhhaSA9IDB4Zjg5MDsKICB0Lm1haXlhbW9rdGhhaSA9IDB4MGU0NjsKICB0Lm1ha2F0YWthbmEgPSAweDMwZGU7CiAgdC5tYWthdGFrYW5haGFsZndpZHRoID0gMHhmZjhmOwogIHQubWFsZSA9IDB4MjY0MjsKICB0Lm1hbnN5b25zcXVhcmUgPSAweDMzNDc7CiAgdC5tYXFhZmhlYnJldyA9IDB4MDViZTsKICB0Lm1hcnMgPSAweDI2NDI7CiAgdC5tYXNvcmFjaXJjbGVoZWJyZXcgPSAweDA1YWY7CiAgdC5tYXNxdWFyZSA9IDB4MzM4MzsKICB0Lm1ib3BvbW9mbyA9IDB4MzEwNzsKICB0Lm1ic3F1YXJlID0gMHgzM2Q0OwogIHQubWNpcmNsZSA9IDB4MjRkYzsKICB0Lm1jdWJlZHNxdWFyZSA9IDB4MzNhNTsKICB0Lm1kb3RhY2NlbnQgPSAweDFlNDE7CiAgdC5tZG90YmVsb3cgPSAweDFlNDM7CiAgdC5tZWVtYXJhYmljID0gMHgwNjQ1OwogIHQubWVlbWZpbmFsYXJhYmljID0gMHhmZWUyOwogIHQubWVlbWluaXRpYWxhcmFiaWMgPSAweGZlZTM7CiAgdC5tZWVtbWVkaWFsYXJhYmljID0gMHhmZWU0OwogIHQubWVlbW1lZW1pbml0aWFsYXJhYmljID0gMHhmY2QxOwogIHQubWVlbW1lZW1pc29sYXRlZGFyYWJpYyA9IDB4ZmM0ODsKICB0Lm1lZXRvcnVzcXVhcmUgPSAweDMzNGQ7CiAgdC5tZWhpcmFnYW5hID0gMHgzMDgxOwogIHQubWVpemllcmFzcXVhcmUgPSAweDMzN2U7CiAgdC5tZWthdGFrYW5hID0gMHgzMGUxOwogIHQubWVrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY5MjsKICB0Lm1lbSA9IDB4MDVkZTsKICB0Lm1lbWRhZ2VzaCA9IDB4ZmIzZTsKICB0Lm1lbWRhZ2VzaGhlYnJldyA9IDB4ZmIzZTsKICB0Lm1lbWhlYnJldyA9IDB4MDVkZTsKICB0Lm1lbmFybWVuaWFuID0gMHgwNTc0OwogIHQubWVya2hhaGVicmV3ID0gMHgwNWE1OwogIHQubWVya2hha2VmdWxhaGVicmV3ID0gMHgwNWE2OwogIHQubWVya2hha2VmdWxhbGVmdGhlYnJldyA9IDB4MDVhNjsKICB0Lm1lcmtoYWxlZnRoZWJyZXcgPSAweDA1YTU7CiAgdC5taG9vayA9IDB4MDI3MTsKICB0Lm1oenNxdWFyZSA9IDB4MzM5MjsKICB0Lm1pZGRsZWRvdGthdGFrYW5haGFsZndpZHRoID0gMHhmZjY1OwogIHQubWlkZG90ID0gMHgwMGI3OwogIHQubWlldW1hY2lyY2xla29yZWFuID0gMHgzMjcyOwogIHQubWlldW1hcGFyZW5rb3JlYW4gPSAweDMyMTI7CiAgdC5taWV1bWNpcmNsZWtvcmVhbiA9IDB4MzI2NDsKICB0Lm1pZXVta29yZWFuID0gMHgzMTQxOwogIHQubWlldW1wYW5zaW9za29yZWFuID0gMHgzMTcwOwogIHQubWlldW1wYXJlbmtvcmVhbiA9IDB4MzIwNDsKICB0Lm1pZXVtcGlldXBrb3JlYW4gPSAweDMxNmU7CiAgdC5taWV1bXNpb3Nrb3JlYW4gPSAweDMxNmY7CiAgdC5taWhpcmFnYW5hID0gMHgzMDdmOwogIHQubWlrYXRha2FuYSA9IDB4MzBkZjsKICB0Lm1pa2F0YWthbmFoYWxmd2lkdGggPSAweGZmOTA7CiAgdC5taW51cyA9IDB4MjIxMjsKICB0Lm1pbnVzYmVsb3djbWIgPSAweDAzMjA7CiAgdC5taW51c2NpcmNsZSA9IDB4MjI5NjsKICB0Lm1pbnVzbW9kID0gMHgwMmQ3OwogIHQubWludXNwbHVzID0gMHgyMjEzOwogIHQubWludXRlID0gMHgyMDMyOwogIHQubWlyaWJhYXJ1c3F1YXJlID0gMHgzMzRhOwogIHQubWlyaXNxdWFyZSA9IDB4MzM0OTsKICB0Lm1sb25nbGVndHVybmVkID0gMHgwMjcwOwogIHQubWxzcXVhcmUgPSAweDMzOTY7CiAgdC5tbWN1YmVkc3F1YXJlID0gMHgzM2EzOwogIHQubW1vbm9zcGFjZSA9IDB4ZmY0ZDsKICB0Lm1tc3F1YXJlZHNxdWFyZSA9IDB4MzM5ZjsKICB0Lm1vaGlyYWdhbmEgPSAweDMwODI7CiAgdC5tb2htc3F1YXJlID0gMHgzM2MxOwogIHQubW9rYXRha2FuYSA9IDB4MzBlMjsKICB0Lm1va2F0YWthbmFoYWxmd2lkdGggPSAweGZmOTM7CiAgdC5tb2xzcXVhcmUgPSAweDMzZDY7CiAgdC5tb21hdGhhaSA9IDB4MGUyMTsKICB0Lm1vdmVyc3NxdWFyZSA9IDB4MzNhNzsKICB0Lm1vdmVyc3NxdWFyZWRzcXVhcmUgPSAweDMzYTg7CiAgdC5tcGFyZW4gPSAweDI0YTg7CiAgdC5tcGFzcXVhcmUgPSAweDMzYWI7CiAgdC5tc3NxdWFyZSA9IDB4MzNiMzsKICB0Lm1zdXBlcmlvciA9IDB4ZjZlZjsKICB0Lm10dXJuZWQgPSAweDAyNmY7CiAgdC5tdSA9IDB4MDBiNTsKICB0Lm11MSA9IDB4MDBiNTsKICB0Lm11YXNxdWFyZSA9IDB4MzM4MjsKICB0Lm11Y2hncmVhdGVyID0gMHgyMjZiOwogIHQubXVjaGxlc3MgPSAweDIyNmE7CiAgdC5tdWZzcXVhcmUgPSAweDMzOGM7CiAgdC5tdWdyZWVrID0gMHgwM2JjOwogIHQubXVnc3F1YXJlID0gMHgzMzhkOwogIHQubXVoaXJhZ2FuYSA9IDB4MzA4MDsKICB0Lm11a2F0YWthbmEgPSAweDMwZTA7CiAgdC5tdWthdGFrYW5haGFsZndpZHRoID0gMHhmZjkxOwogIHQubXVsc3F1YXJlID0gMHgzMzk1OwogIHQubXVsdGlwbHkgPSAweDAwZDc7CiAgdC5tdW1zcXVhcmUgPSAweDMzOWI7CiAgdC5tdW5haGhlYnJldyA9IDB4MDVhMzsKICB0Lm11bmFobGVmdGhlYnJldyA9IDB4MDVhMzsKICB0Lm11c2ljYWxub3RlID0gMHgyNjZhOwogIHQubXVzaWNhbG5vdGVkYmwgPSAweDI2NmI7CiAgdC5tdXNpY2ZsYXRzaWduID0gMHgyNjZkOwogIHQubXVzaWNzaGFycHNpZ24gPSAweDI2NmY7CiAgdC5tdXNzcXVhcmUgPSAweDMzYjI7CiAgdC5tdXZzcXVhcmUgPSAweDMzYjY7CiAgdC5tdXdzcXVhcmUgPSAweDMzYmM7CiAgdC5tdm1lZ2FzcXVhcmUgPSAweDMzYjk7CiAgdC5tdnNxdWFyZSA9IDB4MzNiNzsKICB0Lm13bWVnYXNxdWFyZSA9IDB4MzNiZjsKICB0Lm13c3F1YXJlID0gMHgzM2JkOwogIHQubiA9IDB4MDA2ZTsKICB0Lm5hYmVuZ2FsaSA9IDB4MDlhODsKICB0Lm5hYmxhID0gMHgyMjA3OwogIHQubmFjdXRlID0gMHgwMTQ0OwogIHQubmFkZXZhID0gMHgwOTI4OwogIHQubmFndWphcmF0aSA9IDB4MGFhODsKICB0Lm5hZ3VybXVraGkgPSAweDBhMjg7CiAgdC5uYWhpcmFnYW5hID0gMHgzMDZhOwogIHQubmFrYXRha2FuYSA9IDB4MzBjYTsKICB0Lm5ha2F0YWthbmFoYWxmd2lkdGggPSAweGZmODU7CiAgdC5uYXBvc3Ryb3BoZSA9IDB4MDE0OTsKICB0Lm5hc3F1YXJlID0gMHgzMzgxOwogIHQubmJvcG9tb2ZvID0gMHgzMTBiOwogIHQubmJzcGFjZSA9IDB4MDBhMDsKICB0Lm5jYXJvbiA9IDB4MDE0ODsKICB0Lm5jZWRpbGxhID0gMHgwMTQ2OwogIHQubmNpcmNsZSA9IDB4MjRkZDsKICB0Lm5jaXJjdW1mbGV4YmVsb3cgPSAweDFlNGI7CiAgdC5uY29tbWFhY2NlbnQgPSAweDAxNDY7CiAgdC5uZG90YWNjZW50ID0gMHgxZTQ1OwogIHQubmRvdGJlbG93ID0gMHgxZTQ3OwogIHQubmVoaXJhZ2FuYSA9IDB4MzA2ZDsKICB0Lm5la2F0YWthbmEgPSAweDMwY2Q7CiAgdC5uZWthdGFrYW5haGFsZndpZHRoID0gMHhmZjg4OwogIHQubmV3c2hlcWVsc2lnbiA9IDB4MjBhYTsKICB0Lm5mc3F1YXJlID0gMHgzMzhiOwogIHQubmdhYmVuZ2FsaSA9IDB4MDk5OTsKICB0Lm5nYWRldmEgPSAweDA5MTk7CiAgdC5uZ2FndWphcmF0aSA9IDB4MGE5OTsKICB0Lm5nYWd1cm11a2hpID0gMHgwYTE5OwogIHQubmdvbmd1dGhhaSA9IDB4MGUwNzsKICB0Lm5oaXJhZ2FuYSA9IDB4MzA5MzsKICB0Lm5ob29rbGVmdCA9IDB4MDI3MjsKICB0Lm5ob29rcmV0cm9mbGV4ID0gMHgwMjczOwogIHQubmlldW5hY2lyY2xla29yZWFuID0gMHgzMjZmOwogIHQubmlldW5hcGFyZW5rb3JlYW4gPSAweDMyMGY7CiAgdC5uaWV1bmNpZXVja29yZWFuID0gMHgzMTM1OwogIHQubmlldW5jaXJjbGVrb3JlYW4gPSAweDMyNjE7CiAgdC5uaWV1bmhpZXVoa29yZWFuID0gMHgzMTM2OwogIHQubmlldW5rb3JlYW4gPSAweDMxMzQ7CiAgdC5uaWV1bnBhbnNpb3Nrb3JlYW4gPSAweDMxNjg7CiAgdC5uaWV1bnBhcmVua29yZWFuID0gMHgzMjAxOwogIHQubmlldW5zaW9za29yZWFuID0gMHgzMTY3OwogIHQubmlldW50aWtldXRrb3JlYW4gPSAweDMxNjY7CiAgdC5uaWhpcmFnYW5hID0gMHgzMDZiOwogIHQubmlrYXRha2FuYSA9IDB4MzBjYjsKICB0Lm5pa2F0YWthbmFoYWxmd2lkdGggPSAweGZmODY7CiAgdC5uaWtoYWhpdGxlZnR0aGFpID0gMHhmODk5OwogIHQubmlraGFoaXR0aGFpID0gMHgwZTRkOwogIHQubmluZSA9IDB4MDAzOTsKICB0Lm5pbmVhcmFiaWMgPSAweDA2Njk7CiAgdC5uaW5lYmVuZ2FsaSA9IDB4MDllZjsKICB0Lm5pbmVjaXJjbGUgPSAweDI0Njg7CiAgdC5uaW5lY2lyY2xlaW52ZXJzZXNhbnNzZXJpZiA9IDB4Mjc5MjsKICB0Lm5pbmVkZXZhID0gMHgwOTZmOwogIHQubmluZWd1amFyYXRpID0gMHgwYWVmOwogIHQubmluZWd1cm11a2hpID0gMHgwYTZmOwogIHQubmluZWhhY2thcmFiaWMgPSAweDA2Njk7CiAgdC5uaW5laGFuZ3pob3UgPSAweDMwMjk7CiAgdC5uaW5laWRlb2dyYXBoaWNwYXJlbiA9IDB4MzIyODsKICB0Lm5pbmVpbmZlcmlvciA9IDB4MjA4OTsKICB0Lm5pbmVtb25vc3BhY2UgPSAweGZmMTk7CiAgdC5uaW5lb2xkc3R5bGUgPSAweGY3Mzk7CiAgdC5uaW5lcGFyZW4gPSAweDI0N2M7CiAgdC5uaW5lcGVyaW9kID0gMHgyNDkwOwogIHQubmluZXBlcnNpYW4gPSAweDA2Zjk7CiAgdC5uaW5lcm9tYW4gPSAweDIxNzg7CiAgdC5uaW5lc3VwZXJpb3IgPSAweDIwNzk7CiAgdC5uaW5ldGVlbmNpcmNsZSA9IDB4MjQ3MjsKICB0Lm5pbmV0ZWVucGFyZW4gPSAweDI0ODY7CiAgdC5uaW5ldGVlbnBlcmlvZCA9IDB4MjQ5YTsKICB0Lm5pbmV0aGFpID0gMHgwZTU5OwogIHQubmogPSAweDAxY2M7CiAgdC5uamVjeXJpbGxpYyA9IDB4MDQ1YTsKICB0Lm5rYXRha2FuYSA9IDB4MzBmMzsKICB0Lm5rYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY5ZDsKICB0Lm5sZWdyaWdodGxvbmcgPSAweDAxOWU7CiAgdC5ubGluZWJlbG93ID0gMHgxZTQ5OwogIHQubm1vbm9zcGFjZSA9IDB4ZmY0ZTsKICB0Lm5tc3F1YXJlID0gMHgzMzlhOwogIHQubm5hYmVuZ2FsaSA9IDB4MDlhMzsKICB0Lm5uYWRldmEgPSAweDA5MjM7CiAgdC5ubmFndWphcmF0aSA9IDB4MGFhMzsKICB0Lm5uYWd1cm11a2hpID0gMHgwYTIzOwogIHQubm5uYWRldmEgPSAweDA5Mjk7CiAgdC5ub2hpcmFnYW5hID0gMHgzMDZlOwogIHQubm9rYXRha2FuYSA9IDB4MzBjZTsKICB0Lm5va2F0YWthbmFoYWxmd2lkdGggPSAweGZmODk7CiAgdC5ub25icmVha2luZ3NwYWNlID0gMHgwMGEwOwogIHQubm9uZW50aGFpID0gMHgwZTEzOwogIHQubm9udXRoYWkgPSAweDBlMTk7CiAgdC5ub29uYXJhYmljID0gMHgwNjQ2OwogIHQubm9vbmZpbmFsYXJhYmljID0gMHhmZWU2OwogIHQubm9vbmdodW5uYWFyYWJpYyA9IDB4MDZiYTsKICB0Lm5vb25naHVubmFmaW5hbGFyYWJpYyA9IDB4ZmI5ZjsKICB0Lm5vb25pbml0aWFsYXJhYmljID0gMHhmZWU3OwogIHQubm9vbmplZW1pbml0aWFsYXJhYmljID0gMHhmY2QyOwogIHQubm9vbmplZW1pc29sYXRlZGFyYWJpYyA9IDB4ZmM0YjsKICB0Lm5vb25tZWRpYWxhcmFiaWMgPSAweGZlZTg7CiAgdC5ub29ubWVlbWluaXRpYWxhcmFiaWMgPSAweGZjZDU7CiAgdC5ub29ubWVlbWlzb2xhdGVkYXJhYmljID0gMHhmYzRlOwogIHQubm9vbm5vb25maW5hbGFyYWJpYyA9IDB4ZmM4ZDsKICB0Lm5vdGNvbnRhaW5zID0gMHgyMjBjOwogIHQubm90ZWxlbWVudCA9IDB4MjIwOTsKICB0Lm5vdGVsZW1lbnRvZiA9IDB4MjIwOTsKICB0Lm5vdGVxdWFsID0gMHgyMjYwOwogIHQubm90Z3JlYXRlciA9IDB4MjI2ZjsKICB0Lm5vdGdyZWF0ZXJub3JlcXVhbCA9IDB4MjI3MTsKICB0Lm5vdGdyZWF0ZXJub3JsZXNzID0gMHgyMjc5OwogIHQubm90aWRlbnRpY2FsID0gMHgyMjYyOwogIHQubm90bGVzcyA9IDB4MjI2ZTsKICB0Lm5vdGxlc3Nub3JlcXVhbCA9IDB4MjI3MDsKICB0Lm5vdHBhcmFsbGVsID0gMHgyMjI2OwogIHQubm90cHJlY2VkZXMgPSAweDIyODA7CiAgdC5ub3RzdWJzZXQgPSAweDIyODQ7CiAgdC5ub3RzdWNjZWVkcyA9IDB4MjI4MTsKICB0Lm5vdHN1cGVyc2V0ID0gMHgyMjg1OwogIHQubm93YXJtZW5pYW4gPSAweDA1NzY7CiAgdC5ucGFyZW4gPSAweDI0YTk7CiAgdC5uc3NxdWFyZSA9IDB4MzNiMTsKICB0Lm5zdXBlcmlvciA9IDB4MjA3ZjsKICB0Lm50aWxkZSA9IDB4MDBmMTsKICB0Lm51ID0gMHgwM2JkOwogIHQubnVoaXJhZ2FuYSA9IDB4MzA2YzsKICB0Lm51a2F0YWthbmEgPSAweDMwY2M7CiAgdC5udWthdGFrYW5haGFsZndpZHRoID0gMHhmZjg3OwogIHQubnVrdGFiZW5nYWxpID0gMHgwOWJjOwogIHQubnVrdGFkZXZhID0gMHgwOTNjOwogIHQubnVrdGFndWphcmF0aSA9IDB4MGFiYzsKICB0Lm51a3RhZ3VybXVraGkgPSAweDBhM2M7CiAgdC5udW1iZXJzaWduID0gMHgwMDIzOwogIHQubnVtYmVyc2lnbm1vbm9zcGFjZSA9IDB4ZmYwMzsKICB0Lm51bWJlcnNpZ25zbWFsbCA9IDB4ZmU1ZjsKICB0Lm51bWVyYWxzaWduZ3JlZWsgPSAweDAzNzQ7CiAgdC5udW1lcmFsc2lnbmxvd2VyZ3JlZWsgPSAweDAzNzU7CiAgdC5udW1lcm8gPSAweDIxMTY7CiAgdC5udW4gPSAweDA1ZTA7CiAgdC5udW5kYWdlc2ggPSAweGZiNDA7CiAgdC5udW5kYWdlc2hoZWJyZXcgPSAweGZiNDA7CiAgdC5udW5oZWJyZXcgPSAweDA1ZTA7CiAgdC5udnNxdWFyZSA9IDB4MzNiNTsKICB0Lm53c3F1YXJlID0gMHgzM2JiOwogIHQubnlhYmVuZ2FsaSA9IDB4MDk5ZTsKICB0Lm55YWRldmEgPSAweDA5MWU7CiAgdC5ueWFndWphcmF0aSA9IDB4MGE5ZTsKICB0Lm55YWd1cm11a2hpID0gMHgwYTFlOwogIHQubyA9IDB4MDA2ZjsKICB0Lm9hY3V0ZSA9IDB4MDBmMzsKICB0Lm9hbmd0aGFpID0gMHgwZTJkOwogIHQub2JhcnJlZCA9IDB4MDI3NTsKICB0Lm9iYXJyZWRjeXJpbGxpYyA9IDB4MDRlOTsKICB0Lm9iYXJyZWRkaWVyZXNpc2N5cmlsbGljID0gMHgwNGViOwogIHQub2JlbmdhbGkgPSAweDA5OTM7CiAgdC5vYm9wb21vZm8gPSAweDMxMWI7CiAgdC5vYnJldmUgPSAweDAxNGY7CiAgdC5vY2FuZHJhZGV2YSA9IDB4MDkxMTsKICB0Lm9jYW5kcmFndWphcmF0aSA9IDB4MGE5MTsKICB0Lm9jYW5kcmF2b3dlbHNpZ25kZXZhID0gMHgwOTQ5OwogIHQub2NhbmRyYXZvd2Vsc2lnbmd1amFyYXRpID0gMHgwYWM5OwogIHQub2Nhcm9uID0gMHgwMWQyOwogIHQub2NpcmNsZSA9IDB4MjRkZTsKICB0Lm9jaXJjdW1mbGV4ID0gMHgwMGY0OwogIHQub2NpcmN1bWZsZXhhY3V0ZSA9IDB4MWVkMTsKICB0Lm9jaXJjdW1mbGV4ZG90YmVsb3cgPSAweDFlZDk7CiAgdC5vY2lyY3VtZmxleGdyYXZlID0gMHgxZWQzOwogIHQub2NpcmN1bWZsZXhob29rYWJvdmUgPSAweDFlZDU7CiAgdC5vY2lyY3VtZmxleHRpbGRlID0gMHgxZWQ3OwogIHQub2N5cmlsbGljID0gMHgwNDNlOwogIHQub2RibGFjdXRlID0gMHgwMTUxOwogIHQub2RibGdyYXZlID0gMHgwMjBkOwogIHQub2RldmEgPSAweDA5MTM7CiAgdC5vZGllcmVzaXMgPSAweDAwZjY7CiAgdC5vZGllcmVzaXNjeXJpbGxpYyA9IDB4MDRlNzsKICB0Lm9kb3RiZWxvdyA9IDB4MWVjZDsKICB0Lm9lID0gMHgwMTUzOwogIHQub2Vrb3JlYW4gPSAweDMxNWE7CiAgdC5vZ29uZWsgPSAweDAyZGI7CiAgdC5vZ29uZWtjbWIgPSAweDAzMjg7CiAgdC5vZ3JhdmUgPSAweDAwZjI7CiAgdC5vZ3VqYXJhdGkgPSAweDBhOTM7CiAgdC5vaGFybWVuaWFuID0gMHgwNTg1OwogIHQub2hpcmFnYW5hID0gMHgzMDRhOwogIHQub2hvb2thYm92ZSA9IDB4MWVjZjsKICB0Lm9ob3JuID0gMHgwMWExOwogIHQub2hvcm5hY3V0ZSA9IDB4MWVkYjsKICB0Lm9ob3JuZG90YmVsb3cgPSAweDFlZTM7CiAgdC5vaG9ybmdyYXZlID0gMHgxZWRkOwogIHQub2hvcm5ob29rYWJvdmUgPSAweDFlZGY7CiAgdC5vaG9ybnRpbGRlID0gMHgxZWUxOwogIHQub2h1bmdhcnVtbGF1dCA9IDB4MDE1MTsKICB0Lm9pID0gMHgwMWEzOwogIHQub2ludmVydGVkYnJldmUgPSAweDAyMGY7CiAgdC5va2F0YWthbmEgPSAweDMwYWE7CiAgdC5va2F0YWthbmFoYWxmd2lkdGggPSAweGZmNzU7CiAgdC5va29yZWFuID0gMHgzMTU3OwogIHQub2xlaGVicmV3ID0gMHgwNWFiOwogIHQub21hY3JvbiA9IDB4MDE0ZDsKICB0Lm9tYWNyb25hY3V0ZSA9IDB4MWU1MzsKICB0Lm9tYWNyb25ncmF2ZSA9IDB4MWU1MTsKICB0Lm9tZGV2YSA9IDB4MDk1MDsKICB0Lm9tZWdhID0gMHgwM2M5OwogIHQub21lZ2ExID0gMHgwM2Q2OwogIHQub21lZ2FjeXJpbGxpYyA9IDB4MDQ2MTsKICB0Lm9tZWdhbGF0aW5jbG9zZWQgPSAweDAyNzc7CiAgdC5vbWVnYXJvdW5kY3lyaWxsaWMgPSAweDA0N2I7CiAgdC5vbWVnYXRpdGxvY3lyaWxsaWMgPSAweDA0N2Q7CiAgdC5vbWVnYXRvbm9zID0gMHgwM2NlOwogIHQub21ndWphcmF0aSA9IDB4MGFkMDsKICB0Lm9taWNyb24gPSAweDAzYmY7CiAgdC5vbWljcm9udG9ub3MgPSAweDAzY2M7CiAgdC5vbW9ub3NwYWNlID0gMHhmZjRmOwogIHQub25lID0gMHgwMDMxOwogIHQub25lYXJhYmljID0gMHgwNjYxOwogIHQub25lYmVuZ2FsaSA9IDB4MDllNzsKICB0Lm9uZWNpcmNsZSA9IDB4MjQ2MDsKICB0Lm9uZWNpcmNsZWludmVyc2VzYW5zc2VyaWYgPSAweDI3OGE7CiAgdC5vbmVkZXZhID0gMHgwOTY3OwogIHQub25lZG90ZW5sZWFkZXIgPSAweDIwMjQ7CiAgdC5vbmVlaWdodGggPSAweDIxNWI7CiAgdC5vbmVmaXR0ZWQgPSAweGY2ZGM7CiAgdC5vbmVndWphcmF0aSA9IDB4MGFlNzsKICB0Lm9uZWd1cm11a2hpID0gMHgwYTY3OwogIHQub25laGFja2FyYWJpYyA9IDB4MDY2MTsKICB0Lm9uZWhhbGYgPSAweDAwYmQ7CiAgdC5vbmVoYW5nemhvdSA9IDB4MzAyMTsKICB0Lm9uZWlkZW9ncmFwaGljcGFyZW4gPSAweDMyMjA7CiAgdC5vbmVpbmZlcmlvciA9IDB4MjA4MTsKICB0Lm9uZW1vbm9zcGFjZSA9IDB4ZmYxMTsKICB0Lm9uZW51bWVyYXRvcmJlbmdhbGkgPSAweDA5ZjQ7CiAgdC5vbmVvbGRzdHlsZSA9IDB4ZjczMTsKICB0Lm9uZXBhcmVuID0gMHgyNDc0OwogIHQub25lcGVyaW9kID0gMHgyNDg4OwogIHQub25lcGVyc2lhbiA9IDB4MDZmMTsKICB0Lm9uZXF1YXJ0ZXIgPSAweDAwYmM7CiAgdC5vbmVyb21hbiA9IDB4MjE3MDsKICB0Lm9uZXN1cGVyaW9yID0gMHgwMGI5OwogIHQub25ldGhhaSA9IDB4MGU1MTsKICB0Lm9uZXRoaXJkID0gMHgyMTUzOwogIHQub29nb25layA9IDB4MDFlYjsKICB0Lm9vZ29uZWttYWNyb24gPSAweDAxZWQ7CiAgdC5vb2d1cm11a2hpID0gMHgwYTEzOwogIHQub29tYXRyYWd1cm11a2hpID0gMHgwYTRiOwogIHQub29wZW4gPSAweDAyNTQ7CiAgdC5vcGFyZW4gPSAweDI0YWE7CiAgdC5vcGVuYnVsbGV0ID0gMHgyNWU2OwogIHQub3B0aW9uID0gMHgyMzI1OwogIHQub3JkZmVtaW5pbmUgPSAweDAwYWE7CiAgdC5vcmRtYXNjdWxpbmUgPSAweDAwYmE7CiAgdC5vcnRob2dvbmFsID0gMHgyMjFmOwogIHQub3Nob3J0ZGV2YSA9IDB4MDkxMjsKICB0Lm9zaG9ydHZvd2Vsc2lnbmRldmEgPSAweDA5NGE7CiAgdC5vc2xhc2ggPSAweDAwZjg7CiAgdC5vc2xhc2hhY3V0ZSA9IDB4MDFmZjsKICB0Lm9zbWFsbGhpcmFnYW5hID0gMHgzMDQ5OwogIHQub3NtYWxsa2F0YWthbmEgPSAweDMwYTk7CiAgdC5vc21hbGxrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY2YjsKICB0Lm9zdHJva2VhY3V0ZSA9IDB4MDFmZjsKICB0Lm9zdXBlcmlvciA9IDB4ZjZmMDsKICB0Lm90Y3lyaWxsaWMgPSAweDA0N2Y7CiAgdC5vdGlsZGUgPSAweDAwZjU7CiAgdC5vdGlsZGVhY3V0ZSA9IDB4MWU0ZDsKICB0Lm90aWxkZWRpZXJlc2lzID0gMHgxZTRmOwogIHQub3Vib3BvbW9mbyA9IDB4MzEyMTsKICB0Lm92ZXJsaW5lID0gMHgyMDNlOwogIHQub3ZlcmxpbmVjZW50ZXJsaW5lID0gMHhmZTRhOwogIHQub3ZlcmxpbmVjbWIgPSAweDAzMDU7CiAgdC5vdmVybGluZWRhc2hlZCA9IDB4ZmU0OTsKICB0Lm92ZXJsaW5lZGJsd2F2eSA9IDB4ZmU0YzsKICB0Lm92ZXJsaW5ld2F2eSA9IDB4ZmU0YjsKICB0Lm92ZXJzY29yZSA9IDB4MDBhZjsKICB0Lm92b3dlbHNpZ25iZW5nYWxpID0gMHgwOWNiOwogIHQub3Zvd2Vsc2lnbmRldmEgPSAweDA5NGI7CiAgdC5vdm93ZWxzaWduZ3VqYXJhdGkgPSAweDBhY2I7CiAgdC5wID0gMHgwMDcwOwogIHQucGFhbXBzc3F1YXJlID0gMHgzMzgwOwogIHQucGFhc2VudG9zcXVhcmUgPSAweDMzMmI7CiAgdC5wYWJlbmdhbGkgPSAweDA5YWE7CiAgdC5wYWN1dGUgPSAweDFlNTU7CiAgdC5wYWRldmEgPSAweDA5MmE7CiAgdC5wYWdlZG93biA9IDB4MjFkZjsKICB0LnBhZ2V1cCA9IDB4MjFkZTsKICB0LnBhZ3VqYXJhdGkgPSAweDBhYWE7CiAgdC5wYWd1cm11a2hpID0gMHgwYTJhOwogIHQucGFoaXJhZ2FuYSA9IDB4MzA3MTsKICB0LnBhaXlhbm5vaXRoYWkgPSAweDBlMmY7CiAgdC5wYWthdGFrYW5hID0gMHgzMGQxOwogIHQucGFsYXRhbGl6YXRpb25jeXJpbGxpY2NtYiA9IDB4MDQ4NDsKICB0LnBhbG9jaGthY3lyaWxsaWMgPSAweDA0YzA7CiAgdC5wYW5zaW9za29yZWFuID0gMHgzMTdmOwogIHQucGFyYWdyYXBoID0gMHgwMGI2OwogIHQucGFyYWxsZWwgPSAweDIyMjU7CiAgdC5wYXJlbmxlZnQgPSAweDAwMjg7CiAgdC5wYXJlbmxlZnRhbHRvbmVhcmFiaWMgPSAweGZkM2U7CiAgdC5wYXJlbmxlZnRidCA9IDB4ZjhlZDsKICB0LnBhcmVubGVmdGV4ID0gMHhmOGVjOwogIHQucGFyZW5sZWZ0aW5mZXJpb3IgPSAweDIwOGQ7CiAgdC5wYXJlbmxlZnRtb25vc3BhY2UgPSAweGZmMDg7CiAgdC5wYXJlbmxlZnRzbWFsbCA9IDB4ZmU1OTsKICB0LnBhcmVubGVmdHN1cGVyaW9yID0gMHgyMDdkOwogIHQucGFyZW5sZWZ0dHAgPSAweGY4ZWI7CiAgdC5wYXJlbmxlZnR2ZXJ0aWNhbCA9IDB4ZmUzNTsKICB0LnBhcmVucmlnaHQgPSAweDAwMjk7CiAgdC5wYXJlbnJpZ2h0YWx0b25lYXJhYmljID0gMHhmZDNmOwogIHQucGFyZW5yaWdodGJ0ID0gMHhmOGY4OwogIHQucGFyZW5yaWdodGV4ID0gMHhmOGY3OwogIHQucGFyZW5yaWdodGluZmVyaW9yID0gMHgyMDhlOwogIHQucGFyZW5yaWdodG1vbm9zcGFjZSA9IDB4ZmYwOTsKICB0LnBhcmVucmlnaHRzbWFsbCA9IDB4ZmU1YTsKICB0LnBhcmVucmlnaHRzdXBlcmlvciA9IDB4MjA3ZTsKICB0LnBhcmVucmlnaHR0cCA9IDB4ZjhmNjsKICB0LnBhcmVucmlnaHR2ZXJ0aWNhbCA9IDB4ZmUzNjsKICB0LnBhcnRpYWxkaWZmID0gMHgyMjAyOwogIHQucGFzZXFoZWJyZXcgPSAweDA1YzA7CiAgdC5wYXNodGFoZWJyZXcgPSAweDA1OTk7CiAgdC5wYXNxdWFyZSA9IDB4MzNhOTsKICB0LnBhdGFoID0gMHgwNWI3OwogIHQucGF0YWgxMSA9IDB4MDViNzsKICB0LnBhdGFoMWQgPSAweDA1Yjc7CiAgdC5wYXRhaDJhID0gMHgwNWI3OwogIHQucGF0YWhoZWJyZXcgPSAweDA1Yjc7CiAgdC5wYXRhaG5hcnJvd2hlYnJldyA9IDB4MDViNzsKICB0LnBhdGFocXVhcnRlcmhlYnJldyA9IDB4MDViNzsKICB0LnBhdGFod2lkZWhlYnJldyA9IDB4MDViNzsKICB0LnBhemVyaGVicmV3ID0gMHgwNWExOwogIHQucGJvcG9tb2ZvID0gMHgzMTA2OwogIHQucGNpcmNsZSA9IDB4MjRkZjsKICB0LnBkb3RhY2NlbnQgPSAweDFlNTc7CiAgdC5wZSA9IDB4MDVlNDsKICB0LnBlY3lyaWxsaWMgPSAweDA0M2Y7CiAgdC5wZWRhZ2VzaCA9IDB4ZmI0NDsKICB0LnBlZGFnZXNoaGVicmV3ID0gMHhmYjQ0OwogIHQucGVlemlzcXVhcmUgPSAweDMzM2I7CiAgdC5wZWZpbmFsZGFnZXNoaGVicmV3ID0gMHhmYjQzOwogIHQucGVoYXJhYmljID0gMHgwNjdlOwogIHQucGVoYXJtZW5pYW4gPSAweDA1N2E7CiAgdC5wZWhlYnJldyA9IDB4MDVlNDsKICB0LnBlaGZpbmFsYXJhYmljID0gMHhmYjU3OwogIHQucGVoaW5pdGlhbGFyYWJpYyA9IDB4ZmI1ODsKICB0LnBlaGlyYWdhbmEgPSAweDMwN2E7CiAgdC5wZWhtZWRpYWxhcmFiaWMgPSAweGZiNTk7CiAgdC5wZWthdGFrYW5hID0gMHgzMGRhOwogIHQucGVtaWRkbGVob29rY3lyaWxsaWMgPSAweDA0YTc7CiAgdC5wZXJhZmVoZWJyZXcgPSAweGZiNGU7CiAgdC5wZXJjZW50ID0gMHgwMDI1OwogIHQucGVyY2VudGFyYWJpYyA9IDB4MDY2YTsKICB0LnBlcmNlbnRtb25vc3BhY2UgPSAweGZmMDU7CiAgdC5wZXJjZW50c21hbGwgPSAweGZlNmE7CiAgdC5wZXJpb2QgPSAweDAwMmU7CiAgdC5wZXJpb2Rhcm1lbmlhbiA9IDB4MDU4OTsKICB0LnBlcmlvZGNlbnRlcmVkID0gMHgwMGI3OwogIHQucGVyaW9kaGFsZndpZHRoID0gMHhmZjYxOwogIHQucGVyaW9kaW5mZXJpb3IgPSAweGY2ZTc7CiAgdC5wZXJpb2Rtb25vc3BhY2UgPSAweGZmMGU7CiAgdC5wZXJpb2RzbWFsbCA9IDB4ZmU1MjsKICB0LnBlcmlvZHN1cGVyaW9yID0gMHhmNmU4OwogIHQucGVyaXNwb21lbmlncmVla2NtYiA9IDB4MDM0MjsKICB0LnBlcnBlbmRpY3VsYXIgPSAweDIyYTU7CiAgdC5wZXJ0aG91c2FuZCA9IDB4MjAzMDsKICB0LnBlc2V0YSA9IDB4MjBhNzsKICB0LnBmc3F1YXJlID0gMHgzMzhhOwogIHQucGhhYmVuZ2FsaSA9IDB4MDlhYjsKICB0LnBoYWRldmEgPSAweDA5MmI7CiAgdC5waGFndWphcmF0aSA9IDB4MGFhYjsKICB0LnBoYWd1cm11a2hpID0gMHgwYTJiOwogIHQucGhpID0gMHgwM2M2OwogIHQucGhpMSA9IDB4MDNkNTsKICB0LnBoaWV1cGhhY2lyY2xla29yZWFuID0gMHgzMjdhOwogIHQucGhpZXVwaGFwYXJlbmtvcmVhbiA9IDB4MzIxYTsKICB0LnBoaWV1cGhjaXJjbGVrb3JlYW4gPSAweDMyNmM7CiAgdC5waGlldXBoa29yZWFuID0gMHgzMTRkOwogIHQucGhpZXVwaHBhcmVua29yZWFuID0gMHgzMjBjOwogIHQucGhpbGF0aW4gPSAweDAyNzg7CiAgdC5waGludGh1dGhhaSA9IDB4MGUzYTsKICB0LnBoaXN5bWJvbGdyZWVrID0gMHgwM2Q1OwogIHQucGhvb2sgPSAweDAxYTU7CiAgdC5waG9waGFudGhhaSA9IDB4MGUxZTsKICB0LnBob3BodW5ndGhhaSA9IDB4MGUxYzsKICB0LnBob3NhbXBoYW90aGFpID0gMHgwZTIwOwogIHQucGkgPSAweDAzYzA7CiAgdC5waWV1cGFjaXJjbGVrb3JlYW4gPSAweDMyNzM7CiAgdC5waWV1cGFwYXJlbmtvcmVhbiA9IDB4MzIxMzsKICB0LnBpZXVwY2lldWNrb3JlYW4gPSAweDMxNzY7CiAgdC5waWV1cGNpcmNsZWtvcmVhbiA9IDB4MzI2NTsKICB0LnBpZXVwa2l5ZW9ra29yZWFuID0gMHgzMTcyOwogIHQucGlldXBrb3JlYW4gPSAweDMxNDI7CiAgdC5waWV1cHBhcmVua29yZWFuID0gMHgzMjA1OwogIHQucGlldXBzaW9za2l5ZW9ra29yZWFuID0gMHgzMTc0OwogIHQucGlldXBzaW9za29yZWFuID0gMHgzMTQ0OwogIHQucGlldXBzaW9zdGlrZXV0a29yZWFuID0gMHgzMTc1OwogIHQucGlldXB0aGlldXRoa29yZWFuID0gMHgzMTc3OwogIHQucGlldXB0aWtldXRrb3JlYW4gPSAweDMxNzM7CiAgdC5waWhpcmFnYW5hID0gMHgzMDc0OwogIHQucGlrYXRha2FuYSA9IDB4MzBkNDsKICB0LnBpc3ltYm9sZ3JlZWsgPSAweDAzZDY7CiAgdC5waXdyYXJtZW5pYW4gPSAweDA1ODM7CiAgdC5wbGFuY2tvdmVyMnBpID0gMHgyMTBmOwogIHQucGxhbmNrb3ZlcjJwaTEgPSAweDIxMGY7CiAgdC5wbHVzID0gMHgwMDJiOwogIHQucGx1c2JlbG93Y21iID0gMHgwMzFmOwogIHQucGx1c2NpcmNsZSA9IDB4MjI5NTsKICB0LnBsdXNtaW51cyA9IDB4MDBiMTsKICB0LnBsdXNtb2QgPSAweDAyZDY7CiAgdC5wbHVzbW9ub3NwYWNlID0gMHhmZjBiOwogIHQucGx1c3NtYWxsID0gMHhmZTYyOwogIHQucGx1c3N1cGVyaW9yID0gMHgyMDdhOwogIHQucG1vbm9zcGFjZSA9IDB4ZmY1MDsKICB0LnBtc3F1YXJlID0gMHgzM2Q4OwogIHQucG9oaXJhZ2FuYSA9IDB4MzA3ZDsKICB0LnBvaW50aW5naW5kZXhkb3dud2hpdGUgPSAweDI2MWY7CiAgdC5wb2ludGluZ2luZGV4bGVmdHdoaXRlID0gMHgyNjFjOwogIHQucG9pbnRpbmdpbmRleHJpZ2h0d2hpdGUgPSAweDI2MWU7CiAgdC5wb2ludGluZ2luZGV4dXB3aGl0ZSA9IDB4MjYxZDsKICB0LnBva2F0YWthbmEgPSAweDMwZGQ7CiAgdC5wb3BsYXRoYWkgPSAweDBlMWI7CiAgdC5wb3N0YWxtYXJrID0gMHgzMDEyOwogIHQucG9zdGFsbWFya2ZhY2UgPSAweDMwMjA7CiAgdC5wcGFyZW4gPSAweDI0YWI7CiAgdC5wcmVjZWRlcyA9IDB4MjI3YTsKICB0LnByZXNjcmlwdGlvbiA9IDB4MjExZTsKICB0LnByaW1lbW9kID0gMHgwMmI5OwogIHQucHJpbWVyZXZlcnNlZCA9IDB4MjAzNTsKICB0LnByb2R1Y3QgPSAweDIyMGY7CiAgdC5wcm9qZWN0aXZlID0gMHgyMzA1OwogIHQucHJvbG9uZ2Vka2FuYSA9IDB4MzBmYzsKICB0LnByb3BlbGxvciA9IDB4MjMxODsKICB0LnByb3BlcnN1YnNldCA9IDB4MjI4MjsKICB0LnByb3BlcnN1cGVyc2V0ID0gMHgyMjgzOwogIHQucHJvcG9ydGlvbiA9IDB4MjIzNzsKICB0LnByb3BvcnRpb25hbCA9IDB4MjIxZDsKICB0LnBzaSA9IDB4MDNjODsKICB0LnBzaWN5cmlsbGljID0gMHgwNDcxOwogIHQucHNpbGlwbmV1bWF0YWN5cmlsbGljY21iID0gMHgwNDg2OwogIHQucHNzcXVhcmUgPSAweDMzYjA7CiAgdC5wdWhpcmFnYW5hID0gMHgzMDc3OwogIHQucHVrYXRha2FuYSA9IDB4MzBkNzsKICB0LnB2c3F1YXJlID0gMHgzM2I0OwogIHQucHdzcXVhcmUgPSAweDMzYmE7CiAgdC5xID0gMHgwMDcxOwogIHQucWFkZXZhID0gMHgwOTU4OwogIHQucWFkbWFoZWJyZXcgPSAweDA1YTg7CiAgdC5xYWZhcmFiaWMgPSAweDA2NDI7CiAgdC5xYWZmaW5hbGFyYWJpYyA9IDB4ZmVkNjsKICB0LnFhZmluaXRpYWxhcmFiaWMgPSAweGZlZDc7CiAgdC5xYWZtZWRpYWxhcmFiaWMgPSAweGZlZDg7CiAgdC5xYW1hdHMgPSAweDA1Yjg7CiAgdC5xYW1hdHMxMCA9IDB4MDViODsKICB0LnFhbWF0czFhID0gMHgwNWI4OwogIHQucWFtYXRzMWMgPSAweDA1Yjg7CiAgdC5xYW1hdHMyNyA9IDB4MDViODsKICB0LnFhbWF0czI5ID0gMHgwNWI4OwogIHQucWFtYXRzMzMgPSAweDA1Yjg7CiAgdC5xYW1hdHNkZSA9IDB4MDViODsKICB0LnFhbWF0c2hlYnJldyA9IDB4MDViODsKICB0LnFhbWF0c25hcnJvd2hlYnJldyA9IDB4MDViODsKICB0LnFhbWF0c3FhdGFuaGVicmV3ID0gMHgwNWI4OwogIHQucWFtYXRzcWF0YW5uYXJyb3doZWJyZXcgPSAweDA1Yjg7CiAgdC5xYW1hdHNxYXRhbnF1YXJ0ZXJoZWJyZXcgPSAweDA1Yjg7CiAgdC5xYW1hdHNxYXRhbndpZGVoZWJyZXcgPSAweDA1Yjg7CiAgdC5xYW1hdHNxdWFydGVyaGVicmV3ID0gMHgwNWI4OwogIHQucWFtYXRzd2lkZWhlYnJldyA9IDB4MDViODsKICB0LnFhcm5leXBhcmFoZWJyZXcgPSAweDA1OWY7CiAgdC5xYm9wb21vZm8gPSAweDMxMTE7CiAgdC5xY2lyY2xlID0gMHgyNGUwOwogIHQucWhvb2sgPSAweDAyYTA7CiAgdC5xbW9ub3NwYWNlID0gMHhmZjUxOwogIHQucW9mID0gMHgwNWU3OwogIHQucW9mZGFnZXNoID0gMHhmYjQ3OwogIHQucW9mZGFnZXNoaGVicmV3ID0gMHhmYjQ3OwogIHQucW9maGVicmV3ID0gMHgwNWU3OwogIHQucXBhcmVuID0gMHgyNGFjOwogIHQucXVhcnRlcm5vdGUgPSAweDI2Njk7CiAgdC5xdWJ1dHMgPSAweDA1YmI7CiAgdC5xdWJ1dHMxOCA9IDB4MDViYjsKICB0LnF1YnV0czI1ID0gMHgwNWJiOwogIHQucXVidXRzMzEgPSAweDA1YmI7CiAgdC5xdWJ1dHNoZWJyZXcgPSAweDA1YmI7CiAgdC5xdWJ1dHNuYXJyb3doZWJyZXcgPSAweDA1YmI7CiAgdC5xdWJ1dHNxdWFydGVyaGVicmV3ID0gMHgwNWJiOwogIHQucXVidXRzd2lkZWhlYnJldyA9IDB4MDViYjsKICB0LnF1ZXN0aW9uID0gMHgwMDNmOwogIHQucXVlc3Rpb25hcmFiaWMgPSAweDA2MWY7CiAgdC5xdWVzdGlvbmFybWVuaWFuID0gMHgwNTVlOwogIHQucXVlc3Rpb25kb3duID0gMHgwMGJmOwogIHQucXVlc3Rpb25kb3duc21hbGwgPSAweGY3YmY7CiAgdC5xdWVzdGlvbmdyZWVrID0gMHgwMzdlOwogIHQucXVlc3Rpb25tb25vc3BhY2UgPSAweGZmMWY7CiAgdC5xdWVzdGlvbnNtYWxsID0gMHhmNzNmOwogIHQucXVvdGVkYmwgPSAweDAwMjI7CiAgdC5xdW90ZWRibGJhc2UgPSAweDIwMWU7CiAgdC5xdW90ZWRibGxlZnQgPSAweDIwMWM7CiAgdC5xdW90ZWRibG1vbm9zcGFjZSA9IDB4ZmYwMjsKICB0LnF1b3RlZGJscHJpbWUgPSAweDMwMWU7CiAgdC5xdW90ZWRibHByaW1lcmV2ZXJzZWQgPSAweDMwMWQ7CiAgdC5xdW90ZWRibHJpZ2h0ID0gMHgyMDFkOwogIHQucXVvdGVsZWZ0ID0gMHgyMDE4OwogIHQucXVvdGVsZWZ0cmV2ZXJzZWQgPSAweDIwMWI7CiAgdC5xdW90ZXJldmVyc2VkID0gMHgyMDFiOwogIHQucXVvdGVyaWdodCA9IDB4MjAxOTsKICB0LnF1b3RlcmlnaHRuID0gMHgwMTQ5OwogIHQucXVvdGVzaW5nbGJhc2UgPSAweDIwMWE7CiAgdC5xdW90ZXNpbmdsZSA9IDB4MDAyNzsKICB0LnF1b3Rlc2luZ2xlbW9ub3NwYWNlID0gMHhmZjA3OwogIHQuciA9IDB4MDA3MjsKICB0LnJhYXJtZW5pYW4gPSAweDA1N2M7CiAgdC5yYWJlbmdhbGkgPSAweDA5YjA7CiAgdC5yYWN1dGUgPSAweDAxNTU7CiAgdC5yYWRldmEgPSAweDA5MzA7CiAgdC5yYWRpY2FsID0gMHgyMjFhOwogIHQucmFkaWNhbGV4ID0gMHhmOGU1OwogIHQucmFkb3ZlcnNzcXVhcmUgPSAweDMzYWU7CiAgdC5yYWRvdmVyc3NxdWFyZWRzcXVhcmUgPSAweDMzYWY7CiAgdC5yYWRzcXVhcmUgPSAweDMzYWQ7CiAgdC5yYWZlID0gMHgwNWJmOwogIHQucmFmZWhlYnJldyA9IDB4MDViZjsKICB0LnJhZ3VqYXJhdGkgPSAweDBhYjA7CiAgdC5yYWd1cm11a2hpID0gMHgwYTMwOwogIHQucmFoaXJhZ2FuYSA9IDB4MzA4OTsKICB0LnJha2F0YWthbmEgPSAweDMwZTk7CiAgdC5yYWthdGFrYW5haGFsZndpZHRoID0gMHhmZjk3OwogIHQucmFsb3dlcmRpYWdvbmFsYmVuZ2FsaSA9IDB4MDlmMTsKICB0LnJhbWlkZGxlZGlhZ29uYWxiZW5nYWxpID0gMHgwOWYwOwogIHQucmFtc2hvcm4gPSAweDAyNjQ7CiAgdC5yYXRpbyA9IDB4MjIzNjsKICB0LnJib3BvbW9mbyA9IDB4MzExNjsKICB0LnJjYXJvbiA9IDB4MDE1OTsKICB0LnJjZWRpbGxhID0gMHgwMTU3OwogIHQucmNpcmNsZSA9IDB4MjRlMTsKICB0LnJjb21tYWFjY2VudCA9IDB4MDE1NzsKICB0LnJkYmxncmF2ZSA9IDB4MDIxMTsKICB0LnJkb3RhY2NlbnQgPSAweDFlNTk7CiAgdC5yZG90YmVsb3cgPSAweDFlNWI7CiAgdC5yZG90YmVsb3dtYWNyb24gPSAweDFlNWQ7CiAgdC5yZWZlcmVuY2VtYXJrID0gMHgyMDNiOwogIHQucmVmbGV4c3Vic2V0ID0gMHgyMjg2OwogIHQucmVmbGV4c3VwZXJzZXQgPSAweDIyODc7CiAgdC5yZWdpc3RlcmVkID0gMHgwMGFlOwogIHQucmVnaXN0ZXJzYW5zID0gMHhmOGU4OwogIHQucmVnaXN0ZXJzZXJpZiA9IDB4ZjZkYTsKICB0LnJlaGFyYWJpYyA9IDB4MDYzMTsKICB0LnJlaGFybWVuaWFuID0gMHgwNTgwOwogIHQucmVoZmluYWxhcmFiaWMgPSAweGZlYWU7CiAgdC5yZWhpcmFnYW5hID0gMHgzMDhjOwogIHQucmVrYXRha2FuYSA9IDB4MzBlYzsKICB0LnJla2F0YWthbmFoYWxmd2lkdGggPSAweGZmOWE7CiAgdC5yZXNoID0gMHgwNWU4OwogIHQucmVzaGRhZ2VzaGhlYnJldyA9IDB4ZmI0ODsKICB0LnJlc2hoZWJyZXcgPSAweDA1ZTg7CiAgdC5yZXZlcnNlZHRpbGRlID0gMHgyMjNkOwogIHQucmV2aWFoZWJyZXcgPSAweDA1OTc7CiAgdC5yZXZpYW11Z3Jhc2hoZWJyZXcgPSAweDA1OTc7CiAgdC5yZXZsb2dpY2Fsbm90ID0gMHgyMzEwOwogIHQucmZpc2hob29rID0gMHgwMjdlOwogIHQucmZpc2hob29rcmV2ZXJzZWQgPSAweDAyN2Y7CiAgdC5yaGFiZW5nYWxpID0gMHgwOWRkOwogIHQucmhhZGV2YSA9IDB4MDk1ZDsKICB0LnJobyA9IDB4MDNjMTsKICB0LnJob29rID0gMHgwMjdkOwogIHQucmhvb2t0dXJuZWQgPSAweDAyN2I7CiAgdC5yaG9va3R1cm5lZHN1cGVyaW9yID0gMHgwMmI1OwogIHQucmhvc3ltYm9sZ3JlZWsgPSAweDAzZjE7CiAgdC5yaG90aWNob29rbW9kID0gMHgwMmRlOwogIHQucmlldWxhY2lyY2xla29yZWFuID0gMHgzMjcxOwogIHQucmlldWxhcGFyZW5rb3JlYW4gPSAweDMyMTE7CiAgdC5yaWV1bGNpcmNsZWtvcmVhbiA9IDB4MzI2MzsKICB0LnJpZXVsaGlldWhrb3JlYW4gPSAweDMxNDA7CiAgdC5yaWV1bGtpeWVva2tvcmVhbiA9IDB4MzEzYTsKICB0LnJpZXVsa2l5ZW9rc2lvc2tvcmVhbiA9IDB4MzE2OTsKICB0LnJpZXVsa29yZWFuID0gMHgzMTM5OwogIHQucmlldWxtaWV1bWtvcmVhbiA9IDB4MzEzYjsKICB0LnJpZXVscGFuc2lvc2tvcmVhbiA9IDB4MzE2YzsKICB0LnJpZXVscGFyZW5rb3JlYW4gPSAweDMyMDM7CiAgdC5yaWV1bHBoaWV1cGhrb3JlYW4gPSAweDMxM2Y7CiAgdC5yaWV1bHBpZXVwa29yZWFuID0gMHgzMTNjOwogIHQucmlldWxwaWV1cHNpb3Nrb3JlYW4gPSAweDMxNmI7CiAgdC5yaWV1bHNpb3Nrb3JlYW4gPSAweDMxM2Q7CiAgdC5yaWV1bHRoaWV1dGhrb3JlYW4gPSAweDMxM2U7CiAgdC5yaWV1bHRpa2V1dGtvcmVhbiA9IDB4MzE2YTsKICB0LnJpZXVseWVvcmluaGlldWhrb3JlYW4gPSAweDMxNmQ7CiAgdC5yaWdodGFuZ2xlID0gMHgyMjFmOwogIHQucmlnaHR0YWNrYmVsb3djbWIgPSAweDAzMTk7CiAgdC5yaWdodHRyaWFuZ2xlID0gMHgyMmJmOwogIHQucmloaXJhZ2FuYSA9IDB4MzA4YTsKICB0LnJpa2F0YWthbmEgPSAweDMwZWE7CiAgdC5yaWthdGFrYW5haGFsZndpZHRoID0gMHhmZjk4OwogIHQucmluZyA9IDB4MDJkYTsKICB0LnJpbmdiZWxvd2NtYiA9IDB4MDMyNTsKICB0LnJpbmdjbWIgPSAweDAzMGE7CiAgdC5yaW5naGFsZmxlZnQgPSAweDAyYmY7CiAgdC5yaW5naGFsZmxlZnRhcm1lbmlhbiA9IDB4MDU1OTsKICB0LnJpbmdoYWxmbGVmdGJlbG93Y21iID0gMHgwMzFjOwogIHQucmluZ2hhbGZsZWZ0Y2VudGVyZWQgPSAweDAyZDM7CiAgdC5yaW5naGFsZnJpZ2h0ID0gMHgwMmJlOwogIHQucmluZ2hhbGZyaWdodGJlbG93Y21iID0gMHgwMzM5OwogIHQucmluZ2hhbGZyaWdodGNlbnRlcmVkID0gMHgwMmQyOwogIHQucmludmVydGVkYnJldmUgPSAweDAyMTM7CiAgdC5yaXR0b3J1c3F1YXJlID0gMHgzMzUxOwogIHQucmxpbmViZWxvdyA9IDB4MWU1ZjsKICB0LnJsb25nbGVnID0gMHgwMjdjOwogIHQucmxvbmdsZWd0dXJuZWQgPSAweDAyN2E7CiAgdC5ybW9ub3NwYWNlID0gMHhmZjUyOwogIHQucm9oaXJhZ2FuYSA9IDB4MzA4ZDsKICB0LnJva2F0YWthbmEgPSAweDMwZWQ7CiAgdC5yb2thdGFrYW5haGFsZndpZHRoID0gMHhmZjliOwogIHQucm9ydWF0aGFpID0gMHgwZTIzOwogIHQucnBhcmVuID0gMHgyNGFkOwogIHQucnJhYmVuZ2FsaSA9IDB4MDlkYzsKICB0LnJyYWRldmEgPSAweDA5MzE7CiAgdC5ycmFndXJtdWtoaSA9IDB4MGE1YzsKICB0LnJyZWhhcmFiaWMgPSAweDA2OTE7CiAgdC5ycmVoZmluYWxhcmFiaWMgPSAweGZiOGQ7CiAgdC5ycnZvY2FsaWNiZW5nYWxpID0gMHgwOWUwOwogIHQucnJ2b2NhbGljZGV2YSA9IDB4MDk2MDsKICB0LnJydm9jYWxpY2d1amFyYXRpID0gMHgwYWUwOwogIHQucnJ2b2NhbGljdm93ZWxzaWduYmVuZ2FsaSA9IDB4MDljNDsKICB0LnJydm9jYWxpY3Zvd2Vsc2lnbmRldmEgPSAweDA5NDQ7CiAgdC5ycnZvY2FsaWN2b3dlbHNpZ25ndWphcmF0aSA9IDB4MGFjNDsKICB0LnJzdXBlcmlvciA9IDB4ZjZmMTsKICB0LnJ0YmxvY2sgPSAweDI1OTA7CiAgdC5ydHVybmVkID0gMHgwMjc5OwogIHQucnR1cm5lZHN1cGVyaW9yID0gMHgwMmI0OwogIHQucnVoaXJhZ2FuYSA9IDB4MzA4YjsKICB0LnJ1a2F0YWthbmEgPSAweDMwZWI7CiAgdC5ydWthdGFrYW5haGFsZndpZHRoID0gMHhmZjk5OwogIHQucnVwZWVtYXJrYmVuZ2FsaSA9IDB4MDlmMjsKICB0LnJ1cGVlc2lnbmJlbmdhbGkgPSAweDA5ZjM7CiAgdC5ydXBpYWggPSAweGY2ZGQ7CiAgdC5ydXRoYWkgPSAweDBlMjQ7CiAgdC5ydm9jYWxpY2JlbmdhbGkgPSAweDA5OGI7CiAgdC5ydm9jYWxpY2RldmEgPSAweDA5MGI7CiAgdC5ydm9jYWxpY2d1amFyYXRpID0gMHgwYThiOwogIHQucnZvY2FsaWN2b3dlbHNpZ25iZW5nYWxpID0gMHgwOWMzOwogIHQucnZvY2FsaWN2b3dlbHNpZ25kZXZhID0gMHgwOTQzOwogIHQucnZvY2FsaWN2b3dlbHNpZ25ndWphcmF0aSA9IDB4MGFjMzsKICB0LnMgPSAweDAwNzM7CiAgdC5zYWJlbmdhbGkgPSAweDA5Yjg7CiAgdC5zYWN1dGUgPSAweDAxNWI7CiAgdC5zYWN1dGVkb3RhY2NlbnQgPSAweDFlNjU7CiAgdC5zYWRhcmFiaWMgPSAweDA2MzU7CiAgdC5zYWRldmEgPSAweDA5Mzg7CiAgdC5zYWRmaW5hbGFyYWJpYyA9IDB4ZmViYTsKICB0LnNhZGluaXRpYWxhcmFiaWMgPSAweGZlYmI7CiAgdC5zYWRtZWRpYWxhcmFiaWMgPSAweGZlYmM7CiAgdC5zYWd1amFyYXRpID0gMHgwYWI4OwogIHQuc2FndXJtdWtoaSA9IDB4MGEzODsKICB0LnNhaGlyYWdhbmEgPSAweDMwNTU7CiAgdC5zYWthdGFrYW5hID0gMHgzMGI1OwogIHQuc2FrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY3YjsKICB0LnNhbGxhbGxhaG91YWxheWhld2FzYWxsYW1hcmFiaWMgPSAweGZkZmE7CiAgdC5zYW1la2ggPSAweDA1ZTE7CiAgdC5zYW1la2hkYWdlc2ggPSAweGZiNDE7CiAgdC5zYW1la2hkYWdlc2hoZWJyZXcgPSAweGZiNDE7CiAgdC5zYW1la2hoZWJyZXcgPSAweDA1ZTE7CiAgdC5zYXJhYWF0aGFpID0gMHgwZTMyOwogIHQuc2FyYWFldGhhaSA9IDB4MGU0MTsKICB0LnNhcmFhaW1haW1hbGFpdGhhaSA9IDB4MGU0NDsKICB0LnNhcmFhaW1haW11YW50aGFpID0gMHgwZTQzOwogIHQuc2FyYWFtdGhhaSA9IDB4MGUzMzsKICB0LnNhcmFhdGhhaSA9IDB4MGUzMDsKICB0LnNhcmFldGhhaSA9IDB4MGU0MDsKICB0LnNhcmFpaWxlZnR0aGFpID0gMHhmODg2OwogIHQuc2FyYWlpdGhhaSA9IDB4MGUzNTsKICB0LnNhcmFpbGVmdHRoYWkgPSAweGY4ODU7CiAgdC5zYXJhaXRoYWkgPSAweDBlMzQ7CiAgdC5zYXJhb3RoYWkgPSAweDBlNDI7CiAgdC5zYXJhdWVlbGVmdHRoYWkgPSAweGY4ODg7CiAgdC5zYXJhdWVldGhhaSA9IDB4MGUzNzsKICB0LnNhcmF1ZWxlZnR0aGFpID0gMHhmODg3OwogIHQuc2FyYXVldGhhaSA9IDB4MGUzNjsKICB0LnNhcmF1dGhhaSA9IDB4MGUzODsKICB0LnNhcmF1dXRoYWkgPSAweDBlMzk7CiAgdC5zYm9wb21vZm8gPSAweDMxMTk7CiAgdC5zY2Fyb24gPSAweDAxNjE7CiAgdC5zY2Fyb25kb3RhY2NlbnQgPSAweDFlNjc7CiAgdC5zY2VkaWxsYSA9IDB4MDE1ZjsKICB0LnNjaHdhID0gMHgwMjU5OwogIHQuc2Nod2FjeXJpbGxpYyA9IDB4MDRkOTsKICB0LnNjaHdhZGllcmVzaXNjeXJpbGxpYyA9IDB4MDRkYjsKICB0LnNjaHdhaG9vayA9IDB4MDI1YTsKICB0LnNjaXJjbGUgPSAweDI0ZTI7CiAgdC5zY2lyY3VtZmxleCA9IDB4MDE1ZDsKICB0LnNjb21tYWFjY2VudCA9IDB4MDIxOTsKICB0LnNkb3RhY2NlbnQgPSAweDFlNjE7CiAgdC5zZG90YmVsb3cgPSAweDFlNjM7CiAgdC5zZG90YmVsb3dkb3RhY2NlbnQgPSAweDFlNjk7CiAgdC5zZWFndWxsYmVsb3djbWIgPSAweDAzM2M7CiAgdC5zZWNvbmQgPSAweDIwMzM7CiAgdC5zZWNvbmR0b25lY2hpbmVzZSA9IDB4MDJjYTsKICB0LnNlY3Rpb24gPSAweDAwYTc7CiAgdC5zZWVuYXJhYmljID0gMHgwNjMzOwogIHQuc2VlbmZpbmFsYXJhYmljID0gMHhmZWIyOwogIHQuc2VlbmluaXRpYWxhcmFiaWMgPSAweGZlYjM7CiAgdC5zZWVubWVkaWFsYXJhYmljID0gMHhmZWI0OwogIHQuc2Vnb2wgPSAweDA1YjY7CiAgdC5zZWdvbDEzID0gMHgwNWI2OwogIHQuc2Vnb2wxZiA9IDB4MDViNjsKICB0LnNlZ29sMmMgPSAweDA1YjY7CiAgdC5zZWdvbGhlYnJldyA9IDB4MDViNjsKICB0LnNlZ29sbmFycm93aGVicmV3ID0gMHgwNWI2OwogIHQuc2Vnb2xxdWFydGVyaGVicmV3ID0gMHgwNWI2OwogIHQuc2Vnb2x0YWhlYnJldyA9IDB4MDU5MjsKICB0LnNlZ29sd2lkZWhlYnJldyA9IDB4MDViNjsKICB0LnNlaGFybWVuaWFuID0gMHgwNTdkOwogIHQuc2VoaXJhZ2FuYSA9IDB4MzA1YjsKICB0LnNla2F0YWthbmEgPSAweDMwYmI7CiAgdC5zZWthdGFrYW5haGFsZndpZHRoID0gMHhmZjdlOwogIHQuc2VtaWNvbG9uID0gMHgwMDNiOwogIHQuc2VtaWNvbG9uYXJhYmljID0gMHgwNjFiOwogIHQuc2VtaWNvbG9ubW9ub3NwYWNlID0gMHhmZjFiOwogIHQuc2VtaWNvbG9uc21hbGwgPSAweGZlNTQ7CiAgdC5zZW1pdm9pY2VkbWFya2thbmEgPSAweDMwOWM7CiAgdC5zZW1pdm9pY2VkbWFya2thbmFoYWxmd2lkdGggPSAweGZmOWY7CiAgdC5zZW50aXNxdWFyZSA9IDB4MzMyMjsKICB0LnNlbnRvc3F1YXJlID0gMHgzMzIzOwogIHQuc2V2ZW4gPSAweDAwMzc7CiAgdC5zZXZlbmFyYWJpYyA9IDB4MDY2NzsKICB0LnNldmVuYmVuZ2FsaSA9IDB4MDllZDsKICB0LnNldmVuY2lyY2xlID0gMHgyNDY2OwogIHQuc2V2ZW5jaXJjbGVpbnZlcnNlc2Fuc3NlcmlmID0gMHgyNzkwOwogIHQuc2V2ZW5kZXZhID0gMHgwOTZkOwogIHQuc2V2ZW5laWdodGhzID0gMHgyMTVlOwogIHQuc2V2ZW5ndWphcmF0aSA9IDB4MGFlZDsKICB0LnNldmVuZ3VybXVraGkgPSAweDBhNmQ7CiAgdC5zZXZlbmhhY2thcmFiaWMgPSAweDA2Njc7CiAgdC5zZXZlbmhhbmd6aG91ID0gMHgzMDI3OwogIHQuc2V2ZW5pZGVvZ3JhcGhpY3BhcmVuID0gMHgzMjI2OwogIHQuc2V2ZW5pbmZlcmlvciA9IDB4MjA4NzsKICB0LnNldmVubW9ub3NwYWNlID0gMHhmZjE3OwogIHQuc2V2ZW5vbGRzdHlsZSA9IDB4ZjczNzsKICB0LnNldmVucGFyZW4gPSAweDI0N2E7CiAgdC5zZXZlbnBlcmlvZCA9IDB4MjQ4ZTsKICB0LnNldmVucGVyc2lhbiA9IDB4MDZmNzsKICB0LnNldmVucm9tYW4gPSAweDIxNzY7CiAgdC5zZXZlbnN1cGVyaW9yID0gMHgyMDc3OwogIHQuc2V2ZW50ZWVuY2lyY2xlID0gMHgyNDcwOwogIHQuc2V2ZW50ZWVucGFyZW4gPSAweDI0ODQ7CiAgdC5zZXZlbnRlZW5wZXJpb2QgPSAweDI0OTg7CiAgdC5zZXZlbnRoYWkgPSAweDBlNTc7CiAgdC5zZnRoeXBoZW4gPSAweDAwYWQ7CiAgdC5zaGFhcm1lbmlhbiA9IDB4MDU3NzsKICB0LnNoYWJlbmdhbGkgPSAweDA5YjY7CiAgdC5zaGFjeXJpbGxpYyA9IDB4MDQ0ODsKICB0LnNoYWRkYWFyYWJpYyA9IDB4MDY1MTsKICB0LnNoYWRkYWRhbW1hYXJhYmljID0gMHhmYzYxOwogIHQuc2hhZGRhZGFtbWF0YW5hcmFiaWMgPSAweGZjNWU7CiAgdC5zaGFkZGFmYXRoYWFyYWJpYyA9IDB4ZmM2MDsKICB0LnNoYWRkYWthc3JhYXJhYmljID0gMHhmYzYyOwogIHQuc2hhZGRha2FzcmF0YW5hcmFiaWMgPSAweGZjNWY7CiAgdC5zaGFkZSA9IDB4MjU5MjsKICB0LnNoYWRlZGFyayA9IDB4MjU5MzsKICB0LnNoYWRlbGlnaHQgPSAweDI1OTE7CiAgdC5zaGFkZW1lZGl1bSA9IDB4MjU5MjsKICB0LnNoYWRldmEgPSAweDA5MzY7CiAgdC5zaGFndWphcmF0aSA9IDB4MGFiNjsKICB0LnNoYWd1cm11a2hpID0gMHgwYTM2OwogIHQuc2hhbHNoZWxldGhlYnJldyA9IDB4MDU5MzsKICB0LnNoYm9wb21vZm8gPSAweDMxMTU7CiAgdC5zaGNoYWN5cmlsbGljID0gMHgwNDQ5OwogIHQuc2hlZW5hcmFiaWMgPSAweDA2MzQ7CiAgdC5zaGVlbmZpbmFsYXJhYmljID0gMHhmZWI2OwogIHQuc2hlZW5pbml0aWFsYXJhYmljID0gMHhmZWI3OwogIHQuc2hlZW5tZWRpYWxhcmFiaWMgPSAweGZlYjg7CiAgdC5zaGVpY29wdGljID0gMHgwM2UzOwogIHQuc2hlcWVsID0gMHgyMGFhOwogIHQuc2hlcWVsaGVicmV3ID0gMHgyMGFhOwogIHQuc2hldmEgPSAweDA1YjA7CiAgdC5zaGV2YTExNSA9IDB4MDViMDsKICB0LnNoZXZhMTUgPSAweDA1YjA7CiAgdC5zaGV2YTIyID0gMHgwNWIwOwogIHQuc2hldmEyZSA9IDB4MDViMDsKICB0LnNoZXZhaGVicmV3ID0gMHgwNWIwOwogIHQuc2hldmFuYXJyb3doZWJyZXcgPSAweDA1YjA7CiAgdC5zaGV2YXF1YXJ0ZXJoZWJyZXcgPSAweDA1YjA7CiAgdC5zaGV2YXdpZGVoZWJyZXcgPSAweDA1YjA7CiAgdC5zaGhhY3lyaWxsaWMgPSAweDA0YmI7CiAgdC5zaGltYWNvcHRpYyA9IDB4MDNlZDsKICB0LnNoaW4gPSAweDA1ZTk7CiAgdC5zaGluZGFnZXNoID0gMHhmYjQ5OwogIHQuc2hpbmRhZ2VzaGhlYnJldyA9IDB4ZmI0OTsKICB0LnNoaW5kYWdlc2hzaGluZG90ID0gMHhmYjJjOwogIHQuc2hpbmRhZ2VzaHNoaW5kb3RoZWJyZXcgPSAweGZiMmM7CiAgdC5zaGluZGFnZXNoc2luZG90ID0gMHhmYjJkOwogIHQuc2hpbmRhZ2VzaHNpbmRvdGhlYnJldyA9IDB4ZmIyZDsKICB0LnNoaW5kb3RoZWJyZXcgPSAweDA1YzE7CiAgdC5zaGluaGVicmV3ID0gMHgwNWU5OwogIHQuc2hpbnNoaW5kb3QgPSAweGZiMmE7CiAgdC5zaGluc2hpbmRvdGhlYnJldyA9IDB4ZmIyYTsKICB0LnNoaW5zaW5kb3QgPSAweGZiMmI7CiAgdC5zaGluc2luZG90aGVicmV3ID0gMHhmYjJiOwogIHQuc2hvb2sgPSAweDAyODI7CiAgdC5zaWdtYSA9IDB4MDNjMzsKICB0LnNpZ21hMSA9IDB4MDNjMjsKICB0LnNpZ21hZmluYWwgPSAweDAzYzI7CiAgdC5zaWdtYWx1bmF0ZXN5bWJvbGdyZWVrID0gMHgwM2YyOwogIHQuc2loaXJhZ2FuYSA9IDB4MzA1NzsKICB0LnNpa2F0YWthbmEgPSAweDMwYjc7CiAgdC5zaWthdGFrYW5haGFsZndpZHRoID0gMHhmZjdjOwogIHQuc2lsdXFoZWJyZXcgPSAweDA1YmQ7CiAgdC5zaWx1cWxlZnRoZWJyZXcgPSAweDA1YmQ7CiAgdC5zaW1pbGFyID0gMHgyMjNjOwogIHQuc2luZG90aGVicmV3ID0gMHgwNWMyOwogIHQuc2lvc2FjaXJjbGVrb3JlYW4gPSAweDMyNzQ7CiAgdC5zaW9zYXBhcmVua29yZWFuID0gMHgzMjE0OwogIHQuc2lvc2NpZXVja29yZWFuID0gMHgzMTdlOwogIHQuc2lvc2NpcmNsZWtvcmVhbiA9IDB4MzI2NjsKICB0LnNpb3NraXllb2trb3JlYW4gPSAweDMxN2E7CiAgdC5zaW9za29yZWFuID0gMHgzMTQ1OwogIHQuc2lvc25pZXVua29yZWFuID0gMHgzMTdiOwogIHQuc2lvc3BhcmVua29yZWFuID0gMHgzMjA2OwogIHQuc2lvc3BpZXVwa29yZWFuID0gMHgzMTdkOwogIHQuc2lvc3Rpa2V1dGtvcmVhbiA9IDB4MzE3YzsKICB0LnNpeCA9IDB4MDAzNjsKICB0LnNpeGFyYWJpYyA9IDB4MDY2NjsKICB0LnNpeGJlbmdhbGkgPSAweDA5ZWM7CiAgdC5zaXhjaXJjbGUgPSAweDI0NjU7CiAgdC5zaXhjaXJjbGVpbnZlcnNlc2Fuc3NlcmlmID0gMHgyNzhmOwogIHQuc2l4ZGV2YSA9IDB4MDk2YzsKICB0LnNpeGd1amFyYXRpID0gMHgwYWVjOwogIHQuc2l4Z3VybXVraGkgPSAweDBhNmM7CiAgdC5zaXhoYWNrYXJhYmljID0gMHgwNjY2OwogIHQuc2l4aGFuZ3pob3UgPSAweDMwMjY7CiAgdC5zaXhpZGVvZ3JhcGhpY3BhcmVuID0gMHgzMjI1OwogIHQuc2l4aW5mZXJpb3IgPSAweDIwODY7CiAgdC5zaXhtb25vc3BhY2UgPSAweGZmMTY7CiAgdC5zaXhvbGRzdHlsZSA9IDB4ZjczNjsKICB0LnNpeHBhcmVuID0gMHgyNDc5OwogIHQuc2l4cGVyaW9kID0gMHgyNDhkOwogIHQuc2l4cGVyc2lhbiA9IDB4MDZmNjsKICB0LnNpeHJvbWFuID0gMHgyMTc1OwogIHQuc2l4c3VwZXJpb3IgPSAweDIwNzY7CiAgdC5zaXh0ZWVuY2lyY2xlID0gMHgyNDZmOwogIHQuc2l4dGVlbmN1cnJlbmN5ZGVub21pbmF0b3JiZW5nYWxpID0gMHgwOWY5OwogIHQuc2l4dGVlbnBhcmVuID0gMHgyNDgzOwogIHQuc2l4dGVlbnBlcmlvZCA9IDB4MjQ5NzsKICB0LnNpeHRoYWkgPSAweDBlNTY7CiAgdC5zbGFzaCA9IDB4MDAyZjsKICB0LnNsYXNobW9ub3NwYWNlID0gMHhmZjBmOwogIHQuc2xvbmcgPSAweDAxN2Y7CiAgdC5zbG9uZ2RvdGFjY2VudCA9IDB4MWU5YjsKICB0LnNtaWxlZmFjZSA9IDB4MjYzYTsKICB0LnNtb25vc3BhY2UgPSAweGZmNTM7CiAgdC5zb2ZwYXN1cWhlYnJldyA9IDB4MDVjMzsKICB0LnNvZnRoeXBoZW4gPSAweDAwYWQ7CiAgdC5zb2Z0c2lnbmN5cmlsbGljID0gMHgwNDRjOwogIHQuc29oaXJhZ2FuYSA9IDB4MzA1ZDsKICB0LnNva2F0YWthbmEgPSAweDMwYmQ7CiAgdC5zb2thdGFrYW5haGFsZndpZHRoID0gMHhmZjdmOwogIHQuc29saWR1c2xvbmdvdmVybGF5Y21iID0gMHgwMzM4OwogIHQuc29saWR1c3Nob3J0b3ZlcmxheWNtYiA9IDB4MDMzNzsKICB0LnNvcnVzaXRoYWkgPSAweDBlMjk7CiAgdC5zb3NhbGF0aGFpID0gMHgwZTI4OwogIHQuc29zb3RoYWkgPSAweDBlMGI7CiAgdC5zb3N1YXRoYWkgPSAweDBlMmE7CiAgdC5zcGFjZSA9IDB4MDAyMDsKICB0LnNwYWNlaGFja2FyYWJpYyA9IDB4MDAyMDsKICB0LnNwYWRlID0gMHgyNjYwOwogIHQuc3BhZGVzdWl0YmxhY2sgPSAweDI2NjA7CiAgdC5zcGFkZXN1aXR3aGl0ZSA9IDB4MjY2NDsKICB0LnNwYXJlbiA9IDB4MjRhZTsKICB0LnNxdWFyZWJlbG93Y21iID0gMHgwMzNiOwogIHQuc3F1YXJlY2MgPSAweDMzYzQ7CiAgdC5zcXVhcmVjbSA9IDB4MzM5ZDsKICB0LnNxdWFyZWRpYWdvbmFsY3Jvc3NoYXRjaGZpbGwgPSAweDI1YTk7CiAgdC5zcXVhcmVob3Jpem9udGFsZmlsbCA9IDB4MjVhNDsKICB0LnNxdWFyZWtnID0gMHgzMzhmOwogIHQuc3F1YXJla20gPSAweDMzOWU7CiAgdC5zcXVhcmVrbWNhcGl0YWwgPSAweDMzY2U7CiAgdC5zcXVhcmVsbiA9IDB4MzNkMTsKICB0LnNxdWFyZWxvZyA9IDB4MzNkMjsKICB0LnNxdWFyZW1nID0gMHgzMzhlOwogIHQuc3F1YXJlbWlsID0gMHgzM2Q1OwogIHQuc3F1YXJlbW0gPSAweDMzOWM7CiAgdC5zcXVhcmVtc3F1YXJlZCA9IDB4MzNhMTsKICB0LnNxdWFyZW9ydGhvZ29uYWxjcm9zc2hhdGNoZmlsbCA9IDB4MjVhNjsKICB0LnNxdWFyZXVwcGVybGVmdHRvbG93ZXJyaWdodGZpbGwgPSAweDI1YTc7CiAgdC5zcXVhcmV1cHBlcnJpZ2h0dG9sb3dlcmxlZnRmaWxsID0gMHgyNWE4OwogIHQuc3F1YXJldmVydGljYWxmaWxsID0gMHgyNWE1OwogIHQuc3F1YXJld2hpdGV3aXRoc21hbGxibGFjayA9IDB4MjVhMzsKICB0LnNyc3F1YXJlID0gMHgzM2RiOwogIHQuc3NhYmVuZ2FsaSA9IDB4MDliNzsKICB0LnNzYWRldmEgPSAweDA5Mzc7CiAgdC5zc2FndWphcmF0aSA9IDB4MGFiNzsKICB0LnNzYW5nY2lldWNrb3JlYW4gPSAweDMxNDk7CiAgdC5zc2FuZ2hpZXVoa29yZWFuID0gMHgzMTg1OwogIHQuc3NhbmdpZXVuZ2tvcmVhbiA9IDB4MzE4MDsKICB0LnNzYW5na2l5ZW9ra29yZWFuID0gMHgzMTMyOwogIHQuc3NhbmduaWV1bmtvcmVhbiA9IDB4MzE2NTsKICB0LnNzYW5ncGlldXBrb3JlYW4gPSAweDMxNDM7CiAgdC5zc2FuZ3Npb3Nrb3JlYW4gPSAweDMxNDY7CiAgdC5zc2FuZ3Rpa2V1dGtvcmVhbiA9IDB4MzEzODsKICB0LnNzdXBlcmlvciA9IDB4ZjZmMjsKICB0LnN0ZXJsaW5nID0gMHgwMGEzOwogIHQuc3Rlcmxpbmdtb25vc3BhY2UgPSAweGZmZTE7CiAgdC5zdHJva2Vsb25nb3ZlcmxheWNtYiA9IDB4MDMzNjsKICB0LnN0cm9rZXNob3J0b3ZlcmxheWNtYiA9IDB4MDMzNTsKICB0LnN1YnNldCA9IDB4MjI4MjsKICB0LnN1YnNldG5vdGVxdWFsID0gMHgyMjhhOwogIHQuc3Vic2V0b3JlcXVhbCA9IDB4MjI4NjsKICB0LnN1Y2NlZWRzID0gMHgyMjdiOwogIHQuc3VjaHRoYXQgPSAweDIyMGI7CiAgdC5zdWhpcmFnYW5hID0gMHgzMDU5OwogIHQuc3VrYXRha2FuYSA9IDB4MzBiOTsKICB0LnN1a2F0YWthbmFoYWxmd2lkdGggPSAweGZmN2Q7CiAgdC5zdWt1bmFyYWJpYyA9IDB4MDY1MjsKICB0LnN1bW1hdGlvbiA9IDB4MjIxMTsKICB0LnN1biA9IDB4MjYzYzsKICB0LnN1cGVyc2V0ID0gMHgyMjgzOwogIHQuc3VwZXJzZXRub3RlcXVhbCA9IDB4MjI4YjsKICB0LnN1cGVyc2V0b3JlcXVhbCA9IDB4MjI4NzsKICB0LnN2c3F1YXJlID0gMHgzM2RjOwogIHQuc3lvdXdhZXJhc3F1YXJlID0gMHgzMzdjOwogIHQudCA9IDB4MDA3NDsKICB0LnRhYmVuZ2FsaSA9IDB4MDlhNDsKICB0LnRhY2tkb3duID0gMHgyMmE0OwogIHQudGFja2xlZnQgPSAweDIyYTM7CiAgdC50YWRldmEgPSAweDA5MjQ7CiAgdC50YWd1amFyYXRpID0gMHgwYWE0OwogIHQudGFndXJtdWtoaSA9IDB4MGEyNDsKICB0LnRhaGFyYWJpYyA9IDB4MDYzNzsKICB0LnRhaGZpbmFsYXJhYmljID0gMHhmZWMyOwogIHQudGFoaW5pdGlhbGFyYWJpYyA9IDB4ZmVjMzsKICB0LnRhaGlyYWdhbmEgPSAweDMwNWY7CiAgdC50YWhtZWRpYWxhcmFiaWMgPSAweGZlYzQ7CiAgdC50YWlzeW91ZXJhc3F1YXJlID0gMHgzMzdkOwogIHQudGFrYXRha2FuYSA9IDB4MzBiZjsKICB0LnRha2F0YWthbmFoYWxmd2lkdGggPSAweGZmODA7CiAgdC50YXR3ZWVsYXJhYmljID0gMHgwNjQwOwogIHQudGF1ID0gMHgwM2M0OwogIHQudGF2ID0gMHgwNWVhOwogIHQudGF2ZGFnZXMgPSAweGZiNGE7CiAgdC50YXZkYWdlc2ggPSAweGZiNGE7CiAgdC50YXZkYWdlc2hoZWJyZXcgPSAweGZiNGE7CiAgdC50YXZoZWJyZXcgPSAweDA1ZWE7CiAgdC50YmFyID0gMHgwMTY3OwogIHQudGJvcG9tb2ZvID0gMHgzMTBhOwogIHQudGNhcm9uID0gMHgwMTY1OwogIHQudGNjdXJsID0gMHgwMmE4OwogIHQudGNlZGlsbGEgPSAweDAxNjM7CiAgdC50Y2hlaGFyYWJpYyA9IDB4MDY4NjsKICB0LnRjaGVoZmluYWxhcmFiaWMgPSAweGZiN2I7CiAgdC50Y2hlaGluaXRpYWxhcmFiaWMgPSAweGZiN2M7CiAgdC50Y2hlaG1lZGlhbGFyYWJpYyA9IDB4ZmI3ZDsKICB0LnRjaXJjbGUgPSAweDI0ZTM7CiAgdC50Y2lyY3VtZmxleGJlbG93ID0gMHgxZTcxOwogIHQudGNvbW1hYWNjZW50ID0gMHgwMTYzOwogIHQudGRpZXJlc2lzID0gMHgxZTk3OwogIHQudGRvdGFjY2VudCA9IDB4MWU2YjsKICB0LnRkb3RiZWxvdyA9IDB4MWU2ZDsKICB0LnRlY3lyaWxsaWMgPSAweDA0NDI7CiAgdC50ZWRlc2NlbmRlcmN5cmlsbGljID0gMHgwNGFkOwogIHQudGVoYXJhYmljID0gMHgwNjJhOwogIHQudGVoZmluYWxhcmFiaWMgPSAweGZlOTY7CiAgdC50ZWhoYWhpbml0aWFsYXJhYmljID0gMHhmY2EyOwogIHQudGVoaGFoaXNvbGF0ZWRhcmFiaWMgPSAweGZjMGM7CiAgdC50ZWhpbml0aWFsYXJhYmljID0gMHhmZTk3OwogIHQudGVoaXJhZ2FuYSA9IDB4MzA2NjsKICB0LnRlaGplZW1pbml0aWFsYXJhYmljID0gMHhmY2ExOwogIHQudGVoamVlbWlzb2xhdGVkYXJhYmljID0gMHhmYzBiOwogIHQudGVobWFyYnV0YWFyYWJpYyA9IDB4MDYyOTsKICB0LnRlaG1hcmJ1dGFmaW5hbGFyYWJpYyA9IDB4ZmU5NDsKICB0LnRlaG1lZGlhbGFyYWJpYyA9IDB4ZmU5ODsKICB0LnRlaG1lZW1pbml0aWFsYXJhYmljID0gMHhmY2E0OwogIHQudGVobWVlbWlzb2xhdGVkYXJhYmljID0gMHhmYzBlOwogIHQudGVobm9vbmZpbmFsYXJhYmljID0gMHhmYzczOwogIHQudGVrYXRha2FuYSA9IDB4MzBjNjsKICB0LnRla2F0YWthbmFoYWxmd2lkdGggPSAweGZmODM7CiAgdC50ZWxlcGhvbmUgPSAweDIxMjE7CiAgdC50ZWxlcGhvbmVibGFjayA9IDB4MjYwZTsKICB0LnRlbGlzaGFnZWRvbGFoZWJyZXcgPSAweDA1YTA7CiAgdC50ZWxpc2hhcWV0YW5haGVicmV3ID0gMHgwNWE5OwogIHQudGVuY2lyY2xlID0gMHgyNDY5OwogIHQudGVuaWRlb2dyYXBoaWNwYXJlbiA9IDB4MzIyOTsKICB0LnRlbnBhcmVuID0gMHgyNDdkOwogIHQudGVucGVyaW9kID0gMHgyNDkxOwogIHQudGVucm9tYW4gPSAweDIxNzk7CiAgdC50ZXNoID0gMHgwMmE3OwogIHQudGV0ID0gMHgwNWQ4OwogIHQudGV0ZGFnZXNoID0gMHhmYjM4OwogIHQudGV0ZGFnZXNoaGVicmV3ID0gMHhmYjM4OwogIHQudGV0aGVicmV3ID0gMHgwNWQ4OwogIHQudGV0c2VjeXJpbGxpYyA9IDB4MDRiNTsKICB0LnRldmlyaGVicmV3ID0gMHgwNTliOwogIHQudGV2aXJsZWZ0aGVicmV3ID0gMHgwNTliOwogIHQudGhhYmVuZ2FsaSA9IDB4MDlhNTsKICB0LnRoYWRldmEgPSAweDA5MjU7CiAgdC50aGFndWphcmF0aSA9IDB4MGFhNTsKICB0LnRoYWd1cm11a2hpID0gMHgwYTI1OwogIHQudGhhbGFyYWJpYyA9IDB4MDYzMDsKICB0LnRoYWxmaW5hbGFyYWJpYyA9IDB4ZmVhYzsKICB0LnRoYW50aGFraGF0bG93bGVmdHRoYWkgPSAweGY4OTg7CiAgdC50aGFudGhha2hhdGxvd3JpZ2h0dGhhaSA9IDB4Zjg5NzsKICB0LnRoYW50aGFraGF0dGhhaSA9IDB4MGU0YzsKICB0LnRoYW50aGFraGF0dXBwZXJsZWZ0dGhhaSA9IDB4Zjg5NjsKICB0LnRoZWhhcmFiaWMgPSAweDA2MmI7CiAgdC50aGVoZmluYWxhcmFiaWMgPSAweGZlOWE7CiAgdC50aGVoaW5pdGlhbGFyYWJpYyA9IDB4ZmU5YjsKICB0LnRoZWhtZWRpYWxhcmFiaWMgPSAweGZlOWM7CiAgdC50aGVyZWV4aXN0cyA9IDB4MjIwMzsKICB0LnRoZXJlZm9yZSA9IDB4MjIzNDsKICB0LnRoZXRhID0gMHgwM2I4OwogIHQudGhldGExID0gMHgwM2QxOwogIHQudGhldGFzeW1ib2xncmVlayA9IDB4MDNkMTsKICB0LnRoaWV1dGhhY2lyY2xla29yZWFuID0gMHgzMjc5OwogIHQudGhpZXV0aGFwYXJlbmtvcmVhbiA9IDB4MzIxOTsKICB0LnRoaWV1dGhjaXJjbGVrb3JlYW4gPSAweDMyNmI7CiAgdC50aGlldXRoa29yZWFuID0gMHgzMTRjOwogIHQudGhpZXV0aHBhcmVua29yZWFuID0gMHgzMjBiOwogIHQudGhpcnRlZW5jaXJjbGUgPSAweDI0NmM7CiAgdC50aGlydGVlbnBhcmVuID0gMHgyNDgwOwogIHQudGhpcnRlZW5wZXJpb2QgPSAweDI0OTQ7CiAgdC50aG9uYW5nbW9udGhvdGhhaSA9IDB4MGUxMTsKICB0LnRob29rID0gMHgwMWFkOwogIHQudGhvcGh1dGhhb3RoYWkgPSAweDBlMTI7CiAgdC50aG9ybiA9IDB4MDBmZTsKICB0LnRob3RoYWhhbnRoYWkgPSAweDBlMTc7CiAgdC50aG90aGFudGhhaSA9IDB4MGUxMDsKICB0LnRob3Rob25ndGhhaSA9IDB4MGUxODsKICB0LnRob3RodW5ndGhhaSA9IDB4MGUxNjsKICB0LnRob3VzYW5kY3lyaWxsaWMgPSAweDA0ODI7CiAgdC50aG91c2FuZHNzZXBhcmF0b3JhcmFiaWMgPSAweDA2NmM7CiAgdC50aG91c2FuZHNzZXBhcmF0b3JwZXJzaWFuID0gMHgwNjZjOwogIHQudGhyZWUgPSAweDAwMzM7CiAgdC50aHJlZWFyYWJpYyA9IDB4MDY2MzsKICB0LnRocmVlYmVuZ2FsaSA9IDB4MDllOTsKICB0LnRocmVlY2lyY2xlID0gMHgyNDYyOwogIHQudGhyZWVjaXJjbGVpbnZlcnNlc2Fuc3NlcmlmID0gMHgyNzhjOwogIHQudGhyZWVkZXZhID0gMHgwOTY5OwogIHQudGhyZWVlaWdodGhzID0gMHgyMTVjOwogIHQudGhyZWVndWphcmF0aSA9IDB4MGFlOTsKICB0LnRocmVlZ3VybXVraGkgPSAweDBhNjk7CiAgdC50aHJlZWhhY2thcmFiaWMgPSAweDA2NjM7CiAgdC50aHJlZWhhbmd6aG91ID0gMHgzMDIzOwogIHQudGhyZWVpZGVvZ3JhcGhpY3BhcmVuID0gMHgzMjIyOwogIHQudGhyZWVpbmZlcmlvciA9IDB4MjA4MzsKICB0LnRocmVlbW9ub3NwYWNlID0gMHhmZjEzOwogIHQudGhyZWVudW1lcmF0b3JiZW5nYWxpID0gMHgwOWY2OwogIHQudGhyZWVvbGRzdHlsZSA9IDB4ZjczMzsKICB0LnRocmVlcGFyZW4gPSAweDI0NzY7CiAgdC50aHJlZXBlcmlvZCA9IDB4MjQ4YTsKICB0LnRocmVlcGVyc2lhbiA9IDB4MDZmMzsKICB0LnRocmVlcXVhcnRlcnMgPSAweDAwYmU7CiAgdC50aHJlZXF1YXJ0ZXJzZW1kYXNoID0gMHhmNmRlOwogIHQudGhyZWVyb21hbiA9IDB4MjE3MjsKICB0LnRocmVlc3VwZXJpb3IgPSAweDAwYjM7CiAgdC50aHJlZXRoYWkgPSAweDBlNTM7CiAgdC50aHpzcXVhcmUgPSAweDMzOTQ7CiAgdC50aWhpcmFnYW5hID0gMHgzMDYxOwogIHQudGlrYXRha2FuYSA9IDB4MzBjMTsKICB0LnRpa2F0YWthbmFoYWxmd2lkdGggPSAweGZmODE7CiAgdC50aWtldXRhY2lyY2xla29yZWFuID0gMHgzMjcwOwogIHQudGlrZXV0YXBhcmVua29yZWFuID0gMHgzMjEwOwogIHQudGlrZXV0Y2lyY2xla29yZWFuID0gMHgzMjYyOwogIHQudGlrZXV0a29yZWFuID0gMHgzMTM3OwogIHQudGlrZXV0cGFyZW5rb3JlYW4gPSAweDMyMDI7CiAgdC50aWxkZSA9IDB4MDJkYzsKICB0LnRpbGRlYmVsb3djbWIgPSAweDAzMzA7CiAgdC50aWxkZWNtYiA9IDB4MDMwMzsKICB0LnRpbGRlY29tYiA9IDB4MDMwMzsKICB0LnRpbGRlZG91YmxlY21iID0gMHgwMzYwOwogIHQudGlsZGVvcGVyYXRvciA9IDB4MjIzYzsKICB0LnRpbGRlb3ZlcmxheWNtYiA9IDB4MDMzNDsKICB0LnRpbGRldmVydGljYWxjbWIgPSAweDAzM2U7CiAgdC50aW1lc2NpcmNsZSA9IDB4MjI5NzsKICB0LnRpcGVoYWhlYnJldyA9IDB4MDU5NjsKICB0LnRpcGVoYWxlZnRoZWJyZXcgPSAweDA1OTY7CiAgdC50aXBwaWd1cm11a2hpID0gMHgwYTcwOwogIHQudGl0bG9jeXJpbGxpY2NtYiA9IDB4MDQ4MzsKICB0LnRpd25hcm1lbmlhbiA9IDB4MDU3ZjsKICB0LnRsaW5lYmVsb3cgPSAweDFlNmY7CiAgdC50bW9ub3NwYWNlID0gMHhmZjU0OwogIHQudG9hcm1lbmlhbiA9IDB4MDU2OTsKICB0LnRvaGlyYWdhbmEgPSAweDMwNjg7CiAgdC50b2thdGFrYW5hID0gMHgzMGM4OwogIHQudG9rYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY4NDsKICB0LnRvbmViYXJleHRyYWhpZ2htb2QgPSAweDAyZTU7CiAgdC50b25lYmFyZXh0cmFsb3dtb2QgPSAweDAyZTk7CiAgdC50b25lYmFyaGlnaG1vZCA9IDB4MDJlNjsKICB0LnRvbmViYXJsb3dtb2QgPSAweDAyZTg7CiAgdC50b25lYmFybWlkbW9kID0gMHgwMmU3OwogIHQudG9uZWZpdmUgPSAweDAxYmQ7CiAgdC50b25lc2l4ID0gMHgwMTg1OwogIHQudG9uZXR3byA9IDB4MDFhODsKICB0LnRvbm9zID0gMHgwMzg0OwogIHQudG9uc3F1YXJlID0gMHgzMzI3OwogIHQudG9wYXRha3RoYWkgPSAweDBlMGY7CiAgdC50b3J0b2lzZXNoZWxsYnJhY2tldGxlZnQgPSAweDMwMTQ7CiAgdC50b3J0b2lzZXNoZWxsYnJhY2tldGxlZnRzbWFsbCA9IDB4ZmU1ZDsKICB0LnRvcnRvaXNlc2hlbGxicmFja2V0bGVmdHZlcnRpY2FsID0gMHhmZTM5OwogIHQudG9ydG9pc2VzaGVsbGJyYWNrZXRyaWdodCA9IDB4MzAxNTsKICB0LnRvcnRvaXNlc2hlbGxicmFja2V0cmlnaHRzbWFsbCA9IDB4ZmU1ZTsKICB0LnRvcnRvaXNlc2hlbGxicmFja2V0cmlnaHR2ZXJ0aWNhbCA9IDB4ZmUzYTsKICB0LnRvdGFvdGhhaSA9IDB4MGUxNTsKICB0LnRwYWxhdGFsaG9vayA9IDB4MDFhYjsKICB0LnRwYXJlbiA9IDB4MjRhZjsKICB0LnRyYWRlbWFyayA9IDB4MjEyMjsKICB0LnRyYWRlbWFya3NhbnMgPSAweGY4ZWE7CiAgdC50cmFkZW1hcmtzZXJpZiA9IDB4ZjZkYjsKICB0LnRyZXRyb2ZsZXhob29rID0gMHgwMjg4OwogIHQudHJpYWdkbiA9IDB4MjViYzsKICB0LnRyaWFnbGYgPSAweDI1YzQ7CiAgdC50cmlhZ3J0ID0gMHgyNWJhOwogIHQudHJpYWd1cCA9IDB4MjViMjsKICB0LnRzID0gMHgwMmE2OwogIHQudHNhZGkgPSAweDA1ZTY7CiAgdC50c2FkaWRhZ2VzaCA9IDB4ZmI0NjsKICB0LnRzYWRpZGFnZXNoaGVicmV3ID0gMHhmYjQ2OwogIHQudHNhZGloZWJyZXcgPSAweDA1ZTY7CiAgdC50c2VjeXJpbGxpYyA9IDB4MDQ0NjsKICB0LnRzZXJlID0gMHgwNWI1OwogIHQudHNlcmUxMiA9IDB4MDViNTsKICB0LnRzZXJlMWUgPSAweDA1YjU7CiAgdC50c2VyZTJiID0gMHgwNWI1OwogIHQudHNlcmVoZWJyZXcgPSAweDA1YjU7CiAgdC50c2VyZW5hcnJvd2hlYnJldyA9IDB4MDViNTsKICB0LnRzZXJlcXVhcnRlcmhlYnJldyA9IDB4MDViNTsKICB0LnRzZXJld2lkZWhlYnJldyA9IDB4MDViNTsKICB0LnRzaGVjeXJpbGxpYyA9IDB4MDQ1YjsKICB0LnRzdXBlcmlvciA9IDB4ZjZmMzsKICB0LnR0YWJlbmdhbGkgPSAweDA5OWY7CiAgdC50dGFkZXZhID0gMHgwOTFmOwogIHQudHRhZ3VqYXJhdGkgPSAweDBhOWY7CiAgdC50dGFndXJtdWtoaSA9IDB4MGExZjsKICB0LnR0ZWhhcmFiaWMgPSAweDA2Nzk7CiAgdC50dGVoZmluYWxhcmFiaWMgPSAweGZiNjc7CiAgdC50dGVoaW5pdGlhbGFyYWJpYyA9IDB4ZmI2ODsKICB0LnR0ZWhtZWRpYWxhcmFiaWMgPSAweGZiNjk7CiAgdC50dGhhYmVuZ2FsaSA9IDB4MDlhMDsKICB0LnR0aGFkZXZhID0gMHgwOTIwOwogIHQudHRoYWd1amFyYXRpID0gMHgwYWEwOwogIHQudHRoYWd1cm11a2hpID0gMHgwYTIwOwogIHQudHR1cm5lZCA9IDB4MDI4NzsKICB0LnR1aGlyYWdhbmEgPSAweDMwNjQ7CiAgdC50dWthdGFrYW5hID0gMHgzMGM0OwogIHQudHVrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY4MjsKICB0LnR1c21hbGxoaXJhZ2FuYSA9IDB4MzA2MzsKICB0LnR1c21hbGxrYXRha2FuYSA9IDB4MzBjMzsKICB0LnR1c21hbGxrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY2ZjsKICB0LnR3ZWx2ZWNpcmNsZSA9IDB4MjQ2YjsKICB0LnR3ZWx2ZXBhcmVuID0gMHgyNDdmOwogIHQudHdlbHZlcGVyaW9kID0gMHgyNDkzOwogIHQudHdlbHZlcm9tYW4gPSAweDIxN2I7CiAgdC50d2VudHljaXJjbGUgPSAweDI0NzM7CiAgdC50d2VudHloYW5nemhvdSA9IDB4NTM0NDsKICB0LnR3ZW50eXBhcmVuID0gMHgyNDg3OwogIHQudHdlbnR5cGVyaW9kID0gMHgyNDliOwogIHQudHdvID0gMHgwMDMyOwogIHQudHdvYXJhYmljID0gMHgwNjYyOwogIHQudHdvYmVuZ2FsaSA9IDB4MDllODsKICB0LnR3b2NpcmNsZSA9IDB4MjQ2MTsKICB0LnR3b2NpcmNsZWludmVyc2VzYW5zc2VyaWYgPSAweDI3OGI7CiAgdC50d29kZXZhID0gMHgwOTY4OwogIHQudHdvZG90ZW5sZWFkZXIgPSAweDIwMjU7CiAgdC50d29kb3RsZWFkZXIgPSAweDIwMjU7CiAgdC50d29kb3RsZWFkZXJ2ZXJ0aWNhbCA9IDB4ZmUzMDsKICB0LnR3b2d1amFyYXRpID0gMHgwYWU4OwogIHQudHdvZ3VybXVraGkgPSAweDBhNjg7CiAgdC50d29oYWNrYXJhYmljID0gMHgwNjYyOwogIHQudHdvaGFuZ3pob3UgPSAweDMwMjI7CiAgdC50d29pZGVvZ3JhcGhpY3BhcmVuID0gMHgzMjIxOwogIHQudHdvaW5mZXJpb3IgPSAweDIwODI7CiAgdC50d29tb25vc3BhY2UgPSAweGZmMTI7CiAgdC50d29udW1lcmF0b3JiZW5nYWxpID0gMHgwOWY1OwogIHQudHdvb2xkc3R5bGUgPSAweGY3MzI7CiAgdC50d29wYXJlbiA9IDB4MjQ3NTsKICB0LnR3b3BlcmlvZCA9IDB4MjQ4OTsKICB0LnR3b3BlcnNpYW4gPSAweDA2ZjI7CiAgdC50d29yb21hbiA9IDB4MjE3MTsKICB0LnR3b3N0cm9rZSA9IDB4MDFiYjsKICB0LnR3b3N1cGVyaW9yID0gMHgwMGIyOwogIHQudHdvdGhhaSA9IDB4MGU1MjsKICB0LnR3b3RoaXJkcyA9IDB4MjE1NDsKICB0LnUgPSAweDAwNzU7CiAgdC51YWN1dGUgPSAweDAwZmE7CiAgdC51YmFyID0gMHgwMjg5OwogIHQudWJlbmdhbGkgPSAweDA5ODk7CiAgdC51Ym9wb21vZm8gPSAweDMxMjg7CiAgdC51YnJldmUgPSAweDAxNmQ7CiAgdC51Y2Fyb24gPSAweDAxZDQ7CiAgdC51Y2lyY2xlID0gMHgyNGU0OwogIHQudWNpcmN1bWZsZXggPSAweDAwZmI7CiAgdC51Y2lyY3VtZmxleGJlbG93ID0gMHgxZTc3OwogIHQudWN5cmlsbGljID0gMHgwNDQzOwogIHQudWRhdHRhZGV2YSA9IDB4MDk1MTsKICB0LnVkYmxhY3V0ZSA9IDB4MDE3MTsKICB0LnVkYmxncmF2ZSA9IDB4MDIxNTsKICB0LnVkZXZhID0gMHgwOTA5OwogIHQudWRpZXJlc2lzID0gMHgwMGZjOwogIHQudWRpZXJlc2lzYWN1dGUgPSAweDAxZDg7CiAgdC51ZGllcmVzaXNiZWxvdyA9IDB4MWU3MzsKICB0LnVkaWVyZXNpc2Nhcm9uID0gMHgwMWRhOwogIHQudWRpZXJlc2lzY3lyaWxsaWMgPSAweDA0ZjE7CiAgdC51ZGllcmVzaXNncmF2ZSA9IDB4MDFkYzsKICB0LnVkaWVyZXNpc21hY3JvbiA9IDB4MDFkNjsKICB0LnVkb3RiZWxvdyA9IDB4MWVlNTsKICB0LnVncmF2ZSA9IDB4MDBmOTsKICB0LnVndWphcmF0aSA9IDB4MGE4OTsKICB0LnVndXJtdWtoaSA9IDB4MGEwOTsKICB0LnVoaXJhZ2FuYSA9IDB4MzA0NjsKICB0LnVob29rYWJvdmUgPSAweDFlZTc7CiAgdC51aG9ybiA9IDB4MDFiMDsKICB0LnVob3JuYWN1dGUgPSAweDFlZTk7CiAgdC51aG9ybmRvdGJlbG93ID0gMHgxZWYxOwogIHQudWhvcm5ncmF2ZSA9IDB4MWVlYjsKICB0LnVob3JuaG9va2Fib3ZlID0gMHgxZWVkOwogIHQudWhvcm50aWxkZSA9IDB4MWVlZjsKICB0LnVodW5nYXJ1bWxhdXQgPSAweDAxNzE7CiAgdC51aHVuZ2FydW1sYXV0Y3lyaWxsaWMgPSAweDA0ZjM7CiAgdC51aW52ZXJ0ZWRicmV2ZSA9IDB4MDIxNzsKICB0LnVrYXRha2FuYSA9IDB4MzBhNjsKICB0LnVrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY3MzsKICB0LnVrY3lyaWxsaWMgPSAweDA0Nzk7CiAgdC51a29yZWFuID0gMHgzMTVjOwogIHQudW1hY3JvbiA9IDB4MDE2YjsKICB0LnVtYWNyb25jeXJpbGxpYyA9IDB4MDRlZjsKICB0LnVtYWNyb25kaWVyZXNpcyA9IDB4MWU3YjsKICB0LnVtYXRyYWd1cm11a2hpID0gMHgwYTQxOwogIHQudW1vbm9zcGFjZSA9IDB4ZmY1NTsKICB0LnVuZGVyc2NvcmUgPSAweDAwNWY7CiAgdC51bmRlcnNjb3JlZGJsID0gMHgyMDE3OwogIHQudW5kZXJzY29yZW1vbm9zcGFjZSA9IDB4ZmYzZjsKICB0LnVuZGVyc2NvcmV2ZXJ0aWNhbCA9IDB4ZmUzMzsKICB0LnVuZGVyc2NvcmV3YXZ5ID0gMHhmZTRmOwogIHQudW5pb24gPSAweDIyMmE7CiAgdC51bml2ZXJzYWwgPSAweDIyMDA7CiAgdC51b2dvbmVrID0gMHgwMTczOwogIHQudXBhcmVuID0gMHgyNGIwOwogIHQudXBibG9jayA9IDB4MjU4MDsKICB0LnVwcGVyZG90aGVicmV3ID0gMHgwNWM0OwogIHQudXBzaWxvbiA9IDB4MDNjNTsKICB0LnVwc2lsb25kaWVyZXNpcyA9IDB4MDNjYjsKICB0LnVwc2lsb25kaWVyZXNpc3Rvbm9zID0gMHgwM2IwOwogIHQudXBzaWxvbmxhdGluID0gMHgwMjhhOwogIHQudXBzaWxvbnRvbm9zID0gMHgwM2NkOwogIHQudXB0YWNrYmVsb3djbWIgPSAweDAzMWQ7CiAgdC51cHRhY2ttb2QgPSAweDAyZDQ7CiAgdC51cmFndXJtdWtoaSA9IDB4MGE3MzsKICB0LnVyaW5nID0gMHgwMTZmOwogIHQudXNob3J0Y3lyaWxsaWMgPSAweDA0NWU7CiAgdC51c21hbGxoaXJhZ2FuYSA9IDB4MzA0NTsKICB0LnVzbWFsbGthdGFrYW5hID0gMHgzMGE1OwogIHQudXNtYWxsa2F0YWthbmFoYWxmd2lkdGggPSAweGZmNjk7CiAgdC51c3RyYWlnaHRjeXJpbGxpYyA9IDB4MDRhZjsKICB0LnVzdHJhaWdodHN0cm9rZWN5cmlsbGljID0gMHgwNGIxOwogIHQudXRpbGRlID0gMHgwMTY5OwogIHQudXRpbGRlYWN1dGUgPSAweDFlNzk7CiAgdC51dGlsZGViZWxvdyA9IDB4MWU3NTsKICB0LnV1YmVuZ2FsaSA9IDB4MDk4YTsKICB0LnV1ZGV2YSA9IDB4MDkwYTsKICB0LnV1Z3VqYXJhdGkgPSAweDBhOGE7CiAgdC51dWd1cm11a2hpID0gMHgwYTBhOwogIHQudXVtYXRyYWd1cm11a2hpID0gMHgwYTQyOwogIHQudXV2b3dlbHNpZ25iZW5nYWxpID0gMHgwOWMyOwogIHQudXV2b3dlbHNpZ25kZXZhID0gMHgwOTQyOwogIHQudXV2b3dlbHNpZ25ndWphcmF0aSA9IDB4MGFjMjsKICB0LnV2b3dlbHNpZ25iZW5nYWxpID0gMHgwOWMxOwogIHQudXZvd2Vsc2lnbmRldmEgPSAweDA5NDE7CiAgdC51dm93ZWxzaWduZ3VqYXJhdGkgPSAweDBhYzE7CiAgdC52ID0gMHgwMDc2OwogIHQudmFkZXZhID0gMHgwOTM1OwogIHQudmFndWphcmF0aSA9IDB4MGFiNTsKICB0LnZhZ3VybXVraGkgPSAweDBhMzU7CiAgdC52YWthdGFrYW5hID0gMHgzMGY3OwogIHQudmF2ID0gMHgwNWQ1OwogIHQudmF2ZGFnZXNoID0gMHhmYjM1OwogIHQudmF2ZGFnZXNoNjUgPSAweGZiMzU7CiAgdC52YXZkYWdlc2hoZWJyZXcgPSAweGZiMzU7CiAgdC52YXZoZWJyZXcgPSAweDA1ZDU7CiAgdC52YXZob2xhbSA9IDB4ZmI0YjsKICB0LnZhdmhvbGFtaGVicmV3ID0gMHhmYjRiOwogIHQudmF2dmF2aGVicmV3ID0gMHgwNWYwOwogIHQudmF2eW9kaGVicmV3ID0gMHgwNWYxOwogIHQudmNpcmNsZSA9IDB4MjRlNTsKICB0LnZkb3RiZWxvdyA9IDB4MWU3ZjsKICB0LnZlY3lyaWxsaWMgPSAweDA0MzI7CiAgdC52ZWhhcmFiaWMgPSAweDA2YTQ7CiAgdC52ZWhmaW5hbGFyYWJpYyA9IDB4ZmI2YjsKICB0LnZlaGluaXRpYWxhcmFiaWMgPSAweGZiNmM7CiAgdC52ZWhtZWRpYWxhcmFiaWMgPSAweGZiNmQ7CiAgdC52ZWthdGFrYW5hID0gMHgzMGY5OwogIHQudmVudXMgPSAweDI2NDA7CiAgdC52ZXJ0aWNhbGJhciA9IDB4MDA3YzsKICB0LnZlcnRpY2FsbGluZWFib3ZlY21iID0gMHgwMzBkOwogIHQudmVydGljYWxsaW5lYmVsb3djbWIgPSAweDAzMjk7CiAgdC52ZXJ0aWNhbGxpbmVsb3dtb2QgPSAweDAyY2M7CiAgdC52ZXJ0aWNhbGxpbmVtb2QgPSAweDAyYzg7CiAgdC52ZXdhcm1lbmlhbiA9IDB4MDU3ZTsKICB0LnZob29rID0gMHgwMjhiOwogIHQudmlrYXRha2FuYSA9IDB4MzBmODsKICB0LnZpcmFtYWJlbmdhbGkgPSAweDA5Y2Q7CiAgdC52aXJhbWFkZXZhID0gMHgwOTRkOwogIHQudmlyYW1hZ3VqYXJhdGkgPSAweDBhY2Q7CiAgdC52aXNhcmdhYmVuZ2FsaSA9IDB4MDk4MzsKICB0LnZpc2FyZ2FkZXZhID0gMHgwOTAzOwogIHQudmlzYXJnYWd1amFyYXRpID0gMHgwYTgzOwogIHQudm1vbm9zcGFjZSA9IDB4ZmY1NjsKICB0LnZvYXJtZW5pYW4gPSAweDA1Nzg7CiAgdC52b2ljZWRpdGVyYXRpb25oaXJhZ2FuYSA9IDB4MzA5ZTsKICB0LnZvaWNlZGl0ZXJhdGlvbmthdGFrYW5hID0gMHgzMGZlOwogIHQudm9pY2VkbWFya2thbmEgPSAweDMwOWI7CiAgdC52b2ljZWRtYXJra2FuYWhhbGZ3aWR0aCA9IDB4ZmY5ZTsKICB0LnZva2F0YWthbmEgPSAweDMwZmE7CiAgdC52cGFyZW4gPSAweDI0YjE7CiAgdC52dGlsZGUgPSAweDFlN2Q7CiAgdC52dHVybmVkID0gMHgwMjhjOwogIHQudnVoaXJhZ2FuYSA9IDB4MzA5NDsKICB0LnZ1a2F0YWthbmEgPSAweDMwZjQ7CiAgdC53ID0gMHgwMDc3OwogIHQud2FjdXRlID0gMHgxZTgzOwogIHQud2Fla29yZWFuID0gMHgzMTU5OwogIHQud2FoaXJhZ2FuYSA9IDB4MzA4ZjsKICB0Lndha2F0YWthbmEgPSAweDMwZWY7CiAgdC53YWthdGFrYW5haGFsZndpZHRoID0gMHhmZjljOwogIHQud2Frb3JlYW4gPSAweDMxNTg7CiAgdC53YXNtYWxsaGlyYWdhbmEgPSAweDMwOGU7CiAgdC53YXNtYWxsa2F0YWthbmEgPSAweDMwZWU7CiAgdC53YXR0b3NxdWFyZSA9IDB4MzM1NzsKICB0LndhdmVkYXNoID0gMHgzMDFjOwogIHQud2F2eXVuZGVyc2NvcmV2ZXJ0aWNhbCA9IDB4ZmUzNDsKICB0Lndhd2FyYWJpYyA9IDB4MDY0ODsKICB0Lndhd2ZpbmFsYXJhYmljID0gMHhmZWVlOwogIHQud2F3aGFtemFhYm92ZWFyYWJpYyA9IDB4MDYyNDsKICB0Lndhd2hhbXphYWJvdmVmaW5hbGFyYWJpYyA9IDB4ZmU4NjsKICB0Lndic3F1YXJlID0gMHgzM2RkOwogIHQud2NpcmNsZSA9IDB4MjRlNjsKICB0LndjaXJjdW1mbGV4ID0gMHgwMTc1OwogIHQud2RpZXJlc2lzID0gMHgxZTg1OwogIHQud2RvdGFjY2VudCA9IDB4MWU4NzsKICB0Lndkb3RiZWxvdyA9IDB4MWU4OTsKICB0LndlaGlyYWdhbmEgPSAweDMwOTE7CiAgdC53ZWllcnN0cmFzcyA9IDB4MjExODsKICB0Lndla2F0YWthbmEgPSAweDMwZjE7CiAgdC53ZWtvcmVhbiA9IDB4MzE1ZTsKICB0Lndlb2tvcmVhbiA9IDB4MzE1ZDsKICB0LndncmF2ZSA9IDB4MWU4MTsKICB0LndoaXRlYnVsbGV0ID0gMHgyNWU2OwogIHQud2hpdGVjaXJjbGUgPSAweDI1Y2I7CiAgdC53aGl0ZWNpcmNsZWludmVyc2UgPSAweDI1ZDk7CiAgdC53aGl0ZWNvcm5lcmJyYWNrZXRsZWZ0ID0gMHgzMDBlOwogIHQud2hpdGVjb3JuZXJicmFja2V0bGVmdHZlcnRpY2FsID0gMHhmZTQzOwogIHQud2hpdGVjb3JuZXJicmFja2V0cmlnaHQgPSAweDMwMGY7CiAgdC53aGl0ZWNvcm5lcmJyYWNrZXRyaWdodHZlcnRpY2FsID0gMHhmZTQ0OwogIHQud2hpdGVkaWFtb25kID0gMHgyNWM3OwogIHQud2hpdGVkaWFtb25kY29udGFpbmluZ2JsYWNrc21hbGxkaWFtb25kID0gMHgyNWM4OwogIHQud2hpdGVkb3ducG9pbnRpbmdzbWFsbHRyaWFuZ2xlID0gMHgyNWJmOwogIHQud2hpdGVkb3ducG9pbnRpbmd0cmlhbmdsZSA9IDB4MjViZDsKICB0LndoaXRlbGVmdHBvaW50aW5nc21hbGx0cmlhbmdsZSA9IDB4MjVjMzsKICB0LndoaXRlbGVmdHBvaW50aW5ndHJpYW5nbGUgPSAweDI1YzE7CiAgdC53aGl0ZWxlbnRpY3VsYXJicmFja2V0bGVmdCA9IDB4MzAxNjsKICB0LndoaXRlbGVudGljdWxhcmJyYWNrZXRyaWdodCA9IDB4MzAxNzsKICB0LndoaXRlcmlnaHRwb2ludGluZ3NtYWxsdHJpYW5nbGUgPSAweDI1Yjk7CiAgdC53aGl0ZXJpZ2h0cG9pbnRpbmd0cmlhbmdsZSA9IDB4MjViNzsKICB0LndoaXRlc21hbGxzcXVhcmUgPSAweDI1YWI7CiAgdC53aGl0ZXNtaWxpbmdmYWNlID0gMHgyNjNhOwogIHQud2hpdGVzcXVhcmUgPSAweDI1YTE7CiAgdC53aGl0ZXN0YXIgPSAweDI2MDY7CiAgdC53aGl0ZXRlbGVwaG9uZSA9IDB4MjYwZjsKICB0LndoaXRldG9ydG9pc2VzaGVsbGJyYWNrZXRsZWZ0ID0gMHgzMDE4OwogIHQud2hpdGV0b3J0b2lzZXNoZWxsYnJhY2tldHJpZ2h0ID0gMHgzMDE5OwogIHQud2hpdGV1cHBvaW50aW5nc21hbGx0cmlhbmdsZSA9IDB4MjViNTsKICB0LndoaXRldXBwb2ludGluZ3RyaWFuZ2xlID0gMHgyNWIzOwogIHQud2loaXJhZ2FuYSA9IDB4MzA5MDsKICB0Lndpa2F0YWthbmEgPSAweDMwZjA7CiAgdC53aWtvcmVhbiA9IDB4MzE1ZjsKICB0Lndtb25vc3BhY2UgPSAweGZmNTc7CiAgdC53b2hpcmFnYW5hID0gMHgzMDkyOwogIHQud29rYXRha2FuYSA9IDB4MzBmMjsKICB0Lndva2F0YWthbmFoYWxmd2lkdGggPSAweGZmNjY7CiAgdC53b24gPSAweDIwYTk7CiAgdC53b25tb25vc3BhY2UgPSAweGZmZTY7CiAgdC53b3dhZW50aGFpID0gMHgwZTI3OwogIHQud3BhcmVuID0gMHgyNGIyOwogIHQud3JpbmcgPSAweDFlOTg7CiAgdC53c3VwZXJpb3IgPSAweDAyYjc7CiAgdC53dHVybmVkID0gMHgwMjhkOwogIHQud3lubiA9IDB4MDFiZjsKICB0LnggPSAweDAwNzg7CiAgdC54YWJvdmVjbWIgPSAweDAzM2Q7CiAgdC54Ym9wb21vZm8gPSAweDMxMTI7CiAgdC54Y2lyY2xlID0gMHgyNGU3OwogIHQueGRpZXJlc2lzID0gMHgxZThkOwogIHQueGRvdGFjY2VudCA9IDB4MWU4YjsKICB0LnhlaGFybWVuaWFuID0gMHgwNTZkOwogIHQueGkgPSAweDAzYmU7CiAgdC54bW9ub3NwYWNlID0gMHhmZjU4OwogIHQueHBhcmVuID0gMHgyNGIzOwogIHQueHN1cGVyaW9yID0gMHgwMmUzOwogIHQueSA9IDB4MDA3OTsKICB0LnlhYWRvc3F1YXJlID0gMHgzMzRlOwogIHQueWFiZW5nYWxpID0gMHgwOWFmOwogIHQueWFjdXRlID0gMHgwMGZkOwogIHQueWFkZXZhID0gMHgwOTJmOwogIHQueWFla29yZWFuID0gMHgzMTUyOwogIHQueWFndWphcmF0aSA9IDB4MGFhZjsKICB0LnlhZ3VybXVraGkgPSAweDBhMmY7CiAgdC55YWhpcmFnYW5hID0gMHgzMDg0OwogIHQueWFrYXRha2FuYSA9IDB4MzBlNDsKICB0Lnlha2F0YWthbmFoYWxmd2lkdGggPSAweGZmOTQ7CiAgdC55YWtvcmVhbiA9IDB4MzE1MTsKICB0LnlhbWFra2FudGhhaSA9IDB4MGU0ZTsKICB0Lnlhc21hbGxoaXJhZ2FuYSA9IDB4MzA4MzsKICB0Lnlhc21hbGxrYXRha2FuYSA9IDB4MzBlMzsKICB0Lnlhc21hbGxrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY2YzsKICB0LnlhdGN5cmlsbGljID0gMHgwNDYzOwogIHQueWNpcmNsZSA9IDB4MjRlODsKICB0LnljaXJjdW1mbGV4ID0gMHgwMTc3OwogIHQueWRpZXJlc2lzID0gMHgwMGZmOwogIHQueWRvdGFjY2VudCA9IDB4MWU4ZjsKICB0Lnlkb3RiZWxvdyA9IDB4MWVmNTsKICB0LnllaGFyYWJpYyA9IDB4MDY0YTsKICB0LnllaGJhcnJlZWFyYWJpYyA9IDB4MDZkMjsKICB0LnllaGJhcnJlZWZpbmFsYXJhYmljID0gMHhmYmFmOwogIHQueWVoZmluYWxhcmFiaWMgPSAweGZlZjI7CiAgdC55ZWhoYW16YWFib3ZlYXJhYmljID0gMHgwNjI2OwogIHQueWVoaGFtemFhYm92ZWZpbmFsYXJhYmljID0gMHhmZThhOwogIHQueWVoaGFtemFhYm92ZWluaXRpYWxhcmFiaWMgPSAweGZlOGI7CiAgdC55ZWhoYW16YWFib3ZlbWVkaWFsYXJhYmljID0gMHhmZThjOwogIHQueWVoaW5pdGlhbGFyYWJpYyA9IDB4ZmVmMzsKICB0LnllaG1lZGlhbGFyYWJpYyA9IDB4ZmVmNDsKICB0LnllaG1lZW1pbml0aWFsYXJhYmljID0gMHhmY2RkOwogIHQueWVobWVlbWlzb2xhdGVkYXJhYmljID0gMHhmYzU4OwogIHQueWVobm9vbmZpbmFsYXJhYmljID0gMHhmYzk0OwogIHQueWVodGhyZWVkb3RzYmVsb3dhcmFiaWMgPSAweDA2ZDE7CiAgdC55ZWtvcmVhbiA9IDB4MzE1NjsKICB0LnllbiA9IDB4MDBhNTsKICB0Lnllbm1vbm9zcGFjZSA9IDB4ZmZlNTsKICB0Lnllb2tvcmVhbiA9IDB4MzE1NTsKICB0Lnllb3JpbmhpZXVoa29yZWFuID0gMHgzMTg2OwogIHQueWVyYWhiZW55b21vaGVicmV3ID0gMHgwNWFhOwogIHQueWVyYWhiZW55b21vbGVmdGhlYnJldyA9IDB4MDVhYTsKICB0LnllcmljeXJpbGxpYyA9IDB4MDQ0YjsKICB0LnllcnVkaWVyZXNpc2N5cmlsbGljID0gMHgwNGY5OwogIHQueWVzaWV1bmdrb3JlYW4gPSAweDMxODE7CiAgdC55ZXNpZXVuZ3BhbnNpb3Nrb3JlYW4gPSAweDMxODM7CiAgdC55ZXNpZXVuZ3Npb3Nrb3JlYW4gPSAweDMxODI7CiAgdC55ZXRpdmhlYnJldyA9IDB4MDU5YTsKICB0LnlncmF2ZSA9IDB4MWVmMzsKICB0Lnlob29rID0gMHgwMWI0OwogIHQueWhvb2thYm92ZSA9IDB4MWVmNzsKICB0LnlpYXJtZW5pYW4gPSAweDA1NzU7CiAgdC55aWN5cmlsbGljID0gMHgwNDU3OwogIHQueWlrb3JlYW4gPSAweDMxNjI7CiAgdC55aW55YW5nID0gMHgyNjJmOwogIHQueWl3bmFybWVuaWFuID0gMHgwNTgyOwogIHQueW1vbm9zcGFjZSA9IDB4ZmY1OTsKICB0LnlvZCA9IDB4MDVkOTsKICB0LnlvZGRhZ2VzaCA9IDB4ZmIzOTsKICB0LnlvZGRhZ2VzaGhlYnJldyA9IDB4ZmIzOTsKICB0LnlvZGhlYnJldyA9IDB4MDVkOTsKICB0LnlvZHlvZGhlYnJldyA9IDB4MDVmMjsKICB0LnlvZHlvZHBhdGFoaGVicmV3ID0gMHhmYjFmOwogIHQueW9oaXJhZ2FuYSA9IDB4MzA4ODsKICB0LnlvaWtvcmVhbiA9IDB4MzE4OTsKICB0Lnlva2F0YWthbmEgPSAweDMwZTg7CiAgdC55b2thdGFrYW5haGFsZndpZHRoID0gMHhmZjk2OwogIHQueW9rb3JlYW4gPSAweDMxNWI7CiAgdC55b3NtYWxsaGlyYWdhbmEgPSAweDMwODc7CiAgdC55b3NtYWxsa2F0YWthbmEgPSAweDMwZTc7CiAgdC55b3NtYWxsa2F0YWthbmFoYWxmd2lkdGggPSAweGZmNmU7CiAgdC55b3RncmVlayA9IDB4MDNmMzsKICB0LnlveWFla29yZWFuID0gMHgzMTg4OwogIHQueW95YWtvcmVhbiA9IDB4MzE4NzsKICB0LnlveWFrdGhhaSA9IDB4MGUyMjsKICB0LnlveWluZ3RoYWkgPSAweDBlMGQ7CiAgdC55cGFyZW4gPSAweDI0YjQ7CiAgdC55cG9nZWdyYW1tZW5pID0gMHgwMzdhOwogIHQueXBvZ2VncmFtbWVuaWdyZWVrY21iID0gMHgwMzQ1OwogIHQueXIgPSAweDAxYTY7CiAgdC55cmluZyA9IDB4MWU5OTsKICB0LnlzdXBlcmlvciA9IDB4MDJiODsKICB0Lnl0aWxkZSA9IDB4MWVmOTsKICB0Lnl0dXJuZWQgPSAweDAyOGU7CiAgdC55dWhpcmFnYW5hID0gMHgzMDg2OwogIHQueXVpa29yZWFuID0gMHgzMThjOwogIHQueXVrYXRha2FuYSA9IDB4MzBlNjsKICB0Lnl1a2F0YWthbmFoYWxmd2lkdGggPSAweGZmOTU7CiAgdC55dWtvcmVhbiA9IDB4MzE2MDsKICB0Lnl1c2JpZ2N5cmlsbGljID0gMHgwNDZiOwogIHQueXVzYmlnaW90aWZpZWRjeXJpbGxpYyA9IDB4MDQ2ZDsKICB0Lnl1c2xpdHRsZWN5cmlsbGljID0gMHgwNDY3OwogIHQueXVzbGl0dGxlaW90aWZpZWRjeXJpbGxpYyA9IDB4MDQ2OTsKICB0Lnl1c21hbGxoaXJhZ2FuYSA9IDB4MzA4NTsKICB0Lnl1c21hbGxrYXRha2FuYSA9IDB4MzBlNTsKICB0Lnl1c21hbGxrYXRha2FuYWhhbGZ3aWR0aCA9IDB4ZmY2ZDsKICB0Lnl1eWVrb3JlYW4gPSAweDMxOGI7CiAgdC55dXllb2tvcmVhbiA9IDB4MzE4YTsKICB0Lnl5YWJlbmdhbGkgPSAweDA5ZGY7CiAgdC55eWFkZXZhID0gMHgwOTVmOwogIHQueiA9IDB4MDA3YTsKICB0LnphYXJtZW5pYW4gPSAweDA1NjY7CiAgdC56YWN1dGUgPSAweDAxN2E7CiAgdC56YWRldmEgPSAweDA5NWI7CiAgdC56YWd1cm11a2hpID0gMHgwYTViOwogIHQuemFoYXJhYmljID0gMHgwNjM4OwogIHQuemFoZmluYWxhcmFiaWMgPSAweGZlYzY7CiAgdC56YWhpbml0aWFsYXJhYmljID0gMHhmZWM3OwogIHQuemFoaXJhZ2FuYSA9IDB4MzA1NjsKICB0LnphaG1lZGlhbGFyYWJpYyA9IDB4ZmVjODsKICB0LnphaW5hcmFiaWMgPSAweDA2MzI7CiAgdC56YWluZmluYWxhcmFiaWMgPSAweGZlYjA7CiAgdC56YWthdGFrYW5hID0gMHgzMGI2OwogIHQuemFxZWZnYWRvbGhlYnJldyA9IDB4MDU5NTsKICB0LnphcWVmcWF0YW5oZWJyZXcgPSAweDA1OTQ7CiAgdC56YXJxYWhlYnJldyA9IDB4MDU5ODsKICB0LnpheWluID0gMHgwNWQ2OwogIHQuemF5aW5kYWdlc2ggPSAweGZiMzY7CiAgdC56YXlpbmRhZ2VzaGhlYnJldyA9IDB4ZmIzNjsKICB0LnpheWluaGVicmV3ID0gMHgwNWQ2OwogIHQuemJvcG9tb2ZvID0gMHgzMTE3OwogIHQuemNhcm9uID0gMHgwMTdlOwogIHQuemNpcmNsZSA9IDB4MjRlOTsKICB0LnpjaXJjdW1mbGV4ID0gMHgxZTkxOwogIHQuemN1cmwgPSAweDAyOTE7CiAgdC56ZG90ID0gMHgwMTdjOwogIHQuemRvdGFjY2VudCA9IDB4MDE3YzsKICB0Lnpkb3RiZWxvdyA9IDB4MWU5MzsKICB0LnplY3lyaWxsaWMgPSAweDA0Mzc7CiAgdC56ZWRlc2NlbmRlcmN5cmlsbGljID0gMHgwNDk5OwogIHQuemVkaWVyZXNpc2N5cmlsbGljID0gMHgwNGRmOwogIHQuemVoaXJhZ2FuYSA9IDB4MzA1YzsKICB0Lnpla2F0YWthbmEgPSAweDMwYmM7CiAgdC56ZXJvID0gMHgwMDMwOwogIHQuemVyb2FyYWJpYyA9IDB4MDY2MDsKICB0Lnplcm9iZW5nYWxpID0gMHgwOWU2OwogIHQuemVyb2RldmEgPSAweDA5NjY7CiAgdC56ZXJvZ3VqYXJhdGkgPSAweDBhZTY7CiAgdC56ZXJvZ3VybXVraGkgPSAweDBhNjY7CiAgdC56ZXJvaGFja2FyYWJpYyA9IDB4MDY2MDsKICB0Lnplcm9pbmZlcmlvciA9IDB4MjA4MDsKICB0Lnplcm9tb25vc3BhY2UgPSAweGZmMTA7CiAgdC56ZXJvb2xkc3R5bGUgPSAweGY3MzA7CiAgdC56ZXJvcGVyc2lhbiA9IDB4MDZmMDsKICB0Lnplcm9zdXBlcmlvciA9IDB4MjA3MDsKICB0Lnplcm90aGFpID0gMHgwZTUwOwogIHQuemVyb3dpZHRoam9pbmVyID0gMHhmZWZmOwogIHQuemVyb3dpZHRobm9uam9pbmVyID0gMHgyMDBjOwogIHQuemVyb3dpZHRoc3BhY2UgPSAweDIwMGI7CiAgdC56ZXRhID0gMHgwM2I2OwogIHQuemhib3BvbW9mbyA9IDB4MzExMzsKICB0LnpoZWFybWVuaWFuID0gMHgwNTZhOwogIHQuemhlYnJldmVjeXJpbGxpYyA9IDB4MDRjMjsKICB0LnpoZWN5cmlsbGljID0gMHgwNDM2OwogIHQuemhlZGVzY2VuZGVyY3lyaWxsaWMgPSAweDA0OTc7CiAgdC56aGVkaWVyZXNpc2N5cmlsbGljID0gMHgwNGRkOwogIHQuemloaXJhZ2FuYSA9IDB4MzA1ODsKICB0Lnppa2F0YWthbmEgPSAweDMwYjg7CiAgdC56aW5vcmhlYnJldyA9IDB4MDVhZTsKICB0LnpsaW5lYmVsb3cgPSAweDFlOTU7CiAgdC56bW9ub3NwYWNlID0gMHhmZjVhOwogIHQuem9oaXJhZ2FuYSA9IDB4MzA1ZTsKICB0Lnpva2F0YWthbmEgPSAweDMwYmU7CiAgdC56cGFyZW4gPSAweDI0YjU7CiAgdC56cmV0cm9mbGV4aG9vayA9IDB4MDI5MDsKICB0LnpzdHJva2UgPSAweDAxYjY7CiAgdC56dWhpcmFnYW5hID0gMHgzMDVhOwogIHQuenVrYXRha2FuYSA9IDB4MzBiYTsKICB0WyIubm90ZGVmIl0gPSAweDAwMDA7CiAgdC5hbmdicmFja2V0bGVmdGJpZyA9IDB4MjMyOTsKICB0LmFuZ2JyYWNrZXRsZWZ0QmlnID0gMHgyMzI5OwogIHQuYW5nYnJhY2tldGxlZnRiaWdnID0gMHgyMzI5OwogIHQuYW5nYnJhY2tldGxlZnRCaWdnID0gMHgyMzI5OwogIHQuYW5nYnJhY2tldHJpZ2h0QmlnID0gMHgyMzJhOwogIHQuYW5nYnJhY2tldHJpZ2h0YmlnID0gMHgyMzJhOwogIHQuYW5nYnJhY2tldHJpZ2h0QmlnZyA9IDB4MjMyYTsKICB0LmFuZ2JyYWNrZXRyaWdodGJpZ2cgPSAweDIzMmE7CiAgdC5hcnJvd2hvb2tsZWZ0ID0gMHgyMWFhOwogIHQuYXJyb3dob29rcmlnaHQgPSAweDIxYTk7CiAgdC5hcnJvd2xlZnR0b3BoYWxmID0gMHgyMWJjOwogIHQuYXJyb3dsZWZ0Ym90aGFsZiA9IDB4MjFiZDsKICB0LmFycm93bm9ydGhlYXN0ID0gMHgyMTk3OwogIHQuYXJyb3dub3J0aHdlc3QgPSAweDIxOTY7CiAgdC5hcnJvd3JpZ2h0dG9waGFsZiA9IDB4MjFjMDsKICB0LmFycm93cmlnaHRib3RoYWxmID0gMHgyMWMxOwogIHQuYXJyb3dzb3V0aGVhc3QgPSAweDIxOTg7CiAgdC5hcnJvd3NvdXRod2VzdCA9IDB4MjE5OTsKICB0LmJhY2tzbGFzaGJpZyA9IDB4MjIxNjsKICB0LmJhY2tzbGFzaEJpZyA9IDB4MjIxNjsKICB0LmJhY2tzbGFzaEJpZ2cgPSAweDIyMTY7CiAgdC5iYWNrc2xhc2hiaWdnID0gMHgyMjE2OwogIHQuYmFyZGJsID0gMHgyMDE2OwogIHQuYnJhY2VodGlwZG93bmxlZnQgPSAweGZlMzc7CiAgdC5icmFjZWh0aXBkb3ducmlnaHQgPSAweGZlMzc7CiAgdC5icmFjZWh0aXB1cGxlZnQgPSAweGZlMzg7CiAgdC5icmFjZWh0aXB1cHJpZ2h0ID0gMHhmZTM4OwogIHQuYnJhY2VsZWZ0QmlnID0gMHgwMDdiOwogIHQuYnJhY2VsZWZ0YmlnID0gMHgwMDdiOwogIHQuYnJhY2VsZWZ0YmlnZyA9IDB4MDA3YjsKICB0LmJyYWNlbGVmdEJpZ2cgPSAweDAwN2I7CiAgdC5icmFjZXJpZ2h0QmlnID0gMHgwMDdkOwogIHQuYnJhY2VyaWdodGJpZyA9IDB4MDA3ZDsKICB0LmJyYWNlcmlnaHRiaWdnID0gMHgwMDdkOwogIHQuYnJhY2VyaWdodEJpZ2cgPSAweDAwN2Q7CiAgdC5icmFja2V0bGVmdGJpZyA9IDB4MDA1YjsKICB0LmJyYWNrZXRsZWZ0QmlnID0gMHgwMDViOwogIHQuYnJhY2tldGxlZnRiaWdnID0gMHgwMDViOwogIHQuYnJhY2tldGxlZnRCaWdnID0gMHgwMDViOwogIHQuYnJhY2tldHJpZ2h0QmlnID0gMHgwMDVkOwogIHQuYnJhY2tldHJpZ2h0YmlnID0gMHgwMDVkOwogIHQuYnJhY2tldHJpZ2h0YmlnZyA9IDB4MDA1ZDsKICB0LmJyYWNrZXRyaWdodEJpZ2cgPSAweDAwNWQ7CiAgdC5jZWlsaW5nbGVmdGJpZyA9IDB4MjMwODsKICB0LmNlaWxpbmdsZWZ0QmlnID0gMHgyMzA4OwogIHQuY2VpbGluZ2xlZnRCaWdnID0gMHgyMzA4OwogIHQuY2VpbGluZ2xlZnRiaWdnID0gMHgyMzA4OwogIHQuY2VpbGluZ3JpZ2h0YmlnID0gMHgyMzA5OwogIHQuY2VpbGluZ3JpZ2h0QmlnID0gMHgyMzA5OwogIHQuY2VpbGluZ3JpZ2h0YmlnZyA9IDB4MjMwOTsKICB0LmNlaWxpbmdyaWdodEJpZ2cgPSAweDIzMDk7CiAgdC5jaXJjbGVkb3RkaXNwbGF5ID0gMHgyMjk5OwogIHQuY2lyY2xlZG90dGV4dCA9IDB4MjI5OTsKICB0LmNpcmNsZW11bHRpcGx5ZGlzcGxheSA9IDB4MjI5NzsKICB0LmNpcmNsZW11bHRpcGx5dGV4dCA9IDB4MjI5NzsKICB0LmNpcmNsZXBsdXNkaXNwbGF5ID0gMHgyMjk1OwogIHQuY2lyY2xlcGx1c3RleHQgPSAweDIyOTU7CiAgdC5jb250aW50ZWdyYWxkaXNwbGF5ID0gMHgyMjJlOwogIHQuY29udGludGVncmFsdGV4dCA9IDB4MjIyZTsKICB0LmNvcHJvZHVjdGRpc3BsYXkgPSAweDIyMTA7CiAgdC5jb3Byb2R1Y3R0ZXh0ID0gMHgyMjEwOwogIHQuZmxvb3JsZWZ0QmlnID0gMHgyMzBhOwogIHQuZmxvb3JsZWZ0YmlnID0gMHgyMzBhOwogIHQuZmxvb3JsZWZ0YmlnZyA9IDB4MjMwYTsKICB0LmZsb29ybGVmdEJpZ2cgPSAweDIzMGE7CiAgdC5mbG9vcnJpZ2h0YmlnID0gMHgyMzBiOwogIHQuZmxvb3JyaWdodEJpZyA9IDB4MjMwYjsKICB0LmZsb29ycmlnaHRCaWdnID0gMHgyMzBiOwogIHQuZmxvb3JyaWdodGJpZ2cgPSAweDIzMGI7CiAgdC5oYXR3aWRlID0gMHgwMzAyOwogIHQuaGF0d2lkZXIgPSAweDAzMDI7CiAgdC5oYXR3aWRlc3QgPSAweDAzMDI7CiAgdC5pbnRlcmNhbCA9IDB4MWQ0MDsKICB0LmludGVncmFsZGlzcGxheSA9IDB4MjIyYjsKICB0LmludGVncmFsdGV4dCA9IDB4MjIyYjsKICB0LmludGVyc2VjdGlvbmRpc3BsYXkgPSAweDIyYzI7CiAgdC5pbnRlcnNlY3Rpb250ZXh0ID0gMHgyMmMyOwogIHQubG9naWNhbGFuZGRpc3BsYXkgPSAweDIyMjc7CiAgdC5sb2dpY2FsYW5kdGV4dCA9IDB4MjIyNzsKICB0LmxvZ2ljYWxvcmRpc3BsYXkgPSAweDIyMjg7CiAgdC5sb2dpY2Fsb3J0ZXh0ID0gMHgyMjI4OwogIHQucGFyZW5sZWZ0QmlnID0gMHgwMDI4OwogIHQucGFyZW5sZWZ0YmlnID0gMHgwMDI4OwogIHQucGFyZW5sZWZ0QmlnZyA9IDB4MDAyODsKICB0LnBhcmVubGVmdGJpZ2cgPSAweDAwMjg7CiAgdC5wYXJlbnJpZ2h0QmlnID0gMHgwMDI5OwogIHQucGFyZW5yaWdodGJpZyA9IDB4MDAyOTsKICB0LnBhcmVucmlnaHRCaWdnID0gMHgwMDI5OwogIHQucGFyZW5yaWdodGJpZ2cgPSAweDAwMjk7CiAgdC5wcmltZSA9IDB4MjAzMjsKICB0LnByb2R1Y3RkaXNwbGF5ID0gMHgyMjBmOwogIHQucHJvZHVjdHRleHQgPSAweDIyMGY7CiAgdC5yYWRpY2FsYmlnID0gMHgyMjFhOwogIHQucmFkaWNhbEJpZyA9IDB4MjIxYTsKICB0LnJhZGljYWxCaWdnID0gMHgyMjFhOwogIHQucmFkaWNhbGJpZ2cgPSAweDIyMWE7CiAgdC5yYWRpY2FsYnQgPSAweDIyMWE7CiAgdC5yYWRpY2FsdHAgPSAweDIyMWE7CiAgdC5yYWRpY2FsdmVydGV4ID0gMHgyMjFhOwogIHQuc2xhc2hiaWcgPSAweDAwMmY7CiAgdC5zbGFzaEJpZyA9IDB4MDAyZjsKICB0LnNsYXNoQmlnZyA9IDB4MDAyZjsKICB0LnNsYXNoYmlnZyA9IDB4MDAyZjsKICB0LnN1bW1hdGlvbmRpc3BsYXkgPSAweDIyMTE7CiAgdC5zdW1tYXRpb250ZXh0ID0gMHgyMjExOwogIHQudGlsZGV3aWRlID0gMHgwMmRjOwogIHQudGlsZGV3aWRlciA9IDB4MDJkYzsKICB0LnRpbGRld2lkZXN0ID0gMHgwMmRjOwogIHQudW5pb25kaXNwbGF5ID0gMHgyMmMzOwogIHQudW5pb25tdWx0aWRpc3BsYXkgPSAweDIyOGU7CiAgdC51bmlvbm11bHRpdGV4dCA9IDB4MjI4ZTsKICB0LnVuaW9uc3FkaXNwbGF5ID0gMHgyMjk0OwogIHQudW5pb25zcXRleHQgPSAweDIyOTQ7CiAgdC51bmlvbnRleHQgPSAweDIyYzM7CiAgdC52ZXh0ZW5kZG91YmxlID0gMHgyMjI1OwogIHQudmV4dGVuZHNpbmdsZSA9IDB4MjIyMzsKfSk7CmNvbnN0IGdldERpbmdiYXRzR2x5cGhzVW5pY29kZSA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogIHQuc3BhY2UgPSAweDAwMjA7CiAgdC5hMSA9IDB4MjcwMTsKICB0LmEyID0gMHgyNzAyOwogIHQuYTIwMiA9IDB4MjcwMzsKICB0LmEzID0gMHgyNzA0OwogIHQuYTQgPSAweDI2MGU7CiAgdC5hNSA9IDB4MjcwNjsKICB0LmExMTkgPSAweDI3MDc7CiAgdC5hMTE4ID0gMHgyNzA4OwogIHQuYTExNyA9IDB4MjcwOTsKICB0LmExMSA9IDB4MjYxYjsKICB0LmExMiA9IDB4MjYxZTsKICB0LmExMyA9IDB4MjcwYzsKICB0LmExNCA9IDB4MjcwZDsKICB0LmExNSA9IDB4MjcwZTsKICB0LmExNiA9IDB4MjcwZjsKICB0LmExMDUgPSAweDI3MTA7CiAgdC5hMTcgPSAweDI3MTE7CiAgdC5hMTggPSAweDI3MTI7CiAgdC5hMTkgPSAweDI3MTM7CiAgdC5hMjAgPSAweDI3MTQ7CiAgdC5hMjEgPSAweDI3MTU7CiAgdC5hMjIgPSAweDI3MTY7CiAgdC5hMjMgPSAweDI3MTc7CiAgdC5hMjQgPSAweDI3MTg7CiAgdC5hMjUgPSAweDI3MTk7CiAgdC5hMjYgPSAweDI3MWE7CiAgdC5hMjcgPSAweDI3MWI7CiAgdC5hMjggPSAweDI3MWM7CiAgdC5hNiA9IDB4MjcxZDsKICB0LmE3ID0gMHgyNzFlOwogIHQuYTggPSAweDI3MWY7CiAgdC5hOSA9IDB4MjcyMDsKICB0LmExMCA9IDB4MjcyMTsKICB0LmEyOSA9IDB4MjcyMjsKICB0LmEzMCA9IDB4MjcyMzsKICB0LmEzMSA9IDB4MjcyNDsKICB0LmEzMiA9IDB4MjcyNTsKICB0LmEzMyA9IDB4MjcyNjsKICB0LmEzNCA9IDB4MjcyNzsKICB0LmEzNSA9IDB4MjYwNTsKICB0LmEzNiA9IDB4MjcyOTsKICB0LmEzNyA9IDB4MjcyYTsKICB0LmEzOCA9IDB4MjcyYjsKICB0LmEzOSA9IDB4MjcyYzsKICB0LmE0MCA9IDB4MjcyZDsKICB0LmE0MSA9IDB4MjcyZTsKICB0LmE0MiA9IDB4MjcyZjsKICB0LmE0MyA9IDB4MjczMDsKICB0LmE0NCA9IDB4MjczMTsKICB0LmE0NSA9IDB4MjczMjsKICB0LmE0NiA9IDB4MjczMzsKICB0LmE0NyA9IDB4MjczNDsKICB0LmE0OCA9IDB4MjczNTsKICB0LmE0OSA9IDB4MjczNjsKICB0LmE1MCA9IDB4MjczNzsKICB0LmE1MSA9IDB4MjczODsKICB0LmE1MiA9IDB4MjczOTsKICB0LmE1MyA9IDB4MjczYTsKICB0LmE1NCA9IDB4MjczYjsKICB0LmE1NSA9IDB4MjczYzsKICB0LmE1NiA9IDB4MjczZDsKICB0LmE1NyA9IDB4MjczZTsKICB0LmE1OCA9IDB4MjczZjsKICB0LmE1OSA9IDB4Mjc0MDsKICB0LmE2MCA9IDB4Mjc0MTsKICB0LmE2MSA9IDB4Mjc0MjsKICB0LmE2MiA9IDB4Mjc0MzsKICB0LmE2MyA9IDB4Mjc0NDsKICB0LmE2NCA9IDB4Mjc0NTsKICB0LmE2NSA9IDB4Mjc0NjsKICB0LmE2NiA9IDB4Mjc0NzsKICB0LmE2NyA9IDB4Mjc0ODsKICB0LmE2OCA9IDB4Mjc0OTsKICB0LmE2OSA9IDB4Mjc0YTsKICB0LmE3MCA9IDB4Mjc0YjsKICB0LmE3MSA9IDB4MjVjZjsKICB0LmE3MiA9IDB4Mjc0ZDsKICB0LmE3MyA9IDB4MjVhMDsKICB0LmE3NCA9IDB4Mjc0ZjsKICB0LmEyMDMgPSAweDI3NTA7CiAgdC5hNzUgPSAweDI3NTE7CiAgdC5hMjA0ID0gMHgyNzUyOwogIHQuYTc2ID0gMHgyNWIyOwogIHQuYTc3ID0gMHgyNWJjOwogIHQuYTc4ID0gMHgyNWM2OwogIHQuYTc5ID0gMHgyNzU2OwogIHQuYTgxID0gMHgyNWQ3OwogIHQuYTgyID0gMHgyNzU4OwogIHQuYTgzID0gMHgyNzU5OwogIHQuYTg0ID0gMHgyNzVhOwogIHQuYTk3ID0gMHgyNzViOwogIHQuYTk4ID0gMHgyNzVjOwogIHQuYTk5ID0gMHgyNzVkOwogIHQuYTEwMCA9IDB4Mjc1ZTsKICB0LmExMDEgPSAweDI3NjE7CiAgdC5hMTAyID0gMHgyNzYyOwogIHQuYTEwMyA9IDB4Mjc2MzsKICB0LmExMDQgPSAweDI3NjQ7CiAgdC5hMTA2ID0gMHgyNzY1OwogIHQuYTEwNyA9IDB4Mjc2NjsKICB0LmExMDggPSAweDI3Njc7CiAgdC5hMTEyID0gMHgyNjYzOwogIHQuYTExMSA9IDB4MjY2NjsKICB0LmExMTAgPSAweDI2NjU7CiAgdC5hMTA5ID0gMHgyNjYwOwogIHQuYTEyMCA9IDB4MjQ2MDsKICB0LmExMjEgPSAweDI0NjE7CiAgdC5hMTIyID0gMHgyNDYyOwogIHQuYTEyMyA9IDB4MjQ2MzsKICB0LmExMjQgPSAweDI0NjQ7CiAgdC5hMTI1ID0gMHgyNDY1OwogIHQuYTEyNiA9IDB4MjQ2NjsKICB0LmExMjcgPSAweDI0Njc7CiAgdC5hMTI4ID0gMHgyNDY4OwogIHQuYTEyOSA9IDB4MjQ2OTsKICB0LmExMzAgPSAweDI3NzY7CiAgdC5hMTMxID0gMHgyNzc3OwogIHQuYTEzMiA9IDB4Mjc3ODsKICB0LmExMzMgPSAweDI3Nzk7CiAgdC5hMTM0ID0gMHgyNzdhOwogIHQuYTEzNSA9IDB4Mjc3YjsKICB0LmExMzYgPSAweDI3N2M7CiAgdC5hMTM3ID0gMHgyNzdkOwogIHQuYTEzOCA9IDB4Mjc3ZTsKICB0LmExMzkgPSAweDI3N2Y7CiAgdC5hMTQwID0gMHgyNzgwOwogIHQuYTE0MSA9IDB4Mjc4MTsKICB0LmExNDIgPSAweDI3ODI7CiAgdC5hMTQzID0gMHgyNzgzOwogIHQuYTE0NCA9IDB4Mjc4NDsKICB0LmExNDUgPSAweDI3ODU7CiAgdC5hMTQ2ID0gMHgyNzg2OwogIHQuYTE0NyA9IDB4Mjc4NzsKICB0LmExNDggPSAweDI3ODg7CiAgdC5hMTQ5ID0gMHgyNzg5OwogIHQuYTE1MCA9IDB4Mjc4YTsKICB0LmExNTEgPSAweDI3OGI7CiAgdC5hMTUyID0gMHgyNzhjOwogIHQuYTE1MyA9IDB4Mjc4ZDsKICB0LmExNTQgPSAweDI3OGU7CiAgdC5hMTU1ID0gMHgyNzhmOwogIHQuYTE1NiA9IDB4Mjc5MDsKICB0LmExNTcgPSAweDI3OTE7CiAgdC5hMTU4ID0gMHgyNzkyOwogIHQuYTE1OSA9IDB4Mjc5MzsKICB0LmExNjAgPSAweDI3OTQ7CiAgdC5hMTYxID0gMHgyMTkyOwogIHQuYTE2MyA9IDB4MjE5NDsKICB0LmExNjQgPSAweDIxOTU7CiAgdC5hMTk2ID0gMHgyNzk4OwogIHQuYTE2NSA9IDB4Mjc5OTsKICB0LmExOTIgPSAweDI3OWE7CiAgdC5hMTY2ID0gMHgyNzliOwogIHQuYTE2NyA9IDB4Mjc5YzsKICB0LmExNjggPSAweDI3OWQ7CiAgdC5hMTY5ID0gMHgyNzllOwogIHQuYTE3MCA9IDB4Mjc5ZjsKICB0LmExNzEgPSAweDI3YTA7CiAgdC5hMTcyID0gMHgyN2ExOwogIHQuYTE3MyA9IDB4MjdhMjsKICB0LmExNjIgPSAweDI3YTM7CiAgdC5hMTc0ID0gMHgyN2E0OwogIHQuYTE3NSA9IDB4MjdhNTsKICB0LmExNzYgPSAweDI3YTY7CiAgdC5hMTc3ID0gMHgyN2E3OwogIHQuYTE3OCA9IDB4MjdhODsKICB0LmExNzkgPSAweDI3YTk7CiAgdC5hMTkzID0gMHgyN2FhOwogIHQuYTE4MCA9IDB4MjdhYjsKICB0LmExOTkgPSAweDI3YWM7CiAgdC5hMTgxID0gMHgyN2FkOwogIHQuYTIwMCA9IDB4MjdhZTsKICB0LmExODIgPSAweDI3YWY7CiAgdC5hMjAxID0gMHgyN2IxOwogIHQuYTE4MyA9IDB4MjdiMjsKICB0LmExODQgPSAweDI3YjM7CiAgdC5hMTk3ID0gMHgyN2I0OwogIHQuYTE4NSA9IDB4MjdiNTsKICB0LmExOTQgPSAweDI3YjY7CiAgdC5hMTk4ID0gMHgyN2I3OwogIHQuYTE4NiA9IDB4MjdiODsKICB0LmExOTUgPSAweDI3Yjk7CiAgdC5hMTg3ID0gMHgyN2JhOwogIHQuYTE4OCA9IDB4MjdiYjsKICB0LmExODkgPSAweDI3YmM7CiAgdC5hMTkwID0gMHgyN2JkOwogIHQuYTE5MSA9IDB4MjdiZTsKICB0LmE4OSA9IDB4Mjc2ODsKICB0LmE5MCA9IDB4Mjc2OTsKICB0LmE5MyA9IDB4Mjc2YTsKICB0LmE5NCA9IDB4Mjc2YjsKICB0LmE5MSA9IDB4Mjc2YzsKICB0LmE5MiA9IDB4Mjc2ZDsKICB0LmEyMDUgPSAweDI3NmU7CiAgdC5hODUgPSAweDI3NmY7CiAgdC5hMjA2ID0gMHgyNzcwOwogIHQuYTg2ID0gMHgyNzcxOwogIHQuYTg3ID0gMHgyNzcyOwogIHQuYTg4ID0gMHgyNzczOwogIHQuYTk1ID0gMHgyNzc0OwogIHQuYTk2ID0gMHgyNzc1OwogIHRbIi5ub3RkZWYiXSA9IDB4MDAwMDsKfSk7Cgo7Ly8gLi9zcmMvY29yZS91bmljb2RlLmpzCgpjb25zdCBnZXRTcGVjaWFsUFVBU3ltYm9scyA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogIHRbNjM3MjFdID0gMHgwMGE5OwogIHRbNjMxOTNdID0gMHgwMGE5OwogIHRbNjM3MjBdID0gMHgwMGFlOwogIHRbNjMxOTRdID0gMHgwMGFlOwogIHRbNjM3MjJdID0gMHgyMTIyOwogIHRbNjMxOTVdID0gMHgyMTIyOwogIHRbNjM3MjldID0gMHgyM2E3OwogIHRbNjM3MzBdID0gMHgyM2E4OwogIHRbNjM3MzFdID0gMHgyM2E5OwogIHRbNjM3NDBdID0gMHgyM2FiOwogIHRbNjM3NDFdID0gMHgyM2FjOwogIHRbNjM3NDJdID0gMHgyM2FkOwogIHRbNjM3MjZdID0gMHgyM2ExOwogIHRbNjM3MjddID0gMHgyM2EyOwogIHRbNjM3MjhdID0gMHgyM2EzOwogIHRbNjM3MzddID0gMHgyM2E0OwogIHRbNjM3MzhdID0gMHgyM2E1OwogIHRbNjM3MzldID0gMHgyM2E2OwogIHRbNjM3MjNdID0gMHgyMzliOwogIHRbNjM3MjRdID0gMHgyMzljOwogIHRbNjM3MjVdID0gMHgyMzlkOwogIHRbNjM3MzRdID0gMHgyMzllOwogIHRbNjM3MzVdID0gMHgyMzlmOwogIHRbNjM3MzZdID0gMHgyM2EwOwp9KTsKZnVuY3Rpb24gbWFwU3BlY2lhbFVuaWNvZGVWYWx1ZXMoY29kZSkgewogIGlmIChjb2RlID49IDB4ZmZmMCAmJiBjb2RlIDw9IDB4ZmZmZikgewogICAgcmV0dXJuIDA7CiAgfSBlbHNlIGlmIChjb2RlID49IDB4ZjYwMCAmJiBjb2RlIDw9IDB4ZjhmZikgewogICAgcmV0dXJuIGdldFNwZWNpYWxQVUFTeW1ib2xzKClbY29kZV0gfHwgY29kZTsKICB9IGVsc2UgaWYgKGNvZGUgPT09IDB4MDBhZCkgewogICAgcmV0dXJuIDB4MDAyZDsKICB9CiAgcmV0dXJuIGNvZGU7Cn0KZnVuY3Rpb24gZ2V0VW5pY29kZUZvckdseXBoKG5hbWUsIGdseXBoc1VuaWNvZGVNYXApIHsKICBsZXQgdW5pY29kZSA9IGdseXBoc1VuaWNvZGVNYXBbbmFtZV07CiAgaWYgKHVuaWNvZGUgIT09IHVuZGVmaW5lZCkgewogICAgcmV0dXJuIHVuaWNvZGU7CiAgfQogIGlmICghbmFtZSkgewogICAgcmV0dXJuIC0xOwogIH0KICBpZiAobmFtZVswXSA9PT0gInUiKSB7CiAgICBjb25zdCBuYW1lTGVuID0gbmFtZS5sZW5ndGg7CiAgICBsZXQgaGV4U3RyOwogICAgaWYgKG5hbWVMZW4gPT09IDcgJiYgbmFtZVsxXSA9PT0gIm4iICYmIG5hbWVbMl0gPT09ICJpIikgewogICAgICBoZXhTdHIgPSBuYW1lLnN1YnN0cmluZygzKTsKICAgIH0gZWxzZSBpZiAobmFtZUxlbiA+PSA1ICYmIG5hbWVMZW4gPD0gNykgewogICAgICBoZXhTdHIgPSBuYW1lLnN1YnN0cmluZygxKTsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIGlmIChoZXhTdHIgPT09IGhleFN0ci50b1VwcGVyQ2FzZSgpKSB7CiAgICAgIHVuaWNvZGUgPSBwYXJzZUludChoZXhTdHIsIDE2KTsKICAgICAgaWYgKHVuaWNvZGUgPj0gMCkgewogICAgICAgIHJldHVybiB1bmljb2RlOwogICAgICB9CiAgICB9CiAgfQogIHJldHVybiAtMTsKfQpjb25zdCBVbmljb2RlUmFuZ2VzID0gW1sweDAwMDAsIDB4MDA3Zl0sIFsweDAwODAsIDB4MDBmZl0sIFsweDAxMDAsIDB4MDE3Zl0sIFsweDAxODAsIDB4MDI0Zl0sIFsweDAyNTAsIDB4MDJhZiwgMHgxZDAwLCAweDFkN2YsIDB4MWQ4MCwgMHgxZGJmXSwgWzB4MDJiMCwgMHgwMmZmLCAweGE3MDAsIDB4YTcxZl0sIFsweDAzMDAsIDB4MDM2ZiwgMHgxZGMwLCAweDFkZmZdLCBbMHgwMzcwLCAweDAzZmZdLCBbMHgyYzgwLCAweDJjZmZdLCBbMHgwNDAwLCAweDA0ZmYsIDB4MDUwMCwgMHgwNTJmLCAweDJkZTAsIDB4MmRmZiwgMHhhNjQwLCAweGE2OWZdLCBbMHgwNTMwLCAweDA1OGZdLCBbMHgwNTkwLCAweDA1ZmZdLCBbMHhhNTAwLCAweGE2M2ZdLCBbMHgwNjAwLCAweDA2ZmYsIDB4MDc1MCwgMHgwNzdmXSwgWzB4MDdjMCwgMHgwN2ZmXSwgWzB4MDkwMCwgMHgwOTdmXSwgWzB4MDk4MCwgMHgwOWZmXSwgWzB4MGEwMCwgMHgwYTdmXSwgWzB4MGE4MCwgMHgwYWZmXSwgWzB4MGIwMCwgMHgwYjdmXSwgWzB4MGI4MCwgMHgwYmZmXSwgWzB4MGMwMCwgMHgwYzdmXSwgWzB4MGM4MCwgMHgwY2ZmXSwgWzB4MGQwMCwgMHgwZDdmXSwgWzB4MGUwMCwgMHgwZTdmXSwgWzB4MGU4MCwgMHgwZWZmXSwgWzB4MTBhMCwgMHgxMGZmLCAweDJkMDAsIDB4MmQyZl0sIFsweDFiMDAsIDB4MWI3Zl0sIFsweDExMDAsIDB4MTFmZl0sIFsweDFlMDAsIDB4MWVmZiwgMHgyYzYwLCAweDJjN2YsIDB4YTcyMCwgMHhhN2ZmXSwgWzB4MWYwMCwgMHgxZmZmXSwgWzB4MjAwMCwgMHgyMDZmLCAweDJlMDAsIDB4MmU3Zl0sIFsweDIwNzAsIDB4MjA5Zl0sIFsweDIwYTAsIDB4MjBjZl0sIFsweDIwZDAsIDB4MjBmZl0sIFsweDIxMDAsIDB4MjE0Zl0sIFsweDIxNTAsIDB4MjE4Zl0sIFsweDIxOTAsIDB4MjFmZiwgMHgyN2YwLCAweDI3ZmYsIDB4MjkwMCwgMHgyOTdmLCAweDJiMDAsIDB4MmJmZl0sIFsweDIyMDAsIDB4MjJmZiwgMHgyYTAwLCAweDJhZmYsIDB4MjdjMCwgMHgyN2VmLCAweDI5ODAsIDB4MjlmZl0sIFsweDIzMDAsIDB4MjNmZl0sIFsweDI0MDAsIDB4MjQzZl0sIFsweDI0NDAsIDB4MjQ1Zl0sIFsweDI0NjAsIDB4MjRmZl0sIFsweDI1MDAsIDB4MjU3Zl0sIFsweDI1ODAsIDB4MjU5Zl0sIFsweDI1YTAsIDB4MjVmZl0sIFsweDI2MDAsIDB4MjZmZl0sIFsweDI3MDAsIDB4MjdiZl0sIFsweDMwMDAsIDB4MzAzZl0sIFsweDMwNDAsIDB4MzA5Zl0sIFsweDMwYTAsIDB4MzBmZiwgMHgzMWYwLCAweDMxZmZdLCBbMHgzMTAwLCAweDMxMmYsIDB4MzFhMCwgMHgzMWJmXSwgWzB4MzEzMCwgMHgzMThmXSwgWzB4YTg0MCwgMHhhODdmXSwgWzB4MzIwMCwgMHgzMmZmXSwgWzB4MzMwMCwgMHgzM2ZmXSwgWzB4YWMwMCwgMHhkN2FmXSwgWzB4ZDgwMCwgMHhkZmZmXSwgWzB4MTA5MDAsIDB4MTA5MWZdLCBbMHg0ZTAwLCAweDlmZmYsIDB4MmU4MCwgMHgyZWZmLCAweDJmMDAsIDB4MmZkZiwgMHgyZmYwLCAweDJmZmYsIDB4MzQwMCwgMHg0ZGJmLCAweDIwMDAwLCAweDJhNmRmLCAweDMxOTAsIDB4MzE5Zl0sIFsweGUwMDAsIDB4ZjhmZl0sIFsweDMxYzAsIDB4MzFlZiwgMHhmOTAwLCAweGZhZmYsIDB4MmY4MDAsIDB4MmZhMWZdLCBbMHhmYjAwLCAweGZiNGZdLCBbMHhmYjUwLCAweGZkZmZdLCBbMHhmZTIwLCAweGZlMmZdLCBbMHhmZTEwLCAweGZlMWZdLCBbMHhmZTUwLCAweGZlNmZdLCBbMHhmZTcwLCAweGZlZmZdLCBbMHhmZjAwLCAweGZmZWZdLCBbMHhmZmYwLCAweGZmZmZdLCBbMHgwZjAwLCAweDBmZmZdLCBbMHgwNzAwLCAweDA3NGZdLCBbMHgwNzgwLCAweDA3YmZdLCBbMHgwZDgwLCAweDBkZmZdLCBbMHgxMDAwLCAweDEwOWZdLCBbMHgxMjAwLCAweDEzN2YsIDB4MTM4MCwgMHgxMzlmLCAweDJkODAsIDB4MmRkZl0sIFsweDEzYTAsIDB4MTNmZl0sIFsweDE0MDAsIDB4MTY3Zl0sIFsweDE2ODAsIDB4MTY5Zl0sIFsweDE2YTAsIDB4MTZmZl0sIFsweDE3ODAsIDB4MTdmZl0sIFsweDE4MDAsIDB4MThhZl0sIFsweDI4MDAsIDB4MjhmZl0sIFsweGEwMDAsIDB4YTQ4Zl0sIFsweDE3MDAsIDB4MTcxZiwgMHgxNzIwLCAweDE3M2YsIDB4MTc0MCwgMHgxNzVmLCAweDE3NjAsIDB4MTc3Zl0sIFsweDEwMzAwLCAweDEwMzJmXSwgWzB4MTAzMzAsIDB4MTAzNGZdLCBbMHgxMDQwMCwgMHgxMDQ0Zl0sIFsweDFkMDAwLCAweDFkMGZmLCAweDFkMTAwLCAweDFkMWZmLCAweDFkMjAwLCAweDFkMjRmXSwgWzB4MWQ0MDAsIDB4MWQ3ZmZdLCBbMHhmZjAwMCwgMHhmZmZmZF0sIFsweGZlMDAsIDB4ZmUwZiwgMHhlMDEwMCwgMHhlMDFlZl0sIFsweGUwMDAwLCAweGUwMDdmXSwgWzB4MTkwMCwgMHgxOTRmXSwgWzB4MTk1MCwgMHgxOTdmXSwgWzB4MTk4MCwgMHgxOWRmXSwgWzB4MWEwMCwgMHgxYTFmXSwgWzB4MmMwMCwgMHgyYzVmXSwgWzB4MmQzMCwgMHgyZDdmXSwgWzB4NGRjMCwgMHg0ZGZmXSwgWzB4YTgwMCwgMHhhODJmXSwgWzB4MTAwMDAsIDB4MTAwN2YsIDB4MTAwODAsIDB4MTAwZmYsIDB4MTAxMDAsIDB4MTAxM2ZdLCBbMHgxMDE0MCwgMHgxMDE4Zl0sIFsweDEwMzgwLCAweDEwMzlmXSwgWzB4MTAzYTAsIDB4MTAzZGZdLCBbMHgxMDQ1MCwgMHgxMDQ3Zl0sIFsweDEwNDgwLCAweDEwNGFmXSwgWzB4MTA4MDAsIDB4MTA4M2ZdLCBbMHgxMGEwMCwgMHgxMGE1Zl0sIFsweDFkMzAwLCAweDFkMzVmXSwgWzB4MTIwMDAsIDB4MTIzZmYsIDB4MTI0MDAsIDB4MTI0N2ZdLCBbMHgxZDM2MCwgMHgxZDM3Zl0sIFsweDFiODAsIDB4MWJiZl0sIFsweDFjMDAsIDB4MWM0Zl0sIFsweDFjNTAsIDB4MWM3Zl0sIFsweGE4ODAsIDB4YThkZl0sIFsweGE5MDAsIDB4YTkyZl0sIFsweGE5MzAsIDB4YTk1Zl0sIFsweGFhMDAsIDB4YWE1Zl0sIFsweDEwMTkwLCAweDEwMWNmXSwgWzB4MTAxZDAsIDB4MTAxZmZdLCBbMHgxMDJhMCwgMHgxMDJkZiwgMHgxMDI4MCwgMHgxMDI5ZiwgMHgxMDkyMCwgMHgxMDkzZl0sIFsweDFmMDMwLCAweDFmMDlmLCAweDFmMDAwLCAweDFmMDJmXV07CmZ1bmN0aW9uIGdldFVuaWNvZGVSYW5nZUZvcih2YWx1ZSwgbGFzdFBvc2l0aW9uID0gLTEpIHsKICBpZiAobGFzdFBvc2l0aW9uICE9PSAtMSkgewogICAgY29uc3QgcmFuZ2UgPSBVbmljb2RlUmFuZ2VzW2xhc3RQb3NpdGlvbl07CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSByYW5nZS5sZW5ndGg7IGkgPCBpaTsgaSArPSAyKSB7CiAgICAgIGlmICh2YWx1ZSA+PSByYW5nZVtpXSAmJiB2YWx1ZSA8PSByYW5nZVtpICsgMV0pIHsKICAgICAgICByZXR1cm4gbGFzdFBvc2l0aW9uOwogICAgICB9CiAgICB9CiAgfQogIGZvciAobGV0IGkgPSAwLCBpaSA9IFVuaWNvZGVSYW5nZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgY29uc3QgcmFuZ2UgPSBVbmljb2RlUmFuZ2VzW2ldOwogICAgZm9yIChsZXQgaiA9IDAsIGpqID0gcmFuZ2UubGVuZ3RoOyBqIDwgamo7IGogKz0gMikgewogICAgICBpZiAodmFsdWUgPj0gcmFuZ2Vbal0gJiYgdmFsdWUgPD0gcmFuZ2VbaiArIDFdKSB7CiAgICAgICAgcmV0dXJuIGk7CiAgICAgIH0KICAgIH0KICB9CiAgcmV0dXJuIC0xOwp9CmNvbnN0IFNwZWNpYWxDaGFyUmVnRXhwID0gbmV3IFJlZ0V4cCgiXihcXHMpfChcXHB7TW59KXwoXFxwe0NmfSkkIiwgInUiKTsKY29uc3QgQ2F0ZWdvcnlDYWNoZSA9IG5ldyBNYXAoKTsKZnVuY3Rpb24gZ2V0Q2hhclVuaWNvZGVDYXRlZ29yeShjaGFyKSB7CiAgY29uc3QgY2FjaGVkQ2F0ZWdvcnkgPSBDYXRlZ29yeUNhY2hlLmdldChjaGFyKTsKICBpZiAoY2FjaGVkQ2F0ZWdvcnkpIHsKICAgIHJldHVybiBjYWNoZWRDYXRlZ29yeTsKICB9CiAgY29uc3QgZ3JvdXBzID0gY2hhci5tYXRjaChTcGVjaWFsQ2hhclJlZ0V4cCk7CiAgY29uc3QgY2F0ZWdvcnkgPSB7CiAgICBpc1doaXRlc3BhY2U6ICEhZ3JvdXBzPy5bMV0sCiAgICBpc1plcm9XaWR0aERpYWNyaXRpYzogISFncm91cHM/LlsyXSwKICAgIGlzSW52aXNpYmxlRm9ybWF0TWFyazogISFncm91cHM/LlszXQogIH07CiAgQ2F0ZWdvcnlDYWNoZS5zZXQoY2hhciwgY2F0ZWdvcnkpOwogIHJldHVybiBjYXRlZ29yeTsKfQpmdW5jdGlvbiBjbGVhclVuaWNvZGVDYWNoZXMoKSB7CiAgQ2F0ZWdvcnlDYWNoZS5jbGVhcigpOwp9Cgo7Ly8gLi9zcmMvY29yZS9mb250c191dGlscy5qcwoKCgoKCgoKCgoKCgoKCgpjb25zdCBTRUFDX0FOQUxZU0lTX0VOQUJMRUQgPSB0cnVlOwpjb25zdCBGb250RmxhZ3MgPSB7CiAgRml4ZWRQaXRjaDogMSwKICBTZXJpZjogMiwKICBTeW1ib2xpYzogNCwKICBTY3JpcHQ6IDgsCiAgTm9uc3ltYm9saWM6IDMyLAogIEl0YWxpYzogNjQsCiAgQWxsQ2FwOiA2NTUzNiwKICBTbWFsbENhcDogMTMxMDcyLAogIEZvcmNlQm9sZDogMjYyMTQ0Cn07CmNvbnN0IE1hY1N0YW5kYXJkR2x5cGhPcmRlcmluZyA9IFsiLm5vdGRlZiIsICIubnVsbCIsICJub25tYXJraW5ncmV0dXJuIiwgInNwYWNlIiwgImV4Y2xhbSIsICJxdW90ZWRibCIsICJudW1iZXJzaWduIiwgImRvbGxhciIsICJwZXJjZW50IiwgImFtcGVyc2FuZCIsICJxdW90ZXNpbmdsZSIsICJwYXJlbmxlZnQiLCAicGFyZW5yaWdodCIsICJhc3RlcmlzayIsICJwbHVzIiwgImNvbW1hIiwgImh5cGhlbiIsICJwZXJpb2QiLCAic2xhc2giLCAiemVybyIsICJvbmUiLCAidHdvIiwgInRocmVlIiwgImZvdXIiLCAiZml2ZSIsICJzaXgiLCAic2V2ZW4iLCAiZWlnaHQiLCAibmluZSIsICJjb2xvbiIsICJzZW1pY29sb24iLCAibGVzcyIsICJlcXVhbCIsICJncmVhdGVyIiwgInF1ZXN0aW9uIiwgImF0IiwgIkEiLCAiQiIsICJDIiwgIkQiLCAiRSIsICJGIiwgIkciLCAiSCIsICJJIiwgIkoiLCAiSyIsICJMIiwgIk0iLCAiTiIsICJPIiwgIlAiLCAiUSIsICJSIiwgIlMiLCAiVCIsICJVIiwgIlYiLCAiVyIsICJYIiwgIlkiLCAiWiIsICJicmFja2V0bGVmdCIsICJiYWNrc2xhc2giLCAiYnJhY2tldHJpZ2h0IiwgImFzY2lpY2lyY3VtIiwgInVuZGVyc2NvcmUiLCAiZ3JhdmUiLCAiYSIsICJiIiwgImMiLCAiZCIsICJlIiwgImYiLCAiZyIsICJoIiwgImkiLCAiaiIsICJrIiwgImwiLCAibSIsICJuIiwgIm8iLCAicCIsICJxIiwgInIiLCAicyIsICJ0IiwgInUiLCAidiIsICJ3IiwgIngiLCAieSIsICJ6IiwgImJyYWNlbGVmdCIsICJiYXIiLCAiYnJhY2VyaWdodCIsICJhc2NpaXRpbGRlIiwgIkFkaWVyZXNpcyIsICJBcmluZyIsICJDY2VkaWxsYSIsICJFYWN1dGUiLCAiTnRpbGRlIiwgIk9kaWVyZXNpcyIsICJVZGllcmVzaXMiLCAiYWFjdXRlIiwgImFncmF2ZSIsICJhY2lyY3VtZmxleCIsICJhZGllcmVzaXMiLCAiYXRpbGRlIiwgImFyaW5nIiwgImNjZWRpbGxhIiwgImVhY3V0ZSIsICJlZ3JhdmUiLCAiZWNpcmN1bWZsZXgiLCAiZWRpZXJlc2lzIiwgImlhY3V0ZSIsICJpZ3JhdmUiLCAiaWNpcmN1bWZsZXgiLCAiaWRpZXJlc2lzIiwgIm50aWxkZSIsICJvYWN1dGUiLCAib2dyYXZlIiwgIm9jaXJjdW1mbGV4IiwgIm9kaWVyZXNpcyIsICJvdGlsZGUiLCAidWFjdXRlIiwgInVncmF2ZSIsICJ1Y2lyY3VtZmxleCIsICJ1ZGllcmVzaXMiLCAiZGFnZ2VyIiwgImRlZ3JlZSIsICJjZW50IiwgInN0ZXJsaW5nIiwgInNlY3Rpb24iLCAiYnVsbGV0IiwgInBhcmFncmFwaCIsICJnZXJtYW5kYmxzIiwgInJlZ2lzdGVyZWQiLCAiY29weXJpZ2h0IiwgInRyYWRlbWFyayIsICJhY3V0ZSIsICJkaWVyZXNpcyIsICJub3RlcXVhbCIsICJBRSIsICJPc2xhc2giLCAiaW5maW5pdHkiLCAicGx1c21pbnVzIiwgImxlc3NlcXVhbCIsICJncmVhdGVyZXF1YWwiLCAieWVuIiwgIm11IiwgInBhcnRpYWxkaWZmIiwgInN1bW1hdGlvbiIsICJwcm9kdWN0IiwgInBpIiwgImludGVncmFsIiwgIm9yZGZlbWluaW5lIiwgIm9yZG1hc2N1bGluZSIsICJPbWVnYSIsICJhZSIsICJvc2xhc2giLCAicXVlc3Rpb25kb3duIiwgImV4Y2xhbWRvd24iLCAibG9naWNhbG5vdCIsICJyYWRpY2FsIiwgImZsb3JpbiIsICJhcHByb3hlcXVhbCIsICJEZWx0YSIsICJndWlsbGVtb3RsZWZ0IiwgImd1aWxsZW1vdHJpZ2h0IiwgImVsbGlwc2lzIiwgIm5vbmJyZWFraW5nc3BhY2UiLCAiQWdyYXZlIiwgIkF0aWxkZSIsICJPdGlsZGUiLCAiT0UiLCAib2UiLCAiZW5kYXNoIiwgImVtZGFzaCIsICJxdW90ZWRibGxlZnQiLCAicXVvdGVkYmxyaWdodCIsICJxdW90ZWxlZnQiLCAicXVvdGVyaWdodCIsICJkaXZpZGUiLCAibG96ZW5nZSIsICJ5ZGllcmVzaXMiLCAiWWRpZXJlc2lzIiwgImZyYWN0aW9uIiwgImN1cnJlbmN5IiwgImd1aWxzaW5nbGxlZnQiLCAiZ3VpbHNpbmdscmlnaHQiLCAiZmkiLCAiZmwiLCAiZGFnZ2VyZGJsIiwgInBlcmlvZGNlbnRlcmVkIiwgInF1b3Rlc2luZ2xiYXNlIiwgInF1b3RlZGJsYmFzZSIsICJwZXJ0aG91c2FuZCIsICJBY2lyY3VtZmxleCIsICJFY2lyY3VtZmxleCIsICJBYWN1dGUiLCAiRWRpZXJlc2lzIiwgIkVncmF2ZSIsICJJYWN1dGUiLCAiSWNpcmN1bWZsZXgiLCAiSWRpZXJlc2lzIiwgIklncmF2ZSIsICJPYWN1dGUiLCAiT2NpcmN1bWZsZXgiLCAiYXBwbGUiLCAiT2dyYXZlIiwgIlVhY3V0ZSIsICJVY2lyY3VtZmxleCIsICJVZ3JhdmUiLCAiZG90bGVzc2kiLCAiY2lyY3VtZmxleCIsICJ0aWxkZSIsICJtYWNyb24iLCAiYnJldmUiLCAiZG90YWNjZW50IiwgInJpbmciLCAiY2VkaWxsYSIsICJodW5nYXJ1bWxhdXQiLCAib2dvbmVrIiwgImNhcm9uIiwgIkxzbGFzaCIsICJsc2xhc2giLCAiU2Nhcm9uIiwgInNjYXJvbiIsICJaY2Fyb24iLCAiemNhcm9uIiwgImJyb2tlbmJhciIsICJFdGgiLCAiZXRoIiwgIllhY3V0ZSIsICJ5YWN1dGUiLCAiVGhvcm4iLCAidGhvcm4iLCAibWludXMiLCAibXVsdGlwbHkiLCAib25lc3VwZXJpb3IiLCAidHdvc3VwZXJpb3IiLCAidGhyZWVzdXBlcmlvciIsICJvbmVoYWxmIiwgIm9uZXF1YXJ0ZXIiLCAidGhyZWVxdWFydGVycyIsICJmcmFuYyIsICJHYnJldmUiLCAiZ2JyZXZlIiwgIklkb3RhY2NlbnQiLCAiU2NlZGlsbGEiLCAic2NlZGlsbGEiLCAiQ2FjdXRlIiwgImNhY3V0ZSIsICJDY2Fyb24iLCAiY2Nhcm9uIiwgImRjcm9hdCJdOwpmdW5jdGlvbiByZWNvdmVyR2x5cGhOYW1lKG5hbWUsIGdseXBoc1VuaWNvZGVNYXApIHsKICBpZiAoZ2x5cGhzVW5pY29kZU1hcFtuYW1lXSAhPT0gdW5kZWZpbmVkKSB7CiAgICByZXR1cm4gbmFtZTsKICB9CiAgY29uc3QgdW5pY29kZSA9IGdldFVuaWNvZGVGb3JHbHlwaChuYW1lLCBnbHlwaHNVbmljb2RlTWFwKTsKICBpZiAodW5pY29kZSAhPT0gLTEpIHsKICAgIGZvciAoY29uc3Qga2V5IGluIGdseXBoc1VuaWNvZGVNYXApIHsKICAgICAgaWYgKGdseXBoc1VuaWNvZGVNYXBba2V5XSA9PT0gdW5pY29kZSkgewogICAgICAgIHJldHVybiBrZXk7CiAgICAgIH0KICAgIH0KICB9CiAgaW5mbygiVW5hYmxlIHRvIHJlY292ZXIgYSBzdGFuZGFyZCBnbHlwaCBuYW1lIGZvcjogIiArIG5hbWUpOwogIHJldHVybiBuYW1lOwp9CmZ1bmN0aW9uIHR5cGUxRm9udEdseXBoTWFwcGluZyhwcm9wZXJ0aWVzLCBidWlsdEluRW5jb2RpbmcsIGdseXBoTmFtZXMpIHsKICBjb25zdCBjaGFyQ29kZVRvR2x5cGhJZCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgbGV0IGdseXBoSWQsIGNoYXJDb2RlLCBiYXNlRW5jb2Rpbmc7CiAgY29uc3QgaXNTeW1ib2xpY0ZvbnQgPSAhIShwcm9wZXJ0aWVzLmZsYWdzICYgRm9udEZsYWdzLlN5bWJvbGljKTsKICBpZiAocHJvcGVydGllcy5pc0ludGVybmFsRm9udCkgewogICAgYmFzZUVuY29kaW5nID0gYnVpbHRJbkVuY29kaW5nOwogICAgZm9yIChjaGFyQ29kZSA9IDA7IGNoYXJDb2RlIDwgYmFzZUVuY29kaW5nLmxlbmd0aDsgY2hhckNvZGUrKykgewogICAgICBnbHlwaElkID0gZ2x5cGhOYW1lcy5pbmRleE9mKGJhc2VFbmNvZGluZ1tjaGFyQ29kZV0pOwogICAgICBjaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0gPSBnbHlwaElkID49IDAgPyBnbHlwaElkIDogMDsKICAgIH0KICB9IGVsc2UgaWYgKHByb3BlcnRpZXMuYmFzZUVuY29kaW5nTmFtZSkgewogICAgYmFzZUVuY29kaW5nID0gZ2V0RW5jb2RpbmcocHJvcGVydGllcy5iYXNlRW5jb2RpbmdOYW1lKTsKICAgIGZvciAoY2hhckNvZGUgPSAwOyBjaGFyQ29kZSA8IGJhc2VFbmNvZGluZy5sZW5ndGg7IGNoYXJDb2RlKyspIHsKICAgICAgZ2x5cGhJZCA9IGdseXBoTmFtZXMuaW5kZXhPZihiYXNlRW5jb2RpbmdbY2hhckNvZGVdKTsKICAgICAgY2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdID0gZ2x5cGhJZCA+PSAwID8gZ2x5cGhJZCA6IDA7CiAgICB9CiAgfSBlbHNlIGlmIChpc1N5bWJvbGljRm9udCkgewogICAgZm9yIChjaGFyQ29kZSBpbiBidWlsdEluRW5jb2RpbmcpIHsKICAgICAgY2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdID0gYnVpbHRJbkVuY29kaW5nW2NoYXJDb2RlXTsKICAgIH0KICB9IGVsc2UgewogICAgYmFzZUVuY29kaW5nID0gU3RhbmRhcmRFbmNvZGluZzsKICAgIGZvciAoY2hhckNvZGUgPSAwOyBjaGFyQ29kZSA8IGJhc2VFbmNvZGluZy5sZW5ndGg7IGNoYXJDb2RlKyspIHsKICAgICAgZ2x5cGhJZCA9IGdseXBoTmFtZXMuaW5kZXhPZihiYXNlRW5jb2RpbmdbY2hhckNvZGVdKTsKICAgICAgY2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdID0gZ2x5cGhJZCA+PSAwID8gZ2x5cGhJZCA6IDA7CiAgICB9CiAgfQogIGNvbnN0IGRpZmZlcmVuY2VzID0gcHJvcGVydGllcy5kaWZmZXJlbmNlczsKICBsZXQgZ2x5cGhzVW5pY29kZU1hcDsKICBpZiAoZGlmZmVyZW5jZXMpIHsKICAgIGZvciAoY2hhckNvZGUgaW4gZGlmZmVyZW5jZXMpIHsKICAgICAgY29uc3QgZ2x5cGhOYW1lID0gZGlmZmVyZW5jZXNbY2hhckNvZGVdOwogICAgICBnbHlwaElkID0gZ2x5cGhOYW1lcy5pbmRleE9mKGdseXBoTmFtZSk7CiAgICAgIGlmIChnbHlwaElkID09PSAtMSkgewogICAgICAgIGlmICghZ2x5cGhzVW5pY29kZU1hcCkgewogICAgICAgICAgZ2x5cGhzVW5pY29kZU1hcCA9IGdldEdseXBoc1VuaWNvZGUoKTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgc3RhbmRhcmRHbHlwaE5hbWUgPSByZWNvdmVyR2x5cGhOYW1lKGdseXBoTmFtZSwgZ2x5cGhzVW5pY29kZU1hcCk7CiAgICAgICAgaWYgKHN0YW5kYXJkR2x5cGhOYW1lICE9PSBnbHlwaE5hbWUpIHsKICAgICAgICAgIGdseXBoSWQgPSBnbHlwaE5hbWVzLmluZGV4T2Yoc3RhbmRhcmRHbHlwaE5hbWUpOwogICAgICAgIH0KICAgICAgfQogICAgICBjaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0gPSBnbHlwaElkID49IDAgPyBnbHlwaElkIDogMDsKICAgIH0KICB9CiAgcmV0dXJuIGNoYXJDb2RlVG9HbHlwaElkOwp9CmZ1bmN0aW9uIG5vcm1hbGl6ZUZvbnROYW1lKG5hbWUpIHsKICByZXR1cm4gbmFtZS5yZXBsYWNlQWxsKC9bLF9dL2csICItIikucmVwbGFjZUFsbCgvXHMvZywgIiIpOwp9CmNvbnN0IGdldFZlcnRpY2FsUHJlc2VudGF0aW9uRm9ybSA9IGdldExvb2t1cFRhYmxlRmFjdG9yeSh0ID0+IHsKICB0WzB4MjAxM10gPSAweGZlMzI7CiAgdFsweDIwMTRdID0gMHhmZTMxOwogIHRbMHgyMDI1XSA9IDB4ZmUzMDsKICB0WzB4MjAyNl0gPSAweGZlMTk7CiAgdFsweDMwMDFdID0gMHhmZTExOwogIHRbMHgzMDAyXSA9IDB4ZmUxMjsKICB0WzB4MzAwOF0gPSAweGZlM2Y7CiAgdFsweDMwMDldID0gMHhmZTQwOwogIHRbMHgzMDBhXSA9IDB4ZmUzZDsKICB0WzB4MzAwYl0gPSAweGZlM2U7CiAgdFsweDMwMGNdID0gMHhmZTQxOwogIHRbMHgzMDBkXSA9IDB4ZmU0MjsKICB0WzB4MzAwZV0gPSAweGZlNDM7CiAgdFsweDMwMGZdID0gMHhmZTQ0OwogIHRbMHgzMDEwXSA9IDB4ZmUzYjsKICB0WzB4MzAxMV0gPSAweGZlM2M7CiAgdFsweDMwMTRdID0gMHhmZTM5OwogIHRbMHgzMDE1XSA9IDB4ZmUzYTsKICB0WzB4MzAxNl0gPSAweGZlMTc7CiAgdFsweDMwMTddID0gMHhmZTE4OwogIHRbMHhmZTRmXSA9IDB4ZmUzNDsKICB0WzB4ZmYwMV0gPSAweGZlMTU7CiAgdFsweGZmMDhdID0gMHhmZTM1OwogIHRbMHhmZjA5XSA9IDB4ZmUzNjsKICB0WzB4ZmYwY10gPSAweGZlMTA7CiAgdFsweGZmMWFdID0gMHhmZTEzOwogIHRbMHhmZjFiXSA9IDB4ZmUxNDsKICB0WzB4ZmYxZl0gPSAweGZlMTY7CiAgdFsweGZmM2JdID0gMHhmZTQ3OwogIHRbMHhmZjNkXSA9IDB4ZmU0ODsKICB0WzB4ZmYzZl0gPSAweGZlMzM7CiAgdFsweGZmNWJdID0gMHhmZTM3OwogIHRbMHhmZjVkXSA9IDB4ZmUzODsKfSk7CmNvbnN0IE1BWF9TSVpFX1RPX0NPTVBJTEUgPSAxMDAwOwpmdW5jdGlvbiBjb21waWxlVHlwZTNHbHlwaCh7CiAgZGF0YTogaW1nLAogIHdpZHRoLAogIGhlaWdodAp9KSB7CiAgaWYgKHdpZHRoID4gTUFYX1NJWkVfVE9fQ09NUElMRSB8fCBoZWlnaHQgPiBNQVhfU0laRV9UT19DT01QSUxFKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgY29uc3QgUE9JTlRfVE9fUFJPQ0VTU19MSU1JVCA9IDEwMDA7CiAgY29uc3QgUE9JTlRfVFlQRVMgPSBuZXcgVWludDhBcnJheShbMCwgMiwgNCwgMCwgMSwgMCwgNSwgNCwgOCwgMTAsIDAsIDgsIDAsIDIsIDEsIDBdKTsKICBjb25zdCB3aWR0aDEgPSB3aWR0aCArIDE7CiAgY29uc3QgcG9pbnRzID0gbmV3IFVpbnQ4QXJyYXkod2lkdGgxICogKGhlaWdodCArIDEpKTsKICBsZXQgaSwgaiwgajA7CiAgY29uc3QgbGluZVNpemUgPSB3aWR0aCArIDcgJiB+NzsKICBjb25zdCBkYXRhID0gbmV3IFVpbnQ4QXJyYXkobGluZVNpemUgKiBoZWlnaHQpOwogIGxldCBwb3MgPSAwOwogIGZvciAoY29uc3QgZWxlbSBvZiBpbWcpIHsKICAgIGxldCBtYXNrID0gMTI4OwogICAgd2hpbGUgKG1hc2sgPiAwKSB7CiAgICAgIGRhdGFbcG9zKytdID0gZWxlbSAmIG1hc2sgPyAwIDogMjU1OwogICAgICBtYXNrID4+PSAxOwogICAgfQogIH0KICBsZXQgY291bnQgPSAwOwogIHBvcyA9IDA7CiAgaWYgKGRhdGFbcG9zXSAhPT0gMCkgewogICAgcG9pbnRzWzBdID0gMTsKICAgICsrY291bnQ7CiAgfQogIGZvciAoaiA9IDE7IGogPCB3aWR0aDsgaisrKSB7CiAgICBpZiAoZGF0YVtwb3NdICE9PSBkYXRhW3BvcyArIDFdKSB7CiAgICAgIHBvaW50c1tqXSA9IGRhdGFbcG9zXSA/IDIgOiAxOwogICAgICArK2NvdW50OwogICAgfQogICAgcG9zKys7CiAgfQogIGlmIChkYXRhW3Bvc10gIT09IDApIHsKICAgIHBvaW50c1tqXSA9IDI7CiAgICArK2NvdW50OwogIH0KICBmb3IgKGkgPSAxOyBpIDwgaGVpZ2h0OyBpKyspIHsKICAgIHBvcyA9IGkgKiBsaW5lU2l6ZTsKICAgIGowID0gaSAqIHdpZHRoMTsKICAgIGlmIChkYXRhW3BvcyAtIGxpbmVTaXplXSAhPT0gZGF0YVtwb3NdKSB7CiAgICAgIHBvaW50c1tqMF0gPSBkYXRhW3Bvc10gPyAxIDogODsKICAgICAgKytjb3VudDsKICAgIH0KICAgIGxldCBzdW0gPSAoZGF0YVtwb3NdID8gNCA6IDApICsgKGRhdGFbcG9zIC0gbGluZVNpemVdID8gOCA6IDApOwogICAgZm9yIChqID0gMTsgaiA8IHdpZHRoOyBqKyspIHsKICAgICAgc3VtID0gKHN1bSA+PiAyKSArIChkYXRhW3BvcyArIDFdID8gNCA6IDApICsgKGRhdGFbcG9zIC0gbGluZVNpemUgKyAxXSA/IDggOiAwKTsKICAgICAgaWYgKFBPSU5UX1RZUEVTW3N1bV0pIHsKICAgICAgICBwb2ludHNbajAgKyBqXSA9IFBPSU5UX1RZUEVTW3N1bV07CiAgICAgICAgKytjb3VudDsKICAgICAgfQogICAgICBwb3MrKzsKICAgIH0KICAgIGlmIChkYXRhW3BvcyAtIGxpbmVTaXplXSAhPT0gZGF0YVtwb3NdKSB7CiAgICAgIHBvaW50c1tqMCArIGpdID0gZGF0YVtwb3NdID8gMiA6IDQ7CiAgICAgICsrY291bnQ7CiAgICB9CiAgICBpZiAoY291bnQgPiBQT0lOVF9UT19QUk9DRVNTX0xJTUlUKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogIH0KICBwb3MgPSBsaW5lU2l6ZSAqIChoZWlnaHQgLSAxKTsKICBqMCA9IGkgKiB3aWR0aDE7CiAgaWYgKGRhdGFbcG9zXSAhPT0gMCkgewogICAgcG9pbnRzW2owXSA9IDg7CiAgICArK2NvdW50OwogIH0KICBmb3IgKGogPSAxOyBqIDwgd2lkdGg7IGorKykgewogICAgaWYgKGRhdGFbcG9zXSAhPT0gZGF0YVtwb3MgKyAxXSkgewogICAgICBwb2ludHNbajAgKyBqXSA9IGRhdGFbcG9zXSA/IDQgOiA4OwogICAgICArK2NvdW50OwogICAgfQogICAgcG9zKys7CiAgfQogIGlmIChkYXRhW3Bvc10gIT09IDApIHsKICAgIHBvaW50c1tqMCArIGpdID0gNDsKICAgICsrY291bnQ7CiAgfQogIGlmIChjb3VudCA+IFBPSU5UX1RPX1BST0NFU1NfTElNSVQpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBjb25zdCBzdGVwcyA9IG5ldyBJbnQzMkFycmF5KFswLCB3aWR0aDEsIC0xLCAwLCAtd2lkdGgxLCAwLCAwLCAwLCAxXSk7CiAgY29uc3QgcGF0aEJ1ZiA9IFtdOwogIGNvbnN0IHsKICAgIGEsCiAgICBiLAogICAgYywKICAgIGQsCiAgICBlLAogICAgZgogIH0gPSBuZXcgRE9NTWF0cml4KCkuc2NhbGVTZWxmKDEgLyB3aWR0aCwgLTEgLyBoZWlnaHQpLnRyYW5zbGF0ZVNlbGYoMCwgLWhlaWdodCk7CiAgZm9yIChpID0gMDsgY291bnQgJiYgaSA8PSBoZWlnaHQ7IGkrKykgewogICAgbGV0IHAgPSBpICogd2lkdGgxOwogICAgY29uc3QgZW5kID0gcCArIHdpZHRoOwogICAgd2hpbGUgKHAgPCBlbmQgJiYgIXBvaW50c1twXSkgewogICAgICBwKys7CiAgICB9CiAgICBpZiAocCA9PT0gZW5kKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgbGV0IHggPSBwICUgd2lkdGgxOwogICAgbGV0IHkgPSBpOwogICAgcGF0aEJ1Zi5wdXNoKERyYXdPUFMubW92ZVRvLCBhICogeCArIGMgKiB5ICsgZSwgYiAqIHggKyBkICogeSArIGYpOwogICAgY29uc3QgcDAgPSBwOwogICAgbGV0IHR5cGUgPSBwb2ludHNbcF07CiAgICBkbyB7CiAgICAgIGNvbnN0IHN0ZXAgPSBzdGVwc1t0eXBlXTsKICAgICAgZG8gewogICAgICAgIHAgKz0gc3RlcDsKICAgICAgfSB3aGlsZSAoIXBvaW50c1twXSk7CiAgICAgIGNvbnN0IHBwID0gcG9pbnRzW3BdOwogICAgICBpZiAocHAgIT09IDUgJiYgcHAgIT09IDEwKSB7CiAgICAgICAgdHlwZSA9IHBwOwogICAgICAgIHBvaW50c1twXSA9IDA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdHlwZSA9IHBwICYgMHgzMyAqIHR5cGUgPj4gNDsKICAgICAgICBwb2ludHNbcF0gJj0gdHlwZSA+PiAyIHwgdHlwZSA8PCAyOwogICAgICB9CiAgICAgIHggPSBwICUgd2lkdGgxOwogICAgICB5ID0gcCAvIHdpZHRoMSB8IDA7CiAgICAgIHBhdGhCdWYucHVzaChEcmF3T1BTLmxpbmVUbywgYSAqIHggKyBjICogeSArIGUsIGIgKiB4ICsgZCAqIHkgKyBmKTsKICAgICAgaWYgKCFwb2ludHNbcF0pIHsKICAgICAgICAtLWNvdW50OwogICAgICB9CiAgICB9IHdoaWxlIChwMCAhPT0gcCk7CiAgICAtLWk7CiAgfQogIHJldHVybiBbT1BTLnJhd0ZpbGxQYXRoLCBbbmV3IEZsb2F0MzJBcnJheShwYXRoQnVmKV0sIG5ldyBGbG9hdDMyQXJyYXkoWzAsIDAsIHdpZHRoLCBoZWlnaHRdKV07Cn0KCi8vIEVYVEVSTkFMIE1PRFVMRTogLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLml0ZXJhdG9yLnRvLWFycmF5LmpzCnZhciBlc19pdGVyYXRvcl90b19hcnJheSA9IF9fd2VicGFja19yZXF1aXJlX18oMTgwNik7CjsvLyAuL3NyYy9jb3JlL2NoYXJzZXRzLmpzCmNvbnN0IElTT0Fkb2JlQ2hhcnNldCA9IFsiLm5vdGRlZiIsICJzcGFjZSIsICJleGNsYW0iLCAicXVvdGVkYmwiLCAibnVtYmVyc2lnbiIsICJkb2xsYXIiLCAicGVyY2VudCIsICJhbXBlcnNhbmQiLCAicXVvdGVyaWdodCIsICJwYXJlbmxlZnQiLCAicGFyZW5yaWdodCIsICJhc3RlcmlzayIsICJwbHVzIiwgImNvbW1hIiwgImh5cGhlbiIsICJwZXJpb2QiLCAic2xhc2giLCAiemVybyIsICJvbmUiLCAidHdvIiwgInRocmVlIiwgImZvdXIiLCAiZml2ZSIsICJzaXgiLCAic2V2ZW4iLCAiZWlnaHQiLCAibmluZSIsICJjb2xvbiIsICJzZW1pY29sb24iLCAibGVzcyIsICJlcXVhbCIsICJncmVhdGVyIiwgInF1ZXN0aW9uIiwgImF0IiwgIkEiLCAiQiIsICJDIiwgIkQiLCAiRSIsICJGIiwgIkciLCAiSCIsICJJIiwgIkoiLCAiSyIsICJMIiwgIk0iLCAiTiIsICJPIiwgIlAiLCAiUSIsICJSIiwgIlMiLCAiVCIsICJVIiwgIlYiLCAiVyIsICJYIiwgIlkiLCAiWiIsICJicmFja2V0bGVmdCIsICJiYWNrc2xhc2giLCAiYnJhY2tldHJpZ2h0IiwgImFzY2lpY2lyY3VtIiwgInVuZGVyc2NvcmUiLCAicXVvdGVsZWZ0IiwgImEiLCAiYiIsICJjIiwgImQiLCAiZSIsICJmIiwgImciLCAiaCIsICJpIiwgImoiLCAiayIsICJsIiwgIm0iLCAibiIsICJvIiwgInAiLCAicSIsICJyIiwgInMiLCAidCIsICJ1IiwgInYiLCAidyIsICJ4IiwgInkiLCAieiIsICJicmFjZWxlZnQiLCAiYmFyIiwgImJyYWNlcmlnaHQiLCAiYXNjaWl0aWxkZSIsICJleGNsYW1kb3duIiwgImNlbnQiLCAic3RlcmxpbmciLCAiZnJhY3Rpb24iLCAieWVuIiwgImZsb3JpbiIsICJzZWN0aW9uIiwgImN1cnJlbmN5IiwgInF1b3Rlc2luZ2xlIiwgInF1b3RlZGJsbGVmdCIsICJndWlsbGVtb3RsZWZ0IiwgImd1aWxzaW5nbGxlZnQiLCAiZ3VpbHNpbmdscmlnaHQiLCAiZmkiLCAiZmwiLCAiZW5kYXNoIiwgImRhZ2dlciIsICJkYWdnZXJkYmwiLCAicGVyaW9kY2VudGVyZWQiLCAicGFyYWdyYXBoIiwgImJ1bGxldCIsICJxdW90ZXNpbmdsYmFzZSIsICJxdW90ZWRibGJhc2UiLCAicXVvdGVkYmxyaWdodCIsICJndWlsbGVtb3RyaWdodCIsICJlbGxpcHNpcyIsICJwZXJ0aG91c2FuZCIsICJxdWVzdGlvbmRvd24iLCAiZ3JhdmUiLCAiYWN1dGUiLCAiY2lyY3VtZmxleCIsICJ0aWxkZSIsICJtYWNyb24iLCAiYnJldmUiLCAiZG90YWNjZW50IiwgImRpZXJlc2lzIiwgInJpbmciLCAiY2VkaWxsYSIsICJodW5nYXJ1bWxhdXQiLCAib2dvbmVrIiwgImNhcm9uIiwgImVtZGFzaCIsICJBRSIsICJvcmRmZW1pbmluZSIsICJMc2xhc2giLCAiT3NsYXNoIiwgIk9FIiwgIm9yZG1hc2N1bGluZSIsICJhZSIsICJkb3RsZXNzaSIsICJsc2xhc2giLCAib3NsYXNoIiwgIm9lIiwgImdlcm1hbmRibHMiLCAib25lc3VwZXJpb3IiLCAibG9naWNhbG5vdCIsICJtdSIsICJ0cmFkZW1hcmsiLCAiRXRoIiwgIm9uZWhhbGYiLCAicGx1c21pbnVzIiwgIlRob3JuIiwgIm9uZXF1YXJ0ZXIiLCAiZGl2aWRlIiwgImJyb2tlbmJhciIsICJkZWdyZWUiLCAidGhvcm4iLCAidGhyZWVxdWFydGVycyIsICJ0d29zdXBlcmlvciIsICJyZWdpc3RlcmVkIiwgIm1pbnVzIiwgImV0aCIsICJtdWx0aXBseSIsICJ0aHJlZXN1cGVyaW9yIiwgImNvcHlyaWdodCIsICJBYWN1dGUiLCAiQWNpcmN1bWZsZXgiLCAiQWRpZXJlc2lzIiwgIkFncmF2ZSIsICJBcmluZyIsICJBdGlsZGUiLCAiQ2NlZGlsbGEiLCAiRWFjdXRlIiwgIkVjaXJjdW1mbGV4IiwgIkVkaWVyZXNpcyIsICJFZ3JhdmUiLCAiSWFjdXRlIiwgIkljaXJjdW1mbGV4IiwgIklkaWVyZXNpcyIsICJJZ3JhdmUiLCAiTnRpbGRlIiwgIk9hY3V0ZSIsICJPY2lyY3VtZmxleCIsICJPZGllcmVzaXMiLCAiT2dyYXZlIiwgIk90aWxkZSIsICJTY2Fyb24iLCAiVWFjdXRlIiwgIlVjaXJjdW1mbGV4IiwgIlVkaWVyZXNpcyIsICJVZ3JhdmUiLCAiWWFjdXRlIiwgIllkaWVyZXNpcyIsICJaY2Fyb24iLCAiYWFjdXRlIiwgImFjaXJjdW1mbGV4IiwgImFkaWVyZXNpcyIsICJhZ3JhdmUiLCAiYXJpbmciLCAiYXRpbGRlIiwgImNjZWRpbGxhIiwgImVhY3V0ZSIsICJlY2lyY3VtZmxleCIsICJlZGllcmVzaXMiLCAiZWdyYXZlIiwgImlhY3V0ZSIsICJpY2lyY3VtZmxleCIsICJpZGllcmVzaXMiLCAiaWdyYXZlIiwgIm50aWxkZSIsICJvYWN1dGUiLCAib2NpcmN1bWZsZXgiLCAib2RpZXJlc2lzIiwgIm9ncmF2ZSIsICJvdGlsZGUiLCAic2Nhcm9uIiwgInVhY3V0ZSIsICJ1Y2lyY3VtZmxleCIsICJ1ZGllcmVzaXMiLCAidWdyYXZlIiwgInlhY3V0ZSIsICJ5ZGllcmVzaXMiLCAiemNhcm9uIl07CmNvbnN0IEV4cGVydENoYXJzZXQgPSBbIi5ub3RkZWYiLCAic3BhY2UiLCAiZXhjbGFtc21hbGwiLCAiSHVuZ2FydW1sYXV0c21hbGwiLCAiZG9sbGFyb2xkc3R5bGUiLCAiZG9sbGFyc3VwZXJpb3IiLCAiYW1wZXJzYW5kc21hbGwiLCAiQWN1dGVzbWFsbCIsICJwYXJlbmxlZnRzdXBlcmlvciIsICJwYXJlbnJpZ2h0c3VwZXJpb3IiLCAidHdvZG90ZW5sZWFkZXIiLCAib25lZG90ZW5sZWFkZXIiLCAiY29tbWEiLCAiaHlwaGVuIiwgInBlcmlvZCIsICJmcmFjdGlvbiIsICJ6ZXJvb2xkc3R5bGUiLCAib25lb2xkc3R5bGUiLCAidHdvb2xkc3R5bGUiLCAidGhyZWVvbGRzdHlsZSIsICJmb3Vyb2xkc3R5bGUiLCAiZml2ZW9sZHN0eWxlIiwgInNpeG9sZHN0eWxlIiwgInNldmVub2xkc3R5bGUiLCAiZWlnaHRvbGRzdHlsZSIsICJuaW5lb2xkc3R5bGUiLCAiY29sb24iLCAic2VtaWNvbG9uIiwgImNvbW1hc3VwZXJpb3IiLCAidGhyZWVxdWFydGVyc2VtZGFzaCIsICJwZXJpb2RzdXBlcmlvciIsICJxdWVzdGlvbnNtYWxsIiwgImFzdXBlcmlvciIsICJic3VwZXJpb3IiLCAiY2VudHN1cGVyaW9yIiwgImRzdXBlcmlvciIsICJlc3VwZXJpb3IiLCAiaXN1cGVyaW9yIiwgImxzdXBlcmlvciIsICJtc3VwZXJpb3IiLCAibnN1cGVyaW9yIiwgIm9zdXBlcmlvciIsICJyc3VwZXJpb3IiLCAic3N1cGVyaW9yIiwgInRzdXBlcmlvciIsICJmZiIsICJmaSIsICJmbCIsICJmZmkiLCAiZmZsIiwgInBhcmVubGVmdGluZmVyaW9yIiwgInBhcmVucmlnaHRpbmZlcmlvciIsICJDaXJjdW1mbGV4c21hbGwiLCAiaHlwaGVuc3VwZXJpb3IiLCAiR3JhdmVzbWFsbCIsICJBc21hbGwiLCAiQnNtYWxsIiwgIkNzbWFsbCIsICJEc21hbGwiLCAiRXNtYWxsIiwgIkZzbWFsbCIsICJHc21hbGwiLCAiSHNtYWxsIiwgIklzbWFsbCIsICJKc21hbGwiLCAiS3NtYWxsIiwgIkxzbWFsbCIsICJNc21hbGwiLCAiTnNtYWxsIiwgIk9zbWFsbCIsICJQc21hbGwiLCAiUXNtYWxsIiwgIlJzbWFsbCIsICJTc21hbGwiLCAiVHNtYWxsIiwgIlVzbWFsbCIsICJWc21hbGwiLCAiV3NtYWxsIiwgIlhzbWFsbCIsICJZc21hbGwiLCAiWnNtYWxsIiwgImNvbG9ubW9uZXRhcnkiLCAib25lZml0dGVkIiwgInJ1cGlhaCIsICJUaWxkZXNtYWxsIiwgImV4Y2xhbWRvd25zbWFsbCIsICJjZW50b2xkc3R5bGUiLCAiTHNsYXNoc21hbGwiLCAiU2Nhcm9uc21hbGwiLCAiWmNhcm9uc21hbGwiLCAiRGllcmVzaXNzbWFsbCIsICJCcmV2ZXNtYWxsIiwgIkNhcm9uc21hbGwiLCAiRG90YWNjZW50c21hbGwiLCAiTWFjcm9uc21hbGwiLCAiZmlndXJlZGFzaCIsICJoeXBoZW5pbmZlcmlvciIsICJPZ29uZWtzbWFsbCIsICJSaW5nc21hbGwiLCAiQ2VkaWxsYXNtYWxsIiwgIm9uZXF1YXJ0ZXIiLCAib25laGFsZiIsICJ0aHJlZXF1YXJ0ZXJzIiwgInF1ZXN0aW9uZG93bnNtYWxsIiwgIm9uZWVpZ2h0aCIsICJ0aHJlZWVpZ2h0aHMiLCAiZml2ZWVpZ2h0aHMiLCAic2V2ZW5laWdodGhzIiwgIm9uZXRoaXJkIiwgInR3b3RoaXJkcyIsICJ6ZXJvc3VwZXJpb3IiLCAib25lc3VwZXJpb3IiLCAidHdvc3VwZXJpb3IiLCAidGhyZWVzdXBlcmlvciIsICJmb3Vyc3VwZXJpb3IiLCAiZml2ZXN1cGVyaW9yIiwgInNpeHN1cGVyaW9yIiwgInNldmVuc3VwZXJpb3IiLCAiZWlnaHRzdXBlcmlvciIsICJuaW5lc3VwZXJpb3IiLCAiemVyb2luZmVyaW9yIiwgIm9uZWluZmVyaW9yIiwgInR3b2luZmVyaW9yIiwgInRocmVlaW5mZXJpb3IiLCAiZm91cmluZmVyaW9yIiwgImZpdmVpbmZlcmlvciIsICJzaXhpbmZlcmlvciIsICJzZXZlbmluZmVyaW9yIiwgImVpZ2h0aW5mZXJpb3IiLCAibmluZWluZmVyaW9yIiwgImNlbnRpbmZlcmlvciIsICJkb2xsYXJpbmZlcmlvciIsICJwZXJpb2RpbmZlcmlvciIsICJjb21tYWluZmVyaW9yIiwgIkFncmF2ZXNtYWxsIiwgIkFhY3V0ZXNtYWxsIiwgIkFjaXJjdW1mbGV4c21hbGwiLCAiQXRpbGRlc21hbGwiLCAiQWRpZXJlc2lzc21hbGwiLCAiQXJpbmdzbWFsbCIsICJBRXNtYWxsIiwgIkNjZWRpbGxhc21hbGwiLCAiRWdyYXZlc21hbGwiLCAiRWFjdXRlc21hbGwiLCAiRWNpcmN1bWZsZXhzbWFsbCIsICJFZGllcmVzaXNzbWFsbCIsICJJZ3JhdmVzbWFsbCIsICJJYWN1dGVzbWFsbCIsICJJY2lyY3VtZmxleHNtYWxsIiwgIklkaWVyZXNpc3NtYWxsIiwgIkV0aHNtYWxsIiwgIk50aWxkZXNtYWxsIiwgIk9ncmF2ZXNtYWxsIiwgIk9hY3V0ZXNtYWxsIiwgIk9jaXJjdW1mbGV4c21hbGwiLCAiT3RpbGRlc21hbGwiLCAiT2RpZXJlc2lzc21hbGwiLCAiT0VzbWFsbCIsICJPc2xhc2hzbWFsbCIsICJVZ3JhdmVzbWFsbCIsICJVYWN1dGVzbWFsbCIsICJVY2lyY3VtZmxleHNtYWxsIiwgIlVkaWVyZXNpc3NtYWxsIiwgIllhY3V0ZXNtYWxsIiwgIlRob3Juc21hbGwiLCAiWWRpZXJlc2lzc21hbGwiXTsKY29uc3QgRXhwZXJ0U3Vic2V0Q2hhcnNldCA9IFsiLm5vdGRlZiIsICJzcGFjZSIsICJkb2xsYXJvbGRzdHlsZSIsICJkb2xsYXJzdXBlcmlvciIsICJwYXJlbmxlZnRzdXBlcmlvciIsICJwYXJlbnJpZ2h0c3VwZXJpb3IiLCAidHdvZG90ZW5sZWFkZXIiLCAib25lZG90ZW5sZWFkZXIiLCAiY29tbWEiLCAiaHlwaGVuIiwgInBlcmlvZCIsICJmcmFjdGlvbiIsICJ6ZXJvb2xkc3R5bGUiLCAib25lb2xkc3R5bGUiLCAidHdvb2xkc3R5bGUiLCAidGhyZWVvbGRzdHlsZSIsICJmb3Vyb2xkc3R5bGUiLCAiZml2ZW9sZHN0eWxlIiwgInNpeG9sZHN0eWxlIiwgInNldmVub2xkc3R5bGUiLCAiZWlnaHRvbGRzdHlsZSIsICJuaW5lb2xkc3R5bGUiLCAiY29sb24iLCAic2VtaWNvbG9uIiwgImNvbW1hc3VwZXJpb3IiLCAidGhyZWVxdWFydGVyc2VtZGFzaCIsICJwZXJpb2RzdXBlcmlvciIsICJhc3VwZXJpb3IiLCAiYnN1cGVyaW9yIiwgImNlbnRzdXBlcmlvciIsICJkc3VwZXJpb3IiLCAiZXN1cGVyaW9yIiwgImlzdXBlcmlvciIsICJsc3VwZXJpb3IiLCAibXN1cGVyaW9yIiwgIm5zdXBlcmlvciIsICJvc3VwZXJpb3IiLCAicnN1cGVyaW9yIiwgInNzdXBlcmlvciIsICJ0c3VwZXJpb3IiLCAiZmYiLCAiZmkiLCAiZmwiLCAiZmZpIiwgImZmbCIsICJwYXJlbmxlZnRpbmZlcmlvciIsICJwYXJlbnJpZ2h0aW5mZXJpb3IiLCAiaHlwaGVuc3VwZXJpb3IiLCAiY29sb25tb25ldGFyeSIsICJvbmVmaXR0ZWQiLCAicnVwaWFoIiwgImNlbnRvbGRzdHlsZSIsICJmaWd1cmVkYXNoIiwgImh5cGhlbmluZmVyaW9yIiwgIm9uZXF1YXJ0ZXIiLCAib25laGFsZiIsICJ0aHJlZXF1YXJ0ZXJzIiwgIm9uZWVpZ2h0aCIsICJ0aHJlZWVpZ2h0aHMiLCAiZml2ZWVpZ2h0aHMiLCAic2V2ZW5laWdodGhzIiwgIm9uZXRoaXJkIiwgInR3b3RoaXJkcyIsICJ6ZXJvc3VwZXJpb3IiLCAib25lc3VwZXJpb3IiLCAidHdvc3VwZXJpb3IiLCAidGhyZWVzdXBlcmlvciIsICJmb3Vyc3VwZXJpb3IiLCAiZml2ZXN1cGVyaW9yIiwgInNpeHN1cGVyaW9yIiwgInNldmVuc3VwZXJpb3IiLCAiZWlnaHRzdXBlcmlvciIsICJuaW5lc3VwZXJpb3IiLCAiemVyb2luZmVyaW9yIiwgIm9uZWluZmVyaW9yIiwgInR3b2luZmVyaW9yIiwgInRocmVlaW5mZXJpb3IiLCAiZm91cmluZmVyaW9yIiwgImZpdmVpbmZlcmlvciIsICJzaXhpbmZlcmlvciIsICJzZXZlbmluZmVyaW9yIiwgImVpZ2h0aW5mZXJpb3IiLCAibmluZWluZmVyaW9yIiwgImNlbnRpbmZlcmlvciIsICJkb2xsYXJpbmZlcmlvciIsICJwZXJpb2RpbmZlcmlvciIsICJjb21tYWluZmVyaW9yIl07Cgo7Ly8gLi9zcmMvY29yZS9jZmZfcGFyc2VyLmpzCgoKCgoKCgoKCgoKCgpjb25zdCBNQVhfU1VCUl9ORVNUSU5HID0gMTA7CmNvbnN0IENGRlN0YW5kYXJkU3RyaW5ncyA9IFsiLm5vdGRlZiIsICJzcGFjZSIsICJleGNsYW0iLCAicXVvdGVkYmwiLCAibnVtYmVyc2lnbiIsICJkb2xsYXIiLCAicGVyY2VudCIsICJhbXBlcnNhbmQiLCAicXVvdGVyaWdodCIsICJwYXJlbmxlZnQiLCAicGFyZW5yaWdodCIsICJhc3RlcmlzayIsICJwbHVzIiwgImNvbW1hIiwgImh5cGhlbiIsICJwZXJpb2QiLCAic2xhc2giLCAiemVybyIsICJvbmUiLCAidHdvIiwgInRocmVlIiwgImZvdXIiLCAiZml2ZSIsICJzaXgiLCAic2V2ZW4iLCAiZWlnaHQiLCAibmluZSIsICJjb2xvbiIsICJzZW1pY29sb24iLCAibGVzcyIsICJlcXVhbCIsICJncmVhdGVyIiwgInF1ZXN0aW9uIiwgImF0IiwgIkEiLCAiQiIsICJDIiwgIkQiLCAiRSIsICJGIiwgIkciLCAiSCIsICJJIiwgIkoiLCAiSyIsICJMIiwgIk0iLCAiTiIsICJPIiwgIlAiLCAiUSIsICJSIiwgIlMiLCAiVCIsICJVIiwgIlYiLCAiVyIsICJYIiwgIlkiLCAiWiIsICJicmFja2V0bGVmdCIsICJiYWNrc2xhc2giLCAiYnJhY2tldHJpZ2h0IiwgImFzY2lpY2lyY3VtIiwgInVuZGVyc2NvcmUiLCAicXVvdGVsZWZ0IiwgImEiLCAiYiIsICJjIiwgImQiLCAiZSIsICJmIiwgImciLCAiaCIsICJpIiwgImoiLCAiayIsICJsIiwgIm0iLCAibiIsICJvIiwgInAiLCAicSIsICJyIiwgInMiLCAidCIsICJ1IiwgInYiLCAidyIsICJ4IiwgInkiLCAieiIsICJicmFjZWxlZnQiLCAiYmFyIiwgImJyYWNlcmlnaHQiLCAiYXNjaWl0aWxkZSIsICJleGNsYW1kb3duIiwgImNlbnQiLCAic3RlcmxpbmciLCAiZnJhY3Rpb24iLCAieWVuIiwgImZsb3JpbiIsICJzZWN0aW9uIiwgImN1cnJlbmN5IiwgInF1b3Rlc2luZ2xlIiwgInF1b3RlZGJsbGVmdCIsICJndWlsbGVtb3RsZWZ0IiwgImd1aWxzaW5nbGxlZnQiLCAiZ3VpbHNpbmdscmlnaHQiLCAiZmkiLCAiZmwiLCAiZW5kYXNoIiwgImRhZ2dlciIsICJkYWdnZXJkYmwiLCAicGVyaW9kY2VudGVyZWQiLCAicGFyYWdyYXBoIiwgImJ1bGxldCIsICJxdW90ZXNpbmdsYmFzZSIsICJxdW90ZWRibGJhc2UiLCAicXVvdGVkYmxyaWdodCIsICJndWlsbGVtb3RyaWdodCIsICJlbGxpcHNpcyIsICJwZXJ0aG91c2FuZCIsICJxdWVzdGlvbmRvd24iLCAiZ3JhdmUiLCAiYWN1dGUiLCAiY2lyY3VtZmxleCIsICJ0aWxkZSIsICJtYWNyb24iLCAiYnJldmUiLCAiZG90YWNjZW50IiwgImRpZXJlc2lzIiwgInJpbmciLCAiY2VkaWxsYSIsICJodW5nYXJ1bWxhdXQiLCAib2dvbmVrIiwgImNhcm9uIiwgImVtZGFzaCIsICJBRSIsICJvcmRmZW1pbmluZSIsICJMc2xhc2giLCAiT3NsYXNoIiwgIk9FIiwgIm9yZG1hc2N1bGluZSIsICJhZSIsICJkb3RsZXNzaSIsICJsc2xhc2giLCAib3NsYXNoIiwgIm9lIiwgImdlcm1hbmRibHMiLCAib25lc3VwZXJpb3IiLCAibG9naWNhbG5vdCIsICJtdSIsICJ0cmFkZW1hcmsiLCAiRXRoIiwgIm9uZWhhbGYiLCAicGx1c21pbnVzIiwgIlRob3JuIiwgIm9uZXF1YXJ0ZXIiLCAiZGl2aWRlIiwgImJyb2tlbmJhciIsICJkZWdyZWUiLCAidGhvcm4iLCAidGhyZWVxdWFydGVycyIsICJ0d29zdXBlcmlvciIsICJyZWdpc3RlcmVkIiwgIm1pbnVzIiwgImV0aCIsICJtdWx0aXBseSIsICJ0aHJlZXN1cGVyaW9yIiwgImNvcHlyaWdodCIsICJBYWN1dGUiLCAiQWNpcmN1bWZsZXgiLCAiQWRpZXJlc2lzIiwgIkFncmF2ZSIsICJBcmluZyIsICJBdGlsZGUiLCAiQ2NlZGlsbGEiLCAiRWFjdXRlIiwgIkVjaXJjdW1mbGV4IiwgIkVkaWVyZXNpcyIsICJFZ3JhdmUiLCAiSWFjdXRlIiwgIkljaXJjdW1mbGV4IiwgIklkaWVyZXNpcyIsICJJZ3JhdmUiLCAiTnRpbGRlIiwgIk9hY3V0ZSIsICJPY2lyY3VtZmxleCIsICJPZGllcmVzaXMiLCAiT2dyYXZlIiwgIk90aWxkZSIsICJTY2Fyb24iLCAiVWFjdXRlIiwgIlVjaXJjdW1mbGV4IiwgIlVkaWVyZXNpcyIsICJVZ3JhdmUiLCAiWWFjdXRlIiwgIllkaWVyZXNpcyIsICJaY2Fyb24iLCAiYWFjdXRlIiwgImFjaXJjdW1mbGV4IiwgImFkaWVyZXNpcyIsICJhZ3JhdmUiLCAiYXJpbmciLCAiYXRpbGRlIiwgImNjZWRpbGxhIiwgImVhY3V0ZSIsICJlY2lyY3VtZmxleCIsICJlZGllcmVzaXMiLCAiZWdyYXZlIiwgImlhY3V0ZSIsICJpY2lyY3VtZmxleCIsICJpZGllcmVzaXMiLCAiaWdyYXZlIiwgIm50aWxkZSIsICJvYWN1dGUiLCAib2NpcmN1bWZsZXgiLCAib2RpZXJlc2lzIiwgIm9ncmF2ZSIsICJvdGlsZGUiLCAic2Nhcm9uIiwgInVhY3V0ZSIsICJ1Y2lyY3VtZmxleCIsICJ1ZGllcmVzaXMiLCAidWdyYXZlIiwgInlhY3V0ZSIsICJ5ZGllcmVzaXMiLCAiemNhcm9uIiwgImV4Y2xhbXNtYWxsIiwgIkh1bmdhcnVtbGF1dHNtYWxsIiwgImRvbGxhcm9sZHN0eWxlIiwgImRvbGxhcnN1cGVyaW9yIiwgImFtcGVyc2FuZHNtYWxsIiwgIkFjdXRlc21hbGwiLCAicGFyZW5sZWZ0c3VwZXJpb3IiLCAicGFyZW5yaWdodHN1cGVyaW9yIiwgInR3b2RvdGVubGVhZGVyIiwgIm9uZWRvdGVubGVhZGVyIiwgInplcm9vbGRzdHlsZSIsICJvbmVvbGRzdHlsZSIsICJ0d29vbGRzdHlsZSIsICJ0aHJlZW9sZHN0eWxlIiwgImZvdXJvbGRzdHlsZSIsICJmaXZlb2xkc3R5bGUiLCAic2l4b2xkc3R5bGUiLCAic2V2ZW5vbGRzdHlsZSIsICJlaWdodG9sZHN0eWxlIiwgIm5pbmVvbGRzdHlsZSIsICJjb21tYXN1cGVyaW9yIiwgInRocmVlcXVhcnRlcnNlbWRhc2giLCAicGVyaW9kc3VwZXJpb3IiLCAicXVlc3Rpb25zbWFsbCIsICJhc3VwZXJpb3IiLCAiYnN1cGVyaW9yIiwgImNlbnRzdXBlcmlvciIsICJkc3VwZXJpb3IiLCAiZXN1cGVyaW9yIiwgImlzdXBlcmlvciIsICJsc3VwZXJpb3IiLCAibXN1cGVyaW9yIiwgIm5zdXBlcmlvciIsICJvc3VwZXJpb3IiLCAicnN1cGVyaW9yIiwgInNzdXBlcmlvciIsICJ0c3VwZXJpb3IiLCAiZmYiLCAiZmZpIiwgImZmbCIsICJwYXJlbmxlZnRpbmZlcmlvciIsICJwYXJlbnJpZ2h0aW5mZXJpb3IiLCAiQ2lyY3VtZmxleHNtYWxsIiwgImh5cGhlbnN1cGVyaW9yIiwgIkdyYXZlc21hbGwiLCAiQXNtYWxsIiwgIkJzbWFsbCIsICJDc21hbGwiLCAiRHNtYWxsIiwgIkVzbWFsbCIsICJGc21hbGwiLCAiR3NtYWxsIiwgIkhzbWFsbCIsICJJc21hbGwiLCAiSnNtYWxsIiwgIktzbWFsbCIsICJMc21hbGwiLCAiTXNtYWxsIiwgIk5zbWFsbCIsICJPc21hbGwiLCAiUHNtYWxsIiwgIlFzbWFsbCIsICJSc21hbGwiLCAiU3NtYWxsIiwgIlRzbWFsbCIsICJVc21hbGwiLCAiVnNtYWxsIiwgIldzbWFsbCIsICJYc21hbGwiLCAiWXNtYWxsIiwgIlpzbWFsbCIsICJjb2xvbm1vbmV0YXJ5IiwgIm9uZWZpdHRlZCIsICJydXBpYWgiLCAiVGlsZGVzbWFsbCIsICJleGNsYW1kb3duc21hbGwiLCAiY2VudG9sZHN0eWxlIiwgIkxzbGFzaHNtYWxsIiwgIlNjYXJvbnNtYWxsIiwgIlpjYXJvbnNtYWxsIiwgIkRpZXJlc2lzc21hbGwiLCAiQnJldmVzbWFsbCIsICJDYXJvbnNtYWxsIiwgIkRvdGFjY2VudHNtYWxsIiwgIk1hY3JvbnNtYWxsIiwgImZpZ3VyZWRhc2giLCAiaHlwaGVuaW5mZXJpb3IiLCAiT2dvbmVrc21hbGwiLCAiUmluZ3NtYWxsIiwgIkNlZGlsbGFzbWFsbCIsICJxdWVzdGlvbmRvd25zbWFsbCIsICJvbmVlaWdodGgiLCAidGhyZWVlaWdodGhzIiwgImZpdmVlaWdodGhzIiwgInNldmVuZWlnaHRocyIsICJvbmV0aGlyZCIsICJ0d290aGlyZHMiLCAiemVyb3N1cGVyaW9yIiwgImZvdXJzdXBlcmlvciIsICJmaXZlc3VwZXJpb3IiLCAic2l4c3VwZXJpb3IiLCAic2V2ZW5zdXBlcmlvciIsICJlaWdodHN1cGVyaW9yIiwgIm5pbmVzdXBlcmlvciIsICJ6ZXJvaW5mZXJpb3IiLCAib25laW5mZXJpb3IiLCAidHdvaW5mZXJpb3IiLCAidGhyZWVpbmZlcmlvciIsICJmb3VyaW5mZXJpb3IiLCAiZml2ZWluZmVyaW9yIiwgInNpeGluZmVyaW9yIiwgInNldmVuaW5mZXJpb3IiLCAiZWlnaHRpbmZlcmlvciIsICJuaW5laW5mZXJpb3IiLCAiY2VudGluZmVyaW9yIiwgImRvbGxhcmluZmVyaW9yIiwgInBlcmlvZGluZmVyaW9yIiwgImNvbW1haW5mZXJpb3IiLCAiQWdyYXZlc21hbGwiLCAiQWFjdXRlc21hbGwiLCAiQWNpcmN1bWZsZXhzbWFsbCIsICJBdGlsZGVzbWFsbCIsICJBZGllcmVzaXNzbWFsbCIsICJBcmluZ3NtYWxsIiwgIkFFc21hbGwiLCAiQ2NlZGlsbGFzbWFsbCIsICJFZ3JhdmVzbWFsbCIsICJFYWN1dGVzbWFsbCIsICJFY2lyY3VtZmxleHNtYWxsIiwgIkVkaWVyZXNpc3NtYWxsIiwgIklncmF2ZXNtYWxsIiwgIklhY3V0ZXNtYWxsIiwgIkljaXJjdW1mbGV4c21hbGwiLCAiSWRpZXJlc2lzc21hbGwiLCAiRXRoc21hbGwiLCAiTnRpbGRlc21hbGwiLCAiT2dyYXZlc21hbGwiLCAiT2FjdXRlc21hbGwiLCAiT2NpcmN1bWZsZXhzbWFsbCIsICJPdGlsZGVzbWFsbCIsICJPZGllcmVzaXNzbWFsbCIsICJPRXNtYWxsIiwgIk9zbGFzaHNtYWxsIiwgIlVncmF2ZXNtYWxsIiwgIlVhY3V0ZXNtYWxsIiwgIlVjaXJjdW1mbGV4c21hbGwiLCAiVWRpZXJlc2lzc21hbGwiLCAiWWFjdXRlc21hbGwiLCAiVGhvcm5zbWFsbCIsICJZZGllcmVzaXNzbWFsbCIsICIwMDEuMDAwIiwgIjAwMS4wMDEiLCAiMDAxLjAwMiIsICIwMDEuMDAzIiwgIkJsYWNrIiwgIkJvbGQiLCAiQm9vayIsICJMaWdodCIsICJNZWRpdW0iLCAiUmVndWxhciIsICJSb21hbiIsICJTZW1pYm9sZCJdOwpjb25zdCBOVU1fU1RBTkRBUkRfQ0ZGX1NUUklOR1MgPSAzOTE7CmNvbnN0IENoYXJzdHJpbmdWYWxpZGF0aW9uRGF0YSA9IFtudWxsLCB7CiAgaWQ6ICJoc3RlbSIsCiAgbWluOiAyLAogIHN0YWNrQ2xlYXJpbmc6IHRydWUsCiAgc3RlbTogdHJ1ZQp9LCBudWxsLCB7CiAgaWQ6ICJ2c3RlbSIsCiAgbWluOiAyLAogIHN0YWNrQ2xlYXJpbmc6IHRydWUsCiAgc3RlbTogdHJ1ZQp9LCB7CiAgaWQ6ICJ2bW92ZXRvIiwKICBtaW46IDEsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZQp9LCB7CiAgaWQ6ICJybGluZXRvIiwKICBtaW46IDIsCiAgcmVzZXRTdGFjazogdHJ1ZQp9LCB7CiAgaWQ6ICJobGluZXRvIiwKICBtaW46IDEsCiAgcmVzZXRTdGFjazogdHJ1ZQp9LCB7CiAgaWQ6ICJ2bGluZXRvIiwKICBtaW46IDEsCiAgcmVzZXRTdGFjazogdHJ1ZQp9LCB7CiAgaWQ6ICJycmN1cnZldG8iLAogIG1pbjogNiwKICByZXNldFN0YWNrOiB0cnVlCn0sIG51bGwsIHsKICBpZDogImNhbGxzdWJyIiwKICBtaW46IDEsCiAgdW5kZWZTdGFjazogdHJ1ZQp9LCB7CiAgaWQ6ICJyZXR1cm4iLAogIG1pbjogMCwKICB1bmRlZlN0YWNrOiB0cnVlCn0sIG51bGwsIG51bGwsIHsKICBpZDogImVuZGNoYXIiLAogIG1pbjogMCwKICBzdGFja0NsZWFyaW5nOiB0cnVlCn0sIG51bGwsIG51bGwsIG51bGwsIHsKICBpZDogImhzdGVtaG0iLAogIG1pbjogMiwKICBzdGFja0NsZWFyaW5nOiB0cnVlLAogIHN0ZW06IHRydWUKfSwgewogIGlkOiAiaGludG1hc2siLAogIG1pbjogMCwKICBzdGFja0NsZWFyaW5nOiB0cnVlCn0sIHsKICBpZDogImNudHJtYXNrIiwKICBtaW46IDAsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZQp9LCB7CiAgaWQ6ICJybW92ZXRvIiwKICBtaW46IDIsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZQp9LCB7CiAgaWQ6ICJobW92ZXRvIiwKICBtaW46IDEsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZQp9LCB7CiAgaWQ6ICJ2c3RlbWhtIiwKICBtaW46IDIsCiAgc3RhY2tDbGVhcmluZzogdHJ1ZSwKICBzdGVtOiB0cnVlCn0sIHsKICBpZDogInJjdXJ2ZWxpbmUiLAogIG1pbjogOCwKICByZXNldFN0YWNrOiB0cnVlCn0sIHsKICBpZDogInJsaW5lY3VydmUiLAogIG1pbjogOCwKICByZXNldFN0YWNrOiB0cnVlCn0sIHsKICBpZDogInZ2Y3VydmV0byIsCiAgbWluOiA0LAogIHJlc2V0U3RhY2s6IHRydWUKfSwgewogIGlkOiAiaGhjdXJ2ZXRvIiwKICBtaW46IDQsCiAgcmVzZXRTdGFjazogdHJ1ZQp9LCBudWxsLCB7CiAgaWQ6ICJjYWxsZ3N1YnIiLAogIG1pbjogMSwKICB1bmRlZlN0YWNrOiB0cnVlCn0sIHsKICBpZDogInZoY3VydmV0byIsCiAgbWluOiA0LAogIHJlc2V0U3RhY2s6IHRydWUKfSwgewogIGlkOiAiaHZjdXJ2ZXRvIiwKICBtaW46IDQsCiAgcmVzZXRTdGFjazogdHJ1ZQp9XTsKY29uc3QgQ2hhcnN0cmluZ1ZhbGlkYXRpb25EYXRhMTIgPSBbbnVsbCwgbnVsbCwgbnVsbCwgewogIGlkOiAiYW5kIiwKICBtaW46IDIsCiAgc3RhY2tEZWx0YTogLTEKfSwgewogIGlkOiAib3IiLAogIG1pbjogMiwKICBzdGFja0RlbHRhOiAtMQp9LCB7CiAgaWQ6ICJub3QiLAogIG1pbjogMSwKICBzdGFja0RlbHRhOiAwCn0sIG51bGwsIG51bGwsIG51bGwsIHsKICBpZDogImFicyIsCiAgbWluOiAxLAogIHN0YWNrRGVsdGE6IDAKfSwgewogIGlkOiAiYWRkIiwKICBtaW46IDIsCiAgc3RhY2tEZWx0YTogLTEsCiAgc3RhY2tGbihzdGFjaywgaW5kZXgpIHsKICAgIHN0YWNrW2luZGV4IC0gMl0gPSBzdGFja1tpbmRleCAtIDJdICsgc3RhY2tbaW5kZXggLSAxXTsKICB9Cn0sIHsKICBpZDogInN1YiIsCiAgbWluOiAyLAogIHN0YWNrRGVsdGE6IC0xLAogIHN0YWNrRm4oc3RhY2ssIGluZGV4KSB7CiAgICBzdGFja1tpbmRleCAtIDJdID0gc3RhY2tbaW5kZXggLSAyXSAtIHN0YWNrW2luZGV4IC0gMV07CiAgfQp9LCB7CiAgaWQ6ICJkaXYiLAogIG1pbjogMiwKICBzdGFja0RlbHRhOiAtMSwKICBzdGFja0ZuKHN0YWNrLCBpbmRleCkgewogICAgc3RhY2tbaW5kZXggLSAyXSA9IHN0YWNrW2luZGV4IC0gMl0gLyBzdGFja1tpbmRleCAtIDFdOwogIH0KfSwgbnVsbCwgewogIGlkOiAibmVnIiwKICBtaW46IDEsCiAgc3RhY2tEZWx0YTogMCwKICBzdGFja0ZuKHN0YWNrLCBpbmRleCkgewogICAgc3RhY2tbaW5kZXggLSAxXSA9IC1zdGFja1tpbmRleCAtIDFdOwogIH0KfSwgewogIGlkOiAiZXEiLAogIG1pbjogMiwKICBzdGFja0RlbHRhOiAtMQp9LCBudWxsLCBudWxsLCB7CiAgaWQ6ICJkcm9wIiwKICBtaW46IDEsCiAgc3RhY2tEZWx0YTogLTEKfSwgbnVsbCwgewogIGlkOiAicHV0IiwKICBtaW46IDIsCiAgc3RhY2tEZWx0YTogLTIKfSwgewogIGlkOiAiZ2V0IiwKICBtaW46IDEsCiAgc3RhY2tEZWx0YTogMAp9LCB7CiAgaWQ6ICJpZmVsc2UiLAogIG1pbjogNCwKICBzdGFja0RlbHRhOiAtMwp9LCB7CiAgaWQ6ICJyYW5kb20iLAogIG1pbjogMCwKICBzdGFja0RlbHRhOiAxCn0sIHsKICBpZDogIm11bCIsCiAgbWluOiAyLAogIHN0YWNrRGVsdGE6IC0xLAogIHN0YWNrRm4oc3RhY2ssIGluZGV4KSB7CiAgICBzdGFja1tpbmRleCAtIDJdID0gc3RhY2tbaW5kZXggLSAyXSAqIHN0YWNrW2luZGV4IC0gMV07CiAgfQp9LCBudWxsLCB7CiAgaWQ6ICJzcXJ0IiwKICBtaW46IDEsCiAgc3RhY2tEZWx0YTogMAp9LCB7CiAgaWQ6ICJkdXAiLAogIG1pbjogMSwKICBzdGFja0RlbHRhOiAxCn0sIHsKICBpZDogImV4Y2giLAogIG1pbjogMiwKICBzdGFja0RlbHRhOiAwCn0sIHsKICBpZDogImluZGV4IiwKICBtaW46IDIsCiAgc3RhY2tEZWx0YTogMAp9LCB7CiAgaWQ6ICJyb2xsIiwKICBtaW46IDMsCiAgc3RhY2tEZWx0YTogLTIKfSwgbnVsbCwgbnVsbCwgbnVsbCwgewogIGlkOiAiaGZsZXgiLAogIG1pbjogNywKICByZXNldFN0YWNrOiB0cnVlCn0sIHsKICBpZDogImZsZXgiLAogIG1pbjogMTMsCiAgcmVzZXRTdGFjazogdHJ1ZQp9LCB7CiAgaWQ6ICJoZmxleDEiLAogIG1pbjogOSwKICByZXNldFN0YWNrOiB0cnVlCn0sIHsKICBpZDogImZsZXgxIiwKICBtaW46IDExLAogIHJlc2V0U3RhY2s6IHRydWUKfV07CmNsYXNzIENGRlBhcnNlciB7CiAgY29uc3RydWN0b3IoZmlsZSwgcHJvcGVydGllcywgc2VhY0FuYWx5c2lzRW5hYmxlZCkgewogICAgdGhpcy5ieXRlcyA9IGZpbGUuZ2V0Qnl0ZXMoKTsKICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXM7CiAgICB0aGlzLnNlYWNBbmFseXNpc0VuYWJsZWQgPSAhIXNlYWNBbmFseXNpc0VuYWJsZWQ7CiAgfQogIHBhcnNlKCkgewogICAgY29uc3QgcHJvcGVydGllcyA9IHRoaXMucHJvcGVydGllczsKICAgIGNvbnN0IGNmZiA9IG5ldyBDRkYoKTsKICAgIHRoaXMuY2ZmID0gY2ZmOwogICAgY29uc3QgaGVhZGVyID0gdGhpcy5wYXJzZUhlYWRlcigpOwogICAgY29uc3QgbmFtZUluZGV4ID0gdGhpcy5wYXJzZUluZGV4KGhlYWRlci5lbmRQb3MpOwogICAgY29uc3QgdG9wRGljdEluZGV4ID0gdGhpcy5wYXJzZUluZGV4KG5hbWVJbmRleC5lbmRQb3MpOwogICAgY29uc3Qgc3RyaW5nSW5kZXggPSB0aGlzLnBhcnNlSW5kZXgodG9wRGljdEluZGV4LmVuZFBvcyk7CiAgICBjb25zdCBnbG9iYWxTdWJySW5kZXggPSB0aGlzLnBhcnNlSW5kZXgoc3RyaW5nSW5kZXguZW5kUG9zKTsKICAgIGNvbnN0IHRvcERpY3RQYXJzZWQgPSB0aGlzLnBhcnNlRGljdCh0b3BEaWN0SW5kZXgub2JqLmdldCgwKSk7CiAgICBjb25zdCB0b3BEaWN0ID0gdGhpcy5jcmVhdGVEaWN0KENGRlRvcERpY3QsIHRvcERpY3RQYXJzZWQsIGNmZi5zdHJpbmdzKTsKICAgIGNmZi5oZWFkZXIgPSBoZWFkZXIub2JqOwogICAgY2ZmLm5hbWVzID0gdGhpcy5wYXJzZU5hbWVJbmRleChuYW1lSW5kZXgub2JqKTsKICAgIGNmZi5zdHJpbmdzID0gdGhpcy5wYXJzZVN0cmluZ0luZGV4KHN0cmluZ0luZGV4Lm9iaik7CiAgICBjZmYudG9wRGljdCA9IHRvcERpY3Q7CiAgICBjZmYuZ2xvYmFsU3VickluZGV4ID0gZ2xvYmFsU3VickluZGV4Lm9iajsKICAgIHRoaXMucGFyc2VQcml2YXRlRGljdChjZmYudG9wRGljdCk7CiAgICBjZmYuaXNDSURGb250ID0gdG9wRGljdC5oYXNOYW1lKCJST1MiKTsKICAgIGNvbnN0IGNoYXJTdHJpbmdPZmZzZXQgPSB0b3BEaWN0LmdldEJ5TmFtZSgiQ2hhclN0cmluZ3MiKTsKICAgIGNvbnN0IGNoYXJTdHJpbmdJbmRleCA9IHRoaXMucGFyc2VJbmRleChjaGFyU3RyaW5nT2Zmc2V0KS5vYmo7CiAgICBjb25zdCBmb250TWF0cml4ID0gdG9wRGljdC5nZXRCeU5hbWUoIkZvbnRNYXRyaXgiKTsKICAgIGlmIChmb250TWF0cml4KSB7CiAgICAgIHByb3BlcnRpZXMuZm9udE1hdHJpeCA9IGZvbnRNYXRyaXg7CiAgICB9CiAgICBjb25zdCBmb250QkJveCA9IHRvcERpY3QuZ2V0QnlOYW1lKCJGb250QkJveCIpOwogICAgaWYgKGZvbnRCQm94KSB7CiAgICAgIHByb3BlcnRpZXMuYXNjZW50ID0gTWF0aC5tYXgoZm9udEJCb3hbM10sIGZvbnRCQm94WzFdKTsKICAgICAgcHJvcGVydGllcy5kZXNjZW50ID0gTWF0aC5taW4oZm9udEJCb3hbMV0sIGZvbnRCQm94WzNdKTsKICAgICAgcHJvcGVydGllcy5hc2NlbnRTY2FsZWQgPSB0cnVlOwogICAgfQogICAgbGV0IGNoYXJzZXQsIGVuY29kaW5nOwogICAgaWYgKGNmZi5pc0NJREZvbnQpIHsKICAgICAgY29uc3QgZmRBcnJheUluZGV4ID0gdGhpcy5wYXJzZUluZGV4KHRvcERpY3QuZ2V0QnlOYW1lKCJGREFycmF5IikpLm9iajsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZmRBcnJheUluZGV4LmNvdW50OyBpIDwgaWk7ICsraSkgewogICAgICAgIGNvbnN0IGRpY3RSYXcgPSBmZEFycmF5SW5kZXguZ2V0KGkpOwogICAgICAgIGNvbnN0IGZvbnREaWN0ID0gdGhpcy5jcmVhdGVEaWN0KENGRlRvcERpY3QsIHRoaXMucGFyc2VEaWN0KGRpY3RSYXcpLCBjZmYuc3RyaW5ncyk7CiAgICAgICAgdGhpcy5wYXJzZVByaXZhdGVEaWN0KGZvbnREaWN0KTsKICAgICAgICBjZmYuZmRBcnJheS5wdXNoKGZvbnREaWN0KTsKICAgICAgfQogICAgICBlbmNvZGluZyA9IG51bGw7CiAgICAgIGNoYXJzZXQgPSB0aGlzLnBhcnNlQ2hhcnNldHModG9wRGljdC5nZXRCeU5hbWUoImNoYXJzZXQiKSwgY2hhclN0cmluZ0luZGV4LmNvdW50LCBjZmYuc3RyaW5ncywgdHJ1ZSk7CiAgICAgIGNmZi5mZFNlbGVjdCA9IHRoaXMucGFyc2VGRFNlbGVjdCh0b3BEaWN0LmdldEJ5TmFtZSgiRkRTZWxlY3QiKSwgY2hhclN0cmluZ0luZGV4LmNvdW50KTsKICAgIH0gZWxzZSB7CiAgICAgIGNoYXJzZXQgPSB0aGlzLnBhcnNlQ2hhcnNldHModG9wRGljdC5nZXRCeU5hbWUoImNoYXJzZXQiKSwgY2hhclN0cmluZ0luZGV4LmNvdW50LCBjZmYuc3RyaW5ncywgZmFsc2UpOwogICAgICBlbmNvZGluZyA9IHRoaXMucGFyc2VFbmNvZGluZyh0b3BEaWN0LmdldEJ5TmFtZSgiRW5jb2RpbmciKSwgcHJvcGVydGllcywgY2ZmLnN0cmluZ3MsIGNoYXJzZXQuY2hhcnNldCk7CiAgICB9CiAgICBjZmYuY2hhcnNldCA9IGNoYXJzZXQ7CiAgICBjZmYuZW5jb2RpbmcgPSBlbmNvZGluZzsKICAgIGNvbnN0IGNoYXJTdHJpbmdzQW5kU2VhY3MgPSB0aGlzLnBhcnNlQ2hhclN0cmluZ3MoewogICAgICBjaGFyU3RyaW5nczogY2hhclN0cmluZ0luZGV4LAogICAgICBsb2NhbFN1YnJJbmRleDogdG9wRGljdC5wcml2YXRlRGljdC5zdWJyc0luZGV4LAogICAgICBnbG9iYWxTdWJySW5kZXg6IGdsb2JhbFN1YnJJbmRleC5vYmosCiAgICAgIGZkU2VsZWN0OiBjZmYuZmRTZWxlY3QsCiAgICAgIGZkQXJyYXk6IGNmZi5mZEFycmF5LAogICAgICBwcml2YXRlRGljdDogdG9wRGljdC5wcml2YXRlRGljdAogICAgfSk7CiAgICBjZmYuY2hhclN0cmluZ3MgPSBjaGFyU3RyaW5nc0FuZFNlYWNzLmNoYXJTdHJpbmdzOwogICAgY2ZmLnNlYWNzID0gY2hhclN0cmluZ3NBbmRTZWFjcy5zZWFjczsKICAgIGNmZi53aWR0aHMgPSBjaGFyU3RyaW5nc0FuZFNlYWNzLndpZHRoczsKICAgIHJldHVybiBjZmY7CiAgfQogIHBhcnNlSGVhZGVyKCkgewogICAgbGV0IGJ5dGVzID0gdGhpcy5ieXRlczsKICAgIGNvbnN0IGJ5dGVzTGVuZ3RoID0gYnl0ZXMubGVuZ3RoOwogICAgbGV0IG9mZnNldCA9IDA7CiAgICB3aGlsZSAob2Zmc2V0IDwgYnl0ZXNMZW5ndGggJiYgYnl0ZXNbb2Zmc2V0XSAhPT0gMSkgewogICAgICArK29mZnNldDsKICAgIH0KICAgIGlmIChvZmZzZXQgPj0gYnl0ZXNMZW5ndGgpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIENGRiBoZWFkZXIiKTsKICAgIH0KICAgIGlmIChvZmZzZXQgIT09IDApIHsKICAgICAgaW5mbygiY2ZmIGRhdGEgaXMgc2hpZnRlZCIpOwogICAgICBieXRlcyA9IGJ5dGVzLnN1YmFycmF5KG9mZnNldCk7CiAgICAgIHRoaXMuYnl0ZXMgPSBieXRlczsKICAgIH0KICAgIGNvbnN0IG1ham9yID0gYnl0ZXNbMF07CiAgICBjb25zdCBtaW5vciA9IGJ5dGVzWzFdOwogICAgY29uc3QgaGRyU2l6ZSA9IGJ5dGVzWzJdOwogICAgY29uc3Qgb2ZmU2l6ZSA9IGJ5dGVzWzNdOwogICAgY29uc3QgaGVhZGVyID0gbmV3IENGRkhlYWRlcihtYWpvciwgbWlub3IsIGhkclNpemUsIG9mZlNpemUpOwogICAgcmV0dXJuIHsKICAgICAgb2JqOiBoZWFkZXIsCiAgICAgIGVuZFBvczogaGRyU2l6ZQogICAgfTsKICB9CiAgcGFyc2VEaWN0KGRpY3QpIHsKICAgIGxldCBwb3MgPSAwOwogICAgZnVuY3Rpb24gcGFyc2VPcGVyYW5kKCkgewogICAgICBsZXQgdmFsdWUgPSBkaWN0W3BvcysrXTsKICAgICAgaWYgKHZhbHVlID09PSAzMCkgewogICAgICAgIHJldHVybiBwYXJzZUZsb2F0T3BlcmFuZCgpOwogICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAyOCkgewogICAgICAgIHZhbHVlID0gcmVhZEludDE2KGRpY3QsIHBvcyk7CiAgICAgICAgcG9zICs9IDI7CiAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAyOSkgewogICAgICAgIHZhbHVlID0gZGljdFtwb3MrK107CiAgICAgICAgdmFsdWUgPSB2YWx1ZSA8PCA4IHwgZGljdFtwb3MrK107CiAgICAgICAgdmFsdWUgPSB2YWx1ZSA8PCA4IHwgZGljdFtwb3MrK107CiAgICAgICAgdmFsdWUgPSB2YWx1ZSA8PCA4IHwgZGljdFtwb3MrK107CiAgICAgICAgcmV0dXJuIHZhbHVlOwogICAgICB9IGVsc2UgaWYgKHZhbHVlID49IDMyICYmIHZhbHVlIDw9IDI0NikgewogICAgICAgIHJldHVybiB2YWx1ZSAtIDEzOTsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA+PSAyNDcgJiYgdmFsdWUgPD0gMjUwKSB7CiAgICAgICAgcmV0dXJuICh2YWx1ZSAtIDI0NykgKiAyNTYgKyBkaWN0W3BvcysrXSArIDEwODsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA+PSAyNTEgJiYgdmFsdWUgPD0gMjU0KSB7CiAgICAgICAgcmV0dXJuIC0oKHZhbHVlIC0gMjUxKSAqIDI1NikgLSBkaWN0W3BvcysrXSAtIDEwODsKICAgICAgfQogICAgICB3YXJuKCdDRkZQYXJzZXJfcGFyc2VEaWN0OiAiJyArIHZhbHVlICsgJyIgaXMgYSByZXNlcnZlZCBjb21tYW5kLicpOwogICAgICByZXR1cm4gTmFOOwogICAgfQogICAgZnVuY3Rpb24gcGFyc2VGbG9hdE9wZXJhbmQoKSB7CiAgICAgIGxldCBzdHIgPSAiIjsKICAgICAgY29uc3QgZW9mID0gMTU7CiAgICAgIGNvbnN0IGxvb2t1cCA9IFsiMCIsICIxIiwgIjIiLCAiMyIsICI0IiwgIjUiLCAiNiIsICI3IiwgIjgiLCAiOSIsICIuIiwgIkUiLCAiRS0iLCBudWxsLCAiLSJdOwogICAgICBjb25zdCBsZW5ndGggPSBkaWN0Lmxlbmd0aDsKICAgICAgd2hpbGUgKHBvcyA8IGxlbmd0aCkgewogICAgICAgIGNvbnN0IGIgPSBkaWN0W3BvcysrXTsKICAgICAgICBjb25zdCBiMSA9IGIgPj4gNDsKICAgICAgICBjb25zdCBiMiA9IGIgJiAxNTsKICAgICAgICBpZiAoYjEgPT09IGVvZikgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHN0ciArPSBsb29rdXBbYjFdOwogICAgICAgIGlmIChiMiA9PT0gZW9mKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgc3RyICs9IGxvb2t1cFtiMl07CiAgICAgIH0KICAgICAgcmV0dXJuIHBhcnNlRmxvYXQoc3RyKTsKICAgIH0KICAgIGxldCBvcGVyYW5kcyA9IFtdOwogICAgY29uc3QgZW50cmllcyA9IFtdOwogICAgcG9zID0gMDsKICAgIGNvbnN0IGVuZCA9IGRpY3QubGVuZ3RoOwogICAgd2hpbGUgKHBvcyA8IGVuZCkgewogICAgICBsZXQgYiA9IGRpY3RbcG9zXTsKICAgICAgaWYgKGIgPD0gMjEpIHsKICAgICAgICBpZiAoYiA9PT0gMTIpIHsKICAgICAgICAgIGIgPSBiIDw8IDggfCBkaWN0WysrcG9zXTsKICAgICAgICB9CiAgICAgICAgZW50cmllcy5wdXNoKFtiLCBvcGVyYW5kc10pOwogICAgICAgIG9wZXJhbmRzID0gW107CiAgICAgICAgKytwb3M7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgb3BlcmFuZHMucHVzaChwYXJzZU9wZXJhbmQoKSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBlbnRyaWVzOwogIH0KICBwYXJzZUluZGV4KHBvcykgewogICAgY29uc3QgY2ZmSW5kZXggPSBuZXcgQ0ZGSW5kZXgoKTsKICAgIGNvbnN0IGJ5dGVzID0gdGhpcy5ieXRlczsKICAgIGNvbnN0IGNvdW50ID0gYnl0ZXNbcG9zKytdIDw8IDggfCBieXRlc1twb3MrK107CiAgICBjb25zdCBvZmZzZXRzID0gW107CiAgICBsZXQgZW5kID0gcG9zOwogICAgbGV0IGksIGlpOwogICAgaWYgKGNvdW50ICE9PSAwKSB7CiAgICAgIGNvbnN0IG9mZnNldFNpemUgPSBieXRlc1twb3MrK107CiAgICAgIGNvbnN0IHN0YXJ0UG9zID0gcG9zICsgKGNvdW50ICsgMSkgKiBvZmZzZXRTaXplIC0gMTsKICAgICAgZm9yIChpID0gMCwgaWkgPSBjb3VudCArIDE7IGkgPCBpaTsgKytpKSB7CiAgICAgICAgbGV0IG9mZnNldCA9IDA7CiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBvZmZzZXRTaXplOyArK2opIHsKICAgICAgICAgIG9mZnNldCA8PD0gODsKICAgICAgICAgIG9mZnNldCArPSBieXRlc1twb3MrK107CiAgICAgICAgfQogICAgICAgIG9mZnNldHMucHVzaChzdGFydFBvcyArIG9mZnNldCk7CiAgICAgIH0KICAgICAgZW5kID0gb2Zmc2V0c1tjb3VudF07CiAgICB9CiAgICBmb3IgKGkgPSAwLCBpaSA9IG9mZnNldHMubGVuZ3RoIC0gMTsgaSA8IGlpOyArK2kpIHsKICAgICAgY29uc3Qgb2Zmc2V0U3RhcnQgPSBvZmZzZXRzW2ldOwogICAgICBjb25zdCBvZmZzZXRFbmQgPSBvZmZzZXRzW2kgKyAxXTsKICAgICAgY2ZmSW5kZXguYWRkKGJ5dGVzLnN1YmFycmF5KG9mZnNldFN0YXJ0LCBvZmZzZXRFbmQpKTsKICAgIH0KICAgIHJldHVybiB7CiAgICAgIG9iajogY2ZmSW5kZXgsCiAgICAgIGVuZFBvczogZW5kCiAgICB9OwogIH0KICBwYXJzZU5hbWVJbmRleChpbmRleCkgewogICAgY29uc3QgbmFtZXMgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGluZGV4LmNvdW50OyBpIDwgaWk7ICsraSkgewogICAgICBjb25zdCBuYW1lID0gaW5kZXguZ2V0KGkpOwogICAgICBuYW1lcy5wdXNoKGJ5dGVzVG9TdHJpbmcobmFtZSkpOwogICAgfQogICAgcmV0dXJuIG5hbWVzOwogIH0KICBwYXJzZVN0cmluZ0luZGV4KGluZGV4KSB7CiAgICBjb25zdCBzdHJpbmdzID0gbmV3IENGRlN0cmluZ3MoKTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGluZGV4LmNvdW50OyBpIDwgaWk7ICsraSkgewogICAgICBjb25zdCBkYXRhID0gaW5kZXguZ2V0KGkpOwogICAgICBzdHJpbmdzLmFkZChieXRlc1RvU3RyaW5nKGRhdGEpKTsKICAgIH0KICAgIHJldHVybiBzdHJpbmdzOwogIH0KICBjcmVhdGVEaWN0KFR5cGUsIGRpY3QsIHN0cmluZ3MpIHsKICAgIGNvbnN0IGNmZkRpY3QgPSBuZXcgVHlwZShzdHJpbmdzKTsKICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIGRpY3QpIHsKICAgICAgY2ZmRGljdC5zZXRCeUtleShrZXksIHZhbHVlKTsKICAgIH0KICAgIHJldHVybiBjZmZEaWN0OwogIH0KICBwYXJzZUNoYXJTdHJpbmcoc3RhdGUsIGRhdGEsIGxvY2FsU3VickluZGV4LCBnbG9iYWxTdWJySW5kZXgpIHsKICAgIGlmICghZGF0YSB8fCBzdGF0ZS5jYWxsRGVwdGggPiBNQVhfU1VCUl9ORVNUSU5HKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGxldCBzdGFja1NpemUgPSBzdGF0ZS5zdGFja1NpemU7CiAgICBjb25zdCBzdGFjayA9IHN0YXRlLnN0YWNrOwogICAgbGV0IGxlbmd0aCA9IGRhdGEubGVuZ3RoOwogICAgZm9yIChsZXQgaiA9IDA7IGogPCBsZW5ndGg7KSB7CiAgICAgIGNvbnN0IHZhbHVlID0gZGF0YVtqKytdOwogICAgICBsZXQgdmFsaWRhdGlvbkNvbW1hbmQgPSBudWxsOwogICAgICBpZiAodmFsdWUgPT09IDEyKSB7CiAgICAgICAgY29uc3QgcSA9IGRhdGFbaisrXTsKICAgICAgICBpZiAocSA9PT0gMCkgewogICAgICAgICAgZGF0YVtqIC0gMl0gPSAxMzk7CiAgICAgICAgICBkYXRhW2ogLSAxXSA9IDIyOwogICAgICAgICAgc3RhY2tTaXplID0gMDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdmFsaWRhdGlvbkNvbW1hbmQgPSBDaGFyc3RyaW5nVmFsaWRhdGlvbkRhdGExMltxXTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IDI4KSB7CiAgICAgICAgc3RhY2tbc3RhY2tTaXplXSA9IHJlYWRJbnQxNihkYXRhLCBqKTsKICAgICAgICBqICs9IDI7CiAgICAgICAgc3RhY2tTaXplKys7CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IDE0KSB7CiAgICAgICAgaWYgKHN0YWNrU2l6ZSA+PSA0KSB7CiAgICAgICAgICBzdGFja1NpemUgLT0gNDsKICAgICAgICAgIGlmICh0aGlzLnNlYWNBbmFseXNpc0VuYWJsZWQpIHsKICAgICAgICAgICAgc3RhdGUuc2VhYyA9IHN0YWNrLnNsaWNlKHN0YWNrU2l6ZSwgc3RhY2tTaXplICsgNCk7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgdmFsaWRhdGlvbkNvbW1hbmQgPSBDaGFyc3RyaW5nVmFsaWRhdGlvbkRhdGFbdmFsdWVdOwogICAgICB9IGVsc2UgaWYgKHZhbHVlID49IDMyICYmIHZhbHVlIDw9IDI0NikgewogICAgICAgIHN0YWNrW3N0YWNrU2l6ZV0gPSB2YWx1ZSAtIDEzOTsKICAgICAgICBzdGFja1NpemUrKzsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA+PSAyNDcgJiYgdmFsdWUgPD0gMjU0KSB7CiAgICAgICAgc3RhY2tbc3RhY2tTaXplXSA9IHZhbHVlIDwgMjUxID8gKHZhbHVlIC0gMjQ3IDw8IDgpICsgZGF0YVtqXSArIDEwOCA6IC0odmFsdWUgLSAyNTEgPDwgOCkgLSBkYXRhW2pdIC0gMTA4OwogICAgICAgIGorKzsKICAgICAgICBzdGFja1NpemUrKzsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gMjU1KSB7CiAgICAgICAgc3RhY2tbc3RhY2tTaXplXSA9IChkYXRhW2pdIDw8IDI0IHwgZGF0YVtqICsgMV0gPDwgMTYgfCBkYXRhW2ogKyAyXSA8PCA4IHwgZGF0YVtqICsgM10pIC8gNjU1MzY7CiAgICAgICAgaiArPSA0OwogICAgICAgIHN0YWNrU2l6ZSsrOwogICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSAxOSB8fCB2YWx1ZSA9PT0gMjApIHsKICAgICAgICBzdGF0ZS5oaW50cyArPSBzdGFja1NpemUgPj4gMTsKICAgICAgICBpZiAoc3RhdGUuaGludHMgPT09IDApIHsKICAgICAgICAgIGRhdGEuY29weVdpdGhpbihqIC0gMSwgaiwgLTEpOwogICAgICAgICAgaiAtPSAxOwogICAgICAgICAgbGVuZ3RoIC09IDE7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaiArPSBzdGF0ZS5oaW50cyArIDcgPj4gMzsKICAgICAgICBzdGFja1NpemUgJT0gMjsKICAgICAgICB2YWxpZGF0aW9uQ29tbWFuZCA9IENoYXJzdHJpbmdWYWxpZGF0aW9uRGF0YVt2YWx1ZV07CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IDEwIHx8IHZhbHVlID09PSAyOSkgewogICAgICAgIGNvbnN0IHN1YnJzSW5kZXggPSB2YWx1ZSA9PT0gMTAgPyBsb2NhbFN1YnJJbmRleCA6IGdsb2JhbFN1YnJJbmRleDsKICAgICAgICBpZiAoIXN1YnJzSW5kZXgpIHsKICAgICAgICAgIHZhbGlkYXRpb25Db21tYW5kID0gQ2hhcnN0cmluZ1ZhbGlkYXRpb25EYXRhW3ZhbHVlXTsKICAgICAgICAgIHdhcm4oIk1pc3Npbmcgc3VicnNJbmRleCBmb3IgIiArIHZhbGlkYXRpb25Db21tYW5kLmlkKTsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgbGV0IGJpYXMgPSAzMjc2ODsKICAgICAgICBpZiAoc3VicnNJbmRleC5jb3VudCA8IDEyNDApIHsKICAgICAgICAgIGJpYXMgPSAxMDc7CiAgICAgICAgfSBlbHNlIGlmIChzdWJyc0luZGV4LmNvdW50IDwgMzM5MDApIHsKICAgICAgICAgIGJpYXMgPSAxMTMxOwogICAgICAgIH0KICAgICAgICBjb25zdCBzdWJyTnVtYmVyID0gc3RhY2tbLS1zdGFja1NpemVdICsgYmlhczsKICAgICAgICBpZiAoc3Vick51bWJlciA8IDAgfHwgc3Vick51bWJlciA+PSBzdWJyc0luZGV4LmNvdW50IHx8IGlzTmFOKHN1YnJOdW1iZXIpKSB7CiAgICAgICAgICB2YWxpZGF0aW9uQ29tbWFuZCA9IENoYXJzdHJpbmdWYWxpZGF0aW9uRGF0YVt2YWx1ZV07CiAgICAgICAgICB3YXJuKCJPdXQgb2YgYm91bmRzIHN1YnJJbmRleCBmb3IgIiArIHZhbGlkYXRpb25Db21tYW5kLmlkKTsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgICAgc3RhdGUuc3RhY2tTaXplID0gc3RhY2tTaXplOwogICAgICAgIHN0YXRlLmNhbGxEZXB0aCsrOwogICAgICAgIGNvbnN0IHZhbGlkID0gdGhpcy5wYXJzZUNoYXJTdHJpbmcoc3RhdGUsIHN1YnJzSW5kZXguZ2V0KHN1YnJOdW1iZXIpLCBsb2NhbFN1YnJJbmRleCwgZ2xvYmFsU3VickluZGV4KTsKICAgICAgICBpZiAoIXZhbGlkKSB7CiAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgfQogICAgICAgIHN0YXRlLmNhbGxEZXB0aC0tOwogICAgICAgIHN0YWNrU2l6ZSA9IHN0YXRlLnN0YWNrU2l6ZTsKICAgICAgICBjb250aW51ZTsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gMTEpIHsKICAgICAgICBzdGF0ZS5zdGFja1NpemUgPSBzdGFja1NpemU7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IDAgJiYgaiA9PT0gZGF0YS5sZW5ndGgpIHsKICAgICAgICBkYXRhW2ogLSAxXSA9IDE0OwogICAgICAgIHZhbGlkYXRpb25Db21tYW5kID0gQ2hhcnN0cmluZ1ZhbGlkYXRpb25EYXRhWzE0XTsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gOSkgewogICAgICAgIGRhdGEuY29weVdpdGhpbihqIC0gMSwgaiwgLTEpOwogICAgICAgIGogLT0gMTsKICAgICAgICBsZW5ndGggLT0gMTsKICAgICAgICBjb250aW51ZTsKICAgICAgfSBlbHNlIHsKICAgICAgICB2YWxpZGF0aW9uQ29tbWFuZCA9IENoYXJzdHJpbmdWYWxpZGF0aW9uRGF0YVt2YWx1ZV07CiAgICAgIH0KICAgICAgaWYgKHZhbGlkYXRpb25Db21tYW5kKSB7CiAgICAgICAgaWYgKHZhbGlkYXRpb25Db21tYW5kLnN0ZW0pIHsKICAgICAgICAgIHN0YXRlLmhpbnRzICs9IHN0YWNrU2l6ZSA+PiAxOwogICAgICAgICAgaWYgKHZhbHVlID09PSAzIHx8IHZhbHVlID09PSAyMykgewogICAgICAgICAgICBzdGF0ZS5oYXNWU3RlbXMgPSB0cnVlOwogICAgICAgICAgfSBlbHNlIGlmIChzdGF0ZS5oYXNWU3RlbXMgJiYgKHZhbHVlID09PSAxIHx8IHZhbHVlID09PSAxOCkpIHsKICAgICAgICAgICAgd2FybigiQ0ZGIHN0ZW0gaGludHMgYXJlIGluIHdyb25nIG9yZGVyIik7CiAgICAgICAgICAgIGRhdGFbaiAtIDFdID0gdmFsdWUgPT09IDEgPyAzIDogMjM7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICgibWluIiBpbiB2YWxpZGF0aW9uQ29tbWFuZCkgewogICAgICAgICAgaWYgKCFzdGF0ZS51bmRlZlN0YWNrICYmIHN0YWNrU2l6ZSA8IHZhbGlkYXRpb25Db21tYW5kLm1pbikgewogICAgICAgICAgICB3YXJuKCJOb3QgZW5vdWdoIHBhcmFtZXRlcnMgZm9yICIgKyB2YWxpZGF0aW9uQ29tbWFuZC5pZCArICI7IGFjdHVhbDogIiArIHN0YWNrU2l6ZSArICIsIGV4cGVjdGVkOiAiICsgdmFsaWRhdGlvbkNvbW1hbmQubWluKTsKICAgICAgICAgICAgaWYgKHN0YWNrU2l6ZSA9PT0gMCkgewogICAgICAgICAgICAgIGRhdGFbaiAtIDFdID0gMTQ7CiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoc3RhdGUuZmlyc3RTdGFja0NsZWFyaW5nICYmIHZhbGlkYXRpb25Db21tYW5kLnN0YWNrQ2xlYXJpbmcpIHsKICAgICAgICAgIHN0YXRlLmZpcnN0U3RhY2tDbGVhcmluZyA9IGZhbHNlOwogICAgICAgICAgc3RhY2tTaXplIC09IHZhbGlkYXRpb25Db21tYW5kLm1pbjsKICAgICAgICAgIGlmIChzdGFja1NpemUgPj0gMiAmJiB2YWxpZGF0aW9uQ29tbWFuZC5zdGVtKSB7CiAgICAgICAgICAgIHN0YWNrU2l6ZSAlPSAyOwogICAgICAgICAgfSBlbHNlIGlmIChzdGFja1NpemUgPiAxKSB7CiAgICAgICAgICAgIHdhcm4oIkZvdW5kIHRvbyBtYW55IHBhcmFtZXRlcnMgZm9yIHN0YWNrLWNsZWFyaW5nIGNvbW1hbmQiKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChzdGFja1NpemUgPiAwKSB7CiAgICAgICAgICAgIHN0YXRlLndpZHRoID0gc3RhY2tbc3RhY2tTaXplIC0gMV07CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICgic3RhY2tEZWx0YSIgaW4gdmFsaWRhdGlvbkNvbW1hbmQpIHsKICAgICAgICAgIGlmICgic3RhY2tGbiIgaW4gdmFsaWRhdGlvbkNvbW1hbmQpIHsKICAgICAgICAgICAgdmFsaWRhdGlvbkNvbW1hbmQuc3RhY2tGbihzdGFjaywgc3RhY2tTaXplKTsKICAgICAgICAgIH0KICAgICAgICAgIHN0YWNrU2l6ZSArPSB2YWxpZGF0aW9uQ29tbWFuZC5zdGFja0RlbHRhOwogICAgICAgIH0gZWxzZSBpZiAodmFsaWRhdGlvbkNvbW1hbmQuc3RhY2tDbGVhcmluZykgewogICAgICAgICAgc3RhY2tTaXplID0gMDsKICAgICAgICB9IGVsc2UgaWYgKHZhbGlkYXRpb25Db21tYW5kLnJlc2V0U3RhY2spIHsKICAgICAgICAgIHN0YWNrU2l6ZSA9IDA7CiAgICAgICAgICBzdGF0ZS51bmRlZlN0YWNrID0gZmFsc2U7CiAgICAgICAgfSBlbHNlIGlmICh2YWxpZGF0aW9uQ29tbWFuZC51bmRlZlN0YWNrKSB7CiAgICAgICAgICBzdGFja1NpemUgPSAwOwogICAgICAgICAgc3RhdGUudW5kZWZTdGFjayA9IHRydWU7CiAgICAgICAgICBzdGF0ZS5maXJzdFN0YWNrQ2xlYXJpbmcgPSBmYWxzZTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChsZW5ndGggPCBkYXRhLmxlbmd0aCkgewogICAgICBkYXRhLmZpbGwoMTQsIGxlbmd0aCk7CiAgICB9CiAgICBzdGF0ZS5zdGFja1NpemUgPSBzdGFja1NpemU7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgcGFyc2VDaGFyU3RyaW5ncyh7CiAgICBjaGFyU3RyaW5ncywKICAgIGxvY2FsU3VickluZGV4LAogICAgZ2xvYmFsU3VickluZGV4LAogICAgZmRTZWxlY3QsCiAgICBmZEFycmF5LAogICAgcHJpdmF0ZURpY3QKICB9KSB7CiAgICBjb25zdCBzZWFjcyA9IFtdOwogICAgY29uc3Qgd2lkdGhzID0gW107CiAgICBjb25zdCBjb3VudCA9IGNoYXJTdHJpbmdzLmNvdW50OwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgIGNvbnN0IGNoYXJzdHJpbmcgPSBjaGFyU3RyaW5ncy5nZXQoaSk7CiAgICAgIGNvbnN0IHN0YXRlID0gewogICAgICAgIGNhbGxEZXB0aDogMCwKICAgICAgICBzdGFja1NpemU6IDAsCiAgICAgICAgc3RhY2s6IFtdLAogICAgICAgIHVuZGVmU3RhY2s6IHRydWUsCiAgICAgICAgaGludHM6IDAsCiAgICAgICAgZmlyc3RTdGFja0NsZWFyaW5nOiB0cnVlLAogICAgICAgIHNlYWM6IG51bGwsCiAgICAgICAgd2lkdGg6IG51bGwsCiAgICAgICAgaGFzVlN0ZW1zOiBmYWxzZQogICAgICB9OwogICAgICBsZXQgdmFsaWQgPSB0cnVlOwogICAgICBsZXQgbG9jYWxTdWJyVG9Vc2UgPSBudWxsOwogICAgICBsZXQgcHJpdmF0ZURpY3RUb1VzZSA9IHByaXZhdGVEaWN0OwogICAgICBpZiAoZmRTZWxlY3QgJiYgZmRBcnJheS5sZW5ndGgpIHsKICAgICAgICBjb25zdCBmZEluZGV4ID0gZmRTZWxlY3QuZ2V0RkRJbmRleChpKTsKICAgICAgICBpZiAoZmRJbmRleCA9PT0gLTEpIHsKICAgICAgICAgIHdhcm4oIkdseXBoIGluZGV4IGlzIG5vdCBpbiBmZCBzZWxlY3QuIik7CiAgICAgICAgICB2YWxpZCA9IGZhbHNlOwogICAgICAgIH0KICAgICAgICBpZiAoZmRJbmRleCA+PSBmZEFycmF5Lmxlbmd0aCkgewogICAgICAgICAgd2FybigiSW52YWxpZCBmZCBpbmRleCBmb3IgZ2x5cGggaW5kZXguIik7CiAgICAgICAgICB2YWxpZCA9IGZhbHNlOwogICAgICAgIH0KICAgICAgICBpZiAodmFsaWQpIHsKICAgICAgICAgIHByaXZhdGVEaWN0VG9Vc2UgPSBmZEFycmF5W2ZkSW5kZXhdLnByaXZhdGVEaWN0OwogICAgICAgICAgbG9jYWxTdWJyVG9Vc2UgPSBwcml2YXRlRGljdFRvVXNlLnN1YnJzSW5kZXg7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGxvY2FsU3VickluZGV4KSB7CiAgICAgICAgbG9jYWxTdWJyVG9Vc2UgPSBsb2NhbFN1YnJJbmRleDsKICAgICAgfQogICAgICBpZiAodmFsaWQpIHsKICAgICAgICB2YWxpZCA9IHRoaXMucGFyc2VDaGFyU3RyaW5nKHN0YXRlLCBjaGFyc3RyaW5nLCBsb2NhbFN1YnJUb1VzZSwgZ2xvYmFsU3VickluZGV4KTsKICAgICAgfQogICAgICBpZiAoc3RhdGUud2lkdGggIT09IG51bGwpIHsKICAgICAgICBjb25zdCBub21pbmFsV2lkdGggPSBwcml2YXRlRGljdFRvVXNlLmdldEJ5TmFtZSgibm9taW5hbFdpZHRoWCIpOwogICAgICAgIHdpZHRoc1tpXSA9IG5vbWluYWxXaWR0aCArIHN0YXRlLndpZHRoOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IGRlZmF1bHRXaWR0aCA9IHByaXZhdGVEaWN0VG9Vc2UuZ2V0QnlOYW1lKCJkZWZhdWx0V2lkdGhYIik7CiAgICAgICAgd2lkdGhzW2ldID0gZGVmYXVsdFdpZHRoOwogICAgICB9CiAgICAgIGlmIChzdGF0ZS5zZWFjICE9PSBudWxsKSB7CiAgICAgICAgc2VhY3NbaV0gPSBzdGF0ZS5zZWFjOwogICAgICB9CiAgICAgIGlmICghdmFsaWQpIHsKICAgICAgICBjaGFyU3RyaW5ncy5zZXQoaSwgbmV3IFVpbnQ4QXJyYXkoWzE0XSkpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gewogICAgICBjaGFyU3RyaW5ncywKICAgICAgc2VhY3MsCiAgICAgIHdpZHRocwogICAgfTsKICB9CiAgZW1wdHlQcml2YXRlRGljdGlvbmFyeShwYXJlbnREaWN0KSB7CiAgICBjb25zdCBwcml2YXRlRGljdCA9IHRoaXMuY3JlYXRlRGljdChDRkZQcml2YXRlRGljdCwgW10sIHBhcmVudERpY3Quc3RyaW5ncyk7CiAgICBwYXJlbnREaWN0LnNldEJ5S2V5KDE4LCBbMCwgMF0pOwogICAgcGFyZW50RGljdC5wcml2YXRlRGljdCA9IHByaXZhdGVEaWN0OwogIH0KICBwYXJzZVByaXZhdGVEaWN0KHBhcmVudERpY3QpIHsKICAgIGlmICghcGFyZW50RGljdC5oYXNOYW1lKCJQcml2YXRlIikpIHsKICAgICAgdGhpcy5lbXB0eVByaXZhdGVEaWN0aW9uYXJ5KHBhcmVudERpY3QpOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBwcml2YXRlT2Zmc2V0ID0gcGFyZW50RGljdC5nZXRCeU5hbWUoIlByaXZhdGUiKTsKICAgIGlmICghQXJyYXkuaXNBcnJheShwcml2YXRlT2Zmc2V0KSB8fCBwcml2YXRlT2Zmc2V0Lmxlbmd0aCAhPT0gMikgewogICAgICBwYXJlbnREaWN0LnJlbW92ZUJ5TmFtZSgiUHJpdmF0ZSIpOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBzaXplID0gcHJpdmF0ZU9mZnNldFswXTsKICAgIGNvbnN0IG9mZnNldCA9IHByaXZhdGVPZmZzZXRbMV07CiAgICBpZiAoc2l6ZSA9PT0gMCB8fCBvZmZzZXQgPj0gdGhpcy5ieXRlcy5sZW5ndGgpIHsKICAgICAgdGhpcy5lbXB0eVByaXZhdGVEaWN0aW9uYXJ5KHBhcmVudERpY3QpOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBwcml2YXRlRGljdEVuZCA9IG9mZnNldCArIHNpemU7CiAgICBjb25zdCBkaWN0RGF0YSA9IHRoaXMuYnl0ZXMuc3ViYXJyYXkob2Zmc2V0LCBwcml2YXRlRGljdEVuZCk7CiAgICBjb25zdCBkaWN0ID0gdGhpcy5wYXJzZURpY3QoZGljdERhdGEpOwogICAgY29uc3QgcHJpdmF0ZURpY3QgPSB0aGlzLmNyZWF0ZURpY3QoQ0ZGUHJpdmF0ZURpY3QsIGRpY3QsIHBhcmVudERpY3Quc3RyaW5ncyk7CiAgICBwYXJlbnREaWN0LnByaXZhdGVEaWN0ID0gcHJpdmF0ZURpY3Q7CiAgICBpZiAocHJpdmF0ZURpY3QuZ2V0QnlOYW1lKCJFeHBhbnNpb25GYWN0b3IiKSA9PT0gMCkgewogICAgICBwcml2YXRlRGljdC5zZXRCeU5hbWUoIkV4cGFuc2lvbkZhY3RvciIsIDAuMDYpOwogICAgfQogICAgaWYgKCFwcml2YXRlRGljdC5nZXRCeU5hbWUoIlN1YnJzIikpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3Qgc3VicnNPZmZzZXQgPSBwcml2YXRlRGljdC5nZXRCeU5hbWUoIlN1YnJzIik7CiAgICBjb25zdCByZWxhdGl2ZU9mZnNldCA9IG9mZnNldCArIHN1YnJzT2Zmc2V0OwogICAgaWYgKHN1YnJzT2Zmc2V0ID09PSAwIHx8IHJlbGF0aXZlT2Zmc2V0ID49IHRoaXMuYnl0ZXMubGVuZ3RoKSB7CiAgICAgIHRoaXMuZW1wdHlQcml2YXRlRGljdGlvbmFyeShwYXJlbnREaWN0KTsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3Qgc3VicnNJbmRleCA9IHRoaXMucGFyc2VJbmRleChyZWxhdGl2ZU9mZnNldCk7CiAgICBwcml2YXRlRGljdC5zdWJyc0luZGV4ID0gc3VicnNJbmRleC5vYmo7CiAgfQogIHBhcnNlQ2hhcnNldHMocG9zLCBsZW5ndGgsIHN0cmluZ3MsIGNpZCkgewogICAgaWYgKHBvcyA9PT0gMCkgewogICAgICByZXR1cm4gbmV3IENGRkNoYXJzZXQodHJ1ZSwgQ0ZGQ2hhcnNldFByZWRlZmluZWRUeXBlcy5JU09fQURPQkUsIElTT0Fkb2JlQ2hhcnNldCk7CiAgICB9IGVsc2UgaWYgKHBvcyA9PT0gMSkgewogICAgICByZXR1cm4gbmV3IENGRkNoYXJzZXQodHJ1ZSwgQ0ZGQ2hhcnNldFByZWRlZmluZWRUeXBlcy5FWFBFUlQsIEV4cGVydENoYXJzZXQpOwogICAgfSBlbHNlIGlmIChwb3MgPT09IDIpIHsKICAgICAgcmV0dXJuIG5ldyBDRkZDaGFyc2V0KHRydWUsIENGRkNoYXJzZXRQcmVkZWZpbmVkVHlwZXMuRVhQRVJUX1NVQlNFVCwgRXhwZXJ0U3Vic2V0Q2hhcnNldCk7CiAgICB9CiAgICBjb25zdCBieXRlcyA9IHRoaXMuYnl0ZXM7CiAgICBjb25zdCBzdGFydCA9IHBvczsKICAgIGNvbnN0IGZvcm1hdCA9IGJ5dGVzW3BvcysrXTsKICAgIGNvbnN0IGNoYXJzZXQgPSBbY2lkID8gMCA6ICIubm90ZGVmIl07CiAgICBsZXQgaWQsIGNvdW50LCBpOwogICAgbGVuZ3RoIC09IDE7CiAgICBzd2l0Y2ggKGZvcm1hdCkgewogICAgICBjYXNlIDA6CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBpZCA9IGJ5dGVzW3BvcysrXSA8PCA4IHwgYnl0ZXNbcG9zKytdOwogICAgICAgICAgY2hhcnNldC5wdXNoKGNpZCA/IGlkIDogc3RyaW5ncy5nZXQoaWQpKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMToKICAgICAgICB3aGlsZSAoY2hhcnNldC5sZW5ndGggPD0gbGVuZ3RoKSB7CiAgICAgICAgICBpZCA9IGJ5dGVzW3BvcysrXSA8PCA4IHwgYnl0ZXNbcG9zKytdOwogICAgICAgICAgY291bnQgPSBieXRlc1twb3MrK107CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDw9IGNvdW50OyBpKyspIHsKICAgICAgICAgICAgY2hhcnNldC5wdXNoKGNpZCA/IGlkKysgOiBzdHJpbmdzLmdldChpZCsrKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDI6CiAgICAgICAgd2hpbGUgKGNoYXJzZXQubGVuZ3RoIDw9IGxlbmd0aCkgewogICAgICAgICAgaWQgPSBieXRlc1twb3MrK10gPDwgOCB8IGJ5dGVzW3BvcysrXTsKICAgICAgICAgIGNvdW50ID0gYnl0ZXNbcG9zKytdIDw8IDggfCBieXRlc1twb3MrK107CiAgICAgICAgICBmb3IgKGkgPSAwOyBpIDw9IGNvdW50OyBpKyspIHsKICAgICAgICAgICAgY2hhcnNldC5wdXNoKGNpZCA/IGlkKysgOiBzdHJpbmdzLmdldChpZCsrKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiVW5rbm93biBjaGFyc2V0IGZvcm1hdCIpOwogICAgfQogICAgY29uc3QgZW5kID0gcG9zOwogICAgY29uc3QgcmF3ID0gYnl0ZXMuc3ViYXJyYXkoc3RhcnQsIGVuZCk7CiAgICByZXR1cm4gbmV3IENGRkNoYXJzZXQoZmFsc2UsIGZvcm1hdCwgY2hhcnNldCwgcmF3KTsKICB9CiAgcGFyc2VFbmNvZGluZyhwb3MsIHByb3BlcnRpZXMsIHN0cmluZ3MsIGNoYXJzZXQpIHsKICAgIGNvbnN0IGVuY29kaW5nID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGNvbnN0IGJ5dGVzID0gdGhpcy5ieXRlczsKICAgIGxldCBwcmVkZWZpbmVkID0gZmFsc2U7CiAgICBsZXQgZm9ybWF0LCBpLCBpaTsKICAgIGxldCByYXcgPSBudWxsOwogICAgZnVuY3Rpb24gcmVhZFN1cHBsZW1lbnQoKSB7CiAgICAgIGNvbnN0IHN1cHBsZW1lbnRzQ291bnQgPSBieXRlc1twb3MrK107CiAgICAgIGZvciAoaSA9IDA7IGkgPCBzdXBwbGVtZW50c0NvdW50OyBpKyspIHsKICAgICAgICBjb25zdCBjb2RlID0gYnl0ZXNbcG9zKytdOwogICAgICAgIGNvbnN0IHNpZCA9IChieXRlc1twb3MrK10gPDwgOCkgKyAoYnl0ZXNbcG9zKytdICYgMHhmZik7CiAgICAgICAgZW5jb2RpbmdbY29kZV0gPSBjaGFyc2V0LmluZGV4T2Yoc3RyaW5ncy5nZXQoc2lkKSk7CiAgICAgIH0KICAgIH0KICAgIGlmIChwb3MgPT09IDAgfHwgcG9zID09PSAxKSB7CiAgICAgIHByZWRlZmluZWQgPSB0cnVlOwogICAgICBmb3JtYXQgPSBwb3M7CiAgICAgIGNvbnN0IGJhc2VFbmNvZGluZyA9IHBvcyA/IEV4cGVydEVuY29kaW5nIDogU3RhbmRhcmRFbmNvZGluZzsKICAgICAgZm9yIChpID0gMCwgaWkgPSBjaGFyc2V0Lmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBjb25zdCBpbmRleCA9IGJhc2VFbmNvZGluZy5pbmRleE9mKGNoYXJzZXRbaV0pOwogICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHsKICAgICAgICAgIGVuY29kaW5nW2luZGV4XSA9IGk7CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBkYXRhU3RhcnQgPSBwb3M7CiAgICAgIGZvcm1hdCA9IGJ5dGVzW3BvcysrXTsKICAgICAgc3dpdGNoIChmb3JtYXQgJiAweDdmKSB7CiAgICAgICAgY2FzZSAwOgogICAgICAgICAgY29uc3QgZ2x5cGhzQ291bnQgPSBieXRlc1twb3MrK107CiAgICAgICAgICBmb3IgKGkgPSAxOyBpIDw9IGdseXBoc0NvdW50OyBpKyspIHsKICAgICAgICAgICAgZW5jb2RpbmdbYnl0ZXNbcG9zKytdXSA9IGk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDE6CiAgICAgICAgICBjb25zdCByYW5nZXNDb3VudCA9IGJ5dGVzW3BvcysrXTsKICAgICAgICAgIGxldCBnaWQgPSAxOwogICAgICAgICAgZm9yIChpID0gMDsgaSA8IHJhbmdlc0NvdW50OyBpKyspIHsKICAgICAgICAgICAgY29uc3Qgc3RhcnQgPSBieXRlc1twb3MrK107CiAgICAgICAgICAgIGNvbnN0IGxlZnQgPSBieXRlc1twb3MrK107CiAgICAgICAgICAgIGZvciAobGV0IGogPSBzdGFydDsgaiA8PSBzdGFydCArIGxlZnQ7IGorKykgewogICAgICAgICAgICAgIGVuY29kaW5nW2pdID0gZ2lkKys7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYFVua25vd24gZW5jb2RpbmcgZm9ybWF0OiAke2Zvcm1hdH0gaW4gQ0ZGYCk7CiAgICAgIH0KICAgICAgY29uc3QgZGF0YUVuZCA9IHBvczsKICAgICAgaWYgKGZvcm1hdCAmIDB4ODApIHsKICAgICAgICBieXRlc1tkYXRhU3RhcnRdICY9IDB4N2Y7CiAgICAgICAgcmVhZFN1cHBsZW1lbnQoKTsKICAgICAgfQogICAgICByYXcgPSBieXRlcy5zdWJhcnJheShkYXRhU3RhcnQsIGRhdGFFbmQpOwogICAgfQogICAgZm9ybWF0ICY9IDB4N2Y7CiAgICByZXR1cm4gbmV3IENGRkVuY29kaW5nKHByZWRlZmluZWQsIGZvcm1hdCwgZW5jb2RpbmcsIHJhdyk7CiAgfQogIHBhcnNlRkRTZWxlY3QocG9zLCBsZW5ndGgpIHsKICAgIGNvbnN0IGJ5dGVzID0gdGhpcy5ieXRlczsKICAgIGNvbnN0IGZvcm1hdCA9IGJ5dGVzW3BvcysrXTsKICAgIGNvbnN0IGZkU2VsZWN0ID0gW107CiAgICBsZXQgaTsKICAgIHN3aXRjaCAoZm9ybWF0KSB7CiAgICAgIGNhc2UgMDoKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgICAgICAgIGNvbnN0IGlkID0gYnl0ZXNbcG9zKytdOwogICAgICAgICAgZmRTZWxlY3QucHVzaChpZCk7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDM6CiAgICAgICAgY29uc3QgcmFuZ2VzQ291bnQgPSBieXRlc1twb3MrK10gPDwgOCB8IGJ5dGVzW3BvcysrXTsKICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcmFuZ2VzQ291bnQ7ICsraSkgewogICAgICAgICAgbGV0IGZpcnN0ID0gYnl0ZXNbcG9zKytdIDw8IDggfCBieXRlc1twb3MrK107CiAgICAgICAgICBpZiAoaSA9PT0gMCAmJiBmaXJzdCAhPT0gMCkgewogICAgICAgICAgICB3YXJuKCJwYXJzZUZEU2VsZWN0OiBUaGUgZmlyc3QgcmFuZ2UgbXVzdCBoYXZlIGEgZmlyc3QgR0lEIG9mIDAiICsgIiAtLSB0cnlpbmcgdG8gcmVjb3Zlci4iKTsKICAgICAgICAgICAgZmlyc3QgPSAwOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QgZmRJbmRleCA9IGJ5dGVzW3BvcysrXTsKICAgICAgICAgIGNvbnN0IG5leHQgPSBieXRlc1twb3NdIDw8IDggfCBieXRlc1twb3MgKyAxXTsKICAgICAgICAgIGZvciAobGV0IGogPSBmaXJzdDsgaiA8IG5leHQ7ICsraikgewogICAgICAgICAgICBmZFNlbGVjdC5wdXNoKGZkSW5kZXgpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBwb3MgKz0gMjsKICAgICAgICBicmVhazsKICAgICAgZGVmYXVsdDoKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYHBhcnNlRkRTZWxlY3Q6IFVua25vd24gZm9ybWF0ICIke2Zvcm1hdH0iLmApOwogICAgfQogICAgaWYgKGZkU2VsZWN0Lmxlbmd0aCAhPT0gbGVuZ3RoKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigicGFyc2VGRFNlbGVjdDogSW52YWxpZCBmb250IGRhdGEuIik7CiAgICB9CiAgICByZXR1cm4gbmV3IENGRkZEU2VsZWN0KGZvcm1hdCwgZmRTZWxlY3QpOwogIH0KfQpjbGFzcyBDRkYgewogIGNvbnN0cnVjdG9yKCkgewogICAgdGhpcy5oZWFkZXIgPSBudWxsOwogICAgdGhpcy5uYW1lcyA9IFtdOwogICAgdGhpcy50b3BEaWN0ID0gbnVsbDsKICAgIHRoaXMuc3RyaW5ncyA9IG5ldyBDRkZTdHJpbmdzKCk7CiAgICB0aGlzLmdsb2JhbFN1YnJJbmRleCA9IG51bGw7CiAgICB0aGlzLmVuY29kaW5nID0gbnVsbDsKICAgIHRoaXMuY2hhcnNldCA9IG51bGw7CiAgICB0aGlzLmNoYXJTdHJpbmdzID0gbnVsbDsKICAgIHRoaXMuZmRBcnJheSA9IFtdOwogICAgdGhpcy5mZFNlbGVjdCA9IG51bGw7CiAgICB0aGlzLmlzQ0lERm9udCA9IGZhbHNlOwogIH0KICBkdXBsaWNhdGVGaXJzdEdseXBoKCkgewogICAgaWYgKHRoaXMuY2hhclN0cmluZ3MuY291bnQgPj0gNjU1MzUpIHsKICAgICAgd2FybigiTm90IGVub3VnaCBzcGFjZSBpbiBjaGFyc3RyaW5ncyB0byBkdXBsaWNhdGUgZmlyc3QgZ2x5cGguIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGdseXBoWmVybyA9IHRoaXMuY2hhclN0cmluZ3MuZ2V0KDApOwogICAgdGhpcy5jaGFyU3RyaW5ncy5hZGQoZ2x5cGhaZXJvKTsKICAgIGlmICh0aGlzLmlzQ0lERm9udCkgewogICAgICB0aGlzLmZkU2VsZWN0LmZkU2VsZWN0LnB1c2godGhpcy5mZFNlbGVjdC5mZFNlbGVjdFswXSk7CiAgICB9CiAgfQogIGhhc0dseXBoSWQoaWQpIHsKICAgIGlmIChpZCA8IDAgfHwgaWQgPj0gdGhpcy5jaGFyU3RyaW5ncy5jb3VudCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBjb25zdCBnbHlwaCA9IHRoaXMuY2hhclN0cmluZ3MuZ2V0KGlkKTsKICAgIHJldHVybiBnbHlwaC5sZW5ndGggPiAwOwogIH0KfQpjbGFzcyBDRkZIZWFkZXIgewogIGNvbnN0cnVjdG9yKG1ham9yLCBtaW5vciwgaGRyU2l6ZSwgb2ZmU2l6ZSkgewogICAgdGhpcy5tYWpvciA9IG1ham9yOwogICAgdGhpcy5taW5vciA9IG1pbm9yOwogICAgdGhpcy5oZHJTaXplID0gaGRyU2l6ZTsKICAgIHRoaXMub2ZmU2l6ZSA9IG9mZlNpemU7CiAgfQp9CmNsYXNzIENGRlN0cmluZ3MgewogIGNvbnN0cnVjdG9yKCkgewogICAgdGhpcy5zdHJpbmdzID0gW107CiAgfQogIGdldChpbmRleCkgewogICAgaWYgKGluZGV4ID49IDAgJiYgaW5kZXggPD0gTlVNX1NUQU5EQVJEX0NGRl9TVFJJTkdTIC0gMSkgewogICAgICByZXR1cm4gQ0ZGU3RhbmRhcmRTdHJpbmdzW2luZGV4XTsKICAgIH0KICAgIGlmIChpbmRleCAtIE5VTV9TVEFOREFSRF9DRkZfU1RSSU5HUyA8PSB0aGlzLnN0cmluZ3MubGVuZ3RoKSB7CiAgICAgIHJldHVybiB0aGlzLnN0cmluZ3NbaW5kZXggLSBOVU1fU1RBTkRBUkRfQ0ZGX1NUUklOR1NdOwogICAgfQogICAgcmV0dXJuIENGRlN0YW5kYXJkU3RyaW5nc1swXTsKICB9CiAgZ2V0U0lEKHN0cikgewogICAgbGV0IGluZGV4ID0gQ0ZGU3RhbmRhcmRTdHJpbmdzLmluZGV4T2Yoc3RyKTsKICAgIGlmIChpbmRleCAhPT0gLTEpIHsKICAgICAgcmV0dXJuIGluZGV4OwogICAgfQogICAgaW5kZXggPSB0aGlzLnN0cmluZ3MuaW5kZXhPZihzdHIpOwogICAgaWYgKGluZGV4ICE9PSAtMSkgewogICAgICByZXR1cm4gaW5kZXggKyBOVU1fU1RBTkRBUkRfQ0ZGX1NUUklOR1M7CiAgICB9CiAgICByZXR1cm4gLTE7CiAgfQogIGFkZCh2YWx1ZSkgewogICAgdGhpcy5zdHJpbmdzLnB1c2godmFsdWUpOwogIH0KICBnZXQgY291bnQoKSB7CiAgICByZXR1cm4gdGhpcy5zdHJpbmdzLmxlbmd0aDsKICB9Cn0KY2xhc3MgQ0ZGSW5kZXggewogIGNvbnN0cnVjdG9yKCkgewogICAgdGhpcy5vYmplY3RzID0gW107CiAgICB0aGlzLmxlbmd0aCA9IDA7CiAgfQogIGFkZChkYXRhKSB7CiAgICB0aGlzLmxlbmd0aCArPSBkYXRhLmxlbmd0aDsKICAgIHRoaXMub2JqZWN0cy5wdXNoKGRhdGEpOwogIH0KICBzZXQoaW5kZXgsIGRhdGEpIHsKICAgIHRoaXMubGVuZ3RoICs9IGRhdGEubGVuZ3RoIC0gdGhpcy5vYmplY3RzW2luZGV4XS5sZW5ndGg7CiAgICB0aGlzLm9iamVjdHNbaW5kZXhdID0gZGF0YTsKICB9CiAgZ2V0KGluZGV4KSB7CiAgICByZXR1cm4gdGhpcy5vYmplY3RzW2luZGV4XTsKICB9CiAgZ2V0IGNvdW50KCkgewogICAgcmV0dXJuIHRoaXMub2JqZWN0cy5sZW5ndGg7CiAgfQp9CmNsYXNzIENGRkRpY3QgewogIGNvbnN0cnVjdG9yKHRhYmxlcywgc3RyaW5ncykgewogICAgdGhpcy5rZXlUb05hbWVNYXAgPSB0YWJsZXMua2V5VG9OYW1lTWFwOwogICAgdGhpcy5uYW1lVG9LZXlNYXAgPSB0YWJsZXMubmFtZVRvS2V5TWFwOwogICAgdGhpcy5kZWZhdWx0cyA9IHRhYmxlcy5kZWZhdWx0czsKICAgIHRoaXMudHlwZXMgPSB0YWJsZXMudHlwZXM7CiAgICB0aGlzLm9wY29kZXMgPSB0YWJsZXMub3Bjb2RlczsKICAgIHRoaXMub3JkZXIgPSB0YWJsZXMub3JkZXI7CiAgICB0aGlzLnN0cmluZ3MgPSBzdHJpbmdzOwogICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIH0KICBzZXRCeUtleShrZXksIHZhbHVlKSB7CiAgICBpZiAoIShrZXkgaW4gdGhpcy5rZXlUb05hbWVNYXApKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmICh2YWx1ZS5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBmb3IgKGNvbnN0IHZhbCBvZiB2YWx1ZSkgewogICAgICBpZiAoaXNOYU4odmFsKSkgewogICAgICAgIHdhcm4oYEludmFsaWQgQ0ZGRGljdCB2YWx1ZTogIiR7dmFsdWV9IiBmb3Iga2V5ICIke2tleX0iLmApOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICB9CiAgICBjb25zdCB0eXBlID0gdGhpcy50eXBlc1trZXldOwogICAgaWYgKHR5cGUgPT09ICJudW0iIHx8IHR5cGUgPT09ICJzaWQiIHx8IHR5cGUgPT09ICJvZmZzZXQiKSB7CiAgICAgIHZhbHVlID0gdmFsdWVbMF07CiAgICB9CiAgICB0aGlzLnZhbHVlc1trZXldID0gdmFsdWU7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgc2V0QnlOYW1lKG5hbWUsIHZhbHVlKSB7CiAgICBpZiAoIShuYW1lIGluIHRoaXMubmFtZVRvS2V5TWFwKSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgZGljdGlvbmFyeSBuYW1lICIke25hbWV9ImApOwogICAgfQogICAgdGhpcy52YWx1ZXNbdGhpcy5uYW1lVG9LZXlNYXBbbmFtZV1dID0gdmFsdWU7CiAgfQogIGhhc05hbWUobmFtZSkgewogICAgcmV0dXJuIHRoaXMubmFtZVRvS2V5TWFwW25hbWVdIGluIHRoaXMudmFsdWVzOwogIH0KICBnZXRCeU5hbWUobmFtZSkgewogICAgaWYgKCEobmFtZSBpbiB0aGlzLm5hbWVUb0tleU1hcCkpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIGRpY3Rpb25hcnkgbmFtZSAke25hbWV9ImApOwogICAgfQogICAgY29uc3Qga2V5ID0gdGhpcy5uYW1lVG9LZXlNYXBbbmFtZV07CiAgICBpZiAoIShrZXkgaW4gdGhpcy52YWx1ZXMpKSB7CiAgICAgIHJldHVybiB0aGlzLmRlZmF1bHRzW2tleV07CiAgICB9CiAgICByZXR1cm4gdGhpcy52YWx1ZXNba2V5XTsKICB9CiAgcmVtb3ZlQnlOYW1lKG5hbWUpIHsKICAgIGRlbGV0ZSB0aGlzLnZhbHVlc1t0aGlzLm5hbWVUb0tleU1hcFtuYW1lXV07CiAgfQogIHN0YXRpYyBjcmVhdGVUYWJsZXMobGF5b3V0KSB7CiAgICBjb25zdCB0YWJsZXMgPSB7CiAgICAgIGtleVRvTmFtZU1hcDoge30sCiAgICAgIG5hbWVUb0tleU1hcDoge30sCiAgICAgIGRlZmF1bHRzOiB7fSwKICAgICAgdHlwZXM6IHt9LAogICAgICBvcGNvZGVzOiB7fSwKICAgICAgb3JkZXI6IFtdCiAgICB9OwogICAgZm9yIChjb25zdCBlbnRyeSBvZiBsYXlvdXQpIHsKICAgICAgY29uc3Qga2V5ID0gQXJyYXkuaXNBcnJheShlbnRyeVswXSkgPyAoZW50cnlbMF1bMF0gPDwgOCkgKyBlbnRyeVswXVsxXSA6IGVudHJ5WzBdOwogICAgICB0YWJsZXMua2V5VG9OYW1lTWFwW2tleV0gPSBlbnRyeVsxXTsKICAgICAgdGFibGVzLm5hbWVUb0tleU1hcFtlbnRyeVsxXV0gPSBrZXk7CiAgICAgIHRhYmxlcy50eXBlc1trZXldID0gZW50cnlbMl07CiAgICAgIHRhYmxlcy5kZWZhdWx0c1trZXldID0gZW50cnlbM107CiAgICAgIHRhYmxlcy5vcGNvZGVzW2tleV0gPSBBcnJheS5pc0FycmF5KGVudHJ5WzBdKSA/IGVudHJ5WzBdIDogW2VudHJ5WzBdXTsKICAgICAgdGFibGVzLm9yZGVyLnB1c2goa2V5KTsKICAgIH0KICAgIHJldHVybiB0YWJsZXM7CiAgfQp9CmNvbnN0IENGRlRvcERpY3RMYXlvdXQgPSBbW1sxMiwgMzBdLCAiUk9TIiwgWyJzaWQiLCAic2lkIiwgIm51bSJdLCBudWxsXSwgW1sxMiwgMjBdLCAiU3ludGhldGljQmFzZSIsICJudW0iLCBudWxsXSwgWzAsICJ2ZXJzaW9uIiwgInNpZCIsIG51bGxdLCBbMSwgIk5vdGljZSIsICJzaWQiLCBudWxsXSwgW1sxMiwgMF0sICJDb3B5cmlnaHQiLCAic2lkIiwgbnVsbF0sIFsyLCAiRnVsbE5hbWUiLCAic2lkIiwgbnVsbF0sIFszLCAiRmFtaWx5TmFtZSIsICJzaWQiLCBudWxsXSwgWzQsICJXZWlnaHQiLCAic2lkIiwgbnVsbF0sIFtbMTIsIDFdLCAiaXNGaXhlZFBpdGNoIiwgIm51bSIsIDBdLCBbWzEyLCAyXSwgIkl0YWxpY0FuZ2xlIiwgIm51bSIsIDBdLCBbWzEyLCAzXSwgIlVuZGVybGluZVBvc2l0aW9uIiwgIm51bSIsIC0xMDBdLCBbWzEyLCA0XSwgIlVuZGVybGluZVRoaWNrbmVzcyIsICJudW0iLCA1MF0sIFtbMTIsIDVdLCAiUGFpbnRUeXBlIiwgIm51bSIsIDBdLCBbWzEyLCA2XSwgIkNoYXJzdHJpbmdUeXBlIiwgIm51bSIsIDJdLCBbWzEyLCA3XSwgIkZvbnRNYXRyaXgiLCBbIm51bSIsICJudW0iLCAibnVtIiwgIm51bSIsICJudW0iLCAibnVtIl0sIFswLjAwMSwgMCwgMCwgMC4wMDEsIDAsIDBdXSwgWzEzLCAiVW5pcXVlSUQiLCAibnVtIiwgbnVsbF0sIFs1LCAiRm9udEJCb3giLCBbIm51bSIsICJudW0iLCAibnVtIiwgIm51bSJdLCBbMCwgMCwgMCwgMF1dLCBbWzEyLCA4XSwgIlN0cm9rZVdpZHRoIiwgIm51bSIsIDBdLCBbMTQsICJYVUlEIiwgImFycmF5IiwgbnVsbF0sIFsxNSwgImNoYXJzZXQiLCAib2Zmc2V0IiwgMF0sIFsxNiwgIkVuY29kaW5nIiwgIm9mZnNldCIsIDBdLCBbMTcsICJDaGFyU3RyaW5ncyIsICJvZmZzZXQiLCAwXSwgWzE4LCAiUHJpdmF0ZSIsIFsib2Zmc2V0IiwgIm9mZnNldCJdLCBudWxsXSwgW1sxMiwgMjFdLCAiUG9zdFNjcmlwdCIsICJzaWQiLCBudWxsXSwgW1sxMiwgMjJdLCAiQmFzZUZvbnROYW1lIiwgInNpZCIsIG51bGxdLCBbWzEyLCAyM10sICJCYXNlRm9udEJsZW5kIiwgImRlbHRhIiwgbnVsbF0sIFtbMTIsIDMxXSwgIkNJREZvbnRWZXJzaW9uIiwgIm51bSIsIDBdLCBbWzEyLCAzMl0sICJDSURGb250UmV2aXNpb24iLCAibnVtIiwgMF0sIFtbMTIsIDMzXSwgIkNJREZvbnRUeXBlIiwgIm51bSIsIDBdLCBbWzEyLCAzNF0sICJDSURDb3VudCIsICJudW0iLCA4NzIwXSwgW1sxMiwgMzVdLCAiVUlEQmFzZSIsICJudW0iLCBudWxsXSwgW1sxMiwgMzddLCAiRkRTZWxlY3QiLCAib2Zmc2V0IiwgbnVsbF0sIFtbMTIsIDM2XSwgIkZEQXJyYXkiLCAib2Zmc2V0IiwgbnVsbF0sIFtbMTIsIDM4XSwgIkZvbnROYW1lIiwgInNpZCIsIG51bGxdXTsKY2xhc3MgQ0ZGVG9wRGljdCBleHRlbmRzIENGRkRpY3QgewogIHN0YXRpYyBnZXQgdGFibGVzKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAidGFibGVzIiwgdGhpcy5jcmVhdGVUYWJsZXMoQ0ZGVG9wRGljdExheW91dCkpOwogIH0KICBjb25zdHJ1Y3RvcihzdHJpbmdzKSB7CiAgICBzdXBlcihDRkZUb3BEaWN0LnRhYmxlcywgc3RyaW5ncyk7CiAgICB0aGlzLnByaXZhdGVEaWN0ID0gbnVsbDsKICB9Cn0KY29uc3QgQ0ZGUHJpdmF0ZURpY3RMYXlvdXQgPSBbWzYsICJCbHVlVmFsdWVzIiwgImRlbHRhIiwgbnVsbF0sIFs3LCAiT3RoZXJCbHVlcyIsICJkZWx0YSIsIG51bGxdLCBbOCwgIkZhbWlseUJsdWVzIiwgImRlbHRhIiwgbnVsbF0sIFs5LCAiRmFtaWx5T3RoZXJCbHVlcyIsICJkZWx0YSIsIG51bGxdLCBbWzEyLCA5XSwgIkJsdWVTY2FsZSIsICJudW0iLCAwLjAzOTYyNV0sIFtbMTIsIDEwXSwgIkJsdWVTaGlmdCIsICJudW0iLCA3XSwgW1sxMiwgMTFdLCAiQmx1ZUZ1enoiLCAibnVtIiwgMV0sIFsxMCwgIlN0ZEhXIiwgIm51bSIsIG51bGxdLCBbMTEsICJTdGRWVyIsICJudW0iLCBudWxsXSwgW1sxMiwgMTJdLCAiU3RlbVNuYXBIIiwgImRlbHRhIiwgbnVsbF0sIFtbMTIsIDEzXSwgIlN0ZW1TbmFwViIsICJkZWx0YSIsIG51bGxdLCBbWzEyLCAxNF0sICJGb3JjZUJvbGQiLCAibnVtIiwgMF0sIFtbMTIsIDE3XSwgIkxhbmd1YWdlR3JvdXAiLCAibnVtIiwgMF0sIFtbMTIsIDE4XSwgIkV4cGFuc2lvbkZhY3RvciIsICJudW0iLCAwLjA2XSwgW1sxMiwgMTldLCAiaW5pdGlhbFJhbmRvbVNlZWQiLCAibnVtIiwgMF0sIFsyMCwgImRlZmF1bHRXaWR0aFgiLCAibnVtIiwgMF0sIFsyMSwgIm5vbWluYWxXaWR0aFgiLCAibnVtIiwgMF0sIFsxOSwgIlN1YnJzIiwgIm9mZnNldCIsIG51bGxdXTsKY2xhc3MgQ0ZGUHJpdmF0ZURpY3QgZXh0ZW5kcyBDRkZEaWN0IHsKICBzdGF0aWMgZ2V0IHRhYmxlcygpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgInRhYmxlcyIsIHRoaXMuY3JlYXRlVGFibGVzKENGRlByaXZhdGVEaWN0TGF5b3V0KSk7CiAgfQogIGNvbnN0cnVjdG9yKHN0cmluZ3MpIHsKICAgIHN1cGVyKENGRlByaXZhdGVEaWN0LnRhYmxlcywgc3RyaW5ncyk7CiAgICB0aGlzLnN1YnJzSW5kZXggPSBudWxsOwogIH0KfQpjb25zdCBDRkZDaGFyc2V0UHJlZGVmaW5lZFR5cGVzID0gewogIElTT19BRE9CRTogMCwKICBFWFBFUlQ6IDEsCiAgRVhQRVJUX1NVQlNFVDogMgp9OwpjbGFzcyBDRkZDaGFyc2V0IHsKICBjb25zdHJ1Y3RvcihwcmVkZWZpbmVkLCBmb3JtYXQsIGNoYXJzZXQsIHJhdykgewogICAgdGhpcy5wcmVkZWZpbmVkID0gcHJlZGVmaW5lZDsKICAgIHRoaXMuZm9ybWF0ID0gZm9ybWF0OwogICAgdGhpcy5jaGFyc2V0ID0gY2hhcnNldDsKICAgIHRoaXMucmF3ID0gcmF3OwogIH0KfQpjbGFzcyBDRkZFbmNvZGluZyB7CiAgY29uc3RydWN0b3IocHJlZGVmaW5lZCwgZm9ybWF0LCBlbmNvZGluZywgcmF3KSB7CiAgICB0aGlzLnByZWRlZmluZWQgPSBwcmVkZWZpbmVkOwogICAgdGhpcy5mb3JtYXQgPSBmb3JtYXQ7CiAgICB0aGlzLmVuY29kaW5nID0gZW5jb2Rpbmc7CiAgICB0aGlzLnJhdyA9IHJhdzsKICB9Cn0KY2xhc3MgQ0ZGRkRTZWxlY3QgewogIGNvbnN0cnVjdG9yKGZvcm1hdCwgZmRTZWxlY3QpIHsKICAgIHRoaXMuZm9ybWF0ID0gZm9ybWF0OwogICAgdGhpcy5mZFNlbGVjdCA9IGZkU2VsZWN0OwogIH0KICBnZXRGREluZGV4KGdseXBoSW5kZXgpIHsKICAgIGlmIChnbHlwaEluZGV4IDwgMCB8fCBnbHlwaEluZGV4ID49IHRoaXMuZmRTZWxlY3QubGVuZ3RoKSB7CiAgICAgIHJldHVybiAtMTsKICAgIH0KICAgIHJldHVybiB0aGlzLmZkU2VsZWN0W2dseXBoSW5kZXhdOwogIH0KfQpjbGFzcyBDRkZPZmZzZXRUcmFja2VyIHsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMub2Zmc2V0cyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgfQogIGlzVHJhY2tpbmcoa2V5KSB7CiAgICByZXR1cm4ga2V5IGluIHRoaXMub2Zmc2V0czsKICB9CiAgdHJhY2soa2V5LCBsb2NhdGlvbikgewogICAgaWYgKGtleSBpbiB0aGlzLm9mZnNldHMpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBBbHJlYWR5IHRyYWNraW5nIGxvY2F0aW9uIG9mICR7a2V5fWApOwogICAgfQogICAgdGhpcy5vZmZzZXRzW2tleV0gPSBsb2NhdGlvbjsKICB9CiAgb2Zmc2V0KHZhbHVlKSB7CiAgICBmb3IgKGNvbnN0IGtleSBpbiB0aGlzLm9mZnNldHMpIHsKICAgICAgdGhpcy5vZmZzZXRzW2tleV0gKz0gdmFsdWU7CiAgICB9CiAgfQogIHNldEVudHJ5TG9jYXRpb24oa2V5LCB2YWx1ZXMsIG91dHB1dCkgewogICAgaWYgKCEoa2V5IGluIHRoaXMub2Zmc2V0cykpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBOb3QgdHJhY2tpbmcgbG9jYXRpb24gb2YgJHtrZXl9YCk7CiAgICB9CiAgICBjb25zdCBkYXRhID0gb3V0cHV0LmRhdGE7CiAgICBjb25zdCBkYXRhT2Zmc2V0ID0gdGhpcy5vZmZzZXRzW2tleV07CiAgICBjb25zdCBzaXplID0gNTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHZhbHVlcy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7CiAgICAgIGNvbnN0IG9mZnNldDAgPSBpICogc2l6ZSArIGRhdGFPZmZzZXQ7CiAgICAgIGNvbnN0IG9mZnNldDEgPSBvZmZzZXQwICsgMTsKICAgICAgY29uc3Qgb2Zmc2V0MiA9IG9mZnNldDAgKyAyOwogICAgICBjb25zdCBvZmZzZXQzID0gb2Zmc2V0MCArIDM7CiAgICAgIGNvbnN0IG9mZnNldDQgPSBvZmZzZXQwICsgNDsKICAgICAgaWYgKGRhdGFbb2Zmc2V0MF0gIT09IDB4MWQgfHwgZGF0YVtvZmZzZXQxXSAhPT0gMCB8fCBkYXRhW29mZnNldDJdICE9PSAwIHx8IGRhdGFbb2Zmc2V0M10gIT09IDAgfHwgZGF0YVtvZmZzZXQ0XSAhPT0gMCkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigid3JpdGluZyB0byBhbiBvZmZzZXQgdGhhdCBpcyBub3QgZW1wdHkiKTsKICAgICAgfQogICAgICBjb25zdCB2YWx1ZSA9IHZhbHVlc1tpXTsKICAgICAgZGF0YVtvZmZzZXQwXSA9IDB4MWQ7CiAgICAgIGRhdGFbb2Zmc2V0MV0gPSB2YWx1ZSA+PiAyNCAmIDB4ZmY7CiAgICAgIGRhdGFbb2Zmc2V0Ml0gPSB2YWx1ZSA+PiAxNiAmIDB4ZmY7CiAgICAgIGRhdGFbb2Zmc2V0M10gPSB2YWx1ZSA+PiA4ICYgMHhmZjsKICAgICAgZGF0YVtvZmZzZXQ0XSA9IHZhbHVlICYgMHhmZjsKICAgIH0KICB9Cn0KY2xhc3MgQ0ZGQ29tcGlsZXIgewogIGNvbnN0cnVjdG9yKGNmZikgewogICAgdGhpcy5jZmYgPSBjZmY7CiAgfQogIGNvbXBpbGUoKSB7CiAgICBjb25zdCBjZmYgPSB0aGlzLmNmZjsKICAgIGNvbnN0IG91dHB1dCA9IHsKICAgICAgZGF0YTogW10sCiAgICAgIGxlbmd0aDogMCwKICAgICAgYWRkKGRhdGEpIHsKICAgICAgICB0cnkgewogICAgICAgICAgdGhpcy5kYXRhLnB1c2goLi4uZGF0YSk7CiAgICAgICAgfSBjYXRjaCB7CiAgICAgICAgICB0aGlzLmRhdGEgPSB0aGlzLmRhdGEuY29uY2F0KGRhdGEpOwogICAgICAgIH0KICAgICAgICB0aGlzLmxlbmd0aCA9IHRoaXMuZGF0YS5sZW5ndGg7CiAgICAgIH0KICAgIH07CiAgICBjb25zdCBoZWFkZXIgPSB0aGlzLmNvbXBpbGVIZWFkZXIoY2ZmLmhlYWRlcik7CiAgICBvdXRwdXQuYWRkKGhlYWRlcik7CiAgICBjb25zdCBuYW1lSW5kZXggPSB0aGlzLmNvbXBpbGVOYW1lSW5kZXgoY2ZmLm5hbWVzKTsKICAgIG91dHB1dC5hZGQobmFtZUluZGV4KTsKICAgIGlmIChjZmYuaXNDSURGb250KSB7CiAgICAgIGlmIChjZmYudG9wRGljdC5oYXNOYW1lKCJGb250TWF0cml4IikpIHsKICAgICAgICBjb25zdCBiYXNlID0gY2ZmLnRvcERpY3QuZ2V0QnlOYW1lKCJGb250TWF0cml4Iik7CiAgICAgICAgY2ZmLnRvcERpY3QucmVtb3ZlQnlOYW1lKCJGb250TWF0cml4Iik7CiAgICAgICAgZm9yIChjb25zdCBzdWJEaWN0IG9mIGNmZi5mZEFycmF5KSB7CiAgICAgICAgICBsZXQgbWF0cml4ID0gYmFzZS5zbGljZSgwKTsKICAgICAgICAgIGlmIChzdWJEaWN0Lmhhc05hbWUoIkZvbnRNYXRyaXgiKSkgewogICAgICAgICAgICBtYXRyaXggPSBVdGlsLnRyYW5zZm9ybShtYXRyaXgsIHN1YkRpY3QuZ2V0QnlOYW1lKCJGb250TWF0cml4IikpOwogICAgICAgICAgfQogICAgICAgICAgc3ViRGljdC5zZXRCeU5hbWUoIkZvbnRNYXRyaXgiLCBtYXRyaXgpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgY29uc3QgeHVpZCA9IGNmZi50b3BEaWN0LmdldEJ5TmFtZSgiWFVJRCIpOwogICAgaWYgKHh1aWQ/Lmxlbmd0aCA+IDE2KSB7CiAgICAgIGNmZi50b3BEaWN0LnJlbW92ZUJ5TmFtZSgiWFVJRCIpOwogICAgfQogICAgY2ZmLnRvcERpY3Quc2V0QnlOYW1lKCJjaGFyc2V0IiwgMCk7CiAgICBsZXQgY29tcGlsZWQgPSB0aGlzLmNvbXBpbGVUb3BEaWN0cyhbY2ZmLnRvcERpY3RdLCBvdXRwdXQubGVuZ3RoLCBjZmYuaXNDSURGb250KTsKICAgIG91dHB1dC5hZGQoY29tcGlsZWQub3V0cHV0KTsKICAgIGNvbnN0IHRvcERpY3RUcmFja2VyID0gY29tcGlsZWQudHJhY2tlcnNbMF07CiAgICBjb25zdCBzdHJpbmdJbmRleCA9IHRoaXMuY29tcGlsZVN0cmluZ0luZGV4KGNmZi5zdHJpbmdzLnN0cmluZ3MpOwogICAgb3V0cHV0LmFkZChzdHJpbmdJbmRleCk7CiAgICBjb25zdCBnbG9iYWxTdWJySW5kZXggPSB0aGlzLmNvbXBpbGVJbmRleChjZmYuZ2xvYmFsU3VickluZGV4KTsKICAgIG91dHB1dC5hZGQoZ2xvYmFsU3VickluZGV4KTsKICAgIGlmIChjZmYuZW5jb2RpbmcgJiYgY2ZmLnRvcERpY3QuaGFzTmFtZSgiRW5jb2RpbmciKSkgewogICAgICBpZiAoY2ZmLmVuY29kaW5nLnByZWRlZmluZWQpIHsKICAgICAgICB0b3BEaWN0VHJhY2tlci5zZXRFbnRyeUxvY2F0aW9uKCJFbmNvZGluZyIsIFtjZmYuZW5jb2RpbmcuZm9ybWF0XSwgb3V0cHV0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBlbmNvZGluZyA9IHRoaXMuY29tcGlsZUVuY29kaW5nKGNmZi5lbmNvZGluZyk7CiAgICAgICAgdG9wRGljdFRyYWNrZXIuc2V0RW50cnlMb2NhdGlvbigiRW5jb2RpbmciLCBbb3V0cHV0Lmxlbmd0aF0sIG91dHB1dCk7CiAgICAgICAgb3V0cHV0LmFkZChlbmNvZGluZyk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGNoYXJzZXQgPSB0aGlzLmNvbXBpbGVDaGFyc2V0KGNmZi5jaGFyc2V0LCBjZmYuY2hhclN0cmluZ3MuY291bnQsIGNmZi5zdHJpbmdzLCBjZmYuaXNDSURGb250KTsKICAgIHRvcERpY3RUcmFja2VyLnNldEVudHJ5TG9jYXRpb24oImNoYXJzZXQiLCBbb3V0cHV0Lmxlbmd0aF0sIG91dHB1dCk7CiAgICBvdXRwdXQuYWRkKGNoYXJzZXQpOwogICAgY29uc3QgY2hhclN0cmluZ3MgPSB0aGlzLmNvbXBpbGVDaGFyU3RyaW5ncyhjZmYuY2hhclN0cmluZ3MpOwogICAgdG9wRGljdFRyYWNrZXIuc2V0RW50cnlMb2NhdGlvbigiQ2hhclN0cmluZ3MiLCBbb3V0cHV0Lmxlbmd0aF0sIG91dHB1dCk7CiAgICBvdXRwdXQuYWRkKGNoYXJTdHJpbmdzKTsKICAgIGlmIChjZmYuaXNDSURGb250KSB7CiAgICAgIHRvcERpY3RUcmFja2VyLnNldEVudHJ5TG9jYXRpb24oIkZEU2VsZWN0IiwgW291dHB1dC5sZW5ndGhdLCBvdXRwdXQpOwogICAgICBjb25zdCBmZFNlbGVjdCA9IHRoaXMuY29tcGlsZUZEU2VsZWN0KGNmZi5mZFNlbGVjdCk7CiAgICAgIG91dHB1dC5hZGQoZmRTZWxlY3QpOwogICAgICBjb21waWxlZCA9IHRoaXMuY29tcGlsZVRvcERpY3RzKGNmZi5mZEFycmF5LCBvdXRwdXQubGVuZ3RoLCB0cnVlKTsKICAgICAgdG9wRGljdFRyYWNrZXIuc2V0RW50cnlMb2NhdGlvbigiRkRBcnJheSIsIFtvdXRwdXQubGVuZ3RoXSwgb3V0cHV0KTsKICAgICAgb3V0cHV0LmFkZChjb21waWxlZC5vdXRwdXQpOwogICAgICBjb25zdCBmb250RGljdFRyYWNrZXJzID0gY29tcGlsZWQudHJhY2tlcnM7CiAgICAgIHRoaXMuY29tcGlsZVByaXZhdGVEaWN0cyhjZmYuZmRBcnJheSwgZm9udERpY3RUcmFja2Vycywgb3V0cHV0KTsKICAgIH0KICAgIHRoaXMuY29tcGlsZVByaXZhdGVEaWN0cyhbY2ZmLnRvcERpY3RdLCBbdG9wRGljdFRyYWNrZXJdLCBvdXRwdXQpOwogICAgb3V0cHV0LmFkZChbMF0pOwogICAgcmV0dXJuIG91dHB1dC5kYXRhOwogIH0KICBlbmNvZGVOdW1iZXIodmFsdWUpIHsKICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKSkgewogICAgICByZXR1cm4gdGhpcy5lbmNvZGVJbnRlZ2VyKHZhbHVlKTsKICAgIH0KICAgIHJldHVybiB0aGlzLmVuY29kZUZsb2F0KHZhbHVlKTsKICB9CiAgc3RhdGljIGdldCBFbmNvZGVGbG9hdFJlZ0V4cCgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgIkVuY29kZUZsb2F0UmVnRXhwIiwgL1wuKFxkKj8pKD86OXs1LDIwfXwwezUsMjB9KVxkezAsMn0oPzplKC4rKXwkKS8pOwogIH0KICBlbmNvZGVGbG9hdChudW0pIHsKICAgIGxldCB2YWx1ZSA9IG51bS50b1N0cmluZygpOwogICAgY29uc3QgbSA9IENGRkNvbXBpbGVyLkVuY29kZUZsb2F0UmVnRXhwLmV4ZWModmFsdWUpOwogICAgaWYgKG0pIHsKICAgICAgY29uc3QgZXBzaWxvbiA9IHBhcnNlRmxvYXQoIjFlIiArICgobVsyXSA/ICttWzJdIDogMCkgKyBtWzFdLmxlbmd0aCkpOwogICAgICB2YWx1ZSA9IChNYXRoLnJvdW5kKG51bSAqIGVwc2lsb24pIC8gZXBzaWxvbikudG9TdHJpbmcoKTsKICAgIH0KICAgIGxldCBuaWJibGVzID0gIiI7CiAgICBsZXQgaSwgaWk7CiAgICBmb3IgKGkgPSAwLCBpaSA9IHZhbHVlLmxlbmd0aDsgaSA8IGlpOyArK2kpIHsKICAgICAgY29uc3QgYSA9IHZhbHVlW2ldOwogICAgICBpZiAoYSA9PT0gImUiKSB7CiAgICAgICAgbmliYmxlcyArPSB2YWx1ZVsrK2ldID09PSAiLSIgPyAiYyIgOiAiYiI7CiAgICAgIH0gZWxzZSBpZiAoYSA9PT0gIi4iKSB7CiAgICAgICAgbmliYmxlcyArPSAiYSI7CiAgICAgIH0gZWxzZSBpZiAoYSA9PT0gIi0iKSB7CiAgICAgICAgbmliYmxlcyArPSAiZSI7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbmliYmxlcyArPSBhOwogICAgICB9CiAgICB9CiAgICBuaWJibGVzICs9IG5pYmJsZXMubGVuZ3RoICYgMSA/ICJmIiA6ICJmZiI7CiAgICBjb25zdCBvdXQgPSBbMzBdOwogICAgZm9yIChpID0gMCwgaWkgPSBuaWJibGVzLmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgb3V0LnB1c2gocGFyc2VJbnQobmliYmxlcy5zdWJzdHJpbmcoaSwgaSArIDIpLCAxNikpOwogICAgfQogICAgcmV0dXJuIG91dDsKICB9CiAgZW5jb2RlSW50ZWdlcih2YWx1ZSkgewogICAgbGV0IGNvZGU7CiAgICBpZiAodmFsdWUgPj0gLTEwNyAmJiB2YWx1ZSA8PSAxMDcpIHsKICAgICAgY29kZSA9IFt2YWx1ZSArIDEzOV07CiAgICB9IGVsc2UgaWYgKHZhbHVlID49IDEwOCAmJiB2YWx1ZSA8PSAxMTMxKSB7CiAgICAgIHZhbHVlIC09IDEwODsKICAgICAgY29kZSA9IFsodmFsdWUgPj4gOCkgKyAyNDcsIHZhbHVlICYgMHhmZl07CiAgICB9IGVsc2UgaWYgKHZhbHVlID49IC0xMTMxICYmIHZhbHVlIDw9IC0xMDgpIHsKICAgICAgdmFsdWUgPSAtdmFsdWUgLSAxMDg7CiAgICAgIGNvZGUgPSBbKHZhbHVlID4+IDgpICsgMjUxLCB2YWx1ZSAmIDB4ZmZdOwogICAgfSBlbHNlIGlmICh2YWx1ZSA+PSAtMzI3NjggJiYgdmFsdWUgPD0gMzI3NjcpIHsKICAgICAgY29kZSA9IFsweDFjLCB2YWx1ZSA+PiA4ICYgMHhmZiwgdmFsdWUgJiAweGZmXTsKICAgIH0gZWxzZSB7CiAgICAgIGNvZGUgPSBbMHgxZCwgdmFsdWUgPj4gMjQgJiAweGZmLCB2YWx1ZSA+PiAxNiAmIDB4ZmYsIHZhbHVlID4+IDggJiAweGZmLCB2YWx1ZSAmIDB4ZmZdOwogICAgfQogICAgcmV0dXJuIGNvZGU7CiAgfQogIGNvbXBpbGVIZWFkZXIoaGVhZGVyKSB7CiAgICByZXR1cm4gW2hlYWRlci5tYWpvciwgaGVhZGVyLm1pbm9yLCA0LCBoZWFkZXIub2ZmU2l6ZV07CiAgfQogIGNvbXBpbGVOYW1lSW5kZXgobmFtZXMpIHsKICAgIGNvbnN0IG5hbWVJbmRleCA9IG5ldyBDRkZJbmRleCgpOwogICAgZm9yIChjb25zdCBuYW1lIG9mIG5hbWVzKSB7CiAgICAgIGNvbnN0IGxlbmd0aCA9IE1hdGgubWluKG5hbWUubGVuZ3RoLCAxMjcpOwogICAgICBsZXQgc2FuaXRpemVkTmFtZSA9IG5ldyBBcnJheShsZW5ndGgpOwogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxlbmd0aDsgaisrKSB7CiAgICAgICAgbGV0IGNoYXIgPSBuYW1lW2pdOwogICAgICAgIGlmIChjaGFyIDwgIiEiIHx8IGNoYXIgPiAifiIgfHwgY2hhciA9PT0gIlsiIHx8IGNoYXIgPT09ICJdIiB8fCBjaGFyID09PSAiKCIgfHwgY2hhciA9PT0gIikiIHx8IGNoYXIgPT09ICJ7IiB8fCBjaGFyID09PSAifSIgfHwgY2hhciA9PT0gIjwiIHx8IGNoYXIgPT09ICI+IiB8fCBjaGFyID09PSAiLyIgfHwgY2hhciA9PT0gIiUiKSB7CiAgICAgICAgICBjaGFyID0gIl8iOwogICAgICAgIH0KICAgICAgICBzYW5pdGl6ZWROYW1lW2pdID0gY2hhcjsKICAgICAgfQogICAgICBzYW5pdGl6ZWROYW1lID0gc2FuaXRpemVkTmFtZS5qb2luKCIiKTsKICAgICAgaWYgKHNhbml0aXplZE5hbWUgPT09ICIiKSB7CiAgICAgICAgc2FuaXRpemVkTmFtZSA9ICJCYWRfRm9udF9OYW1lIjsKICAgICAgfQogICAgICBuYW1lSW5kZXguYWRkKHN0cmluZ1RvQnl0ZXMoc2FuaXRpemVkTmFtZSkpOwogICAgfQogICAgcmV0dXJuIHRoaXMuY29tcGlsZUluZGV4KG5hbWVJbmRleCk7CiAgfQogIGNvbXBpbGVUb3BEaWN0cyhkaWN0cywgbGVuZ3RoLCByZW1vdmVDaWRLZXlzKSB7CiAgICBjb25zdCBmb250RGljdFRyYWNrZXJzID0gW107CiAgICBsZXQgZmRBcnJheUluZGV4ID0gbmV3IENGRkluZGV4KCk7CiAgICBmb3IgKGNvbnN0IGZvbnREaWN0IG9mIGRpY3RzKSB7CiAgICAgIGlmIChyZW1vdmVDaWRLZXlzKSB7CiAgICAgICAgZm9udERpY3QucmVtb3ZlQnlOYW1lKCJDSURGb250VmVyc2lvbiIpOwogICAgICAgIGZvbnREaWN0LnJlbW92ZUJ5TmFtZSgiQ0lERm9udFJldmlzaW9uIik7CiAgICAgICAgZm9udERpY3QucmVtb3ZlQnlOYW1lKCJDSURGb250VHlwZSIpOwogICAgICAgIGZvbnREaWN0LnJlbW92ZUJ5TmFtZSgiQ0lEQ291bnQiKTsKICAgICAgICBmb250RGljdC5yZW1vdmVCeU5hbWUoIlVJREJhc2UiKTsKICAgICAgfQogICAgICBjb25zdCBmb250RGljdFRyYWNrZXIgPSBuZXcgQ0ZGT2Zmc2V0VHJhY2tlcigpOwogICAgICBjb25zdCBmb250RGljdERhdGEgPSB0aGlzLmNvbXBpbGVEaWN0KGZvbnREaWN0LCBmb250RGljdFRyYWNrZXIpOwogICAgICBmb250RGljdFRyYWNrZXJzLnB1c2goZm9udERpY3RUcmFja2VyKTsKICAgICAgZmRBcnJheUluZGV4LmFkZChmb250RGljdERhdGEpOwogICAgICBmb250RGljdFRyYWNrZXIub2Zmc2V0KGxlbmd0aCk7CiAgICB9CiAgICBmZEFycmF5SW5kZXggPSB0aGlzLmNvbXBpbGVJbmRleChmZEFycmF5SW5kZXgsIGZvbnREaWN0VHJhY2tlcnMpOwogICAgcmV0dXJuIHsKICAgICAgdHJhY2tlcnM6IGZvbnREaWN0VHJhY2tlcnMsCiAgICAgIG91dHB1dDogZmRBcnJheUluZGV4CiAgICB9OwogIH0KICBjb21waWxlUHJpdmF0ZURpY3RzKGRpY3RzLCB0cmFja2Vycywgb3V0cHV0KSB7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBkaWN0cy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7CiAgICAgIGNvbnN0IGZvbnREaWN0ID0gZGljdHNbaV07CiAgICAgIGNvbnN0IHByaXZhdGVEaWN0ID0gZm9udERpY3QucHJpdmF0ZURpY3Q7CiAgICAgIGlmICghcHJpdmF0ZURpY3QgfHwgIWZvbnREaWN0Lmhhc05hbWUoIlByaXZhdGUiKSkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiVGhlcmUgbXVzdCBiZSBhIHByaXZhdGUgZGljdGlvbmFyeS4iKTsKICAgICAgfQogICAgICBjb25zdCBwcml2YXRlRGljdFRyYWNrZXIgPSBuZXcgQ0ZGT2Zmc2V0VHJhY2tlcigpOwogICAgICBjb25zdCBwcml2YXRlRGljdERhdGEgPSB0aGlzLmNvbXBpbGVEaWN0KHByaXZhdGVEaWN0LCBwcml2YXRlRGljdFRyYWNrZXIpOwogICAgICBsZXQgb3V0cHV0TGVuZ3RoID0gb3V0cHV0Lmxlbmd0aDsKICAgICAgcHJpdmF0ZURpY3RUcmFja2VyLm9mZnNldChvdXRwdXRMZW5ndGgpOwogICAgICBpZiAoIXByaXZhdGVEaWN0RGF0YS5sZW5ndGgpIHsKICAgICAgICBvdXRwdXRMZW5ndGggPSAwOwogICAgICB9CiAgICAgIHRyYWNrZXJzW2ldLnNldEVudHJ5TG9jYXRpb24oIlByaXZhdGUiLCBbcHJpdmF0ZURpY3REYXRhLmxlbmd0aCwgb3V0cHV0TGVuZ3RoXSwgb3V0cHV0KTsKICAgICAgb3V0cHV0LmFkZChwcml2YXRlRGljdERhdGEpOwogICAgICBpZiAocHJpdmF0ZURpY3Quc3VicnNJbmRleCAmJiBwcml2YXRlRGljdC5oYXNOYW1lKCJTdWJycyIpKSB7CiAgICAgICAgY29uc3Qgc3VicnMgPSB0aGlzLmNvbXBpbGVJbmRleChwcml2YXRlRGljdC5zdWJyc0luZGV4KTsKICAgICAgICBwcml2YXRlRGljdFRyYWNrZXIuc2V0RW50cnlMb2NhdGlvbigiU3VicnMiLCBbcHJpdmF0ZURpY3REYXRhLmxlbmd0aF0sIG91dHB1dCk7CiAgICAgICAgb3V0cHV0LmFkZChzdWJycyk7CiAgICAgIH0KICAgIH0KICB9CiAgY29tcGlsZURpY3QoZGljdCwgb2Zmc2V0VHJhY2tlcikgewogICAgY29uc3Qgb3V0ID0gW107CiAgICBmb3IgKGNvbnN0IGtleSBvZiBkaWN0Lm9yZGVyKSB7CiAgICAgIGlmICghKGtleSBpbiBkaWN0LnZhbHVlcykpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBsZXQgdmFsdWVzID0gZGljdC52YWx1ZXNba2V5XTsKICAgICAgbGV0IHR5cGVzID0gZGljdC50eXBlc1trZXldOwogICAgICBpZiAoIUFycmF5LmlzQXJyYXkodHlwZXMpKSB7CiAgICAgICAgdHlwZXMgPSBbdHlwZXNdOwogICAgICB9CiAgICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWx1ZXMpKSB7CiAgICAgICAgdmFsdWVzID0gW3ZhbHVlc107CiAgICAgIH0KICAgICAgaWYgKHZhbHVlcy5sZW5ndGggPT09IDApIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBmb3IgKGxldCBqID0gMCwgamogPSB0eXBlcy5sZW5ndGg7IGogPCBqajsgKytqKSB7CiAgICAgICAgY29uc3QgdHlwZSA9IHR5cGVzW2pdOwogICAgICAgIGNvbnN0IHZhbHVlID0gdmFsdWVzW2pdOwogICAgICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgICAgY2FzZSAibnVtIjoKICAgICAgICAgIGNhc2UgInNpZCI6CiAgICAgICAgICAgIG91dC5wdXNoKC4uLnRoaXMuZW5jb2RlTnVtYmVyKHZhbHVlKSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAib2Zmc2V0IjoKICAgICAgICAgICAgY29uc3QgbmFtZSA9IGRpY3Qua2V5VG9OYW1lTWFwW2tleV07CiAgICAgICAgICAgIGlmICghb2Zmc2V0VHJhY2tlci5pc1RyYWNraW5nKG5hbWUpKSB7CiAgICAgICAgICAgICAgb2Zmc2V0VHJhY2tlci50cmFjayhuYW1lLCBvdXQubGVuZ3RoKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBvdXQucHVzaCgweDFkLCAwLCAwLCAwLCAwKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICJhcnJheSI6CiAgICAgICAgICBjYXNlICJkZWx0YSI6CiAgICAgICAgICAgIG91dC5wdXNoKC4uLnRoaXMuZW5jb2RlTnVtYmVyKHZhbHVlKSk7CiAgICAgICAgICAgIGZvciAobGV0IGsgPSAxLCBrayA9IHZhbHVlcy5sZW5ndGg7IGsgPCBrazsgKytrKSB7CiAgICAgICAgICAgICAgb3V0LnB1c2goLi4udGhpcy5lbmNvZGVOdW1iZXIodmFsdWVzW2tdKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYFVua25vd24gZGF0YSB0eXBlIG9mICR7dHlwZX1gKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgb3V0LnB1c2goLi4uZGljdC5vcGNvZGVzW2tleV0pOwogICAgfQogICAgcmV0dXJuIG91dDsKICB9CiAgY29tcGlsZVN0cmluZ0luZGV4KHN0cmluZ3MpIHsKICAgIGNvbnN0IHN0cmluZ0luZGV4ID0gbmV3IENGRkluZGV4KCk7CiAgICBmb3IgKGNvbnN0IHN0cmluZyBvZiBzdHJpbmdzKSB7CiAgICAgIHN0cmluZ0luZGV4LmFkZChzdHJpbmdUb0J5dGVzKHN0cmluZykpOwogICAgfQogICAgcmV0dXJuIHRoaXMuY29tcGlsZUluZGV4KHN0cmluZ0luZGV4KTsKICB9CiAgY29tcGlsZUNoYXJTdHJpbmdzKGNoYXJTdHJpbmdzKSB7CiAgICBjb25zdCBjaGFyU3RyaW5nc0luZGV4ID0gbmV3IENGRkluZGV4KCk7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNoYXJTdHJpbmdzLmNvdW50OyBpKyspIHsKICAgICAgY29uc3QgZ2x5cGggPSBjaGFyU3RyaW5ncy5nZXQoaSk7CiAgICAgIGlmIChnbHlwaC5sZW5ndGggPT09IDApIHsKICAgICAgICBjaGFyU3RyaW5nc0luZGV4LmFkZChuZXcgVWludDhBcnJheShbMHg4YiwgMHgwZV0pKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjaGFyU3RyaW5nc0luZGV4LmFkZChnbHlwaCk7CiAgICB9CiAgICByZXR1cm4gdGhpcy5jb21waWxlSW5kZXgoY2hhclN0cmluZ3NJbmRleCk7CiAgfQogIGNvbXBpbGVDaGFyc2V0KGNoYXJzZXQsIG51bUdseXBocywgc3RyaW5ncywgaXNDSURGb250KSB7CiAgICBsZXQgb3V0OwogICAgY29uc3QgbnVtR2x5cGhzTGVzc05vdERlZiA9IG51bUdseXBocyAtIDE7CiAgICBpZiAoaXNDSURGb250KSB7CiAgICAgIGNvbnN0IG5MZWZ0ID0gbnVtR2x5cGhzTGVzc05vdERlZiAtIDE7CiAgICAgIG91dCA9IG5ldyBVaW50OEFycmF5KFsyLCAwLCAxLCBuTGVmdCA+PiA4ICYgMHhmZiwgbkxlZnQgJiAweGZmXSk7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBsZW5ndGggPSAxICsgbnVtR2x5cGhzTGVzc05vdERlZiAqIDI7CiAgICAgIG91dCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCk7CiAgICAgIG91dFswXSA9IDA7CiAgICAgIGxldCBjaGFyc2V0SW5kZXggPSAwOwogICAgICBjb25zdCBudW1DaGFyc2V0cyA9IGNoYXJzZXQuY2hhcnNldC5sZW5ndGg7CiAgICAgIGxldCB3YXJuZWQgPSBmYWxzZTsKICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCBvdXQubGVuZ3RoOyBpICs9IDIpIHsKICAgICAgICBsZXQgc2lkID0gMDsKICAgICAgICBpZiAoY2hhcnNldEluZGV4IDwgbnVtQ2hhcnNldHMpIHsKICAgICAgICAgIGNvbnN0IG5hbWUgPSBjaGFyc2V0LmNoYXJzZXRbY2hhcnNldEluZGV4KytdOwogICAgICAgICAgc2lkID0gc3RyaW5ncy5nZXRTSUQobmFtZSk7CiAgICAgICAgICBpZiAoc2lkID09PSAtMSkgewogICAgICAgICAgICBzaWQgPSAwOwogICAgICAgICAgICBpZiAoIXdhcm5lZCkgewogICAgICAgICAgICAgIHdhcm5lZCA9IHRydWU7CiAgICAgICAgICAgICAgd2FybihgQ291bGRuJ3QgZmluZCAke25hbWV9IGluIENGRiBzdHJpbmdzYCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgb3V0W2ldID0gc2lkID4+IDggJiAweGZmOwogICAgICAgIG91dFtpICsgMV0gPSBzaWQgJiAweGZmOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdGhpcy5jb21waWxlVHlwZWRBcnJheShvdXQpOwogIH0KICBjb21waWxlRW5jb2RpbmcoZW5jb2RpbmcpIHsKICAgIHJldHVybiB0aGlzLmNvbXBpbGVUeXBlZEFycmF5KGVuY29kaW5nLnJhdyk7CiAgfQogIGNvbXBpbGVGRFNlbGVjdChmZFNlbGVjdCkgewogICAgY29uc3QgZm9ybWF0ID0gZmRTZWxlY3QuZm9ybWF0OwogICAgbGV0IG91dCwgaTsKICAgIHN3aXRjaCAoZm9ybWF0KSB7CiAgICAgIGNhc2UgMDoKICAgICAgICBvdXQgPSBuZXcgVWludDhBcnJheSgxICsgZmRTZWxlY3QuZmRTZWxlY3QubGVuZ3RoKTsKICAgICAgICBvdXRbMF0gPSBmb3JtYXQ7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGZkU2VsZWN0LmZkU2VsZWN0Lmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICBvdXRbaSArIDFdID0gZmRTZWxlY3QuZmRTZWxlY3RbaV07CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDM6CiAgICAgICAgY29uc3Qgc3RhcnQgPSAwOwogICAgICAgIGxldCBsYXN0RkQgPSBmZFNlbGVjdC5mZFNlbGVjdFswXTsKICAgICAgICBjb25zdCByYW5nZXMgPSBbZm9ybWF0LCAwLCAwLCBzdGFydCA+PiA4ICYgMHhmZiwgc3RhcnQgJiAweGZmLCBsYXN0RkRdOwogICAgICAgIGZvciAoaSA9IDE7IGkgPCBmZFNlbGVjdC5mZFNlbGVjdC5sZW5ndGg7IGkrKykgewogICAgICAgICAgY29uc3QgY3VycmVudEZEID0gZmRTZWxlY3QuZmRTZWxlY3RbaV07CiAgICAgICAgICBpZiAoY3VycmVudEZEICE9PSBsYXN0RkQpIHsKICAgICAgICAgICAgcmFuZ2VzLnB1c2goaSA+PiA4ICYgMHhmZiwgaSAmIDB4ZmYsIGN1cnJlbnRGRCk7CiAgICAgICAgICAgIGxhc3RGRCA9IGN1cnJlbnRGRDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgY29uc3QgbnVtUmFuZ2VzID0gKHJhbmdlcy5sZW5ndGggLSAzKSAvIDM7CiAgICAgICAgcmFuZ2VzWzFdID0gbnVtUmFuZ2VzID4+IDggJiAweGZmOwogICAgICAgIHJhbmdlc1syXSA9IG51bVJhbmdlcyAmIDB4ZmY7CiAgICAgICAgcmFuZ2VzLnB1c2goaSA+PiA4ICYgMHhmZiwgaSAmIDB4ZmYpOwogICAgICAgIG91dCA9IG5ldyBVaW50OEFycmF5KHJhbmdlcyk7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICByZXR1cm4gdGhpcy5jb21waWxlVHlwZWRBcnJheShvdXQpOwogIH0KICBjb21waWxlVHlwZWRBcnJheShkYXRhKSB7CiAgICByZXR1cm4gQXJyYXkuZnJvbShkYXRhKTsKICB9CiAgY29tcGlsZUluZGV4KGluZGV4LCB0cmFja2VycyA9IFtdKSB7CiAgICBjb25zdCBvYmplY3RzID0gaW5kZXgub2JqZWN0czsKICAgIGNvbnN0IGNvdW50ID0gb2JqZWN0cy5sZW5ndGg7CiAgICBpZiAoY291bnQgPT09IDApIHsKICAgICAgcmV0dXJuIFswLCAwXTsKICAgIH0KICAgIGNvbnN0IGRhdGEgPSBbY291bnQgPj4gOCAmIDB4ZmYsIGNvdW50ICYgMHhmZl07CiAgICBsZXQgbGFzdE9mZnNldCA9IDEsCiAgICAgIGk7CiAgICBmb3IgKGkgPSAwOyBpIDwgY291bnQ7ICsraSkgewogICAgICBsYXN0T2Zmc2V0ICs9IG9iamVjdHNbaV0ubGVuZ3RoOwogICAgfQogICAgbGV0IG9mZnNldFNpemU7CiAgICBpZiAobGFzdE9mZnNldCA8IDB4MTAwKSB7CiAgICAgIG9mZnNldFNpemUgPSAxOwogICAgfSBlbHNlIGlmIChsYXN0T2Zmc2V0IDwgMHgxMDAwMCkgewogICAgICBvZmZzZXRTaXplID0gMjsKICAgIH0gZWxzZSBpZiAobGFzdE9mZnNldCA8IDB4MTAwMDAwMCkgewogICAgICBvZmZzZXRTaXplID0gMzsKICAgIH0gZWxzZSB7CiAgICAgIG9mZnNldFNpemUgPSA0OwogICAgfQogICAgZGF0YS5wdXNoKG9mZnNldFNpemUpOwogICAgbGV0IHJlbGF0aXZlT2Zmc2V0ID0gMTsKICAgIGZvciAoaSA9IDA7IGkgPCBjb3VudCArIDE7IGkrKykgewogICAgICBpZiAob2Zmc2V0U2l6ZSA9PT0gMSkgewogICAgICAgIGRhdGEucHVzaChyZWxhdGl2ZU9mZnNldCAmIDB4ZmYpOwogICAgICB9IGVsc2UgaWYgKG9mZnNldFNpemUgPT09IDIpIHsKICAgICAgICBkYXRhLnB1c2gocmVsYXRpdmVPZmZzZXQgPj4gOCAmIDB4ZmYsIHJlbGF0aXZlT2Zmc2V0ICYgMHhmZik7CiAgICAgIH0gZWxzZSBpZiAob2Zmc2V0U2l6ZSA9PT0gMykgewogICAgICAgIGRhdGEucHVzaChyZWxhdGl2ZU9mZnNldCA+PiAxNiAmIDB4ZmYsIHJlbGF0aXZlT2Zmc2V0ID4+IDggJiAweGZmLCByZWxhdGl2ZU9mZnNldCAmIDB4ZmYpOwogICAgICB9IGVsc2UgewogICAgICAgIGRhdGEucHVzaChyZWxhdGl2ZU9mZnNldCA+Pj4gMjQgJiAweGZmLCByZWxhdGl2ZU9mZnNldCA+PiAxNiAmIDB4ZmYsIHJlbGF0aXZlT2Zmc2V0ID4+IDggJiAweGZmLCByZWxhdGl2ZU9mZnNldCAmIDB4ZmYpOwogICAgICB9CiAgICAgIGlmIChvYmplY3RzW2ldKSB7CiAgICAgICAgcmVsYXRpdmVPZmZzZXQgKz0gb2JqZWN0c1tpXS5sZW5ndGg7CiAgICAgIH0KICAgIH0KICAgIGZvciAoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgIGlmICh0cmFja2Vyc1tpXSkgewogICAgICAgIHRyYWNrZXJzW2ldLm9mZnNldChkYXRhLmxlbmd0aCk7CiAgICAgIH0KICAgICAgZGF0YS5wdXNoKC4uLm9iamVjdHNbaV0pOwogICAgfQogICAgcmV0dXJuIGRhdGE7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9zdGFuZGFyZF9mb250cy5qcwoKCmNvbnN0IGdldFN0ZEZvbnRNYXAgPSBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24gKHQpIHsKICB0WyJUaW1lcy1Sb21hbiJdID0gIlRpbWVzLVJvbWFuIjsKICB0LkhlbHZldGljYSA9ICJIZWx2ZXRpY2EiOwogIHQuQ291cmllciA9ICJDb3VyaWVyIjsKICB0LlN5bWJvbCA9ICJTeW1ib2wiOwogIHRbIlRpbWVzLUJvbGQiXSA9ICJUaW1lcy1Cb2xkIjsKICB0WyJIZWx2ZXRpY2EtQm9sZCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJDb3VyaWVyLUJvbGQiXSA9ICJDb3VyaWVyLUJvbGQiOwogIHQuWmFwZkRpbmdiYXRzID0gIlphcGZEaW5nYmF0cyI7CiAgdFsiVGltZXMtSXRhbGljIl0gPSAiVGltZXMtSXRhbGljIjsKICB0WyJIZWx2ZXRpY2EtT2JsaXF1ZSJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0WyJDb3VyaWVyLU9ibGlxdWUiXSA9ICJDb3VyaWVyLU9ibGlxdWUiOwogIHRbIlRpbWVzLUJvbGRJdGFsaWMiXSA9ICJUaW1lcy1Cb2xkSXRhbGljIjsKICB0WyJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkNvdXJpZXItQm9sZE9ibGlxdWUiXSA9ICJDb3VyaWVyLUJvbGRPYmxpcXVlIjsKICB0LkFyaWFsTmFycm93ID0gIkhlbHZldGljYSI7CiAgdFsiQXJpYWxOYXJyb3ctQm9sZCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJBcmlhbE5hcnJvdy1Cb2xkSXRhbGljIl0gPSAiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIjsKICB0WyJBcmlhbE5hcnJvdy1JdGFsaWMiXSA9ICJIZWx2ZXRpY2EtT2JsaXF1ZSI7CiAgdC5BcmlhbEJsYWNrID0gIkhlbHZldGljYSI7CiAgdFsiQXJpYWxCbGFjay1Cb2xkIl0gPSAiSGVsdmV0aWNhLUJvbGQiOwogIHRbIkFyaWFsQmxhY2stQm9sZEl0YWxpYyJdID0gIkhlbHZldGljYS1Cb2xkT2JsaXF1ZSI7CiAgdFsiQXJpYWxCbGFjay1JdGFsaWMiXSA9ICJIZWx2ZXRpY2EtT2JsaXF1ZSI7CiAgdFsiQXJpYWwtQmxhY2siXSA9ICJIZWx2ZXRpY2EiOwogIHRbIkFyaWFsLUJsYWNrLUJvbGQiXSA9ICJIZWx2ZXRpY2EtQm9sZCI7CiAgdFsiQXJpYWwtQmxhY2stQm9sZEl0YWxpYyJdID0gIkhlbHZldGljYS1Cb2xkT2JsaXF1ZSI7CiAgdFsiQXJpYWwtQmxhY2stSXRhbGljIl0gPSAiSGVsdmV0aWNhLU9ibGlxdWUiOwogIHQuQXJpYWwgPSAiSGVsdmV0aWNhIjsKICB0WyJBcmlhbC1Cb2xkIl0gPSAiSGVsdmV0aWNhLUJvbGQiOwogIHRbIkFyaWFsLUJvbGRJdGFsaWMiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkFyaWFsLUl0YWxpYyJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0LkFyaWFsTVQgPSAiSGVsdmV0aWNhIjsKICB0WyJBcmlhbC1Cb2xkSXRhbGljTVQiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkFyaWFsLUJvbGRNVCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJBcmlhbC1JdGFsaWNNVCJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0WyJBcmlhbC1Cb2xkSXRhbGljTVQtQm9sZEl0YWxpYyJdID0gIkhlbHZldGljYS1Cb2xkT2JsaXF1ZSI7CiAgdFsiQXJpYWwtQm9sZE1ULUJvbGQiXSA9ICJIZWx2ZXRpY2EtQm9sZCI7CiAgdFsiQXJpYWwtSXRhbGljTVQtSXRhbGljIl0gPSAiSGVsdmV0aWNhLU9ibGlxdWUiOwogIHQuQXJpYWxVbmljb2RlTVMgPSAiSGVsdmV0aWNhIjsKICB0WyJBcmlhbFVuaWNvZGVNUy1Cb2xkIl0gPSAiSGVsdmV0aWNhLUJvbGQiOwogIHRbIkFyaWFsVW5pY29kZU1TLUJvbGRJdGFsaWMiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkFyaWFsVW5pY29kZU1TLUl0YWxpYyJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0WyJDb3VyaWVyLUJvbGRJdGFsaWMiXSA9ICJDb3VyaWVyLUJvbGRPYmxpcXVlIjsKICB0WyJDb3VyaWVyLUl0YWxpYyJdID0gIkNvdXJpZXItT2JsaXF1ZSI7CiAgdC5Db3VyaWVyTmV3ID0gIkNvdXJpZXIiOwogIHRbIkNvdXJpZXJOZXctQm9sZCJdID0gIkNvdXJpZXItQm9sZCI7CiAgdFsiQ291cmllck5ldy1Cb2xkSXRhbGljIl0gPSAiQ291cmllci1Cb2xkT2JsaXF1ZSI7CiAgdFsiQ291cmllck5ldy1JdGFsaWMiXSA9ICJDb3VyaWVyLU9ibGlxdWUiOwogIHRbIkNvdXJpZXJOZXdQUy1Cb2xkSXRhbGljTVQiXSA9ICJDb3VyaWVyLUJvbGRPYmxpcXVlIjsKICB0WyJDb3VyaWVyTmV3UFMtQm9sZE1UIl0gPSAiQ291cmllci1Cb2xkIjsKICB0WyJDb3VyaWVyTmV3UFMtSXRhbGljTVQiXSA9ICJDb3VyaWVyLU9ibGlxdWUiOwogIHQuQ291cmllck5ld1BTTVQgPSAiQ291cmllciI7CiAgdFsiSGVsdmV0aWNhLUJvbGRJdGFsaWMiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkhlbHZldGljYS1JdGFsaWMiXSA9ICJIZWx2ZXRpY2EtT2JsaXF1ZSI7CiAgdFsiSGVsdmV0aWNhTFRTdGQtQm9sZCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJTeW1ib2wtQm9sZCJdID0gIlN5bWJvbCI7CiAgdFsiU3ltYm9sLUJvbGRJdGFsaWMiXSA9ICJTeW1ib2wiOwogIHRbIlN5bWJvbC1JdGFsaWMiXSA9ICJTeW1ib2wiOwogIHQuVGltZXNOZXdSb21hbiA9ICJUaW1lcy1Sb21hbiI7CiAgdFsiVGltZXNOZXdSb21hbi1Cb2xkIl0gPSAiVGltZXMtQm9sZCI7CiAgdFsiVGltZXNOZXdSb21hbi1Cb2xkSXRhbGljIl0gPSAiVGltZXMtQm9sZEl0YWxpYyI7CiAgdFsiVGltZXNOZXdSb21hbi1JdGFsaWMiXSA9ICJUaW1lcy1JdGFsaWMiOwogIHQuVGltZXNOZXdSb21hblBTID0gIlRpbWVzLVJvbWFuIjsKICB0WyJUaW1lc05ld1JvbWFuUFMtQm9sZCJdID0gIlRpbWVzLUJvbGQiOwogIHRbIlRpbWVzTmV3Um9tYW5QUy1Cb2xkSXRhbGljIl0gPSAiVGltZXMtQm9sZEl0YWxpYyI7CiAgdFsiVGltZXNOZXdSb21hblBTLUJvbGRJdGFsaWNNVCJdID0gIlRpbWVzLUJvbGRJdGFsaWMiOwogIHRbIlRpbWVzTmV3Um9tYW5QUy1Cb2xkTVQiXSA9ICJUaW1lcy1Cb2xkIjsKICB0WyJUaW1lc05ld1JvbWFuUFMtSXRhbGljIl0gPSAiVGltZXMtSXRhbGljIjsKICB0WyJUaW1lc05ld1JvbWFuUFMtSXRhbGljTVQiXSA9ICJUaW1lcy1JdGFsaWMiOwogIHQuVGltZXNOZXdSb21hblBTTVQgPSAiVGltZXMtUm9tYW4iOwogIHRbIlRpbWVzTmV3Um9tYW5QU01ULUJvbGQiXSA9ICJUaW1lcy1Cb2xkIjsKICB0WyJUaW1lc05ld1JvbWFuUFNNVC1Cb2xkSXRhbGljIl0gPSAiVGltZXMtQm9sZEl0YWxpYyI7CiAgdFsiVGltZXNOZXdSb21hblBTTVQtSXRhbGljIl0gPSAiVGltZXMtSXRhbGljIjsKfSk7CmNvbnN0IGdldEZvbnROYW1lVG9GaWxlTWFwID0gZ2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uICh0KSB7CiAgdC5Db3VyaWVyID0gIkZveGl0Rml4ZWQucGZiIjsKICB0WyJDb3VyaWVyLUJvbGQiXSA9ICJGb3hpdEZpeGVkQm9sZC5wZmIiOwogIHRbIkNvdXJpZXItQm9sZE9ibGlxdWUiXSA9ICJGb3hpdEZpeGVkQm9sZEl0YWxpYy5wZmIiOwogIHRbIkNvdXJpZXItT2JsaXF1ZSJdID0gIkZveGl0Rml4ZWRJdGFsaWMucGZiIjsKICB0LkhlbHZldGljYSA9ICJMaWJlcmF0aW9uU2Fucy1SZWd1bGFyLnR0ZiI7CiAgdFsiSGVsdmV0aWNhLUJvbGQiXSA9ICJMaWJlcmF0aW9uU2Fucy1Cb2xkLnR0ZiI7CiAgdFsiSGVsdmV0aWNhLUJvbGRPYmxpcXVlIl0gPSAiTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYy50dGYiOwogIHRbIkhlbHZldGljYS1PYmxpcXVlIl0gPSAiTGliZXJhdGlvblNhbnMtSXRhbGljLnR0ZiI7CiAgdFsiVGltZXMtUm9tYW4iXSA9ICJGb3hpdFNlcmlmLnBmYiI7CiAgdFsiVGltZXMtQm9sZCJdID0gIkZveGl0U2VyaWZCb2xkLnBmYiI7CiAgdFsiVGltZXMtQm9sZEl0YWxpYyJdID0gIkZveGl0U2VyaWZCb2xkSXRhbGljLnBmYiI7CiAgdFsiVGltZXMtSXRhbGljIl0gPSAiRm94aXRTZXJpZkl0YWxpYy5wZmIiOwogIHQuU3ltYm9sID0gIkZveGl0U3ltYm9sLnBmYiI7CiAgdC5aYXBmRGluZ2JhdHMgPSAiRm94aXREaW5nYmF0cy5wZmIiOwogIHRbIkxpYmVyYXRpb25TYW5zLVJlZ3VsYXIiXSA9ICJMaWJlcmF0aW9uU2Fucy1SZWd1bGFyLnR0ZiI7CiAgdFsiTGliZXJhdGlvblNhbnMtQm9sZCJdID0gIkxpYmVyYXRpb25TYW5zLUJvbGQudHRmIjsKICB0WyJMaWJlcmF0aW9uU2Fucy1JdGFsaWMiXSA9ICJMaWJlcmF0aW9uU2Fucy1JdGFsaWMudHRmIjsKICB0WyJMaWJlcmF0aW9uU2Fucy1Cb2xkSXRhbGljIl0gPSAiTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYy50dGYiOwp9KTsKY29uc3QgZ2V0Tm9uU3RkRm9udE1hcCA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogIHQuQ2FsaWJyaSA9ICJIZWx2ZXRpY2EiOwogIHRbIkNhbGlicmktQm9sZCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJDYWxpYnJpLUJvbGRJdGFsaWMiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkNhbGlicmktSXRhbGljIl0gPSAiSGVsdmV0aWNhLU9ibGlxdWUiOwogIHQuQ2VudHVyeUdvdGhpYyA9ICJIZWx2ZXRpY2EiOwogIHRbIkNlbnR1cnlHb3RoaWMtQm9sZCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJDZW50dXJ5R290aGljLUJvbGRJdGFsaWMiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkNlbnR1cnlHb3RoaWMtSXRhbGljIl0gPSAiSGVsdmV0aWNhLU9ibGlxdWUiOwogIHQuQ29taWNTYW5zTVMgPSAiQ29taWMgU2FucyBNUyI7CiAgdFsiQ29taWNTYW5zTVMtQm9sZCJdID0gIkNvbWljIFNhbnMgTVMtQm9sZCI7CiAgdFsiQ29taWNTYW5zTVMtQm9sZEl0YWxpYyJdID0gIkNvbWljIFNhbnMgTVMtQm9sZEl0YWxpYyI7CiAgdFsiQ29taWNTYW5zTVMtSXRhbGljIl0gPSAiQ29taWMgU2FucyBNUy1JdGFsaWMiOwogIHQuR2lsbFNhbnNNVCA9ICJIZWx2ZXRpY2EiOwogIHRbIkdpbGxTYW5zTVQtQm9sZCJdID0gIkhlbHZldGljYS1Cb2xkIjsKICB0WyJHaWxsU2Fuc01ULUJvbGRJdGFsaWMiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkdpbGxTYW5zTVQtSXRhbGljIl0gPSAiSGVsdmV0aWNhLU9ibGlxdWUiOwogIHQuSW1wYWN0ID0gIkhlbHZldGljYSI7CiAgdFsiSXRjU3ltYm9sLUJvbGQiXSA9ICJIZWx2ZXRpY2EtQm9sZCI7CiAgdFsiSXRjU3ltYm9sLUJvbGRJdGFsaWMiXSA9ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiOwogIHRbIkl0Y1N5bWJvbC1Cb29rIl0gPSAiSGVsdmV0aWNhIjsKICB0WyJJdGNTeW1ib2wtQm9va0l0YWxpYyJdID0gIkhlbHZldGljYS1PYmxpcXVlIjsKICB0WyJJdGNTeW1ib2wtTWVkaXVtIl0gPSAiSGVsdmV0aWNhIjsKICB0WyJJdGNTeW1ib2wtTWVkaXVtSXRhbGljIl0gPSAiSGVsdmV0aWNhLU9ibGlxdWUiOwogIHQuTHVjaWRhQ29uc29sZSA9ICJDb3VyaWVyIjsKICB0WyJMdWNpZGFDb25zb2xlLUJvbGQiXSA9ICJDb3VyaWVyLUJvbGQiOwogIHRbIkx1Y2lkYUNvbnNvbGUtQm9sZEl0YWxpYyJdID0gIkNvdXJpZXItQm9sZE9ibGlxdWUiOwogIHRbIkx1Y2lkYUNvbnNvbGUtSXRhbGljIl0gPSAiQ291cmllci1PYmxpcXVlIjsKICB0WyJMdWNpZGFTYW5zLURlbWkiXSA9ICJIZWx2ZXRpY2EtQm9sZCI7CiAgdFsiTVMtR290aGljIl0gPSAiTVMgR290aGljIjsKICB0WyJNUy1Hb3RoaWMtQm9sZCJdID0gIk1TIEdvdGhpYy1Cb2xkIjsKICB0WyJNUy1Hb3RoaWMtQm9sZEl0YWxpYyJdID0gIk1TIEdvdGhpYy1Cb2xkSXRhbGljIjsKICB0WyJNUy1Hb3RoaWMtSXRhbGljIl0gPSAiTVMgR290aGljLUl0YWxpYyI7CiAgdFsiTVMtTWluY2hvIl0gPSAiTVMgTWluY2hvIjsKICB0WyJNUy1NaW5jaG8tQm9sZCJdID0gIk1TIE1pbmNoby1Cb2xkIjsKICB0WyJNUy1NaW5jaG8tQm9sZEl0YWxpYyJdID0gIk1TIE1pbmNoby1Cb2xkSXRhbGljIjsKICB0WyJNUy1NaW5jaG8tSXRhbGljIl0gPSAiTVMgTWluY2hvLUl0YWxpYyI7CiAgdFsiTVMtUEdvdGhpYyJdID0gIk1TIFBHb3RoaWMiOwogIHRbIk1TLVBHb3RoaWMtQm9sZCJdID0gIk1TIFBHb3RoaWMtQm9sZCI7CiAgdFsiTVMtUEdvdGhpYy1Cb2xkSXRhbGljIl0gPSAiTVMgUEdvdGhpYy1Cb2xkSXRhbGljIjsKICB0WyJNUy1QR290aGljLUl0YWxpYyJdID0gIk1TIFBHb3RoaWMtSXRhbGljIjsKICB0WyJNUy1QTWluY2hvIl0gPSAiTVMgUE1pbmNobyI7CiAgdFsiTVMtUE1pbmNoby1Cb2xkIl0gPSAiTVMgUE1pbmNoby1Cb2xkIjsKICB0WyJNUy1QTWluY2hvLUJvbGRJdGFsaWMiXSA9ICJNUyBQTWluY2hvLUJvbGRJdGFsaWMiOwogIHRbIk1TLVBNaW5jaG8tSXRhbGljIl0gPSAiTVMgUE1pbmNoby1JdGFsaWMiOwogIHQuTnVwdGlhbFNjcmlwdCA9ICJUaW1lcy1JdGFsaWMiOwogIHQuU2Vnb2VVSVN5bWJvbCA9ICJIZWx2ZXRpY2EiOwp9KTsKY29uc3QgZ2V0U2VyaWZGb250cyA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogIHRbIkFkb2JlIEplbnNvbiJdID0gdHJ1ZTsKICB0WyJBZG9iZSBUZXh0Il0gPSB0cnVlOwogIHQuQWxiZXJ0dXMgPSB0cnVlOwogIHQuQWxkdXMgPSB0cnVlOwogIHQuQWxleGFuZHJpYSA9IHRydWU7CiAgdC5BbGdlcmlhbiA9IHRydWU7CiAgdFsiQW1lcmljYW4gVHlwZXdyaXRlciJdID0gdHJ1ZTsKICB0LkFudGlxdWEgPSB0cnVlOwogIHQuQXBleCA9IHRydWU7CiAgdC5Bcm5vID0gdHJ1ZTsKICB0LkFzdGVyID0gdHJ1ZTsKICB0LkF1cm9yYSA9IHRydWU7CiAgdC5CYXNrZXJ2aWxsZSA9IHRydWU7CiAgdC5CZWxsID0gdHJ1ZTsKICB0LkJlbWJvID0gdHJ1ZTsKICB0WyJCZW1ibyBTY2hvb2xib29rIl0gPSB0cnVlOwogIHQuQmVuZ3VpYXQgPSB0cnVlOwogIHRbIkJlcmtlbGV5IE9sZCBTdHlsZSJdID0gdHJ1ZTsKICB0WyJCZXJuaGFyZCBNb2Rlcm4iXSA9IHRydWU7CiAgdFsiQmVydGhvbGQgQ2l0eSJdID0gdHJ1ZTsKICB0LkJvZG9uaSA9IHRydWU7CiAgdFsiQmF1ZXIgQm9kb25pIl0gPSB0cnVlOwogIHRbIkJvb2sgQW50aXF1YSJdID0gdHJ1ZTsKICB0LkJvb2ttYW4gPSB0cnVlOwogIHRbIkJvcmRlYXV4IFJvbWFuIl0gPSB0cnVlOwogIHRbIkNhbGlmb3JuaWFuIEZCIl0gPSB0cnVlOwogIHQuQ2FsaXN0byA9IHRydWU7CiAgdC5DYWx2ZXJ0ID0gdHJ1ZTsKICB0LkNhcGl0YWxzID0gdHJ1ZTsKICB0LkNhbWJyaWEgPSB0cnVlOwogIHQuQ2FydGllciA9IHRydWU7CiAgdC5DYXNsb24gPSB0cnVlOwogIHQuQ2F0dWxsID0gdHJ1ZTsKICB0LkNlbnRhdXIgPSB0cnVlOwogIHRbIkNlbnR1cnkgT2xkIFN0eWxlIl0gPSB0cnVlOwogIHRbIkNlbnR1cnkgU2Nob29sYm9vayJdID0gdHJ1ZTsKICB0LkNoYXBhcnJhbCA9IHRydWU7CiAgdFsiQ2hhcmlzIFNJTCJdID0gdHJ1ZTsKICB0LkNoZWx0ZW5oYW0gPSB0cnVlOwogIHRbIkNob2xsYSBTbGFiIl0gPSB0cnVlOwogIHQuQ2xhcmVuZG9uID0gdHJ1ZTsKICB0LkNsZWFyZmFjZSA9IHRydWU7CiAgdC5Db2NoaW4gPSB0cnVlOwogIHQuQ29sb25uYSA9IHRydWU7CiAgdFsiQ29tcHV0ZXIgTW9kZXJuIl0gPSB0cnVlOwogIHRbIkNvbmNyZXRlIFJvbWFuIl0gPSB0cnVlOwogIHQuQ29uc3RhbnRpYSA9IHRydWU7CiAgdFsiQ29vcGVyIEJsYWNrIl0gPSB0cnVlOwogIHQuQ29yb25hID0gdHJ1ZTsKICB0LkVjb3R5cGUgPSB0cnVlOwogIHQuRWd5cHRpZW5uZSA9IHRydWU7CiAgdC5FbGVwaGFudCA9IHRydWU7CiAgdC5FeGNlbHNpb3IgPSB0cnVlOwogIHQuRmFpcmZpZWxkID0gdHJ1ZTsKICB0WyJGRiBTY2FsYSJdID0gdHJ1ZTsKICB0LkZvbGthcmQgPSB0cnVlOwogIHQuRm9vdGxpZ2h0ID0gdHJ1ZTsKICB0LkZyZWVTZXJpZiA9IHRydWU7CiAgdFsiRnJpeiBRdWFkcmF0YSJdID0gdHJ1ZTsKICB0LkdhcmFtb25kID0gdHJ1ZTsKICB0LkdlbnRpdW0gPSB0cnVlOwogIHQuR2VvcmdpYSA9IHRydWU7CiAgdC5HbG91Y2VzdGVyID0gdHJ1ZTsKICB0WyJHb3VkeSBPbGQgU3R5bGUiXSA9IHRydWU7CiAgdFsiR291ZHkgU2Nob29sYm9vayJdID0gdHJ1ZTsKICB0WyJHb3VkeSBQcm8gRm9udCJdID0gdHJ1ZTsKICB0LkdyYW5qb24gPSB0cnVlOwogIHRbIkd1YXJkaWFuIEVneXB0aWFuIl0gPSB0cnVlOwogIHQuSGVhdGhlciA9IHRydWU7CiAgdC5IZXJjdWxlcyA9IHRydWU7CiAgdFsiSGlnaCBUb3dlciBUZXh0Il0gPSB0cnVlOwogIHQuSGlyb3NoaWdlID0gdHJ1ZTsKICB0WyJIb2VmbGVyIFRleHQiXSA9IHRydWU7CiAgdFsiSHVtYW5hIFNlcmlmIl0gPSB0cnVlOwogIHQuSW1wcmludCA9IHRydWU7CiAgdFsiSW9uaWMgTm8uIDUiXSA9IHRydWU7CiAgdC5KYW5zb24gPSB0cnVlOwogIHQuSm9hbm5hID0gdHJ1ZTsKICB0LktvcmlubmEgPSB0cnVlOwogIHQuTGV4aWNvbiA9IHRydWU7CiAgdC5MaWJlcmF0aW9uU2VyaWYgPSB0cnVlOwogIHRbIkxpYmVyYXRpb24gU2VyaWYiXSA9IHRydWU7CiAgdFsiTGludXggTGliZXJ0aW5lIl0gPSB0cnVlOwogIHQuTGl0ZXJhdHVybmF5YSA9IHRydWU7CiAgdC5MdWNpZGEgPSB0cnVlOwogIHRbIkx1Y2lkYSBCcmlnaHQiXSA9IHRydWU7CiAgdC5NZWxpb3IgPSB0cnVlOwogIHQuTWVtcGhpcyA9IHRydWU7CiAgdC5NaWxsZXIgPSB0cnVlOwogIHQuTWluaW9uID0gdHJ1ZTsKICB0Lk1vZGVybiA9IHRydWU7CiAgdFsiTW9uYSBMaXNhIl0gPSB0cnVlOwogIHRbIk1ycyBFYXZlcyJdID0gdHJ1ZTsKICB0WyJNUyBTZXJpZiJdID0gdHJ1ZTsKICB0WyJNdXNlbyBTbGFiIl0gPSB0cnVlOwogIHRbIk5ldyBZb3JrIl0gPSB0cnVlOwogIHRbIk5pbWJ1cyBSb21hbiJdID0gdHJ1ZTsKICB0WyJOUFMgUmF3bGluc29uIFJvYWR3YXkiXSA9IHRydWU7CiAgdC5OdXB0aWFsU2NyaXB0ID0gdHJ1ZTsKICB0LlBhbGF0aW5vID0gdHJ1ZTsKICB0LlBlcnBldHVhID0gdHJ1ZTsKICB0LlBsYW50aW4gPSB0cnVlOwogIHRbIlBsYW50aW4gU2Nob29sYm9vayJdID0gdHJ1ZTsKICB0LlBsYXliaWxsID0gdHJ1ZTsKICB0WyJQb29yIFJpY2hhcmQiXSA9IHRydWU7CiAgdFsiUmF3bGluc29uIFJvYWR3YXkiXSA9IHRydWU7CiAgdC5SZW5hdWx0ID0gdHJ1ZTsKICB0LlJlcXVpZW0gPSB0cnVlOwogIHQuUm9ja3dlbGwgPSB0cnVlOwogIHQuUm9tYW4gPSB0cnVlOwogIHRbIlJvdGlzIFNlcmlmIl0gPSB0cnVlOwogIHQuU2Fib24gPSB0cnVlOwogIHQuU2NhbGEgPSB0cnVlOwogIHQuU2VhZ3VsbCA9IHRydWU7CiAgdC5TaXN0aW5hID0gdHJ1ZTsKICB0LlNvdXZlbmlyID0gdHJ1ZTsKICB0LlNUSVggPSB0cnVlOwogIHRbIlN0b25lIEluZm9ybWFsIl0gPSB0cnVlOwogIHRbIlN0b25lIFNlcmlmIl0gPSB0cnVlOwogIHQuU3lsZmFlbiA9IHRydWU7CiAgdC5UaW1lcyA9IHRydWU7CiAgdC5UcmFqYW4gPSB0cnVlOwogIHRbIlRyaW5pdMOpIl0gPSB0cnVlOwogIHRbIlRydW1wIE1lZGlhZXZhbCJdID0gdHJ1ZTsKICB0LlV0b3BpYSA9IHRydWU7CiAgdFsiVmFsZSBUeXBlIl0gPSB0cnVlOwogIHRbIkJpdHN0cmVhbSBWZXJhIl0gPSB0cnVlOwogIHRbIlZlcmEgU2VyaWYiXSA9IHRydWU7CiAgdC5WZXJzYWlsbGVzID0gdHJ1ZTsKICB0LldhbnRlZCA9IHRydWU7CiAgdC5XZWlzcyA9IHRydWU7CiAgdFsiV2lkZSBMYXRpbiJdID0gdHJ1ZTsKICB0LldpbmRzb3IgPSB0cnVlOwogIHQuWElUUyA9IHRydWU7Cn0pOwpjb25zdCBnZXRTeW1ib2xzRm9udHMgPSBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24gKHQpIHsKICB0LkRpbmdiYXRzID0gdHJ1ZTsKICB0LlN5bWJvbCA9IHRydWU7CiAgdC5aYXBmRGluZ2JhdHMgPSB0cnVlOwogIHQuV2luZ2RpbmdzID0gdHJ1ZTsKICB0WyJXaW5nZGluZ3MtQm9sZCJdID0gdHJ1ZTsKICB0WyJXaW5nZGluZ3MtUmVndWxhciJdID0gdHJ1ZTsKfSk7CmNvbnN0IGdldEdseXBoTWFwRm9yU3RhbmRhcmRGb250cyA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogIHRbMl0gPSAxMDsKICB0WzNdID0gMzI7CiAgdFs0XSA9IDMzOwogIHRbNV0gPSAzNDsKICB0WzZdID0gMzU7CiAgdFs3XSA9IDM2OwogIHRbOF0gPSAzNzsKICB0WzldID0gMzg7CiAgdFsxMF0gPSAzOTsKICB0WzExXSA9IDQwOwogIHRbMTJdID0gNDE7CiAgdFsxM10gPSA0MjsKICB0WzE0XSA9IDQzOwogIHRbMTVdID0gNDQ7CiAgdFsxNl0gPSA0NTsKICB0WzE3XSA9IDQ2OwogIHRbMThdID0gNDc7CiAgdFsxOV0gPSA0ODsKICB0WzIwXSA9IDQ5OwogIHRbMjFdID0gNTA7CiAgdFsyMl0gPSA1MTsKICB0WzIzXSA9IDUyOwogIHRbMjRdID0gNTM7CiAgdFsyNV0gPSA1NDsKICB0WzI2XSA9IDU1OwogIHRbMjddID0gNTY7CiAgdFsyOF0gPSA1NzsKICB0WzI5XSA9IDU4OwogIHRbMzBdID0gODk0OwogIHRbMzFdID0gNjA7CiAgdFszMl0gPSA2MTsKICB0WzMzXSA9IDYyOwogIHRbMzRdID0gNjM7CiAgdFszNV0gPSA2NDsKICB0WzM2XSA9IDY1OwogIHRbMzddID0gNjY7CiAgdFszOF0gPSA2NzsKICB0WzM5XSA9IDY4OwogIHRbNDBdID0gNjk7CiAgdFs0MV0gPSA3MDsKICB0WzQyXSA9IDcxOwogIHRbNDNdID0gNzI7CiAgdFs0NF0gPSA3MzsKICB0WzQ1XSA9IDc0OwogIHRbNDZdID0gNzU7CiAgdFs0N10gPSA3NjsKICB0WzQ4XSA9IDc3OwogIHRbNDldID0gNzg7CiAgdFs1MF0gPSA3OTsKICB0WzUxXSA9IDgwOwogIHRbNTJdID0gODE7CiAgdFs1M10gPSA4MjsKICB0WzU0XSA9IDgzOwogIHRbNTVdID0gODQ7CiAgdFs1Nl0gPSA4NTsKICB0WzU3XSA9IDg2OwogIHRbNThdID0gODc7CiAgdFs1OV0gPSA4ODsKICB0WzYwXSA9IDg5OwogIHRbNjFdID0gOTA7CiAgdFs2Ml0gPSA5MTsKICB0WzYzXSA9IDkyOwogIHRbNjRdID0gOTM7CiAgdFs2NV0gPSA5NDsKICB0WzY2XSA9IDk1OwogIHRbNjddID0gOTY7CiAgdFs2OF0gPSA5NzsKICB0WzY5XSA9IDk4OwogIHRbNzBdID0gOTk7CiAgdFs3MV0gPSAxMDA7CiAgdFs3Ml0gPSAxMDE7CiAgdFs3M10gPSAxMDI7CiAgdFs3NF0gPSAxMDM7CiAgdFs3NV0gPSAxMDQ7CiAgdFs3Nl0gPSAxMDU7CiAgdFs3N10gPSAxMDY7CiAgdFs3OF0gPSAxMDc7CiAgdFs3OV0gPSAxMDg7CiAgdFs4MF0gPSAxMDk7CiAgdFs4MV0gPSAxMTA7CiAgdFs4Ml0gPSAxMTE7CiAgdFs4M10gPSAxMTI7CiAgdFs4NF0gPSAxMTM7CiAgdFs4NV0gPSAxMTQ7CiAgdFs4Nl0gPSAxMTU7CiAgdFs4N10gPSAxMTY7CiAgdFs4OF0gPSAxMTc7CiAgdFs4OV0gPSAxMTg7CiAgdFs5MF0gPSAxMTk7CiAgdFs5MV0gPSAxMjA7CiAgdFs5Ml0gPSAxMjE7CiAgdFs5M10gPSAxMjI7CiAgdFs5NF0gPSAxMjM7CiAgdFs5NV0gPSAxMjQ7CiAgdFs5Nl0gPSAxMjU7CiAgdFs5N10gPSAxMjY7CiAgdFs5OF0gPSAxOTY7CiAgdFs5OV0gPSAxOTc7CiAgdFsxMDBdID0gMTk5OwogIHRbMTAxXSA9IDIwMTsKICB0WzEwMl0gPSAyMDk7CiAgdFsxMDNdID0gMjE0OwogIHRbMTA0XSA9IDIyMDsKICB0WzEwNV0gPSAyMjU7CiAgdFsxMDZdID0gMjI0OwogIHRbMTA3XSA9IDIyNjsKICB0WzEwOF0gPSAyMjg7CiAgdFsxMDldID0gMjI3OwogIHRbMTEwXSA9IDIyOTsKICB0WzExMV0gPSAyMzE7CiAgdFsxMTJdID0gMjMzOwogIHRbMTEzXSA9IDIzMjsKICB0WzExNF0gPSAyMzQ7CiAgdFsxMTVdID0gMjM1OwogIHRbMTE2XSA9IDIzNzsKICB0WzExN10gPSAyMzY7CiAgdFsxMThdID0gMjM4OwogIHRbMTE5XSA9IDIzOTsKICB0WzEyMF0gPSAyNDE7CiAgdFsxMjFdID0gMjQzOwogIHRbMTIyXSA9IDI0MjsKICB0WzEyM10gPSAyNDQ7CiAgdFsxMjRdID0gMjQ2OwogIHRbMTI1XSA9IDI0NTsKICB0WzEyNl0gPSAyNTA7CiAgdFsxMjddID0gMjQ5OwogIHRbMTI4XSA9IDI1MTsKICB0WzEyOV0gPSAyNTI7CiAgdFsxMzBdID0gODIyNDsKICB0WzEzMV0gPSAxNzY7CiAgdFsxMzJdID0gMTYyOwogIHRbMTMzXSA9IDE2MzsKICB0WzEzNF0gPSAxNjc7CiAgdFsxMzVdID0gODIyNjsKICB0WzEzNl0gPSAxODI7CiAgdFsxMzddID0gMjIzOwogIHRbMTM4XSA9IDE3NDsKICB0WzEzOV0gPSAxNjk7CiAgdFsxNDBdID0gODQ4MjsKICB0WzE0MV0gPSAxODA7CiAgdFsxNDJdID0gMTY4OwogIHRbMTQzXSA9IDg4MDA7CiAgdFsxNDRdID0gMTk4OwogIHRbMTQ1XSA9IDIxNjsKICB0WzE0Nl0gPSA4NzM0OwogIHRbMTQ3XSA9IDE3NzsKICB0WzE0OF0gPSA4ODA0OwogIHRbMTQ5XSA9IDg4MDU7CiAgdFsxNTBdID0gMTY1OwogIHRbMTUxXSA9IDE4MTsKICB0WzE1Ml0gPSA4NzA2OwogIHRbMTUzXSA9IDg3MjE7CiAgdFsxNTRdID0gODcxOTsKICB0WzE1Nl0gPSA4NzQ3OwogIHRbMTU3XSA9IDE3MDsKICB0WzE1OF0gPSAxODY7CiAgdFsxNTldID0gODQ4NjsKICB0WzE2MF0gPSAyMzA7CiAgdFsxNjFdID0gMjQ4OwogIHRbMTYyXSA9IDE5MTsKICB0WzE2M10gPSAxNjE7CiAgdFsxNjRdID0gMTcyOwogIHRbMTY1XSA9IDg3MzA7CiAgdFsxNjZdID0gNDAyOwogIHRbMTY3XSA9IDg3NzY7CiAgdFsxNjhdID0gODcxMDsKICB0WzE2OV0gPSAxNzE7CiAgdFsxNzBdID0gMTg3OwogIHRbMTcxXSA9IDgyMzA7CiAgdFsxNzldID0gODIyMDsKICB0WzE4MF0gPSA4MjIxOwogIHRbMTgxXSA9IDgyMTY7CiAgdFsxODJdID0gODIxNzsKICB0WzIwMF0gPSAxOTM7CiAgdFsyMDNdID0gMjA1OwogIHRbMjA3XSA9IDIxMTsKICB0WzIxMF0gPSAyMTg7CiAgdFsyMjNdID0gNzExOwogIHRbMjI0XSA9IDMyMTsKICB0WzIyNV0gPSAzMjI7CiAgdFsyMjZdID0gMzUyOwogIHRbMjI3XSA9IDM1MzsKICB0WzIyOF0gPSAzODE7CiAgdFsyMjldID0gMzgyOwogIHRbMjMzXSA9IDIyMTsKICB0WzIzNF0gPSAyNTM7CiAgdFsyNTJdID0gMjYzOwogIHRbMjUzXSA9IDI2ODsKICB0WzI1NF0gPSAyNjk7CiAgdFsyNThdID0gMjU4OwogIHRbMjYwXSA9IDI2MDsKICB0WzI2MV0gPSAyNjE7CiAgdFsyNjVdID0gMjgwOwogIHRbMjY2XSA9IDI4MTsKICB0WzI2N10gPSAyODI7CiAgdFsyNjhdID0gMjgzOwogIHRbMjY5XSA9IDMxMzsKICB0WzI3NV0gPSAzMjM7CiAgdFsyNzZdID0gMzI0OwogIHRbMjc4XSA9IDMyODsKICB0WzI4M10gPSAzNDQ7CiAgdFsyODRdID0gMzQ1OwogIHRbMjg1XSA9IDM0NjsKICB0WzI4Nl0gPSAzNDc7CiAgdFsyOTJdID0gMzY3OwogIHRbMjk1XSA9IDM3NzsKICB0WzI5Nl0gPSAzNzg7CiAgdFsyOThdID0gMzgwOwogIHRbMzA1XSA9IDk2MzsKICB0WzMwNl0gPSA5NjQ7CiAgdFszMDddID0gOTY2OwogIHRbMzA4XSA9IDgyMTU7CiAgdFszMDldID0gODI1MjsKICB0WzMxMF0gPSA4MzE5OwogIHRbMzExXSA9IDgzNTk7CiAgdFszMTJdID0gODU5MjsKICB0WzMxM10gPSA4NTkzOwogIHRbMzM3XSA9IDk1NTI7CiAgdFs0OTNdID0gMTAzOTsKICB0WzQ5NF0gPSAxMDQwOwogIHRbNTcwXSA9IDEwNDA7CiAgdFs1NzFdID0gMTA0MTsKICB0WzU3Ml0gPSAxMDQyOwogIHRbNTczXSA9IDEwNDM7CiAgdFs1NzRdID0gMTA0NDsKICB0WzU3NV0gPSAxMDQ1OwogIHRbNTc2XSA9IDEwNDY7CiAgdFs1NzddID0gMTA0NzsKICB0WzU3OF0gPSAxMDQ4OwogIHRbNTc5XSA9IDEwNDk7CiAgdFs1ODBdID0gMTA1MDsKICB0WzU4MV0gPSAxMDUxOwogIHRbNTgyXSA9IDEwNTI7CiAgdFs1ODNdID0gMTA1MzsKICB0WzU4NF0gPSAxMDU0OwogIHRbNTg1XSA9IDEwNTU7CiAgdFs1ODZdID0gMTA1NjsKICB0WzU4N10gPSAxMDU3OwogIHRbNTg4XSA9IDEwNTg7CiAgdFs1ODldID0gMTA1OTsKICB0WzU5MF0gPSAxMDYwOwogIHRbNTkxXSA9IDEwNjE7CiAgdFs1OTJdID0gMTA2MjsKICB0WzU5M10gPSAxMDYzOwogIHRbNTk0XSA9IDEwNjQ7CiAgdFs1OTVdID0gMTA2NTsKICB0WzU5Nl0gPSAxMDY2OwogIHRbNTk3XSA9IDEwNjc7CiAgdFs1OThdID0gMTA2ODsKICB0WzU5OV0gPSAxMDY5OwogIHRbNjAwXSA9IDEwNzA7CiAgdFs2NzJdID0gMTQ4ODsKICB0WzY3M10gPSAxNDg5OwogIHRbNjc0XSA9IDE0OTA7CiAgdFs2NzVdID0gMTQ5MTsKICB0WzY3Nl0gPSAxNDkyOwogIHRbNjc3XSA9IDE0OTM7CiAgdFs2NzhdID0gMTQ5NDsKICB0WzY3OV0gPSAxNDk1OwogIHRbNjgwXSA9IDE0OTY7CiAgdFs2ODFdID0gMTQ5NzsKICB0WzY4Ml0gPSAxNDk4OwogIHRbNjgzXSA9IDE0OTk7CiAgdFs2ODRdID0gMTUwMDsKICB0WzY4NV0gPSAxNTAxOwogIHRbNjg2XSA9IDE1MDI7CiAgdFs2ODddID0gMTUwMzsKICB0WzY4OF0gPSAxNTA0OwogIHRbNjg5XSA9IDE1MDU7CiAgdFs2OTBdID0gMTUwNjsKICB0WzY5MV0gPSAxNTA3OwogIHRbNjkyXSA9IDE1MDg7CiAgdFs2OTNdID0gMTUwOTsKICB0WzY5NF0gPSAxNTEwOwogIHRbNjk1XSA9IDE1MTE7CiAgdFs2OTZdID0gMTUxMjsKICB0WzY5N10gPSAxNTEzOwogIHRbNjk4XSA9IDE1MTQ7CiAgdFs3MDVdID0gMTUyNDsKICB0WzcwNl0gPSA4MzYyOwogIHRbNzEwXSA9IDY0Mjg4OwogIHRbNzExXSA9IDY0Mjk4OwogIHRbNzU5XSA9IDE2MTc7CiAgdFs3NjFdID0gMTc3NjsKICB0Wzc2M10gPSAxNzc4OwogIHRbNzc1XSA9IDE2NTI7CiAgdFs3NzddID0gMTc2NDsKICB0Wzc3OF0gPSAxNzgwOwogIHRbNzc5XSA9IDE3ODE7CiAgdFs3ODBdID0gMTc4MjsKICB0Wzc4Ml0gPSA3NzE7CiAgdFs3ODNdID0gNjQ3MjY7CiAgdFs3ODZdID0gODM2MzsKICB0Wzc4OF0gPSA4NTMyOwogIHRbNzkwXSA9IDc2ODsKICB0Wzc5MV0gPSA3Njk7CiAgdFs3OTJdID0gNzY4OwogIHRbNzk1XSA9IDgwMzsKICB0Wzc5N10gPSA2NDMzNjsKICB0Wzc5OF0gPSA2NDMzNzsKICB0Wzc5OV0gPSA2NDM0MjsKICB0WzgwMF0gPSA2NDM0MzsKICB0WzgwMV0gPSA2NDM0NDsKICB0WzgwMl0gPSA2NDM0NTsKICB0WzgwM10gPSA2NDM2MjsKICB0WzgwNF0gPSA2NDM2MzsKICB0WzgwNV0gPSA2NDM2NDsKICB0WzI0MjRdID0gNzgyMTsKICB0WzI0MjVdID0gNzgyMjsKICB0WzI0MjZdID0gNzgyMzsKICB0WzI0MjddID0gNzgyNDsKICB0WzI0MjhdID0gNzgyNTsKICB0WzI0MjldID0gNzgyNjsKICB0WzI0MzBdID0gNzgyNzsKICB0WzI0MzNdID0gNzY4MjsKICB0WzI2NzhdID0gODA0NTsKICB0WzI2NzldID0gODA0NjsKICB0WzI4MzBdID0gMTU1MjsKICB0WzI4MzhdID0gNjg2OwogIHRbMjg0MF0gPSA3NTE7CiAgdFsyODQyXSA9IDc1MzsKICB0WzI4NDNdID0gNzU0OwogIHRbMjg0NF0gPSA3NTU7CiAgdFsyODQ2XSA9IDc1NzsKICB0WzI4NTZdID0gNzY3OwogIHRbMjg1N10gPSA4NDg7CiAgdFsyODU4XSA9IDg0OTsKICB0WzI4NjJdID0gODUzOwogIHRbMjg2M10gPSA4NTQ7CiAgdFsyODY0XSA9IDg1NTsKICB0WzI4NjVdID0gODYxOwogIHRbMjg2Nl0gPSA4NjI7CiAgdFsyOTA2XSA9IDc0NjA7CiAgdFsyOTA4XSA9IDc0NjI7CiAgdFsyOTA5XSA9IDc0NjM7CiAgdFsyOTEwXSA9IDc0NjQ7CiAgdFsyOTEyXSA9IDc0NjY7CiAgdFsyOTEzXSA9IDc0Njc7CiAgdFsyOTE0XSA9IDc0Njg7CiAgdFsyOTE2XSA9IDc0NzA7CiAgdFsyOTE3XSA9IDc0NzE7CiAgdFsyOTE4XSA9IDc0NzI7CiAgdFsyOTIwXSA9IDc0NzQ7CiAgdFsyOTIxXSA9IDc0NzU7CiAgdFsyOTIyXSA9IDc0NzY7CiAgdFsyOTI0XSA9IDc0Nzg7CiAgdFsyOTI1XSA9IDc0Nzk7CiAgdFsyOTI2XSA9IDc0ODA7CiAgdFsyOTI4XSA9IDc0ODI7CiAgdFsyOTI5XSA9IDc0ODM7CiAgdFsyOTMwXSA9IDc0ODQ7CiAgdFsyOTMyXSA9IDc0ODY7CiAgdFsyOTMzXSA9IDc0ODc7CiAgdFsyOTM0XSA9IDc0ODg7CiAgdFsyOTM2XSA9IDc0OTA7CiAgdFsyOTM3XSA9IDc0OTE7CiAgdFsyOTM4XSA9IDc0OTI7CiAgdFsyOTQwXSA9IDc0OTQ7CiAgdFsyOTQxXSA9IDc0OTU7CiAgdFsyOTQyXSA9IDc0OTY7CiAgdFsyOTQ0XSA9IDc0OTg7CiAgdFsyOTQ2XSA9IDc1MDA7CiAgdFsyOTQ4XSA9IDc1MDI7CiAgdFsyOTUwXSA9IDc1MDQ7CiAgdFsyOTUxXSA9IDc1MDU7CiAgdFsyOTUyXSA9IDc1MDY7CiAgdFsyOTU0XSA9IDc1MDg7CiAgdFsyOTU1XSA9IDc1MDk7CiAgdFsyOTU2XSA9IDc1MTA7CiAgdFsyOTU4XSA9IDc1MTI7CiAgdFsyOTU5XSA9IDc1MTM7CiAgdFsyOTYwXSA9IDc1MTQ7CiAgdFsyOTYyXSA9IDc1MTY7CiAgdFsyOTYzXSA9IDc1MTc7CiAgdFsyOTY0XSA9IDc1MTg7CiAgdFsyOTY2XSA9IDc1MjA7CiAgdFsyOTY3XSA9IDc1MjE7CiAgdFsyOTY4XSA9IDc1MjI7CiAgdFsyOTcwXSA9IDc1MjQ7CiAgdFsyOTcxXSA9IDc1MjU7CiAgdFsyOTcyXSA9IDc1MjY7CiAgdFsyOTc0XSA9IDc1Mjg7CiAgdFsyOTc1XSA9IDc1Mjk7CiAgdFsyOTc2XSA9IDc1MzA7CiAgdFsyOTc4XSA9IDE1Mzc7CiAgdFsyOTc5XSA9IDE1Mzg7CiAgdFsyOTgwXSA9IDE1Mzk7CiAgdFsyOTgyXSA9IDE1NDk7CiAgdFsyOTgzXSA9IDE1NTE7CiAgdFsyOTg0XSA9IDE1NTI7CiAgdFsyOTg2XSA9IDE1NTQ7CiAgdFsyOTg3XSA9IDE1NTU7CiAgdFsyOTg4XSA9IDE1NTY7CiAgdFsyOTkwXSA9IDE2MjM7CiAgdFsyOTkxXSA9IDE2MjQ7CiAgdFsyOTk1XSA9IDE3NzU7CiAgdFsyOTk5XSA9IDE3OTE7CiAgdFszMDAyXSA9IDY0MjkwOwogIHRbMzAwM10gPSA2NDI5MTsKICB0WzMwMDRdID0gNjQyOTI7CiAgdFszMDA2XSA9IDY0Mjk0OwogIHRbMzAwN10gPSA2NDI5NTsKICB0WzMwMDhdID0gNjQyOTY7CiAgdFszMDExXSA9IDE5MDA7CiAgdFszMDE0XSA9IDgyMjM7CiAgdFszMDE1XSA9IDgyNDQ7CiAgdFszMDE3XSA9IDc1MzI7CiAgdFszMDE4XSA9IDc1MzM7CiAgdFszMDE5XSA9IDc1MzQ7CiAgdFszMDc1XSA9IDc1OTA7CiAgdFszMDc2XSA9IDc1OTE7CiAgdFszMDc5XSA9IDc1OTQ7CiAgdFszMDgwXSA9IDc1OTU7CiAgdFszMDgzXSA9IDc1OTg7CiAgdFszMDg0XSA9IDc1OTk7CiAgdFszMDg3XSA9IDc2MDI7CiAgdFszMDg4XSA9IDc2MDM7CiAgdFszMDkxXSA9IDc2MDY7CiAgdFszMDkyXSA9IDc2MDc7CiAgdFszMDk1XSA9IDc2MTA7CiAgdFszMDk2XSA9IDc2MTE7CiAgdFszMDk5XSA9IDc2MTQ7CiAgdFszMTAwXSA9IDc2MTU7CiAgdFszMTAzXSA9IDc2MTg7CiAgdFszMTA0XSA9IDc2MTk7CiAgdFszMTA3XSA9IDgzMzc7CiAgdFszMTA4XSA9IDgzMzg7CiAgdFszMTE2XSA9IDE4ODQ7CiAgdFszMTE5XSA9IDE4ODU7CiAgdFszMTIwXSA9IDE4ODU7CiAgdFszMTIzXSA9IDE4ODY7CiAgdFszMTI0XSA9IDE4ODY7CiAgdFszMTI3XSA9IDE4ODc7CiAgdFszMTI4XSA9IDE4ODc7CiAgdFszMTMxXSA9IDE4ODg7CiAgdFszMTMyXSA9IDE4ODg7CiAgdFszMTM1XSA9IDE4ODk7CiAgdFszMTM2XSA9IDE4ODk7CiAgdFszMTM5XSA9IDE4OTA7CiAgdFszMTQwXSA9IDE4OTA7CiAgdFszMTQzXSA9IDE4OTE7CiAgdFszMTQ0XSA9IDE4OTE7CiAgdFszMTQ3XSA9IDE4OTI7CiAgdFszMTQ4XSA9IDE4OTI7CiAgdFszMTUzXSA9IDU4MDsKICB0WzMxNTRdID0gNTgxOwogIHRbMzE1N10gPSA1ODQ7CiAgdFszMTU4XSA9IDU4NTsKICB0WzMxNjFdID0gNTg4OwogIHRbMzE2Ml0gPSA1ODk7CiAgdFszMTY1XSA9IDg5MTsKICB0WzMxNjZdID0gODkyOwogIHRbMzE2OV0gPSAxMjc0OwogIHRbMzE3MF0gPSAxMjc1OwogIHRbMzE3M10gPSAxMjc4OwogIHRbMzE3NF0gPSAxMjc5OwogIHRbMzE4MV0gPSA3NjIyOwogIHRbMzE4Ml0gPSA3NjIzOwogIHRbMzI4Ml0gPSAxMTc5OTsKICB0WzMzMTZdID0gNTc4OwogIHRbMzM3OV0gPSA0Mjc4NTsKICB0WzMzOTNdID0gMTE1OTsKICB0WzM0MTZdID0gODM3NzsKfSk7CmNvbnN0IGdldFN1cHBsZW1lbnRhbEdseXBoTWFwRm9yQXJpYWxCbGFjayA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogIHRbMjI3XSA9IDMyMjsKICB0WzI2NF0gPSAyNjE7CiAgdFsyOTFdID0gMzQ2Owp9KTsKY29uc3QgZ2V0U3VwcGxlbWVudGFsR2x5cGhNYXBGb3JDYWxpYnJpID0gZ2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uICh0KSB7CiAgdFsxXSA9IDMyOwogIHRbNF0gPSA2NTsKICB0WzVdID0gMTkyOwogIHRbNl0gPSAxOTM7CiAgdFs5XSA9IDE5NjsKICB0WzE3XSA9IDY2OwogIHRbMThdID0gNjc7CiAgdFsyMV0gPSAyNjg7CiAgdFsyNF0gPSA2ODsKICB0WzI4XSA9IDY5OwogIHRbMjldID0gMjAwOwogIHRbMzBdID0gMjAxOwogIHRbMzJdID0gMjgyOwogIHRbMzhdID0gNzA7CiAgdFszOV0gPSA3MTsKICB0WzQ0XSA9IDcyOwogIHRbNDddID0gNzM7CiAgdFs0OF0gPSAyMDQ7CiAgdFs0OV0gPSAyMDU7CiAgdFs1OF0gPSA3NDsKICB0WzYwXSA9IDc1OwogIHRbNjJdID0gNzY7CiAgdFs2OF0gPSA3NzsKICB0WzY5XSA9IDc4OwogIHRbNzVdID0gNzk7CiAgdFs3Nl0gPSAyMTA7CiAgdFs4MF0gPSAyMTQ7CiAgdFs4N10gPSA4MDsKICB0Wzg5XSA9IDgxOwogIHRbOTBdID0gODI7CiAgdFs5Ml0gPSAzNDQ7CiAgdFs5NF0gPSA4MzsKICB0Wzk3XSA9IDM1MjsKICB0WzEwMF0gPSA4NDsKICB0WzEwNF0gPSA4NTsKICB0WzEwOV0gPSAyMjA7CiAgdFsxMTVdID0gODY7CiAgdFsxMTZdID0gODc7CiAgdFsxMjFdID0gODg7CiAgdFsxMjJdID0gODk7CiAgdFsxMjRdID0gMjIxOwogIHRbMTI3XSA9IDkwOwogIHRbMTI5XSA9IDM4MTsKICB0WzI1OF0gPSA5NzsKICB0WzI1OV0gPSAyMjQ7CiAgdFsyNjBdID0gMjI1OwogIHRbMjYzXSA9IDIyODsKICB0WzI2OF0gPSAyNjE7CiAgdFsyNzFdID0gOTg7CiAgdFsyNzJdID0gOTk7CiAgdFsyNzNdID0gMjYzOwogIHRbMjc1XSA9IDI2OTsKICB0WzI4Ml0gPSAxMDA7CiAgdFsyODZdID0gMTAxOwogIHRbMjg3XSA9IDIzMjsKICB0WzI4OF0gPSAyMzM7CiAgdFsyOTBdID0gMjgzOwogIHRbMjk1XSA9IDI4MTsKICB0WzI5Nl0gPSAxMDI7CiAgdFszMzZdID0gMTAzOwogIHRbMzQ2XSA9IDEwNDsKICB0WzM0OV0gPSAxMDU7CiAgdFszNTBdID0gMjM2OwogIHRbMzUxXSA9IDIzNzsKICB0WzM2MV0gPSAxMDY7CiAgdFszNjRdID0gMTA3OwogIHRbMzY3XSA9IDEwODsKICB0WzM3MV0gPSAzMjI7CiAgdFszNzNdID0gMTA5OwogIHRbMzc0XSA9IDExMDsKICB0WzM4MV0gPSAxMTE7CiAgdFszODJdID0gMjQyOwogIHRbMzgzXSA9IDI0MzsKICB0WzM4Nl0gPSAyNDY7CiAgdFszOTNdID0gMTEyOwogIHRbMzk1XSA9IDExMzsKICB0WzM5Nl0gPSAxMTQ7CiAgdFszOThdID0gMzQ1OwogIHRbNDAwXSA9IDExNTsKICB0WzQwMV0gPSAzNDc7CiAgdFs0MDNdID0gMzUzOwogIHRbNDEwXSA9IDExNjsKICB0WzQzN10gPSAxMTc7CiAgdFs0NDJdID0gMjUyOwogIHRbNDQ4XSA9IDExODsKICB0WzQ0OV0gPSAxMTk7CiAgdFs0NTRdID0gMTIwOwogIHRbNDU1XSA9IDEyMTsKICB0WzQ1N10gPSAyNTM7CiAgdFs0NjBdID0gMTIyOwogIHRbNDYyXSA9IDM4MjsKICB0WzQ2M10gPSAzODA7CiAgdFs4NTNdID0gNDQ7CiAgdFs4NTVdID0gNTg7CiAgdFs4NTZdID0gNDY7CiAgdFs4NzZdID0gNDc7CiAgdFs4NzhdID0gNDU7CiAgdFs4ODJdID0gNDU7CiAgdFs4OTRdID0gNDA7CiAgdFs4OTVdID0gNDE7CiAgdFs4OTZdID0gOTE7CiAgdFs4OTddID0gOTM7CiAgdFs5MjNdID0gNjQ7CiAgdFs5NDBdID0gMTYzOwogIHRbMTAwNF0gPSA0ODsKICB0WzEwMDVdID0gNDk7CiAgdFsxMDA2XSA9IDUwOwogIHRbMTAwN10gPSA1MTsKICB0WzEwMDhdID0gNTI7CiAgdFsxMDA5XSA9IDUzOwogIHRbMTAxMF0gPSA1NDsKICB0WzEwMTFdID0gNTU7CiAgdFsxMDEyXSA9IDU2OwogIHRbMTAxM10gPSA1NzsKICB0WzEwODFdID0gMzc7CiAgdFsxMDg1XSA9IDQzOwogIHRbMTA4Nl0gPSA0NTsKfSk7CmZ1bmN0aW9uIGdldFN0YW5kYXJkRm9udE5hbWUobmFtZSkgewogIGNvbnN0IGZvbnROYW1lID0gbm9ybWFsaXplRm9udE5hbWUobmFtZSk7CiAgY29uc3Qgc3RkRm9udE1hcCA9IGdldFN0ZEZvbnRNYXAoKTsKICByZXR1cm4gc3RkRm9udE1hcFtmb250TmFtZV07Cn0KZnVuY3Rpb24gaXNLbm93bkZvbnROYW1lKG5hbWUpIHsKICBjb25zdCBmb250TmFtZSA9IG5vcm1hbGl6ZUZvbnROYW1lKG5hbWUpOwogIHJldHVybiAhIShnZXRTdGRGb250TWFwKClbZm9udE5hbWVdIHx8IGdldE5vblN0ZEZvbnRNYXAoKVtmb250TmFtZV0gfHwgZ2V0U2VyaWZGb250cygpW2ZvbnROYW1lXSB8fCBnZXRTeW1ib2xzRm9udHMoKVtmb250TmFtZV0pOwp9Cgo7Ly8gLi9zcmMvY29yZS90b191bmljb2RlX21hcC5qcwoKY2xhc3MgVG9Vbmljb2RlTWFwIHsKICBjb25zdHJ1Y3RvcihjbWFwID0gW10pIHsKICAgIHRoaXMuX21hcCA9IGNtYXA7CiAgfQogIGdldCBsZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5fbWFwLmxlbmd0aDsKICB9CiAgZm9yRWFjaChjYWxsYmFjaykgewogICAgZm9yIChjb25zdCBjaGFyQ29kZSBpbiB0aGlzLl9tYXApIHsKICAgICAgY2FsbGJhY2soY2hhckNvZGUsIHRoaXMuX21hcFtjaGFyQ29kZV0uY29kZVBvaW50QXQoMCkpOwogICAgfQogIH0KICBoYXMoaSkgewogICAgcmV0dXJuIHRoaXMuX21hcFtpXSAhPT0gdW5kZWZpbmVkOwogIH0KICBnZXQoaSkgewogICAgcmV0dXJuIHRoaXMuX21hcFtpXTsKICB9CiAgY2hhckNvZGVPZih2YWx1ZSkgewogICAgY29uc3QgbWFwID0gdGhpcy5fbWFwOwogICAgaWYgKG1hcC5sZW5ndGggPD0gMHgxMDAwMCkgewogICAgICByZXR1cm4gbWFwLmluZGV4T2YodmFsdWUpOwogICAgfQogICAgZm9yIChjb25zdCBjaGFyQ29kZSBpbiBtYXApIHsKICAgICAgaWYgKG1hcFtjaGFyQ29kZV0gPT09IHZhbHVlKSB7CiAgICAgICAgcmV0dXJuIGNoYXJDb2RlIHwgMDsKICAgICAgfQogICAgfQogICAgcmV0dXJuIC0xOwogIH0KICBhbWVuZChtYXApIHsKICAgIGZvciAoY29uc3QgY2hhckNvZGUgaW4gbWFwKSB7CiAgICAgIHRoaXMuX21hcFtjaGFyQ29kZV0gPSBtYXBbY2hhckNvZGVdOwogICAgfQogIH0KfQpjbGFzcyBJZGVudGl0eVRvVW5pY29kZU1hcCB7CiAgY29uc3RydWN0b3IoZmlyc3RDaGFyLCBsYXN0Q2hhcikgewogICAgdGhpcy5maXJzdENoYXIgPSBmaXJzdENoYXI7CiAgICB0aGlzLmxhc3RDaGFyID0gbGFzdENoYXI7CiAgfQogIGdldCBsZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5sYXN0Q2hhciArIDEgLSB0aGlzLmZpcnN0Q2hhcjsKICB9CiAgZm9yRWFjaChjYWxsYmFjaykgewogICAgZm9yIChsZXQgaSA9IHRoaXMuZmlyc3RDaGFyLCBpaSA9IHRoaXMubGFzdENoYXI7IGkgPD0gaWk7IGkrKykgewogICAgICBjYWxsYmFjayhpLCBpKTsKICAgIH0KICB9CiAgaGFzKGkpIHsKICAgIHJldHVybiB0aGlzLmZpcnN0Q2hhciA8PSBpICYmIGkgPD0gdGhpcy5sYXN0Q2hhcjsKICB9CiAgZ2V0KGkpIHsKICAgIGlmICh0aGlzLmZpcnN0Q2hhciA8PSBpICYmIGkgPD0gdGhpcy5sYXN0Q2hhcikgewogICAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShpKTsKICAgIH0KICAgIHJldHVybiB1bmRlZmluZWQ7CiAgfQogIGNoYXJDb2RlT2YodikgewogICAgcmV0dXJuIE51bWJlci5pc0ludGVnZXIodikgJiYgdiA+PSB0aGlzLmZpcnN0Q2hhciAmJiB2IDw9IHRoaXMubGFzdENoYXIgPyB2IDogLTE7CiAgfQogIGFtZW5kKG1hcCkgewogICAgdW5yZWFjaGFibGUoIlNob3VsZCBub3QgY2FsbCBhbWVuZCgpIik7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9jZmZfZm9udC5qcwoKCgpjbGFzcyBDRkZGb250IHsKICBjb25zdHJ1Y3RvcihmaWxlLCBwcm9wZXJ0aWVzKSB7CiAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzOwogICAgY29uc3QgcGFyc2VyID0gbmV3IENGRlBhcnNlcihmaWxlLCBwcm9wZXJ0aWVzLCBTRUFDX0FOQUxZU0lTX0VOQUJMRUQpOwogICAgdGhpcy5jZmYgPSBwYXJzZXIucGFyc2UoKTsKICAgIHRoaXMuY2ZmLmR1cGxpY2F0ZUZpcnN0R2x5cGgoKTsKICAgIGNvbnN0IGNvbXBpbGVyID0gbmV3IENGRkNvbXBpbGVyKHRoaXMuY2ZmKTsKICAgIHRoaXMuc2VhY3MgPSB0aGlzLmNmZi5zZWFjczsKICAgIHRyeSB7CiAgICAgIHRoaXMuZGF0YSA9IGNvbXBpbGVyLmNvbXBpbGUoKTsKICAgIH0gY2F0Y2ggewogICAgICB3YXJuKCJGYWlsZWQgdG8gY29tcGlsZSBmb250ICIgKyBwcm9wZXJ0aWVzLmxvYWRlZE5hbWUpOwogICAgICB0aGlzLmRhdGEgPSBmaWxlOwogICAgfQogICAgdGhpcy5fY3JlYXRlQnVpbHRJbkVuY29kaW5nKCk7CiAgfQogIGdldCBudW1HbHlwaHMoKSB7CiAgICByZXR1cm4gdGhpcy5jZmYuY2hhclN0cmluZ3MuY291bnQ7CiAgfQogIGdldENoYXJzZXQoKSB7CiAgICByZXR1cm4gdGhpcy5jZmYuY2hhcnNldC5jaGFyc2V0OwogIH0KICBnZXRHbHlwaE1hcHBpbmcoKSB7CiAgICBjb25zdCBjZmYgPSB0aGlzLmNmZjsKICAgIGNvbnN0IHByb3BlcnRpZXMgPSB0aGlzLnByb3BlcnRpZXM7CiAgICBjb25zdCB7CiAgICAgIGNpZFRvR2lkTWFwLAogICAgICBjTWFwCiAgICB9ID0gcHJvcGVydGllczsKICAgIGNvbnN0IGNoYXJzZXRzID0gY2ZmLmNoYXJzZXQuY2hhcnNldDsKICAgIGxldCBjaGFyQ29kZVRvR2x5cGhJZDsKICAgIGxldCBnbHlwaElkOwogICAgaWYgKHByb3BlcnRpZXMuY29tcG9zaXRlKSB7CiAgICAgIGxldCBpbnZDaWRUb0dpZE1hcDsKICAgICAgaWYgKGNpZFRvR2lkTWFwPy5sZW5ndGggPiAwKSB7CiAgICAgICAgaW52Q2lkVG9HaWRNYXAgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGNpZFRvR2lkTWFwLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgIGNvbnN0IGdpZCA9IGNpZFRvR2lkTWFwW2ldOwogICAgICAgICAgaWYgKGdpZCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGludkNpZFRvR2lkTWFwW2dpZF0gPSBpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBjaGFyQ29kZVRvR2x5cGhJZCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIGxldCBjaGFyQ29kZTsKICAgICAgaWYgKGNmZi5pc0NJREZvbnQpIHsKICAgICAgICBmb3IgKGdseXBoSWQgPSAwOyBnbHlwaElkIDwgY2hhcnNldHMubGVuZ3RoOyBnbHlwaElkKyspIHsKICAgICAgICAgIGNvbnN0IGNpZCA9IGNoYXJzZXRzW2dseXBoSWRdOwogICAgICAgICAgY2hhckNvZGUgPSBjTWFwLmNoYXJDb2RlT2YoY2lkKTsKICAgICAgICAgIGlmIChpbnZDaWRUb0dpZE1hcD8uW2NoYXJDb2RlXSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGNoYXJDb2RlID0gaW52Q2lkVG9HaWRNYXBbY2hhckNvZGVdOwogICAgICAgICAgfQogICAgICAgICAgY2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdID0gZ2x5cGhJZDsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yIChnbHlwaElkID0gMDsgZ2x5cGhJZCA8IGNmZi5jaGFyU3RyaW5ncy5jb3VudDsgZ2x5cGhJZCsrKSB7CiAgICAgICAgICBjaGFyQ29kZSA9IGNNYXAuY2hhckNvZGVPZihnbHlwaElkKTsKICAgICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IGdseXBoSWQ7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBjaGFyQ29kZVRvR2x5cGhJZDsKICAgIH0KICAgIGxldCBlbmNvZGluZyA9IGNmZi5lbmNvZGluZyA/IGNmZi5lbmNvZGluZy5lbmNvZGluZyA6IG51bGw7CiAgICBpZiAocHJvcGVydGllcy5pc0ludGVybmFsRm9udCkgewogICAgICBlbmNvZGluZyA9IHByb3BlcnRpZXMuZGVmYXVsdEVuY29kaW5nOwogICAgfQogICAgY2hhckNvZGVUb0dseXBoSWQgPSB0eXBlMUZvbnRHbHlwaE1hcHBpbmcocHJvcGVydGllcywgZW5jb2RpbmcsIGNoYXJzZXRzKTsKICAgIHJldHVybiBjaGFyQ29kZVRvR2x5cGhJZDsKICB9CiAgaGFzR2x5cGhJZChpZCkgewogICAgcmV0dXJuIHRoaXMuY2ZmLmhhc0dseXBoSWQoaWQpOwogIH0KICBfY3JlYXRlQnVpbHRJbkVuY29kaW5nKCkgewogICAgY29uc3QgewogICAgICBjaGFyc2V0LAogICAgICBlbmNvZGluZwogICAgfSA9IHRoaXMuY2ZmOwogICAgaWYgKCFjaGFyc2V0IHx8ICFlbmNvZGluZykgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBjaGFyc2V0cyA9IGNoYXJzZXQuY2hhcnNldCwKICAgICAgZW5jb2RpbmdzID0gZW5jb2RpbmcuZW5jb2Rpbmc7CiAgICBjb25zdCBtYXAgPSBbXTsKICAgIGZvciAoY29uc3QgY2hhckNvZGUgaW4gZW5jb2RpbmdzKSB7CiAgICAgIGNvbnN0IGdseXBoSWQgPSBlbmNvZGluZ3NbY2hhckNvZGVdOwogICAgICBpZiAoZ2x5cGhJZCA+PSAwKSB7CiAgICAgICAgY29uc3QgZ2x5cGhOYW1lID0gY2hhcnNldHNbZ2x5cGhJZF07CiAgICAgICAgaWYgKGdseXBoTmFtZSkgewogICAgICAgICAgbWFwW2NoYXJDb2RlXSA9IGdseXBoTmFtZTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChtYXAubGVuZ3RoID4gMCkgewogICAgICB0aGlzLnByb3BlcnRpZXMuYnVpbHRJbkVuY29kaW5nID0gbWFwOwogICAgfQogIH0KfQoKOy8vIC4vc3JjL2NvcmUvZm9udF9yZW5kZXJlci5qcwoKCgoKCgoKCgoKCgoKCgoKZnVuY3Rpb24gZ2V0RmxvYXQyMTQoZGF0YSwgb2Zmc2V0KSB7CiAgcmV0dXJuIHJlYWRJbnQxNihkYXRhLCBvZmZzZXQpIC8gMTYzODQ7Cn0KZnVuY3Rpb24gZ2V0U3Vicm91dGluZUJpYXMoc3VicnMpIHsKICBjb25zdCBudW1TdWJycyA9IHN1YnJzLmxlbmd0aDsKICBsZXQgYmlhcyA9IDMyNzY4OwogIGlmIChudW1TdWJycyA8IDEyNDApIHsKICAgIGJpYXMgPSAxMDc7CiAgfSBlbHNlIGlmIChudW1TdWJycyA8IDMzOTAwKSB7CiAgICBiaWFzID0gMTEzMTsKICB9CiAgcmV0dXJuIGJpYXM7Cn0KZnVuY3Rpb24gcGFyc2VDbWFwKGRhdGEsIHN0YXJ0LCBlbmQpIHsKICBjb25zdCBvZmZzZXQgPSByZWFkVWludDE2KGRhdGEsIHN0YXJ0ICsgMikgPT09IDEgPyByZWFkVWludDMyKGRhdGEsIHN0YXJ0ICsgOCkgOiByZWFkVWludDMyKGRhdGEsIHN0YXJ0ICsgMTYpOwogIGNvbnN0IGZvcm1hdCA9IHJlYWRVaW50MTYoZGF0YSwgc3RhcnQgKyBvZmZzZXQpOwogIGxldCByYW5nZXMsIHAsIGk7CiAgaWYgKGZvcm1hdCA9PT0gNCkgewogICAgcmVhZFVpbnQxNihkYXRhLCBzdGFydCArIG9mZnNldCArIDIpOwogICAgY29uc3Qgc2VnQ291bnQgPSByZWFkVWludDE2KGRhdGEsIHN0YXJ0ICsgb2Zmc2V0ICsgNikgPj4gMTsKICAgIHAgPSBzdGFydCArIG9mZnNldCArIDE0OwogICAgcmFuZ2VzID0gW107CiAgICBmb3IgKGkgPSAwOyBpIDwgc2VnQ291bnQ7IGkrKywgcCArPSAyKSB7CiAgICAgIHJhbmdlc1tpXSA9IHsKICAgICAgICBlbmQ6IHJlYWRVaW50MTYoZGF0YSwgcCkKICAgICAgfTsKICAgIH0KICAgIHAgKz0gMjsKICAgIGZvciAoaSA9IDA7IGkgPCBzZWdDb3VudDsgaSsrLCBwICs9IDIpIHsKICAgICAgcmFuZ2VzW2ldLnN0YXJ0ID0gcmVhZFVpbnQxNihkYXRhLCBwKTsKICAgIH0KICAgIGZvciAoaSA9IDA7IGkgPCBzZWdDb3VudDsgaSsrLCBwICs9IDIpIHsKICAgICAgcmFuZ2VzW2ldLmlkRGVsdGEgPSByZWFkVWludDE2KGRhdGEsIHApOwogICAgfQogICAgZm9yIChpID0gMDsgaSA8IHNlZ0NvdW50OyBpKyssIHAgKz0gMikgewogICAgICBsZXQgaWRPZmZzZXQgPSByZWFkVWludDE2KGRhdGEsIHApOwogICAgICBpZiAoaWRPZmZzZXQgPT09IDApIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICByYW5nZXNbaV0uaWRzID0gW107CiAgICAgIGZvciAobGV0IGogPSAwLCBqaiA9IHJhbmdlc1tpXS5lbmQgLSByYW5nZXNbaV0uc3RhcnQgKyAxOyBqIDwgamo7IGorKykgewogICAgICAgIHJhbmdlc1tpXS5pZHNbal0gPSByZWFkVWludDE2KGRhdGEsIHAgKyBpZE9mZnNldCk7CiAgICAgICAgaWRPZmZzZXQgKz0gMjsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHJhbmdlczsKICB9IGVsc2UgaWYgKGZvcm1hdCA9PT0gMTIpIHsKICAgIGNvbnN0IGdyb3VwcyA9IHJlYWRVaW50MzIoZGF0YSwgc3RhcnQgKyBvZmZzZXQgKyAxMik7CiAgICBwID0gc3RhcnQgKyBvZmZzZXQgKyAxNjsKICAgIHJhbmdlcyA9IFtdOwogICAgZm9yIChpID0gMDsgaSA8IGdyb3VwczsgaSsrKSB7CiAgICAgIHN0YXJ0ID0gcmVhZFVpbnQzMihkYXRhLCBwKTsKICAgICAgcmFuZ2VzLnB1c2goewogICAgICAgIHN0YXJ0LAogICAgICAgIGVuZDogcmVhZFVpbnQzMihkYXRhLCBwICsgNCksCiAgICAgICAgaWREZWx0YTogcmVhZFVpbnQzMihkYXRhLCBwICsgOCkgLSBzdGFydAogICAgICB9KTsKICAgICAgcCArPSAxMjsKICAgIH0KICAgIHJldHVybiByYW5nZXM7CiAgfQogIHRocm93IG5ldyBGb3JtYXRFcnJvcihgdW5zdXBwb3J0ZWQgY21hcDogJHtmb3JtYXR9YCk7Cn0KZnVuY3Rpb24gcGFyc2VDZmYoZGF0YSwgc3RhcnQsIGVuZCwgc2VhY0FuYWx5c2lzRW5hYmxlZCkgewogIGNvbnN0IHByb3BlcnRpZXMgPSB7fTsKICBjb25zdCBwYXJzZXIgPSBuZXcgQ0ZGUGFyc2VyKG5ldyBTdHJlYW0oZGF0YSwgc3RhcnQsIGVuZCAtIHN0YXJ0KSwgcHJvcGVydGllcywgc2VhY0FuYWx5c2lzRW5hYmxlZCk7CiAgY29uc3QgY2ZmID0gcGFyc2VyLnBhcnNlKCk7CiAgcmV0dXJuIHsKICAgIGdseXBoczogY2ZmLmNoYXJTdHJpbmdzLm9iamVjdHMsCiAgICBzdWJyczogY2ZmLnRvcERpY3QucHJpdmF0ZURpY3Q/LnN1YnJzSW5kZXg/Lm9iamVjdHMsCiAgICBnc3VicnM6IGNmZi5nbG9iYWxTdWJySW5kZXg/Lm9iamVjdHMsCiAgICBpc0NGRkNJREZvbnQ6IGNmZi5pc0NJREZvbnQsCiAgICBmZFNlbGVjdDogY2ZmLmZkU2VsZWN0LAogICAgZmRBcnJheTogY2ZmLmZkQXJyYXkKICB9Owp9CmZ1bmN0aW9uIHBhcnNlR2x5ZlRhYmxlKGdseWYsIGxvY2EsIGlzR2x5cGhMb2NhdGlvbnNMb25nKSB7CiAgbGV0IGl0ZW1TaXplLCBpdGVtRGVjb2RlOwogIGlmIChpc0dseXBoTG9jYXRpb25zTG9uZykgewogICAgaXRlbVNpemUgPSA0OwogICAgaXRlbURlY29kZSA9IHJlYWRVaW50MzI7CiAgfSBlbHNlIHsKICAgIGl0ZW1TaXplID0gMjsKICAgIGl0ZW1EZWNvZGUgPSAoZGF0YSwgb2Zmc2V0KSA9PiAyICogcmVhZFVpbnQxNihkYXRhLCBvZmZzZXQpOwogIH0KICBjb25zdCBnbHlwaHMgPSBbXTsKICBsZXQgc3RhcnRPZmZzZXQgPSBpdGVtRGVjb2RlKGxvY2EsIDApOwogIGZvciAobGV0IGogPSBpdGVtU2l6ZTsgaiA8IGxvY2EubGVuZ3RoOyBqICs9IGl0ZW1TaXplKSB7CiAgICBjb25zdCBlbmRPZmZzZXQgPSBpdGVtRGVjb2RlKGxvY2EsIGopOwogICAgZ2x5cGhzLnB1c2goZ2x5Zi5zdWJhcnJheShzdGFydE9mZnNldCwgZW5kT2Zmc2V0KSk7CiAgICBzdGFydE9mZnNldCA9IGVuZE9mZnNldDsKICB9CiAgcmV0dXJuIGdseXBoczsKfQpmdW5jdGlvbiBsb29rdXBDbWFwKHJhbmdlcywgdW5pY29kZSkgewogIGNvbnN0IGNvZGUgPSB1bmljb2RlLmNvZGVQb2ludEF0KDApOwogIGxldCBnaWQgPSAwLAogICAgbCA9IDAsCiAgICByID0gcmFuZ2VzLmxlbmd0aCAtIDE7CiAgd2hpbGUgKGwgPCByKSB7CiAgICBjb25zdCBjID0gbCArIHIgKyAxID4+IDE7CiAgICBpZiAoY29kZSA8IHJhbmdlc1tjXS5zdGFydCkgewogICAgICByID0gYyAtIDE7CiAgICB9IGVsc2UgewogICAgICBsID0gYzsKICAgIH0KICB9CiAgaWYgKHJhbmdlc1tsXS5zdGFydCA8PSBjb2RlICYmIGNvZGUgPD0gcmFuZ2VzW2xdLmVuZCkgewogICAgZ2lkID0gcmFuZ2VzW2xdLmlkRGVsdGEgKyAocmFuZ2VzW2xdLmlkcyA/IHJhbmdlc1tsXS5pZHNbY29kZSAtIHJhbmdlc1tsXS5zdGFydF0gOiBjb2RlKSAmIDB4ZmZmZjsKICB9CiAgcmV0dXJuIHsKICAgIGNoYXJDb2RlOiBjb2RlLAogICAgZ2x5cGhJZDogZ2lkCiAgfTsKfQpmdW5jdGlvbiBjb21waWxlR2x5Zihjb2RlLCBjbWRzLCBmb250KSB7CiAgZnVuY3Rpb24gbW92ZVRvKHgsIHkpIHsKICAgIGlmIChmaXJzdFBvaW50KSB7CiAgICAgIGNtZHMuYWRkKCJMIiwgZmlyc3RQb2ludCk7CiAgICB9CiAgICBmaXJzdFBvaW50ID0gW3gsIHldOwogICAgY21kcy5hZGQoIk0iLCBbeCwgeV0pOwogIH0KICBmdW5jdGlvbiBsaW5lVG8oeCwgeSkgewogICAgY21kcy5hZGQoIkwiLCBbeCwgeV0pOwogIH0KICBmdW5jdGlvbiBxdWFkcmF0aWNDdXJ2ZVRvKHhhLCB5YSwgeCwgeSkgewogICAgY21kcy5hZGQoIlEiLCBbeGEsIHlhLCB4LCB5XSk7CiAgfQogIGxldCBpID0gMDsKICBjb25zdCBudW1iZXJPZkNvbnRvdXJzID0gcmVhZEludDE2KGNvZGUsIGkpOwogIGxldCBmbGFnczsKICBsZXQgZmlyc3RQb2ludCA9IG51bGw7CiAgbGV0IHggPSAwLAogICAgeSA9IDA7CiAgaSArPSAxMDsKICBpZiAobnVtYmVyT2ZDb250b3VycyA8IDApIHsKICAgIGRvIHsKICAgICAgZmxhZ3MgPSByZWFkVWludDE2KGNvZGUsIGkpOwogICAgICBjb25zdCBnbHlwaEluZGV4ID0gcmVhZFVpbnQxNihjb2RlLCBpICsgMik7CiAgICAgIGkgKz0gNDsKICAgICAgbGV0IGFyZzEsIGFyZzI7CiAgICAgIGlmIChmbGFncyAmIDB4MDEpIHsKICAgICAgICBpZiAoZmxhZ3MgJiAweDAyKSB7CiAgICAgICAgICBhcmcxID0gcmVhZEludDE2KGNvZGUsIGkpOwogICAgICAgICAgYXJnMiA9IHJlYWRJbnQxNihjb2RlLCBpICsgMik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGFyZzEgPSByZWFkVWludDE2KGNvZGUsIGkpOwogICAgICAgICAgYXJnMiA9IHJlYWRVaW50MTYoY29kZSwgaSArIDIpOwogICAgICAgIH0KICAgICAgICBpICs9IDQ7CiAgICAgIH0gZWxzZSBpZiAoZmxhZ3MgJiAweDAyKSB7CiAgICAgICAgYXJnMSA9IHJlYWRJbnQ4KGNvZGUsIGkrKyk7CiAgICAgICAgYXJnMiA9IHJlYWRJbnQ4KGNvZGUsIGkrKyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYXJnMSA9IGNvZGVbaSsrXTsKICAgICAgICBhcmcyID0gY29kZVtpKytdOwogICAgICB9CiAgICAgIGlmIChmbGFncyAmIDB4MDIpIHsKICAgICAgICB4ID0gYXJnMTsKICAgICAgICB5ID0gYXJnMjsKICAgICAgfSBlbHNlIHsKICAgICAgICB4ID0gMDsKICAgICAgICB5ID0gMDsKICAgICAgfQogICAgICBsZXQgc2NhbGVYID0gMSwKICAgICAgICBzY2FsZVkgPSAxLAogICAgICAgIHNjYWxlMDEgPSAwLAogICAgICAgIHNjYWxlMTAgPSAwOwogICAgICBpZiAoZmxhZ3MgJiAweDA4KSB7CiAgICAgICAgc2NhbGVYID0gc2NhbGVZID0gZ2V0RmxvYXQyMTQoY29kZSwgaSk7CiAgICAgICAgaSArPSAyOwogICAgICB9IGVsc2UgaWYgKGZsYWdzICYgMHg0MCkgewogICAgICAgIHNjYWxlWCA9IGdldEZsb2F0MjE0KGNvZGUsIGkpOwogICAgICAgIHNjYWxlWSA9IGdldEZsb2F0MjE0KGNvZGUsIGkgKyAyKTsKICAgICAgICBpICs9IDQ7CiAgICAgIH0gZWxzZSBpZiAoZmxhZ3MgJiAweDgwKSB7CiAgICAgICAgc2NhbGVYID0gZ2V0RmxvYXQyMTQoY29kZSwgaSk7CiAgICAgICAgc2NhbGUwMSA9IGdldEZsb2F0MjE0KGNvZGUsIGkgKyAyKTsKICAgICAgICBzY2FsZTEwID0gZ2V0RmxvYXQyMTQoY29kZSwgaSArIDQpOwogICAgICAgIHNjYWxlWSA9IGdldEZsb2F0MjE0KGNvZGUsIGkgKyA2KTsKICAgICAgICBpICs9IDg7CiAgICAgIH0KICAgICAgY29uc3Qgc3ViZ2x5cGggPSBmb250LmdseXBoc1tnbHlwaEluZGV4XTsKICAgICAgaWYgKHN1YmdseXBoKSB7CiAgICAgICAgY21kcy5zYXZlKCk7CiAgICAgICAgY21kcy50cmFuc2Zvcm0oW3NjYWxlWCwgc2NhbGUwMSwgc2NhbGUxMCwgc2NhbGVZLCB4LCB5XSk7CiAgICAgICAgaWYgKCEoZmxhZ3MgJiAweDAyKSkge30KICAgICAgICBjb21waWxlR2x5ZihzdWJnbHlwaCwgY21kcywgZm9udCk7CiAgICAgICAgY21kcy5yZXN0b3JlKCk7CiAgICAgIH0KICAgIH0gd2hpbGUgKGZsYWdzICYgMHgyMCk7CiAgfSBlbHNlIHsKICAgIGNvbnN0IGVuZFB0c09mQ29udG91cnMgPSBbXTsKICAgIGxldCBqLCBqajsKICAgIGZvciAoaiA9IDA7IGogPCBudW1iZXJPZkNvbnRvdXJzOyBqKyspIHsKICAgICAgZW5kUHRzT2ZDb250b3Vycy5wdXNoKHJlYWRVaW50MTYoY29kZSwgaSkpOwogICAgICBpICs9IDI7CiAgICB9CiAgICBjb25zdCBpbnN0cnVjdGlvbkxlbmd0aCA9IHJlYWRVaW50MTYoY29kZSwgaSk7CiAgICBpICs9IDIgKyBpbnN0cnVjdGlvbkxlbmd0aDsKICAgIGNvbnN0IG51bWJlck9mUG9pbnRzID0gZW5kUHRzT2ZDb250b3Vycy5hdCgtMSkgKyAxOwogICAgY29uc3QgcG9pbnRzID0gW107CiAgICB3aGlsZSAocG9pbnRzLmxlbmd0aCA8IG51bWJlck9mUG9pbnRzKSB7CiAgICAgIGZsYWdzID0gY29kZVtpKytdOwogICAgICBsZXQgcmVwZWF0ID0gMTsKICAgICAgaWYgKGZsYWdzICYgMHgwOCkgewogICAgICAgIHJlcGVhdCArPSBjb2RlW2krK107CiAgICAgIH0KICAgICAgd2hpbGUgKHJlcGVhdC0tID4gMCkgewogICAgICAgIHBvaW50cy5wdXNoKHsKICAgICAgICAgIGZsYWdzCiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIGZvciAoaiA9IDA7IGogPCBudW1iZXJPZlBvaW50czsgaisrKSB7CiAgICAgIHN3aXRjaCAocG9pbnRzW2pdLmZsYWdzICYgMHgxMikgewogICAgICAgIGNhc2UgMHgwMDoKICAgICAgICAgIHggKz0gcmVhZEludDE2KGNvZGUsIGkpOwogICAgICAgICAgaSArPSAyOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweDAyOgogICAgICAgICAgeCAtPSBjb2RlW2krK107CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4MTI6CiAgICAgICAgICB4ICs9IGNvZGVbaSsrXTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIHBvaW50c1tqXS54ID0geDsKICAgIH0KICAgIGZvciAoaiA9IDA7IGogPCBudW1iZXJPZlBvaW50czsgaisrKSB7CiAgICAgIHN3aXRjaCAocG9pbnRzW2pdLmZsYWdzICYgMHgyNCkgewogICAgICAgIGNhc2UgMHgwMDoKICAgICAgICAgIHkgKz0gcmVhZEludDE2KGNvZGUsIGkpOwogICAgICAgICAgaSArPSAyOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAweDA0OgogICAgICAgICAgeSAtPSBjb2RlW2krK107CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4MjQ6CiAgICAgICAgICB5ICs9IGNvZGVbaSsrXTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIHBvaW50c1tqXS55ID0geTsKICAgIH0KICAgIGxldCBzdGFydFBvaW50ID0gMDsKICAgIGZvciAoaSA9IDA7IGkgPCBudW1iZXJPZkNvbnRvdXJzOyBpKyspIHsKICAgICAgY29uc3QgZW5kUG9pbnQgPSBlbmRQdHNPZkNvbnRvdXJzW2ldOwogICAgICBjb25zdCBjb250b3VyID0gcG9pbnRzLnNsaWNlKHN0YXJ0UG9pbnQsIGVuZFBvaW50ICsgMSk7CiAgICAgIGlmIChjb250b3VyWzBdLmZsYWdzICYgMSkgewogICAgICAgIGNvbnRvdXIucHVzaChjb250b3VyWzBdKTsKICAgICAgfSBlbHNlIGlmIChjb250b3VyLmF0KC0xKS5mbGFncyAmIDEpIHsKICAgICAgICBjb250b3VyLnVuc2hpZnQoY29udG91ci5hdCgtMSkpOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IHAgPSB7CiAgICAgICAgICBmbGFnczogMSwKICAgICAgICAgIHg6IChjb250b3VyWzBdLnggKyBjb250b3VyLmF0KC0xKS54KSAvIDIsCiAgICAgICAgICB5OiAoY29udG91clswXS55ICsgY29udG91ci5hdCgtMSkueSkgLyAyCiAgICAgICAgfTsKICAgICAgICBjb250b3VyLnVuc2hpZnQocCk7CiAgICAgICAgY29udG91ci5wdXNoKHApOwogICAgICB9CiAgICAgIG1vdmVUbyhjb250b3VyWzBdLngsIGNvbnRvdXJbMF0ueSk7CiAgICAgIGZvciAoaiA9IDEsIGpqID0gY29udG91ci5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgICAgaWYgKGNvbnRvdXJbal0uZmxhZ3MgJiAxKSB7CiAgICAgICAgICBsaW5lVG8oY29udG91cltqXS54LCBjb250b3VyW2pdLnkpOwogICAgICAgIH0gZWxzZSBpZiAoY29udG91cltqICsgMV0uZmxhZ3MgJiAxKSB7CiAgICAgICAgICBxdWFkcmF0aWNDdXJ2ZVRvKGNvbnRvdXJbal0ueCwgY29udG91cltqXS55LCBjb250b3VyW2ogKyAxXS54LCBjb250b3VyW2ogKyAxXS55KTsKICAgICAgICAgIGorKzsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcXVhZHJhdGljQ3VydmVUbyhjb250b3VyW2pdLngsIGNvbnRvdXJbal0ueSwgKGNvbnRvdXJbal0ueCArIGNvbnRvdXJbaiArIDFdLngpIC8gMiwgKGNvbnRvdXJbal0ueSArIGNvbnRvdXJbaiArIDFdLnkpIC8gMik7CiAgICAgICAgfQogICAgICB9CiAgICAgIHN0YXJ0UG9pbnQgPSBlbmRQb2ludCArIDE7CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGNvbXBpbGVDaGFyU3RyaW5nKGNoYXJTdHJpbmdDb2RlLCBjbWRzLCBmb250LCBnbHlwaElkKSB7CiAgZnVuY3Rpb24gbW92ZVRvKHgsIHkpIHsKICAgIGlmIChmaXJzdFBvaW50KSB7CiAgICAgIGNtZHMuYWRkKCJMIiwgZmlyc3RQb2ludCk7CiAgICB9CiAgICBmaXJzdFBvaW50ID0gW3gsIHldOwogICAgY21kcy5hZGQoIk0iLCBbeCwgeV0pOwogIH0KICBmdW5jdGlvbiBsaW5lVG8oeCwgeSkgewogICAgY21kcy5hZGQoIkwiLCBbeCwgeV0pOwogIH0KICBmdW5jdGlvbiBiZXppZXJDdXJ2ZVRvKHgxLCB5MSwgeDIsIHkyLCB4LCB5KSB7CiAgICBjbWRzLmFkZCgiQyIsIFt4MSwgeTEsIHgyLCB5MiwgeCwgeV0pOwogIH0KICBjb25zdCBzdGFjayA9IFtdOwogIGxldCB4ID0gMCwKICAgIHkgPSAwOwogIGxldCBzdGVtcyA9IDA7CiAgbGV0IGZpcnN0UG9pbnQgPSBudWxsOwogIGZ1bmN0aW9uIHBhcnNlKGNvZGUpIHsKICAgIGxldCBpID0gMDsKICAgIHdoaWxlIChpIDwgY29kZS5sZW5ndGgpIHsKICAgICAgbGV0IHN0YWNrQ2xlYW4gPSBmYWxzZTsKICAgICAgbGV0IHYgPSBjb2RlW2krK107CiAgICAgIGxldCB4YSwgeGIsIHlhLCB5YiwgeTEsIHkyLCB5Mywgbiwgc3VickNvZGU7CiAgICAgIHN3aXRjaCAodikgewogICAgICAgIGNhc2UgMToKICAgICAgICAgIHN0ZW1zICs9IHN0YWNrLmxlbmd0aCA+PiAxOwogICAgICAgICAgc3RhY2tDbGVhbiA9IHRydWU7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDM6CiAgICAgICAgICBzdGVtcyArPSBzdGFjay5sZW5ndGggPj4gMTsKICAgICAgICAgIHN0YWNrQ2xlYW4gPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA0OgogICAgICAgICAgeSArPSBzdGFjay5wb3AoKTsKICAgICAgICAgIG1vdmVUbyh4LCB5KTsKICAgICAgICAgIHN0YWNrQ2xlYW4gPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA1OgogICAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgeCArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIGxpbmVUbyh4LCB5KTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgNjoKICAgICAgICAgIHdoaWxlIChzdGFjay5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIHggKz0gc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgbGluZVRvKHgsIHkpOwogICAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoID09PSAwKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgeSArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICBsaW5lVG8oeCwgeSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDc6CiAgICAgICAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkgewogICAgICAgICAgICB5ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIGxpbmVUbyh4LCB5KTsKICAgICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHggKz0gc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgbGluZVRvKHgsIHkpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSA4OgogICAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgeGEgPSB4ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeWEgPSB5ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHliID0geWEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB4ID0geGIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5ID0geWIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTA6CiAgICAgICAgICBuID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdWJyQ29kZSA9IG51bGw7CiAgICAgICAgICBpZiAoZm9udC5pc0NGRkNJREZvbnQpIHsKICAgICAgICAgICAgY29uc3QgZmRJbmRleCA9IGZvbnQuZmRTZWxlY3QuZ2V0RkRJbmRleChnbHlwaElkKTsKICAgICAgICAgICAgaWYgKGZkSW5kZXggPj0gMCAmJiBmZEluZGV4IDwgZm9udC5mZEFycmF5Lmxlbmd0aCkgewogICAgICAgICAgICAgIGNvbnN0IGZvbnREaWN0ID0gZm9udC5mZEFycmF5W2ZkSW5kZXhdOwogICAgICAgICAgICAgIGxldCBzdWJyczsKICAgICAgICAgICAgICBpZiAoZm9udERpY3QucHJpdmF0ZURpY3Q/LnN1YnJzSW5kZXgpIHsKICAgICAgICAgICAgICAgIHN1YnJzID0gZm9udERpY3QucHJpdmF0ZURpY3Quc3VicnNJbmRleC5vYmplY3RzOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoc3VicnMpIHsKICAgICAgICAgICAgICAgIG4gKz0gZ2V0U3Vicm91dGluZUJpYXMoc3VicnMpOwogICAgICAgICAgICAgICAgc3VickNvZGUgPSBzdWJyc1tuXTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgd2FybigiSW52YWxpZCBmZCBpbmRleCBmb3IgZ2x5cGggaW5kZXguIik7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN1YnJDb2RlID0gZm9udC5zdWJyc1tuICsgZm9udC5zdWJyc0JpYXNdOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHN1YnJDb2RlKSB7CiAgICAgICAgICAgIHBhcnNlKHN1YnJDb2RlKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTE6CiAgICAgICAgICByZXR1cm47CiAgICAgICAgY2FzZSAxMjoKICAgICAgICAgIHYgPSBjb2RlW2krK107CiAgICAgICAgICBzd2l0Y2ggKHYpIHsKICAgICAgICAgICAgY2FzZSAzNDoKICAgICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHkxID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5LCB4YiwgeTEsIHgsIHkxKTsKICAgICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeTEsIHhiLCB5LCB4LCB5KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAzNToKICAgICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHlhID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeWIgPSB5YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB5ID0geWIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIGJlemllckN1cnZlVG8oeGEsIHlhLCB4YiwgeWIsIHgsIHkpOwogICAgICAgICAgICAgIHhhID0geCArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeWEgPSB5ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB4YiA9IHhhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB4ID0geGIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHkgPSB5YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICAgICAgc3RhY2sucG9wKCk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMzY6CiAgICAgICAgICAgICAgeGEgPSB4ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB5MSA9IHkgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHkyID0geTEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeTEsIHhiLCB5MiwgeCwgeTIpOwogICAgICAgICAgICAgIHhhID0geCArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeTMgPSB5MiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5MiwgeGIsIHkzLCB4LCB5KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAzNzoKICAgICAgICAgICAgICBjb25zdCB4MCA9IHgsCiAgICAgICAgICAgICAgICB5MCA9IHk7CiAgICAgICAgICAgICAgeGEgPSB4ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB5YSA9IHkgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHliID0geWEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeSA9IHliICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIHlhID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeWIgPSB5YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgICAgeCA9IHhiOwogICAgICAgICAgICAgIHkgPSB5YjsKICAgICAgICAgICAgICBpZiAoTWF0aC5hYnMoeCAtIHgwKSA+IE1hdGguYWJzKHkgLSB5MCkpIHsKICAgICAgICAgICAgICAgIHggKz0gc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgeSArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYHVua25vd24gb3BlcmF0b3I6IDEyICR7dn1gKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTQ6CiAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoID49IDQpIHsKICAgICAgICAgICAgY29uc3QgYWNoYXIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgICAgY29uc3QgYmNoYXIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgICAgeSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgICB4ID0gc3RhY2sucG9wKCk7CiAgICAgICAgICAgIGNtZHMuc2F2ZSgpOwogICAgICAgICAgICBjbWRzLnRyYW5zbGF0ZSh4LCB5KTsKICAgICAgICAgICAgbGV0IGNtYXAgPSBsb29rdXBDbWFwKGZvbnQuY21hcCwgU3RyaW5nLmZyb21DaGFyQ29kZShmb250LmdseXBoTmFtZU1hcFtTdGFuZGFyZEVuY29kaW5nW2FjaGFyXV0pKTsKICAgICAgICAgICAgY29tcGlsZUNoYXJTdHJpbmcoZm9udC5nbHlwaHNbY21hcC5nbHlwaElkXSwgY21kcywgZm9udCwgY21hcC5nbHlwaElkKTsKICAgICAgICAgICAgY21kcy5yZXN0b3JlKCk7CiAgICAgICAgICAgIGNtYXAgPSBsb29rdXBDbWFwKGZvbnQuY21hcCwgU3RyaW5nLmZyb21DaGFyQ29kZShmb250LmdseXBoTmFtZU1hcFtTdGFuZGFyZEVuY29kaW5nW2JjaGFyXV0pKTsKICAgICAgICAgICAgY29tcGlsZUNoYXJTdHJpbmcoZm9udC5nbHlwaHNbY21hcC5nbHlwaElkXSwgY21kcywgZm9udCwgY21hcC5nbHlwaElkKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybjsKICAgICAgICBjYXNlIDE4OgogICAgICAgICAgc3RlbXMgKz0gc3RhY2subGVuZ3RoID4+IDE7CiAgICAgICAgICBzdGFja0NsZWFuID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTk6CiAgICAgICAgICBzdGVtcyArPSBzdGFjay5sZW5ndGggPj4gMTsKICAgICAgICAgIGkgKz0gc3RlbXMgKyA3ID4+IDM7CiAgICAgICAgICBzdGFja0NsZWFuID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjA6CiAgICAgICAgICBzdGVtcyArPSBzdGFjay5sZW5ndGggPj4gMTsKICAgICAgICAgIGkgKz0gc3RlbXMgKyA3ID4+IDM7CiAgICAgICAgICBzdGFja0NsZWFuID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjE6CiAgICAgICAgICB5ICs9IHN0YWNrLnBvcCgpOwogICAgICAgICAgeCArPSBzdGFjay5wb3AoKTsKICAgICAgICAgIG1vdmVUbyh4LCB5KTsKICAgICAgICAgIHN0YWNrQ2xlYW4gPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyMjoKICAgICAgICAgIHggKz0gc3RhY2sucG9wKCk7CiAgICAgICAgICBtb3ZlVG8oeCwgeSk7CiAgICAgICAgICBzdGFja0NsZWFuID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMjM6CiAgICAgICAgICBzdGVtcyArPSBzdGFjay5sZW5ndGggPj4gMTsKICAgICAgICAgIHN0YWNrQ2xlYW4gPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyNDoKICAgICAgICAgIHdoaWxlIChzdGFjay5sZW5ndGggPiAyKSB7CiAgICAgICAgICAgIHhhID0geCArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHlhID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeSA9IHliICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICB9CiAgICAgICAgICB4ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICB5ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICBsaW5lVG8oeCwgeSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI1OgogICAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDYpIHsKICAgICAgICAgICAgeCArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5ICs9IHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIGxpbmVUbyh4LCB5KTsKICAgICAgICAgIH0KICAgICAgICAgIHhhID0geCArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICB5YSA9IHkgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICB5ID0geWIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI2OgogICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCAlIDIpIHsKICAgICAgICAgICAgeCArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgfQogICAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgeGEgPSB4OwogICAgICAgICAgICB5YSA9IHkgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB4YiA9IHhhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeWIgPSB5YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHggPSB4YjsKICAgICAgICAgICAgeSA9IHliICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI3OgogICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCAlIDIpIHsKICAgICAgICAgICAgeSArPSBzdGFjay5zaGlmdCgpOwogICAgICAgICAgfQogICAgICAgICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgeGEgPSB4ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeWEgPSB5OwogICAgICAgICAgICB4YiA9IHhhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeWIgPSB5YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHggPSB4YiArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHkgPSB5YjsKICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI4OgogICAgICAgICAgc3RhY2sucHVzaChyZWFkSW50MTYoY29kZSwgaSkpOwogICAgICAgICAgaSArPSAyOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyOToKICAgICAgICAgIG4gPSBzdGFjay5wb3AoKSArIGZvbnQuZ3N1YnJzQmlhczsKICAgICAgICAgIHN1YnJDb2RlID0gZm9udC5nc3VicnNbbl07CiAgICAgICAgICBpZiAoc3VickNvZGUpIHsKICAgICAgICAgICAgcGFyc2Uoc3VickNvZGUpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAzMDoKICAgICAgICAgIHdoaWxlIChzdGFjay5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIHhhID0geDsKICAgICAgICAgICAgeWEgPSB5ICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHliID0geWEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB4ID0geGIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5ID0geWIgKyAoc3RhY2subGVuZ3RoID09PSAxID8gc3RhY2suc2hpZnQoKSA6IDApOwogICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHhhID0geCArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHlhID0geTsKICAgICAgICAgICAgeGIgPSB4YSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHliID0geWEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5ID0geWIgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB4ID0geGIgKyAoc3RhY2subGVuZ3RoID09PSAxID8gc3RhY2suc2hpZnQoKSA6IDApOwogICAgICAgICAgICBiZXppZXJDdXJ2ZVRvKHhhLCB5YSwgeGIsIHliLCB4LCB5KTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMzE6CiAgICAgICAgICB3aGlsZSAoc3RhY2subGVuZ3RoID4gMCkgewogICAgICAgICAgICB4YSA9IHggKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YSA9IHk7CiAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeSA9IHliICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeCA9IHhiICsgKHN0YWNrLmxlbmd0aCA9PT0gMSA/IHN0YWNrLnNoaWZ0KCkgOiAwKTsKICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICB4YSA9IHg7CiAgICAgICAgICAgIHlhID0geSArIHN0YWNrLnNoaWZ0KCk7CiAgICAgICAgICAgIHhiID0geGEgKyBzdGFjay5zaGlmdCgpOwogICAgICAgICAgICB5YiA9IHlhICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeCA9IHhiICsgc3RhY2suc2hpZnQoKTsKICAgICAgICAgICAgeSA9IHliICsgKHN0YWNrLmxlbmd0aCA9PT0gMSA/IHN0YWNrLnNoaWZ0KCkgOiAwKTsKICAgICAgICAgICAgYmV6aWVyQ3VydmVUbyh4YSwgeWEsIHhiLCB5YiwgeCwgeSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgaWYgKHYgPCAzMikgewogICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYHVua25vd24gb3BlcmF0b3I6ICR7dn1gKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2IDwgMjQ3KSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2godiAtIDEzOSk7CiAgICAgICAgICB9IGVsc2UgaWYgKHYgPCAyNTEpIHsKICAgICAgICAgICAgc3RhY2sucHVzaCgodiAtIDI0NykgKiAyNTYgKyBjb2RlW2krK10gKyAxMDgpOwogICAgICAgICAgfSBlbHNlIGlmICh2IDwgMjU1KSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goLSh2IC0gMjUxKSAqIDI1NiAtIGNvZGVbaSsrXSAtIDEwOCk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdGFjay5wdXNoKChjb2RlW2ldIDw8IDI0IHwgY29kZVtpICsgMV0gPDwgMTYgfCBjb2RlW2kgKyAyXSA8PCA4IHwgY29kZVtpICsgM10pIC8gNjU1MzYpOwogICAgICAgICAgICBpICs9IDQ7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpZiAoc3RhY2tDbGVhbikgewogICAgICAgIHN0YWNrLmxlbmd0aCA9IDA7CiAgICAgIH0KICAgIH0KICB9CiAgcGFyc2UoY2hhclN0cmluZ0NvZGUpOwp9CmNvbnN0IE5PT1AgPSAiIjsKY2xhc3MgQ29tbWFuZHMgewogIGNtZHMgPSBbXTsKICB0cmFuc2Zvcm1TdGFjayA9IFtdOwogIGN1cnJlbnRUcmFuc2Zvcm0gPSBbMSwgMCwgMCwgMSwgMCwgMF07CiAgYWRkKGNtZCwgYXJncykgewogICAgaWYgKGFyZ3MpIHsKICAgICAgY29uc3QgewogICAgICAgIGN1cnJlbnRUcmFuc2Zvcm0KICAgICAgfSA9IHRoaXM7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGFyZ3MubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICAgIFV0aWwuYXBwbHlUcmFuc2Zvcm0oYXJncywgY3VycmVudFRyYW5zZm9ybSwgaSk7CiAgICAgIH0KICAgICAgdGhpcy5jbWRzLnB1c2goYCR7Y21kfSR7YXJncy5qb2luKCIgIil9YCk7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmNtZHMucHVzaChjbWQpOwogICAgfQogIH0KICB0cmFuc2Zvcm0odHJhbnNmKSB7CiAgICB0aGlzLmN1cnJlbnRUcmFuc2Zvcm0gPSBVdGlsLnRyYW5zZm9ybSh0aGlzLmN1cnJlbnRUcmFuc2Zvcm0sIHRyYW5zZik7CiAgfQogIHRyYW5zbGF0ZSh4LCB5KSB7CiAgICB0aGlzLnRyYW5zZm9ybShbMSwgMCwgMCwgMSwgeCwgeV0pOwogIH0KICBzYXZlKCkgewogICAgdGhpcy50cmFuc2Zvcm1TdGFjay5wdXNoKHRoaXMuY3VycmVudFRyYW5zZm9ybS5zbGljZSgpKTsKICB9CiAgcmVzdG9yZSgpIHsKICAgIHRoaXMuY3VycmVudFRyYW5zZm9ybSA9IHRoaXMudHJhbnNmb3JtU3RhY2sucG9wKCkgfHwgWzEsIDAsIDAsIDEsIDAsIDBdOwogIH0KICBnZXRTVkcoKSB7CiAgICByZXR1cm4gdGhpcy5jbWRzLmpvaW4oIiIpOwogIH0KfQpjbGFzcyBDb21waWxlZEZvbnQgewogIGNvbnN0cnVjdG9yKGZvbnRNYXRyaXgpIHsKICAgIHRoaXMuZm9udE1hdHJpeCA9IGZvbnRNYXRyaXg7CiAgICB0aGlzLmNvbXBpbGVkR2x5cGhzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHRoaXMuY29tcGlsZWRDaGFyQ29kZVRvR2x5cGhJZCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgfQogIGdldFBhdGhKcyh1bmljb2RlKSB7CiAgICBjb25zdCB7CiAgICAgIGNoYXJDb2RlLAogICAgICBnbHlwaElkCiAgICB9ID0gbG9va3VwQ21hcCh0aGlzLmNtYXAsIHVuaWNvZGUpOwogICAgbGV0IGZuID0gdGhpcy5jb21waWxlZEdseXBoc1tnbHlwaElkXSwKICAgICAgY29tcGlsZUV4OwogICAgaWYgKGZuID09PSB1bmRlZmluZWQpIHsKICAgICAgdHJ5IHsKICAgICAgICBmbiA9IHRoaXMuY29tcGlsZUdseXBoKHRoaXMuZ2x5cGhzW2dseXBoSWRdLCBnbHlwaElkKTsKICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICBmbiA9IE5PT1A7CiAgICAgICAgY29tcGlsZUV4ID0gZXg7CiAgICAgIH0KICAgICAgdGhpcy5jb21waWxlZEdseXBoc1tnbHlwaElkXSA9IGZuOwogICAgfQogICAgdGhpcy5jb21waWxlZENoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA/Pz0gZ2x5cGhJZDsKICAgIGlmIChjb21waWxlRXgpIHsKICAgICAgdGhyb3cgY29tcGlsZUV4OwogICAgfQogICAgcmV0dXJuIGZuOwogIH0KICBjb21waWxlR2x5cGgoY29kZSwgZ2x5cGhJZCkgewogICAgaWYgKCFjb2RlPy5sZW5ndGggfHwgY29kZVswXSA9PT0gMTQpIHsKICAgICAgcmV0dXJuIE5PT1A7CiAgICB9CiAgICBsZXQgZm9udE1hdHJpeCA9IHRoaXMuZm9udE1hdHJpeDsKICAgIGlmICh0aGlzLmlzQ0ZGQ0lERm9udCkgewogICAgICBjb25zdCBmZEluZGV4ID0gdGhpcy5mZFNlbGVjdC5nZXRGREluZGV4KGdseXBoSWQpOwogICAgICBpZiAoZmRJbmRleCA+PSAwICYmIGZkSW5kZXggPCB0aGlzLmZkQXJyYXkubGVuZ3RoKSB7CiAgICAgICAgY29uc3QgZm9udERpY3QgPSB0aGlzLmZkQXJyYXlbZmRJbmRleF07CiAgICAgICAgZm9udE1hdHJpeCA9IGZvbnREaWN0LmdldEJ5TmFtZSgiRm9udE1hdHJpeCIpIHx8IEZPTlRfSURFTlRJVFlfTUFUUklYOwogICAgICB9IGVsc2UgewogICAgICAgIHdhcm4oIkludmFsaWQgZmQgaW5kZXggZm9yIGdseXBoIGluZGV4LiIpOwogICAgICB9CiAgICB9CiAgICBhc3NlcnQoaXNOdW1iZXJBcnJheShmb250TWF0cml4LCA2KSwgIkV4cGVjdGVkIGEgdmFsaWQgZm9udE1hdHJpeC4iKTsKICAgIGNvbnN0IGNtZHMgPSBuZXcgQ29tbWFuZHMoKTsKICAgIGNtZHMudHJhbnNmb3JtKGZvbnRNYXRyaXguc2xpY2UoKSk7CiAgICB0aGlzLmNvbXBpbGVHbHlwaEltcGwoY29kZSwgY21kcywgZ2x5cGhJZCk7CiAgICBjbWRzLmFkZCgiWiIpOwogICAgcmV0dXJuIGNtZHMuZ2V0U1ZHKCk7CiAgfQogIGNvbXBpbGVHbHlwaEltcGwoKSB7CiAgICB1bnJlYWNoYWJsZSgiQ2hpbGRyZW4gY2xhc3NlcyBzaG91bGQgaW1wbGVtZW50IHRoaXMuIik7CiAgfQogIGhhc0J1aWx0UGF0aCh1bmljb2RlKSB7CiAgICBjb25zdCB7CiAgICAgIGNoYXJDb2RlLAogICAgICBnbHlwaElkCiAgICB9ID0gbG9va3VwQ21hcCh0aGlzLmNtYXAsIHVuaWNvZGUpOwogICAgcmV0dXJuIHRoaXMuY29tcGlsZWRHbHlwaHNbZ2x5cGhJZF0gIT09IHVuZGVmaW5lZCAmJiB0aGlzLmNvbXBpbGVkQ2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdICE9PSB1bmRlZmluZWQ7CiAgfQp9CmNsYXNzIFRydWVUeXBlQ29tcGlsZWQgZXh0ZW5kcyBDb21waWxlZEZvbnQgewogIGNvbnN0cnVjdG9yKGdseXBocywgY21hcCwgZm9udE1hdHJpeCkgewogICAgc3VwZXIoZm9udE1hdHJpeCB8fCBbMC4wMDA0ODgsIDAsIDAsIDAuMDAwNDg4LCAwLCAwXSk7CiAgICB0aGlzLmdseXBocyA9IGdseXBoczsKICAgIHRoaXMuY21hcCA9IGNtYXA7CiAgfQogIGNvbXBpbGVHbHlwaEltcGwoY29kZSwgY21kcykgewogICAgY29tcGlsZUdseWYoY29kZSwgY21kcywgdGhpcyk7CiAgfQp9CmNsYXNzIFR5cGUyQ29tcGlsZWQgZXh0ZW5kcyBDb21waWxlZEZvbnQgewogIGNvbnN0cnVjdG9yKGNmZkluZm8sIGNtYXAsIGZvbnRNYXRyaXgpIHsKICAgIHN1cGVyKGZvbnRNYXRyaXggfHwgWzAuMDAxLCAwLCAwLCAwLjAwMSwgMCwgMF0pOwogICAgdGhpcy5nbHlwaHMgPSBjZmZJbmZvLmdseXBoczsKICAgIHRoaXMuZ3N1YnJzID0gY2ZmSW5mby5nc3VicnMgfHwgW107CiAgICB0aGlzLnN1YnJzID0gY2ZmSW5mby5zdWJycyB8fCBbXTsKICAgIHRoaXMuY21hcCA9IGNtYXA7CiAgICB0aGlzLmdseXBoTmFtZU1hcCA9IGdldEdseXBoc1VuaWNvZGUoKTsKICAgIHRoaXMuZ3N1YnJzQmlhcyA9IGdldFN1YnJvdXRpbmVCaWFzKHRoaXMuZ3N1YnJzKTsKICAgIHRoaXMuc3VicnNCaWFzID0gZ2V0U3Vicm91dGluZUJpYXModGhpcy5zdWJycyk7CiAgICB0aGlzLmlzQ0ZGQ0lERm9udCA9IGNmZkluZm8uaXNDRkZDSURGb250OwogICAgdGhpcy5mZFNlbGVjdCA9IGNmZkluZm8uZmRTZWxlY3Q7CiAgICB0aGlzLmZkQXJyYXkgPSBjZmZJbmZvLmZkQXJyYXk7CiAgfQogIGNvbXBpbGVHbHlwaEltcGwoY29kZSwgY21kcywgZ2x5cGhJZCkgewogICAgY29tcGlsZUNoYXJTdHJpbmcoY29kZSwgY21kcywgdGhpcywgZ2x5cGhJZCk7CiAgfQp9CmNsYXNzIEZvbnRSZW5kZXJlckZhY3RvcnkgewogIHN0YXRpYyBjcmVhdGUoZm9udCwgc2VhY0FuYWx5c2lzRW5hYmxlZCkgewogICAgY29uc3QgZGF0YSA9IG5ldyBVaW50OEFycmF5KGZvbnQuZGF0YSk7CiAgICBsZXQgY21hcCwgZ2x5ZiwgbG9jYSwgY2ZmLCBpbmRleFRvTG9jRm9ybWF0LCB1bml0c1BlckVtOwogICAgY29uc3QgbnVtVGFibGVzID0gcmVhZFVpbnQxNihkYXRhLCA0KTsKICAgIGZvciAobGV0IGkgPSAwLCBwID0gMTI7IGkgPCBudW1UYWJsZXM7IGkrKywgcCArPSAxNikgewogICAgICBjb25zdCB0YWcgPSBieXRlc1RvU3RyaW5nKGRhdGEuc3ViYXJyYXkocCwgcCArIDQpKTsKICAgICAgY29uc3Qgb2Zmc2V0ID0gcmVhZFVpbnQzMihkYXRhLCBwICsgOCk7CiAgICAgIGNvbnN0IGxlbmd0aCA9IHJlYWRVaW50MzIoZGF0YSwgcCArIDEyKTsKICAgICAgc3dpdGNoICh0YWcpIHsKICAgICAgICBjYXNlICJjbWFwIjoKICAgICAgICAgIGNtYXAgPSBwYXJzZUNtYXAoZGF0YSwgb2Zmc2V0LCBvZmZzZXQgKyBsZW5ndGgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZ2x5ZiI6CiAgICAgICAgICBnbHlmID0gZGF0YS5zdWJhcnJheShvZmZzZXQsIG9mZnNldCArIGxlbmd0aCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJsb2NhIjoKICAgICAgICAgIGxvY2EgPSBkYXRhLnN1YmFycmF5KG9mZnNldCwgb2Zmc2V0ICsgbGVuZ3RoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImhlYWQiOgogICAgICAgICAgdW5pdHNQZXJFbSA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0ICsgMTgpOwogICAgICAgICAgaW5kZXhUb0xvY0Zvcm1hdCA9IHJlYWRVaW50MTYoZGF0YSwgb2Zmc2V0ICsgNTApOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiQ0ZGICI6CiAgICAgICAgICBjZmYgPSBwYXJzZUNmZihkYXRhLCBvZmZzZXQsIG9mZnNldCArIGxlbmd0aCwgc2VhY0FuYWx5c2lzRW5hYmxlZCk7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgaWYgKGdseWYpIHsKICAgICAgY29uc3QgZm9udE1hdHJpeCA9ICF1bml0c1BlckVtID8gZm9udC5mb250TWF0cml4IDogWzEgLyB1bml0c1BlckVtLCAwLCAwLCAxIC8gdW5pdHNQZXJFbSwgMCwgMF07CiAgICAgIHJldHVybiBuZXcgVHJ1ZVR5cGVDb21waWxlZChwYXJzZUdseWZUYWJsZShnbHlmLCBsb2NhLCBpbmRleFRvTG9jRm9ybWF0KSwgY21hcCwgZm9udE1hdHJpeCk7CiAgICB9CiAgICByZXR1cm4gbmV3IFR5cGUyQ29tcGlsZWQoY2ZmLCBjbWFwLCBmb250LmZvbnRNYXRyaXgpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvbWV0cmljcy5qcwoKY29uc3QgZ2V0TWV0cmljcyA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogIHQuQ291cmllciA9IDYwMDsKICB0WyJDb3VyaWVyLUJvbGQiXSA9IDYwMDsKICB0WyJDb3VyaWVyLUJvbGRPYmxpcXVlIl0gPSA2MDA7CiAgdFsiQ291cmllci1PYmxpcXVlIl0gPSA2MDA7CiAgdC5IZWx2ZXRpY2EgPSBnZXRMb29rdXBUYWJsZUZhY3RvcnkoZnVuY3Rpb24gKHQpIHsKICAgIHQuc3BhY2UgPSAyNzg7CiAgICB0LmV4Y2xhbSA9IDI3ODsKICAgIHQucXVvdGVkYmwgPSAzNTU7CiAgICB0Lm51bWJlcnNpZ24gPSA1NTY7CiAgICB0LmRvbGxhciA9IDU1NjsKICAgIHQucGVyY2VudCA9IDg4OTsKICAgIHQuYW1wZXJzYW5kID0gNjY3OwogICAgdC5xdW90ZXJpZ2h0ID0gMjIyOwogICAgdC5wYXJlbmxlZnQgPSAzMzM7CiAgICB0LnBhcmVucmlnaHQgPSAzMzM7CiAgICB0LmFzdGVyaXNrID0gMzg5OwogICAgdC5wbHVzID0gNTg0OwogICAgdC5jb21tYSA9IDI3ODsKICAgIHQuaHlwaGVuID0gMzMzOwogICAgdC5wZXJpb2QgPSAyNzg7CiAgICB0LnNsYXNoID0gMjc4OwogICAgdC56ZXJvID0gNTU2OwogICAgdC5vbmUgPSA1NTY7CiAgICB0LnR3byA9IDU1NjsKICAgIHQudGhyZWUgPSA1NTY7CiAgICB0LmZvdXIgPSA1NTY7CiAgICB0LmZpdmUgPSA1NTY7CiAgICB0LnNpeCA9IDU1NjsKICAgIHQuc2V2ZW4gPSA1NTY7CiAgICB0LmVpZ2h0ID0gNTU2OwogICAgdC5uaW5lID0gNTU2OwogICAgdC5jb2xvbiA9IDI3ODsKICAgIHQuc2VtaWNvbG9uID0gMjc4OwogICAgdC5sZXNzID0gNTg0OwogICAgdC5lcXVhbCA9IDU4NDsKICAgIHQuZ3JlYXRlciA9IDU4NDsKICAgIHQucXVlc3Rpb24gPSA1NTY7CiAgICB0LmF0ID0gMTAxNTsKICAgIHQuQSA9IDY2NzsKICAgIHQuQiA9IDY2NzsKICAgIHQuQyA9IDcyMjsKICAgIHQuRCA9IDcyMjsKICAgIHQuRSA9IDY2NzsKICAgIHQuRiA9IDYxMTsKICAgIHQuRyA9IDc3ODsKICAgIHQuSCA9IDcyMjsKICAgIHQuSSA9IDI3ODsKICAgIHQuSiA9IDUwMDsKICAgIHQuSyA9IDY2NzsKICAgIHQuTCA9IDU1NjsKICAgIHQuTSA9IDgzMzsKICAgIHQuTiA9IDcyMjsKICAgIHQuTyA9IDc3ODsKICAgIHQuUCA9IDY2NzsKICAgIHQuUSA9IDc3ODsKICAgIHQuUiA9IDcyMjsKICAgIHQuUyA9IDY2NzsKICAgIHQuVCA9IDYxMTsKICAgIHQuVSA9IDcyMjsKICAgIHQuViA9IDY2NzsKICAgIHQuVyA9IDk0NDsKICAgIHQuWCA9IDY2NzsKICAgIHQuWSA9IDY2NzsKICAgIHQuWiA9IDYxMTsKICAgIHQuYnJhY2tldGxlZnQgPSAyNzg7CiAgICB0LmJhY2tzbGFzaCA9IDI3ODsKICAgIHQuYnJhY2tldHJpZ2h0ID0gMjc4OwogICAgdC5hc2NpaWNpcmN1bSA9IDQ2OTsKICAgIHQudW5kZXJzY29yZSA9IDU1NjsKICAgIHQucXVvdGVsZWZ0ID0gMjIyOwogICAgdC5hID0gNTU2OwogICAgdC5iID0gNTU2OwogICAgdC5jID0gNTAwOwogICAgdC5kID0gNTU2OwogICAgdC5lID0gNTU2OwogICAgdC5mID0gMjc4OwogICAgdC5nID0gNTU2OwogICAgdC5oID0gNTU2OwogICAgdC5pID0gMjIyOwogICAgdC5qID0gMjIyOwogICAgdC5rID0gNTAwOwogICAgdC5sID0gMjIyOwogICAgdC5tID0gODMzOwogICAgdC5uID0gNTU2OwogICAgdC5vID0gNTU2OwogICAgdC5wID0gNTU2OwogICAgdC5xID0gNTU2OwogICAgdC5yID0gMzMzOwogICAgdC5zID0gNTAwOwogICAgdC50ID0gMjc4OwogICAgdC51ID0gNTU2OwogICAgdC52ID0gNTAwOwogICAgdC53ID0gNzIyOwogICAgdC54ID0gNTAwOwogICAgdC55ID0gNTAwOwogICAgdC56ID0gNTAwOwogICAgdC5icmFjZWxlZnQgPSAzMzQ7CiAgICB0LmJhciA9IDI2MDsKICAgIHQuYnJhY2VyaWdodCA9IDMzNDsKICAgIHQuYXNjaWl0aWxkZSA9IDU4NDsKICAgIHQuZXhjbGFtZG93biA9IDMzMzsKICAgIHQuY2VudCA9IDU1NjsKICAgIHQuc3RlcmxpbmcgPSA1NTY7CiAgICB0LmZyYWN0aW9uID0gMTY3OwogICAgdC55ZW4gPSA1NTY7CiAgICB0LmZsb3JpbiA9IDU1NjsKICAgIHQuc2VjdGlvbiA9IDU1NjsKICAgIHQuY3VycmVuY3kgPSA1NTY7CiAgICB0LnF1b3Rlc2luZ2xlID0gMTkxOwogICAgdC5xdW90ZWRibGxlZnQgPSAzMzM7CiAgICB0Lmd1aWxsZW1vdGxlZnQgPSA1NTY7CiAgICB0Lmd1aWxzaW5nbGxlZnQgPSAzMzM7CiAgICB0Lmd1aWxzaW5nbHJpZ2h0ID0gMzMzOwogICAgdC5maSA9IDUwMDsKICAgIHQuZmwgPSA1MDA7CiAgICB0LmVuZGFzaCA9IDU1NjsKICAgIHQuZGFnZ2VyID0gNTU2OwogICAgdC5kYWdnZXJkYmwgPSA1NTY7CiAgICB0LnBlcmlvZGNlbnRlcmVkID0gMjc4OwogICAgdC5wYXJhZ3JhcGggPSA1Mzc7CiAgICB0LmJ1bGxldCA9IDM1MDsKICAgIHQucXVvdGVzaW5nbGJhc2UgPSAyMjI7CiAgICB0LnF1b3RlZGJsYmFzZSA9IDMzMzsKICAgIHQucXVvdGVkYmxyaWdodCA9IDMzMzsKICAgIHQuZ3VpbGxlbW90cmlnaHQgPSA1NTY7CiAgICB0LmVsbGlwc2lzID0gMTAwMDsKICAgIHQucGVydGhvdXNhbmQgPSAxMDAwOwogICAgdC5xdWVzdGlvbmRvd24gPSA2MTE7CiAgICB0LmdyYXZlID0gMzMzOwogICAgdC5hY3V0ZSA9IDMzMzsKICAgIHQuY2lyY3VtZmxleCA9IDMzMzsKICAgIHQudGlsZGUgPSAzMzM7CiAgICB0Lm1hY3JvbiA9IDMzMzsKICAgIHQuYnJldmUgPSAzMzM7CiAgICB0LmRvdGFjY2VudCA9IDMzMzsKICAgIHQuZGllcmVzaXMgPSAzMzM7CiAgICB0LnJpbmcgPSAzMzM7CiAgICB0LmNlZGlsbGEgPSAzMzM7CiAgICB0Lmh1bmdhcnVtbGF1dCA9IDMzMzsKICAgIHQub2dvbmVrID0gMzMzOwogICAgdC5jYXJvbiA9IDMzMzsKICAgIHQuZW1kYXNoID0gMTAwMDsKICAgIHQuQUUgPSAxMDAwOwogICAgdC5vcmRmZW1pbmluZSA9IDM3MDsKICAgIHQuTHNsYXNoID0gNTU2OwogICAgdC5Pc2xhc2ggPSA3Nzg7CiAgICB0Lk9FID0gMTAwMDsKICAgIHQub3JkbWFzY3VsaW5lID0gMzY1OwogICAgdC5hZSA9IDg4OTsKICAgIHQuZG90bGVzc2kgPSAyNzg7CiAgICB0LmxzbGFzaCA9IDIyMjsKICAgIHQub3NsYXNoID0gNjExOwogICAgdC5vZSA9IDk0NDsKICAgIHQuZ2VybWFuZGJscyA9IDYxMTsKICAgIHQuSWRpZXJlc2lzID0gMjc4OwogICAgdC5lYWN1dGUgPSA1NTY7CiAgICB0LmFicmV2ZSA9IDU1NjsKICAgIHQudWh1bmdhcnVtbGF1dCA9IDU1NjsKICAgIHQuZWNhcm9uID0gNTU2OwogICAgdC5ZZGllcmVzaXMgPSA2Njc7CiAgICB0LmRpdmlkZSA9IDU4NDsKICAgIHQuWWFjdXRlID0gNjY3OwogICAgdC5BY2lyY3VtZmxleCA9IDY2NzsKICAgIHQuYWFjdXRlID0gNTU2OwogICAgdC5VY2lyY3VtZmxleCA9IDcyMjsKICAgIHQueWFjdXRlID0gNTAwOwogICAgdC5zY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0LmVjaXJjdW1mbGV4ID0gNTU2OwogICAgdC5VcmluZyA9IDcyMjsKICAgIHQuVWRpZXJlc2lzID0gNzIyOwogICAgdC5hb2dvbmVrID0gNTU2OwogICAgdC5VYWN1dGUgPSA3MjI7CiAgICB0LnVvZ29uZWsgPSA1NTY7CiAgICB0LkVkaWVyZXNpcyA9IDY2NzsKICAgIHQuRGNyb2F0ID0gNzIyOwogICAgdC5jb21tYWFjY2VudCA9IDI1MDsKICAgIHQuY29weXJpZ2h0ID0gNzM3OwogICAgdC5FbWFjcm9uID0gNjY3OwogICAgdC5jY2Fyb24gPSA1MDA7CiAgICB0LmFyaW5nID0gNTU2OwogICAgdC5OY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LmxhY3V0ZSA9IDIyMjsKICAgIHQuYWdyYXZlID0gNTU2OwogICAgdC5UY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0LkNhY3V0ZSA9IDcyMjsKICAgIHQuYXRpbGRlID0gNTU2OwogICAgdC5FZG90YWNjZW50ID0gNjY3OwogICAgdC5zY2Fyb24gPSA1MDA7CiAgICB0LnNjZWRpbGxhID0gNTAwOwogICAgdC5pYWN1dGUgPSAyNzg7CiAgICB0LmxvemVuZ2UgPSA0NzE7CiAgICB0LlJjYXJvbiA9IDcyMjsKICAgIHQuR2NvbW1hYWNjZW50ID0gNzc4OwogICAgdC51Y2lyY3VtZmxleCA9IDU1NjsKICAgIHQuYWNpcmN1bWZsZXggPSA1NTY7CiAgICB0LkFtYWNyb24gPSA2Njc7CiAgICB0LnJjYXJvbiA9IDMzMzsKICAgIHQuY2NlZGlsbGEgPSA1MDA7CiAgICB0Llpkb3RhY2NlbnQgPSA2MTE7CiAgICB0LlRob3JuID0gNjY3OwogICAgdC5PbWFjcm9uID0gNzc4OwogICAgdC5SYWN1dGUgPSA3MjI7CiAgICB0LlNhY3V0ZSA9IDY2NzsKICAgIHQuZGNhcm9uID0gNjQzOwogICAgdC5VbWFjcm9uID0gNzIyOwogICAgdC51cmluZyA9IDU1NjsKICAgIHQudGhyZWVzdXBlcmlvciA9IDMzMzsKICAgIHQuT2dyYXZlID0gNzc4OwogICAgdC5BZ3JhdmUgPSA2Njc7CiAgICB0LkFicmV2ZSA9IDY2NzsKICAgIHQubXVsdGlwbHkgPSA1ODQ7CiAgICB0LnVhY3V0ZSA9IDU1NjsKICAgIHQuVGNhcm9uID0gNjExOwogICAgdC5wYXJ0aWFsZGlmZiA9IDQ3NjsKICAgIHQueWRpZXJlc2lzID0gNTAwOwogICAgdC5OYWN1dGUgPSA3MjI7CiAgICB0LmljaXJjdW1mbGV4ID0gMjc4OwogICAgdC5FY2lyY3VtZmxleCA9IDY2NzsKICAgIHQuYWRpZXJlc2lzID0gNTU2OwogICAgdC5lZGllcmVzaXMgPSA1NTY7CiAgICB0LmNhY3V0ZSA9IDUwMDsKICAgIHQubmFjdXRlID0gNTU2OwogICAgdC51bWFjcm9uID0gNTU2OwogICAgdC5OY2Fyb24gPSA3MjI7CiAgICB0LklhY3V0ZSA9IDI3ODsKICAgIHQucGx1c21pbnVzID0gNTg0OwogICAgdC5icm9rZW5iYXIgPSAyNjA7CiAgICB0LnJlZ2lzdGVyZWQgPSA3Mzc7CiAgICB0LkdicmV2ZSA9IDc3ODsKICAgIHQuSWRvdGFjY2VudCA9IDI3ODsKICAgIHQuc3VtbWF0aW9uID0gNjAwOwogICAgdC5FZ3JhdmUgPSA2Njc7CiAgICB0LnJhY3V0ZSA9IDMzMzsKICAgIHQub21hY3JvbiA9IDU1NjsKICAgIHQuWmFjdXRlID0gNjExOwogICAgdC5aY2Fyb24gPSA2MTE7CiAgICB0LmdyZWF0ZXJlcXVhbCA9IDU0OTsKICAgIHQuRXRoID0gNzIyOwogICAgdC5DY2VkaWxsYSA9IDcyMjsKICAgIHQubGNvbW1hYWNjZW50ID0gMjIyOwogICAgdC50Y2Fyb24gPSAzMTc7CiAgICB0LmVvZ29uZWsgPSA1NTY7CiAgICB0LlVvZ29uZWsgPSA3MjI7CiAgICB0LkFhY3V0ZSA9IDY2NzsKICAgIHQuQWRpZXJlc2lzID0gNjY3OwogICAgdC5lZ3JhdmUgPSA1NTY7CiAgICB0LnphY3V0ZSA9IDUwMDsKICAgIHQuaW9nb25layA9IDIyMjsKICAgIHQuT2FjdXRlID0gNzc4OwogICAgdC5vYWN1dGUgPSA1NTY7CiAgICB0LmFtYWNyb24gPSA1NTY7CiAgICB0LnNhY3V0ZSA9IDUwMDsKICAgIHQuaWRpZXJlc2lzID0gMjc4OwogICAgdC5PY2lyY3VtZmxleCA9IDc3ODsKICAgIHQuVWdyYXZlID0gNzIyOwogICAgdC5EZWx0YSA9IDYxMjsKICAgIHQudGhvcm4gPSA1NTY7CiAgICB0LnR3b3N1cGVyaW9yID0gMzMzOwogICAgdC5PZGllcmVzaXMgPSA3Nzg7CiAgICB0Lm11ID0gNTU2OwogICAgdC5pZ3JhdmUgPSAyNzg7CiAgICB0Lm9odW5nYXJ1bWxhdXQgPSA1NTY7CiAgICB0LkVvZ29uZWsgPSA2Njc7CiAgICB0LmRjcm9hdCA9IDU1NjsKICAgIHQudGhyZWVxdWFydGVycyA9IDgzNDsKICAgIHQuU2NlZGlsbGEgPSA2Njc7CiAgICB0LmxjYXJvbiA9IDI5OTsKICAgIHQuS2NvbW1hYWNjZW50ID0gNjY3OwogICAgdC5MYWN1dGUgPSA1NTY7CiAgICB0LnRyYWRlbWFyayA9IDEwMDA7CiAgICB0LmVkb3RhY2NlbnQgPSA1NTY7CiAgICB0LklncmF2ZSA9IDI3ODsKICAgIHQuSW1hY3JvbiA9IDI3ODsKICAgIHQuTGNhcm9uID0gNTU2OwogICAgdC5vbmVoYWxmID0gODM0OwogICAgdC5sZXNzZXF1YWwgPSA1NDk7CiAgICB0Lm9jaXJjdW1mbGV4ID0gNTU2OwogICAgdC5udGlsZGUgPSA1NTY7CiAgICB0LlVodW5nYXJ1bWxhdXQgPSA3MjI7CiAgICB0LkVhY3V0ZSA9IDY2NzsKICAgIHQuZW1hY3JvbiA9IDU1NjsKICAgIHQuZ2JyZXZlID0gNTU2OwogICAgdC5vbmVxdWFydGVyID0gODM0OwogICAgdC5TY2Fyb24gPSA2Njc7CiAgICB0LlNjb21tYWFjY2VudCA9IDY2NzsKICAgIHQuT2h1bmdhcnVtbGF1dCA9IDc3ODsKICAgIHQuZGVncmVlID0gNDAwOwogICAgdC5vZ3JhdmUgPSA1NTY7CiAgICB0LkNjYXJvbiA9IDcyMjsKICAgIHQudWdyYXZlID0gNTU2OwogICAgdC5yYWRpY2FsID0gNDUzOwogICAgdC5EY2Fyb24gPSA3MjI7CiAgICB0LnJjb21tYWFjY2VudCA9IDMzMzsKICAgIHQuTnRpbGRlID0gNzIyOwogICAgdC5vdGlsZGUgPSA1NTY7CiAgICB0LlJjb21tYWFjY2VudCA9IDcyMjsKICAgIHQuTGNvbW1hYWNjZW50ID0gNTU2OwogICAgdC5BdGlsZGUgPSA2Njc7CiAgICB0LkFvZ29uZWsgPSA2Njc7CiAgICB0LkFyaW5nID0gNjY3OwogICAgdC5PdGlsZGUgPSA3Nzg7CiAgICB0Lnpkb3RhY2NlbnQgPSA1MDA7CiAgICB0LkVjYXJvbiA9IDY2NzsKICAgIHQuSW9nb25layA9IDI3ODsKICAgIHQua2NvbW1hYWNjZW50ID0gNTAwOwogICAgdC5taW51cyA9IDU4NDsKICAgIHQuSWNpcmN1bWZsZXggPSAyNzg7CiAgICB0Lm5jYXJvbiA9IDU1NjsKICAgIHQudGNvbW1hYWNjZW50ID0gMjc4OwogICAgdC5sb2dpY2Fsbm90ID0gNTg0OwogICAgdC5vZGllcmVzaXMgPSA1NTY7CiAgICB0LnVkaWVyZXNpcyA9IDU1NjsKICAgIHQubm90ZXF1YWwgPSA1NDk7CiAgICB0Lmdjb21tYWFjY2VudCA9IDU1NjsKICAgIHQuZXRoID0gNTU2OwogICAgdC56Y2Fyb24gPSA1MDA7CiAgICB0Lm5jb21tYWFjY2VudCA9IDU1NjsKICAgIHQub25lc3VwZXJpb3IgPSAzMzM7CiAgICB0LmltYWNyb24gPSAyNzg7CiAgICB0LkV1cm8gPSA1NTY7CiAgfSk7CiAgdFsiSGVsdmV0aWNhLUJvbGQiXSA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogICAgdC5zcGFjZSA9IDI3ODsKICAgIHQuZXhjbGFtID0gMzMzOwogICAgdC5xdW90ZWRibCA9IDQ3NDsKICAgIHQubnVtYmVyc2lnbiA9IDU1NjsKICAgIHQuZG9sbGFyID0gNTU2OwogICAgdC5wZXJjZW50ID0gODg5OwogICAgdC5hbXBlcnNhbmQgPSA3MjI7CiAgICB0LnF1b3RlcmlnaHQgPSAyNzg7CiAgICB0LnBhcmVubGVmdCA9IDMzMzsKICAgIHQucGFyZW5yaWdodCA9IDMzMzsKICAgIHQuYXN0ZXJpc2sgPSAzODk7CiAgICB0LnBsdXMgPSA1ODQ7CiAgICB0LmNvbW1hID0gMjc4OwogICAgdC5oeXBoZW4gPSAzMzM7CiAgICB0LnBlcmlvZCA9IDI3ODsKICAgIHQuc2xhc2ggPSAyNzg7CiAgICB0Lnplcm8gPSA1NTY7CiAgICB0Lm9uZSA9IDU1NjsKICAgIHQudHdvID0gNTU2OwogICAgdC50aHJlZSA9IDU1NjsKICAgIHQuZm91ciA9IDU1NjsKICAgIHQuZml2ZSA9IDU1NjsKICAgIHQuc2l4ID0gNTU2OwogICAgdC5zZXZlbiA9IDU1NjsKICAgIHQuZWlnaHQgPSA1NTY7CiAgICB0Lm5pbmUgPSA1NTY7CiAgICB0LmNvbG9uID0gMzMzOwogICAgdC5zZW1pY29sb24gPSAzMzM7CiAgICB0Lmxlc3MgPSA1ODQ7CiAgICB0LmVxdWFsID0gNTg0OwogICAgdC5ncmVhdGVyID0gNTg0OwogICAgdC5xdWVzdGlvbiA9IDYxMTsKICAgIHQuYXQgPSA5NzU7CiAgICB0LkEgPSA3MjI7CiAgICB0LkIgPSA3MjI7CiAgICB0LkMgPSA3MjI7CiAgICB0LkQgPSA3MjI7CiAgICB0LkUgPSA2Njc7CiAgICB0LkYgPSA2MTE7CiAgICB0LkcgPSA3Nzg7CiAgICB0LkggPSA3MjI7CiAgICB0LkkgPSAyNzg7CiAgICB0LkogPSA1NTY7CiAgICB0LksgPSA3MjI7CiAgICB0LkwgPSA2MTE7CiAgICB0Lk0gPSA4MzM7CiAgICB0Lk4gPSA3MjI7CiAgICB0Lk8gPSA3Nzg7CiAgICB0LlAgPSA2Njc7CiAgICB0LlEgPSA3Nzg7CiAgICB0LlIgPSA3MjI7CiAgICB0LlMgPSA2Njc7CiAgICB0LlQgPSA2MTE7CiAgICB0LlUgPSA3MjI7CiAgICB0LlYgPSA2Njc7CiAgICB0LlcgPSA5NDQ7CiAgICB0LlggPSA2Njc7CiAgICB0LlkgPSA2Njc7CiAgICB0LlogPSA2MTE7CiAgICB0LmJyYWNrZXRsZWZ0ID0gMzMzOwogICAgdC5iYWNrc2xhc2ggPSAyNzg7CiAgICB0LmJyYWNrZXRyaWdodCA9IDMzMzsKICAgIHQuYXNjaWljaXJjdW0gPSA1ODQ7CiAgICB0LnVuZGVyc2NvcmUgPSA1NTY7CiAgICB0LnF1b3RlbGVmdCA9IDI3ODsKICAgIHQuYSA9IDU1NjsKICAgIHQuYiA9IDYxMTsKICAgIHQuYyA9IDU1NjsKICAgIHQuZCA9IDYxMTsKICAgIHQuZSA9IDU1NjsKICAgIHQuZiA9IDMzMzsKICAgIHQuZyA9IDYxMTsKICAgIHQuaCA9IDYxMTsKICAgIHQuaSA9IDI3ODsKICAgIHQuaiA9IDI3ODsKICAgIHQuayA9IDU1NjsKICAgIHQubCA9IDI3ODsKICAgIHQubSA9IDg4OTsKICAgIHQubiA9IDYxMTsKICAgIHQubyA9IDYxMTsKICAgIHQucCA9IDYxMTsKICAgIHQucSA9IDYxMTsKICAgIHQuciA9IDM4OTsKICAgIHQucyA9IDU1NjsKICAgIHQudCA9IDMzMzsKICAgIHQudSA9IDYxMTsKICAgIHQudiA9IDU1NjsKICAgIHQudyA9IDc3ODsKICAgIHQueCA9IDU1NjsKICAgIHQueSA9IDU1NjsKICAgIHQueiA9IDUwMDsKICAgIHQuYnJhY2VsZWZ0ID0gMzg5OwogICAgdC5iYXIgPSAyODA7CiAgICB0LmJyYWNlcmlnaHQgPSAzODk7CiAgICB0LmFzY2lpdGlsZGUgPSA1ODQ7CiAgICB0LmV4Y2xhbWRvd24gPSAzMzM7CiAgICB0LmNlbnQgPSA1NTY7CiAgICB0LnN0ZXJsaW5nID0gNTU2OwogICAgdC5mcmFjdGlvbiA9IDE2NzsKICAgIHQueWVuID0gNTU2OwogICAgdC5mbG9yaW4gPSA1NTY7CiAgICB0LnNlY3Rpb24gPSA1NTY7CiAgICB0LmN1cnJlbmN5ID0gNTU2OwogICAgdC5xdW90ZXNpbmdsZSA9IDIzODsKICAgIHQucXVvdGVkYmxsZWZ0ID0gNTAwOwogICAgdC5ndWlsbGVtb3RsZWZ0ID0gNTU2OwogICAgdC5ndWlsc2luZ2xsZWZ0ID0gMzMzOwogICAgdC5ndWlsc2luZ2xyaWdodCA9IDMzMzsKICAgIHQuZmkgPSA2MTE7CiAgICB0LmZsID0gNjExOwogICAgdC5lbmRhc2ggPSA1NTY7CiAgICB0LmRhZ2dlciA9IDU1NjsKICAgIHQuZGFnZ2VyZGJsID0gNTU2OwogICAgdC5wZXJpb2RjZW50ZXJlZCA9IDI3ODsKICAgIHQucGFyYWdyYXBoID0gNTU2OwogICAgdC5idWxsZXQgPSAzNTA7CiAgICB0LnF1b3Rlc2luZ2xiYXNlID0gMjc4OwogICAgdC5xdW90ZWRibGJhc2UgPSA1MDA7CiAgICB0LnF1b3RlZGJscmlnaHQgPSA1MDA7CiAgICB0Lmd1aWxsZW1vdHJpZ2h0ID0gNTU2OwogICAgdC5lbGxpcHNpcyA9IDEwMDA7CiAgICB0LnBlcnRob3VzYW5kID0gMTAwMDsKICAgIHQucXVlc3Rpb25kb3duID0gNjExOwogICAgdC5ncmF2ZSA9IDMzMzsKICAgIHQuYWN1dGUgPSAzMzM7CiAgICB0LmNpcmN1bWZsZXggPSAzMzM7CiAgICB0LnRpbGRlID0gMzMzOwogICAgdC5tYWNyb24gPSAzMzM7CiAgICB0LmJyZXZlID0gMzMzOwogICAgdC5kb3RhY2NlbnQgPSAzMzM7CiAgICB0LmRpZXJlc2lzID0gMzMzOwogICAgdC5yaW5nID0gMzMzOwogICAgdC5jZWRpbGxhID0gMzMzOwogICAgdC5odW5nYXJ1bWxhdXQgPSAzMzM7CiAgICB0Lm9nb25layA9IDMzMzsKICAgIHQuY2Fyb24gPSAzMzM7CiAgICB0LmVtZGFzaCA9IDEwMDA7CiAgICB0LkFFID0gMTAwMDsKICAgIHQub3JkZmVtaW5pbmUgPSAzNzA7CiAgICB0LkxzbGFzaCA9IDYxMTsKICAgIHQuT3NsYXNoID0gNzc4OwogICAgdC5PRSA9IDEwMDA7CiAgICB0Lm9yZG1hc2N1bGluZSA9IDM2NTsKICAgIHQuYWUgPSA4ODk7CiAgICB0LmRvdGxlc3NpID0gMjc4OwogICAgdC5sc2xhc2ggPSAyNzg7CiAgICB0Lm9zbGFzaCA9IDYxMTsKICAgIHQub2UgPSA5NDQ7CiAgICB0Lmdlcm1hbmRibHMgPSA2MTE7CiAgICB0LklkaWVyZXNpcyA9IDI3ODsKICAgIHQuZWFjdXRlID0gNTU2OwogICAgdC5hYnJldmUgPSA1NTY7CiAgICB0LnVodW5nYXJ1bWxhdXQgPSA2MTE7CiAgICB0LmVjYXJvbiA9IDU1NjsKICAgIHQuWWRpZXJlc2lzID0gNjY3OwogICAgdC5kaXZpZGUgPSA1ODQ7CiAgICB0LllhY3V0ZSA9IDY2NzsKICAgIHQuQWNpcmN1bWZsZXggPSA3MjI7CiAgICB0LmFhY3V0ZSA9IDU1NjsKICAgIHQuVWNpcmN1bWZsZXggPSA3MjI7CiAgICB0LnlhY3V0ZSA9IDU1NjsKICAgIHQuc2NvbW1hYWNjZW50ID0gNTU2OwogICAgdC5lY2lyY3VtZmxleCA9IDU1NjsKICAgIHQuVXJpbmcgPSA3MjI7CiAgICB0LlVkaWVyZXNpcyA9IDcyMjsKICAgIHQuYW9nb25layA9IDU1NjsKICAgIHQuVWFjdXRlID0gNzIyOwogICAgdC51b2dvbmVrID0gNjExOwogICAgdC5FZGllcmVzaXMgPSA2Njc7CiAgICB0LkRjcm9hdCA9IDcyMjsKICAgIHQuY29tbWFhY2NlbnQgPSAyNTA7CiAgICB0LmNvcHlyaWdodCA9IDczNzsKICAgIHQuRW1hY3JvbiA9IDY2NzsKICAgIHQuY2Nhcm9uID0gNTU2OwogICAgdC5hcmluZyA9IDU1NjsKICAgIHQuTmNvbW1hYWNjZW50ID0gNzIyOwogICAgdC5sYWN1dGUgPSAyNzg7CiAgICB0LmFncmF2ZSA9IDU1NjsKICAgIHQuVGNvbW1hYWNjZW50ID0gNjExOwogICAgdC5DYWN1dGUgPSA3MjI7CiAgICB0LmF0aWxkZSA9IDU1NjsKICAgIHQuRWRvdGFjY2VudCA9IDY2NzsKICAgIHQuc2Nhcm9uID0gNTU2OwogICAgdC5zY2VkaWxsYSA9IDU1NjsKICAgIHQuaWFjdXRlID0gMjc4OwogICAgdC5sb3plbmdlID0gNDk0OwogICAgdC5SY2Fyb24gPSA3MjI7CiAgICB0Lkdjb21tYWFjY2VudCA9IDc3ODsKICAgIHQudWNpcmN1bWZsZXggPSA2MTE7CiAgICB0LmFjaXJjdW1mbGV4ID0gNTU2OwogICAgdC5BbWFjcm9uID0gNzIyOwogICAgdC5yY2Fyb24gPSAzODk7CiAgICB0LmNjZWRpbGxhID0gNTU2OwogICAgdC5aZG90YWNjZW50ID0gNjExOwogICAgdC5UaG9ybiA9IDY2NzsKICAgIHQuT21hY3JvbiA9IDc3ODsKICAgIHQuUmFjdXRlID0gNzIyOwogICAgdC5TYWN1dGUgPSA2Njc7CiAgICB0LmRjYXJvbiA9IDc0MzsKICAgIHQuVW1hY3JvbiA9IDcyMjsKICAgIHQudXJpbmcgPSA2MTE7CiAgICB0LnRocmVlc3VwZXJpb3IgPSAzMzM7CiAgICB0Lk9ncmF2ZSA9IDc3ODsKICAgIHQuQWdyYXZlID0gNzIyOwogICAgdC5BYnJldmUgPSA3MjI7CiAgICB0Lm11bHRpcGx5ID0gNTg0OwogICAgdC51YWN1dGUgPSA2MTE7CiAgICB0LlRjYXJvbiA9IDYxMTsKICAgIHQucGFydGlhbGRpZmYgPSA0OTQ7CiAgICB0LnlkaWVyZXNpcyA9IDU1NjsKICAgIHQuTmFjdXRlID0gNzIyOwogICAgdC5pY2lyY3VtZmxleCA9IDI3ODsKICAgIHQuRWNpcmN1bWZsZXggPSA2Njc7CiAgICB0LmFkaWVyZXNpcyA9IDU1NjsKICAgIHQuZWRpZXJlc2lzID0gNTU2OwogICAgdC5jYWN1dGUgPSA1NTY7CiAgICB0Lm5hY3V0ZSA9IDYxMTsKICAgIHQudW1hY3JvbiA9IDYxMTsKICAgIHQuTmNhcm9uID0gNzIyOwogICAgdC5JYWN1dGUgPSAyNzg7CiAgICB0LnBsdXNtaW51cyA9IDU4NDsKICAgIHQuYnJva2VuYmFyID0gMjgwOwogICAgdC5yZWdpc3RlcmVkID0gNzM3OwogICAgdC5HYnJldmUgPSA3Nzg7CiAgICB0Lklkb3RhY2NlbnQgPSAyNzg7CiAgICB0LnN1bW1hdGlvbiA9IDYwMDsKICAgIHQuRWdyYXZlID0gNjY3OwogICAgdC5yYWN1dGUgPSAzODk7CiAgICB0Lm9tYWNyb24gPSA2MTE7CiAgICB0LlphY3V0ZSA9IDYxMTsKICAgIHQuWmNhcm9uID0gNjExOwogICAgdC5ncmVhdGVyZXF1YWwgPSA1NDk7CiAgICB0LkV0aCA9IDcyMjsKICAgIHQuQ2NlZGlsbGEgPSA3MjI7CiAgICB0Lmxjb21tYWFjY2VudCA9IDI3ODsKICAgIHQudGNhcm9uID0gMzg5OwogICAgdC5lb2dvbmVrID0gNTU2OwogICAgdC5Vb2dvbmVrID0gNzIyOwogICAgdC5BYWN1dGUgPSA3MjI7CiAgICB0LkFkaWVyZXNpcyA9IDcyMjsKICAgIHQuZWdyYXZlID0gNTU2OwogICAgdC56YWN1dGUgPSA1MDA7CiAgICB0LmlvZ29uZWsgPSAyNzg7CiAgICB0Lk9hY3V0ZSA9IDc3ODsKICAgIHQub2FjdXRlID0gNjExOwogICAgdC5hbWFjcm9uID0gNTU2OwogICAgdC5zYWN1dGUgPSA1NTY7CiAgICB0LmlkaWVyZXNpcyA9IDI3ODsKICAgIHQuT2NpcmN1bWZsZXggPSA3Nzg7CiAgICB0LlVncmF2ZSA9IDcyMjsKICAgIHQuRGVsdGEgPSA2MTI7CiAgICB0LnRob3JuID0gNjExOwogICAgdC50d29zdXBlcmlvciA9IDMzMzsKICAgIHQuT2RpZXJlc2lzID0gNzc4OwogICAgdC5tdSA9IDYxMTsKICAgIHQuaWdyYXZlID0gMjc4OwogICAgdC5vaHVuZ2FydW1sYXV0ID0gNjExOwogICAgdC5Fb2dvbmVrID0gNjY3OwogICAgdC5kY3JvYXQgPSA2MTE7CiAgICB0LnRocmVlcXVhcnRlcnMgPSA4MzQ7CiAgICB0LlNjZWRpbGxhID0gNjY3OwogICAgdC5sY2Fyb24gPSA0MDA7CiAgICB0Lktjb21tYWFjY2VudCA9IDcyMjsKICAgIHQuTGFjdXRlID0gNjExOwogICAgdC50cmFkZW1hcmsgPSAxMDAwOwogICAgdC5lZG90YWNjZW50ID0gNTU2OwogICAgdC5JZ3JhdmUgPSAyNzg7CiAgICB0LkltYWNyb24gPSAyNzg7CiAgICB0LkxjYXJvbiA9IDYxMTsKICAgIHQub25laGFsZiA9IDgzNDsKICAgIHQubGVzc2VxdWFsID0gNTQ5OwogICAgdC5vY2lyY3VtZmxleCA9IDYxMTsKICAgIHQubnRpbGRlID0gNjExOwogICAgdC5VaHVuZ2FydW1sYXV0ID0gNzIyOwogICAgdC5FYWN1dGUgPSA2Njc7CiAgICB0LmVtYWNyb24gPSA1NTY7CiAgICB0LmdicmV2ZSA9IDYxMTsKICAgIHQub25lcXVhcnRlciA9IDgzNDsKICAgIHQuU2Nhcm9uID0gNjY3OwogICAgdC5TY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0Lk9odW5nYXJ1bWxhdXQgPSA3Nzg7CiAgICB0LmRlZ3JlZSA9IDQwMDsKICAgIHQub2dyYXZlID0gNjExOwogICAgdC5DY2Fyb24gPSA3MjI7CiAgICB0LnVncmF2ZSA9IDYxMTsKICAgIHQucmFkaWNhbCA9IDU0OTsKICAgIHQuRGNhcm9uID0gNzIyOwogICAgdC5yY29tbWFhY2NlbnQgPSAzODk7CiAgICB0Lk50aWxkZSA9IDcyMjsKICAgIHQub3RpbGRlID0gNjExOwogICAgdC5SY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0Lkxjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuQXRpbGRlID0gNzIyOwogICAgdC5Bb2dvbmVrID0gNzIyOwogICAgdC5BcmluZyA9IDcyMjsKICAgIHQuT3RpbGRlID0gNzc4OwogICAgdC56ZG90YWNjZW50ID0gNTAwOwogICAgdC5FY2Fyb24gPSA2Njc7CiAgICB0LklvZ29uZWsgPSAyNzg7CiAgICB0Lmtjb21tYWFjY2VudCA9IDU1NjsKICAgIHQubWludXMgPSA1ODQ7CiAgICB0LkljaXJjdW1mbGV4ID0gMjc4OwogICAgdC5uY2Fyb24gPSA2MTE7CiAgICB0LnRjb21tYWFjY2VudCA9IDMzMzsKICAgIHQubG9naWNhbG5vdCA9IDU4NDsKICAgIHQub2RpZXJlc2lzID0gNjExOwogICAgdC51ZGllcmVzaXMgPSA2MTE7CiAgICB0Lm5vdGVxdWFsID0gNTQ5OwogICAgdC5nY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0LmV0aCA9IDYxMTsKICAgIHQuemNhcm9uID0gNTAwOwogICAgdC5uY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0Lm9uZXN1cGVyaW9yID0gMzMzOwogICAgdC5pbWFjcm9uID0gMjc4OwogICAgdC5FdXJvID0gNTU2OwogIH0pOwogIHRbIkhlbHZldGljYS1Cb2xkT2JsaXF1ZSJdID0gZ2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uICh0KSB7CiAgICB0LnNwYWNlID0gMjc4OwogICAgdC5leGNsYW0gPSAzMzM7CiAgICB0LnF1b3RlZGJsID0gNDc0OwogICAgdC5udW1iZXJzaWduID0gNTU2OwogICAgdC5kb2xsYXIgPSA1NTY7CiAgICB0LnBlcmNlbnQgPSA4ODk7CiAgICB0LmFtcGVyc2FuZCA9IDcyMjsKICAgIHQucXVvdGVyaWdodCA9IDI3ODsKICAgIHQucGFyZW5sZWZ0ID0gMzMzOwogICAgdC5wYXJlbnJpZ2h0ID0gMzMzOwogICAgdC5hc3RlcmlzayA9IDM4OTsKICAgIHQucGx1cyA9IDU4NDsKICAgIHQuY29tbWEgPSAyNzg7CiAgICB0Lmh5cGhlbiA9IDMzMzsKICAgIHQucGVyaW9kID0gMjc4OwogICAgdC5zbGFzaCA9IDI3ODsKICAgIHQuemVybyA9IDU1NjsKICAgIHQub25lID0gNTU2OwogICAgdC50d28gPSA1NTY7CiAgICB0LnRocmVlID0gNTU2OwogICAgdC5mb3VyID0gNTU2OwogICAgdC5maXZlID0gNTU2OwogICAgdC5zaXggPSA1NTY7CiAgICB0LnNldmVuID0gNTU2OwogICAgdC5laWdodCA9IDU1NjsKICAgIHQubmluZSA9IDU1NjsKICAgIHQuY29sb24gPSAzMzM7CiAgICB0LnNlbWljb2xvbiA9IDMzMzsKICAgIHQubGVzcyA9IDU4NDsKICAgIHQuZXF1YWwgPSA1ODQ7CiAgICB0LmdyZWF0ZXIgPSA1ODQ7CiAgICB0LnF1ZXN0aW9uID0gNjExOwogICAgdC5hdCA9IDk3NTsKICAgIHQuQSA9IDcyMjsKICAgIHQuQiA9IDcyMjsKICAgIHQuQyA9IDcyMjsKICAgIHQuRCA9IDcyMjsKICAgIHQuRSA9IDY2NzsKICAgIHQuRiA9IDYxMTsKICAgIHQuRyA9IDc3ODsKICAgIHQuSCA9IDcyMjsKICAgIHQuSSA9IDI3ODsKICAgIHQuSiA9IDU1NjsKICAgIHQuSyA9IDcyMjsKICAgIHQuTCA9IDYxMTsKICAgIHQuTSA9IDgzMzsKICAgIHQuTiA9IDcyMjsKICAgIHQuTyA9IDc3ODsKICAgIHQuUCA9IDY2NzsKICAgIHQuUSA9IDc3ODsKICAgIHQuUiA9IDcyMjsKICAgIHQuUyA9IDY2NzsKICAgIHQuVCA9IDYxMTsKICAgIHQuVSA9IDcyMjsKICAgIHQuViA9IDY2NzsKICAgIHQuVyA9IDk0NDsKICAgIHQuWCA9IDY2NzsKICAgIHQuWSA9IDY2NzsKICAgIHQuWiA9IDYxMTsKICAgIHQuYnJhY2tldGxlZnQgPSAzMzM7CiAgICB0LmJhY2tzbGFzaCA9IDI3ODsKICAgIHQuYnJhY2tldHJpZ2h0ID0gMzMzOwogICAgdC5hc2NpaWNpcmN1bSA9IDU4NDsKICAgIHQudW5kZXJzY29yZSA9IDU1NjsKICAgIHQucXVvdGVsZWZ0ID0gMjc4OwogICAgdC5hID0gNTU2OwogICAgdC5iID0gNjExOwogICAgdC5jID0gNTU2OwogICAgdC5kID0gNjExOwogICAgdC5lID0gNTU2OwogICAgdC5mID0gMzMzOwogICAgdC5nID0gNjExOwogICAgdC5oID0gNjExOwogICAgdC5pID0gMjc4OwogICAgdC5qID0gMjc4OwogICAgdC5rID0gNTU2OwogICAgdC5sID0gMjc4OwogICAgdC5tID0gODg5OwogICAgdC5uID0gNjExOwogICAgdC5vID0gNjExOwogICAgdC5wID0gNjExOwogICAgdC5xID0gNjExOwogICAgdC5yID0gMzg5OwogICAgdC5zID0gNTU2OwogICAgdC50ID0gMzMzOwogICAgdC51ID0gNjExOwogICAgdC52ID0gNTU2OwogICAgdC53ID0gNzc4OwogICAgdC54ID0gNTU2OwogICAgdC55ID0gNTU2OwogICAgdC56ID0gNTAwOwogICAgdC5icmFjZWxlZnQgPSAzODk7CiAgICB0LmJhciA9IDI4MDsKICAgIHQuYnJhY2VyaWdodCA9IDM4OTsKICAgIHQuYXNjaWl0aWxkZSA9IDU4NDsKICAgIHQuZXhjbGFtZG93biA9IDMzMzsKICAgIHQuY2VudCA9IDU1NjsKICAgIHQuc3RlcmxpbmcgPSA1NTY7CiAgICB0LmZyYWN0aW9uID0gMTY3OwogICAgdC55ZW4gPSA1NTY7CiAgICB0LmZsb3JpbiA9IDU1NjsKICAgIHQuc2VjdGlvbiA9IDU1NjsKICAgIHQuY3VycmVuY3kgPSA1NTY7CiAgICB0LnF1b3Rlc2luZ2xlID0gMjM4OwogICAgdC5xdW90ZWRibGxlZnQgPSA1MDA7CiAgICB0Lmd1aWxsZW1vdGxlZnQgPSA1NTY7CiAgICB0Lmd1aWxzaW5nbGxlZnQgPSAzMzM7CiAgICB0Lmd1aWxzaW5nbHJpZ2h0ID0gMzMzOwogICAgdC5maSA9IDYxMTsKICAgIHQuZmwgPSA2MTE7CiAgICB0LmVuZGFzaCA9IDU1NjsKICAgIHQuZGFnZ2VyID0gNTU2OwogICAgdC5kYWdnZXJkYmwgPSA1NTY7CiAgICB0LnBlcmlvZGNlbnRlcmVkID0gMjc4OwogICAgdC5wYXJhZ3JhcGggPSA1NTY7CiAgICB0LmJ1bGxldCA9IDM1MDsKICAgIHQucXVvdGVzaW5nbGJhc2UgPSAyNzg7CiAgICB0LnF1b3RlZGJsYmFzZSA9IDUwMDsKICAgIHQucXVvdGVkYmxyaWdodCA9IDUwMDsKICAgIHQuZ3VpbGxlbW90cmlnaHQgPSA1NTY7CiAgICB0LmVsbGlwc2lzID0gMTAwMDsKICAgIHQucGVydGhvdXNhbmQgPSAxMDAwOwogICAgdC5xdWVzdGlvbmRvd24gPSA2MTE7CiAgICB0LmdyYXZlID0gMzMzOwogICAgdC5hY3V0ZSA9IDMzMzsKICAgIHQuY2lyY3VtZmxleCA9IDMzMzsKICAgIHQudGlsZGUgPSAzMzM7CiAgICB0Lm1hY3JvbiA9IDMzMzsKICAgIHQuYnJldmUgPSAzMzM7CiAgICB0LmRvdGFjY2VudCA9IDMzMzsKICAgIHQuZGllcmVzaXMgPSAzMzM7CiAgICB0LnJpbmcgPSAzMzM7CiAgICB0LmNlZGlsbGEgPSAzMzM7CiAgICB0Lmh1bmdhcnVtbGF1dCA9IDMzMzsKICAgIHQub2dvbmVrID0gMzMzOwogICAgdC5jYXJvbiA9IDMzMzsKICAgIHQuZW1kYXNoID0gMTAwMDsKICAgIHQuQUUgPSAxMDAwOwogICAgdC5vcmRmZW1pbmluZSA9IDM3MDsKICAgIHQuTHNsYXNoID0gNjExOwogICAgdC5Pc2xhc2ggPSA3Nzg7CiAgICB0Lk9FID0gMTAwMDsKICAgIHQub3JkbWFzY3VsaW5lID0gMzY1OwogICAgdC5hZSA9IDg4OTsKICAgIHQuZG90bGVzc2kgPSAyNzg7CiAgICB0LmxzbGFzaCA9IDI3ODsKICAgIHQub3NsYXNoID0gNjExOwogICAgdC5vZSA9IDk0NDsKICAgIHQuZ2VybWFuZGJscyA9IDYxMTsKICAgIHQuSWRpZXJlc2lzID0gMjc4OwogICAgdC5lYWN1dGUgPSA1NTY7CiAgICB0LmFicmV2ZSA9IDU1NjsKICAgIHQudWh1bmdhcnVtbGF1dCA9IDYxMTsKICAgIHQuZWNhcm9uID0gNTU2OwogICAgdC5ZZGllcmVzaXMgPSA2Njc7CiAgICB0LmRpdmlkZSA9IDU4NDsKICAgIHQuWWFjdXRlID0gNjY3OwogICAgdC5BY2lyY3VtZmxleCA9IDcyMjsKICAgIHQuYWFjdXRlID0gNTU2OwogICAgdC5VY2lyY3VtZmxleCA9IDcyMjsKICAgIHQueWFjdXRlID0gNTU2OwogICAgdC5zY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0LmVjaXJjdW1mbGV4ID0gNTU2OwogICAgdC5VcmluZyA9IDcyMjsKICAgIHQuVWRpZXJlc2lzID0gNzIyOwogICAgdC5hb2dvbmVrID0gNTU2OwogICAgdC5VYWN1dGUgPSA3MjI7CiAgICB0LnVvZ29uZWsgPSA2MTE7CiAgICB0LkVkaWVyZXNpcyA9IDY2NzsKICAgIHQuRGNyb2F0ID0gNzIyOwogICAgdC5jb21tYWFjY2VudCA9IDI1MDsKICAgIHQuY29weXJpZ2h0ID0gNzM3OwogICAgdC5FbWFjcm9uID0gNjY3OwogICAgdC5jY2Fyb24gPSA1NTY7CiAgICB0LmFyaW5nID0gNTU2OwogICAgdC5OY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LmxhY3V0ZSA9IDI3ODsKICAgIHQuYWdyYXZlID0gNTU2OwogICAgdC5UY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0LkNhY3V0ZSA9IDcyMjsKICAgIHQuYXRpbGRlID0gNTU2OwogICAgdC5FZG90YWNjZW50ID0gNjY3OwogICAgdC5zY2Fyb24gPSA1NTY7CiAgICB0LnNjZWRpbGxhID0gNTU2OwogICAgdC5pYWN1dGUgPSAyNzg7CiAgICB0LmxvemVuZ2UgPSA0OTQ7CiAgICB0LlJjYXJvbiA9IDcyMjsKICAgIHQuR2NvbW1hYWNjZW50ID0gNzc4OwogICAgdC51Y2lyY3VtZmxleCA9IDYxMTsKICAgIHQuYWNpcmN1bWZsZXggPSA1NTY7CiAgICB0LkFtYWNyb24gPSA3MjI7CiAgICB0LnJjYXJvbiA9IDM4OTsKICAgIHQuY2NlZGlsbGEgPSA1NTY7CiAgICB0Llpkb3RhY2NlbnQgPSA2MTE7CiAgICB0LlRob3JuID0gNjY3OwogICAgdC5PbWFjcm9uID0gNzc4OwogICAgdC5SYWN1dGUgPSA3MjI7CiAgICB0LlNhY3V0ZSA9IDY2NzsKICAgIHQuZGNhcm9uID0gNzQzOwogICAgdC5VbWFjcm9uID0gNzIyOwogICAgdC51cmluZyA9IDYxMTsKICAgIHQudGhyZWVzdXBlcmlvciA9IDMzMzsKICAgIHQuT2dyYXZlID0gNzc4OwogICAgdC5BZ3JhdmUgPSA3MjI7CiAgICB0LkFicmV2ZSA9IDcyMjsKICAgIHQubXVsdGlwbHkgPSA1ODQ7CiAgICB0LnVhY3V0ZSA9IDYxMTsKICAgIHQuVGNhcm9uID0gNjExOwogICAgdC5wYXJ0aWFsZGlmZiA9IDQ5NDsKICAgIHQueWRpZXJlc2lzID0gNTU2OwogICAgdC5OYWN1dGUgPSA3MjI7CiAgICB0LmljaXJjdW1mbGV4ID0gMjc4OwogICAgdC5FY2lyY3VtZmxleCA9IDY2NzsKICAgIHQuYWRpZXJlc2lzID0gNTU2OwogICAgdC5lZGllcmVzaXMgPSA1NTY7CiAgICB0LmNhY3V0ZSA9IDU1NjsKICAgIHQubmFjdXRlID0gNjExOwogICAgdC51bWFjcm9uID0gNjExOwogICAgdC5OY2Fyb24gPSA3MjI7CiAgICB0LklhY3V0ZSA9IDI3ODsKICAgIHQucGx1c21pbnVzID0gNTg0OwogICAgdC5icm9rZW5iYXIgPSAyODA7CiAgICB0LnJlZ2lzdGVyZWQgPSA3Mzc7CiAgICB0LkdicmV2ZSA9IDc3ODsKICAgIHQuSWRvdGFjY2VudCA9IDI3ODsKICAgIHQuc3VtbWF0aW9uID0gNjAwOwogICAgdC5FZ3JhdmUgPSA2Njc7CiAgICB0LnJhY3V0ZSA9IDM4OTsKICAgIHQub21hY3JvbiA9IDYxMTsKICAgIHQuWmFjdXRlID0gNjExOwogICAgdC5aY2Fyb24gPSA2MTE7CiAgICB0LmdyZWF0ZXJlcXVhbCA9IDU0OTsKICAgIHQuRXRoID0gNzIyOwogICAgdC5DY2VkaWxsYSA9IDcyMjsKICAgIHQubGNvbW1hYWNjZW50ID0gMjc4OwogICAgdC50Y2Fyb24gPSAzODk7CiAgICB0LmVvZ29uZWsgPSA1NTY7CiAgICB0LlVvZ29uZWsgPSA3MjI7CiAgICB0LkFhY3V0ZSA9IDcyMjsKICAgIHQuQWRpZXJlc2lzID0gNzIyOwogICAgdC5lZ3JhdmUgPSA1NTY7CiAgICB0LnphY3V0ZSA9IDUwMDsKICAgIHQuaW9nb25layA9IDI3ODsKICAgIHQuT2FjdXRlID0gNzc4OwogICAgdC5vYWN1dGUgPSA2MTE7CiAgICB0LmFtYWNyb24gPSA1NTY7CiAgICB0LnNhY3V0ZSA9IDU1NjsKICAgIHQuaWRpZXJlc2lzID0gMjc4OwogICAgdC5PY2lyY3VtZmxleCA9IDc3ODsKICAgIHQuVWdyYXZlID0gNzIyOwogICAgdC5EZWx0YSA9IDYxMjsKICAgIHQudGhvcm4gPSA2MTE7CiAgICB0LnR3b3N1cGVyaW9yID0gMzMzOwogICAgdC5PZGllcmVzaXMgPSA3Nzg7CiAgICB0Lm11ID0gNjExOwogICAgdC5pZ3JhdmUgPSAyNzg7CiAgICB0Lm9odW5nYXJ1bWxhdXQgPSA2MTE7CiAgICB0LkVvZ29uZWsgPSA2Njc7CiAgICB0LmRjcm9hdCA9IDYxMTsKICAgIHQudGhyZWVxdWFydGVycyA9IDgzNDsKICAgIHQuU2NlZGlsbGEgPSA2Njc7CiAgICB0LmxjYXJvbiA9IDQwMDsKICAgIHQuS2NvbW1hYWNjZW50ID0gNzIyOwogICAgdC5MYWN1dGUgPSA2MTE7CiAgICB0LnRyYWRlbWFyayA9IDEwMDA7CiAgICB0LmVkb3RhY2NlbnQgPSA1NTY7CiAgICB0LklncmF2ZSA9IDI3ODsKICAgIHQuSW1hY3JvbiA9IDI3ODsKICAgIHQuTGNhcm9uID0gNjExOwogICAgdC5vbmVoYWxmID0gODM0OwogICAgdC5sZXNzZXF1YWwgPSA1NDk7CiAgICB0Lm9jaXJjdW1mbGV4ID0gNjExOwogICAgdC5udGlsZGUgPSA2MTE7CiAgICB0LlVodW5nYXJ1bWxhdXQgPSA3MjI7CiAgICB0LkVhY3V0ZSA9IDY2NzsKICAgIHQuZW1hY3JvbiA9IDU1NjsKICAgIHQuZ2JyZXZlID0gNjExOwogICAgdC5vbmVxdWFydGVyID0gODM0OwogICAgdC5TY2Fyb24gPSA2Njc7CiAgICB0LlNjb21tYWFjY2VudCA9IDY2NzsKICAgIHQuT2h1bmdhcnVtbGF1dCA9IDc3ODsKICAgIHQuZGVncmVlID0gNDAwOwogICAgdC5vZ3JhdmUgPSA2MTE7CiAgICB0LkNjYXJvbiA9IDcyMjsKICAgIHQudWdyYXZlID0gNjExOwogICAgdC5yYWRpY2FsID0gNTQ5OwogICAgdC5EY2Fyb24gPSA3MjI7CiAgICB0LnJjb21tYWFjY2VudCA9IDM4OTsKICAgIHQuTnRpbGRlID0gNzIyOwogICAgdC5vdGlsZGUgPSA2MTE7CiAgICB0LlJjb21tYWFjY2VudCA9IDcyMjsKICAgIHQuTGNvbW1hYWNjZW50ID0gNjExOwogICAgdC5BdGlsZGUgPSA3MjI7CiAgICB0LkFvZ29uZWsgPSA3MjI7CiAgICB0LkFyaW5nID0gNzIyOwogICAgdC5PdGlsZGUgPSA3Nzg7CiAgICB0Lnpkb3RhY2NlbnQgPSA1MDA7CiAgICB0LkVjYXJvbiA9IDY2NzsKICAgIHQuSW9nb25layA9IDI3ODsKICAgIHQua2NvbW1hYWNjZW50ID0gNTU2OwogICAgdC5taW51cyA9IDU4NDsKICAgIHQuSWNpcmN1bWZsZXggPSAyNzg7CiAgICB0Lm5jYXJvbiA9IDYxMTsKICAgIHQudGNvbW1hYWNjZW50ID0gMzMzOwogICAgdC5sb2dpY2Fsbm90ID0gNTg0OwogICAgdC5vZGllcmVzaXMgPSA2MTE7CiAgICB0LnVkaWVyZXNpcyA9IDYxMTsKICAgIHQubm90ZXF1YWwgPSA1NDk7CiAgICB0Lmdjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuZXRoID0gNjExOwogICAgdC56Y2Fyb24gPSA1MDA7CiAgICB0Lm5jb21tYWFjY2VudCA9IDYxMTsKICAgIHQub25lc3VwZXJpb3IgPSAzMzM7CiAgICB0LmltYWNyb24gPSAyNzg7CiAgICB0LkV1cm8gPSA1NTY7CiAgfSk7CiAgdFsiSGVsdmV0aWNhLU9ibGlxdWUiXSA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogICAgdC5zcGFjZSA9IDI3ODsKICAgIHQuZXhjbGFtID0gMjc4OwogICAgdC5xdW90ZWRibCA9IDM1NTsKICAgIHQubnVtYmVyc2lnbiA9IDU1NjsKICAgIHQuZG9sbGFyID0gNTU2OwogICAgdC5wZXJjZW50ID0gODg5OwogICAgdC5hbXBlcnNhbmQgPSA2Njc7CiAgICB0LnF1b3RlcmlnaHQgPSAyMjI7CiAgICB0LnBhcmVubGVmdCA9IDMzMzsKICAgIHQucGFyZW5yaWdodCA9IDMzMzsKICAgIHQuYXN0ZXJpc2sgPSAzODk7CiAgICB0LnBsdXMgPSA1ODQ7CiAgICB0LmNvbW1hID0gMjc4OwogICAgdC5oeXBoZW4gPSAzMzM7CiAgICB0LnBlcmlvZCA9IDI3ODsKICAgIHQuc2xhc2ggPSAyNzg7CiAgICB0Lnplcm8gPSA1NTY7CiAgICB0Lm9uZSA9IDU1NjsKICAgIHQudHdvID0gNTU2OwogICAgdC50aHJlZSA9IDU1NjsKICAgIHQuZm91ciA9IDU1NjsKICAgIHQuZml2ZSA9IDU1NjsKICAgIHQuc2l4ID0gNTU2OwogICAgdC5zZXZlbiA9IDU1NjsKICAgIHQuZWlnaHQgPSA1NTY7CiAgICB0Lm5pbmUgPSA1NTY7CiAgICB0LmNvbG9uID0gMjc4OwogICAgdC5zZW1pY29sb24gPSAyNzg7CiAgICB0Lmxlc3MgPSA1ODQ7CiAgICB0LmVxdWFsID0gNTg0OwogICAgdC5ncmVhdGVyID0gNTg0OwogICAgdC5xdWVzdGlvbiA9IDU1NjsKICAgIHQuYXQgPSAxMDE1OwogICAgdC5BID0gNjY3OwogICAgdC5CID0gNjY3OwogICAgdC5DID0gNzIyOwogICAgdC5EID0gNzIyOwogICAgdC5FID0gNjY3OwogICAgdC5GID0gNjExOwogICAgdC5HID0gNzc4OwogICAgdC5IID0gNzIyOwogICAgdC5JID0gMjc4OwogICAgdC5KID0gNTAwOwogICAgdC5LID0gNjY3OwogICAgdC5MID0gNTU2OwogICAgdC5NID0gODMzOwogICAgdC5OID0gNzIyOwogICAgdC5PID0gNzc4OwogICAgdC5QID0gNjY3OwogICAgdC5RID0gNzc4OwogICAgdC5SID0gNzIyOwogICAgdC5TID0gNjY3OwogICAgdC5UID0gNjExOwogICAgdC5VID0gNzIyOwogICAgdC5WID0gNjY3OwogICAgdC5XID0gOTQ0OwogICAgdC5YID0gNjY3OwogICAgdC5ZID0gNjY3OwogICAgdC5aID0gNjExOwogICAgdC5icmFja2V0bGVmdCA9IDI3ODsKICAgIHQuYmFja3NsYXNoID0gMjc4OwogICAgdC5icmFja2V0cmlnaHQgPSAyNzg7CiAgICB0LmFzY2lpY2lyY3VtID0gNDY5OwogICAgdC51bmRlcnNjb3JlID0gNTU2OwogICAgdC5xdW90ZWxlZnQgPSAyMjI7CiAgICB0LmEgPSA1NTY7CiAgICB0LmIgPSA1NTY7CiAgICB0LmMgPSA1MDA7CiAgICB0LmQgPSA1NTY7CiAgICB0LmUgPSA1NTY7CiAgICB0LmYgPSAyNzg7CiAgICB0LmcgPSA1NTY7CiAgICB0LmggPSA1NTY7CiAgICB0LmkgPSAyMjI7CiAgICB0LmogPSAyMjI7CiAgICB0LmsgPSA1MDA7CiAgICB0LmwgPSAyMjI7CiAgICB0Lm0gPSA4MzM7CiAgICB0Lm4gPSA1NTY7CiAgICB0Lm8gPSA1NTY7CiAgICB0LnAgPSA1NTY7CiAgICB0LnEgPSA1NTY7CiAgICB0LnIgPSAzMzM7CiAgICB0LnMgPSA1MDA7CiAgICB0LnQgPSAyNzg7CiAgICB0LnUgPSA1NTY7CiAgICB0LnYgPSA1MDA7CiAgICB0LncgPSA3MjI7CiAgICB0LnggPSA1MDA7CiAgICB0LnkgPSA1MDA7CiAgICB0LnogPSA1MDA7CiAgICB0LmJyYWNlbGVmdCA9IDMzNDsKICAgIHQuYmFyID0gMjYwOwogICAgdC5icmFjZXJpZ2h0ID0gMzM0OwogICAgdC5hc2NpaXRpbGRlID0gNTg0OwogICAgdC5leGNsYW1kb3duID0gMzMzOwogICAgdC5jZW50ID0gNTU2OwogICAgdC5zdGVybGluZyA9IDU1NjsKICAgIHQuZnJhY3Rpb24gPSAxNjc7CiAgICB0LnllbiA9IDU1NjsKICAgIHQuZmxvcmluID0gNTU2OwogICAgdC5zZWN0aW9uID0gNTU2OwogICAgdC5jdXJyZW5jeSA9IDU1NjsKICAgIHQucXVvdGVzaW5nbGUgPSAxOTE7CiAgICB0LnF1b3RlZGJsbGVmdCA9IDMzMzsKICAgIHQuZ3VpbGxlbW90bGVmdCA9IDU1NjsKICAgIHQuZ3VpbHNpbmdsbGVmdCA9IDMzMzsKICAgIHQuZ3VpbHNpbmdscmlnaHQgPSAzMzM7CiAgICB0LmZpID0gNTAwOwogICAgdC5mbCA9IDUwMDsKICAgIHQuZW5kYXNoID0gNTU2OwogICAgdC5kYWdnZXIgPSA1NTY7CiAgICB0LmRhZ2dlcmRibCA9IDU1NjsKICAgIHQucGVyaW9kY2VudGVyZWQgPSAyNzg7CiAgICB0LnBhcmFncmFwaCA9IDUzNzsKICAgIHQuYnVsbGV0ID0gMzUwOwogICAgdC5xdW90ZXNpbmdsYmFzZSA9IDIyMjsKICAgIHQucXVvdGVkYmxiYXNlID0gMzMzOwogICAgdC5xdW90ZWRibHJpZ2h0ID0gMzMzOwogICAgdC5ndWlsbGVtb3RyaWdodCA9IDU1NjsKICAgIHQuZWxsaXBzaXMgPSAxMDAwOwogICAgdC5wZXJ0aG91c2FuZCA9IDEwMDA7CiAgICB0LnF1ZXN0aW9uZG93biA9IDYxMTsKICAgIHQuZ3JhdmUgPSAzMzM7CiAgICB0LmFjdXRlID0gMzMzOwogICAgdC5jaXJjdW1mbGV4ID0gMzMzOwogICAgdC50aWxkZSA9IDMzMzsKICAgIHQubWFjcm9uID0gMzMzOwogICAgdC5icmV2ZSA9IDMzMzsKICAgIHQuZG90YWNjZW50ID0gMzMzOwogICAgdC5kaWVyZXNpcyA9IDMzMzsKICAgIHQucmluZyA9IDMzMzsKICAgIHQuY2VkaWxsYSA9IDMzMzsKICAgIHQuaHVuZ2FydW1sYXV0ID0gMzMzOwogICAgdC5vZ29uZWsgPSAzMzM7CiAgICB0LmNhcm9uID0gMzMzOwogICAgdC5lbWRhc2ggPSAxMDAwOwogICAgdC5BRSA9IDEwMDA7CiAgICB0Lm9yZGZlbWluaW5lID0gMzcwOwogICAgdC5Mc2xhc2ggPSA1NTY7CiAgICB0Lk9zbGFzaCA9IDc3ODsKICAgIHQuT0UgPSAxMDAwOwogICAgdC5vcmRtYXNjdWxpbmUgPSAzNjU7CiAgICB0LmFlID0gODg5OwogICAgdC5kb3RsZXNzaSA9IDI3ODsKICAgIHQubHNsYXNoID0gMjIyOwogICAgdC5vc2xhc2ggPSA2MTE7CiAgICB0Lm9lID0gOTQ0OwogICAgdC5nZXJtYW5kYmxzID0gNjExOwogICAgdC5JZGllcmVzaXMgPSAyNzg7CiAgICB0LmVhY3V0ZSA9IDU1NjsKICAgIHQuYWJyZXZlID0gNTU2OwogICAgdC51aHVuZ2FydW1sYXV0ID0gNTU2OwogICAgdC5lY2Fyb24gPSA1NTY7CiAgICB0LllkaWVyZXNpcyA9IDY2NzsKICAgIHQuZGl2aWRlID0gNTg0OwogICAgdC5ZYWN1dGUgPSA2Njc7CiAgICB0LkFjaXJjdW1mbGV4ID0gNjY3OwogICAgdC5hYWN1dGUgPSA1NTY7CiAgICB0LlVjaXJjdW1mbGV4ID0gNzIyOwogICAgdC55YWN1dGUgPSA1MDA7CiAgICB0LnNjb21tYWFjY2VudCA9IDUwMDsKICAgIHQuZWNpcmN1bWZsZXggPSA1NTY7CiAgICB0LlVyaW5nID0gNzIyOwogICAgdC5VZGllcmVzaXMgPSA3MjI7CiAgICB0LmFvZ29uZWsgPSA1NTY7CiAgICB0LlVhY3V0ZSA9IDcyMjsKICAgIHQudW9nb25layA9IDU1NjsKICAgIHQuRWRpZXJlc2lzID0gNjY3OwogICAgdC5EY3JvYXQgPSA3MjI7CiAgICB0LmNvbW1hYWNjZW50ID0gMjUwOwogICAgdC5jb3B5cmlnaHQgPSA3Mzc7CiAgICB0LkVtYWNyb24gPSA2Njc7CiAgICB0LmNjYXJvbiA9IDUwMDsKICAgIHQuYXJpbmcgPSA1NTY7CiAgICB0Lk5jb21tYWFjY2VudCA9IDcyMjsKICAgIHQubGFjdXRlID0gMjIyOwogICAgdC5hZ3JhdmUgPSA1NTY7CiAgICB0LlRjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuQ2FjdXRlID0gNzIyOwogICAgdC5hdGlsZGUgPSA1NTY7CiAgICB0LkVkb3RhY2NlbnQgPSA2Njc7CiAgICB0LnNjYXJvbiA9IDUwMDsKICAgIHQuc2NlZGlsbGEgPSA1MDA7CiAgICB0LmlhY3V0ZSA9IDI3ODsKICAgIHQubG96ZW5nZSA9IDQ3MTsKICAgIHQuUmNhcm9uID0gNzIyOwogICAgdC5HY29tbWFhY2NlbnQgPSA3Nzg7CiAgICB0LnVjaXJjdW1mbGV4ID0gNTU2OwogICAgdC5hY2lyY3VtZmxleCA9IDU1NjsKICAgIHQuQW1hY3JvbiA9IDY2NzsKICAgIHQucmNhcm9uID0gMzMzOwogICAgdC5jY2VkaWxsYSA9IDUwMDsKICAgIHQuWmRvdGFjY2VudCA9IDYxMTsKICAgIHQuVGhvcm4gPSA2Njc7CiAgICB0Lk9tYWNyb24gPSA3Nzg7CiAgICB0LlJhY3V0ZSA9IDcyMjsKICAgIHQuU2FjdXRlID0gNjY3OwogICAgdC5kY2Fyb24gPSA2NDM7CiAgICB0LlVtYWNyb24gPSA3MjI7CiAgICB0LnVyaW5nID0gNTU2OwogICAgdC50aHJlZXN1cGVyaW9yID0gMzMzOwogICAgdC5PZ3JhdmUgPSA3Nzg7CiAgICB0LkFncmF2ZSA9IDY2NzsKICAgIHQuQWJyZXZlID0gNjY3OwogICAgdC5tdWx0aXBseSA9IDU4NDsKICAgIHQudWFjdXRlID0gNTU2OwogICAgdC5UY2Fyb24gPSA2MTE7CiAgICB0LnBhcnRpYWxkaWZmID0gNDc2OwogICAgdC55ZGllcmVzaXMgPSA1MDA7CiAgICB0Lk5hY3V0ZSA9IDcyMjsKICAgIHQuaWNpcmN1bWZsZXggPSAyNzg7CiAgICB0LkVjaXJjdW1mbGV4ID0gNjY3OwogICAgdC5hZGllcmVzaXMgPSA1NTY7CiAgICB0LmVkaWVyZXNpcyA9IDU1NjsKICAgIHQuY2FjdXRlID0gNTAwOwogICAgdC5uYWN1dGUgPSA1NTY7CiAgICB0LnVtYWNyb24gPSA1NTY7CiAgICB0Lk5jYXJvbiA9IDcyMjsKICAgIHQuSWFjdXRlID0gMjc4OwogICAgdC5wbHVzbWludXMgPSA1ODQ7CiAgICB0LmJyb2tlbmJhciA9IDI2MDsKICAgIHQucmVnaXN0ZXJlZCA9IDczNzsKICAgIHQuR2JyZXZlID0gNzc4OwogICAgdC5JZG90YWNjZW50ID0gMjc4OwogICAgdC5zdW1tYXRpb24gPSA2MDA7CiAgICB0LkVncmF2ZSA9IDY2NzsKICAgIHQucmFjdXRlID0gMzMzOwogICAgdC5vbWFjcm9uID0gNTU2OwogICAgdC5aYWN1dGUgPSA2MTE7CiAgICB0LlpjYXJvbiA9IDYxMTsKICAgIHQuZ3JlYXRlcmVxdWFsID0gNTQ5OwogICAgdC5FdGggPSA3MjI7CiAgICB0LkNjZWRpbGxhID0gNzIyOwogICAgdC5sY29tbWFhY2NlbnQgPSAyMjI7CiAgICB0LnRjYXJvbiA9IDMxNzsKICAgIHQuZW9nb25layA9IDU1NjsKICAgIHQuVW9nb25layA9IDcyMjsKICAgIHQuQWFjdXRlID0gNjY3OwogICAgdC5BZGllcmVzaXMgPSA2Njc7CiAgICB0LmVncmF2ZSA9IDU1NjsKICAgIHQuemFjdXRlID0gNTAwOwogICAgdC5pb2dvbmVrID0gMjIyOwogICAgdC5PYWN1dGUgPSA3Nzg7CiAgICB0Lm9hY3V0ZSA9IDU1NjsKICAgIHQuYW1hY3JvbiA9IDU1NjsKICAgIHQuc2FjdXRlID0gNTAwOwogICAgdC5pZGllcmVzaXMgPSAyNzg7CiAgICB0Lk9jaXJjdW1mbGV4ID0gNzc4OwogICAgdC5VZ3JhdmUgPSA3MjI7CiAgICB0LkRlbHRhID0gNjEyOwogICAgdC50aG9ybiA9IDU1NjsKICAgIHQudHdvc3VwZXJpb3IgPSAzMzM7CiAgICB0Lk9kaWVyZXNpcyA9IDc3ODsKICAgIHQubXUgPSA1NTY7CiAgICB0LmlncmF2ZSA9IDI3ODsKICAgIHQub2h1bmdhcnVtbGF1dCA9IDU1NjsKICAgIHQuRW9nb25layA9IDY2NzsKICAgIHQuZGNyb2F0ID0gNTU2OwogICAgdC50aHJlZXF1YXJ0ZXJzID0gODM0OwogICAgdC5TY2VkaWxsYSA9IDY2NzsKICAgIHQubGNhcm9uID0gMjk5OwogICAgdC5LY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0LkxhY3V0ZSA9IDU1NjsKICAgIHQudHJhZGVtYXJrID0gMTAwMDsKICAgIHQuZWRvdGFjY2VudCA9IDU1NjsKICAgIHQuSWdyYXZlID0gMjc4OwogICAgdC5JbWFjcm9uID0gMjc4OwogICAgdC5MY2Fyb24gPSA1NTY7CiAgICB0Lm9uZWhhbGYgPSA4MzQ7CiAgICB0Lmxlc3NlcXVhbCA9IDU0OTsKICAgIHQub2NpcmN1bWZsZXggPSA1NTY7CiAgICB0Lm50aWxkZSA9IDU1NjsKICAgIHQuVWh1bmdhcnVtbGF1dCA9IDcyMjsKICAgIHQuRWFjdXRlID0gNjY3OwogICAgdC5lbWFjcm9uID0gNTU2OwogICAgdC5nYnJldmUgPSA1NTY7CiAgICB0Lm9uZXF1YXJ0ZXIgPSA4MzQ7CiAgICB0LlNjYXJvbiA9IDY2NzsKICAgIHQuU2NvbW1hYWNjZW50ID0gNjY3OwogICAgdC5PaHVuZ2FydW1sYXV0ID0gNzc4OwogICAgdC5kZWdyZWUgPSA0MDA7CiAgICB0Lm9ncmF2ZSA9IDU1NjsKICAgIHQuQ2Nhcm9uID0gNzIyOwogICAgdC51Z3JhdmUgPSA1NTY7CiAgICB0LnJhZGljYWwgPSA0NTM7CiAgICB0LkRjYXJvbiA9IDcyMjsKICAgIHQucmNvbW1hYWNjZW50ID0gMzMzOwogICAgdC5OdGlsZGUgPSA3MjI7CiAgICB0Lm90aWxkZSA9IDU1NjsKICAgIHQuUmNvbW1hYWNjZW50ID0gNzIyOwogICAgdC5MY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0LkF0aWxkZSA9IDY2NzsKICAgIHQuQW9nb25layA9IDY2NzsKICAgIHQuQXJpbmcgPSA2Njc7CiAgICB0Lk90aWxkZSA9IDc3ODsKICAgIHQuemRvdGFjY2VudCA9IDUwMDsKICAgIHQuRWNhcm9uID0gNjY3OwogICAgdC5Jb2dvbmVrID0gMjc4OwogICAgdC5rY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0Lm1pbnVzID0gNTg0OwogICAgdC5JY2lyY3VtZmxleCA9IDI3ODsKICAgIHQubmNhcm9uID0gNTU2OwogICAgdC50Y29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LmxvZ2ljYWxub3QgPSA1ODQ7CiAgICB0Lm9kaWVyZXNpcyA9IDU1NjsKICAgIHQudWRpZXJlc2lzID0gNTU2OwogICAgdC5ub3RlcXVhbCA9IDU0OTsKICAgIHQuZ2NvbW1hYWNjZW50ID0gNTU2OwogICAgdC5ldGggPSA1NTY7CiAgICB0LnpjYXJvbiA9IDUwMDsKICAgIHQubmNvbW1hYWNjZW50ID0gNTU2OwogICAgdC5vbmVzdXBlcmlvciA9IDMzMzsKICAgIHQuaW1hY3JvbiA9IDI3ODsKICAgIHQuRXVybyA9IDU1NjsKICB9KTsKICB0LlN5bWJvbCA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogICAgdC5zcGFjZSA9IDI1MDsKICAgIHQuZXhjbGFtID0gMzMzOwogICAgdC51bml2ZXJzYWwgPSA3MTM7CiAgICB0Lm51bWJlcnNpZ24gPSA1MDA7CiAgICB0LmV4aXN0ZW50aWFsID0gNTQ5OwogICAgdC5wZXJjZW50ID0gODMzOwogICAgdC5hbXBlcnNhbmQgPSA3Nzg7CiAgICB0LnN1Y2h0aGF0ID0gNDM5OwogICAgdC5wYXJlbmxlZnQgPSAzMzM7CiAgICB0LnBhcmVucmlnaHQgPSAzMzM7CiAgICB0LmFzdGVyaXNrbWF0aCA9IDUwMDsKICAgIHQucGx1cyA9IDU0OTsKICAgIHQuY29tbWEgPSAyNTA7CiAgICB0Lm1pbnVzID0gNTQ5OwogICAgdC5wZXJpb2QgPSAyNTA7CiAgICB0LnNsYXNoID0gMjc4OwogICAgdC56ZXJvID0gNTAwOwogICAgdC5vbmUgPSA1MDA7CiAgICB0LnR3byA9IDUwMDsKICAgIHQudGhyZWUgPSA1MDA7CiAgICB0LmZvdXIgPSA1MDA7CiAgICB0LmZpdmUgPSA1MDA7CiAgICB0LnNpeCA9IDUwMDsKICAgIHQuc2V2ZW4gPSA1MDA7CiAgICB0LmVpZ2h0ID0gNTAwOwogICAgdC5uaW5lID0gNTAwOwogICAgdC5jb2xvbiA9IDI3ODsKICAgIHQuc2VtaWNvbG9uID0gMjc4OwogICAgdC5sZXNzID0gNTQ5OwogICAgdC5lcXVhbCA9IDU0OTsKICAgIHQuZ3JlYXRlciA9IDU0OTsKICAgIHQucXVlc3Rpb24gPSA0NDQ7CiAgICB0LmNvbmdydWVudCA9IDU0OTsKICAgIHQuQWxwaGEgPSA3MjI7CiAgICB0LkJldGEgPSA2Njc7CiAgICB0LkNoaSA9IDcyMjsKICAgIHQuRGVsdGEgPSA2MTI7CiAgICB0LkVwc2lsb24gPSA2MTE7CiAgICB0LlBoaSA9IDc2MzsKICAgIHQuR2FtbWEgPSA2MDM7CiAgICB0LkV0YSA9IDcyMjsKICAgIHQuSW90YSA9IDMzMzsKICAgIHQudGhldGExID0gNjMxOwogICAgdC5LYXBwYSA9IDcyMjsKICAgIHQuTGFtYmRhID0gNjg2OwogICAgdC5NdSA9IDg4OTsKICAgIHQuTnUgPSA3MjI7CiAgICB0Lk9taWNyb24gPSA3MjI7CiAgICB0LlBpID0gNzY4OwogICAgdC5UaGV0YSA9IDc0MTsKICAgIHQuUmhvID0gNTU2OwogICAgdC5TaWdtYSA9IDU5MjsKICAgIHQuVGF1ID0gNjExOwogICAgdC5VcHNpbG9uID0gNjkwOwogICAgdC5zaWdtYTEgPSA0Mzk7CiAgICB0Lk9tZWdhID0gNzY4OwogICAgdC5YaSA9IDY0NTsKICAgIHQuUHNpID0gNzk1OwogICAgdC5aZXRhID0gNjExOwogICAgdC5icmFja2V0bGVmdCA9IDMzMzsKICAgIHQudGhlcmVmb3JlID0gODYzOwogICAgdC5icmFja2V0cmlnaHQgPSAzMzM7CiAgICB0LnBlcnBlbmRpY3VsYXIgPSA2NTg7CiAgICB0LnVuZGVyc2NvcmUgPSA1MDA7CiAgICB0LnJhZGljYWxleCA9IDUwMDsKICAgIHQuYWxwaGEgPSA2MzE7CiAgICB0LmJldGEgPSA1NDk7CiAgICB0LmNoaSA9IDU0OTsKICAgIHQuZGVsdGEgPSA0OTQ7CiAgICB0LmVwc2lsb24gPSA0Mzk7CiAgICB0LnBoaSA9IDUyMTsKICAgIHQuZ2FtbWEgPSA0MTE7CiAgICB0LmV0YSA9IDYwMzsKICAgIHQuaW90YSA9IDMyOTsKICAgIHQucGhpMSA9IDYwMzsKICAgIHQua2FwcGEgPSA1NDk7CiAgICB0LmxhbWJkYSA9IDU0OTsKICAgIHQubXUgPSA1NzY7CiAgICB0Lm51ID0gNTIxOwogICAgdC5vbWljcm9uID0gNTQ5OwogICAgdC5waSA9IDU0OTsKICAgIHQudGhldGEgPSA1MjE7CiAgICB0LnJobyA9IDU0OTsKICAgIHQuc2lnbWEgPSA2MDM7CiAgICB0LnRhdSA9IDQzOTsKICAgIHQudXBzaWxvbiA9IDU3NjsKICAgIHQub21lZ2ExID0gNzEzOwogICAgdC5vbWVnYSA9IDY4NjsKICAgIHQueGkgPSA0OTM7CiAgICB0LnBzaSA9IDY4NjsKICAgIHQuemV0YSA9IDQ5NDsKICAgIHQuYnJhY2VsZWZ0ID0gNDgwOwogICAgdC5iYXIgPSAyMDA7CiAgICB0LmJyYWNlcmlnaHQgPSA0ODA7CiAgICB0LnNpbWlsYXIgPSA1NDk7CiAgICB0LkV1cm8gPSA3NTA7CiAgICB0LlVwc2lsb24xID0gNjIwOwogICAgdC5taW51dGUgPSAyNDc7CiAgICB0Lmxlc3NlcXVhbCA9IDU0OTsKICAgIHQuZnJhY3Rpb24gPSAxNjc7CiAgICB0LmluZmluaXR5ID0gNzEzOwogICAgdC5mbG9yaW4gPSA1MDA7CiAgICB0LmNsdWIgPSA3NTM7CiAgICB0LmRpYW1vbmQgPSA3NTM7CiAgICB0LmhlYXJ0ID0gNzUzOwogICAgdC5zcGFkZSA9IDc1MzsKICAgIHQuYXJyb3dib3RoID0gMTA0MjsKICAgIHQuYXJyb3dsZWZ0ID0gOTg3OwogICAgdC5hcnJvd3VwID0gNjAzOwogICAgdC5hcnJvd3JpZ2h0ID0gOTg3OwogICAgdC5hcnJvd2Rvd24gPSA2MDM7CiAgICB0LmRlZ3JlZSA9IDQwMDsKICAgIHQucGx1c21pbnVzID0gNTQ5OwogICAgdC5zZWNvbmQgPSA0MTE7CiAgICB0LmdyZWF0ZXJlcXVhbCA9IDU0OTsKICAgIHQubXVsdGlwbHkgPSA1NDk7CiAgICB0LnByb3BvcnRpb25hbCA9IDcxMzsKICAgIHQucGFydGlhbGRpZmYgPSA0OTQ7CiAgICB0LmJ1bGxldCA9IDQ2MDsKICAgIHQuZGl2aWRlID0gNTQ5OwogICAgdC5ub3RlcXVhbCA9IDU0OTsKICAgIHQuZXF1aXZhbGVuY2UgPSA1NDk7CiAgICB0LmFwcHJveGVxdWFsID0gNTQ5OwogICAgdC5lbGxpcHNpcyA9IDEwMDA7CiAgICB0LmFycm93dmVydGV4ID0gNjAzOwogICAgdC5hcnJvd2hvcml6ZXggPSAxMDAwOwogICAgdC5jYXJyaWFnZXJldHVybiA9IDY1ODsKICAgIHQuYWxlcGggPSA4MjM7CiAgICB0LklmcmFrdHVyID0gNjg2OwogICAgdC5SZnJha3R1ciA9IDc5NTsKICAgIHQud2VpZXJzdHJhc3MgPSA5ODc7CiAgICB0LmNpcmNsZW11bHRpcGx5ID0gNzY4OwogICAgdC5jaXJjbGVwbHVzID0gNzY4OwogICAgdC5lbXB0eXNldCA9IDgyMzsKICAgIHQuaW50ZXJzZWN0aW9uID0gNzY4OwogICAgdC51bmlvbiA9IDc2ODsKICAgIHQucHJvcGVyc3VwZXJzZXQgPSA3MTM7CiAgICB0LnJlZmxleHN1cGVyc2V0ID0gNzEzOwogICAgdC5ub3RzdWJzZXQgPSA3MTM7CiAgICB0LnByb3BlcnN1YnNldCA9IDcxMzsKICAgIHQucmVmbGV4c3Vic2V0ID0gNzEzOwogICAgdC5lbGVtZW50ID0gNzEzOwogICAgdC5ub3RlbGVtZW50ID0gNzEzOwogICAgdC5hbmdsZSA9IDc2ODsKICAgIHQuZ3JhZGllbnQgPSA3MTM7CiAgICB0LnJlZ2lzdGVyc2VyaWYgPSA3OTA7CiAgICB0LmNvcHlyaWdodHNlcmlmID0gNzkwOwogICAgdC50cmFkZW1hcmtzZXJpZiA9IDg5MDsKICAgIHQucHJvZHVjdCA9IDgyMzsKICAgIHQucmFkaWNhbCA9IDU0OTsKICAgIHQuZG90bWF0aCA9IDI1MDsKICAgIHQubG9naWNhbG5vdCA9IDcxMzsKICAgIHQubG9naWNhbGFuZCA9IDYwMzsKICAgIHQubG9naWNhbG9yID0gNjAzOwogICAgdC5hcnJvd2RibGJvdGggPSAxMDQyOwogICAgdC5hcnJvd2RibGxlZnQgPSA5ODc7CiAgICB0LmFycm93ZGJsdXAgPSA2MDM7CiAgICB0LmFycm93ZGJscmlnaHQgPSA5ODc7CiAgICB0LmFycm93ZGJsZG93biA9IDYwMzsKICAgIHQubG96ZW5nZSA9IDQ5NDsKICAgIHQuYW5nbGVsZWZ0ID0gMzI5OwogICAgdC5yZWdpc3RlcnNhbnMgPSA3OTA7CiAgICB0LmNvcHlyaWdodHNhbnMgPSA3OTA7CiAgICB0LnRyYWRlbWFya3NhbnMgPSA3ODY7CiAgICB0LnN1bW1hdGlvbiA9IDcxMzsKICAgIHQucGFyZW5sZWZ0dHAgPSAzODQ7CiAgICB0LnBhcmVubGVmdGV4ID0gMzg0OwogICAgdC5wYXJlbmxlZnRidCA9IDM4NDsKICAgIHQuYnJhY2tldGxlZnR0cCA9IDM4NDsKICAgIHQuYnJhY2tldGxlZnRleCA9IDM4NDsKICAgIHQuYnJhY2tldGxlZnRidCA9IDM4NDsKICAgIHQuYnJhY2VsZWZ0dHAgPSA0OTQ7CiAgICB0LmJyYWNlbGVmdG1pZCA9IDQ5NDsKICAgIHQuYnJhY2VsZWZ0YnQgPSA0OTQ7CiAgICB0LmJyYWNlZXggPSA0OTQ7CiAgICB0LmFuZ2xlcmlnaHQgPSAzMjk7CiAgICB0LmludGVncmFsID0gMjc0OwogICAgdC5pbnRlZ3JhbHRwID0gNjg2OwogICAgdC5pbnRlZ3JhbGV4ID0gNjg2OwogICAgdC5pbnRlZ3JhbGJ0ID0gNjg2OwogICAgdC5wYXJlbnJpZ2h0dHAgPSAzODQ7CiAgICB0LnBhcmVucmlnaHRleCA9IDM4NDsKICAgIHQucGFyZW5yaWdodGJ0ID0gMzg0OwogICAgdC5icmFja2V0cmlnaHR0cCA9IDM4NDsKICAgIHQuYnJhY2tldHJpZ2h0ZXggPSAzODQ7CiAgICB0LmJyYWNrZXRyaWdodGJ0ID0gMzg0OwogICAgdC5icmFjZXJpZ2h0dHAgPSA0OTQ7CiAgICB0LmJyYWNlcmlnaHRtaWQgPSA0OTQ7CiAgICB0LmJyYWNlcmlnaHRidCA9IDQ5NDsKICAgIHQuYXBwbGUgPSA3OTA7CiAgfSk7CiAgdFsiVGltZXMtUm9tYW4iXSA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogICAgdC5zcGFjZSA9IDI1MDsKICAgIHQuZXhjbGFtID0gMzMzOwogICAgdC5xdW90ZWRibCA9IDQwODsKICAgIHQubnVtYmVyc2lnbiA9IDUwMDsKICAgIHQuZG9sbGFyID0gNTAwOwogICAgdC5wZXJjZW50ID0gODMzOwogICAgdC5hbXBlcnNhbmQgPSA3Nzg7CiAgICB0LnF1b3RlcmlnaHQgPSAzMzM7CiAgICB0LnBhcmVubGVmdCA9IDMzMzsKICAgIHQucGFyZW5yaWdodCA9IDMzMzsKICAgIHQuYXN0ZXJpc2sgPSA1MDA7CiAgICB0LnBsdXMgPSA1NjQ7CiAgICB0LmNvbW1hID0gMjUwOwogICAgdC5oeXBoZW4gPSAzMzM7CiAgICB0LnBlcmlvZCA9IDI1MDsKICAgIHQuc2xhc2ggPSAyNzg7CiAgICB0Lnplcm8gPSA1MDA7CiAgICB0Lm9uZSA9IDUwMDsKICAgIHQudHdvID0gNTAwOwogICAgdC50aHJlZSA9IDUwMDsKICAgIHQuZm91ciA9IDUwMDsKICAgIHQuZml2ZSA9IDUwMDsKICAgIHQuc2l4ID0gNTAwOwogICAgdC5zZXZlbiA9IDUwMDsKICAgIHQuZWlnaHQgPSA1MDA7CiAgICB0Lm5pbmUgPSA1MDA7CiAgICB0LmNvbG9uID0gMjc4OwogICAgdC5zZW1pY29sb24gPSAyNzg7CiAgICB0Lmxlc3MgPSA1NjQ7CiAgICB0LmVxdWFsID0gNTY0OwogICAgdC5ncmVhdGVyID0gNTY0OwogICAgdC5xdWVzdGlvbiA9IDQ0NDsKICAgIHQuYXQgPSA5MjE7CiAgICB0LkEgPSA3MjI7CiAgICB0LkIgPSA2Njc7CiAgICB0LkMgPSA2Njc7CiAgICB0LkQgPSA3MjI7CiAgICB0LkUgPSA2MTE7CiAgICB0LkYgPSA1NTY7CiAgICB0LkcgPSA3MjI7CiAgICB0LkggPSA3MjI7CiAgICB0LkkgPSAzMzM7CiAgICB0LkogPSAzODk7CiAgICB0LksgPSA3MjI7CiAgICB0LkwgPSA2MTE7CiAgICB0Lk0gPSA4ODk7CiAgICB0Lk4gPSA3MjI7CiAgICB0Lk8gPSA3MjI7CiAgICB0LlAgPSA1NTY7CiAgICB0LlEgPSA3MjI7CiAgICB0LlIgPSA2Njc7CiAgICB0LlMgPSA1NTY7CiAgICB0LlQgPSA2MTE7CiAgICB0LlUgPSA3MjI7CiAgICB0LlYgPSA3MjI7CiAgICB0LlcgPSA5NDQ7CiAgICB0LlggPSA3MjI7CiAgICB0LlkgPSA3MjI7CiAgICB0LlogPSA2MTE7CiAgICB0LmJyYWNrZXRsZWZ0ID0gMzMzOwogICAgdC5iYWNrc2xhc2ggPSAyNzg7CiAgICB0LmJyYWNrZXRyaWdodCA9IDMzMzsKICAgIHQuYXNjaWljaXJjdW0gPSA0Njk7CiAgICB0LnVuZGVyc2NvcmUgPSA1MDA7CiAgICB0LnF1b3RlbGVmdCA9IDMzMzsKICAgIHQuYSA9IDQ0NDsKICAgIHQuYiA9IDUwMDsKICAgIHQuYyA9IDQ0NDsKICAgIHQuZCA9IDUwMDsKICAgIHQuZSA9IDQ0NDsKICAgIHQuZiA9IDMzMzsKICAgIHQuZyA9IDUwMDsKICAgIHQuaCA9IDUwMDsKICAgIHQuaSA9IDI3ODsKICAgIHQuaiA9IDI3ODsKICAgIHQuayA9IDUwMDsKICAgIHQubCA9IDI3ODsKICAgIHQubSA9IDc3ODsKICAgIHQubiA9IDUwMDsKICAgIHQubyA9IDUwMDsKICAgIHQucCA9IDUwMDsKICAgIHQucSA9IDUwMDsKICAgIHQuciA9IDMzMzsKICAgIHQucyA9IDM4OTsKICAgIHQudCA9IDI3ODsKICAgIHQudSA9IDUwMDsKICAgIHQudiA9IDUwMDsKICAgIHQudyA9IDcyMjsKICAgIHQueCA9IDUwMDsKICAgIHQueSA9IDUwMDsKICAgIHQueiA9IDQ0NDsKICAgIHQuYnJhY2VsZWZ0ID0gNDgwOwogICAgdC5iYXIgPSAyMDA7CiAgICB0LmJyYWNlcmlnaHQgPSA0ODA7CiAgICB0LmFzY2lpdGlsZGUgPSA1NDE7CiAgICB0LmV4Y2xhbWRvd24gPSAzMzM7CiAgICB0LmNlbnQgPSA1MDA7CiAgICB0LnN0ZXJsaW5nID0gNTAwOwogICAgdC5mcmFjdGlvbiA9IDE2NzsKICAgIHQueWVuID0gNTAwOwogICAgdC5mbG9yaW4gPSA1MDA7CiAgICB0LnNlY3Rpb24gPSA1MDA7CiAgICB0LmN1cnJlbmN5ID0gNTAwOwogICAgdC5xdW90ZXNpbmdsZSA9IDE4MDsKICAgIHQucXVvdGVkYmxsZWZ0ID0gNDQ0OwogICAgdC5ndWlsbGVtb3RsZWZ0ID0gNTAwOwogICAgdC5ndWlsc2luZ2xsZWZ0ID0gMzMzOwogICAgdC5ndWlsc2luZ2xyaWdodCA9IDMzMzsKICAgIHQuZmkgPSA1NTY7CiAgICB0LmZsID0gNTU2OwogICAgdC5lbmRhc2ggPSA1MDA7CiAgICB0LmRhZ2dlciA9IDUwMDsKICAgIHQuZGFnZ2VyZGJsID0gNTAwOwogICAgdC5wZXJpb2RjZW50ZXJlZCA9IDI1MDsKICAgIHQucGFyYWdyYXBoID0gNDUzOwogICAgdC5idWxsZXQgPSAzNTA7CiAgICB0LnF1b3Rlc2luZ2xiYXNlID0gMzMzOwogICAgdC5xdW90ZWRibGJhc2UgPSA0NDQ7CiAgICB0LnF1b3RlZGJscmlnaHQgPSA0NDQ7CiAgICB0Lmd1aWxsZW1vdHJpZ2h0ID0gNTAwOwogICAgdC5lbGxpcHNpcyA9IDEwMDA7CiAgICB0LnBlcnRob3VzYW5kID0gMTAwMDsKICAgIHQucXVlc3Rpb25kb3duID0gNDQ0OwogICAgdC5ncmF2ZSA9IDMzMzsKICAgIHQuYWN1dGUgPSAzMzM7CiAgICB0LmNpcmN1bWZsZXggPSAzMzM7CiAgICB0LnRpbGRlID0gMzMzOwogICAgdC5tYWNyb24gPSAzMzM7CiAgICB0LmJyZXZlID0gMzMzOwogICAgdC5kb3RhY2NlbnQgPSAzMzM7CiAgICB0LmRpZXJlc2lzID0gMzMzOwogICAgdC5yaW5nID0gMzMzOwogICAgdC5jZWRpbGxhID0gMzMzOwogICAgdC5odW5nYXJ1bWxhdXQgPSAzMzM7CiAgICB0Lm9nb25layA9IDMzMzsKICAgIHQuY2Fyb24gPSAzMzM7CiAgICB0LmVtZGFzaCA9IDEwMDA7CiAgICB0LkFFID0gODg5OwogICAgdC5vcmRmZW1pbmluZSA9IDI3NjsKICAgIHQuTHNsYXNoID0gNjExOwogICAgdC5Pc2xhc2ggPSA3MjI7CiAgICB0Lk9FID0gODg5OwogICAgdC5vcmRtYXNjdWxpbmUgPSAzMTA7CiAgICB0LmFlID0gNjY3OwogICAgdC5kb3RsZXNzaSA9IDI3ODsKICAgIHQubHNsYXNoID0gMjc4OwogICAgdC5vc2xhc2ggPSA1MDA7CiAgICB0Lm9lID0gNzIyOwogICAgdC5nZXJtYW5kYmxzID0gNTAwOwogICAgdC5JZGllcmVzaXMgPSAzMzM7CiAgICB0LmVhY3V0ZSA9IDQ0NDsKICAgIHQuYWJyZXZlID0gNDQ0OwogICAgdC51aHVuZ2FydW1sYXV0ID0gNTAwOwogICAgdC5lY2Fyb24gPSA0NDQ7CiAgICB0LllkaWVyZXNpcyA9IDcyMjsKICAgIHQuZGl2aWRlID0gNTY0OwogICAgdC5ZYWN1dGUgPSA3MjI7CiAgICB0LkFjaXJjdW1mbGV4ID0gNzIyOwogICAgdC5hYWN1dGUgPSA0NDQ7CiAgICB0LlVjaXJjdW1mbGV4ID0gNzIyOwogICAgdC55YWN1dGUgPSA1MDA7CiAgICB0LnNjb21tYWFjY2VudCA9IDM4OTsKICAgIHQuZWNpcmN1bWZsZXggPSA0NDQ7CiAgICB0LlVyaW5nID0gNzIyOwogICAgdC5VZGllcmVzaXMgPSA3MjI7CiAgICB0LmFvZ29uZWsgPSA0NDQ7CiAgICB0LlVhY3V0ZSA9IDcyMjsKICAgIHQudW9nb25layA9IDUwMDsKICAgIHQuRWRpZXJlc2lzID0gNjExOwogICAgdC5EY3JvYXQgPSA3MjI7CiAgICB0LmNvbW1hYWNjZW50ID0gMjUwOwogICAgdC5jb3B5cmlnaHQgPSA3NjA7CiAgICB0LkVtYWNyb24gPSA2MTE7CiAgICB0LmNjYXJvbiA9IDQ0NDsKICAgIHQuYXJpbmcgPSA0NDQ7CiAgICB0Lk5jb21tYWFjY2VudCA9IDcyMjsKICAgIHQubGFjdXRlID0gMjc4OwogICAgdC5hZ3JhdmUgPSA0NDQ7CiAgICB0LlRjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuQ2FjdXRlID0gNjY3OwogICAgdC5hdGlsZGUgPSA0NDQ7CiAgICB0LkVkb3RhY2NlbnQgPSA2MTE7CiAgICB0LnNjYXJvbiA9IDM4OTsKICAgIHQuc2NlZGlsbGEgPSAzODk7CiAgICB0LmlhY3V0ZSA9IDI3ODsKICAgIHQubG96ZW5nZSA9IDQ3MTsKICAgIHQuUmNhcm9uID0gNjY3OwogICAgdC5HY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LnVjaXJjdW1mbGV4ID0gNTAwOwogICAgdC5hY2lyY3VtZmxleCA9IDQ0NDsKICAgIHQuQW1hY3JvbiA9IDcyMjsKICAgIHQucmNhcm9uID0gMzMzOwogICAgdC5jY2VkaWxsYSA9IDQ0NDsKICAgIHQuWmRvdGFjY2VudCA9IDYxMTsKICAgIHQuVGhvcm4gPSA1NTY7CiAgICB0Lk9tYWNyb24gPSA3MjI7CiAgICB0LlJhY3V0ZSA9IDY2NzsKICAgIHQuU2FjdXRlID0gNTU2OwogICAgdC5kY2Fyb24gPSA1ODg7CiAgICB0LlVtYWNyb24gPSA3MjI7CiAgICB0LnVyaW5nID0gNTAwOwogICAgdC50aHJlZXN1cGVyaW9yID0gMzAwOwogICAgdC5PZ3JhdmUgPSA3MjI7CiAgICB0LkFncmF2ZSA9IDcyMjsKICAgIHQuQWJyZXZlID0gNzIyOwogICAgdC5tdWx0aXBseSA9IDU2NDsKICAgIHQudWFjdXRlID0gNTAwOwogICAgdC5UY2Fyb24gPSA2MTE7CiAgICB0LnBhcnRpYWxkaWZmID0gNDc2OwogICAgdC55ZGllcmVzaXMgPSA1MDA7CiAgICB0Lk5hY3V0ZSA9IDcyMjsKICAgIHQuaWNpcmN1bWZsZXggPSAyNzg7CiAgICB0LkVjaXJjdW1mbGV4ID0gNjExOwogICAgdC5hZGllcmVzaXMgPSA0NDQ7CiAgICB0LmVkaWVyZXNpcyA9IDQ0NDsKICAgIHQuY2FjdXRlID0gNDQ0OwogICAgdC5uYWN1dGUgPSA1MDA7CiAgICB0LnVtYWNyb24gPSA1MDA7CiAgICB0Lk5jYXJvbiA9IDcyMjsKICAgIHQuSWFjdXRlID0gMzMzOwogICAgdC5wbHVzbWludXMgPSA1NjQ7CiAgICB0LmJyb2tlbmJhciA9IDIwMDsKICAgIHQucmVnaXN0ZXJlZCA9IDc2MDsKICAgIHQuR2JyZXZlID0gNzIyOwogICAgdC5JZG90YWNjZW50ID0gMzMzOwogICAgdC5zdW1tYXRpb24gPSA2MDA7CiAgICB0LkVncmF2ZSA9IDYxMTsKICAgIHQucmFjdXRlID0gMzMzOwogICAgdC5vbWFjcm9uID0gNTAwOwogICAgdC5aYWN1dGUgPSA2MTE7CiAgICB0LlpjYXJvbiA9IDYxMTsKICAgIHQuZ3JlYXRlcmVxdWFsID0gNTQ5OwogICAgdC5FdGggPSA3MjI7CiAgICB0LkNjZWRpbGxhID0gNjY3OwogICAgdC5sY29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LnRjYXJvbiA9IDMyNjsKICAgIHQuZW9nb25layA9IDQ0NDsKICAgIHQuVW9nb25layA9IDcyMjsKICAgIHQuQWFjdXRlID0gNzIyOwogICAgdC5BZGllcmVzaXMgPSA3MjI7CiAgICB0LmVncmF2ZSA9IDQ0NDsKICAgIHQuemFjdXRlID0gNDQ0OwogICAgdC5pb2dvbmVrID0gMjc4OwogICAgdC5PYWN1dGUgPSA3MjI7CiAgICB0Lm9hY3V0ZSA9IDUwMDsKICAgIHQuYW1hY3JvbiA9IDQ0NDsKICAgIHQuc2FjdXRlID0gMzg5OwogICAgdC5pZGllcmVzaXMgPSAyNzg7CiAgICB0Lk9jaXJjdW1mbGV4ID0gNzIyOwogICAgdC5VZ3JhdmUgPSA3MjI7CiAgICB0LkRlbHRhID0gNjEyOwogICAgdC50aG9ybiA9IDUwMDsKICAgIHQudHdvc3VwZXJpb3IgPSAzMDA7CiAgICB0Lk9kaWVyZXNpcyA9IDcyMjsKICAgIHQubXUgPSA1MDA7CiAgICB0LmlncmF2ZSA9IDI3ODsKICAgIHQub2h1bmdhcnVtbGF1dCA9IDUwMDsKICAgIHQuRW9nb25layA9IDYxMTsKICAgIHQuZGNyb2F0ID0gNTAwOwogICAgdC50aHJlZXF1YXJ0ZXJzID0gNzUwOwogICAgdC5TY2VkaWxsYSA9IDU1NjsKICAgIHQubGNhcm9uID0gMzQ0OwogICAgdC5LY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LkxhY3V0ZSA9IDYxMTsKICAgIHQudHJhZGVtYXJrID0gOTgwOwogICAgdC5lZG90YWNjZW50ID0gNDQ0OwogICAgdC5JZ3JhdmUgPSAzMzM7CiAgICB0LkltYWNyb24gPSAzMzM7CiAgICB0LkxjYXJvbiA9IDYxMTsKICAgIHQub25laGFsZiA9IDc1MDsKICAgIHQubGVzc2VxdWFsID0gNTQ5OwogICAgdC5vY2lyY3VtZmxleCA9IDUwMDsKICAgIHQubnRpbGRlID0gNTAwOwogICAgdC5VaHVuZ2FydW1sYXV0ID0gNzIyOwogICAgdC5FYWN1dGUgPSA2MTE7CiAgICB0LmVtYWNyb24gPSA0NDQ7CiAgICB0LmdicmV2ZSA9IDUwMDsKICAgIHQub25lcXVhcnRlciA9IDc1MDsKICAgIHQuU2Nhcm9uID0gNTU2OwogICAgdC5TY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0Lk9odW5nYXJ1bWxhdXQgPSA3MjI7CiAgICB0LmRlZ3JlZSA9IDQwMDsKICAgIHQub2dyYXZlID0gNTAwOwogICAgdC5DY2Fyb24gPSA2Njc7CiAgICB0LnVncmF2ZSA9IDUwMDsKICAgIHQucmFkaWNhbCA9IDQ1MzsKICAgIHQuRGNhcm9uID0gNzIyOwogICAgdC5yY29tbWFhY2NlbnQgPSAzMzM7CiAgICB0Lk50aWxkZSA9IDcyMjsKICAgIHQub3RpbGRlID0gNTAwOwogICAgdC5SY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0Lkxjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuQXRpbGRlID0gNzIyOwogICAgdC5Bb2dvbmVrID0gNzIyOwogICAgdC5BcmluZyA9IDcyMjsKICAgIHQuT3RpbGRlID0gNzIyOwogICAgdC56ZG90YWNjZW50ID0gNDQ0OwogICAgdC5FY2Fyb24gPSA2MTE7CiAgICB0LklvZ29uZWsgPSAzMzM7CiAgICB0Lmtjb21tYWFjY2VudCA9IDUwMDsKICAgIHQubWludXMgPSA1NjQ7CiAgICB0LkljaXJjdW1mbGV4ID0gMzMzOwogICAgdC5uY2Fyb24gPSA1MDA7CiAgICB0LnRjb21tYWFjY2VudCA9IDI3ODsKICAgIHQubG9naWNhbG5vdCA9IDU2NDsKICAgIHQub2RpZXJlc2lzID0gNTAwOwogICAgdC51ZGllcmVzaXMgPSA1MDA7CiAgICB0Lm5vdGVxdWFsID0gNTQ5OwogICAgdC5nY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0LmV0aCA9IDUwMDsKICAgIHQuemNhcm9uID0gNDQ0OwogICAgdC5uY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0Lm9uZXN1cGVyaW9yID0gMzAwOwogICAgdC5pbWFjcm9uID0gMjc4OwogICAgdC5FdXJvID0gNTAwOwogIH0pOwogIHRbIlRpbWVzLUJvbGQiXSA9IGdldExvb2t1cFRhYmxlRmFjdG9yeShmdW5jdGlvbiAodCkgewogICAgdC5zcGFjZSA9IDI1MDsKICAgIHQuZXhjbGFtID0gMzMzOwogICAgdC5xdW90ZWRibCA9IDU1NTsKICAgIHQubnVtYmVyc2lnbiA9IDUwMDsKICAgIHQuZG9sbGFyID0gNTAwOwogICAgdC5wZXJjZW50ID0gMTAwMDsKICAgIHQuYW1wZXJzYW5kID0gODMzOwogICAgdC5xdW90ZXJpZ2h0ID0gMzMzOwogICAgdC5wYXJlbmxlZnQgPSAzMzM7CiAgICB0LnBhcmVucmlnaHQgPSAzMzM7CiAgICB0LmFzdGVyaXNrID0gNTAwOwogICAgdC5wbHVzID0gNTcwOwogICAgdC5jb21tYSA9IDI1MDsKICAgIHQuaHlwaGVuID0gMzMzOwogICAgdC5wZXJpb2QgPSAyNTA7CiAgICB0LnNsYXNoID0gMjc4OwogICAgdC56ZXJvID0gNTAwOwogICAgdC5vbmUgPSA1MDA7CiAgICB0LnR3byA9IDUwMDsKICAgIHQudGhyZWUgPSA1MDA7CiAgICB0LmZvdXIgPSA1MDA7CiAgICB0LmZpdmUgPSA1MDA7CiAgICB0LnNpeCA9IDUwMDsKICAgIHQuc2V2ZW4gPSA1MDA7CiAgICB0LmVpZ2h0ID0gNTAwOwogICAgdC5uaW5lID0gNTAwOwogICAgdC5jb2xvbiA9IDMzMzsKICAgIHQuc2VtaWNvbG9uID0gMzMzOwogICAgdC5sZXNzID0gNTcwOwogICAgdC5lcXVhbCA9IDU3MDsKICAgIHQuZ3JlYXRlciA9IDU3MDsKICAgIHQucXVlc3Rpb24gPSA1MDA7CiAgICB0LmF0ID0gOTMwOwogICAgdC5BID0gNzIyOwogICAgdC5CID0gNjY3OwogICAgdC5DID0gNzIyOwogICAgdC5EID0gNzIyOwogICAgdC5FID0gNjY3OwogICAgdC5GID0gNjExOwogICAgdC5HID0gNzc4OwogICAgdC5IID0gNzc4OwogICAgdC5JID0gMzg5OwogICAgdC5KID0gNTAwOwogICAgdC5LID0gNzc4OwogICAgdC5MID0gNjY3OwogICAgdC5NID0gOTQ0OwogICAgdC5OID0gNzIyOwogICAgdC5PID0gNzc4OwogICAgdC5QID0gNjExOwogICAgdC5RID0gNzc4OwogICAgdC5SID0gNzIyOwogICAgdC5TID0gNTU2OwogICAgdC5UID0gNjY3OwogICAgdC5VID0gNzIyOwogICAgdC5WID0gNzIyOwogICAgdC5XID0gMTAwMDsKICAgIHQuWCA9IDcyMjsKICAgIHQuWSA9IDcyMjsKICAgIHQuWiA9IDY2NzsKICAgIHQuYnJhY2tldGxlZnQgPSAzMzM7CiAgICB0LmJhY2tzbGFzaCA9IDI3ODsKICAgIHQuYnJhY2tldHJpZ2h0ID0gMzMzOwogICAgdC5hc2NpaWNpcmN1bSA9IDU4MTsKICAgIHQudW5kZXJzY29yZSA9IDUwMDsKICAgIHQucXVvdGVsZWZ0ID0gMzMzOwogICAgdC5hID0gNTAwOwogICAgdC5iID0gNTU2OwogICAgdC5jID0gNDQ0OwogICAgdC5kID0gNTU2OwogICAgdC5lID0gNDQ0OwogICAgdC5mID0gMzMzOwogICAgdC5nID0gNTAwOwogICAgdC5oID0gNTU2OwogICAgdC5pID0gMjc4OwogICAgdC5qID0gMzMzOwogICAgdC5rID0gNTU2OwogICAgdC5sID0gMjc4OwogICAgdC5tID0gODMzOwogICAgdC5uID0gNTU2OwogICAgdC5vID0gNTAwOwogICAgdC5wID0gNTU2OwogICAgdC5xID0gNTU2OwogICAgdC5yID0gNDQ0OwogICAgdC5zID0gMzg5OwogICAgdC50ID0gMzMzOwogICAgdC51ID0gNTU2OwogICAgdC52ID0gNTAwOwogICAgdC53ID0gNzIyOwogICAgdC54ID0gNTAwOwogICAgdC55ID0gNTAwOwogICAgdC56ID0gNDQ0OwogICAgdC5icmFjZWxlZnQgPSAzOTQ7CiAgICB0LmJhciA9IDIyMDsKICAgIHQuYnJhY2VyaWdodCA9IDM5NDsKICAgIHQuYXNjaWl0aWxkZSA9IDUyMDsKICAgIHQuZXhjbGFtZG93biA9IDMzMzsKICAgIHQuY2VudCA9IDUwMDsKICAgIHQuc3RlcmxpbmcgPSA1MDA7CiAgICB0LmZyYWN0aW9uID0gMTY3OwogICAgdC55ZW4gPSA1MDA7CiAgICB0LmZsb3JpbiA9IDUwMDsKICAgIHQuc2VjdGlvbiA9IDUwMDsKICAgIHQuY3VycmVuY3kgPSA1MDA7CiAgICB0LnF1b3Rlc2luZ2xlID0gMjc4OwogICAgdC5xdW90ZWRibGxlZnQgPSA1MDA7CiAgICB0Lmd1aWxsZW1vdGxlZnQgPSA1MDA7CiAgICB0Lmd1aWxzaW5nbGxlZnQgPSAzMzM7CiAgICB0Lmd1aWxzaW5nbHJpZ2h0ID0gMzMzOwogICAgdC5maSA9IDU1NjsKICAgIHQuZmwgPSA1NTY7CiAgICB0LmVuZGFzaCA9IDUwMDsKICAgIHQuZGFnZ2VyID0gNTAwOwogICAgdC5kYWdnZXJkYmwgPSA1MDA7CiAgICB0LnBlcmlvZGNlbnRlcmVkID0gMjUwOwogICAgdC5wYXJhZ3JhcGggPSA1NDA7CiAgICB0LmJ1bGxldCA9IDM1MDsKICAgIHQucXVvdGVzaW5nbGJhc2UgPSAzMzM7CiAgICB0LnF1b3RlZGJsYmFzZSA9IDUwMDsKICAgIHQucXVvdGVkYmxyaWdodCA9IDUwMDsKICAgIHQuZ3VpbGxlbW90cmlnaHQgPSA1MDA7CiAgICB0LmVsbGlwc2lzID0gMTAwMDsKICAgIHQucGVydGhvdXNhbmQgPSAxMDAwOwogICAgdC5xdWVzdGlvbmRvd24gPSA1MDA7CiAgICB0LmdyYXZlID0gMzMzOwogICAgdC5hY3V0ZSA9IDMzMzsKICAgIHQuY2lyY3VtZmxleCA9IDMzMzsKICAgIHQudGlsZGUgPSAzMzM7CiAgICB0Lm1hY3JvbiA9IDMzMzsKICAgIHQuYnJldmUgPSAzMzM7CiAgICB0LmRvdGFjY2VudCA9IDMzMzsKICAgIHQuZGllcmVzaXMgPSAzMzM7CiAgICB0LnJpbmcgPSAzMzM7CiAgICB0LmNlZGlsbGEgPSAzMzM7CiAgICB0Lmh1bmdhcnVtbGF1dCA9IDMzMzsKICAgIHQub2dvbmVrID0gMzMzOwogICAgdC5jYXJvbiA9IDMzMzsKICAgIHQuZW1kYXNoID0gMTAwMDsKICAgIHQuQUUgPSAxMDAwOwogICAgdC5vcmRmZW1pbmluZSA9IDMwMDsKICAgIHQuTHNsYXNoID0gNjY3OwogICAgdC5Pc2xhc2ggPSA3Nzg7CiAgICB0Lk9FID0gMTAwMDsKICAgIHQub3JkbWFzY3VsaW5lID0gMzMwOwogICAgdC5hZSA9IDcyMjsKICAgIHQuZG90bGVzc2kgPSAyNzg7CiAgICB0LmxzbGFzaCA9IDI3ODsKICAgIHQub3NsYXNoID0gNTAwOwogICAgdC5vZSA9IDcyMjsKICAgIHQuZ2VybWFuZGJscyA9IDU1NjsKICAgIHQuSWRpZXJlc2lzID0gMzg5OwogICAgdC5lYWN1dGUgPSA0NDQ7CiAgICB0LmFicmV2ZSA9IDUwMDsKICAgIHQudWh1bmdhcnVtbGF1dCA9IDU1NjsKICAgIHQuZWNhcm9uID0gNDQ0OwogICAgdC5ZZGllcmVzaXMgPSA3MjI7CiAgICB0LmRpdmlkZSA9IDU3MDsKICAgIHQuWWFjdXRlID0gNzIyOwogICAgdC5BY2lyY3VtZmxleCA9IDcyMjsKICAgIHQuYWFjdXRlID0gNTAwOwogICAgdC5VY2lyY3VtZmxleCA9IDcyMjsKICAgIHQueWFjdXRlID0gNTAwOwogICAgdC5zY29tbWFhY2NlbnQgPSAzODk7CiAgICB0LmVjaXJjdW1mbGV4ID0gNDQ0OwogICAgdC5VcmluZyA9IDcyMjsKICAgIHQuVWRpZXJlc2lzID0gNzIyOwogICAgdC5hb2dvbmVrID0gNTAwOwogICAgdC5VYWN1dGUgPSA3MjI7CiAgICB0LnVvZ29uZWsgPSA1NTY7CiAgICB0LkVkaWVyZXNpcyA9IDY2NzsKICAgIHQuRGNyb2F0ID0gNzIyOwogICAgdC5jb21tYWFjY2VudCA9IDI1MDsKICAgIHQuY29weXJpZ2h0ID0gNzQ3OwogICAgdC5FbWFjcm9uID0gNjY3OwogICAgdC5jY2Fyb24gPSA0NDQ7CiAgICB0LmFyaW5nID0gNTAwOwogICAgdC5OY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LmxhY3V0ZSA9IDI3ODsKICAgIHQuYWdyYXZlID0gNTAwOwogICAgdC5UY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0LkNhY3V0ZSA9IDcyMjsKICAgIHQuYXRpbGRlID0gNTAwOwogICAgdC5FZG90YWNjZW50ID0gNjY3OwogICAgdC5zY2Fyb24gPSAzODk7CiAgICB0LnNjZWRpbGxhID0gMzg5OwogICAgdC5pYWN1dGUgPSAyNzg7CiAgICB0LmxvemVuZ2UgPSA0OTQ7CiAgICB0LlJjYXJvbiA9IDcyMjsKICAgIHQuR2NvbW1hYWNjZW50ID0gNzc4OwogICAgdC51Y2lyY3VtZmxleCA9IDU1NjsKICAgIHQuYWNpcmN1bWZsZXggPSA1MDA7CiAgICB0LkFtYWNyb24gPSA3MjI7CiAgICB0LnJjYXJvbiA9IDQ0NDsKICAgIHQuY2NlZGlsbGEgPSA0NDQ7CiAgICB0Llpkb3RhY2NlbnQgPSA2Njc7CiAgICB0LlRob3JuID0gNjExOwogICAgdC5PbWFjcm9uID0gNzc4OwogICAgdC5SYWN1dGUgPSA3MjI7CiAgICB0LlNhY3V0ZSA9IDU1NjsKICAgIHQuZGNhcm9uID0gNjcyOwogICAgdC5VbWFjcm9uID0gNzIyOwogICAgdC51cmluZyA9IDU1NjsKICAgIHQudGhyZWVzdXBlcmlvciA9IDMwMDsKICAgIHQuT2dyYXZlID0gNzc4OwogICAgdC5BZ3JhdmUgPSA3MjI7CiAgICB0LkFicmV2ZSA9IDcyMjsKICAgIHQubXVsdGlwbHkgPSA1NzA7CiAgICB0LnVhY3V0ZSA9IDU1NjsKICAgIHQuVGNhcm9uID0gNjY3OwogICAgdC5wYXJ0aWFsZGlmZiA9IDQ5NDsKICAgIHQueWRpZXJlc2lzID0gNTAwOwogICAgdC5OYWN1dGUgPSA3MjI7CiAgICB0LmljaXJjdW1mbGV4ID0gMjc4OwogICAgdC5FY2lyY3VtZmxleCA9IDY2NzsKICAgIHQuYWRpZXJlc2lzID0gNTAwOwogICAgdC5lZGllcmVzaXMgPSA0NDQ7CiAgICB0LmNhY3V0ZSA9IDQ0NDsKICAgIHQubmFjdXRlID0gNTU2OwogICAgdC51bWFjcm9uID0gNTU2OwogICAgdC5OY2Fyb24gPSA3MjI7CiAgICB0LklhY3V0ZSA9IDM4OTsKICAgIHQucGx1c21pbnVzID0gNTcwOwogICAgdC5icm9rZW5iYXIgPSAyMjA7CiAgICB0LnJlZ2lzdGVyZWQgPSA3NDc7CiAgICB0LkdicmV2ZSA9IDc3ODsKICAgIHQuSWRvdGFjY2VudCA9IDM4OTsKICAgIHQuc3VtbWF0aW9uID0gNjAwOwogICAgdC5FZ3JhdmUgPSA2Njc7CiAgICB0LnJhY3V0ZSA9IDQ0NDsKICAgIHQub21hY3JvbiA9IDUwMDsKICAgIHQuWmFjdXRlID0gNjY3OwogICAgdC5aY2Fyb24gPSA2Njc7CiAgICB0LmdyZWF0ZXJlcXVhbCA9IDU0OTsKICAgIHQuRXRoID0gNzIyOwogICAgdC5DY2VkaWxsYSA9IDcyMjsKICAgIHQubGNvbW1hYWNjZW50ID0gMjc4OwogICAgdC50Y2Fyb24gPSA0MTY7CiAgICB0LmVvZ29uZWsgPSA0NDQ7CiAgICB0LlVvZ29uZWsgPSA3MjI7CiAgICB0LkFhY3V0ZSA9IDcyMjsKICAgIHQuQWRpZXJlc2lzID0gNzIyOwogICAgdC5lZ3JhdmUgPSA0NDQ7CiAgICB0LnphY3V0ZSA9IDQ0NDsKICAgIHQuaW9nb25layA9IDI3ODsKICAgIHQuT2FjdXRlID0gNzc4OwogICAgdC5vYWN1dGUgPSA1MDA7CiAgICB0LmFtYWNyb24gPSA1MDA7CiAgICB0LnNhY3V0ZSA9IDM4OTsKICAgIHQuaWRpZXJlc2lzID0gMjc4OwogICAgdC5PY2lyY3VtZmxleCA9IDc3ODsKICAgIHQuVWdyYXZlID0gNzIyOwogICAgdC5EZWx0YSA9IDYxMjsKICAgIHQudGhvcm4gPSA1NTY7CiAgICB0LnR3b3N1cGVyaW9yID0gMzAwOwogICAgdC5PZGllcmVzaXMgPSA3Nzg7CiAgICB0Lm11ID0gNTU2OwogICAgdC5pZ3JhdmUgPSAyNzg7CiAgICB0Lm9odW5nYXJ1bWxhdXQgPSA1MDA7CiAgICB0LkVvZ29uZWsgPSA2Njc7CiAgICB0LmRjcm9hdCA9IDU1NjsKICAgIHQudGhyZWVxdWFydGVycyA9IDc1MDsKICAgIHQuU2NlZGlsbGEgPSA1NTY7CiAgICB0LmxjYXJvbiA9IDM5NDsKICAgIHQuS2NvbW1hYWNjZW50ID0gNzc4OwogICAgdC5MYWN1dGUgPSA2Njc7CiAgICB0LnRyYWRlbWFyayA9IDEwMDA7CiAgICB0LmVkb3RhY2NlbnQgPSA0NDQ7CiAgICB0LklncmF2ZSA9IDM4OTsKICAgIHQuSW1hY3JvbiA9IDM4OTsKICAgIHQuTGNhcm9uID0gNjY3OwogICAgdC5vbmVoYWxmID0gNzUwOwogICAgdC5sZXNzZXF1YWwgPSA1NDk7CiAgICB0Lm9jaXJjdW1mbGV4ID0gNTAwOwogICAgdC5udGlsZGUgPSA1NTY7CiAgICB0LlVodW5nYXJ1bWxhdXQgPSA3MjI7CiAgICB0LkVhY3V0ZSA9IDY2NzsKICAgIHQuZW1hY3JvbiA9IDQ0NDsKICAgIHQuZ2JyZXZlID0gNTAwOwogICAgdC5vbmVxdWFydGVyID0gNzUwOwogICAgdC5TY2Fyb24gPSA1NTY7CiAgICB0LlNjb21tYWFjY2VudCA9IDU1NjsKICAgIHQuT2h1bmdhcnVtbGF1dCA9IDc3ODsKICAgIHQuZGVncmVlID0gNDAwOwogICAgdC5vZ3JhdmUgPSA1MDA7CiAgICB0LkNjYXJvbiA9IDcyMjsKICAgIHQudWdyYXZlID0gNTU2OwogICAgdC5yYWRpY2FsID0gNTQ5OwogICAgdC5EY2Fyb24gPSA3MjI7CiAgICB0LnJjb21tYWFjY2VudCA9IDQ0NDsKICAgIHQuTnRpbGRlID0gNzIyOwogICAgdC5vdGlsZGUgPSA1MDA7CiAgICB0LlJjb21tYWFjY2VudCA9IDcyMjsKICAgIHQuTGNvbW1hYWNjZW50ID0gNjY3OwogICAgdC5BdGlsZGUgPSA3MjI7CiAgICB0LkFvZ29uZWsgPSA3MjI7CiAgICB0LkFyaW5nID0gNzIyOwogICAgdC5PdGlsZGUgPSA3Nzg7CiAgICB0Lnpkb3RhY2NlbnQgPSA0NDQ7CiAgICB0LkVjYXJvbiA9IDY2NzsKICAgIHQuSW9nb25layA9IDM4OTsKICAgIHQua2NvbW1hYWNjZW50ID0gNTU2OwogICAgdC5taW51cyA9IDU3MDsKICAgIHQuSWNpcmN1bWZsZXggPSAzODk7CiAgICB0Lm5jYXJvbiA9IDU1NjsKICAgIHQudGNvbW1hYWNjZW50ID0gMzMzOwogICAgdC5sb2dpY2Fsbm90ID0gNTcwOwogICAgdC5vZGllcmVzaXMgPSA1MDA7CiAgICB0LnVkaWVyZXNpcyA9IDU1NjsKICAgIHQubm90ZXF1YWwgPSA1NDk7CiAgICB0Lmdjb21tYWFjY2VudCA9IDUwMDsKICAgIHQuZXRoID0gNTAwOwogICAgdC56Y2Fyb24gPSA0NDQ7CiAgICB0Lm5jb21tYWFjY2VudCA9IDU1NjsKICAgIHQub25lc3VwZXJpb3IgPSAzMDA7CiAgICB0LmltYWNyb24gPSAyNzg7CiAgICB0LkV1cm8gPSA1MDA7CiAgfSk7CiAgdFsiVGltZXMtQm9sZEl0YWxpYyJdID0gZ2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uICh0KSB7CiAgICB0LnNwYWNlID0gMjUwOwogICAgdC5leGNsYW0gPSAzODk7CiAgICB0LnF1b3RlZGJsID0gNTU1OwogICAgdC5udW1iZXJzaWduID0gNTAwOwogICAgdC5kb2xsYXIgPSA1MDA7CiAgICB0LnBlcmNlbnQgPSA4MzM7CiAgICB0LmFtcGVyc2FuZCA9IDc3ODsKICAgIHQucXVvdGVyaWdodCA9IDMzMzsKICAgIHQucGFyZW5sZWZ0ID0gMzMzOwogICAgdC5wYXJlbnJpZ2h0ID0gMzMzOwogICAgdC5hc3RlcmlzayA9IDUwMDsKICAgIHQucGx1cyA9IDU3MDsKICAgIHQuY29tbWEgPSAyNTA7CiAgICB0Lmh5cGhlbiA9IDMzMzsKICAgIHQucGVyaW9kID0gMjUwOwogICAgdC5zbGFzaCA9IDI3ODsKICAgIHQuemVybyA9IDUwMDsKICAgIHQub25lID0gNTAwOwogICAgdC50d28gPSA1MDA7CiAgICB0LnRocmVlID0gNTAwOwogICAgdC5mb3VyID0gNTAwOwogICAgdC5maXZlID0gNTAwOwogICAgdC5zaXggPSA1MDA7CiAgICB0LnNldmVuID0gNTAwOwogICAgdC5laWdodCA9IDUwMDsKICAgIHQubmluZSA9IDUwMDsKICAgIHQuY29sb24gPSAzMzM7CiAgICB0LnNlbWljb2xvbiA9IDMzMzsKICAgIHQubGVzcyA9IDU3MDsKICAgIHQuZXF1YWwgPSA1NzA7CiAgICB0LmdyZWF0ZXIgPSA1NzA7CiAgICB0LnF1ZXN0aW9uID0gNTAwOwogICAgdC5hdCA9IDgzMjsKICAgIHQuQSA9IDY2NzsKICAgIHQuQiA9IDY2NzsKICAgIHQuQyA9IDY2NzsKICAgIHQuRCA9IDcyMjsKICAgIHQuRSA9IDY2NzsKICAgIHQuRiA9IDY2NzsKICAgIHQuRyA9IDcyMjsKICAgIHQuSCA9IDc3ODsKICAgIHQuSSA9IDM4OTsKICAgIHQuSiA9IDUwMDsKICAgIHQuSyA9IDY2NzsKICAgIHQuTCA9IDYxMTsKICAgIHQuTSA9IDg4OTsKICAgIHQuTiA9IDcyMjsKICAgIHQuTyA9IDcyMjsKICAgIHQuUCA9IDYxMTsKICAgIHQuUSA9IDcyMjsKICAgIHQuUiA9IDY2NzsKICAgIHQuUyA9IDU1NjsKICAgIHQuVCA9IDYxMTsKICAgIHQuVSA9IDcyMjsKICAgIHQuViA9IDY2NzsKICAgIHQuVyA9IDg4OTsKICAgIHQuWCA9IDY2NzsKICAgIHQuWSA9IDYxMTsKICAgIHQuWiA9IDYxMTsKICAgIHQuYnJhY2tldGxlZnQgPSAzMzM7CiAgICB0LmJhY2tzbGFzaCA9IDI3ODsKICAgIHQuYnJhY2tldHJpZ2h0ID0gMzMzOwogICAgdC5hc2NpaWNpcmN1bSA9IDU3MDsKICAgIHQudW5kZXJzY29yZSA9IDUwMDsKICAgIHQucXVvdGVsZWZ0ID0gMzMzOwogICAgdC5hID0gNTAwOwogICAgdC5iID0gNTAwOwogICAgdC5jID0gNDQ0OwogICAgdC5kID0gNTAwOwogICAgdC5lID0gNDQ0OwogICAgdC5mID0gMzMzOwogICAgdC5nID0gNTAwOwogICAgdC5oID0gNTU2OwogICAgdC5pID0gMjc4OwogICAgdC5qID0gMjc4OwogICAgdC5rID0gNTAwOwogICAgdC5sID0gMjc4OwogICAgdC5tID0gNzc4OwogICAgdC5uID0gNTU2OwogICAgdC5vID0gNTAwOwogICAgdC5wID0gNTAwOwogICAgdC5xID0gNTAwOwogICAgdC5yID0gMzg5OwogICAgdC5zID0gMzg5OwogICAgdC50ID0gMjc4OwogICAgdC51ID0gNTU2OwogICAgdC52ID0gNDQ0OwogICAgdC53ID0gNjY3OwogICAgdC54ID0gNTAwOwogICAgdC55ID0gNDQ0OwogICAgdC56ID0gMzg5OwogICAgdC5icmFjZWxlZnQgPSAzNDg7CiAgICB0LmJhciA9IDIyMDsKICAgIHQuYnJhY2VyaWdodCA9IDM0ODsKICAgIHQuYXNjaWl0aWxkZSA9IDU3MDsKICAgIHQuZXhjbGFtZG93biA9IDM4OTsKICAgIHQuY2VudCA9IDUwMDsKICAgIHQuc3RlcmxpbmcgPSA1MDA7CiAgICB0LmZyYWN0aW9uID0gMTY3OwogICAgdC55ZW4gPSA1MDA7CiAgICB0LmZsb3JpbiA9IDUwMDsKICAgIHQuc2VjdGlvbiA9IDUwMDsKICAgIHQuY3VycmVuY3kgPSA1MDA7CiAgICB0LnF1b3Rlc2luZ2xlID0gMjc4OwogICAgdC5xdW90ZWRibGxlZnQgPSA1MDA7CiAgICB0Lmd1aWxsZW1vdGxlZnQgPSA1MDA7CiAgICB0Lmd1aWxzaW5nbGxlZnQgPSAzMzM7CiAgICB0Lmd1aWxzaW5nbHJpZ2h0ID0gMzMzOwogICAgdC5maSA9IDU1NjsKICAgIHQuZmwgPSA1NTY7CiAgICB0LmVuZGFzaCA9IDUwMDsKICAgIHQuZGFnZ2VyID0gNTAwOwogICAgdC5kYWdnZXJkYmwgPSA1MDA7CiAgICB0LnBlcmlvZGNlbnRlcmVkID0gMjUwOwogICAgdC5wYXJhZ3JhcGggPSA1MDA7CiAgICB0LmJ1bGxldCA9IDM1MDsKICAgIHQucXVvdGVzaW5nbGJhc2UgPSAzMzM7CiAgICB0LnF1b3RlZGJsYmFzZSA9IDUwMDsKICAgIHQucXVvdGVkYmxyaWdodCA9IDUwMDsKICAgIHQuZ3VpbGxlbW90cmlnaHQgPSA1MDA7CiAgICB0LmVsbGlwc2lzID0gMTAwMDsKICAgIHQucGVydGhvdXNhbmQgPSAxMDAwOwogICAgdC5xdWVzdGlvbmRvd24gPSA1MDA7CiAgICB0LmdyYXZlID0gMzMzOwogICAgdC5hY3V0ZSA9IDMzMzsKICAgIHQuY2lyY3VtZmxleCA9IDMzMzsKICAgIHQudGlsZGUgPSAzMzM7CiAgICB0Lm1hY3JvbiA9IDMzMzsKICAgIHQuYnJldmUgPSAzMzM7CiAgICB0LmRvdGFjY2VudCA9IDMzMzsKICAgIHQuZGllcmVzaXMgPSAzMzM7CiAgICB0LnJpbmcgPSAzMzM7CiAgICB0LmNlZGlsbGEgPSAzMzM7CiAgICB0Lmh1bmdhcnVtbGF1dCA9IDMzMzsKICAgIHQub2dvbmVrID0gMzMzOwogICAgdC5jYXJvbiA9IDMzMzsKICAgIHQuZW1kYXNoID0gMTAwMDsKICAgIHQuQUUgPSA5NDQ7CiAgICB0Lm9yZGZlbWluaW5lID0gMjY2OwogICAgdC5Mc2xhc2ggPSA2MTE7CiAgICB0Lk9zbGFzaCA9IDcyMjsKICAgIHQuT0UgPSA5NDQ7CiAgICB0Lm9yZG1hc2N1bGluZSA9IDMwMDsKICAgIHQuYWUgPSA3MjI7CiAgICB0LmRvdGxlc3NpID0gMjc4OwogICAgdC5sc2xhc2ggPSAyNzg7CiAgICB0Lm9zbGFzaCA9IDUwMDsKICAgIHQub2UgPSA3MjI7CiAgICB0Lmdlcm1hbmRibHMgPSA1MDA7CiAgICB0LklkaWVyZXNpcyA9IDM4OTsKICAgIHQuZWFjdXRlID0gNDQ0OwogICAgdC5hYnJldmUgPSA1MDA7CiAgICB0LnVodW5nYXJ1bWxhdXQgPSA1NTY7CiAgICB0LmVjYXJvbiA9IDQ0NDsKICAgIHQuWWRpZXJlc2lzID0gNjExOwogICAgdC5kaXZpZGUgPSA1NzA7CiAgICB0LllhY3V0ZSA9IDYxMTsKICAgIHQuQWNpcmN1bWZsZXggPSA2Njc7CiAgICB0LmFhY3V0ZSA9IDUwMDsKICAgIHQuVWNpcmN1bWZsZXggPSA3MjI7CiAgICB0LnlhY3V0ZSA9IDQ0NDsKICAgIHQuc2NvbW1hYWNjZW50ID0gMzg5OwogICAgdC5lY2lyY3VtZmxleCA9IDQ0NDsKICAgIHQuVXJpbmcgPSA3MjI7CiAgICB0LlVkaWVyZXNpcyA9IDcyMjsKICAgIHQuYW9nb25layA9IDUwMDsKICAgIHQuVWFjdXRlID0gNzIyOwogICAgdC51b2dvbmVrID0gNTU2OwogICAgdC5FZGllcmVzaXMgPSA2Njc7CiAgICB0LkRjcm9hdCA9IDcyMjsKICAgIHQuY29tbWFhY2NlbnQgPSAyNTA7CiAgICB0LmNvcHlyaWdodCA9IDc0NzsKICAgIHQuRW1hY3JvbiA9IDY2NzsKICAgIHQuY2Nhcm9uID0gNDQ0OwogICAgdC5hcmluZyA9IDUwMDsKICAgIHQuTmNvbW1hYWNjZW50ID0gNzIyOwogICAgdC5sYWN1dGUgPSAyNzg7CiAgICB0LmFncmF2ZSA9IDUwMDsKICAgIHQuVGNvbW1hYWNjZW50ID0gNjExOwogICAgdC5DYWN1dGUgPSA2Njc7CiAgICB0LmF0aWxkZSA9IDUwMDsKICAgIHQuRWRvdGFjY2VudCA9IDY2NzsKICAgIHQuc2Nhcm9uID0gMzg5OwogICAgdC5zY2VkaWxsYSA9IDM4OTsKICAgIHQuaWFjdXRlID0gMjc4OwogICAgdC5sb3plbmdlID0gNDk0OwogICAgdC5SY2Fyb24gPSA2Njc7CiAgICB0Lkdjb21tYWFjY2VudCA9IDcyMjsKICAgIHQudWNpcmN1bWZsZXggPSA1NTY7CiAgICB0LmFjaXJjdW1mbGV4ID0gNTAwOwogICAgdC5BbWFjcm9uID0gNjY3OwogICAgdC5yY2Fyb24gPSAzODk7CiAgICB0LmNjZWRpbGxhID0gNDQ0OwogICAgdC5aZG90YWNjZW50ID0gNjExOwogICAgdC5UaG9ybiA9IDYxMTsKICAgIHQuT21hY3JvbiA9IDcyMjsKICAgIHQuUmFjdXRlID0gNjY3OwogICAgdC5TYWN1dGUgPSA1NTY7CiAgICB0LmRjYXJvbiA9IDYwODsKICAgIHQuVW1hY3JvbiA9IDcyMjsKICAgIHQudXJpbmcgPSA1NTY7CiAgICB0LnRocmVlc3VwZXJpb3IgPSAzMDA7CiAgICB0Lk9ncmF2ZSA9IDcyMjsKICAgIHQuQWdyYXZlID0gNjY3OwogICAgdC5BYnJldmUgPSA2Njc7CiAgICB0Lm11bHRpcGx5ID0gNTcwOwogICAgdC51YWN1dGUgPSA1NTY7CiAgICB0LlRjYXJvbiA9IDYxMTsKICAgIHQucGFydGlhbGRpZmYgPSA0OTQ7CiAgICB0LnlkaWVyZXNpcyA9IDQ0NDsKICAgIHQuTmFjdXRlID0gNzIyOwogICAgdC5pY2lyY3VtZmxleCA9IDI3ODsKICAgIHQuRWNpcmN1bWZsZXggPSA2Njc7CiAgICB0LmFkaWVyZXNpcyA9IDUwMDsKICAgIHQuZWRpZXJlc2lzID0gNDQ0OwogICAgdC5jYWN1dGUgPSA0NDQ7CiAgICB0Lm5hY3V0ZSA9IDU1NjsKICAgIHQudW1hY3JvbiA9IDU1NjsKICAgIHQuTmNhcm9uID0gNzIyOwogICAgdC5JYWN1dGUgPSAzODk7CiAgICB0LnBsdXNtaW51cyA9IDU3MDsKICAgIHQuYnJva2VuYmFyID0gMjIwOwogICAgdC5yZWdpc3RlcmVkID0gNzQ3OwogICAgdC5HYnJldmUgPSA3MjI7CiAgICB0Lklkb3RhY2NlbnQgPSAzODk7CiAgICB0LnN1bW1hdGlvbiA9IDYwMDsKICAgIHQuRWdyYXZlID0gNjY3OwogICAgdC5yYWN1dGUgPSAzODk7CiAgICB0Lm9tYWNyb24gPSA1MDA7CiAgICB0LlphY3V0ZSA9IDYxMTsKICAgIHQuWmNhcm9uID0gNjExOwogICAgdC5ncmVhdGVyZXF1YWwgPSA1NDk7CiAgICB0LkV0aCA9IDcyMjsKICAgIHQuQ2NlZGlsbGEgPSA2Njc7CiAgICB0Lmxjb21tYWFjY2VudCA9IDI3ODsKICAgIHQudGNhcm9uID0gMzY2OwogICAgdC5lb2dvbmVrID0gNDQ0OwogICAgdC5Vb2dvbmVrID0gNzIyOwogICAgdC5BYWN1dGUgPSA2Njc7CiAgICB0LkFkaWVyZXNpcyA9IDY2NzsKICAgIHQuZWdyYXZlID0gNDQ0OwogICAgdC56YWN1dGUgPSAzODk7CiAgICB0LmlvZ29uZWsgPSAyNzg7CiAgICB0Lk9hY3V0ZSA9IDcyMjsKICAgIHQub2FjdXRlID0gNTAwOwogICAgdC5hbWFjcm9uID0gNTAwOwogICAgdC5zYWN1dGUgPSAzODk7CiAgICB0LmlkaWVyZXNpcyA9IDI3ODsKICAgIHQuT2NpcmN1bWZsZXggPSA3MjI7CiAgICB0LlVncmF2ZSA9IDcyMjsKICAgIHQuRGVsdGEgPSA2MTI7CiAgICB0LnRob3JuID0gNTAwOwogICAgdC50d29zdXBlcmlvciA9IDMwMDsKICAgIHQuT2RpZXJlc2lzID0gNzIyOwogICAgdC5tdSA9IDU3NjsKICAgIHQuaWdyYXZlID0gMjc4OwogICAgdC5vaHVuZ2FydW1sYXV0ID0gNTAwOwogICAgdC5Fb2dvbmVrID0gNjY3OwogICAgdC5kY3JvYXQgPSA1MDA7CiAgICB0LnRocmVlcXVhcnRlcnMgPSA3NTA7CiAgICB0LlNjZWRpbGxhID0gNTU2OwogICAgdC5sY2Fyb24gPSAzODI7CiAgICB0Lktjb21tYWFjY2VudCA9IDY2NzsKICAgIHQuTGFjdXRlID0gNjExOwogICAgdC50cmFkZW1hcmsgPSAxMDAwOwogICAgdC5lZG90YWNjZW50ID0gNDQ0OwogICAgdC5JZ3JhdmUgPSAzODk7CiAgICB0LkltYWNyb24gPSAzODk7CiAgICB0LkxjYXJvbiA9IDYxMTsKICAgIHQub25laGFsZiA9IDc1MDsKICAgIHQubGVzc2VxdWFsID0gNTQ5OwogICAgdC5vY2lyY3VtZmxleCA9IDUwMDsKICAgIHQubnRpbGRlID0gNTU2OwogICAgdC5VaHVuZ2FydW1sYXV0ID0gNzIyOwogICAgdC5FYWN1dGUgPSA2Njc7CiAgICB0LmVtYWNyb24gPSA0NDQ7CiAgICB0LmdicmV2ZSA9IDUwMDsKICAgIHQub25lcXVhcnRlciA9IDc1MDsKICAgIHQuU2Nhcm9uID0gNTU2OwogICAgdC5TY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0Lk9odW5nYXJ1bWxhdXQgPSA3MjI7CiAgICB0LmRlZ3JlZSA9IDQwMDsKICAgIHQub2dyYXZlID0gNTAwOwogICAgdC5DY2Fyb24gPSA2Njc7CiAgICB0LnVncmF2ZSA9IDU1NjsKICAgIHQucmFkaWNhbCA9IDU0OTsKICAgIHQuRGNhcm9uID0gNzIyOwogICAgdC5yY29tbWFhY2NlbnQgPSAzODk7CiAgICB0Lk50aWxkZSA9IDcyMjsKICAgIHQub3RpbGRlID0gNTAwOwogICAgdC5SY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0Lkxjb21tYWFjY2VudCA9IDYxMTsKICAgIHQuQXRpbGRlID0gNjY3OwogICAgdC5Bb2dvbmVrID0gNjY3OwogICAgdC5BcmluZyA9IDY2NzsKICAgIHQuT3RpbGRlID0gNzIyOwogICAgdC56ZG90YWNjZW50ID0gMzg5OwogICAgdC5FY2Fyb24gPSA2Njc7CiAgICB0LklvZ29uZWsgPSAzODk7CiAgICB0Lmtjb21tYWFjY2VudCA9IDUwMDsKICAgIHQubWludXMgPSA2MDY7CiAgICB0LkljaXJjdW1mbGV4ID0gMzg5OwogICAgdC5uY2Fyb24gPSA1NTY7CiAgICB0LnRjb21tYWFjY2VudCA9IDI3ODsKICAgIHQubG9naWNhbG5vdCA9IDYwNjsKICAgIHQub2RpZXJlc2lzID0gNTAwOwogICAgdC51ZGllcmVzaXMgPSA1NTY7CiAgICB0Lm5vdGVxdWFsID0gNTQ5OwogICAgdC5nY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0LmV0aCA9IDUwMDsKICAgIHQuemNhcm9uID0gMzg5OwogICAgdC5uY29tbWFhY2NlbnQgPSA1NTY7CiAgICB0Lm9uZXN1cGVyaW9yID0gMzAwOwogICAgdC5pbWFjcm9uID0gMjc4OwogICAgdC5FdXJvID0gNTAwOwogIH0pOwogIHRbIlRpbWVzLUl0YWxpYyJdID0gZ2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uICh0KSB7CiAgICB0LnNwYWNlID0gMjUwOwogICAgdC5leGNsYW0gPSAzMzM7CiAgICB0LnF1b3RlZGJsID0gNDIwOwogICAgdC5udW1iZXJzaWduID0gNTAwOwogICAgdC5kb2xsYXIgPSA1MDA7CiAgICB0LnBlcmNlbnQgPSA4MzM7CiAgICB0LmFtcGVyc2FuZCA9IDc3ODsKICAgIHQucXVvdGVyaWdodCA9IDMzMzsKICAgIHQucGFyZW5sZWZ0ID0gMzMzOwogICAgdC5wYXJlbnJpZ2h0ID0gMzMzOwogICAgdC5hc3RlcmlzayA9IDUwMDsKICAgIHQucGx1cyA9IDY3NTsKICAgIHQuY29tbWEgPSAyNTA7CiAgICB0Lmh5cGhlbiA9IDMzMzsKICAgIHQucGVyaW9kID0gMjUwOwogICAgdC5zbGFzaCA9IDI3ODsKICAgIHQuemVybyA9IDUwMDsKICAgIHQub25lID0gNTAwOwogICAgdC50d28gPSA1MDA7CiAgICB0LnRocmVlID0gNTAwOwogICAgdC5mb3VyID0gNTAwOwogICAgdC5maXZlID0gNTAwOwogICAgdC5zaXggPSA1MDA7CiAgICB0LnNldmVuID0gNTAwOwogICAgdC5laWdodCA9IDUwMDsKICAgIHQubmluZSA9IDUwMDsKICAgIHQuY29sb24gPSAzMzM7CiAgICB0LnNlbWljb2xvbiA9IDMzMzsKICAgIHQubGVzcyA9IDY3NTsKICAgIHQuZXF1YWwgPSA2NzU7CiAgICB0LmdyZWF0ZXIgPSA2NzU7CiAgICB0LnF1ZXN0aW9uID0gNTAwOwogICAgdC5hdCA9IDkyMDsKICAgIHQuQSA9IDYxMTsKICAgIHQuQiA9IDYxMTsKICAgIHQuQyA9IDY2NzsKICAgIHQuRCA9IDcyMjsKICAgIHQuRSA9IDYxMTsKICAgIHQuRiA9IDYxMTsKICAgIHQuRyA9IDcyMjsKICAgIHQuSCA9IDcyMjsKICAgIHQuSSA9IDMzMzsKICAgIHQuSiA9IDQ0NDsKICAgIHQuSyA9IDY2NzsKICAgIHQuTCA9IDU1NjsKICAgIHQuTSA9IDgzMzsKICAgIHQuTiA9IDY2NzsKICAgIHQuTyA9IDcyMjsKICAgIHQuUCA9IDYxMTsKICAgIHQuUSA9IDcyMjsKICAgIHQuUiA9IDYxMTsKICAgIHQuUyA9IDUwMDsKICAgIHQuVCA9IDU1NjsKICAgIHQuVSA9IDcyMjsKICAgIHQuViA9IDYxMTsKICAgIHQuVyA9IDgzMzsKICAgIHQuWCA9IDYxMTsKICAgIHQuWSA9IDU1NjsKICAgIHQuWiA9IDU1NjsKICAgIHQuYnJhY2tldGxlZnQgPSAzODk7CiAgICB0LmJhY2tzbGFzaCA9IDI3ODsKICAgIHQuYnJhY2tldHJpZ2h0ID0gMzg5OwogICAgdC5hc2NpaWNpcmN1bSA9IDQyMjsKICAgIHQudW5kZXJzY29yZSA9IDUwMDsKICAgIHQucXVvdGVsZWZ0ID0gMzMzOwogICAgdC5hID0gNTAwOwogICAgdC5iID0gNTAwOwogICAgdC5jID0gNDQ0OwogICAgdC5kID0gNTAwOwogICAgdC5lID0gNDQ0OwogICAgdC5mID0gMjc4OwogICAgdC5nID0gNTAwOwogICAgdC5oID0gNTAwOwogICAgdC5pID0gMjc4OwogICAgdC5qID0gMjc4OwogICAgdC5rID0gNDQ0OwogICAgdC5sID0gMjc4OwogICAgdC5tID0gNzIyOwogICAgdC5uID0gNTAwOwogICAgdC5vID0gNTAwOwogICAgdC5wID0gNTAwOwogICAgdC5xID0gNTAwOwogICAgdC5yID0gMzg5OwogICAgdC5zID0gMzg5OwogICAgdC50ID0gMjc4OwogICAgdC51ID0gNTAwOwogICAgdC52ID0gNDQ0OwogICAgdC53ID0gNjY3OwogICAgdC54ID0gNDQ0OwogICAgdC55ID0gNDQ0OwogICAgdC56ID0gMzg5OwogICAgdC5icmFjZWxlZnQgPSA0MDA7CiAgICB0LmJhciA9IDI3NTsKICAgIHQuYnJhY2VyaWdodCA9IDQwMDsKICAgIHQuYXNjaWl0aWxkZSA9IDU0MTsKICAgIHQuZXhjbGFtZG93biA9IDM4OTsKICAgIHQuY2VudCA9IDUwMDsKICAgIHQuc3RlcmxpbmcgPSA1MDA7CiAgICB0LmZyYWN0aW9uID0gMTY3OwogICAgdC55ZW4gPSA1MDA7CiAgICB0LmZsb3JpbiA9IDUwMDsKICAgIHQuc2VjdGlvbiA9IDUwMDsKICAgIHQuY3VycmVuY3kgPSA1MDA7CiAgICB0LnF1b3Rlc2luZ2xlID0gMjE0OwogICAgdC5xdW90ZWRibGxlZnQgPSA1NTY7CiAgICB0Lmd1aWxsZW1vdGxlZnQgPSA1MDA7CiAgICB0Lmd1aWxzaW5nbGxlZnQgPSAzMzM7CiAgICB0Lmd1aWxzaW5nbHJpZ2h0ID0gMzMzOwogICAgdC5maSA9IDUwMDsKICAgIHQuZmwgPSA1MDA7CiAgICB0LmVuZGFzaCA9IDUwMDsKICAgIHQuZGFnZ2VyID0gNTAwOwogICAgdC5kYWdnZXJkYmwgPSA1MDA7CiAgICB0LnBlcmlvZGNlbnRlcmVkID0gMjUwOwogICAgdC5wYXJhZ3JhcGggPSA1MjM7CiAgICB0LmJ1bGxldCA9IDM1MDsKICAgIHQucXVvdGVzaW5nbGJhc2UgPSAzMzM7CiAgICB0LnF1b3RlZGJsYmFzZSA9IDU1NjsKICAgIHQucXVvdGVkYmxyaWdodCA9IDU1NjsKICAgIHQuZ3VpbGxlbW90cmlnaHQgPSA1MDA7CiAgICB0LmVsbGlwc2lzID0gODg5OwogICAgdC5wZXJ0aG91c2FuZCA9IDEwMDA7CiAgICB0LnF1ZXN0aW9uZG93biA9IDUwMDsKICAgIHQuZ3JhdmUgPSAzMzM7CiAgICB0LmFjdXRlID0gMzMzOwogICAgdC5jaXJjdW1mbGV4ID0gMzMzOwogICAgdC50aWxkZSA9IDMzMzsKICAgIHQubWFjcm9uID0gMzMzOwogICAgdC5icmV2ZSA9IDMzMzsKICAgIHQuZG90YWNjZW50ID0gMzMzOwogICAgdC5kaWVyZXNpcyA9IDMzMzsKICAgIHQucmluZyA9IDMzMzsKICAgIHQuY2VkaWxsYSA9IDMzMzsKICAgIHQuaHVuZ2FydW1sYXV0ID0gMzMzOwogICAgdC5vZ29uZWsgPSAzMzM7CiAgICB0LmNhcm9uID0gMzMzOwogICAgdC5lbWRhc2ggPSA4ODk7CiAgICB0LkFFID0gODg5OwogICAgdC5vcmRmZW1pbmluZSA9IDI3NjsKICAgIHQuTHNsYXNoID0gNTU2OwogICAgdC5Pc2xhc2ggPSA3MjI7CiAgICB0Lk9FID0gOTQ0OwogICAgdC5vcmRtYXNjdWxpbmUgPSAzMTA7CiAgICB0LmFlID0gNjY3OwogICAgdC5kb3RsZXNzaSA9IDI3ODsKICAgIHQubHNsYXNoID0gMjc4OwogICAgdC5vc2xhc2ggPSA1MDA7CiAgICB0Lm9lID0gNjY3OwogICAgdC5nZXJtYW5kYmxzID0gNTAwOwogICAgdC5JZGllcmVzaXMgPSAzMzM7CiAgICB0LmVhY3V0ZSA9IDQ0NDsKICAgIHQuYWJyZXZlID0gNTAwOwogICAgdC51aHVuZ2FydW1sYXV0ID0gNTAwOwogICAgdC5lY2Fyb24gPSA0NDQ7CiAgICB0LllkaWVyZXNpcyA9IDU1NjsKICAgIHQuZGl2aWRlID0gNjc1OwogICAgdC5ZYWN1dGUgPSA1NTY7CiAgICB0LkFjaXJjdW1mbGV4ID0gNjExOwogICAgdC5hYWN1dGUgPSA1MDA7CiAgICB0LlVjaXJjdW1mbGV4ID0gNzIyOwogICAgdC55YWN1dGUgPSA0NDQ7CiAgICB0LnNjb21tYWFjY2VudCA9IDM4OTsKICAgIHQuZWNpcmN1bWZsZXggPSA0NDQ7CiAgICB0LlVyaW5nID0gNzIyOwogICAgdC5VZGllcmVzaXMgPSA3MjI7CiAgICB0LmFvZ29uZWsgPSA1MDA7CiAgICB0LlVhY3V0ZSA9IDcyMjsKICAgIHQudW9nb25layA9IDUwMDsKICAgIHQuRWRpZXJlc2lzID0gNjExOwogICAgdC5EY3JvYXQgPSA3MjI7CiAgICB0LmNvbW1hYWNjZW50ID0gMjUwOwogICAgdC5jb3B5cmlnaHQgPSA3NjA7CiAgICB0LkVtYWNyb24gPSA2MTE7CiAgICB0LmNjYXJvbiA9IDQ0NDsKICAgIHQuYXJpbmcgPSA1MDA7CiAgICB0Lk5jb21tYWFjY2VudCA9IDY2NzsKICAgIHQubGFjdXRlID0gMjc4OwogICAgdC5hZ3JhdmUgPSA1MDA7CiAgICB0LlRjb21tYWFjY2VudCA9IDU1NjsKICAgIHQuQ2FjdXRlID0gNjY3OwogICAgdC5hdGlsZGUgPSA1MDA7CiAgICB0LkVkb3RhY2NlbnQgPSA2MTE7CiAgICB0LnNjYXJvbiA9IDM4OTsKICAgIHQuc2NlZGlsbGEgPSAzODk7CiAgICB0LmlhY3V0ZSA9IDI3ODsKICAgIHQubG96ZW5nZSA9IDQ3MTsKICAgIHQuUmNhcm9uID0gNjExOwogICAgdC5HY29tbWFhY2NlbnQgPSA3MjI7CiAgICB0LnVjaXJjdW1mbGV4ID0gNTAwOwogICAgdC5hY2lyY3VtZmxleCA9IDUwMDsKICAgIHQuQW1hY3JvbiA9IDYxMTsKICAgIHQucmNhcm9uID0gMzg5OwogICAgdC5jY2VkaWxsYSA9IDQ0NDsKICAgIHQuWmRvdGFjY2VudCA9IDU1NjsKICAgIHQuVGhvcm4gPSA2MTE7CiAgICB0Lk9tYWNyb24gPSA3MjI7CiAgICB0LlJhY3V0ZSA9IDYxMTsKICAgIHQuU2FjdXRlID0gNTAwOwogICAgdC5kY2Fyb24gPSA1NDQ7CiAgICB0LlVtYWNyb24gPSA3MjI7CiAgICB0LnVyaW5nID0gNTAwOwogICAgdC50aHJlZXN1cGVyaW9yID0gMzAwOwogICAgdC5PZ3JhdmUgPSA3MjI7CiAgICB0LkFncmF2ZSA9IDYxMTsKICAgIHQuQWJyZXZlID0gNjExOwogICAgdC5tdWx0aXBseSA9IDY3NTsKICAgIHQudWFjdXRlID0gNTAwOwogICAgdC5UY2Fyb24gPSA1NTY7CiAgICB0LnBhcnRpYWxkaWZmID0gNDc2OwogICAgdC55ZGllcmVzaXMgPSA0NDQ7CiAgICB0Lk5hY3V0ZSA9IDY2NzsKICAgIHQuaWNpcmN1bWZsZXggPSAyNzg7CiAgICB0LkVjaXJjdW1mbGV4ID0gNjExOwogICAgdC5hZGllcmVzaXMgPSA1MDA7CiAgICB0LmVkaWVyZXNpcyA9IDQ0NDsKICAgIHQuY2FjdXRlID0gNDQ0OwogICAgdC5uYWN1dGUgPSA1MDA7CiAgICB0LnVtYWNyb24gPSA1MDA7CiAgICB0Lk5jYXJvbiA9IDY2NzsKICAgIHQuSWFjdXRlID0gMzMzOwogICAgdC5wbHVzbWludXMgPSA2NzU7CiAgICB0LmJyb2tlbmJhciA9IDI3NTsKICAgIHQucmVnaXN0ZXJlZCA9IDc2MDsKICAgIHQuR2JyZXZlID0gNzIyOwogICAgdC5JZG90YWNjZW50ID0gMzMzOwogICAgdC5zdW1tYXRpb24gPSA2MDA7CiAgICB0LkVncmF2ZSA9IDYxMTsKICAgIHQucmFjdXRlID0gMzg5OwogICAgdC5vbWFjcm9uID0gNTAwOwogICAgdC5aYWN1dGUgPSA1NTY7CiAgICB0LlpjYXJvbiA9IDU1NjsKICAgIHQuZ3JlYXRlcmVxdWFsID0gNTQ5OwogICAgdC5FdGggPSA3MjI7CiAgICB0LkNjZWRpbGxhID0gNjY3OwogICAgdC5sY29tbWFhY2NlbnQgPSAyNzg7CiAgICB0LnRjYXJvbiA9IDMwMDsKICAgIHQuZW9nb25layA9IDQ0NDsKICAgIHQuVW9nb25layA9IDcyMjsKICAgIHQuQWFjdXRlID0gNjExOwogICAgdC5BZGllcmVzaXMgPSA2MTE7CiAgICB0LmVncmF2ZSA9IDQ0NDsKICAgIHQuemFjdXRlID0gMzg5OwogICAgdC5pb2dvbmVrID0gMjc4OwogICAgdC5PYWN1dGUgPSA3MjI7CiAgICB0Lm9hY3V0ZSA9IDUwMDsKICAgIHQuYW1hY3JvbiA9IDUwMDsKICAgIHQuc2FjdXRlID0gMzg5OwogICAgdC5pZGllcmVzaXMgPSAyNzg7CiAgICB0Lk9jaXJjdW1mbGV4ID0gNzIyOwogICAgdC5VZ3JhdmUgPSA3MjI7CiAgICB0LkRlbHRhID0gNjEyOwogICAgdC50aG9ybiA9IDUwMDsKICAgIHQudHdvc3VwZXJpb3IgPSAzMDA7CiAgICB0Lk9kaWVyZXNpcyA9IDcyMjsKICAgIHQubXUgPSA1MDA7CiAgICB0LmlncmF2ZSA9IDI3ODsKICAgIHQub2h1bmdhcnVtbGF1dCA9IDUwMDsKICAgIHQuRW9nb25layA9IDYxMTsKICAgIHQuZGNyb2F0ID0gNTAwOwogICAgdC50aHJlZXF1YXJ0ZXJzID0gNzUwOwogICAgdC5TY2VkaWxsYSA9IDUwMDsKICAgIHQubGNhcm9uID0gMzAwOwogICAgdC5LY29tbWFhY2NlbnQgPSA2Njc7CiAgICB0LkxhY3V0ZSA9IDU1NjsKICAgIHQudHJhZGVtYXJrID0gOTgwOwogICAgdC5lZG90YWNjZW50ID0gNDQ0OwogICAgdC5JZ3JhdmUgPSAzMzM7CiAgICB0LkltYWNyb24gPSAzMzM7CiAgICB0LkxjYXJvbiA9IDYxMTsKICAgIHQub25laGFsZiA9IDc1MDsKICAgIHQubGVzc2VxdWFsID0gNTQ5OwogICAgdC5vY2lyY3VtZmxleCA9IDUwMDsKICAgIHQubnRpbGRlID0gNTAwOwogICAgdC5VaHVuZ2FydW1sYXV0ID0gNzIyOwogICAgdC5FYWN1dGUgPSA2MTE7CiAgICB0LmVtYWNyb24gPSA0NDQ7CiAgICB0LmdicmV2ZSA9IDUwMDsKICAgIHQub25lcXVhcnRlciA9IDc1MDsKICAgIHQuU2Nhcm9uID0gNTAwOwogICAgdC5TY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0Lk9odW5nYXJ1bWxhdXQgPSA3MjI7CiAgICB0LmRlZ3JlZSA9IDQwMDsKICAgIHQub2dyYXZlID0gNTAwOwogICAgdC5DY2Fyb24gPSA2Njc7CiAgICB0LnVncmF2ZSA9IDUwMDsKICAgIHQucmFkaWNhbCA9IDQ1MzsKICAgIHQuRGNhcm9uID0gNzIyOwogICAgdC5yY29tbWFhY2NlbnQgPSAzODk7CiAgICB0Lk50aWxkZSA9IDY2NzsKICAgIHQub3RpbGRlID0gNTAwOwogICAgdC5SY29tbWFhY2NlbnQgPSA2MTE7CiAgICB0Lkxjb21tYWFjY2VudCA9IDU1NjsKICAgIHQuQXRpbGRlID0gNjExOwogICAgdC5Bb2dvbmVrID0gNjExOwogICAgdC5BcmluZyA9IDYxMTsKICAgIHQuT3RpbGRlID0gNzIyOwogICAgdC56ZG90YWNjZW50ID0gMzg5OwogICAgdC5FY2Fyb24gPSA2MTE7CiAgICB0LklvZ29uZWsgPSAzMzM7CiAgICB0Lmtjb21tYWFjY2VudCA9IDQ0NDsKICAgIHQubWludXMgPSA2NzU7CiAgICB0LkljaXJjdW1mbGV4ID0gMzMzOwogICAgdC5uY2Fyb24gPSA1MDA7CiAgICB0LnRjb21tYWFjY2VudCA9IDI3ODsKICAgIHQubG9naWNhbG5vdCA9IDY3NTsKICAgIHQub2RpZXJlc2lzID0gNTAwOwogICAgdC51ZGllcmVzaXMgPSA1MDA7CiAgICB0Lm5vdGVxdWFsID0gNTQ5OwogICAgdC5nY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0LmV0aCA9IDUwMDsKICAgIHQuemNhcm9uID0gMzg5OwogICAgdC5uY29tbWFhY2NlbnQgPSA1MDA7CiAgICB0Lm9uZXN1cGVyaW9yID0gMzAwOwogICAgdC5pbWFjcm9uID0gMjc4OwogICAgdC5FdXJvID0gNTAwOwogIH0pOwogIHQuWmFwZkRpbmdiYXRzID0gZ2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uICh0KSB7CiAgICB0LnNwYWNlID0gMjc4OwogICAgdC5hMSA9IDk3NDsKICAgIHQuYTIgPSA5NjE7CiAgICB0LmEyMDIgPSA5NzQ7CiAgICB0LmEzID0gOTgwOwogICAgdC5hNCA9IDcxOTsKICAgIHQuYTUgPSA3ODk7CiAgICB0LmExMTkgPSA3OTA7CiAgICB0LmExMTggPSA3OTE7CiAgICB0LmExMTcgPSA2OTA7CiAgICB0LmExMSA9IDk2MDsKICAgIHQuYTEyID0gOTM5OwogICAgdC5hMTMgPSA1NDk7CiAgICB0LmExNCA9IDg1NTsKICAgIHQuYTE1ID0gOTExOwogICAgdC5hMTYgPSA5MzM7CiAgICB0LmExMDUgPSA5MTE7CiAgICB0LmExNyA9IDk0NTsKICAgIHQuYTE4ID0gOTc0OwogICAgdC5hMTkgPSA3NTU7CiAgICB0LmEyMCA9IDg0NjsKICAgIHQuYTIxID0gNzYyOwogICAgdC5hMjIgPSA3NjE7CiAgICB0LmEyMyA9IDU3MTsKICAgIHQuYTI0ID0gNjc3OwogICAgdC5hMjUgPSA3NjM7CiAgICB0LmEyNiA9IDc2MDsKICAgIHQuYTI3ID0gNzU5OwogICAgdC5hMjggPSA3NTQ7CiAgICB0LmE2ID0gNDk0OwogICAgdC5hNyA9IDU1MjsKICAgIHQuYTggPSA1Mzc7CiAgICB0LmE5ID0gNTc3OwogICAgdC5hMTAgPSA2OTI7CiAgICB0LmEyOSA9IDc4NjsKICAgIHQuYTMwID0gNzg4OwogICAgdC5hMzEgPSA3ODg7CiAgICB0LmEzMiA9IDc5MDsKICAgIHQuYTMzID0gNzkzOwogICAgdC5hMzQgPSA3OTQ7CiAgICB0LmEzNSA9IDgxNjsKICAgIHQuYTM2ID0gODIzOwogICAgdC5hMzcgPSA3ODk7CiAgICB0LmEzOCA9IDg0MTsKICAgIHQuYTM5ID0gODIzOwogICAgdC5hNDAgPSA4MzM7CiAgICB0LmE0MSA9IDgxNjsKICAgIHQuYTQyID0gODMxOwogICAgdC5hNDMgPSA5MjM7CiAgICB0LmE0NCA9IDc0NDsKICAgIHQuYTQ1ID0gNzIzOwogICAgdC5hNDYgPSA3NDk7CiAgICB0LmE0NyA9IDc5MDsKICAgIHQuYTQ4ID0gNzkyOwogICAgdC5hNDkgPSA2OTU7CiAgICB0LmE1MCA9IDc3NjsKICAgIHQuYTUxID0gNzY4OwogICAgdC5hNTIgPSA3OTI7CiAgICB0LmE1MyA9IDc1OTsKICAgIHQuYTU0ID0gNzA3OwogICAgdC5hNTUgPSA3MDg7CiAgICB0LmE1NiA9IDY4MjsKICAgIHQuYTU3ID0gNzAxOwogICAgdC5hNTggPSA4MjY7CiAgICB0LmE1OSA9IDgxNTsKICAgIHQuYTYwID0gNzg5OwogICAgdC5hNjEgPSA3ODk7CiAgICB0LmE2MiA9IDcwNzsKICAgIHQuYTYzID0gNjg3OwogICAgdC5hNjQgPSA2OTY7CiAgICB0LmE2NSA9IDY4OTsKICAgIHQuYTY2ID0gNzg2OwogICAgdC5hNjcgPSA3ODc7CiAgICB0LmE2OCA9IDcxMzsKICAgIHQuYTY5ID0gNzkxOwogICAgdC5hNzAgPSA3ODU7CiAgICB0LmE3MSA9IDc5MTsKICAgIHQuYTcyID0gODczOwogICAgdC5hNzMgPSA3NjE7CiAgICB0LmE3NCA9IDc2MjsKICAgIHQuYTIwMyA9IDc2MjsKICAgIHQuYTc1ID0gNzU5OwogICAgdC5hMjA0ID0gNzU5OwogICAgdC5hNzYgPSA4OTI7CiAgICB0LmE3NyA9IDg5MjsKICAgIHQuYTc4ID0gNzg4OwogICAgdC5hNzkgPSA3ODQ7CiAgICB0LmE4MSA9IDQzODsKICAgIHQuYTgyID0gMTM4OwogICAgdC5hODMgPSAyNzc7CiAgICB0LmE4NCA9IDQxNTsKICAgIHQuYTk3ID0gMzkyOwogICAgdC5hOTggPSAzOTI7CiAgICB0LmE5OSA9IDY2ODsKICAgIHQuYTEwMCA9IDY2ODsKICAgIHQuYTg5ID0gMzkwOwogICAgdC5hOTAgPSAzOTA7CiAgICB0LmE5MyA9IDMxNzsKICAgIHQuYTk0ID0gMzE3OwogICAgdC5hOTEgPSAyNzY7CiAgICB0LmE5MiA9IDI3NjsKICAgIHQuYTIwNSA9IDUwOTsKICAgIHQuYTg1ID0gNTA5OwogICAgdC5hMjA2ID0gNDEwOwogICAgdC5hODYgPSA0MTA7CiAgICB0LmE4NyA9IDIzNDsKICAgIHQuYTg4ID0gMjM0OwogICAgdC5hOTUgPSAzMzQ7CiAgICB0LmE5NiA9IDMzNDsKICAgIHQuYTEwMSA9IDczMjsKICAgIHQuYTEwMiA9IDU0NDsKICAgIHQuYTEwMyA9IDU0NDsKICAgIHQuYTEwNCA9IDkxMDsKICAgIHQuYTEwNiA9IDY2NzsKICAgIHQuYTEwNyA9IDc2MDsKICAgIHQuYTEwOCA9IDc2MDsKICAgIHQuYTExMiA9IDc3NjsKICAgIHQuYTExMSA9IDU5NTsKICAgIHQuYTExMCA9IDY5NDsKICAgIHQuYTEwOSA9IDYyNjsKICAgIHQuYTEyMCA9IDc4ODsKICAgIHQuYTEyMSA9IDc4ODsKICAgIHQuYTEyMiA9IDc4ODsKICAgIHQuYTEyMyA9IDc4ODsKICAgIHQuYTEyNCA9IDc4ODsKICAgIHQuYTEyNSA9IDc4ODsKICAgIHQuYTEyNiA9IDc4ODsKICAgIHQuYTEyNyA9IDc4ODsKICAgIHQuYTEyOCA9IDc4ODsKICAgIHQuYTEyOSA9IDc4ODsKICAgIHQuYTEzMCA9IDc4ODsKICAgIHQuYTEzMSA9IDc4ODsKICAgIHQuYTEzMiA9IDc4ODsKICAgIHQuYTEzMyA9IDc4ODsKICAgIHQuYTEzNCA9IDc4ODsKICAgIHQuYTEzNSA9IDc4ODsKICAgIHQuYTEzNiA9IDc4ODsKICAgIHQuYTEzNyA9IDc4ODsKICAgIHQuYTEzOCA9IDc4ODsKICAgIHQuYTEzOSA9IDc4ODsKICAgIHQuYTE0MCA9IDc4ODsKICAgIHQuYTE0MSA9IDc4ODsKICAgIHQuYTE0MiA9IDc4ODsKICAgIHQuYTE0MyA9IDc4ODsKICAgIHQuYTE0NCA9IDc4ODsKICAgIHQuYTE0NSA9IDc4ODsKICAgIHQuYTE0NiA9IDc4ODsKICAgIHQuYTE0NyA9IDc4ODsKICAgIHQuYTE0OCA9IDc4ODsKICAgIHQuYTE0OSA9IDc4ODsKICAgIHQuYTE1MCA9IDc4ODsKICAgIHQuYTE1MSA9IDc4ODsKICAgIHQuYTE1MiA9IDc4ODsKICAgIHQuYTE1MyA9IDc4ODsKICAgIHQuYTE1NCA9IDc4ODsKICAgIHQuYTE1NSA9IDc4ODsKICAgIHQuYTE1NiA9IDc4ODsKICAgIHQuYTE1NyA9IDc4ODsKICAgIHQuYTE1OCA9IDc4ODsKICAgIHQuYTE1OSA9IDc4ODsKICAgIHQuYTE2MCA9IDg5NDsKICAgIHQuYTE2MSA9IDgzODsKICAgIHQuYTE2MyA9IDEwMTY7CiAgICB0LmExNjQgPSA0NTg7CiAgICB0LmExOTYgPSA3NDg7CiAgICB0LmExNjUgPSA5MjQ7CiAgICB0LmExOTIgPSA3NDg7CiAgICB0LmExNjYgPSA5MTg7CiAgICB0LmExNjcgPSA5Mjc7CiAgICB0LmExNjggPSA5Mjg7CiAgICB0LmExNjkgPSA5Mjg7CiAgICB0LmExNzAgPSA4MzQ7CiAgICB0LmExNzEgPSA4NzM7CiAgICB0LmExNzIgPSA4Mjg7CiAgICB0LmExNzMgPSA5MjQ7CiAgICB0LmExNjIgPSA5MjQ7CiAgICB0LmExNzQgPSA5MTc7CiAgICB0LmExNzUgPSA5MzA7CiAgICB0LmExNzYgPSA5MzE7CiAgICB0LmExNzcgPSA0NjM7CiAgICB0LmExNzggPSA4ODM7CiAgICB0LmExNzkgPSA4MzY7CiAgICB0LmExOTMgPSA4MzY7CiAgICB0LmExODAgPSA4Njc7CiAgICB0LmExOTkgPSA4Njc7CiAgICB0LmExODEgPSA2OTY7CiAgICB0LmEyMDAgPSA2OTY7CiAgICB0LmExODIgPSA4NzQ7CiAgICB0LmEyMDEgPSA4NzQ7CiAgICB0LmExODMgPSA3NjA7CiAgICB0LmExODQgPSA5NDY7CiAgICB0LmExOTcgPSA3NzE7CiAgICB0LmExODUgPSA4NjU7CiAgICB0LmExOTQgPSA3NzE7CiAgICB0LmExOTggPSA4ODg7CiAgICB0LmExODYgPSA5Njc7CiAgICB0LmExOTUgPSA4ODg7CiAgICB0LmExODcgPSA4MzE7CiAgICB0LmExODggPSA4NzM7CiAgICB0LmExODkgPSA5Mjc7CiAgICB0LmExOTAgPSA5NzA7CiAgICB0LmExOTEgPSA5MTg7CiAgfSk7Cn0pOwpjb25zdCBnZXRGb250QmFzaWNNZXRyaWNzID0gZ2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uICh0KSB7CiAgdC5Db3VyaWVyID0gewogICAgYXNjZW50OiA2MjksCiAgICBkZXNjZW50OiAtMTU3LAogICAgY2FwSGVpZ2h0OiA1NjIsCiAgICB4SGVpZ2h0OiAtNDI2CiAgfTsKICB0WyJDb3VyaWVyLUJvbGQiXSA9IHsKICAgIGFzY2VudDogNjI5LAogICAgZGVzY2VudDogLTE1NywKICAgIGNhcEhlaWdodDogNTYyLAogICAgeEhlaWdodDogNDM5CiAgfTsKICB0WyJDb3VyaWVyLU9ibGlxdWUiXSA9IHsKICAgIGFzY2VudDogNjI5LAogICAgZGVzY2VudDogLTE1NywKICAgIGNhcEhlaWdodDogNTYyLAogICAgeEhlaWdodDogNDI2CiAgfTsKICB0WyJDb3VyaWVyLUJvbGRPYmxpcXVlIl0gPSB7CiAgICBhc2NlbnQ6IDYyOSwKICAgIGRlc2NlbnQ6IC0xNTcsCiAgICBjYXBIZWlnaHQ6IDU2MiwKICAgIHhIZWlnaHQ6IDQyNgogIH07CiAgdC5IZWx2ZXRpY2EgPSB7CiAgICBhc2NlbnQ6IDcxOCwKICAgIGRlc2NlbnQ6IC0yMDcsCiAgICBjYXBIZWlnaHQ6IDcxOCwKICAgIHhIZWlnaHQ6IDUyMwogIH07CiAgdFsiSGVsdmV0aWNhLUJvbGQiXSA9IHsKICAgIGFzY2VudDogNzE4LAogICAgZGVzY2VudDogLTIwNywKICAgIGNhcEhlaWdodDogNzE4LAogICAgeEhlaWdodDogNTMyCiAgfTsKICB0WyJIZWx2ZXRpY2EtT2JsaXF1ZSJdID0gewogICAgYXNjZW50OiA3MTgsCiAgICBkZXNjZW50OiAtMjA3LAogICAgY2FwSGVpZ2h0OiA3MTgsCiAgICB4SGVpZ2h0OiA1MjMKICB9OwogIHRbIkhlbHZldGljYS1Cb2xkT2JsaXF1ZSJdID0gewogICAgYXNjZW50OiA3MTgsCiAgICBkZXNjZW50OiAtMjA3LAogICAgY2FwSGVpZ2h0OiA3MTgsCiAgICB4SGVpZ2h0OiA1MzIKICB9OwogIHRbIlRpbWVzLVJvbWFuIl0gPSB7CiAgICBhc2NlbnQ6IDY4MywKICAgIGRlc2NlbnQ6IC0yMTcsCiAgICBjYXBIZWlnaHQ6IDY2MiwKICAgIHhIZWlnaHQ6IDQ1MAogIH07CiAgdFsiVGltZXMtQm9sZCJdID0gewogICAgYXNjZW50OiA2ODMsCiAgICBkZXNjZW50OiAtMjE3LAogICAgY2FwSGVpZ2h0OiA2NzYsCiAgICB4SGVpZ2h0OiA0NjEKICB9OwogIHRbIlRpbWVzLUl0YWxpYyJdID0gewogICAgYXNjZW50OiA2ODMsCiAgICBkZXNjZW50OiAtMjE3LAogICAgY2FwSGVpZ2h0OiA2NTMsCiAgICB4SGVpZ2h0OiA0NDEKICB9OwogIHRbIlRpbWVzLUJvbGRJdGFsaWMiXSA9IHsKICAgIGFzY2VudDogNjgzLAogICAgZGVzY2VudDogLTIxNywKICAgIGNhcEhlaWdodDogNjY5LAogICAgeEhlaWdodDogNDYyCiAgfTsKICB0LlN5bWJvbCA9IHsKICAgIGFzY2VudDogTWF0aC5OYU4sCiAgICBkZXNjZW50OiBNYXRoLk5hTiwKICAgIGNhcEhlaWdodDogTWF0aC5OYU4sCiAgICB4SGVpZ2h0OiBNYXRoLk5hTgogIH07CiAgdC5aYXBmRGluZ2JhdHMgPSB7CiAgICBhc2NlbnQ6IE1hdGguTmFOLAogICAgZGVzY2VudDogTWF0aC5OYU4sCiAgICBjYXBIZWlnaHQ6IE1hdGguTmFOLAogICAgeEhlaWdodDogTWF0aC5OYU4KICB9Owp9KTsKCjsvLyAuL3NyYy9jb3JlL2dseWYuanMKCgoKCgoKCgoKCgoKCmNvbnN0IE9OX0NVUlZFX1BPSU5UID0gMSA8PCAwOwpjb25zdCBYX1NIT1JUX1ZFQ1RPUiA9IDEgPDwgMTsKY29uc3QgWV9TSE9SVF9WRUNUT1IgPSAxIDw8IDI7CmNvbnN0IFJFUEVBVF9GTEFHID0gMSA8PCAzOwpjb25zdCBYX0lTX1NBTUVfT1JfUE9TSVRJVkVfWF9TSE9SVF9WRUNUT1IgPSAxIDw8IDQ7CmNvbnN0IFlfSVNfU0FNRV9PUl9QT1NJVElWRV9ZX1NIT1JUX1ZFQ1RPUiA9IDEgPDwgNTsKY29uc3QgT1ZFUkxBUF9TSU1QTEUgPSAxIDw8IDY7CmNvbnN0IEFSR18xX0FORF8yX0FSRV9XT1JEUyA9IDEgPDwgMDsKY29uc3QgQVJHU19BUkVfWFlfVkFMVUVTID0gMSA8PCAxOwpjb25zdCBXRV9IQVZFX0FfU0NBTEUgPSAxIDw8IDM7CmNvbnN0IE1PUkVfQ09NUE9ORU5UUyA9IDEgPDwgNTsKY29uc3QgV0VfSEFWRV9BTl9YX0FORF9ZX1NDQUxFID0gMSA8PCA2Owpjb25zdCBXRV9IQVZFX0FfVFdPX0JZX1RXTyA9IDEgPDwgNzsKY29uc3QgV0VfSEFWRV9JTlNUUlVDVElPTlMgPSAxIDw8IDg7CmNsYXNzIEdseWZUYWJsZSB7CiAgY29uc3RydWN0b3IoewogICAgZ2x5ZlRhYmxlLAogICAgaXNHbHlwaExvY2F0aW9uc0xvbmcsCiAgICBsb2NhVGFibGUsCiAgICBudW1HbHlwaHMKICB9KSB7CiAgICB0aGlzLmdseXBocyA9IFtdOwogICAgY29uc3QgbG9jYSA9IG5ldyBEYXRhVmlldyhsb2NhVGFibGUuYnVmZmVyLCBsb2NhVGFibGUuYnl0ZU9mZnNldCwgbG9jYVRhYmxlLmJ5dGVMZW5ndGgpOwogICAgY29uc3QgZ2x5ZiA9IG5ldyBEYXRhVmlldyhnbHlmVGFibGUuYnVmZmVyLCBnbHlmVGFibGUuYnl0ZU9mZnNldCwgZ2x5ZlRhYmxlLmJ5dGVMZW5ndGgpOwogICAgY29uc3Qgb2Zmc2V0U2l6ZSA9IGlzR2x5cGhMb2NhdGlvbnNMb25nID8gNCA6IDI7CiAgICBsZXQgcHJldiA9IGlzR2x5cGhMb2NhdGlvbnNMb25nID8gbG9jYS5nZXRVaW50MzIoMCkgOiAyICogbG9jYS5nZXRVaW50MTYoMCk7CiAgICBsZXQgcG9zID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtR2x5cGhzOyBpKyspIHsKICAgICAgcG9zICs9IG9mZnNldFNpemU7CiAgICAgIGNvbnN0IG5leHQgPSBpc0dseXBoTG9jYXRpb25zTG9uZyA/IGxvY2EuZ2V0VWludDMyKHBvcykgOiAyICogbG9jYS5nZXRVaW50MTYocG9zKTsKICAgICAgaWYgKG5leHQgPT09IHByZXYpIHsKICAgICAgICB0aGlzLmdseXBocy5wdXNoKG5ldyBHbHlwaCh7fSkpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGdseXBoID0gR2x5cGgucGFyc2UocHJldiwgZ2x5Zik7CiAgICAgIHRoaXMuZ2x5cGhzLnB1c2goZ2x5cGgpOwogICAgICBwcmV2ID0gbmV4dDsKICAgIH0KICB9CiAgZ2V0U2l6ZSgpIHsKICAgIHJldHVybiBNYXRoLnN1bVByZWNpc2UodGhpcy5nbHlwaHMubWFwKGcgPT4gZy5nZXRTaXplKCkgKyAzICYgfjMpKTsKICB9CiAgd3JpdGUoKSB7CiAgICBjb25zdCB0b3RhbFNpemUgPSB0aGlzLmdldFNpemUoKTsKICAgIGNvbnN0IGdseWZUYWJsZSA9IG5ldyBEYXRhVmlldyhuZXcgQXJyYXlCdWZmZXIodG90YWxTaXplKSk7CiAgICBjb25zdCBpc0xvY2F0aW9uTG9uZyA9IHRvdGFsU2l6ZSA+IDB4MWZmZmU7CiAgICBjb25zdCBvZmZzZXRTaXplID0gaXNMb2NhdGlvbkxvbmcgPyA0IDogMjsKICAgIGNvbnN0IGxvY2FUYWJsZSA9IG5ldyBEYXRhVmlldyhuZXcgQXJyYXlCdWZmZXIoKHRoaXMuZ2x5cGhzLmxlbmd0aCArIDEpICogb2Zmc2V0U2l6ZSkpOwogICAgaWYgKGlzTG9jYXRpb25Mb25nKSB7CiAgICAgIGxvY2FUYWJsZS5zZXRVaW50MzIoMCwgMCk7CiAgICB9IGVsc2UgewogICAgICBsb2NhVGFibGUuc2V0VWludDE2KDAsIDApOwogICAgfQogICAgbGV0IHBvcyA9IDA7CiAgICBsZXQgbG9jYUluZGV4ID0gMDsKICAgIGZvciAoY29uc3QgZ2x5cGggb2YgdGhpcy5nbHlwaHMpIHsKICAgICAgcG9zICs9IGdseXBoLndyaXRlKHBvcywgZ2x5ZlRhYmxlKTsKICAgICAgcG9zID0gcG9zICsgMyAmIH4zOwogICAgICBsb2NhSW5kZXggKz0gb2Zmc2V0U2l6ZTsKICAgICAgaWYgKGlzTG9jYXRpb25Mb25nKSB7CiAgICAgICAgbG9jYVRhYmxlLnNldFVpbnQzMihsb2NhSW5kZXgsIHBvcyk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbG9jYVRhYmxlLnNldFVpbnQxNihsb2NhSW5kZXgsIHBvcyA+PiAxKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHsKICAgICAgaXNMb2NhdGlvbkxvbmcsCiAgICAgIGxvY2E6IG5ldyBVaW50OEFycmF5KGxvY2FUYWJsZS5idWZmZXIpLAogICAgICBnbHlmOiBuZXcgVWludDhBcnJheShnbHlmVGFibGUuYnVmZmVyKQogICAgfTsKICB9CiAgc2NhbGUoZmFjdG9ycykgewogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gdGhpcy5nbHlwaHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICB0aGlzLmdseXBoc1tpXS5zY2FsZShmYWN0b3JzW2ldKTsKICAgIH0KICB9Cn0KY2xhc3MgR2x5cGggewogIGNvbnN0cnVjdG9yKHsKICAgIGhlYWRlciA9IG51bGwsCiAgICBzaW1wbGUgPSBudWxsLAogICAgY29tcG9zaXRlcyA9IG51bGwKICB9KSB7CiAgICB0aGlzLmhlYWRlciA9IGhlYWRlcjsKICAgIHRoaXMuc2ltcGxlID0gc2ltcGxlOwogICAgdGhpcy5jb21wb3NpdGVzID0gY29tcG9zaXRlczsKICB9CiAgc3RhdGljIHBhcnNlKHBvcywgZ2x5ZikgewogICAgY29uc3QgW3JlYWQsIGhlYWRlcl0gPSBHbHlwaEhlYWRlci5wYXJzZShwb3MsIGdseWYpOwogICAgcG9zICs9IHJlYWQ7CiAgICBpZiAoaGVhZGVyLm51bWJlck9mQ29udG91cnMgPCAwKSB7CiAgICAgIGNvbnN0IGNvbXBvc2l0ZXMgPSBbXTsKICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICBjb25zdCBbbiwgY29tcG9zaXRlXSA9IENvbXBvc2l0ZUdseXBoLnBhcnNlKHBvcywgZ2x5Zik7CiAgICAgICAgcG9zICs9IG47CiAgICAgICAgY29tcG9zaXRlcy5wdXNoKGNvbXBvc2l0ZSk7CiAgICAgICAgaWYgKCEoY29tcG9zaXRlLmZsYWdzICYgTU9SRV9DT01QT05FTlRTKSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBuZXcgR2x5cGgoewogICAgICAgIGhlYWRlciwKICAgICAgICBjb21wb3NpdGVzCiAgICAgIH0pOwogICAgfQogICAgY29uc3Qgc2ltcGxlID0gU2ltcGxlR2x5cGgucGFyc2UocG9zLCBnbHlmLCBoZWFkZXIubnVtYmVyT2ZDb250b3Vycyk7CiAgICByZXR1cm4gbmV3IEdseXBoKHsKICAgICAgaGVhZGVyLAogICAgICBzaW1wbGUKICAgIH0pOwogIH0KICBnZXRTaXplKCkgewogICAgaWYgKCF0aGlzLmhlYWRlcikgewogICAgICByZXR1cm4gMDsKICAgIH0KICAgIGNvbnN0IHNpemUgPSB0aGlzLnNpbXBsZSA/IHRoaXMuc2ltcGxlLmdldFNpemUoKSA6IE1hdGguc3VtUHJlY2lzZSh0aGlzLmNvbXBvc2l0ZXMubWFwKGMgPT4gYy5nZXRTaXplKCkpKTsKICAgIHJldHVybiB0aGlzLmhlYWRlci5nZXRTaXplKCkgKyBzaXplOwogIH0KICB3cml0ZShwb3MsIGJ1ZikgewogICAgaWYgKCF0aGlzLmhlYWRlcikgewogICAgICByZXR1cm4gMDsKICAgIH0KICAgIGNvbnN0IHNwb3MgPSBwb3M7CiAgICBwb3MgKz0gdGhpcy5oZWFkZXIud3JpdGUocG9zLCBidWYpOwogICAgaWYgKHRoaXMuc2ltcGxlKSB7CiAgICAgIHBvcyArPSB0aGlzLnNpbXBsZS53cml0ZShwb3MsIGJ1Zik7CiAgICB9IGVsc2UgewogICAgICBmb3IgKGNvbnN0IGNvbXBvc2l0ZSBvZiB0aGlzLmNvbXBvc2l0ZXMpIHsKICAgICAgICBwb3MgKz0gY29tcG9zaXRlLndyaXRlKHBvcywgYnVmKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHBvcyAtIHNwb3M7CiAgfQogIHNjYWxlKGZhY3RvcikgewogICAgaWYgKCF0aGlzLmhlYWRlcikgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCB4TWlkZGxlID0gKHRoaXMuaGVhZGVyLnhNaW4gKyB0aGlzLmhlYWRlci54TWF4KSAvIDI7CiAgICB0aGlzLmhlYWRlci5zY2FsZSh4TWlkZGxlLCBmYWN0b3IpOwogICAgaWYgKHRoaXMuc2ltcGxlKSB7CiAgICAgIHRoaXMuc2ltcGxlLnNjYWxlKHhNaWRkbGUsIGZhY3Rvcik7CiAgICB9IGVsc2UgewogICAgICBmb3IgKGNvbnN0IGNvbXBvc2l0ZSBvZiB0aGlzLmNvbXBvc2l0ZXMpIHsKICAgICAgICBjb21wb3NpdGUuc2NhbGUoeE1pZGRsZSwgZmFjdG9yKTsKICAgICAgfQogICAgfQogIH0KfQpjbGFzcyBHbHlwaEhlYWRlciB7CiAgY29uc3RydWN0b3IoewogICAgbnVtYmVyT2ZDb250b3VycywKICAgIHhNaW4sCiAgICB5TWluLAogICAgeE1heCwKICAgIHlNYXgKICB9KSB7CiAgICB0aGlzLm51bWJlck9mQ29udG91cnMgPSBudW1iZXJPZkNvbnRvdXJzOwogICAgdGhpcy54TWluID0geE1pbjsKICAgIHRoaXMueU1pbiA9IHlNaW47CiAgICB0aGlzLnhNYXggPSB4TWF4OwogICAgdGhpcy55TWF4ID0geU1heDsKICB9CiAgc3RhdGljIHBhcnNlKHBvcywgZ2x5ZikgewogICAgcmV0dXJuIFsxMCwgbmV3IEdseXBoSGVhZGVyKHsKICAgICAgbnVtYmVyT2ZDb250b3VyczogZ2x5Zi5nZXRJbnQxNihwb3MpLAogICAgICB4TWluOiBnbHlmLmdldEludDE2KHBvcyArIDIpLAogICAgICB5TWluOiBnbHlmLmdldEludDE2KHBvcyArIDQpLAogICAgICB4TWF4OiBnbHlmLmdldEludDE2KHBvcyArIDYpLAogICAgICB5TWF4OiBnbHlmLmdldEludDE2KHBvcyArIDgpCiAgICB9KV07CiAgfQogIGdldFNpemUoKSB7CiAgICByZXR1cm4gMTA7CiAgfQogIHdyaXRlKHBvcywgYnVmKSB7CiAgICBidWYuc2V0SW50MTYocG9zLCB0aGlzLm51bWJlck9mQ29udG91cnMpOwogICAgYnVmLnNldEludDE2KHBvcyArIDIsIHRoaXMueE1pbik7CiAgICBidWYuc2V0SW50MTYocG9zICsgNCwgdGhpcy55TWluKTsKICAgIGJ1Zi5zZXRJbnQxNihwb3MgKyA2LCB0aGlzLnhNYXgpOwogICAgYnVmLnNldEludDE2KHBvcyArIDgsIHRoaXMueU1heCk7CiAgICByZXR1cm4gMTA7CiAgfQogIHNjYWxlKHgsIGZhY3RvcikgewogICAgdGhpcy54TWluID0gTWF0aC5yb3VuZCh4ICsgKHRoaXMueE1pbiAtIHgpICogZmFjdG9yKTsKICAgIHRoaXMueE1heCA9IE1hdGgucm91bmQoeCArICh0aGlzLnhNYXggLSB4KSAqIGZhY3Rvcik7CiAgfQp9CmNsYXNzIENvbnRvdXIgewogIGNvbnN0cnVjdG9yKHsKICAgIGZsYWdzLAogICAgeENvb3JkaW5hdGVzLAogICAgeUNvb3JkaW5hdGVzCiAgfSkgewogICAgdGhpcy54Q29vcmRpbmF0ZXMgPSB4Q29vcmRpbmF0ZXM7CiAgICB0aGlzLnlDb29yZGluYXRlcyA9IHlDb29yZGluYXRlczsKICAgIHRoaXMuZmxhZ3MgPSBmbGFnczsKICB9Cn0KY2xhc3MgU2ltcGxlR2x5cGggewogIGNvbnN0cnVjdG9yKHsKICAgIGNvbnRvdXJzLAogICAgaW5zdHJ1Y3Rpb25zCiAgfSkgewogICAgdGhpcy5jb250b3VycyA9IGNvbnRvdXJzOwogICAgdGhpcy5pbnN0cnVjdGlvbnMgPSBpbnN0cnVjdGlvbnM7CiAgfQogIHN0YXRpYyBwYXJzZShwb3MsIGdseWYsIG51bWJlck9mQ29udG91cnMpIHsKICAgIGNvbnN0IGVuZFB0c09mQ29udG91cnMgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZDb250b3VyczsgaSsrKSB7CiAgICAgIGNvbnN0IGVuZFB0ID0gZ2x5Zi5nZXRVaW50MTYocG9zKTsKICAgICAgcG9zICs9IDI7CiAgICAgIGVuZFB0c09mQ29udG91cnMucHVzaChlbmRQdCk7CiAgICB9CiAgICBjb25zdCBudW1iZXJPZlB0ID0gZW5kUHRzT2ZDb250b3Vyc1tudW1iZXJPZkNvbnRvdXJzIC0gMV0gKyAxOwogICAgY29uc3QgaW5zdHJ1Y3Rpb25MZW5ndGggPSBnbHlmLmdldFVpbnQxNihwb3MpOwogICAgcG9zICs9IDI7CiAgICBjb25zdCBpbnN0cnVjdGlvbnMgPSBuZXcgVWludDhBcnJheShnbHlmKS5zbGljZShwb3MsIHBvcyArIGluc3RydWN0aW9uTGVuZ3RoKTsKICAgIHBvcyArPSBpbnN0cnVjdGlvbkxlbmd0aDsKICAgIGNvbnN0IGZsYWdzID0gW107CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bWJlck9mUHQ7IHBvcysrLCBpKyspIHsKICAgICAgbGV0IGZsYWcgPSBnbHlmLmdldFVpbnQ4KHBvcyk7CiAgICAgIGZsYWdzLnB1c2goZmxhZyk7CiAgICAgIGlmIChmbGFnICYgUkVQRUFUX0ZMQUcpIHsKICAgICAgICBjb25zdCBjb3VudCA9IGdseWYuZ2V0VWludDgoKytwb3MpOwogICAgICAgIGZsYWcgXj0gUkVQRUFUX0ZMQUc7CiAgICAgICAgZm9yIChsZXQgbSA9IDA7IG0gPCBjb3VudDsgbSsrKSB7CiAgICAgICAgICBmbGFncy5wdXNoKGZsYWcpOwogICAgICAgIH0KICAgICAgICBpICs9IGNvdW50OwogICAgICB9CiAgICB9CiAgICBjb25zdCBhbGxYQ29vcmRpbmF0ZXMgPSBbXTsKICAgIGxldCB4Q29vcmRpbmF0ZXMgPSBbXTsKICAgIGxldCB5Q29vcmRpbmF0ZXMgPSBbXTsKICAgIGxldCBwb2ludEZsYWdzID0gW107CiAgICBjb25zdCBjb250b3VycyA9IFtdOwogICAgbGV0IGVuZFB0c09mQ29udG91cnNJbmRleCA9IDA7CiAgICBsZXQgbGFzdENvb3JkaW5hdGUgPSAwOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJPZlB0OyBpKyspIHsKICAgICAgY29uc3QgZmxhZyA9IGZsYWdzW2ldOwogICAgICBpZiAoZmxhZyAmIFhfU0hPUlRfVkVDVE9SKSB7CiAgICAgICAgY29uc3QgeCA9IGdseWYuZ2V0VWludDgocG9zKyspOwogICAgICAgIGxhc3RDb29yZGluYXRlICs9IGZsYWcgJiBYX0lTX1NBTUVfT1JfUE9TSVRJVkVfWF9TSE9SVF9WRUNUT1IgPyB4IDogLXg7CiAgICAgICAgeENvb3JkaW5hdGVzLnB1c2gobGFzdENvb3JkaW5hdGUpOwogICAgICB9IGVsc2UgaWYgKGZsYWcgJiBYX0lTX1NBTUVfT1JfUE9TSVRJVkVfWF9TSE9SVF9WRUNUT1IpIHsKICAgICAgICB4Q29vcmRpbmF0ZXMucHVzaChsYXN0Q29vcmRpbmF0ZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbGFzdENvb3JkaW5hdGUgKz0gZ2x5Zi5nZXRJbnQxNihwb3MpOwogICAgICAgIHBvcyArPSAyOwogICAgICAgIHhDb29yZGluYXRlcy5wdXNoKGxhc3RDb29yZGluYXRlKTsKICAgICAgfQogICAgICBpZiAoZW5kUHRzT2ZDb250b3Vyc1tlbmRQdHNPZkNvbnRvdXJzSW5kZXhdID09PSBpKSB7CiAgICAgICAgZW5kUHRzT2ZDb250b3Vyc0luZGV4Kys7CiAgICAgICAgYWxsWENvb3JkaW5hdGVzLnB1c2goeENvb3JkaW5hdGVzKTsKICAgICAgICB4Q29vcmRpbmF0ZXMgPSBbXTsKICAgICAgfQogICAgfQogICAgbGFzdENvb3JkaW5hdGUgPSAwOwogICAgZW5kUHRzT2ZDb250b3Vyc0luZGV4ID0gMDsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZQdDsgaSsrKSB7CiAgICAgIGNvbnN0IGZsYWcgPSBmbGFnc1tpXTsKICAgICAgaWYgKGZsYWcgJiBZX1NIT1JUX1ZFQ1RPUikgewogICAgICAgIGNvbnN0IHkgPSBnbHlmLmdldFVpbnQ4KHBvcysrKTsKICAgICAgICBsYXN0Q29vcmRpbmF0ZSArPSBmbGFnICYgWV9JU19TQU1FX09SX1BPU0lUSVZFX1lfU0hPUlRfVkVDVE9SID8geSA6IC15OwogICAgICAgIHlDb29yZGluYXRlcy5wdXNoKGxhc3RDb29yZGluYXRlKTsKICAgICAgfSBlbHNlIGlmIChmbGFnICYgWV9JU19TQU1FX09SX1BPU0lUSVZFX1lfU0hPUlRfVkVDVE9SKSB7CiAgICAgICAgeUNvb3JkaW5hdGVzLnB1c2gobGFzdENvb3JkaW5hdGUpOwogICAgICB9IGVsc2UgewogICAgICAgIGxhc3RDb29yZGluYXRlICs9IGdseWYuZ2V0SW50MTYocG9zKTsKICAgICAgICBwb3MgKz0gMjsKICAgICAgICB5Q29vcmRpbmF0ZXMucHVzaChsYXN0Q29vcmRpbmF0ZSk7CiAgICAgIH0KICAgICAgcG9pbnRGbGFncy5wdXNoKGZsYWcgJiBPTl9DVVJWRV9QT0lOVCB8IGZsYWcgJiBPVkVSTEFQX1NJTVBMRSk7CiAgICAgIGlmIChlbmRQdHNPZkNvbnRvdXJzW2VuZFB0c09mQ29udG91cnNJbmRleF0gPT09IGkpIHsKICAgICAgICB4Q29vcmRpbmF0ZXMgPSBhbGxYQ29vcmRpbmF0ZXNbZW5kUHRzT2ZDb250b3Vyc0luZGV4XTsKICAgICAgICBlbmRQdHNPZkNvbnRvdXJzSW5kZXgrKzsKICAgICAgICBjb250b3Vycy5wdXNoKG5ldyBDb250b3VyKHsKICAgICAgICAgIGZsYWdzOiBwb2ludEZsYWdzLAogICAgICAgICAgeENvb3JkaW5hdGVzLAogICAgICAgICAgeUNvb3JkaW5hdGVzCiAgICAgICAgfSkpOwogICAgICAgIHlDb29yZGluYXRlcyA9IFtdOwogICAgICAgIHBvaW50RmxhZ3MgPSBbXTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIG5ldyBTaW1wbGVHbHlwaCh7CiAgICAgIGNvbnRvdXJzLAogICAgICBpbnN0cnVjdGlvbnMKICAgIH0pOwogIH0KICBnZXRTaXplKCkgewogICAgbGV0IHNpemUgPSB0aGlzLmNvbnRvdXJzLmxlbmd0aCAqIDIgKyAyICsgdGhpcy5pbnN0cnVjdGlvbnMubGVuZ3RoOwogICAgbGV0IGxhc3RYID0gMDsKICAgIGxldCBsYXN0WSA9IDA7CiAgICBmb3IgKGNvbnN0IGNvbnRvdXIgb2YgdGhpcy5jb250b3VycykgewogICAgICBzaXplICs9IGNvbnRvdXIuZmxhZ3MubGVuZ3RoOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBjb250b3VyLnhDb29yZGluYXRlcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29uc3QgeCA9IGNvbnRvdXIueENvb3JkaW5hdGVzW2ldOwogICAgICAgIGNvbnN0IHkgPSBjb250b3VyLnlDb29yZGluYXRlc1tpXTsKICAgICAgICBsZXQgYWJzID0gTWF0aC5hYnMoeCAtIGxhc3RYKTsKICAgICAgICBpZiAoYWJzID4gMjU1KSB7CiAgICAgICAgICBzaXplICs9IDI7CiAgICAgICAgfSBlbHNlIGlmIChhYnMgPiAwKSB7CiAgICAgICAgICBzaXplICs9IDE7CiAgICAgICAgfQogICAgICAgIGxhc3RYID0geDsKICAgICAgICBhYnMgPSBNYXRoLmFicyh5IC0gbGFzdFkpOwogICAgICAgIGlmIChhYnMgPiAyNTUpIHsKICAgICAgICAgIHNpemUgKz0gMjsKICAgICAgICB9IGVsc2UgaWYgKGFicyA+IDApIHsKICAgICAgICAgIHNpemUgKz0gMTsKICAgICAgICB9CiAgICAgICAgbGFzdFkgPSB5OwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2l6ZTsKICB9CiAgd3JpdGUocG9zLCBidWYpIHsKICAgIGNvbnN0IHNwb3MgPSBwb3M7CiAgICBjb25zdCB4Q29vcmRpbmF0ZXMgPSBbXTsKICAgIGNvbnN0IHlDb29yZGluYXRlcyA9IFtdOwogICAgY29uc3QgZmxhZ3MgPSBbXTsKICAgIGxldCBsYXN0WCA9IDA7CiAgICBsZXQgbGFzdFkgPSAwOwogICAgZm9yIChjb25zdCBjb250b3VyIG9mIHRoaXMuY29udG91cnMpIHsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gY29udG91ci54Q29vcmRpbmF0ZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGxldCBmbGFnID0gY29udG91ci5mbGFnc1tpXTsKICAgICAgICBjb25zdCB4ID0gY29udG91ci54Q29vcmRpbmF0ZXNbaV07CiAgICAgICAgbGV0IGRlbHRhID0geCAtIGxhc3RYOwogICAgICAgIGlmIChkZWx0YSA9PT0gMCkgewogICAgICAgICAgZmxhZyB8PSBYX0lTX1NBTUVfT1JfUE9TSVRJVkVfWF9TSE9SVF9WRUNUT1I7CiAgICAgICAgICB4Q29vcmRpbmF0ZXMucHVzaCgwKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3QgYWJzID0gTWF0aC5hYnMoZGVsdGEpOwogICAgICAgICAgaWYgKGFicyA8PSAyNTUpIHsKICAgICAgICAgICAgZmxhZyB8PSBkZWx0YSA+PSAwID8gWF9TSE9SVF9WRUNUT1IgfCBYX0lTX1NBTUVfT1JfUE9TSVRJVkVfWF9TSE9SVF9WRUNUT1IgOiBYX1NIT1JUX1ZFQ1RPUjsKICAgICAgICAgICAgeENvb3JkaW5hdGVzLnB1c2goYWJzKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHhDb29yZGluYXRlcy5wdXNoKGRlbHRhKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbGFzdFggPSB4OwogICAgICAgIGNvbnN0IHkgPSBjb250b3VyLnlDb29yZGluYXRlc1tpXTsKICAgICAgICBkZWx0YSA9IHkgLSBsYXN0WTsKICAgICAgICBpZiAoZGVsdGEgPT09IDApIHsKICAgICAgICAgIGZsYWcgfD0gWV9JU19TQU1FX09SX1BPU0lUSVZFX1lfU0hPUlRfVkVDVE9SOwogICAgICAgICAgeUNvb3JkaW5hdGVzLnB1c2goMCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNvbnN0IGFicyA9IE1hdGguYWJzKGRlbHRhKTsKICAgICAgICAgIGlmIChhYnMgPD0gMjU1KSB7CiAgICAgICAgICAgIGZsYWcgfD0gZGVsdGEgPj0gMCA/IFlfU0hPUlRfVkVDVE9SIHwgWV9JU19TQU1FX09SX1BPU0lUSVZFX1lfU0hPUlRfVkVDVE9SIDogWV9TSE9SVF9WRUNUT1I7CiAgICAgICAgICAgIHlDb29yZGluYXRlcy5wdXNoKGFicyk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICB5Q29vcmRpbmF0ZXMucHVzaChkZWx0YSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGxhc3RZID0geTsKICAgICAgICBmbGFncy5wdXNoKGZsYWcpOwogICAgICB9CiAgICAgIGJ1Zi5zZXRVaW50MTYocG9zLCB4Q29vcmRpbmF0ZXMubGVuZ3RoIC0gMSk7CiAgICAgIHBvcyArPSAyOwogICAgfQogICAgYnVmLnNldFVpbnQxNihwb3MsIHRoaXMuaW5zdHJ1Y3Rpb25zLmxlbmd0aCk7CiAgICBwb3MgKz0gMjsKICAgIGlmICh0aGlzLmluc3RydWN0aW9ucy5sZW5ndGgpIHsKICAgICAgbmV3IFVpbnQ4QXJyYXkoYnVmLmJ1ZmZlciwgMCwgYnVmLmJ1ZmZlci5ieXRlTGVuZ3RoKS5zZXQodGhpcy5pbnN0cnVjdGlvbnMsIHBvcyk7CiAgICAgIHBvcyArPSB0aGlzLmluc3RydWN0aW9ucy5sZW5ndGg7CiAgICB9CiAgICBmb3IgKGNvbnN0IGZsYWcgb2YgZmxhZ3MpIHsKICAgICAgYnVmLnNldFVpbnQ4KHBvcysrLCBmbGFnKTsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHhDb29yZGluYXRlcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IHggPSB4Q29vcmRpbmF0ZXNbaV07CiAgICAgIGNvbnN0IGZsYWcgPSBmbGFnc1tpXTsKICAgICAgaWYgKGZsYWcgJiBYX1NIT1JUX1ZFQ1RPUikgewogICAgICAgIGJ1Zi5zZXRVaW50OChwb3MrKywgeCk7CiAgICAgIH0gZWxzZSBpZiAoIShmbGFnICYgWF9JU19TQU1FX09SX1BPU0lUSVZFX1hfU0hPUlRfVkVDVE9SKSkgewogICAgICAgIGJ1Zi5zZXRJbnQxNihwb3MsIHgpOwogICAgICAgIHBvcyArPSAyOwogICAgICB9CiAgICB9CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB5Q29vcmRpbmF0ZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCB5ID0geUNvb3JkaW5hdGVzW2ldOwogICAgICBjb25zdCBmbGFnID0gZmxhZ3NbaV07CiAgICAgIGlmIChmbGFnICYgWV9TSE9SVF9WRUNUT1IpIHsKICAgICAgICBidWYuc2V0VWludDgocG9zKyssIHkpOwogICAgICB9IGVsc2UgaWYgKCEoZmxhZyAmIFlfSVNfU0FNRV9PUl9QT1NJVElWRV9ZX1NIT1JUX1ZFQ1RPUikpIHsKICAgICAgICBidWYuc2V0SW50MTYocG9zLCB5KTsKICAgICAgICBwb3MgKz0gMjsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHBvcyAtIHNwb3M7CiAgfQogIHNjYWxlKHgsIGZhY3RvcikgewogICAgZm9yIChjb25zdCBjb250b3VyIG9mIHRoaXMuY29udG91cnMpIHsKICAgICAgaWYgKGNvbnRvdXIueENvb3JkaW5hdGVzLmxlbmd0aCA9PT0gMCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGNvbnRvdXIueENvb3JkaW5hdGVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBjb250b3VyLnhDb29yZGluYXRlc1tpXSA9IE1hdGgucm91bmQoeCArIChjb250b3VyLnhDb29yZGluYXRlc1tpXSAtIHgpICogZmFjdG9yKTsKICAgICAgfQogICAgfQogIH0KfQpjbGFzcyBDb21wb3NpdGVHbHlwaCB7CiAgY29uc3RydWN0b3IoewogICAgZmxhZ3MsCiAgICBnbHlwaEluZGV4LAogICAgYXJndW1lbnQxLAogICAgYXJndW1lbnQyLAogICAgdHJhbnNmLAogICAgaW5zdHJ1Y3Rpb25zCiAgfSkgewogICAgdGhpcy5mbGFncyA9IGZsYWdzOwogICAgdGhpcy5nbHlwaEluZGV4ID0gZ2x5cGhJbmRleDsKICAgIHRoaXMuYXJndW1lbnQxID0gYXJndW1lbnQxOwogICAgdGhpcy5hcmd1bWVudDIgPSBhcmd1bWVudDI7CiAgICB0aGlzLnRyYW5zZiA9IHRyYW5zZjsKICAgIHRoaXMuaW5zdHJ1Y3Rpb25zID0gaW5zdHJ1Y3Rpb25zOwogIH0KICBzdGF0aWMgcGFyc2UocG9zLCBnbHlmKSB7CiAgICBjb25zdCBzcG9zID0gcG9zOwogICAgY29uc3QgdHJhbnNmID0gW107CiAgICBsZXQgZmxhZ3MgPSBnbHlmLmdldFVpbnQxNihwb3MpOwogICAgY29uc3QgZ2x5cGhJbmRleCA9IGdseWYuZ2V0VWludDE2KHBvcyArIDIpOwogICAgcG9zICs9IDQ7CiAgICBsZXQgYXJndW1lbnQxLCBhcmd1bWVudDI7CiAgICBpZiAoZmxhZ3MgJiBBUkdfMV9BTkRfMl9BUkVfV09SRFMpIHsKICAgICAgaWYgKGZsYWdzICYgQVJHU19BUkVfWFlfVkFMVUVTKSB7CiAgICAgICAgYXJndW1lbnQxID0gZ2x5Zi5nZXRJbnQxNihwb3MpOwogICAgICAgIGFyZ3VtZW50MiA9IGdseWYuZ2V0SW50MTYocG9zICsgMik7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYXJndW1lbnQxID0gZ2x5Zi5nZXRVaW50MTYocG9zKTsKICAgICAgICBhcmd1bWVudDIgPSBnbHlmLmdldFVpbnQxNihwb3MgKyAyKTsKICAgICAgfQogICAgICBwb3MgKz0gNDsKICAgICAgZmxhZ3MgXj0gQVJHXzFfQU5EXzJfQVJFX1dPUkRTOwogICAgfSBlbHNlIHsKICAgICAgaWYgKGZsYWdzICYgQVJHU19BUkVfWFlfVkFMVUVTKSB7CiAgICAgICAgYXJndW1lbnQxID0gZ2x5Zi5nZXRJbnQ4KHBvcyk7CiAgICAgICAgYXJndW1lbnQyID0gZ2x5Zi5nZXRJbnQ4KHBvcyArIDEpOwogICAgICB9IGVsc2UgewogICAgICAgIGFyZ3VtZW50MSA9IGdseWYuZ2V0VWludDgocG9zKTsKICAgICAgICBhcmd1bWVudDIgPSBnbHlmLmdldFVpbnQ4KHBvcyArIDEpOwogICAgICB9CiAgICAgIHBvcyArPSAyOwogICAgfQogICAgaWYgKGZsYWdzICYgV0VfSEFWRV9BX1NDQUxFKSB7CiAgICAgIHRyYW5zZi5wdXNoKGdseWYuZ2V0VWludDE2KHBvcykpOwogICAgICBwb3MgKz0gMjsKICAgIH0gZWxzZSBpZiAoZmxhZ3MgJiBXRV9IQVZFX0FOX1hfQU5EX1lfU0NBTEUpIHsKICAgICAgdHJhbnNmLnB1c2goZ2x5Zi5nZXRVaW50MTYocG9zKSwgZ2x5Zi5nZXRVaW50MTYocG9zICsgMikpOwogICAgICBwb3MgKz0gNDsKICAgIH0gZWxzZSBpZiAoZmxhZ3MgJiBXRV9IQVZFX0FfVFdPX0JZX1RXTykgewogICAgICB0cmFuc2YucHVzaChnbHlmLmdldFVpbnQxNihwb3MpLCBnbHlmLmdldFVpbnQxNihwb3MgKyAyKSwgZ2x5Zi5nZXRVaW50MTYocG9zICsgNCksIGdseWYuZ2V0VWludDE2KHBvcyArIDYpKTsKICAgICAgcG9zICs9IDg7CiAgICB9CiAgICBsZXQgaW5zdHJ1Y3Rpb25zID0gbnVsbDsKICAgIGlmIChmbGFncyAmIFdFX0hBVkVfSU5TVFJVQ1RJT05TKSB7CiAgICAgIGNvbnN0IGluc3RydWN0aW9uTGVuZ3RoID0gZ2x5Zi5nZXRVaW50MTYocG9zKTsKICAgICAgcG9zICs9IDI7CiAgICAgIGluc3RydWN0aW9ucyA9IG5ldyBVaW50OEFycmF5KGdseWYpLnNsaWNlKHBvcywgcG9zICsgaW5zdHJ1Y3Rpb25MZW5ndGgpOwogICAgICBwb3MgKz0gaW5zdHJ1Y3Rpb25MZW5ndGg7CiAgICB9CiAgICByZXR1cm4gW3BvcyAtIHNwb3MsIG5ldyBDb21wb3NpdGVHbHlwaCh7CiAgICAgIGZsYWdzLAogICAgICBnbHlwaEluZGV4LAogICAgICBhcmd1bWVudDEsCiAgICAgIGFyZ3VtZW50MiwKICAgICAgdHJhbnNmLAogICAgICBpbnN0cnVjdGlvbnMKICAgIH0pXTsKICB9CiAgZ2V0U2l6ZSgpIHsKICAgIGxldCBzaXplID0gMiArIDIgKyB0aGlzLnRyYW5zZi5sZW5ndGggKiAyOwogICAgaWYgKHRoaXMuZmxhZ3MgJiBXRV9IQVZFX0lOU1RSVUNUSU9OUykgewogICAgICBzaXplICs9IDIgKyB0aGlzLmluc3RydWN0aW9ucy5sZW5ndGg7CiAgICB9CiAgICBzaXplICs9IDI7CiAgICBpZiAodGhpcy5mbGFncyAmIDIpIHsKICAgICAgaWYgKCEodGhpcy5hcmd1bWVudDEgPj0gLTEyOCAmJiB0aGlzLmFyZ3VtZW50MSA8PSAxMjcgJiYgdGhpcy5hcmd1bWVudDIgPj0gLTEyOCAmJiB0aGlzLmFyZ3VtZW50MiA8PSAxMjcpKSB7CiAgICAgICAgc2l6ZSArPSAyOwogICAgICB9CiAgICB9IGVsc2UgaWYgKCEodGhpcy5hcmd1bWVudDEgPj0gMCAmJiB0aGlzLmFyZ3VtZW50MSA8PSAyNTUgJiYgdGhpcy5hcmd1bWVudDIgPj0gMCAmJiB0aGlzLmFyZ3VtZW50MiA8PSAyNTUpKSB7CiAgICAgIHNpemUgKz0gMjsKICAgIH0KICAgIHJldHVybiBzaXplOwogIH0KICB3cml0ZShwb3MsIGJ1ZikgewogICAgY29uc3Qgc3BvcyA9IHBvczsKICAgIGlmICh0aGlzLmZsYWdzICYgQVJHU19BUkVfWFlfVkFMVUVTKSB7CiAgICAgIGlmICghKHRoaXMuYXJndW1lbnQxID49IC0xMjggJiYgdGhpcy5hcmd1bWVudDEgPD0gMTI3ICYmIHRoaXMuYXJndW1lbnQyID49IC0xMjggJiYgdGhpcy5hcmd1bWVudDIgPD0gMTI3KSkgewogICAgICAgIHRoaXMuZmxhZ3MgfD0gQVJHXzFfQU5EXzJfQVJFX1dPUkRTOwogICAgICB9CiAgICB9IGVsc2UgaWYgKCEodGhpcy5hcmd1bWVudDEgPj0gMCAmJiB0aGlzLmFyZ3VtZW50MSA8PSAyNTUgJiYgdGhpcy5hcmd1bWVudDIgPj0gMCAmJiB0aGlzLmFyZ3VtZW50MiA8PSAyNTUpKSB7CiAgICAgIHRoaXMuZmxhZ3MgfD0gQVJHXzFfQU5EXzJfQVJFX1dPUkRTOwogICAgfQogICAgYnVmLnNldFVpbnQxNihwb3MsIHRoaXMuZmxhZ3MpOwogICAgYnVmLnNldFVpbnQxNihwb3MgKyAyLCB0aGlzLmdseXBoSW5kZXgpOwogICAgcG9zICs9IDQ7CiAgICBpZiAodGhpcy5mbGFncyAmIEFSR18xX0FORF8yX0FSRV9XT1JEUykgewogICAgICBpZiAodGhpcy5mbGFncyAmIEFSR1NfQVJFX1hZX1ZBTFVFUykgewogICAgICAgIGJ1Zi5zZXRJbnQxNihwb3MsIHRoaXMuYXJndW1lbnQxKTsKICAgICAgICBidWYuc2V0SW50MTYocG9zICsgMiwgdGhpcy5hcmd1bWVudDIpOwogICAgICB9IGVsc2UgewogICAgICAgIGJ1Zi5zZXRVaW50MTYocG9zLCB0aGlzLmFyZ3VtZW50MSk7CiAgICAgICAgYnVmLnNldFVpbnQxNihwb3MgKyAyLCB0aGlzLmFyZ3VtZW50Mik7CiAgICAgIH0KICAgICAgcG9zICs9IDQ7CiAgICB9IGVsc2UgewogICAgICBidWYuc2V0VWludDgocG9zLCB0aGlzLmFyZ3VtZW50MSk7CiAgICAgIGJ1Zi5zZXRVaW50OChwb3MgKyAxLCB0aGlzLmFyZ3VtZW50Mik7CiAgICAgIHBvcyArPSAyOwogICAgfQogICAgaWYgKHRoaXMuZmxhZ3MgJiBXRV9IQVZFX0lOU1RSVUNUSU9OUykgewogICAgICBidWYuc2V0VWludDE2KHBvcywgdGhpcy5pbnN0cnVjdGlvbnMubGVuZ3RoKTsKICAgICAgcG9zICs9IDI7CiAgICAgIGlmICh0aGlzLmluc3RydWN0aW9ucy5sZW5ndGgpIHsKICAgICAgICBuZXcgVWludDhBcnJheShidWYuYnVmZmVyLCAwLCBidWYuYnVmZmVyLmJ5dGVMZW5ndGgpLnNldCh0aGlzLmluc3RydWN0aW9ucywgcG9zKTsKICAgICAgICBwb3MgKz0gdGhpcy5pbnN0cnVjdGlvbnMubGVuZ3RoOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gcG9zIC0gc3BvczsKICB9CiAgc2NhbGUoeCwgZmFjdG9yKSB7fQp9Cgo7Ly8gLi9zcmMvY29yZS9vcGVudHlwZV9maWxlX2J1aWxkZXIuanMKCgoKCgoKCgoKCgpmdW5jdGlvbiB3cml0ZUludDE2KGRlc3QsIG9mZnNldCwgbnVtKSB7CiAgZGVzdFtvZmZzZXRdID0gbnVtID4+IDggJiAweGZmOwogIGRlc3Rbb2Zmc2V0ICsgMV0gPSBudW0gJiAweGZmOwp9CmZ1bmN0aW9uIHdyaXRlSW50MzIoZGVzdCwgb2Zmc2V0LCBudW0pIHsKICBkZXN0W29mZnNldF0gPSBudW0gPj4gMjQgJiAweGZmOwogIGRlc3Rbb2Zmc2V0ICsgMV0gPSBudW0gPj4gMTYgJiAweGZmOwogIGRlc3Rbb2Zmc2V0ICsgMl0gPSBudW0gPj4gOCAmIDB4ZmY7CiAgZGVzdFtvZmZzZXQgKyAzXSA9IG51bSAmIDB4ZmY7Cn0KZnVuY3Rpb24gd3JpdGVEYXRhKGRlc3QsIG9mZnNldCwgZGF0YSkgewogIGlmIChkYXRhIGluc3RhbmNlb2YgVWludDhBcnJheSkgewogICAgZGVzdC5zZXQoZGF0YSwgb2Zmc2V0KTsKICB9IGVsc2UgaWYgKHR5cGVvZiBkYXRhID09PSAic3RyaW5nIikgewogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZGF0YS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGRlc3Rbb2Zmc2V0KytdID0gZGF0YS5jaGFyQ29kZUF0KGkpICYgMHhmZjsKICAgIH0KICB9IGVsc2UgewogICAgZm9yIChjb25zdCBudW0gb2YgZGF0YSkgewogICAgICBkZXN0W29mZnNldCsrXSA9IG51bSAmIDB4ZmY7CiAgICB9CiAgfQp9CmNvbnN0IE9URl9IRUFERVJfU0laRSA9IDEyOwpjb25zdCBPVEZfVEFCTEVfRU5UUllfU0laRSA9IDE2OwpjbGFzcyBPcGVuVHlwZUZpbGVCdWlsZGVyIHsKICBjb25zdHJ1Y3RvcihzZm50KSB7CiAgICB0aGlzLnNmbnQgPSBzZm50OwogICAgdGhpcy50YWJsZXMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIH0KICBzdGF0aWMgZ2V0U2VhcmNoUGFyYW1zKGVudHJpZXNDb3VudCwgZW50cnlTaXplKSB7CiAgICBsZXQgbWF4UG93ZXIyID0gMSwKICAgICAgbG9nMiA9IDA7CiAgICB3aGlsZSAoKG1heFBvd2VyMiBeIGVudHJpZXNDb3VudCkgPiBtYXhQb3dlcjIpIHsKICAgICAgbWF4UG93ZXIyIDw8PSAxOwogICAgICBsb2cyKys7CiAgICB9CiAgICBjb25zdCBzZWFyY2hSYW5nZSA9IG1heFBvd2VyMiAqIGVudHJ5U2l6ZTsKICAgIHJldHVybiB7CiAgICAgIHJhbmdlOiBzZWFyY2hSYW5nZSwKICAgICAgZW50cnk6IGxvZzIsCiAgICAgIHJhbmdlU2hpZnQ6IGVudHJ5U2l6ZSAqIGVudHJpZXNDb3VudCAtIHNlYXJjaFJhbmdlCiAgICB9OwogIH0KICB0b0FycmF5KCkgewogICAgbGV0IHNmbnQgPSB0aGlzLnNmbnQ7CiAgICBjb25zdCB0YWJsZXMgPSB0aGlzLnRhYmxlczsKICAgIGNvbnN0IHRhYmxlc05hbWVzID0gT2JqZWN0LmtleXModGFibGVzKTsKICAgIHRhYmxlc05hbWVzLnNvcnQoKTsKICAgIGNvbnN0IG51bVRhYmxlcyA9IHRhYmxlc05hbWVzLmxlbmd0aDsKICAgIGxldCBpLCBqLCBqaiwgdGFibGUsIHRhYmxlTmFtZTsKICAgIGxldCBvZmZzZXQgPSBPVEZfSEVBREVSX1NJWkUgKyBudW1UYWJsZXMgKiBPVEZfVEFCTEVfRU5UUllfU0laRTsKICAgIGNvbnN0IHRhYmxlT2Zmc2V0cyA9IFtvZmZzZXRdOwogICAgZm9yIChpID0gMDsgaSA8IG51bVRhYmxlczsgaSsrKSB7CiAgICAgIHRhYmxlID0gdGFibGVzW3RhYmxlc05hbWVzW2ldXTsKICAgICAgY29uc3QgcGFkZGVkTGVuZ3RoID0gKHRhYmxlLmxlbmd0aCArIDMgJiB+MykgPj4+IDA7CiAgICAgIG9mZnNldCArPSBwYWRkZWRMZW5ndGg7CiAgICAgIHRhYmxlT2Zmc2V0cy5wdXNoKG9mZnNldCk7CiAgICB9CiAgICBjb25zdCBmaWxlID0gbmV3IFVpbnQ4QXJyYXkob2Zmc2V0KTsKICAgIGZvciAoaSA9IDA7IGkgPCBudW1UYWJsZXM7IGkrKykgewogICAgICB0YWJsZSA9IHRhYmxlc1t0YWJsZXNOYW1lc1tpXV07CiAgICAgIHdyaXRlRGF0YShmaWxlLCB0YWJsZU9mZnNldHNbaV0sIHRhYmxlKTsKICAgIH0KICAgIGlmIChzZm50ID09PSAidHJ1ZSIpIHsKICAgICAgc2ZudCA9IHN0cmluZzMyKDB4MDAwMTAwMDApOwogICAgfQogICAgZmlsZVswXSA9IHNmbnQuY2hhckNvZGVBdCgwKSAmIDB4ZmY7CiAgICBmaWxlWzFdID0gc2ZudC5jaGFyQ29kZUF0KDEpICYgMHhmZjsKICAgIGZpbGVbMl0gPSBzZm50LmNoYXJDb2RlQXQoMikgJiAweGZmOwogICAgZmlsZVszXSA9IHNmbnQuY2hhckNvZGVBdCgzKSAmIDB4ZmY7CiAgICB3cml0ZUludDE2KGZpbGUsIDQsIG51bVRhYmxlcyk7CiAgICBjb25zdCBzZWFyY2hQYXJhbXMgPSBPcGVuVHlwZUZpbGVCdWlsZGVyLmdldFNlYXJjaFBhcmFtcyhudW1UYWJsZXMsIDE2KTsKICAgIHdyaXRlSW50MTYoZmlsZSwgNiwgc2VhcmNoUGFyYW1zLnJhbmdlKTsKICAgIHdyaXRlSW50MTYoZmlsZSwgOCwgc2VhcmNoUGFyYW1zLmVudHJ5KTsKICAgIHdyaXRlSW50MTYoZmlsZSwgMTAsIHNlYXJjaFBhcmFtcy5yYW5nZVNoaWZ0KTsKICAgIG9mZnNldCA9IE9URl9IRUFERVJfU0laRTsKICAgIGZvciAoaSA9IDA7IGkgPCBudW1UYWJsZXM7IGkrKykgewogICAgICB0YWJsZU5hbWUgPSB0YWJsZXNOYW1lc1tpXTsKICAgICAgZmlsZVtvZmZzZXRdID0gdGFibGVOYW1lLmNoYXJDb2RlQXQoMCkgJiAweGZmOwogICAgICBmaWxlW29mZnNldCArIDFdID0gdGFibGVOYW1lLmNoYXJDb2RlQXQoMSkgJiAweGZmOwogICAgICBmaWxlW29mZnNldCArIDJdID0gdGFibGVOYW1lLmNoYXJDb2RlQXQoMikgJiAweGZmOwogICAgICBmaWxlW29mZnNldCArIDNdID0gdGFibGVOYW1lLmNoYXJDb2RlQXQoMykgJiAweGZmOwogICAgICBsZXQgY2hlY2tzdW0gPSAwOwogICAgICBmb3IgKGogPSB0YWJsZU9mZnNldHNbaV0sIGpqID0gdGFibGVPZmZzZXRzW2kgKyAxXTsgaiA8IGpqOyBqICs9IDQpIHsKICAgICAgICBjb25zdCBxdWFkID0gcmVhZFVpbnQzMihmaWxlLCBqKTsKICAgICAgICBjaGVja3N1bSA9IGNoZWNrc3VtICsgcXVhZCA+Pj4gMDsKICAgICAgfQogICAgICB3cml0ZUludDMyKGZpbGUsIG9mZnNldCArIDQsIGNoZWNrc3VtKTsKICAgICAgd3JpdGVJbnQzMihmaWxlLCBvZmZzZXQgKyA4LCB0YWJsZU9mZnNldHNbaV0pOwogICAgICB3cml0ZUludDMyKGZpbGUsIG9mZnNldCArIDEyLCB0YWJsZXNbdGFibGVOYW1lXS5sZW5ndGgpOwogICAgICBvZmZzZXQgKz0gT1RGX1RBQkxFX0VOVFJZX1NJWkU7CiAgICB9CiAgICByZXR1cm4gZmlsZTsKICB9CiAgYWRkVGFibGUodGFnLCBkYXRhKSB7CiAgICBpZiAodGFnIGluIHRoaXMudGFibGVzKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiVGFibGUgIiArIHRhZyArICIgYWxyZWFkeSBleGlzdHMiKTsKICAgIH0KICAgIHRoaXMudGFibGVzW3RhZ10gPSBkYXRhOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvdHlwZTFfcGFyc2VyLmpzCgoKCgoKCgoKCgoKCgpjb25zdCBISU5USU5HX0VOQUJMRUQgPSBmYWxzZTsKY29uc3QgQ09NTUFORF9NQVAgPSB7CiAgaHN0ZW06IFsxXSwKICB2c3RlbTogWzNdLAogIHZtb3ZldG86IFs0XSwKICBybGluZXRvOiBbNV0sCiAgaGxpbmV0bzogWzZdLAogIHZsaW5ldG86IFs3XSwKICBycmN1cnZldG86IFs4XSwKICBjYWxsc3VicjogWzEwXSwKICBmbGV4OiBbMTIsIDM1XSwKICBkcm9wOiBbMTIsIDE4XSwKICBlbmRjaGFyOiBbMTRdLAogIHJtb3ZldG86IFsyMV0sCiAgaG1vdmV0bzogWzIyXSwKICB2aGN1cnZldG86IFszMF0sCiAgaHZjdXJ2ZXRvOiBbMzFdCn07CmNsYXNzIFR5cGUxQ2hhclN0cmluZyB7CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLndpZHRoID0gMDsKICAgIHRoaXMubHNiID0gMDsKICAgIHRoaXMuZmxleGluZyA9IGZhbHNlOwogICAgdGhpcy5vdXRwdXQgPSBbXTsKICAgIHRoaXMuc3RhY2sgPSBbXTsKICB9CiAgY29udmVydChlbmNvZGVkLCBzdWJycywgc2VhY0FuYWx5c2lzRW5hYmxlZCkgewogICAgY29uc3QgY291bnQgPSBlbmNvZGVkLmxlbmd0aDsKICAgIGxldCBlcnJvciA9IGZhbHNlOwogICAgbGV0IHd4LCBzYngsIHN1YnJOdW1iZXI7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgICAgbGV0IHZhbHVlID0gZW5jb2RlZFtpXTsKICAgICAgaWYgKHZhbHVlIDwgMzIpIHsKICAgICAgICBpZiAodmFsdWUgPT09IDEyKSB7CiAgICAgICAgICB2YWx1ZSA9ICh2YWx1ZSA8PCA4KSArIGVuY29kZWRbKytpXTsKICAgICAgICB9CiAgICAgICAgc3dpdGNoICh2YWx1ZSkgewogICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICBpZiAoIUhJTlRJTkdfRU5BQkxFRCkgewogICAgICAgICAgICAgIHRoaXMuc3RhY2sgPSBbXTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBlcnJvciA9IHRoaXMuZXhlY3V0ZUNvbW1hbmQoMiwgQ09NTUFORF9NQVAuaHN0ZW0pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgaWYgKCFISU5USU5HX0VOQUJMRUQpIHsKICAgICAgICAgICAgICB0aGlzLnN0YWNrID0gW107CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDIsIENPTU1BTkRfTUFQLnZzdGVtKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDQ6CiAgICAgICAgICAgIGlmICh0aGlzLmZsZXhpbmcpIHsKICAgICAgICAgICAgICBpZiAodGhpcy5zdGFjay5sZW5ndGggPCAxKSB7CiAgICAgICAgICAgICAgICBlcnJvciA9IHRydWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgZHkgPSB0aGlzLnN0YWNrLnBvcCgpOwogICAgICAgICAgICAgIHRoaXMuc3RhY2sucHVzaCgwLCBkeSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDEsIENPTU1BTkRfTUFQLnZtb3ZldG8pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgNToKICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDIsIENPTU1BTkRfTUFQLnJsaW5ldG8pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgNjoKICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDEsIENPTU1BTkRfTUFQLmhsaW5ldG8pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgNzoKICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDEsIENPTU1BTkRfTUFQLnZsaW5ldG8pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgODoKICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDYsIENPTU1BTkRfTUFQLnJyY3VydmV0byk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSA5OgogICAgICAgICAgICB0aGlzLnN0YWNrID0gW107CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAxMDoKICAgICAgICAgICAgaWYgKHRoaXMuc3RhY2subGVuZ3RoIDwgMSkgewogICAgICAgICAgICAgIGVycm9yID0gdHJ1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBzdWJyTnVtYmVyID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgaWYgKCFzdWJyc1tzdWJyTnVtYmVyXSkgewogICAgICAgICAgICAgIGVycm9yID0gdHJ1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBlcnJvciA9IHRoaXMuY29udmVydChzdWJyc1tzdWJyTnVtYmVyXSwgc3VicnMsIHNlYWNBbmFseXNpc0VuYWJsZWQpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMTE6CiAgICAgICAgICAgIHJldHVybiBlcnJvcjsKICAgICAgICAgIGNhc2UgMTM6CiAgICAgICAgICAgIGlmICh0aGlzLnN0YWNrLmxlbmd0aCA8IDIpIHsKICAgICAgICAgICAgICBlcnJvciA9IHRydWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgd3ggPSB0aGlzLnN0YWNrLnBvcCgpOwogICAgICAgICAgICBzYnggPSB0aGlzLnN0YWNrLnBvcCgpOwogICAgICAgICAgICB0aGlzLmxzYiA9IHNieDsKICAgICAgICAgICAgdGhpcy53aWR0aCA9IHd4OwogICAgICAgICAgICB0aGlzLnN0YWNrLnB1c2god3gsIHNieCk7CiAgICAgICAgICAgIGVycm9yID0gdGhpcy5leGVjdXRlQ29tbWFuZCgyLCBDT01NQU5EX01BUC5obW92ZXRvKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDE0OgogICAgICAgICAgICB0aGlzLm91dHB1dC5wdXNoKENPTU1BTkRfTUFQLmVuZGNoYXJbMF0pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMjE6CiAgICAgICAgICAgIGlmICh0aGlzLmZsZXhpbmcpIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBlcnJvciA9IHRoaXMuZXhlY3V0ZUNvbW1hbmQoMiwgQ09NTUFORF9NQVAucm1vdmV0byk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAyMjoKICAgICAgICAgICAgaWYgKHRoaXMuZmxleGluZykgewogICAgICAgICAgICAgIHRoaXMuc3RhY2sucHVzaCgwKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBlcnJvciA9IHRoaXMuZXhlY3V0ZUNvbW1hbmQoMSwgQ09NTUFORF9NQVAuaG1vdmV0byk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAzMDoKICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDQsIENPTU1BTkRfTUFQLnZoY3VydmV0byk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAzMToKICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDQsIENPTU1BTkRfTUFQLmh2Y3VydmV0byk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAoMTIgPDwgOCkgKyAwOgogICAgICAgICAgICB0aGlzLnN0YWNrID0gW107CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAoMTIgPDwgOCkgKyAxOgogICAgICAgICAgICBpZiAoIUhJTlRJTkdfRU5BQkxFRCkgewogICAgICAgICAgICAgIHRoaXMuc3RhY2sgPSBbXTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBlcnJvciA9IHRoaXMuZXhlY3V0ZUNvbW1hbmQoMiwgQ09NTUFORF9NQVAudnN0ZW0pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgKDEyIDw8IDgpICsgMjoKICAgICAgICAgICAgaWYgKCFISU5USU5HX0VOQUJMRUQpIHsKICAgICAgICAgICAgICB0aGlzLnN0YWNrID0gW107CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDIsIENPTU1BTkRfTUFQLmhzdGVtKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICgxMiA8PCA4KSArIDY6CiAgICAgICAgICAgIGlmIChzZWFjQW5hbHlzaXNFbmFibGVkKSB7CiAgICAgICAgICAgICAgY29uc3QgYXNiID0gdGhpcy5zdGFjay5hdCgtNSk7CiAgICAgICAgICAgICAgdGhpcy5zZWFjID0gdGhpcy5zdGFjay5zcGxpY2UoLTQsIDQpOwogICAgICAgICAgICAgIHRoaXMuc2VhY1swXSArPSB0aGlzLmxzYiAtIGFzYjsKICAgICAgICAgICAgICBlcnJvciA9IHRoaXMuZXhlY3V0ZUNvbW1hbmQoMCwgQ09NTUFORF9NQVAuZW5kY2hhcik7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgZXJyb3IgPSB0aGlzLmV4ZWN1dGVDb21tYW5kKDQsIENPTU1BTkRfTUFQLmVuZGNoYXIpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAoMTIgPDwgOCkgKyA3OgogICAgICAgICAgICBpZiAodGhpcy5zdGFjay5sZW5ndGggPCA0KSB7CiAgICAgICAgICAgICAgZXJyb3IgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMuc3RhY2sucG9wKCk7CiAgICAgICAgICAgIHd4ID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgY29uc3Qgc2J5ID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgc2J4ID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgdGhpcy5sc2IgPSBzYng7CiAgICAgICAgICAgIHRoaXMud2lkdGggPSB3eDsKICAgICAgICAgICAgdGhpcy5zdGFjay5wdXNoKHd4LCBzYngsIHNieSk7CiAgICAgICAgICAgIGVycm9yID0gdGhpcy5leGVjdXRlQ29tbWFuZCgzLCBDT01NQU5EX01BUC5ybW92ZXRvKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICgxMiA8PCA4KSArIDEyOgogICAgICAgICAgICBpZiAodGhpcy5zdGFjay5sZW5ndGggPCAyKSB7CiAgICAgICAgICAgICAgZXJyb3IgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IG51bTIgPSB0aGlzLnN0YWNrLnBvcCgpOwogICAgICAgICAgICBjb25zdCBudW0xID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgdGhpcy5zdGFjay5wdXNoKG51bTEgLyBudW0yKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlICgxMiA8PCA4KSArIDE2OgogICAgICAgICAgICBpZiAodGhpcy5zdGFjay5sZW5ndGggPCAyKSB7CiAgICAgICAgICAgICAgZXJyb3IgPSB0cnVlOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN1YnJOdW1iZXIgPSB0aGlzLnN0YWNrLnBvcCgpOwogICAgICAgICAgICBjb25zdCBudW1BcmdzID0gdGhpcy5zdGFjay5wb3AoKTsKICAgICAgICAgICAgaWYgKHN1YnJOdW1iZXIgPT09IDAgJiYgbnVtQXJncyA9PT0gMykgewogICAgICAgICAgICAgIGNvbnN0IGZsZXhBcmdzID0gdGhpcy5zdGFjay5zcGxpY2UoLTE3LCAxNyk7CiAgICAgICAgICAgICAgdGhpcy5zdGFjay5wdXNoKGZsZXhBcmdzWzJdICsgZmxleEFyZ3NbMF0sIGZsZXhBcmdzWzNdICsgZmxleEFyZ3NbMV0sIGZsZXhBcmdzWzRdLCBmbGV4QXJnc1s1XSwgZmxleEFyZ3NbNl0sIGZsZXhBcmdzWzddLCBmbGV4QXJnc1s4XSwgZmxleEFyZ3NbOV0sIGZsZXhBcmdzWzEwXSwgZmxleEFyZ3NbMTFdLCBmbGV4QXJnc1sxMl0sIGZsZXhBcmdzWzEzXSwgZmxleEFyZ3NbMTRdKTsKICAgICAgICAgICAgICBlcnJvciA9IHRoaXMuZXhlY3V0ZUNvbW1hbmQoMTMsIENPTU1BTkRfTUFQLmZsZXgsIHRydWUpOwogICAgICAgICAgICAgIHRoaXMuZmxleGluZyA9IGZhbHNlOwogICAgICAgICAgICAgIHRoaXMuc3RhY2sucHVzaChmbGV4QXJnc1sxNV0sIGZsZXhBcmdzWzE2XSk7CiAgICAgICAgICAgIH0gZWxzZSBpZiAoc3Vick51bWJlciA9PT0gMSAmJiBudW1BcmdzID09PSAwKSB7CiAgICAgICAgICAgICAgdGhpcy5mbGV4aW5nID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgKDEyIDw8IDgpICsgMTc6CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAoMTIgPDwgOCkgKyAzMzoKICAgICAgICAgICAgdGhpcy5zdGFjayA9IFtdOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIHdhcm4oJ1Vua25vd24gdHlwZSAxIGNoYXJzdHJpbmcgY29tbWFuZCBvZiAiJyArIHZhbHVlICsgJyInKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmIChlcnJvcikgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGNvbnRpbnVlOwogICAgICB9IGVsc2UgaWYgKHZhbHVlIDw9IDI0NikgewogICAgICAgIHZhbHVlIC09IDEzOTsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSA8PSAyNTApIHsKICAgICAgICB2YWx1ZSA9ICh2YWx1ZSAtIDI0NykgKiAyNTYgKyBlbmNvZGVkWysraV0gKyAxMDg7CiAgICAgIH0gZWxzZSBpZiAodmFsdWUgPD0gMjU0KSB7CiAgICAgICAgdmFsdWUgPSAtKCh2YWx1ZSAtIDI1MSkgKiAyNTYpIC0gZW5jb2RlZFsrK2ldIC0gMTA4OwogICAgICB9IGVsc2UgewogICAgICAgIHZhbHVlID0gKGVuY29kZWRbKytpXSAmIDB4ZmYpIDw8IDI0IHwgKGVuY29kZWRbKytpXSAmIDB4ZmYpIDw8IDE2IHwgKGVuY29kZWRbKytpXSAmIDB4ZmYpIDw8IDggfCAoZW5jb2RlZFsrK2ldICYgMHhmZikgPDwgMDsKICAgICAgfQogICAgICB0aGlzLnN0YWNrLnB1c2godmFsdWUpOwogICAgfQogICAgcmV0dXJuIGVycm9yOwogIH0KICBleGVjdXRlQ29tbWFuZChob3dNYW55QXJncywgY29tbWFuZCwga2VlcFN0YWNrKSB7CiAgICBjb25zdCBzdGFja0xlbmd0aCA9IHRoaXMuc3RhY2subGVuZ3RoOwogICAgaWYgKGhvd01hbnlBcmdzID4gc3RhY2tMZW5ndGgpIHsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBjb25zdCBzdGFydCA9IHN0YWNrTGVuZ3RoIC0gaG93TWFueUFyZ3M7CiAgICBmb3IgKGxldCBpID0gc3RhcnQ7IGkgPCBzdGFja0xlbmd0aDsgaSsrKSB7CiAgICAgIGxldCB2YWx1ZSA9IHRoaXMuc3RhY2tbaV07CiAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHZhbHVlKSkgewogICAgICAgIHRoaXMub3V0cHV0LnB1c2goMjgsIHZhbHVlID4+IDggJiAweGZmLCB2YWx1ZSAmIDB4ZmYpOwogICAgICB9IGVsc2UgewogICAgICAgIHZhbHVlID0gNjU1MzYgKiB2YWx1ZSB8IDA7CiAgICAgICAgdGhpcy5vdXRwdXQucHVzaCgyNTUsIHZhbHVlID4+IDI0ICYgMHhmZiwgdmFsdWUgPj4gMTYgJiAweGZmLCB2YWx1ZSA+PiA4ICYgMHhmZiwgdmFsdWUgJiAweGZmKTsKICAgICAgfQogICAgfQogICAgdGhpcy5vdXRwdXQucHVzaCguLi5jb21tYW5kKTsKICAgIGlmIChrZWVwU3RhY2spIHsKICAgICAgdGhpcy5zdGFjay5zcGxpY2Uoc3RhcnQsIGhvd01hbnlBcmdzKTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuc3RhY2subGVuZ3RoID0gMDsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKICB9Cn0KY29uc3QgRUVYRUNfRU5DUllQVF9LRVkgPSA1NTY2NTsKY29uc3QgQ0hBUl9TVFJTX0VOQ1JZUFRfS0VZID0gNDMzMDsKZnVuY3Rpb24gaXNIZXhEaWdpdChjb2RlKSB7CiAgcmV0dXJuIGNvZGUgPj0gNDggJiYgY29kZSA8PSA1NyB8fCBjb2RlID49IDY1ICYmIGNvZGUgPD0gNzAgfHwgY29kZSA+PSA5NyAmJiBjb2RlIDw9IDEwMjsKfQpmdW5jdGlvbiBkZWNyeXB0KGRhdGEsIGtleSwgZGlzY2FyZE51bWJlcikgewogIGlmIChkaXNjYXJkTnVtYmVyID49IGRhdGEubGVuZ3RoKSB7CiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoMCk7CiAgfQogIGNvbnN0IGMxID0gNTI4NDUsCiAgICBjMiA9IDIyNzE5OwogIGxldCByID0ga2V5IHwgMCwKICAgIGksCiAgICBqOwogIGZvciAoaSA9IDA7IGkgPCBkaXNjYXJkTnVtYmVyOyBpKyspIHsKICAgIHIgPSAoZGF0YVtpXSArIHIpICogYzEgKyBjMiAmICgxIDw8IDE2KSAtIDE7CiAgfQogIGNvbnN0IGNvdW50ID0gZGF0YS5sZW5ndGggLSBkaXNjYXJkTnVtYmVyOwogIGNvbnN0IGRlY3J5cHRlZCA9IG5ldyBVaW50OEFycmF5KGNvdW50KTsKICBmb3IgKGkgPSBkaXNjYXJkTnVtYmVyLCBqID0gMDsgaiA8IGNvdW50OyBpKyssIGorKykgewogICAgY29uc3QgdmFsdWUgPSBkYXRhW2ldOwogICAgZGVjcnlwdGVkW2pdID0gdmFsdWUgXiByID4+IDg7CiAgICByID0gKHZhbHVlICsgcikgKiBjMSArIGMyICYgKDEgPDwgMTYpIC0gMTsKICB9CiAgcmV0dXJuIGRlY3J5cHRlZDsKfQpmdW5jdGlvbiBkZWNyeXB0QXNjaWkoZGF0YSwga2V5LCBkaXNjYXJkTnVtYmVyKSB7CiAgY29uc3QgYzEgPSA1Mjg0NSwKICAgIGMyID0gMjI3MTk7CiAgbGV0IHIgPSBrZXkgfCAwOwogIGNvbnN0IGNvdW50ID0gZGF0YS5sZW5ndGgsCiAgICBtYXliZUxlbmd0aCA9IGNvdW50ID4+PiAxOwogIGNvbnN0IGRlY3J5cHRlZCA9IG5ldyBVaW50OEFycmF5KG1heWJlTGVuZ3RoKTsKICBsZXQgaSwgajsKICBmb3IgKGkgPSAwLCBqID0gMDsgaSA8IGNvdW50OyBpKyspIHsKICAgIGNvbnN0IGRpZ2l0MSA9IGRhdGFbaV07CiAgICBpZiAoIWlzSGV4RGlnaXQoZGlnaXQxKSkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIGkrKzsKICAgIGxldCBkaWdpdDI7CiAgICB3aGlsZSAoaSA8IGNvdW50ICYmICFpc0hleERpZ2l0KGRpZ2l0MiA9IGRhdGFbaV0pKSB7CiAgICAgIGkrKzsKICAgIH0KICAgIGlmIChpIDwgY291bnQpIHsKICAgICAgY29uc3QgdmFsdWUgPSBwYXJzZUludChTdHJpbmcuZnJvbUNoYXJDb2RlKGRpZ2l0MSwgZGlnaXQyKSwgMTYpOwogICAgICBkZWNyeXB0ZWRbaisrXSA9IHZhbHVlIF4gciA+PiA4OwogICAgICByID0gKHZhbHVlICsgcikgKiBjMSArIGMyICYgKDEgPDwgMTYpIC0gMTsKICAgIH0KICB9CiAgcmV0dXJuIGRlY3J5cHRlZC5zbGljZShkaXNjYXJkTnVtYmVyLCBqKTsKfQpmdW5jdGlvbiBpc1NwZWNpYWwoYykgewogIHJldHVybiBjID09PSAweDJmIHx8IGMgPT09IDB4NWIgfHwgYyA9PT0gMHg1ZCB8fCBjID09PSAweDdiIHx8IGMgPT09IDB4N2QgfHwgYyA9PT0gMHgyOCB8fCBjID09PSAweDI5Owp9CmNsYXNzIFR5cGUxUGFyc2VyIHsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIGVuY3J5cHRlZCwgc2VhY0FuYWx5c2lzRW5hYmxlZCkgewogICAgaWYgKGVuY3J5cHRlZCkgewogICAgICBjb25zdCBkYXRhID0gc3RyZWFtLmdldEJ5dGVzKCk7CiAgICAgIGNvbnN0IGlzQmluYXJ5ID0gISgoaXNIZXhEaWdpdChkYXRhWzBdKSB8fCBpc1doaXRlU3BhY2UoZGF0YVswXSkpICYmIGlzSGV4RGlnaXQoZGF0YVsxXSkgJiYgaXNIZXhEaWdpdChkYXRhWzJdKSAmJiBpc0hleERpZ2l0KGRhdGFbM10pICYmIGlzSGV4RGlnaXQoZGF0YVs0XSkgJiYgaXNIZXhEaWdpdChkYXRhWzVdKSAmJiBpc0hleERpZ2l0KGRhdGFbNl0pICYmIGlzSGV4RGlnaXQoZGF0YVs3XSkpOwogICAgICBzdHJlYW0gPSBuZXcgU3RyZWFtKGlzQmluYXJ5ID8gZGVjcnlwdChkYXRhLCBFRVhFQ19FTkNSWVBUX0tFWSwgNCkgOiBkZWNyeXB0QXNjaWkoZGF0YSwgRUVYRUNfRU5DUllQVF9LRVksIDQpKTsKICAgIH0KICAgIHRoaXMuc2VhY0FuYWx5c2lzRW5hYmxlZCA9ICEhc2VhY0FuYWx5c2lzRW5hYmxlZDsKICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtOwogICAgdGhpcy5uZXh0Q2hhcigpOwogIH0KICByZWFkTnVtYmVyQXJyYXkoKSB7CiAgICB0aGlzLmdldFRva2VuKCk7CiAgICBjb25zdCBhcnJheSA9IFtdOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgY29uc3QgdG9rZW4gPSB0aGlzLmdldFRva2VuKCk7CiAgICAgIGlmICh0b2tlbiA9PT0gbnVsbCB8fCB0b2tlbiA9PT0gIl0iIHx8IHRva2VuID09PSAifSIpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBhcnJheS5wdXNoKHBhcnNlRmxvYXQodG9rZW4gfHwgMCkpOwogICAgfQogICAgcmV0dXJuIGFycmF5OwogIH0KICByZWFkTnVtYmVyKCkgewogICAgY29uc3QgdG9rZW4gPSB0aGlzLmdldFRva2VuKCk7CiAgICByZXR1cm4gcGFyc2VGbG9hdCh0b2tlbiB8fCAwKTsKICB9CiAgcmVhZEludCgpIHsKICAgIGNvbnN0IHRva2VuID0gdGhpcy5nZXRUb2tlbigpOwogICAgcmV0dXJuIHBhcnNlSW50KHRva2VuIHx8IDAsIDEwKSB8IDA7CiAgfQogIHJlYWRCb29sZWFuKCkgewogICAgY29uc3QgdG9rZW4gPSB0aGlzLmdldFRva2VuKCk7CiAgICByZXR1cm4gdG9rZW4gPT09ICJ0cnVlIiA/IDEgOiAwOwogIH0KICBuZXh0Q2hhcigpIHsKICAgIHJldHVybiB0aGlzLmN1cnJlbnRDaGFyID0gdGhpcy5zdHJlYW0uZ2V0Qnl0ZSgpOwogIH0KICBwcmV2Q2hhcigpIHsKICAgIHRoaXMuc3RyZWFtLnNraXAoLTIpOwogICAgcmV0dXJuIHRoaXMuY3VycmVudENoYXIgPSB0aGlzLnN0cmVhbS5nZXRCeXRlKCk7CiAgfQogIGdldFRva2VuKCkgewogICAgbGV0IGNvbW1lbnQgPSBmYWxzZTsKICAgIGxldCBjaCA9IHRoaXMuY3VycmVudENoYXI7CiAgICB3aGlsZSAodHJ1ZSkgewogICAgICBpZiAoY2ggPT09IC0xKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgaWYgKGNvbW1lbnQpIHsKICAgICAgICBpZiAoY2ggPT09IDB4MGEgfHwgY2ggPT09IDB4MGQpIHsKICAgICAgICAgIGNvbW1lbnQgPSBmYWxzZTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4MjUpIHsKICAgICAgICBjb21tZW50ID0gdHJ1ZTsKICAgICAgfSBlbHNlIGlmICghaXNXaGl0ZVNwYWNlKGNoKSkgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgfQogICAgaWYgKGlzU3BlY2lhbChjaCkpIHsKICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZShjaCk7CiAgICB9CiAgICBsZXQgdG9rZW4gPSAiIjsKICAgIGRvIHsKICAgICAgdG9rZW4gKz0gU3RyaW5nLmZyb21DaGFyQ29kZShjaCk7CiAgICAgIGNoID0gdGhpcy5uZXh0Q2hhcigpOwogICAgfSB3aGlsZSAoY2ggPj0gMCAmJiAhaXNXaGl0ZVNwYWNlKGNoKSAmJiAhaXNTcGVjaWFsKGNoKSk7CiAgICByZXR1cm4gdG9rZW47CiAgfQogIHJlYWRDaGFyU3RyaW5ncyhieXRlcywgbGVuSVYpIHsKICAgIGlmIChsZW5JViA9PT0gLTEpIHsKICAgICAgcmV0dXJuIGJ5dGVzOwogICAgfQogICAgcmV0dXJuIGRlY3J5cHQoYnl0ZXMsIENIQVJfU1RSU19FTkNSWVBUX0tFWSwgbGVuSVYpOwogIH0KICBleHRyYWN0Rm9udFByb2dyYW0ocHJvcGVydGllcykgewogICAgY29uc3Qgc3RyZWFtID0gdGhpcy5zdHJlYW07CiAgICBjb25zdCBzdWJycyA9IFtdLAogICAgICBjaGFyc3RyaW5ncyA9IFtdOwogICAgY29uc3QgcHJpdmF0ZURhdGEgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgcHJpdmF0ZURhdGEubGVuSVYgPSA0OwogICAgY29uc3QgcHJvZ3JhbSA9IHsKICAgICAgc3VicnM6IFtdLAogICAgICBjaGFyc3RyaW5nczogW10sCiAgICAgIHByb3BlcnRpZXM6IHsKICAgICAgICBwcml2YXRlRGF0YQogICAgICB9CiAgICB9OwogICAgbGV0IHRva2VuLCBsZW5ndGgsIGRhdGEsIGxlbklWOwogICAgd2hpbGUgKCh0b2tlbiA9IHRoaXMuZ2V0VG9rZW4oKSkgIT09IG51bGwpIHsKICAgICAgaWYgKHRva2VuICE9PSAiLyIpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICB0b2tlbiA9IHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgc3dpdGNoICh0b2tlbikgewogICAgICAgIGNhc2UgIkNoYXJTdHJpbmdzIjoKICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICAgIHRva2VuID0gdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgICBpZiAodG9rZW4gPT09IG51bGwgfHwgdG9rZW4gPT09ICJlbmQiKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKHRva2VuICE9PSAiLyIpIHsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBnbHlwaCA9IHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgbGVuZ3RoID0gdGhpcy5yZWFkSW50KCk7CiAgICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgZGF0YSA9IGxlbmd0aCA+IDAgPyBzdHJlYW0uZ2V0Qnl0ZXMobGVuZ3RoKSA6IG5ldyBVaW50OEFycmF5KDApOwogICAgICAgICAgICBsZW5JViA9IHByb2dyYW0ucHJvcGVydGllcy5wcml2YXRlRGF0YS5sZW5JVjsKICAgICAgICAgICAgY29uc3QgZW5jb2RlZCA9IHRoaXMucmVhZENoYXJTdHJpbmdzKGRhdGEsIGxlbklWKTsKICAgICAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgICB0b2tlbiA9IHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgaWYgKHRva2VuID09PSAibm9hY2Nlc3MiKSB7CiAgICAgICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgICB9IGVsc2UgaWYgKHRva2VuID09PSAiLyIpIHsKICAgICAgICAgICAgICB0aGlzLnByZXZDaGFyKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY2hhcnN0cmluZ3MucHVzaCh7CiAgICAgICAgICAgICAgZ2x5cGgsCiAgICAgICAgICAgICAgZW5jb2RlZAogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIlN1YnJzIjoKICAgICAgICAgIHRoaXMucmVhZEludCgpOwogICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgd2hpbGUgKHRoaXMuZ2V0VG9rZW4oKSA9PT0gImR1cCIpIHsKICAgICAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLnJlYWRJbnQoKTsKICAgICAgICAgICAgbGVuZ3RoID0gdGhpcy5yZWFkSW50KCk7CiAgICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgZGF0YSA9IGxlbmd0aCA+IDAgPyBzdHJlYW0uZ2V0Qnl0ZXMobGVuZ3RoKSA6IG5ldyBVaW50OEFycmF5KDApOwogICAgICAgICAgICBsZW5JViA9IHByb2dyYW0ucHJvcGVydGllcy5wcml2YXRlRGF0YS5sZW5JVjsKICAgICAgICAgICAgY29uc3QgZW5jb2RlZCA9IHRoaXMucmVhZENoYXJTdHJpbmdzKGRhdGEsIGxlbklWKTsKICAgICAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgICAgICB0b2tlbiA9IHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgaWYgKHRva2VuID09PSAibm9hY2Nlc3MiKSB7CiAgICAgICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHN1YnJzW2luZGV4XSA9IGVuY29kZWQ7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJCbHVlVmFsdWVzIjoKICAgICAgICBjYXNlICJPdGhlckJsdWVzIjoKICAgICAgICBjYXNlICJGYW1pbHlCbHVlcyI6CiAgICAgICAgY2FzZSAiRmFtaWx5T3RoZXJCbHVlcyI6CiAgICAgICAgICBjb25zdCBibHVlQXJyYXkgPSB0aGlzLnJlYWROdW1iZXJBcnJheSgpOwogICAgICAgICAgaWYgKGJsdWVBcnJheS5sZW5ndGggPiAwICYmIGJsdWVBcnJheS5sZW5ndGggJSAyID09PSAwICYmIEhJTlRJTkdfRU5BQkxFRCkgewogICAgICAgICAgICBwcm9ncmFtLnByb3BlcnRpZXMucHJpdmF0ZURhdGFbdG9rZW5dID0gYmx1ZUFycmF5OwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiU3RlbVNuYXBIIjoKICAgICAgICBjYXNlICJTdGVtU25hcFYiOgogICAgICAgICAgcHJvZ3JhbS5wcm9wZXJ0aWVzLnByaXZhdGVEYXRhW3Rva2VuXSA9IHRoaXMucmVhZE51bWJlckFycmF5KCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJTdGRIVyI6CiAgICAgICAgY2FzZSAiU3RkVlciOgogICAgICAgICAgcHJvZ3JhbS5wcm9wZXJ0aWVzLnByaXZhdGVEYXRhW3Rva2VuXSA9IHRoaXMucmVhZE51bWJlckFycmF5KClbMF07CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJCbHVlU2hpZnQiOgogICAgICAgIGNhc2UgImxlbklWIjoKICAgICAgICBjYXNlICJCbHVlRnV6eiI6CiAgICAgICAgY2FzZSAiQmx1ZVNjYWxlIjoKICAgICAgICBjYXNlICJMYW5ndWFnZUdyb3VwIjoKICAgICAgICAgIHByb2dyYW0ucHJvcGVydGllcy5wcml2YXRlRGF0YVt0b2tlbl0gPSB0aGlzLnJlYWROdW1iZXIoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkV4cGFuc2lvbkZhY3RvciI6CiAgICAgICAgICBwcm9ncmFtLnByb3BlcnRpZXMucHJpdmF0ZURhdGFbdG9rZW5dID0gdGhpcy5yZWFkTnVtYmVyKCkgfHwgMC4wNjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkZvcmNlQm9sZCI6CiAgICAgICAgICBwcm9ncmFtLnByb3BlcnRpZXMucHJpdmF0ZURhdGFbdG9rZW5dID0gdGhpcy5yZWFkQm9vbGVhbigpOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgewogICAgICBlbmNvZGVkLAogICAgICBnbHlwaAogICAgfSBvZiBjaGFyc3RyaW5ncykgewogICAgICBjb25zdCBjaGFyU3RyaW5nID0gbmV3IFR5cGUxQ2hhclN0cmluZygpOwogICAgICBjb25zdCBlcnJvciA9IGNoYXJTdHJpbmcuY29udmVydChlbmNvZGVkLCBzdWJycywgdGhpcy5zZWFjQW5hbHlzaXNFbmFibGVkKTsKICAgICAgbGV0IG91dHB1dCA9IGNoYXJTdHJpbmcub3V0cHV0OwogICAgICBpZiAoZXJyb3IpIHsKICAgICAgICBvdXRwdXQgPSBbMTRdOwogICAgICB9CiAgICAgIGNvbnN0IGNoYXJTdHJpbmdPYmplY3QgPSB7CiAgICAgICAgZ2x5cGhOYW1lOiBnbHlwaCwKICAgICAgICBjaGFyc3RyaW5nOiBvdXRwdXQsCiAgICAgICAgd2lkdGg6IGNoYXJTdHJpbmcud2lkdGgsCiAgICAgICAgbHNiOiBjaGFyU3RyaW5nLmxzYiwKICAgICAgICBzZWFjOiBjaGFyU3RyaW5nLnNlYWMKICAgICAgfTsKICAgICAgaWYgKGdseXBoID09PSAiLm5vdGRlZiIpIHsKICAgICAgICBwcm9ncmFtLmNoYXJzdHJpbmdzLnVuc2hpZnQoY2hhclN0cmluZ09iamVjdCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcHJvZ3JhbS5jaGFyc3RyaW5ncy5wdXNoKGNoYXJTdHJpbmdPYmplY3QpOwogICAgICB9CiAgICAgIGlmIChwcm9wZXJ0aWVzLmJ1aWx0SW5FbmNvZGluZykgewogICAgICAgIGNvbnN0IGluZGV4ID0gcHJvcGVydGllcy5idWlsdEluRW5jb2RpbmcuaW5kZXhPZihnbHlwaCk7CiAgICAgICAgaWYgKGluZGV4ID4gLTEgJiYgcHJvcGVydGllcy53aWR0aHNbaW5kZXhdID09PSB1bmRlZmluZWQgJiYgaW5kZXggPj0gcHJvcGVydGllcy5maXJzdENoYXIgJiYgaW5kZXggPD0gcHJvcGVydGllcy5sYXN0Q2hhcikgewogICAgICAgICAgcHJvcGVydGllcy53aWR0aHNbaW5kZXhdID0gY2hhclN0cmluZy53aWR0aDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBwcm9ncmFtOwogIH0KICBleHRyYWN0Rm9udEhlYWRlcihwcm9wZXJ0aWVzKSB7CiAgICBsZXQgdG9rZW47CiAgICB3aGlsZSAoKHRva2VuID0gdGhpcy5nZXRUb2tlbigpKSAhPT0gbnVsbCkgewogICAgICBpZiAodG9rZW4gIT09ICIvIikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHRva2VuID0gdGhpcy5nZXRUb2tlbigpOwogICAgICBzd2l0Y2ggKHRva2VuKSB7CiAgICAgICAgY2FzZSAiRm9udE1hdHJpeCI6CiAgICAgICAgICBjb25zdCBtYXRyaXggPSB0aGlzLnJlYWROdW1iZXJBcnJheSgpOwogICAgICAgICAgcHJvcGVydGllcy5mb250TWF0cml4ID0gbWF0cml4OwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiRW5jb2RpbmciOgogICAgICAgICAgY29uc3QgZW5jb2RpbmdBcmcgPSB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICBsZXQgZW5jb2Rpbmc7CiAgICAgICAgICBpZiAoIS9eXGQrJC8udGVzdChlbmNvZGluZ0FyZykpIHsKICAgICAgICAgICAgZW5jb2RpbmcgPSBnZXRFbmNvZGluZyhlbmNvZGluZ0FyZyk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBlbmNvZGluZyA9IFtdOwogICAgICAgICAgICBjb25zdCBzaXplID0gcGFyc2VJbnQoZW5jb2RpbmdBcmcsIDEwKSB8IDA7CiAgICAgICAgICAgIHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBzaXplOyBqKyspIHsKICAgICAgICAgICAgICB0b2tlbiA9IHRoaXMuZ2V0VG9rZW4oKTsKICAgICAgICAgICAgICB3aGlsZSAodG9rZW4gIT09ICJkdXAiICYmIHRva2VuICE9PSAiZGVmIikgewogICAgICAgICAgICAgICAgdG9rZW4gPSB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICAgICAgICBpZiAodG9rZW4gPT09IG51bGwpIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAodG9rZW4gPT09ICJkZWYiKSB7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgaW5kZXggPSB0aGlzLnJlYWRJbnQoKTsKICAgICAgICAgICAgICB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICAgICAgY29uc3QgZ2x5cGggPSB0aGlzLmdldFRva2VuKCk7CiAgICAgICAgICAgICAgZW5jb2RpbmdbaW5kZXhdID0gZ2x5cGg7CiAgICAgICAgICAgICAgdGhpcy5nZXRUb2tlbigpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBwcm9wZXJ0aWVzLmJ1aWx0SW5FbmNvZGluZyA9IGVuY29kaW5nOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiRm9udEJCb3giOgogICAgICAgICAgY29uc3QgZm9udEJCb3ggPSB0aGlzLnJlYWROdW1iZXJBcnJheSgpOwogICAgICAgICAgcHJvcGVydGllcy5hc2NlbnQgPSBNYXRoLm1heChmb250QkJveFszXSwgZm9udEJCb3hbMV0pOwogICAgICAgICAgcHJvcGVydGllcy5kZXNjZW50ID0gTWF0aC5taW4oZm9udEJCb3hbMV0sIGZvbnRCQm94WzNdKTsKICAgICAgICAgIHByb3BlcnRpZXMuYXNjZW50U2NhbGVkID0gdHJ1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS90eXBlMV9mb250LmpzCgoKCgoKCgpmdW5jdGlvbiBmaW5kQmxvY2soc3RyZWFtQnl0ZXMsIHNpZ25hdHVyZSwgc3RhcnRJbmRleCkgewogIGNvbnN0IHN0cmVhbUJ5dGVzTGVuZ3RoID0gc3RyZWFtQnl0ZXMubGVuZ3RoOwogIGNvbnN0IHNpZ25hdHVyZUxlbmd0aCA9IHNpZ25hdHVyZS5sZW5ndGg7CiAgY29uc3Qgc2Nhbkxlbmd0aCA9IHN0cmVhbUJ5dGVzTGVuZ3RoIC0gc2lnbmF0dXJlTGVuZ3RoOwogIGxldCBpID0gc3RhcnRJbmRleCwKICAgIGZvdW5kID0gZmFsc2U7CiAgd2hpbGUgKGkgPCBzY2FuTGVuZ3RoKSB7CiAgICBsZXQgaiA9IDA7CiAgICB3aGlsZSAoaiA8IHNpZ25hdHVyZUxlbmd0aCAmJiBzdHJlYW1CeXRlc1tpICsgal0gPT09IHNpZ25hdHVyZVtqXSkgewogICAgICBqKys7CiAgICB9CiAgICBpZiAoaiA+PSBzaWduYXR1cmVMZW5ndGgpIHsKICAgICAgaSArPSBqOwogICAgICB3aGlsZSAoaSA8IHN0cmVhbUJ5dGVzTGVuZ3RoICYmIGlzV2hpdGVTcGFjZShzdHJlYW1CeXRlc1tpXSkpIHsKICAgICAgICBpKys7CiAgICAgIH0KICAgICAgZm91bmQgPSB0cnVlOwogICAgICBicmVhazsKICAgIH0KICAgIGkrKzsKICB9CiAgcmV0dXJuIHsKICAgIGZvdW5kLAogICAgbGVuZ3RoOiBpCiAgfTsKfQpmdW5jdGlvbiBnZXRIZWFkZXJCbG9jayhzdHJlYW0sIHN1Z2dlc3RlZExlbmd0aCkgewogIGNvbnN0IEVFWEVDX1NJR05BVFVSRSA9IFsweDY1LCAweDY1LCAweDc4LCAweDY1LCAweDYzXTsKICBjb25zdCBzdHJlYW1TdGFydFBvcyA9IHN0cmVhbS5wb3M7CiAgbGV0IGhlYWRlckJ5dGVzLCBoZWFkZXJCeXRlc0xlbmd0aCwgYmxvY2s7CiAgdHJ5IHsKICAgIGhlYWRlckJ5dGVzID0gc3RyZWFtLmdldEJ5dGVzKHN1Z2dlc3RlZExlbmd0aCk7CiAgICBoZWFkZXJCeXRlc0xlbmd0aCA9IGhlYWRlckJ5dGVzLmxlbmd0aDsKICB9IGNhdGNoIHt9CiAgaWYgKGhlYWRlckJ5dGVzTGVuZ3RoID09PSBzdWdnZXN0ZWRMZW5ndGgpIHsKICAgIGJsb2NrID0gZmluZEJsb2NrKGhlYWRlckJ5dGVzLCBFRVhFQ19TSUdOQVRVUkUsIHN1Z2dlc3RlZExlbmd0aCAtIDIgKiBFRVhFQ19TSUdOQVRVUkUubGVuZ3RoKTsKICAgIGlmIChibG9jay5mb3VuZCAmJiBibG9jay5sZW5ndGggPT09IHN1Z2dlc3RlZExlbmd0aCkgewogICAgICByZXR1cm4gewogICAgICAgIHN0cmVhbTogbmV3IFN0cmVhbShoZWFkZXJCeXRlcyksCiAgICAgICAgbGVuZ3RoOiBzdWdnZXN0ZWRMZW5ndGgKICAgICAgfTsKICAgIH0KICB9CiAgd2FybignSW52YWxpZCAiTGVuZ3RoMSIgcHJvcGVydHkgaW4gVHlwZTEgZm9udCAtLSB0cnlpbmcgdG8gcmVjb3Zlci4nKTsKICBzdHJlYW0ucG9zID0gc3RyZWFtU3RhcnRQb3M7CiAgY29uc3QgU0NBTl9CTE9DS19MRU5HVEggPSAyMDQ4OwogIGxldCBhY3R1YWxMZW5ndGg7CiAgd2hpbGUgKHRydWUpIHsKICAgIGNvbnN0IHNjYW5CeXRlcyA9IHN0cmVhbS5wZWVrQnl0ZXMoU0NBTl9CTE9DS19MRU5HVEgpOwogICAgYmxvY2sgPSBmaW5kQmxvY2soc2NhbkJ5dGVzLCBFRVhFQ19TSUdOQVRVUkUsIDApOwogICAgaWYgKGJsb2NrLmxlbmd0aCA9PT0gMCkgewogICAgICBicmVhazsKICAgIH0KICAgIHN0cmVhbS5wb3MgKz0gYmxvY2subGVuZ3RoOwogICAgaWYgKGJsb2NrLmZvdW5kKSB7CiAgICAgIGFjdHVhbExlbmd0aCA9IHN0cmVhbS5wb3MgLSBzdHJlYW1TdGFydFBvczsKICAgICAgYnJlYWs7CiAgICB9CiAgfQogIHN0cmVhbS5wb3MgPSBzdHJlYW1TdGFydFBvczsKICBpZiAoYWN0dWFsTGVuZ3RoKSB7CiAgICByZXR1cm4gewogICAgICBzdHJlYW06IG5ldyBTdHJlYW0oc3RyZWFtLmdldEJ5dGVzKGFjdHVhbExlbmd0aCkpLAogICAgICBsZW5ndGg6IGFjdHVhbExlbmd0aAogICAgfTsKICB9CiAgd2FybignVW5hYmxlIHRvIHJlY292ZXIgIkxlbmd0aDEiIHByb3BlcnR5IGluIFR5cGUxIGZvbnQgLS0gdXNpbmcgYXMgaXMuJyk7CiAgcmV0dXJuIHsKICAgIHN0cmVhbTogbmV3IFN0cmVhbShzdHJlYW0uZ2V0Qnl0ZXMoc3VnZ2VzdGVkTGVuZ3RoKSksCiAgICBsZW5ndGg6IHN1Z2dlc3RlZExlbmd0aAogIH07Cn0KZnVuY3Rpb24gZ2V0RWV4ZWNCbG9jayhzdHJlYW0sIHN1Z2dlc3RlZExlbmd0aCkgewogIGNvbnN0IGVleGVjQnl0ZXMgPSBzdHJlYW0uZ2V0Qnl0ZXMoKTsKICBpZiAoZWV4ZWNCeXRlcy5sZW5ndGggPT09IDApIHsKICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiZ2V0RWV4ZWNCbG9jayAtIG5vIGZvbnQgcHJvZ3JhbSBmb3VuZC4iKTsKICB9CiAgcmV0dXJuIHsKICAgIHN0cmVhbTogbmV3IFN0cmVhbShlZXhlY0J5dGVzKSwKICAgIGxlbmd0aDogZWV4ZWNCeXRlcy5sZW5ndGgKICB9Owp9CmNsYXNzIFR5cGUxRm9udCB7CiAgY29uc3RydWN0b3IobmFtZSwgZmlsZSwgcHJvcGVydGllcykgewogICAgY29uc3QgUEZCX0hFQURFUl9TSVpFID0gNjsKICAgIGxldCBoZWFkZXJCbG9ja0xlbmd0aCA9IHByb3BlcnRpZXMubGVuZ3RoMTsKICAgIGxldCBlZXhlY0Jsb2NrTGVuZ3RoID0gcHJvcGVydGllcy5sZW5ndGgyOwogICAgbGV0IHBmYkhlYWRlciA9IGZpbGUucGVla0J5dGVzKFBGQl9IRUFERVJfU0laRSk7CiAgICBjb25zdCBwZmJIZWFkZXJQcmVzZW50ID0gcGZiSGVhZGVyWzBdID09PSAweDgwICYmIHBmYkhlYWRlclsxXSA9PT0gMHgwMTsKICAgIGlmIChwZmJIZWFkZXJQcmVzZW50KSB7CiAgICAgIGZpbGUuc2tpcChQRkJfSEVBREVSX1NJWkUpOwogICAgICBoZWFkZXJCbG9ja0xlbmd0aCA9IHBmYkhlYWRlcls1XSA8PCAyNCB8IHBmYkhlYWRlcls0XSA8PCAxNiB8IHBmYkhlYWRlclszXSA8PCA4IHwgcGZiSGVhZGVyWzJdOwogICAgfQogICAgY29uc3QgaGVhZGVyQmxvY2sgPSBnZXRIZWFkZXJCbG9jayhmaWxlLCBoZWFkZXJCbG9ja0xlbmd0aCk7CiAgICBjb25zdCBoZWFkZXJCbG9ja1BhcnNlciA9IG5ldyBUeXBlMVBhcnNlcihoZWFkZXJCbG9jay5zdHJlYW0sIGZhbHNlLCBTRUFDX0FOQUxZU0lTX0VOQUJMRUQpOwogICAgaGVhZGVyQmxvY2tQYXJzZXIuZXh0cmFjdEZvbnRIZWFkZXIocHJvcGVydGllcyk7CiAgICBpZiAocGZiSGVhZGVyUHJlc2VudCkgewogICAgICBwZmJIZWFkZXIgPSBmaWxlLmdldEJ5dGVzKFBGQl9IRUFERVJfU0laRSk7CiAgICAgIGVleGVjQmxvY2tMZW5ndGggPSBwZmJIZWFkZXJbNV0gPDwgMjQgfCBwZmJIZWFkZXJbNF0gPDwgMTYgfCBwZmJIZWFkZXJbM10gPDwgOCB8IHBmYkhlYWRlclsyXTsKICAgIH0KICAgIGNvbnN0IGVleGVjQmxvY2sgPSBnZXRFZXhlY0Jsb2NrKGZpbGUsIGVleGVjQmxvY2tMZW5ndGgpOwogICAgY29uc3QgZWV4ZWNCbG9ja1BhcnNlciA9IG5ldyBUeXBlMVBhcnNlcihlZXhlY0Jsb2NrLnN0cmVhbSwgdHJ1ZSwgU0VBQ19BTkFMWVNJU19FTkFCTEVEKTsKICAgIGNvbnN0IGRhdGEgPSBlZXhlY0Jsb2NrUGFyc2VyLmV4dHJhY3RGb250UHJvZ3JhbShwcm9wZXJ0aWVzKTsKICAgIGZvciAoY29uc3Qga2V5IGluIGRhdGEucHJvcGVydGllcykgewogICAgICBwcm9wZXJ0aWVzW2tleV0gPSBkYXRhLnByb3BlcnRpZXNba2V5XTsKICAgIH0KICAgIGNvbnN0IGNoYXJzdHJpbmdzID0gZGF0YS5jaGFyc3RyaW5nczsKICAgIGNvbnN0IHR5cGUyQ2hhcnN0cmluZ3MgPSB0aGlzLmdldFR5cGUyQ2hhcnN0cmluZ3MoY2hhcnN0cmluZ3MpOwogICAgY29uc3Qgc3VicnMgPSB0aGlzLmdldFR5cGUyU3VicnMoZGF0YS5zdWJycyk7CiAgICB0aGlzLmNoYXJzdHJpbmdzID0gY2hhcnN0cmluZ3M7CiAgICB0aGlzLmRhdGEgPSB0aGlzLndyYXAobmFtZSwgdHlwZTJDaGFyc3RyaW5ncywgdGhpcy5jaGFyc3RyaW5ncywgc3VicnMsIHByb3BlcnRpZXMpOwogICAgdGhpcy5zZWFjcyA9IHRoaXMuZ2V0U2VhY3MoZGF0YS5jaGFyc3RyaW5ncyk7CiAgfQogIGdldCBudW1HbHlwaHMoKSB7CiAgICByZXR1cm4gdGhpcy5jaGFyc3RyaW5ncy5sZW5ndGggKyAxOwogIH0KICBnZXRDaGFyc2V0KCkgewogICAgY29uc3QgY2hhcnNldCA9IFsiLm5vdGRlZiJdOwogICAgZm9yIChjb25zdCB7CiAgICAgIGdseXBoTmFtZQogICAgfSBvZiB0aGlzLmNoYXJzdHJpbmdzKSB7CiAgICAgIGNoYXJzZXQucHVzaChnbHlwaE5hbWUpOwogICAgfQogICAgcmV0dXJuIGNoYXJzZXQ7CiAgfQogIGdldEdseXBoTWFwcGluZyhwcm9wZXJ0aWVzKSB7CiAgICBjb25zdCBjaGFyc3RyaW5ncyA9IHRoaXMuY2hhcnN0cmluZ3M7CiAgICBpZiAocHJvcGVydGllcy5jb21wb3NpdGUpIHsKICAgICAgY29uc3QgY2hhckNvZGVUb0dseXBoSWQgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBmb3IgKGxldCBnbHlwaElkID0gMCwgY2hhcnN0cmluZ3NMZW4gPSBjaGFyc3RyaW5ncy5sZW5ndGg7IGdseXBoSWQgPCBjaGFyc3RyaW5nc0xlbjsgZ2x5cGhJZCsrKSB7CiAgICAgICAgY29uc3QgY2hhckNvZGUgPSBwcm9wZXJ0aWVzLmNNYXAuY2hhckNvZGVPZihnbHlwaElkKTsKICAgICAgICBjaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0gPSBnbHlwaElkICsgMTsKICAgICAgfQogICAgICByZXR1cm4gY2hhckNvZGVUb0dseXBoSWQ7CiAgICB9CiAgICBjb25zdCBnbHlwaE5hbWVzID0gWyIubm90ZGVmIl07CiAgICBsZXQgYnVpbHRJbkVuY29kaW5nLCBnbHlwaElkOwogICAgZm9yIChnbHlwaElkID0gMDsgZ2x5cGhJZCA8IGNoYXJzdHJpbmdzLmxlbmd0aDsgZ2x5cGhJZCsrKSB7CiAgICAgIGdseXBoTmFtZXMucHVzaChjaGFyc3RyaW5nc1tnbHlwaElkXS5nbHlwaE5hbWUpOwogICAgfQogICAgY29uc3QgZW5jb2RpbmcgPSBwcm9wZXJ0aWVzLmJ1aWx0SW5FbmNvZGluZzsKICAgIGlmIChlbmNvZGluZykgewogICAgICBidWlsdEluRW5jb2RpbmcgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBmb3IgKGNvbnN0IGNoYXJDb2RlIGluIGVuY29kaW5nKSB7CiAgICAgICAgZ2x5cGhJZCA9IGdseXBoTmFtZXMuaW5kZXhPZihlbmNvZGluZ1tjaGFyQ29kZV0pOwogICAgICAgIGlmIChnbHlwaElkID49IDApIHsKICAgICAgICAgIGJ1aWx0SW5FbmNvZGluZ1tjaGFyQ29kZV0gPSBnbHlwaElkOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgcmV0dXJuIHR5cGUxRm9udEdseXBoTWFwcGluZyhwcm9wZXJ0aWVzLCBidWlsdEluRW5jb2RpbmcsIGdseXBoTmFtZXMpOwogIH0KICBoYXNHbHlwaElkKGlkKSB7CiAgICBpZiAoaWQgPCAwIHx8IGlkID49IHRoaXMubnVtR2x5cGhzKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmIChpZCA9PT0gMCkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGNvbnN0IGdseXBoID0gdGhpcy5jaGFyc3RyaW5nc1tpZCAtIDFdOwogICAgcmV0dXJuIGdseXBoLmNoYXJzdHJpbmcubGVuZ3RoID4gMDsKICB9CiAgZ2V0U2VhY3MoY2hhcnN0cmluZ3MpIHsKICAgIGNvbnN0IHNlYWNNYXAgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGNoYXJzdHJpbmdzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgY2hhcnN0cmluZyA9IGNoYXJzdHJpbmdzW2ldOwogICAgICBpZiAoY2hhcnN0cmluZy5zZWFjKSB7CiAgICAgICAgc2VhY01hcFtpICsgMV0gPSBjaGFyc3RyaW5nLnNlYWM7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzZWFjTWFwOwogIH0KICBnZXRUeXBlMkNoYXJzdHJpbmdzKHR5cGUxQ2hhcnN0cmluZ3MpIHsKICAgIGNvbnN0IHR5cGUyQ2hhcnN0cmluZ3MgPSBbXTsKICAgIGZvciAoY29uc3QgdHlwZTFDaGFyc3RyaW5nIG9mIHR5cGUxQ2hhcnN0cmluZ3MpIHsKICAgICAgdHlwZTJDaGFyc3RyaW5ncy5wdXNoKHR5cGUxQ2hhcnN0cmluZy5jaGFyc3RyaW5nKTsKICAgIH0KICAgIHJldHVybiB0eXBlMkNoYXJzdHJpbmdzOwogIH0KICBnZXRUeXBlMlN1YnJzKHR5cGUxU3VicnMpIHsKICAgIGxldCBiaWFzID0gMDsKICAgIGNvbnN0IGNvdW50ID0gdHlwZTFTdWJycy5sZW5ndGg7CiAgICBpZiAoY291bnQgPCAxMTMzKSB7CiAgICAgIGJpYXMgPSAxMDc7CiAgICB9IGVsc2UgaWYgKGNvdW50IDwgMzM3NjkpIHsKICAgICAgYmlhcyA9IDExMzE7CiAgICB9IGVsc2UgewogICAgICBiaWFzID0gMzI3Njg7CiAgICB9CiAgICBjb25zdCB0eXBlMlN1YnJzID0gW107CiAgICBsZXQgaTsKICAgIGZvciAoaSA9IDA7IGkgPCBiaWFzOyBpKyspIHsKICAgICAgdHlwZTJTdWJycy5wdXNoKFsweDBiXSk7CiAgICB9CiAgICBmb3IgKGkgPSAwOyBpIDwgY291bnQ7IGkrKykgewogICAgICB0eXBlMlN1YnJzLnB1c2godHlwZTFTdWJyc1tpXSk7CiAgICB9CiAgICByZXR1cm4gdHlwZTJTdWJyczsKICB9CiAgd3JhcChuYW1lLCBnbHlwaHMsIGNoYXJzdHJpbmdzLCBzdWJycywgcHJvcGVydGllcykgewogICAgY29uc3QgY2ZmID0gbmV3IENGRigpOwogICAgY2ZmLmhlYWRlciA9IG5ldyBDRkZIZWFkZXIoMSwgMCwgNCwgNCk7CiAgICBjZmYubmFtZXMgPSBbbmFtZV07CiAgICBjb25zdCB0b3BEaWN0ID0gbmV3IENGRlRvcERpY3QoKTsKICAgIHRvcERpY3Quc2V0QnlOYW1lKCJ2ZXJzaW9uIiwgMzkxKTsKICAgIHRvcERpY3Quc2V0QnlOYW1lKCJOb3RpY2UiLCAzOTIpOwogICAgdG9wRGljdC5zZXRCeU5hbWUoIkZ1bGxOYW1lIiwgMzkzKTsKICAgIHRvcERpY3Quc2V0QnlOYW1lKCJGYW1pbHlOYW1lIiwgMzk0KTsKICAgIHRvcERpY3Quc2V0QnlOYW1lKCJXZWlnaHQiLCAzOTUpOwogICAgdG9wRGljdC5zZXRCeU5hbWUoIkVuY29kaW5nIiwgbnVsbCk7CiAgICB0b3BEaWN0LnNldEJ5TmFtZSgiRm9udE1hdHJpeCIsIHByb3BlcnRpZXMuZm9udE1hdHJpeCk7CiAgICB0b3BEaWN0LnNldEJ5TmFtZSgiRm9udEJCb3giLCBwcm9wZXJ0aWVzLmJib3gpOwogICAgdG9wRGljdC5zZXRCeU5hbWUoImNoYXJzZXQiLCBudWxsKTsKICAgIHRvcERpY3Quc2V0QnlOYW1lKCJDaGFyU3RyaW5ncyIsIG51bGwpOwogICAgdG9wRGljdC5zZXRCeU5hbWUoIlByaXZhdGUiLCBudWxsKTsKICAgIGNmZi50b3BEaWN0ID0gdG9wRGljdDsKICAgIGNvbnN0IHN0cmluZ3MgPSBuZXcgQ0ZGU3RyaW5ncygpOwogICAgc3RyaW5ncy5hZGQoIlZlcnNpb24gMC4xMSIpOwogICAgc3RyaW5ncy5hZGQoIlNlZSBvcmlnaW5hbCBub3RpY2UiKTsKICAgIHN0cmluZ3MuYWRkKG5hbWUpOwogICAgc3RyaW5ncy5hZGQobmFtZSk7CiAgICBzdHJpbmdzLmFkZCgiTWVkaXVtIik7CiAgICBjZmYuc3RyaW5ncyA9IHN0cmluZ3M7CiAgICBjZmYuZ2xvYmFsU3VickluZGV4ID0gbmV3IENGRkluZGV4KCk7CiAgICBjb25zdCBjb3VudCA9IGdseXBocy5sZW5ndGg7CiAgICBjb25zdCBjaGFyc2V0QXJyYXkgPSBbIi5ub3RkZWYiXTsKICAgIGxldCBpLCBpaTsKICAgIGZvciAoaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7CiAgICAgIGNvbnN0IGdseXBoTmFtZSA9IGNoYXJzdHJpbmdzW2ldLmdseXBoTmFtZTsKICAgICAgY29uc3QgaW5kZXggPSBDRkZTdGFuZGFyZFN0cmluZ3MuaW5kZXhPZihnbHlwaE5hbWUpOwogICAgICBpZiAoaW5kZXggPT09IC0xKSB7CiAgICAgICAgc3RyaW5ncy5hZGQoZ2x5cGhOYW1lKTsKICAgICAgfQogICAgICBjaGFyc2V0QXJyYXkucHVzaChnbHlwaE5hbWUpOwogICAgfQogICAgY2ZmLmNoYXJzZXQgPSBuZXcgQ0ZGQ2hhcnNldChmYWxzZSwgMCwgY2hhcnNldEFycmF5KTsKICAgIGNvbnN0IGNoYXJTdHJpbmdzSW5kZXggPSBuZXcgQ0ZGSW5kZXgoKTsKICAgIGNoYXJTdHJpbmdzSW5kZXguYWRkKFsweDhiLCAweDBlXSk7CiAgICBmb3IgKGkgPSAwOyBpIDwgY291bnQ7IGkrKykgewogICAgICBjaGFyU3RyaW5nc0luZGV4LmFkZChnbHlwaHNbaV0pOwogICAgfQogICAgY2ZmLmNoYXJTdHJpbmdzID0gY2hhclN0cmluZ3NJbmRleDsKICAgIGNvbnN0IHByaXZhdGVEaWN0ID0gbmV3IENGRlByaXZhdGVEaWN0KCk7CiAgICBwcml2YXRlRGljdC5zZXRCeU5hbWUoIlN1YnJzIiwgbnVsbCk7CiAgICBjb25zdCBmaWVsZHMgPSBbIkJsdWVWYWx1ZXMiLCAiT3RoZXJCbHVlcyIsICJGYW1pbHlCbHVlcyIsICJGYW1pbHlPdGhlckJsdWVzIiwgIlN0ZW1TbmFwSCIsICJTdGVtU25hcFYiLCAiQmx1ZVNoaWZ0IiwgIkJsdWVGdXp6IiwgIkJsdWVTY2FsZSIsICJMYW5ndWFnZUdyb3VwIiwgIkV4cGFuc2lvbkZhY3RvciIsICJGb3JjZUJvbGQiLCAiU3RkSFciLCAiU3RkVlciXTsKICAgIGZvciAoaSA9IDAsIGlpID0gZmllbGRzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgZmllbGQgPSBmaWVsZHNbaV07CiAgICAgIGlmICghKGZpZWxkIGluIHByb3BlcnRpZXMucHJpdmF0ZURhdGEpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgdmFsdWUgPSBwcm9wZXJ0aWVzLnByaXZhdGVEYXRhW2ZpZWxkXTsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7CiAgICAgICAgZm9yIChsZXQgaiA9IHZhbHVlLmxlbmd0aCAtIDE7IGogPiAwOyBqLS0pIHsKICAgICAgICAgIHZhbHVlW2pdIC09IHZhbHVlW2ogLSAxXTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcHJpdmF0ZURpY3Quc2V0QnlOYW1lKGZpZWxkLCB2YWx1ZSk7CiAgICB9CiAgICBjZmYudG9wRGljdC5wcml2YXRlRGljdCA9IHByaXZhdGVEaWN0OwogICAgY29uc3Qgc3VickluZGV4ID0gbmV3IENGRkluZGV4KCk7CiAgICBmb3IgKGkgPSAwLCBpaSA9IHN1YnJzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgc3VickluZGV4LmFkZChzdWJyc1tpXSk7CiAgICB9CiAgICBwcml2YXRlRGljdC5zdWJyc0luZGV4ID0gc3VickluZGV4OwogICAgY29uc3QgY29tcGlsZXIgPSBuZXcgQ0ZGQ29tcGlsZXIoY2ZmKTsKICAgIHJldHVybiBjb21waWxlci5jb21waWxlKCk7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9mb250cy5qcwoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCmNvbnN0IFBSSVZBVEVfVVNFX0FSRUFTID0gW1sweGUwMDAsIDB4ZjhmZl0sIFsweDEwMDAwMCwgMHgxMGZmZmRdXTsKY29uc3QgUERGX0dMWVBIX1NQQUNFX1VOSVRTID0gMTAwMDsKY29uc3QgRVhQT1JUX0RBVEFfUFJPUEVSVElFUyA9IFsiYXNjZW50IiwgImJib3giLCAiYmxhY2siLCAiYm9sZCIsICJjaGFyUHJvY09wZXJhdG9yTGlzdCIsICJjc3NGb250SW5mbyIsICJkYXRhIiwgImRlZmF1bHRWTWV0cmljcyIsICJkZWZhdWx0V2lkdGgiLCAiZGVzY2VudCIsICJkaXNhYmxlRm9udEZhY2UiLCAiZmFsbGJhY2tOYW1lIiwgImZvbnRFeHRyYVByb3BlcnRpZXMiLCAiZm9udE1hdHJpeCIsICJpc0ludmFsaWRQREZqc0ZvbnQiLCAiaXNUeXBlM0ZvbnQiLCAiaXRhbGljIiwgImxvYWRlZE5hbWUiLCAibWltZXR5cGUiLCAibWlzc2luZ0ZpbGUiLCAibmFtZSIsICJyZW1lYXN1cmUiLCAic3lzdGVtRm9udEluZm8iLCAidmVydGljYWwiXTsKY29uc3QgRVhQT1JUX0RBVEFfRVhUUkFfUFJPUEVSVElFUyA9IFsiY01hcCIsICJjb21wb3NpdGUiLCAiZGVmYXVsdEVuY29kaW5nIiwgImRpZmZlcmVuY2VzIiwgImlzTW9ub3NwYWNlIiwgImlzU2VyaWZGb250IiwgImlzU3ltYm9saWNGb250IiwgInNlYWNNYXAiLCAic3VidHlwZSIsICJ0b0ZvbnRDaGFyIiwgInRvVW5pY29kZSIsICJ0eXBlIiwgInZtZXRyaWNzIiwgIndpZHRocyJdOwpmdW5jdGlvbiBhZGp1c3RXaWR0aHMocHJvcGVydGllcykgewogIGlmICghcHJvcGVydGllcy5mb250TWF0cml4KSB7CiAgICByZXR1cm47CiAgfQogIGlmIChwcm9wZXJ0aWVzLmZvbnRNYXRyaXhbMF0gPT09IEZPTlRfSURFTlRJVFlfTUFUUklYWzBdKSB7CiAgICByZXR1cm47CiAgfQogIGNvbnN0IHNjYWxlID0gMC4wMDEgLyBwcm9wZXJ0aWVzLmZvbnRNYXRyaXhbMF07CiAgY29uc3QgZ2x5cGhzV2lkdGhzID0gcHJvcGVydGllcy53aWR0aHM7CiAgZm9yIChjb25zdCBnbHlwaCBpbiBnbHlwaHNXaWR0aHMpIHsKICAgIGdseXBoc1dpZHRoc1tnbHlwaF0gKj0gc2NhbGU7CiAgfQogIHByb3BlcnRpZXMuZGVmYXVsdFdpZHRoICo9IHNjYWxlOwp9CmZ1bmN0aW9uIGFkanVzdFRydWVUeXBlVG9Vbmljb2RlKHByb3BlcnRpZXMsIGlzU3ltYm9saWNGb250LCBuYW1lUmVjb3JkcykgewogIGlmIChwcm9wZXJ0aWVzLmlzSW50ZXJuYWxGb250KSB7CiAgICByZXR1cm47CiAgfQogIGlmIChwcm9wZXJ0aWVzLmhhc0luY2x1ZGVkVG9Vbmljb2RlTWFwKSB7CiAgICByZXR1cm47CiAgfQogIGlmIChwcm9wZXJ0aWVzLmhhc0VuY29kaW5nKSB7CiAgICByZXR1cm47CiAgfQogIGlmIChwcm9wZXJ0aWVzLnRvVW5pY29kZSBpbnN0YW5jZW9mIElkZW50aXR5VG9Vbmljb2RlTWFwKSB7CiAgICByZXR1cm47CiAgfQogIGlmICghaXNTeW1ib2xpY0ZvbnQpIHsKICAgIHJldHVybjsKICB9CiAgaWYgKG5hbWVSZWNvcmRzLmxlbmd0aCA9PT0gMCkgewogICAgcmV0dXJuOwogIH0KICBpZiAocHJvcGVydGllcy5kZWZhdWx0RW5jb2RpbmcgPT09IFdpbkFuc2lFbmNvZGluZykgewogICAgcmV0dXJuOwogIH0KICBmb3IgKGNvbnN0IHIgb2YgbmFtZVJlY29yZHMpIHsKICAgIGlmICghaXNXaW5OYW1lUmVjb3JkKHIpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICB9CiAgY29uc3QgZW5jb2RpbmcgPSBXaW5BbnNpRW5jb2Rpbmc7CiAgY29uc3QgdG9Vbmljb2RlID0gW10sCiAgICBnbHlwaHNVbmljb2RlTWFwID0gZ2V0R2x5cGhzVW5pY29kZSgpOwogIGZvciAoY29uc3QgY2hhckNvZGUgaW4gZW5jb2RpbmcpIHsKICAgIGNvbnN0IGdseXBoTmFtZSA9IGVuY29kaW5nW2NoYXJDb2RlXTsKICAgIGlmIChnbHlwaE5hbWUgPT09ICIiKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgY29uc3QgdW5pY29kZSA9IGdseXBoc1VuaWNvZGVNYXBbZ2x5cGhOYW1lXTsKICAgIGlmICh1bmljb2RlID09PSB1bmRlZmluZWQpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICB0b1VuaWNvZGVbY2hhckNvZGVdID0gU3RyaW5nLmZyb21DaGFyQ29kZSh1bmljb2RlKTsKICB9CiAgaWYgKHRvVW5pY29kZS5sZW5ndGggPiAwKSB7CiAgICBwcm9wZXJ0aWVzLnRvVW5pY29kZS5hbWVuZCh0b1VuaWNvZGUpOwogIH0KfQpmdW5jdGlvbiBhZGp1c3RUeXBlMVRvVW5pY29kZShwcm9wZXJ0aWVzLCBidWlsdEluRW5jb2RpbmcpIHsKICBpZiAocHJvcGVydGllcy5pc0ludGVybmFsRm9udCkgewogICAgcmV0dXJuOwogIH0KICBpZiAocHJvcGVydGllcy5oYXNJbmNsdWRlZFRvVW5pY29kZU1hcCkgewogICAgcmV0dXJuOwogIH0KICBpZiAoYnVpbHRJbkVuY29kaW5nID09PSBwcm9wZXJ0aWVzLmRlZmF1bHRFbmNvZGluZykgewogICAgcmV0dXJuOwogIH0KICBpZiAocHJvcGVydGllcy50b1VuaWNvZGUgaW5zdGFuY2VvZiBJZGVudGl0eVRvVW5pY29kZU1hcCkgewogICAgcmV0dXJuOwogIH0KICBjb25zdCB0b1VuaWNvZGUgPSBbXSwKICAgIGdseXBoc1VuaWNvZGVNYXAgPSBnZXRHbHlwaHNVbmljb2RlKCk7CiAgZm9yIChjb25zdCBjaGFyQ29kZSBpbiBidWlsdEluRW5jb2RpbmcpIHsKICAgIGlmIChwcm9wZXJ0aWVzLmhhc0VuY29kaW5nKSB7CiAgICAgIGlmIChwcm9wZXJ0aWVzLmJhc2VFbmNvZGluZ05hbWUgfHwgcHJvcGVydGllcy5kaWZmZXJlbmNlc1tjaGFyQ29kZV0gIT09IHVuZGVmaW5lZCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICB9CiAgICBjb25zdCBnbHlwaE5hbWUgPSBidWlsdEluRW5jb2RpbmdbY2hhckNvZGVdOwogICAgY29uc3QgdW5pY29kZSA9IGdldFVuaWNvZGVGb3JHbHlwaChnbHlwaE5hbWUsIGdseXBoc1VuaWNvZGVNYXApOwogICAgaWYgKHVuaWNvZGUgIT09IC0xKSB7CiAgICAgIHRvVW5pY29kZVtjaGFyQ29kZV0gPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHVuaWNvZGUpOwogICAgfQogIH0KICBpZiAodG9Vbmljb2RlLmxlbmd0aCA+IDApIHsKICAgIHByb3BlcnRpZXMudG9Vbmljb2RlLmFtZW5kKHRvVW5pY29kZSk7CiAgfQp9CmZ1bmN0aW9uIGFtZW5kRmFsbGJhY2tUb1VuaWNvZGUocHJvcGVydGllcykgewogIGlmICghcHJvcGVydGllcy5mYWxsYmFja1RvVW5pY29kZSkgewogICAgcmV0dXJuOwogIH0KICBpZiAocHJvcGVydGllcy50b1VuaWNvZGUgaW5zdGFuY2VvZiBJZGVudGl0eVRvVW5pY29kZU1hcCkgewogICAgcmV0dXJuOwogIH0KICBjb25zdCB0b1VuaWNvZGUgPSBbXTsKICBmb3IgKGNvbnN0IGNoYXJDb2RlIGluIHByb3BlcnRpZXMuZmFsbGJhY2tUb1VuaWNvZGUpIHsKICAgIGlmIChwcm9wZXJ0aWVzLnRvVW5pY29kZS5oYXMoY2hhckNvZGUpKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgdG9Vbmljb2RlW2NoYXJDb2RlXSA9IHByb3BlcnRpZXMuZmFsbGJhY2tUb1VuaWNvZGVbY2hhckNvZGVdOwogIH0KICBpZiAodG9Vbmljb2RlLmxlbmd0aCA+IDApIHsKICAgIHByb3BlcnRpZXMudG9Vbmljb2RlLmFtZW5kKHRvVW5pY29kZSk7CiAgfQp9CmNsYXNzIGZvbnRzX0dseXBoIHsKICBjb25zdHJ1Y3RvcihvcmlnaW5hbENoYXJDb2RlLCBmb250Q2hhciwgdW5pY29kZSwgYWNjZW50LCB3aWR0aCwgdm1ldHJpYywgb3BlcmF0b3JMaXN0SWQsIGlzU3BhY2UsIGlzSW5Gb250KSB7CiAgICB0aGlzLm9yaWdpbmFsQ2hhckNvZGUgPSBvcmlnaW5hbENoYXJDb2RlOwogICAgdGhpcy5mb250Q2hhciA9IGZvbnRDaGFyOwogICAgdGhpcy51bmljb2RlID0gdW5pY29kZTsKICAgIHRoaXMuYWNjZW50ID0gYWNjZW50OwogICAgdGhpcy53aWR0aCA9IHdpZHRoOwogICAgdGhpcy52bWV0cmljID0gdm1ldHJpYzsKICAgIHRoaXMub3BlcmF0b3JMaXN0SWQgPSBvcGVyYXRvckxpc3RJZDsKICAgIHRoaXMuaXNTcGFjZSA9IGlzU3BhY2U7CiAgICB0aGlzLmlzSW5Gb250ID0gaXNJbkZvbnQ7CiAgfQogIGdldCBjYXRlZ29yeSgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgImNhdGVnb3J5IiwgZ2V0Q2hhclVuaWNvZGVDYXRlZ29yeSh0aGlzLnVuaWNvZGUpLCB0cnVlKTsKICB9Cn0KZnVuY3Rpb24gaW50MTYoYjAsIGIxKSB7CiAgcmV0dXJuIChiMCA8PCA4KSArIGIxOwp9CmZ1bmN0aW9uIHdyaXRlU2lnbmVkSW50MTYoYnl0ZXMsIGluZGV4LCB2YWx1ZSkgewogIGJ5dGVzW2luZGV4ICsgMV0gPSB2YWx1ZTsKICBieXRlc1tpbmRleF0gPSB2YWx1ZSA+Pj4gODsKfQpmdW5jdGlvbiBzaWduZWRJbnQxNihiMCwgYjEpIHsKICBjb25zdCB2YWx1ZSA9IChiMCA8PCA4KSArIGIxOwogIHJldHVybiB2YWx1ZSAmIDEgPDwgMTUgPyB2YWx1ZSAtIDB4MTAwMDAgOiB2YWx1ZTsKfQpmdW5jdGlvbiB3cml0ZVVpbnQzMihieXRlcywgaW5kZXgsIHZhbHVlKSB7CiAgYnl0ZXNbaW5kZXggKyAzXSA9IHZhbHVlICYgMHhmZjsKICBieXRlc1tpbmRleCArIDJdID0gdmFsdWUgPj4+IDg7CiAgYnl0ZXNbaW5kZXggKyAxXSA9IHZhbHVlID4+PiAxNjsKICBieXRlc1tpbmRleF0gPSB2YWx1ZSA+Pj4gMjQ7Cn0KZnVuY3Rpb24gaW50MzIoYjAsIGIxLCBiMiwgYjMpIHsKICByZXR1cm4gKGIwIDw8IDI0KSArIChiMSA8PCAxNikgKyAoYjIgPDwgOCkgKyBiMzsKfQpmdW5jdGlvbiBzdHJpbmcxNih2YWx1ZSkgewogIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKHZhbHVlID4+IDggJiAweGZmLCB2YWx1ZSAmIDB4ZmYpOwp9CmZ1bmN0aW9uIHNhZmVTdHJpbmcxNih2YWx1ZSkgewogIGlmICh2YWx1ZSA+IDB4N2ZmZikgewogICAgdmFsdWUgPSAweDdmZmY7CiAgfSBlbHNlIGlmICh2YWx1ZSA8IC0weDgwMDApIHsKICAgIHZhbHVlID0gLTB4ODAwMDsKICB9CiAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUodmFsdWUgPj4gOCAmIDB4ZmYsIHZhbHVlICYgMHhmZik7Cn0KZnVuY3Rpb24gaXNUcnVlVHlwZUZpbGUoZmlsZSkgewogIGNvbnN0IGhlYWRlciA9IGZpbGUucGVla0J5dGVzKDQpOwogIHJldHVybiByZWFkVWludDMyKGhlYWRlciwgMCkgPT09IDB4MDAwMTAwMDAgfHwgYnl0ZXNUb1N0cmluZyhoZWFkZXIpID09PSAidHJ1ZSI7Cn0KZnVuY3Rpb24gaXNUcnVlVHlwZUNvbGxlY3Rpb25GaWxlKGZpbGUpIHsKICBjb25zdCBoZWFkZXIgPSBmaWxlLnBlZWtCeXRlcyg0KTsKICByZXR1cm4gYnl0ZXNUb1N0cmluZyhoZWFkZXIpID09PSAidHRjZiI7Cn0KZnVuY3Rpb24gaXNPcGVuVHlwZUZpbGUoZmlsZSkgewogIGNvbnN0IGhlYWRlciA9IGZpbGUucGVla0J5dGVzKDQpOwogIHJldHVybiBieXRlc1RvU3RyaW5nKGhlYWRlcikgPT09ICJPVFRPIjsKfQpmdW5jdGlvbiBpc1R5cGUxRmlsZShmaWxlKSB7CiAgY29uc3QgaGVhZGVyID0gZmlsZS5wZWVrQnl0ZXMoMik7CiAgaWYgKGhlYWRlclswXSA9PT0gMHgyNSAmJiBoZWFkZXJbMV0gPT09IDB4MjEpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICBpZiAoaGVhZGVyWzBdID09PSAweDgwICYmIGhlYWRlclsxXSA9PT0gMHgwMSkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIHJldHVybiBmYWxzZTsKfQpmdW5jdGlvbiBpc0NGRkZpbGUoZmlsZSkgewogIGNvbnN0IGhlYWRlciA9IGZpbGUucGVla0J5dGVzKDQpOwogIGlmIChoZWFkZXJbMF0gPj0gMSAmJiBoZWFkZXJbM10gPj0gMSAmJiBoZWFkZXJbM10gPD0gNCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIHJldHVybiBmYWxzZTsKfQpmdW5jdGlvbiBnZXRGb250RmlsZVR5cGUoZmlsZSwgewogIHR5cGUsCiAgc3VidHlwZSwKICBjb21wb3NpdGUKfSkgewogIGxldCBmaWxlVHlwZSwgZmlsZVN1YnR5cGU7CiAgaWYgKGlzVHJ1ZVR5cGVGaWxlKGZpbGUpIHx8IGlzVHJ1ZVR5cGVDb2xsZWN0aW9uRmlsZShmaWxlKSkgewogICAgZmlsZVR5cGUgPSBjb21wb3NpdGUgPyAiQ0lERm9udFR5cGUyIiA6ICJUcnVlVHlwZSI7CiAgfSBlbHNlIGlmIChpc09wZW5UeXBlRmlsZShmaWxlKSkgewogICAgZmlsZVR5cGUgPSBjb21wb3NpdGUgPyAiQ0lERm9udFR5cGUyIiA6ICJPcGVuVHlwZSI7CiAgfSBlbHNlIGlmIChpc1R5cGUxRmlsZShmaWxlKSkgewogICAgaWYgKGNvbXBvc2l0ZSkgewogICAgICBmaWxlVHlwZSA9ICJDSURGb250VHlwZTAiOwogICAgfSBlbHNlIHsKICAgICAgZmlsZVR5cGUgPSB0eXBlID09PSAiTU1UeXBlMSIgPyAiTU1UeXBlMSIgOiAiVHlwZTEiOwogICAgfQogIH0gZWxzZSBpZiAoaXNDRkZGaWxlKGZpbGUpKSB7CiAgICBpZiAoY29tcG9zaXRlKSB7CiAgICAgIGZpbGVUeXBlID0gIkNJREZvbnRUeXBlMCI7CiAgICAgIGZpbGVTdWJ0eXBlID0gIkNJREZvbnRUeXBlMEMiOwogICAgfSBlbHNlIHsKICAgICAgZmlsZVR5cGUgPSB0eXBlID09PSAiTU1UeXBlMSIgPyAiTU1UeXBlMSIgOiAiVHlwZTEiOwogICAgICBmaWxlU3VidHlwZSA9ICJUeXBlMUMiOwogICAgfQogIH0gZWxzZSB7CiAgICB3YXJuKCJnZXRGb250RmlsZVR5cGU6IFVuYWJsZSB0byBkZXRlY3QgY29ycmVjdCBmb250IGZpbGUgVHlwZS9TdWJ0eXBlLiIpOwogICAgZmlsZVR5cGUgPSB0eXBlOwogICAgZmlsZVN1YnR5cGUgPSBzdWJ0eXBlOwogIH0KICByZXR1cm4gW2ZpbGVUeXBlLCBmaWxlU3VidHlwZV07Cn0KZnVuY3Rpb24gYXBwbHlTdGFuZGFyZEZvbnRHbHlwaE1hcChtYXAsIGdseXBoTWFwKSB7CiAgZm9yIChjb25zdCBjaGFyQ29kZSBpbiBnbHlwaE1hcCkgewogICAgbWFwWytjaGFyQ29kZV0gPSBnbHlwaE1hcFtjaGFyQ29kZV07CiAgfQp9CmZ1bmN0aW9uIGJ1aWxkVG9Gb250Q2hhcihlbmNvZGluZywgZ2x5cGhzVW5pY29kZU1hcCwgZGlmZmVyZW5jZXMpIHsKICBjb25zdCB0b0ZvbnRDaGFyID0gW107CiAgbGV0IHVuaWNvZGU7CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gZW5jb2RpbmcubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgdW5pY29kZSA9IGdldFVuaWNvZGVGb3JHbHlwaChlbmNvZGluZ1tpXSwgZ2x5cGhzVW5pY29kZU1hcCk7CiAgICBpZiAodW5pY29kZSAhPT0gLTEpIHsKICAgICAgdG9Gb250Q2hhcltpXSA9IHVuaWNvZGU7CiAgICB9CiAgfQogIGZvciAoY29uc3QgY2hhckNvZGUgaW4gZGlmZmVyZW5jZXMpIHsKICAgIHVuaWNvZGUgPSBnZXRVbmljb2RlRm9yR2x5cGgoZGlmZmVyZW5jZXNbY2hhckNvZGVdLCBnbHlwaHNVbmljb2RlTWFwKTsKICAgIGlmICh1bmljb2RlICE9PSAtMSkgewogICAgICB0b0ZvbnRDaGFyWytjaGFyQ29kZV0gPSB1bmljb2RlOwogICAgfQogIH0KICByZXR1cm4gdG9Gb250Q2hhcjsKfQpmdW5jdGlvbiBpc01hY05hbWVSZWNvcmQocikgewogIHJldHVybiByLnBsYXRmb3JtID09PSAxICYmIHIuZW5jb2RpbmcgPT09IDAgJiYgci5sYW5ndWFnZSA9PT0gMDsKfQpmdW5jdGlvbiBpc1dpbk5hbWVSZWNvcmQocikgewogIHJldHVybiByLnBsYXRmb3JtID09PSAzICYmIHIuZW5jb2RpbmcgPT09IDEgJiYgci5sYW5ndWFnZSA9PT0gMHg0MDk7Cn0KZnVuY3Rpb24gY29udmVydENpZFN0cmluZyhjaGFyQ29kZSwgY2lkLCBzaG91bGRUaHJvdyA9IGZhbHNlKSB7CiAgc3dpdGNoIChjaWQubGVuZ3RoKSB7CiAgICBjYXNlIDE6CiAgICAgIHJldHVybiBjaWQuY2hhckNvZGVBdCgwKTsKICAgIGNhc2UgMjoKICAgICAgcmV0dXJuIGNpZC5jaGFyQ29kZUF0KDApIDw8IDggfCBjaWQuY2hhckNvZGVBdCgxKTsKICB9CiAgY29uc3QgbXNnID0gYFVuc3VwcG9ydGVkIENJRCBzdHJpbmcgKGNoYXJDb2RlICR7Y2hhckNvZGV9KTogIiR7Y2lkfSIuYDsKICBpZiAoc2hvdWxkVGhyb3cpIHsKICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihtc2cpOwogIH0KICB3YXJuKG1zZyk7CiAgcmV0dXJuIGNpZDsKfQpmdW5jdGlvbiBhZGp1c3RNYXBwaW5nKGNoYXJDb2RlVG9HbHlwaElkLCBoYXNHbHlwaCwgbmV3R2x5cGhaZXJvSWQsIHRvVW5pY29kZSkgewogIGNvbnN0IG5ld01hcCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgY29uc3QgdG9Vbmljb2RlRXh0cmFNYXAgPSBuZXcgTWFwKCk7CiAgY29uc3QgdG9Gb250Q2hhciA9IFtdOwogIGNvbnN0IHVzZWRHbHlwaElkcyA9IG5ldyBTZXQoKTsKICBsZXQgcHJpdmF0ZVVzZUFyZWFJbmRleCA9IDA7CiAgY29uc3QgcHJpdmF0ZVVzZU9mZmV0U3RhcnQgPSBQUklWQVRFX1VTRV9BUkVBU1twcml2YXRlVXNlQXJlYUluZGV4XVswXTsKICBsZXQgbmV4dEF2YWlsYWJsZUZvbnRDaGFyQ29kZSA9IHByaXZhdGVVc2VPZmZldFN0YXJ0OwogIGxldCBwcml2YXRlVXNlT2ZmZXRFbmQgPSBQUklWQVRFX1VTRV9BUkVBU1twcml2YXRlVXNlQXJlYUluZGV4XVsxXTsKICBjb25zdCBpc0luUHJpdmF0ZUFyZWEgPSBjb2RlID0+IFBSSVZBVEVfVVNFX0FSRUFTWzBdWzBdIDw9IGNvZGUgJiYgY29kZSA8PSBQUklWQVRFX1VTRV9BUkVBU1swXVsxXSB8fCBQUklWQVRFX1VTRV9BUkVBU1sxXVswXSA8PSBjb2RlICYmIGNvZGUgPD0gUFJJVkFURV9VU0VfQVJFQVNbMV1bMV07CiAgbGV0IExJR0FUVVJFX1RPX1VOSUNPREUgPSBudWxsOwogIGZvciAoY29uc3Qgb3JpZ2luYWxDaGFyQ29kZSBpbiBjaGFyQ29kZVRvR2x5cGhJZCkgewogICAgbGV0IGdseXBoSWQgPSBjaGFyQ29kZVRvR2x5cGhJZFtvcmlnaW5hbENoYXJDb2RlXTsKICAgIGlmICghaGFzR2x5cGgoZ2x5cGhJZCkpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICBpZiAobmV4dEF2YWlsYWJsZUZvbnRDaGFyQ29kZSA+IHByaXZhdGVVc2VPZmZldEVuZCkgewogICAgICBwcml2YXRlVXNlQXJlYUluZGV4Kys7CiAgICAgIGlmIChwcml2YXRlVXNlQXJlYUluZGV4ID49IFBSSVZBVEVfVVNFX0FSRUFTLmxlbmd0aCkgewogICAgICAgIHdhcm4oIlJhbiBvdXQgb2Ygc3BhY2UgaW4gZm9udCBwcml2YXRlIHVzZSBhcmVhLiIpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIG5leHRBdmFpbGFibGVGb250Q2hhckNvZGUgPSBQUklWQVRFX1VTRV9BUkVBU1twcml2YXRlVXNlQXJlYUluZGV4XVswXTsKICAgICAgcHJpdmF0ZVVzZU9mZmV0RW5kID0gUFJJVkFURV9VU0VfQVJFQVNbcHJpdmF0ZVVzZUFyZWFJbmRleF1bMV07CiAgICB9CiAgICBjb25zdCBmb250Q2hhckNvZGUgPSBuZXh0QXZhaWxhYmxlRm9udENoYXJDb2RlKys7CiAgICBpZiAoZ2x5cGhJZCA9PT0gMCkgewogICAgICBnbHlwaElkID0gbmV3R2x5cGhaZXJvSWQ7CiAgICB9CiAgICBsZXQgdW5pY29kZSA9IHRvVW5pY29kZS5nZXQob3JpZ2luYWxDaGFyQ29kZSk7CiAgICBpZiAodHlwZW9mIHVuaWNvZGUgPT09ICJzdHJpbmciKSB7CiAgICAgIGlmICh1bmljb2RlLmxlbmd0aCA9PT0gMSkgewogICAgICAgIHVuaWNvZGUgPSB1bmljb2RlLmNvZGVQb2ludEF0KDApOwogICAgICB9IGVsc2UgewogICAgICAgIGlmICghTElHQVRVUkVfVE9fVU5JQ09ERSkgewogICAgICAgICAgTElHQVRVUkVfVE9fVU5JQ09ERSA9IG5ldyBNYXAoKTsKICAgICAgICAgIGZvciAobGV0IGkgPSAweGZiMDA7IGkgPD0gMHhmYjRmOyBpKyspIHsKICAgICAgICAgICAgY29uc3Qgbm9ybWFsaXplZCA9IFN0cmluZy5mcm9tQ2hhckNvZGUoaSkubm9ybWFsaXplKCJORktEIik7CiAgICAgICAgICAgIGlmIChub3JtYWxpemVkLmxlbmd0aCA+IDEpIHsKICAgICAgICAgICAgICBMSUdBVFVSRV9UT19VTklDT0RFLnNldChub3JtYWxpemVkLCBpKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB1bmljb2RlID0gTElHQVRVUkVfVE9fVU5JQ09ERS5nZXQodW5pY29kZSkgfHwgdW5pY29kZS5jb2RlUG9pbnRBdCgwKTsKICAgICAgfQogICAgfQogICAgaWYgKHVuaWNvZGUgJiYgIWlzSW5Qcml2YXRlQXJlYSh1bmljb2RlKSAmJiAhdXNlZEdseXBoSWRzLmhhcyhnbHlwaElkKSkgewogICAgICB0b1VuaWNvZGVFeHRyYU1hcC5zZXQodW5pY29kZSwgZ2x5cGhJZCk7CiAgICAgIHVzZWRHbHlwaElkcy5hZGQoZ2x5cGhJZCk7CiAgICB9CiAgICBuZXdNYXBbZm9udENoYXJDb2RlXSA9IGdseXBoSWQ7CiAgICB0b0ZvbnRDaGFyW29yaWdpbmFsQ2hhckNvZGVdID0gZm9udENoYXJDb2RlOwogIH0KICByZXR1cm4gewogICAgdG9Gb250Q2hhciwKICAgIGNoYXJDb2RlVG9HbHlwaElkOiBuZXdNYXAsCiAgICB0b1VuaWNvZGVFeHRyYU1hcCwKICAgIG5leHRBdmFpbGFibGVGb250Q2hhckNvZGUKICB9Owp9CmZ1bmN0aW9uIGdldFJhbmdlcyhnbHlwaHMsIHRvVW5pY29kZUV4dHJhTWFwLCBudW1HbHlwaHMpIHsKICBjb25zdCBjb2RlcyA9IFtdOwogIGZvciAoY29uc3QgY2hhckNvZGUgaW4gZ2x5cGhzKSB7CiAgICBpZiAoZ2x5cGhzW2NoYXJDb2RlXSA+PSBudW1HbHlwaHMpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICBjb2Rlcy5wdXNoKHsKICAgICAgZm9udENoYXJDb2RlOiBjaGFyQ29kZSB8IDAsCiAgICAgIGdseXBoSWQ6IGdseXBoc1tjaGFyQ29kZV0KICAgIH0pOwogIH0KICBpZiAodG9Vbmljb2RlRXh0cmFNYXApIHsKICAgIGZvciAoY29uc3QgW3VuaWNvZGUsIGdseXBoSWRdIG9mIHRvVW5pY29kZUV4dHJhTWFwKSB7CiAgICAgIGlmIChnbHlwaElkID49IG51bUdseXBocykgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvZGVzLnB1c2goewogICAgICAgIGZvbnRDaGFyQ29kZTogdW5pY29kZSwKICAgICAgICBnbHlwaElkCiAgICAgIH0pOwogICAgfQogIH0KICBpZiAoY29kZXMubGVuZ3RoID09PSAwKSB7CiAgICBjb2Rlcy5wdXNoKHsKICAgICAgZm9udENoYXJDb2RlOiAwLAogICAgICBnbHlwaElkOiAwCiAgICB9KTsKICB9CiAgY29kZXMuc29ydCgoYSwgYikgPT4gYS5mb250Q2hhckNvZGUgLSBiLmZvbnRDaGFyQ29kZSk7CiAgY29uc3QgcmFuZ2VzID0gW107CiAgY29uc3QgbGVuZ3RoID0gY29kZXMubGVuZ3RoOwogIGZvciAobGV0IG4gPSAwOyBuIDwgbGVuZ3RoOykgewogICAgY29uc3Qgc3RhcnQgPSBjb2Rlc1tuXS5mb250Q2hhckNvZGU7CiAgICBjb25zdCBjb2RlSW5kaWNlcyA9IFtjb2Rlc1tuXS5nbHlwaElkXTsKICAgICsrbjsKICAgIGxldCBlbmQgPSBzdGFydDsKICAgIHdoaWxlIChuIDwgbGVuZ3RoICYmIGVuZCArIDEgPT09IGNvZGVzW25dLmZvbnRDaGFyQ29kZSkgewogICAgICBjb2RlSW5kaWNlcy5wdXNoKGNvZGVzW25dLmdseXBoSWQpOwogICAgICArK2VuZDsKICAgICAgKytuOwogICAgICBpZiAoZW5kID09PSAweGZmZmYpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgcmFuZ2VzLnB1c2goW3N0YXJ0LCBlbmQsIGNvZGVJbmRpY2VzXSk7CiAgfQogIHJldHVybiByYW5nZXM7Cn0KZnVuY3Rpb24gY3JlYXRlQ21hcFRhYmxlKGdseXBocywgdG9Vbmljb2RlRXh0cmFNYXAsIG51bUdseXBocykgewogIGNvbnN0IHJhbmdlcyA9IGdldFJhbmdlcyhnbHlwaHMsIHRvVW5pY29kZUV4dHJhTWFwLCBudW1HbHlwaHMpOwogIGNvbnN0IG51bVRhYmxlcyA9IHJhbmdlcy5hdCgtMSlbMV0gPiAweGZmZmYgPyAyIDogMTsKICBsZXQgY21hcCA9ICJceDAwXHgwMCIgKyBzdHJpbmcxNihudW1UYWJsZXMpICsgIlx4MDBceDAzIiArICJceDAwXHgwMSIgKyBzdHJpbmczMig0ICsgbnVtVGFibGVzICogOCk7CiAgbGV0IGksIGlpLCBqLCBqajsKICBmb3IgKGkgPSByYW5nZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHsKICAgIGlmIChyYW5nZXNbaV1bMF0gPD0gMHhmZmZmKSB7CiAgICAgIGJyZWFrOwogICAgfQogIH0KICBjb25zdCBibXBMZW5ndGggPSBpICsgMTsKICBpZiAocmFuZ2VzW2ldWzBdIDwgMHhmZmZmICYmIHJhbmdlc1tpXVsxXSA9PT0gMHhmZmZmKSB7CiAgICByYW5nZXNbaV1bMV0gPSAweGZmZmU7CiAgfQogIGNvbnN0IHRyYWlsaW5nUmFuZ2VzQ291bnQgPSByYW5nZXNbaV1bMV0gPCAweGZmZmYgPyAxIDogMDsKICBjb25zdCBzZWdDb3VudCA9IGJtcExlbmd0aCArIHRyYWlsaW5nUmFuZ2VzQ291bnQ7CiAgY29uc3Qgc2VhcmNoUGFyYW1zID0gT3BlblR5cGVGaWxlQnVpbGRlci5nZXRTZWFyY2hQYXJhbXMoc2VnQ291bnQsIDIpOwogIGxldCBzdGFydENvdW50ID0gIiI7CiAgbGV0IGVuZENvdW50ID0gIiI7CiAgbGV0IGlkRGVsdGFzID0gIiI7CiAgbGV0IGlkUmFuZ2VPZmZzZXRzID0gIiI7CiAgbGV0IGdseXBoc0lkcyA9ICIiOwogIGxldCBiaWFzID0gMDsKICBsZXQgcmFuZ2UsIHN0YXJ0LCBlbmQsIGNvZGVzOwogIGZvciAoaSA9IDAsIGlpID0gYm1wTGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgcmFuZ2UgPSByYW5nZXNbaV07CiAgICBzdGFydCA9IHJhbmdlWzBdOwogICAgZW5kID0gcmFuZ2VbMV07CiAgICBzdGFydENvdW50ICs9IHN0cmluZzE2KHN0YXJ0KTsKICAgIGVuZENvdW50ICs9IHN0cmluZzE2KGVuZCk7CiAgICBjb2RlcyA9IHJhbmdlWzJdOwogICAgbGV0IGNvbnRpZ3VvdXMgPSB0cnVlOwogICAgZm9yIChqID0gMSwgamogPSBjb2Rlcy5sZW5ndGg7IGogPCBqajsgKytqKSB7CiAgICAgIGlmIChjb2Rlc1tqXSAhPT0gY29kZXNbaiAtIDFdICsgMSkgewogICAgICAgIGNvbnRpZ3VvdXMgPSBmYWxzZTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgaWYgKCFjb250aWd1b3VzKSB7CiAgICAgIGNvbnN0IG9mZnNldCA9IChzZWdDb3VudCAtIGkpICogMiArIGJpYXMgKiAyOwogICAgICBiaWFzICs9IGVuZCAtIHN0YXJ0ICsgMTsKICAgICAgaWREZWx0YXMgKz0gc3RyaW5nMTYoMCk7CiAgICAgIGlkUmFuZ2VPZmZzZXRzICs9IHN0cmluZzE2KG9mZnNldCk7CiAgICAgIGZvciAoaiA9IDAsIGpqID0gY29kZXMubGVuZ3RoOyBqIDwgamo7ICsraikgewogICAgICAgIGdseXBoc0lkcyArPSBzdHJpbmcxNihjb2Rlc1tqXSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IHN0YXJ0Q29kZSA9IGNvZGVzWzBdOwogICAgICBpZERlbHRhcyArPSBzdHJpbmcxNihzdGFydENvZGUgLSBzdGFydCAmIDB4ZmZmZik7CiAgICAgIGlkUmFuZ2VPZmZzZXRzICs9IHN0cmluZzE2KDApOwogICAgfQogIH0KICBpZiAodHJhaWxpbmdSYW5nZXNDb3VudCA+IDApIHsKICAgIGVuZENvdW50ICs9ICJceEZGXHhGRiI7CiAgICBzdGFydENvdW50ICs9ICJceEZGXHhGRiI7CiAgICBpZERlbHRhcyArPSAiXHgwMFx4MDEiOwogICAgaWRSYW5nZU9mZnNldHMgKz0gIlx4MDBceDAwIjsKICB9CiAgY29uc3QgZm9ybWF0MzE0ID0gIlx4MDBceDAwIiArIHN0cmluZzE2KDIgKiBzZWdDb3VudCkgKyBzdHJpbmcxNihzZWFyY2hQYXJhbXMucmFuZ2UpICsgc3RyaW5nMTYoc2VhcmNoUGFyYW1zLmVudHJ5KSArIHN0cmluZzE2KHNlYXJjaFBhcmFtcy5yYW5nZVNoaWZ0KSArIGVuZENvdW50ICsgIlx4MDBceDAwIiArIHN0YXJ0Q291bnQgKyBpZERlbHRhcyArIGlkUmFuZ2VPZmZzZXRzICsgZ2x5cGhzSWRzOwogIGxldCBmb3JtYXQzMTAxMiA9ICIiOwogIGxldCBoZWFkZXIzMTAxMiA9ICIiOwogIGlmIChudW1UYWJsZXMgPiAxKSB7CiAgICBjbWFwICs9ICJceDAwXHgwMyIgKyAiXHgwMFx4MEEiICsgc3RyaW5nMzIoNCArIG51bVRhYmxlcyAqIDggKyA0ICsgZm9ybWF0MzE0Lmxlbmd0aCk7CiAgICBmb3JtYXQzMTAxMiA9ICIiOwogICAgZm9yIChpID0gMCwgaWkgPSByYW5nZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICByYW5nZSA9IHJhbmdlc1tpXTsKICAgICAgc3RhcnQgPSByYW5nZVswXTsKICAgICAgY29kZXMgPSByYW5nZVsyXTsKICAgICAgbGV0IGNvZGUgPSBjb2Rlc1swXTsKICAgICAgZm9yIChqID0gMSwgamogPSBjb2Rlcy5sZW5ndGg7IGogPCBqajsgKytqKSB7CiAgICAgICAgaWYgKGNvZGVzW2pdICE9PSBjb2Rlc1tqIC0gMV0gKyAxKSB7CiAgICAgICAgICBlbmQgPSByYW5nZVswXSArIGogLSAxOwogICAgICAgICAgZm9ybWF0MzEwMTIgKz0gc3RyaW5nMzIoc3RhcnQpICsgc3RyaW5nMzIoZW5kKSArIHN0cmluZzMyKGNvZGUpOwogICAgICAgICAgc3RhcnQgPSBlbmQgKyAxOwogICAgICAgICAgY29kZSA9IGNvZGVzW2pdOwogICAgICAgIH0KICAgICAgfQogICAgICBmb3JtYXQzMTAxMiArPSBzdHJpbmczMihzdGFydCkgKyBzdHJpbmczMihyYW5nZVsxXSkgKyBzdHJpbmczMihjb2RlKTsKICAgIH0KICAgIGhlYWRlcjMxMDEyID0gIlx4MDBceDBDIiArICJceDAwXHgwMCIgKyBzdHJpbmczMihmb3JtYXQzMTAxMi5sZW5ndGggKyAxNikgKyAiXHgwMFx4MDBceDAwXHgwMCIgKyBzdHJpbmczMihmb3JtYXQzMTAxMi5sZW5ndGggLyAxMik7CiAgfQogIHJldHVybiBjbWFwICsgIlx4MDBceDA0IiArIHN0cmluZzE2KGZvcm1hdDMxNC5sZW5ndGggKyA0KSArIGZvcm1hdDMxNCArIGhlYWRlcjMxMDEyICsgZm9ybWF0MzEwMTI7Cn0KZnVuY3Rpb24gdmFsaWRhdGVPUzJUYWJsZShvczIsIGZpbGUpIHsKICBmaWxlLnBvcyA9IChmaWxlLnN0YXJ0IHx8IDApICsgb3MyLm9mZnNldDsKICBjb25zdCB2ZXJzaW9uID0gZmlsZS5nZXRVaW50MTYoKTsKICBmaWxlLnNraXAoNjApOwogIGNvbnN0IHNlbGVjdGlvbiA9IGZpbGUuZ2V0VWludDE2KCk7CiAgaWYgKHZlcnNpb24gPCA0ICYmIHNlbGVjdGlvbiAmIDB4MDMwMCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBjb25zdCBmaXJzdENoYXIgPSBmaWxlLmdldFVpbnQxNigpOwogIGNvbnN0IGxhc3RDaGFyID0gZmlsZS5nZXRVaW50MTYoKTsKICBpZiAoZmlyc3RDaGFyID4gbGFzdENoYXIpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgZmlsZS5za2lwKDYpOwogIGNvbnN0IHVzV2luQXNjZW50ID0gZmlsZS5nZXRVaW50MTYoKTsKICBpZiAodXNXaW5Bc2NlbnQgPT09IDApIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgb3MyLmRhdGFbOF0gPSBvczIuZGF0YVs5XSA9IDA7CiAgcmV0dXJuIHRydWU7Cn0KZnVuY3Rpb24gY3JlYXRlT1MyVGFibGUocHJvcGVydGllcywgY2hhcnN0cmluZ3MsIG92ZXJyaWRlKSB7CiAgb3ZlcnJpZGUgfHw9IHsKICAgIHVuaXRzUGVyRW06IDAsCiAgICB5TWF4OiAwLAogICAgeU1pbjogMCwKICAgIGFzY2VudDogMCwKICAgIGRlc2NlbnQ6IDAKICB9OwogIGxldCB1bFVuaWNvZGVSYW5nZTEgPSAwOwogIGxldCB1bFVuaWNvZGVSYW5nZTIgPSAwOwogIGxldCB1bFVuaWNvZGVSYW5nZTMgPSAwOwogIGxldCB1bFVuaWNvZGVSYW5nZTQgPSAwOwogIGxldCBmaXJzdENoYXJJbmRleCA9IG51bGw7CiAgbGV0IGxhc3RDaGFySW5kZXggPSAwOwogIGxldCBwb3NpdGlvbiA9IC0xOwogIGlmIChjaGFyc3RyaW5ncykgewogICAgZm9yIChsZXQgY29kZSBpbiBjaGFyc3RyaW5ncykgewogICAgICBjb2RlIHw9IDA7CiAgICAgIGlmIChmaXJzdENoYXJJbmRleCA+IGNvZGUgfHwgIWZpcnN0Q2hhckluZGV4KSB7CiAgICAgICAgZmlyc3RDaGFySW5kZXggPSBjb2RlOwogICAgICB9CiAgICAgIGlmIChsYXN0Q2hhckluZGV4IDwgY29kZSkgewogICAgICAgIGxhc3RDaGFySW5kZXggPSBjb2RlOwogICAgICB9CiAgICAgIHBvc2l0aW9uID0gZ2V0VW5pY29kZVJhbmdlRm9yKGNvZGUsIHBvc2l0aW9uKTsKICAgICAgaWYgKHBvc2l0aW9uIDwgMzIpIHsKICAgICAgICB1bFVuaWNvZGVSYW5nZTEgfD0gMSA8PCBwb3NpdGlvbjsKICAgICAgfSBlbHNlIGlmIChwb3NpdGlvbiA8IDY0KSB7CiAgICAgICAgdWxVbmljb2RlUmFuZ2UyIHw9IDEgPDwgcG9zaXRpb24gLSAzMjsKICAgICAgfSBlbHNlIGlmIChwb3NpdGlvbiA8IDk2KSB7CiAgICAgICAgdWxVbmljb2RlUmFuZ2UzIHw9IDEgPDwgcG9zaXRpb24gLSA2NDsKICAgICAgfSBlbHNlIGlmIChwb3NpdGlvbiA8IDEyMykgewogICAgICAgIHVsVW5pY29kZVJhbmdlNCB8PSAxIDw8IHBvc2l0aW9uIC0gOTY7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJVbmljb2RlIHJhbmdlcyBCaXRzID4gMTIzIGFyZSByZXNlcnZlZCBmb3IgaW50ZXJuYWwgdXNhZ2UiKTsKICAgICAgfQogICAgfQogICAgaWYgKGxhc3RDaGFySW5kZXggPiAweGZmZmYpIHsKICAgICAgbGFzdENoYXJJbmRleCA9IDB4ZmZmZjsKICAgIH0KICB9IGVsc2UgewogICAgZmlyc3RDaGFySW5kZXggPSAwOwogICAgbGFzdENoYXJJbmRleCA9IDI1NTsKICB9CiAgY29uc3QgYmJveCA9IHByb3BlcnRpZXMuYmJveCB8fCBbMCwgMCwgMCwgMF07CiAgY29uc3QgdW5pdHNQZXJFbSA9IG92ZXJyaWRlLnVuaXRzUGVyRW0gfHwgKHByb3BlcnRpZXMuZm9udE1hdHJpeCA/IDEgLyBNYXRoLm1heCguLi5wcm9wZXJ0aWVzLmZvbnRNYXRyaXguc2xpY2UoMCwgNCkubWFwKE1hdGguYWJzKSkgOiAxMDAwKTsKICBjb25zdCBzY2FsZSA9IHByb3BlcnRpZXMuYXNjZW50U2NhbGVkID8gMS4wIDogdW5pdHNQZXJFbSAvIFBERl9HTFlQSF9TUEFDRV9VTklUUzsKICBjb25zdCB0eXBvQXNjZW50ID0gb3ZlcnJpZGUuYXNjZW50IHx8IE1hdGgucm91bmQoc2NhbGUgKiAocHJvcGVydGllcy5hc2NlbnQgfHwgYmJveFszXSkpOwogIGxldCB0eXBvRGVzY2VudCA9IG92ZXJyaWRlLmRlc2NlbnQgfHwgTWF0aC5yb3VuZChzY2FsZSAqIChwcm9wZXJ0aWVzLmRlc2NlbnQgfHwgYmJveFsxXSkpOwogIGlmICh0eXBvRGVzY2VudCA+IDAgJiYgcHJvcGVydGllcy5kZXNjZW50ID4gMCAmJiBiYm94WzFdIDwgMCkgewogICAgdHlwb0Rlc2NlbnQgPSAtdHlwb0Rlc2NlbnQ7CiAgfQogIGNvbnN0IHdpbkFzY2VudCA9IG92ZXJyaWRlLnlNYXggfHwgdHlwb0FzY2VudDsKICBjb25zdCB3aW5EZXNjZW50ID0gLW92ZXJyaWRlLnlNaW4gfHwgLXR5cG9EZXNjZW50OwogIHJldHVybiAiXHgwMFx4MDMiICsgIlx4MDJceDI0IiArICJceDAxXHhGNCIgKyAiXHgwMFx4MDUiICsgIlx4MDBceDAwIiArICJceDAyXHg4QSIgKyAiXHgwMlx4QkIiICsgIlx4MDBceDAwIiArICJceDAwXHg4QyIgKyAiXHgwMlx4OEEiICsgIlx4MDJceEJCIiArICJceDAwXHgwMCIgKyAiXHgwMVx4REYiICsgIlx4MDBceDMxIiArICJceDAxXHgwMiIgKyAiXHgwMFx4MDAiICsgIlx4MDBceDAwXHgwNiIgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKHByb3BlcnRpZXMuZml4ZWRQaXRjaCA/IDB4MDkgOiAweDAwKSArICJceDAwXHgwMFx4MDBceDAwXHgwMFx4MDAiICsgc3RyaW5nMzIodWxVbmljb2RlUmFuZ2UxKSArIHN0cmluZzMyKHVsVW5pY29kZVJhbmdlMikgKyBzdHJpbmczMih1bFVuaWNvZGVSYW5nZTMpICsgc3RyaW5nMzIodWxVbmljb2RlUmFuZ2U0KSArICJceDJBXHgzMlx4MzFceDJBIiArIHN0cmluZzE2KHByb3BlcnRpZXMuaXRhbGljQW5nbGUgPyAxIDogMCkgKyBzdHJpbmcxNihmaXJzdENoYXJJbmRleCB8fCBwcm9wZXJ0aWVzLmZpcnN0Q2hhcikgKyBzdHJpbmcxNihsYXN0Q2hhckluZGV4IHx8IHByb3BlcnRpZXMubGFzdENoYXIpICsgc3RyaW5nMTYodHlwb0FzY2VudCkgKyBzdHJpbmcxNih0eXBvRGVzY2VudCkgKyAiXHgwMFx4NjQiICsgc3RyaW5nMTYod2luQXNjZW50KSArIHN0cmluZzE2KHdpbkRlc2NlbnQpICsgIlx4MDBceDAwXHgwMFx4MDAiICsgIlx4MDBceDAwXHgwMFx4MDAiICsgc3RyaW5nMTYocHJvcGVydGllcy54SGVpZ2h0KSArIHN0cmluZzE2KHByb3BlcnRpZXMuY2FwSGVpZ2h0KSArIHN0cmluZzE2KDApICsgc3RyaW5nMTYoZmlyc3RDaGFySW5kZXggfHwgcHJvcGVydGllcy5maXJzdENoYXIpICsgIlx4MDBceDAzIjsKfQpmdW5jdGlvbiBjcmVhdGVQb3N0VGFibGUocHJvcGVydGllcykgewogIGNvbnN0IGFuZ2xlID0gTWF0aC5mbG9vcihwcm9wZXJ0aWVzLml0YWxpY0FuZ2xlICogMiAqKiAxNik7CiAgcmV0dXJuICJceDAwXHgwM1x4MDBceDAwIiArIHN0cmluZzMyKGFuZ2xlKSArICJceDAwXHgwMCIgKyAiXHgwMFx4MDAiICsgc3RyaW5nMzIocHJvcGVydGllcy5maXhlZFBpdGNoID8gMSA6IDApICsgIlx4MDBceDAwXHgwMFx4MDAiICsgIlx4MDBceDAwXHgwMFx4MDAiICsgIlx4MDBceDAwXHgwMFx4MDAiICsgIlx4MDBceDAwXHgwMFx4MDAiOwp9CmZ1bmN0aW9uIGNyZWF0ZVBvc3RzY3JpcHROYW1lKG5hbWUpIHsKICByZXR1cm4gbmFtZS5yZXBsYWNlQWxsKC9bXlx4MjEtXHg3RV18W1tcXSgpe308Pi8lXS9nLCAiIikuc2xpY2UoMCwgNjMpOwp9CmZ1bmN0aW9uIGNyZWF0ZU5hbWVUYWJsZShuYW1lLCBwcm90bykgewogIGlmICghcHJvdG8pIHsKICAgIHByb3RvID0gW1tdLCBbXV07CiAgfQogIGNvbnN0IHN0cmluZ3MgPSBbcHJvdG9bMF1bMF0gfHwgIk9yaWdpbmFsIGxpY2VuY2UiLCBwcm90b1swXVsxXSB8fCBuYW1lLCBwcm90b1swXVsyXSB8fCAiVW5rbm93biIsIHByb3RvWzBdWzNdIHx8ICJ1bmlxdWVJRCIsIHByb3RvWzBdWzRdIHx8IG5hbWUsIHByb3RvWzBdWzVdIHx8ICJWZXJzaW9uIDAuMTEiLCBwcm90b1swXVs2XSB8fCBjcmVhdGVQb3N0c2NyaXB0TmFtZShuYW1lKSwgcHJvdG9bMF1bN10gfHwgIlVua25vd24iLCBwcm90b1swXVs4XSB8fCAiVW5rbm93biIsIHByb3RvWzBdWzldIHx8ICJVbmtub3duIl07CiAgY29uc3Qgc3RyaW5nc1VuaWNvZGUgPSBbXTsKICBsZXQgaSwgaWksIGosIGpqLCBzdHI7CiAgZm9yIChpID0gMCwgaWkgPSBzdHJpbmdzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIHN0ciA9IHByb3RvWzFdW2ldIHx8IHN0cmluZ3NbaV07CiAgICBjb25zdCBzdHJCdWZVbmljb2RlID0gW107CiAgICBmb3IgKGogPSAwLCBqaiA9IHN0ci5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgIHN0ckJ1ZlVuaWNvZGUucHVzaChzdHJpbmcxNihzdHIuY2hhckNvZGVBdChqKSkpOwogICAgfQogICAgc3RyaW5nc1VuaWNvZGUucHVzaChzdHJCdWZVbmljb2RlLmpvaW4oIiIpKTsKICB9CiAgY29uc3QgbmFtZXMgPSBbc3RyaW5ncywgc3RyaW5nc1VuaWNvZGVdOwogIGNvbnN0IHBsYXRmb3JtcyA9IFsiXHgwMFx4MDEiLCAiXHgwMFx4MDMiXTsKICBjb25zdCBlbmNvZGluZ3MgPSBbIlx4MDBceDAwIiwgIlx4MDBceDAxIl07CiAgY29uc3QgbGFuZ3VhZ2VzID0gWyJceDAwXHgwMCIsICJceDA0XHgwOSJdOwogIGNvbnN0IG5hbWVzUmVjb3JkQ291bnQgPSBzdHJpbmdzLmxlbmd0aCAqIHBsYXRmb3Jtcy5sZW5ndGg7CiAgbGV0IG5hbWVUYWJsZSA9ICJceDAwXHgwMCIgKyBzdHJpbmcxNihuYW1lc1JlY29yZENvdW50KSArIHN0cmluZzE2KG5hbWVzUmVjb3JkQ291bnQgKiAxMiArIDYpOwogIGxldCBzdHJPZmZzZXQgPSAwOwogIGZvciAoaSA9IDAsIGlpID0gcGxhdGZvcm1zLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IHN0cnMgPSBuYW1lc1tpXTsKICAgIGZvciAoaiA9IDAsIGpqID0gc3Rycy5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgIHN0ciA9IHN0cnNbal07CiAgICAgIGNvbnN0IG5hbWVSZWNvcmQgPSBwbGF0Zm9ybXNbaV0gKyBlbmNvZGluZ3NbaV0gKyBsYW5ndWFnZXNbaV0gKyBzdHJpbmcxNihqKSArIHN0cmluZzE2KHN0ci5sZW5ndGgpICsgc3RyaW5nMTYoc3RyT2Zmc2V0KTsKICAgICAgbmFtZVRhYmxlICs9IG5hbWVSZWNvcmQ7CiAgICAgIHN0ck9mZnNldCArPSBzdHIubGVuZ3RoOwogICAgfQogIH0KICBuYW1lVGFibGUgKz0gc3RyaW5ncy5qb2luKCIiKSArIHN0cmluZ3NVbmljb2RlLmpvaW4oIiIpOwogIHJldHVybiBuYW1lVGFibGU7Cn0KY2xhc3MgRm9udCB7CiAgY29uc3RydWN0b3IobmFtZSwgZmlsZSwgcHJvcGVydGllcywgZXZhbHVhdG9yT3B0aW9ucykgewogICAgdGhpcy5uYW1lID0gbmFtZTsKICAgIHRoaXMucHNOYW1lID0gbnVsbDsKICAgIHRoaXMubWltZXR5cGUgPSBudWxsOwogICAgdGhpcy5kaXNhYmxlRm9udEZhY2UgPSBldmFsdWF0b3JPcHRpb25zLmRpc2FibGVGb250RmFjZTsKICAgIHRoaXMuZm9udEV4dHJhUHJvcGVydGllcyA9IGV2YWx1YXRvck9wdGlvbnMuZm9udEV4dHJhUHJvcGVydGllczsKICAgIHRoaXMubG9hZGVkTmFtZSA9IHByb3BlcnRpZXMubG9hZGVkTmFtZTsKICAgIHRoaXMuaXNUeXBlM0ZvbnQgPSBwcm9wZXJ0aWVzLmlzVHlwZTNGb250OwogICAgdGhpcy5taXNzaW5nRmlsZSA9IGZhbHNlOwogICAgdGhpcy5jc3NGb250SW5mbyA9IHByb3BlcnRpZXMuY3NzRm9udEluZm87CiAgICB0aGlzLl9jaGFyc0NhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHRoaXMuX2dseXBoQ2FjaGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgbGV0IGlzU2VyaWZGb250ID0gISEocHJvcGVydGllcy5mbGFncyAmIEZvbnRGbGFncy5TZXJpZik7CiAgICBpZiAoIWlzU2VyaWZGb250ICYmICFwcm9wZXJ0aWVzLmlzU2ltdWxhdGVkRmxhZ3MpIHsKICAgICAgY29uc3Qgc3RkRm9udE1hcCA9IGdldFN0ZEZvbnRNYXAoKSwKICAgICAgICBub25TdGRGb250TWFwID0gZ2V0Tm9uU3RkRm9udE1hcCgpLAogICAgICAgIHNlcmlmRm9udHMgPSBnZXRTZXJpZkZvbnRzKCk7CiAgICAgIGZvciAoY29uc3QgbmFtZVBhcnQgb2YgbmFtZS5zcGxpdCgiKyIpKSB7CiAgICAgICAgbGV0IGZvbnROYW1lID0gbmFtZVBhcnQucmVwbGFjZUFsbCgvWyxfXS9nLCAiLSIpOwogICAgICAgIGZvbnROYW1lID0gc3RkRm9udE1hcFtmb250TmFtZV0gfHwgbm9uU3RkRm9udE1hcFtmb250TmFtZV0gfHwgZm9udE5hbWU7CiAgICAgICAgZm9udE5hbWUgPSBmb250TmFtZS5zcGxpdCgiLSIsIDEpWzBdOwogICAgICAgIGlmIChzZXJpZkZvbnRzW2ZvbnROYW1lXSkgewogICAgICAgICAgaXNTZXJpZkZvbnQgPSB0cnVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICB0aGlzLmlzU2VyaWZGb250ID0gaXNTZXJpZkZvbnQ7CiAgICB0aGlzLmlzU3ltYm9saWNGb250ID0gISEocHJvcGVydGllcy5mbGFncyAmIEZvbnRGbGFncy5TeW1ib2xpYyk7CiAgICB0aGlzLmlzTW9ub3NwYWNlID0gISEocHJvcGVydGllcy5mbGFncyAmIEZvbnRGbGFncy5GaXhlZFBpdGNoKTsKICAgIGxldCB7CiAgICAgIHR5cGUsCiAgICAgIHN1YnR5cGUKICAgIH0gPSBwcm9wZXJ0aWVzOwogICAgdGhpcy50eXBlID0gdHlwZTsKICAgIHRoaXMuc3VidHlwZSA9IHN1YnR5cGU7CiAgICB0aGlzLnN5c3RlbUZvbnRJbmZvID0gcHJvcGVydGllcy5zeXN0ZW1Gb250SW5mbzsKICAgIGNvbnN0IG1hdGNoZXMgPSBuYW1lLm1hdGNoKC9eSW52YWxpZFBERmpzRm9udF8oLiopX1xkKyQvKTsKICAgIHRoaXMuaXNJbnZhbGlkUERGanNGb250ID0gISFtYXRjaGVzOwogICAgaWYgKHRoaXMuaXNJbnZhbGlkUERGanNGb250KSB7CiAgICAgIHRoaXMuZmFsbGJhY2tOYW1lID0gbWF0Y2hlc1sxXTsKICAgIH0gZWxzZSBpZiAodGhpcy5pc01vbm9zcGFjZSkgewogICAgICB0aGlzLmZhbGxiYWNrTmFtZSA9ICJtb25vc3BhY2UiOwogICAgfSBlbHNlIGlmICh0aGlzLmlzU2VyaWZGb250KSB7CiAgICAgIHRoaXMuZmFsbGJhY2tOYW1lID0gInNlcmlmIjsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuZmFsbGJhY2tOYW1lID0gInNhbnMtc2VyaWYiOwogICAgfQogICAgaWYgKHRoaXMuc3lzdGVtRm9udEluZm8/Lmd1ZXNzRmFsbGJhY2spIHsKICAgICAgdGhpcy5zeXN0ZW1Gb250SW5mby5ndWVzc0ZhbGxiYWNrID0gZmFsc2U7CiAgICAgIHRoaXMuc3lzdGVtRm9udEluZm8uY3NzICs9IGAsJHt0aGlzLmZhbGxiYWNrTmFtZX1gOwogICAgfQogICAgdGhpcy5kaWZmZXJlbmNlcyA9IHByb3BlcnRpZXMuZGlmZmVyZW5jZXM7CiAgICB0aGlzLndpZHRocyA9IHByb3BlcnRpZXMud2lkdGhzOwogICAgdGhpcy5kZWZhdWx0V2lkdGggPSBwcm9wZXJ0aWVzLmRlZmF1bHRXaWR0aDsKICAgIHRoaXMuY29tcG9zaXRlID0gcHJvcGVydGllcy5jb21wb3NpdGU7CiAgICB0aGlzLmNNYXAgPSBwcm9wZXJ0aWVzLmNNYXA7CiAgICB0aGlzLmNhcEhlaWdodCA9IHByb3BlcnRpZXMuY2FwSGVpZ2h0IC8gUERGX0dMWVBIX1NQQUNFX1VOSVRTOwogICAgdGhpcy5hc2NlbnQgPSBwcm9wZXJ0aWVzLmFzY2VudCAvIFBERl9HTFlQSF9TUEFDRV9VTklUUzsKICAgIHRoaXMuZGVzY2VudCA9IHByb3BlcnRpZXMuZGVzY2VudCAvIFBERl9HTFlQSF9TUEFDRV9VTklUUzsKICAgIHRoaXMubGluZUhlaWdodCA9IHRoaXMuYXNjZW50IC0gdGhpcy5kZXNjZW50OwogICAgdGhpcy5mb250TWF0cml4ID0gcHJvcGVydGllcy5mb250TWF0cml4OwogICAgdGhpcy5iYm94ID0gcHJvcGVydGllcy5iYm94OwogICAgdGhpcy5kZWZhdWx0RW5jb2RpbmcgPSBwcm9wZXJ0aWVzLmRlZmF1bHRFbmNvZGluZzsKICAgIHRoaXMudG9Vbmljb2RlID0gcHJvcGVydGllcy50b1VuaWNvZGU7CiAgICB0aGlzLnRvRm9udENoYXIgPSBbXTsKICAgIGlmIChwcm9wZXJ0aWVzLnR5cGUgPT09ICJUeXBlMyIpIHsKICAgICAgZm9yIChsZXQgY2hhckNvZGUgPSAwOyBjaGFyQ29kZSA8IDI1NjsgY2hhckNvZGUrKykgewogICAgICAgIHRoaXMudG9Gb250Q2hhcltjaGFyQ29kZV0gPSB0aGlzLmRpZmZlcmVuY2VzW2NoYXJDb2RlXSB8fCBwcm9wZXJ0aWVzLmRlZmF1bHRFbmNvZGluZ1tjaGFyQ29kZV07CiAgICAgIH0KICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5jaWRFbmNvZGluZyA9IHByb3BlcnRpZXMuY2lkRW5jb2RpbmcgfHwgIiI7CiAgICB0aGlzLnZlcnRpY2FsID0gISFwcm9wZXJ0aWVzLnZlcnRpY2FsOwogICAgaWYgKHRoaXMudmVydGljYWwpIHsKICAgICAgdGhpcy52bWV0cmljcyA9IHByb3BlcnRpZXMudm1ldHJpY3M7CiAgICAgIHRoaXMuZGVmYXVsdFZNZXRyaWNzID0gcHJvcGVydGllcy5kZWZhdWx0Vk1ldHJpY3M7CiAgICB9CiAgICBpZiAoIWZpbGUgfHwgZmlsZS5pc0VtcHR5KSB7CiAgICAgIGlmIChmaWxlKSB7CiAgICAgICAgd2FybignRm9udCBmaWxlIGlzIGVtcHR5IGluICInICsgbmFtZSArICciICgnICsgdGhpcy5sb2FkZWROYW1lICsgIikiKTsKICAgICAgfQogICAgICB0aGlzLmZhbGxiYWNrVG9TeXN0ZW1Gb250KHByb3BlcnRpZXMpOwogICAgICByZXR1cm47CiAgICB9CiAgICBbdHlwZSwgc3VidHlwZV0gPSBnZXRGb250RmlsZVR5cGUoZmlsZSwgcHJvcGVydGllcyk7CiAgICBpZiAodHlwZSAhPT0gdGhpcy50eXBlIHx8IHN1YnR5cGUgIT09IHRoaXMuc3VidHlwZSkgewogICAgICBpbmZvKCJJbmNvbnNpc3RlbnQgZm9udCBmaWxlIFR5cGUvU3ViVHlwZSwgZXhwZWN0ZWQ6ICIgKyBgJHt0aGlzLnR5cGV9LyR7dGhpcy5zdWJ0eXBlfSBidXQgZm91bmQ6ICR7dHlwZX0vJHtzdWJ0eXBlfS5gKTsKICAgIH0KICAgIGxldCBkYXRhOwogICAgdHJ5IHsKICAgICAgc3dpdGNoICh0eXBlKSB7CiAgICAgICAgY2FzZSAiTU1UeXBlMSI6CiAgICAgICAgICBpbmZvKCJNTVR5cGUxIGZvbnQgKCIgKyBuYW1lICsgIiksIGZhbGxpbmcgYmFjayB0byBUeXBlMS4iKTsKICAgICAgICBjYXNlICJUeXBlMSI6CiAgICAgICAgY2FzZSAiQ0lERm9udFR5cGUwIjoKICAgICAgICAgIHRoaXMubWltZXR5cGUgPSAiZm9udC9vcGVudHlwZSI7CiAgICAgICAgICBjb25zdCBjZmYgPSBzdWJ0eXBlID09PSAiVHlwZTFDIiB8fCBzdWJ0eXBlID09PSAiQ0lERm9udFR5cGUwQyIgPyBuZXcgQ0ZGRm9udChmaWxlLCBwcm9wZXJ0aWVzKSA6IG5ldyBUeXBlMUZvbnQobmFtZSwgZmlsZSwgcHJvcGVydGllcyk7CiAgICAgICAgICBhZGp1c3RXaWR0aHMocHJvcGVydGllcyk7CiAgICAgICAgICBkYXRhID0gdGhpcy5jb252ZXJ0KG5hbWUsIGNmZiwgcHJvcGVydGllcyk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJPcGVuVHlwZSI6CiAgICAgICAgY2FzZSAiVHJ1ZVR5cGUiOgogICAgICAgIGNhc2UgIkNJREZvbnRUeXBlMiI6CiAgICAgICAgICB0aGlzLm1pbWV0eXBlID0gImZvbnQvb3BlbnR5cGUiOwogICAgICAgICAgZGF0YSA9IHRoaXMuY2hlY2tBbmRSZXBhaXIobmFtZSwgZmlsZSwgcHJvcGVydGllcyk7CiAgICAgICAgICBhZGp1c3RXaWR0aHMocHJvcGVydGllcyk7CiAgICAgICAgICBpZiAodGhpcy5pc09wZW5UeXBlKSB7CiAgICAgICAgICAgIHR5cGUgPSAiT3BlblR5cGUiOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgRm9udCAke3R5cGV9IGlzIG5vdCBzdXBwb3J0ZWRgKTsKICAgICAgfQogICAgfSBjYXRjaCAoZSkgewogICAgICB3YXJuKGUpOwogICAgICB0aGlzLmZhbGxiYWNrVG9TeXN0ZW1Gb250KHByb3BlcnRpZXMpOwogICAgICByZXR1cm47CiAgICB9CiAgICBhbWVuZEZhbGxiYWNrVG9Vbmljb2RlKHByb3BlcnRpZXMpOwogICAgdGhpcy5kYXRhID0gZGF0YTsKICAgIHRoaXMudHlwZSA9IHR5cGU7CiAgICB0aGlzLnN1YnR5cGUgPSBzdWJ0eXBlOwogICAgdGhpcy5mb250TWF0cml4ID0gcHJvcGVydGllcy5mb250TWF0cml4OwogICAgdGhpcy53aWR0aHMgPSBwcm9wZXJ0aWVzLndpZHRoczsKICAgIHRoaXMuZGVmYXVsdFdpZHRoID0gcHJvcGVydGllcy5kZWZhdWx0V2lkdGg7CiAgICB0aGlzLnRvVW5pY29kZSA9IHByb3BlcnRpZXMudG9Vbmljb2RlOwogICAgdGhpcy5zZWFjTWFwID0gcHJvcGVydGllcy5zZWFjTWFwOwogIH0KICBnZXQgcmVuZGVyZXIoKSB7CiAgICBjb25zdCByZW5kZXJlciA9IEZvbnRSZW5kZXJlckZhY3RvcnkuY3JlYXRlKHRoaXMsIFNFQUNfQU5BTFlTSVNfRU5BQkxFRCk7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJyZW5kZXJlciIsIHJlbmRlcmVyKTsKICB9CiAgZXhwb3J0RGF0YSgpIHsKICAgIGNvbnN0IGRhdGEgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgZm9yIChjb25zdCBwcm9wIG9mIEVYUE9SVF9EQVRBX1BST1BFUlRJRVMpIHsKICAgICAgY29uc3QgdmFsdWUgPSB0aGlzW3Byb3BdOwogICAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGRhdGFbcHJvcF0gPSB2YWx1ZTsKICAgICAgfQogICAgfQogICAgaWYgKCF0aGlzLmZvbnRFeHRyYVByb3BlcnRpZXMpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBkYXRhCiAgICAgIH07CiAgICB9CiAgICBjb25zdCBleHRyYSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBmb3IgKGNvbnN0IHByb3Agb2YgRVhQT1JUX0RBVEFfRVhUUkFfUFJPUEVSVElFUykgewogICAgICBjb25zdCB2YWx1ZSA9IHRoaXNbcHJvcF07CiAgICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgZXh0cmFbcHJvcF0gPSB2YWx1ZTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHsKICAgICAgZGF0YSwKICAgICAgZXh0cmEKICAgIH07CiAgfQogIGZhbGxiYWNrVG9TeXN0ZW1Gb250KHByb3BlcnRpZXMpIHsKICAgIHRoaXMubWlzc2luZ0ZpbGUgPSB0cnVlOwogICAgY29uc3QgewogICAgICBuYW1lLAogICAgICB0eXBlCiAgICB9ID0gdGhpczsKICAgIGxldCBmb250TmFtZSA9IG5vcm1hbGl6ZUZvbnROYW1lKG5hbWUpOwogICAgY29uc3Qgc3RkRm9udE1hcCA9IGdldFN0ZEZvbnRNYXAoKSwKICAgICAgbm9uU3RkRm9udE1hcCA9IGdldE5vblN0ZEZvbnRNYXAoKTsKICAgIGNvbnN0IGlzU3RhbmRhcmRGb250ID0gISFzdGRGb250TWFwW2ZvbnROYW1lXTsKICAgIGNvbnN0IGlzTWFwcGVkVG9TdGFuZGFyZEZvbnQgPSAhIShub25TdGRGb250TWFwW2ZvbnROYW1lXSAmJiBzdGRGb250TWFwW25vblN0ZEZvbnRNYXBbZm9udE5hbWVdXSk7CiAgICBmb250TmFtZSA9IHN0ZEZvbnRNYXBbZm9udE5hbWVdIHx8IG5vblN0ZEZvbnRNYXBbZm9udE5hbWVdIHx8IGZvbnROYW1lOwogICAgY29uc3QgZm9udEJhc2ljTWV0cmljc01hcCA9IGdldEZvbnRCYXNpY01ldHJpY3MoKTsKICAgIGNvbnN0IG1ldHJpY3MgPSBmb250QmFzaWNNZXRyaWNzTWFwW2ZvbnROYW1lXTsKICAgIGlmIChtZXRyaWNzKSB7CiAgICAgIGlmIChpc05hTih0aGlzLmFzY2VudCkpIHsKICAgICAgICB0aGlzLmFzY2VudCA9IG1ldHJpY3MuYXNjZW50IC8gUERGX0dMWVBIX1NQQUNFX1VOSVRTOwogICAgICB9CiAgICAgIGlmIChpc05hTih0aGlzLmRlc2NlbnQpKSB7CiAgICAgICAgdGhpcy5kZXNjZW50ID0gbWV0cmljcy5kZXNjZW50IC8gUERGX0dMWVBIX1NQQUNFX1VOSVRTOwogICAgICB9CiAgICAgIGlmIChpc05hTih0aGlzLmNhcEhlaWdodCkpIHsKICAgICAgICB0aGlzLmNhcEhlaWdodCA9IG1ldHJpY3MuY2FwSGVpZ2h0IC8gUERGX0dMWVBIX1NQQUNFX1VOSVRTOwogICAgICB9CiAgICB9CiAgICB0aGlzLmJvbGQgPSAvYm9sZC9naS50ZXN0KGZvbnROYW1lKTsKICAgIHRoaXMuaXRhbGljID0gL29ibGlxdWV8aXRhbGljL2dpLnRlc3QoZm9udE5hbWUpOwogICAgdGhpcy5ibGFjayA9IC9CbGFjay9nLnRlc3QobmFtZSk7CiAgICBjb25zdCBpc05hcnJvdyA9IC9OYXJyb3cvZy50ZXN0KG5hbWUpOwogICAgdGhpcy5yZW1lYXN1cmUgPSAoIWlzU3RhbmRhcmRGb250IHx8IGlzTmFycm93KSAmJiBPYmplY3Qua2V5cyh0aGlzLndpZHRocykubGVuZ3RoID4gMDsKICAgIGlmICgoaXNTdGFuZGFyZEZvbnQgfHwgaXNNYXBwZWRUb1N0YW5kYXJkRm9udCkgJiYgdHlwZSA9PT0gIkNJREZvbnRUeXBlMiIgJiYgdGhpcy5jaWRFbmNvZGluZy5zdGFydHNXaXRoKCJJZGVudGl0eS0iKSkgewogICAgICBjb25zdCBjaWRUb0dpZE1hcCA9IHByb3BlcnRpZXMuY2lkVG9HaWRNYXA7CiAgICAgIGNvbnN0IG1hcCA9IFtdOwogICAgICBhcHBseVN0YW5kYXJkRm9udEdseXBoTWFwKG1hcCwgZ2V0R2x5cGhNYXBGb3JTdGFuZGFyZEZvbnRzKCkpOwogICAgICBpZiAoL0FyaWFsLT9CbGFjay9pLnRlc3QobmFtZSkpIHsKICAgICAgICBhcHBseVN0YW5kYXJkRm9udEdseXBoTWFwKG1hcCwgZ2V0U3VwcGxlbWVudGFsR2x5cGhNYXBGb3JBcmlhbEJsYWNrKCkpOwogICAgICB9IGVsc2UgaWYgKC9DYWxpYnJpL2kudGVzdChuYW1lKSkgewogICAgICAgIGFwcGx5U3RhbmRhcmRGb250R2x5cGhNYXAobWFwLCBnZXRTdXBwbGVtZW50YWxHbHlwaE1hcEZvckNhbGlicmkoKSk7CiAgICAgIH0KICAgICAgaWYgKGNpZFRvR2lkTWFwKSB7CiAgICAgICAgZm9yIChjb25zdCBjaGFyQ29kZSBpbiBtYXApIHsKICAgICAgICAgIGNvbnN0IGNpZCA9IG1hcFtjaGFyQ29kZV07CiAgICAgICAgICBpZiAoY2lkVG9HaWRNYXBbY2lkXSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIG1hcFsrY2hhckNvZGVdID0gY2lkVG9HaWRNYXBbY2lkXTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKGNpZFRvR2lkTWFwLmxlbmd0aCAhPT0gdGhpcy50b1VuaWNvZGUubGVuZ3RoICYmIHByb3BlcnRpZXMuaGFzSW5jbHVkZWRUb1VuaWNvZGVNYXAgJiYgdGhpcy50b1VuaWNvZGUgaW5zdGFuY2VvZiBJZGVudGl0eVRvVW5pY29kZU1hcCkgewogICAgICAgICAgdGhpcy50b1VuaWNvZGUuZm9yRWFjaChmdW5jdGlvbiAoY2hhckNvZGUsIHVuaWNvZGVDaGFyQ29kZSkgewogICAgICAgICAgICBjb25zdCBjaWQgPSBtYXBbY2hhckNvZGVdOwogICAgICAgICAgICBpZiAoY2lkVG9HaWRNYXBbY2lkXSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgbWFwWytjaGFyQ29kZV0gPSB1bmljb2RlQ2hhckNvZGU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoISh0aGlzLnRvVW5pY29kZSBpbnN0YW5jZW9mIElkZW50aXR5VG9Vbmljb2RlTWFwKSkgewogICAgICAgIHRoaXMudG9Vbmljb2RlLmZvckVhY2goZnVuY3Rpb24gKGNoYXJDb2RlLCB1bmljb2RlQ2hhckNvZGUpIHsKICAgICAgICAgIG1hcFsrY2hhckNvZGVdID0gdW5pY29kZUNoYXJDb2RlOwogICAgICAgIH0pOwogICAgICB9CiAgICAgIHRoaXMudG9Gb250Q2hhciA9IG1hcDsKICAgICAgdGhpcy50b1VuaWNvZGUgPSBuZXcgVG9Vbmljb2RlTWFwKG1hcCk7CiAgICB9IGVsc2UgaWYgKC9TeW1ib2wvaS50ZXN0KGZvbnROYW1lKSkgewogICAgICB0aGlzLnRvRm9udENoYXIgPSBidWlsZFRvRm9udENoYXIoU3ltYm9sU2V0RW5jb2RpbmcsIGdldEdseXBoc1VuaWNvZGUoKSwgdGhpcy5kaWZmZXJlbmNlcyk7CiAgICB9IGVsc2UgaWYgKC9EaW5nYmF0cy9pLnRlc3QoZm9udE5hbWUpKSB7CiAgICAgIHRoaXMudG9Gb250Q2hhciA9IGJ1aWxkVG9Gb250Q2hhcihaYXBmRGluZ2JhdHNFbmNvZGluZywgZ2V0RGluZ2JhdHNHbHlwaHNVbmljb2RlKCksIHRoaXMuZGlmZmVyZW5jZXMpOwogICAgfSBlbHNlIGlmIChpc1N0YW5kYXJkRm9udCB8fCBpc01hcHBlZFRvU3RhbmRhcmRGb250KSB7CiAgICAgIGNvbnN0IG1hcCA9IGJ1aWxkVG9Gb250Q2hhcih0aGlzLmRlZmF1bHRFbmNvZGluZywgZ2V0R2x5cGhzVW5pY29kZSgpLCB0aGlzLmRpZmZlcmVuY2VzKTsKICAgICAgaWYgKHR5cGUgPT09ICJDSURGb250VHlwZTIiICYmICF0aGlzLmNpZEVuY29kaW5nLnN0YXJ0c1dpdGgoIklkZW50aXR5LSIpICYmICEodGhpcy50b1VuaWNvZGUgaW5zdGFuY2VvZiBJZGVudGl0eVRvVW5pY29kZU1hcCkpIHsKICAgICAgICB0aGlzLnRvVW5pY29kZS5mb3JFYWNoKGZ1bmN0aW9uIChjaGFyQ29kZSwgdW5pY29kZUNoYXJDb2RlKSB7CiAgICAgICAgICBtYXBbK2NoYXJDb2RlXSA9IHVuaWNvZGVDaGFyQ29kZTsKICAgICAgICB9KTsKICAgICAgfQogICAgICB0aGlzLnRvRm9udENoYXIgPSBtYXA7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBnbHlwaHNVbmljb2RlTWFwID0gZ2V0R2x5cGhzVW5pY29kZSgpOwogICAgICBjb25zdCBtYXAgPSBbXTsKICAgICAgdGhpcy50b1VuaWNvZGUuZm9yRWFjaCgoY2hhckNvZGUsIHVuaWNvZGVDaGFyQ29kZSkgPT4gewogICAgICAgIGlmICghdGhpcy5jb21wb3NpdGUpIHsKICAgICAgICAgIGNvbnN0IGdseXBoTmFtZSA9IHRoaXMuZGlmZmVyZW5jZXNbY2hhckNvZGVdIHx8IHRoaXMuZGVmYXVsdEVuY29kaW5nW2NoYXJDb2RlXTsKICAgICAgICAgIGNvbnN0IHVuaWNvZGUgPSBnZXRVbmljb2RlRm9yR2x5cGgoZ2x5cGhOYW1lLCBnbHlwaHNVbmljb2RlTWFwKTsKICAgICAgICAgIGlmICh1bmljb2RlICE9PSAtMSkgewogICAgICAgICAgICB1bmljb2RlQ2hhckNvZGUgPSB1bmljb2RlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBtYXBbK2NoYXJDb2RlXSA9IHVuaWNvZGVDaGFyQ29kZTsKICAgICAgfSk7CiAgICAgIGlmICh0aGlzLmNvbXBvc2l0ZSAmJiB0aGlzLnRvVW5pY29kZSBpbnN0YW5jZW9mIElkZW50aXR5VG9Vbmljb2RlTWFwKSB7CiAgICAgICAgaWYgKC9UYWhvbWF8VmVyZGFuYS9pLnRlc3QobmFtZSkpIHsKICAgICAgICAgIGFwcGx5U3RhbmRhcmRGb250R2x5cGhNYXAobWFwLCBnZXRHbHlwaE1hcEZvclN0YW5kYXJkRm9udHMoKSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHRoaXMudG9Gb250Q2hhciA9IG1hcDsKICAgIH0KICAgIGFtZW5kRmFsbGJhY2tUb1VuaWNvZGUocHJvcGVydGllcyk7CiAgICB0aGlzLmxvYWRlZE5hbWUgPSBmb250TmFtZS5zcGxpdCgiLSIsIDEpWzBdOwogIH0KICBjaGVja0FuZFJlcGFpcihuYW1lLCBmb250LCBwcm9wZXJ0aWVzKSB7CiAgICBjb25zdCBWQUxJRF9UQUJMRVMgPSBbIk9TLzIiLCAiY21hcCIsICJoZWFkIiwgImhoZWEiLCAiaG10eCIsICJtYXhwIiwgIm5hbWUiLCAicG9zdCIsICJsb2NhIiwgImdseWYiLCAiZnBnbSIsICJwcmVwIiwgImN2dCAiLCAiQ0ZGICJdOwogICAgZnVuY3Rpb24gcmVhZFRhYmxlcyhmaWxlLCBudW1UYWJsZXMpIHsKICAgICAgY29uc3QgdGFibGVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgdGFibGVzWyJPUy8yIl0gPSBudWxsOwogICAgICB0YWJsZXMuY21hcCA9IG51bGw7CiAgICAgIHRhYmxlcy5oZWFkID0gbnVsbDsKICAgICAgdGFibGVzLmhoZWEgPSBudWxsOwogICAgICB0YWJsZXMuaG10eCA9IG51bGw7CiAgICAgIHRhYmxlcy5tYXhwID0gbnVsbDsKICAgICAgdGFibGVzLm5hbWUgPSBudWxsOwogICAgICB0YWJsZXMucG9zdCA9IG51bGw7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtVGFibGVzOyBpKyspIHsKICAgICAgICBjb25zdCB0YWJsZSA9IHJlYWRUYWJsZUVudHJ5KGZpbGUpOwogICAgICAgIGlmICghVkFMSURfVEFCTEVTLmluY2x1ZGVzKHRhYmxlLnRhZykpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBpZiAodGFibGUubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgdGFibGVzW3RhYmxlLnRhZ10gPSB0YWJsZTsKICAgICAgfQogICAgICByZXR1cm4gdGFibGVzOwogICAgfQogICAgZnVuY3Rpb24gcmVhZFRhYmxlRW50cnkoZmlsZSkgewogICAgICBjb25zdCB0YWcgPSBmaWxlLmdldFN0cmluZyg0KTsKICAgICAgY29uc3QgY2hlY2tzdW0gPSBmaWxlLmdldEludDMyKCkgPj4+IDA7CiAgICAgIGNvbnN0IG9mZnNldCA9IGZpbGUuZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgY29uc3QgbGVuZ3RoID0gZmlsZS5nZXRJbnQzMigpID4+PiAwOwogICAgICBjb25zdCBwcmV2aW91c1Bvc2l0aW9uID0gZmlsZS5wb3M7CiAgICAgIGZpbGUucG9zID0gZmlsZS5zdGFydCB8fCAwOwogICAgICBmaWxlLnNraXAob2Zmc2V0KTsKICAgICAgY29uc3QgZGF0YSA9IGZpbGUuZ2V0Qnl0ZXMobGVuZ3RoKTsKICAgICAgZmlsZS5wb3MgPSBwcmV2aW91c1Bvc2l0aW9uOwogICAgICBpZiAodGFnID09PSAiaGVhZCIpIHsKICAgICAgICBkYXRhWzhdID0gZGF0YVs5XSA9IGRhdGFbMTBdID0gZGF0YVsxMV0gPSAwOwogICAgICAgIGRhdGFbMTddIHw9IDB4MjA7CiAgICAgIH0KICAgICAgcmV0dXJuIHsKICAgICAgICB0YWcsCiAgICAgICAgY2hlY2tzdW0sCiAgICAgICAgbGVuZ3RoLAogICAgICAgIG9mZnNldCwKICAgICAgICBkYXRhCiAgICAgIH07CiAgICB9CiAgICBmdW5jdGlvbiByZWFkT3BlblR5cGVIZWFkZXIodHRmKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgdmVyc2lvbjogdHRmLmdldFN0cmluZyg0KSwKICAgICAgICBudW1UYWJsZXM6IHR0Zi5nZXRVaW50MTYoKSwKICAgICAgICBzZWFyY2hSYW5nZTogdHRmLmdldFVpbnQxNigpLAogICAgICAgIGVudHJ5U2VsZWN0b3I6IHR0Zi5nZXRVaW50MTYoKSwKICAgICAgICByYW5nZVNoaWZ0OiB0dGYuZ2V0VWludDE2KCkKICAgICAgfTsKICAgIH0KICAgIGZ1bmN0aW9uIHJlYWRUcnVlVHlwZUNvbGxlY3Rpb25IZWFkZXIodHRjKSB7CiAgICAgIGNvbnN0IHR0Y1RhZyA9IHR0Yy5nZXRTdHJpbmcoNCk7CiAgICAgIGFzc2VydCh0dGNUYWcgPT09ICJ0dGNmIiwgIk11c3QgYmUgYSBUcnVlVHlwZSBDb2xsZWN0aW9uIGZvbnQuIik7CiAgICAgIGNvbnN0IG1ham9yVmVyc2lvbiA9IHR0Yy5nZXRVaW50MTYoKTsKICAgICAgY29uc3QgbWlub3JWZXJzaW9uID0gdHRjLmdldFVpbnQxNigpOwogICAgICBjb25zdCBudW1Gb250cyA9IHR0Yy5nZXRJbnQzMigpID4+PiAwOwogICAgICBjb25zdCBvZmZzZXRUYWJsZSA9IFtdOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG51bUZvbnRzOyBpKyspIHsKICAgICAgICBvZmZzZXRUYWJsZS5wdXNoKHR0Yy5nZXRJbnQzMigpID4+PiAwKTsKICAgICAgfQogICAgICBjb25zdCBoZWFkZXIgPSB7CiAgICAgICAgdHRjVGFnLAogICAgICAgIG1ham9yVmVyc2lvbiwKICAgICAgICBtaW5vclZlcnNpb24sCiAgICAgICAgbnVtRm9udHMsCiAgICAgICAgb2Zmc2V0VGFibGUKICAgICAgfTsKICAgICAgc3dpdGNoIChtYWpvclZlcnNpb24pIHsKICAgICAgICBjYXNlIDE6CiAgICAgICAgICByZXR1cm4gaGVhZGVyOwogICAgICAgIGNhc2UgMjoKICAgICAgICAgIGhlYWRlci5kc2lnVGFnID0gdHRjLmdldEludDMyKCkgPj4+IDA7CiAgICAgICAgICBoZWFkZXIuZHNpZ0xlbmd0aCA9IHR0Yy5nZXRJbnQzMigpID4+PiAwOwogICAgICAgICAgaGVhZGVyLmRzaWdPZmZzZXQgPSB0dGMuZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgICAgIHJldHVybiBoZWFkZXI7CiAgICAgIH0KICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIFRydWVUeXBlIENvbGxlY3Rpb24gbWFqb3JWZXJzaW9uOiAke21ham9yVmVyc2lvbn0uYCk7CiAgICB9CiAgICBmdW5jdGlvbiByZWFkVHJ1ZVR5cGVDb2xsZWN0aW9uRGF0YSh0dGMsIGZvbnROYW1lKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBudW1Gb250cywKICAgICAgICBvZmZzZXRUYWJsZQogICAgICB9ID0gcmVhZFRydWVUeXBlQ29sbGVjdGlvbkhlYWRlcih0dGMpOwogICAgICBjb25zdCBmb250TmFtZVBhcnRzID0gZm9udE5hbWUuc3BsaXQoIisiKTsKICAgICAgbGV0IGZhbGxiYWNrRGF0YTsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1Gb250czsgaSsrKSB7CiAgICAgICAgdHRjLnBvcyA9ICh0dGMuc3RhcnQgfHwgMCkgKyBvZmZzZXRUYWJsZVtpXTsKICAgICAgICBjb25zdCBwb3RlbnRpYWxIZWFkZXIgPSByZWFkT3BlblR5cGVIZWFkZXIodHRjKTsKICAgICAgICBjb25zdCBwb3RlbnRpYWxUYWJsZXMgPSByZWFkVGFibGVzKHR0YywgcG90ZW50aWFsSGVhZGVyLm51bVRhYmxlcyk7CiAgICAgICAgaWYgKCFwb3RlbnRpYWxUYWJsZXMubmFtZSkgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCdUcnVlVHlwZSBDb2xsZWN0aW9uIGZvbnQgbXVzdCBjb250YWluIGEgIm5hbWUiIHRhYmxlLicpOwogICAgICAgIH0KICAgICAgICBjb25zdCBbbmFtZVRhYmxlXSA9IHJlYWROYW1lVGFibGUocG90ZW50aWFsVGFibGVzLm5hbWUpOwogICAgICAgIGZvciAobGV0IGogPSAwLCBqaiA9IG5hbWVUYWJsZS5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgICAgICBmb3IgKGxldCBrID0gMCwga2sgPSBuYW1lVGFibGVbal0ubGVuZ3RoOyBrIDwga2s7IGsrKykgewogICAgICAgICAgICBjb25zdCBuYW1lRW50cnkgPSBuYW1lVGFibGVbal1ba10/LnJlcGxhY2VBbGwoL1xzL2csICIiKTsKICAgICAgICAgICAgaWYgKCFuYW1lRW50cnkpIHsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAobmFtZUVudHJ5ID09PSBmb250TmFtZSkgewogICAgICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgICAgICBoZWFkZXI6IHBvdGVudGlhbEhlYWRlciwKICAgICAgICAgICAgICAgIHRhYmxlczogcG90ZW50aWFsVGFibGVzCiAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoZm9udE5hbWVQYXJ0cy5sZW5ndGggPCAyKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZm9yIChjb25zdCBwYXJ0IG9mIGZvbnROYW1lUGFydHMpIHsKICAgICAgICAgICAgICBpZiAobmFtZUVudHJ5ID09PSBwYXJ0KSB7CiAgICAgICAgICAgICAgICBmYWxsYmFja0RhdGEgPSB7CiAgICAgICAgICAgICAgICAgIG5hbWU6IHBhcnQsCiAgICAgICAgICAgICAgICAgIGhlYWRlcjogcG90ZW50aWFsSGVhZGVyLAogICAgICAgICAgICAgICAgICB0YWJsZXM6IHBvdGVudGlhbFRhYmxlcwogICAgICAgICAgICAgICAgfTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGZhbGxiYWNrRGF0YSkgewogICAgICAgIHdhcm4oYFRydWVUeXBlIENvbGxlY3Rpb24gZG9lcyBub3QgY29udGFpbiAiJHtmb250TmFtZX0iIGZvbnQsIGAgKyBgZmFsbGluZyBiYWNrIHRvICIke2ZhbGxiYWNrRGF0YS5uYW1lfSIgZm9udCBpbnN0ZWFkLmApOwogICAgICAgIHJldHVybiB7CiAgICAgICAgICBoZWFkZXI6IGZhbGxiYWNrRGF0YS5oZWFkZXIsCiAgICAgICAgICB0YWJsZXM6IGZhbGxiYWNrRGF0YS50YWJsZXMKICAgICAgICB9OwogICAgICB9CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgVHJ1ZVR5cGUgQ29sbGVjdGlvbiBkb2VzIG5vdCBjb250YWluICIke2ZvbnROYW1lfSIgZm9udC5gKTsKICAgIH0KICAgIGZ1bmN0aW9uIHJlYWRDbWFwVGFibGUoY21hcCwgZmlsZSwgaXNTeW1ib2xpY0ZvbnQsIGhhc0VuY29kaW5nKSB7CiAgICAgIGlmICghY21hcCkgewogICAgICAgIHdhcm4oIk5vIGNtYXAgdGFibGUgYXZhaWxhYmxlLiIpOwogICAgICAgIHJldHVybiB7CiAgICAgICAgICBwbGF0Zm9ybUlkOiAtMSwKICAgICAgICAgIGVuY29kaW5nSWQ6IC0xLAogICAgICAgICAgbWFwcGluZ3M6IFtdLAogICAgICAgICAgaGFzU2hvcnRDbWFwOiBmYWxzZQogICAgICAgIH07CiAgICAgIH0KICAgICAgbGV0IHNlZ21lbnQ7CiAgICAgIGxldCBzdGFydCA9IChmaWxlLnN0YXJ0IHx8IDApICsgY21hcC5vZmZzZXQ7CiAgICAgIGZpbGUucG9zID0gc3RhcnQ7CiAgICAgIGZpbGUuc2tpcCgyKTsKICAgICAgY29uc3QgbnVtVGFibGVzID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgbGV0IHBvdGVudGlhbFRhYmxlOwogICAgICBsZXQgY2FuQnJlYWsgPSBmYWxzZTsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1UYWJsZXM7IGkrKykgewogICAgICAgIGNvbnN0IHBsYXRmb3JtSWQgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICAgIGNvbnN0IGVuY29kaW5nSWQgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICAgIGNvbnN0IG9mZnNldCA9IGZpbGUuZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgICBsZXQgdXNlVGFibGUgPSBmYWxzZTsKICAgICAgICBpZiAocG90ZW50aWFsVGFibGU/LnBsYXRmb3JtSWQgPT09IHBsYXRmb3JtSWQgJiYgcG90ZW50aWFsVGFibGU/LmVuY29kaW5nSWQgPT09IGVuY29kaW5nSWQpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBpZiAocGxhdGZvcm1JZCA9PT0gMCAmJiAoZW5jb2RpbmdJZCA9PT0gMCB8fCBlbmNvZGluZ0lkID09PSAxIHx8IGVuY29kaW5nSWQgPT09IDMpKSB7CiAgICAgICAgICB1c2VUYWJsZSA9IHRydWU7CiAgICAgICAgfSBlbHNlIGlmIChwbGF0Zm9ybUlkID09PSAxICYmIGVuY29kaW5nSWQgPT09IDApIHsKICAgICAgICAgIHVzZVRhYmxlID0gdHJ1ZTsKICAgICAgICB9IGVsc2UgaWYgKHBsYXRmb3JtSWQgPT09IDMgJiYgZW5jb2RpbmdJZCA9PT0gMSAmJiAoaGFzRW5jb2RpbmcgfHwgIXBvdGVudGlhbFRhYmxlKSkgewogICAgICAgICAgdXNlVGFibGUgPSB0cnVlOwogICAgICAgICAgaWYgKCFpc1N5bWJvbGljRm9udCkgewogICAgICAgICAgICBjYW5CcmVhayA9IHRydWU7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChpc1N5bWJvbGljRm9udCAmJiBwbGF0Zm9ybUlkID09PSAzICYmIGVuY29kaW5nSWQgPT09IDApIHsKICAgICAgICAgIHVzZVRhYmxlID0gdHJ1ZTsKICAgICAgICAgIGxldCBjb3JyZWN0bHlTb3J0ZWQgPSB0cnVlOwogICAgICAgICAgaWYgKGkgPCBudW1UYWJsZXMgLSAxKSB7CiAgICAgICAgICAgIGNvbnN0IG5leHRCeXRlcyA9IGZpbGUucGVla0J5dGVzKDIpLAogICAgICAgICAgICAgIG5leHRQbGF0Zm9ybUlkID0gaW50MTYobmV4dEJ5dGVzWzBdLCBuZXh0Qnl0ZXNbMV0pOwogICAgICAgICAgICBpZiAobmV4dFBsYXRmb3JtSWQgPCBwbGF0Zm9ybUlkKSB7CiAgICAgICAgICAgICAgY29ycmVjdGx5U29ydGVkID0gZmFsc2U7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChjb3JyZWN0bHlTb3J0ZWQpIHsKICAgICAgICAgICAgY2FuQnJlYWsgPSB0cnVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAodXNlVGFibGUpIHsKICAgICAgICAgIHBvdGVudGlhbFRhYmxlID0gewogICAgICAgICAgICBwbGF0Zm9ybUlkLAogICAgICAgICAgICBlbmNvZGluZ0lkLAogICAgICAgICAgICBvZmZzZXQKICAgICAgICAgIH07CiAgICAgICAgfQogICAgICAgIGlmIChjYW5CcmVhaykgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChwb3RlbnRpYWxUYWJsZSkgewogICAgICAgIGZpbGUucG9zID0gc3RhcnQgKyBwb3RlbnRpYWxUYWJsZS5vZmZzZXQ7CiAgICAgIH0KICAgICAgaWYgKCFwb3RlbnRpYWxUYWJsZSB8fCBmaWxlLnBlZWtCeXRlKCkgPT09IC0xKSB7CiAgICAgICAgd2FybigiQ291bGQgbm90IGZpbmQgYSBwcmVmZXJyZWQgY21hcCB0YWJsZS4iKTsKICAgICAgICByZXR1cm4gewogICAgICAgICAgcGxhdGZvcm1JZDogLTEsCiAgICAgICAgICBlbmNvZGluZ0lkOiAtMSwKICAgICAgICAgIG1hcHBpbmdzOiBbXSwKICAgICAgICAgIGhhc1Nob3J0Q21hcDogZmFsc2UKICAgICAgICB9OwogICAgICB9CiAgICAgIGNvbnN0IGZvcm1hdCA9IGZpbGUuZ2V0VWludDE2KCk7CiAgICAgIGxldCBoYXNTaG9ydENtYXAgPSBmYWxzZTsKICAgICAgY29uc3QgbWFwcGluZ3MgPSBbXTsKICAgICAgbGV0IGosIGdseXBoSWQ7CiAgICAgIGlmIChmb3JtYXQgPT09IDApIHsKICAgICAgICBmaWxlLnNraXAoMiArIDIpOwogICAgICAgIGZvciAoaiA9IDA7IGogPCAyNTY7IGorKykgewogICAgICAgICAgY29uc3QgaW5kZXggPSBmaWxlLmdldEJ5dGUoKTsKICAgICAgICAgIGlmICghaW5kZXgpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBtYXBwaW5ncy5wdXNoKHsKICAgICAgICAgICAgY2hhckNvZGU6IGosCiAgICAgICAgICAgIGdseXBoSWQ6IGluZGV4CiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgaGFzU2hvcnRDbWFwID0gdHJ1ZTsKICAgICAgfSBlbHNlIGlmIChmb3JtYXQgPT09IDIpIHsKICAgICAgICBmaWxlLnNraXAoMiArIDIpOwogICAgICAgIGNvbnN0IHN1YkhlYWRlcktleXMgPSBbXTsKICAgICAgICBsZXQgbWF4U3ViSGVhZGVyS2V5ID0gMDsKICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI1NjsgaSsrKSB7CiAgICAgICAgICBjb25zdCBzdWJIZWFkZXJLZXkgPSBmaWxlLmdldFVpbnQxNigpID4+IDM7CiAgICAgICAgICBzdWJIZWFkZXJLZXlzLnB1c2goc3ViSGVhZGVyS2V5KTsKICAgICAgICAgIG1heFN1YkhlYWRlcktleSA9IE1hdGgubWF4KHN1YkhlYWRlcktleSwgbWF4U3ViSGVhZGVyS2V5KTsKICAgICAgICB9CiAgICAgICAgY29uc3Qgc3ViSGVhZGVycyA9IFtdOwogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IG1heFN1YkhlYWRlcktleTsgaSsrKSB7CiAgICAgICAgICBzdWJIZWFkZXJzLnB1c2goewogICAgICAgICAgICBmaXJzdENvZGU6IGZpbGUuZ2V0VWludDE2KCksCiAgICAgICAgICAgIGVudHJ5Q291bnQ6IGZpbGUuZ2V0VWludDE2KCksCiAgICAgICAgICAgIGlkRGVsdGE6IHNpZ25lZEludDE2KGZpbGUuZ2V0Qnl0ZSgpLCBmaWxlLmdldEJ5dGUoKSksCiAgICAgICAgICAgIGlkUmFuZ2VQb3M6IGZpbGUucG9zICsgZmlsZS5nZXRVaW50MTYoKQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMjU2OyBpKyspIHsKICAgICAgICAgIGlmIChzdWJIZWFkZXJLZXlzW2ldID09PSAwKSB7CiAgICAgICAgICAgIGZpbGUucG9zID0gc3ViSGVhZGVyc1swXS5pZFJhbmdlUG9zICsgMiAqIGk7CiAgICAgICAgICAgIGdseXBoSWQgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICAgICAgICBtYXBwaW5ncy5wdXNoKHsKICAgICAgICAgICAgICBjaGFyQ29kZTogaSwKICAgICAgICAgICAgICBnbHlwaElkCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgY29uc3QgcyA9IHN1YkhlYWRlcnNbc3ViSGVhZGVyS2V5c1tpXV07CiAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBzLmVudHJ5Q291bnQ7IGorKykgewogICAgICAgICAgICAgIGNvbnN0IGNoYXJDb2RlID0gKGkgPDwgOCkgKyBqICsgcy5maXJzdENvZGU7CiAgICAgICAgICAgICAgZmlsZS5wb3MgPSBzLmlkUmFuZ2VQb3MgKyAyICogajsKICAgICAgICAgICAgICBnbHlwaElkID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgICAgICAgICBpZiAoZ2x5cGhJZCAhPT0gMCkgewogICAgICAgICAgICAgICAgZ2x5cGhJZCA9IChnbHlwaElkICsgcy5pZERlbHRhKSAlIDY1NTM2OwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBtYXBwaW5ncy5wdXNoKHsKICAgICAgICAgICAgICAgIGNoYXJDb2RlLAogICAgICAgICAgICAgICAgZ2x5cGhJZAogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGZvcm1hdCA9PT0gNCkgewogICAgICAgIGZpbGUuc2tpcCgyICsgMik7CiAgICAgICAgY29uc3Qgc2VnQ291bnQgPSBmaWxlLmdldFVpbnQxNigpID4+IDE7CiAgICAgICAgZmlsZS5za2lwKDYpOwogICAgICAgIGNvbnN0IHNlZ21lbnRzID0gW107CiAgICAgICAgbGV0IHNlZ0luZGV4OwogICAgICAgIGZvciAoc2VnSW5kZXggPSAwOyBzZWdJbmRleCA8IHNlZ0NvdW50OyBzZWdJbmRleCsrKSB7CiAgICAgICAgICBzZWdtZW50cy5wdXNoKHsKICAgICAgICAgICAgZW5kOiBmaWxlLmdldFVpbnQxNigpCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgZmlsZS5za2lwKDIpOwogICAgICAgIGZvciAoc2VnSW5kZXggPSAwOyBzZWdJbmRleCA8IHNlZ0NvdW50OyBzZWdJbmRleCsrKSB7CiAgICAgICAgICBzZWdtZW50c1tzZWdJbmRleF0uc3RhcnQgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICAgIH0KICAgICAgICBmb3IgKHNlZ0luZGV4ID0gMDsgc2VnSW5kZXggPCBzZWdDb3VudDsgc2VnSW5kZXgrKykgewogICAgICAgICAgc2VnbWVudHNbc2VnSW5kZXhdLmRlbHRhID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgICB9CiAgICAgICAgbGV0IG9mZnNldHNDb3VudCA9IDAsCiAgICAgICAgICBvZmZzZXRJbmRleDsKICAgICAgICBmb3IgKHNlZ0luZGV4ID0gMDsgc2VnSW5kZXggPCBzZWdDb3VudDsgc2VnSW5kZXgrKykgewogICAgICAgICAgc2VnbWVudCA9IHNlZ21lbnRzW3NlZ0luZGV4XTsKICAgICAgICAgIGNvbnN0IHJhbmdlT2Zmc2V0ID0gZmlsZS5nZXRVaW50MTYoKTsKICAgICAgICAgIGlmICghcmFuZ2VPZmZzZXQpIHsKICAgICAgICAgICAgc2VnbWVudC5vZmZzZXRJbmRleCA9IC0xOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIG9mZnNldEluZGV4ID0gKHJhbmdlT2Zmc2V0ID4+IDEpIC0gKHNlZ0NvdW50IC0gc2VnSW5kZXgpOwogICAgICAgICAgc2VnbWVudC5vZmZzZXRJbmRleCA9IG9mZnNldEluZGV4OwogICAgICAgICAgb2Zmc2V0c0NvdW50ID0gTWF0aC5tYXgob2Zmc2V0c0NvdW50LCBvZmZzZXRJbmRleCArIHNlZ21lbnQuZW5kIC0gc2VnbWVudC5zdGFydCArIDEpOwogICAgICAgIH0KICAgICAgICBjb25zdCBvZmZzZXRzID0gW107CiAgICAgICAgZm9yIChqID0gMDsgaiA8IG9mZnNldHNDb3VudDsgaisrKSB7CiAgICAgICAgICBvZmZzZXRzLnB1c2goZmlsZS5nZXRVaW50MTYoKSk7CiAgICAgICAgfQogICAgICAgIGZvciAoc2VnSW5kZXggPSAwOyBzZWdJbmRleCA8IHNlZ0NvdW50OyBzZWdJbmRleCsrKSB7CiAgICAgICAgICBzZWdtZW50ID0gc2VnbWVudHNbc2VnSW5kZXhdOwogICAgICAgICAgc3RhcnQgPSBzZWdtZW50LnN0YXJ0OwogICAgICAgICAgY29uc3QgZW5kID0gc2VnbWVudC5lbmQ7CiAgICAgICAgICBjb25zdCBkZWx0YSA9IHNlZ21lbnQuZGVsdGE7CiAgICAgICAgICBvZmZzZXRJbmRleCA9IHNlZ21lbnQub2Zmc2V0SW5kZXg7CiAgICAgICAgICBmb3IgKGogPSBzdGFydDsgaiA8PSBlbmQ7IGorKykgewogICAgICAgICAgICBpZiAoaiA9PT0gMHhmZmZmKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZ2x5cGhJZCA9IG9mZnNldEluZGV4IDwgMCA/IGogOiBvZmZzZXRzW29mZnNldEluZGV4ICsgaiAtIHN0YXJ0XTsKICAgICAgICAgICAgZ2x5cGhJZCA9IGdseXBoSWQgKyBkZWx0YSAmIDB4ZmZmZjsKICAgICAgICAgICAgbWFwcGluZ3MucHVzaCh7CiAgICAgICAgICAgICAgY2hhckNvZGU6IGosCiAgICAgICAgICAgICAgZ2x5cGhJZAogICAgICAgICAgICB9KTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoZm9ybWF0ID09PSA2KSB7CiAgICAgICAgZmlsZS5za2lwKDIgKyAyKTsKICAgICAgICBjb25zdCBmaXJzdENvZGUgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICAgIGNvbnN0IGVudHJ5Q291bnQgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICAgIGZvciAoaiA9IDA7IGogPCBlbnRyeUNvdW50OyBqKyspIHsKICAgICAgICAgIGdseXBoSWQgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICAgICAgY29uc3QgY2hhckNvZGUgPSBmaXJzdENvZGUgKyBqOwogICAgICAgICAgbWFwcGluZ3MucHVzaCh7CiAgICAgICAgICAgIGNoYXJDb2RlLAogICAgICAgICAgICBnbHlwaElkCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoZm9ybWF0ID09PSAxMikgewogICAgICAgIGZpbGUuc2tpcCgyICsgNCArIDQpOwogICAgICAgIGNvbnN0IG5Hcm91cHMgPSBmaWxlLmdldEludDMyKCkgPj4+IDA7CiAgICAgICAgZm9yIChqID0gMDsgaiA8IG5Hcm91cHM7IGorKykgewogICAgICAgICAgY29uc3Qgc3RhcnRDaGFyQ29kZSA9IGZpbGUuZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgICAgIGNvbnN0IGVuZENoYXJDb2RlID0gZmlsZS5nZXRJbnQzMigpID4+PiAwOwogICAgICAgICAgbGV0IGdseXBoQ29kZSA9IGZpbGUuZ2V0SW50MzIoKSA+Pj4gMDsKICAgICAgICAgIGZvciAobGV0IGNoYXJDb2RlID0gc3RhcnRDaGFyQ29kZTsgY2hhckNvZGUgPD0gZW5kQ2hhckNvZGU7IGNoYXJDb2RlKyspIHsKICAgICAgICAgICAgbWFwcGluZ3MucHVzaCh7CiAgICAgICAgICAgICAgY2hhckNvZGUsCiAgICAgICAgICAgICAgZ2x5cGhJZDogZ2x5cGhDb2RlKysKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHdhcm4oImNtYXAgdGFibGUgaGFzIHVuc3VwcG9ydGVkIGZvcm1hdDogIiArIGZvcm1hdCk7CiAgICAgICAgcmV0dXJuIHsKICAgICAgICAgIHBsYXRmb3JtSWQ6IC0xLAogICAgICAgICAgZW5jb2RpbmdJZDogLTEsCiAgICAgICAgICBtYXBwaW5nczogW10sCiAgICAgICAgICBoYXNTaG9ydENtYXA6IGZhbHNlCiAgICAgICAgfTsKICAgICAgfQogICAgICBtYXBwaW5ncy5zb3J0KChhLCBiKSA9PiBhLmNoYXJDb2RlIC0gYi5jaGFyQ29kZSk7CiAgICAgIGNvbnN0IGZpbmFsTWFwcGluZ3MgPSBbXSwKICAgICAgICBzZWVuQ2hhckNvZGVzID0gbmV3IFNldCgpOwogICAgICBmb3IgKGNvbnN0IG1hcCBvZiBtYXBwaW5ncykgewogICAgICAgIGNvbnN0IHsKICAgICAgICAgIGNoYXJDb2RlCiAgICAgICAgfSA9IG1hcDsKICAgICAgICBpZiAoc2VlbkNoYXJDb2Rlcy5oYXMoY2hhckNvZGUpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgc2VlbkNoYXJDb2Rlcy5hZGQoY2hhckNvZGUpOwogICAgICAgIGZpbmFsTWFwcGluZ3MucHVzaChtYXApOwogICAgICB9CiAgICAgIHJldHVybiB7CiAgICAgICAgcGxhdGZvcm1JZDogcG90ZW50aWFsVGFibGUucGxhdGZvcm1JZCwKICAgICAgICBlbmNvZGluZ0lkOiBwb3RlbnRpYWxUYWJsZS5lbmNvZGluZ0lkLAogICAgICAgIG1hcHBpbmdzOiBmaW5hbE1hcHBpbmdzLAogICAgICAgIGhhc1Nob3J0Q21hcAogICAgICB9OwogICAgfQogICAgZnVuY3Rpb24gc2FuaXRpemVNZXRyaWNzKGZpbGUsIGhlYWRlciwgbWV0cmljcywgaGVhZFRhYmxlLCBudW1HbHlwaHMsIGR1cEZpcnN0RW50cnkpIHsKICAgICAgaWYgKCFoZWFkZXIpIHsKICAgICAgICBpZiAobWV0cmljcykgewogICAgICAgICAgbWV0cmljcy5kYXRhID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGZpbGUucG9zID0gKGZpbGUuc3RhcnQgfHwgMCkgKyBoZWFkZXIub2Zmc2V0OwogICAgICBmaWxlLnBvcyArPSA0OwogICAgICBmaWxlLnBvcyArPSAyOwogICAgICBmaWxlLnBvcyArPSAyOwogICAgICBmaWxlLnBvcyArPSAyOwogICAgICBmaWxlLnBvcyArPSAyOwogICAgICBmaWxlLnBvcyArPSAyOwogICAgICBmaWxlLnBvcyArPSAyOwogICAgICBmaWxlLnBvcyArPSAyOwogICAgICBmaWxlLnBvcyArPSAyOwogICAgICBmaWxlLnBvcyArPSAyOwogICAgICBjb25zdCBjYXJldE9mZnNldCA9IGZpbGUuZ2V0VWludDE2KCk7CiAgICAgIGZpbGUucG9zICs9IDg7CiAgICAgIGZpbGUucG9zICs9IDI7CiAgICAgIGxldCBudW1PZk1ldHJpY3MgPSBmaWxlLmdldFVpbnQxNigpOwogICAgICBpZiAoY2FyZXRPZmZzZXQgIT09IDApIHsKICAgICAgICBjb25zdCBtYWNTdHlsZSA9IGludDE2KGhlYWRUYWJsZS5kYXRhWzQ0XSwgaGVhZFRhYmxlLmRhdGFbNDVdKTsKICAgICAgICBpZiAoIShtYWNTdHlsZSAmIDIpKSB7CiAgICAgICAgICBoZWFkZXIuZGF0YVsyMl0gPSAwOwogICAgICAgICAgaGVhZGVyLmRhdGFbMjNdID0gMDsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKG51bU9mTWV0cmljcyA+IG51bUdseXBocykgewogICAgICAgIGluZm8oYFRoZSBudW1PZk1ldHJpY3MgKCR7bnVtT2ZNZXRyaWNzfSkgc2hvdWxkIG5vdCBiZSBgICsgYGdyZWF0ZXIgdGhhbiB0aGUgbnVtR2x5cGhzICgke251bUdseXBoc30pLmApOwogICAgICAgIG51bU9mTWV0cmljcyA9IG51bUdseXBoczsKICAgICAgICBoZWFkZXIuZGF0YVszNF0gPSAobnVtT2ZNZXRyaWNzICYgMHhmZjAwKSA+PiA4OwogICAgICAgIGhlYWRlci5kYXRhWzM1XSA9IG51bU9mTWV0cmljcyAmIDB4MDBmZjsKICAgICAgfQogICAgICBjb25zdCBudW1PZlNpZGViZWFyaW5ncyA9IG51bUdseXBocyAtIG51bU9mTWV0cmljczsKICAgICAgY29uc3QgbnVtTWlzc2luZyA9IG51bU9mU2lkZWJlYXJpbmdzIC0gKG1ldHJpY3MubGVuZ3RoIC0gbnVtT2ZNZXRyaWNzICogNCA+PiAxKTsKICAgICAgaWYgKG51bU1pc3NpbmcgPiAwKSB7CiAgICAgICAgY29uc3QgZW50cmllcyA9IG5ldyBVaW50OEFycmF5KG1ldHJpY3MubGVuZ3RoICsgbnVtTWlzc2luZyAqIDIpOwogICAgICAgIGVudHJpZXMuc2V0KG1ldHJpY3MuZGF0YSk7CiAgICAgICAgaWYgKGR1cEZpcnN0RW50cnkpIHsKICAgICAgICAgIGVudHJpZXNbbWV0cmljcy5sZW5ndGhdID0gbWV0cmljcy5kYXRhWzJdOwogICAgICAgICAgZW50cmllc1ttZXRyaWNzLmxlbmd0aCArIDFdID0gbWV0cmljcy5kYXRhWzNdOwogICAgICAgIH0KICAgICAgICBtZXRyaWNzLmRhdGEgPSBlbnRyaWVzOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBzYW5pdGl6ZUdseXBoKHNvdXJjZSwgc291cmNlU3RhcnQsIHNvdXJjZUVuZCwgZGVzdCwgZGVzdFN0YXJ0LCBoaW50c1ZhbGlkKSB7CiAgICAgIGNvbnN0IGdseXBoUHJvZmlsZSA9IHsKICAgICAgICBsZW5ndGg6IDAsCiAgICAgICAgc2l6ZU9mSW5zdHJ1Y3Rpb25zOiAwCiAgICAgIH07CiAgICAgIGlmIChzb3VyY2VTdGFydCA8IDAgfHwgc291cmNlU3RhcnQgPj0gc291cmNlLmxlbmd0aCB8fCBzb3VyY2VFbmQgPiBzb3VyY2UubGVuZ3RoIHx8IHNvdXJjZUVuZCAtIHNvdXJjZVN0YXJ0IDw9IDEyKSB7CiAgICAgICAgcmV0dXJuIGdseXBoUHJvZmlsZTsKICAgICAgfQogICAgICBjb25zdCBnbHlmID0gc291cmNlLnN1YmFycmF5KHNvdXJjZVN0YXJ0LCBzb3VyY2VFbmQpOwogICAgICBjb25zdCB4TWluID0gc2lnbmVkSW50MTYoZ2x5ZlsyXSwgZ2x5ZlszXSk7CiAgICAgIGNvbnN0IHlNaW4gPSBzaWduZWRJbnQxNihnbHlmWzRdLCBnbHlmWzVdKTsKICAgICAgY29uc3QgeE1heCA9IHNpZ25lZEludDE2KGdseWZbNl0sIGdseWZbN10pOwogICAgICBjb25zdCB5TWF4ID0gc2lnbmVkSW50MTYoZ2x5Zls4XSwgZ2x5Zls5XSk7CiAgICAgIGlmICh4TWluID4geE1heCkgewogICAgICAgIHdyaXRlU2lnbmVkSW50MTYoZ2x5ZiwgMiwgeE1heCk7CiAgICAgICAgd3JpdGVTaWduZWRJbnQxNihnbHlmLCA2LCB4TWluKTsKICAgICAgfQogICAgICBpZiAoeU1pbiA+IHlNYXgpIHsKICAgICAgICB3cml0ZVNpZ25lZEludDE2KGdseWYsIDQsIHlNYXgpOwogICAgICAgIHdyaXRlU2lnbmVkSW50MTYoZ2x5ZiwgOCwgeU1pbik7CiAgICAgIH0KICAgICAgY29uc3QgY29udG91cnNDb3VudCA9IHNpZ25lZEludDE2KGdseWZbMF0sIGdseWZbMV0pOwogICAgICBpZiAoY29udG91cnNDb3VudCA8IDApIHsKICAgICAgICBpZiAoY29udG91cnNDb3VudCA8IC0xKSB7CiAgICAgICAgICByZXR1cm4gZ2x5cGhQcm9maWxlOwogICAgICAgIH0KICAgICAgICBkZXN0LnNldChnbHlmLCBkZXN0U3RhcnQpOwogICAgICAgIGdseXBoUHJvZmlsZS5sZW5ndGggPSBnbHlmLmxlbmd0aDsKICAgICAgICByZXR1cm4gZ2x5cGhQcm9maWxlOwogICAgICB9CiAgICAgIGxldCBpLAogICAgICAgIGogPSAxMCwKICAgICAgICBmbGFnc0NvdW50ID0gMDsKICAgICAgZm9yIChpID0gMDsgaSA8IGNvbnRvdXJzQ291bnQ7IGkrKykgewogICAgICAgIGNvbnN0IGVuZFBvaW50ID0gZ2x5ZltqXSA8PCA4IHwgZ2x5ZltqICsgMV07CiAgICAgICAgZmxhZ3NDb3VudCA9IGVuZFBvaW50ICsgMTsKICAgICAgICBqICs9IDI7CiAgICAgIH0KICAgICAgY29uc3QgaW5zdHJ1Y3Rpb25zU3RhcnQgPSBqOwogICAgICBjb25zdCBpbnN0cnVjdGlvbnNMZW5ndGggPSBnbHlmW2pdIDw8IDggfCBnbHlmW2ogKyAxXTsKICAgICAgZ2x5cGhQcm9maWxlLnNpemVPZkluc3RydWN0aW9ucyA9IGluc3RydWN0aW9uc0xlbmd0aDsKICAgICAgaiArPSAyICsgaW5zdHJ1Y3Rpb25zTGVuZ3RoOwogICAgICBjb25zdCBpbnN0cnVjdGlvbnNFbmQgPSBqOwogICAgICBsZXQgY29vcmRpbmF0ZXNMZW5ndGggPSAwOwogICAgICBmb3IgKGkgPSAwOyBpIDwgZmxhZ3NDb3VudDsgaSsrKSB7CiAgICAgICAgY29uc3QgZmxhZyA9IGdseWZbaisrXTsKICAgICAgICBpZiAoZmxhZyAmIDB4YzApIHsKICAgICAgICAgIGdseWZbaiAtIDFdID0gZmxhZyAmIDB4M2Y7CiAgICAgICAgfQogICAgICAgIGxldCB4TGVuZ3RoID0gMjsKICAgICAgICBpZiAoZmxhZyAmIDIpIHsKICAgICAgICAgIHhMZW5ndGggPSAxOwogICAgICAgIH0gZWxzZSBpZiAoZmxhZyAmIDE2KSB7CiAgICAgICAgICB4TGVuZ3RoID0gMDsKICAgICAgICB9CiAgICAgICAgbGV0IHlMZW5ndGggPSAyOwogICAgICAgIGlmIChmbGFnICYgNCkgewogICAgICAgICAgeUxlbmd0aCA9IDE7CiAgICAgICAgfSBlbHNlIGlmIChmbGFnICYgMzIpIHsKICAgICAgICAgIHlMZW5ndGggPSAwOwogICAgICAgIH0KICAgICAgICBjb25zdCB4eUxlbmd0aCA9IHhMZW5ndGggKyB5TGVuZ3RoOwogICAgICAgIGNvb3JkaW5hdGVzTGVuZ3RoICs9IHh5TGVuZ3RoOwogICAgICAgIGlmIChmbGFnICYgOCkgewogICAgICAgICAgY29uc3QgcmVwZWF0ID0gZ2x5ZltqKytdOwogICAgICAgICAgaWYgKHJlcGVhdCA9PT0gMCkgewogICAgICAgICAgICBnbHlmW2ogLSAxXSBePSA4OwogICAgICAgICAgfQogICAgICAgICAgaSArPSByZXBlYXQ7CiAgICAgICAgICBjb29yZGluYXRlc0xlbmd0aCArPSByZXBlYXQgKiB4eUxlbmd0aDsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGNvb3JkaW5hdGVzTGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIGdseXBoUHJvZmlsZTsKICAgICAgfQogICAgICBsZXQgZ2x5cGhEYXRhTGVuZ3RoID0gaiArIGNvb3JkaW5hdGVzTGVuZ3RoOwogICAgICBpZiAoZ2x5cGhEYXRhTGVuZ3RoID4gZ2x5Zi5sZW5ndGgpIHsKICAgICAgICByZXR1cm4gZ2x5cGhQcm9maWxlOwogICAgICB9CiAgICAgIGlmICghaGludHNWYWxpZCAmJiBpbnN0cnVjdGlvbnNMZW5ndGggPiAwKSB7CiAgICAgICAgZGVzdC5zZXQoZ2x5Zi5zdWJhcnJheSgwLCBpbnN0cnVjdGlvbnNTdGFydCksIGRlc3RTdGFydCk7CiAgICAgICAgZGVzdC5zZXQoWzAsIDBdLCBkZXN0U3RhcnQgKyBpbnN0cnVjdGlvbnNTdGFydCk7CiAgICAgICAgZGVzdC5zZXQoZ2x5Zi5zdWJhcnJheShpbnN0cnVjdGlvbnNFbmQsIGdseXBoRGF0YUxlbmd0aCksIGRlc3RTdGFydCArIGluc3RydWN0aW9uc1N0YXJ0ICsgMik7CiAgICAgICAgZ2x5cGhEYXRhTGVuZ3RoIC09IGluc3RydWN0aW9uc0xlbmd0aDsKICAgICAgICBpZiAoZ2x5Zi5sZW5ndGggLSBnbHlwaERhdGFMZW5ndGggPiAzKSB7CiAgICAgICAgICBnbHlwaERhdGFMZW5ndGggPSBnbHlwaERhdGFMZW5ndGggKyAzICYgfjM7CiAgICAgICAgfQogICAgICAgIGdseXBoUHJvZmlsZS5sZW5ndGggPSBnbHlwaERhdGFMZW5ndGg7CiAgICAgICAgcmV0dXJuIGdseXBoUHJvZmlsZTsKICAgICAgfQogICAgICBpZiAoZ2x5Zi5sZW5ndGggLSBnbHlwaERhdGFMZW5ndGggPiAzKSB7CiAgICAgICAgZ2x5cGhEYXRhTGVuZ3RoID0gZ2x5cGhEYXRhTGVuZ3RoICsgMyAmIH4zOwogICAgICAgIGRlc3Quc2V0KGdseWYuc3ViYXJyYXkoMCwgZ2x5cGhEYXRhTGVuZ3RoKSwgZGVzdFN0YXJ0KTsKICAgICAgICBnbHlwaFByb2ZpbGUubGVuZ3RoID0gZ2x5cGhEYXRhTGVuZ3RoOwogICAgICAgIHJldHVybiBnbHlwaFByb2ZpbGU7CiAgICAgIH0KICAgICAgZGVzdC5zZXQoZ2x5ZiwgZGVzdFN0YXJ0KTsKICAgICAgZ2x5cGhQcm9maWxlLmxlbmd0aCA9IGdseWYubGVuZ3RoOwogICAgICByZXR1cm4gZ2x5cGhQcm9maWxlOwogICAgfQogICAgZnVuY3Rpb24gc2FuaXRpemVIZWFkKGhlYWQsIG51bUdseXBocywgbG9jYUxlbmd0aCkgewogICAgICBjb25zdCBkYXRhID0gaGVhZC5kYXRhOwogICAgICBjb25zdCB2ZXJzaW9uID0gaW50MzIoZGF0YVswXSwgZGF0YVsxXSwgZGF0YVsyXSwgZGF0YVszXSk7CiAgICAgIGlmICh2ZXJzaW9uID4+IDE2ICE9PSAxKSB7CiAgICAgICAgaW5mbygiQXR0ZW1wdGluZyB0byBmaXggaW52YWxpZCB2ZXJzaW9uIGluIGhlYWQgdGFibGU6ICIgKyB2ZXJzaW9uKTsKICAgICAgICBkYXRhWzBdID0gMDsKICAgICAgICBkYXRhWzFdID0gMTsKICAgICAgICBkYXRhWzJdID0gMDsKICAgICAgICBkYXRhWzNdID0gMDsKICAgICAgfQogICAgICBjb25zdCBpbmRleFRvTG9jRm9ybWF0ID0gaW50MTYoZGF0YVs1MF0sIGRhdGFbNTFdKTsKICAgICAgaWYgKGluZGV4VG9Mb2NGb3JtYXQgPCAwIHx8IGluZGV4VG9Mb2NGb3JtYXQgPiAxKSB7CiAgICAgICAgaW5mbygiQXR0ZW1wdGluZyB0byBmaXggaW52YWxpZCBpbmRleFRvTG9jRm9ybWF0IGluIGhlYWQgdGFibGU6ICIgKyBpbmRleFRvTG9jRm9ybWF0KTsKICAgICAgICBjb25zdCBudW1HbHlwaHNQbHVzT25lID0gbnVtR2x5cGhzICsgMTsKICAgICAgICBpZiAobG9jYUxlbmd0aCA9PT0gbnVtR2x5cGhzUGx1c09uZSA8PCAxKSB7CiAgICAgICAgICBkYXRhWzUwXSA9IDA7CiAgICAgICAgICBkYXRhWzUxXSA9IDA7CiAgICAgICAgfSBlbHNlIGlmIChsb2NhTGVuZ3RoID09PSBudW1HbHlwaHNQbHVzT25lIDw8IDIpIHsKICAgICAgICAgIGRhdGFbNTBdID0gMDsKICAgICAgICAgIGRhdGFbNTFdID0gMTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJDb3VsZCBub3QgZml4IGluZGV4VG9Mb2NGb3JtYXQ6ICIgKyBpbmRleFRvTG9jRm9ybWF0KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIHNhbml0aXplR2x5cGhMb2NhdGlvbnMobG9jYSwgZ2x5ZiwgbnVtR2x5cGhzLCBpc0dseXBoTG9jYXRpb25zTG9uZywgaGludHNWYWxpZCwgZHVwRmlyc3RFbnRyeSwgbWF4U2l6ZU9mSW5zdHJ1Y3Rpb25zKSB7CiAgICAgIGxldCBpdGVtU2l6ZSwgaXRlbURlY29kZSwgaXRlbUVuY29kZTsKICAgICAgaWYgKGlzR2x5cGhMb2NhdGlvbnNMb25nKSB7CiAgICAgICAgaXRlbVNpemUgPSA0OwogICAgICAgIGl0ZW1EZWNvZGUgPSBmdW5jdGlvbiBmb250SXRlbURlY29kZUxvbmcoZGF0YSwgb2Zmc2V0KSB7CiAgICAgICAgICByZXR1cm4gZGF0YVtvZmZzZXRdIDw8IDI0IHwgZGF0YVtvZmZzZXQgKyAxXSA8PCAxNiB8IGRhdGFbb2Zmc2V0ICsgMl0gPDwgOCB8IGRhdGFbb2Zmc2V0ICsgM107CiAgICAgICAgfTsKICAgICAgICBpdGVtRW5jb2RlID0gZnVuY3Rpb24gZm9udEl0ZW1FbmNvZGVMb25nKGRhdGEsIG9mZnNldCwgdmFsdWUpIHsKICAgICAgICAgIGRhdGFbb2Zmc2V0XSA9IHZhbHVlID4+PiAyNCAmIDB4ZmY7CiAgICAgICAgICBkYXRhW29mZnNldCArIDFdID0gdmFsdWUgPj4gMTYgJiAweGZmOwogICAgICAgICAgZGF0YVtvZmZzZXQgKyAyXSA9IHZhbHVlID4+IDggJiAweGZmOwogICAgICAgICAgZGF0YVtvZmZzZXQgKyAzXSA9IHZhbHVlICYgMHhmZjsKICAgICAgICB9OwogICAgICB9IGVsc2UgewogICAgICAgIGl0ZW1TaXplID0gMjsKICAgICAgICBpdGVtRGVjb2RlID0gZnVuY3Rpb24gZm9udEl0ZW1EZWNvZGUoZGF0YSwgb2Zmc2V0KSB7CiAgICAgICAgICByZXR1cm4gZGF0YVtvZmZzZXRdIDw8IDkgfCBkYXRhW29mZnNldCArIDFdIDw8IDE7CiAgICAgICAgfTsKICAgICAgICBpdGVtRW5jb2RlID0gZnVuY3Rpb24gZm9udEl0ZW1FbmNvZGUoZGF0YSwgb2Zmc2V0LCB2YWx1ZSkgewogICAgICAgICAgZGF0YVtvZmZzZXRdID0gdmFsdWUgPj4gOSAmIDB4ZmY7CiAgICAgICAgICBkYXRhW29mZnNldCArIDFdID0gdmFsdWUgPj4gMSAmIDB4ZmY7CiAgICAgICAgfTsKICAgICAgfQogICAgICBjb25zdCBudW1HbHlwaHNPdXQgPSBkdXBGaXJzdEVudHJ5ID8gbnVtR2x5cGhzICsgMSA6IG51bUdseXBoczsKICAgICAgY29uc3QgbG9jYURhdGFTaXplID0gaXRlbVNpemUgKiAoMSArIG51bUdseXBoc091dCk7CiAgICAgIGNvbnN0IGxvY2FEYXRhID0gbmV3IFVpbnQ4QXJyYXkobG9jYURhdGFTaXplKTsKICAgICAgbG9jYURhdGEuc2V0KGxvY2EuZGF0YS5zdWJhcnJheSgwLCBsb2NhRGF0YVNpemUpKTsKICAgICAgbG9jYS5kYXRhID0gbG9jYURhdGE7CiAgICAgIGNvbnN0IG9sZEdseWZEYXRhID0gZ2x5Zi5kYXRhOwogICAgICBjb25zdCBvbGRHbHlmRGF0YUxlbmd0aCA9IG9sZEdseWZEYXRhLmxlbmd0aDsKICAgICAgY29uc3QgbmV3R2x5ZkRhdGEgPSBuZXcgVWludDhBcnJheShvbGRHbHlmRGF0YUxlbmd0aCk7CiAgICAgIGxldCBpLCBqOwogICAgICBjb25zdCBsb2NhRW50cmllcyA9IFtdOwogICAgICBmb3IgKGkgPSAwLCBqID0gMDsgaSA8IG51bUdseXBocyArIDE7IGkrKywgaiArPSBpdGVtU2l6ZSkgewogICAgICAgIGxldCBvZmZzZXQgPSBpdGVtRGVjb2RlKGxvY2FEYXRhLCBqKTsKICAgICAgICBpZiAob2Zmc2V0ID4gb2xkR2x5ZkRhdGFMZW5ndGgpIHsKICAgICAgICAgIG9mZnNldCA9IG9sZEdseWZEYXRhTGVuZ3RoOwogICAgICAgIH0KICAgICAgICBsb2NhRW50cmllcy5wdXNoKHsKICAgICAgICAgIGluZGV4OiBpLAogICAgICAgICAgb2Zmc2V0LAogICAgICAgICAgZW5kT2Zmc2V0OiAwCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgbG9jYUVudHJpZXMuc29ydCgoYSwgYikgPT4gYS5vZmZzZXQgLSBiLm9mZnNldCk7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1HbHlwaHM7IGkrKykgewogICAgICAgIGxvY2FFbnRyaWVzW2ldLmVuZE9mZnNldCA9IGxvY2FFbnRyaWVzW2kgKyAxXS5vZmZzZXQ7CiAgICAgIH0KICAgICAgbG9jYUVudHJpZXMuc29ydCgoYSwgYikgPT4gYS5pbmRleCAtIGIuaW5kZXgpOwogICAgICBmb3IgKGkgPSAwOyBpIDwgbnVtR2x5cGhzOyBpKyspIHsKICAgICAgICBjb25zdCB7CiAgICAgICAgICBvZmZzZXQsCiAgICAgICAgICBlbmRPZmZzZXQKICAgICAgICB9ID0gbG9jYUVudHJpZXNbaV07CiAgICAgICAgaWYgKG9mZnNldCAhPT0gMCB8fCBlbmRPZmZzZXQgIT09IDApIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjb25zdCBuZXh0T2Zmc2V0ID0gbG9jYUVudHJpZXNbaSArIDFdLm9mZnNldDsKICAgICAgICBpZiAobmV4dE9mZnNldCA9PT0gMCkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGxvY2FFbnRyaWVzW2ldLmVuZE9mZnNldCA9IG5leHRPZmZzZXQ7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY29uc3QgbGFzdCA9IGxvY2FFbnRyaWVzLmF0KC0yKTsKICAgICAgaWYgKGxhc3Qub2Zmc2V0ICE9PSAwICYmIGxhc3QuZW5kT2Zmc2V0ID09PSAwKSB7CiAgICAgICAgbGFzdC5lbmRPZmZzZXQgPSBvbGRHbHlmRGF0YUxlbmd0aDsKICAgICAgfQogICAgICBjb25zdCBtaXNzaW5nR2x5cGhzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgbGV0IHdyaXRlT2Zmc2V0ID0gMDsKICAgICAgaXRlbUVuY29kZShsb2NhRGF0YSwgMCwgd3JpdGVPZmZzZXQpOwogICAgICBmb3IgKGkgPSAwLCBqID0gaXRlbVNpemU7IGkgPCBudW1HbHlwaHM7IGkrKywgaiArPSBpdGVtU2l6ZSkgewogICAgICAgIGNvbnN0IGdseXBoUHJvZmlsZSA9IHNhbml0aXplR2x5cGgob2xkR2x5ZkRhdGEsIGxvY2FFbnRyaWVzW2ldLm9mZnNldCwgbG9jYUVudHJpZXNbaV0uZW5kT2Zmc2V0LCBuZXdHbHlmRGF0YSwgd3JpdGVPZmZzZXQsIGhpbnRzVmFsaWQpOwogICAgICAgIGNvbnN0IG5ld0xlbmd0aCA9IGdseXBoUHJvZmlsZS5sZW5ndGg7CiAgICAgICAgaWYgKG5ld0xlbmd0aCA9PT0gMCkgewogICAgICAgICAgbWlzc2luZ0dseXBoc1tpXSA9IHRydWU7CiAgICAgICAgfQogICAgICAgIGlmIChnbHlwaFByb2ZpbGUuc2l6ZU9mSW5zdHJ1Y3Rpb25zID4gbWF4U2l6ZU9mSW5zdHJ1Y3Rpb25zKSB7CiAgICAgICAgICBtYXhTaXplT2ZJbnN0cnVjdGlvbnMgPSBnbHlwaFByb2ZpbGUuc2l6ZU9mSW5zdHJ1Y3Rpb25zOwogICAgICAgIH0KICAgICAgICB3cml0ZU9mZnNldCArPSBuZXdMZW5ndGg7CiAgICAgICAgaXRlbUVuY29kZShsb2NhRGF0YSwgaiwgd3JpdGVPZmZzZXQpOwogICAgICB9CiAgICAgIGlmICh3cml0ZU9mZnNldCA9PT0gMCkgewogICAgICAgIGNvbnN0IHNpbXBsZUdseXBoID0gbmV3IFVpbnQ4QXJyYXkoWzAsIDEsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIDQ5LCAwXSk7CiAgICAgICAgZm9yIChpID0gMCwgaiA9IGl0ZW1TaXplOyBpIDwgbnVtR2x5cGhzT3V0OyBpKyssIGogKz0gaXRlbVNpemUpIHsKICAgICAgICAgIGl0ZW1FbmNvZGUobG9jYURhdGEsIGosIHNpbXBsZUdseXBoLmxlbmd0aCk7CiAgICAgICAgfQogICAgICAgIGdseWYuZGF0YSA9IHNpbXBsZUdseXBoOwogICAgICB9IGVsc2UgaWYgKGR1cEZpcnN0RW50cnkpIHsKICAgICAgICBjb25zdCBmaXJzdEVudHJ5TGVuZ3RoID0gaXRlbURlY29kZShsb2NhRGF0YSwgaXRlbVNpemUpOwogICAgICAgIGlmIChuZXdHbHlmRGF0YS5sZW5ndGggPiBmaXJzdEVudHJ5TGVuZ3RoICsgd3JpdGVPZmZzZXQpIHsKICAgICAgICAgIGdseWYuZGF0YSA9IG5ld0dseWZEYXRhLnN1YmFycmF5KDAsIGZpcnN0RW50cnlMZW5ndGggKyB3cml0ZU9mZnNldCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGdseWYuZGF0YSA9IG5ldyBVaW50OEFycmF5KGZpcnN0RW50cnlMZW5ndGggKyB3cml0ZU9mZnNldCk7CiAgICAgICAgICBnbHlmLmRhdGEuc2V0KG5ld0dseWZEYXRhLnN1YmFycmF5KDAsIHdyaXRlT2Zmc2V0KSk7CiAgICAgICAgfQogICAgICAgIGdseWYuZGF0YS5zZXQobmV3R2x5ZkRhdGEuc3ViYXJyYXkoMCwgZmlyc3RFbnRyeUxlbmd0aCksIHdyaXRlT2Zmc2V0KTsKICAgICAgICBpdGVtRW5jb2RlKGxvY2EuZGF0YSwgbG9jYURhdGEubGVuZ3RoIC0gaXRlbVNpemUsIHdyaXRlT2Zmc2V0ICsgZmlyc3RFbnRyeUxlbmd0aCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZ2x5Zi5kYXRhID0gbmV3R2x5ZkRhdGEuc3ViYXJyYXkoMCwgd3JpdGVPZmZzZXQpOwogICAgICB9CiAgICAgIHJldHVybiB7CiAgICAgICAgbWlzc2luZ0dseXBocywKICAgICAgICBtYXhTaXplT2ZJbnN0cnVjdGlvbnMKICAgICAgfTsKICAgIH0KICAgIGZ1bmN0aW9uIHJlYWRQb3N0U2NyaXB0VGFibGUocG9zdCwgcHJvcGVydGllc09iaiwgbWF4cE51bUdseXBocykgewogICAgICBjb25zdCBzdGFydCA9IChmb250LnN0YXJ0IHx8IDApICsgcG9zdC5vZmZzZXQ7CiAgICAgIGZvbnQucG9zID0gc3RhcnQ7CiAgICAgIGNvbnN0IGxlbmd0aCA9IHBvc3QubGVuZ3RoLAogICAgICAgIGVuZCA9IHN0YXJ0ICsgbGVuZ3RoOwogICAgICBjb25zdCB2ZXJzaW9uID0gZm9udC5nZXRJbnQzMigpOwogICAgICBmb250LnNraXAoMjgpOwogICAgICBsZXQgZ2x5cGhOYW1lczsKICAgICAgbGV0IHZhbGlkID0gdHJ1ZTsKICAgICAgbGV0IGk7CiAgICAgIHN3aXRjaCAodmVyc2lvbikgewogICAgICAgIGNhc2UgMHgwMDAxMDAwMDoKICAgICAgICAgIGdseXBoTmFtZXMgPSBNYWNTdGFuZGFyZEdseXBoT3JkZXJpbmc7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4MDAwMjAwMDA6CiAgICAgICAgICBjb25zdCBudW1HbHlwaHMgPSBmb250LmdldFVpbnQxNigpOwogICAgICAgICAgaWYgKG51bUdseXBocyAhPT0gbWF4cE51bUdseXBocykgewogICAgICAgICAgICB2YWxpZCA9IGZhbHNlOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGdseXBoTmFtZUluZGV4ZXMgPSBbXTsKICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1HbHlwaHM7ICsraSkgewogICAgICAgICAgICBjb25zdCBpbmRleCA9IGZvbnQuZ2V0VWludDE2KCk7CiAgICAgICAgICAgIGlmIChpbmRleCA+PSAzMjc2OCkgewogICAgICAgICAgICAgIHZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZ2x5cGhOYW1lSW5kZXhlcy5wdXNoKGluZGV4KTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICghdmFsaWQpIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBjdXN0b21OYW1lcyA9IFtdLAogICAgICAgICAgICBzdHJCdWYgPSBbXTsKICAgICAgICAgIHdoaWxlIChmb250LnBvcyA8IGVuZCkgewogICAgICAgICAgICBjb25zdCBzdHJpbmdMZW5ndGggPSBmb250LmdldEJ5dGUoKTsKICAgICAgICAgICAgc3RyQnVmLmxlbmd0aCA9IHN0cmluZ0xlbmd0aDsKICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHN0cmluZ0xlbmd0aDsgKytpKSB7CiAgICAgICAgICAgICAgc3RyQnVmW2ldID0gU3RyaW5nLmZyb21DaGFyQ29kZShmb250LmdldEJ5dGUoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY3VzdG9tTmFtZXMucHVzaChzdHJCdWYuam9pbigiIikpOwogICAgICAgICAgfQogICAgICAgICAgZ2x5cGhOYW1lcyA9IFtdOwogICAgICAgICAgZm9yIChpID0gMDsgaSA8IG51bUdseXBoczsgKytpKSB7CiAgICAgICAgICAgIGNvbnN0IGogPSBnbHlwaE5hbWVJbmRleGVzW2ldOwogICAgICAgICAgICBpZiAoaiA8IDI1OCkgewogICAgICAgICAgICAgIGdseXBoTmFtZXMucHVzaChNYWNTdGFuZGFyZEdseXBoT3JkZXJpbmdbal0pOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGdseXBoTmFtZXMucHVzaChjdXN0b21OYW1lc1tqIC0gMjU4XSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDB4MDAwMzAwMDA6CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgd2FybigiVW5rbm93bi91bnN1cHBvcnRlZCBwb3N0IHRhYmxlIHZlcnNpb24gIiArIHZlcnNpb24pOwogICAgICAgICAgdmFsaWQgPSBmYWxzZTsKICAgICAgICAgIGlmIChwcm9wZXJ0aWVzT2JqLmRlZmF1bHRFbmNvZGluZykgewogICAgICAgICAgICBnbHlwaE5hbWVzID0gcHJvcGVydGllc09iai5kZWZhdWx0RW5jb2Rpbmc7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBwcm9wZXJ0aWVzT2JqLmdseXBoTmFtZXMgPSBnbHlwaE5hbWVzOwogICAgICByZXR1cm4gdmFsaWQ7CiAgICB9CiAgICBmdW5jdGlvbiByZWFkTmFtZVRhYmxlKG5hbWVUYWJsZSkgewogICAgICBjb25zdCBzdGFydCA9IChmb250LnN0YXJ0IHx8IDApICsgbmFtZVRhYmxlLm9mZnNldDsKICAgICAgZm9udC5wb3MgPSBzdGFydDsKICAgICAgY29uc3QgbmFtZXMgPSBbW10sIFtdXSwKICAgICAgICByZWNvcmRzID0gW107CiAgICAgIGNvbnN0IGxlbmd0aCA9IG5hbWVUYWJsZS5sZW5ndGgsCiAgICAgICAgZW5kID0gc3RhcnQgKyBsZW5ndGg7CiAgICAgIGNvbnN0IGZvcm1hdCA9IGZvbnQuZ2V0VWludDE2KCk7CiAgICAgIGNvbnN0IEZPUk1BVF8wX0hFQURFUl9MRU5HVEggPSA2OwogICAgICBpZiAoZm9ybWF0ICE9PSAwIHx8IGxlbmd0aCA8IEZPUk1BVF8wX0hFQURFUl9MRU5HVEgpIHsKICAgICAgICByZXR1cm4gW25hbWVzLCByZWNvcmRzXTsKICAgICAgfQogICAgICBjb25zdCBudW1SZWNvcmRzID0gZm9udC5nZXRVaW50MTYoKTsKICAgICAgY29uc3Qgc3RyaW5nc1N0YXJ0ID0gZm9udC5nZXRVaW50MTYoKTsKICAgICAgY29uc3QgTkFNRV9SRUNPUkRfTEVOR1RIID0gMTI7CiAgICAgIGxldCBpLCBpaTsKICAgICAgZm9yIChpID0gMDsgaSA8IG51bVJlY29yZHMgJiYgZm9udC5wb3MgKyBOQU1FX1JFQ09SRF9MRU5HVEggPD0gZW5kOyBpKyspIHsKICAgICAgICBjb25zdCByID0gewogICAgICAgICAgcGxhdGZvcm06IGZvbnQuZ2V0VWludDE2KCksCiAgICAgICAgICBlbmNvZGluZzogZm9udC5nZXRVaW50MTYoKSwKICAgICAgICAgIGxhbmd1YWdlOiBmb250LmdldFVpbnQxNigpLAogICAgICAgICAgbmFtZTogZm9udC5nZXRVaW50MTYoKSwKICAgICAgICAgIGxlbmd0aDogZm9udC5nZXRVaW50MTYoKSwKICAgICAgICAgIG9mZnNldDogZm9udC5nZXRVaW50MTYoKQogICAgICAgIH07CiAgICAgICAgaWYgKGlzTWFjTmFtZVJlY29yZChyKSB8fCBpc1dpbk5hbWVSZWNvcmQocikpIHsKICAgICAgICAgIHJlY29yZHMucHVzaChyKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgZm9yIChpID0gMCwgaWkgPSByZWNvcmRzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBjb25zdCByZWNvcmQgPSByZWNvcmRzW2ldOwogICAgICAgIGlmIChyZWNvcmQubGVuZ3RoIDw9IDApIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBwb3MgPSBzdGFydCArIHN0cmluZ3NTdGFydCArIHJlY29yZC5vZmZzZXQ7CiAgICAgICAgaWYgKHBvcyArIHJlY29yZC5sZW5ndGggPiBlbmQpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBmb250LnBvcyA9IHBvczsKICAgICAgICBjb25zdCBuYW1lSW5kZXggPSByZWNvcmQubmFtZTsKICAgICAgICBpZiAocmVjb3JkLmVuY29kaW5nKSB7CiAgICAgICAgICBsZXQgc3RyID0gIiI7CiAgICAgICAgICBmb3IgKGxldCBqID0gMCwgamogPSByZWNvcmQubGVuZ3RoOyBqIDwgamo7IGogKz0gMikgewogICAgICAgICAgICBzdHIgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShmb250LmdldFVpbnQxNigpKTsKICAgICAgICAgIH0KICAgICAgICAgIG5hbWVzWzFdW25hbWVJbmRleF0gPSBzdHI7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG5hbWVzWzBdW25hbWVJbmRleF0gPSBmb250LmdldFN0cmluZyhyZWNvcmQubGVuZ3RoKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIFtuYW1lcywgcmVjb3Jkc107CiAgICB9CiAgICBjb25zdCBUVE9wc1N0YWNrRGVsdGFzID0gWzAsIDAsIDAsIDAsIDAsIDAsIDAsIDAsIC0yLCAtMiwgLTIsIC0yLCAwLCAwLCAtMiwgLTUsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgMCwgMCwgLTEsIDAsIC0xLCAtMSwgLTEsIC0xLCAxLCAtMSwgLTk5OSwgMCwgMSwgMCwgLTEsIC0yLCAwLCAtMSwgLTIsIC0xLCAtMSwgMCwgLTEsIC0xLCAwLCAwLCAtOTk5LCAtOTk5LCAtMSwgLTEsIC0xLCAtMSwgLTIsIC05OTksIC0yLCAtMiwgLTk5OSwgMCwgLTIsIC0yLCAwLCAwLCAtMiwgMCwgLTIsIDAsIDAsIDAsIC0yLCAtMSwgLTEsIDEsIDEsIDAsIDAsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAwLCAwLCAtMSwgMCwgLTEsIC0xLCAwLCAtOTk5LCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAwLCAtMiwgLTk5OSwgLTk5OSwgLTk5OSwgLTk5OSwgLTk5OSwgLTEsIC0xLCAtMiwgLTIsIDAsIDAsIDAsIDAsIC0xLCAtMSwgLTk5OSwgLTIsIC0yLCAwLCAwLCAtMSwgLTIsIC0yLCAwLCAwLCAwLCAtMSwgLTEsIC0xLCAtMl07CiAgICBmdW5jdGlvbiBzYW5pdGl6ZVRUUHJvZ3JhbSh0YWJsZSwgdHRDb250ZXh0KSB7CiAgICAgIGxldCBkYXRhID0gdGFibGUuZGF0YTsKICAgICAgbGV0IGkgPSAwLAogICAgICAgIGosCiAgICAgICAgbiwKICAgICAgICBiLAogICAgICAgIGZ1bmNJZCwKICAgICAgICBwYywKICAgICAgICBsYXN0RW5kZiA9IDAsCiAgICAgICAgbGFzdERlZmYgPSAwOwogICAgICBjb25zdCBzdGFjayA9IFtdOwogICAgICBjb25zdCBjYWxsc3RhY2sgPSBbXTsKICAgICAgY29uc3QgZnVuY3Rpb25zQ2FsbGVkID0gW107CiAgICAgIGxldCB0b29Db21wbGV4VG9Gb2xsb3dGdW5jdGlvbnMgPSB0dENvbnRleHQudG9vQ29tcGxleFRvRm9sbG93RnVuY3Rpb25zOwogICAgICBsZXQgaW5GREVGID0gZmFsc2UsCiAgICAgICAgaWZMZXZlbCA9IDAsCiAgICAgICAgaW5FTFNFID0gMDsKICAgICAgZm9yIChsZXQgaWkgPSBkYXRhLmxlbmd0aDsgaSA8IGlpOykgewogICAgICAgIGNvbnN0IG9wID0gZGF0YVtpKytdOwogICAgICAgIGlmIChvcCA9PT0gMHg0MCkgewogICAgICAgICAgbiA9IGRhdGFbaSsrXTsKICAgICAgICAgIGlmIChpbkZERUYgfHwgaW5FTFNFKSB7CiAgICAgICAgICAgIGkgKz0gbjsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBuOyBqKyspIHsKICAgICAgICAgICAgICBzdGFjay5wdXNoKGRhdGFbaSsrXSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKG9wID09PSAweDQxKSB7CiAgICAgICAgICBuID0gZGF0YVtpKytdOwogICAgICAgICAgaWYgKGluRkRFRiB8fCBpbkVMU0UpIHsKICAgICAgICAgICAgaSArPSBuICogMjsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBuOyBqKyspIHsKICAgICAgICAgICAgICBiID0gZGF0YVtpKytdOwogICAgICAgICAgICAgIHN0YWNrLnB1c2goYiA8PCA4IHwgZGF0YVtpKytdKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoKG9wICYgMHhmOCkgPT09IDB4YjApIHsKICAgICAgICAgIG4gPSBvcCAtIDB4YjAgKyAxOwogICAgICAgICAgaWYgKGluRkRFRiB8fCBpbkVMU0UpIHsKICAgICAgICAgICAgaSArPSBuOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8IG47IGorKykgewogICAgICAgICAgICAgIHN0YWNrLnB1c2goZGF0YVtpKytdKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoKG9wICYgMHhmOCkgPT09IDB4YjgpIHsKICAgICAgICAgIG4gPSBvcCAtIDB4YjggKyAxOwogICAgICAgICAgaWYgKGluRkRFRiB8fCBpbkVMU0UpIHsKICAgICAgICAgICAgaSArPSBuICogMjsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGZvciAoaiA9IDA7IGogPCBuOyBqKyspIHsKICAgICAgICAgICAgICBiID0gZGF0YVtpKytdOwogICAgICAgICAgICAgIHN0YWNrLnB1c2goc2lnbmVkSW50MTYoYiwgZGF0YVtpKytdKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKG9wID09PSAweDJiICYmICF0b29Db21wbGV4VG9Gb2xsb3dGdW5jdGlvbnMpIHsKICAgICAgICAgIGlmICghaW5GREVGICYmICFpbkVMU0UpIHsKICAgICAgICAgICAgZnVuY0lkID0gc3RhY2suYXQoLTEpOwogICAgICAgICAgICBpZiAoaXNOYU4oZnVuY0lkKSkgewogICAgICAgICAgICAgIGluZm8oIlRUOiBDQUxMIGVtcHR5IHN0YWNrIChvciBpbnZhbGlkIGVudHJ5KS4iKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB0dENvbnRleHQuZnVuY3Rpb25zVXNlZFtmdW5jSWRdID0gdHJ1ZTsKICAgICAgICAgICAgICBpZiAoZnVuY0lkIGluIHR0Q29udGV4dC5mdW5jdGlvbnNTdGFja0RlbHRhcykgewogICAgICAgICAgICAgICAgY29uc3QgbmV3U3RhY2tMZW5ndGggPSBzdGFjay5sZW5ndGggKyB0dENvbnRleHQuZnVuY3Rpb25zU3RhY2tEZWx0YXNbZnVuY0lkXTsKICAgICAgICAgICAgICAgIGlmIChuZXdTdGFja0xlbmd0aCA8IDApIHsKICAgICAgICAgICAgICAgICAgd2FybigiVFQ6IENBTEwgaW52YWxpZCBmdW5jdGlvbnMgc3RhY2sgZGVsdGEuIik7CiAgICAgICAgICAgICAgICAgIHR0Q29udGV4dC5oaW50c1ZhbGlkID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHN0YWNrLmxlbmd0aCA9IG5ld1N0YWNrTGVuZ3RoOwogICAgICAgICAgICAgIH0gZWxzZSBpZiAoZnVuY0lkIGluIHR0Q29udGV4dC5mdW5jdGlvbnNEZWZpbmVkICYmICFmdW5jdGlvbnNDYWxsZWQuaW5jbHVkZXMoZnVuY0lkKSkgewogICAgICAgICAgICAgICAgY2FsbHN0YWNrLnB1c2goewogICAgICAgICAgICAgICAgICBkYXRhLAogICAgICAgICAgICAgICAgICBpLAogICAgICAgICAgICAgICAgICBzdGFja1RvcDogc3RhY2subGVuZ3RoIC0gMQogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICBmdW5jdGlvbnNDYWxsZWQucHVzaChmdW5jSWQpOwogICAgICAgICAgICAgICAgcGMgPSB0dENvbnRleHQuZnVuY3Rpb25zRGVmaW5lZFtmdW5jSWRdOwogICAgICAgICAgICAgICAgaWYgKCFwYykgewogICAgICAgICAgICAgICAgICB3YXJuKCJUVDogQ0FMTCBub24tZXhpc3RlbnQgZnVuY3Rpb24iKTsKICAgICAgICAgICAgICAgICAgdHRDb250ZXh0LmhpbnRzVmFsaWQgPSBmYWxzZTsKICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZGF0YSA9IHBjLmRhdGE7CiAgICAgICAgICAgICAgICBpID0gcGMuaTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKG9wID09PSAweDJjICYmICF0b29Db21wbGV4VG9Gb2xsb3dGdW5jdGlvbnMpIHsKICAgICAgICAgIGlmIChpbkZERUYgfHwgaW5FTFNFKSB7CiAgICAgICAgICAgIHdhcm4oIlRUOiBuZXN0ZWQgRkRFRnMgbm90IGFsbG93ZWQiKTsKICAgICAgICAgICAgdG9vQ29tcGxleFRvRm9sbG93RnVuY3Rpb25zID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICAgIGluRkRFRiA9IHRydWU7CiAgICAgICAgICBsYXN0RGVmZiA9IGk7CiAgICAgICAgICBmdW5jSWQgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHR0Q29udGV4dC5mdW5jdGlvbnNEZWZpbmVkW2Z1bmNJZF0gPSB7CiAgICAgICAgICAgIGRhdGEsCiAgICAgICAgICAgIGkKICAgICAgICAgIH07CiAgICAgICAgfSBlbHNlIGlmIChvcCA9PT0gMHgyZCkgewogICAgICAgICAgaWYgKGluRkRFRikgewogICAgICAgICAgICBpbkZERUYgPSBmYWxzZTsKICAgICAgICAgICAgbGFzdEVuZGYgPSBpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcGMgPSBjYWxsc3RhY2sucG9wKCk7CiAgICAgICAgICAgIGlmICghcGMpIHsKICAgICAgICAgICAgICB3YXJuKCJUVDogRU5ERiBiYWQgc3RhY2siKTsKICAgICAgICAgICAgICB0dENvbnRleHQuaGludHNWYWxpZCA9IGZhbHNlOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBmdW5jSWQgPSBmdW5jdGlvbnNDYWxsZWQucG9wKCk7CiAgICAgICAgICAgIGRhdGEgPSBwYy5kYXRhOwogICAgICAgICAgICBpID0gcGMuaTsKICAgICAgICAgICAgdHRDb250ZXh0LmZ1bmN0aW9uc1N0YWNrRGVsdGFzW2Z1bmNJZF0gPSBzdGFjay5sZW5ndGggLSBwYy5zdGFja1RvcDsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKG9wID09PSAweDg5KSB7CiAgICAgICAgICBpZiAoaW5GREVGIHx8IGluRUxTRSkgewogICAgICAgICAgICB3YXJuKCJUVDogbmVzdGVkIElERUZzIG5vdCBhbGxvd2VkIik7CiAgICAgICAgICAgIHRvb0NvbXBsZXhUb0ZvbGxvd0Z1bmN0aW9ucyA9IHRydWU7CiAgICAgICAgICB9CiAgICAgICAgICBpbkZERUYgPSB0cnVlOwogICAgICAgICAgbGFzdERlZmYgPSBpOwogICAgICAgIH0gZWxzZSBpZiAob3AgPT09IDB4NTgpIHsKICAgICAgICAgICsraWZMZXZlbDsKICAgICAgICB9IGVsc2UgaWYgKG9wID09PSAweDFiKSB7CiAgICAgICAgICBpbkVMU0UgPSBpZkxldmVsOwogICAgICAgIH0gZWxzZSBpZiAob3AgPT09IDB4NTkpIHsKICAgICAgICAgIGlmIChpbkVMU0UgPT09IGlmTGV2ZWwpIHsKICAgICAgICAgICAgaW5FTFNFID0gMDsKICAgICAgICAgIH0KICAgICAgICAgIC0taWZMZXZlbDsKICAgICAgICB9IGVsc2UgaWYgKG9wID09PSAweDFjKSB7CiAgICAgICAgICBpZiAoIWluRkRFRiAmJiAhaW5FTFNFKSB7CiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IHN0YWNrLmF0KC0xKTsKICAgICAgICAgICAgaWYgKG9mZnNldCA+IDApIHsKICAgICAgICAgICAgICBpICs9IG9mZnNldCAtIDE7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKCFpbkZERUYgJiYgIWluRUxTRSkgewogICAgICAgICAgbGV0IHN0YWNrRGVsdGEgPSAwOwogICAgICAgICAgaWYgKG9wIDw9IDB4OGUpIHsKICAgICAgICAgICAgc3RhY2tEZWx0YSA9IFRUT3BzU3RhY2tEZWx0YXNbb3BdOwogICAgICAgICAgfSBlbHNlIGlmIChvcCA+PSAweGMwICYmIG9wIDw9IDB4ZGYpIHsKICAgICAgICAgICAgc3RhY2tEZWx0YSA9IC0xOwogICAgICAgICAgfSBlbHNlIGlmIChvcCA+PSAweGUwKSB7CiAgICAgICAgICAgIHN0YWNrRGVsdGEgPSAtMjsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChvcCA+PSAweDcxICYmIG9wIDw9IDB4NzUpIHsKICAgICAgICAgICAgbiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgICBpZiAoIWlzTmFOKG4pKSB7CiAgICAgICAgICAgICAgc3RhY2tEZWx0YSA9IC1uICogMjsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgd2hpbGUgKHN0YWNrRGVsdGEgPCAwICYmIHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgc3RhY2sucG9wKCk7CiAgICAgICAgICAgIHN0YWNrRGVsdGErKzsKICAgICAgICAgIH0KICAgICAgICAgIHdoaWxlIChzdGFja0RlbHRhID4gMCkgewogICAgICAgICAgICBzdGFjay5wdXNoKE5hTik7CiAgICAgICAgICAgIHN0YWNrRGVsdGEtLTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgdHRDb250ZXh0LnRvb0NvbXBsZXhUb0ZvbGxvd0Z1bmN0aW9ucyA9IHRvb0NvbXBsZXhUb0ZvbGxvd0Z1bmN0aW9uczsKICAgICAgY29uc3QgY29udGVudCA9IFtkYXRhXTsKICAgICAgaWYgKGkgPiBkYXRhLmxlbmd0aCkgewogICAgICAgIGNvbnRlbnQucHVzaChuZXcgVWludDhBcnJheShpIC0gZGF0YS5sZW5ndGgpKTsKICAgICAgfQogICAgICBpZiAobGFzdERlZmYgPiBsYXN0RW5kZikgewogICAgICAgIHdhcm4oIlRUOiBjb21wbGVtZW50aW5nIGEgbWlzc2luZyBmdW5jdGlvbiB0YWlsIik7CiAgICAgICAgY29udGVudC5wdXNoKG5ldyBVaW50OEFycmF5KFsweDIyLCAweDJkXSkpOwogICAgICB9CiAgICAgIGZvbGRUVFRhYmxlKHRhYmxlLCBjb250ZW50KTsKICAgIH0KICAgIGZ1bmN0aW9uIGNoZWNrSW52YWxpZEZ1bmN0aW9ucyh0dENvbnRleHQsIG1heEZ1bmN0aW9uRGVmcykgewogICAgICBpZiAodHRDb250ZXh0LnRvb0NvbXBsZXhUb0ZvbGxvd0Z1bmN0aW9ucykgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBpZiAodHRDb250ZXh0LmZ1bmN0aW9uc0RlZmluZWQubGVuZ3RoID4gbWF4RnVuY3Rpb25EZWZzKSB7CiAgICAgICAgd2FybigiVFQ6IG1vcmUgZnVuY3Rpb25zIGRlZmluZWQgdGhhbiBleHBlY3RlZCIpOwogICAgICAgIHR0Q29udGV4dC5oaW50c1ZhbGlkID0gZmFsc2U7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGZvciAobGV0IGogPSAwLCBqaiA9IHR0Q29udGV4dC5mdW5jdGlvbnNVc2VkLmxlbmd0aDsgaiA8IGpqOyBqKyspIHsKICAgICAgICBpZiAoaiA+IG1heEZ1bmN0aW9uRGVmcykgewogICAgICAgICAgd2FybigiVFQ6IGludmFsaWQgZnVuY3Rpb24gaWQ6ICIgKyBqKTsKICAgICAgICAgIHR0Q29udGV4dC5oaW50c1ZhbGlkID0gZmFsc2U7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGlmICh0dENvbnRleHQuZnVuY3Rpb25zVXNlZFtqXSAmJiAhdHRDb250ZXh0LmZ1bmN0aW9uc0RlZmluZWRbal0pIHsKICAgICAgICAgIHdhcm4oIlRUOiB1bmRlZmluZWQgZnVuY3Rpb246ICIgKyBqKTsKICAgICAgICAgIHR0Q29udGV4dC5oaW50c1ZhbGlkID0gZmFsc2U7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBmb2xkVFRUYWJsZSh0YWJsZSwgY29udGVudCkgewogICAgICBpZiAoY29udGVudC5sZW5ndGggPiAxKSB7CiAgICAgICAgbGV0IG5ld0xlbmd0aCA9IDA7CiAgICAgICAgbGV0IGosIGpqOwogICAgICAgIGZvciAoaiA9IDAsIGpqID0gY29udGVudC5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgICAgICBuZXdMZW5ndGggKz0gY29udGVudFtqXS5sZW5ndGg7CiAgICAgICAgfQogICAgICAgIG5ld0xlbmd0aCA9IG5ld0xlbmd0aCArIDMgJiB+MzsKICAgICAgICBjb25zdCByZXN1bHQgPSBuZXcgVWludDhBcnJheShuZXdMZW5ndGgpOwogICAgICAgIGxldCBwb3MgPSAwOwogICAgICAgIGZvciAoaiA9IDAsIGpqID0gY29udGVudC5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgICAgICByZXN1bHQuc2V0KGNvbnRlbnRbal0sIHBvcyk7CiAgICAgICAgICBwb3MgKz0gY29udGVudFtqXS5sZW5ndGg7CiAgICAgICAgfQogICAgICAgIHRhYmxlLmRhdGEgPSByZXN1bHQ7CiAgICAgICAgdGFibGUubGVuZ3RoID0gbmV3TGVuZ3RoOwogICAgICB9CiAgICB9CiAgICBmdW5jdGlvbiBzYW5pdGl6ZVRUUHJvZ3JhbXMoZnBnbSwgcHJlcCwgY3Z0LCBtYXhGdW5jdGlvbkRlZnMpIHsKICAgICAgY29uc3QgdHRDb250ZXh0ID0gewogICAgICAgIGZ1bmN0aW9uc0RlZmluZWQ6IFtdLAogICAgICAgIGZ1bmN0aW9uc1VzZWQ6IFtdLAogICAgICAgIGZ1bmN0aW9uc1N0YWNrRGVsdGFzOiBbXSwKICAgICAgICB0b29Db21wbGV4VG9Gb2xsb3dGdW5jdGlvbnM6IGZhbHNlLAogICAgICAgIGhpbnRzVmFsaWQ6IHRydWUKICAgICAgfTsKICAgICAgaWYgKGZwZ20pIHsKICAgICAgICBzYW5pdGl6ZVRUUHJvZ3JhbShmcGdtLCB0dENvbnRleHQpOwogICAgICB9CiAgICAgIGlmIChwcmVwKSB7CiAgICAgICAgc2FuaXRpemVUVFByb2dyYW0ocHJlcCwgdHRDb250ZXh0KTsKICAgICAgfQogICAgICBpZiAoZnBnbSkgewogICAgICAgIGNoZWNrSW52YWxpZEZ1bmN0aW9ucyh0dENvbnRleHQsIG1heEZ1bmN0aW9uRGVmcyk7CiAgICAgIH0KICAgICAgaWYgKGN2dCAmJiBjdnQubGVuZ3RoICYgMSkgewogICAgICAgIGNvbnN0IGN2dERhdGEgPSBuZXcgVWludDhBcnJheShjdnQubGVuZ3RoICsgMSk7CiAgICAgICAgY3Z0RGF0YS5zZXQoY3Z0LmRhdGEpOwogICAgICAgIGN2dC5kYXRhID0gY3Z0RGF0YTsKICAgICAgfQogICAgICByZXR1cm4gdHRDb250ZXh0LmhpbnRzVmFsaWQ7CiAgICB9CiAgICBmb250ID0gbmV3IFN0cmVhbShuZXcgVWludDhBcnJheShmb250LmdldEJ5dGVzKCkpKTsKICAgIGxldCBoZWFkZXIsIHRhYmxlczsKICAgIGlmIChpc1RydWVUeXBlQ29sbGVjdGlvbkZpbGUoZm9udCkpIHsKICAgICAgY29uc3QgdHRjRGF0YSA9IHJlYWRUcnVlVHlwZUNvbGxlY3Rpb25EYXRhKGZvbnQsIHRoaXMubmFtZSk7CiAgICAgIGhlYWRlciA9IHR0Y0RhdGEuaGVhZGVyOwogICAgICB0YWJsZXMgPSB0dGNEYXRhLnRhYmxlczsKICAgIH0gZWxzZSB7CiAgICAgIGhlYWRlciA9IHJlYWRPcGVuVHlwZUhlYWRlcihmb250KTsKICAgICAgdGFibGVzID0gcmVhZFRhYmxlcyhmb250LCBoZWFkZXIubnVtVGFibGVzKTsKICAgIH0KICAgIGxldCBjZmYsIGNmZkZpbGU7CiAgICBjb25zdCBpc1RydWVUeXBlID0gIXRhYmxlc1siQ0ZGICJdOwogICAgaWYgKCFpc1RydWVUeXBlKSB7CiAgICAgIGNvbnN0IGlzQ29tcG9zaXRlID0gcHJvcGVydGllcy5jb21wb3NpdGUgJiYgKHByb3BlcnRpZXMuY2lkVG9HaWRNYXA/Lmxlbmd0aCA+IDAgfHwgIShwcm9wZXJ0aWVzLmNNYXAgaW5zdGFuY2VvZiBJZGVudGl0eUNNYXApKTsKICAgICAgaWYgKGhlYWRlci52ZXJzaW9uID09PSAiT1RUTyIgJiYgIWlzQ29tcG9zaXRlIHx8ICF0YWJsZXMuaGVhZCB8fCAhdGFibGVzLmhoZWEgfHwgIXRhYmxlcy5tYXhwIHx8ICF0YWJsZXMucG9zdCkgewogICAgICAgIGNmZkZpbGUgPSBuZXcgU3RyZWFtKHRhYmxlc1siQ0ZGICJdLmRhdGEpOwogICAgICAgIGNmZiA9IG5ldyBDRkZGb250KGNmZkZpbGUsIHByb3BlcnRpZXMpOwogICAgICAgIHJldHVybiB0aGlzLmNvbnZlcnQobmFtZSwgY2ZmLCBwcm9wZXJ0aWVzKTsKICAgICAgfQogICAgICBkZWxldGUgdGFibGVzLmdseWY7CiAgICAgIGRlbGV0ZSB0YWJsZXMubG9jYTsKICAgICAgZGVsZXRlIHRhYmxlcy5mcGdtOwogICAgICBkZWxldGUgdGFibGVzLnByZXA7CiAgICAgIGRlbGV0ZSB0YWJsZXNbImN2dCAiXTsKICAgICAgdGhpcy5pc09wZW5UeXBlID0gdHJ1ZTsKICAgIH0gZWxzZSB7CiAgICAgIGlmICghdGFibGVzLmxvY2EpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoJ1JlcXVpcmVkICJsb2NhIiB0YWJsZSBpcyBub3QgZm91bmQnKTsKICAgICAgfQogICAgICBpZiAoIXRhYmxlcy5nbHlmKSB7CiAgICAgICAgd2FybignUmVxdWlyZWQgImdseWYiIHRhYmxlIGlzIG5vdCBmb3VuZCAtLSB0cnlpbmcgdG8gcmVjb3Zlci4nKTsKICAgICAgICB0YWJsZXMuZ2x5ZiA9IHsKICAgICAgICAgIHRhZzogImdseWYiLAogICAgICAgICAgZGF0YTogbmV3IFVpbnQ4QXJyYXkoMCkKICAgICAgICB9OwogICAgICB9CiAgICAgIHRoaXMuaXNPcGVuVHlwZSA9IGZhbHNlOwogICAgfQogICAgaWYgKCF0YWJsZXMubWF4cCkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoJ1JlcXVpcmVkICJtYXhwIiB0YWJsZSBpcyBub3QgZm91bmQnKTsKICAgIH0KICAgIGZvbnQucG9zID0gKGZvbnQuc3RhcnQgfHwgMCkgKyB0YWJsZXMubWF4cC5vZmZzZXQ7CiAgICBsZXQgdmVyc2lvbiA9IGZvbnQuZ2V0SW50MzIoKTsKICAgIGNvbnN0IG51bUdseXBocyA9IGZvbnQuZ2V0VWludDE2KCk7CiAgICBpZiAodmVyc2lvbiAhPT0gMHgwMDAxMDAwMCAmJiB2ZXJzaW9uICE9PSAweDAwMDA1MDAwKSB7CiAgICAgIGlmICh0YWJsZXMubWF4cC5sZW5ndGggPT09IDYpIHsKICAgICAgICB2ZXJzaW9uID0gMHgwMDA1MDAwOwogICAgICB9IGVsc2UgaWYgKHRhYmxlcy5tYXhwLmxlbmd0aCA+PSAzMikgewogICAgICAgIHZlcnNpb24gPSAweDAwMDEwMDAwOwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgIm1heHAiIHRhYmxlIGhhcyBhIHdyb25nIHZlcnNpb24gbnVtYmVyYCk7CiAgICAgIH0KICAgICAgd3JpdGVVaW50MzIodGFibGVzLm1heHAuZGF0YSwgMCwgdmVyc2lvbik7CiAgICB9CiAgICBpZiAocHJvcGVydGllcy5zY2FsZUZhY3RvcnM/Lmxlbmd0aCA9PT0gbnVtR2x5cGhzICYmIGlzVHJ1ZVR5cGUpIHsKICAgICAgY29uc3QgewogICAgICAgIHNjYWxlRmFjdG9ycwogICAgICB9ID0gcHJvcGVydGllczsKICAgICAgY29uc3QgaXNHbHlwaExvY2F0aW9uc0xvbmcgPSBpbnQxNih0YWJsZXMuaGVhZC5kYXRhWzUwXSwgdGFibGVzLmhlYWQuZGF0YVs1MV0pOwogICAgICBjb25zdCBnbHlwaHMgPSBuZXcgR2x5ZlRhYmxlKHsKICAgICAgICBnbHlmVGFibGU6IHRhYmxlcy5nbHlmLmRhdGEsCiAgICAgICAgaXNHbHlwaExvY2F0aW9uc0xvbmcsCiAgICAgICAgbG9jYVRhYmxlOiB0YWJsZXMubG9jYS5kYXRhLAogICAgICAgIG51bUdseXBocwogICAgICB9KTsKICAgICAgZ2x5cGhzLnNjYWxlKHNjYWxlRmFjdG9ycyk7CiAgICAgIGNvbnN0IHsKICAgICAgICBnbHlmLAogICAgICAgIGxvY2EsCiAgICAgICAgaXNMb2NhdGlvbkxvbmcKICAgICAgfSA9IGdseXBocy53cml0ZSgpOwogICAgICB0YWJsZXMuZ2x5Zi5kYXRhID0gZ2x5ZjsKICAgICAgdGFibGVzLmxvY2EuZGF0YSA9IGxvY2E7CiAgICAgIGlmIChpc0xvY2F0aW9uTG9uZyAhPT0gISFpc0dseXBoTG9jYXRpb25zTG9uZykgewogICAgICAgIHRhYmxlcy5oZWFkLmRhdGFbNTBdID0gMDsKICAgICAgICB0YWJsZXMuaGVhZC5kYXRhWzUxXSA9IGlzTG9jYXRpb25Mb25nID8gMSA6IDA7CiAgICAgIH0KICAgICAgY29uc3QgbWV0cmljcyA9IHRhYmxlcy5obXR4LmRhdGE7CiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtR2x5cGhzOyBpKyspIHsKICAgICAgICBjb25zdCBqID0gNCAqIGk7CiAgICAgICAgY29uc3QgYWR2YW5jZVdpZHRoID0gTWF0aC5yb3VuZChzY2FsZUZhY3RvcnNbaV0gKiBpbnQxNihtZXRyaWNzW2pdLCBtZXRyaWNzW2ogKyAxXSkpOwogICAgICAgIG1ldHJpY3Nbal0gPSBhZHZhbmNlV2lkdGggPj4gOCAmIDB4ZmY7CiAgICAgICAgbWV0cmljc1tqICsgMV0gPSBhZHZhbmNlV2lkdGggJiAweGZmOwogICAgICAgIGNvbnN0IGxzYiA9IE1hdGgucm91bmQoc2NhbGVGYWN0b3JzW2ldICogc2lnbmVkSW50MTYobWV0cmljc1tqICsgMl0sIG1ldHJpY3NbaiArIDNdKSk7CiAgICAgICAgd3JpdGVTaWduZWRJbnQxNihtZXRyaWNzLCBqICsgMiwgbHNiKTsKICAgICAgfQogICAgfQogICAgbGV0IG51bUdseXBoc091dCA9IG51bUdseXBocyArIDE7CiAgICBsZXQgZHVwRmlyc3RFbnRyeSA9IHRydWU7CiAgICBpZiAobnVtR2x5cGhzT3V0ID4gMHhmZmZmKSB7CiAgICAgIGR1cEZpcnN0RW50cnkgPSBmYWxzZTsKICAgICAgbnVtR2x5cGhzT3V0ID0gbnVtR2x5cGhzOwogICAgICB3YXJuKCJOb3QgZW5vdWdoIHNwYWNlIGluIGdseWZzIHRvIGR1cGxpY2F0ZSBmaXJzdCBnbHlwaC4iKTsKICAgIH0KICAgIGxldCBtYXhGdW5jdGlvbkRlZnMgPSAwOwogICAgbGV0IG1heFNpemVPZkluc3RydWN0aW9ucyA9IDA7CiAgICBpZiAodmVyc2lvbiA+PSAweDAwMDEwMDAwICYmIHRhYmxlcy5tYXhwLmxlbmd0aCA+PSAzMikgewogICAgICBmb250LnBvcyArPSA4OwogICAgICBjb25zdCBtYXhab25lcyA9IGZvbnQuZ2V0VWludDE2KCk7CiAgICAgIGlmIChtYXhab25lcyA+IDIpIHsKICAgICAgICB0YWJsZXMubWF4cC5kYXRhWzE0XSA9IDA7CiAgICAgICAgdGFibGVzLm1heHAuZGF0YVsxNV0gPSAyOwogICAgICB9CiAgICAgIGZvbnQucG9zICs9IDQ7CiAgICAgIG1heEZ1bmN0aW9uRGVmcyA9IGZvbnQuZ2V0VWludDE2KCk7CiAgICAgIGZvbnQucG9zICs9IDQ7CiAgICAgIG1heFNpemVPZkluc3RydWN0aW9ucyA9IGZvbnQuZ2V0VWludDE2KCk7CiAgICB9CiAgICB0YWJsZXMubWF4cC5kYXRhWzRdID0gbnVtR2x5cGhzT3V0ID4+IDg7CiAgICB0YWJsZXMubWF4cC5kYXRhWzVdID0gbnVtR2x5cGhzT3V0ICYgMjU1OwogICAgY29uc3QgaGludHNWYWxpZCA9IHNhbml0aXplVFRQcm9ncmFtcyh0YWJsZXMuZnBnbSwgdGFibGVzLnByZXAsIHRhYmxlc1siY3Z0ICJdLCBtYXhGdW5jdGlvbkRlZnMpOwogICAgaWYgKCFoaW50c1ZhbGlkKSB7CiAgICAgIGRlbGV0ZSB0YWJsZXMuZnBnbTsKICAgICAgZGVsZXRlIHRhYmxlcy5wcmVwOwogICAgICBkZWxldGUgdGFibGVzWyJjdnQgIl07CiAgICB9CiAgICBzYW5pdGl6ZU1ldHJpY3MoZm9udCwgdGFibGVzLmhoZWEsIHRhYmxlcy5obXR4LCB0YWJsZXMuaGVhZCwgbnVtR2x5cGhzT3V0LCBkdXBGaXJzdEVudHJ5KTsKICAgIGlmICghdGFibGVzLmhlYWQpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCdSZXF1aXJlZCAiaGVhZCIgdGFibGUgaXMgbm90IGZvdW5kJyk7CiAgICB9CiAgICBzYW5pdGl6ZUhlYWQodGFibGVzLmhlYWQsIG51bUdseXBocywgaXNUcnVlVHlwZSA/IHRhYmxlcy5sb2NhLmxlbmd0aCA6IDApOwogICAgbGV0IG1pc3NpbmdHbHlwaHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgaWYgKGlzVHJ1ZVR5cGUpIHsKICAgICAgY29uc3QgaXNHbHlwaExvY2F0aW9uc0xvbmcgPSBpbnQxNih0YWJsZXMuaGVhZC5kYXRhWzUwXSwgdGFibGVzLmhlYWQuZGF0YVs1MV0pOwogICAgICBjb25zdCBnbHlwaHNJbmZvID0gc2FuaXRpemVHbHlwaExvY2F0aW9ucyh0YWJsZXMubG9jYSwgdGFibGVzLmdseWYsIG51bUdseXBocywgaXNHbHlwaExvY2F0aW9uc0xvbmcsIGhpbnRzVmFsaWQsIGR1cEZpcnN0RW50cnksIG1heFNpemVPZkluc3RydWN0aW9ucyk7CiAgICAgIG1pc3NpbmdHbHlwaHMgPSBnbHlwaHNJbmZvLm1pc3NpbmdHbHlwaHM7CiAgICAgIGlmICh2ZXJzaW9uID49IDB4MDAwMTAwMDAgJiYgdGFibGVzLm1heHAubGVuZ3RoID49IDMyKSB7CiAgICAgICAgdGFibGVzLm1heHAuZGF0YVsyNl0gPSBnbHlwaHNJbmZvLm1heFNpemVPZkluc3RydWN0aW9ucyA+PiA4OwogICAgICAgIHRhYmxlcy5tYXhwLmRhdGFbMjddID0gZ2x5cGhzSW5mby5tYXhTaXplT2ZJbnN0cnVjdGlvbnMgJiAyNTU7CiAgICAgIH0KICAgIH0KICAgIGlmICghdGFibGVzLmhoZWEpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCdSZXF1aXJlZCAiaGhlYSIgdGFibGUgaXMgbm90IGZvdW5kJyk7CiAgICB9CiAgICBpZiAodGFibGVzLmhoZWEuZGF0YVsxMF0gPT09IDAgJiYgdGFibGVzLmhoZWEuZGF0YVsxMV0gPT09IDApIHsKICAgICAgdGFibGVzLmhoZWEuZGF0YVsxMF0gPSAweGZmOwogICAgICB0YWJsZXMuaGhlYS5kYXRhWzExXSA9IDB4ZmY7CiAgICB9CiAgICBjb25zdCBtZXRyaWNzT3ZlcnJpZGUgPSB7CiAgICAgIHVuaXRzUGVyRW06IGludDE2KHRhYmxlcy5oZWFkLmRhdGFbMThdLCB0YWJsZXMuaGVhZC5kYXRhWzE5XSksCiAgICAgIHlNYXg6IHNpZ25lZEludDE2KHRhYmxlcy5oZWFkLmRhdGFbNDJdLCB0YWJsZXMuaGVhZC5kYXRhWzQzXSksCiAgICAgIHlNaW46IHNpZ25lZEludDE2KHRhYmxlcy5oZWFkLmRhdGFbMzhdLCB0YWJsZXMuaGVhZC5kYXRhWzM5XSksCiAgICAgIGFzY2VudDogc2lnbmVkSW50MTYodGFibGVzLmhoZWEuZGF0YVs0XSwgdGFibGVzLmhoZWEuZGF0YVs1XSksCiAgICAgIGRlc2NlbnQ6IHNpZ25lZEludDE2KHRhYmxlcy5oaGVhLmRhdGFbNl0sIHRhYmxlcy5oaGVhLmRhdGFbN10pLAogICAgICBsaW5lR2FwOiBzaWduZWRJbnQxNih0YWJsZXMuaGhlYS5kYXRhWzhdLCB0YWJsZXMuaGhlYS5kYXRhWzldKQogICAgfTsKICAgIHRoaXMuYXNjZW50ID0gbWV0cmljc092ZXJyaWRlLmFzY2VudCAvIG1ldHJpY3NPdmVycmlkZS51bml0c1BlckVtOwogICAgdGhpcy5kZXNjZW50ID0gbWV0cmljc092ZXJyaWRlLmRlc2NlbnQgLyBtZXRyaWNzT3ZlcnJpZGUudW5pdHNQZXJFbTsKICAgIHRoaXMubGluZUdhcCA9IG1ldHJpY3NPdmVycmlkZS5saW5lR2FwIC8gbWV0cmljc092ZXJyaWRlLnVuaXRzUGVyRW07CiAgICBpZiAodGhpcy5jc3NGb250SW5mbz8ubGluZUhlaWdodCkgewogICAgICB0aGlzLmxpbmVIZWlnaHQgPSB0aGlzLmNzc0ZvbnRJbmZvLm1ldHJpY3MubGluZUhlaWdodDsKICAgICAgdGhpcy5saW5lR2FwID0gdGhpcy5jc3NGb250SW5mby5tZXRyaWNzLmxpbmVHYXA7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmxpbmVIZWlnaHQgPSB0aGlzLmFzY2VudCAtIHRoaXMuZGVzY2VudCArIHRoaXMubGluZUdhcDsKICAgIH0KICAgIGlmICh0YWJsZXMucG9zdCkgewogICAgICByZWFkUG9zdFNjcmlwdFRhYmxlKHRhYmxlcy5wb3N0LCBwcm9wZXJ0aWVzLCBudW1HbHlwaHMpOwogICAgfQogICAgdGFibGVzLnBvc3QgPSB7CiAgICAgIHRhZzogInBvc3QiLAogICAgICBkYXRhOiBjcmVhdGVQb3N0VGFibGUocHJvcGVydGllcykKICAgIH07CiAgICBjb25zdCBjaGFyQ29kZVRvR2x5cGhJZCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBmdW5jdGlvbiBoYXNHbHlwaChnbHlwaElkKSB7CiAgICAgIHJldHVybiAhbWlzc2luZ0dseXBoc1tnbHlwaElkXTsKICAgIH0KICAgIGlmIChwcm9wZXJ0aWVzLmNvbXBvc2l0ZSkgewogICAgICBjb25zdCBjaWRUb0dpZE1hcCA9IHByb3BlcnRpZXMuY2lkVG9HaWRNYXAgfHwgW107CiAgICAgIGNvbnN0IGlzQ2lkVG9HaWRNYXBFbXB0eSA9IGNpZFRvR2lkTWFwLmxlbmd0aCA9PT0gMDsKICAgICAgcHJvcGVydGllcy5jTWFwLmZvckVhY2goZnVuY3Rpb24gKGNoYXJDb2RlLCBjaWQpIHsKICAgICAgICBpZiAodHlwZW9mIGNpZCA9PT0gInN0cmluZyIpIHsKICAgICAgICAgIGNpZCA9IGNvbnZlcnRDaWRTdHJpbmcoY2hhckNvZGUsIGNpZCwgdHJ1ZSk7CiAgICAgICAgfQogICAgICAgIGlmIChjaWQgPiAweGZmZmYpIHsKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiTWF4IHNpemUgb2YgQ0lEIGlzIDY1LDUzNSIpOwogICAgICAgIH0KICAgICAgICBsZXQgZ2x5cGhJZCA9IC0xOwogICAgICAgIGlmIChpc0NpZFRvR2lkTWFwRW1wdHkpIHsKICAgICAgICAgIGdseXBoSWQgPSBjaWQ7CiAgICAgICAgfSBlbHNlIGlmIChjaWRUb0dpZE1hcFtjaWRdICE9PSB1bmRlZmluZWQpIHsKICAgICAgICAgIGdseXBoSWQgPSBjaWRUb0dpZE1hcFtjaWRdOwogICAgICAgIH0KICAgICAgICBpZiAoZ2x5cGhJZCA+PSAwICYmIGdseXBoSWQgPCBudW1HbHlwaHMgJiYgaGFzR2x5cGgoZ2x5cGhJZCkpIHsKICAgICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW2NoYXJDb2RlXSA9IGdseXBoSWQ7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IGNtYXBUYWJsZSA9IHJlYWRDbWFwVGFibGUodGFibGVzLmNtYXAsIGZvbnQsIHRoaXMuaXNTeW1ib2xpY0ZvbnQsIHByb3BlcnRpZXMuaGFzRW5jb2RpbmcpOwogICAgICBjb25zdCBjbWFwUGxhdGZvcm1JZCA9IGNtYXBUYWJsZS5wbGF0Zm9ybUlkOwogICAgICBjb25zdCBjbWFwRW5jb2RpbmdJZCA9IGNtYXBUYWJsZS5lbmNvZGluZ0lkOwogICAgICBjb25zdCBjbWFwTWFwcGluZ3MgPSBjbWFwVGFibGUubWFwcGluZ3M7CiAgICAgIGxldCBiYXNlRW5jb2RpbmcgPSBbXSwKICAgICAgICBmb3JjZVBvc3RUYWJsZSA9IGZhbHNlOwogICAgICBpZiAocHJvcGVydGllcy5oYXNFbmNvZGluZyAmJiAocHJvcGVydGllcy5iYXNlRW5jb2RpbmdOYW1lID09PSAiTWFjUm9tYW5FbmNvZGluZyIgfHwgcHJvcGVydGllcy5iYXNlRW5jb2RpbmdOYW1lID09PSAiV2luQW5zaUVuY29kaW5nIikpIHsKICAgICAgICBiYXNlRW5jb2RpbmcgPSBnZXRFbmNvZGluZyhwcm9wZXJ0aWVzLmJhc2VFbmNvZGluZ05hbWUpOwogICAgICB9CiAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc0VuY29kaW5nICYmICF0aGlzLmlzU3ltYm9saWNGb250ICYmIChjbWFwUGxhdGZvcm1JZCA9PT0gMyAmJiBjbWFwRW5jb2RpbmdJZCA9PT0gMSB8fCBjbWFwUGxhdGZvcm1JZCA9PT0gMSAmJiBjbWFwRW5jb2RpbmdJZCA9PT0gMCkpIHsKICAgICAgICBjb25zdCBnbHlwaHNVbmljb2RlTWFwID0gZ2V0R2x5cGhzVW5pY29kZSgpOwogICAgICAgIGZvciAobGV0IGNoYXJDb2RlID0gMDsgY2hhckNvZGUgPCAyNTY7IGNoYXJDb2RlKyspIHsKICAgICAgICAgIGxldCBnbHlwaE5hbWU7CiAgICAgICAgICBpZiAodGhpcy5kaWZmZXJlbmNlc1tjaGFyQ29kZV0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBnbHlwaE5hbWUgPSB0aGlzLmRpZmZlcmVuY2VzW2NoYXJDb2RlXTsKICAgICAgICAgIH0gZWxzZSBpZiAoYmFzZUVuY29kaW5nLmxlbmd0aCAmJiBiYXNlRW5jb2RpbmdbY2hhckNvZGVdICE9PSAiIikgewogICAgICAgICAgICBnbHlwaE5hbWUgPSBiYXNlRW5jb2RpbmdbY2hhckNvZGVdOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgZ2x5cGhOYW1lID0gU3RhbmRhcmRFbmNvZGluZ1tjaGFyQ29kZV07CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIWdseXBoTmFtZSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IHN0YW5kYXJkR2x5cGhOYW1lID0gcmVjb3ZlckdseXBoTmFtZShnbHlwaE5hbWUsIGdseXBoc1VuaWNvZGVNYXApOwogICAgICAgICAgbGV0IHVuaWNvZGVPckNoYXJDb2RlOwogICAgICAgICAgaWYgKGNtYXBQbGF0Zm9ybUlkID09PSAzICYmIGNtYXBFbmNvZGluZ0lkID09PSAxKSB7CiAgICAgICAgICAgIHVuaWNvZGVPckNoYXJDb2RlID0gZ2x5cGhzVW5pY29kZU1hcFtzdGFuZGFyZEdseXBoTmFtZV07CiAgICAgICAgICB9IGVsc2UgaWYgKGNtYXBQbGF0Zm9ybUlkID09PSAxICYmIGNtYXBFbmNvZGluZ0lkID09PSAwKSB7CiAgICAgICAgICAgIHVuaWNvZGVPckNoYXJDb2RlID0gTWFjUm9tYW5FbmNvZGluZy5pbmRleE9mKHN0YW5kYXJkR2x5cGhOYW1lKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh1bmljb2RlT3JDaGFyQ29kZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGlmICghcHJvcGVydGllcy5nbHlwaE5hbWVzICYmIHByb3BlcnRpZXMuaGFzSW5jbHVkZWRUb1VuaWNvZGVNYXAgJiYgISh0aGlzLnRvVW5pY29kZSBpbnN0YW5jZW9mIElkZW50aXR5VG9Vbmljb2RlTWFwKSkgewogICAgICAgICAgICAgIGNvbnN0IHVuaWNvZGUgPSB0aGlzLnRvVW5pY29kZS5nZXQoY2hhckNvZGUpOwogICAgICAgICAgICAgIGlmICh1bmljb2RlKSB7CiAgICAgICAgICAgICAgICB1bmljb2RlT3JDaGFyQ29kZSA9IHVuaWNvZGUuY29kZVBvaW50QXQoMCk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh1bmljb2RlT3JDaGFyQ29kZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGZvciAoY29uc3QgbWFwcGluZyBvZiBjbWFwTWFwcGluZ3MpIHsKICAgICAgICAgICAgaWYgKG1hcHBpbmcuY2hhckNvZGUgIT09IHVuaWNvZGVPckNoYXJDb2RlKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdID0gbWFwcGluZy5nbHlwaElkOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoY21hcFBsYXRmb3JtSWQgPT09IDApIHsKICAgICAgICBmb3IgKGNvbnN0IG1hcHBpbmcgb2YgY21hcE1hcHBpbmdzKSB7CiAgICAgICAgICBjaGFyQ29kZVRvR2x5cGhJZFttYXBwaW5nLmNoYXJDb2RlXSA9IG1hcHBpbmcuZ2x5cGhJZDsKICAgICAgICB9CiAgICAgICAgZm9yY2VQb3N0VGFibGUgPSB0cnVlOwogICAgICB9IGVsc2UgaWYgKGNtYXBQbGF0Zm9ybUlkID09PSAzICYmIGNtYXBFbmNvZGluZ0lkID09PSAwKSB7CiAgICAgICAgZm9yIChjb25zdCBtYXBwaW5nIG9mIGNtYXBNYXBwaW5ncykgewogICAgICAgICAgbGV0IGNoYXJDb2RlID0gbWFwcGluZy5jaGFyQ29kZTsKICAgICAgICAgIGlmIChjaGFyQ29kZSA+PSAweGYwMDAgJiYgY2hhckNvZGUgPD0gMHhmMGZmKSB7CiAgICAgICAgICAgIGNoYXJDb2RlICY9IDB4ZmY7CiAgICAgICAgICB9CiAgICAgICAgICBjaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0gPSBtYXBwaW5nLmdseXBoSWQ7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGZvciAoY29uc3QgbWFwcGluZyBvZiBjbWFwTWFwcGluZ3MpIHsKICAgICAgICAgIGNoYXJDb2RlVG9HbHlwaElkW21hcHBpbmcuY2hhckNvZGVdID0gbWFwcGluZy5nbHlwaElkOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAocHJvcGVydGllcy5nbHlwaE5hbWVzICYmIChiYXNlRW5jb2RpbmcubGVuZ3RoIHx8IHRoaXMuZGlmZmVyZW5jZXMubGVuZ3RoKSkgewogICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMjU2OyArK2kpIHsKICAgICAgICAgIGlmICghZm9yY2VQb3N0VGFibGUgJiYgY2hhckNvZGVUb0dseXBoSWRbaV0gIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGdseXBoTmFtZSA9IHRoaXMuZGlmZmVyZW5jZXNbaV0gfHwgYmFzZUVuY29kaW5nW2ldOwogICAgICAgICAgaWYgKCFnbHlwaE5hbWUpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBnbHlwaElkID0gcHJvcGVydGllcy5nbHlwaE5hbWVzLmluZGV4T2YoZ2x5cGhOYW1lKTsKICAgICAgICAgIGlmIChnbHlwaElkID4gMCAmJiBoYXNHbHlwaChnbHlwaElkKSkgewogICAgICAgICAgICBjaGFyQ29kZVRvR2x5cGhJZFtpXSA9IGdseXBoSWQ7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAoY2hhckNvZGVUb0dseXBoSWQubGVuZ3RoID09PSAwKSB7CiAgICAgIGNoYXJDb2RlVG9HbHlwaElkWzBdID0gMDsKICAgIH0KICAgIGxldCBnbHlwaFplcm9JZCA9IG51bUdseXBoc091dCAtIDE7CiAgICBpZiAoIWR1cEZpcnN0RW50cnkpIHsKICAgICAgZ2x5cGhaZXJvSWQgPSAwOwogICAgfQogICAgaWYgKCFwcm9wZXJ0aWVzLmNzc0ZvbnRJbmZvKSB7CiAgICAgIGNvbnN0IG5ld01hcHBpbmcgPSBhZGp1c3RNYXBwaW5nKGNoYXJDb2RlVG9HbHlwaElkLCBoYXNHbHlwaCwgZ2x5cGhaZXJvSWQsIHRoaXMudG9Vbmljb2RlKTsKICAgICAgdGhpcy50b0ZvbnRDaGFyID0gbmV3TWFwcGluZy50b0ZvbnRDaGFyOwogICAgICB0YWJsZXMuY21hcCA9IHsKICAgICAgICB0YWc6ICJjbWFwIiwKICAgICAgICBkYXRhOiBjcmVhdGVDbWFwVGFibGUobmV3TWFwcGluZy5jaGFyQ29kZVRvR2x5cGhJZCwgbmV3TWFwcGluZy50b1VuaWNvZGVFeHRyYU1hcCwgbnVtR2x5cGhzT3V0KQogICAgICB9OwogICAgICBpZiAoIXRhYmxlc1siT1MvMiJdIHx8ICF2YWxpZGF0ZU9TMlRhYmxlKHRhYmxlc1siT1MvMiJdLCBmb250KSkgewogICAgICAgIHRhYmxlc1siT1MvMiJdID0gewogICAgICAgICAgdGFnOiAiT1MvMiIsCiAgICAgICAgICBkYXRhOiBjcmVhdGVPUzJUYWJsZShwcm9wZXJ0aWVzLCBuZXdNYXBwaW5nLmNoYXJDb2RlVG9HbHlwaElkLCBtZXRyaWNzT3ZlcnJpZGUpCiAgICAgICAgfTsKICAgICAgfQogICAgfQogICAgaWYgKCFpc1RydWVUeXBlKSB7CiAgICAgIHRyeSB7CiAgICAgICAgY2ZmRmlsZSA9IG5ldyBTdHJlYW0odGFibGVzWyJDRkYgIl0uZGF0YSk7CiAgICAgICAgY29uc3QgcGFyc2VyID0gbmV3IENGRlBhcnNlcihjZmZGaWxlLCBwcm9wZXJ0aWVzLCBTRUFDX0FOQUxZU0lTX0VOQUJMRUQpOwogICAgICAgIGNmZiA9IHBhcnNlci5wYXJzZSgpOwogICAgICAgIGNmZi5kdXBsaWNhdGVGaXJzdEdseXBoKCk7CiAgICAgICAgY29uc3QgY29tcGlsZXIgPSBuZXcgQ0ZGQ29tcGlsZXIoY2ZmKTsKICAgICAgICB0YWJsZXNbIkNGRiAiXS5kYXRhID0gY29tcGlsZXIuY29tcGlsZSgpOwogICAgICB9IGNhdGNoIHsKICAgICAgICB3YXJuKCJGYWlsZWQgdG8gY29tcGlsZSBmb250ICIgKyBwcm9wZXJ0aWVzLmxvYWRlZE5hbWUpOwogICAgICB9CiAgICB9CiAgICBpZiAoIXRhYmxlcy5uYW1lKSB7CiAgICAgIHRhYmxlcy5uYW1lID0gewogICAgICAgIHRhZzogIm5hbWUiLAogICAgICAgIGRhdGE6IGNyZWF0ZU5hbWVUYWJsZSh0aGlzLm5hbWUpCiAgICAgIH07CiAgICB9IGVsc2UgewogICAgICBjb25zdCBbbmFtZVByb3RvdHlwZSwgbmFtZVJlY29yZHNdID0gcmVhZE5hbWVUYWJsZSh0YWJsZXMubmFtZSk7CiAgICAgIHRhYmxlcy5uYW1lLmRhdGEgPSBjcmVhdGVOYW1lVGFibGUobmFtZSwgbmFtZVByb3RvdHlwZSk7CiAgICAgIHRoaXMucHNOYW1lID0gbmFtZVByb3RvdHlwZVswXVs2XSB8fCBudWxsOwogICAgICBpZiAoIXByb3BlcnRpZXMuY29tcG9zaXRlKSB7CiAgICAgICAgYWRqdXN0VHJ1ZVR5cGVUb1VuaWNvZGUocHJvcGVydGllcywgdGhpcy5pc1N5bWJvbGljRm9udCwgbmFtZVJlY29yZHMpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBidWlsZGVyID0gbmV3IE9wZW5UeXBlRmlsZUJ1aWxkZXIoaGVhZGVyLnZlcnNpb24pOwogICAgZm9yIChjb25zdCB0YWJsZVRhZyBpbiB0YWJsZXMpIHsKICAgICAgYnVpbGRlci5hZGRUYWJsZSh0YWJsZVRhZywgdGFibGVzW3RhYmxlVGFnXS5kYXRhKTsKICAgIH0KICAgIHJldHVybiBidWlsZGVyLnRvQXJyYXkoKTsKICB9CiAgY29udmVydChmb250TmFtZSwgZm9udCwgcHJvcGVydGllcykgewogICAgcHJvcGVydGllcy5maXhlZFBpdGNoID0gZmFsc2U7CiAgICBpZiAocHJvcGVydGllcy5idWlsdEluRW5jb2RpbmcpIHsKICAgICAgYWRqdXN0VHlwZTFUb1VuaWNvZGUocHJvcGVydGllcywgcHJvcGVydGllcy5idWlsdEluRW5jb2RpbmcpOwogICAgfQogICAgbGV0IGdseXBoWmVyb0lkID0gMTsKICAgIGlmIChmb250IGluc3RhbmNlb2YgQ0ZGRm9udCkgewogICAgICBnbHlwaFplcm9JZCA9IGZvbnQubnVtR2x5cGhzIC0gMTsKICAgIH0KICAgIGNvbnN0IG1hcHBpbmcgPSBmb250LmdldEdseXBoTWFwcGluZyhwcm9wZXJ0aWVzKTsKICAgIGxldCBuZXdNYXBwaW5nID0gbnVsbDsKICAgIGxldCBuZXdDaGFyQ29kZVRvR2x5cGhJZCA9IG1hcHBpbmc7CiAgICBsZXQgdG9Vbmljb2RlRXh0cmFNYXAgPSBudWxsOwogICAgaWYgKCFwcm9wZXJ0aWVzLmNzc0ZvbnRJbmZvKSB7CiAgICAgIG5ld01hcHBpbmcgPSBhZGp1c3RNYXBwaW5nKG1hcHBpbmcsIGZvbnQuaGFzR2x5cGhJZC5iaW5kKGZvbnQpLCBnbHlwaFplcm9JZCwgdGhpcy50b1VuaWNvZGUpOwogICAgICB0aGlzLnRvRm9udENoYXIgPSBuZXdNYXBwaW5nLnRvRm9udENoYXI7CiAgICAgIG5ld0NoYXJDb2RlVG9HbHlwaElkID0gbmV3TWFwcGluZy5jaGFyQ29kZVRvR2x5cGhJZDsKICAgICAgdG9Vbmljb2RlRXh0cmFNYXAgPSBuZXdNYXBwaW5nLnRvVW5pY29kZUV4dHJhTWFwOwogICAgfQogICAgY29uc3QgbnVtR2x5cGhzID0gZm9udC5udW1HbHlwaHM7CiAgICBmdW5jdGlvbiBnZXRDaGFyQ29kZXMoY2hhckNvZGVUb0dseXBoSWQsIGdseXBoSWQpIHsKICAgICAgbGV0IGNoYXJDb2RlcyA9IG51bGw7CiAgICAgIGZvciAoY29uc3QgY2hhckNvZGUgaW4gY2hhckNvZGVUb0dseXBoSWQpIHsKICAgICAgICBpZiAoZ2x5cGhJZCA9PT0gY2hhckNvZGVUb0dseXBoSWRbY2hhckNvZGVdKSB7CiAgICAgICAgICAoY2hhckNvZGVzIHx8PSBbXSkucHVzaChjaGFyQ29kZSB8IDApOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gY2hhckNvZGVzOwogICAgfQogICAgZnVuY3Rpb24gY3JlYXRlQ2hhckNvZGUoY2hhckNvZGVUb0dseXBoSWQsIGdseXBoSWQpIHsKICAgICAgZm9yIChjb25zdCBjaGFyQ29kZSBpbiBjaGFyQ29kZVRvR2x5cGhJZCkgewogICAgICAgIGlmIChnbHlwaElkID09PSBjaGFyQ29kZVRvR2x5cGhJZFtjaGFyQ29kZV0pIHsKICAgICAgICAgIHJldHVybiBjaGFyQ29kZSB8IDA7CiAgICAgICAgfQogICAgICB9CiAgICAgIG5ld01hcHBpbmcuY2hhckNvZGVUb0dseXBoSWRbbmV3TWFwcGluZy5uZXh0QXZhaWxhYmxlRm9udENoYXJDb2RlXSA9IGdseXBoSWQ7CiAgICAgIHJldHVybiBuZXdNYXBwaW5nLm5leHRBdmFpbGFibGVGb250Q2hhckNvZGUrKzsKICAgIH0KICAgIGNvbnN0IHNlYWNzID0gZm9udC5zZWFjczsKICAgIGlmIChuZXdNYXBwaW5nICYmIFNFQUNfQU5BTFlTSVNfRU5BQkxFRCAmJiBzZWFjcz8ubGVuZ3RoKSB7CiAgICAgIGNvbnN0IG1hdHJpeCA9IHByb3BlcnRpZXMuZm9udE1hdHJpeCB8fCBGT05UX0lERU5USVRZX01BVFJJWDsKICAgICAgY29uc3QgY2hhcnNldCA9IGZvbnQuZ2V0Q2hhcnNldCgpOwogICAgICBjb25zdCBzZWFjTWFwID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgZm9yIChsZXQgZ2x5cGhJZCBpbiBzZWFjcykgewogICAgICAgIGdseXBoSWQgfD0gMDsKICAgICAgICBjb25zdCBzZWFjID0gc2VhY3NbZ2x5cGhJZF07CiAgICAgICAgY29uc3QgYmFzZUdseXBoTmFtZSA9IFN0YW5kYXJkRW5jb2Rpbmdbc2VhY1syXV07CiAgICAgICAgY29uc3QgYWNjZW50R2x5cGhOYW1lID0gU3RhbmRhcmRFbmNvZGluZ1tzZWFjWzNdXTsKICAgICAgICBjb25zdCBiYXNlR2x5cGhJZCA9IGNoYXJzZXQuaW5kZXhPZihiYXNlR2x5cGhOYW1lKTsKICAgICAgICBjb25zdCBhY2NlbnRHbHlwaElkID0gY2hhcnNldC5pbmRleE9mKGFjY2VudEdseXBoTmFtZSk7CiAgICAgICAgaWYgKGJhc2VHbHlwaElkIDwgMCB8fCBhY2NlbnRHbHlwaElkIDwgMCkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGFjY2VudE9mZnNldCA9IHsKICAgICAgICAgIHg6IHNlYWNbMF0gKiBtYXRyaXhbMF0gKyBzZWFjWzFdICogbWF0cml4WzJdICsgbWF0cml4WzRdLAogICAgICAgICAgeTogc2VhY1swXSAqIG1hdHJpeFsxXSArIHNlYWNbMV0gKiBtYXRyaXhbM10gKyBtYXRyaXhbNV0KICAgICAgICB9OwogICAgICAgIGNvbnN0IGNoYXJDb2RlcyA9IGdldENoYXJDb2RlcyhtYXBwaW5nLCBnbHlwaElkKTsKICAgICAgICBpZiAoIWNoYXJDb2RlcykgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGZvciAoY29uc3QgY2hhckNvZGUgb2YgY2hhckNvZGVzKSB7CiAgICAgICAgICBjb25zdCBjaGFyQ29kZVRvR2x5cGhJZCA9IG5ld01hcHBpbmcuY2hhckNvZGVUb0dseXBoSWQ7CiAgICAgICAgICBjb25zdCBiYXNlRm9udENoYXJDb2RlID0gY3JlYXRlQ2hhckNvZGUoY2hhckNvZGVUb0dseXBoSWQsIGJhc2VHbHlwaElkKTsKICAgICAgICAgIGNvbnN0IGFjY2VudEZvbnRDaGFyQ29kZSA9IGNyZWF0ZUNoYXJDb2RlKGNoYXJDb2RlVG9HbHlwaElkLCBhY2NlbnRHbHlwaElkKTsKICAgICAgICAgIHNlYWNNYXBbY2hhckNvZGVdID0gewogICAgICAgICAgICBiYXNlRm9udENoYXJDb2RlLAogICAgICAgICAgICBhY2NlbnRGb250Q2hhckNvZGUsCiAgICAgICAgICAgIGFjY2VudE9mZnNldAogICAgICAgICAgfTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcHJvcGVydGllcy5zZWFjTWFwID0gc2VhY01hcDsKICAgIH0KICAgIGNvbnN0IHVuaXRzUGVyRW0gPSBwcm9wZXJ0aWVzLmZvbnRNYXRyaXggPyAxIC8gTWF0aC5tYXgoLi4ucHJvcGVydGllcy5mb250TWF0cml4LnNsaWNlKDAsIDQpLm1hcChNYXRoLmFicykpIDogMTAwMDsKICAgIGNvbnN0IGJ1aWxkZXIgPSBuZXcgT3BlblR5cGVGaWxlQnVpbGRlcigiXHg0Rlx4NTRceDU0XHg0RiIpOwogICAgYnVpbGRlci5hZGRUYWJsZSgiQ0ZGICIsIGZvbnQuZGF0YSk7CiAgICBidWlsZGVyLmFkZFRhYmxlKCJPUy8yIiwgY3JlYXRlT1MyVGFibGUocHJvcGVydGllcywgbmV3Q2hhckNvZGVUb0dseXBoSWQpKTsKICAgIGJ1aWxkZXIuYWRkVGFibGUoImNtYXAiLCBjcmVhdGVDbWFwVGFibGUobmV3Q2hhckNvZGVUb0dseXBoSWQsIHRvVW5pY29kZUV4dHJhTWFwLCBudW1HbHlwaHMpKTsKICAgIGJ1aWxkZXIuYWRkVGFibGUoImhlYWQiLCAiXHgwMFx4MDFceDAwXHgwMCIgKyAiXHgwMFx4MDBceDEwXHgwMCIgKyAiXHgwMFx4MDBceDAwXHgwMCIgKyAiXHg1Rlx4MEZceDNDXHhGNSIgKyAiXHgwMFx4MDAiICsgc2FmZVN0cmluZzE2KHVuaXRzUGVyRW0pICsgIlx4MDBceDAwXHgwMFx4MDBceDllXHgwYlx4N2VceDI3IiArICJceDAwXHgwMFx4MDBceDAwXHg5ZVx4MGJceDdlXHgyNyIgKyAiXHgwMFx4MDAiICsgc2FmZVN0cmluZzE2KHByb3BlcnRpZXMuZGVzY2VudCkgKyAiXHgwRlx4RkYiICsgc2FmZVN0cmluZzE2KHByb3BlcnRpZXMuYXNjZW50KSArIHN0cmluZzE2KHByb3BlcnRpZXMuaXRhbGljQW5nbGUgPyAyIDogMCkgKyAiXHgwMFx4MTEiICsgIlx4MDBceDAwIiArICJceDAwXHgwMCIgKyAiXHgwMFx4MDAiKTsKICAgIGJ1aWxkZXIuYWRkVGFibGUoImhoZWEiLCAiXHgwMFx4MDFceDAwXHgwMCIgKyBzYWZlU3RyaW5nMTYocHJvcGVydGllcy5hc2NlbnQpICsgc2FmZVN0cmluZzE2KHByb3BlcnRpZXMuZGVzY2VudCkgKyAiXHgwMFx4MDAiICsgIlx4RkZceEZGIiArICJceDAwXHgwMCIgKyAiXHgwMFx4MDAiICsgIlx4MDBceDAwIiArIHNhZmVTdHJpbmcxNihwcm9wZXJ0aWVzLmNhcEhlaWdodCkgKyBzYWZlU3RyaW5nMTYoTWF0aC50YW4ocHJvcGVydGllcy5pdGFsaWNBbmdsZSkgKiBwcm9wZXJ0aWVzLnhIZWlnaHQpICsgIlx4MDBceDAwIiArICJceDAwXHgwMCIgKyAiXHgwMFx4MDAiICsgIlx4MDBceDAwIiArICJceDAwXHgwMCIgKyAiXHgwMFx4MDAiICsgc3RyaW5nMTYobnVtR2x5cGhzKSk7CiAgICBidWlsZGVyLmFkZFRhYmxlKCJobXR4IiwgZnVuY3Rpb24gZm9udEZpZWxkc0htdHgoKSB7CiAgICAgIGNvbnN0IGNoYXJzdHJpbmdzID0gZm9udC5jaGFyc3RyaW5nczsKICAgICAgY29uc3QgY2ZmV2lkdGhzID0gZm9udC5jZmYgPyBmb250LmNmZi53aWR0aHMgOiBudWxsOwogICAgICBsZXQgaG10eCA9ICJceDAwXHgwMFx4MDBceDAwIjsKICAgICAgZm9yIChsZXQgaSA9IDEsIGlpID0gbnVtR2x5cGhzOyBpIDwgaWk7IGkrKykgewogICAgICAgIGxldCB3aWR0aCA9IDA7CiAgICAgICAgaWYgKGNoYXJzdHJpbmdzKSB7CiAgICAgICAgICBjb25zdCBjaGFyc3RyaW5nID0gY2hhcnN0cmluZ3NbaSAtIDFdOwogICAgICAgICAgd2lkdGggPSAid2lkdGgiIGluIGNoYXJzdHJpbmcgPyBjaGFyc3RyaW5nLndpZHRoIDogMDsKICAgICAgICB9IGVsc2UgaWYgKGNmZldpZHRocykgewogICAgICAgICAgd2lkdGggPSBNYXRoLmNlaWwoY2ZmV2lkdGhzW2ldIHx8IDApOwogICAgICAgIH0KICAgICAgICBobXR4ICs9IHN0cmluZzE2KHdpZHRoKSArIHN0cmluZzE2KDApOwogICAgICB9CiAgICAgIHJldHVybiBobXR4OwogICAgfSgpKTsKICAgIGJ1aWxkZXIuYWRkVGFibGUoIm1heHAiLCAiXHgwMFx4MDBceDUwXHgwMCIgKyBzdHJpbmcxNihudW1HbHlwaHMpKTsKICAgIGJ1aWxkZXIuYWRkVGFibGUoIm5hbWUiLCBjcmVhdGVOYW1lVGFibGUoZm9udE5hbWUpKTsKICAgIGJ1aWxkZXIuYWRkVGFibGUoInBvc3QiLCBjcmVhdGVQb3N0VGFibGUocHJvcGVydGllcykpOwogICAgcmV0dXJuIGJ1aWxkZXIudG9BcnJheSgpOwogIH0KICBnZXQgX3NwYWNlV2lkdGgoKSB7CiAgICBjb25zdCBwb3NzaWJsZVNwYWNlUmVwbGFjZW1lbnRzID0gWyJzcGFjZSIsICJtaW51cyIsICJvbmUiLCAiaSIsICJJIl07CiAgICBsZXQgd2lkdGg7CiAgICBmb3IgKGNvbnN0IGdseXBoTmFtZSBvZiBwb3NzaWJsZVNwYWNlUmVwbGFjZW1lbnRzKSB7CiAgICAgIGlmIChnbHlwaE5hbWUgaW4gdGhpcy53aWR0aHMpIHsKICAgICAgICB3aWR0aCA9IHRoaXMud2lkdGhzW2dseXBoTmFtZV07CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgY29uc3QgZ2x5cGhzVW5pY29kZU1hcCA9IGdldEdseXBoc1VuaWNvZGUoKTsKICAgICAgY29uc3QgZ2x5cGhVbmljb2RlID0gZ2x5cGhzVW5pY29kZU1hcFtnbHlwaE5hbWVdOwogICAgICBsZXQgY2hhcmNvZGUgPSAwOwogICAgICBpZiAodGhpcy5jb21wb3NpdGUgJiYgdGhpcy5jTWFwLmNvbnRhaW5zKGdseXBoVW5pY29kZSkpIHsKICAgICAgICBjaGFyY29kZSA9IHRoaXMuY01hcC5sb29rdXAoZ2x5cGhVbmljb2RlKTsKICAgICAgICBpZiAodHlwZW9mIGNoYXJjb2RlID09PSAic3RyaW5nIikgewogICAgICAgICAgY2hhcmNvZGUgPSBjb252ZXJ0Q2lkU3RyaW5nKGdseXBoVW5pY29kZSwgY2hhcmNvZGUpOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoIWNoYXJjb2RlICYmIHRoaXMudG9Vbmljb2RlKSB7CiAgICAgICAgY2hhcmNvZGUgPSB0aGlzLnRvVW5pY29kZS5jaGFyQ29kZU9mKGdseXBoVW5pY29kZSk7CiAgICAgIH0KICAgICAgaWYgKGNoYXJjb2RlIDw9IDApIHsKICAgICAgICBjaGFyY29kZSA9IGdseXBoVW5pY29kZTsKICAgICAgfQogICAgICB3aWR0aCA9IHRoaXMud2lkdGhzW2NoYXJjb2RlXTsKICAgICAgaWYgKHdpZHRoKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgIl9zcGFjZVdpZHRoIiwgd2lkdGggfHwgdGhpcy5kZWZhdWx0V2lkdGgpOwogIH0KICBfY2hhclRvR2x5cGgoY2hhcmNvZGUsIGlzU3BhY2UgPSBmYWxzZSkgewogICAgbGV0IGdseXBoID0gdGhpcy5fZ2x5cGhDYWNoZVtjaGFyY29kZV07CiAgICBpZiAoZ2x5cGg/LmlzU3BhY2UgPT09IGlzU3BhY2UpIHsKICAgICAgcmV0dXJuIGdseXBoOwogICAgfQogICAgbGV0IGZvbnRDaGFyQ29kZSwgd2lkdGgsIG9wZXJhdG9yTGlzdElkOwogICAgbGV0IHdpZHRoQ29kZSA9IGNoYXJjb2RlOwogICAgaWYgKHRoaXMuY01hcD8uY29udGFpbnMoY2hhcmNvZGUpKSB7CiAgICAgIHdpZHRoQ29kZSA9IHRoaXMuY01hcC5sb29rdXAoY2hhcmNvZGUpOwogICAgICBpZiAodHlwZW9mIHdpZHRoQ29kZSA9PT0gInN0cmluZyIpIHsKICAgICAgICB3aWR0aENvZGUgPSBjb252ZXJ0Q2lkU3RyaW5nKGNoYXJjb2RlLCB3aWR0aENvZGUpOwogICAgICB9CiAgICB9CiAgICB3aWR0aCA9IHRoaXMud2lkdGhzW3dpZHRoQ29kZV07CiAgICBpZiAodHlwZW9mIHdpZHRoICE9PSAibnVtYmVyIikgewogICAgICB3aWR0aCA9IHRoaXMuZGVmYXVsdFdpZHRoOwogICAgfQogICAgY29uc3Qgdm1ldHJpYyA9IHRoaXMudm1ldHJpY3M/Llt3aWR0aENvZGVdOwogICAgbGV0IHVuaWNvZGUgPSB0aGlzLnRvVW5pY29kZS5nZXQoY2hhcmNvZGUpIHx8IGNoYXJjb2RlOwogICAgaWYgKHR5cGVvZiB1bmljb2RlID09PSAibnVtYmVyIikgewogICAgICB1bmljb2RlID0gU3RyaW5nLmZyb21DaGFyQ29kZSh1bmljb2RlKTsKICAgIH0KICAgIGxldCBpc0luRm9udCA9IHRoaXMudG9Gb250Q2hhcltjaGFyY29kZV0gIT09IHVuZGVmaW5lZDsKICAgIGZvbnRDaGFyQ29kZSA9IHRoaXMudG9Gb250Q2hhcltjaGFyY29kZV0gfHwgY2hhcmNvZGU7CiAgICBpZiAodGhpcy5taXNzaW5nRmlsZSkgewogICAgICBjb25zdCBnbHlwaE5hbWUgPSB0aGlzLmRpZmZlcmVuY2VzW2NoYXJjb2RlXSB8fCB0aGlzLmRlZmF1bHRFbmNvZGluZ1tjaGFyY29kZV07CiAgICAgIGlmICgoZ2x5cGhOYW1lID09PSAiLm5vdGRlZiIgfHwgZ2x5cGhOYW1lID09PSAiIikgJiYgdGhpcy50eXBlID09PSAiVHlwZTEiKSB7CiAgICAgICAgZm9udENoYXJDb2RlID0gMHgyMDsKICAgICAgICBpZiAoZ2x5cGhOYW1lID09PSAiIikgewogICAgICAgICAgd2lkdGggfHw9IHRoaXMuX3NwYWNlV2lkdGg7CiAgICAgICAgICB1bmljb2RlID0gU3RyaW5nLmZyb21DaGFyQ29kZShmb250Q2hhckNvZGUpOwogICAgICAgIH0KICAgICAgfQogICAgICBmb250Q2hhckNvZGUgPSBtYXBTcGVjaWFsVW5pY29kZVZhbHVlcyhmb250Q2hhckNvZGUpOwogICAgfQogICAgaWYgKHRoaXMuaXNUeXBlM0ZvbnQpIHsKICAgICAgb3BlcmF0b3JMaXN0SWQgPSBmb250Q2hhckNvZGU7CiAgICB9CiAgICBsZXQgYWNjZW50ID0gbnVsbDsKICAgIGlmICh0aGlzLnNlYWNNYXA/LltjaGFyY29kZV0pIHsKICAgICAgaXNJbkZvbnQgPSB0cnVlOwogICAgICBjb25zdCBzZWFjID0gdGhpcy5zZWFjTWFwW2NoYXJjb2RlXTsKICAgICAgZm9udENoYXJDb2RlID0gc2VhYy5iYXNlRm9udENoYXJDb2RlOwogICAgICBhY2NlbnQgPSB7CiAgICAgICAgZm9udENoYXI6IFN0cmluZy5mcm9tQ29kZVBvaW50KHNlYWMuYWNjZW50Rm9udENoYXJDb2RlKSwKICAgICAgICBvZmZzZXQ6IHNlYWMuYWNjZW50T2Zmc2V0CiAgICAgIH07CiAgICB9CiAgICBsZXQgZm9udENoYXIgPSAiIjsKICAgIGlmICh0eXBlb2YgZm9udENoYXJDb2RlID09PSAibnVtYmVyIikgewogICAgICBpZiAoZm9udENoYXJDb2RlIDw9IDB4MTBmZmZmKSB7CiAgICAgICAgZm9udENoYXIgPSBTdHJpbmcuZnJvbUNvZGVQb2ludChmb250Q2hhckNvZGUpOwogICAgICB9IGVsc2UgewogICAgICAgIHdhcm4oYGNoYXJUb0dseXBoIC0gaW52YWxpZCBmb250Q2hhckNvZGU6ICR7Zm9udENoYXJDb2RlfWApOwogICAgICB9CiAgICB9CiAgICBpZiAodGhpcy5taXNzaW5nRmlsZSAmJiB0aGlzLnZlcnRpY2FsICYmIGZvbnRDaGFyLmxlbmd0aCA9PT0gMSkgewogICAgICBjb25zdCB2ZXJ0aWNhbCA9IGdldFZlcnRpY2FsUHJlc2VudGF0aW9uRm9ybSgpW2ZvbnRDaGFyLmNoYXJDb2RlQXQoMCldOwogICAgICBpZiAodmVydGljYWwpIHsKICAgICAgICBmb250Q2hhciA9IHVuaWNvZGUgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHZlcnRpY2FsKTsKICAgICAgfQogICAgfQogICAgZ2x5cGggPSBuZXcgZm9udHNfR2x5cGgoY2hhcmNvZGUsIGZvbnRDaGFyLCB1bmljb2RlLCBhY2NlbnQsIHdpZHRoLCB2bWV0cmljLCBvcGVyYXRvckxpc3RJZCwgaXNTcGFjZSwgaXNJbkZvbnQpOwogICAgcmV0dXJuIHRoaXMuX2dseXBoQ2FjaGVbY2hhcmNvZGVdID0gZ2x5cGg7CiAgfQogIGNoYXJzVG9HbHlwaHMoY2hhcnMpIHsKICAgIGxldCBnbHlwaHMgPSB0aGlzLl9jaGFyc0NhY2hlW2NoYXJzXTsKICAgIGlmIChnbHlwaHMpIHsKICAgICAgcmV0dXJuIGdseXBoczsKICAgIH0KICAgIGdseXBocyA9IFtdOwogICAgaWYgKHRoaXMuY01hcCkgewogICAgICBjb25zdCBjID0gT2JqZWN0LmNyZWF0ZShudWxsKSwKICAgICAgICBpaSA9IGNoYXJzLmxlbmd0aDsKICAgICAgbGV0IGkgPSAwOwogICAgICB3aGlsZSAoaSA8IGlpKSB7CiAgICAgICAgdGhpcy5jTWFwLnJlYWRDaGFyQ29kZShjaGFycywgaSwgYyk7CiAgICAgICAgY29uc3QgewogICAgICAgICAgY2hhcmNvZGUsCiAgICAgICAgICBsZW5ndGgKICAgICAgICB9ID0gYzsKICAgICAgICBpICs9IGxlbmd0aDsKICAgICAgICBjb25zdCBnbHlwaCA9IHRoaXMuX2NoYXJUb0dseXBoKGNoYXJjb2RlLCBsZW5ndGggPT09IDEgJiYgY2hhcnMuY2hhckNvZGVBdChpIC0gMSkgPT09IDB4MjApOwogICAgICAgIGdseXBocy5wdXNoKGdseXBoKTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gY2hhcnMubGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgICAgIGNvbnN0IGNoYXJjb2RlID0gY2hhcnMuY2hhckNvZGVBdChpKTsKICAgICAgICBjb25zdCBnbHlwaCA9IHRoaXMuX2NoYXJUb0dseXBoKGNoYXJjb2RlLCBjaGFyY29kZSA9PT0gMHgyMCk7CiAgICAgICAgZ2x5cGhzLnB1c2goZ2x5cGgpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdGhpcy5fY2hhcnNDYWNoZVtjaGFyc10gPSBnbHlwaHM7CiAgfQogIGdldENoYXJQb3NpdGlvbnMoY2hhcnMpIHsKICAgIGNvbnN0IHBvc2l0aW9ucyA9IFtdOwogICAgaWYgKHRoaXMuY01hcCkgewogICAgICBjb25zdCBjID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgbGV0IGkgPSAwOwogICAgICB3aGlsZSAoaSA8IGNoYXJzLmxlbmd0aCkgewogICAgICAgIHRoaXMuY01hcC5yZWFkQ2hhckNvZGUoY2hhcnMsIGksIGMpOwogICAgICAgIGNvbnN0IGxlbmd0aCA9IGMubGVuZ3RoOwogICAgICAgIHBvc2l0aW9ucy5wdXNoKFtpLCBpICsgbGVuZ3RoXSk7CiAgICAgICAgaSArPSBsZW5ndGg7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGNoYXJzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHsKICAgICAgICBwb3NpdGlvbnMucHVzaChbaSwgaSArIDFdKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHBvc2l0aW9uczsKICB9CiAgZ2V0IGdseXBoQ2FjaGVWYWx1ZXMoKSB7CiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLl9nbHlwaENhY2hlKTsKICB9CiAgZW5jb2RlU3RyaW5nKHN0cikgewogICAgY29uc3QgYnVmZmVycyA9IFtdOwogICAgY29uc3QgY3VycmVudEJ1ZiA9IFtdOwogICAgY29uc3QgaGFzQ3VycmVudEJ1ZkVycm9ycyA9ICgpID0+IGJ1ZmZlcnMubGVuZ3RoICUgMiA9PT0gMTsKICAgIGNvbnN0IGdldENoYXJDb2RlID0gdGhpcy50b1VuaWNvZGUgaW5zdGFuY2VvZiBJZGVudGl0eVRvVW5pY29kZU1hcCA/IHVuaWNvZGUgPT4gdGhpcy50b1VuaWNvZGUuY2hhckNvZGVPZih1bmljb2RlKSA6IHVuaWNvZGUgPT4gdGhpcy50b1VuaWNvZGUuY2hhckNvZGVPZihTdHJpbmcuZnJvbUNvZGVQb2ludCh1bmljb2RlKSk7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBzdHIubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCB1bmljb2RlID0gc3RyLmNvZGVQb2ludEF0KGkpOwogICAgICBpZiAodW5pY29kZSA+IDB4ZDdmZiAmJiAodW5pY29kZSA8IDB4ZTAwMCB8fCB1bmljb2RlID4gMHhmZmZkKSkgewogICAgICAgIGkrKzsKICAgICAgfQogICAgICBpZiAodGhpcy50b1VuaWNvZGUpIHsKICAgICAgICBjb25zdCBjaGFyQ29kZSA9IGdldENoYXJDb2RlKHVuaWNvZGUpOwogICAgICAgIGlmIChjaGFyQ29kZSAhPT0gLTEpIHsKICAgICAgICAgIGlmIChoYXNDdXJyZW50QnVmRXJyb3JzKCkpIHsKICAgICAgICAgICAgYnVmZmVycy5wdXNoKGN1cnJlbnRCdWYuam9pbigiIikpOwogICAgICAgICAgICBjdXJyZW50QnVmLmxlbmd0aCA9IDA7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBjaGFyQ29kZUxlbmd0aCA9IHRoaXMuY01hcCA/IHRoaXMuY01hcC5nZXRDaGFyQ29kZUxlbmd0aChjaGFyQ29kZSkgOiAxOwogICAgICAgICAgZm9yIChsZXQgaiA9IGNoYXJDb2RlTGVuZ3RoIC0gMTsgaiA+PSAwOyBqLS0pIHsKICAgICAgICAgICAgY3VycmVudEJ1Zi5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUoY2hhckNvZGUgPj4gOCAqIGogJiAweGZmKSk7CiAgICAgICAgICB9CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKCFoYXNDdXJyZW50QnVmRXJyb3JzKCkpIHsKICAgICAgICBidWZmZXJzLnB1c2goY3VycmVudEJ1Zi5qb2luKCIiKSk7CiAgICAgICAgY3VycmVudEJ1Zi5sZW5ndGggPSAwOwogICAgICB9CiAgICAgIGN1cnJlbnRCdWYucHVzaChTdHJpbmcuZnJvbUNvZGVQb2ludCh1bmljb2RlKSk7CiAgICB9CiAgICBidWZmZXJzLnB1c2goY3VycmVudEJ1Zi5qb2luKCIiKSk7CiAgICByZXR1cm4gYnVmZmVyczsKICB9Cn0KY2xhc3MgRXJyb3JGb250IHsKICBjb25zdHJ1Y3RvcihlcnJvcikgewogICAgdGhpcy5lcnJvciA9IGVycm9yOwogICAgdGhpcy5sb2FkZWROYW1lID0gImdfZm9udF9lcnJvciI7CiAgICB0aGlzLm1pc3NpbmdGaWxlID0gdHJ1ZTsKICB9CiAgY2hhcnNUb0dseXBocygpIHsKICAgIHJldHVybiBbXTsKICB9CiAgZW5jb2RlU3RyaW5nKGNoYXJzKSB7CiAgICByZXR1cm4gW2NoYXJzXTsKICB9CiAgZXhwb3J0RGF0YSgpIHsKICAgIHJldHVybiB7CiAgICAgIGVycm9yOiB0aGlzLmVycm9yCiAgICB9OwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvcGF0dGVybi5qcwoKCgoKCgoKCgoKCgoKY29uc3QgU2hhZGluZ1R5cGUgPSB7CiAgRlVOQ1RJT05fQkFTRUQ6IDEsCiAgQVhJQUw6IDIsCiAgUkFESUFMOiAzLAogIEZSRUVfRk9STV9NRVNIOiA0LAogIExBVFRJQ0VfRk9STV9NRVNIOiA1LAogIENPT05TX1BBVENIX01FU0g6IDYsCiAgVEVOU09SX1BBVENIX01FU0g6IDcKfTsKY2xhc3MgUGF0dGVybiB7CiAgY29uc3RydWN0b3IoKSB7CiAgICB1bnJlYWNoYWJsZSgiQ2Fubm90IGluaXRpYWxpemUgUGF0dGVybi4iKTsKICB9CiAgc3RhdGljIHBhcnNlU2hhZGluZyhzaGFkaW5nLCB4cmVmLCByZXMsIHBkZkZ1bmN0aW9uRmFjdG9yeSwgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLCBsb2NhbENvbG9yU3BhY2VDYWNoZSkgewogICAgY29uc3QgZGljdCA9IHNoYWRpbmcgaW5zdGFuY2VvZiBCYXNlU3RyZWFtID8gc2hhZGluZy5kaWN0IDogc2hhZGluZzsKICAgIGNvbnN0IHR5cGUgPSBkaWN0LmdldCgiU2hhZGluZ1R5cGUiKTsKICAgIHRyeSB7CiAgICAgIHN3aXRjaCAodHlwZSkgewogICAgICAgIGNhc2UgU2hhZGluZ1R5cGUuQVhJQUw6CiAgICAgICAgY2FzZSBTaGFkaW5nVHlwZS5SQURJQUw6CiAgICAgICAgICByZXR1cm4gbmV3IFJhZGlhbEF4aWFsU2hhZGluZyhkaWN0LCB4cmVmLCByZXMsIHBkZkZ1bmN0aW9uRmFjdG9yeSwgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLCBsb2NhbENvbG9yU3BhY2VDYWNoZSk7CiAgICAgICAgY2FzZSBTaGFkaW5nVHlwZS5GUkVFX0ZPUk1fTUVTSDoKICAgICAgICBjYXNlIFNoYWRpbmdUeXBlLkxBVFRJQ0VfRk9STV9NRVNIOgogICAgICAgIGNhc2UgU2hhZGluZ1R5cGUuQ09PTlNfUEFUQ0hfTUVTSDoKICAgICAgICBjYXNlIFNoYWRpbmdUeXBlLlRFTlNPUl9QQVRDSF9NRVNIOgogICAgICAgICAgcmV0dXJuIG5ldyBNZXNoU2hhZGluZyhzaGFkaW5nLCB4cmVmLCByZXMsIHBkZkZ1bmN0aW9uRmFjdG9yeSwgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLCBsb2NhbENvbG9yU3BhY2VDYWNoZSk7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiVW5zdXBwb3J0ZWQgU2hhZGluZ1R5cGU6ICIgKyB0eXBlKTsKICAgICAgfQogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICB3YXJuKGV4KTsKICAgICAgcmV0dXJuIG5ldyBEdW1teVNoYWRpbmcoKTsKICAgIH0KICB9Cn0KY2xhc3MgQmFzZVNoYWRpbmcgewogIHN0YXRpYyBTTUFMTF9OVU1CRVIgPSAxZS02OwogIGdldElSKCkgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgZ2V0SVJgIGNhbGxlZC4iKTsKICB9Cn0KY2xhc3MgUmFkaWFsQXhpYWxTaGFkaW5nIGV4dGVuZHMgQmFzZVNoYWRpbmcgewogIGNvbnN0cnVjdG9yKGRpY3QsIHhyZWYsIHJlc291cmNlcywgcGRmRnVuY3Rpb25GYWN0b3J5LCBnbG9iYWxDb2xvclNwYWNlQ2FjaGUsIGxvY2FsQ29sb3JTcGFjZUNhY2hlKSB7CiAgICBzdXBlcigpOwogICAgdGhpcy5zaGFkaW5nVHlwZSA9IGRpY3QuZ2V0KCJTaGFkaW5nVHlwZSIpOwogICAgbGV0IGNvb3Jkc0xlbiA9IDA7CiAgICBpZiAodGhpcy5zaGFkaW5nVHlwZSA9PT0gU2hhZGluZ1R5cGUuQVhJQUwpIHsKICAgICAgY29vcmRzTGVuID0gNDsKICAgIH0gZWxzZSBpZiAodGhpcy5zaGFkaW5nVHlwZSA9PT0gU2hhZGluZ1R5cGUuUkFESUFMKSB7CiAgICAgIGNvb3Jkc0xlbiA9IDY7CiAgICB9CiAgICB0aGlzLmNvb3Jkc0FyciA9IGRpY3QuZ2V0QXJyYXkoIkNvb3JkcyIpOwogICAgaWYgKCFpc051bWJlckFycmF5KHRoaXMuY29vcmRzQXJyLCBjb29yZHNMZW4pKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiUmFkaWFsQXhpYWxTaGFkaW5nOiBJbnZhbGlkIC9Db29yZHMgYXJyYXkuIik7CiAgICB9CiAgICBjb25zdCBjcyA9IENvbG9yU3BhY2VVdGlscy5wYXJzZSh7CiAgICAgIGNzOiBkaWN0LmdldFJhdygiQ1MiKSB8fCBkaWN0LmdldFJhdygiQ29sb3JTcGFjZSIpLAogICAgICB4cmVmLAogICAgICByZXNvdXJjZXMsCiAgICAgIHBkZkZ1bmN0aW9uRmFjdG9yeSwKICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgfSk7CiAgICB0aGlzLmJib3ggPSBsb29rdXBOb3JtYWxSZWN0KGRpY3QuZ2V0QXJyYXkoIkJCb3giKSwgbnVsbCk7CiAgICBsZXQgdDAgPSAwLjAsCiAgICAgIHQxID0gMS4wOwogICAgY29uc3QgZG9tYWluQXJyID0gZGljdC5nZXRBcnJheSgiRG9tYWluIik7CiAgICBpZiAoaXNOdW1iZXJBcnJheShkb21haW5BcnIsIDIpKSB7CiAgICAgIFt0MCwgdDFdID0gZG9tYWluQXJyOwogICAgfQogICAgbGV0IGV4dGVuZFN0YXJ0ID0gZmFsc2UsCiAgICAgIGV4dGVuZEVuZCA9IGZhbHNlOwogICAgY29uc3QgZXh0ZW5kQXJyID0gZGljdC5nZXRBcnJheSgiRXh0ZW5kIik7CiAgICBpZiAoaXNCb29sZWFuQXJyYXkoZXh0ZW5kQXJyLCAyKSkgewogICAgICBbZXh0ZW5kU3RhcnQsIGV4dGVuZEVuZF0gPSBleHRlbmRBcnI7CiAgICB9CiAgICBpZiAodGhpcy5zaGFkaW5nVHlwZSA9PT0gU2hhZGluZ1R5cGUuUkFESUFMICYmICghZXh0ZW5kU3RhcnQgfHwgIWV4dGVuZEVuZCkpIHsKICAgICAgY29uc3QgW3gxLCB5MSwgcjEsIHgyLCB5MiwgcjJdID0gdGhpcy5jb29yZHNBcnI7CiAgICAgIGNvbnN0IGRpc3RhbmNlID0gTWF0aC5oeXBvdCh4MSAtIHgyLCB5MSAtIHkyKTsKICAgICAgaWYgKHIxIDw9IHIyICsgZGlzdGFuY2UgJiYgcjIgPD0gcjEgKyBkaXN0YW5jZSkgewogICAgICAgIHdhcm4oIlVuc3VwcG9ydGVkIHJhZGlhbCBncmFkaWVudC4iKTsKICAgICAgfQogICAgfQogICAgdGhpcy5leHRlbmRTdGFydCA9IGV4dGVuZFN0YXJ0OwogICAgdGhpcy5leHRlbmRFbmQgPSBleHRlbmRFbmQ7CiAgICBjb25zdCBmbk9iaiA9IGRpY3QuZ2V0UmF3KCJGdW5jdGlvbiIpOwogICAgY29uc3QgZm4gPSBwZGZGdW5jdGlvbkZhY3RvcnkuY3JlYXRlKGZuT2JqLCB0cnVlKTsKICAgIGNvbnN0IE5VTUJFUl9PRl9TQU1QTEVTID0gODQwOwogICAgY29uc3Qgc3RlcCA9ICh0MSAtIHQwKSAvIE5VTUJFUl9PRl9TQU1QTEVTOwogICAgY29uc3QgY29sb3JTdG9wcyA9IHRoaXMuY29sb3JTdG9wcyA9IFtdOwogICAgaWYgKHQwID49IHQxIHx8IHN0ZXAgPD0gMCkgewogICAgICBpbmZvKCJCYWQgc2hhZGluZyBkb21haW4uIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGNvbG9yID0gbmV3IEZsb2F0MzJBcnJheShjcy5udW1Db21wcyksCiAgICAgIHJhdGlvID0gbmV3IEZsb2F0MzJBcnJheSgxKTsKICAgIGxldCBpQmFzZSA9IDA7CiAgICByYXRpb1swXSA9IHQwOwogICAgZm4ocmF0aW8sIDAsIGNvbG9yLCAwKTsKICAgIGNvbnN0IHJnYkJ1ZmZlciA9IG5ldyBVaW50OENsYW1wZWRBcnJheSgzKTsKICAgIGNzLmdldFJnYihjb2xvciwgMCwgcmdiQnVmZmVyKTsKICAgIGxldCBbckJhc2UsIGdCYXNlLCBiQmFzZV0gPSByZ2JCdWZmZXI7CiAgICBjb2xvclN0b3BzLnB1c2goWzAsIFV0aWwubWFrZUhleENvbG9yKHJCYXNlLCBnQmFzZSwgYkJhc2UpXSk7CiAgICBsZXQgaVByZXYgPSAxOwogICAgcmF0aW9bMF0gPSB0MCArIHN0ZXA7CiAgICBmbihyYXRpbywgMCwgY29sb3IsIDApOwogICAgY3MuZ2V0UmdiKGNvbG9yLCAwLCByZ2JCdWZmZXIpOwogICAgbGV0IFtyUHJldiwgZ1ByZXYsIGJQcmV2XSA9IHJnYkJ1ZmZlcjsKICAgIGxldCBtYXhTbG9wZVIgPSByUHJldiAtIHJCYXNlICsgMTsKICAgIGxldCBtYXhTbG9wZUcgPSBnUHJldiAtIGdCYXNlICsgMTsKICAgIGxldCBtYXhTbG9wZUIgPSBiUHJldiAtIGJCYXNlICsgMTsKICAgIGxldCBtaW5TbG9wZVIgPSByUHJldiAtIHJCYXNlIC0gMTsKICAgIGxldCBtaW5TbG9wZUcgPSBnUHJldiAtIGdCYXNlIC0gMTsKICAgIGxldCBtaW5TbG9wZUIgPSBiUHJldiAtIGJCYXNlIC0gMTsKICAgIGZvciAobGV0IGkgPSAyOyBpIDwgTlVNQkVSX09GX1NBTVBMRVM7IGkrKykgewogICAgICByYXRpb1swXSA9IHQwICsgaSAqIHN0ZXA7CiAgICAgIGZuKHJhdGlvLCAwLCBjb2xvciwgMCk7CiAgICAgIGNzLmdldFJnYihjb2xvciwgMCwgcmdiQnVmZmVyKTsKICAgICAgY29uc3QgW3IsIGcsIGJdID0gcmdiQnVmZmVyOwogICAgICBjb25zdCBydW4gPSBpIC0gaUJhc2U7CiAgICAgIG1heFNsb3BlUiA9IE1hdGgubWluKG1heFNsb3BlUiwgKHIgLSByQmFzZSArIDEpIC8gcnVuKTsKICAgICAgbWF4U2xvcGVHID0gTWF0aC5taW4obWF4U2xvcGVHLCAoZyAtIGdCYXNlICsgMSkgLyBydW4pOwogICAgICBtYXhTbG9wZUIgPSBNYXRoLm1pbihtYXhTbG9wZUIsIChiIC0gYkJhc2UgKyAxKSAvIHJ1bik7CiAgICAgIG1pblNsb3BlUiA9IE1hdGgubWF4KG1pblNsb3BlUiwgKHIgLSByQmFzZSAtIDEpIC8gcnVuKTsKICAgICAgbWluU2xvcGVHID0gTWF0aC5tYXgobWluU2xvcGVHLCAoZyAtIGdCYXNlIC0gMSkgLyBydW4pOwogICAgICBtaW5TbG9wZUIgPSBNYXRoLm1heChtaW5TbG9wZUIsIChiIC0gYkJhc2UgLSAxKSAvIHJ1bik7CiAgICAgIGNvbnN0IHNsb3Blc0V4aXN0ID0gbWluU2xvcGVSIDw9IG1heFNsb3BlUiAmJiBtaW5TbG9wZUcgPD0gbWF4U2xvcGVHICYmIG1pblNsb3BlQiA8PSBtYXhTbG9wZUI7CiAgICAgIGlmICghc2xvcGVzRXhpc3QpIHsKICAgICAgICBjb25zdCBjc3NDb2xvciA9IFV0aWwubWFrZUhleENvbG9yKHJQcmV2LCBnUHJldiwgYlByZXYpOwogICAgICAgIGNvbG9yU3RvcHMucHVzaChbaVByZXYgLyBOVU1CRVJfT0ZfU0FNUExFUywgY3NzQ29sb3JdKTsKICAgICAgICBtYXhTbG9wZVIgPSByIC0gclByZXYgKyAxOwogICAgICAgIG1heFNsb3BlRyA9IGcgLSBnUHJldiArIDE7CiAgICAgICAgbWF4U2xvcGVCID0gYiAtIGJQcmV2ICsgMTsKICAgICAgICBtaW5TbG9wZVIgPSByIC0gclByZXYgLSAxOwogICAgICAgIG1pblNsb3BlRyA9IGcgLSBnUHJldiAtIDE7CiAgICAgICAgbWluU2xvcGVCID0gYiAtIGJQcmV2IC0gMTsKICAgICAgICBpQmFzZSA9IGlQcmV2OwogICAgICAgIHJCYXNlID0gclByZXY7CiAgICAgICAgZ0Jhc2UgPSBnUHJldjsKICAgICAgICBiQmFzZSA9IGJQcmV2OwogICAgICB9CiAgICAgIGlQcmV2ID0gaTsKICAgICAgclByZXYgPSByOwogICAgICBnUHJldiA9IGc7CiAgICAgIGJQcmV2ID0gYjsKICAgIH0KICAgIGNvbG9yU3RvcHMucHVzaChbMSwgVXRpbC5tYWtlSGV4Q29sb3IoclByZXYsIGdQcmV2LCBiUHJldildKTsKICAgIGxldCBiYWNrZ3JvdW5kID0gInRyYW5zcGFyZW50IjsKICAgIGlmIChkaWN0LmhhcygiQmFja2dyb3VuZCIpKSB7CiAgICAgIGJhY2tncm91bmQgPSBjcy5nZXRSZ2JIZXgoZGljdC5nZXQoIkJhY2tncm91bmQiKSwgMCk7CiAgICB9CiAgICBpZiAoIWV4dGVuZFN0YXJ0KSB7CiAgICAgIGNvbG9yU3RvcHMudW5zaGlmdChbMCwgYmFja2dyb3VuZF0pOwogICAgICBjb2xvclN0b3BzWzFdWzBdICs9IEJhc2VTaGFkaW5nLlNNQUxMX05VTUJFUjsKICAgIH0KICAgIGlmICghZXh0ZW5kRW5kKSB7CiAgICAgIGNvbG9yU3RvcHMuYXQoLTEpWzBdIC09IEJhc2VTaGFkaW5nLlNNQUxMX05VTUJFUjsKICAgICAgY29sb3JTdG9wcy5wdXNoKFsxLCBiYWNrZ3JvdW5kXSk7CiAgICB9CiAgICB0aGlzLmNvbG9yU3RvcHMgPSBjb2xvclN0b3BzOwogIH0KICBnZXRJUigpIHsKICAgIGNvbnN0IHsKICAgICAgY29vcmRzQXJyLAogICAgICBzaGFkaW5nVHlwZQogICAgfSA9IHRoaXM7CiAgICBsZXQgdHlwZSwgcDAsIHAxLCByMCwgcjE7CiAgICBpZiAoc2hhZGluZ1R5cGUgPT09IFNoYWRpbmdUeXBlLkFYSUFMKSB7CiAgICAgIHAwID0gW2Nvb3Jkc0FyclswXSwgY29vcmRzQXJyWzFdXTsKICAgICAgcDEgPSBbY29vcmRzQXJyWzJdLCBjb29yZHNBcnJbM11dOwogICAgICByMCA9IG51bGw7CiAgICAgIHIxID0gbnVsbDsKICAgICAgdHlwZSA9ICJheGlhbCI7CiAgICB9IGVsc2UgaWYgKHNoYWRpbmdUeXBlID09PSBTaGFkaW5nVHlwZS5SQURJQUwpIHsKICAgICAgcDAgPSBbY29vcmRzQXJyWzBdLCBjb29yZHNBcnJbMV1dOwogICAgICBwMSA9IFtjb29yZHNBcnJbM10sIGNvb3Jkc0Fycls0XV07CiAgICAgIHIwID0gY29vcmRzQXJyWzJdOwogICAgICByMSA9IGNvb3Jkc0Fycls1XTsKICAgICAgdHlwZSA9ICJyYWRpYWwiOwogICAgfSBlbHNlIHsKICAgICAgdW5yZWFjaGFibGUoYGdldFBhdHRlcm4gdHlwZSB1bmtub3duOiAke3NoYWRpbmdUeXBlfWApOwogICAgfQogICAgcmV0dXJuIFsiUmFkaWFsQXhpYWwiLCB0eXBlLCB0aGlzLmJib3gsIHRoaXMuY29sb3JTdG9wcywgcDAsIHAxLCByMCwgcjFdOwogIH0KfQpjbGFzcyBNZXNoU3RyZWFtUmVhZGVyIHsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIGNvbnRleHQpIHsKICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtOwogICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDsKICAgIHRoaXMuYnVmZmVyID0gMDsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gMDsKICAgIGNvbnN0IG51bUNvbXBzID0gY29udGV4dC5udW1Db21wczsKICAgIHRoaXMudG1wQ29tcHNCdWYgPSBuZXcgRmxvYXQzMkFycmF5KG51bUNvbXBzKTsKICAgIGNvbnN0IGNzTnVtQ29tcHMgPSBjb250ZXh0LmNvbG9yU3BhY2UubnVtQ29tcHM7CiAgICB0aGlzLnRtcENzQ29tcHNCdWYgPSBjb250ZXh0LmNvbG9yRm4gPyBuZXcgRmxvYXQzMkFycmF5KGNzTnVtQ29tcHMpIDogdGhpcy50bXBDb21wc0J1ZjsKICB9CiAgZ2V0IGhhc0RhdGEoKSB7CiAgICBpZiAodGhpcy5zdHJlYW0uZW5kKSB7CiAgICAgIHJldHVybiB0aGlzLnN0cmVhbS5wb3MgPCB0aGlzLnN0cmVhbS5lbmQ7CiAgICB9CiAgICBpZiAodGhpcy5idWZmZXJMZW5ndGggPiAwKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgY29uc3QgbmV4dEJ5dGUgPSB0aGlzLnN0cmVhbS5nZXRCeXRlKCk7CiAgICBpZiAobmV4dEJ5dGUgPCAwKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHRoaXMuYnVmZmVyID0gbmV4dEJ5dGU7CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IDg7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgcmVhZEJpdHMobikgewogICAgY29uc3QgewogICAgICBzdHJlYW0KICAgIH0gPSB0aGlzOwogICAgbGV0IHsKICAgICAgYnVmZmVyLAogICAgICBidWZmZXJMZW5ndGgKICAgIH0gPSB0aGlzOwogICAgaWYgKG4gPT09IDMyKSB7CiAgICAgIGlmIChidWZmZXJMZW5ndGggPT09IDApIHsKICAgICAgICByZXR1cm4gc3RyZWFtLmdldEludDMyKCkgPj4+IDA7CiAgICAgIH0KICAgICAgYnVmZmVyID0gYnVmZmVyIDw8IDI0IHwgc3RyZWFtLmdldEJ5dGUoKSA8PCAxNiB8IHN0cmVhbS5nZXRCeXRlKCkgPDwgOCB8IHN0cmVhbS5nZXRCeXRlKCk7CiAgICAgIGNvbnN0IG5leHRCeXRlID0gc3RyZWFtLmdldEJ5dGUoKTsKICAgICAgdGhpcy5idWZmZXIgPSBuZXh0Qnl0ZSAmICgxIDw8IGJ1ZmZlckxlbmd0aCkgLSAxOwogICAgICByZXR1cm4gKGJ1ZmZlciA8PCA4IC0gYnVmZmVyTGVuZ3RoIHwgKG5leHRCeXRlICYgMHhmZikgPj4gYnVmZmVyTGVuZ3RoKSA+Pj4gMDsKICAgIH0KICAgIGlmIChuID09PSA4ICYmIGJ1ZmZlckxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gc3RyZWFtLmdldEJ5dGUoKTsKICAgIH0KICAgIHdoaWxlIChidWZmZXJMZW5ndGggPCBuKSB7CiAgICAgIGJ1ZmZlciA9IGJ1ZmZlciA8PCA4IHwgc3RyZWFtLmdldEJ5dGUoKTsKICAgICAgYnVmZmVyTGVuZ3RoICs9IDg7CiAgICB9CiAgICBidWZmZXJMZW5ndGggLT0gbjsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gYnVmZmVyTGVuZ3RoOwogICAgdGhpcy5idWZmZXIgPSBidWZmZXIgJiAoMSA8PCBidWZmZXJMZW5ndGgpIC0gMTsKICAgIHJldHVybiBidWZmZXIgPj4gYnVmZmVyTGVuZ3RoOwogIH0KICBhbGlnbigpIHsKICAgIHRoaXMuYnVmZmVyID0gMDsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gMDsKICB9CiAgcmVhZEZsYWcoKSB7CiAgICByZXR1cm4gdGhpcy5yZWFkQml0cyh0aGlzLmNvbnRleHQuYml0c1BlckZsYWcpOwogIH0KICByZWFkQ29vcmRpbmF0ZSgpIHsKICAgIGNvbnN0IHsKICAgICAgYml0c1BlckNvb3JkaW5hdGUsCiAgICAgIGRlY29kZQogICAgfSA9IHRoaXMuY29udGV4dDsKICAgIGNvbnN0IHhpID0gdGhpcy5yZWFkQml0cyhiaXRzUGVyQ29vcmRpbmF0ZSk7CiAgICBjb25zdCB5aSA9IHRoaXMucmVhZEJpdHMoYml0c1BlckNvb3JkaW5hdGUpOwogICAgY29uc3Qgc2NhbGUgPSBiaXRzUGVyQ29vcmRpbmF0ZSA8IDMyID8gMSAvICgoMSA8PCBiaXRzUGVyQ29vcmRpbmF0ZSkgLSAxKSA6IDIuMzI4MzA2NDM2NTM4Njk2M2UtMTA7CiAgICByZXR1cm4gW3hpICogc2NhbGUgKiAoZGVjb2RlWzFdIC0gZGVjb2RlWzBdKSArIGRlY29kZVswXSwgeWkgKiBzY2FsZSAqIChkZWNvZGVbM10gLSBkZWNvZGVbMl0pICsgZGVjb2RlWzJdXTsKICB9CiAgcmVhZENvbXBvbmVudHMoKSB7CiAgICBjb25zdCB7CiAgICAgIGJpdHNQZXJDb21wb25lbnQsCiAgICAgIGNvbG9yRm4sCiAgICAgIGNvbG9yU3BhY2UsCiAgICAgIGRlY29kZSwKICAgICAgbnVtQ29tcHMKICAgIH0gPSB0aGlzLmNvbnRleHQ7CiAgICBjb25zdCBzY2FsZSA9IGJpdHNQZXJDb21wb25lbnQgPCAzMiA/IDEgLyAoKDEgPDwgYml0c1BlckNvbXBvbmVudCkgLSAxKSA6IDIuMzI4MzA2NDM2NTM4Njk2M2UtMTA7CiAgICBjb25zdCBjb21wb25lbnRzID0gdGhpcy50bXBDb21wc0J1ZjsKICAgIGZvciAobGV0IGkgPSAwLCBqID0gNDsgaSA8IG51bUNvbXBzOyBpKyssIGogKz0gMikgewogICAgICBjb25zdCBjaSA9IHRoaXMucmVhZEJpdHMoYml0c1BlckNvbXBvbmVudCk7CiAgICAgIGNvbXBvbmVudHNbaV0gPSBjaSAqIHNjYWxlICogKGRlY29kZVtqICsgMV0gLSBkZWNvZGVbal0pICsgZGVjb2RlW2pdOwogICAgfQogICAgY29uc3QgY29sb3IgPSB0aGlzLnRtcENzQ29tcHNCdWY7CiAgICBjb2xvckZuPy4oY29tcG9uZW50cywgMCwgY29sb3IsIDApOwogICAgcmV0dXJuIGNvbG9yU3BhY2UuZ2V0UmdiKGNvbG9yLCAwKTsKICB9Cn0KbGV0IGJDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CmZ1bmN0aW9uIGJ1aWxkQihjb3VudCkgewogIGNvbnN0IGx1dCA9IFtdOwogIGZvciAobGV0IGkgPSAwOyBpIDw9IGNvdW50OyBpKyspIHsKICAgIGNvbnN0IHQgPSBpIC8gY291bnQsCiAgICAgIHRfID0gMSAtIHQ7CiAgICBsdXQucHVzaChuZXcgRmxvYXQzMkFycmF5KFt0XyAqKiAzLCAzICogdCAqIHRfICoqIDIsIDMgKiB0ICoqIDIgKiB0XywgdCAqKiAzXSkpOwogIH0KICByZXR1cm4gbHV0Owp9CmZ1bmN0aW9uIGdldEIoY291bnQpIHsKICByZXR1cm4gYkNhY2hlW2NvdW50XSB8fD0gYnVpbGRCKGNvdW50KTsKfQpmdW5jdGlvbiBjbGVhclBhdHRlcm5DYWNoZXMoKSB7CiAgYkNhY2hlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKfQpjbGFzcyBNZXNoU2hhZGluZyBleHRlbmRzIEJhc2VTaGFkaW5nIHsKICBzdGF0aWMgTUlOX1NQTElUX1BBVENIX0NIVU5LU19BTU9VTlQgPSAzOwogIHN0YXRpYyBNQVhfU1BMSVRfUEFUQ0hfQ0hVTktTX0FNT1VOVCA9IDIwOwogIHN0YXRpYyBUUklBTkdMRV9ERU5TSVRZID0gMjA7CiAgY29uc3RydWN0b3Ioc3RyZWFtLCB4cmVmLCByZXNvdXJjZXMsIHBkZkZ1bmN0aW9uRmFjdG9yeSwgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLCBsb2NhbENvbG9yU3BhY2VDYWNoZSkgewogICAgc3VwZXIoKTsKICAgIGlmICghKHN0cmVhbSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiTWVzaCBkYXRhIGlzIG5vdCBhIHN0cmVhbSIpOwogICAgfQogICAgY29uc3QgZGljdCA9IHN0cmVhbS5kaWN0OwogICAgdGhpcy5zaGFkaW5nVHlwZSA9IGRpY3QuZ2V0KCJTaGFkaW5nVHlwZSIpOwogICAgdGhpcy5iYm94ID0gbG9va3VwTm9ybWFsUmVjdChkaWN0LmdldEFycmF5KCJCQm94IiksIG51bGwpOwogICAgY29uc3QgY3MgPSBDb2xvclNwYWNlVXRpbHMucGFyc2UoewogICAgICBjczogZGljdC5nZXRSYXcoIkNTIikgfHwgZGljdC5nZXRSYXcoIkNvbG9yU3BhY2UiKSwKICAgICAgeHJlZiwKICAgICAgcmVzb3VyY2VzLAogICAgICBwZGZGdW5jdGlvbkZhY3RvcnksCiAgICAgIGdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUKICAgIH0pOwogICAgdGhpcy5iYWNrZ3JvdW5kID0gZGljdC5oYXMoIkJhY2tncm91bmQiKSA/IGNzLmdldFJnYihkaWN0LmdldCgiQmFja2dyb3VuZCIpLCAwKSA6IG51bGw7CiAgICBjb25zdCBmbk9iaiA9IGRpY3QuZ2V0UmF3KCJGdW5jdGlvbiIpOwogICAgY29uc3QgZm4gPSBmbk9iaiA/IHBkZkZ1bmN0aW9uRmFjdG9yeS5jcmVhdGUoZm5PYmosIHRydWUpIDogbnVsbDsKICAgIHRoaXMuY29vcmRzID0gW107CiAgICB0aGlzLmNvbG9ycyA9IFtdOwogICAgdGhpcy5maWd1cmVzID0gW107CiAgICBjb25zdCBkZWNvZGVDb250ZXh0ID0gewogICAgICBiaXRzUGVyQ29vcmRpbmF0ZTogZGljdC5nZXQoIkJpdHNQZXJDb29yZGluYXRlIiksCiAgICAgIGJpdHNQZXJDb21wb25lbnQ6IGRpY3QuZ2V0KCJCaXRzUGVyQ29tcG9uZW50IiksCiAgICAgIGJpdHNQZXJGbGFnOiBkaWN0LmdldCgiQml0c1BlckZsYWciKSwKICAgICAgZGVjb2RlOiBkaWN0LmdldEFycmF5KCJEZWNvZGUiKSwKICAgICAgY29sb3JGbjogZm4sCiAgICAgIGNvbG9yU3BhY2U6IGNzLAogICAgICBudW1Db21wczogZm4gPyAxIDogY3MubnVtQ29tcHMKICAgIH07CiAgICBjb25zdCByZWFkZXIgPSBuZXcgTWVzaFN0cmVhbVJlYWRlcihzdHJlYW0sIGRlY29kZUNvbnRleHQpOwogICAgbGV0IHBhdGNoTWVzaCA9IGZhbHNlOwogICAgc3dpdGNoICh0aGlzLnNoYWRpbmdUeXBlKSB7CiAgICAgIGNhc2UgU2hhZGluZ1R5cGUuRlJFRV9GT1JNX01FU0g6CiAgICAgICAgdGhpcy5fZGVjb2RlVHlwZTRTaGFkaW5nKHJlYWRlcik7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgU2hhZGluZ1R5cGUuTEFUVElDRV9GT1JNX01FU0g6CiAgICAgICAgY29uc3QgdmVydGljZXNQZXJSb3cgPSBkaWN0LmdldCgiVmVydGljZXNQZXJSb3ciKSB8IDA7CiAgICAgICAgaWYgKHZlcnRpY2VzUGVyUm93IDwgMikgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFZlcnRpY2VzUGVyUm93Iik7CiAgICAgICAgfQogICAgICAgIHRoaXMuX2RlY29kZVR5cGU1U2hhZGluZyhyZWFkZXIsIHZlcnRpY2VzUGVyUm93KTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBTaGFkaW5nVHlwZS5DT09OU19QQVRDSF9NRVNIOgogICAgICAgIHRoaXMuX2RlY29kZVR5cGU2U2hhZGluZyhyZWFkZXIpOwogICAgICAgIHBhdGNoTWVzaCA9IHRydWU7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgU2hhZGluZ1R5cGUuVEVOU09SX1BBVENIX01FU0g6CiAgICAgICAgdGhpcy5fZGVjb2RlVHlwZTdTaGFkaW5nKHJlYWRlcik7CiAgICAgICAgcGF0Y2hNZXNoID0gdHJ1ZTsKICAgICAgICBicmVhazsKICAgICAgZGVmYXVsdDoKICAgICAgICB1bnJlYWNoYWJsZSgiVW5zdXBwb3J0ZWQgbWVzaCB0eXBlLiIpOwogICAgICAgIGJyZWFrOwogICAgfQogICAgaWYgKHBhdGNoTWVzaCkgewogICAgICB0aGlzLl91cGRhdGVCb3VuZHMoKTsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gdGhpcy5maWd1cmVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICB0aGlzLl9idWlsZEZpZ3VyZUZyb21QYXRjaChpKTsKICAgICAgfQogICAgfQogICAgdGhpcy5fdXBkYXRlQm91bmRzKCk7CiAgICB0aGlzLl9wYWNrRGF0YSgpOwogIH0KICBfZGVjb2RlVHlwZTRTaGFkaW5nKHJlYWRlcikgewogICAgY29uc3QgY29vcmRzID0gdGhpcy5jb29yZHM7CiAgICBjb25zdCBjb2xvcnMgPSB0aGlzLmNvbG9yczsKICAgIGNvbnN0IG9wZXJhdG9ycyA9IFtdOwogICAgY29uc3QgcHMgPSBbXTsKICAgIGxldCB2ZXJ0aWNlc0xlZnQgPSAwOwogICAgd2hpbGUgKHJlYWRlci5oYXNEYXRhKSB7CiAgICAgIGNvbnN0IGYgPSByZWFkZXIucmVhZEZsYWcoKTsKICAgICAgY29uc3QgY29vcmQgPSByZWFkZXIucmVhZENvb3JkaW5hdGUoKTsKICAgICAgY29uc3QgY29sb3IgPSByZWFkZXIucmVhZENvbXBvbmVudHMoKTsKICAgICAgaWYgKHZlcnRpY2VzTGVmdCA9PT0gMCkgewogICAgICAgIGlmICghKDAgPD0gZiAmJiBmIDw9IDIpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVua25vd24gdHlwZTQgZmxhZyIpOwogICAgICAgIH0KICAgICAgICBzd2l0Y2ggKGYpIHsKICAgICAgICAgIGNhc2UgMDoKICAgICAgICAgICAgdmVydGljZXNMZWZ0ID0gMzsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDE6CiAgICAgICAgICAgIHBzLnB1c2gocHMuYXQoLTIpLCBwcy5hdCgtMSkpOwogICAgICAgICAgICB2ZXJ0aWNlc0xlZnQgPSAxOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMjoKICAgICAgICAgICAgcHMucHVzaChwcy5hdCgtMyksIHBzLmF0KC0xKSk7CiAgICAgICAgICAgIHZlcnRpY2VzTGVmdCA9IDE7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBvcGVyYXRvcnMucHVzaChmKTsKICAgICAgfQogICAgICBwcy5wdXNoKGNvb3Jkcy5sZW5ndGgpOwogICAgICBjb29yZHMucHVzaChjb29yZCk7CiAgICAgIGNvbG9ycy5wdXNoKGNvbG9yKTsKICAgICAgdmVydGljZXNMZWZ0LS07CiAgICAgIHJlYWRlci5hbGlnbigpOwogICAgfQogICAgdGhpcy5maWd1cmVzLnB1c2goewogICAgICB0eXBlOiAidHJpYW5nbGVzIiwKICAgICAgY29vcmRzOiBuZXcgSW50MzJBcnJheShwcyksCiAgICAgIGNvbG9yczogbmV3IEludDMyQXJyYXkocHMpCiAgICB9KTsKICB9CiAgX2RlY29kZVR5cGU1U2hhZGluZyhyZWFkZXIsIHZlcnRpY2VzUGVyUm93KSB7CiAgICBjb25zdCBjb29yZHMgPSB0aGlzLmNvb3JkczsKICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuY29sb3JzOwogICAgY29uc3QgcHMgPSBbXTsKICAgIHdoaWxlIChyZWFkZXIuaGFzRGF0YSkgewogICAgICBjb25zdCBjb29yZCA9IHJlYWRlci5yZWFkQ29vcmRpbmF0ZSgpOwogICAgICBjb25zdCBjb2xvciA9IHJlYWRlci5yZWFkQ29tcG9uZW50cygpOwogICAgICBwcy5wdXNoKGNvb3Jkcy5sZW5ndGgpOwogICAgICBjb29yZHMucHVzaChjb29yZCk7CiAgICAgIGNvbG9ycy5wdXNoKGNvbG9yKTsKICAgIH0KICAgIHRoaXMuZmlndXJlcy5wdXNoKHsKICAgICAgdHlwZTogImxhdHRpY2UiLAogICAgICBjb29yZHM6IG5ldyBJbnQzMkFycmF5KHBzKSwKICAgICAgY29sb3JzOiBuZXcgSW50MzJBcnJheShwcyksCiAgICAgIHZlcnRpY2VzUGVyUm93CiAgICB9KTsKICB9CiAgX2RlY29kZVR5cGU2U2hhZGluZyhyZWFkZXIpIHsKICAgIGNvbnN0IGNvb3JkcyA9IHRoaXMuY29vcmRzOwogICAgY29uc3QgY29sb3JzID0gdGhpcy5jb2xvcnM7CiAgICBjb25zdCBwcyA9IG5ldyBJbnQzMkFycmF5KDE2KTsKICAgIGNvbnN0IGNzID0gbmV3IEludDMyQXJyYXkoNCk7CiAgICB3aGlsZSAocmVhZGVyLmhhc0RhdGEpIHsKICAgICAgY29uc3QgZiA9IHJlYWRlci5yZWFkRmxhZygpOwogICAgICBpZiAoISgwIDw9IGYgJiYgZiA8PSAzKSkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiVW5rbm93biB0eXBlNiBmbGFnIik7CiAgICAgIH0KICAgICAgY29uc3QgcGkgPSBjb29yZHMubGVuZ3RoOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBmICE9PSAwID8gOCA6IDEyOyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvb3Jkcy5wdXNoKHJlYWRlci5yZWFkQ29vcmRpbmF0ZSgpKTsKICAgICAgfQogICAgICBjb25zdCBjaSA9IGNvbG9ycy5sZW5ndGg7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGYgIT09IDAgPyAyIDogNDsgaSA8IGlpOyBpKyspIHsKICAgICAgICBjb2xvcnMucHVzaChyZWFkZXIucmVhZENvbXBvbmVudHMoKSk7CiAgICAgIH0KICAgICAgbGV0IHRtcDEsIHRtcDIsIHRtcDMsIHRtcDQ7CiAgICAgIHN3aXRjaCAoZikgewogICAgICAgIGNhc2UgMDoKICAgICAgICAgIHBzWzEyXSA9IHBpICsgMzsKICAgICAgICAgIHBzWzEzXSA9IHBpICsgNDsKICAgICAgICAgIHBzWzE0XSA9IHBpICsgNTsKICAgICAgICAgIHBzWzE1XSA9IHBpICsgNjsKICAgICAgICAgIHBzWzhdID0gcGkgKyAyOwogICAgICAgICAgcHNbMTFdID0gcGkgKyA3OwogICAgICAgICAgcHNbNF0gPSBwaSArIDE7CiAgICAgICAgICBwc1s3XSA9IHBpICsgODsKICAgICAgICAgIHBzWzBdID0gcGk7CiAgICAgICAgICBwc1sxXSA9IHBpICsgMTE7CiAgICAgICAgICBwc1syXSA9IHBpICsgMTA7CiAgICAgICAgICBwc1szXSA9IHBpICsgOTsKICAgICAgICAgIGNzWzJdID0gY2kgKyAxOwogICAgICAgICAgY3NbM10gPSBjaSArIDI7CiAgICAgICAgICBjc1swXSA9IGNpOwogICAgICAgICAgY3NbMV0gPSBjaSArIDM7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDE6CiAgICAgICAgICB0bXAxID0gcHNbMTJdOwogICAgICAgICAgdG1wMiA9IHBzWzEzXTsKICAgICAgICAgIHRtcDMgPSBwc1sxNF07CiAgICAgICAgICB0bXA0ID0gcHNbMTVdOwogICAgICAgICAgcHNbMTJdID0gdG1wNDsKICAgICAgICAgIHBzWzEzXSA9IHBpICsgMDsKICAgICAgICAgIHBzWzE0XSA9IHBpICsgMTsKICAgICAgICAgIHBzWzE1XSA9IHBpICsgMjsKICAgICAgICAgIHBzWzhdID0gdG1wMzsKICAgICAgICAgIHBzWzExXSA9IHBpICsgMzsKICAgICAgICAgIHBzWzRdID0gdG1wMjsKICAgICAgICAgIHBzWzddID0gcGkgKyA0OwogICAgICAgICAgcHNbMF0gPSB0bXAxOwogICAgICAgICAgcHNbMV0gPSBwaSArIDc7CiAgICAgICAgICBwc1syXSA9IHBpICsgNjsKICAgICAgICAgIHBzWzNdID0gcGkgKyA1OwogICAgICAgICAgdG1wMSA9IGNzWzJdOwogICAgICAgICAgdG1wMiA9IGNzWzNdOwogICAgICAgICAgY3NbMl0gPSB0bXAyOwogICAgICAgICAgY3NbM10gPSBjaTsKICAgICAgICAgIGNzWzBdID0gdG1wMTsKICAgICAgICAgIGNzWzFdID0gY2kgKyAxOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyOgogICAgICAgICAgdG1wMSA9IHBzWzE1XTsKICAgICAgICAgIHRtcDIgPSBwc1sxMV07CiAgICAgICAgICBwc1sxMl0gPSBwc1szXTsKICAgICAgICAgIHBzWzEzXSA9IHBpICsgMDsKICAgICAgICAgIHBzWzE0XSA9IHBpICsgMTsKICAgICAgICAgIHBzWzE1XSA9IHBpICsgMjsKICAgICAgICAgIHBzWzhdID0gcHNbN107CiAgICAgICAgICBwc1sxMV0gPSBwaSArIDM7CiAgICAgICAgICBwc1s0XSA9IHRtcDI7CiAgICAgICAgICBwc1s3XSA9IHBpICsgNDsKICAgICAgICAgIHBzWzBdID0gdG1wMTsKICAgICAgICAgIHBzWzFdID0gcGkgKyA3OwogICAgICAgICAgcHNbMl0gPSBwaSArIDY7CiAgICAgICAgICBwc1szXSA9IHBpICsgNTsKICAgICAgICAgIHRtcDEgPSBjc1szXTsKICAgICAgICAgIGNzWzJdID0gY3NbMV07CiAgICAgICAgICBjc1szXSA9IGNpOwogICAgICAgICAgY3NbMF0gPSB0bXAxOwogICAgICAgICAgY3NbMV0gPSBjaSArIDE7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDM6CiAgICAgICAgICBwc1sxMl0gPSBwc1swXTsKICAgICAgICAgIHBzWzEzXSA9IHBpICsgMDsKICAgICAgICAgIHBzWzE0XSA9IHBpICsgMTsKICAgICAgICAgIHBzWzE1XSA9IHBpICsgMjsKICAgICAgICAgIHBzWzhdID0gcHNbMV07CiAgICAgICAgICBwc1sxMV0gPSBwaSArIDM7CiAgICAgICAgICBwc1s0XSA9IHBzWzJdOwogICAgICAgICAgcHNbN10gPSBwaSArIDQ7CiAgICAgICAgICBwc1swXSA9IHBzWzNdOwogICAgICAgICAgcHNbMV0gPSBwaSArIDc7CiAgICAgICAgICBwc1syXSA9IHBpICsgNjsKICAgICAgICAgIHBzWzNdID0gcGkgKyA1OwogICAgICAgICAgY3NbMl0gPSBjc1swXTsKICAgICAgICAgIGNzWzNdID0gY2k7CiAgICAgICAgICBjc1swXSA9IGNzWzFdOwogICAgICAgICAgY3NbMV0gPSBjaSArIDE7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICBwc1s1XSA9IGNvb3Jkcy5sZW5ndGg7CiAgICAgIGNvb3Jkcy5wdXNoKFsoLTQgKiBjb29yZHNbcHNbMF1dWzBdIC0gY29vcmRzW3BzWzE1XV1bMF0gKyA2ICogKGNvb3Jkc1twc1s0XV1bMF0gKyBjb29yZHNbcHNbMV1dWzBdKSAtIDIgKiAoY29vcmRzW3BzWzEyXV1bMF0gKyBjb29yZHNbcHNbM11dWzBdKSArIDMgKiAoY29vcmRzW3BzWzEzXV1bMF0gKyBjb29yZHNbcHNbN11dWzBdKSkgLyA5LCAoLTQgKiBjb29yZHNbcHNbMF1dWzFdIC0gY29vcmRzW3BzWzE1XV1bMV0gKyA2ICogKGNvb3Jkc1twc1s0XV1bMV0gKyBjb29yZHNbcHNbMV1dWzFdKSAtIDIgKiAoY29vcmRzW3BzWzEyXV1bMV0gKyBjb29yZHNbcHNbM11dWzFdKSArIDMgKiAoY29vcmRzW3BzWzEzXV1bMV0gKyBjb29yZHNbcHNbN11dWzFdKSkgLyA5XSk7CiAgICAgIHBzWzZdID0gY29vcmRzLmxlbmd0aDsKICAgICAgY29vcmRzLnB1c2goWygtNCAqIGNvb3Jkc1twc1szXV1bMF0gLSBjb29yZHNbcHNbMTJdXVswXSArIDYgKiAoY29vcmRzW3BzWzJdXVswXSArIGNvb3Jkc1twc1s3XV1bMF0pIC0gMiAqIChjb29yZHNbcHNbMF1dWzBdICsgY29vcmRzW3BzWzE1XV1bMF0pICsgMyAqIChjb29yZHNbcHNbNF1dWzBdICsgY29vcmRzW3BzWzE0XV1bMF0pKSAvIDksICgtNCAqIGNvb3Jkc1twc1szXV1bMV0gLSBjb29yZHNbcHNbMTJdXVsxXSArIDYgKiAoY29vcmRzW3BzWzJdXVsxXSArIGNvb3Jkc1twc1s3XV1bMV0pIC0gMiAqIChjb29yZHNbcHNbMF1dWzFdICsgY29vcmRzW3BzWzE1XV1bMV0pICsgMyAqIChjb29yZHNbcHNbNF1dWzFdICsgY29vcmRzW3BzWzE0XV1bMV0pKSAvIDldKTsKICAgICAgcHNbOV0gPSBjb29yZHMubGVuZ3RoOwogICAgICBjb29yZHMucHVzaChbKC00ICogY29vcmRzW3BzWzEyXV1bMF0gLSBjb29yZHNbcHNbM11dWzBdICsgNiAqIChjb29yZHNbcHNbOF1dWzBdICsgY29vcmRzW3BzWzEzXV1bMF0pIC0gMiAqIChjb29yZHNbcHNbMF1dWzBdICsgY29vcmRzW3BzWzE1XV1bMF0pICsgMyAqIChjb29yZHNbcHNbMTFdXVswXSArIGNvb3Jkc1twc1sxXV1bMF0pKSAvIDksICgtNCAqIGNvb3Jkc1twc1sxMl1dWzFdIC0gY29vcmRzW3BzWzNdXVsxXSArIDYgKiAoY29vcmRzW3BzWzhdXVsxXSArIGNvb3Jkc1twc1sxM11dWzFdKSAtIDIgKiAoY29vcmRzW3BzWzBdXVsxXSArIGNvb3Jkc1twc1sxNV1dWzFdKSArIDMgKiAoY29vcmRzW3BzWzExXV1bMV0gKyBjb29yZHNbcHNbMV1dWzFdKSkgLyA5XSk7CiAgICAgIHBzWzEwXSA9IGNvb3Jkcy5sZW5ndGg7CiAgICAgIGNvb3Jkcy5wdXNoKFsoLTQgKiBjb29yZHNbcHNbMTVdXVswXSAtIGNvb3Jkc1twc1swXV1bMF0gKyA2ICogKGNvb3Jkc1twc1sxMV1dWzBdICsgY29vcmRzW3BzWzE0XV1bMF0pIC0gMiAqIChjb29yZHNbcHNbMTJdXVswXSArIGNvb3Jkc1twc1szXV1bMF0pICsgMyAqIChjb29yZHNbcHNbMl1dWzBdICsgY29vcmRzW3BzWzhdXVswXSkpIC8gOSwgKC00ICogY29vcmRzW3BzWzE1XV1bMV0gLSBjb29yZHNbcHNbMF1dWzFdICsgNiAqIChjb29yZHNbcHNbMTFdXVsxXSArIGNvb3Jkc1twc1sxNF1dWzFdKSAtIDIgKiAoY29vcmRzW3BzWzEyXV1bMV0gKyBjb29yZHNbcHNbM11dWzFdKSArIDMgKiAoY29vcmRzW3BzWzJdXVsxXSArIGNvb3Jkc1twc1s4XV1bMV0pKSAvIDldKTsKICAgICAgdGhpcy5maWd1cmVzLnB1c2goewogICAgICAgIHR5cGU6ICJwYXRjaCIsCiAgICAgICAgY29vcmRzOiBuZXcgSW50MzJBcnJheShwcyksCiAgICAgICAgY29sb3JzOiBuZXcgSW50MzJBcnJheShjcykKICAgICAgfSk7CiAgICB9CiAgfQogIF9kZWNvZGVUeXBlN1NoYWRpbmcocmVhZGVyKSB7CiAgICBjb25zdCBjb29yZHMgPSB0aGlzLmNvb3JkczsKICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuY29sb3JzOwogICAgY29uc3QgcHMgPSBuZXcgSW50MzJBcnJheSgxNik7CiAgICBjb25zdCBjcyA9IG5ldyBJbnQzMkFycmF5KDQpOwogICAgd2hpbGUgKHJlYWRlci5oYXNEYXRhKSB7CiAgICAgIGNvbnN0IGYgPSByZWFkZXIucmVhZEZsYWcoKTsKICAgICAgaWYgKCEoMCA8PSBmICYmIGYgPD0gMykpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVua25vd24gdHlwZTcgZmxhZyIpOwogICAgICB9CiAgICAgIGNvbnN0IHBpID0gY29vcmRzLmxlbmd0aDsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZiAhPT0gMCA/IDEyIDogMTY7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29vcmRzLnB1c2gocmVhZGVyLnJlYWRDb29yZGluYXRlKCkpOwogICAgICB9CiAgICAgIGNvbnN0IGNpID0gY29sb3JzLmxlbmd0aDsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZiAhPT0gMCA/IDIgOiA0OyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbG9ycy5wdXNoKHJlYWRlci5yZWFkQ29tcG9uZW50cygpKTsKICAgICAgfQogICAgICBsZXQgdG1wMSwgdG1wMiwgdG1wMywgdG1wNDsKICAgICAgc3dpdGNoIChmKSB7CiAgICAgICAgY2FzZSAwOgogICAgICAgICAgcHNbMTJdID0gcGkgKyAzOwogICAgICAgICAgcHNbMTNdID0gcGkgKyA0OwogICAgICAgICAgcHNbMTRdID0gcGkgKyA1OwogICAgICAgICAgcHNbMTVdID0gcGkgKyA2OwogICAgICAgICAgcHNbOF0gPSBwaSArIDI7CiAgICAgICAgICBwc1s5XSA9IHBpICsgMTM7CiAgICAgICAgICBwc1sxMF0gPSBwaSArIDE0OwogICAgICAgICAgcHNbMTFdID0gcGkgKyA3OwogICAgICAgICAgcHNbNF0gPSBwaSArIDE7CiAgICAgICAgICBwc1s1XSA9IHBpICsgMTI7CiAgICAgICAgICBwc1s2XSA9IHBpICsgMTU7CiAgICAgICAgICBwc1s3XSA9IHBpICsgODsKICAgICAgICAgIHBzWzBdID0gcGk7CiAgICAgICAgICBwc1sxXSA9IHBpICsgMTE7CiAgICAgICAgICBwc1syXSA9IHBpICsgMTA7CiAgICAgICAgICBwc1szXSA9IHBpICsgOTsKICAgICAgICAgIGNzWzJdID0gY2kgKyAxOwogICAgICAgICAgY3NbM10gPSBjaSArIDI7CiAgICAgICAgICBjc1swXSA9IGNpOwogICAgICAgICAgY3NbMV0gPSBjaSArIDM7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDE6CiAgICAgICAgICB0bXAxID0gcHNbMTJdOwogICAgICAgICAgdG1wMiA9IHBzWzEzXTsKICAgICAgICAgIHRtcDMgPSBwc1sxNF07CiAgICAgICAgICB0bXA0ID0gcHNbMTVdOwogICAgICAgICAgcHNbMTJdID0gdG1wNDsKICAgICAgICAgIHBzWzEzXSA9IHBpICsgMDsKICAgICAgICAgIHBzWzE0XSA9IHBpICsgMTsKICAgICAgICAgIHBzWzE1XSA9IHBpICsgMjsKICAgICAgICAgIHBzWzhdID0gdG1wMzsKICAgICAgICAgIHBzWzldID0gcGkgKyA5OwogICAgICAgICAgcHNbMTBdID0gcGkgKyAxMDsKICAgICAgICAgIHBzWzExXSA9IHBpICsgMzsKICAgICAgICAgIHBzWzRdID0gdG1wMjsKICAgICAgICAgIHBzWzVdID0gcGkgKyA4OwogICAgICAgICAgcHNbNl0gPSBwaSArIDExOwogICAgICAgICAgcHNbN10gPSBwaSArIDQ7CiAgICAgICAgICBwc1swXSA9IHRtcDE7CiAgICAgICAgICBwc1sxXSA9IHBpICsgNzsKICAgICAgICAgIHBzWzJdID0gcGkgKyA2OwogICAgICAgICAgcHNbM10gPSBwaSArIDU7CiAgICAgICAgICB0bXAxID0gY3NbMl07CiAgICAgICAgICB0bXAyID0gY3NbM107CiAgICAgICAgICBjc1syXSA9IHRtcDI7CiAgICAgICAgICBjc1szXSA9IGNpOwogICAgICAgICAgY3NbMF0gPSB0bXAxOwogICAgICAgICAgY3NbMV0gPSBjaSArIDE7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI6CiAgICAgICAgICB0bXAxID0gcHNbMTVdOwogICAgICAgICAgdG1wMiA9IHBzWzExXTsKICAgICAgICAgIHBzWzEyXSA9IHBzWzNdOwogICAgICAgICAgcHNbMTNdID0gcGkgKyAwOwogICAgICAgICAgcHNbMTRdID0gcGkgKyAxOwogICAgICAgICAgcHNbMTVdID0gcGkgKyAyOwogICAgICAgICAgcHNbOF0gPSBwc1s3XTsKICAgICAgICAgIHBzWzldID0gcGkgKyA5OwogICAgICAgICAgcHNbMTBdID0gcGkgKyAxMDsKICAgICAgICAgIHBzWzExXSA9IHBpICsgMzsKICAgICAgICAgIHBzWzRdID0gdG1wMjsKICAgICAgICAgIHBzWzVdID0gcGkgKyA4OwogICAgICAgICAgcHNbNl0gPSBwaSArIDExOwogICAgICAgICAgcHNbN10gPSBwaSArIDQ7CiAgICAgICAgICBwc1swXSA9IHRtcDE7CiAgICAgICAgICBwc1sxXSA9IHBpICsgNzsKICAgICAgICAgIHBzWzJdID0gcGkgKyA2OwogICAgICAgICAgcHNbM10gPSBwaSArIDU7CiAgICAgICAgICB0bXAxID0gY3NbM107CiAgICAgICAgICBjc1syXSA9IGNzWzFdOwogICAgICAgICAgY3NbM10gPSBjaTsKICAgICAgICAgIGNzWzBdID0gdG1wMTsKICAgICAgICAgIGNzWzFdID0gY2kgKyAxOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAzOgogICAgICAgICAgcHNbMTJdID0gcHNbMF07CiAgICAgICAgICBwc1sxM10gPSBwaSArIDA7CiAgICAgICAgICBwc1sxNF0gPSBwaSArIDE7CiAgICAgICAgICBwc1sxNV0gPSBwaSArIDI7CiAgICAgICAgICBwc1s4XSA9IHBzWzFdOwogICAgICAgICAgcHNbOV0gPSBwaSArIDk7CiAgICAgICAgICBwc1sxMF0gPSBwaSArIDEwOwogICAgICAgICAgcHNbMTFdID0gcGkgKyAzOwogICAgICAgICAgcHNbNF0gPSBwc1syXTsKICAgICAgICAgIHBzWzVdID0gcGkgKyA4OwogICAgICAgICAgcHNbNl0gPSBwaSArIDExOwogICAgICAgICAgcHNbN10gPSBwaSArIDQ7CiAgICAgICAgICBwc1swXSA9IHBzWzNdOwogICAgICAgICAgcHNbMV0gPSBwaSArIDc7CiAgICAgICAgICBwc1syXSA9IHBpICsgNjsKICAgICAgICAgIHBzWzNdID0gcGkgKyA1OwogICAgICAgICAgY3NbMl0gPSBjc1swXTsKICAgICAgICAgIGNzWzNdID0gY2k7CiAgICAgICAgICBjc1swXSA9IGNzWzFdOwogICAgICAgICAgY3NbMV0gPSBjaSArIDE7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICB0aGlzLmZpZ3VyZXMucHVzaCh7CiAgICAgICAgdHlwZTogInBhdGNoIiwKICAgICAgICBjb29yZHM6IG5ldyBJbnQzMkFycmF5KHBzKSwKICAgICAgICBjb2xvcnM6IG5ldyBJbnQzMkFycmF5KGNzKQogICAgICB9KTsKICAgIH0KICB9CiAgX2J1aWxkRmlndXJlRnJvbVBhdGNoKGluZGV4KSB7CiAgICBjb25zdCBmaWd1cmUgPSB0aGlzLmZpZ3VyZXNbaW5kZXhdOwogICAgYXNzZXJ0KGZpZ3VyZS50eXBlID09PSAicGF0Y2giLCAiVW5leHBlY3RlZCBwYXRjaCBtZXNoIGZpZ3VyZSIpOwogICAgY29uc3QgY29vcmRzID0gdGhpcy5jb29yZHMsCiAgICAgIGNvbG9ycyA9IHRoaXMuY29sb3JzOwogICAgY29uc3QgcGkgPSBmaWd1cmUuY29vcmRzOwogICAgY29uc3QgY2kgPSBmaWd1cmUuY29sb3JzOwogICAgY29uc3QgZmlndXJlTWluWCA9IE1hdGgubWluKGNvb3Jkc1twaVswXV1bMF0sIGNvb3Jkc1twaVszXV1bMF0sIGNvb3Jkc1twaVsxMl1dWzBdLCBjb29yZHNbcGlbMTVdXVswXSk7CiAgICBjb25zdCBmaWd1cmVNaW5ZID0gTWF0aC5taW4oY29vcmRzW3BpWzBdXVsxXSwgY29vcmRzW3BpWzNdXVsxXSwgY29vcmRzW3BpWzEyXV1bMV0sIGNvb3Jkc1twaVsxNV1dWzFdKTsKICAgIGNvbnN0IGZpZ3VyZU1heFggPSBNYXRoLm1heChjb29yZHNbcGlbMF1dWzBdLCBjb29yZHNbcGlbM11dWzBdLCBjb29yZHNbcGlbMTJdXVswXSwgY29vcmRzW3BpWzE1XV1bMF0pOwogICAgY29uc3QgZmlndXJlTWF4WSA9IE1hdGgubWF4KGNvb3Jkc1twaVswXV1bMV0sIGNvb3Jkc1twaVszXV1bMV0sIGNvb3Jkc1twaVsxMl1dWzFdLCBjb29yZHNbcGlbMTVdXVsxXSk7CiAgICBsZXQgc3BsaXRYQnkgPSBNYXRoLmNlaWwoKGZpZ3VyZU1heFggLSBmaWd1cmVNaW5YKSAqIE1lc2hTaGFkaW5nLlRSSUFOR0xFX0RFTlNJVFkgLyAodGhpcy5ib3VuZHNbMl0gLSB0aGlzLmJvdW5kc1swXSkpOwogICAgc3BsaXRYQnkgPSBNYXRoQ2xhbXAoc3BsaXRYQnksIE1lc2hTaGFkaW5nLk1JTl9TUExJVF9QQVRDSF9DSFVOS1NfQU1PVU5ULCBNZXNoU2hhZGluZy5NQVhfU1BMSVRfUEFUQ0hfQ0hVTktTX0FNT1VOVCk7CiAgICBsZXQgc3BsaXRZQnkgPSBNYXRoLmNlaWwoKGZpZ3VyZU1heFkgLSBmaWd1cmVNaW5ZKSAqIE1lc2hTaGFkaW5nLlRSSUFOR0xFX0RFTlNJVFkgLyAodGhpcy5ib3VuZHNbM10gLSB0aGlzLmJvdW5kc1sxXSkpOwogICAgc3BsaXRZQnkgPSBNYXRoQ2xhbXAoc3BsaXRZQnksIE1lc2hTaGFkaW5nLk1JTl9TUExJVF9QQVRDSF9DSFVOS1NfQU1PVU5ULCBNZXNoU2hhZGluZy5NQVhfU1BMSVRfUEFUQ0hfQ0hVTktTX0FNT1VOVCk7CiAgICBjb25zdCB2ZXJ0aWNlc1BlclJvdyA9IHNwbGl0WEJ5ICsgMTsKICAgIGNvbnN0IGZpZ3VyZUNvb3JkcyA9IG5ldyBJbnQzMkFycmF5KChzcGxpdFlCeSArIDEpICogdmVydGljZXNQZXJSb3cpOwogICAgY29uc3QgZmlndXJlQ29sb3JzID0gbmV3IEludDMyQXJyYXkoKHNwbGl0WUJ5ICsgMSkgKiB2ZXJ0aWNlc1BlclJvdyk7CiAgICBsZXQgayA9IDA7CiAgICBjb25zdCBjbCA9IG5ldyBVaW50OEFycmF5KDMpLAogICAgICBjciA9IG5ldyBVaW50OEFycmF5KDMpOwogICAgY29uc3QgYzAgPSBjb2xvcnNbY2lbMF1dLAogICAgICBjMSA9IGNvbG9yc1tjaVsxXV0sCiAgICAgIGMyID0gY29sb3JzW2NpWzJdXSwKICAgICAgYzMgPSBjb2xvcnNbY2lbM11dOwogICAgY29uc3QgYlJvdyA9IGdldEIoc3BsaXRZQnkpLAogICAgICBiQ29sID0gZ2V0QihzcGxpdFhCeSk7CiAgICBmb3IgKGxldCByb3cgPSAwOyByb3cgPD0gc3BsaXRZQnk7IHJvdysrKSB7CiAgICAgIGNsWzBdID0gKGMwWzBdICogKHNwbGl0WUJ5IC0gcm93KSArIGMyWzBdICogcm93KSAvIHNwbGl0WUJ5IHwgMDsKICAgICAgY2xbMV0gPSAoYzBbMV0gKiAoc3BsaXRZQnkgLSByb3cpICsgYzJbMV0gKiByb3cpIC8gc3BsaXRZQnkgfCAwOwogICAgICBjbFsyXSA9IChjMFsyXSAqIChzcGxpdFlCeSAtIHJvdykgKyBjMlsyXSAqIHJvdykgLyBzcGxpdFlCeSB8IDA7CiAgICAgIGNyWzBdID0gKGMxWzBdICogKHNwbGl0WUJ5IC0gcm93KSArIGMzWzBdICogcm93KSAvIHNwbGl0WUJ5IHwgMDsKICAgICAgY3JbMV0gPSAoYzFbMV0gKiAoc3BsaXRZQnkgLSByb3cpICsgYzNbMV0gKiByb3cpIC8gc3BsaXRZQnkgfCAwOwogICAgICBjclsyXSA9IChjMVsyXSAqIChzcGxpdFlCeSAtIHJvdykgKyBjM1syXSAqIHJvdykgLyBzcGxpdFlCeSB8IDA7CiAgICAgIGZvciAobGV0IGNvbCA9IDA7IGNvbCA8PSBzcGxpdFhCeTsgY29sKyssIGsrKykgewogICAgICAgIGlmICgocm93ID09PSAwIHx8IHJvdyA9PT0gc3BsaXRZQnkpICYmIChjb2wgPT09IDAgfHwgY29sID09PSBzcGxpdFhCeSkpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBsZXQgeCA9IDAsCiAgICAgICAgICB5ID0gMDsKICAgICAgICBsZXQgcSA9IDA7CiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gMzsgaSsrKSB7CiAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8PSAzOyBqKyssIHErKykgewogICAgICAgICAgICBjb25zdCBtID0gYlJvd1tyb3ddW2ldICogYkNvbFtjb2xdW2pdOwogICAgICAgICAgICB4ICs9IGNvb3Jkc1twaVtxXV1bMF0gKiBtOwogICAgICAgICAgICB5ICs9IGNvb3Jkc1twaVtxXV1bMV0gKiBtOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBmaWd1cmVDb29yZHNba10gPSBjb29yZHMubGVuZ3RoOwogICAgICAgIGNvb3Jkcy5wdXNoKFt4LCB5XSk7CiAgICAgICAgZmlndXJlQ29sb3JzW2tdID0gY29sb3JzLmxlbmd0aDsKICAgICAgICBjb25zdCBuZXdDb2xvciA9IG5ldyBVaW50OEFycmF5KDMpOwogICAgICAgIG5ld0NvbG9yWzBdID0gKGNsWzBdICogKHNwbGl0WEJ5IC0gY29sKSArIGNyWzBdICogY29sKSAvIHNwbGl0WEJ5IHwgMDsKICAgICAgICBuZXdDb2xvclsxXSA9IChjbFsxXSAqIChzcGxpdFhCeSAtIGNvbCkgKyBjclsxXSAqIGNvbCkgLyBzcGxpdFhCeSB8IDA7CiAgICAgICAgbmV3Q29sb3JbMl0gPSAoY2xbMl0gKiAoc3BsaXRYQnkgLSBjb2wpICsgY3JbMl0gKiBjb2wpIC8gc3BsaXRYQnkgfCAwOwogICAgICAgIGNvbG9ycy5wdXNoKG5ld0NvbG9yKTsKICAgICAgfQogICAgfQogICAgZmlndXJlQ29vcmRzWzBdID0gcGlbMF07CiAgICBmaWd1cmVDb2xvcnNbMF0gPSBjaVswXTsKICAgIGZpZ3VyZUNvb3Jkc1tzcGxpdFhCeV0gPSBwaVszXTsKICAgIGZpZ3VyZUNvbG9yc1tzcGxpdFhCeV0gPSBjaVsxXTsKICAgIGZpZ3VyZUNvb3Jkc1t2ZXJ0aWNlc1BlclJvdyAqIHNwbGl0WUJ5XSA9IHBpWzEyXTsKICAgIGZpZ3VyZUNvbG9yc1t2ZXJ0aWNlc1BlclJvdyAqIHNwbGl0WUJ5XSA9IGNpWzJdOwogICAgZmlndXJlQ29vcmRzW3ZlcnRpY2VzUGVyUm93ICogc3BsaXRZQnkgKyBzcGxpdFhCeV0gPSBwaVsxNV07CiAgICBmaWd1cmVDb2xvcnNbdmVydGljZXNQZXJSb3cgKiBzcGxpdFlCeSArIHNwbGl0WEJ5XSA9IGNpWzNdOwogICAgdGhpcy5maWd1cmVzW2luZGV4XSA9IHsKICAgICAgdHlwZTogImxhdHRpY2UiLAogICAgICBjb29yZHM6IGZpZ3VyZUNvb3JkcywKICAgICAgY29sb3JzOiBmaWd1cmVDb2xvcnMsCiAgICAgIHZlcnRpY2VzUGVyUm93CiAgICB9OwogIH0KICBfdXBkYXRlQm91bmRzKCkgewogICAgbGV0IG1pblggPSB0aGlzLmNvb3Jkc1swXVswXSwKICAgICAgbWluWSA9IHRoaXMuY29vcmRzWzBdWzFdLAogICAgICBtYXhYID0gbWluWCwKICAgICAgbWF4WSA9IG1pblk7CiAgICBmb3IgKGxldCBpID0gMSwgaWkgPSB0aGlzLmNvb3Jkcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IHggPSB0aGlzLmNvb3Jkc1tpXVswXSwKICAgICAgICB5ID0gdGhpcy5jb29yZHNbaV1bMV07CiAgICAgIG1pblggPSBtaW5YID4geCA/IHggOiBtaW5YOwogICAgICBtaW5ZID0gbWluWSA+IHkgPyB5IDogbWluWTsKICAgICAgbWF4WCA9IG1heFggPCB4ID8geCA6IG1heFg7CiAgICAgIG1heFkgPSBtYXhZIDwgeSA/IHkgOiBtYXhZOwogICAgfQogICAgdGhpcy5ib3VuZHMgPSBbbWluWCwgbWluWSwgbWF4WCwgbWF4WV07CiAgfQogIF9wYWNrRGF0YSgpIHsKICAgIGxldCBpLCBpaSwgaiwgamo7CiAgICBjb25zdCBjb29yZHMgPSB0aGlzLmNvb3JkczsKICAgIGNvbnN0IGNvb3Jkc1BhY2tlZCA9IG5ldyBGbG9hdDMyQXJyYXkoY29vcmRzLmxlbmd0aCAqIDIpOwogICAgZm9yIChpID0gMCwgaiA9IDAsIGlpID0gY29vcmRzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgeHkgPSBjb29yZHNbaV07CiAgICAgIGNvb3Jkc1BhY2tlZFtqKytdID0geHlbMF07CiAgICAgIGNvb3Jkc1BhY2tlZFtqKytdID0geHlbMV07CiAgICB9CiAgICB0aGlzLmNvb3JkcyA9IGNvb3Jkc1BhY2tlZDsKICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuY29sb3JzOwogICAgY29uc3QgY29sb3JzUGFja2VkID0gbmV3IFVpbnQ4QXJyYXkoY29sb3JzLmxlbmd0aCAqIDMpOwogICAgZm9yIChpID0gMCwgaiA9IDAsIGlpID0gY29sb3JzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgYyA9IGNvbG9yc1tpXTsKICAgICAgY29sb3JzUGFja2VkW2orK10gPSBjWzBdOwogICAgICBjb2xvcnNQYWNrZWRbaisrXSA9IGNbMV07CiAgICAgIGNvbG9yc1BhY2tlZFtqKytdID0gY1syXTsKICAgIH0KICAgIHRoaXMuY29sb3JzID0gY29sb3JzUGFja2VkOwogICAgY29uc3QgZmlndXJlcyA9IHRoaXMuZmlndXJlczsKICAgIGZvciAoaSA9IDAsIGlpID0gZmlndXJlcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGNvbnN0IGZpZ3VyZSA9IGZpZ3VyZXNbaV0sCiAgICAgICAgcHMgPSBmaWd1cmUuY29vcmRzLAogICAgICAgIGNzID0gZmlndXJlLmNvbG9yczsKICAgICAgZm9yIChqID0gMCwgamogPSBwcy5sZW5ndGg7IGogPCBqajsgaisrKSB7CiAgICAgICAgcHNbal0gKj0gMjsKICAgICAgICBjc1tqXSAqPSAzOwogICAgICB9CiAgICB9CiAgfQogIGdldElSKCkgewogICAgY29uc3QgewogICAgICBib3VuZHMKICAgIH0gPSB0aGlzOwogICAgaWYgKGJvdW5kc1syXSAtIGJvdW5kc1swXSA9PT0gMCB8fCBib3VuZHNbM10gLSBib3VuZHNbMV0gPT09IDApIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIE1lc2hTaGFkaW5nIGJvdW5kczogWyR7Ym91bmRzfV0uYCk7CiAgICB9CiAgICByZXR1cm4gWyJNZXNoIiwgdGhpcy5zaGFkaW5nVHlwZSwgdGhpcy5jb29yZHMsIHRoaXMuY29sb3JzLCB0aGlzLmZpZ3VyZXMsIGJvdW5kcywgdGhpcy5iYm94LCB0aGlzLmJhY2tncm91bmRdOwogIH0KfQpjbGFzcyBEdW1teVNoYWRpbmcgZXh0ZW5kcyBCYXNlU2hhZGluZyB7CiAgZ2V0SVIoKSB7CiAgICByZXR1cm4gWyJEdW1teSJdOwogIH0KfQpmdW5jdGlvbiBnZXRUaWxpbmdQYXR0ZXJuSVIob3BlcmF0b3JMaXN0LCBkaWN0LCBjb2xvcikgewogIGNvbnN0IG1hdHJpeCA9IGxvb2t1cE1hdHJpeChkaWN0LmdldEFycmF5KCJNYXRyaXgiKSwgSURFTlRJVFlfTUFUUklYKTsKICBjb25zdCBiYm94ID0gbG9va3VwTm9ybWFsUmVjdChkaWN0LmdldEFycmF5KCJCQm94IiksIG51bGwpOwogIGlmICghYmJveCB8fCBiYm94WzJdIC0gYmJveFswXSA9PT0gMCB8fCBiYm94WzNdIC0gYmJveFsxXSA9PT0gMCkgewogICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIGdldFRpbGluZ1BhdHRlcm5JUiAvQkJveCBhcnJheS5gKTsKICB9CiAgY29uc3QgeHN0ZXAgPSBkaWN0LmdldCgiWFN0ZXAiKTsKICBpZiAodHlwZW9mIHhzdGVwICE9PSAibnVtYmVyIikgewogICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIGdldFRpbGluZ1BhdHRlcm5JUiAvWFN0ZXAgdmFsdWUuYCk7CiAgfQogIGNvbnN0IHlzdGVwID0gZGljdC5nZXQoIllTdGVwIik7CiAgaWYgKHR5cGVvZiB5c3RlcCAhPT0gIm51bWJlciIpIHsKICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBnZXRUaWxpbmdQYXR0ZXJuSVIgL1lTdGVwIHZhbHVlLmApOwogIH0KICBjb25zdCBwYWludFR5cGUgPSBkaWN0LmdldCgiUGFpbnRUeXBlIik7CiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKHBhaW50VHlwZSkpIHsKICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBnZXRUaWxpbmdQYXR0ZXJuSVIgL1BhaW50VHlwZSB2YWx1ZS5gKTsKICB9CiAgY29uc3QgdGlsaW5nVHlwZSA9IGRpY3QuZ2V0KCJUaWxpbmdUeXBlIik7CiAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKHRpbGluZ1R5cGUpKSB7CiAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgZ2V0VGlsaW5nUGF0dGVybklSIC9UaWxpbmdUeXBlIHZhbHVlLmApOwogIH0KICByZXR1cm4gWyJUaWxpbmdQYXR0ZXJuIiwgY29sb3IsIG9wZXJhdG9yTGlzdCwgbWF0cml4LCBiYm94LCB4c3RlcCwgeXN0ZXAsIHBhaW50VHlwZSwgdGlsaW5nVHlwZV07Cn0KCjsvLyAuL3NyYy9jb3JlL2NhbGlicmlfZmFjdG9ycy5qcwpjb25zdCBDYWxpYnJpQm9sZEZhY3RvcnMgPSBbMS4zODc3LCAxLCAxLCAxLCAwLjk3ODAxLCAwLjkyNDgyLCAwLjg5NTUyLCAwLjkxMTMzLCAwLjgxOTg4LCAwLjk3NTY2LCAwLjk4MTUyLCAwLjkzNTQ4LCAwLjkzNTQ4LCAxLjI3OTgsIDAuODUyODQsIDAuOTI3OTQsIDEsIDAuOTYxMzQsIDEuNTQ2NTcsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuODI4NDUsIDAuODI4NDUsIDAuODUyODQsIDAuODUyODQsIDAuODUyODQsIDAuNzU4NTksIDAuOTIxMzgsIDAuODM5MDgsIDAuNzc2MiwgMC43MzI5MywgMC44NzI4OSwgMC43MzEzMywgMC43NTE0LCAwLjgxOTIxLCAwLjg3MzU2LCAwLjk1OTU4LCAwLjU5NTI2LCAwLjc1NzI3LCAwLjY5MjI1LCAxLjA0OTI0LCAwLjkxMjEsIDAuODY5NDMsIDAuNzk3OTUsIDAuODgxOTgsIDAuNzc5NTgsIDAuNzA4NjQsIDAuODEwNTUsIDAuOTAzOTksIDAuODg2NTMsIDAuOTYwMTcsIDAuODI1NzcsIDAuNzc4OTIsIDAuNzgyNTcsIDAuOTc1MDcsIDEuNTQ2NTcsIDAuOTc1MDcsIDAuODUyODQsIDAuODk1NTIsIDAuOTAxNzYsIDAuODg3NjIsIDAuODc4NSwgMC43NTI0MSwgMC44Nzg1LCAwLjkwNTE4LCAwLjk1MDE1LCAwLjc3NjE4LCAwLjg3ODUsIDAuODg0MDEsIDAuOTE5MTYsIDAuODYzMDQsIDAuODg0MDEsIDAuOTE0ODgsIDAuODc4NSwgMC44ODAxLCAwLjg3ODUsIDAuODc4NSwgMC45MTM0MywgMC43MTczLCAxLjA0MTA2LCAwLjg3ODUsIDAuODUwNzUsIDAuOTU3OTQsIDAuODI2MTYsIDAuODUxNjIsIDAuNzk0OTIsIDAuODgzMzEsIDEuNjk4MDgsIDAuODgzMzEsIDAuODUyODQsIDAuOTc4MDEsIDAuODk1NTIsIDAuOTExMzMsIDAuODk1NTIsIDAuOTExMzMsIDEuNzgwMSwgMC44OTU1MiwgMS4yNDQ4NywgMS4xMzI1NCwgMS4xMjQwMSwgMC45NjgzOSwgMC44NTI4NCwgMC42ODc4NywgMC43MDY0NSwgMC44NTU5MiwgMC45MDc0NywgMS4wMTQ2NiwgMS4wMDg4LCAwLjkwMzIzLCAxLCAxLjA3NDYzLCAxLCAwLjkxMDU2LCAwLjc1ODA2LCAxLjE5MTE4LCAwLjk2ODM5LCAwLjc4ODY0LCAwLjgyODQ1LCAwLjg0MTMzLCAwLjc1ODU5LCAwLjgzOTA4LCAwLjgzOTA4LCAwLjgzOTA4LCAwLjgzOTA4LCAwLjgzOTA4LCAwLjgzOTA4LCAwLjc3NTM5LCAwLjczMjkzLCAwLjczMTMzLCAwLjczMTMzLCAwLjczMTMzLCAwLjczMTMzLCAwLjk1OTU4LCAwLjk1OTU4LCAwLjk1OTU4LCAwLjk1OTU4LCAwLjg4NTA2LCAwLjkxMjEsIDAuODY5NDMsIDAuODY5NDMsIDAuODY5NDMsIDAuODY5NDMsIDAuODY5NDMsIDAuODUyODQsIDAuODc1MDgsIDAuOTAzOTksIDAuOTAzOTksIDAuOTAzOTksIDAuOTAzOTksIDAuNzc4OTIsIDAuNzk3OTUsIDAuOTA4MDcsIDAuODg3NjIsIDAuODg3NjIsIDAuODg3NjIsIDAuODg3NjIsIDAuODg3NjIsIDAuODg3NjIsIDAuODcxNSwgMC43NTI0MSwgMC45MDUxOCwgMC45MDUxOCwgMC45MDUxOCwgMC45MDUxOCwgMC44ODQwMSwgMC44ODQwMSwgMC44ODQwMSwgMC44ODQwMSwgMC44Nzg1LCAwLjg3ODUsIDAuODgwMSwgMC44ODAxLCAwLjg4MDEsIDAuODgwMSwgMC44ODAxLCAwLjkwNzQ3LCAwLjg5MDQ5LCAwLjg3ODUsIDAuODc4NSwgMC44Nzg1LCAwLjg3ODUsIDAuODUxNjIsIDAuODc4NSwgMC44NTE2MiwgMC44MzkwOCwgMC44ODc2MiwgMC44MzkwOCwgMC44ODc2MiwgMC44MzkwOCwgMC44ODc2MiwgMC43MzI5MywgMC43NTI0MSwgMC43MzI5MywgMC43NTI0MSwgMC43MzI5MywgMC43NTI0MSwgMC43MzI5MywgMC43NTI0MSwgMC44NzI4OSwgMC44MzAxNiwgMC44ODUwNiwgMC45MzEyNSwgMC43MzEzMywgMC45MDUxOCwgMC43MzEzMywgMC45MDUxOCwgMC43MzEzMywgMC45MDUxOCwgMC43MzEzMywgMC45MDUxOCwgMC43MzEzMywgMC45MDUxOCwgMC44MTkyMSwgMC43NzYxOCwgMC44MTkyMSwgMC43NzYxOCwgMC44MTkyMSwgMC43NzYxOCwgMSwgMSwgMC44NzM1NiwgMC44Nzg1LCAwLjkxMDc1LCAwLjg5NjA4LCAwLjk1OTU4LCAwLjg4NDAxLCAwLjk1OTU4LCAwLjg4NDAxLCAwLjk1OTU4LCAwLjg4NDAxLCAwLjk1OTU4LCAwLjg4NDAxLCAwLjk1OTU4LCAwLjg4NDAxLCAwLjc2MjI5LCAwLjkwMTY3LCAwLjU5NTI2LCAwLjkxOTE2LCAxLCAxLCAwLjg2MzA0LCAwLjY5MjI1LCAwLjg4NDAxLCAxLCAxLCAwLjcwNDI0LCAwLjc5NDY4LCAwLjkxOTI2LCAwLjg4MTc1LCAwLjcwODIzLCAwLjk0OTAzLCAwLjkxMjEsIDAuODc4NSwgMSwgMSwgMC45MTIxLCAwLjg3ODUsIDAuODc4MDIsIDAuODg2NTYsIDAuODc4NSwgMC44Njk0MywgMC44ODAxLCAwLjg2OTQzLCAwLjg4MDEsIDAuODY5NDMsIDAuODgwMSwgMC44NzQwMiwgMC44OTI5MSwgMC43Nzk1OCwgMC45MTM0MywgMSwgMSwgMC43Nzk1OCwgMC45MTM0MywgMC43MDg2NCwgMC43MTczLCAwLjcwODY0LCAwLjcxNzMsIDAuNzA4NjQsIDAuNzE3MywgMC43MDg2NCwgMC43MTczLCAxLCAxLCAwLjgxMDU1LCAwLjc1ODQxLCAwLjgxMDU1LCAxLjA2NDUyLCAwLjkwMzk5LCAwLjg3ODUsIDAuOTAzOTksIDAuODc4NSwgMC45MDM5OSwgMC44Nzg1LCAwLjkwMzk5LCAwLjg3ODUsIDAuOTAzOTksIDAuODc4NSwgMC45MDM5OSwgMC44Nzg1LCAwLjk2MDE3LCAwLjk1Nzk0LCAwLjc3ODkyLCAwLjg1MTYyLCAwLjc3ODkyLCAwLjc4MjU3LCAwLjc5NDkyLCAwLjc4MjU3LCAwLjc5NDkyLCAwLjc4MjU3LCAwLjc5NDkyLCAwLjkyOTcsIDAuNTY4OTIsIDAuODM5MDgsIDAuODg3NjIsIDAuNzc1MzksIDAuODcxNSwgMC44NzUwOCwgMC44OTA0OSwgMSwgMSwgMC44MTA1NSwgMS4wNDEwNiwgMS4yMDUyOCwgMS4yMDUyOCwgMSwgMS4xNTU0MywgMC43MDY3NCwgMC45ODM4NywgMC45NDcyMSwgMS4zMzQzMSwgMS40NTg5NCwgMC45NTE2MSwgMS4wNjMwMywgMC44MzkwOCwgMC44MDM1MiwgMC41NzE4NCwgMC42OTY1LCAwLjU2Mjg5LCAwLjgyMDAxLCAwLjU2MDI5LCAwLjgxMjM1LCAxLjAyOTg4LCAwLjgzOTA4LCAwLjc3NjIsIDAuNjgxNTYsIDAuODAzNjcsIDAuNzMxMzMsIDAuNzgyNTcsIDAuODczNTYsIDAuODY5NDMsIDAuOTU5NTgsIDAuNzU3MjcsIDAuODkwMTksIDEuMDQ5MjQsIDAuOTEyMSwgMC43NjQ4LCAwLjg2OTQzLCAwLjg3MzU2LCAwLjc5Nzk1LCAwLjc4Mjc1LCAwLjgxMDU1LCAwLjc3ODkyLCAwLjk3NjIsIDAuODI1NzcsIDAuOTk4MTksIDAuODQ4OTYsIDAuOTU5NTgsIDAuNzc4OTIsIDAuOTYxMDgsIDEuMDE0MDcsIDAuODkwNDksIDEuMDI5ODgsIDAuOTQyMTEsIDAuOTYxMDgsIDAuODkzNiwgMC44NDAyMSwgMC44Nzg0MiwgMC45NjM5OSwgMC43OTEwOSwgMC44OTA0OSwgMS4wMDgxMywgMS4wMjk4OCwgMC44NjA3NywgMC44NzQ0NSwgMC45MjA5OSwgMC44NDcyMywgMC44NjUxMywgMC44ODAxLCAwLjc1NjM4LCAwLjg1NzE0LCAwLjc4MjE2LCAwLjc5NTg2LCAwLjg3OTY1LCAwLjk0MjExLCAwLjk3NzQ3LCAwLjc4Mjg3LCAwLjk3OTI2LCAwLjg0OTcxLCAxLjAyOTg4LCAwLjk0MjExLCAwLjg4MDEsIDAuOTQyMTEsIDAuODQ5NzEsIDAuNzMxMzMsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTAyNjQsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTA1MTgsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTA1NDgsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTYwMTcsIDAuOTU3OTQsIDAuOTYwMTcsIDAuOTU3OTQsIDAuOTYwMTcsIDAuOTU3OTQsIDAuNzc4OTIsIDAuODUxNjIsIDEsIDEsIDAuODk1NTIsIDAuOTA1MjcsIDEsIDAuOTAzNjMsIDAuOTI3OTQsIDAuOTI3OTQsIDAuOTI3OTQsIDAuOTI3OTQsIDAuODcwMTIsIDAuODcwMTIsIDAuODcwMTIsIDAuODk1NTIsIDAuODk1NTIsIDEuNDIyNTksIDAuNzExNDMsIDEuMDYxNTIsIDEsIDEsIDEuMDMzNzIsIDEuMDMzNzIsIDAuOTcxNzEsIDEuNDk1NiwgMi4yODA3LCAwLjkzODM1LCAwLjgzNDA2LCAwLjkxMTMzLCAwLjg0MTA3LCAwLjkxMTMzLCAxLCAxLCAxLCAwLjcyMDIxLCAxLCAxLjIzMTA4LCAwLjgzNDg5LCAwLjg4NTI1LCAwLjg4NTI1LCAwLjgxNDk5LCAwLjkwNTI3LCAxLjgxMDU1LCAwLjkwNTI3LCAxLjgxMDU1LCAxLjMxMDA2LCAxLjUzNzExLCAwLjk0NDM0LCAxLjA4Njk2LCAxLCAwLjk1MDE4LCAwLjc3MTkyLCAwLjg1Mjg0LCAwLjkwNzQ3LCAxLjE3NTM0LCAwLjY5ODI1LCAwLjk3MTYsIDEuMzcwNzcsIDAuOTA3NDcsIDAuOTA3NDcsIDAuODUzNTYsIDAuOTA3NDcsIDAuOTA3NDcsIDEuNDQ5NDcsIDAuODUyODQsIDAuODk0MSwgMC44OTQxLCAwLjcwNTcyLCAwLjgsIDAuNzA1NzIsIDAuNzA1NzIsIDAuNzA1NzIsIDAuNzA1NzIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTk4NjIsIDAuOTk4NjIsIDEsIDEsIDEsIDEsIDEsIDEuMDgwMDQsIDAuOTEwMjcsIDEsIDEsIDEsIDAuOTk4NjIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTA3MjcsIDAuOTA3MjcsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpjb25zdCBDYWxpYnJpQm9sZE1ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4yMjA3LAogIGxpbmVHYXA6IDAuMjIwNwp9Owpjb25zdCBDYWxpYnJpQm9sZEl0YWxpY0ZhY3RvcnMgPSBbMS4zODc3LCAxLCAxLCAxLCAwLjk3ODAxLCAwLjkyNDgyLCAwLjg5NTUyLCAwLjkxMTMzLCAwLjgxOTg4LCAwLjk3NTY2LCAwLjk4MTUyLCAwLjkzNTQ4LCAwLjkzNTQ4LCAxLjI3OTgsIDAuODUyODQsIDAuOTI3OTQsIDEsIDAuOTYxMzQsIDEuNTYyMzksIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuOTExMzMsIDAuODI4NDUsIDAuODI4NDUsIDAuODUyODQsIDAuODUyODQsIDAuODUyODQsIDAuNzU4NTksIDAuOTIxMzgsIDAuODM5MDgsIDAuNzc2MiwgMC43MTgwNSwgMC44NzI4OSwgMC43MzEzMywgMC43NTE0LCAwLjgxOTIxLCAwLjg3MzU2LCAwLjk1OTU4LCAwLjU5NTI2LCAwLjc1NzI3LCAwLjY5MjI1LCAxLjA0OTI0LCAwLjkwODcyLCAwLjg1OTM4LCAwLjc5Nzk1LCAwLjg3MDY4LCAwLjc3OTU4LCAwLjY5NzY2LCAwLjgxMDU1LCAwLjkwMzk5LCAwLjg4NjUzLCAwLjk2MDY4LCAwLjgyNTc3LCAwLjc3ODkyLCAwLjc4MjU3LCAwLjk3NTA3LCAxLjUyOSwgMC45NzUwNywgMC44NTI4NCwgMC44OTU1MiwgMC45MDE3NiwgMC45NDkwOCwgMC44NjQxMSwgMC43NDAxMiwgMC44NjQxMSwgMC44ODMyMywgMC45NTAxNSwgMC44NjQxMSwgMC44NjMzMSwgMC44ODQwMSwgMC45MTkxNiwgMC44NjMwNCwgMC44ODQwMSwgMC45MDM5LCAwLjg2MzMxLCAwLjg2MzMxLCAwLjg2NDExLCAwLjg2NDExLCAwLjkwNDY0LCAwLjcwODUyLCAxLjA0MTA2LCAwLjg2MzMxLCAwLjg0MzcyLCAwLjk1Nzk0LCAwLjgyNjE2LCAwLjg0NTQ4LCAwLjc5NDkyLCAwLjg4MzMxLCAxLjY5ODA4LCAwLjg4MzMxLCAwLjg1Mjg0LCAwLjk3ODAxLCAwLjg5NTUyLCAwLjkxMTMzLCAwLjg5NTUyLCAwLjkxMTMzLCAxLjc4MDEsIDAuODk1NTIsIDEuMjQ0ODcsIDEuMTMyNTQsIDEuMTkxMjksIDAuOTY4MzksIDAuODUyODQsIDAuNjg3ODcsIDAuNzA2NDUsIDAuODU1OTIsIDAuOTA3NDcsIDEuMDE0NjYsIDEuMDA4OCwgMC45MDMyMywgMSwgMS4wNzQ2MywgMSwgMC45MTA1NiwgMC43NTgwNiwgMS4xOTExOCwgMC45NjgzOSwgMC43ODg2NCwgMC44Mjg0NSwgMC44NDEzMywgMC43NTg1OSwgMC44MzkwOCwgMC44MzkwOCwgMC44MzkwOCwgMC44MzkwOCwgMC44MzkwOCwgMC44MzkwOCwgMC43NzUzOSwgMC43MTgwNSwgMC43MzEzMywgMC43MzEzMywgMC43MzEzMywgMC43MzEzMywgMC45NTk1OCwgMC45NTk1OCwgMC45NTk1OCwgMC45NTk1OCwgMC44ODUwNiwgMC45MDg3MiwgMC44NTkzOCwgMC44NTkzOCwgMC44NTkzOCwgMC44NTkzOCwgMC44NTkzOCwgMC44NTI4NCwgMC44NzA2OCwgMC45MDM5OSwgMC45MDM5OSwgMC45MDM5OSwgMC45MDM5OSwgMC43Nzg5MiwgMC43OTc5NSwgMC45MDgwNywgMC45NDkwOCwgMC45NDkwOCwgMC45NDkwOCwgMC45NDkwOCwgMC45NDkwOCwgMC45NDkwOCwgMC44NTg4NywgMC43NDAxMiwgMC44ODMyMywgMC44ODMyMywgMC44ODMyMywgMC44ODMyMywgMC44ODQwMSwgMC44ODQwMSwgMC44ODQwMSwgMC44ODQwMSwgMC44Nzg1LCAwLjg2MzMxLCAwLjg2MzMxLCAwLjg2MzMxLCAwLjg2MzMxLCAwLjg2MzMxLCAwLjg2MzMxLCAwLjkwNzQ3LCAwLjg5MDQ5LCAwLjg2MzMxLCAwLjg2MzMxLCAwLjg2MzMxLCAwLjg2MzMxLCAwLjg0NTQ4LCAwLjg2NDExLCAwLjg0NTQ4LCAwLjgzOTA4LCAwLjk0OTA4LCAwLjgzOTA4LCAwLjk0OTA4LCAwLjgzOTA4LCAwLjk0OTA4LCAwLjcxODA1LCAwLjc0MDEyLCAwLjcxODA1LCAwLjc0MDEyLCAwLjcxODA1LCAwLjc0MDEyLCAwLjcxODA1LCAwLjc0MDEyLCAwLjg3Mjg5LCAwLjc5NTM4LCAwLjg4NTA2LCAwLjkyNzI2LCAwLjczMTMzLCAwLjg4MzIzLCAwLjczMTMzLCAwLjg4MzIzLCAwLjczMTMzLCAwLjg4MzIzLCAwLjczMTMzLCAwLjg4MzIzLCAwLjczMTMzLCAwLjg4MzIzLCAwLjgxOTIxLCAwLjg2NDExLCAwLjgxOTIxLCAwLjg2NDExLCAwLjgxOTIxLCAwLjg2NDExLCAxLCAxLCAwLjg3MzU2LCAwLjg2MzMxLCAwLjkxMDc1LCAwLjg3NzcsIDAuOTU5NTgsIDAuODg0MDEsIDAuOTU5NTgsIDAuODg0MDEsIDAuOTU5NTgsIDAuODg0MDEsIDAuOTU5NTgsIDAuODg0MDEsIDAuOTU5NTgsIDAuODg0MDEsIDAuNzY0NjcsIDAuOTAxNjcsIDAuNTk1MjYsIDAuOTE5MTYsIDEsIDEsIDAuODYzMDQsIDAuNjkyMjUsIDAuODg0MDEsIDEsIDEsIDAuNzA0MjQsIDAuNzczMTIsIDAuOTE5MjYsIDAuODgxNzUsIDAuNzA4MjMsIDAuOTQ5MDMsIDAuOTA4NzIsIDAuODYzMzEsIDEsIDEsIDAuOTA4NzIsIDAuODYzMzEsIDAuODY5MDYsIDAuODgxMTYsIDAuODYzMzEsIDAuODU5MzgsIDAuODYzMzEsIDAuODU5MzgsIDAuODYzMzEsIDAuODU5MzgsIDAuODYzMzEsIDAuODc0MDIsIDAuODY1NDksIDAuNzc5NTgsIDAuOTA0NjQsIDEsIDEsIDAuNzc5NTgsIDAuOTA0NjQsIDAuNjk3NjYsIDAuNzA4NTIsIDAuNjk3NjYsIDAuNzA4NTIsIDAuNjk3NjYsIDAuNzA4NTIsIDAuNjk3NjYsIDAuNzA4NTIsIDEsIDEsIDAuODEwNTUsIDAuNzU4NDEsIDAuODEwNTUsIDEuMDY0NTIsIDAuOTAzOTksIDAuODYzMzEsIDAuOTAzOTksIDAuODYzMzEsIDAuOTAzOTksIDAuODYzMzEsIDAuOTAzOTksIDAuODYzMzEsIDAuOTAzOTksIDAuODYzMzEsIDAuOTAzOTksIDAuODYzMzEsIDAuOTYwNjgsIDAuOTU3OTQsIDAuNzc4OTIsIDAuODQ1NDgsIDAuNzc4OTIsIDAuNzgyNTcsIDAuNzk0OTIsIDAuNzgyNTcsIDAuNzk0OTIsIDAuNzgyNTcsIDAuNzk0OTIsIDAuOTI5NywgMC41Njg5MiwgMC44MzkwOCwgMC45NDkwOCwgMC43NzUzOSwgMC44NTg4NywgMC44NzA2OCwgMC44OTA0OSwgMSwgMSwgMC44MTA1NSwgMS4wNDEwNiwgMS4yMDUyOCwgMS4yMDUyOCwgMSwgMS4xNTU0MywgMC43MDA4OCwgMC45ODM4NywgMC45NDcyMSwgMS4zMzQzMSwgMS40NTg5NCwgMC45NTE2MSwgMS40ODM4NywgMC44MzkwOCwgMC44MDM1MiwgMC41NzExOCwgMC42OTY1LCAwLjU2MzQ3LCAwLjc5MTc5LCAwLjU1ODUzLCAwLjgwMzQ2LCAxLjAyOTg4LCAwLjgzOTA4LCAwLjc3NjIsIDAuNjcxNzQsIDAuODYwMzYsIDAuNzMxMzMsIDAuNzgyNTcsIDAuODczNTYsIDAuODY0NDEsIDAuOTU5NTgsIDAuNzU3MjcsIDAuODkwMTksIDEuMDQ5MjQsIDAuOTA4NzIsIDAuNzQ4ODksIDAuODU5MzgsIDAuODc4OTEsIDAuNzk3OTUsIDAuNzk1NywgMC44MTA1NSwgMC43Nzg5MiwgMC45NzQ0NywgMC44MjU3NywgMC45NzQ2NiwgMC44NzE3OSwgMC45NTk1OCwgMC43Nzg5MiwgMC45NDI1MiwgMC45NTYxMiwgMC44NzUzLCAxLjAyOTg4LCAwLjkyNzMzLCAwLjk0MjUyLCAwLjg3NDExLCAwLjg0MDIxLCAwLjg3MjgsIDAuOTU2MTIsIDAuNzQwODEsIDAuODc1MywgMS4wMjE4OSwgMS4wMjk4OCwgMC44NDgxNCwgMC44NzQ0NSwgMC45MTgyMiwgMC44NDcyMywgMC44NTY2OCwgMC44NjMzMSwgMC44MTM0NCwgMC44NzU4MSwgMC43NjQyMiwgMC44MjA0NiwgMC45NjA1NywgMC45MjczMywgMC45OTM3NSwgMC43ODAyMiwgMC45NTQ1MiwgMC44NjAxNSwgMS4wMjk4OCwgMC45MjczMywgMC44NjMzMSwgMC45MjczMywgMC44NjAxNSwgMC43MzEzMywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MDYzMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC44ODMyMywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC44NTE3NCwgMSwgMSwgMSwgMSwgMSwgMSwgMC45NjA2OCwgMC45NTc5NCwgMC45NjA2OCwgMC45NTc5NCwgMC45NjA2OCwgMC45NTc5NCwgMC43Nzg5MiwgMC44NDU0OCwgMSwgMSwgMC44OTU1MiwgMC45MDUyNywgMSwgMC45MDM2MywgMC45Mjc5NCwgMC45Mjc5NCwgMC45Mjc5NCwgMC44OTgwNywgMC44NzAxMiwgMC44NzAxMiwgMC44NzAxMiwgMC44OTU1MiwgMC44OTU1MiwgMS40MjI1OSwgMC43MTA5NCwgMS4wNjE1MiwgMSwgMSwgMS4wMzM3MiwgMS4wMzM3MiwgMC45NzE3MSwgMS40OTU2LCAyLjI4MDcsIDAuOTI5NzIsIDAuODM0MDYsIDAuOTExMzMsIDAuODMzMjYsIDAuOTExMzMsIDEsIDEsIDEsIDAuNzIwMjEsIDEsIDEuMjMxMDgsIDAuODM0ODksIDAuODg1MjUsIDAuODg1MjUsIDAuODE0OTksIDAuOTA2MTYsIDEuODEwNTUsIDAuOTA1MjcsIDEuODEwNTUsIDEuMzEwNywgMS41MzcxMSwgMC45NDQzNCwgMS4wODY5NiwgMSwgMC45NTAxOCwgMC43NzE5MiwgMC44NTI4NCwgMC45MDc0NywgMS4xNzUzNCwgMC42OTgyNSwgMC45NzE2LCAxLjM3MDc3LCAwLjkwNzQ3LCAwLjkwNzQ3LCAwLjg1MzU2LCAwLjkwNzQ3LCAwLjkwNzQ3LCAxLjQ0OTQ3LCAwLjg1Mjg0LCAwLjg5NDEsIDAuODk0MSwgMC43MDU3MiwgMC44LCAwLjcwNTcyLCAwLjcwNTcyLCAwLjcwNTcyLCAwLjcwNTcyLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk5ODYyLCAwLjk5ODYyLCAxLCAxLCAxLCAxLCAxLCAxLjA4MDA0LCAwLjkxMDI3LCAxLCAxLCAxLCAwLjk5ODYyLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjkwNzI3LCAwLjkwNzI3LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKY29uc3QgQ2FsaWJyaUJvbGRJdGFsaWNNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMjIwNywKICBsaW5lR2FwOiAwLjIyMDcKfTsKY29uc3QgQ2FsaWJyaUl0YWxpY0ZhY3RvcnMgPSBbMS4zODc3LCAxLCAxLCAxLCAxLjE3MjIzLCAxLjEyOTMsIDAuODk1NTIsIDAuOTExMzMsIDAuODAzOTUsIDEuMDIyNjksIDEuMTU2MDEsIDAuOTEwNTYsIDAuOTEwNTYsIDEuMjc5OCwgMC44NTI4NCwgMC44OTgwNywgMSwgMC45MDg2MSwgMS4zOTU0MywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45NjMwOSwgMC45NjMwOSwgMC44NTI4NCwgMC44NTI4NCwgMC44NTI4NCwgMC44MzMxOSwgMC44ODA3MSwgMC44Njc1LCAwLjgxNTUyLCAwLjcyMzQ2LCAwLjg1MTkzLCAwLjczMjA2LCAwLjc1MjIsIDAuODExMDUsIDAuODYyNzUsIDAuOTA2ODUsIDAuNjM3NywgMC43Nzg5MiwgMC43NTU5MywgMS4wMjYzOCwgMC44OTI0OSwgMC44NDExOCwgMC43NzQ1MiwgMC44NTM3NCwgMC43NTE4NiwgMC42Nzc4OSwgMC43OTc3NiwgMC44ODg0NCwgMC44NTA2NiwgMC45NDMwOSwgMC43NzgxOCwgMC43MzA2LCAwLjc2NjU5LCAxLjEwMzY5LCAxLjM4MzEzLCAxLjEwMzY5LCAxLjA2MTM5LCAwLjg5NTUyLCAwLjg3MzksIDAuOTI0NSwgMC45MjQ1LCAwLjgzMjAzLCAwLjkyNDUsIDAuODU4NjUsIDEuMDk4NDIsIDAuOTI0NSwgMC45MjQ1LCAxLjAzMjk3LCAxLjA3NjkyLCAwLjkwOTE4LCAxLjAzMjk3LCAwLjk0OTU5LCAwLjkyNDUsIDAuOTIyNzQsIDAuOTI0NSwgMC45MjQ1LCAxLjAyOTMzLCAwLjc3ODMyLCAxLjIwNTYyLCAwLjkyNDUsIDAuODkxNiwgMC45ODk4NiwgMC44NjYyMSwgMC44OTQ1MywgMC43OTAwNCwgMC45NDE1MiwgMS43NzI1NiwgMC45NDE1MiwgMC44NTI4NCwgMC45NzgwMSwgMC44OTU1MiwgMC45MTEzMywgMC44OTU1MiwgMC45MTEzMywgMS45MTcyOSwgMC44OTU1MiwgMS4xNzg4OSwgMS4xMzI1NCwgMS4xNjM1OSwgMC45MjA5OCwgMC44NTI4NCwgMC42ODc4NywgMC43MTM1MywgMC44NDczNywgMC45MDc0NywgMS4wMDg4LCAxLjAwNDQsIDAuODc2ODMsIDEsIDEuMDkwOTEsIDEsIDAuOTIyMjksIDAuNzM5LCAxLjE1NjQyLCAwLjkyMDk4LCAwLjc2Mjg4LCAwLjgwNTA0LCAwLjgwOTcyLCAwLjc1ODU5LCAwLjg2NzUsIDAuODY3NSwgMC44Njc1LCAwLjg2NzUsIDAuODY3NSwgMC44Njc1LCAwLjc2MzE4LCAwLjcyMzQ2LCAwLjczMjA2LCAwLjczMjA2LCAwLjczMjA2LCAwLjczMjA2LCAwLjkwNjg1LCAwLjkwNjg1LCAwLjkwNjg1LCAwLjkwNjg1LCAwLjg2NDc3LCAwLjg5MjQ5LCAwLjg0MTE4LCAwLjg0MTE4LCAwLjg0MTE4LCAwLjg0MTE4LCAwLjg0MTE4LCAwLjg1Mjg0LCAwLjg0NTU3LCAwLjg4ODQ0LCAwLjg4ODQ0LCAwLjg4ODQ0LCAwLjg4ODQ0LCAwLjczMDYsIDAuNzc0NTIsIDAuODYzMzEsIDAuOTI0NSwgMC45MjQ1LCAwLjkyNDUsIDAuOTI0NSwgMC45MjQ1LCAwLjkyNDUsIDAuODQ4NDMsIDAuODMyMDMsIDAuODU4NjUsIDAuODU4NjUsIDAuODU4NjUsIDAuODU4NjUsIDAuODI2MDEsIDAuODI2MDEsIDAuODI2MDEsIDAuODI2MDEsIDAuOTQ0NjksIDAuOTI0NSwgMC45MjI3NCwgMC45MjI3NCwgMC45MjI3NCwgMC45MjI3NCwgMC45MjI3NCwgMC45MDc0NywgMC44NjY1MSwgMC45MjQ1LCAwLjkyNDUsIDAuOTI0NSwgMC45MjQ1LCAwLjg5NDUzLCAwLjkyNDUsIDAuODk0NTMsIDAuODY3NSwgMC45MjQ1LCAwLjg2NzUsIDAuOTI0NSwgMC44Njc1LCAwLjkyNDUsIDAuNzIzNDYsIDAuODMyMDMsIDAuNzIzNDYsIDAuODMyMDMsIDAuNzIzNDYsIDAuODMyMDMsIDAuNzIzNDYsIDAuODMyMDMsIDAuODUxOTMsIDAuODg3NSwgMC44NjQ3NywgMC45OTAzNCwgMC43MzIwNiwgMC44NTg2NSwgMC43MzIwNiwgMC44NTg2NSwgMC43MzIwNiwgMC44NTg2NSwgMC43MzIwNiwgMC44NTg2NSwgMC43MzIwNiwgMC44NTg2NSwgMC44MTEwNSwgMC45MjQ1LCAwLjgxMTA1LCAwLjkyNDUsIDAuODExMDUsIDAuOTI0NSwgMSwgMSwgMC44NjI3NSwgMC45MjQ1LCAwLjkwODcyLCAwLjkzNTkxLCAwLjkwNjg1LCAwLjgyNjAxLCAwLjkwNjg1LCAwLjgyNjAxLCAwLjkwNjg1LCAwLjgyNjAxLCAwLjkwNjg1LCAxLjAzMjk3LCAwLjkwNjg1LCAwLjgyNjAxLCAwLjc3ODk2LCAxLjA1NjExLCAwLjYzNzcsIDEuMDc2OTIsIDEsIDEsIDAuOTA5MTgsIDAuNzU1OTMsIDEuMDMyOTcsIDEsIDEsIDAuNzYwMzIsIDAuOTM3NSwgMC45ODE1NiwgMC45MzQwNywgMC43NzI2MSwgMS4xMTQyOSwgMC44OTI0OSwgMC45MjQ1LCAxLCAxLCAwLjg5MjQ5LCAwLjkyNDUsIDAuOTI1MzQsIDAuODY2OTgsIDAuOTI0NSwgMC44NDExOCwgMC45MjI3NCwgMC44NDExOCwgMC45MjI3NCwgMC44NDExOCwgMC45MjI3NCwgMC44NjY3LCAwLjg2MjkxLCAwLjc1MTg2LCAxLjAyOTMzLCAxLCAxLCAwLjc1MTg2LCAxLjAyOTMzLCAwLjY3Nzg5LCAwLjc3ODMyLCAwLjY3Nzg5LCAwLjc3ODMyLCAwLjY3Nzg5LCAwLjc3ODMyLCAwLjY3Nzg5LCAwLjc3ODMyLCAxLCAxLCAwLjc5Nzc2LCAwLjk3NjU1LCAwLjc5Nzc2LCAxLjIzMDIzLCAwLjg4ODQ0LCAwLjkyNDUsIDAuODg4NDQsIDAuOTI0NSwgMC44ODg0NCwgMC45MjQ1LCAwLjg4ODQ0LCAwLjkyNDUsIDAuODg4NDQsIDAuOTI0NSwgMC44ODg0NCwgMC45MjQ1LCAwLjk0MzA5LCAwLjk4OTg2LCAwLjczMDYsIDAuODk0NTMsIDAuNzMwNiwgMC43NjY1OSwgMC43OTAwNCwgMC43NjY1OSwgMC43OTAwNCwgMC43NjY1OSwgMC43OTAwNCwgMS4wOTIzMSwgMC41NDg3MywgMC44Njc1LCAwLjkyNDUsIDAuNzYzMTgsIDAuODQ4NDMsIDAuODQ1NTcsIDAuODY2NTEsIDEsIDEsIDAuNzk3NzYsIDEuMjA1NjIsIDEuMTg2MjIsIDEuMTg2MjIsIDEsIDEuMTQzNywgMC42NzAwOSwgMC45NjMzNCwgMC45MzY5NSwgMS4zNTE5MSwgMS40MDkwOSwgMC45NTE2MSwgMS40ODM4NywgMC44Njc1LCAwLjkwODYxLCAwLjYxOTIsIDAuNzM2MywgMC42NDgyNCwgMC44MjQxMSwgMC41NjMyMSwgMC44NTY5NiwgMS4yMzUxNiwgMC44Njc1LCAwLjgxNTUyLCAwLjcyODYsIDAuODQxMzQsIDAuNzMyMDYsIDAuNzY2NTksIDAuODYyNzUsIDAuODQzNjksIDAuOTA2ODUsIDAuNzc4OTIsIDAuODU4NzEsIDEuMDI2MzgsIDAuODkyNDksIDAuNzU4MjgsIDAuODQxMTgsIDAuODU5ODQsIDAuNzc0NTIsIDAuNzY0NjYsIDAuNzk3NzYsIDAuNzMwNiwgMC45MDc4MiwgMC43NzgxOCwgMC45MDMsIDAuODcyOTEsIDAuOTA2ODUsIDAuNzMwNiwgMC45OTA1OCwgMS4wMzY2NywgMC45NDYzNSwgMS4yMzUxNiwgMC45ODQ5LCAwLjk5MDU4LCAwLjkyMzkzLCAwLjg5MTYsIDAuOTQyLCAxLjAzNjY3LCAwLjc1MDI2LCAwLjk0NjM1LCAxLjAyOTcsIDEuMjM1MTYsIDAuOTA5MTgsIDAuOTQwNDgsIDAuOTgyMTcsIDAuODk3NDYsIDAuODQxNTMsIDAuOTIyNzQsIDAuODI1MDcsIDAuODg4MzIsIDAuODQ0MzgsIDAuODgxNzgsIDEuMDM1MjUsIDAuOTg0OSwgMS4wMDIyNSwgMC43ODA4NiwgMC45NzI0OCwgMC44OTQwNCwgMS4yMzUxNiwgMC45ODQ5LCAwLjkyMjc0LCAwLjk4NDksIDAuODk0MDQsIDAuNzMyMDYsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuODk2OTMsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuODU4NjUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTA5MzMsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTQzMDksIDAuOTg5ODYsIDAuOTQzMDksIDAuOTg5ODYsIDAuOTQzMDksIDAuOTg5ODYsIDAuNzMwNiwgMC44OTQ1MywgMSwgMSwgMC44OTU1MiwgMC45MDUyNywgMSwgMC45MDE4NiwgMS4xMjMwOCwgMS4xMjMwOCwgMS4xMjMwOCwgMS4xMjMwOCwgMS4yNTY2LCAxLjI1NjYsIDEuMjU2NiwgMC44OTU1MiwgMC44OTU1MiwgMS40MjI1OSwgMC42ODk5NCwgMS4wMzgwOSwgMSwgMSwgMS4wMTc2LCAxLjAxNzYsIDEuMTE1MjMsIDEuNDk1NiwgMi4wMTQ2MiwgMC45Nzg1OCwgMC44MjYxNiwgMC45MTEzMywgMC44MzQzNywgMC45MTEzMywgMSwgMSwgMSwgMC43MDUwOCwgMSwgMS4yMzEwOCwgMC43OTgwMSwgMC44NDQyNiwgMC44NDQyNiwgMC43NzQsIDAuOTA1NzIsIDEuODEwNTUsIDAuOTA3NDksIDEuODEwNTUsIDEuMjg4MDksIDEuNTU0NjksIDAuOTQ0MzQsIDEuMDc4MDYsIDEsIDAuOTcwOTQsIDAuNzU4OSwgMC44NTI4NCwgMC45MDc0NywgMS4xOTY1OCwgMC42OTgyNSwgMC45NzYyMiwgMS4zMzUxMiwgMC45MDc0NywgMC45MDc0NywgMC44NTI4NCwgMC45MDc0NywgMC45MDc0NywgMS40NDk0NywgMC44NTI4NCwgMC44OTQxLCAwLjg5NDEsIDAuNzA1NzIsIDAuOCwgMC43MDU3MiwgMC43MDU3MiwgMC43MDU3MiwgMC43MDU3MiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45OTg2MiwgMC45OTg2MiwgMSwgMSwgMSwgMSwgMSwgMS4wMzM2LCAwLjkxMDI3LCAxLCAxLCAxLCAwLjk5ODYyLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjA1ODU5LCAxLjA1ODU5LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKY29uc3QgQ2FsaWJyaUl0YWxpY01ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4yMjA3LAogIGxpbmVHYXA6IDAuMjIwNwp9Owpjb25zdCBDYWxpYnJpUmVndWxhckZhY3RvcnMgPSBbMS4zODc3LCAxLCAxLCAxLCAxLjE3MjIzLCAxLjEyOTMsIDAuODk1NTIsIDAuOTExMzMsIDAuODAzOTUsIDEuMDIyNjksIDEuMTU2MDEsIDAuOTEwNTYsIDAuOTEwNTYsIDEuMjc5OCwgMC44NTI4NCwgMC44OTgwNywgMSwgMC45MDg2MSwgMS4zOTAxNiwgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45MTEzMywgMC45NjMwOSwgMC45NjMwOSwgMC44NTI4NCwgMC44NTI4NCwgMC44NTI4NCwgMC44MzMxOSwgMC44ODA3MSwgMC44Njc1LCAwLjgxNTUyLCAwLjczODM0LCAwLjg1MTkzLCAwLjczMjA2LCAwLjc1MjIsIDAuODExMDUsIDAuODYyNzUsIDAuOTA2ODUsIDAuNjM3NywgMC43Nzg5MiwgMC43NTU5MywgMS4wMjYzOCwgMC44OTM4NSwgMC44NTEyMiwgMC43NzQ1MiwgMC44NjUwMywgMC43NTE4NiwgMC42ODg4NywgMC43OTc3NiwgMC44ODg0NCwgMC44NTA2NiwgMC45NDI1OCwgMC43NzgxOCwgMC43MzA2LCAwLjc2NjU5LCAxLjEwMzY5LCAxLjM5MDE2LCAxLjEwMzY5LCAxLjA2MTM5LCAwLjg5NTUyLCAwLjg3MzksIDAuODYxMjgsIDAuOTQ0NjksIDAuODQ1NywgMC45NDQ2OSwgMC44OTQ2NCwgMS4wOTg0MiwgMC44NDYzNiwgMC45NDQ2OSwgMS4wMzI5NywgMS4wNzY5MiwgMC45MDkxOCwgMS4wMzI5NywgMC45NTg5NywgMC45NDQ2OSwgMC45NDgyLCAwLjk0NDY5LCAwLjk0NDY5LCAxLjA0NjkyLCAwLjc4MjIzLCAxLjIwNTYyLCAwLjk0NDY5LCAwLjkwMzMyLCAwLjk4OTg2LCAwLjg2NjIxLCAwLjkwNTI3LCAwLjc5MDA0LCAwLjk0MTUyLCAxLjc3MjU2LCAwLjk0MTUyLCAwLjg1Mjg0LCAwLjk3ODAxLCAwLjg5NTUyLCAwLjkxMTMzLCAwLjg5NTUyLCAwLjkxMTMzLCAxLjkxNzI5LCAwLjg5NTUyLCAxLjE3ODg5LCAxLjEzMjU0LCAxLjA4NzA3LCAwLjkyMDk4LCAwLjg1Mjg0LCAwLjY4Nzg3LCAwLjcxMzUzLCAwLjg0NzM3LCAwLjkwNzQ3LCAxLjAwODgsIDEuMDA0NCwgMC44NzY4MywgMSwgMS4wOTA5MSwgMSwgMC45MjIyOSwgMC43MzksIDEuMTU2NDIsIDAuOTIwOTgsIDAuNzYyODgsIDAuODA1MDQsIDAuODA5NzIsIDAuNzU4NTksIDAuODY3NSwgMC44Njc1LCAwLjg2NzUsIDAuODY3NSwgMC44Njc1LCAwLjg2NzUsIDAuNzYzMTgsIDAuNzM4MzQsIDAuNzMyMDYsIDAuNzMyMDYsIDAuNzMyMDYsIDAuNzMyMDYsIDAuOTA2ODUsIDAuOTA2ODUsIDAuOTA2ODUsIDAuOTA2ODUsIDAuODY0NzcsIDAuODkzODUsIDAuODUxMjIsIDAuODUxMjIsIDAuODUxMjIsIDAuODUxMjIsIDAuODUxMjIsIDAuODUyODQsIDAuODUzMTEsIDAuODg4NDQsIDAuODg4NDQsIDAuODg4NDQsIDAuODg4NDQsIDAuNzMwNiwgMC43NzQ1MiwgMC44NjMzMSwgMC44NjEyOCwgMC44NjEyOCwgMC44NjEyOCwgMC44NjEyOCwgMC44NjEyOCwgMC44NjEyOCwgMC44NjkzLCAwLjg0NTcsIDAuODk0NjQsIDAuODk0NjQsIDAuODk0NjQsIDAuODk0NjQsIDAuODI2MDEsIDAuODI2MDEsIDAuODI2MDEsIDAuODI2MDEsIDAuOTQ0NjksIDAuOTQ0NjksIDAuOTQ4MiwgMC45NDgyLCAwLjk0ODIsIDAuOTQ4MiwgMC45NDgyLCAwLjkwNzQ3LCAwLjg2NjUxLCAwLjk0NDY5LCAwLjk0NDY5LCAwLjk0NDY5LCAwLjk0NDY5LCAwLjkwNTI3LCAwLjk0NDY5LCAwLjkwNTI3LCAwLjg2NzUsIDAuODYxMjgsIDAuODY3NSwgMC44NjEyOCwgMC44Njc1LCAwLjg2MTI4LCAwLjczODM0LCAwLjg0NTcsIDAuNzM4MzQsIDAuODQ1NywgMC43MzgzNCwgMC44NDU3LCAwLjczODM0LCAwLjg0NTcsIDAuODUxOTMsIDAuOTI0NTQsIDAuODY0NzcsIDAuOTkyMSwgMC43MzIwNiwgMC44OTQ2NCwgMC43MzIwNiwgMC44OTQ2NCwgMC43MzIwNiwgMC44OTQ2NCwgMC43MzIwNiwgMC44OTQ2NCwgMC43MzIwNiwgMC44OTQ2NCwgMC44MTEwNSwgMC44NDYzNiwgMC44MTEwNSwgMC44NDYzNiwgMC44MTEwNSwgMC44NDYzNiwgMSwgMSwgMC44NjI3NSwgMC45NDQ2OSwgMC45MDg3MiwgMC45NTc4NiwgMC45MDY4NSwgMC44MjYwMSwgMC45MDY4NSwgMC44MjYwMSwgMC45MDY4NSwgMC44MjYwMSwgMC45MDY4NSwgMS4wMzI5NywgMC45MDY4NSwgMC44MjYwMSwgMC43Nzc0MSwgMS4wNTYxMSwgMC42Mzc3LCAxLjA3NjkyLCAxLCAxLCAwLjkwOTE4LCAwLjc1NTkzLCAxLjAzMjk3LCAxLCAxLCAwLjc2MDMyLCAwLjkwNDUyLCAwLjk4MTU2LCAxLjExODQyLCAwLjc3MjYxLCAxLjExNDI5LCAwLjg5Mzg1LCAwLjk0NDY5LCAxLCAxLCAwLjg5Mzg1LCAwLjk0NDY5LCAwLjk1ODc3LCAwLjg2OTAxLCAwLjk0NDY5LCAwLjg1MTIyLCAwLjk0ODIsIDAuODUxMjIsIDAuOTQ4MiwgMC44NTEyMiwgMC45NDgyLCAwLjg2NjcsIDAuOTAwMTYsIDAuNzUxODYsIDEuMDQ2OTIsIDEsIDEsIDAuNzUxODYsIDEuMDQ2OTIsIDAuNjg4ODcsIDAuNzgyMjMsIDAuNjg4ODcsIDAuNzgyMjMsIDAuNjg4ODcsIDAuNzgyMjMsIDAuNjg4ODcsIDAuNzgyMjMsIDEsIDEsIDAuNzk3NzYsIDAuOTIxODgsIDAuNzk3NzYsIDEuMjMwMjMsIDAuODg4NDQsIDAuOTQ0NjksIDAuODg4NDQsIDAuOTQ0NjksIDAuODg4NDQsIDAuOTQ0NjksIDAuODg4NDQsIDAuOTQ0NjksIDAuODg4NDQsIDAuOTQ0NjksIDAuODg4NDQsIDAuOTQ0NjksIDAuOTQyNTgsIDAuOTg5ODYsIDAuNzMwNiwgMC45MDUyNywgMC43MzA2LCAwLjc2NjU5LCAwLjc5MDA0LCAwLjc2NjU5LCAwLjc5MDA0LCAwLjc2NjU5LCAwLjc5MDA0LCAxLjA5MjMxLCAwLjU0ODczLCAwLjg2NzUsIDAuODYxMjgsIDAuNzYzMTgsIDAuODY5MywgMC44NTMxMSwgMC44NjY1MSwgMSwgMSwgMC43OTc3NiwgMS4yMDU2MiwgMS4xODYyMiwgMS4xODYyMiwgMSwgMS4xNDM3LCAwLjY3NzQyLCAwLjk2MzM0LCAwLjkzNjk1LCAxLjM1MTkxLCAxLjQwOTA5LCAwLjk1MTYxLCAxLjQ4Mzg3LCAwLjg2Njg2LCAwLjkwODYxLCAwLjYyMjY3LCAwLjc0MzU5LCAwLjY1NjQ5LCAwLjg1NDk4LCAwLjU2OTYzLCAwLjg4MjU0LCAxLjIzNTE2LCAwLjg2NzUsIDAuODE1NTIsIDAuNzU0NDMsIDAuODQ1MDMsIDAuNzMyMDYsIDAuNzY2NTksIDAuODYyNzUsIDAuODUxMjIsIDAuOTA2ODUsIDAuNzc4OTIsIDAuODU3NDYsIDEuMDI2MzgsIDAuODkzODUsIDAuNzU2NTcsIDAuODUxMjIsIDAuODYyNzUsIDAuNzc0NTIsIDAuNzQxNzEsIDAuNzk3NzYsIDAuNzMwNiwgMC45NTE2NSwgMC43NzgxOCwgMC44OTc3MiwgMC44ODgzMSwgMC45MDY4NSwgMC43MzA2LCAwLjk4MTQyLCAxLjAyMTkxLCAwLjk2NTc2LCAxLjIzNTE2LCAwLjk5MDE4LCAwLjk4MTQyLCAwLjkyMzYsIDAuODkyNTgsIDAuOTQwMzUsIDEuMDIxOTEsIDAuNzg4NDgsIDAuOTY1NzYsIDAuOTU2MSwgMS4yMzUxNiwgMC45MDkxOCwgMC45MjU3OCwgMC45NTQyNCwgMC44OTc0NiwgMC44Mzk2OSwgMC45NDgyLCAwLjgwMTEzLCAwLjg5NDQyLCAwLjg1MjA4LCAwLjg2MTU1LCAwLjk4MDIyLCAwLjk5MDE4LCAxLjAwNDUyLCAwLjgxMjA5LCAwLjk5MjQ3LCAwLjg5MTgxLCAxLjIzNTE2LCAwLjk5MDE4LCAwLjk0ODIsIDAuOTkwMTgsIDAuODkxODEsIDAuNzMyMDYsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuODg4NDQsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuODk0NjQsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTY3NjYsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTQyNTgsIDAuOTg5ODYsIDAuOTQyNTgsIDAuOTg5ODYsIDAuOTQyNTgsIDAuOTg5ODYsIDAuNzMwNiwgMC45MDUyNywgMSwgMSwgMC44OTU1MiwgMC45MDUyNywgMSwgMC45MDE4NiwgMS4xMjMwOCwgMS4xMjMwOCwgMS4xMjMwOCwgMS4xMjMwOCwgMS4yNTY2LCAxLjI1NjYsIDEuMjU2NiwgMC44OTU1MiwgMC44OTU1MiwgMS40MjI1OSwgMC42OTA0MywgMS4wMzgwOSwgMSwgMSwgMS4wMTc2LCAxLjAxNzYsIDEuMTE1MjMsIDEuNDk1NiwgMi4wMTQ2MiwgMC45OTMzMSwgMC44MjYxNiwgMC45MTEzMywgMC44NDI4NiwgMC45MTEzMywgMSwgMSwgMSwgMC43MDUwOCwgMSwgMS4yMzEwOCwgMC43OTgwMSwgMC44NDQyNiwgMC44NDQyNiwgMC43NzQsIDAuOTA1MjcsIDEuODEwNTUsIDAuOTA1MjcsIDEuODEwNTUsIDEuMjg4MDksIDEuNTU0NjksIDAuOTQ0MzQsIDEuMDc4MDYsIDEsIDAuOTcwOTQsIDAuNzU4OSwgMC44NTI4NCwgMC45MDc0NywgMS4xOTY1OCwgMC42OTgyNSwgMC45NzYyMiwgMS4zMzUxMiwgMC45MDc0NywgMC45MDc0NywgMC44NTM1NiwgMC45MDc0NywgMC45MDc0NywgMS40NDk0NywgMC44NTI4NCwgMC44OTQxLCAwLjg5NDEsIDAuNzA1NzIsIDAuOCwgMC43MDU3MiwgMC43MDU3MiwgMC43MDU3MiwgMC43MDU3MiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45OTg2MiwgMC45OTg2MiwgMSwgMSwgMSwgMSwgMSwgMS4wMzM2LCAwLjkxMDI3LCAxLCAxLCAxLCAwLjk5ODYyLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjA1ODU5LCAxLjA1ODU5LCAxLCAxLCAxLCAxLjA3MTg1LCAwLjk5NDEzLCAwLjk2MzM0LCAxLjA4MDY1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKY29uc3QgQ2FsaWJyaVJlZ3VsYXJNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMjIwNywKICBsaW5lR2FwOiAwLjIyMDcKfTsKCjsvLyAuL3NyYy9jb3JlL2hlbHZldGljYV9mYWN0b3JzLmpzCmNvbnN0IEhlbHZldGljYUJvbGRGYWN0b3JzID0gWzAuNzYxMTYsIDEsIDEsIDEuMDAwNiwgMC45OTk5OCwgMC45OTk3NCwgMC45OTk3MywgMC45OTk3MywgMC45OTk4MiwgMC45OTk3NywgMS4wMDA4NywgMC45OTk5OCwgMC45OTk5OCwgMC45OTk1OSwgMS4wMDAwMywgMS4wMDA2LCAwLjk5OTk4LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk5OCwgMSwgMS4wMDAwMywgMS4wMDAwMywgMS4wMDAwMywgMS4wMDAyNiwgMC45OTk5LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDI2LCAxLjAwMDIyLCAwLjk5OTc3LCAxLjAwMDYsIDAuOTk5NzMsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5OTksIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwMDEsIDEuMDAwMjIsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMTYsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5OTgsIDEuMDAwNiwgMC45OTk5OCwgMS4wMDAwMywgMC45OTk3MywgMC45OTk5OCwgMC45OTk3MywgMS4wMDAyNiwgMC45OTk3MywgMS4wMDAyNiwgMC45OTk3MywgMC45OTk5OCwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzMsIDEuMDAwNiwgMC45OTk4MiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMC45OTk1OSwgMC45OTk3MywgMC45OTk5OCwgMS4wMDAyNiwgMC45OTk3MywgMS4wMDAyMiwgMC45OTk3MywgMC45OTk3MywgMSwgMC45OTk1OSwgMS4wMDA3NywgMC45OTk1OSwgMS4wMDAwMywgMC45OTk5OCwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wMDA3NywgMC45OTk3MywgMC45OTk5OCwgMS4wMDAyNSwgMC45OTk2OCwgMC45OTk3MywgMS4wMDAwMywgMS4wMDAyNSwgMC42MDI5OSwgMS4wMDAyNCwgMS4wNjQwOSwgMSwgMSwgMC45OTk5OCwgMSwgMC45OTk3MywgMS4wMDA2LCAwLjk5OTk4LCAxLCAwLjk5OTM2LCAwLjk5OTczLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDI2LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAxLCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMDMsIDEuMDAwMjIsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5ODIsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wNjQwOSwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMC45OTk3MywgMS4wMDAyNiwgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMS4wMzM3NCwgMC45OTk3NywgMS4wMDAyNiwgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAyMiwgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDQyLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDYsIDAuOTk5NzcsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwMjYsIDEuMDAwNiwgMS4wMDAyNiwgMS4wMDA2LCAxLjAwMDI2LCAxLjAzODI4LCAxLjAwMDI2LCAwLjk5OTk5LCAxLjAwMDI2LCAxLjAwMDYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5MywgMC45OTk4LCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAxLCAxLjAwMDE2LCAwLjk5OTc3LCAwLjk5OTU5LCAwLjk5OTc3LCAwLjk5OTU5LCAwLjk5OTc3LCAwLjk5OTU5LCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDI2LCAwLjk5OTk4LCAxLjAwMDI2LCAwLjgxMjEsIDEuMDAwMjYsIDAuOTk5OTgsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjYsIDEuMDAwMTYsIDEuMDAwMjIsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDEuMDAwMjYsIDEsIDEuMDAwMjYsIDEsIDEuMDAwMjYsIDEsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMSwgMC45OTk4MiwgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAyNiwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMS4wMDAzNCwgMC45OTk3NywgMSwgMC45OTk5NywgMS4wMDAyNiwgMS4wMDA3OCwgMS4wMDAzNiwgMC45OTk3MywgMS4wMDAxMywgMS4wMDA2LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTg4LCAwLjg1MTQ4LCAxLjAwMDAxLCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDIyLCAxLjAwMDYsIDAuOTk5NzcsIDEuMDAwMDEsIDAuOTk5OTksIDAuOTk5NzcsIDEuMDAwNjksIDEuMDAwMjIsIDAuOTk5NzcsIDEuMDAwMDEsIDAuOTk5ODQsIDEuMDAwMjYsIDEuMDAwMDEsIDEuMDAwMjQsIDEuMDAwMDEsIDAuOTk5OSwgMSwgMS4wMDA2LCAxLjAwMDAxLCAxLjAwMDQxLCAwLjk5OTYyLCAxLjAwMDI2LCAxLjAwMDYsIDAuOTk5OTUsIDEuMDAwNDEsIDAuOTk5NDIsIDAuOTk5NzMsIDAuOTk5MjcsIDEuMDAwODIsIDAuOTk5MDIsIDEuMDAwMjYsIDEuMDAwODcsIDEuMDAwNiwgMS4wMDA2OSwgMC45OTk3MywgMC45OTg2NywgMC45OTk3MywgMC45OTkzLCAxLjAwMDI2LCAxLjAwMDQ5LCAxLjAwMDU2LCAxLCAwLjk5OTg4LCAwLjk5OTM1LCAwLjk5OTk1LCAwLjk5OTU0LCAxLjAwMDU1LCAwLjk5OTQ1LCAxLjAwMDMyLCAxLjAwMDYsIDAuOTk5OTUsIDEuMDAwMjYsIDAuOTk5OTUsIDEuMDAwMzIsIDEuMDAwMDEsIDEuMDAwMDgsIDAuOTk5NzEsIDEuMDAwMTksIDAuOTk5NCwgMS4wMDAwMSwgMS4wMDA2LCAxLjAwMDQ0LCAwLjk5OTczLCAxLjAwMDIzLCAxLjAwMDQ3LCAxLCAwLjk5OTQyLCAwLjk5NTYxLCAwLjk5OTg5LCAxLjAwMDM1LCAwLjk5OTc3LCAxLjAwMDM1LCAwLjk5OTc3LCAxLjAwMDE5LCAwLjk5OTQ0LCAxLjAwMDAxLCAxLjAwMDIxLCAwLjk5OTI2LCAxLjAwMDM1LCAxLjAwMDM1LCAwLjk5OTQyLCAxLjAwMDQ4LCAwLjk5OTk5LCAwLjk5OTc3LCAxLjAwMDIyLCAxLjAwMDM1LCAxLjAwMDAxLCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTg5LCAxLjAwMDU3LCAxLjAwMDAxLCAwLjk5OTM2LCAxLjAwMDUyLCAxLjAwMDEyLCAwLjk5OTk2LCAxLjAwMDQzLCAxLCAxLjAwMDM1LCAwLjk5OTQsIDAuOTk5NzYsIDEuMDAwMzUsIDAuOTk5NzMsIDEuMDAwNTIsIDEuMDAwNDEsIDEuMDAxMTksIDEuMDAwMzcsIDAuOTk5NzMsIDEuMDAwMDIsIDAuOTk5ODYsIDEuMDAwNDEsIDEuMDAwNDEsIDAuOTk5MDIsIDAuOTk5NiwgMS4wMDAzNCwgMC45OTk5OSwgMS4wMDAyNiwgMC45OTk5OSwgMS4wMDAyNiwgMC45OTk3MywgMS4wMDA1MiwgMC45OTk3MywgMSwgMC45OTk3MywgMS4wMDA0MSwgMS4wMDA3NSwgMC45OTk0LCAxLjAwMDMsIDAuOTk5OTksIDEsIDEuMDAwNDEsIDAuOTk5NTUsIDEsIDAuOTk5MTUsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwMjYsIDEuMDAxMTksIDAuOTk5NTUsIDAuOTk5NzMsIDEuMDAwNiwgMC45OTkxMSwgMS4wMDA2LCAxLjAwMDI2LCAwLjk5OTcyLCAxLjAwMDI2LCAwLjk5OTAyLCAxLjAwMDQxLCAwLjk5OTczLCAwLjk5OTk5LCAxLCAxLCAxLjAwMDM4LCAxLjAwMDUsIDEuMDAwMTYsIDEuMDAwMjIsIDEuMDAwMTYsIDEuMDAwMjIsIDEuMDAwMTYsIDEuMDAwMjIsIDEuMDAwMDEsIDAuOTk5NzMsIDEsIDEsIDAuOTk5NzMsIDEsIDEsIDAuOTk5NTUsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMSwgMSwgMSwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MiwgMSwgMSwgMS4wMDEwNiwgMC45OTk5OSwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OSwgMC45OTk5OCwgMS42NjQ3NSwgMSwgMC45OTk3MywgMC45OTk3MywgMS4wMDAyMywgMC45OTk3MywgMC45OTk3MSwgMS4wMDA0NywgMS4wMDAyMywgMSwgMC45OTk5MSwgMC45OTk4NCwgMS4wMDAwMiwgMS4wMDAwMiwgMS4wMDAwMiwgMS4wMDAwMiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45OTk3MiwgMSwgMS4yMDk4NSwgMS4zOTcxMywgMS4wMDAwMywgMS4wMDAzMSwgMS4wMDAxNSwgMSwgMC45OTU2MSwgMS4wMDAyNywgMS4wMDAzMSwgMS4wMDAzMSwgMC45OTkxNSwgMS4wMDAzMSwgMS4wMDAzMSwgMC45OTk5OSwgMS4wMDAwMywgMC45OTk5OSwgMC45OTk5OSwgMS40MTE0NCwgMS42LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQwNTc5LCAxLjQwNTc5LCAxLjM2NjI1LCAwLjk5OTk5LCAxLCAwLjk5ODYxLCAwLjk5ODYxLCAxLCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAwLjk5OTcyLCAwLjk5OTk5LCAwLjk5OTk5LCAwLjk5OTk5LCAwLjk5OTk5LCAxLjQwNDgzLCAxLCAwLjk5OTc3LCAxLjAwMDU0LCAxLCAxLCAwLjk5OTUzLCAwLjk5OTYyLCAxLjAwMDQyLCAwLjk5OTUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpjb25zdCBIZWx2ZXRpY2FCb2xkTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjIsCiAgbGluZUdhcDogMC4yCn07CmNvbnN0IEhlbHZldGljYUJvbGRJdGFsaWNGYWN0b3JzID0gWzAuNzYxMTYsIDEsIDEsIDEuMDAwNiwgMC45OTk5OCwgMC45OTk3NCwgMC45OTk3MywgMC45OTk3MywgMC45OTk4MiwgMC45OTk3NywgMS4wMDA4NywgMC45OTk5OCwgMC45OTk5OCwgMC45OTk1OSwgMS4wMDAwMywgMS4wMDA2LCAwLjk5OTk4LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk5OCwgMSwgMS4wMDAwMywgMS4wMDAwMywgMS4wMDAwMywgMS4wMDAyNiwgMC45OTk5LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDI2LCAxLjAwMDIyLCAwLjk5OTc3LCAxLjAwMDYsIDAuOTk5NzMsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5OTksIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwMDEsIDEuMDAwMjIsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMTYsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5OTgsIDEuMDAwNiwgMC45OTk5OCwgMS4wMDAwMywgMC45OTk3MywgMC45OTk5OCwgMC45OTk3MywgMS4wMDAyNiwgMC45OTk3MywgMS4wMDAyNiwgMC45OTk3MywgMC45OTk5OCwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzMsIDEuMDAwNiwgMC45OTk4MiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMC45OTk1OSwgMC45OTk3MywgMC45OTk5OCwgMS4wMDAyNiwgMC45OTk3MywgMS4wMDAyMiwgMC45OTk3MywgMC45OTk3MywgMSwgMC45OTk1OSwgMS4wMDA3NywgMC45OTk1OSwgMS4wMDAwMywgMC45OTk5OCwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wMDA3NywgMC45OTk3MywgMC45OTk5OCwgMS4wMDAyNSwgMC45OTk2OCwgMC45OTk3MywgMS4wMDAwMywgMS4wMDAyNSwgMC42MDI5OSwgMS4wMDAyNCwgMS4wNjQwOSwgMSwgMSwgMC45OTk5OCwgMSwgMC45OTk3MywgMS4wMDA2LCAwLjk5OTk4LCAxLCAwLjk5OTM2LCAwLjk5OTczLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDI2LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAxLCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMDMsIDEuMDAwMjIsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5ODIsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wNjQwOSwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMC45OTk3MywgMS4wMDAyNiwgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMS4wMDQ0LCAwLjk5OTc3LCAxLjAwMDI2LCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDIyLCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDI2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzEsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNiwgMC45OTk3NywgMC45OTk3MywgMC45OTk3MywgMS4wMDAyNiwgMS4wMDA2LCAxLjAwMDI2LCAxLjAwMDYsIDEuMDAwMjYsIDEuMDEwMTEsIDEuMDAwMjYsIDAuOTk5OTksIDEuMDAwMjYsIDEuMDAwNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTkzLCAwLjk5OTgsIDEuMDAwMjYsIDEuMDAwMjIsIDEuMDAwMjYsIDEuMDAwMjIsIDEuMDAwMjYsIDEuMDAwMjIsIDEuMDAwMjYsIDEsIDEuMDAwMTYsIDAuOTk5NzcsIDAuOTk5NTksIDAuOTk5NzcsIDAuOTk5NTksIDAuOTk5NzcsIDAuOTk5NTksIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMjYsIDAuOTk5OTgsIDEuMDAwMjYsIDAuODEyMSwgMS4wMDAyNiwgMC45OTk5OCwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyNiwgMS4wMDAxNiwgMS4wMDAyMiwgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMS4wMDAyNiwgMSwgMS4wMDAyNiwgMSwgMS4wMDAyNiwgMSwgMS4wMDA2LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTczLCAxLCAwLjk5OTgyLCAxLjAwMDIyLCAxLjAwMDI2LCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDI2LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTc3LCAxLCAxLCAxLjAwMDI2LCAwLjk5OTY5LCAwLjk5OTcyLCAwLjk5OTgxLCAwLjk5OTgsIDEuMDAwNiwgMC45OTk3NywgMC45OTk3NywgMS4wMDAyMiwgMC45MTE1NSwgMS4wMDAwMSwgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAyMiwgMS4wMDA2LCAwLjk5OTc3LCAxLjAwMDAxLCAwLjk5OTk5LCAwLjk5OTc3LCAwLjk5OTY2LCAxLjAwMDIyLCAxLjAwMDMyLCAxLjAwMDAxLCAwLjk5OTQ0LCAxLjAwMDI2LCAxLjAwMDAxLCAwLjk5OTY4LCAxLjAwMDAxLCAxLjAwMDQ3LCAxLCAxLjAwMDYsIDEuMDAwMDEsIDAuOTk5ODEsIDEuMDAxMDEsIDEuMDAwMjYsIDEuMDAwNiwgMC45OTk0OCwgMC45OTk4MSwgMS4wMDA2NCwgMC45OTk3MywgMC45OTk0MiwgMS4wMDEwMSwgMS4wMDA2MSwgMS4wMDAyNiwgMS4wMDA2OSwgMS4wMDA2LCAxLjAwMDE0LCAwLjk5OTczLCAxLjAxMzIyLCAwLjk5OTczLCAxLjAwMDY1LCAxLjAwMDI2LCAxLjAwMDEyLCAwLjk5OTIzLCAxLCAxLjAwMDY0LCAxLjAwMDc2LCAwLjk5OTQ4LCAxLjAwMDU1LCAxLjAwMDYzLCAxLjAwMDA3LCAwLjk5OTQzLCAxLjAwMDYsIDAuOTk5NDgsIDEuMDAwMjYsIDAuOTk5NDgsIDAuOTk5NDMsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMjksIDEuMDAwMzgsIDEuMDAwMzUsIDEuMDAwMDEsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTczLCAwLjk5OTc4LCAxLjAwMDAxLCAxLjAwMDU3LCAwLjk5OTg5LCAwLjk5OTY3LCAwLjk5OTY0LCAwLjk5OTY3LCAwLjk5OTc3LCAwLjk5OTk5LCAwLjk5OTc3LCAxLjAwMDM4LCAwLjk5OTc3LCAxLjAwMDAxLCAwLjk5OTczLCAxLjAwMDY2LCAwLjk5OTY3LCAwLjk5OTY3LCAxLjAwMDQxLCAwLjk5OTk4LCAwLjk5OTk5LCAwLjk5OTc3LCAxLjAwMDIyLCAwLjk5OTY3LCAxLjAwMDAxLCAwLjk5OTc3LCAxLjAwMDI2LCAwLjk5OTY0LCAxLjAwMDMxLCAxLjAwMDAxLCAwLjk5OTk5LCAwLjk5OTk5LCAxLCAxLjAwMDIzLCAxLCAxLCAwLjk5OTk5LCAxLjAwMDM1LCAxLjAwMDAxLCAwLjk5OTk5LCAwLjk5OTczLCAwLjk5OTc3LCAwLjk5OTk5LCAxLjAwMDU4LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTU1LCAwLjk5OTUsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMzIsIDAuOTk5ODksIDEuMDAwMzQsIDAuOTk5OTksIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDAuOTk5NzMsIDAuNDU5OTgsIDAuOTk5NzMsIDEuMDAwMjYsIDAuOTk5NzMsIDEuMDAwMDEsIDAuOTk5OTksIDAuOTk5ODIsIDAuOTk5OTQsIDAuOTk5OTYsIDEsIDEuMDAwNDIsIDEuMDAwNDQsIDEuMDAwMjksIDEuMDAwMjMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwMjYsIDAuOTk5NDksIDEuMDAwMDIsIDAuOTk5NzMsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzUsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMzIsIDAuOTg2ODUsIDAuOTk5NzMsIDEuMDAwMjYsIDEsIDEsIDAuOTk5NjYsIDEuMDAwNDQsIDEuMDAwMTYsIDEuMDAwMjIsIDEuMDAwMTYsIDEuMDAwMjIsIDEuMDAwMTYsIDEuMDAwMjIsIDEuMDAwMDEsIDAuOTk5NzMsIDEsIDEsIDAuOTk5NzMsIDEsIDEsIDAuOTk5NTUsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMSwgMSwgMSwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MiwgMSwgMSwgMS4wMDEwNiwgMC45OTk5OSwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OSwgMC45OTk5OCwgMS42NjQ3NSwgMSwgMC45OTk3MywgMC45OTk3MywgMSwgMC45OTk3MywgMC45OTk3MSwgMC45OTk3OCwgMSwgMSwgMC45OTk5MSwgMC45OTk4NCwgMS4wMDAwMiwgMS4wMDAwMiwgMS4wMDAwMiwgMS4wMDAwMiwgMS4wMDA5OCwgMSwgMSwgMSwgMS4wMDA0OSwgMSwgMSwgMC45OTk3MiwgMSwgMS4yMDk4NSwgMS4zOTcxMywgMS4wMDAwMywgMS4wMDAzMSwgMS4wMDAxNSwgMSwgMC45OTU2MSwgMS4wMDAyNywgMS4wMDAzMSwgMS4wMDAzMSwgMC45OTkxNSwgMS4wMDAzMSwgMS4wMDAzMSwgMC45OTk5OSwgMS4wMDAwMywgMC45OTk5OSwgMC45OTk5OSwgMS40MTE0NCwgMS42LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQxMTQ0LCAxLjQwNTc5LCAxLjQwNTc5LCAxLjM2NjI1LCAwLjk5OTk5LCAxLCAwLjk5ODYxLCAwLjk5ODYxLCAxLCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAxLjAwMDI2LCAwLjk5OTcyLCAwLjk5OTk5LCAwLjk5OTk5LCAwLjk5OTk5LCAwLjk5OTk5LCAxLjQwNDgzLCAxLCAwLjk5OTc3LCAxLjAwMDU0LCAxLCAxLCAwLjk5OTUzLCAwLjk5OTYyLCAxLjAwMDQyLCAwLjk5OTUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5OTgsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpjb25zdCBIZWx2ZXRpY2FCb2xkSXRhbGljTWV0cmljcyA9IHsKICBsaW5lSGVpZ2h0OiAxLjM1LAogIGxpbmVHYXA6IDAuMgp9Owpjb25zdCBIZWx2ZXRpY2FJdGFsaWNGYWN0b3JzID0gWzAuNzYxMTYsIDEsIDEsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDA2LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTgyLCAxLjAwMDAxLCAxLjAwMDQzLCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTU5LCAxLjAwMDAzLCAxLjAwMDYsIDAuOTk5OTgsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDYsIDEsIDEuMDAwMDMsIDEuMDAwMDMsIDEuMDAwMDMsIDAuOTk5NzMsIDAuOTk5ODcsIDEuMDAwMDEsIDEuMDAwMDEsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMjYsIDEuMDAwMjIsIDAuOTk5NzcsIDEuMDAwNiwgMSwgMS4wMDAwMSwgMC45OTk3MywgMC45OTk5OSwgMC45OTk3NywgMS4wMDAyMiwgMS4wMDAwMSwgMS4wMDAyMiwgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAyNiwgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAxNiwgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAyNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk0OSwgMC45OTk3MywgMC45OTk5OCwgMC45OTk3MywgMC45OTk3MywgMSwgMC45OTk3MywgMC45OTk3MywgMS4wMDA2LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTI0LCAwLjk5OTI0LCAxLCAwLjk5OTI0LCAwLjk5OTk5LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTk4LCAxLCAxLjAwMDYsIDAuOTk5NzMsIDEsIDAuOTk5NzcsIDEsIDEsIDEsIDEuMDAwMDUsIDEuMDAwOSwgMS4wMDAwNSwgMS4wMDAwMywgMC45OTk5OCwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wMDA5LCAwLjk5OTczLCAwLjk5OTk4LCAxLjAwMDI1LCAwLjk5OTY4LCAwLjk5OTczLCAxLjAwMDAzLCAxLjAwMDI1LCAwLjYwMjk5LCAxLjAwMDI0LCAxLjA2NDA5LCAxLCAxLCAwLjk5OTk4LCAxLCAwLjk5OTgsIDEuMDAwNiwgMC45OTk5OCwgMSwgMC45OTkzNiwgMC45OTk3MywgMS4wMDAwMiwgMS4wMDAwMiwgMS4wMDAwMiwgMS4wMDAyNiwgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAwMSwgMSwgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTc3LCAwLjk5OTc3LCAxLjAwMDIyLCAxLjAwMDIyLCAxLjAwMDIyLCAxLjAwMDIyLCAxLjAwMDIyLCAxLjAwMDAzLCAxLjAwMDIyLCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDI2LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTgyLCAxLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDY0MDksIDEuMDAwMjYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEsIDAuOTk5NzMsIDEsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDAuOTk5NzMsIDEuMDAwMDEsIDAuOTk5NzMsIDAuOTk5NzcsIDEsIDAuOTk5NzcsIDEsIDAuOTk5NzcsIDEsIDAuOTk5NzcsIDEsIDAuOTk5NzcsIDEuMDI4OCwgMC45OTk3NywgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAyMiwgMC45OTk3MywgMS4wMDAyMiwgMC45OTk3MywgMS4wMDAyMiwgMC45OTk3MywgMS4wMDAyMiwgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTI0LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk0NiwgMS4wMDAzNCwgMSwgMC45OTkyNCwgMS4wMDAwMSwgMSwgMSwgMC45OTk3MywgMC45OTkyNCwgMC45OTk3MywgMC45OTkyNCwgMC45OTk3MywgMS4wNjMxMSwgMC45OTk3MywgMS4wMDAyNCwgMC45OTk3MywgMC45OTkyNCwgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMS4wMDA0MSwgMC45OTk4LCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLCAxLjAwMDE2LCAwLjk5OTc3LCAwLjk5OTk4LCAwLjk5OTc3LCAwLjk5OTk4LCAwLjk5OTc3LCAwLjk5OTk4LCAxLjAwMDAxLCAxLCAxLjAwMDAxLCAxLCAxLjAwMDAxLCAxLCAxLjAwMDAxLCAxLCAxLjAwMDI2LCAxLjAwMDYsIDEuMDAwMjYsIDAuODk1NDcsIDEuMDAwMjYsIDEuMDAwNiwgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMS4wMDAxNiwgMC45OTk3NywgMS4wMDAwMSwgMSwgMS4wMDAwMSwgMS4wMDAyNiwgMSwgMS4wMDAyNiwgMSwgMS4wMDAyNiwgMSwgMC45OTkyNCwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMSwgMC45OTk4MiwgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAwMSwgMSwgMS4wMDAyNiwgMS4wMDA2LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAxLjAwMDAxLCAxLCAxLjAwMDU0LCAwLjk5OTc3LCAxLjAwMDg0LCAxLjAwMDA3LCAwLjk5OTczLCAxLjAwMDEzLCAwLjk5OTI0LCAxLjAwMDAxLCAxLjAwMDAxLCAwLjk5OTQ1LCAwLjkxMjIxLCAxLjAwMDAxLCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDIyLCAxLjAwMDYsIDEuMDAwMDEsIDEuMDAwMDEsIDAuOTk5OTksIDAuOTk5NzcsIDAuOTk5MzMsIDEuMDAwMjIsIDEuMDAwNTQsIDEuMDAwMDEsIDEuMDAwNjUsIDEuMDAwMjYsIDEuMDAwMDEsIDEuMDAwMSwgMS4wMDAwMSwgMS4wMDA1MiwgMSwgMS4wMDA2LCAxLjAwMDAxLCAwLjk5OTQ1LCAwLjk5ODk3LCAwLjk5OTY4LCAwLjk5OTI0LCAxLjAwMDM2LCAwLjk5OTQ1LCAwLjk5OTQ5LCAxLCAxLjAwMDYsIDAuOTk4OTcsIDAuOTk5MTgsIDAuOTk5NjgsIDAuOTk5MTEsIDAuOTk5MjQsIDEsIDAuOTk5NjIsIDEuMDE0ODcsIDEsIDEuMDAwNSwgMC45OTk3MywgMS4wMDAxMiwgMS4wMDA0MywgMSwgMC45OTk5NSwgMC45OTk5NCwgMS4wMDAzNiwgMC45OTk0NywgMS4wMDAxOSwgMS4wMDA2MywgMS4wMDAyNSwgMC45OTkyNCwgMS4wMDAzNiwgMC45OTk3MywgMS4wMDAzNiwgMS4wMDAyNSwgMS4wMDAwMSwgMS4wMDAwMSwgMS4wMDAyNywgMS4wMDAxLCAxLjAwMDY4LCAxLjAwMDAxLCAxLjAwMDYsIDEuMDAwNiwgMSwgMS4wMDAwOCwgMC45OTk1NywgMC45OTk3MiwgMC45OTk0LCAwLjk5OTU0LCAwLjk5OTc1LCAxLjAwMDUxLCAxLjAwMDAxLCAxLjAwMDE5LCAxLjAwMDAxLCAxLjAwMDEsIDAuOTk5ODYsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMzgsIDAuOTk5NTQsIDAuOTk5NTQsIDAuOTk5NCwgMS4wMDA2NiwgMC45OTk5OSwgMC45OTk3NywgMS4wMDAyMiwgMS4wMDA1NCwgMS4wMDAwMSwgMC45OTk3NywgMS4wMDAyNiwgMC45OTk3NSwgMS4wMDAxLCAxLjAwMDAxLCAwLjk5OTkzLCAwLjk5OTUsIDAuOTk5NTUsIDEuMDAwMTYsIDAuOTk5NzgsIDAuOTk5NzQsIDEuMDAwMTksIDEuMDAwMjIsIDAuOTk5NTUsIDEuMDAwNTMsIDAuOTk5NzMsIDEuMDAwODksIDEuMDAwMDUsIDAuOTk5NjcsIDEuMDAwNDgsIDAuOTk5NzMsIDEuMDAwMDIsIDEuMDAwMzQsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NjQsIDEuMDAwMDYsIDEuMDAwNjYsIDAuOTk5NDcsIDAuOTk5NzMsIDAuOTg4OTQsIDAuOTk5NzMsIDEsIDAuNDQ4OTgsIDEsIDAuOTk5NDYsIDEsIDEuMDAwMzksIDEuMDAwODIsIDAuOTk5OTEsIDAuOTk5OTEsIDAuOTk5ODUsIDEuMDAwMjIsIDEuMDAwMjMsIDEuMDAwNjEsIDEuMDAwMDYsIDAuOTk5NjYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwMTksIDEuMDAwOCwgMSwgMC45OTkyNCwgMC45OTkyNCwgMC45OTkyNCwgMC45OTk4MywgMS4wMDA0NCwgMC45OTk3MywgMC45OTk2NCwgMC45ODMzMiwgMSwgMC45OTk3MywgMSwgMSwgMC45OTk2MiwgMC45OTg5NSwgMS4wMDAxNiwgMC45OTk3NywgMS4wMDAxNiwgMC45OTk3NywgMS4wMDAxNiwgMC45OTk3NywgMS4wMDAwMSwgMSwgMSwgMSwgMC45OTk3MywgMSwgMSwgMC45OTk1NSwgMC45OTkyNCwgMC45OTkyNCwgMC45OTkyNCwgMC45OTkyNCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MiwgMSwgMSwgMS4wMDI2NywgMC45OTk5OSwgMC45OTk5OCwgMC45OTk5OCwgMSwgMC45OTk5OCwgMS42NjQ3NSwgMSwgMC45OTk3MywgMC45OTk3MywgMS4wMDAyMywgMC45OTk3MywgMS4wMDQyMywgMC45OTkyNSwgMC45OTk5OSwgMSwgMC45OTk5MSwgMC45OTk4NCwgMS4wMDAwMiwgMS4wMDAwMiwgMS4wMDAwMiwgMS4wMDAwMiwgMS4wMDA0OSwgMSwgMS4wMDI0NSwgMSwgMSwgMSwgMSwgMC45NjMyOSwgMSwgMS4yMDk4NSwgMS4zOTcxMywgMS4wMDAwMywgMC44MjU0LCAxLjAwMDE1LCAxLCAxLjAwMDM1LCAxLjAwMDI3LCAxLjAwMDMxLCAxLjAwMDMxLCAxLjAwMDAzLCAxLjAwMDMxLCAxLjAwMDMxLCAwLjk5OTk5LCAxLjAwMDAzLCAwLjk5OTk5LCAwLjk5OTk5LCAxLjQxMTQ0LCAxLjYsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDExNDQsIDEuNDA1NzksIDEuNDA1NzksIDEuMzY2MjUsIDAuOTk5OTksIDEsIDAuOTk4NjEsIDAuOTk4NjEsIDEsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDEuMDAwMjYsIDAuOTUzMTcsIDAuOTk5OTksIDAuOTk5OTksIDAuOTk5OTksIDAuOTk5OTksIDEuNDA0ODMsIDEsIDAuOTk5NzcsIDEuMDAwNTQsIDEsIDEsIDAuOTk5NTMsIDAuOTk5NjIsIDEuMDAwNDIsIDAuOTk5NSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMC45OTk5OCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMV07CmNvbnN0IEhlbHZldGljYUl0YWxpY01ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4zNSwKICBsaW5lR2FwOiAwLjIKfTsKY29uc3QgSGVsdmV0aWNhUmVndWxhckZhY3RvcnMgPSBbMC43NjExNiwgMSwgMSwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwMDYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5ODIsIDEuMDAwMDEsIDEuMDAwNDMsIDAuOTk5OTgsIDAuOTk5OTgsIDAuOTk5NTksIDEuMDAwMDMsIDEuMDAwNiwgMC45OTk5OCwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNiwgMSwgMS4wMDAwMywgMS4wMDAwMywgMS4wMDAwMywgMC45OTk3MywgMC45OTk4NywgMS4wMDAwMSwgMS4wMDAwMSwgMC45OTk3NywgMC45OTk3NywgMS4wMDAwMSwgMS4wMDAyNiwgMS4wMDAyMiwgMC45OTk3NywgMS4wMDA2LCAxLCAxLjAwMDAxLCAwLjk5OTczLCAwLjk5OTk5LCAwLjk5OTc3LCAxLjAwMDIyLCAxLjAwMDAxLCAxLjAwMDIyLCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDI2LCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDE2LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDI2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTQ5LCAwLjk5OTczLCAwLjk5OTk4LCAwLjk5OTczLCAwLjk5OTczLCAxLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5MjQsIDAuOTk5MjQsIDEsIDAuOTk5MjQsIDAuOTk5OTksIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5OTgsIDEsIDEuMDAwNiwgMC45OTk3MywgMSwgMC45OTk3NywgMSwgMSwgMSwgMS4wMDAwNSwgMS4wMDA5LCAxLjAwMDA1LCAxLjAwMDAzLCAwLjk5OTk4LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDksIDAuOTk5NzMsIDAuOTk5OTgsIDEuMDAwMjUsIDAuOTk5NjgsIDAuOTk5NzMsIDEuMDAwMDMsIDEuMDAwMjUsIDAuNjAyOTksIDEuMDAwMjQsIDEuMDY0MDksIDEsIDEsIDAuOTk5OTgsIDEsIDAuOTk5OCwgMS4wMDA2LCAwLjk5OTk4LCAxLCAwLjk5OTM2LCAwLjk5OTczLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDI2LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLCAwLjk5OTc3LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMjIsIDEuMDAwMDMsIDEuMDAwMjIsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDAuOTk5NzcsIDEuMDAwMDEsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5ODIsIDEsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDAuOTk5NzMsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMS4wNjQwOSwgMS4wMDAyNiwgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMC45OTk3MywgMSwgMC45OTk3MywgMSwgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMC45OTk3NywgMSwgMC45OTk3NywgMSwgMC45OTk3NywgMSwgMC45OTk3NywgMSwgMC45OTk3NywgMS4wNDU5NiwgMC45OTk3NywgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAyMiwgMC45OTk3MywgMS4wMDAyMiwgMC45OTk3MywgMS4wMDAyMiwgMC45OTk3MywgMS4wMDAyMiwgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDA2LCAwLjk5OTI0LCAxLjAwMDYsIDEuMDAwNiwgMS4wMDAxOSwgMS4wMDAzNCwgMSwgMC45OTkyNCwgMS4wMDAwMSwgMSwgMSwgMC45OTk3MywgMC45OTkyNCwgMC45OTk3MywgMC45OTkyNCwgMC45OTk3MywgMS4wMjU3MiwgMC45OTk3MywgMS4wMDAwNSwgMC45OTk3MywgMC45OTkyNCwgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk5OSwgMC45OTk4LCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLjAwMDIyLCAwLjk5OTczLCAxLCAxLjAwMDE2LCAwLjk5OTc3LCAwLjk5OTk4LCAwLjk5OTc3LCAwLjk5OTk4LCAwLjk5OTc3LCAwLjk5OTk4LCAxLjAwMDAxLCAxLCAxLjAwMDAxLCAxLCAxLjAwMDAxLCAxLCAxLjAwMDAxLCAxLCAxLjAwMDI2LCAxLjAwMDYsIDEuMDAwMjYsIDAuODQ1MzMsIDEuMDAwMjYsIDEuMDAwNiwgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMC45OTk3NywgMC45OTk3MywgMS4wMDAxNiwgMC45OTk3NywgMS4wMDAwMSwgMSwgMS4wMDAwMSwgMS4wMDAyNiwgMSwgMS4wMDAyNiwgMSwgMS4wMDAyNiwgMSwgMC45OTkyNCwgMC45OTk3MywgMS4wMDAwMSwgMC45OTk3MywgMSwgMC45OTk4MiwgMS4wMDAyMiwgMS4wMDAyNiwgMS4wMDAwMSwgMSwgMS4wMDAyNiwgMS4wMDA2LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTI4LCAxLCAwLjk5OTc3LCAxLjAwMDEzLCAxLjAwMDU1LCAwLjk5OTQ3LCAwLjk5OTQ1LCAwLjk5OTQxLCAwLjk5OTI0LCAxLjAwMDAxLCAxLjAwMDAxLCAxLjAwMDQsIDAuOTE2MjEsIDEuMDAwMDEsIDEuMDAwMjYsIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwNiwgMS4wMDAwMSwgMS4wMDAwNSwgMC45OTk5OSwgMC45OTk3NywgMS4wMDAxNSwgMS4wMDAyMiwgMC45OTk3NywgMS4wMDAwMSwgMC45OTk3MywgMS4wMDAyNiwgMS4wMDAwMSwgMS4wMDAxOSwgMS4wMDAwMSwgMC45OTk0NiwgMSwgMS4wMDA2LCAxLjAwMDAxLCAwLjk5OTc4LCAxLjAwMDQ1LCAwLjk5OTczLCAwLjk5OTI0LCAxLjAwMDIzLCAwLjk5OTc4LCAwLjk5OTY2LCAxLCAxLjAwMDY1LCAxLjAwMDQ1LCAxLjAwMDE5LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTI0LCAxLCAxLCAwLjk2NDk5LCAxLCAxLjAwMDU1LCAwLjk5OTczLCAxLjAwMDA4LCAxLjAwMDI3LCAxLCAwLjk5OTcsIDAuOTk5OTUsIDEuMDAwMjMsIDAuOTk5MzMsIDEuMDAwMTksIDEuMDAwMTUsIDEuMDAwMzEsIDAuOTk5MjQsIDEuMDAwMjMsIDAuOTk5NzMsIDEuMDAwMjMsIDEuMDAwMzEsIDEuMDAwMDEsIDAuOTk5MjgsIDEuMDAwMjksIDEuMDAwOTIsIDEuMDAwMzUsIDEuMDAwMDEsIDEuMDAwNiwgMS4wMDA2LCAxLCAwLjk5OTg4LCAwLjk5OTc1LCAxLCAxLjAwMDgyLCAwLjk5NTYxLCAwLjk5OTYsIDEuMDAwMzUsIDEuMDAwMDEsIDAuOTk5NjIsIDEuMDAwMDEsIDEuMDAwOTIsIDAuOTk5NjQsIDEuMDAwMDEsIDAuOTk5NjMsIDAuOTk5OTksIDEuMDAwMzUsIDEuMDAwMzUsIDEuMDAwODIsIDAuOTk5NjIsIDAuOTk5OTksIDAuOTk5NzcsIDEuMDAwMjIsIDEuMDAwMzUsIDEuMDAwMDEsIDAuOTk5NzcsIDEuMDAwMjYsIDAuOTk5NiwgMC45OTk2NywgMS4wMDAwMSwgMS4wMDAzNCwgMS4wMDA3NCwgMS4wMDA1NCwgMS4wMDA1MywgMS4wMDA2MywgMC45OTk3MSwgMC45OTk2MiwgMS4wMDAzNSwgMC45OTk3NSwgMC45OTk3NywgMC45OTk3MywgMS4wMDA0MywgMC45OTk1MywgMS4wMDA3LCAwLjk5OTE1LCAwLjk5OTczLCAxLjAwMDA4LCAwLjk5ODkyLCAxLjAwMDczLCAxLjAwMDczLCAxLjAwMTE0LCAwLjk5OTE1LCAxLjAwMDczLCAwLjk5OTU1LCAwLjk5OTczLCAxLjAwMDkyLCAwLjk5OTczLCAxLCAwLjk5OTk4LCAxLCAxLjAwMDMsIDEsIDEuMDAwNDMsIDEuMDAwMDEsIDAuOTk5NjksIDEuMDAwMywgMSwgMS4wMDAzNSwgMS4wMDAwMSwgMC45OTk1LCAxLCAxLjAwMDkyLCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDcsIDAuOTk5NSwgMSwgMC45OTkyNCwgMS4wMDA2LCAwLjk5OTI0LCAwLjk5OTcyLCAxLjAwMDYyLCAwLjk5OTczLCAxLjAwMTE0LCAxLjAwMDczLCAxLCAwLjk5OTU1LCAxLCAxLCAxLjAwMDQ3LCAwLjk5OTY4LCAxLjAwMDE2LCAwLjk5OTc3LCAxLjAwMDE2LCAwLjk5OTc3LCAxLjAwMDE2LCAwLjk5OTc3LCAxLjAwMDAxLCAxLCAxLCAxLCAwLjk5OTczLCAxLCAxLCAwLjk5OTU1LCAwLjk5OTI0LCAwLjk5OTI0LCAwLjk5OTI0LCAwLjk5OTI0LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTk4LCAwLjk5OTczLCAwLjk5OTczLCAwLjk5OTcyLCAxLCAxLCAxLjAwMjY3LCAwLjk5OTk5LCAwLjk5OTk4LCAwLjk5OTk4LCAxLCAwLjk5OTk4LCAxLjY2NDc1LCAxLCAwLjk5OTczLCAwLjk5OTczLCAxLjAwMDIzLCAwLjk5OTczLCAwLjk5OTcxLCAwLjk5OTI1LCAxLjAwMDIzLCAxLCAwLjk5OTkxLCAwLjk5OTg0LCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLjAwMDAyLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk2MzI5LCAxLCAxLjIwOTg1LCAxLjM5NzEzLCAxLjAwMDAzLCAwLjgyNTQsIDEuMDAwMTUsIDEsIDEuMDAwMzUsIDEuMDAwMjcsIDEuMDAwMzEsIDEuMDAwMzEsIDAuOTk5MTUsIDEuMDAwMzEsIDEuMDAwMzEsIDAuOTk5OTksIDEuMDAwMDMsIDAuOTk5OTksIDAuOTk5OTksIDEuNDExNDQsIDEuNiwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MTE0NCwgMS40MDU3OSwgMS40MDU3OSwgMS4zNjYyNSwgMC45OTk5OSwgMSwgMC45OTg2MSwgMC45OTg2MSwgMSwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMS4wMDAyNiwgMC45NTMxNywgMC45OTk5OSwgMC45OTk5OSwgMC45OTk5OSwgMC45OTk5OSwgMS40MDQ4MywgMSwgMC45OTk3NywgMS4wMDA1NCwgMSwgMSwgMC45OTk1MywgMC45OTk2MiwgMS4wMDA0MiwgMC45OTk1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKY29uc3QgSGVsdmV0aWNhUmVndWxhck1ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4yLAogIGxpbmVHYXA6IDAuMgp9OwoKOy8vIC4vc3JjL2NvcmUvbGliZXJhdGlvbnNhbnNfd2lkdGhzLmpzCmNvbnN0IExpYmVyYXRpb25TYW5zQm9sZFdpZHRocyA9IFszNjUsIDAsIDMzMywgMjc4LCAzMzMsIDQ3NCwgNTU2LCA1NTYsIDg4OSwgNzIyLCAyMzgsIDMzMywgMzMzLCAzODksIDU4NCwgMjc4LCAzMzMsIDI3OCwgMjc4LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDMzMywgMzMzLCA1ODQsIDU4NCwgNTg0LCA2MTEsIDk3NSwgNzIyLCA3MjIsIDcyMiwgNzIyLCA2NjcsIDYxMSwgNzc4LCA3MjIsIDI3OCwgNTU2LCA3MjIsIDYxMSwgODMzLCA3MjIsIDc3OCwgNjY3LCA3NzgsIDcyMiwgNjY3LCA2MTEsIDcyMiwgNjY3LCA5NDQsIDY2NywgNjY3LCA2MTEsIDMzMywgMjc4LCAzMzMsIDU4NCwgNTU2LCAzMzMsIDU1NiwgNjExLCA1NTYsIDYxMSwgNTU2LCAzMzMsIDYxMSwgNjExLCAyNzgsIDI3OCwgNTU2LCAyNzgsIDg4OSwgNjExLCA2MTEsIDYxMSwgNjExLCAzODksIDU1NiwgMzMzLCA2MTEsIDU1NiwgNzc4LCA1NTYsIDU1NiwgNTAwLCAzODksIDI4MCwgMzg5LCA1ODQsIDMzMywgNTU2LCA1NTYsIDU1NiwgNTU2LCAyODAsIDU1NiwgMzMzLCA3MzcsIDM3MCwgNTU2LCA1ODQsIDczNywgNTUyLCA0MDAsIDU0OSwgMzMzLCAzMzMsIDMzMywgNTc2LCA1NTYsIDI3OCwgMzMzLCAzMzMsIDM2NSwgNTU2LCA4MzQsIDgzNCwgODM0LCA2MTEsIDcyMiwgNzIyLCA3MjIsIDcyMiwgNzIyLCA3MjIsIDEwMDAsIDcyMiwgNjY3LCA2NjcsIDY2NywgNjY3LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDcyMiwgNzIyLCA3NzgsIDc3OCwgNzc4LCA3NzgsIDc3OCwgNTg0LCA3NzgsIDcyMiwgNzIyLCA3MjIsIDcyMiwgNjY3LCA2NjcsIDYxMSwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgODg5LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgMjc4LCAyNzgsIDI3OCwgMjc4LCA2MTEsIDYxMSwgNjExLCA2MTEsIDYxMSwgNjExLCA2MTEsIDU0OSwgNjExLCA2MTEsIDYxMSwgNjExLCA2MTEsIDU1NiwgNjExLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDcxOSwgNzIyLCA2MTEsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNzc4LCA2MTEsIDc3OCwgNjExLCA3NzgsIDYxMSwgNzc4LCA2MTEsIDcyMiwgNjExLCA3MjIsIDYxMSwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCA3ODUsIDU1NiwgNTU2LCAyNzgsIDcyMiwgNTU2LCA1NTYsIDYxMSwgMjc4LCA2MTEsIDI3OCwgNjExLCAzODUsIDYxMSwgNDc5LCA2MTEsIDI3OCwgNzIyLCA2MTEsIDcyMiwgNjExLCA3MjIsIDYxMSwgNzA4LCA3MjMsIDYxMSwgNzc4LCA2MTEsIDc3OCwgNjExLCA3NzgsIDYxMSwgMTAwMCwgOTQ0LCA3MjIsIDM4OSwgNzIyLCAzODksIDcyMiwgMzg5LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjExLCAzMzMsIDYxMSwgNDc5LCA2MTEsIDMzMywgNzIyLCA2MTEsIDcyMiwgNjExLCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCA3MjIsIDYxMSwgOTQ0LCA3NzgsIDY2NywgNTU2LCA2NjcsIDYxMSwgNTAwLCA2MTEsIDUwMCwgNjExLCA1MDAsIDI3OCwgNTU2LCA3MjIsIDU1NiwgMTAwMCwgODg5LCA3NzgsIDYxMSwgNjY3LCA1NTYsIDYxMSwgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDQ2NSwgNzIyLCAzMzMsIDg1MywgOTA2LCA0NzQsIDgyNSwgOTI3LCA4MzgsIDI3OCwgNzIyLCA3MjIsIDYwMSwgNzE5LCA2NjcsIDYxMSwgNzIyLCA3NzgsIDI3OCwgNzIyLCA2NjcsIDgzMywgNzIyLCA2NDQsIDc3OCwgNzIyLCA2NjcsIDYwMCwgNjExLCA2NjcsIDgyMSwgNjY3LCA4MDksIDgwMiwgMjc4LCA2NjcsIDYxNSwgNDUxLCA2MTEsIDI3OCwgNTgyLCA2MTUsIDYxMCwgNTU2LCA2MDYsIDQ3NSwgNDYwLCA2MTEsIDU0MSwgMjc4LCA1NTgsIDU1NiwgNjEyLCA1NTYsIDQ0NSwgNjExLCA3NjYsIDYxOSwgNTIwLCA2ODQsIDQ0NiwgNTgyLCA3MTUsIDU3NiwgNzUzLCA4NDUsIDI3OCwgNTgyLCA2MTEsIDU4MiwgODQ1LCA2NjcsIDY2OSwgODg1LCA1NjcsIDcxMSwgNjY3LCAyNzgsIDI3NiwgNTU2LCAxMDk0LCAxMDYyLCA4NzUsIDYxMCwgNzIyLCA2MjIsIDcxOSwgNzIyLCA3MTksIDcyMiwgNTY3LCA3MTIsIDY2NywgOTA0LCA2MjYsIDcxOSwgNzE5LCA2MTAsIDcwMiwgODMzLCA3MjIsIDc3OCwgNzE5LCA2NjcsIDcyMiwgNjExLCA2MjIsIDg1NCwgNjY3LCA3MzAsIDcwMywgMTAwNSwgMTAxOSwgODcwLCA5NzksIDcxOSwgNzExLCAxMDMxLCA3MTksIDU1NiwgNjE4LCA2MTUsIDQxNywgNjM1LCA1NTYsIDcwOSwgNDk3LCA2MTUsIDYxNSwgNTAwLCA2MzUsIDc0MCwgNjA0LCA2MTEsIDYwNCwgNjExLCA1NTYsIDQ5MCwgNTU2LCA4NzUsIDU1NiwgNjE1LCA1ODEsIDgzMywgODQ0LCA3MjksIDg1NCwgNjE1LCA1NTIsIDg1NCwgNTgzLCA1NTYsIDU1NiwgNjExLCA0MTcsIDU1MiwgNTU2LCAyNzgsIDI4MSwgMjc4LCA5NjksIDkwNiwgNjExLCA1MDAsIDYxNSwgNTU2LCA2MDQsIDc3OCwgNjExLCA0ODcsIDQ0NywgOTQ0LCA3NzgsIDk0NCwgNzc4LCA5NDQsIDc3OCwgNjY3LCA1NTYsIDMzMywgMzMzLCA1NTYsIDEwMDAsIDEwMDAsIDU1MiwgMjc4LCAyNzgsIDI3OCwgMjc4LCA1MDAsIDUwMCwgNTAwLCA1NTYsIDU1NiwgMzUwLCAxMDAwLCAxMDAwLCAyNDAsIDQ3OSwgMzMzLCAzMzMsIDYwNCwgMzMzLCAxNjcsIDM5NiwgNTU2LCA1NTYsIDEwOTQsIDU1NiwgODg1LCA0ODksIDExMTUsIDEwMDAsIDc2OCwgNjAwLCA4MzQsIDgzNCwgODM0LCA4MzQsIDEwMDAsIDUwMCwgMTAwMCwgNTAwLCAxMDAwLCA1MDAsIDUwMCwgNDk0LCA2MTIsIDgyMywgNzEzLCA1ODQsIDU0OSwgNzEzLCA5NzksIDcyMiwgMjc0LCA1NDksIDU0OSwgNTgzLCA1NDksIDU0OSwgNjA0LCA1ODQsIDYwNCwgNjA0LCA3MDgsIDYyNSwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzI5LCA2MDQsIDYwNCwgMzU0LCAzNTQsIDEwMDAsIDk5MCwgOTkwLCA5OTAsIDk5MCwgNDk0LCA2MDQsIDYwNCwgNjA0LCA2MDQsIDM1NCwgMTAyMSwgMTA1MiwgOTE3LCA3NTAsIDc1MCwgNTMxLCA2NTYsIDU5NCwgNTEwLCA1MDAsIDc1MCwgNzUwLCA2MTEsIDYxMSwgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDIyMiwgMjIyLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzM107CmNvbnN0IExpYmVyYXRpb25TYW5zQm9sZE1hcHBpbmcgPSBbLTEsIC0xLCAtMSwgMzIsIDMzLCAzNCwgMzUsIDM2LCAzNywgMzgsIDM5LCA0MCwgNDEsIDQyLCA0MywgNDQsIDQ1LCA0NiwgNDcsIDQ4LCA0OSwgNTAsIDUxLCA1MiwgNTMsIDU0LCA1NSwgNTYsIDU3LCA1OCwgNTksIDYwLCA2MSwgNjIsIDYzLCA2NCwgNjUsIDY2LCA2NywgNjgsIDY5LCA3MCwgNzEsIDcyLCA3MywgNzQsIDc1LCA3NiwgNzcsIDc4LCA3OSwgODAsIDgxLCA4MiwgODMsIDg0LCA4NSwgODYsIDg3LCA4OCwgODksIDkwLCA5MSwgOTIsIDkzLCA5NCwgOTUsIDk2LCA5NywgOTgsIDk5LCAxMDAsIDEwMSwgMTAyLCAxMDMsIDEwNCwgMTA1LCAxMDYsIDEwNywgMTA4LCAxMDksIDExMCwgMTExLCAxMTIsIDExMywgMTE0LCAxMTUsIDExNiwgMTE3LCAxMTgsIDExOSwgMTIwLCAxMjEsIDEyMiwgMTIzLCAxMjQsIDEyNSwgMTI2LCAxNjEsIDE2MiwgMTYzLCAxNjQsIDE2NSwgMTY2LCAxNjcsIDE2OCwgMTY5LCAxNzAsIDE3MSwgMTcyLCAxNzQsIDE3NSwgMTc2LCAxNzcsIDE3OCwgMTc5LCAxODAsIDE4MSwgMTgyLCAxODMsIDE4NCwgMTg1LCAxODYsIDE4NywgMTg4LCAxODksIDE5MCwgMTkxLCAxOTIsIDE5MywgMTk0LCAxOTUsIDE5NiwgMTk3LCAxOTgsIDE5OSwgMjAwLCAyMDEsIDIwMiwgMjAzLCAyMDQsIDIwNSwgMjA2LCAyMDcsIDIwOCwgMjA5LCAyMTAsIDIxMSwgMjEyLCAyMTMsIDIxNCwgMjE1LCAyMTYsIDIxNywgMjE4LCAyMTksIDIyMCwgMjIxLCAyMjIsIDIyMywgMjI0LCAyMjUsIDIyNiwgMjI3LCAyMjgsIDIyOSwgMjMwLCAyMzEsIDIzMiwgMjMzLCAyMzQsIDIzNSwgMjM2LCAyMzcsIDIzOCwgMjM5LCAyNDAsIDI0MSwgMjQyLCAyNDMsIDI0NCwgMjQ1LCAyNDYsIDI0NywgMjQ4LCAyNDksIDI1MCwgMjUxLCAyNTIsIDI1MywgMjU0LCAyNTUsIDI1NiwgMjU3LCAyNTgsIDI1OSwgMjYwLCAyNjEsIDI2MiwgMjYzLCAyNjQsIDI2NSwgMjY2LCAyNjcsIDI2OCwgMjY5LCAyNzAsIDI3MSwgMjcyLCAyNzMsIDI3NCwgMjc1LCAyNzYsIDI3NywgMjc4LCAyNzksIDI4MCwgMjgxLCAyODIsIDI4MywgMjg0LCAyODUsIDI4NiwgMjg3LCAyODgsIDI4OSwgMjkwLCAyOTEsIDI5MiwgMjkzLCAyOTQsIDI5NSwgMjk2LCAyOTcsIDI5OCwgMjk5LCAzMDAsIDMwMSwgMzAyLCAzMDMsIDMwNCwgMzA1LCAzMDYsIDMwNywgMzA4LCAzMDksIDMxMCwgMzExLCAzMTIsIDMxMywgMzE0LCAzMTUsIDMxNiwgMzE3LCAzMTgsIDMxOSwgMzIwLCAzMjEsIDMyMiwgMzIzLCAzMjQsIDMyNSwgMzI2LCAzMjcsIDMyOCwgMzI5LCAzMzAsIDMzMSwgMzMyLCAzMzMsIDMzNCwgMzM1LCAzMzYsIDMzNywgMzM4LCAzMzksIDM0MCwgMzQxLCAzNDIsIDM0MywgMzQ0LCAzNDUsIDM0NiwgMzQ3LCAzNDgsIDM0OSwgMzUwLCAzNTEsIDM1MiwgMzUzLCAzNTQsIDM1NSwgMzU2LCAzNTcsIDM1OCwgMzU5LCAzNjAsIDM2MSwgMzYyLCAzNjMsIDM2NCwgMzY1LCAzNjYsIDM2NywgMzY4LCAzNjksIDM3MCwgMzcxLCAzNzIsIDM3MywgMzc0LCAzNzUsIDM3NiwgMzc3LCAzNzgsIDM3OSwgMzgwLCAzODEsIDM4MiwgMzgzLCA0MDIsIDUwNiwgNTA3LCA1MDgsIDUwOSwgNTEwLCA1MTEsIDUzNiwgNTM3LCA1MzgsIDUzOSwgNzEwLCA3MTEsIDcxMywgNzI4LCA3MjksIDczMCwgNzMxLCA3MzIsIDczMywgOTAwLCA5MDEsIDkwMiwgOTAzLCA5MDQsIDkwNSwgOTA2LCA5MDgsIDkxMCwgOTExLCA5MTIsIDkxMywgOTE0LCA5MTUsIDkxNiwgOTE3LCA5MTgsIDkxOSwgOTIwLCA5MjEsIDkyMiwgOTIzLCA5MjQsIDkyNSwgOTI2LCA5MjcsIDkyOCwgOTI5LCA5MzEsIDkzMiwgOTMzLCA5MzQsIDkzNSwgOTM2LCA5MzcsIDkzOCwgOTM5LCA5NDAsIDk0MSwgOTQyLCA5NDMsIDk0NCwgOTQ1LCA5NDYsIDk0NywgOTQ4LCA5NDksIDk1MCwgOTUxLCA5NTIsIDk1MywgOTU0LCA5NTUsIDk1NiwgOTU3LCA5NTgsIDk1OSwgOTYwLCA5NjEsIDk2MiwgOTYzLCA5NjQsIDk2NSwgOTY2LCA5NjcsIDk2OCwgOTY5LCA5NzAsIDk3MSwgOTcyLCA5NzMsIDk3NCwgMTAyNCwgMTAyNSwgMTAyNiwgMTAyNywgMTAyOCwgMTAyOSwgMTAzMCwgMTAzMSwgMTAzMiwgMTAzMywgMTAzNCwgMTAzNSwgMTAzNiwgMTAzNywgMTAzOCwgMTAzOSwgMTA0MCwgMTA0MSwgMTA0MiwgMTA0MywgMTA0NCwgMTA0NSwgMTA0NiwgMTA0NywgMTA0OCwgMTA0OSwgMTA1MCwgMTA1MSwgMTA1MiwgMTA1MywgMTA1NCwgMTA1NSwgMTA1NiwgMTA1NywgMTA1OCwgMTA1OSwgMTA2MCwgMTA2MSwgMTA2MiwgMTA2MywgMTA2NCwgMTA2NSwgMTA2NiwgMTA2NywgMTA2OCwgMTA2OSwgMTA3MCwgMTA3MSwgMTA3MiwgMTA3MywgMTA3NCwgMTA3NSwgMTA3NiwgMTA3NywgMTA3OCwgMTA3OSwgMTA4MCwgMTA4MSwgMTA4MiwgMTA4MywgMTA4NCwgMTA4NSwgMTA4NiwgMTA4NywgMTA4OCwgMTA4OSwgMTA5MCwgMTA5MSwgMTA5MiwgMTA5MywgMTA5NCwgMTA5NSwgMTA5NiwgMTA5NywgMTA5OCwgMTA5OSwgMTEwMCwgMTEwMSwgMTEwMiwgMTEwMywgMTEwNCwgMTEwNSwgMTEwNiwgMTEwNywgMTEwOCwgMTEwOSwgMTExMCwgMTExMSwgMTExMiwgMTExMywgMTExNCwgMTExNSwgMTExNiwgMTExNywgMTExOCwgMTExOSwgMTEzOCwgMTEzOSwgMTE2OCwgMTE2OSwgNzgwOCwgNzgwOSwgNzgxMCwgNzgxMSwgNzgxMiwgNzgxMywgNzkyMiwgNzkyMywgODIwOCwgODIwOSwgODIxMSwgODIxMiwgODIxMywgODIxNSwgODIxNiwgODIxNywgODIxOCwgODIxOSwgODIyMCwgODIyMSwgODIyMiwgODIyNCwgODIyNSwgODIyNiwgODIzMCwgODI0MCwgODI0MiwgODI0MywgODI0OSwgODI1MCwgODI1MiwgODI1NCwgODI2MCwgODMxOSwgODM1NSwgODM1NiwgODM1OSwgODM2NCwgODQ1MywgODQ2NywgODQ3MCwgODQ4MiwgODQ4NiwgODQ5NCwgODUzOSwgODU0MCwgODU0MSwgODU0MiwgODU5MiwgODU5MywgODU5NCwgODU5NSwgODU5NiwgODU5NywgODYxNiwgODcwNiwgODcxMCwgODcxOSwgODcyMSwgODcyMiwgODczMCwgODczNCwgODczNSwgODc0NSwgODc0NywgODc3NiwgODgwMCwgODgwMSwgODgwNCwgODgwNSwgODk2MiwgODk3NiwgODk5MiwgODk5MywgOTQ3MiwgOTQ3NCwgOTQ4NCwgOTQ4OCwgOTQ5MiwgOTQ5NiwgOTUwMCwgOTUwOCwgOTUxNiwgOTUyNCwgOTUzMiwgOTU1MiwgOTU1MywgOTU1NCwgOTU1NSwgOTU1NiwgOTU1NywgOTU1OCwgOTU1OSwgOTU2MCwgOTU2MSwgOTU2MiwgOTU2MywgOTU2NCwgOTU2NSwgOTU2NiwgOTU2NywgOTU2OCwgOTU2OSwgOTU3MCwgOTU3MSwgOTU3MiwgOTU3MywgOTU3NCwgOTU3NSwgOTU3NiwgOTU3NywgOTU3OCwgOTU3OSwgOTU4MCwgOTYwMCwgOTYwNCwgOTYwOCwgOTYxMiwgOTYxNiwgOTYxNywgOTYxOCwgOTYxOSwgOTYzMiwgOTYzMywgOTY0MiwgOTY0MywgOTY0NCwgOTY1MCwgOTY1OCwgOTY2MCwgOTY2OCwgOTY3NCwgOTY3NSwgOTY3OSwgOTY4OCwgOTY4OSwgOTcwMiwgOTc4NiwgOTc4NywgOTc4OCwgOTc5MiwgOTc5NCwgOTgyNCwgOTgyNywgOTgyOSwgOTgzMCwgOTgzNCwgOTgzNSwgOTgzNiwgNjE0NDEsIDYxNDQyLCA2MTQ0NSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xXTsKY29uc3QgTGliZXJhdGlvblNhbnNCb2xkSXRhbGljV2lkdGhzID0gWzM2NSwgMCwgMzMzLCAyNzgsIDMzMywgNDc0LCA1NTYsIDU1NiwgODg5LCA3MjIsIDIzOCwgMzMzLCAzMzMsIDM4OSwgNTg0LCAyNzgsIDMzMywgMjc4LCAyNzgsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgMzMzLCAzMzMsIDU4NCwgNTg0LCA1ODQsIDYxMSwgOTc1LCA3MjIsIDcyMiwgNzIyLCA3MjIsIDY2NywgNjExLCA3NzgsIDcyMiwgMjc4LCA1NTYsIDcyMiwgNjExLCA4MzMsIDcyMiwgNzc4LCA2NjcsIDc3OCwgNzIyLCA2NjcsIDYxMSwgNzIyLCA2NjcsIDk0NCwgNjY3LCA2NjcsIDYxMSwgMzMzLCAyNzgsIDMzMywgNTg0LCA1NTYsIDMzMywgNTU2LCA2MTEsIDU1NiwgNjExLCA1NTYsIDMzMywgNjExLCA2MTEsIDI3OCwgMjc4LCA1NTYsIDI3OCwgODg5LCA2MTEsIDYxMSwgNjExLCA2MTEsIDM4OSwgNTU2LCAzMzMsIDYxMSwgNTU2LCA3NzgsIDU1NiwgNTU2LCA1MDAsIDM4OSwgMjgwLCAzODksIDU4NCwgMzMzLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDI4MCwgNTU2LCAzMzMsIDczNywgMzcwLCA1NTYsIDU4NCwgNzM3LCA1NTIsIDQwMCwgNTQ5LCAzMzMsIDMzMywgMzMzLCA1NzYsIDU1NiwgMjc4LCAzMzMsIDMzMywgMzY1LCA1NTYsIDgzNCwgODM0LCA4MzQsIDYxMSwgNzIyLCA3MjIsIDcyMiwgNzIyLCA3MjIsIDcyMiwgMTAwMCwgNzIyLCA2NjcsIDY2NywgNjY3LCA2NjcsIDI3OCwgMjc4LCAyNzgsIDI3OCwgNzIyLCA3MjIsIDc3OCwgNzc4LCA3NzgsIDc3OCwgNzc4LCA1ODQsIDc3OCwgNzIyLCA3MjIsIDcyMiwgNzIyLCA2NjcsIDY2NywgNjExLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA4ODksIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDYxMSwgNjExLCA2MTEsIDYxMSwgNjExLCA2MTEsIDYxMSwgNTQ5LCA2MTEsIDYxMSwgNjExLCA2MTEsIDYxMSwgNTU2LCA2MTEsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNzQwLCA3MjIsIDYxMSwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA3NzgsIDYxMSwgNzc4LCA2MTEsIDc3OCwgNjExLCA3NzgsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDc4MiwgNTU2LCA1NTYsIDI3OCwgNzIyLCA1NTYsIDU1NiwgNjExLCAyNzgsIDYxMSwgMjc4LCA2MTEsIDM5NiwgNjExLCA0NzksIDYxMSwgMjc4LCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCA3MDgsIDcyMywgNjExLCA3NzgsIDYxMSwgNzc4LCA2MTEsIDc3OCwgNjExLCAxMDAwLCA5NDQsIDcyMiwgMzg5LCA3MjIsIDM4OSwgNzIyLCAzODksIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA2MTEsIDMzMywgNjExLCA0NzksIDYxMSwgMzMzLCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCA3MjIsIDYxMSwgNzIyLCA2MTEsIDcyMiwgNjExLCA5NDQsIDc3OCwgNjY3LCA1NTYsIDY2NywgNjExLCA1MDAsIDYxMSwgNTAwLCA2MTEsIDUwMCwgMjc4LCA1NTYsIDcyMiwgNTU2LCAxMDAwLCA4ODksIDc3OCwgNjExLCA2NjcsIDU1NiwgNjExLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCA3MjIsIDMzMywgODU0LCA5MDYsIDQ3MywgODQ0LCA5MzAsIDg0NywgMjc4LCA3MjIsIDcyMiwgNjEwLCA2NzEsIDY2NywgNjExLCA3MjIsIDc3OCwgMjc4LCA3MjIsIDY2NywgODMzLCA3MjIsIDY1NywgNzc4LCA3MTgsIDY2NywgNTkwLCA2MTEsIDY2NywgODIyLCA2NjcsIDgyOSwgNzgxLCAyNzgsIDY2NywgNjIwLCA0NzksIDYxMSwgMjc4LCA1OTEsIDYyMCwgNjIxLCA1NTYsIDYxMCwgNDc5LCA0OTIsIDYxMSwgNTU4LCAyNzgsIDU2NiwgNTU2LCA2MDMsIDU1NiwgNDUwLCA2MTEsIDcxMiwgNjA1LCA1MzIsIDY2NCwgNDA5LCA1OTEsIDcwNCwgNTc4LCA3NzMsIDgzNCwgMjc4LCA1OTEsIDYxMSwgNTkxLCA4MzQsIDY2NywgNjY3LCA4ODYsIDYxNCwgNzE5LCA2NjcsIDI3OCwgMjc4LCA1NTYsIDEwOTQsIDEwNDIsIDg1NCwgNjIyLCA3MTksIDY3NywgNzE5LCA3MjIsIDcwOCwgNzIyLCA2MTQsIDcyMiwgNjY3LCA5MjcsIDY0MywgNzE5LCA3MTksIDYxNSwgNjg3LCA4MzMsIDcyMiwgNzc4LCA3MTksIDY2NywgNzIyLCA2MTEsIDY3NywgNzgxLCA2NjcsIDcyOSwgNzA4LCA5NzksIDk4OSwgODU0LCAxMDAwLCA3MDgsIDcxOSwgMTA0MiwgNzI5LCA1NTYsIDYxOSwgNjA0LCA1MzQsIDYxOCwgNTU2LCA3MzYsIDUxMCwgNjExLCA2MTEsIDUwNywgNjIyLCA3NDAsIDYwNCwgNjExLCA2MTEsIDYxMSwgNTU2LCA4ODksIDU1NiwgODg1LCA1NTYsIDY0NiwgNTgzLCA4ODksIDkzNSwgNzA3LCA4NTQsIDU5NCwgNTUyLCA4NjUsIDU4OSwgNTU2LCA1NTYsIDYxMSwgNDY5LCA1NjMsIDU1NiwgMjc4LCAyNzgsIDI3OCwgOTY5LCA5MDYsIDYxMSwgNTA3LCA2MTksIDU1NiwgNjExLCA3NzgsIDYxMSwgNTc1LCA0NjcsIDk0NCwgNzc4LCA5NDQsIDc3OCwgOTQ0LCA3NzgsIDY2NywgNTU2LCAzMzMsIDMzMywgNTU2LCAxMDAwLCAxMDAwLCA1NTIsIDI3OCwgMjc4LCAyNzgsIDI3OCwgNTAwLCA1MDAsIDUwMCwgNTU2LCA1NTYsIDM1MCwgMTAwMCwgMTAwMCwgMjQwLCA0NzksIDMzMywgMzMzLCA2MDQsIDMzMywgMTY3LCAzOTYsIDU1NiwgNTU2LCAxMTA0LCA1NTYsIDg4NSwgNTE2LCAxMTQ2LCAxMDAwLCA3NjgsIDYwMCwgODM0LCA4MzQsIDgzNCwgODM0LCA5OTksIDUwMCwgMTAwMCwgNTAwLCAxMDAwLCA1MDAsIDUwMCwgNDk0LCA2MTIsIDgyMywgNzEzLCA1ODQsIDU0OSwgNzEzLCA5NzksIDcyMiwgMjc0LCA1NDksIDU0OSwgNTgzLCA1NDksIDU0OSwgNjA0LCA1ODQsIDYwNCwgNjA0LCA3MDgsIDYyNSwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzI5LCA2MDQsIDYwNCwgMzU0LCAzNTQsIDEwMDAsIDk5MCwgOTkwLCA5OTAsIDk5MCwgNDk0LCA2MDQsIDYwNCwgNjA0LCA2MDQsIDM1NCwgMTAyMSwgMTA1MiwgOTE3LCA3NTAsIDc1MCwgNTMxLCA2NTYsIDU5NCwgNTEwLCA1MDAsIDc1MCwgNzUwLCA2MTEsIDYxMSwgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDIyMiwgMjIyLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzM107CmNvbnN0IExpYmVyYXRpb25TYW5zQm9sZEl0YWxpY01hcHBpbmcgPSBbLTEsIC0xLCAtMSwgMzIsIDMzLCAzNCwgMzUsIDM2LCAzNywgMzgsIDM5LCA0MCwgNDEsIDQyLCA0MywgNDQsIDQ1LCA0NiwgNDcsIDQ4LCA0OSwgNTAsIDUxLCA1MiwgNTMsIDU0LCA1NSwgNTYsIDU3LCA1OCwgNTksIDYwLCA2MSwgNjIsIDYzLCA2NCwgNjUsIDY2LCA2NywgNjgsIDY5LCA3MCwgNzEsIDcyLCA3MywgNzQsIDc1LCA3NiwgNzcsIDc4LCA3OSwgODAsIDgxLCA4MiwgODMsIDg0LCA4NSwgODYsIDg3LCA4OCwgODksIDkwLCA5MSwgOTIsIDkzLCA5NCwgOTUsIDk2LCA5NywgOTgsIDk5LCAxMDAsIDEwMSwgMTAyLCAxMDMsIDEwNCwgMTA1LCAxMDYsIDEwNywgMTA4LCAxMDksIDExMCwgMTExLCAxMTIsIDExMywgMTE0LCAxMTUsIDExNiwgMTE3LCAxMTgsIDExOSwgMTIwLCAxMjEsIDEyMiwgMTIzLCAxMjQsIDEyNSwgMTI2LCAxNjEsIDE2MiwgMTYzLCAxNjQsIDE2NSwgMTY2LCAxNjcsIDE2OCwgMTY5LCAxNzAsIDE3MSwgMTcyLCAxNzQsIDE3NSwgMTc2LCAxNzcsIDE3OCwgMTc5LCAxODAsIDE4MSwgMTgyLCAxODMsIDE4NCwgMTg1LCAxODYsIDE4NywgMTg4LCAxODksIDE5MCwgMTkxLCAxOTIsIDE5MywgMTk0LCAxOTUsIDE5NiwgMTk3LCAxOTgsIDE5OSwgMjAwLCAyMDEsIDIwMiwgMjAzLCAyMDQsIDIwNSwgMjA2LCAyMDcsIDIwOCwgMjA5LCAyMTAsIDIxMSwgMjEyLCAyMTMsIDIxNCwgMjE1LCAyMTYsIDIxNywgMjE4LCAyMTksIDIyMCwgMjIxLCAyMjIsIDIyMywgMjI0LCAyMjUsIDIyNiwgMjI3LCAyMjgsIDIyOSwgMjMwLCAyMzEsIDIzMiwgMjMzLCAyMzQsIDIzNSwgMjM2LCAyMzcsIDIzOCwgMjM5LCAyNDAsIDI0MSwgMjQyLCAyNDMsIDI0NCwgMjQ1LCAyNDYsIDI0NywgMjQ4LCAyNDksIDI1MCwgMjUxLCAyNTIsIDI1MywgMjU0LCAyNTUsIDI1NiwgMjU3LCAyNTgsIDI1OSwgMjYwLCAyNjEsIDI2MiwgMjYzLCAyNjQsIDI2NSwgMjY2LCAyNjcsIDI2OCwgMjY5LCAyNzAsIDI3MSwgMjcyLCAyNzMsIDI3NCwgMjc1LCAyNzYsIDI3NywgMjc4LCAyNzksIDI4MCwgMjgxLCAyODIsIDI4MywgMjg0LCAyODUsIDI4NiwgMjg3LCAyODgsIDI4OSwgMjkwLCAyOTEsIDI5MiwgMjkzLCAyOTQsIDI5NSwgMjk2LCAyOTcsIDI5OCwgMjk5LCAzMDAsIDMwMSwgMzAyLCAzMDMsIDMwNCwgMzA1LCAzMDYsIDMwNywgMzA4LCAzMDksIDMxMCwgMzExLCAzMTIsIDMxMywgMzE0LCAzMTUsIDMxNiwgMzE3LCAzMTgsIDMxOSwgMzIwLCAzMjEsIDMyMiwgMzIzLCAzMjQsIDMyNSwgMzI2LCAzMjcsIDMyOCwgMzI5LCAzMzAsIDMzMSwgMzMyLCAzMzMsIDMzNCwgMzM1LCAzMzYsIDMzNywgMzM4LCAzMzksIDM0MCwgMzQxLCAzNDIsIDM0MywgMzQ0LCAzNDUsIDM0NiwgMzQ3LCAzNDgsIDM0OSwgMzUwLCAzNTEsIDM1MiwgMzUzLCAzNTQsIDM1NSwgMzU2LCAzNTcsIDM1OCwgMzU5LCAzNjAsIDM2MSwgMzYyLCAzNjMsIDM2NCwgMzY1LCAzNjYsIDM2NywgMzY4LCAzNjksIDM3MCwgMzcxLCAzNzIsIDM3MywgMzc0LCAzNzUsIDM3NiwgMzc3LCAzNzgsIDM3OSwgMzgwLCAzODEsIDM4MiwgMzgzLCA0MDIsIDUwNiwgNTA3LCA1MDgsIDUwOSwgNTEwLCA1MTEsIDUzNiwgNTM3LCA1MzgsIDUzOSwgNzEwLCA3MTEsIDcxMywgNzI4LCA3MjksIDczMCwgNzMxLCA3MzIsIDczMywgOTAwLCA5MDEsIDkwMiwgOTAzLCA5MDQsIDkwNSwgOTA2LCA5MDgsIDkxMCwgOTExLCA5MTIsIDkxMywgOTE0LCA5MTUsIDkxNiwgOTE3LCA5MTgsIDkxOSwgOTIwLCA5MjEsIDkyMiwgOTIzLCA5MjQsIDkyNSwgOTI2LCA5MjcsIDkyOCwgOTI5LCA5MzEsIDkzMiwgOTMzLCA5MzQsIDkzNSwgOTM2LCA5MzcsIDkzOCwgOTM5LCA5NDAsIDk0MSwgOTQyLCA5NDMsIDk0NCwgOTQ1LCA5NDYsIDk0NywgOTQ4LCA5NDksIDk1MCwgOTUxLCA5NTIsIDk1MywgOTU0LCA5NTUsIDk1NiwgOTU3LCA5NTgsIDk1OSwgOTYwLCA5NjEsIDk2MiwgOTYzLCA5NjQsIDk2NSwgOTY2LCA5NjcsIDk2OCwgOTY5LCA5NzAsIDk3MSwgOTcyLCA5NzMsIDk3NCwgMTAyNCwgMTAyNSwgMTAyNiwgMTAyNywgMTAyOCwgMTAyOSwgMTAzMCwgMTAzMSwgMTAzMiwgMTAzMywgMTAzNCwgMTAzNSwgMTAzNiwgMTAzNywgMTAzOCwgMTAzOSwgMTA0MCwgMTA0MSwgMTA0MiwgMTA0MywgMTA0NCwgMTA0NSwgMTA0NiwgMTA0NywgMTA0OCwgMTA0OSwgMTA1MCwgMTA1MSwgMTA1MiwgMTA1MywgMTA1NCwgMTA1NSwgMTA1NiwgMTA1NywgMTA1OCwgMTA1OSwgMTA2MCwgMTA2MSwgMTA2MiwgMTA2MywgMTA2NCwgMTA2NSwgMTA2NiwgMTA2NywgMTA2OCwgMTA2OSwgMTA3MCwgMTA3MSwgMTA3MiwgMTA3MywgMTA3NCwgMTA3NSwgMTA3NiwgMTA3NywgMTA3OCwgMTA3OSwgMTA4MCwgMTA4MSwgMTA4MiwgMTA4MywgMTA4NCwgMTA4NSwgMTA4NiwgMTA4NywgMTA4OCwgMTA4OSwgMTA5MCwgMTA5MSwgMTA5MiwgMTA5MywgMTA5NCwgMTA5NSwgMTA5NiwgMTA5NywgMTA5OCwgMTA5OSwgMTEwMCwgMTEwMSwgMTEwMiwgMTEwMywgMTEwNCwgMTEwNSwgMTEwNiwgMTEwNywgMTEwOCwgMTEwOSwgMTExMCwgMTExMSwgMTExMiwgMTExMywgMTExNCwgMTExNSwgMTExNiwgMTExNywgMTExOCwgMTExOSwgMTEzOCwgMTEzOSwgMTE2OCwgMTE2OSwgNzgwOCwgNzgwOSwgNzgxMCwgNzgxMSwgNzgxMiwgNzgxMywgNzkyMiwgNzkyMywgODIwOCwgODIwOSwgODIxMSwgODIxMiwgODIxMywgODIxNSwgODIxNiwgODIxNywgODIxOCwgODIxOSwgODIyMCwgODIyMSwgODIyMiwgODIyNCwgODIyNSwgODIyNiwgODIzMCwgODI0MCwgODI0MiwgODI0MywgODI0OSwgODI1MCwgODI1MiwgODI1NCwgODI2MCwgODMxOSwgODM1NSwgODM1NiwgODM1OSwgODM2NCwgODQ1MywgODQ2NywgODQ3MCwgODQ4MiwgODQ4NiwgODQ5NCwgODUzOSwgODU0MCwgODU0MSwgODU0MiwgODU5MiwgODU5MywgODU5NCwgODU5NSwgODU5NiwgODU5NywgODYxNiwgODcwNiwgODcxMCwgODcxOSwgODcyMSwgODcyMiwgODczMCwgODczNCwgODczNSwgODc0NSwgODc0NywgODc3NiwgODgwMCwgODgwMSwgODgwNCwgODgwNSwgODk2MiwgODk3NiwgODk5MiwgODk5MywgOTQ3MiwgOTQ3NCwgOTQ4NCwgOTQ4OCwgOTQ5MiwgOTQ5NiwgOTUwMCwgOTUwOCwgOTUxNiwgOTUyNCwgOTUzMiwgOTU1MiwgOTU1MywgOTU1NCwgOTU1NSwgOTU1NiwgOTU1NywgOTU1OCwgOTU1OSwgOTU2MCwgOTU2MSwgOTU2MiwgOTU2MywgOTU2NCwgOTU2NSwgOTU2NiwgOTU2NywgOTU2OCwgOTU2OSwgOTU3MCwgOTU3MSwgOTU3MiwgOTU3MywgOTU3NCwgOTU3NSwgOTU3NiwgOTU3NywgOTU3OCwgOTU3OSwgOTU4MCwgOTYwMCwgOTYwNCwgOTYwOCwgOTYxMiwgOTYxNiwgOTYxNywgOTYxOCwgOTYxOSwgOTYzMiwgOTYzMywgOTY0MiwgOTY0MywgOTY0NCwgOTY1MCwgOTY1OCwgOTY2MCwgOTY2OCwgOTY3NCwgOTY3NSwgOTY3OSwgOTY4OCwgOTY4OSwgOTcwMiwgOTc4NiwgOTc4NywgOTc4OCwgOTc5MiwgOTc5NCwgOTgyNCwgOTgyNywgOTgyOSwgOTgzMCwgOTgzNCwgOTgzNSwgOTgzNiwgNjE0NDEsIDYxNDQyLCA2MTQ0NSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xXTsKY29uc3QgTGliZXJhdGlvblNhbnNJdGFsaWNXaWR0aHMgPSBbMzY1LCAwLCAzMzMsIDI3OCwgMjc4LCAzNTUsIDU1NiwgNTU2LCA4ODksIDY2NywgMTkxLCAzMzMsIDMzMywgMzg5LCA1ODQsIDI3OCwgMzMzLCAyNzgsIDI3OCwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCAyNzgsIDI3OCwgNTg0LCA1ODQsIDU4NCwgNTU2LCAxMDE1LCA2NjcsIDY2NywgNzIyLCA3MjIsIDY2NywgNjExLCA3NzgsIDcyMiwgMjc4LCA1MDAsIDY2NywgNTU2LCA4MzMsIDcyMiwgNzc4LCA2NjcsIDc3OCwgNzIyLCA2NjcsIDYxMSwgNzIyLCA2NjcsIDk0NCwgNjY3LCA2NjcsIDYxMSwgMjc4LCAyNzgsIDI3OCwgNDY5LCA1NTYsIDMzMywgNTU2LCA1NTYsIDUwMCwgNTU2LCA1NTYsIDI3OCwgNTU2LCA1NTYsIDIyMiwgMjIyLCA1MDAsIDIyMiwgODMzLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDMzMywgNTAwLCAyNzgsIDU1NiwgNTAwLCA3MjIsIDUwMCwgNTAwLCA1MDAsIDMzNCwgMjYwLCAzMzQsIDU4NCwgMzMzLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDI2MCwgNTU2LCAzMzMsIDczNywgMzcwLCA1NTYsIDU4NCwgNzM3LCA1NTIsIDQwMCwgNTQ5LCAzMzMsIDMzMywgMzMzLCA1NzYsIDUzNywgMjc4LCAzMzMsIDMzMywgMzY1LCA1NTYsIDgzNCwgODM0LCA4MzQsIDYxMSwgNjY3LCA2NjcsIDY2NywgNjY3LCA2NjcsIDY2NywgMTAwMCwgNzIyLCA2NjcsIDY2NywgNjY3LCA2NjcsIDI3OCwgMjc4LCAyNzgsIDI3OCwgNzIyLCA3MjIsIDc3OCwgNzc4LCA3NzgsIDc3OCwgNzc4LCA1ODQsIDc3OCwgNzIyLCA3MjIsIDcyMiwgNzIyLCA2NjcsIDY2NywgNjExLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA4ODksIDUwMCwgNTU2LCA1NTYsIDU1NiwgNTU2LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTQ5LCA2MTEsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTAwLCA1NTYsIDUwMCwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNzIyLCA1MDAsIDcyMiwgNTAwLCA3MjIsIDUwMCwgNzIyLCA1MDAsIDcyMiwgNjI1LCA3MjIsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA3NzgsIDU1NiwgNzc4LCA1NTYsIDc3OCwgNTU2LCA3NzgsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDIyMiwgMjc4LCAyNzgsIDczMywgNDQ0LCA1MDAsIDIyMiwgNjY3LCA1MDAsIDUwMCwgNTU2LCAyMjIsIDU1NiwgMjIyLCA1NTYsIDI4MSwgNTU2LCA0MDAsIDU1NiwgMjIyLCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA2MTUsIDcyMywgNTU2LCA3NzgsIDU1NiwgNzc4LCA1NTYsIDc3OCwgNTU2LCAxMDAwLCA5NDQsIDcyMiwgMzMzLCA3MjIsIDMzMywgNzIyLCAzMzMsIDY2NywgNTAwLCA2NjcsIDUwMCwgNjY3LCA1MDAsIDY2NywgNTAwLCA2MTEsIDI3OCwgNjExLCAzNTQsIDYxMSwgMjc4LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA5NDQsIDcyMiwgNjY3LCA1MDAsIDY2NywgNjExLCA1MDAsIDYxMSwgNTAwLCA2MTEsIDUwMCwgMjIyLCA1NTYsIDY2NywgNTU2LCAxMDAwLCA4ODksIDc3OCwgNjExLCA2NjcsIDUwMCwgNjExLCAyNzgsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCA2NjcsIDI3OCwgNzg5LCA4NDYsIDM4OSwgNzk0LCA4NjUsIDc3NSwgMjIyLCA2NjcsIDY2NywgNTcwLCA2NzEsIDY2NywgNjExLCA3MjIsIDc3OCwgMjc4LCA2NjcsIDY2NywgODMzLCA3MjIsIDY0OCwgNzc4LCA3MjUsIDY2NywgNjAwLCA2MTEsIDY2NywgODM3LCA2NjcsIDgzMSwgNzYxLCAyNzgsIDY2NywgNTcwLCA0MzksIDU1NSwgMjIyLCA1NTAsIDU3MCwgNTcxLCA1MDAsIDU1NiwgNDM5LCA0NjMsIDU1NSwgNTQyLCAyMjIsIDUwMCwgNDkyLCA1NDgsIDUwMCwgNDQ3LCA1NTYsIDY3MCwgNTczLCA0ODYsIDYwMywgMzc0LCA1NTAsIDY1MiwgNTQ2LCA3MjgsIDc3OSwgMjIyLCA1NTAsIDU1NiwgNTUwLCA3NzksIDY2NywgNjY3LCA4NDMsIDU0NCwgNzA4LCA2NjcsIDI3OCwgMjc4LCA1MDAsIDEwNjYsIDk4MiwgODQ0LCA1ODksIDcxNSwgNjM5LCA3MjQsIDY2NywgNjUxLCA2NjcsIDU0NCwgNzA0LCA2NjcsIDkxNywgNjE0LCA3MTUsIDcxNSwgNTg5LCA2ODYsIDgzMywgNzIyLCA3NzgsIDcyNSwgNjY3LCA3MjIsIDYxMSwgNjM5LCA3OTUsIDY2NywgNzI3LCA2NzMsIDkyMCwgOTIzLCA4MDUsIDg4NiwgNjUxLCA2OTQsIDEwMjIsIDY4MiwgNTU2LCA1NjIsIDUyMiwgNDkzLCA1NTMsIDU1NiwgNjg4LCA0NjUsIDU1NiwgNTU2LCA0NzIsIDU2NCwgNjg2LCA1NTAsIDU1NiwgNTU2LCA1NTYsIDUwMCwgODMzLCA1MDAsIDgzNSwgNTAwLCA1NzIsIDUxOCwgODMwLCA4NTEsIDYyMSwgNzM2LCA1MjYsIDQ5MiwgNzUyLCA1MzQsIDU1NiwgNTU2LCA1NTYsIDM3OCwgNDk2LCA1MDAsIDIyMiwgMjIyLCAyMjIsIDkxMCwgODI4LCA1NTYsIDQ3MiwgNTY1LCA1MDAsIDU1NiwgNzc4LCA1NTYsIDQ5MiwgMzM5LCA5NDQsIDcyMiwgOTQ0LCA3MjIsIDk0NCwgNzIyLCA2NjcsIDUwMCwgMzMzLCAzMzMsIDU1NiwgMTAwMCwgMTAwMCwgNTUyLCAyMjIsIDIyMiwgMjIyLCAyMjIsIDMzMywgMzMzLCAzMzMsIDU1NiwgNTU2LCAzNTAsIDEwMDAsIDEwMDAsIDE4OCwgMzU0LCAzMzMsIDMzMywgNTAwLCAzMzMsIDE2NywgMzY1LCA1NTYsIDU1NiwgMTA5NCwgNTU2LCA4ODUsIDMyMywgMTA4MywgMTAwMCwgNzY4LCA2MDAsIDgzNCwgODM0LCA4MzQsIDgzNCwgMTAwMCwgNTAwLCA5OTgsIDUwMCwgMTAwMCwgNTAwLCA1MDAsIDQ5NCwgNjEyLCA4MjMsIDcxMywgNTg0LCA1NDksIDcxMywgOTc5LCA3MTksIDI3NCwgNTQ5LCA1NDksIDU4NCwgNTQ5LCA1NDksIDYwNCwgNTg0LCA2MDQsIDYwNCwgNzA4LCA2MjUsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcyOSwgNjA0LCA2MDQsIDM1NCwgMzU0LCAxMDAwLCA5OTAsIDk5MCwgOTkwLCA5OTAsIDQ5NCwgNjA0LCA2MDQsIDYwNCwgNjA0LCAzNTQsIDEwMjEsIDEwNTIsIDkxNywgNzUwLCA3NTAsIDUzMSwgNjU2LCA1OTQsIDUxMCwgNTAwLCA3NTAsIDc1MCwgNTAwLCA1MDAsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAyMjIsIDIyMiwgMjk0LCAyOTQsIDMyNCwgMzI0LCAzMTYsIDMyOCwgMzk4LCAyODVdOwpjb25zdCBMaWJlcmF0aW9uU2Fuc0l0YWxpY01hcHBpbmcgPSBbLTEsIC0xLCAtMSwgMzIsIDMzLCAzNCwgMzUsIDM2LCAzNywgMzgsIDM5LCA0MCwgNDEsIDQyLCA0MywgNDQsIDQ1LCA0NiwgNDcsIDQ4LCA0OSwgNTAsIDUxLCA1MiwgNTMsIDU0LCA1NSwgNTYsIDU3LCA1OCwgNTksIDYwLCA2MSwgNjIsIDYzLCA2NCwgNjUsIDY2LCA2NywgNjgsIDY5LCA3MCwgNzEsIDcyLCA3MywgNzQsIDc1LCA3NiwgNzcsIDc4LCA3OSwgODAsIDgxLCA4MiwgODMsIDg0LCA4NSwgODYsIDg3LCA4OCwgODksIDkwLCA5MSwgOTIsIDkzLCA5NCwgOTUsIDk2LCA5NywgOTgsIDk5LCAxMDAsIDEwMSwgMTAyLCAxMDMsIDEwNCwgMTA1LCAxMDYsIDEwNywgMTA4LCAxMDksIDExMCwgMTExLCAxMTIsIDExMywgMTE0LCAxMTUsIDExNiwgMTE3LCAxMTgsIDExOSwgMTIwLCAxMjEsIDEyMiwgMTIzLCAxMjQsIDEyNSwgMTI2LCAxNjEsIDE2MiwgMTYzLCAxNjQsIDE2NSwgMTY2LCAxNjcsIDE2OCwgMTY5LCAxNzAsIDE3MSwgMTcyLCAxNzQsIDE3NSwgMTc2LCAxNzcsIDE3OCwgMTc5LCAxODAsIDE4MSwgMTgyLCAxODMsIDE4NCwgMTg1LCAxODYsIDE4NywgMTg4LCAxODksIDE5MCwgMTkxLCAxOTIsIDE5MywgMTk0LCAxOTUsIDE5NiwgMTk3LCAxOTgsIDE5OSwgMjAwLCAyMDEsIDIwMiwgMjAzLCAyMDQsIDIwNSwgMjA2LCAyMDcsIDIwOCwgMjA5LCAyMTAsIDIxMSwgMjEyLCAyMTMsIDIxNCwgMjE1LCAyMTYsIDIxNywgMjE4LCAyMTksIDIyMCwgMjIxLCAyMjIsIDIyMywgMjI0LCAyMjUsIDIyNiwgMjI3LCAyMjgsIDIyOSwgMjMwLCAyMzEsIDIzMiwgMjMzLCAyMzQsIDIzNSwgMjM2LCAyMzcsIDIzOCwgMjM5LCAyNDAsIDI0MSwgMjQyLCAyNDMsIDI0NCwgMjQ1LCAyNDYsIDI0NywgMjQ4LCAyNDksIDI1MCwgMjUxLCAyNTIsIDI1MywgMjU0LCAyNTUsIDI1NiwgMjU3LCAyNTgsIDI1OSwgMjYwLCAyNjEsIDI2MiwgMjYzLCAyNjQsIDI2NSwgMjY2LCAyNjcsIDI2OCwgMjY5LCAyNzAsIDI3MSwgMjcyLCAyNzMsIDI3NCwgMjc1LCAyNzYsIDI3NywgMjc4LCAyNzksIDI4MCwgMjgxLCAyODIsIDI4MywgMjg0LCAyODUsIDI4NiwgMjg3LCAyODgsIDI4OSwgMjkwLCAyOTEsIDI5MiwgMjkzLCAyOTQsIDI5NSwgMjk2LCAyOTcsIDI5OCwgMjk5LCAzMDAsIDMwMSwgMzAyLCAzMDMsIDMwNCwgMzA1LCAzMDYsIDMwNywgMzA4LCAzMDksIDMxMCwgMzExLCAzMTIsIDMxMywgMzE0LCAzMTUsIDMxNiwgMzE3LCAzMTgsIDMxOSwgMzIwLCAzMjEsIDMyMiwgMzIzLCAzMjQsIDMyNSwgMzI2LCAzMjcsIDMyOCwgMzI5LCAzMzAsIDMzMSwgMzMyLCAzMzMsIDMzNCwgMzM1LCAzMzYsIDMzNywgMzM4LCAzMzksIDM0MCwgMzQxLCAzNDIsIDM0MywgMzQ0LCAzNDUsIDM0NiwgMzQ3LCAzNDgsIDM0OSwgMzUwLCAzNTEsIDM1MiwgMzUzLCAzNTQsIDM1NSwgMzU2LCAzNTcsIDM1OCwgMzU5LCAzNjAsIDM2MSwgMzYyLCAzNjMsIDM2NCwgMzY1LCAzNjYsIDM2NywgMzY4LCAzNjksIDM3MCwgMzcxLCAzNzIsIDM3MywgMzc0LCAzNzUsIDM3NiwgMzc3LCAzNzgsIDM3OSwgMzgwLCAzODEsIDM4MiwgMzgzLCA0MDIsIDUwNiwgNTA3LCA1MDgsIDUwOSwgNTEwLCA1MTEsIDUzNiwgNTM3LCA1MzgsIDUzOSwgNzEwLCA3MTEsIDcxMywgNzI4LCA3MjksIDczMCwgNzMxLCA3MzIsIDczMywgOTAwLCA5MDEsIDkwMiwgOTAzLCA5MDQsIDkwNSwgOTA2LCA5MDgsIDkxMCwgOTExLCA5MTIsIDkxMywgOTE0LCA5MTUsIDkxNiwgOTE3LCA5MTgsIDkxOSwgOTIwLCA5MjEsIDkyMiwgOTIzLCA5MjQsIDkyNSwgOTI2LCA5MjcsIDkyOCwgOTI5LCA5MzEsIDkzMiwgOTMzLCA5MzQsIDkzNSwgOTM2LCA5MzcsIDkzOCwgOTM5LCA5NDAsIDk0MSwgOTQyLCA5NDMsIDk0NCwgOTQ1LCA5NDYsIDk0NywgOTQ4LCA5NDksIDk1MCwgOTUxLCA5NTIsIDk1MywgOTU0LCA5NTUsIDk1NiwgOTU3LCA5NTgsIDk1OSwgOTYwLCA5NjEsIDk2MiwgOTYzLCA5NjQsIDk2NSwgOTY2LCA5NjcsIDk2OCwgOTY5LCA5NzAsIDk3MSwgOTcyLCA5NzMsIDk3NCwgMTAyNCwgMTAyNSwgMTAyNiwgMTAyNywgMTAyOCwgMTAyOSwgMTAzMCwgMTAzMSwgMTAzMiwgMTAzMywgMTAzNCwgMTAzNSwgMTAzNiwgMTAzNywgMTAzOCwgMTAzOSwgMTA0MCwgMTA0MSwgMTA0MiwgMTA0MywgMTA0NCwgMTA0NSwgMTA0NiwgMTA0NywgMTA0OCwgMTA0OSwgMTA1MCwgMTA1MSwgMTA1MiwgMTA1MywgMTA1NCwgMTA1NSwgMTA1NiwgMTA1NywgMTA1OCwgMTA1OSwgMTA2MCwgMTA2MSwgMTA2MiwgMTA2MywgMTA2NCwgMTA2NSwgMTA2NiwgMTA2NywgMTA2OCwgMTA2OSwgMTA3MCwgMTA3MSwgMTA3MiwgMTA3MywgMTA3NCwgMTA3NSwgMTA3NiwgMTA3NywgMTA3OCwgMTA3OSwgMTA4MCwgMTA4MSwgMTA4MiwgMTA4MywgMTA4NCwgMTA4NSwgMTA4NiwgMTA4NywgMTA4OCwgMTA4OSwgMTA5MCwgMTA5MSwgMTA5MiwgMTA5MywgMTA5NCwgMTA5NSwgMTA5NiwgMTA5NywgMTA5OCwgMTA5OSwgMTEwMCwgMTEwMSwgMTEwMiwgMTEwMywgMTEwNCwgMTEwNSwgMTEwNiwgMTEwNywgMTEwOCwgMTEwOSwgMTExMCwgMTExMSwgMTExMiwgMTExMywgMTExNCwgMTExNSwgMTExNiwgMTExNywgMTExOCwgMTExOSwgMTEzOCwgMTEzOSwgMTE2OCwgMTE2OSwgNzgwOCwgNzgwOSwgNzgxMCwgNzgxMSwgNzgxMiwgNzgxMywgNzkyMiwgNzkyMywgODIwOCwgODIwOSwgODIxMSwgODIxMiwgODIxMywgODIxNSwgODIxNiwgODIxNywgODIxOCwgODIxOSwgODIyMCwgODIyMSwgODIyMiwgODIyNCwgODIyNSwgODIyNiwgODIzMCwgODI0MCwgODI0MiwgODI0MywgODI0OSwgODI1MCwgODI1MiwgODI1NCwgODI2MCwgODMxOSwgODM1NSwgODM1NiwgODM1OSwgODM2NCwgODQ1MywgODQ2NywgODQ3MCwgODQ4MiwgODQ4NiwgODQ5NCwgODUzOSwgODU0MCwgODU0MSwgODU0MiwgODU5MiwgODU5MywgODU5NCwgODU5NSwgODU5NiwgODU5NywgODYxNiwgODcwNiwgODcxMCwgODcxOSwgODcyMSwgODcyMiwgODczMCwgODczNCwgODczNSwgODc0NSwgODc0NywgODc3NiwgODgwMCwgODgwMSwgODgwNCwgODgwNSwgODk2MiwgODk3NiwgODk5MiwgODk5MywgOTQ3MiwgOTQ3NCwgOTQ4NCwgOTQ4OCwgOTQ5MiwgOTQ5NiwgOTUwMCwgOTUwOCwgOTUxNiwgOTUyNCwgOTUzMiwgOTU1MiwgOTU1MywgOTU1NCwgOTU1NSwgOTU1NiwgOTU1NywgOTU1OCwgOTU1OSwgOTU2MCwgOTU2MSwgOTU2MiwgOTU2MywgOTU2NCwgOTU2NSwgOTU2NiwgOTU2NywgOTU2OCwgOTU2OSwgOTU3MCwgOTU3MSwgOTU3MiwgOTU3MywgOTU3NCwgOTU3NSwgOTU3NiwgOTU3NywgOTU3OCwgOTU3OSwgOTU4MCwgOTYwMCwgOTYwNCwgOTYwOCwgOTYxMiwgOTYxNiwgOTYxNywgOTYxOCwgOTYxOSwgOTYzMiwgOTYzMywgOTY0MiwgOTY0MywgOTY0NCwgOTY1MCwgOTY1OCwgOTY2MCwgOTY2OCwgOTY3NCwgOTY3NSwgOTY3OSwgOTY4OCwgOTY4OSwgOTcwMiwgOTc4NiwgOTc4NywgOTc4OCwgOTc5MiwgOTc5NCwgOTgyNCwgOTgyNywgOTgyOSwgOTgzMCwgOTgzNCwgOTgzNSwgOTgzNiwgNjE0NDEsIDYxNDQyLCA2MTQ0NSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xXTsKY29uc3QgTGliZXJhdGlvblNhbnNSZWd1bGFyV2lkdGhzID0gWzM2NSwgMCwgMzMzLCAyNzgsIDI3OCwgMzU1LCA1NTYsIDU1NiwgODg5LCA2NjcsIDE5MSwgMzMzLCAzMzMsIDM4OSwgNTg0LCAyNzgsIDMzMywgMjc4LCAyNzgsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgMjc4LCAyNzgsIDU4NCwgNTg0LCA1ODQsIDU1NiwgMTAxNSwgNjY3LCA2NjcsIDcyMiwgNzIyLCA2NjcsIDYxMSwgNzc4LCA3MjIsIDI3OCwgNTAwLCA2NjcsIDU1NiwgODMzLCA3MjIsIDc3OCwgNjY3LCA3NzgsIDcyMiwgNjY3LCA2MTEsIDcyMiwgNjY3LCA5NDQsIDY2NywgNjY3LCA2MTEsIDI3OCwgMjc4LCAyNzgsIDQ2OSwgNTU2LCAzMzMsIDU1NiwgNTU2LCA1MDAsIDU1NiwgNTU2LCAyNzgsIDU1NiwgNTU2LCAyMjIsIDIyMiwgNTAwLCAyMjIsIDgzMywgNTU2LCA1NTYsIDU1NiwgNTU2LCAzMzMsIDUwMCwgMjc4LCA1NTYsIDUwMCwgNzIyLCA1MDAsIDUwMCwgNTAwLCAzMzQsIDI2MCwgMzM0LCA1ODQsIDMzMywgNTU2LCA1NTYsIDU1NiwgNTU2LCAyNjAsIDU1NiwgMzMzLCA3MzcsIDM3MCwgNTU2LCA1ODQsIDczNywgNTUyLCA0MDAsIDU0OSwgMzMzLCAzMzMsIDMzMywgNTc2LCA1MzcsIDI3OCwgMzMzLCAzMzMsIDM2NSwgNTU2LCA4MzQsIDgzNCwgODM0LCA2MTEsIDY2NywgNjY3LCA2NjcsIDY2NywgNjY3LCA2NjcsIDEwMDAsIDcyMiwgNjY3LCA2NjcsIDY2NywgNjY3LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDcyMiwgNzIyLCA3NzgsIDc3OCwgNzc4LCA3NzgsIDc3OCwgNTg0LCA3NzgsIDcyMiwgNzIyLCA3MjIsIDcyMiwgNjY3LCA2NjcsIDYxMSwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgODg5LCA1MDAsIDU1NiwgNTU2LCA1NTYsIDU1NiwgMjc4LCAyNzgsIDI3OCwgMjc4LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU1NiwgNTU2LCA1NTYsIDU0OSwgNjExLCA1NTYsIDU1NiwgNTU2LCA1NTYsIDUwMCwgNTU2LCA1MDAsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDcyMiwgNTAwLCA3MjIsIDUwMCwgNzIyLCA1MDAsIDcyMiwgNTAwLCA3MjIsIDYxNSwgNzIyLCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNjY3LCA1NTYsIDY2NywgNTU2LCA2NjcsIDU1NiwgNzc4LCA1NTYsIDc3OCwgNTU2LCA3NzgsIDU1NiwgNzc4LCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyNzgsIDI3OCwgMjc4LCAyMjIsIDI3OCwgMjc4LCA3MzUsIDQ0NCwgNTAwLCAyMjIsIDY2NywgNTAwLCA1MDAsIDU1NiwgMjIyLCA1NTYsIDIyMiwgNTU2LCAyOTIsIDU1NiwgMzM0LCA1NTYsIDIyMiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNjA0LCA3MjMsIDU1NiwgNzc4LCA1NTYsIDc3OCwgNTU2LCA3NzgsIDU1NiwgMTAwMCwgOTQ0LCA3MjIsIDMzMywgNzIyLCAzMzMsIDcyMiwgMzMzLCA2NjcsIDUwMCwgNjY3LCA1MDAsIDY2NywgNTAwLCA2NjcsIDUwMCwgNjExLCAyNzgsIDYxMSwgMzc1LCA2MTEsIDI3OCwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgNzIyLCA1NTYsIDcyMiwgNTU2LCA3MjIsIDU1NiwgOTQ0LCA3MjIsIDY2NywgNTAwLCA2NjcsIDYxMSwgNTAwLCA2MTEsIDUwMCwgNjExLCA1MDAsIDIyMiwgNTU2LCA2NjcsIDU1NiwgMTAwMCwgODg5LCA3NzgsIDYxMSwgNjY3LCA1MDAsIDYxMSwgMjc4LCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgNjY3LCAyNzgsIDc4NCwgODM4LCAzODQsIDc3NCwgODU1LCA3NTIsIDIyMiwgNjY3LCA2NjcsIDU1MSwgNjY4LCA2NjcsIDYxMSwgNzIyLCA3NzgsIDI3OCwgNjY3LCA2NjgsIDgzMywgNzIyLCA2NTAsIDc3OCwgNzIyLCA2NjcsIDYxOCwgNjExLCA2NjcsIDc5OCwgNjY3LCA4MzUsIDc0OCwgMjc4LCA2NjcsIDU3OCwgNDQ2LCA1NTYsIDIyMiwgNTQ3LCA1NzgsIDU3NSwgNTAwLCA1NTcsIDQ0NiwgNDQxLCA1NTYsIDU1NiwgMjIyLCA1MDAsIDUwMCwgNTc2LCA1MDAsIDQ0OCwgNTU2LCA2OTAsIDU2OSwgNDgyLCA2MTcsIDM5NSwgNTQ3LCA2NDgsIDUyNSwgNzEzLCA3ODEsIDIyMiwgNTQ3LCA1NTYsIDU0NywgNzgxLCA2NjcsIDY2NywgODY1LCA1NDIsIDcxOSwgNjY3LCAyNzgsIDI3OCwgNTAwLCAxMDU3LCAxMDEwLCA4NTQsIDU4MywgNzIyLCA2MzUsIDcxOSwgNjY3LCA2NTYsIDY2NywgNTQyLCA2NzcsIDY2NywgOTIzLCA2MDQsIDcxOSwgNzE5LCA1ODMsIDY1NiwgODMzLCA3MjIsIDc3OCwgNzE5LCA2NjcsIDcyMiwgNjExLCA2MzUsIDc2MCwgNjY3LCA3NDAsIDY2NywgOTE3LCA5MzgsIDc5MiwgODg1LCA2NTYsIDcxOSwgMTAxMCwgNzIyLCA1NTYsIDU3MywgNTMxLCAzNjUsIDU4MywgNTU2LCA2NjksIDQ1OCwgNTU5LCA1NTksIDQzOCwgNTgzLCA2ODgsIDU1MiwgNTU2LCA1NDIsIDU1NiwgNTAwLCA0NTgsIDUwMCwgODIzLCA1MDAsIDU3MywgNTIxLCA4MDIsIDgyMywgNjI1LCA3MTksIDUyMSwgNTEwLCA3NTAsIDU0MiwgNTU2LCA1NTYsIDU1NiwgMzY1LCA1MTAsIDUwMCwgMjIyLCAyNzgsIDIyMiwgOTA2LCA4MTIsIDU1NiwgNDM4LCA1NTksIDUwMCwgNTUyLCA3NzgsIDU1NiwgNDg5LCA0MTEsIDk0NCwgNzIyLCA5NDQsIDcyMiwgOTQ0LCA3MjIsIDY2NywgNTAwLCAzMzMsIDMzMywgNTU2LCAxMDAwLCAxMDAwLCA1NTIsIDIyMiwgMjIyLCAyMjIsIDIyMiwgMzMzLCAzMzMsIDMzMywgNTU2LCA1NTYsIDM1MCwgMTAwMCwgMTAwMCwgMTg4LCAzNTQsIDMzMywgMzMzLCA1MDAsIDMzMywgMTY3LCAzNjUsIDU1NiwgNTU2LCAxMDk0LCA1NTYsIDg4NSwgMzIzLCAxMDczLCAxMDAwLCA3NjgsIDYwMCwgODM0LCA4MzQsIDgzNCwgODM0LCAxMDAwLCA1MDAsIDEwMDAsIDUwMCwgMTAwMCwgNTAwLCA1MDAsIDQ5NCwgNjEyLCA4MjMsIDcxMywgNTg0LCA1NDksIDcxMywgOTc5LCA3MTksIDI3NCwgNTQ5LCA1NDksIDU4MywgNTQ5LCA1NDksIDYwNCwgNTg0LCA2MDQsIDYwNCwgNzA4LCA2MjUsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcwOCwgNzA4LCA3MDgsIDcyOSwgNjA0LCA2MDQsIDM1NCwgMzU0LCAxMDAwLCA5OTAsIDk5MCwgOTkwLCA5OTAsIDQ5NCwgNjA0LCA2MDQsIDYwNCwgNjA0LCAzNTQsIDEwMjEsIDEwNTIsIDkxNywgNzUwLCA3NTAsIDUzMSwgNjU2LCA1OTQsIDUxMCwgNTAwLCA3NTAsIDc1MCwgNTAwLCA1MDAsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAzMzMsIDMzMywgMzMzLCAyMjIsIDIyMiwgMjk0LCAyOTQsIDMyNCwgMzI0LCAzMTYsIDMyOCwgMzk4LCAyODVdOwpjb25zdCBMaWJlcmF0aW9uU2Fuc1JlZ3VsYXJNYXBwaW5nID0gWy0xLCAtMSwgLTEsIDMyLCAzMywgMzQsIDM1LCAzNiwgMzcsIDM4LCAzOSwgNDAsIDQxLCA0MiwgNDMsIDQ0LCA0NSwgNDYsIDQ3LCA0OCwgNDksIDUwLCA1MSwgNTIsIDUzLCA1NCwgNTUsIDU2LCA1NywgNTgsIDU5LCA2MCwgNjEsIDYyLCA2MywgNjQsIDY1LCA2NiwgNjcsIDY4LCA2OSwgNzAsIDcxLCA3MiwgNzMsIDc0LCA3NSwgNzYsIDc3LCA3OCwgNzksIDgwLCA4MSwgODIsIDgzLCA4NCwgODUsIDg2LCA4NywgODgsIDg5LCA5MCwgOTEsIDkyLCA5MywgOTQsIDk1LCA5NiwgOTcsIDk4LCA5OSwgMTAwLCAxMDEsIDEwMiwgMTAzLCAxMDQsIDEwNSwgMTA2LCAxMDcsIDEwOCwgMTA5LCAxMTAsIDExMSwgMTEyLCAxMTMsIDExNCwgMTE1LCAxMTYsIDExNywgMTE4LCAxMTksIDEyMCwgMTIxLCAxMjIsIDEyMywgMTI0LCAxMjUsIDEyNiwgMTYxLCAxNjIsIDE2MywgMTY0LCAxNjUsIDE2NiwgMTY3LCAxNjgsIDE2OSwgMTcwLCAxNzEsIDE3MiwgMTc0LCAxNzUsIDE3NiwgMTc3LCAxNzgsIDE3OSwgMTgwLCAxODEsIDE4MiwgMTgzLCAxODQsIDE4NSwgMTg2LCAxODcsIDE4OCwgMTg5LCAxOTAsIDE5MSwgMTkyLCAxOTMsIDE5NCwgMTk1LCAxOTYsIDE5NywgMTk4LCAxOTksIDIwMCwgMjAxLCAyMDIsIDIwMywgMjA0LCAyMDUsIDIwNiwgMjA3LCAyMDgsIDIwOSwgMjEwLCAyMTEsIDIxMiwgMjEzLCAyMTQsIDIxNSwgMjE2LCAyMTcsIDIxOCwgMjE5LCAyMjAsIDIyMSwgMjIyLCAyMjMsIDIyNCwgMjI1LCAyMjYsIDIyNywgMjI4LCAyMjksIDIzMCwgMjMxLCAyMzIsIDIzMywgMjM0LCAyMzUsIDIzNiwgMjM3LCAyMzgsIDIzOSwgMjQwLCAyNDEsIDI0MiwgMjQzLCAyNDQsIDI0NSwgMjQ2LCAyNDcsIDI0OCwgMjQ5LCAyNTAsIDI1MSwgMjUyLCAyNTMsIDI1NCwgMjU1LCAyNTYsIDI1NywgMjU4LCAyNTksIDI2MCwgMjYxLCAyNjIsIDI2MywgMjY0LCAyNjUsIDI2NiwgMjY3LCAyNjgsIDI2OSwgMjcwLCAyNzEsIDI3MiwgMjczLCAyNzQsIDI3NSwgMjc2LCAyNzcsIDI3OCwgMjc5LCAyODAsIDI4MSwgMjgyLCAyODMsIDI4NCwgMjg1LCAyODYsIDI4NywgMjg4LCAyODksIDI5MCwgMjkxLCAyOTIsIDI5MywgMjk0LCAyOTUsIDI5NiwgMjk3LCAyOTgsIDI5OSwgMzAwLCAzMDEsIDMwMiwgMzAzLCAzMDQsIDMwNSwgMzA2LCAzMDcsIDMwOCwgMzA5LCAzMTAsIDMxMSwgMzEyLCAzMTMsIDMxNCwgMzE1LCAzMTYsIDMxNywgMzE4LCAzMTksIDMyMCwgMzIxLCAzMjIsIDMyMywgMzI0LCAzMjUsIDMyNiwgMzI3LCAzMjgsIDMyOSwgMzMwLCAzMzEsIDMzMiwgMzMzLCAzMzQsIDMzNSwgMzM2LCAzMzcsIDMzOCwgMzM5LCAzNDAsIDM0MSwgMzQyLCAzNDMsIDM0NCwgMzQ1LCAzNDYsIDM0NywgMzQ4LCAzNDksIDM1MCwgMzUxLCAzNTIsIDM1MywgMzU0LCAzNTUsIDM1NiwgMzU3LCAzNTgsIDM1OSwgMzYwLCAzNjEsIDM2MiwgMzYzLCAzNjQsIDM2NSwgMzY2LCAzNjcsIDM2OCwgMzY5LCAzNzAsIDM3MSwgMzcyLCAzNzMsIDM3NCwgMzc1LCAzNzYsIDM3NywgMzc4LCAzNzksIDM4MCwgMzgxLCAzODIsIDM4MywgNDAyLCA1MDYsIDUwNywgNTA4LCA1MDksIDUxMCwgNTExLCA1MzYsIDUzNywgNTM4LCA1MzksIDcxMCwgNzExLCA3MTMsIDcyOCwgNzI5LCA3MzAsIDczMSwgNzMyLCA3MzMsIDkwMCwgOTAxLCA5MDIsIDkwMywgOTA0LCA5MDUsIDkwNiwgOTA4LCA5MTAsIDkxMSwgOTEyLCA5MTMsIDkxNCwgOTE1LCA5MTYsIDkxNywgOTE4LCA5MTksIDkyMCwgOTIxLCA5MjIsIDkyMywgOTI0LCA5MjUsIDkyNiwgOTI3LCA5MjgsIDkyOSwgOTMxLCA5MzIsIDkzMywgOTM0LCA5MzUsIDkzNiwgOTM3LCA5MzgsIDkzOSwgOTQwLCA5NDEsIDk0MiwgOTQzLCA5NDQsIDk0NSwgOTQ2LCA5NDcsIDk0OCwgOTQ5LCA5NTAsIDk1MSwgOTUyLCA5NTMsIDk1NCwgOTU1LCA5NTYsIDk1NywgOTU4LCA5NTksIDk2MCwgOTYxLCA5NjIsIDk2MywgOTY0LCA5NjUsIDk2NiwgOTY3LCA5NjgsIDk2OSwgOTcwLCA5NzEsIDk3MiwgOTczLCA5NzQsIDEwMjQsIDEwMjUsIDEwMjYsIDEwMjcsIDEwMjgsIDEwMjksIDEwMzAsIDEwMzEsIDEwMzIsIDEwMzMsIDEwMzQsIDEwMzUsIDEwMzYsIDEwMzcsIDEwMzgsIDEwMzksIDEwNDAsIDEwNDEsIDEwNDIsIDEwNDMsIDEwNDQsIDEwNDUsIDEwNDYsIDEwNDcsIDEwNDgsIDEwNDksIDEwNTAsIDEwNTEsIDEwNTIsIDEwNTMsIDEwNTQsIDEwNTUsIDEwNTYsIDEwNTcsIDEwNTgsIDEwNTksIDEwNjAsIDEwNjEsIDEwNjIsIDEwNjMsIDEwNjQsIDEwNjUsIDEwNjYsIDEwNjcsIDEwNjgsIDEwNjksIDEwNzAsIDEwNzEsIDEwNzIsIDEwNzMsIDEwNzQsIDEwNzUsIDEwNzYsIDEwNzcsIDEwNzgsIDEwNzksIDEwODAsIDEwODEsIDEwODIsIDEwODMsIDEwODQsIDEwODUsIDEwODYsIDEwODcsIDEwODgsIDEwODksIDEwOTAsIDEwOTEsIDEwOTIsIDEwOTMsIDEwOTQsIDEwOTUsIDEwOTYsIDEwOTcsIDEwOTgsIDEwOTksIDExMDAsIDExMDEsIDExMDIsIDExMDMsIDExMDQsIDExMDUsIDExMDYsIDExMDcsIDExMDgsIDExMDksIDExMTAsIDExMTEsIDExMTIsIDExMTMsIDExMTQsIDExMTUsIDExMTYsIDExMTcsIDExMTgsIDExMTksIDExMzgsIDExMzksIDExNjgsIDExNjksIDc4MDgsIDc4MDksIDc4MTAsIDc4MTEsIDc4MTIsIDc4MTMsIDc5MjIsIDc5MjMsIDgyMDgsIDgyMDksIDgyMTEsIDgyMTIsIDgyMTMsIDgyMTUsIDgyMTYsIDgyMTcsIDgyMTgsIDgyMTksIDgyMjAsIDgyMjEsIDgyMjIsIDgyMjQsIDgyMjUsIDgyMjYsIDgyMzAsIDgyNDAsIDgyNDIsIDgyNDMsIDgyNDksIDgyNTAsIDgyNTIsIDgyNTQsIDgyNjAsIDgzMTksIDgzNTUsIDgzNTYsIDgzNTksIDgzNjQsIDg0NTMsIDg0NjcsIDg0NzAsIDg0ODIsIDg0ODYsIDg0OTQsIDg1MzksIDg1NDAsIDg1NDEsIDg1NDIsIDg1OTIsIDg1OTMsIDg1OTQsIDg1OTUsIDg1OTYsIDg1OTcsIDg2MTYsIDg3MDYsIDg3MTAsIDg3MTksIDg3MjEsIDg3MjIsIDg3MzAsIDg3MzQsIDg3MzUsIDg3NDUsIDg3NDcsIDg3NzYsIDg4MDAsIDg4MDEsIDg4MDQsIDg4MDUsIDg5NjIsIDg5NzYsIDg5OTIsIDg5OTMsIDk0NzIsIDk0NzQsIDk0ODQsIDk0ODgsIDk0OTIsIDk0OTYsIDk1MDAsIDk1MDgsIDk1MTYsIDk1MjQsIDk1MzIsIDk1NTIsIDk1NTMsIDk1NTQsIDk1NTUsIDk1NTYsIDk1NTcsIDk1NTgsIDk1NTksIDk1NjAsIDk1NjEsIDk1NjIsIDk1NjMsIDk1NjQsIDk1NjUsIDk1NjYsIDk1NjcsIDk1NjgsIDk1NjksIDk1NzAsIDk1NzEsIDk1NzIsIDk1NzMsIDk1NzQsIDk1NzUsIDk1NzYsIDk1NzcsIDk1NzgsIDk1NzksIDk1ODAsIDk2MDAsIDk2MDQsIDk2MDgsIDk2MTIsIDk2MTYsIDk2MTcsIDk2MTgsIDk2MTksIDk2MzIsIDk2MzMsIDk2NDIsIDk2NDMsIDk2NDQsIDk2NTAsIDk2NTgsIDk2NjAsIDk2NjgsIDk2NzQsIDk2NzUsIDk2NzksIDk2ODgsIDk2ODksIDk3MDIsIDk3ODYsIDk3ODcsIDk3ODgsIDk3OTIsIDk3OTQsIDk4MjQsIDk4MjcsIDk4MjksIDk4MzAsIDk4MzQsIDk4MzUsIDk4MzYsIDYxNDQxLCA2MTQ0MiwgNjE0NDUsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMSwgLTEsIC0xLCAtMV07Cgo7Ly8gLi9zcmMvY29yZS9teXJpYWRwcm9fZmFjdG9ycy5qcwpjb25zdCBNeXJpYWRQcm9Cb2xkRmFjdG9ycyA9IFsxLjM2ODk4LCAxLCAxLCAwLjcyNzA2LCAwLjgwNDc5LCAwLjgzNzM0LCAwLjk4ODk0LCAwLjk5NzkzLCAwLjk4OTcsIDAuOTM4ODQsIDAuODYyMDksIDAuOTQyOTIsIDAuOTQyOTIsIDEuMTY2NjEsIDEuMDIwNTgsIDAuOTM1ODIsIDAuOTY2OTQsIDAuOTM1ODIsIDEuMTkxMzcsIDAuOTk3OTMsIDAuOTk3OTMsIDAuOTk3OTMsIDAuOTk3OTMsIDAuOTk3OTMsIDAuOTk3OTMsIDAuOTk3OTMsIDAuOTk3OTMsIDAuOTk3OTMsIDAuOTk3OTMsIDAuNzgwNzYsIDAuNzgwNzYsIDEuMDIwNTgsIDEuMDIwNTgsIDEuMDIwNTgsIDAuNzI4NTEsIDAuNzg5NjYsIDAuOTA4MzgsIDAuODM2MzcsIDAuODIzOTEsIDAuOTYzNzYsIDAuODAwNjEsIDAuODYyNzUsIDAuODc2OCwgMC45NTQwNywgMS4wMjU4LCAwLjczOTAxLCAwLjg1MDIyLCAwLjgzNjU1LCAxLjAxNTYsIDAuOTU1NDYsIDAuOTIxNzksIDAuODcxMDcsIDAuOTIxNzksIDAuODIxMTQsIDAuODA5NiwgMC44OTcxMywgMC45NDQzOCwgMC45NTM1MywgMC45NDA4MywgMC45MTkwNSwgMC45MDQwNiwgMC45NDQ2LCAwLjk0MjkyLCAxLjE4Nzc3LCAwLjk0MjkyLCAxLjAyMDU4LCAwLjg5OTAzLCAwLjkwMDg4LCAwLjk0OTM4LCAwLjk3ODk4LCAwLjgxMDkzLCAwLjk3NTcxLCAwLjk0OTM4LCAxLjAyNCwgMC45NTc3LCAwLjk1OTMzLCAwLjk4NjIxLCAxLjA0NzQsIDAuOTc0NTUsIDAuOTg5ODEsIDAuOTY3MiwgMC45NTkzMywgMC45NDQ2LCAwLjk3ODk4LCAwLjk3NDA3LCAwLjk3NjQ2LCAwLjc4MDM2LCAxLjEwMjA4LCAwLjk1NDQyLCAwLjk1Mjk4LCAwLjk3NTc5LCAwLjkzMzIsIDAuOTQwMzksIDAuOTM4LCAwLjgwNjg3LCAxLjAxMTQ5LCAwLjgwNjg3LCAxLjAyMDU4LCAwLjgwNDc5LCAwLjk5NzkzLCAwLjk5NzkzLCAwLjk5NzkzLCAwLjk5NzkzLCAxLjAxMTQ5LCAxLjAwODcyLCAwLjkwMDg4LCAwLjkxODgyLCAxLjAyMTMsIDAuODM2MSwgMS4wMjA1OCwgMC42MjI5NSwgMC41NDMyNCwgMC44OTAyMiwgMS4wODU5NSwgMSwgMSwgMC45MDA4OCwgMSwgMC45NzQ1NSwgMC45MzU4MiwgMC45MDA4OCwgMSwgMS4wNTY4NiwgMC44MzYxLCAwLjk5NjQyLCAwLjk5NjQyLCAwLjk5NjQyLCAwLjcyODUxLCAwLjkwODM4LCAwLjkwODM4LCAwLjkwODM4LCAwLjkwODM4LCAwLjkwODM4LCAwLjkwODM4LCAwLjg2OCwgMC44MjM5MSwgMC44MDA2MSwgMC44MDA2MSwgMC44MDA2MSwgMC44MDA2MSwgMS4wMjU4LCAxLjAyNTgsIDEuMDI1OCwgMS4wMjU4LCAwLjk3NDg0LCAwLjk1NTQ2LCAwLjkyMTc5LCAwLjkyMTc5LCAwLjkyMTc5LCAwLjkyMTc5LCAwLjkyMTc5LCAxLjAyMDU4LCAwLjkyMTc5LCAwLjk0NDM4LCAwLjk0NDM4LCAwLjk0NDM4LCAwLjk0NDM4LCAwLjkwNDA2LCAwLjg2OTU4LCAwLjk4MjI1LCAwLjk0OTM4LCAwLjk0OTM4LCAwLjk0OTM4LCAwLjk0OTM4LCAwLjk0OTM4LCAwLjk0OTM4LCAwLjkwMzEsIDAuODEwOTMsIDAuOTQ5MzgsIDAuOTQ5MzgsIDAuOTQ5MzgsIDAuOTQ5MzgsIDAuOTg2MjEsIDAuOTg2MjEsIDAuOTg2MjEsIDAuOTg2MjEsIDAuOTM5NjksIDAuOTU5MzMsIDAuOTQ0NiwgMC45NDQ2LCAwLjk0NDYsIDAuOTQ0NiwgMC45NDQ2LCAxLjA4NTk1LCAwLjk0NDYsIDAuOTU0NDIsIDAuOTU0NDIsIDAuOTU0NDIsIDAuOTU0NDIsIDAuOTQwMzksIDAuOTc4OTgsIDAuOTQwMzksIDAuOTA4MzgsIDAuOTQ5MzgsIDAuOTA4MzgsIDAuOTQ5MzgsIDAuOTA4MzgsIDAuOTQ5MzgsIDAuODIzOTEsIDAuODEwOTMsIDAuODIzOTEsIDAuODEwOTMsIDAuODIzOTEsIDAuODEwOTMsIDAuODIzOTEsIDAuODEwOTMsIDAuOTYzNzYsIDAuODQzMTMsIDAuOTc0ODQsIDAuOTc1NzEsIDAuODAwNjEsIDAuOTQ5MzgsIDAuODAwNjEsIDAuOTQ5MzgsIDAuODAwNjEsIDAuOTQ5MzgsIDAuODAwNjEsIDAuOTQ5MzgsIDAuODAwNjEsIDAuOTQ5MzgsIDAuODc2OCwgMC45NTc3LCAwLjg3NjgsIDAuOTU3NywgMC44NzY4LCAwLjk1NzcsIDEsIDEsIDAuOTU0MDcsIDAuOTU5MzMsIDAuOTcwNjksIDAuOTU5MzMsIDEuMDI1OCwgMC45ODYyMSwgMS4wMjU4LCAwLjk4NjIxLCAxLjAyNTgsIDAuOTg2MjEsIDEuMDI1OCwgMC45ODYyMSwgMS4wMjU4LCAwLjk4NjIxLCAwLjg4NywgMS4wMTU5MSwgMC43MzkwMSwgMS4wNDc0LCAxLCAxLCAwLjk3NDU1LCAwLjgzNjU1LCAwLjk4OTgxLCAxLCAxLCAwLjgzNjU1LCAwLjczOTc3LCAwLjgzNjU1LCAwLjczOTAzLCAwLjg0NjM4LCAxLjAzMywgMC45NTU0NiwgMC45NTkzMywgMSwgMSwgMC45NTU0NiwgMC45NTkzMywgMC44MjcxLCAwLjk1NDE3LCAwLjk1OTMzLCAwLjkyMTc5LCAwLjk0NDYsIDAuOTIxNzksIDAuOTQ0NiwgMC45MjE3OSwgMC45NDQ2LCAwLjkzNiwgMC45MTk2NCwgMC44MjExNCwgMC45NzY0NiwgMSwgMSwgMC44MjExNCwgMC45NzY0NiwgMC44MDk2LCAwLjc4MDM2LCAwLjgwOTYsIDAuNzgwMzYsIDEsIDEsIDAuODA5NiwgMC43ODAzNiwgMSwgMSwgMC44OTcxMywgMC43NzQ1MiwgMC44OTcxMywgMS4xMDIwOCwgMC45NDQzOCwgMC45NTQ0MiwgMC45NDQzOCwgMC45NTQ0MiwgMC45NDQzOCwgMC45NTQ0MiwgMC45NDQzOCwgMC45NTQ0MiwgMC45NDQzOCwgMC45NTQ0MiwgMC45NDQzOCwgMC45NTQ0MiwgMC45NDA4MywgMC45NzU3OSwgMC45MDQwNiwgMC45NDAzOSwgMC45MDQwNiwgMC45NDQ2LCAwLjkzOCwgMC45NDQ2LCAwLjkzOCwgMC45NDQ2LCAwLjkzOCwgMSwgMC45OTc5MywgMC45MDgzOCwgMC45NDkzOCwgMC44NjgsIDAuOTAzMSwgMC45MjE3OSwgMC45NDQ2LCAxLCAxLCAwLjg5NzEzLCAxLjEwMjA4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwMDg4LCAwLjkwOTg5LCAwLjkzNTgsIDAuOTE5NDUsIDAuODMxODEsIDAuNzUyNjEsIDAuODc5OTIsIDAuODI5NzYsIDAuOTYwMzQsIDAuODM2ODksIDAuOTcyNjgsIDEuMDA3OCwgMC45MDgzOCwgMC44MzYzNywgMC44MDE5LCAwLjkwMTU3LCAwLjgwMDYxLCAwLjk0NDYsIDAuOTU0MDcsIDAuOTI0MzYsIDEuMDI1OCwgMC44NTAyMiwgMC45NzE1MywgMS4wMTU2LCAwLjk1NTQ2LCAwLjg5MTkyLCAwLjkyMTc5LCAwLjkyMzYxLCAwLjg3MTA3LCAwLjk2MzE4LCAwLjg5NzEzLCAwLjkzNzA0LCAwLjk1NjM4LCAwLjkxOTA1LCAwLjkxNzA5LCAwLjkyNzk2LCAxLjAyNTgsIDAuOTM3MDQsIDAuOTQ4MzYsIDEuMDM3MywgMC45NTkzMywgMS4wMDc4LCAwLjk1ODcxLCAwLjk0ODM2LCAwLjk2MTc0LCAwLjkyNjAxLCAwLjk0OTgsIDAuOTg2MDcsIDAuOTU3NzYsIDAuOTU5MzMsIDEuMDU0NTMsIDEuMDA3OCwgMC45ODI3NSwgMC45MzE0LCAwLjk1NjE3LCAwLjkxNzAxLCAxLjA1OTkzLCAwLjk0NDYsIDAuNzgzNjcsIDAuOTU1MywgMSwgMC44NjgzMiwgMS4wMTI4LCAwLjk1ODcxLCAwLjk5Mzk0LCAwLjg3NTQ4LCAwLjk2MzYxLCAwLjg2Nzc0LCAxLjAwNzgsIDAuOTU4NzEsIDAuOTQ0NiwgMC45NTg3MSwgMC44Njc3NCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45NDA4MywgMC45NzU3OSwgMC45NDA4MywgMC45NzU3OSwgMC45NDA4MywgMC45NzU3OSwgMC45MDQwNiwgMC45NDAzOSwgMC45NjY5NCwgMSwgMC44OTkwMywgMSwgMSwgMSwgMC45MzU4MiwgMC45MzU4MiwgMC45MzU4MiwgMSwgMC45MDgsIDAuOTA4LCAwLjkxOCwgMC45NDIxOSwgMC45NDIxOSwgMC45NjU0NCwgMSwgMS4yODUsIDEsIDEsIDAuODEwNzksIDAuODEwNzksIDEsIDEsIDAuNzQ4NTQsIDEsIDEsIDEsIDEsIDAuOTk3OTMsIDEsIDEsIDEsIDAuNjUsIDEsIDEuMzYxNDUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMTcxNzMsIDEsIDAuODA1MzUsIDAuNzYxNjksIDEuMDIwNTgsIDEuMDczMiwgMS4wNTQ4NiwgMSwgMSwgMS4zMDY5MiwgMS4wODU5NSwgMS4wODU5NSwgMSwgMS4wODU5NSwgMS4wODU5NSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4xNjE2MSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMV07CmNvbnN0IE15cmlhZFByb0JvbGRNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMiwKICBsaW5lR2FwOiAwLjIKfTsKY29uc3QgTXlyaWFkUHJvQm9sZEl0YWxpY0ZhY3RvcnMgPSBbMS4zNjg5OCwgMSwgMSwgMC42NjIyNywgMC44MDc3OSwgMC44MTYyNSwgMC45NzI3NiwgMC45NzI3NiwgMC45NzczMywgMC45MjIyMiwgMC44MzI2NiwgMC45NDI5MiwgMC45NDI5MiwgMS4xNjE0OCwgMS4wMjA1OCwgMC45MzU4MiwgMC45NjY5NCwgMC45MzU4MiwgMS4xNzMzNywgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC43ODA3NiwgMC43ODA3NiwgMS4wMjA1OCwgMS4wMjA1OCwgMS4wMjA1OCwgMC43MTU0MSwgMC43NjgxMywgMC44NTU3NiwgMC44MDU5MSwgMC44MDcyOSwgMC45NDI5OSwgMC43NzUxMiwgMC44MzY1NSwgMC44NjUyMywgMC45MjIyMiwgMC45ODYyMSwgMC43MTc0MywgMC44MTY5OCwgMC43OTcyNiwgMC45ODU1OCwgMC45MjIyMiwgMC45MDYzNywgMC44MzgwOSwgMC45MDYzNywgMC44MDcyOSwgMC43NjQ2MywgMC44NjI3NSwgMC45MDY5OSwgMC45MTYwNSwgMC45MTU0LCAwLjg1MzA4LCAwLjg1NDU4LCAwLjkwNTMxLCAwLjk0MjkyLCAxLjIxMjk2LCAwLjk0MjkyLCAxLjAyMDU4LCAwLjg5OTAzLCAxLjE4NjE2LCAwLjk5NjEzLCAwLjkxNjc3LCAwLjc4MjE2LCAwLjkxNjc3LCAwLjkwMDgzLCAwLjk4Nzk2LCAwLjkxMzUsIDAuOTIxNjgsIDAuOTUzODEsIDAuOTg5ODEsIDAuOTUyOTgsIDAuOTUzODEsIDAuOTM0NTksIDAuOTIxNjgsIDAuOTE1MTMsIDAuOTIwMDQsIDAuOTE2NzcsIDAuOTUwNzcsIDAuNzQ4LCAxLjA0NTAyLCAwLjkxNjc3LCAwLjkyMDYxLCAwLjk0MjM2LCAwLjg5NTQ0LCAwLjg5MzY0LCAwLjksIDAuODA2ODcsIDAuODU3OCwgMC44MDY4NywgMS4wMjA1OCwgMC44MDc3OSwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC45NzI3NiwgMC44NTc4LCAwLjk5OTczLCAxLjE4NjE2LCAwLjkxMzM5LCAxLjA4MDc0LCAwLjgyODkxLCAxLjAyMDU4LCAwLjU1NTA5LCAwLjcxNTI2LCAwLjg5MDIyLCAxLjA4NTk1LCAxLCAxLCAxLjE4NjE2LCAxLCAwLjk2NzM2LCAwLjkzNTgyLCAxLjE4NjE2LCAxLCAxLjA0ODY0LCAwLjgyNzExLCAwLjk5MDQzLCAwLjk5MDQzLCAwLjk5MDQzLCAwLjcxNTQxLCAwLjg1NTc2LCAwLjg1NTc2LCAwLjg1NTc2LCAwLjg1NTc2LCAwLjg1NTc2LCAwLjg1NTc2LCAwLjg0NSwgMC44MDcyOSwgMC43NzUxMiwgMC43NzUxMiwgMC43NzUxMiwgMC43NzUxMiwgMC45ODYyMSwgMC45ODYyMSwgMC45ODYyMSwgMC45ODYyMSwgMC45NTk2MSwgMC45MjIyMiwgMC45MDYzNywgMC45MDYzNywgMC45MDYzNywgMC45MDYzNywgMC45MDYzNywgMS4wMjA1OCwgMC45MDI1MSwgMC45MDY5OSwgMC45MDY5OSwgMC45MDY5OSwgMC45MDY5OSwgMC44NTQ1OCwgMC44MzY1OSwgMC45NDk1MSwgMC45OTYxMywgMC45OTYxMywgMC45OTYxMywgMC45OTYxMywgMC45OTYxMywgMC45OTYxMywgMC44NTgxMSwgMC43ODIxNiwgMC45MDA4MywgMC45MDA4MywgMC45MDA4MywgMC45MDA4MywgMC45NTM4MSwgMC45NTM4MSwgMC45NTM4MSwgMC45NTM4MSwgMC45MTM1LCAwLjkyMTY4LCAwLjkxNTEzLCAwLjkxNTEzLCAwLjkxNTEzLCAwLjkxNTEzLCAwLjkxNTEzLCAxLjA4NTk1LCAwLjkxNjc3LCAwLjkxNjc3LCAwLjkxNjc3LCAwLjkxNjc3LCAwLjkxNjc3LCAwLjg5MzY0LCAwLjkyMzMyLCAwLjg5MzY0LCAwLjg1NTc2LCAwLjk5NjEzLCAwLjg1NTc2LCAwLjk5NjEzLCAwLjg1NTc2LCAwLjk5NjEzLCAwLjgwNzI5LCAwLjc4MjE2LCAwLjgwNzI5LCAwLjc4MjE2LCAwLjgwNzI5LCAwLjc4MjE2LCAwLjgwNzI5LCAwLjc4MjE2LCAwLjk0Mjk5LCAwLjc2NzgzLCAwLjk1OTYxLCAwLjkxNjc3LCAwLjc3NTEyLCAwLjkwMDgzLCAwLjc3NTEyLCAwLjkwMDgzLCAwLjc3NTEyLCAwLjkwMDgzLCAwLjc3NTEyLCAwLjkwMDgzLCAwLjc3NTEyLCAwLjkwMDgzLCAwLjg2NTIzLCAwLjkxMzUsIDAuODY1MjMsIDAuOTEzNSwgMC44NjUyMywgMC45MTM1LCAxLCAxLCAwLjkyMjIyLCAwLjkyMTY4LCAwLjkyMjIyLCAwLjkyMTY4LCAwLjk4NjIxLCAwLjk1MzgxLCAwLjk4NjIxLCAwLjk1MzgxLCAwLjk4NjIxLCAwLjk1MzgxLCAwLjk4NjIxLCAwLjk1MzgxLCAwLjk4NjIxLCAwLjk1MzgxLCAwLjg2MDM2LCAwLjk3MDk2LCAwLjcxNzQzLCAwLjk4OTgxLCAxLCAxLCAwLjk1Mjk4LCAwLjc5NzI2LCAwLjk1MzgxLCAxLCAxLCAwLjc5NzI2LCAwLjY4OTQsIDAuNzk3MjYsIDAuNzQzMjEsIDAuODE2OTEsIDEuMDAwNiwgMC45MjIyMiwgMC45MjE2OCwgMSwgMSwgMC45MjIyMiwgMC45MjE2OCwgMC43OTQ2NCwgMC45MjA5OCwgMC45MjE2OCwgMC45MDYzNywgMC45MTUxMywgMC45MDYzNywgMC45MTUxMywgMC45MDYzNywgMC45MTUxMywgMC45MDksIDAuODc1MTQsIDAuODA3MjksIDAuOTUwNzcsIDEsIDEsIDAuODA3MjksIDAuOTUwNzcsIDAuNzY0NjMsIDAuNzQ4LCAwLjc2NDYzLCAwLjc0OCwgMSwgMSwgMC43NjQ2MywgMC43NDgsIDEsIDEsIDAuODYyNzUsIDAuNzI2NTEsIDAuODYyNzUsIDEuMDQ1MDIsIDAuOTA2OTksIDAuOTE2NzcsIDAuOTA2OTksIDAuOTE2NzcsIDAuOTA2OTksIDAuOTE2NzcsIDAuOTA2OTksIDAuOTE2NzcsIDAuOTA2OTksIDAuOTE2NzcsIDAuOTA2OTksIDAuOTE2NzcsIDAuOTE1NCwgMC45NDIzNiwgMC44NTQ1OCwgMC44OTM2NCwgMC44NTQ1OCwgMC45MDUzMSwgMC45LCAwLjkwNTMxLCAwLjksIDAuOTA1MzEsIDAuOSwgMSwgMC45NzI3NiwgMC44NTU3NiwgMC45OTYxMywgMC44NDUsIDAuODU4MTEsIDAuOTAyNTEsIDAuOTE2NzcsIDEsIDEsIDAuODYyNzUsIDEuMDQ1MDIsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMTg2MTYsIDEuMDA4OTksIDEuMzA2MjgsIDAuODU1NzYsIDAuODAxNzgsIDAuNjY4NjIsIDAuNzkyNywgMC42OTMyMywgMC44ODEyNywgMC43MjQ1OSwgMC44OTcxMSwgMC45NTM4MSwgMC44NTU3NiwgMC44MDU5MSwgMC43ODA1LCAwLjk0NzI5LCAwLjc3NTEyLCAwLjkwNTMxLCAwLjkyMjIyLCAwLjkwNjM3LCAwLjk4NjIxLCAwLjgxNjk4LCAwLjkyNjU1LCAwLjk4NTU4LCAwLjkyMjIyLCAwLjg1MzU5LCAwLjkwNjM3LCAwLjkwOTc2LCAwLjgzODA5LCAwLjk0NTIzLCAwLjg2Mjc1LCAwLjgzNTA5LCAwLjkzMTU3LCAwLjg1MzA4LCAwLjgzMzkyLCAwLjkyMzQ2LCAwLjk4NjIxLCAwLjgzNTA5LCAwLjkyODg2LCAwLjkxMzI0LCAwLjkyMTY4LCAwLjk1MzgxLCAwLjkwNjQ2LCAwLjkyODg2LCAwLjkwNTU3LCAwLjg2ODQ3LCAwLjkwMjc2LCAwLjkxMzI0LCAwLjg2ODQyLCAwLjkyMTY4LCAwLjk5NTMxLCAwLjk1MzgxLCAwLjkyMjQsIDAuODU0MDgsIDAuOTI2OTksIDAuODY4NDcsIDEuMDA1MSwgMC45MTUxMywgMC44MDQ4NywgMC45MzQ4MSwgMSwgMC44ODE1OSwgMS4wNTIxNCwgMC45MDY0NiwgMC45NzM1NSwgMC44MTUzOSwgMC44OTM5OCwgMC44NTkyMywgMC45NTM4MSwgMC45MDY0NiwgMC45MTUxMywgMC45MDY0NiwgMC44NTkyMywgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMC45MTU0LCAwLjk0MjM2LCAwLjkxNTQsIDAuOTQyMzYsIDAuOTE1NCwgMC45NDIzNiwgMC44NTQ1OCwgMC44OTM2NCwgMC45NjY5NCwgMSwgMC44OTkwMywgMSwgMSwgMSwgMC45MTc4MiwgMC45MTc4MiwgMC45MTc4MiwgMSwgMC44OTYsIDAuODk2LCAwLjg5NiwgMC45MzMyLCAwLjkzMzIsIDAuOTU5NzMsIDEsIDEuMjYsIDEsIDEsIDAuODA0NzksIDAuODAxNzgsIDEsIDEsIDAuODU2MzMsIDEsIDEsIDEsIDEsIDAuOTcyNzYsIDEsIDEsIDEsIDAuNjk4LCAxLCAxLjM2MTQ1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjE0NTQyLCAxLCAwLjc5MTk5LCAwLjc4Njk0LCAxLjAyMDU4LCAxLjAzNDkzLCAxLjA1NDg2LCAxLCAxLCAxLjIzMDI2LCAxLjA4NTk1LCAxLjA4NTk1LCAxLCAxLjA4NTk1LCAxLjA4NTk1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjIwMDA2LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKY29uc3QgTXlyaWFkUHJvQm9sZEl0YWxpY01ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4yLAogIGxpbmVHYXA6IDAuMgp9Owpjb25zdCBNeXJpYWRQcm9JdGFsaWNGYWN0b3JzID0gWzEuMzY4OTgsIDEsIDEsIDAuNjU1MDcsIDAuODQ5NDMsIDAuODU2MzksIDAuODg0NjUsIDAuODg0NjUsIDAuODY5MzYsIDAuODgzMDcsIDAuODY5NDgsIDAuODUyODMsIDAuODUyODMsIDEuMDYzODMsIDEuMDIwNTgsIDAuNzU5NDUsIDAuOTIxOSwgMC43NTk0NSwgMS4xNzMzNywgMC44ODQ2NSwgMC44ODQ2NSwgMC44ODQ2NSwgMC44ODQ2NSwgMC44ODQ2NSwgMC44ODQ2NSwgMC44ODQ2NSwgMC44ODQ2NSwgMC44ODQ2NSwgMC44ODQ2NSwgMC43NTk0NSwgMC43NTk0NSwgMS4wMjA1OCwgMS4wMjA1OCwgMS4wMjA1OCwgMC42OTA0NiwgMC43MDkyNiwgMC44NTE1OCwgMC43NzgxMiwgMC43Njg1MiwgMC44OTU5MSwgMC43MDQ2NiwgMC43NjEyNSwgMC44MDA5NCwgMC44NjgyMiwgMC44Mzg2NCwgMC43MjgsIDAuNzcyMTIsIDAuNzk0NzUsIDAuOTM2MzcsIDAuODc1MTQsIDAuODU4OCwgMC43NjAxMywgMC44NTg4LCAwLjcyNDIxLCAwLjY5ODY2LCAwLjc3NTk4LCAwLjg1OTkxLCAwLjgwODExLCAwLjg3ODMyLCAwLjc4MTEyLCAwLjc3NTEyLCAwLjg1NjIsIDEuMDIyMiwgMS4xODQxNywgMS4wMjIyLCAxLjI3MDE0LCAwLjg5OTAzLCAxLjE1MDEyLCAwLjkzODU5LCAwLjk0Mzk5LCAwLjg0NiwgMC45NDM5OSwgMC44MTQ1MywgMS4wMTg2LCAwLjk0MjE5LCAwLjk2MDE3LCAxLjAzMDc1LCAxLjAyMTc1LCAwLjkxMiwgMS4wMzA3NSwgMC45Njk5OCwgMC45NjAxNywgMC45Mzg1OSwgMC45NDM5OSwgMC45NDM5OSwgMC45NTQ5MywgMC43NDYsIDEuMTI2NTgsIDAuOTQ1NzgsIDAuOTEsIDAuOTc5LCAwLjg4MiwgMC44ODIsIDAuODMsIDAuODUwMzQsIDAuODM1MzcsIDAuODUwMzQsIDEuMDIwNTgsIDAuNzA4NjksIDAuODg0NjUsIDAuODg0NjUsIDAuODg0NjUsIDAuODg0NjUsIDAuODM1MzcsIDAuOTAwODMsIDEuMTUwMTIsIDAuOTE2MSwgMC45NDU2NSwgMC43MzU0MSwgMS4wMjA1OCwgMC41MzYwOSwgMC42OTM1MywgMC43OTUxOSwgMS4wODU5NSwgMSwgMSwgMS4xNTAxMiwgMSwgMC45MTk3NCwgMC43NTk0NSwgMS4xNTAxMiwgMSwgMC45NDQ2LCAwLjczMzYxLCAwLjkwMDUsIDAuOTAwNSwgMC45MDA1LCAwLjYyODY0LCAwLjg1MTU4LCAwLjg1MTU4LCAwLjg1MTU4LCAwLjg1MTU4LCAwLjg1MTU4LCAwLjg1MTU4LCAwLjc3MywgMC43Njg1MiwgMC43MDQ2NiwgMC43MDQ2NiwgMC43MDQ2NiwgMC43MDQ2NiwgMC44Mzg2NCwgMC44Mzg2NCwgMC44Mzg2NCwgMC44Mzg2NCwgMC45MDU2MSwgMC44NzUxNCwgMC44NTg4LCAwLjg1ODgsIDAuODU4OCwgMC44NTg4LCAwLjg1ODgsIDEuMDIwNTgsIDAuODU3NTEsIDAuODU5OTEsIDAuODU5OTEsIDAuODU5OTEsIDAuODU5OTEsIDAuNzc1MTIsIDAuNzYwMTMsIDAuODgwNzUsIDAuOTM4NTksIDAuOTM4NTksIDAuOTM4NTksIDAuOTM4NTksIDAuOTM4NTksIDAuOTM4NTksIDAuODA3NSwgMC44NDYsIDAuODE0NTMsIDAuODE0NTMsIDAuODE0NTMsIDAuODE0NTMsIDAuODI0MjQsIDAuODI0MjQsIDAuODI0MjQsIDAuODI0MjQsIDAuOTI3OCwgMC45NjAxNywgMC45Mzg1OSwgMC45Mzg1OSwgMC45Mzg1OSwgMC45Mzg1OSwgMC45Mzg1OSwgMS4wODU5NSwgMC44NTYyLCAwLjk0NTc4LCAwLjk0NTc4LCAwLjk0NTc4LCAwLjk0NTc4LCAwLjg4MiwgMC45NDU3OCwgMC44ODIsIDAuODUxNTgsIDAuOTM4NTksIDAuODUxNTgsIDAuOTM4NTksIDAuODUxNTgsIDAuOTM4NTksIDAuNzY4NTIsIDAuODQ2LCAwLjc2ODUyLCAwLjg0NiwgMC43Njg1MiwgMC44NDYsIDAuNzY4NTIsIDAuODQ2LCAwLjg5NTkxLCAwLjg1NDQsIDAuOTA1NjEsIDAuOTQzOTksIDAuNzA0NjYsIDAuODE0NTMsIDAuNzA0NjYsIDAuODE0NTMsIDAuNzA0NjYsIDAuODE0NTMsIDAuNzA0NjYsIDAuODE0NTMsIDAuNzA0NjYsIDAuODE0NTMsIDAuODAwOTQsIDAuOTQyMTksIDAuODAwOTQsIDAuOTQyMTksIDAuODAwOTQsIDAuOTQyMTksIDEsIDEsIDAuODY4MjIsIDAuOTYwMTcsIDAuODY4MjIsIDAuOTYwMTcsIDAuODM4NjQsIDAuODI0MjQsIDAuODM4NjQsIDAuODI0MjQsIDAuODM4NjQsIDAuODI0MjQsIDAuODM4NjQsIDEuMDMwNzUsIDAuODM4NjQsIDAuODI0MjQsIDAuODE0MDIsIDEuMDI3MzgsIDAuNzI4LCAxLjAyMTc1LCAxLCAxLCAwLjkxMiwgMC43OTQ3NSwgMS4wMzA3NSwgMSwgMSwgMC43OTQ3NSwgMC44MzkxMSwgMC43OTQ3NSwgMC42NjI2NiwgMC44MDU1MywgMS4wNjY3NiwgMC44NzUxNCwgMC45NjAxNywgMSwgMSwgMC44NzUxNCwgMC45NjAxNywgMC44Njg2NSwgMC44NzM5NiwgMC45NjAxNywgMC44NTg4LCAwLjkzODU5LCAwLjg1ODgsIDAuOTM4NTksIDAuODU4OCwgMC45Mzg1OSwgMC44NjcsIDAuODQ3NTksIDAuNzI0MjEsIDAuOTU0OTMsIDEsIDEsIDAuNzI0MjEsIDAuOTU0OTMsIDAuNjk4NjYsIDAuNzQ2LCAwLjY5ODY2LCAwLjc0NiwgMSwgMSwgMC42OTg2NiwgMC43NDYsIDEsIDEsIDAuNzc1OTgsIDAuODg0MTcsIDAuNzc1OTgsIDEuMTI2NTgsIDAuODU5OTEsIDAuOTQ1NzgsIDAuODU5OTEsIDAuOTQ1NzgsIDAuODU5OTEsIDAuOTQ1NzgsIDAuODU5OTEsIDAuOTQ1NzgsIDAuODU5OTEsIDAuOTQ1NzgsIDAuODU5OTEsIDAuOTQ1NzgsIDAuODc4MzIsIDAuOTc5LCAwLjc3NTEyLCAwLjg4MiwgMC43NzUxMiwgMC44NTYyLCAwLjgzLCAwLjg1NjIsIDAuODMsIDAuODU2MiwgMC44MywgMSwgMC44ODQ2NSwgMC44NTE1OCwgMC45Mzg1OSwgMC43NzMsIDAuODA3NSwgMC44NTc1MSwgMC44NTYyLCAxLCAxLCAwLjc3NTk4LCAxLjEyNjU4LCAxLjE1MDEyLCAxLjE1MDEyLCAxLjE1MDEyLCAxLjE1MDEyLCAxLjE1MDEyLCAxLjE1MzEzLCAxLjE1MDEyLCAxLjE1MDEyLCAxLjE1MDEyLCAxLjA4MTA2LCAxLjAzOTAxLCAwLjg1MTU4LCAwLjc3MDI1LCAwLjYyMjY0LCAwLjc2NDYsIDAuNjUzNTEsIDAuODYwMjYsIDAuNjk0NjEsIDAuODk5NDcsIDEuMDMwNzUsIDAuODUxNTgsIDAuNzc4MTIsIDAuNzY0NDksIDAuODg4MzYsIDAuNzA0NjYsIDAuODU2MiwgMC44NjgyMiwgMC44NTg4LCAwLjgzODY0LCAwLjc3MjEyLCAwLjg1MzA4LCAwLjkzNjM3LCAwLjg3NTE0LCAwLjgyMzUyLCAwLjg1ODgsIDAuODU3MDEsIDAuNzYwMTMsIDAuODkwNTgsIDAuNzc1OTgsIDAuODE1NiwgMC44MjU2NSwgMC43ODExMiwgMC43Nzg5OSwgMC44OTM4NiwgMC44Mzg2NCwgMC44MTU2LCAwLjk0ODYsIDAuOTIzODgsIDAuOTYxODYsIDEuMDMwNzUsIDAuOTExMjMsIDAuOTQ4NiwgMC45MzI5OCwgMC44NzgsIDAuOTM5NDIsIDAuOTIzODgsIDAuODQ1OTYsIDAuOTYxODYsIDAuOTUxMTksIDEuMDMwNzUsIDAuOTIyLCAwLjg4Nzg3LCAwLjk1ODI5LCAwLjg4LCAwLjkzNTU5LCAwLjkzODU5LCAwLjc4ODE1LCAwLjkzNzU4LCAxLCAwLjg5MjE3LCAxLjAzNzM3LCAwLjkxMTIzLCAwLjkzOTY5LCAwLjc3NDg3LCAwLjg1NzY5LCAwLjg2Nzk5LCAxLjAzMDc1LCAwLjkxMTIzLCAwLjkzODU5LCAwLjkxMTIzLCAwLjg2Nzk5LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjg3ODMyLCAwLjk3OSwgMC44NzgzMiwgMC45NzksIDAuODc4MzIsIDAuOTc5LCAwLjc3NTEyLCAwLjg4MiwgMC45MjE5LCAxLCAwLjg5OTAzLCAxLCAxLCAxLCAwLjg3MzIxLCAwLjg3MzIxLCAwLjg3MzIxLCAxLCAxLjAyNywgMS4wMjcsIDEuMDI3LCAwLjg2ODQ3LCAwLjg2ODQ3LCAwLjc5MTIxLCAxLCAxLjEyNCwgMSwgMSwgMC43MzU3MiwgMC43MzU3MiwgMSwgMSwgMC44NTAzNCwgMSwgMSwgMSwgMSwgMC44ODQ2NSwgMSwgMSwgMSwgMC42NjksIDEsIDEuMzYxNDUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDQ4MjgsIDEsIDAuNzQ5NDgsIDAuNzUxODcsIDEuMDIwNTgsIDAuOTgzOTEsIDEuMDIxMTksIDEsIDEsIDEuMDYyMzMsIDEuMDg1OTUsIDEuMDg1OTUsIDEsIDEuMDg1OTUsIDEuMDg1OTUsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDUyMzMsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpjb25zdCBNeXJpYWRQcm9JdGFsaWNNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMiwKICBsaW5lR2FwOiAwLjIKfTsKY29uc3QgTXlyaWFkUHJvUmVndWxhckZhY3RvcnMgPSBbMS4zNjg5OCwgMSwgMSwgMC43NjMwNSwgMC44Mjc4NCwgMC45NDkzNSwgMC44OTM2NCwgMC45MjI0MSwgMC44OTA3MywgMC45MDcwNiwgMC45ODQ3MiwgMC44NTI4MywgMC44NTI4MywgMS4wNjY0LCAxLjAyMDU4LCAwLjc0NTA1LCAwLjkyMTksIDAuNzQ1MDUsIDEuMjM0NTYsIDAuOTIyNDEsIDAuOTIyNDEsIDAuOTIyNDEsIDAuOTIyNDEsIDAuOTIyNDEsIDAuOTIyNDEsIDAuOTIyNDEsIDAuOTIyNDEsIDAuOTIyNDEsIDAuOTIyNDEsIDAuNzQ1MDUsIDAuNzQ1MDUsIDEuMDIwNTgsIDEuMDIwNTgsIDEuMDIwNTgsIDAuNzMwMDIsIDAuNzI2MDEsIDAuOTE3NTUsIDAuODEyNiwgMC44MDMxNCwgMC45MjIyMiwgMC43Mzc2NCwgMC43OTcyNiwgMC44MzA1MSwgMC45MDI4NCwgMC44NjAyMywgMC43NCwgMC44MTI2LCAwLjg0ODY5LCAwLjk2NTE4LCAwLjkxMTE1LCAwLjg4NTgsIDAuNzk3NjEsIDAuODg1OCwgMC43NDQ5OCwgMC43MzkxNCwgMC44MTM2MywgMC44OTU5MSwgMC44MzY1OSwgMC44OTYzMywgMC44NTYwOCwgMC44MTExLCAwLjkwNTMxLCAxLjAyMjIsIDEuMjI3MzYsIDEuMDIyMiwgMS4yNzAxNCwgMC44OTkwMywgMC45MDA4OCwgMC44NjY2NywgMS4wMjMxLCAwLjg5NiwgMS4wMTQxMSwgMC45MDA4MywgMS4wNTA5OSwgMS4wMDUxMiwgMC45OTc5MywgMS4wNTMyNiwgMS4wOTM3NywgMC45MzgsIDEuMDYyMjYsIDEuMDAxMTksIDAuOTk3OTMsIDAuOTg3MTQsIDEuMDIzMSwgMS4wMTIzMSwgMC45ODE5NiwgMC43OTIsIDEuMTkxMzcsIDAuOTkwNzQsIDAuOTYyLCAxLjAxOTE1LCAwLjkyNiwgMC45NDIsIDAuODU2LCAwLjg1MDM0LCAwLjkyMDA2LCAwLjg1MDM0LCAxLjAyMDU4LCAwLjY5MDY3LCAwLjkyMjQxLCAwLjkyMjQxLCAwLjkyMjQxLCAwLjkyMjQxLCAwLjkyMDA2LCAwLjkzMzIsIDAuOTAwODgsIDAuOTE4ODIsIDAuOTM0ODQsIDAuNzUzMzksIDEuMDIwNTgsIDAuNTY4NjYsIDAuNTQzMjQsIDAuNzk1MTksIDEuMDg1OTUsIDEsIDEsIDAuOTAwODgsIDEsIDAuOTUzMjUsIDAuNzQ1MDUsIDAuOTAwODgsIDEsIDAuOTcxOTgsIDAuNzUzMzksIDAuOTEwMDksIDAuOTEwMDksIDAuOTEwMDksIDAuNjY0NjYsIDAuOTE3NTUsIDAuOTE3NTUsIDAuOTE3NTUsIDAuOTE3NTUsIDAuOTE3NTUsIDAuOTE3NTUsIDAuNzg4LCAwLjgwMzE0LCAwLjczNzY0LCAwLjczNzY0LCAwLjczNzY0LCAwLjczNzY0LCAwLjg2MDIzLCAwLjg2MDIzLCAwLjg2MDIzLCAwLjg2MDIzLCAwLjkyOTE1LCAwLjkxMTE1LCAwLjg4NTgsIDAuODg1OCwgMC44ODU4LCAwLjg4NTgsIDAuODg1OCwgMS4wMjA1OCwgMC44ODU4LCAwLjg5NTkxLCAwLjg5NTkxLCAwLjg5NTkxLCAwLjg5NTkxLCAwLjgxMTEsIDAuNzk2MTEsIDAuODk3MTMsIDAuODY2NjcsIDAuODY2NjcsIDAuODY2NjcsIDAuODY2NjcsIDAuODY2NjcsIDAuODY2NjcsIDAuODY5MzYsIDAuODk2LCAwLjkwMDgzLCAwLjkwMDgzLCAwLjkwMDgzLCAwLjkwMDgzLCAwLjg0MjI0LCAwLjg0MjI0LCAwLjg0MjI0LCAwLjg0MjI0LCAwLjk3Mjc2LCAwLjk5NzkzLCAwLjk4NzE0LCAwLjk4NzE0LCAwLjk4NzE0LCAwLjk4NzE0LCAwLjk4NzE0LCAxLjA4NTk1LCAwLjg5ODc2LCAwLjk5MDc0LCAwLjk5MDc0LCAwLjk5MDc0LCAwLjk5MDc0LCAwLjk0MiwgMS4wMjMxLCAwLjk0MiwgMC45MTc1NSwgMC44NjY2NywgMC45MTc1NSwgMC44NjY2NywgMC45MTc1NSwgMC44NjY2NywgMC44MDMxNCwgMC44OTYsIDAuODAzMTQsIDAuODk2LCAwLjgwMzE0LCAwLjg5NiwgMC44MDMxNCwgMC44OTYsIDAuOTIyMjIsIDAuOTMzNzIsIDAuOTI5MTUsIDEuMDE0MTEsIDAuNzM3NjQsIDAuOTAwODMsIDAuNzM3NjQsIDAuOTAwODMsIDAuNzM3NjQsIDAuOTAwODMsIDAuNzM3NjQsIDAuOTAwODMsIDAuNzM3NjQsIDAuOTAwODMsIDAuODMwNTEsIDEuMDA1MTIsIDAuODMwNTEsIDEuMDA1MTIsIDAuODMwNTEsIDEuMDA1MTIsIDEsIDEsIDAuOTAyODQsIDAuOTk3OTMsIDAuOTA5NzYsIDAuOTk3OTMsIDAuODYwMjMsIDAuODQyMjQsIDAuODYwMjMsIDAuODQyMjQsIDAuODYwMjMsIDAuODQyMjQsIDAuODYwMjMsIDEuMDUzMjYsIDAuODYwMjMsIDAuODQyMjQsIDAuODI4NzMsIDEuMDc0NjksIDAuNzQsIDEuMDkzNzcsIDEsIDEsIDAuOTM4LCAwLjg0ODY5LCAxLjA2MjI2LCAxLCAxLCAwLjg0ODY5LCAwLjgzNzA0LCAwLjg0ODY5LCAwLjgxNDQxLCAwLjg1NTg4LCAxLjA4OTI3LCAwLjkxMTE1LCAwLjk5NzkzLCAxLCAxLCAwLjkxMTE1LCAwLjk5NzkzLCAwLjkxODg3LCAwLjkwOTkxLCAwLjk5NzkzLCAwLjg4NTgsIDAuOTg3MTQsIDAuODg1OCwgMC45ODcxNCwgMC44ODU4LCAwLjk4NzE0LCAwLjg5NCwgMC45MTQzNCwgMC43NDQ5OCwgMC45ODE5NiwgMSwgMSwgMC43NDQ5OCwgMC45ODE5NiwgMC43MzkxNCwgMC43OTIsIDAuNzM5MTQsIDAuNzkyLCAxLCAxLCAwLjczOTE0LCAwLjc5MiwgMSwgMSwgMC44MTM2MywgMC45MDQsIDAuODEzNjMsIDEuMTkxMzcsIDAuODk1OTEsIDAuOTkwNzQsIDAuODk1OTEsIDAuOTkwNzQsIDAuODk1OTEsIDAuOTkwNzQsIDAuODk1OTEsIDAuOTkwNzQsIDAuODk1OTEsIDAuOTkwNzQsIDAuODk1OTEsIDAuOTkwNzQsIDAuODk2MzMsIDEuMDE5MTUsIDAuODExMSwgMC45NDIsIDAuODExMSwgMC45MDUzMSwgMC44NTYsIDAuOTA1MzEsIDAuODU2LCAwLjkwNTMxLCAwLjg1NiwgMSwgMC45MjI0MSwgMC45MTc1NSwgMC44NjY2NywgMC43ODgsIDAuODY5MzYsIDAuODg1OCwgMC44OTg3NiwgMSwgMSwgMC44MTM2MywgMS4xOTEzNywgMC45MDA4OCwgMC45MDA4OCwgMC45MDA4OCwgMC45MDA4OCwgMC45MDA4OCwgMC45MDA4OCwgMC45MDA4OCwgMC45MDA4OCwgMC45MDA4OCwgMC45MDM4OCwgMS4wMzkwMSwgMC45MjEzOCwgMC43ODEwNSwgMC43MTU0LCAwLjg2MTY5LCAwLjgwNTEzLCAwLjk0MDA3LCAwLjgyNTI4LCAwLjk4NjEyLCAxLjA2MjI2LCAwLjkxNzU1LCAwLjgxMjYsIDAuODE4ODQsIDAuOTI4MTksIDAuNzM3NjQsIDAuOTA1MzEsIDAuOTAyODQsIDAuODg1OCwgMC44NjAyMywgMC44MTI2LCAwLjkxMTcyLCAwLjk2NTE4LCAwLjkxMTE1LCAwLjgzMDg5LCAwLjg4NTgsIDAuODc3OTEsIDAuNzk3NjEsIDAuODkyOTcsIDAuODEzNjMsIDAuODgxNTcsIDAuODk5OTIsIDAuODU2MDgsIDAuODE5OTIsIDAuOTQzMDcsIDAuODYwMjMsIDAuODgxNTcsIDAuOTUzMDgsIDAuOTg2OTksIDAuOTk3OTMsIDEuMDYyMjYsIDAuOTU4MTcsIDAuOTUzMDgsIDAuOTczNTgsIDAuOTI4LCAwLjk4MDg4LCAwLjk4Njk5LCAwLjkyNzYxLCAwLjk5NzkzLCAwLjk2MDE3LCAxLjA2MjI2LCAwLjk4NiwgMC45NDQsIDAuOTU5NzgsIDAuOTM4LCAwLjk2NzA1LCAwLjk4NzE0LCAwLjgwNDQyLCAwLjk4OTcyLCAxLCAwLjg5NzYyLCAxLjA0NTUyLCAwLjk1ODE3LCAwLjk5MDA3LCAwLjg3MDY0LCAwLjkxODc5LCAwLjg4ODg4LCAxLjA2MjI2LCAwLjk1ODE3LCAwLjk4NzE0LCAwLjk1ODE3LCAwLjg4ODg4LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjg5NjMzLCAxLjAxOTE1LCAwLjg5NjMzLCAxLjAxOTE1LCAwLjg5NjMzLCAxLjAxOTE1LCAwLjgxMTEsIDAuOTQyLCAwLjkyMTksIDEsIDAuODk5MDMsIDEsIDEsIDEsIDAuOTMxNzMsIDAuOTMxNzMsIDAuOTMxNzMsIDEsIDEuMDYzMDQsIDEuMDYzMDQsIDEuMDY5MDQsIDAuODk5MDMsIDAuODk5MDMsIDAuODA1NDksIDEsIDEuMTU2LCAxLCAxLCAwLjc2NTc1LCAwLjc2NTc1LCAxLCAxLCAwLjcyNDU4LCAxLCAxLCAxLCAxLCAwLjkyMjQxLCAxLCAxLCAxLCAwLjYxOSwgMSwgMS4zNjE0NSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4wNzI1NywgMSwgMC43NDcwNSwgMC43MTExOSwgMS4wMjA1OCwgMS4wMjQsIDEuMDIxMTksIDEsIDEsIDEuMTUzNiwgMS4wODU5NSwgMS4wODU5NSwgMSwgMS4wODU5NSwgMS4wODU5NSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS4wNTYzOCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMV07CmNvbnN0IE15cmlhZFByb1JlZ3VsYXJNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMiwKICBsaW5lR2FwOiAwLjIKfTsKCjsvLyAuL3NyYy9jb3JlL3NlZ29ldWlfZmFjdG9ycy5qcwpjb25zdCBTZWdvZXVpQm9sZEZhY3RvcnMgPSBbMS43NjczOCwgMSwgMSwgMC45OTI5NywgMC45ODI0LCAxLjA0MDE2LCAxLjA2NDk3LCAxLjAzNDI0LCAwLjk3NTI5LCAxLjE3NjQ3LCAxLjIzMjAzLCAxLjEwODUsIDEuMTA4NSwgMS4xNjkzOSwgMS4yMTA3LCAwLjk3NTQsIDEuMjE0MDgsIDAuOTc1NCwgMS41OTU3OCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMC44MTM3OCwgMC44MTM3OCwgMS4yMTA3LCAxLjIxMDcsIDEuMjEwNywgMC43MTcwMywgMC45Nzg0NywgMC45NzM2MywgMC44ODc3NiwgMC44NjQxLCAxLjAyMDk2LCAwLjc5Nzk1LCAwLjg1MTMyLCAwLjkxNCwgMS4wNjA4NSwgMS4xNDA2LCAwLjgwMDcsIDAuODk4NTgsIDAuODM2OTMsIDEuMTQ4ODksIDEuMDkzOTgsIDAuOTc0ODksIDAuOTIwOTQsIDAuOTc0ODksIDAuOTAzOTksIDAuODQwNDEsIDAuOTU5MjMsIDEuMDAxMzUsIDEsIDEuMDY0NjcsIDAuOTgyNDMsIDAuOTA5OTYsIDAuOTkzNjEsIDEuMTA4NSwgMS41Njk0MiwgMS4xMDg1LCAxLjIxMDcsIDAuNzQ2MjcsIDAuOTQyODIsIDAuOTY3NTIsIDEuMDE1MTksIDAuODYzMDQsIDEuMDEzNTksIDAuOTcyNzgsIDEuMTUxMDMsIDEuMDEzNTksIDAuOTg1NjEsIDEuMDIyODUsIDEuMDIyODUsIDEuMDA1MjcsIDEuMDIyODUsIDEuMDMwMiwgMC45OTA0MSwgMS4wMDA4LCAxLjAxNTE5LCAxLjAxMzU5LCAxLjAyMjU4LCAwLjc5MTA0LCAxLjE2ODYyLCAwLjk5MDQxLCAwLjk3NDU0LCAxLjAyNTExLCAwLjk5Mjk4LCAwLjk2NzUyLCAwLjk1ODAxLCAwLjk0ODU2LCAxLjE2NTc5LCAwLjk0ODU2LCAxLjIxMDcsIDAuOTgyNCwgMS4wMzQyNCwgMS4wMzQyNCwgMSwgMS4wMzQyNCwgMS4xNjU3OSwgMC44NzI3LCAxLjM4NzEsIDEuMTg2MjIsIDEuMTA4MTgsIDEuMDQ0NzgsIDEuMjEwNywgMS4xODYyMiwgMC43NTE1NSwgMC45NDk5NCwgMS4yODgyNiwgMS4yMTQwOCwgMS4yMTQwOCwgMC45MTA1NiwgMSwgMC45MTU3MiwgMC45NzU0LCAwLjY0NjYzLCAxLjE4MzI4LCAxLjI0ODY2LCAxLjA0NDc4LCAxLjE0MTY5LCAxLjE1NzQ5LCAxLjE3Mzg5LCAwLjcxNzAzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjk3MzYzLCAwLjkzNTA2LCAwLjg2NDEsIDAuNzk3OTUsIDAuNzk3OTUsIDAuNzk3OTUsIDAuNzk3OTUsIDEuMTQwNiwgMS4xNDA2LCAxLjE0MDYsIDEuMTQwNiwgMS4wMjA5NiwgMS4wOTM5OCwgMC45NzQyNiwgMC45NzQyNiwgMC45NzQyNiwgMC45NzQyNiwgMC45NzQyNiwgMS4yMTA3LCAwLjk3NDg5LCAxLjAwMTM1LCAxLjAwMTM1LCAxLjAwMTM1LCAxLjAwMTM1LCAwLjkwOTk2LCAwLjkyMDk0LCAxLjAyNzk4LCAwLjk2NzUyLCAwLjk2NzUyLCAwLjk2NzUyLCAwLjk2NzUyLCAwLjk2NzUyLCAwLjk2NzUyLCAwLjkzMTM2LCAwLjg2MzA0LCAwLjk3Mjc4LCAwLjk3Mjc4LCAwLjk3Mjc4LCAwLjk3Mjc4LCAxLjAyMjg1LCAxLjAyMjg1LCAxLjAyMjg1LCAxLjAyMjg1LCAwLjk3MTIyLCAwLjk5MDQxLCAxLCAxLCAxLCAxLCAxLCAxLjI4ODI2LCAxLjAwMDgsIDAuOTkwNDEsIDAuOTkwNDEsIDAuOTkwNDEsIDAuOTkwNDEsIDAuOTY3NTIsIDEuMDE1MTksIDAuOTY3NTIsIDAuOTczNjMsIDAuOTY3NTIsIDAuOTczNjMsIDAuOTY3NTIsIDAuOTczNjMsIDAuOTY3NTIsIDAuODY0MSwgMC44NjMwNCwgMC44NjQxLCAwLjg2MzA0LCAwLjg2NDEsIDAuODYzMDQsIDAuODY0MSwgMC44NjMwNCwgMS4wMjA5NiwgMS4wMzA1NywgMS4wMjA5NiwgMS4wMzUxNywgMC43OTc5NSwgMC45NzI3OCwgMC43OTc5NSwgMC45NzI3OCwgMC43OTc5NSwgMC45NzI3OCwgMC43OTc5NSwgMC45NzI3OCwgMC43OTc5NSwgMC45NzI3OCwgMC45MTQsIDEuMDEzNTksIDAuOTE0LCAxLjAxMzU5LCAwLjkxNCwgMS4wMTM1OSwgMSwgMSwgMS4wNjA4NSwgMC45ODU2MSwgMS4wNjA4NSwgMS4wMDg3OSwgMS4xNDA2LCAxLjAyMjg1LCAxLjE0MDYsIDEuMDIyODUsIDEuMTQwNiwgMS4wMjI4NSwgMS4xNDA2LCAxLjAyMjg1LCAxLjE0MDYsIDEuMDIyODUsIDAuOTcxMzgsIDEuMDg2OTIsIDAuODAwNywgMS4wMjI4NSwgMSwgMSwgMS4wMDUyNywgMC44MzY5MywgMS4wMjI4NSwgMSwgMSwgMC44MzY5MywgMC45NDU1LCAwLjgzNjkzLCAwLjkwNDE4LCAwLjgzNjkzLCAxLjEzMDA1LCAxLjA5Mzk4LCAwLjk5MDQxLCAxLCAxLCAxLjA5Mzk4LCAwLjk5MDQxLCAwLjk2NjkyLCAxLjA5MjUxLCAwLjk5MDQxLCAwLjk3NDg5LCAxLjAwMDgsIDAuOTc0ODksIDEuMDAwOCwgMC45NzQ4OSwgMS4wMDA4LCAwLjkzOTk0LCAwLjk3OTMxLCAwLjkwMzk5LCAxLjAyMjU4LCAxLCAxLCAwLjkwMzk5LCAxLjAyMjU4LCAwLjg0MDQxLCAwLjc5MTA0LCAwLjg0MDQxLCAwLjc5MTA0LCAwLjg0MDQxLCAwLjc5MTA0LCAwLjg0MDQxLCAwLjc5MTA0LCAxLCAxLCAwLjk1OTIzLCAxLjA3MDM0LCAwLjk1OTIzLCAxLjE2ODYyLCAxLjAwMTM1LCAwLjk5MDQxLCAxLjAwMTM1LCAwLjk5MDQxLCAxLjAwMTM1LCAwLjk5MDQxLCAxLjAwMTM1LCAwLjk5MDQxLCAxLjAwMTM1LCAwLjk5MDQxLCAxLjAwMTM1LCAwLjk5MDQxLCAxLjA2NDY3LCAxLjAyNTExLCAwLjkwOTk2LCAwLjk2NzUyLCAwLjkwOTk2LCAwLjk5MzYxLCAwLjk1ODAxLCAwLjk5MzYxLCAwLjk1ODAxLCAwLjk5MzYxLCAwLjk1ODAxLCAxLjA3NzMzLCAxLjAzNDI0LCAwLjk3MzYzLCAwLjk2NzUyLCAwLjkzNTA2LCAwLjkzMTM2LCAwLjk3NDg5LCAxLjAwMDgsIDEsIDEsIDAuOTU5MjMsIDEuMTY4NjIsIDEuMTUxMDMsIDEuMTUxMDMsIDEuMDExNzMsIDEuMDM5NTksIDAuNzU5NTMsIDAuODEzNzgsIDAuNzk5MTIsIDEuMTUxMDMsIDEuMjE5OTQsIDAuOTUxNjEsIDAuODc4MTUsIDEuMDExNDksIDAuODE1MjUsIDAuNzY3NiwgMC45ODE2NywgMS4wMTEzNCwgMS4wMjU0NiwgMC44NDA5NywgMS4wMzA4OSwgMS4xODEwMiwgMC45NzM2MywgMC44ODc3NiwgMC44NTEzNCwgMC45NzgyNiwgMC43OTc5NSwgMC45OTM2MSwgMS4wNjA4NSwgMC45NzQ4OSwgMS4xNDA2LCAwLjg5ODU4LCAxLjAzODgsIDEuMTQ4ODksIDEuMDkzOTgsIDAuODYwMzksIDAuOTc0ODksIDEuMDU5NSwgMC45MjA5NCwgMC45NDc5MywgMC45NTkyMywgMC45MDk5NiwgMC45OTM0NiwgMC45ODI0MywgMS4wMjExMiwgMC45NTQ5MywgMS4xNDA2LCAwLjkwOTk2LCAxLjAzNTc0LCAxLjAyNTk3LCAxLjAwMDgsIDEuMTgxMDIsIDEuMDY2MjgsIDEuMDM1NzQsIDEuMDE5MiwgMS4wMTkzMiwgMS4wMDg4NiwgMC45NzUzMSwgMS4wMTA2LCAxLjAwMDgsIDEuMTMxODksIDEuMTgxMDIsIDEuMDIyNzcsIDAuOTg2ODMsIDEuMDAxNiwgMC45OTU2MSwgMS4wNzIzNywgMS4wMDA4LCAwLjkwNDM0LCAwLjk5OTIxLCAwLjkzODAzLCAwLjg5NjUsIDEuMjMwODUsIDEuMDY2MjgsIDEuMDQ5ODMsIDAuOTYyNjgsIDEuMDQ5OSwgMC45ODQzOSwgMS4xODEwMiwgMS4wNjYyOCwgMS4wMDA4LCAxLjA2NjI4LCAwLjk4NDM5LCAwLjc5Nzk1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjA5NDY2LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk3Mjc4LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjAyMDY1LCAxLCAxLCAxLCAxLCAxLCAxLCAxLjA2NDY3LCAxLjAyNTExLCAxLjA2NDY3LCAxLjAyNTExLCAxLjA2NDY3LCAxLjAyNTExLCAwLjkwOTk2LCAwLjk2NzUyLCAxLCAxLjIxNDA4LCAwLjg5OTAzLCAxLCAxLCAwLjc1MTU1LCAxLjA0Mzk0LCAxLjA0Mzk0LCAxLjA0Mzk0LCAxLjA0Mzk0LCAwLjk4NjMzLCAwLjk4NjMzLCAwLjk4NjMzLCAwLjczMDQ3LCAwLjczMDQ3LCAxLjIwNjQyLCAwLjkxMjExLCAxLjI1NjM1LCAxLjIyMiwgMS4wMjk1NiwgMS4wMzM3MiwgMS4wMzM3MiwgMC45NjAzOSwgMS4yNDYzMywgMSwgMS4xMjQ1NCwgMC45MzUwMywgMS4wMzQyNCwgMS4xOTY4NywgMS4wMzQyNCwgMSwgMSwgMSwgMC43NzEsIDEsIDEsIDEuMTU3NDksIDEuMTU3NDksIDEuMTU3NDksIDEuMTA5NDgsIDAuODYyNzksIDAuOTQ0MzQsIDAuODYyNzksIDAuOTQ0MzQsIDAuODYxODIsIDEsIDEsIDEuMTY4OTcsIDEsIDAuOTYwODUsIDAuOTAxMzcsIDEuMjEwNywgMS4xODQxNiwgMS4xMzk3MywgMC42OTgyNSwgMC45NzE2LCAyLjEwMzM5LCAxLjI5MDA0LCAxLjI5MDA0LCAxLjIxMTcyLCAxLjI5MDA0LCAxLjI5MDA0LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjQyNjAzLCAxLCAwLjk5ODYyLCAwLjk5ODYyLCAxLCAwLjg3MDI1LCAwLjg3MDI1LCAwLjg3MDI1LCAwLjg3MDI1LCAxLjE4ODc0LCAxLjQyNjAzLCAxLCAxLjQyNjAzLCAxLjQyNjAzLCAwLjk5ODYyLCAxLCAxLCAxLCAxLCAxLCAxLjI4ODYsIDEuMDQzMTUsIDEuMTUyOTYsIDEuMzQxNjMsIDEsIDEsIDEsIDEuMDkxOTMsIDEuMDkxOTMsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpjb25zdCBTZWdvZXVpQm9sZE1ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4zMzAwOCwKICBsaW5lR2FwOiAwCn07CmNvbnN0IFNlZ29ldWlCb2xkSXRhbGljRmFjdG9ycyA9IFsxLjc2NzM4LCAxLCAxLCAwLjk4OTQ2LCAxLjAzOTU5LCAxLjA0MDE2LCAxLjAyODA5LCAxLjAzNiwgMC45NzYzOSwgMS4xMDk1MywgMS4yMzIwMywgMS4xMTE0NCwgMS4xMTE0NCwgMS4xNjkzOSwgMS4yMTIzNywgMC45NzU0LCAxLjIxMjYxLCAwLjk3NTQsIDEuNTk3NTQsIDEuMDM2LCAxLjAzNiwgMS4wMzYsIDEuMDM2LCAxLjAzNiwgMS4wMzYsIDEuMDM2LCAxLjAzNiwgMS4wMzYsIDEuMDM2LCAwLjgxMzc4LCAwLjgxMzc4LCAxLjIxMjM3LCAxLjIxMjM3LCAxLjIxMjM3LCAwLjczNTQxLCAwLjk3ODQ3LCAwLjk3MzYzLCAwLjg5NzIzLCAwLjg3ODk3LCAxLjA0MjYsIDAuNzk0MjksIDAuODUyOTIsIDAuOTExNDksIDEuMDU4MTUsIDEuMTQwNiwgMC43OTYzMSwgMC45MDEyOCwgMC44Mzg1MywgMS4wNDM5NiwgMS4xMDYxNSwgMC45NzU1MiwgMC45NDQzNiwgMC45NzU1MiwgMC44ODY0MSwgMC44MDUyNywgMC45NjA4MywgMS4wMDEzNSwgMSwgMS4wNjc3NywgMC45ODE3LCAwLjkxMTQyLCAwLjk5MzYxLCAxLjExMTQ0LCAxLjU3MjkzLCAxLjExMTQ0LCAxLjIxMjM3LCAwLjc0NjI3LCAxLjMxODE4LCAxLjA2NTg1LCAwLjk3MDQyLCAwLjgzMDU1LCAwLjk3MDQyLCAwLjkzNTAzLCAxLjEyNjEsIDAuOTcwNDIsIDAuOTc5MjIsIDEuMTQyMzYsIDAuOTQ1NTIsIDEuMDEwNTQsIDEuMTQyMzYsIDEuMDI0NzEsIDAuOTc5MjIsIDAuOTQxNjUsIDAuOTcwNDIsIDAuOTcwNDIsIDEuMDI3NiwgMC43ODkyOSwgMS4xMjYxLCAwLjk3OTIyLCAwLjk1ODc0LCAxLjAyMTk3LCAwLjk4NTA3LCAwLjk2NzUyLCAwLjk3MTY4LCAwLjk1MTA3LCAxLjE2NTc5LCAwLjk1MTA3LCAxLjIxMjM3LCAxLjAzOTU5LCAxLjAzNiwgMS4wMzYsIDEsIDEuMDM2LCAxLjE2NTc5LCAwLjg3MzU3LCAxLjMxODE4LCAxLjE4NzU0LCAxLjI2NzgxLCAxLjA1MzU2LCAxLjIxMjM3LCAxLjE4NjIyLCAwLjc5NDg3LCAwLjk0OTk0LCAxLjI5MDA0LCAxLjI0MDQ3LCAxLjI0MDQ3LCAxLjMxODE4LCAxLCAwLjkxNDg0LCAwLjk3NTQsIDEuMzE4MTgsIDEuMTM0OSwgMS4yNDg2NiwgMS4wNTM1NiwgMS4xMzkzNCwgMS4xNTU3NCwgMS4xNzM4OSwgMC43MzU0MSwgMC45NzM2MywgMC45NzM2MywgMC45NzM2MywgMC45NzM2MywgMC45NzM2MywgMC45NzM2MywgMC45NDM4NSwgMC44Nzg5NywgMC43OTQyOSwgMC43OTQyOSwgMC43OTQyOSwgMC43OTQyOSwgMS4xNDA2LCAxLjE0MDYsIDEuMTQwNiwgMS4xNDA2LCAxLjA0MjYsIDEuMTA2MTUsIDAuOTc1NTIsIDAuOTc1NTIsIDAuOTc1NTIsIDAuOTc1NTIsIDAuOTc1NTIsIDEuMjEyMzcsIDAuOTc1NTIsIDEuMDAxMzUsIDEuMDAxMzUsIDEuMDAxMzUsIDEuMDAxMzUsIDAuOTExNDIsIDAuOTQ0MzYsIDAuOTg3MjEsIDEuMDY1ODUsIDEuMDY1ODUsIDEuMDY1ODUsIDEuMDY1ODUsIDEuMDY1ODUsIDEuMDY1ODUsIDAuOTY3MDUsIDAuODMwNTUsIDAuOTM1MDMsIDAuOTM1MDMsIDAuOTM1MDMsIDAuOTM1MDMsIDEuMTQyMzYsIDEuMTQyMzYsIDEuMTQyMzYsIDEuMTQyMzYsIDAuOTMxMjUsIDAuOTc5MjIsIDAuOTQxNjUsIDAuOTQxNjUsIDAuOTQxNjUsIDAuOTQxNjUsIDAuOTQxNjUsIDEuMjkwMDQsIDAuOTQxNjUsIDAuOTc5MjIsIDAuOTc5MjIsIDAuOTc5MjIsIDAuOTc5MjIsIDAuOTY3NTIsIDAuOTcwNDIsIDAuOTY3NTIsIDAuOTczNjMsIDEuMDY1ODUsIDAuOTczNjMsIDEuMDY1ODUsIDAuOTczNjMsIDEuMDY1ODUsIDAuODc4OTcsIDAuODMwNTUsIDAuODc4OTcsIDAuODMwNTUsIDAuODc4OTcsIDAuODMwNTUsIDAuODc4OTcsIDAuODMwNTUsIDEuMDQyNiwgMS4wMDMzLCAxLjA0MjYsIDAuOTcwNDIsIDAuNzk0MjksIDAuOTM1MDMsIDAuNzk0MjksIDAuOTM1MDMsIDAuNzk0MjksIDAuOTM1MDMsIDAuNzk0MjksIDAuOTM1MDMsIDAuNzk0MjksIDAuOTM1MDMsIDAuOTExNDksIDAuOTcwNDIsIDAuOTExNDksIDAuOTcwNDIsIDAuOTExNDksIDAuOTcwNDIsIDEsIDEsIDEuMDU4MTUsIDAuOTc5MjIsIDEuMDU4MTUsIDAuOTc5MjIsIDEuMTQwNiwgMS4xNDIzNiwgMS4xNDA2LCAxLjE0MjM2LCAxLjE0MDYsIDEuMTQyMzYsIDEuMTQwNiwgMS4xNDIzNiwgMS4xNDA2LCAxLjE0MjM2LCAwLjk3NDQxLCAxLjA0MzAyLCAwLjc5NjMxLCAxLjAxNTgyLCAxLCAxLCAxLjAxMDU0LCAwLjgzODUzLCAxLjE0MjM2LCAxLCAxLCAwLjgzODUzLCAxLjA5MTI1LCAwLjgzODUzLCAwLjkwNDE4LCAwLjgzODUzLCAxLjE5NTA4LCAxLjEwNjE1LCAwLjk3OTIyLCAxLCAxLCAxLjEwNjE1LCAwLjk3OTIyLCAxLjAxMDM0LCAxLjEwNDY2LCAwLjk3OTIyLCAwLjk3NTUyLCAwLjk0MTY1LCAwLjk3NTUyLCAwLjk0MTY1LCAwLjk3NTUyLCAwLjk0MTY1LCAwLjkxNjAyLCAwLjkxOTgxLCAwLjg4NjQxLCAxLjAyNzYsIDEsIDEsIDAuODg2NDEsIDEuMDI3NiwgMC44MDUyNywgMC43ODkyOSwgMC44MDUyNywgMC43ODkyOSwgMC44MDUyNywgMC43ODkyOSwgMC44MDUyNywgMC43ODkyOSwgMSwgMSwgMC45NjA4MywgMS4wNTQwMywgMC45NTkyMywgMS4xNjg2MiwgMS4wMDEzNSwgMC45NzkyMiwgMS4wMDEzNSwgMC45NzkyMiwgMS4wMDEzNSwgMC45NzkyMiwgMS4wMDEzNSwgMC45NzkyMiwgMS4wMDEzNSwgMC45NzkyMiwgMS4wMDEzNSwgMC45NzkyMiwgMS4wNjc3NywgMS4wMjE5NywgMC45MTE0MiwgMC45Njc1MiwgMC45MTE0MiwgMC45OTM2MSwgMC45NzE2OCwgMC45OTM2MSwgMC45NzE2OCwgMC45OTM2MSwgMC45NzE2OCwgMS4yMzE5OSwgMS4wMzYsIDAuOTczNjMsIDEuMDY1ODUsIDAuOTQzODUsIDAuOTY3MDUsIDAuOTc1NTIsIDAuOTQxNjUsIDEsIDEsIDAuOTYwODMsIDEuMTI2MSwgMS4zMTgxOCwgMS4zMTgxOCwgMS4zMTgxOCwgMS4zMTgxOCwgMS4zMTgxOCwgMS4zMTgxOCwgMS4zMTgxOCwgMS4zMTgxOCwgMS4zMTgxOCwgMC45NTE2MSwgMS4yNzEyNiwgMS4wMDgxMSwgMC44MzI4NCwgMC43NzcwMiwgMC45OTEzNywgMC45NTI1MywgMS4wMzQ3LCAwLjg2MTQyLCAxLjA3MjA1LCAxLjE0MjM2LCAwLjk3MzYzLCAwLjg5NzIzLCAwLjg2ODY5LCAxLjA5ODE4LCAwLjc5NDI5LCAwLjk5MzYxLCAxLjA1ODE1LCAwLjk3NTUyLCAxLjE0MDYsIDAuOTAxMjgsIDEuMDY2NjIsIDEuMDQzOTYsIDEuMTA2MTUsIDAuODQ5MTgsIDAuOTc1NTIsIDEuMDQ2OTQsIDAuOTQ0MzYsIDAuOTgwMTUsIDAuOTYwODMsIDAuOTExNDIsIDEuMDAzNTYsIDAuOTgxNywgMS4wMTk0NSwgMC45ODk5OSwgMS4xNDA2LCAwLjkxMTQyLCAxLjA0OTYxLCAwLjk4OTgsIDEuMDA2MzksIDEuMTQyMzYsIDEuMDc1MTQsIDEuMDQ5NjEsIDAuOTk2MDcsIDEuMDI4OTcsIDEuMDA4LCAwLjk4OTgsIDAuOTUxMzQsIDEuMDA2MzksIDEuMTExMjEsIDEuMTQyMzYsIDEuMDA1MTgsIDAuOTc5ODEsIDEuMDIxODYsIDEsIDEuMDg1NzgsIDAuOTQxNjUsIDAuOTkzMTQsIDAuOTgzODcsIDAuOTMwMjgsIDAuOTMzNzcsIDEuMzUxMjUsIDEuMDc1MTQsIDEuMTA2ODcsIDAuOTM0OTEsIDEuMDQyMzIsIDEuMDAzNTEsIDEuMTQyMzYsIDEuMDc1MTQsIDAuOTQxNjUsIDEuMDc1MTQsIDEuMDAzNTEsIDAuNzk0MjksIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDkwOTcsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTM1MDMsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTY2MDksIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDY3NzcsIDEuMDIxOTcsIDEuMDY3NzcsIDEuMDIxOTcsIDEuMDY3NzcsIDEuMDIxOTcsIDAuOTExNDIsIDAuOTY3NTIsIDEsIDEuMjEyNjEsIDAuODk5MDMsIDEsIDEsIDAuNzUxNTUsIDEuMDQ3NDUsIDEuMDQ3NDUsIDEuMDQ3NDUsIDEuMDQzOTQsIDAuOTg2MzMsIDAuOTg2MzMsIDAuOTg2MzMsIDAuNzI5NTksIDAuNzI5NTksIDEuMjA1MDIsIDAuOTE0MDYsIDEuMjY1MTQsIDEuMjIyLCAxLjAyOTU2LCAxLjAzMzcyLCAxLjAzMzcyLCAwLjk2MDM5LCAxLjI0NjMzLCAxLCAxLjA5MTI1LCAwLjkzMzI3LCAxLjAzMzM2LCAxLjE2NTQxLCAxLjAzNiwgMSwgMSwgMSwgMC43NzEsIDEsIDEsIDEuMTU1NzQsIDEuMTU1NzQsIDEuMTU1NzQsIDEuMTU1NzQsIDAuODYzNjQsIDAuOTQ0MzQsIDAuODYyNzksIDAuOTQ0MzQsIDAuODYyMjQsIDEsIDEsIDEuMTY3OTgsIDEsIDAuOTYwODUsIDAuOTAwNjgsIDEuMjEyMzcsIDEuMTg0MTYsIDEuMTM5MDQsIDAuNjk4MjUsIDAuOTcxNiwgMi4xMDMzOSwgMS4yOTAwNCwgMS4yOTAwNCwgMS4yMTMzOSwgMS4yOTAwNCwgMS4yOTAwNCwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMS40MjYwMywgMSwgMC45OTg2MiwgMC45OTg2MiwgMSwgMC44NzAyNSwgMC44NzAyNSwgMC44NzAyNSwgMC44NzAyNSwgMS4xODc3NSwgMS40MjYwMywgMSwgMS40MjYwMywgMS40MjYwMywgMC45OTg2MiwgMSwgMSwgMSwgMSwgMSwgMS4yODg2LCAxLjA0MzE1LCAxLjE1Mjk2LCAxLjM0MTYzLCAxLCAxLCAxLCAxLjEzMjY5LCAxLjEzMjY5LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxXTsKY29uc3QgU2Vnb2V1aUJvbGRJdGFsaWNNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMzMwMDgsCiAgbGluZUdhcDogMAp9Owpjb25zdCBTZWdvZXVpSXRhbGljRmFjdG9ycyA9IFsxLjc2NzM4LCAxLCAxLCAwLjk4OTQ2LCAxLjE0NzYzLCAxLjA1MzY1LCAxLjA2MjM0LCAwLjk2OTI3LCAwLjkyNTg2LCAxLjE1MzczLCAxLjE4NDE0LCAwLjkxMzQ5LCAwLjkxMzQ5LCAxLjA3NDAzLCAxLjE3MzA4LCAwLjc4MzgzLCAxLjIwMDg4LCAwLjc4MzgzLCAxLjQyNTMxLCAwLjk2OTI3LCAwLjk2OTI3LCAwLjk2OTI3LCAwLjk2OTI3LCAwLjk2OTI3LCAwLjk2OTI3LCAwLjk2OTI3LCAwLjk2OTI3LCAwLjk2OTI3LCAwLjk2OTI3LCAwLjc4MzgzLCAwLjc4MzgzLCAxLjE3MzA4LCAxLjE3MzA4LCAxLjE3MzA4LCAwLjc3MzQ5LCAwLjk0NTY1LCAwLjk0NzI5LCAwLjg1OTQ0LCAwLjg4NTA2LCAwLjk4NTgsIDAuNzQ4MTcsIDAuODAwMTYsIDAuODg0NDksIDAuOTgwMzksIDAuOTU3ODIsIDAuNjkyMzgsIDAuODk4OTgsIDAuODMyMzEsIDAuOTgxODMsIDEuMDM5ODksIDAuOTY5MjQsIDAuODYyMzcsIDAuOTY5MjQsIDAuODA1OTUsIDAuNzQ1MjQsIDAuODYwOTEsIDAuOTU0MDIsIDAuOTQxNDMsIDAuOTg0NDgsIDAuODg1OCwgMC44MzA4OSwgMC45MzI4NSwgMS4wOTQ5LCAxLjM5MDE2LCAxLjA5NDksIDEuNDU5OTQsIDAuNzQ2MjcsIDEuMDQ4MzksIDAuOTc0NTQsIDAuOTc0NTQsIDAuODcyMDcsIDAuOTc0NTQsIDAuODc1MzMsIDEuMDYxNTEsIDAuOTc0NTQsIDEuMDAxNzYsIDEuMTY0ODQsIDEuMDgxMzIsIDAuOTgwNDcsIDEuMTY0ODQsIDEuMDI5ODksIDEuMDEwNTQsIDAuOTYyMjUsIDAuOTc0NTQsIDAuOTc0NTQsIDEuMDY1OTgsIDAuNzkwMDQsIDEuMTYzNDQsIDEuMDAzNTEsIDAuOTQ2MjksIDAuOTk3MywgMC45MTAxNiwgMC45Njc3NywgMC45MDQzLCAwLjkxMDgyLCAwLjkyNDgxLCAwLjkxMDgyLCAxLjE3MzA4LCAwLjk1NzQ4LCAwLjk2OTI3LCAwLjk2OTI3LCAxLCAwLjk2OTI3LCAwLjkyNDgxLCAwLjgwNTk3LCAxLjA0ODM5LCAxLjIzMzkzLCAxLjE3ODEsIDAuOTI0NSwgMS4xNzMwOCwgMS4yMDgwOCwgMC42MzIxOCwgMC45NDI2MSwgMS4yNDgyMiwgMS4wOTk3MSwgMS4wOTk3MSwgMS4wNDgzOSwgMSwgMC44NTI3MywgMC43ODAzMiwgMS4wNDgzOSwgMS4wOTk3MSwgMS4yMjMyNiwgMC45MjQ1LCAxLjA5ODM2LCAxLjEzNTI1LCAxLjE1MjIyLCAwLjcwNDI0LCAwLjk0NzI5LCAwLjk0NzI5LCAwLjk0NzI5LCAwLjk0NzI5LCAwLjk0NzI5LCAwLjk0NzI5LCAwLjg1NDk4LCAwLjg4NTA2LCAwLjc0ODE3LCAwLjc0ODE3LCAwLjc0ODE3LCAwLjc0ODE3LCAwLjk1NzgyLCAwLjk1NzgyLCAwLjk1NzgyLCAwLjk1NzgyLCAwLjk4NTgsIDEuMDM5ODksIDAuOTY5MjQsIDAuOTY5MjQsIDAuOTY5MjQsIDAuOTY5MjQsIDAuOTY5MjQsIDEuMTczMDgsIDAuOTY5MjQsIDAuOTU0MDIsIDAuOTU0MDIsIDAuOTU0MDIsIDAuOTU0MDIsIDAuODMwODksIDAuODYyMzcsIDAuODg0MDksIDAuOTc0NTQsIDAuOTc0NTQsIDAuOTc0NTQsIDAuOTc0NTQsIDAuOTc0NTQsIDAuOTc0NTQsIDAuOTI5MTYsIDAuODcyMDcsIDAuODc1MzMsIDAuODc1MzMsIDAuODc1MzMsIDAuODc1MzMsIDAuOTMxNDYsIDAuOTMxNDYsIDAuOTMxNDYsIDAuOTMxNDYsIDAuOTM4NTQsIDEuMDEwNTQsIDAuOTYyMjUsIDAuOTYyMjUsIDAuOTYyMjUsIDAuOTYyMjUsIDAuOTYyMjUsIDEuMjQ4MjIsIDAuODc2MSwgMS4wMDM1MSwgMS4wMDM1MSwgMS4wMDM1MSwgMS4wMDM1MSwgMC45Njc3NywgMC45NzQ1NCwgMC45Njc3NywgMC45NDcyOSwgMC45NzQ1NCwgMC45NDcyOSwgMC45NzQ1NCwgMC45NDcyOSwgMC45NzQ1NCwgMC44ODUwNiwgMC44NzIwNywgMC44ODUwNiwgMC44NzIwNywgMC44ODUwNiwgMC44NzIwNywgMC44ODUwNiwgMC44NzIwNywgMC45ODU4LCAwLjk1MzkxLCAwLjk4NTgsIDAuOTc0NTQsIDAuNzQ4MTcsIDAuODc1MzMsIDAuNzQ4MTcsIDAuODc1MzMsIDAuNzQ4MTcsIDAuODc1MzMsIDAuNzQ4MTcsIDAuODc1MzMsIDAuNzQ4MTcsIDAuODc1MzMsIDAuODg0NDksIDAuOTc0NTQsIDAuODg0NDksIDAuOTc0NTQsIDAuODg0NDksIDAuOTc0NTQsIDEsIDEsIDAuOTgwMzksIDEuMDAxNzYsIDAuOTgwMzksIDEuMDAxNzYsIDAuOTU3ODIsIDAuOTMxNDYsIDAuOTU3ODIsIDAuOTMxNDYsIDAuOTU3ODIsIDAuOTMxNDYsIDAuOTU3ODIsIDEuMTY0ODQsIDAuOTU3ODIsIDAuOTMxNDYsIDAuODQ0MjEsIDEuMTI3NjEsIDAuNjkyMzgsIDEuMDgxMzIsIDEsIDEsIDAuOTgwNDcsIDAuODMyMzEsIDEuMTY0ODQsIDEsIDEsIDAuODQ3MjMsIDEuMDQ4NjEsIDAuODQ3MjMsIDAuNzg3NTUsIDAuODMyMzEsIDEuMjM3MzYsIDEuMDM5ODksIDEuMDEwNTQsIDEsIDEsIDEuMDM5ODksIDEuMDEwNTQsIDAuOTg1NywgMS4wMzg0OSwgMS4wMTA1NCwgMC45NjkyNCwgMC45NjIyNSwgMC45NjkyNCwgMC45NjIyNSwgMC45NjkyNCwgMC45NjIyNSwgMC45MjM4MywgMC45MDE3MSwgMC44MDU5NSwgMS4wNjU5OCwgMSwgMSwgMC44MDU5NSwgMS4wNjU5OCwgMC43NDUyNCwgMC43OTAwNCwgMC43NDUyNCwgMC43OTAwNCwgMC43NDUyNCwgMC43OTAwNCwgMC43NDUyNCwgMC43OTAwNCwgMSwgMSwgMC44NjA5MSwgMS4wMjc1OSwgMC44NTc3MSwgMS4xNjM0NCwgMC45NTQwMiwgMS4wMDM1MSwgMC45NTQwMiwgMS4wMDM1MSwgMC45NTQwMiwgMS4wMDM1MSwgMC45NTQwMiwgMS4wMDM1MSwgMC45NTQwMiwgMS4wMDM1MSwgMC45NTQwMiwgMS4wMDM1MSwgMC45ODQ0OCwgMC45OTczLCAwLjgzMDg5LCAwLjk2Nzc3LCAwLjgzMDg5LCAwLjkzMjg1LCAwLjkwNDMsIDAuOTMyODUsIDAuOTA0MywgMC45MzI4NSwgMC45MDQzLCAxLjMxODY4LCAwLjk2OTI3LCAwLjk0NzI5LCAwLjk3NDU0LCAwLjg1NDk4LCAwLjkyOTE2LCAwLjk2OTI0LCAwLjg3NjEsIDEsIDEsIDAuODYwOTEsIDEuMTYzNDQsIDEuMDQ4MzksIDEuMDQ4MzksIDEuMDQ4MzksIDEuMDQ4MzksIDEuMDQ4MzksIDEuMDQ4MzksIDEuMDQ4MzksIDEuMDQ4MzksIDEuMDQ4MzksIDAuODE5NjUsIDAuODE5NjUsIDAuOTQ3MjksIDAuNzgwMzIsIDAuNzEwMjIsIDAuOTA4ODMsIDAuODQxNzEsIDAuOTk4NzcsIDAuNzc1OTYsIDEuMDU3MzQsIDEuMiwgMC45NDcyOSwgMC44NTk0NCwgMC44Mjc5MSwgMC45NjA3LCAwLjc0ODE3LCAwLjkzMjg1LCAwLjk4MDM5LCAwLjk2OTI0LCAwLjk1NzgyLCAwLjg5ODk4LCAwLjk4MzE2LCAwLjk4MTgzLCAxLjAzOTg5LCAwLjc4NjE0LCAwLjk2OTI0LCAwLjk3NjQyLCAwLjg2MjM3LCAwLjg2MDc1LCAwLjg2MDkxLCAwLjgzMDg5LCAwLjkwMDgyLCAwLjg4NTgsIDAuOTcyOTYsIDEuMDEyODQsIDAuOTU3ODIsIDAuODMwODksIDEuMDk3NiwgMS4wNCwgMS4wMzM0MiwgMS4yLCAxLjA2NzUsIDEuMDk3NiwgMC45ODIwNSwgMS4wMzgwOSwgMS4wNTA5NywgMS4wNCwgMC45NTM2NCwgMS4wMzM0MiwgMS4wNTQwMSwgMS4yLCAxLjAyMTQ4LCAxLjAxMTksIDEuMDQ3MjQsIDEuMDEyNywgMS4wMjczMiwgMC45NjIyNSwgMC44OTY1LCAwLjk3NzgzLCAwLjkzNTc0LCAwLjk0ODE4LCAxLjMwNjc5LCAxLjA2NzUsIDEuMTE4MjYsIDAuOTk4MjEsIDEuMDU1NywgMS4wMzI2LCAxLjIsIDEuMDY3NSwgMC45NjIyNSwgMS4wNjc1LCAxLjAzMjYsIDAuNzQ4MTcsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDM3NTQsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuODc1MzMsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTg3MDUsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTg0NDgsIDAuOTk3MywgMC45ODQ0OCwgMC45OTczLCAwLjk4NDQ4LCAwLjk5NzMsIDAuODMwODksIDAuOTY3NzcsIDEsIDEuMjAwODgsIDAuODk5MDMsIDEsIDEsIDAuNzUxNTUsIDAuOTQ5NDUsIDAuOTQ5NDUsIDAuOTQ5NDUsIDAuOTQ5NDUsIDEuMTIzMTcsIDEuMTIzMTcsIDEuMTIzMTcsIDAuNjc2MDMsIDAuNjc2MDMsIDEuMTU2MjEsIDAuNzM1ODQsIDEuMjExOTEsIDEuMjIxMzUsIDEuMDY0ODMsIDAuOTQ4NjgsIDAuOTQ4NjgsIDAuOTU5OTYsIDEuMjQ2MzMsIDEsIDEuMDc0OTcsIDAuODc3MDksIDAuOTY5MjcsIDEuMDE0NzMsIDAuOTY5MjcsIDEsIDEsIDEsIDAuNzcyOTUsIDEsIDEsIDEuMDk4MzYsIDEuMDk4MzYsIDEuMDk4MzYsIDEuMDE1MjIsIDAuODYzMjEsIDAuOTQ0MzQsIDAuODY0OSwgMC45NDQzNCwgMC44NjE4MiwgMSwgMSwgMS4wODMsIDEsIDAuOTE1NzgsIDAuODY0MzgsIDEuMTczMDgsIDEuMTg0MTYsIDEuMTQ1ODksIDAuNjk4MjUsIDAuOTc2MjIsIDEuOTY3OTEsIDEuMjQ4MjIsIDEuMjQ4MjIsIDEuMTczMDgsIDEuMjQ4MjIsIDEuMjQ4MjIsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuNDI2MDMsIDEsIDAuOTk4NjIsIDAuOTk4NjIsIDEsIDAuODcwMjUsIDAuODcwMjUsIDAuODcwMjUsIDAuODcwMjUsIDEuMTc5ODQsIDEuNDI2MDMsIDEsIDEuNDI2MDMsIDEuNDI2MDMsIDAuOTk4NjIsIDEsIDEsIDEsIDEsIDEsIDEuMjg4NiwgMS4wNDMxNSwgMS4xNTI5NiwgMS4zNDE2MywgMSwgMSwgMSwgMS4xMDc0MiwgMS4xMDc0MiwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMSwgMV07CmNvbnN0IFNlZ29ldWlJdGFsaWNNZXRyaWNzID0gewogIGxpbmVIZWlnaHQ6IDEuMzMwMDgsCiAgbGluZUdhcDogMAp9Owpjb25zdCBTZWdvZXVpUmVndWxhckZhY3RvcnMgPSBbMS43NjczOCwgMSwgMSwgMC45ODU5NCwgMS4wMjI4NSwgMS4xMDQ1NCwgMS4wNjIzNCwgMC45NjkyNywgMC45MjAzNywgMS4xOTk4NSwgMS4yMDQ2LCAwLjkwNjE2LCAwLjkwNjE2LCAxLjA3MTUyLCAxLjE3MTQsIDAuNzgwMzIsIDEuMjAwODgsIDAuNzgwMzIsIDEuNDAyNDYsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuOTY5MjcsIDAuNzgwMzIsIDAuNzgwMzIsIDEuMTcxNCwgMS4xNzE0LCAxLjE3MTQsIDAuODA1OTcsIDAuOTQwODQsIDAuOTY3MDYsIDAuODU5NDQsIDAuODU3MzQsIDAuOTcwOTMsIDAuNzU4NDIsIDAuNzk5MzYsIDAuODgxOTgsIDAuOTgzMSwgMC45NTc4MiwgMC43MTM4NywgMC44Njk2OSwgMC44NDYzNiwgMS4wNzc5NiwgMS4wMzU4NCwgMC45NjkyNCwgMC44Mzk2OCwgMC45NjkyNCwgMC44MjgyNiwgMC43OTY0OSwgMC44NTc3MSwgMC45NTEzMiwgMC45MzExOSwgMC45ODk2NSwgMC44ODQzMywgMC44Mjg3LCAwLjkzMzY1LCAxLjA4NjEyLCAxLjM2MzgsIDEuMDg2MTIsIDEuNDU3ODYsIDAuNzQ2MjcsIDAuODA0OTksIDAuOTE0ODQsIDEuMDU3MDcsIDAuOTIzODMsIDEuMDU4ODIsIDAuOTQwMywgMS4xMjY1NCwgMS4wNTg4MiwgMS4wMTc1NiwgMS4wOTAxMSwgMS4wOTAxMSwgMC45OTQxNCwgMS4wOTAxMSwgMS4wMzQsIDEuMDE3NTYsIDEuMDUzNTYsIDEuMDU3MDcsIDEuMDU4ODIsIDEuMDQzOTksIDAuODQ4NjMsIDEuMjE5NjgsIDEuMDE3NTYsIDAuOTU4MDEsIDEuMDAwNjgsIDAuOTE3OTcsIDAuOTY3NzcsIDAuOTA0MywgMC45MDM1MSwgMC45MjEwNSwgMC45MDM1MSwgMS4xNzE0LCAwLjg1MzM3LCAwLjk2OTI3LCAwLjk2OTI3LCAwLjk5OTEyLCAwLjk2OTI3LCAwLjkyMTA1LCAwLjgwNTk3LCAxLjI0MzQsIDEuMjA4MDgsIDEuMDU5MzcsIDAuOTA5NTcsIDEuMTcxNCwgMS4yMDgwOCwgMC43NTE1NSwgMC45NDI2MSwgMS4yNDY0NCwgMS4wOTk3MSwgMS4wOTk3MSwgMC44NDc1MSwgMSwgMC44NTI3MywgMC43ODAzMiwgMC42MTU4NCwgMS4wNTQyNSwgMS4xNzkxNCwgMC45MDk1NywgMS4wODY2NSwgMS4xMTU5MywgMS4xNDE2OSwgMC43MzM4MSwgMC45NjcwNiwgMC45NjcwNiwgMC45NjcwNiwgMC45NjcwNiwgMC45NjcwNiwgMC45NjcwNiwgMC44NjAzNSwgMC44NTczNCwgMC43NTg0MiwgMC43NTg0MiwgMC43NTg0MiwgMC43NTg0MiwgMC45NTc4MiwgMC45NTc4MiwgMC45NTc4MiwgMC45NTc4MiwgMC45NzA5MywgMS4wMzU4NCwgMC45NjkyNCwgMC45NjkyNCwgMC45NjkyNCwgMC45NjkyNCwgMC45NjkyNCwgMS4xNzE0LCAwLjk2OTI0LCAwLjk1MTMyLCAwLjk1MTMyLCAwLjk1MTMyLCAwLjk1MTMyLCAwLjgyODcsIDAuODM5NjgsIDAuODkwNDksIDAuOTE0ODQsIDAuOTE0ODQsIDAuOTE0ODQsIDAuOTE0ODQsIDAuOTE0ODQsIDAuOTE0ODQsIDAuOTM1NzUsIDAuOTIzODMsIDAuOTQwMywgMC45NDAzLCAwLjk0MDMsIDAuOTQwMywgMC44NzE3LCAwLjg3MTcsIDAuODcxNywgMC44NzE3LCAxLjAwNTI3LCAxLjAxNzU2LCAxLjA1MzU2LCAxLjA1MzU2LCAxLjA1MzU2LCAxLjA1MzU2LCAxLjA1MzU2LCAxLjI0NjQ0LCAwLjk1OTIzLCAxLjAxNzU2LCAxLjAxNzU2LCAxLjAxNzU2LCAxLjAxNzU2LCAwLjk2Nzc3LCAxLjA1NzA3LCAwLjk2Nzc3LCAwLjk2NzA2LCAwLjkxNDg0LCAwLjk2NzA2LCAwLjkxNDg0LCAwLjk2NzA2LCAwLjkxNDg0LCAwLjg1NzM0LCAwLjkyMzgzLCAwLjg1NzM0LCAwLjkyMzgzLCAwLjg1NzM0LCAwLjkyMzgzLCAwLjg1NzM0LCAwLjkyMzgzLCAwLjk3MDkzLCAxLjA5NjksIDAuOTcwOTMsIDEuMDU4ODIsIDAuNzU4NDIsIDAuOTQwMywgMC43NTg0MiwgMC45NDAzLCAwLjc1ODQyLCAwLjk0MDMsIDAuNzU4NDIsIDAuOTQwMywgMC43NTg0MiwgMC45NDAzLCAwLjg4MTk4LCAxLjA1ODgyLCAwLjg4MTk4LCAxLjA1ODgyLCAwLjg4MTk4LCAxLjA1ODgyLCAxLCAxLCAwLjk4MzEsIDEuMDE3NTYsIDAuOTgzMSwgMS4wMTc1NiwgMC45NTc4MiwgMC44NzE3LCAwLjk1NzgyLCAwLjg3MTcsIDAuOTU3ODIsIDAuODcxNywgMC45NTc4MiwgMS4wOTAxMSwgMC45NTc4MiwgMC44NzE3LCAwLjg0Nzg0LCAxLjExNTUxLCAwLjcxMzg3LCAxLjA5MDExLCAxLCAxLCAwLjk5NDE0LCAwLjg0NjM2LCAxLjA5MDExLCAxLCAxLCAwLjg0NjM2LCAxLjA1MzYsIDAuODQ2MzYsIDAuOTQyOTgsIDAuODQ2MzYsIDEuMjMyOTcsIDEuMDM1ODQsIDEuMDE3NTYsIDEsIDEsIDEuMDM1ODQsIDEuMDE3NTYsIDEuMDAzMjMsIDEuMDM0NDQsIDEuMDE3NTYsIDAuOTY5MjQsIDEuMDUzNTYsIDAuOTY5MjQsIDEuMDUzNTYsIDAuOTY5MjQsIDEuMDUzNTYsIDAuOTMwNjYsIDAuOTgyOTMsIDAuODI4MjYsIDEuMDQzOTksIDEsIDEsIDAuODI4MjYsIDEuMDQzOTksIDAuNzk2NDksIDAuODQ4NjMsIDAuNzk2NDksIDAuODQ4NjMsIDAuNzk2NDksIDAuODQ4NjMsIDAuNzk2NDksIDAuODQ4NjMsIDEsIDEsIDAuODU3NzEsIDEuMTczMTgsIDAuODU3NzEsIDEuMjE5NjgsIDAuOTUxMzIsIDEuMDE3NTYsIDAuOTUxMzIsIDEuMDE3NTYsIDAuOTUxMzIsIDEuMDE3NTYsIDAuOTUxMzIsIDEuMDE3NTYsIDAuOTUxMzIsIDEuMDE3NTYsIDAuOTUxMzIsIDEuMDE3NTYsIDAuOTg5NjUsIDEuMDAwNjgsIDAuODI4NywgMC45Njc3NywgMC44Mjg3LCAwLjkzMzY1LCAwLjkwNDMsIDAuOTMzNjUsIDAuOTA0MywgMC45MzM2NSwgMC45MDQzLCAxLjA4NTcxLCAwLjk2OTI3LCAwLjk2NzA2LCAwLjkxNDg0LCAwLjg2MDM1LCAwLjkzNTc1LCAwLjk2OTI0LCAwLjk1OTIzLCAxLCAxLCAwLjg1NzcxLCAxLjIxOTY4LCAxLjExNDM3LCAxLjExNDM3LCAwLjkzMTA5LCAwLjkxMjAyLCAwLjYwNDExLCAwLjg0MTY0LCAwLjU1NTcyLCAxLjAxMTczLCAwLjk3MzYxLCAwLjgxODE4LCAwLjgxODE4LCAwLjk2NjM1LCAwLjc4MDMyLCAwLjcyNzI3LCAwLjkyMzY2LCAwLjk4NjAxLCAxLjAzNDA1LCAwLjc3OTY4LCAxLjA5Nzk5LCAxLjIsIDAuOTY3MDYsIDAuODU5NDQsIDAuODU2MzgsIDAuOTY0OTEsIDAuNzU4NDIsIDAuOTMzNjUsIDAuOTgzMSwgMC45NjkyNCwgMC45NTc4MiwgMC44Njk2OSwgMC45NDE1MiwgMS4wNzc5NiwgMS4wMzU4NCwgMC43ODQzNywgMC45NjkyNCwgMC45ODcxNSwgMC44Mzk2OCwgMC44MzQ5MSwgMC44NTc3MSwgMC44Mjg3LCAwLjk0NDkyLCAwLjg4NDMzLCAwLjkyODcsIDEuMDA5OCwgMC45NTc4MiwgMC44Mjg3LCAxLjA2MjUsIDAuOTgyNDgsIDEuMDM0MjQsIDEuMiwgMS4wMTA3MSwgMS4wNjI1LCAwLjk1MjQ2LCAxLjAzODA5LCAxLjA0OTEyLCAwLjk4MjQ4LCAxLjAwMjIxLCAxLjAzNDI0LCAxLjA1NDQzLCAxLjIsIDEuMDQ3ODUsIDAuOTk2MDksIDEuMDAxNjksIDEuMDUxNzYsIDAuOTkzNDYsIDEuMDUzNTYsIDAuOTA4NywgMS4wMzAwNCwgMC45NTU0MiwgMC45MzExNywgMS4yMzM2MiwgMS4wMTA3MSwgMS4wNzgzMSwgMS4wMjUxMiwgMS4wNTIwNSwgMS4wMzUwMiwgMS4yLCAxLjAxMDcxLCAxLjA1MzU2LCAxLjAxMDcxLCAxLjAzNTAyLCAwLjc1ODQyLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjAzNzE5LCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAwLjk0MDMsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEuMDQwMjEsIDEsIDEsIDEsIDEsIDEsIDEsIDAuOTg5NjUsIDEuMDAwNjgsIDAuOTg5NjUsIDEuMDAwNjgsIDAuOTg5NjUsIDEuMDAwNjgsIDAuODI4NywgMC45Njc3NywgMSwgMS4yMDA4OCwgMC44OTkwMywgMSwgMSwgMC43NTE1NSwgMS4wMzA3NywgMS4wMzA3NywgMS4wMzA3NywgMS4wMzA3NywgMS4xMzE5NiwgMS4xMzE5NiwgMS4xMzE5NiwgMC42NzQyOCwgMC42NzQyOCwgMS4xNjAzOSwgMC43MzI5MSwgMS4yMDk5NiwgMS4yMjEzNSwgMS4wNjQ4MywgMC45NDg2OCwgMC45NDg2OCwgMC45NTk5NiwgMS4yNDYzMywgMSwgMS4wNzQ5NywgMC44Nzc5NiwgMC45NjkyNywgMS4wMTUxOCwgMC45NjkyNywgMSwgMSwgMSwgMC43NzI5NSwgMSwgMSwgMS4xMDUzOSwgMS4xMDUzOSwgMS4xMTM1OCwgMS4wNjk2NywgMC44NjI3OSwgMC45NDQzNCwgMC44NjI3OSwgMC45NDQzNCwgMC44NjE4MiwgMSwgMSwgMS4wODMsIDEsIDAuOTE1NzgsIDAuODY1MDcsIDEuMTcxNCwgMS4xODQxNiwgMS4xNDU4OSwgMC42OTgyNSwgMC45NzYyMiwgMS45Njk3LCAxLjI0ODIyLCAxLjI0ODIyLCAxLjE3MjM4LCAxLjI0ODIyLCAxLjI0ODIyLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLCAxLjQyNjAzLCAxLCAwLjk5ODYyLCAwLjk5ODYyLCAxLCAwLjg3MDI1LCAwLjg3MDI1LCAwLjg3MDI1LCAwLjg3MDI1LCAxLjE4MDgzLCAxLjQyNjAzLCAxLCAxLjQyNjAzLCAxLjQyNjAzLCAwLjk5ODYyLCAxLCAxLCAxLCAxLCAxLCAxLjI4ODYsIDEuMDQzMTUsIDEuMTUyOTYsIDEuMzQxNjMsIDEsIDEsIDEsIDEuMTA5MzgsIDEuMTA5MzgsIDEsIDEsIDEsIDEuMDU0MjUsIDEuMDk5NzEsIDEuMDk5NzEsIDEuMDk5NzEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDEsIDFdOwpjb25zdCBTZWdvZXVpUmVndWxhck1ldHJpY3MgPSB7CiAgbGluZUhlaWdodDogMS4zMzAwOCwKICBsaW5lR2FwOiAwCn07Cgo7Ly8gLi9zcmMvY29yZS94ZmFfZm9udHMuanMKCgoKCgoKCgoKCgpjb25zdCBnZXRYRkFGb250TWFwID0gZ2V0TG9va3VwVGFibGVGYWN0b3J5KGZ1bmN0aW9uICh0KSB7CiAgdFsiTXlyaWFkUHJvLVJlZ3VsYXIiXSA9IHRbIlBkZkpTLUZhbGxiYWNrLVJlZ3VsYXIiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1SZWd1bGFyIiwKICAgIGZhY3RvcnM6IE15cmlhZFByb1JlZ3VsYXJGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNSZWd1bGFyV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zUmVndWxhck1hcHBpbmcsCiAgICBtZXRyaWNzOiBNeXJpYWRQcm9SZWd1bGFyTWV0cmljcwogIH07CiAgdFsiTXlyaWFkUHJvLUJvbGQiXSA9IHRbIlBkZkpTLUZhbGxiYWNrLUJvbGQiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1Cb2xkIiwKICAgIGZhY3RvcnM6IE15cmlhZFByb0JvbGRGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNCb2xkV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zQm9sZE1hcHBpbmcsCiAgICBtZXRyaWNzOiBNeXJpYWRQcm9Cb2xkTWV0cmljcwogIH07CiAgdFsiTXlyaWFkUHJvLUl0Il0gPSB0WyJNeXJpYWRQcm8tSXRhbGljIl0gPSB0WyJQZGZKUy1GYWxsYmFjay1JdGFsaWMiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1JdGFsaWMiLAogICAgZmFjdG9yczogTXlyaWFkUHJvSXRhbGljRmFjdG9ycywKICAgIGJhc2VXaWR0aHM6IExpYmVyYXRpb25TYW5zSXRhbGljV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zSXRhbGljTWFwcGluZywKICAgIG1ldHJpY3M6IE15cmlhZFByb0l0YWxpY01ldHJpY3MKICB9OwogIHRbIk15cmlhZFByby1Cb2xkSXQiXSA9IHRbIk15cmlhZFByby1Cb2xkSXRhbGljIl0gPSB0WyJQZGZKUy1GYWxsYmFjay1Cb2xkSXRhbGljIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtQm9sZEl0YWxpYyIsCiAgICBmYWN0b3JzOiBNeXJpYWRQcm9Cb2xkSXRhbGljRmFjdG9ycywKICAgIGJhc2VXaWR0aHM6IExpYmVyYXRpb25TYW5zQm9sZEl0YWxpY1dpZHRocywKICAgIGJhc2VNYXBwaW5nOiBMaWJlcmF0aW9uU2Fuc0JvbGRJdGFsaWNNYXBwaW5nLAogICAgbWV0cmljczogTXlyaWFkUHJvQm9sZEl0YWxpY01ldHJpY3MKICB9OwogIHQuQXJpYWxNVCA9IHQuQXJpYWwgPSB0WyJBcmlhbC1SZWd1bGFyIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtUmVndWxhciIsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc1JlZ3VsYXJXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNSZWd1bGFyTWFwcGluZwogIH07CiAgdFsiQXJpYWwtQm9sZE1UIl0gPSB0WyJBcmlhbC1Cb2xkIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtQm9sZCIsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc0JvbGRXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNCb2xkTWFwcGluZwogIH07CiAgdFsiQXJpYWwtSXRhbGljTVQiXSA9IHRbIkFyaWFsLUl0YWxpYyJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUl0YWxpYyIsCiAgICBiYXNlV2lkdGhzOiBMaWJlcmF0aW9uU2Fuc0l0YWxpY1dpZHRocywKICAgIGJhc2VNYXBwaW5nOiBMaWJlcmF0aW9uU2Fuc0l0YWxpY01hcHBpbmcKICB9OwogIHRbIkFyaWFsLUJvbGRJdGFsaWNNVCJdID0gdFsiQXJpYWwtQm9sZEl0YWxpYyJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUJvbGRJdGFsaWMiLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNCb2xkSXRhbGljV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zQm9sZEl0YWxpY01hcHBpbmcKICB9OwogIHRbIkNhbGlicmktUmVndWxhciJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLVJlZ3VsYXIiLAogICAgZmFjdG9yczogQ2FsaWJyaVJlZ3VsYXJGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNSZWd1bGFyV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zUmVndWxhck1hcHBpbmcsCiAgICBtZXRyaWNzOiBDYWxpYnJpUmVndWxhck1ldHJpY3MKICB9OwogIHRbIkNhbGlicmktQm9sZCJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUJvbGQiLAogICAgZmFjdG9yczogQ2FsaWJyaUJvbGRGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNCb2xkV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zQm9sZE1hcHBpbmcsCiAgICBtZXRyaWNzOiBDYWxpYnJpQm9sZE1ldHJpY3MKICB9OwogIHRbIkNhbGlicmktSXRhbGljIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtSXRhbGljIiwKICAgIGZhY3RvcnM6IENhbGlicmlJdGFsaWNGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNJdGFsaWNXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNJdGFsaWNNYXBwaW5nLAogICAgbWV0cmljczogQ2FsaWJyaUl0YWxpY01ldHJpY3MKICB9OwogIHRbIkNhbGlicmktQm9sZEl0YWxpYyJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUJvbGRJdGFsaWMiLAogICAgZmFjdG9yczogQ2FsaWJyaUJvbGRJdGFsaWNGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNCb2xkSXRhbGljV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zQm9sZEl0YWxpY01hcHBpbmcsCiAgICBtZXRyaWNzOiBDYWxpYnJpQm9sZEl0YWxpY01ldHJpY3MKICB9OwogIHRbIlNlZ29ldWktUmVndWxhciJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLVJlZ3VsYXIiLAogICAgZmFjdG9yczogU2Vnb2V1aVJlZ3VsYXJGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNSZWd1bGFyV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zUmVndWxhck1hcHBpbmcsCiAgICBtZXRyaWNzOiBTZWdvZXVpUmVndWxhck1ldHJpY3MKICB9OwogIHRbIlNlZ29ldWktQm9sZCJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUJvbGQiLAogICAgZmFjdG9yczogU2Vnb2V1aUJvbGRGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNCb2xkV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zQm9sZE1hcHBpbmcsCiAgICBtZXRyaWNzOiBTZWdvZXVpQm9sZE1ldHJpY3MKICB9OwogIHRbIlNlZ29ldWktSXRhbGljIl0gPSB7CiAgICBuYW1lOiAiTGliZXJhdGlvblNhbnMtSXRhbGljIiwKICAgIGZhY3RvcnM6IFNlZ29ldWlJdGFsaWNGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNJdGFsaWNXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNJdGFsaWNNYXBwaW5nLAogICAgbWV0cmljczogU2Vnb2V1aUl0YWxpY01ldHJpY3MKICB9OwogIHRbIlNlZ29ldWktQm9sZEl0YWxpYyJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUJvbGRJdGFsaWMiLAogICAgZmFjdG9yczogU2Vnb2V1aUJvbGRJdGFsaWNGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNCb2xkSXRhbGljV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zQm9sZEl0YWxpY01hcHBpbmcsCiAgICBtZXRyaWNzOiBTZWdvZXVpQm9sZEl0YWxpY01ldHJpY3MKICB9OwogIHRbIkhlbHZldGljYS1SZWd1bGFyIl0gPSB0LkhlbHZldGljYSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1SZWd1bGFyIiwKICAgIGZhY3RvcnM6IEhlbHZldGljYVJlZ3VsYXJGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNSZWd1bGFyV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zUmVndWxhck1hcHBpbmcsCiAgICBtZXRyaWNzOiBIZWx2ZXRpY2FSZWd1bGFyTWV0cmljcwogIH07CiAgdFsiSGVsdmV0aWNhLUJvbGQiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1Cb2xkIiwKICAgIGZhY3RvcnM6IEhlbHZldGljYUJvbGRGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNCb2xkV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zQm9sZE1hcHBpbmcsCiAgICBtZXRyaWNzOiBIZWx2ZXRpY2FCb2xkTWV0cmljcwogIH07CiAgdFsiSGVsdmV0aWNhLUl0YWxpYyJdID0gewogICAgbmFtZTogIkxpYmVyYXRpb25TYW5zLUl0YWxpYyIsCiAgICBmYWN0b3JzOiBIZWx2ZXRpY2FJdGFsaWNGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNJdGFsaWNXaWR0aHMsCiAgICBiYXNlTWFwcGluZzogTGliZXJhdGlvblNhbnNJdGFsaWNNYXBwaW5nLAogICAgbWV0cmljczogSGVsdmV0aWNhSXRhbGljTWV0cmljcwogIH07CiAgdFsiSGVsdmV0aWNhLUJvbGRJdGFsaWMiXSA9IHsKICAgIG5hbWU6ICJMaWJlcmF0aW9uU2Fucy1Cb2xkSXRhbGljIiwKICAgIGZhY3RvcnM6IEhlbHZldGljYUJvbGRJdGFsaWNGYWN0b3JzLAogICAgYmFzZVdpZHRoczogTGliZXJhdGlvblNhbnNCb2xkSXRhbGljV2lkdGhzLAogICAgYmFzZU1hcHBpbmc6IExpYmVyYXRpb25TYW5zQm9sZEl0YWxpY01hcHBpbmcsCiAgICBtZXRyaWNzOiBIZWx2ZXRpY2FCb2xkSXRhbGljTWV0cmljcwogIH07Cn0pOwpmdW5jdGlvbiBnZXRYZmFGb250TmFtZShuYW1lKSB7CiAgY29uc3QgZm9udE5hbWUgPSBub3JtYWxpemVGb250TmFtZShuYW1lKTsKICBjb25zdCBmb250TWFwID0gZ2V0WEZBRm9udE1hcCgpOwogIHJldHVybiBmb250TWFwW2ZvbnROYW1lXTsKfQpmdW5jdGlvbiBnZXRYZmFGb250V2lkdGhzKG5hbWUpIHsKICBjb25zdCBpbmZvID0gZ2V0WGZhRm9udE5hbWUobmFtZSk7CiAgaWYgKCFpbmZvKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgY29uc3QgewogICAgYmFzZVdpZHRocywKICAgIGJhc2VNYXBwaW5nLAogICAgZmFjdG9ycwogIH0gPSBpbmZvOwogIGNvbnN0IHJlc2NhbGVkQmFzZVdpZHRocyA9ICFmYWN0b3JzID8gYmFzZVdpZHRocyA6IGJhc2VXaWR0aHMubWFwKCh3LCBpKSA9PiB3ICogZmFjdG9yc1tpXSk7CiAgbGV0IGN1cnJlbnRDb2RlID0gLTI7CiAgbGV0IGN1cnJlbnRBcnJheTsKICBjb25zdCBuZXdXaWR0aHMgPSBbXTsKICBmb3IgKGNvbnN0IFt1bmljb2RlLCBnbHlwaEluZGV4XSBvZiBiYXNlTWFwcGluZy5tYXAoKGNoYXJVbmljb2RlLCBpbmRleCkgPT4gW2NoYXJVbmljb2RlLCBpbmRleF0pLnNvcnQoKFt1bmljb2RlMV0sIFt1bmljb2RlMl0pID0+IHVuaWNvZGUxIC0gdW5pY29kZTIpKSB7CiAgICBpZiAodW5pY29kZSA9PT0gLTEpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICBpZiAodW5pY29kZSA9PT0gY3VycmVudENvZGUgKyAxKSB7CiAgICAgIGN1cnJlbnRBcnJheS5wdXNoKHJlc2NhbGVkQmFzZVdpZHRoc1tnbHlwaEluZGV4XSk7CiAgICAgIGN1cnJlbnRDb2RlICs9IDE7CiAgICB9IGVsc2UgewogICAgICBjdXJyZW50Q29kZSA9IHVuaWNvZGU7CiAgICAgIGN1cnJlbnRBcnJheSA9IFtyZXNjYWxlZEJhc2VXaWR0aHNbZ2x5cGhJbmRleF1dOwogICAgICBuZXdXaWR0aHMucHVzaCh1bmljb2RlLCBjdXJyZW50QXJyYXkpOwogICAgfQogIH0KICByZXR1cm4gbmV3V2lkdGhzOwp9CmZ1bmN0aW9uIGdldFhmYUZvbnREaWN0KG5hbWUpIHsKICBjb25zdCB3aWR0aHMgPSBnZXRYZmFGb250V2lkdGhzKG5hbWUpOwogIGNvbnN0IGRpY3QgPSBuZXcgRGljdChudWxsKTsKICBkaWN0LnNldCgiQmFzZUZvbnQiLCBOYW1lLmdldChuYW1lKSk7CiAgZGljdC5zZXQoIlR5cGUiLCBOYW1lLmdldCgiRm9udCIpKTsKICBkaWN0LnNldCgiU3VidHlwZSIsIE5hbWUuZ2V0KCJDSURGb250VHlwZTIiKSk7CiAgZGljdC5zZXQoIkVuY29kaW5nIiwgTmFtZS5nZXQoIklkZW50aXR5LUgiKSk7CiAgZGljdC5zZXQoIkNJRFRvR0lETWFwIiwgTmFtZS5nZXQoIklkZW50aXR5IikpOwogIGRpY3Quc2V0KCJXIiwgd2lkdGhzKTsKICBkaWN0LnNldCgiRmlyc3RDaGFyIiwgd2lkdGhzWzBdKTsKICBkaWN0LnNldCgiTGFzdENoYXIiLCB3aWR0aHMuYXQoLTIpICsgd2lkdGhzLmF0KC0xKS5sZW5ndGggLSAxKTsKICBjb25zdCBkZXNjcmlwdG9yID0gbmV3IERpY3QobnVsbCk7CiAgZGljdC5zZXQoIkZvbnREZXNjcmlwdG9yIiwgZGVzY3JpcHRvcik7CiAgY29uc3Qgc3lzdGVtSW5mbyA9IG5ldyBEaWN0KG51bGwpOwogIHN5c3RlbUluZm8uc2V0KCJPcmRlcmluZyIsICJJZGVudGl0eSIpOwogIHN5c3RlbUluZm8uc2V0KCJSZWdpc3RyeSIsICJBZG9iZSIpOwogIHN5c3RlbUluZm8uc2V0KCJTdXBwbGVtZW50IiwgMCk7CiAgZGljdC5zZXQoIkNJRFN5c3RlbUluZm8iLCBzeXN0ZW1JbmZvKTsKICByZXR1cm4gZGljdDsKfQoKOy8vIC4vc3JjL2NvcmUvcHNfcGFyc2VyLmpzCgoKCgpjbGFzcyBQb3N0U2NyaXB0UGFyc2VyIHsKICBjb25zdHJ1Y3RvcihsZXhlcikgewogICAgdGhpcy5sZXhlciA9IGxleGVyOwogICAgdGhpcy5vcGVyYXRvcnMgPSBbXTsKICAgIHRoaXMudG9rZW4gPSBudWxsOwogICAgdGhpcy5wcmV2ID0gbnVsbDsKICB9CiAgbmV4dFRva2VuKCkgewogICAgdGhpcy5wcmV2ID0gdGhpcy50b2tlbjsKICAgIHRoaXMudG9rZW4gPSB0aGlzLmxleGVyLmdldFRva2VuKCk7CiAgfQogIGFjY2VwdCh0eXBlKSB7CiAgICBpZiAodGhpcy50b2tlbi50eXBlID09PSB0eXBlKSB7CiAgICAgIHRoaXMubmV4dFRva2VuKCk7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwogIH0KICBleHBlY3QodHlwZSkgewogICAgaWYgKHRoaXMuYWNjZXB0KHR5cGUpKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBVbmV4cGVjdGVkIHN5bWJvbDogZm91bmQgJHt0aGlzLnRva2VuLnR5cGV9IGV4cGVjdGVkICR7dHlwZX0uYCk7CiAgfQogIHBhcnNlKCkgewogICAgdGhpcy5uZXh0VG9rZW4oKTsKICAgIHRoaXMuZXhwZWN0KFBvc3RTY3JpcHRUb2tlblR5cGVzLkxCUkFDRSk7CiAgICB0aGlzLnBhcnNlQmxvY2soKTsKICAgIHRoaXMuZXhwZWN0KFBvc3RTY3JpcHRUb2tlblR5cGVzLlJCUkFDRSk7CiAgICByZXR1cm4gdGhpcy5vcGVyYXRvcnM7CiAgfQogIHBhcnNlQmxvY2soKSB7CiAgICB3aGlsZSAodHJ1ZSkgewogICAgICBpZiAodGhpcy5hY2NlcHQoUG9zdFNjcmlwdFRva2VuVHlwZXMuTlVNQkVSKSkgewogICAgICAgIHRoaXMub3BlcmF0b3JzLnB1c2godGhpcy5wcmV2LnZhbHVlKTsKICAgICAgfSBlbHNlIGlmICh0aGlzLmFjY2VwdChQb3N0U2NyaXB0VG9rZW5UeXBlcy5PUEVSQVRPUikpIHsKICAgICAgICB0aGlzLm9wZXJhdG9ycy5wdXNoKHRoaXMucHJldi52YWx1ZSk7CiAgICAgIH0gZWxzZSBpZiAodGhpcy5hY2NlcHQoUG9zdFNjcmlwdFRva2VuVHlwZXMuTEJSQUNFKSkgewogICAgICAgIHRoaXMucGFyc2VDb25kaXRpb24oKTsKICAgICAgfSBlbHNlIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgIH0KICB9CiAgcGFyc2VDb25kaXRpb24oKSB7CiAgICBjb25zdCBjb25kaXRpb25Mb2NhdGlvbiA9IHRoaXMub3BlcmF0b3JzLmxlbmd0aDsKICAgIHRoaXMub3BlcmF0b3JzLnB1c2gobnVsbCwgbnVsbCk7CiAgICB0aGlzLnBhcnNlQmxvY2soKTsKICAgIHRoaXMuZXhwZWN0KFBvc3RTY3JpcHRUb2tlblR5cGVzLlJCUkFDRSk7CiAgICBpZiAodGhpcy5hY2NlcHQoUG9zdFNjcmlwdFRva2VuVHlwZXMuSUYpKSB7CiAgICAgIHRoaXMub3BlcmF0b3JzW2NvbmRpdGlvbkxvY2F0aW9uXSA9IHRoaXMub3BlcmF0b3JzLmxlbmd0aDsKICAgICAgdGhpcy5vcGVyYXRvcnNbY29uZGl0aW9uTG9jYXRpb24gKyAxXSA9ICJqeiI7CiAgICB9IGVsc2UgaWYgKHRoaXMuYWNjZXB0KFBvc3RTY3JpcHRUb2tlblR5cGVzLkxCUkFDRSkpIHsKICAgICAgY29uc3QganVtcExvY2F0aW9uID0gdGhpcy5vcGVyYXRvcnMubGVuZ3RoOwogICAgICB0aGlzLm9wZXJhdG9ycy5wdXNoKG51bGwsIG51bGwpOwogICAgICBjb25zdCBlbmRPZlRydWUgPSB0aGlzLm9wZXJhdG9ycy5sZW5ndGg7CiAgICAgIHRoaXMucGFyc2VCbG9jaygpOwogICAgICB0aGlzLmV4cGVjdChQb3N0U2NyaXB0VG9rZW5UeXBlcy5SQlJBQ0UpOwogICAgICB0aGlzLmV4cGVjdChQb3N0U2NyaXB0VG9rZW5UeXBlcy5JRkVMU0UpOwogICAgICB0aGlzLm9wZXJhdG9yc1tqdW1wTG9jYXRpb25dID0gdGhpcy5vcGVyYXRvcnMubGVuZ3RoOwogICAgICB0aGlzLm9wZXJhdG9yc1tqdW1wTG9jYXRpb24gKyAxXSA9ICJqIjsKICAgICAgdGhpcy5vcGVyYXRvcnNbY29uZGl0aW9uTG9jYXRpb25dID0gZW5kT2ZUcnVlOwogICAgICB0aGlzLm9wZXJhdG9yc1tjb25kaXRpb25Mb2NhdGlvbiArIDFdID0gImp6IjsKICAgIH0gZWxzZSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiUFMgRnVuY3Rpb246IGVycm9yIHBhcnNpbmcgY29uZGl0aW9uYWwuIik7CiAgICB9CiAgfQp9CmNvbnN0IFBvc3RTY3JpcHRUb2tlblR5cGVzID0gewogIExCUkFDRTogMCwKICBSQlJBQ0U6IDEsCiAgTlVNQkVSOiAyLAogIE9QRVJBVE9SOiAzLAogIElGOiA0LAogIElGRUxTRTogNQp9OwpjbGFzcyBQb3N0U2NyaXB0VG9rZW4gewogIHN0YXRpYyBnZXQgb3BDYWNoZSgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgIm9wQ2FjaGUiLCBPYmplY3QuY3JlYXRlKG51bGwpKTsKICB9CiAgY29uc3RydWN0b3IodHlwZSwgdmFsdWUpIHsKICAgIHRoaXMudHlwZSA9IHR5cGU7CiAgICB0aGlzLnZhbHVlID0gdmFsdWU7CiAgfQogIHN0YXRpYyBnZXRPcGVyYXRvcihvcCkgewogICAgcmV0dXJuIFBvc3RTY3JpcHRUb2tlbi5vcENhY2hlW29wXSB8fD0gbmV3IFBvc3RTY3JpcHRUb2tlbihQb3N0U2NyaXB0VG9rZW5UeXBlcy5PUEVSQVRPUiwgb3ApOwogIH0KICBzdGF0aWMgZ2V0IExCUkFDRSgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgIkxCUkFDRSIsIG5ldyBQb3N0U2NyaXB0VG9rZW4oUG9zdFNjcmlwdFRva2VuVHlwZXMuTEJSQUNFLCAieyIpKTsKICB9CiAgc3RhdGljIGdldCBSQlJBQ0UoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJSQlJBQ0UiLCBuZXcgUG9zdFNjcmlwdFRva2VuKFBvc3RTY3JpcHRUb2tlblR5cGVzLlJCUkFDRSwgIn0iKSk7CiAgfQogIHN0YXRpYyBnZXQgSUYoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJJRiIsIG5ldyBQb3N0U2NyaXB0VG9rZW4oUG9zdFNjcmlwdFRva2VuVHlwZXMuSUYsICJJRiIpKTsKICB9CiAgc3RhdGljIGdldCBJRkVMU0UoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJJRkVMU0UiLCBuZXcgUG9zdFNjcmlwdFRva2VuKFBvc3RTY3JpcHRUb2tlblR5cGVzLklGRUxTRSwgIklGRUxTRSIpKTsKICB9Cn0KY2xhc3MgUG9zdFNjcmlwdExleGVyIHsKICBjb25zdHJ1Y3RvcihzdHJlYW0pIHsKICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtOwogICAgdGhpcy5uZXh0Q2hhcigpOwogICAgdGhpcy5zdHJCdWYgPSBbXTsKICB9CiAgbmV4dENoYXIoKSB7CiAgICByZXR1cm4gdGhpcy5jdXJyZW50Q2hhciA9IHRoaXMuc3RyZWFtLmdldEJ5dGUoKTsKICB9CiAgZ2V0VG9rZW4oKSB7CiAgICBsZXQgY29tbWVudCA9IGZhbHNlOwogICAgbGV0IGNoID0gdGhpcy5jdXJyZW50Q2hhcjsKICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIGlmIChjaCA8IDApIHsKICAgICAgICByZXR1cm4gRU9GOwogICAgICB9CiAgICAgIGlmIChjb21tZW50KSB7CiAgICAgICAgaWYgKGNoID09PSAweDBhIHx8IGNoID09PSAweDBkKSB7CiAgICAgICAgICBjb21tZW50ID0gZmFsc2U7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKGNoID09PSAweDI1KSB7CiAgICAgICAgY29tbWVudCA9IHRydWU7CiAgICAgIH0gZWxzZSBpZiAoIWlzV2hpdGVTcGFjZShjaCkpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBjaCA9IHRoaXMubmV4dENoYXIoKTsKICAgIH0KICAgIHN3aXRjaCAoY2ggfCAwKSB7CiAgICAgIGNhc2UgMHgzMDoKICAgICAgY2FzZSAweDMxOgogICAgICBjYXNlIDB4MzI6CiAgICAgIGNhc2UgMHgzMzoKICAgICAgY2FzZSAweDM0OgogICAgICBjYXNlIDB4MzU6CiAgICAgIGNhc2UgMHgzNjoKICAgICAgY2FzZSAweDM3OgogICAgICBjYXNlIDB4Mzg6CiAgICAgIGNhc2UgMHgzOToKICAgICAgY2FzZSAweDJiOgogICAgICBjYXNlIDB4MmQ6CiAgICAgIGNhc2UgMHgyZToKICAgICAgICByZXR1cm4gbmV3IFBvc3RTY3JpcHRUb2tlbihQb3N0U2NyaXB0VG9rZW5UeXBlcy5OVU1CRVIsIHRoaXMuZ2V0TnVtYmVyKCkpOwogICAgICBjYXNlIDB4N2I6CiAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgIHJldHVybiBQb3N0U2NyaXB0VG9rZW4uTEJSQUNFOwogICAgICBjYXNlIDB4N2Q6CiAgICAgICAgdGhpcy5uZXh0Q2hhcigpOwogICAgICAgIHJldHVybiBQb3N0U2NyaXB0VG9rZW4uUkJSQUNFOwogICAgfQogICAgY29uc3Qgc3RyQnVmID0gdGhpcy5zdHJCdWY7CiAgICBzdHJCdWYubGVuZ3RoID0gMDsKICAgIHN0ckJ1ZlswXSA9IFN0cmluZy5mcm9tQ2hhckNvZGUoY2gpOwogICAgd2hpbGUgKChjaCA9IHRoaXMubmV4dENoYXIoKSkgPj0gMCAmJiAoY2ggPj0gMHg0MSAmJiBjaCA8PSAweDVhIHx8IGNoID49IDB4NjEgJiYgY2ggPD0gMHg3YSkpIHsKICAgICAgc3RyQnVmLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShjaCkpOwogICAgfQogICAgY29uc3Qgc3RyID0gc3RyQnVmLmpvaW4oIiIpOwogICAgc3dpdGNoIChzdHIudG9Mb3dlckNhc2UoKSkgewogICAgICBjYXNlICJpZiI6CiAgICAgICAgcmV0dXJuIFBvc3RTY3JpcHRUb2tlbi5JRjsKICAgICAgY2FzZSAiaWZlbHNlIjoKICAgICAgICByZXR1cm4gUG9zdFNjcmlwdFRva2VuLklGRUxTRTsKICAgICAgZGVmYXVsdDoKICAgICAgICByZXR1cm4gUG9zdFNjcmlwdFRva2VuLmdldE9wZXJhdG9yKHN0cik7CiAgICB9CiAgfQogIGdldE51bWJlcigpIHsKICAgIGxldCBjaCA9IHRoaXMuY3VycmVudENoYXI7CiAgICBjb25zdCBzdHJCdWYgPSB0aGlzLnN0ckJ1ZjsKICAgIHN0ckJ1Zi5sZW5ndGggPSAwOwogICAgc3RyQnVmWzBdID0gU3RyaW5nLmZyb21DaGFyQ29kZShjaCk7CiAgICB3aGlsZSAoKGNoID0gdGhpcy5uZXh0Q2hhcigpKSA+PSAwKSB7CiAgICAgIGlmIChjaCA+PSAweDMwICYmIGNoIDw9IDB4MzkgfHwgY2ggPT09IDB4MmQgfHwgY2ggPT09IDB4MmUpIHsKICAgICAgICBzdHJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHZhbHVlID0gcGFyc2VGbG9hdChzdHJCdWYuam9pbigiIikpOwogICAgaWYgKGlzTmFOKHZhbHVlKSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgZmxvYXRpbmcgcG9pbnQgbnVtYmVyOiAke3ZhbHVlfWApOwogICAgfQogICAgcmV0dXJuIHZhbHVlOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvaW1hZ2VfdXRpbHMuanMKCgoKCgoKCgoKY2xhc3MgQmFzZUxvY2FsQ2FjaGUgewogIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHsKICAgIHRoaXMuX29ubHlSZWZzID0gb3B0aW9ucz8ub25seVJlZnMgPT09IHRydWU7CiAgICBpZiAoIXRoaXMuX29ubHlSZWZzKSB7CiAgICAgIHRoaXMuX25hbWVSZWZNYXAgPSBuZXcgTWFwKCk7CiAgICAgIHRoaXMuX2ltYWdlTWFwID0gbmV3IE1hcCgpOwogICAgfQogICAgdGhpcy5faW1hZ2VDYWNoZSA9IG5ldyBSZWZTZXRDYWNoZSgpOwogIH0KICBnZXRCeU5hbWUobmFtZSkgewogICAgaWYgKHRoaXMuX29ubHlSZWZzKSB7CiAgICAgIHVucmVhY2hhYmxlKCJTaG91bGQgbm90IGNhbGwgYGdldEJ5TmFtZWAgbWV0aG9kLiIpOwogICAgfQogICAgY29uc3QgcmVmID0gdGhpcy5fbmFtZVJlZk1hcC5nZXQobmFtZSk7CiAgICBpZiAocmVmKSB7CiAgICAgIHJldHVybiB0aGlzLmdldEJ5UmVmKHJlZik7CiAgICB9CiAgICByZXR1cm4gdGhpcy5faW1hZ2VNYXAuZ2V0KG5hbWUpIHx8IG51bGw7CiAgfQogIGdldEJ5UmVmKHJlZikgewogICAgcmV0dXJuIHRoaXMuX2ltYWdlQ2FjaGUuZ2V0KHJlZikgfHwgbnVsbDsKICB9CiAgc2V0KG5hbWUsIHJlZiwgZGF0YSkgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgc2V0YCBjYWxsZWQuIik7CiAgfQp9CmNsYXNzIExvY2FsSW1hZ2VDYWNoZSBleHRlbmRzIEJhc2VMb2NhbENhY2hlIHsKICBzZXQobmFtZSwgcmVmID0gbnVsbCwgZGF0YSkgewogICAgaWYgKHR5cGVvZiBuYW1lICE9PSAic3RyaW5nIikgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvY2FsSW1hZ2VDYWNoZS5zZXQgLSBleHBlY3RlZCAibmFtZSIgYXJndW1lbnQuJyk7CiAgICB9CiAgICBpZiAocmVmKSB7CiAgICAgIGlmICh0aGlzLl9pbWFnZUNhY2hlLmhhcyhyZWYpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIHRoaXMuX25hbWVSZWZNYXAuc2V0KG5hbWUsIHJlZik7CiAgICAgIHRoaXMuX2ltYWdlQ2FjaGUucHV0KHJlZiwgZGF0YSk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh0aGlzLl9pbWFnZU1hcC5oYXMobmFtZSkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5faW1hZ2VNYXAuc2V0KG5hbWUsIGRhdGEpOwogIH0KfQpjbGFzcyBMb2NhbENvbG9yU3BhY2VDYWNoZSBleHRlbmRzIEJhc2VMb2NhbENhY2hlIHsKICBzZXQobmFtZSA9IG51bGwsIHJlZiA9IG51bGwsIGRhdGEpIHsKICAgIGlmICh0eXBlb2YgbmFtZSAhPT0gInN0cmluZyIgJiYgIXJlZikgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xvY2FsQ29sb3JTcGFjZUNhY2hlLnNldCAtIGV4cGVjdGVkICJuYW1lIiBhbmQvb3IgInJlZiIgYXJndW1lbnQuJyk7CiAgICB9CiAgICBpZiAocmVmKSB7CiAgICAgIGlmICh0aGlzLl9pbWFnZUNhY2hlLmhhcyhyZWYpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmIChuYW1lICE9PSBudWxsKSB7CiAgICAgICAgdGhpcy5fbmFtZVJlZk1hcC5zZXQobmFtZSwgcmVmKTsKICAgICAgfQogICAgICB0aGlzLl9pbWFnZUNhY2hlLnB1dChyZWYsIGRhdGEpOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAodGhpcy5faW1hZ2VNYXAuaGFzKG5hbWUpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuX2ltYWdlTWFwLnNldChuYW1lLCBkYXRhKTsKICB9Cn0KY2xhc3MgTG9jYWxGdW5jdGlvbkNhY2hlIGV4dGVuZHMgQmFzZUxvY2FsQ2FjaGUgewogIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHsKICAgIHN1cGVyKHsKICAgICAgb25seVJlZnM6IHRydWUKICAgIH0pOwogIH0KICBzZXQobmFtZSA9IG51bGwsIHJlZiwgZGF0YSkgewogICAgaWYgKCFyZWYpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdMb2NhbEZ1bmN0aW9uQ2FjaGUuc2V0IC0gZXhwZWN0ZWQgInJlZiIgYXJndW1lbnQuJyk7CiAgICB9CiAgICBpZiAodGhpcy5faW1hZ2VDYWNoZS5oYXMocmVmKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9pbWFnZUNhY2hlLnB1dChyZWYsIGRhdGEpOwogIH0KfQpjbGFzcyBMb2NhbEdTdGF0ZUNhY2hlIGV4dGVuZHMgQmFzZUxvY2FsQ2FjaGUgewogIHNldChuYW1lLCByZWYgPSBudWxsLCBkYXRhKSB7CiAgICBpZiAodHlwZW9mIG5hbWUgIT09ICJzdHJpbmciKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignTG9jYWxHU3RhdGVDYWNoZS5zZXQgLSBleHBlY3RlZCAibmFtZSIgYXJndW1lbnQuJyk7CiAgICB9CiAgICBpZiAocmVmKSB7CiAgICAgIGlmICh0aGlzLl9pbWFnZUNhY2hlLmhhcyhyZWYpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIHRoaXMuX25hbWVSZWZNYXAuc2V0KG5hbWUsIHJlZik7CiAgICAgIHRoaXMuX2ltYWdlQ2FjaGUucHV0KHJlZiwgZGF0YSk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh0aGlzLl9pbWFnZU1hcC5oYXMobmFtZSkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5faW1hZ2VNYXAuc2V0KG5hbWUsIGRhdGEpOwogIH0KfQpjbGFzcyBMb2NhbFRpbGluZ1BhdHRlcm5DYWNoZSBleHRlbmRzIEJhc2VMb2NhbENhY2hlIHsKICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CiAgICBzdXBlcih7CiAgICAgIG9ubHlSZWZzOiB0cnVlCiAgICB9KTsKICB9CiAgc2V0KG5hbWUgPSBudWxsLCByZWYsIGRhdGEpIHsKICAgIGlmICghcmVmKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignTG9jYWxUaWxpbmdQYXR0ZXJuQ2FjaGUuc2V0IC0gZXhwZWN0ZWQgInJlZiIgYXJndW1lbnQuJyk7CiAgICB9CiAgICBpZiAodGhpcy5faW1hZ2VDYWNoZS5oYXMocmVmKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLl9pbWFnZUNhY2hlLnB1dChyZWYsIGRhdGEpOwogIH0KfQpjbGFzcyBSZWdpb25hbEltYWdlQ2FjaGUgZXh0ZW5kcyBCYXNlTG9jYWxDYWNoZSB7CiAgY29uc3RydWN0b3Iob3B0aW9ucykgewogICAgc3VwZXIoewogICAgICBvbmx5UmVmczogdHJ1ZQogICAgfSk7CiAgfQogIHNldChuYW1lID0gbnVsbCwgcmVmLCBkYXRhKSB7CiAgICBpZiAoIXJlZikgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ1JlZ2lvbmFsSW1hZ2VDYWNoZS5zZXQgLSBleHBlY3RlZCAicmVmIiBhcmd1bWVudC4nKTsKICAgIH0KICAgIGlmICh0aGlzLl9pbWFnZUNhY2hlLmhhcyhyZWYpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuX2ltYWdlQ2FjaGUucHV0KHJlZiwgZGF0YSk7CiAgfQp9CmNsYXNzIEdsb2JhbENvbG9yU3BhY2VDYWNoZSBleHRlbmRzIEJhc2VMb2NhbENhY2hlIHsKICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CiAgICBzdXBlcih7CiAgICAgIG9ubHlSZWZzOiB0cnVlCiAgICB9KTsKICB9CiAgc2V0KG5hbWUgPSBudWxsLCByZWYsIGRhdGEpIHsKICAgIGlmICghcmVmKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignR2xvYmFsQ29sb3JTcGFjZUNhY2hlLnNldCAtIGV4cGVjdGVkICJyZWYiIGFyZ3VtZW50LicpOwogICAgfQogICAgaWYgKHRoaXMuX2ltYWdlQ2FjaGUuaGFzKHJlZikpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5faW1hZ2VDYWNoZS5wdXQocmVmLCBkYXRhKTsKICB9CiAgY2xlYXIoKSB7CiAgICB0aGlzLl9pbWFnZUNhY2hlLmNsZWFyKCk7CiAgfQp9CmNsYXNzIEdsb2JhbEltYWdlQ2FjaGUgewogIHN0YXRpYyBOVU1fUEFHRVNfVEhSRVNIT0xEID0gMjsKICBzdGF0aWMgTUlOX0lNQUdFU19UT19DQUNIRSA9IDEwOwogIHN0YXRpYyBNQVhfQllURV9TSVpFID0gNWU3OwogICNkZWNvZGVGYWlsZWRTZXQgPSBuZXcgUmVmU2V0KCk7CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLl9yZWZDYWNoZSA9IG5ldyBSZWZTZXRDYWNoZSgpOwogICAgdGhpcy5faW1hZ2VDYWNoZSA9IG5ldyBSZWZTZXRDYWNoZSgpOwogIH0KICBnZXQgI2J5dGVTaXplKCkgewogICAgbGV0IGJ5dGVTaXplID0gMDsKICAgIGZvciAoY29uc3QgaW1hZ2VEYXRhIG9mIHRoaXMuX2ltYWdlQ2FjaGUpIHsKICAgICAgYnl0ZVNpemUgKz0gaW1hZ2VEYXRhLmJ5dGVTaXplOwogICAgfQogICAgcmV0dXJuIGJ5dGVTaXplOwogIH0KICBnZXQgI2NhY2hlTGltaXRSZWFjaGVkKCkgewogICAgaWYgKHRoaXMuX2ltYWdlQ2FjaGUuc2l6ZSA8IEdsb2JhbEltYWdlQ2FjaGUuTUlOX0lNQUdFU19UT19DQUNIRSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpcy4jYnl0ZVNpemUgPCBHbG9iYWxJbWFnZUNhY2hlLk1BWF9CWVRFX1NJWkUpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgcmV0dXJuIHRydWU7CiAgfQogIHNob3VsZENhY2hlKHJlZiwgcGFnZUluZGV4KSB7CiAgICBsZXQgcGFnZUluZGV4U2V0ID0gdGhpcy5fcmVmQ2FjaGUuZ2V0KHJlZik7CiAgICBpZiAoIXBhZ2VJbmRleFNldCkgewogICAgICBwYWdlSW5kZXhTZXQgPSBuZXcgU2V0KCk7CiAgICAgIHRoaXMuX3JlZkNhY2hlLnB1dChyZWYsIHBhZ2VJbmRleFNldCk7CiAgICB9CiAgICBwYWdlSW5kZXhTZXQuYWRkKHBhZ2VJbmRleCk7CiAgICBpZiAocGFnZUluZGV4U2V0LnNpemUgPCBHbG9iYWxJbWFnZUNhY2hlLk5VTV9QQUdFU19USFJFU0hPTEQpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKCF0aGlzLl9pbWFnZUNhY2hlLmhhcyhyZWYpICYmIHRoaXMuI2NhY2hlTGltaXRSZWFjaGVkKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHJldHVybiB0cnVlOwogIH0KICBhZGREZWNvZGVGYWlsZWQocmVmKSB7CiAgICB0aGlzLiNkZWNvZGVGYWlsZWRTZXQucHV0KHJlZik7CiAgfQogIGhhc0RlY29kZUZhaWxlZChyZWYpIHsKICAgIHJldHVybiB0aGlzLiNkZWNvZGVGYWlsZWRTZXQuaGFzKHJlZik7CiAgfQogIGFkZEJ5dGVTaXplKHJlZiwgYnl0ZVNpemUpIHsKICAgIGNvbnN0IGltYWdlRGF0YSA9IHRoaXMuX2ltYWdlQ2FjaGUuZ2V0KHJlZik7CiAgICBpZiAoIWltYWdlRGF0YSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoaW1hZ2VEYXRhLmJ5dGVTaXplKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGltYWdlRGF0YS5ieXRlU2l6ZSA9IGJ5dGVTaXplOwogIH0KICBnZXREYXRhKHJlZiwgcGFnZUluZGV4KSB7CiAgICBjb25zdCBwYWdlSW5kZXhTZXQgPSB0aGlzLl9yZWZDYWNoZS5nZXQocmVmKTsKICAgIGlmICghcGFnZUluZGV4U2V0KSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgaWYgKHBhZ2VJbmRleFNldC5zaXplIDwgR2xvYmFsSW1hZ2VDYWNoZS5OVU1fUEFHRVNfVEhSRVNIT0xEKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgaW1hZ2VEYXRhID0gdGhpcy5faW1hZ2VDYWNoZS5nZXQocmVmKTsKICAgIGlmICghaW1hZ2VEYXRhKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgcGFnZUluZGV4U2V0LmFkZChwYWdlSW5kZXgpOwogICAgcmV0dXJuIGltYWdlRGF0YTsKICB9CiAgc2V0RGF0YShyZWYsIGRhdGEpIHsKICAgIGlmICghdGhpcy5fcmVmQ2FjaGUuaGFzKHJlZikpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCdHbG9iYWxJbWFnZUNhY2hlLnNldERhdGEgLSBleHBlY3RlZCAic2hvdWxkQ2FjaGUiIHRvIGhhdmUgYmVlbiBjYWxsZWQuJyk7CiAgICB9CiAgICBpZiAodGhpcy5faW1hZ2VDYWNoZS5oYXMocmVmKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAodGhpcy4jY2FjaGVMaW1pdFJlYWNoZWQpIHsKICAgICAgd2FybigiR2xvYmFsSW1hZ2VDYWNoZS5zZXREYXRhIC0gY2FjaGUgbGltaXQgcmVhY2hlZC4iKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5faW1hZ2VDYWNoZS5wdXQocmVmLCBkYXRhKTsKICB9CiAgY2xlYXIob25seURhdGEgPSBmYWxzZSkgewogICAgaWYgKCFvbmx5RGF0YSkgewogICAgICB0aGlzLiNkZWNvZGVGYWlsZWRTZXQuY2xlYXIoKTsKICAgICAgdGhpcy5fcmVmQ2FjaGUuY2xlYXIoKTsKICAgIH0KICAgIHRoaXMuX2ltYWdlQ2FjaGUuY2xlYXIoKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2Z1bmN0aW9uLmpzCgoKCgoKCgoKCgoKCgpjbGFzcyBQREZGdW5jdGlvbkZhY3RvcnkgewogIGNvbnN0cnVjdG9yKHsKICAgIHhyZWYsCiAgICBpc0V2YWxTdXBwb3J0ZWQgPSB0cnVlCiAgfSkgewogICAgdGhpcy54cmVmID0geHJlZjsKICAgIHRoaXMuaXNFdmFsU3VwcG9ydGVkID0gaXNFdmFsU3VwcG9ydGVkICE9PSBmYWxzZTsKICB9CiAgY3JlYXRlKGZuLCBwYXJzZUFycmF5ID0gZmFsc2UpIHsKICAgIGxldCBmblJlZiwgcGFyc2VkRm47CiAgICBpZiAoZm4gaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgZm5SZWYgPSBmbjsKICAgIH0gZWxzZSBpZiAoZm4gaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgIGZuUmVmID0gZm4ub2JqSWQ7CiAgICB9IGVsc2UgaWYgKGZuIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICBmblJlZiA9IGZuLmRpY3Q/Lm9iaklkOwogICAgfQogICAgaWYgKGZuUmVmKSB7CiAgICAgIGNvbnN0IGNhY2hlZEZuID0gdGhpcy5fbG9jYWxGdW5jdGlvbkNhY2hlLmdldEJ5UmVmKGZuUmVmKTsKICAgICAgaWYgKGNhY2hlZEZuKSB7CiAgICAgICAgcmV0dXJuIGNhY2hlZEZuOwogICAgICB9CiAgICB9CiAgICBjb25zdCBmbk9iaiA9IHRoaXMueHJlZi5mZXRjaElmUmVmKGZuKTsKICAgIGlmIChBcnJheS5pc0FycmF5KGZuT2JqKSkgewogICAgICBpZiAoIXBhcnNlQXJyYXkpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BERkZ1bmN0aW9uRmFjdG9yeS5jcmVhdGUgLSBleHBlY3RlZCAicGFyc2VBcnJheSIgYXJndW1lbnQuJyk7CiAgICAgIH0KICAgICAgcGFyc2VkRm4gPSBQREZGdW5jdGlvbi5wYXJzZUFycmF5KHRoaXMsIGZuT2JqKTsKICAgIH0gZWxzZSB7CiAgICAgIHBhcnNlZEZuID0gUERGRnVuY3Rpb24ucGFyc2UodGhpcywgZm5PYmopOwogICAgfQogICAgaWYgKGZuUmVmKSB7CiAgICAgIHRoaXMuX2xvY2FsRnVuY3Rpb25DYWNoZS5zZXQobnVsbCwgZm5SZWYsIHBhcnNlZEZuKTsKICAgIH0KICAgIHJldHVybiBwYXJzZWRGbjsKICB9CiAgZ2V0IF9sb2NhbEZ1bmN0aW9uQ2FjaGUoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJfbG9jYWxGdW5jdGlvbkNhY2hlIiwgbmV3IExvY2FsRnVuY3Rpb25DYWNoZSgpKTsKICB9Cn0KZnVuY3Rpb24gdG9OdW1iZXJBcnJheShhcnIpIHsKICBpZiAoIUFycmF5LmlzQXJyYXkoYXJyKSkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGlmICghaXNOdW1iZXJBcnJheShhcnIsIG51bGwpKSB7CiAgICByZXR1cm4gYXJyLm1hcCh4ID0+ICt4KTsKICB9CiAgcmV0dXJuIGFycjsKfQpjbGFzcyBQREZGdW5jdGlvbiB7CiAgc3RhdGljIGdldFNhbXBsZUFycmF5KHNpemUsIG91dHB1dFNpemUsIGJwcywgc3RyZWFtKSB7CiAgICBsZXQgaSwgaWk7CiAgICBsZXQgbGVuZ3RoID0gMTsKICAgIGZvciAoaSA9IDAsIGlpID0gc2l6ZS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGxlbmd0aCAqPSBzaXplW2ldOwogICAgfQogICAgbGVuZ3RoICo9IG91dHB1dFNpemU7CiAgICBjb25zdCBhcnJheSA9IG5ldyBBcnJheShsZW5ndGgpOwogICAgbGV0IGNvZGVTaXplID0gMDsKICAgIGxldCBjb2RlQnVmID0gMDsKICAgIGNvbnN0IHNhbXBsZU11bCA9IDEuMCAvICgyLjAgKiogYnBzIC0gMSk7CiAgICBjb25zdCBzdHJCeXRlcyA9IHN0cmVhbS5nZXRCeXRlcygobGVuZ3RoICogYnBzICsgNykgLyA4KTsKICAgIGxldCBzdHJJZHggPSAwOwogICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgIHdoaWxlIChjb2RlU2l6ZSA8IGJwcykgewogICAgICAgIGNvZGVCdWYgPDw9IDg7CiAgICAgICAgY29kZUJ1ZiB8PSBzdHJCeXRlc1tzdHJJZHgrK107CiAgICAgICAgY29kZVNpemUgKz0gODsKICAgICAgfQogICAgICBjb2RlU2l6ZSAtPSBicHM7CiAgICAgIGFycmF5W2ldID0gKGNvZGVCdWYgPj4gY29kZVNpemUpICogc2FtcGxlTXVsOwogICAgICBjb2RlQnVmICY9ICgxIDw8IGNvZGVTaXplKSAtIDE7CiAgICB9CiAgICByZXR1cm4gYXJyYXk7CiAgfQogIHN0YXRpYyBwYXJzZShmYWN0b3J5LCBmbikgewogICAgY29uc3QgZGljdCA9IGZuLmRpY3QgfHwgZm47CiAgICBjb25zdCB0eXBlTnVtID0gZGljdC5nZXQoIkZ1bmN0aW9uVHlwZSIpOwogICAgc3dpdGNoICh0eXBlTnVtKSB7CiAgICAgIGNhc2UgMDoKICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3RTYW1wbGVkKGZhY3RvcnksIGZuLCBkaWN0KTsKICAgICAgY2FzZSAxOgogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDI6CiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0SW50ZXJwb2xhdGVkKGZhY3RvcnksIGRpY3QpOwogICAgICBjYXNlIDM6CiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0U3RpY2hlZChmYWN0b3J5LCBkaWN0KTsKICAgICAgY2FzZSA0OgogICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdFBvc3RTY3JpcHQoZmFjdG9yeSwgZm4sIGRpY3QpOwogICAgfQogICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJVbmtub3duIHR5cGUgb2YgZnVuY3Rpb24iKTsKICB9CiAgc3RhdGljIHBhcnNlQXJyYXkoZmFjdG9yeSwgZm5PYmopIHsKICAgIGNvbnN0IHsKICAgICAgeHJlZgogICAgfSA9IGZhY3Rvcnk7CiAgICBjb25zdCBmbkFycmF5ID0gW107CiAgICBmb3IgKGNvbnN0IGZuIG9mIGZuT2JqKSB7CiAgICAgIGZuQXJyYXkucHVzaCh0aGlzLnBhcnNlKGZhY3RvcnksIHhyZWYuZmV0Y2hJZlJlZihmbikpKTsKICAgIH0KICAgIHJldHVybiBmdW5jdGlvbiAoc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZm5BcnJheS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgZm5BcnJheVtpXShzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCArIGkpOwogICAgICB9CiAgICB9OwogIH0KICBzdGF0aWMgY29uc3RydWN0U2FtcGxlZChmYWN0b3J5LCBmbiwgZGljdCkgewogICAgZnVuY3Rpb24gdG9NdWx0aUFycmF5KGFycikgewogICAgICBjb25zdCBpbnB1dExlbmd0aCA9IGFyci5sZW5ndGg7CiAgICAgIGNvbnN0IG91dCA9IFtdOwogICAgICBsZXQgaW5kZXggPSAwOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlucHV0TGVuZ3RoOyBpICs9IDIpIHsKICAgICAgICBvdXRbaW5kZXgrK10gPSBbYXJyW2ldLCBhcnJbaSArIDFdXTsKICAgICAgfQogICAgICByZXR1cm4gb3V0OwogICAgfQogICAgZnVuY3Rpb24gaW50ZXJwb2xhdGUoeCwgeG1pbiwgeG1heCwgeW1pbiwgeW1heCkgewogICAgICByZXR1cm4geW1pbiArICh4IC0geG1pbikgKiAoKHltYXggLSB5bWluKSAvICh4bWF4IC0geG1pbikpOwogICAgfQogICAgbGV0IGRvbWFpbiA9IHRvTnVtYmVyQXJyYXkoZGljdC5nZXRBcnJheSgiRG9tYWluIikpOwogICAgbGV0IHJhbmdlID0gdG9OdW1iZXJBcnJheShkaWN0LmdldEFycmF5KCJSYW5nZSIpKTsKICAgIGlmICghZG9tYWluIHx8ICFyYW5nZSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIk5vIGRvbWFpbiBvciByYW5nZSIpOwogICAgfQogICAgY29uc3QgaW5wdXRTaXplID0gZG9tYWluLmxlbmd0aCAvIDI7CiAgICBjb25zdCBvdXRwdXRTaXplID0gcmFuZ2UubGVuZ3RoIC8gMjsKICAgIGRvbWFpbiA9IHRvTXVsdGlBcnJheShkb21haW4pOwogICAgcmFuZ2UgPSB0b011bHRpQXJyYXkocmFuZ2UpOwogICAgY29uc3Qgc2l6ZSA9IHRvTnVtYmVyQXJyYXkoZGljdC5nZXRBcnJheSgiU2l6ZSIpKTsKICAgIGNvbnN0IGJwcyA9IGRpY3QuZ2V0KCJCaXRzUGVyU2FtcGxlIik7CiAgICBjb25zdCBvcmRlciA9IGRpY3QuZ2V0KCJPcmRlciIpIHx8IDE7CiAgICBpZiAob3JkZXIgIT09IDEpIHsKICAgICAgaW5mbygiTm8gc3VwcG9ydCBmb3IgY3ViaWMgc3BsaW5lIGludGVycG9sYXRpb246ICIgKyBvcmRlcik7CiAgICB9CiAgICBsZXQgZW5jb2RlID0gdG9OdW1iZXJBcnJheShkaWN0LmdldEFycmF5KCJFbmNvZGUiKSk7CiAgICBpZiAoIWVuY29kZSkgewogICAgICBlbmNvZGUgPSBbXTsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbnB1dFNpemU7ICsraSkgewogICAgICAgIGVuY29kZS5wdXNoKFswLCBzaXplW2ldIC0gMV0pOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBlbmNvZGUgPSB0b011bHRpQXJyYXkoZW5jb2RlKTsKICAgIH0KICAgIGxldCBkZWNvZGUgPSB0b051bWJlckFycmF5KGRpY3QuZ2V0QXJyYXkoIkRlY29kZSIpKTsKICAgIGRlY29kZSA9ICFkZWNvZGUgPyByYW5nZSA6IHRvTXVsdGlBcnJheShkZWNvZGUpOwogICAgY29uc3Qgc2FtcGxlcyA9IHRoaXMuZ2V0U2FtcGxlQXJyYXkoc2l6ZSwgb3V0cHV0U2l6ZSwgYnBzLCBmbik7CiAgICByZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0U2FtcGxlZEZuKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICAgIGNvbnN0IGN1YmVWZXJ0aWNlcyA9IDEgPDwgaW5wdXRTaXplOwogICAgICBjb25zdCBjdWJlTiA9IG5ldyBGbG9hdDY0QXJyYXkoY3ViZVZlcnRpY2VzKS5maWxsKDEpOwogICAgICBjb25zdCBjdWJlVmVydGV4ID0gbmV3IFVpbnQzMkFycmF5KGN1YmVWZXJ0aWNlcyk7CiAgICAgIGxldCBpLCBqOwogICAgICBsZXQgayA9IG91dHB1dFNpemUsCiAgICAgICAgcG9zID0gMTsKICAgICAgZm9yIChpID0gMDsgaSA8IGlucHV0U2l6ZTsgKytpKSB7CiAgICAgICAgY29uc3QgZG9tYWluXzJpID0gZG9tYWluW2ldWzBdOwogICAgICAgIGNvbnN0IGRvbWFpbl8yaV8xID0gZG9tYWluW2ldWzFdOwogICAgICAgIGNvbnN0IHhpID0gTWF0aENsYW1wKHNyY1tzcmNPZmZzZXQgKyBpXSwgZG9tYWluXzJpLCBkb21haW5fMmlfMSk7CiAgICAgICAgbGV0IGUgPSBpbnRlcnBvbGF0ZSh4aSwgZG9tYWluXzJpLCBkb21haW5fMmlfMSwgZW5jb2RlW2ldWzBdLCBlbmNvZGVbaV1bMV0pOwogICAgICAgIGNvbnN0IHNpemVfaSA9IHNpemVbaV07CiAgICAgICAgZSA9IE1hdGhDbGFtcChlLCAwLCBzaXplX2kgLSAxKTsKICAgICAgICBjb25zdCBlMCA9IGUgPCBzaXplX2kgLSAxID8gTWF0aC5mbG9vcihlKSA6IGUgLSAxOwogICAgICAgIGNvbnN0IG4wID0gZTAgKyAxIC0gZTsKICAgICAgICBjb25zdCBuMSA9IGUgLSBlMDsKICAgICAgICBjb25zdCBvZmZzZXQwID0gZTAgKiBrOwogICAgICAgIGNvbnN0IG9mZnNldDEgPSBvZmZzZXQwICsgazsKICAgICAgICBmb3IgKGogPSAwOyBqIDwgY3ViZVZlcnRpY2VzOyBqKyspIHsKICAgICAgICAgIGlmIChqICYgcG9zKSB7CiAgICAgICAgICAgIGN1YmVOW2pdICo9IG4xOwogICAgICAgICAgICBjdWJlVmVydGV4W2pdICs9IG9mZnNldDE7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBjdWJlTltqXSAqPSBuMDsKICAgICAgICAgICAgY3ViZVZlcnRleFtqXSArPSBvZmZzZXQwOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBrICo9IHNpemVfaTsKICAgICAgICBwb3MgPDw9IDE7CiAgICAgIH0KICAgICAgZm9yIChqID0gMDsgaiA8IG91dHB1dFNpemU7ICsraikgewogICAgICAgIGxldCByaiA9IDA7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGN1YmVWZXJ0aWNlczsgaSsrKSB7CiAgICAgICAgICByaiArPSBzYW1wbGVzW2N1YmVWZXJ0ZXhbaV0gKyBqXSAqIGN1YmVOW2ldOwogICAgICAgIH0KICAgICAgICByaiA9IGludGVycG9sYXRlKHJqLCAwLCAxLCBkZWNvZGVbal1bMF0sIGRlY29kZVtqXVsxXSk7CiAgICAgICAgZGVzdFtkZXN0T2Zmc2V0ICsgal0gPSBNYXRoQ2xhbXAocmosIHJhbmdlW2pdWzBdLCByYW5nZVtqXVsxXSk7CiAgICAgIH0KICAgIH07CiAgfQogIHN0YXRpYyBjb25zdHJ1Y3RJbnRlcnBvbGF0ZWQoZmFjdG9yeSwgZGljdCkgewogICAgY29uc3QgYzAgPSB0b051bWJlckFycmF5KGRpY3QuZ2V0QXJyYXkoIkMwIikpIHx8IFswXTsKICAgIGNvbnN0IGMxID0gdG9OdW1iZXJBcnJheShkaWN0LmdldEFycmF5KCJDMSIpKSB8fCBbMV07CiAgICBjb25zdCBuID0gZGljdC5nZXQoIk4iKTsKICAgIGNvbnN0IGRpZmYgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGMwLmxlbmd0aDsgaSA8IGlpOyArK2kpIHsKICAgICAgZGlmZi5wdXNoKGMxW2ldIC0gYzBbaV0pOwogICAgfQogICAgY29uc3QgbGVuZ3RoID0gZGlmZi5sZW5ndGg7CiAgICByZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0SW50ZXJwb2xhdGVkRm4oc3JjLCBzcmNPZmZzZXQsIGRlc3QsIGRlc3RPZmZzZXQpIHsKICAgICAgY29uc3QgeCA9IG4gPT09IDEgPyBzcmNbc3JjT2Zmc2V0XSA6IHNyY1tzcmNPZmZzZXRdICoqIG47CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgbGVuZ3RoOyArK2opIHsKICAgICAgICBkZXN0W2Rlc3RPZmZzZXQgKyBqXSA9IGMwW2pdICsgeCAqIGRpZmZbal07CiAgICAgIH0KICAgIH07CiAgfQogIHN0YXRpYyBjb25zdHJ1Y3RTdGljaGVkKGZhY3RvcnksIGRpY3QpIHsKICAgIGNvbnN0IGRvbWFpbiA9IHRvTnVtYmVyQXJyYXkoZGljdC5nZXRBcnJheSgiRG9tYWluIikpOwogICAgaWYgKCFkb21haW4pIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJObyBkb21haW4iKTsKICAgIH0KICAgIGNvbnN0IGlucHV0U2l6ZSA9IGRvbWFpbi5sZW5ndGggLyAyOwogICAgaWYgKGlucHV0U2l6ZSAhPT0gMSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkJhZCBkb21haW4gZm9yIHN0aWNoZWQgZnVuY3Rpb24iKTsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgeHJlZgogICAgfSA9IGZhY3Rvcnk7CiAgICBjb25zdCBmbnMgPSBbXTsKICAgIGZvciAoY29uc3QgZm4gb2YgZGljdC5nZXQoIkZ1bmN0aW9ucyIpKSB7CiAgICAgIGZucy5wdXNoKHRoaXMucGFyc2UoZmFjdG9yeSwgeHJlZi5mZXRjaElmUmVmKGZuKSkpOwogICAgfQogICAgY29uc3QgYm91bmRzID0gdG9OdW1iZXJBcnJheShkaWN0LmdldEFycmF5KCJCb3VuZHMiKSk7CiAgICBjb25zdCBlbmNvZGUgPSB0b051bWJlckFycmF5KGRpY3QuZ2V0QXJyYXkoIkVuY29kZSIpKTsKICAgIGNvbnN0IHRtcEJ1ZiA9IG5ldyBGbG9hdDMyQXJyYXkoMSk7CiAgICByZXR1cm4gZnVuY3Rpb24gY29uc3RydWN0U3RpY2hlZEZuKHNyYywgc3JjT2Zmc2V0LCBkZXN0LCBkZXN0T2Zmc2V0KSB7CiAgICAgIGNvbnN0IHYgPSBNYXRoQ2xhbXAoc3JjW3NyY09mZnNldF0sIGRvbWFpblswXSwgZG9tYWluWzFdKTsKICAgICAgY29uc3QgbGVuZ3RoID0gYm91bmRzLmxlbmd0aDsKICAgICAgbGV0IGk7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgIGlmICh2IDwgYm91bmRzW2ldKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgICAgbGV0IGRtaW4gPSBkb21haW5bMF07CiAgICAgIGlmIChpID4gMCkgewogICAgICAgIGRtaW4gPSBib3VuZHNbaSAtIDFdOwogICAgICB9CiAgICAgIGxldCBkbWF4ID0gZG9tYWluWzFdOwogICAgICBpZiAoaSA8IGJvdW5kcy5sZW5ndGgpIHsKICAgICAgICBkbWF4ID0gYm91bmRzW2ldOwogICAgICB9CiAgICAgIGNvbnN0IHJtaW4gPSBlbmNvZGVbMiAqIGldOwogICAgICBjb25zdCBybWF4ID0gZW5jb2RlWzIgKiBpICsgMV07CiAgICAgIHRtcEJ1ZlswXSA9IGRtaW4gPT09IGRtYXggPyBybWluIDogcm1pbiArICh2IC0gZG1pbikgKiAocm1heCAtIHJtaW4pIC8gKGRtYXggLSBkbWluKTsKICAgICAgZm5zW2ldKHRtcEJ1ZiwgMCwgZGVzdCwgZGVzdE9mZnNldCk7CiAgICB9OwogIH0KICBzdGF0aWMgY29uc3RydWN0UG9zdFNjcmlwdChmYWN0b3J5LCBmbiwgZGljdCkgewogICAgY29uc3QgZG9tYWluID0gdG9OdW1iZXJBcnJheShkaWN0LmdldEFycmF5KCJEb21haW4iKSk7CiAgICBjb25zdCByYW5nZSA9IHRvTnVtYmVyQXJyYXkoZGljdC5nZXRBcnJheSgiUmFuZ2UiKSk7CiAgICBpZiAoIWRvbWFpbikgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIk5vIGRvbWFpbi4iKTsKICAgIH0KICAgIGlmICghcmFuZ2UpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJObyByYW5nZS4iKTsKICAgIH0KICAgIGNvbnN0IGxleGVyID0gbmV3IFBvc3RTY3JpcHRMZXhlcihmbik7CiAgICBjb25zdCBwYXJzZXIgPSBuZXcgUG9zdFNjcmlwdFBhcnNlcihsZXhlcik7CiAgICBjb25zdCBjb2RlID0gcGFyc2VyLnBhcnNlKCk7CiAgICBpZiAoZmFjdG9yeS5pc0V2YWxTdXBwb3J0ZWQgJiYgRmVhdHVyZVRlc3QuaXNFdmFsU3VwcG9ydGVkKSB7CiAgICAgIGNvbnN0IGNvbXBpbGVkID0gbmV3IFBvc3RTY3JpcHRDb21waWxlcigpLmNvbXBpbGUoY29kZSwgZG9tYWluLCByYW5nZSk7CiAgICAgIGlmIChjb21waWxlZCkgewogICAgICAgIHJldHVybiBuZXcgRnVuY3Rpb24oInNyYyIsICJzcmNPZmZzZXQiLCAiZGVzdCIsICJkZXN0T2Zmc2V0IiwgY29tcGlsZWQpOwogICAgICB9CiAgICB9CiAgICBpbmZvKCJVbmFibGUgdG8gY29tcGlsZSBQUyBmdW5jdGlvbiIpOwogICAgY29uc3QgbnVtT3V0cHV0cyA9IHJhbmdlLmxlbmd0aCA+PiAxOwogICAgY29uc3QgbnVtSW5wdXRzID0gZG9tYWluLmxlbmd0aCA+PiAxOwogICAgY29uc3QgZXZhbHVhdG9yID0gbmV3IFBvc3RTY3JpcHRFdmFsdWF0b3IoY29kZSk7CiAgICBjb25zdCBjYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBjb25zdCBNQVhfQ0FDSEVfU0laRSA9IDIwNDggKiA0OwogICAgbGV0IGNhY2hlX2F2YWlsYWJsZSA9IE1BWF9DQUNIRV9TSVpFOwogICAgY29uc3QgdG1wQnVmID0gbmV3IEZsb2F0MzJBcnJheShudW1JbnB1dHMpOwogICAgcmV0dXJuIGZ1bmN0aW9uIGNvbnN0cnVjdFBvc3RTY3JpcHRGbihzcmMsIHNyY09mZnNldCwgZGVzdCwgZGVzdE9mZnNldCkgewogICAgICBsZXQgaSwgdmFsdWU7CiAgICAgIGxldCBrZXkgPSAiIjsKICAgICAgY29uc3QgaW5wdXQgPSB0bXBCdWY7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBudW1JbnB1dHM7IGkrKykgewogICAgICAgIHZhbHVlID0gc3JjW3NyY09mZnNldCArIGldOwogICAgICAgIGlucHV0W2ldID0gdmFsdWU7CiAgICAgICAga2V5ICs9IHZhbHVlICsgIl8iOwogICAgICB9CiAgICAgIGNvbnN0IGNhY2hlZFZhbHVlID0gY2FjaGVba2V5XTsKICAgICAgaWYgKGNhY2hlZFZhbHVlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBkZXN0LnNldChjYWNoZWRWYWx1ZSwgZGVzdE9mZnNldCk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGNvbnN0IG91dHB1dCA9IG5ldyBGbG9hdDMyQXJyYXkobnVtT3V0cHV0cyk7CiAgICAgIGNvbnN0IHN0YWNrID0gZXZhbHVhdG9yLmV4ZWN1dGUoaW5wdXQpOwogICAgICBjb25zdCBzdGFja0luZGV4ID0gc3RhY2subGVuZ3RoIC0gbnVtT3V0cHV0czsKICAgICAgZm9yIChpID0gMDsgaSA8IG51bU91dHB1dHM7IGkrKykgewogICAgICAgIHZhbHVlID0gc3RhY2tbc3RhY2tJbmRleCArIGldOwogICAgICAgIGxldCBib3VuZCA9IHJhbmdlW2kgKiAyXTsKICAgICAgICBpZiAodmFsdWUgPCBib3VuZCkgewogICAgICAgICAgdmFsdWUgPSBib3VuZDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgYm91bmQgPSByYW5nZVtpICogMiArIDFdOwogICAgICAgICAgaWYgKHZhbHVlID4gYm91bmQpIHsKICAgICAgICAgICAgdmFsdWUgPSBib3VuZDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgb3V0cHV0W2ldID0gdmFsdWU7CiAgICAgIH0KICAgICAgaWYgKGNhY2hlX2F2YWlsYWJsZSA+IDApIHsKICAgICAgICBjYWNoZV9hdmFpbGFibGUtLTsKICAgICAgICBjYWNoZVtrZXldID0gb3V0cHV0OwogICAgICB9CiAgICAgIGRlc3Quc2V0KG91dHB1dCwgZGVzdE9mZnNldCk7CiAgICB9OwogIH0KfQpmdW5jdGlvbiBpc1BERkZ1bmN0aW9uKHYpIHsKICBsZXQgZm5EaWN0OwogIGlmICh2IGluc3RhbmNlb2YgRGljdCkgewogICAgZm5EaWN0ID0gdjsKICB9IGVsc2UgaWYgKHYgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICBmbkRpY3QgPSB2LmRpY3Q7CiAgfSBlbHNlIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgcmV0dXJuIGZuRGljdC5oYXMoIkZ1bmN0aW9uVHlwZSIpOwp9CmNsYXNzIFBvc3RTY3JpcHRTdGFjayB7CiAgc3RhdGljIE1BWF9TVEFDS19TSVpFID0gMTAwOwogIGNvbnN0cnVjdG9yKGluaXRpYWxTdGFjaykgewogICAgdGhpcy5zdGFjayA9IGluaXRpYWxTdGFjayA/IEFycmF5LmZyb20oaW5pdGlhbFN0YWNrKSA6IFtdOwogIH0KICBwdXNoKHZhbHVlKSB7CiAgICBpZiAodGhpcy5zdGFjay5sZW5ndGggPj0gUG9zdFNjcmlwdFN0YWNrLk1BWF9TVEFDS19TSVpFKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiUG9zdFNjcmlwdCBmdW5jdGlvbiBzdGFjayBvdmVyZmxvdy4iKTsKICAgIH0KICAgIHRoaXMuc3RhY2sucHVzaCh2YWx1ZSk7CiAgfQogIHBvcCgpIHsKICAgIGlmICh0aGlzLnN0YWNrLmxlbmd0aCA8PSAwKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigiUG9zdFNjcmlwdCBmdW5jdGlvbiBzdGFjayB1bmRlcmZsb3cuIik7CiAgICB9CiAgICByZXR1cm4gdGhpcy5zdGFjay5wb3AoKTsKICB9CiAgY29weShuKSB7CiAgICBpZiAodGhpcy5zdGFjay5sZW5ndGggKyBuID49IFBvc3RTY3JpcHRTdGFjay5NQVhfU1RBQ0tfU0laRSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIlBvc3RTY3JpcHQgZnVuY3Rpb24gc3RhY2sgb3ZlcmZsb3cuIik7CiAgICB9CiAgICBjb25zdCBzdGFjayA9IHRoaXMuc3RhY2s7CiAgICBmb3IgKGxldCBpID0gc3RhY2subGVuZ3RoIC0gbiwgaiA9IG4gLSAxOyBqID49IDA7IGotLSwgaSsrKSB7CiAgICAgIHN0YWNrLnB1c2goc3RhY2tbaV0pOwogICAgfQogIH0KICBpbmRleChuKSB7CiAgICB0aGlzLnB1c2godGhpcy5zdGFja1t0aGlzLnN0YWNrLmxlbmd0aCAtIG4gLSAxXSk7CiAgfQogIHJvbGwobiwgcCkgewogICAgY29uc3Qgc3RhY2sgPSB0aGlzLnN0YWNrOwogICAgY29uc3QgbCA9IHN0YWNrLmxlbmd0aCAtIG47CiAgICBjb25zdCByID0gc3RhY2subGVuZ3RoIC0gMTsKICAgIGNvbnN0IGMgPSBsICsgKHAgLSBNYXRoLmZsb29yKHAgLyBuKSAqIG4pOwogICAgZm9yIChsZXQgaSA9IGwsIGogPSByOyBpIDwgajsgaSsrLCBqLS0pIHsKICAgICAgY29uc3QgdCA9IHN0YWNrW2ldOwogICAgICBzdGFja1tpXSA9IHN0YWNrW2pdOwogICAgICBzdGFja1tqXSA9IHQ7CiAgICB9CiAgICBmb3IgKGxldCBpID0gbCwgaiA9IGMgLSAxOyBpIDwgajsgaSsrLCBqLS0pIHsKICAgICAgY29uc3QgdCA9IHN0YWNrW2ldOwogICAgICBzdGFja1tpXSA9IHN0YWNrW2pdOwogICAgICBzdGFja1tqXSA9IHQ7CiAgICB9CiAgICBmb3IgKGxldCBpID0gYywgaiA9IHI7IGkgPCBqOyBpKyssIGotLSkgewogICAgICBjb25zdCB0ID0gc3RhY2tbaV07CiAgICAgIHN0YWNrW2ldID0gc3RhY2tbal07CiAgICAgIHN0YWNrW2pdID0gdDsKICAgIH0KICB9Cn0KY2xhc3MgUG9zdFNjcmlwdEV2YWx1YXRvciB7CiAgY29uc3RydWN0b3Iob3BlcmF0b3JzKSB7CiAgICB0aGlzLm9wZXJhdG9ycyA9IG9wZXJhdG9yczsKICB9CiAgZXhlY3V0ZShpbml0aWFsU3RhY2spIHsKICAgIGNvbnN0IHN0YWNrID0gbmV3IFBvc3RTY3JpcHRTdGFjayhpbml0aWFsU3RhY2spOwogICAgbGV0IGNvdW50ZXIgPSAwOwogICAgY29uc3Qgb3BlcmF0b3JzID0gdGhpcy5vcGVyYXRvcnM7CiAgICBjb25zdCBsZW5ndGggPSBvcGVyYXRvcnMubGVuZ3RoOwogICAgbGV0IG9wZXJhdG9yLCBhLCBiOwogICAgd2hpbGUgKGNvdW50ZXIgPCBsZW5ndGgpIHsKICAgICAgb3BlcmF0b3IgPSBvcGVyYXRvcnNbY291bnRlcisrXTsKICAgICAgaWYgKHR5cGVvZiBvcGVyYXRvciA9PT0gIm51bWJlciIpIHsKICAgICAgICBzdGFjay5wdXNoKG9wZXJhdG9yKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBzd2l0Y2ggKG9wZXJhdG9yKSB7CiAgICAgICAgY2FzZSAianoiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgaWYgKCFhKSB7CiAgICAgICAgICAgIGNvdW50ZXIgPSBiOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiaiI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBjb3VudGVyID0gYTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImFicyI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKE1hdGguYWJzKGEpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImFkZCI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGEgKyBiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImFuZCI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBpZiAodHlwZW9mIGEgPT09ICJib29sZWFuIiAmJiB0eXBlb2YgYiA9PT0gImJvb2xlYW4iKSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goYSAmJiBiKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goYSAmIGIpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiYXRhbiI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gTWF0aC5hdGFuMihhLCBiKSAvIE1hdGguUEkgKiAxODA7CiAgICAgICAgICBpZiAoYSA8IDApIHsKICAgICAgICAgICAgYSArPSAzNjA7CiAgICAgICAgICB9CiAgICAgICAgICBzdGFjay5wdXNoKGEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiYml0c2hpZnQiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgaWYgKGEgPiAwKSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goYSA8PCBiKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goYSA+PiBiKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImNlaWxpbmciOgogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChNYXRoLmNlaWwoYSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiY29weSI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5jb3B5KGEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiY29zIjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goTWF0aC5jb3MoYSAlIDM2MCAvIDE4MCAqIE1hdGguUEkpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImN2aSI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCkgfCAwOwogICAgICAgICAgc3RhY2sucHVzaChhKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImN2ciI6CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJkaXYiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhIC8gYik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJkdXAiOgogICAgICAgICAgc3RhY2suY29weSgxKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImVxIjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYSA9PT0gYik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJleGNoIjoKICAgICAgICAgIHN0YWNrLnJvbGwoMiwgMSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJleHAiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhICoqIGIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZmFsc2UiOgogICAgICAgICAgc3RhY2sucHVzaChmYWxzZSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJmbG9vciI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKE1hdGguZmxvb3IoYSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZ2UiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhID49IGIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZ3QiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhID4gYik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJpZGl2IjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYSAvIGIgfCAwKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImluZGV4IjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLmluZGV4KGEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibGUiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhIDw9IGIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibG4iOgogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChNYXRoLmxvZyhhKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJsb2ciOgogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChNYXRoLmxvZzEwKGEpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImx0IjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYSA8IGIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibW9kIjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYSAlIGIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibXVsIjoKICAgICAgICAgIGIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYSAqIGIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibmUiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhICE9PSBiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm5lZyI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKC1hKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm5vdCI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBpZiAodHlwZW9mIGEgPT09ICJib29sZWFuIikgewogICAgICAgICAgICBzdGFjay5wdXNoKCFhKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2gofmEpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAib3IiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgaWYgKHR5cGVvZiBhID09PSAiYm9vbGVhbiIgJiYgdHlwZW9mIGIgPT09ICJib29sZWFuIikgewogICAgICAgICAgICBzdGFjay5wdXNoKGEgfHwgYik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdGFjay5wdXNoKGEgfCBiKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInBvcCI6CiAgICAgICAgICBzdGFjay5wb3AoKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInJvbGwiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucm9sbChhLCBiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInJvdW5kIjoKICAgICAgICAgIGEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goTWF0aC5yb3VuZChhKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJzaW4iOgogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChNYXRoLnNpbihhICUgMzYwIC8gMTgwICogTWF0aC5QSSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAic3FydCI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKE1hdGguc3FydChhKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJzdWIiOgogICAgICAgICAgYiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgYSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChhIC0gYik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJ0cnVlIjoKICAgICAgICAgIHN0YWNrLnB1c2godHJ1ZSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJ0cnVuY2F0ZSI6CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gYSA8IDAgPyBNYXRoLmNlaWwoYSkgOiBNYXRoLmZsb29yKGEpOwogICAgICAgICAgc3RhY2sucHVzaChhKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInhvciI6CiAgICAgICAgICBiID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBpZiAodHlwZW9mIGEgPT09ICJib29sZWFuIiAmJiB0eXBlb2YgYiA9PT0gImJvb2xlYW4iKSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goYSAhPT0gYik7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzdGFjay5wdXNoKGEgXiBiKTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYFVua25vd24gb3BlcmF0b3IgJHtvcGVyYXRvcn1gKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHN0YWNrLnN0YWNrOwogIH0KfQpjbGFzcyBBc3ROb2RlIHsKICBjb25zdHJ1Y3Rvcih0eXBlKSB7CiAgICB0aGlzLnR5cGUgPSB0eXBlOwogIH0KICB2aXNpdCh2aXNpdG9yKSB7CiAgICB1bnJlYWNoYWJsZSgiYWJzdHJhY3QgbWV0aG9kIik7CiAgfQp9CmNsYXNzIEFzdEFyZ3VtZW50IGV4dGVuZHMgQXN0Tm9kZSB7CiAgY29uc3RydWN0b3IoaW5kZXgsIG1pbiwgbWF4KSB7CiAgICBzdXBlcigiYXJncyIpOwogICAgdGhpcy5pbmRleCA9IGluZGV4OwogICAgdGhpcy5taW4gPSBtaW47CiAgICB0aGlzLm1heCA9IG1heDsKICB9CiAgdmlzaXQodmlzaXRvcikgewogICAgdmlzaXRvci52aXNpdEFyZ3VtZW50KHRoaXMpOwogIH0KfQpjbGFzcyBBc3RMaXRlcmFsIGV4dGVuZHMgQXN0Tm9kZSB7CiAgY29uc3RydWN0b3IobnVtYmVyKSB7CiAgICBzdXBlcigibGl0ZXJhbCIpOwogICAgdGhpcy5udW1iZXIgPSBudW1iZXI7CiAgICB0aGlzLm1pbiA9IG51bWJlcjsKICAgIHRoaXMubWF4ID0gbnVtYmVyOwogIH0KICB2aXNpdCh2aXNpdG9yKSB7CiAgICB2aXNpdG9yLnZpc2l0TGl0ZXJhbCh0aGlzKTsKICB9Cn0KY2xhc3MgQXN0QmluYXJ5T3BlcmF0aW9uIGV4dGVuZHMgQXN0Tm9kZSB7CiAgY29uc3RydWN0b3Iob3AsIGFyZzEsIGFyZzIsIG1pbiwgbWF4KSB7CiAgICBzdXBlcigiYmluYXJ5Iik7CiAgICB0aGlzLm9wID0gb3A7CiAgICB0aGlzLmFyZzEgPSBhcmcxOwogICAgdGhpcy5hcmcyID0gYXJnMjsKICAgIHRoaXMubWluID0gbWluOwogICAgdGhpcy5tYXggPSBtYXg7CiAgfQogIHZpc2l0KHZpc2l0b3IpIHsKICAgIHZpc2l0b3IudmlzaXRCaW5hcnlPcGVyYXRpb24odGhpcyk7CiAgfQp9CmNsYXNzIEFzdE1pbiBleHRlbmRzIEFzdE5vZGUgewogIGNvbnN0cnVjdG9yKGFyZywgbWF4KSB7CiAgICBzdXBlcigibWF4Iik7CiAgICB0aGlzLmFyZyA9IGFyZzsKICAgIHRoaXMubWluID0gYXJnLm1pbjsKICAgIHRoaXMubWF4ID0gbWF4OwogIH0KICB2aXNpdCh2aXNpdG9yKSB7CiAgICB2aXNpdG9yLnZpc2l0TWluKHRoaXMpOwogIH0KfQpjbGFzcyBBc3RWYXJpYWJsZSBleHRlbmRzIEFzdE5vZGUgewogIGNvbnN0cnVjdG9yKGluZGV4LCBtaW4sIG1heCkgewogICAgc3VwZXIoInZhciIpOwogICAgdGhpcy5pbmRleCA9IGluZGV4OwogICAgdGhpcy5taW4gPSBtaW47CiAgICB0aGlzLm1heCA9IG1heDsKICB9CiAgdmlzaXQodmlzaXRvcikgewogICAgdmlzaXRvci52aXNpdFZhcmlhYmxlKHRoaXMpOwogIH0KfQpjbGFzcyBBc3RWYXJpYWJsZURlZmluaXRpb24gZXh0ZW5kcyBBc3ROb2RlIHsKICBjb25zdHJ1Y3Rvcih2YXJpYWJsZSwgYXJnKSB7CiAgICBzdXBlcigiZGVmaW5pdGlvbiIpOwogICAgdGhpcy52YXJpYWJsZSA9IHZhcmlhYmxlOwogICAgdGhpcy5hcmcgPSBhcmc7CiAgfQogIHZpc2l0KHZpc2l0b3IpIHsKICAgIHZpc2l0b3IudmlzaXRWYXJpYWJsZURlZmluaXRpb24odGhpcyk7CiAgfQp9CmNsYXNzIEV4cHJlc3Npb25CdWlsZGVyVmlzaXRvciB7CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLnBhcnRzID0gW107CiAgfQogIHZpc2l0QXJndW1lbnQoYXJnKSB7CiAgICB0aGlzLnBhcnRzLnB1c2goIk1hdGgubWF4KCIsIGFyZy5taW4sICIsIE1hdGgubWluKCIsIGFyZy5tYXgsICIsIHNyY1tzcmNPZmZzZXQgKyAiLCBhcmcuaW5kZXgsICJdKSkiKTsKICB9CiAgdmlzaXRWYXJpYWJsZSh2YXJpYWJsZSkgewogICAgdGhpcy5wYXJ0cy5wdXNoKCJ2IiwgdmFyaWFibGUuaW5kZXgpOwogIH0KICB2aXNpdExpdGVyYWwobGl0ZXJhbCkgewogICAgdGhpcy5wYXJ0cy5wdXNoKGxpdGVyYWwubnVtYmVyKTsKICB9CiAgdmlzaXRCaW5hcnlPcGVyYXRpb24ob3BlcmF0aW9uKSB7CiAgICB0aGlzLnBhcnRzLnB1c2goIigiKTsKICAgIG9wZXJhdGlvbi5hcmcxLnZpc2l0KHRoaXMpOwogICAgdGhpcy5wYXJ0cy5wdXNoKCIgIiwgb3BlcmF0aW9uLm9wLCAiICIpOwogICAgb3BlcmF0aW9uLmFyZzIudmlzaXQodGhpcyk7CiAgICB0aGlzLnBhcnRzLnB1c2goIikiKTsKICB9CiAgdmlzaXRWYXJpYWJsZURlZmluaXRpb24oZGVmaW5pdGlvbikgewogICAgdGhpcy5wYXJ0cy5wdXNoKCJ2YXIgIik7CiAgICBkZWZpbml0aW9uLnZhcmlhYmxlLnZpc2l0KHRoaXMpOwogICAgdGhpcy5wYXJ0cy5wdXNoKCIgPSAiKTsKICAgIGRlZmluaXRpb24uYXJnLnZpc2l0KHRoaXMpOwogICAgdGhpcy5wYXJ0cy5wdXNoKCI7Iik7CiAgfQogIHZpc2l0TWluKG1heCkgewogICAgdGhpcy5wYXJ0cy5wdXNoKCJNYXRoLm1pbigiKTsKICAgIG1heC5hcmcudmlzaXQodGhpcyk7CiAgICB0aGlzLnBhcnRzLnB1c2goIiwgIiwgbWF4Lm1heCwgIikiKTsKICB9CiAgdG9TdHJpbmcoKSB7CiAgICByZXR1cm4gdGhpcy5wYXJ0cy5qb2luKCIiKTsKICB9Cn0KZnVuY3Rpb24gYnVpbGRBZGRPcGVyYXRpb24obnVtMSwgbnVtMikgewogIGlmIChudW0yLnR5cGUgPT09ICJsaXRlcmFsIiAmJiBudW0yLm51bWJlciA9PT0gMCkgewogICAgcmV0dXJuIG51bTE7CiAgfQogIGlmIChudW0xLnR5cGUgPT09ICJsaXRlcmFsIiAmJiBudW0xLm51bWJlciA9PT0gMCkgewogICAgcmV0dXJuIG51bTI7CiAgfQogIGlmIChudW0yLnR5cGUgPT09ICJsaXRlcmFsIiAmJiBudW0xLnR5cGUgPT09ICJsaXRlcmFsIikgewogICAgcmV0dXJuIG5ldyBBc3RMaXRlcmFsKG51bTEubnVtYmVyICsgbnVtMi5udW1iZXIpOwogIH0KICByZXR1cm4gbmV3IEFzdEJpbmFyeU9wZXJhdGlvbigiKyIsIG51bTEsIG51bTIsIG51bTEubWluICsgbnVtMi5taW4sIG51bTEubWF4ICsgbnVtMi5tYXgpOwp9CmZ1bmN0aW9uIGJ1aWxkTXVsT3BlcmF0aW9uKG51bTEsIG51bTIpIHsKICBpZiAobnVtMi50eXBlID09PSAibGl0ZXJhbCIpIHsKICAgIGlmIChudW0yLm51bWJlciA9PT0gMCkgewogICAgICByZXR1cm4gbmV3IEFzdExpdGVyYWwoMCk7CiAgICB9IGVsc2UgaWYgKG51bTIubnVtYmVyID09PSAxKSB7CiAgICAgIHJldHVybiBudW0xOwogICAgfSBlbHNlIGlmIChudW0xLnR5cGUgPT09ICJsaXRlcmFsIikgewogICAgICByZXR1cm4gbmV3IEFzdExpdGVyYWwobnVtMS5udW1iZXIgKiBudW0yLm51bWJlcik7CiAgICB9CiAgfQogIGlmIChudW0xLnR5cGUgPT09ICJsaXRlcmFsIikgewogICAgaWYgKG51bTEubnVtYmVyID09PSAwKSB7CiAgICAgIHJldHVybiBuZXcgQXN0TGl0ZXJhbCgwKTsKICAgIH0gZWxzZSBpZiAobnVtMS5udW1iZXIgPT09IDEpIHsKICAgICAgcmV0dXJuIG51bTI7CiAgICB9CiAgfQogIGNvbnN0IG1pbiA9IE1hdGgubWluKG51bTEubWluICogbnVtMi5taW4sIG51bTEubWluICogbnVtMi5tYXgsIG51bTEubWF4ICogbnVtMi5taW4sIG51bTEubWF4ICogbnVtMi5tYXgpOwogIGNvbnN0IG1heCA9IE1hdGgubWF4KG51bTEubWluICogbnVtMi5taW4sIG51bTEubWluICogbnVtMi5tYXgsIG51bTEubWF4ICogbnVtMi5taW4sIG51bTEubWF4ICogbnVtMi5tYXgpOwogIHJldHVybiBuZXcgQXN0QmluYXJ5T3BlcmF0aW9uKCIqIiwgbnVtMSwgbnVtMiwgbWluLCBtYXgpOwp9CmZ1bmN0aW9uIGJ1aWxkU3ViT3BlcmF0aW9uKG51bTEsIG51bTIpIHsKICBpZiAobnVtMi50eXBlID09PSAibGl0ZXJhbCIpIHsKICAgIGlmIChudW0yLm51bWJlciA9PT0gMCkgewogICAgICByZXR1cm4gbnVtMTsKICAgIH0gZWxzZSBpZiAobnVtMS50eXBlID09PSAibGl0ZXJhbCIpIHsKICAgICAgcmV0dXJuIG5ldyBBc3RMaXRlcmFsKG51bTEubnVtYmVyIC0gbnVtMi5udW1iZXIpOwogICAgfQogIH0KICBpZiAobnVtMi50eXBlID09PSAiYmluYXJ5IiAmJiBudW0yLm9wID09PSAiLSIgJiYgbnVtMS50eXBlID09PSAibGl0ZXJhbCIgJiYgbnVtMS5udW1iZXIgPT09IDEgJiYgbnVtMi5hcmcxLnR5cGUgPT09ICJsaXRlcmFsIiAmJiBudW0yLmFyZzEubnVtYmVyID09PSAxKSB7CiAgICByZXR1cm4gbnVtMi5hcmcyOwogIH0KICByZXR1cm4gbmV3IEFzdEJpbmFyeU9wZXJhdGlvbigiLSIsIG51bTEsIG51bTIsIG51bTEubWluIC0gbnVtMi5tYXgsIG51bTEubWF4IC0gbnVtMi5taW4pOwp9CmZ1bmN0aW9uIGJ1aWxkTWluT3BlcmF0aW9uKG51bTEsIG1heCkgewogIGlmIChudW0xLm1pbiA+PSBtYXgpIHsKICAgIHJldHVybiBuZXcgQXN0TGl0ZXJhbChtYXgpOwogIH0gZWxzZSBpZiAobnVtMS5tYXggPD0gbWF4KSB7CiAgICByZXR1cm4gbnVtMTsKICB9CiAgcmV0dXJuIG5ldyBBc3RNaW4obnVtMSwgbWF4KTsKfQpjbGFzcyBQb3N0U2NyaXB0Q29tcGlsZXIgewogIGNvbXBpbGUoY29kZSwgZG9tYWluLCByYW5nZSkgewogICAgY29uc3Qgc3RhY2sgPSBbXTsKICAgIGNvbnN0IGluc3RydWN0aW9ucyA9IFtdOwogICAgY29uc3QgaW5wdXRTaXplID0gZG9tYWluLmxlbmd0aCA+PiAxLAogICAgICBvdXRwdXRTaXplID0gcmFuZ2UubGVuZ3RoID4+IDE7CiAgICBsZXQgbGFzdFJlZ2lzdGVyID0gMDsKICAgIGxldCBuLCBqOwogICAgbGV0IG51bTEsIG51bTIsIGFzdDEsIGFzdDIsIHRtcFZhciwgaXRlbTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXRTaXplOyBpKyspIHsKICAgICAgc3RhY2sucHVzaChuZXcgQXN0QXJndW1lbnQoaSwgZG9tYWluW2kgKiAyXSwgZG9tYWluW2kgKiAyICsgMV0pKTsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGNvZGUubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBpdGVtID0gY29kZVtpXTsKICAgICAgaWYgKHR5cGVvZiBpdGVtID09PSAibnVtYmVyIikgewogICAgICAgIHN0YWNrLnB1c2gobmV3IEFzdExpdGVyYWwoaXRlbSkpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHN3aXRjaCAoaXRlbSkgewogICAgICAgIGNhc2UgImFkZCI6CiAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoIDwgMikgewogICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIG51bTIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIG51bTEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIHN0YWNrLnB1c2goYnVpbGRBZGRPcGVyYXRpb24obnVtMSwgbnVtMikpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiY3ZyIjoKICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPCAxKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibXVsIjoKICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPCAyKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgbnVtMiA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgbnVtMSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgc3RhY2sucHVzaChidWlsZE11bE9wZXJhdGlvbihudW0xLCBudW0yKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJzdWIiOgogICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCA8IDIpIHsKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBudW0yID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBudW0xID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGJ1aWxkU3ViT3BlcmF0aW9uKG51bTEsIG51bTIpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImV4Y2giOgogICAgICAgICAgaWYgKHN0YWNrLmxlbmd0aCA8IDIpIHsKICAgICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBhc3QxID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBhc3QyID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBzdGFjay5wdXNoKGFzdDEsIGFzdDIpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAicG9wIjoKICAgICAgICAgIGlmIChzdGFjay5sZW5ndGggPCAxKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgc3RhY2sucG9wKCk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJpbmRleCI6CiAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoIDwgMSkgewogICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIG51bTEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGlmIChudW0xLnR5cGUgIT09ICJsaXRlcmFsIikgewogICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIG4gPSBudW0xLm51bWJlcjsKICAgICAgICAgIGlmIChuIDwgMCB8fCAhTnVtYmVyLmlzSW50ZWdlcihuKSB8fCBzdGFjay5sZW5ndGggPCBuKSB7CiAgICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgICAgfQogICAgICAgICAgYXN0MSA9IHN0YWNrW3N0YWNrLmxlbmd0aCAtIG4gLSAxXTsKICAgICAgICAgIGlmIChhc3QxLnR5cGUgPT09ICJsaXRlcmFsIiB8fCBhc3QxLnR5cGUgPT09ICJ2YXIiKSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goYXN0MSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgdG1wVmFyID0gbmV3IEFzdFZhcmlhYmxlKGxhc3RSZWdpc3RlcisrLCBhc3QxLm1pbiwgYXN0MS5tYXgpOwogICAgICAgICAgc3RhY2tbc3RhY2subGVuZ3RoIC0gbiAtIDFdID0gdG1wVmFyOwogICAgICAgICAgc3RhY2sucHVzaCh0bXBWYXIpOwogICAgICAgICAgaW5zdHJ1Y3Rpb25zLnB1c2gobmV3IEFzdFZhcmlhYmxlRGVmaW5pdGlvbih0bXBWYXIsIGFzdDEpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImR1cCI6CiAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoIDwgMSkgewogICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh0eXBlb2YgY29kZVtpICsgMV0gPT09ICJudW1iZXIiICYmIGNvZGVbaSArIDJdID09PSAiZ3QiICYmIGNvZGVbaSArIDNdID09PSBpICsgNyAmJiBjb2RlW2kgKyA0XSA9PT0gImp6IiAmJiBjb2RlW2kgKyA1XSA9PT0gInBvcCIgJiYgY29kZVtpICsgNl0gPT09IGNvZGVbaSArIDFdKSB7CiAgICAgICAgICAgIG51bTEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgICAgc3RhY2sucHVzaChidWlsZE1pbk9wZXJhdGlvbihudW0xLCBjb2RlW2kgKyAxXSkpOwogICAgICAgICAgICBpICs9IDY7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgYXN0MSA9IHN0YWNrLmF0KC0xKTsKICAgICAgICAgIGlmIChhc3QxLnR5cGUgPT09ICJsaXRlcmFsIiB8fCBhc3QxLnR5cGUgPT09ICJ2YXIiKSB7CiAgICAgICAgICAgIHN0YWNrLnB1c2goYXN0MSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgdG1wVmFyID0gbmV3IEFzdFZhcmlhYmxlKGxhc3RSZWdpc3RlcisrLCBhc3QxLm1pbiwgYXN0MS5tYXgpOwogICAgICAgICAgc3RhY2tbc3RhY2subGVuZ3RoIC0gMV0gPSB0bXBWYXI7CiAgICAgICAgICBzdGFjay5wdXNoKHRtcFZhcik7CiAgICAgICAgICBpbnN0cnVjdGlvbnMucHVzaChuZXcgQXN0VmFyaWFibGVEZWZpbml0aW9uKHRtcFZhciwgYXN0MSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAicm9sbCI6CiAgICAgICAgICBpZiAoc3RhY2subGVuZ3RoIDwgMikgewogICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIG51bTIgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIG51bTEgPSBzdGFjay5wb3AoKTsKICAgICAgICAgIGlmIChudW0yLnR5cGUgIT09ICJsaXRlcmFsIiB8fCBudW0xLnR5cGUgIT09ICJsaXRlcmFsIikgewogICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIGogPSBudW0yLm51bWJlcjsKICAgICAgICAgIG4gPSBudW0xLm51bWJlcjsKICAgICAgICAgIGlmIChuIDw9IDAgfHwgIU51bWJlci5pc0ludGVnZXIobikgfHwgIU51bWJlci5pc0ludGVnZXIoaikgfHwgc3RhY2subGVuZ3RoIDwgbikgewogICAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIGogPSAoaiAlIG4gKyBuKSAlIG47CiAgICAgICAgICBpZiAoaiA9PT0gMCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIHN0YWNrLnB1c2goLi4uc3RhY2suc3BsaWNlKHN0YWNrLmxlbmd0aCAtIG4sIG4gLSBqKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgIH0KICAgIGlmIChzdGFjay5sZW5ndGggIT09IG91dHB1dFNpemUpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCByZXN1bHQgPSBbXTsKICAgIGZvciAoY29uc3QgaW5zdHJ1Y3Rpb24gb2YgaW5zdHJ1Y3Rpb25zKSB7CiAgICAgIGNvbnN0IHN0YXRlbWVudEJ1aWxkZXIgPSBuZXcgRXhwcmVzc2lvbkJ1aWxkZXJWaXNpdG9yKCk7CiAgICAgIGluc3RydWN0aW9uLnZpc2l0KHN0YXRlbWVudEJ1aWxkZXIpOwogICAgICByZXN1bHQucHVzaChzdGF0ZW1lbnRCdWlsZGVyLnRvU3RyaW5nKCkpOwogICAgfQogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gc3RhY2subGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCBleHByID0gc3RhY2tbaV0sCiAgICAgICAgc3RhdGVtZW50QnVpbGRlciA9IG5ldyBFeHByZXNzaW9uQnVpbGRlclZpc2l0b3IoKTsKICAgICAgZXhwci52aXNpdChzdGF0ZW1lbnRCdWlsZGVyKTsKICAgICAgY29uc3QgbWluID0gcmFuZ2VbaSAqIDJdLAogICAgICAgIG1heCA9IHJhbmdlW2kgKiAyICsgMV07CiAgICAgIGNvbnN0IG91dCA9IFtzdGF0ZW1lbnRCdWlsZGVyLnRvU3RyaW5nKCldOwogICAgICBpZiAobWluID4gZXhwci5taW4pIHsKICAgICAgICBvdXQudW5zaGlmdCgiTWF0aC5tYXgoIiwgbWluLCAiLCAiKTsKICAgICAgICBvdXQucHVzaCgiKSIpOwogICAgICB9CiAgICAgIGlmIChtYXggPCBleHByLm1heCkgewogICAgICAgIG91dC51bnNoaWZ0KCJNYXRoLm1pbigiLCBtYXgsICIsICIpOwogICAgICAgIG91dC5wdXNoKCIpIik7CiAgICAgIH0KICAgICAgb3V0LnVuc2hpZnQoImRlc3RbZGVzdE9mZnNldCArICIsIGksICJdID0gIik7CiAgICAgIG91dC5wdXNoKCI7Iik7CiAgICAgIHJlc3VsdC5wdXNoKG91dC5qb2luKCIiKSk7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0LmpvaW4oIlxuIik7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9iaWRpLmpzCgpjb25zdCBiYXNlVHlwZXMgPSBbIkJOIiwgIkJOIiwgIkJOIiwgIkJOIiwgIkJOIiwgIkJOIiwgIkJOIiwgIkJOIiwgIkJOIiwgIlMiLCAiQiIsICJTIiwgIldTIiwgIkIiLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQiIsICJCIiwgIkIiLCAiUyIsICJXUyIsICJPTiIsICJPTiIsICJFVCIsICJFVCIsICJFVCIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJFUyIsICJDUyIsICJFUyIsICJDUyIsICJDUyIsICJFTiIsICJFTiIsICJFTiIsICJFTiIsICJFTiIsICJFTiIsICJFTiIsICJFTiIsICJFTiIsICJFTiIsICJDUyIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJPTiIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiT04iLCAiT04iLCAiT04iLCAiT04iLCAiT04iLCAiT04iLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIk9OIiwgIk9OIiwgIk9OIiwgIk9OIiwgIkJOIiwgIkJOIiwgIkJOIiwgIkJOIiwgIkJOIiwgIkJOIiwgIkIiLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQk4iLCAiQ1MiLCAiT04iLCAiRVQiLCAiRVQiLCAiRVQiLCAiRVQiLCAiT04iLCAiT04iLCAiT04iLCAiT04iLCAiTCIsICJPTiIsICJPTiIsICJCTiIsICJPTiIsICJPTiIsICJFVCIsICJFVCIsICJFTiIsICJFTiIsICJPTiIsICJMIiwgIk9OIiwgIk9OIiwgIk9OIiwgIkVOIiwgIkwiLCAiT04iLCAiT04iLCAiT04iLCAiT04iLCAiT04iLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIk9OIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiT04iLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIiwgIkwiLCAiTCIsICJMIl07CmNvbnN0IGFyYWJpY1R5cGVzID0gWyJBTiIsICJBTiIsICJBTiIsICJBTiIsICJBTiIsICJBTiIsICJPTiIsICJPTiIsICJBTCIsICJFVCIsICJFVCIsICJBTCIsICJDUyIsICJBTCIsICJPTiIsICJPTiIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIkFMIiwgIkFMIiwgIiIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJBTCIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJBTiIsICJBTiIsICJBTiIsICJBTiIsICJBTiIsICJBTiIsICJBTiIsICJBTiIsICJBTiIsICJBTiIsICJFVCIsICJBTiIsICJBTiIsICJBTCIsICJBTCIsICJBTCIsICJOU00iLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiQUwiLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIkFOIiwgIk9OIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIkFMIiwgIkFMIiwgIk5TTSIsICJOU00iLCAiT04iLCAiTlNNIiwgIk5TTSIsICJOU00iLCAiTlNNIiwgIkFMIiwgIkFMIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkVOIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIiwgIkFMIl07CmZ1bmN0aW9uIGlzT2RkKGkpIHsKICByZXR1cm4gKGkgJiAxKSAhPT0gMDsKfQpmdW5jdGlvbiBpc0V2ZW4oaSkgewogIHJldHVybiAoaSAmIDEpID09PSAwOwp9CmZ1bmN0aW9uIGZpbmRVbmVxdWFsKGFyciwgc3RhcnQsIHZhbHVlKSB7CiAgbGV0IGosIGpqOwogIGZvciAoaiA9IHN0YXJ0LCBqaiA9IGFyci5sZW5ndGg7IGogPCBqajsgKytqKSB7CiAgICBpZiAoYXJyW2pdICE9PSB2YWx1ZSkgewogICAgICByZXR1cm4gajsKICAgIH0KICB9CiAgcmV0dXJuIGo7Cn0KZnVuY3Rpb24gcmV2ZXJzZVZhbHVlcyhhcnIsIHN0YXJ0LCBlbmQpIHsKICBmb3IgKGxldCBpID0gc3RhcnQsIGogPSBlbmQgLSAxOyBpIDwgajsgKytpLCAtLWopIHsKICAgIGNvbnN0IHRlbXAgPSBhcnJbaV07CiAgICBhcnJbaV0gPSBhcnJbal07CiAgICBhcnJbal0gPSB0ZW1wOwogIH0KfQpmdW5jdGlvbiBjcmVhdGVCaWRpVGV4dChzdHIsIGlzTFRSLCB2ZXJ0aWNhbCA9IGZhbHNlKSB7CiAgbGV0IGRpciA9ICJsdHIiOwogIGlmICh2ZXJ0aWNhbCkgewogICAgZGlyID0gInR0YiI7CiAgfSBlbHNlIGlmICghaXNMVFIpIHsKICAgIGRpciA9ICJydGwiOwogIH0KICByZXR1cm4gewogICAgc3RyLAogICAgZGlyCiAgfTsKfQpjb25zdCBjaGFycyA9IFtdOwpjb25zdCB0eXBlcyA9IFtdOwpmdW5jdGlvbiBiaWRpKHN0ciwgc3RhcnRMZXZlbCA9IC0xLCB2ZXJ0aWNhbCA9IGZhbHNlKSB7CiAgbGV0IGlzTFRSID0gdHJ1ZTsKICBjb25zdCBzdHJMZW5ndGggPSBzdHIubGVuZ3RoOwogIGlmIChzdHJMZW5ndGggPT09IDAgfHwgdmVydGljYWwpIHsKICAgIHJldHVybiBjcmVhdGVCaWRpVGV4dChzdHIsIGlzTFRSLCB2ZXJ0aWNhbCk7CiAgfQogIGNoYXJzLmxlbmd0aCA9IHN0ckxlbmd0aDsKICB0eXBlcy5sZW5ndGggPSBzdHJMZW5ndGg7CiAgbGV0IG51bUJpZGkgPSAwOwogIGxldCBpLCBpaTsKICBmb3IgKGkgPSAwOyBpIDwgc3RyTGVuZ3RoOyArK2kpIHsKICAgIGNoYXJzW2ldID0gc3RyLmNoYXJBdChpKTsKICAgIGNvbnN0IGNoYXJDb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7CiAgICBsZXQgY2hhclR5cGUgPSAiTCI7CiAgICBpZiAoY2hhckNvZGUgPD0gMHgwMGZmKSB7CiAgICAgIGNoYXJUeXBlID0gYmFzZVR5cGVzW2NoYXJDb2RlXTsKICAgIH0gZWxzZSBpZiAoMHgwNTkwIDw9IGNoYXJDb2RlICYmIGNoYXJDb2RlIDw9IDB4MDVmNCkgewogICAgICBjaGFyVHlwZSA9ICJSIjsKICAgIH0gZWxzZSBpZiAoMHgwNjAwIDw9IGNoYXJDb2RlICYmIGNoYXJDb2RlIDw9IDB4MDZmZikgewogICAgICBjaGFyVHlwZSA9IGFyYWJpY1R5cGVzW2NoYXJDb2RlICYgMHhmZl07CiAgICAgIGlmICghY2hhclR5cGUpIHsKICAgICAgICB3YXJuKCJCaWRpOiBpbnZhbGlkIFVuaWNvZGUgY2hhcmFjdGVyICIgKyBjaGFyQ29kZS50b1N0cmluZygxNikpOwogICAgICB9CiAgICB9IGVsc2UgaWYgKDB4MDcwMCA8PSBjaGFyQ29kZSAmJiBjaGFyQ29kZSA8PSAweDA4YWMgfHwgMHhmYjUwIDw9IGNoYXJDb2RlICYmIGNoYXJDb2RlIDw9IDB4ZmRmZiB8fCAweGZlNzAgPD0gY2hhckNvZGUgJiYgY2hhckNvZGUgPD0gMHhmZWZmKSB7CiAgICAgIGNoYXJUeXBlID0gIkFMIjsKICAgIH0KICAgIGlmIChjaGFyVHlwZSA9PT0gIlIiIHx8IGNoYXJUeXBlID09PSAiQUwiIHx8IGNoYXJUeXBlID09PSAiQU4iKSB7CiAgICAgIG51bUJpZGkrKzsKICAgIH0KICAgIHR5cGVzW2ldID0gY2hhclR5cGU7CiAgfQogIGlmIChudW1CaWRpID09PSAwKSB7CiAgICBpc0xUUiA9IHRydWU7CiAgICByZXR1cm4gY3JlYXRlQmlkaVRleHQoc3RyLCBpc0xUUik7CiAgfQogIGlmIChzdGFydExldmVsID09PSAtMSkgewogICAgaWYgKG51bUJpZGkgLyBzdHJMZW5ndGggPCAwLjMgJiYgc3RyTGVuZ3RoID4gNCkgewogICAgICBpc0xUUiA9IHRydWU7CiAgICAgIHN0YXJ0TGV2ZWwgPSAwOwogICAgfSBlbHNlIHsKICAgICAgaXNMVFIgPSBmYWxzZTsKICAgICAgc3RhcnRMZXZlbCA9IDE7CiAgICB9CiAgfQogIGNvbnN0IGxldmVscyA9IFtdOwogIGZvciAoaSA9IDA7IGkgPCBzdHJMZW5ndGg7ICsraSkgewogICAgbGV2ZWxzW2ldID0gc3RhcnRMZXZlbDsKICB9CiAgY29uc3QgZSA9IGlzT2RkKHN0YXJ0TGV2ZWwpID8gIlIiIDogIkwiOwogIGNvbnN0IHNvciA9IGU7CiAgY29uc3QgZW9yID0gc29yOwogIGxldCBsYXN0VHlwZSA9IHNvcjsKICBmb3IgKGkgPSAwOyBpIDwgc3RyTGVuZ3RoOyArK2kpIHsKICAgIGlmICh0eXBlc1tpXSA9PT0gIk5TTSIpIHsKICAgICAgdHlwZXNbaV0gPSBsYXN0VHlwZTsKICAgIH0gZWxzZSB7CiAgICAgIGxhc3RUeXBlID0gdHlwZXNbaV07CiAgICB9CiAgfQogIGxhc3RUeXBlID0gc29yOwogIGxldCB0OwogIGZvciAoaSA9IDA7IGkgPCBzdHJMZW5ndGg7ICsraSkgewogICAgdCA9IHR5cGVzW2ldOwogICAgaWYgKHQgPT09ICJFTiIpIHsKICAgICAgdHlwZXNbaV0gPSBsYXN0VHlwZSA9PT0gIkFMIiA/ICJBTiIgOiAiRU4iOwogICAgfSBlbHNlIGlmICh0ID09PSAiUiIgfHwgdCA9PT0gIkwiIHx8IHQgPT09ICJBTCIpIHsKICAgICAgbGFzdFR5cGUgPSB0OwogICAgfQogIH0KICBmb3IgKGkgPSAwOyBpIDwgc3RyTGVuZ3RoOyArK2kpIHsKICAgIHQgPSB0eXBlc1tpXTsKICAgIGlmICh0ID09PSAiQUwiKSB7CiAgICAgIHR5cGVzW2ldID0gIlIiOwogICAgfQogIH0KICBmb3IgKGkgPSAxOyBpIDwgc3RyTGVuZ3RoIC0gMTsgKytpKSB7CiAgICBpZiAodHlwZXNbaV0gPT09ICJFUyIgJiYgdHlwZXNbaSAtIDFdID09PSAiRU4iICYmIHR5cGVzW2kgKyAxXSA9PT0gIkVOIikgewogICAgICB0eXBlc1tpXSA9ICJFTiI7CiAgICB9CiAgICBpZiAodHlwZXNbaV0gPT09ICJDUyIgJiYgKHR5cGVzW2kgLSAxXSA9PT0gIkVOIiB8fCB0eXBlc1tpIC0gMV0gPT09ICJBTiIpICYmIHR5cGVzW2kgKyAxXSA9PT0gdHlwZXNbaSAtIDFdKSB7CiAgICAgIHR5cGVzW2ldID0gdHlwZXNbaSAtIDFdOwogICAgfQogIH0KICBmb3IgKGkgPSAwOyBpIDwgc3RyTGVuZ3RoOyArK2kpIHsKICAgIGlmICh0eXBlc1tpXSA9PT0gIkVOIikgewogICAgICBmb3IgKGxldCBqID0gaSAtIDE7IGogPj0gMDsgLS1qKSB7CiAgICAgICAgaWYgKHR5cGVzW2pdICE9PSAiRVQiKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdHlwZXNbal0gPSAiRU4iOwogICAgICB9CiAgICAgIGZvciAobGV0IGogPSBpICsgMTsgaiA8IHN0ckxlbmd0aDsgKytqKSB7CiAgICAgICAgaWYgKHR5cGVzW2pdICE9PSAiRVQiKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdHlwZXNbal0gPSAiRU4iOwogICAgICB9CiAgICB9CiAgfQogIGZvciAoaSA9IDA7IGkgPCBzdHJMZW5ndGg7ICsraSkgewogICAgdCA9IHR5cGVzW2ldOwogICAgaWYgKHQgPT09ICJXUyIgfHwgdCA9PT0gIkVTIiB8fCB0ID09PSAiRVQiIHx8IHQgPT09ICJDUyIpIHsKICAgICAgdHlwZXNbaV0gPSAiT04iOwogICAgfQogIH0KICBsYXN0VHlwZSA9IHNvcjsKICBmb3IgKGkgPSAwOyBpIDwgc3RyTGVuZ3RoOyArK2kpIHsKICAgIHQgPSB0eXBlc1tpXTsKICAgIGlmICh0ID09PSAiRU4iKSB7CiAgICAgIHR5cGVzW2ldID0gbGFzdFR5cGUgPT09ICJMIiA/ICJMIiA6ICJFTiI7CiAgICB9IGVsc2UgaWYgKHQgPT09ICJSIiB8fCB0ID09PSAiTCIpIHsKICAgICAgbGFzdFR5cGUgPSB0OwogICAgfQogIH0KICBmb3IgKGkgPSAwOyBpIDwgc3RyTGVuZ3RoOyArK2kpIHsKICAgIGlmICh0eXBlc1tpXSA9PT0gIk9OIikgewogICAgICBjb25zdCBlbmQgPSBmaW5kVW5lcXVhbCh0eXBlcywgaSArIDEsICJPTiIpOwogICAgICBsZXQgYmVmb3JlID0gc29yOwogICAgICBpZiAoaSA+IDApIHsKICAgICAgICBiZWZvcmUgPSB0eXBlc1tpIC0gMV07CiAgICAgIH0KICAgICAgbGV0IGFmdGVyID0gZW9yOwogICAgICBpZiAoZW5kICsgMSA8IHN0ckxlbmd0aCkgewogICAgICAgIGFmdGVyID0gdHlwZXNbZW5kICsgMV07CiAgICAgIH0KICAgICAgaWYgKGJlZm9yZSAhPT0gIkwiKSB7CiAgICAgICAgYmVmb3JlID0gIlIiOwogICAgICB9CiAgICAgIGlmIChhZnRlciAhPT0gIkwiKSB7CiAgICAgICAgYWZ0ZXIgPSAiUiI7CiAgICAgIH0KICAgICAgaWYgKGJlZm9yZSA9PT0gYWZ0ZXIpIHsKICAgICAgICB0eXBlcy5maWxsKGJlZm9yZSwgaSwgZW5kKTsKICAgICAgfQogICAgICBpID0gZW5kIC0gMTsKICAgIH0KICB9CiAgZm9yIChpID0gMDsgaSA8IHN0ckxlbmd0aDsgKytpKSB7CiAgICBpZiAodHlwZXNbaV0gPT09ICJPTiIpIHsKICAgICAgdHlwZXNbaV0gPSBlOwogICAgfQogIH0KICBmb3IgKGkgPSAwOyBpIDwgc3RyTGVuZ3RoOyArK2kpIHsKICAgIHQgPSB0eXBlc1tpXTsKICAgIGlmIChpc0V2ZW4obGV2ZWxzW2ldKSkgewogICAgICBpZiAodCA9PT0gIlIiKSB7CiAgICAgICAgbGV2ZWxzW2ldICs9IDE7CiAgICAgIH0gZWxzZSBpZiAodCA9PT0gIkFOIiB8fCB0ID09PSAiRU4iKSB7CiAgICAgICAgbGV2ZWxzW2ldICs9IDI7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAodCA9PT0gIkwiIHx8IHQgPT09ICJBTiIgfHwgdCA9PT0gIkVOIikgewogICAgICBsZXZlbHNbaV0gKz0gMTsKICAgIH0KICB9CiAgbGV0IGhpZ2hlc3RMZXZlbCA9IC0xOwogIGxldCBsb3dlc3RPZGRMZXZlbCA9IDk5OwogIGxldCBsZXZlbDsKICBmb3IgKGkgPSAwLCBpaSA9IGxldmVscy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7CiAgICBsZXZlbCA9IGxldmVsc1tpXTsKICAgIGlmIChoaWdoZXN0TGV2ZWwgPCBsZXZlbCkgewogICAgICBoaWdoZXN0TGV2ZWwgPSBsZXZlbDsKICAgIH0KICAgIGlmIChsb3dlc3RPZGRMZXZlbCA+IGxldmVsICYmIGlzT2RkKGxldmVsKSkgewogICAgICBsb3dlc3RPZGRMZXZlbCA9IGxldmVsOwogICAgfQogIH0KICBmb3IgKGxldmVsID0gaGlnaGVzdExldmVsOyBsZXZlbCA+PSBsb3dlc3RPZGRMZXZlbDsgLS1sZXZlbCkgewogICAgbGV0IHN0YXJ0ID0gLTE7CiAgICBmb3IgKGkgPSAwLCBpaSA9IGxldmVscy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7CiAgICAgIGlmIChsZXZlbHNbaV0gPCBsZXZlbCkgewogICAgICAgIGlmIChzdGFydCA+PSAwKSB7CiAgICAgICAgICByZXZlcnNlVmFsdWVzKGNoYXJzLCBzdGFydCwgaSk7CiAgICAgICAgICBzdGFydCA9IC0xOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChzdGFydCA8IDApIHsKICAgICAgICBzdGFydCA9IGk7CiAgICAgIH0KICAgIH0KICAgIGlmIChzdGFydCA+PSAwKSB7CiAgICAgIHJldmVyc2VWYWx1ZXMoY2hhcnMsIHN0YXJ0LCBsZXZlbHMubGVuZ3RoKTsKICAgIH0KICB9CiAgZm9yIChpID0gMCwgaWkgPSBjaGFycy5sZW5ndGg7IGkgPCBpaTsgKytpKSB7CiAgICBjb25zdCBjaCA9IGNoYXJzW2ldOwogICAgaWYgKGNoID09PSAiPCIgfHwgY2ggPT09ICI+IikgewogICAgICBjaGFyc1tpXSA9ICIiOwogICAgfQogIH0KICByZXR1cm4gY3JlYXRlQmlkaVRleHQoY2hhcnMuam9pbigiIiksIGlzTFRSKTsKfQoKOy8vIC4vc3JjL3NoYXJlZC9vYmotYmluLXRyYW5zZm9ybS5qcwoKCgoKCgoKCgoKY2xhc3MgQ3NzRm9udEluZm8gewogICNidWZmZXI7CiAgI3ZpZXc7CiAgI2RlY29kZXI7CiAgc3RhdGljIHN0cmluZ3MgPSBbImZvbnRGYW1pbHkiLCAiZm9udFdlaWdodCIsICJpdGFsaWNBbmdsZSJdOwogIHN0YXRpYyB3cml0ZShpbmZvKSB7CiAgICBjb25zdCBlbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKCk7CiAgICBjb25zdCBlbmNvZGVkU3RyaW5ncyA9IHt9OwogICAgbGV0IHN0cmluZ3NMZW5ndGggPSAwOwogICAgZm9yIChjb25zdCBwcm9wIG9mIENzc0ZvbnRJbmZvLnN0cmluZ3MpIHsKICAgICAgY29uc3QgZW5jb2RlZCA9IGVuY29kZXIuZW5jb2RlKGluZm9bcHJvcF0pOwogICAgICBlbmNvZGVkU3RyaW5nc1twcm9wXSA9IGVuY29kZWQ7CiAgICAgIHN0cmluZ3NMZW5ndGggKz0gNCArIGVuY29kZWQubGVuZ3RoOwogICAgfQogICAgY29uc3QgYnVmZmVyID0gbmV3IEFycmF5QnVmZmVyKHN0cmluZ3NMZW5ndGgpOwogICAgY29uc3QgZGF0YSA9IG5ldyBVaW50OEFycmF5KGJ1ZmZlcik7CiAgICBjb25zdCB2aWV3ID0gbmV3IERhdGFWaWV3KGJ1ZmZlcik7CiAgICBsZXQgb2Zmc2V0ID0gMDsKICAgIGZvciAoY29uc3QgcHJvcCBvZiBDc3NGb250SW5mby5zdHJpbmdzKSB7CiAgICAgIGNvbnN0IGVuY29kZWQgPSBlbmNvZGVkU3RyaW5nc1twcm9wXTsKICAgICAgY29uc3QgbGVuZ3RoID0gZW5jb2RlZC5sZW5ndGg7CiAgICAgIHZpZXcuc2V0VWludDMyKG9mZnNldCwgbGVuZ3RoKTsKICAgICAgZGF0YS5zZXQoZW5jb2RlZCwgb2Zmc2V0ICsgNCk7CiAgICAgIG9mZnNldCArPSA0ICsgbGVuZ3RoOwogICAgfQogICAgYXNzZXJ0KG9mZnNldCA9PT0gYnVmZmVyLmJ5dGVMZW5ndGgsICJDc3NGb250SW5mby53cml0ZTogQnVmZmVyIG92ZXJmbG93Iik7CiAgICByZXR1cm4gYnVmZmVyOwogIH0KICBjb25zdHJ1Y3RvcihidWZmZXIpIHsKICAgIHRoaXMuI2J1ZmZlciA9IGJ1ZmZlcjsKICAgIHRoaXMuI3ZpZXcgPSBuZXcgRGF0YVZpZXcodGhpcy4jYnVmZmVyKTsKICAgIHRoaXMuI2RlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoKTsKICB9CiAgI3JlYWRTdHJpbmcoaW5kZXgpIHsKICAgIGFzc2VydChpbmRleCA8IENzc0ZvbnRJbmZvLnN0cmluZ3MubGVuZ3RoLCAiSW52YWxpZCBzdHJpbmcgaW5kZXgiKTsKICAgIGxldCBvZmZzZXQgPSAwOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbmRleDsgaSsrKSB7CiAgICAgIG9mZnNldCArPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpICsgNDsKICAgIH0KICAgIGNvbnN0IGxlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICByZXR1cm4gdGhpcy4jZGVjb2Rlci5kZWNvZGUobmV3IFVpbnQ4QXJyYXkodGhpcy4jYnVmZmVyLCBvZmZzZXQgKyA0LCBsZW5ndGgpKTsKICB9CiAgZ2V0IGZvbnRGYW1pbHkoKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZFN0cmluZygwKTsKICB9CiAgZ2V0IGZvbnRXZWlnaHQoKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZFN0cmluZygxKTsKICB9CiAgZ2V0IGl0YWxpY0FuZ2xlKCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWRTdHJpbmcoMik7CiAgfQp9CmNsYXNzIFN5c3RlbUZvbnRJbmZvIHsKICAjYnVmZmVyOwogICN2aWV3OwogICNkZWNvZGVyOwogIHN0YXRpYyBzdHJpbmdzID0gWyJjc3MiLCAibG9hZGVkTmFtZSIsICJiYXNlRm9udE5hbWUiLCAic3JjIl07CiAgc3RhdGljIHdyaXRlKGluZm8pIHsKICAgIGNvbnN0IGVuY29kZXIgPSBuZXcgVGV4dEVuY29kZXIoKTsKICAgIGNvbnN0IGVuY29kZWRTdHJpbmdzID0ge307CiAgICBsZXQgc3RyaW5nc0xlbmd0aCA9IDA7CiAgICBmb3IgKGNvbnN0IHByb3Agb2YgU3lzdGVtRm9udEluZm8uc3RyaW5ncykgewogICAgICBjb25zdCBlbmNvZGVkID0gZW5jb2Rlci5lbmNvZGUoaW5mb1twcm9wXSk7CiAgICAgIGVuY29kZWRTdHJpbmdzW3Byb3BdID0gZW5jb2RlZDsKICAgICAgc3RyaW5nc0xlbmd0aCArPSA0ICsgZW5jb2RlZC5sZW5ndGg7CiAgICB9CiAgICBzdHJpbmdzTGVuZ3RoICs9IDQ7CiAgICBsZXQgZW5jb2RlZFN0eWxlU3R5bGUsCiAgICAgIGVuY29kZWRTdHlsZVdlaWdodCwKICAgICAgbGVuZ3RoRXN0aW1hdGUgPSAxICsgc3RyaW5nc0xlbmd0aDsKICAgIGlmIChpbmZvLnN0eWxlKSB7CiAgICAgIGVuY29kZWRTdHlsZVN0eWxlID0gZW5jb2Rlci5lbmNvZGUoaW5mby5zdHlsZS5zdHlsZSk7CiAgICAgIGVuY29kZWRTdHlsZVdlaWdodCA9IGVuY29kZXIuZW5jb2RlKGluZm8uc3R5bGUud2VpZ2h0KTsKICAgICAgbGVuZ3RoRXN0aW1hdGUgKz0gNCArIGVuY29kZWRTdHlsZVN0eWxlLmxlbmd0aCArIDQgKyBlbmNvZGVkU3R5bGVXZWlnaHQubGVuZ3RoOwogICAgfQogICAgY29uc3QgYnVmZmVyID0gbmV3IEFycmF5QnVmZmVyKGxlbmd0aEVzdGltYXRlKTsKICAgIGNvbnN0IGRhdGEgPSBuZXcgVWludDhBcnJheShidWZmZXIpOwogICAgY29uc3QgdmlldyA9IG5ldyBEYXRhVmlldyhidWZmZXIpOwogICAgbGV0IG9mZnNldCA9IDA7CiAgICB2aWV3LnNldFVpbnQ4KG9mZnNldCsrLCBpbmZvLmd1ZXNzRmFsbGJhY2sgPyAxIDogMCk7CiAgICB2aWV3LnNldFVpbnQzMihvZmZzZXQsIDApOwogICAgb2Zmc2V0ICs9IDQ7CiAgICBzdHJpbmdzTGVuZ3RoID0gMDsKICAgIGZvciAoY29uc3QgcHJvcCBvZiBTeXN0ZW1Gb250SW5mby5zdHJpbmdzKSB7CiAgICAgIGNvbnN0IGVuY29kZWQgPSBlbmNvZGVkU3RyaW5nc1twcm9wXTsKICAgICAgY29uc3QgbGVuZ3RoID0gZW5jb2RlZC5sZW5ndGg7CiAgICAgIHN0cmluZ3NMZW5ndGggKz0gNCArIGxlbmd0aDsKICAgICAgdmlldy5zZXRVaW50MzIob2Zmc2V0LCBsZW5ndGgpOwogICAgICBkYXRhLnNldChlbmNvZGVkLCBvZmZzZXQgKyA0KTsKICAgICAgb2Zmc2V0ICs9IDQgKyBsZW5ndGg7CiAgICB9CiAgICB2aWV3LnNldFVpbnQzMihvZmZzZXQgLSBzdHJpbmdzTGVuZ3RoIC0gNCwgc3RyaW5nc0xlbmd0aCk7CiAgICBpZiAoaW5mby5zdHlsZSkgewogICAgICB2aWV3LnNldFVpbnQzMihvZmZzZXQsIGVuY29kZWRTdHlsZVN0eWxlLmxlbmd0aCk7CiAgICAgIGRhdGEuc2V0KGVuY29kZWRTdHlsZVN0eWxlLCBvZmZzZXQgKyA0KTsKICAgICAgb2Zmc2V0ICs9IDQgKyBlbmNvZGVkU3R5bGVTdHlsZS5sZW5ndGg7CiAgICAgIHZpZXcuc2V0VWludDMyKG9mZnNldCwgZW5jb2RlZFN0eWxlV2VpZ2h0Lmxlbmd0aCk7CiAgICAgIGRhdGEuc2V0KGVuY29kZWRTdHlsZVdlaWdodCwgb2Zmc2V0ICsgNCk7CiAgICAgIG9mZnNldCArPSA0ICsgZW5jb2RlZFN0eWxlV2VpZ2h0Lmxlbmd0aDsKICAgIH0KICAgIGFzc2VydChvZmZzZXQgPD0gYnVmZmVyLmJ5dGVMZW5ndGgsICJTdWJzdGl0aW9uSW5mby53cml0ZTogQnVmZmVyIG92ZXJmbG93Iik7CiAgICByZXR1cm4gYnVmZmVyLnRyYW5zZmVyVG9GaXhlZExlbmd0aChvZmZzZXQpOwogIH0KICBjb25zdHJ1Y3RvcihidWZmZXIpIHsKICAgIHRoaXMuI2J1ZmZlciA9IGJ1ZmZlcjsKICAgIHRoaXMuI3ZpZXcgPSBuZXcgRGF0YVZpZXcodGhpcy4jYnVmZmVyKTsKICAgIHRoaXMuI2RlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoKTsKICB9CiAgZ2V0IGd1ZXNzRmFsbGJhY2soKSB7CiAgICByZXR1cm4gdGhpcy4jdmlldy5nZXRVaW50OCgwKSAhPT0gMDsKICB9CiAgI3JlYWRTdHJpbmcoaW5kZXgpIHsKICAgIGFzc2VydChpbmRleCA8IFN5c3RlbUZvbnRJbmZvLnN0cmluZ3MubGVuZ3RoLCAiSW52YWxpZCBzdHJpbmcgaW5kZXgiKTsKICAgIGxldCBvZmZzZXQgPSA1OwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpbmRleDsgaSsrKSB7CiAgICAgIG9mZnNldCArPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpICsgNDsKICAgIH0KICAgIGNvbnN0IGxlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICByZXR1cm4gdGhpcy4jZGVjb2Rlci5kZWNvZGUobmV3IFVpbnQ4QXJyYXkodGhpcy4jYnVmZmVyLCBvZmZzZXQgKyA0LCBsZW5ndGgpKTsKICB9CiAgZ2V0IGNzcygpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkU3RyaW5nKDApOwogIH0KICBnZXQgbG9hZGVkTmFtZSgpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkU3RyaW5nKDEpOwogIH0KICBnZXQgYmFzZUZvbnROYW1lKCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWRTdHJpbmcoMik7CiAgfQogIGdldCBzcmMoKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZFN0cmluZygzKTsKICB9CiAgZ2V0IHN0eWxlKCkgewogICAgbGV0IG9mZnNldCA9IDE7CiAgICBvZmZzZXQgKz0gNCArIHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBjb25zdCBzdHlsZUxlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBjb25zdCBzdHlsZSA9IHRoaXMuI2RlY29kZXIuZGVjb2RlKG5ldyBVaW50OEFycmF5KHRoaXMuI2J1ZmZlciwgb2Zmc2V0ICsgNCwgc3R5bGVMZW5ndGgpKTsKICAgIG9mZnNldCArPSA0ICsgc3R5bGVMZW5ndGg7CiAgICBjb25zdCB3ZWlnaHRMZW5ndGggPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpOwogICAgY29uc3Qgd2VpZ2h0ID0gdGhpcy4jZGVjb2Rlci5kZWNvZGUobmV3IFVpbnQ4QXJyYXkodGhpcy4jYnVmZmVyLCBvZmZzZXQgKyA0LCB3ZWlnaHRMZW5ndGgpKTsKICAgIHJldHVybiB7CiAgICAgIHN0eWxlLAogICAgICB3ZWlnaHQKICAgIH07CiAgfQp9CmNsYXNzIEZvbnRJbmZvIHsKICBzdGF0aWMgYm9vbHMgPSBbImJsYWNrIiwgImJvbGQiLCAiZGlzYWJsZUZvbnRGYWNlIiwgImZvbnRFeHRyYVByb3BlcnRpZXMiLCAiaXNJbnZhbGlkUERGanNGb250IiwgImlzVHlwZTNGb250IiwgIml0YWxpYyIsICJtaXNzaW5nRmlsZSIsICJyZW1lYXN1cmUiLCAidmVydGljYWwiXTsKICBzdGF0aWMgbnVtYmVycyA9IFsiYXNjZW50IiwgImRlZmF1bHRXaWR0aCIsICJkZXNjZW50Il07CiAgc3RhdGljIHN0cmluZ3MgPSBbImZhbGxiYWNrTmFtZSIsICJsb2FkZWROYW1lIiwgIm1pbWV0eXBlIiwgIm5hbWUiXTsKICBzdGF0aWMgI09GRlNFVF9OVU1CRVJTID0gTWF0aC5jZWlsKHRoaXMuYm9vbHMubGVuZ3RoICogMiAvIDgpOwogIHN0YXRpYyAjT0ZGU0VUX0JCT1ggPSB0aGlzLiNPRkZTRVRfTlVNQkVSUyArIHRoaXMubnVtYmVycy5sZW5ndGggKiA4OwogIHN0YXRpYyAjT0ZGU0VUX0ZPTlRfTUFUUklYID0gdGhpcy4jT0ZGU0VUX0JCT1ggKyAxICsgMiAqIDQ7CiAgc3RhdGljICNPRkZTRVRfREVGQVVMVF9WTUVUUklDUyA9IHRoaXMuI09GRlNFVF9GT05UX01BVFJJWCArIDEgKyA4ICogNjsKICBzdGF0aWMgI09GRlNFVF9TVFJJTkdTID0gdGhpcy4jT0ZGU0VUX0RFRkFVTFRfVk1FVFJJQ1MgKyAxICsgMiAqIDM7CiAgI2J1ZmZlcjsKICAjZGVjb2RlcjsKICAjdmlldzsKICBjb25zdHJ1Y3Rvcih7CiAgICBkYXRhLAogICAgZXh0cmEKICB9KSB7CiAgICB0aGlzLiNidWZmZXIgPSBkYXRhOwogICAgdGhpcy4jZGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcigpOwogICAgdGhpcy4jdmlldyA9IG5ldyBEYXRhVmlldyh0aGlzLiNidWZmZXIpOwogICAgaWYgKGV4dHJhKSB7CiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgZXh0cmEpOwogICAgfQogIH0KICAjcmVhZEJvb2xlYW4oaW5kZXgpIHsKICAgIGFzc2VydChpbmRleCA8IEZvbnRJbmZvLmJvb2xzLmxlbmd0aCwgIkludmFsaWQgYm9vbGVhbiBpbmRleCIpOwogICAgY29uc3QgYnl0ZU9mZnNldCA9IE1hdGguZmxvb3IoaW5kZXggLyA0KTsKICAgIGNvbnN0IGJpdE9mZnNldCA9IGluZGV4ICogMiAlIDg7CiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuI3ZpZXcuZ2V0VWludDgoYnl0ZU9mZnNldCkgPj4gYml0T2Zmc2V0ICYgMHgwMzsKICAgIHJldHVybiB2YWx1ZSA9PT0gMHgwMCA/IHVuZGVmaW5lZCA6IHZhbHVlID09PSAweDAyOwogIH0KICBnZXQgYmxhY2soKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZEJvb2xlYW4oMCk7CiAgfQogIGdldCBib2xkKCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWRCb29sZWFuKDEpOwogIH0KICBnZXQgZGlzYWJsZUZvbnRGYWNlKCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWRCb29sZWFuKDIpOwogIH0KICBnZXQgZm9udEV4dHJhUHJvcGVydGllcygpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkQm9vbGVhbigzKTsKICB9CiAgZ2V0IGlzSW52YWxpZFBERmpzRm9udCgpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkQm9vbGVhbig0KTsKICB9CiAgZ2V0IGlzVHlwZTNGb250KCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWRCb29sZWFuKDUpOwogIH0KICBnZXQgaXRhbGljKCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWRCb29sZWFuKDYpOwogIH0KICBnZXQgbWlzc2luZ0ZpbGUoKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZEJvb2xlYW4oNyk7CiAgfQogIGdldCByZW1lYXN1cmUoKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZEJvb2xlYW4oOCk7CiAgfQogIGdldCB2ZXJ0aWNhbCgpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkQm9vbGVhbig5KTsKICB9CiAgI3JlYWROdW1iZXIoaW5kZXgpIHsKICAgIGFzc2VydChpbmRleCA8IEZvbnRJbmZvLm51bWJlcnMubGVuZ3RoLCAiSW52YWxpZCBudW1iZXIgaW5kZXgiKTsKICAgIHJldHVybiB0aGlzLiN2aWV3LmdldEZsb2F0NjQoRm9udEluZm8uI09GRlNFVF9OVU1CRVJTICsgaW5kZXggKiA4KTsKICB9CiAgZ2V0IGFzY2VudCgpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkTnVtYmVyKDApOwogIH0KICBnZXQgZGVmYXVsdFdpZHRoKCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWROdW1iZXIoMSk7CiAgfQogIGdldCBkZXNjZW50KCkgewogICAgcmV0dXJuIHRoaXMuI3JlYWROdW1iZXIoMik7CiAgfQogIGdldCBiYm94KCkgewogICAgbGV0IG9mZnNldCA9IEZvbnRJbmZvLiNPRkZTRVRfQkJPWDsKICAgIGNvbnN0IG51bUNvb3JkcyA9IHRoaXMuI3ZpZXcuZ2V0VWludDgob2Zmc2V0KTsKICAgIGlmIChudW1Db29yZHMgPT09IDApIHsKICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgIH0KICAgIG9mZnNldCArPSAxOwogICAgY29uc3QgYmJveCA9IFtdOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCA0OyBpKyspIHsKICAgICAgYmJveC5wdXNoKHRoaXMuI3ZpZXcuZ2V0SW50MTYob2Zmc2V0LCB0cnVlKSk7CiAgICAgIG9mZnNldCArPSAyOwogICAgfQogICAgcmV0dXJuIGJib3g7CiAgfQogIGdldCBmb250TWF0cml4KCkgewogICAgbGV0IG9mZnNldCA9IEZvbnRJbmZvLiNPRkZTRVRfRk9OVF9NQVRSSVg7CiAgICBjb25zdCBudW1Qb2ludHMgPSB0aGlzLiN2aWV3LmdldFVpbnQ4KG9mZnNldCk7CiAgICBpZiAobnVtUG9pbnRzID09PSAwKSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICBvZmZzZXQgKz0gMTsKICAgIGNvbnN0IGZvbnRNYXRyaXggPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgNjsgaSsrKSB7CiAgICAgIGZvbnRNYXRyaXgucHVzaCh0aGlzLiN2aWV3LmdldEZsb2F0NjQob2Zmc2V0LCB0cnVlKSk7CiAgICAgIG9mZnNldCArPSA4OwogICAgfQogICAgcmV0dXJuIGZvbnRNYXRyaXg7CiAgfQogIGdldCBkZWZhdWx0Vk1ldHJpY3MoKSB7CiAgICBsZXQgb2Zmc2V0ID0gRm9udEluZm8uI09GRlNFVF9ERUZBVUxUX1ZNRVRSSUNTOwogICAgY29uc3QgbnVtTWV0cmljcyA9IHRoaXMuI3ZpZXcuZ2V0VWludDgob2Zmc2V0KTsKICAgIGlmIChudW1NZXRyaWNzID09PSAwKSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICBvZmZzZXQgKz0gMTsKICAgIGNvbnN0IGRlZmF1bHRWTWV0cmljcyA9IFtdOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCAzOyBpKyspIHsKICAgICAgZGVmYXVsdFZNZXRyaWNzLnB1c2godGhpcy4jdmlldy5nZXRJbnQxNihvZmZzZXQsIHRydWUpKTsKICAgICAgb2Zmc2V0ICs9IDI7CiAgICB9CiAgICByZXR1cm4gZGVmYXVsdFZNZXRyaWNzOwogIH0KICAjcmVhZFN0cmluZyhpbmRleCkgewogICAgYXNzZXJ0KGluZGV4IDwgRm9udEluZm8uc3RyaW5ncy5sZW5ndGgsICJJbnZhbGlkIHN0cmluZyBpbmRleCIpOwogICAgbGV0IG9mZnNldCA9IEZvbnRJbmZvLiNPRkZTRVRfU1RSSU5HUyArIDQ7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGluZGV4OyBpKyspIHsKICAgICAgb2Zmc2V0ICs9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCkgKyA0OwogICAgfQogICAgY29uc3QgbGVuZ3RoID0gdGhpcy4jdmlldy5nZXRVaW50MzIob2Zmc2V0KTsKICAgIGNvbnN0IHN0cmluZ0RhdGEgPSBuZXcgVWludDhBcnJheShsZW5ndGgpOwogICAgc3RyaW5nRGF0YS5zZXQobmV3IFVpbnQ4QXJyYXkodGhpcy4jYnVmZmVyLCBvZmZzZXQgKyA0LCBsZW5ndGgpKTsKICAgIHJldHVybiB0aGlzLiNkZWNvZGVyLmRlY29kZShzdHJpbmdEYXRhKTsKICB9CiAgZ2V0IGZhbGxiYWNrTmFtZSgpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkU3RyaW5nKDApOwogIH0KICBnZXQgbG9hZGVkTmFtZSgpIHsKICAgIHJldHVybiB0aGlzLiNyZWFkU3RyaW5nKDEpOwogIH0KICBnZXQgbWltZXR5cGUoKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZFN0cmluZygyKTsKICB9CiAgZ2V0IG5hbWUoKSB7CiAgICByZXR1cm4gdGhpcy4jcmVhZFN0cmluZygzKTsKICB9CiAgZ2V0IGRhdGEoKSB7CiAgICBsZXQgb2Zmc2V0ID0gRm9udEluZm8uI09GRlNFVF9TVFJJTkdTOwogICAgY29uc3Qgc3RyaW5nc0xlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBvZmZzZXQgKz0gNCArIHN0cmluZ3NMZW5ndGg7CiAgICBjb25zdCBzeXN0ZW1Gb250SW5mb0xlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBvZmZzZXQgKz0gNCArIHN5c3RlbUZvbnRJbmZvTGVuZ3RoOwogICAgY29uc3QgY3NzRm9udEluZm9MZW5ndGggPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpOwogICAgb2Zmc2V0ICs9IDQgKyBjc3NGb250SW5mb0xlbmd0aDsKICAgIGNvbnN0IGxlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBpZiAobGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkodGhpcy4jYnVmZmVyLCBvZmZzZXQgKyA0LCBsZW5ndGgpOwogIH0KICBjbGVhckRhdGEoKSB7CiAgICBsZXQgb2Zmc2V0ID0gRm9udEluZm8uI09GRlNFVF9TVFJJTkdTOwogICAgY29uc3Qgc3RyaW5nc0xlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBvZmZzZXQgKz0gNCArIHN0cmluZ3NMZW5ndGg7CiAgICBjb25zdCBzeXN0ZW1Gb250SW5mb0xlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBvZmZzZXQgKz0gNCArIHN5c3RlbUZvbnRJbmZvTGVuZ3RoOwogICAgY29uc3QgY3NzRm9udEluZm9MZW5ndGggPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpOwogICAgb2Zmc2V0ICs9IDQgKyBjc3NGb250SW5mb0xlbmd0aDsKICAgIGNvbnN0IGxlbmd0aCA9IHRoaXMuI3ZpZXcuZ2V0VWludDMyKG9mZnNldCk7CiAgICBjb25zdCBkYXRhID0gbmV3IFVpbnQ4QXJyYXkodGhpcy4jYnVmZmVyLCBvZmZzZXQgKyA0LCBsZW5ndGgpOwogICAgZGF0YS5maWxsKDApOwogICAgdGhpcy4jdmlldy5zZXRVaW50MzIob2Zmc2V0LCAwKTsKICB9CiAgZ2V0IGNzc0ZvbnRJbmZvKCkgewogICAgbGV0IG9mZnNldCA9IEZvbnRJbmZvLiNPRkZTRVRfU1RSSU5HUzsKICAgIGNvbnN0IHN0cmluZ3NMZW5ndGggPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpOwogICAgb2Zmc2V0ICs9IDQgKyBzdHJpbmdzTGVuZ3RoOwogICAgY29uc3Qgc3lzdGVtRm9udEluZm9MZW5ndGggPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpOwogICAgb2Zmc2V0ICs9IDQgKyBzeXN0ZW1Gb250SW5mb0xlbmd0aDsKICAgIGNvbnN0IGNzc0ZvbnRJbmZvTGVuZ3RoID0gdGhpcy4jdmlldy5nZXRVaW50MzIob2Zmc2V0KTsKICAgIGlmIChjc3NGb250SW5mb0xlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IGNzc0ZvbnRJbmZvRGF0YSA9IG5ldyBVaW50OEFycmF5KGNzc0ZvbnRJbmZvTGVuZ3RoKTsKICAgIGNzc0ZvbnRJbmZvRGF0YS5zZXQobmV3IFVpbnQ4QXJyYXkodGhpcy4jYnVmZmVyLCBvZmZzZXQgKyA0LCBjc3NGb250SW5mb0xlbmd0aCkpOwogICAgcmV0dXJuIG5ldyBDc3NGb250SW5mbyhjc3NGb250SW5mb0RhdGEuYnVmZmVyKTsKICB9CiAgZ2V0IHN5c3RlbUZvbnRJbmZvKCkgewogICAgbGV0IG9mZnNldCA9IEZvbnRJbmZvLiNPRkZTRVRfU1RSSU5HUzsKICAgIGNvbnN0IHN0cmluZ3NMZW5ndGggPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpOwogICAgb2Zmc2V0ICs9IDQgKyBzdHJpbmdzTGVuZ3RoOwogICAgY29uc3Qgc3lzdGVtRm9udEluZm9MZW5ndGggPSB0aGlzLiN2aWV3LmdldFVpbnQzMihvZmZzZXQpOwogICAgaWYgKHN5c3RlbUZvbnRJbmZvTGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3Qgc3lzdGVtRm9udEluZm9EYXRhID0gbmV3IFVpbnQ4QXJyYXkoc3lzdGVtRm9udEluZm9MZW5ndGgpOwogICAgc3lzdGVtRm9udEluZm9EYXRhLnNldChuZXcgVWludDhBcnJheSh0aGlzLiNidWZmZXIsIG9mZnNldCArIDQsIHN5c3RlbUZvbnRJbmZvTGVuZ3RoKSk7CiAgICByZXR1cm4gbmV3IFN5c3RlbUZvbnRJbmZvKHN5c3RlbUZvbnRJbmZvRGF0YS5idWZmZXIpOwogIH0KICBzdGF0aWMgd3JpdGUoZm9udCkgewogICAgY29uc3Qgc3lzdGVtRm9udEluZm9CdWZmZXIgPSBmb250LnN5c3RlbUZvbnRJbmZvID8gU3lzdGVtRm9udEluZm8ud3JpdGUoZm9udC5zeXN0ZW1Gb250SW5mbykgOiBudWxsOwogICAgY29uc3QgY3NzRm9udEluZm9CdWZmZXIgPSBmb250LmNzc0ZvbnRJbmZvID8gQ3NzRm9udEluZm8ud3JpdGUoZm9udC5jc3NGb250SW5mbykgOiBudWxsOwogICAgY29uc3QgZW5jb2RlciA9IG5ldyBUZXh0RW5jb2RlcigpOwogICAgY29uc3QgZW5jb2RlZFN0cmluZ3MgPSB7fTsKICAgIGxldCBzdHJpbmdzTGVuZ3RoID0gMDsKICAgIGZvciAoY29uc3QgcHJvcCBvZiBGb250SW5mby5zdHJpbmdzKSB7CiAgICAgIGVuY29kZWRTdHJpbmdzW3Byb3BdID0gZW5jb2Rlci5lbmNvZGUoZm9udFtwcm9wXSk7CiAgICAgIHN0cmluZ3NMZW5ndGggKz0gNCArIGVuY29kZWRTdHJpbmdzW3Byb3BdLmxlbmd0aDsKICAgIH0KICAgIGNvbnN0IGxlbmd0aEVzdGltYXRlID0gRm9udEluZm8uI09GRlNFVF9TVFJJTkdTICsgNCArIHN0cmluZ3NMZW5ndGggKyA0ICsgKHN5c3RlbUZvbnRJbmZvQnVmZmVyID8gc3lzdGVtRm9udEluZm9CdWZmZXIuYnl0ZUxlbmd0aCA6IDApICsgNCArIChjc3NGb250SW5mb0J1ZmZlciA/IGNzc0ZvbnRJbmZvQnVmZmVyLmJ5dGVMZW5ndGggOiAwKSArIDQgKyAoZm9udC5kYXRhID8gZm9udC5kYXRhLmxlbmd0aCA6IDApOwogICAgY29uc3QgYnVmZmVyID0gbmV3IEFycmF5QnVmZmVyKGxlbmd0aEVzdGltYXRlKTsKICAgIGNvbnN0IGRhdGEgPSBuZXcgVWludDhBcnJheShidWZmZXIpOwogICAgY29uc3QgdmlldyA9IG5ldyBEYXRhVmlldyhidWZmZXIpOwogICAgbGV0IG9mZnNldCA9IDA7CiAgICBjb25zdCBudW1Cb29scyA9IEZvbnRJbmZvLmJvb2xzLmxlbmd0aDsKICAgIGxldCBib29sQnl0ZSA9IDAsCiAgICAgIGJvb2xCaXQgPSAwOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1Cb29sczsgaSsrKSB7CiAgICAgIGNvbnN0IHZhbHVlID0gZm9udFtGb250SW5mby5ib29sc1tpXV07CiAgICAgIGNvbnN0IGJpdHMgPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gMHgwMCA6IHZhbHVlID8gMHgwMiA6IDB4MDE7CiAgICAgIGJvb2xCeXRlIHw9IGJpdHMgPDwgYm9vbEJpdDsKICAgICAgYm9vbEJpdCArPSAyOwogICAgICBpZiAoYm9vbEJpdCA9PT0gOCB8fCBpID09PSBudW1Cb29scyAtIDEpIHsKICAgICAgICB2aWV3LnNldFVpbnQ4KG9mZnNldCsrLCBib29sQnl0ZSk7CiAgICAgICAgYm9vbEJ5dGUgPSAwOwogICAgICAgIGJvb2xCaXQgPSAwOwogICAgICB9CiAgICB9CiAgICBhc3NlcnQob2Zmc2V0ID09PSBGb250SW5mby4jT0ZGU0VUX05VTUJFUlMsICJGb250SW5mby53cml0ZTogQm9vbGVhbiBwcm9wZXJ0aWVzIG9mZnNldCBtaXNtYXRjaCIpOwogICAgZm9yIChjb25zdCBwcm9wIG9mIEZvbnRJbmZvLm51bWJlcnMpIHsKICAgICAgdmlldy5zZXRGbG9hdDY0KG9mZnNldCwgZm9udFtwcm9wXSk7CiAgICAgIG9mZnNldCArPSA4OwogICAgfQogICAgYXNzZXJ0KG9mZnNldCA9PT0gRm9udEluZm8uI09GRlNFVF9CQk9YLCAiRm9udEluZm8ud3JpdGU6IE51bWJlciBwcm9wZXJ0aWVzIG9mZnNldCBtaXNtYXRjaCIpOwogICAgaWYgKGZvbnQuYmJveCkgewogICAgICB2aWV3LnNldFVpbnQ4KG9mZnNldCsrLCA0KTsKICAgICAgZm9yIChjb25zdCBjb29yZCBvZiBmb250LmJib3gpIHsKICAgICAgICB2aWV3LnNldEludDE2KG9mZnNldCwgY29vcmQsIHRydWUpOwogICAgICAgIG9mZnNldCArPSAyOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB2aWV3LnNldFVpbnQ4KG9mZnNldCsrLCAwKTsKICAgICAgb2Zmc2V0ICs9IDIgKiA0OwogICAgfQogICAgYXNzZXJ0KG9mZnNldCA9PT0gRm9udEluZm8uI09GRlNFVF9GT05UX01BVFJJWCwgIkZvbnRJbmZvLndyaXRlOiBCQm94IHByb3BlcnRpZXMgb2Zmc2V0IG1pc21hdGNoIik7CiAgICBpZiAoZm9udC5mb250TWF0cml4KSB7CiAgICAgIHZpZXcuc2V0VWludDgob2Zmc2V0KyssIDYpOwogICAgICBmb3IgKGNvbnN0IHBvaW50IG9mIGZvbnQuZm9udE1hdHJpeCkgewogICAgICAgIHZpZXcuc2V0RmxvYXQ2NChvZmZzZXQsIHBvaW50LCB0cnVlKTsKICAgICAgICBvZmZzZXQgKz0gODsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgdmlldy5zZXRVaW50OChvZmZzZXQrKywgMCk7CiAgICAgIG9mZnNldCArPSA4ICogNjsKICAgIH0KICAgIGFzc2VydChvZmZzZXQgPT09IEZvbnRJbmZvLiNPRkZTRVRfREVGQVVMVF9WTUVUUklDUywgIkZvbnRJbmZvLndyaXRlOiBGb250TWF0cml4IHByb3BlcnRpZXMgb2Zmc2V0IG1pc21hdGNoIik7CiAgICBpZiAoZm9udC5kZWZhdWx0Vk1ldHJpY3MpIHsKICAgICAgdmlldy5zZXRVaW50OChvZmZzZXQrKywgMSk7CiAgICAgIGZvciAoY29uc3QgbWV0cmljIG9mIGZvbnQuZGVmYXVsdFZNZXRyaWNzKSB7CiAgICAgICAgdmlldy5zZXRJbnQxNihvZmZzZXQsIG1ldHJpYywgdHJ1ZSk7CiAgICAgICAgb2Zmc2V0ICs9IDI7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHZpZXcuc2V0VWludDgob2Zmc2V0KyssIDApOwogICAgICBvZmZzZXQgKz0gMyAqIDI7CiAgICB9CiAgICBhc3NlcnQob2Zmc2V0ID09PSBGb250SW5mby4jT0ZGU0VUX1NUUklOR1MsICJGb250SW5mby53cml0ZTogRGVmYXVsdFZNZXRyaWNzIHByb3BlcnRpZXMgb2Zmc2V0IG1pc21hdGNoIik7CiAgICB2aWV3LnNldFVpbnQzMihGb250SW5mby4jT0ZGU0VUX1NUUklOR1MsIDApOwogICAgb2Zmc2V0ICs9IDQ7CiAgICBmb3IgKGNvbnN0IHByb3Agb2YgRm9udEluZm8uc3RyaW5ncykgewogICAgICBjb25zdCBlbmNvZGVkID0gZW5jb2RlZFN0cmluZ3NbcHJvcF07CiAgICAgIGNvbnN0IGxlbmd0aCA9IGVuY29kZWQubGVuZ3RoOwogICAgICB2aWV3LnNldFVpbnQzMihvZmZzZXQsIGxlbmd0aCk7CiAgICAgIGRhdGEuc2V0KGVuY29kZWQsIG9mZnNldCArIDQpOwogICAgICBvZmZzZXQgKz0gNCArIGxlbmd0aDsKICAgIH0KICAgIHZpZXcuc2V0VWludDMyKEZvbnRJbmZvLiNPRkZTRVRfU1RSSU5HUywgb2Zmc2V0IC0gRm9udEluZm8uI09GRlNFVF9TVFJJTkdTIC0gNCk7CiAgICBpZiAoIXN5c3RlbUZvbnRJbmZvQnVmZmVyKSB7CiAgICAgIHZpZXcuc2V0VWludDMyKG9mZnNldCwgMCk7CiAgICAgIG9mZnNldCArPSA0OwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgbGVuZ3RoID0gc3lzdGVtRm9udEluZm9CdWZmZXIuYnl0ZUxlbmd0aDsKICAgICAgdmlldy5zZXRVaW50MzIob2Zmc2V0LCBsZW5ndGgpOwogICAgICBhc3NlcnQob2Zmc2V0ICsgNCArIGxlbmd0aCA8PSBidWZmZXIuYnl0ZUxlbmd0aCwgIkZvbnRJbmZvLndyaXRlOiBCdWZmZXIgb3ZlcmZsb3cgYXQgc3lzdGVtRm9udEluZm8iKTsKICAgICAgZGF0YS5zZXQobmV3IFVpbnQ4QXJyYXkoc3lzdGVtRm9udEluZm9CdWZmZXIpLCBvZmZzZXQgKyA0KTsKICAgICAgb2Zmc2V0ICs9IDQgKyBsZW5ndGg7CiAgICB9CiAgICBpZiAoIWNzc0ZvbnRJbmZvQnVmZmVyKSB7CiAgICAgIHZpZXcuc2V0VWludDMyKG9mZnNldCwgMCk7CiAgICAgIG9mZnNldCArPSA0OwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgbGVuZ3RoID0gY3NzRm9udEluZm9CdWZmZXIuYnl0ZUxlbmd0aDsKICAgICAgdmlldy5zZXRVaW50MzIob2Zmc2V0LCBsZW5ndGgpOwogICAgICBhc3NlcnQob2Zmc2V0ICsgNCArIGxlbmd0aCA8PSBidWZmZXIuYnl0ZUxlbmd0aCwgIkZvbnRJbmZvLndyaXRlOiBCdWZmZXIgb3ZlcmZsb3cgYXQgY3NzRm9udEluZm8iKTsKICAgICAgZGF0YS5zZXQobmV3IFVpbnQ4QXJyYXkoY3NzRm9udEluZm9CdWZmZXIpLCBvZmZzZXQgKyA0KTsKICAgICAgb2Zmc2V0ICs9IDQgKyBsZW5ndGg7CiAgICB9CiAgICBpZiAoZm9udC5kYXRhID09PSB1bmRlZmluZWQpIHsKICAgICAgdmlldy5zZXRVaW50MzIob2Zmc2V0LCAwKTsKICAgICAgb2Zmc2V0ICs9IDQ7CiAgICB9IGVsc2UgewogICAgICB2aWV3LnNldFVpbnQzMihvZmZzZXQsIGZvbnQuZGF0YS5sZW5ndGgpOwogICAgICBkYXRhLnNldChmb250LmRhdGEsIG9mZnNldCArIDQpOwogICAgICBvZmZzZXQgKz0gNCArIGZvbnQuZGF0YS5sZW5ndGg7CiAgICB9CiAgICBhc3NlcnQob2Zmc2V0IDw9IGJ1ZmZlci5ieXRlTGVuZ3RoLCAiRm9udEluZm8ud3JpdGU6IEJ1ZmZlciBvdmVyZmxvdyIpOwogICAgcmV0dXJuIGJ1ZmZlci50cmFuc2ZlclRvRml4ZWRMZW5ndGgob2Zmc2V0KTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2ZvbnRfc3Vic3RpdHV0aW9ucy5qcwoKCgoKCgoKCgoKCgoKY29uc3QgTk9STUFMID0gewogIHN0eWxlOiAibm9ybWFsIiwKICB3ZWlnaHQ6ICJub3JtYWwiCn07CmNvbnN0IEJPTEQgPSB7CiAgc3R5bGU6ICJub3JtYWwiLAogIHdlaWdodDogImJvbGQiCn07CmNvbnN0IElUQUxJQyA9IHsKICBzdHlsZTogIml0YWxpYyIsCiAgd2VpZ2h0OiAibm9ybWFsIgp9Owpjb25zdCBCT0xESVRBTElDID0gewogIHN0eWxlOiAiaXRhbGljIiwKICB3ZWlnaHQ6ICJib2xkIgp9Owpjb25zdCBzdWJzdGl0dXRpb25NYXAgPSBuZXcgTWFwKFtbIlRpbWVzLVJvbWFuIiwgewogIGxvY2FsOiBbIlRpbWVzIE5ldyBSb21hbiIsICJUaW1lcy1Sb21hbiIsICJUaW1lcyIsICJMaWJlcmF0aW9uIFNlcmlmIiwgIk5pbWJ1cyBSb21hbiIsICJOaW1idXMgUm9tYW4gTCIsICJUaW5vcyIsICJUaG9ybmRhbGUiLCAiVGVYIEd5cmUgVGVybWVzIiwgIkZyZWVTZXJpZiIsICJMaW51eCBMaWJlcnRpbmUgTyIsICJMaWJlcnRpbnVzIFNlcmlmIiwgIkRlamFWdSBTZXJpZiIsICJCaXRzdHJlYW0gVmVyYSBTZXJpZiIsICJVYnVudHUiXSwKICBzdHlsZTogTk9STUFMLAogIHVsdGltYXRlOiAic2VyaWYiCn1dLCBbIlRpbWVzLUJvbGQiLCB7CiAgYWxpYXM6ICJUaW1lcy1Sb21hbiIsCiAgc3R5bGU6IEJPTEQsCiAgdWx0aW1hdGU6ICJzZXJpZiIKfV0sIFsiVGltZXMtSXRhbGljIiwgewogIGFsaWFzOiAiVGltZXMtUm9tYW4iLAogIHN0eWxlOiBJVEFMSUMsCiAgdWx0aW1hdGU6ICJzZXJpZiIKfV0sIFsiVGltZXMtQm9sZEl0YWxpYyIsIHsKICBhbGlhczogIlRpbWVzLVJvbWFuIiwKICBzdHlsZTogQk9MRElUQUxJQywKICB1bHRpbWF0ZTogInNlcmlmIgp9XSwgWyJIZWx2ZXRpY2EiLCB7CiAgbG9jYWw6IFsiSGVsdmV0aWNhIiwgIkhlbHZldGljYSBOZXVlIiwgIkFyaWFsIiwgIkFyaWFsIE5vdmEiLCAiTGliZXJhdGlvbiBTYW5zIiwgIkFyaW1vIiwgIk5pbWJ1cyBTYW5zIiwgIk5pbWJ1cyBTYW5zIEwiLCAiQTAzMCIsICJUZVggR3lyZSBIZXJvcyIsICJGcmVlU2FucyIsICJEZWphVnUgU2FucyIsICJBbGJhbnkiLCAiQml0c3RyZWFtIFZlcmEgU2FucyIsICJBcmlhbCBVbmljb2RlIE1TIiwgIk1pY3Jvc29mdCBTYW5zIFNlcmlmIiwgIkFwcGxlIFN5bWJvbHMiLCAiQ2FudGFyZWxsIl0sCiAgcGF0aDogIkxpYmVyYXRpb25TYW5zLVJlZ3VsYXIudHRmIiwKICBzdHlsZTogTk9STUFMLAogIHVsdGltYXRlOiAic2Fucy1zZXJpZiIKfV0sIFsiSGVsdmV0aWNhLUJvbGQiLCB7CiAgYWxpYXM6ICJIZWx2ZXRpY2EiLAogIHBhdGg6ICJMaWJlcmF0aW9uU2Fucy1Cb2xkLnR0ZiIsCiAgc3R5bGU6IEJPTEQsCiAgdWx0aW1hdGU6ICJzYW5zLXNlcmlmIgp9XSwgWyJIZWx2ZXRpY2EtT2JsaXF1ZSIsIHsKICBhbGlhczogIkhlbHZldGljYSIsCiAgcGF0aDogIkxpYmVyYXRpb25TYW5zLUl0YWxpYy50dGYiLAogIHN0eWxlOiBJVEFMSUMsCiAgdWx0aW1hdGU6ICJzYW5zLXNlcmlmIgp9XSwgWyJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiLCB7CiAgYWxpYXM6ICJIZWx2ZXRpY2EiLAogIHBhdGg6ICJMaWJlcmF0aW9uU2Fucy1Cb2xkSXRhbGljLnR0ZiIsCiAgc3R5bGU6IEJPTERJVEFMSUMsCiAgdWx0aW1hdGU6ICJzYW5zLXNlcmlmIgp9XSwgWyJDb3VyaWVyIiwgewogIGxvY2FsOiBbIkNvdXJpZXIiLCAiQ291cmllciBOZXciLCAiTGliZXJhdGlvbiBNb25vIiwgIk5pbWJ1cyBNb25vIiwgIk5pbWJ1cyBNb25vIEwiLCAiQ291c2luZSIsICJDdW1iZXJsYW5kIiwgIlRlWCBHeXJlIEN1cnNvciIsICJGcmVlTW9ubyIsICJMaW51eCBMaWJlcnRpbmUgTW9ubyBPIiwgIkxpYmVydGludXMgTW9ubyJdLAogIHN0eWxlOiBOT1JNQUwsCiAgdWx0aW1hdGU6ICJtb25vc3BhY2UiCn1dLCBbIkNvdXJpZXItQm9sZCIsIHsKICBhbGlhczogIkNvdXJpZXIiLAogIHN0eWxlOiBCT0xELAogIHVsdGltYXRlOiAibW9ub3NwYWNlIgp9XSwgWyJDb3VyaWVyLU9ibGlxdWUiLCB7CiAgYWxpYXM6ICJDb3VyaWVyIiwKICBzdHlsZTogSVRBTElDLAogIHVsdGltYXRlOiAibW9ub3NwYWNlIgp9XSwgWyJDb3VyaWVyLUJvbGRPYmxpcXVlIiwgewogIGFsaWFzOiAiQ291cmllciIsCiAgc3R5bGU6IEJPTERJVEFMSUMsCiAgdWx0aW1hdGU6ICJtb25vc3BhY2UiCn1dLCBbIkFyaWFsQmxhY2siLCB7CiAgbG9jYWw6IFsiQXJpYWwgQmxhY2siXSwKICBzdHlsZTogewogICAgc3R5bGU6ICJub3JtYWwiLAogICAgd2VpZ2h0OiAiOTAwIgogIH0sCiAgZmFsbGJhY2s6ICJIZWx2ZXRpY2EtQm9sZCIKfV0sIFsiQXJpYWxCbGFjay1Cb2xkIiwgewogIGFsaWFzOiAiQXJpYWxCbGFjayIKfV0sIFsiQXJpYWxCbGFjay1JdGFsaWMiLCB7CiAgYWxpYXM6ICJBcmlhbEJsYWNrIiwKICBzdHlsZTogewogICAgc3R5bGU6ICJpdGFsaWMiLAogICAgd2VpZ2h0OiAiOTAwIgogIH0sCiAgZmFsbGJhY2s6ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiCn1dLCBbIkFyaWFsQmxhY2stQm9sZEl0YWxpYyIsIHsKICBhbGlhczogIkFyaWFsQmxhY2stSXRhbGljIgp9XSwgWyJBcmlhbE5hcnJvdyIsIHsKICBsb2NhbDogWyJBcmlhbCBOYXJyb3ciLCAiTGliZXJhdGlvbiBTYW5zIE5hcnJvdyIsICJIZWx2ZXRpY2EgQ29uZGVuc2VkIiwgIk5pbWJ1cyBTYW5zIE5hcnJvdyIsICJUZVggR3lyZSBIZXJvcyBDbiJdLAogIHN0eWxlOiBOT1JNQUwsCiAgZmFsbGJhY2s6ICJIZWx2ZXRpY2EiCn1dLCBbIkFyaWFsTmFycm93LUJvbGQiLCB7CiAgYWxpYXM6ICJBcmlhbE5hcnJvdyIsCiAgc3R5bGU6IEJPTEQsCiAgZmFsbGJhY2s6ICJIZWx2ZXRpY2EtQm9sZCIKfV0sIFsiQXJpYWxOYXJyb3ctSXRhbGljIiwgewogIGFsaWFzOiAiQXJpYWxOYXJyb3ciLAogIHN0eWxlOiBJVEFMSUMsCiAgZmFsbGJhY2s6ICJIZWx2ZXRpY2EtT2JsaXF1ZSIKfV0sIFsiQXJpYWxOYXJyb3ctQm9sZEl0YWxpYyIsIHsKICBhbGlhczogIkFyaWFsTmFycm93IiwKICBzdHlsZTogQk9MRElUQUxJQywKICBmYWxsYmFjazogIkhlbHZldGljYS1Cb2xkT2JsaXF1ZSIKfV0sIFsiQ2FsaWJyaSIsIHsKICBsb2NhbDogWyJDYWxpYnJpIiwgIkNhcmxpdG8iXSwKICBzdHlsZTogTk9STUFMLAogIGZhbGxiYWNrOiAiSGVsdmV0aWNhIgp9XSwgWyJDYWxpYnJpLUJvbGQiLCB7CiAgYWxpYXM6ICJDYWxpYnJpIiwKICBzdHlsZTogQk9MRCwKICBmYWxsYmFjazogIkhlbHZldGljYS1Cb2xkIgp9XSwgWyJDYWxpYnJpLUl0YWxpYyIsIHsKICBhbGlhczogIkNhbGlicmkiLAogIHN0eWxlOiBJVEFMSUMsCiAgZmFsbGJhY2s6ICJIZWx2ZXRpY2EtT2JsaXF1ZSIKfV0sIFsiQ2FsaWJyaS1Cb2xkSXRhbGljIiwgewogIGFsaWFzOiAiQ2FsaWJyaSIsCiAgc3R5bGU6IEJPTERJVEFMSUMsCiAgZmFsbGJhY2s6ICJIZWx2ZXRpY2EtQm9sZE9ibGlxdWUiCn1dLCBbIldpbmdkaW5ncyIsIHsKICBsb2NhbDogWyJXaW5nZGluZ3MiLCAiVVJXIERpbmdiYXRzIl0sCiAgc3R5bGU6IE5PUk1BTAp9XSwgWyJXaW5nZGluZ3MtUmVndWxhciIsIHsKICBhbGlhczogIldpbmdkaW5ncyIKfV0sIFsiV2luZ2RpbmdzLUJvbGQiLCB7CiAgYWxpYXM6ICJXaW5nZGluZ3MiCn1dXSk7CmNvbnN0IGZvbnRBbGlhc2VzID0gbmV3IE1hcChbWyJBcmlhbC1CbGFjayIsICJBcmlhbEJsYWNrIl1dKTsKZnVuY3Rpb24gZ2V0U3R5bGVUb0FwcGVuZChzdHlsZSkgewogIHN3aXRjaCAoc3R5bGUpIHsKICAgIGNhc2UgQk9MRDoKICAgICAgcmV0dXJuICJCb2xkIjsKICAgIGNhc2UgSVRBTElDOgogICAgICByZXR1cm4gIkl0YWxpYyI7CiAgICBjYXNlIEJPTERJVEFMSUM6CiAgICAgIHJldHVybiAiQm9sZCBJdGFsaWMiOwogICAgZGVmYXVsdDoKICAgICAgaWYgKHN0eWxlPy53ZWlnaHQgPT09ICJib2xkIikgewogICAgICAgIHJldHVybiAiQm9sZCI7CiAgICAgIH0KICAgICAgaWYgKHN0eWxlPy5zdHlsZSA9PT0gIml0YWxpYyIpIHsKICAgICAgICByZXR1cm4gIkl0YWxpYyI7CiAgICAgIH0KICB9CiAgcmV0dXJuICIiOwp9CmZ1bmN0aW9uIGdldEZhbWlseU5hbWUoc3RyKSB7CiAgY29uc3Qga2V5d29yZHMgPSBuZXcgU2V0KFsidGhpbiIsICJleHRyYWxpZ2h0IiwgInVsdHJhbGlnaHQiLCAiZGVtaWxpZ2h0IiwgInNlbWlsaWdodCIsICJsaWdodCIsICJib29rIiwgInJlZ3VsYXIiLCAibm9ybWFsIiwgIm1lZGl1bSIsICJkZW1pYm9sZCIsICJzZW1pYm9sZCIsICJib2xkIiwgImV4dHJhYm9sZCIsICJ1bHRyYWJvbGQiLCAiYmxhY2siLCAiaGVhdnkiLCAiZXh0cmFibGFjayIsICJ1bHRyYWJsYWNrIiwgInJvbWFuIiwgIml0YWxpYyIsICJvYmxpcXVlIiwgInVsdHJhY29uZGVuc2VkIiwgImV4dHJhY29uZGVuc2VkIiwgImNvbmRlbnNlZCIsICJzZW1pY29uZGVuc2VkIiwgIm5vcm1hbCIsICJzZW1pZXhwYW5kZWQiLCAiZXhwYW5kZWQiLCAiZXh0cmFleHBhbmRlZCIsICJ1bHRyYWV4cGFuZGVkIiwgImJvbGRpdGFsaWMiXSk7CiAgcmV0dXJuIHN0ci5zcGxpdCgvWy0gLCtdKy9nKS5maWx0ZXIodG9rID0+ICFrZXl3b3Jkcy5oYXModG9rLnRvTG93ZXJDYXNlKCkpKS5qb2luKCIgIik7Cn0KZnVuY3Rpb24gZ2VuZXJhdGVGb250KHsKICBhbGlhcywKICBsb2NhbCwKICBwYXRoLAogIGZhbGxiYWNrLAogIHN0eWxlLAogIHVsdGltYXRlCn0sIHNyYywgbG9jYWxGb250UGF0aCwgdXNlRmFsbGJhY2sgPSB0cnVlLCB1c2VQYXRoID0gdHJ1ZSwgYXBwZW5kID0gIiIpIHsKICBjb25zdCByZXN1bHQgPSB7CiAgICBzdHlsZTogbnVsbCwKICAgIHVsdGltYXRlOiBudWxsCiAgfTsKICBpZiAobG9jYWwpIHsKICAgIGNvbnN0IGV4dHJhID0gYXBwZW5kID8gYCAke2FwcGVuZH1gIDogIiI7CiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgbG9jYWwpIHsKICAgICAgc3JjLnB1c2goYGxvY2FsKCR7bmFtZX0ke2V4dHJhfSlgKTsKICAgIH0KICB9CiAgaWYgKGFsaWFzKSB7CiAgICBjb25zdCBzdWJzdGl0dXRpb24gPSBzdWJzdGl0dXRpb25NYXAuZ2V0KGFsaWFzKTsKICAgIGNvbnN0IGFsaWFzQXBwZW5kID0gYXBwZW5kIHx8IGdldFN0eWxlVG9BcHBlbmQoc3R5bGUpOwogICAgT2JqZWN0LmFzc2lnbihyZXN1bHQsIGdlbmVyYXRlRm9udChzdWJzdGl0dXRpb24sIHNyYywgbG9jYWxGb250UGF0aCwgdXNlRmFsbGJhY2sgJiYgIWZhbGxiYWNrLCB1c2VQYXRoICYmICFwYXRoLCBhbGlhc0FwcGVuZCkpOwogIH0KICBpZiAoc3R5bGUpIHsKICAgIHJlc3VsdC5zdHlsZSA9IHN0eWxlOwogIH0KICBpZiAodWx0aW1hdGUpIHsKICAgIHJlc3VsdC51bHRpbWF0ZSA9IHVsdGltYXRlOwogIH0KICBpZiAodXNlRmFsbGJhY2sgJiYgZmFsbGJhY2spIHsKICAgIGNvbnN0IGZhbGxiYWNrSW5mbyA9IHN1YnN0aXR1dGlvbk1hcC5nZXQoZmFsbGJhY2spOwogICAgY29uc3QgewogICAgICB1bHRpbWF0ZTogZmFsbGJhY2tVbHRpbWF0ZQogICAgfSA9IGdlbmVyYXRlRm9udChmYWxsYmFja0luZm8sIHNyYywgbG9jYWxGb250UGF0aCwgdXNlRmFsbGJhY2ssIHVzZVBhdGggJiYgIXBhdGgsIGFwcGVuZCk7CiAgICByZXN1bHQudWx0aW1hdGUgfHw9IGZhbGxiYWNrVWx0aW1hdGU7CiAgfQogIGlmICh1c2VQYXRoICYmIHBhdGggJiYgbG9jYWxGb250UGF0aCkgewogICAgc3JjLnB1c2goYHVybCgke2xvY2FsRm9udFBhdGh9JHtwYXRofSlgKTsKICB9CiAgcmV0dXJuIHJlc3VsdDsKfQpmdW5jdGlvbiBnZXRGb250U3Vic3RpdHV0aW9uKHN5c3RlbUZvbnRDYWNoZSwgaWRGYWN0b3J5LCBsb2NhbEZvbnRQYXRoLCBiYXNlRm9udE5hbWUsIHN0YW5kYXJkRm9udE5hbWUsIHR5cGUpIHsKICBpZiAoYmFzZUZvbnROYW1lLnN0YXJ0c1dpdGgoIkludmFsaWRQREZqc0ZvbnRfIikpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBpZiAoKHR5cGUgPT09ICJUcnVlVHlwZSIgfHwgdHlwZSA9PT0gIlR5cGUxIikgJiYgL15bQS1aXXs2fVwrLy50ZXN0KGJhc2VGb250TmFtZSkpIHsKICAgIGJhc2VGb250TmFtZSA9IGJhc2VGb250TmFtZS5zbGljZSg3KTsKICB9CiAgYmFzZUZvbnROYW1lID0gbm9ybWFsaXplRm9udE5hbWUoYmFzZUZvbnROYW1lKTsKICBjb25zdCBrZXkgPSBiYXNlRm9udE5hbWU7CiAgbGV0IHN1YnN0aXR1dGlvbkluZm8gPSBzeXN0ZW1Gb250Q2FjaGUuZ2V0KGtleSk7CiAgaWYgKHN1YnN0aXR1dGlvbkluZm8pIHsKICAgIHJldHVybiBzdWJzdGl0dXRpb25JbmZvOwogIH0KICBsZXQgc3Vic3RpdHV0aW9uID0gc3Vic3RpdHV0aW9uTWFwLmdldChiYXNlRm9udE5hbWUpOwogIGlmICghc3Vic3RpdHV0aW9uKSB7CiAgICBmb3IgKGNvbnN0IFthbGlhcywgc3Vic3RdIG9mIGZvbnRBbGlhc2VzKSB7CiAgICAgIGlmIChiYXNlRm9udE5hbWUuc3RhcnRzV2l0aChhbGlhcykpIHsKICAgICAgICBiYXNlRm9udE5hbWUgPSBgJHtzdWJzdH0ke2Jhc2VGb250TmFtZS5zdWJzdHJpbmcoYWxpYXMubGVuZ3RoKX1gOwogICAgICAgIHN1YnN0aXR1dGlvbiA9IHN1YnN0aXR1dGlvbk1hcC5nZXQoYmFzZUZvbnROYW1lKTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogIH0KICBsZXQgbXVzdEFkZEJhc2VGb250ID0gZmFsc2U7CiAgaWYgKCFzdWJzdGl0dXRpb24pIHsKICAgIHN1YnN0aXR1dGlvbiA9IHN1YnN0aXR1dGlvbk1hcC5nZXQoc3RhbmRhcmRGb250TmFtZSk7CiAgICBtdXN0QWRkQmFzZUZvbnQgPSB0cnVlOwogIH0KICBjb25zdCBsb2FkZWROYW1lID0gYCR7aWRGYWN0b3J5LmdldERvY0lkKCl9X3Mke2lkRmFjdG9yeS5jcmVhdGVGb250SWQoKX1gOwogIGlmICghc3Vic3RpdHV0aW9uKSB7CiAgICBpZiAoIXZhbGlkYXRlRm9udE5hbWUoYmFzZUZvbnROYW1lKSkgewogICAgICB3YXJuKGBDYW5ub3Qgc3Vic3RpdHV0ZSB0aGUgZm9udCBiZWNhdXNlIG9mIGl0cyBuYW1lOiAke2Jhc2VGb250TmFtZX1gKTsKICAgICAgc3lzdGVtRm9udENhY2hlLnNldChrZXksIG51bGwpOwogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IGJvbGQgPSAvYm9sZC9naS50ZXN0KGJhc2VGb250TmFtZSk7CiAgICBjb25zdCBpdGFsaWMgPSAvb2JsaXF1ZXxpdGFsaWMvZ2kudGVzdChiYXNlRm9udE5hbWUpOwogICAgY29uc3Qgc3R5bGUgPSBib2xkICYmIGl0YWxpYyAmJiBCT0xESVRBTElDIHx8IGJvbGQgJiYgQk9MRCB8fCBpdGFsaWMgJiYgSVRBTElDIHx8IE5PUk1BTDsKICAgIHN1YnN0aXR1dGlvbkluZm8gPSB7CiAgICAgIGNzczogYCIke2dldEZhbWlseU5hbWUoYmFzZUZvbnROYW1lKX0iLCR7bG9hZGVkTmFtZX1gLAogICAgICBndWVzc0ZhbGxiYWNrOiB0cnVlLAogICAgICBsb2FkZWROYW1lLAogICAgICBiYXNlRm9udE5hbWUsCiAgICAgIHNyYzogYGxvY2FsKCR7YmFzZUZvbnROYW1lfSlgLAogICAgICBzdHlsZQogICAgfTsKICAgIHN5c3RlbUZvbnRDYWNoZS5zZXQoa2V5LCBzdWJzdGl0dXRpb25JbmZvKTsKICAgIHJldHVybiBzdWJzdGl0dXRpb25JbmZvOwogIH0KICBjb25zdCBzcmMgPSBbXTsKICBpZiAobXVzdEFkZEJhc2VGb250ICYmIHZhbGlkYXRlRm9udE5hbWUoYmFzZUZvbnROYW1lKSkgewogICAgc3JjLnB1c2goYGxvY2FsKCR7YmFzZUZvbnROYW1lfSlgKTsKICB9CiAgY29uc3QgewogICAgc3R5bGUsCiAgICB1bHRpbWF0ZQogIH0gPSBnZW5lcmF0ZUZvbnQoc3Vic3RpdHV0aW9uLCBzcmMsIGxvY2FsRm9udFBhdGgpOwogIGNvbnN0IGd1ZXNzRmFsbGJhY2sgPSB1bHRpbWF0ZSA9PT0gbnVsbDsKICBjb25zdCBmYWxsYmFjayA9IGd1ZXNzRmFsbGJhY2sgPyAiIiA6IGAsJHt1bHRpbWF0ZX1gOwogIHN1YnN0aXR1dGlvbkluZm8gPSB7CiAgICBjc3M6IGAiJHtnZXRGYW1pbHlOYW1lKGJhc2VGb250TmFtZSl9Iiwke2xvYWRlZE5hbWV9JHtmYWxsYmFja31gLAogICAgZ3Vlc3NGYWxsYmFjaywKICAgIGxvYWRlZE5hbWUsCiAgICBiYXNlRm9udE5hbWUsCiAgICBzcmM6IHNyYy5qb2luKCIsIiksCiAgICBzdHlsZQogIH07CiAgc3lzdGVtRm9udENhY2hlLnNldChrZXksIHN1YnN0aXR1dGlvbkluZm8pOwogIHJldHVybiBzdWJzdGl0dXRpb25JbmZvOwp9Cgo7Ly8gLi9zcmMvc2hhcmVkL211cm11cmhhc2gzLmpzCgoKCgoKCgoKY29uc3QgU0VFRCA9IDB4YzNkMmUxZjA7CmNvbnN0IE1BU0tfSElHSCA9IDB4ZmZmZjAwMDA7CmNvbnN0IE1BU0tfTE9XID0gMHhmZmZmOwpjbGFzcyBNdXJtdXJIYXNoM182NCB7CiAgY29uc3RydWN0b3Ioc2VlZCkgewogICAgdGhpcy5oMSA9IHNlZWQgPyBzZWVkICYgMHhmZmZmZmZmZiA6IFNFRUQ7CiAgICB0aGlzLmgyID0gc2VlZCA/IHNlZWQgJiAweGZmZmZmZmZmIDogU0VFRDsKICB9CiAgdXBkYXRlKGlucHV0KSB7CiAgICBsZXQgZGF0YSwgbGVuZ3RoOwogICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gInN0cmluZyIpIHsKICAgICAgZGF0YSA9IG5ldyBVaW50OEFycmF5KGlucHV0Lmxlbmd0aCAqIDIpOwogICAgICBsZW5ndGggPSAwOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBpbnB1dC5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29uc3QgY29kZSA9IGlucHV0LmNoYXJDb2RlQXQoaSk7CiAgICAgICAgaWYgKGNvZGUgPD0gMHhmZikgewogICAgICAgICAgZGF0YVtsZW5ndGgrK10gPSBjb2RlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBkYXRhW2xlbmd0aCsrXSA9IGNvZGUgPj4+IDg7CiAgICAgICAgICBkYXRhW2xlbmd0aCsrXSA9IGNvZGUgJiAweGZmOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIGlmIChBcnJheUJ1ZmZlci5pc1ZpZXcoaW5wdXQpKSB7CiAgICAgIGRhdGEgPSBpbnB1dC5zbGljZSgpOwogICAgICBsZW5ndGggPSBkYXRhLmJ5dGVMZW5ndGg7CiAgICB9IGVsc2UgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIkludmFsaWQgZGF0YSBmb3JtYXQsIG11c3QgYmUgYSBzdHJpbmcgb3IgVHlwZWRBcnJheS4iKTsKICAgIH0KICAgIGNvbnN0IGJsb2NrQ291bnRzID0gbGVuZ3RoID4+IDI7CiAgICBjb25zdCB0YWlsTGVuZ3RoID0gbGVuZ3RoIC0gYmxvY2tDb3VudHMgKiA0OwogICAgY29uc3QgZGF0YVVpbnQzMiA9IG5ldyBVaW50MzJBcnJheShkYXRhLmJ1ZmZlciwgMCwgYmxvY2tDb3VudHMpOwogICAgbGV0IGsxID0gMCwKICAgICAgazIgPSAwOwogICAgbGV0IGgxID0gdGhpcy5oMSwKICAgICAgaDIgPSB0aGlzLmgyOwogICAgY29uc3QgQzEgPSAweGNjOWUyZDUxLAogICAgICBDMiA9IDB4MWI4NzM1OTM7CiAgICBjb25zdCBDMV9MT1cgPSBDMSAmIE1BU0tfTE9XLAogICAgICBDMl9MT1cgPSBDMiAmIE1BU0tfTE9XOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCBibG9ja0NvdW50czsgaSsrKSB7CiAgICAgIGlmIChpICYgMSkgewogICAgICAgIGsxID0gZGF0YVVpbnQzMltpXTsKICAgICAgICBrMSA9IGsxICogQzEgJiBNQVNLX0hJR0ggfCBrMSAqIEMxX0xPVyAmIE1BU0tfTE9XOwogICAgICAgIGsxID0gazEgPDwgMTUgfCBrMSA+Pj4gMTc7CiAgICAgICAgazEgPSBrMSAqIEMyICYgTUFTS19ISUdIIHwgazEgKiBDMl9MT1cgJiBNQVNLX0xPVzsKICAgICAgICBoMSBePSBrMTsKICAgICAgICBoMSA9IGgxIDw8IDEzIHwgaDEgPj4+IDE5OwogICAgICAgIGgxID0gaDEgKiA1ICsgMHhlNjU0NmI2NDsKICAgICAgfSBlbHNlIHsKICAgICAgICBrMiA9IGRhdGFVaW50MzJbaV07CiAgICAgICAgazIgPSBrMiAqIEMxICYgTUFTS19ISUdIIHwgazIgKiBDMV9MT1cgJiBNQVNLX0xPVzsKICAgICAgICBrMiA9IGsyIDw8IDE1IHwgazIgPj4+IDE3OwogICAgICAgIGsyID0gazIgKiBDMiAmIE1BU0tfSElHSCB8IGsyICogQzJfTE9XICYgTUFTS19MT1c7CiAgICAgICAgaDIgXj0gazI7CiAgICAgICAgaDIgPSBoMiA8PCAxMyB8IGgyID4+PiAxOTsKICAgICAgICBoMiA9IGgyICogNSArIDB4ZTY1NDZiNjQ7CiAgICAgIH0KICAgIH0KICAgIGsxID0gMDsKICAgIHN3aXRjaCAodGFpbExlbmd0aCkgewogICAgICBjYXNlIDM6CiAgICAgICAgazEgXj0gZGF0YVtibG9ja0NvdW50cyAqIDQgKyAyXSA8PCAxNjsKICAgICAgY2FzZSAyOgogICAgICAgIGsxIF49IGRhdGFbYmxvY2tDb3VudHMgKiA0ICsgMV0gPDwgODsKICAgICAgY2FzZSAxOgogICAgICAgIGsxIF49IGRhdGFbYmxvY2tDb3VudHMgKiA0XTsKICAgICAgICBrMSA9IGsxICogQzEgJiBNQVNLX0hJR0ggfCBrMSAqIEMxX0xPVyAmIE1BU0tfTE9XOwogICAgICAgIGsxID0gazEgPDwgMTUgfCBrMSA+Pj4gMTc7CiAgICAgICAgazEgPSBrMSAqIEMyICYgTUFTS19ISUdIIHwgazEgKiBDMl9MT1cgJiBNQVNLX0xPVzsKICAgICAgICBpZiAoYmxvY2tDb3VudHMgJiAxKSB7CiAgICAgICAgICBoMSBePSBrMTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaDIgXj0gazE7CiAgICAgICAgfQogICAgfQogICAgdGhpcy5oMSA9IGgxOwogICAgdGhpcy5oMiA9IGgyOwogIH0KICBoZXhkaWdlc3QoKSB7CiAgICBsZXQgaDEgPSB0aGlzLmgxLAogICAgICBoMiA9IHRoaXMuaDI7CiAgICBoMSBePSBoMiA+Pj4gMTsKICAgIGgxID0gaDEgKiAweGVkNTU4Y2NkICYgTUFTS19ISUdIIHwgaDEgKiAweDhjY2QgJiBNQVNLX0xPVzsKICAgIGgyID0gaDIgKiAweGZmNTFhZmQ3ICYgTUFTS19ISUdIIHwgKChoMiA8PCAxNiB8IGgxID4+PiAxNikgKiAweGFmZDdlZDU1ICYgTUFTS19ISUdIKSA+Pj4gMTY7CiAgICBoMSBePSBoMiA+Pj4gMTsKICAgIGgxID0gaDEgKiAweDFhODVlYzUzICYgTUFTS19ISUdIIHwgaDEgKiAweGVjNTMgJiBNQVNLX0xPVzsKICAgIGgyID0gaDIgKiAweGM0Y2ViOWZlICYgTUFTS19ISUdIIHwgKChoMiA8PCAxNiB8IGgxID4+PiAxNikgKiAweGI5ZmUxYTg1ICYgTUFTS19ISUdIKSA+Pj4gMTY7CiAgICBoMSBePSBoMiA+Pj4gMTsKICAgIHJldHVybiAoaDEgPj4+IDApLnRvU3RyaW5nKDE2KS5wYWRTdGFydCg4LCAiMCIpICsgKGgyID4+PiAwKS50b1N0cmluZygxNikucGFkU3RhcnQoOCwgIjAiKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2ltYWdlLmpzCgoKCgoKCgoKCgoKCgoKCgoKCmZ1bmN0aW9uIHJlc2l6ZUltYWdlTWFzayhzcmMsIGJwYywgdzEsIGgxLCB3MiwgaDIpIHsKICBjb25zdCBsZW5ndGggPSB3MiAqIGgyOwogIGxldCBkZXN0OwogIGlmIChicGMgPD0gOCkgewogICAgZGVzdCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCk7CiAgfSBlbHNlIGlmIChicGMgPD0gMTYpIHsKICAgIGRlc3QgPSBuZXcgVWludDE2QXJyYXkobGVuZ3RoKTsKICB9IGVsc2UgewogICAgZGVzdCA9IG5ldyBVaW50MzJBcnJheShsZW5ndGgpOwogIH0KICBjb25zdCB4UmF0aW8gPSB3MSAvIHcyOwogIGNvbnN0IHlSYXRpbyA9IGgxIC8gaDI7CiAgbGV0IGksCiAgICBqLAogICAgcHksCiAgICBuZXdJbmRleCA9IDAsCiAgICBvbGRJbmRleDsKICBjb25zdCB4U2NhbGVkID0gbmV3IFVpbnQxNkFycmF5KHcyKTsKICBjb25zdCB3MVNjYW5saW5lID0gdzE7CiAgZm9yIChpID0gMDsgaSA8IHcyOyBpKyspIHsKICAgIHhTY2FsZWRbaV0gPSBNYXRoLmZsb29yKGkgKiB4UmF0aW8pOwogIH0KICBmb3IgKGkgPSAwOyBpIDwgaDI7IGkrKykgewogICAgcHkgPSBNYXRoLmZsb29yKGkgKiB5UmF0aW8pICogdzFTY2FubGluZTsKICAgIGZvciAoaiA9IDA7IGogPCB3MjsgaisrKSB7CiAgICAgIG9sZEluZGV4ID0gcHkgKyB4U2NhbGVkW2pdOwogICAgICBkZXN0W25ld0luZGV4KytdID0gc3JjW29sZEluZGV4XTsKICAgIH0KICB9CiAgcmV0dXJuIGRlc3Q7Cn0KY2xhc3MgUERGSW1hZ2UgewogIGNvbnN0cnVjdG9yKHsKICAgIHhyZWYsCiAgICByZXMsCiAgICBpbWFnZSwKICAgIGlzSW5saW5lID0gZmFsc2UsCiAgICBzbWFzayA9IG51bGwsCiAgICBtYXNrID0gbnVsbCwKICAgIGlzTWFzayA9IGZhbHNlLAogICAgcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUKICB9KSB7CiAgICB0aGlzLmltYWdlID0gaW1hZ2U7CiAgICBjb25zdCBkaWN0ID0gaW1hZ2UuZGljdDsKICAgIGNvbnN0IGZpbHRlciA9IGRpY3QuZ2V0KCJGIiwgIkZpbHRlciIpOwogICAgbGV0IGZpbHRlck5hbWU7CiAgICBpZiAoZmlsdGVyIGluc3RhbmNlb2YgTmFtZSkgewogICAgICBmaWx0ZXJOYW1lID0gZmlsdGVyLm5hbWU7CiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZmlsdGVyKSkgewogICAgICBjb25zdCBmaWx0ZXJaZXJvID0geHJlZi5mZXRjaElmUmVmKGZpbHRlclswXSk7CiAgICAgIGlmIChmaWx0ZXJaZXJvIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgIGZpbHRlck5hbWUgPSBmaWx0ZXJaZXJvLm5hbWU7CiAgICAgIH0KICAgIH0KICAgIHN3aXRjaCAoZmlsdGVyTmFtZSkgewogICAgICBjYXNlICJKUFhEZWNvZGUiOgogICAgICAgICh7CiAgICAgICAgICB3aWR0aDogaW1hZ2Uud2lkdGgsCiAgICAgICAgICBoZWlnaHQ6IGltYWdlLmhlaWdodCwKICAgICAgICAgIGNvbXBvbmVudHNDb3VudDogaW1hZ2UubnVtQ29tcHMsCiAgICAgICAgICBiaXRzUGVyQ29tcG9uZW50OiBpbWFnZS5iaXRzUGVyQ29tcG9uZW50CiAgICAgICAgfSA9IEpweEltYWdlLnBhcnNlSW1hZ2VQcm9wZXJ0aWVzKGltYWdlLnN0cmVhbSkpOwogICAgICAgIGltYWdlLnN0cmVhbS5yZXNldCgpOwogICAgICAgIGNvbnN0IHJlZHVjZVBvd2VyID0gSW1hZ2VSZXNpemVyLmdldFJlZHVjZVBvd2VyRm9ySlBYKGltYWdlLndpZHRoLCBpbWFnZS5oZWlnaHQsIGltYWdlLm51bUNvbXBzKTsKICAgICAgICB0aGlzLmpweERlY29kZXJPcHRpb25zID0gewogICAgICAgICAgbnVtQ29tcG9uZW50czogMCwKICAgICAgICAgIGlzSW5kZXhlZENvbG9ybWFwOiBmYWxzZSwKICAgICAgICAgIHNtYXNrSW5EYXRhOiBkaWN0LmhhcygiU01hc2tJbkRhdGEiKSwKICAgICAgICAgIHJlZHVjZVBvd2VyCiAgICAgICAgfTsKICAgICAgICBpZiAocmVkdWNlUG93ZXIpIHsKICAgICAgICAgIGNvbnN0IGZhY3RvciA9IDIgKiogcmVkdWNlUG93ZXI7CiAgICAgICAgICBpbWFnZS53aWR0aCA9IE1hdGguY2VpbChpbWFnZS53aWR0aCAvIGZhY3Rvcik7CiAgICAgICAgICBpbWFnZS5oZWlnaHQgPSBNYXRoLmNlaWwoaW1hZ2UuaGVpZ2h0IC8gZmFjdG9yKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIkpCSUcyRGVjb2RlIjoKICAgICAgICBpbWFnZS5iaXRzUGVyQ29tcG9uZW50ID0gMTsKICAgICAgICBpbWFnZS5udW1Db21wcyA9IDE7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBsZXQgd2lkdGggPSBkaWN0LmdldCgiVyIsICJXaWR0aCIpOwogICAgbGV0IGhlaWdodCA9IGRpY3QuZ2V0KCJIIiwgIkhlaWdodCIpOwogICAgaWYgKE51bWJlci5pc0ludGVnZXIoaW1hZ2Uud2lkdGgpICYmIGltYWdlLndpZHRoID4gMCAmJiBOdW1iZXIuaXNJbnRlZ2VyKGltYWdlLmhlaWdodCkgJiYgaW1hZ2UuaGVpZ2h0ID4gMCAmJiAoaW1hZ2Uud2lkdGggIT09IHdpZHRoIHx8IGltYWdlLmhlaWdodCAhPT0gaGVpZ2h0KSkgewogICAgICB3YXJuKCJQREZJbWFnZSAtIHVzaW5nIHRoZSBXaWR0aC9IZWlnaHQgb2YgdGhlIGltYWdlIGRhdGEsICIgKyAicmF0aGVyIHRoYW4gdGhlIGltYWdlIGRpY3Rpb25hcnkuIik7CiAgICAgIHdpZHRoID0gaW1hZ2Uud2lkdGg7CiAgICAgIGhlaWdodCA9IGltYWdlLmhlaWdodDsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IHZhbGlkV2lkdGggPSB0eXBlb2Ygd2lkdGggPT09ICJudW1iZXIiICYmIHdpZHRoID4gMCwKICAgICAgICB2YWxpZEhlaWdodCA9IHR5cGVvZiBoZWlnaHQgPT09ICJudW1iZXIiICYmIGhlaWdodCA+IDA7CiAgICAgIGlmICghdmFsaWRXaWR0aCB8fCAhdmFsaWRIZWlnaHQpIHsKICAgICAgICBpZiAoIWltYWdlLmZhbGxiYWNrRGltcykgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIGltYWdlIHdpZHRoOiAke3dpZHRofSBvciBoZWlnaHQ6ICR7aGVpZ2h0fWApOwogICAgICAgIH0KICAgICAgICB3YXJuKCJQREZJbWFnZSAtIHVzaW5nIHRoZSBXaWR0aC9IZWlnaHQgb2YgdGhlIHBhcmVudCBpbWFnZSwgZm9yIFNNYXNrL01hc2sgZGF0YS4iKTsKICAgICAgICBpZiAoIXZhbGlkV2lkdGgpIHsKICAgICAgICAgIHdpZHRoID0gaW1hZ2UuZmFsbGJhY2tEaW1zLndpZHRoOwogICAgICAgIH0KICAgICAgICBpZiAoIXZhbGlkSGVpZ2h0KSB7CiAgICAgICAgICBoZWlnaHQgPSBpbWFnZS5mYWxsYmFja0RpbXMuaGVpZ2h0OwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgdGhpcy53aWR0aCA9IHdpZHRoOwogICAgdGhpcy5oZWlnaHQgPSBoZWlnaHQ7CiAgICB0aGlzLmludGVycG9sYXRlID0gZGljdC5nZXQoIkkiLCAiSW50ZXJwb2xhdGUiKTsKICAgIHRoaXMuaW1hZ2VNYXNrID0gZGljdC5nZXQoIklNIiwgIkltYWdlTWFzayIpIHx8IGZhbHNlOwogICAgdGhpcy5tYXR0ZSA9IGRpY3QuZ2V0KCJNYXR0ZSIpIHx8IGZhbHNlOwogICAgbGV0IGJpdHNQZXJDb21wb25lbnQgPSBpbWFnZS5iaXRzUGVyQ29tcG9uZW50OwogICAgaWYgKCFiaXRzUGVyQ29tcG9uZW50KSB7CiAgICAgIGJpdHNQZXJDb21wb25lbnQgPSBkaWN0LmdldCgiQlBDIiwgIkJpdHNQZXJDb21wb25lbnQiKTsKICAgICAgaWYgKCFiaXRzUGVyQ29tcG9uZW50KSB7CiAgICAgICAgaWYgKHRoaXMuaW1hZ2VNYXNrKSB7CiAgICAgICAgICBiaXRzUGVyQ29tcG9uZW50ID0gMTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBCaXRzIHBlciBjb21wb25lbnQgbWlzc2luZyBpbiBpbWFnZTogJHt0aGlzLmltYWdlTWFza31gKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHRoaXMuYnBjID0gYml0c1BlckNvbXBvbmVudDsKICAgIGlmICghdGhpcy5pbWFnZU1hc2spIHsKICAgICAgbGV0IGNvbG9yU3BhY2UgPSBkaWN0LmdldFJhdygiQ1MiKSB8fCBkaWN0LmdldFJhdygiQ29sb3JTcGFjZSIpOwogICAgICBjb25zdCBoYXNDb2xvclNwYWNlID0gISFjb2xvclNwYWNlOwogICAgICBpZiAoIWhhc0NvbG9yU3BhY2UpIHsKICAgICAgICBpZiAodGhpcy5qcHhEZWNvZGVyT3B0aW9ucykgewogICAgICAgICAgY29sb3JTcGFjZSA9IE5hbWUuZ2V0KCJEZXZpY2VSR0JBIik7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN3aXRjaCAoaW1hZ2UubnVtQ29tcHMpIHsKICAgICAgICAgICAgY2FzZSAxOgogICAgICAgICAgICAgIGNvbG9yU3BhY2UgPSBOYW1lLmdldCgiRGV2aWNlR3JheSIpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDM6CiAgICAgICAgICAgICAgY29sb3JTcGFjZSA9IE5hbWUuZ2V0KCJEZXZpY2VSR0IiKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSA0OgogICAgICAgICAgICAgIGNvbG9yU3BhY2UgPSBOYW1lLmdldCgiRGV2aWNlQ01ZSyIpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW1hZ2VzIHdpdGggJHtpbWFnZS5udW1Db21wc30gY29sb3IgY29tcG9uZW50cyBub3Qgc3VwcG9ydGVkLmApOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSBlbHNlIGlmICh0aGlzLmpweERlY29kZXJPcHRpb25zPy5zbWFza0luRGF0YSkgewogICAgICAgIGNvbG9yU3BhY2UgPSBOYW1lLmdldCgiRGV2aWNlUkdCQSIpOwogICAgICB9CiAgICAgIHRoaXMuY29sb3JTcGFjZSA9IENvbG9yU3BhY2VVdGlscy5wYXJzZSh7CiAgICAgICAgY3M6IGNvbG9yU3BhY2UsCiAgICAgICAgeHJlZiwKICAgICAgICByZXNvdXJjZXM6IGlzSW5saW5lID8gcmVzIDogbnVsbCwKICAgICAgICBwZGZGdW5jdGlvbkZhY3RvcnksCiAgICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgICAgIH0pOwogICAgICB0aGlzLm51bUNvbXBzID0gdGhpcy5jb2xvclNwYWNlLm51bUNvbXBzOwogICAgICBpZiAodGhpcy5qcHhEZWNvZGVyT3B0aW9ucykgewogICAgICAgIHRoaXMuanB4RGVjb2Rlck9wdGlvbnMubnVtQ29tcG9uZW50cyA9IGhhc0NvbG9yU3BhY2UgPyB0aGlzLm51bUNvbXBzIDogMDsKICAgICAgICB0aGlzLmpweERlY29kZXJPcHRpb25zLmlzSW5kZXhlZENvbG9ybWFwID0gdGhpcy5jb2xvclNwYWNlLm5hbWUgPT09ICJJbmRleGVkIjsKICAgICAgfQogICAgfQogICAgdGhpcy5kZWNvZGUgPSBkaWN0LmdldEFycmF5KCJEIiwgIkRlY29kZSIpOwogICAgdGhpcy5uZWVkc0RlY29kZSA9IGZhbHNlOwogICAgaWYgKHRoaXMuZGVjb2RlICYmICh0aGlzLmNvbG9yU3BhY2UgJiYgIXRoaXMuY29sb3JTcGFjZS5pc0RlZmF1bHREZWNvZGUodGhpcy5kZWNvZGUsIGJpdHNQZXJDb21wb25lbnQpIHx8IGlzTWFzayAmJiAhQ29sb3JTcGFjZS5pc0RlZmF1bHREZWNvZGUodGhpcy5kZWNvZGUsIDEpKSkgewogICAgICB0aGlzLm5lZWRzRGVjb2RlID0gdHJ1ZTsKICAgICAgY29uc3QgbWF4ID0gKDEgPDwgYml0c1BlckNvbXBvbmVudCkgLSAxOwogICAgICB0aGlzLmRlY29kZUNvZWZmaWNpZW50cyA9IFtdOwogICAgICB0aGlzLmRlY29kZUFkZGVuZHMgPSBbXTsKICAgICAgY29uc3QgaXNJbmRleGVkID0gdGhpcy5jb2xvclNwYWNlPy5uYW1lID09PSAiSW5kZXhlZCI7CiAgICAgIGZvciAobGV0IGkgPSAwLCBqID0gMDsgaSA8IHRoaXMuZGVjb2RlLmxlbmd0aDsgaSArPSAyLCArK2opIHsKICAgICAgICBjb25zdCBkbWluID0gdGhpcy5kZWNvZGVbaV07CiAgICAgICAgY29uc3QgZG1heCA9IHRoaXMuZGVjb2RlW2kgKyAxXTsKICAgICAgICB0aGlzLmRlY29kZUNvZWZmaWNpZW50c1tqXSA9IGlzSW5kZXhlZCA/IChkbWF4IC0gZG1pbikgLyBtYXggOiBkbWF4IC0gZG1pbjsKICAgICAgICB0aGlzLmRlY29kZUFkZGVuZHNbal0gPSBpc0luZGV4ZWQgPyBkbWluIDogbWF4ICogZG1pbjsKICAgICAgfQogICAgfQogICAgaWYgKHNtYXNrKSB7CiAgICAgIHNtYXNrLmZhbGxiYWNrRGltcyA/Pz0gewogICAgICAgIHdpZHRoLAogICAgICAgIGhlaWdodAogICAgICB9OwogICAgICB0aGlzLnNtYXNrID0gbmV3IFBERkltYWdlKHsKICAgICAgICB4cmVmLAogICAgICAgIHJlcywKICAgICAgICBpbWFnZTogc21hc2ssCiAgICAgICAgaXNJbmxpbmUsCiAgICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgICAgIGdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgICB9KTsKICAgIH0gZWxzZSBpZiAobWFzaykgewogICAgICBpZiAobWFzayBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgICBjb25zdCBtYXNrRGljdCA9IG1hc2suZGljdCwKICAgICAgICAgIGltYWdlTWFzayA9IG1hc2tEaWN0LmdldCgiSU0iLCAiSW1hZ2VNYXNrIik7CiAgICAgICAgaWYgKCFpbWFnZU1hc2spIHsKICAgICAgICAgIHdhcm4oIklnbm9yaW5nIC9NYXNrIGluIGltYWdlIHdpdGhvdXQgL0ltYWdlTWFzay4iKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbWFzay5mYWxsYmFja0RpbXMgPz89IHsKICAgICAgICAgICAgd2lkdGgsCiAgICAgICAgICAgIGhlaWdodAogICAgICAgICAgfTsKICAgICAgICAgIHRoaXMubWFzayA9IG5ldyBQREZJbWFnZSh7CiAgICAgICAgICAgIHhyZWYsCiAgICAgICAgICAgIHJlcywKICAgICAgICAgICAgaW1hZ2U6IG1hc2ssCiAgICAgICAgICAgIGlzSW5saW5lLAogICAgICAgICAgICBpc01hc2s6IHRydWUsCiAgICAgICAgICAgIHBkZkZ1bmN0aW9uRmFjdG9yeSwKICAgICAgICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMubWFzayA9IG1hc2s7CiAgICAgIH0KICAgIH0KICB9CiAgc3RhdGljIGFzeW5jIGJ1aWxkSW1hZ2UoewogICAgeHJlZiwKICAgIHJlcywKICAgIGltYWdlLAogICAgaXNJbmxpbmUgPSBmYWxzZSwKICAgIHBkZkZ1bmN0aW9uRmFjdG9yeSwKICAgIGdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgfSkgewogICAgY29uc3QgaW1hZ2VEYXRhID0gaW1hZ2U7CiAgICBsZXQgc21hc2tEYXRhID0gbnVsbDsKICAgIGxldCBtYXNrRGF0YSA9IG51bGw7CiAgICBjb25zdCBzbWFzayA9IGltYWdlLmRpY3QuZ2V0KCJTTWFzayIpOwogICAgY29uc3QgbWFzayA9IGltYWdlLmRpY3QuZ2V0KCJNYXNrIik7CiAgICBpZiAoc21hc2spIHsKICAgICAgaWYgKHNtYXNrIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICAgIHNtYXNrRGF0YSA9IHNtYXNrOwogICAgICB9IGVsc2UgewogICAgICAgIHdhcm4oIlVuc3VwcG9ydGVkIC9TTWFzayBmb3JtYXQuIik7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAobWFzaykgewogICAgICBpZiAobWFzayBpbnN0YW5jZW9mIEJhc2VTdHJlYW0gfHwgQXJyYXkuaXNBcnJheShtYXNrKSkgewogICAgICAgIG1hc2tEYXRhID0gbWFzazsKICAgICAgfSBlbHNlIHsKICAgICAgICB3YXJuKCJVbnN1cHBvcnRlZCAvTWFzayBmb3JtYXQuIik7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBuZXcgUERGSW1hZ2UoewogICAgICB4cmVmLAogICAgICByZXMsCiAgICAgIGltYWdlOiBpbWFnZURhdGEsCiAgICAgIGlzSW5saW5lLAogICAgICBzbWFzazogc21hc2tEYXRhLAogICAgICBtYXNrOiBtYXNrRGF0YSwKICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGUsCiAgICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgICB9KTsKICB9CiAgc3RhdGljIGFzeW5jIGNyZWF0ZU1hc2soewogICAgaW1hZ2UsCiAgICBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCA9IGZhbHNlCiAgfSkgewogICAgY29uc3QgewogICAgICBkaWN0CiAgICB9ID0gaW1hZ2U7CiAgICBjb25zdCB3aWR0aCA9IGRpY3QuZ2V0KCJXIiwgIldpZHRoIik7CiAgICBjb25zdCBoZWlnaHQgPSBkaWN0LmdldCgiSCIsICJIZWlnaHQiKTsKICAgIGNvbnN0IGludGVycG9sYXRlID0gZGljdC5nZXQoIkkiLCAiSW50ZXJwb2xhdGUiKTsKICAgIGNvbnN0IGRlY29kZSA9IGRpY3QuZ2V0QXJyYXkoIkQiLCAiRGVjb2RlIik7CiAgICBjb25zdCBpbnZlcnNlRGVjb2RlID0gZGVjb2RlPy5bMF0gPiAwOwogICAgY29uc3QgY29tcHV0ZWRMZW5ndGggPSAod2lkdGggKyA3ID4+IDMpICogaGVpZ2h0OwogICAgY29uc3QgaW1nQXJyYXkgPSBpbWFnZS5nZXRCeXRlcyhjb21wdXRlZExlbmd0aCk7CiAgICBjb25zdCBpc1NpbmdsZU9wYXF1ZVBpeGVsID0gd2lkdGggPT09IDEgJiYgaGVpZ2h0ID09PSAxICYmIGludmVyc2VEZWNvZGUgPT09IChpbWdBcnJheS5sZW5ndGggPT09IDAgfHwgISEoaW1nQXJyYXlbMF0gJiAxMjgpKTsKICAgIGlmIChpc1NpbmdsZU9wYXF1ZVBpeGVsKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgaXNTaW5nbGVPcGFxdWVQaXhlbAogICAgICB9OwogICAgfQogICAgaWYgKGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKSB7CiAgICAgIGlmIChJbWFnZVJlc2l6ZXIubmVlZHNUb0JlUmVzaXplZCh3aWR0aCwgaGVpZ2h0KSkgewogICAgICAgIGNvbnN0IGRhdGEgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkod2lkdGggKiBoZWlnaHQgKiA0KTsKICAgICAgICBjb252ZXJ0QmxhY2tBbmRXaGl0ZVRvUkdCQSh7CiAgICAgICAgICBzcmM6IGltZ0FycmF5LAogICAgICAgICAgZGVzdDogZGF0YSwKICAgICAgICAgIHdpZHRoLAogICAgICAgICAgaGVpZ2h0LAogICAgICAgICAgbm9uQmxhY2tDb2xvcjogMCwKICAgICAgICAgIGludmVyc2VEZWNvZGUKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gSW1hZ2VSZXNpemVyLmNyZWF0ZUltYWdlKHsKICAgICAgICAgIGtpbmQ6IEltYWdlS2luZC5SR0JBXzMyQlBQLAogICAgICAgICAgZGF0YSwKICAgICAgICAgIHdpZHRoLAogICAgICAgICAgaGVpZ2h0LAogICAgICAgICAgaW50ZXJwb2xhdGUKICAgICAgICB9KTsKICAgICAgfQogICAgICBjb25zdCBjYW52YXMgPSBuZXcgT2Zmc2NyZWVuQ2FudmFzKHdpZHRoLCBoZWlnaHQpOwogICAgICBjb25zdCBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgiMmQiKTsKICAgICAgY29uc3QgaW1nRGF0YSA9IGN0eC5jcmVhdGVJbWFnZURhdGEod2lkdGgsIGhlaWdodCk7CiAgICAgIGNvbnZlcnRCbGFja0FuZFdoaXRlVG9SR0JBKHsKICAgICAgICBzcmM6IGltZ0FycmF5LAogICAgICAgIGRlc3Q6IGltZ0RhdGEuZGF0YSwKICAgICAgICB3aWR0aCwKICAgICAgICBoZWlnaHQsCiAgICAgICAgbm9uQmxhY2tDb2xvcjogMCwKICAgICAgICBpbnZlcnNlRGVjb2RlCiAgICAgIH0pOwogICAgICBjdHgucHV0SW1hZ2VEYXRhKGltZ0RhdGEsIDAsIDApOwogICAgICBjb25zdCBiaXRtYXAgPSBjYW52YXMudHJhbnNmZXJUb0ltYWdlQml0bWFwKCk7CiAgICAgIHJldHVybiB7CiAgICAgICAgZGF0YTogbnVsbCwKICAgICAgICB3aWR0aCwKICAgICAgICBoZWlnaHQsCiAgICAgICAgaW50ZXJwb2xhdGUsCiAgICAgICAgYml0bWFwCiAgICAgIH07CiAgICB9CiAgICBjb25zdCBhY3R1YWxMZW5ndGggPSBpbWdBcnJheS5ieXRlTGVuZ3RoOwogICAgY29uc3QgaGF2ZUZ1bGxEYXRhID0gY29tcHV0ZWRMZW5ndGggPT09IGFjdHVhbExlbmd0aDsKICAgIGxldCBkYXRhOwogICAgaWYgKGltYWdlIGluc3RhbmNlb2YgRGVjb2RlU3RyZWFtICYmICghaW52ZXJzZURlY29kZSB8fCBoYXZlRnVsbERhdGEpKSB7CiAgICAgIGRhdGEgPSBpbWdBcnJheTsKICAgIH0gZWxzZSBpZiAoIWludmVyc2VEZWNvZGUpIHsKICAgICAgZGF0YSA9IG5ldyBVaW50OEFycmF5KGltZ0FycmF5KTsKICAgIH0gZWxzZSB7CiAgICAgIGRhdGEgPSBuZXcgVWludDhBcnJheShjb21wdXRlZExlbmd0aCk7CiAgICAgIGRhdGEuc2V0KGltZ0FycmF5KTsKICAgICAgZGF0YS5maWxsKDB4ZmYsIGFjdHVhbExlbmd0aCk7CiAgICB9CiAgICBpZiAoaW52ZXJzZURlY29kZSkgewogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGFjdHVhbExlbmd0aDsgaSsrKSB7CiAgICAgICAgZGF0YVtpXSBePSAweGZmOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gewogICAgICBkYXRhLAogICAgICB3aWR0aCwKICAgICAgaGVpZ2h0LAogICAgICBpbnRlcnBvbGF0ZQogICAgfTsKICB9CiAgZ2V0IGRyYXdXaWR0aCgpIHsKICAgIHJldHVybiBNYXRoLm1heCh0aGlzLndpZHRoLCB0aGlzLnNtYXNrPy53aWR0aCB8fCAwLCB0aGlzLm1hc2s/LndpZHRoIHx8IDApOwogIH0KICBnZXQgZHJhd0hlaWdodCgpIHsKICAgIHJldHVybiBNYXRoLm1heCh0aGlzLmhlaWdodCwgdGhpcy5zbWFzaz8uaGVpZ2h0IHx8IDAsIHRoaXMubWFzaz8uaGVpZ2h0IHx8IDApOwogIH0KICBkZWNvZGVCdWZmZXIoYnVmZmVyKSB7CiAgICBjb25zdCBicGMgPSB0aGlzLmJwYzsKICAgIGNvbnN0IG51bUNvbXBzID0gdGhpcy5udW1Db21wczsKICAgIGNvbnN0IGRlY29kZUFkZGVuZHMgPSB0aGlzLmRlY29kZUFkZGVuZHM7CiAgICBjb25zdCBkZWNvZGVDb2VmZmljaWVudHMgPSB0aGlzLmRlY29kZUNvZWZmaWNpZW50czsKICAgIGNvbnN0IG1heCA9ICgxIDw8IGJwYykgLSAxOwogICAgbGV0IGksIGlpOwogICAgaWYgKGJwYyA9PT0gMSkgewogICAgICBmb3IgKGkgPSAwLCBpaSA9IGJ1ZmZlci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgYnVmZmVyW2ldID0gKyFidWZmZXJbaV07CiAgICAgIH0KICAgICAgcmV0dXJuOwogICAgfQogICAgbGV0IGluZGV4ID0gMDsKICAgIGZvciAoaSA9IDAsIGlpID0gdGhpcy53aWR0aCAqIHRoaXMuaGVpZ2h0OyBpIDwgaWk7IGkrKykgewogICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG51bUNvbXBzOyBqKyspIHsKICAgICAgICBidWZmZXJbaW5kZXhdID0gTWF0aENsYW1wKGRlY29kZUFkZGVuZHNbal0gKyBidWZmZXJbaW5kZXhdICogZGVjb2RlQ29lZmZpY2llbnRzW2pdLCAwLCBtYXgpOwogICAgICAgIGluZGV4Kys7CiAgICAgIH0KICAgIH0KICB9CiAgZ2V0Q29tcG9uZW50cyhidWZmZXIpIHsKICAgIGNvbnN0IGJwYyA9IHRoaXMuYnBjOwogICAgaWYgKGJwYyA9PT0gOCkgewogICAgICByZXR1cm4gYnVmZmVyOwogICAgfQogICAgY29uc3Qgd2lkdGggPSB0aGlzLndpZHRoOwogICAgY29uc3QgaGVpZ2h0ID0gdGhpcy5oZWlnaHQ7CiAgICBjb25zdCBudW1Db21wcyA9IHRoaXMubnVtQ29tcHM7CiAgICBjb25zdCBsZW5ndGggPSB3aWR0aCAqIGhlaWdodCAqIG51bUNvbXBzOwogICAgbGV0IGJ1ZmZlclBvcyA9IDA7CiAgICBsZXQgb3V0cHV0OwogICAgaWYgKGJwYyA8PSA4KSB7CiAgICAgIG91dHB1dCA9IG5ldyBVaW50OEFycmF5KGxlbmd0aCk7CiAgICB9IGVsc2UgaWYgKGJwYyA8PSAxNikgewogICAgICBvdXRwdXQgPSBuZXcgVWludDE2QXJyYXkobGVuZ3RoKTsKICAgIH0gZWxzZSB7CiAgICAgIG91dHB1dCA9IG5ldyBVaW50MzJBcnJheShsZW5ndGgpOwogICAgfQogICAgY29uc3Qgcm93Q29tcHMgPSB3aWR0aCAqIG51bUNvbXBzOwogICAgY29uc3QgbWF4ID0gKDEgPDwgYnBjKSAtIDE7CiAgICBsZXQgaSA9IDAsCiAgICAgIGlpLAogICAgICBidWY7CiAgICBpZiAoYnBjID09PSAxKSB7CiAgICAgIGxldCBtYXNrLCBsb29wMUVuZCwgbG9vcDJFbmQ7CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgaGVpZ2h0OyBqKyspIHsKICAgICAgICBsb29wMUVuZCA9IGkgKyAocm93Q29tcHMgJiB+Nyk7CiAgICAgICAgbG9vcDJFbmQgPSBpICsgcm93Q29tcHM7CiAgICAgICAgd2hpbGUgKGkgPCBsb29wMUVuZCkgewogICAgICAgICAgYnVmID0gYnVmZmVyW2J1ZmZlclBvcysrXTsKICAgICAgICAgIG91dHB1dFtpXSA9IGJ1ZiA+PiA3ICYgMTsKICAgICAgICAgIG91dHB1dFtpICsgMV0gPSBidWYgPj4gNiAmIDE7CiAgICAgICAgICBvdXRwdXRbaSArIDJdID0gYnVmID4+IDUgJiAxOwogICAgICAgICAgb3V0cHV0W2kgKyAzXSA9IGJ1ZiA+PiA0ICYgMTsKICAgICAgICAgIG91dHB1dFtpICsgNF0gPSBidWYgPj4gMyAmIDE7CiAgICAgICAgICBvdXRwdXRbaSArIDVdID0gYnVmID4+IDIgJiAxOwogICAgICAgICAgb3V0cHV0W2kgKyA2XSA9IGJ1ZiA+PiAxICYgMTsKICAgICAgICAgIG91dHB1dFtpICsgN10gPSBidWYgJiAxOwogICAgICAgICAgaSArPSA4OwogICAgICAgIH0KICAgICAgICBpZiAoaSA8IGxvb3AyRW5kKSB7CiAgICAgICAgICBidWYgPSBidWZmZXJbYnVmZmVyUG9zKytdOwogICAgICAgICAgbWFzayA9IDEyODsKICAgICAgICAgIHdoaWxlIChpIDwgbG9vcDJFbmQpIHsKICAgICAgICAgICAgb3V0cHV0W2krK10gPSArISEoYnVmICYgbWFzayk7CiAgICAgICAgICAgIG1hc2sgPj49IDE7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICBsZXQgYml0cyA9IDA7CiAgICAgIGJ1ZiA9IDA7CiAgICAgIGZvciAoaSA9IDAsIGlpID0gbGVuZ3RoOyBpIDwgaWk7ICsraSkgewogICAgICAgIGlmIChpICUgcm93Q29tcHMgPT09IDApIHsKICAgICAgICAgIGJ1ZiA9IDA7CiAgICAgICAgICBiaXRzID0gMDsKICAgICAgICB9CiAgICAgICAgd2hpbGUgKGJpdHMgPCBicGMpIHsKICAgICAgICAgIGJ1ZiA9IGJ1ZiA8PCA4IHwgYnVmZmVyW2J1ZmZlclBvcysrXTsKICAgICAgICAgIGJpdHMgKz0gODsKICAgICAgICB9CiAgICAgICAgY29uc3QgcmVtYWluaW5nQml0cyA9IGJpdHMgLSBicGM7CiAgICAgICAgbGV0IHZhbHVlID0gYnVmID4+IHJlbWFpbmluZ0JpdHM7CiAgICAgICAgaWYgKHZhbHVlIDwgMCkgewogICAgICAgICAgdmFsdWUgPSAwOwogICAgICAgIH0gZWxzZSBpZiAodmFsdWUgPiBtYXgpIHsKICAgICAgICAgIHZhbHVlID0gbWF4OwogICAgICAgIH0KICAgICAgICBvdXRwdXRbaV0gPSB2YWx1ZTsKICAgICAgICBidWYgJj0gKDEgPDwgcmVtYWluaW5nQml0cykgLSAxOwogICAgICAgIGJpdHMgPSByZW1haW5pbmdCaXRzOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gb3V0cHV0OwogIH0KICBhc3luYyBmaWxsT3BhY2l0eShyZ2JhQnVmLCB3aWR0aCwgaGVpZ2h0LCBhY3R1YWxIZWlnaHQsIGltYWdlKSB7CiAgICBjb25zdCBzbWFzayA9IHRoaXMuc21hc2s7CiAgICBjb25zdCBtYXNrID0gdGhpcy5tYXNrOwogICAgbGV0IGFscGhhQnVmLCBzdywgc2gsIGksIGlpLCBqOwogICAgaWYgKHNtYXNrKSB7CiAgICAgIHN3ID0gc21hc2sud2lkdGg7CiAgICAgIHNoID0gc21hc2suaGVpZ2h0OwogICAgICBhbHBoYUJ1ZiA9IG5ldyBVaW50OENsYW1wZWRBcnJheShzdyAqIHNoKTsKICAgICAgYXdhaXQgc21hc2suZmlsbEdyYXlCdWZmZXIoYWxwaGFCdWYpOwogICAgICBpZiAoc3cgIT09IHdpZHRoIHx8IHNoICE9PSBoZWlnaHQpIHsKICAgICAgICBhbHBoYUJ1ZiA9IHJlc2l6ZUltYWdlTWFzayhhbHBoYUJ1Ziwgc21hc2suYnBjLCBzdywgc2gsIHdpZHRoLCBoZWlnaHQpOwogICAgICB9CiAgICB9IGVsc2UgaWYgKG1hc2spIHsKICAgICAgaWYgKG1hc2sgaW5zdGFuY2VvZiBQREZJbWFnZSkgewogICAgICAgIHN3ID0gbWFzay53aWR0aDsKICAgICAgICBzaCA9IG1hc2suaGVpZ2h0OwogICAgICAgIGFscGhhQnVmID0gbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KHN3ICogc2gpOwogICAgICAgIG1hc2subnVtQ29tcHMgPSAxOwogICAgICAgIGF3YWl0IG1hc2suZmlsbEdyYXlCdWZmZXIoYWxwaGFCdWYpOwogICAgICAgIGZvciAoaSA9IDAsIGlpID0gc3cgKiBzaDsgaSA8IGlpOyArK2kpIHsKICAgICAgICAgIGFscGhhQnVmW2ldID0gMjU1IC0gYWxwaGFCdWZbaV07CiAgICAgICAgfQogICAgICAgIGlmIChzdyAhPT0gd2lkdGggfHwgc2ggIT09IGhlaWdodCkgewogICAgICAgICAgYWxwaGFCdWYgPSByZXNpemVJbWFnZU1hc2soYWxwaGFCdWYsIG1hc2suYnBjLCBzdywgc2gsIHdpZHRoLCBoZWlnaHQpOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KG1hc2spKSB7CiAgICAgICAgYWxwaGFCdWYgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkod2lkdGggKiBoZWlnaHQpOwogICAgICAgIGNvbnN0IG51bUNvbXBzID0gdGhpcy5udW1Db21wczsKICAgICAgICBmb3IgKGkgPSAwLCBpaSA9IHdpZHRoICogaGVpZ2h0OyBpIDwgaWk7ICsraSkgewogICAgICAgICAgbGV0IG9wYWNpdHkgPSAwOwogICAgICAgICAgY29uc3QgaW1hZ2VPZmZzZXQgPSBpICogbnVtQ29tcHM7CiAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgbnVtQ29tcHM7ICsraikgewogICAgICAgICAgICBjb25zdCBjb2xvciA9IGltYWdlW2ltYWdlT2Zmc2V0ICsgal07CiAgICAgICAgICAgIGNvbnN0IG1hc2tPZmZzZXQgPSBqICogMjsKICAgICAgICAgICAgaWYgKGNvbG9yIDwgbWFza1ttYXNrT2Zmc2V0XSB8fCBjb2xvciA+IG1hc2tbbWFza09mZnNldCArIDFdKSB7CiAgICAgICAgICAgICAgb3BhY2l0eSA9IDI1NTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgYWxwaGFCdWZbaV0gPSBvcGFjaXR5OwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVua25vd24gbWFzayBmb3JtYXQuIik7CiAgICAgIH0KICAgIH0KICAgIGlmIChhbHBoYUJ1ZikgewogICAgICBmb3IgKGkgPSAwLCBqID0gMywgaWkgPSB3aWR0aCAqIGFjdHVhbEhlaWdodDsgaSA8IGlpOyArK2ksIGogKz0gNCkgewogICAgICAgIHJnYmFCdWZbal0gPSBhbHBoYUJ1ZltpXTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgZm9yIChpID0gMCwgaiA9IDMsIGlpID0gd2lkdGggKiBhY3R1YWxIZWlnaHQ7IGkgPCBpaTsgKytpLCBqICs9IDQpIHsKICAgICAgICByZ2JhQnVmW2pdID0gMjU1OwogICAgICB9CiAgICB9CiAgfQogIHVuZG9QcmVibGVuZChidWZmZXIsIHdpZHRoLCBoZWlnaHQpIHsKICAgIGNvbnN0IG1hdHRlID0gdGhpcy5zbWFzaz8ubWF0dGU7CiAgICBpZiAoIW1hdHRlKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IG1hdHRlUmdiID0gdGhpcy5jb2xvclNwYWNlLmdldFJnYihtYXR0ZSwgMCk7CiAgICBjb25zdCBtYXR0ZVIgPSBtYXR0ZVJnYlswXTsKICAgIGNvbnN0IG1hdHRlRyA9IG1hdHRlUmdiWzFdOwogICAgY29uc3QgbWF0dGVCID0gbWF0dGVSZ2JbMl07CiAgICBjb25zdCBsZW5ndGggPSB3aWR0aCAqIGhlaWdodCAqIDQ7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSA0KSB7CiAgICAgIGNvbnN0IGFscGhhID0gYnVmZmVyW2kgKyAzXTsKICAgICAgaWYgKGFscGhhID09PSAwKSB7CiAgICAgICAgYnVmZmVyW2ldID0gMjU1OwogICAgICAgIGJ1ZmZlcltpICsgMV0gPSAyNTU7CiAgICAgICAgYnVmZmVyW2kgKyAyXSA9IDI1NTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBrID0gMjU1IC8gYWxwaGE7CiAgICAgIGJ1ZmZlcltpXSA9IChidWZmZXJbaV0gLSBtYXR0ZVIpICogayArIG1hdHRlUjsKICAgICAgYnVmZmVyW2kgKyAxXSA9IChidWZmZXJbaSArIDFdIC0gbWF0dGVHKSAqIGsgKyBtYXR0ZUc7CiAgICAgIGJ1ZmZlcltpICsgMl0gPSAoYnVmZmVyW2kgKyAyXSAtIG1hdHRlQikgKiBrICsgbWF0dGVCOwogICAgfQogIH0KICBhc3luYyBjcmVhdGVJbWFnZURhdGEoZm9yY2VSR0JBID0gZmFsc2UsIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkID0gZmFsc2UpIHsKICAgIGNvbnN0IGRyYXdXaWR0aCA9IHRoaXMuZHJhd1dpZHRoOwogICAgY29uc3QgZHJhd0hlaWdodCA9IHRoaXMuZHJhd0hlaWdodDsKICAgIGNvbnN0IGltZ0RhdGEgPSB7CiAgICAgIHdpZHRoOiBkcmF3V2lkdGgsCiAgICAgIGhlaWdodDogZHJhd0hlaWdodCwKICAgICAgaW50ZXJwb2xhdGU6IHRoaXMuaW50ZXJwb2xhdGUsCiAgICAgIGtpbmQ6IDAsCiAgICAgIGRhdGE6IG51bGwKICAgIH07CiAgICBjb25zdCBudW1Db21wcyA9IHRoaXMubnVtQ29tcHM7CiAgICBjb25zdCBvcmlnaW5hbFdpZHRoID0gdGhpcy53aWR0aDsKICAgIGNvbnN0IG9yaWdpbmFsSGVpZ2h0ID0gdGhpcy5oZWlnaHQ7CiAgICBjb25zdCBicGMgPSB0aGlzLmJwYzsKICAgIGNvbnN0IHJvd0J5dGVzID0gb3JpZ2luYWxXaWR0aCAqIG51bUNvbXBzICogYnBjICsgNyA+PiAzOwogICAgY29uc3QgbXVzdEJlUmVzaXplZCA9IGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkICYmIEltYWdlUmVzaXplci5uZWVkc1RvQmVSZXNpemVkKGRyYXdXaWR0aCwgZHJhd0hlaWdodCk7CiAgICBpZiAoIXRoaXMuc21hc2sgJiYgIXRoaXMubWFzayAmJiB0aGlzLmNvbG9yU3BhY2UubmFtZSA9PT0gIkRldmljZVJHQkEiKSB7CiAgICAgIGltZ0RhdGEua2luZCA9IEltYWdlS2luZC5SR0JBXzMyQlBQOwogICAgICBjb25zdCBpbWdBcnJheSA9IGltZ0RhdGEuZGF0YSA9IGF3YWl0IHRoaXMuZ2V0SW1hZ2VCeXRlcyhvcmlnaW5hbEhlaWdodCAqIG9yaWdpbmFsV2lkdGggKiA0LCB7fSk7CiAgICAgIGlmIChpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCkgewogICAgICAgIGlmICghbXVzdEJlUmVzaXplZCkgewogICAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlQml0bWFwKEltYWdlS2luZC5SR0JBXzMyQlBQLCBkcmF3V2lkdGgsIGRyYXdIZWlnaHQsIGltZ0FycmF5KTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIEltYWdlUmVzaXplci5jcmVhdGVJbWFnZShpbWdEYXRhLCBmYWxzZSk7CiAgICAgIH0KICAgICAgcmV0dXJuIGltZ0RhdGE7CiAgICB9CiAgICBpZiAoIWZvcmNlUkdCQSkgewogICAgICBsZXQga2luZDsKICAgICAgaWYgKHRoaXMuY29sb3JTcGFjZS5uYW1lID09PSAiRGV2aWNlR3JheSIgJiYgYnBjID09PSAxKSB7CiAgICAgICAga2luZCA9IEltYWdlS2luZC5HUkFZU0NBTEVfMUJQUDsKICAgICAgfSBlbHNlIGlmICh0aGlzLmNvbG9yU3BhY2UubmFtZSA9PT0gIkRldmljZVJHQiIgJiYgYnBjID09PSA4ICYmICF0aGlzLm5lZWRzRGVjb2RlKSB7CiAgICAgICAga2luZCA9IEltYWdlS2luZC5SR0JfMjRCUFA7CiAgICAgIH0KICAgICAgaWYgKGtpbmQgJiYgIXRoaXMuc21hc2sgJiYgIXRoaXMubWFzayAmJiBkcmF3V2lkdGggPT09IG9yaWdpbmFsV2lkdGggJiYgZHJhd0hlaWdodCA9PT0gb3JpZ2luYWxIZWlnaHQpIHsKICAgICAgICBjb25zdCBpbWFnZSA9IGF3YWl0IHRoaXMuI2dldEltYWdlKG9yaWdpbmFsV2lkdGgsIG9yaWdpbmFsSGVpZ2h0KTsKICAgICAgICBpZiAoaW1hZ2UpIHsKICAgICAgICAgIHJldHVybiBpbWFnZTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZGF0YSA9IGF3YWl0IHRoaXMuZ2V0SW1hZ2VCeXRlcyhvcmlnaW5hbEhlaWdodCAqIHJvd0J5dGVzLCB7fSk7CiAgICAgICAgaWYgKGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKSB7CiAgICAgICAgICBpZiAobXVzdEJlUmVzaXplZCkgewogICAgICAgICAgICByZXR1cm4gSW1hZ2VSZXNpemVyLmNyZWF0ZUltYWdlKHsKICAgICAgICAgICAgICBkYXRhLAogICAgICAgICAgICAgIGtpbmQsCiAgICAgICAgICAgICAgd2lkdGg6IGRyYXdXaWR0aCwKICAgICAgICAgICAgICBoZWlnaHQ6IGRyYXdIZWlnaHQsCiAgICAgICAgICAgICAgaW50ZXJwb2xhdGU6IHRoaXMuaW50ZXJwb2xhdGUKICAgICAgICAgICAgfSwgdGhpcy5uZWVkc0RlY29kZSk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVCaXRtYXAoa2luZCwgb3JpZ2luYWxXaWR0aCwgb3JpZ2luYWxIZWlnaHQsIGRhdGEpOwogICAgICAgIH0KICAgICAgICBpbWdEYXRhLmtpbmQgPSBraW5kOwogICAgICAgIGltZ0RhdGEuZGF0YSA9IGRhdGE7CiAgICAgICAgaWYgKHRoaXMubmVlZHNEZWNvZGUpIHsKICAgICAgICAgIGFzc2VydChraW5kID09PSBJbWFnZUtpbmQuR1JBWVNDQUxFXzFCUFAsICJQREZJbWFnZS5jcmVhdGVJbWFnZURhdGE6IFRoZSBpbWFnZSBtdXN0IGJlIGdyYXlzY2FsZS4iKTsKICAgICAgICAgIGNvbnN0IGJ1ZmZlciA9IGltZ0RhdGEuZGF0YTsKICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGJ1ZmZlci5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICAgIGJ1ZmZlcltpXSBePSAweGZmOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gaW1nRGF0YTsKICAgICAgfQogICAgICBpZiAodGhpcy5pbWFnZSBpbnN0YW5jZW9mIEpwZWdTdHJlYW0gJiYgIXRoaXMuc21hc2sgJiYgIXRoaXMubWFzayAmJiAhdGhpcy5uZWVkc0RlY29kZSkgewogICAgICAgIGxldCBpbWFnZUxlbmd0aCA9IG9yaWdpbmFsSGVpZ2h0ICogcm93Qnl0ZXM7CiAgICAgICAgaWYgKGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkICYmICFtdXN0QmVSZXNpemVkKSB7CiAgICAgICAgICBsZXQgaXNIYW5kbGVkID0gZmFsc2U7CiAgICAgICAgICBzd2l0Y2ggKHRoaXMuY29sb3JTcGFjZS5uYW1lKSB7CiAgICAgICAgICAgIGNhc2UgIkRldmljZUdyYXkiOgogICAgICAgICAgICAgIGltYWdlTGVuZ3RoICo9IDQ7CiAgICAgICAgICAgICAgaXNIYW5kbGVkID0gdHJ1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiRGV2aWNlUkdCIjoKICAgICAgICAgICAgICBpbWFnZUxlbmd0aCA9IGltYWdlTGVuZ3RoIC8gMyAqIDQ7CiAgICAgICAgICAgICAgaXNIYW5kbGVkID0gdHJ1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAiRGV2aWNlQ01ZSyI6CiAgICAgICAgICAgICAgaXNIYW5kbGVkID0gdHJ1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChpc0hhbmRsZWQpIHsKICAgICAgICAgICAgY29uc3QgaW1hZ2UgPSBhd2FpdCB0aGlzLiNnZXRJbWFnZShkcmF3V2lkdGgsIGRyYXdIZWlnaHQpOwogICAgICAgICAgICBpZiAoaW1hZ2UpIHsKICAgICAgICAgICAgICByZXR1cm4gaW1hZ2U7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgcmdiYSA9IGF3YWl0IHRoaXMuZ2V0SW1hZ2VCeXRlcyhpbWFnZUxlbmd0aCwgewogICAgICAgICAgICAgIGRyYXdXaWR0aCwKICAgICAgICAgICAgICBkcmF3SGVpZ2h0LAogICAgICAgICAgICAgIGZvcmNlUkdCQTogdHJ1ZQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlQml0bWFwKEltYWdlS2luZC5SR0JBXzMyQlBQLCBkcmF3V2lkdGgsIGRyYXdIZWlnaHQsIHJnYmEpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzd2l0Y2ggKHRoaXMuY29sb3JTcGFjZS5uYW1lKSB7CiAgICAgICAgICAgIGNhc2UgIkRldmljZUdyYXkiOgogICAgICAgICAgICAgIGltYWdlTGVuZ3RoICo9IDM7CiAgICAgICAgICAgIGNhc2UgIkRldmljZVJHQiI6CiAgICAgICAgICAgIGNhc2UgIkRldmljZUNNWUsiOgogICAgICAgICAgICAgIGltZ0RhdGEua2luZCA9IEltYWdlS2luZC5SR0JfMjRCUFA7CiAgICAgICAgICAgICAgaW1nRGF0YS5kYXRhID0gYXdhaXQgdGhpcy5nZXRJbWFnZUJ5dGVzKGltYWdlTGVuZ3RoLCB7CiAgICAgICAgICAgICAgICBkcmF3V2lkdGgsCiAgICAgICAgICAgICAgICBkcmF3SGVpZ2h0LAogICAgICAgICAgICAgICAgZm9yY2VSR0I6IHRydWUKICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICBpZiAobXVzdEJlUmVzaXplZCkgewogICAgICAgICAgICAgICAgcmV0dXJuIEltYWdlUmVzaXplci5jcmVhdGVJbWFnZShpbWdEYXRhKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmV0dXJuIGltZ0RhdGE7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBjb25zdCBpbWdBcnJheSA9IGF3YWl0IHRoaXMuZ2V0SW1hZ2VCeXRlcyhvcmlnaW5hbEhlaWdodCAqIHJvd0J5dGVzLCB7CiAgICAgIGludGVybmFsOiB0cnVlCiAgICB9KTsKICAgIGNvbnN0IGFjdHVhbEhlaWdodCA9IDAgfCBpbWdBcnJheS5sZW5ndGggLyByb3dCeXRlcyAqIGRyYXdIZWlnaHQgLyBvcmlnaW5hbEhlaWdodDsKICAgIGNvbnN0IGNvbXBzID0gdGhpcy5nZXRDb21wb25lbnRzKGltZ0FycmF5KTsKICAgIGxldCBhbHBoYTAxLCBtYXliZVVuZG9QcmVibGVuZDsKICAgIGxldCBjYW52YXMsIGN0eCwgY2FudmFzSW1nRGF0YSwgZGF0YTsKICAgIGlmIChpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCAmJiAhbXVzdEJlUmVzaXplZCkgewogICAgICBjYW52YXMgPSBuZXcgT2Zmc2NyZWVuQ2FudmFzKGRyYXdXaWR0aCwgZHJhd0hlaWdodCk7CiAgICAgIGN0eCA9IGNhbnZhcy5nZXRDb250ZXh0KCIyZCIpOwogICAgICBjYW52YXNJbWdEYXRhID0gY3R4LmNyZWF0ZUltYWdlRGF0YShkcmF3V2lkdGgsIGRyYXdIZWlnaHQpOwogICAgICBkYXRhID0gY2FudmFzSW1nRGF0YS5kYXRhOwogICAgfQogICAgaW1nRGF0YS5raW5kID0gSW1hZ2VLaW5kLlJHQkFfMzJCUFA7CiAgICBpZiAoIWZvcmNlUkdCQSAmJiAhdGhpcy5zbWFzayAmJiAhdGhpcy5tYXNrKSB7CiAgICAgIGlmICghaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgfHwgbXVzdEJlUmVzaXplZCkgewogICAgICAgIGltZ0RhdGEua2luZCA9IEltYWdlS2luZC5SR0JfMjRCUFA7CiAgICAgICAgZGF0YSA9IG5ldyBVaW50OENsYW1wZWRBcnJheShkcmF3V2lkdGggKiBkcmF3SGVpZ2h0ICogMyk7CiAgICAgICAgYWxwaGEwMSA9IDA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgYXJyID0gbmV3IFVpbnQzMkFycmF5KGRhdGEuYnVmZmVyKTsKICAgICAgICBhcnIuZmlsbChGZWF0dXJlVGVzdC5pc0xpdHRsZUVuZGlhbiA/IDB4ZmYwMDAwMDAgOiAweDAwMDAwMGZmKTsKICAgICAgICBhbHBoYTAxID0gMTsKICAgICAgfQogICAgICBtYXliZVVuZG9QcmVibGVuZCA9IGZhbHNlOwogICAgfSBlbHNlIHsKICAgICAgaWYgKCFpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCB8fCBtdXN0QmVSZXNpemVkKSB7CiAgICAgICAgZGF0YSA9IG5ldyBVaW50OENsYW1wZWRBcnJheShkcmF3V2lkdGggKiBkcmF3SGVpZ2h0ICogNCk7CiAgICAgIH0KICAgICAgYWxwaGEwMSA9IDE7CiAgICAgIG1heWJlVW5kb1ByZWJsZW5kID0gdHJ1ZTsKICAgICAgYXdhaXQgdGhpcy5maWxsT3BhY2l0eShkYXRhLCBkcmF3V2lkdGgsIGRyYXdIZWlnaHQsIGFjdHVhbEhlaWdodCwgY29tcHMpOwogICAgfQogICAgaWYgKHRoaXMubmVlZHNEZWNvZGUpIHsKICAgICAgdGhpcy5kZWNvZGVCdWZmZXIoY29tcHMpOwogICAgfQogICAgdGhpcy5jb2xvclNwYWNlLmZpbGxSZ2IoZGF0YSwgb3JpZ2luYWxXaWR0aCwgb3JpZ2luYWxIZWlnaHQsIGRyYXdXaWR0aCwgZHJhd0hlaWdodCwgYWN0dWFsSGVpZ2h0LCBicGMsIGNvbXBzLCBhbHBoYTAxKTsKICAgIGlmIChtYXliZVVuZG9QcmVibGVuZCkgewogICAgICB0aGlzLnVuZG9QcmVibGVuZChkYXRhLCBkcmF3V2lkdGgsIGFjdHVhbEhlaWdodCk7CiAgICB9CiAgICBpZiAoaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgJiYgIW11c3RCZVJlc2l6ZWQpIHsKICAgICAgY3R4LnB1dEltYWdlRGF0YShjYW52YXNJbWdEYXRhLCAwLCAwKTsKICAgICAgY29uc3QgYml0bWFwID0gY2FudmFzLnRyYW5zZmVyVG9JbWFnZUJpdG1hcCgpOwogICAgICByZXR1cm4gewogICAgICAgIGRhdGE6IG51bGwsCiAgICAgICAgd2lkdGg6IGRyYXdXaWR0aCwKICAgICAgICBoZWlnaHQ6IGRyYXdIZWlnaHQsCiAgICAgICAgYml0bWFwLAogICAgICAgIGludGVycG9sYXRlOiB0aGlzLmludGVycG9sYXRlCiAgICAgIH07CiAgICB9CiAgICBpbWdEYXRhLmRhdGEgPSBkYXRhOwogICAgaWYgKG11c3RCZVJlc2l6ZWQpIHsKICAgICAgcmV0dXJuIEltYWdlUmVzaXplci5jcmVhdGVJbWFnZShpbWdEYXRhKTsKICAgIH0KICAgIHJldHVybiBpbWdEYXRhOwogIH0KICBhc3luYyBmaWxsR3JheUJ1ZmZlcihidWZmZXIpIHsKICAgIGNvbnN0IG51bUNvbXBzID0gdGhpcy5udW1Db21wczsKICAgIGlmIChudW1Db21wcyAhPT0gMSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYFJlYWRpbmcgZ3JheSBzY2FsZSBmcm9tIGEgY29sb3IgaW1hZ2U6ICR7bnVtQ29tcHN9YCk7CiAgICB9CiAgICBjb25zdCB3aWR0aCA9IHRoaXMud2lkdGg7CiAgICBjb25zdCBoZWlnaHQgPSB0aGlzLmhlaWdodDsKICAgIGNvbnN0IGJwYyA9IHRoaXMuYnBjOwogICAgY29uc3Qgcm93Qnl0ZXMgPSB3aWR0aCAqIG51bUNvbXBzICogYnBjICsgNyA+PiAzOwogICAgY29uc3QgaW1nQXJyYXkgPSBhd2FpdCB0aGlzLmdldEltYWdlQnl0ZXMoaGVpZ2h0ICogcm93Qnl0ZXMsIHsKICAgICAgaW50ZXJuYWw6IHRydWUKICAgIH0pOwogICAgY29uc3QgY29tcHMgPSB0aGlzLmdldENvbXBvbmVudHMoaW1nQXJyYXkpOwogICAgbGV0IGksIGxlbmd0aDsKICAgIGlmIChicGMgPT09IDEpIHsKICAgICAgbGVuZ3RoID0gd2lkdGggKiBoZWlnaHQ7CiAgICAgIGlmICh0aGlzLm5lZWRzRGVjb2RlKSB7CiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICAgICAgICBidWZmZXJbaV0gPSBjb21wc1tpXSAtIDEgJiAyNTU7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICAgICAgYnVmZmVyW2ldID0gLWNvbXBzW2ldICYgMjU1OwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAodGhpcy5uZWVkc0RlY29kZSkgewogICAgICB0aGlzLmRlY29kZUJ1ZmZlcihjb21wcyk7CiAgICB9CiAgICBsZW5ndGggPSB3aWR0aCAqIGhlaWdodDsKICAgIGNvbnN0IHNjYWxlID0gMjU1IC8gKCgxIDw8IGJwYykgLSAxKTsKICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7ICsraSkgewogICAgICBidWZmZXJbaV0gPSBzY2FsZSAqIGNvbXBzW2ldOwogICAgfQogIH0KICBjcmVhdGVCaXRtYXAoa2luZCwgd2lkdGgsIGhlaWdodCwgc3JjKSB7CiAgICBjb25zdCBjYW52YXMgPSBuZXcgT2Zmc2NyZWVuQ2FudmFzKHdpZHRoLCBoZWlnaHQpOwogICAgY29uc3QgY3R4ID0gY2FudmFzLmdldENvbnRleHQoIjJkIik7CiAgICBsZXQgaW1nRGF0YTsKICAgIGlmIChraW5kID09PSBJbWFnZUtpbmQuUkdCQV8zMkJQUCkgewogICAgICBpbWdEYXRhID0gbmV3IEltYWdlRGF0YShzcmMsIHdpZHRoLCBoZWlnaHQpOwogICAgfSBlbHNlIHsKICAgICAgaW1nRGF0YSA9IGN0eC5jcmVhdGVJbWFnZURhdGEod2lkdGgsIGhlaWdodCk7CiAgICAgIGNvbnZlcnRUb1JHQkEoewogICAgICAgIGtpbmQsCiAgICAgICAgc3JjLAogICAgICAgIGRlc3Q6IG5ldyBVaW50MzJBcnJheShpbWdEYXRhLmRhdGEuYnVmZmVyKSwKICAgICAgICB3aWR0aCwKICAgICAgICBoZWlnaHQsCiAgICAgICAgaW52ZXJzZURlY29kZTogdGhpcy5uZWVkc0RlY29kZQogICAgICB9KTsKICAgIH0KICAgIGN0eC5wdXRJbWFnZURhdGEoaW1nRGF0YSwgMCwgMCk7CiAgICBjb25zdCBiaXRtYXAgPSBjYW52YXMudHJhbnNmZXJUb0ltYWdlQml0bWFwKCk7CiAgICByZXR1cm4gewogICAgICBkYXRhOiBudWxsLAogICAgICB3aWR0aCwKICAgICAgaGVpZ2h0LAogICAgICBiaXRtYXAsCiAgICAgIGludGVycG9sYXRlOiB0aGlzLmludGVycG9sYXRlCiAgICB9OwogIH0KICBhc3luYyAjZ2V0SW1hZ2Uod2lkdGgsIGhlaWdodCkgewogICAgY29uc3QgYml0bWFwID0gYXdhaXQgdGhpcy5pbWFnZS5nZXRUcmFuc2ZlcmFibGVJbWFnZSgpOwogICAgaWYgKCFiaXRtYXApIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICByZXR1cm4gewogICAgICBkYXRhOiBudWxsLAogICAgICB3aWR0aCwKICAgICAgaGVpZ2h0LAogICAgICBiaXRtYXAsCiAgICAgIGludGVycG9sYXRlOiB0aGlzLmludGVycG9sYXRlCiAgICB9OwogIH0KICBhc3luYyBnZXRJbWFnZUJ5dGVzKGxlbmd0aCwgewogICAgZHJhd1dpZHRoLAogICAgZHJhd0hlaWdodCwKICAgIGZvcmNlUkdCQSA9IGZhbHNlLAogICAgZm9yY2VSR0IgPSBmYWxzZSwKICAgIGludGVybmFsID0gZmFsc2UKICB9KSB7CiAgICB0aGlzLmltYWdlLnJlc2V0KCk7CiAgICB0aGlzLmltYWdlLmRyYXdXaWR0aCA9IGRyYXdXaWR0aCB8fCB0aGlzLndpZHRoOwogICAgdGhpcy5pbWFnZS5kcmF3SGVpZ2h0ID0gZHJhd0hlaWdodCB8fCB0aGlzLmhlaWdodDsKICAgIHRoaXMuaW1hZ2UuZm9yY2VSR0JBID0gISFmb3JjZVJHQkE7CiAgICB0aGlzLmltYWdlLmZvcmNlUkdCID0gISFmb3JjZVJHQjsKICAgIGNvbnN0IGltYWdlQnl0ZXMgPSBhd2FpdCB0aGlzLmltYWdlLmdldEltYWdlRGF0YShsZW5ndGgsIHRoaXMuanB4RGVjb2Rlck9wdGlvbnMpOwogICAgaWYgKGludGVybmFsIHx8IHRoaXMuaW1hZ2UgaW5zdGFuY2VvZiBEZWNvZGVTdHJlYW0pIHsKICAgICAgcmV0dXJuIGltYWdlQnl0ZXM7CiAgICB9CiAgICBhc3NlcnQoaW1hZ2VCeXRlcyBpbnN0YW5jZW9mIFVpbnQ4QXJyYXksICdQREZJbWFnZS5nZXRJbWFnZUJ5dGVzOiBVbnN1cHBvcnRlZCAiaW1hZ2VCeXRlcyIgdHlwZS4nKTsKICAgIHJldHVybiBuZXcgVWludDhBcnJheShpbWFnZUJ5dGVzKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2V2YWx1YXRvci5qcwoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKY29uc3QgRGVmYXVsdFBhcnRpYWxFdmFsdWF0b3JPcHRpb25zID0gT2JqZWN0LmZyZWV6ZSh7CiAgbWF4SW1hZ2VTaXplOiAtMSwKICBkaXNhYmxlRm9udEZhY2U6IGZhbHNlLAogIGlnbm9yZUVycm9yczogZmFsc2UsCiAgaXNFdmFsU3VwcG9ydGVkOiB0cnVlLAogIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkOiBmYWxzZSwKICBpc0ltYWdlRGVjb2RlclN1cHBvcnRlZDogZmFsc2UsCiAgY2FudmFzTWF4QXJlYUluQnl0ZXM6IC0xLAogIGZvbnRFeHRyYVByb3BlcnRpZXM6IGZhbHNlLAogIHVzZVN5c3RlbUZvbnRzOiB0cnVlLAogIHVzZVdhc206IHRydWUsCiAgdXNlV29ya2VyRmV0Y2g6IHRydWUsCiAgY01hcFVybDogbnVsbCwKICBpY2NVcmw6IG51bGwsCiAgc3RhbmRhcmRGb250RGF0YVVybDogbnVsbCwKICB3YXNtVXJsOiBudWxsCn0pOwpjb25zdCBQYXR0ZXJuVHlwZSA9IHsKICBUSUxJTkc6IDEsCiAgU0hBRElORzogMgp9Owpjb25zdCBURVhUX0NIVU5LX0JBVENIX1NJWkUgPSAxMDsKY29uc3QgZGVmZXJyZWQgPSBQcm9taXNlLnJlc29sdmUoKTsKZnVuY3Rpb24gbm9ybWFsaXplQmxlbmRNb2RlKHZhbHVlLCBwYXJzaW5nQXJyYXkgPSBmYWxzZSkgewogIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkgewogICAgZm9yIChjb25zdCB2YWwgb2YgdmFsdWUpIHsKICAgICAgY29uc3QgbWF5YmVCTSA9IG5vcm1hbGl6ZUJsZW5kTW9kZSh2YWwsIHRydWUpOwogICAgICBpZiAobWF5YmVCTSkgewogICAgICAgIHJldHVybiBtYXliZUJNOwogICAgICB9CiAgICB9CiAgICB3YXJuKGBVbnN1cHBvcnRlZCBibGVuZCBtb2RlIEFycmF5OiAke3ZhbHVlfWApOwogICAgcmV0dXJuICJzb3VyY2Utb3ZlciI7CiAgfQogIGlmICghKHZhbHVlIGluc3RhbmNlb2YgTmFtZSkpIHsKICAgIGlmIChwYXJzaW5nQXJyYXkpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICByZXR1cm4gInNvdXJjZS1vdmVyIjsKICB9CiAgc3dpdGNoICh2YWx1ZS5uYW1lKSB7CiAgICBjYXNlICJOb3JtYWwiOgogICAgY2FzZSAiQ29tcGF0aWJsZSI6CiAgICAgIHJldHVybiAic291cmNlLW92ZXIiOwogICAgY2FzZSAiTXVsdGlwbHkiOgogICAgICByZXR1cm4gIm11bHRpcGx5IjsKICAgIGNhc2UgIlNjcmVlbiI6CiAgICAgIHJldHVybiAic2NyZWVuIjsKICAgIGNhc2UgIk92ZXJsYXkiOgogICAgICByZXR1cm4gIm92ZXJsYXkiOwogICAgY2FzZSAiRGFya2VuIjoKICAgICAgcmV0dXJuICJkYXJrZW4iOwogICAgY2FzZSAiTGlnaHRlbiI6CiAgICAgIHJldHVybiAibGlnaHRlbiI7CiAgICBjYXNlICJDb2xvckRvZGdlIjoKICAgICAgcmV0dXJuICJjb2xvci1kb2RnZSI7CiAgICBjYXNlICJDb2xvckJ1cm4iOgogICAgICByZXR1cm4gImNvbG9yLWJ1cm4iOwogICAgY2FzZSAiSGFyZExpZ2h0IjoKICAgICAgcmV0dXJuICJoYXJkLWxpZ2h0IjsKICAgIGNhc2UgIlNvZnRMaWdodCI6CiAgICAgIHJldHVybiAic29mdC1saWdodCI7CiAgICBjYXNlICJEaWZmZXJlbmNlIjoKICAgICAgcmV0dXJuICJkaWZmZXJlbmNlIjsKICAgIGNhc2UgIkV4Y2x1c2lvbiI6CiAgICAgIHJldHVybiAiZXhjbHVzaW9uIjsKICAgIGNhc2UgIkh1ZSI6CiAgICAgIHJldHVybiAiaHVlIjsKICAgIGNhc2UgIlNhdHVyYXRpb24iOgogICAgICByZXR1cm4gInNhdHVyYXRpb24iOwogICAgY2FzZSAiQ29sb3IiOgogICAgICByZXR1cm4gImNvbG9yIjsKICAgIGNhc2UgIkx1bWlub3NpdHkiOgogICAgICByZXR1cm4gImx1bWlub3NpdHkiOwogIH0KICBpZiAocGFyc2luZ0FycmF5KSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgd2FybihgVW5zdXBwb3J0ZWQgYmxlbmQgbW9kZTogJHt2YWx1ZS5uYW1lfWApOwogIHJldHVybiAic291cmNlLW92ZXIiOwp9CmZ1bmN0aW9uIGFkZENhY2hlZEltYWdlT3BzKG9wTGlzdCwgewogIG9iaklkLAogIGZuLAogIGFyZ3MsCiAgb3B0aW9uYWxDb250ZW50LAogIGhhc01hc2sKfSkgewogIGlmIChvYmpJZCkgewogICAgb3BMaXN0LmFkZERlcGVuZGVuY3kob2JqSWQpOwogIH0KICBvcExpc3QuYWRkSW1hZ2VPcHMoZm4sIGFyZ3MsIG9wdGlvbmFsQ29udGVudCwgaGFzTWFzayk7CiAgaWYgKGZuID09PSBPUFMucGFpbnRJbWFnZU1hc2tYT2JqZWN0ICYmIGFyZ3NbMF0/LmNvdW50ID4gMCkgewogICAgYXJnc1swXS5jb3VudCsrOwogIH0KfQpjbGFzcyBUaW1lU2xvdE1hbmFnZXIgewogIHN0YXRpYyBUSU1FX1NMT1RfRFVSQVRJT05fTVMgPSAyMDsKICBzdGF0aWMgQ0hFQ0tfVElNRV9FVkVSWSA9IDEwMDsKICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMucmVzZXQoKTsKICB9CiAgY2hlY2soKSB7CiAgICBpZiAoKyt0aGlzLmNoZWNrZWQgPCBUaW1lU2xvdE1hbmFnZXIuQ0hFQ0tfVElNRV9FVkVSWSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICB0aGlzLmNoZWNrZWQgPSAwOwogICAgcmV0dXJuIHRoaXMuZW5kVGltZSA8PSBEYXRlLm5vdygpOwogIH0KICByZXNldCgpIHsKICAgIHRoaXMuZW5kVGltZSA9IERhdGUubm93KCkgKyBUaW1lU2xvdE1hbmFnZXIuVElNRV9TTE9UX0RVUkFUSU9OX01TOwogICAgdGhpcy5jaGVja2VkID0gMDsKICB9Cn0KY2xhc3MgUGFydGlhbEV2YWx1YXRvciB7CiAgY29uc3RydWN0b3IoewogICAgeHJlZiwKICAgIGhhbmRsZXIsCiAgICBwYWdlSW5kZXgsCiAgICBpZEZhY3RvcnksCiAgICBmb250Q2FjaGUsCiAgICBidWlsdEluQ01hcENhY2hlLAogICAgc3RhbmRhcmRGb250RGF0YUNhY2hlLAogICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgZ2xvYmFsSW1hZ2VDYWNoZSwKICAgIHN5c3RlbUZvbnRDYWNoZSwKICAgIG9wdGlvbnMgPSBudWxsCiAgfSkgewogICAgdGhpcy54cmVmID0geHJlZjsKICAgIHRoaXMuaGFuZGxlciA9IGhhbmRsZXI7CiAgICB0aGlzLnBhZ2VJbmRleCA9IHBhZ2VJbmRleDsKICAgIHRoaXMuaWRGYWN0b3J5ID0gaWRGYWN0b3J5OwogICAgdGhpcy5mb250Q2FjaGUgPSBmb250Q2FjaGU7CiAgICB0aGlzLmJ1aWx0SW5DTWFwQ2FjaGUgPSBidWlsdEluQ01hcENhY2hlOwogICAgdGhpcy5zdGFuZGFyZEZvbnREYXRhQ2FjaGUgPSBzdGFuZGFyZEZvbnREYXRhQ2FjaGU7CiAgICB0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSA9IGdsb2JhbENvbG9yU3BhY2VDYWNoZTsKICAgIHRoaXMuZ2xvYmFsSW1hZ2VDYWNoZSA9IGdsb2JhbEltYWdlQ2FjaGU7CiAgICB0aGlzLnN5c3RlbUZvbnRDYWNoZSA9IHN5c3RlbUZvbnRDYWNoZTsKICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnMgfHwgRGVmYXVsdFBhcnRpYWxFdmFsdWF0b3JPcHRpb25zOwogICAgdGhpcy50eXBlM0ZvbnRSZWZzID0gbnVsbDsKICAgIHRoaXMuX3JlZ2lvbmFsSW1hZ2VDYWNoZSA9IG5ldyBSZWdpb25hbEltYWdlQ2FjaGUoKTsKICAgIHRoaXMuX2ZldGNoQnVpbHRJbkNNYXBCb3VuZCA9IHRoaXMuZmV0Y2hCdWlsdEluQ01hcC5iaW5kKHRoaXMpOwogIH0KICBnZXQgX3BkZkZ1bmN0aW9uRmFjdG9yeSgpIHsKICAgIGNvbnN0IHBkZkZ1bmN0aW9uRmFjdG9yeSA9IG5ldyBQREZGdW5jdGlvbkZhY3RvcnkoewogICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgIGlzRXZhbFN1cHBvcnRlZDogdGhpcy5vcHRpb25zLmlzRXZhbFN1cHBvcnRlZAogICAgfSk7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJfcGRmRnVuY3Rpb25GYWN0b3J5IiwgcGRmRnVuY3Rpb25GYWN0b3J5KTsKICB9CiAgZ2V0IHBhcnNpbmdUeXBlM0ZvbnQoKSB7CiAgICByZXR1cm4gISF0aGlzLnR5cGUzRm9udFJlZnM7CiAgfQogIGNsb25lKG5ld09wdGlvbnMgPSBudWxsKSB7CiAgICBjb25zdCBuZXdFdmFsdWF0b3IgPSBPYmplY3QuY3JlYXRlKHRoaXMpOwogICAgbmV3RXZhbHVhdG9yLm9wdGlvbnMgPSBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobnVsbCksIHRoaXMub3B0aW9ucywgbmV3T3B0aW9ucyk7CiAgICByZXR1cm4gbmV3RXZhbHVhdG9yOwogIH0KICBoYXNCbGVuZE1vZGVzKHJlc291cmNlcywgbm9uQmxlbmRNb2Rlc1NldCkgewogICAgaWYgKCEocmVzb3VyY2VzIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKHJlc291cmNlcy5vYmpJZCAmJiBub25CbGVuZE1vZGVzU2V0LmhhcyhyZXNvdXJjZXMub2JqSWQpKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGNvbnN0IHByb2Nlc3NlZCA9IG5ldyBSZWZTZXQobm9uQmxlbmRNb2Rlc1NldCk7CiAgICBpZiAocmVzb3VyY2VzLm9iaklkKSB7CiAgICAgIHByb2Nlc3NlZC5wdXQocmVzb3VyY2VzLm9iaklkKTsKICAgIH0KICAgIGNvbnN0IG5vZGVzID0gW3Jlc291cmNlc10sCiAgICAgIHhyZWYgPSB0aGlzLnhyZWY7CiAgICB3aGlsZSAobm9kZXMubGVuZ3RoKSB7CiAgICAgIGNvbnN0IG5vZGUgPSBub2Rlcy5zaGlmdCgpOwogICAgICBjb25zdCBncmFwaGljU3RhdGVzID0gbm9kZS5nZXQoIkV4dEdTdGF0ZSIpOwogICAgICBpZiAoZ3JhcGhpY1N0YXRlcyBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICBmb3IgKGxldCBncmFwaGljU3RhdGUgb2YgZ3JhcGhpY1N0YXRlcy5nZXRSYXdWYWx1ZXMoKSkgewogICAgICAgICAgaWYgKGdyYXBoaWNTdGF0ZSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgICBpZiAocHJvY2Vzc2VkLmhhcyhncmFwaGljU3RhdGUpKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICBncmFwaGljU3RhdGUgPSB4cmVmLmZldGNoKGdyYXBoaWNTdGF0ZSk7CiAgICAgICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICAgICAgcHJvY2Vzc2VkLnB1dChncmFwaGljU3RhdGUpOwogICAgICAgICAgICAgIGluZm8oYGhhc0JsZW5kTW9kZXMgLSBpZ25vcmluZyBFeHRHU3RhdGU6ICIke2V4fSIuYCk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmICghKGdyYXBoaWNTdGF0ZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGdyYXBoaWNTdGF0ZS5vYmpJZCkgewogICAgICAgICAgICBwcm9jZXNzZWQucHV0KGdyYXBoaWNTdGF0ZS5vYmpJZCk7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBibSA9IGdyYXBoaWNTdGF0ZS5nZXQoIkJNIik7CiAgICAgICAgICBpZiAoYm0gaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgIGlmIChibS5uYW1lICE9PSAiTm9ybWFsIikgewogICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKGJtICE9PSB1bmRlZmluZWQgJiYgQXJyYXkuaXNBcnJheShibSkpIHsKICAgICAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGJtKSB7CiAgICAgICAgICAgICAgaWYgKGVsZW1lbnQgaW5zdGFuY2VvZiBOYW1lICYmIGVsZW1lbnQubmFtZSAhPT0gIk5vcm1hbCIpIHsKICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCB4T2JqZWN0cyA9IG5vZGUuZ2V0KCJYT2JqZWN0Iik7CiAgICAgIGlmICghKHhPYmplY3RzIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBmb3IgKGxldCB4T2JqZWN0IG9mIHhPYmplY3RzLmdldFJhd1ZhbHVlcygpKSB7CiAgICAgICAgaWYgKHhPYmplY3QgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICAgIGlmIChwcm9jZXNzZWQuaGFzKHhPYmplY3QpKSB7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgeE9iamVjdCA9IHhyZWYuZmV0Y2goeE9iamVjdCk7CiAgICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgICBwcm9jZXNzZWQucHV0KHhPYmplY3QpOwogICAgICAgICAgICBpbmZvKGBoYXNCbGVuZE1vZGVzIC0gaWdub3JpbmcgWE9iamVjdDogIiR7ZXh9Ii5gKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmICghKHhPYmplY3QgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmICh4T2JqZWN0LmRpY3Qub2JqSWQpIHsKICAgICAgICAgIHByb2Nlc3NlZC5wdXQoeE9iamVjdC5kaWN0Lm9iaklkKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgeFJlc291cmNlcyA9IHhPYmplY3QuZGljdC5nZXQoIlJlc291cmNlcyIpOwogICAgICAgIGlmICghKHhSZXNvdXJjZXMgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmICh4UmVzb3VyY2VzLm9iaklkICYmIHByb2Nlc3NlZC5oYXMoeFJlc291cmNlcy5vYmpJZCkpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBub2Rlcy5wdXNoKHhSZXNvdXJjZXMpOwogICAgICAgIGlmICh4UmVzb3VyY2VzLm9iaklkKSB7CiAgICAgICAgICBwcm9jZXNzZWQucHV0KHhSZXNvdXJjZXMub2JqSWQpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgZm9yIChjb25zdCByZWYgb2YgcHJvY2Vzc2VkKSB7CiAgICAgIG5vbkJsZW5kTW9kZXNTZXQucHV0KHJlZik7CiAgICB9CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGFzeW5jIGZldGNoQnVpbHRJbkNNYXAobmFtZSkgewogICAgY29uc3QgY2FjaGVkRGF0YSA9IHRoaXMuYnVpbHRJbkNNYXBDYWNoZS5nZXQobmFtZSk7CiAgICBpZiAoY2FjaGVkRGF0YSkgewogICAgICByZXR1cm4gY2FjaGVkRGF0YTsKICAgIH0KICAgIGxldCBkYXRhOwogICAgaWYgKHRoaXMub3B0aW9ucy51c2VXb3JrZXJGZXRjaCkgewogICAgICBkYXRhID0gewogICAgICAgIGNNYXBEYXRhOiBhd2FpdCBmZXRjaEJpbmFyeURhdGEoYCR7dGhpcy5vcHRpb25zLmNNYXBVcmx9JHtuYW1lfS5iY21hcGApLAogICAgICAgIGlzQ29tcHJlc3NlZDogdHJ1ZQogICAgICB9OwogICAgfSBlbHNlIHsKICAgICAgZGF0YSA9IGF3YWl0IHRoaXMuaGFuZGxlci5zZW5kV2l0aFByb21pc2UoIkZldGNoQmluYXJ5RGF0YSIsIHsKICAgICAgICB0eXBlOiAiY01hcFJlYWRlckZhY3RvcnkiLAogICAgICAgIG5hbWUKICAgICAgfSk7CiAgICB9CiAgICB0aGlzLmJ1aWx0SW5DTWFwQ2FjaGUuc2V0KG5hbWUsIGRhdGEpOwogICAgcmV0dXJuIGRhdGE7CiAgfQogIGFzeW5jIGZldGNoU3RhbmRhcmRGb250RGF0YShuYW1lKSB7CiAgICBjb25zdCBjYWNoZWREYXRhID0gdGhpcy5zdGFuZGFyZEZvbnREYXRhQ2FjaGUuZ2V0KG5hbWUpOwogICAgaWYgKGNhY2hlZERhdGEpIHsKICAgICAgcmV0dXJuIG5ldyBTdHJlYW0oY2FjaGVkRGF0YSk7CiAgICB9CiAgICBpZiAodGhpcy5vcHRpb25zLnVzZVN5c3RlbUZvbnRzICYmIG5hbWUgIT09ICJTeW1ib2wiICYmIG5hbWUgIT09ICJaYXBmRGluZ2JhdHMiKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3Qgc3RhbmRhcmRGb250TmFtZVRvRmlsZU5hbWUgPSBnZXRGb250TmFtZVRvRmlsZU1hcCgpLAogICAgICBmaWxlbmFtZSA9IHN0YW5kYXJkRm9udE5hbWVUb0ZpbGVOYW1lW25hbWVdOwogICAgbGV0IGRhdGE7CiAgICB0cnkgewogICAgICBpZiAodGhpcy5vcHRpb25zLnVzZVdvcmtlckZldGNoKSB7CiAgICAgICAgZGF0YSA9IGF3YWl0IGZldGNoQmluYXJ5RGF0YShgJHt0aGlzLm9wdGlvbnMuc3RhbmRhcmRGb250RGF0YVVybH0ke2ZpbGVuYW1lfWApOwogICAgICB9IGVsc2UgewogICAgICAgIGRhdGEgPSBhd2FpdCB0aGlzLmhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJGZXRjaEJpbmFyeURhdGEiLCB7CiAgICAgICAgICB0eXBlOiAic3RhbmRhcmRGb250RGF0YUZhY3RvcnkiLAogICAgICAgICAgZmlsZW5hbWUKICAgICAgICB9KTsKICAgICAgfQogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgd2FybihleCk7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgdGhpcy5zdGFuZGFyZEZvbnREYXRhQ2FjaGUuc2V0KG5hbWUsIGRhdGEpOwogICAgcmV0dXJuIG5ldyBTdHJlYW0oZGF0YSk7CiAgfQogIGFzeW5jIGJ1aWxkRm9ybVhPYmplY3QocmVzb3VyY2VzLCB4b2JqLCBzbWFzaywgb3BlcmF0b3JMaXN0LCB0YXNrLCBpbml0aWFsU3RhdGUsIGxvY2FsQ29sb3JTcGFjZUNhY2hlLCBzZWVuUmVmcykgewogICAgY29uc3QgewogICAgICBkaWN0CiAgICB9ID0geG9iajsKICAgIGNvbnN0IG1hdHJpeCA9IGxvb2t1cE1hdHJpeChkaWN0LmdldEFycmF5KCJNYXRyaXgiKSwgbnVsbCk7CiAgICBjb25zdCBiYm94ID0gbG9va3VwTm9ybWFsUmVjdChkaWN0LmdldEFycmF5KCJCQm94IiksIG51bGwpOwogICAgbGV0IG9wdGlvbmFsQ29udGVudCwgZ3JvdXBPcHRpb25zOwogICAgaWYgKGRpY3QuaGFzKCJPQyIpKSB7CiAgICAgIG9wdGlvbmFsQ29udGVudCA9IGF3YWl0IHRoaXMucGFyc2VNYXJrZWRDb250ZW50UHJvcHMoZGljdC5nZXQoIk9DIiksIHJlc291cmNlcyk7CiAgICB9CiAgICBpZiAob3B0aW9uYWxDb250ZW50ICE9PSB1bmRlZmluZWQpIHsKICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5iZWdpbk1hcmtlZENvbnRlbnRQcm9wcywgWyJPQyIsIG9wdGlvbmFsQ29udGVudF0pOwogICAgfQogICAgY29uc3QgZ3JvdXAgPSBkaWN0LmdldCgiR3JvdXAiKTsKICAgIGlmIChncm91cCkgewogICAgICBncm91cE9wdGlvbnMgPSB7CiAgICAgICAgbWF0cml4LAogICAgICAgIGJib3gsCiAgICAgICAgc21hc2ssCiAgICAgICAgaXNvbGF0ZWQ6IGZhbHNlLAogICAgICAgIGtub2Nrb3V0OiBmYWxzZQogICAgICB9OwogICAgICBjb25zdCBncm91cFN1YnR5cGUgPSBncm91cC5nZXQoIlMiKTsKICAgICAgbGV0IGNvbG9yU3BhY2UgPSBudWxsOwogICAgICBpZiAoaXNOYW1lKGdyb3VwU3VidHlwZSwgIlRyYW5zcGFyZW5jeSIpKSB7CiAgICAgICAgZ3JvdXBPcHRpb25zLmlzb2xhdGVkID0gZ3JvdXAuZ2V0KCJJIikgfHwgZmFsc2U7CiAgICAgICAgZ3JvdXBPcHRpb25zLmtub2Nrb3V0ID0gZ3JvdXAuZ2V0KCJLIikgfHwgZmFsc2U7CiAgICAgICAgaWYgKGdyb3VwLmhhcygiQ1MiKSkgewogICAgICAgICAgY29uc3QgY3MgPSB0aGlzLl9nZXRDb2xvclNwYWNlKGdyb3VwLmdldFJhdygiQ1MiKSwgcmVzb3VyY2VzLCBsb2NhbENvbG9yU3BhY2VDYWNoZSk7CiAgICAgICAgICBjb2xvclNwYWNlID0gY3MgaW5zdGFuY2VvZiBDb2xvclNwYWNlID8gY3MgOiBhd2FpdCB0aGlzLl9oYW5kbGVDb2xvclNwYWNlKGNzKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKHNtYXNrPy5iYWNrZHJvcCkgewogICAgICAgIGNvbG9yU3BhY2UgfHw9IENvbG9yU3BhY2VVdGlscy5yZ2I7CiAgICAgICAgc21hc2suYmFja2Ryb3AgPSBjb2xvclNwYWNlLmdldFJnYkhleChzbWFzay5iYWNrZHJvcCwgMCk7CiAgICAgIH0KICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5iZWdpbkdyb3VwLCBbZ3JvdXBPcHRpb25zXSk7CiAgICB9CiAgICBjb25zdCBmMzJtYXRyaXggPSBtYXRyaXggJiYgbmV3IEZsb2F0MzJBcnJheShtYXRyaXgpOwogICAgY29uc3QgZjMyYmJveCA9ICFncm91cCAmJiBiYm94ICYmIG5ldyBGbG9hdDMyQXJyYXkoYmJveCkgfHwgbnVsbDsKICAgIGNvbnN0IGFyZ3MgPSBbZjMybWF0cml4LCBmMzJiYm94XTsKICAgIG9wZXJhdG9yTGlzdC5hZGRPcChPUFMucGFpbnRGb3JtWE9iamVjdEJlZ2luLCBhcmdzKTsKICAgIGNvbnN0IGxvY2FsUmVzb3VyY2VzID0gZGljdC5nZXQoIlJlc291cmNlcyIpOwogICAgYXdhaXQgdGhpcy5nZXRPcGVyYXRvckxpc3QoewogICAgICBzdHJlYW06IHhvYmosCiAgICAgIHRhc2ssCiAgICAgIHJlc291cmNlczogbG9jYWxSZXNvdXJjZXMgaW5zdGFuY2VvZiBEaWN0ID8gbG9jYWxSZXNvdXJjZXMgOiByZXNvdXJjZXMsCiAgICAgIG9wZXJhdG9yTGlzdCwKICAgICAgaW5pdGlhbFN0YXRlLAogICAgICBwcmV2UmVmczogc2VlblJlZnMKICAgIH0pOwogICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5wYWludEZvcm1YT2JqZWN0RW5kLCBbXSk7CiAgICBpZiAoZ3JvdXApIHsKICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5lbmRHcm91cCwgW2dyb3VwT3B0aW9uc10pOwogICAgfQogICAgaWYgKG9wdGlvbmFsQ29udGVudCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChPUFMuZW5kTWFya2VkQ29udGVudCwgW10pOwogICAgfQogIH0KICBfc2VuZEltZ0RhdGEob2JqSWQsIGltZ0RhdGEsIGNhY2hlR2xvYmFsbHkgPSBmYWxzZSkgewogICAgY29uc3QgdHJhbnNmZXJzID0gaW1nRGF0YSA/IFtpbWdEYXRhLmJpdG1hcCB8fCBpbWdEYXRhLmRhdGEuYnVmZmVyXSA6IG51bGw7CiAgICBpZiAodGhpcy5wYXJzaW5nVHlwZTNGb250IHx8IGNhY2hlR2xvYmFsbHkpIHsKICAgICAgcmV0dXJuIHRoaXMuaGFuZGxlci5zZW5kKCJjb21tb25vYmoiLCBbb2JqSWQsICJJbWFnZSIsIGltZ0RhdGFdLCB0cmFuc2ZlcnMpOwogICAgfQogICAgcmV0dXJuIHRoaXMuaGFuZGxlci5zZW5kKCJvYmoiLCBbb2JqSWQsIHRoaXMucGFnZUluZGV4LCAiSW1hZ2UiLCBpbWdEYXRhXSwgdHJhbnNmZXJzKTsKICB9CiAgYXN5bmMgYnVpbGRQYWludEltYWdlWE9iamVjdCh7CiAgICByZXNvdXJjZXMsCiAgICBpbWFnZSwKICAgIGlzSW5saW5lID0gZmFsc2UsCiAgICBvcGVyYXRvckxpc3QsCiAgICBjYWNoZUtleSwKICAgIGxvY2FsSW1hZ2VDYWNoZSwKICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlCiAgfSkgewogICAgY29uc3QgewogICAgICBtYXhJbWFnZVNpemUsCiAgICAgIGlnbm9yZUVycm9ycywKICAgICAgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQKICAgIH0gPSB0aGlzLm9wdGlvbnM7CiAgICBjb25zdCB7CiAgICAgIGRpY3QKICAgIH0gPSBpbWFnZTsKICAgIGNvbnN0IGltYWdlUmVmID0gZGljdC5vYmpJZDsKICAgIGNvbnN0IHcgPSBkaWN0LmdldCgiVyIsICJXaWR0aCIpOwogICAgY29uc3QgaCA9IGRpY3QuZ2V0KCJIIiwgIkhlaWdodCIpOwogICAgaWYgKCEodyAmJiB0eXBlb2YgdyA9PT0gIm51bWJlciIpIHx8ICEoaCAmJiB0eXBlb2YgaCA9PT0gIm51bWJlciIpKSB7CiAgICAgIHdhcm4oIkltYWdlIGRpbWVuc2lvbnMgYXJlIG1pc3NpbmcsIG9yIG5vdCBudW1iZXJzLiIpOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAobWF4SW1hZ2VTaXplICE9PSAtMSAmJiB3ICogaCA+IG1heEltYWdlU2l6ZSkgewogICAgICBjb25zdCBtc2cgPSAiSW1hZ2UgZXhjZWVkZWQgbWF4aW11bSBhbGxvd2VkIHNpemUgYW5kIHdhcyByZW1vdmVkLiI7CiAgICAgIGlmICghaWdub3JlRXJyb3JzKSB7CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7CiAgICAgIH0KICAgICAgd2Fybihtc2cpOwogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgb3B0aW9uYWxDb250ZW50OwogICAgaWYgKGRpY3QuaGFzKCJPQyIpKSB7CiAgICAgIG9wdGlvbmFsQ29udGVudCA9IGF3YWl0IHRoaXMucGFyc2VNYXJrZWRDb250ZW50UHJvcHMoZGljdC5nZXQoIk9DIiksIHJlc291cmNlcyk7CiAgICB9CiAgICBjb25zdCBpbWFnZU1hc2sgPSBkaWN0LmdldCgiSU0iLCAiSW1hZ2VNYXNrIikgfHwgZmFsc2U7CiAgICBsZXQgaW1nRGF0YSwgZm4sIGFyZ3M7CiAgICBpZiAoaW1hZ2VNYXNrKSB7CiAgICAgIGltZ0RhdGEgPSBhd2FpdCBQREZJbWFnZS5jcmVhdGVNYXNrKHsKICAgICAgICBpbWFnZSwKICAgICAgICBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZDogaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgJiYgIXRoaXMucGFyc2luZ1R5cGUzRm9udAogICAgICB9KTsKICAgICAgaWYgKGltZ0RhdGEuaXNTaW5nbGVPcGFxdWVQaXhlbCkgewogICAgICAgIGZuID0gT1BTLnBhaW50U29saWRDb2xvckltYWdlTWFzazsKICAgICAgICBhcmdzID0gW107CiAgICAgICAgb3BlcmF0b3JMaXN0LmFkZEltYWdlT3BzKGZuLCBhcmdzLCBvcHRpb25hbENvbnRlbnQpOwogICAgICAgIGlmIChjYWNoZUtleSkgewogICAgICAgICAgY29uc3QgY2FjaGVEYXRhID0gewogICAgICAgICAgICBmbiwKICAgICAgICAgICAgYXJncywKICAgICAgICAgICAgb3B0aW9uYWxDb250ZW50CiAgICAgICAgICB9OwogICAgICAgICAgbG9jYWxJbWFnZUNhY2hlLnNldChjYWNoZUtleSwgaW1hZ2VSZWYsIGNhY2hlRGF0YSk7CiAgICAgICAgICBpZiAoaW1hZ2VSZWYpIHsKICAgICAgICAgICAgdGhpcy5fcmVnaW9uYWxJbWFnZUNhY2hlLnNldChudWxsLCBpbWFnZVJlZiwgY2FjaGVEYXRhKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmICh0aGlzLnBhcnNpbmdUeXBlM0ZvbnQpIHsKICAgICAgICBhcmdzID0gY29tcGlsZVR5cGUzR2x5cGgoaW1nRGF0YSk7CiAgICAgICAgaWYgKGFyZ3MpIHsKICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGRJbWFnZU9wcyhPUFMuY29uc3RydWN0UGF0aCwgYXJncywgb3B0aW9uYWxDb250ZW50KTsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgd2FybigiQ2Fubm90IGNvbXBpbGUgVHlwZTMgZ2x5cGguIik7CiAgICAgICAgb3BlcmF0b3JMaXN0LmFkZEltYWdlT3BzKE9QUy5wYWludEltYWdlTWFza1hPYmplY3QsIFtpbWdEYXRhXSwgb3B0aW9uYWxDb250ZW50KTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgY29uc3Qgb2JqSWQgPSBgbWFza18ke3RoaXMuaWRGYWN0b3J5LmNyZWF0ZU9iaklkKCl9YDsKICAgICAgb3BlcmF0b3JMaXN0LmFkZERlcGVuZGVuY3kob2JqSWQpOwogICAgICBpbWdEYXRhLmRhdGFMZW4gPSBpbWdEYXRhLmJpdG1hcCA/IGltZ0RhdGEud2lkdGggKiBpbWdEYXRhLmhlaWdodCAqIDQgOiBpbWdEYXRhLmRhdGEubGVuZ3RoOwogICAgICB0aGlzLl9zZW5kSW1nRGF0YShvYmpJZCwgaW1nRGF0YSk7CiAgICAgIGZuID0gT1BTLnBhaW50SW1hZ2VNYXNrWE9iamVjdDsKICAgICAgYXJncyA9IFt7CiAgICAgICAgZGF0YTogb2JqSWQsCiAgICAgICAgd2lkdGg6IGltZ0RhdGEud2lkdGgsCiAgICAgICAgaGVpZ2h0OiBpbWdEYXRhLmhlaWdodCwKICAgICAgICBpbnRlcnBvbGF0ZTogaW1nRGF0YS5pbnRlcnBvbGF0ZSwKICAgICAgICBjb3VudDogMQogICAgICB9XTsKICAgICAgb3BlcmF0b3JMaXN0LmFkZEltYWdlT3BzKGZuLCBhcmdzLCBvcHRpb25hbENvbnRlbnQpOwogICAgICBpZiAoY2FjaGVLZXkpIHsKICAgICAgICBjb25zdCBjYWNoZURhdGEgPSB7CiAgICAgICAgICBvYmpJZCwKICAgICAgICAgIGZuLAogICAgICAgICAgYXJncywKICAgICAgICAgIG9wdGlvbmFsQ29udGVudAogICAgICAgIH07CiAgICAgICAgbG9jYWxJbWFnZUNhY2hlLnNldChjYWNoZUtleSwgaW1hZ2VSZWYsIGNhY2hlRGF0YSk7CiAgICAgICAgaWYgKGltYWdlUmVmKSB7CiAgICAgICAgICB0aGlzLl9yZWdpb25hbEltYWdlQ2FjaGUuc2V0KG51bGwsIGltYWdlUmVmLCBjYWNoZURhdGEpOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBTTUFMTF9JTUFHRV9ESU1FTlNJT05TID0gMjAwOwogICAgY29uc3QgaGFzTWFzayA9IGRpY3QuaGFzKCJTTWFzayIpIHx8IGRpY3QuaGFzKCJNYXNrIik7CiAgICBpZiAoaXNJbmxpbmUgJiYgdyArIGggPCBTTUFMTF9JTUFHRV9ESU1FTlNJT05TICYmICFoYXNNYXNrKSB7CiAgICAgIHRyeSB7CiAgICAgICAgY29uc3QgaW1hZ2VPYmogPSBuZXcgUERGSW1hZ2UoewogICAgICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICAgICAgcmVzOiByZXNvdXJjZXMsCiAgICAgICAgICBpbWFnZSwKICAgICAgICAgIGlzSW5saW5lLAogICAgICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5OiB0aGlzLl9wZGZGdW5jdGlvbkZhY3RvcnksCiAgICAgICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGU6IHRoaXMuZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUKICAgICAgICB9KTsKICAgICAgICBpbWdEYXRhID0gYXdhaXQgaW1hZ2VPYmouY3JlYXRlSW1hZ2VEYXRhKHRydWUsIGZhbHNlKTsKICAgICAgICBvcGVyYXRvckxpc3QuYWRkSW1hZ2VPcHMoT1BTLnBhaW50SW5saW5lSW1hZ2VYT2JqZWN0LCBbaW1nRGF0YV0sIG9wdGlvbmFsQ29udGVudCk7CiAgICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICAgIGNvbnN0IG1zZyA9IGBVbmFibGUgdG8gZGVjb2RlIGlubGluZSBpbWFnZTogIiR7cmVhc29ufSIuYDsKICAgICAgICBpZiAoIWlnbm9yZUVycm9ycykgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7CiAgICAgICAgfQogICAgICAgIHdhcm4obXNnKTsKICAgICAgfQogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgb2JqSWQgPSBgaW1nXyR7dGhpcy5pZEZhY3RvcnkuY3JlYXRlT2JqSWQoKX1gLAogICAgICBjYWNoZUdsb2JhbGx5ID0gZmFsc2UsCiAgICAgIGdsb2JhbENhY2hlRGF0YSA9IG51bGw7CiAgICBpZiAodGhpcy5wYXJzaW5nVHlwZTNGb250KSB7CiAgICAgIG9iaklkID0gYCR7dGhpcy5pZEZhY3RvcnkuZ2V0RG9jSWQoKX1fdHlwZTNfJHtvYmpJZH1gOwogICAgfSBlbHNlIGlmIChjYWNoZUtleSAmJiBpbWFnZVJlZikgewogICAgICBjYWNoZUdsb2JhbGx5ID0gdGhpcy5nbG9iYWxJbWFnZUNhY2hlLnNob3VsZENhY2hlKGltYWdlUmVmLCB0aGlzLnBhZ2VJbmRleCk7CiAgICAgIGlmIChjYWNoZUdsb2JhbGx5KSB7CiAgICAgICAgYXNzZXJ0KCFpc0lubGluZSwgIkNhbm5vdCBjYWNoZSBhbiBpbmxpbmUgaW1hZ2UgZ2xvYmFsbHkuIik7CiAgICAgICAgb2JqSWQgPSBgJHt0aGlzLmlkRmFjdG9yeS5nZXREb2NJZCgpfV8ke29iaklkfWA7CiAgICAgIH0KICAgIH0KICAgIG9wZXJhdG9yTGlzdC5hZGREZXBlbmRlbmN5KG9iaklkKTsKICAgIGZuID0gT1BTLnBhaW50SW1hZ2VYT2JqZWN0OwogICAgYXJncyA9IFtvYmpJZCwgdywgaF07CiAgICBvcGVyYXRvckxpc3QuYWRkSW1hZ2VPcHMoZm4sIGFyZ3MsIG9wdGlvbmFsQ29udGVudCwgaGFzTWFzayk7CiAgICBpZiAoY2FjaGVHbG9iYWxseSkgewogICAgICBnbG9iYWxDYWNoZURhdGEgPSB7CiAgICAgICAgb2JqSWQsCiAgICAgICAgZm4sCiAgICAgICAgYXJncywKICAgICAgICBvcHRpb25hbENvbnRlbnQsCiAgICAgICAgaGFzTWFzaywKICAgICAgICBieXRlU2l6ZTogMAogICAgICB9OwogICAgICBpZiAodGhpcy5nbG9iYWxJbWFnZUNhY2hlLmhhc0RlY29kZUZhaWxlZChpbWFnZVJlZikpIHsKICAgICAgICB0aGlzLmdsb2JhbEltYWdlQ2FjaGUuc2V0RGF0YShpbWFnZVJlZiwgZ2xvYmFsQ2FjaGVEYXRhKTsKICAgICAgICB0aGlzLl9zZW5kSW1nRGF0YShvYmpJZCwgbnVsbCwgY2FjaGVHbG9iYWxseSk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmICh3ICogaCA+IDI1MDAwMCB8fCBoYXNNYXNrKSB7CiAgICAgICAgY29uc3QgbG9jYWxMZW5ndGggPSBhd2FpdCB0aGlzLmhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJjb21tb25vYmoiLCBbb2JqSWQsICJDb3B5TG9jYWxJbWFnZSIsIHsKICAgICAgICAgIGltYWdlUmVmCiAgICAgICAgfV0pOwogICAgICAgIGlmIChsb2NhbExlbmd0aCkgewogICAgICAgICAgdGhpcy5nbG9iYWxJbWFnZUNhY2hlLnNldERhdGEoaW1hZ2VSZWYsIGdsb2JhbENhY2hlRGF0YSk7CiAgICAgICAgICB0aGlzLmdsb2JhbEltYWdlQ2FjaGUuYWRkQnl0ZVNpemUoaW1hZ2VSZWYsIGxvY2FsTGVuZ3RoKTsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIFBERkltYWdlLmJ1aWxkSW1hZ2UoewogICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgIHJlczogcmVzb3VyY2VzLAogICAgICBpbWFnZSwKICAgICAgaXNJbmxpbmUsCiAgICAgIHBkZkZ1bmN0aW9uRmFjdG9yeTogdGhpcy5fcGRmRnVuY3Rpb25GYWN0b3J5LAogICAgICBnbG9iYWxDb2xvclNwYWNlQ2FjaGU6IHRoaXMuZ2xvYmFsQ29sb3JTcGFjZUNhY2hlLAogICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgfSkudGhlbihhc3luYyBpbWFnZU9iaiA9PiB7CiAgICAgIGltZ0RhdGEgPSBhd2FpdCBpbWFnZU9iai5jcmVhdGVJbWFnZURhdGEoZmFsc2UsIGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKTsKICAgICAgaW1nRGF0YS5kYXRhTGVuID0gaW1nRGF0YS5iaXRtYXAgPyBpbWdEYXRhLndpZHRoICogaW1nRGF0YS5oZWlnaHQgKiA0IDogaW1nRGF0YS5kYXRhLmxlbmd0aDsKICAgICAgaW1nRGF0YS5yZWYgPSBpbWFnZVJlZjsKICAgICAgaWYgKGNhY2hlR2xvYmFsbHkpIHsKICAgICAgICB0aGlzLmdsb2JhbEltYWdlQ2FjaGUuYWRkQnl0ZVNpemUoaW1hZ2VSZWYsIGltZ0RhdGEuZGF0YUxlbik7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMuX3NlbmRJbWdEYXRhKG9iaklkLCBpbWdEYXRhLCBjYWNoZUdsb2JhbGx5KTsKICAgIH0pLmNhdGNoKHJlYXNvbiA9PiB7CiAgICAgIHdhcm4oYFVuYWJsZSB0byBkZWNvZGUgaW1hZ2UgIiR7b2JqSWR9IjogIiR7cmVhc29ufSIuYCk7CiAgICAgIGlmIChpbWFnZVJlZikgewogICAgICAgIHRoaXMuZ2xvYmFsSW1hZ2VDYWNoZS5hZGREZWNvZGVGYWlsZWQoaW1hZ2VSZWYpOwogICAgICB9CiAgICAgIHJldHVybiB0aGlzLl9zZW5kSW1nRGF0YShvYmpJZCwgbnVsbCwgY2FjaGVHbG9iYWxseSk7CiAgICB9KTsKICAgIGlmIChjYWNoZUtleSkgewogICAgICBjb25zdCBjYWNoZURhdGEgPSB7CiAgICAgICAgb2JqSWQsCiAgICAgICAgZm4sCiAgICAgICAgYXJncywKICAgICAgICBvcHRpb25hbENvbnRlbnQsCiAgICAgICAgaGFzTWFzawogICAgICB9OwogICAgICBsb2NhbEltYWdlQ2FjaGUuc2V0KGNhY2hlS2V5LCBpbWFnZVJlZiwgY2FjaGVEYXRhKTsKICAgICAgaWYgKGltYWdlUmVmKSB7CiAgICAgICAgdGhpcy5fcmVnaW9uYWxJbWFnZUNhY2hlLnNldChudWxsLCBpbWFnZVJlZiwgY2FjaGVEYXRhKTsKICAgICAgICBpZiAoY2FjaGVHbG9iYWxseSkgewogICAgICAgICAgYXNzZXJ0KGdsb2JhbENhY2hlRGF0YSwgIlRoZSBnbG9iYWwgY2FjaGUtZGF0YSBtdXN0IGJlIGF2YWlsYWJsZS4iKTsKICAgICAgICAgIHRoaXMuZ2xvYmFsSW1hZ2VDYWNoZS5zZXREYXRhKGltYWdlUmVmLCBnbG9iYWxDYWNoZURhdGEpOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KICBoYW5kbGVTTWFzayhzbWFzaywgcmVzb3VyY2VzLCBvcGVyYXRvckxpc3QsIHRhc2ssIHN0YXRlTWFuYWdlciwgbG9jYWxDb2xvclNwYWNlQ2FjaGUsIHNlZW5SZWZzKSB7CiAgICBjb25zdCBzbWFza0NvbnRlbnQgPSBzbWFzay5nZXQoIkciKTsKICAgIGNvbnN0IHNtYXNrT3B0aW9ucyA9IHsKICAgICAgc3VidHlwZTogc21hc2suZ2V0KCJTIikubmFtZSwKICAgICAgYmFja2Ryb3A6IHNtYXNrLmdldCgiQkMiKQogICAgfTsKICAgIGNvbnN0IHRyYW5zZmVyT2JqID0gc21hc2suZ2V0KCJUUiIpOwogICAgaWYgKGlzUERGRnVuY3Rpb24odHJhbnNmZXJPYmopKSB7CiAgICAgIGNvbnN0IHRyYW5zZmVyRm4gPSB0aGlzLl9wZGZGdW5jdGlvbkZhY3RvcnkuY3JlYXRlKHRyYW5zZmVyT2JqKTsKICAgICAgY29uc3QgdHJhbnNmZXJNYXAgPSBuZXcgVWludDhBcnJheSgyNTYpOwogICAgICBjb25zdCB0bXAgPSBuZXcgRmxvYXQzMkFycmF5KDEpOwogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDI1NjsgaSsrKSB7CiAgICAgICAgdG1wWzBdID0gaSAvIDI1NTsKICAgICAgICB0cmFuc2ZlckZuKHRtcCwgMCwgdG1wLCAwKTsKICAgICAgICB0cmFuc2Zlck1hcFtpXSA9IHRtcFswXSAqIDI1NSB8IDA7CiAgICAgIH0KICAgICAgc21hc2tPcHRpb25zLnRyYW5zZmVyTWFwID0gdHJhbnNmZXJNYXA7CiAgICB9CiAgICByZXR1cm4gdGhpcy5idWlsZEZvcm1YT2JqZWN0KHJlc291cmNlcywgc21hc2tDb250ZW50LCBzbWFza09wdGlvbnMsIG9wZXJhdG9yTGlzdCwgdGFzaywgc3RhdGVNYW5hZ2VyLnN0YXRlLmNsb25lKHsKICAgICAgbmV3UGF0aDogdHJ1ZQogICAgfSksIGxvY2FsQ29sb3JTcGFjZUNhY2hlLCBzZWVuUmVmcyk7CiAgfQogIGhhbmRsZVRyYW5zZmVyRnVuY3Rpb24odHIpIHsKICAgIGxldCB0cmFuc2ZlckFycmF5OwogICAgaWYgKEFycmF5LmlzQXJyYXkodHIpKSB7CiAgICAgIHRyYW5zZmVyQXJyYXkgPSB0cjsKICAgIH0gZWxzZSBpZiAoaXNQREZGdW5jdGlvbih0cikpIHsKICAgICAgdHJhbnNmZXJBcnJheSA9IFt0cl07CiAgICB9IGVsc2UgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHRyYW5zZmVyTWFwcyA9IFtdOwogICAgbGV0IG51bUZucyA9IDAsCiAgICAgIG51bUVmZmVjdGZ1bEZucyA9IDA7CiAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIHRyYW5zZmVyQXJyYXkpIHsKICAgICAgY29uc3QgdHJhbnNmZXJPYmogPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihlbnRyeSk7CiAgICAgIG51bUZucysrOwogICAgICBpZiAoaXNOYW1lKHRyYW5zZmVyT2JqLCAiSWRlbnRpdHkiKSkgewogICAgICAgIHRyYW5zZmVyTWFwcy5wdXNoKG51bGwpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9IGVsc2UgaWYgKCFpc1BERkZ1bmN0aW9uKHRyYW5zZmVyT2JqKSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IHRyYW5zZmVyRm4gPSB0aGlzLl9wZGZGdW5jdGlvbkZhY3RvcnkuY3JlYXRlKHRyYW5zZmVyT2JqKTsKICAgICAgY29uc3QgdHJhbnNmZXJNYXAgPSBuZXcgVWludDhBcnJheSgyNTYpLAogICAgICAgIHRtcCA9IG5ldyBGbG9hdDMyQXJyYXkoMSk7CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgMjU2OyBqKyspIHsKICAgICAgICB0bXBbMF0gPSBqIC8gMjU1OwogICAgICAgIHRyYW5zZmVyRm4odG1wLCAwLCB0bXAsIDApOwogICAgICAgIHRyYW5zZmVyTWFwW2pdID0gdG1wWzBdICogMjU1IHwgMDsKICAgICAgfQogICAgICB0cmFuc2Zlck1hcHMucHVzaCh0cmFuc2Zlck1hcCk7CiAgICAgIG51bUVmZmVjdGZ1bEZucysrOwogICAgfQogICAgaWYgKCEobnVtRm5zID09PSAxIHx8IG51bUZucyA9PT0gNCkpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBpZiAobnVtRWZmZWN0ZnVsRm5zID09PSAwKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgcmV0dXJuIHRyYW5zZmVyTWFwczsKICB9CiAgaGFuZGxlVGlsaW5nVHlwZShmbiwgY29sb3IsIHJlc291cmNlcywgcGF0dGVybiwgcGF0dGVybkRpY3QsIG9wZXJhdG9yTGlzdCwgdGFzaywgbG9jYWxUaWxpbmdQYXR0ZXJuQ2FjaGUpIHsKICAgIGNvbnN0IHRpbGluZ09wTGlzdCA9IG5ldyBPcGVyYXRvckxpc3QoKTsKICAgIGNvbnN0IHBhdHRlcm5SZXNvdXJjZXMgPSBEaWN0Lm1lcmdlKHsKICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICBkaWN0QXJyYXk6IFtwYXR0ZXJuRGljdC5nZXQoIlJlc291cmNlcyIpLCByZXNvdXJjZXNdCiAgICB9KTsKICAgIHJldHVybiB0aGlzLmdldE9wZXJhdG9yTGlzdCh7CiAgICAgIHN0cmVhbTogcGF0dGVybiwKICAgICAgdGFzaywKICAgICAgcmVzb3VyY2VzOiBwYXR0ZXJuUmVzb3VyY2VzLAogICAgICBvcGVyYXRvckxpc3Q6IHRpbGluZ09wTGlzdAogICAgfSkudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgIGNvbnN0IG9wZXJhdG9yTGlzdElSID0gdGlsaW5nT3BMaXN0LmdldElSKCk7CiAgICAgIGNvbnN0IHRpbGluZ1BhdHRlcm5JUiA9IGdldFRpbGluZ1BhdHRlcm5JUihvcGVyYXRvckxpc3RJUiwgcGF0dGVybkRpY3QsIGNvbG9yKTsKICAgICAgb3BlcmF0b3JMaXN0LmFkZERlcGVuZGVuY2llcyh0aWxpbmdPcExpc3QuZGVwZW5kZW5jaWVzKTsKICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKGZuLCB0aWxpbmdQYXR0ZXJuSVIpOwogICAgICBpZiAocGF0dGVybkRpY3Qub2JqSWQpIHsKICAgICAgICBsb2NhbFRpbGluZ1BhdHRlcm5DYWNoZS5zZXQobnVsbCwgcGF0dGVybkRpY3Qub2JqSWQsIHsKICAgICAgICAgIG9wZXJhdG9yTGlzdElSLAogICAgICAgICAgZGljdDogcGF0dGVybkRpY3QKICAgICAgICB9KTsKICAgICAgfQogICAgfSkuY2F0Y2gocmVhc29uID0+IHsKICAgICAgaWYgKHJlYXNvbiBpbnN0YW5jZW9mIEFib3J0RXhjZXB0aW9uKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmICh0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgd2FybihgaGFuZGxlVGlsaW5nVHlwZSAtIGlnbm9yaW5nIHBhdHRlcm46ICIke3JlYXNvbn0iLmApOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICB0aHJvdyByZWFzb247CiAgICB9KTsKICB9CiAgYXN5bmMgaGFuZGxlU2V0Rm9udChyZXNvdXJjZXMsIGZvbnRBcmdzLCBmb250UmVmLCBvcGVyYXRvckxpc3QsIHRhc2ssIHN0YXRlLCBmYWxsYmFja0ZvbnREaWN0ID0gbnVsbCwgY3NzRm9udEluZm8gPSBudWxsKSB7CiAgICBjb25zdCBmb250TmFtZSA9IGZvbnRBcmdzPy5bMF0gaW5zdGFuY2VvZiBOYW1lID8gZm9udEFyZ3NbMF0ubmFtZSA6IG51bGw7CiAgICBjb25zdCB0cmFuc2xhdGVkID0gYXdhaXQgdGhpcy5sb2FkRm9udChmb250TmFtZSwgZm9udFJlZiwgcmVzb3VyY2VzLCB0YXNrLCBmYWxsYmFja0ZvbnREaWN0LCBjc3NGb250SW5mbyk7CiAgICBpZiAodHJhbnNsYXRlZC5mb250LmlzVHlwZTNGb250KSB7CiAgICAgIG9wZXJhdG9yTGlzdC5hZGREZXBlbmRlbmNpZXModHJhbnNsYXRlZC50eXBlM0RlcGVuZGVuY2llcyk7CiAgICB9CiAgICBzdGF0ZS5mb250ID0gdHJhbnNsYXRlZC5mb250OwogICAgdHJhbnNsYXRlZC5zZW5kKHRoaXMuaGFuZGxlcik7CiAgICByZXR1cm4gdHJhbnNsYXRlZC5sb2FkZWROYW1lOwogIH0KICBoYW5kbGVUZXh0KGNoYXJzLCBzdGF0ZSkgewogICAgY29uc3QgZm9udCA9IHN0YXRlLmZvbnQ7CiAgICBjb25zdCBnbHlwaHMgPSBmb250LmNoYXJzVG9HbHlwaHMoY2hhcnMpOwogICAgaWYgKGZvbnQuZGF0YSkgewogICAgICBjb25zdCBpc0FkZFRvUGF0aFNldCA9ICEhKHN0YXRlLnRleHRSZW5kZXJpbmdNb2RlICYgVGV4dFJlbmRlcmluZ01vZGUuQUREX1RPX1BBVEhfRkxBRyk7CiAgICAgIGlmIChpc0FkZFRvUGF0aFNldCB8fCBzdGF0ZS5maWxsQ29sb3JTcGFjZS5uYW1lID09PSAiUGF0dGVybiIgfHwgZm9udC5kaXNhYmxlRm9udEZhY2UpIHsKICAgICAgICBQYXJ0aWFsRXZhbHVhdG9yLmJ1aWxkRm9udFBhdGhzKGZvbnQsIGdseXBocywgdGhpcy5oYW5kbGVyLCB0aGlzLm9wdGlvbnMpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gZ2x5cGhzOwogIH0KICBlbnN1cmVTdGF0ZUZvbnQoc3RhdGUpIHsKICAgIGlmIChzdGF0ZS5mb250KSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHJlYXNvbiA9IG5ldyBGb3JtYXRFcnJvcigiTWlzc2luZyBzZXRGb250IChUZikgb3BlcmF0b3IgYmVmb3JlIHRleHQgcmVuZGVyaW5nIG9wZXJhdG9yLiIpOwogICAgaWYgKHRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgd2FybihgZW5zdXJlU3RhdGVGb250OiAiJHtyZWFzb259Ii5gKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhyb3cgcmVhc29uOwogIH0KICBhc3luYyBzZXRHU3RhdGUoewogICAgcmVzb3VyY2VzLAogICAgZ1N0YXRlLAogICAgb3BlcmF0b3JMaXN0LAogICAgY2FjaGVLZXksCiAgICB0YXNrLAogICAgc3RhdGVNYW5hZ2VyLAogICAgbG9jYWxHU3RhdGVDYWNoZSwKICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlLAogICAgc2VlblJlZnMKICB9KSB7CiAgICBjb25zdCBnU3RhdGVSZWYgPSBnU3RhdGUub2JqSWQ7CiAgICBsZXQgaXNTaW1wbGVHU3RhdGUgPSB0cnVlOwogICAgY29uc3QgZ1N0YXRlT2JqID0gW107CiAgICBsZXQgcHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZSgpOwogICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgZ1N0YXRlKSB7CiAgICAgIHN3aXRjaCAoa2V5KSB7CiAgICAgICAgY2FzZSAiVHlwZSI6CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJMVyI6CiAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAibnVtYmVyIikgewogICAgICAgICAgICB3YXJuKGBJbnZhbGlkIExXIChsaW5lIHdpZHRoKTogJHt2YWx1ZX1gKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBnU3RhdGVPYmoucHVzaChba2V5LCBNYXRoLmFicyh2YWx1ZSldKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkxDIjoKICAgICAgICBjYXNlICJMSiI6CiAgICAgICAgY2FzZSAiTUwiOgogICAgICAgIGNhc2UgIkQiOgogICAgICAgIGNhc2UgIlJJIjoKICAgICAgICBjYXNlICJGTCI6CiAgICAgICAgY2FzZSAiQ0EiOgogICAgICAgIGNhc2UgImNhIjoKICAgICAgICAgIGdTdGF0ZU9iai5wdXNoKFtrZXksIHZhbHVlXSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJGb250IjoKICAgICAgICAgIGlzU2ltcGxlR1N0YXRlID0gZmFsc2U7CiAgICAgICAgICBwcm9taXNlID0gcHJvbWlzZS50aGVuKCgpID0+IHRoaXMuaGFuZGxlU2V0Rm9udChyZXNvdXJjZXMsIG51bGwsIHZhbHVlWzBdLCBvcGVyYXRvckxpc3QsIHRhc2ssIHN0YXRlTWFuYWdlci5zdGF0ZSkudGhlbihmdW5jdGlvbiAobG9hZGVkTmFtZSkgewogICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkRGVwZW5kZW5jeShsb2FkZWROYW1lKTsKICAgICAgICAgICAgZ1N0YXRlT2JqLnB1c2goW2tleSwgW2xvYWRlZE5hbWUsIHZhbHVlWzFdXV0pOwogICAgICAgICAgfSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiQk0iOgogICAgICAgICAgZ1N0YXRlT2JqLnB1c2goW2tleSwgbm9ybWFsaXplQmxlbmRNb2RlKHZhbHVlKV0pOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiU01hc2siOgogICAgICAgICAgaWYgKGlzTmFtZSh2YWx1ZSwgIk5vbmUiKSkgewogICAgICAgICAgICBnU3RhdGVPYmoucHVzaChba2V5LCBmYWxzZV0pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICAgICAgaXNTaW1wbGVHU3RhdGUgPSBmYWxzZTsKICAgICAgICAgICAgcHJvbWlzZSA9IHByb21pc2UudGhlbigoKSA9PiB0aGlzLmhhbmRsZVNNYXNrKHZhbHVlLCByZXNvdXJjZXMsIG9wZXJhdG9yTGlzdCwgdGFzaywgc3RhdGVNYW5hZ2VyLCBsb2NhbENvbG9yU3BhY2VDYWNoZSwgc2VlblJlZnMpKTsKICAgICAgICAgICAgZ1N0YXRlT2JqLnB1c2goW2tleSwgdHJ1ZV0pOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgd2FybigiVW5zdXBwb3J0ZWQgU01hc2sgdHlwZSIpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiVFIiOgogICAgICAgICAgY29uc3QgdHJhbnNmZXJNYXBzID0gdGhpcy5oYW5kbGVUcmFuc2ZlckZ1bmN0aW9uKHZhbHVlKTsKICAgICAgICAgIGdTdGF0ZU9iai5wdXNoKFtrZXksIHRyYW5zZmVyTWFwc10pOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiT1AiOgogICAgICAgIGNhc2UgIm9wIjoKICAgICAgICBjYXNlICJPUE0iOgogICAgICAgIGNhc2UgIkJHIjoKICAgICAgICBjYXNlICJCRzIiOgogICAgICAgIGNhc2UgIlVDUiI6CiAgICAgICAgY2FzZSAiVUNSMiI6CiAgICAgICAgY2FzZSAiVFIyIjoKICAgICAgICBjYXNlICJIVCI6CiAgICAgICAgY2FzZSAiU00iOgogICAgICAgIGNhc2UgIlNBIjoKICAgICAgICBjYXNlICJBSVMiOgogICAgICAgIGNhc2UgIlRLIjoKICAgICAgICAgIGluZm8oImdyYXBoaWMgc3RhdGUgb3BlcmF0b3IgIiArIGtleSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgaW5mbygiVW5rbm93biBncmFwaGljIHN0YXRlIG9wZXJhdG9yICIgKyBrZXkpOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGF3YWl0IHByb21pc2U7CiAgICBpZiAoZ1N0YXRlT2JqLmxlbmd0aCA+IDApIHsKICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5zZXRHU3RhdGUsIFtnU3RhdGVPYmpdKTsKICAgIH0KICAgIGlmIChpc1NpbXBsZUdTdGF0ZSkgewogICAgICBsb2NhbEdTdGF0ZUNhY2hlLnNldChjYWNoZUtleSwgZ1N0YXRlUmVmLCBnU3RhdGVPYmopOwogICAgfQogIH0KICBsb2FkRm9udChmb250TmFtZSwgZm9udCwgcmVzb3VyY2VzLCB0YXNrLCBmYWxsYmFja0ZvbnREaWN0ID0gbnVsbCwgY3NzRm9udEluZm8gPSBudWxsKSB7CiAgICBjb25zdCBlcnJvckZvbnQgPSBhc3luYyAoKSA9PiBuZXcgVHJhbnNsYXRlZEZvbnQoewogICAgICBsb2FkZWROYW1lOiAiZ19mb250X2Vycm9yIiwKICAgICAgZm9udDogbmV3IEVycm9yRm9udChgRm9udCAiJHtmb250TmFtZX0iIGlzIG5vdCBhdmFpbGFibGUuYCksCiAgICAgIGRpY3Q6IGZvbnQKICAgIH0pOwogICAgbGV0IGZvbnRSZWY7CiAgICBpZiAoZm9udCkgewogICAgICBpZiAoZm9udCBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIGZvbnRSZWYgPSBmb250OwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBmb250UmVzID0gcmVzb3VyY2VzLmdldCgiRm9udCIpOwogICAgICBpZiAoZm9udFJlcykgewogICAgICAgIGZvbnRSZWYgPSBmb250UmVzLmdldFJhdyhmb250TmFtZSk7CiAgICAgIH0KICAgIH0KICAgIGlmIChmb250UmVmKSB7CiAgICAgIGlmICh0aGlzLnR5cGUzRm9udFJlZnM/Lmhhcyhmb250UmVmKSkgewogICAgICAgIHJldHVybiBlcnJvckZvbnQoKTsKICAgICAgfQogICAgICBpZiAodGhpcy5mb250Q2FjaGUuaGFzKGZvbnRSZWYpKSB7CiAgICAgICAgcmV0dXJuIHRoaXMuZm9udENhY2hlLmdldChmb250UmVmKTsKICAgICAgfQogICAgICB0cnkgewogICAgICAgIGZvbnQgPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihmb250UmVmKTsKICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICB3YXJuKGBsb2FkRm9udCAtIGxvb2t1cCBmYWlsZWQ6ICIke2V4fSIuYCk7CiAgICAgIH0KICAgIH0KICAgIGlmICghKGZvbnQgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICBpZiAoIXRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMgJiYgIXRoaXMucGFyc2luZ1R5cGUzRm9udCkgewogICAgICAgIHdhcm4oYEZvbnQgIiR7Zm9udE5hbWV9IiBpcyBub3QgYXZhaWxhYmxlLmApOwogICAgICAgIHJldHVybiBlcnJvckZvbnQoKTsKICAgICAgfQogICAgICB3YXJuKGBGb250ICIke2ZvbnROYW1lfSIgaXMgbm90IGF2YWlsYWJsZSAtLSBhdHRlbXB0aW5nIHRvIGZhbGxiYWNrIHRvIGEgZGVmYXVsdCBmb250LmApOwogICAgICBmb250ID0gZmFsbGJhY2tGb250RGljdCB8fCBQYXJ0aWFsRXZhbHVhdG9yLmZhbGxiYWNrRm9udERpY3Q7CiAgICB9CiAgICBpZiAoZm9udC5jYWNoZUtleSAmJiB0aGlzLmZvbnRDYWNoZS5oYXMoZm9udC5jYWNoZUtleSkpIHsKICAgICAgcmV0dXJuIHRoaXMuZm9udENhY2hlLmdldChmb250LmNhY2hlS2V5KTsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgcHJvbWlzZSwKICAgICAgcmVzb2x2ZQogICAgfSA9IFByb21pc2Uud2l0aFJlc29sdmVycygpOwogICAgbGV0IHByZUV2YWx1YXRlZEZvbnQ7CiAgICB0cnkgewogICAgICBwcmVFdmFsdWF0ZWRGb250ID0gdGhpcy5wcmVFdmFsdWF0ZUZvbnQoZm9udCk7CiAgICAgIHByZUV2YWx1YXRlZEZvbnQuY3NzRm9udEluZm8gPSBjc3NGb250SW5mbzsKICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICB3YXJuKGBsb2FkRm9udCAtIHByZUV2YWx1YXRlRm9udCBmYWlsZWQ6ICIke3JlYXNvbn0iLmApOwogICAgICByZXR1cm4gZXJyb3JGb250KCk7CiAgICB9CiAgICBjb25zdCB7CiAgICAgIGRlc2NyaXB0b3IsCiAgICAgIGhhc2gKICAgIH0gPSBwcmVFdmFsdWF0ZWRGb250OwogICAgY29uc3QgZm9udFJlZklzUmVmID0gZm9udFJlZiBpbnN0YW5jZW9mIFJlZjsKICAgIGxldCBmb250SUQ7CiAgICBpZiAoaGFzaCAmJiBkZXNjcmlwdG9yIGluc3RhbmNlb2YgRGljdCkgewogICAgICBjb25zdCBmb250QWxpYXNlcyA9IGRlc2NyaXB0b3IuZm9udEFsaWFzZXMgfHw9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIGlmIChmb250QWxpYXNlc1toYXNoXSkgewogICAgICAgIGNvbnN0IGFsaWFzRm9udFJlZiA9IGZvbnRBbGlhc2VzW2hhc2hdLmFsaWFzUmVmOwogICAgICAgIGlmIChmb250UmVmSXNSZWYgJiYgYWxpYXNGb250UmVmICYmIHRoaXMuZm9udENhY2hlLmhhcyhhbGlhc0ZvbnRSZWYpKSB7CiAgICAgICAgICB0aGlzLmZvbnRDYWNoZS5wdXRBbGlhcyhmb250UmVmLCBhbGlhc0ZvbnRSZWYpOwogICAgICAgICAgcmV0dXJuIHRoaXMuZm9udENhY2hlLmdldChmb250UmVmKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9udEFsaWFzZXNbaGFzaF0gPSB7CiAgICAgICAgICBmb250SUQ6IHRoaXMuaWRGYWN0b3J5LmNyZWF0ZUZvbnRJZCgpCiAgICAgICAgfTsKICAgICAgfQogICAgICBpZiAoZm9udFJlZklzUmVmKSB7CiAgICAgICAgZm9udEFsaWFzZXNbaGFzaF0uYWxpYXNSZWYgPSBmb250UmVmOwogICAgICB9CiAgICAgIGZvbnRJRCA9IGZvbnRBbGlhc2VzW2hhc2hdLmZvbnRJRDsKICAgIH0gZWxzZSB7CiAgICAgIGZvbnRJRCA9IHRoaXMuaWRGYWN0b3J5LmNyZWF0ZUZvbnRJZCgpOwogICAgfQogICAgYXNzZXJ0KGZvbnRJRD8uc3RhcnRzV2l0aCgiZiIpLCAnVGhlICJmb250SUQiIG11c3QgYmUgKGNvcnJlY3RseSkgZGVmaW5lZC4nKTsKICAgIGlmIChmb250UmVmSXNSZWYpIHsKICAgICAgdGhpcy5mb250Q2FjaGUucHV0KGZvbnRSZWYsIHByb21pc2UpOwogICAgfSBlbHNlIHsKICAgICAgZm9udC5jYWNoZUtleSA9IGBjYWNoZUtleV8ke2ZvbnRJRH1gOwogICAgICB0aGlzLmZvbnRDYWNoZS5wdXQoZm9udC5jYWNoZUtleSwgcHJvbWlzZSk7CiAgICB9CiAgICBmb250LmxvYWRlZE5hbWUgPSBgJHt0aGlzLmlkRmFjdG9yeS5nZXREb2NJZCgpfV8ke2ZvbnRJRH1gOwogICAgdGhpcy50cmFuc2xhdGVGb250KHByZUV2YWx1YXRlZEZvbnQpLnRoZW4oYXN5bmMgdHJhbnNsYXRlZEZvbnQgPT4gewogICAgICBjb25zdCB0cmFuc2xhdGVkID0gbmV3IFRyYW5zbGF0ZWRGb250KHsKICAgICAgICBsb2FkZWROYW1lOiBmb250LmxvYWRlZE5hbWUsCiAgICAgICAgZm9udDogdHJhbnNsYXRlZEZvbnQsCiAgICAgICAgZGljdDogZm9udAogICAgICB9KTsKICAgICAgaWYgKHRyYW5zbGF0ZWRGb250LmlzVHlwZTNGb250KSB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGF3YWl0IHRyYW5zbGF0ZWQubG9hZFR5cGUzRGF0YSh0aGlzLCByZXNvdXJjZXMsIHRhc2spOwogICAgICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUeXBlMyBmb250IGxvYWQgZXJyb3I6ICR7cmVhc29ufWApOwogICAgICAgIH0KICAgICAgfQogICAgICByZXNvbHZlKHRyYW5zbGF0ZWQpOwogICAgfSkuY2F0Y2gocmVhc29uID0+IHsKICAgICAgd2FybihgbG9hZEZvbnQgLSB0cmFuc2xhdGVGb250IGZhaWxlZDogIiR7cmVhc29ufSIuYCk7CiAgICAgIHJlc29sdmUobmV3IFRyYW5zbGF0ZWRGb250KHsKICAgICAgICBsb2FkZWROYW1lOiBmb250LmxvYWRlZE5hbWUsCiAgICAgICAgZm9udDogbmV3IEVycm9yRm9udChyZWFzb24/Lm1lc3NhZ2UpLAogICAgICAgIGRpY3Q6IGZvbnQKICAgICAgfSkpOwogICAgfSk7CiAgICByZXR1cm4gcHJvbWlzZTsKICB9CiAgYnVpbGRQYXRoKGZuLCBhcmdzLCBzdGF0ZSkgewogICAgY29uc3QgewogICAgICBwYXRoTWluTWF4OiBtaW5NYXgsCiAgICAgIHBhdGhCdWZmZXIKICAgIH0gPSBzdGF0ZTsKICAgIHN3aXRjaCAoZm4gfCAwKSB7CiAgICAgIGNhc2UgT1BTLnJlY3RhbmdsZToKICAgICAgICB7CiAgICAgICAgICBjb25zdCB4ID0gc3RhdGUuY3VycmVudFBvaW50WCA9IGFyZ3NbMF07CiAgICAgICAgICBjb25zdCB5ID0gc3RhdGUuY3VycmVudFBvaW50WSA9IGFyZ3NbMV07CiAgICAgICAgICBjb25zdCB3aWR0aCA9IGFyZ3NbMl07CiAgICAgICAgICBjb25zdCBoZWlnaHQgPSBhcmdzWzNdOwogICAgICAgICAgY29uc3QgeHcgPSB4ICsgd2lkdGg7CiAgICAgICAgICBjb25zdCB5aCA9IHkgKyBoZWlnaHQ7CiAgICAgICAgICBpZiAod2lkdGggPT09IDAgfHwgaGVpZ2h0ID09PSAwKSB7CiAgICAgICAgICAgIHBhdGhCdWZmZXIucHVzaChEcmF3T1BTLm1vdmVUbywgeCwgeSwgRHJhd09QUy5saW5lVG8sIHh3LCB5aCwgRHJhd09QUy5jbG9zZVBhdGgpOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgcGF0aEJ1ZmZlci5wdXNoKERyYXdPUFMubW92ZVRvLCB4LCB5LCBEcmF3T1BTLmxpbmVUbywgeHcsIHksIERyYXdPUFMubGluZVRvLCB4dywgeWgsIERyYXdPUFMubGluZVRvLCB4LCB5aCwgRHJhd09QUy5jbG9zZVBhdGgpOwogICAgICAgICAgfQogICAgICAgICAgVXRpbC5yZWN0Qm91bmRpbmdCb3goeCwgeSwgeHcsIHloLCBtaW5NYXgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICBjYXNlIE9QUy5tb3ZlVG86CiAgICAgICAgewogICAgICAgICAgY29uc3QgeCA9IHN0YXRlLmN1cnJlbnRQb2ludFggPSBhcmdzWzBdOwogICAgICAgICAgY29uc3QgeSA9IHN0YXRlLmN1cnJlbnRQb2ludFkgPSBhcmdzWzFdOwogICAgICAgICAgcGF0aEJ1ZmZlci5wdXNoKERyYXdPUFMubW92ZVRvLCB4LCB5KTsKICAgICAgICAgIFV0aWwucG9pbnRCb3VuZGluZ0JveCh4LCB5LCBtaW5NYXgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICBjYXNlIE9QUy5saW5lVG86CiAgICAgICAgewogICAgICAgICAgY29uc3QgeCA9IHN0YXRlLmN1cnJlbnRQb2ludFggPSBhcmdzWzBdOwogICAgICAgICAgY29uc3QgeSA9IHN0YXRlLmN1cnJlbnRQb2ludFkgPSBhcmdzWzFdOwogICAgICAgICAgcGF0aEJ1ZmZlci5wdXNoKERyYXdPUFMubGluZVRvLCB4LCB5KTsKICAgICAgICAgIFV0aWwucG9pbnRCb3VuZGluZ0JveCh4LCB5LCBtaW5NYXgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICBjYXNlIE9QUy5jdXJ2ZVRvOgogICAgICAgIHsKICAgICAgICAgIGNvbnN0IHN0YXJ0WCA9IHN0YXRlLmN1cnJlbnRQb2ludFg7CiAgICAgICAgICBjb25zdCBzdGFydFkgPSBzdGF0ZS5jdXJyZW50UG9pbnRZOwogICAgICAgICAgY29uc3QgW3gxLCB5MSwgeDIsIHkyLCB4LCB5XSA9IGFyZ3M7CiAgICAgICAgICBzdGF0ZS5jdXJyZW50UG9pbnRYID0geDsKICAgICAgICAgIHN0YXRlLmN1cnJlbnRQb2ludFkgPSB5OwogICAgICAgICAgcGF0aEJ1ZmZlci5wdXNoKERyYXdPUFMuY3VydmVUbywgeDEsIHkxLCB4MiwgeTIsIHgsIHkpOwogICAgICAgICAgVXRpbC5iZXppZXJCb3VuZGluZ0JveChzdGFydFgsIHN0YXJ0WSwgeDEsIHkxLCB4MiwgeTIsIHgsIHksIG1pbk1heCk7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIGNhc2UgT1BTLmN1cnZlVG8yOgogICAgICAgIHsKICAgICAgICAgIGNvbnN0IHN0YXJ0WCA9IHN0YXRlLmN1cnJlbnRQb2ludFg7CiAgICAgICAgICBjb25zdCBzdGFydFkgPSBzdGF0ZS5jdXJyZW50UG9pbnRZOwogICAgICAgICAgY29uc3QgW3gxLCB5MSwgeCwgeV0gPSBhcmdzOwogICAgICAgICAgc3RhdGUuY3VycmVudFBvaW50WCA9IHg7CiAgICAgICAgICBzdGF0ZS5jdXJyZW50UG9pbnRZID0geTsKICAgICAgICAgIHBhdGhCdWZmZXIucHVzaChEcmF3T1BTLmN1cnZlVG8sIHN0YXJ0WCwgc3RhcnRZLCB4MSwgeTEsIHgsIHkpOwogICAgICAgICAgVXRpbC5iZXppZXJCb3VuZGluZ0JveChzdGFydFgsIHN0YXJ0WSwgc3RhcnRYLCBzdGFydFksIHgxLCB5MSwgeCwgeSwgbWluTWF4KTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgY2FzZSBPUFMuY3VydmVUbzM6CiAgICAgICAgewogICAgICAgICAgY29uc3Qgc3RhcnRYID0gc3RhdGUuY3VycmVudFBvaW50WDsKICAgICAgICAgIGNvbnN0IHN0YXJ0WSA9IHN0YXRlLmN1cnJlbnRQb2ludFk7CiAgICAgICAgICBjb25zdCBbeDEsIHkxLCB4LCB5XSA9IGFyZ3M7CiAgICAgICAgICBzdGF0ZS5jdXJyZW50UG9pbnRYID0geDsKICAgICAgICAgIHN0YXRlLmN1cnJlbnRQb2ludFkgPSB5OwogICAgICAgICAgcGF0aEJ1ZmZlci5wdXNoKERyYXdPUFMuY3VydmVUbywgeDEsIHkxLCB4LCB5LCB4LCB5KTsKICAgICAgICAgIFV0aWwuYmV6aWVyQm91bmRpbmdCb3goc3RhcnRYLCBzdGFydFksIHgxLCB5MSwgeCwgeSwgeCwgeSwgbWluTWF4KTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgY2FzZSBPUFMuY2xvc2VQYXRoOgogICAgICAgIHBhdGhCdWZmZXIucHVzaChEcmF3T1BTLmNsb3NlUGF0aCk7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgfQogIF9nZXRDb2xvclNwYWNlKGNzLCByZXNvdXJjZXMsIGxvY2FsQ29sb3JTcGFjZUNhY2hlKSB7CiAgICByZXR1cm4gQ29sb3JTcGFjZVV0aWxzLnBhcnNlKHsKICAgICAgY3MsCiAgICAgIHhyZWY6IHRoaXMueHJlZiwKICAgICAgcmVzb3VyY2VzLAogICAgICBwZGZGdW5jdGlvbkZhY3Rvcnk6IHRoaXMuX3BkZkZ1bmN0aW9uRmFjdG9yeSwKICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOiB0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUsCiAgICAgIGFzeW5jSWZOb3RDYWNoZWQ6IHRydWUKICAgIH0pOwogIH0KICBhc3luYyBfaGFuZGxlQ29sb3JTcGFjZShjc1Byb21pc2UpIHsKICAgIHRyeSB7CiAgICAgIHJldHVybiBhd2FpdCBjc1Byb21pc2U7CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoZXggaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbikgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGlmICh0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgd2FybihgX2hhbmRsZUNvbG9yU3BhY2UgLSBpZ25vcmluZyBDb2xvclNwYWNlOiAiJHtleH0iLmApOwogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIHRocm93IGV4OwogICAgfQogIH0KICBwYXJzZVNoYWRpbmcoewogICAgc2hhZGluZywKICAgIHJlc291cmNlcywKICAgIGxvY2FsQ29sb3JTcGFjZUNhY2hlLAogICAgbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlCiAgfSkgewogICAgbGV0IGlkID0gbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlLmdldChzaGFkaW5nKTsKICAgIGlmIChpZCkgewogICAgICByZXR1cm4gaWQ7CiAgICB9CiAgICBsZXQgcGF0dGVybklSOwogICAgdHJ5IHsKICAgICAgY29uc3Qgc2hhZGluZ0ZpbGwgPSBQYXR0ZXJuLnBhcnNlU2hhZGluZyhzaGFkaW5nLCB0aGlzLnhyZWYsIHJlc291cmNlcywgdGhpcy5fcGRmRnVuY3Rpb25GYWN0b3J5LCB0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSwgbG9jYWxDb2xvclNwYWNlQ2FjaGUpOwogICAgICBwYXR0ZXJuSVIgPSBzaGFkaW5nRmlsbC5nZXRJUigpOwogICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbikgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGlmICh0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgd2FybihgcGFyc2VTaGFkaW5nIC0gaWdub3Jpbmcgc2hhZGluZzogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlLnNldChzaGFkaW5nLCBudWxsKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICB0aHJvdyByZWFzb247CiAgICB9CiAgICBpZCA9IGBwYXR0ZXJuXyR7dGhpcy5pZEZhY3RvcnkuY3JlYXRlT2JqSWQoKX1gOwogICAgaWYgKHRoaXMucGFyc2luZ1R5cGUzRm9udCkgewogICAgICBpZCA9IGAke3RoaXMuaWRGYWN0b3J5LmdldERvY0lkKCl9X3R5cGUzXyR7aWR9YDsKICAgIH0KICAgIGxvY2FsU2hhZGluZ1BhdHRlcm5DYWNoZS5zZXQoc2hhZGluZywgaWQpOwogICAgaWYgKHRoaXMucGFyc2luZ1R5cGUzRm9udCkgewogICAgICB0aGlzLmhhbmRsZXIuc2VuZCgiY29tbW9ub2JqIiwgW2lkLCAiUGF0dGVybiIsIHBhdHRlcm5JUl0pOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5oYW5kbGVyLnNlbmQoIm9iaiIsIFtpZCwgdGhpcy5wYWdlSW5kZXgsICJQYXR0ZXJuIiwgcGF0dGVybklSXSk7CiAgICB9CiAgICByZXR1cm4gaWQ7CiAgfQogIGhhbmRsZUNvbG9yTihvcGVyYXRvckxpc3QsIGZuLCBhcmdzLCBjcywgcGF0dGVybnMsIHJlc291cmNlcywgdGFzaywgbG9jYWxDb2xvclNwYWNlQ2FjaGUsIGxvY2FsVGlsaW5nUGF0dGVybkNhY2hlLCBsb2NhbFNoYWRpbmdQYXR0ZXJuQ2FjaGUpIHsKICAgIGNvbnN0IHBhdHRlcm5OYW1lID0gYXJncy5wb3AoKTsKICAgIGlmIChwYXR0ZXJuTmFtZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgY29uc3QgcmF3UGF0dGVybiA9IHBhdHRlcm5zLmdldFJhdyhwYXR0ZXJuTmFtZS5uYW1lKTsKICAgICAgY29uc3QgbG9jYWxUaWxpbmdQYXR0ZXJuID0gcmF3UGF0dGVybiBpbnN0YW5jZW9mIFJlZiAmJiBsb2NhbFRpbGluZ1BhdHRlcm5DYWNoZS5nZXRCeVJlZihyYXdQYXR0ZXJuKTsKICAgICAgaWYgKGxvY2FsVGlsaW5nUGF0dGVybikgewogICAgICAgIHRyeSB7CiAgICAgICAgICBjb25zdCBjb2xvciA9IGNzLmJhc2UgPyBjcy5iYXNlLmdldFJnYkhleChhcmdzLCAwKSA6IG51bGw7CiAgICAgICAgICBjb25zdCB0aWxpbmdQYXR0ZXJuSVIgPSBnZXRUaWxpbmdQYXR0ZXJuSVIobG9jYWxUaWxpbmdQYXR0ZXJuLm9wZXJhdG9yTGlzdElSLCBsb2NhbFRpbGluZ1BhdHRlcm4uZGljdCwgY29sb3IpOwogICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKGZuLCB0aWxpbmdQYXR0ZXJuSVIpOwogICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgICAgICB9IGNhdGNoIHt9CiAgICAgIH0KICAgICAgY29uc3QgcGF0dGVybiA9IHRoaXMueHJlZi5mZXRjaElmUmVmKHJhd1BhdHRlcm4pOwogICAgICBpZiAocGF0dGVybikgewogICAgICAgIGNvbnN0IGRpY3QgPSBwYXR0ZXJuIGluc3RhbmNlb2YgQmFzZVN0cmVhbSA/IHBhdHRlcm4uZGljdCA6IHBhdHRlcm47CiAgICAgICAgY29uc3QgdHlwZU51bSA9IGRpY3QuZ2V0KCJQYXR0ZXJuVHlwZSIpOwogICAgICAgIGlmICh0eXBlTnVtID09PSBQYXR0ZXJuVHlwZS5USUxJTkcpIHsKICAgICAgICAgIGNvbnN0IGNvbG9yID0gY3MuYmFzZSA/IGNzLmJhc2UuZ2V0UmdiSGV4KGFyZ3MsIDApIDogbnVsbDsKICAgICAgICAgIHJldHVybiB0aGlzLmhhbmRsZVRpbGluZ1R5cGUoZm4sIGNvbG9yLCByZXNvdXJjZXMsIHBhdHRlcm4sIGRpY3QsIG9wZXJhdG9yTGlzdCwgdGFzaywgbG9jYWxUaWxpbmdQYXR0ZXJuQ2FjaGUpOwogICAgICAgIH0gZWxzZSBpZiAodHlwZU51bSA9PT0gUGF0dGVyblR5cGUuU0hBRElORykgewogICAgICAgICAgY29uc3Qgc2hhZGluZyA9IGRpY3QuZ2V0KCJTaGFkaW5nIik7CiAgICAgICAgICBjb25zdCBvYmpJZCA9IHRoaXMucGFyc2VTaGFkaW5nKHsKICAgICAgICAgICAgc2hhZGluZywKICAgICAgICAgICAgcmVzb3VyY2VzLAogICAgICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZSwKICAgICAgICAgICAgbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlCiAgICAgICAgICB9KTsKICAgICAgICAgIGlmIChvYmpJZCkgewogICAgICAgICAgICBjb25zdCBtYXRyaXggPSBsb29rdXBNYXRyaXgoZGljdC5nZXRBcnJheSgiTWF0cml4IiksIG51bGwpOwogICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoZm4sIFsiU2hhZGluZyIsIG9iaklkLCBtYXRyaXhdKTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICAgICAgfQogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgVW5rbm93biBQYXR0ZXJuVHlwZTogJHt0eXBlTnVtfWApOwogICAgICB9CiAgICB9CiAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYFVua25vd24gUGF0dGVybk5hbWU6ICR7cGF0dGVybk5hbWV9YCk7CiAgfQogIF9wYXJzZVZpc2liaWxpdHlFeHByZXNzaW9uKGFycmF5LCBuZXN0aW5nQ291bnRlciwgY3VycmVudFJlc3VsdCkgewogICAgY29uc3QgTUFYX05FU1RJTkcgPSAxMDsKICAgIGlmICgrK25lc3RpbmdDb3VudGVyID4gTUFYX05FU1RJTkcpIHsKICAgICAgd2FybigiVmlzaWJpbGl0eSBleHByZXNzaW9uIGlzIHRvbyBkZWVwbHkgbmVzdGVkIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGxlbmd0aCA9IGFycmF5Lmxlbmd0aDsKICAgIGNvbnN0IG9wZXJhdG9yID0gdGhpcy54cmVmLmZldGNoSWZSZWYoYXJyYXlbMF0pOwogICAgaWYgKGxlbmd0aCA8IDIgfHwgIShvcGVyYXRvciBpbnN0YW5jZW9mIE5hbWUpKSB7CiAgICAgIHdhcm4oIkludmFsaWQgdmlzaWJpbGl0eSBleHByZXNzaW9uIik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHN3aXRjaCAob3BlcmF0b3IubmFtZSkgewogICAgICBjYXNlICJBbmQiOgogICAgICBjYXNlICJPciI6CiAgICAgIGNhc2UgIk5vdCI6CiAgICAgICAgY3VycmVudFJlc3VsdC5wdXNoKG9wZXJhdG9yLm5hbWUpOwogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHdhcm4oYEludmFsaWQgb3BlcmF0b3IgJHtvcGVyYXRvci5uYW1lfSBpbiB2aXNpYmlsaXR5IGV4cHJlc3Npb25gKTsKICAgICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGxldCBpID0gMTsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgIGNvbnN0IHJhdyA9IGFycmF5W2ldOwogICAgICBjb25zdCBvYmplY3QgPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZihyYXcpOwogICAgICBpZiAoQXJyYXkuaXNBcnJheShvYmplY3QpKSB7CiAgICAgICAgY29uc3QgbmVzdGVkUmVzdWx0ID0gW107CiAgICAgICAgY3VycmVudFJlc3VsdC5wdXNoKG5lc3RlZFJlc3VsdCk7CiAgICAgICAgdGhpcy5fcGFyc2VWaXNpYmlsaXR5RXhwcmVzc2lvbihvYmplY3QsIG5lc3RpbmdDb3VudGVyLCBuZXN0ZWRSZXN1bHQpOwogICAgICB9IGVsc2UgaWYgKHJhdyBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIGN1cnJlbnRSZXN1bHQucHVzaChyYXcudG9TdHJpbmcoKSk7CiAgICAgIH0KICAgIH0KICB9CiAgYXN5bmMgcGFyc2VNYXJrZWRDb250ZW50UHJvcHMoY29udGVudFByb3BlcnRpZXMsIHJlc291cmNlcykgewogICAgbGV0IG9wdGlvbmFsQ29udGVudDsKICAgIGlmIChjb250ZW50UHJvcGVydGllcyBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgY29uc3QgcHJvcGVydGllcyA9IHJlc291cmNlcy5nZXQoIlByb3BlcnRpZXMiKTsKICAgICAgb3B0aW9uYWxDb250ZW50ID0gcHJvcGVydGllcy5nZXQoY29udGVudFByb3BlcnRpZXMubmFtZSk7CiAgICB9IGVsc2UgaWYgKGNvbnRlbnRQcm9wZXJ0aWVzIGluc3RhbmNlb2YgRGljdCkgewogICAgICBvcHRpb25hbENvbnRlbnQgPSBjb250ZW50UHJvcGVydGllczsKICAgIH0gZWxzZSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiT3B0aW9uYWwgY29udGVudCBwcm9wZXJ0aWVzIG1hbGZvcm1lZC4iKTsKICAgIH0KICAgIGNvbnN0IG9wdGlvbmFsQ29udGVudFR5cGUgPSBvcHRpb25hbENvbnRlbnQuZ2V0KCJUeXBlIik/Lm5hbWU7CiAgICBpZiAob3B0aW9uYWxDb250ZW50VHlwZSA9PT0gIk9DRyIpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICB0eXBlOiBvcHRpb25hbENvbnRlbnRUeXBlLAogICAgICAgIGlkOiBvcHRpb25hbENvbnRlbnQub2JqSWQKICAgICAgfTsKICAgIH0gZWxzZSBpZiAob3B0aW9uYWxDb250ZW50VHlwZSA9PT0gIk9DTUQiKSB7CiAgICAgIGNvbnN0IGV4cHJlc3Npb24gPSBvcHRpb25hbENvbnRlbnQuZ2V0KCJWRSIpOwogICAgICBpZiAoQXJyYXkuaXNBcnJheShleHByZXNzaW9uKSkgewogICAgICAgIGNvbnN0IHJlc3VsdCA9IFtdOwogICAgICAgIHRoaXMuX3BhcnNlVmlzaWJpbGl0eUV4cHJlc3Npb24oZXhwcmVzc2lvbiwgMCwgcmVzdWx0KTsKICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCA+IDApIHsKICAgICAgICAgIHJldHVybiB7CiAgICAgICAgICAgIHR5cGU6ICJPQ01EIiwKICAgICAgICAgICAgZXhwcmVzc2lvbjogcmVzdWx0CiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCBvcHRpb25hbENvbnRlbnRHcm91cHMgPSBvcHRpb25hbENvbnRlbnQuZ2V0KCJPQ0dzIik7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KG9wdGlvbmFsQ29udGVudEdyb3VwcykgfHwgb3B0aW9uYWxDb250ZW50R3JvdXBzIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgIGNvbnN0IGdyb3VwSWRzID0gW107CiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9uYWxDb250ZW50R3JvdXBzKSkgewogICAgICAgICAgZm9yIChjb25zdCBvY2cgb2Ygb3B0aW9uYWxDb250ZW50R3JvdXBzKSB7CiAgICAgICAgICAgIGdyb3VwSWRzLnB1c2gob2NnLnRvU3RyaW5nKCkpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBncm91cElkcy5wdXNoKG9wdGlvbmFsQ29udGVudEdyb3Vwcy5vYmpJZCk7CiAgICAgICAgfQogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiBvcHRpb25hbENvbnRlbnRUeXBlLAogICAgICAgICAgaWRzOiBncm91cElkcywKICAgICAgICAgIHBvbGljeTogb3B0aW9uYWxDb250ZW50LmdldCgiUCIpIGluc3RhbmNlb2YgTmFtZSA/IG9wdGlvbmFsQ29udGVudC5nZXQoIlAiKS5uYW1lIDogbnVsbCwKICAgICAgICAgIGV4cHJlc3Npb246IG51bGwKICAgICAgICB9OwogICAgICB9IGVsc2UgaWYgKG9wdGlvbmFsQ29udGVudEdyb3VwcyBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIHJldHVybiB7CiAgICAgICAgICB0eXBlOiBvcHRpb25hbENvbnRlbnRUeXBlLAogICAgICAgICAgaWQ6IG9wdGlvbmFsQ29udGVudEdyb3Vwcy50b1N0cmluZygpCiAgICAgICAgfTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIG51bGw7CiAgfQogIGdldE9wZXJhdG9yTGlzdCh7CiAgICBzdHJlYW0sCiAgICB0YXNrLAogICAgcmVzb3VyY2VzLAogICAgb3BlcmF0b3JMaXN0LAogICAgaW5pdGlhbFN0YXRlID0gbnVsbCwKICAgIGZhbGxiYWNrRm9udERpY3QgPSBudWxsLAogICAgcHJldlJlZnMgPSBudWxsCiAgfSkgewogICAgY29uc3Qgb2JqSWQgPSBzdHJlYW0uZGljdD8ub2JqSWQ7CiAgICBjb25zdCBzZWVuUmVmcyA9IG5ldyBSZWZTZXQocHJldlJlZnMpOwogICAgaWYgKG9iaklkKSB7CiAgICAgIGlmIChwcmV2UmVmcz8uaGFzKG9iaklkKSkgewogICAgICAgIHRocm93IG5ldyBFcnJvcihgZ2V0T3BlcmF0b3JMaXN0IC0gaWdub3JpbmcgY2lyY3VsYXIgcmVmZXJlbmNlOiAke29iaklkfWApOwogICAgICB9CiAgICAgIHNlZW5SZWZzLnB1dChvYmpJZCk7CiAgICB9CiAgICByZXNvdXJjZXMgfHw9IERpY3QuZW1wdHk7CiAgICBpbml0aWFsU3RhdGUgfHw9IG5ldyBFdmFsU3RhdGUoKTsKICAgIGlmICghb3BlcmF0b3JMaXN0KSB7CiAgICAgIHRocm93IG5ldyBFcnJvcignZ2V0T3BlcmF0b3JMaXN0OiBtaXNzaW5nICJvcGVyYXRvckxpc3QiIHBhcmFtZXRlcicpOwogICAgfQogICAgY29uc3Qgc2VsZiA9IHRoaXM7CiAgICBjb25zdCB4cmVmID0gdGhpcy54cmVmOwogICAgY29uc3QgbG9jYWxJbWFnZUNhY2hlID0gbmV3IExvY2FsSW1hZ2VDYWNoZSgpOwogICAgY29uc3QgbG9jYWxDb2xvclNwYWNlQ2FjaGUgPSBuZXcgTG9jYWxDb2xvclNwYWNlQ2FjaGUoKTsKICAgIGNvbnN0IGxvY2FsR1N0YXRlQ2FjaGUgPSBuZXcgTG9jYWxHU3RhdGVDYWNoZSgpOwogICAgY29uc3QgbG9jYWxUaWxpbmdQYXR0ZXJuQ2FjaGUgPSBuZXcgTG9jYWxUaWxpbmdQYXR0ZXJuQ2FjaGUoKTsKICAgIGNvbnN0IGxvY2FsU2hhZGluZ1BhdHRlcm5DYWNoZSA9IG5ldyBNYXAoKTsKICAgIGNvbnN0IHhvYmpzID0gcmVzb3VyY2VzLmdldCgiWE9iamVjdCIpIHx8IERpY3QuZW1wdHk7CiAgICBjb25zdCBwYXR0ZXJucyA9IHJlc291cmNlcy5nZXQoIlBhdHRlcm4iKSB8fCBEaWN0LmVtcHR5OwogICAgY29uc3Qgc3RhdGVNYW5hZ2VyID0gbmV3IFN0YXRlTWFuYWdlcihpbml0aWFsU3RhdGUpOwogICAgY29uc3QgcHJlcHJvY2Vzc29yID0gbmV3IEV2YWx1YXRvclByZXByb2Nlc3NvcihzdHJlYW0sIHhyZWYsIHN0YXRlTWFuYWdlcik7CiAgICBjb25zdCB0aW1lU2xvdE1hbmFnZXIgPSBuZXcgVGltZVNsb3RNYW5hZ2VyKCk7CiAgICBmdW5jdGlvbiBjbG9zZVBlbmRpbmdSZXN0b3JlT1BTKGFyZ3VtZW50KSB7CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHByZXByb2Nlc3Nvci5zYXZlZFN0YXRlc0RlcHRoOyBpIDwgaWk7IGkrKykgewogICAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChPUFMucmVzdG9yZSwgW10pOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gcHJvbWlzZUJvZHkocmVzb2x2ZSwgcmVqZWN0KSB7CiAgICAgIGNvbnN0IG5leHQgPSBmdW5jdGlvbiAocHJvbWlzZSkgewogICAgICAgIFByb21pc2UuYWxsKFtwcm9taXNlLCBvcGVyYXRvckxpc3QucmVhZHldKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIHByb21pc2VCb2R5KHJlc29sdmUsIHJlamVjdCk7CiAgICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgICByZWplY3QoZXgpOwogICAgICAgICAgfQogICAgICAgIH0sIHJlamVjdCk7CiAgICAgIH07CiAgICAgIHRhc2suZW5zdXJlTm90VGVybWluYXRlZCgpOwogICAgICB0aW1lU2xvdE1hbmFnZXIucmVzZXQoKTsKICAgICAgY29uc3Qgb3BlcmF0aW9uID0ge307CiAgICAgIGxldCBzdG9wLCBpLCBpaSwgY3MsIG5hbWUsIGlzVmFsaWROYW1lOwogICAgICB3aGlsZSAoIShzdG9wID0gdGltZVNsb3RNYW5hZ2VyLmNoZWNrKCkpKSB7CiAgICAgICAgb3BlcmF0aW9uLmFyZ3MgPSBudWxsOwogICAgICAgIGlmICghcHJlcHJvY2Vzc29yLnJlYWQob3BlcmF0aW9uKSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGxldCBhcmdzID0gb3BlcmF0aW9uLmFyZ3M7CiAgICAgICAgbGV0IGZuID0gb3BlcmF0aW9uLmZuOwogICAgICAgIHN3aXRjaCAoZm4gfCAwKSB7CiAgICAgICAgICBjYXNlIE9QUy5wYWludFhPYmplY3Q6CiAgICAgICAgICAgIGlzVmFsaWROYW1lID0gYXJnc1swXSBpbnN0YW5jZW9mIE5hbWU7CiAgICAgICAgICAgIG5hbWUgPSBhcmdzWzBdLm5hbWU7CiAgICAgICAgICAgIGlmIChpc1ZhbGlkTmFtZSkgewogICAgICAgICAgICAgIGNvbnN0IGxvY2FsSW1hZ2UgPSBsb2NhbEltYWdlQ2FjaGUuZ2V0QnlOYW1lKG5hbWUpOwogICAgICAgICAgICAgIGlmIChsb2NhbEltYWdlKSB7CiAgICAgICAgICAgICAgICBhZGRDYWNoZWRJbWFnZU9wcyhvcGVyYXRvckxpc3QsIGxvY2FsSW1hZ2UpOwogICAgICAgICAgICAgICAgYXJncyA9IG51bGw7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbmV4dChuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZVhPYmplY3QsIHJlamVjdFhPYmplY3QpIHsKICAgICAgICAgICAgICBpZiAoIWlzVmFsaWROYW1lKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlhPYmplY3QgbXVzdCBiZSByZWZlcnJlZCB0byBieSBuYW1lLiIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBsZXQgeG9iaiA9IHhvYmpzLmdldFJhdyhuYW1lKTsKICAgICAgICAgICAgICBpZiAoeG9iaiBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgICAgICAgY29uc3QgY2FjaGVkSW1hZ2UgPSBsb2NhbEltYWdlQ2FjaGUuZ2V0QnlSZWYoeG9iaikgfHwgc2VsZi5fcmVnaW9uYWxJbWFnZUNhY2hlLmdldEJ5UmVmKHhvYmopIHx8IHNlbGYuZ2xvYmFsSW1hZ2VDYWNoZS5nZXREYXRhKHhvYmosIHNlbGYucGFnZUluZGV4KTsKICAgICAgICAgICAgICAgIGlmIChjYWNoZWRJbWFnZSkgewogICAgICAgICAgICAgICAgICBhZGRDYWNoZWRJbWFnZU9wcyhvcGVyYXRvckxpc3QsIGNhY2hlZEltYWdlKTsKICAgICAgICAgICAgICAgICAgcmVzb2x2ZVhPYmplY3QoKTsKICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgeG9iaiA9IHhyZWYuZmV0Y2goeG9iaik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmICghKHhvYmogaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJYT2JqZWN0IHNob3VsZCBiZSBhIHN0cmVhbSIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCB0eXBlID0geG9iai5kaWN0LmdldCgiU3VidHlwZSIpOwogICAgICAgICAgICAgIGlmICghKHR5cGUgaW5zdGFuY2VvZiBOYW1lKSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJYT2JqZWN0IHNob3VsZCBoYXZlIGEgTmFtZSBzdWJ0eXBlIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmICh0eXBlLm5hbWUgPT09ICJGb3JtIikgewogICAgICAgICAgICAgICAgc3RhdGVNYW5hZ2VyLnNhdmUoKTsKICAgICAgICAgICAgICAgIHNlbGYuYnVpbGRGb3JtWE9iamVjdChyZXNvdXJjZXMsIHhvYmosIG51bGwsIG9wZXJhdG9yTGlzdCwgdGFzaywgc3RhdGVNYW5hZ2VyLnN0YXRlLmNsb25lKHsKICAgICAgICAgICAgICAgICAgbmV3UGF0aDogdHJ1ZQogICAgICAgICAgICAgICAgfSksIGxvY2FsQ29sb3JTcGFjZUNhY2hlLCBzZWVuUmVmcykudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgICAgICAgIHN0YXRlTWFuYWdlci5yZXN0b3JlKCk7CiAgICAgICAgICAgICAgICAgIHJlc29sdmVYT2JqZWN0KCk7CiAgICAgICAgICAgICAgICB9LCByZWplY3RYT2JqZWN0KTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUubmFtZSA9PT0gIkltYWdlIikgewogICAgICAgICAgICAgICAgc2VsZi5idWlsZFBhaW50SW1hZ2VYT2JqZWN0KHsKICAgICAgICAgICAgICAgICAgcmVzb3VyY2VzLAogICAgICAgICAgICAgICAgICBpbWFnZTogeG9iaiwKICAgICAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0LAogICAgICAgICAgICAgICAgICBjYWNoZUtleTogbmFtZSwKICAgICAgICAgICAgICAgICAgbG9jYWxJbWFnZUNhY2hlLAogICAgICAgICAgICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgICAgICAgICAgICAgfSkudGhlbihyZXNvbHZlWE9iamVjdCwgcmVqZWN0WE9iamVjdCk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlLm5hbWUgPT09ICJQUyIpIHsKICAgICAgICAgICAgICAgIGluZm8oIklnbm9yZWQgWE9iamVjdCBzdWJ0eXBlIFBTIik7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgVW5oYW5kbGVkIFhPYmplY3Qgc3VidHlwZSAke3R5cGUubmFtZX1gKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgcmVzb2x2ZVhPYmplY3QoKTsKICAgICAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbikgewogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoc2VsZi5vcHRpb25zLmlnbm9yZUVycm9ycykgewogICAgICAgICAgICAgICAgd2FybihgZ2V0T3BlcmF0b3JMaXN0IC0gaWdub3JpbmcgWE9iamVjdDogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRocm93IHJlYXNvbjsKICAgICAgICAgICAgfSkpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICBjYXNlIE9QUy5zZXRGb250OgogICAgICAgICAgICBjb25zdCBmb250U2l6ZSA9IGFyZ3NbMV07CiAgICAgICAgICAgIG5leHQoc2VsZi5oYW5kbGVTZXRGb250KHJlc291cmNlcywgYXJncywgbnVsbCwgb3BlcmF0b3JMaXN0LCB0YXNrLCBzdGF0ZU1hbmFnZXIuc3RhdGUsIGZhbGxiYWNrRm9udERpY3QpLnRoZW4oZnVuY3Rpb24gKGxvYWRlZE5hbWUpIHsKICAgICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkRGVwZW5kZW5jeShsb2FkZWROYW1lKTsKICAgICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoT1BTLnNldEZvbnQsIFtsb2FkZWROYW1lLCBmb250U2l6ZV0pOwogICAgICAgICAgICB9KSk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIGNhc2UgT1BTLmVuZElubGluZUltYWdlOgogICAgICAgICAgICBjb25zdCBjYWNoZUtleSA9IGFyZ3NbMF0uY2FjaGVLZXk7CiAgICAgICAgICAgIGlmIChjYWNoZUtleSkgewogICAgICAgICAgICAgIGNvbnN0IGxvY2FsSW1hZ2UgPSBsb2NhbEltYWdlQ2FjaGUuZ2V0QnlOYW1lKGNhY2hlS2V5KTsKICAgICAgICAgICAgICBpZiAobG9jYWxJbWFnZSkgewogICAgICAgICAgICAgICAgYWRkQ2FjaGVkSW1hZ2VPcHMob3BlcmF0b3JMaXN0LCBsb2NhbEltYWdlKTsKICAgICAgICAgICAgICAgIGFyZ3MgPSBudWxsOwogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIG5leHQoc2VsZi5idWlsZFBhaW50SW1hZ2VYT2JqZWN0KHsKICAgICAgICAgICAgICByZXNvdXJjZXMsCiAgICAgICAgICAgICAgaW1hZ2U6IGFyZ3NbMF0sCiAgICAgICAgICAgICAgaXNJbmxpbmU6IHRydWUsCiAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0LAogICAgICAgICAgICAgIGNhY2hlS2V5LAogICAgICAgICAgICAgIGxvY2FsSW1hZ2VDYWNoZSwKICAgICAgICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZQogICAgICAgICAgICB9KSk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIGNhc2UgT1BTLnNob3dUZXh0OgogICAgICAgICAgICBpZiAoIXN0YXRlTWFuYWdlci5zdGF0ZS5mb250KSB7CiAgICAgICAgICAgICAgc2VsZi5lbnN1cmVTdGF0ZUZvbnQoc3RhdGVNYW5hZ2VyLnN0YXRlKTsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBhcmdzWzBdID0gc2VsZi5oYW5kbGVUZXh0KGFyZ3NbMF0sIHN0YXRlTWFuYWdlci5zdGF0ZSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2hvd1NwYWNlZFRleHQ6CiAgICAgICAgICAgIGlmICghc3RhdGVNYW5hZ2VyLnN0YXRlLmZvbnQpIHsKICAgICAgICAgICAgICBzZWxmLmVuc3VyZVN0YXRlRm9udChzdGF0ZU1hbmFnZXIuc3RhdGUpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGNvbWJpbmVkR2x5cGhzID0gW10sCiAgICAgICAgICAgICAgc3RhdGUgPSBzdGF0ZU1hbmFnZXIuc3RhdGU7CiAgICAgICAgICAgIGZvciAoY29uc3QgYXJySXRlbSBvZiBhcmdzWzBdKSB7CiAgICAgICAgICAgICAgaWYgKHR5cGVvZiBhcnJJdGVtID09PSAic3RyaW5nIikgewogICAgICAgICAgICAgICAgY29tYmluZWRHbHlwaHMucHVzaCguLi5zZWxmLmhhbmRsZVRleHQoYXJySXRlbSwgc3RhdGUpKTsKICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBhcnJJdGVtID09PSAibnVtYmVyIikgewogICAgICAgICAgICAgICAgY29tYmluZWRHbHlwaHMucHVzaChhcnJJdGVtKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYXJnc1swXSA9IGNvbWJpbmVkR2x5cGhzOwogICAgICAgICAgICBmbiA9IE9QUy5zaG93VGV4dDsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5uZXh0TGluZVNob3dUZXh0OgogICAgICAgICAgICBpZiAoIXN0YXRlTWFuYWdlci5zdGF0ZS5mb250KSB7CiAgICAgICAgICAgICAgc2VsZi5lbnN1cmVTdGF0ZUZvbnQoc3RhdGVNYW5hZ2VyLnN0YXRlKTsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoT1BTLm5leHRMaW5lKTsKICAgICAgICAgICAgYXJnc1swXSA9IHNlbGYuaGFuZGxlVGV4dChhcmdzWzBdLCBzdGF0ZU1hbmFnZXIuc3RhdGUpOwogICAgICAgICAgICBmbiA9IE9QUy5zaG93VGV4dDsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5uZXh0TGluZVNldFNwYWNpbmdTaG93VGV4dDoKICAgICAgICAgICAgaWYgKCFzdGF0ZU1hbmFnZXIuc3RhdGUuZm9udCkgewogICAgICAgICAgICAgIHNlbGYuZW5zdXJlU3RhdGVGb250KHN0YXRlTWFuYWdlci5zdGF0ZSk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5uZXh0TGluZSk7CiAgICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChPUFMuc2V0V29yZFNwYWNpbmcsIFthcmdzLnNoaWZ0KCldKTsKICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5zZXRDaGFyU3BhY2luZywgW2FyZ3Muc2hpZnQoKV0pOwogICAgICAgICAgICBhcmdzWzBdID0gc2VsZi5oYW5kbGVUZXh0KGFyZ3NbMF0sIHN0YXRlTWFuYWdlci5zdGF0ZSk7CiAgICAgICAgICAgIGZuID0gT1BTLnNob3dUZXh0OwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldFRleHRSZW5kZXJpbmdNb2RlOgogICAgICAgICAgICBzdGF0ZU1hbmFnZXIuc3RhdGUudGV4dFJlbmRlcmluZ01vZGUgPSBhcmdzWzBdOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldEZpbGxDb2xvclNwYWNlOgogICAgICAgICAgICB7CiAgICAgICAgICAgICAgY29uc3QgZmlsbENTID0gc2VsZi5fZ2V0Q29sb3JTcGFjZShhcmdzWzBdLCByZXNvdXJjZXMsIGxvY2FsQ29sb3JTcGFjZUNhY2hlKTsKICAgICAgICAgICAgICBpZiAoZmlsbENTIGluc3RhbmNlb2YgQ29sb3JTcGFjZSkgewogICAgICAgICAgICAgICAgc3RhdGVNYW5hZ2VyLnN0YXRlLmZpbGxDb2xvclNwYWNlID0gZmlsbENTOwogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIG5leHQoc2VsZi5faGFuZGxlQ29sb3JTcGFjZShmaWxsQ1MpLnRoZW4oY29sb3JTcGFjZSA9PiB7CiAgICAgICAgICAgICAgICBzdGF0ZU1hbmFnZXIuc3RhdGUuZmlsbENvbG9yU3BhY2UgPSBjb2xvclNwYWNlIHx8IENvbG9yU3BhY2VVdGlscy5ncmF5OwogICAgICAgICAgICAgIH0pKTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgIGNhc2UgT1BTLnNldFN0cm9rZUNvbG9yU3BhY2U6CiAgICAgICAgICAgIHsKICAgICAgICAgICAgICBjb25zdCBzdHJva2VDUyA9IHNlbGYuX2dldENvbG9yU3BhY2UoYXJnc1swXSwgcmVzb3VyY2VzLCBsb2NhbENvbG9yU3BhY2VDYWNoZSk7CiAgICAgICAgICAgICAgaWYgKHN0cm9rZUNTIGluc3RhbmNlb2YgQ29sb3JTcGFjZSkgewogICAgICAgICAgICAgICAgc3RhdGVNYW5hZ2VyLnN0YXRlLnN0cm9rZUNvbG9yU3BhY2UgPSBzdHJva2VDUzsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBuZXh0KHNlbGYuX2hhbmRsZUNvbG9yU3BhY2Uoc3Ryb2tlQ1MpLnRoZW4oY29sb3JTcGFjZSA9PiB7CiAgICAgICAgICAgICAgICBzdGF0ZU1hbmFnZXIuc3RhdGUuc3Ryb2tlQ29sb3JTcGFjZSA9IGNvbG9yU3BhY2UgfHwgQ29sb3JTcGFjZVV0aWxzLmdyYXk7CiAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgY2FzZSBPUFMuc2V0RmlsbENvbG9yOgogICAgICAgICAgICBjcyA9IHN0YXRlTWFuYWdlci5zdGF0ZS5maWxsQ29sb3JTcGFjZTsKICAgICAgICAgICAgYXJncyA9IFtjcy5nZXRSZ2JIZXgoYXJncywgMCldOwogICAgICAgICAgICBmbiA9IE9QUy5zZXRGaWxsUkdCQ29sb3I7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0U3Ryb2tlQ29sb3I6CiAgICAgICAgICAgIGNzID0gc3RhdGVNYW5hZ2VyLnN0YXRlLnN0cm9rZUNvbG9yU3BhY2U7CiAgICAgICAgICAgIGFyZ3MgPSBbY3MuZ2V0UmdiSGV4KGFyZ3MsIDApXTsKICAgICAgICAgICAgZm4gPSBPUFMuc2V0U3Ryb2tlUkdCQ29sb3I7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0RmlsbEdyYXk6CiAgICAgICAgICAgIHN0YXRlTWFuYWdlci5zdGF0ZS5maWxsQ29sb3JTcGFjZSA9IENvbG9yU3BhY2VVdGlscy5ncmF5OwogICAgICAgICAgICBhcmdzID0gW0NvbG9yU3BhY2VVdGlscy5ncmF5LmdldFJnYkhleChhcmdzLCAwKV07CiAgICAgICAgICAgIGZuID0gT1BTLnNldEZpbGxSR0JDb2xvcjsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRTdHJva2VHcmF5OgogICAgICAgICAgICBzdGF0ZU1hbmFnZXIuc3RhdGUuc3Ryb2tlQ29sb3JTcGFjZSA9IENvbG9yU3BhY2VVdGlscy5ncmF5OwogICAgICAgICAgICBhcmdzID0gW0NvbG9yU3BhY2VVdGlscy5ncmF5LmdldFJnYkhleChhcmdzLCAwKV07CiAgICAgICAgICAgIGZuID0gT1BTLnNldFN0cm9rZVJHQkNvbG9yOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldEZpbGxDTVlLQ29sb3I6CiAgICAgICAgICAgIHN0YXRlTWFuYWdlci5zdGF0ZS5maWxsQ29sb3JTcGFjZSA9IENvbG9yU3BhY2VVdGlscy5jbXlrOwogICAgICAgICAgICBhcmdzID0gW0NvbG9yU3BhY2VVdGlscy5jbXlrLmdldFJnYkhleChhcmdzLCAwKV07CiAgICAgICAgICAgIGZuID0gT1BTLnNldEZpbGxSR0JDb2xvcjsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRTdHJva2VDTVlLQ29sb3I6CiAgICAgICAgICAgIHN0YXRlTWFuYWdlci5zdGF0ZS5zdHJva2VDb2xvclNwYWNlID0gQ29sb3JTcGFjZVV0aWxzLmNteWs7CiAgICAgICAgICAgIGFyZ3MgPSBbQ29sb3JTcGFjZVV0aWxzLmNteWsuZ2V0UmdiSGV4KGFyZ3MsIDApXTsKICAgICAgICAgICAgZm4gPSBPUFMuc2V0U3Ryb2tlUkdCQ29sb3I7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0RmlsbFJHQkNvbG9yOgogICAgICAgICAgICBzdGF0ZU1hbmFnZXIuc3RhdGUuZmlsbENvbG9yU3BhY2UgPSBDb2xvclNwYWNlVXRpbHMucmdiOwogICAgICAgICAgICBhcmdzID0gW0NvbG9yU3BhY2VVdGlscy5yZ2IuZ2V0UmdiSGV4KGFyZ3MsIDApXTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRTdHJva2VSR0JDb2xvcjoKICAgICAgICAgICAgc3RhdGVNYW5hZ2VyLnN0YXRlLnN0cm9rZUNvbG9yU3BhY2UgPSBDb2xvclNwYWNlVXRpbHMucmdiOwogICAgICAgICAgICBhcmdzID0gW0NvbG9yU3BhY2VVdGlscy5yZ2IuZ2V0UmdiSGV4KGFyZ3MsIDApXTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRGaWxsQ29sb3JOOgogICAgICAgICAgICBjcyA9IHN0YXRlTWFuYWdlci5zdGF0ZS5wYXR0ZXJuRmlsbENvbG9yU3BhY2U7CiAgICAgICAgICAgIGlmICghY3MpIHsKICAgICAgICAgICAgICBpZiAoaXNOdW1iZXJBcnJheShhcmdzLCBudWxsKSkgewogICAgICAgICAgICAgICAgYXJncyA9IFtDb2xvclNwYWNlVXRpbHMuZ3JheS5nZXRSZ2JIZXgoYXJncywgMCldOwogICAgICAgICAgICAgICAgZm4gPSBPUFMuc2V0RmlsbFJHQkNvbG9yOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGFyZ3MgPSBbXTsKICAgICAgICAgICAgICBmbiA9IE9QUy5zZXRGaWxsVHJhbnNwYXJlbnQ7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGNzLm5hbWUgPT09ICJQYXR0ZXJuIikgewogICAgICAgICAgICAgIG5leHQoc2VsZi5oYW5kbGVDb2xvck4ob3BlcmF0b3JMaXN0LCBPUFMuc2V0RmlsbENvbG9yTiwgYXJncywgY3MsIHBhdHRlcm5zLCByZXNvdXJjZXMsIHRhc2ssIGxvY2FsQ29sb3JTcGFjZUNhY2hlLCBsb2NhbFRpbGluZ1BhdHRlcm5DYWNoZSwgbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlKSk7CiAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGFyZ3MgPSBbY3MuZ2V0UmdiSGV4KGFyZ3MsIDApXTsKICAgICAgICAgICAgZm4gPSBPUFMuc2V0RmlsbFJHQkNvbG9yOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldFN0cm9rZUNvbG9yTjoKICAgICAgICAgICAgY3MgPSBzdGF0ZU1hbmFnZXIuc3RhdGUucGF0dGVyblN0cm9rZUNvbG9yU3BhY2U7CiAgICAgICAgICAgIGlmICghY3MpIHsKICAgICAgICAgICAgICBpZiAoaXNOdW1iZXJBcnJheShhcmdzLCBudWxsKSkgewogICAgICAgICAgICAgICAgYXJncyA9IFtDb2xvclNwYWNlVXRpbHMuZ3JheS5nZXRSZ2JIZXgoYXJncywgMCldOwogICAgICAgICAgICAgICAgZm4gPSBPUFMuc2V0U3Ryb2tlUkdCQ29sb3I7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYXJncyA9IFtdOwogICAgICAgICAgICAgIGZuID0gT1BTLnNldFN0cm9rZVRyYW5zcGFyZW50OwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChjcy5uYW1lID09PSAiUGF0dGVybiIpIHsKICAgICAgICAgICAgICBuZXh0KHNlbGYuaGFuZGxlQ29sb3JOKG9wZXJhdG9yTGlzdCwgT1BTLnNldFN0cm9rZUNvbG9yTiwgYXJncywgY3MsIHBhdHRlcm5zLCByZXNvdXJjZXMsIHRhc2ssIGxvY2FsQ29sb3JTcGFjZUNhY2hlLCBsb2NhbFRpbGluZ1BhdHRlcm5DYWNoZSwgbG9jYWxTaGFkaW5nUGF0dGVybkNhY2hlKSk7CiAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGFyZ3MgPSBbY3MuZ2V0UmdiSGV4KGFyZ3MsIDApXTsKICAgICAgICAgICAgZm4gPSBPUFMuc2V0U3Ryb2tlUkdCQ29sb3I7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2hhZGluZ0ZpbGw6CiAgICAgICAgICAgIGxldCBzaGFkaW5nOwogICAgICAgICAgICB0cnkgewogICAgICAgICAgICAgIGNvbnN0IHNoYWRpbmdSZXMgPSByZXNvdXJjZXMuZ2V0KCJTaGFkaW5nIik7CiAgICAgICAgICAgICAgaWYgKCFzaGFkaW5nUmVzKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIk5vIHNoYWRpbmcgcmVzb3VyY2UgZm91bmQiKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgc2hhZGluZyA9IHNoYWRpbmdSZXMuZ2V0KGFyZ3NbMF0ubmFtZSk7CiAgICAgICAgICAgICAgaWYgKCFzaGFkaW5nKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIk5vIHNoYWRpbmcgb2JqZWN0IGZvdW5kIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGNhdGNoIChyZWFzb24pIHsKICAgICAgICAgICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgQWJvcnRFeGNlcHRpb24pIHsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoc2VsZi5vcHRpb25zLmlnbm9yZUVycm9ycykgewogICAgICAgICAgICAgICAgd2FybihgZ2V0T3BlcmF0b3JMaXN0IC0gaWdub3JpbmcgU2hhZGluZzogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdGhyb3cgcmVhc29uOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IHBhdHRlcm5JZCA9IHNlbGYucGFyc2VTaGFkaW5nKHsKICAgICAgICAgICAgICBzaGFkaW5nLAogICAgICAgICAgICAgIHJlc291cmNlcywKICAgICAgICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZSwKICAgICAgICAgICAgICBsb2NhbFNoYWRpbmdQYXR0ZXJuQ2FjaGUKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGlmICghcGF0dGVybklkKSB7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYXJncyA9IFtwYXR0ZXJuSWRdOwogICAgICAgICAgICBmbiA9IE9QUy5zaGFkaW5nRmlsbDsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRHU3RhdGU6CiAgICAgICAgICAgIGlzVmFsaWROYW1lID0gYXJnc1swXSBpbnN0YW5jZW9mIE5hbWU7CiAgICAgICAgICAgIG5hbWUgPSBhcmdzWzBdLm5hbWU7CiAgICAgICAgICAgIGlmIChpc1ZhbGlkTmFtZSkgewogICAgICAgICAgICAgIGNvbnN0IGxvY2FsR1N0YXRlT2JqID0gbG9jYWxHU3RhdGVDYWNoZS5nZXRCeU5hbWUobmFtZSk7CiAgICAgICAgICAgICAgaWYgKGxvY2FsR1N0YXRlT2JqKSB7CiAgICAgICAgICAgICAgICBpZiAobG9jYWxHU3RhdGVPYmoubGVuZ3RoID4gMCkgewogICAgICAgICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoT1BTLnNldEdTdGF0ZSwgW2xvY2FsR1N0YXRlT2JqXSk7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBhcmdzID0gbnVsbDsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBuZXh0KG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlR1N0YXRlLCByZWplY3RHU3RhdGUpIHsKICAgICAgICAgICAgICBpZiAoIWlzVmFsaWROYW1lKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkdTdGF0ZSBtdXN0IGJlIHJlZmVycmVkIHRvIGJ5IG5hbWUuIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGNvbnN0IGV4dEdTdGF0ZSA9IHJlc291cmNlcy5nZXQoIkV4dEdTdGF0ZSIpOwogICAgICAgICAgICAgIGlmICghKGV4dEdTdGF0ZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkV4dEdTdGF0ZSBzaG91bGQgYmUgYSBkaWN0aW9uYXJ5LiIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCBnU3RhdGUgPSBleHRHU3RhdGUuZ2V0KG5hbWUpOwogICAgICAgICAgICAgIGlmICghKGdTdGF0ZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkdTdGF0ZSBzaG91bGQgYmUgYSBkaWN0aW9uYXJ5LiIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBzZWxmLnNldEdTdGF0ZSh7CiAgICAgICAgICAgICAgICByZXNvdXJjZXMsCiAgICAgICAgICAgICAgICBnU3RhdGUsCiAgICAgICAgICAgICAgICBvcGVyYXRvckxpc3QsCiAgICAgICAgICAgICAgICBjYWNoZUtleTogbmFtZSwKICAgICAgICAgICAgICAgIHRhc2ssCiAgICAgICAgICAgICAgICBzdGF0ZU1hbmFnZXIsCiAgICAgICAgICAgICAgICBsb2NhbEdTdGF0ZUNhY2hlLAogICAgICAgICAgICAgICAgbG9jYWxDb2xvclNwYWNlQ2FjaGUsCiAgICAgICAgICAgICAgICBzZWVuUmVmcwogICAgICAgICAgICAgIH0pLnRoZW4ocmVzb2x2ZUdTdGF0ZSwgcmVqZWN0R1N0YXRlKTsKICAgICAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbikgewogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoc2VsZi5vcHRpb25zLmlnbm9yZUVycm9ycykgewogICAgICAgICAgICAgICAgd2FybihgZ2V0T3BlcmF0b3JMaXN0IC0gaWdub3JpbmcgRXh0R1N0YXRlOiAiJHtyZWFzb259Ii5gKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdGhyb3cgcmVhc29uOwogICAgICAgICAgICB9KSk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIGNhc2UgT1BTLnNldExpbmVXaWR0aDoKICAgICAgICAgICAgewogICAgICAgICAgICAgIGNvbnN0IFt0aGlja25lc3NdID0gYXJnczsKICAgICAgICAgICAgICBpZiAodHlwZW9mIHRoaWNrbmVzcyAhPT0gIm51bWJlciIpIHsKICAgICAgICAgICAgICAgIHdhcm4oYEludmFsaWQgc2V0TGluZVdpZHRoOiAke3RoaWNrbmVzc31gKTsKICAgICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBhcmdzWzBdID0gTWF0aC5hYnModGhpY2tuZXNzKTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgY2FzZSBPUFMuc2V0RGFzaDoKICAgICAgICAgICAgewogICAgICAgICAgICAgIGNvbnN0IGRhc2hQaGFzZSA9IGFyZ3NbMV07CiAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXNoUGhhc2UgIT09ICJudW1iZXIiKSB7CiAgICAgICAgICAgICAgICB3YXJuKGBJbnZhbGlkIHNldERhc2g6ICR7ZGFzaFBoYXNlfWApOwogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGNvbnN0IGRhc2hBcnJheSA9IGFyZ3NbMF07CiAgICAgICAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGRhc2hBcnJheSkpIHsKICAgICAgICAgICAgICAgIHdhcm4oYEludmFsaWQgc2V0RGFzaDogJHtkYXNoQXJyYXl9YCk7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKGRhc2hBcnJheS5zb21lKHggPT4gdHlwZW9mIHggIT09ICJudW1iZXIiKSkgewogICAgICAgICAgICAgICAgYXJnc1swXSA9IGRhc2hBcnJheS5maWx0ZXIoeCA9PiB0eXBlb2YgeCA9PT0gIm51bWJlciIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgY2FzZSBPUFMubW92ZVRvOgogICAgICAgICAgY2FzZSBPUFMubGluZVRvOgogICAgICAgICAgY2FzZSBPUFMuY3VydmVUbzoKICAgICAgICAgIGNhc2UgT1BTLmN1cnZlVG8yOgogICAgICAgICAgY2FzZSBPUFMuY3VydmVUbzM6CiAgICAgICAgICBjYXNlIE9QUy5jbG9zZVBhdGg6CiAgICAgICAgICBjYXNlIE9QUy5yZWN0YW5nbGU6CiAgICAgICAgICAgIHNlbGYuYnVpbGRQYXRoKGZuLCBhcmdzLCBzdGF0ZU1hbmFnZXIuc3RhdGUpOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIGNhc2UgT1BTLnN0cm9rZToKICAgICAgICAgIGNhc2UgT1BTLmNsb3NlU3Ryb2tlOgogICAgICAgICAgY2FzZSBPUFMuZmlsbDoKICAgICAgICAgIGNhc2UgT1BTLmVvRmlsbDoKICAgICAgICAgIGNhc2UgT1BTLmZpbGxTdHJva2U6CiAgICAgICAgICBjYXNlIE9QUy5lb0ZpbGxTdHJva2U6CiAgICAgICAgICBjYXNlIE9QUy5jbG9zZUZpbGxTdHJva2U6CiAgICAgICAgICBjYXNlIE9QUy5jbG9zZUVPRmlsbFN0cm9rZToKICAgICAgICAgIGNhc2UgT1BTLmVuZFBhdGg6CiAgICAgICAgICAgIHsKICAgICAgICAgICAgICBjb25zdCB7CiAgICAgICAgICAgICAgICBzdGF0ZTogewogICAgICAgICAgICAgICAgICBwYXRoQnVmZmVyLAogICAgICAgICAgICAgICAgICBwYXRoTWluTWF4CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgfSA9IHN0YXRlTWFuYWdlcjsKICAgICAgICAgICAgICBpZiAoZm4gPT09IE9QUy5jbG9zZVN0cm9rZSB8fCBmbiA9PT0gT1BTLmNsb3NlRmlsbFN0cm9rZSB8fCBmbiA9PT0gT1BTLmNsb3NlRU9GaWxsU3Ryb2tlKSB7CiAgICAgICAgICAgICAgICBwYXRoQnVmZmVyLnB1c2goRHJhd09QUy5jbG9zZVBhdGgpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAocGF0aEJ1ZmZlci5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChPUFMuY29uc3RydWN0UGF0aCwgW2ZuLCBbbnVsbF0sIG51bGxdKTsKICAgICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKE9QUy5jb25zdHJ1Y3RQYXRoLCBbZm4sIFtuZXcgRmxvYXQzMkFycmF5KHBhdGhCdWZmZXIpXSwgcGF0aE1pbk1heC5zbGljZSgpXSk7CiAgICAgICAgICAgICAgICBwYXRoQnVmZmVyLmxlbmd0aCA9IDA7CiAgICAgICAgICAgICAgICBwYXRoTWluTWF4LnNldChbSW5maW5pdHksIEluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV0sIDApOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgY2FzZSBPUFMuc2V0VGV4dE1hdHJpeDoKICAgICAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKGZuLCBbbmV3IEZsb2F0MzJBcnJheShhcmdzKV0pOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIGNhc2UgT1BTLm1hcmtQb2ludDoKICAgICAgICAgIGNhc2UgT1BTLm1hcmtQb2ludFByb3BzOgogICAgICAgICAgY2FzZSBPUFMuYmVnaW5Db21wYXQ6CiAgICAgICAgICBjYXNlIE9QUy5lbmRDb21wYXQ6CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgY2FzZSBPUFMuYmVnaW5NYXJrZWRDb250ZW50UHJvcHM6CiAgICAgICAgICAgIGlmICghKGFyZ3NbMF0gaW5zdGFuY2VvZiBOYW1lKSkgewogICAgICAgICAgICAgIHdhcm4oYEV4cGVjdGVkIG5hbWUgZm9yIGJlZ2luTWFya2VkQ29udGVudFByb3BzIGFyZzA9JHthcmdzWzBdfWApOwogICAgICAgICAgICAgIG9wZXJhdG9yTGlzdC5hZGRPcChPUFMuYmVnaW5NYXJrZWRDb250ZW50UHJvcHMsIFsiT0MiLCBudWxsXSk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGFyZ3NbMF0ubmFtZSA9PT0gIk9DIikgewogICAgICAgICAgICAgIG5leHQoc2VsZi5wYXJzZU1hcmtlZENvbnRlbnRQcm9wcyhhcmdzWzFdLCByZXNvdXJjZXMpLnRoZW4oZGF0YSA9PiB7CiAgICAgICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoT1BTLmJlZ2luTWFya2VkQ29udGVudFByb3BzLCBbIk9DIiwgZGF0YV0pOwogICAgICAgICAgICAgIH0pLmNhdGNoKHJlYXNvbiA9PiB7CiAgICAgICAgICAgICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgQWJvcnRFeGNlcHRpb24pIHsKICAgICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgaWYgKHNlbGYub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAgICAgICAgICAgd2FybihgZ2V0T3BlcmF0b3JMaXN0IC0gaWdub3JpbmcgYmVnaW5NYXJrZWRDb250ZW50UHJvcHM6ICIke3JlYXNvbn0iLmApOwogICAgICAgICAgICAgICAgICBvcGVyYXRvckxpc3QuYWRkT3AoT1BTLmJlZ2luTWFya2VkQ29udGVudFByb3BzLCBbIk9DIiwgbnVsbF0pOwogICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB0aHJvdyByZWFzb247CiAgICAgICAgICAgICAgfSkpOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBhcmdzID0gW2FyZ3NbMF0ubmFtZSwgYXJnc1sxXSBpbnN0YW5jZW9mIERpY3QgPyBhcmdzWzFdLmdldCgiTUNJRCIpIDogbnVsbF07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuYmVnaW5NYXJrZWRDb250ZW50OgogICAgICAgICAgY2FzZSBPUFMuZW5kTWFya2VkQ29udGVudDoKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIGlmIChhcmdzICE9PSBudWxsKSB7CiAgICAgICAgICAgICAgZm9yIChpID0gMCwgaWkgPSBhcmdzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgICAgICAgIGlmIChhcmdzW2ldIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgaWYgKGkgPCBpaSkgewogICAgICAgICAgICAgICAgd2FybigiZ2V0T3BlcmF0b3JMaXN0IC0gaWdub3Jpbmcgb3BlcmF0b3I6ICIgKyBmbik7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgb3BlcmF0b3JMaXN0LmFkZE9wKGZuLCBhcmdzKTsKICAgICAgfQogICAgICBpZiAoc3RvcCkgewogICAgICAgIG5leHQoZGVmZXJyZWQpOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBjbG9zZVBlbmRpbmdSZXN0b3JlT1BTKCk7CiAgICAgIHJlc29sdmUoKTsKICAgIH0pLmNhdGNoKHJlYXNvbiA9PiB7CiAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbikgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBpZiAodGhpcy5vcHRpb25zLmlnbm9yZUVycm9ycykgewogICAgICAgIHdhcm4oYGdldE9wZXJhdG9yTGlzdCAtIGlnbm9yaW5nIGVycm9ycyBkdXJpbmcgIiR7dGFzay5uYW1lfSIgYCArIGB0YXNrOiAiJHtyZWFzb259Ii5gKTsKICAgICAgICBjbG9zZVBlbmRpbmdSZXN0b3JlT1BTKCk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIHRocm93IHJlYXNvbjsKICAgIH0pOwogIH0KICBnZXRUZXh0Q29udGVudCh7CiAgICBzdHJlYW0sCiAgICB0YXNrLAogICAgcmVzb3VyY2VzLAogICAgc3RhdGVNYW5hZ2VyID0gbnVsbCwKICAgIGluY2x1ZGVNYXJrZWRDb250ZW50ID0gZmFsc2UsCiAgICBzaW5rLAogICAgc2VlblN0eWxlcyA9IG5ldyBTZXQoKSwKICAgIHZpZXdCb3gsCiAgICBsYW5nID0gbnVsbCwKICAgIG1hcmtlZENvbnRlbnREYXRhID0gbnVsbCwKICAgIGRpc2FibGVOb3JtYWxpemF0aW9uID0gZmFsc2UsCiAgICBrZWVwV2hpdGVTcGFjZSA9IGZhbHNlLAogICAgcHJldlJlZnMgPSBudWxsLAogICAgaW50ZXJzZWN0b3IgPSBudWxsCiAgfSkgewogICAgY29uc3Qgb2JqSWQgPSBzdHJlYW0uZGljdD8ub2JqSWQ7CiAgICBjb25zdCBzZWVuUmVmcyA9IG5ldyBSZWZTZXQocHJldlJlZnMpOwogICAgaWYgKG9iaklkKSB7CiAgICAgIGlmIChwcmV2UmVmcz8uaGFzKG9iaklkKSkgewogICAgICAgIHRocm93IG5ldyBFcnJvcihgZ2V0VGV4dENvbnRlbnQgLSBpZ25vcmluZyBjaXJjdWxhciByZWZlcmVuY2U6ICR7b2JqSWR9YCk7CiAgICAgIH0KICAgICAgc2VlblJlZnMucHV0KG9iaklkKTsKICAgIH0KICAgIHJlc291cmNlcyB8fD0gRGljdC5lbXB0eTsKICAgIHN0YXRlTWFuYWdlciB8fD0gbmV3IFN0YXRlTWFuYWdlcihuZXcgVGV4dFN0YXRlKCkpOwogICAgaWYgKGluY2x1ZGVNYXJrZWRDb250ZW50KSB7CiAgICAgIG1hcmtlZENvbnRlbnREYXRhIHx8PSB7CiAgICAgICAgbGV2ZWw6IDAKICAgICAgfTsKICAgIH0KICAgIGNvbnN0IHRleHRDb250ZW50ID0gewogICAgICBpdGVtczogW10sCiAgICAgIHN0eWxlczogT2JqZWN0LmNyZWF0ZShudWxsKSwKICAgICAgbGFuZwogICAgfTsKICAgIGNvbnN0IHRleHRDb250ZW50SXRlbSA9IHsKICAgICAgaW5pdGlhbGl6ZWQ6IGZhbHNlLAogICAgICBzdHI6IFtdLAogICAgICB0b3RhbFdpZHRoOiAwLAogICAgICB0b3RhbEhlaWdodDogMCwKICAgICAgd2lkdGg6IDAsCiAgICAgIGhlaWdodDogMCwKICAgICAgdmVydGljYWw6IGZhbHNlLAogICAgICBwcmV2VHJhbnNmb3JtOiBudWxsLAogICAgICB0ZXh0QWR2YW5jZVNjYWxlOiAwLAogICAgICBzcGFjZUluRmxvd01pbjogMCwKICAgICAgc3BhY2VJbkZsb3dNYXg6IDAsCiAgICAgIHRyYWNraW5nU3BhY2VNaW46IEluZmluaXR5LAogICAgICBuZWdhdGl2ZVNwYWNlTWF4OiAtSW5maW5pdHksCiAgICAgIG5vdEFTcGFjZTogLUluZmluaXR5LAogICAgICB0cmFuc2Zvcm06IG51bGwsCiAgICAgIGZvbnROYW1lOiBudWxsLAogICAgICBoYXNFT0w6IGZhbHNlCiAgICB9OwogICAgY29uc3QgdHdvTGFzdENoYXJzID0gWyIgIiwgIiAiXTsKICAgIGxldCB0d29MYXN0Q2hhcnNQb3MgPSAwOwogICAgZnVuY3Rpb24gc2F2ZUxhc3RDaGFyKGNoYXIpIHsKICAgICAgY29uc3QgbmV4dFBvcyA9ICh0d29MYXN0Q2hhcnNQb3MgKyAxKSAlIDI7CiAgICAgIGNvbnN0IHJldCA9IHR3b0xhc3RDaGFyc1t0d29MYXN0Q2hhcnNQb3NdICE9PSAiICIgJiYgdHdvTGFzdENoYXJzW25leHRQb3NdID09PSAiICI7CiAgICAgIHR3b0xhc3RDaGFyc1t0d29MYXN0Q2hhcnNQb3NdID0gY2hhcjsKICAgICAgdHdvTGFzdENoYXJzUG9zID0gbmV4dFBvczsKICAgICAgcmV0dXJuICFrZWVwV2hpdGVTcGFjZSAmJiByZXQ7CiAgICB9CiAgICBmdW5jdGlvbiBzaG91bGRBZGRXaGl0ZXBzYWNlKCkgewogICAgICByZXR1cm4gIWtlZXBXaGl0ZVNwYWNlICYmIHR3b0xhc3RDaGFyc1t0d29MYXN0Q2hhcnNQb3NdICE9PSAiICIgJiYgdHdvTGFzdENoYXJzWyh0d29MYXN0Q2hhcnNQb3MgKyAxKSAlIDJdID09PSAiICI7CiAgICB9CiAgICBmdW5jdGlvbiByZXNldExhc3RDaGFycygpIHsKICAgICAgdHdvTGFzdENoYXJzWzBdID0gdHdvTGFzdENoYXJzWzFdID0gIiAiOwogICAgICB0d29MYXN0Q2hhcnNQb3MgPSAwOwogICAgfQogICAgY29uc3QgVFJBQ0tJTkdfU1BBQ0VfRkFDVE9SID0gMC4xMDI7CiAgICBjb25zdCBOT1RfQV9TUEFDRV9GQUNUT1IgPSAwLjAzOwogICAgY29uc3QgTkVHQVRJVkVfU1BBQ0VfRkFDVE9SID0gLTAuMjsKICAgIGNvbnN0IFNQQUNFX0lOX0ZMT1dfTUlOX0ZBQ1RPUiA9IDAuMTAyOwogICAgY29uc3QgU1BBQ0VfSU5fRkxPV19NQVhfRkFDVE9SID0gMC42OwogICAgY29uc3QgVkVSVElDQUxfU0hJRlRfUkFUSU8gPSAwLjI1OwogICAgY29uc3Qgc2VsZiA9IHRoaXM7CiAgICBjb25zdCB4cmVmID0gdGhpcy54cmVmOwogICAgY29uc3Qgc2hvd1NwYWNlZFRleHRCdWZmZXIgPSBbXTsKICAgIGxldCB4b2JqcyA9IG51bGw7CiAgICBjb25zdCBlbXB0eVhPYmplY3RDYWNoZSA9IG5ldyBMb2NhbEltYWdlQ2FjaGUoKTsKICAgIGNvbnN0IGVtcHR5R1N0YXRlQ2FjaGUgPSBuZXcgTG9jYWxHU3RhdGVDYWNoZSgpOwogICAgY29uc3QgcHJlcHJvY2Vzc29yID0gbmV3IEV2YWx1YXRvclByZXByb2Nlc3NvcihzdHJlYW0sIHhyZWYsIHN0YXRlTWFuYWdlcik7CiAgICBsZXQgdGV4dFN0YXRlOwogICAgZnVuY3Rpb24gcHVzaFdoaXRlc3BhY2UoewogICAgICB3aWR0aCA9IDAsCiAgICAgIGhlaWdodCA9IDAsCiAgICAgIHRyYW5zZm9ybSA9IHRleHRDb250ZW50SXRlbS5wcmV2VHJhbnNmb3JtLAogICAgICBmb250TmFtZSA9IHRleHRDb250ZW50SXRlbS5mb250TmFtZQogICAgfSkgewogICAgICBpbnRlcnNlY3Rvcj8uYWRkRXh0cmFDaGFyKCIgIik7CiAgICAgIHRleHRDb250ZW50Lml0ZW1zLnB1c2goewogICAgICAgIHN0cjogIiAiLAogICAgICAgIGRpcjogImx0ciIsCiAgICAgICAgd2lkdGgsCiAgICAgICAgaGVpZ2h0LAogICAgICAgIHRyYW5zZm9ybSwKICAgICAgICBmb250TmFtZSwKICAgICAgICBoYXNFT0w6IGZhbHNlCiAgICAgIH0pOwogICAgfQogICAgZnVuY3Rpb24gZ2V0Q3VycmVudFRleHRUcmFuc2Zvcm0oKSB7CiAgICAgIGNvbnN0IGZvbnQgPSB0ZXh0U3RhdGUuZm9udDsKICAgICAgY29uc3QgdHNtID0gW3RleHRTdGF0ZS5mb250U2l6ZSAqIHRleHRTdGF0ZS50ZXh0SFNjYWxlLCAwLCAwLCB0ZXh0U3RhdGUuZm9udFNpemUsIDAsIHRleHRTdGF0ZS50ZXh0UmlzZV07CiAgICAgIGlmIChmb250LmlzVHlwZTNGb250ICYmICh0ZXh0U3RhdGUuZm9udFNpemUgPD0gMSB8fCBmb250LmlzQ2hhckJCb3gpICYmICFpc0FycmF5RXF1YWwodGV4dFN0YXRlLmZvbnRNYXRyaXgsIEZPTlRfSURFTlRJVFlfTUFUUklYKSkgewogICAgICAgIGNvbnN0IGdseXBoSGVpZ2h0ID0gZm9udC5iYm94WzNdIC0gZm9udC5iYm94WzFdOwogICAgICAgIGlmIChnbHlwaEhlaWdodCA+IDApIHsKICAgICAgICAgIHRzbVszXSAqPSBnbHlwaEhlaWdodCAqIHRleHRTdGF0ZS5mb250TWF0cml4WzNdOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gVXRpbC50cmFuc2Zvcm0odGV4dFN0YXRlLmN0bSwgVXRpbC50cmFuc2Zvcm0odGV4dFN0YXRlLnRleHRNYXRyaXgsIHRzbSkpOwogICAgfQogICAgZnVuY3Rpb24gZW5zdXJlVGV4dENvbnRlbnRJdGVtKCkgewogICAgICBpZiAodGV4dENvbnRlbnRJdGVtLmluaXRpYWxpemVkKSB7CiAgICAgICAgcmV0dXJuIHRleHRDb250ZW50SXRlbTsKICAgICAgfQogICAgICBjb25zdCB7CiAgICAgICAgZm9udCwKICAgICAgICBsb2FkZWROYW1lCiAgICAgIH0gPSB0ZXh0U3RhdGU7CiAgICAgIGlmICghc2VlblN0eWxlcy5oYXMobG9hZGVkTmFtZSkpIHsKICAgICAgICBzZWVuU3R5bGVzLmFkZChsb2FkZWROYW1lKTsKICAgICAgICB0ZXh0Q29udGVudC5zdHlsZXNbbG9hZGVkTmFtZV0gPSB7CiAgICAgICAgICBmb250RmFtaWx5OiBmb250LmZhbGxiYWNrTmFtZSwKICAgICAgICAgIGFzY2VudDogZm9udC5hc2NlbnQsCiAgICAgICAgICBkZXNjZW50OiBmb250LmRlc2NlbnQsCiAgICAgICAgICB2ZXJ0aWNhbDogZm9udC52ZXJ0aWNhbAogICAgICAgIH07CiAgICAgICAgaWYgKHNlbGYub3B0aW9ucy5mb250RXh0cmFQcm9wZXJ0aWVzICYmIGZvbnQuc3lzdGVtRm9udEluZm8pIHsKICAgICAgICAgIGNvbnN0IHN0eWxlID0gdGV4dENvbnRlbnQuc3R5bGVzW2xvYWRlZE5hbWVdOwogICAgICAgICAgc3R5bGUuZm9udFN1YnN0aXR1dGlvbiA9IGZvbnQuc3lzdGVtRm9udEluZm8uY3NzOwogICAgICAgICAgc3R5bGUuZm9udFN1YnN0aXR1dGlvbkxvYWRlZE5hbWUgPSBmb250LnN5c3RlbUZvbnRJbmZvLmxvYWRlZE5hbWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIHRleHRDb250ZW50SXRlbS5mb250TmFtZSA9IGxvYWRlZE5hbWU7CiAgICAgIGNvbnN0IHRybSA9IHRleHRDb250ZW50SXRlbS50cmFuc2Zvcm0gPSBnZXRDdXJyZW50VGV4dFRyYW5zZm9ybSgpOwogICAgICBpZiAoIWZvbnQudmVydGljYWwpIHsKICAgICAgICB0ZXh0Q29udGVudEl0ZW0ud2lkdGggPSB0ZXh0Q29udGVudEl0ZW0udG90YWxXaWR0aCA9IDA7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLmhlaWdodCA9IHRleHRDb250ZW50SXRlbS50b3RhbEhlaWdodCA9IE1hdGguaHlwb3QodHJtWzJdLCB0cm1bM10pOwogICAgICAgIHRleHRDb250ZW50SXRlbS52ZXJ0aWNhbCA9IGZhbHNlOwogICAgICB9IGVsc2UgewogICAgICAgIHRleHRDb250ZW50SXRlbS53aWR0aCA9IHRleHRDb250ZW50SXRlbS50b3RhbFdpZHRoID0gTWF0aC5oeXBvdCh0cm1bMF0sIHRybVsxXSk7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLmhlaWdodCA9IHRleHRDb250ZW50SXRlbS50b3RhbEhlaWdodCA9IDA7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLnZlcnRpY2FsID0gdHJ1ZTsKICAgICAgfQogICAgICBjb25zdCBzY2FsZUxpbmVYID0gTWF0aC5oeXBvdCh0ZXh0U3RhdGUudGV4dExpbmVNYXRyaXhbMF0sIHRleHRTdGF0ZS50ZXh0TGluZU1hdHJpeFsxXSk7CiAgICAgIGNvbnN0IHNjYWxlQ3RtWCA9IE1hdGguaHlwb3QodGV4dFN0YXRlLmN0bVswXSwgdGV4dFN0YXRlLmN0bVsxXSk7CiAgICAgIHRleHRDb250ZW50SXRlbS50ZXh0QWR2YW5jZVNjYWxlID0gc2NhbGVDdG1YICogc2NhbGVMaW5lWDsKICAgICAgY29uc3QgewogICAgICAgIGZvbnRTaXplCiAgICAgIH0gPSB0ZXh0U3RhdGU7CiAgICAgIHRleHRDb250ZW50SXRlbS50cmFja2luZ1NwYWNlTWluID0gZm9udFNpemUgKiBUUkFDS0lOR19TUEFDRV9GQUNUT1I7CiAgICAgIHRleHRDb250ZW50SXRlbS5ub3RBU3BhY2UgPSBmb250U2l6ZSAqIE5PVF9BX1NQQUNFX0ZBQ1RPUjsKICAgICAgdGV4dENvbnRlbnRJdGVtLm5lZ2F0aXZlU3BhY2VNYXggPSBmb250U2l6ZSAqIE5FR0FUSVZFX1NQQUNFX0ZBQ1RPUjsKICAgICAgdGV4dENvbnRlbnRJdGVtLnNwYWNlSW5GbG93TWluID0gZm9udFNpemUgKiBTUEFDRV9JTl9GTE9XX01JTl9GQUNUT1I7CiAgICAgIHRleHRDb250ZW50SXRlbS5zcGFjZUluRmxvd01heCA9IGZvbnRTaXplICogU1BBQ0VfSU5fRkxPV19NQVhfRkFDVE9SOwogICAgICB0ZXh0Q29udGVudEl0ZW0uaGFzRU9MID0gZmFsc2U7CiAgICAgIHRleHRDb250ZW50SXRlbS5pbml0aWFsaXplZCA9IHRydWU7CiAgICAgIHJldHVybiB0ZXh0Q29udGVudEl0ZW07CiAgICB9CiAgICBmdW5jdGlvbiB1cGRhdGVBZHZhbmNlU2NhbGUoKSB7CiAgICAgIGlmICghdGV4dENvbnRlbnRJdGVtLmluaXRpYWxpemVkKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGNvbnN0IHNjYWxlTGluZVggPSBNYXRoLmh5cG90KHRleHRTdGF0ZS50ZXh0TGluZU1hdHJpeFswXSwgdGV4dFN0YXRlLnRleHRMaW5lTWF0cml4WzFdKTsKICAgICAgY29uc3Qgc2NhbGVDdG1YID0gTWF0aC5oeXBvdCh0ZXh0U3RhdGUuY3RtWzBdLCB0ZXh0U3RhdGUuY3RtWzFdKTsKICAgICAgY29uc3Qgc2NhbGVGYWN0b3IgPSBzY2FsZUN0bVggKiBzY2FsZUxpbmVYOwogICAgICBpZiAoc2NhbGVGYWN0b3IgPT09IHRleHRDb250ZW50SXRlbS50ZXh0QWR2YW5jZVNjYWxlKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmICghdGV4dENvbnRlbnRJdGVtLnZlcnRpY2FsKSB7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLnRvdGFsV2lkdGggKz0gdGV4dENvbnRlbnRJdGVtLndpZHRoICogdGV4dENvbnRlbnRJdGVtLnRleHRBZHZhbmNlU2NhbGU7CiAgICAgICAgdGV4dENvbnRlbnRJdGVtLndpZHRoID0gMDsKICAgICAgfSBlbHNlIHsKICAgICAgICB0ZXh0Q29udGVudEl0ZW0udG90YWxIZWlnaHQgKz0gdGV4dENvbnRlbnRJdGVtLmhlaWdodCAqIHRleHRDb250ZW50SXRlbS50ZXh0QWR2YW5jZVNjYWxlOwogICAgICAgIHRleHRDb250ZW50SXRlbS5oZWlnaHQgPSAwOwogICAgICB9CiAgICAgIHRleHRDb250ZW50SXRlbS50ZXh0QWR2YW5jZVNjYWxlID0gc2NhbGVGYWN0b3I7CiAgICB9CiAgICBmdW5jdGlvbiBydW5CaWRpVHJhbnNmb3JtKHRleHRDaHVuaykgewogICAgICBsZXQgdGV4dCA9IHRleHRDaHVuay5zdHIuam9pbigiIik7CiAgICAgIGlmICghZGlzYWJsZU5vcm1hbGl6YXRpb24pIHsKICAgICAgICB0ZXh0ID0gbm9ybWFsaXplVW5pY29kZSh0ZXh0KTsKICAgICAgfQogICAgICBjb25zdCBiaWRpUmVzdWx0ID0gYmlkaSh0ZXh0LCAtMSwgdGV4dENodW5rLnZlcnRpY2FsKTsKICAgICAgcmV0dXJuIHsKICAgICAgICBzdHI6IGJpZGlSZXN1bHQuc3RyLAogICAgICAgIGRpcjogYmlkaVJlc3VsdC5kaXIsCiAgICAgICAgd2lkdGg6IE1hdGguYWJzKHRleHRDaHVuay50b3RhbFdpZHRoKSwKICAgICAgICBoZWlnaHQ6IE1hdGguYWJzKHRleHRDaHVuay50b3RhbEhlaWdodCksCiAgICAgICAgdHJhbnNmb3JtOiB0ZXh0Q2h1bmsudHJhbnNmb3JtLAogICAgICAgIGZvbnROYW1lOiB0ZXh0Q2h1bmsuZm9udE5hbWUsCiAgICAgICAgaGFzRU9MOiB0ZXh0Q2h1bmsuaGFzRU9MCiAgICAgIH07CiAgICB9CiAgICBhc3luYyBmdW5jdGlvbiBoYW5kbGVTZXRGb250KGZvbnROYW1lLCBmb250UmVmKSB7CiAgICAgIGNvbnN0IHRyYW5zbGF0ZWQgPSBhd2FpdCBzZWxmLmxvYWRGb250KGZvbnROYW1lLCBmb250UmVmLCByZXNvdXJjZXMsIHRhc2spOwogICAgICB0ZXh0U3RhdGUubG9hZGVkTmFtZSA9IHRyYW5zbGF0ZWQubG9hZGVkTmFtZTsKICAgICAgdGV4dFN0YXRlLmZvbnQgPSB0cmFuc2xhdGVkLmZvbnQ7CiAgICAgIHRleHRTdGF0ZS5mb250TWF0cml4ID0gdHJhbnNsYXRlZC5mb250LmZvbnRNYXRyaXggfHwgRk9OVF9JREVOVElUWV9NQVRSSVg7CiAgICB9CiAgICBmdW5jdGlvbiBhcHBseUludmVyc2VSb3RhdGlvbih4LCB5LCBtYXRyaXgpIHsKICAgICAgY29uc3Qgc2NhbGUgPSBNYXRoLmh5cG90KG1hdHJpeFswXSwgbWF0cml4WzFdKTsKICAgICAgcmV0dXJuIFsobWF0cml4WzBdICogeCArIG1hdHJpeFsxXSAqIHkpIC8gc2NhbGUsIChtYXRyaXhbMl0gKiB4ICsgbWF0cml4WzNdICogeSkgLyBzY2FsZV07CiAgICB9CiAgICBmdW5jdGlvbiBjb21wYXJlV2l0aExhc3RQb3NpdGlvbihnbHlwaFdpZHRoKSB7CiAgICAgIGNvbnN0IGN1cnJlbnRUcmFuc2Zvcm0gPSBnZXRDdXJyZW50VGV4dFRyYW5zZm9ybSgpOwogICAgICBsZXQgcG9zWCA9IGN1cnJlbnRUcmFuc2Zvcm1bNF07CiAgICAgIGxldCBwb3NZID0gY3VycmVudFRyYW5zZm9ybVs1XTsKICAgICAgaWYgKHRleHRTdGF0ZS5mb250Py52ZXJ0aWNhbCkgewogICAgICAgIGlmIChwb3NYIDwgdmlld0JveFswXSB8fCBwb3NYID4gdmlld0JveFsyXSB8fCBwb3NZICsgZ2x5cGhXaWR0aCA8IHZpZXdCb3hbMV0gfHwgcG9zWSA+IHZpZXdCb3hbM10pIHsKICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAocG9zWCArIGdseXBoV2lkdGggPCB2aWV3Qm94WzBdIHx8IHBvc1ggPiB2aWV3Qm94WzJdIHx8IHBvc1kgPCB2aWV3Qm94WzFdIHx8IHBvc1kgPiB2aWV3Qm94WzNdKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmICghdGV4dFN0YXRlLmZvbnQgfHwgIXRleHRDb250ZW50SXRlbS5wcmV2VHJhbnNmb3JtKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgbGV0IGxhc3RQb3NYID0gdGV4dENvbnRlbnRJdGVtLnByZXZUcmFuc2Zvcm1bNF07CiAgICAgIGxldCBsYXN0UG9zWSA9IHRleHRDb250ZW50SXRlbS5wcmV2VHJhbnNmb3JtWzVdOwogICAgICBpZiAobGFzdFBvc1ggPT09IHBvc1ggJiYgbGFzdFBvc1kgPT09IHBvc1kpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBsZXQgcm90YXRlID0gLTE7CiAgICAgIGlmIChjdXJyZW50VHJhbnNmb3JtWzBdICYmIGN1cnJlbnRUcmFuc2Zvcm1bMV0gPT09IDAgJiYgY3VycmVudFRyYW5zZm9ybVsyXSA9PT0gMCkgewogICAgICAgIHJvdGF0ZSA9IGN1cnJlbnRUcmFuc2Zvcm1bMF0gPiAwID8gMCA6IDE4MDsKICAgICAgfSBlbHNlIGlmIChjdXJyZW50VHJhbnNmb3JtWzFdICYmIGN1cnJlbnRUcmFuc2Zvcm1bMF0gPT09IDAgJiYgY3VycmVudFRyYW5zZm9ybVszXSA9PT0gMCkgewogICAgICAgIHJvdGF0ZSA9IGN1cnJlbnRUcmFuc2Zvcm1bMV0gPiAwID8gOTAgOiAyNzA7CiAgICAgIH0KICAgICAgc3dpdGNoIChyb3RhdGUpIHsKICAgICAgICBjYXNlIDA6CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDkwOgogICAgICAgICAgW3Bvc1gsIHBvc1ldID0gW3Bvc1ksIHBvc1hdOwogICAgICAgICAgW2xhc3RQb3NYLCBsYXN0UG9zWV0gPSBbbGFzdFBvc1ksIGxhc3RQb3NYXTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgMTgwOgogICAgICAgICAgW3Bvc1gsIHBvc1ksIGxhc3RQb3NYLCBsYXN0UG9zWV0gPSBbLXBvc1gsIC1wb3NZLCAtbGFzdFBvc1gsIC1sYXN0UG9zWV07CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDI3MDoKICAgICAgICAgIFtwb3NYLCBwb3NZXSA9IFstcG9zWSwgLXBvc1hdOwogICAgICAgICAgW2xhc3RQb3NYLCBsYXN0UG9zWV0gPSBbLWxhc3RQb3NZLCAtbGFzdFBvc1hdOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIFtwb3NYLCBwb3NZXSA9IGFwcGx5SW52ZXJzZVJvdGF0aW9uKHBvc1gsIHBvc1ksIGN1cnJlbnRUcmFuc2Zvcm0pOwogICAgICAgICAgW2xhc3RQb3NYLCBsYXN0UG9zWV0gPSBhcHBseUludmVyc2VSb3RhdGlvbihsYXN0UG9zWCwgbGFzdFBvc1ksIHRleHRDb250ZW50SXRlbS5wcmV2VHJhbnNmb3JtKTsKICAgICAgfQogICAgICBpZiAodGV4dFN0YXRlLmZvbnQudmVydGljYWwpIHsKICAgICAgICBjb25zdCBhZHZhbmNlWSA9IChsYXN0UG9zWSAtIHBvc1kpIC8gdGV4dENvbnRlbnRJdGVtLnRleHRBZHZhbmNlU2NhbGU7CiAgICAgICAgY29uc3QgYWR2YW5jZVggPSBwb3NYIC0gbGFzdFBvc1g7CiAgICAgICAgY29uc3QgdGV4dE9yaWVudGF0aW9uID0gTWF0aC5zaWduKHRleHRDb250ZW50SXRlbS5oZWlnaHQpOwogICAgICAgIGlmIChhZHZhbmNlWSA8IHRleHRPcmllbnRhdGlvbiAqIHRleHRDb250ZW50SXRlbS5uZWdhdGl2ZVNwYWNlTWF4KSB7CiAgICAgICAgICBpZiAoTWF0aC5hYnMoYWR2YW5jZVgpID4gMC41ICogdGV4dENvbnRlbnRJdGVtLndpZHRoKSB7CiAgICAgICAgICAgIGFwcGVuZEVPTCgpOwogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICAgIHJlc2V0TGFzdENoYXJzKCk7CiAgICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIGlmIChNYXRoLmFicyhhZHZhbmNlWCkgPiB0ZXh0Q29udGVudEl0ZW0ud2lkdGgpIHsKICAgICAgICAgIGFwcGVuZEVPTCgpOwogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIGlmIChhZHZhbmNlWSA8PSB0ZXh0T3JpZW50YXRpb24gKiB0ZXh0Q29udGVudEl0ZW0ubm90QVNwYWNlKSB7CiAgICAgICAgICByZXNldExhc3RDaGFycygpOwogICAgICAgIH0KICAgICAgICBpZiAoYWR2YW5jZVkgPD0gdGV4dE9yaWVudGF0aW9uICogdGV4dENvbnRlbnRJdGVtLnRyYWNraW5nU3BhY2VNaW4pIHsKICAgICAgICAgIGlmIChzaG91bGRBZGRXaGl0ZXBzYWNlKCkpIHsKICAgICAgICAgICAgcmVzZXRMYXN0Q2hhcnMoKTsKICAgICAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICAgICAgcHVzaFdoaXRlc3BhY2UoewogICAgICAgICAgICAgIGhlaWdodDogTWF0aC5hYnMoYWR2YW5jZVkpCiAgICAgICAgICAgIH0pOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGV4dENvbnRlbnRJdGVtLmhlaWdodCArPSBhZHZhbmNlWTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKCFhZGRGYWtlU3BhY2VzKGFkdmFuY2VZLCB0ZXh0Q29udGVudEl0ZW0ucHJldlRyYW5zZm9ybSwgdGV4dE9yaWVudGF0aW9uKSkgewogICAgICAgICAgaWYgKHRleHRDb250ZW50SXRlbS5zdHIubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICAgIHJlc2V0TGFzdENoYXJzKCk7CiAgICAgICAgICAgIHB1c2hXaGl0ZXNwYWNlKHsKICAgICAgICAgICAgICBoZWlnaHQ6IE1hdGguYWJzKGFkdmFuY2VZKQogICAgICAgICAgICB9KTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRleHRDb250ZW50SXRlbS5oZWlnaHQgKz0gYWR2YW5jZVk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChNYXRoLmFicyhhZHZhbmNlWCkgPiB0ZXh0Q29udGVudEl0ZW0ud2lkdGggKiBWRVJUSUNBTF9TSElGVF9SQVRJTykgewogICAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgY29uc3QgYWR2YW5jZVggPSAocG9zWCAtIGxhc3RQb3NYKSAvIHRleHRDb250ZW50SXRlbS50ZXh0QWR2YW5jZVNjYWxlOwogICAgICBjb25zdCBhZHZhbmNlWSA9IHBvc1kgLSBsYXN0UG9zWTsKICAgICAgY29uc3QgdGV4dE9yaWVudGF0aW9uID0gTWF0aC5zaWduKHRleHRDb250ZW50SXRlbS53aWR0aCk7CiAgICAgIGlmIChhZHZhbmNlWCA8IHRleHRPcmllbnRhdGlvbiAqIHRleHRDb250ZW50SXRlbS5uZWdhdGl2ZVNwYWNlTWF4KSB7CiAgICAgICAgaWYgKE1hdGguYWJzKGFkdmFuY2VZKSA+IDAuNSAqIHRleHRDb250ZW50SXRlbS5oZWlnaHQpIHsKICAgICAgICAgIGFwcGVuZEVPTCgpOwogICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgICAgIHJlc2V0TGFzdENoYXJzKCk7CiAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAoTWF0aC5hYnMoYWR2YW5jZVkpID4gdGV4dENvbnRlbnRJdGVtLmhlaWdodCkgewogICAgICAgIGFwcGVuZEVPTCgpOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmIChhZHZhbmNlWCA8PSB0ZXh0T3JpZW50YXRpb24gKiB0ZXh0Q29udGVudEl0ZW0ubm90QVNwYWNlKSB7CiAgICAgICAgcmVzZXRMYXN0Q2hhcnMoKTsKICAgICAgfQogICAgICBpZiAoYWR2YW5jZVggPD0gdGV4dE9yaWVudGF0aW9uICogdGV4dENvbnRlbnRJdGVtLnRyYWNraW5nU3BhY2VNaW4pIHsKICAgICAgICBpZiAoc2hvdWxkQWRkV2hpdGVwc2FjZSgpKSB7CiAgICAgICAgICByZXNldExhc3RDaGFycygpOwogICAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICAgIHB1c2hXaGl0ZXNwYWNlKHsKICAgICAgICAgICAgd2lkdGg6IE1hdGguYWJzKGFkdmFuY2VYKQogICAgICAgICAgfSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRleHRDb250ZW50SXRlbS53aWR0aCArPSBhZHZhbmNlWDsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoIWFkZEZha2VTcGFjZXMoYWR2YW5jZVgsIHRleHRDb250ZW50SXRlbS5wcmV2VHJhbnNmb3JtLCB0ZXh0T3JpZW50YXRpb24pKSB7CiAgICAgICAgaWYgKHRleHRDb250ZW50SXRlbS5zdHIubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXNldExhc3RDaGFycygpOwogICAgICAgICAgcHVzaFdoaXRlc3BhY2UoewogICAgICAgICAgICB3aWR0aDogTWF0aC5hYnMoYWR2YW5jZVgpCiAgICAgICAgICB9KTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgdGV4dENvbnRlbnRJdGVtLndpZHRoICs9IGFkdmFuY2VYOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoTWF0aC5hYnMoYWR2YW5jZVkpID4gdGV4dENvbnRlbnRJdGVtLmhlaWdodCAqIFZFUlRJQ0FMX1NISUZUX1JBVElPKSB7CiAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgfQogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGZ1bmN0aW9uIGJ1aWxkVGV4dENvbnRlbnRJdGVtKHsKICAgICAgY2hhcnMsCiAgICAgIGV4dHJhU3BhY2luZwogICAgfSkgewogICAgICBjb25zdCBmb250ID0gdGV4dFN0YXRlLmZvbnQ7CiAgICAgIGlmICghY2hhcnMpIHsKICAgICAgICBjb25zdCBjaGFyU3BhY2luZyA9IHRleHRTdGF0ZS5jaGFyU3BhY2luZyArIGV4dHJhU3BhY2luZzsKICAgICAgICBpZiAoY2hhclNwYWNpbmcpIHsKICAgICAgICAgIGlmICghZm9udC52ZXJ0aWNhbCkgewogICAgICAgICAgICB0ZXh0U3RhdGUudHJhbnNsYXRlVGV4dE1hdHJpeChjaGFyU3BhY2luZyAqIHRleHRTdGF0ZS50ZXh0SFNjYWxlLCAwKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRleHRTdGF0ZS50cmFuc2xhdGVUZXh0TWF0cml4KDAsIC1jaGFyU3BhY2luZyk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGlmIChrZWVwV2hpdGVTcGFjZSkgewogICAgICAgICAgY29tcGFyZVdpdGhMYXN0UG9zaXRpb24oMCk7CiAgICAgICAgfQogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBjb25zdCBnbHlwaHMgPSBmb250LmNoYXJzVG9HbHlwaHMoY2hhcnMpOwogICAgICBjb25zdCBzY2FsZSA9IHRleHRTdGF0ZS5mb250TWF0cml4WzBdICogdGV4dFN0YXRlLmZvbnRTaXplOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBnbHlwaHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbnN0IGdseXBoID0gZ2x5cGhzW2ldOwogICAgICAgIGNvbnN0IHsKICAgICAgICAgIGNhdGVnb3J5LAogICAgICAgICAgb3JpZ2luYWxDaGFyQ29kZQogICAgICAgIH0gPSBnbHlwaDsKICAgICAgICBpZiAoY2F0ZWdvcnkuaXNJbnZpc2libGVGb3JtYXRNYXJrKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgbGV0IGNoYXJTcGFjaW5nID0gdGV4dFN0YXRlLmNoYXJTcGFjaW5nICsgKGkgKyAxID09PSBpaSA/IGV4dHJhU3BhY2luZyA6IDApOwogICAgICAgIGxldCBnbHlwaFdpZHRoID0gZ2x5cGgud2lkdGg7CiAgICAgICAgaWYgKGZvbnQudmVydGljYWwpIHsKICAgICAgICAgIGdseXBoV2lkdGggPSBnbHlwaC52bWV0cmljID8gZ2x5cGgudm1ldHJpY1swXSA6IC1nbHlwaFdpZHRoOwogICAgICAgIH0KICAgICAgICBsZXQgc2NhbGVkRGltID0gZ2x5cGhXaWR0aCAqIHNjYWxlOwogICAgICAgIGlmIChvcmlnaW5hbENoYXJDb2RlID09PSAweDIwKSB7CiAgICAgICAgICBjaGFyU3BhY2luZyArPSB0ZXh0U3RhdGUud29yZFNwYWNpbmc7CiAgICAgICAgfQogICAgICAgIGlmICgha2VlcFdoaXRlU3BhY2UgJiYgY2F0ZWdvcnkuaXNXaGl0ZXNwYWNlKSB7CiAgICAgICAgICBpZiAoIWZvbnQudmVydGljYWwpIHsKICAgICAgICAgICAgY2hhclNwYWNpbmcgKz0gc2NhbGVkRGltOwogICAgICAgICAgICB0ZXh0U3RhdGUudHJhbnNsYXRlVGV4dE1hdHJpeChjaGFyU3BhY2luZyAqIHRleHRTdGF0ZS50ZXh0SFNjYWxlLCAwKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGNoYXJTcGFjaW5nICs9IC1zY2FsZWREaW07CiAgICAgICAgICAgIHRleHRTdGF0ZS50cmFuc2xhdGVUZXh0TWF0cml4KDAsIC1jaGFyU3BhY2luZyk7CiAgICAgICAgICB9CiAgICAgICAgICBzYXZlTGFzdENoYXIoIiAiKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBpZiAoIWNhdGVnb3J5LmlzWmVyb1dpZHRoRGlhY3JpdGljICYmICFjb21wYXJlV2l0aExhc3RQb3NpdGlvbihzY2FsZWREaW0pKSB7CiAgICAgICAgICBpZiAoIWZvbnQudmVydGljYWwpIHsKICAgICAgICAgICAgdGV4dFN0YXRlLnRyYW5zbGF0ZVRleHRNYXRyaXgoc2NhbGVkRGltICogdGV4dFN0YXRlLnRleHRIU2NhbGUsIDApOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGV4dFN0YXRlLnRyYW5zbGF0ZVRleHRNYXRyaXgoMCwgc2NhbGVkRGltKTsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCB0ZXh0Q2h1bmsgPSBlbnN1cmVUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICBpZiAoY2F0ZWdvcnkuaXNaZXJvV2lkdGhEaWFjcml0aWMpIHsKICAgICAgICAgIHNjYWxlZERpbSA9IDA7CiAgICAgICAgfQogICAgICAgIGlmICghZm9udC52ZXJ0aWNhbCkgewogICAgICAgICAgc2NhbGVkRGltICo9IHRleHRTdGF0ZS50ZXh0SFNjYWxlOwogICAgICAgICAgaW50ZXJzZWN0b3I/LmFkZEdseXBoKGdldEN1cnJlbnRUZXh0VHJhbnNmb3JtKCksIHNjYWxlZERpbSwgMCwgZ2x5cGgudW5pY29kZSk7CiAgICAgICAgICB0ZXh0U3RhdGUudHJhbnNsYXRlVGV4dE1hdHJpeChzY2FsZWREaW0sIDApOwogICAgICAgICAgdGV4dENodW5rLndpZHRoICs9IHNjYWxlZERpbTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaW50ZXJzZWN0b3I/LmFkZEdseXBoKGdldEN1cnJlbnRUZXh0VHJhbnNmb3JtKCksIDAsIHNjYWxlZERpbSwgZ2x5cGgudW5pY29kZSk7CiAgICAgICAgICB0ZXh0U3RhdGUudHJhbnNsYXRlVGV4dE1hdHJpeCgwLCBzY2FsZWREaW0pOwogICAgICAgICAgc2NhbGVkRGltID0gTWF0aC5hYnMoc2NhbGVkRGltKTsKICAgICAgICAgIHRleHRDaHVuay5oZWlnaHQgKz0gc2NhbGVkRGltOwogICAgICAgIH0KICAgICAgICBpZiAoc2NhbGVkRGltKSB7CiAgICAgICAgICB0ZXh0Q2h1bmsucHJldlRyYW5zZm9ybSA9IGdldEN1cnJlbnRUZXh0VHJhbnNmb3JtKCk7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGdseXBoVW5pY29kZSA9IGdseXBoLnVuaWNvZGU7CiAgICAgICAgaWYgKHNhdmVMYXN0Q2hhcihnbHlwaFVuaWNvZGUpKSB7CiAgICAgICAgICB0ZXh0Q2h1bmsuc3RyLnB1c2goIiAiKTsKICAgICAgICAgIGludGVyc2VjdG9yPy5hZGRFeHRyYUNoYXIoIiAiKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFpbnRlcnNlY3RvcikgewogICAgICAgICAgdGV4dENodW5rLnN0ci5wdXNoKGdseXBoVW5pY29kZSk7CiAgICAgICAgfQogICAgICAgIGlmIChjaGFyU3BhY2luZykgewogICAgICAgICAgaWYgKCFmb250LnZlcnRpY2FsKSB7CiAgICAgICAgICAgIHRleHRTdGF0ZS50cmFuc2xhdGVUZXh0TWF0cml4KGNoYXJTcGFjaW5nICogdGV4dFN0YXRlLnRleHRIU2NhbGUsIDApOwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGV4dFN0YXRlLnRyYW5zbGF0ZVRleHRNYXRyaXgoMCwgLWNoYXJTcGFjaW5nKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIGFwcGVuZEVPTCgpIHsKICAgICAgaW50ZXJzZWN0b3I/LmFkZEV4dHJhQ2hhcigiXG4iKTsKICAgICAgcmVzZXRMYXN0Q2hhcnMoKTsKICAgICAgaWYgKHRleHRDb250ZW50SXRlbS5pbml0aWFsaXplZCkgewogICAgICAgIHRleHRDb250ZW50SXRlbS5oYXNFT0wgPSB0cnVlOwogICAgICAgIGZsdXNoVGV4dENvbnRlbnRJdGVtKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGV4dENvbnRlbnQuaXRlbXMucHVzaCh7CiAgICAgICAgICBzdHI6ICIiLAogICAgICAgICAgZGlyOiAibHRyIiwKICAgICAgICAgIHdpZHRoOiAwLAogICAgICAgICAgaGVpZ2h0OiAwLAogICAgICAgICAgdHJhbnNmb3JtOiBnZXRDdXJyZW50VGV4dFRyYW5zZm9ybSgpLAogICAgICAgICAgZm9udE5hbWU6IHRleHRTdGF0ZS5sb2FkZWROYW1lLAogICAgICAgICAgaGFzRU9MOiB0cnVlCiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIGFkZEZha2VTcGFjZXMod2lkdGgsIHRyYW5zZiwgdGV4dE9yaWVudGF0aW9uKSB7CiAgICAgIGlmICh0ZXh0T3JpZW50YXRpb24gKiB0ZXh0Q29udGVudEl0ZW0uc3BhY2VJbkZsb3dNaW4gPD0gd2lkdGggJiYgd2lkdGggPD0gdGV4dE9yaWVudGF0aW9uICogdGV4dENvbnRlbnRJdGVtLnNwYWNlSW5GbG93TWF4KSB7CiAgICAgICAgaWYgKHRleHRDb250ZW50SXRlbS5pbml0aWFsaXplZCkgewogICAgICAgICAgcmVzZXRMYXN0Q2hhcnMoKTsKICAgICAgICAgIHRleHRDb250ZW50SXRlbS5zdHIucHVzaCgiICIpOwogICAgICAgICAgaW50ZXJzZWN0b3I/LmFkZEV4dHJhQ2hhcigiICIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgY29uc3QgZm9udE5hbWUgPSB0ZXh0Q29udGVudEl0ZW0uZm9udE5hbWU7CiAgICAgIGxldCBoZWlnaHQgPSAwOwogICAgICBpZiAodGV4dENvbnRlbnRJdGVtLnZlcnRpY2FsKSB7CiAgICAgICAgaGVpZ2h0ID0gd2lkdGg7CiAgICAgICAgd2lkdGggPSAwOwogICAgICB9CiAgICAgIGZsdXNoVGV4dENvbnRlbnRJdGVtKCk7CiAgICAgIHJlc2V0TGFzdENoYXJzKCk7CiAgICAgIHB1c2hXaGl0ZXNwYWNlKHsKICAgICAgICB3aWR0aDogTWF0aC5hYnMod2lkdGgpLAogICAgICAgIGhlaWdodDogTWF0aC5hYnMoaGVpZ2h0KSwKICAgICAgICB0cmFuc2Zvcm06IHRyYW5zZiB8fCBnZXRDdXJyZW50VGV4dFRyYW5zZm9ybSgpLAogICAgICAgIGZvbnROYW1lCiAgICAgIH0pOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGZ1bmN0aW9uIGZsdXNoVGV4dENvbnRlbnRJdGVtKCkgewogICAgICBpZiAoIXRleHRDb250ZW50SXRlbS5pbml0aWFsaXplZCB8fCAhdGV4dENvbnRlbnRJdGVtLnN0cikgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBpZiAoIXRleHRDb250ZW50SXRlbS52ZXJ0aWNhbCkgewogICAgICAgIHRleHRDb250ZW50SXRlbS50b3RhbFdpZHRoICs9IHRleHRDb250ZW50SXRlbS53aWR0aCAqIHRleHRDb250ZW50SXRlbS50ZXh0QWR2YW5jZVNjYWxlOwogICAgICB9IGVsc2UgewogICAgICAgIHRleHRDb250ZW50SXRlbS50b3RhbEhlaWdodCArPSB0ZXh0Q29udGVudEl0ZW0uaGVpZ2h0ICogdGV4dENvbnRlbnRJdGVtLnRleHRBZHZhbmNlU2NhbGU7CiAgICAgIH0KICAgICAgdGV4dENvbnRlbnQuaXRlbXMucHVzaChydW5CaWRpVHJhbnNmb3JtKHRleHRDb250ZW50SXRlbSkpOwogICAgICB0ZXh0Q29udGVudEl0ZW0uaW5pdGlhbGl6ZWQgPSBmYWxzZTsKICAgICAgdGV4dENvbnRlbnRJdGVtLnN0ci5sZW5ndGggPSAwOwogICAgfQogICAgZnVuY3Rpb24gZW5xdWV1ZUNodW5rKGJhdGNoID0gZmFsc2UpIHsKICAgICAgY29uc3QgbGVuZ3RoID0gdGV4dENvbnRlbnQuaXRlbXMubGVuZ3RoOwogICAgICBpZiAobGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmIChiYXRjaCAmJiBsZW5ndGggPCBURVhUX0NIVU5LX0JBVENIX1NJWkUpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgc2luaz8uZW5xdWV1ZSh0ZXh0Q29udGVudCwgbGVuZ3RoKTsKICAgICAgdGV4dENvbnRlbnQuaXRlbXMgPSBbXTsKICAgICAgdGV4dENvbnRlbnQuc3R5bGVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIH0KICAgIGNvbnN0IHRpbWVTbG90TWFuYWdlciA9IG5ldyBUaW1lU2xvdE1hbmFnZXIoKTsKICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiBwcm9taXNlQm9keShyZXNvbHZlLCByZWplY3QpIHsKICAgICAgY29uc3QgbmV4dCA9IGZ1bmN0aW9uIChwcm9taXNlKSB7CiAgICAgICAgZW5xdWV1ZUNodW5rKHRydWUpOwogICAgICAgIFByb21pc2UuYWxsKFtwcm9taXNlLCBzaW5rPy5yZWFkeV0pLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgcHJvbWlzZUJvZHkocmVzb2x2ZSwgcmVqZWN0KTsKICAgICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICAgIHJlamVjdChleCk7CiAgICAgICAgICB9CiAgICAgICAgfSwgcmVqZWN0KTsKICAgICAgfTsKICAgICAgdGFzay5lbnN1cmVOb3RUZXJtaW5hdGVkKCk7CiAgICAgIHRpbWVTbG90TWFuYWdlci5yZXNldCgpOwogICAgICBjb25zdCBvcGVyYXRpb24gPSB7fTsKICAgICAgbGV0IHN0b3AsCiAgICAgICAgbmFtZSwKICAgICAgICBpc1ZhbGlkTmFtZSwKICAgICAgICBhcmdzID0gW107CiAgICAgIHdoaWxlICghKHN0b3AgPSB0aW1lU2xvdE1hbmFnZXIuY2hlY2soKSkpIHsKICAgICAgICBhcmdzLmxlbmd0aCA9IDA7CiAgICAgICAgb3BlcmF0aW9uLmFyZ3MgPSBhcmdzOwogICAgICAgIGlmICghcHJlcHJvY2Vzc29yLnJlYWQob3BlcmF0aW9uKSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHByZXZpb3VzU3RhdGUgPSB0ZXh0U3RhdGU7CiAgICAgICAgdGV4dFN0YXRlID0gc3RhdGVNYW5hZ2VyLnN0YXRlOwogICAgICAgIGNvbnN0IGZuID0gb3BlcmF0aW9uLmZuOwogICAgICAgIGFyZ3MgPSBvcGVyYXRpb24uYXJnczsKICAgICAgICBzd2l0Y2ggKGZuIHwgMCkgewogICAgICAgICAgY2FzZSBPUFMuc2V0Rm9udDoKICAgICAgICAgICAgY29uc3QgZm9udE5hbWVBcmcgPSBhcmdzWzBdLm5hbWUsCiAgICAgICAgICAgICAgZm9udFNpemVBcmcgPSBhcmdzWzFdOwogICAgICAgICAgICBpZiAodGV4dFN0YXRlLmZvbnQgJiYgZm9udE5hbWVBcmcgPT09IHRleHRTdGF0ZS5mb250TmFtZSAmJiBmb250U2l6ZUFyZyA9PT0gdGV4dFN0YXRlLmZvbnRTaXplKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICAgICAgdGV4dFN0YXRlLmZvbnROYW1lID0gZm9udE5hbWVBcmc7CiAgICAgICAgICAgIHRleHRTdGF0ZS5mb250U2l6ZSA9IGZvbnRTaXplQXJnOwogICAgICAgICAgICBuZXh0KGhhbmRsZVNldEZvbnQoZm9udE5hbWVBcmcsIG51bGwpKTsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgY2FzZSBPUFMuc2V0VGV4dFJpc2U6CiAgICAgICAgICAgIHRleHRTdGF0ZS50ZXh0UmlzZSA9IGFyZ3NbMF07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0SFNjYWxlOgogICAgICAgICAgICB0ZXh0U3RhdGUudGV4dEhTY2FsZSA9IGFyZ3NbMF0gLyAxMDA7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0TGVhZGluZzoKICAgICAgICAgICAgdGV4dFN0YXRlLmxlYWRpbmcgPSBhcmdzWzBdOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLm1vdmVUZXh0OgogICAgICAgICAgICB0ZXh0U3RhdGUudHJhbnNsYXRlVGV4dExpbmVNYXRyaXgoYXJnc1swXSwgYXJnc1sxXSk7CiAgICAgICAgICAgIHRleHRTdGF0ZS50ZXh0TWF0cml4ID0gdGV4dFN0YXRlLnRleHRMaW5lTWF0cml4LnNsaWNlKCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0TGVhZGluZ01vdmVUZXh0OgogICAgICAgICAgICB0ZXh0U3RhdGUubGVhZGluZyA9IC1hcmdzWzFdOwogICAgICAgICAgICB0ZXh0U3RhdGUudHJhbnNsYXRlVGV4dExpbmVNYXRyaXgoYXJnc1swXSwgYXJnc1sxXSk7CiAgICAgICAgICAgIHRleHRTdGF0ZS50ZXh0TWF0cml4ID0gdGV4dFN0YXRlLnRleHRMaW5lTWF0cml4LnNsaWNlKCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMubmV4dExpbmU6CiAgICAgICAgICAgIHRleHRTdGF0ZS5jYXJyaWFnZVJldHVybigpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldFRleHRNYXRyaXg6CiAgICAgICAgICAgIHRleHRTdGF0ZS5zZXRUZXh0TWF0cml4KGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10sIGFyZ3NbNF0sIGFyZ3NbNV0pOwogICAgICAgICAgICB0ZXh0U3RhdGUuc2V0VGV4dExpbmVNYXRyaXgoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSwgYXJnc1s0XSwgYXJnc1s1XSk7CiAgICAgICAgICAgIHVwZGF0ZUFkdmFuY2VTY2FsZSgpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldENoYXJTcGFjaW5nOgogICAgICAgICAgICB0ZXh0U3RhdGUuY2hhclNwYWNpbmcgPSBhcmdzWzBdOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldFdvcmRTcGFjaW5nOgogICAgICAgICAgICB0ZXh0U3RhdGUud29yZFNwYWNpbmcgPSBhcmdzWzBdOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLmJlZ2luVGV4dDoKICAgICAgICAgICAgdGV4dFN0YXRlLnRleHRNYXRyaXggPSBJREVOVElUWV9NQVRSSVguc2xpY2UoKTsKICAgICAgICAgICAgdGV4dFN0YXRlLnRleHRMaW5lTWF0cml4ID0gSURFTlRJVFlfTUFUUklYLnNsaWNlKCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2hvd1NwYWNlZFRleHQ6CiAgICAgICAgICAgIGlmICghc3RhdGVNYW5hZ2VyLnN0YXRlLmZvbnQpIHsKICAgICAgICAgICAgICBzZWxmLmVuc3VyZVN0YXRlRm9udChzdGF0ZU1hbmFnZXIuc3RhdGUpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IHNwYWNlRmFjdG9yID0gKHRleHRTdGF0ZS5mb250LnZlcnRpY2FsID8gMSA6IC0xKSAqIHRleHRTdGF0ZS5mb250U2l6ZSAvIDEwMDA7CiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnRzID0gYXJnc1swXTsKICAgICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZWxlbWVudHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgICAgIGNvbnN0IGl0ZW0gPSBlbGVtZW50c1tpXTsKICAgICAgICAgICAgICBpZiAodHlwZW9mIGl0ZW0gPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgICAgICBzaG93U3BhY2VkVGV4dEJ1ZmZlci5wdXNoKGl0ZW0pOwogICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGl0ZW0gPT09ICJudW1iZXIiICYmIGl0ZW0gIT09IDApIHsKICAgICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHNob3dTcGFjZWRUZXh0QnVmZmVyLmpvaW4oIiIpOwogICAgICAgICAgICAgICAgc2hvd1NwYWNlZFRleHRCdWZmZXIubGVuZ3RoID0gMDsKICAgICAgICAgICAgICAgIGJ1aWxkVGV4dENvbnRlbnRJdGVtKHsKICAgICAgICAgICAgICAgICAgY2hhcnM6IHN0ciwKICAgICAgICAgICAgICAgICAgZXh0cmFTcGFjaW5nOiBpdGVtICogc3BhY2VGYWN0b3IKICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoc2hvd1NwYWNlZFRleHRCdWZmZXIubGVuZ3RoID4gMCkgewogICAgICAgICAgICAgIGNvbnN0IHN0ciA9IHNob3dTcGFjZWRUZXh0QnVmZmVyLmpvaW4oIiIpOwogICAgICAgICAgICAgIHNob3dTcGFjZWRUZXh0QnVmZmVyLmxlbmd0aCA9IDA7CiAgICAgICAgICAgICAgYnVpbGRUZXh0Q29udGVudEl0ZW0oewogICAgICAgICAgICAgICAgY2hhcnM6IHN0ciwKICAgICAgICAgICAgICAgIGV4dHJhU3BhY2luZzogMAogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2hvd1RleHQ6CiAgICAgICAgICAgIGlmICghc3RhdGVNYW5hZ2VyLnN0YXRlLmZvbnQpIHsKICAgICAgICAgICAgICBzZWxmLmVuc3VyZVN0YXRlRm9udChzdGF0ZU1hbmFnZXIuc3RhdGUpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJ1aWxkVGV4dENvbnRlbnRJdGVtKHsKICAgICAgICAgICAgICBjaGFyczogYXJnc1swXSwKICAgICAgICAgICAgICBleHRyYVNwYWNpbmc6IDAKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMubmV4dExpbmVTaG93VGV4dDoKICAgICAgICAgICAgaWYgKCFzdGF0ZU1hbmFnZXIuc3RhdGUuZm9udCkgewogICAgICAgICAgICAgIHNlbGYuZW5zdXJlU3RhdGVGb250KHN0YXRlTWFuYWdlci5zdGF0ZSk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGV4dFN0YXRlLmNhcnJpYWdlUmV0dXJuKCk7CiAgICAgICAgICAgIGJ1aWxkVGV4dENvbnRlbnRJdGVtKHsKICAgICAgICAgICAgICBjaGFyczogYXJnc1swXSwKICAgICAgICAgICAgICBleHRyYVNwYWNpbmc6IDAKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMubmV4dExpbmVTZXRTcGFjaW5nU2hvd1RleHQ6CiAgICAgICAgICAgIGlmICghc3RhdGVNYW5hZ2VyLnN0YXRlLmZvbnQpIHsKICAgICAgICAgICAgICBzZWxmLmVuc3VyZVN0YXRlRm9udChzdGF0ZU1hbmFnZXIuc3RhdGUpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRleHRTdGF0ZS53b3JkU3BhY2luZyA9IGFyZ3NbMF07CiAgICAgICAgICAgIHRleHRTdGF0ZS5jaGFyU3BhY2luZyA9IGFyZ3NbMV07CiAgICAgICAgICAgIHRleHRTdGF0ZS5jYXJyaWFnZVJldHVybigpOwogICAgICAgICAgICBidWlsZFRleHRDb250ZW50SXRlbSh7CiAgICAgICAgICAgICAgY2hhcnM6IGFyZ3NbMl0sCiAgICAgICAgICAgICAgZXh0cmFTcGFjaW5nOiAwCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnBhaW50WE9iamVjdDoKICAgICAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICAgICAgeG9ianMgPz89IHJlc291cmNlcy5nZXQoIlhPYmplY3QiKSB8fCBEaWN0LmVtcHR5OwogICAgICAgICAgICBpc1ZhbGlkTmFtZSA9IGFyZ3NbMF0gaW5zdGFuY2VvZiBOYW1lOwogICAgICAgICAgICBuYW1lID0gYXJnc1swXS5uYW1lOwogICAgICAgICAgICBpZiAoaXNWYWxpZE5hbWUgJiYgZW1wdHlYT2JqZWN0Q2FjaGUuZ2V0QnlOYW1lKG5hbWUpKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbmV4dChuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZVhPYmplY3QsIHJlamVjdFhPYmplY3QpIHsKICAgICAgICAgICAgICBpZiAoIWlzVmFsaWROYW1lKSB7CiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlhPYmplY3QgbXVzdCBiZSByZWZlcnJlZCB0byBieSBuYW1lLiIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBsZXQgeG9iaiA9IHhvYmpzLmdldFJhdyhuYW1lKTsKICAgICAgICAgICAgICBpZiAoeG9iaiBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgICAgICAgaWYgKGVtcHR5WE9iamVjdENhY2hlLmdldEJ5UmVmKHhvYmopKSB7CiAgICAgICAgICAgICAgICAgIHJlc29sdmVYT2JqZWN0KCk7CiAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGNvbnN0IGdsb2JhbEltYWdlID0gc2VsZi5nbG9iYWxJbWFnZUNhY2hlLmdldERhdGEoeG9iaiwgc2VsZi5wYWdlSW5kZXgpOwogICAgICAgICAgICAgICAgaWYgKGdsb2JhbEltYWdlKSB7CiAgICAgICAgICAgICAgICAgIHJlc29sdmVYT2JqZWN0KCk7CiAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIHhvYmogPSB4cmVmLmZldGNoKHhvYmopOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoISh4b2JqIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkpIHsKICAgICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiWE9iamVjdCBzaG91bGQgYmUgYSBzdHJlYW0iKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgICAgZGljdAogICAgICAgICAgICAgIH0gPSB4b2JqOwogICAgICAgICAgICAgIGNvbnN0IHR5cGUgPSBkaWN0LmdldCgiU3VidHlwZSIpOwogICAgICAgICAgICAgIGlmICghKHR5cGUgaW5zdGFuY2VvZiBOYW1lKSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJYT2JqZWN0IHNob3VsZCBoYXZlIGEgTmFtZSBzdWJ0eXBlIik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmICh0eXBlLm5hbWUgIT09ICJGb3JtIikgewogICAgICAgICAgICAgICAgZW1wdHlYT2JqZWN0Q2FjaGUuc2V0KG5hbWUsIGRpY3Qub2JqSWQsIHRydWUpOwogICAgICAgICAgICAgICAgcmVzb2x2ZVhPYmplY3QoKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgY3VycmVudFN0YXRlID0gc3RhdGVNYW5hZ2VyLnN0YXRlLmNsb25lKCk7CiAgICAgICAgICAgICAgY29uc3QgeE9ialN0YXRlTWFuYWdlciA9IG5ldyBTdGF0ZU1hbmFnZXIoY3VycmVudFN0YXRlKTsKICAgICAgICAgICAgICBjb25zdCBtYXRyaXggPSBsb29rdXBNYXRyaXgoZGljdC5nZXRBcnJheSgiTWF0cml4IiksIG51bGwpOwogICAgICAgICAgICAgIGlmIChtYXRyaXgpIHsKICAgICAgICAgICAgICAgIHhPYmpTdGF0ZU1hbmFnZXIudHJhbnNmb3JtKG1hdHJpeCk7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGNvbnN0IGxvY2FsUmVzb3VyY2VzID0gZGljdC5nZXQoIlJlc291cmNlcyIpOwogICAgICAgICAgICAgIGVucXVldWVDaHVuaygpOwogICAgICAgICAgICAgIGNvbnN0IHNpbmtXcmFwcGVyID0gewogICAgICAgICAgICAgICAgZW5xdWV1ZUludm9rZWQ6IGZhbHNlLAogICAgICAgICAgICAgICAgZW5xdWV1ZShjaHVuaywgc2l6ZSkgewogICAgICAgICAgICAgICAgICB0aGlzLmVucXVldWVJbnZva2VkID0gdHJ1ZTsKICAgICAgICAgICAgICAgICAgc2luay5lbnF1ZXVlKGNodW5rLCBzaXplKTsKICAgICAgICAgICAgICAgIH0sCiAgICAgICAgICAgICAgICBnZXQgZGVzaXJlZFNpemUoKSB7CiAgICAgICAgICAgICAgICAgIHJldHVybiBzaW5rLmRlc2lyZWRTaXplID8/IDA7CiAgICAgICAgICAgICAgICB9LAogICAgICAgICAgICAgICAgZ2V0IHJlYWR5KCkgewogICAgICAgICAgICAgICAgICByZXR1cm4gc2luay5yZWFkeTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9OwogICAgICAgICAgICAgIHNlbGYuZ2V0VGV4dENvbnRlbnQoewogICAgICAgICAgICAgICAgc3RyZWFtOiB4b2JqLAogICAgICAgICAgICAgICAgdGFzaywKICAgICAgICAgICAgICAgIHJlc291cmNlczogbG9jYWxSZXNvdXJjZXMgaW5zdGFuY2VvZiBEaWN0ID8gbG9jYWxSZXNvdXJjZXMgOiByZXNvdXJjZXMsCiAgICAgICAgICAgICAgICBzdGF0ZU1hbmFnZXI6IHhPYmpTdGF0ZU1hbmFnZXIsCiAgICAgICAgICAgICAgICBpbmNsdWRlTWFya2VkQ29udGVudCwKICAgICAgICAgICAgICAgIHNpbms6IHNpbmsgJiYgc2lua1dyYXBwZXIsCiAgICAgICAgICAgICAgICBzZWVuU3R5bGVzLAogICAgICAgICAgICAgICAgdmlld0JveCwKICAgICAgICAgICAgICAgIGxhbmcsCiAgICAgICAgICAgICAgICBtYXJrZWRDb250ZW50RGF0YSwKICAgICAgICAgICAgICAgIGRpc2FibGVOb3JtYWxpemF0aW9uLAogICAgICAgICAgICAgICAga2VlcFdoaXRlU3BhY2UsCiAgICAgICAgICAgICAgICBwcmV2UmVmczogc2VlblJlZnMKICAgICAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICAgIGlmICghc2lua1dyYXBwZXIuZW5xdWV1ZUludm9rZWQpIHsKICAgICAgICAgICAgICAgICAgZW1wdHlYT2JqZWN0Q2FjaGUuc2V0KG5hbWUsIGRpY3Qub2JqSWQsIHRydWUpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgcmVzb2x2ZVhPYmplY3QoKTsKICAgICAgICAgICAgICB9LCByZWplY3RYT2JqZWN0KTsKICAgICAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbikgewogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAoc2VsZi5vcHRpb25zLmlnbm9yZUVycm9ycykgewogICAgICAgICAgICAgICAgd2FybihgZ2V0VGV4dENvbnRlbnQgLSBpZ25vcmluZyBYT2JqZWN0OiAiJHtyZWFzb259Ii5gKTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdGhyb3cgcmVhc29uOwogICAgICAgICAgICB9KSk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIGNhc2UgT1BTLnNldEdTdGF0ZToKICAgICAgICAgICAgaXNWYWxpZE5hbWUgPSBhcmdzWzBdIGluc3RhbmNlb2YgTmFtZTsKICAgICAgICAgICAgbmFtZSA9IGFyZ3NbMF0ubmFtZTsKICAgICAgICAgICAgaWYgKGlzVmFsaWROYW1lICYmIGVtcHR5R1N0YXRlQ2FjaGUuZ2V0QnlOYW1lKG5hbWUpKSB7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbmV4dChuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZUdTdGF0ZSwgcmVqZWN0R1N0YXRlKSB7CiAgICAgICAgICAgICAgaWYgKCFpc1ZhbGlkTmFtZSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJHU3RhdGUgbXVzdCBiZSByZWZlcnJlZCB0byBieSBuYW1lLiIpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBjb25zdCBleHRHU3RhdGUgPSByZXNvdXJjZXMuZ2V0KCJFeHRHU3RhdGUiKTsKICAgICAgICAgICAgICBpZiAoIShleHRHU3RhdGUgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJFeHRHU3RhdGUgc2hvdWxkIGJlIGEgZGljdGlvbmFyeS4iKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgZ1N0YXRlID0gZXh0R1N0YXRlLmdldChuYW1lKTsKICAgICAgICAgICAgICBpZiAoIShnU3RhdGUgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJHU3RhdGUgc2hvdWxkIGJlIGEgZGljdGlvbmFyeS4iKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgY29uc3QgZ1N0YXRlRm9udCA9IGdTdGF0ZS5nZXQoIkZvbnQiKTsKICAgICAgICAgICAgICBpZiAoIWdTdGF0ZUZvbnQpIHsKICAgICAgICAgICAgICAgIGVtcHR5R1N0YXRlQ2FjaGUuc2V0KG5hbWUsIGdTdGF0ZS5vYmpJZCwgdHJ1ZSk7CiAgICAgICAgICAgICAgICByZXNvbHZlR1N0YXRlKCk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGZsdXNoVGV4dENvbnRlbnRJdGVtKCk7CiAgICAgICAgICAgICAgdGV4dFN0YXRlLmZvbnROYW1lID0gbnVsbDsKICAgICAgICAgICAgICB0ZXh0U3RhdGUuZm9udFNpemUgPSBnU3RhdGVGb250WzFdOwogICAgICAgICAgICAgIGhhbmRsZVNldEZvbnQobnVsbCwgZ1N0YXRlRm9udFswXSkudGhlbihyZXNvbHZlR1N0YXRlLCByZWplY3RHU3RhdGUpOwogICAgICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICAgICAgaWYgKHJlYXNvbiBpbnN0YW5jZW9mIEFib3J0RXhjZXB0aW9uKSB7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGlmIChzZWxmLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgICAgICAgICB3YXJuKGBnZXRUZXh0Q29udGVudCAtIGlnbm9yaW5nIEV4dEdTdGF0ZTogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRocm93IHJlYXNvbjsKICAgICAgICAgICAgfSkpOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICBjYXNlIE9QUy5iZWdpbk1hcmtlZENvbnRlbnQ6CiAgICAgICAgICAgIGZsdXNoVGV4dENvbnRlbnRJdGVtKCk7CiAgICAgICAgICAgIGlmIChpbmNsdWRlTWFya2VkQ29udGVudCkgewogICAgICAgICAgICAgIG1hcmtlZENvbnRlbnREYXRhLmxldmVsKys7CiAgICAgICAgICAgICAgdGV4dENvbnRlbnQuaXRlbXMucHVzaCh7CiAgICAgICAgICAgICAgICB0eXBlOiAiYmVnaW5NYXJrZWRDb250ZW50IiwKICAgICAgICAgICAgICAgIHRhZzogYXJnc1swXSBpbnN0YW5jZW9mIE5hbWUgPyBhcmdzWzBdLm5hbWUgOiBudWxsCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5iZWdpbk1hcmtlZENvbnRlbnRQcm9wczoKICAgICAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICAgICAgaWYgKGluY2x1ZGVNYXJrZWRDb250ZW50KSB7CiAgICAgICAgICAgICAgbWFya2VkQ29udGVudERhdGEubGV2ZWwrKzsKICAgICAgICAgICAgICBsZXQgbWNpZCA9IG51bGw7CiAgICAgICAgICAgICAgaWYgKGFyZ3NbMV0gaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgICAgICAgICAgICBtY2lkID0gYXJnc1sxXS5nZXQoIk1DSUQiKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgdGV4dENvbnRlbnQuaXRlbXMucHVzaCh7CiAgICAgICAgICAgICAgICB0eXBlOiAiYmVnaW5NYXJrZWRDb250ZW50UHJvcHMiLAogICAgICAgICAgICAgICAgaWQ6IE51bWJlci5pc0ludGVnZXIobWNpZCkgPyBgJHtzZWxmLmlkRmFjdG9yeS5nZXRQYWdlT2JqSWQoKX1fbWMke21jaWR9YCA6IG51bGwsCiAgICAgICAgICAgICAgICB0YWc6IGFyZ3NbMF0gaW5zdGFuY2VvZiBOYW1lID8gYXJnc1swXS5uYW1lIDogbnVsbAogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuZW5kTWFya2VkQ29udGVudDoKICAgICAgICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgICAgICAgaWYgKGluY2x1ZGVNYXJrZWRDb250ZW50KSB7CiAgICAgICAgICAgICAgaWYgKG1hcmtlZENvbnRlbnREYXRhLmxldmVsID09PSAwKSB7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgbWFya2VkQ29udGVudERhdGEubGV2ZWwtLTsKICAgICAgICAgICAgICB0ZXh0Q29udGVudC5pdGVtcy5wdXNoKHsKICAgICAgICAgICAgICAgIHR5cGU6ICJlbmRNYXJrZWRDb250ZW50IgogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMucmVzdG9yZToKICAgICAgICAgICAgaWYgKHByZXZpb3VzU3RhdGUgJiYgKHByZXZpb3VzU3RhdGUuZm9udCAhPT0gdGV4dFN0YXRlLmZvbnQgfHwgcHJldmlvdXNTdGF0ZS5mb250U2l6ZSAhPT0gdGV4dFN0YXRlLmZvbnRTaXplIHx8IHByZXZpb3VzU3RhdGUuZm9udE5hbWUgIT09IHRleHRTdGF0ZS5mb250TmFtZSkpIHsKICAgICAgICAgICAgICBmbHVzaFRleHRDb250ZW50SXRlbSgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBpZiAodGV4dENvbnRlbnQuaXRlbXMubGVuZ3RoID49IChzaW5rPy5kZXNpcmVkU2l6ZSA/PyAxKSkgewogICAgICAgICAgc3RvcCA9IHRydWU7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKHN0b3ApIHsKICAgICAgICBuZXh0KGRlZmVycmVkKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgZmx1c2hUZXh0Q29udGVudEl0ZW0oKTsKICAgICAgZW5xdWV1ZUNodW5rKCk7CiAgICAgIHJlc29sdmUoKTsKICAgIH0pLmNhdGNoKHJlYXNvbiA9PiB7CiAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBBYm9ydEV4Y2VwdGlvbikgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBpZiAodGhpcy5vcHRpb25zLmlnbm9yZUVycm9ycykgewogICAgICAgIHdhcm4oYGdldFRleHRDb250ZW50IC0gaWdub3JpbmcgZXJyb3JzIGR1cmluZyAiJHt0YXNrLm5hbWV9IiBgICsgYHRhc2s6ICIke3JlYXNvbn0iLmApOwogICAgICAgIGZsdXNoVGV4dENvbnRlbnRJdGVtKCk7CiAgICAgICAgZW5xdWV1ZUNodW5rKCk7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIHRocm93IHJlYXNvbjsKICAgIH0pOwogIH0KICBhc3luYyBleHRyYWN0RGF0YVN0cnVjdHVyZXMoZGljdCwgcHJvcGVydGllcykgewogICAgY29uc3QgeHJlZiA9IHRoaXMueHJlZjsKICAgIGxldCBjaWRUb0dpZEJ5dGVzOwogICAgY29uc3QgdG9Vbmljb2RlUHJvbWlzZSA9IHRoaXMucmVhZFRvVW5pY29kZShwcm9wZXJ0aWVzLnRvVW5pY29kZSk7CiAgICBpZiAocHJvcGVydGllcy5jb21wb3NpdGUpIHsKICAgICAgY29uc3QgY2lkU3lzdGVtSW5mbyA9IGRpY3QuZ2V0KCJDSURTeXN0ZW1JbmZvIik7CiAgICAgIGlmIChjaWRTeXN0ZW1JbmZvIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgIHByb3BlcnRpZXMuY2lkU3lzdGVtSW5mbyA9IHsKICAgICAgICAgIHJlZ2lzdHJ5OiBzdHJpbmdUb1BERlN0cmluZyhjaWRTeXN0ZW1JbmZvLmdldCgiUmVnaXN0cnkiKSksCiAgICAgICAgICBvcmRlcmluZzogc3RyaW5nVG9QREZTdHJpbmcoY2lkU3lzdGVtSW5mby5nZXQoIk9yZGVyaW5nIikpLAogICAgICAgICAgc3VwcGxlbWVudDogY2lkU3lzdGVtSW5mby5nZXQoIlN1cHBsZW1lbnQiKQogICAgICAgIH07CiAgICAgIH0KICAgICAgdHJ5IHsKICAgICAgICBjb25zdCBjaWRUb0dpZE1hcCA9IGRpY3QuZ2V0KCJDSURUb0dJRE1hcCIpOwogICAgICAgIGlmIChjaWRUb0dpZE1hcCBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgICAgIGNpZFRvR2lkQnl0ZXMgPSBjaWRUb0dpZE1hcC5nZXRCeXRlcygpOwogICAgICAgIH0KICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICBpZiAoIXRoaXMub3B0aW9ucy5pZ25vcmVFcnJvcnMpIHsKICAgICAgICAgIHRocm93IGV4OwogICAgICAgIH0KICAgICAgICB3YXJuKGBleHRyYWN0RGF0YVN0cnVjdHVyZXMgLSBpZ25vcmluZyBDSURUb0dJRE1hcCBkYXRhOiAiJHtleH0iLmApOwogICAgICB9CiAgICB9CiAgICBjb25zdCBkaWZmZXJlbmNlcyA9IFtdOwogICAgbGV0IGJhc2VFbmNvZGluZ05hbWUgPSBudWxsOwogICAgbGV0IGVuY29kaW5nOwogICAgaWYgKGRpY3QuaGFzKCJFbmNvZGluZyIpKSB7CiAgICAgIGVuY29kaW5nID0gZGljdC5nZXQoIkVuY29kaW5nIik7CiAgICAgIGlmIChlbmNvZGluZyBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICBiYXNlRW5jb2RpbmdOYW1lID0gZW5jb2RpbmcuZ2V0KCJCYXNlRW5jb2RpbmciKTsKICAgICAgICBiYXNlRW5jb2RpbmdOYW1lID0gYmFzZUVuY29kaW5nTmFtZSBpbnN0YW5jZW9mIE5hbWUgPyBiYXNlRW5jb2RpbmdOYW1lLm5hbWUgOiBudWxsOwogICAgICAgIGlmIChlbmNvZGluZy5oYXMoIkRpZmZlcmVuY2VzIikpIHsKICAgICAgICAgIGNvbnN0IGRpZmZFbmNvZGluZyA9IGVuY29kaW5nLmdldCgiRGlmZmVyZW5jZXMiKTsKICAgICAgICAgIGxldCBpbmRleCA9IDA7CiAgICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGRpZmZFbmNvZGluZykgewogICAgICAgICAgICBjb25zdCBkYXRhID0geHJlZi5mZXRjaElmUmVmKGVudHJ5KTsKICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRhID09PSAibnVtYmVyIikgewogICAgICAgICAgICAgIGluZGV4ID0gZGF0YTsKICAgICAgICAgICAgfSBlbHNlIGlmIChkYXRhIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgICAgIGRpZmZlcmVuY2VzW2luZGV4KytdID0gZGF0YS5uYW1lOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCBlbnRyeSBpbiAnRGlmZmVyZW5jZXMnIGFycmF5OiAke2RhdGF9YCk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAoZW5jb2RpbmcgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgYmFzZUVuY29kaW5nTmFtZSA9IGVuY29kaW5nLm5hbWU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgbXNnID0gIkVuY29kaW5nIGlzIG5vdCBhIE5hbWUgbm9yIGEgRGljdCI7CiAgICAgICAgaWYgKCF0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IobXNnKTsKICAgICAgICB9CiAgICAgICAgd2Fybihtc2cpOwogICAgICB9CiAgICAgIGlmIChiYXNlRW5jb2RpbmdOYW1lICE9PSAiTWFjUm9tYW5FbmNvZGluZyIgJiYgYmFzZUVuY29kaW5nTmFtZSAhPT0gIk1hY0V4cGVydEVuY29kaW5nIiAmJiBiYXNlRW5jb2RpbmdOYW1lICE9PSAiV2luQW5zaUVuY29kaW5nIikgewogICAgICAgIGJhc2VFbmNvZGluZ05hbWUgPSBudWxsOwogICAgICB9CiAgICB9CiAgICBjb25zdCBub25FbWJlZGRlZEZvbnQgPSAhcHJvcGVydGllcy5maWxlIHx8IHByb3BlcnRpZXMuaXNJbnRlcm5hbEZvbnQsCiAgICAgIGlzU3ltYm9sc0ZvbnROYW1lID0gZ2V0U3ltYm9sc0ZvbnRzKClbcHJvcGVydGllcy5uYW1lXTsKICAgIGlmIChiYXNlRW5jb2RpbmdOYW1lICYmIG5vbkVtYmVkZGVkRm9udCAmJiBpc1N5bWJvbHNGb250TmFtZSkgewogICAgICBiYXNlRW5jb2RpbmdOYW1lID0gbnVsbDsKICAgIH0KICAgIGlmIChiYXNlRW5jb2RpbmdOYW1lKSB7CiAgICAgIHByb3BlcnRpZXMuZGVmYXVsdEVuY29kaW5nID0gZ2V0RW5jb2RpbmcoYmFzZUVuY29kaW5nTmFtZSk7CiAgICB9IGVsc2UgewogICAgICBsZXQgaXNTeW1ib2xpY0ZvbnQgPSAhIShwcm9wZXJ0aWVzLmZsYWdzICYgRm9udEZsYWdzLlN5bWJvbGljKTsKICAgICAgY29uc3QgaXNOb25zeW1ib2xpY0ZvbnQgPSAhIShwcm9wZXJ0aWVzLmZsYWdzICYgRm9udEZsYWdzLk5vbnN5bWJvbGljKTsKICAgICAgaWYgKHByb3BlcnRpZXMudHlwZSA9PT0gIlRydWVUeXBlIiAmJiBpc1N5bWJvbGljRm9udCAmJiBpc05vbnN5bWJvbGljRm9udCAmJiBkaWZmZXJlbmNlcy5sZW5ndGggIT09IDApIHsKICAgICAgICBwcm9wZXJ0aWVzLmZsYWdzICY9IH5Gb250RmxhZ3MuU3ltYm9saWM7CiAgICAgICAgaXNTeW1ib2xpY0ZvbnQgPSBmYWxzZTsKICAgICAgfQogICAgICBlbmNvZGluZyA9IFN0YW5kYXJkRW5jb2Rpbmc7CiAgICAgIGlmIChwcm9wZXJ0aWVzLnR5cGUgPT09ICJUcnVlVHlwZSIgJiYgIWlzTm9uc3ltYm9saWNGb250KSB7CiAgICAgICAgZW5jb2RpbmcgPSBXaW5BbnNpRW5jb2Rpbmc7CiAgICAgIH0KICAgICAgaWYgKGlzU3ltYm9saWNGb250IHx8IGlzU3ltYm9sc0ZvbnROYW1lKSB7CiAgICAgICAgZW5jb2RpbmcgPSBNYWNSb21hbkVuY29kaW5nOwogICAgICAgIGlmIChub25FbWJlZGRlZEZvbnQpIHsKICAgICAgICAgIGlmICgvU3ltYm9sL2kudGVzdChwcm9wZXJ0aWVzLm5hbWUpKSB7CiAgICAgICAgICAgIGVuY29kaW5nID0gU3ltYm9sU2V0RW5jb2Rpbmc7CiAgICAgICAgICB9IGVsc2UgaWYgKC9EaW5nYmF0cy9pLnRlc3QocHJvcGVydGllcy5uYW1lKSkgewogICAgICAgICAgICBlbmNvZGluZyA9IFphcGZEaW5nYmF0c0VuY29kaW5nOwogICAgICAgICAgfSBlbHNlIGlmICgvV2luZ2RpbmdzL2kudGVzdChwcm9wZXJ0aWVzLm5hbWUpKSB7CiAgICAgICAgICAgIGVuY29kaW5nID0gV2luQW5zaUVuY29kaW5nOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBwcm9wZXJ0aWVzLmRlZmF1bHRFbmNvZGluZyA9IGVuY29kaW5nOwogICAgfQogICAgcHJvcGVydGllcy5kaWZmZXJlbmNlcyA9IGRpZmZlcmVuY2VzOwogICAgcHJvcGVydGllcy5iYXNlRW5jb2RpbmdOYW1lID0gYmFzZUVuY29kaW5nTmFtZTsKICAgIHByb3BlcnRpZXMuaGFzRW5jb2RpbmcgPSAhIWJhc2VFbmNvZGluZ05hbWUgfHwgZGlmZmVyZW5jZXMubGVuZ3RoID4gMDsKICAgIHByb3BlcnRpZXMuZGljdCA9IGRpY3Q7CiAgICBwcm9wZXJ0aWVzLnRvVW5pY29kZSA9IGF3YWl0IHRvVW5pY29kZVByb21pc2U7CiAgICBjb25zdCBidWlsdFRvVW5pY29kZSA9IGF3YWl0IHRoaXMuYnVpbGRUb1VuaWNvZGUocHJvcGVydGllcyk7CiAgICBwcm9wZXJ0aWVzLnRvVW5pY29kZSA9IGJ1aWx0VG9Vbmljb2RlOwogICAgaWYgKGNpZFRvR2lkQnl0ZXMpIHsKICAgICAgcHJvcGVydGllcy5jaWRUb0dpZE1hcCA9IHRoaXMucmVhZENpZFRvR2lkTWFwKGNpZFRvR2lkQnl0ZXMsIGJ1aWx0VG9Vbmljb2RlKTsKICAgIH0KICAgIHJldHVybiBwcm9wZXJ0aWVzOwogIH0KICBfc2ltcGxlRm9udFRvVW5pY29kZShwcm9wZXJ0aWVzLCBmb3JjZUdseXBocyA9IGZhbHNlKSB7CiAgICBhc3NlcnQoIXByb3BlcnRpZXMuY29tcG9zaXRlLCAiTXVzdCBiZSBhIHNpbXBsZSBmb250LiIpOwogICAgY29uc3QgdG9Vbmljb2RlID0gW107CiAgICBjb25zdCBlbmNvZGluZyA9IHByb3BlcnRpZXMuZGVmYXVsdEVuY29kaW5nLnNsaWNlKCk7CiAgICBjb25zdCBiYXNlRW5jb2RpbmdOYW1lID0gcHJvcGVydGllcy5iYXNlRW5jb2RpbmdOYW1lOwogICAgY29uc3QgZGlmZmVyZW5jZXMgPSBwcm9wZXJ0aWVzLmRpZmZlcmVuY2VzOwogICAgZm9yIChjb25zdCBjaGFyY29kZSBpbiBkaWZmZXJlbmNlcykgewogICAgICBjb25zdCBnbHlwaE5hbWUgPSBkaWZmZXJlbmNlc1tjaGFyY29kZV07CiAgICAgIGlmIChnbHlwaE5hbWUgPT09ICIubm90ZGVmIikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGVuY29kaW5nW2NoYXJjb2RlXSA9IGdseXBoTmFtZTsKICAgIH0KICAgIGNvbnN0IGdseXBoc1VuaWNvZGVNYXAgPSBnZXRHbHlwaHNVbmljb2RlKCk7CiAgICBmb3IgKGNvbnN0IGNoYXJjb2RlIGluIGVuY29kaW5nKSB7CiAgICAgIGxldCBnbHlwaE5hbWUgPSBlbmNvZGluZ1tjaGFyY29kZV07CiAgICAgIGlmIChnbHlwaE5hbWUgPT09ICIiKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgbGV0IHVuaWNvZGUgPSBnbHlwaHNVbmljb2RlTWFwW2dseXBoTmFtZV07CiAgICAgIGlmICh1bmljb2RlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICB0b1VuaWNvZGVbY2hhcmNvZGVdID0gU3RyaW5nLmZyb21DaGFyQ29kZSh1bmljb2RlKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBsZXQgY29kZSA9IDA7CiAgICAgIHN3aXRjaCAoZ2x5cGhOYW1lWzBdKSB7CiAgICAgICAgY2FzZSAiRyI6CiAgICAgICAgICBpZiAoZ2x5cGhOYW1lLmxlbmd0aCA9PT0gMykgewogICAgICAgICAgICBjb2RlID0gcGFyc2VJbnQoZ2x5cGhOYW1lLnN1YnN0cmluZygxKSwgMTYpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZyI6CiAgICAgICAgICBpZiAoZ2x5cGhOYW1lLmxlbmd0aCA9PT0gNSkgewogICAgICAgICAgICBjb2RlID0gcGFyc2VJbnQoZ2x5cGhOYW1lLnN1YnN0cmluZygxKSwgMTYpOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiQyI6CiAgICAgICAgY2FzZSAiYyI6CiAgICAgICAgICBpZiAoZ2x5cGhOYW1lLmxlbmd0aCA+PSAzICYmIGdseXBoTmFtZS5sZW5ndGggPD0gNCkgewogICAgICAgICAgICBjb25zdCBjb2RlU3RyID0gZ2x5cGhOYW1lLnN1YnN0cmluZygxKTsKICAgICAgICAgICAgaWYgKGZvcmNlR2x5cGhzKSB7CiAgICAgICAgICAgICAgY29kZSA9IHBhcnNlSW50KGNvZGVTdHIsIDE2KTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb2RlID0gK2NvZGVTdHI7CiAgICAgICAgICAgIGlmIChOdW1iZXIuaXNOYU4oY29kZSkgJiYgTnVtYmVyLmlzSW50ZWdlcihwYXJzZUludChjb2RlU3RyLCAxNikpKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3NpbXBsZUZvbnRUb1VuaWNvZGUocHJvcGVydGllcywgdHJ1ZSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgInUiOgogICAgICAgICAgdW5pY29kZSA9IGdldFVuaWNvZGVGb3JHbHlwaChnbHlwaE5hbWUsIGdseXBoc1VuaWNvZGVNYXApOwogICAgICAgICAgaWYgKHVuaWNvZGUgIT09IC0xKSB7CiAgICAgICAgICAgIGNvZGUgPSB1bmljb2RlOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIHN3aXRjaCAoZ2x5cGhOYW1lKSB7CiAgICAgICAgICAgIGNhc2UgImZfaCI6CiAgICAgICAgICAgIGNhc2UgImZfdCI6CiAgICAgICAgICAgIGNhc2UgIlRfaCI6CiAgICAgICAgICAgICAgdG9Vbmljb2RlW2NoYXJjb2RlXSA9IGdseXBoTmFtZS5yZXBsYWNlQWxsKCJfIiwgIiIpOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKGNvZGUgPiAwICYmIGNvZGUgPD0gMHgxMGZmZmYgJiYgTnVtYmVyLmlzSW50ZWdlcihjb2RlKSkgewogICAgICAgIGlmIChiYXNlRW5jb2RpbmdOYW1lICYmIGNvZGUgPT09ICtjaGFyY29kZSkgewogICAgICAgICAgY29uc3QgYmFzZUVuY29kaW5nID0gZ2V0RW5jb2RpbmcoYmFzZUVuY29kaW5nTmFtZSk7CiAgICAgICAgICBpZiAoYmFzZUVuY29kaW5nICYmIChnbHlwaE5hbWUgPSBiYXNlRW5jb2RpbmdbY2hhcmNvZGVdKSkgewogICAgICAgICAgICB0b1VuaWNvZGVbY2hhcmNvZGVdID0gU3RyaW5nLmZyb21DaGFyQ29kZShnbHlwaHNVbmljb2RlTWFwW2dseXBoTmFtZV0pOwogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgdG9Vbmljb2RlW2NoYXJjb2RlXSA9IFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGUpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gdG9Vbmljb2RlOwogIH0KICBhc3luYyBidWlsZFRvVW5pY29kZShwcm9wZXJ0aWVzKSB7CiAgICBwcm9wZXJ0aWVzLmhhc0luY2x1ZGVkVG9Vbmljb2RlTWFwID0gcHJvcGVydGllcy50b1VuaWNvZGU/Lmxlbmd0aCA+IDA7CiAgICBpZiAocHJvcGVydGllcy5oYXNJbmNsdWRlZFRvVW5pY29kZU1hcCkgewogICAgICBpZiAoIXByb3BlcnRpZXMuY29tcG9zaXRlICYmIHByb3BlcnRpZXMuaGFzRW5jb2RpbmcpIHsKICAgICAgICBwcm9wZXJ0aWVzLmZhbGxiYWNrVG9Vbmljb2RlID0gdGhpcy5fc2ltcGxlRm9udFRvVW5pY29kZShwcm9wZXJ0aWVzKTsKICAgICAgfQogICAgICByZXR1cm4gcHJvcGVydGllcy50b1VuaWNvZGU7CiAgICB9CiAgICBpZiAoIXByb3BlcnRpZXMuY29tcG9zaXRlKSB7CiAgICAgIHJldHVybiBuZXcgVG9Vbmljb2RlTWFwKHRoaXMuX3NpbXBsZUZvbnRUb1VuaWNvZGUocHJvcGVydGllcykpOwogICAgfQogICAgaWYgKHByb3BlcnRpZXMuY29tcG9zaXRlICYmIChwcm9wZXJ0aWVzLmNNYXAuYnVpbHRJbkNNYXAgJiYgIShwcm9wZXJ0aWVzLmNNYXAgaW5zdGFuY2VvZiBJZGVudGl0eUNNYXApIHx8IHByb3BlcnRpZXMuY2lkU3lzdGVtSW5mbz8ucmVnaXN0cnkgPT09ICJBZG9iZSIgJiYgKHByb3BlcnRpZXMuY2lkU3lzdGVtSW5mby5vcmRlcmluZyA9PT0gIkdCMSIgfHwgcHJvcGVydGllcy5jaWRTeXN0ZW1JbmZvLm9yZGVyaW5nID09PSAiQ05TMSIgfHwgcHJvcGVydGllcy5jaWRTeXN0ZW1JbmZvLm9yZGVyaW5nID09PSAiSmFwYW4xIiB8fCBwcm9wZXJ0aWVzLmNpZFN5c3RlbUluZm8ub3JkZXJpbmcgPT09ICJLb3JlYTEiKSkpIHsKICAgICAgY29uc3QgewogICAgICAgIHJlZ2lzdHJ5LAogICAgICAgIG9yZGVyaW5nCiAgICAgIH0gPSBwcm9wZXJ0aWVzLmNpZFN5c3RlbUluZm87CiAgICAgIGNvbnN0IHVjczJDTWFwTmFtZSA9IE5hbWUuZ2V0KGAke3JlZ2lzdHJ5fS0ke29yZGVyaW5nfS1VQ1MyYCk7CiAgICAgIGNvbnN0IHVjczJDTWFwID0gYXdhaXQgQ01hcEZhY3RvcnkuY3JlYXRlKHsKICAgICAgICBlbmNvZGluZzogdWNzMkNNYXBOYW1lLAogICAgICAgIGZldGNoQnVpbHRJbkNNYXA6IHRoaXMuX2ZldGNoQnVpbHRJbkNNYXBCb3VuZCwKICAgICAgICB1c2VDTWFwOiBudWxsCiAgICAgIH0pOwogICAgICBjb25zdCB0b1VuaWNvZGUgPSBbXSwKICAgICAgICBidWYgPSBbXTsKICAgICAgcHJvcGVydGllcy5jTWFwLmZvckVhY2goZnVuY3Rpb24gKGNoYXJjb2RlLCBjaWQpIHsKICAgICAgICBpZiAoY2lkID4gMHhmZmZmKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIk1heCBzaXplIG9mIENJRCBpcyA2NSw1MzUiKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgdWNzMiA9IHVjczJDTWFwLmxvb2t1cChjaWQpOwogICAgICAgIGlmICh1Y3MyKSB7CiAgICAgICAgICBidWYubGVuZ3RoID0gMDsKICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHVjczIubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICAgICAgICBidWYucHVzaCgodWNzMi5jaGFyQ29kZUF0KGkpIDw8IDgpICsgdWNzMi5jaGFyQ29kZUF0KGkgKyAxKSk7CiAgICAgICAgICB9CiAgICAgICAgICB0b1VuaWNvZGVbY2hhcmNvZGVdID0gU3RyaW5nLmZyb21DaGFyQ29kZSguLi5idWYpOwogICAgICAgIH0KICAgICAgfSk7CiAgICAgIHJldHVybiBuZXcgVG9Vbmljb2RlTWFwKHRvVW5pY29kZSk7CiAgICB9CiAgICByZXR1cm4gbmV3IElkZW50aXR5VG9Vbmljb2RlTWFwKHByb3BlcnRpZXMuZmlyc3RDaGFyLCBwcm9wZXJ0aWVzLmxhc3RDaGFyKTsKICB9CiAgYXN5bmMgcmVhZFRvVW5pY29kZShjbWFwT2JqKSB7CiAgICBpZiAoIWNtYXBPYmopIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBpZiAoY21hcE9iaiBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgY29uc3QgY21hcCA9IGF3YWl0IENNYXBGYWN0b3J5LmNyZWF0ZSh7CiAgICAgICAgZW5jb2Rpbmc6IGNtYXBPYmosCiAgICAgICAgZmV0Y2hCdWlsdEluQ01hcDogdGhpcy5fZmV0Y2hCdWlsdEluQ01hcEJvdW5kLAogICAgICAgIHVzZUNNYXA6IG51bGwKICAgICAgfSk7CiAgICAgIGlmIChjbWFwIGluc3RhbmNlb2YgSWRlbnRpdHlDTWFwKSB7CiAgICAgICAgcmV0dXJuIG5ldyBJZGVudGl0eVRvVW5pY29kZU1hcCgwLCAweGZmZmYpOwogICAgICB9CiAgICAgIHJldHVybiBuZXcgVG9Vbmljb2RlTWFwKGNtYXAuZ2V0TWFwKCkpOwogICAgfQogICAgaWYgKGNtYXBPYmogaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICAgIHRyeSB7CiAgICAgICAgY29uc3QgY21hcCA9IGF3YWl0IENNYXBGYWN0b3J5LmNyZWF0ZSh7CiAgICAgICAgICBlbmNvZGluZzogY21hcE9iaiwKICAgICAgICAgIGZldGNoQnVpbHRJbkNNYXA6IHRoaXMuX2ZldGNoQnVpbHRJbkNNYXBCb3VuZCwKICAgICAgICAgIHVzZUNNYXA6IG51bGwKICAgICAgICB9KTsKICAgICAgICBpZiAoY21hcCBpbnN0YW5jZW9mIElkZW50aXR5Q01hcCkgewogICAgICAgICAgcmV0dXJuIG5ldyBJZGVudGl0eVRvVW5pY29kZU1hcCgwLCAweGZmZmYpOwogICAgICAgIH0KICAgICAgICBjb25zdCBtYXAgPSBuZXcgQXJyYXkoY21hcC5sZW5ndGgpOwogICAgICAgIGNtYXAuZm9yRWFjaChmdW5jdGlvbiAoY2hhckNvZGUsIHRva2VuKSB7CiAgICAgICAgICBpZiAodHlwZW9mIHRva2VuID09PSAibnVtYmVyIikgewogICAgICAgICAgICBtYXBbY2hhckNvZGVdID0gU3RyaW5nLmZyb21Db2RlUG9pbnQodG9rZW4pOwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodG9rZW4ubGVuZ3RoICUgMiAhPT0gMCkgewogICAgICAgICAgICB0b2tlbiA9ICJcdTAwMDAiICsgdG9rZW47CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBzdHIgPSBbXTsKICAgICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgdG9rZW4ubGVuZ3RoOyBrICs9IDIpIHsKICAgICAgICAgICAgY29uc3QgdzEgPSB0b2tlbi5jaGFyQ29kZUF0KGspIDw8IDggfCB0b2tlbi5jaGFyQ29kZUF0KGsgKyAxKTsKICAgICAgICAgICAgaWYgKCh3MSAmIDB4ZjgwMCkgIT09IDB4ZDgwMCkgewogICAgICAgICAgICAgIHN0ci5wdXNoKHcxKTsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBrICs9IDI7CiAgICAgICAgICAgIGNvbnN0IHcyID0gdG9rZW4uY2hhckNvZGVBdChrKSA8PCA4IHwgdG9rZW4uY2hhckNvZGVBdChrICsgMSk7CiAgICAgICAgICAgIHN0ci5wdXNoKCgodzEgJiAweDNmZikgPDwgMTApICsgKHcyICYgMHgzZmYpICsgMHgxMDAwMCk7CiAgICAgICAgICB9CiAgICAgICAgICBtYXBbY2hhckNvZGVdID0gU3RyaW5nLmZyb21Db2RlUG9pbnQoLi4uc3RyKTsKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gbmV3IFRvVW5pY29kZU1hcChtYXApOwogICAgICB9IGNhdGNoIChyZWFzb24pIHsKICAgICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgQWJvcnRFeGNlcHRpb24pIHsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgICBpZiAodGhpcy5vcHRpb25zLmlnbm9yZUVycm9ycykgewogICAgICAgICAgd2FybihgcmVhZFRvVW5pY29kZSAtIGlnbm9yaW5nIFRvVW5pY29kZSBkYXRhOiAiJHtyZWFzb259Ii5gKTsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgICB0aHJvdyByZWFzb247CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KICByZWFkQ2lkVG9HaWRNYXAoZ2x5cGhzRGF0YSwgdG9Vbmljb2RlKSB7CiAgICBjb25zdCByZXN1bHQgPSBbXTsKICAgIGZvciAobGV0IGogPSAwLCBqaiA9IGdseXBoc0RhdGEubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICBjb25zdCBnbHlwaElEID0gZ2x5cGhzRGF0YVtqKytdIDw8IDggfCBnbHlwaHNEYXRhW2pdOwogICAgICBjb25zdCBjb2RlID0gaiA+PiAxOwogICAgICBpZiAoZ2x5cGhJRCA9PT0gMCAmJiAhdG9Vbmljb2RlLmhhcyhjb2RlKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHJlc3VsdFtjb2RlXSA9IGdseXBoSUQ7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICBleHRyYWN0V2lkdGhzKGRpY3QsIGRlc2NyaXB0b3IsIHByb3BlcnRpZXMpIHsKICAgIGNvbnN0IHhyZWYgPSB0aGlzLnhyZWY7CiAgICBsZXQgZ2x5cGhzV2lkdGhzID0gW107CiAgICBsZXQgZGVmYXVsdFdpZHRoID0gMDsKICAgIGNvbnN0IGdseXBoc1ZNZXRyaWNzID0gW107CiAgICBsZXQgZGVmYXVsdFZNZXRyaWNzOwogICAgaWYgKHByb3BlcnRpZXMuY29tcG9zaXRlKSB7CiAgICAgIGNvbnN0IGR3ID0gZGljdC5nZXQoIkRXIik7CiAgICAgIGRlZmF1bHRXaWR0aCA9IHR5cGVvZiBkdyA9PT0gIm51bWJlciIgPyBNYXRoLmNlaWwoZHcpIDogMTAwMDsKICAgICAgY29uc3Qgd2lkdGhzID0gZGljdC5nZXQoIlciKTsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkod2lkdGhzKSkgewogICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHdpZHRocy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICBsZXQgc3RhcnQgPSB4cmVmLmZldGNoSWZSZWYod2lkdGhzW2krK10pOwogICAgICAgICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKHN0YXJ0KSkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IGNvZGUgPSB4cmVmLmZldGNoSWZSZWYod2lkdGhzW2ldKTsKICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvZGUpKSB7CiAgICAgICAgICAgIGZvciAoY29uc3QgYyBvZiBjb2RlKSB7CiAgICAgICAgICAgICAgY29uc3Qgd2lkdGggPSB4cmVmLmZldGNoSWZSZWYoYyk7CiAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3aWR0aCA9PT0gIm51bWJlciIpIHsKICAgICAgICAgICAgICAgIGdseXBoc1dpZHRoc1tzdGFydF0gPSB3aWR0aDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgc3RhcnQrKzsKICAgICAgICAgICAgfQogICAgICAgICAgfSBlbHNlIGlmIChOdW1iZXIuaXNJbnRlZ2VyKGNvZGUpKSB7CiAgICAgICAgICAgIGNvbnN0IHdpZHRoID0geHJlZi5mZXRjaElmUmVmKHdpZHRoc1srK2ldKTsKICAgICAgICAgICAgaWYgKHR5cGVvZiB3aWR0aCAhPT0gIm51bWJlciIpIHsKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBmb3IgKGxldCBqID0gc3RhcnQ7IGogPD0gY29kZTsgaisrKSB7CiAgICAgICAgICAgICAgZ2x5cGhzV2lkdGhzW2pdID0gd2lkdGg7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBpZiAocHJvcGVydGllcy52ZXJ0aWNhbCkgewogICAgICAgIGNvbnN0IGR3MiA9IGRpY3QuZ2V0QXJyYXkoIkRXMiIpOwogICAgICAgIGxldCB2bWV0cmljcyA9IGlzTnVtYmVyQXJyYXkoZHcyLCAyKSA/IGR3MiA6IFs4ODAsIC0xMDAwXTsKICAgICAgICBkZWZhdWx0Vk1ldHJpY3MgPSBbdm1ldHJpY3NbMV0sIGRlZmF1bHRXaWR0aCAqIDAuNSwgdm1ldHJpY3NbMF1dOwogICAgICAgIHZtZXRyaWNzID0gZGljdC5nZXQoIlcyIik7CiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodm1ldHJpY3MpKSB7CiAgICAgICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB2bWV0cmljcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICAgIGxldCBzdGFydCA9IHhyZWYuZmV0Y2hJZlJlZih2bWV0cmljc1tpKytdKTsKICAgICAgICAgICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKHN0YXJ0KSkgewogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGNvbnN0IGNvZGUgPSB4cmVmLmZldGNoSWZSZWYodm1ldHJpY3NbaV0pOwogICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjb2RlKSkgewogICAgICAgICAgICAgIGZvciAobGV0IGogPSAwLCBqaiA9IGNvZGUubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICAgICAgICAgICAgY29uc3Qgdm1ldHJpYyA9IFt4cmVmLmZldGNoSWZSZWYoY29kZVtqKytdKSwgeHJlZi5mZXRjaElmUmVmKGNvZGVbaisrXSksIHhyZWYuZmV0Y2hJZlJlZihjb2RlW2pdKV07CiAgICAgICAgICAgICAgICBpZiAoaXNOdW1iZXJBcnJheSh2bWV0cmljLCBudWxsKSkgewogICAgICAgICAgICAgICAgICBnbHlwaHNWTWV0cmljc1tzdGFydF0gPSB2bWV0cmljOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgc3RhcnQrKzsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSBpZiAoTnVtYmVyLmlzSW50ZWdlcihjb2RlKSkgewogICAgICAgICAgICAgIGNvbnN0IHZtZXRyaWMgPSBbeHJlZi5mZXRjaElmUmVmKHZtZXRyaWNzWysraV0pLCB4cmVmLmZldGNoSWZSZWYodm1ldHJpY3NbKytpXSksIHhyZWYuZmV0Y2hJZlJlZih2bWV0cmljc1srK2ldKV07CiAgICAgICAgICAgICAgaWYgKCFpc051bWJlckFycmF5KHZtZXRyaWMsIG51bGwpKSB7CiAgICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IHN0YXJ0OyBqIDw9IGNvZGU7IGorKykgewogICAgICAgICAgICAgICAgZ2x5cGhzVk1ldHJpY3Nbal0gPSB2bWV0cmljOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgY29uc3Qgd2lkdGhzID0gZGljdC5nZXQoIldpZHRocyIpOwogICAgICBpZiAoQXJyYXkuaXNBcnJheSh3aWR0aHMpKSB7CiAgICAgICAgbGV0IGogPSBwcm9wZXJ0aWVzLmZpcnN0Q2hhcjsKICAgICAgICBmb3IgKGNvbnN0IHcgb2Ygd2lkdGhzKSB7CiAgICAgICAgICBjb25zdCB3aWR0aCA9IHhyZWYuZmV0Y2hJZlJlZih3KTsKICAgICAgICAgIGlmICh0eXBlb2Ygd2lkdGggPT09ICJudW1iZXIiKSB7CiAgICAgICAgICAgIGdseXBoc1dpZHRoc1tqXSA9IHdpZHRoOwogICAgICAgICAgfQogICAgICAgICAgaisrOwogICAgICAgIH0KICAgICAgICBjb25zdCBtaXNzaW5nV2lkdGggPSBkZXNjcmlwdG9yLmdldCgiTWlzc2luZ1dpZHRoIik7CiAgICAgICAgZGVmYXVsdFdpZHRoID0gdHlwZW9mIG1pc3NpbmdXaWR0aCA9PT0gIm51bWJlciIgPyBtaXNzaW5nV2lkdGggOiAwOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IGJhc2VGb250TmFtZSA9IGRpY3QuZ2V0KCJCYXNlRm9udCIpOwogICAgICAgIGlmIChiYXNlRm9udE5hbWUgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICBjb25zdCBtZXRyaWNzID0gdGhpcy5nZXRCYXNlRm9udE1ldHJpY3MoYmFzZUZvbnROYW1lLm5hbWUpOwogICAgICAgICAgZ2x5cGhzV2lkdGhzID0gdGhpcy5idWlsZENoYXJDb2RlVG9XaWR0aChtZXRyaWNzLndpZHRocywgcHJvcGVydGllcyk7CiAgICAgICAgICBkZWZhdWx0V2lkdGggPSBtZXRyaWNzLmRlZmF1bHRXaWR0aDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGxldCBpc01vbm9zcGFjZSA9IHRydWU7CiAgICBsZXQgZmlyc3RXaWR0aCA9IGRlZmF1bHRXaWR0aDsKICAgIGZvciAoY29uc3QgZ2x5cGggaW4gZ2x5cGhzV2lkdGhzKSB7CiAgICAgIGNvbnN0IGdseXBoV2lkdGggPSBnbHlwaHNXaWR0aHNbZ2x5cGhdOwogICAgICBpZiAoIWdseXBoV2lkdGgpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoIWZpcnN0V2lkdGgpIHsKICAgICAgICBmaXJzdFdpZHRoID0gZ2x5cGhXaWR0aDsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoZmlyc3RXaWR0aCAhPT0gZ2x5cGhXaWR0aCkgewogICAgICAgIGlzTW9ub3NwYWNlID0gZmFsc2U7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGlmIChpc01vbm9zcGFjZSkgewogICAgICBwcm9wZXJ0aWVzLmZsYWdzIHw9IEZvbnRGbGFncy5GaXhlZFBpdGNoOwogICAgfSBlbHNlIHsKICAgICAgcHJvcGVydGllcy5mbGFncyAmPSB+Rm9udEZsYWdzLkZpeGVkUGl0Y2g7CiAgICB9CiAgICBwcm9wZXJ0aWVzLmRlZmF1bHRXaWR0aCA9IGRlZmF1bHRXaWR0aDsKICAgIHByb3BlcnRpZXMud2lkdGhzID0gZ2x5cGhzV2lkdGhzOwogICAgcHJvcGVydGllcy5kZWZhdWx0Vk1ldHJpY3MgPSBkZWZhdWx0Vk1ldHJpY3M7CiAgICBwcm9wZXJ0aWVzLnZtZXRyaWNzID0gZ2x5cGhzVk1ldHJpY3M7CiAgfQogIGlzU2VyaWZGb250KGJhc2VGb250TmFtZSkgewogICAgY29uc3QgZm9udE5hbWVXb1N0eWxlID0gYmFzZUZvbnROYW1lLnNwbGl0KCItIiwgMSlbMF07CiAgICByZXR1cm4gZm9udE5hbWVXb1N0eWxlIGluIGdldFNlcmlmRm9udHMoKSB8fCAvc2VyaWYvZ2kudGVzdChmb250TmFtZVdvU3R5bGUpOwogIH0KICBnZXRCYXNlRm9udE1ldHJpY3MobmFtZSkgewogICAgbGV0IGRlZmF1bHRXaWR0aCA9IDA7CiAgICBsZXQgd2lkdGhzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGxldCBtb25vc3BhY2UgPSBmYWxzZTsKICAgIGNvbnN0IHN0ZEZvbnRNYXAgPSBnZXRTdGRGb250TWFwKCk7CiAgICBsZXQgbG9va3VwTmFtZSA9IHN0ZEZvbnRNYXBbbmFtZV0gfHwgbmFtZTsKICAgIGNvbnN0IE1ldHJpY3MgPSBnZXRNZXRyaWNzKCk7CiAgICBpZiAoIShsb29rdXBOYW1lIGluIE1ldHJpY3MpKSB7CiAgICAgIGxvb2t1cE5hbWUgPSB0aGlzLmlzU2VyaWZGb250KG5hbWUpID8gIlRpbWVzLVJvbWFuIiA6ICJIZWx2ZXRpY2EiOwogICAgfQogICAgY29uc3QgZ2x5cGhXaWR0aHMgPSBNZXRyaWNzW2xvb2t1cE5hbWVdOwogICAgaWYgKHR5cGVvZiBnbHlwaFdpZHRocyA9PT0gIm51bWJlciIpIHsKICAgICAgZGVmYXVsdFdpZHRoID0gZ2x5cGhXaWR0aHM7CiAgICAgIG1vbm9zcGFjZSA9IHRydWU7CiAgICB9IGVsc2UgewogICAgICB3aWR0aHMgPSBnbHlwaFdpZHRocygpOwogICAgfQogICAgcmV0dXJuIHsKICAgICAgZGVmYXVsdFdpZHRoLAogICAgICBtb25vc3BhY2UsCiAgICAgIHdpZHRocwogICAgfTsKICB9CiAgYnVpbGRDaGFyQ29kZVRvV2lkdGgod2lkdGhzQnlHbHlwaE5hbWUsIHByb3BlcnRpZXMpIHsKICAgIGNvbnN0IHdpZHRocyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBjb25zdCBkaWZmZXJlbmNlcyA9IHByb3BlcnRpZXMuZGlmZmVyZW5jZXM7CiAgICBjb25zdCBlbmNvZGluZyA9IHByb3BlcnRpZXMuZGVmYXVsdEVuY29kaW5nOwogICAgZm9yIChsZXQgY2hhckNvZGUgPSAwOyBjaGFyQ29kZSA8IDI1NjsgY2hhckNvZGUrKykgewogICAgICBpZiAoY2hhckNvZGUgaW4gZGlmZmVyZW5jZXMgJiYgd2lkdGhzQnlHbHlwaE5hbWVbZGlmZmVyZW5jZXNbY2hhckNvZGVdXSkgewogICAgICAgIHdpZHRoc1tjaGFyQ29kZV0gPSB3aWR0aHNCeUdseXBoTmFtZVtkaWZmZXJlbmNlc1tjaGFyQ29kZV1dOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChjaGFyQ29kZSBpbiBlbmNvZGluZyAmJiB3aWR0aHNCeUdseXBoTmFtZVtlbmNvZGluZ1tjaGFyQ29kZV1dKSB7CiAgICAgICAgd2lkdGhzW2NoYXJDb2RlXSA9IHdpZHRoc0J5R2x5cGhOYW1lW2VuY29kaW5nW2NoYXJDb2RlXV07CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB3aWR0aHM7CiAgfQogIHByZUV2YWx1YXRlRm9udChkaWN0KSB7CiAgICBjb25zdCBiYXNlRGljdCA9IGRpY3Q7CiAgICBsZXQgdHlwZSA9IGRpY3QuZ2V0KCJTdWJ0eXBlIik7CiAgICBpZiAoISh0eXBlIGluc3RhbmNlb2YgTmFtZSkpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJpbnZhbGlkIGZvbnQgU3VidHlwZSIpOwogICAgfQogICAgbGV0IGNvbXBvc2l0ZSA9IGZhbHNlOwogICAgbGV0IGhhc2g7CiAgICBpZiAodHlwZS5uYW1lID09PSAiVHlwZTAiKSB7CiAgICAgIGNvbnN0IGRmID0gZGljdC5nZXQoIkRlc2NlbmRhbnRGb250cyIpOwogICAgICBpZiAoIWRmKSB7CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJEZXNjZW5kYW50IGZvbnRzIGFyZSBub3Qgc3BlY2lmaWVkIik7CiAgICAgIH0KICAgICAgZGljdCA9IEFycmF5LmlzQXJyYXkoZGYpID8gdGhpcy54cmVmLmZldGNoSWZSZWYoZGZbMF0pIDogZGY7CiAgICAgIGlmICghKGRpY3QgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiRGVzY2VuZGFudCBmb250IGlzIG5vdCBhIGRpY3Rpb25hcnkuIik7CiAgICAgIH0KICAgICAgdHlwZSA9IGRpY3QuZ2V0KCJTdWJ0eXBlIik7CiAgICAgIGlmICghKHR5cGUgaW5zdGFuY2VvZiBOYW1lKSkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiaW52YWxpZCBmb250IFN1YnR5cGUiKTsKICAgICAgfQogICAgICBjb21wb3NpdGUgPSB0cnVlOwogICAgfQogICAgbGV0IGZpcnN0Q2hhciA9IGRpY3QuZ2V0KCJGaXJzdENoYXIiKTsKICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihmaXJzdENoYXIpKSB7CiAgICAgIGZpcnN0Q2hhciA9IDA7CiAgICB9CiAgICBsZXQgbGFzdENoYXIgPSBkaWN0LmdldCgiTGFzdENoYXIiKTsKICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihsYXN0Q2hhcikpIHsKICAgICAgbGFzdENoYXIgPSBjb21wb3NpdGUgPyAweGZmZmYgOiAweGZmOwogICAgfQogICAgY29uc3QgZGVzY3JpcHRvciA9IGRpY3QuZ2V0KCJGb250RGVzY3JpcHRvciIpOwogICAgY29uc3QgdG9Vbmljb2RlID0gZGljdC5nZXQoIlRvVW5pY29kZSIpIHx8IGJhc2VEaWN0LmdldCgiVG9Vbmljb2RlIik7CiAgICBpZiAoZGVzY3JpcHRvcikgewogICAgICBoYXNoID0gbmV3IE11cm11ckhhc2gzXzY0KCk7CiAgICAgIGNvbnN0IGVuY29kaW5nID0gYmFzZURpY3QuZ2V0UmF3KCJFbmNvZGluZyIpOwogICAgICBpZiAoZW5jb2RpbmcgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgaGFzaC51cGRhdGUoZW5jb2RpbmcubmFtZSk7CiAgICAgIH0gZWxzZSBpZiAoZW5jb2RpbmcgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICBoYXNoLnVwZGF0ZShlbmNvZGluZy50b1N0cmluZygpKTsKICAgICAgfSBlbHNlIGlmIChlbmNvZGluZyBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVuY29kaW5nLmdldFJhd1ZhbHVlcygpKSB7CiAgICAgICAgICBpZiAoZW50cnkgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgIGhhc2gudXBkYXRlKGVudHJ5Lm5hbWUpOwogICAgICAgICAgfSBlbHNlIGlmIChlbnRyeSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgICBoYXNoLnVwZGF0ZShlbnRyeS50b1N0cmluZygpKTsKICAgICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShlbnRyeSkpIHsKICAgICAgICAgICAgY29uc3QgZGlmZkxlbmd0aCA9IGVudHJ5Lmxlbmd0aCwKICAgICAgICAgICAgICBkaWZmQnVmID0gbmV3IEFycmF5KGRpZmZMZW5ndGgpOwogICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGRpZmZMZW5ndGg7IGorKykgewogICAgICAgICAgICAgIGNvbnN0IGRpZmZFbnRyeSA9IGVudHJ5W2pdOwogICAgICAgICAgICAgIGlmIChkaWZmRW50cnkgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgICAgICBkaWZmQnVmW2pdID0gZGlmZkVudHJ5Lm5hbWU7CiAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgZGlmZkVudHJ5ID09PSAibnVtYmVyIiB8fCBkaWZmRW50cnkgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICAgICAgICAgIGRpZmZCdWZbal0gPSBkaWZmRW50cnkudG9TdHJpbmcoKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaGFzaC51cGRhdGUoZGlmZkJ1Zi5qb2luKCkpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBoYXNoLnVwZGF0ZShgJHtmaXJzdENoYXJ9LSR7bGFzdENoYXJ9YCk7CiAgICAgIGlmICh0b1VuaWNvZGUgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICAgICAgY29uc3Qgc3RyZWFtID0gdG9Vbmljb2RlLnN0ciB8fCB0b1VuaWNvZGU7CiAgICAgICAgY29uc3QgdWludDhhcnJheSA9IHN0cmVhbS5idWZmZXIgPyBuZXcgVWludDhBcnJheShzdHJlYW0uYnVmZmVyLmJ1ZmZlciwgMCwgc3RyZWFtLmJ1ZmZlckxlbmd0aCkgOiBuZXcgVWludDhBcnJheShzdHJlYW0uYnl0ZXMuYnVmZmVyLCBzdHJlYW0uc3RhcnQsIHN0cmVhbS5lbmQgLSBzdHJlYW0uc3RhcnQpOwogICAgICAgIGhhc2gudXBkYXRlKHVpbnQ4YXJyYXkpOwogICAgICB9IGVsc2UgaWYgKHRvVW5pY29kZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICBoYXNoLnVwZGF0ZSh0b1VuaWNvZGUubmFtZSk7CiAgICAgIH0KICAgICAgY29uc3Qgd2lkdGhzID0gZGljdC5nZXQoIldpZHRocyIpIHx8IGJhc2VEaWN0LmdldCgiV2lkdGhzIik7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KHdpZHRocykpIHsKICAgICAgICBjb25zdCB3aWR0aHNCdWYgPSBbXTsKICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIHdpZHRocykgewogICAgICAgICAgaWYgKHR5cGVvZiBlbnRyeSA9PT0gIm51bWJlciIgfHwgZW50cnkgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICAgICAgd2lkdGhzQnVmLnB1c2goZW50cnkudG9TdHJpbmcoKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGhhc2gudXBkYXRlKHdpZHRoc0J1Zi5qb2luKCkpOwogICAgICB9CiAgICAgIGlmIChjb21wb3NpdGUpIHsKICAgICAgICBoYXNoLnVwZGF0ZSgiY29tcG9zaXRlRm9udCIpOwogICAgICAgIGNvbnN0IGNvbXBvc2l0ZVdpZHRocyA9IGRpY3QuZ2V0KCJXIikgfHwgYmFzZURpY3QuZ2V0KCJXIik7CiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoY29tcG9zaXRlV2lkdGhzKSkgewogICAgICAgICAgY29uc3Qgd2lkdGhzQnVmID0gW107CiAgICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGNvbXBvc2l0ZVdpZHRocykgewogICAgICAgICAgICBpZiAodHlwZW9mIGVudHJ5ID09PSAibnVtYmVyIiB8fCBlbnRyeSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgICAgIHdpZHRoc0J1Zi5wdXNoKGVudHJ5LnRvU3RyaW5nKCkpOwogICAgICAgICAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoZW50cnkpKSB7CiAgICAgICAgICAgICAgY29uc3Qgc3ViV2lkdGhzQnVmID0gW107CiAgICAgICAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGVudHJ5KSB7CiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGVsZW1lbnQgPT09ICJudW1iZXIiIHx8IGVsZW1lbnQgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICAgICAgICAgICAgc3ViV2lkdGhzQnVmLnB1c2goZWxlbWVudC50b1N0cmluZygpKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgd2lkdGhzQnVmLnB1c2goYFske3N1YldpZHRoc0J1Zi5qb2luKCl9XWApOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBoYXNoLnVwZGF0ZSh3aWR0aHNCdWYuam9pbigpKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgY2lkVG9HaWRNYXAgPSBkaWN0LmdldFJhdygiQ0lEVG9HSURNYXAiKSB8fCBiYXNlRGljdC5nZXRSYXcoIkNJRFRvR0lETWFwIik7CiAgICAgICAgaWYgKGNpZFRvR2lkTWFwIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgaGFzaC51cGRhdGUoY2lkVG9HaWRNYXAubmFtZSk7CiAgICAgICAgfSBlbHNlIGlmIChjaWRUb0dpZE1hcCBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgaGFzaC51cGRhdGUoY2lkVG9HaWRNYXAudG9TdHJpbmcoKSk7CiAgICAgICAgfSBlbHNlIGlmIChjaWRUb0dpZE1hcCBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgICAgIGhhc2gudXBkYXRlKGNpZFRvR2lkTWFwLnBlZWtCeXRlcygpKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB7CiAgICAgIGRlc2NyaXB0b3IsCiAgICAgIGRpY3QsCiAgICAgIGJhc2VEaWN0LAogICAgICBjb21wb3NpdGUsCiAgICAgIHR5cGU6IHR5cGUubmFtZSwKICAgICAgZmlyc3RDaGFyLAogICAgICBsYXN0Q2hhciwKICAgICAgdG9Vbmljb2RlLAogICAgICBoYXNoOiBoYXNoID8gaGFzaC5oZXhkaWdlc3QoKSA6ICIiCiAgICB9OwogIH0KICBhc3luYyB0cmFuc2xhdGVGb250KHsKICAgIGRlc2NyaXB0b3IsCiAgICBkaWN0LAogICAgYmFzZURpY3QsCiAgICBjb21wb3NpdGUsCiAgICB0eXBlLAogICAgZmlyc3RDaGFyLAogICAgbGFzdENoYXIsCiAgICB0b1VuaWNvZGUsCiAgICBjc3NGb250SW5mbwogIH0pIHsKICAgIGNvbnN0IGlzVHlwZTNGb250ID0gdHlwZSA9PT0gIlR5cGUzIjsKICAgIGlmICghZGVzY3JpcHRvcikgewogICAgICBpZiAoaXNUeXBlM0ZvbnQpIHsKICAgICAgICBkZXNjcmlwdG9yID0gRGljdC5lbXB0eTsKICAgICAgfSBlbHNlIHsKICAgICAgICBsZXQgYmFzZUZvbnROYW1lID0gZGljdC5nZXQoIkJhc2VGb250Iik7CiAgICAgICAgaWYgKCEoYmFzZUZvbnROYW1lIGluc3RhbmNlb2YgTmFtZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiQmFzZSBmb250IGlzIG5vdCBzcGVjaWZpZWQiKTsKICAgICAgICB9CiAgICAgICAgYmFzZUZvbnROYW1lID0gYmFzZUZvbnROYW1lLm5hbWUucmVwbGFjZUFsbCgvWyxfXS9nLCAiLSIpOwogICAgICAgIGNvbnN0IG1ldHJpY3MgPSB0aGlzLmdldEJhc2VGb250TWV0cmljcyhiYXNlRm9udE5hbWUpOwogICAgICAgIGNvbnN0IGZvbnROYW1lV29TdHlsZSA9IGJhc2VGb250TmFtZS5zcGxpdCgiLSIsIDEpWzBdOwogICAgICAgIGNvbnN0IGZsYWdzID0gKHRoaXMuaXNTZXJpZkZvbnQoZm9udE5hbWVXb1N0eWxlKSA/IEZvbnRGbGFncy5TZXJpZiA6IDApIHwgKG1ldHJpY3MubW9ub3NwYWNlID8gRm9udEZsYWdzLkZpeGVkUGl0Y2ggOiAwKSB8IChnZXRTeW1ib2xzRm9udHMoKVtmb250TmFtZVdvU3R5bGVdID8gRm9udEZsYWdzLlN5bWJvbGljIDogRm9udEZsYWdzLk5vbnN5bWJvbGljKTsKICAgICAgICBjb25zdCBwcm9wZXJ0aWVzID0gewogICAgICAgICAgdHlwZSwKICAgICAgICAgIG5hbWU6IGJhc2VGb250TmFtZSwKICAgICAgICAgIGxvYWRlZE5hbWU6IGJhc2VEaWN0LmxvYWRlZE5hbWUsCiAgICAgICAgICBzeXN0ZW1Gb250SW5mbzogbnVsbCwKICAgICAgICAgIHdpZHRoczogbWV0cmljcy53aWR0aHMsCiAgICAgICAgICBkZWZhdWx0V2lkdGg6IG1ldHJpY3MuZGVmYXVsdFdpZHRoLAogICAgICAgICAgaXNTaW11bGF0ZWRGbGFnczogdHJ1ZSwKICAgICAgICAgIGZsYWdzLAogICAgICAgICAgZmlyc3RDaGFyLAogICAgICAgICAgbGFzdENoYXIsCiAgICAgICAgICB0b1VuaWNvZGUsCiAgICAgICAgICB4SGVpZ2h0OiAwLAogICAgICAgICAgY2FwSGVpZ2h0OiAwLAogICAgICAgICAgaXRhbGljQW5nbGU6IDAsCiAgICAgICAgICBpc1R5cGUzRm9udAogICAgICAgIH07CiAgICAgICAgY29uc3Qgd2lkdGhzID0gZGljdC5nZXQoIldpZHRocyIpOwogICAgICAgIGNvbnN0IHN0YW5kYXJkRm9udE5hbWUgPSBnZXRTdGFuZGFyZEZvbnROYW1lKGJhc2VGb250TmFtZSk7CiAgICAgICAgbGV0IGZpbGUgPSBudWxsOwogICAgICAgIGlmIChzdGFuZGFyZEZvbnROYW1lKSB7CiAgICAgICAgICBmaWxlID0gYXdhaXQgdGhpcy5mZXRjaFN0YW5kYXJkRm9udERhdGEoc3RhbmRhcmRGb250TmFtZSk7CiAgICAgICAgICBwcm9wZXJ0aWVzLmlzSW50ZXJuYWxGb250ID0gISFmaWxlOwogICAgICAgIH0KICAgICAgICBpZiAoIXByb3BlcnRpZXMuaXNJbnRlcm5hbEZvbnQgJiYgdGhpcy5vcHRpb25zLnVzZVN5c3RlbUZvbnRzKSB7CiAgICAgICAgICBwcm9wZXJ0aWVzLnN5c3RlbUZvbnRJbmZvID0gZ2V0Rm9udFN1YnN0aXR1dGlvbih0aGlzLnN5c3RlbUZvbnRDYWNoZSwgdGhpcy5pZEZhY3RvcnksIHRoaXMub3B0aW9ucy5zdGFuZGFyZEZvbnREYXRhVXJsLCBiYXNlRm9udE5hbWUsIHN0YW5kYXJkRm9udE5hbWUsIHR5cGUpOwogICAgICAgIH0KICAgICAgICBjb25zdCBuZXdQcm9wZXJ0aWVzID0gYXdhaXQgdGhpcy5leHRyYWN0RGF0YVN0cnVjdHVyZXMoZGljdCwgcHJvcGVydGllcyk7CiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkod2lkdGhzKSkgewogICAgICAgICAgY29uc3QgZ2x5cGhXaWR0aHMgPSBbXTsKICAgICAgICAgIGxldCBqID0gZmlyc3RDaGFyOwogICAgICAgICAgZm9yIChjb25zdCB3IG9mIHdpZHRocykgewogICAgICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMueHJlZi5mZXRjaElmUmVmKHcpOwogICAgICAgICAgICBpZiAodHlwZW9mIHdpZHRoID09PSAibnVtYmVyIikgewogICAgICAgICAgICAgIGdseXBoV2lkdGhzW2pdID0gd2lkdGg7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaisrOwogICAgICAgICAgfQogICAgICAgICAgbmV3UHJvcGVydGllcy53aWR0aHMgPSBnbHlwaFdpZHRoczsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgbmV3UHJvcGVydGllcy53aWR0aHMgPSB0aGlzLmJ1aWxkQ2hhckNvZGVUb1dpZHRoKG1ldHJpY3Mud2lkdGhzLCBuZXdQcm9wZXJ0aWVzKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIG5ldyBGb250KGJhc2VGb250TmFtZSwgZmlsZSwgbmV3UHJvcGVydGllcywgdGhpcy5vcHRpb25zKTsKICAgICAgfQogICAgfQogICAgbGV0IGZvbnROYW1lID0gZGVzY3JpcHRvci5nZXQoIkZvbnROYW1lIik7CiAgICBsZXQgYmFzZUZvbnQgPSBkaWN0LmdldCgiQmFzZUZvbnQiKTsKICAgIGlmICh0eXBlb2YgZm9udE5hbWUgPT09ICJzdHJpbmciKSB7CiAgICAgIGZvbnROYW1lID0gTmFtZS5nZXQoZm9udE5hbWUpOwogICAgfQogICAgaWYgKHR5cGVvZiBiYXNlRm9udCA9PT0gInN0cmluZyIpIHsKICAgICAgYmFzZUZvbnQgPSBOYW1lLmdldChiYXNlRm9udCk7CiAgICB9CiAgICBjb25zdCBmb250TmFtZVN0ciA9IGZvbnROYW1lPy5uYW1lOwogICAgY29uc3QgYmFzZUZvbnRTdHIgPSBiYXNlRm9udD8ubmFtZTsKICAgIGlmIChpc1R5cGUzRm9udCkgewogICAgICBpZiAoIWZvbnROYW1lU3RyKSB7CiAgICAgICAgZm9udE5hbWUgPSBOYW1lLmdldCh0eXBlKTsKICAgICAgfQogICAgfSBlbHNlIGlmIChmb250TmFtZVN0ciAhPT0gYmFzZUZvbnRTdHIpIHsKICAgICAgaW5mbyhgVGhlIEZvbnREZXNjcmlwdG9yJ3MgRm9udE5hbWUgaXMgIiR7Zm9udE5hbWVTdHJ9IiBidXQgYCArIGBzaG91bGQgYmUgdGhlIHNhbWUgYXMgdGhlIEZvbnQncyBCYXNlRm9udCAiJHtiYXNlRm9udFN0cn0iLmApOwogICAgICBpZiAoZm9udE5hbWVTdHIgJiYgYmFzZUZvbnRTdHIgJiYgKGJhc2VGb250U3RyLnN0YXJ0c1dpdGgoZm9udE5hbWVTdHIpIHx8ICFpc0tub3duRm9udE5hbWUoZm9udE5hbWVTdHIpICYmIGlzS25vd25Gb250TmFtZShiYXNlRm9udFN0cikpKSB7CiAgICAgICAgZm9udE5hbWUgPSBudWxsOwogICAgICB9CiAgICAgIGZvbnROYW1lIHx8PSBiYXNlRm9udDsKICAgIH0KICAgIGlmICghKGZvbnROYW1lIGluc3RhbmNlb2YgTmFtZSkpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJpbnZhbGlkIGZvbnQgbmFtZSIpOwogICAgfQogICAgbGV0IGZvbnRGaWxlLCBzdWJ0eXBlLCBsZW5ndGgxLCBsZW5ndGgyLCBsZW5ndGgzOwogICAgdHJ5IHsKICAgICAgZm9udEZpbGUgPSBkZXNjcmlwdG9yLmdldCgiRm9udEZpbGUiLCAiRm9udEZpbGUyIiwgIkZvbnRGaWxlMyIpOwogICAgICBpZiAoZm9udEZpbGUpIHsKICAgICAgICBpZiAoIShmb250RmlsZSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkZvbnRGaWxlIHNob3VsZCBiZSBhIHN0cmVhbSIpOwogICAgICAgIH0gZWxzZSBpZiAoZm9udEZpbGUuaXNFbXB0eSkgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJGb250RmlsZSBpcyBlbXB0eSIpOwogICAgICAgIH0KICAgICAgfQogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKCF0aGlzLm9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgd2FybihgdHJhbnNsYXRlRm9udCAtIGZldGNoaW5nICIke2ZvbnROYW1lLm5hbWV9IiBmb250IGZpbGU6ICIke2V4fSIuYCk7CiAgICAgIGZvbnRGaWxlID0gbnVsbDsKICAgIH0KICAgIGxldCBpc0ludGVybmFsRm9udCA9IGZhbHNlOwogICAgbGV0IGdseXBoU2NhbGVGYWN0b3JzID0gbnVsbDsKICAgIGxldCBzeXN0ZW1Gb250SW5mbyA9IG51bGw7CiAgICBpZiAoZm9udEZpbGUpIHsKICAgICAgaWYgKGZvbnRGaWxlLmRpY3QpIHsKICAgICAgICBjb25zdCBzdWJ0eXBlRW50cnkgPSBmb250RmlsZS5kaWN0LmdldCgiU3VidHlwZSIpOwogICAgICAgIGlmIChzdWJ0eXBlRW50cnkgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICBzdWJ0eXBlID0gc3VidHlwZUVudHJ5Lm5hbWU7CiAgICAgICAgfQogICAgICAgIGxlbmd0aDEgPSBmb250RmlsZS5kaWN0LmdldCgiTGVuZ3RoMSIpOwogICAgICAgIGxlbmd0aDIgPSBmb250RmlsZS5kaWN0LmdldCgiTGVuZ3RoMiIpOwogICAgICAgIGxlbmd0aDMgPSBmb250RmlsZS5kaWN0LmdldCgiTGVuZ3RoMyIpOwogICAgICB9CiAgICB9IGVsc2UgaWYgKGNzc0ZvbnRJbmZvKSB7CiAgICAgIGNvbnN0IHN0YW5kYXJkRm9udE5hbWUgPSBnZXRYZmFGb250TmFtZShmb250TmFtZS5uYW1lKTsKICAgICAgaWYgKHN0YW5kYXJkRm9udE5hbWUpIHsKICAgICAgICBjc3NGb250SW5mby5mb250RmFtaWx5ID0gYCR7Y3NzRm9udEluZm8uZm9udEZhbWlseX0tUGRmSlMtWEZBYDsKICAgICAgICBjc3NGb250SW5mby5tZXRyaWNzID0gc3RhbmRhcmRGb250TmFtZS5tZXRyaWNzIHx8IG51bGw7CiAgICAgICAgZ2x5cGhTY2FsZUZhY3RvcnMgPSBzdGFuZGFyZEZvbnROYW1lLmZhY3RvcnMgfHwgbnVsbDsKICAgICAgICBmb250RmlsZSA9IGF3YWl0IHRoaXMuZmV0Y2hTdGFuZGFyZEZvbnREYXRhKHN0YW5kYXJkRm9udE5hbWUubmFtZSk7CiAgICAgICAgaXNJbnRlcm5hbEZvbnQgPSAhIWZvbnRGaWxlOwogICAgICAgIGJhc2VEaWN0ID0gZGljdCA9IGdldFhmYUZvbnREaWN0KGZvbnROYW1lLm5hbWUpOwogICAgICAgIGNvbXBvc2l0ZSA9IHRydWU7CiAgICAgIH0KICAgIH0gZWxzZSBpZiAoIWlzVHlwZTNGb250KSB7CiAgICAgIGNvbnN0IHN0YW5kYXJkRm9udE5hbWUgPSBnZXRTdGFuZGFyZEZvbnROYW1lKGZvbnROYW1lLm5hbWUpOwogICAgICBpZiAoc3RhbmRhcmRGb250TmFtZSkgewogICAgICAgIGZvbnRGaWxlID0gYXdhaXQgdGhpcy5mZXRjaFN0YW5kYXJkRm9udERhdGEoc3RhbmRhcmRGb250TmFtZSk7CiAgICAgICAgaXNJbnRlcm5hbEZvbnQgPSAhIWZvbnRGaWxlOwogICAgICB9CiAgICAgIGlmICghaXNJbnRlcm5hbEZvbnQgJiYgdGhpcy5vcHRpb25zLnVzZVN5c3RlbUZvbnRzKSB7CiAgICAgICAgc3lzdGVtRm9udEluZm8gPSBnZXRGb250U3Vic3RpdHV0aW9uKHRoaXMuc3lzdGVtRm9udENhY2hlLCB0aGlzLmlkRmFjdG9yeSwgdGhpcy5vcHRpb25zLnN0YW5kYXJkRm9udERhdGFVcmwsIGZvbnROYW1lLm5hbWUsIHN0YW5kYXJkRm9udE5hbWUsIHR5cGUpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBmb250TWF0cml4ID0gbG9va3VwTWF0cml4KGRpY3QuZ2V0QXJyYXkoIkZvbnRNYXRyaXgiKSwgRk9OVF9JREVOVElUWV9NQVRSSVgpOwogICAgY29uc3QgYmJveCA9IGxvb2t1cE5vcm1hbFJlY3QoZGVzY3JpcHRvci5nZXRBcnJheSgiRm9udEJCb3giKSB8fCBkaWN0LmdldEFycmF5KCJGb250QkJveCIpLCBpc1R5cGUzRm9udCA/IFswLCAwLCAwLCAwXSA6IHVuZGVmaW5lZCk7CiAgICBsZXQgYXNjZW50ID0gZGVzY3JpcHRvci5nZXQoIkFzY2VudCIpOwogICAgaWYgKHR5cGVvZiBhc2NlbnQgIT09ICJudW1iZXIiKSB7CiAgICAgIGFzY2VudCA9IHVuZGVmaW5lZDsKICAgIH0KICAgIGxldCBkZXNjZW50ID0gZGVzY3JpcHRvci5nZXQoIkRlc2NlbnQiKTsKICAgIGlmICh0eXBlb2YgZGVzY2VudCAhPT0gIm51bWJlciIpIHsKICAgICAgZGVzY2VudCA9IHVuZGVmaW5lZDsKICAgIH0KICAgIGxldCB4SGVpZ2h0ID0gZGVzY3JpcHRvci5nZXQoIlhIZWlnaHQiKTsKICAgIGlmICh0eXBlb2YgeEhlaWdodCAhPT0gIm51bWJlciIpIHsKICAgICAgeEhlaWdodCA9IDA7CiAgICB9CiAgICBsZXQgY2FwSGVpZ2h0ID0gZGVzY3JpcHRvci5nZXQoIkNhcEhlaWdodCIpOwogICAgaWYgKHR5cGVvZiBjYXBIZWlnaHQgIT09ICJudW1iZXIiKSB7CiAgICAgIGNhcEhlaWdodCA9IDA7CiAgICB9CiAgICBsZXQgZmxhZ3MgPSBkZXNjcmlwdG9yLmdldCgiRmxhZ3MiKTsKICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihmbGFncykpIHsKICAgICAgZmxhZ3MgPSAwOwogICAgfQogICAgbGV0IGl0YWxpY0FuZ2xlID0gZGVzY3JpcHRvci5nZXQoIkl0YWxpY0FuZ2xlIik7CiAgICBpZiAodHlwZW9mIGl0YWxpY0FuZ2xlICE9PSAibnVtYmVyIikgewogICAgICBpdGFsaWNBbmdsZSA9IDA7CiAgICB9CiAgICBjb25zdCBwcm9wZXJ0aWVzID0gewogICAgICB0eXBlLAogICAgICBuYW1lOiBmb250TmFtZS5uYW1lLAogICAgICBzdWJ0eXBlLAogICAgICBmaWxlOiBmb250RmlsZSwKICAgICAgbGVuZ3RoMSwKICAgICAgbGVuZ3RoMiwKICAgICAgbGVuZ3RoMywKICAgICAgaXNJbnRlcm5hbEZvbnQsCiAgICAgIGxvYWRlZE5hbWU6IGJhc2VEaWN0LmxvYWRlZE5hbWUsCiAgICAgIGNvbXBvc2l0ZSwKICAgICAgZml4ZWRQaXRjaDogZmFsc2UsCiAgICAgIGZvbnRNYXRyaXgsCiAgICAgIGZpcnN0Q2hhciwKICAgICAgbGFzdENoYXIsCiAgICAgIHRvVW5pY29kZSwKICAgICAgYmJveCwKICAgICAgYXNjZW50LAogICAgICBkZXNjZW50LAogICAgICB4SGVpZ2h0LAogICAgICBjYXBIZWlnaHQsCiAgICAgIGZsYWdzLAogICAgICBpdGFsaWNBbmdsZSwKICAgICAgaXNUeXBlM0ZvbnQsCiAgICAgIGNzc0ZvbnRJbmZvLAogICAgICBzY2FsZUZhY3RvcnM6IGdseXBoU2NhbGVGYWN0b3JzLAogICAgICBzeXN0ZW1Gb250SW5mbwogICAgfTsKICAgIGlmIChjb21wb3NpdGUpIHsKICAgICAgY29uc3QgY2lkRW5jb2RpbmcgPSBiYXNlRGljdC5nZXQoIkVuY29kaW5nIik7CiAgICAgIGlmIChjaWRFbmNvZGluZyBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICBwcm9wZXJ0aWVzLmNpZEVuY29kaW5nID0gY2lkRW5jb2RpbmcubmFtZTsKICAgICAgfQogICAgICBjb25zdCBjTWFwID0gYXdhaXQgQ01hcEZhY3RvcnkuY3JlYXRlKHsKICAgICAgICBlbmNvZGluZzogY2lkRW5jb2RpbmcsCiAgICAgICAgZmV0Y2hCdWlsdEluQ01hcDogdGhpcy5fZmV0Y2hCdWlsdEluQ01hcEJvdW5kLAogICAgICAgIHVzZUNNYXA6IG51bGwKICAgICAgfSk7CiAgICAgIHByb3BlcnRpZXMuY01hcCA9IGNNYXA7CiAgICAgIHByb3BlcnRpZXMudmVydGljYWwgPSBwcm9wZXJ0aWVzLmNNYXAudmVydGljYWw7CiAgICB9CiAgICBjb25zdCBuZXdQcm9wZXJ0aWVzID0gYXdhaXQgdGhpcy5leHRyYWN0RGF0YVN0cnVjdHVyZXMoZGljdCwgcHJvcGVydGllcyk7CiAgICB0aGlzLmV4dHJhY3RXaWR0aHMoZGljdCwgZGVzY3JpcHRvciwgbmV3UHJvcGVydGllcyk7CiAgICByZXR1cm4gbmV3IEZvbnQoZm9udE5hbWUubmFtZSwgZm9udEZpbGUsIG5ld1Byb3BlcnRpZXMsIHRoaXMub3B0aW9ucyk7CiAgfQogIHN0YXRpYyBidWlsZEZvbnRQYXRocyhmb250LCBnbHlwaHMsIGhhbmRsZXIsIGV2YWx1YXRvck9wdGlvbnMpIHsKICAgIGZ1bmN0aW9uIGJ1aWxkUGF0aChmb250Q2hhcikgewogICAgICBjb25zdCBnbHlwaE5hbWUgPSBgJHtmb250LmxvYWRlZE5hbWV9X3BhdGhfJHtmb250Q2hhcn1gOwogICAgICB0cnkgewogICAgICAgIGlmIChmb250LnJlbmRlcmVyLmhhc0J1aWx0UGF0aChmb250Q2hhcikpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgaGFuZGxlci5zZW5kKCJjb21tb25vYmoiLCBbZ2x5cGhOYW1lLCAiRm9udFBhdGgiLCBmb250LnJlbmRlcmVyLmdldFBhdGhKcyhmb250Q2hhcildKTsKICAgICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgICAgaWYgKGV2YWx1YXRvck9wdGlvbnMuaWdub3JlRXJyb3JzKSB7CiAgICAgICAgICB3YXJuKGBidWlsZEZvbnRQYXRocyAtIGlnbm9yaW5nICR7Z2x5cGhOYW1lfSBnbHlwaDogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIHRocm93IHJlYXNvbjsKICAgICAgfQogICAgfQogICAgZm9yIChjb25zdCBnbHlwaCBvZiBnbHlwaHMpIHsKICAgICAgYnVpbGRQYXRoKGdseXBoLmZvbnRDaGFyKTsKICAgICAgY29uc3QgYWNjZW50ID0gZ2x5cGguYWNjZW50OwogICAgICBpZiAoYWNjZW50Py5mb250Q2hhcikgewogICAgICAgIGJ1aWxkUGF0aChhY2NlbnQuZm9udENoYXIpOwogICAgICB9CiAgICB9CiAgfQogIHN0YXRpYyBnZXQgZmFsbGJhY2tGb250RGljdCgpIHsKICAgIGNvbnN0IGRpY3QgPSBuZXcgRGljdCgpOwogICAgZGljdC5zZXQoIkJhc2VGb250IiwgTmFtZS5nZXQoIkhlbHZldGljYSIpKTsKICAgIGRpY3Quc2V0KCJUeXBlIiwgTmFtZS5nZXQoIkZhbGxiYWNrVHlwZSIpKTsKICAgIGRpY3Quc2V0KCJTdWJ0eXBlIiwgTmFtZS5nZXQoIkZhbGxiYWNrVHlwZSIpKTsKICAgIGRpY3Quc2V0KCJFbmNvZGluZyIsIE5hbWUuZ2V0KCJXaW5BbnNpRW5jb2RpbmciKSk7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJmYWxsYmFja0ZvbnREaWN0IiwgZGljdCk7CiAgfQp9CmNsYXNzIFRyYW5zbGF0ZWRGb250IHsKICAjc2VudCA9IGZhbHNlOwogICN0eXBlM0xvYWRlZCA9IG51bGw7CiAgY29uc3RydWN0b3IoewogICAgbG9hZGVkTmFtZSwKICAgIGZvbnQsCiAgICBkaWN0CiAgfSkgewogICAgdGhpcy5sb2FkZWROYW1lID0gbG9hZGVkTmFtZTsKICAgIHRoaXMuZm9udCA9IGZvbnQ7CiAgICB0aGlzLmRpY3QgPSBkaWN0OwogICAgdGhpcy50eXBlM0RlcGVuZGVuY2llcyA9IGZvbnQuaXNUeXBlM0ZvbnQgPyBuZXcgU2V0KCkgOiBudWxsOwogIH0KICBzZW5kKGhhbmRsZXIpIHsKICAgIGlmICh0aGlzLiNzZW50KSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuI3NlbnQgPSB0cnVlOwogICAgY29uc3QgZm9udERhdGEgPSB0aGlzLmZvbnQuZXhwb3J0RGF0YSgpOwogICAgY29uc3QgdHJhbnNmZXIgPSBbXTsKICAgIGlmIChmb250RGF0YS5kYXRhKSB7CiAgICAgIGlmIChmb250RGF0YS5kYXRhLmNoYXJQcm9jT3BlcmF0b3JMaXN0KSB7CiAgICAgICAgZm9udERhdGEuY2hhclByb2NPcGVyYXRvckxpc3QgPSBmb250RGF0YS5kYXRhLmNoYXJQcm9jT3BlcmF0b3JMaXN0OwogICAgICB9CiAgICAgIGZvbnREYXRhLmRhdGEgPSBGb250SW5mby53cml0ZShmb250RGF0YS5kYXRhKTsKICAgICAgdHJhbnNmZXIucHVzaChmb250RGF0YS5kYXRhKTsKICAgIH0KICAgIGhhbmRsZXIuc2VuZCgiY29tbW9ub2JqIiwgW3RoaXMubG9hZGVkTmFtZSwgIkZvbnQiLCBmb250RGF0YV0sIHRyYW5zZmVyKTsKICB9CiAgZmFsbGJhY2soaGFuZGxlciwgZXZhbHVhdG9yT3B0aW9ucykgewogICAgaWYgKCF0aGlzLmZvbnQuZGF0YSkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLmZvbnQuZGlzYWJsZUZvbnRGYWNlID0gdHJ1ZTsKICAgIFBhcnRpYWxFdmFsdWF0b3IuYnVpbGRGb250UGF0aHModGhpcy5mb250LCB0aGlzLmZvbnQuZ2x5cGhDYWNoZVZhbHVlcywgaGFuZGxlciwgZXZhbHVhdG9yT3B0aW9ucyk7CiAgfQogIGxvYWRUeXBlM0RhdGEoZXZhbHVhdG9yLCByZXNvdXJjZXMsIHRhc2spIHsKICAgIGlmICh0aGlzLiN0eXBlM0xvYWRlZCkgewogICAgICByZXR1cm4gdGhpcy4jdHlwZTNMb2FkZWQ7CiAgICB9CiAgICBjb25zdCB7CiAgICAgIGZvbnQsCiAgICAgIHR5cGUzRGVwZW5kZW5jaWVzCiAgICB9ID0gdGhpczsKICAgIGFzc2VydChmb250LmlzVHlwZTNGb250LCAiTXVzdCBiZSBhIFR5cGUzIGZvbnQuIik7CiAgICBjb25zdCB0eXBlM0V2YWx1YXRvciA9IGV2YWx1YXRvci5jbG9uZSh7CiAgICAgIGlnbm9yZUVycm9yczogZmFsc2UKICAgIH0pOwogICAgY29uc3QgdHlwZTNGb250UmVmcyA9IG5ldyBSZWZTZXQoZXZhbHVhdG9yLnR5cGUzRm9udFJlZnMpOwogICAgaWYgKHRoaXMuZGljdC5vYmpJZCAmJiAhdHlwZTNGb250UmVmcy5oYXModGhpcy5kaWN0Lm9iaklkKSkgewogICAgICB0eXBlM0ZvbnRSZWZzLnB1dCh0aGlzLmRpY3Qub2JqSWQpOwogICAgfQogICAgdHlwZTNFdmFsdWF0b3IudHlwZTNGb250UmVmcyA9IHR5cGUzRm9udFJlZnM7CiAgICBsZXQgbG9hZENoYXJQcm9jc1Byb21pc2UgPSBQcm9taXNlLnJlc29sdmUoKTsKICAgIGNvbnN0IGNoYXJQcm9jcyA9IHRoaXMuZGljdC5nZXQoIkNoYXJQcm9jcyIpOwogICAgY29uc3QgZm9udFJlc291cmNlcyA9IHRoaXMuZGljdC5nZXQoIlJlc291cmNlcyIpIHx8IHJlc291cmNlczsKICAgIGNvbnN0IGNoYXJQcm9jT3BlcmF0b3JMaXN0ID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGNvbnN0IFt4MCwgeTAsIHgxLCB5MV0gPSBmb250LmJib3gsCiAgICAgIHdpZHRoID0geDEgLSB4MCwKICAgICAgaGVpZ2h0ID0geTEgLSB5MDsKICAgIGNvbnN0IGZvbnRCQm94U2l6ZSA9IE1hdGguaHlwb3Qod2lkdGgsIGhlaWdodCk7CiAgICBmb3IgKGNvbnN0IGtleSBvZiBjaGFyUHJvY3MuZ2V0S2V5cygpKSB7CiAgICAgIGxvYWRDaGFyUHJvY3NQcm9taXNlID0gbG9hZENoYXJQcm9jc1Byb21pc2UudGhlbigoKSA9PiB7CiAgICAgICAgY29uc3QgZ2x5cGhTdHJlYW0gPSBjaGFyUHJvY3MuZ2V0KGtleSk7CiAgICAgICAgY29uc3Qgb3BlcmF0b3JMaXN0ID0gbmV3IE9wZXJhdG9yTGlzdCgpOwogICAgICAgIHJldHVybiB0eXBlM0V2YWx1YXRvci5nZXRPcGVyYXRvckxpc3QoewogICAgICAgICAgc3RyZWFtOiBnbHlwaFN0cmVhbSwKICAgICAgICAgIHRhc2ssCiAgICAgICAgICByZXNvdXJjZXM6IGZvbnRSZXNvdXJjZXMsCiAgICAgICAgICBvcGVyYXRvckxpc3QKICAgICAgICB9KS50aGVuKCgpID0+IHsKICAgICAgICAgIHN3aXRjaCAob3BlcmF0b3JMaXN0LmZuQXJyYXlbMF0pIHsKICAgICAgICAgICAgY2FzZSBPUFMuc2V0Q2hhcldpZHRoQW5kQm91bmRzOgogICAgICAgICAgICAgIHRoaXMuI3JlbW92ZVR5cGUzQ29sb3JPcGVyYXRvcnMob3BlcmF0b3JMaXN0LCBmb250QkJveFNpemUpOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIE9QUy5zZXRDaGFyV2lkdGg6CiAgICAgICAgICAgICAgaWYgKCFmb250QkJveFNpemUpIHsKICAgICAgICAgICAgICAgIHRoaXMuI2d1ZXNzVHlwZTNGb250QkJveChvcGVyYXRvckxpc3QpOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIGNoYXJQcm9jT3BlcmF0b3JMaXN0W2tleV0gPSBvcGVyYXRvckxpc3QuZ2V0SVIoKTsKICAgICAgICAgIGZvciAoY29uc3QgZGVwZW5kZW5jeSBvZiBvcGVyYXRvckxpc3QuZGVwZW5kZW5jaWVzKSB7CiAgICAgICAgICAgIHR5cGUzRGVwZW5kZW5jaWVzLmFkZChkZXBlbmRlbmN5KTsKICAgICAgICAgIH0KICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICB3YXJuKGBUeXBlMyBmb250IHJlc291cmNlICIke2tleX0iIGlzIG5vdCBhdmFpbGFibGUuYCk7CiAgICAgICAgICBjb25zdCBkdW1teU9wZXJhdG9yTGlzdCA9IG5ldyBPcGVyYXRvckxpc3QoKTsKICAgICAgICAgIGNoYXJQcm9jT3BlcmF0b3JMaXN0W2tleV0gPSBkdW1teU9wZXJhdG9yTGlzdC5nZXRJUigpOwogICAgICAgIH0pOwogICAgICB9KTsKICAgIH0KICAgIHRoaXMuI3R5cGUzTG9hZGVkID0gbG9hZENoYXJQcm9jc1Byb21pc2UudGhlbigoKSA9PiB7CiAgICAgIGZvbnQuY2hhclByb2NPcGVyYXRvckxpc3QgPSBjaGFyUHJvY09wZXJhdG9yTGlzdDsKICAgICAgaWYgKHRoaXMuX2Jib3gpIHsKICAgICAgICBmb250LmlzQ2hhckJCb3ggPSB0cnVlOwogICAgICAgIGZvbnQuYmJveCA9IHRoaXMuX2Jib3g7CiAgICAgIH0KICAgIH0pOwogICAgcmV0dXJuIHRoaXMuI3R5cGUzTG9hZGVkOwogIH0KICAjcmVtb3ZlVHlwZTNDb2xvck9wZXJhdG9ycyhvcGVyYXRvckxpc3QsIGZvbnRCQm94U2l6ZSA9IE5hTikgewogICAgY29uc3QgY2hhckJCb3ggPSBVdGlsLm5vcm1hbGl6ZVJlY3Qob3BlcmF0b3JMaXN0LmFyZ3NBcnJheVswXS5zbGljZSgyKSksCiAgICAgIHdpZHRoID0gY2hhckJCb3hbMl0gLSBjaGFyQkJveFswXSwKICAgICAgaGVpZ2h0ID0gY2hhckJCb3hbM10gLSBjaGFyQkJveFsxXTsKICAgIGNvbnN0IGNoYXJCQm94U2l6ZSA9IE1hdGguaHlwb3Qod2lkdGgsIGhlaWdodCk7CiAgICBpZiAod2lkdGggPT09IDAgfHwgaGVpZ2h0ID09PSAwKSB7CiAgICAgIG9wZXJhdG9yTGlzdC5mbkFycmF5LnNwbGljZSgwLCAxKTsKICAgICAgb3BlcmF0b3JMaXN0LmFyZ3NBcnJheS5zcGxpY2UoMCwgMSk7CiAgICB9IGVsc2UgaWYgKGZvbnRCQm94U2l6ZSA9PT0gMCB8fCBNYXRoLnJvdW5kKGNoYXJCQm94U2l6ZSAvIGZvbnRCQm94U2l6ZSkgPj0gMTApIHsKICAgICAgdGhpcy5fYmJveCA/Pz0gW0luZmluaXR5LCBJbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldOwogICAgICBVdGlsLnJlY3RCb3VuZGluZ0JveCguLi5jaGFyQkJveCwgdGhpcy5fYmJveCk7CiAgICB9CiAgICBsZXQgaSA9IDAsCiAgICAgIGlpID0gb3BlcmF0b3JMaXN0Lmxlbmd0aDsKICAgIHdoaWxlIChpIDwgaWkpIHsKICAgICAgc3dpdGNoIChvcGVyYXRvckxpc3QuZm5BcnJheVtpXSkgewogICAgICAgIGNhc2UgT1BTLnNldENoYXJXaWR0aEFuZEJvdW5kczoKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgT1BTLnNldFN0cm9rZUNvbG9yU3BhY2U6CiAgICAgICAgY2FzZSBPUFMuc2V0RmlsbENvbG9yU3BhY2U6CiAgICAgICAgY2FzZSBPUFMuc2V0U3Ryb2tlQ29sb3I6CiAgICAgICAgY2FzZSBPUFMuc2V0U3Ryb2tlQ29sb3JOOgogICAgICAgIGNhc2UgT1BTLnNldEZpbGxDb2xvcjoKICAgICAgICBjYXNlIE9QUy5zZXRGaWxsQ29sb3JOOgogICAgICAgIGNhc2UgT1BTLnNldFN0cm9rZUdyYXk6CiAgICAgICAgY2FzZSBPUFMuc2V0RmlsbEdyYXk6CiAgICAgICAgY2FzZSBPUFMuc2V0U3Ryb2tlUkdCQ29sb3I6CiAgICAgICAgY2FzZSBPUFMuc2V0RmlsbFJHQkNvbG9yOgogICAgICAgIGNhc2UgT1BTLnNldFN0cm9rZUNNWUtDb2xvcjoKICAgICAgICBjYXNlIE9QUy5zZXRGaWxsQ01ZS0NvbG9yOgogICAgICAgIGNhc2UgT1BTLnNoYWRpbmdGaWxsOgogICAgICAgIGNhc2UgT1BTLnNldFJlbmRlcmluZ0ludGVudDoKICAgICAgICAgIG9wZXJhdG9yTGlzdC5mbkFycmF5LnNwbGljZShpLCAxKTsKICAgICAgICAgIG9wZXJhdG9yTGlzdC5hcmdzQXJyYXkuc3BsaWNlKGksIDEpOwogICAgICAgICAgaWktLTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIGNhc2UgT1BTLnNldEdTdGF0ZToKICAgICAgICAgIGNvbnN0IFtnU3RhdGVPYmpdID0gb3BlcmF0b3JMaXN0LmFyZ3NBcnJheVtpXTsKICAgICAgICAgIGxldCBqID0gMCwKICAgICAgICAgICAgamogPSBnU3RhdGVPYmoubGVuZ3RoOwogICAgICAgICAgd2hpbGUgKGogPCBqaikgewogICAgICAgICAgICBjb25zdCBbZ1N0YXRlS2V5XSA9IGdTdGF0ZU9ialtqXTsKICAgICAgICAgICAgc3dpdGNoIChnU3RhdGVLZXkpIHsKICAgICAgICAgICAgICBjYXNlICJUUiI6CiAgICAgICAgICAgICAgY2FzZSAiVFIyIjoKICAgICAgICAgICAgICBjYXNlICJIVCI6CiAgICAgICAgICAgICAgY2FzZSAiQkciOgogICAgICAgICAgICAgIGNhc2UgIkJHMiI6CiAgICAgICAgICAgICAgY2FzZSAiVUNSIjoKICAgICAgICAgICAgICBjYXNlICJVQ1IyIjoKICAgICAgICAgICAgICAgIGdTdGF0ZU9iai5zcGxpY2UoaiwgMSk7CiAgICAgICAgICAgICAgICBqai0tOwogICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaisrOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaSsrOwogICAgfQogIH0KICAjZ3Vlc3NUeXBlM0ZvbnRCQm94KG9wZXJhdG9yTGlzdCkgewogICAgbGV0IGkgPSAxOwogICAgY29uc3QgaWkgPSBvcGVyYXRvckxpc3QubGVuZ3RoOwogICAgd2hpbGUgKGkgPCBpaSkgewogICAgICBzd2l0Y2ggKG9wZXJhdG9yTGlzdC5mbkFycmF5W2ldKSB7CiAgICAgICAgY2FzZSBPUFMuY29uc3RydWN0UGF0aDoKICAgICAgICAgIGNvbnN0IG1pbk1heCA9IG9wZXJhdG9yTGlzdC5hcmdzQXJyYXlbaV1bMl07CiAgICAgICAgICB0aGlzLl9iYm94ID8/PSBbSW5maW5pdHksIEluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV07CiAgICAgICAgICBVdGlsLnJlY3RCb3VuZGluZ0JveCguLi5taW5NYXgsIHRoaXMuX2Jib3gpOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaSsrOwogICAgfQogIH0KfQpjbGFzcyBTdGF0ZU1hbmFnZXIgewogIGNvbnN0cnVjdG9yKGluaXRpYWxTdGF0ZSA9IG5ldyBFdmFsU3RhdGUoKSkgewogICAgdGhpcy5zdGF0ZSA9IGluaXRpYWxTdGF0ZTsKICAgIHRoaXMuc3RhdGVTdGFjayA9IFtdOwogIH0KICBzYXZlKCkgewogICAgY29uc3Qgb2xkID0gdGhpcy5zdGF0ZTsKICAgIHRoaXMuc3RhdGVTdGFjay5wdXNoKHRoaXMuc3RhdGUpOwogICAgdGhpcy5zdGF0ZSA9IG9sZC5jbG9uZSgpOwogIH0KICByZXN0b3JlKCkgewogICAgY29uc3QgcHJldiA9IHRoaXMuc3RhdGVTdGFjay5wb3AoKTsKICAgIGlmIChwcmV2KSB7CiAgICAgIHRoaXMuc3RhdGUgPSBwcmV2OwogICAgfQogIH0KICB0cmFuc2Zvcm0oYXJncykgewogICAgdGhpcy5zdGF0ZS5jdG0gPSBVdGlsLnRyYW5zZm9ybSh0aGlzLnN0YXRlLmN0bSwgYXJncyk7CiAgfQp9CmNsYXNzIFRleHRTdGF0ZSB7CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLmN0bSA9IG5ldyBGbG9hdDMyQXJyYXkoSURFTlRJVFlfTUFUUklYKTsKICAgIHRoaXMuZm9udE5hbWUgPSBudWxsOwogICAgdGhpcy5mb250U2l6ZSA9IDA7CiAgICB0aGlzLmxvYWRlZE5hbWUgPSBudWxsOwogICAgdGhpcy5mb250ID0gbnVsbDsKICAgIHRoaXMuZm9udE1hdHJpeCA9IEZPTlRfSURFTlRJVFlfTUFUUklYOwogICAgdGhpcy50ZXh0TWF0cml4ID0gSURFTlRJVFlfTUFUUklYLnNsaWNlKCk7CiAgICB0aGlzLnRleHRMaW5lTWF0cml4ID0gSURFTlRJVFlfTUFUUklYLnNsaWNlKCk7CiAgICB0aGlzLmNoYXJTcGFjaW5nID0gMDsKICAgIHRoaXMud29yZFNwYWNpbmcgPSAwOwogICAgdGhpcy5sZWFkaW5nID0gMDsKICAgIHRoaXMudGV4dEhTY2FsZSA9IDE7CiAgICB0aGlzLnRleHRSaXNlID0gMDsKICB9CiAgc2V0VGV4dE1hdHJpeChhLCBiLCBjLCBkLCBlLCBmKSB7CiAgICBjb25zdCBtID0gdGhpcy50ZXh0TWF0cml4OwogICAgbVswXSA9IGE7CiAgICBtWzFdID0gYjsKICAgIG1bMl0gPSBjOwogICAgbVszXSA9IGQ7CiAgICBtWzRdID0gZTsKICAgIG1bNV0gPSBmOwogIH0KICBzZXRUZXh0TGluZU1hdHJpeChhLCBiLCBjLCBkLCBlLCBmKSB7CiAgICBjb25zdCBtID0gdGhpcy50ZXh0TGluZU1hdHJpeDsKICAgIG1bMF0gPSBhOwogICAgbVsxXSA9IGI7CiAgICBtWzJdID0gYzsKICAgIG1bM10gPSBkOwogICAgbVs0XSA9IGU7CiAgICBtWzVdID0gZjsKICB9CiAgdHJhbnNsYXRlVGV4dE1hdHJpeCh4LCB5KSB7CiAgICBjb25zdCBtID0gdGhpcy50ZXh0TWF0cml4OwogICAgbVs0XSA9IG1bMF0gKiB4ICsgbVsyXSAqIHkgKyBtWzRdOwogICAgbVs1XSA9IG1bMV0gKiB4ICsgbVszXSAqIHkgKyBtWzVdOwogIH0KICB0cmFuc2xhdGVUZXh0TGluZU1hdHJpeCh4LCB5KSB7CiAgICBjb25zdCBtID0gdGhpcy50ZXh0TGluZU1hdHJpeDsKICAgIG1bNF0gPSBtWzBdICogeCArIG1bMl0gKiB5ICsgbVs0XTsKICAgIG1bNV0gPSBtWzFdICogeCArIG1bM10gKiB5ICsgbVs1XTsKICB9CiAgY2FycmlhZ2VSZXR1cm4oKSB7CiAgICB0aGlzLnRyYW5zbGF0ZVRleHRMaW5lTWF0cml4KDAsIC10aGlzLmxlYWRpbmcpOwogICAgdGhpcy50ZXh0TWF0cml4ID0gdGhpcy50ZXh0TGluZU1hdHJpeC5zbGljZSgpOwogIH0KICBjbG9uZSgpIHsKICAgIGNvbnN0IGNsb25lID0gT2JqZWN0LmNyZWF0ZSh0aGlzKTsKICAgIGNsb25lLnRleHRNYXRyaXggPSB0aGlzLnRleHRNYXRyaXguc2xpY2UoKTsKICAgIGNsb25lLnRleHRMaW5lTWF0cml4ID0gdGhpcy50ZXh0TGluZU1hdHJpeC5zbGljZSgpOwogICAgY2xvbmUuZm9udE1hdHJpeCA9IHRoaXMuZm9udE1hdHJpeC5zbGljZSgpOwogICAgcmV0dXJuIGNsb25lOwogIH0KfQpjbGFzcyBFdmFsU3RhdGUgewogIGNvbnN0cnVjdG9yKCkgewogICAgdGhpcy5jdG0gPSBuZXcgRmxvYXQzMkFycmF5KElERU5USVRZX01BVFJJWCk7CiAgICB0aGlzLmZvbnQgPSBudWxsOwogICAgdGhpcy50ZXh0UmVuZGVyaW5nTW9kZSA9IFRleHRSZW5kZXJpbmdNb2RlLkZJTEw7CiAgICB0aGlzLl9maWxsQ29sb3JTcGFjZSA9IHRoaXMuX3N0cm9rZUNvbG9yU3BhY2UgPSBDb2xvclNwYWNlVXRpbHMuZ3JheTsKICAgIHRoaXMucGF0dGVybkZpbGxDb2xvclNwYWNlID0gbnVsbDsKICAgIHRoaXMucGF0dGVyblN0cm9rZUNvbG9yU3BhY2UgPSBudWxsOwogICAgdGhpcy5jdXJyZW50UG9pbnRYID0gdGhpcy5jdXJyZW50UG9pbnRZID0gMDsKICAgIHRoaXMucGF0aE1pbk1heCA9IG5ldyBGbG9hdDMyQXJyYXkoW0luZmluaXR5LCBJbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldKTsKICAgIHRoaXMucGF0aEJ1ZmZlciA9IFtdOwogIH0KICBnZXQgZmlsbENvbG9yU3BhY2UoKSB7CiAgICByZXR1cm4gdGhpcy5fZmlsbENvbG9yU3BhY2U7CiAgfQogIHNldCBmaWxsQ29sb3JTcGFjZShjb2xvclNwYWNlKSB7CiAgICB0aGlzLl9maWxsQ29sb3JTcGFjZSA9IHRoaXMucGF0dGVybkZpbGxDb2xvclNwYWNlID0gY29sb3JTcGFjZTsKICB9CiAgZ2V0IHN0cm9rZUNvbG9yU3BhY2UoKSB7CiAgICByZXR1cm4gdGhpcy5fc3Ryb2tlQ29sb3JTcGFjZTsKICB9CiAgc2V0IHN0cm9rZUNvbG9yU3BhY2UoY29sb3JTcGFjZSkgewogICAgdGhpcy5fc3Ryb2tlQ29sb3JTcGFjZSA9IHRoaXMucGF0dGVyblN0cm9rZUNvbG9yU3BhY2UgPSBjb2xvclNwYWNlOwogIH0KICBjbG9uZSh7CiAgICBuZXdQYXRoID0gZmFsc2UKICB9ID0ge30pIHsKICAgIGNvbnN0IGNsb25lID0gT2JqZWN0LmNyZWF0ZSh0aGlzKTsKICAgIGlmIChuZXdQYXRoKSB7CiAgICAgIGNsb25lLnBhdGhCdWZmZXIgPSBbXTsKICAgICAgY2xvbmUucGF0aE1pbk1heCA9IG5ldyBGbG9hdDMyQXJyYXkoW0luZmluaXR5LCBJbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldKTsKICAgIH0KICAgIHJldHVybiBjbG9uZTsKICB9Cn0KY2xhc3MgRXZhbHVhdG9yUHJlcHJvY2Vzc29yIHsKICBzdGF0aWMgZ2V0IG9wTWFwKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAib3BNYXAiLCBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobnVsbCksIHsKICAgICAgdzogewogICAgICAgIGlkOiBPUFMuc2V0TGluZVdpZHRoLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBKOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRMaW5lQ2FwLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBqOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRMaW5lSm9pbiwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgTTogewogICAgICAgIGlkOiBPUFMuc2V0TWl0ZXJMaW1pdCwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgZDogewogICAgICAgIGlkOiBPUFMuc2V0RGFzaCwKICAgICAgICBudW1BcmdzOiAyLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgcmk6IHsKICAgICAgICBpZDogT1BTLnNldFJlbmRlcmluZ0ludGVudCwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgaTogewogICAgICAgIGlkOiBPUFMuc2V0RmxhdG5lc3MsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIGdzOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRHU3RhdGUsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIHE6IHsKICAgICAgICBpZDogT1BTLnNhdmUsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIFE6IHsKICAgICAgICBpZDogT1BTLnJlc3RvcmUsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIGNtOiB7CiAgICAgICAgaWQ6IE9QUy50cmFuc2Zvcm0sCiAgICAgICAgbnVtQXJnczogNiwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIG06IHsKICAgICAgICBpZDogT1BTLm1vdmVUbywKICAgICAgICBudW1BcmdzOiAyLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgbDogewogICAgICAgIGlkOiBPUFMubGluZVRvLAogICAgICAgIG51bUFyZ3M6IDIsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBjOiB7CiAgICAgICAgaWQ6IE9QUy5jdXJ2ZVRvLAogICAgICAgIG51bUFyZ3M6IDYsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICB2OiB7CiAgICAgICAgaWQ6IE9QUy5jdXJ2ZVRvMiwKICAgICAgICBudW1BcmdzOiA0LAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgeTogewogICAgICAgIGlkOiBPUFMuY3VydmVUbzMsCiAgICAgICAgbnVtQXJnczogNCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIGg6IHsKICAgICAgICBpZDogT1BTLmNsb3NlUGF0aCwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgcmU6IHsKICAgICAgICBpZDogT1BTLnJlY3RhbmdsZSwKICAgICAgICBudW1BcmdzOiA0LAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgUzogewogICAgICAgIGlkOiBPUFMuc3Ryb2tlLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBzOiB7CiAgICAgICAgaWQ6IE9QUy5jbG9zZVN0cm9rZSwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgZjogewogICAgICAgIGlkOiBPUFMuZmlsbCwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgRjogewogICAgICAgIGlkOiBPUFMuZmlsbCwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgImYqIjogewogICAgICAgIGlkOiBPUFMuZW9GaWxsLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBCOiB7CiAgICAgICAgaWQ6IE9QUy5maWxsU3Ryb2tlLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICAiQioiOiB7CiAgICAgICAgaWQ6IE9QUy5lb0ZpbGxTdHJva2UsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIGI6IHsKICAgICAgICBpZDogT1BTLmNsb3NlRmlsbFN0cm9rZSwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgImIqIjogewogICAgICAgIGlkOiBPUFMuY2xvc2VFT0ZpbGxTdHJva2UsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIG46IHsKICAgICAgICBpZDogT1BTLmVuZFBhdGgsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIFc6IHsKICAgICAgICBpZDogT1BTLmNsaXAsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgICJXKiI6IHsKICAgICAgICBpZDogT1BTLmVvQ2xpcCwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgQlQ6IHsKICAgICAgICBpZDogT1BTLmJlZ2luVGV4dCwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgRVQ6IHsKICAgICAgICBpZDogT1BTLmVuZFRleHQsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIFRjOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRDaGFyU3BhY2luZywKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgVHc6IHsKICAgICAgICBpZDogT1BTLnNldFdvcmRTcGFjaW5nLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBUejogewogICAgICAgIGlkOiBPUFMuc2V0SFNjYWxlLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBUTDogewogICAgICAgIGlkOiBPUFMuc2V0TGVhZGluZywKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgVGY6IHsKICAgICAgICBpZDogT1BTLnNldEZvbnQsCiAgICAgICAgbnVtQXJnczogMiwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIFRyOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRUZXh0UmVuZGVyaW5nTW9kZSwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgVHM6IHsKICAgICAgICBpZDogT1BTLnNldFRleHRSaXNlLAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBUZDogewogICAgICAgIGlkOiBPUFMubW92ZVRleHQsCiAgICAgICAgbnVtQXJnczogMiwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIFREOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRMZWFkaW5nTW92ZVRleHQsCiAgICAgICAgbnVtQXJnczogMiwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIFRtOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRUZXh0TWF0cml4LAogICAgICAgIG51bUFyZ3M6IDYsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICAiVCoiOiB7CiAgICAgICAgaWQ6IE9QUy5uZXh0TGluZSwKICAgICAgICBudW1BcmdzOiAwLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgVGo6IHsKICAgICAgICBpZDogT1BTLnNob3dUZXh0LAogICAgICAgIG51bUFyZ3M6IDEsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBUSjogewogICAgICAgIGlkOiBPUFMuc2hvd1NwYWNlZFRleHQsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgICInIjogewogICAgICAgIGlkOiBPUFMubmV4dExpbmVTaG93VGV4dCwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgJyInOiB7CiAgICAgICAgaWQ6IE9QUy5uZXh0TGluZVNldFNwYWNpbmdTaG93VGV4dCwKICAgICAgICBudW1BcmdzOiAzLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgZDA6IHsKICAgICAgICBpZDogT1BTLnNldENoYXJXaWR0aCwKICAgICAgICBudW1BcmdzOiAyLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgZDE6IHsKICAgICAgICBpZDogT1BTLnNldENoYXJXaWR0aEFuZEJvdW5kcywKICAgICAgICBudW1BcmdzOiA2LAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgQ1M6IHsKICAgICAgICBpZDogT1BTLnNldFN0cm9rZUNvbG9yU3BhY2UsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIGNzOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRGaWxsQ29sb3JTcGFjZSwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgU0M6IHsKICAgICAgICBpZDogT1BTLnNldFN0cm9rZUNvbG9yLAogICAgICAgIG51bUFyZ3M6IDQsCiAgICAgICAgdmFyaWFibGVBcmdzOiB0cnVlCiAgICAgIH0sCiAgICAgIFNDTjogewogICAgICAgIGlkOiBPUFMuc2V0U3Ryb2tlQ29sb3JOLAogICAgICAgIG51bUFyZ3M6IDMzLAogICAgICAgIHZhcmlhYmxlQXJnczogdHJ1ZQogICAgICB9LAogICAgICBzYzogewogICAgICAgIGlkOiBPUFMuc2V0RmlsbENvbG9yLAogICAgICAgIG51bUFyZ3M6IDQsCiAgICAgICAgdmFyaWFibGVBcmdzOiB0cnVlCiAgICAgIH0sCiAgICAgIHNjbjogewogICAgICAgIGlkOiBPUFMuc2V0RmlsbENvbG9yTiwKICAgICAgICBudW1BcmdzOiAzMywKICAgICAgICB2YXJpYWJsZUFyZ3M6IHRydWUKICAgICAgfSwKICAgICAgRzogewogICAgICAgIGlkOiBPUFMuc2V0U3Ryb2tlR3JheSwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgZzogewogICAgICAgIGlkOiBPUFMuc2V0RmlsbEdyYXksCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIFJHOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRTdHJva2VSR0JDb2xvciwKICAgICAgICBudW1BcmdzOiAzLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgcmc6IHsKICAgICAgICBpZDogT1BTLnNldEZpbGxSR0JDb2xvciwKICAgICAgICBudW1BcmdzOiAzLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgSzogewogICAgICAgIGlkOiBPUFMuc2V0U3Ryb2tlQ01ZS0NvbG9yLAogICAgICAgIG51bUFyZ3M6IDQsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBrOiB7CiAgICAgICAgaWQ6IE9QUy5zZXRGaWxsQ01ZS0NvbG9yLAogICAgICAgIG51bUFyZ3M6IDQsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBzaDogewogICAgICAgIGlkOiBPUFMuc2hhZGluZ0ZpbGwsCiAgICAgICAgbnVtQXJnczogMSwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIEJJOiB7CiAgICAgICAgaWQ6IE9QUy5iZWdpbklubGluZUltYWdlLAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBJRDogewogICAgICAgIGlkOiBPUFMuYmVnaW5JbWFnZURhdGEsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIEVJOiB7CiAgICAgICAgaWQ6IE9QUy5lbmRJbmxpbmVJbWFnZSwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgRG86IHsKICAgICAgICBpZDogT1BTLnBhaW50WE9iamVjdCwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgTVA6IHsKICAgICAgICBpZDogT1BTLm1hcmtQb2ludCwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgRFA6IHsKICAgICAgICBpZDogT1BTLm1hcmtQb2ludFByb3BzLAogICAgICAgIG51bUFyZ3M6IDIsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBCTUM6IHsKICAgICAgICBpZDogT1BTLmJlZ2luTWFya2VkQ29udGVudCwKICAgICAgICBudW1BcmdzOiAxLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgQkRDOiB7CiAgICAgICAgaWQ6IE9QUy5iZWdpbk1hcmtlZENvbnRlbnRQcm9wcywKICAgICAgICBudW1BcmdzOiAyLAogICAgICAgIHZhcmlhYmxlQXJnczogZmFsc2UKICAgICAgfSwKICAgICAgRU1DOiB7CiAgICAgICAgaWQ6IE9QUy5lbmRNYXJrZWRDb250ZW50LAogICAgICAgIG51bUFyZ3M6IDAsCiAgICAgICAgdmFyaWFibGVBcmdzOiBmYWxzZQogICAgICB9LAogICAgICBCWDogewogICAgICAgIGlkOiBPUFMuYmVnaW5Db21wYXQsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIEVYOiB7CiAgICAgICAgaWQ6IE9QUy5lbmRDb21wYXQsCiAgICAgICAgbnVtQXJnczogMCwKICAgICAgICB2YXJpYWJsZUFyZ3M6IGZhbHNlCiAgICAgIH0sCiAgICAgIEJNOiBudWxsLAogICAgICBCRDogbnVsbCwKICAgICAgdHJ1ZTogbnVsbCwKICAgICAgZmE6IG51bGwsCiAgICAgIGZhbDogbnVsbCwKICAgICAgZmFsczogbnVsbCwKICAgICAgZmFsc2U6IG51bGwsCiAgICAgIG51OiBudWxsLAogICAgICBudWw6IG51bGwsCiAgICAgIG51bGw6IG51bGwKICAgIH0pKTsKICB9CiAgc3RhdGljIE1BWF9JTlZBTElEX1BBVEhfT1BTID0gMTA7CiAgY29uc3RydWN0b3Ioc3RyZWFtLCB4cmVmLCBzdGF0ZU1hbmFnZXIgPSBuZXcgU3RhdGVNYW5hZ2VyKCkpIHsKICAgIHRoaXMucGFyc2VyID0gbmV3IFBhcnNlcih7CiAgICAgIGxleGVyOiBuZXcgTGV4ZXIoc3RyZWFtLCBFdmFsdWF0b3JQcmVwcm9jZXNzb3Iub3BNYXApLAogICAgICB4cmVmCiAgICB9KTsKICAgIHRoaXMuc3RhdGVNYW5hZ2VyID0gc3RhdGVNYW5hZ2VyOwogICAgdGhpcy5ub25Qcm9jZXNzZWRBcmdzID0gW107CiAgICB0aGlzLl9pc1BhdGhPcCA9IGZhbHNlOwogICAgdGhpcy5fbnVtSW52YWxpZFBhdGhPUFMgPSAwOwogIH0KICBnZXQgc2F2ZWRTdGF0ZXNEZXB0aCgpIHsKICAgIHJldHVybiB0aGlzLnN0YXRlTWFuYWdlci5zdGF0ZVN0YWNrLmxlbmd0aDsKICB9CiAgcmVhZChvcGVyYXRpb24pIHsKICAgIGxldCBhcmdzID0gb3BlcmF0aW9uLmFyZ3M7CiAgICB3aGlsZSAodHJ1ZSkgewogICAgICBjb25zdCBvYmogPSB0aGlzLnBhcnNlci5nZXRPYmooKTsKICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIENtZCkgewogICAgICAgIGNvbnN0IGNtZCA9IG9iai5jbWQ7CiAgICAgICAgY29uc3Qgb3BTcGVjID0gRXZhbHVhdG9yUHJlcHJvY2Vzc29yLm9wTWFwW2NtZF07CiAgICAgICAgaWYgKCFvcFNwZWMpIHsKICAgICAgICAgIHdhcm4oYFVua25vd24gY29tbWFuZCAiJHtjbWR9Ii5gKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBmbiA9IG9wU3BlYy5pZDsKICAgICAgICBjb25zdCBudW1BcmdzID0gb3BTcGVjLm51bUFyZ3M7CiAgICAgICAgbGV0IGFyZ3NMZW5ndGggPSBhcmdzICE9PSBudWxsID8gYXJncy5sZW5ndGggOiAwOwogICAgICAgIGlmICghdGhpcy5faXNQYXRoT3ApIHsKICAgICAgICAgIHRoaXMuX251bUludmFsaWRQYXRoT1BTID0gMDsKICAgICAgICB9CiAgICAgICAgdGhpcy5faXNQYXRoT3AgPSBmbiA+PSBPUFMubW92ZVRvICYmIGZuIDw9IE9QUy5lbmRQYXRoOwogICAgICAgIGlmICghb3BTcGVjLnZhcmlhYmxlQXJncykgewogICAgICAgICAgaWYgKGFyZ3NMZW5ndGggIT09IG51bUFyZ3MpIHsKICAgICAgICAgICAgY29uc3Qgbm9uUHJvY2Vzc2VkQXJncyA9IHRoaXMubm9uUHJvY2Vzc2VkQXJnczsKICAgICAgICAgICAgd2hpbGUgKGFyZ3NMZW5ndGggPiBudW1BcmdzKSB7CiAgICAgICAgICAgICAgbm9uUHJvY2Vzc2VkQXJncy5wdXNoKGFyZ3Muc2hpZnQoKSk7CiAgICAgICAgICAgICAgYXJnc0xlbmd0aC0tOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHdoaWxlIChhcmdzTGVuZ3RoIDwgbnVtQXJncyAmJiBub25Qcm9jZXNzZWRBcmdzLmxlbmd0aCAhPT0gMCkgewogICAgICAgICAgICAgIGlmIChhcmdzID09PSBudWxsKSB7CiAgICAgICAgICAgICAgICBhcmdzID0gW107CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGFyZ3MudW5zaGlmdChub25Qcm9jZXNzZWRBcmdzLnBvcCgpKTsKICAgICAgICAgICAgICBhcmdzTGVuZ3RoKys7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChhcmdzTGVuZ3RoIDwgbnVtQXJncykgewogICAgICAgICAgICBjb25zdCBwYXJ0aWFsTXNnID0gYGNvbW1hbmQgJHtjbWR9OiBleHBlY3RlZCAke251bUFyZ3N9IGFyZ3MsIGAgKyBgYnV0IHJlY2VpdmVkICR7YXJnc0xlbmd0aH0gYXJncy5gOwogICAgICAgICAgICBpZiAodGhpcy5faXNQYXRoT3AgJiYgKyt0aGlzLl9udW1JbnZhbGlkUGF0aE9QUyA+IEV2YWx1YXRvclByZXByb2Nlc3Nvci5NQVhfSU5WQUxJRF9QQVRIX09QUykgewogICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgSW52YWxpZCAke3BhcnRpYWxNc2d9YCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgd2FybihgU2tpcHBpbmcgJHtwYXJ0aWFsTXNnfWApOwogICAgICAgICAgICBpZiAoYXJncyAhPT0gbnVsbCkgewogICAgICAgICAgICAgIGFyZ3MubGVuZ3RoID0gMDsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGFyZ3NMZW5ndGggPiBudW1BcmdzKSB7CiAgICAgICAgICBpbmZvKGBDb21tYW5kICR7Y21kfTogZXhwZWN0ZWQgWzAsICR7bnVtQXJnc31dIGFyZ3MsIGAgKyBgYnV0IHJlY2VpdmVkICR7YXJnc0xlbmd0aH0gYXJncy5gKTsKICAgICAgICB9CiAgICAgICAgdGhpcy5wcmVwcm9jZXNzQ29tbWFuZChmbiwgYXJncyk7CiAgICAgICAgb3BlcmF0aW9uLmZuID0gZm47CiAgICAgICAgb3BlcmF0aW9uLmFyZ3MgPSBhcmdzOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmIChvYmogPT09IEVPRikgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAob2JqICE9PSBudWxsKSB7CiAgICAgICAgaWYgKGFyZ3MgPT09IG51bGwpIHsKICAgICAgICAgIGFyZ3MgPSBbXTsKICAgICAgICB9CiAgICAgICAgYXJncy5wdXNoKG9iaik7CiAgICAgICAgaWYgKGFyZ3MubGVuZ3RoID4gMzMpIHsKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiVG9vIG1hbnkgYXJndW1lbnRzIik7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQogIHByZXByb2Nlc3NDb21tYW5kKGZuLCBhcmdzKSB7CiAgICBzd2l0Y2ggKGZuIHwgMCkgewogICAgICBjYXNlIE9QUy5zYXZlOgogICAgICAgIHRoaXMuc3RhdGVNYW5hZ2VyLnNhdmUoKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBPUFMucmVzdG9yZToKICAgICAgICB0aGlzLnN0YXRlTWFuYWdlci5yZXN0b3JlKCk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgT1BTLnRyYW5zZm9ybToKICAgICAgICB0aGlzLnN0YXRlTWFuYWdlci50cmFuc2Zvcm0oYXJncyk7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9kZWZhdWx0X2FwcGVhcmFuY2UuanMKCgoKCgoKCgoKCgoKCmNsYXNzIERlZmF1bHRBcHBlYXJhbmNlRXZhbHVhdG9yIGV4dGVuZHMgRXZhbHVhdG9yUHJlcHJvY2Vzc29yIHsKICBjb25zdHJ1Y3RvcihzdHIpIHsKICAgIHN1cGVyKG5ldyBTdHJpbmdTdHJlYW0oc3RyKSk7CiAgfQogIHBhcnNlKCkgewogICAgY29uc3Qgb3BlcmF0aW9uID0gewogICAgICBmbjogMCwKICAgICAgYXJnczogW10KICAgIH07CiAgICBjb25zdCByZXN1bHQgPSB7CiAgICAgIGZvbnRTaXplOiAwLAogICAgICBmb250TmFtZTogIiIsCiAgICAgIGZvbnRDb2xvcjogbmV3IFVpbnQ4Q2xhbXBlZEFycmF5KDMpCiAgICB9OwogICAgdHJ5IHsKICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICBvcGVyYXRpb24uYXJncy5sZW5ndGggPSAwOwogICAgICAgIGlmICghdGhpcy5yZWFkKG9wZXJhdGlvbikpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBpZiAodGhpcy5zYXZlZFN0YXRlc0RlcHRoICE9PSAwKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY29uc3QgewogICAgICAgICAgZm4sCiAgICAgICAgICBhcmdzCiAgICAgICAgfSA9IG9wZXJhdGlvbjsKICAgICAgICBzd2l0Y2ggKGZuIHwgMCkgewogICAgICAgICAgY2FzZSBPUFMuc2V0Rm9udDoKICAgICAgICAgICAgY29uc3QgW2ZvbnROYW1lLCBmb250U2l6ZV0gPSBhcmdzOwogICAgICAgICAgICBpZiAoZm9udE5hbWUgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgICAgcmVzdWx0LmZvbnROYW1lID0gZm9udE5hbWUubmFtZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAodHlwZW9mIGZvbnRTaXplID09PSAibnVtYmVyIiAmJiBmb250U2l6ZSA+IDApIHsKICAgICAgICAgICAgICByZXN1bHQuZm9udFNpemUgPSBmb250U2l6ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldEZpbGxSR0JDb2xvcjoKICAgICAgICAgICAgQ29sb3JTcGFjZVV0aWxzLnJnYi5nZXRSZ2JJdGVtKGFyZ3MsIDAsIHJlc3VsdC5mb250Q29sb3IsIDApOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldEZpbGxHcmF5OgogICAgICAgICAgICBDb2xvclNwYWNlVXRpbHMuZ3JheS5nZXRSZ2JJdGVtKGFyZ3MsIDAsIHJlc3VsdC5mb250Q29sb3IsIDApOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNldEZpbGxDTVlLQ29sb3I6CiAgICAgICAgICAgIENvbG9yU3BhY2VVdGlscy5jbXlrLmdldFJnYkl0ZW0oYXJncywgMCwgcmVzdWx0LmZvbnRDb2xvciwgMCk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgIHdhcm4oYHBhcnNlRGVmYXVsdEFwcGVhcmFuY2UgLSBpZ25vcmluZyBlcnJvcnM6ICIke3JlYXNvbn0iLmApOwogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKICB9Cn0KZnVuY3Rpb24gcGFyc2VEZWZhdWx0QXBwZWFyYW5jZShzdHIpIHsKICByZXR1cm4gbmV3IERlZmF1bHRBcHBlYXJhbmNlRXZhbHVhdG9yKHN0cikucGFyc2UoKTsKfQpjbGFzcyBBcHBlYXJhbmNlU3RyZWFtRXZhbHVhdG9yIGV4dGVuZHMgRXZhbHVhdG9yUHJlcHJvY2Vzc29yIHsKICBjb25zdHJ1Y3RvcihzdHJlYW0sIGV2YWx1YXRvck9wdGlvbnMsIHhyZWYsIGdsb2JhbENvbG9yU3BhY2VDYWNoZSkgewogICAgc3VwZXIoc3RyZWFtKTsKICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtOwogICAgdGhpcy5ldmFsdWF0b3JPcHRpb25zID0gZXZhbHVhdG9yT3B0aW9uczsKICAgIHRoaXMueHJlZiA9IHhyZWY7CiAgICB0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSA9IGdsb2JhbENvbG9yU3BhY2VDYWNoZTsKICAgIHRoaXMucmVzb3VyY2VzID0gc3RyZWFtLmRpY3Q/LmdldCgiUmVzb3VyY2VzIik7CiAgfQogIHBhcnNlKCkgewogICAgY29uc3Qgb3BlcmF0aW9uID0gewogICAgICBmbjogMCwKICAgICAgYXJnczogW10KICAgIH07CiAgICBsZXQgcmVzdWx0ID0gewogICAgICBzY2FsZUZhY3RvcjogMSwKICAgICAgZm9udFNpemU6IDAsCiAgICAgIGZvbnROYW1lOiAiIiwKICAgICAgZm9udENvbG9yOiBuZXcgVWludDhDbGFtcGVkQXJyYXkoMyksCiAgICAgIGZpbGxDb2xvclNwYWNlOiBDb2xvclNwYWNlVXRpbHMuZ3JheQogICAgfTsKICAgIGxldCBicmVha0xvb3AgPSBmYWxzZTsKICAgIGNvbnN0IHN0YWNrID0gW107CiAgICB0cnkgewogICAgICB3aGlsZSAodHJ1ZSkgewogICAgICAgIG9wZXJhdGlvbi5hcmdzLmxlbmd0aCA9IDA7CiAgICAgICAgaWYgKGJyZWFrTG9vcCB8fCAhdGhpcy5yZWFkKG9wZXJhdGlvbikpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBjb25zdCB7CiAgICAgICAgICBmbiwKICAgICAgICAgIGFyZ3MKICAgICAgICB9ID0gb3BlcmF0aW9uOwogICAgICAgIHN3aXRjaCAoZm4gfCAwKSB7CiAgICAgICAgICBjYXNlIE9QUy5zYXZlOgogICAgICAgICAgICBzdGFjay5wdXNoKHsKICAgICAgICAgICAgICBzY2FsZUZhY3RvcjogcmVzdWx0LnNjYWxlRmFjdG9yLAogICAgICAgICAgICAgIGZvbnRTaXplOiByZXN1bHQuZm9udFNpemUsCiAgICAgICAgICAgICAgZm9udE5hbWU6IHJlc3VsdC5mb250TmFtZSwKICAgICAgICAgICAgICBmb250Q29sb3I6IHJlc3VsdC5mb250Q29sb3Iuc2xpY2UoKSwKICAgICAgICAgICAgICBmaWxsQ29sb3JTcGFjZTogcmVzdWx0LmZpbGxDb2xvclNwYWNlCiAgICAgICAgICAgIH0pOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnJlc3RvcmU6CiAgICAgICAgICAgIHJlc3VsdCA9IHN0YWNrLnBvcCgpIHx8IHJlc3VsdDsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRUZXh0TWF0cml4OgogICAgICAgICAgICByZXN1bHQuc2NhbGVGYWN0b3IgKj0gTWF0aC5oeXBvdChhcmdzWzBdLCBhcmdzWzFdKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRGb250OgogICAgICAgICAgICBjb25zdCBbZm9udE5hbWUsIGZvbnRTaXplXSA9IGFyZ3M7CiAgICAgICAgICAgIGlmIChmb250TmFtZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICAgICAgICByZXN1bHQuZm9udE5hbWUgPSBmb250TmFtZS5uYW1lOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmICh0eXBlb2YgZm9udFNpemUgPT09ICJudW1iZXIiICYmIGZvbnRTaXplID4gMCkgewogICAgICAgICAgICAgIHJlc3VsdC5mb250U2l6ZSA9IGZvbnRTaXplICogcmVzdWx0LnNjYWxlRmFjdG9yOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0RmlsbENvbG9yU3BhY2U6CiAgICAgICAgICAgIHJlc3VsdC5maWxsQ29sb3JTcGFjZSA9IENvbG9yU3BhY2VVdGlscy5wYXJzZSh7CiAgICAgICAgICAgICAgY3M6IGFyZ3NbMF0sCiAgICAgICAgICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICAgICAgICAgIHJlc291cmNlczogdGhpcy5yZXNvdXJjZXMsCiAgICAgICAgICAgICAgcGRmRnVuY3Rpb25GYWN0b3J5OiB0aGlzLl9wZGZGdW5jdGlvbkZhY3RvcnksCiAgICAgICAgICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOiB0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgICAgICAgICAgICBsb2NhbENvbG9yU3BhY2VDYWNoZTogdGhpcy5fbG9jYWxDb2xvclNwYWNlQ2FjaGUKICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBPUFMuc2V0RmlsbENvbG9yOgogICAgICAgICAgICBjb25zdCBjcyA9IHJlc3VsdC5maWxsQ29sb3JTcGFjZTsKICAgICAgICAgICAgY3MuZ2V0UmdiSXRlbShhcmdzLCAwLCByZXN1bHQuZm9udENvbG9yLCAwKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRGaWxsUkdCQ29sb3I6CiAgICAgICAgICAgIENvbG9yU3BhY2VVdGlscy5yZ2IuZ2V0UmdiSXRlbShhcmdzLCAwLCByZXN1bHQuZm9udENvbG9yLCAwKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRGaWxsR3JheToKICAgICAgICAgICAgQ29sb3JTcGFjZVV0aWxzLmdyYXkuZ2V0UmdiSXRlbShhcmdzLCAwLCByZXN1bHQuZm9udENvbG9yLCAwKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIE9QUy5zZXRGaWxsQ01ZS0NvbG9yOgogICAgICAgICAgICBDb2xvclNwYWNlVXRpbHMuY215ay5nZXRSZ2JJdGVtKGFyZ3MsIDAsIHJlc3VsdC5mb250Q29sb3IsIDApOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgT1BTLnNob3dUZXh0OgogICAgICAgICAgY2FzZSBPUFMuc2hvd1NwYWNlZFRleHQ6CiAgICAgICAgICBjYXNlIE9QUy5uZXh0TGluZVNob3dUZXh0OgogICAgICAgICAgY2FzZSBPUFMubmV4dExpbmVTZXRTcGFjaW5nU2hvd1RleHQ6CiAgICAgICAgICAgIGJyZWFrTG9vcCA9IHRydWU7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgfSBjYXRjaCAocmVhc29uKSB7CiAgICAgIHdhcm4oYHBhcnNlQXBwZWFyYW5jZVN0cmVhbSAtIGlnbm9yaW5nIGVycm9yczogIiR7cmVhc29ufSIuYCk7CiAgICB9CiAgICB0aGlzLnN0cmVhbS5yZXNldCgpOwogICAgZGVsZXRlIHJlc3VsdC5zY2FsZUZhY3RvcjsKICAgIGRlbGV0ZSByZXN1bHQuZmlsbENvbG9yU3BhY2U7CiAgICByZXR1cm4gcmVzdWx0OwogIH0KICBnZXQgX2xvY2FsQ29sb3JTcGFjZUNhY2hlKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiX2xvY2FsQ29sb3JTcGFjZUNhY2hlIiwgbmV3IExvY2FsQ29sb3JTcGFjZUNhY2hlKCkpOwogIH0KICBnZXQgX3BkZkZ1bmN0aW9uRmFjdG9yeSgpIHsKICAgIGNvbnN0IHBkZkZ1bmN0aW9uRmFjdG9yeSA9IG5ldyBQREZGdW5jdGlvbkZhY3RvcnkoewogICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgIGlzRXZhbFN1cHBvcnRlZDogdGhpcy5ldmFsdWF0b3JPcHRpb25zLmlzRXZhbFN1cHBvcnRlZAogICAgfSk7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJfcGRmRnVuY3Rpb25GYWN0b3J5IiwgcGRmRnVuY3Rpb25GYWN0b3J5KTsKICB9Cn0KZnVuY3Rpb24gcGFyc2VBcHBlYXJhbmNlU3RyZWFtKHN0cmVhbSwgZXZhbHVhdG9yT3B0aW9ucywgeHJlZiwgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlKSB7CiAgcmV0dXJuIG5ldyBBcHBlYXJhbmNlU3RyZWFtRXZhbHVhdG9yKHN0cmVhbSwgZXZhbHVhdG9yT3B0aW9ucywgeHJlZiwgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlKS5wYXJzZSgpOwp9CmZ1bmN0aW9uIGdldFBkZkNvbG9yKGNvbG9yLCBpc0ZpbGwpIHsKICBpZiAoY29sb3JbMF0gPT09IGNvbG9yWzFdICYmIGNvbG9yWzFdID09PSBjb2xvclsyXSkgewogICAgY29uc3QgZ3JheSA9IGNvbG9yWzBdIC8gMjU1OwogICAgcmV0dXJuIGAke251bWJlclRvU3RyaW5nKGdyYXkpfSAke2lzRmlsbCA/ICJnIiA6ICJHIn1gOwogIH0KICByZXR1cm4gQXJyYXkuZnJvbShjb2xvciwgYyA9PiBudW1iZXJUb1N0cmluZyhjIC8gMjU1KSkuam9pbigiICIpICsgYCAke2lzRmlsbCA/ICJyZyIgOiAiUkcifWA7Cn0KZnVuY3Rpb24gY3JlYXRlRGVmYXVsdEFwcGVhcmFuY2UoewogIGZvbnRTaXplLAogIGZvbnROYW1lLAogIGZvbnRDb2xvcgp9KSB7CiAgcmV0dXJuIGAvJHtlc2NhcGVQREZOYW1lKGZvbnROYW1lKX0gJHtmb250U2l6ZX0gVGYgJHtnZXRQZGZDb2xvcihmb250Q29sb3IsIHRydWUpfWA7Cn0KY2xhc3MgRmFrZVVuaWNvZGVGb250IHsKICBjb25zdHJ1Y3Rvcih4cmVmLCBmb250RmFtaWx5KSB7CiAgICB0aGlzLnhyZWYgPSB4cmVmOwogICAgdGhpcy53aWR0aHMgPSBudWxsOwogICAgdGhpcy5maXJzdENoYXIgPSBJbmZpbml0eTsKICAgIHRoaXMubGFzdENoYXIgPSAtSW5maW5pdHk7CiAgICB0aGlzLmZvbnRGYW1pbHkgPSBmb250RmFtaWx5OwogICAgY29uc3QgY2FudmFzID0gbmV3IE9mZnNjcmVlbkNhbnZhcygxLCAxKTsKICAgIHRoaXMuY3R4TWVhc3VyZSA9IGNhbnZhcy5nZXRDb250ZXh0KCIyZCIsIHsKICAgICAgd2lsbFJlYWRGcmVxdWVudGx5OiB0cnVlCiAgICB9KTsKICAgIGlmICghRmFrZVVuaWNvZGVGb250Ll9mb250TmFtZUlkKSB7CiAgICAgIEZha2VVbmljb2RlRm9udC5fZm9udE5hbWVJZCA9IDE7CiAgICB9CiAgICB0aGlzLmZvbnROYW1lID0gTmFtZS5nZXQoYEludmFsaWRQREZqc0ZvbnRfJHtmb250RmFtaWx5fV8ke0Zha2VVbmljb2RlRm9udC5fZm9udE5hbWVJZCsrfWApOwogIH0KICBnZXQgZm9udERlc2NyaXB0b3JSZWYoKSB7CiAgICBpZiAoIUZha2VVbmljb2RlRm9udC5fZm9udERlc2NyaXB0b3JSZWYpIHsKICAgICAgY29uc3QgZm9udERlc2NyaXB0b3IgPSBuZXcgRGljdCh0aGlzLnhyZWYpOwogICAgICBmb250RGVzY3JpcHRvci5zZXRJZk5hbWUoIlR5cGUiLCAiRm9udERlc2NyaXB0b3IiKTsKICAgICAgZm9udERlc2NyaXB0b3Iuc2V0KCJGb250TmFtZSIsIHRoaXMuZm9udE5hbWUpOwogICAgICBmb250RGVzY3JpcHRvci5zZXQoIkZvbnRGYW1pbHkiLCAiTXlyaWFkUHJvIFJlZ3VsYXIiKTsKICAgICAgZm9udERlc2NyaXB0b3Iuc2V0KCJGb250QkJveCIsIFswLCAwLCAwLCAwXSk7CiAgICAgIGZvbnREZXNjcmlwdG9yLnNldElmTmFtZSgiRm9udFN0cmV0Y2giLCAiTm9ybWFsIik7CiAgICAgIGZvbnREZXNjcmlwdG9yLnNldCgiRm9udFdlaWdodCIsIDQwMCk7CiAgICAgIGZvbnREZXNjcmlwdG9yLnNldCgiSXRhbGljQW5nbGUiLCAwKTsKICAgICAgRmFrZVVuaWNvZGVGb250Ll9mb250RGVzY3JpcHRvclJlZiA9IHRoaXMueHJlZi5nZXROZXdQZXJzaXN0ZW50UmVmKGZvbnREZXNjcmlwdG9yKTsKICAgIH0KICAgIHJldHVybiBGYWtlVW5pY29kZUZvbnQuX2ZvbnREZXNjcmlwdG9yUmVmOwogIH0KICBnZXQgZGVzY2VuZGFudEZvbnRSZWYoKSB7CiAgICBjb25zdCBkZXNjZW5kYW50Rm9udCA9IG5ldyBEaWN0KHRoaXMueHJlZik7CiAgICBkZXNjZW5kYW50Rm9udC5zZXQoIkJhc2VGb250IiwgdGhpcy5mb250TmFtZSk7CiAgICBkZXNjZW5kYW50Rm9udC5zZXRJZk5hbWUoIlR5cGUiLCAiRm9udCIpOwogICAgZGVzY2VuZGFudEZvbnQuc2V0SWZOYW1lKCJTdWJ0eXBlIiwgIkNJREZvbnRUeXBlMCIpOwogICAgZGVzY2VuZGFudEZvbnQuc2V0SWZOYW1lKCJDSURUb0dJRE1hcCIsICJJZGVudGl0eSIpOwogICAgZGVzY2VuZGFudEZvbnQuc2V0KCJGaXJzdENoYXIiLCB0aGlzLmZpcnN0Q2hhcik7CiAgICBkZXNjZW5kYW50Rm9udC5zZXQoIkxhc3RDaGFyIiwgdGhpcy5sYXN0Q2hhcik7CiAgICBkZXNjZW5kYW50Rm9udC5zZXQoIkZvbnREZXNjcmlwdG9yIiwgdGhpcy5mb250RGVzY3JpcHRvclJlZik7CiAgICBkZXNjZW5kYW50Rm9udC5zZXQoIkRXIiwgMTAwMCk7CiAgICBjb25zdCB3aWR0aHMgPSBbXTsKICAgIGNvbnN0IGNoYXJzID0gWy4uLnRoaXMud2lkdGhzLmVudHJpZXMoKV0uc29ydCgpOwogICAgbGV0IGN1cnJlbnRDaGFyID0gbnVsbDsKICAgIGxldCBjdXJyZW50V2lkdGhzID0gbnVsbDsKICAgIGZvciAoY29uc3QgW2NoYXIsIHdpZHRoXSBvZiBjaGFycykgewogICAgICBpZiAoIWN1cnJlbnRDaGFyKSB7CiAgICAgICAgY3VycmVudENoYXIgPSBjaGFyOwogICAgICAgIGN1cnJlbnRXaWR0aHMgPSBbd2lkdGhdOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChjaGFyID09PSBjdXJyZW50Q2hhciArIGN1cnJlbnRXaWR0aHMubGVuZ3RoKSB7CiAgICAgICAgY3VycmVudFdpZHRocy5wdXNoKHdpZHRoKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB3aWR0aHMucHVzaChjdXJyZW50Q2hhciwgY3VycmVudFdpZHRocyk7CiAgICAgICAgY3VycmVudENoYXIgPSBjaGFyOwogICAgICAgIGN1cnJlbnRXaWR0aHMgPSBbd2lkdGhdOwogICAgICB9CiAgICB9CiAgICBpZiAoY3VycmVudENoYXIpIHsKICAgICAgd2lkdGhzLnB1c2goY3VycmVudENoYXIsIGN1cnJlbnRXaWR0aHMpOwogICAgfQogICAgZGVzY2VuZGFudEZvbnQuc2V0KCJXIiwgd2lkdGhzKTsKICAgIGNvbnN0IGNpZFN5c3RlbUluZm8gPSBuZXcgRGljdCh0aGlzLnhyZWYpOwogICAgY2lkU3lzdGVtSW5mby5zZXQoIk9yZGVyaW5nIiwgIklkZW50aXR5Iik7CiAgICBjaWRTeXN0ZW1JbmZvLnNldCgiUmVnaXN0cnkiLCAiQWRvYmUiKTsKICAgIGNpZFN5c3RlbUluZm8uc2V0KCJTdXBwbGVtZW50IiwgMCk7CiAgICBkZXNjZW5kYW50Rm9udC5zZXQoIkNJRFN5c3RlbUluZm8iLCBjaWRTeXN0ZW1JbmZvKTsKICAgIHJldHVybiB0aGlzLnhyZWYuZ2V0TmV3UGVyc2lzdGVudFJlZihkZXNjZW5kYW50Rm9udCk7CiAgfQogIGdldCBiYXNlRm9udFJlZigpIHsKICAgIGNvbnN0IGJhc2VGb250ID0gbmV3IERpY3QodGhpcy54cmVmKTsKICAgIGJhc2VGb250LnNldCgiQmFzZUZvbnQiLCB0aGlzLmZvbnROYW1lKTsKICAgIGJhc2VGb250LnNldElmTmFtZSgiVHlwZSIsICJGb250Iik7CiAgICBiYXNlRm9udC5zZXRJZk5hbWUoIlN1YnR5cGUiLCAiVHlwZTAiKTsKICAgIGJhc2VGb250LnNldElmTmFtZSgiRW5jb2RpbmciLCAiSWRlbnRpdHktSCIpOwogICAgYmFzZUZvbnQuc2V0KCJEZXNjZW5kYW50Rm9udHMiLCBbdGhpcy5kZXNjZW5kYW50Rm9udFJlZl0pOwogICAgYmFzZUZvbnQuc2V0SWZOYW1lKCJUb1VuaWNvZGUiLCAiSWRlbnRpdHktSCIpOwogICAgcmV0dXJuIHRoaXMueHJlZi5nZXROZXdQZXJzaXN0ZW50UmVmKGJhc2VGb250KTsKICB9CiAgZ2V0IHJlc291cmNlcygpIHsKICAgIGNvbnN0IHJlc291cmNlcyA9IG5ldyBEaWN0KHRoaXMueHJlZik7CiAgICBjb25zdCBmb250ID0gbmV3IERpY3QodGhpcy54cmVmKTsKICAgIGZvbnQuc2V0KHRoaXMuZm9udE5hbWUubmFtZSwgdGhpcy5iYXNlRm9udFJlZik7CiAgICByZXNvdXJjZXMuc2V0KCJGb250IiwgZm9udCk7CiAgICByZXR1cm4gcmVzb3VyY2VzOwogIH0KICBfY3JlYXRlQ29udGV4dCgpIHsKICAgIHRoaXMud2lkdGhzID0gbmV3IE1hcCgpOwogICAgdGhpcy5jdHhNZWFzdXJlLmZvbnQgPSBgMTAwMHB4ICR7dGhpcy5mb250RmFtaWx5fWA7CiAgICByZXR1cm4gdGhpcy5jdHhNZWFzdXJlOwogIH0KICBjcmVhdGVGb250UmVzb3VyY2VzKHRleHQpIHsKICAgIGNvbnN0IGN0eCA9IHRoaXMuX2NyZWF0ZUNvbnRleHQoKTsKICAgIGZvciAoY29uc3QgbGluZSBvZiB0ZXh0LnNwbGl0KC9cclxuP3xcbi8pKSB7CiAgICAgIGZvciAoY29uc3QgY2hhciBvZiBsaW5lLnNwbGl0KCIiKSkgewogICAgICAgIGNvbnN0IGNvZGUgPSBjaGFyLmNoYXJDb2RlQXQoMCk7CiAgICAgICAgaWYgKHRoaXMud2lkdGhzLmhhcyhjb2RlKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IG1ldHJpY3MgPSBjdHgubWVhc3VyZVRleHQoY2hhcik7CiAgICAgICAgY29uc3Qgd2lkdGggPSBNYXRoLmNlaWwobWV0cmljcy53aWR0aCk7CiAgICAgICAgdGhpcy53aWR0aHMuc2V0KGNvZGUsIHdpZHRoKTsKICAgICAgICB0aGlzLmZpcnN0Q2hhciA9IE1hdGgubWluKGNvZGUsIHRoaXMuZmlyc3RDaGFyKTsKICAgICAgICB0aGlzLmxhc3RDaGFyID0gTWF0aC5tYXgoY29kZSwgdGhpcy5sYXN0Q2hhcik7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB0aGlzLnJlc291cmNlczsKICB9CiAgc3RhdGljIGdldEZpcnN0UG9zaXRpb25JbmZvKHJlY3QsIHJvdGF0aW9uLCBmb250U2l6ZSkgewogICAgY29uc3QgW3gxLCB5MSwgeDIsIHkyXSA9IHJlY3Q7CiAgICBsZXQgdyA9IHgyIC0geDE7CiAgICBsZXQgaCA9IHkyIC0geTE7CiAgICBpZiAocm90YXRpb24gJSAxODAgIT09IDApIHsKICAgICAgW3csIGhdID0gW2gsIHddOwogICAgfQogICAgY29uc3QgbGluZUhlaWdodCA9IExJTkVfRkFDVE9SICogZm9udFNpemU7CiAgICBjb25zdCBsaW5lRGVzY2VudCA9IExJTkVfREVTQ0VOVF9GQUNUT1IgKiBmb250U2l6ZTsKICAgIHJldHVybiB7CiAgICAgIGNvb3JkczogWzAsIGggKyBsaW5lRGVzY2VudCAtIGxpbmVIZWlnaHRdLAogICAgICBiYm94OiBbMCwgMCwgdywgaF0sCiAgICAgIG1hdHJpeDogcm90YXRpb24gIT09IDAgPyBnZXRSb3RhdGlvbk1hdHJpeChyb3RhdGlvbiwgaCwgbGluZUhlaWdodCkgOiB1bmRlZmluZWQKICAgIH07CiAgfQogIGNyZWF0ZUFwcGVhcmFuY2UodGV4dCwgcmVjdCwgcm90YXRpb24sIGZvbnRTaXplLCBiZ0NvbG9yLCBzdHJva2VBbHBoYSkgewogICAgY29uc3QgY3R4ID0gdGhpcy5fY3JlYXRlQ29udGV4dCgpOwogICAgY29uc3QgbGluZXMgPSBbXTsKICAgIGxldCBtYXhXaWR0aCA9IC1JbmZpbml0eTsKICAgIGZvciAoY29uc3QgbGluZSBvZiB0ZXh0LnNwbGl0KC9cclxuP3xcbi8pKSB7CiAgICAgIGxpbmVzLnB1c2gobGluZSk7CiAgICAgIGNvbnN0IGxpbmVXaWR0aCA9IGN0eC5tZWFzdXJlVGV4dChsaW5lKS53aWR0aDsKICAgICAgbWF4V2lkdGggPSBNYXRoLm1heChtYXhXaWR0aCwgbGluZVdpZHRoKTsKICAgICAgZm9yIChjb25zdCBjb2RlIG9mIGNvZGVQb2ludEl0ZXIobGluZSkpIHsKICAgICAgICBjb25zdCBjaGFyID0gU3RyaW5nLmZyb21Db2RlUG9pbnQoY29kZSk7CiAgICAgICAgbGV0IHdpZHRoID0gdGhpcy53aWR0aHMuZ2V0KGNvZGUpOwogICAgICAgIGlmICh3aWR0aCA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICBjb25zdCBtZXRyaWNzID0gY3R4Lm1lYXN1cmVUZXh0KGNoYXIpOwogICAgICAgICAgd2lkdGggPSBNYXRoLmNlaWwobWV0cmljcy53aWR0aCk7CiAgICAgICAgICB0aGlzLndpZHRocy5zZXQoY29kZSwgd2lkdGgpOwogICAgICAgICAgdGhpcy5maXJzdENoYXIgPSBNYXRoLm1pbihjb2RlLCB0aGlzLmZpcnN0Q2hhcik7CiAgICAgICAgICB0aGlzLmxhc3RDaGFyID0gTWF0aC5tYXgoY29kZSwgdGhpcy5sYXN0Q2hhcik7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBtYXhXaWR0aCAqPSBmb250U2l6ZSAvIDEwMDA7CiAgICBjb25zdCBbeDEsIHkxLCB4MiwgeTJdID0gcmVjdDsKICAgIGxldCB3ID0geDIgLSB4MTsKICAgIGxldCBoID0geTIgLSB5MTsKICAgIGlmIChyb3RhdGlvbiAlIDE4MCAhPT0gMCkgewogICAgICBbdywgaF0gPSBbaCwgd107CiAgICB9CiAgICBsZXQgaHNjYWxlID0gMTsKICAgIGlmIChtYXhXaWR0aCA+IHcpIHsKICAgICAgaHNjYWxlID0gdyAvIG1heFdpZHRoOwogICAgfQogICAgbGV0IHZzY2FsZSA9IDE7CiAgICBjb25zdCBsaW5lSGVpZ2h0ID0gTElORV9GQUNUT1IgKiBmb250U2l6ZTsKICAgIGNvbnN0IGxpbmVEZXNjZW50ID0gTElORV9ERVNDRU5UX0ZBQ1RPUiAqIGZvbnRTaXplOwogICAgY29uc3QgbWF4SGVpZ2h0ID0gbGluZUhlaWdodCAqIGxpbmVzLmxlbmd0aDsKICAgIGlmIChtYXhIZWlnaHQgPiBoKSB7CiAgICAgIHZzY2FsZSA9IGggLyBtYXhIZWlnaHQ7CiAgICB9CiAgICBjb25zdCBmc2NhbGUgPSBNYXRoLm1pbihoc2NhbGUsIHZzY2FsZSk7CiAgICBjb25zdCBuZXdGb250U2l6ZSA9IGZvbnRTaXplICogZnNjYWxlOwogICAgY29uc3QgYnVmZmVyID0gWyJxIiwgYDAgMCAke251bWJlclRvU3RyaW5nKHcpfSAke251bWJlclRvU3RyaW5nKGgpfSByZSBXIG5gLCBgQlRgLCBgMSAwIDAgMSAwICR7bnVtYmVyVG9TdHJpbmcoaCArIGxpbmVEZXNjZW50KX0gVG0gMCBUYyAke2dldFBkZkNvbG9yKGJnQ29sb3IsIHRydWUpfWAsIGAvJHt0aGlzLmZvbnROYW1lLm5hbWV9ICR7bnVtYmVyVG9TdHJpbmcobmV3Rm9udFNpemUpfSBUZmBdOwogICAgY29uc3QgewogICAgICByZXNvdXJjZXMKICAgIH0gPSB0aGlzOwogICAgc3Ryb2tlQWxwaGEgPSB0eXBlb2Ygc3Ryb2tlQWxwaGEgPT09ICJudW1iZXIiICYmIHN0cm9rZUFscGhhID49IDAgJiYgc3Ryb2tlQWxwaGEgPD0gMSA/IHN0cm9rZUFscGhhIDogMTsKICAgIGlmIChzdHJva2VBbHBoYSAhPT0gMSkgewogICAgICBidWZmZXIucHVzaCgiL1IwIGdzIik7CiAgICAgIGNvbnN0IGV4dEdTdGF0ZSA9IG5ldyBEaWN0KHRoaXMueHJlZik7CiAgICAgIGNvbnN0IHIwID0gbmV3IERpY3QodGhpcy54cmVmKTsKICAgICAgcjAuc2V0KCJjYSIsIHN0cm9rZUFscGhhKTsKICAgICAgcjAuc2V0KCJDQSIsIHN0cm9rZUFscGhhKTsKICAgICAgcjAuc2V0SWZOYW1lKCJUeXBlIiwgIkV4dEdTdGF0ZSIpOwogICAgICBleHRHU3RhdGUuc2V0KCJSMCIsIHIwKTsKICAgICAgcmVzb3VyY2VzLnNldCgiRXh0R1N0YXRlIiwgZXh0R1N0YXRlKTsKICAgIH0KICAgIGNvbnN0IHZTaGlmdCA9IG51bWJlclRvU3RyaW5nKGxpbmVIZWlnaHQpOwogICAgZm9yIChjb25zdCBsaW5lIG9mIGxpbmVzKSB7CiAgICAgIGJ1ZmZlci5wdXNoKGAwIC0ke3ZTaGlmdH0gVGQgPCR7c3RyaW5nVG9VVEYxNkhleFN0cmluZyhsaW5lKX0+IFRqYCk7CiAgICB9CiAgICBidWZmZXIucHVzaCgiRVQiLCAiUSIpOwogICAgY29uc3QgYXBwZWFyYW5jZSA9IGJ1ZmZlci5qb2luKCJcbiIpOwogICAgY29uc3QgYXBwZWFyYW5jZVN0cmVhbURpY3QgPSBuZXcgRGljdCh0aGlzLnhyZWYpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0SWZOYW1lKCJTdWJ0eXBlIiwgIkZvcm0iKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldElmTmFtZSgiVHlwZSIsICJYT2JqZWN0Iik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkJCb3giLCBbMCwgMCwgdywgaF0pOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJMZW5ndGgiLCBhcHBlYXJhbmNlLmxlbmd0aCk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIlJlc291cmNlcyIsIHJlc291cmNlcyk7CiAgICBpZiAocm90YXRpb24pIHsKICAgICAgY29uc3QgbWF0cml4ID0gZ2V0Um90YXRpb25NYXRyaXgocm90YXRpb24sIHcsIGgpOwogICAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIk1hdHJpeCIsIG1hdHJpeCk7CiAgICB9CiAgICBjb25zdCBhcCA9IG5ldyBTdHJpbmdTdHJlYW0oYXBwZWFyYW5jZSk7CiAgICBhcC5kaWN0ID0gYXBwZWFyYW5jZVN0cmVhbURpY3Q7CiAgICByZXR1cm4gYXA7CiAgfQp9Cgo7Ly8gLi9zcmMvc2hhcmVkL3NjcmlwdGluZ191dGlscy5qcwoKCmZ1bmN0aW9uIG1ha2VDb2xvckNvbXAobikgewogIHJldHVybiBNYXRoLmZsb29yKE1hdGgubWF4KDAsIE1hdGgubWluKDEsIG4pKSAqIDI1NSkudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDIsICIwIik7Cn0KZnVuY3Rpb24gc2NhbGVBbmRDbGFtcCh4KSB7CiAgcmV0dXJuIE1hdGgubWF4KDAsIE1hdGgubWluKDI1NSwgMjU1ICogeCkpOwp9CmNsYXNzIENvbG9yQ29udmVydGVycyB7CiAgc3RhdGljIENNWUtfRyhbYywgeSwgbSwga10pIHsKICAgIHJldHVybiBbIkciLCAxIC0gTWF0aC5taW4oMSwgMC4zICogYyArIDAuNTkgKiBtICsgMC4xMSAqIHkgKyBrKV07CiAgfQogIHN0YXRpYyBHX0NNWUsoW2ddKSB7CiAgICByZXR1cm4gWyJDTVlLIiwgMCwgMCwgMCwgMSAtIGddOwogIH0KICBzdGF0aWMgR19SR0IoW2ddKSB7CiAgICByZXR1cm4gWyJSR0IiLCBnLCBnLCBnXTsKICB9CiAgc3RhdGljIEdfcmdiKFtnXSkgewogICAgZyA9IHNjYWxlQW5kQ2xhbXAoZyk7CiAgICByZXR1cm4gW2csIGcsIGddOwogIH0KICBzdGF0aWMgR19IVE1MKFtnXSkgewogICAgY29uc3QgRyA9IG1ha2VDb2xvckNvbXAoZyk7CiAgICByZXR1cm4gYCMke0d9JHtHfSR7R31gOwogIH0KICBzdGF0aWMgUkdCX0coW3IsIGcsIGJdKSB7CiAgICByZXR1cm4gWyJHIiwgMC4zICogciArIDAuNTkgKiBnICsgMC4xMSAqIGJdOwogIH0KICBzdGF0aWMgUkdCX3JnYihjb2xvcikgewogICAgcmV0dXJuIGNvbG9yLm1hcChzY2FsZUFuZENsYW1wKTsKICB9CiAgc3RhdGljIFJHQl9IVE1MKGNvbG9yKSB7CiAgICByZXR1cm4gYCMke2NvbG9yLm1hcChtYWtlQ29sb3JDb21wKS5qb2luKCIiKX1gOwogIH0KICBzdGF0aWMgVF9IVE1MKCkgewogICAgcmV0dXJuICIjMDAwMDAwMDAiOwogIH0KICBzdGF0aWMgVF9yZ2IoKSB7CiAgICByZXR1cm4gW251bGxdOwogIH0KICBzdGF0aWMgQ01ZS19SR0IoW2MsIHksIG0sIGtdKSB7CiAgICByZXR1cm4gWyJSR0IiLCAxIC0gTWF0aC5taW4oMSwgYyArIGspLCAxIC0gTWF0aC5taW4oMSwgbSArIGspLCAxIC0gTWF0aC5taW4oMSwgeSArIGspXTsKICB9CiAgc3RhdGljIENNWUtfcmdiKFtjLCB5LCBtLCBrXSkgewogICAgcmV0dXJuIFtzY2FsZUFuZENsYW1wKDEgLSBNYXRoLm1pbigxLCBjICsgaykpLCBzY2FsZUFuZENsYW1wKDEgLSBNYXRoLm1pbigxLCBtICsgaykpLCBzY2FsZUFuZENsYW1wKDEgLSBNYXRoLm1pbigxLCB5ICsgaykpXTsKICB9CiAgc3RhdGljIENNWUtfSFRNTChjb21wb25lbnRzKSB7CiAgICBjb25zdCByZ2IgPSB0aGlzLkNNWUtfUkdCKGNvbXBvbmVudHMpLnNsaWNlKDEpOwogICAgcmV0dXJuIHRoaXMuUkdCX0hUTUwocmdiKTsKICB9CiAgc3RhdGljIFJHQl9DTVlLKFtyLCBnLCBiXSkgewogICAgY29uc3QgYyA9IDEgLSByOwogICAgY29uc3QgbSA9IDEgLSBnOwogICAgY29uc3QgeSA9IDEgLSBiOwogICAgY29uc3QgayA9IE1hdGgubWluKGMsIG0sIHkpOwogICAgcmV0dXJuIFsiQ01ZSyIsIGMsIG0sIHksIGtdOwogIH0KfQpjb25zdCBEYXRlRm9ybWF0cyA9IFsibS9kIiwgIm0vZC95eSIsICJtbS9kZC95eSIsICJtbS95eSIsICJkLW1tbSIsICJkLW1tbS15eSIsICJkZC1tbW0teXkiLCAieXktbW0tZGQiLCAibW1tLXl5IiwgIm1tbW0teXkiLCAibW1tIGQsIHl5eXkiLCAibW1tbSBkLCB5eXl5IiwgIm0vZC95eSBoOk1NIHR0IiwgIm0vZC95eSBISDpNTSJdOwpjb25zdCBUaW1lRm9ybWF0cyA9IFsiSEg6TU0iLCAiaDpNTSB0dCIsICJISDpNTTpzcyIsICJoOk1NOnNzIHR0Il07Cgo7Ly8gLi9zcmMvY29yZS9uYW1lX251bWJlcl90cmVlLmpzCgoKCmNsYXNzIE5hbWVPck51bWJlclRyZWUgewogIGNvbnN0cnVjdG9yKHJvb3QsIHhyZWYsIHR5cGUpIHsKICAgIHRoaXMucm9vdCA9IHJvb3Q7CiAgICB0aGlzLnhyZWYgPSB4cmVmOwogICAgdGhpcy5fdHlwZSA9IHR5cGU7CiAgfQogIGdldEFsbCgpIHsKICAgIGNvbnN0IG1hcCA9IG5ldyBNYXAoKTsKICAgIGlmICghdGhpcy5yb290KSB7CiAgICAgIHJldHVybiBtYXA7CiAgICB9CiAgICBjb25zdCB4cmVmID0gdGhpcy54cmVmOwogICAgY29uc3QgcHJvY2Vzc2VkID0gbmV3IFJlZlNldCgpOwogICAgcHJvY2Vzc2VkLnB1dCh0aGlzLnJvb3QpOwogICAgY29uc3QgcXVldWUgPSBbdGhpcy5yb290XTsKICAgIHdoaWxlIChxdWV1ZS5sZW5ndGggPiAwKSB7CiAgICAgIGNvbnN0IG9iaiA9IHhyZWYuZmV0Y2hJZlJlZihxdWV1ZS5zaGlmdCgpKTsKICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAob2JqLmhhcygiS2lkcyIpKSB7CiAgICAgICAgY29uc3Qga2lkcyA9IG9iai5nZXQoIktpZHMiKTsKICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoa2lkcykpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBmb3IgKGNvbnN0IGtpZCBvZiBraWRzKSB7CiAgICAgICAgICBpZiAocHJvY2Vzc2VkLmhhcyhraWQpKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcihgRHVwbGljYXRlIGVudHJ5IGluICIke3RoaXMuX3R5cGV9IiB0cmVlLmApOwogICAgICAgICAgfQogICAgICAgICAgcXVldWUucHVzaChraWQpOwogICAgICAgICAgcHJvY2Vzc2VkLnB1dChraWQpOwogICAgICAgIH0KICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBlbnRyaWVzID0gb2JqLmdldCh0aGlzLl90eXBlKTsKICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGVudHJpZXMpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gZW50cmllcy5sZW5ndGg7IGkgPCBpaTsgaSArPSAyKSB7CiAgICAgICAgbWFwLnNldCh4cmVmLmZldGNoSWZSZWYoZW50cmllc1tpXSksIHhyZWYuZmV0Y2hJZlJlZihlbnRyaWVzW2kgKyAxXSkpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbWFwOwogIH0KICBnZXRSYXcoa2V5KSB7CiAgICBpZiAoIXRoaXMucm9vdCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHhyZWYgPSB0aGlzLnhyZWY7CiAgICBsZXQga2lkc09yRW50cmllcyA9IHhyZWYuZmV0Y2hJZlJlZih0aGlzLnJvb3QpOwogICAgbGV0IGxvb3BDb3VudCA9IDA7CiAgICBjb25zdCBNQVhfTEVWRUxTID0gMTA7CiAgICB3aGlsZSAoa2lkc09yRW50cmllcy5oYXMoIktpZHMiKSkgewogICAgICBpZiAoKytsb29wQ291bnQgPiBNQVhfTEVWRUxTKSB7CiAgICAgICAgd2FybihgU2VhcmNoIGRlcHRoIGxpbWl0IHJlYWNoZWQgZm9yICIke3RoaXMuX3R5cGV9IiB0cmVlLmApOwogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IGtpZHMgPSBraWRzT3JFbnRyaWVzLmdldCgiS2lkcyIpOwogICAgICBpZiAoIUFycmF5LmlzQXJyYXkoa2lkcykpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBsZXQgbCA9IDAsCiAgICAgICAgciA9IGtpZHMubGVuZ3RoIC0gMTsKICAgICAgd2hpbGUgKGwgPD0gcikgewogICAgICAgIGNvbnN0IG0gPSBsICsgciA+PiAxOwogICAgICAgIGNvbnN0IGtpZCA9IHhyZWYuZmV0Y2hJZlJlZihraWRzW21dKTsKICAgICAgICBjb25zdCBsaW1pdHMgPSBraWQuZ2V0KCJMaW1pdHMiKTsKICAgICAgICBpZiAoa2V5IDwgeHJlZi5mZXRjaElmUmVmKGxpbWl0c1swXSkpIHsKICAgICAgICAgIHIgPSBtIC0gMTsKICAgICAgICB9IGVsc2UgaWYgKGtleSA+IHhyZWYuZmV0Y2hJZlJlZihsaW1pdHNbMV0pKSB7CiAgICAgICAgICBsID0gbSArIDE7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGtpZHNPckVudHJpZXMgPSBraWQ7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGwgPiByKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGVudHJpZXMgPSBraWRzT3JFbnRyaWVzLmdldCh0aGlzLl90eXBlKTsKICAgIGlmIChBcnJheS5pc0FycmF5KGVudHJpZXMpKSB7CiAgICAgIGxldCBsID0gMCwKICAgICAgICByID0gZW50cmllcy5sZW5ndGggLSAyOwogICAgICB3aGlsZSAobCA8PSByKSB7CiAgICAgICAgY29uc3QgdG1wID0gbCArIHIgPj4gMSwKICAgICAgICAgIG0gPSB0bXAgKyAodG1wICYgMSk7CiAgICAgICAgY29uc3QgY3VycmVudEtleSA9IHhyZWYuZmV0Y2hJZlJlZihlbnRyaWVzW21dKTsKICAgICAgICBpZiAoa2V5IDwgY3VycmVudEtleSkgewogICAgICAgICAgciA9IG0gLSAyOwogICAgICAgIH0gZWxzZSBpZiAoa2V5ID4gY3VycmVudEtleSkgewogICAgICAgICAgbCA9IG0gKyAyOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICByZXR1cm4gZW50cmllc1ttICsgMV07CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgZ2V0KGtleSkgewogICAgcmV0dXJuIHRoaXMueHJlZi5mZXRjaElmUmVmKHRoaXMuZ2V0UmF3KGtleSkpOwogIH0KfQpjbGFzcyBOYW1lVHJlZSBleHRlbmRzIE5hbWVPck51bWJlclRyZWUgewogIGNvbnN0cnVjdG9yKHJvb3QsIHhyZWYpIHsKICAgIHN1cGVyKHJvb3QsIHhyZWYsICJOYW1lcyIpOwogIH0KfQpjbGFzcyBOdW1iZXJUcmVlIGV4dGVuZHMgTmFtZU9yTnVtYmVyVHJlZSB7CiAgY29uc3RydWN0b3Iocm9vdCwgeHJlZikgewogICAgc3VwZXIocm9vdCwgeHJlZiwgIk51bXMiKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2NsZWFudXBfaGVscGVyLmpzCgoKCgpmdW5jdGlvbiBjbGVhckdsb2JhbENhY2hlcygpIHsKICBjbGVhclBhdHRlcm5DYWNoZXMoKTsKICBjbGVhclByaW1pdGl2ZUNhY2hlcygpOwogIGNsZWFyVW5pY29kZUNhY2hlcygpOwogIEpweEltYWdlLmNsZWFudXAoKTsKfQoKOy8vIC4vc3JjL2NvcmUvZmlsZV9zcGVjLmpzCgoKCmZ1bmN0aW9uIHBpY2tQbGF0Zm9ybUl0ZW0oZGljdCkgewogIGlmICghKGRpY3QgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGlmIChkaWN0LmhhcygiVUYiKSkgewogICAgcmV0dXJuIGRpY3QuZ2V0KCJVRiIpOwogIH0gZWxzZSBpZiAoZGljdC5oYXMoIkYiKSkgewogICAgcmV0dXJuIGRpY3QuZ2V0KCJGIik7CiAgfSBlbHNlIGlmIChkaWN0LmhhcygiVW5peCIpKSB7CiAgICByZXR1cm4gZGljdC5nZXQoIlVuaXgiKTsKICB9IGVsc2UgaWYgKGRpY3QuaGFzKCJNYWMiKSkgewogICAgcmV0dXJuIGRpY3QuZ2V0KCJNYWMiKTsKICB9IGVsc2UgaWYgKGRpY3QuaGFzKCJET1MiKSkgewogICAgcmV0dXJuIGRpY3QuZ2V0KCJET1MiKTsKICB9CiAgcmV0dXJuIG51bGw7Cn0KZnVuY3Rpb24gc3RyaXBQYXRoKHN0cikgewogIHJldHVybiBzdHIuc3Vic3RyaW5nKHN0ci5sYXN0SW5kZXhPZigiLyIpICsgMSk7Cn0KY2xhc3MgRmlsZVNwZWMgewogICNjb250ZW50QXZhaWxhYmxlID0gZmFsc2U7CiAgY29uc3RydWN0b3Iocm9vdCwgeHJlZiwgc2tpcENvbnRlbnQgPSBmYWxzZSkgewogICAgaWYgKCEocm9vdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMueHJlZiA9IHhyZWY7CiAgICB0aGlzLnJvb3QgPSByb290OwogICAgaWYgKHJvb3QuaGFzKCJGUyIpKSB7CiAgICAgIHRoaXMuZnMgPSByb290LmdldCgiRlMiKTsKICAgIH0KICAgIGlmIChyb290LmhhcygiUkYiKSkgewogICAgICB3YXJuKCJSZWxhdGVkIGZpbGUgc3BlY2lmaWNhdGlvbnMgYXJlIG5vdCBzdXBwb3J0ZWQiKTsKICAgIH0KICAgIGlmICghc2tpcENvbnRlbnQpIHsKICAgICAgaWYgKHJvb3QuaGFzKCJFRiIpKSB7CiAgICAgICAgdGhpcy4jY29udGVudEF2YWlsYWJsZSA9IHRydWU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgd2FybigiTm9uLWVtYmVkZGVkIGZpbGUgc3BlY2lmaWNhdGlvbnMgYXJlIG5vdCBzdXBwb3J0ZWQiKTsKICAgICAgfQogICAgfQogIH0KICBnZXQgZmlsZW5hbWUoKSB7CiAgICBsZXQgZmlsZW5hbWUgPSAiIjsKICAgIGNvbnN0IGl0ZW0gPSBwaWNrUGxhdGZvcm1JdGVtKHRoaXMucm9vdCk7CiAgICBpZiAoaXRlbSAmJiB0eXBlb2YgaXRlbSA9PT0gInN0cmluZyIpIHsKICAgICAgZmlsZW5hbWUgPSBzdHJpbmdUb1BERlN0cmluZyhpdGVtLCB0cnVlKS5yZXBsYWNlQWxsKCJcXFxcIiwgIlxcIikucmVwbGFjZUFsbCgiXFwvIiwgIi8iKS5yZXBsYWNlQWxsKCJcXCIsICIvIik7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJmaWxlbmFtZSIsIGZpbGVuYW1lIHx8ICJ1bm5hbWVkIik7CiAgfQogIGdldCBjb250ZW50KCkgewogICAgaWYgKCF0aGlzLiNjb250ZW50QXZhaWxhYmxlKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgdGhpcy5fY29udGVudFJlZiB8fD0gcGlja1BsYXRmb3JtSXRlbSh0aGlzLnJvb3Q/LmdldCgiRUYiKSk7CiAgICBsZXQgY29udGVudCA9IG51bGw7CiAgICBpZiAodGhpcy5fY29udGVudFJlZikgewogICAgICBjb25zdCBmaWxlT2JqID0gdGhpcy54cmVmLmZldGNoSWZSZWYodGhpcy5fY29udGVudFJlZik7CiAgICAgIGlmIChmaWxlT2JqIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICAgIGNvbnRlbnQgPSBmaWxlT2JqLmdldEJ5dGVzKCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgd2FybigiRW1iZWRkZWQgZmlsZSBzcGVjaWZpY2F0aW9uIHBvaW50cyB0byBub24tZXhpc3RpbmcvaW52YWxpZCBjb250ZW50Iik7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHdhcm4oIkVtYmVkZGVkIGZpbGUgc3BlY2lmaWNhdGlvbiBkb2VzIG5vdCBoYXZlIGFueSBjb250ZW50Iik7CiAgICB9CiAgICByZXR1cm4gY29udGVudDsKICB9CiAgZ2V0IGRlc2NyaXB0aW9uKCkgewogICAgbGV0IGRlc2NyaXB0aW9uID0gIiI7CiAgICBjb25zdCBkZXNjID0gdGhpcy5yb290Py5nZXQoIkRlc2MiKTsKICAgIGlmIChkZXNjICYmIHR5cGVvZiBkZXNjID09PSAic3RyaW5nIikgewogICAgICBkZXNjcmlwdGlvbiA9IHN0cmluZ1RvUERGU3RyaW5nKGRlc2MpOwogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiZGVzY3JpcHRpb24iLCBkZXNjcmlwdGlvbik7CiAgfQogIGdldCBzZXJpYWxpemFibGUoKSB7CiAgICByZXR1cm4gewogICAgICByYXdGaWxlbmFtZTogdGhpcy5maWxlbmFtZSwKICAgICAgZmlsZW5hbWU6IHN0cmlwUGF0aCh0aGlzLmZpbGVuYW1lKSwKICAgICAgY29udGVudDogdGhpcy5jb250ZW50LAogICAgICBkZXNjcmlwdGlvbjogdGhpcy5kZXNjcmlwdGlvbgogICAgfTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3htbF9wYXJzZXIuanMKCgoKCmNvbnN0IFhNTFBhcnNlckVycm9yQ29kZSA9IHsKICBOb0Vycm9yOiAwLAogIEVuZE9mRG9jdW1lbnQ6IC0xLAogIFVudGVybWluYXRlZENkYXQ6IC0yLAogIFVudGVybWluYXRlZFhtbERlY2xhcmF0aW9uOiAtMywKICBVbnRlcm1pbmF0ZWREb2N0eXBlRGVjbGFyYXRpb246IC00LAogIFVudGVybWluYXRlZENvbW1lbnQ6IC01LAogIE1hbGZvcm1lZEVsZW1lbnQ6IC02LAogIE91dE9mTWVtb3J5OiAtNywKICBVbnRlcm1pbmF0ZWRBdHRyaWJ1dGVWYWx1ZTogLTgsCiAgVW50ZXJtaW5hdGVkRWxlbWVudDogLTksCiAgRWxlbWVudE5ldmVyQmVndW46IC0xMAp9OwpmdW5jdGlvbiBpc1doaXRlc3BhY2UocywgaW5kZXgpIHsKICBjb25zdCBjaCA9IHNbaW5kZXhdOwogIHJldHVybiBjaCA9PT0gIiAiIHx8IGNoID09PSAiXG4iIHx8IGNoID09PSAiXHIiIHx8IGNoID09PSAiXHQiOwp9CmZ1bmN0aW9uIGlzV2hpdGVzcGFjZVN0cmluZyhzKSB7CiAgZm9yIChsZXQgaSA9IDAsIGlpID0gcy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICBpZiAoIWlzV2hpdGVzcGFjZShzLCBpKSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgfQogIHJldHVybiB0cnVlOwp9CmNsYXNzIFhNTFBhcnNlckJhc2UgewogIF9yZXNvbHZlRW50aXRpZXMocykgewogICAgcmV0dXJuIHMucmVwbGFjZUFsbCgvJihbXjtdKyk7L2csIChhbGwsIGVudGl0eSkgPT4gewogICAgICBpZiAoZW50aXR5LnN1YnN0cmluZygwLCAyKSA9PT0gIiN4IikgewogICAgICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChwYXJzZUludChlbnRpdHkuc3Vic3RyaW5nKDIpLCAxNikpOwogICAgICB9IGVsc2UgaWYgKGVudGl0eS5zdWJzdHJpbmcoMCwgMSkgPT09ICIjIikgewogICAgICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChwYXJzZUludChlbnRpdHkuc3Vic3RyaW5nKDEpLCAxMCkpOwogICAgICB9CiAgICAgIHN3aXRjaCAoZW50aXR5KSB7CiAgICAgICAgY2FzZSAibHQiOgogICAgICAgICAgcmV0dXJuICI8IjsKICAgICAgICBjYXNlICJndCI6CiAgICAgICAgICByZXR1cm4gIj4iOwogICAgICAgIGNhc2UgImFtcCI6CiAgICAgICAgICByZXR1cm4gIiYiOwogICAgICAgIGNhc2UgInF1b3QiOgogICAgICAgICAgcmV0dXJuICciJzsKICAgICAgICBjYXNlICJhcG9zIjoKICAgICAgICAgIHJldHVybiAiJyI7CiAgICAgIH0KICAgICAgcmV0dXJuIHRoaXMub25SZXNvbHZlRW50aXR5KGVudGl0eSk7CiAgICB9KTsKICB9CiAgX3BhcnNlQ29udGVudChzLCBzdGFydCkgewogICAgY29uc3QgYXR0cmlidXRlcyA9IFtdOwogICAgbGV0IHBvcyA9IHN0YXJ0OwogICAgZnVuY3Rpb24gc2tpcFdzKCkgewogICAgICB3aGlsZSAocG9zIDwgcy5sZW5ndGggJiYgaXNXaGl0ZXNwYWNlKHMsIHBvcykpIHsKICAgICAgICArK3BvczsKICAgICAgfQogICAgfQogICAgd2hpbGUgKHBvcyA8IHMubGVuZ3RoICYmICFpc1doaXRlc3BhY2UocywgcG9zKSAmJiBzW3Bvc10gIT09ICI+IiAmJiBzW3Bvc10gIT09ICIvIikgewogICAgICArK3BvczsKICAgIH0KICAgIGNvbnN0IG5hbWUgPSBzLnN1YnN0cmluZyhzdGFydCwgcG9zKTsKICAgIHNraXBXcygpOwogICAgd2hpbGUgKHBvcyA8IHMubGVuZ3RoICYmIHNbcG9zXSAhPT0gIj4iICYmIHNbcG9zXSAhPT0gIi8iICYmIHNbcG9zXSAhPT0gIj8iKSB7CiAgICAgIHNraXBXcygpOwogICAgICBsZXQgYXR0ck5hbWUgPSAiIiwKICAgICAgICBhdHRyVmFsdWUgPSAiIjsKICAgICAgd2hpbGUgKHBvcyA8IHMubGVuZ3RoICYmICFpc1doaXRlc3BhY2UocywgcG9zKSAmJiBzW3Bvc10gIT09ICI9IikgewogICAgICAgIGF0dHJOYW1lICs9IHNbcG9zXTsKICAgICAgICArK3BvczsKICAgICAgfQogICAgICBza2lwV3MoKTsKICAgICAgaWYgKHNbcG9zXSAhPT0gIj0iKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgKytwb3M7CiAgICAgIHNraXBXcygpOwogICAgICBjb25zdCBhdHRyRW5kQ2hhciA9IHNbcG9zXTsKICAgICAgaWYgKGF0dHJFbmRDaGFyICE9PSAnIicgJiYgYXR0ckVuZENoYXIgIT09ICInIikgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IGF0dHJFbmRJbmRleCA9IHMuaW5kZXhPZihhdHRyRW5kQ2hhciwgKytwb3MpOwogICAgICBpZiAoYXR0ckVuZEluZGV4IDwgMCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGF0dHJWYWx1ZSA9IHMuc3Vic3RyaW5nKHBvcywgYXR0ckVuZEluZGV4KTsKICAgICAgYXR0cmlidXRlcy5wdXNoKHsKICAgICAgICBuYW1lOiBhdHRyTmFtZSwKICAgICAgICB2YWx1ZTogdGhpcy5fcmVzb2x2ZUVudGl0aWVzKGF0dHJWYWx1ZSkKICAgICAgfSk7CiAgICAgIHBvcyA9IGF0dHJFbmRJbmRleCArIDE7CiAgICAgIHNraXBXcygpOwogICAgfQogICAgcmV0dXJuIHsKICAgICAgbmFtZSwKICAgICAgYXR0cmlidXRlcywKICAgICAgcGFyc2VkOiBwb3MgLSBzdGFydAogICAgfTsKICB9CiAgX3BhcnNlUHJvY2Vzc2luZ0luc3RydWN0aW9uKHMsIHN0YXJ0KSB7CiAgICBsZXQgcG9zID0gc3RhcnQ7CiAgICBmdW5jdGlvbiBza2lwV3MoKSB7CiAgICAgIHdoaWxlIChwb3MgPCBzLmxlbmd0aCAmJiBpc1doaXRlc3BhY2UocywgcG9zKSkgewogICAgICAgICsrcG9zOwogICAgICB9CiAgICB9CiAgICB3aGlsZSAocG9zIDwgcy5sZW5ndGggJiYgIWlzV2hpdGVzcGFjZShzLCBwb3MpICYmIHNbcG9zXSAhPT0gIj4iICYmIHNbcG9zXSAhPT0gIj8iICYmIHNbcG9zXSAhPT0gIi8iKSB7CiAgICAgICsrcG9zOwogICAgfQogICAgY29uc3QgbmFtZSA9IHMuc3Vic3RyaW5nKHN0YXJ0LCBwb3MpOwogICAgc2tpcFdzKCk7CiAgICBjb25zdCBhdHRyU3RhcnQgPSBwb3M7CiAgICB3aGlsZSAocG9zIDwgcy5sZW5ndGggJiYgKHNbcG9zXSAhPT0gIj8iIHx8IHNbcG9zICsgMV0gIT09ICI+IikpIHsKICAgICAgKytwb3M7CiAgICB9CiAgICBjb25zdCB2YWx1ZSA9IHMuc3Vic3RyaW5nKGF0dHJTdGFydCwgcG9zKTsKICAgIHJldHVybiB7CiAgICAgIG5hbWUsCiAgICAgIHZhbHVlLAogICAgICBwYXJzZWQ6IHBvcyAtIHN0YXJ0CiAgICB9OwogIH0KICBwYXJzZVhtbChzKSB7CiAgICBsZXQgaSA9IDA7CiAgICB3aGlsZSAoaSA8IHMubGVuZ3RoKSB7CiAgICAgIGNvbnN0IGNoID0gc1tpXTsKICAgICAgbGV0IGogPSBpOwogICAgICBpZiAoY2ggPT09ICI8IikgewogICAgICAgICsrajsKICAgICAgICBjb25zdCBjaDIgPSBzW2pdOwogICAgICAgIGxldCBxOwogICAgICAgIHN3aXRjaCAoY2gyKSB7CiAgICAgICAgICBjYXNlICIvIjoKICAgICAgICAgICAgKytqOwogICAgICAgICAgICBxID0gcy5pbmRleE9mKCI+Iiwgaik7CiAgICAgICAgICAgIGlmIChxIDwgMCkgewogICAgICAgICAgICAgIHRoaXMub25FcnJvcihYTUxQYXJzZXJFcnJvckNvZGUuVW50ZXJtaW5hdGVkRWxlbWVudCk7CiAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMub25FbmRFbGVtZW50KHMuc3Vic3RyaW5nKGosIHEpKTsKICAgICAgICAgICAgaiA9IHEgKyAxOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgIj8iOgogICAgICAgICAgICArK2o7CiAgICAgICAgICAgIGNvbnN0IHBpID0gdGhpcy5fcGFyc2VQcm9jZXNzaW5nSW5zdHJ1Y3Rpb24ocywgaik7CiAgICAgICAgICAgIGlmIChzLnN1YnN0cmluZyhqICsgcGkucGFyc2VkLCBqICsgcGkucGFyc2VkICsgMikgIT09ICI/PiIpIHsKICAgICAgICAgICAgICB0aGlzLm9uRXJyb3IoWE1MUGFyc2VyRXJyb3JDb2RlLlVudGVybWluYXRlZFhtbERlY2xhcmF0aW9uKTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgdGhpcy5vblBpKHBpLm5hbWUsIHBpLnZhbHVlKTsKICAgICAgICAgICAgaiArPSBwaS5wYXJzZWQgKyAyOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgIiEiOgogICAgICAgICAgICBpZiAocy5zdWJzdHJpbmcoaiArIDEsIGogKyAzKSA9PT0gIi0tIikgewogICAgICAgICAgICAgIHEgPSBzLmluZGV4T2YoIi0tPiIsIGogKyAzKTsKICAgICAgICAgICAgICBpZiAocSA8IDApIHsKICAgICAgICAgICAgICAgIHRoaXMub25FcnJvcihYTUxQYXJzZXJFcnJvckNvZGUuVW50ZXJtaW5hdGVkQ29tbWVudCk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRoaXMub25Db21tZW50KHMuc3Vic3RyaW5nKGogKyAzLCBxKSk7CiAgICAgICAgICAgICAgaiA9IHEgKyAzOwogICAgICAgICAgICB9IGVsc2UgaWYgKHMuc3Vic3RyaW5nKGogKyAxLCBqICsgOCkgPT09ICJbQ0RBVEFbIikgewogICAgICAgICAgICAgIHEgPSBzLmluZGV4T2YoIl1dPiIsIGogKyA4KTsKICAgICAgICAgICAgICBpZiAocSA8IDApIHsKICAgICAgICAgICAgICAgIHRoaXMub25FcnJvcihYTUxQYXJzZXJFcnJvckNvZGUuVW50ZXJtaW5hdGVkQ2RhdCk7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIHRoaXMub25DZGF0YShzLnN1YnN0cmluZyhqICsgOCwgcSkpOwogICAgICAgICAgICAgIGogPSBxICsgMzsKICAgICAgICAgICAgfSBlbHNlIGlmIChzLnN1YnN0cmluZyhqICsgMSwgaiArIDgpID09PSAiRE9DVFlQRSIpIHsKICAgICAgICAgICAgICBjb25zdCBxMiA9IHMuaW5kZXhPZigiWyIsIGogKyA4KTsKICAgICAgICAgICAgICBsZXQgY29tcGxleERvY3R5cGUgPSBmYWxzZTsKICAgICAgICAgICAgICBxID0gcy5pbmRleE9mKCI+IiwgaiArIDgpOwogICAgICAgICAgICAgIGlmIChxIDwgMCkgewogICAgICAgICAgICAgICAgdGhpcy5vbkVycm9yKFhNTFBhcnNlckVycm9yQ29kZS5VbnRlcm1pbmF0ZWREb2N0eXBlRGVjbGFyYXRpb24pOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICAgIH0KICAgICAgICAgICAgICBpZiAocTIgPiAwICYmIHEgPiBxMikgewogICAgICAgICAgICAgICAgcSA9IHMuaW5kZXhPZigiXT4iLCBqICsgOCk7CiAgICAgICAgICAgICAgICBpZiAocSA8IDApIHsKICAgICAgICAgICAgICAgICAgdGhpcy5vbkVycm9yKFhNTFBhcnNlckVycm9yQ29kZS5VbnRlcm1pbmF0ZWREb2N0eXBlRGVjbGFyYXRpb24pOwogICAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICBjb21wbGV4RG9jdHlwZSA9IHRydWU7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGNvbnN0IGRvY3R5cGVDb250ZW50ID0gcy5zdWJzdHJpbmcoaiArIDgsIHEgKyAoY29tcGxleERvY3R5cGUgPyAxIDogMCkpOwogICAgICAgICAgICAgIHRoaXMub25Eb2N0eXBlKGRvY3R5cGVDb250ZW50KTsKICAgICAgICAgICAgICBqID0gcSArIChjb21wbGV4RG9jdHlwZSA/IDIgOiAxKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB0aGlzLm9uRXJyb3IoWE1MUGFyc2VyRXJyb3JDb2RlLk1hbGZvcm1lZEVsZW1lbnQpOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgIGNvbnN0IGNvbnRlbnQgPSB0aGlzLl9wYXJzZUNvbnRlbnQocywgaik7CiAgICAgICAgICAgIGlmIChjb250ZW50ID09PSBudWxsKSB7CiAgICAgICAgICAgICAgdGhpcy5vbkVycm9yKFhNTFBhcnNlckVycm9yQ29kZS5NYWxmb3JtZWRFbGVtZW50KTsKICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICAgICAgbGV0IGlzQ2xvc2VkID0gZmFsc2U7CiAgICAgICAgICAgIGlmIChzLnN1YnN0cmluZyhqICsgY29udGVudC5wYXJzZWQsIGogKyBjb250ZW50LnBhcnNlZCArIDIpID09PSAiLz4iKSB7CiAgICAgICAgICAgICAgaXNDbG9zZWQgPSB0cnVlOwogICAgICAgICAgICB9IGVsc2UgaWYgKHMuc3Vic3RyaW5nKGogKyBjb250ZW50LnBhcnNlZCwgaiArIGNvbnRlbnQucGFyc2VkICsgMSkgIT09ICI+IikgewogICAgICAgICAgICAgIHRoaXMub25FcnJvcihYTUxQYXJzZXJFcnJvckNvZGUuVW50ZXJtaW5hdGVkRWxlbWVudCk7CiAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHRoaXMub25CZWdpbkVsZW1lbnQoY29udGVudC5uYW1lLCBjb250ZW50LmF0dHJpYnV0ZXMsIGlzQ2xvc2VkKTsKICAgICAgICAgICAgaiArPSBjb250ZW50LnBhcnNlZCArIChpc0Nsb3NlZCA/IDIgOiAxKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIHdoaWxlIChqIDwgcy5sZW5ndGggJiYgc1tqXSAhPT0gIjwiKSB7CiAgICAgICAgICBqKys7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHRleHQgPSBzLnN1YnN0cmluZyhpLCBqKTsKICAgICAgICB0aGlzLm9uVGV4dCh0aGlzLl9yZXNvbHZlRW50aXRpZXModGV4dCkpOwogICAgICB9CiAgICAgIGkgPSBqOwogICAgfQogIH0KICBvblJlc29sdmVFbnRpdHkobmFtZSkgewogICAgcmV0dXJuIGAmJHtuYW1lfTtgOwogIH0KICBvblBpKG5hbWUsIHZhbHVlKSB7fQogIG9uQ29tbWVudCh0ZXh0KSB7fQogIG9uQ2RhdGEodGV4dCkge30KICBvbkRvY3R5cGUoZG9jdHlwZUNvbnRlbnQpIHt9CiAgb25UZXh0KHRleHQpIHt9CiAgb25CZWdpbkVsZW1lbnQobmFtZSwgYXR0cmlidXRlcywgaXNFbXB0eSkge30KICBvbkVuZEVsZW1lbnQobmFtZSkge30KICBvbkVycm9yKGNvZGUpIHt9Cn0KY2xhc3MgU2ltcGxlRE9NTm9kZSB7CiAgY29uc3RydWN0b3Iobm9kZU5hbWUsIG5vZGVWYWx1ZSkgewogICAgdGhpcy5ub2RlTmFtZSA9IG5vZGVOYW1lOwogICAgdGhpcy5ub2RlVmFsdWUgPSBub2RlVmFsdWU7CiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgInBhcmVudE5vZGUiLCB7CiAgICAgIHZhbHVlOiBudWxsLAogICAgICB3cml0YWJsZTogdHJ1ZQogICAgfSk7CiAgfQogIGdldCBmaXJzdENoaWxkKCkgewogICAgcmV0dXJuIHRoaXMuY2hpbGROb2Rlcz8uWzBdOwogIH0KICBnZXQgbmV4dFNpYmxpbmcoKSB7CiAgICBjb25zdCBjaGlsZE5vZGVzID0gdGhpcy5wYXJlbnROb2RlLmNoaWxkTm9kZXM7CiAgICBpZiAoIWNoaWxkTm9kZXMpIHsKICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgIH0KICAgIGNvbnN0IGluZGV4ID0gY2hpbGROb2Rlcy5pbmRleE9mKHRoaXMpOwogICAgaWYgKGluZGV4ID09PSAtMSkgewogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfQogICAgcmV0dXJuIGNoaWxkTm9kZXNbaW5kZXggKyAxXTsKICB9CiAgZ2V0IHRleHRDb250ZW50KCkgewogICAgaWYgKCF0aGlzLmNoaWxkTm9kZXMpIHsKICAgICAgcmV0dXJuIHRoaXMubm9kZVZhbHVlIHx8ICIiOwogICAgfQogICAgcmV0dXJuIHRoaXMuY2hpbGROb2Rlcy5tYXAoY2hpbGQgPT4gY2hpbGQudGV4dENvbnRlbnQpLmpvaW4oIiIpOwogIH0KICBnZXQgY2hpbGRyZW4oKSB7CiAgICByZXR1cm4gdGhpcy5jaGlsZE5vZGVzIHx8IFtdOwogIH0KICBoYXNDaGlsZE5vZGVzKCkgewogICAgcmV0dXJuIHRoaXMuY2hpbGROb2Rlcz8ubGVuZ3RoID4gMDsKICB9CiAgc2VhcmNoTm9kZShwYXRocywgcG9zKSB7CiAgICBpZiAocG9zID49IHBhdGhzLmxlbmd0aCkgewogICAgICByZXR1cm4gdGhpczsKICAgIH0KICAgIGNvbnN0IGNvbXBvbmVudCA9IHBhdGhzW3Bvc107CiAgICBpZiAoY29tcG9uZW50Lm5hbWUuc3RhcnRzV2l0aCgiIyIpICYmIHBvcyA8IHBhdGhzLmxlbmd0aCAtIDEpIHsKICAgICAgcmV0dXJuIHRoaXMuc2VhcmNoTm9kZShwYXRocywgcG9zICsgMSk7CiAgICB9CiAgICBjb25zdCBzdGFjayA9IFtdOwogICAgbGV0IG5vZGUgPSB0aGlzOwogICAgd2hpbGUgKHRydWUpIHsKICAgICAgaWYgKGNvbXBvbmVudC5uYW1lID09PSBub2RlLm5vZGVOYW1lKSB7CiAgICAgICAgaWYgKGNvbXBvbmVudC5wb3MgPT09IDApIHsKICAgICAgICAgIGNvbnN0IHJlcyA9IG5vZGUuc2VhcmNoTm9kZShwYXRocywgcG9zICsgMSk7CiAgICAgICAgICBpZiAocmVzICE9PSBudWxsKSB7CiAgICAgICAgICAgIHJldHVybiByZXM7CiAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIGlmIChzdGFjay5sZW5ndGggPT09IDApIHsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb25zdCBbcGFyZW50XSA9IHN0YWNrLnBvcCgpOwogICAgICAgICAgbGV0IHNpYmxpbmdQb3MgPSAwOwogICAgICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiBwYXJlbnQuY2hpbGROb2RlcykgewogICAgICAgICAgICBpZiAoY29tcG9uZW50Lm5hbWUgPT09IGNoaWxkLm5vZGVOYW1lKSB7CiAgICAgICAgICAgICAgaWYgKHNpYmxpbmdQb3MgPT09IGNvbXBvbmVudC5wb3MpIHsKICAgICAgICAgICAgICAgIHJldHVybiBjaGlsZC5zZWFyY2hOb2RlKHBhdGhzLCBwb3MgKyAxKTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgc2libGluZ1BvcysrOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gbm9kZS5zZWFyY2hOb2RlKHBhdGhzLCBwb3MgKyAxKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKG5vZGUuY2hpbGROb2Rlcz8ubGVuZ3RoID4gMCkgewogICAgICAgIHN0YWNrLnB1c2goW25vZGUsIDBdKTsKICAgICAgICBub2RlID0gbm9kZS5jaGlsZE5vZGVzWzBdOwogICAgICB9IGVsc2UgaWYgKHN0YWNrLmxlbmd0aCA9PT0gMCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9IGVsc2UgewogICAgICAgIHdoaWxlIChzdGFjay5sZW5ndGggIT09IDApIHsKICAgICAgICAgIGNvbnN0IFtwYXJlbnQsIGN1cnJlbnRQb3NdID0gc3RhY2sucG9wKCk7CiAgICAgICAgICBjb25zdCBuZXdQb3MgPSBjdXJyZW50UG9zICsgMTsKICAgICAgICAgIGlmIChuZXdQb3MgPCBwYXJlbnQuY2hpbGROb2Rlcy5sZW5ndGgpIHsKICAgICAgICAgICAgc3RhY2sucHVzaChbcGFyZW50LCBuZXdQb3NdKTsKICAgICAgICAgICAgbm9kZSA9IHBhcmVudC5jaGlsZE5vZGVzW25ld1Bvc107CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoc3RhY2subGVuZ3RoID09PSAwKSB7CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICB9CiAgZHVtcChidWZmZXIpIHsKICAgIGlmICh0aGlzLm5vZGVOYW1lID09PSAiI3RleHQiKSB7CiAgICAgIGJ1ZmZlci5wdXNoKGVuY29kZVRvWG1sU3RyaW5nKHRoaXMubm9kZVZhbHVlKSk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGJ1ZmZlci5wdXNoKGA8JHt0aGlzLm5vZGVOYW1lfWApOwogICAgaWYgKHRoaXMuYXR0cmlidXRlcykgewogICAgICBmb3IgKGNvbnN0IGF0dHJpYnV0ZSBvZiB0aGlzLmF0dHJpYnV0ZXMpIHsKICAgICAgICBidWZmZXIucHVzaChgICR7YXR0cmlidXRlLm5hbWV9PSIke2VuY29kZVRvWG1sU3RyaW5nKGF0dHJpYnV0ZS52YWx1ZSl9ImApOwogICAgICB9CiAgICB9CiAgICBpZiAodGhpcy5oYXNDaGlsZE5vZGVzKCkpIHsKICAgICAgYnVmZmVyLnB1c2goIj4iKTsKICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzLmNoaWxkTm9kZXMpIHsKICAgICAgICBjaGlsZC5kdW1wKGJ1ZmZlcik7CiAgICAgIH0KICAgICAgYnVmZmVyLnB1c2goYDwvJHt0aGlzLm5vZGVOYW1lfT5gKTsKICAgIH0gZWxzZSBpZiAodGhpcy5ub2RlVmFsdWUpIHsKICAgICAgYnVmZmVyLnB1c2goYD4ke2VuY29kZVRvWG1sU3RyaW5nKHRoaXMubm9kZVZhbHVlKX08LyR7dGhpcy5ub2RlTmFtZX0+YCk7CiAgICB9IGVsc2UgewogICAgICBidWZmZXIucHVzaCgiLz4iKTsKICAgIH0KICB9Cn0KY2xhc3MgU2ltcGxlWE1MUGFyc2VyIGV4dGVuZHMgWE1MUGFyc2VyQmFzZSB7CiAgY29uc3RydWN0b3IoewogICAgaGFzQXR0cmlidXRlcyA9IGZhbHNlLAogICAgbG93ZXJDYXNlTmFtZSA9IGZhbHNlCiAgfSkgewogICAgc3VwZXIoKTsKICAgIHRoaXMuX2N1cnJlbnRGcmFnbWVudCA9IG51bGw7CiAgICB0aGlzLl9zdGFjayA9IG51bGw7CiAgICB0aGlzLl9lcnJvckNvZGUgPSBYTUxQYXJzZXJFcnJvckNvZGUuTm9FcnJvcjsKICAgIHRoaXMuX2hhc0F0dHJpYnV0ZXMgPSBoYXNBdHRyaWJ1dGVzOwogICAgdGhpcy5fbG93ZXJDYXNlTmFtZSA9IGxvd2VyQ2FzZU5hbWU7CiAgfQogIHBhcnNlRnJvbVN0cmluZyhkYXRhKSB7CiAgICB0aGlzLl9jdXJyZW50RnJhZ21lbnQgPSBbXTsKICAgIHRoaXMuX3N0YWNrID0gW107CiAgICB0aGlzLl9lcnJvckNvZGUgPSBYTUxQYXJzZXJFcnJvckNvZGUuTm9FcnJvcjsKICAgIHRoaXMucGFyc2VYbWwoZGF0YSk7CiAgICBpZiAodGhpcy5fZXJyb3JDb2RlICE9PSBYTUxQYXJzZXJFcnJvckNvZGUuTm9FcnJvcikgewogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfQogICAgY29uc3QgW2RvY3VtZW50RWxlbWVudF0gPSB0aGlzLl9jdXJyZW50RnJhZ21lbnQ7CiAgICBpZiAoIWRvY3VtZW50RWxlbWVudCkgewogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfQogICAgcmV0dXJuIHsKICAgICAgZG9jdW1lbnRFbGVtZW50CiAgICB9OwogIH0KICBvblRleHQodGV4dCkgewogICAgaWYgKGlzV2hpdGVzcGFjZVN0cmluZyh0ZXh0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBub2RlID0gbmV3IFNpbXBsZURPTU5vZGUoIiN0ZXh0IiwgdGV4dCk7CiAgICB0aGlzLl9jdXJyZW50RnJhZ21lbnQucHVzaChub2RlKTsKICB9CiAgb25DZGF0YSh0ZXh0KSB7CiAgICBjb25zdCBub2RlID0gbmV3IFNpbXBsZURPTU5vZGUoIiN0ZXh0IiwgdGV4dCk7CiAgICB0aGlzLl9jdXJyZW50RnJhZ21lbnQucHVzaChub2RlKTsKICB9CiAgb25CZWdpbkVsZW1lbnQobmFtZSwgYXR0cmlidXRlcywgaXNFbXB0eSkgewogICAgaWYgKHRoaXMuX2xvd2VyQ2FzZU5hbWUpIHsKICAgICAgbmFtZSA9IG5hbWUudG9Mb3dlckNhc2UoKTsKICAgIH0KICAgIGNvbnN0IG5vZGUgPSBuZXcgU2ltcGxlRE9NTm9kZShuYW1lKTsKICAgIG5vZGUuY2hpbGROb2RlcyA9IFtdOwogICAgaWYgKHRoaXMuX2hhc0F0dHJpYnV0ZXMpIHsKICAgICAgbm9kZS5hdHRyaWJ1dGVzID0gYXR0cmlidXRlczsKICAgIH0KICAgIHRoaXMuX2N1cnJlbnRGcmFnbWVudC5wdXNoKG5vZGUpOwogICAgaWYgKGlzRW1wdHkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5fc3RhY2sucHVzaCh0aGlzLl9jdXJyZW50RnJhZ21lbnQpOwogICAgdGhpcy5fY3VycmVudEZyYWdtZW50ID0gbm9kZS5jaGlsZE5vZGVzOwogIH0KICBvbkVuZEVsZW1lbnQobmFtZSkgewogICAgdGhpcy5fY3VycmVudEZyYWdtZW50ID0gdGhpcy5fc3RhY2sucG9wKCkgfHwgW107CiAgICBjb25zdCBsYXN0RWxlbWVudCA9IHRoaXMuX2N1cnJlbnRGcmFnbWVudC5hdCgtMSk7CiAgICBpZiAoIWxhc3RFbGVtZW50KSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgZm9yIChjb25zdCBjaGlsZE5vZGUgb2YgbGFzdEVsZW1lbnQuY2hpbGROb2RlcykgewogICAgICBjaGlsZE5vZGUucGFyZW50Tm9kZSA9IGxhc3RFbGVtZW50OwogICAgfQogICAgcmV0dXJuIGxhc3RFbGVtZW50OwogIH0KICBvbkVycm9yKGNvZGUpIHsKICAgIHRoaXMuX2Vycm9yQ29kZSA9IGNvZGU7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9tZXRhZGF0YV9wYXJzZXIuanMKCgoKCgpjbGFzcyBNZXRhZGF0YVBhcnNlciB7CiAgY29uc3RydWN0b3IoZGF0YSkgewogICAgZGF0YSA9IHRoaXMuX3JlcGFpcihkYXRhKTsKICAgIGNvbnN0IHBhcnNlciA9IG5ldyBTaW1wbGVYTUxQYXJzZXIoewogICAgICBsb3dlckNhc2VOYW1lOiB0cnVlCiAgICB9KTsKICAgIGNvbnN0IHhtbERvY3VtZW50ID0gcGFyc2VyLnBhcnNlRnJvbVN0cmluZyhkYXRhKTsKICAgIHRoaXMuX21ldGFkYXRhTWFwID0gbmV3IE1hcCgpOwogICAgdGhpcy5fZGF0YSA9IGRhdGE7CiAgICBpZiAoeG1sRG9jdW1lbnQpIHsKICAgICAgdGhpcy5fcGFyc2UoeG1sRG9jdW1lbnQpOwogICAgfQogIH0KICBfcmVwYWlyKGRhdGEpIHsKICAgIHJldHVybiBkYXRhLnJlcGxhY2UoL15bXjxdKy8sICIiKS5yZXBsYWNlQWxsKC8+XFwzNzZcXDM3NyhbXjxdKykvZywgZnVuY3Rpb24gKGFsbCwgY29kZXMpIHsKICAgICAgY29uc3QgYnl0ZXMgPSBjb2Rlcy5yZXBsYWNlQWxsKC9cXChbMC0zXSkoWzAtN10pKFswLTddKS9nLCBmdW5jdGlvbiAoY29kZSwgZDEsIGQyLCBkMykgewogICAgICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKGQxICogNjQgKyBkMiAqIDggKyBkMyAqIDEpOwogICAgICB9KS5yZXBsYWNlQWxsKC8mKGFtcHxhcG9zfGd0fGx0fHF1b3QpOy9nLCBmdW5jdGlvbiAoc3RyLCBuYW1lKSB7CiAgICAgICAgc3dpdGNoIChuYW1lKSB7CiAgICAgICAgICBjYXNlICJhbXAiOgogICAgICAgICAgICByZXR1cm4gIiYiOwogICAgICAgICAgY2FzZSAiYXBvcyI6CiAgICAgICAgICAgIHJldHVybiAiJyI7CiAgICAgICAgICBjYXNlICJndCI6CiAgICAgICAgICAgIHJldHVybiAiPiI7CiAgICAgICAgICBjYXNlICJsdCI6CiAgICAgICAgICAgIHJldHVybiAiPCI7CiAgICAgICAgICBjYXNlICJxdW90IjoKICAgICAgICAgICAgcmV0dXJuICciJzsKICAgICAgICB9CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBfcmVwYWlyOiAke25hbWV9IGlzbid0IGRlZmluZWQuYCk7CiAgICAgIH0pOwogICAgICBjb25zdCBjaGFyQnVmID0gWyI+Il07CiAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGJ5dGVzLmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgICBjb25zdCBjb2RlID0gYnl0ZXMuY2hhckNvZGVBdChpKSAqIDI1NiArIGJ5dGVzLmNoYXJDb2RlQXQoaSArIDEpOwogICAgICAgIGlmIChjb2RlID49IDMyICYmIGNvZGUgPCAxMjcgJiYgY29kZSAhPT0gNjAgJiYgY29kZSAhPT0gNjIgJiYgY29kZSAhPT0gMzgpIHsKICAgICAgICAgIGNoYXJCdWYucHVzaChTdHJpbmcuZnJvbUNoYXJDb2RlKGNvZGUpKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY2hhckJ1Zi5wdXNoKCImI3giICsgKDB4MTAwMDAgKyBjb2RlKS50b1N0cmluZygxNikuc3Vic3RyaW5nKDEpICsgIjsiKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIGNoYXJCdWYuam9pbigiIik7CiAgICB9KTsKICB9CiAgX2dldFNlcXVlbmNlKGVudHJ5KSB7CiAgICBjb25zdCBuYW1lID0gZW50cnkubm9kZU5hbWU7CiAgICBpZiAobmFtZSAhPT0gInJkZjpiYWciICYmIG5hbWUgIT09ICJyZGY6c2VxIiAmJiBuYW1lICE9PSAicmRmOmFsdCIpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICByZXR1cm4gZW50cnkuY2hpbGROb2Rlcy5maWx0ZXIobm9kZSA9PiBub2RlLm5vZGVOYW1lID09PSAicmRmOmxpIik7CiAgfQogIF9wYXJzZUFycmF5KGVudHJ5KSB7CiAgICBpZiAoIWVudHJ5Lmhhc0NoaWxkTm9kZXMoKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBbc2VxTm9kZV0gPSBlbnRyeS5jaGlsZE5vZGVzOwogICAgY29uc3Qgc2VxdWVuY2UgPSB0aGlzLl9nZXRTZXF1ZW5jZShzZXFOb2RlKSB8fCBbXTsKICAgIHRoaXMuX21ldGFkYXRhTWFwLnNldChlbnRyeS5ub2RlTmFtZSwgc2VxdWVuY2UubWFwKG5vZGUgPT4gbm9kZS50ZXh0Q29udGVudC50cmltKCkpKTsKICB9CiAgX3BhcnNlKHhtbERvY3VtZW50KSB7CiAgICBsZXQgcmRmID0geG1sRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50OwogICAgaWYgKHJkZi5ub2RlTmFtZSAhPT0gInJkZjpyZGYiKSB7CiAgICAgIHJkZiA9IHJkZi5maXJzdENoaWxkOwogICAgICB3aGlsZSAocmRmICYmIHJkZi5ub2RlTmFtZSAhPT0gInJkZjpyZGYiKSB7CiAgICAgICAgcmRmID0gcmRmLm5leHRTaWJsaW5nOwogICAgICB9CiAgICB9CiAgICBpZiAoIXJkZiB8fCByZGYubm9kZU5hbWUgIT09ICJyZGY6cmRmIiB8fCAhcmRmLmhhc0NoaWxkTm9kZXMoKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGNvbnN0IGRlc2Mgb2YgcmRmLmNoaWxkTm9kZXMpIHsKICAgICAgaWYgKGRlc2Mubm9kZU5hbWUgIT09ICJyZGY6ZGVzY3JpcHRpb24iKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBlbnRyeSBvZiBkZXNjLmNoaWxkTm9kZXMpIHsKICAgICAgICBjb25zdCBuYW1lID0gZW50cnkubm9kZU5hbWU7CiAgICAgICAgc3dpdGNoIChuYW1lKSB7CiAgICAgICAgICBjYXNlICIjdGV4dCI6CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgY2FzZSAiZGM6Y3JlYXRvciI6CiAgICAgICAgICBjYXNlICJkYzpzdWJqZWN0IjoKICAgICAgICAgICAgdGhpcy5fcGFyc2VBcnJheShlbnRyeSk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICB0aGlzLl9tZXRhZGF0YU1hcC5zZXQobmFtZSwgZW50cnkudGV4dENvbnRlbnQudHJpbSgpKTsKICAgICAgfQogICAgfQogIH0KICBnZXQgc2VyaWFsaXphYmxlKCkgewogICAgcmV0dXJuIHsKICAgICAgcGFyc2VkRGF0YTogdGhpcy5fbWV0YWRhdGFNYXAsCiAgICAgIHJhd0RhdGE6IHRoaXMuX2RhdGEKICAgIH07CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9zdHJ1Y3RfdHJlZS5qcwoKCgoKCmNvbnN0IE1BWF9ERVBUSCA9IDQwOwpjb25zdCBTdHJ1Y3RFbGVtZW50VHlwZSA9IHsKICBQQUdFX0NPTlRFTlQ6IDEsCiAgU1RSRUFNX0NPTlRFTlQ6IDIsCiAgT0JKRUNUOiAzLAogIEFOTk9UQVRJT046IDQsCiAgRUxFTUVOVDogNQp9OwpjbGFzcyBTdHJ1Y3RUcmVlUm9vdCB7CiAgY29uc3RydWN0b3IoeHJlZiwgcm9vdERpY3QsIHJvb3RSZWYpIHsKICAgIHRoaXMueHJlZiA9IHhyZWY7CiAgICB0aGlzLmRpY3QgPSByb290RGljdDsKICAgIHRoaXMucmVmID0gcm9vdFJlZiBpbnN0YW5jZW9mIFJlZiA/IHJvb3RSZWYgOiBudWxsOwogICAgdGhpcy5yb2xlTWFwID0gbmV3IE1hcCgpOwogICAgdGhpcy5zdHJ1Y3RQYXJlbnRJZHMgPSBudWxsOwogIH0KICBpbml0KCkgewogICAgdGhpcy5yZWFkUm9sZU1hcCgpOwogIH0KICAjYWRkSWRUb1BhZ2UocGFnZVJlZiwgaWQsIHR5cGUpIHsKICAgIGlmICghKHBhZ2VSZWYgaW5zdGFuY2VvZiBSZWYpIHx8IGlkIDwgMCkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLnN0cnVjdFBhcmVudElkcyB8fD0gbmV3IFJlZlNldENhY2hlKCk7CiAgICBsZXQgaWRzID0gdGhpcy5zdHJ1Y3RQYXJlbnRJZHMuZ2V0KHBhZ2VSZWYpOwogICAgaWYgKCFpZHMpIHsKICAgICAgaWRzID0gW107CiAgICAgIHRoaXMuc3RydWN0UGFyZW50SWRzLnB1dChwYWdlUmVmLCBpZHMpOwogICAgfQogICAgaWRzLnB1c2goW2lkLCB0eXBlXSk7CiAgfQogIGFkZEFubm90YXRpb25JZFRvUGFnZShwYWdlUmVmLCBpZCkgewogICAgdGhpcy4jYWRkSWRUb1BhZ2UocGFnZVJlZiwgaWQsIFN0cnVjdEVsZW1lbnRUeXBlLkFOTk9UQVRJT04pOwogIH0KICByZWFkUm9sZU1hcCgpIHsKICAgIGNvbnN0IHJvbGVNYXBEaWN0ID0gdGhpcy5kaWN0LmdldCgiUm9sZU1hcCIpOwogICAgaWYgKCEocm9sZU1hcERpY3QgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiByb2xlTWFwRGljdCkgewogICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgdGhpcy5yb2xlTWFwLnNldChrZXksIHZhbHVlLm5hbWUpOwogICAgICB9CiAgICB9CiAgfQogIHN0YXRpYyBhc3luYyBjYW5DcmVhdGVTdHJ1Y3R1cmVUcmVlKHsKICAgIGNhdGFsb2dSZWYsCiAgICBwZGZNYW5hZ2VyLAogICAgbmV3QW5ub3RhdGlvbnNCeVBhZ2UKICB9KSB7CiAgICBpZiAoIShjYXRhbG9nUmVmIGluc3RhbmNlb2YgUmVmKSkgewogICAgICB3YXJuKCJDYW5ub3Qgc2F2ZSB0aGUgc3RydWN0IHRyZWU6IG5vIGNhdGFsb2cgcmVmZXJlbmNlLiIpOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBsZXQgbmV4dEtleSA9IDA7CiAgICBsZXQgaGFzTm90aGluZ1RvVXBkYXRlID0gdHJ1ZTsKICAgIGZvciAoY29uc3QgW3BhZ2VJbmRleCwgZWxlbWVudHNdIG9mIG5ld0Fubm90YXRpb25zQnlQYWdlKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICByZWY6IHBhZ2VSZWYKICAgICAgfSA9IGF3YWl0IHBkZk1hbmFnZXIuZ2V0UGFnZShwYWdlSW5kZXgpOwogICAgICBpZiAoIShwYWdlUmVmIGluc3RhbmNlb2YgUmVmKSkgewogICAgICAgIHdhcm4oYENhbm5vdCBzYXZlIHRoZSBzdHJ1Y3QgdHJlZTogcGFnZSAke3BhZ2VJbmRleH0gaGFzIG5vIHJlZi5gKTsKICAgICAgICBoYXNOb3RoaW5nVG9VcGRhdGUgPSB0cnVlOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBlbGVtZW50cykgewogICAgICAgIGlmIChlbGVtZW50LmFjY2Vzc2liaWxpdHlEYXRhPy50eXBlKSB7CiAgICAgICAgICBlbGVtZW50LnBhcmVudFRyZWVJZCA9IG5leHRLZXkrKzsKICAgICAgICAgIGhhc05vdGhpbmdUb1VwZGF0ZSA9IGZhbHNlOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKGhhc05vdGhpbmdUb1VwZGF0ZSkgewogICAgICBmb3IgKGNvbnN0IGVsZW1lbnRzIG9mIG5ld0Fubm90YXRpb25zQnlQYWdlLnZhbHVlcygpKSB7CiAgICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGVsZW1lbnRzKSB7CiAgICAgICAgICBkZWxldGUgZWxlbWVudC5wYXJlbnRUcmVlSWQ7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHJldHVybiB0cnVlOwogIH0KICBzdGF0aWMgYXN5bmMgY3JlYXRlU3RydWN0dXJlVHJlZSh7CiAgICBuZXdBbm5vdGF0aW9uc0J5UGFnZSwKICAgIHhyZWYsCiAgICBjYXRhbG9nUmVmLAogICAgcGRmTWFuYWdlciwKICAgIGNoYW5nZXMKICB9KSB7CiAgICBjb25zdCByb290ID0gYXdhaXQgcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJjbG9uZURpY3QiKTsKICAgIGNvbnN0IGNhY2hlID0gbmV3IFJlZlNldENhY2hlKCk7CiAgICBjYWNoZS5wdXQoY2F0YWxvZ1JlZiwgcm9vdCk7CiAgICBjb25zdCBzdHJ1Y3RUcmVlUm9vdFJlZiA9IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7CiAgICByb290LnNldCgiU3RydWN0VHJlZVJvb3QiLCBzdHJ1Y3RUcmVlUm9vdFJlZik7CiAgICBjb25zdCBzdHJ1Y3RUcmVlUm9vdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgc3RydWN0VHJlZVJvb3Quc2V0KCJUeXBlIiwgTmFtZS5nZXQoIlN0cnVjdFRyZWVSb290IikpOwogICAgY29uc3QgcGFyZW50VHJlZVJlZiA9IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7CiAgICBzdHJ1Y3RUcmVlUm9vdC5zZXQoIlBhcmVudFRyZWUiLCBwYXJlbnRUcmVlUmVmKTsKICAgIGNvbnN0IGtpZHMgPSBbXTsKICAgIHN0cnVjdFRyZWVSb290LnNldCgiSyIsIGtpZHMpOwogICAgY2FjaGUucHV0KHN0cnVjdFRyZWVSb290UmVmLCBzdHJ1Y3RUcmVlUm9vdCk7CiAgICBjb25zdCBwYXJlbnRUcmVlID0gbmV3IERpY3QoeHJlZik7CiAgICBjb25zdCBudW1zID0gW107CiAgICBwYXJlbnRUcmVlLnNldCgiTnVtcyIsIG51bXMpOwogICAgY29uc3QgbmV4dEtleSA9IGF3YWl0IHRoaXMuI3dyaXRlS2lkcyh7CiAgICAgIG5ld0Fubm90YXRpb25zQnlQYWdlLAogICAgICBzdHJ1Y3RUcmVlUm9vdFJlZiwKICAgICAgc3RydWN0VHJlZVJvb3Q6IG51bGwsCiAgICAgIGtpZHMsCiAgICAgIG51bXMsCiAgICAgIHhyZWYsCiAgICAgIHBkZk1hbmFnZXIsCiAgICAgIGNoYW5nZXMsCiAgICAgIGNhY2hlCiAgICB9KTsKICAgIHN0cnVjdFRyZWVSb290LnNldCgiUGFyZW50VHJlZU5leHRLZXkiLCBuZXh0S2V5KTsKICAgIGNhY2hlLnB1dChwYXJlbnRUcmVlUmVmLCBwYXJlbnRUcmVlKTsKICAgIGZvciAoY29uc3QgW3JlZiwgb2JqXSBvZiBjYWNoZS5pdGVtcygpKSB7CiAgICAgIGNoYW5nZXMucHV0KHJlZiwgewogICAgICAgIGRhdGE6IG9iagogICAgICB9KTsKICAgIH0KICB9CiAgYXN5bmMgY2FuVXBkYXRlU3RydWN0VHJlZSh7CiAgICBwZGZNYW5hZ2VyLAogICAgbmV3QW5ub3RhdGlvbnNCeVBhZ2UKICB9KSB7CiAgICBpZiAoIXRoaXMucmVmKSB7CiAgICAgIHdhcm4oIkNhbm5vdCB1cGRhdGUgdGhlIHN0cnVjdCB0cmVlOiBubyByb290IHJlZmVyZW5jZS4iKTsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgbGV0IG5leHRLZXkgPSB0aGlzLmRpY3QuZ2V0KCJQYXJlbnRUcmVlTmV4dEtleSIpOwogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKG5leHRLZXkpIHx8IG5leHRLZXkgPCAwKSB7CiAgICAgIHdhcm4oIkNhbm5vdCB1cGRhdGUgdGhlIHN0cnVjdCB0cmVlOiBpbnZhbGlkIG5leHQga2V5LiIpOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBjb25zdCBwYXJlbnRUcmVlID0gdGhpcy5kaWN0LmdldCgiUGFyZW50VHJlZSIpOwogICAgaWYgKCEocGFyZW50VHJlZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHdhcm4oIkNhbm5vdCB1cGRhdGUgdGhlIHN0cnVjdCB0cmVlOiBQYXJlbnRUcmVlIGlzbid0IGEgZGljdC4iKTsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgY29uc3QgbnVtcyA9IHBhcmVudFRyZWUuZ2V0KCJOdW1zIik7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkobnVtcykpIHsKICAgICAgd2FybigiQ2Fubm90IHVwZGF0ZSB0aGUgc3RydWN0IHRyZWU6IG51bXMgaXNuJ3QgYW4gYXJyYXkuIik7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGNvbnN0IG51bWJlclRyZWUgPSBuZXcgTnVtYmVyVHJlZShwYXJlbnRUcmVlLCB0aGlzLnhyZWYpOwogICAgZm9yIChjb25zdCBwYWdlSW5kZXggb2YgbmV3QW5ub3RhdGlvbnNCeVBhZ2Uua2V5cygpKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBwYWdlRGljdAogICAgICB9ID0gYXdhaXQgcGRmTWFuYWdlci5nZXRQYWdlKHBhZ2VJbmRleCk7CiAgICAgIGlmICghcGFnZURpY3QuaGFzKCJTdHJ1Y3RQYXJlbnRzIikpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBpZCA9IHBhZ2VEaWN0LmdldCgiU3RydWN0UGFyZW50cyIpOwogICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoaWQpIHx8ICFBcnJheS5pc0FycmF5KG51bWJlclRyZWUuZ2V0KGlkKSkpIHsKICAgICAgICB3YXJuKGBDYW5ub3Qgc2F2ZSB0aGUgc3RydWN0IHRyZWU6IHBhZ2UgJHtwYWdlSW5kZXh9IGhhcyBhIHdyb25nIGlkLmApOwogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgfQogICAgbGV0IGhhc05vdGhpbmdUb1VwZGF0ZSA9IHRydWU7CiAgICBmb3IgKGNvbnN0IFtwYWdlSW5kZXgsIGVsZW1lbnRzXSBvZiBuZXdBbm5vdGF0aW9uc0J5UGFnZSkgewogICAgICBjb25zdCB7CiAgICAgICAgcGFnZURpY3QKICAgICAgfSA9IGF3YWl0IHBkZk1hbmFnZXIuZ2V0UGFnZShwYWdlSW5kZXgpOwogICAgICBTdHJ1Y3RUcmVlUm9vdC4jY29sbGVjdFBhcmVudHMoewogICAgICAgIGVsZW1lbnRzLAogICAgICAgIHhyZWY6IHRoaXMueHJlZiwKICAgICAgICBwYWdlRGljdCwKICAgICAgICBudW1iZXJUcmVlCiAgICAgIH0pOwogICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZWxlbWVudHMpIHsKICAgICAgICBpZiAoZWxlbWVudC5hY2Nlc3NpYmlsaXR5RGF0YT8udHlwZSkgewogICAgICAgICAgaWYgKCEoZWxlbWVudC5hY2Nlc3NpYmlsaXR5RGF0YS5zdHJ1Y3RQYXJlbnQgPj0gMCkpIHsKICAgICAgICAgICAgZWxlbWVudC5wYXJlbnRUcmVlSWQgPSBuZXh0S2V5Kys7CiAgICAgICAgICB9CiAgICAgICAgICBoYXNOb3RoaW5nVG9VcGRhdGUgPSBmYWxzZTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChoYXNOb3RoaW5nVG9VcGRhdGUpIHsKICAgICAgZm9yIChjb25zdCBlbGVtZW50cyBvZiBuZXdBbm5vdGF0aW9uc0J5UGFnZS52YWx1ZXMoKSkgewogICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBlbGVtZW50cykgewogICAgICAgICAgZGVsZXRlIGVsZW1lbnQucGFyZW50VHJlZUlkOwogICAgICAgICAgZGVsZXRlIGVsZW1lbnQuc3RydWN0VHJlZVBhcmVudDsKICAgICAgICB9CiAgICAgIH0KICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgcmV0dXJuIHRydWU7CiAgfQogIGFzeW5jIHVwZGF0ZVN0cnVjdHVyZVRyZWUoewogICAgbmV3QW5ub3RhdGlvbnNCeVBhZ2UsCiAgICBwZGZNYW5hZ2VyLAogICAgY2hhbmdlcwogIH0pIHsKICAgIGNvbnN0IHsKICAgICAgcmVmOiBzdHJ1Y3RUcmVlUm9vdFJlZiwKICAgICAgeHJlZgogICAgfSA9IHRoaXM7CiAgICBjb25zdCBzdHJ1Y3RUcmVlUm9vdCA9IHRoaXMuZGljdC5jbG9uZSgpOwogICAgY29uc3QgY2FjaGUgPSBuZXcgUmVmU2V0Q2FjaGUoKTsKICAgIGNhY2hlLnB1dChzdHJ1Y3RUcmVlUm9vdFJlZiwgc3RydWN0VHJlZVJvb3QpOwogICAgbGV0IHBhcmVudFRyZWVSZWYgPSBzdHJ1Y3RUcmVlUm9vdC5nZXRSYXcoIlBhcmVudFRyZWUiKTsKICAgIGxldCBwYXJlbnRUcmVlOwogICAgaWYgKHBhcmVudFRyZWVSZWYgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgcGFyZW50VHJlZSA9IHhyZWYuZmV0Y2gocGFyZW50VHJlZVJlZik7CiAgICB9IGVsc2UgewogICAgICBwYXJlbnRUcmVlID0gcGFyZW50VHJlZVJlZjsKICAgICAgcGFyZW50VHJlZVJlZiA9IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7CiAgICAgIHN0cnVjdFRyZWVSb290LnNldCgiUGFyZW50VHJlZSIsIHBhcmVudFRyZWVSZWYpOwogICAgfQogICAgcGFyZW50VHJlZSA9IHBhcmVudFRyZWUuY2xvbmUoKTsKICAgIGNhY2hlLnB1dChwYXJlbnRUcmVlUmVmLCBwYXJlbnRUcmVlKTsKICAgIGxldCBudW1zID0gcGFyZW50VHJlZS5nZXRSYXcoIk51bXMiKTsKICAgIGxldCBudW1zUmVmID0gbnVsbDsKICAgIGlmIChudW1zIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgIG51bXNSZWYgPSBudW1zOwogICAgICBudW1zID0geHJlZi5mZXRjaChudW1zUmVmKTsKICAgIH0KICAgIG51bXMgPSBudW1zLnNsaWNlKCk7CiAgICBpZiAoIW51bXNSZWYpIHsKICAgICAgcGFyZW50VHJlZS5zZXQoIk51bXMiLCBudW1zKTsKICAgIH0KICAgIGNvbnN0IG5ld05leHRLZXkgPSBhd2FpdCBTdHJ1Y3RUcmVlUm9vdC4jd3JpdGVLaWRzKHsKICAgICAgbmV3QW5ub3RhdGlvbnNCeVBhZ2UsCiAgICAgIHN0cnVjdFRyZWVSb290UmVmLAogICAgICBzdHJ1Y3RUcmVlUm9vdDogdGhpcywKICAgICAga2lkczogbnVsbCwKICAgICAgbnVtcywKICAgICAgeHJlZiwKICAgICAgcGRmTWFuYWdlciwKICAgICAgY2hhbmdlcywKICAgICAgY2FjaGUKICAgIH0pOwogICAgaWYgKG5ld05leHRLZXkgPT09IC0xKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHN0cnVjdFRyZWVSb290LnNldCgiUGFyZW50VHJlZU5leHRLZXkiLCBuZXdOZXh0S2V5KTsKICAgIGlmIChudW1zUmVmKSB7CiAgICAgIGNhY2hlLnB1dChudW1zUmVmLCBudW1zKTsKICAgIH0KICAgIGZvciAoY29uc3QgW3JlZiwgb2JqXSBvZiBjYWNoZS5pdGVtcygpKSB7CiAgICAgIGNoYW5nZXMucHV0KHJlZiwgewogICAgICAgIGRhdGE6IG9iagogICAgICB9KTsKICAgIH0KICB9CiAgc3RhdGljIGFzeW5jICN3cml0ZUtpZHMoewogICAgbmV3QW5ub3RhdGlvbnNCeVBhZ2UsCiAgICBzdHJ1Y3RUcmVlUm9vdFJlZiwKICAgIHN0cnVjdFRyZWVSb290LAogICAga2lkcywKICAgIG51bXMsCiAgICB4cmVmLAogICAgcGRmTWFuYWdlciwKICAgIGNoYW5nZXMsCiAgICBjYWNoZQogIH0pIHsKICAgIGNvbnN0IG9ianIgPSBOYW1lLmdldCgiT0JKUiIpOwogICAgbGV0IG5leHRLZXkgPSAtMTsKICAgIGxldCBzdHJ1Y3RUcmVlUGFnZU9ianM7CiAgICBmb3IgKGNvbnN0IFtwYWdlSW5kZXgsIGVsZW1lbnRzXSBvZiBuZXdBbm5vdGF0aW9uc0J5UGFnZSkgewogICAgICBjb25zdCBwYWdlID0gYXdhaXQgcGRmTWFuYWdlci5nZXRQYWdlKHBhZ2VJbmRleCk7CiAgICAgIGNvbnN0IHsKICAgICAgICByZWY6IHBhZ2VSZWYKICAgICAgfSA9IHBhZ2U7CiAgICAgIGNvbnN0IGlzUGFnZVJlZiA9IHBhZ2VSZWYgaW5zdGFuY2VvZiBSZWY7CiAgICAgIGZvciAoY29uc3QgewogICAgICAgIGFjY2Vzc2liaWxpdHlEYXRhLAogICAgICAgIHJlZiwKICAgICAgICBwYXJlbnRUcmVlSWQsCiAgICAgICAgc3RydWN0VHJlZVBhcmVudAogICAgICB9IG9mIGVsZW1lbnRzKSB7CiAgICAgICAgaWYgKCFhY2Nlc3NpYmlsaXR5RGF0YT8udHlwZSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHsKICAgICAgICAgIHN0cnVjdFBhcmVudAogICAgICAgIH0gPSBhY2Nlc3NpYmlsaXR5RGF0YTsKICAgICAgICBpZiAoc3RydWN0VHJlZVJvb3QgJiYgTnVtYmVyLmlzSW50ZWdlcihzdHJ1Y3RQYXJlbnQpICYmIHN0cnVjdFBhcmVudCA+PSAwKSB7CiAgICAgICAgICBsZXQgb2JqcyA9IChzdHJ1Y3RUcmVlUGFnZU9ianMgfHw9IG5ldyBNYXAoKSkuZ2V0KHBhZ2VJbmRleCk7CiAgICAgICAgICBpZiAob2JqcyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgICAgICAgIGNvbnN0IHN0cnVjdFRyZWVQYWdlID0gbmV3IFN0cnVjdFRyZWVQYWdlKHN0cnVjdFRyZWVSb290LCBwYWdlLnBhZ2VEaWN0KTsKICAgICAgICAgICAgb2JqcyA9IHN0cnVjdFRyZWVQYWdlLmNvbGxlY3RPYmplY3RzKHBhZ2VSZWYpOwogICAgICAgICAgICBzdHJ1Y3RUcmVlUGFnZU9ianMuc2V0KHBhZ2VJbmRleCwgb2Jqcyk7CiAgICAgICAgICB9CiAgICAgICAgICBjb25zdCBvYmpSZWYgPSBvYmpzPy5nZXQoc3RydWN0UGFyZW50KTsKICAgICAgICAgIGlmIChvYmpSZWYpIHsKICAgICAgICAgICAgY29uc3QgdGFnRGljdCA9IHhyZWYuZmV0Y2gob2JqUmVmKS5jbG9uZSgpOwogICAgICAgICAgICBTdHJ1Y3RUcmVlUm9vdC4jd3JpdGVQcm9wZXJ0aWVzKHRhZ0RpY3QsIGFjY2Vzc2liaWxpdHlEYXRhKTsKICAgICAgICAgICAgY2hhbmdlcy5wdXQob2JqUmVmLCB7CiAgICAgICAgICAgICAgZGF0YTogdGFnRGljdAogICAgICAgICAgICB9KTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG5leHRLZXkgPSBNYXRoLm1heChuZXh0S2V5LCBwYXJlbnRUcmVlSWQpOwogICAgICAgIGNvbnN0IHRhZ1JlZiA9IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7CiAgICAgICAgY29uc3QgdGFnRGljdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgICAgIFN0cnVjdFRyZWVSb290LiN3cml0ZVByb3BlcnRpZXModGFnRGljdCwgYWNjZXNzaWJpbGl0eURhdGEpOwogICAgICAgIGF3YWl0IHRoaXMuI3VwZGF0ZVBhcmVudFRhZyh7CiAgICAgICAgICBzdHJ1Y3RUcmVlUGFyZW50LAogICAgICAgICAgdGFnRGljdCwKICAgICAgICAgIG5ld1RhZ1JlZjogdGFnUmVmLAogICAgICAgICAgc3RydWN0VHJlZVJvb3RSZWYsCiAgICAgICAgICBmYWxsYmFja0tpZHM6IGtpZHMsCiAgICAgICAgICB4cmVmLAogICAgICAgICAgY2FjaGUKICAgICAgICB9KTsKICAgICAgICBjb25zdCBvYmpEaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICAgICAgdGFnRGljdC5zZXQoIksiLCBvYmpEaWN0KTsKICAgICAgICBvYmpEaWN0LnNldCgiVHlwZSIsIG9ianIpOwogICAgICAgIGlmIChpc1BhZ2VSZWYpIHsKICAgICAgICAgIG9iakRpY3Quc2V0KCJQZyIsIHBhZ2VSZWYpOwogICAgICAgIH0KICAgICAgICBvYmpEaWN0LnNldCgiT2JqIiwgcmVmKTsKICAgICAgICBjYWNoZS5wdXQodGFnUmVmLCB0YWdEaWN0KTsKICAgICAgICBudW1zLnB1c2gocGFyZW50VHJlZUlkLCB0YWdSZWYpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbmV4dEtleSArIDE7CiAgfQogIHN0YXRpYyAjd3JpdGVQcm9wZXJ0aWVzKHRhZ0RpY3QsIHsKICAgIHR5cGUsCiAgICB0aXRsZSwKICAgIGxhbmcsCiAgICBhbHQsCiAgICBleHBhbmRlZCwKICAgIGFjdHVhbFRleHQKICB9KSB7CiAgICB0YWdEaWN0LnNldCgiUyIsIE5hbWUuZ2V0KHR5cGUpKTsKICAgIGlmICh0aXRsZSkgewogICAgICB0YWdEaWN0LnNldCgiVCIsIHN0cmluZ1RvQXNjaWlPclVURjE2QkUodGl0bGUpKTsKICAgIH0KICAgIGlmIChsYW5nKSB7CiAgICAgIHRhZ0RpY3Quc2V0KCJMYW5nIiwgc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRShsYW5nKSk7CiAgICB9CiAgICBpZiAoYWx0KSB7CiAgICAgIHRhZ0RpY3Quc2V0KCJBbHQiLCBzdHJpbmdUb0FzY2lpT3JVVEYxNkJFKGFsdCkpOwogICAgfQogICAgaWYgKGV4cGFuZGVkKSB7CiAgICAgIHRhZ0RpY3Quc2V0KCJFIiwgc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRShleHBhbmRlZCkpOwogICAgfQogICAgaWYgKGFjdHVhbFRleHQpIHsKICAgICAgdGFnRGljdC5zZXQoIkFjdHVhbFRleHQiLCBzdHJpbmdUb0FzY2lpT3JVVEYxNkJFKGFjdHVhbFRleHQpKTsKICAgIH0KICB9CiAgc3RhdGljICNjb2xsZWN0UGFyZW50cyh7CiAgICBlbGVtZW50cywKICAgIHhyZWYsCiAgICBwYWdlRGljdCwKICAgIG51bWJlclRyZWUKICB9KSB7CiAgICBjb25zdCBpZFRvRWxlbWVudHMgPSBuZXcgTWFwKCk7CiAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZWxlbWVudHMpIHsKICAgICAgaWYgKGVsZW1lbnQuc3RydWN0VHJlZVBhcmVudElkKSB7CiAgICAgICAgY29uc3QgaWQgPSBwYXJzZUludChlbGVtZW50LnN0cnVjdFRyZWVQYXJlbnRJZC5zcGxpdCgiX21jIilbMV0sIDEwKTsKICAgICAgICBsZXQgZWxlbXMgPSBpZFRvRWxlbWVudHMuZ2V0KGlkKTsKICAgICAgICBpZiAoIWVsZW1zKSB7CiAgICAgICAgICBlbGVtcyA9IFtdOwogICAgICAgICAgaWRUb0VsZW1lbnRzLnNldChpZCwgZWxlbXMpOwogICAgICAgIH0KICAgICAgICBlbGVtcy5wdXNoKGVsZW1lbnQpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBpZCA9IHBhZ2VEaWN0LmdldCgiU3RydWN0UGFyZW50cyIpOwogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGlkKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBwYXJlbnRBcnJheSA9IG51bWJlclRyZWUuZ2V0KGlkKTsKICAgIGNvbnN0IHVwZGF0ZUVsZW1lbnQgPSAoa2lkLCBwYWdlS2lkLCBraWRSZWYpID0+IHsKICAgICAgY29uc3QgZWxlbXMgPSBpZFRvRWxlbWVudHMuZ2V0KGtpZCk7CiAgICAgIGlmIChlbGVtcykgewogICAgICAgIGNvbnN0IHBhcmVudFJlZiA9IHBhZ2VLaWQuZ2V0UmF3KCJQIik7CiAgICAgICAgY29uc3QgcGFyZW50RGljdCA9IHhyZWYuZmV0Y2hJZlJlZihwYXJlbnRSZWYpOwogICAgICAgIGlmIChwYXJlbnRSZWYgaW5zdGFuY2VvZiBSZWYgJiYgcGFyZW50RGljdCBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICAgIGNvbnN0IHBhcmFtcyA9IHsKICAgICAgICAgICAgcmVmOiBraWRSZWYsCiAgICAgICAgICAgIGRpY3Q6IHBhZ2VLaWQKICAgICAgICAgIH07CiAgICAgICAgICBmb3IgKGNvbnN0IGVsZW1lbnQgb2YgZWxlbXMpIHsKICAgICAgICAgICAgZWxlbWVudC5zdHJ1Y3RUcmVlUGFyZW50ID0gcGFyYW1zOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICByZXR1cm4gZmFsc2U7CiAgICB9OwogICAgZm9yIChjb25zdCBraWRSZWYgb2YgcGFyZW50QXJyYXkpIHsKICAgICAgaWYgKCEoa2lkUmVmIGluc3RhbmNlb2YgUmVmKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IHBhZ2VLaWQgPSB4cmVmLmZldGNoKGtpZFJlZik7CiAgICAgIGNvbnN0IGsgPSBwYWdlS2lkLmdldCgiSyIpOwogICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihrKSkgewogICAgICAgIHVwZGF0ZUVsZW1lbnQoaywgcGFnZUtpZCwga2lkUmVmKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoIUFycmF5LmlzQXJyYXkoaykpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBmb3IgKGxldCBraWQgb2YgaykgewogICAgICAgIGtpZCA9IHhyZWYuZmV0Y2hJZlJlZihraWQpOwogICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKGtpZCkgJiYgdXBkYXRlRWxlbWVudChraWQsIHBhZ2VLaWQsIGtpZFJlZikpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBpZiAoIShraWQgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmICghaXNOYW1lKGtpZC5nZXQoIlR5cGUiKSwgIk1DUiIpKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgY29uc3QgbWNpZCA9IGtpZC5nZXQoIk1DSUQiKTsKICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihtY2lkKSAmJiB1cGRhdGVFbGVtZW50KG1jaWQsIHBhZ2VLaWQsIGtpZFJlZikpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KICBzdGF0aWMgYXN5bmMgI3VwZGF0ZVBhcmVudFRhZyh7CiAgICBzdHJ1Y3RUcmVlUGFyZW50LAogICAgdGFnRGljdCwKICAgIG5ld1RhZ1JlZiwKICAgIHN0cnVjdFRyZWVSb290UmVmLAogICAgZmFsbGJhY2tLaWRzLAogICAgeHJlZiwKICAgIGNhY2hlCiAgfSkgewogICAgbGV0IHJlZiA9IG51bGw7CiAgICBsZXQgcGFyZW50UmVmOwogICAgaWYgKHN0cnVjdFRyZWVQYXJlbnQpIHsKICAgICAgKHsKICAgICAgICByZWYKICAgICAgfSA9IHN0cnVjdFRyZWVQYXJlbnQpOwogICAgICBwYXJlbnRSZWYgPSBzdHJ1Y3RUcmVlUGFyZW50LmRpY3QuZ2V0UmF3KCJQIikgfHwgc3RydWN0VHJlZVJvb3RSZWY7CiAgICB9IGVsc2UgewogICAgICBwYXJlbnRSZWYgPSBzdHJ1Y3RUcmVlUm9vdFJlZjsKICAgIH0KICAgIHRhZ0RpY3Quc2V0KCJQIiwgcGFyZW50UmVmKTsKICAgIGNvbnN0IHBhcmVudERpY3QgPSB4cmVmLmZldGNoSWZSZWYocGFyZW50UmVmKTsKICAgIGlmICghcGFyZW50RGljdCkgewogICAgICBmYWxsYmFja0tpZHMucHVzaChuZXdUYWdSZWYpOwogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgY2FjaGVkUGFyZW50RGljdCA9IGNhY2hlLmdldChwYXJlbnRSZWYpOwogICAgaWYgKCFjYWNoZWRQYXJlbnREaWN0KSB7CiAgICAgIGNhY2hlZFBhcmVudERpY3QgPSBwYXJlbnREaWN0LmNsb25lKCk7CiAgICAgIGNhY2hlLnB1dChwYXJlbnRSZWYsIGNhY2hlZFBhcmVudERpY3QpOwogICAgfQogICAgY29uc3QgcGFyZW50S2lkc1JhdyA9IGNhY2hlZFBhcmVudERpY3QuZ2V0UmF3KCJLIik7CiAgICBsZXQgY2FjaGVkUGFyZW50S2lkcyA9IHBhcmVudEtpZHNSYXcgaW5zdGFuY2VvZiBSZWYgPyBjYWNoZS5nZXQocGFyZW50S2lkc1JhdykgOiBudWxsOwogICAgaWYgKCFjYWNoZWRQYXJlbnRLaWRzKSB7CiAgICAgIGNhY2hlZFBhcmVudEtpZHMgPSB4cmVmLmZldGNoSWZSZWYocGFyZW50S2lkc1Jhdyk7CiAgICAgIGNhY2hlZFBhcmVudEtpZHMgPSBBcnJheS5pc0FycmF5KGNhY2hlZFBhcmVudEtpZHMpID8gY2FjaGVkUGFyZW50S2lkcy5zbGljZSgpIDogW3BhcmVudEtpZHNSYXddOwogICAgICBjb25zdCBwYXJlbnRLaWRzUmVmID0geHJlZi5nZXROZXdUZW1wb3JhcnlSZWYoKTsKICAgICAgY2FjaGVkUGFyZW50RGljdC5zZXQoIksiLCBwYXJlbnRLaWRzUmVmKTsKICAgICAgY2FjaGUucHV0KHBhcmVudEtpZHNSZWYsIGNhY2hlZFBhcmVudEtpZHMpOwogICAgfQogICAgY29uc3QgaW5kZXggPSBjYWNoZWRQYXJlbnRLaWRzLmluZGV4T2YocmVmKTsKICAgIGNhY2hlZFBhcmVudEtpZHMuc3BsaWNlKGluZGV4ID49IDAgPyBpbmRleCArIDEgOiBjYWNoZWRQYXJlbnRLaWRzLmxlbmd0aCwgMCwgbmV3VGFnUmVmKTsKICB9Cn0KY2xhc3MgU3RydWN0RWxlbWVudE5vZGUgewogIGNvbnN0cnVjdG9yKHRyZWUsIGRpY3QpIHsKICAgIHRoaXMudHJlZSA9IHRyZWU7CiAgICB0aGlzLnhyZWYgPSB0cmVlLnhyZWY7CiAgICB0aGlzLmRpY3QgPSBkaWN0OwogICAgdGhpcy5raWRzID0gW107CiAgICB0aGlzLnBhcnNlS2lkcygpOwogIH0KICBnZXQgcm9sZSgpIHsKICAgIGNvbnN0IG5hbWVPYmogPSB0aGlzLmRpY3QuZ2V0KCJTIik7CiAgICBjb25zdCBuYW1lID0gbmFtZU9iaiBpbnN0YW5jZW9mIE5hbWUgPyBuYW1lT2JqLm5hbWUgOiAiIjsKICAgIGNvbnN0IHsKICAgICAgcm9vdAogICAgfSA9IHRoaXMudHJlZTsKICAgIHJldHVybiByb290LnJvbGVNYXAuZ2V0KG5hbWUpID8/IG5hbWU7CiAgfQogIHBhcnNlS2lkcygpIHsKICAgIGxldCBwYWdlT2JqSWQgPSBudWxsOwogICAgY29uc3Qgb2JqUmVmID0gdGhpcy5kaWN0LmdldFJhdygiUGciKTsKICAgIGlmIChvYmpSZWYgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgcGFnZU9iaklkID0gb2JqUmVmLnRvU3RyaW5nKCk7CiAgICB9CiAgICBjb25zdCBraWRzID0gdGhpcy5kaWN0LmdldCgiSyIpOwogICAgaWYgKEFycmF5LmlzQXJyYXkoa2lkcykpIHsKICAgICAgZm9yIChjb25zdCBraWQgb2Yga2lkcykgewogICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLnBhcnNlS2lkKHBhZ2VPYmpJZCwgdGhpcy54cmVmLmZldGNoSWZSZWYoa2lkKSk7CiAgICAgICAgaWYgKGVsZW1lbnQpIHsKICAgICAgICAgIHRoaXMua2lkcy5wdXNoKGVsZW1lbnQpOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgY29uc3QgZWxlbWVudCA9IHRoaXMucGFyc2VLaWQocGFnZU9iaklkLCBraWRzKTsKICAgICAgaWYgKGVsZW1lbnQpIHsKICAgICAgICB0aGlzLmtpZHMucHVzaChlbGVtZW50KTsKICAgICAgfQogICAgfQogIH0KICBwYXJzZUtpZChwYWdlT2JqSWQsIGtpZCkgewogICAgaWYgKE51bWJlci5pc0ludGVnZXIoa2lkKSkgewogICAgICBpZiAodGhpcy50cmVlLnBhZ2VEaWN0Lm9iaklkICE9PSBwYWdlT2JqSWQpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICByZXR1cm4gbmV3IFN0cnVjdEVsZW1lbnQoewogICAgICAgIHR5cGU6IFN0cnVjdEVsZW1lbnRUeXBlLlBBR0VfQ09OVEVOVCwKICAgICAgICBtY2lkOiBraWQsCiAgICAgICAgcGFnZU9iaklkCiAgICAgIH0pOwogICAgfQogICAgaWYgKCEoa2lkIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCBwYWdlUmVmID0ga2lkLmdldFJhdygiUGciKTsKICAgIGlmIChwYWdlUmVmIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgIHBhZ2VPYmpJZCA9IHBhZ2VSZWYudG9TdHJpbmcoKTsKICAgIH0KICAgIGNvbnN0IHR5cGUgPSBraWQuZ2V0KCJUeXBlIikgaW5zdGFuY2VvZiBOYW1lID8ga2lkLmdldCgiVHlwZSIpLm5hbWUgOiBudWxsOwogICAgaWYgKHR5cGUgPT09ICJNQ1IiKSB7CiAgICAgIGlmICh0aGlzLnRyZWUucGFnZURpY3Qub2JqSWQgIT09IHBhZ2VPYmpJZCkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IGtpZFJlZiA9IGtpZC5nZXRSYXcoIlN0bSIpOwogICAgICByZXR1cm4gbmV3IFN0cnVjdEVsZW1lbnQoewogICAgICAgIHR5cGU6IFN0cnVjdEVsZW1lbnRUeXBlLlNUUkVBTV9DT05URU5ULAogICAgICAgIHJlZk9iaklkOiBraWRSZWYgaW5zdGFuY2VvZiBSZWYgPyBraWRSZWYudG9TdHJpbmcoKSA6IG51bGwsCiAgICAgICAgcGFnZU9iaklkLAogICAgICAgIG1jaWQ6IGtpZC5nZXQoIk1DSUQiKQogICAgICB9KTsKICAgIH0KICAgIGlmICh0eXBlID09PSAiT0JKUiIpIHsKICAgICAgaWYgKHRoaXMudHJlZS5wYWdlRGljdC5vYmpJZCAhPT0gcGFnZU9iaklkKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgY29uc3Qga2lkUmVmID0ga2lkLmdldFJhdygiT2JqIik7CiAgICAgIHJldHVybiBuZXcgU3RydWN0RWxlbWVudCh7CiAgICAgICAgdHlwZTogU3RydWN0RWxlbWVudFR5cGUuT0JKRUNULAogICAgICAgIHJlZk9iaklkOiBraWRSZWYgaW5zdGFuY2VvZiBSZWYgPyBraWRSZWYudG9TdHJpbmcoKSA6IG51bGwsCiAgICAgICAgcGFnZU9iaklkCiAgICAgIH0pOwogICAgfQogICAgcmV0dXJuIG5ldyBTdHJ1Y3RFbGVtZW50KHsKICAgICAgdHlwZTogU3RydWN0RWxlbWVudFR5cGUuRUxFTUVOVCwKICAgICAgZGljdDoga2lkCiAgICB9KTsKICB9Cn0KY2xhc3MgU3RydWN0RWxlbWVudCB7CiAgY29uc3RydWN0b3IoewogICAgdHlwZSwKICAgIGRpY3QgPSBudWxsLAogICAgbWNpZCA9IG51bGwsCiAgICBwYWdlT2JqSWQgPSBudWxsLAogICAgcmVmT2JqSWQgPSBudWxsCiAgfSkgewogICAgdGhpcy50eXBlID0gdHlwZTsKICAgIHRoaXMuZGljdCA9IGRpY3Q7CiAgICB0aGlzLm1jaWQgPSBtY2lkOwogICAgdGhpcy5wYWdlT2JqSWQgPSBwYWdlT2JqSWQ7CiAgICB0aGlzLnJlZk9iaklkID0gcmVmT2JqSWQ7CiAgICB0aGlzLnBhcmVudE5vZGUgPSBudWxsOwogIH0KfQpjbGFzcyBTdHJ1Y3RUcmVlUGFnZSB7CiAgY29uc3RydWN0b3Ioc3RydWN0VHJlZVJvb3QsIHBhZ2VEaWN0KSB7CiAgICB0aGlzLnJvb3QgPSBzdHJ1Y3RUcmVlUm9vdDsKICAgIHRoaXMueHJlZiA9IHN0cnVjdFRyZWVSb290Py54cmVmID8/IG51bGw7CiAgICB0aGlzLnJvb3REaWN0ID0gc3RydWN0VHJlZVJvb3Q/LmRpY3QgPz8gbnVsbDsKICAgIHRoaXMucGFnZURpY3QgPSBwYWdlRGljdDsKICAgIHRoaXMubm9kZXMgPSBbXTsKICB9CiAgY29sbGVjdE9iamVjdHMocGFnZVJlZikgewogICAgaWYgKCF0aGlzLnJvb3QgfHwgIXRoaXMucm9vdERpY3QgfHwgIShwYWdlUmVmIGluc3RhbmNlb2YgUmVmKSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHBhcmVudFRyZWUgPSB0aGlzLnJvb3REaWN0LmdldCgiUGFyZW50VHJlZSIpOwogICAgaWYgKCFwYXJlbnRUcmVlKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgaWRzID0gdGhpcy5yb290LnN0cnVjdFBhcmVudElkcz8uZ2V0KHBhZ2VSZWYpOwogICAgaWYgKCFpZHMpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCBtYXAgPSBuZXcgTWFwKCk7CiAgICBjb25zdCBudW1iZXJUcmVlID0gbmV3IE51bWJlclRyZWUocGFyZW50VHJlZSwgdGhpcy54cmVmKTsKICAgIGZvciAoY29uc3QgW2VsZW1JZF0gb2YgaWRzKSB7CiAgICAgIGNvbnN0IG9iaiA9IG51bWJlclRyZWUuZ2V0UmF3KGVsZW1JZCk7CiAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICBtYXAuc2V0KGVsZW1JZCwgb2JqKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIG1hcDsKICB9CiAgcGFyc2UocGFnZVJlZikgewogICAgaWYgKCF0aGlzLnJvb3QgfHwgIXRoaXMucm9vdERpY3QgfHwgIShwYWdlUmVmIGluc3RhbmNlb2YgUmVmKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBwYXJlbnRUcmVlID0gdGhpcy5yb290RGljdC5nZXQoIlBhcmVudFRyZWUiKTsKICAgIGlmICghcGFyZW50VHJlZSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBpZCA9IHRoaXMucGFnZURpY3QuZ2V0KCJTdHJ1Y3RQYXJlbnRzIik7CiAgICBjb25zdCBpZHMgPSB0aGlzLnJvb3Quc3RydWN0UGFyZW50SWRzPy5nZXQocGFnZVJlZik7CiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoaWQpICYmICFpZHMpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgbWFwID0gbmV3IE1hcCgpOwogICAgY29uc3QgbnVtYmVyVHJlZSA9IG5ldyBOdW1iZXJUcmVlKHBhcmVudFRyZWUsIHRoaXMueHJlZik7CiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihpZCkpIHsKICAgICAgY29uc3QgcGFyZW50QXJyYXkgPSBudW1iZXJUcmVlLmdldChpZCk7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KHBhcmVudEFycmF5KSkgewogICAgICAgIGZvciAoY29uc3QgcmVmIG9mIHBhcmVudEFycmF5KSB7CiAgICAgICAgICBpZiAocmVmIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgICAgIHRoaXMuYWRkTm9kZSh0aGlzLnhyZWYuZmV0Y2gocmVmKSwgbWFwKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmICghaWRzKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGZvciAoY29uc3QgW2VsZW1JZCwgdHlwZV0gb2YgaWRzKSB7CiAgICAgIGNvbnN0IG9iaiA9IG51bWJlclRyZWUuZ2V0KGVsZW1JZCk7CiAgICAgIGlmIChvYmopIHsKICAgICAgICBjb25zdCBlbGVtID0gdGhpcy5hZGROb2RlKHRoaXMueHJlZi5mZXRjaElmUmVmKG9iaiksIG1hcCk7CiAgICAgICAgaWYgKGVsZW0/LmtpZHM/Lmxlbmd0aCA9PT0gMSAmJiBlbGVtLmtpZHNbMF0udHlwZSA9PT0gU3RydWN0RWxlbWVudFR5cGUuT0JKRUNUKSB7CiAgICAgICAgICBlbGVtLmtpZHNbMF0udHlwZSA9IHR5cGU7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQogIGFkZE5vZGUoZGljdCwgbWFwLCBsZXZlbCA9IDApIHsKICAgIGlmIChsZXZlbCA+IE1BWF9ERVBUSCkgewogICAgICB3YXJuKCJTdHJ1Y3RUcmVlIE1BWF9ERVBUSCByZWFjaGVkLiIpOwogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGlmICghKGRpY3QgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGlmIChtYXAuaGFzKGRpY3QpKSB7CiAgICAgIHJldHVybiBtYXAuZ2V0KGRpY3QpOwogICAgfQogICAgY29uc3QgZWxlbWVudCA9IG5ldyBTdHJ1Y3RFbGVtZW50Tm9kZSh0aGlzLCBkaWN0KTsKICAgIG1hcC5zZXQoZGljdCwgZWxlbWVudCk7CiAgICBjb25zdCBwYXJlbnQgPSBkaWN0LmdldCgiUCIpOwogICAgaWYgKCEocGFyZW50IGluc3RhbmNlb2YgRGljdCkgfHwgaXNOYW1lKHBhcmVudC5nZXQoIlR5cGUiKSwgIlN0cnVjdFRyZWVSb290IikpIHsKICAgICAgaWYgKCF0aGlzLmFkZFRvcExldmVsTm9kZShkaWN0LCBlbGVtZW50KSkgewogICAgICAgIG1hcC5kZWxldGUoZGljdCk7CiAgICAgIH0KICAgICAgcmV0dXJuIGVsZW1lbnQ7CiAgICB9CiAgICBjb25zdCBwYXJlbnROb2RlID0gdGhpcy5hZGROb2RlKHBhcmVudCwgbWFwLCBsZXZlbCArIDEpOwogICAgaWYgKCFwYXJlbnROb2RlKSB7CiAgICAgIHJldHVybiBlbGVtZW50OwogICAgfQogICAgbGV0IHNhdmUgPSBmYWxzZTsKICAgIGZvciAoY29uc3Qga2lkIG9mIHBhcmVudE5vZGUua2lkcykgewogICAgICBpZiAoa2lkLnR5cGUgPT09IFN0cnVjdEVsZW1lbnRUeXBlLkVMRU1FTlQgJiYga2lkLmRpY3QgPT09IGRpY3QpIHsKICAgICAgICBraWQucGFyZW50Tm9kZSA9IGVsZW1lbnQ7CiAgICAgICAgc2F2ZSA9IHRydWU7CiAgICAgIH0KICAgIH0KICAgIGlmICghc2F2ZSkgewogICAgICBtYXAuZGVsZXRlKGRpY3QpOwogICAgfQogICAgcmV0dXJuIGVsZW1lbnQ7CiAgfQogIGFkZFRvcExldmVsTm9kZShkaWN0LCBlbGVtZW50KSB7CiAgICBjb25zdCBvYmogPSB0aGlzLnJvb3REaWN0LmdldCgiSyIpOwogICAgaWYgKCFvYmopIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKG9iaiBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgaWYgKG9iai5vYmpJZCAhPT0gZGljdC5vYmpJZCkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICB0aGlzLm5vZGVzWzBdID0gZWxlbWVudDsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBpZiAoIUFycmF5LmlzQXJyYXkob2JqKSkgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGxldCBzYXZlID0gZmFsc2U7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG9iai5sZW5ndGg7IGkrKykgewogICAgICBjb25zdCBraWRSZWYgPSBvYmpbaV07CiAgICAgIGlmIChraWRSZWY/LnRvU3RyaW5nKCkgPT09IGRpY3Qub2JqSWQpIHsKICAgICAgICB0aGlzLm5vZGVzW2ldID0gZWxlbWVudDsKICAgICAgICBzYXZlID0gdHJ1ZTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHNhdmU7CiAgfQogIGdldCBzZXJpYWxpemFibGUoKSB7CiAgICBmdW5jdGlvbiBub2RlVG9TZXJpYWxpemFibGUobm9kZSwgcGFyZW50LCBsZXZlbCA9IDApIHsKICAgICAgaWYgKGxldmVsID4gTUFYX0RFUFRIKSB7CiAgICAgICAgd2FybigiU3RydWN0VHJlZSB0b28gZGVlcCB0byBiZSBmdWxseSBzZXJpYWxpemVkLiIpOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBjb25zdCBvYmogPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBvYmoucm9sZSA9IG5vZGUucm9sZTsKICAgICAgb2JqLmNoaWxkcmVuID0gW107CiAgICAgIHBhcmVudC5jaGlsZHJlbi5wdXNoKG9iaik7CiAgICAgIGxldCBhbHQgPSBub2RlLmRpY3QuZ2V0KCJBbHQiKTsKICAgICAgaWYgKHR5cGVvZiBhbHQgIT09ICJzdHJpbmciKSB7CiAgICAgICAgYWx0ID0gbm9kZS5kaWN0LmdldCgiQWN0dWFsVGV4dCIpOwogICAgICB9CiAgICAgIGlmICh0eXBlb2YgYWx0ID09PSAic3RyaW5nIikgewogICAgICAgIG9iai5hbHQgPSBzdHJpbmdUb1BERlN0cmluZyhhbHQpOwogICAgICB9CiAgICAgIGNvbnN0IGEgPSBub2RlLmRpY3QuZ2V0KCJBIik7CiAgICAgIGlmIChhIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgIGNvbnN0IGJib3ggPSBsb29rdXBOb3JtYWxSZWN0KGEuZ2V0QXJyYXkoIkJCb3giKSwgbnVsbCk7CiAgICAgICAgaWYgKGJib3gpIHsKICAgICAgICAgIG9iai5iYm94ID0gYmJveDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3Qgd2lkdGggPSBhLmdldCgiV2lkdGgiKTsKICAgICAgICAgIGNvbnN0IGhlaWdodCA9IGEuZ2V0KCJIZWlnaHQiKTsKICAgICAgICAgIGlmICh0eXBlb2Ygd2lkdGggPT09ICJudW1iZXIiICYmIHdpZHRoID4gMCAmJiB0eXBlb2YgaGVpZ2h0ID09PSAibnVtYmVyIiAmJiBoZWlnaHQgPiAwKSB7CiAgICAgICAgICAgIG9iai5iYm94ID0gWzAsIDAsIHdpZHRoLCBoZWlnaHRdOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCBsYW5nID0gbm9kZS5kaWN0LmdldCgiTGFuZyIpOwogICAgICBpZiAodHlwZW9mIGxhbmcgPT09ICJzdHJpbmciKSB7CiAgICAgICAgb2JqLmxhbmcgPSBzdHJpbmdUb1BERlN0cmluZyhsYW5nKTsKICAgICAgfQogICAgICBmb3IgKGNvbnN0IGtpZCBvZiBub2RlLmtpZHMpIHsKICAgICAgICBjb25zdCBraWRFbGVtZW50ID0ga2lkLnR5cGUgPT09IFN0cnVjdEVsZW1lbnRUeXBlLkVMRU1FTlQgPyBraWQucGFyZW50Tm9kZSA6IG51bGw7CiAgICAgICAgaWYgKGtpZEVsZW1lbnQpIHsKICAgICAgICAgIG5vZGVUb1NlcmlhbGl6YWJsZShraWRFbGVtZW50LCBvYmosIGxldmVsICsgMSk7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9IGVsc2UgaWYgKGtpZC50eXBlID09PSBTdHJ1Y3RFbGVtZW50VHlwZS5QQUdFX0NPTlRFTlQgfHwga2lkLnR5cGUgPT09IFN0cnVjdEVsZW1lbnRUeXBlLlNUUkVBTV9DT05URU5UKSB7CiAgICAgICAgICBvYmouY2hpbGRyZW4ucHVzaCh7CiAgICAgICAgICAgIHR5cGU6ICJjb250ZW50IiwKICAgICAgICAgICAgaWQ6IGBwJHtraWQucGFnZU9iaklkfV9tYyR7a2lkLm1jaWR9YAogICAgICAgICAgfSk7CiAgICAgICAgfSBlbHNlIGlmIChraWQudHlwZSA9PT0gU3RydWN0RWxlbWVudFR5cGUuT0JKRUNUKSB7CiAgICAgICAgICBvYmouY2hpbGRyZW4ucHVzaCh7CiAgICAgICAgICAgIHR5cGU6ICJvYmplY3QiLAogICAgICAgICAgICBpZDoga2lkLnJlZk9iaklkCiAgICAgICAgICB9KTsKICAgICAgICB9IGVsc2UgaWYgKGtpZC50eXBlID09PSBTdHJ1Y3RFbGVtZW50VHlwZS5BTk5PVEFUSU9OKSB7CiAgICAgICAgICBvYmouY2hpbGRyZW4ucHVzaCh7CiAgICAgICAgICAgIHR5cGU6ICJhbm5vdGF0aW9uIiwKICAgICAgICAgICAgaWQ6IGAke0Fubm90YXRpb25QcmVmaXh9JHtraWQucmVmT2JqSWR9YAogICAgICAgICAgfSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBjb25zdCByb290ID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHJvb3QuY2hpbGRyZW4gPSBbXTsKICAgIHJvb3Qucm9sZSA9ICJSb290IjsKICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpcy5ub2RlcykgewogICAgICBpZiAoIWNoaWxkKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgbm9kZVRvU2VyaWFsaXphYmxlKGNoaWxkLCByb290KTsKICAgIH0KICAgIHJldHVybiByb290OwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvY2F0YWxvZy5qcwoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCmNvbnN0IGlzUmVmID0gdiA9PiB2IGluc3RhbmNlb2YgUmVmOwpjb25zdCBpc1ZhbGlkRXhwbGljaXREZXN0ID0gX2lzVmFsaWRFeHBsaWNpdERlc3QuYmluZChudWxsLCBpc1JlZiwgaXNOYW1lKTsKZnVuY3Rpb24gZmV0Y2hEZXN0KGRlc3QpIHsKICBpZiAoZGVzdCBpbnN0YW5jZW9mIERpY3QpIHsKICAgIGRlc3QgPSBkZXN0LmdldCgiRCIpOwogIH0KICByZXR1cm4gaXNWYWxpZEV4cGxpY2l0RGVzdChkZXN0KSA/IGRlc3QgOiBudWxsOwp9CmZ1bmN0aW9uIGZldGNoUmVtb3RlRGVzdChhY3Rpb24pIHsKICBsZXQgZGVzdCA9IGFjdGlvbi5nZXQoIkQiKTsKICBpZiAoZGVzdCkgewogICAgaWYgKGRlc3QgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgIGRlc3QgPSBkZXN0Lm5hbWU7CiAgICB9CiAgICBpZiAodHlwZW9mIGRlc3QgPT09ICJzdHJpbmciKSB7CiAgICAgIHJldHVybiBzdHJpbmdUb1BERlN0cmluZyhkZXN0LCB0cnVlKTsKICAgIH0gZWxzZSBpZiAoaXNWYWxpZEV4cGxpY2l0RGVzdChkZXN0KSkgewogICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoZGVzdCk7CiAgICB9CiAgfQogIHJldHVybiBudWxsOwp9CmNsYXNzIENhdGFsb2cgewogICNhY3R1YWxOdW1QYWdlcyA9IG51bGw7CiAgI2NhdERpY3QgPSBudWxsOwogIGJ1aWx0SW5DTWFwQ2FjaGUgPSBuZXcgTWFwKCk7CiAgZm9udENhY2hlID0gbmV3IFJlZlNldENhY2hlKCk7CiAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlID0gbmV3IEdsb2JhbENvbG9yU3BhY2VDYWNoZSgpOwogIGdsb2JhbEltYWdlQ2FjaGUgPSBuZXcgR2xvYmFsSW1hZ2VDYWNoZSgpOwogIG5vbkJsZW5kTW9kZXNTZXQgPSBuZXcgUmVmU2V0KCk7CiAgcGFnZURpY3RDYWNoZSA9IG5ldyBSZWZTZXRDYWNoZSgpOwogIHBhZ2VJbmRleENhY2hlID0gbmV3IFJlZlNldENhY2hlKCk7CiAgcGFnZUtpZHNDb3VudENhY2hlID0gbmV3IFJlZlNldENhY2hlKCk7CiAgc3RhbmRhcmRGb250RGF0YUNhY2hlID0gbmV3IE1hcCgpOwogIHN5c3RlbUZvbnRDYWNoZSA9IG5ldyBNYXAoKTsKICBjb25zdHJ1Y3RvcihwZGZNYW5hZ2VyLCB4cmVmKSB7CiAgICB0aGlzLnBkZk1hbmFnZXIgPSBwZGZNYW5hZ2VyOwogICAgdGhpcy54cmVmID0geHJlZjsKICAgIHRoaXMuI2NhdERpY3QgPSB4cmVmLmdldENhdGFsb2dPYmooKTsKICAgIGlmICghKHRoaXMuI2NhdERpY3QgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkNhdGFsb2cgb2JqZWN0IGlzIG5vdCBhIGRpY3Rpb25hcnkuIik7CiAgICB9CiAgICB0aGlzLnRvcGxldmVsUGFnZXNEaWN0OwogIH0KICBjbG9uZURpY3QoKSB7CiAgICByZXR1cm4gdGhpcy4jY2F0RGljdC5jbG9uZSgpOwogIH0KICBnZXQgdmVyc2lvbigpIHsKICAgIGNvbnN0IHZlcnNpb24gPSB0aGlzLiNjYXREaWN0LmdldCgiVmVyc2lvbiIpOwogICAgaWYgKHZlcnNpb24gaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgIGlmIChQREZfVkVSU0lPTl9SRUdFWFAudGVzdCh2ZXJzaW9uLm5hbWUpKSB7CiAgICAgICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAidmVyc2lvbiIsIHZlcnNpb24ubmFtZSk7CiAgICAgIH0KICAgICAgd2FybihgSW52YWxpZCBQREYgY2F0YWxvZyB2ZXJzaW9uOiAke3ZlcnNpb24ubmFtZX1gKTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgInZlcnNpb24iLCBudWxsKTsKICB9CiAgZ2V0IGxhbmcoKSB7CiAgICBjb25zdCBsYW5nID0gdGhpcy4jY2F0RGljdC5nZXQoIkxhbmciKTsKICAgIHJldHVybiBzaGFkb3codGhpcywgImxhbmciLCBsYW5nICYmIHR5cGVvZiBsYW5nID09PSAic3RyaW5nIiA/IHN0cmluZ1RvUERGU3RyaW5nKGxhbmcpIDogbnVsbCk7CiAgfQogIGdldCBuZWVkc1JlbmRlcmluZygpIHsKICAgIGNvbnN0IG5lZWRzUmVuZGVyaW5nID0gdGhpcy4jY2F0RGljdC5nZXQoIk5lZWRzUmVuZGVyaW5nIik7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJuZWVkc1JlbmRlcmluZyIsIHR5cGVvZiBuZWVkc1JlbmRlcmluZyA9PT0gImJvb2xlYW4iID8gbmVlZHNSZW5kZXJpbmcgOiBmYWxzZSk7CiAgfQogIGdldCBjb2xsZWN0aW9uKCkgewogICAgbGV0IGNvbGxlY3Rpb24gPSBudWxsOwogICAgdHJ5IHsKICAgICAgY29uc3Qgb2JqID0gdGhpcy4jY2F0RGljdC5nZXQoIkNvbGxlY3Rpb24iKTsKICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIERpY3QgJiYgb2JqLnNpemUgPiAwKSB7CiAgICAgICAgY29sbGVjdGlvbiA9IG9iajsKICAgICAgfQogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICBpbmZvKCJDYW5ub3QgZmV0Y2ggQ29sbGVjdGlvbiBlbnRyeTsgYXNzdW1pbmcgbm8gY29sbGVjdGlvbiBpcyBwcmVzZW50LiIpOwogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiY29sbGVjdGlvbiIsIGNvbGxlY3Rpb24pOwogIH0KICBnZXQgYWNyb0Zvcm0oKSB7CiAgICBsZXQgYWNyb0Zvcm0gPSBudWxsOwogICAgdHJ5IHsKICAgICAgY29uc3Qgb2JqID0gdGhpcy4jY2F0RGljdC5nZXQoIkFjcm9Gb3JtIik7CiAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBEaWN0ICYmIG9iai5zaXplID4gMCkgewogICAgICAgIGFjcm9Gb3JtID0gb2JqOwogICAgICB9CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoZXggaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIGluZm8oIkNhbm5vdCBmZXRjaCBBY3JvRm9ybSBlbnRyeTsgYXNzdW1pbmcgbm8gZm9ybXMgYXJlIHByZXNlbnQuIik7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJhY3JvRm9ybSIsIGFjcm9Gb3JtKTsKICB9CiAgZ2V0IGFjcm9Gb3JtUmVmKCkgewogICAgY29uc3QgdmFsdWUgPSB0aGlzLiNjYXREaWN0LmdldFJhdygiQWNyb0Zvcm0iKTsKICAgIHJldHVybiBzaGFkb3codGhpcywgImFjcm9Gb3JtUmVmIiwgdmFsdWUgaW5zdGFuY2VvZiBSZWYgPyB2YWx1ZSA6IG51bGwpOwogIH0KICBnZXQgbWV0YWRhdGEoKSB7CiAgICBjb25zdCBzdHJlYW1SZWYgPSB0aGlzLiNjYXREaWN0LmdldFJhdygiTWV0YWRhdGEiKTsKICAgIGlmICghKHN0cmVhbVJlZiBpbnN0YW5jZW9mIFJlZikpIHsKICAgICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAibWV0YWRhdGEiLCBudWxsKTsKICAgIH0KICAgIGxldCBtZXRhZGF0YSA9IG51bGw7CiAgICB0cnkgewogICAgICBjb25zdCBzdHJlYW0gPSB0aGlzLnhyZWYuZmV0Y2goc3RyZWFtUmVmLCAhdGhpcy54cmVmLmVuY3J5cHQ/LmVuY3J5cHRNZXRhZGF0YSk7CiAgICAgIGlmIChzdHJlYW0gaW5zdGFuY2VvZiBCYXNlU3RyZWFtICYmIHN0cmVhbS5kaWN0IGluc3RhbmNlb2YgRGljdCkgewogICAgICAgIGNvbnN0IHR5cGUgPSBzdHJlYW0uZGljdC5nZXQoIlR5cGUiKTsKICAgICAgICBjb25zdCBzdWJ0eXBlID0gc3RyZWFtLmRpY3QuZ2V0KCJTdWJ0eXBlIik7CiAgICAgICAgaWYgKGlzTmFtZSh0eXBlLCAiTWV0YWRhdGEiKSAmJiBpc05hbWUoc3VidHlwZSwgIlhNTCIpKSB7CiAgICAgICAgICBjb25zdCBkYXRhID0gc3RyaW5nVG9VVEY4U3RyaW5nKHN0cmVhbS5nZXRTdHJpbmcoKSk7CiAgICAgICAgICBpZiAoZGF0YSkgewogICAgICAgICAgICBtZXRhZGF0YSA9IG5ldyBNZXRhZGF0YVBhcnNlcihkYXRhKS5zZXJpYWxpemFibGU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoZXggaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIGluZm8oYFNraXBwaW5nIGludmFsaWQgTWV0YWRhdGE6ICIke2V4fSIuYCk7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJtZXRhZGF0YSIsIG1ldGFkYXRhKTsKICB9CiAgZ2V0IG1hcmtJbmZvKCkgewogICAgbGV0IG1hcmtJbmZvID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIG1hcmtJbmZvID0gdGhpcy4jcmVhZE1hcmtJbmZvKCk7CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoZXggaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIHdhcm4oIlVuYWJsZSB0byByZWFkIG1hcmsgaW5mby4iKTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgIm1hcmtJbmZvIiwgbWFya0luZm8pOwogIH0KICAjcmVhZE1hcmtJbmZvKCkgewogICAgY29uc3Qgb2JqID0gdGhpcy4jY2F0RGljdC5nZXQoIk1hcmtJbmZvIik7CiAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IG1hcmtJbmZvID0gewogICAgICBNYXJrZWQ6IGZhbHNlLAogICAgICBVc2VyUHJvcGVydGllczogZmFsc2UsCiAgICAgIFN1c3BlY3RzOiBmYWxzZQogICAgfTsKICAgIGZvciAoY29uc3Qga2V5IGluIG1hcmtJbmZvKSB7CiAgICAgIGNvbnN0IHZhbHVlID0gb2JqLmdldChrZXkpOwogICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAiYm9vbGVhbiIpIHsKICAgICAgICBtYXJrSW5mb1trZXldID0gdmFsdWU7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBtYXJrSW5mbzsKICB9CiAgZ2V0IHN0cnVjdFRyZWVSb290KCkgewogICAgbGV0IHN0cnVjdFRyZWUgPSBudWxsOwogICAgdHJ5IHsKICAgICAgc3RydWN0VHJlZSA9IHRoaXMuI3JlYWRTdHJ1Y3RUcmVlUm9vdCgpOwogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICB3YXJuKCJVbmFibGUgcmVhZCB0byBzdHJ1Y3RUcmVlUm9vdCBpbmZvLiIpOwogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAic3RydWN0VHJlZVJvb3QiLCBzdHJ1Y3RUcmVlKTsKICB9CiAgI3JlYWRTdHJ1Y3RUcmVlUm9vdCgpIHsKICAgIGNvbnN0IHJhd09iaiA9IHRoaXMuI2NhdERpY3QuZ2V0UmF3KCJTdHJ1Y3RUcmVlUm9vdCIpOwogICAgY29uc3Qgb2JqID0gdGhpcy54cmVmLmZldGNoSWZSZWYocmF3T2JqKTsKICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3Qgcm9vdCA9IG5ldyBTdHJ1Y3RUcmVlUm9vdCh0aGlzLnhyZWYsIG9iaiwgcmF3T2JqKTsKICAgIHJvb3QuaW5pdCgpOwogICAgcmV0dXJuIHJvb3Q7CiAgfQogIGdldCB0b3BsZXZlbFBhZ2VzRGljdCgpIHsKICAgIGNvbnN0IHBhZ2VzT2JqID0gdGhpcy4jY2F0RGljdC5nZXQoIlBhZ2VzIik7CiAgICBpZiAoIShwYWdlc09iaiBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCB0b3AtbGV2ZWwgcGFnZXMgZGljdGlvbmFyeS4iKTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgInRvcGxldmVsUGFnZXNEaWN0IiwgcGFnZXNPYmopOwogIH0KICBnZXQgZG9jdW1lbnRPdXRsaW5lKCkgewogICAgbGV0IG9iaiA9IG51bGw7CiAgICB0cnkgewogICAgICBvYmogPSB0aGlzLiNyZWFkRG9jdW1lbnRPdXRsaW5lKCk7CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoZXggaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIHdhcm4oIlVuYWJsZSB0byByZWFkIGRvY3VtZW50IG91dGxpbmUuIik7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJkb2N1bWVudE91dGxpbmUiLCBvYmopOwogIH0KICAjcmVhZERvY3VtZW50T3V0bGluZSgpIHsKICAgIGxldCBvYmogPSB0aGlzLiNjYXREaWN0LmdldCgiT3V0bGluZXMiKTsKICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgb2JqID0gb2JqLmdldFJhdygiRmlyc3QiKTsKICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIFJlZikpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCByb290ID0gewogICAgICBpdGVtczogW10KICAgIH07CiAgICBjb25zdCBxdWV1ZSA9IFt7CiAgICAgIG9iaiwKICAgICAgcGFyZW50OiByb290CiAgICB9XTsKICAgIGNvbnN0IHByb2Nlc3NlZCA9IG5ldyBSZWZTZXQoKTsKICAgIHByb2Nlc3NlZC5wdXQob2JqKTsKICAgIGNvbnN0IHhyZWYgPSB0aGlzLnhyZWYsCiAgICAgIGJsYWNrQ29sb3IgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoMyk7CiAgICB3aGlsZSAocXVldWUubGVuZ3RoID4gMCkgewogICAgICBjb25zdCBpID0gcXVldWUuc2hpZnQoKTsKICAgICAgY29uc3Qgb3V0bGluZURpY3QgPSB4cmVmLmZldGNoSWZSZWYoaS5vYmopOwogICAgICBpZiAob3V0bGluZURpY3QgPT09IG51bGwpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoIW91dGxpbmVEaWN0LmhhcygiVGl0bGUiKSkgewogICAgICAgIHdhcm4oIkludmFsaWQgb3V0bGluZSBpdGVtIGVuY291bnRlcmVkLiIpOwogICAgICB9CiAgICAgIGNvbnN0IGRhdGEgPSB7CiAgICAgICAgdXJsOiBudWxsLAogICAgICAgIGRlc3Q6IG51bGwsCiAgICAgICAgYWN0aW9uOiBudWxsCiAgICAgIH07CiAgICAgIENhdGFsb2cucGFyc2VEZXN0RGljdGlvbmFyeSh7CiAgICAgICAgZGVzdERpY3Q6IG91dGxpbmVEaWN0LAogICAgICAgIHJlc3VsdE9iajogZGF0YSwKICAgICAgICBkb2NCYXNlVXJsOiB0aGlzLmJhc2VVcmwsCiAgICAgICAgZG9jQXR0YWNobWVudHM6IHRoaXMuYXR0YWNobWVudHMKICAgICAgfSk7CiAgICAgIGNvbnN0IHRpdGxlID0gb3V0bGluZURpY3QuZ2V0KCJUaXRsZSIpOwogICAgICBjb25zdCBmbGFncyA9IG91dGxpbmVEaWN0LmdldCgiRiIpIHx8IDA7CiAgICAgIGNvbnN0IGNvbG9yID0gb3V0bGluZURpY3QuZ2V0QXJyYXkoIkMiKTsKICAgICAgY29uc3QgY291bnQgPSBvdXRsaW5lRGljdC5nZXQoIkNvdW50Iik7CiAgICAgIGxldCByZ2JDb2xvciA9IGJsYWNrQ29sb3I7CiAgICAgIGlmIChpc051bWJlckFycmF5KGNvbG9yLCAzKSAmJiAoY29sb3JbMF0gIT09IDAgfHwgY29sb3JbMV0gIT09IDAgfHwgY29sb3JbMl0gIT09IDApKSB7CiAgICAgICAgcmdiQ29sb3IgPSBDb2xvclNwYWNlVXRpbHMucmdiLmdldFJnYihjb2xvciwgMCk7CiAgICAgIH0KICAgICAgY29uc3Qgb3V0bGluZUl0ZW0gPSB7CiAgICAgICAgYWN0aW9uOiBkYXRhLmFjdGlvbiwKICAgICAgICBhdHRhY2htZW50OiBkYXRhLmF0dGFjaG1lbnQsCiAgICAgICAgZGVzdDogZGF0YS5kZXN0LAogICAgICAgIHVybDogZGF0YS51cmwsCiAgICAgICAgdW5zYWZlVXJsOiBkYXRhLnVuc2FmZVVybCwKICAgICAgICBuZXdXaW5kb3c6IGRhdGEubmV3V2luZG93LAogICAgICAgIHNldE9DR1N0YXRlOiBkYXRhLnNldE9DR1N0YXRlLAogICAgICAgIHRpdGxlOiB0eXBlb2YgdGl0bGUgPT09ICJzdHJpbmciID8gc3RyaW5nVG9QREZTdHJpbmcodGl0bGUpIDogIiIsCiAgICAgICAgY29sb3I6IHJnYkNvbG9yLAogICAgICAgIGNvdW50OiBOdW1iZXIuaXNJbnRlZ2VyKGNvdW50KSA/IGNvdW50IDogdW5kZWZpbmVkLAogICAgICAgIGJvbGQ6ICEhKGZsYWdzICYgMiksCiAgICAgICAgaXRhbGljOiAhIShmbGFncyAmIDEpLAogICAgICAgIGl0ZW1zOiBbXQogICAgICB9OwogICAgICBpLnBhcmVudC5pdGVtcy5wdXNoKG91dGxpbmVJdGVtKTsKICAgICAgb2JqID0gb3V0bGluZURpY3QuZ2V0UmF3KCJGaXJzdCIpOwogICAgICBpZiAob2JqIGluc3RhbmNlb2YgUmVmICYmICFwcm9jZXNzZWQuaGFzKG9iaikpIHsKICAgICAgICBxdWV1ZS5wdXNoKHsKICAgICAgICAgIG9iaiwKICAgICAgICAgIHBhcmVudDogb3V0bGluZUl0ZW0KICAgICAgICB9KTsKICAgICAgICBwcm9jZXNzZWQucHV0KG9iaik7CiAgICAgIH0KICAgICAgb2JqID0gb3V0bGluZURpY3QuZ2V0UmF3KCJOZXh0Iik7CiAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBSZWYgJiYgIXByb2Nlc3NlZC5oYXMob2JqKSkgewogICAgICAgIHF1ZXVlLnB1c2goewogICAgICAgICAgb2JqLAogICAgICAgICAgcGFyZW50OiBpLnBhcmVudAogICAgICAgIH0pOwogICAgICAgIHByb2Nlc3NlZC5wdXQob2JqKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHJvb3QuaXRlbXMubGVuZ3RoID4gMCA/IHJvb3QuaXRlbXMgOiBudWxsOwogIH0KICBnZXQgcGVybWlzc2lvbnMoKSB7CiAgICBsZXQgcGVybWlzc2lvbnMgPSBudWxsOwogICAgdHJ5IHsKICAgICAgcGVybWlzc2lvbnMgPSB0aGlzLiNyZWFkUGVybWlzc2lvbnMoKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgd2FybigiVW5hYmxlIHRvIHJlYWQgcGVybWlzc2lvbnMuIik7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJwZXJtaXNzaW9ucyIsIHBlcm1pc3Npb25zKTsKICB9CiAgI3JlYWRQZXJtaXNzaW9ucygpIHsKICAgIGNvbnN0IGVuY3J5cHQgPSB0aGlzLnhyZWYudHJhaWxlci5nZXQoIkVuY3J5cHQiKTsKICAgIGlmICghKGVuY3J5cHQgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGxldCBmbGFncyA9IGVuY3J5cHQuZ2V0KCJQIik7CiAgICBpZiAodHlwZW9mIGZsYWdzICE9PSAibnVtYmVyIikgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGZsYWdzICs9IDIgKiogMzI7CiAgICBjb25zdCBwZXJtaXNzaW9ucyA9IFtdOwogICAgZm9yIChjb25zdCBrZXkgaW4gUGVybWlzc2lvbkZsYWcpIHsKICAgICAgY29uc3QgdmFsdWUgPSBQZXJtaXNzaW9uRmxhZ1trZXldOwogICAgICBpZiAoZmxhZ3MgJiB2YWx1ZSkgewogICAgICAgIHBlcm1pc3Npb25zLnB1c2godmFsdWUpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gcGVybWlzc2lvbnM7CiAgfQogIGdldCBvcHRpb25hbENvbnRlbnRDb25maWcoKSB7CiAgICBsZXQgY29uZmlnID0gbnVsbDsKICAgIHRyeSB7CiAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSB0aGlzLiNjYXREaWN0LmdldCgiT0NQcm9wZXJ0aWVzIik7CiAgICAgIGlmICghcHJvcGVydGllcykgewogICAgICAgIHJldHVybiBzaGFkb3codGhpcywgIm9wdGlvbmFsQ29udGVudENvbmZpZyIsIG51bGwpOwogICAgICB9CiAgICAgIGNvbnN0IGRlZmF1bHRDb25maWcgPSBwcm9wZXJ0aWVzLmdldCgiRCIpOwogICAgICBpZiAoIWRlZmF1bHRDb25maWcpIHsKICAgICAgICByZXR1cm4gc2hhZG93KHRoaXMsICJvcHRpb25hbENvbnRlbnRDb25maWciLCBudWxsKTsKICAgICAgfQogICAgICBjb25zdCBncm91cHNEYXRhID0gcHJvcGVydGllcy5nZXQoIk9DR3MiKTsKICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGdyb3Vwc0RhdGEpKSB7CiAgICAgICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAib3B0aW9uYWxDb250ZW50Q29uZmlnIiwgbnVsbCk7CiAgICAgIH0KICAgICAgY29uc3QgZ3JvdXBSZWZDYWNoZSA9IG5ldyBSZWZTZXRDYWNoZSgpOwogICAgICBmb3IgKGNvbnN0IGdyb3VwUmVmIG9mIGdyb3Vwc0RhdGEpIHsKICAgICAgICBpZiAoIShncm91cFJlZiBpbnN0YW5jZW9mIFJlZikgfHwgZ3JvdXBSZWZDYWNoZS5oYXMoZ3JvdXBSZWYpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgZ3JvdXBSZWZDYWNoZS5wdXQoZ3JvdXBSZWYsIHRoaXMuI3JlYWRPcHRpb25hbENvbnRlbnRHcm91cChncm91cFJlZikpOwogICAgICB9CiAgICAgIGNvbmZpZyA9IHRoaXMuI3JlYWRPcHRpb25hbENvbnRlbnRDb25maWcoZGVmYXVsdENvbmZpZywgZ3JvdXBSZWZDYWNoZSk7CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoZXggaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIHdhcm4oYFVuYWJsZSB0byByZWFkIG9wdGlvbmFsIGNvbnRlbnQgY29uZmlnOiAke2V4fWApOwogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAib3B0aW9uYWxDb250ZW50Q29uZmlnIiwgY29uZmlnKTsKICB9CiAgI3JlYWRPcHRpb25hbENvbnRlbnRHcm91cChncm91cFJlZikgewogICAgY29uc3QgZ3JvdXAgPSB0aGlzLnhyZWYuZmV0Y2goZ3JvdXBSZWYpOwogICAgY29uc3Qgb2JqID0gewogICAgICBpZDogZ3JvdXBSZWYudG9TdHJpbmcoKSwKICAgICAgbmFtZTogbnVsbCwKICAgICAgaW50ZW50OiBudWxsLAogICAgICB1c2FnZTogewogICAgICAgIHByaW50OiBudWxsLAogICAgICAgIHZpZXc6IG51bGwKICAgICAgfSwKICAgICAgcmJHcm91cHM6IFtdCiAgICB9OwogICAgY29uc3QgbmFtZSA9IGdyb3VwLmdldCgiTmFtZSIpOwogICAgaWYgKHR5cGVvZiBuYW1lID09PSAic3RyaW5nIikgewogICAgICBvYmoubmFtZSA9IHN0cmluZ1RvUERGU3RyaW5nKG5hbWUpOwogICAgfQogICAgbGV0IGludGVudCA9IGdyb3VwLmdldEFycmF5KCJJbnRlbnQiKTsKICAgIGlmICghQXJyYXkuaXNBcnJheShpbnRlbnQpKSB7CiAgICAgIGludGVudCA9IFtpbnRlbnRdOwogICAgfQogICAgaWYgKGludGVudC5ldmVyeShpID0+IGkgaW5zdGFuY2VvZiBOYW1lKSkgewogICAgICBvYmouaW50ZW50ID0gaW50ZW50Lm1hcChpID0+IGkubmFtZSk7CiAgICB9CiAgICBjb25zdCB1c2FnZSA9IGdyb3VwLmdldCgiVXNhZ2UiKTsKICAgIGlmICghKHVzYWdlIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuIG9iajsKICAgIH0KICAgIGNvbnN0IHVzYWdlT2JqID0gb2JqLnVzYWdlOwogICAgY29uc3QgcHJpbnQgPSB1c2FnZS5nZXQoIlByaW50Iik7CiAgICBpZiAocHJpbnQgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgIGNvbnN0IHByaW50U3RhdGUgPSBwcmludC5nZXQoIlByaW50U3RhdGUiKTsKICAgICAgaWYgKHByaW50U3RhdGUgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgc3dpdGNoIChwcmludFN0YXRlLm5hbWUpIHsKICAgICAgICAgIGNhc2UgIk9OIjoKICAgICAgICAgIGNhc2UgIk9GRiI6CiAgICAgICAgICAgIHVzYWdlT2JqLnByaW50ID0gewogICAgICAgICAgICAgIHByaW50U3RhdGU6IHByaW50U3RhdGUubmFtZQogICAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgY29uc3QgdmlldyA9IHVzYWdlLmdldCgiVmlldyIpOwogICAgaWYgKHZpZXcgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgIGNvbnN0IHZpZXdTdGF0ZSA9IHZpZXcuZ2V0KCJWaWV3U3RhdGUiKTsKICAgICAgaWYgKHZpZXdTdGF0ZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICBzd2l0Y2ggKHZpZXdTdGF0ZS5uYW1lKSB7CiAgICAgICAgICBjYXNlICJPTiI6CiAgICAgICAgICBjYXNlICJPRkYiOgogICAgICAgICAgICB1c2FnZU9iai52aWV3ID0gewogICAgICAgICAgICAgIHZpZXdTdGF0ZTogdmlld1N0YXRlLm5hbWUKICAgICAgICAgICAgfTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBvYmo7CiAgfQogICNyZWFkT3B0aW9uYWxDb250ZW50Q29uZmlnKGNvbmZpZywgZ3JvdXBSZWZDYWNoZSkgewogICAgZnVuY3Rpb24gcGFyc2VPbk9mZihyZWZzKSB7CiAgICAgIGNvbnN0IG9uUGFyc2VkID0gW107CiAgICAgIGlmIChBcnJheS5pc0FycmF5KHJlZnMpKSB7CiAgICAgICAgZm9yIChjb25zdCB2YWx1ZSBvZiByZWZzKSB7CiAgICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBSZWYgJiYgZ3JvdXBSZWZDYWNoZS5oYXModmFsdWUpKSB7CiAgICAgICAgICAgIG9uUGFyc2VkLnB1c2godmFsdWUudG9TdHJpbmcoKSk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybiBvblBhcnNlZDsKICAgIH0KICAgIGZ1bmN0aW9uIHBhcnNlT3JkZXIocmVmcywgbmVzdGVkTGV2ZWxzID0gMCkgewogICAgICBpZiAoIUFycmF5LmlzQXJyYXkocmVmcykpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBjb25zdCBvcmRlciA9IFtdOwogICAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIHJlZnMpIHsKICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBSZWYgJiYgZ3JvdXBSZWZDYWNoZS5oYXModmFsdWUpKSB7CiAgICAgICAgICBwYXJzZWRPcmRlclJlZnMucHV0KHZhbHVlKTsKICAgICAgICAgIG9yZGVyLnB1c2godmFsdWUudG9TdHJpbmcoKSk7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgY29uc3QgbmVzdGVkT3JkZXIgPSBwYXJzZU5lc3RlZE9yZGVyKHZhbHVlLCBuZXN0ZWRMZXZlbHMpOwogICAgICAgIGlmIChuZXN0ZWRPcmRlcikgewogICAgICAgICAgb3JkZXIucHVzaChuZXN0ZWRPcmRlcik7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChuZXN0ZWRMZXZlbHMgPiAwKSB7CiAgICAgICAgcmV0dXJuIG9yZGVyOwogICAgICB9CiAgICAgIGNvbnN0IGhpZGRlbkdyb3VwcyA9IFtdOwogICAgICBmb3IgKGNvbnN0IFtncm91cFJlZl0gb2YgZ3JvdXBSZWZDYWNoZS5pdGVtcygpKSB7CiAgICAgICAgaWYgKHBhcnNlZE9yZGVyUmVmcy5oYXMoZ3JvdXBSZWYpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaGlkZGVuR3JvdXBzLnB1c2goZ3JvdXBSZWYudG9TdHJpbmcoKSk7CiAgICAgIH0KICAgICAgaWYgKGhpZGRlbkdyb3Vwcy5sZW5ndGgpIHsKICAgICAgICBvcmRlci5wdXNoKHsKICAgICAgICAgIG5hbWU6IG51bGwsCiAgICAgICAgICBvcmRlcjogaGlkZGVuR3JvdXBzCiAgICAgICAgfSk7CiAgICAgIH0KICAgICAgcmV0dXJuIG9yZGVyOwogICAgfQogICAgZnVuY3Rpb24gcGFyc2VOZXN0ZWRPcmRlcihyZWYsIG5lc3RlZExldmVscykgewogICAgICBpZiAoKytuZXN0ZWRMZXZlbHMgPiBNQVhfTkVTVEVEX0xFVkVMUykgewogICAgICAgIHdhcm4oInBhcnNlTmVzdGVkT3JkZXIgLSByZWFjaGVkIE1BWF9ORVNURURfTEVWRUxTLiIpOwogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IHZhbHVlID0geHJlZi5mZXRjaElmUmVmKHJlZik7CiAgICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBjb25zdCBuZXN0ZWROYW1lID0geHJlZi5mZXRjaElmUmVmKHZhbHVlWzBdKTsKICAgICAgaWYgKHR5cGVvZiBuZXN0ZWROYW1lICE9PSAic3RyaW5nIikgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IG5lc3RlZE9yZGVyID0gcGFyc2VPcmRlcih2YWx1ZS5zbGljZSgxKSwgbmVzdGVkTGV2ZWxzKTsKICAgICAgaWYgKCFuZXN0ZWRPcmRlcj8ubGVuZ3RoKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgcmV0dXJuIHsKICAgICAgICBuYW1lOiBzdHJpbmdUb1BERlN0cmluZyhuZXN0ZWROYW1lKSwKICAgICAgICBvcmRlcjogbmVzdGVkT3JkZXIKICAgICAgfTsKICAgIH0KICAgIGZ1bmN0aW9uIHBhcnNlUkJHcm91cHMocmJHcm91cHMpIHsKICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHJiR3JvdXBzKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBmb3IgKGNvbnN0IHZhbHVlIG9mIHJiR3JvdXBzKSB7CiAgICAgICAgY29uc3QgcmJHcm91cCA9IHhyZWYuZmV0Y2hJZlJlZih2YWx1ZSk7CiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHJiR3JvdXApIHx8ICFyYkdyb3VwLmxlbmd0aCkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHBhcnNlZFJiR3JvdXAgPSBuZXcgU2V0KCk7CiAgICAgICAgZm9yIChjb25zdCByZWYgb2YgcmJHcm91cCkgewogICAgICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFJlZiAmJiBncm91cFJlZkNhY2hlLmhhcyhyZWYpICYmICFwYXJzZWRSYkdyb3VwLmhhcyhyZWYudG9TdHJpbmcoKSkpIHsKICAgICAgICAgICAgcGFyc2VkUmJHcm91cC5hZGQocmVmLnRvU3RyaW5nKCkpOwogICAgICAgICAgICBncm91cFJlZkNhY2hlLmdldChyZWYpLnJiR3JvdXBzLnB1c2gocGFyc2VkUmJHcm91cCk7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBjb25zdCB4cmVmID0gdGhpcy54cmVmLAogICAgICBwYXJzZWRPcmRlclJlZnMgPSBuZXcgUmVmU2V0KCksCiAgICAgIE1BWF9ORVNURURfTEVWRUxTID0gMTA7CiAgICBwYXJzZVJCR3JvdXBzKGNvbmZpZy5nZXQoIlJCR3JvdXBzIikpOwogICAgcmV0dXJuIHsKICAgICAgbmFtZTogdHlwZW9mIGNvbmZpZy5nZXQoIk5hbWUiKSA9PT0gInN0cmluZyIgPyBzdHJpbmdUb1BERlN0cmluZyhjb25maWcuZ2V0KCJOYW1lIikpIDogbnVsbCwKICAgICAgY3JlYXRvcjogdHlwZW9mIGNvbmZpZy5nZXQoIkNyZWF0b3IiKSA9PT0gInN0cmluZyIgPyBzdHJpbmdUb1BERlN0cmluZyhjb25maWcuZ2V0KCJDcmVhdG9yIikpIDogbnVsbCwKICAgICAgYmFzZVN0YXRlOiBjb25maWcuZ2V0KCJCYXNlU3RhdGUiKSBpbnN0YW5jZW9mIE5hbWUgPyBjb25maWcuZ2V0KCJCYXNlU3RhdGUiKS5uYW1lIDogbnVsbCwKICAgICAgb246IHBhcnNlT25PZmYoY29uZmlnLmdldCgiT04iKSksCiAgICAgIG9mZjogcGFyc2VPbk9mZihjb25maWcuZ2V0KCJPRkYiKSksCiAgICAgIG9yZGVyOiBwYXJzZU9yZGVyKGNvbmZpZy5nZXQoIk9yZGVyIikpLAogICAgICBncm91cHM6IFsuLi5ncm91cFJlZkNhY2hlXQogICAgfTsKICB9CiAgc2V0QWN0dWFsTnVtUGFnZXMobnVtID0gbnVsbCkgewogICAgdGhpcy4jYWN0dWFsTnVtUGFnZXMgPSBudW07CiAgfQogIGdldCBoYXNBY3R1YWxOdW1QYWdlcygpIHsKICAgIHJldHVybiB0aGlzLiNhY3R1YWxOdW1QYWdlcyAhPT0gbnVsbDsKICB9CiAgZ2V0IF9wYWdlc0NvdW50KCkgewogICAgY29uc3Qgb2JqID0gdGhpcy50b3BsZXZlbFBhZ2VzRGljdC5nZXQoIkNvdW50Iik7CiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIob2JqKSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlBhZ2UgY291bnQgaW4gdG9wLWxldmVsIHBhZ2VzIGRpY3Rpb25hcnkgaXMgbm90IGFuIGludGVnZXIuIik7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJfcGFnZXNDb3VudCIsIG9iaik7CiAgfQogIGdldCBudW1QYWdlcygpIHsKICAgIHJldHVybiB0aGlzLiNhY3R1YWxOdW1QYWdlcyA/PyB0aGlzLl9wYWdlc0NvdW50OwogIH0KICBnZXQgZGVzdGluYXRpb25zKCkgewogICAgY29uc3QgcmF3RGVzdHMgPSB0aGlzLiNyZWFkRGVzdHMoKSwKICAgICAgZGVzdHMgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgZm9yIChjb25zdCBvYmogb2YgcmF3RGVzdHMpIHsKICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIE5hbWVUcmVlKSB7CiAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2Ygb2JqLmdldEFsbCgpKSB7CiAgICAgICAgICBjb25zdCBkZXN0ID0gZmV0Y2hEZXN0KHZhbHVlKTsKICAgICAgICAgIGlmIChkZXN0KSB7CiAgICAgICAgICAgIGRlc3RzW3N0cmluZ1RvUERGU3RyaW5nKGtleSwgdHJ1ZSldID0gZGVzdDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAob2JqIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIG9iaikgewogICAgICAgICAgY29uc3QgZGVzdCA9IGZldGNoRGVzdCh2YWx1ZSk7CiAgICAgICAgICBpZiAoZGVzdCkgewogICAgICAgICAgICBkZXN0c1tzdHJpbmdUb1BERlN0cmluZyhrZXksIHRydWUpXSB8fD0gZGVzdDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgImRlc3RpbmF0aW9ucyIsIGRlc3RzKTsKICB9CiAgZ2V0RGVzdGluYXRpb24oaWQpIHsKICAgIGlmICh0aGlzLmhhc093blByb3BlcnR5KCJkZXN0aW5hdGlvbnMiKSkgewogICAgICByZXR1cm4gdGhpcy5kZXN0aW5hdGlvbnNbaWRdID8/IG51bGw7CiAgICB9CiAgICBjb25zdCByYXdEZXN0cyA9IHRoaXMuI3JlYWREZXN0cygpOwogICAgZm9yIChjb25zdCBvYmogb2YgcmF3RGVzdHMpIHsKICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIE5hbWVUcmVlIHx8IG9iaiBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICBjb25zdCBkZXN0ID0gZmV0Y2hEZXN0KG9iai5nZXQoaWQpKTsKICAgICAgICBpZiAoZGVzdCkgewogICAgICAgICAgcmV0dXJuIGRlc3Q7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAocmF3RGVzdHMubGVuZ3RoKSB7CiAgICAgIGNvbnN0IGRlc3QgPSB0aGlzLmRlc3RpbmF0aW9uc1tpZF07CiAgICAgIGlmIChkZXN0KSB7CiAgICAgICAgcmV0dXJuIGRlc3Q7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KICAjcmVhZERlc3RzKCkgewogICAgY29uc3Qgb2JqID0gdGhpcy4jY2F0RGljdC5nZXQoIk5hbWVzIik7CiAgICBjb25zdCByYXdEZXN0cyA9IFtdOwogICAgaWYgKG9iaj8uaGFzKCJEZXN0cyIpKSB7CiAgICAgIHJhd0Rlc3RzLnB1c2gobmV3IE5hbWVUcmVlKG9iai5nZXRSYXcoIkRlc3RzIiksIHRoaXMueHJlZikpOwogICAgfQogICAgaWYgKHRoaXMuI2NhdERpY3QuaGFzKCJEZXN0cyIpKSB7CiAgICAgIHJhd0Rlc3RzLnB1c2godGhpcy4jY2F0RGljdC5nZXQoIkRlc3RzIikpOwogICAgfQogICAgcmV0dXJuIHJhd0Rlc3RzOwogIH0KICBnZXQgcGFnZUxhYmVscygpIHsKICAgIGxldCBvYmogPSBudWxsOwogICAgdHJ5IHsKICAgICAgb2JqID0gdGhpcy4jcmVhZFBhZ2VMYWJlbHMoKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgd2FybigiVW5hYmxlIHRvIHJlYWQgcGFnZSBsYWJlbHMuIik7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJwYWdlTGFiZWxzIiwgb2JqKTsKICB9CiAgI3JlYWRQYWdlTGFiZWxzKCkgewogICAgY29uc3Qgb2JqID0gdGhpcy4jY2F0RGljdC5nZXRSYXcoIlBhZ2VMYWJlbHMiKTsKICAgIGlmICghb2JqKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgcGFnZUxhYmVscyA9IG5ldyBBcnJheSh0aGlzLm51bVBhZ2VzKTsKICAgIGxldCBzdHlsZSA9IG51bGwsCiAgICAgIHByZWZpeCA9ICIiOwogICAgY29uc3QgbnVtYmVyVHJlZSA9IG5ldyBOdW1iZXJUcmVlKG9iaiwgdGhpcy54cmVmKTsKICAgIGNvbnN0IG51bXMgPSBudW1iZXJUcmVlLmdldEFsbCgpOwogICAgbGV0IGN1cnJlbnRMYWJlbCA9ICIiLAogICAgICBjdXJyZW50SW5kZXggPSAxOwogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gdGhpcy5udW1QYWdlczsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgbGFiZWxEaWN0ID0gbnVtcy5nZXQoaSk7CiAgICAgIGlmIChsYWJlbERpY3QgIT09IHVuZGVmaW5lZCkgewogICAgICAgIGlmICghKGxhYmVsRGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlBhZ2VMYWJlbCBpcyBub3QgYSBkaWN0aW9uYXJ5LiIpOwogICAgICAgIH0KICAgICAgICBpZiAobGFiZWxEaWN0LmhhcygiVHlwZSIpICYmICFpc05hbWUobGFiZWxEaWN0LmdldCgiVHlwZSIpLCAiUGFnZUxhYmVsIikpIHsKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCB0eXBlIGluIFBhZ2VMYWJlbCBkaWN0aW9uYXJ5LiIpOwogICAgICAgIH0KICAgICAgICBpZiAobGFiZWxEaWN0LmhhcygiUyIpKSB7CiAgICAgICAgICBjb25zdCBzID0gbGFiZWxEaWN0LmdldCgiUyIpOwogICAgICAgICAgaWYgKCEocyBpbnN0YW5jZW9mIE5hbWUpKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBzdHlsZSBpbiBQYWdlTGFiZWwgZGljdGlvbmFyeS4iKTsKICAgICAgICAgIH0KICAgICAgICAgIHN0eWxlID0gcy5uYW1lOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdHlsZSA9IG51bGw7CiAgICAgICAgfQogICAgICAgIGlmIChsYWJlbERpY3QuaGFzKCJQIikpIHsKICAgICAgICAgIGNvbnN0IHAgPSBsYWJlbERpY3QuZ2V0KCJQIik7CiAgICAgICAgICBpZiAodHlwZW9mIHAgIT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBwcmVmaXggaW4gUGFnZUxhYmVsIGRpY3Rpb25hcnkuIik7CiAgICAgICAgICB9CiAgICAgICAgICBwcmVmaXggPSBzdHJpbmdUb1BERlN0cmluZyhwKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgcHJlZml4ID0gIiI7CiAgICAgICAgfQogICAgICAgIGlmIChsYWJlbERpY3QuaGFzKCJTdCIpKSB7CiAgICAgICAgICBjb25zdCBzdCA9IGxhYmVsRGljdC5nZXQoIlN0Iik7CiAgICAgICAgICBpZiAoIShOdW1iZXIuaXNJbnRlZ2VyKHN0KSAmJiBzdCA+PSAxKSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgc3RhcnQgaW4gUGFnZUxhYmVsIGRpY3Rpb25hcnkuIik7CiAgICAgICAgICB9CiAgICAgICAgICBjdXJyZW50SW5kZXggPSBzdDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY3VycmVudEluZGV4ID0gMTsKICAgICAgICB9CiAgICAgIH0KICAgICAgc3dpdGNoIChzdHlsZSkgewogICAgICAgIGNhc2UgIkQiOgogICAgICAgICAgY3VycmVudExhYmVsID0gY3VycmVudEluZGV4OwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiUiI6CiAgICAgICAgY2FzZSAiciI6CiAgICAgICAgICBjdXJyZW50TGFiZWwgPSB0b1JvbWFuTnVtZXJhbHMoY3VycmVudEluZGV4LCBzdHlsZSA9PT0gInIiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkEiOgogICAgICAgIGNhc2UgImEiOgogICAgICAgICAgY29uc3QgTElNSVQgPSAyNjsKICAgICAgICAgIGNvbnN0IEFfVVBQRVJfQ0FTRSA9IDB4NDEsCiAgICAgICAgICAgIEFfTE9XRVJfQ0FTRSA9IDB4NjE7CiAgICAgICAgICBjb25zdCBiYXNlQ2hhckNvZGUgPSBzdHlsZSA9PT0gImEiID8gQV9MT1dFUl9DQVNFIDogQV9VUFBFUl9DQVNFOwogICAgICAgICAgY29uc3QgbGV0dGVySW5kZXggPSBjdXJyZW50SW5kZXggLSAxOwogICAgICAgICAgY29uc3QgY2hhcmFjdGVyID0gU3RyaW5nLmZyb21DaGFyQ29kZShiYXNlQ2hhckNvZGUgKyBsZXR0ZXJJbmRleCAlIExJTUlUKTsKICAgICAgICAgIGN1cnJlbnRMYWJlbCA9IGNoYXJhY3Rlci5yZXBlYXQoTWF0aC5mbG9vcihsZXR0ZXJJbmRleCAvIExJTUlUKSArIDEpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIGlmIChzdHlsZSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgc3R5bGUgIiR7c3R5bGV9IiBpbiBQYWdlTGFiZWwgZGljdGlvbmFyeS5gKTsKICAgICAgICAgIH0KICAgICAgICAgIGN1cnJlbnRMYWJlbCA9ICIiOwogICAgICB9CiAgICAgIHBhZ2VMYWJlbHNbaV0gPSBwcmVmaXggKyBjdXJyZW50TGFiZWw7CiAgICAgIGN1cnJlbnRJbmRleCsrOwogICAgfQogICAgcmV0dXJuIHBhZ2VMYWJlbHM7CiAgfQogIGdldCBwYWdlTGF5b3V0KCkgewogICAgY29uc3Qgb2JqID0gdGhpcy4jY2F0RGljdC5nZXQoIlBhZ2VMYXlvdXQiKTsKICAgIGxldCBwYWdlTGF5b3V0ID0gIiI7CiAgICBpZiAob2JqIGluc3RhbmNlb2YgTmFtZSkgewogICAgICBzd2l0Y2ggKG9iai5uYW1lKSB7CiAgICAgICAgY2FzZSAiU2luZ2xlUGFnZSI6CiAgICAgICAgY2FzZSAiT25lQ29sdW1uIjoKICAgICAgICBjYXNlICJUd29Db2x1bW5MZWZ0IjoKICAgICAgICBjYXNlICJUd29Db2x1bW5SaWdodCI6CiAgICAgICAgY2FzZSAiVHdvUGFnZUxlZnQiOgogICAgICAgIGNhc2UgIlR3b1BhZ2VSaWdodCI6CiAgICAgICAgICBwYWdlTGF5b3V0ID0gb2JqLm5hbWU7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgInBhZ2VMYXlvdXQiLCBwYWdlTGF5b3V0KTsKICB9CiAgZ2V0IHBhZ2VNb2RlKCkgewogICAgY29uc3Qgb2JqID0gdGhpcy4jY2F0RGljdC5nZXQoIlBhZ2VNb2RlIik7CiAgICBsZXQgcGFnZU1vZGUgPSAiVXNlTm9uZSI7CiAgICBpZiAob2JqIGluc3RhbmNlb2YgTmFtZSkgewogICAgICBzd2l0Y2ggKG9iai5uYW1lKSB7CiAgICAgICAgY2FzZSAiVXNlTm9uZSI6CiAgICAgICAgY2FzZSAiVXNlT3V0bGluZXMiOgogICAgICAgIGNhc2UgIlVzZVRodW1icyI6CiAgICAgICAgY2FzZSAiRnVsbFNjcmVlbiI6CiAgICAgICAgY2FzZSAiVXNlT0MiOgogICAgICAgIGNhc2UgIlVzZUF0dGFjaG1lbnRzIjoKICAgICAgICAgIHBhZ2VNb2RlID0gb2JqLm5hbWU7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgInBhZ2VNb2RlIiwgcGFnZU1vZGUpOwogIH0KICBnZXQgdmlld2VyUHJlZmVyZW5jZXMoKSB7CiAgICBjb25zdCBvYmogPSB0aGlzLiNjYXREaWN0LmdldCgiVmlld2VyUHJlZmVyZW5jZXMiKTsKICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybiBzaGFkb3codGhpcywgInZpZXdlclByZWZlcmVuY2VzIiwgbnVsbCk7CiAgICB9CiAgICBsZXQgcHJlZnMgPSBudWxsOwogICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2Ygb2JqKSB7CiAgICAgIGxldCBwcmVmVmFsdWU7CiAgICAgIHN3aXRjaCAoa2V5KSB7CiAgICAgICAgY2FzZSAiSGlkZVRvb2xiYXIiOgogICAgICAgIGNhc2UgIkhpZGVNZW51YmFyIjoKICAgICAgICBjYXNlICJIaWRlV2luZG93VUkiOgogICAgICAgIGNhc2UgIkZpdFdpbmRvdyI6CiAgICAgICAgY2FzZSAiQ2VudGVyV2luZG93IjoKICAgICAgICBjYXNlICJEaXNwbGF5RG9jVGl0bGUiOgogICAgICAgIGNhc2UgIlBpY2tUcmF5QnlQREZTaXplIjoKICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJib29sZWFuIikgewogICAgICAgICAgICBwcmVmVmFsdWUgPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIk5vbkZ1bGxTY3JlZW5QYWdlTW9kZSI6CiAgICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgIHN3aXRjaCAodmFsdWUubmFtZSkgewogICAgICAgICAgICAgIGNhc2UgIlVzZU5vbmUiOgogICAgICAgICAgICAgIGNhc2UgIlVzZU91dGxpbmVzIjoKICAgICAgICAgICAgICBjYXNlICJVc2VUaHVtYnMiOgogICAgICAgICAgICAgIGNhc2UgIlVzZU9DIjoKICAgICAgICAgICAgICAgIHByZWZWYWx1ZSA9IHZhbHVlLm5hbWU7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgICBkZWZhdWx0OgogICAgICAgICAgICAgICAgcHJlZlZhbHVlID0gIlVzZU5vbmUiOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJEaXJlY3Rpb24iOgogICAgICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgICBzd2l0Y2ggKHZhbHVlLm5hbWUpIHsKICAgICAgICAgICAgICBjYXNlICJMMlIiOgogICAgICAgICAgICAgIGNhc2UgIlIyTCI6CiAgICAgICAgICAgICAgICBwcmVmVmFsdWUgPSB2YWx1ZS5uYW1lOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHByZWZWYWx1ZSA9ICJMMlIiOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJWaWV3QXJlYSI6CiAgICAgICAgY2FzZSAiVmlld0NsaXAiOgogICAgICAgIGNhc2UgIlByaW50QXJlYSI6CiAgICAgICAgY2FzZSAiUHJpbnRDbGlwIjoKICAgICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICAgICAgc3dpdGNoICh2YWx1ZS5uYW1lKSB7CiAgICAgICAgICAgICAgY2FzZSAiTWVkaWFCb3giOgogICAgICAgICAgICAgIGNhc2UgIkNyb3BCb3giOgogICAgICAgICAgICAgIGNhc2UgIkJsZWVkQm94IjoKICAgICAgICAgICAgICBjYXNlICJUcmltQm94IjoKICAgICAgICAgICAgICBjYXNlICJBcnRCb3giOgogICAgICAgICAgICAgICAgcHJlZlZhbHVlID0gdmFsdWUubmFtZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBwcmVmVmFsdWUgPSAiQ3JvcEJveCI7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIlByaW50U2NhbGluZyI6CiAgICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgIHN3aXRjaCAodmFsdWUubmFtZSkgewogICAgICAgICAgICAgIGNhc2UgIk5vbmUiOgogICAgICAgICAgICAgIGNhc2UgIkFwcERlZmF1bHQiOgogICAgICAgICAgICAgICAgcHJlZlZhbHVlID0gdmFsdWUubmFtZTsKICAgICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgICBwcmVmVmFsdWUgPSAiQXBwRGVmYXVsdCI7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkR1cGxleCI6CiAgICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgIHN3aXRjaCAodmFsdWUubmFtZSkgewogICAgICAgICAgICAgIGNhc2UgIlNpbXBsZXgiOgogICAgICAgICAgICAgIGNhc2UgIkR1cGxleEZsaXBTaG9ydEVkZ2UiOgogICAgICAgICAgICAgIGNhc2UgIkR1cGxleEZsaXBMb25nRWRnZSI6CiAgICAgICAgICAgICAgICBwcmVmVmFsdWUgPSB2YWx1ZS5uYW1lOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIHByZWZWYWx1ZSA9ICJOb25lIjsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiUHJpbnRQYWdlUmFuZ2UiOgogICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCAlIDIgPT09IDApIHsKICAgICAgICAgICAgY29uc3QgaXNWYWxpZCA9IHZhbHVlLmV2ZXJ5KChwYWdlLCBpLCBhcnIpID0+IE51bWJlci5pc0ludGVnZXIocGFnZSkgJiYgcGFnZSA+IDAgJiYgKGkgPT09IDAgfHwgcGFnZSA+PSBhcnJbaSAtIDFdKSAmJiBwYWdlIDw9IHRoaXMubnVtUGFnZXMpOwogICAgICAgICAgICBpZiAoaXNWYWxpZCkgewogICAgICAgICAgICAgIHByZWZWYWx1ZSA9IHZhbHVlOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJOdW1Db3BpZXMiOgogICAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodmFsdWUpICYmIHZhbHVlID4gMCkgewogICAgICAgICAgICBwcmVmVmFsdWUgPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICB3YXJuKGBJZ25vcmluZyBub24tc3RhbmRhcmQga2V5IGluIFZpZXdlclByZWZlcmVuY2VzOiAke2tleX0uYCk7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAocHJlZlZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgICB3YXJuKGBCYWQgdmFsdWUsIGZvciBrZXkgIiR7a2V5fSIsIGluIFZpZXdlclByZWZlcmVuY2VzOiAke3ZhbHVlfS5gKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBwcmVmcyA/Pz0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgcHJlZnNba2V5XSA9IHByZWZWYWx1ZTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgInZpZXdlclByZWZlcmVuY2VzIiwgcHJlZnMpOwogIH0KICBnZXQgb3BlbkFjdGlvbigpIHsKICAgIGNvbnN0IG9iaiA9IHRoaXMuI2NhdERpY3QuZ2V0KCJPcGVuQWN0aW9uIik7CiAgICBjb25zdCBvcGVuQWN0aW9uID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGlmIChvYmogaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgIGNvbnN0IGRlc3REaWN0ID0gbmV3IERpY3QodGhpcy54cmVmKTsKICAgICAgZGVzdERpY3Quc2V0KCJBIiwgb2JqKTsKICAgICAgY29uc3QgcmVzdWx0T2JqID0gewogICAgICAgIHVybDogbnVsbCwKICAgICAgICBkZXN0OiBudWxsLAogICAgICAgIGFjdGlvbjogbnVsbAogICAgICB9OwogICAgICBDYXRhbG9nLnBhcnNlRGVzdERpY3Rpb25hcnkoewogICAgICAgIGRlc3REaWN0LAogICAgICAgIHJlc3VsdE9iagogICAgICB9KTsKICAgICAgaWYgKEFycmF5LmlzQXJyYXkocmVzdWx0T2JqLmRlc3QpKSB7CiAgICAgICAgb3BlbkFjdGlvbi5kZXN0ID0gcmVzdWx0T2JqLmRlc3Q7CiAgICAgIH0gZWxzZSBpZiAocmVzdWx0T2JqLmFjdGlvbikgewogICAgICAgIG9wZW5BY3Rpb24uYWN0aW9uID0gcmVzdWx0T2JqLmFjdGlvbjsKICAgICAgfQogICAgfSBlbHNlIGlmIChpc1ZhbGlkRXhwbGljaXREZXN0KG9iaikpIHsKICAgICAgb3BlbkFjdGlvbi5kZXN0ID0gb2JqOwogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAib3BlbkFjdGlvbiIsIG9iamVjdFNpemUob3BlbkFjdGlvbikgPiAwID8gb3BlbkFjdGlvbiA6IG51bGwpOwogIH0KICBnZXQgYXR0YWNobWVudHMoKSB7CiAgICBjb25zdCBvYmogPSB0aGlzLiNjYXREaWN0LmdldCgiTmFtZXMiKTsKICAgIGxldCBhdHRhY2htZW50cyA9IG51bGw7CiAgICBpZiAob2JqIGluc3RhbmNlb2YgRGljdCAmJiBvYmouaGFzKCJFbWJlZGRlZEZpbGVzIikpIHsKICAgICAgY29uc3QgbmFtZVRyZWUgPSBuZXcgTmFtZVRyZWUob2JqLmdldFJhdygiRW1iZWRkZWRGaWxlcyIpLCB0aGlzLnhyZWYpOwogICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBuYW1lVHJlZS5nZXRBbGwoKSkgewogICAgICAgIGNvbnN0IGZzID0gbmV3IEZpbGVTcGVjKHZhbHVlLCB0aGlzLnhyZWYpOwogICAgICAgIGF0dGFjaG1lbnRzID8/PSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICAgIGF0dGFjaG1lbnRzW3N0cmluZ1RvUERGU3RyaW5nKGtleSwgdHJ1ZSldID0gZnMuc2VyaWFsaXphYmxlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJhdHRhY2htZW50cyIsIGF0dGFjaG1lbnRzKTsKICB9CiAgZ2V0IHhmYUltYWdlcygpIHsKICAgIGNvbnN0IG9iaiA9IHRoaXMuI2NhdERpY3QuZ2V0KCJOYW1lcyIpOwogICAgbGV0IHhmYUltYWdlcyA9IG51bGw7CiAgICBpZiAob2JqIGluc3RhbmNlb2YgRGljdCAmJiBvYmouaGFzKCJYRkFJbWFnZXMiKSkgewogICAgICBjb25zdCBuYW1lVHJlZSA9IG5ldyBOYW1lVHJlZShvYmouZ2V0UmF3KCJYRkFJbWFnZXMiKSwgdGhpcy54cmVmKTsKICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgbmFtZVRyZWUuZ2V0QWxsKCkpIHsKICAgICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICAgICAgICB4ZmFJbWFnZXMgPz89IG5ldyBNYXAoKTsKICAgICAgICAgIHhmYUltYWdlcy5zZXQoc3RyaW5nVG9QREZTdHJpbmcoa2V5LCB0cnVlKSwgdmFsdWUuZ2V0Qnl0ZXMoKSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJ4ZmFJbWFnZXMiLCB4ZmFJbWFnZXMpOwogIH0KICAjY29sbGVjdEphdmFTY3JpcHQoKSB7CiAgICBjb25zdCBvYmogPSB0aGlzLiNjYXREaWN0LmdldCgiTmFtZXMiKTsKICAgIGxldCBqYXZhU2NyaXB0ID0gbnVsbDsKICAgIGZ1bmN0aW9uIGFwcGVuZElmSmF2YVNjcmlwdERpY3QobmFtZSwganNEaWN0KSB7CiAgICAgIGlmICghKGpzRGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGlmICghaXNOYW1lKGpzRGljdC5nZXQoIlMiKSwgIkphdmFTY3JpcHQiKSkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBsZXQganMgPSBqc0RpY3QuZ2V0KCJKUyIpOwogICAgICBpZiAoanMgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICAgICAganMgPSBqcy5nZXRTdHJpbmcoKTsKICAgICAgfSBlbHNlIGlmICh0eXBlb2YganMgIT09ICJzdHJpbmciKSB7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGpzID0gc3RyaW5nVG9QREZTdHJpbmcoanMsIHRydWUpLnJlcGxhY2VBbGwoIlx4MDAiLCAiIik7CiAgICAgIGlmIChqcykgewogICAgICAgIChqYXZhU2NyaXB0IHx8PSBuZXcgTWFwKCkpLnNldChuYW1lLCBqcyk7CiAgICAgIH0KICAgIH0KICAgIGlmIChvYmogaW5zdGFuY2VvZiBEaWN0ICYmIG9iai5oYXMoIkphdmFTY3JpcHQiKSkgewogICAgICBjb25zdCBuYW1lVHJlZSA9IG5ldyBOYW1lVHJlZShvYmouZ2V0UmF3KCJKYXZhU2NyaXB0IiksIHRoaXMueHJlZik7CiAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIG5hbWVUcmVlLmdldEFsbCgpKSB7CiAgICAgICAgYXBwZW5kSWZKYXZhU2NyaXB0RGljdChzdHJpbmdUb1BERlN0cmluZyhrZXksIHRydWUpLCB2YWx1ZSk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IG9wZW5BY3Rpb24gPSB0aGlzLiNjYXREaWN0LmdldCgiT3BlbkFjdGlvbiIpOwogICAgaWYgKG9wZW5BY3Rpb24pIHsKICAgICAgYXBwZW5kSWZKYXZhU2NyaXB0RGljdCgiT3BlbkFjdGlvbiIsIG9wZW5BY3Rpb24pOwogICAgfQogICAgcmV0dXJuIGphdmFTY3JpcHQ7CiAgfQogIGdldCBqc0FjdGlvbnMoKSB7CiAgICBjb25zdCBqYXZhU2NyaXB0ID0gdGhpcy4jY29sbGVjdEphdmFTY3JpcHQoKTsKICAgIGxldCBhY3Rpb25zID0gY29sbGVjdEFjdGlvbnModGhpcy54cmVmLCB0aGlzLiNjYXREaWN0LCBEb2N1bWVudEFjdGlvbkV2ZW50VHlwZSk7CiAgICBpZiAoamF2YVNjcmlwdCkgewogICAgICBhY3Rpb25zIHx8PSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbF0gb2YgamF2YVNjcmlwdCkgewogICAgICAgIGlmIChrZXkgaW4gYWN0aW9ucykgewogICAgICAgICAgYWN0aW9uc1trZXldLnB1c2godmFsKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgYWN0aW9uc1trZXldID0gW3ZhbF07CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJqc0FjdGlvbnMiLCBhY3Rpb25zKTsKICB9CiAgYXN5bmMgY2xlYW51cChtYW51YWxseVRyaWdnZXJlZCA9IGZhbHNlKSB7CiAgICBjbGVhckdsb2JhbENhY2hlcygpOwogICAgdGhpcy5nbG9iYWxDb2xvclNwYWNlQ2FjaGUuY2xlYXIoKTsKICAgIHRoaXMuZ2xvYmFsSW1hZ2VDYWNoZS5jbGVhcihtYW51YWxseVRyaWdnZXJlZCk7CiAgICB0aGlzLnBhZ2VLaWRzQ291bnRDYWNoZS5jbGVhcigpOwogICAgdGhpcy5wYWdlSW5kZXhDYWNoZS5jbGVhcigpOwogICAgdGhpcy5wYWdlRGljdENhY2hlLmNsZWFyKCk7CiAgICB0aGlzLm5vbkJsZW5kTW9kZXNTZXQuY2xlYXIoKTsKICAgIGZvciAoY29uc3QgewogICAgICBkaWN0CiAgICB9IG9mIGF3YWl0IFByb21pc2UuYWxsKHRoaXMuZm9udENhY2hlKSkgewogICAgICBkZWxldGUgZGljdC5jYWNoZUtleTsKICAgIH0KICAgIHRoaXMuZm9udENhY2hlLmNsZWFyKCk7CiAgICB0aGlzLmJ1aWx0SW5DTWFwQ2FjaGUuY2xlYXIoKTsKICAgIHRoaXMuc3RhbmRhcmRGb250RGF0YUNhY2hlLmNsZWFyKCk7CiAgICB0aGlzLnN5c3RlbUZvbnRDYWNoZS5jbGVhcigpOwogIH0KICBhc3luYyBnZXRQYWdlRGljdChwYWdlSW5kZXgpIHsKICAgIGNvbnN0IG5vZGVzVG9WaXNpdCA9IFt0aGlzLnRvcGxldmVsUGFnZXNEaWN0XTsKICAgIGNvbnN0IHZpc2l0ZWROb2RlcyA9IG5ldyBSZWZTZXQoKTsKICAgIGNvbnN0IHBhZ2VzUmVmID0gdGhpcy4jY2F0RGljdC5nZXRSYXcoIlBhZ2VzIik7CiAgICBpZiAocGFnZXNSZWYgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgdmlzaXRlZE5vZGVzLnB1dChwYWdlc1JlZik7CiAgICB9CiAgICBjb25zdCB4cmVmID0gdGhpcy54cmVmLAogICAgICBwYWdlS2lkc0NvdW50Q2FjaGUgPSB0aGlzLnBhZ2VLaWRzQ291bnRDYWNoZSwKICAgICAgcGFnZUluZGV4Q2FjaGUgPSB0aGlzLnBhZ2VJbmRleENhY2hlLAogICAgICBwYWdlRGljdENhY2hlID0gdGhpcy5wYWdlRGljdENhY2hlOwogICAgbGV0IGN1cnJlbnRQYWdlSW5kZXggPSAwOwogICAgd2hpbGUgKG5vZGVzVG9WaXNpdC5sZW5ndGgpIHsKICAgICAgY29uc3QgY3VycmVudE5vZGUgPSBub2Rlc1RvVmlzaXQucG9wKCk7CiAgICAgIGlmIChjdXJyZW50Tm9kZSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIGNvbnN0IGNvdW50ID0gcGFnZUtpZHNDb3VudENhY2hlLmdldChjdXJyZW50Tm9kZSk7CiAgICAgICAgaWYgKGNvdW50ID49IDAgJiYgY3VycmVudFBhZ2VJbmRleCArIGNvdW50IDw9IHBhZ2VJbmRleCkgewogICAgICAgICAgY3VycmVudFBhZ2VJbmRleCArPSBjb3VudDsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBpZiAodmlzaXRlZE5vZGVzLmhhcyhjdXJyZW50Tm9kZSkpIHsKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiUGFnZXMgdHJlZSBjb250YWlucyBjaXJjdWxhciByZWZlcmVuY2UuIik7CiAgICAgICAgfQogICAgICAgIHZpc2l0ZWROb2Rlcy5wdXQoY3VycmVudE5vZGUpOwogICAgICAgIGNvbnN0IG9iaiA9IGF3YWl0IChwYWdlRGljdENhY2hlLmdldChjdXJyZW50Tm9kZSkgfHwgeHJlZi5mZXRjaEFzeW5jKGN1cnJlbnROb2RlKSk7CiAgICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICAgIGxldCB0eXBlID0gb2JqLmdldFJhdygiVHlwZSIpOwogICAgICAgICAgaWYgKHR5cGUgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICAgICAgdHlwZSA9IGF3YWl0IHhyZWYuZmV0Y2hBc3luYyh0eXBlKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChpc05hbWUodHlwZSwgIlBhZ2UiKSB8fCAhb2JqLmhhcygiS2lkcyIpKSB7CiAgICAgICAgICAgIGlmICghcGFnZUtpZHNDb3VudENhY2hlLmhhcyhjdXJyZW50Tm9kZSkpIHsKICAgICAgICAgICAgICBwYWdlS2lkc0NvdW50Q2FjaGUucHV0KGN1cnJlbnROb2RlLCAxKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAoIXBhZ2VJbmRleENhY2hlLmhhcyhjdXJyZW50Tm9kZSkpIHsKICAgICAgICAgICAgICBwYWdlSW5kZXhDYWNoZS5wdXQoY3VycmVudE5vZGUsIGN1cnJlbnRQYWdlSW5kZXgpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChjdXJyZW50UGFnZUluZGV4ID09PSBwYWdlSW5kZXgpIHsKICAgICAgICAgICAgICByZXR1cm4gW29iaiwgY3VycmVudE5vZGVdOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGN1cnJlbnRQYWdlSW5kZXgrKzsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIG5vZGVzVG9WaXNpdC5wdXNoKG9iaik7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKCEoY3VycmVudE5vZGUgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiUGFnZSBkaWN0aW9uYXJ5IGtpZCByZWZlcmVuY2UgcG9pbnRzIHRvIHdyb25nIHR5cGUgb2Ygb2JqZWN0LiIpOwogICAgICB9CiAgICAgIGNvbnN0IHsKICAgICAgICBvYmpJZAogICAgICB9ID0gY3VycmVudE5vZGU7CiAgICAgIGxldCBjb3VudCA9IGN1cnJlbnROb2RlLmdldFJhdygiQ291bnQiKTsKICAgICAgaWYgKGNvdW50IGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgY291bnQgPSBhd2FpdCB4cmVmLmZldGNoQXN5bmMoY291bnQpOwogICAgICB9CiAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKGNvdW50KSAmJiBjb3VudCA+PSAwKSB7CiAgICAgICAgaWYgKG9iaklkICYmICFwYWdlS2lkc0NvdW50Q2FjaGUuaGFzKG9iaklkKSkgewogICAgICAgICAgcGFnZUtpZHNDb3VudENhY2hlLnB1dChvYmpJZCwgY291bnQpOwogICAgICAgIH0KICAgICAgICBpZiAoY3VycmVudFBhZ2VJbmRleCArIGNvdW50IDw9IHBhZ2VJbmRleCkgewogICAgICAgICAgY3VycmVudFBhZ2VJbmRleCArPSBjb3VudDsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgfQogICAgICBsZXQga2lkcyA9IGN1cnJlbnROb2RlLmdldFJhdygiS2lkcyIpOwogICAgICBpZiAoa2lkcyBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIGtpZHMgPSBhd2FpdCB4cmVmLmZldGNoQXN5bmMoa2lkcyk7CiAgICAgIH0KICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGtpZHMpKSB7CiAgICAgICAgbGV0IHR5cGUgPSBjdXJyZW50Tm9kZS5nZXRSYXcoIlR5cGUiKTsKICAgICAgICBpZiAodHlwZSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgdHlwZSA9IGF3YWl0IHhyZWYuZmV0Y2hBc3luYyh0eXBlKTsKICAgICAgICB9CiAgICAgICAgaWYgKGlzTmFtZSh0eXBlLCAiUGFnZSIpIHx8ICFjdXJyZW50Tm9kZS5oYXMoIktpZHMiKSkgewogICAgICAgICAgaWYgKGN1cnJlbnRQYWdlSW5kZXggPT09IHBhZ2VJbmRleCkgewogICAgICAgICAgICByZXR1cm4gW2N1cnJlbnROb2RlLCBudWxsXTsKICAgICAgICAgIH0KICAgICAgICAgIGN1cnJlbnRQYWdlSW5kZXgrKzsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlBhZ2UgZGljdGlvbmFyeSBraWRzIG9iamVjdCBpcyBub3QgYW4gYXJyYXkuIik7CiAgICAgIH0KICAgICAgZm9yIChsZXQgbGFzdCA9IGtpZHMubGVuZ3RoIC0gMTsgbGFzdCA+PSAwOyBsYXN0LS0pIHsKICAgICAgICBjb25zdCBsYXN0S2lkID0ga2lkc1tsYXN0XTsKICAgICAgICBub2Rlc1RvVmlzaXQucHVzaChsYXN0S2lkKTsKICAgICAgICBpZiAoY3VycmVudE5vZGUgPT09IHRoaXMudG9wbGV2ZWxQYWdlc0RpY3QgJiYgbGFzdEtpZCBpbnN0YW5jZW9mIFJlZiAmJiAhcGFnZURpY3RDYWNoZS5oYXMobGFzdEtpZCkpIHsKICAgICAgICAgIHBhZ2VEaWN0Q2FjaGUucHV0KGxhc3RLaWQsIHhyZWYuZmV0Y2hBc3luYyhsYXN0S2lkKSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICB0aHJvdyBuZXcgRXJyb3IoYFBhZ2UgaW5kZXggJHtwYWdlSW5kZXh9IG5vdCBmb3VuZC5gKTsKICB9CiAgYXN5bmMgZ2V0QWxsUGFnZURpY3RzKHJlY292ZXJ5TW9kZSA9IGZhbHNlKSB7CiAgICBjb25zdCB7CiAgICAgIGlnbm9yZUVycm9ycwogICAgfSA9IHRoaXMucGRmTWFuYWdlci5ldmFsdWF0b3JPcHRpb25zOwogICAgY29uc3QgcXVldWUgPSBbewogICAgICBjdXJyZW50Tm9kZTogdGhpcy50b3BsZXZlbFBhZ2VzRGljdCwKICAgICAgcG9zSW5LaWRzOiAwCiAgICB9XTsKICAgIGNvbnN0IHZpc2l0ZWROb2RlcyA9IG5ldyBSZWZTZXQoKTsKICAgIGNvbnN0IHBhZ2VzUmVmID0gdGhpcy4jY2F0RGljdC5nZXRSYXcoIlBhZ2VzIik7CiAgICBpZiAocGFnZXNSZWYgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgdmlzaXRlZE5vZGVzLnB1dChwYWdlc1JlZik7CiAgICB9CiAgICBjb25zdCBtYXAgPSBuZXcgTWFwKCksCiAgICAgIHhyZWYgPSB0aGlzLnhyZWYsCiAgICAgIHBhZ2VJbmRleENhY2hlID0gdGhpcy5wYWdlSW5kZXhDYWNoZTsKICAgIGxldCBwYWdlSW5kZXggPSAwOwogICAgZnVuY3Rpb24gYWRkUGFnZURpY3QocGFnZURpY3QsIHBhZ2VSZWYpIHsKICAgICAgaWYgKHBhZ2VSZWYgJiYgIXBhZ2VJbmRleENhY2hlLmhhcyhwYWdlUmVmKSkgewogICAgICAgIHBhZ2VJbmRleENhY2hlLnB1dChwYWdlUmVmLCBwYWdlSW5kZXgpOwogICAgICB9CiAgICAgIG1hcC5zZXQocGFnZUluZGV4KyssIFtwYWdlRGljdCwgcGFnZVJlZl0pOwogICAgfQogICAgZnVuY3Rpb24gYWRkUGFnZUVycm9yKGVycm9yKSB7CiAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFhSZWZFbnRyeUV4Y2VwdGlvbiAmJiAhcmVjb3ZlcnlNb2RlKSB7CiAgICAgICAgdGhyb3cgZXJyb3I7CiAgICAgIH0KICAgICAgaWYgKHJlY292ZXJ5TW9kZSAmJiBpZ25vcmVFcnJvcnMgJiYgcGFnZUluZGV4ID09PSAwKSB7CiAgICAgICAgd2FybihgZ2V0QWxsUGFnZURpY3RzIC0gU2tpcHBpbmcgaW52YWxpZCBmaXJzdCBwYWdlOiAiJHtlcnJvcn0iLmApOwogICAgICAgIGVycm9yID0gRGljdC5lbXB0eTsKICAgICAgfQogICAgICBtYXAuc2V0KHBhZ2VJbmRleCsrLCBbZXJyb3IsIG51bGxdKTsKICAgIH0KICAgIHdoaWxlIChxdWV1ZS5sZW5ndGggPiAwKSB7CiAgICAgIGNvbnN0IHF1ZXVlSXRlbSA9IHF1ZXVlLmF0KC0xKTsKICAgICAgY29uc3QgewogICAgICAgIGN1cnJlbnROb2RlLAogICAgICAgIHBvc0luS2lkcwogICAgICB9ID0gcXVldWVJdGVtOwogICAgICBsZXQga2lkcyA9IGN1cnJlbnROb2RlLmdldFJhdygiS2lkcyIpOwogICAgICBpZiAoa2lkcyBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIHRyeSB7CiAgICAgICAgICBraWRzID0gYXdhaXQgeHJlZi5mZXRjaEFzeW5jKGtpZHMpOwogICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICBhZGRQYWdlRXJyb3IoZXgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmICghQXJyYXkuaXNBcnJheShraWRzKSkgewogICAgICAgIGFkZFBhZ2VFcnJvcihuZXcgRm9ybWF0RXJyb3IoIlBhZ2UgZGljdGlvbmFyeSBraWRzIG9iamVjdCBpcyBub3QgYW4gYXJyYXkuIikpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGlmIChwb3NJbktpZHMgPj0ga2lkcy5sZW5ndGgpIHsKICAgICAgICBxdWV1ZS5wb3AoKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBraWRPYmogPSBraWRzW3Bvc0luS2lkc107CiAgICAgIGxldCBvYmo7CiAgICAgIGlmIChraWRPYmogaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICBpZiAodmlzaXRlZE5vZGVzLmhhcyhraWRPYmopKSB7CiAgICAgICAgICBhZGRQYWdlRXJyb3IobmV3IEZvcm1hdEVycm9yKCJQYWdlcyB0cmVlIGNvbnRhaW5zIGNpcmN1bGFyIHJlZmVyZW5jZS4iKSk7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdmlzaXRlZE5vZGVzLnB1dChraWRPYmopOwogICAgICAgIHRyeSB7CiAgICAgICAgICBvYmogPSBhd2FpdCB4cmVmLmZldGNoQXN5bmMoa2lkT2JqKTsKICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgYWRkUGFnZUVycm9yKGV4KTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBvYmogPSBraWRPYmo7CiAgICAgIH0KICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICBhZGRQYWdlRXJyb3IobmV3IEZvcm1hdEVycm9yKCJQYWdlIGRpY3Rpb25hcnkga2lkIHJlZmVyZW5jZSBwb2ludHMgdG8gd3JvbmcgdHlwZSBvZiBvYmplY3QuIikpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGxldCB0eXBlID0gb2JqLmdldFJhdygiVHlwZSIpOwogICAgICBpZiAodHlwZSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIHRyeSB7CiAgICAgICAgICB0eXBlID0gYXdhaXQgeHJlZi5mZXRjaEFzeW5jKHR5cGUpOwogICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICBhZGRQYWdlRXJyb3IoZXgpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChpc05hbWUodHlwZSwgIlBhZ2UiKSB8fCAhb2JqLmhhcygiS2lkcyIpKSB7CiAgICAgICAgYWRkUGFnZURpY3Qob2JqLCBraWRPYmogaW5zdGFuY2VvZiBSZWYgPyBraWRPYmogOiBudWxsKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBxdWV1ZS5wdXNoKHsKICAgICAgICAgIGN1cnJlbnROb2RlOiBvYmosCiAgICAgICAgICBwb3NJbktpZHM6IDAKICAgICAgICB9KTsKICAgICAgfQogICAgICBxdWV1ZUl0ZW0ucG9zSW5LaWRzKys7CiAgICB9CiAgICByZXR1cm4gbWFwOwogIH0KICBnZXRQYWdlSW5kZXgocGFnZVJlZikgewogICAgY29uc3QgY2FjaGVkUGFnZUluZGV4ID0gdGhpcy5wYWdlSW5kZXhDYWNoZS5nZXQocGFnZVJlZik7CiAgICBpZiAoY2FjaGVkUGFnZUluZGV4ICE9PSB1bmRlZmluZWQpIHsKICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShjYWNoZWRQYWdlSW5kZXgpOwogICAgfQogICAgY29uc3QgeHJlZiA9IHRoaXMueHJlZjsKICAgIGZ1bmN0aW9uIHBhZ2VzQmVmb3JlUmVmKGtpZFJlZikgewogICAgICBsZXQgdG90YWwgPSAwLAogICAgICAgIHBhcmVudFJlZjsKICAgICAgcmV0dXJuIHhyZWYuZmV0Y2hBc3luYyhraWRSZWYpLnRoZW4oZnVuY3Rpb24gKG5vZGUpIHsKICAgICAgICBpZiAoaXNSZWZzRXF1YWwoa2lkUmVmLCBwYWdlUmVmKSAmJiAhaXNEaWN0KG5vZGUsICJQYWdlIikgJiYgIShub2RlIGluc3RhbmNlb2YgRGljdCAmJiAhbm9kZS5oYXMoIlR5cGUiKSAmJiBub2RlLmhhcygiQ29udGVudHMiKSkpIHsKICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiVGhlIHJlZmVyZW5jZSBkb2VzIG5vdCBwb2ludCB0byBhIC9QYWdlIGRpY3Rpb25hcnkuIik7CiAgICAgICAgfQogICAgICAgIGlmICghbm9kZSkgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIGlmICghKG5vZGUgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJOb2RlIG11c3QgYmUgYSBkaWN0aW9uYXJ5LiIpOwogICAgICAgIH0KICAgICAgICBwYXJlbnRSZWYgPSBub2RlLmdldFJhdygiUGFyZW50Iik7CiAgICAgICAgcmV0dXJuIG5vZGUuZ2V0QXN5bmMoIlBhcmVudCIpOwogICAgICB9KS50aGVuKGZ1bmN0aW9uIChwYXJlbnQpIHsKICAgICAgICBpZiAoIXBhcmVudCkgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIGlmICghKHBhcmVudCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlBhcmVudCBtdXN0IGJlIGEgZGljdGlvbmFyeS4iKTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHBhcmVudC5nZXRBc3luYygiS2lkcyIpOwogICAgICB9KS50aGVuKGZ1bmN0aW9uIChraWRzKSB7CiAgICAgICAgaWYgKCFraWRzKSB7CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgICAgY29uc3Qga2lkUHJvbWlzZXMgPSBbXTsKICAgICAgICBsZXQgZm91bmQgPSBmYWxzZTsKICAgICAgICBmb3IgKGNvbnN0IGtpZCBvZiBraWRzKSB7CiAgICAgICAgICBpZiAoIShraWQgaW5zdGFuY2VvZiBSZWYpKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiS2lkIG11c3QgYmUgYSByZWZlcmVuY2UuIik7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoaXNSZWZzRXF1YWwoa2lkLCBraWRSZWYpKSB7CiAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBraWRQcm9taXNlcy5wdXNoKHhyZWYuZmV0Y2hBc3luYyhraWQpLnRoZW4oZnVuY3Rpb24gKG9iaikgewogICAgICAgICAgICBpZiAoIShvYmogaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiS2lkIG5vZGUgbXVzdCBiZSBhIGRpY3Rpb25hcnkuIik7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKG9iai5oYXMoIkNvdW50IikpIHsKICAgICAgICAgICAgICB0b3RhbCArPSBvYmouZ2V0KCJDb3VudCIpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIHRvdGFsKys7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0pKTsKICAgICAgICB9CiAgICAgICAgaWYgKCFmb3VuZCkgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJLaWQgcmVmZXJlbmNlIG5vdCBmb3VuZCBpbiBwYXJlbnQncyBraWRzLiIpOwogICAgICAgIH0KICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwoa2lkUHJvbWlzZXMpLnRoZW4oKCkgPT4gW3RvdGFsLCBwYXJlbnRSZWZdKTsKICAgICAgfSk7CiAgICB9CiAgICBsZXQgdG90YWwgPSAwOwogICAgY29uc3QgbmV4dCA9IHJlZiA9PiBwYWdlc0JlZm9yZVJlZihyZWYpLnRoZW4oYXJncyA9PiB7CiAgICAgIGlmICghYXJncykgewogICAgICAgIHRoaXMucGFnZUluZGV4Q2FjaGUucHV0KHBhZ2VSZWYsIHRvdGFsKTsKICAgICAgICByZXR1cm4gdG90YWw7CiAgICAgIH0KICAgICAgY29uc3QgW2NvdW50LCBwYXJlbnRSZWZdID0gYXJnczsKICAgICAgdG90YWwgKz0gY291bnQ7CiAgICAgIHJldHVybiBuZXh0KHBhcmVudFJlZik7CiAgICB9KTsKICAgIHJldHVybiBuZXh0KHBhZ2VSZWYpOwogIH0KICBnZXQgYmFzZVVybCgpIHsKICAgIGNvbnN0IHVyaSA9IHRoaXMuI2NhdERpY3QuZ2V0KCJVUkkiKTsKICAgIGlmICh1cmkgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgIGNvbnN0IGJhc2UgPSB1cmkuZ2V0KCJCYXNlIik7CiAgICAgIGlmICh0eXBlb2YgYmFzZSA9PT0gInN0cmluZyIpIHsKICAgICAgICBjb25zdCBhYnNvbHV0ZVVybCA9IGNyZWF0ZVZhbGlkQWJzb2x1dGVVcmwoYmFzZSwgbnVsbCwgewogICAgICAgICAgdHJ5Q29udmVydEVuY29kaW5nOiB0cnVlCiAgICAgICAgfSk7CiAgICAgICAgaWYgKGFic29sdXRlVXJsKSB7CiAgICAgICAgICByZXR1cm4gc2hhZG93KHRoaXMsICJiYXNlVXJsIiwgYWJzb2x1dGVVcmwuaHJlZik7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJiYXNlVXJsIiwgdGhpcy5wZGZNYW5hZ2VyLmRvY0Jhc2VVcmwpOwogIH0KICBzdGF0aWMgcGFyc2VEZXN0RGljdGlvbmFyeSh7CiAgICBkZXN0RGljdCwKICAgIHJlc3VsdE9iaiwKICAgIGRvY0Jhc2VVcmwgPSBudWxsLAogICAgZG9jQXR0YWNobWVudHMgPSBudWxsCiAgfSkgewogICAgaWYgKCEoZGVzdERpY3QgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICB3YXJuKCJwYXJzZURlc3REaWN0aW9uYXJ5OiBgZGVzdERpY3RgIG11c3QgYmUgYSBkaWN0aW9uYXJ5LiIpOwogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgYWN0aW9uID0gZGVzdERpY3QuZ2V0KCJBIiksCiAgICAgIHVybCwKICAgICAgZGVzdDsKICAgIGlmICghKGFjdGlvbiBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIGlmIChkZXN0RGljdC5oYXMoIkRlc3QiKSkgewogICAgICAgIGFjdGlvbiA9IGRlc3REaWN0LmdldCgiRGVzdCIpOwogICAgICB9IGVsc2UgewogICAgICAgIGFjdGlvbiA9IGRlc3REaWN0LmdldCgiQUEiKTsKICAgICAgICBpZiAoYWN0aW9uIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgICAgaWYgKGFjdGlvbi5oYXMoIkQiKSkgewogICAgICAgICAgICBhY3Rpb24gPSBhY3Rpb24uZ2V0KCJEIik7CiAgICAgICAgICB9IGVsc2UgaWYgKGFjdGlvbi5oYXMoIlUiKSkgewogICAgICAgICAgICBhY3Rpb24gPSBhY3Rpb24uZ2V0KCJVIik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAoYWN0aW9uIGluc3RhbmNlb2YgRGljdCkgewogICAgICBjb25zdCBhY3Rpb25UeXBlID0gYWN0aW9uLmdldCgiUyIpOwogICAgICBpZiAoIShhY3Rpb25UeXBlIGluc3RhbmNlb2YgTmFtZSkpIHsKICAgICAgICB3YXJuKCJwYXJzZURlc3REaWN0aW9uYXJ5OiBJbnZhbGlkIHR5cGUgaW4gQWN0aW9uIGRpY3Rpb25hcnkuIik7CiAgICAgICAgcmV0dXJuOwogICAgICB9CiAgICAgIGNvbnN0IGFjdGlvbk5hbWUgPSBhY3Rpb25UeXBlLm5hbWU7CiAgICAgIHN3aXRjaCAoYWN0aW9uTmFtZSkgewogICAgICAgIGNhc2UgIlJlc2V0Rm9ybSI6CiAgICAgICAgICBjb25zdCBmbGFncyA9IGFjdGlvbi5nZXQoIkZsYWdzIik7CiAgICAgICAgICBjb25zdCBpbmNsdWRlID0gKCh0eXBlb2YgZmxhZ3MgPT09ICJudW1iZXIiID8gZmxhZ3MgOiAwKSAmIDEpID09PSAwOwogICAgICAgICAgY29uc3QgZmllbGRzID0gW107CiAgICAgICAgICBjb25zdCByZWZzID0gW107CiAgICAgICAgICBmb3IgKGNvbnN0IG9iaiBvZiBhY3Rpb24uZ2V0KCJGaWVsZHMiKSB8fCBbXSkgewogICAgICAgICAgICBpZiAob2JqIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgICAgICAgcmVmcy5wdXNoKG9iai50b1N0cmluZygpKTsKICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygb2JqID09PSAic3RyaW5nIikgewogICAgICAgICAgICAgIGZpZWxkcy5wdXNoKHN0cmluZ1RvUERGU3RyaW5nKG9iaikpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICByZXN1bHRPYmoucmVzZXRGb3JtID0gewogICAgICAgICAgICBmaWVsZHMsCiAgICAgICAgICAgIHJlZnMsCiAgICAgICAgICAgIGluY2x1ZGUKICAgICAgICAgIH07CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJVUkkiOgogICAgICAgICAgdXJsID0gYWN0aW9uLmdldCgiVVJJIik7CiAgICAgICAgICBpZiAodXJsIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgICB1cmwgPSAiLyIgKyB1cmwubmFtZTsKICAgICAgICAgIH0KICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkdvVG8iOgogICAgICAgICAgZGVzdCA9IGFjdGlvbi5nZXQoIkQiKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIkxhdW5jaCI6CiAgICAgICAgY2FzZSAiR29Ub1IiOgogICAgICAgICAgY29uc3QgdXJsRGljdCA9IGFjdGlvbi5nZXQoIkYiKTsKICAgICAgICAgIGlmICh1cmxEaWN0IGluc3RhbmNlb2YgRGljdCkgewogICAgICAgICAgICBjb25zdCBmcyA9IG5ldyBGaWxlU3BlYyh1cmxEaWN0LCBudWxsLCB0cnVlKTsKICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgIHJhd0ZpbGVuYW1lCiAgICAgICAgICAgIH0gPSBmcy5zZXJpYWxpemFibGU7CiAgICAgICAgICAgIHVybCA9IHJhd0ZpbGVuYW1lOwogICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdXJsRGljdCA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgdXJsID0gdXJsRGljdDsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IHJlbW90ZURlc3QgPSBmZXRjaFJlbW90ZURlc3QoYWN0aW9uKTsKICAgICAgICAgIGlmIChyZW1vdGVEZXN0ICYmIHR5cGVvZiB1cmwgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgIHVybCA9IHVybC5zcGxpdCgiIyIsIDEpWzBdICsgIiMiICsgcmVtb3RlRGVzdDsKICAgICAgICAgIH0KICAgICAgICAgIGNvbnN0IG5ld1dpbmRvdyA9IGFjdGlvbi5nZXQoIk5ld1dpbmRvdyIpOwogICAgICAgICAgaWYgKHR5cGVvZiBuZXdXaW5kb3cgPT09ICJib29sZWFuIikgewogICAgICAgICAgICByZXN1bHRPYmoubmV3V2luZG93ID0gbmV3V2luZG93OwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiR29Ub0UiOgogICAgICAgICAgY29uc3QgdGFyZ2V0ID0gYWN0aW9uLmdldCgiVCIpOwogICAgICAgICAgbGV0IGF0dGFjaG1lbnQ7CiAgICAgICAgICBpZiAoZG9jQXR0YWNobWVudHMgJiYgdGFyZ2V0IGluc3RhbmNlb2YgRGljdCkgewogICAgICAgICAgICBjb25zdCByZWxhdGlvbnNoaXAgPSB0YXJnZXQuZ2V0KCJSIik7CiAgICAgICAgICAgIGNvbnN0IG5hbWUgPSB0YXJnZXQuZ2V0KCJOIik7CiAgICAgICAgICAgIGlmIChpc05hbWUocmVsYXRpb25zaGlwLCAiQyIpICYmIHR5cGVvZiBuYW1lID09PSAic3RyaW5nIikgewogICAgICAgICAgICAgIGF0dGFjaG1lbnQgPSBkb2NBdHRhY2htZW50c1tzdHJpbmdUb1BERlN0cmluZyhuYW1lLCB0cnVlKV07CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChhdHRhY2htZW50KSB7CiAgICAgICAgICAgIHJlc3VsdE9iai5hdHRhY2htZW50ID0gYXR0YWNobWVudDsKICAgICAgICAgICAgY29uc3QgYXR0YWNobWVudERlc3QgPSBmZXRjaFJlbW90ZURlc3QoYWN0aW9uKTsKICAgICAgICAgICAgaWYgKGF0dGFjaG1lbnREZXN0KSB7CiAgICAgICAgICAgICAgcmVzdWx0T2JqLmF0dGFjaG1lbnREZXN0ID0gYXR0YWNobWVudERlc3Q7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHdhcm4oYHBhcnNlRGVzdERpY3Rpb25hcnkgLSB1bmltcGxlbWVudGVkICJHb1RvRSIgYWN0aW9uLmApOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiTmFtZWQiOgogICAgICAgICAgY29uc3QgbmFtZWRBY3Rpb24gPSBhY3Rpb24uZ2V0KCJOIik7CiAgICAgICAgICBpZiAobmFtZWRBY3Rpb24gaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgICAgIHJlc3VsdE9iai5hY3Rpb24gPSBuYW1lZEFjdGlvbi5uYW1lOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiU2V0T0NHU3RhdGUiOgogICAgICAgICAgY29uc3Qgc3RhdGUgPSBhY3Rpb24uZ2V0KCJTdGF0ZSIpOwogICAgICAgICAgY29uc3QgcHJlc2VydmVSQiA9IGFjdGlvbi5nZXQoIlByZXNlcnZlUkIiKTsKICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShzdGF0ZSkgfHwgc3RhdGUubGVuZ3RoID09PSAwKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY29uc3Qgc3RhdGVBcnIgPSBbXTsKICAgICAgICAgIGZvciAoY29uc3QgZWxlbSBvZiBzdGF0ZSkgewogICAgICAgICAgICBpZiAoZWxlbSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICAgICAgICBzd2l0Y2ggKGVsZW0ubmFtZSkgewogICAgICAgICAgICAgICAgY2FzZSAiT04iOgogICAgICAgICAgICAgICAgY2FzZSAiT0ZGIjoKICAgICAgICAgICAgICAgIGNhc2UgIlRvZ2dsZSI6CiAgICAgICAgICAgICAgICAgIHN0YXRlQXJyLnB1c2goZWxlbS5uYW1lKTsKICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICB9IGVsc2UgaWYgKGVsZW0gaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICAgICAgICBzdGF0ZUFyci5wdXNoKGVsZW0udG9TdHJpbmcoKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChzdGF0ZUFyci5sZW5ndGggIT09IHN0YXRlLmxlbmd0aCkgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIHJlc3VsdE9iai5zZXRPQ0dTdGF0ZSA9IHsKICAgICAgICAgICAgc3RhdGU6IHN0YXRlQXJyLAogICAgICAgICAgICBwcmVzZXJ2ZVJCOiB0eXBlb2YgcHJlc2VydmVSQiA9PT0gImJvb2xlYW4iID8gcHJlc2VydmVSQiA6IHRydWUKICAgICAgICAgIH07CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJKYXZhU2NyaXB0IjoKICAgICAgICAgIGNvbnN0IGpzQWN0aW9uID0gYWN0aW9uLmdldCgiSlMiKTsKICAgICAgICAgIGxldCBqczsKICAgICAgICAgIGlmIChqc0FjdGlvbiBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgICAgICAganMgPSBqc0FjdGlvbi5nZXRTdHJpbmcoKTsKICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGpzQWN0aW9uID09PSAic3RyaW5nIikgewogICAgICAgICAgICBqcyA9IGpzQWN0aW9uOwogICAgICAgICAgfQogICAgICAgICAgY29uc3QganNVUkwgPSBqcyAmJiByZWNvdmVySnNVUkwoc3RyaW5nVG9QREZTdHJpbmcoanMsIHRydWUpKTsKICAgICAgICAgIGlmIChqc1VSTCkgewogICAgICAgICAgICB1cmwgPSBqc1VSTC51cmw7CiAgICAgICAgICAgIHJlc3VsdE9iai5uZXdXaW5kb3cgPSBqc1VSTC5uZXdXaW5kb3c7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICBpZiAoYWN0aW9uTmFtZSA9PT0gIkphdmFTY3JpcHQiIHx8IGFjdGlvbk5hbWUgPT09ICJTdWJtaXRGb3JtIikgewogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICAgIHdhcm4oYHBhcnNlRGVzdERpY3Rpb25hcnkgLSB1bnN1cHBvcnRlZCBhY3Rpb246ICIke2FjdGlvbk5hbWV9Ii5gKTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9IGVsc2UgaWYgKGRlc3REaWN0LmhhcygiRGVzdCIpKSB7CiAgICAgIGRlc3QgPSBkZXN0RGljdC5nZXQoIkRlc3QiKTsKICAgIH0KICAgIGlmICh0eXBlb2YgdXJsID09PSAic3RyaW5nIikgewogICAgICBjb25zdCBhYnNvbHV0ZVVybCA9IGNyZWF0ZVZhbGlkQWJzb2x1dGVVcmwodXJsLCBkb2NCYXNlVXJsLCB7CiAgICAgICAgYWRkRGVmYXVsdFByb3RvY29sOiB0cnVlLAogICAgICAgIHRyeUNvbnZlcnRFbmNvZGluZzogdHJ1ZQogICAgICB9KTsKICAgICAgaWYgKGFic29sdXRlVXJsKSB7CiAgICAgICAgcmVzdWx0T2JqLnVybCA9IGFic29sdXRlVXJsLmhyZWY7CiAgICAgIH0KICAgICAgcmVzdWx0T2JqLnVuc2FmZVVybCA9IHVybDsKICAgIH0KICAgIGlmIChkZXN0KSB7CiAgICAgIGlmIChkZXN0IGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgIGRlc3QgPSBkZXN0Lm5hbWU7CiAgICAgIH0KICAgICAgaWYgKHR5cGVvZiBkZXN0ID09PSAic3RyaW5nIikgewogICAgICAgIHJlc3VsdE9iai5kZXN0ID0gc3RyaW5nVG9QREZTdHJpbmcoZGVzdCwgdHJ1ZSk7CiAgICAgIH0gZWxzZSBpZiAoaXNWYWxpZEV4cGxpY2l0RGVzdChkZXN0KSkgewogICAgICAgIHJlc3VsdE9iai5kZXN0ID0gZGVzdDsKICAgICAgfQogICAgfQogIH0KfQoKOy8vIC4vc3JjL2NvcmUvb2JqZWN0X2xvYWRlci5qcwoKCgoKCmZ1bmN0aW9uIG1heUhhdmVDaGlsZHJlbih2YWx1ZSkgewogIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFJlZiB8fCB2YWx1ZSBpbnN0YW5jZW9mIERpY3QgfHwgdmFsdWUgaW5zdGFuY2VvZiBCYXNlU3RyZWFtIHx8IEFycmF5LmlzQXJyYXkodmFsdWUpOwp9CmZ1bmN0aW9uIGFkZENoaWxkcmVuKG5vZGUsIG5vZGVzVG9WaXNpdCkgewogIGlmIChub2RlIGluc3RhbmNlb2YgRGljdCkgewogICAgbm9kZSA9IG5vZGUuZ2V0UmF3VmFsdWVzKCk7CiAgfSBlbHNlIGlmIChub2RlIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgbm9kZSA9IG5vZGUuZGljdC5nZXRSYXdWYWx1ZXMoKTsKICB9IGVsc2UgaWYgKCFBcnJheS5pc0FycmF5KG5vZGUpKSB7CiAgICByZXR1cm47CiAgfQogIGZvciAoY29uc3QgcmF3VmFsdWUgb2Ygbm9kZSkgewogICAgaWYgKG1heUhhdmVDaGlsZHJlbihyYXdWYWx1ZSkpIHsKICAgICAgbm9kZXNUb1Zpc2l0LnB1c2gocmF3VmFsdWUpOwogICAgfQogIH0KfQpjbGFzcyBPYmplY3RMb2FkZXIgewogIHJlZlNldCA9IG5ldyBSZWZTZXQoKTsKICBjb25zdHJ1Y3RvcihkaWN0LCBrZXlzLCB4cmVmKSB7CiAgICB0aGlzLmRpY3QgPSBkaWN0OwogICAgdGhpcy5rZXlzID0ga2V5czsKICAgIHRoaXMueHJlZiA9IHhyZWY7CiAgfQogIGFzeW5jIGxvYWQoKSB7CiAgICBjb25zdCB7CiAgICAgIGtleXMsCiAgICAgIGRpY3QKICAgIH0gPSB0aGlzOwogICAgY29uc3Qgbm9kZXNUb1Zpc2l0ID0gW107CiAgICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7CiAgICAgIGNvbnN0IHJhd1ZhbHVlID0gZGljdC5nZXRSYXcoa2V5KTsKICAgICAgaWYgKHJhd1ZhbHVlICE9PSB1bmRlZmluZWQpIHsKICAgICAgICBub2Rlc1RvVmlzaXQucHVzaChyYXdWYWx1ZSk7CiAgICAgIH0KICAgIH0KICAgIGF3YWl0IHRoaXMuI3dhbGsobm9kZXNUb1Zpc2l0KTsKICAgIHRoaXMucmVmU2V0ID0gbnVsbDsKICB9CiAgYXN5bmMgI3dhbGsobm9kZXNUb1Zpc2l0KSB7CiAgICBjb25zdCBub2Rlc1RvUmV2aXNpdCA9IFtdOwogICAgY29uc3QgcGVuZGluZ1JlcXVlc3RzID0gW107CiAgICB3aGlsZSAobm9kZXNUb1Zpc2l0Lmxlbmd0aCkgewogICAgICBsZXQgY3VycmVudE5vZGUgPSBub2Rlc1RvVmlzaXQucG9wKCk7CiAgICAgIGlmIChjdXJyZW50Tm9kZSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgIGlmICh0aGlzLnJlZlNldC5oYXMoY3VycmVudE5vZGUpKSB7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgdHJ5IHsKICAgICAgICAgIHRoaXMucmVmU2V0LnB1dChjdXJyZW50Tm9kZSk7CiAgICAgICAgICBjdXJyZW50Tm9kZSA9IHRoaXMueHJlZi5mZXRjaChjdXJyZW50Tm9kZSk7CiAgICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICAgIGlmICghKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pKSB7CiAgICAgICAgICAgIHdhcm4oYE9iamVjdExvYWRlci4jd2FsayAtIHJlcXVlc3RpbmcgYWxsIGRhdGE6ICIke2V4fSIuYCk7CiAgICAgICAgICAgIGF3YWl0IHRoaXMueHJlZi5zdHJlYW0ubWFuYWdlci5yZXF1ZXN0QWxsQ2h1bmtzKCk7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KICAgICAgICAgIG5vZGVzVG9SZXZpc2l0LnB1c2goY3VycmVudE5vZGUpOwogICAgICAgICAgcGVuZGluZ1JlcXVlc3RzLnB1c2goewogICAgICAgICAgICBiZWdpbjogZXguYmVnaW4sCiAgICAgICAgICAgIGVuZDogZXguZW5kCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGN1cnJlbnROb2RlIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICAgIGNvbnN0IGJhc2VTdHJlYW1zID0gY3VycmVudE5vZGUuZ2V0QmFzZVN0cmVhbXMoKTsKICAgICAgICBpZiAoYmFzZVN0cmVhbXMpIHsKICAgICAgICAgIGxldCBmb3VuZE1pc3NpbmdEYXRhID0gZmFsc2U7CiAgICAgICAgICBmb3IgKGNvbnN0IHN0cmVhbSBvZiBiYXNlU3RyZWFtcykgewogICAgICAgICAgICBpZiAoc3RyZWFtLmlzRGF0YUxvYWRlZCkgewogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGZvdW5kTWlzc2luZ0RhdGEgPSB0cnVlOwogICAgICAgICAgICBwZW5kaW5nUmVxdWVzdHMucHVzaCh7CiAgICAgICAgICAgICAgYmVnaW46IHN0cmVhbS5zdGFydCwKICAgICAgICAgICAgICBlbmQ6IHN0cmVhbS5lbmQKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoZm91bmRNaXNzaW5nRGF0YSkgewogICAgICAgICAgICBub2Rlc1RvUmV2aXNpdC5wdXNoKGN1cnJlbnROb2RlKTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgYWRkQ2hpbGRyZW4oY3VycmVudE5vZGUsIG5vZGVzVG9WaXNpdCk7CiAgICB9CiAgICBpZiAocGVuZGluZ1JlcXVlc3RzLmxlbmd0aCkgewogICAgICBhd2FpdCB0aGlzLnhyZWYuc3RyZWFtLm1hbmFnZXIucmVxdWVzdFJhbmdlcyhwZW5kaW5nUmVxdWVzdHMpOwogICAgICBmb3IgKGNvbnN0IG5vZGUgb2Ygbm9kZXNUb1JldmlzaXQpIHsKICAgICAgICBpZiAobm9kZSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgdGhpcy5yZWZTZXQucmVtb3ZlKG5vZGUpOwogICAgICAgIH0KICAgICAgfQogICAgICBhd2FpdCB0aGlzLiN3YWxrKG5vZGVzVG9SZXZpc2l0KTsKICAgIH0KICB9CiAgc3RhdGljIGFzeW5jIGxvYWQob2JqLCBrZXlzLCB4cmVmKSB7CiAgICBpZiAoeHJlZi5zdHJlYW0uaXNEYXRhTG9hZGVkKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IG9iakxvYWRlciA9IG5ldyBPYmplY3RMb2FkZXIob2JqLCBrZXlzLCB4cmVmKTsKICAgIGF3YWl0IG9iakxvYWRlci5sb2FkKCk7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEvc3ltYm9sX3V0aWxzLmpzCmNvbnN0ICRhY2NlcHRXaGl0ZXNwYWNlID0gU3ltYm9sKCk7CmNvbnN0ICRhZGRIVE1MID0gU3ltYm9sKCk7CmNvbnN0ICRhcHBlbmRDaGlsZCA9IFN5bWJvbCgpOwpjb25zdCAkY2hpbGRyZW5Ub0hUTUwgPSBTeW1ib2woKTsKY29uc3QgJGNsZWFuID0gU3ltYm9sKCk7CmNvbnN0ICRjbGVhblBhZ2UgPSBTeW1ib2woKTsKY29uc3QgJGNsZWFudXAgPSBTeW1ib2woKTsKY29uc3QgJGNsb25lID0gU3ltYm9sKCk7CmNvbnN0ICRjb25zdW1lZCA9IFN5bWJvbCgpOwpjb25zdCAkY29udGVudCA9IFN5bWJvbCgiY29udGVudCIpOwpjb25zdCAkZGF0YSA9IFN5bWJvbCgiZGF0YSIpOwpjb25zdCAkZHVtcCA9IFN5bWJvbCgpOwpjb25zdCAkZXh0cmEgPSBTeW1ib2woImV4dHJhIik7CmNvbnN0ICRmaW5hbGl6ZSA9IFN5bWJvbCgpOwpjb25zdCAkZmx1c2hIVE1MID0gU3ltYm9sKCk7CmNvbnN0ICRnZXRBdHRyaWJ1dGVJdCA9IFN5bWJvbCgpOwpjb25zdCAkZ2V0QXR0cmlidXRlcyA9IFN5bWJvbCgpOwpjb25zdCAkZ2V0QXZhaWxhYmxlU3BhY2UgPSBTeW1ib2woKTsKY29uc3QgJGdldENoaWxkcmVuQnlDbGFzcyA9IFN5bWJvbCgpOwpjb25zdCAkZ2V0Q2hpbGRyZW5CeU5hbWUgPSBTeW1ib2woKTsKY29uc3QgJGdldENoaWxkcmVuQnlOYW1lSXQgPSBTeW1ib2woKTsKY29uc3QgJGdldERhdGFWYWx1ZSA9IFN5bWJvbCgpOwpjb25zdCAkZ2V0RXh0cmEgPSBTeW1ib2woKTsKY29uc3QgJGdldFJlYWxDaGlsZHJlbkJ5TmFtZUl0ID0gU3ltYm9sKCk7CmNvbnN0ICRnZXRDaGlsZHJlbiA9IFN5bWJvbCgpOwpjb25zdCAkZ2V0Q29udGFpbmVkQ2hpbGRyZW4gPSBTeW1ib2woKTsKY29uc3QgJGdldE5leHRQYWdlID0gU3ltYm9sKCk7CmNvbnN0ICRnZXRTdWJmb3JtUGFyZW50ID0gU3ltYm9sKCk7CmNvbnN0ICRnZXRQYXJlbnQgPSBTeW1ib2woKTsKY29uc3QgJGdldFRlbXBsYXRlUm9vdCA9IFN5bWJvbCgpOwpjb25zdCAkZ2xvYmFsRGF0YSA9IFN5bWJvbCgpOwpjb25zdCAkaGFzU2V0dGFibGVWYWx1ZSA9IFN5bWJvbCgpOwpjb25zdCAkaWRzID0gU3ltYm9sKCk7CmNvbnN0ICRpbmRleE9mID0gU3ltYm9sKCk7CmNvbnN0ICRpbnNlcnRBdCA9IFN5bWJvbCgpOwpjb25zdCAkaXNDREFUQVhtbCA9IFN5bWJvbCgpOwpjb25zdCAkaXNCaW5kYWJsZSA9IFN5bWJvbCgpOwpjb25zdCAkaXNEYXRhVmFsdWUgPSBTeW1ib2woKTsKY29uc3QgJGlzRGVzY2VuZGVudCA9IFN5bWJvbCgpOwpjb25zdCAkaXNOc0Fnbm9zdGljID0gU3ltYm9sKCk7CmNvbnN0ICRpc1NwbGl0dGFibGUgPSBTeW1ib2woKTsKY29uc3QgJGlzVGhlcmVNb3JlV2lkdGggPSBTeW1ib2woKTsKY29uc3QgJGlzVHJhbnNwYXJlbnQgPSBTeW1ib2woKTsKY29uc3QgJGlzVXNhYmxlID0gU3ltYm9sKCk7CmNvbnN0ICRsYXN0QXR0cmlidXRlID0gU3ltYm9sKCk7CmNvbnN0ICRuYW1lc3BhY2VJZCA9IFN5bWJvbCgibmFtZXNwYWNlSWQiKTsKY29uc3QgJG5vZGVOYW1lID0gU3ltYm9sKCJub2RlTmFtZSIpOwpjb25zdCAkbnNBdHRyaWJ1dGVzID0gU3ltYm9sKCk7CmNvbnN0ICRvbkNoaWxkID0gU3ltYm9sKCk7CmNvbnN0ICRvbkNoaWxkQ2hlY2sgPSBTeW1ib2woKTsKY29uc3QgJG9uVGV4dCA9IFN5bWJvbCgpOwpjb25zdCAkcHVzaEdseXBocyA9IFN5bWJvbCgpOwpjb25zdCAkcG9wUGFyYSA9IFN5bWJvbCgpOwpjb25zdCAkcHVzaFBhcmEgPSBTeW1ib2woKTsKY29uc3QgJHJlbW92ZUNoaWxkID0gU3ltYm9sKCk7CmNvbnN0ICRyb290ID0gU3ltYm9sKCJyb290Iik7CmNvbnN0ICRyZXNvbHZlUHJvdG90eXBlcyA9IFN5bWJvbCgpOwpjb25zdCAkc2VhcmNoTm9kZSA9IFN5bWJvbCgpOwpjb25zdCAkc2V0SWQgPSBTeW1ib2woKTsKY29uc3QgJHNldFNldEF0dHJpYnV0ZXMgPSBTeW1ib2woKTsKY29uc3QgJHNldFZhbHVlID0gU3ltYm9sKCk7CmNvbnN0ICR0YWJJbmRleCA9IFN5bWJvbCgpOwpjb25zdCAkdGV4dCA9IFN5bWJvbCgpOwpjb25zdCAkdG9QYWdlcyA9IFN5bWJvbCgpOwpjb25zdCAkdG9IVE1MID0gU3ltYm9sKCk7CmNvbnN0ICR0b1N0cmluZyA9IFN5bWJvbCgpOwpjb25zdCAkdG9TdHlsZSA9IFN5bWJvbCgpOwpjb25zdCAkdWlkID0gU3ltYm9sKCJ1aWQiKTsKCi8vIEVYVEVSTkFMIE1PRFVMRTogLi9ub2RlX21vZHVsZXMvY29yZS1qcy9tb2R1bGVzL2VzLml0ZXJhdG9yLmZsYXQtbWFwLmpzCnZhciBlc19pdGVyYXRvcl9mbGF0X21hcCA9IF9fd2VicGFja19yZXF1aXJlX18oNTMxKTsKOy8vIC4vc3JjL2NvcmUveGZhL25hbWVzcGFjZXMuanMKY29uc3QgJGJ1aWxkWEZBT2JqZWN0ID0gU3ltYm9sKCk7CmNvbnN0IE5hbWVzcGFjZUlkcyA9IHsKICBjb25maWc6IHsKICAgIGlkOiAwLAogICAgY2hlY2s6IG5zID0+IG5zLnN0YXJ0c1dpdGgoImh0dHA6Ly93d3cueGZhLm9yZy9zY2hlbWEveGNpLyIpCiAgfSwKICBjb25uZWN0aW9uU2V0OiB7CiAgICBpZDogMSwKICAgIGNoZWNrOiBucyA9PiBucy5zdGFydHNXaXRoKCJodHRwOi8vd3d3LnhmYS5vcmcvc2NoZW1hL3hmYS1jb25uZWN0aW9uLXNldC8iKQogIH0sCiAgZGF0YXNldHM6IHsKICAgIGlkOiAyLAogICAgY2hlY2s6IG5zID0+IG5zLnN0YXJ0c1dpdGgoImh0dHA6Ly93d3cueGZhLm9yZy9zY2hlbWEveGZhLWRhdGEvIikKICB9LAogIGZvcm06IHsKICAgIGlkOiAzLAogICAgY2hlY2s6IG5zID0+IG5zLnN0YXJ0c1dpdGgoImh0dHA6Ly93d3cueGZhLm9yZy9zY2hlbWEveGZhLWZvcm0vIikKICB9LAogIGxvY2FsZVNldDogewogICAgaWQ6IDQsCiAgICBjaGVjazogbnMgPT4gbnMuc3RhcnRzV2l0aCgiaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94ZmEtbG9jYWxlLXNldC8iKQogIH0sCiAgcGRmOiB7CiAgICBpZDogNSwKICAgIGNoZWNrOiBucyA9PiBucyA9PT0gImh0dHA6Ly9ucy5hZG9iZS5jb20veGRwL3BkZi8iCiAgfSwKICBzaWduYXR1cmU6IHsKICAgIGlkOiA2LAogICAgY2hlY2s6IG5zID0+IG5zID09PSAiaHR0cDovL3d3dy53My5vcmcvMjAwMC8wOS94bWxkc2lnIyIKICB9LAogIHNvdXJjZVNldDogewogICAgaWQ6IDcsCiAgICBjaGVjazogbnMgPT4gbnMuc3RhcnRzV2l0aCgiaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94ZmEtc291cmNlLXNldC8iKQogIH0sCiAgc3R5bGVzaGVldDogewogICAgaWQ6IDgsCiAgICBjaGVjazogbnMgPT4gbnMgPT09ICJodHRwOi8vd3d3LnczLm9yZy8xOTk5L1hTTC9UcmFuc2Zvcm0iCiAgfSwKICB0ZW1wbGF0ZTogewogICAgaWQ6IDksCiAgICBjaGVjazogbnMgPT4gbnMuc3RhcnRzV2l0aCgiaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94ZmEtdGVtcGxhdGUvIikKICB9LAogIHhkYzogewogICAgaWQ6IDEwLAogICAgY2hlY2s6IG5zID0+IG5zLnN0YXJ0c1dpdGgoImh0dHA6Ly93d3cueGZhLm9yZy9zY2hlbWEveGRjLyIpCiAgfSwKICB4ZHA6IHsKICAgIGlkOiAxMSwKICAgIGNoZWNrOiBucyA9PiBucyA9PT0gImh0dHA6Ly9ucy5hZG9iZS5jb20veGRwLyIKICB9LAogIHhmZGY6IHsKICAgIGlkOiAxMiwKICAgIGNoZWNrOiBucyA9PiBucyA9PT0gImh0dHA6Ly9ucy5hZG9iZS5jb20veGZkZi8iCiAgfSwKICB4aHRtbDogewogICAgaWQ6IDEzLAogICAgY2hlY2s6IG5zID0+IG5zID09PSAiaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIKICB9LAogIHhtcG1ldGE6IHsKICAgIGlkOiAxNCwKICAgIGNoZWNrOiBucyA9PiBucyA9PT0gImh0dHA6Ly9ucy5hZG9iZS5jb20veG1wbWV0YS8iCiAgfQp9OwoKOy8vIC4vc3JjL2NvcmUveGZhL3V0aWxzLmpzCgoKCgoKY29uc3QgZGltQ29udmVydGVycyA9IHsKICBwdDogeCA9PiB4LAogIGNtOiB4ID0+IHggLyAyLjU0ICogNzIsCiAgbW06IHggPT4geCAvICgxMCAqIDIuNTQpICogNzIsCiAgaW46IHggPT4geCAqIDcyLAogIHB4OiB4ID0+IHgKfTsKY29uc3QgbWVhc3VyZW1lbnRQYXR0ZXJuID0gLyhbKy1dP1xkK1wuP1xkKikoLiopLzsKZnVuY3Rpb24gc3RyaXBRdW90ZXMoc3RyKSB7CiAgaWYgKHN0ci5zdGFydHNXaXRoKCInIikgfHwgc3RyLnN0YXJ0c1dpdGgoJyInKSkgewogICAgcmV0dXJuIHN0ci5zbGljZSgxLCAtMSk7CiAgfQogIHJldHVybiBzdHI7Cn0KZnVuY3Rpb24gZ2V0SW50ZWdlcih7CiAgZGF0YSwKICBkZWZhdWx0VmFsdWUsCiAgdmFsaWRhdGUKfSkgewogIGlmICghZGF0YSkgewogICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTsKICB9CiAgZGF0YSA9IGRhdGEudHJpbSgpOwogIGNvbnN0IG4gPSBwYXJzZUludChkYXRhLCAxMCk7CiAgaWYgKCFpc05hTihuKSAmJiB2YWxpZGF0ZShuKSkgewogICAgcmV0dXJuIG47CiAgfQogIHJldHVybiBkZWZhdWx0VmFsdWU7Cn0KZnVuY3Rpb24gZ2V0RmxvYXQoewogIGRhdGEsCiAgZGVmYXVsdFZhbHVlLAogIHZhbGlkYXRlCn0pIHsKICBpZiAoIWRhdGEpIHsKICAgIHJldHVybiBkZWZhdWx0VmFsdWU7CiAgfQogIGRhdGEgPSBkYXRhLnRyaW0oKTsKICBjb25zdCBuID0gcGFyc2VGbG9hdChkYXRhKTsKICBpZiAoIWlzTmFOKG4pICYmIHZhbGlkYXRlKG4pKSB7CiAgICByZXR1cm4gbjsKICB9CiAgcmV0dXJuIGRlZmF1bHRWYWx1ZTsKfQpmdW5jdGlvbiBnZXRLZXl3b3JkKHsKICBkYXRhLAogIGRlZmF1bHRWYWx1ZSwKICB2YWxpZGF0ZQp9KSB7CiAgaWYgKCFkYXRhKSB7CiAgICByZXR1cm4gZGVmYXVsdFZhbHVlOwogIH0KICBkYXRhID0gZGF0YS50cmltKCk7CiAgaWYgKHZhbGlkYXRlKGRhdGEpKSB7CiAgICByZXR1cm4gZGF0YTsKICB9CiAgcmV0dXJuIGRlZmF1bHRWYWx1ZTsKfQpmdW5jdGlvbiBnZXRTdHJpbmdPcHRpb24oZGF0YSwgb3B0aW9ucykgewogIHJldHVybiBnZXRLZXl3b3JkKHsKICAgIGRhdGEsCiAgICBkZWZhdWx0VmFsdWU6IG9wdGlvbnNbMF0sCiAgICB2YWxpZGF0ZTogayA9PiBvcHRpb25zLmluY2x1ZGVzKGspCiAgfSk7Cn0KZnVuY3Rpb24gZ2V0TWVhc3VyZW1lbnQoc3RyLCBkZWYgPSAiMCIpIHsKICBkZWYgfHw9ICIwIjsKICBpZiAoIXN0cikgewogICAgcmV0dXJuIGdldE1lYXN1cmVtZW50KGRlZik7CiAgfQogIGNvbnN0IG1hdGNoID0gc3RyLnRyaW0oKS5tYXRjaChtZWFzdXJlbWVudFBhdHRlcm4pOwogIGlmICghbWF0Y2gpIHsKICAgIHJldHVybiBnZXRNZWFzdXJlbWVudChkZWYpOwogIH0KICBjb25zdCBbLCB2YWx1ZVN0ciwgdW5pdF0gPSBtYXRjaDsKICBjb25zdCB2YWx1ZSA9IHBhcnNlRmxvYXQodmFsdWVTdHIpOwogIGlmIChpc05hTih2YWx1ZSkpIHsKICAgIHJldHVybiBnZXRNZWFzdXJlbWVudChkZWYpOwogIH0KICBpZiAodmFsdWUgPT09IDApIHsKICAgIHJldHVybiAwOwogIH0KICBjb25zdCBjb252ID0gZGltQ29udmVydGVyc1t1bml0XTsKICBpZiAoY29udikgewogICAgcmV0dXJuIGNvbnYodmFsdWUpOwogIH0KICByZXR1cm4gdmFsdWU7Cn0KZnVuY3Rpb24gZ2V0UmF0aW8oZGF0YSkgewogIGlmICghZGF0YSkgewogICAgcmV0dXJuIHsKICAgICAgbnVtOiAxLAogICAgICBkZW46IDEKICAgIH07CiAgfQogIGNvbnN0IHJhdGlvID0gZGF0YS5zcGxpdCgiOiIsIDIpLm1hcCh4ID0+IHBhcnNlRmxvYXQoeC50cmltKCkpKS5maWx0ZXIoeCA9PiAhaXNOYU4oeCkpOwogIGlmIChyYXRpby5sZW5ndGggPT09IDEpIHsKICAgIHJhdGlvLnB1c2goMSk7CiAgfQogIGlmIChyYXRpby5sZW5ndGggPT09IDApIHsKICAgIHJldHVybiB7CiAgICAgIG51bTogMSwKICAgICAgZGVuOiAxCiAgICB9OwogIH0KICBjb25zdCBbbnVtLCBkZW5dID0gcmF0aW87CiAgcmV0dXJuIHsKICAgIG51bSwKICAgIGRlbgogIH07Cn0KZnVuY3Rpb24gZ2V0UmVsZXZhbnQoZGF0YSkgewogIGlmICghZGF0YSkgewogICAgcmV0dXJuIFtdOwogIH0KICByZXR1cm4gZGF0YS50cmltKCkuc3BsaXQoL1xzKy8pLm1hcChlID0+ICh7CiAgICBleGNsdWRlZDogZVswXSA9PT0gIi0iLAogICAgdmlld25hbWU6IGUuc3Vic3RyaW5nKDEpCiAgfSkpOwp9CmZ1bmN0aW9uIGdldENvbG9yKGRhdGEsIGRlZiA9IFswLCAwLCAwXSkgewogIGxldCBbciwgZywgYl0gPSBkZWY7CiAgaWYgKCFkYXRhKSB7CiAgICByZXR1cm4gewogICAgICByLAogICAgICBnLAogICAgICBiCiAgICB9OwogIH0KICBjb25zdCBjb2xvciA9IGRhdGEuc3BsaXQoIiwiLCAzKS5tYXAoYyA9PiBNYXRoQ2xhbXAocGFyc2VJbnQoYy50cmltKCksIDEwKSwgMCwgMjU1KSkubWFwKGMgPT4gaXNOYU4oYykgPyAwIDogYyk7CiAgaWYgKGNvbG9yLmxlbmd0aCA8IDMpIHsKICAgIHJldHVybiB7CiAgICAgIHIsCiAgICAgIGcsCiAgICAgIGIKICAgIH07CiAgfQogIFtyLCBnLCBiXSA9IGNvbG9yOwogIHJldHVybiB7CiAgICByLAogICAgZywKICAgIGIKICB9Owp9CmZ1bmN0aW9uIGdldEJCb3goZGF0YSkgewogIGNvbnN0IGRlZiA9IC0xOwogIGlmICghZGF0YSkgewogICAgcmV0dXJuIHsKICAgICAgeDogZGVmLAogICAgICB5OiBkZWYsCiAgICAgIHdpZHRoOiBkZWYsCiAgICAgIGhlaWdodDogZGVmCiAgICB9OwogIH0KICBjb25zdCBiYm94ID0gZGF0YS5zcGxpdCgiLCIsIDQpLm1hcChtID0+IGdldE1lYXN1cmVtZW50KG0udHJpbSgpLCAiLTEiKSk7CiAgaWYgKGJib3gubGVuZ3RoIDwgNCB8fCBiYm94WzJdIDwgMCB8fCBiYm94WzNdIDwgMCkgewogICAgcmV0dXJuIHsKICAgICAgeDogZGVmLAogICAgICB5OiBkZWYsCiAgICAgIHdpZHRoOiBkZWYsCiAgICAgIGhlaWdodDogZGVmCiAgICB9OwogIH0KICBjb25zdCBbeCwgeSwgd2lkdGgsIGhlaWdodF0gPSBiYm94OwogIHJldHVybiB7CiAgICB4LAogICAgeSwKICAgIHdpZHRoLAogICAgaGVpZ2h0CiAgfTsKfQpjbGFzcyBIVE1MUmVzdWx0IHsKICBzdGF0aWMgZ2V0IEZBSUxVUkUoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJGQUlMVVJFIiwgbmV3IEhUTUxSZXN1bHQoZmFsc2UsIG51bGwsIG51bGwsIG51bGwpKTsKICB9CiAgc3RhdGljIGdldCBFTVBUWSgpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgIkVNUFRZIiwgbmV3IEhUTUxSZXN1bHQodHJ1ZSwgbnVsbCwgbnVsbCwgbnVsbCkpOwogIH0KICBjb25zdHJ1Y3RvcihzdWNjZXNzLCBodG1sLCBiYm94LCBicmVha05vZGUpIHsKICAgIHRoaXMuc3VjY2VzcyA9IHN1Y2Nlc3M7CiAgICB0aGlzLmh0bWwgPSBodG1sOwogICAgdGhpcy5iYm94ID0gYmJveDsKICAgIHRoaXMuYnJlYWtOb2RlID0gYnJlYWtOb2RlOwogIH0KICBpc0JyZWFrKCkgewogICAgcmV0dXJuICEhdGhpcy5icmVha05vZGU7CiAgfQogIHN0YXRpYyBicmVha05vZGUobm9kZSkgewogICAgcmV0dXJuIG5ldyBIVE1MUmVzdWx0KGZhbHNlLCBudWxsLCBudWxsLCBub2RlKTsKICB9CiAgc3RhdGljIHN1Y2Nlc3MoaHRtbCwgYmJveCA9IG51bGwpIHsKICAgIHJldHVybiBuZXcgSFRNTFJlc3VsdCh0cnVlLCBodG1sLCBiYm94LCBudWxsKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3hmYS9mb250cy5qcwoKCgoKCgoKCgoKCgoKY2xhc3MgRm9udEZpbmRlciB7CiAgY29uc3RydWN0b3IocGRmRm9udHMpIHsKICAgIHRoaXMuZm9udHMgPSBuZXcgTWFwKCk7CiAgICB0aGlzLmNhY2hlID0gbmV3IE1hcCgpOwogICAgdGhpcy53YXJuZWQgPSBuZXcgU2V0KCk7CiAgICB0aGlzLmRlZmF1bHRGb250ID0gbnVsbDsKICAgIHRoaXMuYWRkKHBkZkZvbnRzKTsKICB9CiAgYWRkKHBkZkZvbnRzLCByZWFsbHlNaXNzaW5nRm9udHMgPSBudWxsKSB7CiAgICBmb3IgKGNvbnN0IHBkZkZvbnQgb2YgcGRmRm9udHMpIHsKICAgICAgdGhpcy5hZGRQZGZGb250KHBkZkZvbnQpOwogICAgfQogICAgZm9yIChjb25zdCBwZGZGb250IG9mIHRoaXMuZm9udHMudmFsdWVzKCkpIHsKICAgICAgaWYgKCFwZGZGb250LnJlZ3VsYXIpIHsKICAgICAgICBwZGZGb250LnJlZ3VsYXIgPSBwZGZGb250Lml0YWxpYyB8fCBwZGZGb250LmJvbGQgfHwgcGRmRm9udC5ib2xkaXRhbGljOwogICAgICB9CiAgICB9CiAgICBpZiAoIXJlYWxseU1pc3NpbmdGb250cyB8fCByZWFsbHlNaXNzaW5nRm9udHMuc2l6ZSA9PT0gMCkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBteXJpYWQgPSB0aGlzLmZvbnRzLmdldCgiUGRmSlMtRmFsbGJhY2stUGRmSlMtWEZBIik7CiAgICBmb3IgKGNvbnN0IG1pc3Npbmcgb2YgcmVhbGx5TWlzc2luZ0ZvbnRzKSB7CiAgICAgIHRoaXMuZm9udHMuc2V0KG1pc3NpbmcsIG15cmlhZCk7CiAgICB9CiAgfQogIGFkZFBkZkZvbnQocGRmRm9udCkgewogICAgY29uc3QgY3NzRm9udEluZm8gPSBwZGZGb250LmNzc0ZvbnRJbmZvOwogICAgY29uc3QgbmFtZSA9IGNzc0ZvbnRJbmZvLmZvbnRGYW1pbHk7CiAgICBsZXQgZm9udCA9IHRoaXMuZm9udHMuZ2V0KG5hbWUpOwogICAgaWYgKCFmb250KSB7CiAgICAgIGZvbnQgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICB0aGlzLmZvbnRzLnNldChuYW1lLCBmb250KTsKICAgICAgaWYgKCF0aGlzLmRlZmF1bHRGb250KSB7CiAgICAgICAgdGhpcy5kZWZhdWx0Rm9udCA9IGZvbnQ7CiAgICAgIH0KICAgIH0KICAgIGxldCBwcm9wZXJ0eSA9ICIiOwogICAgY29uc3QgZm9udFdlaWdodCA9IHBhcnNlRmxvYXQoY3NzRm9udEluZm8uZm9udFdlaWdodCk7CiAgICBpZiAocGFyc2VGbG9hdChjc3NGb250SW5mby5pdGFsaWNBbmdsZSkgIT09IDApIHsKICAgICAgcHJvcGVydHkgPSBmb250V2VpZ2h0ID49IDcwMCA/ICJib2xkaXRhbGljIiA6ICJpdGFsaWMiOwogICAgfSBlbHNlIGlmIChmb250V2VpZ2h0ID49IDcwMCkgewogICAgICBwcm9wZXJ0eSA9ICJib2xkIjsKICAgIH0KICAgIGlmICghcHJvcGVydHkpIHsKICAgICAgaWYgKHBkZkZvbnQubmFtZS5pbmNsdWRlcygiQm9sZCIpIHx8IHBkZkZvbnQucHNOYW1lPy5pbmNsdWRlcygiQm9sZCIpKSB7CiAgICAgICAgcHJvcGVydHkgPSAiYm9sZCI7CiAgICAgIH0KICAgICAgaWYgKHBkZkZvbnQubmFtZS5pbmNsdWRlcygiSXRhbGljIikgfHwgcGRmRm9udC5uYW1lLmVuZHNXaXRoKCJJdCIpIHx8IHBkZkZvbnQucHNOYW1lPy5pbmNsdWRlcygiSXRhbGljIikgfHwgcGRmRm9udC5wc05hbWU/LmVuZHNXaXRoKCJJdCIpKSB7CiAgICAgICAgcHJvcGVydHkgKz0gIml0YWxpYyI7CiAgICAgIH0KICAgIH0KICAgIGlmICghcHJvcGVydHkpIHsKICAgICAgcHJvcGVydHkgPSAicmVndWxhciI7CiAgICB9CiAgICBmb250W3Byb3BlcnR5XSA9IHBkZkZvbnQ7CiAgfQogIGdldERlZmF1bHQoKSB7CiAgICByZXR1cm4gdGhpcy5kZWZhdWx0Rm9udDsKICB9CiAgZmluZChmb250TmFtZSwgbXVzdFdhcm4gPSB0cnVlKSB7CiAgICBsZXQgZm9udCA9IHRoaXMuZm9udHMuZ2V0KGZvbnROYW1lKSB8fCB0aGlzLmNhY2hlLmdldChmb250TmFtZSk7CiAgICBpZiAoZm9udCkgewogICAgICByZXR1cm4gZm9udDsKICAgIH0KICAgIGNvbnN0IHBhdHRlcm4gPSAvLHwtfF98IHxib2xkaXRhbGljfGJvbGR8aXRhbGljfHJlZ3VsYXJ8aXQvZ2k7CiAgICBsZXQgbmFtZSA9IGZvbnROYW1lLnJlcGxhY2VBbGwocGF0dGVybiwgIiIpOwogICAgZm9udCA9IHRoaXMuZm9udHMuZ2V0KG5hbWUpOwogICAgaWYgKGZvbnQpIHsKICAgICAgdGhpcy5jYWNoZS5zZXQoZm9udE5hbWUsIGZvbnQpOwogICAgICByZXR1cm4gZm9udDsKICAgIH0KICAgIG5hbWUgPSBuYW1lLnRvTG93ZXJDYXNlKCk7CiAgICBjb25zdCBtYXliZSA9IFtdOwogICAgZm9yIChjb25zdCBbZmFtaWx5LCBwZGZGb250XSBvZiB0aGlzLmZvbnRzLmVudHJpZXMoKSkgewogICAgICBpZiAoZmFtaWx5LnJlcGxhY2VBbGwocGF0dGVybiwgIiIpLnRvTG93ZXJDYXNlKCkuc3RhcnRzV2l0aChuYW1lKSkgewogICAgICAgIG1heWJlLnB1c2gocGRmRm9udCk7CiAgICAgIH0KICAgIH0KICAgIGlmIChtYXliZS5sZW5ndGggPT09IDApIHsKICAgICAgZm9yIChjb25zdCBbLCBwZGZGb250XSBvZiB0aGlzLmZvbnRzLmVudHJpZXMoKSkgewogICAgICAgIGlmIChwZGZGb250LnJlZ3VsYXIubmFtZT8ucmVwbGFjZUFsbChwYXR0ZXJuLCAiIikudG9Mb3dlckNhc2UoKS5zdGFydHNXaXRoKG5hbWUpKSB7CiAgICAgICAgICBtYXliZS5wdXNoKHBkZkZvbnQpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKG1heWJlLmxlbmd0aCA9PT0gMCkgewogICAgICBuYW1lID0gbmFtZS5yZXBsYWNlQWxsKC9wc210fG10L2dpLCAiIik7CiAgICAgIGZvciAoY29uc3QgW2ZhbWlseSwgcGRmRm9udF0gb2YgdGhpcy5mb250cy5lbnRyaWVzKCkpIHsKICAgICAgICBpZiAoZmFtaWx5LnJlcGxhY2VBbGwocGF0dGVybiwgIiIpLnRvTG93ZXJDYXNlKCkuc3RhcnRzV2l0aChuYW1lKSkgewogICAgICAgICAgbWF5YmUucHVzaChwZGZGb250KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChtYXliZS5sZW5ndGggPT09IDApIHsKICAgICAgZm9yIChjb25zdCBwZGZGb250IG9mIHRoaXMuZm9udHMudmFsdWVzKCkpIHsKICAgICAgICBpZiAocGRmRm9udC5yZWd1bGFyLm5hbWU/LnJlcGxhY2VBbGwocGF0dGVybiwgIiIpLnRvTG93ZXJDYXNlKCkuc3RhcnRzV2l0aChuYW1lKSkgewogICAgICAgICAgbWF5YmUucHVzaChwZGZGb250KTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChtYXliZS5sZW5ndGggPj0gMSkgewogICAgICBpZiAobWF5YmUubGVuZ3RoICE9PSAxICYmIG11c3RXYXJuKSB7CiAgICAgICAgd2FybihgWEZBIC0gVG9vIG1hbnkgY2hvaWNlcyB0byBndWVzcyB0aGUgY29ycmVjdCBmb250OiAke2ZvbnROYW1lfWApOwogICAgICB9CiAgICAgIHRoaXMuY2FjaGUuc2V0KGZvbnROYW1lLCBtYXliZVswXSk7CiAgICAgIHJldHVybiBtYXliZVswXTsKICAgIH0KICAgIGlmIChtdXN0V2FybiAmJiAhdGhpcy53YXJuZWQuaGFzKGZvbnROYW1lKSkgewogICAgICB0aGlzLndhcm5lZC5hZGQoZm9udE5hbWUpOwogICAgICB3YXJuKGBYRkEgLSBDYW5ub3QgZmluZCB0aGUgZm9udDogJHtmb250TmFtZX1gKTsKICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KfQpmdW5jdGlvbiBzZWxlY3RGb250KHhmYUZvbnQsIHR5cGVmYWNlKSB7CiAgaWYgKHhmYUZvbnQucG9zdHVyZSA9PT0gIml0YWxpYyIpIHsKICAgIGlmICh4ZmFGb250LndlaWdodCA9PT0gImJvbGQiKSB7CiAgICAgIHJldHVybiB0eXBlZmFjZS5ib2xkaXRhbGljOwogICAgfQogICAgcmV0dXJuIHR5cGVmYWNlLml0YWxpYzsKICB9IGVsc2UgaWYgKHhmYUZvbnQud2VpZ2h0ID09PSAiYm9sZCIpIHsKICAgIHJldHVybiB0eXBlZmFjZS5ib2xkOwogIH0KICByZXR1cm4gdHlwZWZhY2UucmVndWxhcjsKfQpmdW5jdGlvbiBmb250c19nZXRNZXRyaWNzKHhmYUZvbnQsIHJlYWwgPSBmYWxzZSkgewogIGxldCBwZGZGb250ID0gbnVsbDsKICBpZiAoeGZhRm9udCkgewogICAgY29uc3QgbmFtZSA9IHN0cmlwUXVvdGVzKHhmYUZvbnQudHlwZWZhY2UpOwogICAgY29uc3QgdHlwZWZhY2UgPSB4ZmFGb250WyRnbG9iYWxEYXRhXS5mb250RmluZGVyLmZpbmQobmFtZSk7CiAgICBwZGZGb250ID0gc2VsZWN0Rm9udCh4ZmFGb250LCB0eXBlZmFjZSk7CiAgfQogIGlmICghcGRmRm9udCkgewogICAgcmV0dXJuIHsKICAgICAgbGluZUhlaWdodDogMTIsCiAgICAgIGxpbmVHYXA6IDIsCiAgICAgIGxpbmVOb0dhcDogMTAKICAgIH07CiAgfQogIGNvbnN0IHNpemUgPSB4ZmFGb250LnNpemUgfHwgMTA7CiAgY29uc3QgbGluZUhlaWdodCA9IHBkZkZvbnQubGluZUhlaWdodCA/IE1hdGgubWF4KHJlYWwgPyAwIDogMS4yLCBwZGZGb250LmxpbmVIZWlnaHQpIDogMS4yOwogIGNvbnN0IGxpbmVHYXAgPSBwZGZGb250LmxpbmVHYXAgPT09IHVuZGVmaW5lZCA/IDAuMiA6IHBkZkZvbnQubGluZUdhcDsKICByZXR1cm4gewogICAgbGluZUhlaWdodDogbGluZUhlaWdodCAqIHNpemUsCiAgICBsaW5lR2FwOiBsaW5lR2FwICogc2l6ZSwKICAgIGxpbmVOb0dhcDogTWF0aC5tYXgoMSwgbGluZUhlaWdodCAtIGxpbmVHYXApICogc2l6ZQogIH07Cn0KCjsvLyAuL3NyYy9jb3JlL3hmYS90ZXh0LmpzCgoKCgpjb25zdCBXSURUSF9GQUNUT1IgPSAxLjAyOwpjbGFzcyB0ZXh0X0ZvbnRJbmZvIHsKICBjb25zdHJ1Y3Rvcih4ZmFGb250LCBtYXJnaW4sIGxpbmVIZWlnaHQsIGZvbnRGaW5kZXIpIHsKICAgIHRoaXMubGluZUhlaWdodCA9IGxpbmVIZWlnaHQ7CiAgICB0aGlzLnBhcmFNYXJnaW4gPSBtYXJnaW4gfHwgewogICAgICB0b3A6IDAsCiAgICAgIGJvdHRvbTogMCwKICAgICAgbGVmdDogMCwKICAgICAgcmlnaHQ6IDAKICAgIH07CiAgICBpZiAoIXhmYUZvbnQpIHsKICAgICAgW3RoaXMucGRmRm9udCwgdGhpcy54ZmFGb250XSA9IHRoaXMuZGVmYXVsdEZvbnQoZm9udEZpbmRlcik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMueGZhRm9udCA9IHsKICAgICAgdHlwZWZhY2U6IHhmYUZvbnQudHlwZWZhY2UsCiAgICAgIHBvc3R1cmU6IHhmYUZvbnQucG9zdHVyZSwKICAgICAgd2VpZ2h0OiB4ZmFGb250LndlaWdodCwKICAgICAgc2l6ZTogeGZhRm9udC5zaXplLAogICAgICBsZXR0ZXJTcGFjaW5nOiB4ZmFGb250LmxldHRlclNwYWNpbmcKICAgIH07CiAgICBjb25zdCB0eXBlZmFjZSA9IGZvbnRGaW5kZXIuZmluZCh4ZmFGb250LnR5cGVmYWNlKTsKICAgIGlmICghdHlwZWZhY2UpIHsKICAgICAgW3RoaXMucGRmRm9udCwgdGhpcy54ZmFGb250XSA9IHRoaXMuZGVmYXVsdEZvbnQoZm9udEZpbmRlcik7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMucGRmRm9udCA9IHNlbGVjdEZvbnQoeGZhRm9udCwgdHlwZWZhY2UpOwogICAgaWYgKCF0aGlzLnBkZkZvbnQpIHsKICAgICAgW3RoaXMucGRmRm9udCwgdGhpcy54ZmFGb250XSA9IHRoaXMuZGVmYXVsdEZvbnQoZm9udEZpbmRlcik7CiAgICB9CiAgfQogIGRlZmF1bHRGb250KGZvbnRGaW5kZXIpIHsKICAgIGNvbnN0IGZvbnQgPSBmb250RmluZGVyLmZpbmQoIkhlbHZldGljYSIsIGZhbHNlKSB8fCBmb250RmluZGVyLmZpbmQoIk15cmlhZCBQcm8iLCBmYWxzZSkgfHwgZm9udEZpbmRlci5maW5kKCJBcmlhbCIsIGZhbHNlKSB8fCBmb250RmluZGVyLmdldERlZmF1bHQoKTsKICAgIGlmIChmb250Py5yZWd1bGFyKSB7CiAgICAgIGNvbnN0IHBkZkZvbnQgPSBmb250LnJlZ3VsYXI7CiAgICAgIGNvbnN0IGluZm8gPSBwZGZGb250LmNzc0ZvbnRJbmZvOwogICAgICBjb25zdCB4ZmFGb250ID0gewogICAgICAgIHR5cGVmYWNlOiBpbmZvLmZvbnRGYW1pbHksCiAgICAgICAgcG9zdHVyZTogIm5vcm1hbCIsCiAgICAgICAgd2VpZ2h0OiAibm9ybWFsIiwKICAgICAgICBzaXplOiAxMCwKICAgICAgICBsZXR0ZXJTcGFjaW5nOiAwCiAgICAgIH07CiAgICAgIHJldHVybiBbcGRmRm9udCwgeGZhRm9udF07CiAgICB9CiAgICBjb25zdCB4ZmFGb250ID0gewogICAgICB0eXBlZmFjZTogIkNvdXJpZXIiLAogICAgICBwb3N0dXJlOiAibm9ybWFsIiwKICAgICAgd2VpZ2h0OiAibm9ybWFsIiwKICAgICAgc2l6ZTogMTAsCiAgICAgIGxldHRlclNwYWNpbmc6IDAKICAgIH07CiAgICByZXR1cm4gW251bGwsIHhmYUZvbnRdOwogIH0KfQpjbGFzcyBGb250U2VsZWN0b3IgewogIGNvbnN0cnVjdG9yKGRlZmF1bHRYZmFGb250LCBkZWZhdWx0UGFyYU1hcmdpbiwgZGVmYXVsdExpbmVIZWlnaHQsIGZvbnRGaW5kZXIpIHsKICAgIHRoaXMuZm9udEZpbmRlciA9IGZvbnRGaW5kZXI7CiAgICB0aGlzLnN0YWNrID0gW25ldyB0ZXh0X0ZvbnRJbmZvKGRlZmF1bHRYZmFGb250LCBkZWZhdWx0UGFyYU1hcmdpbiwgZGVmYXVsdExpbmVIZWlnaHQsIGZvbnRGaW5kZXIpXTsKICB9CiAgcHVzaERhdGEoeGZhRm9udCwgbWFyZ2luLCBsaW5lSGVpZ2h0KSB7CiAgICBjb25zdCBsYXN0Rm9udCA9IHRoaXMuc3RhY2suYXQoLTEpOwogICAgZm9yIChjb25zdCBuYW1lIG9mIFsidHlwZWZhY2UiLCAicG9zdHVyZSIsICJ3ZWlnaHQiLCAic2l6ZSIsICJsZXR0ZXJTcGFjaW5nIl0pIHsKICAgICAgaWYgKCF4ZmFGb250W25hbWVdKSB7CiAgICAgICAgeGZhRm9udFtuYW1lXSA9IGxhc3RGb250LnhmYUZvbnRbbmFtZV07CiAgICAgIH0KICAgIH0KICAgIGZvciAoY29uc3QgbmFtZSBvZiBbInRvcCIsICJib3R0b20iLCAibGVmdCIsICJyaWdodCJdKSB7CiAgICAgIGlmIChpc05hTihtYXJnaW5bbmFtZV0pKSB7CiAgICAgICAgbWFyZ2luW25hbWVdID0gbGFzdEZvbnQucGFyYU1hcmdpbltuYW1lXTsKICAgICAgfQogICAgfQogICAgY29uc3QgZm9udEluZm8gPSBuZXcgdGV4dF9Gb250SW5mbyh4ZmFGb250LCBtYXJnaW4sIGxpbmVIZWlnaHQgfHwgbGFzdEZvbnQubGluZUhlaWdodCwgdGhpcy5mb250RmluZGVyKTsKICAgIGlmICghZm9udEluZm8ucGRmRm9udCkgewogICAgICBmb250SW5mby5wZGZGb250ID0gbGFzdEZvbnQucGRmRm9udDsKICAgIH0KICAgIHRoaXMuc3RhY2sucHVzaChmb250SW5mbyk7CiAgfQogIHBvcEZvbnQoKSB7CiAgICB0aGlzLnN0YWNrLnBvcCgpOwogIH0KICB0b3BGb250KCkgewogICAgcmV0dXJuIHRoaXMuc3RhY2suYXQoLTEpOwogIH0KfQpjbGFzcyBUZXh0TWVhc3VyZSB7CiAgY29uc3RydWN0b3IoZGVmYXVsdFhmYUZvbnQsIGRlZmF1bHRQYXJhTWFyZ2luLCBkZWZhdWx0TGluZUhlaWdodCwgZm9udHMpIHsKICAgIHRoaXMuZ2x5cGhzID0gW107CiAgICB0aGlzLmZvbnRTZWxlY3RvciA9IG5ldyBGb250U2VsZWN0b3IoZGVmYXVsdFhmYUZvbnQsIGRlZmF1bHRQYXJhTWFyZ2luLCBkZWZhdWx0TGluZUhlaWdodCwgZm9udHMpOwogICAgdGhpcy5leHRyYUhlaWdodCA9IDA7CiAgfQogIHB1c2hEYXRhKHhmYUZvbnQsIG1hcmdpbiwgbGluZUhlaWdodCkgewogICAgdGhpcy5mb250U2VsZWN0b3IucHVzaERhdGEoeGZhRm9udCwgbWFyZ2luLCBsaW5lSGVpZ2h0KTsKICB9CiAgcG9wRm9udCh4ZmFGb250KSB7CiAgICByZXR1cm4gdGhpcy5mb250U2VsZWN0b3IucG9wRm9udCgpOwogIH0KICBhZGRQYXJhKCkgewogICAgY29uc3QgbGFzdEZvbnQgPSB0aGlzLmZvbnRTZWxlY3Rvci50b3BGb250KCk7CiAgICB0aGlzLmV4dHJhSGVpZ2h0ICs9IGxhc3RGb250LnBhcmFNYXJnaW4udG9wICsgbGFzdEZvbnQucGFyYU1hcmdpbi5ib3R0b207CiAgfQogIGFkZFN0cmluZyhzdHIpIHsKICAgIGlmICghc3RyKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGxhc3RGb250ID0gdGhpcy5mb250U2VsZWN0b3IudG9wRm9udCgpOwogICAgY29uc3QgZm9udFNpemUgPSBsYXN0Rm9udC54ZmFGb250LnNpemU7CiAgICBpZiAobGFzdEZvbnQucGRmRm9udCkgewogICAgICBjb25zdCBsZXR0ZXJTcGFjaW5nID0gbGFzdEZvbnQueGZhRm9udC5sZXR0ZXJTcGFjaW5nOwogICAgICBjb25zdCBwZGZGb250ID0gbGFzdEZvbnQucGRmRm9udDsKICAgICAgY29uc3QgZm9udExpbmVIZWlnaHQgPSBwZGZGb250LmxpbmVIZWlnaHQgfHwgMS4yOwogICAgICBjb25zdCBsaW5lSGVpZ2h0ID0gbGFzdEZvbnQubGluZUhlaWdodCB8fCBNYXRoLm1heCgxLjIsIGZvbnRMaW5lSGVpZ2h0KSAqIGZvbnRTaXplOwogICAgICBjb25zdCBsaW5lR2FwID0gcGRmRm9udC5saW5lR2FwID09PSB1bmRlZmluZWQgPyAwLjIgOiBwZGZGb250LmxpbmVHYXA7CiAgICAgIGNvbnN0IG5vR2FwID0gZm9udExpbmVIZWlnaHQgLSBsaW5lR2FwOwogICAgICBjb25zdCBmaXJzdExpbmVIZWlnaHQgPSBNYXRoLm1heCgxLCBub0dhcCkgKiBmb250U2l6ZTsKICAgICAgY29uc3Qgc2NhbGUgPSBmb250U2l6ZSAvIDEwMDA7CiAgICAgIGNvbnN0IGZhbGxiYWNrV2lkdGggPSBwZGZGb250LmRlZmF1bHRXaWR0aCB8fCBwZGZGb250LmNoYXJzVG9HbHlwaHMoIiAiKVswXS53aWR0aDsKICAgICAgZm9yIChjb25zdCBsaW5lIG9mIHN0ci5zcGxpdCgvW1x1MjAyOVxuXS8pKSB7CiAgICAgICAgY29uc3QgZW5jb2RlZExpbmUgPSBwZGZGb250LmVuY29kZVN0cmluZyhsaW5lKS5qb2luKCIiKTsKICAgICAgICBjb25zdCBnbHlwaHMgPSBwZGZGb250LmNoYXJzVG9HbHlwaHMoZW5jb2RlZExpbmUpOwogICAgICAgIGZvciAoY29uc3QgZ2x5cGggb2YgZ2x5cGhzKSB7CiAgICAgICAgICBjb25zdCB3aWR0aCA9IGdseXBoLndpZHRoIHx8IGZhbGxiYWNrV2lkdGg7CiAgICAgICAgICB0aGlzLmdseXBocy5wdXNoKFt3aWR0aCAqIHNjYWxlICsgbGV0dGVyU3BhY2luZywgbGluZUhlaWdodCwgZmlyc3RMaW5lSGVpZ2h0LCBnbHlwaC51bmljb2RlLCBmYWxzZV0pOwogICAgICAgIH0KICAgICAgICB0aGlzLmdseXBocy5wdXNoKFswLCAwLCAwLCAiXG4iLCB0cnVlXSk7CiAgICAgIH0KICAgICAgdGhpcy5nbHlwaHMucG9wKCk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGZvciAoY29uc3QgbGluZSBvZiBzdHIuc3BsaXQoL1tcdTIwMjlcbl0vKSkgewogICAgICBmb3IgKGNvbnN0IGNoYXIgb2YgbGluZS5zcGxpdCgiIikpIHsKICAgICAgICB0aGlzLmdseXBocy5wdXNoKFtmb250U2l6ZSwgMS4yICogZm9udFNpemUsIGZvbnRTaXplLCBjaGFyLCBmYWxzZV0pOwogICAgICB9CiAgICAgIHRoaXMuZ2x5cGhzLnB1c2goWzAsIDAsIDAsICJcbiIsIHRydWVdKTsKICAgIH0KICAgIHRoaXMuZ2x5cGhzLnBvcCgpOwogIH0KICBjb21wdXRlKG1heFdpZHRoKSB7CiAgICBsZXQgbGFzdFNwYWNlUG9zID0gLTEsCiAgICAgIGxhc3RTcGFjZVdpZHRoID0gMCwKICAgICAgd2lkdGggPSAwLAogICAgICBoZWlnaHQgPSAwLAogICAgICBjdXJyZW50TGluZVdpZHRoID0gMCwKICAgICAgY3VycmVudExpbmVIZWlnaHQgPSAwOwogICAgbGV0IGlzQnJva2VuID0gZmFsc2U7CiAgICBsZXQgaXNGaXJzdExpbmUgPSB0cnVlOwogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gdGhpcy5nbHlwaHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCBbZ2x5cGhXaWR0aCwgbGluZUhlaWdodCwgZmlyc3RMaW5lSGVpZ2h0LCBjaGFyLCBpc0VPTF0gPSB0aGlzLmdseXBoc1tpXTsKICAgICAgY29uc3QgaXNTcGFjZSA9IGNoYXIgPT09ICIgIjsKICAgICAgY29uc3QgZ2x5cGhIZWlnaHQgPSBpc0ZpcnN0TGluZSA/IGZpcnN0TGluZUhlaWdodCA6IGxpbmVIZWlnaHQ7CiAgICAgIGlmIChpc0VPTCkgewogICAgICAgIHdpZHRoID0gTWF0aC5tYXgod2lkdGgsIGN1cnJlbnRMaW5lV2lkdGgpOwogICAgICAgIGN1cnJlbnRMaW5lV2lkdGggPSAwOwogICAgICAgIGhlaWdodCArPSBjdXJyZW50TGluZUhlaWdodDsKICAgICAgICBjdXJyZW50TGluZUhlaWdodCA9IGdseXBoSGVpZ2h0OwogICAgICAgIGxhc3RTcGFjZVBvcyA9IC0xOwogICAgICAgIGxhc3RTcGFjZVdpZHRoID0gMDsKICAgICAgICBpc0ZpcnN0TGluZSA9IGZhbHNlOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChpc1NwYWNlKSB7CiAgICAgICAgaWYgKGN1cnJlbnRMaW5lV2lkdGggKyBnbHlwaFdpZHRoID4gbWF4V2lkdGgpIHsKICAgICAgICAgIHdpZHRoID0gTWF0aC5tYXgod2lkdGgsIGN1cnJlbnRMaW5lV2lkdGgpOwogICAgICAgICAgY3VycmVudExpbmVXaWR0aCA9IDA7CiAgICAgICAgICBoZWlnaHQgKz0gY3VycmVudExpbmVIZWlnaHQ7CiAgICAgICAgICBjdXJyZW50TGluZUhlaWdodCA9IGdseXBoSGVpZ2h0OwogICAgICAgICAgbGFzdFNwYWNlUG9zID0gLTE7CiAgICAgICAgICBsYXN0U3BhY2VXaWR0aCA9IDA7CiAgICAgICAgICBpc0Jyb2tlbiA9IHRydWU7CiAgICAgICAgICBpc0ZpcnN0TGluZSA9IGZhbHNlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjdXJyZW50TGluZUhlaWdodCA9IE1hdGgubWF4KGdseXBoSGVpZ2h0LCBjdXJyZW50TGluZUhlaWdodCk7CiAgICAgICAgICBsYXN0U3BhY2VXaWR0aCA9IGN1cnJlbnRMaW5lV2lkdGg7CiAgICAgICAgICBjdXJyZW50TGluZVdpZHRoICs9IGdseXBoV2lkdGg7CiAgICAgICAgICBsYXN0U3BhY2VQb3MgPSBpOwogICAgICAgIH0KICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoY3VycmVudExpbmVXaWR0aCArIGdseXBoV2lkdGggPiBtYXhXaWR0aCkgewogICAgICAgIGhlaWdodCArPSBjdXJyZW50TGluZUhlaWdodDsKICAgICAgICBjdXJyZW50TGluZUhlaWdodCA9IGdseXBoSGVpZ2h0OwogICAgICAgIGlmIChsYXN0U3BhY2VQb3MgIT09IC0xKSB7CiAgICAgICAgICBpID0gbGFzdFNwYWNlUG9zOwogICAgICAgICAgd2lkdGggPSBNYXRoLm1heCh3aWR0aCwgbGFzdFNwYWNlV2lkdGgpOwogICAgICAgICAgY3VycmVudExpbmVXaWR0aCA9IDA7CiAgICAgICAgICBsYXN0U3BhY2VQb3MgPSAtMTsKICAgICAgICAgIGxhc3RTcGFjZVdpZHRoID0gMDsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgd2lkdGggPSBNYXRoLm1heCh3aWR0aCwgY3VycmVudExpbmVXaWR0aCk7CiAgICAgICAgICBjdXJyZW50TGluZVdpZHRoID0gZ2x5cGhXaWR0aDsKICAgICAgICB9CiAgICAgICAgaXNCcm9rZW4gPSB0cnVlOwogICAgICAgIGlzRmlyc3RMaW5lID0gZmFsc2U7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY3VycmVudExpbmVXaWR0aCArPSBnbHlwaFdpZHRoOwogICAgICBjdXJyZW50TGluZUhlaWdodCA9IE1hdGgubWF4KGdseXBoSGVpZ2h0LCBjdXJyZW50TGluZUhlaWdodCk7CiAgICB9CiAgICB3aWR0aCA9IE1hdGgubWF4KHdpZHRoLCBjdXJyZW50TGluZVdpZHRoKTsKICAgIGhlaWdodCArPSBjdXJyZW50TGluZUhlaWdodCArIHRoaXMuZXh0cmFIZWlnaHQ7CiAgICByZXR1cm4gewogICAgICB3aWR0aDogV0lEVEhfRkFDVE9SICogd2lkdGgsCiAgICAgIGhlaWdodCwKICAgICAgaXNCcm9rZW4KICAgIH07CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEvc29tLmpzCgoKCgoKCmNvbnN0IG5hbWVQYXR0ZXJuID0gL15bXi5bXSsvOwpjb25zdCBpbmRleFBhdHRlcm4gPSAvXlteXF1dKy87CmNvbnN0IG9wZXJhdG9ycyA9IHsKICBkb3Q6IDAsCiAgZG90RG90OiAxLAogIGRvdEhhc2g6IDIsCiAgZG90QnJhY2tldDogMywKICBkb3RQYXJlbjogNAp9Owpjb25zdCBzaG9ydGN1dHMgPSBuZXcgTWFwKFtbIiRkYXRhIiwgKHJvb3QsIGN1cnJlbnQpID0+IHJvb3QuZGF0YXNldHMgPyByb290LmRhdGFzZXRzLmRhdGEgOiByb290XSwgWyIkcmVjb3JkIiwgKHJvb3QsIGN1cnJlbnQpID0+IChyb290LmRhdGFzZXRzID8gcm9vdC5kYXRhc2V0cy5kYXRhIDogcm9vdClbJGdldENoaWxkcmVuXSgpWzBdXSwgWyIkdGVtcGxhdGUiLCAocm9vdCwgY3VycmVudCkgPT4gcm9vdC50ZW1wbGF0ZV0sIFsiJGNvbm5lY3Rpb25TZXQiLCAocm9vdCwgY3VycmVudCkgPT4gcm9vdC5jb25uZWN0aW9uU2V0XSwgWyIkZm9ybSIsIChyb290LCBjdXJyZW50KSA9PiByb290LmZvcm1dLCBbIiRsYXlvdXQiLCAocm9vdCwgY3VycmVudCkgPT4gcm9vdC5sYXlvdXRdLCBbIiRob3N0IiwgKHJvb3QsIGN1cnJlbnQpID0+IHJvb3QuaG9zdF0sIFsiJGRhdGFXaW5kb3ciLCAocm9vdCwgY3VycmVudCkgPT4gcm9vdC5kYXRhV2luZG93XSwgWyIkZXZlbnQiLCAocm9vdCwgY3VycmVudCkgPT4gcm9vdC5ldmVudF0sIFsiISIsIChyb290LCBjdXJyZW50KSA9PiByb290LmRhdGFzZXRzXSwgWyIkeGZhIiwgKHJvb3QsIGN1cnJlbnQpID0+IHJvb3RdLCBbInhmYSIsIChyb290LCBjdXJyZW50KSA9PiByb290XSwgWyIkIiwgKHJvb3QsIGN1cnJlbnQpID0+IGN1cnJlbnRdXSk7CmNvbnN0IHNvbUNhY2hlID0gbmV3IFdlYWtNYXAoKTsKZnVuY3Rpb24gcGFyc2VJbmRleChpbmRleCkgewogIGluZGV4ID0gaW5kZXgudHJpbSgpOwogIGlmIChpbmRleCA9PT0gIioiKSB7CiAgICByZXR1cm4gSW5maW5pdHk7CiAgfQogIHJldHVybiBwYXJzZUludChpbmRleCwgMTApIHx8IDA7Cn0KZnVuY3Rpb24gcGFyc2VFeHByZXNzaW9uKGV4cHIsIGRvdERvdEFsbG93ZWQsIG5vRXhwciA9IHRydWUpIHsKICBsZXQgbWF0Y2ggPSBleHByLm1hdGNoKG5hbWVQYXR0ZXJuKTsKICBpZiAoIW1hdGNoKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgbGV0IFtuYW1lXSA9IG1hdGNoOwogIGNvbnN0IHBhcnNlZCA9IFt7CiAgICBuYW1lLAogICAgY2FjaGVOYW1lOiAiLiIgKyBuYW1lLAogICAgaW5kZXg6IDAsCiAgICBqczogbnVsbCwKICAgIGZvcm1DYWxjOiBudWxsLAogICAgb3BlcmF0b3I6IG9wZXJhdG9ycy5kb3QKICB9XTsKICBsZXQgcG9zID0gbmFtZS5sZW5ndGg7CiAgd2hpbGUgKHBvcyA8IGV4cHIubGVuZ3RoKSB7CiAgICBjb25zdCBzcG9zID0gcG9zOwogICAgY29uc3QgY2hhciA9IGV4cHIuY2hhckF0KHBvcysrKTsKICAgIGlmIChjaGFyID09PSAiWyIpIHsKICAgICAgbWF0Y2ggPSBleHByLnNsaWNlKHBvcykubWF0Y2goaW5kZXhQYXR0ZXJuKTsKICAgICAgaWYgKCFtYXRjaCkgewogICAgICAgIHdhcm4oIlhGQSAtIEludmFsaWQgaW5kZXggaW4gU09NIGV4cHJlc3Npb24iKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBwYXJzZWQuYXQoLTEpLmluZGV4ID0gcGFyc2VJbmRleChtYXRjaFswXSk7CiAgICAgIHBvcyArPSBtYXRjaFswXS5sZW5ndGggKyAxOwogICAgICBjb250aW51ZTsKICAgIH0KICAgIGxldCBvcGVyYXRvcjsKICAgIHN3aXRjaCAoZXhwci5jaGFyQXQocG9zKSkgewogICAgICBjYXNlICIuIjoKICAgICAgICBpZiAoIWRvdERvdEFsbG93ZWQpIHsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgICBwb3MrKzsKICAgICAgICBvcGVyYXRvciA9IG9wZXJhdG9ycy5kb3REb3Q7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIiMiOgogICAgICAgIHBvcysrOwogICAgICAgIG9wZXJhdG9yID0gb3BlcmF0b3JzLmRvdEhhc2g7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIlsiOgogICAgICAgIGlmIChub0V4cHIpIHsKICAgICAgICAgIHdhcm4oIlhGQSAtIFNPTSBleHByZXNzaW9uIGNvbnRhaW5zIGEgRm9ybUNhbGMgc3ViZXhwcmVzc2lvbiB3aGljaCBpcyBub3Qgc3VwcG9ydGVkIGZvciBub3cuIik7CiAgICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgICB9CiAgICAgICAgb3BlcmF0b3IgPSBvcGVyYXRvcnMuZG90QnJhY2tldDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiKCI6CiAgICAgICAgaWYgKG5vRXhwcikgewogICAgICAgICAgd2FybigiWEZBIC0gU09NIGV4cHJlc3Npb24gY29udGFpbnMgYSBKYXZhU2NyaXB0IHN1YmV4cHJlc3Npb24gd2hpY2ggaXMgbm90IHN1cHBvcnRlZCBmb3Igbm93LiIpOwogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIG9wZXJhdG9yID0gb3BlcmF0b3JzLmRvdFBhcmVuOwogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIG9wZXJhdG9yID0gb3BlcmF0b3JzLmRvdDsKICAgICAgICBicmVhazsKICAgIH0KICAgIG1hdGNoID0gZXhwci5zbGljZShwb3MpLm1hdGNoKG5hbWVQYXR0ZXJuKTsKICAgIGlmICghbWF0Y2gpIHsKICAgICAgYnJlYWs7CiAgICB9CiAgICBbbmFtZV0gPSBtYXRjaDsKICAgIHBvcyArPSBuYW1lLmxlbmd0aDsKICAgIHBhcnNlZC5wdXNoKHsKICAgICAgbmFtZSwKICAgICAgY2FjaGVOYW1lOiBleHByLnNsaWNlKHNwb3MsIHBvcyksCiAgICAgIG9wZXJhdG9yLAogICAgICBpbmRleDogMCwKICAgICAganM6IG51bGwsCiAgICAgIGZvcm1DYWxjOiBudWxsCiAgICB9KTsKICB9CiAgcmV0dXJuIHBhcnNlZDsKfQpmdW5jdGlvbiBzZWFyY2hOb2RlKHJvb3QsIGNvbnRhaW5lciwgZXhwciwgZG90RG90QWxsb3dlZCA9IHRydWUsIHVzZUNhY2hlID0gdHJ1ZSkgewogIGNvbnN0IHBhcnNlZCA9IHBhcnNlRXhwcmVzc2lvbihleHByLCBkb3REb3RBbGxvd2VkKTsKICBpZiAoIXBhcnNlZCkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGNvbnN0IGZuID0gc2hvcnRjdXRzLmdldChwYXJzZWRbMF0ubmFtZSk7CiAgbGV0IGkgPSAwOwogIGxldCBpc1F1YWxpZmllZDsKICBpZiAoZm4pIHsKICAgIGlzUXVhbGlmaWVkID0gdHJ1ZTsKICAgIHJvb3QgPSBbZm4ocm9vdCwgY29udGFpbmVyKV07CiAgICBpID0gMTsKICB9IGVsc2UgewogICAgaXNRdWFsaWZpZWQgPSBjb250YWluZXIgPT09IG51bGw7CiAgICByb290ID0gW2NvbnRhaW5lciB8fCByb290XTsKICB9CiAgZm9yIChsZXQgaWkgPSBwYXJzZWQubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgY29uc3QgewogICAgICBuYW1lLAogICAgICBjYWNoZU5hbWUsCiAgICAgIG9wZXJhdG9yLAogICAgICBpbmRleAogICAgfSA9IHBhcnNlZFtpXTsKICAgIGNvbnN0IG5vZGVzID0gW107CiAgICBmb3IgKGNvbnN0IG5vZGUgb2Ygcm9vdCkgewogICAgICBpZiAoIW5vZGUuaXNYRkFPYmplY3QpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBsZXQgY2hpbGRyZW4sIGNhY2hlZDsKICAgICAgaWYgKHVzZUNhY2hlKSB7CiAgICAgICAgY2FjaGVkID0gc29tQ2FjaGUuZ2V0KG5vZGUpOwogICAgICAgIGlmICghY2FjaGVkKSB7CiAgICAgICAgICBjYWNoZWQgPSBuZXcgTWFwKCk7CiAgICAgICAgICBzb21DYWNoZS5zZXQobm9kZSwgY2FjaGVkKTsKICAgICAgICB9CiAgICAgICAgY2hpbGRyZW4gPSBjYWNoZWQuZ2V0KGNhY2hlTmFtZSk7CiAgICAgIH0KICAgICAgaWYgKCFjaGlsZHJlbikgewogICAgICAgIHN3aXRjaCAob3BlcmF0b3IpIHsKICAgICAgICAgIGNhc2Ugb3BlcmF0b3JzLmRvdDoKICAgICAgICAgICAgY2hpbGRyZW4gPSBub2RlWyRnZXRDaGlsZHJlbkJ5TmFtZV0obmFtZSwgZmFsc2UpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2Ugb3BlcmF0b3JzLmRvdERvdDoKICAgICAgICAgICAgY2hpbGRyZW4gPSBub2RlWyRnZXRDaGlsZHJlbkJ5TmFtZV0obmFtZSwgdHJ1ZSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSBvcGVyYXRvcnMuZG90SGFzaDoKICAgICAgICAgICAgY2hpbGRyZW4gPSBub2RlWyRnZXRDaGlsZHJlbkJ5Q2xhc3NdKG5hbWUpOwogICAgICAgICAgICBjaGlsZHJlbiA9IGNoaWxkcmVuLmlzWEZBT2JqZWN0QXJyYXkgPyBjaGlsZHJlbi5jaGlsZHJlbiA6IFtjaGlsZHJlbl07CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmICh1c2VDYWNoZSkgewogICAgICAgICAgY2FjaGVkLnNldChjYWNoZU5hbWUsIGNoaWxkcmVuKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA+IDApIHsKICAgICAgICBub2Rlcy5wdXNoKGNoaWxkcmVuKTsKICAgICAgfQogICAgfQogICAgaWYgKG5vZGVzLmxlbmd0aCA9PT0gMCAmJiAhaXNRdWFsaWZpZWQgJiYgaSA9PT0gMCkgewogICAgICBjb25zdCBwYXJlbnQgPSBjb250YWluZXJbJGdldFBhcmVudF0oKTsKICAgICAgY29udGFpbmVyID0gcGFyZW50OwogICAgICBpZiAoIWNvbnRhaW5lcikgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGkgPSAtMTsKICAgICAgcm9vdCA9IFtjb250YWluZXJdOwogICAgICBjb250aW51ZTsKICAgIH0KICAgIHJvb3QgPSBpc0Zpbml0ZShpbmRleCkgPyBub2Rlcy5maWx0ZXIobm9kZSA9PiBpbmRleCA8IG5vZGUubGVuZ3RoKS5tYXAobm9kZSA9PiBub2RlW2luZGV4XSkgOiBub2Rlcy5mbGF0KCk7CiAgfQogIGlmIChyb290Lmxlbmd0aCA9PT0gMCkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIHJldHVybiByb290Owp9CmZ1bmN0aW9uIGNyZWF0ZURhdGFOb2RlKHJvb3QsIGNvbnRhaW5lciwgZXhwcikgewogIGNvbnN0IHBhcnNlZCA9IHBhcnNlRXhwcmVzc2lvbihleHByKTsKICBpZiAoIXBhcnNlZCkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGlmIChwYXJzZWQuc29tZSh4ID0+IHgub3BlcmF0b3IgPT09IG9wZXJhdG9ycy5kb3REb3QpKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgY29uc3QgZm4gPSBzaG9ydGN1dHMuZ2V0KHBhcnNlZFswXS5uYW1lKTsKICBsZXQgaSA9IDA7CiAgaWYgKGZuKSB7CiAgICByb290ID0gZm4ocm9vdCwgY29udGFpbmVyKTsKICAgIGkgPSAxOwogIH0gZWxzZSB7CiAgICByb290ID0gY29udGFpbmVyIHx8IHJvb3Q7CiAgfQogIGZvciAobGV0IGlpID0gcGFyc2VkLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgIGNvbnN0IHsKICAgICAgbmFtZSwKICAgICAgb3BlcmF0b3IsCiAgICAgIGluZGV4CiAgICB9ID0gcGFyc2VkW2ldOwogICAgaWYgKCFpc0Zpbml0ZShpbmRleCkpIHsKICAgICAgcGFyc2VkW2ldLmluZGV4ID0gMDsKICAgICAgcmV0dXJuIHJvb3QuY3JlYXRlTm9kZXMocGFyc2VkLnNsaWNlKGkpKTsKICAgIH0KICAgIGxldCBjaGlsZHJlbjsKICAgIHN3aXRjaCAob3BlcmF0b3IpIHsKICAgICAgY2FzZSBvcGVyYXRvcnMuZG90OgogICAgICAgIGNoaWxkcmVuID0gcm9vdFskZ2V0Q2hpbGRyZW5CeU5hbWVdKG5hbWUsIGZhbHNlKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBvcGVyYXRvcnMuZG90RG90OgogICAgICAgIGNoaWxkcmVuID0gcm9vdFskZ2V0Q2hpbGRyZW5CeU5hbWVdKG5hbWUsIHRydWUpOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIG9wZXJhdG9ycy5kb3RIYXNoOgogICAgICAgIGNoaWxkcmVuID0gcm9vdFskZ2V0Q2hpbGRyZW5CeUNsYXNzXShuYW1lKTsKICAgICAgICBjaGlsZHJlbiA9IGNoaWxkcmVuLmlzWEZBT2JqZWN0QXJyYXkgPyBjaGlsZHJlbi5jaGlsZHJlbiA6IFtjaGlsZHJlbl07CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiByb290LmNyZWF0ZU5vZGVzKHBhcnNlZC5zbGljZShpKSk7CiAgICB9CiAgICBpZiAoaW5kZXggPCBjaGlsZHJlbi5sZW5ndGgpIHsKICAgICAgY29uc3QgY2hpbGQgPSBjaGlsZHJlbltpbmRleF07CiAgICAgIGlmICghY2hpbGQuaXNYRkFPYmplY3QpIHsKICAgICAgICB3YXJuKGBYRkEgLSBDYW5ub3QgY3JlYXRlIGEgbm9kZS5gKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICByb290ID0gY2hpbGQ7CiAgICB9IGVsc2UgewogICAgICBwYXJzZWRbaV0uaW5kZXggPSBpbmRleCAtIGNoaWxkcmVuLmxlbmd0aDsKICAgICAgcmV0dXJuIHJvb3QuY3JlYXRlTm9kZXMocGFyc2VkLnNsaWNlKGkpKTsKICAgIH0KICB9CiAgcmV0dXJuIG51bGw7Cn0KCjsvLyAuL3NyYy9jb3JlL3hmYS94ZmFfb2JqZWN0LmpzCgoKCgoKCgoKCgoKCgoKCgoKY29uc3QgX2FwcGx5UHJvdG90eXBlID0gU3ltYm9sKCk7CmNvbnN0IF9hdHRyaWJ1dGVzID0gU3ltYm9sKCk7CmNvbnN0IF9hdHRyaWJ1dGVOYW1lcyA9IFN5bWJvbCgpOwpjb25zdCBfY2hpbGRyZW4gPSBTeW1ib2woIl9jaGlsZHJlbiIpOwpjb25zdCBfY2xvbmVBdHRyaWJ1dGUgPSBTeW1ib2woKTsKY29uc3QgX2RhdGFWYWx1ZSA9IFN5bWJvbCgpOwpjb25zdCBfZGVmYXVsdFZhbHVlID0gU3ltYm9sKCk7CmNvbnN0IF9maWx0ZXJlZENoaWxkcmVuR2VuZXJhdG9yID0gU3ltYm9sKCk7CmNvbnN0IF9nZXRQcm90b3R5cGUgPSBTeW1ib2woKTsKY29uc3QgX2dldFVuc2V0QXR0cmlidXRlcyA9IFN5bWJvbCgpOwpjb25zdCBfaGFzQ2hpbGRyZW4gPSBTeW1ib2woKTsKY29uc3QgX21heCA9IFN5bWJvbCgpOwpjb25zdCBfb3B0aW9ucyA9IFN5bWJvbCgpOwpjb25zdCBfcGFyZW50ID0gU3ltYm9sKCJwYXJlbnQiKTsKY29uc3QgX3Jlc29sdmVQcm90b3R5cGVzSGVscGVyID0gU3ltYm9sKCk7CmNvbnN0IF9zZXRBdHRyaWJ1dGVzID0gU3ltYm9sKCk7CmNvbnN0IF92YWxpZGF0b3IgPSBTeW1ib2woKTsKbGV0IHVpZCA9IDA7CmNvbnN0IE5TX0RBVEFTRVRTID0gTmFtZXNwYWNlSWRzLmRhdGFzZXRzLmlkOwpjbGFzcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKG5zSWQsIG5hbWUsIGhhc0NoaWxkcmVuID0gZmFsc2UpIHsKICAgIHRoaXNbJG5hbWVzcGFjZUlkXSA9IG5zSWQ7CiAgICB0aGlzWyRub2RlTmFtZV0gPSBuYW1lOwogICAgdGhpc1tfaGFzQ2hpbGRyZW5dID0gaGFzQ2hpbGRyZW47CiAgICB0aGlzW19wYXJlbnRdID0gbnVsbDsKICAgIHRoaXNbX2NoaWxkcmVuXSA9IFtdOwogICAgdGhpc1skdWlkXSA9IGAke25hbWV9JHt1aWQrK31gOwogICAgdGhpc1skZ2xvYmFsRGF0YV0gPSBudWxsOwogIH0KICBnZXQgaXNYRkFPYmplY3QoKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgZ2V0IGlzWEZBT2JqZWN0QXJyYXkoKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGNyZWF0ZU5vZGVzKHBhdGgpIHsKICAgIGxldCByb290ID0gdGhpcywKICAgICAgbm9kZSA9IG51bGw7CiAgICBmb3IgKGNvbnN0IHsKICAgICAgbmFtZSwKICAgICAgaW5kZXgKICAgIH0gb2YgcGF0aCkgewogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBpc0Zpbml0ZShpbmRleCkgPyBpbmRleCA6IDA7IGkgPD0gaWk7IGkrKykgewogICAgICAgIGNvbnN0IG5zSWQgPSByb290WyRuYW1lc3BhY2VJZF0gPT09IE5TX0RBVEFTRVRTID8gLTEgOiByb290WyRuYW1lc3BhY2VJZF07CiAgICAgICAgbm9kZSA9IG5ldyBYbWxPYmplY3QobnNJZCwgbmFtZSk7CiAgICAgICAgcm9vdFskYXBwZW5kQ2hpbGRdKG5vZGUpOwogICAgICB9CiAgICAgIHJvb3QgPSBub2RlOwogICAgfQogICAgcmV0dXJuIG5vZGU7CiAgfQogIFskb25DaGlsZF0oY2hpbGQpIHsKICAgIGlmICghdGhpc1tfaGFzQ2hpbGRyZW5dIHx8ICF0aGlzWyRvbkNoaWxkQ2hlY2tdKGNoaWxkKSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBjb25zdCBuYW1lID0gY2hpbGRbJG5vZGVOYW1lXTsKICAgIGNvbnN0IG5vZGUgPSB0aGlzW25hbWVdOwogICAgaWYgKG5vZGUgaW5zdGFuY2VvZiBYRkFPYmplY3RBcnJheSkgewogICAgICBpZiAobm9kZS5wdXNoKGNoaWxkKSkgewogICAgICAgIHRoaXNbJGFwcGVuZENoaWxkXShjaGlsZCk7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGlmIChub2RlICE9PSBudWxsKSB7CiAgICAgICAgdGhpc1skcmVtb3ZlQ2hpbGRdKG5vZGUpOwogICAgICB9CiAgICAgIHRoaXNbbmFtZV0gPSBjaGlsZDsKICAgICAgdGhpc1skYXBwZW5kQ2hpbGRdKGNoaWxkKTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBsZXQgaWQgPSAiIjsKICAgIGlmICh0aGlzLmlkKSB7CiAgICAgIGlkID0gYCAoaWQ6ICR7dGhpcy5pZH0pYDsKICAgIH0gZWxzZSBpZiAodGhpcy5uYW1lKSB7CiAgICAgIGlkID0gYCAobmFtZTogJHt0aGlzLm5hbWV9ICR7dGhpcy5oLnZhbHVlfSlgOwogICAgfQogICAgd2FybihgWEZBIC0gbm9kZSAiJHt0aGlzWyRub2RlTmFtZV19IiR7aWR9IGhhcyBhbHJlYWR5IGVub3VnaCAiJHtuYW1lfSIhYCk7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFskb25DaGlsZENoZWNrXShjaGlsZCkgewogICAgcmV0dXJuIHRoaXMuaGFzT3duUHJvcGVydHkoY2hpbGRbJG5vZGVOYW1lXSkgJiYgY2hpbGRbJG5hbWVzcGFjZUlkXSA9PT0gdGhpc1skbmFtZXNwYWNlSWRdOwogIH0KICBbJGlzTnNBZ25vc3RpY10oKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFskYWNjZXB0V2hpdGVzcGFjZV0oKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFskaXNDREFUQVhtbF0oKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFskaXNCaW5kYWJsZV0oKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFskcG9wUGFyYV0oKSB7CiAgICBpZiAodGhpcy5wYXJhKSB7CiAgICAgIHRoaXNbJGdldFRlbXBsYXRlUm9vdF0oKVskZXh0cmFdLnBhcmFTdGFjay5wb3AoKTsKICAgIH0KICB9CiAgWyRwdXNoUGFyYV0oKSB7CiAgICB0aGlzWyRnZXRUZW1wbGF0ZVJvb3RdKClbJGV4dHJhXS5wYXJhU3RhY2sucHVzaCh0aGlzLnBhcmEpOwogIH0KICBbJHNldElkXShpZHMpIHsKICAgIGlmICh0aGlzLmlkICYmIHRoaXNbJG5hbWVzcGFjZUlkXSA9PT0gTmFtZXNwYWNlSWRzLnRlbXBsYXRlLmlkKSB7CiAgICAgIGlkcy5zZXQodGhpcy5pZCwgdGhpcyk7CiAgICB9CiAgfQogIFskZ2V0VGVtcGxhdGVSb290XSgpIHsKICAgIHJldHVybiB0aGlzWyRnbG9iYWxEYXRhXS50ZW1wbGF0ZTsKICB9CiAgWyRpc1NwbGl0dGFibGVdKCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBbJGlzVGhlcmVNb3JlV2lkdGhdKCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBbJGFwcGVuZENoaWxkXShjaGlsZCkgewogICAgY2hpbGRbX3BhcmVudF0gPSB0aGlzOwogICAgdGhpc1tfY2hpbGRyZW5dLnB1c2goY2hpbGQpOwogICAgaWYgKCFjaGlsZFskZ2xvYmFsRGF0YV0gJiYgdGhpc1skZ2xvYmFsRGF0YV0pIHsKICAgICAgY2hpbGRbJGdsb2JhbERhdGFdID0gdGhpc1skZ2xvYmFsRGF0YV07CiAgICB9CiAgfQogIFskcmVtb3ZlQ2hpbGRdKGNoaWxkKSB7CiAgICBjb25zdCBpID0gdGhpc1tfY2hpbGRyZW5dLmluZGV4T2YoY2hpbGQpOwogICAgdGhpc1tfY2hpbGRyZW5dLnNwbGljZShpLCAxKTsKICB9CiAgWyRoYXNTZXR0YWJsZVZhbHVlXSgpIHsKICAgIHJldHVybiB0aGlzLmhhc093blByb3BlcnR5KCJ2YWx1ZSIpOwogIH0KICBbJHNldFZhbHVlXShfKSB7fQogIFskb25UZXh0XShfKSB7fQogIFskZmluYWxpemVdKCkge30KICBbJGNsZWFuXShidWlsZGVyKSB7CiAgICBkZWxldGUgdGhpc1tfaGFzQ2hpbGRyZW5dOwogICAgaWYgKHRoaXNbJGNsZWFudXBdKSB7CiAgICAgIGJ1aWxkZXIuY2xlYW4odGhpc1skY2xlYW51cF0pOwogICAgICBkZWxldGUgdGhpc1skY2xlYW51cF07CiAgICB9CiAgfQogIFskaW5kZXhPZl0oY2hpbGQpIHsKICAgIHJldHVybiB0aGlzW19jaGlsZHJlbl0uaW5kZXhPZihjaGlsZCk7CiAgfQogIFskaW5zZXJ0QXRdKGksIGNoaWxkKSB7CiAgICBjaGlsZFtfcGFyZW50XSA9IHRoaXM7CiAgICB0aGlzW19jaGlsZHJlbl0uc3BsaWNlKGksIDAsIGNoaWxkKTsKICAgIGlmICghY2hpbGRbJGdsb2JhbERhdGFdICYmIHRoaXNbJGdsb2JhbERhdGFdKSB7CiAgICAgIGNoaWxkWyRnbG9iYWxEYXRhXSA9IHRoaXNbJGdsb2JhbERhdGFdOwogICAgfQogIH0KICBbJGlzVHJhbnNwYXJlbnRdKCkgewogICAgcmV0dXJuICF0aGlzLm5hbWU7CiAgfQogIFskbGFzdEF0dHJpYnV0ZV0oKSB7CiAgICByZXR1cm4gIiI7CiAgfQogIFskdGV4dF0oKSB7CiAgICBpZiAodGhpc1tfY2hpbGRyZW5dLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gdGhpc1skY29udGVudF07CiAgICB9CiAgICByZXR1cm4gdGhpc1tfY2hpbGRyZW5dLm1hcChjID0+IGNbJHRleHRdKCkpLmpvaW4oIiIpOwogIH0KICBnZXQgW19hdHRyaWJ1dGVOYW1lc10oKSB7CiAgICBjb25zdCBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZih0aGlzKTsKICAgIGlmICghcHJvdG8uX2F0dHJpYnV0ZXMpIHsKICAgICAgY29uc3QgYXR0cmlidXRlcyA9IHByb3RvLl9hdHRyaWJ1dGVzID0gbmV3IFNldCgpOwogICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGhpcykpIHsKICAgICAgICBpZiAodGhpc1tuYW1lXSA9PT0gbnVsbCB8fCB0aGlzW25hbWVdIGluc3RhbmNlb2YgWEZBT2JqZWN0IHx8IHRoaXNbbmFtZV0gaW5zdGFuY2VvZiBYRkFPYmplY3RBcnJheSkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGF0dHJpYnV0ZXMuYWRkKG5hbWUpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsIF9hdHRyaWJ1dGVOYW1lcywgcHJvdG8uX2F0dHJpYnV0ZXMpOwogIH0KICBbJGlzRGVzY2VuZGVudF0ocGFyZW50KSB7CiAgICBsZXQgbm9kZSA9IHRoaXM7CiAgICB3aGlsZSAobm9kZSkgewogICAgICBpZiAobm9kZSA9PT0gcGFyZW50KSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgbm9kZSA9IG5vZGVbJGdldFBhcmVudF0oKTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKICB9CiAgWyRnZXRQYXJlbnRdKCkgewogICAgcmV0dXJuIHRoaXNbX3BhcmVudF07CiAgfQogIFskZ2V0U3ViZm9ybVBhcmVudF0oKSB7CiAgICByZXR1cm4gdGhpc1skZ2V0UGFyZW50XSgpOwogIH0KICBbJGdldENoaWxkcmVuXShuYW1lID0gbnVsbCkgewogICAgaWYgKCFuYW1lKSB7CiAgICAgIHJldHVybiB0aGlzW19jaGlsZHJlbl07CiAgICB9CiAgICByZXR1cm4gdGhpc1tuYW1lXTsKICB9CiAgWyRkdW1wXSgpIHsKICAgIGNvbnN0IGR1bXBlZCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBpZiAodGhpc1skY29udGVudF0pIHsKICAgICAgZHVtcGVkLiRjb250ZW50ID0gdGhpc1skY29udGVudF07CiAgICB9CiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGhpcykpIHsKICAgICAgY29uc3QgdmFsdWUgPSB0aGlzW25hbWVdOwogICAgICBpZiAodmFsdWUgPT09IG51bGwpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBYRkFPYmplY3QpIHsKICAgICAgICBkdW1wZWRbbmFtZV0gPSB2YWx1ZVskZHVtcF0oKTsKICAgICAgfSBlbHNlIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFhGQU9iamVjdEFycmF5KSB7CiAgICAgICAgaWYgKCF2YWx1ZS5pc0VtcHR5KCkpIHsKICAgICAgICAgIGR1bXBlZFtuYW1lXSA9IHZhbHVlLmR1bXAoKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZHVtcGVkW25hbWVdID0gdmFsdWU7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBkdW1wZWQ7CiAgfQogIFskdG9TdHlsZV0oKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgWyR0b0hUTUxdKCkgewogICAgcmV0dXJuIEhUTUxSZXN1bHQuRU1QVFk7CiAgfQogICpbJGdldENvbnRhaW5lZENoaWxkcmVuXSgpIHsKICAgIGZvciAoY29uc3Qgbm9kZSBvZiB0aGlzWyRnZXRDaGlsZHJlbl0oKSkgewogICAgICB5aWVsZCBub2RlOwogICAgfQogIH0KICAqW19maWx0ZXJlZENoaWxkcmVuR2VuZXJhdG9yXShmaWx0ZXIsIGluY2x1ZGUpIHsKICAgIGZvciAoY29uc3Qgbm9kZSBvZiB0aGlzWyRnZXRDb250YWluZWRDaGlsZHJlbl0oKSkgewogICAgICBpZiAoIWZpbHRlciB8fCBpbmNsdWRlID09PSBmaWx0ZXIuaGFzKG5vZGVbJG5vZGVOYW1lXSkpIHsKICAgICAgICBjb25zdCBhdmFpbGFibGVTcGFjZSA9IHRoaXNbJGdldEF2YWlsYWJsZVNwYWNlXSgpOwogICAgICAgIGNvbnN0IHJlcyA9IG5vZGVbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpOwogICAgICAgIGlmICghcmVzLnN1Y2Nlc3MpIHsKICAgICAgICAgIHRoaXNbJGV4dHJhXS5mYWlsaW5nTm9kZSA9IG5vZGU7CiAgICAgICAgfQogICAgICAgIHlpZWxkIHJlczsKICAgICAgfQogICAgfQogIH0KICBbJGZsdXNoSFRNTF0oKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgWyRhZGRIVE1MXShodG1sLCBiYm94KSB7CiAgICB0aGlzWyRleHRyYV0uY2hpbGRyZW4ucHVzaChodG1sKTsKICB9CiAgWyRnZXRBdmFpbGFibGVTcGFjZV0oKSB7fQogIFskY2hpbGRyZW5Ub0hUTUxdKHsKICAgIGZpbHRlciA9IG51bGwsCiAgICBpbmNsdWRlID0gdHJ1ZQogIH0pIHsKICAgIGlmICghdGhpc1skZXh0cmFdLmdlbmVyYXRvcikgewogICAgICB0aGlzWyRleHRyYV0uZ2VuZXJhdG9yID0gdGhpc1tfZmlsdGVyZWRDaGlsZHJlbkdlbmVyYXRvcl0oZmlsdGVyLCBpbmNsdWRlKTsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IGF2YWlsYWJsZVNwYWNlID0gdGhpc1skZ2V0QXZhaWxhYmxlU3BhY2VdKCk7CiAgICAgIGNvbnN0IHJlcyA9IHRoaXNbJGV4dHJhXS5mYWlsaW5nTm9kZVskdG9IVE1MXShhdmFpbGFibGVTcGFjZSk7CiAgICAgIGlmICghcmVzLnN1Y2Nlc3MpIHsKICAgICAgICByZXR1cm4gcmVzOwogICAgICB9CiAgICAgIGlmIChyZXMuaHRtbCkgewogICAgICAgIHRoaXNbJGFkZEhUTUxdKHJlcy5odG1sLCByZXMuYmJveCk7CiAgICAgIH0KICAgICAgZGVsZXRlIHRoaXNbJGV4dHJhXS5mYWlsaW5nTm9kZTsKICAgIH0KICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIGNvbnN0IGdlbiA9IHRoaXNbJGV4dHJhXS5nZW5lcmF0b3IubmV4dCgpOwogICAgICBpZiAoZ2VuLmRvbmUpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBjb25zdCByZXMgPSBnZW4udmFsdWU7CiAgICAgIGlmICghcmVzLnN1Y2Nlc3MpIHsKICAgICAgICByZXR1cm4gcmVzOwogICAgICB9CiAgICAgIGlmIChyZXMuaHRtbCkgewogICAgICAgIHRoaXNbJGFkZEhUTUxdKHJlcy5odG1sLCByZXMuYmJveCk7CiAgICAgIH0KICAgIH0KICAgIHRoaXNbJGV4dHJhXS5nZW5lcmF0b3IgPSBudWxsOwogICAgcmV0dXJuIEhUTUxSZXN1bHQuRU1QVFk7CiAgfQogIFskc2V0U2V0QXR0cmlidXRlc10oYXR0cmlidXRlcykgewogICAgdGhpc1tfc2V0QXR0cmlidXRlc10gPSBuZXcgU2V0KE9iamVjdC5rZXlzKGF0dHJpYnV0ZXMpKTsKICB9CiAgW19nZXRVbnNldEF0dHJpYnV0ZXNdKHByb3RvQXR0cmlidXRlcykgewogICAgY29uc3QgYWxsQXR0ciA9IHRoaXNbX2F0dHJpYnV0ZU5hbWVzXTsKICAgIGNvbnN0IHNldEF0dHIgPSB0aGlzW19zZXRBdHRyaWJ1dGVzXTsKICAgIHJldHVybiBbLi4ucHJvdG9BdHRyaWJ1dGVzXS5maWx0ZXIoeCA9PiBhbGxBdHRyLmhhcyh4KSAmJiAhc2V0QXR0ci5oYXMoeCkpOwogIH0KICBbJHJlc29sdmVQcm90b3R5cGVzXShpZHMsIGFuY2VzdG9ycyA9IG5ldyBTZXQoKSkgewogICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzW19jaGlsZHJlbl0pIHsKICAgICAgY2hpbGRbX3Jlc29sdmVQcm90b3R5cGVzSGVscGVyXShpZHMsIGFuY2VzdG9ycyk7CiAgICB9CiAgfQogIFtfcmVzb2x2ZVByb3RvdHlwZXNIZWxwZXJdKGlkcywgYW5jZXN0b3JzKSB7CiAgICBjb25zdCBwcm90byA9IHRoaXNbX2dldFByb3RvdHlwZV0oaWRzLCBhbmNlc3RvcnMpOwogICAgaWYgKHByb3RvKSB7CiAgICAgIHRoaXNbX2FwcGx5UHJvdG90eXBlXShwcm90bywgaWRzLCBhbmNlc3RvcnMpOwogICAgfSBlbHNlIHsKICAgICAgdGhpc1skcmVzb2x2ZVByb3RvdHlwZXNdKGlkcywgYW5jZXN0b3JzKTsKICAgIH0KICB9CiAgW19nZXRQcm90b3R5cGVdKGlkcywgYW5jZXN0b3JzKSB7CiAgICBjb25zdCB7CiAgICAgIHVzZSwKICAgICAgdXNlaHJlZgogICAgfSA9IHRoaXM7CiAgICBpZiAoIXVzZSAmJiAhdXNlaHJlZikgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGxldCBwcm90byA9IG51bGw7CiAgICBsZXQgc29tRXhwcmVzc2lvbiA9IG51bGw7CiAgICBsZXQgaWQgPSBudWxsOwogICAgbGV0IHJlZiA9IHVzZTsKICAgIGlmICh1c2VocmVmKSB7CiAgICAgIHJlZiA9IHVzZWhyZWY7CiAgICAgIGlmICh1c2VocmVmLnN0YXJ0c1dpdGgoIiNzb20oIikgJiYgdXNlaHJlZi5lbmRzV2l0aCgiKSIpKSB7CiAgICAgICAgc29tRXhwcmVzc2lvbiA9IHVzZWhyZWYuc2xpY2UoIiNzb20oIi5sZW5ndGgsIC0xKTsKICAgICAgfSBlbHNlIGlmICh1c2VocmVmLnN0YXJ0c1dpdGgoIi4jc29tKCIpICYmIHVzZWhyZWYuZW5kc1dpdGgoIikiKSkgewogICAgICAgIHNvbUV4cHJlc3Npb24gPSB1c2VocmVmLnNsaWNlKCIuI3NvbSgiLmxlbmd0aCwgLTEpOwogICAgICB9IGVsc2UgaWYgKHVzZWhyZWYuc3RhcnRzV2l0aCgiIyIpKSB7CiAgICAgICAgaWQgPSB1c2VocmVmLnNsaWNlKDEpOwogICAgICB9IGVsc2UgaWYgKHVzZWhyZWYuc3RhcnRzV2l0aCgiLiMiKSkgewogICAgICAgIGlkID0gdXNlaHJlZi5zbGljZSgyKTsKICAgICAgfQogICAgfSBlbHNlIGlmICh1c2Uuc3RhcnRzV2l0aCgiIyIpKSB7CiAgICAgIGlkID0gdXNlLnNsaWNlKDEpOwogICAgfSBlbHNlIHsKICAgICAgc29tRXhwcmVzc2lvbiA9IHVzZTsKICAgIH0KICAgIHRoaXMudXNlID0gdGhpcy51c2VocmVmID0gIiI7CiAgICBpZiAoaWQpIHsKICAgICAgcHJvdG8gPSBpZHMuZ2V0KGlkKTsKICAgIH0gZWxzZSB7CiAgICAgIHByb3RvID0gc2VhcmNoTm9kZShpZHMuZ2V0KCRyb290KSwgdGhpcywgc29tRXhwcmVzc2lvbiwgdHJ1ZSwgZmFsc2UpOwogICAgICBpZiAocHJvdG8pIHsKICAgICAgICBwcm90byA9IHByb3RvWzBdOwogICAgICB9CiAgICB9CiAgICBpZiAoIXByb3RvKSB7CiAgICAgIHdhcm4oYFhGQSAtIEludmFsaWQgcHJvdG90eXBlIHJlZmVyZW5jZTogJHtyZWZ9LmApOwogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGlmIChwcm90b1skbm9kZU5hbWVdICE9PSB0aGlzWyRub2RlTmFtZV0pIHsKICAgICAgd2FybihgWEZBIC0gSW5jb21wYXRpYmxlIHByb3RvdHlwZTogJHtwcm90b1skbm9kZU5hbWVdfSAhPT0gJHt0aGlzWyRub2RlTmFtZV19LmApOwogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGlmIChhbmNlc3RvcnMuaGFzKHByb3RvKSkgewogICAgICB3YXJuKGBYRkEgLSBDeWNsZSBkZXRlY3RlZCBpbiBwcm90b3R5cGVzIHVzZS5gKTsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBhbmNlc3RvcnMuYWRkKHByb3RvKTsKICAgIGNvbnN0IHByb3RvUHJvdG8gPSBwcm90b1tfZ2V0UHJvdG90eXBlXShpZHMsIGFuY2VzdG9ycyk7CiAgICBpZiAocHJvdG9Qcm90bykgewogICAgICBwcm90b1tfYXBwbHlQcm90b3R5cGVdKHByb3RvUHJvdG8sIGlkcywgYW5jZXN0b3JzKTsKICAgIH0KICAgIHByb3RvWyRyZXNvbHZlUHJvdG90eXBlc10oaWRzLCBhbmNlc3RvcnMpOwogICAgYW5jZXN0b3JzLmRlbGV0ZShwcm90byk7CiAgICByZXR1cm4gcHJvdG87CiAgfQogIFtfYXBwbHlQcm90b3R5cGVdKHByb3RvLCBpZHMsIGFuY2VzdG9ycykgewogICAgaWYgKGFuY2VzdG9ycy5oYXMocHJvdG8pKSB7CiAgICAgIHdhcm4oYFhGQSAtIEN5Y2xlIGRldGVjdGVkIGluIHByb3RvdHlwZXMgdXNlLmApOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoIXRoaXNbJGNvbnRlbnRdICYmIHByb3RvWyRjb250ZW50XSkgewogICAgICB0aGlzWyRjb250ZW50XSA9IHByb3RvWyRjb250ZW50XTsKICAgIH0KICAgIGNvbnN0IG5ld0FuY2VzdG9ycyA9IG5ldyBTZXQoYW5jZXN0b3JzKTsKICAgIG5ld0FuY2VzdG9ycy5hZGQocHJvdG8pOwogICAgZm9yIChjb25zdCB1bnNldEF0dHJOYW1lIG9mIHRoaXNbX2dldFVuc2V0QXR0cmlidXRlc10ocHJvdG9bX3NldEF0dHJpYnV0ZXNdKSkgewogICAgICB0aGlzW3Vuc2V0QXR0ck5hbWVdID0gcHJvdG9bdW5zZXRBdHRyTmFtZV07CiAgICAgIGlmICh0aGlzW19zZXRBdHRyaWJ1dGVzXSkgewogICAgICAgIHRoaXNbX3NldEF0dHJpYnV0ZXNdLmFkZCh1bnNldEF0dHJOYW1lKTsKICAgICAgfQogICAgfQogICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpKSB7CiAgICAgIGlmICh0aGlzW19hdHRyaWJ1dGVOYW1lc10uaGFzKG5hbWUpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgdmFsdWUgPSB0aGlzW25hbWVdOwogICAgICBjb25zdCBwcm90b1ZhbHVlID0gcHJvdG9bbmFtZV07CiAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFhGQU9iamVjdEFycmF5KSB7CiAgICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiB2YWx1ZVtfY2hpbGRyZW5dKSB7CiAgICAgICAgICBjaGlsZFtfcmVzb2x2ZVByb3RvdHlwZXNIZWxwZXJdKGlkcywgYW5jZXN0b3JzKTsKICAgICAgICB9CiAgICAgICAgZm9yIChsZXQgaSA9IHZhbHVlW19jaGlsZHJlbl0ubGVuZ3RoLCBpaSA9IHByb3RvVmFsdWVbX2NoaWxkcmVuXS5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICBjb25zdCBjaGlsZCA9IHByb3RvW19jaGlsZHJlbl1baV1bJGNsb25lXSgpOwogICAgICAgICAgaWYgKHZhbHVlLnB1c2goY2hpbGQpKSB7CiAgICAgICAgICAgIGNoaWxkW19wYXJlbnRdID0gdGhpczsKICAgICAgICAgICAgdGhpc1tfY2hpbGRyZW5dLnB1c2goY2hpbGQpOwogICAgICAgICAgICBjaGlsZFtfcmVzb2x2ZVByb3RvdHlwZXNIZWxwZXJdKGlkcywgYW5jZXN0b3JzKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAodmFsdWUgIT09IG51bGwpIHsKICAgICAgICB2YWx1ZVskcmVzb2x2ZVByb3RvdHlwZXNdKGlkcywgYW5jZXN0b3JzKTsKICAgICAgICBpZiAocHJvdG9WYWx1ZSkgewogICAgICAgICAgdmFsdWVbX2FwcGx5UHJvdG90eXBlXShwcm90b1ZhbHVlLCBpZHMsIGFuY2VzdG9ycyk7CiAgICAgICAgfQogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChwcm90b1ZhbHVlICE9PSBudWxsKSB7CiAgICAgICAgY29uc3QgY2hpbGQgPSBwcm90b1ZhbHVlWyRjbG9uZV0oKTsKICAgICAgICBjaGlsZFtfcGFyZW50XSA9IHRoaXM7CiAgICAgICAgdGhpc1tuYW1lXSA9IGNoaWxkOwogICAgICAgIHRoaXNbX2NoaWxkcmVuXS5wdXNoKGNoaWxkKTsKICAgICAgICBjaGlsZFtfcmVzb2x2ZVByb3RvdHlwZXNIZWxwZXJdKGlkcywgYW5jZXN0b3JzKTsKICAgICAgfQogICAgfQogIH0KICBzdGF0aWMgW19jbG9uZUF0dHJpYnV0ZV0ob2JqKSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopKSB7CiAgICAgIHJldHVybiBvYmoubWFwKHggPT4gWEZBT2JqZWN0W19jbG9uZUF0dHJpYnV0ZV0oeCkpOwogICAgfQogICAgaWYgKHR5cGVvZiBvYmogPT09ICJvYmplY3QiICYmIG9iaiAhPT0gbnVsbCkgewogICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbih7fSwgb2JqKTsKICAgIH0KICAgIHJldHVybiBvYmo7CiAgfQogIFskY2xvbmVdKCkgewogICAgY29uc3QgY2xvbmUgPSBPYmplY3QuY3JlYXRlKE9iamVjdC5nZXRQcm90b3R5cGVPZih0aGlzKSk7CiAgICBmb3IgKGNvbnN0ICRzeW1ib2wgb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyh0aGlzKSkgewogICAgICB0cnkgewogICAgICAgIGNsb25lWyRzeW1ib2xdID0gdGhpc1skc3ltYm9sXTsKICAgICAgfSBjYXRjaCB7CiAgICAgICAgc2hhZG93KGNsb25lLCAkc3ltYm9sLCB0aGlzWyRzeW1ib2xdKTsKICAgICAgfQogICAgfQogICAgY2xvbmVbJHVpZF0gPSBgJHtjbG9uZVskbm9kZU5hbWVdfSR7dWlkKyt9YDsKICAgIGNsb25lW19jaGlsZHJlbl0gPSBbXTsKICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKSkgewogICAgICBpZiAodGhpc1tfYXR0cmlidXRlTmFtZXNdLmhhcyhuYW1lKSkgewogICAgICAgIGNsb25lW25hbWVdID0gWEZBT2JqZWN0W19jbG9uZUF0dHJpYnV0ZV0odGhpc1tuYW1lXSk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgdmFsdWUgPSB0aGlzW25hbWVdOwogICAgICBjbG9uZVtuYW1lXSA9IHZhbHVlIGluc3RhbmNlb2YgWEZBT2JqZWN0QXJyYXkgPyBuZXcgWEZBT2JqZWN0QXJyYXkodmFsdWVbX21heF0pIDogbnVsbDsKICAgIH0KICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpc1tfY2hpbGRyZW5dKSB7CiAgICAgIGNvbnN0IG5hbWUgPSBjaGlsZFskbm9kZU5hbWVdOwogICAgICBjb25zdCBjbG9uZWRDaGlsZCA9IGNoaWxkWyRjbG9uZV0oKTsKICAgICAgY2xvbmVbX2NoaWxkcmVuXS5wdXNoKGNsb25lZENoaWxkKTsKICAgICAgY2xvbmVkQ2hpbGRbX3BhcmVudF0gPSBjbG9uZTsKICAgICAgaWYgKGNsb25lW25hbWVdID09PSBudWxsKSB7CiAgICAgICAgY2xvbmVbbmFtZV0gPSBjbG9uZWRDaGlsZDsKICAgICAgfSBlbHNlIHsKICAgICAgICBjbG9uZVtuYW1lXVtfY2hpbGRyZW5dLnB1c2goY2xvbmVkQ2hpbGQpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gY2xvbmU7CiAgfQogIFskZ2V0Q2hpbGRyZW5dKG5hbWUgPSBudWxsKSB7CiAgICBpZiAoIW5hbWUpIHsKICAgICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXTsKICAgIH0KICAgIHJldHVybiB0aGlzW19jaGlsZHJlbl0uZmlsdGVyKGMgPT4gY1skbm9kZU5hbWVdID09PSBuYW1lKTsKICB9CiAgWyRnZXRDaGlsZHJlbkJ5Q2xhc3NdKG5hbWUpIHsKICAgIHJldHVybiB0aGlzW25hbWVdOwogIH0KICBbJGdldENoaWxkcmVuQnlOYW1lXShuYW1lLCBhbGxUcmFuc3BhcmVudCwgZmlyc3QgPSB0cnVlKSB7CiAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzWyRnZXRDaGlsZHJlbkJ5TmFtZUl0XShuYW1lLCBhbGxUcmFuc3BhcmVudCwgZmlyc3QpKTsKICB9CiAgKlskZ2V0Q2hpbGRyZW5CeU5hbWVJdF0obmFtZSwgYWxsVHJhbnNwYXJlbnQsIGZpcnN0ID0gdHJ1ZSkgewogICAgaWYgKG5hbWUgPT09ICJwYXJlbnQiKSB7CiAgICAgIHlpZWxkIHRoaXNbX3BhcmVudF07CiAgICAgIHJldHVybjsKICAgIH0KICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpc1tfY2hpbGRyZW5dKSB7CiAgICAgIGlmIChjaGlsZFskbm9kZU5hbWVdID09PSBuYW1lKSB7CiAgICAgICAgeWllbGQgY2hpbGQ7CiAgICAgIH0KICAgICAgaWYgKGNoaWxkLm5hbWUgPT09IG5hbWUpIHsKICAgICAgICB5aWVsZCBjaGlsZDsKICAgICAgfQogICAgICBpZiAoYWxsVHJhbnNwYXJlbnQgfHwgY2hpbGRbJGlzVHJhbnNwYXJlbnRdKCkpIHsKICAgICAgICB5aWVsZCogY2hpbGRbJGdldENoaWxkcmVuQnlOYW1lSXRdKG5hbWUsIGFsbFRyYW5zcGFyZW50LCBmYWxzZSk7CiAgICAgIH0KICAgIH0KICAgIGlmIChmaXJzdCAmJiB0aGlzW19hdHRyaWJ1dGVOYW1lc10uaGFzKG5hbWUpKSB7CiAgICAgIHlpZWxkIG5ldyBYRkFBdHRyaWJ1dGUodGhpcywgbmFtZSwgdGhpc1tuYW1lXSk7CiAgICB9CiAgfQp9CmNsYXNzIFhGQU9iamVjdEFycmF5IHsKICBjb25zdHJ1Y3RvcihtYXggPSBJbmZpbml0eSkgewogICAgdGhpc1tfbWF4XSA9IG1heDsKICAgIHRoaXNbX2NoaWxkcmVuXSA9IFtdOwogIH0KICBnZXQgaXNYRkFPYmplY3QoKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGdldCBpc1hGQU9iamVjdEFycmF5KCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIHB1c2goY2hpbGQpIHsKICAgIGNvbnN0IGxlbiA9IHRoaXNbX2NoaWxkcmVuXS5sZW5ndGg7CiAgICBpZiAobGVuIDw9IHRoaXNbX21heF0pIHsKICAgICAgdGhpc1tfY2hpbGRyZW5dLnB1c2goY2hpbGQpOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHdhcm4oYFhGQSAtIG5vZGUgIiR7Y2hpbGRbJG5vZGVOYW1lXX0iIGFjY2VwdHMgbm8gbW9yZSB0aGFuICR7dGhpc1tfbWF4XX0gY2hpbGRyZW5gKTsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgaXNFbXB0eSgpIHsKICAgIHJldHVybiB0aGlzW19jaGlsZHJlbl0ubGVuZ3RoID09PSAwOwogIH0KICBkdW1wKCkgewogICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXS5sZW5ndGggPT09IDEgPyB0aGlzW19jaGlsZHJlbl1bMF1bJGR1bXBdKCkgOiB0aGlzW19jaGlsZHJlbl0ubWFwKHggPT4geFskZHVtcF0oKSk7CiAgfQogIFskY2xvbmVdKCkgewogICAgY29uc3QgY2xvbmUgPSBuZXcgWEZBT2JqZWN0QXJyYXkodGhpc1tfbWF4XSk7CiAgICBjbG9uZVtfY2hpbGRyZW5dID0gdGhpc1tfY2hpbGRyZW5dLm1hcChjID0+IGNbJGNsb25lXSgpKTsKICAgIHJldHVybiBjbG9uZTsKICB9CiAgZ2V0IGNoaWxkcmVuKCkgewogICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXTsKICB9CiAgY2xlYXIoKSB7CiAgICB0aGlzW19jaGlsZHJlbl0ubGVuZ3RoID0gMDsKICB9Cn0KY2xhc3MgWEZBQXR0cmlidXRlIHsKICBjb25zdHJ1Y3Rvcihub2RlLCBuYW1lLCB2YWx1ZSkgewogICAgdGhpc1tfcGFyZW50XSA9IG5vZGU7CiAgICB0aGlzWyRub2RlTmFtZV0gPSBuYW1lOwogICAgdGhpc1skY29udGVudF0gPSB2YWx1ZTsKICAgIHRoaXNbJGNvbnN1bWVkXSA9IGZhbHNlOwogICAgdGhpc1skdWlkXSA9IGBhdHRyaWJ1dGUke3VpZCsrfWA7CiAgfQogIFskZ2V0UGFyZW50XSgpIHsKICAgIHJldHVybiB0aGlzW19wYXJlbnRdOwogIH0KICBbJGlzRGF0YVZhbHVlXSgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICBbJGdldERhdGFWYWx1ZV0oKSB7CiAgICByZXR1cm4gdGhpc1skY29udGVudF0udHJpbSgpOwogIH0KICBbJHNldFZhbHVlXSh2YWx1ZSkgewogICAgdmFsdWUgPSB2YWx1ZS52YWx1ZSB8fCAiIjsKICAgIHRoaXNbJGNvbnRlbnRdID0gdmFsdWUudG9TdHJpbmcoKTsKICB9CiAgWyR0ZXh0XSgpIHsKICAgIHJldHVybiB0aGlzWyRjb250ZW50XTsKICB9CiAgWyRpc0Rlc2NlbmRlbnRdKHBhcmVudCkgewogICAgcmV0dXJuIHRoaXNbX3BhcmVudF0gPT09IHBhcmVudCB8fCB0aGlzW19wYXJlbnRdWyRpc0Rlc2NlbmRlbnRdKHBhcmVudCk7CiAgfQp9CmNsYXNzIFhtbE9iamVjdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IobnNJZCwgbmFtZSwgYXR0cmlidXRlcyA9IHt9KSB7CiAgICBzdXBlcihuc0lkLCBuYW1lKTsKICAgIHRoaXNbJGNvbnRlbnRdID0gIiI7CiAgICB0aGlzW19kYXRhVmFsdWVdID0gbnVsbDsKICAgIGlmIChuYW1lICE9PSAiI3RleHQiKSB7CiAgICAgIGNvbnN0IG1hcCA9IG5ldyBNYXAoKTsKICAgICAgdGhpc1tfYXR0cmlidXRlc10gPSBtYXA7CiAgICAgIGZvciAoY29uc3QgW2F0dHJOYW1lLCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoYXR0cmlidXRlcykpIHsKICAgICAgICBtYXAuc2V0KGF0dHJOYW1lLCBuZXcgWEZBQXR0cmlidXRlKHRoaXMsIGF0dHJOYW1lLCB2YWx1ZSkpOwogICAgICB9CiAgICAgIGlmIChhdHRyaWJ1dGVzLmhhc093blByb3BlcnR5KCRuc0F0dHJpYnV0ZXMpKSB7CiAgICAgICAgY29uc3QgZGF0YU5vZGUgPSBhdHRyaWJ1dGVzWyRuc0F0dHJpYnV0ZXNdLnhmYS5kYXRhTm9kZTsKICAgICAgICBpZiAoZGF0YU5vZGUgIT09IHVuZGVmaW5lZCkgewogICAgICAgICAgaWYgKGRhdGFOb2RlID09PSAiZGF0YUdyb3VwIikgewogICAgICAgICAgICB0aGlzW19kYXRhVmFsdWVdID0gZmFsc2U7CiAgICAgICAgICB9IGVsc2UgaWYgKGRhdGFOb2RlID09PSAiZGF0YVZhbHVlIikgewogICAgICAgICAgICB0aGlzW19kYXRhVmFsdWVdID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHRoaXNbJGNvbnN1bWVkXSA9IGZhbHNlOwogIH0KICBbJHRvU3RyaW5nXShidWYpIHsKICAgIGNvbnN0IHRhZ05hbWUgPSB0aGlzWyRub2RlTmFtZV07CiAgICBpZiAodGFnTmFtZSA9PT0gIiN0ZXh0IikgewogICAgICBidWYucHVzaChlbmNvZGVUb1htbFN0cmluZyh0aGlzWyRjb250ZW50XSkpOwogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCB1dGY4VGFnTmFtZSA9IHV0ZjhTdHJpbmdUb1N0cmluZyh0YWdOYW1lKTsKICAgIGNvbnN0IHByZWZpeCA9IHRoaXNbJG5hbWVzcGFjZUlkXSA9PT0gTlNfREFUQVNFVFMgPyAieGZhOiIgOiAiIjsKICAgIGJ1Zi5wdXNoKGA8JHtwcmVmaXh9JHt1dGY4VGFnTmFtZX1gKTsKICAgIGZvciAoY29uc3QgW25hbWUsIHZhbHVlXSBvZiB0aGlzW19hdHRyaWJ1dGVzXS5lbnRyaWVzKCkpIHsKICAgICAgY29uc3QgdXRmOE5hbWUgPSB1dGY4U3RyaW5nVG9TdHJpbmcobmFtZSk7CiAgICAgIGJ1Zi5wdXNoKGAgJHt1dGY4TmFtZX09IiR7ZW5jb2RlVG9YbWxTdHJpbmcodmFsdWVbJGNvbnRlbnRdKX0iYCk7CiAgICB9CiAgICBpZiAodGhpc1tfZGF0YVZhbHVlXSAhPT0gbnVsbCkgewogICAgICBpZiAodGhpc1tfZGF0YVZhbHVlXSkgewogICAgICAgIGJ1Zi5wdXNoKGAgeGZhOmRhdGFOb2RlPSJkYXRhVmFsdWUiYCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgYnVmLnB1c2goYCB4ZmE6ZGF0YU5vZGU9ImRhdGFHcm91cCJgKTsKICAgICAgfQogICAgfQogICAgaWYgKCF0aGlzWyRjb250ZW50XSAmJiB0aGlzW19jaGlsZHJlbl0ubGVuZ3RoID09PSAwKSB7CiAgICAgIGJ1Zi5wdXNoKCIvPiIpOwogICAgICByZXR1cm47CiAgICB9CiAgICBidWYucHVzaCgiPiIpOwogICAgaWYgKHRoaXNbJGNvbnRlbnRdKSB7CiAgICAgIGlmICh0eXBlb2YgdGhpc1skY29udGVudF0gPT09ICJzdHJpbmciKSB7CiAgICAgICAgYnVmLnB1c2goZW5jb2RlVG9YbWxTdHJpbmcodGhpc1skY29udGVudF0pKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzWyRjb250ZW50XVskdG9TdHJpbmddKGJ1Zik7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpc1tfY2hpbGRyZW5dKSB7CiAgICAgICAgY2hpbGRbJHRvU3RyaW5nXShidWYpOwogICAgICB9CiAgICB9CiAgICBidWYucHVzaChgPC8ke3ByZWZpeH0ke3V0ZjhUYWdOYW1lfT5gKTsKICB9CiAgWyRvbkNoaWxkXShjaGlsZCkgewogICAgaWYgKHRoaXNbJGNvbnRlbnRdKSB7CiAgICAgIGNvbnN0IG5vZGUgPSBuZXcgWG1sT2JqZWN0KHRoaXNbJG5hbWVzcGFjZUlkXSwgIiN0ZXh0Iik7CiAgICAgIHRoaXNbJGFwcGVuZENoaWxkXShub2RlKTsKICAgICAgbm9kZVskY29udGVudF0gPSB0aGlzWyRjb250ZW50XTsKICAgICAgdGhpc1skY29udGVudF0gPSAiIjsKICAgIH0KICAgIHRoaXNbJGFwcGVuZENoaWxkXShjaGlsZCk7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgWyRvblRleHRdKHN0cikgewogICAgdGhpc1skY29udGVudF0gKz0gc3RyOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIGlmICh0aGlzWyRjb250ZW50XSAmJiB0aGlzW19jaGlsZHJlbl0ubGVuZ3RoID4gMCkgewogICAgICBjb25zdCBub2RlID0gbmV3IFhtbE9iamVjdCh0aGlzWyRuYW1lc3BhY2VJZF0sICIjdGV4dCIpOwogICAgICB0aGlzWyRhcHBlbmRDaGlsZF0obm9kZSk7CiAgICAgIG5vZGVbJGNvbnRlbnRdID0gdGhpc1skY29udGVudF07CiAgICAgIGRlbGV0ZSB0aGlzWyRjb250ZW50XTsKICAgIH0KICB9CiAgWyR0b0hUTUxdKCkgewogICAgaWYgKHRoaXNbJG5vZGVOYW1lXSA9PT0gIiN0ZXh0IikgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgICBuYW1lOiAiI3RleHQiLAogICAgICAgIHZhbHVlOiB0aGlzWyRjb250ZW50XQogICAgICB9KTsKICAgIH0KICAgIHJldHVybiBIVE1MUmVzdWx0LkVNUFRZOwogIH0KICBbJGdldENoaWxkcmVuXShuYW1lID0gbnVsbCkgewogICAgaWYgKCFuYW1lKSB7CiAgICAgIHJldHVybiB0aGlzW19jaGlsZHJlbl07CiAgICB9CiAgICByZXR1cm4gdGhpc1tfY2hpbGRyZW5dLmZpbHRlcihjID0+IGNbJG5vZGVOYW1lXSA9PT0gbmFtZSk7CiAgfQogIFskZ2V0QXR0cmlidXRlc10oKSB7CiAgICByZXR1cm4gdGhpc1tfYXR0cmlidXRlc107CiAgfQogIFskZ2V0Q2hpbGRyZW5CeUNsYXNzXShuYW1lKSB7CiAgICBjb25zdCB2YWx1ZSA9IHRoaXNbX2F0dHJpYnV0ZXNdLmdldChuYW1lKTsKICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiB2YWx1ZTsKICAgIH0KICAgIHJldHVybiB0aGlzWyRnZXRDaGlsZHJlbl0obmFtZSk7CiAgfQogICpbJGdldENoaWxkcmVuQnlOYW1lSXRdKG5hbWUsIGFsbFRyYW5zcGFyZW50KSB7CiAgICBjb25zdCB2YWx1ZSA9IHRoaXNbX2F0dHJpYnV0ZXNdLmdldChuYW1lKTsKICAgIGlmICh2YWx1ZSkgewogICAgICB5aWVsZCB2YWx1ZTsKICAgIH0KICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpc1tfY2hpbGRyZW5dKSB7CiAgICAgIGlmIChjaGlsZFskbm9kZU5hbWVdID09PSBuYW1lKSB7CiAgICAgICAgeWllbGQgY2hpbGQ7CiAgICAgIH0KICAgICAgaWYgKGFsbFRyYW5zcGFyZW50KSB7CiAgICAgICAgeWllbGQqIGNoaWxkWyRnZXRDaGlsZHJlbkJ5TmFtZUl0XShuYW1lLCBhbGxUcmFuc3BhcmVudCk7CiAgICAgIH0KICAgIH0KICB9CiAgKlskZ2V0QXR0cmlidXRlSXRdKG5hbWUsIHNraXBDb25zdW1lZCkgewogICAgY29uc3QgdmFsdWUgPSB0aGlzW19hdHRyaWJ1dGVzXS5nZXQobmFtZSk7CiAgICBpZiAodmFsdWUgJiYgKCFza2lwQ29uc3VtZWQgfHwgIXZhbHVlWyRjb25zdW1lZF0pKSB7CiAgICAgIHlpZWxkIHZhbHVlOwogICAgfQogICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzW19jaGlsZHJlbl0pIHsKICAgICAgeWllbGQqIGNoaWxkWyRnZXRBdHRyaWJ1dGVJdF0obmFtZSwgc2tpcENvbnN1bWVkKTsKICAgIH0KICB9CiAgKlskZ2V0UmVhbENoaWxkcmVuQnlOYW1lSXRdKG5hbWUsIGFsbFRyYW5zcGFyZW50LCBza2lwQ29uc3VtZWQpIHsKICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpc1tfY2hpbGRyZW5dKSB7CiAgICAgIGlmIChjaGlsZFskbm9kZU5hbWVdID09PSBuYW1lICYmICghc2tpcENvbnN1bWVkIHx8ICFjaGlsZFskY29uc3VtZWRdKSkgewogICAgICAgIHlpZWxkIGNoaWxkOwogICAgICB9CiAgICAgIGlmIChhbGxUcmFuc3BhcmVudCkgewogICAgICAgIHlpZWxkKiBjaGlsZFskZ2V0UmVhbENoaWxkcmVuQnlOYW1lSXRdKG5hbWUsIGFsbFRyYW5zcGFyZW50LCBza2lwQ29uc3VtZWQpOwogICAgICB9CiAgICB9CiAgfQogIFskaXNEYXRhVmFsdWVdKCkgewogICAgaWYgKHRoaXNbX2RhdGFWYWx1ZV0gPT09IG51bGwpIHsKICAgICAgcmV0dXJuIHRoaXNbX2NoaWxkcmVuXS5sZW5ndGggPT09IDAgfHwgdGhpc1tfY2hpbGRyZW5dWzBdWyRuYW1lc3BhY2VJZF0gPT09IE5hbWVzcGFjZUlkcy54aHRtbC5pZDsKICAgIH0KICAgIHJldHVybiB0aGlzW19kYXRhVmFsdWVdOwogIH0KICBbJGdldERhdGFWYWx1ZV0oKSB7CiAgICBpZiAodGhpc1tfZGF0YVZhbHVlXSA9PT0gbnVsbCkgewogICAgICBpZiAodGhpc1tfY2hpbGRyZW5dLmxlbmd0aCA9PT0gMCkgewogICAgICAgIHJldHVybiB0aGlzWyRjb250ZW50XS50cmltKCk7CiAgICAgIH0KICAgICAgaWYgKHRoaXNbX2NoaWxkcmVuXVswXVskbmFtZXNwYWNlSWRdID09PSBOYW1lc3BhY2VJZHMueGh0bWwuaWQpIHsKICAgICAgICByZXR1cm4gdGhpc1tfY2hpbGRyZW5dWzBdWyR0ZXh0XSgpLnRyaW0oKTsKICAgICAgfQogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIHJldHVybiB0aGlzWyRjb250ZW50XS50cmltKCk7CiAgfQogIFskc2V0VmFsdWVdKHZhbHVlKSB7CiAgICB2YWx1ZSA9IHZhbHVlLnZhbHVlIHx8ICIiOwogICAgdGhpc1skY29udGVudF0gPSB2YWx1ZS50b1N0cmluZygpOwogIH0KICBbJGR1bXBdKGhhc05TID0gZmFsc2UpIHsKICAgIGNvbnN0IGR1bXBlZCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBpZiAoaGFzTlMpIHsKICAgICAgZHVtcGVkLiRucyA9IHRoaXNbJG5hbWVzcGFjZUlkXTsKICAgIH0KICAgIGlmICh0aGlzWyRjb250ZW50XSkgewogICAgICBkdW1wZWQuJGNvbnRlbnQgPSB0aGlzWyRjb250ZW50XTsKICAgIH0KICAgIGR1bXBlZC4kbmFtZSA9IHRoaXNbJG5vZGVOYW1lXTsKICAgIGR1bXBlZC5jaGlsZHJlbiA9IFtdOwogICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzW19jaGlsZHJlbl0pIHsKICAgICAgZHVtcGVkLmNoaWxkcmVuLnB1c2goY2hpbGRbJGR1bXBdKGhhc05TKSk7CiAgICB9CiAgICBkdW1wZWQuYXR0cmlidXRlcyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBmb3IgKGNvbnN0IFtuYW1lLCB2YWx1ZV0gb2YgdGhpc1tfYXR0cmlidXRlc10pIHsKICAgICAgZHVtcGVkLmF0dHJpYnV0ZXNbbmFtZV0gPSB2YWx1ZVskY29udGVudF07CiAgICB9CiAgICByZXR1cm4gZHVtcGVkOwogIH0KfQpjbGFzcyBDb250ZW50T2JqZWN0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3Rvcihuc0lkLCBuYW1lKSB7CiAgICBzdXBlcihuc0lkLCBuYW1lKTsKICAgIHRoaXNbJGNvbnRlbnRdID0gIiI7CiAgfQogIFskb25UZXh0XSh0ZXh0KSB7CiAgICB0aGlzWyRjb250ZW50XSArPSB0ZXh0OwogIH0KICBbJGZpbmFsaXplXSgpIHt9Cn0KY2xhc3MgT3B0aW9uT2JqZWN0IGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IobnNJZCwgbmFtZSwgb3B0aW9ucykgewogICAgc3VwZXIobnNJZCwgbmFtZSk7CiAgICB0aGlzW19vcHRpb25zXSA9IG9wdGlvbnM7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgdGhpc1skY29udGVudF0gPSBnZXRLZXl3b3JkKHsKICAgICAgZGF0YTogdGhpc1skY29udGVudF0sCiAgICAgIGRlZmF1bHRWYWx1ZTogdGhpc1tfb3B0aW9uc11bMF0sCiAgICAgIHZhbGlkYXRlOiBrID0+IHRoaXNbX29wdGlvbnNdLmluY2x1ZGVzKGspCiAgICB9KTsKICB9CiAgWyRjbGVhbl0oYnVpbGRlcikgewogICAgc3VwZXJbJGNsZWFuXShidWlsZGVyKTsKICAgIGRlbGV0ZSB0aGlzW19vcHRpb25zXTsKICB9Cn0KY2xhc3MgU3RyaW5nT2JqZWN0IGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzWyRjb250ZW50XSA9IHRoaXNbJGNvbnRlbnRdLnRyaW0oKTsKICB9Cn0KY2xhc3MgSW50ZWdlck9iamVjdCBleHRlbmRzIENvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKG5zSWQsIG5hbWUsIGRlZmF1bHRWYWx1ZSwgdmFsaWRhdG9yKSB7CiAgICBzdXBlcihuc0lkLCBuYW1lKTsKICAgIHRoaXNbX2RlZmF1bHRWYWx1ZV0gPSBkZWZhdWx0VmFsdWU7CiAgICB0aGlzW192YWxpZGF0b3JdID0gdmFsaWRhdG9yOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIHRoaXNbJGNvbnRlbnRdID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IHRoaXNbJGNvbnRlbnRdLAogICAgICBkZWZhdWx0VmFsdWU6IHRoaXNbX2RlZmF1bHRWYWx1ZV0sCiAgICAgIHZhbGlkYXRlOiB0aGlzW192YWxpZGF0b3JdCiAgICB9KTsKICB9CiAgWyRjbGVhbl0oYnVpbGRlcikgewogICAgc3VwZXJbJGNsZWFuXShidWlsZGVyKTsKICAgIGRlbGV0ZSB0aGlzW19kZWZhdWx0VmFsdWVdOwogICAgZGVsZXRlIHRoaXNbX3ZhbGlkYXRvcl07CiAgfQp9CmNsYXNzIE9wdGlvbjAxIGV4dGVuZHMgSW50ZWdlck9iamVjdCB7CiAgY29uc3RydWN0b3IobnNJZCwgbmFtZSkgewogICAgc3VwZXIobnNJZCwgbmFtZSwgMCwgbiA9PiBuID09PSAxKTsKICB9Cn0KY2xhc3MgT3B0aW9uMTAgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3Rvcihuc0lkLCBuYW1lKSB7CiAgICBzdXBlcihuc0lkLCBuYW1lLCAxLCBuID0+IG4gPT09IDApOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveGZhL2h0bWxfdXRpbHMuanMKCgoKCgoKCgoKCmZ1bmN0aW9uIG1lYXN1cmVUb1N0cmluZyhtKSB7CiAgaWYgKHR5cGVvZiBtID09PSAic3RyaW5nIikgewogICAgcmV0dXJuICIwcHgiOwogIH0KICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcihtKSA/IGAke219cHhgIDogYCR7bS50b0ZpeGVkKDIpfXB4YDsKfQpjb25zdCBjb252ZXJ0ZXJzID0gewogIGFuY2hvclR5cGUobm9kZSwgc3R5bGUpIHsKICAgIGNvbnN0IHBhcmVudCA9IG5vZGVbJGdldFN1YmZvcm1QYXJlbnRdKCk7CiAgICBpZiAoIXBhcmVudCB8fCBwYXJlbnQubGF5b3V0ICYmIHBhcmVudC5sYXlvdXQgIT09ICJwb3NpdGlvbiIpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKCEoInRyYW5zZm9ybSIgaW4gc3R5bGUpKSB7CiAgICAgIHN0eWxlLnRyYW5zZm9ybSA9ICIiOwogICAgfQogICAgc3dpdGNoIChub2RlLmFuY2hvclR5cGUpIHsKICAgICAgY2FzZSAiYm90dG9tQ2VudGVyIjoKICAgICAgICBzdHlsZS50cmFuc2Zvcm0gKz0gInRyYW5zbGF0ZSgtNTAlLCAtMTAwJSkiOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJib3R0b21MZWZ0IjoKICAgICAgICBzdHlsZS50cmFuc2Zvcm0gKz0gInRyYW5zbGF0ZSgwLC0xMDAlKSI7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgImJvdHRvbVJpZ2h0IjoKICAgICAgICBzdHlsZS50cmFuc2Zvcm0gKz0gInRyYW5zbGF0ZSgtMTAwJSwtMTAwJSkiOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJtaWRkbGVDZW50ZXIiOgogICAgICAgIHN0eWxlLnRyYW5zZm9ybSArPSAidHJhbnNsYXRlKC01MCUsLTUwJSkiOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJtaWRkbGVMZWZ0IjoKICAgICAgICBzdHlsZS50cmFuc2Zvcm0gKz0gInRyYW5zbGF0ZSgwLC01MCUpIjsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAibWlkZGxlUmlnaHQiOgogICAgICAgIHN0eWxlLnRyYW5zZm9ybSArPSAidHJhbnNsYXRlKC0xMDAlLC01MCUpIjsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAidG9wQ2VudGVyIjoKICAgICAgICBzdHlsZS50cmFuc2Zvcm0gKz0gInRyYW5zbGF0ZSgtNTAlLDApIjsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAidG9wUmlnaHQiOgogICAgICAgIHN0eWxlLnRyYW5zZm9ybSArPSAidHJhbnNsYXRlKC0xMDAlLDApIjsKICAgICAgICBicmVhazsKICAgIH0KICB9LAogIGRpbWVuc2lvbnMobm9kZSwgc3R5bGUpIHsKICAgIGNvbnN0IHBhcmVudCA9IG5vZGVbJGdldFN1YmZvcm1QYXJlbnRdKCk7CiAgICBsZXQgd2lkdGggPSBub2RlLnc7CiAgICBjb25zdCBoZWlnaHQgPSBub2RlLmg7CiAgICBpZiAocGFyZW50LmxheW91dD8uaW5jbHVkZXMoInJvdyIpKSB7CiAgICAgIGNvbnN0IGV4dHJhID0gcGFyZW50WyRleHRyYV07CiAgICAgIGNvbnN0IGNvbFNwYW4gPSBub2RlLmNvbFNwYW47CiAgICAgIGxldCB3OwogICAgICBpZiAoY29sU3BhbiA9PT0gLTEpIHsKICAgICAgICB3ID0gTWF0aC5zdW1QcmVjaXNlKGV4dHJhLmNvbHVtbldpZHRocy5zbGljZShleHRyYS5jdXJyZW50Q29sdW1uKSk7CiAgICAgICAgZXh0cmEuY3VycmVudENvbHVtbiA9IDA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdyA9IE1hdGguc3VtUHJlY2lzZShleHRyYS5jb2x1bW5XaWR0aHMuc2xpY2UoZXh0cmEuY3VycmVudENvbHVtbiwgZXh0cmEuY3VycmVudENvbHVtbiArIGNvbFNwYW4pKTsKICAgICAgICBleHRyYS5jdXJyZW50Q29sdW1uID0gKGV4dHJhLmN1cnJlbnRDb2x1bW4gKyBub2RlLmNvbFNwYW4pICUgZXh0cmEuY29sdW1uV2lkdGhzLmxlbmd0aDsKICAgICAgfQogICAgICBpZiAoIWlzTmFOKHcpKSB7CiAgICAgICAgd2lkdGggPSBub2RlLncgPSB3OwogICAgICB9CiAgICB9CiAgICBzdHlsZS53aWR0aCA9IHdpZHRoICE9PSAiIiA/IG1lYXN1cmVUb1N0cmluZyh3aWR0aCkgOiAiYXV0byI7CiAgICBzdHlsZS5oZWlnaHQgPSBoZWlnaHQgIT09ICIiID8gbWVhc3VyZVRvU3RyaW5nKGhlaWdodCkgOiAiYXV0byI7CiAgfSwKICBwb3NpdGlvbihub2RlLCBzdHlsZSkgewogICAgY29uc3QgcGFyZW50ID0gbm9kZVskZ2V0U3ViZm9ybVBhcmVudF0oKTsKICAgIGlmIChwYXJlbnQ/LmxheW91dCAmJiBwYXJlbnQubGF5b3V0ICE9PSAicG9zaXRpb24iKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHN0eWxlLnBvc2l0aW9uID0gImFic29sdXRlIjsKICAgIHN0eWxlLmxlZnQgPSBtZWFzdXJlVG9TdHJpbmcobm9kZS54KTsKICAgIHN0eWxlLnRvcCA9IG1lYXN1cmVUb1N0cmluZyhub2RlLnkpOwogIH0sCiAgcm90YXRlKG5vZGUsIHN0eWxlKSB7CiAgICBpZiAobm9kZS5yb3RhdGUpIHsKICAgICAgaWYgKCEoInRyYW5zZm9ybSIgaW4gc3R5bGUpKSB7CiAgICAgICAgc3R5bGUudHJhbnNmb3JtID0gIiI7CiAgICAgIH0KICAgICAgc3R5bGUudHJhbnNmb3JtICs9IGByb3RhdGUoLSR7bm9kZS5yb3RhdGV9ZGVnKWA7CiAgICAgIHN0eWxlLnRyYW5zZm9ybU9yaWdpbiA9ICJ0b3AgbGVmdCI7CiAgICB9CiAgfSwKICBwcmVzZW5jZShub2RlLCBzdHlsZSkgewogICAgc3dpdGNoIChub2RlLnByZXNlbmNlKSB7CiAgICAgIGNhc2UgImludmlzaWJsZSI6CiAgICAgICAgc3R5bGUudmlzaWJpbGl0eSA9ICJoaWRkZW4iOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJoaWRkZW4iOgogICAgICBjYXNlICJpbmFjdGl2ZSI6CiAgICAgICAgc3R5bGUuZGlzcGxheSA9ICJub25lIjsKICAgICAgICBicmVhazsKICAgIH0KICB9LAogIGhBbGlnbihub2RlLCBzdHlsZSkgewogICAgaWYgKG5vZGVbJG5vZGVOYW1lXSA9PT0gInBhcmEiKSB7CiAgICAgIHN3aXRjaCAobm9kZS5oQWxpZ24pIHsKICAgICAgICBjYXNlICJqdXN0aWZ5QWxsIjoKICAgICAgICAgIHN0eWxlLnRleHRBbGlnbiA9ICJqdXN0aWZ5LWFsbCI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJyYWRpeCI6CiAgICAgICAgICBzdHlsZS50ZXh0QWxpZ24gPSAibGVmdCI7CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgc3R5bGUudGV4dEFsaWduID0gbm9kZS5oQWxpZ247CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHN3aXRjaCAobm9kZS5oQWxpZ24pIHsKICAgICAgICBjYXNlICJsZWZ0IjoKICAgICAgICAgIHN0eWxlLmFsaWduU2VsZiA9ICJzdGFydCI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJjZW50ZXIiOgogICAgICAgICAgc3R5bGUuYWxpZ25TZWxmID0gImNlbnRlciI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJyaWdodCI6CiAgICAgICAgICBzdHlsZS5hbGlnblNlbGYgPSAiZW5kIjsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgfSwKICBtYXJnaW4obm9kZSwgc3R5bGUpIHsKICAgIGlmIChub2RlLm1hcmdpbikgewogICAgICBzdHlsZS5tYXJnaW4gPSBub2RlLm1hcmdpblskdG9TdHlsZV0oKS5tYXJnaW47CiAgICB9CiAgfQp9OwpmdW5jdGlvbiBzZXRNaW5NYXhEaW1lbnNpb25zKG5vZGUsIHN0eWxlKSB7CiAgY29uc3QgcGFyZW50ID0gbm9kZVskZ2V0U3ViZm9ybVBhcmVudF0oKTsKICBpZiAocGFyZW50LmxheW91dCA9PT0gInBvc2l0aW9uIikgewogICAgaWYgKG5vZGUubWluVyA+IDApIHsKICAgICAgc3R5bGUubWluV2lkdGggPSBtZWFzdXJlVG9TdHJpbmcobm9kZS5taW5XKTsKICAgIH0KICAgIGlmIChub2RlLm1heFcgPiAwKSB7CiAgICAgIHN0eWxlLm1heFdpZHRoID0gbWVhc3VyZVRvU3RyaW5nKG5vZGUubWF4Vyk7CiAgICB9CiAgICBpZiAobm9kZS5taW5IID4gMCkgewogICAgICBzdHlsZS5taW5IZWlnaHQgPSBtZWFzdXJlVG9TdHJpbmcobm9kZS5taW5IKTsKICAgIH0KICAgIGlmIChub2RlLm1heEggPiAwKSB7CiAgICAgIHN0eWxlLm1heEhlaWdodCA9IG1lYXN1cmVUb1N0cmluZyhub2RlLm1heEgpOwogICAgfQogIH0KfQpmdW5jdGlvbiBsYXlvdXRUZXh0KHRleHQsIHhmYUZvbnQsIG1hcmdpbiwgbGluZUhlaWdodCwgZm9udEZpbmRlciwgd2lkdGgpIHsKICBjb25zdCBtZWFzdXJlID0gbmV3IFRleHRNZWFzdXJlKHhmYUZvbnQsIG1hcmdpbiwgbGluZUhlaWdodCwgZm9udEZpbmRlcik7CiAgaWYgKHR5cGVvZiB0ZXh0ID09PSAic3RyaW5nIikgewogICAgbWVhc3VyZS5hZGRTdHJpbmcodGV4dCk7CiAgfSBlbHNlIHsKICAgIHRleHRbJHB1c2hHbHlwaHNdKG1lYXN1cmUpOwogIH0KICByZXR1cm4gbWVhc3VyZS5jb21wdXRlKHdpZHRoKTsKfQpmdW5jdGlvbiBsYXlvdXROb2RlKG5vZGUsIGF2YWlsYWJsZVNwYWNlKSB7CiAgbGV0IGhlaWdodCA9IG51bGw7CiAgbGV0IHdpZHRoID0gbnVsbDsKICBsZXQgaXNCcm9rZW4gPSBmYWxzZTsKICBpZiAoKCFub2RlLncgfHwgIW5vZGUuaCkgJiYgbm9kZS52YWx1ZSkgewogICAgbGV0IG1hcmdpbkggPSAwOwogICAgbGV0IG1hcmdpblYgPSAwOwogICAgaWYgKG5vZGUubWFyZ2luKSB7CiAgICAgIG1hcmdpbkggPSBub2RlLm1hcmdpbi5sZWZ0SW5zZXQgKyBub2RlLm1hcmdpbi5yaWdodEluc2V0OwogICAgICBtYXJnaW5WID0gbm9kZS5tYXJnaW4udG9wSW5zZXQgKyBub2RlLm1hcmdpbi5ib3R0b21JbnNldDsKICAgIH0KICAgIGxldCBsaW5lSGVpZ2h0ID0gbnVsbDsKICAgIGxldCBtYXJnaW4gPSBudWxsOwogICAgaWYgKG5vZGUucGFyYSkgewogICAgICBtYXJnaW4gPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgICBsaW5lSGVpZ2h0ID0gbm9kZS5wYXJhLmxpbmVIZWlnaHQgPT09ICIiID8gbnVsbCA6IG5vZGUucGFyYS5saW5lSGVpZ2h0OwogICAgICBtYXJnaW4udG9wID0gbm9kZS5wYXJhLnNwYWNlQWJvdmUgPT09ICIiID8gMCA6IG5vZGUucGFyYS5zcGFjZUFib3ZlOwogICAgICBtYXJnaW4uYm90dG9tID0gbm9kZS5wYXJhLnNwYWNlQmVsb3cgPT09ICIiID8gMCA6IG5vZGUucGFyYS5zcGFjZUJlbG93OwogICAgICBtYXJnaW4ubGVmdCA9IG5vZGUucGFyYS5tYXJnaW5MZWZ0ID09PSAiIiA/IDAgOiBub2RlLnBhcmEubWFyZ2luTGVmdDsKICAgICAgbWFyZ2luLnJpZ2h0ID0gbm9kZS5wYXJhLm1hcmdpblJpZ2h0ID09PSAiIiA/IDAgOiBub2RlLnBhcmEubWFyZ2luUmlnaHQ7CiAgICB9CiAgICBsZXQgZm9udCA9IG5vZGUuZm9udDsKICAgIGlmICghZm9udCkgewogICAgICBjb25zdCByb290ID0gbm9kZVskZ2V0VGVtcGxhdGVSb290XSgpOwogICAgICBsZXQgcGFyZW50ID0gbm9kZVskZ2V0UGFyZW50XSgpOwogICAgICB3aGlsZSAocGFyZW50ICYmIHBhcmVudCAhPT0gcm9vdCkgewogICAgICAgIGlmIChwYXJlbnQuZm9udCkgewogICAgICAgICAgZm9udCA9IHBhcmVudC5mb250OwogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHBhcmVudCA9IHBhcmVudFskZ2V0UGFyZW50XSgpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBtYXhXaWR0aCA9IChub2RlLncgfHwgYXZhaWxhYmxlU3BhY2Uud2lkdGgpIC0gbWFyZ2luSDsKICAgIGNvbnN0IGZvbnRGaW5kZXIgPSBub2RlWyRnbG9iYWxEYXRhXS5mb250RmluZGVyOwogICAgaWYgKG5vZGUudmFsdWUuZXhEYXRhICYmIG5vZGUudmFsdWUuZXhEYXRhWyRjb250ZW50XSAmJiBub2RlLnZhbHVlLmV4RGF0YS5jb250ZW50VHlwZSA9PT0gInRleHQvaHRtbCIpIHsKICAgICAgY29uc3QgcmVzID0gbGF5b3V0VGV4dChub2RlLnZhbHVlLmV4RGF0YVskY29udGVudF0sIGZvbnQsIG1hcmdpbiwgbGluZUhlaWdodCwgZm9udEZpbmRlciwgbWF4V2lkdGgpOwogICAgICB3aWR0aCA9IHJlcy53aWR0aDsKICAgICAgaGVpZ2h0ID0gcmVzLmhlaWdodDsKICAgICAgaXNCcm9rZW4gPSByZXMuaXNCcm9rZW47CiAgICB9IGVsc2UgewogICAgICBjb25zdCB0ZXh0ID0gbm9kZS52YWx1ZVskdGV4dF0oKTsKICAgICAgaWYgKHRleHQpIHsKICAgICAgICBjb25zdCByZXMgPSBsYXlvdXRUZXh0KHRleHQsIGZvbnQsIG1hcmdpbiwgbGluZUhlaWdodCwgZm9udEZpbmRlciwgbWF4V2lkdGgpOwogICAgICAgIHdpZHRoID0gcmVzLndpZHRoOwogICAgICAgIGhlaWdodCA9IHJlcy5oZWlnaHQ7CiAgICAgICAgaXNCcm9rZW4gPSByZXMuaXNCcm9rZW47CiAgICAgIH0KICAgIH0KICAgIGlmICh3aWR0aCAhPT0gbnVsbCAmJiAhbm9kZS53KSB7CiAgICAgIHdpZHRoICs9IG1hcmdpbkg7CiAgICB9CiAgICBpZiAoaGVpZ2h0ICE9PSBudWxsICYmICFub2RlLmgpIHsKICAgICAgaGVpZ2h0ICs9IG1hcmdpblY7CiAgICB9CiAgfQogIHJldHVybiB7CiAgICB3OiB3aWR0aCwKICAgIGg6IGhlaWdodCwKICAgIGlzQnJva2VuCiAgfTsKfQpmdW5jdGlvbiBjb21wdXRlQmJveChub2RlLCBodG1sLCBhdmFpbGFibGVTcGFjZSkgewogIGxldCBiYm94OwogIGlmIChub2RlLncgIT09ICIiICYmIG5vZGUuaCAhPT0gIiIpIHsKICAgIGJib3ggPSBbbm9kZS54LCBub2RlLnksIG5vZGUudywgbm9kZS5oXTsKICB9IGVsc2UgewogICAgaWYgKCFhdmFpbGFibGVTcGFjZSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGxldCB3aWR0aCA9IG5vZGUudzsKICAgIGlmICh3aWR0aCA9PT0gIiIpIHsKICAgICAgaWYgKG5vZGUubWF4VyA9PT0gMCkgewogICAgICAgIGNvbnN0IHBhcmVudCA9IG5vZGVbJGdldFN1YmZvcm1QYXJlbnRdKCk7CiAgICAgICAgd2lkdGggPSBwYXJlbnQubGF5b3V0ID09PSAicG9zaXRpb24iICYmIHBhcmVudC53ICE9PSAiIiA/IDAgOiBub2RlLm1pblc7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgd2lkdGggPSBNYXRoLm1pbihub2RlLm1heFcsIGF2YWlsYWJsZVNwYWNlLndpZHRoKTsKICAgICAgfQogICAgICBodG1sLmF0dHJpYnV0ZXMuc3R5bGUud2lkdGggPSBtZWFzdXJlVG9TdHJpbmcod2lkdGgpOwogICAgfQogICAgbGV0IGhlaWdodCA9IG5vZGUuaDsKICAgIGlmIChoZWlnaHQgPT09ICIiKSB7CiAgICAgIGlmIChub2RlLm1heEggPT09IDApIHsKICAgICAgICBjb25zdCBwYXJlbnQgPSBub2RlWyRnZXRTdWJmb3JtUGFyZW50XSgpOwogICAgICAgIGhlaWdodCA9IHBhcmVudC5sYXlvdXQgPT09ICJwb3NpdGlvbiIgJiYgcGFyZW50LmggIT09ICIiID8gMCA6IG5vZGUubWluSDsKICAgICAgfSBlbHNlIHsKICAgICAgICBoZWlnaHQgPSBNYXRoLm1pbihub2RlLm1heEgsIGF2YWlsYWJsZVNwYWNlLmhlaWdodCk7CiAgICAgIH0KICAgICAgaHRtbC5hdHRyaWJ1dGVzLnN0eWxlLmhlaWdodCA9IG1lYXN1cmVUb1N0cmluZyhoZWlnaHQpOwogICAgfQogICAgYmJveCA9IFtub2RlLngsIG5vZGUueSwgd2lkdGgsIGhlaWdodF07CiAgfQogIHJldHVybiBiYm94Owp9CmZ1bmN0aW9uIGZpeERpbWVuc2lvbnMobm9kZSkgewogIGNvbnN0IHBhcmVudCA9IG5vZGVbJGdldFN1YmZvcm1QYXJlbnRdKCk7CiAgaWYgKHBhcmVudC5sYXlvdXQ/LmluY2x1ZGVzKCJyb3ciKSkgewogICAgY29uc3QgZXh0cmEgPSBwYXJlbnRbJGV4dHJhXTsKICAgIGNvbnN0IGNvbFNwYW4gPSBub2RlLmNvbFNwYW47CiAgICBsZXQgd2lkdGg7CiAgICBpZiAoY29sU3BhbiA9PT0gLTEpIHsKICAgICAgd2lkdGggPSBNYXRoLnN1bVByZWNpc2UoZXh0cmEuY29sdW1uV2lkdGhzLnNsaWNlKGV4dHJhLmN1cnJlbnRDb2x1bW4pKTsKICAgIH0gZWxzZSB7CiAgICAgIHdpZHRoID0gTWF0aC5zdW1QcmVjaXNlKGV4dHJhLmNvbHVtbldpZHRocy5zbGljZShleHRyYS5jdXJyZW50Q29sdW1uLCBleHRyYS5jdXJyZW50Q29sdW1uICsgY29sU3BhbikpOwogICAgfQogICAgaWYgKCFpc05hTih3aWR0aCkpIHsKICAgICAgbm9kZS53ID0gd2lkdGg7CiAgICB9CiAgfQogIGlmIChwYXJlbnQubGF5b3V0ICYmIHBhcmVudC5sYXlvdXQgIT09ICJwb3NpdGlvbiIpIHsKICAgIG5vZGUueCA9IG5vZGUueSA9IDA7CiAgfQogIGlmIChub2RlLmxheW91dCA9PT0gInRhYmxlIikgewogICAgaWYgKG5vZGUudyA9PT0gIiIgJiYgQXJyYXkuaXNBcnJheShub2RlLmNvbHVtbldpZHRocykpIHsKICAgICAgbm9kZS53ID0gTWF0aC5zdW1QcmVjaXNlKG5vZGUuY29sdW1uV2lkdGhzKTsKICAgIH0KICB9Cn0KZnVuY3Rpb24gbGF5b3V0Q2xhc3Mobm9kZSkgewogIHN3aXRjaCAobm9kZS5sYXlvdXQpIHsKICAgIGNhc2UgInBvc2l0aW9uIjoKICAgICAgcmV0dXJuICJ4ZmFQb3NpdGlvbiI7CiAgICBjYXNlICJsci10YiI6CiAgICAgIHJldHVybiAieGZhTHJUYiI7CiAgICBjYXNlICJybC1yb3ciOgogICAgICByZXR1cm4gInhmYVJsUm93IjsKICAgIGNhc2UgInJsLXRiIjoKICAgICAgcmV0dXJuICJ4ZmFSbFRiIjsKICAgIGNhc2UgInJvdyI6CiAgICAgIHJldHVybiAieGZhUm93IjsKICAgIGNhc2UgInRhYmxlIjoKICAgICAgcmV0dXJuICJ4ZmFUYWJsZSI7CiAgICBjYXNlICJ0YiI6CiAgICAgIHJldHVybiAieGZhVGIiOwogICAgZGVmYXVsdDoKICAgICAgcmV0dXJuICJ4ZmFQb3NpdGlvbiI7CiAgfQp9CmZ1bmN0aW9uIHRvU3R5bGUobm9kZSwgLi4ubmFtZXMpIHsKICBjb25zdCBzdHlsZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgZm9yIChjb25zdCBuYW1lIG9mIG5hbWVzKSB7CiAgICBjb25zdCB2YWx1ZSA9IG5vZGVbbmFtZV07CiAgICBpZiAodmFsdWUgPT09IG51bGwpIHsKICAgICAgY29udGludWU7CiAgICB9CiAgICBpZiAoY29udmVydGVycy5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICBjb252ZXJ0ZXJzW25hbWVdKG5vZGUsIHN0eWxlKTsKICAgICAgY29udGludWU7CiAgICB9CiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBYRkFPYmplY3QpIHsKICAgICAgY29uc3QgbmV3U3R5bGUgPSB2YWx1ZVskdG9TdHlsZV0oKTsKICAgICAgaWYgKG5ld1N0eWxlKSB7CiAgICAgICAgT2JqZWN0LmFzc2lnbihzdHlsZSwgbmV3U3R5bGUpOwogICAgICB9IGVsc2UgewogICAgICAgIHdhcm4oYChERUJVRykgLSBYRkEgLSBzdHlsZSBmb3IgJHtuYW1lfSBub3QgaW1wbGVtZW50ZWQgeWV0YCk7CiAgICAgIH0KICAgIH0KICB9CiAgcmV0dXJuIHN0eWxlOwp9CmZ1bmN0aW9uIGNyZWF0ZVdyYXBwZXIobm9kZSwgaHRtbCkgewogIGNvbnN0IHsKICAgIGF0dHJpYnV0ZXMKICB9ID0gaHRtbDsKICBjb25zdCB7CiAgICBzdHlsZQogIH0gPSBhdHRyaWJ1dGVzOwogIGNvbnN0IHdyYXBwZXIgPSB7CiAgICBuYW1lOiAiZGl2IiwKICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgY2xhc3M6IFsieGZhV3JhcHBlciJdLAogICAgICBzdHlsZTogT2JqZWN0LmNyZWF0ZShudWxsKQogICAgfSwKICAgIGNoaWxkcmVuOiBbXQogIH07CiAgYXR0cmlidXRlcy5jbGFzcy5wdXNoKCJ4ZmFXcmFwcGVkIik7CiAgaWYgKG5vZGUuYm9yZGVyKSB7CiAgICBjb25zdCB7CiAgICAgIHdpZHRocywKICAgICAgaW5zZXRzCiAgICB9ID0gbm9kZS5ib3JkZXJbJGV4dHJhXTsKICAgIGxldCB3aWR0aCwgaGVpZ2h0OwogICAgbGV0IHRvcCA9IGluc2V0c1swXTsKICAgIGxldCBsZWZ0ID0gaW5zZXRzWzNdOwogICAgY29uc3QgaW5zZXRzSCA9IGluc2V0c1swXSArIGluc2V0c1syXTsKICAgIGNvbnN0IGluc2V0c1cgPSBpbnNldHNbMV0gKyBpbnNldHNbM107CiAgICBzd2l0Y2ggKG5vZGUuYm9yZGVyLmhhbmQpIHsKICAgICAgY2FzZSAiZXZlbiI6CiAgICAgICAgdG9wIC09IHdpZHRoc1swXSAvIDI7CiAgICAgICAgbGVmdCAtPSB3aWR0aHNbM10gLyAyOwogICAgICAgIHdpZHRoID0gYGNhbGMoMTAwJSArICR7KHdpZHRoc1sxXSArIHdpZHRoc1szXSkgLyAyIC0gaW5zZXRzV31weClgOwogICAgICAgIGhlaWdodCA9IGBjYWxjKDEwMCUgKyAkeyh3aWR0aHNbMF0gKyB3aWR0aHNbMl0pIC8gMiAtIGluc2V0c0h9cHgpYDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAibGVmdCI6CiAgICAgICAgdG9wIC09IHdpZHRoc1swXTsKICAgICAgICBsZWZ0IC09IHdpZHRoc1szXTsKICAgICAgICB3aWR0aCA9IGBjYWxjKDEwMCUgKyAke3dpZHRoc1sxXSArIHdpZHRoc1szXSAtIGluc2V0c1d9cHgpYDsKICAgICAgICBoZWlnaHQgPSBgY2FsYygxMDAlICsgJHt3aWR0aHNbMF0gKyB3aWR0aHNbMl0gLSBpbnNldHNIfXB4KWA7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgInJpZ2h0IjoKICAgICAgICB3aWR0aCA9IGluc2V0c1cgPyBgY2FsYygxMDAlIC0gJHtpbnNldHNXfXB4KWAgOiAiMTAwJSI7CiAgICAgICAgaGVpZ2h0ID0gaW5zZXRzSCA/IGBjYWxjKDEwMCUgLSAke2luc2V0c0h9cHgpYCA6ICIxMDAlIjsKICAgICAgICBicmVhazsKICAgIH0KICAgIGNvbnN0IGNsYXNzTmFtZXMgPSBbInhmYUJvcmRlciJdOwogICAgaWYgKGlzUHJpbnRPbmx5KG5vZGUuYm9yZGVyKSkgewogICAgICBjbGFzc05hbWVzLnB1c2goInhmYVByaW50T25seSIpOwogICAgfQogICAgY29uc3QgYm9yZGVyID0gewogICAgICBuYW1lOiAiZGl2IiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIGNsYXNzOiBjbGFzc05hbWVzLAogICAgICAgIHN0eWxlOiB7CiAgICAgICAgICB0b3A6IGAke3RvcH1weGAsCiAgICAgICAgICBsZWZ0OiBgJHtsZWZ0fXB4YCwKICAgICAgICAgIHdpZHRoLAogICAgICAgICAgaGVpZ2h0CiAgICAgICAgfQogICAgICB9LAogICAgICBjaGlsZHJlbjogW10KICAgIH07CiAgICBmb3IgKGNvbnN0IGtleSBvZiBbImJvcmRlciIsICJib3JkZXJXaWR0aCIsICJib3JkZXJDb2xvciIsICJib3JkZXJSYWRpdXMiLCAiYm9yZGVyU3R5bGUiXSkgewogICAgICBpZiAoc3R5bGVba2V5XSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgICAgYm9yZGVyLmF0dHJpYnV0ZXMuc3R5bGVba2V5XSA9IHN0eWxlW2tleV07CiAgICAgICAgZGVsZXRlIHN0eWxlW2tleV07CiAgICAgIH0KICAgIH0KICAgIHdyYXBwZXIuY2hpbGRyZW4ucHVzaChib3JkZXIsIGh0bWwpOwogIH0gZWxzZSB7CiAgICB3cmFwcGVyLmNoaWxkcmVuLnB1c2goaHRtbCk7CiAgfQogIGZvciAoY29uc3Qga2V5IG9mIFsiYmFja2dyb3VuZCIsICJiYWNrZ3JvdW5kQ2xpcCIsICJ0b3AiLCAibGVmdCIsICJ3aWR0aCIsICJoZWlnaHQiLCAibWluV2lkdGgiLCAibWluSGVpZ2h0IiwgIm1heFdpZHRoIiwgIm1heEhlaWdodCIsICJ0cmFuc2Zvcm0iLCAidHJhbnNmb3JtT3JpZ2luIiwgInZpc2liaWxpdHkiXSkgewogICAgaWYgKHN0eWxlW2tleV0gIT09IHVuZGVmaW5lZCkgewogICAgICB3cmFwcGVyLmF0dHJpYnV0ZXMuc3R5bGVba2V5XSA9IHN0eWxlW2tleV07CiAgICAgIGRlbGV0ZSBzdHlsZVtrZXldOwogICAgfQogIH0KICB3cmFwcGVyLmF0dHJpYnV0ZXMuc3R5bGUucG9zaXRpb24gPSBzdHlsZS5wb3NpdGlvbiA9PT0gImFic29sdXRlIiA/ICJhYnNvbHV0ZSIgOiAicmVsYXRpdmUiOwogIGRlbGV0ZSBzdHlsZS5wb3NpdGlvbjsKICBpZiAoc3R5bGUuYWxpZ25TZWxmKSB7CiAgICB3cmFwcGVyLmF0dHJpYnV0ZXMuc3R5bGUuYWxpZ25TZWxmID0gc3R5bGUuYWxpZ25TZWxmOwogICAgZGVsZXRlIHN0eWxlLmFsaWduU2VsZjsKICB9CiAgcmV0dXJuIHdyYXBwZXI7Cn0KZnVuY3Rpb24gZml4VGV4dEluZGVudChzdHlsZXMpIHsKICBjb25zdCBpbmRlbnQgPSBnZXRNZWFzdXJlbWVudChzdHlsZXMudGV4dEluZGVudCwgIjBweCIpOwogIGlmIChpbmRlbnQgPj0gMCkgewogICAgcmV0dXJuOwogIH0KICBjb25zdCBhbGlnbiA9IHN0eWxlcy50ZXh0QWxpZ24gPT09ICJyaWdodCIgPyAicmlnaHQiIDogImxlZnQiOwogIGNvbnN0IG5hbWUgPSAicGFkZGluZyIgKyAoYWxpZ24gPT09ICJsZWZ0IiA/ICJMZWZ0IiA6ICJSaWdodCIpOwogIGNvbnN0IHBhZGRpbmcgPSBnZXRNZWFzdXJlbWVudChzdHlsZXNbbmFtZV0sICIwcHgiKTsKICBzdHlsZXNbbmFtZV0gPSBgJHtwYWRkaW5nIC0gaW5kZW50fXB4YDsKfQpmdW5jdGlvbiBzZXRBY2Nlc3Mobm9kZSwgY2xhc3NOYW1lcykgewogIHN3aXRjaCAobm9kZS5hY2Nlc3MpIHsKICAgIGNhc2UgIm5vbkludGVyYWN0aXZlIjoKICAgICAgY2xhc3NOYW1lcy5wdXNoKCJ4ZmFOb25JbnRlcmFjdGl2ZSIpOwogICAgICBicmVhazsKICAgIGNhc2UgInJlYWRPbmx5IjoKICAgICAgY2xhc3NOYW1lcy5wdXNoKCJ4ZmFSZWFkT25seSIpOwogICAgICBicmVhazsKICAgIGNhc2UgInByb3RlY3RlZCI6CiAgICAgIGNsYXNzTmFtZXMucHVzaCgieGZhRGlzYWJsZWQiKTsKICAgICAgYnJlYWs7CiAgfQp9CmZ1bmN0aW9uIGlzUHJpbnRPbmx5KG5vZGUpIHsKICByZXR1cm4gbm9kZS5yZWxldmFudC5sZW5ndGggPiAwICYmICFub2RlLnJlbGV2YW50WzBdLmV4Y2x1ZGVkICYmIG5vZGUucmVsZXZhbnRbMF0udmlld25hbWUgPT09ICJwcmludCI7Cn0KZnVuY3Rpb24gZ2V0Q3VycmVudFBhcmEobm9kZSkgewogIGNvbnN0IHN0YWNrID0gbm9kZVskZ2V0VGVtcGxhdGVSb290XSgpWyRleHRyYV0ucGFyYVN0YWNrOwogIHJldHVybiBzdGFjay5sZW5ndGggPyBzdGFjay5hdCgtMSkgOiBudWxsOwp9CmZ1bmN0aW9uIHNldFBhcmEobm9kZSwgbm9kZVN0eWxlLCB2YWx1ZSkgewogIGlmICh2YWx1ZS5hdHRyaWJ1dGVzLmNsYXNzPy5pbmNsdWRlcygieGZhUmljaCIpKSB7CiAgICBpZiAobm9kZVN0eWxlKSB7CiAgICAgIGlmIChub2RlLmggPT09ICIiKSB7CiAgICAgICAgbm9kZVN0eWxlLmhlaWdodCA9ICJhdXRvIjsKICAgICAgfQogICAgICBpZiAobm9kZS53ID09PSAiIikgewogICAgICAgIG5vZGVTdHlsZS53aWR0aCA9ICJhdXRvIjsKICAgICAgfQogICAgfQogICAgY29uc3QgcGFyYSA9IGdldEN1cnJlbnRQYXJhKG5vZGUpOwogICAgaWYgKHBhcmEpIHsKICAgICAgY29uc3QgdmFsdWVTdHlsZSA9IHZhbHVlLmF0dHJpYnV0ZXMuc3R5bGU7CiAgICAgIHZhbHVlU3R5bGUuZGlzcGxheSA9ICJmbGV4IjsKICAgICAgdmFsdWVTdHlsZS5mbGV4RGlyZWN0aW9uID0gImNvbHVtbiI7CiAgICAgIHN3aXRjaCAocGFyYS52QWxpZ24pIHsKICAgICAgICBjYXNlICJ0b3AiOgogICAgICAgICAgdmFsdWVTdHlsZS5qdXN0aWZ5Q29udGVudCA9ICJzdGFydCI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJib3R0b20iOgogICAgICAgICAgdmFsdWVTdHlsZS5qdXN0aWZ5Q29udGVudCA9ICJlbmQiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibWlkZGxlIjoKICAgICAgICAgIHZhbHVlU3R5bGUuanVzdGlmeUNvbnRlbnQgPSAiY2VudGVyIjsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGNvbnN0IHBhcmFTdHlsZSA9IHBhcmFbJHRvU3R5bGVdKCk7CiAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsXSBvZiBPYmplY3QuZW50cmllcyhwYXJhU3R5bGUpKSB7CiAgICAgICAgaWYgKCEoa2V5IGluIHZhbHVlU3R5bGUpKSB7CiAgICAgICAgICB2YWx1ZVN0eWxlW2tleV0gPSB2YWw7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQp9CmZ1bmN0aW9uIHNldEZvbnRGYW1pbHkoeGZhRm9udCwgbm9kZSwgZm9udEZpbmRlciwgc3R5bGUpIHsKICBpZiAoIWZvbnRGaW5kZXIpIHsKICAgIGRlbGV0ZSBzdHlsZS5mb250RmFtaWx5OwogICAgcmV0dXJuOwogIH0KICBjb25zdCBuYW1lID0gc3RyaXBRdW90ZXMoeGZhRm9udC50eXBlZmFjZSk7CiAgc3R5bGUuZm9udEZhbWlseSA9IGAiJHtuYW1lfSJgOwogIGNvbnN0IHR5cGVmYWNlID0gZm9udEZpbmRlci5maW5kKG5hbWUpOwogIGlmICh0eXBlZmFjZSkgewogICAgY29uc3QgewogICAgICBmb250RmFtaWx5CiAgICB9ID0gdHlwZWZhY2UucmVndWxhci5jc3NGb250SW5mbzsKICAgIGlmIChmb250RmFtaWx5ICE9PSBuYW1lKSB7CiAgICAgIHN0eWxlLmZvbnRGYW1pbHkgPSBgIiR7Zm9udEZhbWlseX0iYDsKICAgIH0KICAgIGNvbnN0IHBhcmEgPSBnZXRDdXJyZW50UGFyYShub2RlKTsKICAgIGlmIChwYXJhICYmIHBhcmEubGluZUhlaWdodCAhPT0gIiIpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKHN0eWxlLmxpbmVIZWlnaHQpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgcGRmRm9udCA9IHNlbGVjdEZvbnQoeGZhRm9udCwgdHlwZWZhY2UpOwogICAgaWYgKHBkZkZvbnQpIHsKICAgICAgc3R5bGUubGluZUhlaWdodCA9IE1hdGgubWF4KDEuMiwgcGRmRm9udC5saW5lSGVpZ2h0KTsKICAgIH0KICB9Cn0KZnVuY3Rpb24gZml4VVJMKHN0cikgewogIGNvbnN0IGFic29sdXRlVXJsID0gY3JlYXRlVmFsaWRBYnNvbHV0ZVVybChzdHIsIG51bGwsIHsKICAgIGFkZERlZmF1bHRQcm90b2NvbDogdHJ1ZSwKICAgIHRyeUNvbnZlcnRFbmNvZGluZzogdHJ1ZQogIH0pOwogIHJldHVybiBhYnNvbHV0ZVVybCA/IGFic29sdXRlVXJsLmhyZWYgOiBudWxsOwp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEvbGF5b3V0LmpzCgoKCgoKZnVuY3Rpb24gY3JlYXRlTGluZShub2RlLCBjaGlsZHJlbikgewogIHJldHVybiB7CiAgICBuYW1lOiAiZGl2IiwKICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgY2xhc3M6IFtub2RlLmxheW91dCA9PT0gImxyLXRiIiA/ICJ4ZmFMciIgOiAieGZhUmwiXQogICAgfSwKICAgIGNoaWxkcmVuCiAgfTsKfQpmdW5jdGlvbiBmbHVzaEhUTUwobm9kZSkgewogIGlmICghbm9kZVskZXh0cmFdKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgY29uc3QgYXR0cmlidXRlcyA9IG5vZGVbJGV4dHJhXS5hdHRyaWJ1dGVzOwogIGNvbnN0IGh0bWwgPSB7CiAgICBuYW1lOiAiZGl2IiwKICAgIGF0dHJpYnV0ZXMsCiAgICBjaGlsZHJlbjogbm9kZVskZXh0cmFdLmNoaWxkcmVuCiAgfTsKICBpZiAobm9kZVskZXh0cmFdLmZhaWxpbmdOb2RlKSB7CiAgICBjb25zdCBodG1sRnJvbUZhaWxpbmcgPSBub2RlWyRleHRyYV0uZmFpbGluZ05vZGVbJGZsdXNoSFRNTF0oKTsKICAgIGlmIChodG1sRnJvbUZhaWxpbmcpIHsKICAgICAgaWYgKG5vZGUubGF5b3V0LmVuZHNXaXRoKCItdGIiKSkgewogICAgICAgIGh0bWwuY2hpbGRyZW4ucHVzaChjcmVhdGVMaW5lKG5vZGUsIFtodG1sRnJvbUZhaWxpbmddKSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgaHRtbC5jaGlsZHJlbi5wdXNoKGh0bWxGcm9tRmFpbGluZyk7CiAgICAgIH0KICAgIH0KICB9CiAgaWYgKGh0bWwuY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgcmV0dXJuIGh0bWw7Cn0KZnVuY3Rpb24gYWRkSFRNTChub2RlLCBodG1sLCBiYm94KSB7CiAgY29uc3QgZXh0cmEgPSBub2RlWyRleHRyYV07CiAgY29uc3QgYXZhaWxhYmxlU3BhY2UgPSBleHRyYS5hdmFpbGFibGVTcGFjZTsKICBjb25zdCBbeCwgeSwgdywgaF0gPSBiYm94OwogIHN3aXRjaCAobm9kZS5sYXlvdXQpIHsKICAgIGNhc2UgInBvc2l0aW9uIjoKICAgICAgewogICAgICAgIGV4dHJhLndpZHRoID0gTWF0aC5tYXgoZXh0cmEud2lkdGgsIHggKyB3KTsKICAgICAgICBleHRyYS5oZWlnaHQgPSBNYXRoLm1heChleHRyYS5oZWlnaHQsIHkgKyBoKTsKICAgICAgICBleHRyYS5jaGlsZHJlbi5wdXNoKGh0bWwpOwogICAgICAgIGJyZWFrOwogICAgICB9CiAgICBjYXNlICJsci10YiI6CiAgICBjYXNlICJybC10YiI6CiAgICAgIGlmICghZXh0cmEubGluZSB8fCBleHRyYS5hdHRlbXB0ID09PSAxKSB7CiAgICAgICAgZXh0cmEubGluZSA9IGNyZWF0ZUxpbmUobm9kZSwgW10pOwogICAgICAgIGV4dHJhLmNoaWxkcmVuLnB1c2goZXh0cmEubGluZSk7CiAgICAgICAgZXh0cmEubnVtYmVySW5MaW5lID0gMDsKICAgICAgfQogICAgICBleHRyYS5udW1iZXJJbkxpbmUgKz0gMTsKICAgICAgZXh0cmEubGluZS5jaGlsZHJlbi5wdXNoKGh0bWwpOwogICAgICBpZiAoZXh0cmEuYXR0ZW1wdCA9PT0gMCkgewogICAgICAgIGV4dHJhLmN1cnJlbnRXaWR0aCArPSB3OwogICAgICAgIGV4dHJhLmhlaWdodCA9IE1hdGgubWF4KGV4dHJhLmhlaWdodCwgZXh0cmEucHJldkhlaWdodCArIGgpOwogICAgICB9IGVsc2UgewogICAgICAgIGV4dHJhLmN1cnJlbnRXaWR0aCA9IHc7CiAgICAgICAgZXh0cmEucHJldkhlaWdodCA9IGV4dHJhLmhlaWdodDsKICAgICAgICBleHRyYS5oZWlnaHQgKz0gaDsKICAgICAgICBleHRyYS5hdHRlbXB0ID0gMDsKICAgICAgfQogICAgICBleHRyYS53aWR0aCA9IE1hdGgubWF4KGV4dHJhLndpZHRoLCBleHRyYS5jdXJyZW50V2lkdGgpOwogICAgICBicmVhazsKICAgIGNhc2UgInJsLXJvdyI6CiAgICBjYXNlICJyb3ciOgogICAgICB7CiAgICAgICAgZXh0cmEuY2hpbGRyZW4ucHVzaChodG1sKTsKICAgICAgICBleHRyYS53aWR0aCArPSB3OwogICAgICAgIGV4dHJhLmhlaWdodCA9IE1hdGgubWF4KGV4dHJhLmhlaWdodCwgaCk7CiAgICAgICAgY29uc3QgaGVpZ2h0ID0gbWVhc3VyZVRvU3RyaW5nKGV4dHJhLmhlaWdodCk7CiAgICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiBleHRyYS5jaGlsZHJlbikgewogICAgICAgICAgY2hpbGQuYXR0cmlidXRlcy5zdHlsZS5oZWlnaHQgPSBoZWlnaHQ7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICB9CiAgICBjYXNlICJ0YWJsZSI6CiAgICAgIHsKICAgICAgICBleHRyYS53aWR0aCA9IE1hdGhDbGFtcCh3LCBleHRyYS53aWR0aCwgYXZhaWxhYmxlU3BhY2Uud2lkdGgpOwogICAgICAgIGV4dHJhLmhlaWdodCArPSBoOwogICAgICAgIGV4dHJhLmNoaWxkcmVuLnB1c2goaHRtbCk7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIGNhc2UgInRiIjoKICAgICAgewogICAgICAgIGV4dHJhLndpZHRoID0gTWF0aENsYW1wKHcsIGV4dHJhLndpZHRoLCBhdmFpbGFibGVTcGFjZS53aWR0aCk7CiAgICAgICAgZXh0cmEuaGVpZ2h0ICs9IGg7CiAgICAgICAgZXh0cmEuY2hpbGRyZW4ucHVzaChodG1sKTsKICAgICAgICBicmVhazsKICAgICAgfQogIH0KfQpmdW5jdGlvbiBnZXRBdmFpbGFibGVTcGFjZShub2RlKSB7CiAgY29uc3QgYXZhaWxhYmxlU3BhY2UgPSBub2RlWyRleHRyYV0uYXZhaWxhYmxlU3BhY2U7CiAgY29uc3QgbWFyZ2luViA9IG5vZGUubWFyZ2luID8gbm9kZS5tYXJnaW4udG9wSW5zZXQgKyBub2RlLm1hcmdpbi5ib3R0b21JbnNldCA6IDA7CiAgY29uc3QgbWFyZ2luSCA9IG5vZGUubWFyZ2luID8gbm9kZS5tYXJnaW4ubGVmdEluc2V0ICsgbm9kZS5tYXJnaW4ucmlnaHRJbnNldCA6IDA7CiAgc3dpdGNoIChub2RlLmxheW91dCkgewogICAgY2FzZSAibHItdGIiOgogICAgY2FzZSAicmwtdGIiOgogICAgICBpZiAobm9kZVskZXh0cmFdLmF0dGVtcHQgPT09IDApIHsKICAgICAgICByZXR1cm4gewogICAgICAgICAgd2lkdGg6IGF2YWlsYWJsZVNwYWNlLndpZHRoIC0gbWFyZ2luSCAtIG5vZGVbJGV4dHJhXS5jdXJyZW50V2lkdGgsCiAgICAgICAgICBoZWlnaHQ6IGF2YWlsYWJsZVNwYWNlLmhlaWdodCAtIG1hcmdpblYgLSBub2RlWyRleHRyYV0ucHJldkhlaWdodAogICAgICAgIH07CiAgICAgIH0KICAgICAgcmV0dXJuIHsKICAgICAgICB3aWR0aDogYXZhaWxhYmxlU3BhY2Uud2lkdGggLSBtYXJnaW5ILAogICAgICAgIGhlaWdodDogYXZhaWxhYmxlU3BhY2UuaGVpZ2h0IC0gbWFyZ2luViAtIG5vZGVbJGV4dHJhXS5oZWlnaHQKICAgICAgfTsKICAgIGNhc2UgInJsLXJvdyI6CiAgICBjYXNlICJyb3ciOgogICAgICBjb25zdCB3aWR0aCA9IE1hdGguc3VtUHJlY2lzZShub2RlWyRleHRyYV0uY29sdW1uV2lkdGhzLnNsaWNlKG5vZGVbJGV4dHJhXS5jdXJyZW50Q29sdW1uKSk7CiAgICAgIHJldHVybiB7CiAgICAgICAgd2lkdGgsCiAgICAgICAgaGVpZ2h0OiBhdmFpbGFibGVTcGFjZS5oZWlnaHQgLSBtYXJnaW5ICiAgICAgIH07CiAgICBjYXNlICJ0YWJsZSI6CiAgICBjYXNlICJ0YiI6CiAgICAgIHJldHVybiB7CiAgICAgICAgd2lkdGg6IGF2YWlsYWJsZVNwYWNlLndpZHRoIC0gbWFyZ2luSCwKICAgICAgICBoZWlnaHQ6IGF2YWlsYWJsZVNwYWNlLmhlaWdodCAtIG1hcmdpblYgLSBub2RlWyRleHRyYV0uaGVpZ2h0CiAgICAgIH07CiAgICBjYXNlICJwb3NpdGlvbiI6CiAgICBkZWZhdWx0OgogICAgICByZXR1cm4gYXZhaWxhYmxlU3BhY2U7CiAgfQp9CmZ1bmN0aW9uIGdldFRyYW5zZm9ybWVkQkJveChub2RlKSB7CiAgbGV0IHcgPSBub2RlLncgPT09ICIiID8gTmFOIDogbm9kZS53OwogIGxldCBoID0gbm9kZS5oID09PSAiIiA/IE5hTiA6IG5vZGUuaDsKICBsZXQgW2NlbnRlclgsIGNlbnRlclldID0gWzAsIDBdOwogIHN3aXRjaCAobm9kZS5hbmNob3JUeXBlIHx8ICIiKSB7CiAgICBjYXNlICJib3R0b21DZW50ZXIiOgogICAgICBbY2VudGVyWCwgY2VudGVyWV0gPSBbdyAvIDIsIGhdOwogICAgICBicmVhazsKICAgIGNhc2UgImJvdHRvbUxlZnQiOgogICAgICBbY2VudGVyWCwgY2VudGVyWV0gPSBbMCwgaF07CiAgICAgIGJyZWFrOwogICAgY2FzZSAiYm90dG9tUmlnaHQiOgogICAgICBbY2VudGVyWCwgY2VudGVyWV0gPSBbdywgaF07CiAgICAgIGJyZWFrOwogICAgY2FzZSAibWlkZGxlQ2VudGVyIjoKICAgICAgW2NlbnRlclgsIGNlbnRlclldID0gW3cgLyAyLCBoIC8gMl07CiAgICAgIGJyZWFrOwogICAgY2FzZSAibWlkZGxlTGVmdCI6CiAgICAgIFtjZW50ZXJYLCBjZW50ZXJZXSA9IFswLCBoIC8gMl07CiAgICAgIGJyZWFrOwogICAgY2FzZSAibWlkZGxlUmlnaHQiOgogICAgICBbY2VudGVyWCwgY2VudGVyWV0gPSBbdywgaCAvIDJdOwogICAgICBicmVhazsKICAgIGNhc2UgInRvcENlbnRlciI6CiAgICAgIFtjZW50ZXJYLCBjZW50ZXJZXSA9IFt3IC8gMiwgMF07CiAgICAgIGJyZWFrOwogICAgY2FzZSAidG9wUmlnaHQiOgogICAgICBbY2VudGVyWCwgY2VudGVyWV0gPSBbdywgMF07CiAgICAgIGJyZWFrOwogIH0KICBsZXQgeCwgeTsKICBzd2l0Y2ggKG5vZGUucm90YXRlIHx8IDApIHsKICAgIGNhc2UgMDoKICAgICAgW3gsIHldID0gWy1jZW50ZXJYLCAtY2VudGVyWV07CiAgICAgIGJyZWFrOwogICAgY2FzZSA5MDoKICAgICAgW3gsIHldID0gWy1jZW50ZXJZLCBjZW50ZXJYXTsKICAgICAgW3csIGhdID0gW2gsIC13XTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDE4MDoKICAgICAgW3gsIHldID0gW2NlbnRlclgsIGNlbnRlclldOwogICAgICBbdywgaF0gPSBbLXcsIC1oXTsKICAgICAgYnJlYWs7CiAgICBjYXNlIDI3MDoKICAgICAgW3gsIHldID0gW2NlbnRlclksIC1jZW50ZXJYXTsKICAgICAgW3csIGhdID0gWy1oLCB3XTsKICAgICAgYnJlYWs7CiAgfQogIHJldHVybiBbbm9kZS54ICsgeCArIE1hdGgubWluKDAsIHcpLCBub2RlLnkgKyB5ICsgTWF0aC5taW4oMCwgaCksIE1hdGguYWJzKHcpLCBNYXRoLmFicyhoKV07Cn0KZnVuY3Rpb24gY2hlY2tEaW1lbnNpb25zKG5vZGUsIHNwYWNlKSB7CiAgaWYgKG5vZGVbJGdldFRlbXBsYXRlUm9vdF0oKVskZXh0cmFdLmZpcnN0VW5zcGxpdHRhYmxlID09PSBudWxsKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgaWYgKG5vZGUudyA9PT0gMCB8fCBub2RlLmggPT09IDApIHsKICAgIHJldHVybiB0cnVlOwogIH0KICBjb25zdCBFUlJPUiA9IDI7CiAgY29uc3QgcGFyZW50ID0gbm9kZVskZ2V0U3ViZm9ybVBhcmVudF0oKTsKICBjb25zdCBhdHRlbXB0ID0gcGFyZW50WyRleHRyYV0/LmF0dGVtcHQgfHwgMDsKICBjb25zdCBbLCB5LCB3LCBoXSA9IGdldFRyYW5zZm9ybWVkQkJveChub2RlKTsKICBzd2l0Y2ggKHBhcmVudC5sYXlvdXQpIHsKICAgIGNhc2UgImxyLXRiIjoKICAgIGNhc2UgInJsLXRiIjoKICAgICAgaWYgKGF0dGVtcHQgPT09IDApIHsKICAgICAgICBpZiAoIW5vZGVbJGdldFRlbXBsYXRlUm9vdF0oKVskZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSkgewogICAgICAgICAgaWYgKG5vZGUuaCAhPT0gIiIgJiYgTWF0aC5yb3VuZChoIC0gc3BhY2UuaGVpZ2h0KSA+IEVSUk9SKSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChub2RlLncgIT09ICIiKSB7CiAgICAgICAgICAgIGlmIChNYXRoLnJvdW5kKHcgLSBzcGFjZS53aWR0aCkgPD0gRVJST1IpIHsKICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpZiAocGFyZW50WyRleHRyYV0ubnVtYmVySW5MaW5lID09PSAwKSB7CiAgICAgICAgICAgICAgcmV0dXJuIHNwYWNlLmhlaWdodCA+IEVSUk9SOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBzcGFjZS53aWR0aCA+IEVSUk9SOwogICAgICAgIH0KICAgICAgICBpZiAobm9kZS53ICE9PSAiIikgewogICAgICAgICAgcmV0dXJuIE1hdGgucm91bmQodyAtIHNwYWNlLndpZHRoKSA8PSBFUlJPUjsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHNwYWNlLndpZHRoID4gRVJST1I7CiAgICAgIH0KICAgICAgaWYgKG5vZGVbJGdldFRlbXBsYXRlUm9vdF0oKVskZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmIChub2RlLmggIT09ICIiICYmIE1hdGgucm91bmQoaCAtIHNwYWNlLmhlaWdodCkgPiBFUlJPUikgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBpZiAobm9kZS53ID09PSAiIiB8fCBNYXRoLnJvdW5kKHcgLSBzcGFjZS53aWR0aCkgPD0gRVJST1IpIHsKICAgICAgICByZXR1cm4gc3BhY2UuaGVpZ2h0ID4gRVJST1I7CiAgICAgIH0KICAgICAgaWYgKHBhcmVudFskaXNUaGVyZU1vcmVXaWR0aF0oKSkgewogICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICByZXR1cm4gc3BhY2UuaGVpZ2h0ID4gRVJST1I7CiAgICBjYXNlICJ0YWJsZSI6CiAgICBjYXNlICJ0YiI6CiAgICAgIGlmIChub2RlWyRnZXRUZW1wbGF0ZVJvb3RdKClbJGV4dHJhXS5ub0xheW91dEZhaWx1cmUpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBpZiAobm9kZS5oICE9PSAiIiAmJiAhbm9kZVskaXNTcGxpdHRhYmxlXSgpKSB7CiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQoaCAtIHNwYWNlLmhlaWdodCkgPD0gRVJST1I7CiAgICAgIH0KICAgICAgaWYgKG5vZGUudyA9PT0gIiIgfHwgTWF0aC5yb3VuZCh3IC0gc3BhY2Uud2lkdGgpIDw9IEVSUk9SKSB7CiAgICAgICAgcmV0dXJuIHNwYWNlLmhlaWdodCA+IEVSUk9SOwogICAgICB9CiAgICAgIGlmIChwYXJlbnRbJGlzVGhlcmVNb3JlV2lkdGhdKCkpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgICAgcmV0dXJuIHNwYWNlLmhlaWdodCA+IEVSUk9SOwogICAgY2FzZSAicG9zaXRpb24iOgogICAgICBpZiAobm9kZVskZ2V0VGVtcGxhdGVSb290XSgpWyRleHRyYV0ubm9MYXlvdXRGYWlsdXJlKSB7CiAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgIH0KICAgICAgaWYgKG5vZGUuaCA9PT0gIiIgfHwgTWF0aC5yb3VuZChoICsgeSAtIHNwYWNlLmhlaWdodCkgPD0gRVJST1IpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBjb25zdCBhcmVhID0gbm9kZVskZ2V0VGVtcGxhdGVSb290XSgpWyRleHRyYV0uY3VycmVudENvbnRlbnRBcmVhOwogICAgICByZXR1cm4gaCArIHkgPiBhcmVhLmg7CiAgICBjYXNlICJybC1yb3ciOgogICAgY2FzZSAicm93IjoKICAgICAgaWYgKG5vZGVbJGdldFRlbXBsYXRlUm9vdF0oKVskZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlmIChub2RlLmggIT09ICIiKSB7CiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQoaCAtIHNwYWNlLmhlaWdodCkgPD0gRVJST1I7CiAgICAgIH0KICAgICAgcmV0dXJuIHRydWU7CiAgICBkZWZhdWx0OgogICAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3hmYS90ZW1wbGF0ZS5qcwoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCmNvbnN0IFRFTVBMQVRFX05TX0lEID0gTmFtZXNwYWNlSWRzLnRlbXBsYXRlLmlkOwpjb25zdCBTVkdfTlMgPSAiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciOwpjb25zdCBNQVhfQVRURU1QVFNfRk9SX0xSVEJfTEFZT1VUID0gMjsKY29uc3QgTUFYX0VNUFRZX1BBR0VTID0gMzsKY29uc3QgREVGQVVMVF9UQUJfSU5ERVggPSA1MDAwOwpjb25zdCBIRUFESU5HX1BBVFRFUk4gPSAvXkgoXGQrKSQvOwpjb25zdCBNSU1FUyA9IG5ldyBTZXQoWyJpbWFnZS9naWYiLCAiaW1hZ2UvanBlZyIsICJpbWFnZS9qcGciLCAiaW1hZ2UvcGpwZWciLCAiaW1hZ2UvcG5nIiwgImltYWdlL2FwbmciLCAiaW1hZ2UveC1wbmciLCAiaW1hZ2UvYm1wIiwgImltYWdlL3gtbXMtYm1wIiwgImltYWdlL3RpZmYiLCAiaW1hZ2UvdGlmIiwgImFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbSJdKTsKY29uc3QgSU1BR0VTX0hFQURFUlMgPSBbW1sweDQyLCAweDRkXSwgImltYWdlL2JtcCJdLCBbWzB4ZmYsIDB4ZDgsIDB4ZmZdLCAiaW1hZ2UvanBlZyJdLCBbWzB4NDksIDB4NDksIDB4MmEsIDB4MDBdLCAiaW1hZ2UvdGlmZiJdLCBbWzB4NGQsIDB4NGQsIDB4MDAsIDB4MmFdLCAiaW1hZ2UvdGlmZiJdLCBbWzB4NDcsIDB4NDksIDB4NDYsIDB4MzgsIDB4MzksIDB4NjFdLCAiaW1hZ2UvZ2lmIl0sIFtbMHg4OSwgMHg1MCwgMHg0ZSwgMHg0NywgMHgwZCwgMHgwYSwgMHgxYSwgMHgwYV0sICJpbWFnZS9wbmciXV07CmZ1bmN0aW9uIGdldEJvcmRlckRpbXMobm9kZSkgewogIGlmICghbm9kZSB8fCAhbm9kZS5ib3JkZXIpIHsKICAgIHJldHVybiB7CiAgICAgIHc6IDAsCiAgICAgIGg6IDAKICAgIH07CiAgfQogIGNvbnN0IGJvcmRlckV4dHJhID0gbm9kZS5ib3JkZXJbJGdldEV4dHJhXSgpOwogIGlmICghYm9yZGVyRXh0cmEpIHsKICAgIHJldHVybiB7CiAgICAgIHc6IDAsCiAgICAgIGg6IDAKICAgIH07CiAgfQogIHJldHVybiB7CiAgICB3OiBib3JkZXJFeHRyYS53aWR0aHNbMF0gKyBib3JkZXJFeHRyYS53aWR0aHNbMl0gKyBib3JkZXJFeHRyYS5pbnNldHNbMF0gKyBib3JkZXJFeHRyYS5pbnNldHNbMl0sCiAgICBoOiBib3JkZXJFeHRyYS53aWR0aHNbMV0gKyBib3JkZXJFeHRyYS53aWR0aHNbM10gKyBib3JkZXJFeHRyYS5pbnNldHNbMV0gKyBib3JkZXJFeHRyYS5pbnNldHNbM10KICB9Owp9CmZ1bmN0aW9uIGhhc01hcmdpbihub2RlKSB7CiAgcmV0dXJuIG5vZGUubWFyZ2luICYmIChub2RlLm1hcmdpbi50b3BJbnNldCB8fCBub2RlLm1hcmdpbi5yaWdodEluc2V0IHx8IG5vZGUubWFyZ2luLmJvdHRvbUluc2V0IHx8IG5vZGUubWFyZ2luLmxlZnRJbnNldCk7Cn0KZnVuY3Rpb24gX3NldFZhbHVlKHRlbXBsYXRlTm9kZSwgdmFsdWUpIHsKICBpZiAoIXRlbXBsYXRlTm9kZS52YWx1ZSkgewogICAgY29uc3Qgbm9kZVZhbHVlID0gbmV3IFZhbHVlKHt9KTsKICAgIHRlbXBsYXRlTm9kZVskYXBwZW5kQ2hpbGRdKG5vZGVWYWx1ZSk7CiAgICB0ZW1wbGF0ZU5vZGUudmFsdWUgPSBub2RlVmFsdWU7CiAgfQogIHRlbXBsYXRlTm9kZS52YWx1ZVskc2V0VmFsdWVdKHZhbHVlKTsKfQpmdW5jdGlvbiogZ2V0Q29udGFpbmVkQ2hpbGRyZW4obm9kZSkgewogIGZvciAoY29uc3QgY2hpbGQgb2Ygbm9kZVskZ2V0Q2hpbGRyZW5dKCkpIHsKICAgIGlmIChjaGlsZCBpbnN0YW5jZW9mIFN1YmZvcm1TZXQpIHsKICAgICAgeWllbGQqIGNoaWxkWyRnZXRDb250YWluZWRDaGlsZHJlbl0oKTsKICAgICAgY29udGludWU7CiAgICB9CiAgICB5aWVsZCBjaGlsZDsKICB9Cn0KZnVuY3Rpb24gaXNSZXF1aXJlZChub2RlKSB7CiAgcmV0dXJuIG5vZGUudmFsaWRhdGU/Lm51bGxUZXN0ID09PSAiZXJyb3IiOwp9CmZ1bmN0aW9uIHNldFRhYkluZGV4KG5vZGUpIHsKICB3aGlsZSAobm9kZSkgewogICAgaWYgKCFub2RlLnRyYXZlcnNhbCkgewogICAgICBub2RlWyR0YWJJbmRleF0gPSBub2RlWyRnZXRQYXJlbnRdKClbJHRhYkluZGV4XTsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKG5vZGVbJHRhYkluZGV4XSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgbmV4dCA9IG51bGw7CiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIG5vZGUudHJhdmVyc2FsWyRnZXRDaGlsZHJlbl0oKSkgewogICAgICBpZiAoY2hpbGQub3BlcmF0aW9uID09PSAibmV4dCIpIHsKICAgICAgICBuZXh0ID0gY2hpbGQ7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGlmICghbmV4dCB8fCAhbmV4dC5yZWYpIHsKICAgICAgbm9kZVskdGFiSW5kZXhdID0gbm9kZVskZ2V0UGFyZW50XSgpWyR0YWJJbmRleF07CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHJvb3QgPSBub2RlWyRnZXRUZW1wbGF0ZVJvb3RdKCk7CiAgICBub2RlWyR0YWJJbmRleF0gPSArK3Jvb3RbJHRhYkluZGV4XTsKICAgIGNvbnN0IHJlZiA9IHJvb3RbJHNlYXJjaE5vZGVdKG5leHQucmVmLCBub2RlKTsKICAgIGlmICghcmVmKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIG5vZGUgPSByZWZbMF07CiAgfQp9CmZ1bmN0aW9uIGFwcGx5QXNzaXN0KG9iaiwgYXR0cmlidXRlcykgewogIGNvbnN0IGFzc2lzdCA9IG9iai5hc3Npc3Q7CiAgaWYgKGFzc2lzdCkgewogICAgY29uc3QgYXNzaXN0VGl0bGUgPSBhc3Npc3RbJHRvSFRNTF0oKTsKICAgIGlmIChhc3Npc3RUaXRsZSkgewogICAgICBhdHRyaWJ1dGVzLnRpdGxlID0gYXNzaXN0VGl0bGU7CiAgICB9CiAgICBjb25zdCByb2xlID0gYXNzaXN0LnJvbGU7CiAgICBjb25zdCBtYXRjaCA9IHJvbGUubWF0Y2goSEVBRElOR19QQVRURVJOKTsKICAgIGlmIChtYXRjaCkgewogICAgICBjb25zdCBhcmlhUm9sZSA9ICJoZWFkaW5nIjsKICAgICAgY29uc3QgYXJpYUxldmVsID0gbWF0Y2hbMV07CiAgICAgIGF0dHJpYnV0ZXMucm9sZSA9IGFyaWFSb2xlOwogICAgICBhdHRyaWJ1dGVzWyJhcmlhLWxldmVsIl0gPSBhcmlhTGV2ZWw7CiAgICB9CiAgfQogIGlmIChvYmoubGF5b3V0ID09PSAidGFibGUiKSB7CiAgICBhdHRyaWJ1dGVzLnJvbGUgPSAidGFibGUiOwogIH0gZWxzZSBpZiAob2JqLmxheW91dCA9PT0gInJvdyIpIHsKICAgIGF0dHJpYnV0ZXMucm9sZSA9ICJyb3ciOwogIH0gZWxzZSB7CiAgICBjb25zdCBwYXJlbnQgPSBvYmpbJGdldFBhcmVudF0oKTsKICAgIGlmIChwYXJlbnQubGF5b3V0ID09PSAicm93IikgewogICAgICBhdHRyaWJ1dGVzLnJvbGUgPSBwYXJlbnQuYXNzaXN0Py5yb2xlID09PSAiVEgiID8gImNvbHVtbmhlYWRlciIgOiAiY2VsbCI7CiAgICB9CiAgfQp9CmZ1bmN0aW9uIGFyaWFMYWJlbChvYmopIHsKICBpZiAoIW9iai5hc3Npc3QpIHsKICAgIHJldHVybiBudWxsOwogIH0KICBjb25zdCBhc3Npc3QgPSBvYmouYXNzaXN0OwogIGlmIChhc3Npc3Quc3BlYWsgJiYgYXNzaXN0LnNwZWFrWyRjb250ZW50XSAhPT0gIiIpIHsKICAgIHJldHVybiBhc3Npc3Quc3BlYWtbJGNvbnRlbnRdOwogIH0KICBpZiAoYXNzaXN0LnRvb2xUaXApIHsKICAgIHJldHVybiBhc3Npc3QudG9vbFRpcFskY29udGVudF07CiAgfQogIHJldHVybiBudWxsOwp9CmZ1bmN0aW9uIHZhbHVlVG9IdG1sKHZhbHVlKSB7CiAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICBuYW1lOiAiZGl2IiwKICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgY2xhc3M6IFsieGZhUmljaCJdLAogICAgICBzdHlsZTogT2JqZWN0LmNyZWF0ZShudWxsKQogICAgfSwKICAgIGNoaWxkcmVuOiBbewogICAgICBuYW1lOiAic3BhbiIsCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBzdHlsZTogT2JqZWN0LmNyZWF0ZShudWxsKQogICAgICB9LAogICAgICB2YWx1ZQogICAgfV0KICB9KTsKfQpmdW5jdGlvbiBzZXRGaXJzdFVuc3BsaXR0YWJsZShub2RlKSB7CiAgY29uc3Qgcm9vdCA9IG5vZGVbJGdldFRlbXBsYXRlUm9vdF0oKTsKICBpZiAocm9vdFskZXh0cmFdLmZpcnN0VW5zcGxpdHRhYmxlID09PSBudWxsKSB7CiAgICByb290WyRleHRyYV0uZmlyc3RVbnNwbGl0dGFibGUgPSBub2RlOwogICAgcm9vdFskZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSA9IHRydWU7CiAgfQp9CmZ1bmN0aW9uIHVuc2V0Rmlyc3RVbnNwbGl0dGFibGUobm9kZSkgewogIGNvbnN0IHJvb3QgPSBub2RlWyRnZXRUZW1wbGF0ZVJvb3RdKCk7CiAgaWYgKHJvb3RbJGV4dHJhXS5maXJzdFVuc3BsaXR0YWJsZSA9PT0gbm9kZSkgewogICAgcm9vdFskZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSA9IGZhbHNlOwogIH0KfQpmdW5jdGlvbiBoYW5kbGVCcmVhayhub2RlKSB7CiAgaWYgKG5vZGVbJGV4dHJhXSkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBub2RlWyRleHRyYV0gPSBPYmplY3QuY3JlYXRlKG51bGwpOwogIGlmIChub2RlLnRhcmdldFR5cGUgPT09ICJhdXRvIikgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBjb25zdCByb290ID0gbm9kZVskZ2V0VGVtcGxhdGVSb290XSgpOwogIGxldCB0YXJnZXQgPSBudWxsOwogIGlmIChub2RlLnRhcmdldCkgewogICAgdGFyZ2V0ID0gcm9vdFskc2VhcmNoTm9kZV0obm9kZS50YXJnZXQsIG5vZGVbJGdldFBhcmVudF0oKSk7CiAgICBpZiAoIXRhcmdldCkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICB0YXJnZXQgPSB0YXJnZXRbMF07CiAgfQogIGNvbnN0IHsKICAgIGN1cnJlbnRQYWdlQXJlYSwKICAgIGN1cnJlbnRDb250ZW50QXJlYQogIH0gPSByb290WyRleHRyYV07CiAgaWYgKG5vZGUudGFyZ2V0VHlwZSA9PT0gInBhZ2VBcmVhIikgewogICAgaWYgKCEodGFyZ2V0IGluc3RhbmNlb2YgUGFnZUFyZWEpKSB7CiAgICAgIHRhcmdldCA9IG51bGw7CiAgICB9CiAgICBpZiAobm9kZS5zdGFydE5ldykgewogICAgICBub2RlWyRleHRyYV0udGFyZ2V0ID0gdGFyZ2V0IHx8IGN1cnJlbnRQYWdlQXJlYTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9IGVsc2UgaWYgKHRhcmdldCAmJiB0YXJnZXQgIT09IGN1cnJlbnRQYWdlQXJlYSkgewogICAgICBub2RlWyRleHRyYV0udGFyZ2V0ID0gdGFyZ2V0OwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKICB9CiAgaWYgKCEodGFyZ2V0IGluc3RhbmNlb2YgQ29udGVudEFyZWEpKSB7CiAgICB0YXJnZXQgPSBudWxsOwogIH0KICBjb25zdCBwYWdlQXJlYSA9IHRhcmdldCAmJiB0YXJnZXRbJGdldFBhcmVudF0oKTsKICBsZXQgaW5kZXg7CiAgbGV0IG5leHRQYWdlQXJlYSA9IHBhZ2VBcmVhOwogIGlmIChub2RlLnN0YXJ0TmV3KSB7CiAgICBpZiAodGFyZ2V0KSB7CiAgICAgIGNvbnN0IGNvbnRlbnRBcmVhcyA9IHBhZ2VBcmVhLmNvbnRlbnRBcmVhLmNoaWxkcmVuOwogICAgICBjb25zdCBpbmRleEZvckN1cnJlbnQgPSBjb250ZW50QXJlYXMuaW5kZXhPZihjdXJyZW50Q29udGVudEFyZWEpOwogICAgICBjb25zdCBpbmRleEZvclRhcmdldCA9IGNvbnRlbnRBcmVhcy5pbmRleE9mKHRhcmdldCk7CiAgICAgIGlmIChpbmRleEZvckN1cnJlbnQgIT09IC0xICYmIGluZGV4Rm9yQ3VycmVudCA8IGluZGV4Rm9yVGFyZ2V0KSB7CiAgICAgICAgbmV4dFBhZ2VBcmVhID0gbnVsbDsKICAgICAgfQogICAgICBpbmRleCA9IGluZGV4Rm9yVGFyZ2V0IC0gMTsKICAgIH0gZWxzZSB7CiAgICAgIGluZGV4ID0gY3VycmVudFBhZ2VBcmVhLmNvbnRlbnRBcmVhLmNoaWxkcmVuLmluZGV4T2YoY3VycmVudENvbnRlbnRBcmVhKTsKICAgIH0KICB9IGVsc2UgaWYgKHRhcmdldCAmJiB0YXJnZXQgIT09IGN1cnJlbnRDb250ZW50QXJlYSkgewogICAgY29uc3QgY29udGVudEFyZWFzID0gcGFnZUFyZWEuY29udGVudEFyZWEuY2hpbGRyZW47CiAgICBpbmRleCA9IGNvbnRlbnRBcmVhcy5pbmRleE9mKHRhcmdldCkgLSAxOwogICAgbmV4dFBhZ2VBcmVhID0gcGFnZUFyZWEgPT09IGN1cnJlbnRQYWdlQXJlYSA/IG51bGwgOiBwYWdlQXJlYTsKICB9IGVsc2UgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBub2RlWyRleHRyYV0udGFyZ2V0ID0gbmV4dFBhZ2VBcmVhOwogIG5vZGVbJGV4dHJhXS5pbmRleCA9IGluZGV4OwogIHJldHVybiB0cnVlOwp9CmZ1bmN0aW9uIGhhbmRsZU92ZXJmbG93KG5vZGUsIGV4dHJhTm9kZSwgc3BhY2UpIHsKICBjb25zdCByb290ID0gbm9kZVskZ2V0VGVtcGxhdGVSb290XSgpOwogIGNvbnN0IHNhdmVkID0gcm9vdFskZXh0cmFdLm5vTGF5b3V0RmFpbHVyZTsKICBjb25zdCBzYXZlZE1ldGhvZCA9IGV4dHJhTm9kZVskZ2V0U3ViZm9ybVBhcmVudF07CiAgZXh0cmFOb2RlWyRnZXRTdWJmb3JtUGFyZW50XSA9ICgpID0+IG5vZGU7CiAgcm9vdFskZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSA9IHRydWU7CiAgY29uc3QgcmVzID0gZXh0cmFOb2RlWyR0b0hUTUxdKHNwYWNlKTsKICBub2RlWyRhZGRIVE1MXShyZXMuaHRtbCwgcmVzLmJib3gpOwogIHJvb3RbJGV4dHJhXS5ub0xheW91dEZhaWx1cmUgPSBzYXZlZDsKICBleHRyYU5vZGVbJGdldFN1YmZvcm1QYXJlbnRdID0gc2F2ZWRNZXRob2Q7Cn0KY2xhc3MgQXBwZWFyYW5jZUZpbHRlciBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJhcHBlYXJhbmNlRmlsdGVyIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudHlwZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnR5cGUsIFsib3B0aW9uYWwiLCAicmVxdWlyZWQiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBBcmMgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYXJjIiwgdHJ1ZSk7CiAgICB0aGlzLmNpcmN1bGFyID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuY2lyY3VsYXIsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLmhhbmQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5oYW5kLCBbImV2ZW4iLCAibGVmdCIsICJyaWdodCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5zdGFydEFuZ2xlID0gZ2V0RmxvYXQoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnN0YXJ0QW5nbGUsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4gdHJ1ZQogICAgfSk7CiAgICB0aGlzLnN3ZWVwQW5nbGUgPSBnZXRGbG9hdCh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuc3dlZXBBbmdsZSwKICAgICAgZGVmYXVsdFZhbHVlOiAzNjAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHRydWUKICAgIH0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZWRnZSA9IG51bGw7CiAgICB0aGlzLmZpbGwgPSBudWxsOwogIH0KICBbJHRvSFRNTF0oKSB7CiAgICBjb25zdCBlZGdlID0gdGhpcy5lZGdlIHx8IG5ldyBFZGdlKHt9KTsKICAgIGNvbnN0IGVkZ2VTdHlsZSA9IGVkZ2VbJHRvU3R5bGVdKCk7CiAgICBjb25zdCBzdHlsZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBpZiAodGhpcy5maWxsPy5wcmVzZW5jZSA9PT0gInZpc2libGUiKSB7CiAgICAgIE9iamVjdC5hc3NpZ24oc3R5bGUsIHRoaXMuZmlsbFskdG9TdHlsZV0oKSk7CiAgICB9IGVsc2UgewogICAgICBzdHlsZS5maWxsID0gInRyYW5zcGFyZW50IjsKICAgIH0KICAgIHN0eWxlLnN0cm9rZVdpZHRoID0gbWVhc3VyZVRvU3RyaW5nKGVkZ2UucHJlc2VuY2UgPT09ICJ2aXNpYmxlIiA/IGVkZ2UudGhpY2tuZXNzIDogMCk7CiAgICBzdHlsZS5zdHJva2UgPSBlZGdlU3R5bGUuY29sb3I7CiAgICBsZXQgYXJjOwogICAgY29uc3QgYXR0cmlidXRlcyA9IHsKICAgICAgeG1sbnM6IFNWR19OUywKICAgICAgc3R5bGU6IHsKICAgICAgICB3aWR0aDogIjEwMCUiLAogICAgICAgIGhlaWdodDogIjEwMCUiLAogICAgICAgIG92ZXJmbG93OiAidmlzaWJsZSIKICAgICAgfQogICAgfTsKICAgIGlmICh0aGlzLnN3ZWVwQW5nbGUgPT09IDM2MCkgewogICAgICBhcmMgPSB7CiAgICAgICAgbmFtZTogImVsbGlwc2UiLAogICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgIHhtbG5zOiBTVkdfTlMsCiAgICAgICAgICBjeDogIjUwJSIsCiAgICAgICAgICBjeTogIjUwJSIsCiAgICAgICAgICByeDogIjUwJSIsCiAgICAgICAgICByeTogIjUwJSIsCiAgICAgICAgICBzdHlsZQogICAgICAgIH0KICAgICAgfTsKICAgIH0gZWxzZSB7CiAgICAgIGNvbnN0IHN0YXJ0QW5nbGUgPSB0aGlzLnN0YXJ0QW5nbGUgKiBNYXRoLlBJIC8gMTgwOwogICAgICBjb25zdCBzd2VlcEFuZ2xlID0gdGhpcy5zd2VlcEFuZ2xlICogTWF0aC5QSSAvIDE4MDsKICAgICAgY29uc3QgbGFyZ2VBcmMgPSB0aGlzLnN3ZWVwQW5nbGUgPiAxODAgPyAxIDogMDsKICAgICAgY29uc3QgW3gxLCB5MSwgeDIsIHkyXSA9IFs1MCAqICgxICsgTWF0aC5jb3Moc3RhcnRBbmdsZSkpLCA1MCAqICgxIC0gTWF0aC5zaW4oc3RhcnRBbmdsZSkpLCA1MCAqICgxICsgTWF0aC5jb3Moc3RhcnRBbmdsZSArIHN3ZWVwQW5nbGUpKSwgNTAgKiAoMSAtIE1hdGguc2luKHN0YXJ0QW5nbGUgKyBzd2VlcEFuZ2xlKSldOwogICAgICBhcmMgPSB7CiAgICAgICAgbmFtZTogInBhdGgiLAogICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgIHhtbG5zOiBTVkdfTlMsCiAgICAgICAgICBkOiBgTSAke3gxfSAke3kxfSBBIDUwIDUwIDAgJHtsYXJnZUFyY30gMCAke3gyfSAke3kyfWAsCiAgICAgICAgICB2ZWN0b3JFZmZlY3Q6ICJub24tc2NhbGluZy1zdHJva2UiLAogICAgICAgICAgc3R5bGUKICAgICAgICB9CiAgICAgIH07CiAgICAgIE9iamVjdC5hc3NpZ24oYXR0cmlidXRlcywgewogICAgICAgIHZpZXdCb3g6ICIwIDAgMTAwIDEwMCIsCiAgICAgICAgcHJlc2VydmVBc3BlY3RSYXRpbzogIm5vbmUiCiAgICAgIH0pOwogICAgfQogICAgY29uc3Qgc3ZnID0gewogICAgICBuYW1lOiAic3ZnIiwKICAgICAgY2hpbGRyZW46IFthcmNdLAogICAgICBhdHRyaWJ1dGVzCiAgICB9OwogICAgY29uc3QgcGFyZW50ID0gdGhpc1skZ2V0UGFyZW50XSgpWyRnZXRQYXJlbnRdKCk7CiAgICBpZiAoaGFzTWFyZ2luKHBhcmVudCkpIHsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgICAgbmFtZTogImRpdiIsCiAgICAgICAgYXR0cmlidXRlczogewogICAgICAgICAgc3R5bGU6IHsKICAgICAgICAgICAgZGlzcGxheTogImlubGluZSIsCiAgICAgICAgICAgIHdpZHRoOiAiMTAwJSIsCiAgICAgICAgICAgIGhlaWdodDogIjEwMCUiCiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICBjaGlsZHJlbjogW3N2Z10KICAgICAgfSk7CiAgICB9CiAgICBzdmcuYXR0cmlidXRlcy5zdHlsZS5wb3NpdGlvbiA9ICJhYnNvbHV0ZSI7CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHN2Zyk7CiAgfQp9CmNsYXNzIEFyZWEgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYXJlYSIsIHRydWUpOwogICAgdGhpcy5jb2xTcGFuID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuY29sU3BhbiwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogbiA9PiBuID49IDEgfHwgbiA9PT0gLTEKICAgIH0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnJlbGV2YW50ID0gZ2V0UmVsZXZhbnQoYXR0cmlidXRlcy5yZWxldmFudCk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy54ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy54LCAiMHB0Iik7CiAgICB0aGlzLnkgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnksICIwcHQiKTsKICAgIHRoaXMuZGVzYyA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLmFyZWEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZHJhdyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leE9iamVjdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leGNsR3JvdXAgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmllbGQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3ViZm9ybSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zdWJmb3JtU2V0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQogICpbJGdldENvbnRhaW5lZENoaWxkcmVuXSgpIHsKICAgIHlpZWxkKiBnZXRDb250YWluZWRDaGlsZHJlbih0aGlzKTsKICB9CiAgWyRpc1RyYW5zcGFyZW50XSgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICBbJGlzQmluZGFibGVdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIFskYWRkSFRNTF0oaHRtbCwgYmJveCkgewogICAgY29uc3QgW3gsIHksIHcsIGhdID0gYmJveDsKICAgIHRoaXNbJGV4dHJhXS53aWR0aCA9IE1hdGgubWF4KHRoaXNbJGV4dHJhXS53aWR0aCwgeCArIHcpOwogICAgdGhpc1skZXh0cmFdLmhlaWdodCA9IE1hdGgubWF4KHRoaXNbJGV4dHJhXS5oZWlnaHQsIHkgKyBoKTsKICAgIHRoaXNbJGV4dHJhXS5jaGlsZHJlbi5wdXNoKGh0bWwpOwogIH0KICBbJGdldEF2YWlsYWJsZVNwYWNlXSgpIHsKICAgIHJldHVybiB0aGlzWyRleHRyYV0uYXZhaWxhYmxlU3BhY2U7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgY29uc3Qgc3R5bGUgPSB0b1N0eWxlKHRoaXMsICJwb3NpdGlvbiIpOwogICAgY29uc3QgYXR0cmlidXRlcyA9IHsKICAgICAgc3R5bGUsCiAgICAgIGlkOiB0aGlzWyR1aWRdLAogICAgICBjbGFzczogWyJ4ZmFBcmVhIl0KICAgIH07CiAgICBpZiAoaXNQcmludE9ubHkodGhpcykpIHsKICAgICAgYXR0cmlidXRlcy5jbGFzcy5wdXNoKCJ4ZmFQcmludE9ubHkiKTsKICAgIH0KICAgIGlmICh0aGlzLm5hbWUpIHsKICAgICAgYXR0cmlidXRlcy54ZmFOYW1lID0gdGhpcy5uYW1lOwogICAgfQogICAgY29uc3QgY2hpbGRyZW4gPSBbXTsKICAgIHRoaXNbJGV4dHJhXSA9IHsKICAgICAgY2hpbGRyZW4sCiAgICAgIHdpZHRoOiAwLAogICAgICBoZWlnaHQ6IDAsCiAgICAgIGF2YWlsYWJsZVNwYWNlCiAgICB9OwogICAgY29uc3QgcmVzdWx0ID0gdGhpc1skY2hpbGRyZW5Ub0hUTUxdKHsKICAgICAgZmlsdGVyOiBuZXcgU2V0KFsiYXJlYSIsICJkcmF3IiwgImZpZWxkIiwgImV4Y2xHcm91cCIsICJzdWJmb3JtIiwgInN1YmZvcm1TZXQiXSksCiAgICAgIGluY2x1ZGU6IHRydWUKICAgIH0pOwogICAgaWYgKCFyZXN1bHQuc3VjY2VzcykgewogICAgICBpZiAocmVzdWx0LmlzQnJlYWsoKSkgewogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KICAgICAgZGVsZXRlIHRoaXNbJGV4dHJhXTsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuRkFJTFVSRTsKICAgIH0KICAgIHN0eWxlLndpZHRoID0gbWVhc3VyZVRvU3RyaW5nKHRoaXNbJGV4dHJhXS53aWR0aCk7CiAgICBzdHlsZS5oZWlnaHQgPSBtZWFzdXJlVG9TdHJpbmcodGhpc1skZXh0cmFdLmhlaWdodCk7CiAgICBjb25zdCBodG1sID0gewogICAgICBuYW1lOiAiZGl2IiwKICAgICAgYXR0cmlidXRlcywKICAgICAgY2hpbGRyZW4KICAgIH07CiAgICBjb25zdCBiYm94ID0gW3RoaXMueCwgdGhpcy55LCB0aGlzWyRleHRyYV0ud2lkdGgsIHRoaXNbJGV4dHJhXS5oZWlnaHRdOwogICAgZGVsZXRlIHRoaXNbJGV4dHJhXTsKICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoaHRtbCwgYmJveCk7CiAgfQp9CmNsYXNzIEFzc2lzdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJhc3Npc3QiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5yb2xlID0gYXR0cmlidXRlcy5yb2xlIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuc3BlYWsgPSBudWxsOwogICAgdGhpcy50b29sVGlwID0gbnVsbDsKICB9CiAgWyR0b0hUTUxdKCkgewogICAgcmV0dXJuIHRoaXMudG9vbFRpcD8uWyRjb250ZW50XSB8fCBudWxsOwogIH0KfQpjbGFzcyBCYXJjb2RlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImJhcmNvZGUiLCB0cnVlKTsKICAgIHRoaXMuY2hhckVuY29kaW5nID0gZ2V0S2V5d29yZCh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuY2hhckVuY29kaW5nID8gYXR0cmlidXRlcy5jaGFyRW5jb2RpbmcudG9Mb3dlckNhc2UoKSA6ICIiLAogICAgICBkZWZhdWx0VmFsdWU6ICIiLAogICAgICB2YWxpZGF0ZTogayA9PiBbInV0Zi04IiwgImJpZy1maXZlIiwgImZvbnRzcGVjaWZpYyIsICJnYmsiLCAiZ2ItMTgwMzAiLCAiZ2ItMjMxMiIsICJrc2MtNTYwMSIsICJub25lIiwgInNoaWZ0LWppcyIsICJ1Y3MtMiIsICJ1dGYtMTYiXS5pbmNsdWRlcyhrKSB8fCBrLm1hdGNoKC9pc28tODg1OS1cZHsyfS8pCiAgICB9KTsKICAgIHRoaXMuY2hlY2tzdW0gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5jaGVja3N1bSwgWyJub25lIiwgIjFtb2QxMCIsICIxbW9kMTBfMW1vZDExIiwgIjJtb2QxMCIsICJhdXRvIl0pOwogICAgdGhpcy5kYXRhQ29sdW1uQ291bnQgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5kYXRhQ29sdW1uQ291bnQsCiAgICAgIGRlZmF1bHRWYWx1ZTogLTEsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gMAogICAgfSk7CiAgICB0aGlzLmRhdGFMZW5ndGggPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5kYXRhTGVuZ3RoLAogICAgICBkZWZhdWx0VmFsdWU6IC0xLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDAKICAgIH0pOwogICAgdGhpcy5kYXRhUHJlcCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmRhdGFQcmVwLCBbIm5vbmUiLCAiZmxhdGVDb21wcmVzcyJdKTsKICAgIHRoaXMuZGF0YVJvd0NvdW50ID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuZGF0YVJvd0NvdW50LAogICAgICBkZWZhdWx0VmFsdWU6IC0xLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDAKICAgIH0pOwogICAgdGhpcy5lbmRDaGFyID0gYXR0cmlidXRlcy5lbmRDaGFyIHx8ICIiOwogICAgdGhpcy5lcnJvckNvcnJlY3Rpb25MZXZlbCA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmVycm9yQ29ycmVjdGlvbkxldmVsLAogICAgICBkZWZhdWx0VmFsdWU6IC0xLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDAgJiYgeCA8PSA4CiAgICB9KTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5tb2R1bGVIZWlnaHQgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLm1vZHVsZUhlaWdodCwgIjVtbSIpOwogICAgdGhpcy5tb2R1bGVXaWR0aCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubW9kdWxlV2lkdGgsICIwLjI1bW0iKTsKICAgIHRoaXMucHJpbnRDaGVja0RpZ2l0ID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMucHJpbnRDaGVja0RpZ2l0LAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEKICAgIH0pOwogICAgdGhpcy5yb3dDb2x1bW5SYXRpbyA9IGdldFJhdGlvKGF0dHJpYnV0ZXMucm93Q29sdW1uUmF0aW8pOwogICAgdGhpcy5zdGFydENoYXIgPSBhdHRyaWJ1dGVzLnN0YXJ0Q2hhciB8fCAiIjsKICAgIHRoaXMudGV4dExvY2F0aW9uID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudGV4dExvY2F0aW9uLCBbImJlbG93IiwgImFib3ZlIiwgImFib3ZlRW1iZWRkZWQiLCAiYmVsb3dFbWJlZGRlZCIsICJub25lIl0pOwogICAgdGhpcy50cnVuY2F0ZSA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnRydW5jYXRlLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEKICAgIH0pOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSA/IGF0dHJpYnV0ZXMudHlwZS50b0xvd2VyQ2FzZSgpIDogIiIsIFsiYXp0ZWMiLCAiY29kYWJhciIsICJjb2RlMm9mNWluZHVzdHJpYWwiLCAiY29kZTJvZjVpbnRlcmxlYXZlZCIsICJjb2RlMm9mNW1hdHJpeCIsICJjb2RlMm9mNXN0YW5kYXJkIiwgImNvZGUzb2Y5IiwgImNvZGUzb2Y5ZXh0ZW5kZWQiLCAiY29kZTExIiwgImNvZGU0OSIsICJjb2RlOTMiLCAiY29kZTEyOCIsICJjb2RlMTI4YSIsICJjb2RlMTI4YiIsICJjb2RlMTI4YyIsICJjb2RlMTI4c3NjYyIsICJkYXRhbWF0cml4IiwgImVhbjgiLCAiZWFuOGFkZDIiLCAiZWFuOGFkZDUiLCAiZWFuMTMiLCAiZWFuMTNhZGQyIiwgImVhbjEzYWRkNSIsICJlYW4xM3B3Y2QiLCAiZmltIiwgImxvZ21hcnMiLCAibWF4aWNvZGUiLCAibXNpIiwgInBkZjQxNyIsICJwZGY0MTdtYWNybyIsICJwbGVzc2V5IiwgInBvc3RhdXNjdXN0MiIsICJwb3N0YXVzY3VzdDMiLCAicG9zdGF1c3JlcGx5cGFpZCIsICJwb3N0YXVzc3RhbmRhcmQiLCAicG9zdHVrcm00c2NjIiwgInBvc3R1c2RwYmMiLCAicG9zdHVzaW1iIiwgInBvc3R1c3N0YW5kYXJkIiwgInBvc3R1czV6aXAiLCAicXJjb2RlIiwgInJmaWQiLCAicnNzMTQiLCAicnNzMTRleHBhbmRlZCIsICJyc3MxNGxpbWl0ZWQiLCAicnNzMTRzdGFja2VkIiwgInJzczE0c3RhY2tlZG9tbmkiLCAicnNzMTR0cnVuY2F0ZWQiLCAidGVsZXBlbiIsICJ1Y2MxMjgiLCAidWNjMTI4cmFuZG9tIiwgInVjYzEyOHNzY2MiLCAidXBjYSIsICJ1cGNhYWRkMiIsICJ1cGNhYWRkNSIsICJ1cGNhcHdjZCIsICJ1cGNlIiwgInVwY2VhZGQyIiwgInVwY2VhZGQ1IiwgInVwY2VhbjIiLCAidXBjZWFuNSIsICJ1cHNtYXhpY29kZSJdKTsKICAgIHRoaXMudXBzTW9kZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnVwc01vZGUsIFsidXNDYXJyaWVyIiwgImludGVybmF0aW9uYWxDYXJyaWVyIiwgInNlY3VyZVN5bWJvbCIsICJzdGFuZGFyZFN5bWJvbCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLndpZGVOYXJyb3dSYXRpbyA9IGdldFJhdGlvKGF0dHJpYnV0ZXMud2lkZU5hcnJvd1JhdGlvKTsKICAgIHRoaXMuZW5jcnlwdCA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQp9CmNsYXNzIEJpbmQgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYmluZCIsIHRydWUpOwogICAgdGhpcy5tYXRjaCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLm1hdGNoLCBbIm9uY2UiLCAiZGF0YVJlZiIsICJnbG9iYWwiLCAibm9uZSJdKTsKICAgIHRoaXMucmVmID0gYXR0cmlidXRlcy5yZWYgfHwgIiI7CiAgICB0aGlzLnBpY3R1cmUgPSBudWxsOwogIH0KfQpjbGFzcyBCaW5kSXRlbXMgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYmluZEl0ZW1zIik7CiAgICB0aGlzLmNvbm5lY3Rpb24gPSBhdHRyaWJ1dGVzLmNvbm5lY3Rpb24gfHwgIiI7CiAgICB0aGlzLmxhYmVsUmVmID0gYXR0cmlidXRlcy5sYWJlbFJlZiB8fCAiIjsKICAgIHRoaXMucmVmID0gYXR0cmlidXRlcy5yZWYgfHwgIiI7CiAgICB0aGlzLnZhbHVlUmVmID0gYXR0cmlidXRlcy52YWx1ZVJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgQm9va2VuZCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJib29rZW5kIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubGVhZGVyID0gYXR0cmlidXRlcy5sZWFkZXIgfHwgIiI7CiAgICB0aGlzLnRyYWlsZXIgPSBhdHRyaWJ1dGVzLnRyYWlsZXIgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBCb29sZWFuRWxlbWVudCBleHRlbmRzIE9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImJvb2xlYW4iKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICByZXR1cm4gdmFsdWVUb0h0bWwodGhpc1skY29udGVudF0gPT09IDEgPyAiMSIgOiAiMCIpOwogIH0KfQpjbGFzcyBCb3JkZXIgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYm9yZGVyIiwgdHJ1ZSk7CiAgICB0aGlzLmJyZWFrID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuYnJlYWssIFsiY2xvc2UiLCAib3BlbiJdKTsKICAgIHRoaXMuaGFuZCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmhhbmQsIFsiZXZlbiIsICJsZWZ0IiwgInJpZ2h0Il0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnByZXNlbmNlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMucHJlc2VuY2UsIFsidmlzaWJsZSIsICJoaWRkZW4iLCAiaW5hY3RpdmUiLCAiaW52aXNpYmxlIl0pOwogICAgdGhpcy5yZWxldmFudCA9IGdldFJlbGV2YW50KGF0dHJpYnV0ZXMucmVsZXZhbnQpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuY29ybmVyID0gbmV3IFhGQU9iamVjdEFycmF5KDQpOwogICAgdGhpcy5lZGdlID0gbmV3IFhGQU9iamVjdEFycmF5KDQpOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5maWxsID0gbnVsbDsKICAgIHRoaXMubWFyZ2luID0gbnVsbDsKICB9CiAgWyRnZXRFeHRyYV0oKSB7CiAgICBpZiAoIXRoaXNbJGV4dHJhXSkgewogICAgICBjb25zdCBlZGdlcyA9IHRoaXMuZWRnZS5jaGlsZHJlbi5zbGljZSgpOwogICAgICBpZiAoZWRnZXMubGVuZ3RoIDwgNCkgewogICAgICAgIGNvbnN0IGRlZmF1bHRFZGdlID0gZWRnZXMuYXQoLTEpIHx8IG5ldyBFZGdlKHt9KTsKICAgICAgICBmb3IgKGxldCBpID0gZWRnZXMubGVuZ3RoOyBpIDwgNDsgaSsrKSB7CiAgICAgICAgICBlZGdlcy5wdXNoKGRlZmF1bHRFZGdlKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3Qgd2lkdGhzID0gZWRnZXMubWFwKGVkZ2UgPT4gZWRnZS50aGlja25lc3MpOwogICAgICBjb25zdCBpbnNldHMgPSBbMCwgMCwgMCwgMF07CiAgICAgIGlmICh0aGlzLm1hcmdpbikgewogICAgICAgIGluc2V0c1swXSA9IHRoaXMubWFyZ2luLnRvcEluc2V0OwogICAgICAgIGluc2V0c1sxXSA9IHRoaXMubWFyZ2luLnJpZ2h0SW5zZXQ7CiAgICAgICAgaW5zZXRzWzJdID0gdGhpcy5tYXJnaW4uYm90dG9tSW5zZXQ7CiAgICAgICAgaW5zZXRzWzNdID0gdGhpcy5tYXJnaW4ubGVmdEluc2V0OwogICAgICB9CiAgICAgIHRoaXNbJGV4dHJhXSA9IHsKICAgICAgICB3aWR0aHMsCiAgICAgICAgaW5zZXRzLAogICAgICAgIGVkZ2VzCiAgICAgIH07CiAgICB9CiAgICByZXR1cm4gdGhpc1skZXh0cmFdOwogIH0KICBbJHRvU3R5bGVdKCkgewogICAgY29uc3QgewogICAgICBlZGdlcwogICAgfSA9IHRoaXNbJGdldEV4dHJhXSgpOwogICAgY29uc3QgZWRnZVN0eWxlcyA9IGVkZ2VzLm1hcChub2RlID0+IHsKICAgICAgY29uc3Qgc3R5bGUgPSBub2RlWyR0b1N0eWxlXSgpOwogICAgICBzdHlsZS5jb2xvciB8fD0gIiMwMDAwMDAiOwogICAgICByZXR1cm4gc3R5bGU7CiAgICB9KTsKICAgIGNvbnN0IHN0eWxlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGlmICh0aGlzLm1hcmdpbikgewogICAgICBPYmplY3QuYXNzaWduKHN0eWxlLCB0aGlzLm1hcmdpblskdG9TdHlsZV0oKSk7CiAgICB9CiAgICBpZiAodGhpcy5maWxsPy5wcmVzZW5jZSA9PT0gInZpc2libGUiKSB7CiAgICAgIE9iamVjdC5hc3NpZ24oc3R5bGUsIHRoaXMuZmlsbFskdG9TdHlsZV0oKSk7CiAgICB9CiAgICBpZiAodGhpcy5jb3JuZXIuY2hpbGRyZW4uc29tZShub2RlID0+IG5vZGUucmFkaXVzICE9PSAwKSkgewogICAgICBjb25zdCBjb3JuZXJTdHlsZXMgPSB0aGlzLmNvcm5lci5jaGlsZHJlbi5tYXAobm9kZSA9PiBub2RlWyR0b1N0eWxlXSgpKTsKICAgICAgaWYgKGNvcm5lclN0eWxlcy5sZW5ndGggPT09IDIgfHwgY29ybmVyU3R5bGVzLmxlbmd0aCA9PT0gMykgewogICAgICAgIGNvbnN0IGxhc3QgPSBjb3JuZXJTdHlsZXMuYXQoLTEpOwogICAgICAgIGZvciAobGV0IGkgPSBjb3JuZXJTdHlsZXMubGVuZ3RoOyBpIDwgNDsgaSsrKSB7CiAgICAgICAgICBjb3JuZXJTdHlsZXMucHVzaChsYXN0KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgc3R5bGUuYm9yZGVyUmFkaXVzID0gY29ybmVyU3R5bGVzLm1hcChzID0+IHMucmFkaXVzKS5qb2luKCIgIik7CiAgICB9CiAgICBzd2l0Y2ggKHRoaXMucHJlc2VuY2UpIHsKICAgICAgY2FzZSAiaW52aXNpYmxlIjoKICAgICAgY2FzZSAiaGlkZGVuIjoKICAgICAgICBzdHlsZS5ib3JkZXJTdHlsZSA9ICIiOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJpbmFjdGl2ZSI6CiAgICAgICAgc3R5bGUuYm9yZGVyU3R5bGUgPSAibm9uZSI7CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgc3R5bGUuYm9yZGVyU3R5bGUgPSBlZGdlU3R5bGVzLm1hcChzID0+IHMuc3R5bGUpLmpvaW4oIiAiKTsKICAgICAgICBicmVhazsKICAgIH0KICAgIHN0eWxlLmJvcmRlcldpZHRoID0gZWRnZVN0eWxlcy5tYXAocyA9PiBzLndpZHRoKS5qb2luKCIgIik7CiAgICBzdHlsZS5ib3JkZXJDb2xvciA9IGVkZ2VTdHlsZXMubWFwKHMgPT4gcy5jb2xvcikuam9pbigiICIpOwogICAgcmV0dXJuIHN0eWxlOwogIH0KfQpjbGFzcyBCcmVhayBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJicmVhayIsIHRydWUpOwogICAgdGhpcy5hZnRlciA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmFmdGVyLCBbImF1dG8iLCAiY29udGVudEFyZWEiLCAicGFnZUFyZWEiLCAicGFnZUV2ZW4iLCAicGFnZU9kZCJdKTsKICAgIHRoaXMuYWZ0ZXJUYXJnZXQgPSBhdHRyaWJ1dGVzLmFmdGVyVGFyZ2V0IHx8ICIiOwogICAgdGhpcy5iZWZvcmUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5iZWZvcmUsIFsiYXV0byIsICJjb250ZW50QXJlYSIsICJwYWdlQXJlYSIsICJwYWdlRXZlbiIsICJwYWdlT2RkIl0pOwogICAgdGhpcy5iZWZvcmVUYXJnZXQgPSBhdHRyaWJ1dGVzLmJlZm9yZVRhcmdldCB8fCAiIjsKICAgIHRoaXMuYm9va2VuZExlYWRlciA9IGF0dHJpYnV0ZXMuYm9va2VuZExlYWRlciB8fCAiIjsKICAgIHRoaXMuYm9va2VuZFRyYWlsZXIgPSBhdHRyaWJ1dGVzLmJvb2tlbmRUcmFpbGVyIHx8ICIiOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm92ZXJmbG93TGVhZGVyID0gYXR0cmlidXRlcy5vdmVyZmxvd0xlYWRlciB8fCAiIjsKICAgIHRoaXMub3ZlcmZsb3dUYXJnZXQgPSBhdHRyaWJ1dGVzLm92ZXJmbG93VGFyZ2V0IHx8ICIiOwogICAgdGhpcy5vdmVyZmxvd1RyYWlsZXIgPSBhdHRyaWJ1dGVzLm92ZXJmbG93VHJhaWxlciB8fCAiIjsKICAgIHRoaXMuc3RhcnROZXcgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5zdGFydE5ldywKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQp9CmNsYXNzIEJyZWFrQWZ0ZXIgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiYnJlYWtBZnRlciIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmxlYWRlciA9IGF0dHJpYnV0ZXMubGVhZGVyIHx8ICIiOwogICAgdGhpcy5zdGFydE5ldyA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnN0YXJ0TmV3LAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEKICAgIH0pOwogICAgdGhpcy50YXJnZXQgPSBhdHRyaWJ1dGVzLnRhcmdldCB8fCAiIjsKICAgIHRoaXMudGFyZ2V0VHlwZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnRhcmdldFR5cGUsIFsiYXV0byIsICJjb250ZW50QXJlYSIsICJwYWdlQXJlYSJdKTsKICAgIHRoaXMudHJhaWxlciA9IGF0dHJpYnV0ZXMudHJhaWxlciB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnNjcmlwdCA9IG51bGw7CiAgfQp9CmNsYXNzIEJyZWFrQmVmb3JlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImJyZWFrQmVmb3JlIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubGVhZGVyID0gYXR0cmlidXRlcy5sZWFkZXIgfHwgIiI7CiAgICB0aGlzLnN0YXJ0TmV3ID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuc3RhcnROZXcsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLnRhcmdldCA9IGF0dHJpYnV0ZXMudGFyZ2V0IHx8ICIiOwogICAgdGhpcy50YXJnZXRUeXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudGFyZ2V0VHlwZSwgWyJhdXRvIiwgImNvbnRlbnRBcmVhIiwgInBhZ2VBcmVhIl0pOwogICAgdGhpcy50cmFpbGVyID0gYXR0cmlidXRlcy50cmFpbGVyIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuc2NyaXB0ID0gbnVsbDsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICB0aGlzWyRleHRyYV0gPSB7fTsKICAgIHJldHVybiBIVE1MUmVzdWx0LkZBSUxVUkU7CiAgfQp9CmNsYXNzIEJ1dHRvbiBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJidXR0b24iLCB0cnVlKTsKICAgIHRoaXMuaGlnaGxpZ2h0ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuaGlnaGxpZ2h0LCBbImludmVydGVkIiwgIm5vbmUiLCAib3V0bGluZSIsICJwdXNoIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IHBhcmVudCA9IHRoaXNbJGdldFBhcmVudF0oKTsKICAgIGNvbnN0IGdyYW5kcGEgPSBwYXJlbnRbJGdldFBhcmVudF0oKTsKICAgIGNvbnN0IGh0bWxCdXR0b24gPSB7CiAgICAgIG5hbWU6ICJidXR0b24iLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgaWQ6IHRoaXNbJHVpZF0sCiAgICAgICAgY2xhc3M6IFsieGZhQnV0dG9uIl0sCiAgICAgICAgc3R5bGU6IHt9CiAgICAgIH0sCiAgICAgIGNoaWxkcmVuOiBbXQogICAgfTsKICAgIGZvciAoY29uc3QgZXZlbnQgb2YgZ3JhbmRwYS5ldmVudC5jaGlsZHJlbikgewogICAgICBpZiAoZXZlbnQuYWN0aXZpdHkgIT09ICJjbGljayIgfHwgIWV2ZW50LnNjcmlwdCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGpzVVJMID0gcmVjb3ZlckpzVVJMKGV2ZW50LnNjcmlwdFskY29udGVudF0pOwogICAgICBpZiAoIWpzVVJMKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgaHJlZiA9IGZpeFVSTChqc1VSTC51cmwpOwogICAgICBpZiAoIWhyZWYpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBodG1sQnV0dG9uLmNoaWxkcmVuLnB1c2goewogICAgICAgIG5hbWU6ICJhIiwKICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICBpZDogImxpbmsiICsgdGhpc1skdWlkXSwKICAgICAgICAgIGhyZWYsCiAgICAgICAgICBuZXdXaW5kb3c6IGpzVVJMLm5ld1dpbmRvdywKICAgICAgICAgIGNsYXNzOiBbInhmYUxpbmsiXSwKICAgICAgICAgIHN0eWxlOiB7fQogICAgICAgIH0sCiAgICAgICAgY2hpbGRyZW46IFtdCiAgICAgIH0pOwogICAgfQogICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhodG1sQnV0dG9uKTsKICB9Cn0KY2xhc3MgQ2FsY3VsYXRlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImNhbGN1bGF0ZSIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm92ZXJyaWRlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMub3ZlcnJpZGUsIFsiZGlzYWJsZWQiLCAiZXJyb3IiLCAiaWdub3JlIiwgIndhcm5pbmciXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tZXNzYWdlID0gbnVsbDsKICAgIHRoaXMuc2NyaXB0ID0gbnVsbDsKICB9Cn0KY2xhc3MgQ2FwdGlvbiBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJjYXB0aW9uIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMucGxhY2VtZW50ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMucGxhY2VtZW50LCBbImxlZnQiLCAiYm90dG9tIiwgImlubGluZSIsICJyaWdodCIsICJ0b3AiXSk7CiAgICB0aGlzLnByZXNlbmNlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMucHJlc2VuY2UsIFsidmlzaWJsZSIsICJoaWRkZW4iLCAiaW5hY3RpdmUiLCAiaW52aXNpYmxlIl0pOwogICAgdGhpcy5yZXNlcnZlID0gTWF0aC5jZWlsKGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMucmVzZXJ2ZSkpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMuZm9udCA9IG51bGw7CiAgICB0aGlzLm1hcmdpbiA9IG51bGw7CiAgICB0aGlzLnBhcmEgPSBudWxsOwogICAgdGhpcy52YWx1ZSA9IG51bGw7CiAgfQogIFskc2V0VmFsdWVdKHZhbHVlKSB7CiAgICBfc2V0VmFsdWUodGhpcywgdmFsdWUpOwogIH0KICBbJGdldEV4dHJhXShhdmFpbGFibGVTcGFjZSkgewogICAgaWYgKCF0aGlzWyRleHRyYV0pIHsKICAgICAgbGV0IHsKICAgICAgICB3aWR0aCwKICAgICAgICBoZWlnaHQKICAgICAgfSA9IGF2YWlsYWJsZVNwYWNlOwogICAgICBzd2l0Y2ggKHRoaXMucGxhY2VtZW50KSB7CiAgICAgICAgY2FzZSAibGVmdCI6CiAgICAgICAgY2FzZSAicmlnaHQiOgogICAgICAgIGNhc2UgImlubGluZSI6CiAgICAgICAgICB3aWR0aCA9IHRoaXMucmVzZXJ2ZSA8PSAwID8gd2lkdGggOiB0aGlzLnJlc2VydmU7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJ0b3AiOgogICAgICAgIGNhc2UgImJvdHRvbSI6CiAgICAgICAgICBoZWlnaHQgPSB0aGlzLnJlc2VydmUgPD0gMCA/IGhlaWdodCA6IHRoaXMucmVzZXJ2ZTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIHRoaXNbJGV4dHJhXSA9IGxheW91dE5vZGUodGhpcywgewogICAgICAgIHdpZHRoLAogICAgICAgIGhlaWdodAogICAgICB9KTsKICAgIH0KICAgIHJldHVybiB0aGlzWyRleHRyYV07CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgaWYgKCF0aGlzLnZhbHVlKSB7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkVNUFRZOwogICAgfQogICAgdGhpc1skcHVzaFBhcmFdKCk7CiAgICBjb25zdCB2YWx1ZSA9IHRoaXMudmFsdWVbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpLmh0bWw7CiAgICBpZiAoIXZhbHVlKSB7CiAgICAgIHRoaXNbJHBvcFBhcmFdKCk7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkVNUFRZOwogICAgfQogICAgY29uc3Qgc2F2ZWRSZXNlcnZlID0gdGhpcy5yZXNlcnZlOwogICAgaWYgKHRoaXMucmVzZXJ2ZSA8PSAwKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICB3LAogICAgICAgIGgKICAgICAgfSA9IHRoaXNbJGdldEV4dHJhXShhdmFpbGFibGVTcGFjZSk7CiAgICAgIHN3aXRjaCAodGhpcy5wbGFjZW1lbnQpIHsKICAgICAgICBjYXNlICJsZWZ0IjoKICAgICAgICBjYXNlICJyaWdodCI6CiAgICAgICAgY2FzZSAiaW5saW5lIjoKICAgICAgICAgIHRoaXMucmVzZXJ2ZSA9IHc7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJ0b3AiOgogICAgICAgIGNhc2UgImJvdHRvbSI6CiAgICAgICAgICB0aGlzLnJlc2VydmUgPSBoOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGNoaWxkcmVuID0gW107CiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAic3RyaW5nIikgewogICAgICBjaGlsZHJlbi5wdXNoKHsKICAgICAgICBuYW1lOiAiI3RleHQiLAogICAgICAgIHZhbHVlCiAgICAgIH0pOwogICAgfSBlbHNlIHsKICAgICAgY2hpbGRyZW4ucHVzaCh2YWx1ZSk7CiAgICB9CiAgICBjb25zdCBzdHlsZSA9IHRvU3R5bGUodGhpcywgImZvbnQiLCAibWFyZ2luIiwgInZpc2liaWxpdHkiKTsKICAgIHN3aXRjaCAodGhpcy5wbGFjZW1lbnQpIHsKICAgICAgY2FzZSAibGVmdCI6CiAgICAgIGNhc2UgInJpZ2h0IjoKICAgICAgICBpZiAodGhpcy5yZXNlcnZlID4gMCkgewogICAgICAgICAgc3R5bGUud2lkdGggPSBtZWFzdXJlVG9TdHJpbmcodGhpcy5yZXNlcnZlKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgInRvcCI6CiAgICAgIGNhc2UgImJvdHRvbSI6CiAgICAgICAgaWYgKHRoaXMucmVzZXJ2ZSA+IDApIHsKICAgICAgICAgIHN0eWxlLmhlaWdodCA9IG1lYXN1cmVUb1N0cmluZyh0aGlzLnJlc2VydmUpOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgIH0KICAgIHNldFBhcmEodGhpcywgbnVsbCwgdmFsdWUpOwogICAgdGhpc1skcG9wUGFyYV0oKTsKICAgIHRoaXMucmVzZXJ2ZSA9IHNhdmVkUmVzZXJ2ZTsKICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICBuYW1lOiAiZGl2IiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIHN0eWxlLAogICAgICAgIGNsYXNzOiBbInhmYUNhcHRpb24iXQogICAgICB9LAogICAgICBjaGlsZHJlbgogICAgfSk7CiAgfQp9CmNsYXNzIENlcnRpZmljYXRlIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImNlcnRpZmljYXRlIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIENlcnRpZmljYXRlcyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJjZXJ0aWZpY2F0ZXMiLCB0cnVlKTsKICAgIHRoaXMuY3JlZGVudGlhbFNlcnZlclBvbGljeSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmNyZWRlbnRpYWxTZXJ2ZXJQb2xpY3ksIFsib3B0aW9uYWwiLCAicmVxdWlyZWQiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXJsID0gYXR0cmlidXRlcy51cmwgfHwgIiI7CiAgICB0aGlzLnVybFBvbGljeSA9IGF0dHJpYnV0ZXMudXJsUG9saWN5IHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZW5jcnlwdGlvbiA9IG51bGw7CiAgICB0aGlzLmlzc3VlcnMgPSBudWxsOwogICAgdGhpcy5rZXlVc2FnZSA9IG51bGw7CiAgICB0aGlzLm9pZHMgPSBudWxsOwogICAgdGhpcy5zaWduaW5nID0gbnVsbDsKICAgIHRoaXMuc3ViamVjdEROcyA9IG51bGw7CiAgfQp9CmNsYXNzIENoZWNrQnV0dG9uIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImNoZWNrQnV0dG9uIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubWFyayA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLm1hcmssIFsiZGVmYXVsdCIsICJjaGVjayIsICJjaXJjbGUiLCAiY3Jvc3MiLCAiZGlhbW9uZCIsICJzcXVhcmUiLCAic3RhciJdKTsKICAgIHRoaXMuc2hhcGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5zaGFwZSwgWyJzcXVhcmUiLCAicm91bmQiXSk7CiAgICB0aGlzLnNpemUgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnNpemUsICIxMHB0Iik7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5ib3JkZXIgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IHN0eWxlID0gdG9TdHlsZSh0aGlzLCAibWFyZ2luIik7CiAgICBjb25zdCBzaXplID0gbWVhc3VyZVRvU3RyaW5nKHRoaXMuc2l6ZSk7CiAgICBzdHlsZS53aWR0aCA9IHN0eWxlLmhlaWdodCA9IHNpemU7CiAgICBsZXQgdHlwZTsKICAgIGxldCBjbGFzc05hbWU7CiAgICBsZXQgZ3JvdXBJZDsKICAgIGNvbnN0IGZpZWxkID0gdGhpc1skZ2V0UGFyZW50XSgpWyRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBpdGVtcyA9IGZpZWxkLml0ZW1zLmNoaWxkcmVuLmxlbmd0aCAmJiBmaWVsZC5pdGVtcy5jaGlsZHJlblswXVskdG9IVE1MXSgpLmh0bWwgfHwgW107CiAgICBjb25zdCBleHBvcnRlZFZhbHVlID0gewogICAgICBvbjogKGl0ZW1zWzBdICE9PSB1bmRlZmluZWQgPyBpdGVtc1swXSA6ICJvbiIpLnRvU3RyaW5nKCksCiAgICAgIG9mZjogKGl0ZW1zWzFdICE9PSB1bmRlZmluZWQgPyBpdGVtc1sxXSA6ICJvZmYiKS50b1N0cmluZygpCiAgICB9OwogICAgY29uc3QgdmFsdWUgPSBmaWVsZC52YWx1ZT8uWyR0ZXh0XSgpIHx8ICJvZmYiOwogICAgY29uc3QgY2hlY2tlZCA9IHZhbHVlID09PSBleHBvcnRlZFZhbHVlLm9uIHx8IHVuZGVmaW5lZDsKICAgIGNvbnN0IGNvbnRhaW5lciA9IGZpZWxkWyRnZXRTdWJmb3JtUGFyZW50XSgpOwogICAgY29uc3QgZmllbGRJZCA9IGZpZWxkWyR1aWRdOwogICAgbGV0IGRhdGFJZDsKICAgIGlmIChjb250YWluZXIgaW5zdGFuY2VvZiBFeGNsR3JvdXApIHsKICAgICAgZ3JvdXBJZCA9IGNvbnRhaW5lclskdWlkXTsKICAgICAgdHlwZSA9ICJyYWRpbyI7CiAgICAgIGNsYXNzTmFtZSA9ICJ4ZmFSYWRpbyI7CiAgICAgIGRhdGFJZCA9IGNvbnRhaW5lclskZGF0YV0/LlskdWlkXSB8fCBjb250YWluZXJbJHVpZF07CiAgICB9IGVsc2UgewogICAgICB0eXBlID0gImNoZWNrYm94IjsKICAgICAgY2xhc3NOYW1lID0gInhmYUNoZWNrYm94IjsKICAgICAgZGF0YUlkID0gZmllbGRbJGRhdGFdPy5bJHVpZF0gfHwgZmllbGRbJHVpZF07CiAgICB9CiAgICBjb25zdCBpbnB1dCA9IHsKICAgICAgbmFtZTogImlucHV0IiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIGNsYXNzOiBbY2xhc3NOYW1lXSwKICAgICAgICBzdHlsZSwKICAgICAgICBmaWVsZElkLAogICAgICAgIGRhdGFJZCwKICAgICAgICB0eXBlLAogICAgICAgIGNoZWNrZWQsCiAgICAgICAgeGZhT246IGV4cG9ydGVkVmFsdWUub24sCiAgICAgICAgeGZhT2ZmOiBleHBvcnRlZFZhbHVlLm9mZiwKICAgICAgICAiYXJpYS1sYWJlbCI6IGFyaWFMYWJlbChmaWVsZCksCiAgICAgICAgImFyaWEtcmVxdWlyZWQiOiBmYWxzZQogICAgICB9CiAgICB9OwogICAgaWYgKGdyb3VwSWQpIHsKICAgICAgaW5wdXQuYXR0cmlidXRlcy5uYW1lID0gZ3JvdXBJZDsKICAgIH0KICAgIGlmIChpc1JlcXVpcmVkKGZpZWxkKSkgewogICAgICBpbnB1dC5hdHRyaWJ1dGVzWyJhcmlhLXJlcXVpcmVkIl0gPSB0cnVlOwogICAgICBpbnB1dC5hdHRyaWJ1dGVzLnJlcXVpcmVkID0gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICBuYW1lOiAibGFiZWwiLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgY2xhc3M6IFsieGZhTGFiZWwiXQogICAgICB9LAogICAgICBjaGlsZHJlbjogW2lucHV0XQogICAgfSk7CiAgfQp9CmNsYXNzIENob2ljZUxpc3QgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiY2hvaWNlTGlzdCIsIHRydWUpOwogICAgdGhpcy5jb21taXRPbiA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmNvbW1pdE9uLCBbInNlbGVjdCIsICJleGl0Il0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm9wZW4gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5vcGVuLCBbInVzZXJDb250cm9sIiwgImFsd2F5cyIsICJtdWx0aVNlbGVjdCIsICJvbkVudHJ5Il0pOwogICAgdGhpcy50ZXh0RW50cnkgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy50ZXh0RW50cnksCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5ib3JkZXIgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IHN0eWxlID0gdG9TdHlsZSh0aGlzLCAiYm9yZGVyIiwgIm1hcmdpbiIpOwogICAgY29uc3QgdWkgPSB0aGlzWyRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBmaWVsZCA9IHVpWyRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBmb250U2l6ZSA9IGZpZWxkLmZvbnQ/LnNpemUgfHwgMTA7CiAgICBjb25zdCBvcHRpb25TdHlsZSA9IHsKICAgICAgZm9udFNpemU6IGBjYWxjKCR7Zm9udFNpemV9cHggKiB2YXIoLS10b3RhbC1zY2FsZS1mYWN0b3IpKWAKICAgIH07CiAgICBjb25zdCBjaGlsZHJlbiA9IFtdOwogICAgaWYgKGZpZWxkLml0ZW1zLmNoaWxkcmVuLmxlbmd0aCA+IDApIHsKICAgICAgY29uc3QgaXRlbXMgPSBmaWVsZC5pdGVtczsKICAgICAgbGV0IGRpc3BsYXllZEluZGV4ID0gMDsKICAgICAgbGV0IHNhdmVJbmRleCA9IDA7CiAgICAgIGlmIChpdGVtcy5jaGlsZHJlbi5sZW5ndGggPT09IDIpIHsKICAgICAgICBkaXNwbGF5ZWRJbmRleCA9IGl0ZW1zLmNoaWxkcmVuWzBdLnNhdmU7CiAgICAgICAgc2F2ZUluZGV4ID0gMSAtIGRpc3BsYXllZEluZGV4OwogICAgICB9CiAgICAgIGNvbnN0IGRpc3BsYXllZCA9IGl0ZW1zLmNoaWxkcmVuW2Rpc3BsYXllZEluZGV4XVskdG9IVE1MXSgpLmh0bWw7CiAgICAgIGNvbnN0IHZhbHVlcyA9IGl0ZW1zLmNoaWxkcmVuW3NhdmVJbmRleF1bJHRvSFRNTF0oKS5odG1sOwogICAgICBsZXQgc2VsZWN0ZWQgPSBmYWxzZTsKICAgICAgY29uc3QgdmFsdWUgPSBmaWVsZC52YWx1ZT8uWyR0ZXh0XSgpIHx8ICIiOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBkaXNwbGF5ZWQubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbnN0IG9wdGlvbiA9IHsKICAgICAgICAgIG5hbWU6ICJvcHRpb24iLAogICAgICAgICAgYXR0cmlidXRlczogewogICAgICAgICAgICB2YWx1ZTogdmFsdWVzW2ldIHx8IGRpc3BsYXllZFtpXSwKICAgICAgICAgICAgc3R5bGU6IG9wdGlvblN0eWxlCiAgICAgICAgICB9LAogICAgICAgICAgdmFsdWU6IGRpc3BsYXllZFtpXQogICAgICAgIH07CiAgICAgICAgaWYgKHZhbHVlc1tpXSA9PT0gdmFsdWUpIHsKICAgICAgICAgIG9wdGlvbi5hdHRyaWJ1dGVzLnNlbGVjdGVkID0gc2VsZWN0ZWQgPSB0cnVlOwogICAgICAgIH0KICAgICAgICBjaGlsZHJlbi5wdXNoKG9wdGlvbik7CiAgICAgIH0KICAgICAgaWYgKCFzZWxlY3RlZCkgewogICAgICAgIGNoaWxkcmVuLnNwbGljZSgwLCAwLCB7CiAgICAgICAgICBuYW1lOiAib3B0aW9uIiwKICAgICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgICAgaGlkZGVuOiB0cnVlLAogICAgICAgICAgICBzZWxlY3RlZDogdHJ1ZQogICAgICAgICAgfSwKICAgICAgICAgIHZhbHVlOiAiICIKICAgICAgICB9KTsKICAgICAgfQogICAgfQogICAgY29uc3Qgc2VsZWN0QXR0cmlidXRlcyA9IHsKICAgICAgY2xhc3M6IFsieGZhU2VsZWN0Il0sCiAgICAgIGZpZWxkSWQ6IGZpZWxkWyR1aWRdLAogICAgICBkYXRhSWQ6IGZpZWxkWyRkYXRhXT8uWyR1aWRdIHx8IGZpZWxkWyR1aWRdLAogICAgICBzdHlsZSwKICAgICAgImFyaWEtbGFiZWwiOiBhcmlhTGFiZWwoZmllbGQpLAogICAgICAiYXJpYS1yZXF1aXJlZCI6IGZhbHNlCiAgICB9OwogICAgaWYgKGlzUmVxdWlyZWQoZmllbGQpKSB7CiAgICAgIHNlbGVjdEF0dHJpYnV0ZXNbImFyaWEtcmVxdWlyZWQiXSA9IHRydWU7CiAgICAgIHNlbGVjdEF0dHJpYnV0ZXMucmVxdWlyZWQgPSB0cnVlOwogICAgfQogICAgaWYgKHRoaXMub3BlbiA9PT0gIm11bHRpU2VsZWN0IikgewogICAgICBzZWxlY3RBdHRyaWJ1dGVzLm11bHRpcGxlID0gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICBuYW1lOiAibGFiZWwiLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgY2xhc3M6IFsieGZhTGFiZWwiXQogICAgICB9LAogICAgICBjaGlsZHJlbjogW3sKICAgICAgICBuYW1lOiAic2VsZWN0IiwKICAgICAgICBjaGlsZHJlbiwKICAgICAgICBhdHRyaWJ1dGVzOiBzZWxlY3RBdHRyaWJ1dGVzCiAgICAgIH1dCiAgICB9KTsKICB9Cn0KY2xhc3MgQ29sb3IgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiY29sb3IiLCB0cnVlKTsKICAgIHRoaXMuY1NwYWNlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuY1NwYWNlLCBbIlNSR0IiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnZhbHVlID0gYXR0cmlidXRlcy52YWx1ZSA/IGdldENvbG9yKGF0dHJpYnV0ZXMudmFsdWUpIDogIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQogIFskaGFzU2V0dGFibGVWYWx1ZV0oKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIFskdG9TdHlsZV0oKSB7CiAgICByZXR1cm4gdGhpcy52YWx1ZSA/IFV0aWwubWFrZUhleENvbG9yKHRoaXMudmFsdWUuciwgdGhpcy52YWx1ZS5nLCB0aGlzLnZhbHVlLmIpIDogbnVsbDsKICB9Cn0KY2xhc3MgQ29tYiBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJjb21iIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubnVtYmVyT2ZDZWxscyA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLm51bWJlck9mQ2VsbHMsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwCiAgICB9KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIENvbm5lY3QgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiY29ubmVjdCIsIHRydWUpOwogICAgdGhpcy5jb25uZWN0aW9uID0gYXR0cmlidXRlcy5jb25uZWN0aW9uIHx8ICIiOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnJlZiA9IGF0dHJpYnV0ZXMucmVmIHx8ICIiOwogICAgdGhpcy51c2FnZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnVzYWdlLCBbImV4cG9ydEFuZEltcG9ydCIsICJleHBvcnRPbmx5IiwgImltcG9ydE9ubHkiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5waWN0dXJlID0gbnVsbDsKICB9Cn0KY2xhc3MgQ29udGVudEFyZWEgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiY29udGVudEFyZWEiLCB0cnVlKTsKICAgIHRoaXMuaCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMuaCk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMucmVsZXZhbnQgPSBnZXRSZWxldmFudChhdHRyaWJ1dGVzLnJlbGV2YW50KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLncgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLncpOwogICAgdGhpcy54ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy54LCAiMHB0Iik7CiAgICB0aGlzLnkgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnksICIwcHQiKTsKICAgIHRoaXMuZGVzYyA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgY29uc3QgbGVmdCA9IG1lYXN1cmVUb1N0cmluZyh0aGlzLngpOwogICAgY29uc3QgdG9wID0gbWVhc3VyZVRvU3RyaW5nKHRoaXMueSk7CiAgICBjb25zdCBzdHlsZSA9IHsKICAgICAgbGVmdCwKICAgICAgdG9wLAogICAgICB3aWR0aDogbWVhc3VyZVRvU3RyaW5nKHRoaXMudyksCiAgICAgIGhlaWdodDogbWVhc3VyZVRvU3RyaW5nKHRoaXMuaCkKICAgIH07CiAgICBjb25zdCBjbGFzc05hbWVzID0gWyJ4ZmFDb250ZW50YXJlYSJdOwogICAgaWYgKGlzUHJpbnRPbmx5KHRoaXMpKSB7CiAgICAgIGNsYXNzTmFtZXMucHVzaCgieGZhUHJpbnRPbmx5Iik7CiAgICB9CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGNoaWxkcmVuOiBbXSwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIHN0eWxlLAogICAgICAgIGNsYXNzOiBjbGFzc05hbWVzLAogICAgICAgIGlkOiB0aGlzWyR1aWRdCiAgICAgIH0KICAgIH0pOwogIH0KfQpjbGFzcyBDb3JuZXIgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiY29ybmVyIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMuaW52ZXJ0ZWQgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5pbnZlcnRlZCwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMuam9pbiA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmpvaW4sIFsic3F1YXJlIiwgInJvdW5kIl0pOwogICAgdGhpcy5wcmVzZW5jZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnByZXNlbmNlLCBbInZpc2libGUiLCAiaGlkZGVuIiwgImluYWN0aXZlIiwgImludmlzaWJsZSJdKTsKICAgIHRoaXMucmFkaXVzID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5yYWRpdXMpOwogICAgdGhpcy5zdHJva2UgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5zdHJva2UsIFsic29saWQiLCAiZGFzaERvdCIsICJkYXNoRG90RG90IiwgImRhc2hlZCIsICJkb3R0ZWQiLCAiZW1ib3NzZWQiLCAiZXRjaGVkIiwgImxvd2VyZWQiLCAicmFpc2VkIl0pOwogICAgdGhpcy50aGlja25lc3MgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnRoaWNrbmVzcywgIjAuNXB0Iik7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5jb2xvciA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQogIFskdG9TdHlsZV0oKSB7CiAgICBjb25zdCBzdHlsZSA9IHRvU3R5bGUodGhpcywgInZpc2liaWxpdHkiKTsKICAgIHN0eWxlLnJhZGl1cyA9IG1lYXN1cmVUb1N0cmluZyh0aGlzLmpvaW4gPT09ICJzcXVhcmUiID8gMCA6IHRoaXMucmFkaXVzKTsKICAgIHJldHVybiBzdHlsZTsKICB9Cn0KY2xhc3MgRGF0ZUVsZW1lbnQgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImRhdGUiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICBjb25zdCBkYXRlID0gdGhpc1skY29udGVudF0udHJpbSgpOwogICAgdGhpc1skY29udGVudF0gPSBkYXRlID8gbmV3IERhdGUoZGF0ZSkgOiBudWxsOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIHJldHVybiB2YWx1ZVRvSHRtbCh0aGlzWyRjb250ZW50XSA/IHRoaXNbJGNvbnRlbnRdLnRvU3RyaW5nKCkgOiAiIik7CiAgfQp9CmNsYXNzIERhdGVUaW1lIGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJkYXRlVGltZSIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIGNvbnN0IGRhdGUgPSB0aGlzWyRjb250ZW50XS50cmltKCk7CiAgICB0aGlzWyRjb250ZW50XSA9IGRhdGUgPyBuZXcgRGF0ZShkYXRlKSA6IG51bGw7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgcmV0dXJuIHZhbHVlVG9IdG1sKHRoaXNbJGNvbnRlbnRdID8gdGhpc1skY29udGVudF0udG9TdHJpbmcoKSA6ICIiKTsKICB9Cn0KY2xhc3MgRGF0ZVRpbWVFZGl0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImRhdGVUaW1lRWRpdCIsIHRydWUpOwogICAgdGhpcy5oU2Nyb2xsUG9saWN5ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuaFNjcm9sbFBvbGljeSwgWyJhdXRvIiwgIm9mZiIsICJvbiJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5waWNrZXIgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5waWNrZXIsIFsiaG9zdCIsICJub25lIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuYm9yZGVyID0gbnVsbDsKICAgIHRoaXMuY29tYiA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLm1hcmdpbiA9IG51bGw7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgY29uc3Qgc3R5bGUgPSB0b1N0eWxlKHRoaXMsICJib3JkZXIiLCAiZm9udCIsICJtYXJnaW4iKTsKICAgIGNvbnN0IGZpZWxkID0gdGhpc1skZ2V0UGFyZW50XSgpWyRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBodG1sID0gewogICAgICBuYW1lOiAiaW5wdXQiLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgdHlwZTogInRleHQiLAogICAgICAgIGZpZWxkSWQ6IGZpZWxkWyR1aWRdLAogICAgICAgIGRhdGFJZDogZmllbGRbJGRhdGFdPy5bJHVpZF0gfHwgZmllbGRbJHVpZF0sCiAgICAgICAgY2xhc3M6IFsieGZhVGV4dGZpZWxkIl0sCiAgICAgICAgc3R5bGUsCiAgICAgICAgImFyaWEtbGFiZWwiOiBhcmlhTGFiZWwoZmllbGQpLAogICAgICAgICJhcmlhLXJlcXVpcmVkIjogZmFsc2UKICAgICAgfQogICAgfTsKICAgIGlmIChpc1JlcXVpcmVkKGZpZWxkKSkgewogICAgICBodG1sLmF0dHJpYnV0ZXNbImFyaWEtcmVxdWlyZWQiXSA9IHRydWU7CiAgICAgIGh0bWwuYXR0cmlidXRlcy5yZXF1aXJlZCA9IHRydWU7CiAgICB9CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgbmFtZTogImxhYmVsIiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIGNsYXNzOiBbInhmYUxhYmVsIl0KICAgICAgfSwKICAgICAgY2hpbGRyZW46IFtodG1sXQogICAgfSk7CiAgfQp9CmNsYXNzIERlY2ltYWwgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImRlY2ltYWwiKTsKICAgIHRoaXMuZnJhY0RpZ2l0cyA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmZyYWNEaWdpdHMsCiAgICAgIGRlZmF1bHRWYWx1ZTogMiwKICAgICAgdmFsaWRhdGU6IHggPT4gdHJ1ZQogICAgfSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubGVhZERpZ2l0cyA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmxlYWREaWdpdHMsCiAgICAgIGRlZmF1bHRWYWx1ZTogLTEsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHRydWUKICAgIH0pOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICBjb25zdCBudW1iZXIgPSBwYXJzZUZsb2F0KHRoaXNbJGNvbnRlbnRdLnRyaW0oKSk7CiAgICB0aGlzWyRjb250ZW50XSA9IGlzTmFOKG51bWJlcikgPyBudWxsIDogbnVtYmVyOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIHJldHVybiB2YWx1ZVRvSHRtbCh0aGlzWyRjb250ZW50XSAhPT0gbnVsbCA/IHRoaXNbJGNvbnRlbnRdLnRvU3RyaW5nKCkgOiAiIik7CiAgfQp9CmNsYXNzIERlZmF1bHRVaSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJkZWZhdWx0VWkiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICB9Cn0KY2xhc3MgRGVzYyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJkZXNjIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmJvb2xlYW4gPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGF0ZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kYXRlVGltZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kZWNpbWFsID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4RGF0YSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5mbG9hdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbWFnZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbnRlZ2VyID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRleHQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGltZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBEaWdlc3RNZXRob2QgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZGlnZXN0TWV0aG9kIiwgWyIiLCAiU0hBMSIsICJTSEEyNTYiLCAiU0hBNTEyIiwgIlJJUEVNRDE2MCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgRGlnZXN0TWV0aG9kcyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJkaWdlc3RNZXRob2RzIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudHlwZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnR5cGUsIFsib3B0aW9uYWwiLCAicmVxdWlyZWQiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5kaWdlc3RNZXRob2QgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgRHJhdyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJkcmF3IiwgdHJ1ZSk7CiAgICB0aGlzLmFuY2hvclR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5hbmNob3JUeXBlLCBbInRvcExlZnQiLCAiYm90dG9tQ2VudGVyIiwgImJvdHRvbUxlZnQiLCAiYm90dG9tUmlnaHQiLCAibWlkZGxlQ2VudGVyIiwgIm1pZGRsZUxlZnQiLCAibWlkZGxlUmlnaHQiLCAidG9wQ2VudGVyIiwgInRvcFJpZ2h0Il0pOwogICAgdGhpcy5jb2xTcGFuID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuY29sU3BhbiwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogbiA9PiBuID49IDEgfHwgbiA9PT0gLTEKICAgIH0pOwogICAgdGhpcy5oID0gYXR0cmlidXRlcy5oID8gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5oKSA6ICIiOwogICAgdGhpcy5oQWxpZ24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5oQWxpZ24sIFsibGVmdCIsICJjZW50ZXIiLCAianVzdGlmeSIsICJqdXN0aWZ5QWxsIiwgInJhZGl4IiwgInJpZ2h0Il0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmxvY2FsZSA9IGF0dHJpYnV0ZXMubG9jYWxlIHx8ICIiOwogICAgdGhpcy5tYXhIID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5tYXhILCAiMHB0Iik7CiAgICB0aGlzLm1heFcgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLm1heFcsICIwcHQiKTsKICAgIHRoaXMubWluSCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubWluSCwgIjBwdCIpOwogICAgdGhpcy5taW5XID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5taW5XLCAiMHB0Iik7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnByZXNlbmNlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMucHJlc2VuY2UsIFsidmlzaWJsZSIsICJoaWRkZW4iLCAiaW5hY3RpdmUiLCAiaW52aXNpYmxlIl0pOwogICAgdGhpcy5yZWxldmFudCA9IGdldFJlbGV2YW50KGF0dHJpYnV0ZXMucmVsZXZhbnQpOwogICAgdGhpcy5yb3RhdGUgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5yb3RhdGUsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCAlIDkwID09PSAwCiAgICB9KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLncgPSBhdHRyaWJ1dGVzLncgPyBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLncpIDogIiI7CiAgICB0aGlzLnggPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLngsICIwcHQiKTsKICAgIHRoaXMueSA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMueSwgIjBwdCIpOwogICAgdGhpcy5hc3Npc3QgPSBudWxsOwogICAgdGhpcy5ib3JkZXIgPSBudWxsOwogICAgdGhpcy5jYXB0aW9uID0gbnVsbDsKICAgIHRoaXMuZGVzYyA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLmZvbnQgPSBudWxsOwogICAgdGhpcy5rZWVwID0gbnVsbDsKICAgIHRoaXMubWFyZ2luID0gbnVsbDsKICAgIHRoaXMucGFyYSA9IG51bGw7CiAgICB0aGlzLnRyYXZlcnNhbCA9IG51bGw7CiAgICB0aGlzLnVpID0gbnVsbDsKICAgIHRoaXMudmFsdWUgPSBudWxsOwogICAgdGhpcy5zZXRQcm9wZXJ0eSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KICBbJHNldFZhbHVlXSh2YWx1ZSkgewogICAgX3NldFZhbHVlKHRoaXMsIHZhbHVlKTsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBzZXRUYWJJbmRleCh0aGlzKTsKICAgIGlmICh0aGlzLnByZXNlbmNlID09PSAiaGlkZGVuIiB8fCB0aGlzLnByZXNlbmNlID09PSAiaW5hY3RpdmUiKSB7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkVNUFRZOwogICAgfQogICAgZml4RGltZW5zaW9ucyh0aGlzKTsKICAgIHRoaXNbJHB1c2hQYXJhXSgpOwogICAgY29uc3Qgc2F2ZWRXID0gdGhpcy53OwogICAgY29uc3Qgc2F2ZWRIID0gdGhpcy5oOwogICAgY29uc3QgewogICAgICB3LAogICAgICBoLAogICAgICBpc0Jyb2tlbgogICAgfSA9IGxheW91dE5vZGUodGhpcywgYXZhaWxhYmxlU3BhY2UpOwogICAgaWYgKHcgJiYgdGhpcy53ID09PSAiIikgewogICAgICBpZiAoaXNCcm9rZW4gJiYgdGhpc1skZ2V0U3ViZm9ybVBhcmVudF0oKVskaXNUaGVyZU1vcmVXaWR0aF0oKSkgewogICAgICAgIHRoaXNbJHBvcFBhcmFdKCk7CiAgICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuRkFJTFVSRTsKICAgICAgfQogICAgICB0aGlzLncgPSB3OwogICAgfQogICAgaWYgKGggJiYgdGhpcy5oID09PSAiIikgewogICAgICB0aGlzLmggPSBoOwogICAgfQogICAgc2V0Rmlyc3RVbnNwbGl0dGFibGUodGhpcyk7CiAgICBpZiAoIWNoZWNrRGltZW5zaW9ucyh0aGlzLCBhdmFpbGFibGVTcGFjZSkpIHsKICAgICAgdGhpcy53ID0gc2F2ZWRXOwogICAgICB0aGlzLmggPSBzYXZlZEg7CiAgICAgIHRoaXNbJHBvcFBhcmFdKCk7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkZBSUxVUkU7CiAgICB9CiAgICB1bnNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpOwogICAgY29uc3Qgc3R5bGUgPSB0b1N0eWxlKHRoaXMsICJmb250IiwgImhBbGlnbiIsICJkaW1lbnNpb25zIiwgInBvc2l0aW9uIiwgInByZXNlbmNlIiwgInJvdGF0ZSIsICJhbmNob3JUeXBlIiwgImJvcmRlciIsICJtYXJnaW4iKTsKICAgIHNldE1pbk1heERpbWVuc2lvbnModGhpcywgc3R5bGUpOwogICAgaWYgKHN0eWxlLm1hcmdpbikgewogICAgICBzdHlsZS5wYWRkaW5nID0gc3R5bGUubWFyZ2luOwogICAgICBkZWxldGUgc3R5bGUubWFyZ2luOwogICAgfQogICAgY29uc3QgY2xhc3NOYW1lcyA9IFsieGZhRHJhdyJdOwogICAgaWYgKHRoaXMuZm9udCkgewogICAgICBjbGFzc05hbWVzLnB1c2goInhmYUZvbnQiKTsKICAgIH0KICAgIGlmIChpc1ByaW50T25seSh0aGlzKSkgewogICAgICBjbGFzc05hbWVzLnB1c2goInhmYVByaW50T25seSIpOwogICAgfQogICAgY29uc3QgYXR0cmlidXRlcyA9IHsKICAgICAgc3R5bGUsCiAgICAgIGlkOiB0aGlzWyR1aWRdLAogICAgICBjbGFzczogY2xhc3NOYW1lcwogICAgfTsKICAgIGlmICh0aGlzLm5hbWUpIHsKICAgICAgYXR0cmlidXRlcy54ZmFOYW1lID0gdGhpcy5uYW1lOwogICAgfQogICAgY29uc3QgaHRtbCA9IHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGF0dHJpYnV0ZXMsCiAgICAgIGNoaWxkcmVuOiBbXQogICAgfTsKICAgIGFwcGx5QXNzaXN0KHRoaXMsIGF0dHJpYnV0ZXMpOwogICAgY29uc3QgYmJveCA9IGNvbXB1dGVCYm94KHRoaXMsIGh0bWwsIGF2YWlsYWJsZVNwYWNlKTsKICAgIGNvbnN0IHZhbHVlID0gdGhpcy52YWx1ZSA/IHRoaXMudmFsdWVbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpLmh0bWwgOiBudWxsOwogICAgaWYgKHZhbHVlID09PSBudWxsKSB7CiAgICAgIHRoaXMudyA9IHNhdmVkVzsKICAgICAgdGhpcy5oID0gc2F2ZWRIOwogICAgICB0aGlzWyRwb3BQYXJhXSgpOwogICAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKGNyZWF0ZVdyYXBwZXIodGhpcywgaHRtbCksIGJib3gpOwogICAgfQogICAgaHRtbC5jaGlsZHJlbi5wdXNoKHZhbHVlKTsKICAgIHNldFBhcmEodGhpcywgc3R5bGUsIHZhbHVlKTsKICAgIHRoaXMudyA9IHNhdmVkVzsKICAgIHRoaXMuaCA9IHNhdmVkSDsKICAgIHRoaXNbJHBvcFBhcmFdKCk7CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKGNyZWF0ZVdyYXBwZXIodGhpcywgaHRtbCksIGJib3gpOwogIH0KfQpjbGFzcyBFZGdlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImVkZ2UiLCB0cnVlKTsKICAgIHRoaXMuY2FwID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuY2FwLCBbInNxdWFyZSIsICJidXR0IiwgInJvdW5kIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnByZXNlbmNlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMucHJlc2VuY2UsIFsidmlzaWJsZSIsICJoaWRkZW4iLCAiaW5hY3RpdmUiLCAiaW52aXNpYmxlIl0pOwogICAgdGhpcy5zdHJva2UgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5zdHJva2UsIFsic29saWQiLCAiZGFzaERvdCIsICJkYXNoRG90RG90IiwgImRhc2hlZCIsICJkb3R0ZWQiLCAiZW1ib3NzZWQiLCAiZXRjaGVkIiwgImxvd2VyZWQiLCAicmFpc2VkIl0pOwogICAgdGhpcy50aGlja25lc3MgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnRoaWNrbmVzcywgIjAuNXB0Iik7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5jb2xvciA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQogIFskdG9TdHlsZV0oKSB7CiAgICBjb25zdCBzdHlsZSA9IHRvU3R5bGUodGhpcywgInZpc2liaWxpdHkiKTsKICAgIE9iamVjdC5hc3NpZ24oc3R5bGUsIHsKICAgICAgbGluZWNhcDogdGhpcy5jYXAsCiAgICAgIHdpZHRoOiBtZWFzdXJlVG9TdHJpbmcodGhpcy50aGlja25lc3MpLAogICAgICBjb2xvcjogdGhpcy5jb2xvciA/IHRoaXMuY29sb3JbJHRvU3R5bGVdKCkgOiAiIzAwMDAwMCIsCiAgICAgIHN0eWxlOiAiIgogICAgfSk7CiAgICBpZiAodGhpcy5wcmVzZW5jZSAhPT0gInZpc2libGUiKSB7CiAgICAgIHN0eWxlLnN0eWxlID0gIm5vbmUiOwogICAgfSBlbHNlIHsKICAgICAgc3dpdGNoICh0aGlzLnN0cm9rZSkgewogICAgICAgIGNhc2UgInNvbGlkIjoKICAgICAgICAgIHN0eWxlLnN0eWxlID0gInNvbGlkIjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImRhc2hEb3QiOgogICAgICAgICAgc3R5bGUuc3R5bGUgPSAiZGFzaGVkIjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImRhc2hEb3REb3QiOgogICAgICAgICAgc3R5bGUuc3R5bGUgPSAiZGFzaGVkIjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImRhc2hlZCI6CiAgICAgICAgICBzdHlsZS5zdHlsZSA9ICJkYXNoZWQiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZG90dGVkIjoKICAgICAgICAgIHN0eWxlLnN0eWxlID0gImRvdHRlZCI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJlbWJvc3NlZCI6CiAgICAgICAgICBzdHlsZS5zdHlsZSA9ICJyaWRnZSI7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJldGNoZWQiOgogICAgICAgICAgc3R5bGUuc3R5bGUgPSAiZ3Jvb3ZlIjsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImxvd2VyZWQiOgogICAgICAgICAgc3R5bGUuc3R5bGUgPSAiaW5zZXQiOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAicmFpc2VkIjoKICAgICAgICAgIHN0eWxlLnN0eWxlID0gIm91dHNldCI7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHN0eWxlOwogIH0KfQpjbGFzcyBFbmNvZGluZyBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJlbmNvZGluZyIsIFsiYWRiZS54NTA5LnJzYV9zaGExIiwgImFkYmUucGtjczcuZGV0YWNoZWQiLCAiYWRiZS5wa2NzNy5zaGExIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBFbmNvZGluZ3MgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZW5jb2RpbmdzIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudHlwZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnR5cGUsIFsib3B0aW9uYWwiLCAicmVxdWlyZWQiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5lbmNvZGluZyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBFbmNyeXB0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImVuY3J5cHQiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuY2VydGlmaWNhdGUgPSBudWxsOwogIH0KfQpjbGFzcyBFbmNyeXB0RGF0YSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJlbmNyeXB0RGF0YSIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm9wZXJhdGlvbiA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLm9wZXJhdGlvbiwgWyJlbmNyeXB0IiwgImRlY3J5cHQiXSk7CiAgICB0aGlzLnRhcmdldCA9IGF0dHJpYnV0ZXMudGFyZ2V0IHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZmlsdGVyID0gbnVsbDsKICAgIHRoaXMubWFuaWZlc3QgPSBudWxsOwogIH0KfQpjbGFzcyBFbmNyeXB0aW9uIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImVuY3J5cHRpb24iLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmNlcnRpZmljYXRlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIEVuY3J5cHRpb25NZXRob2QgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZW5jcnlwdGlvbk1ldGhvZCIsIFsiIiwgIkFFUzI1Ni1DQkMiLCAiVFJJUExFREVTLUNCQyIsICJBRVMxMjgtQ0JDIiwgIkFFUzE5Mi1DQkMiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIEVuY3J5cHRpb25NZXRob2RzIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImVuY3J5cHRpb25NZXRob2RzIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudHlwZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnR5cGUsIFsib3B0aW9uYWwiLCAicmVxdWlyZWQiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5lbmNyeXB0aW9uTWV0aG9kID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIEV2ZW50IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImV2ZW50IiwgdHJ1ZSk7CiAgICB0aGlzLmFjdGl2aXR5ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuYWN0aXZpdHksIFsiY2xpY2siLCAiY2hhbmdlIiwgImRvY0Nsb3NlIiwgImRvY1JlYWR5IiwgImVudGVyIiwgImV4aXQiLCAiZnVsbCIsICJpbmRleENoYW5nZSIsICJpbml0aWFsaXplIiwgIm1vdXNlRG93biIsICJtb3VzZUVudGVyIiwgIm1vdXNlRXhpdCIsICJtb3VzZVVwIiwgInBvc3RFeGVjdXRlIiwgInBvc3RPcGVuIiwgInBvc3RQcmludCIsICJwb3N0U2F2ZSIsICJwb3N0U2lnbiIsICJwb3N0U3VibWl0IiwgInByZUV4ZWN1dGUiLCAicHJlT3BlbiIsICJwcmVQcmludCIsICJwcmVTYXZlIiwgInByZVNpZ24iLCAicHJlU3VibWl0IiwgInJlYWR5IiwgInZhbGlkYXRpb25TdGF0ZSJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5saXN0ZW4gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5saXN0ZW4sIFsicmVmT25seSIsICJyZWZBbmREZXNjZW5kZW50cyJdKTsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMucmVmID0gYXR0cmlidXRlcy5yZWYgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5lbmNyeXB0RGF0YSA9IG51bGw7CiAgICB0aGlzLmV4ZWN1dGUgPSBudWxsOwogICAgdGhpcy5zY3JpcHQgPSBudWxsOwogICAgdGhpcy5zaWduRGF0YSA9IG51bGw7CiAgICB0aGlzLnN1Ym1pdCA9IG51bGw7CiAgfQp9CmNsYXNzIEV4RGF0YSBleHRlbmRzIENvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZXhEYXRhIik7CiAgICB0aGlzLmNvbnRlbnRUeXBlID0gYXR0cmlidXRlcy5jb250ZW50VHlwZSB8fCAiIjsKICAgIHRoaXMuaHJlZiA9IGF0dHJpYnV0ZXMuaHJlZiB8fCAiIjsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5tYXhMZW5ndGggPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5tYXhMZW5ndGgsCiAgICAgIGRlZmF1bHRWYWx1ZTogLTEsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gLTEKICAgIH0pOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5yaWQgPSBhdHRyaWJ1dGVzLnJpZCB8fCAiIjsKICAgIHRoaXMudHJhbnNmZXJFbmNvZGluZyA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnRyYW5zZmVyRW5jb2RpbmcsIFsibm9uZSIsICJiYXNlNjQiLCAicGFja2FnZSJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQogIFskaXNDREFUQVhtbF0oKSB7CiAgICByZXR1cm4gdGhpcy5jb250ZW50VHlwZSA9PT0gInRleHQvaHRtbCI7CiAgfQogIFskb25DaGlsZF0oY2hpbGQpIHsKICAgIGlmICh0aGlzLmNvbnRlbnRUeXBlID09PSAidGV4dC9odG1sIiAmJiBjaGlsZFskbmFtZXNwYWNlSWRdID09PSBOYW1lc3BhY2VJZHMueGh0bWwuaWQpIHsKICAgICAgdGhpc1skY29udGVudF0gPSBjaGlsZDsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9CiAgICBpZiAodGhpcy5jb250ZW50VHlwZSA9PT0gInRleHQveG1sIikgewogICAgICB0aGlzWyRjb250ZW50XSA9IGNoaWxkOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBpZiAodGhpcy5jb250ZW50VHlwZSAhPT0gInRleHQvaHRtbCIgfHwgIXRoaXNbJGNvbnRlbnRdKSB7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkVNUFRZOwogICAgfQogICAgcmV0dXJuIHRoaXNbJGNvbnRlbnRdWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKTsKICB9Cn0KY2xhc3MgRXhPYmplY3QgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZXhPYmplY3QiLCB0cnVlKTsKICAgIHRoaXMuYXJjaGl2ZSA9IGF0dHJpYnV0ZXMuYXJjaGl2ZSB8fCAiIjsKICAgIHRoaXMuY2xhc3NJZCA9IGF0dHJpYnV0ZXMuY2xhc3NJZCB8fCAiIjsKICAgIHRoaXMuY29kZUJhc2UgPSBhdHRyaWJ1dGVzLmNvZGVCYXNlIHx8ICIiOwogICAgdGhpcy5jb2RlVHlwZSA9IGF0dHJpYnV0ZXMuY29kZVR5cGUgfHwgIiI7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLmJvb2xlYW4gPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGF0ZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kYXRlVGltZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kZWNpbWFsID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4RGF0YSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leE9iamVjdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5mbG9hdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbWFnZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbnRlZ2VyID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRleHQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGltZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBFeGNsR3JvdXAgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZXhjbEdyb3VwIiwgdHJ1ZSk7CiAgICB0aGlzLmFjY2VzcyA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmFjY2VzcywgWyJvcGVuIiwgIm5vbkludGVyYWN0aXZlIiwgInByb3RlY3RlZCIsICJyZWFkT25seSJdKTsKICAgIHRoaXMuYWNjZXNzS2V5ID0gYXR0cmlidXRlcy5hY2Nlc3NLZXkgfHwgIiI7CiAgICB0aGlzLmFuY2hvclR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5hbmNob3JUeXBlLCBbInRvcExlZnQiLCAiYm90dG9tQ2VudGVyIiwgImJvdHRvbUxlZnQiLCAiYm90dG9tUmlnaHQiLCAibWlkZGxlQ2VudGVyIiwgIm1pZGRsZUxlZnQiLCAibWlkZGxlUmlnaHQiLCAidG9wQ2VudGVyIiwgInRvcFJpZ2h0Il0pOwogICAgdGhpcy5jb2xTcGFuID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuY29sU3BhbiwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogbiA9PiBuID49IDEgfHwgbiA9PT0gLTEKICAgIH0pOwogICAgdGhpcy5oID0gYXR0cmlidXRlcy5oID8gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5oKSA6ICIiOwogICAgdGhpcy5oQWxpZ24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5oQWxpZ24sIFsibGVmdCIsICJjZW50ZXIiLCAianVzdGlmeSIsICJqdXN0aWZ5QWxsIiwgInJhZGl4IiwgInJpZ2h0Il0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmxheW91dCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmxheW91dCwgWyJwb3NpdGlvbiIsICJsci10YiIsICJybC1yb3ciLCAicmwtdGIiLCAicm93IiwgInRhYmxlIiwgInRiIl0pOwogICAgdGhpcy5tYXhIID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5tYXhILCAiMHB0Iik7CiAgICB0aGlzLm1heFcgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLm1heFcsICIwcHQiKTsKICAgIHRoaXMubWluSCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubWluSCwgIjBwdCIpOwogICAgdGhpcy5taW5XID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5taW5XLCAiMHB0Iik7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnByZXNlbmNlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMucHJlc2VuY2UsIFsidmlzaWJsZSIsICJoaWRkZW4iLCAiaW5hY3RpdmUiLCAiaW52aXNpYmxlIl0pOwogICAgdGhpcy5yZWxldmFudCA9IGdldFJlbGV2YW50KGF0dHJpYnV0ZXMucmVsZXZhbnQpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMudyA9IGF0dHJpYnV0ZXMudyA/IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMudykgOiAiIjsKICAgIHRoaXMueCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMueCwgIjBwdCIpOwogICAgdGhpcy55ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy55LCAiMHB0Iik7CiAgICB0aGlzLmFzc2lzdCA9IG51bGw7CiAgICB0aGlzLmJpbmQgPSBudWxsOwogICAgdGhpcy5ib3JkZXIgPSBudWxsOwogICAgdGhpcy5jYWxjdWxhdGUgPSBudWxsOwogICAgdGhpcy5jYXB0aW9uID0gbnVsbDsKICAgIHRoaXMuZGVzYyA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLm1hcmdpbiA9IG51bGw7CiAgICB0aGlzLnBhcmEgPSBudWxsOwogICAgdGhpcy50cmF2ZXJzYWwgPSBudWxsOwogICAgdGhpcy52YWxpZGF0ZSA9IG51bGw7CiAgICB0aGlzLmNvbm5lY3QgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXZlbnQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmllbGQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2V0UHJvcGVydHkgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICB9CiAgWyRpc0JpbmRhYmxlXSgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICBbJGhhc1NldHRhYmxlVmFsdWVdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIFskc2V0VmFsdWVdKHZhbHVlKSB7CiAgICBmb3IgKGNvbnN0IGZpZWxkIG9mIHRoaXMuZmllbGQuY2hpbGRyZW4pIHsKICAgICAgaWYgKCFmaWVsZC52YWx1ZSkgewogICAgICAgIGNvbnN0IG5vZGVWYWx1ZSA9IG5ldyBWYWx1ZSh7fSk7CiAgICAgICAgZmllbGRbJGFwcGVuZENoaWxkXShub2RlVmFsdWUpOwogICAgICAgIGZpZWxkLnZhbHVlID0gbm9kZVZhbHVlOwogICAgICB9CiAgICAgIGZpZWxkLnZhbHVlWyRzZXRWYWx1ZV0odmFsdWUpOwogICAgfQogIH0KICBbJGlzVGhlcmVNb3JlV2lkdGhdKCkgewogICAgcmV0dXJuIHRoaXMubGF5b3V0LmVuZHNXaXRoKCItdGIiKSAmJiB0aGlzWyRleHRyYV0uYXR0ZW1wdCA9PT0gMCAmJiB0aGlzWyRleHRyYV0ubnVtYmVySW5MaW5lID4gMCB8fCB0aGlzWyRnZXRQYXJlbnRdKClbJGlzVGhlcmVNb3JlV2lkdGhdKCk7CiAgfQogIFskaXNTcGxpdHRhYmxlXSgpIHsKICAgIGNvbnN0IHBhcmVudCA9IHRoaXNbJGdldFN1YmZvcm1QYXJlbnRdKCk7CiAgICBpZiAoIXBhcmVudFskaXNTcGxpdHRhYmxlXSgpKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmICh0aGlzWyRleHRyYV0uX2lzU3BsaXR0YWJsZSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiB0aGlzWyRleHRyYV0uX2lzU3BsaXR0YWJsZTsKICAgIH0KICAgIGlmICh0aGlzLmxheW91dCA9PT0gInBvc2l0aW9uIiB8fCB0aGlzLmxheW91dC5pbmNsdWRlcygicm93IikpIHsKICAgICAgdGhpc1skZXh0cmFdLl9pc1NwbGl0dGFibGUgPSBmYWxzZTsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKHBhcmVudC5sYXlvdXQ/LmVuZHNXaXRoKCItdGIiKSAmJiBwYXJlbnRbJGV4dHJhXS5udW1iZXJJbkxpbmUgIT09IDApIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgdGhpc1skZXh0cmFdLl9pc1NwbGl0dGFibGUgPSB0cnVlOwogICAgcmV0dXJuIHRydWU7CiAgfQogIFskZmx1c2hIVE1MXSgpIHsKICAgIHJldHVybiBmbHVzaEhUTUwodGhpcyk7CiAgfQogIFskYWRkSFRNTF0oaHRtbCwgYmJveCkgewogICAgYWRkSFRNTCh0aGlzLCBodG1sLCBiYm94KTsKICB9CiAgWyRnZXRBdmFpbGFibGVTcGFjZV0oKSB7CiAgICByZXR1cm4gZ2V0QXZhaWxhYmxlU3BhY2UodGhpcyk7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgc2V0VGFiSW5kZXgodGhpcyk7CiAgICBpZiAodGhpcy5wcmVzZW5jZSA9PT0gImhpZGRlbiIgfHwgdGhpcy5wcmVzZW5jZSA9PT0gImluYWN0aXZlIiB8fCB0aGlzLmggPT09IDAgfHwgdGhpcy53ID09PSAwKSB7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkVNUFRZOwogICAgfQogICAgZml4RGltZW5zaW9ucyh0aGlzKTsKICAgIGNvbnN0IGNoaWxkcmVuID0gW107CiAgICBjb25zdCBhdHRyaWJ1dGVzID0gewogICAgICBpZDogdGhpc1skdWlkXSwKICAgICAgY2xhc3M6IFtdCiAgICB9OwogICAgc2V0QWNjZXNzKHRoaXMsIGF0dHJpYnV0ZXMuY2xhc3MpOwogICAgdGhpc1skZXh0cmFdIHx8PSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgT2JqZWN0LmFzc2lnbih0aGlzWyRleHRyYV0sIHsKICAgICAgY2hpbGRyZW4sCiAgICAgIGF0dHJpYnV0ZXMsCiAgICAgIGF0dGVtcHQ6IDAsCiAgICAgIGxpbmU6IG51bGwsCiAgICAgIG51bWJlckluTGluZTogMCwKICAgICAgYXZhaWxhYmxlU3BhY2U6IHsKICAgICAgICB3aWR0aDogTWF0aC5taW4odGhpcy53IHx8IEluZmluaXR5LCBhdmFpbGFibGVTcGFjZS53aWR0aCksCiAgICAgICAgaGVpZ2h0OiBNYXRoLm1pbih0aGlzLmggfHwgSW5maW5pdHksIGF2YWlsYWJsZVNwYWNlLmhlaWdodCkKICAgICAgfSwKICAgICAgd2lkdGg6IDAsCiAgICAgIGhlaWdodDogMCwKICAgICAgcHJldkhlaWdodDogMCwKICAgICAgY3VycmVudFdpZHRoOiAwCiAgICB9KTsKICAgIGNvbnN0IGlzU3BsaXR0YWJsZSA9IHRoaXNbJGlzU3BsaXR0YWJsZV0oKTsKICAgIGlmICghaXNTcGxpdHRhYmxlKSB7CiAgICAgIHNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpOwogICAgfQogICAgaWYgKCFjaGVja0RpbWVuc2lvbnModGhpcywgYXZhaWxhYmxlU3BhY2UpKSB7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkZBSUxVUkU7CiAgICB9CiAgICBjb25zdCBmaWx0ZXIgPSBuZXcgU2V0KFsiZmllbGQiXSk7CiAgICBpZiAodGhpcy5sYXlvdXQuaW5jbHVkZXMoInJvdyIpKSB7CiAgICAgIGNvbnN0IGNvbHVtbldpZHRocyA9IHRoaXNbJGdldFN1YmZvcm1QYXJlbnRdKCkuY29sdW1uV2lkdGhzOwogICAgICBpZiAoQXJyYXkuaXNBcnJheShjb2x1bW5XaWR0aHMpICYmIGNvbHVtbldpZHRocy5sZW5ndGggPiAwKSB7CiAgICAgICAgdGhpc1skZXh0cmFdLmNvbHVtbldpZHRocyA9IGNvbHVtbldpZHRoczsKICAgICAgICB0aGlzWyRleHRyYV0uY3VycmVudENvbHVtbiA9IDA7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IHN0eWxlID0gdG9TdHlsZSh0aGlzLCAiYW5jaG9yVHlwZSIsICJkaW1lbnNpb25zIiwgInBvc2l0aW9uIiwgInByZXNlbmNlIiwgImJvcmRlciIsICJtYXJnaW4iLCAiaEFsaWduIik7CiAgICBjb25zdCBjbGFzc05hbWVzID0gWyJ4ZmFFeGNsZ3JvdXAiXTsKICAgIGNvbnN0IGNsID0gbGF5b3V0Q2xhc3ModGhpcyk7CiAgICBpZiAoY2wpIHsKICAgICAgY2xhc3NOYW1lcy5wdXNoKGNsKTsKICAgIH0KICAgIGlmIChpc1ByaW50T25seSh0aGlzKSkgewogICAgICBjbGFzc05hbWVzLnB1c2goInhmYVByaW50T25seSIpOwogICAgfQogICAgYXR0cmlidXRlcy5zdHlsZSA9IHN0eWxlOwogICAgYXR0cmlidXRlcy5jbGFzcyA9IGNsYXNzTmFtZXM7CiAgICBpZiAodGhpcy5uYW1lKSB7CiAgICAgIGF0dHJpYnV0ZXMueGZhTmFtZSA9IHRoaXMubmFtZTsKICAgIH0KICAgIHRoaXNbJHB1c2hQYXJhXSgpOwogICAgY29uc3QgaXNMclRiID0gdGhpcy5sYXlvdXQgPT09ICJsci10YiIgfHwgdGhpcy5sYXlvdXQgPT09ICJybC10YiI7CiAgICBjb25zdCBtYXhSdW4gPSBpc0xyVGIgPyBNQVhfQVRURU1QVFNfRk9SX0xSVEJfTEFZT1VUIDogMTsKICAgIGZvciAoOyB0aGlzWyRleHRyYV0uYXR0ZW1wdCA8IG1heFJ1bjsgdGhpc1skZXh0cmFdLmF0dGVtcHQrKykgewogICAgICBpZiAoaXNMclRiICYmIHRoaXNbJGV4dHJhXS5hdHRlbXB0ID09PSBNQVhfQVRURU1QVFNfRk9SX0xSVEJfTEFZT1VUIC0gMSkgewogICAgICAgIHRoaXNbJGV4dHJhXS5udW1iZXJJbkxpbmUgPSAwOwogICAgICB9CiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXNbJGNoaWxkcmVuVG9IVE1MXSh7CiAgICAgICAgZmlsdGVyLAogICAgICAgIGluY2x1ZGU6IHRydWUKICAgICAgfSk7CiAgICAgIGlmIChyZXN1bHQuc3VjY2VzcykgewogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIGlmIChyZXN1bHQuaXNCcmVhaygpKSB7CiAgICAgICAgdGhpc1skcG9wUGFyYV0oKTsKICAgICAgICByZXR1cm4gcmVzdWx0OwogICAgICB9CiAgICAgIGlmIChpc0xyVGIgJiYgdGhpc1skZXh0cmFdLmF0dGVtcHQgPT09IDAgJiYgdGhpc1skZXh0cmFdLm51bWJlckluTGluZSA9PT0gMCAmJiAhdGhpc1skZ2V0VGVtcGxhdGVSb290XSgpWyRleHRyYV0ubm9MYXlvdXRGYWlsdXJlKSB7CiAgICAgICAgdGhpc1skZXh0cmFdLmF0dGVtcHQgPSBtYXhSdW47CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIHRoaXNbJHBvcFBhcmFdKCk7CiAgICBpZiAoIWlzU3BsaXR0YWJsZSkgewogICAgICB1bnNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpOwogICAgfQogICAgaWYgKHRoaXNbJGV4dHJhXS5hdHRlbXB0ID09PSBtYXhSdW4pIHsKICAgICAgaWYgKCFpc1NwbGl0dGFibGUpIHsKICAgICAgICBkZWxldGUgdGhpc1skZXh0cmFdOwogICAgICB9CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkZBSUxVUkU7CiAgICB9CiAgICBsZXQgbWFyZ2luSCA9IDA7CiAgICBsZXQgbWFyZ2luViA9IDA7CiAgICBpZiAodGhpcy5tYXJnaW4pIHsKICAgICAgbWFyZ2luSCA9IHRoaXMubWFyZ2luLmxlZnRJbnNldCArIHRoaXMubWFyZ2luLnJpZ2h0SW5zZXQ7CiAgICAgIG1hcmdpblYgPSB0aGlzLm1hcmdpbi50b3BJbnNldCArIHRoaXMubWFyZ2luLmJvdHRvbUluc2V0OwogICAgfQogICAgY29uc3Qgd2lkdGggPSBNYXRoLm1heCh0aGlzWyRleHRyYV0ud2lkdGggKyBtYXJnaW5ILCB0aGlzLncgfHwgMCk7CiAgICBjb25zdCBoZWlnaHQgPSBNYXRoLm1heCh0aGlzWyRleHRyYV0uaGVpZ2h0ICsgbWFyZ2luViwgdGhpcy5oIHx8IDApOwogICAgY29uc3QgYmJveCA9IFt0aGlzLngsIHRoaXMueSwgd2lkdGgsIGhlaWdodF07CiAgICBpZiAodGhpcy53ID09PSAiIikgewogICAgICBzdHlsZS53aWR0aCA9IG1lYXN1cmVUb1N0cmluZyh3aWR0aCk7CiAgICB9CiAgICBpZiAodGhpcy5oID09PSAiIikgewogICAgICBzdHlsZS5oZWlnaHQgPSBtZWFzdXJlVG9TdHJpbmcoaGVpZ2h0KTsKICAgIH0KICAgIGNvbnN0IGh0bWwgPSB7CiAgICAgIG5hbWU6ICJkaXYiLAogICAgICBhdHRyaWJ1dGVzLAogICAgICBjaGlsZHJlbgogICAgfTsKICAgIGFwcGx5QXNzaXN0KHRoaXMsIGF0dHJpYnV0ZXMpOwogICAgZGVsZXRlIHRoaXNbJGV4dHJhXTsKICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoY3JlYXRlV3JhcHBlcih0aGlzLCBodG1sKSwgYmJveCk7CiAgfQp9CmNsYXNzIEV4ZWN1dGUgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZXhlY3V0ZSIpOwogICAgdGhpcy5jb25uZWN0aW9uID0gYXR0cmlidXRlcy5jb25uZWN0aW9uIHx8ICIiOwogICAgdGhpcy5leGVjdXRlVHlwZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmV4ZWN1dGVUeXBlLCBbImltcG9ydCIsICJyZW1lcmdlIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnJ1bkF0ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMucnVuQXQsIFsiY2xpZW50IiwgImJvdGgiLCAic2VydmVyIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgRXh0cmFzIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImV4dHJhcyIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5ib29sZWFuID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRhdGUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGF0ZVRpbWUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGVjaW1hbCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leERhdGEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXh0cmFzID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmZsb2F0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmltYWdlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmludGVnZXIgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGV4dCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy50aW1lID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIEZpZWxkIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImZpZWxkIiwgdHJ1ZSk7CiAgICB0aGlzLmFjY2VzcyA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmFjY2VzcywgWyJvcGVuIiwgIm5vbkludGVyYWN0aXZlIiwgInByb3RlY3RlZCIsICJyZWFkT25seSJdKTsKICAgIHRoaXMuYWNjZXNzS2V5ID0gYXR0cmlidXRlcy5hY2Nlc3NLZXkgfHwgIiI7CiAgICB0aGlzLmFuY2hvclR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5hbmNob3JUeXBlLCBbInRvcExlZnQiLCAiYm90dG9tQ2VudGVyIiwgImJvdHRvbUxlZnQiLCAiYm90dG9tUmlnaHQiLCAibWlkZGxlQ2VudGVyIiwgIm1pZGRsZUxlZnQiLCAibWlkZGxlUmlnaHQiLCAidG9wQ2VudGVyIiwgInRvcFJpZ2h0Il0pOwogICAgdGhpcy5jb2xTcGFuID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuY29sU3BhbiwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogbiA9PiBuID49IDEgfHwgbiA9PT0gLTEKICAgIH0pOwogICAgdGhpcy5oID0gYXR0cmlidXRlcy5oID8gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5oKSA6ICIiOwogICAgdGhpcy5oQWxpZ24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5oQWxpZ24sIFsibGVmdCIsICJjZW50ZXIiLCAianVzdGlmeSIsICJqdXN0aWZ5QWxsIiwgInJhZGl4IiwgInJpZ2h0Il0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmxvY2FsZSA9IGF0dHJpYnV0ZXMubG9jYWxlIHx8ICIiOwogICAgdGhpcy5tYXhIID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5tYXhILCAiMHB0Iik7CiAgICB0aGlzLm1heFcgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLm1heFcsICIwcHQiKTsKICAgIHRoaXMubWluSCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubWluSCwgIjBwdCIpOwogICAgdGhpcy5taW5XID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5taW5XLCAiMHB0Iik7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnByZXNlbmNlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMucHJlc2VuY2UsIFsidmlzaWJsZSIsICJoaWRkZW4iLCAiaW5hY3RpdmUiLCAiaW52aXNpYmxlIl0pOwogICAgdGhpcy5yZWxldmFudCA9IGdldFJlbGV2YW50KGF0dHJpYnV0ZXMucmVsZXZhbnQpOwogICAgdGhpcy5yb3RhdGUgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5yb3RhdGUsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCAlIDkwID09PSAwCiAgICB9KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLncgPSBhdHRyaWJ1dGVzLncgPyBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLncpIDogIiI7CiAgICB0aGlzLnggPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLngsICIwcHQiKTsKICAgIHRoaXMueSA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMueSwgIjBwdCIpOwogICAgdGhpcy5hc3Npc3QgPSBudWxsOwogICAgdGhpcy5iaW5kID0gbnVsbDsKICAgIHRoaXMuYm9yZGVyID0gbnVsbDsKICAgIHRoaXMuY2FsY3VsYXRlID0gbnVsbDsKICAgIHRoaXMuY2FwdGlvbiA9IG51bGw7CiAgICB0aGlzLmRlc2MgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5mb250ID0gbnVsbDsKICAgIHRoaXMuZm9ybWF0ID0gbnVsbDsKICAgIHRoaXMuaXRlbXMgPSBuZXcgWEZBT2JqZWN0QXJyYXkoMik7CiAgICB0aGlzLmtlZXAgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogICAgdGhpcy5wYXJhID0gbnVsbDsKICAgIHRoaXMudHJhdmVyc2FsID0gbnVsbDsKICAgIHRoaXMudWkgPSBudWxsOwogICAgdGhpcy52YWxpZGF0ZSA9IG51bGw7CiAgICB0aGlzLnZhbHVlID0gbnVsbDsKICAgIHRoaXMuYmluZEl0ZW1zID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNvbm5lY3QgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXZlbnQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2V0UHJvcGVydHkgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICB9CiAgWyRpc0JpbmRhYmxlXSgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KICBbJHNldFZhbHVlXSh2YWx1ZSkgewogICAgX3NldFZhbHVlKHRoaXMsIHZhbHVlKTsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBzZXRUYWJJbmRleCh0aGlzKTsKICAgIGlmICghdGhpcy51aSkgewogICAgICB0aGlzLnVpID0gbmV3IFVpKHt9KTsKICAgICAgdGhpcy51aVskZ2xvYmFsRGF0YV0gPSB0aGlzWyRnbG9iYWxEYXRhXTsKICAgICAgdGhpc1skYXBwZW5kQ2hpbGRdKHRoaXMudWkpOwogICAgICBsZXQgbm9kZTsKICAgICAgc3dpdGNoICh0aGlzLml0ZW1zLmNoaWxkcmVuLmxlbmd0aCkgewogICAgICAgIGNhc2UgMDoKICAgICAgICAgIG5vZGUgPSBuZXcgVGV4dEVkaXQoe30pOwogICAgICAgICAgdGhpcy51aS50ZXh0RWRpdCA9IG5vZGU7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIDE6CiAgICAgICAgICBub2RlID0gbmV3IENoZWNrQnV0dG9uKHt9KTsKICAgICAgICAgIHRoaXMudWkuY2hlY2tCdXR0b24gPSBub2RlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAyOgogICAgICAgICAgbm9kZSA9IG5ldyBDaG9pY2VMaXN0KHt9KTsKICAgICAgICAgIHRoaXMudWkuY2hvaWNlTGlzdCA9IG5vZGU7CiAgICAgICAgICBicmVhazsKICAgICAgfQogICAgICB0aGlzLnVpWyRhcHBlbmRDaGlsZF0obm9kZSk7CiAgICB9CiAgICBpZiAoIXRoaXMudWkgfHwgdGhpcy5wcmVzZW5jZSA9PT0gImhpZGRlbiIgfHwgdGhpcy5wcmVzZW5jZSA9PT0gImluYWN0aXZlIiB8fCB0aGlzLmggPT09IDAgfHwgdGhpcy53ID09PSAwKSB7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkVNUFRZOwogICAgfQogICAgaWYgKHRoaXMuY2FwdGlvbikgewogICAgICBkZWxldGUgdGhpcy5jYXB0aW9uWyRleHRyYV07CiAgICB9CiAgICB0aGlzWyRwdXNoUGFyYV0oKTsKICAgIGNvbnN0IGNhcHRpb24gPSB0aGlzLmNhcHRpb24gPyB0aGlzLmNhcHRpb25bJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpLmh0bWwgOiBudWxsOwogICAgY29uc3Qgc2F2ZWRXID0gdGhpcy53OwogICAgY29uc3Qgc2F2ZWRIID0gdGhpcy5oOwogICAgbGV0IG1hcmdpbkggPSAwOwogICAgbGV0IG1hcmdpblYgPSAwOwogICAgaWYgKHRoaXMubWFyZ2luKSB7CiAgICAgIG1hcmdpbkggPSB0aGlzLm1hcmdpbi5sZWZ0SW5zZXQgKyB0aGlzLm1hcmdpbi5yaWdodEluc2V0OwogICAgICBtYXJnaW5WID0gdGhpcy5tYXJnaW4udG9wSW5zZXQgKyB0aGlzLm1hcmdpbi5ib3R0b21JbnNldDsKICAgIH0KICAgIGxldCBib3JkZXJEaW1zID0gbnVsbDsKICAgIGlmICh0aGlzLncgPT09ICIiIHx8IHRoaXMuaCA9PT0gIiIpIHsKICAgICAgbGV0IHdpZHRoID0gbnVsbDsKICAgICAgbGV0IGhlaWdodCA9IG51bGw7CiAgICAgIGxldCB1aVcgPSAwOwogICAgICBsZXQgdWlIID0gMDsKICAgICAgaWYgKHRoaXMudWkuY2hlY2tCdXR0b24pIHsKICAgICAgICB1aVcgPSB1aUggPSB0aGlzLnVpLmNoZWNrQnV0dG9uLnNpemU7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgewogICAgICAgICAgdywKICAgICAgICAgIGgKICAgICAgICB9ID0gbGF5b3V0Tm9kZSh0aGlzLCBhdmFpbGFibGVTcGFjZSk7CiAgICAgICAgaWYgKHcgIT09IG51bGwpIHsKICAgICAgICAgIHVpVyA9IHc7CiAgICAgICAgICB1aUggPSBoOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB1aUggPSBmb250c19nZXRNZXRyaWNzKHRoaXMuZm9udCwgdHJ1ZSkubGluZU5vR2FwOwogICAgICAgIH0KICAgICAgfQogICAgICBib3JkZXJEaW1zID0gZ2V0Qm9yZGVyRGltcyh0aGlzLnVpWyRnZXRFeHRyYV0oKSk7CiAgICAgIHVpVyArPSBib3JkZXJEaW1zLnc7CiAgICAgIHVpSCArPSBib3JkZXJEaW1zLmg7CiAgICAgIGlmICh0aGlzLmNhcHRpb24pIHsKICAgICAgICBjb25zdCB7CiAgICAgICAgICB3LAogICAgICAgICAgaCwKICAgICAgICAgIGlzQnJva2VuCiAgICAgICAgfSA9IHRoaXMuY2FwdGlvblskZ2V0RXh0cmFdKGF2YWlsYWJsZVNwYWNlKTsKICAgICAgICBpZiAoaXNCcm9rZW4gJiYgdGhpc1skZ2V0U3ViZm9ybVBhcmVudF0oKVskaXNUaGVyZU1vcmVXaWR0aF0oKSkgewogICAgICAgICAgdGhpc1skcG9wUGFyYV0oKTsKICAgICAgICAgIHJldHVybiBIVE1MUmVzdWx0LkZBSUxVUkU7CiAgICAgICAgfQogICAgICAgIHdpZHRoID0gdzsKICAgICAgICBoZWlnaHQgPSBoOwogICAgICAgIHN3aXRjaCAodGhpcy5jYXB0aW9uLnBsYWNlbWVudCkgewogICAgICAgICAgY2FzZSAibGVmdCI6CiAgICAgICAgICBjYXNlICJyaWdodCI6CiAgICAgICAgICBjYXNlICJpbmxpbmUiOgogICAgICAgICAgICB3aWR0aCArPSB1aVc7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgY2FzZSAidG9wIjoKICAgICAgICAgIGNhc2UgImJvdHRvbSI6CiAgICAgICAgICAgIGhlaWdodCArPSB1aUg7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB3aWR0aCA9IHVpVzsKICAgICAgICBoZWlnaHQgPSB1aUg7CiAgICAgIH0KICAgICAgaWYgKHdpZHRoICYmIHRoaXMudyA9PT0gIiIpIHsKICAgICAgICB3aWR0aCArPSBtYXJnaW5IOwogICAgICAgIHRoaXMudyA9IE1hdGgubWluKHRoaXMubWF4VyA8PSAwID8gSW5maW5pdHkgOiB0aGlzLm1heFcsIHRoaXMubWluVyArIDEgPCB3aWR0aCA/IHdpZHRoIDogdGhpcy5taW5XKTsKICAgICAgfQogICAgICBpZiAoaGVpZ2h0ICYmIHRoaXMuaCA9PT0gIiIpIHsKICAgICAgICBoZWlnaHQgKz0gbWFyZ2luVjsKICAgICAgICB0aGlzLmggPSBNYXRoLm1pbih0aGlzLm1heEggPD0gMCA/IEluZmluaXR5IDogdGhpcy5tYXhILCB0aGlzLm1pbkggKyAxIDwgaGVpZ2h0ID8gaGVpZ2h0IDogdGhpcy5taW5IKTsKICAgICAgfQogICAgfQogICAgdGhpc1skcG9wUGFyYV0oKTsKICAgIGZpeERpbWVuc2lvbnModGhpcyk7CiAgICBzZXRGaXJzdFVuc3BsaXR0YWJsZSh0aGlzKTsKICAgIGlmICghY2hlY2tEaW1lbnNpb25zKHRoaXMsIGF2YWlsYWJsZVNwYWNlKSkgewogICAgICB0aGlzLncgPSBzYXZlZFc7CiAgICAgIHRoaXMuaCA9IHNhdmVkSDsKICAgICAgdGhpc1skcG9wUGFyYV0oKTsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuRkFJTFVSRTsKICAgIH0KICAgIHVuc2V0Rmlyc3RVbnNwbGl0dGFibGUodGhpcyk7CiAgICBjb25zdCBzdHlsZSA9IHRvU3R5bGUodGhpcywgImZvbnQiLCAiZGltZW5zaW9ucyIsICJwb3NpdGlvbiIsICJyb3RhdGUiLCAiYW5jaG9yVHlwZSIsICJwcmVzZW5jZSIsICJtYXJnaW4iLCAiaEFsaWduIik7CiAgICBzZXRNaW5NYXhEaW1lbnNpb25zKHRoaXMsIHN0eWxlKTsKICAgIGNvbnN0IGNsYXNzTmFtZXMgPSBbInhmYUZpZWxkIl07CiAgICBpZiAodGhpcy5mb250KSB7CiAgICAgIGNsYXNzTmFtZXMucHVzaCgieGZhRm9udCIpOwogICAgfQogICAgaWYgKGlzUHJpbnRPbmx5KHRoaXMpKSB7CiAgICAgIGNsYXNzTmFtZXMucHVzaCgieGZhUHJpbnRPbmx5Iik7CiAgICB9CiAgICBjb25zdCBhdHRyaWJ1dGVzID0gewogICAgICBzdHlsZSwKICAgICAgaWQ6IHRoaXNbJHVpZF0sCiAgICAgIGNsYXNzOiBjbGFzc05hbWVzCiAgICB9OwogICAgaWYgKHN0eWxlLm1hcmdpbikgewogICAgICBzdHlsZS5wYWRkaW5nID0gc3R5bGUubWFyZ2luOwogICAgICBkZWxldGUgc3R5bGUubWFyZ2luOwogICAgfQogICAgc2V0QWNjZXNzKHRoaXMsIGNsYXNzTmFtZXMpOwogICAgaWYgKHRoaXMubmFtZSkgewogICAgICBhdHRyaWJ1dGVzLnhmYU5hbWUgPSB0aGlzLm5hbWU7CiAgICB9CiAgICBjb25zdCBjaGlsZHJlbiA9IFtdOwogICAgY29uc3QgaHRtbCA9IHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGF0dHJpYnV0ZXMsCiAgICAgIGNoaWxkcmVuCiAgICB9OwogICAgYXBwbHlBc3Npc3QodGhpcywgYXR0cmlidXRlcyk7CiAgICBjb25zdCBib3JkZXJTdHlsZSA9IHRoaXMuYm9yZGVyID8gdGhpcy5ib3JkZXJbJHRvU3R5bGVdKCkgOiBudWxsOwogICAgY29uc3QgYmJveCA9IGNvbXB1dGVCYm94KHRoaXMsIGh0bWwsIGF2YWlsYWJsZVNwYWNlKTsKICAgIGNvbnN0IHVpID0gdGhpcy51aVskdG9IVE1MXSgpLmh0bWw7CiAgICBpZiAoIXVpKSB7CiAgICAgIE9iamVjdC5hc3NpZ24oc3R5bGUsIGJvcmRlclN0eWxlKTsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhjcmVhdGVXcmFwcGVyKHRoaXMsIGh0bWwpLCBiYm94KTsKICAgIH0KICAgIGlmICh0aGlzWyR0YWJJbmRleF0pIHsKICAgICAgaWYgKHVpLmNoaWxkcmVuPy5bMF0pIHsKICAgICAgICB1aS5jaGlsZHJlblswXS5hdHRyaWJ1dGVzLnRhYmluZGV4ID0gdGhpc1skdGFiSW5kZXhdOwogICAgICB9IGVsc2UgewogICAgICAgIHVpLmF0dHJpYnV0ZXMudGFiaW5kZXggPSB0aGlzWyR0YWJJbmRleF07CiAgICAgIH0KICAgIH0KICAgIHVpLmF0dHJpYnV0ZXMuc3R5bGUgfHw9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBsZXQgYUVsZW1lbnQgPSBudWxsOwogICAgaWYgKHRoaXMudWkuYnV0dG9uKSB7CiAgICAgIGlmICh1aS5jaGlsZHJlbi5sZW5ndGggPT09IDEpIHsKICAgICAgICBbYUVsZW1lbnRdID0gdWkuY2hpbGRyZW4uc3BsaWNlKDAsIDEpOwogICAgICB9CiAgICAgIE9iamVjdC5hc3NpZ24odWkuYXR0cmlidXRlcy5zdHlsZSwgYm9yZGVyU3R5bGUpOwogICAgfSBlbHNlIHsKICAgICAgT2JqZWN0LmFzc2lnbihzdHlsZSwgYm9yZGVyU3R5bGUpOwogICAgfQogICAgY2hpbGRyZW4ucHVzaCh1aSk7CiAgICBpZiAodGhpcy52YWx1ZSkgewogICAgICBpZiAodGhpcy51aS5pbWFnZUVkaXQpIHsKICAgICAgICB1aS5jaGlsZHJlbi5wdXNoKHRoaXMudmFsdWVbJHRvSFRNTF0oKS5odG1sKTsKICAgICAgfSBlbHNlIGlmICghdGhpcy51aS5idXR0b24pIHsKICAgICAgICBsZXQgdmFsdWUgPSAiIjsKICAgICAgICBpZiAodGhpcy52YWx1ZS5leERhdGEpIHsKICAgICAgICAgIHZhbHVlID0gdGhpcy52YWx1ZS5leERhdGFbJHRleHRdKCk7CiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnZhbHVlLnRleHQpIHsKICAgICAgICAgIHZhbHVlID0gdGhpcy52YWx1ZS50ZXh0WyRnZXRFeHRyYV0oKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3QgaHRtbFZhbHVlID0gdGhpcy52YWx1ZVskdG9IVE1MXSgpLmh0bWw7CiAgICAgICAgICBpZiAoaHRtbFZhbHVlICE9PSBudWxsKSB7CiAgICAgICAgICAgIHZhbHVlID0gaHRtbFZhbHVlLmNoaWxkcmVuWzBdLnZhbHVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAodGhpcy51aS50ZXh0RWRpdCAmJiB0aGlzLnZhbHVlLnRleHQ/Lm1heENoYXJzKSB7CiAgICAgICAgICB1aS5jaGlsZHJlblswXS5hdHRyaWJ1dGVzLm1heExlbmd0aCA9IHRoaXMudmFsdWUudGV4dC5tYXhDaGFyczsKICAgICAgICB9CiAgICAgICAgaWYgKHZhbHVlKSB7CiAgICAgICAgICBpZiAodGhpcy51aS5udW1lcmljRWRpdCkgewogICAgICAgICAgICB2YWx1ZSA9IHBhcnNlRmxvYXQodmFsdWUpOwogICAgICAgICAgICB2YWx1ZSA9IGlzTmFOKHZhbHVlKSA/ICIiIDogdmFsdWUudG9TdHJpbmcoKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICh1aS5jaGlsZHJlblswXS5uYW1lID09PSAidGV4dGFyZWEiKSB7CiAgICAgICAgICAgIHVpLmNoaWxkcmVuWzBdLmF0dHJpYnV0ZXMudGV4dENvbnRlbnQgPSB2YWx1ZTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHVpLmNoaWxkcmVuWzBdLmF0dHJpYnV0ZXMudmFsdWUgPSB2YWx1ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmICghdGhpcy51aS5pbWFnZUVkaXQgJiYgdWkuY2hpbGRyZW4/LlswXSAmJiB0aGlzLmgpIHsKICAgICAgYm9yZGVyRGltcyA9IGJvcmRlckRpbXMgfHwgZ2V0Qm9yZGVyRGltcyh0aGlzLnVpWyRnZXRFeHRyYV0oKSk7CiAgICAgIGxldCBjYXB0aW9uSGVpZ2h0ID0gMDsKICAgICAgaWYgKHRoaXMuY2FwdGlvbiAmJiBbInRvcCIsICJib3R0b20iXS5pbmNsdWRlcyh0aGlzLmNhcHRpb24ucGxhY2VtZW50KSkgewogICAgICAgIGNhcHRpb25IZWlnaHQgPSB0aGlzLmNhcHRpb24ucmVzZXJ2ZTsKICAgICAgICBpZiAoY2FwdGlvbkhlaWdodCA8PSAwKSB7CiAgICAgICAgICBjYXB0aW9uSGVpZ2h0ID0gdGhpcy5jYXB0aW9uWyRnZXRFeHRyYV0oYXZhaWxhYmxlU3BhY2UpLmg7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGlucHV0SGVpZ2h0ID0gdGhpcy5oIC0gY2FwdGlvbkhlaWdodCAtIG1hcmdpblYgLSBib3JkZXJEaW1zLmg7CiAgICAgICAgdWkuY2hpbGRyZW5bMF0uYXR0cmlidXRlcy5zdHlsZS5oZWlnaHQgPSBtZWFzdXJlVG9TdHJpbmcoaW5wdXRIZWlnaHQpOwogICAgICB9IGVsc2UgewogICAgICAgIHVpLmNoaWxkcmVuWzBdLmF0dHJpYnV0ZXMuc3R5bGUuaGVpZ2h0ID0gIjEwMCUiOwogICAgICB9CiAgICB9CiAgICBpZiAoYUVsZW1lbnQpIHsKICAgICAgdWkuY2hpbGRyZW4ucHVzaChhRWxlbWVudCk7CiAgICB9CiAgICBpZiAoIWNhcHRpb24pIHsKICAgICAgaWYgKHVpLmF0dHJpYnV0ZXMuY2xhc3MpIHsKICAgICAgICB1aS5hdHRyaWJ1dGVzLmNsYXNzLnB1c2goInhmYUxlZnQiKTsKICAgICAgfQogICAgICB0aGlzLncgPSBzYXZlZFc7CiAgICAgIHRoaXMuaCA9IHNhdmVkSDsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2VzcyhjcmVhdGVXcmFwcGVyKHRoaXMsIGh0bWwpLCBiYm94KTsKICAgIH0KICAgIGlmICh0aGlzLnVpLmJ1dHRvbikgewogICAgICBpZiAoc3R5bGUucGFkZGluZykgewogICAgICAgIGRlbGV0ZSBzdHlsZS5wYWRkaW5nOwogICAgICB9CiAgICAgIGlmIChjYXB0aW9uLm5hbWUgPT09ICJkaXYiKSB7CiAgICAgICAgY2FwdGlvbi5uYW1lID0gInNwYW4iOwogICAgICB9CiAgICAgIHVpLmNoaWxkcmVuLnB1c2goY2FwdGlvbik7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoaHRtbCwgYmJveCk7CiAgICB9IGVsc2UgaWYgKHRoaXMudWkuY2hlY2tCdXR0b24pIHsKICAgICAgY2FwdGlvbi5hdHRyaWJ1dGVzLmNsYXNzWzBdID0gInhmYUNhcHRpb25Gb3JDaGVja0J1dHRvbiI7CiAgICB9CiAgICB1aS5hdHRyaWJ1dGVzLmNsYXNzIHx8PSBbXTsKICAgIHVpLmNoaWxkcmVuLnNwbGljZSgwLCAwLCBjYXB0aW9uKTsKICAgIHN3aXRjaCAodGhpcy5jYXB0aW9uLnBsYWNlbWVudCkgewogICAgICBjYXNlICJsZWZ0IjoKICAgICAgICB1aS5hdHRyaWJ1dGVzLmNsYXNzLnB1c2goInhmYUxlZnQiKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAicmlnaHQiOgogICAgICAgIHVpLmF0dHJpYnV0ZXMuY2xhc3MucHVzaCgieGZhUmlnaHQiKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAidG9wIjoKICAgICAgICB1aS5hdHRyaWJ1dGVzLmNsYXNzLnB1c2goInhmYVRvcCIpOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJib3R0b20iOgogICAgICAgIHVpLmF0dHJpYnV0ZXMuY2xhc3MucHVzaCgieGZhQm90dG9tIik7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgImlubGluZSI6CiAgICAgICAgdWkuYXR0cmlidXRlcy5jbGFzcy5wdXNoKCJ4ZmFMZWZ0Iik7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICB0aGlzLncgPSBzYXZlZFc7CiAgICB0aGlzLmggPSBzYXZlZEg7CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKGNyZWF0ZVdyYXBwZXIodGhpcywgaHRtbCksIGJib3gpOwogIH0KfQpjbGFzcyBGaWxsIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImZpbGwiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5wcmVzZW5jZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnByZXNlbmNlLCBbInZpc2libGUiLCAiaGlkZGVuIiwgImluYWN0aXZlIiwgImludmlzaWJsZSJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmNvbG9yID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMubGluZWFyID0gbnVsbDsKICAgIHRoaXMucGF0dGVybiA9IG51bGw7CiAgICB0aGlzLnJhZGlhbCA9IG51bGw7CiAgICB0aGlzLnNvbGlkID0gbnVsbDsKICAgIHRoaXMuc3RpcHBsZSA9IG51bGw7CiAgfQogIFskdG9TdHlsZV0oKSB7CiAgICBjb25zdCBwYXJlbnQgPSB0aGlzWyRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBncmFuZHBhID0gcGFyZW50WyRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBnZ3JhbmRwYSA9IGdyYW5kcGFbJGdldFBhcmVudF0oKTsKICAgIGNvbnN0IHN0eWxlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGxldCBwcm9wTmFtZSA9ICJjb2xvciI7CiAgICBsZXQgYWx0UHJvcE5hbWUgPSBwcm9wTmFtZTsKICAgIGlmIChwYXJlbnQgaW5zdGFuY2VvZiBCb3JkZXIpIHsKICAgICAgcHJvcE5hbWUgPSAiYmFja2dyb3VuZC1jb2xvciI7CiAgICAgIGFsdFByb3BOYW1lID0gImJhY2tncm91bmQiOwogICAgICBpZiAoZ2dyYW5kcGEgaW5zdGFuY2VvZiBVaSkgewogICAgICAgIHN0eWxlLmJhY2tncm91bmRDb2xvciA9ICJ3aGl0ZSI7CiAgICAgIH0KICAgIH0KICAgIGlmIChwYXJlbnQgaW5zdGFuY2VvZiBSZWN0YW5nbGUgfHwgcGFyZW50IGluc3RhbmNlb2YgQXJjKSB7CiAgICAgIHByb3BOYW1lID0gYWx0UHJvcE5hbWUgPSAiZmlsbCI7CiAgICAgIHN0eWxlLmZpbGwgPSAid2hpdGUiOwogICAgfQogICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpKSB7CiAgICAgIGlmIChuYW1lID09PSAiZXh0cmFzIiB8fCBuYW1lID09PSAiY29sb3IiKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3Qgb2JqID0gdGhpc1tuYW1lXTsKICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgWEZBT2JqZWN0KSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGNvbG9yID0gb2JqWyR0b1N0eWxlXSh0aGlzLmNvbG9yKTsKICAgICAgaWYgKGNvbG9yKSB7CiAgICAgICAgc3R5bGVbY29sb3Iuc3RhcnRzV2l0aCgiIyIpID8gcHJvcE5hbWUgOiBhbHRQcm9wTmFtZV0gPSBjb2xvcjsKICAgICAgfQogICAgICByZXR1cm4gc3R5bGU7CiAgICB9CiAgICBpZiAodGhpcy5jb2xvcj8udmFsdWUpIHsKICAgICAgY29uc3QgY29sb3IgPSB0aGlzLmNvbG9yWyR0b1N0eWxlXSgpOwogICAgICBzdHlsZVtjb2xvci5zdGFydHNXaXRoKCIjIikgPyBwcm9wTmFtZSA6IGFsdFByb3BOYW1lXSA9IGNvbG9yOwogICAgfQogICAgcmV0dXJuIHN0eWxlOwogIH0KfQpjbGFzcyBGaWx0ZXIgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZmlsdGVyIiwgdHJ1ZSk7CiAgICB0aGlzLmFkZFJldm9jYXRpb25JbmZvID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuYWRkUmV2b2NhdGlvbkluZm8sIFsiIiwgInJlcXVpcmVkIiwgIm9wdGlvbmFsIiwgIm5vbmUiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnZlcnNpb24gPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogdGhpcy52ZXJzaW9uLAogICAgICBkZWZhdWx0VmFsdWU6IDUsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gMSAmJiB4IDw9IDUKICAgIH0pOwogICAgdGhpcy5hcHBlYXJhbmNlRmlsdGVyID0gbnVsbDsKICAgIHRoaXMuY2VydGlmaWNhdGVzID0gbnVsbDsKICAgIHRoaXMuZGlnZXN0TWV0aG9kcyA9IG51bGw7CiAgICB0aGlzLmVuY29kaW5ncyA9IG51bGw7CiAgICB0aGlzLmVuY3J5cHRpb25NZXRob2RzID0gbnVsbDsKICAgIHRoaXMuaGFuZGxlciA9IG51bGw7CiAgICB0aGlzLmxvY2tEb2N1bWVudCA9IG51bGw7CiAgICB0aGlzLm1kcCA9IG51bGw7CiAgICB0aGlzLnJlYXNvbnMgPSBudWxsOwogICAgdGhpcy50aW1lU3RhbXAgPSBudWxsOwogIH0KfQpjbGFzcyBGbG9hdCBleHRlbmRzIENvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZmxvYXQiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICBjb25zdCBudW1iZXIgPSBwYXJzZUZsb2F0KHRoaXNbJGNvbnRlbnRdLnRyaW0oKSk7CiAgICB0aGlzWyRjb250ZW50XSA9IGlzTmFOKG51bWJlcikgPyBudWxsIDogbnVtYmVyOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIHJldHVybiB2YWx1ZVRvSHRtbCh0aGlzWyRjb250ZW50XSAhPT0gbnVsbCA/IHRoaXNbJGNvbnRlbnRdLnRvU3RyaW5nKCkgOiAiIik7CiAgfQp9CmNsYXNzIHRlbXBsYXRlX0ZvbnQgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiZm9udCIsIHRydWUpOwogICAgdGhpcy5iYXNlbGluZVNoaWZ0ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5iYXNlbGluZVNoaWZ0KTsKICAgIHRoaXMuZm9udEhvcml6b250YWxTY2FsZSA9IGdldEZsb2F0KHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5mb250SG9yaXpvbnRhbFNjYWxlLAogICAgICBkZWZhdWx0VmFsdWU6IDEwMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwCiAgICB9KTsKICAgIHRoaXMuZm9udFZlcnRpY2FsU2NhbGUgPSBnZXRGbG9hdCh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuZm9udFZlcnRpY2FsU2NhbGUsCiAgICAgIGRlZmF1bHRWYWx1ZTogMTAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDAKICAgIH0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmtlcm5pbmdNb2RlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMua2VybmluZ01vZGUsIFsibm9uZSIsICJwYWlyIl0pOwogICAgdGhpcy5sZXR0ZXJTcGFjaW5nID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5sZXR0ZXJTcGFjaW5nLCAiMCIpOwogICAgdGhpcy5saW5lVGhyb3VnaCA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmxpbmVUaHJvdWdoLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEgfHwgeCA9PT0gMgogICAgfSk7CiAgICB0aGlzLmxpbmVUaHJvdWdoUGVyaW9kID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMubGluZVRocm91Z2hQZXJpb2QsIFsiYWxsIiwgIndvcmQiXSk7CiAgICB0aGlzLm92ZXJsaW5lID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMub3ZlcmxpbmUsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMSB8fCB4ID09PSAyCiAgICB9KTsKICAgIHRoaXMub3ZlcmxpbmVQZXJpb2QgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5vdmVybGluZVBlcmlvZCwgWyJhbGwiLCAid29yZCJdKTsKICAgIHRoaXMucG9zdHVyZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnBvc3R1cmUsIFsibm9ybWFsIiwgIml0YWxpYyJdKTsKICAgIHRoaXMuc2l6ZSA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMuc2l6ZSwgIjEwcHQiKTsKICAgIHRoaXMudHlwZWZhY2UgPSBhdHRyaWJ1dGVzLnR5cGVmYWNlIHx8ICJDb3VyaWVyIjsKICAgIHRoaXMudW5kZXJsaW5lID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMudW5kZXJsaW5lLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEgfHwgeCA9PT0gMgogICAgfSk7CiAgICB0aGlzLnVuZGVybGluZVBlcmlvZCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnVuZGVybGluZVBlcmlvZCwgWyJhbGwiLCAid29yZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLndlaWdodCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLndlaWdodCwgWyJub3JtYWwiLCAiYm9sZCJdKTsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMuZmlsbCA9IG51bGw7CiAgfQogIFskY2xlYW5dKGJ1aWxkZXIpIHsKICAgIHN1cGVyWyRjbGVhbl0oYnVpbGRlcik7CiAgICB0aGlzWyRnbG9iYWxEYXRhXS51c2VkVHlwZWZhY2VzLmFkZCh0aGlzLnR5cGVmYWNlKTsKICB9CiAgWyR0b1N0eWxlXSgpIHsKICAgIGNvbnN0IHN0eWxlID0gdG9TdHlsZSh0aGlzLCAiZmlsbCIpOwogICAgY29uc3QgY29sb3IgPSBzdHlsZS5jb2xvcjsKICAgIGlmIChjb2xvcikgewogICAgICBpZiAoY29sb3IgPT09ICIjMDAwMDAwIikgewogICAgICAgIGRlbGV0ZSBzdHlsZS5jb2xvcjsKICAgICAgfSBlbHNlIGlmICghY29sb3Iuc3RhcnRzV2l0aCgiIyIpKSB7CiAgICAgICAgc3R5bGUuYmFja2dyb3VuZCA9IGNvbG9yOwogICAgICAgIHN0eWxlLmJhY2tncm91bmRDbGlwID0gInRleHQiOwogICAgICAgIHN0eWxlLmNvbG9yID0gInRyYW5zcGFyZW50IjsKICAgICAgfQogICAgfQogICAgaWYgKHRoaXMuYmFzZWxpbmVTaGlmdCkgewogICAgICBzdHlsZS52ZXJ0aWNhbEFsaWduID0gbWVhc3VyZVRvU3RyaW5nKHRoaXMuYmFzZWxpbmVTaGlmdCk7CiAgICB9CiAgICBzdHlsZS5mb250S2VybmluZyA9IHRoaXMua2VybmluZ01vZGUgPT09ICJub25lIiA/ICJub25lIiA6ICJub3JtYWwiOwogICAgc3R5bGUubGV0dGVyU3BhY2luZyA9IG1lYXN1cmVUb1N0cmluZyh0aGlzLmxldHRlclNwYWNpbmcpOwogICAgaWYgKHRoaXMubGluZVRocm91Z2ggIT09IDApIHsKICAgICAgc3R5bGUudGV4dERlY29yYXRpb24gPSAibGluZS10aHJvdWdoIjsKICAgICAgaWYgKHRoaXMubGluZVRocm91Z2ggPT09IDIpIHsKICAgICAgICBzdHlsZS50ZXh0RGVjb3JhdGlvblN0eWxlID0gImRvdWJsZSI7CiAgICAgIH0KICAgIH0KICAgIGlmICh0aGlzLm92ZXJsaW5lICE9PSAwKSB7CiAgICAgIHN0eWxlLnRleHREZWNvcmF0aW9uID0gIm92ZXJsaW5lIjsKICAgICAgaWYgKHRoaXMub3ZlcmxpbmUgPT09IDIpIHsKICAgICAgICBzdHlsZS50ZXh0RGVjb3JhdGlvblN0eWxlID0gImRvdWJsZSI7CiAgICAgIH0KICAgIH0KICAgIHN0eWxlLmZvbnRTdHlsZSA9IHRoaXMucG9zdHVyZTsKICAgIHN0eWxlLmZvbnRTaXplID0gbWVhc3VyZVRvU3RyaW5nKDAuOTkgKiB0aGlzLnNpemUpOwogICAgc2V0Rm9udEZhbWlseSh0aGlzLCB0aGlzLCB0aGlzWyRnbG9iYWxEYXRhXS5mb250RmluZGVyLCBzdHlsZSk7CiAgICBpZiAodGhpcy51bmRlcmxpbmUgIT09IDApIHsKICAgICAgc3R5bGUudGV4dERlY29yYXRpb24gPSAidW5kZXJsaW5lIjsKICAgICAgaWYgKHRoaXMudW5kZXJsaW5lID09PSAyKSB7CiAgICAgICAgc3R5bGUudGV4dERlY29yYXRpb25TdHlsZSA9ICJkb3VibGUiOwogICAgICB9CiAgICB9CiAgICBzdHlsZS5mb250V2VpZ2h0ID0gdGhpcy53ZWlnaHQ7CiAgICByZXR1cm4gc3R5bGU7CiAgfQp9CmNsYXNzIEZvcm1hdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJmb3JtYXQiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMucGljdHVyZSA9IG51bGw7CiAgfQp9CmNsYXNzIEhhbmRsZXIgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiaGFuZGxlciIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgSHlwaGVuYXRpb24gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiaHlwaGVuYXRpb24iKTsKICAgIHRoaXMuZXhjbHVkZUFsbENhcHMgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5leGNsdWRlQWxsQ2FwcywKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMuZXhjbHVkZUluaXRpYWxDYXAgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5leGNsdWRlSW5pdGlhbENhcCwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMuaHlwaGVuYXRlID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuaHlwaGVuYXRlLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEKICAgIH0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnB1c2hDaGFyYWN0ZXJDb3VudCA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnB1c2hDaGFyYWN0ZXJDb3VudCwKICAgICAgZGVmYXVsdFZhbHVlOiAzLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDAKICAgIH0pOwogICAgdGhpcy5yZW1haW5DaGFyYWN0ZXJDb3VudCA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnJlbWFpbkNoYXJhY3RlckNvdW50LAogICAgICBkZWZhdWx0VmFsdWU6IDMsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gMAogICAgfSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy53b3JkQ2hhcmFjdGVyQ291bnQgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy53b3JkQ2hhcmFjdGVyQ291bnQsCiAgICAgIGRlZmF1bHRWYWx1ZTogNywKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwCiAgICB9KTsKICB9Cn0KY2xhc3MgSW1hZ2UgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAiaW1hZ2UiKTsKICAgIHRoaXMuYXNwZWN0ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuYXNwZWN0LCBbImZpdCIsICJhY3R1YWwiLCAiaGVpZ2h0IiwgIm5vbmUiLCAid2lkdGgiXSk7CiAgICB0aGlzLmNvbnRlbnRUeXBlID0gYXR0cmlidXRlcy5jb250ZW50VHlwZSB8fCAiIjsKICAgIHRoaXMuaHJlZiA9IGF0dHJpYnV0ZXMuaHJlZiB8fCAiIjsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy50cmFuc2ZlckVuY29kaW5nID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHJhbnNmZXJFbmNvZGluZywgWyJiYXNlNjQiLCAibm9uZSIsICJwYWNrYWdlIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgWyR0b0hUTUxdKCkgewogICAgaWYgKHRoaXMuY29udGVudFR5cGUgJiYgIU1JTUVTLmhhcyh0aGlzLmNvbnRlbnRUeXBlLnRvTG93ZXJDYXNlKCkpKSB7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkVNUFRZOwogICAgfQogICAgbGV0IGJ1ZmZlciA9IHRoaXNbJGdsb2JhbERhdGFdLmltYWdlcz8uZ2V0KHRoaXMuaHJlZik7CiAgICBpZiAoIWJ1ZmZlciAmJiAodGhpcy5ocmVmIHx8ICF0aGlzWyRjb250ZW50XSkpIHsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuRU1QVFk7CiAgICB9CiAgICBpZiAoIWJ1ZmZlciAmJiB0aGlzLnRyYW5zZmVyRW5jb2RpbmcgPT09ICJiYXNlNjQiKSB7CiAgICAgIGJ1ZmZlciA9IGZyb21CYXNlNjRVdGlsKHRoaXNbJGNvbnRlbnRdKTsKICAgIH0KICAgIGlmICghYnVmZmVyKSB7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkVNUFRZOwogICAgfQogICAgaWYgKCF0aGlzLmNvbnRlbnRUeXBlKSB7CiAgICAgIGZvciAoY29uc3QgW2hlYWRlciwgdHlwZV0gb2YgSU1BR0VTX0hFQURFUlMpIHsKICAgICAgICBpZiAoYnVmZmVyLmxlbmd0aCA+IGhlYWRlci5sZW5ndGggJiYgaGVhZGVyLmV2ZXJ5KCh4LCBpKSA9PiB4ID09PSBidWZmZXJbaV0pKSB7CiAgICAgICAgICB0aGlzLmNvbnRlbnRUeXBlID0gdHlwZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoIXRoaXMuY29udGVudFR5cGUpIHsKICAgICAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICAgICAgfQogICAgfQogICAgY29uc3QgYmxvYiA9IG5ldyBCbG9iKFtidWZmZXJdLCB7CiAgICAgIHR5cGU6IHRoaXMuY29udGVudFR5cGUKICAgIH0pOwogICAgbGV0IHN0eWxlOwogICAgc3dpdGNoICh0aGlzLmFzcGVjdCkgewogICAgICBjYXNlICJmaXQiOgogICAgICBjYXNlICJhY3R1YWwiOgogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJoZWlnaHQiOgogICAgICAgIHN0eWxlID0gewogICAgICAgICAgaGVpZ2h0OiAiMTAwJSIsCiAgICAgICAgICBvYmplY3RGaXQ6ICJmaWxsIgogICAgICAgIH07CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIm5vbmUiOgogICAgICAgIHN0eWxlID0gewogICAgICAgICAgd2lkdGg6ICIxMDAlIiwKICAgICAgICAgIGhlaWdodDogIjEwMCUiLAogICAgICAgICAgb2JqZWN0Rml0OiAiZmlsbCIKICAgICAgICB9OwogICAgICAgIGJyZWFrOwogICAgICBjYXNlICJ3aWR0aCI6CiAgICAgICAgc3R5bGUgPSB7CiAgICAgICAgICB3aWR0aDogIjEwMCUiLAogICAgICAgICAgb2JqZWN0Rml0OiAiZmlsbCIKICAgICAgICB9OwogICAgICAgIGJyZWFrOwogICAgfQogICAgY29uc3QgcGFyZW50ID0gdGhpc1skZ2V0UGFyZW50XSgpOwogICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgIG5hbWU6ICJpbWciLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgY2xhc3M6IFsieGZhSW1hZ2UiXSwKICAgICAgICBzdHlsZSwKICAgICAgICBzcmM6IFVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYiksCiAgICAgICAgYWx0OiBwYXJlbnQgPyBhcmlhTGFiZWwocGFyZW50WyRnZXRQYXJlbnRdKCkpIDogbnVsbAogICAgICB9CiAgICB9KTsKICB9Cn0KY2xhc3MgSW1hZ2VFZGl0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImltYWdlRWRpdCIsIHRydWUpOwogICAgdGhpcy5kYXRhID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuZGF0YSwgWyJsaW5rIiwgImVtYmVkIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5ib3JkZXIgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGlmICh0aGlzLmRhdGEgPT09ICJlbWJlZCIpIHsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgICAgbmFtZTogImRpdiIsCiAgICAgICAgY2hpbGRyZW46IFtdLAogICAgICAgIGF0dHJpYnV0ZXM6IHt9CiAgICAgIH0pOwogICAgfQogICAgcmV0dXJuIEhUTUxSZXN1bHQuRU1QVFk7CiAgfQp9CmNsYXNzIEludGVnZXIgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImludGVnZXIiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICBjb25zdCBudW1iZXIgPSBwYXJzZUludCh0aGlzWyRjb250ZW50XS50cmltKCksIDEwKTsKICAgIHRoaXNbJGNvbnRlbnRdID0gaXNOYU4obnVtYmVyKSA/IG51bGwgOiBudW1iZXI7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgcmV0dXJuIHZhbHVlVG9IdG1sKHRoaXNbJGNvbnRlbnRdICE9PSBudWxsID8gdGhpc1skY29udGVudF0udG9TdHJpbmcoKSA6ICIiKTsKICB9Cn0KY2xhc3MgSXNzdWVycyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJpc3N1ZXJzIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudHlwZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnR5cGUsIFsib3B0aW9uYWwiLCAicmVxdWlyZWQiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5jZXJ0aWZpY2F0ZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBJdGVtcyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJpdGVtcyIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnByZXNlbmNlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMucHJlc2VuY2UsIFsidmlzaWJsZSIsICJoaWRkZW4iLCAiaW5hY3RpdmUiLCAiaW52aXNpYmxlIl0pOwogICAgdGhpcy5yZWYgPSBhdHRyaWJ1dGVzLnJlZiB8fCAiIjsKICAgIHRoaXMuc2F2ZSA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnNhdmUsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5ib29sZWFuID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRhdGUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGF0ZVRpbWUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZGVjaW1hbCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leERhdGEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmxvYXQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuaW1hZ2UgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuaW50ZWdlciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy50ZXh0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRpbWUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICB9CiAgWyR0b0hUTUxdKCkgewogICAgY29uc3Qgb3V0cHV0ID0gW107CiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIHRoaXNbJGdldENoaWxkcmVuXSgpKSB7CiAgICAgIG91dHB1dC5wdXNoKGNoaWxkWyR0ZXh0XSgpKTsKICAgIH0KICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3Mob3V0cHV0KTsKICB9Cn0KY2xhc3MgS2VlcCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJrZWVwIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIGNvbnN0IG9wdGlvbnMgPSBbIm5vbmUiLCAiY29udGVudEFyZWEiLCAicGFnZUFyZWEiXTsKICAgIHRoaXMuaW50YWN0ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuaW50YWN0LCBvcHRpb25zKTsKICAgIHRoaXMubmV4dCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLm5leHQsIG9wdGlvbnMpOwogICAgdGhpcy5wcmV2aW91cyA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnByZXZpb3VzLCBvcHRpb25zKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQp9CmNsYXNzIEtleVVzYWdlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgImtleVVzYWdlIik7CiAgICBjb25zdCBvcHRpb25zID0gWyIiLCAieWVzIiwgIm5vIl07CiAgICB0aGlzLmNybFNpZ24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5jcmxTaWduLCBvcHRpb25zKTsKICAgIHRoaXMuZGF0YUVuY2lwaGVybWVudCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmRhdGFFbmNpcGhlcm1lbnQsIG9wdGlvbnMpOwogICAgdGhpcy5kZWNpcGhlck9ubHkgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5kZWNpcGhlck9ubHksIG9wdGlvbnMpOwogICAgdGhpcy5kaWdpdGFsU2lnbmF0dXJlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuZGlnaXRhbFNpZ25hdHVyZSwgb3B0aW9ucyk7CiAgICB0aGlzLmVuY2lwaGVyT25seSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmVuY2lwaGVyT25seSwgb3B0aW9ucyk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMua2V5QWdyZWVtZW50ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMua2V5QWdyZWVtZW50LCBvcHRpb25zKTsKICAgIHRoaXMua2V5Q2VydFNpZ24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5rZXlDZXJ0U2lnbiwgb3B0aW9ucyk7CiAgICB0aGlzLmtleUVuY2lwaGVybWVudCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmtleUVuY2lwaGVybWVudCwgb3B0aW9ucyk7CiAgICB0aGlzLm5vblJlcHVkaWF0aW9uID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMubm9uUmVwdWRpYXRpb24sIG9wdGlvbnMpOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIExpbmUgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAibGluZSIsIHRydWUpOwogICAgdGhpcy5oYW5kID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuaGFuZCwgWyJldmVuIiwgImxlZnQiLCAicmlnaHQiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMuc2xvcGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5zbG9wZSwgWyJcXCIsICIvIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZWRnZSA9IG51bGw7CiAgfQogIFskdG9IVE1MXSgpIHsKICAgIGNvbnN0IHBhcmVudCA9IHRoaXNbJGdldFBhcmVudF0oKVskZ2V0UGFyZW50XSgpOwogICAgY29uc3QgZWRnZSA9IHRoaXMuZWRnZSB8fCBuZXcgRWRnZSh7fSk7CiAgICBjb25zdCBlZGdlU3R5bGUgPSBlZGdlWyR0b1N0eWxlXSgpOwogICAgY29uc3Qgc3R5bGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgY29uc3QgdGhpY2tuZXNzID0gZWRnZS5wcmVzZW5jZSA9PT0gInZpc2libGUiID8gZWRnZS50aGlja25lc3MgOiAwOwogICAgc3R5bGUuc3Ryb2tlV2lkdGggPSBtZWFzdXJlVG9TdHJpbmcodGhpY2tuZXNzKTsKICAgIHN0eWxlLnN0cm9rZSA9IGVkZ2VTdHlsZS5jb2xvcjsKICAgIGxldCB4MSwgeTEsIHgyLCB5MjsKICAgIGxldCB3aWR0aCA9ICIxMDAlIjsKICAgIGxldCBoZWlnaHQgPSAiMTAwJSI7CiAgICBpZiAocGFyZW50LncgPD0gdGhpY2tuZXNzKSB7CiAgICAgIFt4MSwgeTEsIHgyLCB5Ml0gPSBbIjUwJSIsIDAsICI1MCUiLCAiMTAwJSJdOwogICAgICB3aWR0aCA9IHN0eWxlLnN0cm9rZVdpZHRoOwogICAgfSBlbHNlIGlmIChwYXJlbnQuaCA8PSB0aGlja25lc3MpIHsKICAgICAgW3gxLCB5MSwgeDIsIHkyXSA9IFswLCAiNTAlIiwgIjEwMCUiLCAiNTAlIl07CiAgICAgIGhlaWdodCA9IHN0eWxlLnN0cm9rZVdpZHRoOwogICAgfSBlbHNlIGlmICh0aGlzLnNsb3BlID09PSAiXFwiKSB7CiAgICAgIFt4MSwgeTEsIHgyLCB5Ml0gPSBbMCwgMCwgIjEwMCUiLCAiMTAwJSJdOwogICAgfSBlbHNlIHsKICAgICAgW3gxLCB5MSwgeDIsIHkyXSA9IFswLCAiMTAwJSIsICIxMDAlIiwgMF07CiAgICB9CiAgICBjb25zdCBsaW5lID0gewogICAgICBuYW1lOiAibGluZSIsCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICB4bWxuczogU1ZHX05TLAogICAgICAgIHgxLAogICAgICAgIHkxLAogICAgICAgIHgyLAogICAgICAgIHkyLAogICAgICAgIHN0eWxlCiAgICAgIH0KICAgIH07CiAgICBjb25zdCBzdmcgPSB7CiAgICAgIG5hbWU6ICJzdmciLAogICAgICBjaGlsZHJlbjogW2xpbmVdLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgeG1sbnM6IFNWR19OUywKICAgICAgICB3aWR0aCwKICAgICAgICBoZWlnaHQsCiAgICAgICAgc3R5bGU6IHsKICAgICAgICAgIG92ZXJmbG93OiAidmlzaWJsZSIKICAgICAgICB9CiAgICAgIH0KICAgIH07CiAgICBpZiAoaGFzTWFyZ2luKHBhcmVudCkpIHsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgICAgbmFtZTogImRpdiIsCiAgICAgICAgYXR0cmlidXRlczogewogICAgICAgICAgc3R5bGU6IHsKICAgICAgICAgICAgZGlzcGxheTogImlubGluZSIsCiAgICAgICAgICAgIHdpZHRoOiAiMTAwJSIsCiAgICAgICAgICAgIGhlaWdodDogIjEwMCUiCiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICBjaGlsZHJlbjogW3N2Z10KICAgICAgfSk7CiAgICB9CiAgICBzdmcuYXR0cmlidXRlcy5zdHlsZS5wb3NpdGlvbiA9ICJhYnNvbHV0ZSI7CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHN2Zyk7CiAgfQp9CmNsYXNzIExpbmVhciBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJsaW5lYXIiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJ0b1JpZ2h0IiwgInRvQm90dG9tIiwgInRvTGVmdCIsICJ0b1RvcCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmNvbG9yID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICB9CiAgWyR0b1N0eWxlXShzdGFydENvbG9yKSB7CiAgICBzdGFydENvbG9yID0gc3RhcnRDb2xvciA/IHN0YXJ0Q29sb3JbJHRvU3R5bGVdKCkgOiAiI0ZGRkZGRiI7CiAgICBjb25zdCB0cmFuc2YgPSB0aGlzLnR5cGUucmVwbGFjZSgvKFtSQkxUXSkvLCAiICQxIikudG9Mb3dlckNhc2UoKTsKICAgIGNvbnN0IGVuZENvbG9yID0gdGhpcy5jb2xvciA/IHRoaXMuY29sb3JbJHRvU3R5bGVdKCkgOiAiIzAwMDAwMCI7CiAgICByZXR1cm4gYGxpbmVhci1ncmFkaWVudCgke3RyYW5zZn0sICR7c3RhcnRDb2xvcn0sICR7ZW5kQ29sb3J9KWA7CiAgfQp9CmNsYXNzIExvY2tEb2N1bWVudCBleHRlbmRzIENvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAibG9ja0RvY3VtZW50Iik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudHlwZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnR5cGUsIFsib3B0aW9uYWwiLCAicmVxdWlyZWQiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIHRoaXNbJGNvbnRlbnRdID0gZ2V0U3RyaW5nT3B0aW9uKHRoaXNbJGNvbnRlbnRdLCBbImF1dG8iLCAiMCIsICIxIl0pOwogIH0KfQpjbGFzcyBNYW5pZmVzdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJtYW5pZmVzdCIsIHRydWUpOwogICAgdGhpcy5hY3Rpb24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5hY3Rpb24sIFsiaW5jbHVkZSIsICJhbGwiLCAiZXhjbHVkZSJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMucmVmID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIE1hcmdpbiBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJtYXJnaW4iLCB0cnVlKTsKICAgIHRoaXMuYm90dG9tSW5zZXQgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLmJvdHRvbUluc2V0LCAiMCIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmxlZnRJbnNldCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubGVmdEluc2V0LCAiMCIpOwogICAgdGhpcy5yaWdodEluc2V0ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5yaWdodEluc2V0LCAiMCIpOwogICAgdGhpcy50b3BJbnNldCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMudG9wSW5zZXQsICIwIik7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KICBbJHRvU3R5bGVdKCkgewogICAgcmV0dXJuIHsKICAgICAgbWFyZ2luOiBtZWFzdXJlVG9TdHJpbmcodGhpcy50b3BJbnNldCkgKyAiICIgKyBtZWFzdXJlVG9TdHJpbmcodGhpcy5yaWdodEluc2V0KSArICIgIiArIG1lYXN1cmVUb1N0cmluZyh0aGlzLmJvdHRvbUluc2V0KSArICIgIiArIG1lYXN1cmVUb1N0cmluZyh0aGlzLmxlZnRJbnNldCkKICAgIH07CiAgfQp9CmNsYXNzIE1kcCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJtZHAiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5wZXJtaXNzaW9ucyA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLnBlcm1pc3Npb25zLAogICAgICBkZWZhdWx0VmFsdWU6IDIsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPT09IDEgfHwgeCA9PT0gMwogICAgfSk7CiAgICB0aGlzLnNpZ25hdHVyZVR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5zaWduYXR1cmVUeXBlLCBbImZpbGxlciIsICJhdXRob3IiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBNZWRpdW0gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAibWVkaXVtIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMuaW1hZ2luZ0JCb3ggPSBnZXRCQm94KGF0dHJpYnV0ZXMuaW1hZ2luZ0JCb3gpOwogICAgdGhpcy5sb25nID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5sb25nKTsKICAgIHRoaXMub3JpZW50YXRpb24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5vcmllbnRhdGlvbiwgWyJwb3J0cmFpdCIsICJsYW5kc2NhcGUiXSk7CiAgICB0aGlzLnNob3J0ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5zaG9ydCk7CiAgICB0aGlzLnN0b2NrID0gYXR0cmlidXRlcy5zdG9jayB8fCAiIjsKICAgIHRoaXMudHJheUluID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHJheUluLCBbImF1dG8iLCAiZGVsZWdhdGUiLCAicGFnZUZyb250Il0pOwogICAgdGhpcy50cmF5T3V0ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHJheU91dCwgWyJhdXRvIiwgImRlbGVnYXRlIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgTWVzc2FnZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJtZXNzYWdlIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnRleHQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgTnVtZXJpY0VkaXQgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAibnVtZXJpY0VkaXQiLCB0cnVlKTsKICAgIHRoaXMuaFNjcm9sbFBvbGljeSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmhTY3JvbGxQb2xpY3ksIFsiYXV0byIsICJvZmYiLCAib24iXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmJvcmRlciA9IG51bGw7CiAgICB0aGlzLmNvbWIgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IHN0eWxlID0gdG9TdHlsZSh0aGlzLCAiYm9yZGVyIiwgImZvbnQiLCAibWFyZ2luIik7CiAgICBjb25zdCBmaWVsZCA9IHRoaXNbJGdldFBhcmVudF0oKVskZ2V0UGFyZW50XSgpOwogICAgY29uc3QgaHRtbCA9IHsKICAgICAgbmFtZTogImlucHV0IiwKICAgICAgYXR0cmlidXRlczogewogICAgICAgIHR5cGU6ICJ0ZXh0IiwKICAgICAgICBmaWVsZElkOiBmaWVsZFskdWlkXSwKICAgICAgICBkYXRhSWQ6IGZpZWxkWyRkYXRhXT8uWyR1aWRdIHx8IGZpZWxkWyR1aWRdLAogICAgICAgIGNsYXNzOiBbInhmYVRleHRmaWVsZCJdLAogICAgICAgIHN0eWxlLAogICAgICAgICJhcmlhLWxhYmVsIjogYXJpYUxhYmVsKGZpZWxkKSwKICAgICAgICAiYXJpYS1yZXF1aXJlZCI6IGZhbHNlCiAgICAgIH0KICAgIH07CiAgICBpZiAoaXNSZXF1aXJlZChmaWVsZCkpIHsKICAgICAgaHRtbC5hdHRyaWJ1dGVzWyJhcmlhLXJlcXVpcmVkIl0gPSB0cnVlOwogICAgICBodG1sLmF0dHJpYnV0ZXMucmVxdWlyZWQgPSB0cnVlOwogICAgfQogICAgcmV0dXJuIEhUTUxSZXN1bHQuc3VjY2Vzcyh7CiAgICAgIG5hbWU6ICJsYWJlbCIsCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBjbGFzczogWyJ4ZmFMYWJlbCJdCiAgICAgIH0sCiAgICAgIGNoaWxkcmVuOiBbaHRtbF0KICAgIH0pOwogIH0KfQpjbGFzcyBPY2N1ciBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJvY2N1ciIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmluaXRpYWwgPSBhdHRyaWJ1dGVzLmluaXRpYWwgIT09ICIiID8gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuaW5pdGlhbCwKICAgICAgZGVmYXVsdFZhbHVlOiAiIiwKICAgICAgdmFsaWRhdGU6IHggPT4gdHJ1ZQogICAgfSkgOiAiIjsKICAgIHRoaXMubWF4ID0gYXR0cmlidXRlcy5tYXggIT09ICIiID8gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMubWF4LAogICAgICBkZWZhdWx0VmFsdWU6IDEsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHRydWUKICAgIH0pIDogIiI7CiAgICB0aGlzLm1pbiA9IGF0dHJpYnV0ZXMubWluICE9PSAiIiA/IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLm1pbiwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogeCA9PiB0cnVlCiAgICB9KSA6ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICB9CiAgWyRjbGVhbl0oKSB7CiAgICBjb25zdCBwYXJlbnQgPSB0aGlzWyRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBvcmlnaW5hbE1pbiA9IHRoaXMubWluOwogICAgaWYgKHRoaXMubWluID09PSAiIikgewogICAgICB0aGlzLm1pbiA9IHBhcmVudCBpbnN0YW5jZW9mIFBhZ2VBcmVhIHx8IHBhcmVudCBpbnN0YW5jZW9mIFBhZ2VTZXQgPyAwIDogMTsKICAgIH0KICAgIGlmICh0aGlzLm1heCA9PT0gIiIpIHsKICAgICAgaWYgKG9yaWdpbmFsTWluID09PSAiIikgewogICAgICAgIHRoaXMubWF4ID0gcGFyZW50IGluc3RhbmNlb2YgUGFnZUFyZWEgfHwgcGFyZW50IGluc3RhbmNlb2YgUGFnZVNldCA/IC0xIDogMTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLm1heCA9IHRoaXMubWluOwogICAgICB9CiAgICB9CiAgICBpZiAodGhpcy5tYXggIT09IC0xICYmIHRoaXMubWF4IDwgdGhpcy5taW4pIHsKICAgICAgdGhpcy5tYXggPSB0aGlzLm1pbjsKICAgIH0KICAgIGlmICh0aGlzLmluaXRpYWwgPT09ICIiKSB7CiAgICAgIHRoaXMuaW5pdGlhbCA9IHBhcmVudCBpbnN0YW5jZW9mIFRlbXBsYXRlID8gMSA6IHRoaXMubWluOwogICAgfQogIH0KfQpjbGFzcyBPaWQgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAib2lkIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIE9pZHMgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAib2lkcyIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMub2lkID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIE92ZXJmbG93IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgIm92ZXJmbG93Iik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubGVhZGVyID0gYXR0cmlidXRlcy5sZWFkZXIgfHwgIiI7CiAgICB0aGlzLnRhcmdldCA9IGF0dHJpYnV0ZXMudGFyZ2V0IHx8ICIiOwogICAgdGhpcy50cmFpbGVyID0gYXR0cmlidXRlcy50cmFpbGVyIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9CiAgWyRnZXRFeHRyYV0oKSB7CiAgICBpZiAoIXRoaXNbJGV4dHJhXSkgewogICAgICBjb25zdCBwYXJlbnQgPSB0aGlzWyRnZXRQYXJlbnRdKCk7CiAgICAgIGNvbnN0IHJvb3QgPSB0aGlzWyRnZXRUZW1wbGF0ZVJvb3RdKCk7CiAgICAgIGNvbnN0IHRhcmdldCA9IHJvb3RbJHNlYXJjaE5vZGVdKHRoaXMudGFyZ2V0LCBwYXJlbnQpOwogICAgICBjb25zdCBsZWFkZXIgPSByb290WyRzZWFyY2hOb2RlXSh0aGlzLmxlYWRlciwgcGFyZW50KTsKICAgICAgY29uc3QgdHJhaWxlciA9IHJvb3RbJHNlYXJjaE5vZGVdKHRoaXMudHJhaWxlciwgcGFyZW50KTsKICAgICAgdGhpc1skZXh0cmFdID0gewogICAgICAgIHRhcmdldDogdGFyZ2V0Py5bMF0gfHwgbnVsbCwKICAgICAgICBsZWFkZXI6IGxlYWRlcj8uWzBdIHx8IG51bGwsCiAgICAgICAgdHJhaWxlcjogdHJhaWxlcj8uWzBdIHx8IG51bGwsCiAgICAgICAgYWRkTGVhZGVyOiBmYWxzZSwKICAgICAgICBhZGRUcmFpbGVyOiBmYWxzZQogICAgICB9OwogICAgfQogICAgcmV0dXJuIHRoaXNbJGV4dHJhXTsKICB9Cn0KY2xhc3MgUGFnZUFyZWEgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAicGFnZUFyZWEiLCB0cnVlKTsKICAgIHRoaXMuYmxhbmtPck5vdEJsYW5rID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuYmxhbmtPck5vdEJsYW5rLCBbImFueSIsICJibGFuayIsICJub3RCbGFuayJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5pbml0aWFsTnVtYmVyID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuaW5pdGlhbE51bWJlciwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogeCA9PiB0cnVlCiAgICB9KTsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMubnVtYmVyZWQgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5udW1iZXJlZCwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogeCA9PiB0cnVlCiAgICB9KTsKICAgIHRoaXMub2RkT3JFdmVuID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMub2RkT3JFdmVuLCBbImFueSIsICJldmVuIiwgIm9kZCJdKTsKICAgIHRoaXMucGFnZVBvc2l0aW9uID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMucGFnZVBvc2l0aW9uLCBbImFueSIsICJmaXJzdCIsICJsYXN0IiwgIm9ubHkiLCAicmVzdCJdKTsKICAgIHRoaXMucmVsZXZhbnQgPSBnZXRSZWxldmFudChhdHRyaWJ1dGVzLnJlbGV2YW50KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmRlc2MgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tZWRpdW0gPSBudWxsOwogICAgdGhpcy5vY2N1ciA9IG51bGw7CiAgICB0aGlzLmFyZWEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY29udGVudEFyZWEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZHJhdyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leGNsR3JvdXAgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZmllbGQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3ViZm9ybSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KICBbJGlzVXNhYmxlXSgpIHsKICAgIGlmICghdGhpc1skZXh0cmFdKSB7CiAgICAgIHRoaXNbJGV4dHJhXSA9IHsKICAgICAgICBudW1iZXJPZlVzZTogMAogICAgICB9OwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiAhdGhpcy5vY2N1ciB8fCB0aGlzLm9jY3VyLm1heCA9PT0gLTEgfHwgdGhpc1skZXh0cmFdLm51bWJlck9mVXNlIDwgdGhpcy5vY2N1ci5tYXg7CiAgfQogIFskY2xlYW5QYWdlXSgpIHsKICAgIGRlbGV0ZSB0aGlzWyRleHRyYV07CiAgfQogIFskZ2V0TmV4dFBhZ2VdKCkgewogICAgdGhpc1skZXh0cmFdIHx8PSB7CiAgICAgIG51bWJlck9mVXNlOiAwCiAgICB9OwogICAgY29uc3QgcGFyZW50ID0gdGhpc1skZ2V0UGFyZW50XSgpOwogICAgaWYgKHBhcmVudC5yZWxhdGlvbiA9PT0gIm9yZGVyZWRPY2N1cnJlbmNlIikgewogICAgICBpZiAodGhpc1skaXNVc2FibGVdKCkpIHsKICAgICAgICB0aGlzWyRleHRyYV0ubnVtYmVyT2ZVc2UgKz0gMTsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHBhcmVudFskZ2V0TmV4dFBhZ2VdKCk7CiAgfQogIFskZ2V0QXZhaWxhYmxlU3BhY2VdKCkgewogICAgcmV0dXJuIHRoaXNbJGV4dHJhXS5zcGFjZSB8fCB7CiAgICAgIHdpZHRoOiAwLAogICAgICBoZWlnaHQ6IDAKICAgIH07CiAgfQogIFskdG9IVE1MXSgpIHsKICAgIHRoaXNbJGV4dHJhXSB8fD0gewogICAgICBudW1iZXJPZlVzZTogMQogICAgfTsKICAgIGNvbnN0IGNoaWxkcmVuID0gW107CiAgICB0aGlzWyRleHRyYV0uY2hpbGRyZW4gPSBjaGlsZHJlbjsKICAgIGNvbnN0IHN0eWxlID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIGlmICh0aGlzLm1lZGl1bSAmJiB0aGlzLm1lZGl1bS5zaG9ydCAmJiB0aGlzLm1lZGl1bS5sb25nKSB7CiAgICAgIHN0eWxlLndpZHRoID0gbWVhc3VyZVRvU3RyaW5nKHRoaXMubWVkaXVtLnNob3J0KTsKICAgICAgc3R5bGUuaGVpZ2h0ID0gbWVhc3VyZVRvU3RyaW5nKHRoaXMubWVkaXVtLmxvbmcpOwogICAgICB0aGlzWyRleHRyYV0uc3BhY2UgPSB7CiAgICAgICAgd2lkdGg6IHRoaXMubWVkaXVtLnNob3J0LAogICAgICAgIGhlaWdodDogdGhpcy5tZWRpdW0ubG9uZwogICAgICB9OwogICAgICBpZiAodGhpcy5tZWRpdW0ub3JpZW50YXRpb24gPT09ICJsYW5kc2NhcGUiKSB7CiAgICAgICAgY29uc3QgeCA9IHN0eWxlLndpZHRoOwogICAgICAgIHN0eWxlLndpZHRoID0gc3R5bGUuaGVpZ2h0OwogICAgICAgIHN0eWxlLmhlaWdodCA9IHg7CiAgICAgICAgdGhpc1skZXh0cmFdLnNwYWNlID0gewogICAgICAgICAgd2lkdGg6IHRoaXMubWVkaXVtLmxvbmcsCiAgICAgICAgICBoZWlnaHQ6IHRoaXMubWVkaXVtLnNob3J0CiAgICAgICAgfTsKICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgd2FybigiWEZBIC0gTm8gbWVkaXVtIHNwZWNpZmllZCBpbiBwYWdlQXJlYTogcGxlYXNlIGZpbGUgYSBidWcuIik7CiAgICB9CiAgICB0aGlzWyRjaGlsZHJlblRvSFRNTF0oewogICAgICBmaWx0ZXI6IG5ldyBTZXQoWyJhcmVhIiwgImRyYXciLCAiZmllbGQiLCAic3ViZm9ybSJdKSwKICAgICAgaW5jbHVkZTogdHJ1ZQogICAgfSk7CiAgICB0aGlzWyRjaGlsZHJlblRvSFRNTF0oewogICAgICBmaWx0ZXI6IG5ldyBTZXQoWyJjb250ZW50QXJlYSJdKSwKICAgICAgaW5jbHVkZTogdHJ1ZQogICAgfSk7CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGNoaWxkcmVuLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgY2xhc3M6IFsieGZhUGFnZSJdLAogICAgICAgIGlkOiB0aGlzWyR1aWRdLAogICAgICAgIHN0eWxlLAogICAgICAgIHhmYU5hbWU6IHRoaXMubmFtZQogICAgICB9CiAgICB9KTsKICB9Cn0KY2xhc3MgUGFnZVNldCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJwYWdlU2V0IiwgdHJ1ZSk7CiAgICB0aGlzLmR1cGxleEltcG9zaXRpb24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5kdXBsZXhJbXBvc2l0aW9uLCBbImxvbmdFZGdlIiwgInNob3J0RWRnZSJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5yZWxhdGlvbiA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnJlbGF0aW9uLCBbIm9yZGVyZWRPY2N1cnJlbmNlIiwgImR1cGxleFBhZ2luYXRlZCIsICJzaW1wbGV4UGFnaW5hdGVkIl0pOwogICAgdGhpcy5yZWxldmFudCA9IGdldFJlbGV2YW50KGF0dHJpYnV0ZXMucmVsZXZhbnQpOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMub2NjdXIgPSBudWxsOwogICAgdGhpcy5wYWdlQXJlYSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5wYWdlU2V0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQogIFskY2xlYW5QYWdlXSgpIHsKICAgIGZvciAoY29uc3QgcGFnZSBvZiB0aGlzLnBhZ2VBcmVhLmNoaWxkcmVuKSB7CiAgICAgIHBhZ2VbJGNsZWFuUGFnZV0oKTsKICAgIH0KICAgIGZvciAoY29uc3QgcGFnZSBvZiB0aGlzLnBhZ2VTZXQuY2hpbGRyZW4pIHsKICAgICAgcGFnZVskY2xlYW5QYWdlXSgpOwogICAgfQogIH0KICBbJGlzVXNhYmxlXSgpIHsKICAgIHJldHVybiAhdGhpcy5vY2N1ciB8fCB0aGlzLm9jY3VyLm1heCA9PT0gLTEgfHwgdGhpc1skZXh0cmFdLm51bWJlck9mVXNlIDwgdGhpcy5vY2N1ci5tYXg7CiAgfQogIFskZ2V0TmV4dFBhZ2VdKCkgewogICAgdGhpc1skZXh0cmFdIHx8PSB7CiAgICAgIG51bWJlck9mVXNlOiAxLAogICAgICBwYWdlSW5kZXg6IC0xLAogICAgICBwYWdlU2V0SW5kZXg6IC0xCiAgICB9OwogICAgaWYgKHRoaXMucmVsYXRpb24gPT09ICJvcmRlcmVkT2NjdXJyZW5jZSIpIHsKICAgICAgaWYgKHRoaXNbJGV4dHJhXS5wYWdlSW5kZXggKyAxIDwgdGhpcy5wYWdlQXJlYS5jaGlsZHJlbi5sZW5ndGgpIHsKICAgICAgICB0aGlzWyRleHRyYV0ucGFnZUluZGV4ICs9IDE7CiAgICAgICAgY29uc3QgcGFnZUFyZWEgPSB0aGlzLnBhZ2VBcmVhLmNoaWxkcmVuW3RoaXNbJGV4dHJhXS5wYWdlSW5kZXhdOwogICAgICAgIHJldHVybiBwYWdlQXJlYVskZ2V0TmV4dFBhZ2VdKCk7CiAgICAgIH0KICAgICAgaWYgKHRoaXNbJGV4dHJhXS5wYWdlU2V0SW5kZXggKyAxIDwgdGhpcy5wYWdlU2V0LmNoaWxkcmVuLmxlbmd0aCkgewogICAgICAgIHRoaXNbJGV4dHJhXS5wYWdlU2V0SW5kZXggKz0gMTsKICAgICAgICByZXR1cm4gdGhpcy5wYWdlU2V0LmNoaWxkcmVuW3RoaXNbJGV4dHJhXS5wYWdlU2V0SW5kZXhdWyRnZXROZXh0UGFnZV0oKTsKICAgICAgfQogICAgICBpZiAodGhpc1skaXNVc2FibGVdKCkpIHsKICAgICAgICB0aGlzWyRleHRyYV0ubnVtYmVyT2ZVc2UgKz0gMTsKICAgICAgICB0aGlzWyRleHRyYV0ucGFnZUluZGV4ID0gLTE7CiAgICAgICAgdGhpc1skZXh0cmFdLnBhZ2VTZXRJbmRleCA9IC0xOwogICAgICAgIHJldHVybiB0aGlzWyRnZXROZXh0UGFnZV0oKTsKICAgICAgfQogICAgICBjb25zdCBwYXJlbnQgPSB0aGlzWyRnZXRQYXJlbnRdKCk7CiAgICAgIGlmIChwYXJlbnQgaW5zdGFuY2VvZiBQYWdlU2V0KSB7CiAgICAgICAgcmV0dXJuIHBhcmVudFskZ2V0TmV4dFBhZ2VdKCk7CiAgICAgIH0KICAgICAgdGhpc1skY2xlYW5QYWdlXSgpOwogICAgICByZXR1cm4gdGhpc1skZ2V0TmV4dFBhZ2VdKCk7CiAgICB9CiAgICBjb25zdCBwYWdlTnVtYmVyID0gdGhpc1skZ2V0VGVtcGxhdGVSb290XSgpWyRleHRyYV0ucGFnZU51bWJlcjsKICAgIGNvbnN0IHBhcml0eSA9IHBhZ2VOdW1iZXIgJSAyID09PSAwID8gImV2ZW4iIDogIm9kZCI7CiAgICBjb25zdCBwb3NpdGlvbiA9IHBhZ2VOdW1iZXIgPT09IDAgPyAiZmlyc3QiIDogInJlc3QiOwogICAgbGV0IHBhZ2UgPSB0aGlzLnBhZ2VBcmVhLmNoaWxkcmVuLmZpbmQocCA9PiBwLm9kZE9yRXZlbiA9PT0gcGFyaXR5ICYmIHAucGFnZVBvc2l0aW9uID09PSBwb3NpdGlvbik7CiAgICBpZiAocGFnZSkgewogICAgICByZXR1cm4gcGFnZTsKICAgIH0KICAgIHBhZ2UgPSB0aGlzLnBhZ2VBcmVhLmNoaWxkcmVuLmZpbmQocCA9PiBwLm9kZE9yRXZlbiA9PT0gImFueSIgJiYgcC5wYWdlUG9zaXRpb24gPT09IHBvc2l0aW9uKTsKICAgIGlmIChwYWdlKSB7CiAgICAgIHJldHVybiBwYWdlOwogICAgfQogICAgcGFnZSA9IHRoaXMucGFnZUFyZWEuY2hpbGRyZW4uZmluZChwID0+IHAub2RkT3JFdmVuID09PSAiYW55IiAmJiBwLnBhZ2VQb3NpdGlvbiA9PT0gImFueSIpOwogICAgaWYgKHBhZ2UpIHsKICAgICAgcmV0dXJuIHBhZ2U7CiAgICB9CiAgICByZXR1cm4gdGhpcy5wYWdlQXJlYS5jaGlsZHJlblswXTsKICB9Cn0KY2xhc3MgUGFyYSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJwYXJhIiwgdHJ1ZSk7CiAgICB0aGlzLmhBbGlnbiA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmhBbGlnbiwgWyJsZWZ0IiwgImNlbnRlciIsICJqdXN0aWZ5IiwgImp1c3RpZnlBbGwiLCAicmFkaXgiLCAicmlnaHQiXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubGluZUhlaWdodCA9IGF0dHJpYnV0ZXMubGluZUhlaWdodCA/IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubGluZUhlaWdodCwgIjBwdCIpIDogIiI7CiAgICB0aGlzLm1hcmdpbkxlZnQgPSBhdHRyaWJ1dGVzLm1hcmdpbkxlZnQgPyBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLm1hcmdpbkxlZnQsICIwcHQiKSA6ICIiOwogICAgdGhpcy5tYXJnaW5SaWdodCA9IGF0dHJpYnV0ZXMubWFyZ2luUmlnaHQgPyBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLm1hcmdpblJpZ2h0LCAiMHB0IikgOiAiIjsKICAgIHRoaXMub3JwaGFucyA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLm9ycGhhbnMsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwCiAgICB9KTsKICAgIHRoaXMucHJlc2VydmUgPSBhdHRyaWJ1dGVzLnByZXNlcnZlIHx8ICIiOwogICAgdGhpcy5yYWRpeE9mZnNldCA9IGF0dHJpYnV0ZXMucmFkaXhPZmZzZXQgPyBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnJhZGl4T2Zmc2V0LCAiMHB0IikgOiAiIjsKICAgIHRoaXMuc3BhY2VBYm92ZSA9IGF0dHJpYnV0ZXMuc3BhY2VBYm92ZSA/IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMuc3BhY2VBYm92ZSwgIjBwdCIpIDogIiI7CiAgICB0aGlzLnNwYWNlQmVsb3cgPSBhdHRyaWJ1dGVzLnNwYWNlQmVsb3cgPyBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnNwYWNlQmVsb3csICIwcHQiKSA6ICIiOwogICAgdGhpcy50YWJEZWZhdWx0ID0gYXR0cmlidXRlcy50YWJEZWZhdWx0ID8gZ2V0TWVhc3VyZW1lbnQodGhpcy50YWJEZWZhdWx0KSA6ICIiOwogICAgdGhpcy50YWJTdG9wcyA9IChhdHRyaWJ1dGVzLnRhYlN0b3BzIHx8ICIiKS50cmltKCkuc3BsaXQoL1xzKy8pLm1hcCgoeCwgaSkgPT4gaSAlIDIgPT09IDEgPyBnZXRNZWFzdXJlbWVudCh4KSA6IHgpOwogICAgdGhpcy50ZXh0SW5kZW50ID0gYXR0cmlidXRlcy50ZXh0SW5kZW50ID8gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy50ZXh0SW5kZW50LCAiMHB0IikgOiAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnZBbGlnbiA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnZBbGlnbiwgWyJ0b3AiLCAiYm90dG9tIiwgIm1pZGRsZSJdKTsKICAgIHRoaXMud2lkb3dzID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMud2lkb3dzLAogICAgICBkZWZhdWx0VmFsdWU6IDAsCiAgICAgIHZhbGlkYXRlOiB4ID0+IHggPj0gMAogICAgfSk7CiAgICB0aGlzLmh5cGhlbmF0aW9uID0gbnVsbDsKICB9CiAgWyR0b1N0eWxlXSgpIHsKICAgIGNvbnN0IHN0eWxlID0gdG9TdHlsZSh0aGlzLCAiaEFsaWduIik7CiAgICBpZiAodGhpcy5tYXJnaW5MZWZ0ICE9PSAiIikgewogICAgICBzdHlsZS5wYWRkaW5nTGVmdCA9IG1lYXN1cmVUb1N0cmluZyh0aGlzLm1hcmdpbkxlZnQpOwogICAgfQogICAgaWYgKHRoaXMubWFyZ2luUmlnaHQgIT09ICIiKSB7CiAgICAgIHN0eWxlLnBhZGRpbmdSaWdodCA9IG1lYXN1cmVUb1N0cmluZyh0aGlzLm1hcmdpblJpZ2h0KTsKICAgIH0KICAgIGlmICh0aGlzLnNwYWNlQWJvdmUgIT09ICIiKSB7CiAgICAgIHN0eWxlLnBhZGRpbmdUb3AgPSBtZWFzdXJlVG9TdHJpbmcodGhpcy5zcGFjZUFib3ZlKTsKICAgIH0KICAgIGlmICh0aGlzLnNwYWNlQmVsb3cgIT09ICIiKSB7CiAgICAgIHN0eWxlLnBhZGRpbmdCb3R0b20gPSBtZWFzdXJlVG9TdHJpbmcodGhpcy5zcGFjZUJlbG93KTsKICAgIH0KICAgIGlmICh0aGlzLnRleHRJbmRlbnQgIT09ICIiKSB7CiAgICAgIHN0eWxlLnRleHRJbmRlbnQgPSBtZWFzdXJlVG9TdHJpbmcodGhpcy50ZXh0SW5kZW50KTsKICAgICAgZml4VGV4dEluZGVudChzdHlsZSk7CiAgICB9CiAgICBpZiAodGhpcy5saW5lSGVpZ2h0ID4gMCkgewogICAgICBzdHlsZS5saW5lSGVpZ2h0ID0gbWVhc3VyZVRvU3RyaW5nKHRoaXMubGluZUhlaWdodCk7CiAgICB9CiAgICBpZiAodGhpcy50YWJEZWZhdWx0ICE9PSAiIikgewogICAgICBzdHlsZS50YWJTaXplID0gbWVhc3VyZVRvU3RyaW5nKHRoaXMudGFiRGVmYXVsdCk7CiAgICB9CiAgICBpZiAodGhpcy50YWJTdG9wcy5sZW5ndGggPiAwKSB7fQogICAgaWYgKHRoaXMuaHlwaGVuYXRhdGlvbikgewogICAgICBPYmplY3QuYXNzaWduKHN0eWxlLCB0aGlzLmh5cGhlbmF0YXRpb25bJHRvU3R5bGVdKCkpOwogICAgfQogICAgcmV0dXJuIHN0eWxlOwogIH0KfQpjbGFzcyBQYXNzd29yZEVkaXQgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAicGFzc3dvcmRFZGl0IiwgdHJ1ZSk7CiAgICB0aGlzLmhTY3JvbGxQb2xpY3kgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5oU2Nyb2xsUG9saWN5LCBbImF1dG8iLCAib2ZmIiwgIm9uIl0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnBhc3N3b3JkQ2hhciA9IGF0dHJpYnV0ZXMucGFzc3dvcmRDaGFyIHx8ICIqIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmJvcmRlciA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLm1hcmdpbiA9IG51bGw7CiAgfQp9CmNsYXNzIHRlbXBsYXRlX1BhdHRlcm4gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAicGF0dGVybiIsIHRydWUpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50eXBlLCBbImNyb3NzSGF0Y2giLCAiY3Jvc3NEaWFnb25hbCIsICJkaWFnb25hbExlZnQiLCAiZGlhZ29uYWxSaWdodCIsICJob3Jpem9udGFsIiwgInZlcnRpY2FsIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuY29sb3IgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogIH0KICBbJHRvU3R5bGVdKHN0YXJ0Q29sb3IpIHsKICAgIHN0YXJ0Q29sb3IgPSBzdGFydENvbG9yID8gc3RhcnRDb2xvclskdG9TdHlsZV0oKSA6ICIjRkZGRkZGIjsKICAgIGNvbnN0IGVuZENvbG9yID0gdGhpcy5jb2xvciA/IHRoaXMuY29sb3JbJHRvU3R5bGVdKCkgOiAiIzAwMDAwMCI7CiAgICBjb25zdCB3aWR0aCA9IDU7CiAgICBjb25zdCBjbWQgPSAicmVwZWF0aW5nLWxpbmVhci1ncmFkaWVudCI7CiAgICBjb25zdCBjb2xvcnMgPSBgJHtzdGFydENvbG9yfSwke3N0YXJ0Q29sb3J9ICR7d2lkdGh9cHgsJHtlbmRDb2xvcn0gJHt3aWR0aH1weCwke2VuZENvbG9yfSAkezIgKiB3aWR0aH1weGA7CiAgICBzd2l0Y2ggKHRoaXMudHlwZSkgewogICAgICBjYXNlICJjcm9zc0hhdGNoIjoKICAgICAgICByZXR1cm4gYCR7Y21kfSh0byB0b3AsJHtjb2xvcnN9KSAke2NtZH0odG8gcmlnaHQsJHtjb2xvcnN9KWA7CiAgICAgIGNhc2UgImNyb3NzRGlhZ29uYWwiOgogICAgICAgIHJldHVybiBgJHtjbWR9KDQ1ZGVnLCR7Y29sb3JzfSkgJHtjbWR9KC00NWRlZywke2NvbG9yc30pYDsKICAgICAgY2FzZSAiZGlhZ29uYWxMZWZ0IjoKICAgICAgICByZXR1cm4gYCR7Y21kfSg0NWRlZywke2NvbG9yc30pYDsKICAgICAgY2FzZSAiZGlhZ29uYWxSaWdodCI6CiAgICAgICAgcmV0dXJuIGAke2NtZH0oLTQ1ZGVnLCR7Y29sb3JzfSlgOwogICAgICBjYXNlICJob3Jpem9udGFsIjoKICAgICAgICByZXR1cm4gYCR7Y21kfSh0byB0b3AsJHtjb2xvcnN9KWA7CiAgICAgIGNhc2UgInZlcnRpY2FsIjoKICAgICAgICByZXR1cm4gYCR7Y21kfSh0byByaWdodCwke2NvbG9yc30pYDsKICAgIH0KICAgIHJldHVybiAiIjsKICB9Cn0KY2xhc3MgUGljdHVyZSBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJwaWN0dXJlIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIFByb3RvIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInByb3RvIiwgdHJ1ZSk7CiAgICB0aGlzLmFwcGVhcmFuY2VGaWx0ZXIgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYXJjID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmFyZWEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYXNzaXN0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmJhcmNvZGUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYmluZEl0ZW1zID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmJvb2tlbmQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYm9vbGVhbiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5ib3JkZXIgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYnJlYWsgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYnJlYWtBZnRlciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5icmVha0JlZm9yZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5idXR0b24gPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY2FsY3VsYXRlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNhcHRpb24gPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY2VydGlmaWNhdGUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY2VydGlmaWNhdGVzID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNoZWNrQnV0dG9uID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNob2ljZUxpc3QgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY29sb3IgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY29tYiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5jb25uZWN0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNvbnRlbnRBcmVhID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmNvcm5lciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kYXRlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRhdGVUaW1lID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRhdGVUaW1lRWRpdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kZWNpbWFsID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRlZmF1bHRVaSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kZXNjID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRpZ2VzdE1ldGhvZCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kaWdlc3RNZXRob2RzID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRyYXcgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZWRnZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5lbmNvZGluZyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5lbmNvZGluZ3MgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZW5jcnlwdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5lbmNyeXB0RGF0YSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5lbmNyeXB0aW9uID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmVuY3J5cHRpb25NZXRob2QgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZW5jcnlwdGlvbk1ldGhvZHMgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXZlbnQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXhEYXRhID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4T2JqZWN0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4Y2xHcm91cCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5leGVjdXRlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4dHJhcyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5maWVsZCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5maWxsID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmZpbHRlciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5mbG9hdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5mb250ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmZvcm1hdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5oYW5kbGVyID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmh5cGhlbmF0aW9uID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmltYWdlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmltYWdlRWRpdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5pbnRlZ2VyID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmlzc3VlcnMgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuaXRlbXMgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMua2VlcCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5rZXlVc2FnZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5saW5lID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmxpbmVhciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5sb2NrRG9jdW1lbnQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubWFuaWZlc3QgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubWFyZ2luID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLm1kcCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5tZWRpdW0gPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubWVzc2FnZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5udW1lcmljRWRpdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5vY2N1ciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5vaWQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMub2lkcyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5vdmVyZmxvdyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5wYWdlQXJlYSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5wYWdlU2V0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnBhcmEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucGFzc3dvcmRFZGl0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnBhdHRlcm4gPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucGljdHVyZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5yYWRpYWwgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucmVhc29uID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnJlYXNvbnMgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucmVjdGFuZ2xlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnJlZiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zY3JpcHQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2V0UHJvcGVydHkgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2lnbkRhdGEgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2lnbmF0dXJlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnNpZ25pbmcgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc29saWQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3BlYWsgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3RpcHBsZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zdWJmb3JtID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnN1YmZvcm1TZXQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3ViamVjdEROID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnN1YmplY3RETnMgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3VibWl0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRleHQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGV4dEVkaXQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGltZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy50aW1lU3RhbXAgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudG9vbFRpcCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy50cmF2ZXJzYWwgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudHJhdmVyc2UgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudWkgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudmFsaWRhdGUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudmFsdWUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudmFyaWFibGVzID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIFJhZGlhbCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJyYWRpYWwiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJ0b0VkZ2UiLCAidG9DZW50ZXIiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5jb2xvciA9IG51bGw7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQogIFskdG9TdHlsZV0oc3RhcnRDb2xvcikgewogICAgc3RhcnRDb2xvciA9IHN0YXJ0Q29sb3IgPyBzdGFydENvbG9yWyR0b1N0eWxlXSgpIDogIiNGRkZGRkYiOwogICAgY29uc3QgZW5kQ29sb3IgPSB0aGlzLmNvbG9yID8gdGhpcy5jb2xvclskdG9TdHlsZV0oKSA6ICIjMDAwMDAwIjsKICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMudHlwZSA9PT0gInRvRWRnZSIgPyBgJHtzdGFydENvbG9yfSwke2VuZENvbG9yfWAgOiBgJHtlbmRDb2xvcn0sJHtzdGFydENvbG9yfWA7CiAgICByZXR1cm4gYHJhZGlhbC1ncmFkaWVudChjaXJjbGUgYXQgY2VudGVyLCAke2NvbG9yc30pYDsKICB9Cn0KY2xhc3MgUmVhc29uIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInJlYXNvbiIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBSZWFzb25zIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInJlYXNvbnMiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnJlYXNvbiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBSZWN0YW5nbGUgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAicmVjdGFuZ2xlIiwgdHJ1ZSk7CiAgICB0aGlzLmhhbmQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5oYW5kLCBbImV2ZW4iLCAibGVmdCIsICJyaWdodCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuY29ybmVyID0gbmV3IFhGQU9iamVjdEFycmF5KDQpOwogICAgdGhpcy5lZGdlID0gbmV3IFhGQU9iamVjdEFycmF5KDQpOwogICAgdGhpcy5maWxsID0gbnVsbDsKICB9CiAgWyR0b0hUTUxdKCkgewogICAgY29uc3QgZWRnZSA9IHRoaXMuZWRnZS5jaGlsZHJlbi5sZW5ndGggPyB0aGlzLmVkZ2UuY2hpbGRyZW5bMF0gOiBuZXcgRWRnZSh7fSk7CiAgICBjb25zdCBlZGdlU3R5bGUgPSBlZGdlWyR0b1N0eWxlXSgpOwogICAgY29uc3Qgc3R5bGUgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgaWYgKHRoaXMuZmlsbD8ucHJlc2VuY2UgPT09ICJ2aXNpYmxlIikgewogICAgICBPYmplY3QuYXNzaWduKHN0eWxlLCB0aGlzLmZpbGxbJHRvU3R5bGVdKCkpOwogICAgfSBlbHNlIHsKICAgICAgc3R5bGUuZmlsbCA9ICJ0cmFuc3BhcmVudCI7CiAgICB9CiAgICBzdHlsZS5zdHJva2VXaWR0aCA9IG1lYXN1cmVUb1N0cmluZyhlZGdlLnByZXNlbmNlID09PSAidmlzaWJsZSIgPyBlZGdlLnRoaWNrbmVzcyA6IDApOwogICAgc3R5bGUuc3Ryb2tlID0gZWRnZVN0eWxlLmNvbG9yOwogICAgY29uc3QgY29ybmVyID0gdGhpcy5jb3JuZXIuY2hpbGRyZW4ubGVuZ3RoID8gdGhpcy5jb3JuZXIuY2hpbGRyZW5bMF0gOiBuZXcgQ29ybmVyKHt9KTsKICAgIGNvbnN0IGNvcm5lclN0eWxlID0gY29ybmVyWyR0b1N0eWxlXSgpOwogICAgY29uc3QgcmVjdCA9IHsKICAgICAgbmFtZTogInJlY3QiLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgeG1sbnM6IFNWR19OUywKICAgICAgICB3aWR0aDogIjEwMCUiLAogICAgICAgIGhlaWdodDogIjEwMCUiLAogICAgICAgIHg6IDAsCiAgICAgICAgeTogMCwKICAgICAgICByeDogY29ybmVyU3R5bGUucmFkaXVzLAogICAgICAgIHJ5OiBjb3JuZXJTdHlsZS5yYWRpdXMsCiAgICAgICAgc3R5bGUKICAgICAgfQogICAgfTsKICAgIGNvbnN0IHN2ZyA9IHsKICAgICAgbmFtZTogInN2ZyIsCiAgICAgIGNoaWxkcmVuOiBbcmVjdF0sCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICB4bWxuczogU1ZHX05TLAogICAgICAgIHN0eWxlOiB7CiAgICAgICAgICBvdmVyZmxvdzogInZpc2libGUiCiAgICAgICAgfSwKICAgICAgICB3aWR0aDogIjEwMCUiLAogICAgICAgIGhlaWdodDogIjEwMCUiCiAgICAgIH0KICAgIH07CiAgICBjb25zdCBwYXJlbnQgPSB0aGlzWyRnZXRQYXJlbnRdKClbJGdldFBhcmVudF0oKTsKICAgIGlmIChoYXNNYXJnaW4ocGFyZW50KSkgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgICBuYW1lOiAiZGl2IiwKICAgICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgICBzdHlsZTogewogICAgICAgICAgICBkaXNwbGF5OiAiaW5saW5lIiwKICAgICAgICAgICAgd2lkdGg6ICIxMDAlIiwKICAgICAgICAgICAgaGVpZ2h0OiAiMTAwJSIKICAgICAgICAgIH0KICAgICAgICB9LAogICAgICAgIGNoaWxkcmVuOiBbc3ZnXQogICAgICB9KTsKICAgIH0KICAgIHN2Zy5hdHRyaWJ1dGVzLnN0eWxlLnBvc2l0aW9uID0gImFic29sdXRlIjsKICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3Moc3ZnKTsKICB9Cn0KY2xhc3MgUmVmRWxlbWVudCBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJyZWYiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgU2NyaXB0IGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInNjcmlwdCIpOwogICAgdGhpcy5iaW5kaW5nID0gYXR0cmlidXRlcy5iaW5kaW5nIHx8ICIiOwogICAgdGhpcy5jb250ZW50VHlwZSA9IGF0dHJpYnV0ZXMuY29udGVudFR5cGUgfHwgIiI7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMucnVuQXQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5ydW5BdCwgWyJjbGllbnQiLCAiYm90aCIsICJzZXJ2ZXIiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBTZXRQcm9wZXJ0eSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzZXRQcm9wZXJ0eSIpOwogICAgdGhpcy5jb25uZWN0aW9uID0gYXR0cmlidXRlcy5jb25uZWN0aW9uIHx8ICIiOwogICAgdGhpcy5yZWYgPSBhdHRyaWJ1dGVzLnJlZiB8fCAiIjsKICAgIHRoaXMudGFyZ2V0ID0gYXR0cmlidXRlcy50YXJnZXQgfHwgIiI7CiAgfQp9CmNsYXNzIFNpZ25EYXRhIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInNpZ25EYXRhIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMub3BlcmF0aW9uID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMub3BlcmF0aW9uLCBbInNpZ24iLCAiY2xlYXIiLCAidmVyaWZ5Il0pOwogICAgdGhpcy5yZWYgPSBhdHRyaWJ1dGVzLnJlZiB8fCAiIjsKICAgIHRoaXMudGFyZ2V0ID0gYXR0cmlidXRlcy50YXJnZXQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5maWx0ZXIgPSBudWxsOwogICAgdGhpcy5tYW5pZmVzdCA9IG51bGw7CiAgfQp9CmNsYXNzIFNpZ25hdHVyZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzaWduYXR1cmUiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJQREYxLjMiLCAiUERGMS42Il0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuYm9yZGVyID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMuZmlsdGVyID0gbnVsbDsKICAgIHRoaXMubWFuaWZlc3QgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogIH0KfQpjbGFzcyBTaWduaW5nIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInNpZ25pbmciLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmNlcnRpZmljYXRlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIFNvbGlkIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInNvbGlkIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgfQogIFskdG9TdHlsZV0oc3RhcnRDb2xvcikgewogICAgcmV0dXJuIHN0YXJ0Q29sb3IgPyBzdGFydENvbG9yWyR0b1N0eWxlXSgpIDogIiNGRkZGRkYiOwogIH0KfQpjbGFzcyBTcGVhayBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzcGVhayIpOwogICAgdGhpcy5kaXNhYmxlID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuZGlzYWJsZSwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5wcmlvcml0eSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnByaW9yaXR5LCBbImN1c3RvbSIsICJjYXB0aW9uIiwgIm5hbWUiLCAidG9vbFRpcCJdKTsKICAgIHRoaXMucmlkID0gYXR0cmlidXRlcy5yaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBTdGlwcGxlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInN0aXBwbGUiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5yYXRlID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMucmF0ZSwKICAgICAgZGVmYXVsdFZhbHVlOiA1MCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA+PSAwICYmIHggPD0gMTAwCiAgICB9KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmNvbG9yID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICB9CiAgWyR0b1N0eWxlXShiZ0NvbG9yKSB7CiAgICBjb25zdCBhbHBoYSA9IHRoaXMucmF0ZSAvIDEwMDsKICAgIHJldHVybiBVdGlsLm1ha2VIZXhDb2xvcihNYXRoLnJvdW5kKGJnQ29sb3IudmFsdWUuciAqICgxIC0gYWxwaGEpICsgdGhpcy52YWx1ZS5yICogYWxwaGEpLCBNYXRoLnJvdW5kKGJnQ29sb3IudmFsdWUuZyAqICgxIC0gYWxwaGEpICsgdGhpcy52YWx1ZS5nICogYWxwaGEpLCBNYXRoLnJvdW5kKGJnQ29sb3IudmFsdWUuYiAqICgxIC0gYWxwaGEpICsgdGhpcy52YWx1ZS5iICogYWxwaGEpKTsKICB9Cn0KY2xhc3MgU3ViZm9ybSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzdWJmb3JtIiwgdHJ1ZSk7CiAgICB0aGlzLmFjY2VzcyA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmFjY2VzcywgWyJvcGVuIiwgIm5vbkludGVyYWN0aXZlIiwgInByb3RlY3RlZCIsICJyZWFkT25seSJdKTsKICAgIHRoaXMuYWxsb3dNYWNybyA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmFsbG93TWFjcm8sCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLmFuY2hvclR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5hbmNob3JUeXBlLCBbInRvcExlZnQiLCAiYm90dG9tQ2VudGVyIiwgImJvdHRvbUxlZnQiLCAiYm90dG9tUmlnaHQiLCAibWlkZGxlQ2VudGVyIiwgIm1pZGRsZUxlZnQiLCAibWlkZGxlUmlnaHQiLCAidG9wQ2VudGVyIiwgInRvcFJpZ2h0Il0pOwogICAgdGhpcy5jb2xTcGFuID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuY29sU3BhbiwKICAgICAgZGVmYXVsdFZhbHVlOiAxLAogICAgICB2YWxpZGF0ZTogbiA9PiBuID49IDEgfHwgbiA9PT0gLTEKICAgIH0pOwogICAgdGhpcy5jb2x1bW5XaWR0aHMgPSAoYXR0cmlidXRlcy5jb2x1bW5XaWR0aHMgfHwgIiIpLnRyaW0oKS5zcGxpdCgvXHMrLykubWFwKHggPT4geCA9PT0gIi0xIiA/IC0xIDogZ2V0TWVhc3VyZW1lbnQoeCkpOwogICAgdGhpcy5oID0gYXR0cmlidXRlcy5oID8gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5oKSA6ICIiOwogICAgdGhpcy5oQWxpZ24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5oQWxpZ24sIFsibGVmdCIsICJjZW50ZXIiLCAianVzdGlmeSIsICJqdXN0aWZ5QWxsIiwgInJhZGl4IiwgInJpZ2h0Il0pOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmxheW91dCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmxheW91dCwgWyJwb3NpdGlvbiIsICJsci10YiIsICJybC1yb3ciLCAicmwtdGIiLCAicm93IiwgInRhYmxlIiwgInRiIl0pOwogICAgdGhpcy5sb2NhbGUgPSBhdHRyaWJ1dGVzLmxvY2FsZSB8fCAiIjsKICAgIHRoaXMubWF4SCA9IGdldE1lYXN1cmVtZW50KGF0dHJpYnV0ZXMubWF4SCwgIjBwdCIpOwogICAgdGhpcy5tYXhXID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5tYXhXLCAiMHB0Iik7CiAgICB0aGlzLm1lcmdlTW9kZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLm1lcmdlTW9kZSwgWyJjb25zdW1lRGF0YSIsICJtYXRjaFRlbXBsYXRlIl0pOwogICAgdGhpcy5taW5IID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy5taW5ILCAiMHB0Iik7CiAgICB0aGlzLm1pblcgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLm1pblcsICIwcHQiKTsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMucHJlc2VuY2UgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5wcmVzZW5jZSwgWyJ2aXNpYmxlIiwgImhpZGRlbiIsICJpbmFjdGl2ZSIsICJpbnZpc2libGUiXSk7CiAgICB0aGlzLnJlbGV2YW50ID0gZ2V0UmVsZXZhbnQoYXR0cmlidXRlcy5yZWxldmFudCk7CiAgICB0aGlzLnJlc3RvcmVTdGF0ZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnJlc3RvcmVTdGF0ZSwgWyJtYW51YWwiLCAiYXV0byJdKTsKICAgIHRoaXMuc2NvcGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5zY29wZSwgWyJuYW1lIiwgIm5vbmUiXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy53ID0gYXR0cmlidXRlcy53ID8gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy53KSA6ICIiOwogICAgdGhpcy54ID0gZ2V0TWVhc3VyZW1lbnQoYXR0cmlidXRlcy54LCAiMHB0Iik7CiAgICB0aGlzLnkgPSBnZXRNZWFzdXJlbWVudChhdHRyaWJ1dGVzLnksICIwcHQiKTsKICAgIHRoaXMuYXNzaXN0ID0gbnVsbDsKICAgIHRoaXMuYmluZCA9IG51bGw7CiAgICB0aGlzLmJvb2tlbmQgPSBudWxsOwogICAgdGhpcy5ib3JkZXIgPSBudWxsOwogICAgdGhpcy5icmVhayA9IG51bGw7CiAgICB0aGlzLmNhbGN1bGF0ZSA9IG51bGw7CiAgICB0aGlzLmRlc2MgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5rZWVwID0gbnVsbDsKICAgIHRoaXMubWFyZ2luID0gbnVsbDsKICAgIHRoaXMub2NjdXIgPSBudWxsOwogICAgdGhpcy5vdmVyZmxvdyA9IG51bGw7CiAgICB0aGlzLnBhZ2VTZXQgPSBudWxsOwogICAgdGhpcy5wYXJhID0gbnVsbDsKICAgIHRoaXMudHJhdmVyc2FsID0gbnVsbDsKICAgIHRoaXMudmFsaWRhdGUgPSBudWxsOwogICAgdGhpcy52YXJpYWJsZXMgPSBudWxsOwogICAgdGhpcy5hcmVhID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmJyZWFrQWZ0ZXIgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYnJlYWtCZWZvcmUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuY29ubmVjdCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kcmF3ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV2ZW50ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4T2JqZWN0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmV4Y2xHcm91cCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5maWVsZCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5wcm90byA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zZXRQcm9wZXJ0eSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zdWJmb3JtID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnN1YmZvcm1TZXQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICB9CiAgWyRnZXRTdWJmb3JtUGFyZW50XSgpIHsKICAgIGNvbnN0IHBhcmVudCA9IHRoaXNbJGdldFBhcmVudF0oKTsKICAgIGlmIChwYXJlbnQgaW5zdGFuY2VvZiBTdWJmb3JtU2V0KSB7CiAgICAgIHJldHVybiBwYXJlbnRbJGdldFN1YmZvcm1QYXJlbnRdKCk7CiAgICB9CiAgICByZXR1cm4gcGFyZW50OwogIH0KICBbJGlzQmluZGFibGVdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIFskaXNUaGVyZU1vcmVXaWR0aF0oKSB7CiAgICByZXR1cm4gdGhpcy5sYXlvdXQuZW5kc1dpdGgoIi10YiIpICYmIHRoaXNbJGV4dHJhXS5hdHRlbXB0ID09PSAwICYmIHRoaXNbJGV4dHJhXS5udW1iZXJJbkxpbmUgPiAwIHx8IHRoaXNbJGdldFBhcmVudF0oKVskaXNUaGVyZU1vcmVXaWR0aF0oKTsKICB9CiAgKlskZ2V0Q29udGFpbmVkQ2hpbGRyZW5dKCkgewogICAgeWllbGQqIGdldENvbnRhaW5lZENoaWxkcmVuKHRoaXMpOwogIH0KICBbJGZsdXNoSFRNTF0oKSB7CiAgICByZXR1cm4gZmx1c2hIVE1MKHRoaXMpOwogIH0KICBbJGFkZEhUTUxdKGh0bWwsIGJib3gpIHsKICAgIGFkZEhUTUwodGhpcywgaHRtbCwgYmJveCk7CiAgfQogIFskZ2V0QXZhaWxhYmxlU3BhY2VdKCkgewogICAgcmV0dXJuIGdldEF2YWlsYWJsZVNwYWNlKHRoaXMpOwogIH0KICBbJGlzU3BsaXR0YWJsZV0oKSB7CiAgICBjb25zdCBwYXJlbnQgPSB0aGlzWyRnZXRTdWJmb3JtUGFyZW50XSgpOwogICAgaWYgKCFwYXJlbnRbJGlzU3BsaXR0YWJsZV0oKSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpc1skZXh0cmFdLl9pc1NwbGl0dGFibGUgIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gdGhpc1skZXh0cmFdLl9pc1NwbGl0dGFibGU7CiAgICB9CiAgICBpZiAodGhpcy5sYXlvdXQgPT09ICJwb3NpdGlvbiIgfHwgdGhpcy5sYXlvdXQuaW5jbHVkZXMoInJvdyIpKSB7CiAgICAgIHRoaXNbJGV4dHJhXS5faXNTcGxpdHRhYmxlID0gZmFsc2U7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmICh0aGlzLmtlZXAgJiYgdGhpcy5rZWVwLmludGFjdCAhPT0gIm5vbmUiKSB7CiAgICAgIHRoaXNbJGV4dHJhXS5faXNTcGxpdHRhYmxlID0gZmFsc2U7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmIChwYXJlbnQubGF5b3V0Py5lbmRzV2l0aCgiLXRiIikgJiYgcGFyZW50WyRleHRyYV0ubnVtYmVySW5MaW5lICE9PSAwKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHRoaXNbJGV4dHJhXS5faXNTcGxpdHRhYmxlID0gdHJ1ZTsKICAgIHJldHVybiB0cnVlOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIHNldFRhYkluZGV4KHRoaXMpOwogICAgaWYgKHRoaXMuYnJlYWspIHsKICAgICAgaWYgKHRoaXMuYnJlYWsuYWZ0ZXIgIT09ICJhdXRvIiB8fCB0aGlzLmJyZWFrLmFmdGVyVGFyZ2V0ICE9PSAiIikgewogICAgICAgIGNvbnN0IG5vZGUgPSBuZXcgQnJlYWtBZnRlcih7CiAgICAgICAgICB0YXJnZXRUeXBlOiB0aGlzLmJyZWFrLmFmdGVyLAogICAgICAgICAgdGFyZ2V0OiB0aGlzLmJyZWFrLmFmdGVyVGFyZ2V0LAogICAgICAgICAgc3RhcnROZXc6IHRoaXMuYnJlYWsuc3RhcnROZXcudG9TdHJpbmcoKQogICAgICAgIH0pOwogICAgICAgIG5vZGVbJGdsb2JhbERhdGFdID0gdGhpc1skZ2xvYmFsRGF0YV07CiAgICAgICAgdGhpc1skYXBwZW5kQ2hpbGRdKG5vZGUpOwogICAgICAgIHRoaXMuYnJlYWtBZnRlci5wdXNoKG5vZGUpOwogICAgICB9CiAgICAgIGlmICh0aGlzLmJyZWFrLmJlZm9yZSAhPT0gImF1dG8iIHx8IHRoaXMuYnJlYWsuYmVmb3JlVGFyZ2V0ICE9PSAiIikgewogICAgICAgIGNvbnN0IG5vZGUgPSBuZXcgQnJlYWtCZWZvcmUoewogICAgICAgICAgdGFyZ2V0VHlwZTogdGhpcy5icmVhay5iZWZvcmUsCiAgICAgICAgICB0YXJnZXQ6IHRoaXMuYnJlYWsuYmVmb3JlVGFyZ2V0LAogICAgICAgICAgc3RhcnROZXc6IHRoaXMuYnJlYWsuc3RhcnROZXcudG9TdHJpbmcoKQogICAgICAgIH0pOwogICAgICAgIG5vZGVbJGdsb2JhbERhdGFdID0gdGhpc1skZ2xvYmFsRGF0YV07CiAgICAgICAgdGhpc1skYXBwZW5kQ2hpbGRdKG5vZGUpOwogICAgICAgIHRoaXMuYnJlYWtCZWZvcmUucHVzaChub2RlKTsKICAgICAgfQogICAgICBpZiAodGhpcy5icmVhay5vdmVyZmxvd1RhcmdldCAhPT0gIiIpIHsKICAgICAgICBjb25zdCBub2RlID0gbmV3IE92ZXJmbG93KHsKICAgICAgICAgIHRhcmdldDogdGhpcy5icmVhay5vdmVyZmxvd1RhcmdldCwKICAgICAgICAgIGxlYWRlcjogdGhpcy5icmVhay5vdmVyZmxvd0xlYWRlciwKICAgICAgICAgIHRyYWlsZXI6IHRoaXMuYnJlYWsub3ZlcmZsb3dUcmFpbGVyCiAgICAgICAgfSk7CiAgICAgICAgbm9kZVskZ2xvYmFsRGF0YV0gPSB0aGlzWyRnbG9iYWxEYXRhXTsKICAgICAgICB0aGlzWyRhcHBlbmRDaGlsZF0obm9kZSk7CiAgICAgICAgdGhpcy5vdmVyZmxvdy5wdXNoKG5vZGUpOwogICAgICB9CiAgICAgIHRoaXNbJHJlbW92ZUNoaWxkXSh0aGlzLmJyZWFrKTsKICAgICAgdGhpcy5icmVhayA9IG51bGw7CiAgICB9CiAgICBpZiAodGhpcy5wcmVzZW5jZSA9PT0gImhpZGRlbiIgfHwgdGhpcy5wcmVzZW5jZSA9PT0gImluYWN0aXZlIikgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGlmICh0aGlzLmJyZWFrQmVmb3JlLmNoaWxkcmVuLmxlbmd0aCA+IDEgfHwgdGhpcy5icmVha0FmdGVyLmNoaWxkcmVuLmxlbmd0aCA+IDEpIHsKICAgICAgd2FybigiWEZBIC0gU2V2ZXJhbCBicmVha0JlZm9yZSBvciBicmVha0FmdGVyIGluIHN1YmZvcm1zOiBwbGVhc2UgZmlsZSBhIGJ1Zy4iKTsKICAgIH0KICAgIGlmICh0aGlzLmJyZWFrQmVmb3JlLmNoaWxkcmVuLmxlbmd0aCA+PSAxKSB7CiAgICAgIGNvbnN0IGJyZWFrQmVmb3JlID0gdGhpcy5icmVha0JlZm9yZS5jaGlsZHJlblswXTsKICAgICAgaWYgKGhhbmRsZUJyZWFrKGJyZWFrQmVmb3JlKSkgewogICAgICAgIHJldHVybiBIVE1MUmVzdWx0LmJyZWFrTm9kZShicmVha0JlZm9yZSk7CiAgICAgIH0KICAgIH0KICAgIGlmICh0aGlzWyRleHRyYV0/LmFmdGVyQnJlYWtBZnRlcikgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICAgIH0KICAgIGZpeERpbWVuc2lvbnModGhpcyk7CiAgICBjb25zdCBjaGlsZHJlbiA9IFtdOwogICAgY29uc3QgYXR0cmlidXRlcyA9IHsKICAgICAgaWQ6IHRoaXNbJHVpZF0sCiAgICAgIGNsYXNzOiBbXQogICAgfTsKICAgIHNldEFjY2Vzcyh0aGlzLCBhdHRyaWJ1dGVzLmNsYXNzKTsKICAgIHRoaXNbJGV4dHJhXSB8fD0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIE9iamVjdC5hc3NpZ24odGhpc1skZXh0cmFdLCB7CiAgICAgIGNoaWxkcmVuLAogICAgICBsaW5lOiBudWxsLAogICAgICBhdHRyaWJ1dGVzLAogICAgICBhdHRlbXB0OiAwLAogICAgICBudW1iZXJJbkxpbmU6IDAsCiAgICAgIGF2YWlsYWJsZVNwYWNlOiB7CiAgICAgICAgd2lkdGg6IE1hdGgubWluKHRoaXMudyB8fCBJbmZpbml0eSwgYXZhaWxhYmxlU3BhY2Uud2lkdGgpLAogICAgICAgIGhlaWdodDogTWF0aC5taW4odGhpcy5oIHx8IEluZmluaXR5LCBhdmFpbGFibGVTcGFjZS5oZWlnaHQpCiAgICAgIH0sCiAgICAgIHdpZHRoOiAwLAogICAgICBoZWlnaHQ6IDAsCiAgICAgIHByZXZIZWlnaHQ6IDAsCiAgICAgIGN1cnJlbnRXaWR0aDogMAogICAgfSk7CiAgICBjb25zdCByb290ID0gdGhpc1skZ2V0VGVtcGxhdGVSb290XSgpOwogICAgY29uc3Qgc2F2ZWROb0xheW91dEZhaWx1cmUgPSByb290WyRleHRyYV0ubm9MYXlvdXRGYWlsdXJlOwogICAgY29uc3QgaXNTcGxpdHRhYmxlID0gdGhpc1skaXNTcGxpdHRhYmxlXSgpOwogICAgaWYgKCFpc1NwbGl0dGFibGUpIHsKICAgICAgc2V0Rmlyc3RVbnNwbGl0dGFibGUodGhpcyk7CiAgICB9CiAgICBpZiAoIWNoZWNrRGltZW5zaW9ucyh0aGlzLCBhdmFpbGFibGVTcGFjZSkpIHsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuRkFJTFVSRTsKICAgIH0KICAgIGNvbnN0IGZpbHRlciA9IG5ldyBTZXQoWyJhcmVhIiwgImRyYXciLCAiZXhjbEdyb3VwIiwgImZpZWxkIiwgInN1YmZvcm0iLCAic3ViZm9ybVNldCJdKTsKICAgIGlmICh0aGlzLmxheW91dC5pbmNsdWRlcygicm93IikpIHsKICAgICAgY29uc3QgY29sdW1uV2lkdGhzID0gdGhpc1skZ2V0U3ViZm9ybVBhcmVudF0oKS5jb2x1bW5XaWR0aHM7CiAgICAgIGlmIChBcnJheS5pc0FycmF5KGNvbHVtbldpZHRocykgJiYgY29sdW1uV2lkdGhzLmxlbmd0aCA+IDApIHsKICAgICAgICB0aGlzWyRleHRyYV0uY29sdW1uV2lkdGhzID0gY29sdW1uV2lkdGhzOwogICAgICAgIHRoaXNbJGV4dHJhXS5jdXJyZW50Q29sdW1uID0gMDsKICAgICAgfQogICAgfQogICAgY29uc3Qgc3R5bGUgPSB0b1N0eWxlKHRoaXMsICJhbmNob3JUeXBlIiwgImRpbWVuc2lvbnMiLCAicG9zaXRpb24iLCAicHJlc2VuY2UiLCAiYm9yZGVyIiwgIm1hcmdpbiIsICJoQWxpZ24iKTsKICAgIGNvbnN0IGNsYXNzTmFtZXMgPSBbInhmYVN1YmZvcm0iXTsKICAgIGNvbnN0IGNsID0gbGF5b3V0Q2xhc3ModGhpcyk7CiAgICBpZiAoY2wpIHsKICAgICAgY2xhc3NOYW1lcy5wdXNoKGNsKTsKICAgIH0KICAgIGF0dHJpYnV0ZXMuc3R5bGUgPSBzdHlsZTsKICAgIGF0dHJpYnV0ZXMuY2xhc3MgPSBjbGFzc05hbWVzOwogICAgaWYgKHRoaXMubmFtZSkgewogICAgICBhdHRyaWJ1dGVzLnhmYU5hbWUgPSB0aGlzLm5hbWU7CiAgICB9CiAgICBpZiAodGhpcy5vdmVyZmxvdykgewogICAgICBjb25zdCBvdmVyZmxvd0V4dHJhID0gdGhpcy5vdmVyZmxvd1skZ2V0RXh0cmFdKCk7CiAgICAgIGlmIChvdmVyZmxvd0V4dHJhLmFkZExlYWRlcikgewogICAgICAgIG92ZXJmbG93RXh0cmEuYWRkTGVhZGVyID0gZmFsc2U7CiAgICAgICAgaGFuZGxlT3ZlcmZsb3codGhpcywgb3ZlcmZsb3dFeHRyYS5sZWFkZXIsIGF2YWlsYWJsZVNwYWNlKTsKICAgICAgfQogICAgfQogICAgdGhpc1skcHVzaFBhcmFdKCk7CiAgICBjb25zdCBpc0xyVGIgPSB0aGlzLmxheW91dCA9PT0gImxyLXRiIiB8fCB0aGlzLmxheW91dCA9PT0gInJsLXRiIjsKICAgIGNvbnN0IG1heFJ1biA9IGlzTHJUYiA/IE1BWF9BVFRFTVBUU19GT1JfTFJUQl9MQVlPVVQgOiAxOwogICAgZm9yICg7IHRoaXNbJGV4dHJhXS5hdHRlbXB0IDwgbWF4UnVuOyB0aGlzWyRleHRyYV0uYXR0ZW1wdCsrKSB7CiAgICAgIGlmIChpc0xyVGIgJiYgdGhpc1skZXh0cmFdLmF0dGVtcHQgPT09IE1BWF9BVFRFTVBUU19GT1JfTFJUQl9MQVlPVVQgLSAxKSB7CiAgICAgICAgdGhpc1skZXh0cmFdLm51bWJlckluTGluZSA9IDA7CiAgICAgIH0KICAgICAgY29uc3QgcmVzdWx0ID0gdGhpc1skY2hpbGRyZW5Ub0hUTUxdKHsKICAgICAgICBmaWx0ZXIsCiAgICAgICAgaW5jbHVkZTogdHJ1ZQogICAgICB9KTsKICAgICAgaWYgKHJlc3VsdC5zdWNjZXNzKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKHJlc3VsdC5pc0JyZWFrKCkpIHsKICAgICAgICB0aGlzWyRwb3BQYXJhXSgpOwogICAgICAgIHJldHVybiByZXN1bHQ7CiAgICAgIH0KICAgICAgaWYgKGlzTHJUYiAmJiB0aGlzWyRleHRyYV0uYXR0ZW1wdCA9PT0gMCAmJiB0aGlzWyRleHRyYV0ubnVtYmVySW5MaW5lID09PSAwICYmICFyb290WyRleHRyYV0ubm9MYXlvdXRGYWlsdXJlKSB7CiAgICAgICAgdGhpc1skZXh0cmFdLmF0dGVtcHQgPSBtYXhSdW47CiAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIHRoaXNbJHBvcFBhcmFdKCk7CiAgICBpZiAoIWlzU3BsaXR0YWJsZSkgewogICAgICB1bnNldEZpcnN0VW5zcGxpdHRhYmxlKHRoaXMpOwogICAgfQogICAgcm9vdFskZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSA9IHNhdmVkTm9MYXlvdXRGYWlsdXJlOwogICAgaWYgKHRoaXNbJGV4dHJhXS5hdHRlbXB0ID09PSBtYXhSdW4pIHsKICAgICAgaWYgKHRoaXMub3ZlcmZsb3cpIHsKICAgICAgICB0aGlzWyRnZXRUZW1wbGF0ZVJvb3RdKClbJGV4dHJhXS5vdmVyZmxvd05vZGUgPSB0aGlzLm92ZXJmbG93OwogICAgICB9CiAgICAgIGlmICghaXNTcGxpdHRhYmxlKSB7CiAgICAgICAgZGVsZXRlIHRoaXNbJGV4dHJhXTsKICAgICAgfQogICAgICByZXR1cm4gSFRNTFJlc3VsdC5GQUlMVVJFOwogICAgfQogICAgaWYgKHRoaXMub3ZlcmZsb3cpIHsKICAgICAgY29uc3Qgb3ZlcmZsb3dFeHRyYSA9IHRoaXMub3ZlcmZsb3dbJGdldEV4dHJhXSgpOwogICAgICBpZiAob3ZlcmZsb3dFeHRyYS5hZGRUcmFpbGVyKSB7CiAgICAgICAgb3ZlcmZsb3dFeHRyYS5hZGRUcmFpbGVyID0gZmFsc2U7CiAgICAgICAgaGFuZGxlT3ZlcmZsb3codGhpcywgb3ZlcmZsb3dFeHRyYS50cmFpbGVyLCBhdmFpbGFibGVTcGFjZSk7CiAgICAgIH0KICAgIH0KICAgIGxldCBtYXJnaW5IID0gMDsKICAgIGxldCBtYXJnaW5WID0gMDsKICAgIGlmICh0aGlzLm1hcmdpbikgewogICAgICBtYXJnaW5IID0gdGhpcy5tYXJnaW4ubGVmdEluc2V0ICsgdGhpcy5tYXJnaW4ucmlnaHRJbnNldDsKICAgICAgbWFyZ2luViA9IHRoaXMubWFyZ2luLnRvcEluc2V0ICsgdGhpcy5tYXJnaW4uYm90dG9tSW5zZXQ7CiAgICB9CiAgICBjb25zdCB3aWR0aCA9IE1hdGgubWF4KHRoaXNbJGV4dHJhXS53aWR0aCArIG1hcmdpbkgsIHRoaXMudyB8fCAwKTsKICAgIGNvbnN0IGhlaWdodCA9IE1hdGgubWF4KHRoaXNbJGV4dHJhXS5oZWlnaHQgKyBtYXJnaW5WLCB0aGlzLmggfHwgMCk7CiAgICBjb25zdCBiYm94ID0gW3RoaXMueCwgdGhpcy55LCB3aWR0aCwgaGVpZ2h0XTsKICAgIGlmICh0aGlzLncgPT09ICIiKSB7CiAgICAgIHN0eWxlLndpZHRoID0gbWVhc3VyZVRvU3RyaW5nKHdpZHRoKTsKICAgIH0KICAgIGlmICh0aGlzLmggPT09ICIiKSB7CiAgICAgIHN0eWxlLmhlaWdodCA9IG1lYXN1cmVUb1N0cmluZyhoZWlnaHQpOwogICAgfQogICAgaWYgKChzdHlsZS53aWR0aCA9PT0gIjBweCIgfHwgc3R5bGUuaGVpZ2h0ID09PSAiMHB4IikgJiYgY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LkVNUFRZOwogICAgfQogICAgY29uc3QgaHRtbCA9IHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGF0dHJpYnV0ZXMsCiAgICAgIGNoaWxkcmVuCiAgICB9OwogICAgYXBwbHlBc3Npc3QodGhpcywgYXR0cmlidXRlcyk7CiAgICBjb25zdCByZXN1bHQgPSBIVE1MUmVzdWx0LnN1Y2Nlc3MoY3JlYXRlV3JhcHBlcih0aGlzLCBodG1sKSwgYmJveCk7CiAgICBpZiAodGhpcy5icmVha0FmdGVyLmNoaWxkcmVuLmxlbmd0aCA+PSAxKSB7CiAgICAgIGNvbnN0IGJyZWFrQWZ0ZXIgPSB0aGlzLmJyZWFrQWZ0ZXIuY2hpbGRyZW5bMF07CiAgICAgIGlmIChoYW5kbGVCcmVhayhicmVha0FmdGVyKSkgewogICAgICAgIHRoaXNbJGV4dHJhXS5hZnRlckJyZWFrQWZ0ZXIgPSByZXN1bHQ7CiAgICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuYnJlYWtOb2RlKGJyZWFrQWZ0ZXIpOwogICAgICB9CiAgICB9CiAgICBkZWxldGUgdGhpc1skZXh0cmFdOwogICAgcmV0dXJuIHJlc3VsdDsKICB9Cn0KY2xhc3MgU3ViZm9ybVNldCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzdWJmb3JtU2V0IiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMucmVsYXRpb24gPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5yZWxhdGlvbiwgWyJvcmRlcmVkIiwgImNob2ljZSIsICJ1bm9yZGVyZWQiXSk7CiAgICB0aGlzLnJlbGV2YW50ID0gZ2V0UmVsZXZhbnQoYXR0cmlidXRlcy5yZWxldmFudCk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5ib29rZW5kID0gbnVsbDsKICAgIHRoaXMuYnJlYWsgPSBudWxsOwogICAgdGhpcy5kZXNjID0gbnVsbDsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMub2NjdXIgPSBudWxsOwogICAgdGhpcy5vdmVyZmxvdyA9IG51bGw7CiAgICB0aGlzLmJyZWFrQWZ0ZXIgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuYnJlYWtCZWZvcmUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc3ViZm9ybSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zdWJmb3JtU2V0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQogICpbJGdldENvbnRhaW5lZENoaWxkcmVuXSgpIHsKICAgIHlpZWxkKiBnZXRDb250YWluZWRDaGlsZHJlbih0aGlzKTsKICB9CiAgWyRnZXRTdWJmb3JtUGFyZW50XSgpIHsKICAgIGxldCBwYXJlbnQgPSB0aGlzWyRnZXRQYXJlbnRdKCk7CiAgICB3aGlsZSAoIShwYXJlbnQgaW5zdGFuY2VvZiBTdWJmb3JtKSkgewogICAgICBwYXJlbnQgPSBwYXJlbnRbJGdldFBhcmVudF0oKTsKICAgIH0KICAgIHJldHVybiBwYXJlbnQ7CiAgfQogIFskaXNCaW5kYWJsZV0oKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KY2xhc3MgU3ViamVjdEROIGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJzdWJqZWN0RE4iKTsKICAgIHRoaXMuZGVsaW1pdGVyID0gYXR0cmlidXRlcy5kZWxpbWl0ZXIgfHwgIiwiOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIHRoaXNbJGNvbnRlbnRdID0gbmV3IE1hcCh0aGlzWyRjb250ZW50XS5zcGxpdCh0aGlzLmRlbGltaXRlcikubWFwKGt2ID0+IHsKICAgICAga3YgPSBrdi5zcGxpdCgiPSIsIDIpOwogICAgICBrdlswXSA9IGt2WzBdLnRyaW0oKTsKICAgICAgcmV0dXJuIGt2OwogICAgfSkpOwogIH0KfQpjbGFzcyBTdWJqZWN0RE5zIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInN1YmplY3RETnMiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50eXBlID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMudHlwZSwgWyJvcHRpb25hbCIsICJyZXF1aXJlZCJdKTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnN1YmplY3RETiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBTdWJtaXQgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAic3VibWl0IiwgdHJ1ZSk7CiAgICB0aGlzLmVtYmVkUERGID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuZW1iZWRQREYsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLmZvcm1hdCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmZvcm1hdCwgWyJ4ZHAiLCAiZm9ybWRhdGEiLCAicGRmIiwgInVybGVuY29kZWQiLCAieGZkIiwgInhtbCJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy50YXJnZXQgPSBhdHRyaWJ1dGVzLnRhcmdldCB8fCAiIjsKICAgIHRoaXMudGV4dEVuY29kaW5nID0gZ2V0S2V5d29yZCh7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMudGV4dEVuY29kaW5nID8gYXR0cmlidXRlcy50ZXh0RW5jb2RpbmcudG9Mb3dlckNhc2UoKSA6ICIiLAogICAgICBkZWZhdWx0VmFsdWU6ICIiLAogICAgICB2YWxpZGF0ZTogayA9PiBbInV0Zi04IiwgImJpZy1maXZlIiwgImZvbnRzcGVjaWZpYyIsICJnYmsiLCAiZ2ItMTgwMzAiLCAiZ2ItMjMxMiIsICJrc2MtNTYwMSIsICJub25lIiwgInNoaWZ0LWppcyIsICJ1Y3MtMiIsICJ1dGYtMTYiXS5pbmNsdWRlcyhrKSB8fCBrLm1hdGNoKC9pc28tODg1OS1cZHsyfS8pCiAgICB9KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLnhkcENvbnRlbnQgPSBhdHRyaWJ1dGVzLnhkcENvbnRlbnQgfHwgIiI7CiAgICB0aGlzLmVuY3J5cHQgPSBudWxsOwogICAgdGhpcy5lbmNyeXB0RGF0YSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5zaWduRGF0YSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBUZW1wbGF0ZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ0ZW1wbGF0ZSIsIHRydWUpOwogICAgdGhpcy5iYXNlUHJvZmlsZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmJhc2VQcm9maWxlLCBbImZ1bGwiLCAiaW50ZXJhY3RpdmVGb3JtcyJdKTsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMuc3ViZm9ybSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIGlmICh0aGlzLnN1YmZvcm0uY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7CiAgICAgIHdhcm4oIlhGQSAtIE5vIHN1YmZvcm1zIGluIHRlbXBsYXRlIG5vZGUuIik7CiAgICB9CiAgICBpZiAodGhpcy5zdWJmb3JtLmNoaWxkcmVuLmxlbmd0aCA+PSAyKSB7CiAgICAgIHdhcm4oIlhGQSAtIFNldmVyYWwgc3ViZm9ybXMgaW4gdGVtcGxhdGUgbm9kZTogcGxlYXNlIGZpbGUgYSBidWcuIik7CiAgICB9CiAgICB0aGlzWyR0YWJJbmRleF0gPSBERUZBVUxUX1RBQl9JTkRFWDsKICB9CiAgWyRpc1NwbGl0dGFibGVdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIFskc2VhcmNoTm9kZV0oZXhwciwgY29udGFpbmVyKSB7CiAgICBpZiAoZXhwci5zdGFydHNXaXRoKCIjIikpIHsKICAgICAgcmV0dXJuIFt0aGlzWyRpZHNdLmdldChleHByLnNsaWNlKDEpKV07CiAgICB9CiAgICByZXR1cm4gc2VhcmNoTm9kZSh0aGlzLCBjb250YWluZXIsIGV4cHIsIHRydWUsIHRydWUpOwogIH0KICAqWyR0b1BhZ2VzXSgpIHsKICAgIGlmICghdGhpcy5zdWJmb3JtLmNoaWxkcmVuLmxlbmd0aCkgewogICAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgICBuYW1lOiAiZGl2IiwKICAgICAgICBjaGlsZHJlbjogW10KICAgICAgfSk7CiAgICB9CiAgICB0aGlzWyRleHRyYV0gPSB7CiAgICAgIG92ZXJmbG93Tm9kZTogbnVsbCwKICAgICAgZmlyc3RVbnNwbGl0dGFibGU6IG51bGwsCiAgICAgIGN1cnJlbnRDb250ZW50QXJlYTogbnVsbCwKICAgICAgY3VycmVudFBhZ2VBcmVhOiBudWxsLAogICAgICBub0xheW91dEZhaWx1cmU6IGZhbHNlLAogICAgICBwYWdlTnVtYmVyOiAxLAogICAgICBwYWdlUG9zaXRpb246ICJmaXJzdCIsCiAgICAgIG9kZE9yRXZlbjogIm9kZCIsCiAgICAgIGJsYW5rT3JOb3RCbGFuazogIm5vbkJsYW5rIiwKICAgICAgcGFyYVN0YWNrOiBbXQogICAgfTsKICAgIGNvbnN0IHJvb3QgPSB0aGlzLnN1YmZvcm0uY2hpbGRyZW5bMF07CiAgICByb290LnBhZ2VTZXRbJGNsZWFuUGFnZV0oKTsKICAgIGNvbnN0IHBhZ2VBcmVhcyA9IHJvb3QucGFnZVNldC5wYWdlQXJlYS5jaGlsZHJlbjsKICAgIGNvbnN0IG1haW5IdG1sID0gewogICAgICBuYW1lOiAiZGl2IiwKICAgICAgY2hpbGRyZW46IFtdCiAgICB9OwogICAgbGV0IHBhZ2VBcmVhID0gbnVsbDsKICAgIGxldCBicmVha0JlZm9yZSA9IG51bGw7CiAgICBsZXQgYnJlYWtCZWZvcmVUYXJnZXQgPSBudWxsOwogICAgaWYgKHJvb3QuYnJlYWtCZWZvcmUuY2hpbGRyZW4ubGVuZ3RoID49IDEpIHsKICAgICAgYnJlYWtCZWZvcmUgPSByb290LmJyZWFrQmVmb3JlLmNoaWxkcmVuWzBdOwogICAgICBicmVha0JlZm9yZVRhcmdldCA9IGJyZWFrQmVmb3JlLnRhcmdldDsKICAgIH0gZWxzZSBpZiAocm9vdC5zdWJmb3JtLmNoaWxkcmVuLmxlbmd0aCA+PSAxICYmIHJvb3Quc3ViZm9ybS5jaGlsZHJlblswXS5icmVha0JlZm9yZS5jaGlsZHJlbi5sZW5ndGggPj0gMSkgewogICAgICBicmVha0JlZm9yZSA9IHJvb3Quc3ViZm9ybS5jaGlsZHJlblswXS5icmVha0JlZm9yZS5jaGlsZHJlblswXTsKICAgICAgYnJlYWtCZWZvcmVUYXJnZXQgPSBicmVha0JlZm9yZS50YXJnZXQ7CiAgICB9IGVsc2UgaWYgKHJvb3QuYnJlYWs/LmJlZm9yZVRhcmdldCkgewogICAgICBicmVha0JlZm9yZSA9IHJvb3QuYnJlYWs7CiAgICAgIGJyZWFrQmVmb3JlVGFyZ2V0ID0gYnJlYWtCZWZvcmUuYmVmb3JlVGFyZ2V0OwogICAgfSBlbHNlIGlmIChyb290LnN1YmZvcm0uY2hpbGRyZW4ubGVuZ3RoID49IDEgJiYgcm9vdC5zdWJmb3JtLmNoaWxkcmVuWzBdLmJyZWFrPy5iZWZvcmVUYXJnZXQpIHsKICAgICAgYnJlYWtCZWZvcmUgPSByb290LnN1YmZvcm0uY2hpbGRyZW5bMF0uYnJlYWs7CiAgICAgIGJyZWFrQmVmb3JlVGFyZ2V0ID0gYnJlYWtCZWZvcmUuYmVmb3JlVGFyZ2V0OwogICAgfQogICAgaWYgKGJyZWFrQmVmb3JlKSB7CiAgICAgIGNvbnN0IHRhcmdldCA9IHRoaXNbJHNlYXJjaE5vZGVdKGJyZWFrQmVmb3JlVGFyZ2V0LCBicmVha0JlZm9yZVskZ2V0UGFyZW50XSgpKTsKICAgICAgaWYgKHRhcmdldCBpbnN0YW5jZW9mIFBhZ2VBcmVhKSB7CiAgICAgICAgcGFnZUFyZWEgPSB0YXJnZXQ7CiAgICAgICAgYnJlYWtCZWZvcmVbJGV4dHJhXSA9IHt9OwogICAgICB9CiAgICB9CiAgICBwYWdlQXJlYSB8fD0gcGFnZUFyZWFzWzBdOwogICAgcGFnZUFyZWFbJGV4dHJhXSA9IHsKICAgICAgbnVtYmVyT2ZVc2U6IDEKICAgIH07CiAgICBjb25zdCBwYWdlQXJlYVBhcmVudCA9IHBhZ2VBcmVhWyRnZXRQYXJlbnRdKCk7CiAgICBwYWdlQXJlYVBhcmVudFskZXh0cmFdID0gewogICAgICBudW1iZXJPZlVzZTogMSwKICAgICAgcGFnZUluZGV4OiBwYWdlQXJlYVBhcmVudC5wYWdlQXJlYS5jaGlsZHJlbi5pbmRleE9mKHBhZ2VBcmVhKSwKICAgICAgcGFnZVNldEluZGV4OiAwCiAgICB9OwogICAgbGV0IHRhcmdldFBhZ2VBcmVhOwogICAgbGV0IGxlYWRlciA9IG51bGw7CiAgICBsZXQgdHJhaWxlciA9IG51bGw7CiAgICBsZXQgaGFzU29tZXRoaW5nID0gdHJ1ZTsKICAgIGxldCBoYXNTb21ldGhpbmdDb3VudGVyID0gMDsKICAgIGxldCBzdGFydEluZGV4ID0gMDsKICAgIHdoaWxlICh0cnVlKSB7CiAgICAgIGlmICghaGFzU29tZXRoaW5nKSB7CiAgICAgICAgbWFpbkh0bWwuY2hpbGRyZW4ucG9wKCk7CiAgICAgICAgaWYgKCsraGFzU29tZXRoaW5nQ291bnRlciA9PT0gTUFYX0VNUFRZX1BBR0VTKSB7CiAgICAgICAgICB3YXJuKCJYRkEgLSBTb21ldGhpbmcgZ29lcyB3cm9uZzogcGxlYXNlIGZpbGUgYSBidWcuIik7CiAgICAgICAgICByZXR1cm4gbWFpbkh0bWw7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGhhc1NvbWV0aGluZ0NvdW50ZXIgPSAwOwogICAgICB9CiAgICAgIHRhcmdldFBhZ2VBcmVhID0gbnVsbDsKICAgICAgdGhpc1skZXh0cmFdLmN1cnJlbnRQYWdlQXJlYSA9IHBhZ2VBcmVhOwogICAgICBjb25zdCBwYWdlID0gcGFnZUFyZWFbJHRvSFRNTF0oKS5odG1sOwogICAgICBtYWluSHRtbC5jaGlsZHJlbi5wdXNoKHBhZ2UpOwogICAgICBpZiAobGVhZGVyKSB7CiAgICAgICAgdGhpc1skZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSA9IHRydWU7CiAgICAgICAgcGFnZS5jaGlsZHJlbi5wdXNoKGxlYWRlclskdG9IVE1MXShwYWdlQXJlYVskZXh0cmFdLnNwYWNlKS5odG1sKTsKICAgICAgICBsZWFkZXIgPSBudWxsOwogICAgICB9CiAgICAgIGlmICh0cmFpbGVyKSB7CiAgICAgICAgdGhpc1skZXh0cmFdLm5vTGF5b3V0RmFpbHVyZSA9IHRydWU7CiAgICAgICAgcGFnZS5jaGlsZHJlbi5wdXNoKHRyYWlsZXJbJHRvSFRNTF0ocGFnZUFyZWFbJGV4dHJhXS5zcGFjZSkuaHRtbCk7CiAgICAgICAgdHJhaWxlciA9IG51bGw7CiAgICAgIH0KICAgICAgY29uc3QgY29udGVudEFyZWFzID0gcGFnZUFyZWEuY29udGVudEFyZWEuY2hpbGRyZW47CiAgICAgIGNvbnN0IGh0bWxDb250ZW50QXJlYXMgPSBwYWdlLmNoaWxkcmVuLmZpbHRlcihub2RlID0+IG5vZGUuYXR0cmlidXRlcy5jbGFzcy5pbmNsdWRlcygieGZhQ29udGVudGFyZWEiKSk7CiAgICAgIGhhc1NvbWV0aGluZyA9IGZhbHNlOwogICAgICB0aGlzWyRleHRyYV0uZmlyc3RVbnNwbGl0dGFibGUgPSBudWxsOwogICAgICB0aGlzWyRleHRyYV0ubm9MYXlvdXRGYWlsdXJlID0gZmFsc2U7CiAgICAgIGNvbnN0IGZsdXNoID0gaW5kZXggPT4gewogICAgICAgIGNvbnN0IGh0bWwgPSByb290WyRmbHVzaEhUTUxdKCk7CiAgICAgICAgaWYgKGh0bWwpIHsKICAgICAgICAgIGhhc1NvbWV0aGluZyB8fD0gaHRtbC5jaGlsZHJlbj8ubGVuZ3RoID4gMDsKICAgICAgICAgIGh0bWxDb250ZW50QXJlYXNbaW5kZXhdLmNoaWxkcmVuLnB1c2goaHRtbCk7CiAgICAgICAgfQogICAgICB9OwogICAgICBmb3IgKGxldCBpID0gc3RhcnRJbmRleCwgaWkgPSBjb250ZW50QXJlYXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbnN0IGNvbnRlbnRBcmVhID0gdGhpc1skZXh0cmFdLmN1cnJlbnRDb250ZW50QXJlYSA9IGNvbnRlbnRBcmVhc1tpXTsKICAgICAgICBjb25zdCBzcGFjZSA9IHsKICAgICAgICAgIHdpZHRoOiBjb250ZW50QXJlYS53LAogICAgICAgICAgaGVpZ2h0OiBjb250ZW50QXJlYS5oCiAgICAgICAgfTsKICAgICAgICBzdGFydEluZGV4ID0gMDsKICAgICAgICBpZiAobGVhZGVyKSB7CiAgICAgICAgICBodG1sQ29udGVudEFyZWFzW2ldLmNoaWxkcmVuLnB1c2gobGVhZGVyWyR0b0hUTUxdKHNwYWNlKS5odG1sKTsKICAgICAgICAgIGxlYWRlciA9IG51bGw7CiAgICAgICAgfQogICAgICAgIGlmICh0cmFpbGVyKSB7CiAgICAgICAgICBodG1sQ29udGVudEFyZWFzW2ldLmNoaWxkcmVuLnB1c2godHJhaWxlclskdG9IVE1MXShzcGFjZSkuaHRtbCk7CiAgICAgICAgICB0cmFpbGVyID0gbnVsbDsKICAgICAgICB9CiAgICAgICAgY29uc3QgaHRtbCA9IHJvb3RbJHRvSFRNTF0oc3BhY2UpOwogICAgICAgIGlmIChodG1sLnN1Y2Nlc3MpIHsKICAgICAgICAgIGlmIChodG1sLmh0bWwpIHsKICAgICAgICAgICAgaGFzU29tZXRoaW5nIHx8PSBodG1sLmh0bWwuY2hpbGRyZW4/Lmxlbmd0aCA+IDA7CiAgICAgICAgICAgIGh0bWxDb250ZW50QXJlYXNbaV0uY2hpbGRyZW4ucHVzaChodG1sLmh0bWwpOwogICAgICAgICAgfSBlbHNlIGlmICghaGFzU29tZXRoaW5nICYmIG1haW5IdG1sLmNoaWxkcmVuLmxlbmd0aCA+IDEpIHsKICAgICAgICAgICAgbWFpbkh0bWwuY2hpbGRyZW4ucG9wKCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gbWFpbkh0bWw7CiAgICAgICAgfQogICAgICAgIGlmIChodG1sLmlzQnJlYWsoKSkgewogICAgICAgICAgY29uc3Qgbm9kZSA9IGh0bWwuYnJlYWtOb2RlOwogICAgICAgICAgZmx1c2goaSk7CiAgICAgICAgICBpZiAobm9kZS50YXJnZXRUeXBlID09PSAiYXV0byIpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAobm9kZS5sZWFkZXIpIHsKICAgICAgICAgICAgbGVhZGVyID0gdGhpc1skc2VhcmNoTm9kZV0obm9kZS5sZWFkZXIsIG5vZGVbJGdldFBhcmVudF0oKSk7CiAgICAgICAgICAgIGxlYWRlciA9IGxlYWRlciA/IGxlYWRlclswXSA6IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAobm9kZS50cmFpbGVyKSB7CiAgICAgICAgICAgIHRyYWlsZXIgPSB0aGlzWyRzZWFyY2hOb2RlXShub2RlLnRyYWlsZXIsIG5vZGVbJGdldFBhcmVudF0oKSk7CiAgICAgICAgICAgIHRyYWlsZXIgPSB0cmFpbGVyID8gdHJhaWxlclswXSA6IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAobm9kZS50YXJnZXRUeXBlID09PSAicGFnZUFyZWEiKSB7CiAgICAgICAgICAgIHRhcmdldFBhZ2VBcmVhID0gbm9kZVskZXh0cmFdLnRhcmdldDsKICAgICAgICAgICAgaSA9IEluZmluaXR5OwogICAgICAgICAgfSBlbHNlIGlmICghbm9kZVskZXh0cmFdLnRhcmdldCkgewogICAgICAgICAgICBpID0gbm9kZVskZXh0cmFdLmluZGV4OwogICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgdGFyZ2V0UGFnZUFyZWEgPSBub2RlWyRleHRyYV0udGFyZ2V0OwogICAgICAgICAgICBzdGFydEluZGV4ID0gbm9kZVskZXh0cmFdLmluZGV4ICsgMTsKICAgICAgICAgICAgaSA9IEluZmluaXR5OwogICAgICAgICAgfQogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmICh0aGlzWyRleHRyYV0ub3ZlcmZsb3dOb2RlKSB7CiAgICAgICAgICBjb25zdCBub2RlID0gdGhpc1skZXh0cmFdLm92ZXJmbG93Tm9kZTsKICAgICAgICAgIHRoaXNbJGV4dHJhXS5vdmVyZmxvd05vZGUgPSBudWxsOwogICAgICAgICAgY29uc3Qgb3ZlcmZsb3dFeHRyYSA9IG5vZGVbJGdldEV4dHJhXSgpOwogICAgICAgICAgY29uc3QgdGFyZ2V0ID0gb3ZlcmZsb3dFeHRyYS50YXJnZXQ7CiAgICAgICAgICBvdmVyZmxvd0V4dHJhLmFkZExlYWRlciA9IG92ZXJmbG93RXh0cmEubGVhZGVyICE9PSBudWxsOwogICAgICAgICAgb3ZlcmZsb3dFeHRyYS5hZGRUcmFpbGVyID0gb3ZlcmZsb3dFeHRyYS50cmFpbGVyICE9PSBudWxsOwogICAgICAgICAgZmx1c2goaSk7CiAgICAgICAgICBjb25zdCBjdXJyZW50SW5kZXggPSBpOwogICAgICAgICAgaSA9IEluZmluaXR5OwogICAgICAgICAgaWYgKHRhcmdldCBpbnN0YW5jZW9mIFBhZ2VBcmVhKSB7CiAgICAgICAgICAgIHRhcmdldFBhZ2VBcmVhID0gdGFyZ2V0OwogICAgICAgICAgfSBlbHNlIGlmICh0YXJnZXQgaW5zdGFuY2VvZiBDb250ZW50QXJlYSkgewogICAgICAgICAgICBjb25zdCBpbmRleCA9IGNvbnRlbnRBcmVhcy5pbmRleE9mKHRhcmdldCk7CiAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHsKICAgICAgICAgICAgICBpZiAoaW5kZXggPiBjdXJyZW50SW5kZXgpIHsKICAgICAgICAgICAgICAgIGkgPSBpbmRleCAtIDE7CiAgICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHN0YXJ0SW5kZXggPSBpbmRleDsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgdGFyZ2V0UGFnZUFyZWEgPSB0YXJnZXRbJGdldFBhcmVudF0oKTsKICAgICAgICAgICAgICBzdGFydEluZGV4ID0gdGFyZ2V0UGFnZUFyZWEuY29udGVudEFyZWEuY2hpbGRyZW4uaW5kZXhPZih0YXJnZXQpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgZmx1c2goaSk7CiAgICAgIH0KICAgICAgdGhpc1skZXh0cmFdLnBhZ2VOdW1iZXIgKz0gMTsKICAgICAgaWYgKHRhcmdldFBhZ2VBcmVhKSB7CiAgICAgICAgaWYgKHRhcmdldFBhZ2VBcmVhWyRpc1VzYWJsZV0oKSkgewogICAgICAgICAgdGFyZ2V0UGFnZUFyZWFbJGV4dHJhXS5udW1iZXJPZlVzZSArPSAxOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0YXJnZXRQYWdlQXJlYSA9IG51bGw7CiAgICAgICAgfQogICAgICB9CiAgICAgIHBhZ2VBcmVhID0gdGFyZ2V0UGFnZUFyZWEgfHwgcGFnZUFyZWFbJGdldE5leHRQYWdlXSgpOwogICAgICB5aWVsZCBudWxsOwogICAgfQogIH0KfQpjbGFzcyBUZXh0IGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ0ZXh0Iik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubWF4Q2hhcnMgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5tYXhDaGFycywKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID49IDAKICAgIH0pOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5yaWQgPSBhdHRyaWJ1dGVzLnJpZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQogIFskYWNjZXB0V2hpdGVzcGFjZV0oKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9CiAgWyRvbkNoaWxkXShjaGlsZCkgewogICAgaWYgKGNoaWxkWyRuYW1lc3BhY2VJZF0gPT09IE5hbWVzcGFjZUlkcy54aHRtbC5pZCkgewogICAgICB0aGlzWyRjb250ZW50XSA9IGNoaWxkOwogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHdhcm4oYFhGQSAtIEludmFsaWQgY29udGVudCBpbiBUZXh0OiAke2NoaWxkWyRub2RlTmFtZV19LmApOwogICAgcmV0dXJuIGZhbHNlOwogIH0KICBbJG9uVGV4dF0oc3RyKSB7CiAgICBpZiAodGhpc1skY29udGVudF0gaW5zdGFuY2VvZiBYRkFPYmplY3QpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgc3VwZXJbJG9uVGV4dF0oc3RyKTsKICB9CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICBpZiAodHlwZW9mIHRoaXNbJGNvbnRlbnRdID09PSAic3RyaW5nIikgewogICAgICB0aGlzWyRjb250ZW50XSA9IHRoaXNbJGNvbnRlbnRdLnJlcGxhY2VBbGwoIlxyXG4iLCAiXG4iKTsKICAgIH0KICB9CiAgWyRnZXRFeHRyYV0oKSB7CiAgICBpZiAodHlwZW9mIHRoaXNbJGNvbnRlbnRdID09PSAic3RyaW5nIikgewogICAgICByZXR1cm4gdGhpc1skY29udGVudF0uc3BsaXQoL1tcdTIwMjlcdTIwMjhcbl0vKS5maWx0ZXIobGluZSA9PiAhIWxpbmUpLmpvaW4oIlxuIik7CiAgICB9CiAgICByZXR1cm4gdGhpc1skY29udGVudF1bJHRleHRdKCk7CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgaWYgKHR5cGVvZiB0aGlzWyRjb250ZW50XSA9PT0gInN0cmluZyIpIHsKICAgICAgY29uc3QgaHRtbCA9IHZhbHVlVG9IdG1sKHRoaXNbJGNvbnRlbnRdKS5odG1sOwogICAgICBpZiAodGhpc1skY29udGVudF0uaW5jbHVkZXMoIlx1MjAyOSIpKSB7CiAgICAgICAgaHRtbC5uYW1lID0gImRpdiI7CiAgICAgICAgaHRtbC5jaGlsZHJlbiA9IFtdOwogICAgICAgIHRoaXNbJGNvbnRlbnRdLnNwbGl0KCJcdTIwMjkiKS5tYXAocGFyYSA9PiBwYXJhLnNwbGl0KC9bXHUyMDI4XG5dLykuZmxhdE1hcChsaW5lID0+IFt7CiAgICAgICAgICBuYW1lOiAic3BhbiIsCiAgICAgICAgICB2YWx1ZTogbGluZQogICAgICAgIH0sIHsKICAgICAgICAgIG5hbWU6ICJiciIKICAgICAgICB9XSkpLmZvckVhY2gobGluZXMgPT4gewogICAgICAgICAgaHRtbC5jaGlsZHJlbi5wdXNoKHsKICAgICAgICAgICAgbmFtZTogInAiLAogICAgICAgICAgICBjaGlsZHJlbjogbGluZXMKICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICB9IGVsc2UgaWYgKC9bXHUyMDI4XG5dLy50ZXN0KHRoaXNbJGNvbnRlbnRdKSkgewogICAgICAgIGh0bWwubmFtZSA9ICJkaXYiOwogICAgICAgIGh0bWwuY2hpbGRyZW4gPSBbXTsKICAgICAgICB0aGlzWyRjb250ZW50XS5zcGxpdCgvW1x1MjAyOFxuXS8pLmZvckVhY2gobGluZSA9PiB7CiAgICAgICAgICBodG1sLmNoaWxkcmVuLnB1c2goewogICAgICAgICAgICBuYW1lOiAic3BhbiIsCiAgICAgICAgICAgIHZhbHVlOiBsaW5lCiAgICAgICAgICB9LCB7CiAgICAgICAgICAgIG5hbWU6ICJiciIKICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICB9CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoaHRtbCk7CiAgICB9CiAgICByZXR1cm4gdGhpc1skY29udGVudF1bJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpOwogIH0KfQpjbGFzcyBUZXh0RWRpdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ0ZXh0RWRpdCIsIHRydWUpOwogICAgdGhpcy5hbGxvd1JpY2hUZXh0ID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuYWxsb3dSaWNoVGV4dCwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMuaFNjcm9sbFBvbGljeSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmhTY3JvbGxQb2xpY3ksIFsiYXV0byIsICJvZmYiLCAib24iXSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubXVsdGlMaW5lID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMubXVsdGlMaW5lLAogICAgICBkZWZhdWx0VmFsdWU6ICIiLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAwIHx8IHggPT09IDEKICAgIH0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMudlNjcm9sbFBvbGljeSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnZTY3JvbGxQb2xpY3ksIFsiYXV0byIsICJvZmYiLCAib24iXSk7CiAgICB0aGlzLmJvcmRlciA9IG51bGw7CiAgICB0aGlzLmNvbWIgPSBudWxsOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tYXJnaW4gPSBudWxsOwogIH0KICBbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpIHsKICAgIGNvbnN0IHN0eWxlID0gdG9TdHlsZSh0aGlzLCAiYm9yZGVyIiwgImZvbnQiLCAibWFyZ2luIik7CiAgICBsZXQgaHRtbDsKICAgIGNvbnN0IGZpZWxkID0gdGhpc1skZ2V0UGFyZW50XSgpWyRnZXRQYXJlbnRdKCk7CiAgICBpZiAodGhpcy5tdWx0aUxpbmUgPT09ICIiKSB7CiAgICAgIHRoaXMubXVsdGlMaW5lID0gZmllbGQgaW5zdGFuY2VvZiBEcmF3ID8gMSA6IDA7CiAgICB9CiAgICBpZiAodGhpcy5tdWx0aUxpbmUgPT09IDEpIHsKICAgICAgaHRtbCA9IHsKICAgICAgICBuYW1lOiAidGV4dGFyZWEiLAogICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgIGRhdGFJZDogZmllbGRbJGRhdGFdPy5bJHVpZF0gfHwgZmllbGRbJHVpZF0sCiAgICAgICAgICBmaWVsZElkOiBmaWVsZFskdWlkXSwKICAgICAgICAgIGNsYXNzOiBbInhmYVRleHRmaWVsZCJdLAogICAgICAgICAgc3R5bGUsCiAgICAgICAgICAiYXJpYS1sYWJlbCI6IGFyaWFMYWJlbChmaWVsZCksCiAgICAgICAgICAiYXJpYS1yZXF1aXJlZCI6IGZhbHNlCiAgICAgICAgfQogICAgICB9OwogICAgfSBlbHNlIHsKICAgICAgaHRtbCA9IHsKICAgICAgICBuYW1lOiAiaW5wdXQiLAogICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgIHR5cGU6ICJ0ZXh0IiwKICAgICAgICAgIGRhdGFJZDogZmllbGRbJGRhdGFdPy5bJHVpZF0gfHwgZmllbGRbJHVpZF0sCiAgICAgICAgICBmaWVsZElkOiBmaWVsZFskdWlkXSwKICAgICAgICAgIGNsYXNzOiBbInhmYVRleHRmaWVsZCJdLAogICAgICAgICAgc3R5bGUsCiAgICAgICAgICAiYXJpYS1sYWJlbCI6IGFyaWFMYWJlbChmaWVsZCksCiAgICAgICAgICAiYXJpYS1yZXF1aXJlZCI6IGZhbHNlCiAgICAgICAgfQogICAgICB9OwogICAgfQogICAgaWYgKGlzUmVxdWlyZWQoZmllbGQpKSB7CiAgICAgIGh0bWwuYXR0cmlidXRlc1siYXJpYS1yZXF1aXJlZCJdID0gdHJ1ZTsKICAgICAgaHRtbC5hdHRyaWJ1dGVzLnJlcXVpcmVkID0gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICBuYW1lOiAibGFiZWwiLAogICAgICBhdHRyaWJ1dGVzOiB7CiAgICAgICAgY2xhc3M6IFsieGZhTGFiZWwiXQogICAgICB9LAogICAgICBjaGlsZHJlbjogW2h0bWxdCiAgICB9KTsKICB9Cn0KY2xhc3MgVGltZSBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ0aW1lIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgY29uc3QgZGF0ZSA9IHRoaXNbJGNvbnRlbnRdLnRyaW0oKTsKICAgIHRoaXNbJGNvbnRlbnRdID0gZGF0ZSA/IG5ldyBEYXRlKGRhdGUpIDogbnVsbDsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICByZXR1cm4gdmFsdWVUb0h0bWwodGhpc1skY29udGVudF0gPyB0aGlzWyRjb250ZW50XS50b1N0cmluZygpIDogIiIpOwogIH0KfQpjbGFzcyBUaW1lU3RhbXAgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAidGltZVN0YW1wIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMuc2VydmVyID0gYXR0cmlidXRlcy5zZXJ2ZXIgfHwgIiI7CiAgICB0aGlzLnR5cGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy50eXBlLCBbIm9wdGlvbmFsIiwgInJlcXVpcmVkIl0pOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgVG9vbFRpcCBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ0b29sVGlwIik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMucmlkID0gYXR0cmlidXRlcy5yaWQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBUcmF2ZXJzYWwgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAidHJhdmVyc2FsIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLnRyYXZlcnNlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIFRyYXZlcnNlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInRyYXZlcnNlIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMub3BlcmF0aW9uID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMub3BlcmF0aW9uLCBbIm5leHQiLCAiYmFjayIsICJkb3duIiwgImZpcnN0IiwgImxlZnQiLCAicmlnaHQiLCAidXAiXSk7CiAgICB0aGlzLnJlZiA9IGF0dHJpYnV0ZXMucmVmIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuZXh0cmFzID0gbnVsbDsKICAgIHRoaXMuc2NyaXB0ID0gbnVsbDsKICB9CiAgZ2V0IG5hbWUoKSB7CiAgICByZXR1cm4gdGhpcy5vcGVyYXRpb247CiAgfQogIFskaXNUcmFuc3BhcmVudF0oKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQp9CmNsYXNzIFVpIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInVpIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmV4dHJhcyA9IG51bGw7CiAgICB0aGlzLnBpY3R1cmUgPSBudWxsOwogICAgdGhpcy5iYXJjb2RlID0gbnVsbDsKICAgIHRoaXMuYnV0dG9uID0gbnVsbDsKICAgIHRoaXMuY2hlY2tCdXR0b24gPSBudWxsOwogICAgdGhpcy5jaG9pY2VMaXN0ID0gbnVsbDsKICAgIHRoaXMuZGF0ZVRpbWVFZGl0ID0gbnVsbDsKICAgIHRoaXMuZGVmYXVsdFVpID0gbnVsbDsKICAgIHRoaXMuaW1hZ2VFZGl0ID0gbnVsbDsKICAgIHRoaXMubnVtZXJpY0VkaXQgPSBudWxsOwogICAgdGhpcy5wYXNzd29yZEVkaXQgPSBudWxsOwogICAgdGhpcy5zaWduYXR1cmUgPSBudWxsOwogICAgdGhpcy50ZXh0RWRpdCA9IG51bGw7CiAgfQogIFskZ2V0RXh0cmFdKCkgewogICAgaWYgKHRoaXNbJGV4dHJhXSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKSkgewogICAgICAgIGlmIChuYW1lID09PSAiZXh0cmFzIiB8fCBuYW1lID09PSAicGljdHVyZSIpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBvYmogPSB0aGlzW25hbWVdOwogICAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIFhGQU9iamVjdCkpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICB0aGlzWyRleHRyYV0gPSBvYmo7CiAgICAgICAgcmV0dXJuIG9iajsKICAgICAgfQogICAgICB0aGlzWyRleHRyYV0gPSBudWxsOwogICAgfQogICAgcmV0dXJuIHRoaXNbJGV4dHJhXTsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBjb25zdCBvYmogPSB0aGlzWyRnZXRFeHRyYV0oKTsKICAgIGlmIChvYmopIHsKICAgICAgcmV0dXJuIG9ialskdG9IVE1MXShhdmFpbGFibGVTcGFjZSk7CiAgICB9CiAgICByZXR1cm4gSFRNTFJlc3VsdC5FTVBUWTsKICB9Cn0KY2xhc3MgVmFsaWRhdGUgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFRFTVBMQVRFX05TX0lELCAidmFsaWRhdGUiLCB0cnVlKTsKICAgIHRoaXMuZm9ybWF0VGVzdCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLmZvcm1hdFRlc3QsIFsid2FybmluZyIsICJkaXNhYmxlZCIsICJlcnJvciJdKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5udWxsVGVzdCA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLm51bGxUZXN0LCBbImRpc2FibGVkIiwgImVycm9yIiwgIndhcm5pbmciXSk7CiAgICB0aGlzLnNjcmlwdFRlc3QgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5zY3JpcHRUZXN0LCBbImVycm9yIiwgImRpc2FibGVkIiwgIndhcm5pbmciXSk7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogICAgdGhpcy5leHRyYXMgPSBudWxsOwogICAgdGhpcy5tZXNzYWdlID0gbnVsbDsKICAgIHRoaXMucGljdHVyZSA9IG51bGw7CiAgICB0aGlzLnNjcmlwdCA9IG51bGw7CiAgfQp9CmNsYXNzIFZhbHVlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihURU1QTEFURV9OU19JRCwgInZhbHVlIiwgdHJ1ZSk7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMub3ZlcnJpZGUgPSBnZXRJbnRlZ2VyKHsKICAgICAgZGF0YTogYXR0cmlidXRlcy5vdmVycmlkZSwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMucmVsZXZhbnQgPSBnZXRSZWxldmFudChhdHRyaWJ1dGVzLnJlbGV2YW50KTsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgICB0aGlzLmFyYyA9IG51bGw7CiAgICB0aGlzLmJvb2xlYW4gPSBudWxsOwogICAgdGhpcy5kYXRlID0gbnVsbDsKICAgIHRoaXMuZGF0ZVRpbWUgPSBudWxsOwogICAgdGhpcy5kZWNpbWFsID0gbnVsbDsKICAgIHRoaXMuZXhEYXRhID0gbnVsbDsKICAgIHRoaXMuZmxvYXQgPSBudWxsOwogICAgdGhpcy5pbWFnZSA9IG51bGw7CiAgICB0aGlzLmludGVnZXIgPSBudWxsOwogICAgdGhpcy5saW5lID0gbnVsbDsKICAgIHRoaXMucmVjdGFuZ2xlID0gbnVsbDsKICAgIHRoaXMudGV4dCA9IG51bGw7CiAgICB0aGlzLnRpbWUgPSBudWxsOwogIH0KICBbJHNldFZhbHVlXSh2YWx1ZSkgewogICAgY29uc3QgcGFyZW50ID0gdGhpc1skZ2V0UGFyZW50XSgpOwogICAgaWYgKHBhcmVudCBpbnN0YW5jZW9mIEZpZWxkKSB7CiAgICAgIGlmIChwYXJlbnQudWk/LmltYWdlRWRpdCkgewogICAgICAgIGlmICghdGhpcy5pbWFnZSkgewogICAgICAgICAgdGhpcy5pbWFnZSA9IG5ldyBJbWFnZSh7fSk7CiAgICAgICAgICB0aGlzWyRhcHBlbmRDaGlsZF0odGhpcy5pbWFnZSk7CiAgICAgICAgfQogICAgICAgIHRoaXMuaW1hZ2VbJGNvbnRlbnRdID0gdmFsdWVbJGNvbnRlbnRdOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgfQogICAgY29uc3QgdmFsdWVOYW1lID0gdmFsdWVbJG5vZGVOYW1lXTsKICAgIGlmICh0aGlzW3ZhbHVlTmFtZV0gIT09IG51bGwpIHsKICAgICAgdGhpc1t2YWx1ZU5hbWVdWyRjb250ZW50XSA9IHZhbHVlWyRjb250ZW50XTsKICAgICAgcmV0dXJuOwogICAgfQogICAgZm9yIChjb25zdCBuYW1lIG9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHRoaXMpKSB7CiAgICAgIGNvbnN0IG9iaiA9IHRoaXNbbmFtZV07CiAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBYRkFPYmplY3QpIHsKICAgICAgICB0aGlzW25hbWVdID0gbnVsbDsKICAgICAgICB0aGlzWyRyZW1vdmVDaGlsZF0ob2JqKTsKICAgICAgfQogICAgfQogICAgdGhpc1t2YWx1ZVskbm9kZU5hbWVdXSA9IHZhbHVlOwogICAgdGhpc1skYXBwZW5kQ2hpbGRdKHZhbHVlKTsKICB9CiAgWyR0ZXh0XSgpIHsKICAgIGlmICh0aGlzLmV4RGF0YSkgewogICAgICBpZiAodHlwZW9mIHRoaXMuZXhEYXRhWyRjb250ZW50XSA9PT0gInN0cmluZyIpIHsKICAgICAgICByZXR1cm4gdGhpcy5leERhdGFbJGNvbnRlbnRdLnRyaW0oKTsKICAgICAgfQogICAgICByZXR1cm4gdGhpcy5leERhdGFbJGNvbnRlbnRdWyR0ZXh0XSgpLnRyaW0oKTsKICAgIH0KICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh0aGlzKSkgewogICAgICBpZiAobmFtZSA9PT0gImltYWdlIikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IG9iaiA9IHRoaXNbbmFtZV07CiAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBYRkFPYmplY3QpIHsKICAgICAgICByZXR1cm4gKG9ialskY29udGVudF0gfHwgIiIpLnRvU3RyaW5nKCkudHJpbSgpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModGhpcykpIHsKICAgICAgY29uc3Qgb2JqID0gdGhpc1tuYW1lXTsKICAgICAgaWYgKCEob2JqIGluc3RhbmNlb2YgWEZBT2JqZWN0KSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHJldHVybiBvYmpbJHRvSFRNTF0oYXZhaWxhYmxlU3BhY2UpOwogICAgfQogICAgcmV0dXJuIEhUTUxSZXN1bHQuRU1QVFk7CiAgfQp9CmNsYXNzIFZhcmlhYmxlcyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoVEVNUExBVEVfTlNfSUQsICJ2YXJpYWJsZXMiLCB0cnVlKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICAgIHRoaXMuYm9vbGVhbiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kYXRlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRhdGVUaW1lID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmRlY2ltYWwgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuZXhEYXRhID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmZsb2F0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmltYWdlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmludGVnZXIgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubWFuaWZlc3QgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuc2NyaXB0ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRleHQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMudGltZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KICBbJGlzVHJhbnNwYXJlbnRdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQp9CmNsYXNzIFRlbXBsYXRlTmFtZXNwYWNlIHsKICBzdGF0aWMgWyRidWlsZFhGQU9iamVjdF0obmFtZSwgYXR0cmlidXRlcykgewogICAgaWYgKFRlbXBsYXRlTmFtZXNwYWNlLmhhc093blByb3BlcnR5KG5hbWUpKSB7CiAgICAgIGNvbnN0IG5vZGUgPSBUZW1wbGF0ZU5hbWVzcGFjZVtuYW1lXShhdHRyaWJ1dGVzKTsKICAgICAgbm9kZVskc2V0U2V0QXR0cmlidXRlc10oYXR0cmlidXRlcyk7CiAgICAgIHJldHVybiBub2RlOwogICAgfQogICAgcmV0dXJuIHVuZGVmaW5lZDsKICB9CiAgc3RhdGljIGFwcGVhcmFuY2VGaWx0ZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQXBwZWFyYW5jZUZpbHRlcihhdHRycyk7CiAgfQogIHN0YXRpYyBhcmMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQXJjKGF0dHJzKTsKICB9CiAgc3RhdGljIGFyZWEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQXJlYShhdHRycyk7CiAgfQogIHN0YXRpYyBhc3Npc3QoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQXNzaXN0KGF0dHJzKTsKICB9CiAgc3RhdGljIGJhcmNvZGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQmFyY29kZShhdHRycyk7CiAgfQogIHN0YXRpYyBiaW5kKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJpbmQoYXR0cnMpOwogIH0KICBzdGF0aWMgYmluZEl0ZW1zKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJpbmRJdGVtcyhhdHRycyk7CiAgfQogIHN0YXRpYyBib29rZW5kKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJvb2tlbmQoYXR0cnMpOwogIH0KICBzdGF0aWMgYm9vbGVhbihhdHRycykgewogICAgcmV0dXJuIG5ldyBCb29sZWFuRWxlbWVudChhdHRycyk7CiAgfQogIHN0YXRpYyBib3JkZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQm9yZGVyKGF0dHJzKTsKICB9CiAgc3RhdGljIGJyZWFrKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJyZWFrKGF0dHJzKTsKICB9CiAgc3RhdGljIGJyZWFrQWZ0ZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQnJlYWtBZnRlcihhdHRycyk7CiAgfQogIHN0YXRpYyBicmVha0JlZm9yZShhdHRycykgewogICAgcmV0dXJuIG5ldyBCcmVha0JlZm9yZShhdHRycyk7CiAgfQogIHN0YXRpYyBidXR0b24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQnV0dG9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGNhbGN1bGF0ZShhdHRycykgewogICAgcmV0dXJuIG5ldyBDYWxjdWxhdGUoYXR0cnMpOwogIH0KICBzdGF0aWMgY2FwdGlvbihhdHRycykgewogICAgcmV0dXJuIG5ldyBDYXB0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGNlcnRpZmljYXRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENlcnRpZmljYXRlKGF0dHJzKTsKICB9CiAgc3RhdGljIGNlcnRpZmljYXRlcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBDZXJ0aWZpY2F0ZXMoYXR0cnMpOwogIH0KICBzdGF0aWMgY2hlY2tCdXR0b24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ2hlY2tCdXR0b24oYXR0cnMpOwogIH0KICBzdGF0aWMgY2hvaWNlTGlzdChhdHRycykgewogICAgcmV0dXJuIG5ldyBDaG9pY2VMaXN0KGF0dHJzKTsKICB9CiAgc3RhdGljIGNvbG9yKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbG9yKGF0dHJzKTsKICB9CiAgc3RhdGljIGNvbWIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29tYihhdHRycyk7CiAgfQogIHN0YXRpYyBjb25uZWN0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbm5lY3QoYXR0cnMpOwogIH0KICBzdGF0aWMgY29udGVudEFyZWEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29udGVudEFyZWEoYXR0cnMpOwogIH0KICBzdGF0aWMgY29ybmVyKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvcm5lcihhdHRycyk7CiAgfQogIHN0YXRpYyBkYXRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERhdGVFbGVtZW50KGF0dHJzKTsKICB9CiAgc3RhdGljIGRhdGVUaW1lKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERhdGVUaW1lKGF0dHJzKTsKICB9CiAgc3RhdGljIGRhdGVUaW1lRWRpdChhdHRycykgewogICAgcmV0dXJuIG5ldyBEYXRlVGltZUVkaXQoYXR0cnMpOwogIH0KICBzdGF0aWMgZGVjaW1hbChhdHRycykgewogICAgcmV0dXJuIG5ldyBEZWNpbWFsKGF0dHJzKTsKICB9CiAgc3RhdGljIGRlZmF1bHRVaShhdHRycykgewogICAgcmV0dXJuIG5ldyBEZWZhdWx0VWkoYXR0cnMpOwogIH0KICBzdGF0aWMgZGVzYyhhdHRycykgewogICAgcmV0dXJuIG5ldyBEZXNjKGF0dHJzKTsKICB9CiAgc3RhdGljIGRpZ2VzdE1ldGhvZChhdHRycykgewogICAgcmV0dXJuIG5ldyBEaWdlc3RNZXRob2QoYXR0cnMpOwogIH0KICBzdGF0aWMgZGlnZXN0TWV0aG9kcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBEaWdlc3RNZXRob2RzKGF0dHJzKTsKICB9CiAgc3RhdGljIGRyYXcoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRHJhdyhhdHRycyk7CiAgfQogIHN0YXRpYyBlZGdlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVkZ2UoYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jb2RpbmcoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRW5jb2RpbmcoYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jb2RpbmdzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVuY29kaW5ncyhhdHRycyk7CiAgfQogIHN0YXRpYyBlbmNyeXB0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVuY3J5cHQoYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jcnlwdERhdGEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRW5jcnlwdERhdGEoYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jcnlwdGlvbihhdHRycykgewogICAgcmV0dXJuIG5ldyBFbmNyeXB0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGVuY3J5cHRpb25NZXRob2QoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRW5jcnlwdGlvbk1ldGhvZChhdHRycyk7CiAgfQogIHN0YXRpYyBlbmNyeXB0aW9uTWV0aG9kcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBFbmNyeXB0aW9uTWV0aG9kcyhhdHRycyk7CiAgfQogIHN0YXRpYyBldmVudChhdHRycykgewogICAgcmV0dXJuIG5ldyBFdmVudChhdHRycyk7CiAgfQogIHN0YXRpYyBleERhdGEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRXhEYXRhKGF0dHJzKTsKICB9CiAgc3RhdGljIGV4T2JqZWN0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEV4T2JqZWN0KGF0dHJzKTsKICB9CiAgc3RhdGljIGV4Y2xHcm91cChhdHRycykgewogICAgcmV0dXJuIG5ldyBFeGNsR3JvdXAoYXR0cnMpOwogIH0KICBzdGF0aWMgZXhlY3V0ZShhdHRycykgewogICAgcmV0dXJuIG5ldyBFeGVjdXRlKGF0dHJzKTsKICB9CiAgc3RhdGljIGV4dHJhcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBFeHRyYXMoYXR0cnMpOwogIH0KICBzdGF0aWMgZmllbGQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRmllbGQoYXR0cnMpOwogIH0KICBzdGF0aWMgZmlsbChhdHRycykgewogICAgcmV0dXJuIG5ldyBGaWxsKGF0dHJzKTsKICB9CiAgc3RhdGljIGZpbHRlcihhdHRycykgewogICAgcmV0dXJuIG5ldyBGaWx0ZXIoYXR0cnMpOwogIH0KICBzdGF0aWMgZmxvYXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRmxvYXQoYXR0cnMpOwogIH0KICBzdGF0aWMgZm9udChhdHRycykgewogICAgcmV0dXJuIG5ldyB0ZW1wbGF0ZV9Gb250KGF0dHJzKTsKICB9CiAgc3RhdGljIGZvcm1hdChhdHRycykgewogICAgcmV0dXJuIG5ldyBGb3JtYXQoYXR0cnMpOwogIH0KICBzdGF0aWMgaGFuZGxlcihhdHRycykgewogICAgcmV0dXJuIG5ldyBIYW5kbGVyKGF0dHJzKTsKICB9CiAgc3RhdGljIGh5cGhlbmF0aW9uKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEh5cGhlbmF0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGltYWdlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEltYWdlKGF0dHJzKTsKICB9CiAgc3RhdGljIGltYWdlRWRpdChhdHRycykgewogICAgcmV0dXJuIG5ldyBJbWFnZUVkaXQoYXR0cnMpOwogIH0KICBzdGF0aWMgaW50ZWdlcihhdHRycykgewogICAgcmV0dXJuIG5ldyBJbnRlZ2VyKGF0dHJzKTsKICB9CiAgc3RhdGljIGlzc3VlcnMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgSXNzdWVycyhhdHRycyk7CiAgfQogIHN0YXRpYyBpdGVtcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBJdGVtcyhhdHRycyk7CiAgfQogIHN0YXRpYyBrZWVwKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEtlZXAoYXR0cnMpOwogIH0KICBzdGF0aWMga2V5VXNhZ2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgS2V5VXNhZ2UoYXR0cnMpOwogIH0KICBzdGF0aWMgbGluZShhdHRycykgewogICAgcmV0dXJuIG5ldyBMaW5lKGF0dHJzKTsKICB9CiAgc3RhdGljIGxpbmVhcihhdHRycykgewogICAgcmV0dXJuIG5ldyBMaW5lYXIoYXR0cnMpOwogIH0KICBzdGF0aWMgbG9ja0RvY3VtZW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IExvY2tEb2N1bWVudChhdHRycyk7CiAgfQogIHN0YXRpYyBtYW5pZmVzdChhdHRycykgewogICAgcmV0dXJuIG5ldyBNYW5pZmVzdChhdHRycyk7CiAgfQogIHN0YXRpYyBtYXJnaW4oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTWFyZ2luKGF0dHJzKTsKICB9CiAgc3RhdGljIG1kcChhdHRycykgewogICAgcmV0dXJuIG5ldyBNZHAoYXR0cnMpOwogIH0KICBzdGF0aWMgbWVkaXVtKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE1lZGl1bShhdHRycyk7CiAgfQogIHN0YXRpYyBtZXNzYWdlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE1lc3NhZ2UoYXR0cnMpOwogIH0KICBzdGF0aWMgbnVtZXJpY0VkaXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTnVtZXJpY0VkaXQoYXR0cnMpOwogIH0KICBzdGF0aWMgb2NjdXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgT2NjdXIoYXR0cnMpOwogIH0KICBzdGF0aWMgb2lkKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE9pZChhdHRycyk7CiAgfQogIHN0YXRpYyBvaWRzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE9pZHMoYXR0cnMpOwogIH0KICBzdGF0aWMgb3ZlcmZsb3coYXR0cnMpIHsKICAgIHJldHVybiBuZXcgT3ZlcmZsb3coYXR0cnMpOwogIH0KICBzdGF0aWMgcGFnZUFyZWEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGFnZUFyZWEoYXR0cnMpOwogIH0KICBzdGF0aWMgcGFnZVNldChhdHRycykgewogICAgcmV0dXJuIG5ldyBQYWdlU2V0KGF0dHJzKTsKICB9CiAgc3RhdGljIHBhcmEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGFyYShhdHRycyk7CiAgfQogIHN0YXRpYyBwYXNzd29yZEVkaXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGFzc3dvcmRFZGl0KGF0dHJzKTsKICB9CiAgc3RhdGljIHBhdHRlcm4oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgdGVtcGxhdGVfUGF0dGVybihhdHRycyk7CiAgfQogIHN0YXRpYyBwaWN0dXJlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBpY3R1cmUoYXR0cnMpOwogIH0KICBzdGF0aWMgcHJvdG8oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUHJvdG8oYXR0cnMpOwogIH0KICBzdGF0aWMgcmFkaWFsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFJhZGlhbChhdHRycyk7CiAgfQogIHN0YXRpYyByZWFzb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmVhc29uKGF0dHJzKTsKICB9CiAgc3RhdGljIHJlYXNvbnMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmVhc29ucyhhdHRycyk7CiAgfQogIHN0YXRpYyByZWN0YW5nbGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmVjdGFuZ2xlKGF0dHJzKTsKICB9CiAgc3RhdGljIHJlZihhdHRycykgewogICAgcmV0dXJuIG5ldyBSZWZFbGVtZW50KGF0dHJzKTsKICB9CiAgc3RhdGljIHNjcmlwdChhdHRycykgewogICAgcmV0dXJuIG5ldyBTY3JpcHQoYXR0cnMpOwogIH0KICBzdGF0aWMgc2V0UHJvcGVydHkoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU2V0UHJvcGVydHkoYXR0cnMpOwogIH0KICBzdGF0aWMgc2lnbkRhdGEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU2lnbkRhdGEoYXR0cnMpOwogIH0KICBzdGF0aWMgc2lnbmF0dXJlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNpZ25hdHVyZShhdHRycyk7CiAgfQogIHN0YXRpYyBzaWduaW5nKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNpZ25pbmcoYXR0cnMpOwogIH0KICBzdGF0aWMgc29saWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU29saWQoYXR0cnMpOwogIH0KICBzdGF0aWMgc3BlYWsoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU3BlYWsoYXR0cnMpOwogIH0KICBzdGF0aWMgc3RpcHBsZShhdHRycykgewogICAgcmV0dXJuIG5ldyBTdGlwcGxlKGF0dHJzKTsKICB9CiAgc3RhdGljIHN1YmZvcm0oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU3ViZm9ybShhdHRycyk7CiAgfQogIHN0YXRpYyBzdWJmb3JtU2V0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1YmZvcm1TZXQoYXR0cnMpOwogIH0KICBzdGF0aWMgc3ViamVjdEROKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1YmplY3RETihhdHRycyk7CiAgfQogIHN0YXRpYyBzdWJqZWN0RE5zKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1YmplY3RETnMoYXR0cnMpOwogIH0KICBzdGF0aWMgc3VibWl0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1Ym1pdChhdHRycyk7CiAgfQogIHN0YXRpYyB0ZW1wbGF0ZShhdHRycykgewogICAgcmV0dXJuIG5ldyBUZW1wbGF0ZShhdHRycyk7CiAgfQogIHN0YXRpYyB0ZXh0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFRleHQoYXR0cnMpOwogIH0KICBzdGF0aWMgdGV4dEVkaXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVGV4dEVkaXQoYXR0cnMpOwogIH0KICBzdGF0aWMgdGltZShhdHRycykgewogICAgcmV0dXJuIG5ldyBUaW1lKGF0dHJzKTsKICB9CiAgc3RhdGljIHRpbWVTdGFtcChhdHRycykgewogICAgcmV0dXJuIG5ldyBUaW1lU3RhbXAoYXR0cnMpOwogIH0KICBzdGF0aWMgdG9vbFRpcChhdHRycykgewogICAgcmV0dXJuIG5ldyBUb29sVGlwKGF0dHJzKTsKICB9CiAgc3RhdGljIHRyYXZlcnNhbChhdHRycykgewogICAgcmV0dXJuIG5ldyBUcmF2ZXJzYWwoYXR0cnMpOwogIH0KICBzdGF0aWMgdHJhdmVyc2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVHJhdmVyc2UoYXR0cnMpOwogIH0KICBzdGF0aWMgdWkoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVWkoYXR0cnMpOwogIH0KICBzdGF0aWMgdmFsaWRhdGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVmFsaWRhdGUoYXR0cnMpOwogIH0KICBzdGF0aWMgdmFsdWUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVmFsdWUoYXR0cnMpOwogIH0KICBzdGF0aWMgdmFyaWFibGVzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFZhcmlhYmxlcyhhdHRycyk7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEvYmluZC5qcwoKCgoKCgoKCgoKCmNvbnN0IGJpbmRfTlNfREFUQVNFVFMgPSBOYW1lc3BhY2VJZHMuZGF0YXNldHMuaWQ7CmZ1bmN0aW9uIGNyZWF0ZVRleHQoY29udGVudCkgewogIGNvbnN0IG5vZGUgPSBuZXcgVGV4dCh7fSk7CiAgbm9kZVskY29udGVudF0gPSBjb250ZW50OwogIHJldHVybiBub2RlOwp9CmNsYXNzIEJpbmRlciB7CiAgY29uc3RydWN0b3Iocm9vdCkgewogICAgdGhpcy5yb290ID0gcm9vdDsKICAgIHRoaXMuZGF0YXNldHMgPSByb290LmRhdGFzZXRzOwogICAgdGhpcy5kYXRhID0gcm9vdC5kYXRhc2V0cz8uZGF0YSB8fCBuZXcgWG1sT2JqZWN0KE5hbWVzcGFjZUlkcy5kYXRhc2V0cy5pZCwgImRhdGEiKTsKICAgIHRoaXMuZW1wdHlNZXJnZSA9IHRoaXMuZGF0YVskZ2V0Q2hpbGRyZW5dKCkubGVuZ3RoID09PSAwOwogICAgdGhpcy5yb290LmZvcm0gPSB0aGlzLmZvcm0gPSByb290LnRlbXBsYXRlWyRjbG9uZV0oKTsKICB9CiAgX2lzQ29uc3VtZURhdGEoKSB7CiAgICByZXR1cm4gIXRoaXMuZW1wdHlNZXJnZSAmJiB0aGlzLl9tZXJnZU1vZGU7CiAgfQogIF9pc01hdGNoVGVtcGxhdGUoKSB7CiAgICByZXR1cm4gIXRoaXMuX2lzQ29uc3VtZURhdGEoKTsKICB9CiAgYmluZCgpIHsKICAgIHRoaXMuX2JpbmRFbGVtZW50KHRoaXMuZm9ybSwgdGhpcy5kYXRhKTsKICAgIHJldHVybiB0aGlzLmZvcm07CiAgfQogIGdldERhdGEoKSB7CiAgICByZXR1cm4gdGhpcy5kYXRhOwogIH0KICBfYmluZFZhbHVlKGZvcm1Ob2RlLCBkYXRhLCBwaWN0dXJlKSB7CiAgICBmb3JtTm9kZVskZGF0YV0gPSBkYXRhOwogICAgaWYgKGZvcm1Ob2RlWyRoYXNTZXR0YWJsZVZhbHVlXSgpKSB7CiAgICAgIGlmIChkYXRhWyRpc0RhdGFWYWx1ZV0oKSkgewogICAgICAgIGNvbnN0IHZhbHVlID0gZGF0YVskZ2V0RGF0YVZhbHVlXSgpOwogICAgICAgIGZvcm1Ob2RlWyRzZXRWYWx1ZV0oY3JlYXRlVGV4dCh2YWx1ZSkpOwogICAgICB9IGVsc2UgaWYgKGZvcm1Ob2RlIGluc3RhbmNlb2YgRmllbGQgJiYgZm9ybU5vZGUudWk/LmNob2ljZUxpc3Q/Lm9wZW4gPT09ICJtdWx0aVNlbGVjdCIpIHsKICAgICAgICBjb25zdCB2YWx1ZSA9IGRhdGFbJGdldENoaWxkcmVuXSgpLm1hcChjaGlsZCA9PiBjaGlsZFskY29udGVudF0udHJpbSgpKS5qb2luKCJcbiIpOwogICAgICAgIGZvcm1Ob2RlWyRzZXRWYWx1ZV0oY3JlYXRlVGV4dCh2YWx1ZSkpOwogICAgICB9IGVsc2UgaWYgKHRoaXMuX2lzQ29uc3VtZURhdGEoKSkgewogICAgICAgIHdhcm4oYFhGQSAtIE5vZGVzIGhhdmVuJ3QgdGhlIHNhbWUgdHlwZS5gKTsKICAgICAgfQogICAgfSBlbHNlIGlmICghZGF0YVskaXNEYXRhVmFsdWVdKCkgfHwgdGhpcy5faXNNYXRjaFRlbXBsYXRlKCkpIHsKICAgICAgdGhpcy5fYmluZEVsZW1lbnQoZm9ybU5vZGUsIGRhdGEpOwogICAgfSBlbHNlIHsKICAgICAgd2FybihgWEZBIC0gTm9kZXMgaGF2ZW4ndCB0aGUgc2FtZSB0eXBlLmApOwogICAgfQogIH0KICBfZmluZERhdGFCeU5hbWVUb0NvbnN1bWUobmFtZSwgaXNWYWx1ZSwgZGF0YU5vZGUsIGdsb2JhbCkgewogICAgaWYgKCFuYW1lKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgbGV0IGdlbmVyYXRvciwgbWF0Y2g7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDM7IGkrKykgewogICAgICBnZW5lcmF0b3IgPSBkYXRhTm9kZVskZ2V0UmVhbENoaWxkcmVuQnlOYW1lSXRdKG5hbWUsIGZhbHNlLCB0cnVlKTsKICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICBtYXRjaCA9IGdlbmVyYXRvci5uZXh0KCkudmFsdWU7CiAgICAgICAgaWYgKCFtYXRjaCkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmIChpc1ZhbHVlID09PSBtYXRjaFskaXNEYXRhVmFsdWVdKCkpIHsKICAgICAgICAgIHJldHVybiBtYXRjaDsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGRhdGFOb2RlWyRuYW1lc3BhY2VJZF0gPT09IE5hbWVzcGFjZUlkcy5kYXRhc2V0cy5pZCAmJiBkYXRhTm9kZVskbm9kZU5hbWVdID09PSAiZGF0YSIpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBkYXRhTm9kZSA9IGRhdGFOb2RlWyRnZXRQYXJlbnRdKCk7CiAgICB9CiAgICBpZiAoIWdsb2JhbCkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGdlbmVyYXRvciA9IHRoaXMuZGF0YVskZ2V0UmVhbENoaWxkcmVuQnlOYW1lSXRdKG5hbWUsIHRydWUsIGZhbHNlKTsKICAgIG1hdGNoID0gZ2VuZXJhdG9yLm5leHQoKS52YWx1ZTsKICAgIGlmIChtYXRjaCkgewogICAgICByZXR1cm4gbWF0Y2g7CiAgICB9CiAgICBnZW5lcmF0b3IgPSB0aGlzLmRhdGFbJGdldEF0dHJpYnV0ZUl0XShuYW1lLCB0cnVlKTsKICAgIG1hdGNoID0gZ2VuZXJhdG9yLm5leHQoKS52YWx1ZTsKICAgIGlmIChtYXRjaD8uWyRpc0RhdGFWYWx1ZV0oKSkgewogICAgICByZXR1cm4gbWF0Y2g7CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgX3NldFByb3BlcnRpZXMoZm9ybU5vZGUsIGRhdGFOb2RlKSB7CiAgICBpZiAoIWZvcm1Ob2RlLmhhc093blByb3BlcnR5KCJzZXRQcm9wZXJ0eSIpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGZvciAoY29uc3QgewogICAgICByZWYsCiAgICAgIHRhcmdldCwKICAgICAgY29ubmVjdGlvbgogICAgfSBvZiBmb3JtTm9kZS5zZXRQcm9wZXJ0eS5jaGlsZHJlbikgewogICAgICBpZiAoY29ubmVjdGlvbikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICghcmVmKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3Qgbm9kZXMgPSBzZWFyY2hOb2RlKHRoaXMucm9vdCwgZGF0YU5vZGUsIHJlZiwgZmFsc2UsIGZhbHNlKTsKICAgICAgaWYgKCFub2RlcykgewogICAgICAgIHdhcm4oYFhGQSAtIEludmFsaWQgcmVmZXJlbmNlOiAke3JlZn0uYCk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgW25vZGVdID0gbm9kZXM7CiAgICAgIGlmICghbm9kZVskaXNEZXNjZW5kZW50XSh0aGlzLmRhdGEpKSB7CiAgICAgICAgd2FybihgWEZBIC0gSW52YWxpZCBub2RlOiBtdXN0IGJlIGEgZGF0YSBub2RlLmApOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IHRhcmdldE5vZGVzID0gc2VhcmNoTm9kZSh0aGlzLnJvb3QsIGZvcm1Ob2RlLCB0YXJnZXQsIGZhbHNlLCBmYWxzZSk7CiAgICAgIGlmICghdGFyZ2V0Tm9kZXMpIHsKICAgICAgICB3YXJuKGBYRkEgLSBJbnZhbGlkIHRhcmdldDogJHt0YXJnZXR9LmApOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IFt0YXJnZXROb2RlXSA9IHRhcmdldE5vZGVzOwogICAgICBpZiAoIXRhcmdldE5vZGVbJGlzRGVzY2VuZGVudF0oZm9ybU5vZGUpKSB7CiAgICAgICAgd2FybihgWEZBIC0gSW52YWxpZCB0YXJnZXQ6IG11c3QgYmUgYSBwcm9wZXJ0eSBvciBzdWJwcm9wZXJ0eS5gKTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB0YXJnZXRQYXJlbnQgPSB0YXJnZXROb2RlWyRnZXRQYXJlbnRdKCk7CiAgICAgIGlmICh0YXJnZXROb2RlIGluc3RhbmNlb2YgU2V0UHJvcGVydHkgfHwgdGFyZ2V0UGFyZW50IGluc3RhbmNlb2YgU2V0UHJvcGVydHkpIHsKICAgICAgICB3YXJuKGBYRkEgLSBJbnZhbGlkIHRhcmdldDogY2Fubm90IGJlIGEgc2V0UHJvcGVydHkgb3Igb25lIG9mIGl0cyBwcm9wZXJ0aWVzLmApOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICh0YXJnZXROb2RlIGluc3RhbmNlb2YgQmluZEl0ZW1zIHx8IHRhcmdldFBhcmVudCBpbnN0YW5jZW9mIEJpbmRJdGVtcykgewogICAgICAgIHdhcm4oYFhGQSAtIEludmFsaWQgdGFyZ2V0OiBjYW5ub3QgYmUgYSBiaW5kSXRlbXMgb3Igb25lIG9mIGl0cyBwcm9wZXJ0aWVzLmApOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGNvbnRlbnQgPSBub2RlWyR0ZXh0XSgpOwogICAgICBjb25zdCBuYW1lID0gdGFyZ2V0Tm9kZVskbm9kZU5hbWVdOwogICAgICBpZiAodGFyZ2V0Tm9kZSBpbnN0YW5jZW9mIFhGQUF0dHJpYnV0ZSkgewogICAgICAgIGNvbnN0IGF0dHJzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICBhdHRyc1tuYW1lXSA9IGNvbnRlbnQ7CiAgICAgICAgY29uc3Qgb2JqID0gUmVmbGVjdC5jb25zdHJ1Y3QoT2JqZWN0LmdldFByb3RvdHlwZU9mKHRhcmdldFBhcmVudCkuY29uc3RydWN0b3IsIFthdHRyc10pOwogICAgICAgIHRhcmdldFBhcmVudFtuYW1lXSA9IG9ialtuYW1lXTsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoIXRhcmdldE5vZGUuaGFzT3duUHJvcGVydHkoJGNvbnRlbnQpKSB7CiAgICAgICAgd2FybihgWEZBIC0gSW52YWxpZCBub2RlIHRvIHVzZSBpbiBzZXRQcm9wZXJ0eWApOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHRhcmdldE5vZGVbJGRhdGFdID0gbm9kZTsKICAgICAgdGFyZ2V0Tm9kZVskY29udGVudF0gPSBjb250ZW50OwogICAgICB0YXJnZXROb2RlWyRmaW5hbGl6ZV0oKTsKICAgIH0KICB9CiAgX2JpbmRJdGVtcyhmb3JtTm9kZSwgZGF0YU5vZGUpIHsKICAgIGlmICghZm9ybU5vZGUuaGFzT3duUHJvcGVydHkoIml0ZW1zIikgfHwgIWZvcm1Ob2RlLmhhc093blByb3BlcnR5KCJiaW5kSXRlbXMiKSB8fCBmb3JtTm9kZS5iaW5kSXRlbXMuaXNFbXB0eSgpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGZvciAoY29uc3QgaXRlbSBvZiBmb3JtTm9kZS5pdGVtcy5jaGlsZHJlbikgewogICAgICBmb3JtTm9kZVskcmVtb3ZlQ2hpbGRdKGl0ZW0pOwogICAgfQogICAgZm9ybU5vZGUuaXRlbXMuY2xlYXIoKTsKICAgIGNvbnN0IGxhYmVscyA9IG5ldyBJdGVtcyh7fSk7CiAgICBjb25zdCB2YWx1ZXMgPSBuZXcgSXRlbXMoe30pOwogICAgZm9ybU5vZGVbJGFwcGVuZENoaWxkXShsYWJlbHMpOwogICAgZm9ybU5vZGUuaXRlbXMucHVzaChsYWJlbHMpOwogICAgZm9ybU5vZGVbJGFwcGVuZENoaWxkXSh2YWx1ZXMpOwogICAgZm9ybU5vZGUuaXRlbXMucHVzaCh2YWx1ZXMpOwogICAgZm9yIChjb25zdCB7CiAgICAgIHJlZiwKICAgICAgbGFiZWxSZWYsCiAgICAgIHZhbHVlUmVmLAogICAgICBjb25uZWN0aW9uCiAgICB9IG9mIGZvcm1Ob2RlLmJpbmRJdGVtcy5jaGlsZHJlbikgewogICAgICBpZiAoY29ubmVjdGlvbikgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmICghcmVmKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3Qgbm9kZXMgPSBzZWFyY2hOb2RlKHRoaXMucm9vdCwgZGF0YU5vZGUsIHJlZiwgZmFsc2UsIGZhbHNlKTsKICAgICAgaWYgKCFub2RlcykgewogICAgICAgIHdhcm4oYFhGQSAtIEludmFsaWQgcmVmZXJlbmNlOiAke3JlZn0uYCk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBub2RlIG9mIG5vZGVzKSB7CiAgICAgICAgaWYgKCFub2RlWyRpc0Rlc2NlbmRlbnRdKHRoaXMuZGF0YXNldHMpKSB7CiAgICAgICAgICB3YXJuKGBYRkEgLSBJbnZhbGlkIHJlZiAoJHtyZWZ9KTogbXVzdCBiZSBhIGRhdGFzZXRzIGNoaWxkLmApOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGxhYmVsTm9kZXMgPSBzZWFyY2hOb2RlKHRoaXMucm9vdCwgbm9kZSwgbGFiZWxSZWYsIHRydWUsIGZhbHNlKTsKICAgICAgICBpZiAoIWxhYmVsTm9kZXMpIHsKICAgICAgICAgIHdhcm4oYFhGQSAtIEludmFsaWQgbGFiZWw6ICR7bGFiZWxSZWZ9LmApOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IFtsYWJlbE5vZGVdID0gbGFiZWxOb2RlczsKICAgICAgICBpZiAoIWxhYmVsTm9kZVskaXNEZXNjZW5kZW50XSh0aGlzLmRhdGFzZXRzKSkgewogICAgICAgICAgd2FybihgWEZBIC0gSW52YWxpZCBsYWJlbDogbXVzdCBiZSBhIGRhdGFzZXRzIGNoaWxkLmApOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IHZhbHVlTm9kZXMgPSBzZWFyY2hOb2RlKHRoaXMucm9vdCwgbm9kZSwgdmFsdWVSZWYsIHRydWUsIGZhbHNlKTsKICAgICAgICBpZiAoIXZhbHVlTm9kZXMpIHsKICAgICAgICAgIHdhcm4oYFhGQSAtIEludmFsaWQgdmFsdWU6ICR7dmFsdWVSZWZ9LmApOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IFt2YWx1ZU5vZGVdID0gdmFsdWVOb2RlczsKICAgICAgICBpZiAoIXZhbHVlTm9kZVskaXNEZXNjZW5kZW50XSh0aGlzLmRhdGFzZXRzKSkgewogICAgICAgICAgd2FybihgWEZBIC0gSW52YWxpZCB2YWx1ZTogbXVzdCBiZSBhIGRhdGFzZXRzIGNoaWxkLmApOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGxhYmVsID0gY3JlYXRlVGV4dChsYWJlbE5vZGVbJHRleHRdKCkpOwogICAgICAgIGNvbnN0IHZhbHVlID0gY3JlYXRlVGV4dCh2YWx1ZU5vZGVbJHRleHRdKCkpOwogICAgICAgIGxhYmVsc1skYXBwZW5kQ2hpbGRdKGxhYmVsKTsKICAgICAgICBsYWJlbHMudGV4dC5wdXNoKGxhYmVsKTsKICAgICAgICB2YWx1ZXNbJGFwcGVuZENoaWxkXSh2YWx1ZSk7CiAgICAgICAgdmFsdWVzLnRleHQucHVzaCh2YWx1ZSk7CiAgICAgIH0KICAgIH0KICB9CiAgX2JpbmRPY2N1cnJlbmNlcyhmb3JtTm9kZSwgbWF0Y2hlcywgcGljdHVyZSkgewogICAgbGV0IGJhc2VDbG9uZTsKICAgIGlmIChtYXRjaGVzLmxlbmd0aCA+IDEpIHsKICAgICAgYmFzZUNsb25lID0gZm9ybU5vZGVbJGNsb25lXSgpOwogICAgICBiYXNlQ2xvbmVbJHJlbW92ZUNoaWxkXShiYXNlQ2xvbmUub2NjdXIpOwogICAgICBiYXNlQ2xvbmUub2NjdXIgPSBudWxsOwogICAgfQogICAgdGhpcy5fYmluZFZhbHVlKGZvcm1Ob2RlLCBtYXRjaGVzWzBdLCBwaWN0dXJlKTsKICAgIHRoaXMuX3NldFByb3BlcnRpZXMoZm9ybU5vZGUsIG1hdGNoZXNbMF0pOwogICAgdGhpcy5fYmluZEl0ZW1zKGZvcm1Ob2RlLCBtYXRjaGVzWzBdKTsKICAgIGlmIChtYXRjaGVzLmxlbmd0aCA9PT0gMSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBwYXJlbnQgPSBmb3JtTm9kZVskZ2V0UGFyZW50XSgpOwogICAgY29uc3QgbmFtZSA9IGZvcm1Ob2RlWyRub2RlTmFtZV07CiAgICBjb25zdCBwb3MgPSBwYXJlbnRbJGluZGV4T2ZdKGZvcm1Ob2RlKTsKICAgIGZvciAobGV0IGkgPSAxLCBpaSA9IG1hdGNoZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCBtYXRjaCA9IG1hdGNoZXNbaV07CiAgICAgIGNvbnN0IGNsb25lID0gYmFzZUNsb25lWyRjbG9uZV0oKTsKICAgICAgcGFyZW50W25hbWVdLnB1c2goY2xvbmUpOwogICAgICBwYXJlbnRbJGluc2VydEF0XShwb3MgKyBpLCBjbG9uZSk7CiAgICAgIHRoaXMuX2JpbmRWYWx1ZShjbG9uZSwgbWF0Y2gsIHBpY3R1cmUpOwogICAgICB0aGlzLl9zZXRQcm9wZXJ0aWVzKGNsb25lLCBtYXRjaCk7CiAgICAgIHRoaXMuX2JpbmRJdGVtcyhjbG9uZSwgbWF0Y2gpOwogICAgfQogIH0KICBfY3JlYXRlT2NjdXJyZW5jZXMoZm9ybU5vZGUpIHsKICAgIGlmICghdGhpcy5lbXB0eU1lcmdlKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgb2NjdXIKICAgIH0gPSBmb3JtTm9kZTsKICAgIGlmICghb2NjdXIgfHwgb2NjdXIuaW5pdGlhbCA8PSAxKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IHBhcmVudCA9IGZvcm1Ob2RlWyRnZXRQYXJlbnRdKCk7CiAgICBjb25zdCBuYW1lID0gZm9ybU5vZGVbJG5vZGVOYW1lXTsKICAgIGlmICghKHBhcmVudFtuYW1lXSBpbnN0YW5jZW9mIFhGQU9iamVjdEFycmF5KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgY3VycmVudE51bWJlcjsKICAgIGlmIChmb3JtTm9kZS5uYW1lKSB7CiAgICAgIGN1cnJlbnROdW1iZXIgPSBwYXJlbnRbbmFtZV0uY2hpbGRyZW4uZmlsdGVyKGUgPT4gZS5uYW1lID09PSBmb3JtTm9kZS5uYW1lKS5sZW5ndGg7CiAgICB9IGVsc2UgewogICAgICBjdXJyZW50TnVtYmVyID0gcGFyZW50W25hbWVdLmNoaWxkcmVuLmxlbmd0aDsKICAgIH0KICAgIGNvbnN0IHBvcyA9IHBhcmVudFskaW5kZXhPZl0oZm9ybU5vZGUpICsgMTsKICAgIGNvbnN0IGlpID0gb2NjdXIuaW5pdGlhbCAtIGN1cnJlbnROdW1iZXI7CiAgICBpZiAoaWkpIHsKICAgICAgY29uc3Qgbm9kZUNsb25lID0gZm9ybU5vZGVbJGNsb25lXSgpOwogICAgICBub2RlQ2xvbmVbJHJlbW92ZUNoaWxkXShub2RlQ2xvbmUub2NjdXIpOwogICAgICBub2RlQ2xvbmUub2NjdXIgPSBudWxsOwogICAgICBwYXJlbnRbbmFtZV0ucHVzaChub2RlQ2xvbmUpOwogICAgICBwYXJlbnRbJGluc2VydEF0XShwb3MsIG5vZGVDbG9uZSk7CiAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbnN0IGNsb25lID0gbm9kZUNsb25lWyRjbG9uZV0oKTsKICAgICAgICBwYXJlbnRbbmFtZV0ucHVzaChjbG9uZSk7CiAgICAgICAgcGFyZW50WyRpbnNlcnRBdF0ocG9zICsgaSwgY2xvbmUpOwogICAgICB9CiAgICB9CiAgfQogIF9nZXRPY2N1ckluZm8oZm9ybU5vZGUpIHsKICAgIGNvbnN0IHsKICAgICAgbmFtZSwKICAgICAgb2NjdXIKICAgIH0gPSBmb3JtTm9kZTsKICAgIGlmICghb2NjdXIgfHwgIW5hbWUpIHsKICAgICAgcmV0dXJuIFsxLCAxXTsKICAgIH0KICAgIGNvbnN0IG1heCA9IG9jY3VyLm1heCA9PT0gLTEgPyBJbmZpbml0eSA6IG9jY3VyLm1heDsKICAgIHJldHVybiBbb2NjdXIubWluLCBtYXhdOwogIH0KICBfc2V0QW5kQmluZChmb3JtTm9kZSwgZGF0YU5vZGUpIHsKICAgIHRoaXMuX3NldFByb3BlcnRpZXMoZm9ybU5vZGUsIGRhdGFOb2RlKTsKICAgIHRoaXMuX2JpbmRJdGVtcyhmb3JtTm9kZSwgZGF0YU5vZGUpOwogICAgdGhpcy5fYmluZEVsZW1lbnQoZm9ybU5vZGUsIGRhdGFOb2RlKTsKICB9CiAgX2JpbmRFbGVtZW50KGZvcm1Ob2RlLCBkYXRhTm9kZSkgewogICAgY29uc3QgdXNlbGVzc05vZGVzID0gW107CiAgICB0aGlzLl9jcmVhdGVPY2N1cnJlbmNlcyhmb3JtTm9kZSk7CiAgICBmb3IgKGNvbnN0IGNoaWxkIG9mIGZvcm1Ob2RlWyRnZXRDaGlsZHJlbl0oKSkgewogICAgICBpZiAoY2hpbGRbJGRhdGFdKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKHRoaXMuX21lcmdlTW9kZSA9PT0gdW5kZWZpbmVkICYmIGNoaWxkWyRub2RlTmFtZV0gPT09ICJzdWJmb3JtIikgewogICAgICAgIHRoaXMuX21lcmdlTW9kZSA9IGNoaWxkLm1lcmdlTW9kZSA9PT0gImNvbnN1bWVEYXRhIjsKICAgICAgICBjb25zdCBkYXRhQ2hpbGRyZW4gPSBkYXRhTm9kZVskZ2V0Q2hpbGRyZW5dKCk7CiAgICAgICAgaWYgKGRhdGFDaGlsZHJlbi5sZW5ndGggPiAwKSB7CiAgICAgICAgICB0aGlzLl9iaW5kT2NjdXJyZW5jZXMoY2hpbGQsIFtkYXRhQ2hpbGRyZW5bMF1dLCBudWxsKTsKICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZW1wdHlNZXJnZSkgewogICAgICAgICAgY29uc3QgbnNJZCA9IGRhdGFOb2RlWyRuYW1lc3BhY2VJZF0gPT09IGJpbmRfTlNfREFUQVNFVFMgPyAtMSA6IGRhdGFOb2RlWyRuYW1lc3BhY2VJZF07CiAgICAgICAgICBjb25zdCBkYXRhQ2hpbGQgPSBjaGlsZFskZGF0YV0gPSBuZXcgWG1sT2JqZWN0KG5zSWQsIGNoaWxkLm5hbWUgfHwgInJvb3QiKTsKICAgICAgICAgIGRhdGFOb2RlWyRhcHBlbmRDaGlsZF0oZGF0YUNoaWxkKTsKICAgICAgICAgIHRoaXMuX2JpbmRFbGVtZW50KGNoaWxkLCBkYXRhQ2hpbGQpOwogICAgICAgIH0KICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAoIWNoaWxkWyRpc0JpbmRhYmxlXSgpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgbGV0IGdsb2JhbCA9IGZhbHNlOwogICAgICBsZXQgcGljdHVyZSA9IG51bGw7CiAgICAgIGxldCByZWYgPSBudWxsOwogICAgICBsZXQgbWF0Y2ggPSBudWxsOwogICAgICBpZiAoY2hpbGQuYmluZCkgewogICAgICAgIHN3aXRjaCAoY2hpbGQuYmluZC5tYXRjaCkgewogICAgICAgICAgY2FzZSAibm9uZSI6CiAgICAgICAgICAgIHRoaXMuX3NldEFuZEJpbmQoY2hpbGQsIGRhdGFOb2RlKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICBjYXNlICJnbG9iYWwiOgogICAgICAgICAgICBnbG9iYWwgPSB0cnVlOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgImRhdGFSZWYiOgogICAgICAgICAgICBpZiAoIWNoaWxkLmJpbmQucmVmKSB7CiAgICAgICAgICAgICAgd2FybihgWEZBIC0gcmVmIGlzIGVtcHR5IGluIG5vZGUgJHtjaGlsZFskbm9kZU5hbWVdfS5gKTsKICAgICAgICAgICAgICB0aGlzLl9zZXRBbmRCaW5kKGNoaWxkLCBkYXRhTm9kZSk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmVmID0gY2hpbGQuYmluZC5yZWY7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIGlmIChjaGlsZC5iaW5kLnBpY3R1cmUpIHsKICAgICAgICAgIHBpY3R1cmUgPSBjaGlsZC5iaW5kLnBpY3R1cmVbJGNvbnRlbnRdOwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCBbbWluLCBtYXhdID0gdGhpcy5fZ2V0T2NjdXJJbmZvKGNoaWxkKTsKICAgICAgaWYgKHJlZikgewogICAgICAgIG1hdGNoID0gc2VhcmNoTm9kZSh0aGlzLnJvb3QsIGRhdGFOb2RlLCByZWYsIHRydWUsIGZhbHNlKTsKICAgICAgICBpZiAobWF0Y2ggPT09IG51bGwpIHsKICAgICAgICAgIG1hdGNoID0gY3JlYXRlRGF0YU5vZGUodGhpcy5kYXRhLCBkYXRhTm9kZSwgcmVmKTsKICAgICAgICAgIGlmICghbWF0Y2gpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAodGhpcy5faXNDb25zdW1lRGF0YSgpKSB7CiAgICAgICAgICAgIG1hdGNoWyRjb25zdW1lZF0gPSB0cnVlOwogICAgICAgICAgfQogICAgICAgICAgdGhpcy5fc2V0QW5kQmluZChjaGlsZCwgbWF0Y2gpOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGlmICh0aGlzLl9pc0NvbnN1bWVEYXRhKCkpIHsKICAgICAgICAgICAgbWF0Y2ggPSBtYXRjaC5maWx0ZXIobm9kZSA9PiAhbm9kZVskY29uc3VtZWRdKTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiBtYXgpIHsKICAgICAgICAgICAgbWF0Y2ggPSBtYXRjaC5zbGljZSgwLCBtYXgpOwogICAgICAgICAgfSBlbHNlIGlmIChtYXRjaC5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgbWF0Y2ggPSBudWxsOwogICAgICAgICAgfQogICAgICAgICAgaWYgKG1hdGNoICYmIHRoaXMuX2lzQ29uc3VtZURhdGEoKSkgewogICAgICAgICAgICBtYXRjaC5mb3JFYWNoKG5vZGUgPT4gewogICAgICAgICAgICAgIG5vZGVbJGNvbnN1bWVkXSA9IHRydWU7CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBpZiAoIWNoaWxkLm5hbWUpIHsKICAgICAgICAgIHRoaXMuX3NldEFuZEJpbmQoY2hpbGQsIGRhdGFOb2RlKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBpZiAodGhpcy5faXNDb25zdW1lRGF0YSgpKSB7CiAgICAgICAgICBjb25zdCBtYXRjaGVzID0gW107CiAgICAgICAgICB3aGlsZSAobWF0Y2hlcy5sZW5ndGggPCBtYXgpIHsKICAgICAgICAgICAgY29uc3QgZm91bmQgPSB0aGlzLl9maW5kRGF0YUJ5TmFtZVRvQ29uc3VtZShjaGlsZC5uYW1lLCBjaGlsZFskaGFzU2V0dGFibGVWYWx1ZV0oKSwgZGF0YU5vZGUsIGdsb2JhbCk7CiAgICAgICAgICAgIGlmICghZm91bmQpIHsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgICAgICBmb3VuZFskY29uc3VtZWRdID0gdHJ1ZTsKICAgICAgICAgICAgbWF0Y2hlcy5wdXNoKGZvdW5kKTsKICAgICAgICAgIH0KICAgICAgICAgIG1hdGNoID0gbWF0Y2hlcy5sZW5ndGggPiAwID8gbWF0Y2hlcyA6IG51bGw7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIG1hdGNoID0gZGF0YU5vZGVbJGdldFJlYWxDaGlsZHJlbkJ5TmFtZUl0XShjaGlsZC5uYW1lLCBmYWxzZSwgdGhpcy5lbXB0eU1lcmdlKS5uZXh0KCkudmFsdWU7CiAgICAgICAgICBpZiAoIW1hdGNoKSB7CiAgICAgICAgICAgIGlmIChtaW4gPT09IDApIHsKICAgICAgICAgICAgICB1c2VsZXNzTm9kZXMucHVzaChjaGlsZCk7CiAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgY29uc3QgbnNJZCA9IGRhdGFOb2RlWyRuYW1lc3BhY2VJZF0gPT09IGJpbmRfTlNfREFUQVNFVFMgPyAtMSA6IGRhdGFOb2RlWyRuYW1lc3BhY2VJZF07CiAgICAgICAgICAgIG1hdGNoID0gY2hpbGRbJGRhdGFdID0gbmV3IFhtbE9iamVjdChuc0lkLCBjaGlsZC5uYW1lKTsKICAgICAgICAgICAgaWYgKHRoaXMuZW1wdHlNZXJnZSkgewogICAgICAgICAgICAgIG1hdGNoWyRjb25zdW1lZF0gPSB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGRhdGFOb2RlWyRhcHBlbmRDaGlsZF0obWF0Y2gpOwogICAgICAgICAgICB0aGlzLl9zZXRBbmRCaW5kKGNoaWxkLCBtYXRjaCk7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgaWYgKHRoaXMuZW1wdHlNZXJnZSkgewogICAgICAgICAgICBtYXRjaFskY29uc3VtZWRdID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICAgIG1hdGNoID0gW21hdGNoXTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKG1hdGNoKSB7CiAgICAgICAgdGhpcy5fYmluZE9jY3VycmVuY2VzKGNoaWxkLCBtYXRjaCwgcGljdHVyZSk7CiAgICAgIH0gZWxzZSBpZiAobWluID4gMCkgewogICAgICAgIHRoaXMuX3NldEFuZEJpbmQoY2hpbGQsIGRhdGFOb2RlKTsKICAgICAgfSBlbHNlIHsKICAgICAgICB1c2VsZXNzTm9kZXMucHVzaChjaGlsZCk7CiAgICAgIH0KICAgIH0KICAgIHVzZWxlc3NOb2Rlcy5mb3JFYWNoKG5vZGUgPT4gbm9kZVskZ2V0UGFyZW50XSgpWyRyZW1vdmVDaGlsZF0obm9kZSkpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveGZhL2RhdGEuanMKCgpjbGFzcyBEYXRhSGFuZGxlciB7CiAgY29uc3RydWN0b3Iocm9vdCwgZGF0YSkgewogICAgdGhpcy5kYXRhID0gZGF0YTsKICAgIHRoaXMuZGF0YXNldCA9IHJvb3QuZGF0YXNldHMgfHwgbnVsbDsKICB9CiAgc2VyaWFsaXplKHN0b3JhZ2UpIHsKICAgIGNvbnN0IHN0YWNrID0gW1stMSwgdGhpcy5kYXRhWyRnZXRDaGlsZHJlbl0oKV1dOwogICAgd2hpbGUgKHN0YWNrLmxlbmd0aCA+IDApIHsKICAgICAgY29uc3QgbGFzdCA9IHN0YWNrLmF0KC0xKTsKICAgICAgY29uc3QgW2ksIGNoaWxkcmVuXSA9IGxhc3Q7CiAgICAgIGlmIChpICsgMSA9PT0gY2hpbGRyZW4ubGVuZ3RoKSB7CiAgICAgICAgc3RhY2sucG9wKCk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgY2hpbGQgPSBjaGlsZHJlblsrK2xhc3RbMF1dOwogICAgICBjb25zdCBzdG9yYWdlRW50cnkgPSBzdG9yYWdlLmdldChjaGlsZFskdWlkXSk7CiAgICAgIGlmIChzdG9yYWdlRW50cnkpIHsKICAgICAgICBjaGlsZFskc2V0VmFsdWVdKHN0b3JhZ2VFbnRyeSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY29uc3QgYXR0cmlidXRlcyA9IGNoaWxkWyRnZXRBdHRyaWJ1dGVzXSgpOwogICAgICAgIGZvciAoY29uc3QgdmFsdWUgb2YgYXR0cmlidXRlcy52YWx1ZXMoKSkgewogICAgICAgICAgY29uc3QgZW50cnkgPSBzdG9yYWdlLmdldCh2YWx1ZVskdWlkXSk7CiAgICAgICAgICBpZiAoZW50cnkpIHsKICAgICAgICAgICAgdmFsdWVbJHNldFZhbHVlXShlbnRyeSk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCBub2RlcyA9IGNoaWxkWyRnZXRDaGlsZHJlbl0oKTsKICAgICAgaWYgKG5vZGVzLmxlbmd0aCA+IDApIHsKICAgICAgICBzdGFjay5wdXNoKFstMSwgbm9kZXNdKTsKICAgICAgfQogICAgfQogICAgY29uc3QgYnVmID0gW2A8eGZhOmRhdGFzZXRzIHhtbG5zOnhmYT0iaHR0cDovL3d3dy54ZmEub3JnL3NjaGVtYS94ZmEtZGF0YS8xLjAvIj5gXTsKICAgIGlmICh0aGlzLmRhdGFzZXQpIHsKICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzLmRhdGFzZXRbJGdldENoaWxkcmVuXSgpKSB7CiAgICAgICAgaWYgKGNoaWxkWyRub2RlTmFtZV0gIT09ICJkYXRhIikgewogICAgICAgICAgY2hpbGRbJHRvU3RyaW5nXShidWYpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgdGhpcy5kYXRhWyR0b1N0cmluZ10oYnVmKTsKICAgIGJ1Zi5wdXNoKCI8L3hmYTpkYXRhc2V0cz4iKTsKICAgIHJldHVybiBidWYuam9pbigiIik7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEvY29uZmlnLmpzCgoKCgoKCgoKCgoKY29uc3QgQ09ORklHX05TX0lEID0gTmFtZXNwYWNlSWRzLmNvbmZpZy5pZDsKY2xhc3MgQWNyb2JhdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYWNyb2JhdCIsIHRydWUpOwogICAgdGhpcy5hY3JvYmF0NyA9IG51bGw7CiAgICB0aGlzLmF1dG9TYXZlID0gbnVsbDsKICAgIHRoaXMuY29tbW9uID0gbnVsbDsKICAgIHRoaXMudmFsaWRhdGUgPSBudWxsOwogICAgdGhpcy52YWxpZGF0ZUFwcHJvdmFsU2lnbmF0dXJlcyA9IG51bGw7CiAgICB0aGlzLnN1Ym1pdFVybCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBBY3JvYmF0NyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYWNyb2JhdDciLCB0cnVlKTsKICAgIHRoaXMuZHluYW1pY1JlbmRlciA9IG51bGw7CiAgfQp9CmNsYXNzIEFEQkVfSlNDb25zb2xlIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJBREJFX0pTQ29uc29sZSIsIFsiZGVsZWdhdGUiLCAiRW5hYmxlIiwgIkRpc2FibGUiXSk7CiAgfQp9CmNsYXNzIEFEQkVfSlNEZWJ1Z2dlciBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiQURCRV9KU0RlYnVnZ2VyIiwgWyJkZWxlZ2F0ZSIsICJFbmFibGUiLCAiRGlzYWJsZSJdKTsKICB9Cn0KY2xhc3MgQWRkU2lsZW50UHJpbnQgZXh0ZW5kcyBPcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYWRkU2lsZW50UHJpbnQiKTsKICB9Cn0KY2xhc3MgQWRkVmlld2VyUHJlZmVyZW5jZXMgZXh0ZW5kcyBPcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYWRkVmlld2VyUHJlZmVyZW5jZXMiKTsKICB9Cn0KY2xhc3MgQWRqdXN0RGF0YSBleHRlbmRzIE9wdGlvbjEwIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJhZGp1c3REYXRhIik7CiAgfQp9CmNsYXNzIEFkb2JlRXh0ZW5zaW9uTGV2ZWwgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJhZG9iZUV4dGVuc2lvbkxldmVsIiwgMCwgbiA9PiBuID49IDEgJiYgbiA8PSA4KTsKICB9Cn0KY2xhc3MgQWdlbnQgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImFnZW50IiwgdHJ1ZSk7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgPyBhdHRyaWJ1dGVzLm5hbWUudHJpbSgpIDogIiI7CiAgICB0aGlzLmNvbW1vbiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBBbHdheXNFbWJlZCBleHRlbmRzIENvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImFsd2F5c0VtYmVkIik7CiAgfQp9CmNsYXNzIEFtZCBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYW1kIik7CiAgfQp9CmNsYXNzIGNvbmZpZ19BcmVhIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJhcmVhIik7CiAgICB0aGlzLmxldmVsID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMubGV2ZWwsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IG4gPT4gbiA+PSAxICYmIG4gPD0gMwogICAgfSk7CiAgICB0aGlzLm5hbWUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5uYW1lLCBbIiIsICJiYXJjb2RlIiwgImNvcmVpbml0IiwgImRldmljZURyaXZlciIsICJmb250IiwgImdlbmVyYWwiLCAibGF5b3V0IiwgIm1lcmdlIiwgInNjcmlwdCIsICJzaWduYXR1cmUiLCAic291cmNlU2V0IiwgInRlbXBsYXRlQ2FjaGUiXSk7CiAgfQp9CmNsYXNzIEF0dHJpYnV0ZXMgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImF0dHJpYnV0ZXMiLCBbInByZXNlcnZlIiwgImRlbGVnYXRlIiwgImlnbm9yZSJdKTsKICB9Cn0KY2xhc3MgQXV0b1NhdmUgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImF1dG9TYXZlIiwgWyJkaXNhYmxlZCIsICJlbmFibGVkIl0pOwogIH0KfQpjbGFzcyBCYXNlIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJiYXNlIik7CiAgfQp9CmNsYXNzIEJhdGNoT3V0cHV0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJiYXRjaE91dHB1dCIpOwogICAgdGhpcy5mb3JtYXQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5mb3JtYXQsIFsibm9uZSIsICJjb25jYXQiLCAiemlwIiwgInppcENvbXByZXNzIl0pOwogIH0KfQpjbGFzcyBCZWhhdmlvck92ZXJyaWRlIGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiYmVoYXZpb3JPdmVycmlkZSIpOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIHRoaXNbJGNvbnRlbnRdID0gbmV3IE1hcCh0aGlzWyRjb250ZW50XS50cmltKCkuc3BsaXQoL1xzKy8pLmZpbHRlcih4ID0+IHguaW5jbHVkZXMoIjoiKSkubWFwKHggPT4geC5zcGxpdCgiOiIsIDIpKSk7CiAgfQp9CmNsYXNzIENhY2hlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjYWNoZSIsIHRydWUpOwogICAgdGhpcy50ZW1wbGF0ZUNhY2hlID0gbnVsbDsKICB9Cn0KY2xhc3MgQ2hhbmdlIGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImNoYW5nZSIpOwogIH0KfQpjbGFzcyBDb21tb24gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImNvbW1vbiIsIHRydWUpOwogICAgdGhpcy5kYXRhID0gbnVsbDsKICAgIHRoaXMubG9jYWxlID0gbnVsbDsKICAgIHRoaXMubG9jYWxlU2V0ID0gbnVsbDsKICAgIHRoaXMubWVzc2FnaW5nID0gbnVsbDsKICAgIHRoaXMuc3VwcHJlc3NCYW5uZXIgPSBudWxsOwogICAgdGhpcy50ZW1wbGF0ZSA9IG51bGw7CiAgICB0aGlzLnZhbGlkYXRpb25NZXNzYWdpbmcgPSBudWxsOwogICAgdGhpcy52ZXJzaW9uQ29udHJvbCA9IG51bGw7CiAgICB0aGlzLmxvZyA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBDb21wcmVzcyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiY29tcHJlc3MiKTsKICAgIHRoaXMuc2NvcGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5zY29wZSwgWyJpbWFnZU9ubHkiLCAiZG9jdW1lbnQiXSk7CiAgfQp9CmNsYXNzIENvbXByZXNzTG9naWNhbFN0cnVjdHVyZSBleHRlbmRzIE9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjb21wcmVzc0xvZ2ljYWxTdHJ1Y3R1cmUiKTsKICB9Cn0KY2xhc3MgQ29tcHJlc3NPYmplY3RTdHJlYW0gZXh0ZW5kcyBPcHRpb24xMCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiY29tcHJlc3NPYmplY3RTdHJlYW0iKTsKICB9Cn0KY2xhc3MgQ29tcHJlc3Npb24gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImNvbXByZXNzaW9uIiwgdHJ1ZSk7CiAgICB0aGlzLmNvbXByZXNzTG9naWNhbFN0cnVjdHVyZSA9IG51bGw7CiAgICB0aGlzLmNvbXByZXNzT2JqZWN0U3RyZWFtID0gbnVsbDsKICAgIHRoaXMubGV2ZWwgPSBudWxsOwogICAgdGhpcy50eXBlID0gbnVsbDsKICB9Cn0KY2xhc3MgQ29uZmlnIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjb25maWciLCB0cnVlKTsKICAgIHRoaXMuYWNyb2JhdCA9IG51bGw7CiAgICB0aGlzLnByZXNlbnQgPSBudWxsOwogICAgdGhpcy50cmFjZSA9IG51bGw7CiAgICB0aGlzLmFnZW50ID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIENvbmZvcm1hbmNlIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjb25mb3JtYW5jZSIsIFsiQSIsICJCIl0pOwogIH0KfQpjbGFzcyBDb250ZW50Q29weSBleHRlbmRzIE9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjb250ZW50Q29weSIpOwogIH0KfQpjbGFzcyBDb3BpZXMgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjb3BpZXMiLCAxLCBuID0+IG4gPj0gMSk7CiAgfQp9CmNsYXNzIENyZWF0b3IgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImNyZWF0b3IiKTsKICB9Cn0KY2xhc3MgQ3VycmVudFBhZ2UgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJjdXJyZW50UGFnZSIsIDAsIG4gPT4gbiA+PSAwKTsKICB9Cn0KY2xhc3MgRGF0YSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZGF0YSIsIHRydWUpOwogICAgdGhpcy5hZGp1c3REYXRhID0gbnVsbDsKICAgIHRoaXMuYXR0cmlidXRlcyA9IG51bGw7CiAgICB0aGlzLmluY3JlbWVudGFsTG9hZCA9IG51bGw7CiAgICB0aGlzLm91dHB1dFhTTCA9IG51bGw7CiAgICB0aGlzLnJhbmdlID0gbnVsbDsKICAgIHRoaXMucmVjb3JkID0gbnVsbDsKICAgIHRoaXMuc3RhcnROb2RlID0gbnVsbDsKICAgIHRoaXMudXJpID0gbnVsbDsKICAgIHRoaXMud2luZG93ID0gbnVsbDsKICAgIHRoaXMueHNsID0gbnVsbDsKICAgIHRoaXMuZXhjbHVkZU5TID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnRyYW5zZm9ybSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBEZWJ1ZyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZGVidWciLCB0cnVlKTsKICAgIHRoaXMudXJpID0gbnVsbDsKICB9Cn0KY2xhc3MgRGVmYXVsdFR5cGVmYWNlIGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZGVmYXVsdFR5cGVmYWNlIik7CiAgICB0aGlzLndyaXRpbmdTY3JpcHQgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy53cml0aW5nU2NyaXB0LCBbIioiLCAiQXJhYmljIiwgIkN5cmlsbGljIiwgIkVhc3RFdXJvcGVhblJvbWFuIiwgIkdyZWVrIiwgIkhlYnJldyIsICJKYXBhbmVzZSIsICJLb3JlYW4iLCAiUm9tYW4iLCAiU2ltcGxpZmllZENoaW5lc2UiLCAiVGhhaSIsICJUcmFkaXRpb25hbENoaW5lc2UiLCAiVmlldG5hbWVzZSJdKTsKICB9Cn0KY2xhc3MgRGVzdGluYXRpb24gZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImRlc3RpbmF0aW9uIiwgWyJwZGYiLCAicGNsIiwgInBzIiwgIndlYkNsaWVudCIsICJ6cGwiXSk7CiAgfQp9CmNsYXNzIERvY3VtZW50QXNzZW1ibHkgZXh0ZW5kcyBPcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZG9jdW1lbnRBc3NlbWJseSIpOwogIH0KfQpjbGFzcyBEcml2ZXIgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImRyaXZlciIsIHRydWUpOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lID8gYXR0cmlidXRlcy5uYW1lLnRyaW0oKSA6ICIiOwogICAgdGhpcy5mb250SW5mbyA9IG51bGw7CiAgICB0aGlzLnhkYyA9IG51bGw7CiAgfQp9CmNsYXNzIER1cGxleE9wdGlvbiBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZHVwbGV4T3B0aW9uIiwgWyJzaW1wbGV4IiwgImR1cGxleEZsaXBMb25nRWRnZSIsICJkdXBsZXhGbGlwU2hvcnRFZGdlIl0pOwogIH0KfQpjbGFzcyBEeW5hbWljUmVuZGVyIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJkeW5hbWljUmVuZGVyIiwgWyJmb3JiaWRkZW4iLCAicmVxdWlyZWQiXSk7CiAgfQp9CmNsYXNzIEVtYmVkIGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImVtYmVkIik7CiAgfQp9CmNsYXNzIGNvbmZpZ19FbmNyeXB0IGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImVuY3J5cHQiKTsKICB9Cn0KY2xhc3MgY29uZmlnX0VuY3J5cHRpb24gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImVuY3J5cHRpb24iLCB0cnVlKTsKICAgIHRoaXMuZW5jcnlwdCA9IG51bGw7CiAgICB0aGlzLmVuY3J5cHRpb25MZXZlbCA9IG51bGw7CiAgICB0aGlzLnBlcm1pc3Npb25zID0gbnVsbDsKICB9Cn0KY2xhc3MgRW5jcnlwdGlvbkxldmVsIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJlbmNyeXB0aW9uTGV2ZWwiLCBbIjQwYml0IiwgIjEyOGJpdCJdKTsKICB9Cn0KY2xhc3MgRW5mb3JjZSBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiZW5mb3JjZSIpOwogIH0KfQpjbGFzcyBFcXVhdGUgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImVxdWF0ZSIpOwogICAgdGhpcy5mb3JjZSA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmZvcmNlLAogICAgICBkZWZhdWx0VmFsdWU6IDEsCiAgICAgIHZhbGlkYXRlOiBuID0+IG4gPT09IDAKICAgIH0pOwogICAgdGhpcy5mcm9tID0gYXR0cmlidXRlcy5mcm9tIHx8ICIiOwogICAgdGhpcy50byA9IGF0dHJpYnV0ZXMudG8gfHwgIiI7CiAgfQp9CmNsYXNzIEVxdWF0ZVJhbmdlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJlcXVhdGVSYW5nZSIpOwogICAgdGhpcy5mcm9tID0gYXR0cmlidXRlcy5mcm9tIHx8ICIiOwogICAgdGhpcy50byA9IGF0dHJpYnV0ZXMudG8gfHwgIiI7CiAgICB0aGlzLl91bmljb2RlUmFuZ2UgPSBhdHRyaWJ1dGVzLnVuaWNvZGVSYW5nZSB8fCAiIjsKICB9CiAgZ2V0IHVuaWNvZGVSYW5nZSgpIHsKICAgIGNvbnN0IHJhbmdlcyA9IFtdOwogICAgY29uc3QgdW5pY29kZVJlZ2V4ID0gL1VcKyhbMC05YS1mQS1GXSspLzsKICAgIGNvbnN0IHVuaWNvZGVSYW5nZSA9IHRoaXMuX3VuaWNvZGVSYW5nZTsKICAgIGZvciAobGV0IHJhbmdlIG9mIHVuaWNvZGVSYW5nZS5zcGxpdCgiLCIpLm1hcCh4ID0+IHgudHJpbSgpKS5maWx0ZXIoeCA9PiAhIXgpKSB7CiAgICAgIHJhbmdlID0gcmFuZ2Uuc3BsaXQoIi0iLCAyKS5tYXAoeCA9PiB7CiAgICAgICAgY29uc3QgZm91bmQgPSB4Lm1hdGNoKHVuaWNvZGVSZWdleCk7CiAgICAgICAgaWYgKCFmb3VuZCkgewogICAgICAgICAgcmV0dXJuIDA7CiAgICAgICAgfQogICAgICAgIHJldHVybiBwYXJzZUludChmb3VuZFsxXSwgMTYpOwogICAgICB9KTsKICAgICAgaWYgKHJhbmdlLmxlbmd0aCA9PT0gMSkgewogICAgICAgIHJhbmdlLnB1c2gocmFuZ2VbMF0pOwogICAgICB9CiAgICAgIHJhbmdlcy5wdXNoKHJhbmdlKTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgInVuaWNvZGVSYW5nZSIsIHJhbmdlcyk7CiAgfQp9CmNsYXNzIEV4Y2x1ZGUgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJleGNsdWRlIik7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgdGhpc1skY29udGVudF0gPSB0aGlzWyRjb250ZW50XS50cmltKCkuc3BsaXQoL1xzKy8pLmZpbHRlcih4ID0+IHggJiYgWyJjYWxjdWxhdGUiLCAiY2xvc2UiLCAiZW50ZXIiLCAiZXhpdCIsICJpbml0aWFsaXplIiwgInJlYWR5IiwgInZhbGlkYXRlIl0uaW5jbHVkZXMoeCkpOwogIH0KfQpjbGFzcyBFeGNsdWRlTlMgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImV4Y2x1ZGVOUyIpOwogIH0KfQpjbGFzcyBGbGlwTGFiZWwgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImZsaXBMYWJlbCIsIFsidXNlUHJpbnRlclNldHRpbmciLCAib24iLCAib2ZmIl0pOwogIH0KfQpjbGFzcyBjb25maWdfRm9udEluZm8gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImZvbnRJbmZvIiwgdHJ1ZSk7CiAgICB0aGlzLmVtYmVkID0gbnVsbDsKICAgIHRoaXMubWFwID0gbnVsbDsKICAgIHRoaXMuc3Vic2V0QmVsb3cgPSBudWxsOwogICAgdGhpcy5hbHdheXNFbWJlZCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5kZWZhdWx0VHlwZWZhY2UgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMubmV2ZXJFbWJlZCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBGb3JtRmllbGRGaWxsaW5nIGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImZvcm1GaWVsZEZpbGxpbmciKTsKICB9Cn0KY2xhc3MgR3JvdXBQYXJlbnQgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImdyb3VwUGFyZW50Iik7CiAgfQp9CmNsYXNzIElmRW1wdHkgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImlmRW1wdHkiLCBbImRhdGFWYWx1ZSIsICJkYXRhR3JvdXAiLCAiaWdub3JlIiwgInJlbW92ZSJdKTsKICB9Cn0KY2xhc3MgSW5jbHVkZVhEUENvbnRlbnQgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImluY2x1ZGVYRFBDb250ZW50Iik7CiAgfQp9CmNsYXNzIEluY3JlbWVudGFsTG9hZCBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiaW5jcmVtZW50YWxMb2FkIiwgWyJub25lIiwgImZvcndhcmRPbmx5Il0pOwogIH0KfQpjbGFzcyBJbmNyZW1lbnRhbE1lcmdlIGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImluY3JlbWVudGFsTWVyZ2UiKTsKICB9Cn0KY2xhc3MgSW50ZXJhY3RpdmUgZXh0ZW5kcyBPcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAiaW50ZXJhY3RpdmUiKTsKICB9Cn0KY2xhc3MgSm9nIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJqb2ciLCBbInVzZVByaW50ZXJTZXR0aW5nIiwgIm5vbmUiLCAicGFnZVNldCJdKTsKICB9Cn0KY2xhc3MgTGFiZWxQcmludGVyIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsYWJlbFByaW50ZXIiLCB0cnVlKTsKICAgIHRoaXMubmFtZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLm5hbWUsIFsienBsIiwgImRwbCIsICJpcGwiLCAidGNwbCJdKTsKICAgIHRoaXMuYmF0Y2hPdXRwdXQgPSBudWxsOwogICAgdGhpcy5mbGlwTGFiZWwgPSBudWxsOwogICAgdGhpcy5mb250SW5mbyA9IG51bGw7CiAgICB0aGlzLnhkYyA9IG51bGw7CiAgfQp9CmNsYXNzIExheW91dCBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAibGF5b3V0IiwgWyJwYWdpbmF0ZSIsICJwYW5lbCJdKTsKICB9Cn0KY2xhc3MgTGV2ZWwgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsZXZlbCIsIDAsIG4gPT4gbiA+IDApOwogIH0KfQpjbGFzcyBMaW5lYXJpemVkIGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgImxpbmVhcml6ZWQiKTsKICB9Cn0KY2xhc3MgTG9jYWxlIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsb2NhbGUiKTsKICB9Cn0KY2xhc3MgTG9jYWxlU2V0IGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsb2NhbGVTZXQiKTsKICB9Cn0KY2xhc3MgTG9nIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJsb2ciLCB0cnVlKTsKICAgIHRoaXMubW9kZSA9IG51bGw7CiAgICB0aGlzLnRocmVzaG9sZCA9IG51bGw7CiAgICB0aGlzLnRvID0gbnVsbDsKICAgIHRoaXMudXJpID0gbnVsbDsKICB9Cn0KY2xhc3MgTWFwRWxlbWVudCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAibWFwIiwgdHJ1ZSk7CiAgICB0aGlzLmVxdWF0ZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5lcXVhdGVSYW5nZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBNZWRpdW1JbmZvIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJtZWRpdW1JbmZvIiwgdHJ1ZSk7CiAgICB0aGlzLm1hcCA9IG51bGw7CiAgfQp9CmNsYXNzIGNvbmZpZ19NZXNzYWdlIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJtZXNzYWdlIiwgdHJ1ZSk7CiAgICB0aGlzLm1zZ0lkID0gbnVsbDsKICAgIHRoaXMuc2V2ZXJpdHkgPSBudWxsOwogIH0KfQpjbGFzcyBNZXNzYWdpbmcgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm1lc3NhZ2luZyIsIHRydWUpOwogICAgdGhpcy5tZXNzYWdlID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIE1vZGUgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm1vZGUiLCBbImFwcGVuZCIsICJvdmVyd3JpdGUiXSk7CiAgfQp9CmNsYXNzIE1vZGlmeUFubm90cyBleHRlbmRzIE9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJtb2RpZnlBbm5vdHMiKTsKICB9Cn0KY2xhc3MgTXNnSWQgZXh0ZW5kcyBJbnRlZ2VyT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJtc2dJZCIsIDEsIG4gPT4gbiA+PSAxKTsKICB9Cn0KY2xhc3MgTmFtZUF0dHIgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgIm5hbWVBdHRyIik7CiAgfQp9CmNsYXNzIE5ldmVyRW1iZWQgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJuZXZlckVtYmVkIik7CiAgfQp9CmNsYXNzIE51bWJlck9mQ29waWVzIGV4dGVuZHMgSW50ZWdlck9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAibnVtYmVyT2ZDb3BpZXMiLCBudWxsLCBuID0+IG4gPj0gMiAmJiBuIDw9IDUpOwogIH0KfQpjbGFzcyBPcGVuQWN0aW9uIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJvcGVuQWN0aW9uIiwgdHJ1ZSk7CiAgICB0aGlzLmRlc3RpbmF0aW9uID0gbnVsbDsKICB9Cn0KY2xhc3MgT3V0cHV0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJvdXRwdXQiLCB0cnVlKTsKICAgIHRoaXMudG8gPSBudWxsOwogICAgdGhpcy50eXBlID0gbnVsbDsKICAgIHRoaXMudXJpID0gbnVsbDsKICB9Cn0KY2xhc3MgT3V0cHV0QmluIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJvdXRwdXRCaW4iKTsKICB9Cn0KY2xhc3MgT3V0cHV0WFNMIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJvdXRwdXRYU0wiLCB0cnVlKTsKICAgIHRoaXMudXJpID0gbnVsbDsKICB9Cn0KY2xhc3MgT3ZlcnByaW50IGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJvdmVycHJpbnQiLCBbIm5vbmUiLCAiYm90aCIsICJkcmF3IiwgImZpZWxkIl0pOwogIH0KfQpjbGFzcyBQYWNrZXRzIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwYWNrZXRzIik7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgaWYgKHRoaXNbJGNvbnRlbnRdID09PSAiKiIpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpc1skY29udGVudF0gPSB0aGlzWyRjb250ZW50XS50cmltKCkuc3BsaXQoL1xzKy8pLmZpbHRlcih4ID0+IFsiY29uZmlnIiwgImRhdGFzZXRzIiwgInRlbXBsYXRlIiwgInhmZGYiLCAieHNsdCJdLmluY2x1ZGVzKHgpKTsKICB9Cn0KY2xhc3MgUGFnZU9mZnNldCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGFnZU9mZnNldCIpOwogICAgdGhpcy54ID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMueCwKICAgICAgZGVmYXVsdFZhbHVlOiAidXNlWERDU2V0dGluZyIsCiAgICAgIHZhbGlkYXRlOiBuID0+IHRydWUKICAgIH0pOwogICAgdGhpcy55ID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMueSwKICAgICAgZGVmYXVsdFZhbHVlOiAidXNlWERDU2V0dGluZyIsCiAgICAgIHZhbGlkYXRlOiBuID0+IHRydWUKICAgIH0pOwogIH0KfQpjbGFzcyBQYWdlUmFuZ2UgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInBhZ2VSYW5nZSIpOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIGNvbnN0IG51bWJlcnMgPSB0aGlzWyRjb250ZW50XS50cmltKCkuc3BsaXQoL1xzKy8pLm1hcCh4ID0+IHBhcnNlSW50KHgsIDEwKSk7CiAgICBjb25zdCByYW5nZXMgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IG51bWJlcnMubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICByYW5nZXMucHVzaChudW1iZXJzLnNsaWNlKGksIGkgKyAyKSk7CiAgICB9CiAgICB0aGlzWyRjb250ZW50XSA9IHJhbmdlczsKICB9Cn0KY2xhc3MgUGFnaW5hdGlvbiBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGFnaW5hdGlvbiIsIFsic2ltcGxleCIsICJkdXBsZXhTaG9ydEVkZ2UiLCAiZHVwbGV4TG9uZ0VkZ2UiXSk7CiAgfQp9CmNsYXNzIFBhZ2luYXRpb25PdmVycmlkZSBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGFnaW5hdGlvbk92ZXJyaWRlIiwgWyJub25lIiwgImZvcmNlRHVwbGV4IiwgImZvcmNlRHVwbGV4TG9uZ0VkZ2UiLCAiZm9yY2VEdXBsZXhTaG9ydEVkZ2UiLCAiZm9yY2VTaW1wbGV4Il0pOwogIH0KfQpjbGFzcyBQYXJ0IGV4dGVuZHMgSW50ZWdlck9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGFydCIsIDEsIG4gPT4gZmFsc2UpOwogIH0KfQpjbGFzcyBQY2wgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInBjbCIsIHRydWUpOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5iYXRjaE91dHB1dCA9IG51bGw7CiAgICB0aGlzLmZvbnRJbmZvID0gbnVsbDsKICAgIHRoaXMuam9nID0gbnVsbDsKICAgIHRoaXMubWVkaXVtSW5mbyA9IG51bGw7CiAgICB0aGlzLm91dHB1dEJpbiA9IG51bGw7CiAgICB0aGlzLnBhZ2VPZmZzZXQgPSBudWxsOwogICAgdGhpcy5zdGFwbGUgPSBudWxsOwogICAgdGhpcy54ZGMgPSBudWxsOwogIH0KfQpjbGFzcyBQZGYgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInBkZiIsIHRydWUpOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5hZG9iZUV4dGVuc2lvbkxldmVsID0gbnVsbDsKICAgIHRoaXMuYmF0Y2hPdXRwdXQgPSBudWxsOwogICAgdGhpcy5jb21wcmVzc2lvbiA9IG51bGw7CiAgICB0aGlzLmNyZWF0b3IgPSBudWxsOwogICAgdGhpcy5lbmNyeXB0aW9uID0gbnVsbDsKICAgIHRoaXMuZm9udEluZm8gPSBudWxsOwogICAgdGhpcy5pbnRlcmFjdGl2ZSA9IG51bGw7CiAgICB0aGlzLmxpbmVhcml6ZWQgPSBudWxsOwogICAgdGhpcy5vcGVuQWN0aW9uID0gbnVsbDsKICAgIHRoaXMucGRmYSA9IG51bGw7CiAgICB0aGlzLnByb2R1Y2VyID0gbnVsbDsKICAgIHRoaXMucmVuZGVyUG9saWN5ID0gbnVsbDsKICAgIHRoaXMuc2NyaXB0TW9kZWwgPSBudWxsOwogICAgdGhpcy5zaWxlbnRQcmludCA9IG51bGw7CiAgICB0aGlzLnN1Ym1pdEZvcm1hdCA9IG51bGw7CiAgICB0aGlzLnRhZ2dlZCA9IG51bGw7CiAgICB0aGlzLnZlcnNpb24gPSBudWxsOwogICAgdGhpcy52aWV3ZXJQcmVmZXJlbmNlcyA9IG51bGw7CiAgICB0aGlzLnhkYyA9IG51bGw7CiAgfQp9CmNsYXNzIFBkZmEgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInBkZmEiLCB0cnVlKTsKICAgIHRoaXMuYW1kID0gbnVsbDsKICAgIHRoaXMuY29uZm9ybWFuY2UgPSBudWxsOwogICAgdGhpcy5pbmNsdWRlWERQQ29udGVudCA9IG51bGw7CiAgICB0aGlzLnBhcnQgPSBudWxsOwogIH0KfQpjbGFzcyBQZXJtaXNzaW9ucyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGVybWlzc2lvbnMiLCB0cnVlKTsKICAgIHRoaXMuYWNjZXNzaWJsZUNvbnRlbnQgPSBudWxsOwogICAgdGhpcy5jaGFuZ2UgPSBudWxsOwogICAgdGhpcy5jb250ZW50Q29weSA9IG51bGw7CiAgICB0aGlzLmRvY3VtZW50QXNzZW1ibHkgPSBudWxsOwogICAgdGhpcy5mb3JtRmllbGRGaWxsaW5nID0gbnVsbDsKICAgIHRoaXMubW9kaWZ5QW5ub3RzID0gbnVsbDsKICAgIHRoaXMucGxhaW50ZXh0TWV0YWRhdGEgPSBudWxsOwogICAgdGhpcy5wcmludCA9IG51bGw7CiAgICB0aGlzLnByaW50SGlnaFF1YWxpdHkgPSBudWxsOwogIH0KfQpjbGFzcyBQaWNrVHJheUJ5UERGU2l6ZSBleHRlbmRzIE9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwaWNrVHJheUJ5UERGU2l6ZSIpOwogIH0KfQpjbGFzcyBjb25maWdfUGljdHVyZSBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicGljdHVyZSIpOwogIH0KfQpjbGFzcyBQbGFpbnRleHRNZXRhZGF0YSBleHRlbmRzIE9wdGlvbjAxIHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwbGFpbnRleHRNZXRhZGF0YSIpOwogIH0KfQpjbGFzcyBQcmVzZW5jZSBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicHJlc2VuY2UiLCBbInByZXNlcnZlIiwgImRpc3NvbHZlIiwgImRpc3NvbHZlU3RydWN0dXJlIiwgImlnbm9yZSIsICJyZW1vdmUiXSk7CiAgfQp9CmNsYXNzIFByZXNlbnQgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInByZXNlbnQiLCB0cnVlKTsKICAgIHRoaXMuYmVoYXZpb3JPdmVycmlkZSA9IG51bGw7CiAgICB0aGlzLmNhY2hlID0gbnVsbDsKICAgIHRoaXMuY29tbW9uID0gbnVsbDsKICAgIHRoaXMuY29waWVzID0gbnVsbDsKICAgIHRoaXMuZGVzdGluYXRpb24gPSBudWxsOwogICAgdGhpcy5pbmNyZW1lbnRhbE1lcmdlID0gbnVsbDsKICAgIHRoaXMubGF5b3V0ID0gbnVsbDsKICAgIHRoaXMub3V0cHV0ID0gbnVsbDsKICAgIHRoaXMub3ZlcnByaW50ID0gbnVsbDsKICAgIHRoaXMucGFnaW5hdGlvbiA9IG51bGw7CiAgICB0aGlzLnBhZ2luYXRpb25PdmVycmlkZSA9IG51bGw7CiAgICB0aGlzLnNjcmlwdCA9IG51bGw7CiAgICB0aGlzLnZhbGlkYXRlID0gbnVsbDsKICAgIHRoaXMueGRwID0gbnVsbDsKICAgIHRoaXMuZHJpdmVyID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLmxhYmVsUHJpbnRlciA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy5wY2wgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMucGRmID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnBzID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgICB0aGlzLnN1Ym1pdFVybCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy53ZWJDbGllbnQgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMuenBsID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIFByaW50IGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInByaW50Iik7CiAgfQp9CmNsYXNzIFByaW50SGlnaFF1YWxpdHkgZXh0ZW5kcyBPcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicHJpbnRIaWdoUXVhbGl0eSIpOwogIH0KfQpjbGFzcyBQcmludFNjYWxpbmcgZXh0ZW5kcyBPcHRpb25PYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInByaW50U2NhbGluZyIsIFsiYXBwZGVmYXVsdCIsICJub1NjYWxpbmciXSk7CiAgfQp9CmNsYXNzIFByaW50ZXJOYW1lIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJwcmludGVyTmFtZSIpOwogIH0KfQpjbGFzcyBQcm9kdWNlciBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicHJvZHVjZXIiKTsKICB9Cn0KY2xhc3MgUHMgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInBzIiwgdHJ1ZSk7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLmJhdGNoT3V0cHV0ID0gbnVsbDsKICAgIHRoaXMuZm9udEluZm8gPSBudWxsOwogICAgdGhpcy5qb2cgPSBudWxsOwogICAgdGhpcy5tZWRpdW1JbmZvID0gbnVsbDsKICAgIHRoaXMub3V0cHV0QmluID0gbnVsbDsKICAgIHRoaXMuc3RhcGxlID0gbnVsbDsKICAgIHRoaXMueGRjID0gbnVsbDsKICB9Cn0KY2xhc3MgUmFuZ2UgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJyYW5nZSIpOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIHRoaXNbJGNvbnRlbnRdID0gdGhpc1skY29udGVudF0uc3BsaXQoIiwiLCAyKS5tYXAocmFuZ2UgPT4gcmFuZ2Uuc3BsaXQoIi0iKS5tYXAoeCA9PiBwYXJzZUludCh4LnRyaW0oKSwgMTApKSkuZmlsdGVyKHJhbmdlID0+IHJhbmdlLmV2ZXJ5KHggPT4gIWlzTmFOKHgpKSkubWFwKHJhbmdlID0+IHsKICAgICAgaWYgKHJhbmdlLmxlbmd0aCA9PT0gMSkgewogICAgICAgIHJhbmdlLnB1c2gocmFuZ2VbMF0pOwogICAgICB9CiAgICAgIHJldHVybiByYW5nZTsKICAgIH0pOwogIH0KfQpjbGFzcyBSZWNvcmQgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJyZWNvcmQiKTsKICB9CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzWyRjb250ZW50XSA9IHRoaXNbJGNvbnRlbnRdLnRyaW0oKTsKICAgIGNvbnN0IG4gPSBwYXJzZUludCh0aGlzWyRjb250ZW50XSwgMTApOwogICAgaWYgKCFpc05hTihuKSAmJiBuID49IDApIHsKICAgICAgdGhpc1skY29udGVudF0gPSBuOwogICAgfQogIH0KfQpjbGFzcyBSZWxldmFudCBleHRlbmRzIENvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInJlbGV2YW50Iik7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgdGhpc1skY29udGVudF0gPSB0aGlzWyRjb250ZW50XS50cmltKCkuc3BsaXQoL1xzKy8pOwogIH0KfQpjbGFzcyBSZW5hbWUgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJyZW5hbWUiKTsKICB9CiAgWyRmaW5hbGl6ZV0oKSB7CiAgICB0aGlzWyRjb250ZW50XSA9IHRoaXNbJGNvbnRlbnRdLnRyaW0oKTsKICAgIGlmICh0aGlzWyRjb250ZW50XS50b0xvd2VyQ2FzZSgpLnN0YXJ0c1dpdGgoInhtbCIpIHx8IG5ldyBSZWdFeHAoIltcXHB7TH1fXVtcXHB7TH1cXGQuX1xccHtNfS1dKiIsICJ1IikudGVzdCh0aGlzWyRjb250ZW50XSkpIHsKICAgICAgd2FybigiWEZBIC0gUmVuYW1lOiBpbnZhbGlkIFhGQSBuYW1lIik7CiAgICB9CiAgfQp9CmNsYXNzIFJlbmRlclBvbGljeSBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAicmVuZGVyUG9saWN5IiwgWyJzZXJ2ZXIiLCAiY2xpZW50Il0pOwogIH0KfQpjbGFzcyBSdW5TY3JpcHRzIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJydW5TY3JpcHRzIiwgWyJib3RoIiwgImNsaWVudCIsICJub25lIiwgInNlcnZlciJdKTsKICB9Cn0KY2xhc3MgY29uZmlnX1NjcmlwdCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic2NyaXB0IiwgdHJ1ZSk7CiAgICB0aGlzLmN1cnJlbnRQYWdlID0gbnVsbDsKICAgIHRoaXMuZXhjbHVkZSA9IG51bGw7CiAgICB0aGlzLnJ1blNjcmlwdHMgPSBudWxsOwogIH0KfQpjbGFzcyBTY3JpcHRNb2RlbCBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic2NyaXB0TW9kZWwiLCBbIlhGQSIsICJub25lIl0pOwogIH0KfQpjbGFzcyBTZXZlcml0eSBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic2V2ZXJpdHkiLCBbImlnbm9yZSIsICJlcnJvciIsICJpbmZvcm1hdGlvbiIsICJ0cmFjZSIsICJ3YXJuaW5nIl0pOwogIH0KfQpjbGFzcyBTaWxlbnRQcmludCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic2lsZW50UHJpbnQiLCB0cnVlKTsKICAgIHRoaXMuYWRkU2lsZW50UHJpbnQgPSBudWxsOwogICAgdGhpcy5wcmludGVyTmFtZSA9IG51bGw7CiAgfQp9CmNsYXNzIFN0YXBsZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3RhcGxlIik7CiAgICB0aGlzLm1vZGUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5tb2RlLCBbInVzZVByaW50ZXJTZXR0aW5nIiwgIm9uIiwgIm9mZiJdKTsKICB9Cn0KY2xhc3MgU3RhcnROb2RlIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJzdGFydE5vZGUiKTsKICB9Cn0KY2xhc3MgU3RhcnRQYWdlIGV4dGVuZHMgSW50ZWdlck9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3RhcnRQYWdlIiwgMCwgbiA9PiB0cnVlKTsKICB9Cn0KY2xhc3MgU3VibWl0Rm9ybWF0IGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJzdWJtaXRGb3JtYXQiLCBbImh0bWwiLCAiZGVsZWdhdGUiLCAiZmRmIiwgInhtbCIsICJwZGYiXSk7CiAgfQp9CmNsYXNzIFN1Ym1pdFVybCBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3VibWl0VXJsIik7CiAgfQp9CmNsYXNzIFN1YnNldEJlbG93IGV4dGVuZHMgSW50ZWdlck9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3Vic2V0QmVsb3ciLCAxMDAsIG4gPT4gbiA+PSAwICYmIG4gPD0gMTAwKTsKICB9Cn0KY2xhc3MgU3VwcHJlc3NCYW5uZXIgZXh0ZW5kcyBPcHRpb24wMSB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAic3VwcHJlc3NCYW5uZXIiKTsKICB9Cn0KY2xhc3MgVGFnZ2VkIGV4dGVuZHMgT3B0aW9uMDEgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInRhZ2dlZCIpOwogIH0KfQpjbGFzcyBjb25maWdfVGVtcGxhdGUgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInRlbXBsYXRlIiwgdHJ1ZSk7CiAgICB0aGlzLmJhc2UgPSBudWxsOwogICAgdGhpcy5yZWxldmFudCA9IG51bGw7CiAgICB0aGlzLnN0YXJ0UGFnZSA9IG51bGw7CiAgICB0aGlzLnVyaSA9IG51bGw7CiAgICB0aGlzLnhzbCA9IG51bGw7CiAgfQp9CmNsYXNzIFRocmVzaG9sZCBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidGhyZXNob2xkIiwgWyJ0cmFjZSIsICJlcnJvciIsICJpbmZvcm1hdGlvbiIsICJ3YXJuaW5nIl0pOwogIH0KfQpjbGFzcyBUbyBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidG8iLCBbIm51bGwiLCAibWVtb3J5IiwgInN0ZGVyciIsICJzdGRvdXQiLCAic3lzdGVtIiwgInVyaSJdKTsKICB9Cn0KY2xhc3MgVGVtcGxhdGVDYWNoZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidGVtcGxhdGVDYWNoZSIpOwogICAgdGhpcy5tYXhFbnRyaWVzID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMubWF4RW50cmllcywKICAgICAgZGVmYXVsdFZhbHVlOiA1LAogICAgICB2YWxpZGF0ZTogbiA9PiBuID49IDAKICAgIH0pOwogIH0KfQpjbGFzcyBUcmFjZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidHJhY2UiLCB0cnVlKTsKICAgIHRoaXMuYXJlYSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBUcmFuc2Zvcm0gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInRyYW5zZm9ybSIsIHRydWUpOwogICAgdGhpcy5ncm91cFBhcmVudCA9IG51bGw7CiAgICB0aGlzLmlmRW1wdHkgPSBudWxsOwogICAgdGhpcy5uYW1lQXR0ciA9IG51bGw7CiAgICB0aGlzLnBpY3R1cmUgPSBudWxsOwogICAgdGhpcy5wcmVzZW5jZSA9IG51bGw7CiAgICB0aGlzLnJlbmFtZSA9IG51bGw7CiAgICB0aGlzLndoaXRlc3BhY2UgPSBudWxsOwogIH0KfQpjbGFzcyBUeXBlIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ0eXBlIiwgWyJub25lIiwgImFzY2lpODUiLCAiYXNjaWlIZXgiLCAiY2NpdHRmYXgiLCAiZmxhdGUiLCAibHp3IiwgInJ1bkxlbmd0aCIsICJuYXRpdmUiLCAieGRwIiwgIm1lcmdlZFhEUCJdKTsKICB9Cn0KY2xhc3MgVXJpIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ1cmkiKTsKICB9Cn0KY2xhc3MgY29uZmlnX1ZhbGlkYXRlIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ2YWxpZGF0ZSIsIFsicHJlU3VibWl0IiwgInByZVByaW50IiwgInByZUV4ZWN1dGUiLCAicHJlU2F2ZSJdKTsKICB9Cn0KY2xhc3MgVmFsaWRhdGVBcHByb3ZhbFNpZ25hdHVyZXMgZXh0ZW5kcyBDb250ZW50T2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ2YWxpZGF0ZUFwcHJvdmFsU2lnbmF0dXJlcyIpOwogIH0KICBbJGZpbmFsaXplXSgpIHsKICAgIHRoaXNbJGNvbnRlbnRdID0gdGhpc1skY29udGVudF0udHJpbSgpLnNwbGl0KC9ccysvKS5maWx0ZXIoeCA9PiBbImRvY1JlYWR5IiwgInBvc3RTaWduIl0uaW5jbHVkZXMoeCkpOwogIH0KfQpjbGFzcyBWYWxpZGF0aW9uTWVzc2FnaW5nIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ2YWxpZGF0aW9uTWVzc2FnaW5nIiwgWyJhbGxNZXNzYWdlc0luZGl2aWR1YWxseSIsICJhbGxNZXNzYWdlc1RvZ2V0aGVyIiwgImZpcnN0TWVzc2FnZU9ubHkiLCAibm9NZXNzYWdlcyJdKTsKICB9Cn0KY2xhc3MgVmVyc2lvbiBleHRlbmRzIE9wdGlvbk9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidmVyc2lvbiIsIFsiMS43IiwgIjEuNiIsICIxLjUiLCAiMS40IiwgIjEuMyIsICIxLjIiXSk7CiAgfQp9CmNsYXNzIFZlcnNpb25Db250cm9sIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJWZXJzaW9uQ29udHJvbCIpOwogICAgdGhpcy5vdXRwdXRCZWxvdyA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLm91dHB1dEJlbG93LCBbIndhcm4iLCAiZXJyb3IiLCAidXBkYXRlIl0pOwogICAgdGhpcy5zb3VyY2VBYm92ZSA9IGdldFN0cmluZ09wdGlvbihhdHRyaWJ1dGVzLnNvdXJjZUFib3ZlLCBbIndhcm4iLCAiZXJyb3IiXSk7CiAgICB0aGlzLnNvdXJjZUJlbG93ID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMuc291cmNlQmVsb3csIFsidXBkYXRlIiwgIm1haW50YWluIl0pOwogIH0KfQpjbGFzcyBWaWV3ZXJQcmVmZXJlbmNlcyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAidmlld2VyUHJlZmVyZW5jZXMiLCB0cnVlKTsKICAgIHRoaXMuQURCRV9KU0NvbnNvbGUgPSBudWxsOwogICAgdGhpcy5BREJFX0pTRGVidWdnZXIgPSBudWxsOwogICAgdGhpcy5hZGRWaWV3ZXJQcmVmZXJlbmNlcyA9IG51bGw7CiAgICB0aGlzLmR1cGxleE9wdGlvbiA9IG51bGw7CiAgICB0aGlzLmVuZm9yY2UgPSBudWxsOwogICAgdGhpcy5udW1iZXJPZkNvcGllcyA9IG51bGw7CiAgICB0aGlzLnBhZ2VSYW5nZSA9IG51bGw7CiAgICB0aGlzLnBpY2tUcmF5QnlQREZTaXplID0gbnVsbDsKICAgIHRoaXMucHJpbnRTY2FsaW5nID0gbnVsbDsKICB9Cn0KY2xhc3MgV2ViQ2xpZW50IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ3ZWJDbGllbnQiLCB0cnVlKTsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSA/IGF0dHJpYnV0ZXMubmFtZS50cmltKCkgOiAiIjsKICAgIHRoaXMuZm9udEluZm8gPSBudWxsOwogICAgdGhpcy54ZGMgPSBudWxsOwogIH0KfQpjbGFzcyBXaGl0ZXNwYWNlIGV4dGVuZHMgT3B0aW9uT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05GSUdfTlNfSUQsICJ3aGl0ZXNwYWNlIiwgWyJwcmVzZXJ2ZSIsICJsdHJpbSIsICJub3JtYWxpemUiLCAicnRyaW0iLCAidHJpbSJdKTsKICB9Cn0KY2xhc3MgV2luZG93IGV4dGVuZHMgQ29udGVudE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAid2luZG93Iik7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgY29uc3QgcGFpciA9IHRoaXNbJGNvbnRlbnRdLnNwbGl0KCIsIiwgMikubWFwKHggPT4gcGFyc2VJbnQoeC50cmltKCksIDEwKSk7CiAgICBpZiAocGFpci5zb21lKHggPT4gaXNOYU4oeCkpKSB7CiAgICAgIHRoaXNbJGNvbnRlbnRdID0gWzAsIDBdOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAocGFpci5sZW5ndGggPT09IDEpIHsKICAgICAgcGFpci5wdXNoKHBhaXJbMF0pOwogICAgfQogICAgdGhpc1skY29udGVudF0gPSBwYWlyOwogIH0KfQpjbGFzcyBYZGMgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInhkYyIsIHRydWUpOwogICAgdGhpcy51cmkgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMueHNsID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIFhkcCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAieGRwIiwgdHJ1ZSk7CiAgICB0aGlzLnBhY2tldHMgPSBudWxsOwogIH0KfQpjbGFzcyBYc2wgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTkZJR19OU19JRCwgInhzbCIsIHRydWUpOwogICAgdGhpcy5kZWJ1ZyA9IG51bGw7CiAgICB0aGlzLnVyaSA9IG51bGw7CiAgfQp9CmNsYXNzIFpwbCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09ORklHX05TX0lELCAienBsIiwgdHJ1ZSk7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgPyBhdHRyaWJ1dGVzLm5hbWUudHJpbSgpIDogIiI7CiAgICB0aGlzLmJhdGNoT3V0cHV0ID0gbnVsbDsKICAgIHRoaXMuZmxpcExhYmVsID0gbnVsbDsKICAgIHRoaXMuZm9udEluZm8gPSBudWxsOwogICAgdGhpcy54ZGMgPSBudWxsOwogIH0KfQpjbGFzcyBDb25maWdOYW1lc3BhY2UgewogIHN0YXRpYyBbJGJ1aWxkWEZBT2JqZWN0XShuYW1lLCBhdHRyaWJ1dGVzKSB7CiAgICBpZiAoQ29uZmlnTmFtZXNwYWNlLmhhc093blByb3BlcnR5KG5hbWUpKSB7CiAgICAgIHJldHVybiBDb25maWdOYW1lc3BhY2VbbmFtZV0oYXR0cmlidXRlcyk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBzdGF0aWMgYWNyb2JhdChhdHRycykgewogICAgcmV0dXJuIG5ldyBBY3JvYmF0KGF0dHJzKTsKICB9CiAgc3RhdGljIGFjcm9iYXQ3KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEFjcm9iYXQ3KGF0dHJzKTsKICB9CiAgc3RhdGljIEFEQkVfSlNDb25zb2xlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEFEQkVfSlNDb25zb2xlKGF0dHJzKTsKICB9CiAgc3RhdGljIEFEQkVfSlNEZWJ1Z2dlcihhdHRycykgewogICAgcmV0dXJuIG5ldyBBREJFX0pTRGVidWdnZXIoYXR0cnMpOwogIH0KICBzdGF0aWMgYWRkU2lsZW50UHJpbnQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQWRkU2lsZW50UHJpbnQoYXR0cnMpOwogIH0KICBzdGF0aWMgYWRkVmlld2VyUHJlZmVyZW5jZXMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQWRkVmlld2VyUHJlZmVyZW5jZXMoYXR0cnMpOwogIH0KICBzdGF0aWMgYWRqdXN0RGF0YShhdHRycykgewogICAgcmV0dXJuIG5ldyBBZGp1c3REYXRhKGF0dHJzKTsKICB9CiAgc3RhdGljIGFkb2JlRXh0ZW5zaW9uTGV2ZWwoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQWRvYmVFeHRlbnNpb25MZXZlbChhdHRycyk7CiAgfQogIHN0YXRpYyBhZ2VudChhdHRycykgewogICAgcmV0dXJuIG5ldyBBZ2VudChhdHRycyk7CiAgfQogIHN0YXRpYyBhbHdheXNFbWJlZChhdHRycykgewogICAgcmV0dXJuIG5ldyBBbHdheXNFbWJlZChhdHRycyk7CiAgfQogIHN0YXRpYyBhbWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQW1kKGF0dHJzKTsKICB9CiAgc3RhdGljIGFyZWEoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgY29uZmlnX0FyZWEoYXR0cnMpOwogIH0KICBzdGF0aWMgYXR0cmlidXRlcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBBdHRyaWJ1dGVzKGF0dHJzKTsKICB9CiAgc3RhdGljIGF1dG9TYXZlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEF1dG9TYXZlKGF0dHJzKTsKICB9CiAgc3RhdGljIGJhc2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQmFzZShhdHRycyk7CiAgfQogIHN0YXRpYyBiYXRjaE91dHB1dChhdHRycykgewogICAgcmV0dXJuIG5ldyBCYXRjaE91dHB1dChhdHRycyk7CiAgfQogIHN0YXRpYyBiZWhhdmlvck92ZXJyaWRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEJlaGF2aW9yT3ZlcnJpZGUoYXR0cnMpOwogIH0KICBzdGF0aWMgY2FjaGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ2FjaGUoYXR0cnMpOwogIH0KICBzdGF0aWMgY2hhbmdlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENoYW5nZShhdHRycyk7CiAgfQogIHN0YXRpYyBjb21tb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29tbW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGNvbXByZXNzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbXByZXNzKGF0dHJzKTsKICB9CiAgc3RhdGljIGNvbXByZXNzTG9naWNhbFN0cnVjdHVyZShhdHRycykgewogICAgcmV0dXJuIG5ldyBDb21wcmVzc0xvZ2ljYWxTdHJ1Y3R1cmUoYXR0cnMpOwogIH0KICBzdGF0aWMgY29tcHJlc3NPYmplY3RTdHJlYW0oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29tcHJlc3NPYmplY3RTdHJlYW0oYXR0cnMpOwogIH0KICBzdGF0aWMgY29tcHJlc3Npb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29tcHJlc3Npb24oYXR0cnMpOwogIH0KICBzdGF0aWMgY29uZmlnKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbmZpZyhhdHRycyk7CiAgfQogIHN0YXRpYyBjb25mb3JtYW5jZShhdHRycykgewogICAgcmV0dXJuIG5ldyBDb25mb3JtYW5jZShhdHRycyk7CiAgfQogIHN0YXRpYyBjb250ZW50Q29weShhdHRycykgewogICAgcmV0dXJuIG5ldyBDb250ZW50Q29weShhdHRycyk7CiAgfQogIHN0YXRpYyBjb3BpZXMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ29waWVzKGF0dHJzKTsKICB9CiAgc3RhdGljIGNyZWF0b3IoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ3JlYXRvcihhdHRycyk7CiAgfQogIHN0YXRpYyBjdXJyZW50UGFnZShhdHRycykgewogICAgcmV0dXJuIG5ldyBDdXJyZW50UGFnZShhdHRycyk7CiAgfQogIHN0YXRpYyBkYXRhKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERhdGEoYXR0cnMpOwogIH0KICBzdGF0aWMgZGVidWcoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRGVidWcoYXR0cnMpOwogIH0KICBzdGF0aWMgZGVmYXVsdFR5cGVmYWNlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERlZmF1bHRUeXBlZmFjZShhdHRycyk7CiAgfQogIHN0YXRpYyBkZXN0aW5hdGlvbihhdHRycykgewogICAgcmV0dXJuIG5ldyBEZXN0aW5hdGlvbihhdHRycyk7CiAgfQogIHN0YXRpYyBkb2N1bWVudEFzc2VtYmx5KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERvY3VtZW50QXNzZW1ibHkoYXR0cnMpOwogIH0KICBzdGF0aWMgZHJpdmVyKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERyaXZlcihhdHRycyk7CiAgfQogIHN0YXRpYyBkdXBsZXhPcHRpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRHVwbGV4T3B0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIGR5bmFtaWNSZW5kZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRHluYW1pY1JlbmRlcihhdHRycyk7CiAgfQogIHN0YXRpYyBlbWJlZChhdHRycykgewogICAgcmV0dXJuIG5ldyBFbWJlZChhdHRycyk7CiAgfQogIHN0YXRpYyBlbmNyeXB0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IGNvbmZpZ19FbmNyeXB0KGF0dHJzKTsKICB9CiAgc3RhdGljIGVuY3J5cHRpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgY29uZmlnX0VuY3J5cHRpb24oYXR0cnMpOwogIH0KICBzdGF0aWMgZW5jcnlwdGlvbkxldmVsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVuY3J5cHRpb25MZXZlbChhdHRycyk7CiAgfQogIHN0YXRpYyBlbmZvcmNlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVuZm9yY2UoYXR0cnMpOwogIH0KICBzdGF0aWMgZXF1YXRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVxdWF0ZShhdHRycyk7CiAgfQogIHN0YXRpYyBlcXVhdGVSYW5nZShhdHRycykgewogICAgcmV0dXJuIG5ldyBFcXVhdGVSYW5nZShhdHRycyk7CiAgfQogIHN0YXRpYyBleGNsdWRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEV4Y2x1ZGUoYXR0cnMpOwogIH0KICBzdGF0aWMgZXhjbHVkZU5TKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEV4Y2x1ZGVOUyhhdHRycyk7CiAgfQogIHN0YXRpYyBmbGlwTGFiZWwoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRmxpcExhYmVsKGF0dHJzKTsKICB9CiAgc3RhdGljIGZvbnRJbmZvKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IGNvbmZpZ19Gb250SW5mbyhhdHRycyk7CiAgfQogIHN0YXRpYyBmb3JtRmllbGRGaWxsaW5nKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEZvcm1GaWVsZEZpbGxpbmcoYXR0cnMpOwogIH0KICBzdGF0aWMgZ3JvdXBQYXJlbnQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgR3JvdXBQYXJlbnQoYXR0cnMpOwogIH0KICBzdGF0aWMgaWZFbXB0eShhdHRycykgewogICAgcmV0dXJuIG5ldyBJZkVtcHR5KGF0dHJzKTsKICB9CiAgc3RhdGljIGluY2x1ZGVYRFBDb250ZW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEluY2x1ZGVYRFBDb250ZW50KGF0dHJzKTsKICB9CiAgc3RhdGljIGluY3JlbWVudGFsTG9hZChhdHRycykgewogICAgcmV0dXJuIG5ldyBJbmNyZW1lbnRhbExvYWQoYXR0cnMpOwogIH0KICBzdGF0aWMgaW5jcmVtZW50YWxNZXJnZShhdHRycykgewogICAgcmV0dXJuIG5ldyBJbmNyZW1lbnRhbE1lcmdlKGF0dHJzKTsKICB9CiAgc3RhdGljIGludGVyYWN0aXZlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEludGVyYWN0aXZlKGF0dHJzKTsKICB9CiAgc3RhdGljIGpvZyhhdHRycykgewogICAgcmV0dXJuIG5ldyBKb2coYXR0cnMpOwogIH0KICBzdGF0aWMgbGFiZWxQcmludGVyKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IExhYmVsUHJpbnRlcihhdHRycyk7CiAgfQogIHN0YXRpYyBsYXlvdXQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTGF5b3V0KGF0dHJzKTsKICB9CiAgc3RhdGljIGxldmVsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IExldmVsKGF0dHJzKTsKICB9CiAgc3RhdGljIGxpbmVhcml6ZWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTGluZWFyaXplZChhdHRycyk7CiAgfQogIHN0YXRpYyBsb2NhbGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTG9jYWxlKGF0dHJzKTsKICB9CiAgc3RhdGljIGxvY2FsZVNldChhdHRycykgewogICAgcmV0dXJuIG5ldyBMb2NhbGVTZXQoYXR0cnMpOwogIH0KICBzdGF0aWMgbG9nKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IExvZyhhdHRycyk7CiAgfQogIHN0YXRpYyBtYXAoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTWFwRWxlbWVudChhdHRycyk7CiAgfQogIHN0YXRpYyBtZWRpdW1JbmZvKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE1lZGl1bUluZm8oYXR0cnMpOwogIH0KICBzdGF0aWMgbWVzc2FnZShhdHRycykgewogICAgcmV0dXJuIG5ldyBjb25maWdfTWVzc2FnZShhdHRycyk7CiAgfQogIHN0YXRpYyBtZXNzYWdpbmcoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTWVzc2FnaW5nKGF0dHJzKTsKICB9CiAgc3RhdGljIG1vZGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTW9kZShhdHRycyk7CiAgfQogIHN0YXRpYyBtb2RpZnlBbm5vdHMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTW9kaWZ5QW5ub3RzKGF0dHJzKTsKICB9CiAgc3RhdGljIG1zZ0lkKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE1zZ0lkKGF0dHJzKTsKICB9CiAgc3RhdGljIG5hbWVBdHRyKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE5hbWVBdHRyKGF0dHJzKTsKICB9CiAgc3RhdGljIG5ldmVyRW1iZWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTmV2ZXJFbWJlZChhdHRycyk7CiAgfQogIHN0YXRpYyBudW1iZXJPZkNvcGllcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBOdW1iZXJPZkNvcGllcyhhdHRycyk7CiAgfQogIHN0YXRpYyBvcGVuQWN0aW9uKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE9wZW5BY3Rpb24oYXR0cnMpOwogIH0KICBzdGF0aWMgb3V0cHV0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE91dHB1dChhdHRycyk7CiAgfQogIHN0YXRpYyBvdXRwdXRCaW4oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgT3V0cHV0QmluKGF0dHJzKTsKICB9CiAgc3RhdGljIG91dHB1dFhTTChhdHRycykgewogICAgcmV0dXJuIG5ldyBPdXRwdXRYU0woYXR0cnMpOwogIH0KICBzdGF0aWMgb3ZlcnByaW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE92ZXJwcmludChhdHRycyk7CiAgfQogIHN0YXRpYyBwYWNrZXRzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBhY2tldHMoYXR0cnMpOwogIH0KICBzdGF0aWMgcGFnZU9mZnNldChhdHRycykgewogICAgcmV0dXJuIG5ldyBQYWdlT2Zmc2V0KGF0dHJzKTsKICB9CiAgc3RhdGljIHBhZ2VSYW5nZShhdHRycykgewogICAgcmV0dXJuIG5ldyBQYWdlUmFuZ2UoYXR0cnMpOwogIH0KICBzdGF0aWMgcGFnaW5hdGlvbihhdHRycykgewogICAgcmV0dXJuIG5ldyBQYWdpbmF0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIHBhZ2luYXRpb25PdmVycmlkZShhdHRycykgewogICAgcmV0dXJuIG5ldyBQYWdpbmF0aW9uT3ZlcnJpZGUoYXR0cnMpOwogIH0KICBzdGF0aWMgcGFydChhdHRycykgewogICAgcmV0dXJuIG5ldyBQYXJ0KGF0dHJzKTsKICB9CiAgc3RhdGljIHBjbChhdHRycykgewogICAgcmV0dXJuIG5ldyBQY2woYXR0cnMpOwogIH0KICBzdGF0aWMgcGRmKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBkZihhdHRycyk7CiAgfQogIHN0YXRpYyBwZGZhKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFBkZmEoYXR0cnMpOwogIH0KICBzdGF0aWMgcGVybWlzc2lvbnMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGVybWlzc2lvbnMoYXR0cnMpOwogIH0KICBzdGF0aWMgcGlja1RyYXlCeVBERlNpemUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUGlja1RyYXlCeVBERlNpemUoYXR0cnMpOwogIH0KICBzdGF0aWMgcGljdHVyZShhdHRycykgewogICAgcmV0dXJuIG5ldyBjb25maWdfUGljdHVyZShhdHRycyk7CiAgfQogIHN0YXRpYyBwbGFpbnRleHRNZXRhZGF0YShhdHRycykgewogICAgcmV0dXJuIG5ldyBQbGFpbnRleHRNZXRhZGF0YShhdHRycyk7CiAgfQogIHN0YXRpYyBwcmVzZW5jZShhdHRycykgewogICAgcmV0dXJuIG5ldyBQcmVzZW5jZShhdHRycyk7CiAgfQogIHN0YXRpYyBwcmVzZW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFByZXNlbnQoYXR0cnMpOwogIH0KICBzdGF0aWMgcHJpbnQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUHJpbnQoYXR0cnMpOwogIH0KICBzdGF0aWMgcHJpbnRIaWdoUXVhbGl0eShhdHRycykgewogICAgcmV0dXJuIG5ldyBQcmludEhpZ2hRdWFsaXR5KGF0dHJzKTsKICB9CiAgc3RhdGljIHByaW50U2NhbGluZyhhdHRycykgewogICAgcmV0dXJuIG5ldyBQcmludFNjYWxpbmcoYXR0cnMpOwogIH0KICBzdGF0aWMgcHJpbnRlck5hbWUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUHJpbnRlck5hbWUoYXR0cnMpOwogIH0KICBzdGF0aWMgcHJvZHVjZXIoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUHJvZHVjZXIoYXR0cnMpOwogIH0KICBzdGF0aWMgcHMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUHMoYXR0cnMpOwogIH0KICBzdGF0aWMgcmFuZ2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmFuZ2UoYXR0cnMpOwogIH0KICBzdGF0aWMgcmVjb3JkKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFJlY29yZChhdHRycyk7CiAgfQogIHN0YXRpYyByZWxldmFudChhdHRycykgewogICAgcmV0dXJuIG5ldyBSZWxldmFudChhdHRycyk7CiAgfQogIHN0YXRpYyByZW5hbWUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgUmVuYW1lKGF0dHJzKTsKICB9CiAgc3RhdGljIHJlbmRlclBvbGljeShhdHRycykgewogICAgcmV0dXJuIG5ldyBSZW5kZXJQb2xpY3koYXR0cnMpOwogIH0KICBzdGF0aWMgcnVuU2NyaXB0cyhhdHRycykgewogICAgcmV0dXJuIG5ldyBSdW5TY3JpcHRzKGF0dHJzKTsKICB9CiAgc3RhdGljIHNjcmlwdChhdHRycykgewogICAgcmV0dXJuIG5ldyBjb25maWdfU2NyaXB0KGF0dHJzKTsKICB9CiAgc3RhdGljIHNjcmlwdE1vZGVsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNjcmlwdE1vZGVsKGF0dHJzKTsKICB9CiAgc3RhdGljIHNldmVyaXR5KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNldmVyaXR5KGF0dHJzKTsKICB9CiAgc3RhdGljIHNpbGVudFByaW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFNpbGVudFByaW50KGF0dHJzKTsKICB9CiAgc3RhdGljIHN0YXBsZShhdHRycykgewogICAgcmV0dXJuIG5ldyBTdGFwbGUoYXR0cnMpOwogIH0KICBzdGF0aWMgc3RhcnROb2RlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN0YXJ0Tm9kZShhdHRycyk7CiAgfQogIHN0YXRpYyBzdGFydFBhZ2UoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU3RhcnRQYWdlKGF0dHJzKTsKICB9CiAgc3RhdGljIHN1Ym1pdEZvcm1hdChhdHRycykgewogICAgcmV0dXJuIG5ldyBTdWJtaXRGb3JtYXQoYXR0cnMpOwogIH0KICBzdGF0aWMgc3VibWl0VXJsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFN1Ym1pdFVybChhdHRycyk7CiAgfQogIHN0YXRpYyBzdWJzZXRCZWxvdyhhdHRycykgewogICAgcmV0dXJuIG5ldyBTdWJzZXRCZWxvdyhhdHRycyk7CiAgfQogIHN0YXRpYyBzdXBwcmVzc0Jhbm5lcihhdHRycykgewogICAgcmV0dXJuIG5ldyBTdXBwcmVzc0Jhbm5lcihhdHRycyk7CiAgfQogIHN0YXRpYyB0YWdnZWQoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVGFnZ2VkKGF0dHJzKTsKICB9CiAgc3RhdGljIHRlbXBsYXRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IGNvbmZpZ19UZW1wbGF0ZShhdHRycyk7CiAgfQogIHN0YXRpYyB0ZW1wbGF0ZUNhY2hlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFRlbXBsYXRlQ2FjaGUoYXR0cnMpOwogIH0KICBzdGF0aWMgdGhyZXNob2xkKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFRocmVzaG9sZChhdHRycyk7CiAgfQogIHN0YXRpYyB0byhhdHRycykgewogICAgcmV0dXJuIG5ldyBUbyhhdHRycyk7CiAgfQogIHN0YXRpYyB0cmFjZShhdHRycykgewogICAgcmV0dXJuIG5ldyBUcmFjZShhdHRycyk7CiAgfQogIHN0YXRpYyB0cmFuc2Zvcm0oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVHJhbnNmb3JtKGF0dHJzKTsKICB9CiAgc3RhdGljIHR5cGUoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVHlwZShhdHRycyk7CiAgfQogIHN0YXRpYyB1cmkoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVXJpKGF0dHJzKTsKICB9CiAgc3RhdGljIHZhbGlkYXRlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IGNvbmZpZ19WYWxpZGF0ZShhdHRycyk7CiAgfQogIHN0YXRpYyB2YWxpZGF0ZUFwcHJvdmFsU2lnbmF0dXJlcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBWYWxpZGF0ZUFwcHJvdmFsU2lnbmF0dXJlcyhhdHRycyk7CiAgfQogIHN0YXRpYyB2YWxpZGF0aW9uTWVzc2FnaW5nKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFZhbGlkYXRpb25NZXNzYWdpbmcoYXR0cnMpOwogIH0KICBzdGF0aWMgdmVyc2lvbihhdHRycykgewogICAgcmV0dXJuIG5ldyBWZXJzaW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIHZlcnNpb25Db250cm9sKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFZlcnNpb25Db250cm9sKGF0dHJzKTsKICB9CiAgc3RhdGljIHZpZXdlclByZWZlcmVuY2VzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFZpZXdlclByZWZlcmVuY2VzKGF0dHJzKTsKICB9CiAgc3RhdGljIHdlYkNsaWVudChhdHRycykgewogICAgcmV0dXJuIG5ldyBXZWJDbGllbnQoYXR0cnMpOwogIH0KICBzdGF0aWMgd2hpdGVzcGFjZShhdHRycykgewogICAgcmV0dXJuIG5ldyBXaGl0ZXNwYWNlKGF0dHJzKTsKICB9CiAgc3RhdGljIHdpbmRvdyhhdHRycykgewogICAgcmV0dXJuIG5ldyBXaW5kb3coYXR0cnMpOwogIH0KICBzdGF0aWMgeGRjKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFhkYyhhdHRycyk7CiAgfQogIHN0YXRpYyB4ZHAoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgWGRwKGF0dHJzKTsKICB9CiAgc3RhdGljIHhzbChhdHRycykgewogICAgcmV0dXJuIG5ldyBYc2woYXR0cnMpOwogIH0KICBzdGF0aWMgenBsKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFpwbChhdHRycyk7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEvY29ubmVjdGlvbl9zZXQuanMKCgpjb25zdCBDT05ORUNUSU9OX1NFVF9OU19JRCA9IE5hbWVzcGFjZUlkcy5jb25uZWN0aW9uU2V0LmlkOwpjbGFzcyBDb25uZWN0aW9uU2V0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgImNvbm5lY3Rpb25TZXQiLCB0cnVlKTsKICAgIHRoaXMud3NkbENvbm5lY3Rpb24gPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICAgIHRoaXMueG1sQ29ubmVjdGlvbiA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy54c2RDb25uZWN0aW9uID0gbmV3IFhGQU9iamVjdEFycmF5KCk7CiAgfQp9CmNsYXNzIEVmZmVjdGl2ZUlucHV0UG9saWN5IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgImVmZmVjdGl2ZUlucHV0UG9saWN5Iik7CiAgICB0aGlzLmlkID0gYXR0cmlidXRlcy5pZCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXNlID0gYXR0cmlidXRlcy51c2UgfHwgIiI7CiAgICB0aGlzLnVzZWhyZWYgPSBhdHRyaWJ1dGVzLnVzZWhyZWYgfHwgIiI7CiAgfQp9CmNsYXNzIEVmZmVjdGl2ZU91dHB1dFBvbGljeSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJlZmZlY3RpdmVPdXRwdXRQb2xpY3kiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgT3BlcmF0aW9uIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgIm9wZXJhdGlvbiIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLmlucHV0ID0gYXR0cmlidXRlcy5pbnB1dCB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMub3V0cHV0ID0gYXR0cmlidXRlcy5vdXRwdXQgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBSb290RWxlbWVudCBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJyb290RWxlbWVudCIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBTb2FwQWN0aW9uIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgInNvYXBBY3Rpb24iKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgU29hcEFkZHJlc3MgZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTk5FQ1RJT05fU0VUX05TX0lELCAic29hcEFkZHJlc3MiKTsKICAgIHRoaXMuaWQgPSBhdHRyaWJ1dGVzLmlkIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy51c2UgPSBhdHRyaWJ1dGVzLnVzZSB8fCAiIjsKICAgIHRoaXMudXNlaHJlZiA9IGF0dHJpYnV0ZXMudXNlaHJlZiB8fCAiIjsKICB9Cn0KY2xhc3MgY29ubmVjdGlvbl9zZXRfVXJpIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihDT05ORUNUSU9OX1NFVF9OU19JRCwgInVyaSIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBXc2RsQWRkcmVzcyBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJ3c2RsQWRkcmVzcyIpOwogICAgdGhpcy5pZCA9IGF0dHJpYnV0ZXMuaWQgfHwgIiI7CiAgICB0aGlzLm5hbWUgPSBhdHRyaWJ1dGVzLm5hbWUgfHwgIiI7CiAgICB0aGlzLnVzZSA9IGF0dHJpYnV0ZXMudXNlIHx8ICIiOwogICAgdGhpcy51c2VocmVmID0gYXR0cmlidXRlcy51c2VocmVmIHx8ICIiOwogIH0KfQpjbGFzcyBXc2RsQ29ubmVjdGlvbiBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJ3c2RsQ29ubmVjdGlvbiIsIHRydWUpOwogICAgdGhpcy5kYXRhRGVzY3JpcHRpb24gPSBhdHRyaWJ1dGVzLmRhdGFEZXNjcmlwdGlvbiB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMuZWZmZWN0aXZlSW5wdXRQb2xpY3kgPSBudWxsOwogICAgdGhpcy5lZmZlY3RpdmVPdXRwdXRQb2xpY3kgPSBudWxsOwogICAgdGhpcy5vcGVyYXRpb24gPSBudWxsOwogICAgdGhpcy5zb2FwQWN0aW9uID0gbnVsbDsKICAgIHRoaXMuc29hcEFkZHJlc3MgPSBudWxsOwogICAgdGhpcy53c2RsQWRkcmVzcyA9IG51bGw7CiAgfQp9CmNsYXNzIFhtbENvbm5lY3Rpb24gZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKENPTk5FQ1RJT05fU0VUX05TX0lELCAieG1sQ29ubmVjdGlvbiIsIHRydWUpOwogICAgdGhpcy5kYXRhRGVzY3JpcHRpb24gPSBhdHRyaWJ1dGVzLmRhdGFEZXNjcmlwdGlvbiB8fCAiIjsKICAgIHRoaXMubmFtZSA9IGF0dHJpYnV0ZXMubmFtZSB8fCAiIjsKICAgIHRoaXMudXJpID0gbnVsbDsKICB9Cn0KY2xhc3MgWHNkQ29ubmVjdGlvbiBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoQ09OTkVDVElPTl9TRVRfTlNfSUQsICJ4c2RDb25uZWN0aW9uIiwgdHJ1ZSk7CiAgICB0aGlzLmRhdGFEZXNjcmlwdGlvbiA9IGF0dHJpYnV0ZXMuZGF0YURlc2NyaXB0aW9uIHx8ICIiOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHx8ICIiOwogICAgdGhpcy5yb290RWxlbWVudCA9IG51bGw7CiAgICB0aGlzLnVyaSA9IG51bGw7CiAgfQp9CmNsYXNzIENvbm5lY3Rpb25TZXROYW1lc3BhY2UgewogIHN0YXRpYyBbJGJ1aWxkWEZBT2JqZWN0XShuYW1lLCBhdHRyaWJ1dGVzKSB7CiAgICBpZiAoQ29ubmVjdGlvblNldE5hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICByZXR1cm4gQ29ubmVjdGlvblNldE5hbWVzcGFjZVtuYW1lXShhdHRyaWJ1dGVzKTsKICAgIH0KICAgIHJldHVybiB1bmRlZmluZWQ7CiAgfQogIHN0YXRpYyBjb25uZWN0aW9uU2V0KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENvbm5lY3Rpb25TZXQoYXR0cnMpOwogIH0KICBzdGF0aWMgZWZmZWN0aXZlSW5wdXRQb2xpY3koYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRWZmZWN0aXZlSW5wdXRQb2xpY3koYXR0cnMpOwogIH0KICBzdGF0aWMgZWZmZWN0aXZlT3V0cHV0UG9saWN5KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IEVmZmVjdGl2ZU91dHB1dFBvbGljeShhdHRycyk7CiAgfQogIHN0YXRpYyBvcGVyYXRpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgT3BlcmF0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIHJvb3RFbGVtZW50KGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFJvb3RFbGVtZW50KGF0dHJzKTsKICB9CiAgc3RhdGljIHNvYXBBY3Rpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgU29hcEFjdGlvbihhdHRycyk7CiAgfQogIHN0YXRpYyBzb2FwQWRkcmVzcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBTb2FwQWRkcmVzcyhhdHRycyk7CiAgfQogIHN0YXRpYyB1cmkoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgY29ubmVjdGlvbl9zZXRfVXJpKGF0dHJzKTsKICB9CiAgc3RhdGljIHdzZGxBZGRyZXNzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFdzZGxBZGRyZXNzKGF0dHJzKTsKICB9CiAgc3RhdGljIHdzZGxDb25uZWN0aW9uKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFdzZGxDb25uZWN0aW9uKGF0dHJzKTsKICB9CiAgc3RhdGljIHhtbENvbm5lY3Rpb24oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgWG1sQ29ubmVjdGlvbihhdHRycyk7CiAgfQogIHN0YXRpYyB4c2RDb25uZWN0aW9uKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFhzZENvbm5lY3Rpb24oYXR0cnMpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveGZhL2RhdGFzZXRzLmpzCgoKCmNvbnN0IERBVEFTRVRTX05TX0lEID0gTmFtZXNwYWNlSWRzLmRhdGFzZXRzLmlkOwpjbGFzcyBkYXRhc2V0c19EYXRhIGV4dGVuZHMgWG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihEQVRBU0VUU19OU19JRCwgImRhdGEiLCBhdHRyaWJ1dGVzKTsKICB9CiAgWyRpc05zQWdub3N0aWNdKCkgewogICAgcmV0dXJuIHRydWU7CiAgfQp9CmNsYXNzIERhdGFzZXRzIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihEQVRBU0VUU19OU19JRCwgImRhdGFzZXRzIiwgdHJ1ZSk7CiAgICB0aGlzLmRhdGEgPSBudWxsOwogICAgdGhpcy5TaWduYXR1cmUgPSBudWxsOwogIH0KICBbJG9uQ2hpbGRdKGNoaWxkKSB7CiAgICBjb25zdCBuYW1lID0gY2hpbGRbJG5vZGVOYW1lXTsKICAgIGlmIChuYW1lID09PSAiZGF0YSIgJiYgY2hpbGRbJG5hbWVzcGFjZUlkXSA9PT0gREFUQVNFVFNfTlNfSUQgfHwgbmFtZSA9PT0gIlNpZ25hdHVyZSIgJiYgY2hpbGRbJG5hbWVzcGFjZUlkXSA9PT0gTmFtZXNwYWNlSWRzLnNpZ25hdHVyZS5pZCkgewogICAgICB0aGlzW25hbWVdID0gY2hpbGQ7CiAgICB9CiAgICB0aGlzWyRhcHBlbmRDaGlsZF0oY2hpbGQpOwogIH0KfQpjbGFzcyBEYXRhc2V0c05hbWVzcGFjZSB7CiAgc3RhdGljIFskYnVpbGRYRkFPYmplY3RdKG5hbWUsIGF0dHJpYnV0ZXMpIHsKICAgIGlmIChEYXRhc2V0c05hbWVzcGFjZS5oYXNPd25Qcm9wZXJ0eShuYW1lKSkgewogICAgICByZXR1cm4gRGF0YXNldHNOYW1lc3BhY2VbbmFtZV0oYXR0cmlidXRlcyk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBzdGF0aWMgZGF0YXNldHMoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBEYXRhc2V0cyhhdHRyaWJ1dGVzKTsKICB9CiAgc3RhdGljIGRhdGEoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBkYXRhc2V0c19EYXRhKGF0dHJpYnV0ZXMpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveGZhL2xvY2FsZV9zZXQuanMKCgoKY29uc3QgTE9DQUxFX1NFVF9OU19JRCA9IE5hbWVzcGFjZUlkcy5sb2NhbGVTZXQuaWQ7CmNsYXNzIENhbGVuZGFyU3ltYm9scyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgImNhbGVuZGFyU3ltYm9scyIsIHRydWUpOwogICAgdGhpcy5uYW1lID0gImdyZWdvcmlhbiI7CiAgICB0aGlzLmRheU5hbWVzID0gbmV3IFhGQU9iamVjdEFycmF5KDIpOwogICAgdGhpcy5lcmFOYW1lcyA9IG51bGw7CiAgICB0aGlzLm1lcmlkaWVtTmFtZXMgPSBudWxsOwogICAgdGhpcy5tb250aE5hbWVzID0gbmV3IFhGQU9iamVjdEFycmF5KDIpOwogIH0KfQpjbGFzcyBDdXJyZW5jeVN5bWJvbCBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgImN1cnJlbmN5U3ltYm9sIik7CiAgICB0aGlzLm5hbWUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5uYW1lLCBbInN5bWJvbCIsICJpc29uYW1lIiwgImRlY2ltYWwiXSk7CiAgfQp9CmNsYXNzIEN1cnJlbmN5U3ltYm9scyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgImN1cnJlbmN5U3ltYm9scyIsIHRydWUpOwogICAgdGhpcy5jdXJyZW5jeVN5bWJvbCA9IG5ldyBYRkFPYmplY3RBcnJheSgzKTsKICB9Cn0KY2xhc3MgRGF0ZVBhdHRlcm4gZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJkYXRlUGF0dGVybiIpOwogICAgdGhpcy5uYW1lID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMubmFtZSwgWyJmdWxsIiwgImxvbmciLCAibWVkIiwgInNob3J0Il0pOwogIH0KfQpjbGFzcyBEYXRlUGF0dGVybnMgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJkYXRlUGF0dGVybnMiLCB0cnVlKTsKICAgIHRoaXMuZGF0ZVBhdHRlcm4gPSBuZXcgWEZBT2JqZWN0QXJyYXkoNCk7CiAgfQp9CmNsYXNzIERhdGVUaW1lU3ltYm9scyBleHRlbmRzIENvbnRlbnRPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJkYXRlVGltZVN5bWJvbHMiKTsKICB9Cn0KY2xhc3MgRGF5IGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAiZGF5Iik7CiAgfQp9CmNsYXNzIERheU5hbWVzIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAiZGF5TmFtZXMiLCB0cnVlKTsKICAgIHRoaXMuYWJiciA9IGdldEludGVnZXIoewogICAgICBkYXRhOiBhdHRyaWJ1dGVzLmFiYnIsCiAgICAgIGRlZmF1bHRWYWx1ZTogMCwKICAgICAgdmFsaWRhdGU6IHggPT4geCA9PT0gMQogICAgfSk7CiAgICB0aGlzLmRheSA9IG5ldyBYRkFPYmplY3RBcnJheSg3KTsKICB9Cn0KY2xhc3MgRXJhIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAiZXJhIik7CiAgfQp9CmNsYXNzIEVyYU5hbWVzIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAiZXJhTmFtZXMiLCB0cnVlKTsKICAgIHRoaXMuZXJhID0gbmV3IFhGQU9iamVjdEFycmF5KDIpOwogIH0KfQpjbGFzcyBsb2NhbGVfc2V0X0xvY2FsZSBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgImxvY2FsZSIsIHRydWUpOwogICAgdGhpcy5kZXNjID0gYXR0cmlidXRlcy5kZXNjIHx8ICIiOwogICAgdGhpcy5uYW1lID0gImlzb25hbWUiOwogICAgdGhpcy5jYWxlbmRhclN5bWJvbHMgPSBudWxsOwogICAgdGhpcy5jdXJyZW5jeVN5bWJvbHMgPSBudWxsOwogICAgdGhpcy5kYXRlUGF0dGVybnMgPSBudWxsOwogICAgdGhpcy5kYXRlVGltZVN5bWJvbHMgPSBudWxsOwogICAgdGhpcy5udW1iZXJQYXR0ZXJucyA9IG51bGw7CiAgICB0aGlzLm51bWJlclN5bWJvbHMgPSBudWxsOwogICAgdGhpcy50aW1lUGF0dGVybnMgPSBudWxsOwogICAgdGhpcy50eXBlRmFjZXMgPSBudWxsOwogIH0KfQpjbGFzcyBsb2NhbGVfc2V0X0xvY2FsZVNldCBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgImxvY2FsZVNldCIsIHRydWUpOwogICAgdGhpcy5sb2NhbGUgPSBuZXcgWEZBT2JqZWN0QXJyYXkoKTsKICB9Cn0KY2xhc3MgTWVyaWRpZW0gZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJtZXJpZGllbSIpOwogIH0KfQpjbGFzcyBNZXJpZGllbU5hbWVzIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAibWVyaWRpZW1OYW1lcyIsIHRydWUpOwogICAgdGhpcy5tZXJpZGllbSA9IG5ldyBYRkFPYmplY3RBcnJheSgyKTsKICB9Cn0KY2xhc3MgTW9udGggZXh0ZW5kcyBTdHJpbmdPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJtb250aCIpOwogIH0KfQpjbGFzcyBNb250aE5hbWVzIGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAibW9udGhOYW1lcyIsIHRydWUpOwogICAgdGhpcy5hYmJyID0gZ2V0SW50ZWdlcih7CiAgICAgIGRhdGE6IGF0dHJpYnV0ZXMuYWJiciwKICAgICAgZGVmYXVsdFZhbHVlOiAwLAogICAgICB2YWxpZGF0ZTogeCA9PiB4ID09PSAxCiAgICB9KTsKICAgIHRoaXMubW9udGggPSBuZXcgWEZBT2JqZWN0QXJyYXkoMTIpOwogIH0KfQpjbGFzcyBOdW1iZXJQYXR0ZXJuIGV4dGVuZHMgU3RyaW5nT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihMT0NBTEVfU0VUX05TX0lELCAibnVtYmVyUGF0dGVybiIpOwogICAgdGhpcy5uYW1lID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMubmFtZSwgWyJmdWxsIiwgImxvbmciLCAibWVkIiwgInNob3J0Il0pOwogIH0KfQpjbGFzcyBOdW1iZXJQYXR0ZXJucyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgIm51bWJlclBhdHRlcm5zIiwgdHJ1ZSk7CiAgICB0aGlzLm51bWJlclBhdHRlcm4gPSBuZXcgWEZBT2JqZWN0QXJyYXkoNCk7CiAgfQp9CmNsYXNzIE51bWJlclN5bWJvbCBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgIm51bWJlclN5bWJvbCIpOwogICAgdGhpcy5uYW1lID0gZ2V0U3RyaW5nT3B0aW9uKGF0dHJpYnV0ZXMubmFtZSwgWyJkZWNpbWFsIiwgImdyb3VwaW5nIiwgInBlcmNlbnQiLCAibWludXMiLCAiemVybyJdKTsKICB9Cn0KY2xhc3MgTnVtYmVyU3ltYm9scyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgIm51bWJlclN5bWJvbHMiLCB0cnVlKTsKICAgIHRoaXMubnVtYmVyU3ltYm9sID0gbmV3IFhGQU9iamVjdEFycmF5KDUpOwogIH0KfQpjbGFzcyBUaW1lUGF0dGVybiBleHRlbmRzIFN0cmluZ09iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgInRpbWVQYXR0ZXJuIik7CiAgICB0aGlzLm5hbWUgPSBnZXRTdHJpbmdPcHRpb24oYXR0cmlidXRlcy5uYW1lLCBbImZ1bGwiLCAibG9uZyIsICJtZWQiLCAic2hvcnQiXSk7CiAgfQp9CmNsYXNzIFRpbWVQYXR0ZXJucyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgInRpbWVQYXR0ZXJucyIsIHRydWUpOwogICAgdGhpcy50aW1lUGF0dGVybiA9IG5ldyBYRkFPYmplY3RBcnJheSg0KTsKICB9Cn0KY2xhc3MgVHlwZUZhY2UgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKExPQ0FMRV9TRVRfTlNfSUQsICJ0eXBlRmFjZSIsIHRydWUpOwogICAgdGhpcy5uYW1lID0gYXR0cmlidXRlcy5uYW1lIHwgIiI7CiAgfQp9CmNsYXNzIFR5cGVGYWNlcyBleHRlbmRzIFhGQU9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoTE9DQUxFX1NFVF9OU19JRCwgInR5cGVGYWNlcyIsIHRydWUpOwogICAgdGhpcy50eXBlRmFjZSA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogIH0KfQpjbGFzcyBMb2NhbGVTZXROYW1lc3BhY2UgewogIHN0YXRpYyBbJGJ1aWxkWEZBT2JqZWN0XShuYW1lLCBhdHRyaWJ1dGVzKSB7CiAgICBpZiAoTG9jYWxlU2V0TmFtZXNwYWNlLmhhc093blByb3BlcnR5KG5hbWUpKSB7CiAgICAgIHJldHVybiBMb2NhbGVTZXROYW1lc3BhY2VbbmFtZV0oYXR0cmlidXRlcyk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBzdGF0aWMgY2FsZW5kYXJTeW1ib2xzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IENhbGVuZGFyU3ltYm9scyhhdHRycyk7CiAgfQogIHN0YXRpYyBjdXJyZW5jeVN5bWJvbChhdHRycykgewogICAgcmV0dXJuIG5ldyBDdXJyZW5jeVN5bWJvbChhdHRycyk7CiAgfQogIHN0YXRpYyBjdXJyZW5jeVN5bWJvbHMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgQ3VycmVuY3lTeW1ib2xzKGF0dHJzKTsKICB9CiAgc3RhdGljIGRhdGVQYXR0ZXJuKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERhdGVQYXR0ZXJuKGF0dHJzKTsKICB9CiAgc3RhdGljIGRhdGVQYXR0ZXJucyhhdHRycykgewogICAgcmV0dXJuIG5ldyBEYXRlUGF0dGVybnMoYXR0cnMpOwogIH0KICBzdGF0aWMgZGF0ZVRpbWVTeW1ib2xzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERhdGVUaW1lU3ltYm9scyhhdHRycyk7CiAgfQogIHN0YXRpYyBkYXkoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRGF5KGF0dHJzKTsKICB9CiAgc3RhdGljIGRheU5hbWVzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IERheU5hbWVzKGF0dHJzKTsKICB9CiAgc3RhdGljIGVyYShhdHRycykgewogICAgcmV0dXJuIG5ldyBFcmEoYXR0cnMpOwogIH0KICBzdGF0aWMgZXJhTmFtZXMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgRXJhTmFtZXMoYXR0cnMpOwogIH0KICBzdGF0aWMgbG9jYWxlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IGxvY2FsZV9zZXRfTG9jYWxlKGF0dHJzKTsKICB9CiAgc3RhdGljIGxvY2FsZVNldChhdHRycykgewogICAgcmV0dXJuIG5ldyBsb2NhbGVfc2V0X0xvY2FsZVNldChhdHRycyk7CiAgfQogIHN0YXRpYyBtZXJpZGllbShhdHRycykgewogICAgcmV0dXJuIG5ldyBNZXJpZGllbShhdHRycyk7CiAgfQogIHN0YXRpYyBtZXJpZGllbU5hbWVzKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IE1lcmlkaWVtTmFtZXMoYXR0cnMpOwogIH0KICBzdGF0aWMgbW9udGgoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTW9udGgoYXR0cnMpOwogIH0KICBzdGF0aWMgbW9udGhOYW1lcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBNb250aE5hbWVzKGF0dHJzKTsKICB9CiAgc3RhdGljIG51bWJlclBhdHRlcm4oYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTnVtYmVyUGF0dGVybihhdHRycyk7CiAgfQogIHN0YXRpYyBudW1iZXJQYXR0ZXJucyhhdHRycykgewogICAgcmV0dXJuIG5ldyBOdW1iZXJQYXR0ZXJucyhhdHRycyk7CiAgfQogIHN0YXRpYyBudW1iZXJTeW1ib2woYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTnVtYmVyU3ltYm9sKGF0dHJzKTsKICB9CiAgc3RhdGljIG51bWJlclN5bWJvbHMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgTnVtYmVyU3ltYm9scyhhdHRycyk7CiAgfQogIHN0YXRpYyB0aW1lUGF0dGVybihhdHRycykgewogICAgcmV0dXJuIG5ldyBUaW1lUGF0dGVybihhdHRycyk7CiAgfQogIHN0YXRpYyB0aW1lUGF0dGVybnMoYXR0cnMpIHsKICAgIHJldHVybiBuZXcgVGltZVBhdHRlcm5zKGF0dHJzKTsKICB9CiAgc3RhdGljIHR5cGVGYWNlKGF0dHJzKSB7CiAgICByZXR1cm4gbmV3IFR5cGVGYWNlKGF0dHJzKTsKICB9CiAgc3RhdGljIHR5cGVGYWNlcyhhdHRycykgewogICAgcmV0dXJuIG5ldyBUeXBlRmFjZXMoYXR0cnMpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveGZhL3NpZ25hdHVyZS5qcwoKCmNvbnN0IFNJR05BVFVSRV9OU19JRCA9IE5hbWVzcGFjZUlkcy5zaWduYXR1cmUuaWQ7CmNsYXNzIHNpZ25hdHVyZV9TaWduYXR1cmUgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFNJR05BVFVSRV9OU19JRCwgInNpZ25hdHVyZSIsIHRydWUpOwogIH0KfQpjbGFzcyBTaWduYXR1cmVOYW1lc3BhY2UgewogIHN0YXRpYyBbJGJ1aWxkWEZBT2JqZWN0XShuYW1lLCBhdHRyaWJ1dGVzKSB7CiAgICBpZiAoU2lnbmF0dXJlTmFtZXNwYWNlLmhhc093blByb3BlcnR5KG5hbWUpKSB7CiAgICAgIHJldHVybiBTaWduYXR1cmVOYW1lc3BhY2VbbmFtZV0oYXR0cmlidXRlcyk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBzdGF0aWMgc2lnbmF0dXJlKGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgc2lnbmF0dXJlX1NpZ25hdHVyZShhdHRyaWJ1dGVzKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3hmYS9zdHlsZXNoZWV0LmpzCgoKY29uc3QgU1RZTEVTSEVFVF9OU19JRCA9IE5hbWVzcGFjZUlkcy5zdHlsZXNoZWV0LmlkOwpjbGFzcyBTdHlsZXNoZWV0IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihTVFlMRVNIRUVUX05TX0lELCAic3R5bGVzaGVldCIsIHRydWUpOwogIH0KfQpjbGFzcyBTdHlsZXNoZWV0TmFtZXNwYWNlIHsKICBzdGF0aWMgWyRidWlsZFhGQU9iamVjdF0obmFtZSwgYXR0cmlidXRlcykgewogICAgaWYgKFN0eWxlc2hlZXROYW1lc3BhY2UuaGFzT3duUHJvcGVydHkobmFtZSkpIHsKICAgICAgcmV0dXJuIFN0eWxlc2hlZXROYW1lc3BhY2VbbmFtZV0oYXR0cmlidXRlcyk7CiAgICB9CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KICBzdGF0aWMgc3R5bGVzaGVldChhdHRyaWJ1dGVzKSB7CiAgICByZXR1cm4gbmV3IFN0eWxlc2hlZXQoYXR0cmlidXRlcyk7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS94ZmEveGRwLmpzCgoKCmNvbnN0IFhEUF9OU19JRCA9IE5hbWVzcGFjZUlkcy54ZHAuaWQ7CmNsYXNzIHhkcF9YZHAgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKFhEUF9OU19JRCwgInhkcCIsIHRydWUpOwogICAgdGhpcy51dWlkID0gYXR0cmlidXRlcy51dWlkIHx8ICIiOwogICAgdGhpcy50aW1lU3RhbXAgPSBhdHRyaWJ1dGVzLnRpbWVTdGFtcCB8fCAiIjsKICAgIHRoaXMuY29uZmlnID0gbnVsbDsKICAgIHRoaXMuY29ubmVjdGlvblNldCA9IG51bGw7CiAgICB0aGlzLmRhdGFzZXRzID0gbnVsbDsKICAgIHRoaXMubG9jYWxlU2V0ID0gbnVsbDsKICAgIHRoaXMuc3R5bGVzaGVldCA9IG5ldyBYRkFPYmplY3RBcnJheSgpOwogICAgdGhpcy50ZW1wbGF0ZSA9IG51bGw7CiAgfQogIFskb25DaGlsZENoZWNrXShjaGlsZCkgewogICAgY29uc3QgbnMgPSBOYW1lc3BhY2VJZHNbY2hpbGRbJG5vZGVOYW1lXV07CiAgICByZXR1cm4gbnMgJiYgY2hpbGRbJG5hbWVzcGFjZUlkXSA9PT0gbnMuaWQ7CiAgfQp9CmNsYXNzIFhkcE5hbWVzcGFjZSB7CiAgc3RhdGljIFskYnVpbGRYRkFPYmplY3RdKG5hbWUsIGF0dHJpYnV0ZXMpIHsKICAgIGlmIChYZHBOYW1lc3BhY2UuaGFzT3duUHJvcGVydHkobmFtZSkpIHsKICAgICAgcmV0dXJuIFhkcE5hbWVzcGFjZVtuYW1lXShhdHRyaWJ1dGVzKTsKICAgIH0KICAgIHJldHVybiB1bmRlZmluZWQ7CiAgfQogIHN0YXRpYyB4ZHAoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyB4ZHBfWGRwKGF0dHJpYnV0ZXMpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveGZhL3hodG1sLmpzCgoKCgoKCgoKCgoKCgoKCmNvbnN0IFhIVE1MX05TX0lEID0gTmFtZXNwYWNlSWRzLnhodG1sLmlkOwpjb25zdCAkcmljaFRleHQgPSBTeW1ib2woKTsKY29uc3QgVkFMSURfU1RZTEVTID0gbmV3IFNldChbImNvbG9yIiwgImZvbnQiLCAiZm9udC1mYW1pbHkiLCAiZm9udC1zaXplIiwgImZvbnQtc3RyZXRjaCIsICJmb250LXN0eWxlIiwgImZvbnQtd2VpZ2h0IiwgIm1hcmdpbiIsICJtYXJnaW4tYm90dG9tIiwgIm1hcmdpbi1sZWZ0IiwgIm1hcmdpbi1yaWdodCIsICJtYXJnaW4tdG9wIiwgImxldHRlci1zcGFjaW5nIiwgImxpbmUtaGVpZ2h0IiwgIm9ycGhhbnMiLCAicGFnZS1icmVhay1hZnRlciIsICJwYWdlLWJyZWFrLWJlZm9yZSIsICJwYWdlLWJyZWFrLWluc2lkZSIsICJ0YWItaW50ZXJ2YWwiLCAidGFiLXN0b3AiLCAidGV4dC1hbGlnbiIsICJ0ZXh0LWRlY29yYXRpb24iLCAidGV4dC1pbmRlbnQiLCAidmVydGljYWwtYWxpZ24iLCAid2lkb3dzIiwgImtlcm5pbmctbW9kZSIsICJ4ZmEtZm9udC1ob3Jpem9udGFsLXNjYWxlIiwgInhmYS1mb250LXZlcnRpY2FsLXNjYWxlIiwgInhmYS1zcGFjZXJ1biIsICJ4ZmEtdGFiLXN0b3BzIl0pOwpjb25zdCBTdHlsZU1hcHBpbmcgPSBuZXcgTWFwKFtbInBhZ2UtYnJlYWstYWZ0ZXIiLCAiYnJlYWtBZnRlciJdLCBbInBhZ2UtYnJlYWstYmVmb3JlIiwgImJyZWFrQmVmb3JlIl0sIFsicGFnZS1icmVhay1pbnNpZGUiLCAiYnJlYWtJbnNpZGUiXSwgWyJrZXJuaW5nLW1vZGUiLCB2YWx1ZSA9PiB2YWx1ZSA9PT0gIm5vbmUiID8gIm5vbmUiIDogIm5vcm1hbCJdLCBbInhmYS1mb250LWhvcml6b250YWwtc2NhbGUiLCB2YWx1ZSA9PiBgc2NhbGVYKCR7TWF0aC5tYXgoMCwgcGFyc2VJbnQodmFsdWUpIC8gMTAwKS50b0ZpeGVkKDIpfSlgXSwgWyJ4ZmEtZm9udC12ZXJ0aWNhbC1zY2FsZSIsIHZhbHVlID0+IGBzY2FsZVkoJHtNYXRoLm1heCgwLCBwYXJzZUludCh2YWx1ZSkgLyAxMDApLnRvRml4ZWQoMil9KWBdLCBbInhmYS1zcGFjZXJ1biIsICIiXSwgWyJ4ZmEtdGFiLXN0b3BzIiwgIiJdLCBbImZvbnQtc2l6ZSIsICh2YWx1ZSwgb3JpZ2luYWwpID0+IHsKICB2YWx1ZSA9IG9yaWdpbmFsLmZvbnRTaXplID0gTWF0aC5hYnMoZ2V0TWVhc3VyZW1lbnQodmFsdWUpKTsKICByZXR1cm4gbWVhc3VyZVRvU3RyaW5nKDAuOTkgKiB2YWx1ZSk7Cn1dLCBbImxldHRlci1zcGFjaW5nIiwgdmFsdWUgPT4gbWVhc3VyZVRvU3RyaW5nKGdldE1lYXN1cmVtZW50KHZhbHVlKSldLCBbImxpbmUtaGVpZ2h0IiwgdmFsdWUgPT4gbWVhc3VyZVRvU3RyaW5nKGdldE1lYXN1cmVtZW50KHZhbHVlKSldLCBbIm1hcmdpbiIsIHZhbHVlID0+IG1lYXN1cmVUb1N0cmluZyhnZXRNZWFzdXJlbWVudCh2YWx1ZSkpXSwgWyJtYXJnaW4tYm90dG9tIiwgdmFsdWUgPT4gbWVhc3VyZVRvU3RyaW5nKGdldE1lYXN1cmVtZW50KHZhbHVlKSldLCBbIm1hcmdpbi1sZWZ0IiwgdmFsdWUgPT4gbWVhc3VyZVRvU3RyaW5nKGdldE1lYXN1cmVtZW50KHZhbHVlKSldLCBbIm1hcmdpbi1yaWdodCIsIHZhbHVlID0+IG1lYXN1cmVUb1N0cmluZyhnZXRNZWFzdXJlbWVudCh2YWx1ZSkpXSwgWyJtYXJnaW4tdG9wIiwgdmFsdWUgPT4gbWVhc3VyZVRvU3RyaW5nKGdldE1lYXN1cmVtZW50KHZhbHVlKSldLCBbInRleHQtaW5kZW50IiwgdmFsdWUgPT4gbWVhc3VyZVRvU3RyaW5nKGdldE1lYXN1cmVtZW50KHZhbHVlKSldLCBbImZvbnQtZmFtaWx5IiwgdmFsdWUgPT4gdmFsdWVdLCBbInZlcnRpY2FsLWFsaWduIiwgdmFsdWUgPT4gbWVhc3VyZVRvU3RyaW5nKGdldE1lYXN1cmVtZW50KHZhbHVlKSldXSk7CmNvbnN0IHNwYWNlc1JlZ0V4cCA9IC9ccysvZzsKY29uc3QgY3JsZlJlZ0V4cCA9IC9bXHJcbl0rL2c7CmNvbnN0IGNybGZGb3JSaWNoVGV4dFJlZ0V4cCA9IC9cclxuPy9nOwpmdW5jdGlvbiBtYXBTdHlsZShzdHlsZVN0ciwgbm9kZSwgcmljaFRleHQpIHsKICBjb25zdCBzdHlsZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgaWYgKCFzdHlsZVN0cikgewogICAgcmV0dXJuIHN0eWxlOwogIH0KICBjb25zdCBvcmlnaW5hbCA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2Ygc3R5bGVTdHIuc3BsaXQoIjsiKS5tYXAocyA9PiBzLnNwbGl0KCI6IiwgMikpKSB7CiAgICBjb25zdCBtYXBwaW5nID0gU3R5bGVNYXBwaW5nLmdldChrZXkpOwogICAgaWYgKG1hcHBpbmcgPT09ICIiKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgbGV0IG5ld1ZhbHVlID0gdmFsdWU7CiAgICBpZiAobWFwcGluZykgewogICAgICBuZXdWYWx1ZSA9IHR5cGVvZiBtYXBwaW5nID09PSAic3RyaW5nIiA/IG1hcHBpbmcgOiBtYXBwaW5nKHZhbHVlLCBvcmlnaW5hbCk7CiAgICB9CiAgICBpZiAoa2V5LmVuZHNXaXRoKCJzY2FsZSIpKSB7CiAgICAgIHN0eWxlLnRyYW5zZm9ybSA9IHN0eWxlLnRyYW5zZm9ybSA/IGAke3N0eWxlW2tleV19ICR7bmV3VmFsdWV9YCA6IG5ld1ZhbHVlOwogICAgfSBlbHNlIHsKICAgICAgc3R5bGVba2V5LnJlcGxhY2VBbGwoLy0oW2EtekEtWl0pL2csIChfLCB4KSA9PiB4LnRvVXBwZXJDYXNlKCkpXSA9IG5ld1ZhbHVlOwogICAgfQogIH0KICBpZiAoc3R5bGUuZm9udEZhbWlseSkgewogICAgc2V0Rm9udEZhbWlseSh7CiAgICAgIHR5cGVmYWNlOiBzdHlsZS5mb250RmFtaWx5LAogICAgICB3ZWlnaHQ6IHN0eWxlLmZvbnRXZWlnaHQgfHwgIm5vcm1hbCIsCiAgICAgIHBvc3R1cmU6IHN0eWxlLmZvbnRTdHlsZSB8fCAibm9ybWFsIiwKICAgICAgc2l6ZTogb3JpZ2luYWwuZm9udFNpemUgfHwgMAogICAgfSwgbm9kZSwgbm9kZVskZ2xvYmFsRGF0YV0uZm9udEZpbmRlciwgc3R5bGUpOwogIH0KICBpZiAocmljaFRleHQgJiYgc3R5bGUudmVydGljYWxBbGlnbiAmJiBzdHlsZS52ZXJ0aWNhbEFsaWduICE9PSAiMHB4IiAmJiBzdHlsZS5mb250U2l6ZSkgewogICAgY29uc3QgU1VCX1NVUEVSX1NDUklQVF9GQUNUT1IgPSAwLjU4MzsKICAgIGNvbnN0IFZFUlRJQ0FMX0ZBQ1RPUiA9IDAuMzMzOwogICAgY29uc3QgZm9udFNpemUgPSBnZXRNZWFzdXJlbWVudChzdHlsZS5mb250U2l6ZSk7CiAgICBzdHlsZS5mb250U2l6ZSA9IG1lYXN1cmVUb1N0cmluZyhmb250U2l6ZSAqIFNVQl9TVVBFUl9TQ1JJUFRfRkFDVE9SKTsKICAgIHN0eWxlLnZlcnRpY2FsQWxpZ24gPSBtZWFzdXJlVG9TdHJpbmcoTWF0aC5zaWduKGdldE1lYXN1cmVtZW50KHN0eWxlLnZlcnRpY2FsQWxpZ24pKSAqIGZvbnRTaXplICogVkVSVElDQUxfRkFDVE9SKTsKICB9CiAgaWYgKHJpY2hUZXh0ICYmIHN0eWxlLmZvbnRTaXplKSB7CiAgICBzdHlsZS5mb250U2l6ZSA9IGBjYWxjKCR7c3R5bGUuZm9udFNpemV9ICogdmFyKC0tdG90YWwtc2NhbGUtZmFjdG9yKSlgOwogIH0KICBmaXhUZXh0SW5kZW50KHN0eWxlKTsKICByZXR1cm4gc3R5bGU7Cn0KZnVuY3Rpb24gY2hlY2tTdHlsZShub2RlKSB7CiAgaWYgKCFub2RlLnN0eWxlKSB7CiAgICByZXR1cm4gIiI7CiAgfQogIHJldHVybiBub2RlLnN0eWxlLnNwbGl0KCI7IikuZmlsdGVyKHMgPT4gISFzLnRyaW0oKSkubWFwKHMgPT4gcy5zcGxpdCgiOiIsIDIpLm1hcCh0ID0+IHQudHJpbSgpKSkuZmlsdGVyKChba2V5LCB2YWx1ZV0pID0+IHsKICAgIGlmIChrZXkgPT09ICJmb250LWZhbWlseSIpIHsKICAgICAgbm9kZVskZ2xvYmFsRGF0YV0udXNlZFR5cGVmYWNlcy5hZGQodmFsdWUpOwogICAgfQogICAgcmV0dXJuIFZBTElEX1NUWUxFUy5oYXMoa2V5KTsKICB9KS5tYXAoa3YgPT4ga3Yuam9pbigiOiIpKS5qb2luKCI7Iik7Cn0KY29uc3QgTm9XaGl0ZXMgPSBuZXcgU2V0KFsiYm9keSIsICJodG1sIl0pOwpjbGFzcyBYaHRtbE9iamVjdCBleHRlbmRzIFhtbE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcywgbmFtZSkgewogICAgc3VwZXIoWEhUTUxfTlNfSUQsIG5hbWUpOwogICAgdGhpc1skcmljaFRleHRdID0gZmFsc2U7CiAgICB0aGlzLnN0eWxlID0gYXR0cmlidXRlcy5zdHlsZSB8fCAiIjsKICB9CiAgWyRjbGVhbl0oYnVpbGRlcikgewogICAgc3VwZXJbJGNsZWFuXShidWlsZGVyKTsKICAgIHRoaXMuc3R5bGUgPSBjaGVja1N0eWxlKHRoaXMpOwogIH0KICBbJGFjY2VwdFdoaXRlc3BhY2VdKCkgewogICAgcmV0dXJuICFOb1doaXRlcy5oYXModGhpc1skbm9kZU5hbWVdKTsKICB9CiAgWyRvblRleHRdKHN0ciwgcmljaFRleHQgPSBmYWxzZSkgewogICAgaWYgKCFyaWNoVGV4dCkgewogICAgICBzdHIgPSBzdHIucmVwbGFjZUFsbChjcmxmUmVnRXhwLCAiIik7CiAgICAgIGlmICghdGhpcy5zdHlsZS5pbmNsdWRlcygieGZhLXNwYWNlcnVuOnllcyIpKSB7CiAgICAgICAgc3RyID0gc3RyLnJlcGxhY2VBbGwoc3BhY2VzUmVnRXhwLCAiICIpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzWyRyaWNoVGV4dF0gPSB0cnVlOwogICAgfQogICAgaWYgKHN0cikgewogICAgICB0aGlzWyRjb250ZW50XSArPSBzdHI7CiAgICB9CiAgfQogIFskcHVzaEdseXBoc10obWVhc3VyZSwgbXVzdFBvcCA9IHRydWUpIHsKICAgIGNvbnN0IHhmYUZvbnQgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgY29uc3QgbWFyZ2luID0gewogICAgICB0b3A6IE5hTiwKICAgICAgYm90dG9tOiBOYU4sCiAgICAgIGxlZnQ6IE5hTiwKICAgICAgcmlnaHQ6IE5hTgogICAgfTsKICAgIGxldCBsaW5lSGVpZ2h0ID0gbnVsbDsKICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIHRoaXMuc3R5bGUuc3BsaXQoIjsiKS5tYXAocyA9PiBzLnNwbGl0KCI6IiwgMikpKSB7CiAgICAgIHN3aXRjaCAoa2V5KSB7CiAgICAgICAgY2FzZSAiZm9udC1mYW1pbHkiOgogICAgICAgICAgeGZhRm9udC50eXBlZmFjZSA9IHN0cmlwUXVvdGVzKHZhbHVlKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImZvbnQtc2l6ZSI6CiAgICAgICAgICB4ZmFGb250LnNpemUgPSBnZXRNZWFzdXJlbWVudCh2YWx1ZSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJmb250LXdlaWdodCI6CiAgICAgICAgICB4ZmFGb250LndlaWdodCA9IHZhbHVlOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAiZm9udC1zdHlsZSI6CiAgICAgICAgICB4ZmFGb250LnBvc3R1cmUgPSB2YWx1ZTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgImxldHRlci1zcGFjaW5nIjoKICAgICAgICAgIHhmYUZvbnQubGV0dGVyU3BhY2luZyA9IGdldE1lYXN1cmVtZW50KHZhbHVlKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgIm1hcmdpbiI6CiAgICAgICAgICBjb25zdCB2YWx1ZXMgPSB2YWx1ZS5zcGxpdCgvIFx0LykubWFwKHggPT4gZ2V0TWVhc3VyZW1lbnQoeCkpOwogICAgICAgICAgc3dpdGNoICh2YWx1ZXMubGVuZ3RoKSB7CiAgICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgICBtYXJnaW4udG9wID0gbWFyZ2luLmJvdHRvbSA9IG1hcmdpbi5sZWZ0ID0gbWFyZ2luLnJpZ2h0ID0gdmFsdWVzWzBdOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgICAgbWFyZ2luLnRvcCA9IG1hcmdpbi5ib3R0b20gPSB2YWx1ZXNbMF07CiAgICAgICAgICAgICAgbWFyZ2luLmxlZnQgPSBtYXJnaW4ucmlnaHQgPSB2YWx1ZXNbMV07CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMzoKICAgICAgICAgICAgICBtYXJnaW4udG9wID0gdmFsdWVzWzBdOwogICAgICAgICAgICAgIG1hcmdpbi5ib3R0b20gPSB2YWx1ZXNbMl07CiAgICAgICAgICAgICAgbWFyZ2luLmxlZnQgPSBtYXJnaW4ucmlnaHQgPSB2YWx1ZXNbMV07CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgNDoKICAgICAgICAgICAgICBtYXJnaW4udG9wID0gdmFsdWVzWzBdOwogICAgICAgICAgICAgIG1hcmdpbi5sZWZ0ID0gdmFsdWVzWzFdOwogICAgICAgICAgICAgIG1hcmdpbi5ib3R0b20gPSB2YWx1ZXNbMl07CiAgICAgICAgICAgICAgbWFyZ2luLnJpZ2h0ID0gdmFsdWVzWzNdOwogICAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibWFyZ2luLXRvcCI6CiAgICAgICAgICBtYXJnaW4udG9wID0gZ2V0TWVhc3VyZW1lbnQodmFsdWUpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibWFyZ2luLWJvdHRvbSI6CiAgICAgICAgICBtYXJnaW4uYm90dG9tID0gZ2V0TWVhc3VyZW1lbnQodmFsdWUpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibWFyZ2luLWxlZnQiOgogICAgICAgICAgbWFyZ2luLmxlZnQgPSBnZXRNZWFzdXJlbWVudCh2YWx1ZSk7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJtYXJnaW4tcmlnaHQiOgogICAgICAgICAgbWFyZ2luLnJpZ2h0ID0gZ2V0TWVhc3VyZW1lbnQodmFsdWUpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSAibGluZS1oZWlnaHQiOgogICAgICAgICAgbGluZUhlaWdodCA9IGdldE1lYXN1cmVtZW50KHZhbHVlKTsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBtZWFzdXJlLnB1c2hEYXRhKHhmYUZvbnQsIG1hcmdpbiwgbGluZUhlaWdodCk7CiAgICBpZiAodGhpc1skY29udGVudF0pIHsKICAgICAgbWVhc3VyZS5hZGRTdHJpbmcodGhpc1skY29udGVudF0pOwogICAgfSBlbHNlIHsKICAgICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzWyRnZXRDaGlsZHJlbl0oKSkgewogICAgICAgIGlmIChjaGlsZFskbm9kZU5hbWVdID09PSAiI3RleHQiKSB7CiAgICAgICAgICBtZWFzdXJlLmFkZFN0cmluZyhjaGlsZFskY29udGVudF0pOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNoaWxkWyRwdXNoR2x5cGhzXShtZWFzdXJlKTsKICAgICAgfQogICAgfQogICAgaWYgKG11c3RQb3ApIHsKICAgICAgbWVhc3VyZS5wb3BGb250KCk7CiAgICB9CiAgfQogIFskdG9IVE1MXShhdmFpbGFibGVTcGFjZSkgewogICAgY29uc3QgY2hpbGRyZW4gPSBbXTsKICAgIHRoaXNbJGV4dHJhXSA9IHsKICAgICAgY2hpbGRyZW4KICAgIH07CiAgICB0aGlzWyRjaGlsZHJlblRvSFRNTF0oe30pOwogICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA9PT0gMCAmJiAhdGhpc1skY29udGVudF0pIHsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuRU1QVFk7CiAgICB9CiAgICBsZXQgdmFsdWU7CiAgICBpZiAodGhpc1skcmljaFRleHRdKSB7CiAgICAgIHZhbHVlID0gdGhpc1skY29udGVudF0gPyB0aGlzWyRjb250ZW50XS5yZXBsYWNlQWxsKGNybGZGb3JSaWNoVGV4dFJlZ0V4cCwgIlxuIikgOiB1bmRlZmluZWQ7CiAgICB9IGVsc2UgewogICAgICB2YWx1ZSA9IHRoaXNbJGNvbnRlbnRdIHx8IHVuZGVmaW5lZDsKICAgIH0KICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICBuYW1lOiB0aGlzWyRub2RlTmFtZV0sCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBocmVmOiB0aGlzLmhyZWYsCiAgICAgICAgc3R5bGU6IG1hcFN0eWxlKHRoaXMuc3R5bGUsIHRoaXMsIHRoaXNbJHJpY2hUZXh0XSkKICAgICAgfSwKICAgICAgY2hpbGRyZW4sCiAgICAgIHZhbHVlCiAgICB9KTsKICB9Cn0KY2xhc3MgQSBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAiYSIpOwogICAgdGhpcy5ocmVmID0gZml4VVJMKGF0dHJpYnV0ZXMuaHJlZikgfHwgIiI7CiAgfQp9CmNsYXNzIEIgZXh0ZW5kcyBYaHRtbE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoYXR0cmlidXRlcywgImIiKTsKICB9CiAgWyRwdXNoR2x5cGhzXShtZWFzdXJlKSB7CiAgICBtZWFzdXJlLnB1c2hGb250KHsKICAgICAgd2VpZ2h0OiAiYm9sZCIKICAgIH0pOwogICAgc3VwZXJbJHB1c2hHbHlwaHNdKG1lYXN1cmUpOwogICAgbWVhc3VyZS5wb3BGb250KCk7CiAgfQp9CmNsYXNzIEJvZHkgZXh0ZW5kcyBYaHRtbE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoYXR0cmlidXRlcywgImJvZHkiKTsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBjb25zdCByZXMgPSBzdXBlclskdG9IVE1MXShhdmFpbGFibGVTcGFjZSk7CiAgICBjb25zdCB7CiAgICAgIGh0bWwKICAgIH0gPSByZXM7CiAgICBpZiAoIWh0bWwpIHsKICAgICAgcmV0dXJuIEhUTUxSZXN1bHQuRU1QVFk7CiAgICB9CiAgICBodG1sLm5hbWUgPSAiZGl2IjsKICAgIGh0bWwuYXR0cmlidXRlcy5jbGFzcyA9IFsieGZhUmljaCJdOwogICAgcmV0dXJuIHJlczsKICB9Cn0KY2xhc3MgQnIgZXh0ZW5kcyBYaHRtbE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoYXR0cmlidXRlcywgImJyIik7CiAgfQogIFskdGV4dF0oKSB7CiAgICByZXR1cm4gIlxuIjsKICB9CiAgWyRwdXNoR2x5cGhzXShtZWFzdXJlKSB7CiAgICBtZWFzdXJlLmFkZFN0cmluZygiXG4iKTsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgbmFtZTogImJyIgogICAgfSk7CiAgfQp9CmNsYXNzIEh0bWwgZXh0ZW5kcyBYaHRtbE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoYXR0cmlidXRlcywgImh0bWwiKTsKICB9CiAgWyR0b0hUTUxdKGF2YWlsYWJsZVNwYWNlKSB7CiAgICBjb25zdCBjaGlsZHJlbiA9IFtdOwogICAgdGhpc1skZXh0cmFdID0gewogICAgICBjaGlsZHJlbgogICAgfTsKICAgIHRoaXNbJGNoaWxkcmVuVG9IVE1MXSh7fSk7CiAgICBpZiAoY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoewogICAgICAgIG5hbWU6ICJkaXYiLAogICAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICAgIGNsYXNzOiBbInhmYVJpY2giXSwKICAgICAgICAgIHN0eWxlOiB7fQogICAgICAgIH0sCiAgICAgICAgdmFsdWU6IHRoaXNbJGNvbnRlbnRdIHx8ICIiCiAgICAgIH0pOwogICAgfQogICAgaWYgKGNoaWxkcmVuLmxlbmd0aCA9PT0gMSkgewogICAgICBjb25zdCBjaGlsZCA9IGNoaWxkcmVuWzBdOwogICAgICBpZiAoY2hpbGQuYXR0cmlidXRlcz8uY2xhc3MuaW5jbHVkZXMoInhmYVJpY2giKSkgewogICAgICAgIHJldHVybiBIVE1MUmVzdWx0LnN1Y2Nlc3MoY2hpbGQpOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gSFRNTFJlc3VsdC5zdWNjZXNzKHsKICAgICAgbmFtZTogImRpdiIsCiAgICAgIGF0dHJpYnV0ZXM6IHsKICAgICAgICBjbGFzczogWyJ4ZmFSaWNoIl0sCiAgICAgICAgc3R5bGU6IHt9CiAgICAgIH0sCiAgICAgIGNoaWxkcmVuCiAgICB9KTsKICB9Cn0KY2xhc3MgSSBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAiaSIpOwogIH0KICBbJHB1c2hHbHlwaHNdKG1lYXN1cmUpIHsKICAgIG1lYXN1cmUucHVzaEZvbnQoewogICAgICBwb3N0dXJlOiAiaXRhbGljIgogICAgfSk7CiAgICBzdXBlclskcHVzaEdseXBoc10obWVhc3VyZSk7CiAgICBtZWFzdXJlLnBvcEZvbnQoKTsKICB9Cn0KY2xhc3MgTGkgZXh0ZW5kcyBYaHRtbE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoYXR0cmlidXRlcywgImxpIik7CiAgfQp9CmNsYXNzIE9sIGV4dGVuZHMgWGh0bWxPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKGF0dHJpYnV0ZXMsICJvbCIpOwogIH0KfQpjbGFzcyBQIGV4dGVuZHMgWGh0bWxPYmplY3QgewogIGNvbnN0cnVjdG9yKGF0dHJpYnV0ZXMpIHsKICAgIHN1cGVyKGF0dHJpYnV0ZXMsICJwIik7CiAgfQogIFskcHVzaEdseXBoc10obWVhc3VyZSkgewogICAgc3VwZXJbJHB1c2hHbHlwaHNdKG1lYXN1cmUsIGZhbHNlKTsKICAgIG1lYXN1cmUuYWRkU3RyaW5nKCJcbiIpOwogICAgbWVhc3VyZS5hZGRQYXJhKCk7CiAgICBtZWFzdXJlLnBvcEZvbnQoKTsKICB9CiAgWyR0ZXh0XSgpIHsKICAgIGNvbnN0IHNpYmxpbmdzID0gdGhpc1skZ2V0UGFyZW50XSgpWyRnZXRDaGlsZHJlbl0oKTsKICAgIGlmIChzaWJsaW5ncy5hdCgtMSkgPT09IHRoaXMpIHsKICAgICAgcmV0dXJuIHN1cGVyWyR0ZXh0XSgpOwogICAgfQogICAgcmV0dXJuIHN1cGVyWyR0ZXh0XSgpICsgIlxuIjsKICB9Cn0KY2xhc3MgU3BhbiBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAic3BhbiIpOwogIH0KfQpjbGFzcyBTdWIgZXh0ZW5kcyBYaHRtbE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoYXR0cmlidXRlcywgInN1YiIpOwogIH0KfQpjbGFzcyBTdXAgZXh0ZW5kcyBYaHRtbE9iamVjdCB7CiAgY29uc3RydWN0b3IoYXR0cmlidXRlcykgewogICAgc3VwZXIoYXR0cmlidXRlcywgInN1cCIpOwogIH0KfQpjbGFzcyBVbCBleHRlbmRzIFhodG1sT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihhdHRyaWJ1dGVzKSB7CiAgICBzdXBlcihhdHRyaWJ1dGVzLCAidWwiKTsKICB9Cn0KY2xhc3MgWGh0bWxOYW1lc3BhY2UgewogIHN0YXRpYyBbJGJ1aWxkWEZBT2JqZWN0XShuYW1lLCBhdHRyaWJ1dGVzKSB7CiAgICBpZiAoWGh0bWxOYW1lc3BhY2UuaGFzT3duUHJvcGVydHkobmFtZSkpIHsKICAgICAgcmV0dXJuIFhodG1sTmFtZXNwYWNlW25hbWVdKGF0dHJpYnV0ZXMpOwogICAgfQogICAgcmV0dXJuIHVuZGVmaW5lZDsKICB9CiAgc3RhdGljIGEoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBBKGF0dHJpYnV0ZXMpOwogIH0KICBzdGF0aWMgYihhdHRyaWJ1dGVzKSB7CiAgICByZXR1cm4gbmV3IEIoYXR0cmlidXRlcyk7CiAgfQogIHN0YXRpYyBib2R5KGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgQm9keShhdHRyaWJ1dGVzKTsKICB9CiAgc3RhdGljIGJyKGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgQnIoYXR0cmlidXRlcyk7CiAgfQogIHN0YXRpYyBodG1sKGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgSHRtbChhdHRyaWJ1dGVzKTsKICB9CiAgc3RhdGljIGkoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBJKGF0dHJpYnV0ZXMpOwogIH0KICBzdGF0aWMgbGkoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBMaShhdHRyaWJ1dGVzKTsKICB9CiAgc3RhdGljIG9sKGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgT2woYXR0cmlidXRlcyk7CiAgfQogIHN0YXRpYyBwKGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgUChhdHRyaWJ1dGVzKTsKICB9CiAgc3RhdGljIHNwYW4oYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBTcGFuKGF0dHJpYnV0ZXMpOwogIH0KICBzdGF0aWMgc3ViKGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgU3ViKGF0dHJpYnV0ZXMpOwogIH0KICBzdGF0aWMgc3VwKGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgU3VwKGF0dHJpYnV0ZXMpOwogIH0KICBzdGF0aWMgdWwoYXR0cmlidXRlcykgewogICAgcmV0dXJuIG5ldyBVbChhdHRyaWJ1dGVzKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3hmYS9zZXR1cC5qcwoKCgoKCgoKCgpjb25zdCBOYW1lc3BhY2VTZXRVcCA9IHsKICBjb25maWc6IENvbmZpZ05hbWVzcGFjZSwKICBjb25uZWN0aW9uOiBDb25uZWN0aW9uU2V0TmFtZXNwYWNlLAogIGRhdGFzZXRzOiBEYXRhc2V0c05hbWVzcGFjZSwKICBsb2NhbGVTZXQ6IExvY2FsZVNldE5hbWVzcGFjZSwKICBzaWduYXR1cmU6IFNpZ25hdHVyZU5hbWVzcGFjZSwKICBzdHlsZXNoZWV0OiBTdHlsZXNoZWV0TmFtZXNwYWNlLAogIHRlbXBsYXRlOiBUZW1wbGF0ZU5hbWVzcGFjZSwKICB4ZHA6IFhkcE5hbWVzcGFjZSwKICB4aHRtbDogWGh0bWxOYW1lc3BhY2UKfTsKCjsvLyAuL3NyYy9jb3JlL3hmYS91bmtub3duLmpzCgoKY2xhc3MgVW5rbm93bk5hbWVzcGFjZSB7CiAgY29uc3RydWN0b3IobnNJZCkgewogICAgdGhpcy5uYW1lc3BhY2VJZCA9IG5zSWQ7CiAgfQogIFskYnVpbGRYRkFPYmplY3RdKG5hbWUsIGF0dHJpYnV0ZXMpIHsKICAgIHJldHVybiBuZXcgWG1sT2JqZWN0KHRoaXMubmFtZXNwYWNlSWQsIG5hbWUsIGF0dHJpYnV0ZXMpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveGZhL2J1aWxkZXIuanMKCgoKCgoKCgoKCgpjbGFzcyBSb290IGV4dGVuZHMgWEZBT2JqZWN0IHsKICBjb25zdHJ1Y3RvcihpZHMpIHsKICAgIHN1cGVyKC0xLCAicm9vdCIsIE9iamVjdC5jcmVhdGUobnVsbCkpOwogICAgdGhpcy5lbGVtZW50ID0gbnVsbDsKICAgIHRoaXNbJGlkc10gPSBpZHM7CiAgfQogIFskb25DaGlsZF0oY2hpbGQpIHsKICAgIHRoaXMuZWxlbWVudCA9IGNoaWxkOwogICAgcmV0dXJuIHRydWU7CiAgfQogIFskZmluYWxpemVdKCkgewogICAgc3VwZXJbJGZpbmFsaXplXSgpOwogICAgaWYgKHRoaXMuZWxlbWVudC50ZW1wbGF0ZSBpbnN0YW5jZW9mIFRlbXBsYXRlKSB7CiAgICAgIHRoaXNbJGlkc10uc2V0KCRyb290LCB0aGlzLmVsZW1lbnQpOwogICAgICB0aGlzLmVsZW1lbnQudGVtcGxhdGVbJHJlc29sdmVQcm90b3R5cGVzXSh0aGlzWyRpZHNdKTsKICAgICAgdGhpcy5lbGVtZW50LnRlbXBsYXRlWyRpZHNdID0gdGhpc1skaWRzXTsKICAgIH0KICB9Cn0KY2xhc3MgRW1wdHkgZXh0ZW5kcyBYRkFPYmplY3QgewogIGNvbnN0cnVjdG9yKCkgewogICAgc3VwZXIoLTEsICIiLCBPYmplY3QuY3JlYXRlKG51bGwpKTsKICB9CiAgWyRvbkNoaWxkXShfKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQp9CmNsYXNzIEJ1aWxkZXIgewogIGNvbnN0cnVjdG9yKHJvb3ROYW1lU3BhY2UgPSBudWxsKSB7CiAgICB0aGlzLl9uYW1lc3BhY2VTdGFjayA9IFtdOwogICAgdGhpcy5fbnNBZ25vc3RpY0xldmVsID0gMDsKICAgIHRoaXMuX25hbWVzcGFjZVByZWZpeGVzID0gbmV3IE1hcCgpOwogICAgdGhpcy5fbmFtZXNwYWNlcyA9IG5ldyBNYXAoKTsKICAgIHRoaXMuX25leHROc0lkID0gTWF0aC5tYXgoLi4uT2JqZWN0LnZhbHVlcyhOYW1lc3BhY2VJZHMpLm1hcCgoewogICAgICBpZAogICAgfSkgPT4gaWQpKTsKICAgIHRoaXMuX2N1cnJlbnROYW1lc3BhY2UgPSByb290TmFtZVNwYWNlIHx8IG5ldyBVbmtub3duTmFtZXNwYWNlKCsrdGhpcy5fbmV4dE5zSWQpOwogIH0KICBidWlsZFJvb3QoaWRzKSB7CiAgICByZXR1cm4gbmV3IFJvb3QoaWRzKTsKICB9CiAgYnVpbGQoewogICAgbnNQcmVmaXgsCiAgICBuYW1lLAogICAgYXR0cmlidXRlcywKICAgIG5hbWVzcGFjZSwKICAgIHByZWZpeGVzCiAgfSkgewogICAgY29uc3QgaGFzTmFtZXNwYWNlRGVmID0gbmFtZXNwYWNlICE9PSBudWxsOwogICAgaWYgKGhhc05hbWVzcGFjZURlZikgewogICAgICB0aGlzLl9uYW1lc3BhY2VTdGFjay5wdXNoKHRoaXMuX2N1cnJlbnROYW1lc3BhY2UpOwogICAgICB0aGlzLl9jdXJyZW50TmFtZXNwYWNlID0gdGhpcy5fc2VhcmNoTmFtZXNwYWNlKG5hbWVzcGFjZSk7CiAgICB9CiAgICBpZiAocHJlZml4ZXMpIHsKICAgICAgdGhpcy5fYWRkTmFtZXNwYWNlUHJlZml4KHByZWZpeGVzKTsKICAgIH0KICAgIGlmIChhdHRyaWJ1dGVzLmhhc093blByb3BlcnR5KCRuc0F0dHJpYnV0ZXMpKSB7CiAgICAgIGNvbnN0IGRhdGFUZW1wbGF0ZSA9IE5hbWVzcGFjZVNldFVwLmRhdGFzZXRzOwogICAgICBjb25zdCBuc0F0dHJzID0gYXR0cmlidXRlc1skbnNBdHRyaWJ1dGVzXTsKICAgICAgbGV0IHhmYUF0dHJzID0gbnVsbDsKICAgICAgZm9yIChjb25zdCBbbnMsIGF0dHJzXSBvZiBPYmplY3QuZW50cmllcyhuc0F0dHJzKSkgewogICAgICAgIGNvbnN0IG5zVG9Vc2UgPSB0aGlzLl9nZXROYW1lc3BhY2VUb1VzZShucyk7CiAgICAgICAgaWYgKG5zVG9Vc2UgPT09IGRhdGFUZW1wbGF0ZSkgewogICAgICAgICAgeGZhQXR0cnMgPSB7CiAgICAgICAgICAgIHhmYTogYXR0cnMKICAgICAgICAgIH07CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKHhmYUF0dHJzKSB7CiAgICAgICAgYXR0cmlidXRlc1skbnNBdHRyaWJ1dGVzXSA9IHhmYUF0dHJzOwogICAgICB9IGVsc2UgewogICAgICAgIGRlbGV0ZSBhdHRyaWJ1dGVzWyRuc0F0dHJpYnV0ZXNdOwogICAgICB9CiAgICB9CiAgICBjb25zdCBuYW1lc3BhY2VUb1VzZSA9IHRoaXMuX2dldE5hbWVzcGFjZVRvVXNlKG5zUHJlZml4KTsKICAgIGNvbnN0IG5vZGUgPSBuYW1lc3BhY2VUb1VzZT8uWyRidWlsZFhGQU9iamVjdF0obmFtZSwgYXR0cmlidXRlcykgfHwgbmV3IEVtcHR5KCk7CiAgICBpZiAobm9kZVskaXNOc0Fnbm9zdGljXSgpKSB7CiAgICAgIHRoaXMuX25zQWdub3N0aWNMZXZlbCsrOwogICAgfQogICAgaWYgKGhhc05hbWVzcGFjZURlZiB8fCBwcmVmaXhlcyB8fCBub2RlWyRpc05zQWdub3N0aWNdKCkpIHsKICAgICAgbm9kZVskY2xlYW51cF0gPSB7CiAgICAgICAgaGFzTmFtZXNwYWNlOiBoYXNOYW1lc3BhY2VEZWYsCiAgICAgICAgcHJlZml4ZXMsCiAgICAgICAgbnNBZ25vc3RpYzogbm9kZVskaXNOc0Fnbm9zdGljXSgpCiAgICAgIH07CiAgICB9CiAgICByZXR1cm4gbm9kZTsKICB9CiAgaXNOc0Fnbm9zdGljKCkgewogICAgcmV0dXJuIHRoaXMuX25zQWdub3N0aWNMZXZlbCA+IDA7CiAgfQogIF9zZWFyY2hOYW1lc3BhY2UobnNOYW1lKSB7CiAgICBsZXQgbnMgPSB0aGlzLl9uYW1lc3BhY2VzLmdldChuc05hbWUpOwogICAgaWYgKG5zKSB7CiAgICAgIHJldHVybiBuczsKICAgIH0KICAgIGZvciAoY29uc3QgW25hbWUsIHsKICAgICAgY2hlY2sKICAgIH1dIG9mIE9iamVjdC5lbnRyaWVzKE5hbWVzcGFjZUlkcykpIHsKICAgICAgaWYgKGNoZWNrKG5zTmFtZSkpIHsKICAgICAgICBucyA9IE5hbWVzcGFjZVNldFVwW25hbWVdOwogICAgICAgIGlmIChucykgewogICAgICAgICAgdGhpcy5fbmFtZXNwYWNlcy5zZXQobnNOYW1lLCBucyk7CiAgICAgICAgICByZXR1cm4gbnM7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICB9CiAgICB9CiAgICBucyA9IG5ldyBVbmtub3duTmFtZXNwYWNlKCsrdGhpcy5fbmV4dE5zSWQpOwogICAgdGhpcy5fbmFtZXNwYWNlcy5zZXQobnNOYW1lLCBucyk7CiAgICByZXR1cm4gbnM7CiAgfQogIF9hZGROYW1lc3BhY2VQcmVmaXgocHJlZml4ZXMpIHsKICAgIGZvciAoY29uc3QgewogICAgICBwcmVmaXgsCiAgICAgIHZhbHVlCiAgICB9IG9mIHByZWZpeGVzKSB7CiAgICAgIGNvbnN0IG5hbWVzcGFjZSA9IHRoaXMuX3NlYXJjaE5hbWVzcGFjZSh2YWx1ZSk7CiAgICAgIGxldCBwcmVmaXhTdGFjayA9IHRoaXMuX25hbWVzcGFjZVByZWZpeGVzLmdldChwcmVmaXgpOwogICAgICBpZiAoIXByZWZpeFN0YWNrKSB7CiAgICAgICAgcHJlZml4U3RhY2sgPSBbXTsKICAgICAgICB0aGlzLl9uYW1lc3BhY2VQcmVmaXhlcy5zZXQocHJlZml4LCBwcmVmaXhTdGFjayk7CiAgICAgIH0KICAgICAgcHJlZml4U3RhY2sucHVzaChuYW1lc3BhY2UpOwogICAgfQogIH0KICBfZ2V0TmFtZXNwYWNlVG9Vc2UocHJlZml4KSB7CiAgICBpZiAoIXByZWZpeCkgewogICAgICByZXR1cm4gdGhpcy5fY3VycmVudE5hbWVzcGFjZTsKICAgIH0KICAgIGNvbnN0IHByZWZpeFN0YWNrID0gdGhpcy5fbmFtZXNwYWNlUHJlZml4ZXMuZ2V0KHByZWZpeCk7CiAgICBpZiAocHJlZml4U3RhY2s/Lmxlbmd0aCA+IDApIHsKICAgICAgcmV0dXJuIHByZWZpeFN0YWNrLmF0KC0xKTsKICAgIH0KICAgIHdhcm4oYFVua25vd24gbmFtZXNwYWNlIHByZWZpeDogJHtwcmVmaXh9LmApOwogICAgcmV0dXJuIG51bGw7CiAgfQogIGNsZWFuKGRhdGEpIHsKICAgIGNvbnN0IHsKICAgICAgaGFzTmFtZXNwYWNlLAogICAgICBwcmVmaXhlcywKICAgICAgbnNBZ25vc3RpYwogICAgfSA9IGRhdGE7CiAgICBpZiAoaGFzTmFtZXNwYWNlKSB7CiAgICAgIHRoaXMuX2N1cnJlbnROYW1lc3BhY2UgPSB0aGlzLl9uYW1lc3BhY2VTdGFjay5wb3AoKTsKICAgIH0KICAgIGlmIChwcmVmaXhlcykgewogICAgICBwcmVmaXhlcy5mb3JFYWNoKCh7CiAgICAgICAgcHJlZml4CiAgICAgIH0pID0+IHsKICAgICAgICB0aGlzLl9uYW1lc3BhY2VQcmVmaXhlcy5nZXQocHJlZml4KS5wb3AoKTsKICAgICAgfSk7CiAgICB9CiAgICBpZiAobnNBZ25vc3RpYykgewogICAgICB0aGlzLl9uc0Fnbm9zdGljTGV2ZWwtLTsKICAgIH0KICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3hmYS9wYXJzZXIuanMKCgoKCgoKCgoKCgoKY2xhc3MgWEZBUGFyc2VyIGV4dGVuZHMgWE1MUGFyc2VyQmFzZSB7CiAgY29uc3RydWN0b3Iocm9vdE5hbWVTcGFjZSA9IG51bGwsIHJpY2hUZXh0ID0gZmFsc2UpIHsKICAgIHN1cGVyKCk7CiAgICB0aGlzLl9idWlsZGVyID0gbmV3IEJ1aWxkZXIocm9vdE5hbWVTcGFjZSk7CiAgICB0aGlzLl9zdGFjayA9IFtdOwogICAgdGhpcy5fZ2xvYmFsRGF0YSA9IHsKICAgICAgdXNlZFR5cGVmYWNlczogbmV3IFNldCgpCiAgICB9OwogICAgdGhpcy5faWRzID0gbmV3IE1hcCgpOwogICAgdGhpcy5fY3VycmVudCA9IHRoaXMuX2J1aWxkZXIuYnVpbGRSb290KHRoaXMuX2lkcyk7CiAgICB0aGlzLl9lcnJvckNvZGUgPSBYTUxQYXJzZXJFcnJvckNvZGUuTm9FcnJvcjsKICAgIHRoaXMuX3doaXRlUmVnZXggPSAvXlxzKyQvOwogICAgdGhpcy5fbmJzcHMgPSAvXHhhMCsvZzsKICAgIHRoaXMuX3JpY2hUZXh0ID0gcmljaFRleHQ7CiAgfQogIHBhcnNlKGRhdGEpIHsKICAgIHRoaXMucGFyc2VYbWwoZGF0YSk7CiAgICBpZiAodGhpcy5fZXJyb3JDb2RlICE9PSBYTUxQYXJzZXJFcnJvckNvZGUuTm9FcnJvcikgewogICAgICByZXR1cm4gdW5kZWZpbmVkOwogICAgfQogICAgdGhpcy5fY3VycmVudFskZmluYWxpemVdKCk7CiAgICByZXR1cm4gdGhpcy5fY3VycmVudC5lbGVtZW50OwogIH0KICBvblRleHQodGV4dCkgewogICAgdGV4dCA9IHRleHQucmVwbGFjZSh0aGlzLl9uYnNwcywgbWF0Y2ggPT4gbWF0Y2guc2xpY2UoMSkgKyAiICIpOwogICAgaWYgKHRoaXMuX3JpY2hUZXh0IHx8IHRoaXMuX2N1cnJlbnRbJGFjY2VwdFdoaXRlc3BhY2VdKCkpIHsKICAgICAgdGhpcy5fY3VycmVudFskb25UZXh0XSh0ZXh0LCB0aGlzLl9yaWNoVGV4dCk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh0aGlzLl93aGl0ZVJlZ2V4LnRlc3QodGV4dCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5fY3VycmVudFskb25UZXh0XSh0ZXh0LnRyaW0oKSk7CiAgfQogIG9uQ2RhdGEodGV4dCkgewogICAgdGhpcy5fY3VycmVudFskb25UZXh0XSh0ZXh0KTsKICB9CiAgX21rQXR0cmlidXRlcyhhdHRyaWJ1dGVzLCB0YWdOYW1lKSB7CiAgICBsZXQgbmFtZXNwYWNlID0gbnVsbDsKICAgIGxldCBwcmVmaXhlcyA9IG51bGw7CiAgICBjb25zdCBhdHRyaWJ1dGVPYmogPSBPYmplY3QuY3JlYXRlKHt9KTsKICAgIGZvciAoY29uc3QgewogICAgICBuYW1lLAogICAgICB2YWx1ZQogICAgfSBvZiBhdHRyaWJ1dGVzKSB7CiAgICAgIGlmIChuYW1lID09PSAieG1sbnMiKSB7CiAgICAgICAgaWYgKCFuYW1lc3BhY2UpIHsKICAgICAgICAgIG5hbWVzcGFjZSA9IHZhbHVlOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB3YXJuKGBYRkEgLSBtdWx0aXBsZSBuYW1lc3BhY2UgZGVmaW5pdGlvbiBpbiA8JHt0YWdOYW1lfT5gKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSBpZiAobmFtZS5zdGFydHNXaXRoKCJ4bWxuczoiKSkgewogICAgICAgIGNvbnN0IHByZWZpeCA9IG5hbWUuc3Vic3RyaW5nKCJ4bWxuczoiLmxlbmd0aCk7CiAgICAgICAgcHJlZml4ZXMgPz89IFtdOwogICAgICAgIHByZWZpeGVzLnB1c2goewogICAgICAgICAgcHJlZml4LAogICAgICAgICAgdmFsdWUKICAgICAgICB9KTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBpID0gbmFtZS5pbmRleE9mKCI6Iik7CiAgICAgICAgaWYgKGkgPT09IC0xKSB7CiAgICAgICAgICBhdHRyaWJ1dGVPYmpbbmFtZV0gPSB2YWx1ZTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgY29uc3QgbnNBdHRycyA9IGF0dHJpYnV0ZU9ialskbnNBdHRyaWJ1dGVzXSA/Pz0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgIGNvbnN0IFtucywgYXR0ck5hbWVdID0gW25hbWUuc2xpY2UoMCwgaSksIG5hbWUuc2xpY2UoaSArIDEpXTsKICAgICAgICAgIGNvbnN0IGF0dHJzID0gbnNBdHRyc1tuc10gfHw9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgICAgICBhdHRyc1thdHRyTmFtZV0gPSB2YWx1ZTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBbbmFtZXNwYWNlLCBwcmVmaXhlcywgYXR0cmlidXRlT2JqXTsKICB9CiAgX2dldE5hbWVBbmRQcmVmaXgobmFtZSwgbnNBZ25vc3RpYykgewogICAgY29uc3QgaSA9IG5hbWUuaW5kZXhPZigiOiIpOwogICAgaWYgKGkgPT09IC0xKSB7CiAgICAgIHJldHVybiBbbmFtZSwgbnVsbF07CiAgICB9CiAgICByZXR1cm4gW25hbWUuc3Vic3RyaW5nKGkgKyAxKSwgbnNBZ25vc3RpYyA/ICIiIDogbmFtZS5zdWJzdHJpbmcoMCwgaSldOwogIH0KICBvbkJlZ2luRWxlbWVudCh0YWdOYW1lLCBhdHRyaWJ1dGVzLCBpc0VtcHR5KSB7CiAgICBjb25zdCBbbmFtZXNwYWNlLCBwcmVmaXhlcywgYXR0cmlidXRlc09ial0gPSB0aGlzLl9ta0F0dHJpYnV0ZXMoYXR0cmlidXRlcywgdGFnTmFtZSk7CiAgICBjb25zdCBbbmFtZSwgbnNQcmVmaXhdID0gdGhpcy5fZ2V0TmFtZUFuZFByZWZpeCh0YWdOYW1lLCB0aGlzLl9idWlsZGVyLmlzTnNBZ25vc3RpYygpKTsKICAgIGNvbnN0IG5vZGUgPSB0aGlzLl9idWlsZGVyLmJ1aWxkKHsKICAgICAgbnNQcmVmaXgsCiAgICAgIG5hbWUsCiAgICAgIGF0dHJpYnV0ZXM6IGF0dHJpYnV0ZXNPYmosCiAgICAgIG5hbWVzcGFjZSwKICAgICAgcHJlZml4ZXMKICAgIH0pOwogICAgbm9kZVskZ2xvYmFsRGF0YV0gPSB0aGlzLl9nbG9iYWxEYXRhOwogICAgaWYgKGlzRW1wdHkpIHsKICAgICAgbm9kZVskZmluYWxpemVdKCk7CiAgICAgIGlmICh0aGlzLl9jdXJyZW50WyRvbkNoaWxkXShub2RlKSkgewogICAgICAgIG5vZGVbJHNldElkXSh0aGlzLl9pZHMpOwogICAgICB9CiAgICAgIG5vZGVbJGNsZWFuXSh0aGlzLl9idWlsZGVyKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5fc3RhY2sucHVzaCh0aGlzLl9jdXJyZW50KTsKICAgIHRoaXMuX2N1cnJlbnQgPSBub2RlOwogIH0KICBvbkVuZEVsZW1lbnQobmFtZSkgewogICAgY29uc3Qgbm9kZSA9IHRoaXMuX2N1cnJlbnQ7CiAgICBpZiAobm9kZVskaXNDREFUQVhtbF0oKSAmJiB0eXBlb2Ygbm9kZVskY29udGVudF0gPT09ICJzdHJpbmciKSB7CiAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBYRkFQYXJzZXIoKTsKICAgICAgcGFyc2VyLl9nbG9iYWxEYXRhID0gdGhpcy5fZ2xvYmFsRGF0YTsKICAgICAgY29uc3Qgcm9vdCA9IHBhcnNlci5wYXJzZShub2RlWyRjb250ZW50XSk7CiAgICAgIG5vZGVbJGNvbnRlbnRdID0gbnVsbDsKICAgICAgbm9kZVskb25DaGlsZF0ocm9vdCk7CiAgICB9CiAgICBub2RlWyRmaW5hbGl6ZV0oKTsKICAgIHRoaXMuX2N1cnJlbnQgPSB0aGlzLl9zdGFjay5wb3AoKTsKICAgIGlmICh0aGlzLl9jdXJyZW50WyRvbkNoaWxkXShub2RlKSkgewogICAgICBub2RlWyRzZXRJZF0odGhpcy5faWRzKTsKICAgIH0KICAgIG5vZGVbJGNsZWFuXSh0aGlzLl9idWlsZGVyKTsKICB9CiAgb25FcnJvcihjb2RlKSB7CiAgICB0aGlzLl9lcnJvckNvZGUgPSBjb2RlOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveGZhL2ZhY3RvcnkuanMKCgoKCgoKCgoKCgoKCmNsYXNzIFhGQUZhY3RvcnkgewogIGNvbnN0cnVjdG9yKGRhdGEpIHsKICAgIHRyeSB7CiAgICAgIHRoaXMucm9vdCA9IG5ldyBYRkFQYXJzZXIoKS5wYXJzZShYRkFGYWN0b3J5Ll9jcmVhdGVEb2N1bWVudChkYXRhKSk7CiAgICAgIGNvbnN0IGJpbmRlciA9IG5ldyBCaW5kZXIodGhpcy5yb290KTsKICAgICAgdGhpcy5mb3JtID0gYmluZGVyLmJpbmQoKTsKICAgICAgdGhpcy5kYXRhSGFuZGxlciA9IG5ldyBEYXRhSGFuZGxlcih0aGlzLnJvb3QsIGJpbmRlci5nZXREYXRhKCkpOwogICAgICB0aGlzLmZvcm1bJGdsb2JhbERhdGFdLnRlbXBsYXRlID0gdGhpcy5mb3JtOwogICAgfSBjYXRjaCAoZSkgewogICAgICB3YXJuKGBYRkEgLSBhbiBlcnJvciBvY2N1cnJlZCBkdXJpbmcgcGFyc2luZyBhbmQgYmluZGluZzogJHtlfWApOwogICAgfQogIH0KICBpc1ZhbGlkKCkgewogICAgcmV0dXJuICEhKHRoaXMucm9vdCAmJiB0aGlzLmZvcm0pOwogIH0KICBfY3JlYXRlUGFnZXNIZWxwZXIoKSB7CiAgICBjb25zdCBpdGVyYXRvciA9IHRoaXMuZm9ybVskdG9QYWdlc10oKTsKICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7CiAgICAgIGNvbnN0IG5leHRJdGVyYXRpb24gPSAoKSA9PiB7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIGNvbnN0IHZhbHVlID0gaXRlcmF0b3IubmV4dCgpOwogICAgICAgICAgaWYgKHZhbHVlLmRvbmUpIHsKICAgICAgICAgICAgcmVzb2x2ZSh2YWx1ZS52YWx1ZSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBzZXRUaW1lb3V0KG5leHRJdGVyYXRpb24sIDApOwogICAgICAgICAgfQogICAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICAgIHJlamVjdChlKTsKICAgICAgICB9CiAgICAgIH07CiAgICAgIHNldFRpbWVvdXQobmV4dEl0ZXJhdGlvbiwgMCk7CiAgICB9KTsKICB9CiAgYXN5bmMgX2NyZWF0ZVBhZ2VzKCkgewogICAgdHJ5IHsKICAgICAgdGhpcy5wYWdlcyA9IGF3YWl0IHRoaXMuX2NyZWF0ZVBhZ2VzSGVscGVyKCk7CiAgICAgIHRoaXMuZGltcyA9IHRoaXMucGFnZXMuY2hpbGRyZW4ubWFwKGMgPT4gewogICAgICAgIGNvbnN0IHsKICAgICAgICAgIHdpZHRoLAogICAgICAgICAgaGVpZ2h0CiAgICAgICAgfSA9IGMuYXR0cmlidXRlcy5zdHlsZTsKICAgICAgICByZXR1cm4gWzAsIDAsIHBhcnNlSW50KHdpZHRoKSwgcGFyc2VJbnQoaGVpZ2h0KV07CiAgICAgIH0pOwogICAgfSBjYXRjaCAoZSkgewogICAgICB3YXJuKGBYRkEgLSBhbiBlcnJvciBvY2N1cnJlZCBkdXJpbmcgbGF5b3V0OiAke2V9YCk7CiAgICB9CiAgfQogIGdldEJvdW5kaW5nQm94KHBhZ2VJbmRleCkgewogICAgcmV0dXJuIHRoaXMuZGltc1twYWdlSW5kZXhdOwogIH0KICBhc3luYyBnZXROdW1QYWdlcygpIHsKICAgIGlmICghdGhpcy5wYWdlcykgewogICAgICBhd2FpdCB0aGlzLl9jcmVhdGVQYWdlcygpOwogICAgfQogICAgcmV0dXJuIHRoaXMuZGltcy5sZW5ndGg7CiAgfQogIHNldEltYWdlcyhpbWFnZXMpIHsKICAgIHRoaXMuZm9ybVskZ2xvYmFsRGF0YV0uaW1hZ2VzID0gaW1hZ2VzOwogIH0KICBzZXRGb250cyhmb250cykgewogICAgdGhpcy5mb3JtWyRnbG9iYWxEYXRhXS5mb250RmluZGVyID0gbmV3IEZvbnRGaW5kZXIoZm9udHMpOwogICAgY29uc3QgbWlzc2luZ0ZvbnRzID0gW107CiAgICBmb3IgKGxldCB0eXBlZmFjZSBvZiB0aGlzLmZvcm1bJGdsb2JhbERhdGFdLnVzZWRUeXBlZmFjZXMpIHsKICAgICAgdHlwZWZhY2UgPSBzdHJpcFF1b3Rlcyh0eXBlZmFjZSk7CiAgICAgIGNvbnN0IGZvbnQgPSB0aGlzLmZvcm1bJGdsb2JhbERhdGFdLmZvbnRGaW5kZXIuZmluZCh0eXBlZmFjZSk7CiAgICAgIGlmICghZm9udCkgewogICAgICAgIG1pc3NpbmdGb250cy5wdXNoKHR5cGVmYWNlKTsKICAgICAgfQogICAgfQogICAgaWYgKG1pc3NpbmdGb250cy5sZW5ndGggPiAwKSB7CiAgICAgIHJldHVybiBtaXNzaW5nRm9udHM7CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgYXBwZW5kRm9udHMoZm9udHMsIHJlYWxseU1pc3NpbmdGb250cykgewogICAgdGhpcy5mb3JtWyRnbG9iYWxEYXRhXS5mb250RmluZGVyLmFkZChmb250cywgcmVhbGx5TWlzc2luZ0ZvbnRzKTsKICB9CiAgYXN5bmMgZ2V0UGFnZXMoKSB7CiAgICBpZiAoIXRoaXMucGFnZXMpIHsKICAgICAgYXdhaXQgdGhpcy5fY3JlYXRlUGFnZXMoKTsKICAgIH0KICAgIGNvbnN0IHBhZ2VzID0gdGhpcy5wYWdlczsKICAgIHRoaXMucGFnZXMgPSBudWxsOwogICAgcmV0dXJuIHBhZ2VzOwogIH0KICBzZXJpYWxpemVEYXRhKHN0b3JhZ2UpIHsKICAgIHJldHVybiB0aGlzLmRhdGFIYW5kbGVyLnNlcmlhbGl6ZShzdG9yYWdlKTsKICB9CiAgc3RhdGljIF9jcmVhdGVEb2N1bWVudChkYXRhKSB7CiAgICBpZiAoIWRhdGFbIi94ZHA6eGRwIl0pIHsKICAgICAgcmV0dXJuIGRhdGFbInhkcDp4ZHAiXTsKICAgIH0KICAgIHJldHVybiBPYmplY3QudmFsdWVzKGRhdGEpLmpvaW4oIiIpOwogIH0KICBzdGF0aWMgZ2V0UmljaFRleHRBc0h0bWwocmMpIHsKICAgIGlmICghcmMgfHwgdHlwZW9mIHJjICE9PSAic3RyaW5nIikgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIHRyeSB7CiAgICAgIGxldCByb290ID0gbmV3IFhGQVBhcnNlcihYaHRtbE5hbWVzcGFjZSwgdHJ1ZSkucGFyc2UocmMpOwogICAgICBpZiAoIVsiYm9keSIsICJ4aHRtbCJdLmluY2x1ZGVzKHJvb3RbJG5vZGVOYW1lXSkpIHsKICAgICAgICBjb25zdCBuZXdSb290ID0gWGh0bWxOYW1lc3BhY2UuYm9keSh7fSk7CiAgICAgICAgbmV3Um9vdFskYXBwZW5kQ2hpbGRdKHJvb3QpOwogICAgICAgIHJvb3QgPSBuZXdSb290OwogICAgICB9CiAgICAgIGNvbnN0IHJlc3VsdCA9IHJvb3RbJHRvSFRNTF0oKTsKICAgICAgaWYgKCFyZXN1bHQuc3VjY2VzcykgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGNvbnN0IHsKICAgICAgICBodG1sCiAgICAgIH0gPSByZXN1bHQ7CiAgICAgIGNvbnN0IHsKICAgICAgICBhdHRyaWJ1dGVzCiAgICAgIH0gPSBodG1sOwogICAgICBpZiAoYXR0cmlidXRlcykgewogICAgICAgIGlmIChhdHRyaWJ1dGVzLmNsYXNzKSB7CiAgICAgICAgICBhdHRyaWJ1dGVzLmNsYXNzID0gYXR0cmlidXRlcy5jbGFzcy5maWx0ZXIoYXR0ciA9PiAhYXR0ci5zdGFydHNXaXRoKCJ4ZmEiKSk7CiAgICAgICAgfQogICAgICAgIGF0dHJpYnV0ZXMuZGlyID0gImF1dG8iOwogICAgICB9CiAgICAgIHJldHVybiB7CiAgICAgICAgaHRtbCwKICAgICAgICBzdHI6IHJvb3RbJHRleHRdKCkKICAgICAgfTsKICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgd2FybihgWEZBIC0gYW4gZXJyb3Igb2NjdXJyZWQgZHVyaW5nIHBhcnNpbmcgb2YgcmljaCB0ZXh0OiAke2V9YCk7CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2Fubm90YXRpb24uanMKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgpjbGFzcyBBbm5vdGF0aW9uRmFjdG9yeSB7CiAgc3RhdGljIGNyZWF0ZUdsb2JhbHMocGRmTWFuYWdlcikgewogICAgcmV0dXJuIFByb21pc2UuYWxsKFtwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImFjcm9Gb3JtIiksIHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJ4ZmFEYXRhc2V0cyIpLCBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coInN0cnVjdFRyZWVSb290IiksIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiYmFzZVVybCIpLCBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImF0dGFjaG1lbnRzIiksIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiZ2xvYmFsQ29sb3JTcGFjZUNhY2hlIildKS50aGVuKChbYWNyb0Zvcm0sIHhmYURhdGFzZXRzLCBzdHJ1Y3RUcmVlUm9vdCwgYmFzZVVybCwgYXR0YWNobWVudHMsIGdsb2JhbENvbG9yU3BhY2VDYWNoZV0pID0+ICh7CiAgICAgIHBkZk1hbmFnZXIsCiAgICAgIGFjcm9Gb3JtOiBhY3JvRm9ybSBpbnN0YW5jZW9mIERpY3QgPyBhY3JvRm9ybSA6IERpY3QuZW1wdHksCiAgICAgIHhmYURhdGFzZXRzLAogICAgICBzdHJ1Y3RUcmVlUm9vdCwKICAgICAgYmFzZVVybCwKICAgICAgYXR0YWNobWVudHMsCiAgICAgIGdsb2JhbENvbG9yU3BhY2VDYWNoZQogICAgfSksIHJlYXNvbiA9PiB7CiAgICAgIHdhcm4oYGNyZWF0ZUdsb2JhbHM6ICIke3JlYXNvbn0iLmApOwogICAgICByZXR1cm4gbnVsbDsKICAgIH0pOwogIH0KICBzdGF0aWMgYXN5bmMgY3JlYXRlKHhyZWYsIHJlZiwgYW5ub3RhdGlvbkdsb2JhbHMsIGlkRmFjdG9yeSwgY29sbGVjdEZpZWxkcywgb3JwaGFuRmllbGRzLCBjb2xsZWN0QnlUeXBlLCBwYWdlUmVmKSB7CiAgICBjb25zdCBwYWdlSW5kZXggPSBjb2xsZWN0RmllbGRzID8gYXdhaXQgdGhpcy5fZ2V0UGFnZUluZGV4KHhyZWYsIHJlZiwgYW5ub3RhdGlvbkdsb2JhbHMucGRmTWFuYWdlcikgOiBudWxsOwogICAgcmV0dXJuIGFubm90YXRpb25HbG9iYWxzLnBkZk1hbmFnZXIuZW5zdXJlKHRoaXMsICJfY3JlYXRlIiwgW3hyZWYsIHJlZiwgYW5ub3RhdGlvbkdsb2JhbHMsIGlkRmFjdG9yeSwgY29sbGVjdEZpZWxkcywgb3JwaGFuRmllbGRzLCBjb2xsZWN0QnlUeXBlLCBwYWdlSW5kZXgsIHBhZ2VSZWZdKTsKICB9CiAgc3RhdGljIF9jcmVhdGUoeHJlZiwgcmVmLCBhbm5vdGF0aW9uR2xvYmFscywgaWRGYWN0b3J5LCBjb2xsZWN0RmllbGRzID0gZmFsc2UsIG9ycGhhbkZpZWxkcyA9IG51bGwsIGNvbGxlY3RCeVR5cGUgPSBudWxsLCBwYWdlSW5kZXggPSBudWxsLCBwYWdlUmVmID0gbnVsbCkgewogICAgY29uc3QgZGljdCA9IHhyZWYuZmV0Y2hJZlJlZihyZWYpOwogICAgaWYgKCEoZGljdCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICB9CiAgICBsZXQgc3VidHlwZSA9IGRpY3QuZ2V0KCJTdWJ0eXBlIik7CiAgICBzdWJ0eXBlID0gc3VidHlwZSBpbnN0YW5jZW9mIE5hbWUgPyBzdWJ0eXBlLm5hbWUgOiBudWxsOwogICAgaWYgKGNvbGxlY3RCeVR5cGUgJiYgIWNvbGxlY3RCeVR5cGUuaGFzKEFubm90YXRpb25UeXBlW3N1YnR5cGUudG9VcHBlckNhc2UoKV0pKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgewogICAgICBhY3JvRm9ybSwKICAgICAgcGRmTWFuYWdlcgogICAgfSA9IGFubm90YXRpb25HbG9iYWxzOwogICAgY29uc3QgaWQgPSByZWYgaW5zdGFuY2VvZiBSZWYgPyByZWYudG9TdHJpbmcoKSA6IGBhbm5vdF8ke2lkRmFjdG9yeS5jcmVhdGVPYmpJZCgpfWA7CiAgICBjb25zdCBwYXJhbWV0ZXJzID0gewogICAgICB4cmVmLAogICAgICByZWYsCiAgICAgIGRpY3QsCiAgICAgIHN1YnR5cGUsCiAgICAgIGlkLAogICAgICBhbm5vdGF0aW9uR2xvYmFscywKICAgICAgY29sbGVjdEZpZWxkcywKICAgICAgb3JwaGFuRmllbGRzLAogICAgICBuZWVkQXBwZWFyYW5jZXM6ICFjb2xsZWN0RmllbGRzICYmIGFjcm9Gb3JtLmdldCgiTmVlZEFwcGVhcmFuY2VzIikgPT09IHRydWUsCiAgICAgIHBhZ2VJbmRleCwKICAgICAgZXZhbHVhdG9yT3B0aW9uczogcGRmTWFuYWdlci5ldmFsdWF0b3JPcHRpb25zLAogICAgICBwYWdlUmVmCiAgICB9OwogICAgc3dpdGNoIChzdWJ0eXBlKSB7CiAgICAgIGNhc2UgIkxpbmsiOgogICAgICAgIHJldHVybiBuZXcgTGlua0Fubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIlRleHQiOgogICAgICAgIHJldHVybiBuZXcgVGV4dEFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIldpZGdldCI6CiAgICAgICAgbGV0IGZpZWxkVHlwZSA9IGdldEluaGVyaXRhYmxlUHJvcGVydHkoewogICAgICAgICAgZGljdCwKICAgICAgICAgIGtleTogIkZUIgogICAgICAgIH0pOwogICAgICAgIGZpZWxkVHlwZSA9IGZpZWxkVHlwZSBpbnN0YW5jZW9mIE5hbWUgPyBmaWVsZFR5cGUubmFtZSA6IG51bGw7CiAgICAgICAgc3dpdGNoIChmaWVsZFR5cGUpIHsKICAgICAgICAgIGNhc2UgIlR4IjoKICAgICAgICAgICAgcmV0dXJuIG5ldyBUZXh0V2lkZ2V0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgICAgIGNhc2UgIkJ0biI6CiAgICAgICAgICAgIHJldHVybiBuZXcgQnV0dG9uV2lkZ2V0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgICAgIGNhc2UgIkNoIjoKICAgICAgICAgICAgcmV0dXJuIG5ldyBDaG9pY2VXaWRnZXRBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICAgICAgY2FzZSAiU2lnIjoKICAgICAgICAgICAgcmV0dXJuIG5ldyBTaWduYXR1cmVXaWRnZXRBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICAgIH0KICAgICAgICB3YXJuKGBVbmltcGxlbWVudGVkIHdpZGdldCBmaWVsZCB0eXBlICIke2ZpZWxkVHlwZX0iLCBgICsgImZhbGxpbmcgYmFjayB0byBiYXNlIGZpZWxkIHR5cGUuIik7CiAgICAgICAgcmV0dXJuIG5ldyBXaWRnZXRBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJQb3B1cCI6CiAgICAgICAgcmV0dXJuIG5ldyBQb3B1cEFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIkZyZWVUZXh0IjoKICAgICAgICByZXR1cm4gbmV3IEZyZWVUZXh0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiTGluZSI6CiAgICAgICAgcmV0dXJuIG5ldyBMaW5lQW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiU3F1YXJlIjoKICAgICAgICByZXR1cm4gbmV3IFNxdWFyZUFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIkNpcmNsZSI6CiAgICAgICAgcmV0dXJuIG5ldyBDaXJjbGVBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJQb2x5TGluZSI6CiAgICAgICAgcmV0dXJuIG5ldyBQb2x5bGluZUFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIlBvbHlnb24iOgogICAgICAgIHJldHVybiBuZXcgUG9seWdvbkFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIkNhcmV0IjoKICAgICAgICByZXR1cm4gbmV3IENhcmV0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiSW5rIjoKICAgICAgICByZXR1cm4gbmV3IElua0Fubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGNhc2UgIkhpZ2hsaWdodCI6CiAgICAgICAgcmV0dXJuIG5ldyBIaWdobGlnaHRBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJVbmRlcmxpbmUiOgogICAgICAgIHJldHVybiBuZXcgVW5kZXJsaW5lQW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiU3F1aWdnbHkiOgogICAgICAgIHJldHVybiBuZXcgU3F1aWdnbHlBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJTdHJpa2VPdXQiOgogICAgICAgIHJldHVybiBuZXcgU3RyaWtlT3V0QW5ub3RhdGlvbihwYXJhbWV0ZXJzKTsKICAgICAgY2FzZSAiU3RhbXAiOgogICAgICAgIHJldHVybiBuZXcgU3RhbXBBbm5vdGF0aW9uKHBhcmFtZXRlcnMpOwogICAgICBjYXNlICJGaWxlQXR0YWNobWVudCI6CiAgICAgICAgcmV0dXJuIG5ldyBGaWxlQXR0YWNobWVudEFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgaWYgKCFjb2xsZWN0RmllbGRzKSB7CiAgICAgICAgICBpZiAoIXN1YnR5cGUpIHsKICAgICAgICAgICAgd2FybigiQW5ub3RhdGlvbiBpcyBtaXNzaW5nIHRoZSByZXF1aXJlZCAvU3VidHlwZS4iKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHdhcm4oYFVuaW1wbGVtZW50ZWQgYW5ub3RhdGlvbiB0eXBlICIke3N1YnR5cGV9IiwgYCArICJmYWxsaW5nIGJhY2sgdG8gYmFzZSBhbm5vdGF0aW9uLiIpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gbmV3IEFubm90YXRpb24ocGFyYW1ldGVycyk7CiAgICB9CiAgfQogIHN0YXRpYyBhc3luYyBfZ2V0UGFnZUluZGV4KHhyZWYsIHJlZiwgcGRmTWFuYWdlcikgewogICAgdHJ5IHsKICAgICAgY29uc3QgYW5ub3REaWN0ID0gYXdhaXQgeHJlZi5mZXRjaElmUmVmQXN5bmMocmVmKTsKICAgICAgaWYgKCEoYW5ub3REaWN0IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICByZXR1cm4gLTE7CiAgICAgIH0KICAgICAgY29uc3QgcGFnZVJlZiA9IGFubm90RGljdC5nZXRSYXcoIlAiKTsKICAgICAgaWYgKHBhZ2VSZWYgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICB0cnkgewogICAgICAgICAgY29uc3QgcGFnZUluZGV4ID0gYXdhaXQgcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJnZXRQYWdlSW5kZXgiLCBbcGFnZVJlZl0pOwogICAgICAgICAgcmV0dXJuIHBhZ2VJbmRleDsKICAgICAgICB9IGNhdGNoIChleCkgewogICAgICAgICAgaW5mbyhgX2dldFBhZ2VJbmRleCAtLSBub3QgYSB2YWxpZCBwYWdlIHJlZmVyZW5jZTogIiR7ZXh9Ii5gKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKGFubm90RGljdC5oYXMoIktpZHMiKSkgewogICAgICAgIHJldHVybiAtMTsKICAgICAgfQogICAgICBjb25zdCBudW1QYWdlcyA9IGF3YWl0IHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJudW1QYWdlcyIpOwogICAgICBmb3IgKGxldCBwYWdlSW5kZXggPSAwOyBwYWdlSW5kZXggPCBudW1QYWdlczsgcGFnZUluZGV4KyspIHsKICAgICAgICBjb25zdCBwYWdlID0gYXdhaXQgcGRmTWFuYWdlci5nZXRQYWdlKHBhZ2VJbmRleCk7CiAgICAgICAgY29uc3QgYW5ub3RhdGlvbnMgPSBhd2FpdCBwZGZNYW5hZ2VyLmVuc3VyZShwYWdlLCAiYW5ub3RhdGlvbnMiKTsKICAgICAgICBmb3IgKGNvbnN0IGFubm90UmVmIG9mIGFubm90YXRpb25zKSB7CiAgICAgICAgICBpZiAoYW5ub3RSZWYgaW5zdGFuY2VvZiBSZWYgJiYgaXNSZWZzRXF1YWwoYW5ub3RSZWYsIHJlZikpIHsKICAgICAgICAgICAgcmV0dXJuIHBhZ2VJbmRleDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIHdhcm4oYF9nZXRQYWdlSW5kZXg6ICIke2V4fSIuYCk7CiAgICB9CiAgICByZXR1cm4gLTE7CiAgfQogIHN0YXRpYyBnZW5lcmF0ZUltYWdlcyhhbm5vdGF0aW9ucywgeHJlZiwgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpIHsKICAgIGlmICghaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpIHsKICAgICAgd2FybigiZ2VuZXJhdGVJbWFnZXM6IE9mZnNjcmVlbkNhbnZhcyBpcyBub3Qgc3VwcG9ydGVkLCBjYW5ub3Qgc2F2ZSBvciBwcmludCBzb21lIGFubm90YXRpb25zIHdpdGggaW1hZ2VzLiIpOwogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGxldCBpbWFnZVByb21pc2VzOwogICAgZm9yIChjb25zdCB7CiAgICAgIGJpdG1hcElkLAogICAgICBiaXRtYXAKICAgIH0gb2YgYW5ub3RhdGlvbnMpIHsKICAgICAgaWYgKCFiaXRtYXApIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpbWFnZVByb21pc2VzIHx8PSBuZXcgTWFwKCk7CiAgICAgIGltYWdlUHJvbWlzZXMuc2V0KGJpdG1hcElkLCBTdGFtcEFubm90YXRpb24uY3JlYXRlSW1hZ2UoYml0bWFwLCB4cmVmKSk7CiAgICB9CiAgICByZXR1cm4gaW1hZ2VQcm9taXNlczsKICB9CiAgc3RhdGljIGFzeW5jIHNhdmVOZXdBbm5vdGF0aW9ucyhldmFsdWF0b3IsIHRhc2ssIGFubm90YXRpb25zLCBpbWFnZVByb21pc2VzLCBjaGFuZ2VzKSB7CiAgICBjb25zdCB4cmVmID0gZXZhbHVhdG9yLnhyZWY7CiAgICBsZXQgYmFzZUZvbnRSZWY7CiAgICBjb25zdCBwcm9taXNlcyA9IFtdOwogICAgY29uc3QgewogICAgICBpc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZAogICAgfSA9IGV2YWx1YXRvci5vcHRpb25zOwogICAgZm9yIChjb25zdCBhbm5vdGF0aW9uIG9mIGFubm90YXRpb25zKSB7CiAgICAgIGlmIChhbm5vdGF0aW9uLmRlbGV0ZWQpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBzd2l0Y2ggKGFubm90YXRpb24uYW5ub3RhdGlvblR5cGUpIHsKICAgICAgICBjYXNlIEFubm90YXRpb25FZGl0b3JUeXBlLkZSRUVURVhUOgogICAgICAgICAgaWYgKCFiYXNlRm9udFJlZikgewogICAgICAgICAgICBjb25zdCBiYXNlRm9udCA9IG5ldyBEaWN0KHhyZWYpOwogICAgICAgICAgICBiYXNlRm9udC5zZXRJZk5hbWUoIkJhc2VGb250IiwgIkhlbHZldGljYSIpOwogICAgICAgICAgICBiYXNlRm9udC5zZXRJZk5hbWUoIlR5cGUiLCAiRm9udCIpOwogICAgICAgICAgICBiYXNlRm9udC5zZXRJZk5hbWUoIlN1YnR5cGUiLCAiVHlwZTEiKTsKICAgICAgICAgICAgYmFzZUZvbnQuc2V0SWZOYW1lKCJFbmNvZGluZyIsICJXaW5BbnNpRW5jb2RpbmciKTsKICAgICAgICAgICAgYmFzZUZvbnRSZWYgPSB4cmVmLmdldE5ld1RlbXBvcmFyeVJlZigpOwogICAgICAgICAgICBjaGFuZ2VzLnB1dChiYXNlRm9udFJlZiwgewogICAgICAgICAgICAgIGRhdGE6IGJhc2VGb250CiAgICAgICAgICAgIH0pOwogICAgICAgICAgfQogICAgICAgICAgcHJvbWlzZXMucHVzaChGcmVlVGV4dEFubm90YXRpb24uY3JlYXRlTmV3QW5ub3RhdGlvbih4cmVmLCBhbm5vdGF0aW9uLCBjaGFuZ2VzLCB7CiAgICAgICAgICAgIGV2YWx1YXRvciwKICAgICAgICAgICAgdGFzaywKICAgICAgICAgICAgYmFzZUZvbnRSZWYKICAgICAgICAgIH0pKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgQW5ub3RhdGlvbkVkaXRvclR5cGUuSElHSExJR0hUOgogICAgICAgICAgaWYgKGFubm90YXRpb24ucXVhZFBvaW50cykgewogICAgICAgICAgICBwcm9taXNlcy5wdXNoKEhpZ2hsaWdodEFubm90YXRpb24uY3JlYXRlTmV3QW5ub3RhdGlvbih4cmVmLCBhbm5vdGF0aW9uLCBjaGFuZ2VzKSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBwcm9taXNlcy5wdXNoKElua0Fubm90YXRpb24uY3JlYXRlTmV3QW5ub3RhdGlvbih4cmVmLCBhbm5vdGF0aW9uLCBjaGFuZ2VzKSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIEFubm90YXRpb25FZGl0b3JUeXBlLklOSzoKICAgICAgICAgIHByb21pc2VzLnB1c2goSW5rQW5ub3RhdGlvbi5jcmVhdGVOZXdBbm5vdGF0aW9uKHhyZWYsIGFubm90YXRpb24sIGNoYW5nZXMpKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgQW5ub3RhdGlvbkVkaXRvclR5cGUuU1RBTVA6CiAgICAgICAgICBjb25zdCBpbWFnZSA9IGlzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkID8gYXdhaXQgaW1hZ2VQcm9taXNlcz8uZ2V0KGFubm90YXRpb24uYml0bWFwSWQpIDogbnVsbDsKICAgICAgICAgIGlmIChpbWFnZT8uaW1hZ2VTdHJlYW0pIHsKICAgICAgICAgICAgY29uc3QgewogICAgICAgICAgICAgIGltYWdlU3RyZWFtLAogICAgICAgICAgICAgIHNtYXNrU3RyZWFtCiAgICAgICAgICAgIH0gPSBpbWFnZTsKICAgICAgICAgICAgaWYgKHNtYXNrU3RyZWFtKSB7CiAgICAgICAgICAgICAgY29uc3Qgc21hc2tSZWYgPSB4cmVmLmdldE5ld1RlbXBvcmFyeVJlZigpOwogICAgICAgICAgICAgIGNoYW5nZXMucHV0KHNtYXNrUmVmLCB7CiAgICAgICAgICAgICAgICBkYXRhOiBzbWFza1N0cmVhbQogICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgIGltYWdlU3RyZWFtLmRpY3Quc2V0KCJTTWFzayIsIHNtYXNrUmVmKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBjb25zdCBpbWFnZVJlZiA9IGltYWdlLmltYWdlUmVmID0geHJlZi5nZXROZXdUZW1wb3JhcnlSZWYoKTsKICAgICAgICAgICAgY2hhbmdlcy5wdXQoaW1hZ2VSZWYsIHsKICAgICAgICAgICAgICBkYXRhOiBpbWFnZVN0cmVhbQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgaW1hZ2UuaW1hZ2VTdHJlYW0gPSBpbWFnZS5zbWFza1N0cmVhbSA9IG51bGw7CiAgICAgICAgICB9CiAgICAgICAgICBwcm9taXNlcy5wdXNoKFN0YW1wQW5ub3RhdGlvbi5jcmVhdGVOZXdBbm5vdGF0aW9uKHhyZWYsIGFubm90YXRpb24sIGNoYW5nZXMsIHsKICAgICAgICAgICAgaW1hZ2UKICAgICAgICAgIH0pKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgQW5ub3RhdGlvbkVkaXRvclR5cGUuU0lHTkFUVVJFOgogICAgICAgICAgcHJvbWlzZXMucHVzaChTdGFtcEFubm90YXRpb24uY3JlYXRlTmV3QW5ub3RhdGlvbih4cmVmLCBhbm5vdGF0aW9uLCBjaGFuZ2VzLCB7fSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiB7CiAgICAgIGFubm90YXRpb25zOiAoYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpKS5mbGF0KCkKICAgIH07CiAgfQogIHN0YXRpYyBhc3luYyBwcmludE5ld0Fubm90YXRpb25zKGFubm90YXRpb25HbG9iYWxzLCBldmFsdWF0b3IsIHRhc2ssIGFubm90YXRpb25zLCBpbWFnZVByb21pc2VzKSB7CiAgICBpZiAoIWFubm90YXRpb25zKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgewogICAgICBvcHRpb25zLAogICAgICB4cmVmCiAgICB9ID0gZXZhbHVhdG9yOwogICAgY29uc3QgcHJvbWlzZXMgPSBbXTsKICAgIGZvciAoY29uc3QgYW5ub3RhdGlvbiBvZiBhbm5vdGF0aW9ucykgewogICAgICBpZiAoYW5ub3RhdGlvbi5kZWxldGVkKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgc3dpdGNoIChhbm5vdGF0aW9uLmFubm90YXRpb25UeXBlKSB7CiAgICAgICAgY2FzZSBBbm5vdGF0aW9uRWRpdG9yVHlwZS5GUkVFVEVYVDoKICAgICAgICAgIHByb21pc2VzLnB1c2goRnJlZVRleHRBbm5vdGF0aW9uLmNyZWF0ZU5ld1ByaW50QW5ub3RhdGlvbihhbm5vdGF0aW9uR2xvYmFscywgeHJlZiwgYW5ub3RhdGlvbiwgewogICAgICAgICAgICBldmFsdWF0b3IsCiAgICAgICAgICAgIHRhc2ssCiAgICAgICAgICAgIGV2YWx1YXRvck9wdGlvbnM6IG9wdGlvbnMKICAgICAgICAgIH0pKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgQW5ub3RhdGlvbkVkaXRvclR5cGUuSElHSExJR0hUOgogICAgICAgICAgaWYgKGFubm90YXRpb24ucXVhZFBvaW50cykgewogICAgICAgICAgICBwcm9taXNlcy5wdXNoKEhpZ2hsaWdodEFubm90YXRpb24uY3JlYXRlTmV3UHJpbnRBbm5vdGF0aW9uKGFubm90YXRpb25HbG9iYWxzLCB4cmVmLCBhbm5vdGF0aW9uLCB7CiAgICAgICAgICAgICAgZXZhbHVhdG9yT3B0aW9uczogb3B0aW9ucwogICAgICAgICAgICB9KSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBwcm9taXNlcy5wdXNoKElua0Fubm90YXRpb24uY3JlYXRlTmV3UHJpbnRBbm5vdGF0aW9uKGFubm90YXRpb25HbG9iYWxzLCB4cmVmLCBhbm5vdGF0aW9uLCB7CiAgICAgICAgICAgICAgZXZhbHVhdG9yT3B0aW9uczogb3B0aW9ucwogICAgICAgICAgICB9KSk7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIEFubm90YXRpb25FZGl0b3JUeXBlLklOSzoKICAgICAgICAgIHByb21pc2VzLnB1c2goSW5rQW5ub3RhdGlvbi5jcmVhdGVOZXdQcmludEFubm90YXRpb24oYW5ub3RhdGlvbkdsb2JhbHMsIHhyZWYsIGFubm90YXRpb24sIHsKICAgICAgICAgICAgZXZhbHVhdG9yT3B0aW9uczogb3B0aW9ucwogICAgICAgICAgfSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBBbm5vdGF0aW9uRWRpdG9yVHlwZS5TVEFNUDoKICAgICAgICAgIGNvbnN0IGltYWdlID0gb3B0aW9ucy5pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCA/IGF3YWl0IGltYWdlUHJvbWlzZXM/LmdldChhbm5vdGF0aW9uLmJpdG1hcElkKSA6IG51bGw7CiAgICAgICAgICBpZiAoaW1hZ2U/LmltYWdlU3RyZWFtKSB7CiAgICAgICAgICAgIGNvbnN0IHsKICAgICAgICAgICAgICBpbWFnZVN0cmVhbSwKICAgICAgICAgICAgICBzbWFza1N0cmVhbQogICAgICAgICAgICB9ID0gaW1hZ2U7CiAgICAgICAgICAgIGlmIChzbWFza1N0cmVhbSkgewogICAgICAgICAgICAgIGltYWdlU3RyZWFtLmRpY3Quc2V0KCJTTWFzayIsIHNtYXNrU3RyZWFtKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBpbWFnZS5pbWFnZVJlZiA9IG5ldyBKcGVnU3RyZWFtKGltYWdlU3RyZWFtLCBpbWFnZVN0cmVhbS5sZW5ndGgpOwogICAgICAgICAgICBpbWFnZS5pbWFnZVN0cmVhbSA9IGltYWdlLnNtYXNrU3RyZWFtID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICAgIHByb21pc2VzLnB1c2goU3RhbXBBbm5vdGF0aW9uLmNyZWF0ZU5ld1ByaW50QW5ub3RhdGlvbihhbm5vdGF0aW9uR2xvYmFscywgeHJlZiwgYW5ub3RhdGlvbiwgewogICAgICAgICAgICBpbWFnZSwKICAgICAgICAgICAgZXZhbHVhdG9yT3B0aW9uczogb3B0aW9ucwogICAgICAgICAgfSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBBbm5vdGF0aW9uRWRpdG9yVHlwZS5TSUdOQVRVUkU6CiAgICAgICAgICBwcm9taXNlcy5wdXNoKFN0YW1wQW5ub3RhdGlvbi5jcmVhdGVOZXdQcmludEFubm90YXRpb24oYW5ub3RhdGlvbkdsb2JhbHMsIHhyZWYsIGFubm90YXRpb24sIHsKICAgICAgICAgICAgZXZhbHVhdG9yT3B0aW9uczogb3B0aW9ucwogICAgICAgICAgfSkpOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcyk7CiAgfQp9CmZ1bmN0aW9uIGdldFJnYkNvbG9yKGNvbG9yLCBkZWZhdWx0Q29sb3IgPSBuZXcgVWludDhDbGFtcGVkQXJyYXkoMykpIHsKICBpZiAoIUFycmF5LmlzQXJyYXkoY29sb3IpKSB7CiAgICByZXR1cm4gZGVmYXVsdENvbG9yOwogIH0KICBjb25zdCByZ2JDb2xvciA9IGRlZmF1bHRDb2xvciB8fCBuZXcgVWludDhDbGFtcGVkQXJyYXkoMyk7CiAgc3dpdGNoIChjb2xvci5sZW5ndGgpIHsKICAgIGNhc2UgMDoKICAgICAgcmV0dXJuIG51bGw7CiAgICBjYXNlIDE6CiAgICAgIENvbG9yU3BhY2VVdGlscy5ncmF5LmdldFJnYkl0ZW0oY29sb3IsIDAsIHJnYkNvbG9yLCAwKTsKICAgICAgcmV0dXJuIHJnYkNvbG9yOwogICAgY2FzZSAzOgogICAgICBDb2xvclNwYWNlVXRpbHMucmdiLmdldFJnYkl0ZW0oY29sb3IsIDAsIHJnYkNvbG9yLCAwKTsKICAgICAgcmV0dXJuIHJnYkNvbG9yOwogICAgY2FzZSA0OgogICAgICBDb2xvclNwYWNlVXRpbHMuY215ay5nZXRSZ2JJdGVtKGNvbG9yLCAwLCByZ2JDb2xvciwgMCk7CiAgICAgIHJldHVybiByZ2JDb2xvcjsKICAgIGRlZmF1bHQ6CiAgICAgIHJldHVybiBkZWZhdWx0Q29sb3I7CiAgfQp9CmZ1bmN0aW9uIGdldFBkZkNvbG9yQXJyYXkoY29sb3IsIGRlZmF1bHRWYWx1ZSA9IG51bGwpIHsKICByZXR1cm4gY29sb3IgJiYgQXJyYXkuZnJvbShjb2xvciwgYyA9PiBjIC8gMjU1KSB8fCBkZWZhdWx0VmFsdWU7Cn0KZnVuY3Rpb24gZ2V0UXVhZFBvaW50cyhkaWN0LCByZWN0KSB7CiAgY29uc3QgcXVhZFBvaW50cyA9IGRpY3QuZ2V0QXJyYXkoIlF1YWRQb2ludHMiKTsKICBpZiAoIWlzTnVtYmVyQXJyYXkocXVhZFBvaW50cywgbnVsbCkgfHwgcXVhZFBvaW50cy5sZW5ndGggPT09IDAgfHwgcXVhZFBvaW50cy5sZW5ndGggJSA4ID4gMCkgewogICAgcmV0dXJuIG51bGw7CiAgfQogIGNvbnN0IG5ld1F1YWRQb2ludHMgPSBuZXcgRmxvYXQzMkFycmF5KHF1YWRQb2ludHMubGVuZ3RoKTsKICBmb3IgKGxldCBpID0gMCwgaWkgPSBxdWFkUG9pbnRzLmxlbmd0aDsgaSA8IGlpOyBpICs9IDgpIHsKICAgIGNvbnN0IFt4MSwgeTEsIHgyLCB5MiwgeDMsIHkzLCB4NCwgeTRdID0gcXVhZFBvaW50cy5zbGljZShpLCBpICsgOCk7CiAgICBjb25zdCBtaW5YID0gTWF0aC5taW4oeDEsIHgyLCB4MywgeDQpOwogICAgY29uc3QgbWF4WCA9IE1hdGgubWF4KHgxLCB4MiwgeDMsIHg0KTsKICAgIGNvbnN0IG1pblkgPSBNYXRoLm1pbih5MSwgeTIsIHkzLCB5NCk7CiAgICBjb25zdCBtYXhZID0gTWF0aC5tYXgoeTEsIHkyLCB5MywgeTQpOwogICAgaWYgKHJlY3QgIT09IG51bGwgJiYgKG1pblggPCByZWN0WzBdIHx8IG1heFggPiByZWN0WzJdIHx8IG1pblkgPCByZWN0WzFdIHx8IG1heFkgPiByZWN0WzNdKSkgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIG5ld1F1YWRQb2ludHMuc2V0KFttaW5YLCBtYXhZLCBtYXhYLCBtYXhZLCBtaW5YLCBtaW5ZLCBtYXhYLCBtaW5ZXSwgaSk7CiAgfQogIHJldHVybiBuZXdRdWFkUG9pbnRzOwp9CmZ1bmN0aW9uIGdldFRyYW5zZm9ybU1hdHJpeChyZWN0LCBiYm94LCBtYXRyaXgpIHsKICBjb25zdCBtaW5NYXggPSBuZXcgRmxvYXQzMkFycmF5KFtJbmZpbml0eSwgSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5XSk7CiAgVXRpbC5heGlhbEFsaWduZWRCb3VuZGluZ0JveChiYm94LCBtYXRyaXgsIG1pbk1heCk7CiAgY29uc3QgW21pblgsIG1pblksIG1heFgsIG1heFldID0gbWluTWF4OwogIGlmIChtaW5YID09PSBtYXhYIHx8IG1pblkgPT09IG1heFkpIHsKICAgIHJldHVybiBbMSwgMCwgMCwgMSwgcmVjdFswXSwgcmVjdFsxXV07CiAgfQogIGNvbnN0IHhSYXRpbyA9IChyZWN0WzJdIC0gcmVjdFswXSkgLyAobWF4WCAtIG1pblgpOwogIGNvbnN0IHlSYXRpbyA9IChyZWN0WzNdIC0gcmVjdFsxXSkgLyAobWF4WSAtIG1pblkpOwogIHJldHVybiBbeFJhdGlvLCAwLCAwLCB5UmF0aW8sIHJlY3RbMF0gLSBtaW5YICogeFJhdGlvLCByZWN0WzFdIC0gbWluWSAqIHlSYXRpb107Cn0KY2xhc3MgQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBjb25zdCB7CiAgICAgIGRpY3QsCiAgICAgIHhyZWYsCiAgICAgIGFubm90YXRpb25HbG9iYWxzLAogICAgICByZWYsCiAgICAgIG9ycGhhbkZpZWxkcwogICAgfSA9IHBhcmFtczsKICAgIGNvbnN0IHBhcmVudFJlZiA9IG9ycGhhbkZpZWxkcz8uZ2V0KHJlZik7CiAgICBpZiAocGFyZW50UmVmKSB7CiAgICAgIGRpY3Quc2V0KCJQYXJlbnQiLCBwYXJlbnRSZWYpOwogICAgfQogICAgdGhpcy5zZXRUaXRsZShkaWN0LmdldCgiVCIpKTsKICAgIHRoaXMuc2V0Q29udGVudHMoZGljdC5nZXQoIkNvbnRlbnRzIikpOwogICAgdGhpcy5zZXRNb2RpZmljYXRpb25EYXRlKGRpY3QuZ2V0KCJNIikpOwogICAgdGhpcy5zZXRGbGFncyhkaWN0LmdldCgiRiIpKTsKICAgIHRoaXMuc2V0UmVjdGFuZ2xlKGRpY3QuZ2V0QXJyYXkoIlJlY3QiKSk7CiAgICB0aGlzLnNldENvbG9yKGRpY3QuZ2V0QXJyYXkoIkMiKSk7CiAgICB0aGlzLnNldEJvcmRlclN0eWxlKGRpY3QpOwogICAgdGhpcy5zZXRBcHBlYXJhbmNlKGRpY3QpOwogICAgdGhpcy5zZXRPcHRpb25hbENvbnRlbnQoZGljdCk7CiAgICBjb25zdCBNSyA9IGRpY3QuZ2V0KCJNSyIpOwogICAgdGhpcy5zZXRCb3JkZXJBbmRCYWNrZ3JvdW5kQ29sb3JzKE1LKTsKICAgIHRoaXMuc2V0Um90YXRpb24oTUssIGRpY3QpOwogICAgdGhpcy5yZWYgPSBwYXJhbXMucmVmIGluc3RhbmNlb2YgUmVmID8gcGFyYW1zLnJlZiA6IG51bGw7CiAgICB0aGlzLl9zdHJlYW1zID0gW107CiAgICBpZiAodGhpcy5hcHBlYXJhbmNlKSB7CiAgICAgIHRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLmFwcGVhcmFuY2UpOwogICAgfQogICAgY29uc3QgaXNMb2NrZWQgPSAhISh0aGlzLmZsYWdzICYgQW5ub3RhdGlvbkZsYWcuTE9DS0VEKTsKICAgIGNvbnN0IGlzQ29udGVudExvY2tlZCA9ICEhKHRoaXMuZmxhZ3MgJiBBbm5vdGF0aW9uRmxhZy5MT0NLRURDT05URU5UUyk7CiAgICB0aGlzLmRhdGEgPSB7CiAgICAgIGFubm90YXRpb25GbGFnczogdGhpcy5mbGFncywKICAgICAgYm9yZGVyU3R5bGU6IHRoaXMuYm9yZGVyU3R5bGUsCiAgICAgIGNvbG9yOiB0aGlzLmNvbG9yLAogICAgICBiYWNrZ3JvdW5kQ29sb3I6IHRoaXMuYmFja2dyb3VuZENvbG9yLAogICAgICBib3JkZXJDb2xvcjogdGhpcy5ib3JkZXJDb2xvciwKICAgICAgcm90YXRpb246IHRoaXMucm90YXRpb24sCiAgICAgIGNvbnRlbnRzT2JqOiB0aGlzLl9jb250ZW50cywKICAgICAgaGFzQXBwZWFyYW5jZTogISF0aGlzLmFwcGVhcmFuY2UsCiAgICAgIGlkOiBwYXJhbXMuaWQsCiAgICAgIG1vZGlmaWNhdGlvbkRhdGU6IHRoaXMubW9kaWZpY2F0aW9uRGF0ZSwKICAgICAgcmVjdDogdGhpcy5yZWN0YW5nbGUsCiAgICAgIHN1YnR5cGU6IHBhcmFtcy5zdWJ0eXBlLAogICAgICBoYXNPd25DYW52YXM6IGZhbHNlLAogICAgICBub1JvdGF0ZTogISEodGhpcy5mbGFncyAmIEFubm90YXRpb25GbGFnLk5PUk9UQVRFKSwKICAgICAgbm9IVE1MOiBpc0xvY2tlZCAmJiBpc0NvbnRlbnRMb2NrZWQsCiAgICAgIGlzRWRpdGFibGU6IGZhbHNlLAogICAgICBzdHJ1Y3RQYXJlbnQ6IC0xCiAgICB9OwogICAgaWYgKGFubm90YXRpb25HbG9iYWxzLnN0cnVjdFRyZWVSb290KSB7CiAgICAgIGxldCBzdHJ1Y3RQYXJlbnQgPSBkaWN0LmdldCgiU3RydWN0UGFyZW50Iik7CiAgICAgIHRoaXMuZGF0YS5zdHJ1Y3RQYXJlbnQgPSBzdHJ1Y3RQYXJlbnQgPSBOdW1iZXIuaXNJbnRlZ2VyKHN0cnVjdFBhcmVudCkgJiYgc3RydWN0UGFyZW50ID49IDAgPyBzdHJ1Y3RQYXJlbnQgOiAtMTsKICAgICAgYW5ub3RhdGlvbkdsb2JhbHMuc3RydWN0VHJlZVJvb3QuYWRkQW5ub3RhdGlvbklkVG9QYWdlKHBhcmFtcy5wYWdlUmVmLCBzdHJ1Y3RQYXJlbnQpOwogICAgfQogICAgaWYgKHBhcmFtcy5jb2xsZWN0RmllbGRzKSB7CiAgICAgIGNvbnN0IGtpZHMgPSBkaWN0LmdldCgiS2lkcyIpOwogICAgICBpZiAoQXJyYXkuaXNBcnJheShraWRzKSkgewogICAgICAgIGNvbnN0IGtpZElkcyA9IFtdOwogICAgICAgIGZvciAoY29uc3Qga2lkIG9mIGtpZHMpIHsKICAgICAgICAgIGlmIChraWQgaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICAgICAga2lkSWRzLnB1c2goa2lkLnRvU3RyaW5nKCkpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoa2lkSWRzLmxlbmd0aCAhPT0gMCkgewogICAgICAgICAgdGhpcy5kYXRhLmtpZElkcyA9IGtpZElkczsKICAgICAgICB9CiAgICAgIH0KICAgICAgdGhpcy5kYXRhLmFjdGlvbnMgPSBjb2xsZWN0QWN0aW9ucyh4cmVmLCBkaWN0LCBBbm5vdGF0aW9uQWN0aW9uRXZlbnRUeXBlKTsKICAgICAgdGhpcy5kYXRhLmZpZWxkTmFtZSA9IHRoaXMuX2NvbnN0cnVjdEZpZWxkTmFtZShkaWN0KTsKICAgICAgdGhpcy5kYXRhLnBhZ2VJbmRleCA9IHBhcmFtcy5wYWdlSW5kZXg7CiAgICB9CiAgICBjb25zdCBpdCA9IGRpY3QuZ2V0KCJJVCIpOwogICAgaWYgKGl0IGluc3RhbmNlb2YgTmFtZSkgewogICAgICB0aGlzLmRhdGEuaXQgPSBpdC5uYW1lOwogICAgfQogICAgdGhpcy5faXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQgPSBwYXJhbXMuZXZhbHVhdG9yT3B0aW9ucy5pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZDsKICAgIHRoaXMuX2ZhbGxiYWNrRm9udERpY3QgPSBudWxsOwogICAgdGhpcy5fbmVlZEFwcGVhcmFuY2VzID0gZmFsc2U7CiAgfQogIF9oYXNGbGFnKGZsYWdzLCBmbGFnKSB7CiAgICByZXR1cm4gISEoZmxhZ3MgJiBmbGFnKTsKICB9CiAgX2J1aWxkRmxhZ3Mobm9WaWV3LCBub1ByaW50KSB7CiAgICBsZXQgewogICAgICBmbGFncwogICAgfSA9IHRoaXM7CiAgICBpZiAobm9WaWV3ID09PSB1bmRlZmluZWQpIHsKICAgICAgaWYgKG5vUHJpbnQgPT09IHVuZGVmaW5lZCkgewogICAgICAgIHJldHVybiB1bmRlZmluZWQ7CiAgICAgIH0KICAgICAgaWYgKG5vUHJpbnQpIHsKICAgICAgICByZXR1cm4gZmxhZ3MgJiB+QW5ub3RhdGlvbkZsYWcuUFJJTlQ7CiAgICAgIH0KICAgICAgcmV0dXJuIGZsYWdzICYgfkFubm90YXRpb25GbGFnLkhJRERFTiB8IEFubm90YXRpb25GbGFnLlBSSU5UOwogICAgfQogICAgaWYgKG5vVmlldykgewogICAgICBmbGFncyB8PSBBbm5vdGF0aW9uRmxhZy5QUklOVDsKICAgICAgaWYgKG5vUHJpbnQpIHsKICAgICAgICByZXR1cm4gZmxhZ3MgJiB+QW5ub3RhdGlvbkZsYWcuTk9WSUVXIHwgQW5ub3RhdGlvbkZsYWcuSElEREVOOwogICAgICB9CiAgICAgIHJldHVybiBmbGFncyAmIH5Bbm5vdGF0aW9uRmxhZy5ISURERU4gfCBBbm5vdGF0aW9uRmxhZy5OT1ZJRVc7CiAgICB9CiAgICBmbGFncyAmPSB+KEFubm90YXRpb25GbGFnLkhJRERFTiB8IEFubm90YXRpb25GbGFnLk5PVklFVyk7CiAgICBpZiAobm9QcmludCkgewogICAgICByZXR1cm4gZmxhZ3MgJiB+QW5ub3RhdGlvbkZsYWcuUFJJTlQ7CiAgICB9CiAgICByZXR1cm4gZmxhZ3MgfCBBbm5vdGF0aW9uRmxhZy5QUklOVDsKICB9CiAgX2lzVmlld2FibGUoZmxhZ3MpIHsKICAgIHJldHVybiAhdGhpcy5faGFzRmxhZyhmbGFncywgQW5ub3RhdGlvbkZsYWcuSU5WSVNJQkxFKSAmJiAhdGhpcy5faGFzRmxhZyhmbGFncywgQW5ub3RhdGlvbkZsYWcuTk9WSUVXKTsKICB9CiAgX2lzUHJpbnRhYmxlKGZsYWdzKSB7CiAgICByZXR1cm4gdGhpcy5faGFzRmxhZyhmbGFncywgQW5ub3RhdGlvbkZsYWcuUFJJTlQpICYmICF0aGlzLl9oYXNGbGFnKGZsYWdzLCBBbm5vdGF0aW9uRmxhZy5ISURERU4pICYmICF0aGlzLl9oYXNGbGFnKGZsYWdzLCBBbm5vdGF0aW9uRmxhZy5JTlZJU0lCTEUpOwogIH0KICBtdXN0QmVWaWV3ZWQoYW5ub3RhdGlvblN0b3JhZ2UsIF9yZW5kZXJGb3JtcykgewogICAgY29uc3Qgbm9WaWV3ID0gYW5ub3RhdGlvblN0b3JhZ2U/LmdldCh0aGlzLmRhdGEuaWQpPy5ub1ZpZXc7CiAgICBpZiAobm9WaWV3ICE9PSB1bmRlZmluZWQpIHsKICAgICAgcmV0dXJuICFub1ZpZXc7CiAgICB9CiAgICByZXR1cm4gdGhpcy52aWV3YWJsZSAmJiAhdGhpcy5faGFzRmxhZyh0aGlzLmZsYWdzLCBBbm5vdGF0aW9uRmxhZy5ISURERU4pOwogIH0KICBtdXN0QmVQcmludGVkKGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBjb25zdCBub1ByaW50ID0gYW5ub3RhdGlvblN0b3JhZ2U/LmdldCh0aGlzLmRhdGEuaWQpPy5ub1ByaW50OwogICAgaWYgKG5vUHJpbnQgIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gIW5vUHJpbnQ7CiAgICB9CiAgICByZXR1cm4gdGhpcy5wcmludGFibGU7CiAgfQogIG11c3RCZVZpZXdlZFdoZW5FZGl0aW5nKGlzRWRpdGluZywgbW9kaWZpZWRJZHMgPSBudWxsKSB7CiAgICByZXR1cm4gaXNFZGl0aW5nID8gIXRoaXMuZGF0YS5pc0VkaXRhYmxlIDogIW1vZGlmaWVkSWRzPy5oYXModGhpcy5kYXRhLmlkKTsKICB9CiAgZ2V0IHZpZXdhYmxlKCkgewogICAgaWYgKHRoaXMuZGF0YS5xdWFkUG9pbnRzID09PSBudWxsKSB7CiAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KICAgIGlmICh0aGlzLmZsYWdzID09PSAwKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgcmV0dXJuIHRoaXMuX2lzVmlld2FibGUodGhpcy5mbGFncyk7CiAgfQogIGdldCBwcmludGFibGUoKSB7CiAgICBpZiAodGhpcy5kYXRhLnF1YWRQb2ludHMgPT09IG51bGwpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgaWYgKHRoaXMuZmxhZ3MgPT09IDApIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgcmV0dXJuIHRoaXMuX2lzUHJpbnRhYmxlKHRoaXMuZmxhZ3MpOwogIH0KICBfcGFyc2VTdHJpbmdIZWxwZXIoZGF0YSkgewogICAgY29uc3Qgc3RyID0gdHlwZW9mIGRhdGEgPT09ICJzdHJpbmciID8gc3RyaW5nVG9QREZTdHJpbmcoZGF0YSkgOiAiIjsKICAgIGNvbnN0IGRpciA9IHN0ciAmJiBiaWRpKHN0cikuZGlyID09PSAicnRsIiA/ICJydGwiIDogImx0ciI7CiAgICByZXR1cm4gewogICAgICBzdHIsCiAgICAgIGRpcgogICAgfTsKICB9CiAgc2V0RGVmYXVsdEFwcGVhcmFuY2UocGFyYW1zKSB7CiAgICBjb25zdCB7CiAgICAgIGRpY3QsCiAgICAgIGFubm90YXRpb25HbG9iYWxzCiAgICB9ID0gcGFyYW1zOwogICAgY29uc3QgZGVmYXVsdEFwcGVhcmFuY2UgPSBnZXRJbmhlcml0YWJsZVByb3BlcnR5KHsKICAgICAgZGljdCwKICAgICAga2V5OiAiREEiCiAgICB9KSB8fCBhbm5vdGF0aW9uR2xvYmFscy5hY3JvRm9ybS5nZXQoIkRBIik7CiAgICB0aGlzLl9kZWZhdWx0QXBwZWFyYW5jZSA9IHR5cGVvZiBkZWZhdWx0QXBwZWFyYW5jZSA9PT0gInN0cmluZyIgPyBkZWZhdWx0QXBwZWFyYW5jZSA6ICIiOwogICAgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YSA9IHBhcnNlRGVmYXVsdEFwcGVhcmFuY2UodGhpcy5fZGVmYXVsdEFwcGVhcmFuY2UpOwogIH0KICBzZXRUaXRsZSh0aXRsZSkgewogICAgdGhpcy5fdGl0bGUgPSB0aGlzLl9wYXJzZVN0cmluZ0hlbHBlcih0aXRsZSk7CiAgfQogIHNldENvbnRlbnRzKGNvbnRlbnRzKSB7CiAgICB0aGlzLl9jb250ZW50cyA9IHRoaXMuX3BhcnNlU3RyaW5nSGVscGVyKGNvbnRlbnRzKTsKICB9CiAgc2V0TW9kaWZpY2F0aW9uRGF0ZShtb2RpZmljYXRpb25EYXRlKSB7CiAgICB0aGlzLm1vZGlmaWNhdGlvbkRhdGUgPSB0eXBlb2YgbW9kaWZpY2F0aW9uRGF0ZSA9PT0gInN0cmluZyIgPyBtb2RpZmljYXRpb25EYXRlIDogbnVsbDsKICB9CiAgc2V0RmxhZ3MoZmxhZ3MpIHsKICAgIHRoaXMuZmxhZ3MgPSBOdW1iZXIuaXNJbnRlZ2VyKGZsYWdzKSAmJiBmbGFncyA+IDAgPyBmbGFncyA6IDA7CiAgICBpZiAodGhpcy5mbGFncyAmIEFubm90YXRpb25GbGFnLklOVklTSUJMRSAmJiB0aGlzLmNvbnN0cnVjdG9yLm5hbWUgIT09ICJBbm5vdGF0aW9uIikgewogICAgICB0aGlzLmZsYWdzIF49IEFubm90YXRpb25GbGFnLklOVklTSUJMRTsKICAgIH0KICB9CiAgaGFzRmxhZyhmbGFnKSB7CiAgICByZXR1cm4gdGhpcy5faGFzRmxhZyh0aGlzLmZsYWdzLCBmbGFnKTsKICB9CiAgc2V0UmVjdGFuZ2xlKHJlY3RhbmdsZSkgewogICAgdGhpcy5yZWN0YW5nbGUgPSBsb29rdXBOb3JtYWxSZWN0KHJlY3RhbmdsZSwgWzAsIDAsIDAsIDBdKTsKICB9CiAgc2V0Q29sb3IoY29sb3IpIHsKICAgIHRoaXMuY29sb3IgPSBnZXRSZ2JDb2xvcihjb2xvcik7CiAgfQogIHNldExpbmVFbmRpbmdzKGxpbmVFbmRpbmdzKSB7CiAgICB0aGlzLmxpbmVFbmRpbmdzID0gWyJOb25lIiwgIk5vbmUiXTsKICAgIGlmIChBcnJheS5pc0FycmF5KGxpbmVFbmRpbmdzKSAmJiBsaW5lRW5kaW5ncy5sZW5ndGggPT09IDIpIHsKICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAyOyBpKyspIHsKICAgICAgICBjb25zdCBvYmogPSBsaW5lRW5kaW5nc1tpXTsKICAgICAgICBpZiAob2JqIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgc3dpdGNoIChvYmoubmFtZSkgewogICAgICAgICAgICBjYXNlICJOb25lIjoKICAgICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgICAgY2FzZSAiU3F1YXJlIjoKICAgICAgICAgICAgY2FzZSAiQ2lyY2xlIjoKICAgICAgICAgICAgY2FzZSAiRGlhbW9uZCI6CiAgICAgICAgICAgIGNhc2UgIk9wZW5BcnJvdyI6CiAgICAgICAgICAgIGNhc2UgIkNsb3NlZEFycm93IjoKICAgICAgICAgICAgY2FzZSAiQnV0dCI6CiAgICAgICAgICAgIGNhc2UgIlJPcGVuQXJyb3ciOgogICAgICAgICAgICBjYXNlICJSQ2xvc2VkQXJyb3ciOgogICAgICAgICAgICBjYXNlICJTbGFzaCI6CiAgICAgICAgICAgICAgdGhpcy5saW5lRW5kaW5nc1tpXSA9IG9iai5uYW1lOwogICAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICB3YXJuKGBJZ25vcmluZyBpbnZhbGlkIGxpbmVFbmRpbmc6ICR7b2JqfWApOwogICAgICB9CiAgICB9CiAgfQogIHNldFJvdGF0aW9uKG1rLCBkaWN0KSB7CiAgICB0aGlzLnJvdGF0aW9uID0gMDsKICAgIGxldCBhbmdsZSA9IG1rIGluc3RhbmNlb2YgRGljdCA/IG1rLmdldCgiUiIpIHx8IDAgOiBkaWN0LmdldCgiUm90YXRlIikgfHwgMDsKICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKGFuZ2xlKSAmJiBhbmdsZSAhPT0gMCkgewogICAgICBhbmdsZSAlPSAzNjA7CiAgICAgIGlmIChhbmdsZSA8IDApIHsKICAgICAgICBhbmdsZSArPSAzNjA7CiAgICAgIH0KICAgICAgaWYgKGFuZ2xlICUgOTAgPT09IDApIHsKICAgICAgICB0aGlzLnJvdGF0aW9uID0gYW5nbGU7CiAgICAgIH0KICAgIH0KICB9CiAgc2V0Qm9yZGVyQW5kQmFja2dyb3VuZENvbG9ycyhtaykgewogICAgaWYgKG1rIGluc3RhbmNlb2YgRGljdCkgewogICAgICB0aGlzLmJvcmRlckNvbG9yID0gZ2V0UmdiQ29sb3IobWsuZ2V0QXJyYXkoIkJDIiksIG51bGwpOwogICAgICB0aGlzLmJhY2tncm91bmRDb2xvciA9IGdldFJnYkNvbG9yKG1rLmdldEFycmF5KCJCRyIpLCBudWxsKTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuYm9yZGVyQ29sb3IgPSB0aGlzLmJhY2tncm91bmRDb2xvciA9IG51bGw7CiAgICB9CiAgfQogIHNldEJvcmRlclN0eWxlKGJvcmRlclN0eWxlKSB7CiAgICB0aGlzLmJvcmRlclN0eWxlID0gbmV3IEFubm90YXRpb25Cb3JkZXJTdHlsZSgpOwogICAgaWYgKCEoYm9yZGVyU3R5bGUgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoYm9yZGVyU3R5bGUuaGFzKCJCUyIpKSB7CiAgICAgIGNvbnN0IGRpY3QgPSBib3JkZXJTdHlsZS5nZXQoIkJTIik7CiAgICAgIGlmIChkaWN0IGluc3RhbmNlb2YgRGljdCkgewogICAgICAgIGNvbnN0IGRpY3RUeXBlID0gZGljdC5nZXQoIlR5cGUiKTsKICAgICAgICBpZiAoIWRpY3RUeXBlIHx8IGlzTmFtZShkaWN0VHlwZSwgIkJvcmRlciIpKSB7CiAgICAgICAgICB0aGlzLmJvcmRlclN0eWxlLnNldFdpZHRoKGRpY3QuZ2V0KCJXIiksIHRoaXMucmVjdGFuZ2xlKTsKICAgICAgICAgIHRoaXMuYm9yZGVyU3R5bGUuc2V0U3R5bGUoZGljdC5nZXQoIlMiKSk7CiAgICAgICAgICB0aGlzLmJvcmRlclN0eWxlLnNldERhc2hBcnJheShkaWN0LmdldEFycmF5KCJEIikpOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIGlmIChib3JkZXJTdHlsZS5oYXMoIkJvcmRlciIpKSB7CiAgICAgIGNvbnN0IGFycmF5ID0gYm9yZGVyU3R5bGUuZ2V0QXJyYXkoIkJvcmRlciIpOwogICAgICBpZiAoQXJyYXkuaXNBcnJheShhcnJheSkgJiYgYXJyYXkubGVuZ3RoID49IDMpIHsKICAgICAgICB0aGlzLmJvcmRlclN0eWxlLnNldEhvcml6b250YWxDb3JuZXJSYWRpdXMoYXJyYXlbMF0pOwogICAgICAgIHRoaXMuYm9yZGVyU3R5bGUuc2V0VmVydGljYWxDb3JuZXJSYWRpdXMoYXJyYXlbMV0pOwogICAgICAgIHRoaXMuYm9yZGVyU3R5bGUuc2V0V2lkdGgoYXJyYXlbMl0sIHRoaXMucmVjdGFuZ2xlKTsKICAgICAgICBpZiAoYXJyYXkubGVuZ3RoID09PSA0KSB7CiAgICAgICAgICB0aGlzLmJvcmRlclN0eWxlLnNldERhc2hBcnJheShhcnJheVszXSwgdHJ1ZSk7CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzLmJvcmRlclN0eWxlLnNldFdpZHRoKDApOwogICAgfQogIH0KICBzZXRBcHBlYXJhbmNlKGRpY3QpIHsKICAgIHRoaXMuYXBwZWFyYW5jZSA9IG51bGw7CiAgICBjb25zdCBhcHBlYXJhbmNlU3RhdGVzID0gZGljdC5nZXQoIkFQIik7CiAgICBpZiAoIShhcHBlYXJhbmNlU3RhdGVzIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3Qgbm9ybWFsQXBwZWFyYW5jZVN0YXRlID0gYXBwZWFyYW5jZVN0YXRlcy5nZXQoIk4iKTsKICAgIGlmIChub3JtYWxBcHBlYXJhbmNlU3RhdGUgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICAgIHRoaXMuYXBwZWFyYW5jZSA9IG5vcm1hbEFwcGVhcmFuY2VTdGF0ZTsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKCEobm9ybWFsQXBwZWFyYW5jZVN0YXRlIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgYXMgPSBkaWN0LmdldCgiQVMiKTsKICAgIGlmICghKGFzIGluc3RhbmNlb2YgTmFtZSkgfHwgIW5vcm1hbEFwcGVhcmFuY2VTdGF0ZS5oYXMoYXMubmFtZSkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgYXBwZWFyYW5jZSA9IG5vcm1hbEFwcGVhcmFuY2VTdGF0ZS5nZXQoYXMubmFtZSk7CiAgICBpZiAoYXBwZWFyYW5jZSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHsKICAgICAgdGhpcy5hcHBlYXJhbmNlID0gYXBwZWFyYW5jZTsKICAgIH0KICB9CiAgc2V0T3B0aW9uYWxDb250ZW50KGRpY3QpIHsKICAgIHRoaXMub2MgPSBudWxsOwogICAgY29uc3Qgb2MgPSBkaWN0LmdldCgiT0MiKTsKICAgIGlmIChvYyBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgd2Fybigic2V0T3B0aW9uYWxDb250ZW50OiBTdXBwb3J0IGZvciAvTmFtZS1lbnRyeSBpcyBub3QgaW1wbGVtZW50ZWQuIik7CiAgICB9IGVsc2UgaWYgKG9jIGluc3RhbmNlb2YgRGljdCkgewogICAgICB0aGlzLm9jID0gb2M7CiAgICB9CiAgfQogIGFzeW5jIGxvYWRSZXNvdXJjZXMoa2V5cywgYXBwZWFyYW5jZSkgewogICAgY29uc3QgcmVzb3VyY2VzID0gYXdhaXQgYXBwZWFyYW5jZS5kaWN0LmdldEFzeW5jKCJSZXNvdXJjZXMiKTsKICAgIGlmIChyZXNvdXJjZXMpIHsKICAgICAgYXdhaXQgT2JqZWN0TG9hZGVyLmxvYWQocmVzb3VyY2VzLCBrZXlzLCByZXNvdXJjZXMueHJlZik7CiAgICB9CiAgICByZXR1cm4gcmVzb3VyY2VzOwogIH0KICBhc3luYyBnZXRPcGVyYXRvckxpc3QoZXZhbHVhdG9yLCB0YXNrLCBpbnRlbnQsIGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBjb25zdCB7CiAgICAgIGhhc093bkNhbnZhcywKICAgICAgaWQsCiAgICAgIHJlY3QKICAgIH0gPSB0aGlzLmRhdGE7CiAgICBsZXQgYXBwZWFyYW5jZSA9IHRoaXMuYXBwZWFyYW5jZTsKICAgIGNvbnN0IGlzVXNpbmdPd25DYW52YXMgPSAhIShoYXNPd25DYW52YXMgJiYgaW50ZW50ICYgUmVuZGVyaW5nSW50ZW50RmxhZy5ESVNQTEFZKTsKICAgIGlmIChpc1VzaW5nT3duQ2FudmFzICYmICh0aGlzLndpZHRoID09PSAwIHx8IHRoaXMuaGVpZ2h0ID09PSAwKSkgewogICAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gZmFsc2U7CiAgICAgIHJldHVybiB7CiAgICAgICAgb3BMaXN0OiBuZXcgT3BlcmF0b3JMaXN0KCksCiAgICAgICAgc2VwYXJhdGVGb3JtOiBmYWxzZSwKICAgICAgICBzZXBhcmF0ZUNhbnZhczogZmFsc2UKICAgICAgfTsKICAgIH0KICAgIGlmICghYXBwZWFyYW5jZSkgewogICAgICBpZiAoIWlzVXNpbmdPd25DYW52YXMpIHsKICAgICAgICByZXR1cm4gewogICAgICAgICAgb3BMaXN0OiBuZXcgT3BlcmF0b3JMaXN0KCksCiAgICAgICAgICBzZXBhcmF0ZUZvcm06IGZhbHNlLAogICAgICAgICAgc2VwYXJhdGVDYW52YXM6IGZhbHNlCiAgICAgICAgfTsKICAgICAgfQogICAgICBhcHBlYXJhbmNlID0gbmV3IFN0cmluZ1N0cmVhbSgiIik7CiAgICAgIGFwcGVhcmFuY2UuZGljdCA9IG5ldyBEaWN0KCk7CiAgICB9CiAgICBjb25zdCBhcHBlYXJhbmNlRGljdCA9IGFwcGVhcmFuY2UuZGljdDsKICAgIGNvbnN0IHJlc291cmNlcyA9IGF3YWl0IHRoaXMubG9hZFJlc291cmNlcyhSRVNPVVJDRVNfS0VZU19PUEVSQVRPUl9MSVNULCBhcHBlYXJhbmNlKTsKICAgIGNvbnN0IGJib3ggPSBsb29rdXBSZWN0KGFwcGVhcmFuY2VEaWN0LmdldEFycmF5KCJCQm94IiksIFswLCAwLCAxLCAxXSk7CiAgICBjb25zdCBtYXRyaXggPSBsb29rdXBNYXRyaXgoYXBwZWFyYW5jZURpY3QuZ2V0QXJyYXkoIk1hdHJpeCIpLCBJREVOVElUWV9NQVRSSVgpOwogICAgY29uc3QgdHJhbnNmb3JtID0gZ2V0VHJhbnNmb3JtTWF0cml4KHJlY3QsIGJib3gsIG1hdHJpeCk7CiAgICBjb25zdCBvcExpc3QgPSBuZXcgT3BlcmF0b3JMaXN0KCk7CiAgICBsZXQgb3B0aW9uYWxDb250ZW50OwogICAgaWYgKHRoaXMub2MpIHsKICAgICAgb3B0aW9uYWxDb250ZW50ID0gYXdhaXQgZXZhbHVhdG9yLnBhcnNlTWFya2VkQ29udGVudFByb3BzKHRoaXMub2MsIG51bGwpOwogICAgfQogICAgaWYgKG9wdGlvbmFsQ29udGVudCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIG9wTGlzdC5hZGRPcChPUFMuYmVnaW5NYXJrZWRDb250ZW50UHJvcHMsIFsiT0MiLCBvcHRpb25hbENvbnRlbnRdKTsKICAgIH0KICAgIG9wTGlzdC5hZGRPcChPUFMuYmVnaW5Bbm5vdGF0aW9uLCBbaWQsIHJlY3QsIHRyYW5zZm9ybSwgbWF0cml4LCBpc1VzaW5nT3duQ2FudmFzXSk7CiAgICBhd2FpdCBldmFsdWF0b3IuZ2V0T3BlcmF0b3JMaXN0KHsKICAgICAgc3RyZWFtOiBhcHBlYXJhbmNlLAogICAgICB0YXNrLAogICAgICByZXNvdXJjZXMsCiAgICAgIG9wZXJhdG9yTGlzdDogb3BMaXN0LAogICAgICBmYWxsYmFja0ZvbnREaWN0OiB0aGlzLl9mYWxsYmFja0ZvbnREaWN0CiAgICB9KTsKICAgIG9wTGlzdC5hZGRPcChPUFMuZW5kQW5ub3RhdGlvbiwgW10pOwogICAgaWYgKG9wdGlvbmFsQ29udGVudCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIG9wTGlzdC5hZGRPcChPUFMuZW5kTWFya2VkQ29udGVudCwgW10pOwogICAgfQogICAgdGhpcy5yZXNldCgpOwogICAgcmV0dXJuIHsKICAgICAgb3BMaXN0LAogICAgICBzZXBhcmF0ZUZvcm06IGZhbHNlLAogICAgICBzZXBhcmF0ZUNhbnZhczogaXNVc2luZ093bkNhbnZhcwogICAgfTsKICB9CiAgYXN5bmMgc2F2ZShldmFsdWF0b3IsIHRhc2ssIGFubm90YXRpb25TdG9yYWdlLCBjaGFuZ2VzKSB7CiAgICByZXR1cm4gbnVsbDsKICB9CiAgZ2V0IG92ZXJsYXlzVGV4dENvbnRlbnQoKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGdldCBoYXNUZXh0Q29udGVudCgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgYXN5bmMgZXh0cmFjdFRleHRDb250ZW50KGV2YWx1YXRvciwgdGFzaywgdmlld0JveCkgewogICAgaWYgKCF0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgcmVzb3VyY2VzID0gYXdhaXQgdGhpcy5sb2FkUmVzb3VyY2VzKFJFU09VUkNFU19LRVlTX1RFWFRfQ09OVEVOVCwgdGhpcy5hcHBlYXJhbmNlKTsKICAgIGNvbnN0IHRleHQgPSBbXTsKICAgIGNvbnN0IGJ1ZmZlciA9IFtdOwogICAgbGV0IGZpcnN0UG9zaXRpb24gPSBudWxsOwogICAgY29uc3Qgc2luayA9IHsKICAgICAgZGVzaXJlZFNpemU6IE1hdGguSW5maW5pdHksCiAgICAgIHJlYWR5OiB0cnVlLAogICAgICBlbnF1ZXVlKGNodW5rLCBzaXplKSB7CiAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIGNodW5rLml0ZW1zKSB7CiAgICAgICAgICBpZiAoaXRlbS5zdHIgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGZpcnN0UG9zaXRpb24gfHw9IGl0ZW0udHJhbnNmb3JtLnNsaWNlKC0yKTsKICAgICAgICAgIGJ1ZmZlci5wdXNoKGl0ZW0uc3RyKTsKICAgICAgICAgIGlmIChpdGVtLmhhc0VPTCkgewogICAgICAgICAgICB0ZXh0LnB1c2goYnVmZmVyLmpvaW4oIiIpLnRyaW1FbmQoKSk7CiAgICAgICAgICAgIGJ1ZmZlci5sZW5ndGggPSAwOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfTsKICAgIGF3YWl0IGV2YWx1YXRvci5nZXRUZXh0Q29udGVudCh7CiAgICAgIHN0cmVhbTogdGhpcy5hcHBlYXJhbmNlLAogICAgICB0YXNrLAogICAgICByZXNvdXJjZXMsCiAgICAgIGluY2x1ZGVNYXJrZWRDb250ZW50OiB0cnVlLAogICAgICBrZWVwV2hpdGVTcGFjZTogdHJ1ZSwKICAgICAgc2luaywKICAgICAgdmlld0JveAogICAgfSk7CiAgICB0aGlzLnJlc2V0KCk7CiAgICBpZiAoYnVmZmVyLmxlbmd0aCkgewogICAgICB0ZXh0LnB1c2goYnVmZmVyLmpvaW4oIiIpLnRyaW1FbmQoKSk7CiAgICB9CiAgICBpZiAodGV4dC5sZW5ndGggPiAxIHx8IHRleHRbMF0pIHsKICAgICAgY29uc3QgYXBwZWFyYW5jZURpY3QgPSB0aGlzLmFwcGVhcmFuY2UuZGljdDsKICAgICAgY29uc3QgYmJveCA9IGxvb2t1cFJlY3QoYXBwZWFyYW5jZURpY3QuZ2V0QXJyYXkoIkJCb3giKSwgbnVsbCk7CiAgICAgIGNvbnN0IG1hdHJpeCA9IGxvb2t1cE1hdHJpeChhcHBlYXJhbmNlRGljdC5nZXRBcnJheSgiTWF0cml4IiksIG51bGwpOwogICAgICB0aGlzLmRhdGEudGV4dFBvc2l0aW9uID0gdGhpcy5fdHJhbnNmb3JtUG9pbnQoZmlyc3RQb3NpdGlvbiwgYmJveCwgbWF0cml4KTsKICAgICAgdGhpcy5kYXRhLnRleHRDb250ZW50ID0gdGV4dDsKICAgIH0KICB9CiAgX3RyYW5zZm9ybVBvaW50KGNvb3JkcywgYmJveCwgbWF0cml4KSB7CiAgICBjb25zdCB7CiAgICAgIHJlY3QKICAgIH0gPSB0aGlzLmRhdGE7CiAgICBiYm94IHx8PSBbMCwgMCwgMSwgMV07CiAgICBtYXRyaXggfHw9IFsxLCAwLCAwLCAxLCAwLCAwXTsKICAgIGNvbnN0IHRyYW5zZm9ybSA9IGdldFRyYW5zZm9ybU1hdHJpeChyZWN0LCBiYm94LCBtYXRyaXgpOwogICAgdHJhbnNmb3JtWzRdIC09IHJlY3RbMF07CiAgICB0cmFuc2Zvcm1bNV0gLT0gcmVjdFsxXTsKICAgIGNvbnN0IHAgPSBjb29yZHMuc2xpY2UoKTsKICAgIFV0aWwuYXBwbHlUcmFuc2Zvcm0ocCwgdHJhbnNmb3JtKTsKICAgIFV0aWwuYXBwbHlUcmFuc2Zvcm0ocCwgbWF0cml4KTsKICAgIHJldHVybiBwOwogIH0KICBnZXRGaWVsZE9iamVjdCgpIHsKICAgIGlmICh0aGlzLmRhdGEua2lkSWRzKSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgaWQ6IHRoaXMuZGF0YS5pZCwKICAgICAgICBhY3Rpb25zOiB0aGlzLmRhdGEuYWN0aW9ucywKICAgICAgICBuYW1lOiB0aGlzLmRhdGEuZmllbGROYW1lLAogICAgICAgIHN0cm9rZUNvbG9yOiB0aGlzLmRhdGEuYm9yZGVyQ29sb3IsCiAgICAgICAgZmlsbENvbG9yOiB0aGlzLmRhdGEuYmFja2dyb3VuZENvbG9yLAogICAgICAgIHR5cGU6ICIiLAogICAgICAgIGtpZElkczogdGhpcy5kYXRhLmtpZElkcywKICAgICAgICBwYWdlOiB0aGlzLmRhdGEucGFnZUluZGV4LAogICAgICAgIHJvdGF0aW9uOiB0aGlzLnJvdGF0aW9uCiAgICAgIH07CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgcmVzZXQoKSB7CiAgICBmb3IgKGNvbnN0IHN0cmVhbSBvZiB0aGlzLl9zdHJlYW1zKSB7CiAgICAgIHN0cmVhbS5yZXNldCgpOwogICAgfQogIH0KICBfY29uc3RydWN0RmllbGROYW1lKGRpY3QpIHsKICAgIGlmICghZGljdC5oYXMoIlQiKSAmJiAhZGljdC5oYXMoIlBhcmVudCIpKSB7CiAgICAgIHdhcm4oIlVua25vd24gZmllbGQgbmFtZSwgZmFsbGluZyBiYWNrIHRvIGVtcHR5IGZpZWxkIG5hbWUuIik7CiAgICAgIHJldHVybiAiIjsKICAgIH0KICAgIGlmICghZGljdC5oYXMoIlBhcmVudCIpKSB7CiAgICAgIHJldHVybiBzdHJpbmdUb1BERlN0cmluZyhkaWN0LmdldCgiVCIpKTsKICAgIH0KICAgIGNvbnN0IGZpZWxkTmFtZSA9IFtdOwogICAgaWYgKGRpY3QuaGFzKCJUIikpIHsKICAgICAgZmllbGROYW1lLnVuc2hpZnQoc3RyaW5nVG9QREZTdHJpbmcoZGljdC5nZXQoIlQiKSkpOwogICAgfQogICAgbGV0IGxvb3BEaWN0ID0gZGljdDsKICAgIGNvbnN0IHZpc2l0ZWQgPSBuZXcgUmVmU2V0KCk7CiAgICBpZiAoZGljdC5vYmpJZCkgewogICAgICB2aXNpdGVkLnB1dChkaWN0Lm9iaklkKTsKICAgIH0KICAgIHdoaWxlIChsb29wRGljdC5oYXMoIlBhcmVudCIpKSB7CiAgICAgIGxvb3BEaWN0ID0gbG9vcERpY3QuZ2V0KCJQYXJlbnQiKTsKICAgICAgaWYgKCEobG9vcERpY3QgaW5zdGFuY2VvZiBEaWN0KSB8fCBsb29wRGljdC5vYmpJZCAmJiB2aXNpdGVkLmhhcyhsb29wRGljdC5vYmpJZCkpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpZiAobG9vcERpY3Qub2JqSWQpIHsKICAgICAgICB2aXNpdGVkLnB1dChsb29wRGljdC5vYmpJZCk7CiAgICAgIH0KICAgICAgaWYgKGxvb3BEaWN0LmhhcygiVCIpKSB7CiAgICAgICAgZmllbGROYW1lLnVuc2hpZnQoc3RyaW5nVG9QREZTdHJpbmcobG9vcERpY3QuZ2V0KCJUIikpKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGZpZWxkTmFtZS5qb2luKCIuIik7CiAgfQogIGdldCB3aWR0aCgpIHsKICAgIHJldHVybiB0aGlzLmRhdGEucmVjdFsyXSAtIHRoaXMuZGF0YS5yZWN0WzBdOwogIH0KICBnZXQgaGVpZ2h0KCkgewogICAgcmV0dXJuIHRoaXMuZGF0YS5yZWN0WzNdIC0gdGhpcy5kYXRhLnJlY3RbMV07CiAgfQp9CmNsYXNzIEFubm90YXRpb25Cb3JkZXJTdHlsZSB7CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLndpZHRoID0gMTsKICAgIHRoaXMucmF3V2lkdGggPSAxOwogICAgdGhpcy5zdHlsZSA9IEFubm90YXRpb25Cb3JkZXJTdHlsZVR5cGUuU09MSUQ7CiAgICB0aGlzLmRhc2hBcnJheSA9IFszXTsKICAgIHRoaXMuaG9yaXpvbnRhbENvcm5lclJhZGl1cyA9IDA7CiAgICB0aGlzLnZlcnRpY2FsQ29ybmVyUmFkaXVzID0gMDsKICB9CiAgc2V0V2lkdGgod2lkdGgsIHJlY3QgPSBbMCwgMCwgMCwgMF0pIHsKICAgIGlmICh3aWR0aCBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgdGhpcy53aWR0aCA9IDA7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmICh0eXBlb2Ygd2lkdGggPT09ICJudW1iZXIiKSB7CiAgICAgIGlmICh3aWR0aCA+IDApIHsKICAgICAgICB0aGlzLnJhd1dpZHRoID0gd2lkdGg7CiAgICAgICAgY29uc3QgbWF4V2lkdGggPSAocmVjdFsyXSAtIHJlY3RbMF0pIC8gMjsKICAgICAgICBjb25zdCBtYXhIZWlnaHQgPSAocmVjdFszXSAtIHJlY3RbMV0pIC8gMjsKICAgICAgICBpZiAobWF4V2lkdGggPiAwICYmIG1heEhlaWdodCA+IDAgJiYgKHdpZHRoID4gbWF4V2lkdGggfHwgd2lkdGggPiBtYXhIZWlnaHQpKSB7CiAgICAgICAgICB3YXJuKGBBbm5vdGF0aW9uQm9yZGVyU3R5bGUuc2V0V2lkdGggLSBpZ25vcmluZyB3aWR0aDogJHt3aWR0aH1gKTsKICAgICAgICAgIHdpZHRoID0gMTsKICAgICAgICB9CiAgICAgIH0KICAgICAgdGhpcy53aWR0aCA9IHdpZHRoOwogICAgfQogIH0KICBzZXRTdHlsZShzdHlsZSkgewogICAgaWYgKCEoc3R5bGUgaW5zdGFuY2VvZiBOYW1lKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBzd2l0Y2ggKHN0eWxlLm5hbWUpIHsKICAgICAgY2FzZSAiUyI6CiAgICAgICAgdGhpcy5zdHlsZSA9IEFubm90YXRpb25Cb3JkZXJTdHlsZVR5cGUuU09MSUQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIkQiOgogICAgICAgIHRoaXMuc3R5bGUgPSBBbm5vdGF0aW9uQm9yZGVyU3R5bGVUeXBlLkRBU0hFRDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiQiI6CiAgICAgICAgdGhpcy5zdHlsZSA9IEFubm90YXRpb25Cb3JkZXJTdHlsZVR5cGUuQkVWRUxFRDsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAiSSI6CiAgICAgICAgdGhpcy5zdHlsZSA9IEFubm90YXRpb25Cb3JkZXJTdHlsZVR5cGUuSU5TRVQ7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgIlUiOgogICAgICAgIHRoaXMuc3R5bGUgPSBBbm5vdGF0aW9uQm9yZGVyU3R5bGVUeXBlLlVOREVSTElORTsKICAgICAgICBicmVhazsKICAgICAgZGVmYXVsdDoKICAgICAgICBicmVhazsKICAgIH0KICB9CiAgc2V0RGFzaEFycmF5KGRhc2hBcnJheSwgZm9yY2VTdHlsZSA9IGZhbHNlKSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheShkYXNoQXJyYXkpKSB7CiAgICAgIGxldCBpc1ZhbGlkID0gdHJ1ZTsKICAgICAgbGV0IGFsbFplcm9zID0gdHJ1ZTsKICAgICAgZm9yIChjb25zdCBlbGVtZW50IG9mIGRhc2hBcnJheSkgewogICAgICAgIGNvbnN0IHZhbGlkTnVtYmVyID0gK2VsZW1lbnQgPj0gMDsKICAgICAgICBpZiAoIXZhbGlkTnVtYmVyKSB7CiAgICAgICAgICBpc1ZhbGlkID0gZmFsc2U7CiAgICAgICAgICBicmVhazsKICAgICAgICB9IGVsc2UgaWYgKGVsZW1lbnQgPiAwKSB7CiAgICAgICAgICBhbGxaZXJvcyA9IGZhbHNlOwogICAgICAgIH0KICAgICAgfQogICAgICBpZiAoZGFzaEFycmF5Lmxlbmd0aCA9PT0gMCB8fCBpc1ZhbGlkICYmICFhbGxaZXJvcykgewogICAgICAgIHRoaXMuZGFzaEFycmF5ID0gZGFzaEFycmF5OwogICAgICAgIGlmIChmb3JjZVN0eWxlKSB7CiAgICAgICAgICB0aGlzLnNldFN0eWxlKE5hbWUuZ2V0KCJEIikpOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLndpZHRoID0gMDsKICAgICAgfQogICAgfSBlbHNlIGlmIChkYXNoQXJyYXkpIHsKICAgICAgdGhpcy53aWR0aCA9IDA7CiAgICB9CiAgfQogIHNldEhvcml6b250YWxDb3JuZXJSYWRpdXMocmFkaXVzKSB7CiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihyYWRpdXMpKSB7CiAgICAgIHRoaXMuaG9yaXpvbnRhbENvcm5lclJhZGl1cyA9IHJhZGl1czsKICAgIH0KICB9CiAgc2V0VmVydGljYWxDb3JuZXJSYWRpdXMocmFkaXVzKSB7CiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihyYWRpdXMpKSB7CiAgICAgIHRoaXMudmVydGljYWxDb3JuZXJSYWRpdXMgPSByYWRpdXM7CiAgICB9CiAgfQp9CmNsYXNzIE1hcmt1cEFubm90YXRpb24gZXh0ZW5kcyBBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICBjb25zdCB7CiAgICAgIGRpY3QKICAgIH0gPSBwYXJhbXM7CiAgICBpZiAoZGljdC5oYXMoIklSVCIpKSB7CiAgICAgIGNvbnN0IHJhd0lSVCA9IGRpY3QuZ2V0UmF3KCJJUlQiKTsKICAgICAgdGhpcy5kYXRhLmluUmVwbHlUbyA9IHJhd0lSVCBpbnN0YW5jZW9mIFJlZiA/IHJhd0lSVC50b1N0cmluZygpIDogbnVsbDsKICAgICAgY29uc3QgcnQgPSBkaWN0LmdldCgiUlQiKTsKICAgICAgdGhpcy5kYXRhLnJlcGx5VHlwZSA9IHJ0IGluc3RhbmNlb2YgTmFtZSA/IHJ0Lm5hbWUgOiBBbm5vdGF0aW9uUmVwbHlUeXBlLlJFUExZOwogICAgfQogICAgbGV0IHBvcHVwUmVmID0gbnVsbDsKICAgIGlmICh0aGlzLmRhdGEucmVwbHlUeXBlID09PSBBbm5vdGF0aW9uUmVwbHlUeXBlLkdST1VQKSB7CiAgICAgIGNvbnN0IHBhcmVudCA9IGRpY3QuZ2V0KCJJUlQiKTsKICAgICAgdGhpcy5zZXRUaXRsZShwYXJlbnQuZ2V0KCJUIikpOwogICAgICB0aGlzLmRhdGEudGl0bGVPYmogPSB0aGlzLl90aXRsZTsKICAgICAgdGhpcy5zZXRDb250ZW50cyhwYXJlbnQuZ2V0KCJDb250ZW50cyIpKTsKICAgICAgdGhpcy5kYXRhLmNvbnRlbnRzT2JqID0gdGhpcy5fY29udGVudHM7CiAgICAgIGlmICghcGFyZW50LmhhcygiQ3JlYXRpb25EYXRlIikpIHsKICAgICAgICB0aGlzLmRhdGEuY3JlYXRpb25EYXRlID0gbnVsbDsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aGlzLnNldENyZWF0aW9uRGF0ZShwYXJlbnQuZ2V0KCJDcmVhdGlvbkRhdGUiKSk7CiAgICAgICAgdGhpcy5kYXRhLmNyZWF0aW9uRGF0ZSA9IHRoaXMuY3JlYXRpb25EYXRlOwogICAgICB9CiAgICAgIGlmICghcGFyZW50LmhhcygiTSIpKSB7CiAgICAgICAgdGhpcy5kYXRhLm1vZGlmaWNhdGlvbkRhdGUgPSBudWxsOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuc2V0TW9kaWZpY2F0aW9uRGF0ZShwYXJlbnQuZ2V0KCJNIikpOwogICAgICAgIHRoaXMuZGF0YS5tb2RpZmljYXRpb25EYXRlID0gdGhpcy5tb2RpZmljYXRpb25EYXRlOwogICAgICB9CiAgICAgIHBvcHVwUmVmID0gcGFyZW50LmdldFJhdygiUG9wdXAiKTsKICAgICAgaWYgKCFwYXJlbnQuaGFzKCJDIikpIHsKICAgICAgICB0aGlzLmRhdGEuY29sb3IgPSBudWxsOwogICAgICB9IGVsc2UgewogICAgICAgIHRoaXMuc2V0Q29sb3IocGFyZW50LmdldEFycmF5KCJDIikpOwogICAgICAgIHRoaXMuZGF0YS5jb2xvciA9IHRoaXMuY29sb3I7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuZGF0YS50aXRsZU9iaiA9IHRoaXMuX3RpdGxlOwogICAgICB0aGlzLnNldENyZWF0aW9uRGF0ZShkaWN0LmdldCgiQ3JlYXRpb25EYXRlIikpOwogICAgICB0aGlzLmRhdGEuY3JlYXRpb25EYXRlID0gdGhpcy5jcmVhdGlvbkRhdGU7CiAgICAgIHBvcHVwUmVmID0gZGljdC5nZXRSYXcoIlBvcHVwIik7CiAgICAgIGlmICghZGljdC5oYXMoIkMiKSkgewogICAgICAgIHRoaXMuZGF0YS5jb2xvciA9IG51bGw7CiAgICAgIH0KICAgIH0KICAgIHRoaXMuZGF0YS5wb3B1cFJlZiA9IHBvcHVwUmVmIGluc3RhbmNlb2YgUmVmID8gcG9wdXBSZWYudG9TdHJpbmcoKSA6IG51bGw7CiAgICBpZiAoZGljdC5oYXMoIlJDIikpIHsKICAgICAgdGhpcy5kYXRhLnJpY2hUZXh0ID0gWEZBRmFjdG9yeS5nZXRSaWNoVGV4dEFzSHRtbChkaWN0LmdldCgiUkMiKSk7CiAgICB9CiAgfQogIHNldENyZWF0aW9uRGF0ZShjcmVhdGlvbkRhdGUpIHsKICAgIHRoaXMuY3JlYXRpb25EYXRlID0gdHlwZW9mIGNyZWF0aW9uRGF0ZSA9PT0gInN0cmluZyIgPyBjcmVhdGlvbkRhdGUgOiBudWxsOwogIH0KICBfc2V0RGVmYXVsdEFwcGVhcmFuY2UoewogICAgeHJlZiwKICAgIGV4dHJhLAogICAgc3Ryb2tlQ29sb3IsCiAgICBmaWxsQ29sb3IsCiAgICBibGVuZE1vZGUsCiAgICBzdHJva2VBbHBoYSwKICAgIGZpbGxBbHBoYSwKICAgIHBvaW50c0NhbGxiYWNrCiAgfSkgewogICAgY29uc3QgYmJveCA9IHRoaXMuZGF0YS5yZWN0ID0gW0luZmluaXR5LCBJbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldOwogICAgY29uc3QgYnVmZmVyID0gWyJxIl07CiAgICBpZiAoZXh0cmEpIHsKICAgICAgYnVmZmVyLnB1c2goZXh0cmEpOwogICAgfQogICAgaWYgKHN0cm9rZUNvbG9yKSB7CiAgICAgIGJ1ZmZlci5wdXNoKGAke3N0cm9rZUNvbG9yWzBdfSAke3N0cm9rZUNvbG9yWzFdfSAke3N0cm9rZUNvbG9yWzJdfSBSR2ApOwogICAgfQogICAgaWYgKGZpbGxDb2xvcikgewogICAgICBidWZmZXIucHVzaChgJHtmaWxsQ29sb3JbMF19ICR7ZmlsbENvbG9yWzFdfSAke2ZpbGxDb2xvclsyXX0gcmdgKTsKICAgIH0KICAgIGNvbnN0IHBvaW50c0FycmF5ID0gdGhpcy5kYXRhLnF1YWRQb2ludHMgfHwgRmxvYXQzMkFycmF5LmZyb20oW3RoaXMucmVjdGFuZ2xlWzBdLCB0aGlzLnJlY3RhbmdsZVszXSwgdGhpcy5yZWN0YW5nbGVbMl0sIHRoaXMucmVjdGFuZ2xlWzNdLCB0aGlzLnJlY3RhbmdsZVswXSwgdGhpcy5yZWN0YW5nbGVbMV0sIHRoaXMucmVjdGFuZ2xlWzJdLCB0aGlzLnJlY3RhbmdsZVsxXV0pOwogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gcG9pbnRzQXJyYXkubGVuZ3RoOyBpIDwgaWk7IGkgKz0gOCkgewogICAgICBjb25zdCBwb2ludHMgPSBwb2ludHNDYWxsYmFjayhidWZmZXIsIHBvaW50c0FycmF5LnN1YmFycmF5KGksIGkgKyA4KSk7CiAgICAgIFV0aWwucmVjdEJvdW5kaW5nQm94KC4uLnBvaW50cywgYmJveCk7CiAgICB9CiAgICBidWZmZXIucHVzaCgiUSIpOwogICAgY29uc3QgZm9ybURpY3QgPSBuZXcgRGljdCh4cmVmKTsKICAgIGNvbnN0IGFwcGVhcmFuY2VTdHJlYW1EaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXRJZk5hbWUoIlN1YnR5cGUiLCAiRm9ybSIpOwogICAgY29uc3QgYXBwZWFyYW5jZVN0cmVhbSA9IG5ldyBTdHJpbmdTdHJlYW0oYnVmZmVyLmpvaW4oIiAiKSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtLmRpY3QgPSBhcHBlYXJhbmNlU3RyZWFtRGljdDsKICAgIGZvcm1EaWN0LnNldCgiRm0wIiwgYXBwZWFyYW5jZVN0cmVhbSk7CiAgICBjb25zdCBnc0RpY3QgPSBuZXcgRGljdCh4cmVmKTsKICAgIGlmIChibGVuZE1vZGUpIHsKICAgICAgZ3NEaWN0LnNldElmTmFtZSgiQk0iLCBibGVuZE1vZGUpOwogICAgfQogICAgZ3NEaWN0LnNldElmTnVtYmVyKCJDQSIsIHN0cm9rZUFscGhhKTsKICAgIGdzRGljdC5zZXRJZk51bWJlcigiY2EiLCBmaWxsQWxwaGEpOwogICAgY29uc3Qgc3RhdGVEaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICBzdGF0ZURpY3Quc2V0KCJHUzAiLCBnc0RpY3QpOwogICAgY29uc3QgcmVzb3VyY2VzID0gbmV3IERpY3QoeHJlZik7CiAgICByZXNvdXJjZXMuc2V0KCJFeHRHU3RhdGUiLCBzdGF0ZURpY3QpOwogICAgcmVzb3VyY2VzLnNldCgiWE9iamVjdCIsIGZvcm1EaWN0KTsKICAgIGNvbnN0IGFwcGVhcmFuY2VEaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICBhcHBlYXJhbmNlRGljdC5zZXQoIlJlc291cmNlcyIsIHJlc291cmNlcyk7CiAgICBhcHBlYXJhbmNlRGljdC5zZXQoIkJCb3giLCBiYm94KTsKICAgIHRoaXMuYXBwZWFyYW5jZSA9IG5ldyBTdHJpbmdTdHJlYW0oIi9HUzAgZ3MgL0ZtMCBEbyIpOwogICAgdGhpcy5hcHBlYXJhbmNlLmRpY3QgPSBhcHBlYXJhbmNlRGljdDsKICAgIHRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLmFwcGVhcmFuY2UsIGFwcGVhcmFuY2VTdHJlYW0pOwogIH0KICBzdGF0aWMgYXN5bmMgY3JlYXRlTmV3QW5ub3RhdGlvbih4cmVmLCBhbm5vdGF0aW9uLCBjaGFuZ2VzLCBwYXJhbXMpIHsKICAgIGNvbnN0IGFubm90YXRpb25SZWYgPSBhbm5vdGF0aW9uLnJlZiB8fD0geHJlZi5nZXROZXdUZW1wb3JhcnlSZWYoKTsKICAgIGNvbnN0IGFwID0gYXdhaXQgdGhpcy5jcmVhdGVOZXdBcHBlYXJhbmNlU3RyZWFtKGFubm90YXRpb24sIHhyZWYsIHBhcmFtcyk7CiAgICBsZXQgYW5ub3RhdGlvbkRpY3Q7CiAgICBpZiAoYXApIHsKICAgICAgY29uc3QgYXBSZWYgPSB4cmVmLmdldE5ld1RlbXBvcmFyeVJlZigpOwogICAgICBhbm5vdGF0aW9uRGljdCA9IHRoaXMuY3JlYXRlTmV3RGljdChhbm5vdGF0aW9uLCB4cmVmLCB7CiAgICAgICAgYXBSZWYKICAgICAgfSk7CiAgICAgIGNoYW5nZXMucHV0KGFwUmVmLCB7CiAgICAgICAgZGF0YTogYXAKICAgICAgfSk7CiAgICB9IGVsc2UgewogICAgICBhbm5vdGF0aW9uRGljdCA9IHRoaXMuY3JlYXRlTmV3RGljdChhbm5vdGF0aW9uLCB4cmVmLCB7fSk7CiAgICB9CiAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihhbm5vdGF0aW9uLnBhcmVudFRyZWVJZCkpIHsKICAgICAgYW5ub3RhdGlvbkRpY3Quc2V0KCJTdHJ1Y3RQYXJlbnQiLCBhbm5vdGF0aW9uLnBhcmVudFRyZWVJZCk7CiAgICB9CiAgICBjaGFuZ2VzLnB1dChhbm5vdGF0aW9uUmVmLCB7CiAgICAgIGRhdGE6IGFubm90YXRpb25EaWN0CiAgICB9KTsKICAgIGNvbnN0IHJldFJlZiA9IHsKICAgICAgcmVmOiBhbm5vdGF0aW9uUmVmCiAgICB9OwogICAgY29uc3QgewogICAgICBwb3B1cAogICAgfSA9IGFubm90YXRpb247CiAgICBpZiAocG9wdXApIHsKICAgICAgaWYgKHBvcHVwLmRlbGV0ZWQpIHsKICAgICAgICBhbm5vdGF0aW9uRGljdC5kZWxldGUoIlBvcHVwIik7CiAgICAgICAgYW5ub3RhdGlvbkRpY3QuZGVsZXRlKCJDb250ZW50cyIpOwogICAgICAgIGFubm90YXRpb25EaWN0LmRlbGV0ZSgiUkMiKTsKICAgICAgICByZXR1cm4gcmV0UmVmOwogICAgICB9CiAgICAgIGNvbnN0IHBvcHVwUmVmID0gcG9wdXAucmVmIHx8PSB4cmVmLmdldE5ld1RlbXBvcmFyeVJlZigpOwogICAgICBwb3B1cC5wYXJlbnQgPSBhbm5vdGF0aW9uUmVmOwogICAgICBjb25zdCBwb3B1cERpY3QgPSBQb3B1cEFubm90YXRpb24uY3JlYXRlTmV3RGljdChwb3B1cCwgeHJlZik7CiAgICAgIGNoYW5nZXMucHV0KHBvcHVwUmVmLCB7CiAgICAgICAgZGF0YTogcG9wdXBEaWN0CiAgICAgIH0pOwogICAgICBhbm5vdGF0aW9uRGljdC5zZXRJZkRlZmluZWQoIkNvbnRlbnRzIiwgc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRShwb3B1cC5jb250ZW50cykpOwogICAgICBhbm5vdGF0aW9uRGljdC5zZXQoIlBvcHVwIiwgcG9wdXBSZWYpOwogICAgICByZXR1cm4gW3JldFJlZiwgewogICAgICAgIHJlZjogcG9wdXBSZWYKICAgICAgfV07CiAgICB9CiAgICByZXR1cm4gcmV0UmVmOwogIH0KICBzdGF0aWMgYXN5bmMgY3JlYXRlTmV3UHJpbnRBbm5vdGF0aW9uKGFubm90YXRpb25HbG9iYWxzLCB4cmVmLCBhbm5vdGF0aW9uLCBwYXJhbXMpIHsKICAgIGNvbnN0IGFwID0gYXdhaXQgdGhpcy5jcmVhdGVOZXdBcHBlYXJhbmNlU3RyZWFtKGFubm90YXRpb24sIHhyZWYsIHBhcmFtcyk7CiAgICBjb25zdCBhbm5vdGF0aW9uRGljdCA9IHRoaXMuY3JlYXRlTmV3RGljdChhbm5vdGF0aW9uLCB4cmVmLCBhcCA/IHsKICAgICAgYXAKICAgIH0gOiB7fSk7CiAgICBjb25zdCBuZXdBbm5vdGF0aW9uID0gbmV3IHRoaXMucHJvdG90eXBlLmNvbnN0cnVjdG9yKHsKICAgICAgZGljdDogYW5ub3RhdGlvbkRpY3QsCiAgICAgIHhyZWYsCiAgICAgIGFubm90YXRpb25HbG9iYWxzLAogICAgICBldmFsdWF0b3JPcHRpb25zOiBwYXJhbXMuZXZhbHVhdG9yT3B0aW9ucwogICAgfSk7CiAgICBpZiAoYW5ub3RhdGlvbi5yZWYpIHsKICAgICAgbmV3QW5ub3RhdGlvbi5yZWYgPSBuZXdBbm5vdGF0aW9uLnJlZlRvUmVwbGFjZSA9IGFubm90YXRpb24ucmVmOwogICAgfQogICAgcmV0dXJuIG5ld0Fubm90YXRpb247CiAgfQp9CmNsYXNzIFdpZGdldEFubm90YXRpb24gZXh0ZW5kcyBBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICBjb25zdCB7CiAgICAgIGRpY3QsCiAgICAgIHhyZWYsCiAgICAgIGFubm90YXRpb25HbG9iYWxzCiAgICB9ID0gcGFyYW1zOwogICAgY29uc3QgZGF0YSA9IHRoaXMuZGF0YTsKICAgIHRoaXMuX25lZWRBcHBlYXJhbmNlcyA9IHBhcmFtcy5uZWVkQXBwZWFyYW5jZXM7CiAgICBkYXRhLmFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGUuV0lER0VUOwogICAgaWYgKGRhdGEuZmllbGROYW1lID09PSB1bmRlZmluZWQpIHsKICAgICAgZGF0YS5maWVsZE5hbWUgPSB0aGlzLl9jb25zdHJ1Y3RGaWVsZE5hbWUoZGljdCk7CiAgICB9CiAgICBpZiAoZGF0YS5hY3Rpb25zID09PSB1bmRlZmluZWQpIHsKICAgICAgZGF0YS5hY3Rpb25zID0gY29sbGVjdEFjdGlvbnMoeHJlZiwgZGljdCwgQW5ub3RhdGlvbkFjdGlvbkV2ZW50VHlwZSk7CiAgICB9CiAgICBsZXQgZmllbGRWYWx1ZSA9IGdldEluaGVyaXRhYmxlUHJvcGVydHkoewogICAgICBkaWN0LAogICAgICBrZXk6ICJWIiwKICAgICAgZ2V0QXJyYXk6IHRydWUKICAgIH0pOwogICAgZGF0YS5maWVsZFZhbHVlID0gdGhpcy5fZGVjb2RlRm9ybVZhbHVlKGZpZWxkVmFsdWUpOwogICAgY29uc3QgZGVmYXVsdEZpZWxkVmFsdWUgPSBnZXRJbmhlcml0YWJsZVByb3BlcnR5KHsKICAgICAgZGljdCwKICAgICAga2V5OiAiRFYiLAogICAgICBnZXRBcnJheTogdHJ1ZQogICAgfSk7CiAgICBkYXRhLmRlZmF1bHRGaWVsZFZhbHVlID0gdGhpcy5fZGVjb2RlRm9ybVZhbHVlKGRlZmF1bHRGaWVsZFZhbHVlKTsKICAgIGlmIChmaWVsZFZhbHVlID09PSB1bmRlZmluZWQgJiYgYW5ub3RhdGlvbkdsb2JhbHMueGZhRGF0YXNldHMpIHsKICAgICAgY29uc3QgcGF0aCA9IHRoaXMuX3RpdGxlLnN0cjsKICAgICAgaWYgKHBhdGgpIHsKICAgICAgICB0aGlzLl9oYXNWYWx1ZUZyb21YRkEgPSB0cnVlOwogICAgICAgIGRhdGEuZmllbGRWYWx1ZSA9IGZpZWxkVmFsdWUgPSBhbm5vdGF0aW9uR2xvYmFscy54ZmFEYXRhc2V0cy5nZXRWYWx1ZShwYXRoKTsKICAgICAgfQogICAgfQogICAgaWYgKGZpZWxkVmFsdWUgPT09IHVuZGVmaW5lZCAmJiBkYXRhLmRlZmF1bHRGaWVsZFZhbHVlICE9PSBudWxsKSB7CiAgICAgIGRhdGEuZmllbGRWYWx1ZSA9IGRhdGEuZGVmYXVsdEZpZWxkVmFsdWU7CiAgICB9CiAgICBkYXRhLmFsdGVybmF0aXZlVGV4dCA9IHN0cmluZ1RvUERGU3RyaW5nKGRpY3QuZ2V0KCJUVSIpIHx8ICIiKTsKICAgIHRoaXMuc2V0RGVmYXVsdEFwcGVhcmFuY2UocGFyYW1zKTsKICAgIGRhdGEuaGFzQXBwZWFyYW5jZSB8fD0gdGhpcy5fbmVlZEFwcGVhcmFuY2VzICYmIGRhdGEuZmllbGRWYWx1ZSAhPT0gdW5kZWZpbmVkICYmIGRhdGEuZmllbGRWYWx1ZSAhPT0gbnVsbDsKICAgIGNvbnN0IGZpZWxkVHlwZSA9IGdldEluaGVyaXRhYmxlUHJvcGVydHkoewogICAgICBkaWN0LAogICAgICBrZXk6ICJGVCIKICAgIH0pOwogICAgZGF0YS5maWVsZFR5cGUgPSBmaWVsZFR5cGUgaW5zdGFuY2VvZiBOYW1lID8gZmllbGRUeXBlLm5hbWUgOiBudWxsOwogICAgY29uc3QgbG9jYWxSZXNvdXJjZXMgPSBnZXRJbmhlcml0YWJsZVByb3BlcnR5KHsKICAgICAgZGljdCwKICAgICAga2V5OiAiRFIiCiAgICB9KTsKICAgIGNvbnN0IGFjcm9Gb3JtUmVzb3VyY2VzID0gYW5ub3RhdGlvbkdsb2JhbHMuYWNyb0Zvcm0uZ2V0KCJEUiIpOwogICAgY29uc3QgYXBwZWFyYW5jZVJlc291cmNlcyA9IHRoaXMuYXBwZWFyYW5jZT8uZGljdC5nZXQoIlJlc291cmNlcyIpOwogICAgdGhpcy5fZmllbGRSZXNvdXJjZXMgPSB7CiAgICAgIGxvY2FsUmVzb3VyY2VzLAogICAgICBhY3JvRm9ybVJlc291cmNlcywKICAgICAgYXBwZWFyYW5jZVJlc291cmNlcywKICAgICAgbWVyZ2VkUmVzb3VyY2VzOiBEaWN0Lm1lcmdlKHsKICAgICAgICB4cmVmLAogICAgICAgIGRpY3RBcnJheTogW2xvY2FsUmVzb3VyY2VzLCBhcHBlYXJhbmNlUmVzb3VyY2VzLCBhY3JvRm9ybVJlc291cmNlc10sCiAgICAgICAgbWVyZ2VTdWJEaWN0czogdHJ1ZQogICAgICB9KQogICAgfTsKICAgIGRhdGEuZmllbGRGbGFncyA9IGdldEluaGVyaXRhYmxlUHJvcGVydHkoewogICAgICBkaWN0LAogICAgICBrZXk6ICJGZiIKICAgIH0pOwogICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGRhdGEuZmllbGRGbGFncykgfHwgZGF0YS5maWVsZEZsYWdzIDwgMCkgewogICAgICBkYXRhLmZpZWxkRmxhZ3MgPSAwOwogICAgfQogICAgZGF0YS5wYXNzd29yZCA9IHRoaXMuaGFzRmllbGRGbGFnKEFubm90YXRpb25GaWVsZEZsYWcuUEFTU1dPUkQpOwogICAgZGF0YS5yZWFkT25seSA9IHRoaXMuaGFzRmllbGRGbGFnKEFubm90YXRpb25GaWVsZEZsYWcuUkVBRE9OTFkpOwogICAgZGF0YS5yZXF1aXJlZCA9IHRoaXMuaGFzRmllbGRGbGFnKEFubm90YXRpb25GaWVsZEZsYWcuUkVRVUlSRUQpOwogICAgZGF0YS5oaWRkZW4gPSB0aGlzLl9oYXNGbGFnKGRhdGEuYW5ub3RhdGlvbkZsYWdzLCBBbm5vdGF0aW9uRmxhZy5ISURERU4pIHx8IHRoaXMuX2hhc0ZsYWcoZGF0YS5hbm5vdGF0aW9uRmxhZ3MsIEFubm90YXRpb25GbGFnLk5PVklFVyk7CiAgfQogIF9kZWNvZGVGb3JtVmFsdWUoZm9ybVZhbHVlKSB7CiAgICBpZiAoQXJyYXkuaXNBcnJheShmb3JtVmFsdWUpKSB7CiAgICAgIHJldHVybiBmb3JtVmFsdWUuZmlsdGVyKGl0ZW0gPT4gdHlwZW9mIGl0ZW0gPT09ICJzdHJpbmciKS5tYXAoaXRlbSA9PiBzdHJpbmdUb1BERlN0cmluZyhpdGVtKSk7CiAgICB9IGVsc2UgaWYgKGZvcm1WYWx1ZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgcmV0dXJuIHN0cmluZ1RvUERGU3RyaW5nKGZvcm1WYWx1ZS5uYW1lKTsKICAgIH0gZWxzZSBpZiAodHlwZW9mIGZvcm1WYWx1ZSA9PT0gInN0cmluZyIpIHsKICAgICAgcmV0dXJuIHN0cmluZ1RvUERGU3RyaW5nKGZvcm1WYWx1ZSk7CiAgICB9CiAgICByZXR1cm4gbnVsbDsKICB9CiAgaGFzRmllbGRGbGFnKGZsYWcpIHsKICAgIHJldHVybiAhISh0aGlzLmRhdGEuZmllbGRGbGFncyAmIGZsYWcpOwogIH0KICBfaXNWaWV3YWJsZShmbGFncykgewogICAgcmV0dXJuIHRydWU7CiAgfQogIG11c3RCZVZpZXdlZChhbm5vdGF0aW9uU3RvcmFnZSwgcmVuZGVyRm9ybXMpIHsKICAgIGlmIChyZW5kZXJGb3JtcykgewogICAgICByZXR1cm4gdGhpcy52aWV3YWJsZTsKICAgIH0KICAgIHJldHVybiBzdXBlci5tdXN0QmVWaWV3ZWQoYW5ub3RhdGlvblN0b3JhZ2UsIHJlbmRlckZvcm1zKSAmJiAhdGhpcy5faGFzRmxhZyh0aGlzLmZsYWdzLCBBbm5vdGF0aW9uRmxhZy5OT1ZJRVcpOwogIH0KICBnZXRSb3RhdGlvbk1hdHJpeChhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgbGV0IHJvdGF0aW9uID0gYW5ub3RhdGlvblN0b3JhZ2U/LmdldCh0aGlzLmRhdGEuaWQpPy5yb3RhdGlvbjsKICAgIGlmIChyb3RhdGlvbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJvdGF0aW9uID0gdGhpcy5yb3RhdGlvbjsKICAgIH0KICAgIHJldHVybiByb3RhdGlvbiA9PT0gMCA/IElERU5USVRZX01BVFJJWCA6IGdldFJvdGF0aW9uTWF0cml4KHJvdGF0aW9uLCB0aGlzLndpZHRoLCB0aGlzLmhlaWdodCk7CiAgfQogIGdldEJvcmRlckFuZEJhY2tncm91bmRBcHBlYXJhbmNlcyhhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgbGV0IHJvdGF0aW9uID0gYW5ub3RhdGlvblN0b3JhZ2U/LmdldCh0aGlzLmRhdGEuaWQpPy5yb3RhdGlvbjsKICAgIGlmIChyb3RhdGlvbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJvdGF0aW9uID0gdGhpcy5yb3RhdGlvbjsKICAgIH0KICAgIGlmICghdGhpcy5iYWNrZ3JvdW5kQ29sb3IgJiYgIXRoaXMuYm9yZGVyQ29sb3IpIHsKICAgICAgcmV0dXJuICIiOwogICAgfQogICAgY29uc3QgcmVjdCA9IHJvdGF0aW9uID09PSAwIHx8IHJvdGF0aW9uID09PSAxODAgPyBgMCAwICR7dGhpcy53aWR0aH0gJHt0aGlzLmhlaWdodH0gcmVgIDogYDAgMCAke3RoaXMuaGVpZ2h0fSAke3RoaXMud2lkdGh9IHJlYDsKICAgIGxldCBzdHIgPSAiIjsKICAgIGlmICh0aGlzLmJhY2tncm91bmRDb2xvcikgewogICAgICBzdHIgPSBgJHtnZXRQZGZDb2xvcih0aGlzLmJhY2tncm91bmRDb2xvciwgdHJ1ZSl9ICR7cmVjdH0gZiBgOwogICAgfQogICAgaWYgKHRoaXMuYm9yZGVyQ29sb3IpIHsKICAgICAgY29uc3QgYm9yZGVyV2lkdGggPSB0aGlzLmJvcmRlclN0eWxlLndpZHRoIHx8IDE7CiAgICAgIHN0ciArPSBgJHtib3JkZXJXaWR0aH0gdyAke2dldFBkZkNvbG9yKHRoaXMuYm9yZGVyQ29sb3IsIGZhbHNlKX0gJHtyZWN0fSBTIGA7CiAgICB9CiAgICByZXR1cm4gc3RyOwogIH0KICBhc3luYyBnZXRPcGVyYXRvckxpc3QoZXZhbHVhdG9yLCB0YXNrLCBpbnRlbnQsIGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBpZiAoaW50ZW50ICYgUmVuZGVyaW5nSW50ZW50RmxhZy5BTk5PVEFUSU9OU19GT1JNUyAmJiAhKHRoaXMgaW5zdGFuY2VvZiBTaWduYXR1cmVXaWRnZXRBbm5vdGF0aW9uKSAmJiAhdGhpcy5kYXRhLm5vSFRNTCAmJiAhdGhpcy5kYXRhLmhhc093bkNhbnZhcykgewogICAgICByZXR1cm4gewogICAgICAgIG9wTGlzdDogbmV3IE9wZXJhdG9yTGlzdCgpLAogICAgICAgIHNlcGFyYXRlRm9ybTogdHJ1ZSwKICAgICAgICBzZXBhcmF0ZUNhbnZhczogZmFsc2UKICAgICAgfTsKICAgIH0KICAgIGlmICghdGhpcy5faGFzVGV4dCkgewogICAgICByZXR1cm4gc3VwZXIuZ2V0T3BlcmF0b3JMaXN0KGV2YWx1YXRvciwgdGFzaywgaW50ZW50LCBhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICB9CiAgICBjb25zdCBjb250ZW50ID0gYXdhaXQgdGhpcy5fZ2V0QXBwZWFyYW5jZShldmFsdWF0b3IsIHRhc2ssIGludGVudCwgYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgaWYgKHRoaXMuYXBwZWFyYW5jZSAmJiBjb250ZW50ID09PSBudWxsKSB7CiAgICAgIHJldHVybiBzdXBlci5nZXRPcGVyYXRvckxpc3QoZXZhbHVhdG9yLCB0YXNrLCBpbnRlbnQsIGFubm90YXRpb25TdG9yYWdlKTsKICAgIH0KICAgIGNvbnN0IG9wTGlzdCA9IG5ldyBPcGVyYXRvckxpc3QoKTsKICAgIGlmICghdGhpcy5fZGVmYXVsdEFwcGVhcmFuY2UgfHwgY29udGVudCA9PT0gbnVsbCkgewogICAgICByZXR1cm4gewogICAgICAgIG9wTGlzdCwKICAgICAgICBzZXBhcmF0ZUZvcm06IGZhbHNlLAogICAgICAgIHNlcGFyYXRlQ2FudmFzOiBmYWxzZQogICAgICB9OwogICAgfQogICAgY29uc3QgaXNVc2luZ093bkNhbnZhcyA9ICEhKHRoaXMuZGF0YS5oYXNPd25DYW52YXMgJiYgaW50ZW50ICYgUmVuZGVyaW5nSW50ZW50RmxhZy5ESVNQTEFZKTsKICAgIGNvbnN0IG1hdHJpeCA9IFsxLCAwLCAwLCAxLCAwLCAwXTsKICAgIGNvbnN0IGJib3ggPSBbMCwgMCwgdGhpcy53aWR0aCwgdGhpcy5oZWlnaHRdOwogICAgY29uc3QgdHJhbnNmb3JtID0gZ2V0VHJhbnNmb3JtTWF0cml4KHRoaXMuZGF0YS5yZWN0LCBiYm94LCBtYXRyaXgpOwogICAgbGV0IG9wdGlvbmFsQ29udGVudDsKICAgIGlmICh0aGlzLm9jKSB7CiAgICAgIG9wdGlvbmFsQ29udGVudCA9IGF3YWl0IGV2YWx1YXRvci5wYXJzZU1hcmtlZENvbnRlbnRQcm9wcyh0aGlzLm9jLCBudWxsKTsKICAgIH0KICAgIGlmIChvcHRpb25hbENvbnRlbnQgIT09IHVuZGVmaW5lZCkgewogICAgICBvcExpc3QuYWRkT3AoT1BTLmJlZ2luTWFya2VkQ29udGVudFByb3BzLCBbIk9DIiwgb3B0aW9uYWxDb250ZW50XSk7CiAgICB9CiAgICBvcExpc3QuYWRkT3AoT1BTLmJlZ2luQW5ub3RhdGlvbiwgW3RoaXMuZGF0YS5pZCwgdGhpcy5kYXRhLnJlY3QsIHRyYW5zZm9ybSwgdGhpcy5nZXRSb3RhdGlvbk1hdHJpeChhbm5vdGF0aW9uU3RvcmFnZSksIGlzVXNpbmdPd25DYW52YXNdKTsKICAgIGNvbnN0IHN0cmVhbSA9IG5ldyBTdHJpbmdTdHJlYW0oY29udGVudCk7CiAgICBhd2FpdCBldmFsdWF0b3IuZ2V0T3BlcmF0b3JMaXN0KHsKICAgICAgc3RyZWFtLAogICAgICB0YXNrLAogICAgICByZXNvdXJjZXM6IHRoaXMuX2ZpZWxkUmVzb3VyY2VzLm1lcmdlZFJlc291cmNlcywKICAgICAgb3BlcmF0b3JMaXN0OiBvcExpc3QKICAgIH0pOwogICAgb3BMaXN0LmFkZE9wKE9QUy5lbmRBbm5vdGF0aW9uLCBbXSk7CiAgICBpZiAob3B0aW9uYWxDb250ZW50ICE9PSB1bmRlZmluZWQpIHsKICAgICAgb3BMaXN0LmFkZE9wKE9QUy5lbmRNYXJrZWRDb250ZW50LCBbXSk7CiAgICB9CiAgICByZXR1cm4gewogICAgICBvcExpc3QsCiAgICAgIHNlcGFyYXRlRm9ybTogZmFsc2UsCiAgICAgIHNlcGFyYXRlQ2FudmFzOiBpc1VzaW5nT3duQ2FudmFzCiAgICB9OwogIH0KICBfZ2V0TUtEaWN0KHJvdGF0aW9uKSB7CiAgICBjb25zdCBtayA9IG5ldyBEaWN0KG51bGwpOwogICAgaWYgKHJvdGF0aW9uKSB7CiAgICAgIG1rLnNldCgiUiIsIHJvdGF0aW9uKTsKICAgIH0KICAgIG1rLnNldElmQXJyYXkoIkJDIiwgZ2V0UGRmQ29sb3JBcnJheSh0aGlzLmJvcmRlckNvbG9yKSk7CiAgICBtay5zZXRJZkFycmF5KCJCRyIsIGdldFBkZkNvbG9yQXJyYXkodGhpcy5iYWNrZ3JvdW5kQ29sb3IpKTsKICAgIHJldHVybiBtay5zaXplID4gMCA/IG1rIDogbnVsbDsKICB9CiAgYW1lbmRTYXZlZERpY3QoYW5ub3RhdGlvblN0b3JhZ2UsIGRpY3QpIHt9CiAgc2V0VmFsdWUoZGljdCwgdmFsdWUsIHhyZWYsIGNoYW5nZXMpIHsKICAgIGNvbnN0IHsKICAgICAgZGljdDogcGFyZW50RGljdCwKICAgICAgcmVmOiBwYXJlbnRSZWYKICAgIH0gPSBnZXRQYXJlbnRUb1VwZGF0ZShkaWN0LCB0aGlzLnJlZiwgeHJlZik7CiAgICBpZiAoIXBhcmVudERpY3QpIHsKICAgICAgZGljdC5zZXQoIlYiLCB2YWx1ZSk7CiAgICB9IGVsc2UgaWYgKCFjaGFuZ2VzLmhhcyhwYXJlbnRSZWYpKSB7CiAgICAgIGNvbnN0IG5ld1BhcmVudERpY3QgPSBwYXJlbnREaWN0LmNsb25lKCk7CiAgICAgIG5ld1BhcmVudERpY3Quc2V0KCJWIiwgdmFsdWUpOwogICAgICBjaGFuZ2VzLnB1dChwYXJlbnRSZWYsIHsKICAgICAgICBkYXRhOiBuZXdQYXJlbnREaWN0CiAgICAgIH0pOwogICAgICByZXR1cm4gbmV3UGFyZW50RGljdDsKICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KICBhc3luYyBzYXZlKGV2YWx1YXRvciwgdGFzaywgYW5ub3RhdGlvblN0b3JhZ2UsIGNoYW5nZXMpIHsKICAgIGNvbnN0IHN0b3JhZ2VFbnRyeSA9IGFubm90YXRpb25TdG9yYWdlPy5nZXQodGhpcy5kYXRhLmlkKTsKICAgIGNvbnN0IGZsYWdzID0gdGhpcy5fYnVpbGRGbGFncyhzdG9yYWdlRW50cnk/Lm5vVmlldywgc3RvcmFnZUVudHJ5Py5ub1ByaW50KTsKICAgIGxldCB2YWx1ZSA9IHN0b3JhZ2VFbnRyeT8udmFsdWUsCiAgICAgIHJvdGF0aW9uID0gc3RvcmFnZUVudHJ5Py5yb3RhdGlvbjsKICAgIGlmICh2YWx1ZSA9PT0gdGhpcy5kYXRhLmZpZWxkVmFsdWUgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkgewogICAgICBpZiAoIXRoaXMuX2hhc1ZhbHVlRnJvbVhGQSAmJiByb3RhdGlvbiA9PT0gdW5kZWZpbmVkICYmIGZsYWdzID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdmFsdWUgfHw9IHRoaXMuZGF0YS5maWVsZFZhbHVlOwogICAgfQogICAgaWYgKHJvdGF0aW9uID09PSB1bmRlZmluZWQgJiYgIXRoaXMuX2hhc1ZhbHVlRnJvbVhGQSAmJiBBcnJheS5pc0FycmF5KHZhbHVlKSAmJiBBcnJheS5pc0FycmF5KHRoaXMuZGF0YS5maWVsZFZhbHVlKSAmJiBpc0FycmF5RXF1YWwodmFsdWUsIHRoaXMuZGF0YS5maWVsZFZhbHVlKSAmJiBmbGFncyA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmIChyb3RhdGlvbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJvdGF0aW9uID0gdGhpcy5yb3RhdGlvbjsKICAgIH0KICAgIGxldCBhcHBlYXJhbmNlID0gbnVsbDsKICAgIGlmICghdGhpcy5fbmVlZEFwcGVhcmFuY2VzKSB7CiAgICAgIGFwcGVhcmFuY2UgPSBhd2FpdCB0aGlzLl9nZXRBcHBlYXJhbmNlKGV2YWx1YXRvciwgdGFzaywgUmVuZGVyaW5nSW50ZW50RmxhZy5TQVZFLCBhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICAgIGlmIChhcHBlYXJhbmNlID09PSBudWxsICYmIGZsYWdzID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgIH0gZWxzZSB7fQogICAgbGV0IG5lZWRBcHBlYXJhbmNlcyA9IGZhbHNlOwogICAgaWYgKGFwcGVhcmFuY2U/Lm5lZWRBcHBlYXJhbmNlcykgewogICAgICBuZWVkQXBwZWFyYW5jZXMgPSB0cnVlOwogICAgICBhcHBlYXJhbmNlID0gbnVsbDsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgeHJlZgogICAgfSA9IGV2YWx1YXRvcjsKICAgIGNvbnN0IG9yaWdpbmFsRGljdCA9IHhyZWYuZmV0Y2hJZlJlZih0aGlzLnJlZik7CiAgICBpZiAoIShvcmlnaW5hbERpY3QgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBkaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICBmb3IgKGNvbnN0IGtleSBvZiBvcmlnaW5hbERpY3QuZ2V0S2V5cygpKSB7CiAgICAgIGlmIChrZXkgIT09ICJBUCIpIHsKICAgICAgICBkaWN0LnNldChrZXksIG9yaWdpbmFsRGljdC5nZXRSYXcoa2V5KSk7CiAgICAgIH0KICAgIH0KICAgIGlmIChmbGFncyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIGRpY3Quc2V0KCJGIiwgZmxhZ3MpOwogICAgICBpZiAoYXBwZWFyYW5jZSA9PT0gbnVsbCAmJiAhbmVlZEFwcGVhcmFuY2VzKSB7CiAgICAgICAgY29uc3QgYXAgPSBvcmlnaW5hbERpY3QuZ2V0UmF3KCJBUCIpOwogICAgICAgIGlmIChhcCkgewogICAgICAgICAgZGljdC5zZXQoIkFQIiwgYXApOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgY29uc3QgeGZhID0gewogICAgICBwYXRoOiB0aGlzLmRhdGEuZmllbGROYW1lLAogICAgICB2YWx1ZQogICAgfTsKICAgIGNvbnN0IG5ld1BhcmVudERpY3QgPSB0aGlzLnNldFZhbHVlKGRpY3QsIEFycmF5LmlzQXJyYXkodmFsdWUpID8gdmFsdWUubWFwKHN0cmluZ1RvQXNjaWlPclVURjE2QkUpIDogc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRSh2YWx1ZSksIHhyZWYsIGNoYW5nZXMpOwogICAgdGhpcy5hbWVuZFNhdmVkRGljdChhbm5vdGF0aW9uU3RvcmFnZSwgbmV3UGFyZW50RGljdCB8fCBkaWN0KTsKICAgIGNvbnN0IG1heWJlTUsgPSB0aGlzLl9nZXRNS0RpY3Qocm90YXRpb24pOwogICAgaWYgKG1heWJlTUspIHsKICAgICAgZGljdC5zZXQoIk1LIiwgbWF5YmVNSyk7CiAgICB9CiAgICBjaGFuZ2VzLnB1dCh0aGlzLnJlZiwgewogICAgICBkYXRhOiBkaWN0LAogICAgICB4ZmEsCiAgICAgIG5lZWRBcHBlYXJhbmNlcwogICAgfSk7CiAgICBpZiAoYXBwZWFyYW5jZSAhPT0gbnVsbCkgewogICAgICBjb25zdCBuZXdSZWYgPSB4cmVmLmdldE5ld1RlbXBvcmFyeVJlZigpOwogICAgICBjb25zdCBBUCA9IG5ldyBEaWN0KHhyZWYpOwogICAgICBkaWN0LnNldCgiQVAiLCBBUCk7CiAgICAgIEFQLnNldCgiTiIsIG5ld1JlZik7CiAgICAgIGNvbnN0IHJlc291cmNlcyA9IHRoaXMuX2dldFNhdmVGaWVsZFJlc291cmNlcyh4cmVmKTsKICAgICAgY29uc3QgYXBwZWFyYW5jZVN0cmVhbSA9IG5ldyBTdHJpbmdTdHJlYW0oYXBwZWFyYW5jZSk7CiAgICAgIGNvbnN0IGFwcGVhcmFuY2VEaWN0ID0gYXBwZWFyYW5jZVN0cmVhbS5kaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICAgIGFwcGVhcmFuY2VEaWN0LnNldElmTmFtZSgiU3VidHlwZSIsICJGb3JtIik7CiAgICAgIGFwcGVhcmFuY2VEaWN0LnNldCgiUmVzb3VyY2VzIiwgcmVzb3VyY2VzKTsKICAgICAgY29uc3QgYmJveCA9IHJvdGF0aW9uICUgMTgwID09PSAwID8gWzAsIDAsIHRoaXMud2lkdGgsIHRoaXMuaGVpZ2h0XSA6IFswLCAwLCB0aGlzLmhlaWdodCwgdGhpcy53aWR0aF07CiAgICAgIGFwcGVhcmFuY2VEaWN0LnNldCgiQkJveCIsIGJib3gpOwogICAgICBjb25zdCByb3RhdGlvbk1hdHJpeCA9IHRoaXMuZ2V0Um90YXRpb25NYXRyaXgoYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgICBpZiAocm90YXRpb25NYXRyaXggIT09IElERU5USVRZX01BVFJJWCkgewogICAgICAgIGFwcGVhcmFuY2VEaWN0LnNldCgiTWF0cml4Iiwgcm90YXRpb25NYXRyaXgpOwogICAgICB9CiAgICAgIGNoYW5nZXMucHV0KG5ld1JlZiwgewogICAgICAgIGRhdGE6IGFwcGVhcmFuY2VTdHJlYW0sCiAgICAgICAgeGZhOiBudWxsLAogICAgICAgIG5lZWRBcHBlYXJhbmNlczogZmFsc2UKICAgICAgfSk7CiAgICB9CiAgICBkaWN0LnNldCgiTSIsIGBEOiR7Z2V0TW9kaWZpY2F0aW9uRGF0ZSgpfWApOwogIH0KICBhc3luYyBfZ2V0QXBwZWFyYW5jZShldmFsdWF0b3IsIHRhc2ssIGludGVudCwgYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgIGlmICh0aGlzLmRhdGEucGFzc3dvcmQpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCBzdG9yYWdlRW50cnkgPSBhbm5vdGF0aW9uU3RvcmFnZT8uZ2V0KHRoaXMuZGF0YS5pZCk7CiAgICBsZXQgdmFsdWUsIHJvdGF0aW9uOwogICAgaWYgKHN0b3JhZ2VFbnRyeSkgewogICAgICB2YWx1ZSA9IHN0b3JhZ2VFbnRyeS5mb3JtYXR0ZWRWYWx1ZSB8fCBzdG9yYWdlRW50cnkudmFsdWU7CiAgICAgIHJvdGF0aW9uID0gc3RvcmFnZUVudHJ5LnJvdGF0aW9uOwogICAgfQogICAgaWYgKHJvdGF0aW9uID09PSB1bmRlZmluZWQgJiYgdmFsdWUgPT09IHVuZGVmaW5lZCAmJiAhdGhpcy5fbmVlZEFwcGVhcmFuY2VzKSB7CiAgICAgIGlmICghdGhpcy5faGFzVmFsdWVGcm9tWEZBIHx8IHRoaXMuYXBwZWFyYW5jZSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICB9CiAgICBjb25zdCBjb2xvcnMgPSB0aGlzLmdldEJvcmRlckFuZEJhY2tncm91bmRBcHBlYXJhbmNlcyhhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkgewogICAgICB2YWx1ZSA9IHRoaXMuZGF0YS5maWVsZFZhbHVlOwogICAgICBpZiAoIXZhbHVlKSB7CiAgICAgICAgcmV0dXJuIGAvVHggQk1DIHEgJHtjb2xvcnN9USBFTUNgOwogICAgICB9CiAgICB9CiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkgJiYgdmFsdWUubGVuZ3RoID09PSAxKSB7CiAgICAgIHZhbHVlID0gdmFsdWVbMF07CiAgICB9CiAgICBhc3NlcnQodHlwZW9mIHZhbHVlID09PSAic3RyaW5nIiwgIkV4cGVjdGVkIGB2YWx1ZWAgdG8gYmUgYSBzdHJpbmcuIik7CiAgICB2YWx1ZSA9IHZhbHVlLnRyaW1FbmQoKTsKICAgIGlmICh0aGlzLmRhdGEuY29tYm8pIHsKICAgICAgY29uc3Qgb3B0aW9uID0gdGhpcy5kYXRhLm9wdGlvbnMuZmluZCgoewogICAgICAgIGV4cG9ydFZhbHVlCiAgICAgIH0pID0+IHZhbHVlID09PSBleHBvcnRWYWx1ZSk7CiAgICAgIHZhbHVlID0gb3B0aW9uPy5kaXNwbGF5VmFsdWUgfHwgdmFsdWU7CiAgICB9CiAgICBpZiAodmFsdWUgPT09ICIiKSB7CiAgICAgIHJldHVybiBgL1R4IEJNQyBxICR7Y29sb3JzfVEgRU1DYDsKICAgIH0KICAgIGlmIChyb3RhdGlvbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJvdGF0aW9uID0gdGhpcy5yb3RhdGlvbjsKICAgIH0KICAgIGxldCBsaW5lQ291bnQgPSAtMTsKICAgIGxldCBsaW5lczsKICAgIGlmICh0aGlzLmRhdGEubXVsdGlMaW5lKSB7CiAgICAgIGxpbmVzID0gdmFsdWUuc3BsaXQoL1xyXG4/fFxuLykubWFwKGxpbmUgPT4gbGluZS5ub3JtYWxpemUoIk5GQyIpKTsKICAgICAgbGluZUNvdW50ID0gbGluZXMubGVuZ3RoOwogICAgfSBlbHNlIHsKICAgICAgbGluZXMgPSBbdmFsdWUucmVwbGFjZSgvXHJcbj98XG4vLCAiIikubm9ybWFsaXplKCJORkMiKV07CiAgICB9CiAgICBjb25zdCBkZWZhdWx0UGFkZGluZyA9IDE7CiAgICBjb25zdCBkZWZhdWx0SFBhZGRpbmcgPSAyOwogICAgbGV0IHsKICAgICAgd2lkdGg6IHRvdGFsV2lkdGgsCiAgICAgIGhlaWdodDogdG90YWxIZWlnaHQKICAgIH0gPSB0aGlzOwogICAgaWYgKHJvdGF0aW9uID09PSA5MCB8fCByb3RhdGlvbiA9PT0gMjcwKSB7CiAgICAgIFt0b3RhbFdpZHRoLCB0b3RhbEhlaWdodF0gPSBbdG90YWxIZWlnaHQsIHRvdGFsV2lkdGhdOwogICAgfQogICAgaWYgKCF0aGlzLl9kZWZhdWx0QXBwZWFyYW5jZSkgewogICAgICB0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhID0gcGFyc2VEZWZhdWx0QXBwZWFyYW5jZSh0aGlzLl9kZWZhdWx0QXBwZWFyYW5jZSA9ICIvSGVsdmV0aWNhIDAgVGYgMCBnIik7CiAgICB9CiAgICBsZXQgZm9udCA9IGF3YWl0IFdpZGdldEFubm90YXRpb24uX2dldEZvbnREYXRhKGV2YWx1YXRvciwgdGFzaywgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YSwgdGhpcy5fZmllbGRSZXNvdXJjZXMubWVyZ2VkUmVzb3VyY2VzKTsKICAgIGxldCBkZWZhdWx0QXBwZWFyYW5jZSwgZm9udFNpemUsIGxpbmVIZWlnaHQ7CiAgICBjb25zdCBlbmNvZGVkTGluZXMgPSBbXTsKICAgIGxldCBlbmNvZGluZ0Vycm9yID0gZmFsc2U7CiAgICBmb3IgKGNvbnN0IGxpbmUgb2YgbGluZXMpIHsKICAgICAgY29uc3QgZW5jb2RlZFN0cmluZyA9IGZvbnQuZW5jb2RlU3RyaW5nKGxpbmUpOwogICAgICBpZiAoZW5jb2RlZFN0cmluZy5sZW5ndGggPiAxKSB7CiAgICAgICAgZW5jb2RpbmdFcnJvciA9IHRydWU7CiAgICAgIH0KICAgICAgZW5jb2RlZExpbmVzLnB1c2goZW5jb2RlZFN0cmluZy5qb2luKCIiKSk7CiAgICB9CiAgICBpZiAoZW5jb2RpbmdFcnJvciAmJiBpbnRlbnQgJiBSZW5kZXJpbmdJbnRlbnRGbGFnLlNBVkUpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICBuZWVkQXBwZWFyYW5jZXM6IHRydWUKICAgICAgfTsKICAgIH0KICAgIGlmIChlbmNvZGluZ0Vycm9yICYmIHRoaXMuX2lzT2Zmc2NyZWVuQ2FudmFzU3VwcG9ydGVkKSB7CiAgICAgIGNvbnN0IGZvbnRGYW1pbHkgPSB0aGlzLmRhdGEuY29tYiA/ICJtb25vc3BhY2UiIDogInNhbnMtc2VyaWYiOwogICAgICBjb25zdCBmYWtlVW5pY29kZUZvbnQgPSBuZXcgRmFrZVVuaWNvZGVGb250KGV2YWx1YXRvci54cmVmLCBmb250RmFtaWx5KTsKICAgICAgY29uc3QgcmVzb3VyY2VzID0gZmFrZVVuaWNvZGVGb250LmNyZWF0ZUZvbnRSZXNvdXJjZXMobGluZXMuam9pbigiIikpOwogICAgICBjb25zdCBuZXdGb250ID0gcmVzb3VyY2VzLmdldFJhdygiRm9udCIpOwogICAgICBpZiAodGhpcy5fZmllbGRSZXNvdXJjZXMubWVyZ2VkUmVzb3VyY2VzLmhhcygiRm9udCIpKSB7CiAgICAgICAgY29uc3Qgb2xkRm9udCA9IHRoaXMuX2ZpZWxkUmVzb3VyY2VzLm1lcmdlZFJlc291cmNlcy5nZXQoIkZvbnQiKTsKICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiBuZXdGb250LmdldEtleXMoKSkgewogICAgICAgICAgb2xkRm9udC5zZXQoa2V5LCBuZXdGb250LmdldFJhdyhrZXkpKTsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5fZmllbGRSZXNvdXJjZXMubWVyZ2VkUmVzb3VyY2VzLnNldCgiRm9udCIsIG5ld0ZvbnQpOwogICAgICB9CiAgICAgIGNvbnN0IGZvbnROYW1lID0gZmFrZVVuaWNvZGVGb250LmZvbnROYW1lLm5hbWU7CiAgICAgIGZvbnQgPSBhd2FpdCBXaWRnZXRBbm5vdGF0aW9uLl9nZXRGb250RGF0YShldmFsdWF0b3IsIHRhc2ssIHsKICAgICAgICBmb250TmFtZSwKICAgICAgICBmb250U2l6ZTogMAogICAgICB9LCByZXNvdXJjZXMpOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBlbmNvZGVkTGluZXMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGVuY29kZWRMaW5lc1tpXSA9IHN0cmluZ1RvVVRGMTZTdHJpbmcobGluZXNbaV0pOwogICAgICB9CiAgICAgIGNvbnN0IHNhdmVkRGVmYXVsdEFwcGVhcmFuY2UgPSBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobnVsbCksIHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEpOwogICAgICB0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhLmZvbnRTaXplID0gMDsKICAgICAgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YS5mb250TmFtZSA9IGZvbnROYW1lOwogICAgICBbZGVmYXVsdEFwcGVhcmFuY2UsIGZvbnRTaXplLCBsaW5lSGVpZ2h0XSA9IHRoaXMuX2NvbXB1dGVGb250U2l6ZSh0b3RhbEhlaWdodCAtIDIgKiBkZWZhdWx0UGFkZGluZywgdG90YWxXaWR0aCAtIDIgKiBkZWZhdWx0SFBhZGRpbmcsIHZhbHVlLCBmb250LCBsaW5lQ291bnQpOwogICAgICB0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhID0gc2F2ZWREZWZhdWx0QXBwZWFyYW5jZTsKICAgIH0gZWxzZSB7CiAgICAgIGlmICghdGhpcy5faXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpIHsKICAgICAgICB3YXJuKCJfZ2V0QXBwZWFyYW5jZTogT2Zmc2NyZWVuQ2FudmFzIGlzIG5vdCBzdXBwb3J0ZWQsIGFubm90YXRpb24gbWF5IG5vdCByZW5kZXIgY29ycmVjdGx5LiIpOwogICAgICB9CiAgICAgIFtkZWZhdWx0QXBwZWFyYW5jZSwgZm9udFNpemUsIGxpbmVIZWlnaHRdID0gdGhpcy5fY29tcHV0ZUZvbnRTaXplKHRvdGFsSGVpZ2h0IC0gMiAqIGRlZmF1bHRQYWRkaW5nLCB0b3RhbFdpZHRoIC0gMiAqIGRlZmF1bHRIUGFkZGluZywgdmFsdWUsIGZvbnQsIGxpbmVDb3VudCk7CiAgICB9CiAgICBsZXQgZGVzY2VudCA9IGZvbnQuZGVzY2VudDsKICAgIGlmIChpc05hTihkZXNjZW50KSkgewogICAgICBkZXNjZW50ID0gQkFTRUxJTkVfRkFDVE9SICogbGluZUhlaWdodDsKICAgIH0gZWxzZSB7CiAgICAgIGRlc2NlbnQgPSBNYXRoLm1heChCQVNFTElORV9GQUNUT1IgKiBsaW5lSGVpZ2h0LCBNYXRoLmFicyhkZXNjZW50KSAqIGZvbnRTaXplKTsKICAgIH0KICAgIGNvbnN0IGRlZmF1bHRWUGFkZGluZyA9IE1hdGgubWluKE1hdGguZmxvb3IoKHRvdGFsSGVpZ2h0IC0gZm9udFNpemUpIC8gMiksIGRlZmF1bHRQYWRkaW5nKTsKICAgIGNvbnN0IGFsaWdubWVudCA9IHRoaXMuZGF0YS50ZXh0QWxpZ25tZW50OwogICAgaWYgKHRoaXMuZGF0YS5tdWx0aUxpbmUpIHsKICAgICAgcmV0dXJuIHRoaXMuX2dldE11bHRpbGluZUFwcGVhcmFuY2UoZGVmYXVsdEFwcGVhcmFuY2UsIGVuY29kZWRMaW5lcywgZm9udCwgZm9udFNpemUsIHRvdGFsV2lkdGgsIHRvdGFsSGVpZ2h0LCBhbGlnbm1lbnQsIGRlZmF1bHRIUGFkZGluZywgZGVmYXVsdFZQYWRkaW5nLCBkZXNjZW50LCBsaW5lSGVpZ2h0LCBhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICB9CiAgICBpZiAodGhpcy5kYXRhLmNvbWIpIHsKICAgICAgcmV0dXJuIHRoaXMuX2dldENvbWJBcHBlYXJhbmNlKGRlZmF1bHRBcHBlYXJhbmNlLCBmb250LCBlbmNvZGVkTGluZXNbMF0sIGZvbnRTaXplLCB0b3RhbFdpZHRoLCB0b3RhbEhlaWdodCwgZGVmYXVsdEhQYWRkaW5nLCBkZWZhdWx0VlBhZGRpbmcsIGRlc2NlbnQsIGxpbmVIZWlnaHQsIGFubm90YXRpb25TdG9yYWdlKTsKICAgIH0KICAgIGNvbnN0IGJvdHRvbVBhZGRpbmcgPSBkZWZhdWx0VlBhZGRpbmcgKyBkZXNjZW50OwogICAgaWYgKGFsaWdubWVudCA9PT0gMCB8fCBhbGlnbm1lbnQgPiAyKSB7CiAgICAgIHJldHVybiBgL1R4IEJNQyBxICR7Y29sb3JzfUJUIGAgKyBkZWZhdWx0QXBwZWFyYW5jZSArIGAgMSAwIDAgMSAke251bWJlclRvU3RyaW5nKGRlZmF1bHRIUGFkZGluZyl9ICR7bnVtYmVyVG9TdHJpbmcoYm90dG9tUGFkZGluZyl9IFRtICgke2VzY2FwZVN0cmluZyhlbmNvZGVkTGluZXNbMF0pfSkgVGpgICsgIiBFVCBRIEVNQyI7CiAgICB9CiAgICBjb25zdCBwcmV2SW5mbyA9IHsKICAgICAgc2hpZnQ6IDAKICAgIH07CiAgICBjb25zdCByZW5kZXJlZFRleHQgPSB0aGlzLl9yZW5kZXJUZXh0KGVuY29kZWRMaW5lc1swXSwgZm9udCwgZm9udFNpemUsIHRvdGFsV2lkdGgsIGFsaWdubWVudCwgcHJldkluZm8sIGRlZmF1bHRIUGFkZGluZywgYm90dG9tUGFkZGluZyk7CiAgICByZXR1cm4gYC9UeCBCTUMgcSAke2NvbG9yc31CVCBgICsgZGVmYXVsdEFwcGVhcmFuY2UgKyBgIDEgMCAwIDEgMCAwIFRtICR7cmVuZGVyZWRUZXh0fWAgKyAiIEVUIFEgRU1DIjsKICB9CiAgc3RhdGljIGFzeW5jIF9nZXRGb250RGF0YShldmFsdWF0b3IsIHRhc2ssIGFwcGVhcmFuY2VEYXRhLCByZXNvdXJjZXMpIHsKICAgIGNvbnN0IG9wZXJhdG9yTGlzdCA9IG5ldyBPcGVyYXRvckxpc3QoKTsKICAgIGNvbnN0IGluaXRpYWxTdGF0ZSA9IHsKICAgICAgZm9udDogbnVsbCwKICAgICAgY2xvbmUoKSB7CiAgICAgICAgcmV0dXJuIHRoaXM7CiAgICAgIH0KICAgIH07CiAgICBjb25zdCB7CiAgICAgIGZvbnROYW1lLAogICAgICBmb250U2l6ZQogICAgfSA9IGFwcGVhcmFuY2VEYXRhOwogICAgYXdhaXQgZXZhbHVhdG9yLmhhbmRsZVNldEZvbnQocmVzb3VyY2VzLCBbZm9udE5hbWUgJiYgTmFtZS5nZXQoZm9udE5hbWUpLCBmb250U2l6ZV0sIG51bGwsIG9wZXJhdG9yTGlzdCwgdGFzaywgaW5pdGlhbFN0YXRlLCBudWxsKTsKICAgIHJldHVybiBpbml0aWFsU3RhdGUuZm9udDsKICB9CiAgX2dldFRleHRXaWR0aCh0ZXh0LCBmb250KSB7CiAgICByZXR1cm4gTWF0aC5zdW1QcmVjaXNlKGZvbnQuY2hhcnNUb0dseXBocyh0ZXh0KS5tYXAoZyA9PiBnLndpZHRoKSkgLyAxMDAwOwogIH0KICBfY29tcHV0ZUZvbnRTaXplKGhlaWdodCwgd2lkdGgsIHRleHQsIGZvbnQsIGxpbmVDb3VudCkgewogICAgbGV0IHsKICAgICAgZm9udFNpemUKICAgIH0gPSB0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhOwogICAgbGV0IGxpbmVIZWlnaHQgPSAoZm9udFNpemUgfHwgMTIpICogTElORV9GQUNUT1IsCiAgICAgIG51bWJlck9mTGluZXMgPSBNYXRoLnJvdW5kKGhlaWdodCAvIGxpbmVIZWlnaHQpOwogICAgaWYgKCFmb250U2l6ZSkgewogICAgICBjb25zdCByb3VuZFdpdGhUd29EaWdpdHMgPSB4ID0+IE1hdGguZmxvb3IoeCAqIDEwMCkgLyAxMDA7CiAgICAgIGlmIChsaW5lQ291bnQgPT09IC0xKSB7CiAgICAgICAgY29uc3QgdGV4dFdpZHRoID0gdGhpcy5fZ2V0VGV4dFdpZHRoKHRleHQsIGZvbnQpOwogICAgICAgIGZvbnRTaXplID0gcm91bmRXaXRoVHdvRGlnaXRzKE1hdGgubWluKGhlaWdodCAvIExJTkVfRkFDVE9SLCB3aWR0aCAvIHRleHRXaWR0aCkpOwogICAgICAgIG51bWJlck9mTGluZXMgPSAxOwogICAgICB9IGVsc2UgewogICAgICAgIGNvbnN0IGxpbmVzID0gdGV4dC5zcGxpdCgvXHJcbj98XG4vKTsKICAgICAgICBjb25zdCBjYWNoZWRMaW5lcyA9IFtdOwogICAgICAgIGZvciAoY29uc3QgbGluZSBvZiBsaW5lcykgewogICAgICAgICAgY29uc3QgZW5jb2RlZCA9IGZvbnQuZW5jb2RlU3RyaW5nKGxpbmUpLmpvaW4oIiIpOwogICAgICAgICAgY29uc3QgZ2x5cGhzID0gZm9udC5jaGFyc1RvR2x5cGhzKGVuY29kZWQpOwogICAgICAgICAgY29uc3QgcG9zaXRpb25zID0gZm9udC5nZXRDaGFyUG9zaXRpb25zKGVuY29kZWQpOwogICAgICAgICAgY2FjaGVkTGluZXMucHVzaCh7CiAgICAgICAgICAgIGxpbmU6IGVuY29kZWQsCiAgICAgICAgICAgIGdseXBocywKICAgICAgICAgICAgcG9zaXRpb25zCiAgICAgICAgICB9KTsKICAgICAgICB9CiAgICAgICAgY29uc3QgaXNUb29CaWcgPSBmc2l6ZSA9PiB7CiAgICAgICAgICBsZXQgdG90YWxIZWlnaHQgPSAwOwogICAgICAgICAgZm9yIChjb25zdCBjYWNoZSBvZiBjYWNoZWRMaW5lcykgewogICAgICAgICAgICBjb25zdCBjaHVua3MgPSB0aGlzLl9zcGxpdExpbmUobnVsbCwgZm9udCwgZnNpemUsIHdpZHRoLCBjYWNoZSk7CiAgICAgICAgICAgIHRvdGFsSGVpZ2h0ICs9IGNodW5rcy5sZW5ndGggKiBmc2l6ZTsKICAgICAgICAgICAgaWYgKHRvdGFsSGVpZ2h0ID4gaGVpZ2h0KSB7CiAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9OwogICAgICAgIG51bWJlck9mTGluZXMgPSBNYXRoLm1heChudW1iZXJPZkxpbmVzLCBsaW5lQ291bnQpOwogICAgICAgIHdoaWxlICh0cnVlKSB7CiAgICAgICAgICBsaW5lSGVpZ2h0ID0gaGVpZ2h0IC8gbnVtYmVyT2ZMaW5lczsKICAgICAgICAgIGZvbnRTaXplID0gcm91bmRXaXRoVHdvRGlnaXRzKGxpbmVIZWlnaHQgLyBMSU5FX0ZBQ1RPUik7CiAgICAgICAgICBpZiAoaXNUb29CaWcoZm9udFNpemUpKSB7CiAgICAgICAgICAgIG51bWJlck9mTGluZXMrKzsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgewogICAgICAgIGZvbnROYW1lLAogICAgICAgIGZvbnRDb2xvcgogICAgICB9ID0gdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YTsKICAgICAgdGhpcy5fZGVmYXVsdEFwcGVhcmFuY2UgPSBjcmVhdGVEZWZhdWx0QXBwZWFyYW5jZSh7CiAgICAgICAgZm9udFNpemUsCiAgICAgICAgZm9udE5hbWUsCiAgICAgICAgZm9udENvbG9yCiAgICAgIH0pOwogICAgfQogICAgcmV0dXJuIFt0aGlzLl9kZWZhdWx0QXBwZWFyYW5jZSwgZm9udFNpemUsIGhlaWdodCAvIG51bWJlck9mTGluZXNdOwogIH0KICBfcmVuZGVyVGV4dCh0ZXh0LCBmb250LCBmb250U2l6ZSwgdG90YWxXaWR0aCwgYWxpZ25tZW50LCBwcmV2SW5mbywgaFBhZGRpbmcsIHZQYWRkaW5nKSB7CiAgICBsZXQgc2hpZnQ7CiAgICBpZiAoYWxpZ25tZW50ID09PSAxKSB7CiAgICAgIGNvbnN0IHdpZHRoID0gdGhpcy5fZ2V0VGV4dFdpZHRoKHRleHQsIGZvbnQpICogZm9udFNpemU7CiAgICAgIHNoaWZ0ID0gKHRvdGFsV2lkdGggLSB3aWR0aCkgLyAyOwogICAgfSBlbHNlIGlmIChhbGlnbm1lbnQgPT09IDIpIHsKICAgICAgY29uc3Qgd2lkdGggPSB0aGlzLl9nZXRUZXh0V2lkdGgodGV4dCwgZm9udCkgKiBmb250U2l6ZTsKICAgICAgc2hpZnQgPSB0b3RhbFdpZHRoIC0gd2lkdGggLSBoUGFkZGluZzsKICAgIH0gZWxzZSB7CiAgICAgIHNoaWZ0ID0gaFBhZGRpbmc7CiAgICB9CiAgICBjb25zdCBzaGlmdFN0ciA9IG51bWJlclRvU3RyaW5nKHNoaWZ0IC0gcHJldkluZm8uc2hpZnQpOwogICAgcHJldkluZm8uc2hpZnQgPSBzaGlmdDsKICAgIHZQYWRkaW5nID0gbnVtYmVyVG9TdHJpbmcodlBhZGRpbmcpOwogICAgcmV0dXJuIGAke3NoaWZ0U3RyfSAke3ZQYWRkaW5nfSBUZCAoJHtlc2NhcGVTdHJpbmcodGV4dCl9KSBUamA7CiAgfQogIF9nZXRTYXZlRmllbGRSZXNvdXJjZXMoeHJlZikgewogICAgY29uc3QgewogICAgICBsb2NhbFJlc291cmNlcywKICAgICAgYXBwZWFyYW5jZVJlc291cmNlcywKICAgICAgYWNyb0Zvcm1SZXNvdXJjZXMKICAgIH0gPSB0aGlzLl9maWVsZFJlc291cmNlczsKICAgIGNvbnN0IGZvbnROYW1lID0gdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YT8uZm9udE5hbWU7CiAgICBpZiAoIWZvbnROYW1lKSB7CiAgICAgIHJldHVybiBsb2NhbFJlc291cmNlcyB8fCBEaWN0LmVtcHR5OwogICAgfQogICAgZm9yIChjb25zdCByZXNvdXJjZXMgb2YgW2xvY2FsUmVzb3VyY2VzLCBhcHBlYXJhbmNlUmVzb3VyY2VzXSkgewogICAgICBpZiAocmVzb3VyY2VzIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgIGNvbnN0IGxvY2FsRm9udCA9IHJlc291cmNlcy5nZXQoIkZvbnQiKTsKICAgICAgICBpZiAobG9jYWxGb250IGluc3RhbmNlb2YgRGljdCAmJiBsb2NhbEZvbnQuaGFzKGZvbnROYW1lKSkgewogICAgICAgICAgcmV0dXJuIHJlc291cmNlczsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIGlmIChhY3JvRm9ybVJlc291cmNlcyBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgY29uc3QgYWNyb0Zvcm1Gb250ID0gYWNyb0Zvcm1SZXNvdXJjZXMuZ2V0KCJGb250Iik7CiAgICAgIGlmIChhY3JvRm9ybUZvbnQgaW5zdGFuY2VvZiBEaWN0ICYmIGFjcm9Gb3JtRm9udC5oYXMoZm9udE5hbWUpKSB7CiAgICAgICAgY29uc3Qgc3ViRm9udERpY3QgPSBuZXcgRGljdCh4cmVmKTsKICAgICAgICBzdWJGb250RGljdC5zZXQoZm9udE5hbWUsIGFjcm9Gb3JtRm9udC5nZXRSYXcoZm9udE5hbWUpKTsKICAgICAgICBjb25zdCBzdWJSZXNvdXJjZXNEaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICAgICAgc3ViUmVzb3VyY2VzRGljdC5zZXQoIkZvbnQiLCBzdWJGb250RGljdCk7CiAgICAgICAgcmV0dXJuIERpY3QubWVyZ2UoewogICAgICAgICAgeHJlZiwKICAgICAgICAgIGRpY3RBcnJheTogW3N1YlJlc291cmNlc0RpY3QsIGxvY2FsUmVzb3VyY2VzXSwKICAgICAgICAgIG1lcmdlU3ViRGljdHM6IHRydWUKICAgICAgICB9KTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGxvY2FsUmVzb3VyY2VzIHx8IERpY3QuZW1wdHk7CiAgfQogIGdldEZpZWxkT2JqZWN0KCkgewogICAgcmV0dXJuIG51bGw7CiAgfQp9CmNsYXNzIFRleHRXaWRnZXRBbm5vdGF0aW9uIGV4dGVuZHMgV2lkZ2V0QW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0CiAgICB9ID0gcGFyYW1zOwogICAgaWYgKGRpY3QuaGFzKCJQTUQiKSkgewogICAgICB0aGlzLmZsYWdzIHw9IEFubm90YXRpb25GbGFnLkhJRERFTjsKICAgICAgdGhpcy5kYXRhLmhpZGRlbiA9IHRydWU7CiAgICAgIHdhcm4oIkJhcmNvZGVzIGFyZSBub3Qgc3VwcG9ydGVkIik7CiAgICB9CiAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdGhpcy5kYXRhLnJlYWRPbmx5ICYmICF0aGlzLmRhdGEubm9IVE1MOwogICAgdGhpcy5faGFzVGV4dCA9IHRydWU7CiAgICBpZiAodHlwZW9mIHRoaXMuZGF0YS5maWVsZFZhbHVlICE9PSAic3RyaW5nIikgewogICAgICB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9ICIiOwogICAgfQogICAgbGV0IGFsaWdubWVudCA9IGdldEluaGVyaXRhYmxlUHJvcGVydHkoewogICAgICBkaWN0LAogICAgICBrZXk6ICJRIgogICAgfSk7CiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoYWxpZ25tZW50KSB8fCBhbGlnbm1lbnQgPCAwIHx8IGFsaWdubWVudCA+IDIpIHsKICAgICAgYWxpZ25tZW50ID0gbnVsbDsKICAgIH0KICAgIHRoaXMuZGF0YS50ZXh0QWxpZ25tZW50ID0gYWxpZ25tZW50OwogICAgbGV0IG1heGltdW1MZW5ndGggPSBnZXRJbmhlcml0YWJsZVByb3BlcnR5KHsKICAgICAgZGljdCwKICAgICAga2V5OiAiTWF4TGVuIgogICAgfSk7CiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIobWF4aW11bUxlbmd0aCkgfHwgbWF4aW11bUxlbmd0aCA8IDApIHsKICAgICAgbWF4aW11bUxlbmd0aCA9IDA7CiAgICB9CiAgICB0aGlzLmRhdGEubWF4TGVuID0gbWF4aW11bUxlbmd0aDsKICAgIHRoaXMuZGF0YS5tdWx0aUxpbmUgPSB0aGlzLmhhc0ZpZWxkRmxhZyhBbm5vdGF0aW9uRmllbGRGbGFnLk1VTFRJTElORSk7CiAgICB0aGlzLmRhdGEuY29tYiA9IHRoaXMuaGFzRmllbGRGbGFnKEFubm90YXRpb25GaWVsZEZsYWcuQ09NQikgJiYgIXRoaXMuZGF0YS5tdWx0aUxpbmUgJiYgIXRoaXMuZGF0YS5wYXNzd29yZCAmJiAhdGhpcy5oYXNGaWVsZEZsYWcoQW5ub3RhdGlvbkZpZWxkRmxhZy5GSUxFU0VMRUNUKSAmJiB0aGlzLmRhdGEubWF4TGVuICE9PSAwOwogICAgdGhpcy5kYXRhLmRvTm90U2Nyb2xsID0gdGhpcy5oYXNGaWVsZEZsYWcoQW5ub3RhdGlvbkZpZWxkRmxhZy5ET05PVFNDUk9MTCk7CiAgICBjb25zdCB7CiAgICAgIGRhdGE6IHsKICAgICAgICBhY3Rpb25zCiAgICAgIH0KICAgIH0gPSB0aGlzOwogICAgaWYgKCFhY3Rpb25zKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IEFGRGF0ZVRpbWUgPSAvXkFGKERhdGV8VGltZSlfKD86S2V5c3Ryb2tlfEZvcm1hdCkoPzpFeCk/XChbJyJdPyhbXiciXSspWyciXT9cKTskLzsKICAgIGxldCBjYW5Vc2VIVE1MRGF0ZVRpbWUgPSBmYWxzZTsKICAgIGlmIChhY3Rpb25zLkZvcm1hdD8ubGVuZ3RoID09PSAxICYmIGFjdGlvbnMuS2V5c3Ryb2tlPy5sZW5ndGggPT09IDEgJiYgQUZEYXRlVGltZS50ZXN0KGFjdGlvbnMuRm9ybWF0WzBdKSAmJiBBRkRhdGVUaW1lLnRlc3QoYWN0aW9ucy5LZXlzdHJva2VbMF0pIHx8IGFjdGlvbnMuRm9ybWF0Py5sZW5ndGggPT09IDAgJiYgYWN0aW9ucy5LZXlzdHJva2U/Lmxlbmd0aCA9PT0gMSAmJiBBRkRhdGVUaW1lLnRlc3QoYWN0aW9ucy5LZXlzdHJva2VbMF0pIHx8IGFjdGlvbnMuS2V5c3Ryb2tlPy5sZW5ndGggPT09IDAgJiYgYWN0aW9ucy5Gb3JtYXQ/Lmxlbmd0aCA9PT0gMSAmJiBBRkRhdGVUaW1lLnRlc3QoYWN0aW9ucy5Gb3JtYXRbMF0pKSB7CiAgICAgIGNhblVzZUhUTUxEYXRlVGltZSA9IHRydWU7CiAgICB9CiAgICBjb25zdCBhY3Rpb25zVG9WaXNpdCA9IFtdOwogICAgaWYgKGFjdGlvbnMuRm9ybWF0KSB7CiAgICAgIGFjdGlvbnNUb1Zpc2l0LnB1c2goLi4uYWN0aW9ucy5Gb3JtYXQpOwogICAgfQogICAgaWYgKGFjdGlvbnMuS2V5c3Ryb2tlKSB7CiAgICAgIGFjdGlvbnNUb1Zpc2l0LnB1c2goLi4uYWN0aW9ucy5LZXlzdHJva2UpOwogICAgfQogICAgaWYgKGNhblVzZUhUTUxEYXRlVGltZSkgewogICAgICBkZWxldGUgYWN0aW9ucy5LZXlzdHJva2U7CiAgICAgIGFjdGlvbnMuRm9ybWF0ID0gYWN0aW9uc1RvVmlzaXQ7CiAgICB9CiAgICBmb3IgKGNvbnN0IGZvcm1hdEFjdGlvbiBvZiBhY3Rpb25zVG9WaXNpdCkgewogICAgICBjb25zdCBtID0gZm9ybWF0QWN0aW9uLm1hdGNoKEFGRGF0ZVRpbWUpOwogICAgICBpZiAoIW0pIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBpc0RhdGUgPSBtWzFdID09PSAiRGF0ZSI7CiAgICAgIGxldCBmb3JtYXQgPSBtWzJdOwogICAgICBjb25zdCBudW0gPSBwYXJzZUludChmb3JtYXQsIDEwKTsKICAgICAgaWYgKCFpc05hTihudW0pICYmIE1hdGguZmxvb3IoTWF0aC5sb2cxMChudW0pKSArIDEgPT09IG1bMl0ubGVuZ3RoKSB7CiAgICAgICAgZm9ybWF0ID0gKGlzRGF0ZSA/IERhdGVGb3JtYXRzIDogVGltZUZvcm1hdHMpW251bV0gPz8gZm9ybWF0OwogICAgICB9CiAgICAgIHRoaXMuZGF0YS5kYXRldGltZUZvcm1hdCA9IGZvcm1hdDsKICAgICAgaWYgKCFjYW5Vc2VIVE1MRGF0ZVRpbWUpIHsKICAgICAgICBicmVhazsKICAgICAgfQogICAgICBpZiAoaXNEYXRlKSB7CiAgICAgICAgaWYgKC9ISHxNTXxzc3xoLy50ZXN0KGZvcm1hdCkpIHsKICAgICAgICAgIHRoaXMuZGF0YS5kYXRldGltZVR5cGUgPSAiZGF0ZXRpbWUtbG9jYWwiOwogICAgICAgICAgdGhpcy5kYXRhLnRpbWVTdGVwID0gL3NzLy50ZXN0KGZvcm1hdCkgPyAxIDogNjA7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHRoaXMuZGF0YS5kYXRldGltZVR5cGUgPSAiZGF0ZSI7CiAgICAgICAgfQogICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIHRoaXMuZGF0YS5kYXRldGltZVR5cGUgPSAidGltZSI7CiAgICAgIHRoaXMuZGF0YS50aW1lU3RlcCA9IC9zcy8udGVzdChmb3JtYXQpID8gMSA6IDYwOwogICAgICBicmVhazsKICAgIH0KICB9CiAgZ2V0IGhhc1RleHRDb250ZW50KCkgewogICAgcmV0dXJuICEhdGhpcy5hcHBlYXJhbmNlICYmICF0aGlzLl9uZWVkQXBwZWFyYW5jZXM7CiAgfQogIF9nZXRDb21iQXBwZWFyYW5jZShkZWZhdWx0QXBwZWFyYW5jZSwgZm9udCwgdGV4dCwgZm9udFNpemUsIHdpZHRoLCBoZWlnaHQsIGhQYWRkaW5nLCB2UGFkZGluZywgZGVzY2VudCwgbGluZUhlaWdodCwgYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgIGNvbnN0IGNvbWJXaWR0aCA9IHdpZHRoIC8gdGhpcy5kYXRhLm1heExlbjsKICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuZ2V0Qm9yZGVyQW5kQmFja2dyb3VuZEFwcGVhcmFuY2VzKGFubm90YXRpb25TdG9yYWdlKTsKICAgIGNvbnN0IGJ1ZiA9IFtdOwogICAgY29uc3QgcG9zaXRpb25zID0gZm9udC5nZXRDaGFyUG9zaXRpb25zKHRleHQpOwogICAgZm9yIChjb25zdCBbc3RhcnQsIGVuZF0gb2YgcG9zaXRpb25zKSB7CiAgICAgIGJ1Zi5wdXNoKGAoJHtlc2NhcGVTdHJpbmcodGV4dC5zdWJzdHJpbmcoc3RhcnQsIGVuZCkpfSkgVGpgKTsKICAgIH0KICAgIGNvbnN0IHJlbmRlcmVkQ29tYiA9IGJ1Zi5qb2luKGAgJHtudW1iZXJUb1N0cmluZyhjb21iV2lkdGgpfSAwIFRkIGApOwogICAgcmV0dXJuIGAvVHggQk1DIHEgJHtjb2xvcnN9QlQgYCArIGRlZmF1bHRBcHBlYXJhbmNlICsgYCAxIDAgMCAxICR7bnVtYmVyVG9TdHJpbmcoaFBhZGRpbmcpfSAke251bWJlclRvU3RyaW5nKHZQYWRkaW5nICsgZGVzY2VudCl9IFRtICR7cmVuZGVyZWRDb21ifWAgKyAiIEVUIFEgRU1DIjsKICB9CiAgX2dldE11bHRpbGluZUFwcGVhcmFuY2UoZGVmYXVsdEFwcGVhcmFuY2UsIGxpbmVzLCBmb250LCBmb250U2l6ZSwgd2lkdGgsIGhlaWdodCwgYWxpZ25tZW50LCBoUGFkZGluZywgdlBhZGRpbmcsIGRlc2NlbnQsIGxpbmVIZWlnaHQsIGFubm90YXRpb25TdG9yYWdlKSB7CiAgICBjb25zdCBidWYgPSBbXTsKICAgIGNvbnN0IHRvdGFsV2lkdGggPSB3aWR0aCAtIDIgKiBoUGFkZGluZzsKICAgIGNvbnN0IHByZXZJbmZvID0gewogICAgICBzaGlmdDogMAogICAgfTsKICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGxpbmVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgbGluZSA9IGxpbmVzW2ldOwogICAgICBjb25zdCBjaHVua3MgPSB0aGlzLl9zcGxpdExpbmUobGluZSwgZm9udCwgZm9udFNpemUsIHRvdGFsV2lkdGgpOwogICAgICBmb3IgKGxldCBqID0gMCwgamogPSBjaHVua3MubGVuZ3RoOyBqIDwgamo7IGorKykgewogICAgICAgIGNvbnN0IGNodW5rID0gY2h1bmtzW2pdOwogICAgICAgIGNvbnN0IHZTaGlmdCA9IGkgPT09IDAgJiYgaiA9PT0gMCA/IC12UGFkZGluZyAtIChsaW5lSGVpZ2h0IC0gZGVzY2VudCkgOiAtbGluZUhlaWdodDsKICAgICAgICBidWYucHVzaCh0aGlzLl9yZW5kZXJUZXh0KGNodW5rLCBmb250LCBmb250U2l6ZSwgd2lkdGgsIGFsaWdubWVudCwgcHJldkluZm8sIGhQYWRkaW5nLCB2U2hpZnQpKTsKICAgICAgfQogICAgfQogICAgY29uc3QgY29sb3JzID0gdGhpcy5nZXRCb3JkZXJBbmRCYWNrZ3JvdW5kQXBwZWFyYW5jZXMoYW5ub3RhdGlvblN0b3JhZ2UpOwogICAgY29uc3QgcmVuZGVyZWRUZXh0ID0gYnVmLmpvaW4oIlxuIik7CiAgICByZXR1cm4gYC9UeCBCTUMgcSAke2NvbG9yc31CVCBgICsgZGVmYXVsdEFwcGVhcmFuY2UgKyBgIDEgMCAwIDEgMCAke251bWJlclRvU3RyaW5nKGhlaWdodCl9IFRtICR7cmVuZGVyZWRUZXh0fWAgKyAiIEVUIFEgRU1DIjsKICB9CiAgX3NwbGl0TGluZShsaW5lLCBmb250LCBmb250U2l6ZSwgd2lkdGgsIGNhY2hlID0ge30pIHsKICAgIGxpbmUgPSBjYWNoZS5saW5lIHx8IGxpbmU7CiAgICBjb25zdCBnbHlwaHMgPSBjYWNoZS5nbHlwaHMgfHwgZm9udC5jaGFyc1RvR2x5cGhzKGxpbmUpOwogICAgaWYgKGdseXBocy5sZW5ndGggPD0gMSkgewogICAgICByZXR1cm4gW2xpbmVdOwogICAgfQogICAgY29uc3QgcG9zaXRpb25zID0gY2FjaGUucG9zaXRpb25zIHx8IGZvbnQuZ2V0Q2hhclBvc2l0aW9ucyhsaW5lKTsKICAgIGNvbnN0IHNjYWxlID0gZm9udFNpemUgLyAxMDAwOwogICAgY29uc3QgY2h1bmtzID0gW107CiAgICBsZXQgbGFzdFNwYWNlUG9zSW5TdHJpbmdTdGFydCA9IC0xLAogICAgICBsYXN0U3BhY2VQb3NJblN0cmluZ0VuZCA9IC0xLAogICAgICBsYXN0U3BhY2VQb3MgPSAtMSwKICAgICAgc3RhcnRDaHVuayA9IDAsCiAgICAgIGN1cnJlbnRXaWR0aCA9IDA7CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBnbHlwaHMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICBjb25zdCBbc3RhcnQsIGVuZF0gPSBwb3NpdGlvbnNbaV07CiAgICAgIGNvbnN0IGdseXBoID0gZ2x5cGhzW2ldOwogICAgICBjb25zdCBnbHlwaFdpZHRoID0gZ2x5cGgud2lkdGggKiBzY2FsZTsKICAgICAgaWYgKGdseXBoLnVuaWNvZGUgPT09ICIgIikgewogICAgICAgIGlmIChjdXJyZW50V2lkdGggKyBnbHlwaFdpZHRoID4gd2lkdGgpIHsKICAgICAgICAgIGNodW5rcy5wdXNoKGxpbmUuc3Vic3RyaW5nKHN0YXJ0Q2h1bmssIHN0YXJ0KSk7CiAgICAgICAgICBzdGFydENodW5rID0gc3RhcnQ7CiAgICAgICAgICBjdXJyZW50V2lkdGggPSBnbHlwaFdpZHRoOwogICAgICAgICAgbGFzdFNwYWNlUG9zSW5TdHJpbmdTdGFydCA9IC0xOwogICAgICAgICAgbGFzdFNwYWNlUG9zID0gLTE7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGN1cnJlbnRXaWR0aCArPSBnbHlwaFdpZHRoOwogICAgICAgICAgbGFzdFNwYWNlUG9zSW5TdHJpbmdTdGFydCA9IHN0YXJ0OwogICAgICAgICAgbGFzdFNwYWNlUG9zSW5TdHJpbmdFbmQgPSBlbmQ7CiAgICAgICAgICBsYXN0U3BhY2VQb3MgPSBpOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChjdXJyZW50V2lkdGggKyBnbHlwaFdpZHRoID4gd2lkdGgpIHsKICAgICAgICBpZiAobGFzdFNwYWNlUG9zSW5TdHJpbmdTdGFydCAhPT0gLTEpIHsKICAgICAgICAgIGNodW5rcy5wdXNoKGxpbmUuc3Vic3RyaW5nKHN0YXJ0Q2h1bmssIGxhc3RTcGFjZVBvc0luU3RyaW5nRW5kKSk7CiAgICAgICAgICBzdGFydENodW5rID0gbGFzdFNwYWNlUG9zSW5TdHJpbmdFbmQ7CiAgICAgICAgICBpID0gbGFzdFNwYWNlUG9zICsgMTsKICAgICAgICAgIGxhc3RTcGFjZVBvc0luU3RyaW5nU3RhcnQgPSAtMTsKICAgICAgICAgIGN1cnJlbnRXaWR0aCA9IDA7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGNodW5rcy5wdXNoKGxpbmUuc3Vic3RyaW5nKHN0YXJ0Q2h1bmssIHN0YXJ0KSk7CiAgICAgICAgICBzdGFydENodW5rID0gc3RhcnQ7CiAgICAgICAgICBjdXJyZW50V2lkdGggPSBnbHlwaFdpZHRoOwogICAgICAgIH0KICAgICAgfSBlbHNlIHsKICAgICAgICBjdXJyZW50V2lkdGggKz0gZ2x5cGhXaWR0aDsKICAgICAgfQogICAgfQogICAgaWYgKHN0YXJ0Q2h1bmsgPCBsaW5lLmxlbmd0aCkgewogICAgICBjaHVua3MucHVzaChsaW5lLnN1YnN0cmluZyhzdGFydENodW5rLCBsaW5lLmxlbmd0aCkpOwogICAgfQogICAgcmV0dXJuIGNodW5rczsKICB9CiAgYXN5bmMgZXh0cmFjdFRleHRDb250ZW50KGV2YWx1YXRvciwgdGFzaywgdmlld0JveCkgewogICAgYXdhaXQgc3VwZXIuZXh0cmFjdFRleHRDb250ZW50KGV2YWx1YXRvciwgdGFzaywgdmlld0JveCk7CiAgICBjb25zdCB0ZXh0ID0gdGhpcy5kYXRhLnRleHRDb250ZW50OwogICAgaWYgKCF0ZXh0KSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGFsbFRleHQgPSB0ZXh0LmpvaW4oIlxuIik7CiAgICBpZiAoYWxsVGV4dCA9PT0gdGhpcy5kYXRhLmZpZWxkVmFsdWUpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgcmVnZXggPSBhbGxUZXh0LnJlcGxhY2VBbGwoLyhbLiorP14ke30oKXxbXF1cXF0pfChccyspL2csIChfbSwgcDEpID0+IHAxID8gYFxcJHtwMX1gIDogIlxccysiKTsKICAgIGlmIChuZXcgUmVnRXhwKGBeXFxzKiR7cmVnZXh9XFxzKiRgKS50ZXN0KHRoaXMuZGF0YS5maWVsZFZhbHVlKSkgewogICAgICB0aGlzLmRhdGEudGV4dENvbnRlbnQgPSB0aGlzLmRhdGEuZmllbGRWYWx1ZS5zcGxpdCgiXG4iKTsKICAgIH0KICB9CiAgZ2V0RmllbGRPYmplY3QoKSB7CiAgICByZXR1cm4gewogICAgICBpZDogdGhpcy5kYXRhLmlkLAogICAgICB2YWx1ZTogdGhpcy5kYXRhLmZpZWxkVmFsdWUsCiAgICAgIGRlZmF1bHRWYWx1ZTogdGhpcy5kYXRhLmRlZmF1bHRGaWVsZFZhbHVlIHx8ICIiLAogICAgICBtdWx0aWxpbmU6IHRoaXMuZGF0YS5tdWx0aUxpbmUsCiAgICAgIHBhc3N3b3JkOiB0aGlzLmRhdGEucGFzc3dvcmQsCiAgICAgIGNoYXJMaW1pdDogdGhpcy5kYXRhLm1heExlbiwKICAgICAgY29tYjogdGhpcy5kYXRhLmNvbWIsCiAgICAgIGVkaXRhYmxlOiAhdGhpcy5kYXRhLnJlYWRPbmx5LAogICAgICBoaWRkZW46IHRoaXMuZGF0YS5oaWRkZW4sCiAgICAgIG5hbWU6IHRoaXMuZGF0YS5maWVsZE5hbWUsCiAgICAgIHJlY3Q6IHRoaXMuZGF0YS5yZWN0LAogICAgICBhY3Rpb25zOiB0aGlzLmRhdGEuYWN0aW9ucywKICAgICAgcGFnZTogdGhpcy5kYXRhLnBhZ2VJbmRleCwKICAgICAgc3Ryb2tlQ29sb3I6IHRoaXMuZGF0YS5ib3JkZXJDb2xvciwKICAgICAgZmlsbENvbG9yOiB0aGlzLmRhdGEuYmFja2dyb3VuZENvbG9yLAogICAgICByb3RhdGlvbjogdGhpcy5yb3RhdGlvbiwKICAgICAgZGF0ZXRpbWVGb3JtYXQ6IHRoaXMuZGF0YS5kYXRldGltZUZvcm1hdCwKICAgICAgaGFzRGF0ZXRpbWVIVE1MOiAhIXRoaXMuZGF0YS5kYXRldGltZVR5cGUsCiAgICAgIHR5cGU6ICJ0ZXh0IgogICAgfTsKICB9Cn0KY2xhc3MgQnV0dG9uV2lkZ2V0QW5ub3RhdGlvbiBleHRlbmRzIFdpZGdldEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIHRoaXMuY2hlY2tlZEFwcGVhcmFuY2UgPSBudWxsOwogICAgdGhpcy51bmNoZWNrZWRBcHBlYXJhbmNlID0gbnVsbDsKICAgIGNvbnN0IGlzUmFkaW8gPSB0aGlzLmhhc0ZpZWxkRmxhZyhBbm5vdGF0aW9uRmllbGRGbGFnLlJBRElPKSwKICAgICAgaXNQdXNoQnV0dG9uID0gdGhpcy5oYXNGaWVsZEZsYWcoQW5ub3RhdGlvbkZpZWxkRmxhZy5QVVNIQlVUVE9OKTsKICAgIHRoaXMuZGF0YS5jaGVja0JveCA9ICFpc1JhZGlvICYmICFpc1B1c2hCdXR0b247CiAgICB0aGlzLmRhdGEucmFkaW9CdXR0b24gPSBpc1JhZGlvICYmICFpc1B1c2hCdXR0b247CiAgICB0aGlzLmRhdGEucHVzaEJ1dHRvbiA9IGlzUHVzaEJ1dHRvbjsKICAgIHRoaXMuZGF0YS5pc1Rvb2x0aXBPbmx5ID0gZmFsc2U7CiAgICBpZiAodGhpcy5kYXRhLmNoZWNrQm94KSB7CiAgICAgIHRoaXMuX3Byb2Nlc3NDaGVja0JveChwYXJhbXMpOwogICAgfSBlbHNlIGlmICh0aGlzLmRhdGEucmFkaW9CdXR0b24pIHsKICAgICAgdGhpcy5fcHJvY2Vzc1JhZGlvQnV0dG9uKHBhcmFtcyk7CiAgICB9IGVsc2UgaWYgKHRoaXMuZGF0YS5wdXNoQnV0dG9uKSB7CiAgICAgIHRoaXMuZGF0YS5oYXNPd25DYW52YXMgPSB0cnVlOwogICAgICB0aGlzLmRhdGEubm9IVE1MID0gZmFsc2U7CiAgICAgIHRoaXMuX3Byb2Nlc3NQdXNoQnV0dG9uKHBhcmFtcyk7CiAgICB9IGVsc2UgewogICAgICB3YXJuKCJJbnZhbGlkIGZpZWxkIGZsYWdzIGZvciBidXR0b24gd2lkZ2V0IGFubm90YXRpb24iKTsKICAgIH0KICB9CiAgYXN5bmMgZ2V0T3BlcmF0b3JMaXN0KGV2YWx1YXRvciwgdGFzaywgaW50ZW50LCBhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgaWYgKHRoaXMuZGF0YS5wdXNoQnV0dG9uKSB7CiAgICAgIHJldHVybiBzdXBlci5nZXRPcGVyYXRvckxpc3QoZXZhbHVhdG9yLCB0YXNrLCBpbnRlbnQsIGZhbHNlLCBhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICB9CiAgICBsZXQgdmFsdWUgPSBudWxsOwogICAgbGV0IHJvdGF0aW9uID0gbnVsbDsKICAgIGlmIChhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgICBjb25zdCBzdG9yYWdlRW50cnkgPSBhbm5vdGF0aW9uU3RvcmFnZS5nZXQodGhpcy5kYXRhLmlkKTsKICAgICAgdmFsdWUgPSBzdG9yYWdlRW50cnkgPyBzdG9yYWdlRW50cnkudmFsdWUgOiBudWxsOwogICAgICByb3RhdGlvbiA9IHN0b3JhZ2VFbnRyeSA/IHN0b3JhZ2VFbnRyeS5yb3RhdGlvbiA6IG51bGw7CiAgICB9CiAgICBpZiAodmFsdWUgPT09IG51bGwgJiYgdGhpcy5hcHBlYXJhbmNlKSB7CiAgICAgIHJldHVybiBzdXBlci5nZXRPcGVyYXRvckxpc3QoZXZhbHVhdG9yLCB0YXNrLCBpbnRlbnQsIGFubm90YXRpb25TdG9yYWdlKTsKICAgIH0KICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHZhbHVlID0gdGhpcy5kYXRhLmNoZWNrQm94ID8gdGhpcy5kYXRhLmZpZWxkVmFsdWUgPT09IHRoaXMuZGF0YS5leHBvcnRWYWx1ZSA6IHRoaXMuZGF0YS5maWVsZFZhbHVlID09PSB0aGlzLmRhdGEuYnV0dG9uVmFsdWU7CiAgICB9CiAgICBjb25zdCBhcHBlYXJhbmNlID0gdmFsdWUgPyB0aGlzLmNoZWNrZWRBcHBlYXJhbmNlIDogdGhpcy51bmNoZWNrZWRBcHBlYXJhbmNlOwogICAgaWYgKGFwcGVhcmFuY2UpIHsKICAgICAgY29uc3Qgc2F2ZWRBcHBlYXJhbmNlID0gdGhpcy5hcHBlYXJhbmNlOwogICAgICBjb25zdCBzYXZlZE1hdHJpeCA9IGxvb2t1cE1hdHJpeChhcHBlYXJhbmNlLmRpY3QuZ2V0QXJyYXkoIk1hdHJpeCIpLCBJREVOVElUWV9NQVRSSVgpOwogICAgICBpZiAocm90YXRpb24pIHsKICAgICAgICBhcHBlYXJhbmNlLmRpY3Quc2V0KCJNYXRyaXgiLCB0aGlzLmdldFJvdGF0aW9uTWF0cml4KGFubm90YXRpb25TdG9yYWdlKSk7CiAgICAgIH0KICAgICAgdGhpcy5hcHBlYXJhbmNlID0gYXBwZWFyYW5jZTsKICAgICAgY29uc3Qgb3BlcmF0b3JMaXN0ID0gc3VwZXIuZ2V0T3BlcmF0b3JMaXN0KGV2YWx1YXRvciwgdGFzaywgaW50ZW50LCBhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICAgIHRoaXMuYXBwZWFyYW5jZSA9IHNhdmVkQXBwZWFyYW5jZTsKICAgICAgYXBwZWFyYW5jZS5kaWN0LnNldCgiTWF0cml4Iiwgc2F2ZWRNYXRyaXgpOwogICAgICByZXR1cm4gb3BlcmF0b3JMaXN0OwogICAgfQogICAgcmV0dXJuIHsKICAgICAgb3BMaXN0OiBuZXcgT3BlcmF0b3JMaXN0KCksCiAgICAgIHNlcGFyYXRlRm9ybTogZmFsc2UsCiAgICAgIHNlcGFyYXRlQ2FudmFzOiBmYWxzZQogICAgfTsKICB9CiAgYXN5bmMgc2F2ZShldmFsdWF0b3IsIHRhc2ssIGFubm90YXRpb25TdG9yYWdlLCBjaGFuZ2VzKSB7CiAgICBpZiAodGhpcy5kYXRhLmNoZWNrQm94KSB7CiAgICAgIHRoaXMuX3NhdmVDaGVja2JveChldmFsdWF0b3IsIHRhc2ssIGFubm90YXRpb25TdG9yYWdlLCBjaGFuZ2VzKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgaWYgKHRoaXMuZGF0YS5yYWRpb0J1dHRvbikgewogICAgICB0aGlzLl9zYXZlUmFkaW9CdXR0b24oZXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9uU3RvcmFnZSwgY2hhbmdlcyk7CiAgICB9CiAgfQogIGFzeW5jIF9zYXZlQ2hlY2tib3goZXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9uU3RvcmFnZSwgY2hhbmdlcykgewogICAgaWYgKCFhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBzdG9yYWdlRW50cnkgPSBhbm5vdGF0aW9uU3RvcmFnZS5nZXQodGhpcy5kYXRhLmlkKTsKICAgIGNvbnN0IGZsYWdzID0gdGhpcy5fYnVpbGRGbGFncyhzdG9yYWdlRW50cnk/Lm5vVmlldywgc3RvcmFnZUVudHJ5Py5ub1ByaW50KTsKICAgIGxldCByb3RhdGlvbiA9IHN0b3JhZ2VFbnRyeT8ucm90YXRpb24sCiAgICAgIHZhbHVlID0gc3RvcmFnZUVudHJ5Py52YWx1ZTsKICAgIGlmIChyb3RhdGlvbiA9PT0gdW5kZWZpbmVkICYmIGZsYWdzID09PSB1bmRlZmluZWQpIHsKICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgY29uc3QgZGVmYXVsdFZhbHVlID0gdGhpcy5kYXRhLmZpZWxkVmFsdWUgPT09IHRoaXMuZGF0YS5leHBvcnRWYWx1ZTsKICAgICAgaWYgKGRlZmF1bHRWYWx1ZSA9PT0gdmFsdWUpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgIH0KICAgIGxldCBkaWN0ID0gZXZhbHVhdG9yLnhyZWYuZmV0Y2hJZlJlZih0aGlzLnJlZik7CiAgICBpZiAoIShkaWN0IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgZGljdCA9IGRpY3QuY2xvbmUoKTsKICAgIGlmIChyb3RhdGlvbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJvdGF0aW9uID0gdGhpcy5yb3RhdGlvbjsKICAgIH0KICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHZhbHVlID0gdGhpcy5kYXRhLmZpZWxkVmFsdWUgPT09IHRoaXMuZGF0YS5leHBvcnRWYWx1ZTsKICAgIH0KICAgIGNvbnN0IHhmYSA9IHsKICAgICAgcGF0aDogdGhpcy5kYXRhLmZpZWxkTmFtZSwKICAgICAgdmFsdWU6IHZhbHVlID8gdGhpcy5kYXRhLmV4cG9ydFZhbHVlIDogIiIKICAgIH07CiAgICBjb25zdCBuYW1lID0gTmFtZS5nZXQodmFsdWUgPyB0aGlzLmRhdGEuZXhwb3J0VmFsdWUgOiAiT2ZmIik7CiAgICB0aGlzLnNldFZhbHVlKGRpY3QsIG5hbWUsIGV2YWx1YXRvci54cmVmLCBjaGFuZ2VzKTsKICAgIGRpY3Quc2V0KCJBUyIsIG5hbWUpOwogICAgZGljdC5zZXQoIk0iLCBgRDoke2dldE1vZGlmaWNhdGlvbkRhdGUoKX1gKTsKICAgIGlmIChmbGFncyAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIGRpY3Quc2V0KCJGIiwgZmxhZ3MpOwogICAgfQogICAgY29uc3QgbWF5YmVNSyA9IHRoaXMuX2dldE1LRGljdChyb3RhdGlvbik7CiAgICBpZiAobWF5YmVNSykgewogICAgICBkaWN0LnNldCgiTUsiLCBtYXliZU1LKTsKICAgIH0KICAgIGNoYW5nZXMucHV0KHRoaXMucmVmLCB7CiAgICAgIGRhdGE6IGRpY3QsCiAgICAgIHhmYSwKICAgICAgbmVlZEFwcGVhcmFuY2VzOiBmYWxzZQogICAgfSk7CiAgfQogIGFzeW5jIF9zYXZlUmFkaW9CdXR0b24oZXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9uU3RvcmFnZSwgY2hhbmdlcykgewogICAgaWYgKCFhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBzdG9yYWdlRW50cnkgPSBhbm5vdGF0aW9uU3RvcmFnZS5nZXQodGhpcy5kYXRhLmlkKTsKICAgIGNvbnN0IGZsYWdzID0gdGhpcy5fYnVpbGRGbGFncyhzdG9yYWdlRW50cnk/Lm5vVmlldywgc3RvcmFnZUVudHJ5Py5ub1ByaW50KTsKICAgIGxldCByb3RhdGlvbiA9IHN0b3JhZ2VFbnRyeT8ucm90YXRpb24sCiAgICAgIHZhbHVlID0gc3RvcmFnZUVudHJ5Py52YWx1ZTsKICAgIGlmIChyb3RhdGlvbiA9PT0gdW5kZWZpbmVkICYmIGZsYWdzID09PSB1bmRlZmluZWQpIHsKICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgY29uc3QgZGVmYXVsdFZhbHVlID0gdGhpcy5kYXRhLmZpZWxkVmFsdWUgPT09IHRoaXMuZGF0YS5idXR0b25WYWx1ZTsKICAgICAgaWYgKGRlZmF1bHRWYWx1ZSA9PT0gdmFsdWUpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgIH0KICAgIGxldCBkaWN0ID0gZXZhbHVhdG9yLnhyZWYuZmV0Y2hJZlJlZih0aGlzLnJlZik7CiAgICBpZiAoIShkaWN0IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgZGljdCA9IGRpY3QuY2xvbmUoKTsKICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHZhbHVlID0gdGhpcy5kYXRhLmZpZWxkVmFsdWUgPT09IHRoaXMuZGF0YS5idXR0b25WYWx1ZTsKICAgIH0KICAgIGlmIChyb3RhdGlvbiA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHJvdGF0aW9uID0gdGhpcy5yb3RhdGlvbjsKICAgIH0KICAgIGNvbnN0IHhmYSA9IHsKICAgICAgcGF0aDogdGhpcy5kYXRhLmZpZWxkTmFtZSwKICAgICAgdmFsdWU6IHZhbHVlID8gdGhpcy5kYXRhLmJ1dHRvblZhbHVlIDogIiIKICAgIH07CiAgICBjb25zdCBuYW1lID0gTmFtZS5nZXQodmFsdWUgPyB0aGlzLmRhdGEuYnV0dG9uVmFsdWUgOiAiT2ZmIik7CiAgICBpZiAodmFsdWUpIHsKICAgICAgdGhpcy5zZXRWYWx1ZShkaWN0LCBuYW1lLCBldmFsdWF0b3IueHJlZiwgY2hhbmdlcyk7CiAgICB9CiAgICBkaWN0LnNldCgiQVMiLCBuYW1lKTsKICAgIGRpY3Quc2V0KCJNIiwgYEQ6JHtnZXRNb2RpZmljYXRpb25EYXRlKCl9YCk7CiAgICBpZiAoZmxhZ3MgIT09IHVuZGVmaW5lZCkgewogICAgICBkaWN0LnNldCgiRiIsIGZsYWdzKTsKICAgIH0KICAgIGNvbnN0IG1heWJlTUsgPSB0aGlzLl9nZXRNS0RpY3Qocm90YXRpb24pOwogICAgaWYgKG1heWJlTUspIHsKICAgICAgZGljdC5zZXQoIk1LIiwgbWF5YmVNSyk7CiAgICB9CiAgICBjaGFuZ2VzLnB1dCh0aGlzLnJlZiwgewogICAgICBkYXRhOiBkaWN0LAogICAgICB4ZmEsCiAgICAgIG5lZWRBcHBlYXJhbmNlczogZmFsc2UKICAgIH0pOwogIH0KICBfZ2V0RGVmYXVsdENoZWNrZWRBcHBlYXJhbmNlKHBhcmFtcywgdHlwZSkgewogICAgY29uc3QgewogICAgICB3aWR0aCwKICAgICAgaGVpZ2h0CiAgICB9ID0gdGhpczsKICAgIGNvbnN0IGJib3ggPSBbMCwgMCwgd2lkdGgsIGhlaWdodF07CiAgICBjb25zdCBGT05UX1JBVElPID0gMC44OwogICAgY29uc3QgZm9udFNpemUgPSBNYXRoLm1pbih3aWR0aCwgaGVpZ2h0KSAqIEZPTlRfUkFUSU87CiAgICBsZXQgbWV0cmljcywgY2hhcjsKICAgIGlmICh0eXBlID09PSAiY2hlY2siKSB7CiAgICAgIG1ldHJpY3MgPSB7CiAgICAgICAgd2lkdGg6IDAuNzU1ICogZm9udFNpemUsCiAgICAgICAgaGVpZ2h0OiAwLjcwNSAqIGZvbnRTaXplCiAgICAgIH07CiAgICAgIGNoYXIgPSAiXHgzMyI7CiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICJkaXNjIikgewogICAgICBtZXRyaWNzID0gewogICAgICAgIHdpZHRoOiAwLjc5MSAqIGZvbnRTaXplLAogICAgICAgIGhlaWdodDogMC43MDUgKiBmb250U2l6ZQogICAgICB9OwogICAgICBjaGFyID0gIlx4NkMiOwogICAgfSBlbHNlIHsKICAgICAgdW5yZWFjaGFibGUoYF9nZXREZWZhdWx0Q2hlY2tlZEFwcGVhcmFuY2UgLSB1bnN1cHBvcnRlZCB0eXBlOiAke3R5cGV9YCk7CiAgICB9CiAgICBjb25zdCB4U2hpZnQgPSBudW1iZXJUb1N0cmluZygod2lkdGggLSBtZXRyaWNzLndpZHRoKSAvIDIpOwogICAgY29uc3QgeVNoaWZ0ID0gbnVtYmVyVG9TdHJpbmcoKGhlaWdodCAtIG1ldHJpY3MuaGVpZ2h0KSAvIDIpOwogICAgY29uc3QgYXBwZWFyYW5jZSA9IGBxIEJUIC9QZGZKc1phRGIgJHtmb250U2l6ZX0gVGYgMCBnICR7eFNoaWZ0fSAke3lTaGlmdH0gVGQgKCR7Y2hhcn0pIFRqIEVUIFFgOwogICAgY29uc3QgYXBwZWFyYW5jZVN0cmVhbURpY3QgPSBuZXcgRGljdChwYXJhbXMueHJlZik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkZvcm1UeXBlIiwgMSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXRJZk5hbWUoIlN1YnR5cGUiLCAiRm9ybSIpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0SWZOYW1lKCJUeXBlIiwgIlhPYmplY3QiKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiQkJveCIsIGJib3gpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJNYXRyaXgiLCBbMSwgMCwgMCwgMSwgMCwgMF0pOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJMZW5ndGgiLCBhcHBlYXJhbmNlLmxlbmd0aCk7CiAgICBjb25zdCByZXNvdXJjZXMgPSBuZXcgRGljdChwYXJhbXMueHJlZik7CiAgICBjb25zdCBmb250ID0gbmV3IERpY3QocGFyYW1zLnhyZWYpOwogICAgZm9udC5zZXQoIlBkZkpzWmFEYiIsIHRoaXMuZmFsbGJhY2tGb250RGljdCk7CiAgICByZXNvdXJjZXMuc2V0KCJGb250IiwgZm9udCk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIlJlc291cmNlcyIsIHJlc291cmNlcyk7CiAgICB0aGlzLmNoZWNrZWRBcHBlYXJhbmNlID0gbmV3IFN0cmluZ1N0cmVhbShhcHBlYXJhbmNlKTsKICAgIHRoaXMuY2hlY2tlZEFwcGVhcmFuY2UuZGljdCA9IGFwcGVhcmFuY2VTdHJlYW1EaWN0OwogICAgdGhpcy5fc3RyZWFtcy5wdXNoKHRoaXMuY2hlY2tlZEFwcGVhcmFuY2UpOwogIH0KICBfcHJvY2Vzc0NoZWNrQm94KHBhcmFtcykgewogICAgY29uc3QgY3VzdG9tQXBwZWFyYW5jZSA9IHBhcmFtcy5kaWN0LmdldCgiQVAiKTsKICAgIGlmICghKGN1c3RvbUFwcGVhcmFuY2UgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBub3JtYWxBcHBlYXJhbmNlID0gY3VzdG9tQXBwZWFyYW5jZS5nZXQoIk4iKTsKICAgIGlmICghKG5vcm1hbEFwcGVhcmFuY2UgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBhc1ZhbHVlID0gdGhpcy5fZGVjb2RlRm9ybVZhbHVlKHBhcmFtcy5kaWN0LmdldCgiQVMiKSk7CiAgICBpZiAodHlwZW9mIGFzVmFsdWUgPT09ICJzdHJpbmciKSB7CiAgICAgIHRoaXMuZGF0YS5maWVsZFZhbHVlID0gYXNWYWx1ZTsKICAgIH0KICAgIGNvbnN0IHllcyA9IHRoaXMuZGF0YS5maWVsZFZhbHVlICE9PSBudWxsICYmIHRoaXMuZGF0YS5maWVsZFZhbHVlICE9PSAiT2ZmIiA/IHRoaXMuZGF0YS5maWVsZFZhbHVlIDogIlllcyI7CiAgICBjb25zdCBleHBvcnRWYWx1ZXMgPSB0aGlzLl9kZWNvZGVGb3JtVmFsdWUobm9ybWFsQXBwZWFyYW5jZS5nZXRLZXlzKCkpOwogICAgaWYgKGV4cG9ydFZhbHVlcy5sZW5ndGggPT09IDApIHsKICAgICAgZXhwb3J0VmFsdWVzLnB1c2goIk9mZiIsIHllcyk7CiAgICB9IGVsc2UgaWYgKGV4cG9ydFZhbHVlcy5sZW5ndGggPT09IDEpIHsKICAgICAgaWYgKGV4cG9ydFZhbHVlc1swXSA9PT0gIk9mZiIpIHsKICAgICAgICBleHBvcnRWYWx1ZXMucHVzaCh5ZXMpOwogICAgICB9IGVsc2UgewogICAgICAgIGV4cG9ydFZhbHVlcy51bnNoaWZ0KCJPZmYiKTsKICAgICAgfQogICAgfSBlbHNlIGlmIChleHBvcnRWYWx1ZXMuaW5jbHVkZXMoeWVzKSkgewogICAgICBleHBvcnRWYWx1ZXMubGVuZ3RoID0gMDsKICAgICAgZXhwb3J0VmFsdWVzLnB1c2goIk9mZiIsIHllcyk7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBvdGhlclllcyA9IGV4cG9ydFZhbHVlcy5maW5kKHYgPT4gdiAhPT0gIk9mZiIpOwogICAgICBleHBvcnRWYWx1ZXMubGVuZ3RoID0gMDsKICAgICAgZXhwb3J0VmFsdWVzLnB1c2goIk9mZiIsIG90aGVyWWVzKTsKICAgIH0KICAgIGlmICghZXhwb3J0VmFsdWVzLmluY2x1ZGVzKHRoaXMuZGF0YS5maWVsZFZhbHVlKSkgewogICAgICB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9ICJPZmYiOwogICAgfQogICAgdGhpcy5kYXRhLmV4cG9ydFZhbHVlID0gZXhwb3J0VmFsdWVzWzFdOwogICAgY29uc3QgY2hlY2tlZEFwcGVhcmFuY2UgPSBub3JtYWxBcHBlYXJhbmNlLmdldCh0aGlzLmRhdGEuZXhwb3J0VmFsdWUpOwogICAgdGhpcy5jaGVja2VkQXBwZWFyYW5jZSA9IGNoZWNrZWRBcHBlYXJhbmNlIGluc3RhbmNlb2YgQmFzZVN0cmVhbSA/IGNoZWNrZWRBcHBlYXJhbmNlIDogbnVsbDsKICAgIGNvbnN0IHVuY2hlY2tlZEFwcGVhcmFuY2UgPSBub3JtYWxBcHBlYXJhbmNlLmdldCgiT2ZmIik7CiAgICB0aGlzLnVuY2hlY2tlZEFwcGVhcmFuY2UgPSB1bmNoZWNrZWRBcHBlYXJhbmNlIGluc3RhbmNlb2YgQmFzZVN0cmVhbSA/IHVuY2hlY2tlZEFwcGVhcmFuY2UgOiBudWxsOwogICAgaWYgKHRoaXMuY2hlY2tlZEFwcGVhcmFuY2UpIHsKICAgICAgdGhpcy5fc3RyZWFtcy5wdXNoKHRoaXMuY2hlY2tlZEFwcGVhcmFuY2UpOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5fZ2V0RGVmYXVsdENoZWNrZWRBcHBlYXJhbmNlKHBhcmFtcywgImNoZWNrIik7CiAgICB9CiAgICBpZiAodGhpcy51bmNoZWNrZWRBcHBlYXJhbmNlKSB7CiAgICAgIHRoaXMuX3N0cmVhbXMucHVzaCh0aGlzLnVuY2hlY2tlZEFwcGVhcmFuY2UpOwogICAgfQogICAgdGhpcy5fZmFsbGJhY2tGb250RGljdCA9IHRoaXMuZmFsbGJhY2tGb250RGljdDsKICAgIGlmICh0aGlzLmRhdGEuZGVmYXVsdEZpZWxkVmFsdWUgPT09IG51bGwpIHsKICAgICAgdGhpcy5kYXRhLmRlZmF1bHRGaWVsZFZhbHVlID0gIk9mZiI7CiAgICB9CiAgfQogIF9wcm9jZXNzUmFkaW9CdXR0b24ocGFyYW1zKSB7CiAgICB0aGlzLmRhdGEuYnV0dG9uVmFsdWUgPSBudWxsOwogICAgY29uc3QgZmllbGRQYXJlbnQgPSBwYXJhbXMuZGljdC5nZXQoIlBhcmVudCIpOwogICAgaWYgKGZpZWxkUGFyZW50IGluc3RhbmNlb2YgRGljdCkgewogICAgICB0aGlzLnBhcmVudCA9IHBhcmFtcy5kaWN0LmdldFJhdygiUGFyZW50Iik7CiAgICAgIGNvbnN0IGZpZWxkUGFyZW50VmFsdWUgPSBmaWVsZFBhcmVudC5nZXQoIlYiKTsKICAgICAgaWYgKGZpZWxkUGFyZW50VmFsdWUgaW5zdGFuY2VvZiBOYW1lKSB7CiAgICAgICAgdGhpcy5kYXRhLmZpZWxkVmFsdWUgPSB0aGlzLl9kZWNvZGVGb3JtVmFsdWUoZmllbGRQYXJlbnRWYWx1ZSk7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IGFwcGVhcmFuY2VTdGF0ZXMgPSBwYXJhbXMuZGljdC5nZXQoIkFQIik7CiAgICBpZiAoIShhcHBlYXJhbmNlU3RhdGVzIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3Qgbm9ybWFsQXBwZWFyYW5jZSA9IGFwcGVhcmFuY2VTdGF0ZXMuZ2V0KCJOIik7CiAgICBpZiAoIShub3JtYWxBcHBlYXJhbmNlIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgZm9yIChjb25zdCBrZXkgb2Ygbm9ybWFsQXBwZWFyYW5jZS5nZXRLZXlzKCkpIHsKICAgICAgaWYgKGtleSAhPT0gIk9mZiIpIHsKICAgICAgICB0aGlzLmRhdGEuYnV0dG9uVmFsdWUgPSB0aGlzLl9kZWNvZGVGb3JtVmFsdWUoa2V5KTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgY29uc3QgY2hlY2tlZEFwcGVhcmFuY2UgPSBub3JtYWxBcHBlYXJhbmNlLmdldCh0aGlzLmRhdGEuYnV0dG9uVmFsdWUpOwogICAgdGhpcy5jaGVja2VkQXBwZWFyYW5jZSA9IGNoZWNrZWRBcHBlYXJhbmNlIGluc3RhbmNlb2YgQmFzZVN0cmVhbSA/IGNoZWNrZWRBcHBlYXJhbmNlIDogbnVsbDsKICAgIGNvbnN0IHVuY2hlY2tlZEFwcGVhcmFuY2UgPSBub3JtYWxBcHBlYXJhbmNlLmdldCgiT2ZmIik7CiAgICB0aGlzLnVuY2hlY2tlZEFwcGVhcmFuY2UgPSB1bmNoZWNrZWRBcHBlYXJhbmNlIGluc3RhbmNlb2YgQmFzZVN0cmVhbSA/IHVuY2hlY2tlZEFwcGVhcmFuY2UgOiBudWxsOwogICAgaWYgKHRoaXMuY2hlY2tlZEFwcGVhcmFuY2UpIHsKICAgICAgdGhpcy5fc3RyZWFtcy5wdXNoKHRoaXMuY2hlY2tlZEFwcGVhcmFuY2UpOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5fZ2V0RGVmYXVsdENoZWNrZWRBcHBlYXJhbmNlKHBhcmFtcywgImRpc2MiKTsKICAgIH0KICAgIGlmICh0aGlzLnVuY2hlY2tlZEFwcGVhcmFuY2UpIHsKICAgICAgdGhpcy5fc3RyZWFtcy5wdXNoKHRoaXMudW5jaGVja2VkQXBwZWFyYW5jZSk7CiAgICB9CiAgICB0aGlzLl9mYWxsYmFja0ZvbnREaWN0ID0gdGhpcy5mYWxsYmFja0ZvbnREaWN0OwogICAgaWYgKHRoaXMuZGF0YS5kZWZhdWx0RmllbGRWYWx1ZSA9PT0gbnVsbCkgewogICAgICB0aGlzLmRhdGEuZGVmYXVsdEZpZWxkVmFsdWUgPSAiT2ZmIjsKICAgIH0KICB9CiAgX3Byb2Nlc3NQdXNoQnV0dG9uKHBhcmFtcykgewogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICBhbm5vdGF0aW9uR2xvYmFscwogICAgfSA9IHBhcmFtczsKICAgIGlmICghZGljdC5oYXMoIkEiKSAmJiAhZGljdC5oYXMoIkFBIikgJiYgIXRoaXMuZGF0YS5hbHRlcm5hdGl2ZVRleHQpIHsKICAgICAgd2FybigiUHVzaCBidXR0b25zIHdpdGhvdXQgYWN0aW9uIGRpY3Rpb25hcmllcyBhcmUgbm90IHN1cHBvcnRlZCIpOwogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLmRhdGEuaXNUb29sdGlwT25seSA9ICFkaWN0LmhhcygiQSIpICYmICFkaWN0LmhhcygiQUEiKTsKICAgIENhdGFsb2cucGFyc2VEZXN0RGljdGlvbmFyeSh7CiAgICAgIGRlc3REaWN0OiBkaWN0LAogICAgICByZXN1bHRPYmo6IHRoaXMuZGF0YSwKICAgICAgZG9jQmFzZVVybDogYW5ub3RhdGlvbkdsb2JhbHMuYmFzZVVybCwKICAgICAgZG9jQXR0YWNobWVudHM6IGFubm90YXRpb25HbG9iYWxzLmF0dGFjaG1lbnRzCiAgICB9KTsKICB9CiAgZ2V0RmllbGRPYmplY3QoKSB7CiAgICBsZXQgdHlwZSA9ICJidXR0b24iOwogICAgbGV0IGV4cG9ydFZhbHVlczsKICAgIGlmICh0aGlzLmRhdGEuY2hlY2tCb3gpIHsKICAgICAgdHlwZSA9ICJjaGVja2JveCI7CiAgICAgIGV4cG9ydFZhbHVlcyA9IHRoaXMuZGF0YS5leHBvcnRWYWx1ZTsKICAgIH0gZWxzZSBpZiAodGhpcy5kYXRhLnJhZGlvQnV0dG9uKSB7CiAgICAgIHR5cGUgPSAicmFkaW9idXR0b24iOwogICAgICBleHBvcnRWYWx1ZXMgPSB0aGlzLmRhdGEuYnV0dG9uVmFsdWU7CiAgICB9CiAgICByZXR1cm4gewogICAgICBpZDogdGhpcy5kYXRhLmlkLAogICAgICB2YWx1ZTogdGhpcy5kYXRhLmZpZWxkVmFsdWUgfHwgIk9mZiIsCiAgICAgIGRlZmF1bHRWYWx1ZTogdGhpcy5kYXRhLmRlZmF1bHRGaWVsZFZhbHVlLAogICAgICBleHBvcnRWYWx1ZXMsCiAgICAgIGVkaXRhYmxlOiAhdGhpcy5kYXRhLnJlYWRPbmx5LAogICAgICBuYW1lOiB0aGlzLmRhdGEuZmllbGROYW1lLAogICAgICByZWN0OiB0aGlzLmRhdGEucmVjdCwKICAgICAgaGlkZGVuOiB0aGlzLmRhdGEuaGlkZGVuLAogICAgICBhY3Rpb25zOiB0aGlzLmRhdGEuYWN0aW9ucywKICAgICAgcGFnZTogdGhpcy5kYXRhLnBhZ2VJbmRleCwKICAgICAgc3Ryb2tlQ29sb3I6IHRoaXMuZGF0YS5ib3JkZXJDb2xvciwKICAgICAgZmlsbENvbG9yOiB0aGlzLmRhdGEuYmFja2dyb3VuZENvbG9yLAogICAgICByb3RhdGlvbjogdGhpcy5yb3RhdGlvbiwKICAgICAgdHlwZQogICAgfTsKICB9CiAgZ2V0IGZhbGxiYWNrRm9udERpY3QoKSB7CiAgICBjb25zdCBkaWN0ID0gbmV3IERpY3QoKTsKICAgIGRpY3Quc2V0SWZOYW1lKCJCYXNlRm9udCIsICJaYXBmRGluZ2JhdHMiKTsKICAgIGRpY3Quc2V0SWZOYW1lKCJUeXBlIiwgIkZhbGxiYWNrVHlwZSIpOwogICAgZGljdC5zZXRJZk5hbWUoIlN1YnR5cGUiLCAiRmFsbGJhY2tUeXBlIik7CiAgICBkaWN0LnNldElmTmFtZSgiRW5jb2RpbmciLCAiWmFwZkRpbmdiYXRzRW5jb2RpbmciKTsKICAgIHJldHVybiBzaGFkb3codGhpcywgImZhbGxiYWNrRm9udERpY3QiLCBkaWN0KTsKICB9Cn0KY2xhc3MgQ2hvaWNlV2lkZ2V0QW5ub3RhdGlvbiBleHRlbmRzIFdpZGdldEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIGNvbnN0IHsKICAgICAgZGljdCwKICAgICAgeHJlZgogICAgfSA9IHBhcmFtczsKICAgIHRoaXMuaW5kaWNlcyA9IGRpY3QuZ2V0QXJyYXkoIkkiKTsKICAgIHRoaXMuaGFzSW5kaWNlcyA9IEFycmF5LmlzQXJyYXkodGhpcy5pbmRpY2VzKSAmJiB0aGlzLmluZGljZXMubGVuZ3RoID4gMDsKICAgIHRoaXMuZGF0YS5vcHRpb25zID0gW107CiAgICBjb25zdCBvcHRpb25zID0gZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7CiAgICAgIGRpY3QsCiAgICAgIGtleTogIk9wdCIKICAgIH0pOwogICAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucykpIHsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gb3B0aW9ucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgY29uc3Qgb3B0aW9uID0geHJlZi5mZXRjaElmUmVmKG9wdGlvbnNbaV0pOwogICAgICAgIGNvbnN0IGlzT3B0aW9uQXJyYXkgPSBBcnJheS5pc0FycmF5KG9wdGlvbik7CiAgICAgICAgdGhpcy5kYXRhLm9wdGlvbnNbaV0gPSB7CiAgICAgICAgICBleHBvcnRWYWx1ZTogdGhpcy5fZGVjb2RlRm9ybVZhbHVlKGlzT3B0aW9uQXJyYXkgPyB4cmVmLmZldGNoSWZSZWYob3B0aW9uWzBdKSA6IG9wdGlvbiksCiAgICAgICAgICBkaXNwbGF5VmFsdWU6IHRoaXMuX2RlY29kZUZvcm1WYWx1ZShpc09wdGlvbkFycmF5ID8geHJlZi5mZXRjaElmUmVmKG9wdGlvblsxXSkgOiBvcHRpb24pCiAgICAgICAgfTsKICAgICAgfQogICAgfQogICAgaWYgKCF0aGlzLmhhc0luZGljZXMpIHsKICAgICAgaWYgKHR5cGVvZiB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9PT0gInN0cmluZyIpIHsKICAgICAgICB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9IFt0aGlzLmRhdGEuZmllbGRWYWx1ZV07CiAgICAgIH0gZWxzZSB7CiAgICAgICAgdGhpcy5kYXRhLmZpZWxkVmFsdWUgfHw9IFtdOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzLmRhdGEuZmllbGRWYWx1ZSA9IFtdOwogICAgICBjb25zdCBpaSA9IHRoaXMuZGF0YS5vcHRpb25zLmxlbmd0aDsKICAgICAgZm9yIChjb25zdCBpIG9mIHRoaXMuaW5kaWNlcykgewogICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKGkpICYmIGkgPj0gMCAmJiBpIDwgaWkpIHsKICAgICAgICAgIHRoaXMuZGF0YS5maWVsZFZhbHVlLnB1c2godGhpcy5kYXRhLm9wdGlvbnNbaV0uZXhwb3J0VmFsdWUpOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKHRoaXMuZGF0YS5vcHRpb25zLmxlbmd0aCA9PT0gMCAmJiB0aGlzLmRhdGEuZmllbGRWYWx1ZS5sZW5ndGggPiAwKSB7CiAgICAgIHRoaXMuZGF0YS5vcHRpb25zID0gdGhpcy5kYXRhLmZpZWxkVmFsdWUubWFwKHZhbHVlID0+ICh7CiAgICAgICAgZXhwb3J0VmFsdWU6IHZhbHVlLAogICAgICAgIGRpc3BsYXlWYWx1ZTogdmFsdWUKICAgICAgfSkpOwogICAgfQogICAgdGhpcy5kYXRhLmNvbWJvID0gdGhpcy5oYXNGaWVsZEZsYWcoQW5ub3RhdGlvbkZpZWxkRmxhZy5DT01CTyk7CiAgICB0aGlzLmRhdGEubXVsdGlTZWxlY3QgPSB0aGlzLmhhc0ZpZWxkRmxhZyhBbm5vdGF0aW9uRmllbGRGbGFnLk1VTFRJU0VMRUNUKTsKICAgIHRoaXMuX2hhc1RleHQgPSB0cnVlOwogIH0KICBnZXRGaWVsZE9iamVjdCgpIHsKICAgIGNvbnN0IHR5cGUgPSB0aGlzLmRhdGEuY29tYm8gPyAiY29tYm9ib3giIDogImxpc3Rib3giOwogICAgY29uc3QgdmFsdWUgPSB0aGlzLmRhdGEuZmllbGRWYWx1ZS5sZW5ndGggPiAwID8gdGhpcy5kYXRhLmZpZWxkVmFsdWVbMF0gOiBudWxsOwogICAgcmV0dXJuIHsKICAgICAgaWQ6IHRoaXMuZGF0YS5pZCwKICAgICAgdmFsdWUsCiAgICAgIGRlZmF1bHRWYWx1ZTogdGhpcy5kYXRhLmRlZmF1bHRGaWVsZFZhbHVlLAogICAgICBlZGl0YWJsZTogIXRoaXMuZGF0YS5yZWFkT25seSwKICAgICAgbmFtZTogdGhpcy5kYXRhLmZpZWxkTmFtZSwKICAgICAgcmVjdDogdGhpcy5kYXRhLnJlY3QsCiAgICAgIG51bUl0ZW1zOiB0aGlzLmRhdGEuZmllbGRWYWx1ZS5sZW5ndGgsCiAgICAgIG11bHRpcGxlU2VsZWN0aW9uOiB0aGlzLmRhdGEubXVsdGlTZWxlY3QsCiAgICAgIGhpZGRlbjogdGhpcy5kYXRhLmhpZGRlbiwKICAgICAgYWN0aW9uczogdGhpcy5kYXRhLmFjdGlvbnMsCiAgICAgIGl0ZW1zOiB0aGlzLmRhdGEub3B0aW9ucywKICAgICAgcGFnZTogdGhpcy5kYXRhLnBhZ2VJbmRleCwKICAgICAgc3Ryb2tlQ29sb3I6IHRoaXMuZGF0YS5ib3JkZXJDb2xvciwKICAgICAgZmlsbENvbG9yOiB0aGlzLmRhdGEuYmFja2dyb3VuZENvbG9yLAogICAgICByb3RhdGlvbjogdGhpcy5yb3RhdGlvbiwKICAgICAgdHlwZQogICAgfTsKICB9CiAgYW1lbmRTYXZlZERpY3QoYW5ub3RhdGlvblN0b3JhZ2UsIGRpY3QpIHsKICAgIGlmICghdGhpcy5oYXNJbmRpY2VzKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGxldCB2YWx1ZXMgPSBhbm5vdGF0aW9uU3RvcmFnZT8uZ2V0KHRoaXMuZGF0YS5pZCk/LnZhbHVlOwogICAgaWYgKCFBcnJheS5pc0FycmF5KHZhbHVlcykpIHsKICAgICAgdmFsdWVzID0gW3ZhbHVlc107CiAgICB9CiAgICBjb25zdCBpbmRpY2VzID0gW107CiAgICBjb25zdCB7CiAgICAgIG9wdGlvbnMKICAgIH0gPSB0aGlzLmRhdGE7CiAgICBmb3IgKGxldCBpID0gMCwgaiA9IDAsIGlpID0gb3B0aW9ucy5sZW5ndGg7IGkgPCBpaTsgaSsrKSB7CiAgICAgIGlmIChvcHRpb25zW2ldLmV4cG9ydFZhbHVlID09PSB2YWx1ZXNbal0pIHsKICAgICAgICBpbmRpY2VzLnB1c2goaSk7CiAgICAgICAgaiArPSAxOwogICAgICB9CiAgICB9CiAgICBkaWN0LnNldCgiSSIsIGluZGljZXMpOwogIH0KICBhc3luYyBfZ2V0QXBwZWFyYW5jZShldmFsdWF0b3IsIHRhc2ssIGludGVudCwgYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgIGlmICh0aGlzLmRhdGEuY29tYm8pIHsKICAgICAgcmV0dXJuIHN1cGVyLl9nZXRBcHBlYXJhbmNlKGV2YWx1YXRvciwgdGFzaywgaW50ZW50LCBhbm5vdGF0aW9uU3RvcmFnZSk7CiAgICB9CiAgICBsZXQgZXhwb3J0ZWRWYWx1ZSwgcm90YXRpb247CiAgICBjb25zdCBzdG9yYWdlRW50cnkgPSBhbm5vdGF0aW9uU3RvcmFnZT8uZ2V0KHRoaXMuZGF0YS5pZCk7CiAgICBpZiAoc3RvcmFnZUVudHJ5KSB7CiAgICAgIHJvdGF0aW9uID0gc3RvcmFnZUVudHJ5LnJvdGF0aW9uOwogICAgICBleHBvcnRlZFZhbHVlID0gc3RvcmFnZUVudHJ5LnZhbHVlOwogICAgfQogICAgaWYgKHJvdGF0aW9uID09PSB1bmRlZmluZWQgJiYgZXhwb3J0ZWRWYWx1ZSA9PT0gdW5kZWZpbmVkICYmICF0aGlzLl9uZWVkQXBwZWFyYW5jZXMpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBpZiAoZXhwb3J0ZWRWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIGV4cG9ydGVkVmFsdWUgPSB0aGlzLmRhdGEuZmllbGRWYWx1ZTsKICAgIH0gZWxzZSBpZiAoIUFycmF5LmlzQXJyYXkoZXhwb3J0ZWRWYWx1ZSkpIHsKICAgICAgZXhwb3J0ZWRWYWx1ZSA9IFtleHBvcnRlZFZhbHVlXTsKICAgIH0KICAgIGNvbnN0IGRlZmF1bHRQYWRkaW5nID0gMTsKICAgIGNvbnN0IGRlZmF1bHRIUGFkZGluZyA9IDI7CiAgICBsZXQgewogICAgICB3aWR0aDogdG90YWxXaWR0aCwKICAgICAgaGVpZ2h0OiB0b3RhbEhlaWdodAogICAgfSA9IHRoaXM7CiAgICBpZiAocm90YXRpb24gPT09IDkwIHx8IHJvdGF0aW9uID09PSAyNzApIHsKICAgICAgW3RvdGFsV2lkdGgsIHRvdGFsSGVpZ2h0XSA9IFt0b3RhbEhlaWdodCwgdG90YWxXaWR0aF07CiAgICB9CiAgICBjb25zdCBsaW5lQ291bnQgPSB0aGlzLmRhdGEub3B0aW9ucy5sZW5ndGg7CiAgICBjb25zdCB2YWx1ZUluZGljZXMgPSBbXTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGluZUNvdW50OyBpKyspIHsKICAgICAgY29uc3QgewogICAgICAgIGV4cG9ydFZhbHVlCiAgICAgIH0gPSB0aGlzLmRhdGEub3B0aW9uc1tpXTsKICAgICAgaWYgKGV4cG9ydGVkVmFsdWUuaW5jbHVkZXMoZXhwb3J0VmFsdWUpKSB7CiAgICAgICAgdmFsdWVJbmRpY2VzLnB1c2goaSk7CiAgICAgIH0KICAgIH0KICAgIGlmICghdGhpcy5fZGVmYXVsdEFwcGVhcmFuY2UpIHsKICAgICAgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YSA9IHBhcnNlRGVmYXVsdEFwcGVhcmFuY2UodGhpcy5fZGVmYXVsdEFwcGVhcmFuY2UgPSAiL0hlbHZldGljYSAwIFRmIDAgZyIpOwogICAgfQogICAgY29uc3QgZm9udCA9IGF3YWl0IFdpZGdldEFubm90YXRpb24uX2dldEZvbnREYXRhKGV2YWx1YXRvciwgdGFzaywgdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YSwgdGhpcy5fZmllbGRSZXNvdXJjZXMubWVyZ2VkUmVzb3VyY2VzKTsKICAgIGxldCBkZWZhdWx0QXBwZWFyYW5jZTsKICAgIGxldCB7CiAgICAgIGZvbnRTaXplCiAgICB9ID0gdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YTsKICAgIGlmICghZm9udFNpemUpIHsKICAgICAgY29uc3QgbGluZUhlaWdodCA9ICh0b3RhbEhlaWdodCAtIGRlZmF1bHRQYWRkaW5nKSAvIGxpbmVDb3VudDsKICAgICAgbGV0IGxpbmVXaWR0aCA9IC0xOwogICAgICBsZXQgdmFsdWU7CiAgICAgIGZvciAoY29uc3QgewogICAgICAgIGRpc3BsYXlWYWx1ZQogICAgICB9IG9mIHRoaXMuZGF0YS5vcHRpb25zKSB7CiAgICAgICAgY29uc3Qgd2lkdGggPSB0aGlzLl9nZXRUZXh0V2lkdGgoZGlzcGxheVZhbHVlLCBmb250KTsKICAgICAgICBpZiAod2lkdGggPiBsaW5lV2lkdGgpIHsKICAgICAgICAgIGxpbmVXaWR0aCA9IHdpZHRoOwogICAgICAgICAgdmFsdWUgPSBkaXNwbGF5VmFsdWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIFtkZWZhdWx0QXBwZWFyYW5jZSwgZm9udFNpemVdID0gdGhpcy5fY29tcHV0ZUZvbnRTaXplKGxpbmVIZWlnaHQsIHRvdGFsV2lkdGggLSAyICogZGVmYXVsdEhQYWRkaW5nLCB2YWx1ZSwgZm9udCwgLTEpOwogICAgfSBlbHNlIHsKICAgICAgZGVmYXVsdEFwcGVhcmFuY2UgPSB0aGlzLl9kZWZhdWx0QXBwZWFyYW5jZTsKICAgIH0KICAgIGNvbnN0IGxpbmVIZWlnaHQgPSBmb250U2l6ZSAqIExJTkVfRkFDVE9SOwogICAgY29uc3QgdlBhZGRpbmcgPSAobGluZUhlaWdodCAtIGZvbnRTaXplKSAvIDI7CiAgICBjb25zdCBudW1iZXJPZlZpc2libGVMaW5lcyA9IE1hdGguZmxvb3IodG90YWxIZWlnaHQgLyBsaW5lSGVpZ2h0KTsKICAgIGxldCBmaXJzdEluZGV4ID0gMDsKICAgIGlmICh2YWx1ZUluZGljZXMubGVuZ3RoID4gMCkgewogICAgICBjb25zdCBtaW5JbmRleCA9IE1hdGgubWluKC4uLnZhbHVlSW5kaWNlcyk7CiAgICAgIGNvbnN0IG1heEluZGV4ID0gTWF0aC5tYXgoLi4udmFsdWVJbmRpY2VzKTsKICAgICAgZmlyc3RJbmRleCA9IE1hdGgubWF4KDAsIG1heEluZGV4IC0gbnVtYmVyT2ZWaXNpYmxlTGluZXMgKyAxKTsKICAgICAgaWYgKGZpcnN0SW5kZXggPiBtaW5JbmRleCkgewogICAgICAgIGZpcnN0SW5kZXggPSBtaW5JbmRleDsKICAgICAgfQogICAgfQogICAgY29uc3QgZW5kID0gTWF0aC5taW4oZmlyc3RJbmRleCArIG51bWJlck9mVmlzaWJsZUxpbmVzICsgMSwgbGluZUNvdW50KTsKICAgIGNvbnN0IGJ1ZiA9IFsiL1R4IEJNQyBxIiwgYDEgMSAke3RvdGFsV2lkdGh9ICR7dG90YWxIZWlnaHR9IHJlIFcgbmBdOwogICAgaWYgKHZhbHVlSW5kaWNlcy5sZW5ndGgpIHsKICAgICAgYnVmLnB1c2goIjAuNjAwMDA2IDAuNzU2ODY2IDAuODU0OTA0IHJnIik7CiAgICAgIGZvciAoY29uc3QgaW5kZXggb2YgdmFsdWVJbmRpY2VzKSB7CiAgICAgICAgaWYgKGZpcnN0SW5kZXggPD0gaW5kZXggJiYgaW5kZXggPCBlbmQpIHsKICAgICAgICAgIGJ1Zi5wdXNoKGAxICR7dG90YWxIZWlnaHQgLSAoaW5kZXggLSBmaXJzdEluZGV4ICsgMSkgKiBsaW5lSGVpZ2h0fSAke3RvdGFsV2lkdGh9ICR7bGluZUhlaWdodH0gcmUgZmApOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgYnVmLnB1c2goIkJUIiwgZGVmYXVsdEFwcGVhcmFuY2UsIGAxIDAgMCAxIDAgJHt0b3RhbEhlaWdodH0gVG1gKTsKICAgIGNvbnN0IHByZXZJbmZvID0gewogICAgICBzaGlmdDogMAogICAgfTsKICAgIGZvciAobGV0IGkgPSBmaXJzdEluZGV4OyBpIDwgZW5kOyBpKyspIHsKICAgICAgY29uc3QgewogICAgICAgIGRpc3BsYXlWYWx1ZQogICAgICB9ID0gdGhpcy5kYXRhLm9wdGlvbnNbaV07CiAgICAgIGNvbnN0IHZwYWRkaW5nID0gaSA9PT0gZmlyc3RJbmRleCA/IHZQYWRkaW5nIDogMDsKICAgICAgYnVmLnB1c2godGhpcy5fcmVuZGVyVGV4dChkaXNwbGF5VmFsdWUsIGZvbnQsIGZvbnRTaXplLCB0b3RhbFdpZHRoLCAwLCBwcmV2SW5mbywgZGVmYXVsdEhQYWRkaW5nLCAtbGluZUhlaWdodCArIHZwYWRkaW5nKSk7CiAgICB9CiAgICBidWYucHVzaCgiRVQgUSBFTUMiKTsKICAgIHJldHVybiBidWYuam9pbigiXG4iKTsKICB9Cn0KY2xhc3MgU2lnbmF0dXJlV2lkZ2V0QW5ub3RhdGlvbiBleHRlbmRzIFdpZGdldEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIHRoaXMuZGF0YS5maWVsZFZhbHVlID0gbnVsbDsKICAgIHRoaXMuZGF0YS5oYXNPd25DYW52YXMgPSB0aGlzLmRhdGEubm9Sb3RhdGU7CiAgICB0aGlzLmRhdGEubm9IVE1MID0gIXRoaXMuZGF0YS5oYXNPd25DYW52YXM7CiAgfQogIGdldEZpZWxkT2JqZWN0KCkgewogICAgcmV0dXJuIHsKICAgICAgaWQ6IHRoaXMuZGF0YS5pZCwKICAgICAgdmFsdWU6IG51bGwsCiAgICAgIHBhZ2U6IHRoaXMuZGF0YS5wYWdlSW5kZXgsCiAgICAgIHR5cGU6ICJzaWduYXR1cmUiCiAgICB9OwogIH0KfQpjbGFzcyBUZXh0QW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgY29uc3QgREVGQVVMVF9JQ09OX1NJWkUgPSAyMjsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICB0aGlzLmRhdGEubm9Sb3RhdGUgPSB0cnVlOwogICAgdGhpcy5kYXRhLmhhc093bkNhbnZhcyA9IHRoaXMuZGF0YS5ub1JvdGF0ZTsKICAgIHRoaXMuZGF0YS5ub0hUTUwgPSBmYWxzZTsKICAgIGNvbnN0IHsKICAgICAgZGljdAogICAgfSA9IHBhcmFtczsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IEFubm90YXRpb25UeXBlLlRFWFQ7CiAgICBpZiAodGhpcy5kYXRhLmhhc0FwcGVhcmFuY2UpIHsKICAgICAgdGhpcy5kYXRhLm5hbWUgPSAiTm9JY29uIjsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuZGF0YS5yZWN0WzFdID0gdGhpcy5kYXRhLnJlY3RbM10gLSBERUZBVUxUX0lDT05fU0laRTsKICAgICAgdGhpcy5kYXRhLnJlY3RbMl0gPSB0aGlzLmRhdGEucmVjdFswXSArIERFRkFVTFRfSUNPTl9TSVpFOwogICAgICB0aGlzLmRhdGEubmFtZSA9IGRpY3QuaGFzKCJOYW1lIikgPyBkaWN0LmdldCgiTmFtZSIpLm5hbWUgOiAiTm90ZSI7CiAgICB9CiAgICBpZiAoZGljdC5oYXMoIlN0YXRlIikpIHsKICAgICAgdGhpcy5kYXRhLnN0YXRlID0gZGljdC5nZXQoIlN0YXRlIikgfHwgbnVsbDsKICAgICAgdGhpcy5kYXRhLnN0YXRlTW9kZWwgPSBkaWN0LmdldCgiU3RhdGVNb2RlbCIpIHx8IG51bGw7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmRhdGEuc3RhdGUgPSBudWxsOwogICAgICB0aGlzLmRhdGEuc3RhdGVNb2RlbCA9IG51bGw7CiAgICB9CiAgfQp9CmNsYXNzIExpbmtBbm5vdGF0aW9uIGV4dGVuZHMgQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICBhbm5vdGF0aW9uR2xvYmFscwogICAgfSA9IHBhcmFtczsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IEFubm90YXRpb25UeXBlLkxJTks7CiAgICB0aGlzLmRhdGEubm9IVE1MID0gZmFsc2U7CiAgICBjb25zdCBxdWFkUG9pbnRzID0gZ2V0UXVhZFBvaW50cyhkaWN0LCB0aGlzLnJlY3RhbmdsZSk7CiAgICBpZiAocXVhZFBvaW50cykgewogICAgICB0aGlzLmRhdGEucXVhZFBvaW50cyA9IHF1YWRQb2ludHM7CiAgICB9CiAgICB0aGlzLmRhdGEuYm9yZGVyQ29sb3IgfHw9IHRoaXMuZGF0YS5jb2xvcjsKICAgIENhdGFsb2cucGFyc2VEZXN0RGljdGlvbmFyeSh7CiAgICAgIGRlc3REaWN0OiBkaWN0LAogICAgICByZXN1bHRPYmo6IHRoaXMuZGF0YSwKICAgICAgZG9jQmFzZVVybDogYW5ub3RhdGlvbkdsb2JhbHMuYmFzZVVybCwKICAgICAgZG9jQXR0YWNobWVudHM6IGFubm90YXRpb25HbG9iYWxzLmF0dGFjaG1lbnRzCiAgICB9KTsKICB9CiAgZ2V0IG92ZXJsYXlzVGV4dENvbnRlbnQoKSB7CiAgICByZXR1cm4gdHJ1ZTsKICB9Cn0KY2xhc3MgUG9wdXBBbm5vdGF0aW9uIGV4dGVuZHMgQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0CiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGUuUE9QVVA7CiAgICB0aGlzLmRhdGEubm9IVE1MID0gZmFsc2U7CiAgICBpZiAodGhpcy53aWR0aCA9PT0gMCB8fCB0aGlzLmhlaWdodCA9PT0gMCkgewogICAgICB0aGlzLmRhdGEucmVjdCA9IG51bGw7CiAgICB9CiAgICBsZXQgcGFyZW50SXRlbSA9IGRpY3QuZ2V0KCJQYXJlbnQiKTsKICAgIGlmICghcGFyZW50SXRlbSkgewogICAgICB3YXJuKCJQb3B1cCBhbm5vdGF0aW9uIGhhcyBhIG1pc3Npbmcgb3IgaW52YWxpZCBwYXJlbnQgYW5ub3RhdGlvbi4iKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5kYXRhLnBhcmVudFJlY3QgPSBsb29rdXBOb3JtYWxSZWN0KHBhcmVudEl0ZW0uZ2V0QXJyYXkoIlJlY3QiKSwgbnVsbCk7CiAgICB0aGlzLmRhdGEuY3JlYXRpb25EYXRlID0gcGFyZW50SXRlbS5nZXQoIkNyZWF0aW9uRGF0ZSIpIHx8ICIiOwogICAgY29uc3QgcnQgPSBwYXJlbnRJdGVtLmdldCgiUlQiKTsKICAgIGlmIChpc05hbWUocnQsIEFubm90YXRpb25SZXBseVR5cGUuR1JPVVApKSB7CiAgICAgIHBhcmVudEl0ZW0gPSBwYXJlbnRJdGVtLmdldCgiSVJUIik7CiAgICB9CiAgICBpZiAoIXBhcmVudEl0ZW0uaGFzKCJNIikpIHsKICAgICAgdGhpcy5kYXRhLm1vZGlmaWNhdGlvbkRhdGUgPSBudWxsOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5zZXRNb2RpZmljYXRpb25EYXRlKHBhcmVudEl0ZW0uZ2V0KCJNIikpOwogICAgICB0aGlzLmRhdGEubW9kaWZpY2F0aW9uRGF0ZSA9IHRoaXMubW9kaWZpY2F0aW9uRGF0ZTsKICAgIH0KICAgIGlmICghcGFyZW50SXRlbS5oYXMoIkMiKSkgewogICAgICB0aGlzLmRhdGEuY29sb3IgPSBudWxsOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5zZXRDb2xvcihwYXJlbnRJdGVtLmdldEFycmF5KCJDIikpOwogICAgICB0aGlzLmRhdGEuY29sb3IgPSB0aGlzLmNvbG9yOwogICAgfQogICAgaWYgKCF0aGlzLnZpZXdhYmxlKSB7CiAgICAgIGNvbnN0IHBhcmVudEZsYWdzID0gcGFyZW50SXRlbS5nZXQoIkYiKTsKICAgICAgaWYgKHRoaXMuX2lzVmlld2FibGUocGFyZW50RmxhZ3MpKSB7CiAgICAgICAgdGhpcy5zZXRGbGFncyhwYXJlbnRGbGFncyk7CiAgICAgIH0KICAgIH0KICAgIHRoaXMuc2V0VGl0bGUocGFyZW50SXRlbS5nZXQoIlQiKSk7CiAgICB0aGlzLmRhdGEudGl0bGVPYmogPSB0aGlzLl90aXRsZTsKICAgIHRoaXMuc2V0Q29udGVudHMocGFyZW50SXRlbS5nZXQoIkNvbnRlbnRzIikpOwogICAgdGhpcy5kYXRhLmNvbnRlbnRzT2JqID0gdGhpcy5fY29udGVudHM7CiAgICBpZiAocGFyZW50SXRlbS5oYXMoIlJDIikpIHsKICAgICAgdGhpcy5kYXRhLnJpY2hUZXh0ID0gWEZBRmFjdG9yeS5nZXRSaWNoVGV4dEFzSHRtbChwYXJlbnRJdGVtLmdldCgiUkMiKSk7CiAgICB9CiAgICB0aGlzLmRhdGEub3BlbiA9ICEhZGljdC5nZXQoIk9wZW4iKTsKICB9CiAgc3RhdGljIGNyZWF0ZU5ld0RpY3QoYW5ub3RhdGlvbiwgeHJlZiwgX3BhcmFtcykgewogICAgY29uc3QgewogICAgICBvbGRBbm5vdGF0aW9uLAogICAgICByZWN0LAogICAgICBwYXJlbnQKICAgIH0gPSBhbm5vdGF0aW9uOwogICAgY29uc3QgcG9wdXAgPSBvbGRBbm5vdGF0aW9uIHx8IG5ldyBEaWN0KHhyZWYpOwogICAgcG9wdXAuc2V0SWZOb3RFeGlzdHMoIlR5cGUiLCBOYW1lLmdldCgiQW5ub3QiKSk7CiAgICBwb3B1cC5zZXRJZk5vdEV4aXN0cygiU3VidHlwZSIsIE5hbWUuZ2V0KCJQb3B1cCIpKTsKICAgIHBvcHVwLnNldElmTm90RXhpc3RzKCJPcGVuIiwgZmFsc2UpOwogICAgcG9wdXAuc2V0SWZBcnJheSgiUmVjdCIsIHJlY3QpOwogICAgcG9wdXAuc2V0KCJQYXJlbnQiLCBwYXJlbnQpOwogICAgcmV0dXJuIHBvcHVwOwogIH0KICBzdGF0aWMgYXN5bmMgY3JlYXRlTmV3QXBwZWFyYW5jZVN0cmVhbShhbm5vdGF0aW9uLCB4cmVmLCBwYXJhbXMpIHsKICAgIHJldHVybiBudWxsOwogIH0KfQpjbGFzcyBGcmVlVGV4dEFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdGhpcy5kYXRhLm5vUm90YXRlOwogICAgdGhpcy5kYXRhLmlzRWRpdGFibGUgPSAhdGhpcy5kYXRhLm5vSFRNTDsKICAgIHRoaXMuZGF0YS5ub0hUTUwgPSBmYWxzZTsKICAgIGNvbnN0IHsKICAgICAgYW5ub3RhdGlvbkdsb2JhbHMsCiAgICAgIGV2YWx1YXRvck9wdGlvbnMsCiAgICAgIHhyZWYKICAgIH0gPSBwYXJhbXM7CiAgICB0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGUgPSBBbm5vdGF0aW9uVHlwZS5GUkVFVEVYVDsKICAgIHRoaXMuc2V0RGVmYXVsdEFwcGVhcmFuY2UocGFyYW1zKTsKICAgIHRoaXMuX2hhc0FwcGVhcmFuY2UgPSAhIXRoaXMuYXBwZWFyYW5jZTsKICAgIGlmICh0aGlzLl9oYXNBcHBlYXJhbmNlKSB7CiAgICAgIGNvbnN0IHsKICAgICAgICBmb250Q29sb3IsCiAgICAgICAgZm9udFNpemUKICAgICAgfSA9IHBhcnNlQXBwZWFyYW5jZVN0cmVhbSh0aGlzLmFwcGVhcmFuY2UsIGV2YWx1YXRvck9wdGlvbnMsIHhyZWYsIGFubm90YXRpb25HbG9iYWxzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSk7CiAgICAgIHRoaXMuZGF0YS5kZWZhdWx0QXBwZWFyYW5jZURhdGEuZm9udENvbG9yID0gZm9udENvbG9yOwogICAgICB0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhLmZvbnRTaXplID0gZm9udFNpemUgfHwgMTA7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmRhdGEuZGVmYXVsdEFwcGVhcmFuY2VEYXRhLmZvbnRTaXplIHx8PSAxMDsKICAgICAgY29uc3QgewogICAgICAgIGZvbnRDb2xvciwKICAgICAgICBmb250U2l6ZQogICAgICB9ID0gdGhpcy5kYXRhLmRlZmF1bHRBcHBlYXJhbmNlRGF0YTsKICAgICAgaWYgKHRoaXMuX2NvbnRlbnRzLnN0cikgewogICAgICAgIHRoaXMuZGF0YS50ZXh0Q29udGVudCA9IHRoaXMuX2NvbnRlbnRzLnN0ci5zcGxpdCgvXHJcbj98XG4vKS5tYXAobGluZSA9PiBsaW5lLnRyaW1FbmQoKSk7CiAgICAgICAgY29uc3QgewogICAgICAgICAgY29vcmRzLAogICAgICAgICAgYmJveCwKICAgICAgICAgIG1hdHJpeAogICAgICAgIH0gPSBGYWtlVW5pY29kZUZvbnQuZ2V0Rmlyc3RQb3NpdGlvbkluZm8odGhpcy5yZWN0YW5nbGUsIHRoaXMucm90YXRpb24sIGZvbnRTaXplKTsKICAgICAgICB0aGlzLmRhdGEudGV4dFBvc2l0aW9uID0gdGhpcy5fdHJhbnNmb3JtUG9pbnQoY29vcmRzLCBiYm94LCBtYXRyaXgpOwogICAgICB9CiAgICAgIGlmICh0aGlzLl9pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCkgewogICAgICAgIGNvbnN0IHN0cm9rZUFscGhhID0gcGFyYW1zLmRpY3QuZ2V0KCJDQSIpOwogICAgICAgIGNvbnN0IGZha2VVbmljb2RlRm9udCA9IG5ldyBGYWtlVW5pY29kZUZvbnQoeHJlZiwgInNhbnMtc2VyaWYiKTsKICAgICAgICB0aGlzLmFwcGVhcmFuY2UgPSBmYWtlVW5pY29kZUZvbnQuY3JlYXRlQXBwZWFyYW5jZSh0aGlzLl9jb250ZW50cy5zdHIsIHRoaXMucmVjdGFuZ2xlLCB0aGlzLnJvdGF0aW9uLCBmb250U2l6ZSwgZm9udENvbG9yLCBzdHJva2VBbHBoYSk7CiAgICAgICAgdGhpcy5fc3RyZWFtcy5wdXNoKHRoaXMuYXBwZWFyYW5jZSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgd2FybigiRnJlZVRleHRBbm5vdGF0aW9uOiBPZmZzY3JlZW5DYW52YXMgaXMgbm90IHN1cHBvcnRlZCwgYW5ub3RhdGlvbiBtYXkgbm90IHJlbmRlciBjb3JyZWN0bHkuIik7CiAgICAgIH0KICAgIH0KICB9CiAgZ2V0IGhhc1RleHRDb250ZW50KCkgewogICAgcmV0dXJuIHRoaXMuX2hhc0FwcGVhcmFuY2U7CiAgfQogIHN0YXRpYyBjcmVhdGVOZXdEaWN0KGFubm90YXRpb24sIHhyZWYsIHsKICAgIGFwUmVmLAogICAgYXAKICB9KSB7CiAgICBjb25zdCB7CiAgICAgIGNvbG9yLAogICAgICBkYXRlLAogICAgICBmb250U2l6ZSwKICAgICAgb2xkQW5ub3RhdGlvbiwKICAgICAgcmVjdCwKICAgICAgcm90YXRpb24sCiAgICAgIHVzZXIsCiAgICAgIHZhbHVlCiAgICB9ID0gYW5ub3RhdGlvbjsKICAgIGNvbnN0IGZyZWV0ZXh0ID0gb2xkQW5ub3RhdGlvbiB8fCBuZXcgRGljdCh4cmVmKTsKICAgIGZyZWV0ZXh0LnNldElmTm90RXhpc3RzKCJUeXBlIiwgTmFtZS5nZXQoIkFubm90IikpOwogICAgZnJlZXRleHQuc2V0SWZOb3RFeGlzdHMoIlN1YnR5cGUiLCBOYW1lLmdldCgiRnJlZVRleHQiKSk7CiAgICBmcmVldGV4dC5zZXQob2xkQW5ub3RhdGlvbiA/ICJNIiA6ICJDcmVhdGlvbkRhdGUiLCBgRDoke2dldE1vZGlmaWNhdGlvbkRhdGUoZGF0ZSl9YCk7CiAgICBpZiAob2xkQW5ub3RhdGlvbikgewogICAgICBmcmVldGV4dC5kZWxldGUoIlJDIik7CiAgICB9CiAgICBmcmVldGV4dC5zZXRJZkFycmF5KCJSZWN0IiwgcmVjdCk7CiAgICBjb25zdCBkYSA9IGAvSGVsdiAke2ZvbnRTaXplfSBUZiAke2dldFBkZkNvbG9yKGNvbG9yLCB0cnVlKX1gOwogICAgZnJlZXRleHQuc2V0KCJEQSIsIGRhKTsKICAgIGZyZWV0ZXh0LnNldElmRGVmaW5lZCgiQ29udGVudHMiLCBzdHJpbmdUb0FzY2lpT3JVVEYxNkJFKHZhbHVlKSk7CiAgICBmcmVldGV4dC5zZXRJZk5vdEV4aXN0cygiRiIsIDQpOwogICAgZnJlZXRleHQuc2V0SWZOb3RFeGlzdHMoIkJvcmRlciIsIFswLCAwLCAwXSk7CiAgICBmcmVldGV4dC5zZXRJZk51bWJlcigiUm90YXRlIiwgcm90YXRpb24pOwogICAgZnJlZXRleHQuc2V0SWZEZWZpbmVkKCJUIiwgc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRSh1c2VyKSk7CiAgICBpZiAoYXBSZWYgfHwgYXApIHsKICAgICAgY29uc3QgbiA9IG5ldyBEaWN0KHhyZWYpOwogICAgICBmcmVldGV4dC5zZXQoIkFQIiwgbik7CiAgICAgIG4uc2V0KCJOIiwgYXBSZWYgfHwgYXApOwogICAgfQogICAgcmV0dXJuIGZyZWV0ZXh0OwogIH0KICBzdGF0aWMgYXN5bmMgY3JlYXRlTmV3QXBwZWFyYW5jZVN0cmVhbShhbm5vdGF0aW9uLCB4cmVmLCBwYXJhbXMpIHsKICAgIGNvbnN0IHsKICAgICAgYmFzZUZvbnRSZWYsCiAgICAgIGV2YWx1YXRvciwKICAgICAgdGFzawogICAgfSA9IHBhcmFtczsKICAgIGNvbnN0IHsKICAgICAgY29sb3IsCiAgICAgIGZvbnRTaXplLAogICAgICByZWN0LAogICAgICByb3RhdGlvbiwKICAgICAgdmFsdWUKICAgIH0gPSBhbm5vdGF0aW9uOwogICAgaWYgKCFjb2xvcikgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IHJlc291cmNlcyA9IG5ldyBEaWN0KHhyZWYpOwogICAgY29uc3QgZm9udCA9IG5ldyBEaWN0KHhyZWYpOwogICAgaWYgKGJhc2VGb250UmVmKSB7CiAgICAgIGZvbnQuc2V0KCJIZWx2IiwgYmFzZUZvbnRSZWYpOwogICAgfSBlbHNlIHsKICAgICAgY29uc3QgYmFzZUZvbnQgPSBuZXcgRGljdCh4cmVmKTsKICAgICAgYmFzZUZvbnQuc2V0SWZOYW1lKCJCYXNlRm9udCIsICJIZWx2ZXRpY2EiKTsKICAgICAgYmFzZUZvbnQuc2V0SWZOYW1lKCJUeXBlIiwgIkZvbnQiKTsKICAgICAgYmFzZUZvbnQuc2V0SWZOYW1lKCJTdWJ0eXBlIiwgIlR5cGUxIik7CiAgICAgIGJhc2VGb250LnNldElmTmFtZSgiRW5jb2RpbmciLCAiV2luQW5zaUVuY29kaW5nIik7CiAgICAgIGZvbnQuc2V0KCJIZWx2IiwgYmFzZUZvbnQpOwogICAgfQogICAgcmVzb3VyY2VzLnNldCgiRm9udCIsIGZvbnQpOwogICAgY29uc3QgaGVsdiA9IGF3YWl0IFdpZGdldEFubm90YXRpb24uX2dldEZvbnREYXRhKGV2YWx1YXRvciwgdGFzaywgewogICAgICBmb250TmFtZTogIkhlbHYiLAogICAgICBmb250U2l6ZQogICAgfSwgcmVzb3VyY2VzKTsKICAgIGNvbnN0IFt4MSwgeTEsIHgyLCB5Ml0gPSByZWN0OwogICAgbGV0IHcgPSB4MiAtIHgxOwogICAgbGV0IGggPSB5MiAtIHkxOwogICAgaWYgKHJvdGF0aW9uICUgMTgwICE9PSAwKSB7CiAgICAgIFt3LCBoXSA9IFtoLCB3XTsKICAgIH0KICAgIGNvbnN0IGxpbmVzID0gdmFsdWUuc3BsaXQoIlxuIik7CiAgICBjb25zdCBzY2FsZSA9IGZvbnRTaXplIC8gMTAwMDsKICAgIGxldCB0b3RhbFdpZHRoID0gLUluZmluaXR5OwogICAgY29uc3QgZW5jb2RlZExpbmVzID0gW107CiAgICBmb3IgKGxldCBsaW5lIG9mIGxpbmVzKSB7CiAgICAgIGNvbnN0IGVuY29kZWQgPSBoZWx2LmVuY29kZVN0cmluZyhsaW5lKTsKICAgICAgaWYgKGVuY29kZWQubGVuZ3RoID4gMSkgewogICAgICAgIHJldHVybiBudWxsOwogICAgICB9CiAgICAgIGxpbmUgPSBlbmNvZGVkLmpvaW4oIiIpOwogICAgICBlbmNvZGVkTGluZXMucHVzaChsaW5lKTsKICAgICAgbGV0IGxpbmVXaWR0aCA9IDA7CiAgICAgIGNvbnN0IGdseXBocyA9IGhlbHYuY2hhcnNUb0dseXBocyhsaW5lKTsKICAgICAgZm9yIChjb25zdCBnbHlwaCBvZiBnbHlwaHMpIHsKICAgICAgICBsaW5lV2lkdGggKz0gZ2x5cGgud2lkdGggKiBzY2FsZTsKICAgICAgfQogICAgICB0b3RhbFdpZHRoID0gTWF0aC5tYXgodG90YWxXaWR0aCwgbGluZVdpZHRoKTsKICAgIH0KICAgIGxldCBoc2NhbGUgPSAxOwogICAgaWYgKHRvdGFsV2lkdGggPiB3KSB7CiAgICAgIGhzY2FsZSA9IHcgLyB0b3RhbFdpZHRoOwogICAgfQogICAgbGV0IHZzY2FsZSA9IDE7CiAgICBjb25zdCBsaW5lSGVpZ2h0ID0gTElORV9GQUNUT1IgKiBmb250U2l6ZTsKICAgIGNvbnN0IGxpbmVBc2NlbnQgPSAoTElORV9GQUNUT1IgLSBMSU5FX0RFU0NFTlRfRkFDVE9SKSAqIGZvbnRTaXplOwogICAgY29uc3QgdG90YWxIZWlnaHQgPSBsaW5lSGVpZ2h0ICogbGluZXMubGVuZ3RoOwogICAgaWYgKHRvdGFsSGVpZ2h0ID4gaCkgewogICAgICB2c2NhbGUgPSBoIC8gdG90YWxIZWlnaHQ7CiAgICB9CiAgICBjb25zdCBmc2NhbGUgPSBNYXRoLm1pbihoc2NhbGUsIHZzY2FsZSk7CiAgICBjb25zdCBuZXdGb250U2l6ZSA9IGZvbnRTaXplICogZnNjYWxlOwogICAgbGV0IGZpcnN0UG9pbnQsIGNsaXBCb3gsIG1hdHJpeDsKICAgIHN3aXRjaCAocm90YXRpb24pIHsKICAgICAgY2FzZSAwOgogICAgICAgIG1hdHJpeCA9IFsxLCAwLCAwLCAxXTsKICAgICAgICBjbGlwQm94ID0gW3JlY3RbMF0sIHJlY3RbMV0sIHcsIGhdOwogICAgICAgIGZpcnN0UG9pbnQgPSBbcmVjdFswXSwgcmVjdFszXSAtIGxpbmVBc2NlbnRdOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDkwOgogICAgICAgIG1hdHJpeCA9IFswLCAxLCAtMSwgMF07CiAgICAgICAgY2xpcEJveCA9IFtyZWN0WzFdLCAtcmVjdFsyXSwgdywgaF07CiAgICAgICAgZmlyc3RQb2ludCA9IFtyZWN0WzFdLCAtcmVjdFswXSAtIGxpbmVBc2NlbnRdOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDE4MDoKICAgICAgICBtYXRyaXggPSBbLTEsIDAsIDAsIC0xXTsKICAgICAgICBjbGlwQm94ID0gWy1yZWN0WzJdLCAtcmVjdFszXSwgdywgaF07CiAgICAgICAgZmlyc3RQb2ludCA9IFstcmVjdFsyXSwgLXJlY3RbMV0gLSBsaW5lQXNjZW50XTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSAyNzA6CiAgICAgICAgbWF0cml4ID0gWzAsIC0xLCAxLCAwXTsKICAgICAgICBjbGlwQm94ID0gWy1yZWN0WzNdLCByZWN0WzBdLCB3LCBoXTsKICAgICAgICBmaXJzdFBvaW50ID0gWy1yZWN0WzNdLCByZWN0WzJdIC0gbGluZUFzY2VudF07CiAgICAgICAgYnJlYWs7CiAgICB9CiAgICBjb25zdCBidWZmZXIgPSBbInEiLCBgJHttYXRyaXguam9pbigiICIpfSAwIDAgY21gLCBgJHtjbGlwQm94LmpvaW4oIiAiKX0gcmUgVyBuYCwgYEJUYCwgYCR7Z2V0UGRmQ29sb3IoY29sb3IsIHRydWUpfWAsIGAwIFRjIC9IZWx2ICR7bnVtYmVyVG9TdHJpbmcobmV3Rm9udFNpemUpfSBUZmBdOwogICAgYnVmZmVyLnB1c2goYCR7Zmlyc3RQb2ludC5qb2luKCIgIil9IFRkICgke2VzY2FwZVN0cmluZyhlbmNvZGVkTGluZXNbMF0pfSkgVGpgKTsKICAgIGNvbnN0IHZTaGlmdCA9IG51bWJlclRvU3RyaW5nKGxpbmVIZWlnaHQpOwogICAgZm9yIChsZXQgaSA9IDEsIGlpID0gZW5jb2RlZExpbmVzLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgY29uc3QgbGluZSA9IGVuY29kZWRMaW5lc1tpXTsKICAgICAgYnVmZmVyLnB1c2goYDAgLSR7dlNoaWZ0fSBUZCAoJHtlc2NhcGVTdHJpbmcobGluZSl9KSBUamApOwogICAgfQogICAgYnVmZmVyLnB1c2goIkVUIiwgIlEiKTsKICAgIGNvbnN0IGFwcGVhcmFuY2UgPSBidWZmZXIuam9pbigiXG4iKTsKICAgIGNvbnN0IGFwcGVhcmFuY2VTdHJlYW1EaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkZvcm1UeXBlIiwgMSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXRJZk5hbWUoIlN1YnR5cGUiLCAiRm9ybSIpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0SWZOYW1lKCJUeXBlIiwgIlhPYmplY3QiKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiQkJveCIsIHJlY3QpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJSZXNvdXJjZXMiLCByZXNvdXJjZXMpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJNYXRyaXgiLCBbMSwgMCwgMCwgMSwgLXJlY3RbMF0sIC1yZWN0WzFdXSk7CiAgICBjb25zdCBhcCA9IG5ldyBTdHJpbmdTdHJlYW0oYXBwZWFyYW5jZSk7CiAgICBhcC5kaWN0ID0gYXBwZWFyYW5jZVN0cmVhbURpY3Q7CiAgICByZXR1cm4gYXA7CiAgfQp9CmNsYXNzIExpbmVBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGUuTElORTsKICAgIHRoaXMuZGF0YS5oYXNPd25DYW52YXMgPSB0aGlzLmRhdGEubm9Sb3RhdGU7CiAgICB0aGlzLmRhdGEubm9IVE1MID0gZmFsc2U7CiAgICBjb25zdCBsaW5lQ29vcmRpbmF0ZXMgPSBsb29rdXBSZWN0KGRpY3QuZ2V0QXJyYXkoIkwiKSwgWzAsIDAsIDAsIDBdKTsKICAgIHRoaXMuZGF0YS5saW5lQ29vcmRpbmF0ZXMgPSBVdGlsLm5vcm1hbGl6ZVJlY3QobGluZUNvb3JkaW5hdGVzKTsKICAgIHRoaXMuc2V0TGluZUVuZGluZ3MoZGljdC5nZXRBcnJheSgiTEUiKSk7CiAgICB0aGlzLmRhdGEubGluZUVuZGluZ3MgPSB0aGlzLmxpbmVFbmRpbmdzOwogICAgaWYgKCF0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgY29uc3Qgc3Ryb2tlQ29sb3IgPSBnZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IsIFswLCAwLCAwXSk7CiAgICAgIGNvbnN0IHN0cm9rZUFscGhhID0gZGljdC5nZXQoIkNBIik7CiAgICAgIGNvbnN0IGludGVyaW9yQ29sb3IgPSBnZXRSZ2JDb2xvcihkaWN0LmdldEFycmF5KCJJQyIpLCBudWxsKTsKICAgICAgY29uc3QgZmlsbENvbG9yID0gZ2V0UGRmQ29sb3JBcnJheShpbnRlcmlvckNvbG9yKTsKICAgICAgY29uc3QgZmlsbEFscGhhID0gZmlsbENvbG9yID8gc3Ryb2tlQWxwaGEgOiBudWxsOwogICAgICBjb25zdCBib3JkZXJXaWR0aCA9IHRoaXMuYm9yZGVyU3R5bGUud2lkdGggfHwgMSwKICAgICAgICBib3JkZXJBZGp1c3QgPSAyICogYm9yZGVyV2lkdGg7CiAgICAgIGNvbnN0IGJib3ggPSBbdGhpcy5kYXRhLmxpbmVDb29yZGluYXRlc1swXSAtIGJvcmRlckFkanVzdCwgdGhpcy5kYXRhLmxpbmVDb29yZGluYXRlc1sxXSAtIGJvcmRlckFkanVzdCwgdGhpcy5kYXRhLmxpbmVDb29yZGluYXRlc1syXSArIGJvcmRlckFkanVzdCwgdGhpcy5kYXRhLmxpbmVDb29yZGluYXRlc1szXSArIGJvcmRlckFkanVzdF07CiAgICAgIGlmICghVXRpbC5pbnRlcnNlY3QodGhpcy5yZWN0YW5nbGUsIGJib3gpKSB7CiAgICAgICAgdGhpcy5yZWN0YW5nbGUgPSBiYm94OwogICAgICB9CiAgICAgIHRoaXMuX3NldERlZmF1bHRBcHBlYXJhbmNlKHsKICAgICAgICB4cmVmLAogICAgICAgIGV4dHJhOiBgJHtib3JkZXJXaWR0aH0gd2AsCiAgICAgICAgc3Ryb2tlQ29sb3IsCiAgICAgICAgZmlsbENvbG9yLAogICAgICAgIHN0cm9rZUFscGhhLAogICAgICAgIGZpbGxBbHBoYSwKICAgICAgICBwb2ludHNDYWxsYmFjazogKGJ1ZmZlciwgcG9pbnRzKSA9PiB7CiAgICAgICAgICBidWZmZXIucHVzaChgJHtsaW5lQ29vcmRpbmF0ZXNbMF19ICR7bGluZUNvb3JkaW5hdGVzWzFdfSBtYCwgYCR7bGluZUNvb3JkaW5hdGVzWzJdfSAke2xpbmVDb29yZGluYXRlc1szXX0gbGAsICJTIik7CiAgICAgICAgICByZXR1cm4gW3BvaW50c1swXSAtIGJvcmRlcldpZHRoLCBwb2ludHNbN10gLSBib3JkZXJXaWR0aCwgcG9pbnRzWzJdICsgYm9yZGVyV2lkdGgsIHBvaW50c1szXSArIGJvcmRlcldpZHRoXTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQogIH0KfQpjbGFzcyBTcXVhcmVBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGUuU1FVQVJFOwogICAgdGhpcy5kYXRhLmhhc093bkNhbnZhcyA9IHRoaXMuZGF0YS5ub1JvdGF0ZTsKICAgIHRoaXMuZGF0YS5ub0hUTUwgPSBmYWxzZTsKICAgIGlmICghdGhpcy5hcHBlYXJhbmNlKSB7CiAgICAgIGNvbnN0IHN0cm9rZUNvbG9yID0gZ2V0UGRmQ29sb3JBcnJheSh0aGlzLmNvbG9yLCBbMCwgMCwgMF0pOwogICAgICBjb25zdCBzdHJva2VBbHBoYSA9IGRpY3QuZ2V0KCJDQSIpOwogICAgICBjb25zdCBpbnRlcmlvckNvbG9yID0gZ2V0UmdiQ29sb3IoZGljdC5nZXRBcnJheSgiSUMiKSwgbnVsbCk7CiAgICAgIGNvbnN0IGZpbGxDb2xvciA9IGdldFBkZkNvbG9yQXJyYXkoaW50ZXJpb3JDb2xvcik7CiAgICAgIGNvbnN0IGZpbGxBbHBoYSA9IGZpbGxDb2xvciA/IHN0cm9rZUFscGhhIDogbnVsbDsKICAgICAgaWYgKHRoaXMuYm9yZGVyU3R5bGUud2lkdGggPT09IDAgJiYgIWZpbGxDb2xvcikgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICB0aGlzLl9zZXREZWZhdWx0QXBwZWFyYW5jZSh7CiAgICAgICAgeHJlZiwKICAgICAgICBleHRyYTogYCR7dGhpcy5ib3JkZXJTdHlsZS53aWR0aH0gd2AsCiAgICAgICAgc3Ryb2tlQ29sb3IsCiAgICAgICAgZmlsbENvbG9yLAogICAgICAgIHN0cm9rZUFscGhhLAogICAgICAgIGZpbGxBbHBoYSwKICAgICAgICBwb2ludHNDYWxsYmFjazogKGJ1ZmZlciwgcG9pbnRzKSA9PiB7CiAgICAgICAgICBjb25zdCB4ID0gcG9pbnRzWzRdICsgdGhpcy5ib3JkZXJTdHlsZS53aWR0aCAvIDI7CiAgICAgICAgICBjb25zdCB5ID0gcG9pbnRzWzVdICsgdGhpcy5ib3JkZXJTdHlsZS53aWR0aCAvIDI7CiAgICAgICAgICBjb25zdCB3aWR0aCA9IHBvaW50c1s2XSAtIHBvaW50c1s0XSAtIHRoaXMuYm9yZGVyU3R5bGUud2lkdGg7CiAgICAgICAgICBjb25zdCBoZWlnaHQgPSBwb2ludHNbM10gLSBwb2ludHNbN10gLSB0aGlzLmJvcmRlclN0eWxlLndpZHRoOwogICAgICAgICAgYnVmZmVyLnB1c2goYCR7eH0gJHt5fSAke3dpZHRofSAke2hlaWdodH0gcmVgKTsKICAgICAgICAgIGlmIChmaWxsQ29sb3IpIHsKICAgICAgICAgICAgYnVmZmVyLnB1c2goIkIiKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGJ1ZmZlci5wdXNoKCJTIik7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gW3BvaW50c1swXSwgcG9pbnRzWzddLCBwb2ludHNbMl0sIHBvaW50c1szXV07CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KICB9Cn0KY2xhc3MgQ2lyY2xlQW5ub3RhdGlvbiBleHRlbmRzIE1hcmt1cEFubm90YXRpb24gewogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIGNvbnN0IHsKICAgICAgZGljdCwKICAgICAgeHJlZgogICAgfSA9IHBhcmFtczsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IEFubm90YXRpb25UeXBlLkNJUkNMRTsKICAgIGlmICghdGhpcy5hcHBlYXJhbmNlKSB7CiAgICAgIGNvbnN0IHN0cm9rZUNvbG9yID0gZ2V0UGRmQ29sb3JBcnJheSh0aGlzLmNvbG9yLCBbMCwgMCwgMF0pOwogICAgICBjb25zdCBzdHJva2VBbHBoYSA9IGRpY3QuZ2V0KCJDQSIpOwogICAgICBjb25zdCBpbnRlcmlvckNvbG9yID0gZ2V0UmdiQ29sb3IoZGljdC5nZXRBcnJheSgiSUMiKSwgbnVsbCk7CiAgICAgIGNvbnN0IGZpbGxDb2xvciA9IGdldFBkZkNvbG9yQXJyYXkoaW50ZXJpb3JDb2xvcik7CiAgICAgIGNvbnN0IGZpbGxBbHBoYSA9IGZpbGxDb2xvciA/IHN0cm9rZUFscGhhIDogbnVsbDsKICAgICAgaWYgKHRoaXMuYm9yZGVyU3R5bGUud2lkdGggPT09IDAgJiYgIWZpbGxDb2xvcikgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBjb25zdCBjb250cm9sUG9pbnRzRGlzdGFuY2UgPSA0IC8gMyAqIE1hdGgudGFuKE1hdGguUEkgLyAoMiAqIDQpKTsKICAgICAgdGhpcy5fc2V0RGVmYXVsdEFwcGVhcmFuY2UoewogICAgICAgIHhyZWYsCiAgICAgICAgZXh0cmE6IGAke3RoaXMuYm9yZGVyU3R5bGUud2lkdGh9IHdgLAogICAgICAgIHN0cm9rZUNvbG9yLAogICAgICAgIGZpbGxDb2xvciwKICAgICAgICBzdHJva2VBbHBoYSwKICAgICAgICBmaWxsQWxwaGEsCiAgICAgICAgcG9pbnRzQ2FsbGJhY2s6IChidWZmZXIsIHBvaW50cykgPT4gewogICAgICAgICAgY29uc3QgeDAgPSBwb2ludHNbMF0gKyB0aGlzLmJvcmRlclN0eWxlLndpZHRoIC8gMjsKICAgICAgICAgIGNvbnN0IHkwID0gcG9pbnRzWzFdIC0gdGhpcy5ib3JkZXJTdHlsZS53aWR0aCAvIDI7CiAgICAgICAgICBjb25zdCB4MSA9IHBvaW50c1s2XSAtIHRoaXMuYm9yZGVyU3R5bGUud2lkdGggLyAyOwogICAgICAgICAgY29uc3QgeTEgPSBwb2ludHNbN10gKyB0aGlzLmJvcmRlclN0eWxlLndpZHRoIC8gMjsKICAgICAgICAgIGNvbnN0IHhNaWQgPSB4MCArICh4MSAtIHgwKSAvIDI7CiAgICAgICAgICBjb25zdCB5TWlkID0geTAgKyAoeTEgLSB5MCkgLyAyOwogICAgICAgICAgY29uc3QgeE9mZnNldCA9ICh4MSAtIHgwKSAvIDIgKiBjb250cm9sUG9pbnRzRGlzdGFuY2U7CiAgICAgICAgICBjb25zdCB5T2Zmc2V0ID0gKHkxIC0geTApIC8gMiAqIGNvbnRyb2xQb2ludHNEaXN0YW5jZTsKICAgICAgICAgIGJ1ZmZlci5wdXNoKGAke3hNaWR9ICR7eTF9IG1gLCBgJHt4TWlkICsgeE9mZnNldH0gJHt5MX0gJHt4MX0gJHt5TWlkICsgeU9mZnNldH0gJHt4MX0gJHt5TWlkfSBjYCwgYCR7eDF9ICR7eU1pZCAtIHlPZmZzZXR9ICR7eE1pZCArIHhPZmZzZXR9ICR7eTB9ICR7eE1pZH0gJHt5MH0gY2AsIGAke3hNaWQgLSB4T2Zmc2V0fSAke3kwfSAke3gwfSAke3lNaWQgLSB5T2Zmc2V0fSAke3gwfSAke3lNaWR9IGNgLCBgJHt4MH0gJHt5TWlkICsgeU9mZnNldH0gJHt4TWlkIC0geE9mZnNldH0gJHt5MX0gJHt4TWlkfSAke3kxfSBjYCwgImgiKTsKICAgICAgICAgIGlmIChmaWxsQ29sb3IpIHsKICAgICAgICAgICAgYnVmZmVyLnB1c2goIkIiKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGJ1ZmZlci5wdXNoKCJTIik7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gW3BvaW50c1swXSwgcG9pbnRzWzddLCBwb2ludHNbMl0sIHBvaW50c1szXV07CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KICB9Cn0KY2xhc3MgUG9seWxpbmVBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGUuUE9MWUxJTkU7CiAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdGhpcy5kYXRhLm5vUm90YXRlOwogICAgdGhpcy5kYXRhLm5vSFRNTCA9IGZhbHNlOwogICAgdGhpcy5kYXRhLnZlcnRpY2VzID0gbnVsbDsKICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBQb2x5Z29uQW5ub3RhdGlvbikpIHsKICAgICAgdGhpcy5zZXRMaW5lRW5kaW5ncyhkaWN0LmdldEFycmF5KCJMRSIpKTsKICAgICAgdGhpcy5kYXRhLmxpbmVFbmRpbmdzID0gdGhpcy5saW5lRW5kaW5nczsKICAgIH0KICAgIGNvbnN0IHJhd1ZlcnRpY2VzID0gZGljdC5nZXRBcnJheSgiVmVydGljZXMiKTsKICAgIGlmICghaXNOdW1iZXJBcnJheShyYXdWZXJ0aWNlcywgbnVsbCkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgdmVydGljZXMgPSB0aGlzLmRhdGEudmVydGljZXMgPSBGbG9hdDMyQXJyYXkuZnJvbShyYXdWZXJ0aWNlcyk7CiAgICBpZiAoIXRoaXMuYXBwZWFyYW5jZSkgewogICAgICBjb25zdCBzdHJva2VDb2xvciA9IGdldFBkZkNvbG9yQXJyYXkodGhpcy5jb2xvciwgWzAsIDAsIDBdKTsKICAgICAgY29uc3Qgc3Ryb2tlQWxwaGEgPSBkaWN0LmdldCgiQ0EiKTsKICAgICAgbGV0IGZpbGxDb2xvciA9IGdldFJnYkNvbG9yKGRpY3QuZ2V0QXJyYXkoIklDIiksIG51bGwpOwogICAgICBpZiAoZmlsbENvbG9yKSB7CiAgICAgICAgZmlsbENvbG9yID0gZ2V0UGRmQ29sb3JBcnJheShmaWxsQ29sb3IpOwogICAgICB9CiAgICAgIGxldCBvcGVyYXRvcjsKICAgICAgaWYgKGZpbGxDb2xvcikgewogICAgICAgIGlmICh0aGlzLmNvbG9yKSB7CiAgICAgICAgICBvcGVyYXRvciA9IGZpbGxDb2xvci5ldmVyeSgoYywgaSkgPT4gYyA9PT0gc3Ryb2tlQ29sb3JbaV0pID8gImYiIDogIkIiOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBvcGVyYXRvciA9ICJmIjsKICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgb3BlcmF0b3IgPSAiUyI7CiAgICAgIH0KICAgICAgY29uc3QgYm9yZGVyV2lkdGggPSB0aGlzLmJvcmRlclN0eWxlLndpZHRoIHx8IDEsCiAgICAgICAgYm9yZGVyQWRqdXN0ID0gMiAqIGJvcmRlcldpZHRoOwogICAgICBjb25zdCBiYm94ID0gW0luZmluaXR5LCBJbmZpbml0eSwgLUluZmluaXR5LCAtSW5maW5pdHldOwogICAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB2ZXJ0aWNlcy5sZW5ndGg7IGkgPCBpaTsgaSArPSAyKSB7CiAgICAgICAgVXRpbC5yZWN0Qm91bmRpbmdCb3godmVydGljZXNbaV0gLSBib3JkZXJBZGp1c3QsIHZlcnRpY2VzW2kgKyAxXSAtIGJvcmRlckFkanVzdCwgdmVydGljZXNbaV0gKyBib3JkZXJBZGp1c3QsIHZlcnRpY2VzW2kgKyAxXSArIGJvcmRlckFkanVzdCwgYmJveCk7CiAgICAgIH0KICAgICAgaWYgKCFVdGlsLmludGVyc2VjdCh0aGlzLnJlY3RhbmdsZSwgYmJveCkpIHsKICAgICAgICB0aGlzLnJlY3RhbmdsZSA9IGJib3g7CiAgICAgIH0KICAgICAgdGhpcy5fc2V0RGVmYXVsdEFwcGVhcmFuY2UoewogICAgICAgIHhyZWYsCiAgICAgICAgZXh0cmE6IGAke2JvcmRlcldpZHRofSB3YCwKICAgICAgICBzdHJva2VDb2xvciwKICAgICAgICBzdHJva2VBbHBoYSwKICAgICAgICBmaWxsQ29sb3IsCiAgICAgICAgZmlsbEFscGhhOiBmaWxsQ29sb3IgPyBzdHJva2VBbHBoYSA6IG51bGwsCiAgICAgICAgcG9pbnRzQ2FsbGJhY2s6IChidWZmZXIsIHBvaW50cykgPT4gewogICAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gdmVydGljZXMubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICAgICAgICBidWZmZXIucHVzaChgJHt2ZXJ0aWNlc1tpXX0gJHt2ZXJ0aWNlc1tpICsgMV19ICR7aSA9PT0gMCA/ICJtIiA6ICJsIn1gKTsKICAgICAgICAgIH0KICAgICAgICAgIGJ1ZmZlci5wdXNoKG9wZXJhdG9yKTsKICAgICAgICAgIHJldHVybiBbcG9pbnRzWzBdLCBwb2ludHNbN10sIHBvaW50c1syXSwgcG9pbnRzWzNdXTsKICAgICAgICB9CiAgICAgIH0pOwogICAgfQogIH0KfQpjbGFzcyBQb2x5Z29uQW5ub3RhdGlvbiBleHRlbmRzIFBvbHlsaW5lQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGUuUE9MWUdPTjsKICB9Cn0KY2xhc3MgQ2FyZXRBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGUuQ0FSRVQ7CiAgfQp9CmNsYXNzIElua0Fubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICB0aGlzLmRhdGEuaGFzT3duQ2FudmFzID0gdGhpcy5kYXRhLm5vUm90YXRlOwogICAgdGhpcy5kYXRhLm5vSFRNTCA9IGZhbHNlOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGUuSU5LOwogICAgdGhpcy5kYXRhLmlua0xpc3RzID0gW107CiAgICB0aGlzLmRhdGEuaXNFZGl0YWJsZSA9ICF0aGlzLmRhdGEubm9IVE1MOwogICAgdGhpcy5kYXRhLm5vSFRNTCA9IGZhbHNlOwogICAgdGhpcy5kYXRhLm9wYWNpdHkgPSBkaWN0LmdldCgiQ0EiKSB8fCAxOwogICAgY29uc3QgcmF3SW5rTGlzdHMgPSBkaWN0LmdldEFycmF5KCJJbmtMaXN0Iik7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkocmF3SW5rTGlzdHMpKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IHJhd0lua0xpc3RzLmxlbmd0aDsgaSA8IGlpOyArK2kpIHsKICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHJhd0lua0xpc3RzW2ldKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGlua0xpc3QgPSBuZXcgRmxvYXQzMkFycmF5KHJhd0lua0xpc3RzW2ldLmxlbmd0aCk7CiAgICAgIHRoaXMuZGF0YS5pbmtMaXN0cy5wdXNoKGlua0xpc3QpOwogICAgICBmb3IgKGxldCBqID0gMCwgamogPSByYXdJbmtMaXN0c1tpXS5sZW5ndGg7IGogPCBqajsgaiArPSAyKSB7CiAgICAgICAgY29uc3QgeCA9IHhyZWYuZmV0Y2hJZlJlZihyYXdJbmtMaXN0c1tpXVtqXSksCiAgICAgICAgICB5ID0geHJlZi5mZXRjaElmUmVmKHJhd0lua0xpc3RzW2ldW2ogKyAxXSk7CiAgICAgICAgaWYgKHR5cGVvZiB4ID09PSAibnVtYmVyIiAmJiB0eXBlb2YgeSA9PT0gIm51bWJlciIpIHsKICAgICAgICAgIGlua0xpc3Rbal0gPSB4OwogICAgICAgICAgaW5rTGlzdFtqICsgMV0gPSB5OwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKCF0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgY29uc3Qgc3Ryb2tlQ29sb3IgPSBnZXRQZGZDb2xvckFycmF5KHRoaXMuY29sb3IsIFswLCAwLCAwXSk7CiAgICAgIGNvbnN0IHN0cm9rZUFscGhhID0gZGljdC5nZXQoIkNBIik7CiAgICAgIGNvbnN0IGJvcmRlcldpZHRoID0gdGhpcy5ib3JkZXJTdHlsZS53aWR0aCB8fCAxLAogICAgICAgIGJvcmRlckFkanVzdCA9IDIgKiBib3JkZXJXaWR0aDsKICAgICAgY29uc3QgYmJveCA9IFtJbmZpbml0eSwgSW5maW5pdHksIC1JbmZpbml0eSwgLUluZmluaXR5XTsKICAgICAgZm9yIChjb25zdCBpbmtMaXN0IG9mIHRoaXMuZGF0YS5pbmtMaXN0cykgewogICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGlua0xpc3QubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICAgICAgVXRpbC5yZWN0Qm91bmRpbmdCb3goaW5rTGlzdFtpXSAtIGJvcmRlckFkanVzdCwgaW5rTGlzdFtpICsgMV0gLSBib3JkZXJBZGp1c3QsIGlua0xpc3RbaV0gKyBib3JkZXJBZGp1c3QsIGlua0xpc3RbaSArIDFdICsgYm9yZGVyQWRqdXN0LCBiYm94KTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKCFVdGlsLmludGVyc2VjdCh0aGlzLnJlY3RhbmdsZSwgYmJveCkpIHsKICAgICAgICB0aGlzLnJlY3RhbmdsZSA9IGJib3g7CiAgICAgIH0KICAgICAgdGhpcy5fc2V0RGVmYXVsdEFwcGVhcmFuY2UoewogICAgICAgIHhyZWYsCiAgICAgICAgZXh0cmE6IGAke2JvcmRlcldpZHRofSB3YCwKICAgICAgICBzdHJva2VDb2xvciwKICAgICAgICBzdHJva2VBbHBoYSwKICAgICAgICBwb2ludHNDYWxsYmFjazogKGJ1ZmZlciwgcG9pbnRzKSA9PiB7CiAgICAgICAgICBmb3IgKGNvbnN0IGlua0xpc3Qgb2YgdGhpcy5kYXRhLmlua0xpc3RzKSB7CiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGlua0xpc3QubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICAgICAgICAgIGJ1ZmZlci5wdXNoKGAke2lua0xpc3RbaV19ICR7aW5rTGlzdFtpICsgMV19ICR7aSA9PT0gMCA/ICJtIiA6ICJsIn1gKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBidWZmZXIucHVzaCgiUyIpOwogICAgICAgICAgfQogICAgICAgICAgcmV0dXJuIFtwb2ludHNbMF0sIHBvaW50c1s3XSwgcG9pbnRzWzJdLCBwb2ludHNbM11dOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9CiAgfQogIHN0YXRpYyBjcmVhdGVOZXdEaWN0KGFubm90YXRpb24sIHhyZWYsIHsKICAgIGFwUmVmLAogICAgYXAKICB9KSB7CiAgICBjb25zdCB7CiAgICAgIG9sZEFubm90YXRpb24sCiAgICAgIGNvbG9yLAogICAgICBkYXRlLAogICAgICBvcGFjaXR5LAogICAgICBwYXRocywKICAgICAgb3V0bGluZXMsCiAgICAgIHJlY3QsCiAgICAgIHJvdGF0aW9uLAogICAgICB0aGlja25lc3MsCiAgICAgIHVzZXIKICAgIH0gPSBhbm5vdGF0aW9uOwogICAgY29uc3QgaW5rID0gb2xkQW5ub3RhdGlvbiB8fCBuZXcgRGljdCh4cmVmKTsKICAgIGluay5zZXRJZk5vdEV4aXN0cygiVHlwZSIsIE5hbWUuZ2V0KCJBbm5vdCIpKTsKICAgIGluay5zZXRJZk5vdEV4aXN0cygiU3VidHlwZSIsIE5hbWUuZ2V0KCJJbmsiKSk7CiAgICBpbmsuc2V0KG9sZEFubm90YXRpb24gPyAiTSIgOiAiQ3JlYXRpb25EYXRlIiwgYEQ6JHtnZXRNb2RpZmljYXRpb25EYXRlKGRhdGUpfWApOwogICAgaW5rLnNldElmQXJyYXkoIlJlY3QiLCByZWN0KTsKICAgIGluay5zZXRJZkFycmF5KCJJbmtMaXN0Iiwgb3V0bGluZXM/LnBvaW50cyB8fCBwYXRocz8ucG9pbnRzKTsKICAgIGluay5zZXRJZk5vdEV4aXN0cygiRiIsIDQpOwogICAgaW5rLnNldElmTnVtYmVyKCJSb3RhdGUiLCByb3RhdGlvbik7CiAgICBpbmsuc2V0SWZEZWZpbmVkKCJUIiwgc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRSh1c2VyKSk7CiAgICBpZiAob3V0bGluZXMpIHsKICAgICAgaW5rLnNldElmTmFtZSgiSVQiLCAiSW5rSGlnaGxpZ2h0Iik7CiAgICB9CiAgICBpZiAodGhpY2tuZXNzID4gMCkgewogICAgICBjb25zdCBicyA9IG5ldyBEaWN0KHhyZWYpOwogICAgICBpbmsuc2V0KCJCUyIsIGJzKTsKICAgICAgYnMuc2V0KCJXIiwgdGhpY2tuZXNzKTsKICAgIH0KICAgIGluay5zZXRJZkFycmF5KCJDIiwgZ2V0UGRmQ29sb3JBcnJheShjb2xvcikpOwogICAgaW5rLnNldElmTnVtYmVyKCJDQSIsIG9wYWNpdHkpOwogICAgaWYgKGFwIHx8IGFwUmVmKSB7CiAgICAgIGNvbnN0IG4gPSBuZXcgRGljdCh4cmVmKTsKICAgICAgaW5rLnNldCgiQVAiLCBuKTsKICAgICAgbi5zZXQoIk4iLCBhcFJlZiB8fCBhcCk7CiAgICB9CiAgICByZXR1cm4gaW5rOwogIH0KICBzdGF0aWMgYXN5bmMgY3JlYXRlTmV3QXBwZWFyYW5jZVN0cmVhbShhbm5vdGF0aW9uLCB4cmVmLCBwYXJhbXMpIHsKICAgIGlmIChhbm5vdGF0aW9uLm91dGxpbmVzKSB7CiAgICAgIHJldHVybiB0aGlzLmNyZWF0ZU5ld0FwcGVhcmFuY2VTdHJlYW1Gb3JIaWdobGlnaHQoYW5ub3RhdGlvbiwgeHJlZiwgcGFyYW1zKTsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgY29sb3IsCiAgICAgIHJlY3QsCiAgICAgIHBhdGhzLAogICAgICB0aGlja25lc3MsCiAgICAgIG9wYWNpdHkKICAgIH0gPSBhbm5vdGF0aW9uOwogICAgaWYgKCFjb2xvcikgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IGFwcGVhcmFuY2VCdWZmZXIgPSBbYCR7dGhpY2tuZXNzfSB3IDEgSiAxIGpgLCBgJHtnZXRQZGZDb2xvcihjb2xvciwgZmFsc2UpfWBdOwogICAgaWYgKG9wYWNpdHkgIT09IDEpIHsKICAgICAgYXBwZWFyYW5jZUJ1ZmZlci5wdXNoKCIvUjAgZ3MiKTsKICAgIH0KICAgIGZvciAoY29uc3Qgb3V0bGluZSBvZiBwYXRocy5saW5lcykgewogICAgICBhcHBlYXJhbmNlQnVmZmVyLnB1c2goYCR7bnVtYmVyVG9TdHJpbmcob3V0bGluZVs0XSl9ICR7bnVtYmVyVG9TdHJpbmcob3V0bGluZVs1XSl9IG1gKTsKICAgICAgZm9yIChsZXQgaSA9IDYsIGlpID0gb3V0bGluZS5sZW5ndGg7IGkgPCBpaTsgaSArPSA2KSB7CiAgICAgICAgaWYgKGlzTmFOKG91dGxpbmVbaV0pKSB7CiAgICAgICAgICBhcHBlYXJhbmNlQnVmZmVyLnB1c2goYCR7bnVtYmVyVG9TdHJpbmcob3V0bGluZVtpICsgNF0pfSAke251bWJlclRvU3RyaW5nKG91dGxpbmVbaSArIDVdKX0gbGApOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb25zdCBbYzF4LCBjMXksIGMyeCwgYzJ5LCB4LCB5XSA9IG91dGxpbmUuc2xpY2UoaSwgaSArIDYpOwogICAgICAgICAgYXBwZWFyYW5jZUJ1ZmZlci5wdXNoKFtjMXgsIGMxeSwgYzJ4LCBjMnksIHgsIHldLm1hcChudW1iZXJUb1N0cmluZykuam9pbigiICIpICsgIiBjIik7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChvdXRsaW5lLmxlbmd0aCA9PT0gNikgewogICAgICAgIGFwcGVhcmFuY2VCdWZmZXIucHVzaChgJHtudW1iZXJUb1N0cmluZyhvdXRsaW5lWzRdKX0gJHtudW1iZXJUb1N0cmluZyhvdXRsaW5lWzVdKX0gbGApOwogICAgICB9CiAgICB9CiAgICBhcHBlYXJhbmNlQnVmZmVyLnB1c2goIlMiKTsKICAgIGNvbnN0IGFwcGVhcmFuY2UgPSBhcHBlYXJhbmNlQnVmZmVyLmpvaW4oIlxuIik7CiAgICBjb25zdCBhcHBlYXJhbmNlU3RyZWFtRGljdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJGb3JtVHlwZSIsIDEpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0SWZOYW1lKCJTdWJ0eXBlIiwgIkZvcm0iKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldElmTmFtZSgiVHlwZSIsICJYT2JqZWN0Iik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkJCb3giLCByZWN0KTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiTGVuZ3RoIiwgYXBwZWFyYW5jZS5sZW5ndGgpOwogICAgaWYgKG9wYWNpdHkgIT09IDEpIHsKICAgICAgY29uc3QgcmVzb3VyY2VzID0gbmV3IERpY3QoeHJlZik7CiAgICAgIGNvbnN0IGV4dEdTdGF0ZSA9IG5ldyBEaWN0KHhyZWYpOwogICAgICBjb25zdCByMCA9IG5ldyBEaWN0KHhyZWYpOwogICAgICByMC5zZXQoIkNBIiwgb3BhY2l0eSk7CiAgICAgIHIwLnNldElmTmFtZSgiVHlwZSIsICJFeHRHU3RhdGUiKTsKICAgICAgZXh0R1N0YXRlLnNldCgiUjAiLCByMCk7CiAgICAgIHJlc291cmNlcy5zZXQoIkV4dEdTdGF0ZSIsIGV4dEdTdGF0ZSk7CiAgICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiUmVzb3VyY2VzIiwgcmVzb3VyY2VzKTsKICAgIH0KICAgIGNvbnN0IGFwID0gbmV3IFN0cmluZ1N0cmVhbShhcHBlYXJhbmNlKTsKICAgIGFwLmRpY3QgPSBhcHBlYXJhbmNlU3RyZWFtRGljdDsKICAgIHJldHVybiBhcDsKICB9CiAgc3RhdGljIGFzeW5jIGNyZWF0ZU5ld0FwcGVhcmFuY2VTdHJlYW1Gb3JIaWdobGlnaHQoYW5ub3RhdGlvbiwgeHJlZiwgcGFyYW1zKSB7CiAgICBjb25zdCB7CiAgICAgIGNvbG9yLAogICAgICByZWN0LAogICAgICBvdXRsaW5lczogewogICAgICAgIG91dGxpbmUKICAgICAgfSwKICAgICAgb3BhY2l0eQogICAgfSA9IGFubm90YXRpb247CiAgICBpZiAoIWNvbG9yKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgYXBwZWFyYW5jZUJ1ZmZlciA9IFtgJHtnZXRQZGZDb2xvcihjb2xvciwgdHJ1ZSl9YCwgIi9SMCBncyJdOwogICAgYXBwZWFyYW5jZUJ1ZmZlci5wdXNoKGAke251bWJlclRvU3RyaW5nKG91dGxpbmVbNF0pfSAke251bWJlclRvU3RyaW5nKG91dGxpbmVbNV0pfSBtYCk7CiAgICBmb3IgKGxldCBpID0gNiwgaWkgPSBvdXRsaW5lLmxlbmd0aDsgaSA8IGlpOyBpICs9IDYpIHsKICAgICAgaWYgKGlzTmFOKG91dGxpbmVbaV0pKSB7CiAgICAgICAgYXBwZWFyYW5jZUJ1ZmZlci5wdXNoKGAke251bWJlclRvU3RyaW5nKG91dGxpbmVbaSArIDRdKX0gJHtudW1iZXJUb1N0cmluZyhvdXRsaW5lW2kgKyA1XSl9IGxgKTsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBbYzF4LCBjMXksIGMyeCwgYzJ5LCB4LCB5XSA9IG91dGxpbmUuc2xpY2UoaSwgaSArIDYpOwogICAgICAgIGFwcGVhcmFuY2VCdWZmZXIucHVzaChbYzF4LCBjMXksIGMyeCwgYzJ5LCB4LCB5XS5tYXAobnVtYmVyVG9TdHJpbmcpLmpvaW4oIiAiKSArICIgYyIpOwogICAgICB9CiAgICB9CiAgICBhcHBlYXJhbmNlQnVmZmVyLnB1c2goImggZiIpOwogICAgY29uc3QgYXBwZWFyYW5jZSA9IGFwcGVhcmFuY2VCdWZmZXIuam9pbigiXG4iKTsKICAgIGNvbnN0IGFwcGVhcmFuY2VTdHJlYW1EaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkZvcm1UeXBlIiwgMSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXRJZk5hbWUoIlN1YnR5cGUiLCAiRm9ybSIpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0SWZOYW1lKCJUeXBlIiwgIlhPYmplY3QiKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiQkJveCIsIHJlY3QpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJMZW5ndGgiLCBhcHBlYXJhbmNlLmxlbmd0aCk7CiAgICBjb25zdCByZXNvdXJjZXMgPSBuZXcgRGljdCh4cmVmKTsKICAgIGNvbnN0IGV4dEdTdGF0ZSA9IG5ldyBEaWN0KHhyZWYpOwogICAgcmVzb3VyY2VzLnNldCgiRXh0R1N0YXRlIiwgZXh0R1N0YXRlKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiUmVzb3VyY2VzIiwgcmVzb3VyY2VzKTsKICAgIGNvbnN0IHIwID0gbmV3IERpY3QoeHJlZik7CiAgICBleHRHU3RhdGUuc2V0KCJSMCIsIHIwKTsKICAgIHIwLnNldElmTmFtZSgiQk0iLCAiTXVsdGlwbHkiKTsKICAgIGlmIChvcGFjaXR5ICE9PSAxKSB7CiAgICAgIHIwLnNldCgiY2EiLCBvcGFjaXR5KTsKICAgICAgcjAuc2V0SWZOYW1lKCJUeXBlIiwgIkV4dEdTdGF0ZSIpOwogICAgfQogICAgY29uc3QgYXAgPSBuZXcgU3RyaW5nU3RyZWFtKGFwcGVhcmFuY2UpOwogICAgYXAuZGljdCA9IGFwcGVhcmFuY2VTdHJlYW1EaWN0OwogICAgcmV0dXJuIGFwOwogIH0KfQpjbGFzcyBIaWdobGlnaHRBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgdGhpcy5kYXRhLmFubm90YXRpb25UeXBlID0gQW5ub3RhdGlvblR5cGUuSElHSExJR0hUOwogICAgdGhpcy5kYXRhLmlzRWRpdGFibGUgPSAhdGhpcy5kYXRhLm5vSFRNTDsKICAgIHRoaXMuZGF0YS5ub0hUTUwgPSBmYWxzZTsKICAgIHRoaXMuZGF0YS5vcGFjaXR5ID0gZGljdC5nZXQoIkNBIikgfHwgMTsKICAgIGNvbnN0IHF1YWRQb2ludHMgPSB0aGlzLmRhdGEucXVhZFBvaW50cyA9IGdldFF1YWRQb2ludHMoZGljdCwgbnVsbCk7CiAgICBpZiAocXVhZFBvaW50cykgewogICAgICBjb25zdCByZXNvdXJjZXMgPSB0aGlzLmFwcGVhcmFuY2U/LmRpY3QuZ2V0KCJSZXNvdXJjZXMiKTsKICAgICAgaWYgKCF0aGlzLmFwcGVhcmFuY2UgfHwgIXJlc291cmNlcz8uaGFzKCJFeHRHU3RhdGUiKSkgewogICAgICAgIGlmICh0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgICAgIHdhcm4oIkhpZ2hsaWdodEFubm90YXRpb24gLSBpZ25vcmluZyBidWlsdC1pbiBhcHBlYXJhbmNlIHN0cmVhbS4iKTsKICAgICAgICB9CiAgICAgICAgY29uc3QgZmlsbENvbG9yID0gZ2V0UGRmQ29sb3JBcnJheSh0aGlzLmNvbG9yLCBbMSwgMSwgMF0pOwogICAgICAgIGNvbnN0IGZpbGxBbHBoYSA9IGRpY3QuZ2V0KCJDQSIpOwogICAgICAgIHRoaXMuX3NldERlZmF1bHRBcHBlYXJhbmNlKHsKICAgICAgICAgIHhyZWYsCiAgICAgICAgICBmaWxsQ29sb3IsCiAgICAgICAgICBibGVuZE1vZGU6ICJNdWx0aXBseSIsCiAgICAgICAgICBmaWxsQWxwaGEsCiAgICAgICAgICBwb2ludHNDYWxsYmFjazogKGJ1ZmZlciwgcG9pbnRzKSA9PiB7CiAgICAgICAgICAgIGJ1ZmZlci5wdXNoKGAke3BvaW50c1swXX0gJHtwb2ludHNbMV19IG1gLCBgJHtwb2ludHNbMl19ICR7cG9pbnRzWzNdfSBsYCwgYCR7cG9pbnRzWzZdfSAke3BvaW50c1s3XX0gbGAsIGAke3BvaW50c1s0XX0gJHtwb2ludHNbNV19IGxgLCAiZiIpOwogICAgICAgICAgICByZXR1cm4gW3BvaW50c1swXSwgcG9pbnRzWzddLCBwb2ludHNbMl0sIHBvaW50c1szXV07CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuZGF0YS5wb3B1cFJlZiA9IG51bGw7CiAgICB9CiAgfQogIGdldCBvdmVybGF5c1RleHRDb250ZW50KCkgewogICAgcmV0dXJuIHRydWU7CiAgfQogIHN0YXRpYyBjcmVhdGVOZXdEaWN0KGFubm90YXRpb24sIHhyZWYsIHsKICAgIGFwUmVmLAogICAgYXAKICB9KSB7CiAgICBjb25zdCB7CiAgICAgIGNvbG9yLAogICAgICBkYXRlLAogICAgICBvbGRBbm5vdGF0aW9uLAogICAgICBvcGFjaXR5LAogICAgICByZWN0LAogICAgICByb3RhdGlvbiwKICAgICAgdXNlciwKICAgICAgcXVhZFBvaW50cwogICAgfSA9IGFubm90YXRpb247CiAgICBjb25zdCBoaWdobGlnaHQgPSBvbGRBbm5vdGF0aW9uIHx8IG5ldyBEaWN0KHhyZWYpOwogICAgaGlnaGxpZ2h0LnNldElmTm90RXhpc3RzKCJUeXBlIiwgTmFtZS5nZXQoIkFubm90IikpOwogICAgaGlnaGxpZ2h0LnNldElmTm90RXhpc3RzKCJTdWJ0eXBlIiwgTmFtZS5nZXQoIkhpZ2hsaWdodCIpKTsKICAgIGhpZ2hsaWdodC5zZXQob2xkQW5ub3RhdGlvbiA/ICJNIiA6ICJDcmVhdGlvbkRhdGUiLCBgRDoke2dldE1vZGlmaWNhdGlvbkRhdGUoZGF0ZSl9YCk7CiAgICBoaWdobGlnaHQuc2V0SWZBcnJheSgiUmVjdCIsIHJlY3QpOwogICAgaGlnaGxpZ2h0LnNldElmTm90RXhpc3RzKCJGIiwgNCk7CiAgICBoaWdobGlnaHQuc2V0SWZOb3RFeGlzdHMoIkJvcmRlciIsIFswLCAwLCAwXSk7CiAgICBoaWdobGlnaHQuc2V0SWZOdW1iZXIoIlJvdGF0ZSIsIHJvdGF0aW9uKTsKICAgIGhpZ2hsaWdodC5zZXRJZkFycmF5KCJRdWFkUG9pbnRzIiwgcXVhZFBvaW50cyk7CiAgICBoaWdobGlnaHQuc2V0SWZBcnJheSgiQyIsIGdldFBkZkNvbG9yQXJyYXkoY29sb3IpKTsKICAgIGhpZ2hsaWdodC5zZXRJZk51bWJlcigiQ0EiLCBvcGFjaXR5KTsKICAgIGhpZ2hsaWdodC5zZXRJZkRlZmluZWQoIlQiLCBzdHJpbmdUb0FzY2lpT3JVVEYxNkJFKHVzZXIpKTsKICAgIGlmIChhcFJlZiB8fCBhcCkgewogICAgICBjb25zdCBuID0gbmV3IERpY3QoeHJlZik7CiAgICAgIGhpZ2hsaWdodC5zZXQoIkFQIiwgbik7CiAgICAgIG4uc2V0KCJOIiwgYXBSZWYgfHwgYXApOwogICAgfQogICAgcmV0dXJuIGhpZ2hsaWdodDsKICB9CiAgc3RhdGljIGFzeW5jIGNyZWF0ZU5ld0FwcGVhcmFuY2VTdHJlYW0oYW5ub3RhdGlvbiwgeHJlZiwgcGFyYW1zKSB7CiAgICBjb25zdCB7CiAgICAgIGNvbG9yLAogICAgICByZWN0LAogICAgICBvdXRsaW5lcywKICAgICAgb3BhY2l0eQogICAgfSA9IGFubm90YXRpb247CiAgICBpZiAoIWNvbG9yKSB7CiAgICAgIHJldHVybiBudWxsOwogICAgfQogICAgY29uc3QgYXBwZWFyYW5jZUJ1ZmZlciA9IFtgJHtnZXRQZGZDb2xvcihjb2xvciwgdHJ1ZSl9YCwgIi9SMCBncyJdOwogICAgY29uc3QgYnVmZmVyID0gW107CiAgICBmb3IgKGNvbnN0IG91dGxpbmUgb2Ygb3V0bGluZXMpIHsKICAgICAgYnVmZmVyLmxlbmd0aCA9IDA7CiAgICAgIGJ1ZmZlci5wdXNoKGAke251bWJlclRvU3RyaW5nKG91dGxpbmVbMF0pfSAke251bWJlclRvU3RyaW5nKG91dGxpbmVbMV0pfSBtYCk7CiAgICAgIGZvciAobGV0IGkgPSAyLCBpaSA9IG91dGxpbmUubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICAgIGJ1ZmZlci5wdXNoKGAke251bWJlclRvU3RyaW5nKG91dGxpbmVbaV0pfSAke251bWJlclRvU3RyaW5nKG91dGxpbmVbaSArIDFdKX0gbGApOwogICAgICB9CiAgICAgIGJ1ZmZlci5wdXNoKCJoIik7CiAgICAgIGFwcGVhcmFuY2VCdWZmZXIucHVzaChidWZmZXIuam9pbigiXG4iKSk7CiAgICB9CiAgICBhcHBlYXJhbmNlQnVmZmVyLnB1c2goImYqIik7CiAgICBjb25zdCBhcHBlYXJhbmNlID0gYXBwZWFyYW5jZUJ1ZmZlci5qb2luKCJcbiIpOwogICAgY29uc3QgYXBwZWFyYW5jZVN0cmVhbURpY3QgPSBuZXcgRGljdCh4cmVmKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiRm9ybVR5cGUiLCAxKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldElmTmFtZSgiU3VidHlwZSIsICJGb3JtIik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXRJZk5hbWUoIlR5cGUiLCAiWE9iamVjdCIpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJCQm94IiwgcmVjdCk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkxlbmd0aCIsIGFwcGVhcmFuY2UubGVuZ3RoKTsKICAgIGNvbnN0IHJlc291cmNlcyA9IG5ldyBEaWN0KHhyZWYpOwogICAgY29uc3QgZXh0R1N0YXRlID0gbmV3IERpY3QoeHJlZik7CiAgICByZXNvdXJjZXMuc2V0KCJFeHRHU3RhdGUiLCBleHRHU3RhdGUpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJSZXNvdXJjZXMiLCByZXNvdXJjZXMpOwogICAgY29uc3QgcjAgPSBuZXcgRGljdCh4cmVmKTsKICAgIGV4dEdTdGF0ZS5zZXQoIlIwIiwgcjApOwogICAgcjAuc2V0SWZOYW1lKCJCTSIsICJNdWx0aXBseSIpOwogICAgaWYgKG9wYWNpdHkgIT09IDEpIHsKICAgICAgcjAuc2V0KCJjYSIsIG9wYWNpdHkpOwogICAgICByMC5zZXRJZk5hbWUoIlR5cGUiLCAiRXh0R1N0YXRlIik7CiAgICB9CiAgICBjb25zdCBhcCA9IG5ldyBTdHJpbmdTdHJlYW0oYXBwZWFyYW5jZSk7CiAgICBhcC5kaWN0ID0gYXBwZWFyYW5jZVN0cmVhbURpY3Q7CiAgICByZXR1cm4gYXA7CiAgfQp9CmNsYXNzIFVuZGVybGluZUFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICBjb25zdCB7CiAgICAgIGRpY3QsCiAgICAgIHhyZWYKICAgIH0gPSBwYXJhbXM7CiAgICB0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGUgPSBBbm5vdGF0aW9uVHlwZS5VTkRFUkxJTkU7CiAgICBjb25zdCBxdWFkUG9pbnRzID0gdGhpcy5kYXRhLnF1YWRQb2ludHMgPSBnZXRRdWFkUG9pbnRzKGRpY3QsIG51bGwpOwogICAgaWYgKHF1YWRQb2ludHMpIHsKICAgICAgaWYgKCF0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgICBjb25zdCBzdHJva2VDb2xvciA9IGdldFBkZkNvbG9yQXJyYXkodGhpcy5jb2xvciwgWzAsIDAsIDBdKTsKICAgICAgICBjb25zdCBzdHJva2VBbHBoYSA9IGRpY3QuZ2V0KCJDQSIpOwogICAgICAgIHRoaXMuX3NldERlZmF1bHRBcHBlYXJhbmNlKHsKICAgICAgICAgIHhyZWYsCiAgICAgICAgICBleHRyYTogIltdIDAgZCAwLjU3MSB3IiwKICAgICAgICAgIHN0cm9rZUNvbG9yLAogICAgICAgICAgc3Ryb2tlQWxwaGEsCiAgICAgICAgICBwb2ludHNDYWxsYmFjazogKGJ1ZmZlciwgcG9pbnRzKSA9PiB7CiAgICAgICAgICAgIGJ1ZmZlci5wdXNoKGAke3BvaW50c1s0XX0gJHtwb2ludHNbNV0gKyAxLjN9IG1gLCBgJHtwb2ludHNbNl19ICR7cG9pbnRzWzddICsgMS4zfSBsYCwgIlMiKTsKICAgICAgICAgICAgcmV0dXJuIFtwb2ludHNbMF0sIHBvaW50c1s3XSwgcG9pbnRzWzJdLCBwb2ludHNbM11dOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzLmRhdGEucG9wdXBSZWYgPSBudWxsOwogICAgfQogIH0KICBnZXQgb3ZlcmxheXNUZXh0Q29udGVudCgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KfQpjbGFzcyBTcXVpZ2dseUFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICBjb25zdCB7CiAgICAgIGRpY3QsCiAgICAgIHhyZWYKICAgIH0gPSBwYXJhbXM7CiAgICB0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGUgPSBBbm5vdGF0aW9uVHlwZS5TUVVJR0dMWTsKICAgIGNvbnN0IHF1YWRQb2ludHMgPSB0aGlzLmRhdGEucXVhZFBvaW50cyA9IGdldFF1YWRQb2ludHMoZGljdCwgbnVsbCk7CiAgICBpZiAocXVhZFBvaW50cykgewogICAgICBpZiAoIXRoaXMuYXBwZWFyYW5jZSkgewogICAgICAgIGNvbnN0IHN0cm9rZUNvbG9yID0gZ2V0UGRmQ29sb3JBcnJheSh0aGlzLmNvbG9yLCBbMCwgMCwgMF0pOwogICAgICAgIGNvbnN0IHN0cm9rZUFscGhhID0gZGljdC5nZXQoIkNBIik7CiAgICAgICAgdGhpcy5fc2V0RGVmYXVsdEFwcGVhcmFuY2UoewogICAgICAgICAgeHJlZiwKICAgICAgICAgIGV4dHJhOiAiW10gMCBkIDEgdyIsCiAgICAgICAgICBzdHJva2VDb2xvciwKICAgICAgICAgIHN0cm9rZUFscGhhLAogICAgICAgICAgcG9pbnRzQ2FsbGJhY2s6IChidWZmZXIsIHBvaW50cykgPT4gewogICAgICAgICAgICBjb25zdCBkeSA9IChwb2ludHNbMV0gLSBwb2ludHNbNV0pIC8gNjsKICAgICAgICAgICAgbGV0IHNoaWZ0ID0gZHk7CiAgICAgICAgICAgIGxldCB4ID0gcG9pbnRzWzRdOwogICAgICAgICAgICBjb25zdCB5ID0gcG9pbnRzWzVdOwogICAgICAgICAgICBjb25zdCB4RW5kID0gcG9pbnRzWzZdOwogICAgICAgICAgICBidWZmZXIucHVzaChgJHt4fSAke3kgKyBzaGlmdH0gbWApOwogICAgICAgICAgICBkbyB7CiAgICAgICAgICAgICAgeCArPSAyOwogICAgICAgICAgICAgIHNoaWZ0ID0gc2hpZnQgPT09IDAgPyBkeSA6IDA7CiAgICAgICAgICAgICAgYnVmZmVyLnB1c2goYCR7eH0gJHt5ICsgc2hpZnR9IGxgKTsKICAgICAgICAgICAgfSB3aGlsZSAoeCA8IHhFbmQpOwogICAgICAgICAgICBidWZmZXIucHVzaCgiUyIpOwogICAgICAgICAgICByZXR1cm4gW3BvaW50c1s0XSwgeSAtIDIgKiBkeSwgeEVuZCwgeSArIDIgKiBkeV07CiAgICAgICAgICB9CiAgICAgICAgfSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuZGF0YS5wb3B1cFJlZiA9IG51bGw7CiAgICB9CiAgfQogIGdldCBvdmVybGF5c1RleHRDb250ZW50KCkgewogICAgcmV0dXJuIHRydWU7CiAgfQp9CmNsYXNzIFN0cmlrZU91dEFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9uIHsKICBjb25zdHJ1Y3RvcihwYXJhbXMpIHsKICAgIHN1cGVyKHBhcmFtcyk7CiAgICBjb25zdCB7CiAgICAgIGRpY3QsCiAgICAgIHhyZWYKICAgIH0gPSBwYXJhbXM7CiAgICB0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGUgPSBBbm5vdGF0aW9uVHlwZS5TVFJJS0VPVVQ7CiAgICBjb25zdCBxdWFkUG9pbnRzID0gdGhpcy5kYXRhLnF1YWRQb2ludHMgPSBnZXRRdWFkUG9pbnRzKGRpY3QsIG51bGwpOwogICAgaWYgKHF1YWRQb2ludHMpIHsKICAgICAgaWYgKCF0aGlzLmFwcGVhcmFuY2UpIHsKICAgICAgICBjb25zdCBzdHJva2VDb2xvciA9IGdldFBkZkNvbG9yQXJyYXkodGhpcy5jb2xvciwgWzAsIDAsIDBdKTsKICAgICAgICBjb25zdCBzdHJva2VBbHBoYSA9IGRpY3QuZ2V0KCJDQSIpOwogICAgICAgIHRoaXMuX3NldERlZmF1bHRBcHBlYXJhbmNlKHsKICAgICAgICAgIHhyZWYsCiAgICAgICAgICBleHRyYTogIltdIDAgZCAxIHciLAogICAgICAgICAgc3Ryb2tlQ29sb3IsCiAgICAgICAgICBzdHJva2VBbHBoYSwKICAgICAgICAgIHBvaW50c0NhbGxiYWNrOiAoYnVmZmVyLCBwb2ludHMpID0+IHsKICAgICAgICAgICAgYnVmZmVyLnB1c2goYCR7KHBvaW50c1swXSArIHBvaW50c1s0XSkgLyAyfSBgICsgYCR7KHBvaW50c1sxXSArIHBvaW50c1s1XSkgLyAyfSBtYCwgYCR7KHBvaW50c1syXSArIHBvaW50c1s2XSkgLyAyfSBgICsgYCR7KHBvaW50c1szXSArIHBvaW50c1s3XSkgLyAyfSBsYCwgIlMiKTsKICAgICAgICAgICAgcmV0dXJuIFtwb2ludHNbMF0sIHBvaW50c1s3XSwgcG9pbnRzWzJdLCBwb2ludHNbM11dOwogICAgICAgICAgfQogICAgICAgIH0pOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICB0aGlzLmRhdGEucG9wdXBSZWYgPSBudWxsOwogICAgfQogIH0KICBnZXQgb3ZlcmxheXNUZXh0Q29udGVudCgpIHsKICAgIHJldHVybiB0cnVlOwogIH0KfQpjbGFzcyBTdGFtcEFubm90YXRpb24gZXh0ZW5kcyBNYXJrdXBBbm5vdGF0aW9uIHsKICAjc2F2ZWRIYXNPd25DYW52YXMgPSBudWxsOwogIGNvbnN0cnVjdG9yKHBhcmFtcykgewogICAgc3VwZXIocGFyYW1zKTsKICAgIHRoaXMuZGF0YS5hbm5vdGF0aW9uVHlwZSA9IEFubm90YXRpb25UeXBlLlNUQU1QOwogICAgdGhpcy5kYXRhLmhhc093bkNhbnZhcyA9IHRoaXMuZGF0YS5ub1JvdGF0ZTsKICAgIHRoaXMuZGF0YS5pc0VkaXRhYmxlID0gIXRoaXMuZGF0YS5ub0hUTUw7CiAgICB0aGlzLmRhdGEubm9IVE1MID0gZmFsc2U7CiAgfQogIG11c3RCZVZpZXdlZFdoZW5FZGl0aW5nKGlzRWRpdGluZywgbW9kaWZpZWRJZHMgPSBudWxsKSB7CiAgICBpZiAoaXNFZGl0aW5nKSB7CiAgICAgIGlmICghdGhpcy5kYXRhLmlzRWRpdGFibGUpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICB0aGlzLiNzYXZlZEhhc093bkNhbnZhcyA/Pz0gdGhpcy5kYXRhLmhhc093bkNhbnZhczsKICAgICAgdGhpcy5kYXRhLmhhc093bkNhbnZhcyA9IHRydWU7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgaWYgKHRoaXMuI3NhdmVkSGFzT3duQ2FudmFzICE9PSBudWxsKSB7CiAgICAgIHRoaXMuZGF0YS5oYXNPd25DYW52YXMgPSB0aGlzLiNzYXZlZEhhc093bkNhbnZhczsKICAgICAgdGhpcy4jc2F2ZWRIYXNPd25DYW52YXMgPSBudWxsOwogICAgfQogICAgcmV0dXJuICFtb2RpZmllZElkcz8uaGFzKHRoaXMuZGF0YS5pZCk7CiAgfQogIHN0YXRpYyBhc3luYyBjcmVhdGVJbWFnZShiaXRtYXAsIHhyZWYpIHsKICAgIGNvbnN0IHsKICAgICAgd2lkdGgsCiAgICAgIGhlaWdodAogICAgfSA9IGJpdG1hcDsKICAgIGNvbnN0IGNhbnZhcyA9IG5ldyBPZmZzY3JlZW5DYW52YXMod2lkdGgsIGhlaWdodCk7CiAgICBjb25zdCBjdHggPSBjYW52YXMuZ2V0Q29udGV4dCgiMmQiLCB7CiAgICAgIGFscGhhOiB0cnVlCiAgICB9KTsKICAgIGN0eC5kcmF3SW1hZ2UoYml0bWFwLCAwLCAwKTsKICAgIGNvbnN0IGRhdGEgPSBjdHguZ2V0SW1hZ2VEYXRhKDAsIDAsIHdpZHRoLCBoZWlnaHQpLmRhdGE7CiAgICBjb25zdCBidWYzMiA9IG5ldyBVaW50MzJBcnJheShkYXRhLmJ1ZmZlcik7CiAgICBjb25zdCBoYXNBbHBoYSA9IGJ1ZjMyLnNvbWUoRmVhdHVyZVRlc3QuaXNMaXR0bGVFbmRpYW4gPyB4ID0+IHggPj4+IDI0ICE9PSAweGZmIDogeCA9PiAoeCAmIDB4ZmYpICE9PSAweGZmKTsKICAgIGlmIChoYXNBbHBoYSkgewogICAgICBjdHguZmlsbFN0eWxlID0gIndoaXRlIjsKICAgICAgY3R4LmZpbGxSZWN0KDAsIDAsIHdpZHRoLCBoZWlnaHQpOwogICAgICBjdHguZHJhd0ltYWdlKGJpdG1hcCwgMCwgMCk7CiAgICB9CiAgICBjb25zdCBqcGVnQnVmZmVyUHJvbWlzZSA9IGNhbnZhcy5jb252ZXJ0VG9CbG9iKHsKICAgICAgdHlwZTogImltYWdlL2pwZWciLAogICAgICBxdWFsaXR5OiAxCiAgICB9KS50aGVuKGJsb2IgPT4gYmxvYi5hcnJheUJ1ZmZlcigpKTsKICAgIGNvbnN0IHhvYmplY3ROYW1lID0gTmFtZS5nZXQoIlhPYmplY3QiKTsKICAgIGNvbnN0IGltYWdlTmFtZSA9IE5hbWUuZ2V0KCJJbWFnZSIpOwogICAgY29uc3QgaW1hZ2UgPSBuZXcgRGljdCh4cmVmKTsKICAgIGltYWdlLnNldCgiVHlwZSIsIHhvYmplY3ROYW1lKTsKICAgIGltYWdlLnNldCgiU3VidHlwZSIsIGltYWdlTmFtZSk7CiAgICBpbWFnZS5zZXQoIkJpdHNQZXJDb21wb25lbnQiLCA4KTsKICAgIGltYWdlLnNldElmTmFtZSgiQ29sb3JTcGFjZSIsICJEZXZpY2VSR0IiKTsKICAgIGltYWdlLnNldElmTmFtZSgiRmlsdGVyIiwgIkRDVERlY29kZSIpOwogICAgaW1hZ2Uuc2V0KCJCQm94IiwgWzAsIDAsIHdpZHRoLCBoZWlnaHRdKTsKICAgIGltYWdlLnNldCgiV2lkdGgiLCB3aWR0aCk7CiAgICBpbWFnZS5zZXQoIkhlaWdodCIsIGhlaWdodCk7CiAgICBsZXQgc21hc2tTdHJlYW0gPSBudWxsOwogICAgaWYgKGhhc0FscGhhKSB7CiAgICAgIGNvbnN0IGFscGhhQnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoYnVmMzIubGVuZ3RoKTsKICAgICAgaWYgKEZlYXR1cmVUZXN0LmlzTGl0dGxlRW5kaWFuKSB7CiAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gYnVmMzIubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgICAgYWxwaGFCdWZmZXJbaV0gPSBidWYzMltpXSA+Pj4gMjQ7CiAgICAgICAgfQogICAgICB9IGVsc2UgewogICAgICAgIGZvciAobGV0IGkgPSAwLCBpaSA9IGJ1ZjMyLmxlbmd0aDsgaSA8IGlpOyBpKyspIHsKICAgICAgICAgIGFscGhhQnVmZmVyW2ldID0gYnVmMzJbaV0gJiAweGZmOwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCBzbWFzayA9IG5ldyBEaWN0KHhyZWYpOwogICAgICBzbWFzay5zZXQoIlR5cGUiLCB4b2JqZWN0TmFtZSk7CiAgICAgIHNtYXNrLnNldCgiU3VidHlwZSIsIGltYWdlTmFtZSk7CiAgICAgIHNtYXNrLnNldCgiQml0c1BlckNvbXBvbmVudCIsIDgpOwogICAgICBzbWFzay5zZXRJZk5hbWUoIkNvbG9yU3BhY2UiLCAiRGV2aWNlR3JheSIpOwogICAgICBzbWFzay5zZXQoIldpZHRoIiwgd2lkdGgpOwogICAgICBzbWFzay5zZXQoIkhlaWdodCIsIGhlaWdodCk7CiAgICAgIHNtYXNrU3RyZWFtID0gbmV3IFN0cmVhbShhbHBoYUJ1ZmZlciwgMCwgMCwgc21hc2spOwogICAgfQogICAgY29uc3QgaW1hZ2VTdHJlYW0gPSBuZXcgU3RyZWFtKGF3YWl0IGpwZWdCdWZmZXJQcm9taXNlLCAwLCAwLCBpbWFnZSk7CiAgICByZXR1cm4gewogICAgICBpbWFnZVN0cmVhbSwKICAgICAgc21hc2tTdHJlYW0sCiAgICAgIHdpZHRoLAogICAgICBoZWlnaHQKICAgIH07CiAgfQogIHN0YXRpYyBjcmVhdGVOZXdEaWN0KGFubm90YXRpb24sIHhyZWYsIHsKICAgIGFwUmVmLAogICAgYXAKICB9KSB7CiAgICBjb25zdCB7CiAgICAgIGRhdGUsCiAgICAgIG9sZEFubm90YXRpb24sCiAgICAgIHJlY3QsCiAgICAgIHJvdGF0aW9uLAogICAgICB1c2VyCiAgICB9ID0gYW5ub3RhdGlvbjsKICAgIGNvbnN0IHN0YW1wID0gb2xkQW5ub3RhdGlvbiB8fCBuZXcgRGljdCh4cmVmKTsKICAgIHN0YW1wLnNldElmTm90RXhpc3RzKCJUeXBlIiwgTmFtZS5nZXQoIkFubm90IikpOwogICAgc3RhbXAuc2V0SWZOb3RFeGlzdHMoIlN1YnR5cGUiLCBOYW1lLmdldCgiU3RhbXAiKSk7CiAgICBzdGFtcC5zZXQob2xkQW5ub3RhdGlvbiA/ICJNIiA6ICJDcmVhdGlvbkRhdGUiLCBgRDoke2dldE1vZGlmaWNhdGlvbkRhdGUoZGF0ZSl9YCk7CiAgICBzdGFtcC5zZXRJZkFycmF5KCJSZWN0IiwgcmVjdCk7CiAgICBzdGFtcC5zZXRJZk5vdEV4aXN0cygiRiIsIDQpOwogICAgc3RhbXAuc2V0SWZOb3RFeGlzdHMoIkJvcmRlciIsIFswLCAwLCAwXSk7CiAgICBzdGFtcC5zZXRJZk51bWJlcigiUm90YXRlIiwgcm90YXRpb24pOwogICAgc3RhbXAuc2V0SWZEZWZpbmVkKCJUIiwgc3RyaW5nVG9Bc2NpaU9yVVRGMTZCRSh1c2VyKSk7CiAgICBpZiAoYXBSZWYgfHwgYXApIHsKICAgICAgY29uc3QgbiA9IG5ldyBEaWN0KHhyZWYpOwogICAgICBzdGFtcC5zZXQoIkFQIiwgbik7CiAgICAgIG4uc2V0KCJOIiwgYXBSZWYgfHwgYXApOwogICAgfQogICAgcmV0dXJuIHN0YW1wOwogIH0KICBzdGF0aWMgYXN5bmMgI2NyZWF0ZU5ld0FwcGVhcmFuY2VTdHJlYW1Gb3JEcmF3aW5nKGFubm90YXRpb24sIHhyZWYpIHsKICAgIGNvbnN0IHsKICAgICAgYXJlQ29udG91cnMsCiAgICAgIGNvbG9yLAogICAgICByZWN0LAogICAgICBsaW5lcywKICAgICAgdGhpY2tuZXNzCiAgICB9ID0gYW5ub3RhdGlvbjsKICAgIGlmICghY29sb3IpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCBhcHBlYXJhbmNlQnVmZmVyID0gW2Ake3RoaWNrbmVzc30gdyAxIEogMSBqYCwgYCR7Z2V0UGRmQ29sb3IoY29sb3IsIGFyZUNvbnRvdXJzKX1gXTsKICAgIGZvciAoY29uc3QgbGluZSBvZiBsaW5lcykgewogICAgICBhcHBlYXJhbmNlQnVmZmVyLnB1c2goYCR7bnVtYmVyVG9TdHJpbmcobGluZVs0XSl9ICR7bnVtYmVyVG9TdHJpbmcobGluZVs1XSl9IG1gKTsKICAgICAgZm9yIChsZXQgaSA9IDYsIGlpID0gbGluZS5sZW5ndGg7IGkgPCBpaTsgaSArPSA2KSB7CiAgICAgICAgaWYgKGlzTmFOKGxpbmVbaV0pKSB7CiAgICAgICAgICBhcHBlYXJhbmNlQnVmZmVyLnB1c2goYCR7bnVtYmVyVG9TdHJpbmcobGluZVtpICsgNF0pfSAke251bWJlclRvU3RyaW5nKGxpbmVbaSArIDVdKX0gbGApOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb25zdCBbYzF4LCBjMXksIGMyeCwgYzJ5LCB4LCB5XSA9IGxpbmUuc2xpY2UoaSwgaSArIDYpOwogICAgICAgICAgYXBwZWFyYW5jZUJ1ZmZlci5wdXNoKFtjMXgsIGMxeSwgYzJ4LCBjMnksIHgsIHldLm1hcChudW1iZXJUb1N0cmluZykuam9pbigiICIpICsgIiBjIik7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChsaW5lLmxlbmd0aCA9PT0gNikgewogICAgICAgIGFwcGVhcmFuY2VCdWZmZXIucHVzaChgJHtudW1iZXJUb1N0cmluZyhsaW5lWzRdKX0gJHtudW1iZXJUb1N0cmluZyhsaW5lWzVdKX0gbGApOwogICAgICB9CiAgICB9CiAgICBhcHBlYXJhbmNlQnVmZmVyLnB1c2goYXJlQ29udG91cnMgPyAiRiIgOiAiUyIpOwogICAgY29uc3QgYXBwZWFyYW5jZSA9IGFwcGVhcmFuY2VCdWZmZXIuam9pbigiXG4iKTsKICAgIGNvbnN0IGFwcGVhcmFuY2VTdHJlYW1EaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXQoIkZvcm1UeXBlIiwgMSk7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXRJZk5hbWUoIlN1YnR5cGUiLCAiRm9ybSIpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0SWZOYW1lKCJUeXBlIiwgIlhPYmplY3QiKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiQkJveCIsIHJlY3QpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJMZW5ndGgiLCBhcHBlYXJhbmNlLmxlbmd0aCk7CiAgICBjb25zdCBhcCA9IG5ldyBTdHJpbmdTdHJlYW0oYXBwZWFyYW5jZSk7CiAgICBhcC5kaWN0ID0gYXBwZWFyYW5jZVN0cmVhbURpY3Q7CiAgICByZXR1cm4gYXA7CiAgfQogIHN0YXRpYyBhc3luYyBjcmVhdGVOZXdBcHBlYXJhbmNlU3RyZWFtKGFubm90YXRpb24sIHhyZWYsIHBhcmFtcykgewogICAgaWYgKGFubm90YXRpb24ub2xkQW5ub3RhdGlvbikgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGlmIChhbm5vdGF0aW9uLmlzU2lnbmF0dXJlKSB7CiAgICAgIHJldHVybiB0aGlzLiNjcmVhdGVOZXdBcHBlYXJhbmNlU3RyZWFtRm9yRHJhd2luZyhhbm5vdGF0aW9uLCB4cmVmKTsKICAgIH0KICAgIGNvbnN0IHsKICAgICAgcm90YXRpb24KICAgIH0gPSBhbm5vdGF0aW9uOwogICAgY29uc3QgewogICAgICBpbWFnZVJlZiwKICAgICAgd2lkdGgsCiAgICAgIGhlaWdodAogICAgfSA9IHBhcmFtcy5pbWFnZTsKICAgIGNvbnN0IHJlc291cmNlcyA9IG5ldyBEaWN0KHhyZWYpOwogICAgY29uc3QgeG9iamVjdCA9IG5ldyBEaWN0KHhyZWYpOwogICAgcmVzb3VyY2VzLnNldCgiWE9iamVjdCIsIHhvYmplY3QpOwogICAgeG9iamVjdC5zZXQoIkltMCIsIGltYWdlUmVmKTsKICAgIGNvbnN0IGFwcGVhcmFuY2UgPSBgcSAke3dpZHRofSAwIDAgJHtoZWlnaHR9IDAgMCBjbSAvSW0wIERvIFFgOwogICAgY29uc3QgYXBwZWFyYW5jZVN0cmVhbURpY3QgPSBuZXcgRGljdCh4cmVmKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiRm9ybVR5cGUiLCAxKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldElmTmFtZSgiU3VidHlwZSIsICJGb3JtIik7CiAgICBhcHBlYXJhbmNlU3RyZWFtRGljdC5zZXRJZk5hbWUoIlR5cGUiLCAiWE9iamVjdCIpOwogICAgYXBwZWFyYW5jZVN0cmVhbURpY3Quc2V0KCJCQm94IiwgWzAsIDAsIHdpZHRoLCBoZWlnaHRdKTsKICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiUmVzb3VyY2VzIiwgcmVzb3VyY2VzKTsKICAgIGlmIChyb3RhdGlvbikgewogICAgICBjb25zdCBtYXRyaXggPSBnZXRSb3RhdGlvbk1hdHJpeChyb3RhdGlvbiwgd2lkdGgsIGhlaWdodCk7CiAgICAgIGFwcGVhcmFuY2VTdHJlYW1EaWN0LnNldCgiTWF0cml4IiwgbWF0cml4KTsKICAgIH0KICAgIGNvbnN0IGFwID0gbmV3IFN0cmluZ1N0cmVhbShhcHBlYXJhbmNlKTsKICAgIGFwLmRpY3QgPSBhcHBlYXJhbmNlU3RyZWFtRGljdDsKICAgIHJldHVybiBhcDsKICB9Cn0KY2xhc3MgRmlsZUF0dGFjaG1lbnRBbm5vdGF0aW9uIGV4dGVuZHMgTWFya3VwQW5ub3RhdGlvbiB7CiAgY29uc3RydWN0b3IocGFyYW1zKSB7CiAgICBzdXBlcihwYXJhbXMpOwogICAgY29uc3QgewogICAgICBkaWN0LAogICAgICB4cmVmCiAgICB9ID0gcGFyYW1zOwogICAgY29uc3QgZmlsZSA9IG5ldyBGaWxlU3BlYyhkaWN0LmdldCgiRlMiKSwgeHJlZik7CiAgICB0aGlzLmRhdGEuYW5ub3RhdGlvblR5cGUgPSBBbm5vdGF0aW9uVHlwZS5GSUxFQVRUQUNITUVOVDsKICAgIHRoaXMuZGF0YS5oYXNPd25DYW52YXMgPSB0aGlzLmRhdGEubm9Sb3RhdGU7CiAgICB0aGlzLmRhdGEubm9IVE1MID0gZmFsc2U7CiAgICB0aGlzLmRhdGEuZmlsZSA9IGZpbGUuc2VyaWFsaXphYmxlOwogICAgY29uc3QgbmFtZSA9IGRpY3QuZ2V0KCJOYW1lIik7CiAgICB0aGlzLmRhdGEubmFtZSA9IG5hbWUgaW5zdGFuY2VvZiBOYW1lID8gc3RyaW5nVG9QREZTdHJpbmcobmFtZS5uYW1lKSA6ICJQdXNoUGluIjsKICAgIGNvbnN0IGZpbGxBbHBoYSA9IGRpY3QuZ2V0KCJjYSIpOwogICAgdGhpcy5kYXRhLmZpbGxBbHBoYSA9IHR5cGVvZiBmaWxsQWxwaGEgPT09ICJudW1iZXIiICYmIGZpbGxBbHBoYSA+PSAwICYmIGZpbGxBbHBoYSA8PSAxID8gZmlsbEFscGhhIDogbnVsbDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2NhbGN1bGF0ZV9tZDUuanMKCgoKCgoKCgoKY29uc3QgUEFSQU1TID0gewogIGdldCByKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiciIsIG5ldyBVaW50OEFycmF5KFs3LCAxMiwgMTcsIDIyLCA3LCAxMiwgMTcsIDIyLCA3LCAxMiwgMTcsIDIyLCA3LCAxMiwgMTcsIDIyLCA1LCA5LCAxNCwgMjAsIDUsIDksIDE0LCAyMCwgNSwgOSwgMTQsIDIwLCA1LCA5LCAxNCwgMjAsIDQsIDExLCAxNiwgMjMsIDQsIDExLCAxNiwgMjMsIDQsIDExLCAxNiwgMjMsIDQsIDExLCAxNiwgMjMsIDYsIDEwLCAxNSwgMjEsIDYsIDEwLCAxNSwgMjEsIDYsIDEwLCAxNSwgMjEsIDYsIDEwLCAxNSwgMjFdKSk7CiAgfSwKICBnZXQgaygpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgImsiLCBuZXcgSW50MzJBcnJheShbLTY4MDg3NjkzNiwgLTM4OTU2NDU4NiwgNjA2MTA1ODE5LCAtMTA0NDUyNTMzMCwgLTE3NjQxODg5NywgMTIwMDA4MDQyNiwgLTE0NzMyMzEzNDEsIC00NTcwNTk4MywgMTc3MDAzNTQxNiwgLTE5NTg0MTQ0MTcsIC00MjA2MywgLTE5OTA0MDQxNjIsIDE4MDQ2MDM2ODIsIC00MDM0MTEwMSwgLTE1MDIwMDIyOTAsIDEyMzY1MzUzMjksIC0xNjU3OTY1MTAsIC0xMDY5NTAxNjMyLCA2NDM3MTc3MTMsIC0zNzM4OTczMDIsIC03MDE1NTg2OTEsIDM4MDE2MDgzLCAtNjYwNDc4MzM1LCAtNDA1NTM3ODQ4LCA1Njg0NDY0MzgsIC0xMDE5ODAzNjkwLCAtMTg3MzYzOTYxLCAxMTYzNTMxNTAxLCAtMTQ0NDY4MTQ2NywgLTUxNDAzNzg0LCAxNzM1MzI4NDczLCAtMTkyNjYwNzczNCwgLTM3ODU1OCwgLTIwMjI1NzQ0NjMsIDE4MzkwMzA1NjIsIC0zNTMwOTU1NiwgLTE1MzA5OTIwNjAsIDEyNzI4OTMzNTMsIC0xNTU0OTc2MzIsIC0xMDk0NzMwNjQwLCA2ODEyNzkxNzQsIC0zNTg1MzcyMjIsIC03MjI1MjE5NzksIDc2MDI5MTg5LCAtNjQwMzY0NDg3LCAtNDIxODE1ODM1LCA1MzA3NDI1MjAsIC05OTUzMzg2NTEsIC0xOTg2MzA4NDQsIDExMjY4OTE0MTUsIC0xNDE2MzU0OTA1LCAtNTc0MzQwNTUsIDE3MDA0ODU1NzEsIC0xODk0OTg2NjA2LCAtMTA1MTUyMywgLTIwNTQ5MjI3OTksIDE4NzMzMTMzNTksIC0zMDYxMTc0NCwgLTE1NjAxOTgzODAsIDEzMDkxNTE2NDksIC0xNDU1MjMwNzAsIC0xMTIwMjEwMzc5LCA3MTg3ODcyNTksIC0zNDM0ODU1NTFdKSk7CiAgfQp9OwpmdW5jdGlvbiBjYWxjdWxhdGVNRDUoZGF0YSwgb2Zmc2V0LCBsZW5ndGgpIHsKICBsZXQgaDAgPSAxNzMyNTg0MTkzLAogICAgaDEgPSAtMjcxNzMzODc5LAogICAgaDIgPSAtMTczMjU4NDE5NCwKICAgIGgzID0gMjcxNzMzODc4OwogIGNvbnN0IHBhZGRlZExlbmd0aCA9IGxlbmd0aCArIDcyICYgfjYzOwogIGNvbnN0IHBhZGRlZCA9IG5ldyBVaW50OEFycmF5KHBhZGRlZExlbmd0aCk7CiAgbGV0IGksIGo7CiAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7CiAgICBwYWRkZWRbaV0gPSBkYXRhW29mZnNldCsrXTsKICB9CiAgcGFkZGVkW2krK10gPSAweDgwOwogIGNvbnN0IG4gPSBwYWRkZWRMZW5ndGggLSA4OwogIGlmIChpIDwgbikgewogICAgaSA9IG47CiAgfQogIHBhZGRlZFtpKytdID0gbGVuZ3RoIDw8IDMgJiAweGZmOwogIHBhZGRlZFtpKytdID0gbGVuZ3RoID4+IDUgJiAweGZmOwogIHBhZGRlZFtpKytdID0gbGVuZ3RoID4+IDEzICYgMHhmZjsKICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA+PiAyMSAmIDB4ZmY7CiAgcGFkZGVkW2krK10gPSBsZW5ndGggPj4+IDI5ICYgMHhmZjsKICBpICs9IDM7CiAgY29uc3QgdyA9IG5ldyBJbnQzMkFycmF5KDE2KTsKICBjb25zdCB7CiAgICBrLAogICAgcgogIH0gPSBQQVJBTVM7CiAgZm9yIChpID0gMDsgaSA8IHBhZGRlZExlbmd0aDspIHsKICAgIGZvciAoaiA9IDA7IGogPCAxNjsgKytqLCBpICs9IDQpIHsKICAgICAgd1tqXSA9IHBhZGRlZFtpXSB8IHBhZGRlZFtpICsgMV0gPDwgOCB8IHBhZGRlZFtpICsgMl0gPDwgMTYgfCBwYWRkZWRbaSArIDNdIDw8IDI0OwogICAgfQogICAgbGV0IGEgPSBoMCwKICAgICAgYiA9IGgxLAogICAgICBjID0gaDIsCiAgICAgIGQgPSBoMywKICAgICAgZiwKICAgICAgZzsKICAgIGZvciAoaiA9IDA7IGogPCA2NDsgKytqKSB7CiAgICAgIGlmIChqIDwgMTYpIHsKICAgICAgICBmID0gYiAmIGMgfCB+YiAmIGQ7CiAgICAgICAgZyA9IGo7CiAgICAgIH0gZWxzZSBpZiAoaiA8IDMyKSB7CiAgICAgICAgZiA9IGQgJiBiIHwgfmQgJiBjOwogICAgICAgIGcgPSA1ICogaiArIDEgJiAxNTsKICAgICAgfSBlbHNlIGlmIChqIDwgNDgpIHsKICAgICAgICBmID0gYiBeIGMgXiBkOwogICAgICAgIGcgPSAzICogaiArIDUgJiAxNTsKICAgICAgfSBlbHNlIHsKICAgICAgICBmID0gYyBeIChiIHwgfmQpOwogICAgICAgIGcgPSA3ICogaiAmIDE1OwogICAgICB9CiAgICAgIGNvbnN0IHRtcCA9IGQsCiAgICAgICAgcm90YXRlQXJnID0gYSArIGYgKyBrW2pdICsgd1tnXSB8IDAsCiAgICAgICAgcm90YXRlID0gcltqXTsKICAgICAgZCA9IGM7CiAgICAgIGMgPSBiOwogICAgICBiID0gYiArIChyb3RhdGVBcmcgPDwgcm90YXRlIHwgcm90YXRlQXJnID4+PiAzMiAtIHJvdGF0ZSkgfCAwOwogICAgICBhID0gdG1wOwogICAgfQogICAgaDAgPSBoMCArIGEgfCAwOwogICAgaDEgPSBoMSArIGIgfCAwOwogICAgaDIgPSBoMiArIGMgfCAwOwogICAgaDMgPSBoMyArIGQgfCAwOwogIH0KICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW2gwICYgMHhGRiwgaDAgPj4gOCAmIDB4RkYsIGgwID4+IDE2ICYgMHhGRiwgaDAgPj4+IDI0ICYgMHhGRiwgaDEgJiAweEZGLCBoMSA+PiA4ICYgMHhGRiwgaDEgPj4gMTYgJiAweEZGLCBoMSA+Pj4gMjQgJiAweEZGLCBoMiAmIDB4RkYsIGgyID4+IDggJiAweEZGLCBoMiA+PiAxNiAmIDB4RkYsIGgyID4+PiAyNCAmIDB4RkYsIGgzICYgMHhGRiwgaDMgPj4gOCAmIDB4RkYsIGgzID4+IDE2ICYgMHhGRiwgaDMgPj4+IDI0ICYgMHhGRl0pOwp9Cgo7Ly8gLi9zcmMvY29yZS9kYXRhc2V0X3JlYWRlci5qcwoKCgoKCmZ1bmN0aW9uIGRlY29kZVN0cmluZyhzdHIpIHsKICB0cnkgewogICAgcmV0dXJuIHN0cmluZ1RvVVRGOFN0cmluZyhzdHIpOwogIH0gY2F0Y2ggKGV4KSB7CiAgICB3YXJuKGBVVEYtOCBkZWNvZGluZyBmYWlsZWQ6ICIke2V4fSIuYCk7CiAgICByZXR1cm4gc3RyOwogIH0KfQpjbGFzcyBEYXRhc2V0WE1MUGFyc2VyIGV4dGVuZHMgU2ltcGxlWE1MUGFyc2VyIHsKICBjb25zdHJ1Y3RvcihvcHRpb25zKSB7CiAgICBzdXBlcihvcHRpb25zKTsKICAgIHRoaXMubm9kZSA9IG51bGw7CiAgfQogIG9uRW5kRWxlbWVudChuYW1lKSB7CiAgICBjb25zdCBub2RlID0gc3VwZXIub25FbmRFbGVtZW50KG5hbWUpOwogICAgaWYgKG5vZGUgJiYgbmFtZSA9PT0gInhmYTpkYXRhc2V0cyIpIHsKICAgICAgdGhpcy5ub2RlID0gbm9kZTsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJBYm9ydGluZyBEYXRhc2V0WE1MUGFyc2VyLiIpOwogICAgfQogIH0KfQpjbGFzcyBEYXRhc2V0UmVhZGVyIHsKICBjb25zdHJ1Y3RvcihkYXRhKSB7CiAgICBpZiAoZGF0YS5kYXRhc2V0cykgewogICAgICB0aGlzLm5vZGUgPSBuZXcgU2ltcGxlWE1MUGFyc2VyKHsKICAgICAgICBoYXNBdHRyaWJ1dGVzOiB0cnVlCiAgICAgIH0pLnBhcnNlRnJvbVN0cmluZyhkYXRhLmRhdGFzZXRzKS5kb2N1bWVudEVsZW1lbnQ7CiAgICB9IGVsc2UgewogICAgICBjb25zdCBwYXJzZXIgPSBuZXcgRGF0YXNldFhNTFBhcnNlcih7CiAgICAgICAgaGFzQXR0cmlidXRlczogdHJ1ZQogICAgICB9KTsKICAgICAgdHJ5IHsKICAgICAgICBwYXJzZXIucGFyc2VGcm9tU3RyaW5nKGRhdGFbInhkcDp4ZHAiXSk7CiAgICAgIH0gY2F0Y2gge30KICAgICAgdGhpcy5ub2RlID0gcGFyc2VyLm5vZGU7CiAgICB9CiAgfQogIGdldFZhbHVlKHBhdGgpIHsKICAgIGlmICghdGhpcy5ub2RlIHx8ICFwYXRoKSB7CiAgICAgIHJldHVybiAiIjsKICAgIH0KICAgIGNvbnN0IG5vZGUgPSB0aGlzLm5vZGUuc2VhcmNoTm9kZShwYXJzZVhGQVBhdGgocGF0aCksIDApOwogICAgaWYgKCFub2RlKSB7CiAgICAgIHJldHVybiAiIjsKICAgIH0KICAgIGNvbnN0IGZpcnN0ID0gbm9kZS5maXJzdENoaWxkOwogICAgaWYgKGZpcnN0Py5ub2RlTmFtZSA9PT0gInZhbHVlIikgewogICAgICByZXR1cm4gbm9kZS5jaGlsZHJlbi5tYXAoY2hpbGQgPT4gZGVjb2RlU3RyaW5nKGNoaWxkLnRleHRDb250ZW50KSk7CiAgICB9CiAgICByZXR1cm4gZGVjb2RlU3RyaW5nKG5vZGUudGV4dENvbnRlbnQpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvaW50ZXJzZWN0b3IuanMKCgoKCgoKCgpjbGFzcyBTaW5nbGVJbnRlcnNlY3RvciB7CiAgI2Fubm90YXRpb247CiAgI21pblggPSBJbmZpbml0eTsKICAjbWluWSA9IEluZmluaXR5OwogICNtYXhYID0gLUluZmluaXR5OwogICNtYXhZID0gLUluZmluaXR5OwogICNxdWFkUG9pbnRzID0gbnVsbDsKICAjdGV4dCA9IFtdOwogICNleHRyYUNoYXJzID0gW107CiAgI2xhc3RJbnRlcnNlY3RpbmdRdWFkSW5kZXggPSAtMTsKICAjY2FuVGFrZUV4dHJhQ2hhcnMgPSBmYWxzZTsKICBjb25zdHJ1Y3Rvcihhbm5vdGF0aW9uKSB7CiAgICB0aGlzLiNhbm5vdGF0aW9uID0gYW5ub3RhdGlvbjsKICAgIGNvbnN0IHF1YWRQb2ludHMgPSBhbm5vdGF0aW9uLmRhdGEucXVhZFBvaW50czsKICAgIGlmICghcXVhZFBvaW50cykgewogICAgICBbdGhpcy4jbWluWCwgdGhpcy4jbWluWSwgdGhpcy4jbWF4WCwgdGhpcy4jbWF4WV0gPSBhbm5vdGF0aW9uLmRhdGEucmVjdDsKICAgICAgcmV0dXJuOwogICAgfQogICAgZm9yIChsZXQgaSA9IDAsIGlpID0gcXVhZFBvaW50cy5sZW5ndGg7IGkgPCBpaTsgaSArPSA4KSB7CiAgICAgIHRoaXMuI21pblggPSBNYXRoLm1pbih0aGlzLiNtaW5YLCBxdWFkUG9pbnRzW2ldKTsKICAgICAgdGhpcy4jbWF4WCA9IE1hdGgubWF4KHRoaXMuI21heFgsIHF1YWRQb2ludHNbaSArIDJdKTsKICAgICAgdGhpcy4jbWluWSA9IE1hdGgubWluKHRoaXMuI21pblksIHF1YWRQb2ludHNbaSArIDVdKTsKICAgICAgdGhpcy4jbWF4WSA9IE1hdGgubWF4KHRoaXMuI21heFksIHF1YWRQb2ludHNbaSArIDFdKTsKICAgIH0KICAgIGlmIChxdWFkUG9pbnRzLmxlbmd0aCA+IDgpIHsKICAgICAgdGhpcy4jcXVhZFBvaW50cyA9IHF1YWRQb2ludHM7CiAgICB9CiAgfQogIG92ZXJsYXBzKG90aGVyKSB7CiAgICByZXR1cm4gISh0aGlzLiNtaW5YID49IG90aGVyLiNtYXhYIHx8IHRoaXMuI21heFggPD0gb3RoZXIuI21pblggfHwgdGhpcy4jbWluWSA+PSBvdGhlci4jbWF4WSB8fCB0aGlzLiNtYXhZIDw9IG90aGVyLiNtaW5ZKTsKICB9CiAgI2ludGVyc2VjdHMoeCwgeSkgewogICAgaWYgKHRoaXMuI21pblggPj0geCB8fCB0aGlzLiNtYXhYIDw9IHggfHwgdGhpcy4jbWluWSA+PSB5IHx8IHRoaXMuI21heFkgPD0geSkgewogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBjb25zdCBxdWFkUG9pbnRzID0gdGhpcy4jcXVhZFBvaW50czsKICAgIGlmICghcXVhZFBvaW50cykgewogICAgICByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIGlmICh0aGlzLiNsYXN0SW50ZXJzZWN0aW5nUXVhZEluZGV4ID49IDApIHsKICAgICAgY29uc3QgaSA9IHRoaXMuI2xhc3RJbnRlcnNlY3RpbmdRdWFkSW5kZXg7CiAgICAgIGlmICghKHF1YWRQb2ludHNbaV0gPj0geCB8fCBxdWFkUG9pbnRzW2kgKyAyXSA8PSB4IHx8IHF1YWRQb2ludHNbaSArIDVdID49IHkgfHwgcXVhZFBvaW50c1tpICsgMV0gPD0geSkpIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICB0aGlzLiNsYXN0SW50ZXJzZWN0aW5nUXVhZEluZGV4ID0gLTE7CiAgICB9CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSBxdWFkUG9pbnRzLmxlbmd0aDsgaSA8IGlpOyBpICs9IDgpIHsKICAgICAgaWYgKCEocXVhZFBvaW50c1tpXSA+PSB4IHx8IHF1YWRQb2ludHNbaSArIDJdIDw9IHggfHwgcXVhZFBvaW50c1tpICsgNV0gPj0geSB8fCBxdWFkUG9pbnRzW2kgKyAxXSA8PSB5KSkgewogICAgICAgIHRoaXMuI2xhc3RJbnRlcnNlY3RpbmdRdWFkSW5kZXggPSBpOwogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gZmFsc2U7CiAgfQogIGFkZEdseXBoKHgsIHksIGdseXBoKSB7CiAgICBpZiAoIXRoaXMuI2ludGVyc2VjdHMoeCwgeSkpIHsKICAgICAgdGhpcy5kaXNhYmxlRXh0cmFDaGFycygpOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpcy4jZXh0cmFDaGFycy5sZW5ndGggPiAwKSB7CiAgICAgIHRoaXMuI3RleHQucHVzaCh0aGlzLiNleHRyYUNoYXJzLmpvaW4oIiIpKTsKICAgICAgdGhpcy4jZXh0cmFDaGFycy5sZW5ndGggPSAwOwogICAgfQogICAgdGhpcy4jdGV4dC5wdXNoKGdseXBoKTsKICAgIHRoaXMuI2NhblRha2VFeHRyYUNoYXJzID0gdHJ1ZTsKICAgIHJldHVybiB0cnVlOwogIH0KICBhZGRFeHRyYUNoYXIoY2hhcikgewogICAgaWYgKHRoaXMuI2NhblRha2VFeHRyYUNoYXJzKSB7CiAgICAgIHRoaXMuI2V4dHJhQ2hhcnMucHVzaChjaGFyKTsKICAgIH0KICB9CiAgZGlzYWJsZUV4dHJhQ2hhcnMoKSB7CiAgICBpZiAoIXRoaXMuI2NhblRha2VFeHRyYUNoYXJzKSB7CiAgICAgIHJldHVybjsKICAgIH0KICAgIHRoaXMuI2NhblRha2VFeHRyYUNoYXJzID0gZmFsc2U7CiAgICB0aGlzLiNleHRyYUNoYXJzLmxlbmd0aCA9IDA7CiAgfQogIHNldFRleHQoKSB7CiAgICB0aGlzLiNhbm5vdGF0aW9uLmRhdGEub3ZlcmxhaWRUZXh0ID0gdGhpcy4jdGV4dC5qb2luKCIiKTsKICB9Cn0KY2xhc3MgSW50ZXJzZWN0b3IgewogICNpbnRlcnNlY3RvcnMgPSBuZXcgTWFwKCk7CiAgY29uc3RydWN0b3IoYW5ub3RhdGlvbnMpIHsKICAgIGZvciAoY29uc3QgYW5ub3RhdGlvbiBvZiBhbm5vdGF0aW9ucykgewogICAgICBpZiAoIWFubm90YXRpb24uZGF0YS5xdWFkUG9pbnRzICYmICFhbm5vdGF0aW9uLmRhdGEucmVjdCkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGludGVyc2VjdG9yID0gbmV3IFNpbmdsZUludGVyc2VjdG9yKGFubm90YXRpb24pOwogICAgICBmb3IgKGNvbnN0IFtvdGhlckludGVyc2VjdG9yLCBvdmVybGFwcGluZ10gb2YgdGhpcy4jaW50ZXJzZWN0b3JzKSB7CiAgICAgICAgaWYgKG90aGVySW50ZXJzZWN0b3Iub3ZlcmxhcHMoaW50ZXJzZWN0b3IpKSB7CiAgICAgICAgICBpZiAoIW92ZXJsYXBwaW5nKSB7CiAgICAgICAgICAgIHRoaXMuI2ludGVyc2VjdG9ycy5zZXQob3RoZXJJbnRlcnNlY3RvciwgbmV3IFNldChbaW50ZXJzZWN0b3JdKSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBvdmVybGFwcGluZy5hZGQoaW50ZXJzZWN0b3IpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgICB0aGlzLiNpbnRlcnNlY3RvcnMuc2V0KGludGVyc2VjdG9yLCBudWxsKTsKICAgIH0KICB9CiAgYWRkR2x5cGgodHJhbnNmb3JtLCB3aWR0aCwgaGVpZ2h0LCBnbHlwaCkgewogICAgY29uc3QgeCA9IHRyYW5zZm9ybVs0XSArIHdpZHRoIC8gMjsKICAgIGNvbnN0IHkgPSB0cmFuc2Zvcm1bNV0gKyBoZWlnaHQgLyAyOwogICAgbGV0IG92ZXJsYXBwaW5nSW50ZXJzZWN0b3JzOwogICAgZm9yIChjb25zdCBbaW50ZXJzZWN0b3IsIG92ZXJsYXBwaW5nXSBvZiB0aGlzLiNpbnRlcnNlY3RvcnMpIHsKICAgICAgaWYgKG92ZXJsYXBwaW5nSW50ZXJzZWN0b3JzKSB7CiAgICAgICAgaWYgKG92ZXJsYXBwaW5nSW50ZXJzZWN0b3JzLmhhcyhpbnRlcnNlY3RvcikpIHsKICAgICAgICAgIGludGVyc2VjdG9yLmFkZEdseXBoKHgsIHksIGdseXBoKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaW50ZXJzZWN0b3IuZGlzYWJsZUV4dHJhQ2hhcnMoKTsKICAgICAgICB9CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgaWYgKCFpbnRlcnNlY3Rvci5hZGRHbHlwaCh4LCB5LCBnbHlwaCkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBvdmVybGFwcGluZ0ludGVyc2VjdG9ycyA9IG92ZXJsYXBwaW5nOwogICAgfQogIH0KICBhZGRFeHRyYUNoYXIoY2hhcikgewogICAgZm9yIChjb25zdCBpbnRlcnNlY3RvciBvZiB0aGlzLiNpbnRlcnNlY3RvcnMua2V5cygpKSB7CiAgICAgIGludGVyc2VjdG9yLmFkZEV4dHJhQ2hhcihjaGFyKTsKICAgIH0KICB9CiAgc2V0VGV4dCgpIHsKICAgIGZvciAoY29uc3QgaW50ZXJzZWN0b3Igb2YgdGhpcy4jaW50ZXJzZWN0b3JzLmtleXMoKSkgewogICAgICBpbnRlcnNlY3Rvci5zZXRUZXh0KCk7CiAgICB9CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS9jYWxjdWxhdGVfc2hhX290aGVyLmpzCgoKCgoKCgoKCmNsYXNzIFdvcmQ2NCB7CiAgY29uc3RydWN0b3IoaGlnaEludGVnZXIsIGxvd0ludGVnZXIpIHsKICAgIHRoaXMuaGlnaCA9IGhpZ2hJbnRlZ2VyIHwgMDsKICAgIHRoaXMubG93ID0gbG93SW50ZWdlciB8IDA7CiAgfQogIGFuZCh3b3JkKSB7CiAgICB0aGlzLmhpZ2ggJj0gd29yZC5oaWdoOwogICAgdGhpcy5sb3cgJj0gd29yZC5sb3c7CiAgfQogIHhvcih3b3JkKSB7CiAgICB0aGlzLmhpZ2ggXj0gd29yZC5oaWdoOwogICAgdGhpcy5sb3cgXj0gd29yZC5sb3c7CiAgfQogIHNoaWZ0UmlnaHQocGxhY2VzKSB7CiAgICBpZiAocGxhY2VzID49IDMyKSB7CiAgICAgIHRoaXMubG93ID0gdGhpcy5oaWdoID4+PiBwbGFjZXMgLSAzMiB8IDA7CiAgICAgIHRoaXMuaGlnaCA9IDA7CiAgICB9IGVsc2UgewogICAgICB0aGlzLmxvdyA9IHRoaXMubG93ID4+PiBwbGFjZXMgfCB0aGlzLmhpZ2ggPDwgMzIgLSBwbGFjZXM7CiAgICAgIHRoaXMuaGlnaCA9IHRoaXMuaGlnaCA+Pj4gcGxhY2VzIHwgMDsKICAgIH0KICB9CiAgcm90YXRlUmlnaHQocGxhY2VzKSB7CiAgICBsZXQgbG93LCBoaWdoOwogICAgaWYgKHBsYWNlcyAmIDMyKSB7CiAgICAgIGhpZ2ggPSB0aGlzLmxvdzsKICAgICAgbG93ID0gdGhpcy5oaWdoOwogICAgfSBlbHNlIHsKICAgICAgbG93ID0gdGhpcy5sb3c7CiAgICAgIGhpZ2ggPSB0aGlzLmhpZ2g7CiAgICB9CiAgICBwbGFjZXMgJj0gMzE7CiAgICB0aGlzLmxvdyA9IGxvdyA+Pj4gcGxhY2VzIHwgaGlnaCA8PCAzMiAtIHBsYWNlczsKICAgIHRoaXMuaGlnaCA9IGhpZ2ggPj4+IHBsYWNlcyB8IGxvdyA8PCAzMiAtIHBsYWNlczsKICB9CiAgbm90KCkgewogICAgdGhpcy5oaWdoID0gfnRoaXMuaGlnaDsKICAgIHRoaXMubG93ID0gfnRoaXMubG93OwogIH0KICBhZGQod29yZCkgewogICAgY29uc3QgbG93QWRkID0gKHRoaXMubG93ID4+PiAwKSArICh3b3JkLmxvdyA+Pj4gMCk7CiAgICBsZXQgaGlnaEFkZCA9ICh0aGlzLmhpZ2ggPj4+IDApICsgKHdvcmQuaGlnaCA+Pj4gMCk7CiAgICBpZiAobG93QWRkID4gMHhmZmZmZmZmZikgewogICAgICBoaWdoQWRkICs9IDE7CiAgICB9CiAgICB0aGlzLmxvdyA9IGxvd0FkZCB8IDA7CiAgICB0aGlzLmhpZ2ggPSBoaWdoQWRkIHwgMDsKICB9CiAgY29weVRvKGJ5dGVzLCBvZmZzZXQpIHsKICAgIGJ5dGVzW29mZnNldF0gPSB0aGlzLmhpZ2ggPj4+IDI0ICYgMHhmZjsKICAgIGJ5dGVzW29mZnNldCArIDFdID0gdGhpcy5oaWdoID4+IDE2ICYgMHhmZjsKICAgIGJ5dGVzW29mZnNldCArIDJdID0gdGhpcy5oaWdoID4+IDggJiAweGZmOwogICAgYnl0ZXNbb2Zmc2V0ICsgM10gPSB0aGlzLmhpZ2ggJiAweGZmOwogICAgYnl0ZXNbb2Zmc2V0ICsgNF0gPSB0aGlzLmxvdyA+Pj4gMjQgJiAweGZmOwogICAgYnl0ZXNbb2Zmc2V0ICsgNV0gPSB0aGlzLmxvdyA+PiAxNiAmIDB4ZmY7CiAgICBieXRlc1tvZmZzZXQgKyA2XSA9IHRoaXMubG93ID4+IDggJiAweGZmOwogICAgYnl0ZXNbb2Zmc2V0ICsgN10gPSB0aGlzLmxvdyAmIDB4ZmY7CiAgfQogIGFzc2lnbih3b3JkKSB7CiAgICB0aGlzLmhpZ2ggPSB3b3JkLmhpZ2g7CiAgICB0aGlzLmxvdyA9IHdvcmQubG93OwogIH0KfQpjb25zdCBjYWxjdWxhdGVfc2hhX290aGVyX1BBUkFNUyA9IHsKICBnZXQgaygpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgImsiLCBbbmV3IFdvcmQ2NCgweDQyOGEyZjk4LCAweGQ3MjhhZTIyKSwgbmV3IFdvcmQ2NCgweDcxMzc0NDkxLCAweDIzZWY2NWNkKSwgbmV3IFdvcmQ2NCgweGI1YzBmYmNmLCAweGVjNGQzYjJmKSwgbmV3IFdvcmQ2NCgweGU5YjVkYmE1LCAweDgxODlkYmJjKSwgbmV3IFdvcmQ2NCgweDM5NTZjMjViLCAweGYzNDhiNTM4KSwgbmV3IFdvcmQ2NCgweDU5ZjExMWYxLCAweGI2MDVkMDE5KSwgbmV3IFdvcmQ2NCgweDkyM2Y4MmE0LCAweGFmMTk0ZjliKSwgbmV3IFdvcmQ2NCgweGFiMWM1ZWQ1LCAweGRhNmQ4MTE4KSwgbmV3IFdvcmQ2NCgweGQ4MDdhYTk4LCAweGEzMDMwMjQyKSwgbmV3IFdvcmQ2NCgweDEyODM1YjAxLCAweDQ1NzA2ZmJlKSwgbmV3IFdvcmQ2NCgweDI0MzE4NWJlLCAweDRlZTRiMjhjKSwgbmV3IFdvcmQ2NCgweDU1MGM3ZGMzLCAweGQ1ZmZiNGUyKSwgbmV3IFdvcmQ2NCgweDcyYmU1ZDc0LCAweGYyN2I4OTZmKSwgbmV3IFdvcmQ2NCgweDgwZGViMWZlLCAweDNiMTY5NmIxKSwgbmV3IFdvcmQ2NCgweDliZGMwNmE3LCAweDI1YzcxMjM1KSwgbmV3IFdvcmQ2NCgweGMxOWJmMTc0LCAweGNmNjkyNjk0KSwgbmV3IFdvcmQ2NCgweGU0OWI2OWMxLCAweDllZjE0YWQyKSwgbmV3IFdvcmQ2NCgweGVmYmU0Nzg2LCAweDM4NGYyNWUzKSwgbmV3IFdvcmQ2NCgweDBmYzE5ZGM2LCAweDhiOGNkNWI1KSwgbmV3IFdvcmQ2NCgweDI0MGNhMWNjLCAweDc3YWM5YzY1KSwgbmV3IFdvcmQ2NCgweDJkZTkyYzZmLCAweDU5MmIwMjc1KSwgbmV3IFdvcmQ2NCgweDRhNzQ4NGFhLCAweDZlYTZlNDgzKSwgbmV3IFdvcmQ2NCgweDVjYjBhOWRjLCAweGJkNDFmYmQ0KSwgbmV3IFdvcmQ2NCgweDc2Zjk4OGRhLCAweDgzMTE1M2I1KSwgbmV3IFdvcmQ2NCgweDk4M2U1MTUyLCAweGVlNjZkZmFiKSwgbmV3IFdvcmQ2NCgweGE4MzFjNjZkLCAweDJkYjQzMjEwKSwgbmV3IFdvcmQ2NCgweGIwMDMyN2M4LCAweDk4ZmIyMTNmKSwgbmV3IFdvcmQ2NCgweGJmNTk3ZmM3LCAweGJlZWYwZWU0KSwgbmV3IFdvcmQ2NCgweGM2ZTAwYmYzLCAweDNkYTg4ZmMyKSwgbmV3IFdvcmQ2NCgweGQ1YTc5MTQ3LCAweDkzMGFhNzI1KSwgbmV3IFdvcmQ2NCgweDA2Y2E2MzUxLCAweGUwMDM4MjZmKSwgbmV3IFdvcmQ2NCgweDE0MjkyOTY3LCAweDBhMGU2ZTcwKSwgbmV3IFdvcmQ2NCgweDI3YjcwYTg1LCAweDQ2ZDIyZmZjKSwgbmV3IFdvcmQ2NCgweDJlMWIyMTM4LCAweDVjMjZjOTI2KSwgbmV3IFdvcmQ2NCgweDRkMmM2ZGZjLCAweDVhYzQyYWVkKSwgbmV3IFdvcmQ2NCgweDUzMzgwZDEzLCAweDlkOTViM2RmKSwgbmV3IFdvcmQ2NCgweDY1MGE3MzU0LCAweDhiYWY2M2RlKSwgbmV3IFdvcmQ2NCgweDc2NmEwYWJiLCAweDNjNzdiMmE4KSwgbmV3IFdvcmQ2NCgweDgxYzJjOTJlLCAweDQ3ZWRhZWU2KSwgbmV3IFdvcmQ2NCgweDkyNzIyYzg1LCAweDE0ODIzNTNiKSwgbmV3IFdvcmQ2NCgweGEyYmZlOGExLCAweDRjZjEwMzY0KSwgbmV3IFdvcmQ2NCgweGE4MWE2NjRiLCAweGJjNDIzMDAxKSwgbmV3IFdvcmQ2NCgweGMyNGI4YjcwLCAweGQwZjg5NzkxKSwgbmV3IFdvcmQ2NCgweGM3NmM1MWEzLCAweDA2NTRiZTMwKSwgbmV3IFdvcmQ2NCgweGQxOTJlODE5LCAweGQ2ZWY1MjE4KSwgbmV3IFdvcmQ2NCgweGQ2OTkwNjI0LCAweDU1NjVhOTEwKSwgbmV3IFdvcmQ2NCgweGY0MGUzNTg1LCAweDU3NzEyMDJhKSwgbmV3IFdvcmQ2NCgweDEwNmFhMDcwLCAweDMyYmJkMWI4KSwgbmV3IFdvcmQ2NCgweDE5YTRjMTE2LCAweGI4ZDJkMGM4KSwgbmV3IFdvcmQ2NCgweDFlMzc2YzA4LCAweDUxNDFhYjUzKSwgbmV3IFdvcmQ2NCgweDI3NDg3NzRjLCAweGRmOGVlYjk5KSwgbmV3IFdvcmQ2NCgweDM0YjBiY2I1LCAweGUxOWI0OGE4KSwgbmV3IFdvcmQ2NCgweDM5MWMwY2IzLCAweGM1Yzk1YTYzKSwgbmV3IFdvcmQ2NCgweDRlZDhhYTRhLCAweGUzNDE4YWNiKSwgbmV3IFdvcmQ2NCgweDViOWNjYTRmLCAweDc3NjNlMzczKSwgbmV3IFdvcmQ2NCgweDY4MmU2ZmYzLCAweGQ2YjJiOGEzKSwgbmV3IFdvcmQ2NCgweDc0OGY4MmVlLCAweDVkZWZiMmZjKSwgbmV3IFdvcmQ2NCgweDc4YTU2MzZmLCAweDQzMTcyZjYwKSwgbmV3IFdvcmQ2NCgweDg0Yzg3ODE0LCAweGExZjBhYjcyKSwgbmV3IFdvcmQ2NCgweDhjYzcwMjA4LCAweDFhNjQzOWVjKSwgbmV3IFdvcmQ2NCgweDkwYmVmZmZhLCAweDIzNjMxZTI4KSwgbmV3IFdvcmQ2NCgweGE0NTA2Y2ViLCAweGRlODJiZGU5KSwgbmV3IFdvcmQ2NCgweGJlZjlhM2Y3LCAweGIyYzY3OTE1KSwgbmV3IFdvcmQ2NCgweGM2NzE3OGYyLCAweGUzNzI1MzJiKSwgbmV3IFdvcmQ2NCgweGNhMjczZWNlLCAweGVhMjY2MTljKSwgbmV3IFdvcmQ2NCgweGQxODZiOGM3LCAweDIxYzBjMjA3KSwgbmV3IFdvcmQ2NCgweGVhZGE3ZGQ2LCAweGNkZTBlYjFlKSwgbmV3IFdvcmQ2NCgweGY1N2Q0ZjdmLCAweGVlNmVkMTc4KSwgbmV3IFdvcmQ2NCgweDA2ZjA2N2FhLCAweDcyMTc2ZmJhKSwgbmV3IFdvcmQ2NCgweDBhNjM3ZGM1LCAweGEyYzg5OGE2KSwgbmV3IFdvcmQ2NCgweDExM2Y5ODA0LCAweGJlZjkwZGFlKSwgbmV3IFdvcmQ2NCgweDFiNzEwYjM1LCAweDEzMWM0NzFiKSwgbmV3IFdvcmQ2NCgweDI4ZGI3N2Y1LCAweDIzMDQ3ZDg0KSwgbmV3IFdvcmQ2NCgweDMyY2FhYjdiLCAweDQwYzcyNDkzKSwgbmV3IFdvcmQ2NCgweDNjOWViZTBhLCAweDE1YzliZWJjKSwgbmV3IFdvcmQ2NCgweDQzMWQ2N2M0LCAweDljMTAwZDRjKSwgbmV3IFdvcmQ2NCgweDRjYzVkNGJlLCAweGNiM2U0MmI2KSwgbmV3IFdvcmQ2NCgweDU5N2YyOTljLCAweGZjNjU3ZTJhKSwgbmV3IFdvcmQ2NCgweDVmY2I2ZmFiLCAweDNhZDZmYWVjKSwgbmV3IFdvcmQ2NCgweDZjNDQxOThjLCAweDRhNDc1ODE3KV0pOwogIH0KfTsKZnVuY3Rpb24gY2gocmVzdWx0LCB4LCB5LCB6LCB0bXApIHsKICByZXN1bHQuYXNzaWduKHgpOwogIHJlc3VsdC5hbmQoeSk7CiAgdG1wLmFzc2lnbih4KTsKICB0bXAubm90KCk7CiAgdG1wLmFuZCh6KTsKICByZXN1bHQueG9yKHRtcCk7Cn0KZnVuY3Rpb24gbWFqKHJlc3VsdCwgeCwgeSwgeiwgdG1wKSB7CiAgcmVzdWx0LmFzc2lnbih4KTsKICByZXN1bHQuYW5kKHkpOwogIHRtcC5hc3NpZ24oeCk7CiAgdG1wLmFuZCh6KTsKICByZXN1bHQueG9yKHRtcCk7CiAgdG1wLmFzc2lnbih5KTsKICB0bXAuYW5kKHopOwogIHJlc3VsdC54b3IodG1wKTsKfQpmdW5jdGlvbiBzaWdtYShyZXN1bHQsIHgsIHRtcCkgewogIHJlc3VsdC5hc3NpZ24oeCk7CiAgcmVzdWx0LnJvdGF0ZVJpZ2h0KDI4KTsKICB0bXAuYXNzaWduKHgpOwogIHRtcC5yb3RhdGVSaWdodCgzNCk7CiAgcmVzdWx0Lnhvcih0bXApOwogIHRtcC5hc3NpZ24oeCk7CiAgdG1wLnJvdGF0ZVJpZ2h0KDM5KTsKICByZXN1bHQueG9yKHRtcCk7Cn0KZnVuY3Rpb24gc2lnbWFQcmltZShyZXN1bHQsIHgsIHRtcCkgewogIHJlc3VsdC5hc3NpZ24oeCk7CiAgcmVzdWx0LnJvdGF0ZVJpZ2h0KDE0KTsKICB0bXAuYXNzaWduKHgpOwogIHRtcC5yb3RhdGVSaWdodCgxOCk7CiAgcmVzdWx0Lnhvcih0bXApOwogIHRtcC5hc3NpZ24oeCk7CiAgdG1wLnJvdGF0ZVJpZ2h0KDQxKTsKICByZXN1bHQueG9yKHRtcCk7Cn0KZnVuY3Rpb24gbGl0dGxlU2lnbWEocmVzdWx0LCB4LCB0bXApIHsKICByZXN1bHQuYXNzaWduKHgpOwogIHJlc3VsdC5yb3RhdGVSaWdodCgxKTsKICB0bXAuYXNzaWduKHgpOwogIHRtcC5yb3RhdGVSaWdodCg4KTsKICByZXN1bHQueG9yKHRtcCk7CiAgdG1wLmFzc2lnbih4KTsKICB0bXAuc2hpZnRSaWdodCg3KTsKICByZXN1bHQueG9yKHRtcCk7Cn0KZnVuY3Rpb24gbGl0dGxlU2lnbWFQcmltZShyZXN1bHQsIHgsIHRtcCkgewogIHJlc3VsdC5hc3NpZ24oeCk7CiAgcmVzdWx0LnJvdGF0ZVJpZ2h0KDE5KTsKICB0bXAuYXNzaWduKHgpOwogIHRtcC5yb3RhdGVSaWdodCg2MSk7CiAgcmVzdWx0Lnhvcih0bXApOwogIHRtcC5hc3NpZ24oeCk7CiAgdG1wLnNoaWZ0UmlnaHQoNik7CiAgcmVzdWx0Lnhvcih0bXApOwp9CmZ1bmN0aW9uIGNhbGN1bGF0ZVNIQTUxMihkYXRhLCBvZmZzZXQsIGxlbmd0aCwgbW9kZTM4NCA9IGZhbHNlKSB7CiAgbGV0IGgwLCBoMSwgaDIsIGgzLCBoNCwgaDUsIGg2LCBoNzsKICBpZiAoIW1vZGUzODQpIHsKICAgIGgwID0gbmV3IFdvcmQ2NCgweDZhMDllNjY3LCAweGYzYmNjOTA4KTsKICAgIGgxID0gbmV3IFdvcmQ2NCgweGJiNjdhZTg1LCAweDg0Y2FhNzNiKTsKICAgIGgyID0gbmV3IFdvcmQ2NCgweDNjNmVmMzcyLCAweGZlOTRmODJiKTsKICAgIGgzID0gbmV3IFdvcmQ2NCgweGE1NGZmNTNhLCAweDVmMWQzNmYxKTsKICAgIGg0ID0gbmV3IFdvcmQ2NCgweDUxMGU1MjdmLCAweGFkZTY4MmQxKTsKICAgIGg1ID0gbmV3IFdvcmQ2NCgweDliMDU2ODhjLCAweDJiM2U2YzFmKTsKICAgIGg2ID0gbmV3IFdvcmQ2NCgweDFmODNkOWFiLCAweGZiNDFiZDZiKTsKICAgIGg3ID0gbmV3IFdvcmQ2NCgweDViZTBjZDE5LCAweDEzN2UyMTc5KTsKICB9IGVsc2UgewogICAgaDAgPSBuZXcgV29yZDY0KDB4Y2JiYjlkNWQsIDB4YzEwNTllZDgpOwogICAgaDEgPSBuZXcgV29yZDY0KDB4NjI5YTI5MmEsIDB4MzY3Y2Q1MDcpOwogICAgaDIgPSBuZXcgV29yZDY0KDB4OTE1OTAxNWEsIDB4MzA3MGRkMTcpOwogICAgaDMgPSBuZXcgV29yZDY0KDB4MTUyZmVjZDgsIDB4ZjcwZTU5MzkpOwogICAgaDQgPSBuZXcgV29yZDY0KDB4NjczMzI2NjcsIDB4ZmZjMDBiMzEpOwogICAgaDUgPSBuZXcgV29yZDY0KDB4OGViNDRhODcsIDB4Njg1ODE1MTEpOwogICAgaDYgPSBuZXcgV29yZDY0KDB4ZGIwYzJlMGQsIDB4NjRmOThmYTcpOwogICAgaDcgPSBuZXcgV29yZDY0KDB4NDdiNTQ4MWQsIDB4YmVmYTRmYTQpOwogIH0KICBjb25zdCBwYWRkZWRMZW5ndGggPSBNYXRoLmNlaWwoKGxlbmd0aCArIDE3KSAvIDEyOCkgKiAxMjg7CiAgY29uc3QgcGFkZGVkID0gbmV3IFVpbnQ4QXJyYXkocGFkZGVkTGVuZ3RoKTsKICBsZXQgaSwgajsKICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgIHBhZGRlZFtpXSA9IGRhdGFbb2Zmc2V0KytdOwogIH0KICBwYWRkZWRbaSsrXSA9IDB4ODA7CiAgY29uc3QgbiA9IHBhZGRlZExlbmd0aCAtIDE2OwogIGlmIChpIDwgbikgewogICAgaSA9IG47CiAgfQogIGkgKz0gMTE7CiAgcGFkZGVkW2krK10gPSBsZW5ndGggPj4+IDI5ICYgMHhmZjsKICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA+PiAyMSAmIDB4ZmY7CiAgcGFkZGVkW2krK10gPSBsZW5ndGggPj4gMTMgJiAweGZmOwogIHBhZGRlZFtpKytdID0gbGVuZ3RoID4+IDUgJiAweGZmOwogIHBhZGRlZFtpKytdID0gbGVuZ3RoIDw8IDMgJiAweGZmOwogIGNvbnN0IHcgPSBuZXcgQXJyYXkoODApOwogIGZvciAoaSA9IDA7IGkgPCA4MDsgaSsrKSB7CiAgICB3W2ldID0gbmV3IFdvcmQ2NCgwLCAwKTsKICB9CiAgY29uc3QgewogICAgawogIH0gPSBjYWxjdWxhdGVfc2hhX290aGVyX1BBUkFNUzsKICBsZXQgYSA9IG5ldyBXb3JkNjQoMCwgMCksCiAgICBiID0gbmV3IFdvcmQ2NCgwLCAwKSwKICAgIGMgPSBuZXcgV29yZDY0KDAsIDApOwogIGxldCBkID0gbmV3IFdvcmQ2NCgwLCAwKSwKICAgIGUgPSBuZXcgV29yZDY0KDAsIDApLAogICAgZiA9IG5ldyBXb3JkNjQoMCwgMCk7CiAgbGV0IGcgPSBuZXcgV29yZDY0KDAsIDApLAogICAgaCA9IG5ldyBXb3JkNjQoMCwgMCk7CiAgY29uc3QgdDEgPSBuZXcgV29yZDY0KDAsIDApLAogICAgdDIgPSBuZXcgV29yZDY0KDAsIDApOwogIGNvbnN0IHRtcDEgPSBuZXcgV29yZDY0KDAsIDApLAogICAgdG1wMiA9IG5ldyBXb3JkNjQoMCwgMCk7CiAgbGV0IHRtcDM7CiAgZm9yIChpID0gMDsgaSA8IHBhZGRlZExlbmd0aDspIHsKICAgIGZvciAoaiA9IDA7IGogPCAxNjsgKytqKSB7CiAgICAgIHdbal0uaGlnaCA9IHBhZGRlZFtpXSA8PCAyNCB8IHBhZGRlZFtpICsgMV0gPDwgMTYgfCBwYWRkZWRbaSArIDJdIDw8IDggfCBwYWRkZWRbaSArIDNdOwogICAgICB3W2pdLmxvdyA9IHBhZGRlZFtpICsgNF0gPDwgMjQgfCBwYWRkZWRbaSArIDVdIDw8IDE2IHwgcGFkZGVkW2kgKyA2XSA8PCA4IHwgcGFkZGVkW2kgKyA3XTsKICAgICAgaSArPSA4OwogICAgfQogICAgZm9yIChqID0gMTY7IGogPCA4MDsgKytqKSB7CiAgICAgIHRtcDMgPSB3W2pdOwogICAgICBsaXR0bGVTaWdtYVByaW1lKHRtcDMsIHdbaiAtIDJdLCB0bXAyKTsKICAgICAgdG1wMy5hZGQod1tqIC0gN10pOwogICAgICBsaXR0bGVTaWdtYSh0bXAxLCB3W2ogLSAxNV0sIHRtcDIpOwogICAgICB0bXAzLmFkZCh0bXAxKTsKICAgICAgdG1wMy5hZGQod1tqIC0gMTZdKTsKICAgIH0KICAgIGEuYXNzaWduKGgwKTsKICAgIGIuYXNzaWduKGgxKTsKICAgIGMuYXNzaWduKGgyKTsKICAgIGQuYXNzaWduKGgzKTsKICAgIGUuYXNzaWduKGg0KTsKICAgIGYuYXNzaWduKGg1KTsKICAgIGcuYXNzaWduKGg2KTsKICAgIGguYXNzaWduKGg3KTsKICAgIGZvciAoaiA9IDA7IGogPCA4MDsgKytqKSB7CiAgICAgIHQxLmFzc2lnbihoKTsKICAgICAgc2lnbWFQcmltZSh0bXAxLCBlLCB0bXAyKTsKICAgICAgdDEuYWRkKHRtcDEpOwogICAgICBjaCh0bXAxLCBlLCBmLCBnLCB0bXAyKTsKICAgICAgdDEuYWRkKHRtcDEpOwogICAgICB0MS5hZGQoa1tqXSk7CiAgICAgIHQxLmFkZCh3W2pdKTsKICAgICAgc2lnbWEodDIsIGEsIHRtcDIpOwogICAgICBtYWoodG1wMSwgYSwgYiwgYywgdG1wMik7CiAgICAgIHQyLmFkZCh0bXAxKTsKICAgICAgdG1wMyA9IGg7CiAgICAgIGggPSBnOwogICAgICBnID0gZjsKICAgICAgZiA9IGU7CiAgICAgIGQuYWRkKHQxKTsKICAgICAgZSA9IGQ7CiAgICAgIGQgPSBjOwogICAgICBjID0gYjsKICAgICAgYiA9IGE7CiAgICAgIHRtcDMuYXNzaWduKHQxKTsKICAgICAgdG1wMy5hZGQodDIpOwogICAgICBhID0gdG1wMzsKICAgIH0KICAgIGgwLmFkZChhKTsKICAgIGgxLmFkZChiKTsKICAgIGgyLmFkZChjKTsKICAgIGgzLmFkZChkKTsKICAgIGg0LmFkZChlKTsKICAgIGg1LmFkZChmKTsKICAgIGg2LmFkZChnKTsKICAgIGg3LmFkZChoKTsKICB9CiAgbGV0IHJlc3VsdDsKICBpZiAoIW1vZGUzODQpIHsKICAgIHJlc3VsdCA9IG5ldyBVaW50OEFycmF5KDY0KTsKICAgIGgwLmNvcHlUbyhyZXN1bHQsIDApOwogICAgaDEuY29weVRvKHJlc3VsdCwgOCk7CiAgICBoMi5jb3B5VG8ocmVzdWx0LCAxNik7CiAgICBoMy5jb3B5VG8ocmVzdWx0LCAyNCk7CiAgICBoNC5jb3B5VG8ocmVzdWx0LCAzMik7CiAgICBoNS5jb3B5VG8ocmVzdWx0LCA0MCk7CiAgICBoNi5jb3B5VG8ocmVzdWx0LCA0OCk7CiAgICBoNy5jb3B5VG8ocmVzdWx0LCA1Nik7CiAgfSBlbHNlIHsKICAgIHJlc3VsdCA9IG5ldyBVaW50OEFycmF5KDQ4KTsKICAgIGgwLmNvcHlUbyhyZXN1bHQsIDApOwogICAgaDEuY29weVRvKHJlc3VsdCwgOCk7CiAgICBoMi5jb3B5VG8ocmVzdWx0LCAxNik7CiAgICBoMy5jb3B5VG8ocmVzdWx0LCAyNCk7CiAgICBoNC5jb3B5VG8ocmVzdWx0LCAzMik7CiAgICBoNS5jb3B5VG8ocmVzdWx0LCA0MCk7CiAgfQogIHJldHVybiByZXN1bHQ7Cn0KZnVuY3Rpb24gY2FsY3VsYXRlU0hBMzg0KGRhdGEsIG9mZnNldCwgbGVuZ3RoKSB7CiAgcmV0dXJuIGNhbGN1bGF0ZVNIQTUxMihkYXRhLCBvZmZzZXQsIGxlbmd0aCwgdHJ1ZSk7Cn0KCjsvLyAuL3NyYy9jb3JlL2NhbGN1bGF0ZV9zaGEyNTYuanMKCgoKCgoKCgoKY29uc3QgY2FsY3VsYXRlX3NoYTI1Nl9QQVJBTVMgPSB7CiAgZ2V0IGsoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJrIiwgWzB4NDI4YTJmOTgsIDB4NzEzNzQ0OTEsIDB4YjVjMGZiY2YsIDB4ZTliNWRiYTUsIDB4Mzk1NmMyNWIsIDB4NTlmMTExZjEsIDB4OTIzZjgyYTQsIDB4YWIxYzVlZDUsIDB4ZDgwN2FhOTgsIDB4MTI4MzViMDEsIDB4MjQzMTg1YmUsIDB4NTUwYzdkYzMsIDB4NzJiZTVkNzQsIDB4ODBkZWIxZmUsIDB4OWJkYzA2YTcsIDB4YzE5YmYxNzQsIDB4ZTQ5YjY5YzEsIDB4ZWZiZTQ3ODYsIDB4MGZjMTlkYzYsIDB4MjQwY2ExY2MsIDB4MmRlOTJjNmYsIDB4NGE3NDg0YWEsIDB4NWNiMGE5ZGMsIDB4NzZmOTg4ZGEsIDB4OTgzZTUxNTIsIDB4YTgzMWM2NmQsIDB4YjAwMzI3YzgsIDB4YmY1OTdmYzcsIDB4YzZlMDBiZjMsIDB4ZDVhNzkxNDcsIDB4MDZjYTYzNTEsIDB4MTQyOTI5NjcsIDB4MjdiNzBhODUsIDB4MmUxYjIxMzgsIDB4NGQyYzZkZmMsIDB4NTMzODBkMTMsIDB4NjUwYTczNTQsIDB4NzY2YTBhYmIsIDB4ODFjMmM5MmUsIDB4OTI3MjJjODUsIDB4YTJiZmU4YTEsIDB4YTgxYTY2NGIsIDB4YzI0YjhiNzAsIDB4Yzc2YzUxYTMsIDB4ZDE5MmU4MTksIDB4ZDY5OTA2MjQsIDB4ZjQwZTM1ODUsIDB4MTA2YWEwNzAsIDB4MTlhNGMxMTYsIDB4MWUzNzZjMDgsIDB4Mjc0ODc3NGMsIDB4MzRiMGJjYjUsIDB4MzkxYzBjYjMsIDB4NGVkOGFhNGEsIDB4NWI5Y2NhNGYsIDB4NjgyZTZmZjMsIDB4NzQ4ZjgyZWUsIDB4NzhhNTYzNmYsIDB4ODRjODc4MTQsIDB4OGNjNzAyMDgsIDB4OTBiZWZmZmEsIDB4YTQ1MDZjZWIsIDB4YmVmOWEzZjcsIDB4YzY3MTc4ZjJdKTsKICB9Cn07CmZ1bmN0aW9uIHJvdHIoeCwgbikgewogIHJldHVybiB4ID4+PiBuIHwgeCA8PCAzMiAtIG47Cn0KZnVuY3Rpb24gY2FsY3VsYXRlX3NoYTI1Nl9jaCh4LCB5LCB6KSB7CiAgcmV0dXJuIHggJiB5IF4gfnggJiB6Owp9CmZ1bmN0aW9uIGNhbGN1bGF0ZV9zaGEyNTZfbWFqKHgsIHksIHopIHsKICByZXR1cm4geCAmIHkgXiB4ICYgeiBeIHkgJiB6Owp9CmZ1bmN0aW9uIGNhbGN1bGF0ZV9zaGEyNTZfc2lnbWEoeCkgewogIHJldHVybiByb3RyKHgsIDIpIF4gcm90cih4LCAxMykgXiByb3RyKHgsIDIyKTsKfQpmdW5jdGlvbiBjYWxjdWxhdGVfc2hhMjU2X3NpZ21hUHJpbWUoeCkgewogIHJldHVybiByb3RyKHgsIDYpIF4gcm90cih4LCAxMSkgXiByb3RyKHgsIDI1KTsKfQpmdW5jdGlvbiBjYWxjdWxhdGVfc2hhMjU2X2xpdHRsZVNpZ21hKHgpIHsKICByZXR1cm4gcm90cih4LCA3KSBeIHJvdHIoeCwgMTgpIF4geCA+Pj4gMzsKfQpmdW5jdGlvbiBjYWxjdWxhdGVfc2hhMjU2X2xpdHRsZVNpZ21hUHJpbWUoeCkgewogIHJldHVybiByb3RyKHgsIDE3KSBeIHJvdHIoeCwgMTkpIF4geCA+Pj4gMTA7Cn0KZnVuY3Rpb24gY2FsY3VsYXRlU0hBMjU2KGRhdGEsIG9mZnNldCwgbGVuZ3RoKSB7CiAgbGV0IGgwID0gMHg2YTA5ZTY2NywKICAgIGgxID0gMHhiYjY3YWU4NSwKICAgIGgyID0gMHgzYzZlZjM3MiwKICAgIGgzID0gMHhhNTRmZjUzYSwKICAgIGg0ID0gMHg1MTBlNTI3ZiwKICAgIGg1ID0gMHg5YjA1Njg4YywKICAgIGg2ID0gMHgxZjgzZDlhYiwKICAgIGg3ID0gMHg1YmUwY2QxOTsKICBjb25zdCBwYWRkZWRMZW5ndGggPSBNYXRoLmNlaWwoKGxlbmd0aCArIDkpIC8gNjQpICogNjQ7CiAgY29uc3QgcGFkZGVkID0gbmV3IFVpbnQ4QXJyYXkocGFkZGVkTGVuZ3RoKTsKICBsZXQgaSwgajsKICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHsKICAgIHBhZGRlZFtpXSA9IGRhdGFbb2Zmc2V0KytdOwogIH0KICBwYWRkZWRbaSsrXSA9IDB4ODA7CiAgY29uc3QgbiA9IHBhZGRlZExlbmd0aCAtIDg7CiAgaWYgKGkgPCBuKSB7CiAgICBpID0gbjsKICB9CiAgaSArPSAzOwogIHBhZGRlZFtpKytdID0gbGVuZ3RoID4+PiAyOSAmIDB4ZmY7CiAgcGFkZGVkW2krK10gPSBsZW5ndGggPj4gMjEgJiAweGZmOwogIHBhZGRlZFtpKytdID0gbGVuZ3RoID4+IDEzICYgMHhmZjsKICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA+PiA1ICYgMHhmZjsKICBwYWRkZWRbaSsrXSA9IGxlbmd0aCA8PCAzICYgMHhmZjsKICBjb25zdCB3ID0gbmV3IFVpbnQzMkFycmF5KDY0KTsKICBjb25zdCB7CiAgICBrCiAgfSA9IGNhbGN1bGF0ZV9zaGEyNTZfUEFSQU1TOwogIGZvciAoaSA9IDA7IGkgPCBwYWRkZWRMZW5ndGg7KSB7CiAgICBmb3IgKGogPSAwOyBqIDwgMTY7ICsraikgewogICAgICB3W2pdID0gcGFkZGVkW2ldIDw8IDI0IHwgcGFkZGVkW2kgKyAxXSA8PCAxNiB8IHBhZGRlZFtpICsgMl0gPDwgOCB8IHBhZGRlZFtpICsgM107CiAgICAgIGkgKz0gNDsKICAgIH0KICAgIGZvciAoaiA9IDE2OyBqIDwgNjQ7ICsraikgewogICAgICB3W2pdID0gY2FsY3VsYXRlX3NoYTI1Nl9saXR0bGVTaWdtYVByaW1lKHdbaiAtIDJdKSArIHdbaiAtIDddICsgY2FsY3VsYXRlX3NoYTI1Nl9saXR0bGVTaWdtYSh3W2ogLSAxNV0pICsgd1tqIC0gMTZdIHwgMDsKICAgIH0KICAgIGxldCBhID0gaDAsCiAgICAgIGIgPSBoMSwKICAgICAgYyA9IGgyLAogICAgICBkID0gaDMsCiAgICAgIGUgPSBoNCwKICAgICAgZiA9IGg1LAogICAgICBnID0gaDYsCiAgICAgIGggPSBoNywKICAgICAgdDEsCiAgICAgIHQyOwogICAgZm9yIChqID0gMDsgaiA8IDY0OyArK2opIHsKICAgICAgdDEgPSBoICsgY2FsY3VsYXRlX3NoYTI1Nl9zaWdtYVByaW1lKGUpICsgY2FsY3VsYXRlX3NoYTI1Nl9jaChlLCBmLCBnKSArIGtbal0gKyB3W2pdOwogICAgICB0MiA9IGNhbGN1bGF0ZV9zaGEyNTZfc2lnbWEoYSkgKyBjYWxjdWxhdGVfc2hhMjU2X21haihhLCBiLCBjKTsKICAgICAgaCA9IGc7CiAgICAgIGcgPSBmOwogICAgICBmID0gZTsKICAgICAgZSA9IGQgKyB0MSB8IDA7CiAgICAgIGQgPSBjOwogICAgICBjID0gYjsKICAgICAgYiA9IGE7CiAgICAgIGEgPSB0MSArIHQyIHwgMDsKICAgIH0KICAgIGgwID0gaDAgKyBhIHwgMDsKICAgIGgxID0gaDEgKyBiIHwgMDsKICAgIGgyID0gaDIgKyBjIHwgMDsKICAgIGgzID0gaDMgKyBkIHwgMDsKICAgIGg0ID0gaDQgKyBlIHwgMDsKICAgIGg1ID0gaDUgKyBmIHwgMDsKICAgIGg2ID0gaDYgKyBnIHwgMDsKICAgIGg3ID0gaDcgKyBoIHwgMDsKICB9CiAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFtoMCA+PiAyNCAmIDB4RkYsIGgwID4+IDE2ICYgMHhGRiwgaDAgPj4gOCAmIDB4RkYsIGgwICYgMHhGRiwgaDEgPj4gMjQgJiAweEZGLCBoMSA+PiAxNiAmIDB4RkYsIGgxID4+IDggJiAweEZGLCBoMSAmIDB4RkYsIGgyID4+IDI0ICYgMHhGRiwgaDIgPj4gMTYgJiAweEZGLCBoMiA+PiA4ICYgMHhGRiwgaDIgJiAweEZGLCBoMyA+PiAyNCAmIDB4RkYsIGgzID4+IDE2ICYgMHhGRiwgaDMgPj4gOCAmIDB4RkYsIGgzICYgMHhGRiwgaDQgPj4gMjQgJiAweEZGLCBoNCA+PiAxNiAmIDB4RkYsIGg0ID4+IDggJiAweEZGLCBoNCAmIDB4RkYsIGg1ID4+IDI0ICYgMHhGRiwgaDUgPj4gMTYgJiAweEZGLCBoNSA+PiA4ICYgMHhGRiwgaDUgJiAweEZGLCBoNiA+PiAyNCAmIDB4RkYsIGg2ID4+IDE2ICYgMHhGRiwgaDYgPj4gOCAmIDB4RkYsIGg2ICYgMHhGRiwgaDcgPj4gMjQgJiAweEZGLCBoNyA+PiAxNiAmIDB4RkYsIGg3ID4+IDggJiAweEZGLCBoNyAmIDB4RkZdKTsKfQoKOy8vIC4vc3JjL2NvcmUvZGVjcnlwdF9zdHJlYW0uanMKCmNvbnN0IGNodW5rU2l6ZSA9IDUxMjsKY2xhc3MgRGVjcnlwdFN0cmVhbSBleHRlbmRzIERlY29kZVN0cmVhbSB7CiAgY29uc3RydWN0b3Ioc3RyLCBtYXliZUxlbmd0aCwgZGVjcnlwdCkgewogICAgc3VwZXIobWF5YmVMZW5ndGgpOwogICAgdGhpcy5zdHIgPSBzdHI7CiAgICB0aGlzLmRpY3QgPSBzdHIuZGljdDsKICAgIHRoaXMuZGVjcnlwdCA9IGRlY3J5cHQ7CiAgICB0aGlzLm5leHRDaHVuayA9IG51bGw7CiAgICB0aGlzLmluaXRpYWxpemVkID0gZmFsc2U7CiAgfQogIHJlYWRCbG9jaygpIHsKICAgIGxldCBjaHVuazsKICAgIGlmICh0aGlzLmluaXRpYWxpemVkKSB7CiAgICAgIGNodW5rID0gdGhpcy5uZXh0Q2h1bms7CiAgICB9IGVsc2UgewogICAgICBjaHVuayA9IHRoaXMuc3RyLmdldEJ5dGVzKGNodW5rU2l6ZSk7CiAgICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSB0cnVlOwogICAgfQogICAgaWYgKCFjaHVuaz8ubGVuZ3RoKSB7CiAgICAgIHRoaXMuZW9mID0gdHJ1ZTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhpcy5uZXh0Q2h1bmsgPSB0aGlzLnN0ci5nZXRCeXRlcyhjaHVua1NpemUpOwogICAgY29uc3QgaGFzTW9yZURhdGEgPSB0aGlzLm5leHRDaHVuaz8ubGVuZ3RoID4gMDsKICAgIGNvbnN0IGRlY3J5cHQgPSB0aGlzLmRlY3J5cHQ7CiAgICBjaHVuayA9IGRlY3J5cHQoY2h1bmssICFoYXNNb3JlRGF0YSk7CiAgICBjb25zdCBidWZmZXJMZW5ndGggPSB0aGlzLmJ1ZmZlckxlbmd0aCwKICAgICAgbmV3TGVuZ3RoID0gYnVmZmVyTGVuZ3RoICsgY2h1bmsubGVuZ3RoLAogICAgICBidWZmZXIgPSB0aGlzLmVuc3VyZUJ1ZmZlcihuZXdMZW5ndGgpOwogICAgYnVmZmVyLnNldChjaHVuaywgYnVmZmVyTGVuZ3RoKTsKICAgIHRoaXMuYnVmZmVyTGVuZ3RoID0gbmV3TGVuZ3RoOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUvY3J5cHRvLmpzCgoKCgoKCgoKCgoKCgoKCgoKCgpjbGFzcyBBUkNGb3VyQ2lwaGVyIHsKICBjb25zdHJ1Y3RvcihrZXkpIHsKICAgIHRoaXMuYSA9IDA7CiAgICB0aGlzLmIgPSAwOwogICAgY29uc3QgcyA9IG5ldyBVaW50OEFycmF5KDI1Nik7CiAgICBjb25zdCBrZXlMZW5ndGggPSBrZXkubGVuZ3RoOwogICAgZm9yIChsZXQgaSA9IDA7IGkgPCAyNTY7ICsraSkgewogICAgICBzW2ldID0gaTsKICAgIH0KICAgIGZvciAobGV0IGkgPSAwLCBqID0gMDsgaSA8IDI1NjsgKytpKSB7CiAgICAgIGNvbnN0IHRtcCA9IHNbaV07CiAgICAgIGogPSBqICsgdG1wICsga2V5W2kgJSBrZXlMZW5ndGhdICYgMHhmZjsKICAgICAgc1tpXSA9IHNbal07CiAgICAgIHNbal0gPSB0bXA7CiAgICB9CiAgICB0aGlzLnMgPSBzOwogIH0KICBlbmNyeXB0QmxvY2soZGF0YSkgewogICAgbGV0IGEgPSB0aGlzLmEsCiAgICAgIGIgPSB0aGlzLmI7CiAgICBjb25zdCBzID0gdGhpcy5zOwogICAgY29uc3QgbiA9IGRhdGEubGVuZ3RoOwogICAgY29uc3Qgb3V0cHV0ID0gbmV3IFVpbnQ4QXJyYXkobik7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG47ICsraSkgewogICAgICBhID0gYSArIDEgJiAweGZmOwogICAgICBjb25zdCB0bXAgPSBzW2FdOwogICAgICBiID0gYiArIHRtcCAmIDB4ZmY7CiAgICAgIGNvbnN0IHRtcDIgPSBzW2JdOwogICAgICBzW2FdID0gdG1wMjsKICAgICAgc1tiXSA9IHRtcDsKICAgICAgb3V0cHV0W2ldID0gZGF0YVtpXSBeIHNbdG1wICsgdG1wMiAmIDB4ZmZdOwogICAgfQogICAgdGhpcy5hID0gYTsKICAgIHRoaXMuYiA9IGI7CiAgICByZXR1cm4gb3V0cHV0OwogIH0KICBkZWNyeXB0QmxvY2soZGF0YSkgewogICAgcmV0dXJuIHRoaXMuZW5jcnlwdEJsb2NrKGRhdGEpOwogIH0KICBlbmNyeXB0KGRhdGEpIHsKICAgIHJldHVybiB0aGlzLmVuY3J5cHRCbG9jayhkYXRhKTsKICB9Cn0KY2xhc3MgTnVsbENpcGhlciB7CiAgZGVjcnlwdEJsb2NrKGRhdGEpIHsKICAgIHJldHVybiBkYXRhOwogIH0KICBlbmNyeXB0KGRhdGEpIHsKICAgIHJldHVybiBkYXRhOwogIH0KfQpjbGFzcyBBRVNCYXNlQ2lwaGVyIHsKICBfcyA9IG5ldyBVaW50OEFycmF5KFsweDYzLCAweDdjLCAweDc3LCAweDdiLCAweGYyLCAweDZiLCAweDZmLCAweGM1LCAweDMwLCAweDAxLCAweDY3LCAweDJiLCAweGZlLCAweGQ3LCAweGFiLCAweDc2LCAweGNhLCAweDgyLCAweGM5LCAweDdkLCAweGZhLCAweDU5LCAweDQ3LCAweGYwLCAweGFkLCAweGQ0LCAweGEyLCAweGFmLCAweDljLCAweGE0LCAweDcyLCAweGMwLCAweGI3LCAweGZkLCAweDkzLCAweDI2LCAweDM2LCAweDNmLCAweGY3LCAweGNjLCAweDM0LCAweGE1LCAweGU1LCAweGYxLCAweDcxLCAweGQ4LCAweDMxLCAweDE1LCAweDA0LCAweGM3LCAweDIzLCAweGMzLCAweDE4LCAweDk2LCAweDA1LCAweDlhLCAweDA3LCAweDEyLCAweDgwLCAweGUyLCAweGViLCAweDI3LCAweGIyLCAweDc1LCAweDA5LCAweDgzLCAweDJjLCAweDFhLCAweDFiLCAweDZlLCAweDVhLCAweGEwLCAweDUyLCAweDNiLCAweGQ2LCAweGIzLCAweDI5LCAweGUzLCAweDJmLCAweDg0LCAweDUzLCAweGQxLCAweDAwLCAweGVkLCAweDIwLCAweGZjLCAweGIxLCAweDViLCAweDZhLCAweGNiLCAweGJlLCAweDM5LCAweDRhLCAweDRjLCAweDU4LCAweGNmLCAweGQwLCAweGVmLCAweGFhLCAweGZiLCAweDQzLCAweDRkLCAweDMzLCAweDg1LCAweDQ1LCAweGY5LCAweDAyLCAweDdmLCAweDUwLCAweDNjLCAweDlmLCAweGE4LCAweDUxLCAweGEzLCAweDQwLCAweDhmLCAweDkyLCAweDlkLCAweDM4LCAweGY1LCAweGJjLCAweGI2LCAweGRhLCAweDIxLCAweDEwLCAweGZmLCAweGYzLCAweGQyLCAweGNkLCAweDBjLCAweDEzLCAweGVjLCAweDVmLCAweDk3LCAweDQ0LCAweDE3LCAweGM0LCAweGE3LCAweDdlLCAweDNkLCAweDY0LCAweDVkLCAweDE5LCAweDczLCAweDYwLCAweDgxLCAweDRmLCAweGRjLCAweDIyLCAweDJhLCAweDkwLCAweDg4LCAweDQ2LCAweGVlLCAweGI4LCAweDE0LCAweGRlLCAweDVlLCAweDBiLCAweGRiLCAweGUwLCAweDMyLCAweDNhLCAweDBhLCAweDQ5LCAweDA2LCAweDI0LCAweDVjLCAweGMyLCAweGQzLCAweGFjLCAweDYyLCAweDkxLCAweDk1LCAweGU0LCAweDc5LCAweGU3LCAweGM4LCAweDM3LCAweDZkLCAweDhkLCAweGQ1LCAweDRlLCAweGE5LCAweDZjLCAweDU2LCAweGY0LCAweGVhLCAweDY1LCAweDdhLCAweGFlLCAweDA4LCAweGJhLCAweDc4LCAweDI1LCAweDJlLCAweDFjLCAweGE2LCAweGI0LCAweGM2LCAweGU4LCAweGRkLCAweDc0LCAweDFmLCAweDRiLCAweGJkLCAweDhiLCAweDhhLCAweDcwLCAweDNlLCAweGI1LCAweDY2LCAweDQ4LCAweDAzLCAweGY2LCAweDBlLCAweDYxLCAweDM1LCAweDU3LCAweGI5LCAweDg2LCAweGMxLCAweDFkLCAweDllLCAweGUxLCAweGY4LCAweDk4LCAweDExLCAweDY5LCAweGQ5LCAweDhlLCAweDk0LCAweDliLCAweDFlLCAweDg3LCAweGU5LCAweGNlLCAweDU1LCAweDI4LCAweGRmLCAweDhjLCAweGExLCAweDg5LCAweDBkLCAweGJmLCAweGU2LCAweDQyLCAweDY4LCAweDQxLCAweDk5LCAweDJkLCAweDBmLCAweGIwLCAweDU0LCAweGJiLCAweDE2XSk7CiAgX2ludl9zID0gbmV3IFVpbnQ4QXJyYXkoWzB4NTIsIDB4MDksIDB4NmEsIDB4ZDUsIDB4MzAsIDB4MzYsIDB4YTUsIDB4MzgsIDB4YmYsIDB4NDAsIDB4YTMsIDB4OWUsIDB4ODEsIDB4ZjMsIDB4ZDcsIDB4ZmIsIDB4N2MsIDB4ZTMsIDB4MzksIDB4ODIsIDB4OWIsIDB4MmYsIDB4ZmYsIDB4ODcsIDB4MzQsIDB4OGUsIDB4NDMsIDB4NDQsIDB4YzQsIDB4ZGUsIDB4ZTksIDB4Y2IsIDB4NTQsIDB4N2IsIDB4OTQsIDB4MzIsIDB4YTYsIDB4YzIsIDB4MjMsIDB4M2QsIDB4ZWUsIDB4NGMsIDB4OTUsIDB4MGIsIDB4NDIsIDB4ZmEsIDB4YzMsIDB4NGUsIDB4MDgsIDB4MmUsIDB4YTEsIDB4NjYsIDB4MjgsIDB4ZDksIDB4MjQsIDB4YjIsIDB4NzYsIDB4NWIsIDB4YTIsIDB4NDksIDB4NmQsIDB4OGIsIDB4ZDEsIDB4MjUsIDB4NzIsIDB4ZjgsIDB4ZjYsIDB4NjQsIDB4ODYsIDB4NjgsIDB4OTgsIDB4MTYsIDB4ZDQsIDB4YTQsIDB4NWMsIDB4Y2MsIDB4NWQsIDB4NjUsIDB4YjYsIDB4OTIsIDB4NmMsIDB4NzAsIDB4NDgsIDB4NTAsIDB4ZmQsIDB4ZWQsIDB4YjksIDB4ZGEsIDB4NWUsIDB4MTUsIDB4NDYsIDB4NTcsIDB4YTcsIDB4OGQsIDB4OWQsIDB4ODQsIDB4OTAsIDB4ZDgsIDB4YWIsIDB4MDAsIDB4OGMsIDB4YmMsIDB4ZDMsIDB4MGEsIDB4ZjcsIDB4ZTQsIDB4NTgsIDB4MDUsIDB4YjgsIDB4YjMsIDB4NDUsIDB4MDYsIDB4ZDAsIDB4MmMsIDB4MWUsIDB4OGYsIDB4Y2EsIDB4M2YsIDB4MGYsIDB4MDIsIDB4YzEsIDB4YWYsIDB4YmQsIDB4MDMsIDB4MDEsIDB4MTMsIDB4OGEsIDB4NmIsIDB4M2EsIDB4OTEsIDB4MTEsIDB4NDEsIDB4NGYsIDB4NjcsIDB4ZGMsIDB4ZWEsIDB4OTcsIDB4ZjIsIDB4Y2YsIDB4Y2UsIDB4ZjAsIDB4YjQsIDB4ZTYsIDB4NzMsIDB4OTYsIDB4YWMsIDB4NzQsIDB4MjIsIDB4ZTcsIDB4YWQsIDB4MzUsIDB4ODUsIDB4ZTIsIDB4ZjksIDB4MzcsIDB4ZTgsIDB4MWMsIDB4NzUsIDB4ZGYsIDB4NmUsIDB4NDcsIDB4ZjEsIDB4MWEsIDB4NzEsIDB4MWQsIDB4MjksIDB4YzUsIDB4ODksIDB4NmYsIDB4YjcsIDB4NjIsIDB4MGUsIDB4YWEsIDB4MTgsIDB4YmUsIDB4MWIsIDB4ZmMsIDB4NTYsIDB4M2UsIDB4NGIsIDB4YzYsIDB4ZDIsIDB4NzksIDB4MjAsIDB4OWEsIDB4ZGIsIDB4YzAsIDB4ZmUsIDB4NzgsIDB4Y2QsIDB4NWEsIDB4ZjQsIDB4MWYsIDB4ZGQsIDB4YTgsIDB4MzMsIDB4ODgsIDB4MDcsIDB4YzcsIDB4MzEsIDB4YjEsIDB4MTIsIDB4MTAsIDB4NTksIDB4MjcsIDB4ODAsIDB4ZWMsIDB4NWYsIDB4NjAsIDB4NTEsIDB4N2YsIDB4YTksIDB4MTksIDB4YjUsIDB4NGEsIDB4MGQsIDB4MmQsIDB4ZTUsIDB4N2EsIDB4OWYsIDB4OTMsIDB4YzksIDB4OWMsIDB4ZWYsIDB4YTAsIDB4ZTAsIDB4M2IsIDB4NGQsIDB4YWUsIDB4MmEsIDB4ZjUsIDB4YjAsIDB4YzgsIDB4ZWIsIDB4YmIsIDB4M2MsIDB4ODMsIDB4NTMsIDB4OTksIDB4NjEsIDB4MTcsIDB4MmIsIDB4MDQsIDB4N2UsIDB4YmEsIDB4NzcsIDB4ZDYsIDB4MjYsIDB4ZTEsIDB4NjksIDB4MTQsIDB4NjMsIDB4NTUsIDB4MjEsIDB4MGMsIDB4N2RdKTsKICBfbWl4ID0gbmV3IFVpbnQzMkFycmF5KFsweDAwMDAwMDAwLCAweDBlMDkwZDBiLCAweDFjMTIxYTE2LCAweDEyMWIxNzFkLCAweDM4MjQzNDJjLCAweDM2MmQzOTI3LCAweDI0MzYyZTNhLCAweDJhM2YyMzMxLCAweDcwNDg2ODU4LCAweDdlNDE2NTUzLCAweDZjNWE3MjRlLCAweDYyNTM3ZjQ1LCAweDQ4NmM1Yzc0LCAweDQ2NjU1MTdmLCAweDU0N2U0NjYyLCAweDVhNzc0YjY5LCAweGUwOTBkMGIwLCAweGVlOTlkZGJiLCAweGZjODJjYWE2LCAweGYyOGJjN2FkLCAweGQ4YjRlNDljLCAweGQ2YmRlOTk3LCAweGM0YTZmZThhLCAweGNhYWZmMzgxLCAweDkwZDhiOGU4LCAweDllZDFiNWUzLCAweDhjY2FhMmZlLCAweDgyYzNhZmY1LCAweGE4ZmM4Y2M0LCAweGE2ZjU4MWNmLCAweGI0ZWU5NmQyLCAweGJhZTc5YmQ5LCAweGRiM2JiYjdiLCAweGQ1MzJiNjcwLCAweGM3MjlhMTZkLCAweGM5MjBhYzY2LCAweGUzMWY4ZjU3LCAweGVkMTY4MjVjLCAweGZmMGQ5NTQxLCAweGYxMDQ5ODRhLCAweGFiNzNkMzIzLCAweGE1N2FkZTI4LCAweGI3NjFjOTM1LCAweGI5NjhjNDNlLCAweDkzNTdlNzBmLCAweDlkNWVlYTA0LCAweDhmNDVmZDE5LCAweDgxNGNmMDEyLCAweDNiYWI2YmNiLCAweDM1YTI2NmMwLCAweDI3Yjk3MWRkLCAweDI5YjA3Y2Q2LCAweDAzOGY1ZmU3LCAweDBkODY1MmVjLCAweDFmOWQ0NWYxLCAweDExOTQ0OGZhLCAweDRiZTMwMzkzLCAweDQ1ZWEwZTk4LCAweDU3ZjExOTg1LCAweDU5ZjgxNDhlLCAweDczYzczN2JmLCAweDdkY2UzYWI0LCAweDZmZDUyZGE5LCAweDYxZGMyMGEyLCAweGFkNzY2ZGY2LCAweGEzN2Y2MGZkLCAweGIxNjQ3N2UwLCAweGJmNmQ3YWViLCAweDk1NTI1OWRhLCAweDliNWI1NGQxLCAweDg5NDA0M2NjLCAweDg3NDk0ZWM3LCAweGRkM2UwNWFlLCAweGQzMzcwOGE1LCAweGMxMmMxZmI4LCAweGNmMjUxMmIzLCAweGU1MWEzMTgyLCAweGViMTMzYzg5LCAweGY5MDgyYjk0LCAweGY3MDEyNjlmLCAweDRkZTZiZDQ2LCAweDQzZWZiMDRkLCAweDUxZjRhNzUwLCAweDVmZmRhYTViLCAweDc1YzI4OTZhLCAweDdiY2I4NDYxLCAweDY5ZDA5MzdjLCAweDY3ZDk5ZTc3LCAweDNkYWVkNTFlLCAweDMzYTdkODE1LCAweDIxYmNjZjA4LCAweDJmYjVjMjAzLCAweDA1OGFlMTMyLCAweDBiODNlYzM5LCAweDE5OThmYjI0LCAweDE3OTFmNjJmLCAweDc2NGRkNjhkLCAweDc4NDRkYjg2LCAweDZhNWZjYzliLCAweDY0NTZjMTkwLCAweDRlNjllMmExLCAweDQwNjBlZmFhLCAweDUyN2JmOGI3LCAweDVjNzJmNWJjLCAweDA2MDViZWQ1LCAweDA4MGNiM2RlLCAweDFhMTdhNGMzLCAweDE0MWVhOWM4LCAweDNlMjE4YWY5LCAweDMwMjg4N2YyLCAweDIyMzM5MGVmLCAweDJjM2E5ZGU0LCAweDk2ZGQwNjNkLCAweDk4ZDQwYjM2LCAweDhhY2YxYzJiLCAweDg0YzYxMTIwLCAweGFlZjkzMjExLCAweGEwZjAzZjFhLCAweGIyZWIyODA3LCAweGJjZTIyNTBjLCAweGU2OTU2ZTY1LCAweGU4OWM2MzZlLCAweGZhODc3NDczLCAweGY0OGU3OTc4LCAweGRlYjE1YTQ5LCAweGQwYjg1NzQyLCAweGMyYTM0MDVmLCAweGNjYWE0ZDU0LCAweDQxZWNkYWY3LCAweDRmZTVkN2ZjLCAweDVkZmVjMGUxLCAweDUzZjdjZGVhLCAweDc5YzhlZWRiLCAweDc3YzFlM2QwLCAweDY1ZGFmNGNkLCAweDZiZDNmOWM2LCAweDMxYTRiMmFmLCAweDNmYWRiZmE0LCAweDJkYjZhOGI5LCAweDIzYmZhNWIyLCAweDA5ODA4NjgzLCAweDA3ODk4Yjg4LCAweDE1OTI5Yzk1LCAweDFiOWI5MTllLCAweGExN2MwYTQ3LCAweGFmNzUwNzRjLCAweGJkNmUxMDUxLCAweGIzNjcxZDVhLCAweDk5NTgzZTZiLCAweDk3NTEzMzYwLCAweDg1NGEyNDdkLCAweDhiNDMyOTc2LCAweGQxMzQ2MjFmLCAweGRmM2Q2ZjE0LCAweGNkMjY3ODA5LCAweGMzMmY3NTAyLCAweGU5MTA1NjMzLCAweGU3MTk1YjM4LCAweGY1MDI0YzI1LCAweGZiMGI0MTJlLCAweDlhZDc2MThjLCAweDk0ZGU2Yzg3LCAweDg2YzU3YjlhLCAweDg4Y2M3NjkxLCAweGEyZjM1NWEwLCAweGFjZmE1OGFiLCAweGJlZTE0ZmI2LCAweGIwZTg0MmJkLCAweGVhOWYwOWQ0LCAweGU0OTYwNGRmLCAweGY2OGQxM2MyLCAweGY4ODQxZWM5LCAweGQyYmIzZGY4LCAweGRjYjIzMGYzLCAweGNlYTkyN2VlLCAweGMwYTAyYWU1LCAweDdhNDdiMTNjLCAweDc0NGViYzM3LCAweDY2NTVhYjJhLCAweDY4NWNhNjIxLCAweDQyNjM4NTEwLCAweDRjNmE4ODFiLCAweDVlNzE5ZjA2LCAweDUwNzg5MjBkLCAweDBhMGZkOTY0LCAweDA0MDZkNDZmLCAweDE2MWRjMzcyLCAweDE4MTRjZTc5LCAweDMyMmJlZDQ4LCAweDNjMjJlMDQzLCAweDJlMzlmNzVlLCAweDIwMzBmYTU1LCAweGVjOWFiNzAxLCAweGUyOTNiYTBhLCAweGYwODhhZDE3LCAweGZlODFhMDFjLCAweGQ0YmU4MzJkLCAweGRhYjc4ZTI2LCAweGM4YWM5OTNiLCAweGM2YTU5NDMwLCAweDljZDJkZjU5LCAweDkyZGJkMjUyLCAweDgwYzBjNTRmLCAweDhlYzljODQ0LCAweGE0ZjZlYjc1LCAweGFhZmZlNjdlLCAweGI4ZTRmMTYzLCAweGI2ZWRmYzY4LCAweDBjMGE2N2IxLCAweDAyMDM2YWJhLCAweDEwMTg3ZGE3LCAweDFlMTE3MGFjLCAweDM0MmU1MzlkLCAweDNhMjc1ZTk2LCAweDI4M2M0OThiLCAweDI2MzU0NDgwLCAweDdjNDIwZmU5LCAweDcyNGIwMmUyLCAweDYwNTAxNWZmLCAweDZlNTkxOGY0LCAweDQ0NjYzYmM1LCAweDRhNmYzNmNlLCAweDU4NzQyMWQzLCAweDU2N2QyY2Q4LCAweDM3YTEwYzdhLCAweDM5YTgwMTcxLCAweDJiYjMxNjZjLCAweDI1YmExYjY3LCAweDBmODUzODU2LCAweDAxOGMzNTVkLCAweDEzOTcyMjQwLCAweDFkOWUyZjRiLCAweDQ3ZTk2NDIyLCAweDQ5ZTA2OTI5LCAweDViZmI3ZTM0LCAweDU1ZjI3MzNmLCAweDdmY2Q1MDBlLCAweDcxYzQ1ZDA1LCAweDYzZGY0YTE4LCAweDZkZDY0NzEzLCAweGQ3MzFkY2NhLCAweGQ5MzhkMWMxLCAweGNiMjNjNmRjLCAweGM1MmFjYmQ3LCAweGVmMTVlOGU2LCAweGUxMWNlNWVkLCAweGYzMDdmMmYwLCAweGZkMGVmZmZiLCAweGE3NzliNDkyLCAweGE5NzBiOTk5LCAweGJiNmJhZTg0LCAweGI1NjJhMzhmLCAweDlmNWQ4MGJlLCAweDkxNTQ4ZGI1LCAweDgzNGY5YWE4LCAweDhkNDY5N2EzXSk7CiAgX21peENvbCA9IG5ldyBVaW50OEFycmF5KDI1NikubWFwKChfLCBpKSA9PiBpIDwgMTI4ID8gaSA8PCAxIDogaSA8PCAxIF4gMHgxYik7CiAgY29uc3RydWN0b3IoKSB7CiAgICB0aGlzLmJ1ZmZlciA9IG5ldyBVaW50OEFycmF5KDE2KTsKICAgIHRoaXMuYnVmZmVyUG9zaXRpb24gPSAwOwogIH0KICBfZXhwYW5kS2V5KGNpcGhlcktleSkgewogICAgdW5yZWFjaGFibGUoIkNhbm5vdCBjYWxsIGBfZXhwYW5kS2V5YCBvbiB0aGUgYmFzZSBjbGFzcyIpOwogIH0KICBfZGVjcnlwdChpbnB1dCwga2V5KSB7CiAgICBsZXQgdCwgdSwgdjsKICAgIGNvbnN0IHN0YXRlID0gbmV3IFVpbnQ4QXJyYXkoMTYpOwogICAgc3RhdGUuc2V0KGlucHV0KTsKICAgIGZvciAobGV0IGogPSAwLCBrID0gdGhpcy5fa2V5U2l6ZTsgaiA8IDE2OyArK2osICsraykgewogICAgICBzdGF0ZVtqXSBePSBrZXlba107CiAgICB9CiAgICBmb3IgKGxldCBpID0gdGhpcy5fY3ljbGVzT2ZSZXBldGl0aW9uIC0gMTsgaSA+PSAxOyAtLWkpIHsKICAgICAgdCA9IHN0YXRlWzEzXTsKICAgICAgc3RhdGVbMTNdID0gc3RhdGVbOV07CiAgICAgIHN0YXRlWzldID0gc3RhdGVbNV07CiAgICAgIHN0YXRlWzVdID0gc3RhdGVbMV07CiAgICAgIHN0YXRlWzFdID0gdDsKICAgICAgdCA9IHN0YXRlWzE0XTsKICAgICAgdSA9IHN0YXRlWzEwXTsKICAgICAgc3RhdGVbMTRdID0gc3RhdGVbNl07CiAgICAgIHN0YXRlWzEwXSA9IHN0YXRlWzJdOwogICAgICBzdGF0ZVs2XSA9IHQ7CiAgICAgIHN0YXRlWzJdID0gdTsKICAgICAgdCA9IHN0YXRlWzE1XTsKICAgICAgdSA9IHN0YXRlWzExXTsKICAgICAgdiA9IHN0YXRlWzddOwogICAgICBzdGF0ZVsxNV0gPSBzdGF0ZVszXTsKICAgICAgc3RhdGVbMTFdID0gdDsKICAgICAgc3RhdGVbN10gPSB1OwogICAgICBzdGF0ZVszXSA9IHY7CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgMTY7ICsraikgewogICAgICAgIHN0YXRlW2pdID0gdGhpcy5faW52X3Nbc3RhdGVbal1dOwogICAgICB9CiAgICAgIGZvciAobGV0IGogPSAwLCBrID0gaSAqIDE2OyBqIDwgMTY7ICsraiwgKytrKSB7CiAgICAgICAgc3RhdGVbal0gXj0ga2V5W2tdOwogICAgICB9CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgMTY7IGogKz0gNCkgewogICAgICAgIGNvbnN0IHMwID0gdGhpcy5fbWl4W3N0YXRlW2pdXTsKICAgICAgICBjb25zdCBzMSA9IHRoaXMuX21peFtzdGF0ZVtqICsgMV1dOwogICAgICAgIGNvbnN0IHMyID0gdGhpcy5fbWl4W3N0YXRlW2ogKyAyXV07CiAgICAgICAgY29uc3QgczMgPSB0aGlzLl9taXhbc3RhdGVbaiArIDNdXTsKICAgICAgICB0ID0gczAgXiBzMSA+Pj4gOCBeIHMxIDw8IDI0IF4gczIgPj4+IDE2IF4gczIgPDwgMTYgXiBzMyA+Pj4gMjQgXiBzMyA8PCA4OwogICAgICAgIHN0YXRlW2pdID0gdCA+Pj4gMjQgJiAweGZmOwogICAgICAgIHN0YXRlW2ogKyAxXSA9IHQgPj4gMTYgJiAweGZmOwogICAgICAgIHN0YXRlW2ogKyAyXSA9IHQgPj4gOCAmIDB4ZmY7CiAgICAgICAgc3RhdGVbaiArIDNdID0gdCAmIDB4ZmY7CiAgICAgIH0KICAgIH0KICAgIHQgPSBzdGF0ZVsxM107CiAgICBzdGF0ZVsxM10gPSBzdGF0ZVs5XTsKICAgIHN0YXRlWzldID0gc3RhdGVbNV07CiAgICBzdGF0ZVs1XSA9IHN0YXRlWzFdOwogICAgc3RhdGVbMV0gPSB0OwogICAgdCA9IHN0YXRlWzE0XTsKICAgIHUgPSBzdGF0ZVsxMF07CiAgICBzdGF0ZVsxNF0gPSBzdGF0ZVs2XTsKICAgIHN0YXRlWzEwXSA9IHN0YXRlWzJdOwogICAgc3RhdGVbNl0gPSB0OwogICAgc3RhdGVbMl0gPSB1OwogICAgdCA9IHN0YXRlWzE1XTsKICAgIHUgPSBzdGF0ZVsxMV07CiAgICB2ID0gc3RhdGVbN107CiAgICBzdGF0ZVsxNV0gPSBzdGF0ZVszXTsKICAgIHN0YXRlWzExXSA9IHQ7CiAgICBzdGF0ZVs3XSA9IHU7CiAgICBzdGF0ZVszXSA9IHY7CiAgICBmb3IgKGxldCBqID0gMDsgaiA8IDE2OyArK2opIHsKICAgICAgc3RhdGVbal0gPSB0aGlzLl9pbnZfc1tzdGF0ZVtqXV07CiAgICAgIHN0YXRlW2pdIF49IGtleVtqXTsKICAgIH0KICAgIHJldHVybiBzdGF0ZTsKICB9CiAgX2VuY3J5cHQoaW5wdXQsIGtleSkgewogICAgY29uc3QgcyA9IHRoaXMuX3M7CiAgICBsZXQgdCwgdSwgdjsKICAgIGNvbnN0IHN0YXRlID0gbmV3IFVpbnQ4QXJyYXkoMTYpOwogICAgc3RhdGUuc2V0KGlucHV0KTsKICAgIGZvciAobGV0IGogPSAwOyBqIDwgMTY7ICsraikgewogICAgICBzdGF0ZVtqXSBePSBrZXlbal07CiAgICB9CiAgICBmb3IgKGxldCBpID0gMTsgaSA8IHRoaXMuX2N5Y2xlc09mUmVwZXRpdGlvbjsgaSsrKSB7CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgMTY7ICsraikgewogICAgICAgIHN0YXRlW2pdID0gc1tzdGF0ZVtqXV07CiAgICAgIH0KICAgICAgdiA9IHN0YXRlWzFdOwogICAgICBzdGF0ZVsxXSA9IHN0YXRlWzVdOwogICAgICBzdGF0ZVs1XSA9IHN0YXRlWzldOwogICAgICBzdGF0ZVs5XSA9IHN0YXRlWzEzXTsKICAgICAgc3RhdGVbMTNdID0gdjsKICAgICAgdiA9IHN0YXRlWzJdOwogICAgICB1ID0gc3RhdGVbNl07CiAgICAgIHN0YXRlWzJdID0gc3RhdGVbMTBdOwogICAgICBzdGF0ZVs2XSA9IHN0YXRlWzE0XTsKICAgICAgc3RhdGVbMTBdID0gdjsKICAgICAgc3RhdGVbMTRdID0gdTsKICAgICAgdiA9IHN0YXRlWzNdOwogICAgICB1ID0gc3RhdGVbN107CiAgICAgIHQgPSBzdGF0ZVsxMV07CiAgICAgIHN0YXRlWzNdID0gc3RhdGVbMTVdOwogICAgICBzdGF0ZVs3XSA9IHY7CiAgICAgIHN0YXRlWzExXSA9IHU7CiAgICAgIHN0YXRlWzE1XSA9IHQ7CiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgMTY7IGogKz0gNCkgewogICAgICAgIGNvbnN0IHMwID0gc3RhdGVbal07CiAgICAgICAgY29uc3QgczEgPSBzdGF0ZVtqICsgMV07CiAgICAgICAgY29uc3QgczIgPSBzdGF0ZVtqICsgMl07CiAgICAgICAgY29uc3QgczMgPSBzdGF0ZVtqICsgM107CiAgICAgICAgdCA9IHMwIF4gczEgXiBzMiBeIHMzOwogICAgICAgIHN0YXRlW2pdIF49IHQgXiB0aGlzLl9taXhDb2xbczAgXiBzMV07CiAgICAgICAgc3RhdGVbaiArIDFdIF49IHQgXiB0aGlzLl9taXhDb2xbczEgXiBzMl07CiAgICAgICAgc3RhdGVbaiArIDJdIF49IHQgXiB0aGlzLl9taXhDb2xbczIgXiBzM107CiAgICAgICAgc3RhdGVbaiArIDNdIF49IHQgXiB0aGlzLl9taXhDb2xbczMgXiBzMF07CiAgICAgIH0KICAgICAgZm9yIChsZXQgaiA9IDAsIGsgPSBpICogMTY7IGogPCAxNjsgKytqLCArK2spIHsKICAgICAgICBzdGF0ZVtqXSBePSBrZXlba107CiAgICAgIH0KICAgIH0KICAgIGZvciAobGV0IGogPSAwOyBqIDwgMTY7ICsraikgewogICAgICBzdGF0ZVtqXSA9IHNbc3RhdGVbal1dOwogICAgfQogICAgdiA9IHN0YXRlWzFdOwogICAgc3RhdGVbMV0gPSBzdGF0ZVs1XTsKICAgIHN0YXRlWzVdID0gc3RhdGVbOV07CiAgICBzdGF0ZVs5XSA9IHN0YXRlWzEzXTsKICAgIHN0YXRlWzEzXSA9IHY7CiAgICB2ID0gc3RhdGVbMl07CiAgICB1ID0gc3RhdGVbNl07CiAgICBzdGF0ZVsyXSA9IHN0YXRlWzEwXTsKICAgIHN0YXRlWzZdID0gc3RhdGVbMTRdOwogICAgc3RhdGVbMTBdID0gdjsKICAgIHN0YXRlWzE0XSA9IHU7CiAgICB2ID0gc3RhdGVbM107CiAgICB1ID0gc3RhdGVbN107CiAgICB0ID0gc3RhdGVbMTFdOwogICAgc3RhdGVbM10gPSBzdGF0ZVsxNV07CiAgICBzdGF0ZVs3XSA9IHY7CiAgICBzdGF0ZVsxMV0gPSB1OwogICAgc3RhdGVbMTVdID0gdDsKICAgIGZvciAobGV0IGogPSAwLCBrID0gdGhpcy5fa2V5U2l6ZTsgaiA8IDE2OyArK2osICsraykgewogICAgICBzdGF0ZVtqXSBePSBrZXlba107CiAgICB9CiAgICByZXR1cm4gc3RhdGU7CiAgfQogIF9kZWNyeXB0QmxvY2syKGRhdGEsIGZpbmFsaXplKSB7CiAgICBjb25zdCBzb3VyY2VMZW5ndGggPSBkYXRhLmxlbmd0aDsKICAgIGxldCBidWZmZXIgPSB0aGlzLmJ1ZmZlciwKICAgICAgYnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXJQb3NpdGlvbjsKICAgIGNvbnN0IHJlc3VsdCA9IFtdOwogICAgbGV0IGl2ID0gdGhpcy5pdjsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc291cmNlTGVuZ3RoOyArK2kpIHsKICAgICAgYnVmZmVyW2J1ZmZlckxlbmd0aF0gPSBkYXRhW2ldOwogICAgICArK2J1ZmZlckxlbmd0aDsKICAgICAgaWYgKGJ1ZmZlckxlbmd0aCA8IDE2KSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgcGxhaW4gPSB0aGlzLl9kZWNyeXB0KGJ1ZmZlciwgdGhpcy5fa2V5KTsKICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCAxNjsgKytqKSB7CiAgICAgICAgcGxhaW5bal0gXj0gaXZbal07CiAgICAgIH0KICAgICAgaXYgPSBidWZmZXI7CiAgICAgIHJlc3VsdC5wdXNoKHBsYWluKTsKICAgICAgYnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoMTYpOwogICAgICBidWZmZXJMZW5ndGggPSAwOwogICAgfQogICAgdGhpcy5idWZmZXIgPSBidWZmZXI7CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IGJ1ZmZlckxlbmd0aDsKICAgIHRoaXMuaXYgPSBpdjsKICAgIGlmIChyZXN1bHQubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBuZXcgVWludDhBcnJheSgwKTsKICAgIH0KICAgIGxldCBvdXRwdXRMZW5ndGggPSAxNiAqIHJlc3VsdC5sZW5ndGg7CiAgICBpZiAoZmluYWxpemUpIHsKICAgICAgY29uc3QgbGFzdEJsb2NrID0gcmVzdWx0LmF0KC0xKTsKICAgICAgbGV0IHBzTGVuID0gbGFzdEJsb2NrWzE1XTsKICAgICAgaWYgKHBzTGVuIDw9IDE2KSB7CiAgICAgICAgZm9yIChsZXQgaSA9IDE1LCBpaSA9IDE2IC0gcHNMZW47IGkgPj0gaWk7IC0taSkgewogICAgICAgICAgaWYgKGxhc3RCbG9ja1tpXSAhPT0gcHNMZW4pIHsKICAgICAgICAgICAgcHNMZW4gPSAwOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgb3V0cHV0TGVuZ3RoIC09IHBzTGVuOwogICAgICAgIHJlc3VsdFtyZXN1bHQubGVuZ3RoIC0gMV0gPSBsYXN0QmxvY2suc3ViYXJyYXkoMCwgMTYgLSBwc0xlbik7CiAgICAgIH0KICAgIH0KICAgIGNvbnN0IG91dHB1dCA9IG5ldyBVaW50OEFycmF5KG91dHB1dExlbmd0aCk7CiAgICBmb3IgKGxldCBpID0gMCwgaiA9IDAsIGlpID0gcmVzdWx0Lmxlbmd0aDsgaSA8IGlpOyArK2ksIGogKz0gMTYpIHsKICAgICAgb3V0cHV0LnNldChyZXN1bHRbaV0sIGopOwogICAgfQogICAgcmV0dXJuIG91dHB1dDsKICB9CiAgZGVjcnlwdEJsb2NrKGRhdGEsIGZpbmFsaXplLCBpdiA9IG51bGwpIHsKICAgIGNvbnN0IHNvdXJjZUxlbmd0aCA9IGRhdGEubGVuZ3RoOwogICAgY29uc3QgYnVmZmVyID0gdGhpcy5idWZmZXI7CiAgICBsZXQgYnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXJQb3NpdGlvbjsKICAgIGlmIChpdikgewogICAgICB0aGlzLml2ID0gaXY7CiAgICB9IGVsc2UgewogICAgICBmb3IgKGxldCBpID0gMDsgYnVmZmVyTGVuZ3RoIDwgMTYgJiYgaSA8IHNvdXJjZUxlbmd0aDsgKytpLCArK2J1ZmZlckxlbmd0aCkgewogICAgICAgIGJ1ZmZlcltidWZmZXJMZW5ndGhdID0gZGF0YVtpXTsKICAgICAgfQogICAgICBpZiAoYnVmZmVyTGVuZ3RoIDwgMTYpIHsKICAgICAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IGJ1ZmZlckxlbmd0aDsKICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoMCk7CiAgICAgIH0KICAgICAgdGhpcy5pdiA9IGJ1ZmZlcjsKICAgICAgZGF0YSA9IGRhdGEuc3ViYXJyYXkoMTYpOwogICAgfQogICAgdGhpcy5idWZmZXIgPSBuZXcgVWludDhBcnJheSgxNik7CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IDA7CiAgICB0aGlzLmRlY3J5cHRCbG9jayA9IHRoaXMuX2RlY3J5cHRCbG9jazI7CiAgICByZXR1cm4gdGhpcy5kZWNyeXB0QmxvY2soZGF0YSwgZmluYWxpemUpOwogIH0KICBlbmNyeXB0KGRhdGEsIGl2KSB7CiAgICBjb25zdCBzb3VyY2VMZW5ndGggPSBkYXRhLmxlbmd0aDsKICAgIGxldCBidWZmZXIgPSB0aGlzLmJ1ZmZlciwKICAgICAgYnVmZmVyTGVuZ3RoID0gdGhpcy5idWZmZXJQb3NpdGlvbjsKICAgIGNvbnN0IHJlc3VsdCA9IFtdOwogICAgaXYgfHw9IG5ldyBVaW50OEFycmF5KDE2KTsKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc291cmNlTGVuZ3RoOyArK2kpIHsKICAgICAgYnVmZmVyW2J1ZmZlckxlbmd0aF0gPSBkYXRhW2ldOwogICAgICArK2J1ZmZlckxlbmd0aDsKICAgICAgaWYgKGJ1ZmZlckxlbmd0aCA8IDE2KSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCAxNjsgKytqKSB7CiAgICAgICAgYnVmZmVyW2pdIF49IGl2W2pdOwogICAgICB9CiAgICAgIGNvbnN0IGNpcGhlciA9IHRoaXMuX2VuY3J5cHQoYnVmZmVyLCB0aGlzLl9rZXkpOwogICAgICBpdiA9IGNpcGhlcjsKICAgICAgcmVzdWx0LnB1c2goY2lwaGVyKTsKICAgICAgYnVmZmVyID0gbmV3IFVpbnQ4QXJyYXkoMTYpOwogICAgICBidWZmZXJMZW5ndGggPSAwOwogICAgfQogICAgdGhpcy5idWZmZXIgPSBidWZmZXI7CiAgICB0aGlzLmJ1ZmZlckxlbmd0aCA9IGJ1ZmZlckxlbmd0aDsKICAgIHRoaXMuaXYgPSBpdjsKICAgIGlmIChyZXN1bHQubGVuZ3RoID09PSAwKSB7CiAgICAgIHJldHVybiBuZXcgVWludDhBcnJheSgwKTsKICAgIH0KICAgIGNvbnN0IG91dHB1dExlbmd0aCA9IDE2ICogcmVzdWx0Lmxlbmd0aDsKICAgIGNvbnN0IG91dHB1dCA9IG5ldyBVaW50OEFycmF5KG91dHB1dExlbmd0aCk7CiAgICBmb3IgKGxldCBpID0gMCwgaiA9IDAsIGlpID0gcmVzdWx0Lmxlbmd0aDsgaSA8IGlpOyArK2ksIGogKz0gMTYpIHsKICAgICAgb3V0cHV0LnNldChyZXN1bHRbaV0sIGopOwogICAgfQogICAgcmV0dXJuIG91dHB1dDsKICB9Cn0KY2xhc3MgQUVTMTI4Q2lwaGVyIGV4dGVuZHMgQUVTQmFzZUNpcGhlciB7CiAgX3Jjb24gPSBuZXcgVWludDhBcnJheShbMHg4ZCwgMHgwMSwgMHgwMiwgMHgwNCwgMHgwOCwgMHgxMCwgMHgyMCwgMHg0MCwgMHg4MCwgMHgxYiwgMHgzNiwgMHg2YywgMHhkOCwgMHhhYiwgMHg0ZCwgMHg5YSwgMHgyZiwgMHg1ZSwgMHhiYywgMHg2MywgMHhjNiwgMHg5NywgMHgzNSwgMHg2YSwgMHhkNCwgMHhiMywgMHg3ZCwgMHhmYSwgMHhlZiwgMHhjNSwgMHg5MSwgMHgzOSwgMHg3MiwgMHhlNCwgMHhkMywgMHhiZCwgMHg2MSwgMHhjMiwgMHg5ZiwgMHgyNSwgMHg0YSwgMHg5NCwgMHgzMywgMHg2NiwgMHhjYywgMHg4MywgMHgxZCwgMHgzYSwgMHg3NCwgMHhlOCwgMHhjYiwgMHg4ZCwgMHgwMSwgMHgwMiwgMHgwNCwgMHgwOCwgMHgxMCwgMHgyMCwgMHg0MCwgMHg4MCwgMHgxYiwgMHgzNiwgMHg2YywgMHhkOCwgMHhhYiwgMHg0ZCwgMHg5YSwgMHgyZiwgMHg1ZSwgMHhiYywgMHg2MywgMHhjNiwgMHg5NywgMHgzNSwgMHg2YSwgMHhkNCwgMHhiMywgMHg3ZCwgMHhmYSwgMHhlZiwgMHhjNSwgMHg5MSwgMHgzOSwgMHg3MiwgMHhlNCwgMHhkMywgMHhiZCwgMHg2MSwgMHhjMiwgMHg5ZiwgMHgyNSwgMHg0YSwgMHg5NCwgMHgzMywgMHg2NiwgMHhjYywgMHg4MywgMHgxZCwgMHgzYSwgMHg3NCwgMHhlOCwgMHhjYiwgMHg4ZCwgMHgwMSwgMHgwMiwgMHgwNCwgMHgwOCwgMHgxMCwgMHgyMCwgMHg0MCwgMHg4MCwgMHgxYiwgMHgzNiwgMHg2YywgMHhkOCwgMHhhYiwgMHg0ZCwgMHg5YSwgMHgyZiwgMHg1ZSwgMHhiYywgMHg2MywgMHhjNiwgMHg5NywgMHgzNSwgMHg2YSwgMHhkNCwgMHhiMywgMHg3ZCwgMHhmYSwgMHhlZiwgMHhjNSwgMHg5MSwgMHgzOSwgMHg3MiwgMHhlNCwgMHhkMywgMHhiZCwgMHg2MSwgMHhjMiwgMHg5ZiwgMHgyNSwgMHg0YSwgMHg5NCwgMHgzMywgMHg2NiwgMHhjYywgMHg4MywgMHgxZCwgMHgzYSwgMHg3NCwgMHhlOCwgMHhjYiwgMHg4ZCwgMHgwMSwgMHgwMiwgMHgwNCwgMHgwOCwgMHgxMCwgMHgyMCwgMHg0MCwgMHg4MCwgMHgxYiwgMHgzNiwgMHg2YywgMHhkOCwgMHhhYiwgMHg0ZCwgMHg5YSwgMHgyZiwgMHg1ZSwgMHhiYywgMHg2MywgMHhjNiwgMHg5NywgMHgzNSwgMHg2YSwgMHhkNCwgMHhiMywgMHg3ZCwgMHhmYSwgMHhlZiwgMHhjNSwgMHg5MSwgMHgzOSwgMHg3MiwgMHhlNCwgMHhkMywgMHhiZCwgMHg2MSwgMHhjMiwgMHg5ZiwgMHgyNSwgMHg0YSwgMHg5NCwgMHgzMywgMHg2NiwgMHhjYywgMHg4MywgMHgxZCwgMHgzYSwgMHg3NCwgMHhlOCwgMHhjYiwgMHg4ZCwgMHgwMSwgMHgwMiwgMHgwNCwgMHgwOCwgMHgxMCwgMHgyMCwgMHg0MCwgMHg4MCwgMHgxYiwgMHgzNiwgMHg2YywgMHhkOCwgMHhhYiwgMHg0ZCwgMHg5YSwgMHgyZiwgMHg1ZSwgMHhiYywgMHg2MywgMHhjNiwgMHg5NywgMHgzNSwgMHg2YSwgMHhkNCwgMHhiMywgMHg3ZCwgMHhmYSwgMHhlZiwgMHhjNSwgMHg5MSwgMHgzOSwgMHg3MiwgMHhlNCwgMHhkMywgMHhiZCwgMHg2MSwgMHhjMiwgMHg5ZiwgMHgyNSwgMHg0YSwgMHg5NCwgMHgzMywgMHg2NiwgMHhjYywgMHg4MywgMHgxZCwgMHgzYSwgMHg3NCwgMHhlOCwgMHhjYiwgMHg4ZF0pOwogIGNvbnN0cnVjdG9yKGtleSkgewogICAgc3VwZXIoKTsKICAgIHRoaXMuX2N5Y2xlc09mUmVwZXRpdGlvbiA9IDEwOwogICAgdGhpcy5fa2V5U2l6ZSA9IDE2MDsKICAgIHRoaXMuX2tleSA9IHRoaXMuX2V4cGFuZEtleShrZXkpOwogIH0KICBfZXhwYW5kS2V5KGNpcGhlcktleSkgewogICAgY29uc3QgYiA9IDE3NjsKICAgIGNvbnN0IHMgPSB0aGlzLl9zOwogICAgY29uc3QgcmNvbiA9IHRoaXMuX3Jjb247CiAgICBjb25zdCByZXN1bHQgPSBuZXcgVWludDhBcnJheShiKTsKICAgIHJlc3VsdC5zZXQoY2lwaGVyS2V5KTsKICAgIGZvciAobGV0IGogPSAxNiwgaSA9IDE7IGogPCBiOyArK2kpIHsKICAgICAgbGV0IHQxID0gcmVzdWx0W2ogLSAzXTsKICAgICAgbGV0IHQyID0gcmVzdWx0W2ogLSAyXTsKICAgICAgbGV0IHQzID0gcmVzdWx0W2ogLSAxXTsKICAgICAgbGV0IHQ0ID0gcmVzdWx0W2ogLSA0XTsKICAgICAgdDEgPSBzW3QxXTsKICAgICAgdDIgPSBzW3QyXTsKICAgICAgdDMgPSBzW3QzXTsKICAgICAgdDQgPSBzW3Q0XTsKICAgICAgdDEgXj0gcmNvbltpXTsKICAgICAgZm9yIChsZXQgbiA9IDA7IG4gPCA0OyArK24pIHsKICAgICAgICByZXN1bHRbal0gPSB0MSBePSByZXN1bHRbaiAtIDE2XTsKICAgICAgICBqKys7CiAgICAgICAgcmVzdWx0W2pdID0gdDIgXj0gcmVzdWx0W2ogLSAxNl07CiAgICAgICAgaisrOwogICAgICAgIHJlc3VsdFtqXSA9IHQzIF49IHJlc3VsdFtqIC0gMTZdOwogICAgICAgIGorKzsKICAgICAgICByZXN1bHRbal0gPSB0NCBePSByZXN1bHRbaiAtIDE2XTsKICAgICAgICBqKys7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfQp9CmNsYXNzIEFFUzI1NkNpcGhlciBleHRlbmRzIEFFU0Jhc2VDaXBoZXIgewogIGNvbnN0cnVjdG9yKGtleSkgewogICAgc3VwZXIoKTsKICAgIHRoaXMuX2N5Y2xlc09mUmVwZXRpdGlvbiA9IDE0OwogICAgdGhpcy5fa2V5U2l6ZSA9IDIyNDsKICAgIHRoaXMuX2tleSA9IHRoaXMuX2V4cGFuZEtleShrZXkpOwogIH0KICBfZXhwYW5kS2V5KGNpcGhlcktleSkgewogICAgY29uc3QgYiA9IDI0MDsKICAgIGNvbnN0IHMgPSB0aGlzLl9zOwogICAgY29uc3QgcmVzdWx0ID0gbmV3IFVpbnQ4QXJyYXkoYik7CiAgICByZXN1bHQuc2V0KGNpcGhlcktleSk7CiAgICBsZXQgciA9IDE7CiAgICBsZXQgdDEsIHQyLCB0MywgdDQ7CiAgICBmb3IgKGxldCBqID0gMzIsIGkgPSAxOyBqIDwgYjsgKytpKSB7CiAgICAgIGlmIChqICUgMzIgPT09IDE2KSB7CiAgICAgICAgdDEgPSBzW3QxXTsKICAgICAgICB0MiA9IHNbdDJdOwogICAgICAgIHQzID0gc1t0M107CiAgICAgICAgdDQgPSBzW3Q0XTsKICAgICAgfSBlbHNlIGlmIChqICUgMzIgPT09IDApIHsKICAgICAgICB0MSA9IHJlc3VsdFtqIC0gM107CiAgICAgICAgdDIgPSByZXN1bHRbaiAtIDJdOwogICAgICAgIHQzID0gcmVzdWx0W2ogLSAxXTsKICAgICAgICB0NCA9IHJlc3VsdFtqIC0gNF07CiAgICAgICAgdDEgPSBzW3QxXTsKICAgICAgICB0MiA9IHNbdDJdOwogICAgICAgIHQzID0gc1t0M107CiAgICAgICAgdDQgPSBzW3Q0XTsKICAgICAgICB0MSBePSByOwogICAgICAgIGlmICgociA8PD0gMSkgPj0gMjU2KSB7CiAgICAgICAgICByID0gKHIgXiAweDFiKSAmIDB4ZmY7CiAgICAgICAgfQogICAgICB9CiAgICAgIGZvciAobGV0IG4gPSAwOyBuIDwgNDsgKytuKSB7CiAgICAgICAgcmVzdWx0W2pdID0gdDEgXj0gcmVzdWx0W2ogLSAzMl07CiAgICAgICAgaisrOwogICAgICAgIHJlc3VsdFtqXSA9IHQyIF49IHJlc3VsdFtqIC0gMzJdOwogICAgICAgIGorKzsKICAgICAgICByZXN1bHRbal0gPSB0MyBePSByZXN1bHRbaiAtIDMyXTsKICAgICAgICBqKys7CiAgICAgICAgcmVzdWx0W2pdID0gdDQgXj0gcmVzdWx0W2ogLSAzMl07CiAgICAgICAgaisrOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gcmVzdWx0OwogIH0KfQpjbGFzcyBQREZCYXNlIHsKICBfaGFzaChwYXNzd29yZCwgaW5wdXQsIHVzZXJCeXRlcykgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgX2hhc2hgIGNhbGxlZCIpOwogIH0KICBjaGVja093bmVyUGFzc3dvcmQocGFzc3dvcmQsIG93bmVyVmFsaWRhdGlvblNhbHQsIHVzZXJCeXRlcywgb3duZXJQYXNzd29yZCkgewogICAgY29uc3QgaGFzaERhdGEgPSBuZXcgVWludDhBcnJheShwYXNzd29yZC5sZW5ndGggKyA1Nik7CiAgICBoYXNoRGF0YS5zZXQocGFzc3dvcmQsIDApOwogICAgaGFzaERhdGEuc2V0KG93bmVyVmFsaWRhdGlvblNhbHQsIHBhc3N3b3JkLmxlbmd0aCk7CiAgICBoYXNoRGF0YS5zZXQodXNlckJ5dGVzLCBwYXNzd29yZC5sZW5ndGggKyBvd25lclZhbGlkYXRpb25TYWx0Lmxlbmd0aCk7CiAgICBjb25zdCByZXN1bHQgPSB0aGlzLl9oYXNoKHBhc3N3b3JkLCBoYXNoRGF0YSwgdXNlckJ5dGVzKTsKICAgIHJldHVybiBpc0FycmF5RXF1YWwocmVzdWx0LCBvd25lclBhc3N3b3JkKTsKICB9CiAgY2hlY2tVc2VyUGFzc3dvcmQocGFzc3dvcmQsIHVzZXJWYWxpZGF0aW9uU2FsdCwgdXNlclBhc3N3b3JkKSB7CiAgICBjb25zdCBoYXNoRGF0YSA9IG5ldyBVaW50OEFycmF5KHBhc3N3b3JkLmxlbmd0aCArIDgpOwogICAgaGFzaERhdGEuc2V0KHBhc3N3b3JkLCAwKTsKICAgIGhhc2hEYXRhLnNldCh1c2VyVmFsaWRhdGlvblNhbHQsIHBhc3N3b3JkLmxlbmd0aCk7CiAgICBjb25zdCByZXN1bHQgPSB0aGlzLl9oYXNoKHBhc3N3b3JkLCBoYXNoRGF0YSwgW10pOwogICAgcmV0dXJuIGlzQXJyYXlFcXVhbChyZXN1bHQsIHVzZXJQYXNzd29yZCk7CiAgfQogIGdldE93bmVyS2V5KHBhc3N3b3JkLCBvd25lcktleVNhbHQsIHVzZXJCeXRlcywgb3duZXJFbmNyeXB0aW9uKSB7CiAgICBjb25zdCBoYXNoRGF0YSA9IG5ldyBVaW50OEFycmF5KHBhc3N3b3JkLmxlbmd0aCArIDU2KTsKICAgIGhhc2hEYXRhLnNldChwYXNzd29yZCwgMCk7CiAgICBoYXNoRGF0YS5zZXQob3duZXJLZXlTYWx0LCBwYXNzd29yZC5sZW5ndGgpOwogICAgaGFzaERhdGEuc2V0KHVzZXJCeXRlcywgcGFzc3dvcmQubGVuZ3RoICsgb3duZXJLZXlTYWx0Lmxlbmd0aCk7CiAgICBjb25zdCBrZXkgPSB0aGlzLl9oYXNoKHBhc3N3b3JkLCBoYXNoRGF0YSwgdXNlckJ5dGVzKTsKICAgIGNvbnN0IGNpcGhlciA9IG5ldyBBRVMyNTZDaXBoZXIoa2V5KTsKICAgIHJldHVybiBjaXBoZXIuZGVjcnlwdEJsb2NrKG93bmVyRW5jcnlwdGlvbiwgZmFsc2UsIG5ldyBVaW50OEFycmF5KDE2KSk7CiAgfQogIGdldFVzZXJLZXkocGFzc3dvcmQsIHVzZXJLZXlTYWx0LCB1c2VyRW5jcnlwdGlvbikgewogICAgY29uc3QgaGFzaERhdGEgPSBuZXcgVWludDhBcnJheShwYXNzd29yZC5sZW5ndGggKyA4KTsKICAgIGhhc2hEYXRhLnNldChwYXNzd29yZCwgMCk7CiAgICBoYXNoRGF0YS5zZXQodXNlcktleVNhbHQsIHBhc3N3b3JkLmxlbmd0aCk7CiAgICBjb25zdCBrZXkgPSB0aGlzLl9oYXNoKHBhc3N3b3JkLCBoYXNoRGF0YSwgW10pOwogICAgY29uc3QgY2lwaGVyID0gbmV3IEFFUzI1NkNpcGhlcihrZXkpOwogICAgcmV0dXJuIGNpcGhlci5kZWNyeXB0QmxvY2sodXNlckVuY3J5cHRpb24sIGZhbHNlLCBuZXcgVWludDhBcnJheSgxNikpOwogIH0KfQpjbGFzcyBQREYxNyBleHRlbmRzIFBERkJhc2UgewogIF9oYXNoKHBhc3N3b3JkLCBpbnB1dCwgdXNlckJ5dGVzKSB7CiAgICByZXR1cm4gY2FsY3VsYXRlU0hBMjU2KGlucHV0LCAwLCBpbnB1dC5sZW5ndGgpOwogIH0KfQpjbGFzcyBQREYyMCBleHRlbmRzIFBERkJhc2UgewogIF9oYXNoKHBhc3N3b3JkLCBpbnB1dCwgdXNlckJ5dGVzKSB7CiAgICBsZXQgayA9IGNhbGN1bGF0ZVNIQTI1NihpbnB1dCwgMCwgaW5wdXQubGVuZ3RoKS5zdWJhcnJheSgwLCAzMik7CiAgICBsZXQgZSA9IFswXTsKICAgIGxldCBpID0gMDsKICAgIHdoaWxlIChpIDwgNjQgfHwgZS5hdCgtMSkgPiBpIC0gMzIpIHsKICAgICAgY29uc3QgY29tYmluZWRMZW5ndGggPSBwYXNzd29yZC5sZW5ndGggKyBrLmxlbmd0aCArIHVzZXJCeXRlcy5sZW5ndGgsCiAgICAgICAgY29tYmluZWRBcnJheSA9IG5ldyBVaW50OEFycmF5KGNvbWJpbmVkTGVuZ3RoKTsKICAgICAgbGV0IHdyaXRlT2Zmc2V0ID0gMDsKICAgICAgY29tYmluZWRBcnJheS5zZXQocGFzc3dvcmQsIHdyaXRlT2Zmc2V0KTsKICAgICAgd3JpdGVPZmZzZXQgKz0gcGFzc3dvcmQubGVuZ3RoOwogICAgICBjb21iaW5lZEFycmF5LnNldChrLCB3cml0ZU9mZnNldCk7CiAgICAgIHdyaXRlT2Zmc2V0ICs9IGsubGVuZ3RoOwogICAgICBjb21iaW5lZEFycmF5LnNldCh1c2VyQnl0ZXMsIHdyaXRlT2Zmc2V0KTsKICAgICAgY29uc3QgazEgPSBuZXcgVWludDhBcnJheShjb21iaW5lZExlbmd0aCAqIDY0KTsKICAgICAgZm9yIChsZXQgaiA9IDAsIHBvcyA9IDA7IGogPCA2NDsgaisrLCBwb3MgKz0gY29tYmluZWRMZW5ndGgpIHsKICAgICAgICBrMS5zZXQoY29tYmluZWRBcnJheSwgcG9zKTsKICAgICAgfQogICAgICBjb25zdCBjaXBoZXIgPSBuZXcgQUVTMTI4Q2lwaGVyKGsuc3ViYXJyYXkoMCwgMTYpKTsKICAgICAgZSA9IGNpcGhlci5lbmNyeXB0KGsxLCBrLnN1YmFycmF5KDE2LCAzMikpOwogICAgICBjb25zdCByZW1haW5kZXIgPSBNYXRoLnN1bVByZWNpc2UoZS5zbGljZSgwLCAxNikpICUgMzsKICAgICAgaWYgKHJlbWFpbmRlciA9PT0gMCkgewogICAgICAgIGsgPSBjYWxjdWxhdGVTSEEyNTYoZSwgMCwgZS5sZW5ndGgpOwogICAgICB9IGVsc2UgaWYgKHJlbWFpbmRlciA9PT0gMSkgewogICAgICAgIGsgPSBjYWxjdWxhdGVTSEEzODQoZSwgMCwgZS5sZW5ndGgpOwogICAgICB9IGVsc2UgaWYgKHJlbWFpbmRlciA9PT0gMikgewogICAgICAgIGsgPSBjYWxjdWxhdGVTSEE1MTIoZSwgMCwgZS5sZW5ndGgpOwogICAgICB9CiAgICAgIGkrKzsKICAgIH0KICAgIHJldHVybiBrLnN1YmFycmF5KDAsIDMyKTsKICB9Cn0KY2xhc3MgQ2lwaGVyVHJhbnNmb3JtIHsKICBjb25zdHJ1Y3RvcihzdHJpbmdDaXBoZXJDb25zdHJ1Y3Rvciwgc3RyZWFtQ2lwaGVyQ29uc3RydWN0b3IpIHsKICAgIHRoaXMuU3RyaW5nQ2lwaGVyQ29uc3RydWN0b3IgPSBzdHJpbmdDaXBoZXJDb25zdHJ1Y3RvcjsKICAgIHRoaXMuU3RyZWFtQ2lwaGVyQ29uc3RydWN0b3IgPSBzdHJlYW1DaXBoZXJDb25zdHJ1Y3RvcjsKICB9CiAgY3JlYXRlU3RyZWFtKHN0cmVhbSwgbGVuZ3RoKSB7CiAgICBjb25zdCBjaXBoZXIgPSBuZXcgdGhpcy5TdHJlYW1DaXBoZXJDb25zdHJ1Y3RvcigpOwogICAgcmV0dXJuIG5ldyBEZWNyeXB0U3RyZWFtKHN0cmVhbSwgbGVuZ3RoLCBmdW5jdGlvbiBjaXBoZXJUcmFuc2Zvcm1EZWNyeXB0U3RyZWFtKGRhdGEsIGZpbmFsaXplKSB7CiAgICAgIHJldHVybiBjaXBoZXIuZGVjcnlwdEJsb2NrKGRhdGEsIGZpbmFsaXplKTsKICAgIH0pOwogIH0KICBkZWNyeXB0U3RyaW5nKHMpIHsKICAgIGNvbnN0IGNpcGhlciA9IG5ldyB0aGlzLlN0cmluZ0NpcGhlckNvbnN0cnVjdG9yKCk7CiAgICBsZXQgZGF0YSA9IHN0cmluZ1RvQnl0ZXMocyk7CiAgICBkYXRhID0gY2lwaGVyLmRlY3J5cHRCbG9jayhkYXRhLCB0cnVlKTsKICAgIHJldHVybiBieXRlc1RvU3RyaW5nKGRhdGEpOwogIH0KICBlbmNyeXB0U3RyaW5nKHMpIHsKICAgIGNvbnN0IGNpcGhlciA9IG5ldyB0aGlzLlN0cmluZ0NpcGhlckNvbnN0cnVjdG9yKCk7CiAgICBpZiAoY2lwaGVyIGluc3RhbmNlb2YgQUVTQmFzZUNpcGhlcikgewogICAgICBjb25zdCBzdHJMZW4gPSBzLmxlbmd0aDsKICAgICAgY29uc3QgcGFkID0gMTYgLSBzdHJMZW4gJSAxNjsKICAgICAgcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKHBhZCkucmVwZWF0KHBhZCk7CiAgICAgIGNvbnN0IGl2ID0gbmV3IFVpbnQ4QXJyYXkoMTYpOwogICAgICBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKGl2KTsKICAgICAgbGV0IGRhdGEgPSBzdHJpbmdUb0J5dGVzKHMpOwogICAgICBkYXRhID0gY2lwaGVyLmVuY3J5cHQoZGF0YSwgaXYpOwogICAgICBjb25zdCBidWYgPSBuZXcgVWludDhBcnJheSgxNiArIGRhdGEubGVuZ3RoKTsKICAgICAgYnVmLnNldChpdik7CiAgICAgIGJ1Zi5zZXQoZGF0YSwgMTYpOwogICAgICByZXR1cm4gYnl0ZXNUb1N0cmluZyhidWYpOwogICAgfQogICAgbGV0IGRhdGEgPSBzdHJpbmdUb0J5dGVzKHMpOwogICAgZGF0YSA9IGNpcGhlci5lbmNyeXB0KGRhdGEpOwogICAgcmV0dXJuIGJ5dGVzVG9TdHJpbmcoZGF0YSk7CiAgfQp9CmNsYXNzIENpcGhlclRyYW5zZm9ybUZhY3RvcnkgewogIHN0YXRpYyBnZXQgX2RlZmF1bHRQYXNzd29yZEJ5dGVzKCkgewogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiX2RlZmF1bHRQYXNzd29yZEJ5dGVzIiwgbmV3IFVpbnQ4QXJyYXkoWzB4MjgsIDB4YmYsIDB4NGUsIDB4NWUsIDB4NGUsIDB4NzUsIDB4OGEsIDB4NDEsIDB4NjQsIDB4MDAsIDB4NGUsIDB4NTYsIDB4ZmYsIDB4ZmEsIDB4MDEsIDB4MDgsIDB4MmUsIDB4MmUsIDB4MDAsIDB4YjYsIDB4ZDAsIDB4NjgsIDB4M2UsIDB4ODAsIDB4MmYsIDB4MGMsIDB4YTksIDB4ZmUsIDB4NjQsIDB4NTMsIDB4NjksIDB4N2FdKSk7CiAgfQogICNjcmVhdGVFbmNyeXB0aW9uS2V5MjAocmV2aXNpb24sIHBhc3N3b3JkLCBvd25lclBhc3N3b3JkLCBvd25lclZhbGlkYXRpb25TYWx0LCBvd25lcktleVNhbHQsIHVCeXRlcywgdXNlclBhc3N3b3JkLCB1c2VyVmFsaWRhdGlvblNhbHQsIHVzZXJLZXlTYWx0LCBvd25lckVuY3J5cHRpb24sIHVzZXJFbmNyeXB0aW9uLCBwZXJtcykgewogICAgaWYgKHBhc3N3b3JkKSB7CiAgICAgIGNvbnN0IHBhc3N3b3JkTGVuZ3RoID0gTWF0aC5taW4oMTI3LCBwYXNzd29yZC5sZW5ndGgpOwogICAgICBwYXNzd29yZCA9IHBhc3N3b3JkLnN1YmFycmF5KDAsIHBhc3N3b3JkTGVuZ3RoKTsKICAgIH0gZWxzZSB7CiAgICAgIHBhc3N3b3JkID0gW107CiAgICB9CiAgICBjb25zdCBwZGZBbGdvcml0aG0gPSByZXZpc2lvbiA9PT0gNiA/IG5ldyBQREYyMCgpIDogbmV3IFBERjE3KCk7CiAgICBpZiAocGRmQWxnb3JpdGhtLmNoZWNrVXNlclBhc3N3b3JkKHBhc3N3b3JkLCB1c2VyVmFsaWRhdGlvblNhbHQsIHVzZXJQYXNzd29yZCkpIHsKICAgICAgcmV0dXJuIHBkZkFsZ29yaXRobS5nZXRVc2VyS2V5KHBhc3N3b3JkLCB1c2VyS2V5U2FsdCwgdXNlckVuY3J5cHRpb24pOwogICAgfSBlbHNlIGlmIChwYXNzd29yZC5sZW5ndGggJiYgcGRmQWxnb3JpdGhtLmNoZWNrT3duZXJQYXNzd29yZChwYXNzd29yZCwgb3duZXJWYWxpZGF0aW9uU2FsdCwgdUJ5dGVzLCBvd25lclBhc3N3b3JkKSkgewogICAgICByZXR1cm4gcGRmQWxnb3JpdGhtLmdldE93bmVyS2V5KHBhc3N3b3JkLCBvd25lcktleVNhbHQsIHVCeXRlcywgb3duZXJFbmNyeXB0aW9uKTsKICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KICAjcHJlcGFyZUtleURhdGEoZmlsZUlkLCBwYXNzd29yZCwgb3duZXJQYXNzd29yZCwgdXNlclBhc3N3b3JkLCBmbGFncywgcmV2aXNpb24sIGtleUxlbmd0aCwgZW5jcnlwdE1ldGFkYXRhKSB7CiAgICBjb25zdCBoYXNoRGF0YVNpemUgPSA0MCArIG93bmVyUGFzc3dvcmQubGVuZ3RoICsgZmlsZUlkLmxlbmd0aDsKICAgIGNvbnN0IGhhc2hEYXRhID0gbmV3IFVpbnQ4QXJyYXkoaGFzaERhdGFTaXplKTsKICAgIGxldCBpID0gMCwKICAgICAgaiwKICAgICAgbjsKICAgIGlmIChwYXNzd29yZCkgewogICAgICBuID0gTWF0aC5taW4oMzIsIHBhc3N3b3JkLmxlbmd0aCk7CiAgICAgIGZvciAoOyBpIDwgbjsgKytpKSB7CiAgICAgICAgaGFzaERhdGFbaV0gPSBwYXNzd29yZFtpXTsKICAgICAgfQogICAgfQogICAgaiA9IDA7CiAgICB3aGlsZSAoaSA8IDMyKSB7CiAgICAgIGhhc2hEYXRhW2krK10gPSBDaXBoZXJUcmFuc2Zvcm1GYWN0b3J5Ll9kZWZhdWx0UGFzc3dvcmRCeXRlc1tqKytdOwogICAgfQogICAgaGFzaERhdGEuc2V0KG93bmVyUGFzc3dvcmQsIGkpOwogICAgaSArPSBvd25lclBhc3N3b3JkLmxlbmd0aDsKICAgIGhhc2hEYXRhW2krK10gPSBmbGFncyAmIDB4ZmY7CiAgICBoYXNoRGF0YVtpKytdID0gZmxhZ3MgPj4gOCAmIDB4ZmY7CiAgICBoYXNoRGF0YVtpKytdID0gZmxhZ3MgPj4gMTYgJiAweGZmOwogICAgaGFzaERhdGFbaSsrXSA9IGZsYWdzID4+PiAyNCAmIDB4ZmY7CiAgICBoYXNoRGF0YS5zZXQoZmlsZUlkLCBpKTsKICAgIGkgKz0gZmlsZUlkLmxlbmd0aDsKICAgIGlmIChyZXZpc2lvbiA+PSA0ICYmICFlbmNyeXB0TWV0YWRhdGEpIHsKICAgICAgaGFzaERhdGEuZmlsbCgweGZmLCBpLCBpICsgNCk7CiAgICAgIGkgKz0gNDsKICAgIH0KICAgIGxldCBoYXNoID0gY2FsY3VsYXRlTUQ1KGhhc2hEYXRhLCAwLCBpKTsKICAgIGNvbnN0IGtleUxlbmd0aEluQnl0ZXMgPSBrZXlMZW5ndGggPj4gMzsKICAgIGlmIChyZXZpc2lvbiA+PSAzKSB7CiAgICAgIGZvciAoaiA9IDA7IGogPCA1MDsgKytqKSB7CiAgICAgICAgaGFzaCA9IGNhbGN1bGF0ZU1ENShoYXNoLCAwLCBrZXlMZW5ndGhJbkJ5dGVzKTsKICAgICAgfQogICAgfQogICAgY29uc3QgZW5jcnlwdGlvbktleSA9IGhhc2guc3ViYXJyYXkoMCwga2V5TGVuZ3RoSW5CeXRlcyk7CiAgICBsZXQgY2lwaGVyLCBjaGVja0RhdGE7CiAgICBpZiAocmV2aXNpb24gPj0gMykgewogICAgICBpID0gMDsKICAgICAgaGFzaERhdGEuc2V0KENpcGhlclRyYW5zZm9ybUZhY3RvcnkuX2RlZmF1bHRQYXNzd29yZEJ5dGVzLCBpKTsKICAgICAgaSArPSAzMjsKICAgICAgaGFzaERhdGEuc2V0KGZpbGVJZCwgaSk7CiAgICAgIGkgKz0gZmlsZUlkLmxlbmd0aDsKICAgICAgY2lwaGVyID0gbmV3IEFSQ0ZvdXJDaXBoZXIoZW5jcnlwdGlvbktleSk7CiAgICAgIGNoZWNrRGF0YSA9IGNpcGhlci5lbmNyeXB0QmxvY2soY2FsY3VsYXRlTUQ1KGhhc2hEYXRhLCAwLCBpKSk7CiAgICAgIG4gPSBlbmNyeXB0aW9uS2V5Lmxlbmd0aDsKICAgICAgY29uc3QgZGVyaXZlZEtleSA9IG5ldyBVaW50OEFycmF5KG4pOwogICAgICBmb3IgKGogPSAxOyBqIDw9IDE5OyArK2opIHsKICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IG47ICsraykgewogICAgICAgICAgZGVyaXZlZEtleVtrXSA9IGVuY3J5cHRpb25LZXlba10gXiBqOwogICAgICAgIH0KICAgICAgICBjaXBoZXIgPSBuZXcgQVJDRm91ckNpcGhlcihkZXJpdmVkS2V5KTsKICAgICAgICBjaGVja0RhdGEgPSBjaXBoZXIuZW5jcnlwdEJsb2NrKGNoZWNrRGF0YSk7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGNpcGhlciA9IG5ldyBBUkNGb3VyQ2lwaGVyKGVuY3J5cHRpb25LZXkpOwogICAgICBjaGVja0RhdGEgPSBjaXBoZXIuZW5jcnlwdEJsb2NrKENpcGhlclRyYW5zZm9ybUZhY3RvcnkuX2RlZmF1bHRQYXNzd29yZEJ5dGVzKTsKICAgIH0KICAgIHJldHVybiBjaGVja0RhdGEuZXZlcnkoKGRhdGEsIGspID0+IHVzZXJQYXNzd29yZFtrXSA9PT0gZGF0YSkgPyBlbmNyeXB0aW9uS2V5IDogbnVsbDsKICB9CiAgI2RlY29kZVVzZXJQYXNzd29yZChwYXNzd29yZCwgb3duZXJQYXNzd29yZCwgcmV2aXNpb24sIGtleUxlbmd0aCkgewogICAgY29uc3QgaGFzaERhdGEgPSBuZXcgVWludDhBcnJheSgzMik7CiAgICBsZXQgaSA9IDA7CiAgICBjb25zdCBuID0gTWF0aC5taW4oMzIsIHBhc3N3b3JkLmxlbmd0aCk7CiAgICBmb3IgKDsgaSA8IG47ICsraSkgewogICAgICBoYXNoRGF0YVtpXSA9IHBhc3N3b3JkW2ldOwogICAgfQogICAgbGV0IGogPSAwOwogICAgd2hpbGUgKGkgPCAzMikgewogICAgICBoYXNoRGF0YVtpKytdID0gQ2lwaGVyVHJhbnNmb3JtRmFjdG9yeS5fZGVmYXVsdFBhc3N3b3JkQnl0ZXNbaisrXTsKICAgIH0KICAgIGxldCBoYXNoID0gY2FsY3VsYXRlTUQ1KGhhc2hEYXRhLCAwLCBpKTsKICAgIGNvbnN0IGtleUxlbmd0aEluQnl0ZXMgPSBrZXlMZW5ndGggPj4gMzsKICAgIGlmIChyZXZpc2lvbiA+PSAzKSB7CiAgICAgIGZvciAoaiA9IDA7IGogPCA1MDsgKytqKSB7CiAgICAgICAgaGFzaCA9IGNhbGN1bGF0ZU1ENShoYXNoLCAwLCBoYXNoLmxlbmd0aCk7CiAgICAgIH0KICAgIH0KICAgIGxldCBjaXBoZXIsIHVzZXJQYXNzd29yZDsKICAgIGlmIChyZXZpc2lvbiA+PSAzKSB7CiAgICAgIHVzZXJQYXNzd29yZCA9IG93bmVyUGFzc3dvcmQ7CiAgICAgIGNvbnN0IGRlcml2ZWRLZXkgPSBuZXcgVWludDhBcnJheShrZXlMZW5ndGhJbkJ5dGVzKTsKICAgICAgZm9yIChqID0gMTk7IGogPj0gMDsgai0tKSB7CiAgICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCBrZXlMZW5ndGhJbkJ5dGVzOyArK2spIHsKICAgICAgICAgIGRlcml2ZWRLZXlba10gPSBoYXNoW2tdIF4gajsKICAgICAgICB9CiAgICAgICAgY2lwaGVyID0gbmV3IEFSQ0ZvdXJDaXBoZXIoZGVyaXZlZEtleSk7CiAgICAgICAgdXNlclBhc3N3b3JkID0gY2lwaGVyLmVuY3J5cHRCbG9jayh1c2VyUGFzc3dvcmQpOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjaXBoZXIgPSBuZXcgQVJDRm91ckNpcGhlcihoYXNoLnN1YmFycmF5KDAsIGtleUxlbmd0aEluQnl0ZXMpKTsKICAgICAgdXNlclBhc3N3b3JkID0gY2lwaGVyLmVuY3J5cHRCbG9jayhvd25lclBhc3N3b3JkKTsKICAgIH0KICAgIHJldHVybiB1c2VyUGFzc3dvcmQ7CiAgfQogICNidWlsZE9iamVjdEtleShudW0sIGdlbiwgZW5jcnlwdGlvbktleSwgaXNBZXMgPSBmYWxzZSkgewogICAgY29uc3QgbiA9IGVuY3J5cHRpb25LZXkubGVuZ3RoOwogICAgY29uc3Qga2V5ID0gbmV3IFVpbnQ4QXJyYXkobiArIDkpOwogICAga2V5LnNldChlbmNyeXB0aW9uS2V5KTsKICAgIGxldCBpID0gbjsKICAgIGtleVtpKytdID0gbnVtICYgMHhmZjsKICAgIGtleVtpKytdID0gbnVtID4+IDggJiAweGZmOwogICAga2V5W2krK10gPSBudW0gPj4gMTYgJiAweGZmOwogICAga2V5W2krK10gPSBnZW4gJiAweGZmOwogICAga2V5W2krK10gPSBnZW4gPj4gOCAmIDB4ZmY7CiAgICBpZiAoaXNBZXMpIHsKICAgICAga2V5W2krK10gPSAweDczOwogICAgICBrZXlbaSsrXSA9IDB4NDE7CiAgICAgIGtleVtpKytdID0gMHg2YzsKICAgICAga2V5W2krK10gPSAweDU0OwogICAgfQogICAgY29uc3QgaGFzaCA9IGNhbGN1bGF0ZU1ENShrZXksIDAsIGkpOwogICAgcmV0dXJuIGhhc2guc3ViYXJyYXkoMCwgTWF0aC5taW4obiArIDUsIDE2KSk7CiAgfQogICNidWlsZENpcGhlckNvbnN0cnVjdG9yKGNmLCBuYW1lLCBudW0sIGdlbiwga2V5KSB7CiAgICBpZiAoIShuYW1lIGluc3RhbmNlb2YgTmFtZSkpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIGNyeXB0IGZpbHRlciBuYW1lLiIpOwogICAgfQogICAgY29uc3Qgc2VsZiA9IHRoaXM7CiAgICBjb25zdCBjcnlwdEZpbHRlciA9IGNmLmdldChuYW1lLm5hbWUpOwogICAgY29uc3QgY2ZtID0gY3J5cHRGaWx0ZXI/LmdldCgiQ0ZNIik7CiAgICBpZiAoIWNmbSB8fCBjZm0ubmFtZSA9PT0gIk5vbmUiKSB7CiAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7CiAgICAgICAgcmV0dXJuIG5ldyBOdWxsQ2lwaGVyKCk7CiAgICAgIH07CiAgICB9CiAgICBpZiAoY2ZtLm5hbWUgPT09ICJWMiIpIHsKICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHsKICAgICAgICByZXR1cm4gbmV3IEFSQ0ZvdXJDaXBoZXIoc2VsZi4jYnVpbGRPYmplY3RLZXkobnVtLCBnZW4sIGtleSwgZmFsc2UpKTsKICAgICAgfTsKICAgIH0KICAgIGlmIChjZm0ubmFtZSA9PT0gIkFFU1YyIikgewogICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBuZXcgQUVTMTI4Q2lwaGVyKHNlbGYuI2J1aWxkT2JqZWN0S2V5KG51bSwgZ2VuLCBrZXksIHRydWUpKTsKICAgICAgfTsKICAgIH0KICAgIGlmIChjZm0ubmFtZSA9PT0gIkFFU1YzIikgewogICAgICByZXR1cm4gZnVuY3Rpb24gKCkgewogICAgICAgIHJldHVybiBuZXcgQUVTMjU2Q2lwaGVyKGtleSk7CiAgICAgIH07CiAgICB9CiAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlVua25vd24gY3J5cHRvIG1ldGhvZCIpOwogIH0KICBjb25zdHJ1Y3RvcihkaWN0LCBmaWxlSWQsIHBhc3N3b3JkKSB7CiAgICBjb25zdCBmaWx0ZXIgPSBkaWN0LmdldCgiRmlsdGVyIik7CiAgICBpZiAoIWlzTmFtZShmaWx0ZXIsICJTdGFuZGFyZCIpKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigidW5rbm93biBlbmNyeXB0aW9uIG1ldGhvZCIpOwogICAgfQogICAgdGhpcy5maWx0ZXJOYW1lID0gZmlsdGVyLm5hbWU7CiAgICB0aGlzLmRpY3QgPSBkaWN0OwogICAgY29uc3QgYWxnb3JpdGhtID0gZGljdC5nZXQoIlYiKTsKICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihhbGdvcml0aG0pIHx8IGFsZ29yaXRobSAhPT0gMSAmJiBhbGdvcml0aG0gIT09IDIgJiYgYWxnb3JpdGhtICE9PSA0ICYmIGFsZ29yaXRobSAhPT0gNSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoInVuc3VwcG9ydGVkIGVuY3J5cHRpb24gYWxnb3JpdGhtIik7CiAgICB9CiAgICB0aGlzLmFsZ29yaXRobSA9IGFsZ29yaXRobTsKICAgIGxldCBrZXlMZW5ndGggPSBkaWN0LmdldCgiTGVuZ3RoIik7CiAgICBpZiAoIWtleUxlbmd0aCkgewogICAgICBpZiAoYWxnb3JpdGhtIDw9IDMpIHsKICAgICAgICBrZXlMZW5ndGggPSA0MDsKICAgICAgfSBlbHNlIHsKICAgICAgICBjb25zdCBjZkRpY3QgPSBkaWN0LmdldCgiQ0YiKTsKICAgICAgICBjb25zdCBzdHJlYW1DcnlwdG9OYW1lID0gZGljdC5nZXQoIlN0bUYiKTsKICAgICAgICBpZiAoY2ZEaWN0IGluc3RhbmNlb2YgRGljdCAmJiBzdHJlYW1DcnlwdG9OYW1lIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgY2ZEaWN0LnN1cHByZXNzRW5jcnlwdGlvbiA9IHRydWU7CiAgICAgICAgICBjb25zdCBoYW5kbGVyRGljdCA9IGNmRGljdC5nZXQoc3RyZWFtQ3J5cHRvTmFtZS5uYW1lKTsKICAgICAgICAgIGtleUxlbmd0aCA9IGhhbmRsZXJEaWN0Py5nZXQoIkxlbmd0aCIpIHx8IDEyODsKICAgICAgICAgIGlmIChrZXlMZW5ndGggPCA0MCkgewogICAgICAgICAgICBrZXlMZW5ndGggPDw9IDM7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoa2V5TGVuZ3RoKSB8fCBrZXlMZW5ndGggPCA0MCB8fCBrZXlMZW5ndGggJSA4ICE9PSAwKSB7CiAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiaW52YWxpZCBrZXkgbGVuZ3RoIik7CiAgICB9CiAgICBjb25zdCBvd25lckJ5dGVzID0gc3RyaW5nVG9CeXRlcyhkaWN0LmdldCgiTyIpKSwKICAgICAgdXNlckJ5dGVzID0gc3RyaW5nVG9CeXRlcyhkaWN0LmdldCgiVSIpKTsKICAgIGNvbnN0IG93bmVyUGFzc3dvcmQgPSBvd25lckJ5dGVzLnN1YmFycmF5KDAsIDMyKTsKICAgIGNvbnN0IHVzZXJQYXNzd29yZCA9IHVzZXJCeXRlcy5zdWJhcnJheSgwLCAzMik7CiAgICBjb25zdCBmbGFncyA9IGRpY3QuZ2V0KCJQIik7CiAgICBjb25zdCByZXZpc2lvbiA9IGRpY3QuZ2V0KCJSIik7CiAgICBjb25zdCBlbmNyeXB0TWV0YWRhdGEgPSAoYWxnb3JpdGhtID09PSA0IHx8IGFsZ29yaXRobSA9PT0gNSkgJiYgZGljdC5nZXQoIkVuY3J5cHRNZXRhZGF0YSIpICE9PSBmYWxzZTsKICAgIHRoaXMuZW5jcnlwdE1ldGFkYXRhID0gZW5jcnlwdE1ldGFkYXRhOwogICAgY29uc3QgZmlsZUlkQnl0ZXMgPSBzdHJpbmdUb0J5dGVzKGZpbGVJZCk7CiAgICBsZXQgcGFzc3dvcmRCeXRlczsKICAgIGlmIChwYXNzd29yZCkgewogICAgICBpZiAocmV2aXNpb24gPT09IDYpIHsKICAgICAgICB0cnkgewogICAgICAgICAgcGFzc3dvcmQgPSB1dGY4U3RyaW5nVG9TdHJpbmcocGFzc3dvcmQpOwogICAgICAgIH0gY2F0Y2ggewogICAgICAgICAgd2FybigiQ2lwaGVyVHJhbnNmb3JtRmFjdG9yeTogVW5hYmxlIHRvIGNvbnZlcnQgVVRGOCBlbmNvZGVkIHBhc3N3b3JkLiIpOwogICAgICAgIH0KICAgICAgfQogICAgICBwYXNzd29yZEJ5dGVzID0gc3RyaW5nVG9CeXRlcyhwYXNzd29yZCk7CiAgICB9CiAgICBsZXQgZW5jcnlwdGlvbktleTsKICAgIGlmIChhbGdvcml0aG0gIT09IDUpIHsKICAgICAgZW5jcnlwdGlvbktleSA9IHRoaXMuI3ByZXBhcmVLZXlEYXRhKGZpbGVJZEJ5dGVzLCBwYXNzd29yZEJ5dGVzLCBvd25lclBhc3N3b3JkLCB1c2VyUGFzc3dvcmQsIGZsYWdzLCByZXZpc2lvbiwga2V5TGVuZ3RoLCBlbmNyeXB0TWV0YWRhdGEpOwogICAgfSBlbHNlIHsKICAgICAgY29uc3Qgb3duZXJWYWxpZGF0aW9uU2FsdCA9IG93bmVyQnl0ZXMuc3ViYXJyYXkoMzIsIDQwKTsKICAgICAgY29uc3Qgb3duZXJLZXlTYWx0ID0gb3duZXJCeXRlcy5zdWJhcnJheSg0MCwgNDgpOwogICAgICBjb25zdCB1Qnl0ZXMgPSB1c2VyQnl0ZXMuc3ViYXJyYXkoMCwgNDgpOwogICAgICBjb25zdCB1c2VyVmFsaWRhdGlvblNhbHQgPSB1c2VyQnl0ZXMuc3ViYXJyYXkoMzIsIDQwKTsKICAgICAgY29uc3QgdXNlcktleVNhbHQgPSB1c2VyQnl0ZXMuc3ViYXJyYXkoNDAsIDQ4KTsKICAgICAgY29uc3Qgb3duZXJFbmNyeXB0aW9uID0gc3RyaW5nVG9CeXRlcyhkaWN0LmdldCgiT0UiKSk7CiAgICAgIGNvbnN0IHVzZXJFbmNyeXB0aW9uID0gc3RyaW5nVG9CeXRlcyhkaWN0LmdldCgiVUUiKSk7CiAgICAgIGNvbnN0IHBlcm1zID0gc3RyaW5nVG9CeXRlcyhkaWN0LmdldCgiUGVybXMiKSk7CiAgICAgIGVuY3J5cHRpb25LZXkgPSB0aGlzLiNjcmVhdGVFbmNyeXB0aW9uS2V5MjAocmV2aXNpb24sIHBhc3N3b3JkQnl0ZXMsIG93bmVyUGFzc3dvcmQsIG93bmVyVmFsaWRhdGlvblNhbHQsIG93bmVyS2V5U2FsdCwgdUJ5dGVzLCB1c2VyUGFzc3dvcmQsIHVzZXJWYWxpZGF0aW9uU2FsdCwgdXNlcktleVNhbHQsIG93bmVyRW5jcnlwdGlvbiwgdXNlckVuY3J5cHRpb24sIHBlcm1zKTsKICAgIH0KICAgIGlmICghZW5jcnlwdGlvbktleSkgewogICAgICBpZiAoIXBhc3N3b3JkKSB7CiAgICAgICAgdGhyb3cgbmV3IFBhc3N3b3JkRXhjZXB0aW9uKCJObyBwYXNzd29yZCBnaXZlbiIsIFBhc3N3b3JkUmVzcG9uc2VzLk5FRURfUEFTU1dPUkQpOwogICAgICB9CiAgICAgIGNvbnN0IGRlY29kZWRQYXNzd29yZCA9IHRoaXMuI2RlY29kZVVzZXJQYXNzd29yZChwYXNzd29yZEJ5dGVzLCBvd25lclBhc3N3b3JkLCByZXZpc2lvbiwga2V5TGVuZ3RoKTsKICAgICAgZW5jcnlwdGlvbktleSA9IHRoaXMuI3ByZXBhcmVLZXlEYXRhKGZpbGVJZEJ5dGVzLCBkZWNvZGVkUGFzc3dvcmQsIG93bmVyUGFzc3dvcmQsIHVzZXJQYXNzd29yZCwgZmxhZ3MsIHJldmlzaW9uLCBrZXlMZW5ndGgsIGVuY3J5cHRNZXRhZGF0YSk7CiAgICB9CiAgICBpZiAoIWVuY3J5cHRpb25LZXkpIHsKICAgICAgdGhyb3cgbmV3IFBhc3N3b3JkRXhjZXB0aW9uKCJJbmNvcnJlY3QgUGFzc3dvcmQiLCBQYXNzd29yZFJlc3BvbnNlcy5JTkNPUlJFQ1RfUEFTU1dPUkQpOwogICAgfQogICAgaWYgKGFsZ29yaXRobSA9PT0gNCAmJiBlbmNyeXB0aW9uS2V5Lmxlbmd0aCA8IDE2KSB7CiAgICAgIHRoaXMuZW5jcnlwdGlvbktleSA9IG5ldyBVaW50OEFycmF5KDE2KTsKICAgICAgdGhpcy5lbmNyeXB0aW9uS2V5LnNldChlbmNyeXB0aW9uS2V5KTsKICAgIH0gZWxzZSB7CiAgICAgIHRoaXMuZW5jcnlwdGlvbktleSA9IGVuY3J5cHRpb25LZXk7CiAgICB9CiAgICBpZiAoYWxnb3JpdGhtID49IDQpIHsKICAgICAgY29uc3QgY2YgPSBkaWN0LmdldCgiQ0YiKTsKICAgICAgaWYgKGNmIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgIGNmLnN1cHByZXNzRW5jcnlwdGlvbiA9IHRydWU7CiAgICAgIH0KICAgICAgdGhpcy5jZiA9IGNmOwogICAgICB0aGlzLnN0bWYgPSBkaWN0LmdldCgiU3RtRiIpIHx8IE5hbWUuZ2V0KCJJZGVudGl0eSIpOwogICAgICB0aGlzLnN0cmYgPSBkaWN0LmdldCgiU3RyRiIpIHx8IE5hbWUuZ2V0KCJJZGVudGl0eSIpOwogICAgICB0aGlzLmVmZiA9IGRpY3QuZ2V0KCJFRkYiKSB8fCB0aGlzLnN0bWY7CiAgICB9CiAgfQogIGNyZWF0ZUNpcGhlclRyYW5zZm9ybShudW0sIGdlbikgewogICAgaWYgKHRoaXMuYWxnb3JpdGhtID09PSA0IHx8IHRoaXMuYWxnb3JpdGhtID09PSA1KSB7CiAgICAgIHJldHVybiBuZXcgQ2lwaGVyVHJhbnNmb3JtKHRoaXMuI2J1aWxkQ2lwaGVyQ29uc3RydWN0b3IodGhpcy5jZiwgdGhpcy5zdHJmLCBudW0sIGdlbiwgdGhpcy5lbmNyeXB0aW9uS2V5KSwgdGhpcy4jYnVpbGRDaXBoZXJDb25zdHJ1Y3Rvcih0aGlzLmNmLCB0aGlzLnN0bWYsIG51bSwgZ2VuLCB0aGlzLmVuY3J5cHRpb25LZXkpKTsKICAgIH0KICAgIGNvbnN0IGtleSA9IHRoaXMuI2J1aWxkT2JqZWN0S2V5KG51bSwgZ2VuLCB0aGlzLmVuY3J5cHRpb25LZXksIGZhbHNlKTsKICAgIGNvbnN0IGNpcGhlckNvbnN0cnVjdG9yID0gZnVuY3Rpb24gKCkgewogICAgICByZXR1cm4gbmV3IEFSQ0ZvdXJDaXBoZXIoa2V5KTsKICAgIH07CiAgICByZXR1cm4gbmV3IENpcGhlclRyYW5zZm9ybShjaXBoZXJDb25zdHJ1Y3RvciwgY2lwaGVyQ29uc3RydWN0b3IpOwogIH0KfQoKOy8vIC4vc3JjL2NvcmUveHJlZi5qcwoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKY2xhc3MgWFJlZiB7CiAgY29uc3RydWN0b3Ioc3RyZWFtLCBwZGZNYW5hZ2VyKSB7CiAgICB0aGlzLnN0cmVhbSA9IHN0cmVhbTsKICAgIHRoaXMucGRmTWFuYWdlciA9IHBkZk1hbmFnZXI7CiAgICB0aGlzLmVudHJpZXMgPSBbXTsKICAgIHRoaXMuX3hyZWZTdG1zID0gbmV3IFNldCgpOwogICAgdGhpcy5fY2FjaGVNYXAgPSBuZXcgTWFwKCk7CiAgICB0aGlzLl9wZW5kaW5nUmVmcyA9IG5ldyBSZWZTZXQoKTsKICAgIHRoaXMuX25ld1BlcnNpc3RlbnRSZWZOdW0gPSBudWxsOwogICAgdGhpcy5fbmV3VGVtcG9yYXJ5UmVmTnVtID0gbnVsbDsKICAgIHRoaXMuX3BlcnNpc3RlbnRSZWZzQ2FjaGUgPSBudWxsOwogIH0KICBnZXROZXdQZXJzaXN0ZW50UmVmKG9iaikgewogICAgaWYgKHRoaXMuX25ld1BlcnNpc3RlbnRSZWZOdW0gPT09IG51bGwpIHsKICAgICAgdGhpcy5fbmV3UGVyc2lzdGVudFJlZk51bSA9IHRoaXMuZW50cmllcy5sZW5ndGggfHwgMTsKICAgIH0KICAgIGNvbnN0IG51bSA9IHRoaXMuX25ld1BlcnNpc3RlbnRSZWZOdW0rKzsKICAgIHRoaXMuX2NhY2hlTWFwLnNldChudW0sIG9iaik7CiAgICByZXR1cm4gUmVmLmdldChudW0sIDApOwogIH0KICBnZXROZXdUZW1wb3JhcnlSZWYoKSB7CiAgICBpZiAodGhpcy5fbmV3VGVtcG9yYXJ5UmVmTnVtID09PSBudWxsKSB7CiAgICAgIHRoaXMuX25ld1RlbXBvcmFyeVJlZk51bSA9IHRoaXMuZW50cmllcy5sZW5ndGggfHwgMTsKICAgICAgaWYgKHRoaXMuX25ld1BlcnNpc3RlbnRSZWZOdW0pIHsKICAgICAgICB0aGlzLl9wZXJzaXN0ZW50UmVmc0NhY2hlID0gbmV3IE1hcCgpOwogICAgICAgIGZvciAobGV0IGkgPSB0aGlzLl9uZXdUZW1wb3JhcnlSZWZOdW07IGkgPCB0aGlzLl9uZXdQZXJzaXN0ZW50UmVmTnVtOyBpKyspIHsKICAgICAgICAgIHRoaXMuX3BlcnNpc3RlbnRSZWZzQ2FjaGUuc2V0KGksIHRoaXMuX2NhY2hlTWFwLmdldChpKSk7CiAgICAgICAgICB0aGlzLl9jYWNoZU1hcC5kZWxldGUoaSk7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gUmVmLmdldCh0aGlzLl9uZXdUZW1wb3JhcnlSZWZOdW0rKywgMCk7CiAgfQogIHJlc2V0TmV3VGVtcG9yYXJ5UmVmKCkgewogICAgdGhpcy5fbmV3VGVtcG9yYXJ5UmVmTnVtID0gbnVsbDsKICAgIGlmICh0aGlzLl9wZXJzaXN0ZW50UmVmc0NhY2hlKSB7CiAgICAgIGZvciAoY29uc3QgW251bSwgb2JqXSBvZiB0aGlzLl9wZXJzaXN0ZW50UmVmc0NhY2hlKSB7CiAgICAgICAgdGhpcy5fY2FjaGVNYXAuc2V0KG51bSwgb2JqKTsKICAgICAgfQogICAgfQogICAgdGhpcy5fcGVyc2lzdGVudFJlZnNDYWNoZSA9IG51bGw7CiAgfQogIHNldFN0YXJ0WFJlZihzdGFydFhSZWYpIHsKICAgIHRoaXMuc3RhcnRYUmVmUXVldWUgPSBbc3RhcnRYUmVmXTsKICB9CiAgcGFyc2UocmVjb3ZlcnlNb2RlID0gZmFsc2UpIHsKICAgIGxldCB0cmFpbGVyRGljdDsKICAgIGlmICghcmVjb3ZlcnlNb2RlKSB7CiAgICAgIHRyYWlsZXJEaWN0ID0gdGhpcy5yZWFkWFJlZigpOwogICAgfSBlbHNlIHsKICAgICAgd2FybigiSW5kZXhpbmcgYWxsIFBERiBvYmplY3RzIik7CiAgICAgIHRyYWlsZXJEaWN0ID0gdGhpcy5pbmRleE9iamVjdHMoKTsKICAgIH0KICAgIHRyYWlsZXJEaWN0LmFzc2lnblhyZWYodGhpcyk7CiAgICB0aGlzLnRyYWlsZXIgPSB0cmFpbGVyRGljdDsKICAgIGxldCBlbmNyeXB0OwogICAgdHJ5IHsKICAgICAgZW5jcnlwdCA9IHRyYWlsZXJEaWN0LmdldCgiRW5jcnlwdCIpOwogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICB3YXJuKGBYUmVmLnBhcnNlIC0gSW52YWxpZCAiRW5jcnlwdCIgcmVmZXJlbmNlOiAiJHtleH0iLmApOwogICAgfQogICAgaWYgKGVuY3J5cHQgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgIGNvbnN0IGlkcyA9IHRyYWlsZXJEaWN0LmdldCgiSUQiKTsKICAgICAgY29uc3QgZmlsZUlkID0gaWRzPy5sZW5ndGggPyBpZHNbMF0gOiAiIjsKICAgICAgZW5jcnlwdC5zdXBwcmVzc0VuY3J5cHRpb24gPSB0cnVlOwogICAgICB0aGlzLmVuY3J5cHQgPSBuZXcgQ2lwaGVyVHJhbnNmb3JtRmFjdG9yeShlbmNyeXB0LCBmaWxlSWQsIHRoaXMucGRmTWFuYWdlci5wYXNzd29yZCk7CiAgICB9CiAgICBsZXQgcm9vdDsKICAgIHRyeSB7CiAgICAgIHJvb3QgPSB0cmFpbGVyRGljdC5nZXQoIlJvb3QiKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmIChleCBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgd2FybihgWFJlZi5wYXJzZSAtIEludmFsaWQgIlJvb3QiIHJlZmVyZW5jZTogIiR7ZXh9Ii5gKTsKICAgIH0KICAgIGlmIChyb290IGluc3RhbmNlb2YgRGljdCkgewogICAgICB0cnkgewogICAgICAgIGNvbnN0IHBhZ2VzID0gcm9vdC5nZXQoIlBhZ2VzIik7CiAgICAgICAgaWYgKHBhZ2VzIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgICAgdGhpcy5yb290ID0gcm9vdDsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICAgIHRocm93IGV4OwogICAgICAgIH0KICAgICAgICB3YXJuKGBYUmVmLnBhcnNlIC0gSW52YWxpZCAiUGFnZXMiIHJlZmVyZW5jZTogIiR7ZXh9Ii5gKTsKICAgICAgfQogICAgfQogICAgaWYgKCFyZWNvdmVyeU1vZGUpIHsKICAgICAgdGhyb3cgbmV3IFhSZWZQYXJzZUV4Y2VwdGlvbigpOwogICAgfQogICAgdGhyb3cgbmV3IEludmFsaWRQREZFeGNlcHRpb24oIkludmFsaWQgUm9vdCByZWZlcmVuY2UuIik7CiAgfQogIHByb2Nlc3NYUmVmVGFibGUocGFyc2VyKSB7CiAgICBpZiAoISgidGFibGVTdGF0ZSIgaW4gdGhpcykpIHsKICAgICAgdGhpcy50YWJsZVN0YXRlID0gewogICAgICAgIGVudHJ5TnVtOiAwLAogICAgICAgIHN0cmVhbVBvczogcGFyc2VyLmxleGVyLnN0cmVhbS5wb3MsCiAgICAgICAgcGFyc2VyQnVmMTogcGFyc2VyLmJ1ZjEsCiAgICAgICAgcGFyc2VyQnVmMjogcGFyc2VyLmJ1ZjIKICAgICAgfTsKICAgIH0KICAgIGNvbnN0IG9iaiA9IHRoaXMucmVhZFhSZWZUYWJsZShwYXJzZXIpOwogICAgaWYgKCFpc0NtZChvYmosICJ0cmFpbGVyIikpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFhSZWYgdGFibGU6IGNvdWxkIG5vdCBmaW5kIHRyYWlsZXIgZGljdGlvbmFyeSIpOwogICAgfQogICAgbGV0IGRpY3QgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICBpZiAoIShkaWN0IGluc3RhbmNlb2YgRGljdCkgJiYgZGljdC5kaWN0KSB7CiAgICAgIGRpY3QgPSBkaWN0LmRpY3Q7CiAgICB9CiAgICBpZiAoIShkaWN0IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFhSZWYgdGFibGU6IGNvdWxkIG5vdCBwYXJzZSB0cmFpbGVyIGRpY3Rpb25hcnkiKTsKICAgIH0KICAgIGRlbGV0ZSB0aGlzLnRhYmxlU3RhdGU7CiAgICByZXR1cm4gZGljdDsKICB9CiAgcmVhZFhSZWZUYWJsZShwYXJzZXIpIHsKICAgIGNvbnN0IHN0cmVhbSA9IHBhcnNlci5sZXhlci5zdHJlYW07CiAgICBjb25zdCB0YWJsZVN0YXRlID0gdGhpcy50YWJsZVN0YXRlOwogICAgc3RyZWFtLnBvcyA9IHRhYmxlU3RhdGUuc3RyZWFtUG9zOwogICAgcGFyc2VyLmJ1ZjEgPSB0YWJsZVN0YXRlLnBhcnNlckJ1ZjE7CiAgICBwYXJzZXIuYnVmMiA9IHRhYmxlU3RhdGUucGFyc2VyQnVmMjsKICAgIGxldCBvYmo7CiAgICB3aGlsZSAodHJ1ZSkgewogICAgICBpZiAoISgiZmlyc3RFbnRyeU51bSIgaW4gdGFibGVTdGF0ZSkgfHwgISgiZW50cnlDb3VudCIgaW4gdGFibGVTdGF0ZSkpIHsKICAgICAgICBpZiAoaXNDbWQob2JqID0gcGFyc2VyLmdldE9iaigpLCAidHJhaWxlciIpKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgdGFibGVTdGF0ZS5maXJzdEVudHJ5TnVtID0gb2JqOwogICAgICAgIHRhYmxlU3RhdGUuZW50cnlDb3VudCA9IHBhcnNlci5nZXRPYmooKTsKICAgICAgfQogICAgICBsZXQgZmlyc3QgPSB0YWJsZVN0YXRlLmZpcnN0RW50cnlOdW07CiAgICAgIGNvbnN0IGNvdW50ID0gdGFibGVTdGF0ZS5lbnRyeUNvdW50OwogICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIoZmlyc3QpIHx8ICFOdW1iZXIuaXNJbnRlZ2VyKGNvdW50KSkgewogICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBYUmVmIHRhYmxlOiB3cm9uZyB0eXBlcyBpbiBzdWJzZWN0aW9uIGhlYWRlciIpOwogICAgICB9CiAgICAgIGZvciAobGV0IGkgPSB0YWJsZVN0YXRlLmVudHJ5TnVtOyBpIDwgY291bnQ7IGkrKykgewogICAgICAgIHRhYmxlU3RhdGUuc3RyZWFtUG9zID0gc3RyZWFtLnBvczsKICAgICAgICB0YWJsZVN0YXRlLmVudHJ5TnVtID0gaTsKICAgICAgICB0YWJsZVN0YXRlLnBhcnNlckJ1ZjEgPSBwYXJzZXIuYnVmMTsKICAgICAgICB0YWJsZVN0YXRlLnBhcnNlckJ1ZjIgPSBwYXJzZXIuYnVmMjsKICAgICAgICBjb25zdCBlbnRyeSA9IHt9OwogICAgICAgIGVudHJ5Lm9mZnNldCA9IHBhcnNlci5nZXRPYmooKTsKICAgICAgICBlbnRyeS5nZW4gPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICAgICAgY29uc3QgdHlwZSA9IHBhcnNlci5nZXRPYmooKTsKICAgICAgICBpZiAodHlwZSBpbnN0YW5jZW9mIENtZCkgewogICAgICAgICAgc3dpdGNoICh0eXBlLmNtZCkgewogICAgICAgICAgICBjYXNlICJmIjoKICAgICAgICAgICAgICBlbnRyeS5mcmVlID0gdHJ1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgY2FzZSAibiI6CiAgICAgICAgICAgICAgZW50cnkudW5jb21wcmVzc2VkID0gdHJ1ZTsKICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKGVudHJ5Lm9mZnNldCkgfHwgIU51bWJlci5pc0ludGVnZXIoZW50cnkuZ2VuKSB8fCAhKGVudHJ5LmZyZWUgfHwgZW50cnkudW5jb21wcmVzc2VkKSkgewogICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIGVudHJ5IGluIFhSZWYgc3Vic2VjdGlvbjogJHtmaXJzdH0sICR7Y291bnR9YCk7CiAgICAgICAgfQogICAgICAgIGlmIChpID09PSAwICYmIGVudHJ5LmZyZWUgJiYgZmlyc3QgPT09IDEpIHsKICAgICAgICAgIGZpcnN0ID0gMDsKICAgICAgICB9CiAgICAgICAgaWYgKCF0aGlzLmVudHJpZXNbaSArIGZpcnN0XSkgewogICAgICAgICAgdGhpcy5lbnRyaWVzW2kgKyBmaXJzdF0gPSBlbnRyeTsKICAgICAgICB9CiAgICAgIH0KICAgICAgdGFibGVTdGF0ZS5lbnRyeU51bSA9IDA7CiAgICAgIHRhYmxlU3RhdGUuc3RyZWFtUG9zID0gc3RyZWFtLnBvczsKICAgICAgdGFibGVTdGF0ZS5wYXJzZXJCdWYxID0gcGFyc2VyLmJ1ZjE7CiAgICAgIHRhYmxlU3RhdGUucGFyc2VyQnVmMiA9IHBhcnNlci5idWYyOwogICAgICBkZWxldGUgdGFibGVTdGF0ZS5maXJzdEVudHJ5TnVtOwogICAgICBkZWxldGUgdGFibGVTdGF0ZS5lbnRyeUNvdW50OwogICAgfQogICAgaWYgKHRoaXMuZW50cmllc1swXSAmJiAhdGhpcy5lbnRyaWVzWzBdLmZyZWUpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFhSZWYgdGFibGU6IHVuZXhwZWN0ZWQgZmlyc3Qgb2JqZWN0Iik7CiAgICB9CiAgICByZXR1cm4gb2JqOwogIH0KICBwcm9jZXNzWFJlZlN0cmVhbShzdHJlYW0pIHsKICAgIGlmICghKCJzdHJlYW1TdGF0ZSIgaW4gdGhpcykpIHsKICAgICAgY29uc3QgewogICAgICAgIGRpY3QsCiAgICAgICAgcG9zCiAgICAgIH0gPSBzdHJlYW07CiAgICAgIGNvbnN0IGJ5dGVXaWR0aHMgPSBkaWN0LmdldCgiVyIpOwogICAgICBjb25zdCByYW5nZSA9IGRpY3QuZ2V0KCJJbmRleCIpIHx8IFswLCBkaWN0LmdldCgiU2l6ZSIpXTsKICAgICAgdGhpcy5zdHJlYW1TdGF0ZSA9IHsKICAgICAgICBlbnRyeVJhbmdlczogcmFuZ2UsCiAgICAgICAgYnl0ZVdpZHRocywKICAgICAgICBlbnRyeU51bTogMCwKICAgICAgICBzdHJlYW1Qb3M6IHBvcwogICAgICB9OwogICAgfQogICAgdGhpcy5yZWFkWFJlZlN0cmVhbShzdHJlYW0pOwogICAgZGVsZXRlIHRoaXMuc3RyZWFtU3RhdGU7CiAgICByZXR1cm4gc3RyZWFtLmRpY3Q7CiAgfQogIHJlYWRYUmVmU3RyZWFtKHN0cmVhbSkgewogICAgY29uc3Qgc3RyZWFtU3RhdGUgPSB0aGlzLnN0cmVhbVN0YXRlOwogICAgc3RyZWFtLnBvcyA9IHN0cmVhbVN0YXRlLnN0cmVhbVBvczsKICAgIGNvbnN0IFt0eXBlRmllbGRXaWR0aCwgb2Zmc2V0RmllbGRXaWR0aCwgZ2VuZXJhdGlvbkZpZWxkV2lkdGhdID0gc3RyZWFtU3RhdGUuYnl0ZVdpZHRoczsKICAgIGNvbnN0IGVudHJ5UmFuZ2VzID0gc3RyZWFtU3RhdGUuZW50cnlSYW5nZXM7CiAgICB3aGlsZSAoZW50cnlSYW5nZXMubGVuZ3RoID4gMCkgewogICAgICBjb25zdCBbZmlyc3QsIG5dID0gZW50cnlSYW5nZXM7CiAgICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihmaXJzdCkgfHwgIU51bWJlci5pc0ludGVnZXIobikpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgWFJlZiByYW5nZSBmaWVsZHM6ICR7Zmlyc3R9LCAke259YCk7CiAgICAgIH0KICAgICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKHR5cGVGaWVsZFdpZHRoKSB8fCAhTnVtYmVyLmlzSW50ZWdlcihvZmZzZXRGaWVsZFdpZHRoKSB8fCAhTnVtYmVyLmlzSW50ZWdlcihnZW5lcmF0aW9uRmllbGRXaWR0aCkpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYEludmFsaWQgWFJlZiBlbnRyeSBmaWVsZHMgbGVuZ3RoOiAke2ZpcnN0fSwgJHtufWApOwogICAgICB9CiAgICAgIGZvciAobGV0IGkgPSBzdHJlYW1TdGF0ZS5lbnRyeU51bTsgaSA8IG47ICsraSkgewogICAgICAgIHN0cmVhbVN0YXRlLmVudHJ5TnVtID0gaTsKICAgICAgICBzdHJlYW1TdGF0ZS5zdHJlYW1Qb3MgPSBzdHJlYW0ucG9zOwogICAgICAgIGxldCB0eXBlID0gMCwKICAgICAgICAgIG9mZnNldCA9IDAsCiAgICAgICAgICBnZW5lcmF0aW9uID0gMDsKICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IHR5cGVGaWVsZFdpZHRoOyArK2opIHsKICAgICAgICAgIGNvbnN0IHR5cGVCeXRlID0gc3RyZWFtLmdldEJ5dGUoKTsKICAgICAgICAgIGlmICh0eXBlQnl0ZSA9PT0gLTEpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFhSZWYgYnl0ZVdpZHRocyAndHlwZScuIik7CiAgICAgICAgICB9CiAgICAgICAgICB0eXBlID0gdHlwZSA8PCA4IHwgdHlwZUJ5dGU7CiAgICAgICAgfQogICAgICAgIGlmICh0eXBlRmllbGRXaWR0aCA9PT0gMCkgewogICAgICAgICAgdHlwZSA9IDE7CiAgICAgICAgfQogICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgb2Zmc2V0RmllbGRXaWR0aDsgKytqKSB7CiAgICAgICAgICBjb25zdCBvZmZzZXRCeXRlID0gc3RyZWFtLmdldEJ5dGUoKTsKICAgICAgICAgIGlmIChvZmZzZXRCeXRlID09PSAtMSkgewogICAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgWFJlZiBieXRlV2lkdGhzICdvZmZzZXQnLiIpOwogICAgICAgICAgfQogICAgICAgICAgb2Zmc2V0ID0gb2Zmc2V0IDw8IDggfCBvZmZzZXRCeXRlOwogICAgICAgIH0KICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGdlbmVyYXRpb25GaWVsZFdpZHRoOyArK2opIHsKICAgICAgICAgIGNvbnN0IGdlbmVyYXRpb25CeXRlID0gc3RyZWFtLmdldEJ5dGUoKTsKICAgICAgICAgIGlmIChnZW5lcmF0aW9uQnl0ZSA9PT0gLTEpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIFhSZWYgYnl0ZVdpZHRocyAnZ2VuZXJhdGlvbicuIik7CiAgICAgICAgICB9CiAgICAgICAgICBnZW5lcmF0aW9uID0gZ2VuZXJhdGlvbiA8PCA4IHwgZ2VuZXJhdGlvbkJ5dGU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGVudHJ5ID0ge307CiAgICAgICAgZW50cnkub2Zmc2V0ID0gb2Zmc2V0OwogICAgICAgIGVudHJ5LmdlbiA9IGdlbmVyYXRpb247CiAgICAgICAgc3dpdGNoICh0eXBlKSB7CiAgICAgICAgICBjYXNlIDA6CiAgICAgICAgICAgIGVudHJ5LmZyZWUgPSB0cnVlOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIGNhc2UgMToKICAgICAgICAgICAgZW50cnkudW5jb21wcmVzc2VkID0gdHJ1ZTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICBjYXNlIDI6CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBJbnZhbGlkIFhSZWYgZW50cnkgdHlwZTogJHt0eXBlfWApOwogICAgICAgIH0KICAgICAgICBpZiAoIXRoaXMuZW50cmllc1tmaXJzdCArIGldKSB7CiAgICAgICAgICB0aGlzLmVudHJpZXNbZmlyc3QgKyBpXSA9IGVudHJ5OwogICAgICAgIH0KICAgICAgfQogICAgICBzdHJlYW1TdGF0ZS5lbnRyeU51bSA9IDA7CiAgICAgIHN0cmVhbVN0YXRlLnN0cmVhbVBvcyA9IHN0cmVhbS5wb3M7CiAgICAgIGVudHJ5UmFuZ2VzLnNwbGljZSgwLCAyKTsKICAgIH0KICB9CiAgaW5kZXhPYmplY3RzKCkgewogICAgY29uc3QgVEFCID0gMHg5LAogICAgICBMRiA9IDB4YSwKICAgICAgQ1IgPSAweGQsCiAgICAgIFNQQUNFID0gMHgyMDsKICAgIGNvbnN0IFBFUkNFTlQgPSAweDI1LAogICAgICBMVCA9IDB4M2M7CiAgICBmdW5jdGlvbiByZWFkVG9rZW4oZGF0YSwgb2Zmc2V0KSB7CiAgICAgIGxldCB0b2tlbiA9ICIiLAogICAgICAgIGNoID0gZGF0YVtvZmZzZXRdOwogICAgICB3aGlsZSAoY2ggIT09IExGICYmIGNoICE9PSBDUiAmJiBjaCAhPT0gTFQpIHsKICAgICAgICBpZiAoKytvZmZzZXQgPj0gZGF0YS5sZW5ndGgpIHsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICB0b2tlbiArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKTsKICAgICAgICBjaCA9IGRhdGFbb2Zmc2V0XTsKICAgICAgfQogICAgICByZXR1cm4gdG9rZW47CiAgICB9CiAgICBmdW5jdGlvbiBza2lwVW50aWwoZGF0YSwgb2Zmc2V0LCB3aGF0KSB7CiAgICAgIGNvbnN0IGxlbmd0aCA9IHdoYXQubGVuZ3RoLAogICAgICAgIGRhdGFMZW5ndGggPSBkYXRhLmxlbmd0aDsKICAgICAgbGV0IHNraXBwZWQgPSAwOwogICAgICB3aGlsZSAob2Zmc2V0IDwgZGF0YUxlbmd0aCkgewogICAgICAgIGxldCBpID0gMDsKICAgICAgICB3aGlsZSAoaSA8IGxlbmd0aCAmJiBkYXRhW29mZnNldCArIGldID09PSB3aGF0W2ldKSB7CiAgICAgICAgICArK2k7CiAgICAgICAgfQogICAgICAgIGlmIChpID49IGxlbmd0aCkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIG9mZnNldCsrOwogICAgICAgIHNraXBwZWQrKzsKICAgICAgfQogICAgICByZXR1cm4gc2tpcHBlZDsKICAgIH0KICAgIGNvbnN0IGdFbmRvYmpSZWdFeHAgPSAvXGIoZW5kb2JqfFxkK1xzK1xkK1xzK29ianx4cmVmfHRyYWlsZXJccyo8PClcYi9nOwogICAgY29uc3QgZ1N0YXJ0eHJlZlJlZ0V4cCA9IC9cYihzdGFydHhyZWZ8XGQrXHMrXGQrXHMrb2JqKVxiL2c7CiAgICBjb25zdCBvYmpSZWdFeHAgPSAvXihcZCspXHMrKFxkKylccytvYmpcYi87CiAgICBjb25zdCB0cmFpbGVyQnl0ZXMgPSBuZXcgVWludDhBcnJheShbMTE2LCAxMTQsIDk3LCAxMDUsIDEwOCwgMTAxLCAxMTRdKTsKICAgIGNvbnN0IHN0YXJ0eHJlZkJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoWzExNSwgMTE2LCA5NywgMTE0LCAxMTYsIDEyMCwgMTE0LCAxMDEsIDEwMl0pOwogICAgY29uc3QgeHJlZkJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoWzQ3LCA4OCwgODIsIDEwMSwgMTAyXSk7CiAgICB0aGlzLmVudHJpZXMubGVuZ3RoID0gMDsKICAgIHRoaXMuX2NhY2hlTWFwLmNsZWFyKCk7CiAgICBjb25zdCBzdHJlYW0gPSB0aGlzLnN0cmVhbTsKICAgIHN0cmVhbS5wb3MgPSAwOwogICAgY29uc3QgYnVmZmVyID0gc3RyZWFtLmdldEJ5dGVzKCksCiAgICAgIGJ1ZmZlclN0ciA9IGJ5dGVzVG9TdHJpbmcoYnVmZmVyKSwKICAgICAgbGVuZ3RoID0gYnVmZmVyLmxlbmd0aDsKICAgIGxldCBwb3NpdGlvbiA9IHN0cmVhbS5zdGFydDsKICAgIGNvbnN0IHRyYWlsZXJzID0gW10sCiAgICAgIHhyZWZTdG1zID0gW107CiAgICB3aGlsZSAocG9zaXRpb24gPCBsZW5ndGgpIHsKICAgICAgbGV0IGNoID0gYnVmZmVyW3Bvc2l0aW9uXTsKICAgICAgaWYgKGNoID09PSBUQUIgfHwgY2ggPT09IExGIHx8IGNoID09PSBDUiB8fCBjaCA9PT0gU1BBQ0UpIHsKICAgICAgICArK3Bvc2l0aW9uOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChjaCA9PT0gUEVSQ0VOVCkgewogICAgICAgIGRvIHsKICAgICAgICAgICsrcG9zaXRpb247CiAgICAgICAgICBpZiAocG9zaXRpb24gPj0gbGVuZ3RoKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgY2ggPSBidWZmZXJbcG9zaXRpb25dOwogICAgICAgIH0gd2hpbGUgKGNoICE9PSBMRiAmJiBjaCAhPT0gQ1IpOwogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IHRva2VuID0gcmVhZFRva2VuKGJ1ZmZlciwgcG9zaXRpb24pOwogICAgICBsZXQgbTsKICAgICAgaWYgKHRva2VuLnN0YXJ0c1dpdGgoInhyZWYiKSAmJiAodG9rZW4ubGVuZ3RoID09PSA0IHx8IC9ccy8udGVzdCh0b2tlbls0XSkpKSB7CiAgICAgICAgcG9zaXRpb24gKz0gc2tpcFVudGlsKGJ1ZmZlciwgcG9zaXRpb24sIHRyYWlsZXJCeXRlcyk7CiAgICAgICAgdHJhaWxlcnMucHVzaChwb3NpdGlvbik7CiAgICAgICAgcG9zaXRpb24gKz0gc2tpcFVudGlsKGJ1ZmZlciwgcG9zaXRpb24sIHN0YXJ0eHJlZkJ5dGVzKTsKICAgICAgfSBlbHNlIGlmIChtID0gb2JqUmVnRXhwLmV4ZWModG9rZW4pKSB7CiAgICAgICAgY29uc3QgbnVtID0gbVsxXSB8IDAsCiAgICAgICAgICBnZW4gPSBtWzJdIHwgMDsKICAgICAgICBjb25zdCBzdGFydFBvcyA9IHBvc2l0aW9uICsgdG9rZW4ubGVuZ3RoOwogICAgICAgIGxldCBjb250ZW50TGVuZ3RoLAogICAgICAgICAgdXBkYXRlRW50cmllcyA9IGZhbHNlOwogICAgICAgIGlmICghdGhpcy5lbnRyaWVzW251bV0pIHsKICAgICAgICAgIHVwZGF0ZUVudHJpZXMgPSB0cnVlOwogICAgICAgIH0gZWxzZSBpZiAodGhpcy5lbnRyaWVzW251bV0uZ2VuID09PSBnZW4pIHsKICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBQYXJzZXIoewogICAgICAgICAgICAgIGxleGVyOiBuZXcgTGV4ZXIoc3RyZWFtLm1ha2VTdWJTdHJlYW0oc3RhcnRQb3MpKQogICAgICAgICAgICB9KTsKICAgICAgICAgICAgcGFyc2VyLmdldE9iaigpOwogICAgICAgICAgICB1cGRhdGVFbnRyaWVzID0gdHJ1ZTsKICAgICAgICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhcnNlckVPRkV4Y2VwdGlvbikgewogICAgICAgICAgICAgIHdhcm4oYGluZGV4T2JqZWN0cyAtLSBjaGVja2luZyBvYmplY3QgKCR7dG9rZW59KTogIiR7ZXh9Ii5gKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICB1cGRhdGVFbnRyaWVzID0gdHJ1ZTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAodXBkYXRlRW50cmllcykgewogICAgICAgICAgdGhpcy5lbnRyaWVzW251bV0gPSB7CiAgICAgICAgICAgIG9mZnNldDogcG9zaXRpb24gLSBzdHJlYW0uc3RhcnQsCiAgICAgICAgICAgIGdlbiwKICAgICAgICAgICAgdW5jb21wcmVzc2VkOiB0cnVlCiAgICAgICAgICB9OwogICAgICAgIH0KICAgICAgICBnRW5kb2JqUmVnRXhwLmxhc3RJbmRleCA9IHN0YXJ0UG9zOwogICAgICAgIGNvbnN0IG1hdGNoID0gZ0VuZG9ialJlZ0V4cC5leGVjKGJ1ZmZlclN0cik7CiAgICAgICAgaWYgKG1hdGNoKSB7CiAgICAgICAgICBjb25zdCBlbmRQb3MgPSBnRW5kb2JqUmVnRXhwLmxhc3RJbmRleCArIDE7CiAgICAgICAgICBjb250ZW50TGVuZ3RoID0gZW5kUG9zIC0gcG9zaXRpb247CiAgICAgICAgICBpZiAobWF0Y2hbMV0gIT09ICJlbmRvYmoiKSB7CiAgICAgICAgICAgIHdhcm4oYGluZGV4T2JqZWN0czogRm91bmQgIiR7bWF0Y2hbMV19IiBpbnNpZGUgb2YgYW5vdGhlciAib2JqIiwgYCArICdjYXVzZWQgYnkgbWlzc2luZyAiZW5kb2JqIiAtLSB0cnlpbmcgdG8gcmVjb3Zlci4nKTsKICAgICAgICAgICAgY29udGVudExlbmd0aCAtPSBtYXRjaFsxXS5sZW5ndGggKyAxOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb250ZW50TGVuZ3RoID0gbGVuZ3RoIC0gcG9zaXRpb247CiAgICAgICAgfQogICAgICAgIGNvbnN0IGNvbnRlbnQgPSBidWZmZXIuc3ViYXJyYXkocG9zaXRpb24sIHBvc2l0aW9uICsgY29udGVudExlbmd0aCk7CiAgICAgICAgY29uc3QgeHJlZlRhZ09mZnNldCA9IHNraXBVbnRpbChjb250ZW50LCAwLCB4cmVmQnl0ZXMpOwogICAgICAgIGlmICh4cmVmVGFnT2Zmc2V0IDwgY29udGVudExlbmd0aCAmJiBjb250ZW50W3hyZWZUYWdPZmZzZXQgKyA1XSA8IDY0KSB7CiAgICAgICAgICB4cmVmU3Rtcy5wdXNoKHBvc2l0aW9uIC0gc3RyZWFtLnN0YXJ0KTsKICAgICAgICAgIHRoaXMuX3hyZWZTdG1zLmFkZChwb3NpdGlvbiAtIHN0cmVhbS5zdGFydCk7CiAgICAgICAgfQogICAgICAgIHBvc2l0aW9uICs9IGNvbnRlbnRMZW5ndGg7CiAgICAgIH0gZWxzZSBpZiAodG9rZW4uc3RhcnRzV2l0aCgidHJhaWxlciIpICYmICh0b2tlbi5sZW5ndGggPT09IDcgfHwgL1xzLy50ZXN0KHRva2VuWzddKSkpIHsKICAgICAgICB0cmFpbGVycy5wdXNoKHBvc2l0aW9uKTsKICAgICAgICBjb25zdCBzdGFydFBvcyA9IHBvc2l0aW9uICsgdG9rZW4ubGVuZ3RoOwogICAgICAgIGxldCBjb250ZW50TGVuZ3RoOwogICAgICAgIGdTdGFydHhyZWZSZWdFeHAubGFzdEluZGV4ID0gc3RhcnRQb3M7CiAgICAgICAgY29uc3QgbWF0Y2ggPSBnU3RhcnR4cmVmUmVnRXhwLmV4ZWMoYnVmZmVyU3RyKTsKICAgICAgICBpZiAobWF0Y2gpIHsKICAgICAgICAgIGNvbnN0IGVuZFBvcyA9IGdTdGFydHhyZWZSZWdFeHAubGFzdEluZGV4ICsgMTsKICAgICAgICAgIGNvbnRlbnRMZW5ndGggPSBlbmRQb3MgLSBwb3NpdGlvbjsKICAgICAgICAgIGlmIChtYXRjaFsxXSAhPT0gInN0YXJ0eHJlZiIpIHsKICAgICAgICAgICAgd2FybihgaW5kZXhPYmplY3RzOiBGb3VuZCAiJHttYXRjaFsxXX0iIGFmdGVyICJ0cmFpbGVyIiwgYCArICdjYXVzZWQgYnkgbWlzc2luZyAic3RhcnR4cmVmIiAtLSB0cnlpbmcgdG8gcmVjb3Zlci4nKTsKICAgICAgICAgICAgY29udGVudExlbmd0aCAtPSBtYXRjaFsxXS5sZW5ndGggKyAxOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBjb250ZW50TGVuZ3RoID0gbGVuZ3RoIC0gcG9zaXRpb247CiAgICAgICAgfQogICAgICAgIHBvc2l0aW9uICs9IGNvbnRlbnRMZW5ndGg7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgcG9zaXRpb24gKz0gdG9rZW4ubGVuZ3RoICsgMTsKICAgICAgfQogICAgfQogICAgZm9yIChjb25zdCB4cmVmU3RtIG9mIHhyZWZTdG1zKSB7CiAgICAgIHRoaXMuc3RhcnRYUmVmUXVldWUucHVzaCh4cmVmU3RtKTsKICAgICAgdGhpcy5yZWFkWFJlZih0cnVlKTsKICAgIH0KICAgIGNvbnN0IHRyYWlsZXJEaWN0cyA9IFtdOwogICAgbGV0IGlzRW5jcnlwdGVkID0gZmFsc2U7CiAgICBmb3IgKGNvbnN0IHRyYWlsZXIgb2YgdHJhaWxlcnMpIHsKICAgICAgc3RyZWFtLnBvcyA9IHRyYWlsZXI7CiAgICAgIGNvbnN0IHBhcnNlciA9IG5ldyBQYXJzZXIoewogICAgICAgIGxleGVyOiBuZXcgTGV4ZXIoc3RyZWFtKSwKICAgICAgICB4cmVmOiB0aGlzLAogICAgICAgIGFsbG93U3RyZWFtczogdHJ1ZSwKICAgICAgICByZWNvdmVyeU1vZGU6IHRydWUKICAgICAgfSk7CiAgICAgIGNvbnN0IG9iaiA9IHBhcnNlci5nZXRPYmooKTsKICAgICAgaWYgKCFpc0NtZChvYmosICJ0cmFpbGVyIikpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCBkaWN0ID0gcGFyc2VyLmdldE9iaigpOwogICAgICBpZiAoIShkaWN0IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICB0cmFpbGVyRGljdHMucHVzaChkaWN0KTsKICAgICAgaWYgKGRpY3QuaGFzKCJFbmNyeXB0IikpIHsKICAgICAgICBpc0VuY3J5cHRlZCA9IHRydWU7CiAgICAgIH0KICAgIH0KICAgIGxldCB0cmFpbGVyRGljdCwgdHJhaWxlckVycm9yOwogICAgZm9yIChjb25zdCBkaWN0IG9mIFsuLi50cmFpbGVyRGljdHMsICJnZW5GYWxsYmFjayIsIC4uLnRyYWlsZXJEaWN0c10pIHsKICAgICAgaWYgKGRpY3QgPT09ICJnZW5GYWxsYmFjayIpIHsKICAgICAgICBpZiAoIXRyYWlsZXJFcnJvcikgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHRoaXMuX2dlbmVyYXRpb25GYWxsYmFjayA9IHRydWU7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgbGV0IHZhbGlkUGFnZXNEaWN0ID0gZmFsc2U7CiAgICAgIHRyeSB7CiAgICAgICAgY29uc3Qgcm9vdERpY3QgPSBkaWN0LmdldCgiUm9vdCIpOwogICAgICAgIGlmICghKHJvb3REaWN0IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBwYWdlc0RpY3QgPSByb290RGljdC5nZXQoIlBhZ2VzIik7CiAgICAgICAgaWYgKCEocGFnZXNEaWN0IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBjb25zdCBwYWdlc0NvdW50ID0gcGFnZXNEaWN0LmdldCgiQ291bnQiKTsKICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcihwYWdlc0NvdW50KSkgewogICAgICAgICAgdmFsaWRQYWdlc0RpY3QgPSB0cnVlOwogICAgICAgIH0KICAgICAgfSBjYXRjaCAoZXgpIHsKICAgICAgICB0cmFpbGVyRXJyb3IgPSBleDsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBpZiAodmFsaWRQYWdlc0RpY3QgJiYgKCFpc0VuY3J5cHRlZCB8fCBkaWN0LmhhcygiRW5jcnlwdCIpKSAmJiBkaWN0LmhhcygiSUQiKSkgewogICAgICAgIHJldHVybiBkaWN0OwogICAgICB9CiAgICAgIHRyYWlsZXJEaWN0ID0gZGljdDsKICAgIH0KICAgIGlmICh0cmFpbGVyRGljdCkgewogICAgICByZXR1cm4gdHJhaWxlckRpY3Q7CiAgICB9CiAgICBpZiAodGhpcy50b3BEaWN0KSB7CiAgICAgIHJldHVybiB0aGlzLnRvcERpY3Q7CiAgICB9CiAgICBpZiAoIXRyYWlsZXJEaWN0cy5sZW5ndGgpIHsKICAgICAgZm9yIChjb25zdCBudW0gaW4gdGhpcy5lbnRyaWVzKSB7CiAgICAgICAgaWYgKCFPYmplY3QuaGFzT3duKHRoaXMuZW50cmllcywgbnVtKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvbnN0IGVudHJ5ID0gdGhpcy5lbnRyaWVzW251bV07CiAgICAgICAgY29uc3QgcmVmID0gUmVmLmdldChwYXJzZUludChudW0pLCBlbnRyeS5nZW4pOwogICAgICAgIGxldCBvYmo7CiAgICAgICAgdHJ5IHsKICAgICAgICAgIG9iaiA9IHRoaXMuZmV0Y2gocmVmKTsKICAgICAgICB9IGNhdGNoIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBpZiAob2JqIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICAgICAgb2JqID0gb2JqLmRpY3Q7CiAgICAgICAgfQogICAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBEaWN0ICYmIG9iai5oYXMoIlJvb3QiKSkgewogICAgICAgICAgcmV0dXJuIG9iajsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHRocm93IG5ldyBJbnZhbGlkUERGRXhjZXB0aW9uKCJJbnZhbGlkIFBERiBzdHJ1Y3R1cmUuIik7CiAgfQogIHJlYWRYUmVmKHJlY292ZXJ5TW9kZSA9IGZhbHNlKSB7CiAgICBjb25zdCBzdHJlYW0gPSB0aGlzLnN0cmVhbTsKICAgIGNvbnN0IHN0YXJ0WFJlZlBhcnNlZENhY2hlID0gbmV3IFNldCgpOwogICAgd2hpbGUgKHRoaXMuc3RhcnRYUmVmUXVldWUubGVuZ3RoKSB7CiAgICAgIHRyeSB7CiAgICAgICAgY29uc3Qgc3RhcnRYUmVmID0gdGhpcy5zdGFydFhSZWZRdWV1ZVswXTsKICAgICAgICBpZiAoc3RhcnRYUmVmUGFyc2VkQ2FjaGUuaGFzKHN0YXJ0WFJlZikpIHsKICAgICAgICAgIHdhcm4oInJlYWRYUmVmIC0gc2tpcHBpbmcgWFJlZiB0YWJsZSBzaW5jZSBpdCB3YXMgYWxyZWFkeSBwYXJzZWQuIik7CiAgICAgICAgICB0aGlzLnN0YXJ0WFJlZlF1ZXVlLnNoaWZ0KCk7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgc3RhcnRYUmVmUGFyc2VkQ2FjaGUuYWRkKHN0YXJ0WFJlZik7CiAgICAgICAgc3RyZWFtLnBvcyA9IHN0YXJ0WFJlZiArIHN0cmVhbS5zdGFydDsKICAgICAgICBjb25zdCBwYXJzZXIgPSBuZXcgUGFyc2VyKHsKICAgICAgICAgIGxleGVyOiBuZXcgTGV4ZXIoc3RyZWFtKSwKICAgICAgICAgIHhyZWY6IHRoaXMsCiAgICAgICAgICBhbGxvd1N0cmVhbXM6IHRydWUKICAgICAgICB9KTsKICAgICAgICBsZXQgb2JqID0gcGFyc2VyLmdldE9iaigpOwogICAgICAgIGxldCBkaWN0OwogICAgICAgIGlmIChpc0NtZChvYmosICJ4cmVmIikpIHsKICAgICAgICAgIGRpY3QgPSB0aGlzLnByb2Nlc3NYUmVmVGFibGUocGFyc2VyKTsKICAgICAgICAgIGlmICghdGhpcy50b3BEaWN0KSB7CiAgICAgICAgICAgIHRoaXMudG9wRGljdCA9IGRpY3Q7CiAgICAgICAgICB9CiAgICAgICAgICBvYmogPSBkaWN0LmdldCgiWFJlZlN0bSIpOwogICAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIob2JqKSAmJiAhdGhpcy5feHJlZlN0bXMuaGFzKG9iaikpIHsKICAgICAgICAgICAgdGhpcy5feHJlZlN0bXMuYWRkKG9iaik7CiAgICAgICAgICAgIHRoaXMuc3RhcnRYUmVmUXVldWUucHVzaChvYmopOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSBpZiAoTnVtYmVyLmlzSW50ZWdlcihvYmopKSB7CiAgICAgICAgICBpZiAoIU51bWJlci5pc0ludGVnZXIocGFyc2VyLmdldE9iaigpKSB8fCAhaXNDbWQocGFyc2VyLmdldE9iaigpLCAib2JqIikgfHwgISgob2JqID0gcGFyc2VyLmdldE9iaigpKSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pKSB7CiAgICAgICAgICAgIHRocm93IG5ldyBGb3JtYXRFcnJvcigiSW52YWxpZCBYUmVmIHN0cmVhbSIpOwogICAgICAgICAgfQogICAgICAgICAgZGljdCA9IHRoaXMucHJvY2Vzc1hSZWZTdHJlYW0ob2JqKTsKICAgICAgICAgIGlmICghdGhpcy50b3BEaWN0KSB7CiAgICAgICAgICAgIHRoaXMudG9wRGljdCA9IGRpY3Q7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoIWRpY3QpIHsKICAgICAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJGYWlsZWQgdG8gcmVhZCBYUmVmIHN0cmVhbSIpOwogICAgICAgICAgfQogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIkludmFsaWQgWFJlZiBzdHJlYW0gaGVhZGVyIik7CiAgICAgICAgfQogICAgICAgIG9iaiA9IGRpY3QuZ2V0KCJQcmV2Iik7CiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIob2JqKSkgewogICAgICAgICAgdGhpcy5zdGFydFhSZWZRdWV1ZS5wdXNoKG9iaik7CiAgICAgICAgfSBlbHNlIGlmIChvYmogaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgICAgIHRoaXMuc3RhcnRYUmVmUXVldWUucHVzaChvYmoubnVtKTsKICAgICAgICB9CiAgICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgICBpZiAoZSBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSB7CiAgICAgICAgICB0aHJvdyBlOwogICAgICAgIH0KICAgICAgICBpbmZvKCIod2hpbGUgcmVhZGluZyBYUmVmKTogIiArIGUpOwogICAgICB9CiAgICAgIHRoaXMuc3RhcnRYUmVmUXVldWUuc2hpZnQoKTsKICAgIH0KICAgIGlmICh0aGlzLnRvcERpY3QpIHsKICAgICAgcmV0dXJuIHRoaXMudG9wRGljdDsKICAgIH0KICAgIGlmIChyZWNvdmVyeU1vZGUpIHsKICAgICAgcmV0dXJuIHVuZGVmaW5lZDsKICAgIH0KICAgIHRocm93IG5ldyBYUmVmUGFyc2VFeGNlcHRpb24oKTsKICB9CiAgZ2V0RW50cnkoaSkgewogICAgY29uc3QgeHJlZkVudHJ5ID0gdGhpcy5lbnRyaWVzW2ldOwogICAgaWYgKHhyZWZFbnRyeSAmJiAheHJlZkVudHJ5LmZyZWUgJiYgeHJlZkVudHJ5Lm9mZnNldCkgewogICAgICByZXR1cm4geHJlZkVudHJ5OwogICAgfQogICAgcmV0dXJuIG51bGw7CiAgfQogIGZldGNoSWZSZWYob2JqLCBzdXBwcmVzc0VuY3J5cHRpb24gPSBmYWxzZSkgewogICAgaWYgKG9iaiBpbnN0YW5jZW9mIFJlZikgewogICAgICByZXR1cm4gdGhpcy5mZXRjaChvYmosIHN1cHByZXNzRW5jcnlwdGlvbik7CiAgICB9CiAgICByZXR1cm4gb2JqOwogIH0KICBmZXRjaChyZWYsIHN1cHByZXNzRW5jcnlwdGlvbiA9IGZhbHNlKSB7CiAgICBpZiAoIShyZWYgaW5zdGFuY2VvZiBSZWYpKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcigicmVmIG9iamVjdCBpcyBub3QgYSByZWZlcmVuY2UiKTsKICAgIH0KICAgIGNvbnN0IG51bSA9IHJlZi5udW07CiAgICBjb25zdCBjYWNoZUVudHJ5ID0gdGhpcy5fY2FjaGVNYXAuZ2V0KG51bSk7CiAgICBpZiAoY2FjaGVFbnRyeSAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIGlmIChjYWNoZUVudHJ5IGluc3RhbmNlb2YgRGljdCAmJiAhY2FjaGVFbnRyeS5vYmpJZCkgewogICAgICAgIGNhY2hlRW50cnkub2JqSWQgPSByZWYudG9TdHJpbmcoKTsKICAgICAgfQogICAgICByZXR1cm4gY2FjaGVFbnRyeTsKICAgIH0KICAgIGxldCB4cmVmRW50cnkgPSB0aGlzLmdldEVudHJ5KG51bSk7CiAgICBpZiAoeHJlZkVudHJ5ID09PSBudWxsKSB7CiAgICAgIHJldHVybiB4cmVmRW50cnk7CiAgICB9CiAgICBpZiAodGhpcy5fcGVuZGluZ1JlZnMuaGFzKHJlZikpIHsKICAgICAgdGhpcy5fcGVuZGluZ1JlZnMucmVtb3ZlKHJlZik7CiAgICAgIHdhcm4oYElnbm9yaW5nIGNpcmN1bGFyIHJlZmVyZW5jZTogJHtyZWZ9LmApOwogICAgICByZXR1cm4gQ0lSQ1VMQVJfUkVGOwogICAgfQogICAgdGhpcy5fcGVuZGluZ1JlZnMucHV0KHJlZik7CiAgICB0cnkgewogICAgICB4cmVmRW50cnkgPSB4cmVmRW50cnkudW5jb21wcmVzc2VkID8gdGhpcy5mZXRjaFVuY29tcHJlc3NlZChyZWYsIHhyZWZFbnRyeSwgc3VwcHJlc3NFbmNyeXB0aW9uKSA6IHRoaXMuZmV0Y2hDb21wcmVzc2VkKHJlZiwgeHJlZkVudHJ5LCBzdXBwcmVzc0VuY3J5cHRpb24pOwogICAgICB0aGlzLl9wZW5kaW5nUmVmcy5yZW1vdmUocmVmKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIHRoaXMuX3BlbmRpbmdSZWZzLnJlbW92ZShyZWYpOwogICAgICB0aHJvdyBleDsKICAgIH0KICAgIGlmICh4cmVmRW50cnkgaW5zdGFuY2VvZiBEaWN0KSB7CiAgICAgIHhyZWZFbnRyeS5vYmpJZCA9IHJlZi50b1N0cmluZygpOwogICAgfSBlbHNlIGlmICh4cmVmRW50cnkgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICAgIHhyZWZFbnRyeS5kaWN0Lm9iaklkID0gcmVmLnRvU3RyaW5nKCk7CiAgICB9CiAgICByZXR1cm4geHJlZkVudHJ5OwogIH0KICBmZXRjaFVuY29tcHJlc3NlZChyZWYsIHhyZWZFbnRyeSwgc3VwcHJlc3NFbmNyeXB0aW9uID0gZmFsc2UpIHsKICAgIGNvbnN0IGdlbiA9IHJlZi5nZW47CiAgICBsZXQgbnVtID0gcmVmLm51bTsKICAgIGlmICh4cmVmRW50cnkuZ2VuICE9PSBnZW4pIHsKICAgICAgY29uc3QgbXNnID0gYEluY29uc2lzdGVudCBnZW5lcmF0aW9uIGluIFhSZWY6ICR7cmVmfWA7CiAgICAgIGlmICh0aGlzLl9nZW5lcmF0aW9uRmFsbGJhY2sgJiYgeHJlZkVudHJ5LmdlbiA8IGdlbikgewogICAgICAgIHdhcm4obXNnKTsKICAgICAgICByZXR1cm4gdGhpcy5mZXRjaFVuY29tcHJlc3NlZChSZWYuZ2V0KG51bSwgeHJlZkVudHJ5LmdlbiksIHhyZWZFbnRyeSwgc3VwcHJlc3NFbmNyeXB0aW9uKTsKICAgICAgfQogICAgICB0aHJvdyBuZXcgWFJlZkVudHJ5RXhjZXB0aW9uKG1zZyk7CiAgICB9CiAgICBjb25zdCBzdHJlYW0gPSB0aGlzLnN0cmVhbS5tYWtlU3ViU3RyZWFtKHhyZWZFbnRyeS5vZmZzZXQgKyB0aGlzLnN0cmVhbS5zdGFydCk7CiAgICBjb25zdCBwYXJzZXIgPSBuZXcgUGFyc2VyKHsKICAgICAgbGV4ZXI6IG5ldyBMZXhlcihzdHJlYW0pLAogICAgICB4cmVmOiB0aGlzLAogICAgICBhbGxvd1N0cmVhbXM6IHRydWUKICAgIH0pOwogICAgY29uc3Qgb2JqMSA9IHBhcnNlci5nZXRPYmooKTsKICAgIGNvbnN0IG9iajIgPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICBjb25zdCBvYmozID0gcGFyc2VyLmdldE9iaigpOwogICAgaWYgKG9iajEgIT09IG51bSB8fCBvYmoyICE9PSBnZW4gfHwgIShvYmozIGluc3RhbmNlb2YgQ21kKSkgewogICAgICB0aHJvdyBuZXcgWFJlZkVudHJ5RXhjZXB0aW9uKGBCYWQgKHVuY29tcHJlc3NlZCkgWFJlZiBlbnRyeTogJHtyZWZ9YCk7CiAgICB9CiAgICBpZiAob2JqMy5jbWQgIT09ICJvYmoiKSB7CiAgICAgIGlmIChvYmozLmNtZC5zdGFydHNXaXRoKCJvYmoiKSkgewogICAgICAgIG51bSA9IHBhcnNlSW50KG9iajMuY21kLnN1YnN0cmluZygzKSwgMTApOwogICAgICAgIGlmICghTnVtYmVyLmlzTmFOKG51bSkpIHsKICAgICAgICAgIHJldHVybiBudW07CiAgICAgICAgfQogICAgICB9CiAgICAgIHRocm93IG5ldyBYUmVmRW50cnlFeGNlcHRpb24oYEJhZCAodW5jb21wcmVzc2VkKSBYUmVmIGVudHJ5OiAke3JlZn1gKTsKICAgIH0KICAgIHhyZWZFbnRyeSA9IHRoaXMuZW5jcnlwdCAmJiAhc3VwcHJlc3NFbmNyeXB0aW9uID8gcGFyc2VyLmdldE9iaih0aGlzLmVuY3J5cHQuY3JlYXRlQ2lwaGVyVHJhbnNmb3JtKG51bSwgZ2VuKSkgOiBwYXJzZXIuZ2V0T2JqKCk7CiAgICBpZiAoISh4cmVmRW50cnkgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSkgewogICAgICB0aGlzLl9jYWNoZU1hcC5zZXQobnVtLCB4cmVmRW50cnkpOwogICAgfQogICAgcmV0dXJuIHhyZWZFbnRyeTsKICB9CiAgZmV0Y2hDb21wcmVzc2VkKHJlZiwgeHJlZkVudHJ5LCBzdXBwcmVzc0VuY3J5cHRpb24gPSBmYWxzZSkgewogICAgY29uc3QgdGFibGVPZmZzZXQgPSB4cmVmRW50cnkub2Zmc2V0OwogICAgY29uc3Qgc3RyZWFtID0gdGhpcy5mZXRjaChSZWYuZ2V0KHRhYmxlT2Zmc2V0LCAwKSk7CiAgICBpZiAoIShzdHJlYW0gaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSkgewogICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoImJhZCBPYmpTdG0gc3RyZWFtIik7CiAgICB9CiAgICBjb25zdCBmaXJzdCA9IHN0cmVhbS5kaWN0LmdldCgiRmlyc3QiKTsKICAgIGNvbnN0IG4gPSBzdHJlYW0uZGljdC5nZXQoIk4iKTsKICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihmaXJzdCkgfHwgIU51bWJlci5pc0ludGVnZXIobikpIHsKICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJpbnZhbGlkIGZpcnN0IGFuZCBuIHBhcmFtZXRlcnMgZm9yIE9ialN0bSBzdHJlYW0iKTsKICAgIH0KICAgIGxldCBwYXJzZXIgPSBuZXcgUGFyc2VyKHsKICAgICAgbGV4ZXI6IG5ldyBMZXhlcihzdHJlYW0pLAogICAgICB4cmVmOiB0aGlzLAogICAgICBhbGxvd1N0cmVhbXM6IHRydWUKICAgIH0pOwogICAgY29uc3QgbnVtcyA9IG5ldyBBcnJheShuKTsKICAgIGNvbnN0IG9mZnNldHMgPSBuZXcgQXJyYXkobik7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG47ICsraSkgewogICAgICBjb25zdCBudW0gPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihudW0pKSB7CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKGBpbnZhbGlkIG9iamVjdCBudW1iZXIgaW4gdGhlIE9ialN0bSBzdHJlYW06ICR7bnVtfWApOwogICAgICB9CiAgICAgIGNvbnN0IG9mZnNldCA9IHBhcnNlci5nZXRPYmooKTsKICAgICAgaWYgKCFOdW1iZXIuaXNJbnRlZ2VyKG9mZnNldCkpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoYGludmFsaWQgb2JqZWN0IG9mZnNldCBpbiB0aGUgT2JqU3RtIHN0cmVhbTogJHtvZmZzZXR9YCk7CiAgICAgIH0KICAgICAgbnVtc1tpXSA9IG51bTsKICAgICAgY29uc3QgZW50cnkgPSB0aGlzLmdldEVudHJ5KG51bSk7CiAgICAgIGlmIChlbnRyeT8ub2Zmc2V0ID09PSB0YWJsZU9mZnNldCAmJiBlbnRyeS5nZW4gIT09IGkpIHsKICAgICAgICBlbnRyeS5nZW4gPSBpOwogICAgICB9CiAgICAgIG9mZnNldHNbaV0gPSBvZmZzZXQ7CiAgICB9CiAgICBjb25zdCBzdGFydCA9IChzdHJlYW0uc3RhcnQgfHwgMCkgKyBmaXJzdDsKICAgIGNvbnN0IGVudHJpZXMgPSBuZXcgQXJyYXkobik7CiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG47ICsraSkgewogICAgICBjb25zdCBsZW5ndGggPSBpIDwgbiAtIDEgPyBvZmZzZXRzW2kgKyAxXSAtIG9mZnNldHNbaV0gOiB1bmRlZmluZWQ7CiAgICAgIGlmIChsZW5ndGggPCAwKSB7CiAgICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJJbnZhbGlkIG9mZnNldCBpbiB0aGUgT2JqU3RtIHN0cmVhbS4iKTsKICAgICAgfQogICAgICBwYXJzZXIgPSBuZXcgUGFyc2VyKHsKICAgICAgICBsZXhlcjogbmV3IExleGVyKHN0cmVhbS5tYWtlU3ViU3RyZWFtKHN0YXJ0ICsgb2Zmc2V0c1tpXSwgbGVuZ3RoLCBzdHJlYW0uZGljdCkpLAogICAgICAgIHhyZWY6IHRoaXMsCiAgICAgICAgYWxsb3dTdHJlYW1zOiB0cnVlCiAgICAgIH0pOwogICAgICBjb25zdCBvYmogPSBwYXJzZXIuZ2V0T2JqKCk7CiAgICAgIGVudHJpZXNbaV0gPSBvYmo7CiAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgbnVtID0gbnVtc1tpXSwKICAgICAgICBlbnRyeSA9IHRoaXMuZW50cmllc1tudW1dOwogICAgICBpZiAoZW50cnkgJiYgZW50cnkub2Zmc2V0ID09PSB0YWJsZU9mZnNldCAmJiBlbnRyeS5nZW4gPT09IGkpIHsKICAgICAgICB0aGlzLl9jYWNoZU1hcC5zZXQobnVtLCBvYmopOwogICAgICB9CiAgICB9CiAgICB4cmVmRW50cnkgPSBlbnRyaWVzW3hyZWZFbnRyeS5nZW5dOwogICAgaWYgKHhyZWZFbnRyeSA9PT0gdW5kZWZpbmVkKSB7CiAgICAgIHRocm93IG5ldyBYUmVmRW50cnlFeGNlcHRpb24oYEJhZCAoY29tcHJlc3NlZCkgWFJlZiBlbnRyeTogJHtyZWZ9YCk7CiAgICB9CiAgICByZXR1cm4geHJlZkVudHJ5OwogIH0KICBhc3luYyBmZXRjaElmUmVmQXN5bmMob2JqLCBzdXBwcmVzc0VuY3J5cHRpb24pIHsKICAgIGlmIChvYmogaW5zdGFuY2VvZiBSZWYpIHsKICAgICAgcmV0dXJuIHRoaXMuZmV0Y2hBc3luYyhvYmosIHN1cHByZXNzRW5jcnlwdGlvbik7CiAgICB9CiAgICByZXR1cm4gb2JqOwogIH0KICBhc3luYyBmZXRjaEFzeW5jKHJlZiwgc3VwcHJlc3NFbmNyeXB0aW9uKSB7CiAgICB0cnkgewogICAgICByZXR1cm4gdGhpcy5mZXRjaChyZWYsIHN1cHByZXNzRW5jcnlwdGlvbik7CiAgICB9IGNhdGNoIChleCkgewogICAgICBpZiAoIShleCBpbnN0YW5jZW9mIE1pc3NpbmdEYXRhRXhjZXB0aW9uKSkgewogICAgICAgIHRocm93IGV4OwogICAgICB9CiAgICAgIGF3YWl0IHRoaXMucGRmTWFuYWdlci5yZXF1ZXN0UmFuZ2UoZXguYmVnaW4sIGV4LmVuZCk7CiAgICAgIHJldHVybiB0aGlzLmZldGNoQXN5bmMocmVmLCBzdXBwcmVzc0VuY3J5cHRpb24pOwogICAgfQogIH0KICBnZXRDYXRhbG9nT2JqKCkgewogICAgcmV0dXJuIHRoaXMucm9vdDsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL2RvY3VtZW50LmpzCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgpjb25zdCBMRVRURVJfU0laRV9NRURJQUJPWCA9IFswLCAwLCA2MTIsIDc5Ml07CmNsYXNzIFBhZ2UgewogICNhcmVBbm5vdGF0aW9uc0NhY2hlZCA9IGZhbHNlOwogICNyZXNvdXJjZXNQcm9taXNlID0gbnVsbDsKICBjb25zdHJ1Y3Rvcih7CiAgICBwZGZNYW5hZ2VyLAogICAgeHJlZiwKICAgIHBhZ2VJbmRleCwKICAgIHBhZ2VEaWN0LAogICAgcmVmLAogICAgZ2xvYmFsSWRGYWN0b3J5LAogICAgZm9udENhY2hlLAogICAgYnVpbHRJbkNNYXBDYWNoZSwKICAgIHN0YW5kYXJkRm9udERhdGFDYWNoZSwKICAgIGdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgIGdsb2JhbEltYWdlQ2FjaGUsCiAgICBzeXN0ZW1Gb250Q2FjaGUsCiAgICBub25CbGVuZE1vZGVzU2V0LAogICAgeGZhRmFjdG9yeQogIH0pIHsKICAgIHRoaXMucGRmTWFuYWdlciA9IHBkZk1hbmFnZXI7CiAgICB0aGlzLnBhZ2VJbmRleCA9IHBhZ2VJbmRleDsKICAgIHRoaXMucGFnZURpY3QgPSBwYWdlRGljdDsKICAgIHRoaXMueHJlZiA9IHhyZWY7CiAgICB0aGlzLnJlZiA9IHJlZjsKICAgIHRoaXMuZm9udENhY2hlID0gZm9udENhY2hlOwogICAgdGhpcy5idWlsdEluQ01hcENhY2hlID0gYnVpbHRJbkNNYXBDYWNoZTsKICAgIHRoaXMuc3RhbmRhcmRGb250RGF0YUNhY2hlID0gc3RhbmRhcmRGb250RGF0YUNhY2hlOwogICAgdGhpcy5nbG9iYWxDb2xvclNwYWNlQ2FjaGUgPSBnbG9iYWxDb2xvclNwYWNlQ2FjaGU7CiAgICB0aGlzLmdsb2JhbEltYWdlQ2FjaGUgPSBnbG9iYWxJbWFnZUNhY2hlOwogICAgdGhpcy5zeXN0ZW1Gb250Q2FjaGUgPSBzeXN0ZW1Gb250Q2FjaGU7CiAgICB0aGlzLm5vbkJsZW5kTW9kZXNTZXQgPSBub25CbGVuZE1vZGVzU2V0OwogICAgdGhpcy5ldmFsdWF0b3JPcHRpb25zID0gcGRmTWFuYWdlci5ldmFsdWF0b3JPcHRpb25zOwogICAgdGhpcy54ZmFGYWN0b3J5ID0geGZhRmFjdG9yeTsKICAgIGNvbnN0IGlkQ291bnRlcnMgPSB7CiAgICAgIG9iajogMAogICAgfTsKICAgIHRoaXMuX2xvY2FsSWRGYWN0b3J5ID0gY2xhc3MgZXh0ZW5kcyBnbG9iYWxJZEZhY3RvcnkgewogICAgICBzdGF0aWMgY3JlYXRlT2JqSWQoKSB7CiAgICAgICAgcmV0dXJuIGBwJHtwYWdlSW5kZXh9XyR7KytpZENvdW50ZXJzLm9ian1gOwogICAgICB9CiAgICAgIHN0YXRpYyBnZXRQYWdlT2JqSWQoKSB7CiAgICAgICAgcmV0dXJuIGBwJHtyZWYudG9TdHJpbmcoKX1gOwogICAgICB9CiAgICB9OwogIH0KICAjY3JlYXRlUGFydGlhbEV2YWx1YXRvcihoYW5kbGVyKSB7CiAgICByZXR1cm4gbmV3IFBhcnRpYWxFdmFsdWF0b3IoewogICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgIGhhbmRsZXIsCiAgICAgIHBhZ2VJbmRleDogdGhpcy5wYWdlSW5kZXgsCiAgICAgIGlkRmFjdG9yeTogdGhpcy5fbG9jYWxJZEZhY3RvcnksCiAgICAgIGZvbnRDYWNoZTogdGhpcy5mb250Q2FjaGUsCiAgICAgIGJ1aWx0SW5DTWFwQ2FjaGU6IHRoaXMuYnVpbHRJbkNNYXBDYWNoZSwKICAgICAgc3RhbmRhcmRGb250RGF0YUNhY2hlOiB0aGlzLnN0YW5kYXJkRm9udERhdGFDYWNoZSwKICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOiB0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgICAgZ2xvYmFsSW1hZ2VDYWNoZTogdGhpcy5nbG9iYWxJbWFnZUNhY2hlLAogICAgICBzeXN0ZW1Gb250Q2FjaGU6IHRoaXMuc3lzdGVtRm9udENhY2hlLAogICAgICBvcHRpb25zOiB0aGlzLmV2YWx1YXRvck9wdGlvbnMKICAgIH0pOwogIH0KICAjZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eShrZXksIGdldEFycmF5ID0gZmFsc2UpIHsKICAgIGNvbnN0IHZhbHVlID0gZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSh7CiAgICAgIGRpY3Q6IHRoaXMucGFnZURpY3QsCiAgICAgIGtleSwKICAgICAgZ2V0QXJyYXksCiAgICAgIHN0b3BXaGVuRm91bmQ6IGZhbHNlCiAgICB9KTsKICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHsKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfQogICAgaWYgKHZhbHVlLmxlbmd0aCA9PT0gMSB8fCAhKHZhbHVlWzBdIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuIHZhbHVlWzBdOwogICAgfQogICAgcmV0dXJuIERpY3QubWVyZ2UoewogICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgIGRpY3RBcnJheTogdmFsdWUKICAgIH0pOwogIH0KICBnZXQgY29udGVudCgpIHsKICAgIHJldHVybiB0aGlzLnBhZ2VEaWN0LmdldEFycmF5KCJDb250ZW50cyIpOwogIH0KICBnZXQgcmVzb3VyY2VzKCkgewogICAgY29uc3QgcmVzb3VyY2VzID0gdGhpcy4jZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSgiUmVzb3VyY2VzIik7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJyZXNvdXJjZXMiLCByZXNvdXJjZXMgaW5zdGFuY2VvZiBEaWN0ID8gcmVzb3VyY2VzIDogRGljdC5lbXB0eSk7CiAgfQogICNnZXRCb3VuZGluZ0JveChuYW1lKSB7CiAgICBpZiAodGhpcy54ZmFEYXRhKSB7CiAgICAgIHJldHVybiB0aGlzLnhmYURhdGEuYmJveDsKICAgIH0KICAgIGNvbnN0IGJveCA9IGxvb2t1cE5vcm1hbFJlY3QodGhpcy4jZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eShuYW1lLCB0cnVlKSwgbnVsbCk7CiAgICBpZiAoYm94KSB7CiAgICAgIGlmIChib3hbMl0gLSBib3hbMF0gPiAwICYmIGJveFszXSAtIGJveFsxXSA+IDApIHsKICAgICAgICByZXR1cm4gYm94OwogICAgICB9CiAgICAgIHdhcm4oYEVtcHR5LCBvciBpbnZhbGlkLCAvJHtuYW1lfSBlbnRyeS5gKTsKICAgIH0KICAgIHJldHVybiBudWxsOwogIH0KICBnZXQgbWVkaWFCb3goKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJtZWRpYUJveCIsIHRoaXMuI2dldEJvdW5kaW5nQm94KCJNZWRpYUJveCIpIHx8IExFVFRFUl9TSVpFX01FRElBQk9YKTsKICB9CiAgZ2V0IGNyb3BCb3goKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJjcm9wQm94IiwgdGhpcy4jZ2V0Qm91bmRpbmdCb3goIkNyb3BCb3giKSB8fCB0aGlzLm1lZGlhQm94KTsKICB9CiAgZ2V0IHVzZXJVbml0KCkgewogICAgY29uc3Qgb2JqID0gdGhpcy5wYWdlRGljdC5nZXQoIlVzZXJVbml0Iik7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJ1c2VyVW5pdCIsIHR5cGVvZiBvYmogPT09ICJudW1iZXIiICYmIG9iaiA+IDAgPyBvYmogOiAxLjApOwogIH0KICBnZXQgdmlldygpIHsKICAgIGNvbnN0IHsKICAgICAgY3JvcEJveCwKICAgICAgbWVkaWFCb3gKICAgIH0gPSB0aGlzOwogICAgaWYgKGNyb3BCb3ggIT09IG1lZGlhQm94ICYmICFpc0FycmF5RXF1YWwoY3JvcEJveCwgbWVkaWFCb3gpKSB7CiAgICAgIGNvbnN0IGJveCA9IFV0aWwuaW50ZXJzZWN0KGNyb3BCb3gsIG1lZGlhQm94KTsKICAgICAgaWYgKGJveCAmJiBib3hbMl0gLSBib3hbMF0gPiAwICYmIGJveFszXSAtIGJveFsxXSA+IDApIHsKICAgICAgICByZXR1cm4gc2hhZG93KHRoaXMsICJ2aWV3IiwgYm94KTsKICAgICAgfQogICAgICB3YXJuKCJFbXB0eSAvQ3JvcEJveCBhbmQgL01lZGlhQm94IGludGVyc2VjdGlvbi4iKTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgInZpZXciLCBtZWRpYUJveCk7CiAgfQogIGdldCByb3RhdGUoKSB7CiAgICBsZXQgcm90YXRlID0gdGhpcy4jZ2V0SW5oZXJpdGFibGVQcm9wZXJ0eSgiUm90YXRlIikgfHwgMDsKICAgIGlmIChyb3RhdGUgJSA5MCAhPT0gMCkgewogICAgICByb3RhdGUgPSAwOwogICAgfSBlbHNlIGlmIChyb3RhdGUgPj0gMzYwKSB7CiAgICAgIHJvdGF0ZSAlPSAzNjA7CiAgICB9IGVsc2UgaWYgKHJvdGF0ZSA8IDApIHsKICAgICAgcm90YXRlID0gKHJvdGF0ZSAlIDM2MCArIDM2MCkgJSAzNjA7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJyb3RhdGUiLCByb3RhdGUpOwogIH0KICAjb25TdWJTdHJlYW1FcnJvcihyZWFzb24sIG9iaklkKSB7CiAgICBpZiAodGhpcy5ldmFsdWF0b3JPcHRpb25zLmlnbm9yZUVycm9ycykgewogICAgICB3YXJuKGBnZXRDb250ZW50U3RyZWFtIC0gaWdub3Jpbmcgc3ViLXN0cmVhbSAoJHtvYmpJZH0pOiAiJHtyZWFzb259Ii5gKTsKICAgICAgcmV0dXJuOwogICAgfQogICAgdGhyb3cgcmVhc29uOwogIH0KICBhc3luYyBnZXRDb250ZW50U3RyZWFtKCkgewogICAgY29uc3QgY29udGVudCA9IGF3YWl0IHRoaXMucGRmTWFuYWdlci5lbnN1cmUodGhpcywgImNvbnRlbnQiKTsKICAgIGlmIChjb250ZW50IGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgICByZXR1cm4gY29udGVudDsKICAgIH0KICAgIGlmIChBcnJheS5pc0FycmF5KGNvbnRlbnQpKSB7CiAgICAgIHJldHVybiBuZXcgU3RyZWFtc1NlcXVlbmNlU3RyZWFtKGNvbnRlbnQsIHRoaXMuI29uU3ViU3RyZWFtRXJyb3IuYmluZCh0aGlzKSk7CiAgICB9CiAgICByZXR1cm4gbmV3IE51bGxTdHJlYW0oKTsKICB9CiAgZ2V0IHhmYURhdGEoKSB7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJ4ZmFEYXRhIiwgdGhpcy54ZmFGYWN0b3J5ID8gewogICAgICBiYm94OiB0aGlzLnhmYUZhY3RvcnkuZ2V0Qm91bmRpbmdCb3godGhpcy5wYWdlSW5kZXgpCiAgICB9IDogbnVsbCk7CiAgfQogIGFzeW5jICNyZXBsYWNlSWRCeVJlZihhbm5vdGF0aW9ucywgZGVsZXRlZEFubm90YXRpb25zLCBleGlzdGluZ0Fubm90YXRpb25zKSB7CiAgICBjb25zdCBwcm9taXNlcyA9IFtdOwogICAgZm9yIChjb25zdCBhbm5vdGF0aW9uIG9mIGFubm90YXRpb25zKSB7CiAgICAgIGlmIChhbm5vdGF0aW9uLmlkKSB7CiAgICAgICAgY29uc3QgcmVmID0gUmVmLmZyb21TdHJpbmcoYW5ub3RhdGlvbi5pZCk7CiAgICAgICAgaWYgKCFyZWYpIHsKICAgICAgICAgIHdhcm4oYEEgbm9uLWxpbmtlZCBhbm5vdGF0aW9uIGNhbm5vdCBiZSBtb2RpZmllZDogJHthbm5vdGF0aW9uLmlkfWApOwogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGlmIChhbm5vdGF0aW9uLmRlbGV0ZWQpIHsKICAgICAgICAgIGRlbGV0ZWRBbm5vdGF0aW9ucy5wdXQocmVmLCByZWYpOwogICAgICAgICAgaWYgKGFubm90YXRpb24ucG9wdXBSZWYpIHsKICAgICAgICAgICAgY29uc3QgcG9wdXBSZWYgPSBSZWYuZnJvbVN0cmluZyhhbm5vdGF0aW9uLnBvcHVwUmVmKTsKICAgICAgICAgICAgaWYgKHBvcHVwUmVmKSB7CiAgICAgICAgICAgICAgZGVsZXRlZEFubm90YXRpb25zLnB1dChwb3B1cFJlZiwgcG9wdXBSZWYpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaWYgKGFubm90YXRpb24ucG9wdXA/LmRlbGV0ZWQpIHsKICAgICAgICAgIGNvbnN0IHBvcHVwUmVmID0gUmVmLmZyb21TdHJpbmcoYW5ub3RhdGlvbi5wb3B1cFJlZik7CiAgICAgICAgICBpZiAocG9wdXBSZWYpIHsKICAgICAgICAgICAgZGVsZXRlZEFubm90YXRpb25zLnB1dChwb3B1cFJlZiwgcG9wdXBSZWYpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBleGlzdGluZ0Fubm90YXRpb25zPy5wdXQocmVmKTsKICAgICAgICBhbm5vdGF0aW9uLnJlZiA9IHJlZjsKICAgICAgICBwcm9taXNlcy5wdXNoKHRoaXMueHJlZi5mZXRjaEFzeW5jKHJlZikudGhlbihvYmogPT4gewogICAgICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICAgICAgYW5ub3RhdGlvbi5vbGRBbm5vdGF0aW9uID0gb2JqLmNsb25lKCk7CiAgICAgICAgICB9CiAgICAgICAgfSwgKCkgPT4gewogICAgICAgICAgd2FybihgQ2Fubm90IGZldGNoIFxgb2xkQW5ub3RhdGlvblxgIGZvcjogJHtyZWZ9LmApOwogICAgICAgIH0pKTsKICAgICAgICBkZWxldGUgYW5ub3RhdGlvbi5pZDsKICAgICAgfQogICAgfQogICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpOwogIH0KICBhc3luYyBzYXZlTmV3QW5ub3RhdGlvbnMoaGFuZGxlciwgdGFzaywgYW5ub3RhdGlvbnMsIGltYWdlUHJvbWlzZXMsIGNoYW5nZXMpIHsKICAgIGlmICh0aGlzLnhmYUZhY3RvcnkpIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKCJYRkE6IENhbm5vdCBzYXZlIG5ldyBhbm5vdGF0aW9ucy4iKTsKICAgIH0KICAgIGNvbnN0IHBhcnRpYWxFdmFsdWF0b3IgPSB0aGlzLiNjcmVhdGVQYXJ0aWFsRXZhbHVhdG9yKGhhbmRsZXIpOwogICAgY29uc3QgZGVsZXRlZEFubm90YXRpb25zID0gbmV3IFJlZlNldENhY2hlKCk7CiAgICBjb25zdCBleGlzdGluZ0Fubm90YXRpb25zID0gbmV3IFJlZlNldCgpOwogICAgYXdhaXQgdGhpcy4jcmVwbGFjZUlkQnlSZWYoYW5ub3RhdGlvbnMsIGRlbGV0ZWRBbm5vdGF0aW9ucywgZXhpc3RpbmdBbm5vdGF0aW9ucyk7CiAgICBjb25zdCBwYWdlRGljdCA9IHRoaXMucGFnZURpY3Q7CiAgICBjb25zdCBhbm5vdGF0aW9uc0FycmF5ID0gdGhpcy5hbm5vdGF0aW9ucy5maWx0ZXIoYSA9PiAhKGEgaW5zdGFuY2VvZiBSZWYgJiYgZGVsZXRlZEFubm90YXRpb25zLmhhcyhhKSkpOwogICAgY29uc3QgbmV3RGF0YSA9IGF3YWl0IEFubm90YXRpb25GYWN0b3J5LnNhdmVOZXdBbm5vdGF0aW9ucyhwYXJ0aWFsRXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9ucywgaW1hZ2VQcm9taXNlcywgY2hhbmdlcyk7CiAgICBmb3IgKGNvbnN0IHsKICAgICAgcmVmCiAgICB9IG9mIG5ld0RhdGEuYW5ub3RhdGlvbnMpIHsKICAgICAgaWYgKHJlZiBpbnN0YW5jZW9mIFJlZiAmJiAhZXhpc3RpbmdBbm5vdGF0aW9ucy5oYXMocmVmKSkgewogICAgICAgIGFubm90YXRpb25zQXJyYXkucHVzaChyZWYpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBkaWN0ID0gcGFnZURpY3QuY2xvbmUoKTsKICAgIGRpY3Quc2V0KCJBbm5vdHMiLCBhbm5vdGF0aW9uc0FycmF5KTsKICAgIGNoYW5nZXMucHV0KHRoaXMucmVmLCB7CiAgICAgIGRhdGE6IGRpY3QKICAgIH0pOwogICAgZm9yIChjb25zdCBkZWxldGVkUmVmIG9mIGRlbGV0ZWRBbm5vdGF0aW9ucykgewogICAgICBjaGFuZ2VzLnB1dChkZWxldGVkUmVmLCB7CiAgICAgICAgZGF0YTogbnVsbAogICAgICB9KTsKICAgIH0KICB9CiAgYXN5bmMgc2F2ZShoYW5kbGVyLCB0YXNrLCBhbm5vdGF0aW9uU3RvcmFnZSwgY2hhbmdlcykgewogICAgY29uc3QgcGFydGlhbEV2YWx1YXRvciA9IHRoaXMuI2NyZWF0ZVBhcnRpYWxFdmFsdWF0b3IoaGFuZGxlcik7CiAgICBjb25zdCBhbm5vdGF0aW9ucyA9IGF3YWl0IHRoaXMuX3BhcnNlZEFubm90YXRpb25zOwogICAgY29uc3QgcHJvbWlzZXMgPSBbXTsKICAgIGZvciAoY29uc3QgYW5ub3RhdGlvbiBvZiBhbm5vdGF0aW9ucykgewogICAgICBwcm9taXNlcy5wdXNoKGFubm90YXRpb24uc2F2ZShwYXJ0aWFsRXZhbHVhdG9yLCB0YXNrLCBhbm5vdGF0aW9uU3RvcmFnZSwgY2hhbmdlcykuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgIHdhcm4oInNhdmUgLSBpZ25vcmluZyBhbm5vdGF0aW9uIGRhdGEgZHVyaW5nICIgKyBgIiR7dGFzay5uYW1lfSIgdGFzazogIiR7cmVhc29ufSIuYCk7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0pKTsKICAgIH0KICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcyk7CiAgfQogIGFzeW5jIGxvYWRSZXNvdXJjZXMoa2V5cykgewogICAgYXdhaXQgKHRoaXMuI3Jlc291cmNlc1Byb21pc2UgPz89IHRoaXMucGRmTWFuYWdlci5lbnN1cmUodGhpcywgInJlc291cmNlcyIpKTsKICAgIGF3YWl0IE9iamVjdExvYWRlci5sb2FkKHRoaXMucmVzb3VyY2VzLCBrZXlzLCB0aGlzLnhyZWYpOwogIH0KICBhc3luYyAjZ2V0TWVyZ2VkUmVzb3VyY2VzKHN0cmVhbURpY3QsIGtleXMpIHsKICAgIGNvbnN0IGxvY2FsUmVzb3VyY2VzID0gc3RyZWFtRGljdD8uZ2V0KCJSZXNvdXJjZXMiKTsKICAgIGlmICghKGxvY2FsUmVzb3VyY2VzIGluc3RhbmNlb2YgRGljdCAmJiBsb2NhbFJlc291cmNlcy5zaXplKSkgewogICAgICByZXR1cm4gdGhpcy5yZXNvdXJjZXM7CiAgICB9CiAgICBhd2FpdCBPYmplY3RMb2FkZXIubG9hZChsb2NhbFJlc291cmNlcywga2V5cywgdGhpcy54cmVmKTsKICAgIHJldHVybiBEaWN0Lm1lcmdlKHsKICAgICAgeHJlZjogdGhpcy54cmVmLAogICAgICBkaWN0QXJyYXk6IFtsb2NhbFJlc291cmNlcywgdGhpcy5yZXNvdXJjZXNdLAogICAgICBtZXJnZVN1YkRpY3RzOiB0cnVlCiAgICB9KTsKICB9CiAgYXN5bmMgZ2V0T3BlcmF0b3JMaXN0KHsKICAgIGhhbmRsZXIsCiAgICBzaW5rLAogICAgdGFzaywKICAgIGludGVudCwKICAgIGNhY2hlS2V5LAogICAgYW5ub3RhdGlvblN0b3JhZ2UgPSBudWxsLAogICAgbW9kaWZpZWRJZHMgPSBudWxsCiAgfSkgewogICAgY29uc3QgY29udGVudFN0cmVhbVByb21pc2UgPSB0aGlzLmdldENvbnRlbnRTdHJlYW0oKTsKICAgIGNvbnN0IHJlc291cmNlc1Byb21pc2UgPSB0aGlzLmxvYWRSZXNvdXJjZXMoUkVTT1VSQ0VTX0tFWVNfT1BFUkFUT1JfTElTVCk7CiAgICBjb25zdCBwYXJ0aWFsRXZhbHVhdG9yID0gdGhpcy4jY3JlYXRlUGFydGlhbEV2YWx1YXRvcihoYW5kbGVyKTsKICAgIGNvbnN0IG5ld0Fubm90c0J5UGFnZSA9ICF0aGlzLnhmYUZhY3RvcnkgPyBnZXROZXdBbm5vdGF0aW9uc01hcChhbm5vdGF0aW9uU3RvcmFnZSkgOiBudWxsOwogICAgY29uc3QgbmV3QW5ub3RzID0gbmV3QW5ub3RzQnlQYWdlPy5nZXQodGhpcy5wYWdlSW5kZXgpOwogICAgbGV0IG5ld0Fubm90YXRpb25zUHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZShudWxsKTsKICAgIGxldCBkZWxldGVkQW5ub3RhdGlvbnMgPSBudWxsOwogICAgaWYgKG5ld0Fubm90cykgewogICAgICBjb25zdCBhbm5vdGF0aW9uR2xvYmFsc1Byb21pc2UgPSB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlRG9jKCJhbm5vdGF0aW9uR2xvYmFscyIpOwogICAgICBsZXQgaW1hZ2VQcm9taXNlczsKICAgICAgY29uc3QgbWlzc2luZ0JpdG1hcHMgPSBuZXcgU2V0KCk7CiAgICAgIGZvciAoY29uc3QgewogICAgICAgIGJpdG1hcElkLAogICAgICAgIGJpdG1hcAogICAgICB9IG9mIG5ld0Fubm90cykgewogICAgICAgIGlmIChiaXRtYXBJZCAmJiAhYml0bWFwICYmICFtaXNzaW5nQml0bWFwcy5oYXMoYml0bWFwSWQpKSB7CiAgICAgICAgICBtaXNzaW5nQml0bWFwcy5hZGQoYml0bWFwSWQpOwogICAgICAgIH0KICAgICAgfQogICAgICBjb25zdCB7CiAgICAgICAgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQKICAgICAgfSA9IHRoaXMuZXZhbHVhdG9yT3B0aW9uczsKICAgICAgaWYgKG1pc3NpbmdCaXRtYXBzLnNpemUgPiAwKSB7CiAgICAgICAgY29uc3QgYW5ub3RhdGlvbldpdGhCaXRtYXBzID0gbmV3QW5ub3RzLnNsaWNlKCk7CiAgICAgICAgZm9yIChjb25zdCBba2V5LCBhbm5vdGF0aW9uXSBvZiBhbm5vdGF0aW9uU3RvcmFnZSkgewogICAgICAgICAgaWYgKCFrZXkuc3RhcnRzV2l0aChBbm5vdGF0aW9uRWRpdG9yUHJlZml4KSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmIChhbm5vdGF0aW9uLmJpdG1hcCAmJiBtaXNzaW5nQml0bWFwcy5oYXMoYW5ub3RhdGlvbi5iaXRtYXBJZCkpIHsKICAgICAgICAgICAgYW5ub3RhdGlvbldpdGhCaXRtYXBzLnB1c2goYW5ub3RhdGlvbik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGltYWdlUHJvbWlzZXMgPSBBbm5vdGF0aW9uRmFjdG9yeS5nZW5lcmF0ZUltYWdlcyhhbm5vdGF0aW9uV2l0aEJpdG1hcHMsIHRoaXMueHJlZiwgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpOwogICAgICB9IGVsc2UgewogICAgICAgIGltYWdlUHJvbWlzZXMgPSBBbm5vdGF0aW9uRmFjdG9yeS5nZW5lcmF0ZUltYWdlcyhuZXdBbm5vdHMsIHRoaXMueHJlZiwgaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpOwogICAgICB9CiAgICAgIGRlbGV0ZWRBbm5vdGF0aW9ucyA9IG5ldyBSZWZTZXQoKTsKICAgICAgbmV3QW5ub3RhdGlvbnNQcm9taXNlID0gUHJvbWlzZS5hbGwoW2Fubm90YXRpb25HbG9iYWxzUHJvbWlzZSwgdGhpcy4jcmVwbGFjZUlkQnlSZWYobmV3QW5ub3RzLCBkZWxldGVkQW5ub3RhdGlvbnMsIG51bGwpXSkudGhlbigoW2Fubm90YXRpb25HbG9iYWxzXSkgPT4gewogICAgICAgIGlmICghYW5ub3RhdGlvbkdsb2JhbHMpIHsKICAgICAgICAgIHJldHVybiBudWxsOwogICAgICAgIH0KICAgICAgICByZXR1cm4gQW5ub3RhdGlvbkZhY3RvcnkucHJpbnROZXdBbm5vdGF0aW9ucyhhbm5vdGF0aW9uR2xvYmFscywgcGFydGlhbEV2YWx1YXRvciwgdGFzaywgbmV3QW5ub3RzLCBpbWFnZVByb21pc2VzKTsKICAgICAgfSk7CiAgICB9CiAgICBjb25zdCBwYWdlTGlzdFByb21pc2UgPSBQcm9taXNlLmFsbChbY29udGVudFN0cmVhbVByb21pc2UsIHJlc291cmNlc1Byb21pc2VdKS50aGVuKGFzeW5jIChbY29udGVudFN0cmVhbV0pID0+IHsKICAgICAgY29uc3QgcmVzb3VyY2VzID0gYXdhaXQgdGhpcy4jZ2V0TWVyZ2VkUmVzb3VyY2VzKGNvbnRlbnRTdHJlYW0uZGljdCwgUkVTT1VSQ0VTX0tFWVNfT1BFUkFUT1JfTElTVCk7CiAgICAgIGNvbnN0IG9wTGlzdCA9IG5ldyBPcGVyYXRvckxpc3QoaW50ZW50LCBzaW5rKTsKICAgICAgaGFuZGxlci5zZW5kKCJTdGFydFJlbmRlclBhZ2UiLCB7CiAgICAgICAgdHJhbnNwYXJlbmN5OiBwYXJ0aWFsRXZhbHVhdG9yLmhhc0JsZW5kTW9kZXMocmVzb3VyY2VzLCB0aGlzLm5vbkJsZW5kTW9kZXNTZXQpLAogICAgICAgIHBhZ2VJbmRleDogdGhpcy5wYWdlSW5kZXgsCiAgICAgICAgY2FjaGVLZXkKICAgICAgfSk7CiAgICAgIGF3YWl0IHBhcnRpYWxFdmFsdWF0b3IuZ2V0T3BlcmF0b3JMaXN0KHsKICAgICAgICBzdHJlYW06IGNvbnRlbnRTdHJlYW0sCiAgICAgICAgdGFzaywKICAgICAgICByZXNvdXJjZXMsCiAgICAgICAgb3BlcmF0b3JMaXN0OiBvcExpc3QKICAgICAgfSk7CiAgICAgIHJldHVybiBvcExpc3Q7CiAgICB9KTsKICAgIGxldCBbcGFnZU9wTGlzdCwgYW5ub3RhdGlvbnMsIG5ld0Fubm90YXRpb25zXSA9IGF3YWl0IFByb21pc2UuYWxsKFtwYWdlTGlzdFByb21pc2UsIHRoaXMuX3BhcnNlZEFubm90YXRpb25zLCBuZXdBbm5vdGF0aW9uc1Byb21pc2VdKTsKICAgIGlmIChuZXdBbm5vdGF0aW9ucykgewogICAgICBhbm5vdGF0aW9ucyA9IGFubm90YXRpb25zLmZpbHRlcihhID0+ICEoYS5yZWYgJiYgZGVsZXRlZEFubm90YXRpb25zLmhhcyhhLnJlZikpKTsKICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gbmV3QW5ub3RhdGlvbnMubGVuZ3RoOyBpIDwgaWk7IGkrKykgewogICAgICAgIGNvbnN0IG5ld0Fubm90YXRpb24gPSBuZXdBbm5vdGF0aW9uc1tpXTsKICAgICAgICBpZiAobmV3QW5ub3RhdGlvbi5yZWZUb1JlcGxhY2UpIHsKICAgICAgICAgIGNvbnN0IGogPSBhbm5vdGF0aW9ucy5maW5kSW5kZXgoYSA9PiBhLnJlZiAmJiBpc1JlZnNFcXVhbChhLnJlZiwgbmV3QW5ub3RhdGlvbi5yZWZUb1JlcGxhY2UpKTsKICAgICAgICAgIGlmIChqID49IDApIHsKICAgICAgICAgICAgYW5ub3RhdGlvbnMuc3BsaWNlKGosIDEsIG5ld0Fubm90YXRpb24pOwogICAgICAgICAgICBuZXdBbm5vdGF0aW9ucy5zcGxpY2UoaS0tLCAxKTsKICAgICAgICAgICAgaWktLTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgYW5ub3RhdGlvbnMgPSBhbm5vdGF0aW9ucy5jb25jYXQobmV3QW5ub3RhdGlvbnMpOwogICAgfQogICAgaWYgKGFubm90YXRpb25zLmxlbmd0aCA9PT0gMCB8fCBpbnRlbnQgJiBSZW5kZXJpbmdJbnRlbnRGbGFnLkFOTk9UQVRJT05TX0RJU0FCTEUpIHsKICAgICAgcGFnZU9wTGlzdC5mbHVzaCh0cnVlKTsKICAgICAgcmV0dXJuIHsKICAgICAgICBsZW5ndGg6IHBhZ2VPcExpc3QudG90YWxMZW5ndGgKICAgICAgfTsKICAgIH0KICAgIGNvbnN0IHJlbmRlckZvcm1zID0gISEoaW50ZW50ICYgUmVuZGVyaW5nSW50ZW50RmxhZy5BTk5PVEFUSU9OU19GT1JNUyksCiAgICAgIGlzRWRpdGluZyA9ICEhKGludGVudCAmIFJlbmRlcmluZ0ludGVudEZsYWcuSVNfRURJVElORyksCiAgICAgIGludGVudEFueSA9ICEhKGludGVudCAmIFJlbmRlcmluZ0ludGVudEZsYWcuQU5ZKSwKICAgICAgaW50ZW50RGlzcGxheSA9ICEhKGludGVudCAmIFJlbmRlcmluZ0ludGVudEZsYWcuRElTUExBWSksCiAgICAgIGludGVudFByaW50ID0gISEoaW50ZW50ICYgUmVuZGVyaW5nSW50ZW50RmxhZy5QUklOVCk7CiAgICBjb25zdCBvcExpc3RQcm9taXNlcyA9IFtdOwogICAgZm9yIChjb25zdCBhbm5vdGF0aW9uIG9mIGFubm90YXRpb25zKSB7CiAgICAgIGlmIChpbnRlbnRBbnkgfHwgaW50ZW50RGlzcGxheSAmJiBhbm5vdGF0aW9uLm11c3RCZVZpZXdlZChhbm5vdGF0aW9uU3RvcmFnZSwgcmVuZGVyRm9ybXMpICYmIGFubm90YXRpb24ubXVzdEJlVmlld2VkV2hlbkVkaXRpbmcoaXNFZGl0aW5nLCBtb2RpZmllZElkcykgfHwgaW50ZW50UHJpbnQgJiYgYW5ub3RhdGlvbi5tdXN0QmVQcmludGVkKGFubm90YXRpb25TdG9yYWdlKSkgewogICAgICAgIG9wTGlzdFByb21pc2VzLnB1c2goYW5ub3RhdGlvbi5nZXRPcGVyYXRvckxpc3QocGFydGlhbEV2YWx1YXRvciwgdGFzaywgaW50ZW50LCBhbm5vdGF0aW9uU3RvcmFnZSkuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgd2FybigiZ2V0T3BlcmF0b3JMaXN0IC0gaWdub3JpbmcgYW5ub3RhdGlvbiBkYXRhIGR1cmluZyAiICsgYCIke3Rhc2submFtZX0iIHRhc2s6ICIke3JlYXNvbn0iLmApOwogICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgb3BMaXN0OiBudWxsLAogICAgICAgICAgICBzZXBhcmF0ZUZvcm06IGZhbHNlLAogICAgICAgICAgICBzZXBhcmF0ZUNhbnZhczogZmFsc2UKICAgICAgICAgIH07CiAgICAgICAgfSkpOwogICAgICB9CiAgICB9CiAgICBjb25zdCBvcExpc3RzID0gYXdhaXQgUHJvbWlzZS5hbGwob3BMaXN0UHJvbWlzZXMpOwogICAgbGV0IGZvcm0gPSBmYWxzZSwKICAgICAgY2FudmFzID0gZmFsc2U7CiAgICBmb3IgKGNvbnN0IHsKICAgICAgb3BMaXN0LAogICAgICBzZXBhcmF0ZUZvcm0sCiAgICAgIHNlcGFyYXRlQ2FudmFzCiAgICB9IG9mIG9wTGlzdHMpIHsKICAgICAgcGFnZU9wTGlzdC5hZGRPcExpc3Qob3BMaXN0KTsKICAgICAgZm9ybSB8fD0gc2VwYXJhdGVGb3JtOwogICAgICBjYW52YXMgfHw9IHNlcGFyYXRlQ2FudmFzOwogICAgfQogICAgcGFnZU9wTGlzdC5mbHVzaCh0cnVlLCB7CiAgICAgIGZvcm0sCiAgICAgIGNhbnZhcwogICAgfSk7CiAgICByZXR1cm4gewogICAgICBsZW5ndGg6IHBhZ2VPcExpc3QudG90YWxMZW5ndGgKICAgIH07CiAgfQogIGFzeW5jIGV4dHJhY3RUZXh0Q29udGVudCh7CiAgICBoYW5kbGVyLAogICAgdGFzaywKICAgIGluY2x1ZGVNYXJrZWRDb250ZW50LAogICAgZGlzYWJsZU5vcm1hbGl6YXRpb24sCiAgICBzaW5rLAogICAgaW50ZXJzZWN0b3IgPSBudWxsCiAgfSkgewogICAgY29uc3QgY29udGVudFN0cmVhbVByb21pc2UgPSB0aGlzLmdldENvbnRlbnRTdHJlYW0oKTsKICAgIGNvbnN0IHJlc291cmNlc1Byb21pc2UgPSB0aGlzLmxvYWRSZXNvdXJjZXMoUkVTT1VSQ0VTX0tFWVNfVEVYVF9DT05URU5UKTsKICAgIGNvbnN0IGxhbmdQcm9taXNlID0gdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImxhbmciKTsKICAgIGNvbnN0IFtjb250ZW50U3RyZWFtLCwgbGFuZ10gPSBhd2FpdCBQcm9taXNlLmFsbChbY29udGVudFN0cmVhbVByb21pc2UsIHJlc291cmNlc1Byb21pc2UsIGxhbmdQcm9taXNlXSk7CiAgICBjb25zdCByZXNvdXJjZXMgPSBhd2FpdCB0aGlzLiNnZXRNZXJnZWRSZXNvdXJjZXMoY29udGVudFN0cmVhbS5kaWN0LCBSRVNPVVJDRVNfS0VZU19URVhUX0NPTlRFTlQpOwogICAgY29uc3QgcGFydGlhbEV2YWx1YXRvciA9IHRoaXMuI2NyZWF0ZVBhcnRpYWxFdmFsdWF0b3IoaGFuZGxlcik7CiAgICByZXR1cm4gcGFydGlhbEV2YWx1YXRvci5nZXRUZXh0Q29udGVudCh7CiAgICAgIHN0cmVhbTogY29udGVudFN0cmVhbSwKICAgICAgdGFzaywKICAgICAgcmVzb3VyY2VzLAogICAgICBpbmNsdWRlTWFya2VkQ29udGVudCwKICAgICAgZGlzYWJsZU5vcm1hbGl6YXRpb24sCiAgICAgIHNpbmssCiAgICAgIHZpZXdCb3g6IHRoaXMudmlldywKICAgICAgbGFuZywKICAgICAgaW50ZXJzZWN0b3IKICAgIH0pOwogIH0KICBhc3luYyBnZXRTdHJ1Y3RUcmVlKCkgewogICAgY29uc3Qgc3RydWN0VHJlZVJvb3QgPSBhd2FpdCB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygic3RydWN0VHJlZVJvb3QiKTsKICAgIGlmICghc3RydWN0VHJlZVJvb3QpIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBhd2FpdCB0aGlzLl9wYXJzZWRBbm5vdGF0aW9uczsKICAgIHRyeSB7CiAgICAgIGNvbnN0IHN0cnVjdFRyZWUgPSBhd2FpdCB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlKHRoaXMsICJfcGFyc2VTdHJ1Y3RUcmVlIiwgW3N0cnVjdFRyZWVSb290XSk7CiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlKHN0cnVjdFRyZWUsICJzZXJpYWxpemFibGUiKTsKICAgICAgcmV0dXJuIGRhdGE7CiAgICB9IGNhdGNoIChleCkgewogICAgICB3YXJuKGBnZXRTdHJ1Y3RUcmVlOiAiJHtleH0iLmApOwogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICB9CiAgX3BhcnNlU3RydWN0VHJlZShzdHJ1Y3RUcmVlUm9vdCkgewogICAgY29uc3QgdHJlZSA9IG5ldyBTdHJ1Y3RUcmVlUGFnZShzdHJ1Y3RUcmVlUm9vdCwgdGhpcy5wYWdlRGljdCk7CiAgICB0cmVlLnBhcnNlKHRoaXMucmVmKTsKICAgIHJldHVybiB0cmVlOwogIH0KICBhc3luYyBnZXRBbm5vdGF0aW9uc0RhdGEoaGFuZGxlciwgdGFzaywgaW50ZW50KSB7CiAgICBjb25zdCBhbm5vdGF0aW9ucyA9IGF3YWl0IHRoaXMuX3BhcnNlZEFubm90YXRpb25zOwogICAgaWYgKGFubm90YXRpb25zLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gYW5ub3RhdGlvbnM7CiAgICB9CiAgICBjb25zdCBhbm5vdGF0aW9uc0RhdGEgPSBbXSwKICAgICAgdGV4dENvbnRlbnRQcm9taXNlcyA9IFtdOwogICAgbGV0IHBhcnRpYWxFdmFsdWF0b3I7CiAgICBjb25zdCBpbnRlbnRBbnkgPSAhIShpbnRlbnQgJiBSZW5kZXJpbmdJbnRlbnRGbGFnLkFOWSksCiAgICAgIGludGVudERpc3BsYXkgPSAhIShpbnRlbnQgJiBSZW5kZXJpbmdJbnRlbnRGbGFnLkRJU1BMQVkpLAogICAgICBpbnRlbnRQcmludCA9ICEhKGludGVudCAmIFJlbmRlcmluZ0ludGVudEZsYWcuUFJJTlQpOwogICAgY29uc3QgaGlnaGxpZ2h0ZWRBbm5vdGF0aW9ucyA9IFtdOwogICAgZm9yIChjb25zdCBhbm5vdGF0aW9uIG9mIGFubm90YXRpb25zKSB7CiAgICAgIGNvbnN0IGlzVmlzaWJsZSA9IGludGVudEFueSB8fCBpbnRlbnREaXNwbGF5ICYmIGFubm90YXRpb24udmlld2FibGU7CiAgICAgIGlmIChpc1Zpc2libGUgfHwgaW50ZW50UHJpbnQgJiYgYW5ub3RhdGlvbi5wcmludGFibGUpIHsKICAgICAgICBhbm5vdGF0aW9uc0RhdGEucHVzaChhbm5vdGF0aW9uLmRhdGEpOwogICAgICB9CiAgICAgIGlmIChhbm5vdGF0aW9uLmhhc1RleHRDb250ZW50ICYmIGlzVmlzaWJsZSkgewogICAgICAgIHBhcnRpYWxFdmFsdWF0b3IgPz89IHRoaXMuI2NyZWF0ZVBhcnRpYWxFdmFsdWF0b3IoaGFuZGxlcik7CiAgICAgICAgdGV4dENvbnRlbnRQcm9taXNlcy5wdXNoKGFubm90YXRpb24uZXh0cmFjdFRleHRDb250ZW50KHBhcnRpYWxFdmFsdWF0b3IsIHRhc2ssIFstSW5maW5pdHksIC1JbmZpbml0eSwgSW5maW5pdHksIEluZmluaXR5XSkuY2F0Y2goZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgd2FybihgZ2V0QW5ub3RhdGlvbnNEYXRhIC0gaWdub3JpbmcgdGV4dENvbnRlbnQgZHVyaW5nICIke3Rhc2submFtZX0iIHRhc2s6ICIke3JlYXNvbn0iLmApOwogICAgICAgIH0pKTsKICAgICAgfSBlbHNlIGlmIChhbm5vdGF0aW9uLm92ZXJsYXlzVGV4dENvbnRlbnQgJiYgaXNWaXNpYmxlKSB7CiAgICAgICAgaGlnaGxpZ2h0ZWRBbm5vdGF0aW9ucy5wdXNoKGFubm90YXRpb24pOwogICAgICB9CiAgICB9CiAgICBpZiAoaGlnaGxpZ2h0ZWRBbm5vdGF0aW9ucy5sZW5ndGggPiAwKSB7CiAgICAgIGNvbnN0IGludGVyc2VjdG9yID0gbmV3IEludGVyc2VjdG9yKGhpZ2hsaWdodGVkQW5ub3RhdGlvbnMpOwogICAgICB0ZXh0Q29udGVudFByb21pc2VzLnB1c2godGhpcy5leHRyYWN0VGV4dENvbnRlbnQoewogICAgICAgIGhhbmRsZXIsCiAgICAgICAgdGFzaywKICAgICAgICBpbmNsdWRlTWFya2VkQ29udGVudDogZmFsc2UsCiAgICAgICAgZGlzYWJsZU5vcm1hbGl6YXRpb246IGZhbHNlLAogICAgICAgIHNpbms6IG51bGwsCiAgICAgICAgdmlld0JveDogdGhpcy52aWV3LAogICAgICAgIGxhbmc6IG51bGwsCiAgICAgICAgaW50ZXJzZWN0b3IKICAgICAgfSkudGhlbigoKSA9PiB7CiAgICAgICAgaW50ZXJzZWN0b3Iuc2V0VGV4dCgpOwogICAgICB9KSk7CiAgICB9CiAgICBhd2FpdCBQcm9taXNlLmFsbCh0ZXh0Q29udGVudFByb21pc2VzKTsKICAgIHJldHVybiBhbm5vdGF0aW9uc0RhdGE7CiAgfQogIGdldCBhbm5vdGF0aW9ucygpIHsKICAgIGNvbnN0IGFubm90cyA9IHRoaXMuI2dldEluaGVyaXRhYmxlUHJvcGVydHkoIkFubm90cyIpOwogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiYW5ub3RhdGlvbnMiLCBBcnJheS5pc0FycmF5KGFubm90cykgPyBhbm5vdHMgOiBbXSk7CiAgfQogIGdldCBfcGFyc2VkQW5ub3RhdGlvbnMoKSB7CiAgICBjb25zdCBwcm9taXNlID0gdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZSh0aGlzLCAiYW5ub3RhdGlvbnMiKS50aGVuKGFzeW5jIGFubm90cyA9PiB7CiAgICAgIGlmIChhbm5vdHMubGVuZ3RoID09PSAwKSB7CiAgICAgICAgcmV0dXJuIGFubm90czsKICAgICAgfQogICAgICBjb25zdCBbYW5ub3RhdGlvbkdsb2JhbHMsIGZpZWxkT2JqZWN0c10gPSBhd2FpdCBQcm9taXNlLmFsbChbdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZURvYygiYW5ub3RhdGlvbkdsb2JhbHMiKSwgdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZURvYygiZmllbGRPYmplY3RzIildKTsKICAgICAgaWYgKCFhbm5vdGF0aW9uR2xvYmFscykgewogICAgICAgIHJldHVybiBbXTsKICAgICAgfQogICAgICBjb25zdCBvcnBoYW5GaWVsZHMgPSBmaWVsZE9iamVjdHM/Lm9ycGhhbkZpZWxkczsKICAgICAgY29uc3QgYW5ub3RhdGlvblByb21pc2VzID0gW107CiAgICAgIGZvciAoY29uc3QgYW5ub3RhdGlvblJlZiBvZiBhbm5vdHMpIHsKICAgICAgICBhbm5vdGF0aW9uUHJvbWlzZXMucHVzaChBbm5vdGF0aW9uRmFjdG9yeS5jcmVhdGUodGhpcy54cmVmLCBhbm5vdGF0aW9uUmVmLCBhbm5vdGF0aW9uR2xvYmFscywgdGhpcy5fbG9jYWxJZEZhY3RvcnksIGZhbHNlLCBvcnBoYW5GaWVsZHMsIG51bGwsIHRoaXMucmVmKS5jYXRjaChmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgICB3YXJuKGBfcGFyc2VkQW5ub3RhdGlvbnM6ICIke3JlYXNvbn0iLmApOwogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfSkpOwogICAgICB9CiAgICAgIGNvbnN0IHNvcnRlZEFubm90YXRpb25zID0gW107CiAgICAgIGxldCBwb3B1cEFubm90YXRpb25zLCB3aWRnZXRBbm5vdGF0aW9uczsKICAgICAgZm9yIChjb25zdCBhbm5vdGF0aW9uIG9mIGF3YWl0IFByb21pc2UuYWxsKGFubm90YXRpb25Qcm9taXNlcykpIHsKICAgICAgICBpZiAoIWFubm90YXRpb24pIHsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBpZiAoYW5ub3RhdGlvbiBpbnN0YW5jZW9mIFdpZGdldEFubm90YXRpb24pIHsKICAgICAgICAgICh3aWRnZXRBbm5vdGF0aW9ucyB8fD0gW10pLnB1c2goYW5ub3RhdGlvbik7CiAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgaWYgKGFubm90YXRpb24gaW5zdGFuY2VvZiBQb3B1cEFubm90YXRpb24pIHsKICAgICAgICAgIChwb3B1cEFubm90YXRpb25zIHx8PSBbXSkucHVzaChhbm5vdGF0aW9uKTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBzb3J0ZWRBbm5vdGF0aW9ucy5wdXNoKGFubm90YXRpb24pOwogICAgICB9CiAgICAgIGlmICh3aWRnZXRBbm5vdGF0aW9ucykgewogICAgICAgIHNvcnRlZEFubm90YXRpb25zLnB1c2goLi4ud2lkZ2V0QW5ub3RhdGlvbnMpOwogICAgICB9CiAgICAgIGlmIChwb3B1cEFubm90YXRpb25zKSB7CiAgICAgICAgc29ydGVkQW5ub3RhdGlvbnMucHVzaCguLi5wb3B1cEFubm90YXRpb25zKTsKICAgICAgfQogICAgICByZXR1cm4gc29ydGVkQW5ub3RhdGlvbnM7CiAgICB9KTsKICAgIHRoaXMuI2FyZUFubm90YXRpb25zQ2FjaGVkID0gdHJ1ZTsKICAgIHJldHVybiBzaGFkb3codGhpcywgIl9wYXJzZWRBbm5vdGF0aW9ucyIsIHByb21pc2UpOwogIH0KICBnZXQganNBY3Rpb25zKCkgewogICAgY29uc3QgYWN0aW9ucyA9IGNvbGxlY3RBY3Rpb25zKHRoaXMueHJlZiwgdGhpcy5wYWdlRGljdCwgUGFnZUFjdGlvbkV2ZW50VHlwZSk7CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJqc0FjdGlvbnMiLCBhY3Rpb25zKTsKICB9CiAgYXN5bmMgY29sbGVjdEFubm90YXRpb25zQnlUeXBlKGhhbmRsZXIsIHRhc2ssIHR5cGVzLCBwcm9taXNlcywgYW5ub3RhdGlvbkdsb2JhbHMpIHsKICAgIGNvbnN0IHsKICAgICAgcGFnZUluZGV4CiAgICB9ID0gdGhpczsKICAgIGlmICh0aGlzLiNhcmVBbm5vdGF0aW9uc0NhY2hlZCkgewogICAgICBjb25zdCBjYWNoZWRBbm5vdGF0aW9ucyA9IGF3YWl0IHRoaXMuX3BhcnNlZEFubm90YXRpb25zOwogICAgICBmb3IgKGNvbnN0IHsKICAgICAgICBkYXRhCiAgICAgIH0gb2YgY2FjaGVkQW5ub3RhdGlvbnMpIHsKICAgICAgICBpZiAoIXR5cGVzIHx8IHR5cGVzLmhhcyhkYXRhLmFubm90YXRpb25UeXBlKSkgewogICAgICAgICAgZGF0YS5wYWdlSW5kZXggPSBwYWdlSW5kZXg7CiAgICAgICAgICBwcm9taXNlcy5wdXNoKFByb21pc2UucmVzb2x2ZShkYXRhKSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIHJldHVybjsKICAgIH0KICAgIGNvbnN0IGFubm90cyA9IGF3YWl0IHRoaXMucGRmTWFuYWdlci5lbnN1cmUodGhpcywgImFubm90YXRpb25zIik7CiAgICBmb3IgKGNvbnN0IGFubm90YXRpb25SZWYgb2YgYW5ub3RzKSB7CiAgICAgIHByb21pc2VzLnB1c2goQW5ub3RhdGlvbkZhY3RvcnkuY3JlYXRlKHRoaXMueHJlZiwgYW5ub3RhdGlvblJlZiwgYW5ub3RhdGlvbkdsb2JhbHMsIHRoaXMuX2xvY2FsSWRGYWN0b3J5LCBmYWxzZSwgbnVsbCwgdHlwZXMsIHRoaXMucmVmKS50aGVuKGFzeW5jIGFubm90YXRpb24gPT4gewogICAgICAgIGlmICghYW5ub3RhdGlvbikgewogICAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgICAgfQogICAgICAgIGFubm90YXRpb24uZGF0YS5wYWdlSW5kZXggPSBwYWdlSW5kZXg7CiAgICAgICAgaWYgKGFubm90YXRpb24uaGFzVGV4dENvbnRlbnQgJiYgYW5ub3RhdGlvbi52aWV3YWJsZSkgewogICAgICAgICAgY29uc3QgcGFydGlhbEV2YWx1YXRvciA9IHRoaXMuI2NyZWF0ZVBhcnRpYWxFdmFsdWF0b3IoaGFuZGxlcik7CiAgICAgICAgICBhd2FpdCBhbm5vdGF0aW9uLmV4dHJhY3RUZXh0Q29udGVudChwYXJ0aWFsRXZhbHVhdG9yLCB0YXNrLCBbLUluZmluaXR5LCAtSW5maW5pdHksIEluZmluaXR5LCBJbmZpbml0eV0pOwogICAgICAgIH0KICAgICAgICByZXR1cm4gYW5ub3RhdGlvbi5kYXRhOwogICAgICB9KS5jYXRjaChmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgd2FybihgY29sbGVjdEFubm90YXRpb25zQnlUeXBlOiAiJHtyZWFzb259Ii5gKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfSkpOwogICAgfQogIH0KfQpjb25zdCBQREZfSEVBREVSX1NJR05BVFVSRSA9IG5ldyBVaW50OEFycmF5KFsweDI1LCAweDUwLCAweDQ0LCAweDQ2LCAweDJkXSk7CmNvbnN0IFNUQVJUWFJFRl9TSUdOQVRVUkUgPSBuZXcgVWludDhBcnJheShbMHg3MywgMHg3NCwgMHg2MSwgMHg3MiwgMHg3NCwgMHg3OCwgMHg3MiwgMHg2NSwgMHg2Nl0pOwpjb25zdCBFTkRPQkpfU0lHTkFUVVJFID0gbmV3IFVpbnQ4QXJyYXkoWzB4NjUsIDB4NmUsIDB4NjQsIDB4NmYsIDB4NjIsIDB4NmFdKTsKZnVuY3Rpb24gZmluZChzdHJlYW0sIHNpZ25hdHVyZSwgbGltaXQgPSAxMDI0LCBiYWNrd2FyZHMgPSBmYWxzZSkgewogIGNvbnN0IHNpZ25hdHVyZUxlbmd0aCA9IHNpZ25hdHVyZS5sZW5ndGg7CiAgY29uc3Qgc2NhbkJ5dGVzID0gc3RyZWFtLnBlZWtCeXRlcyhsaW1pdCk7CiAgY29uc3Qgc2Nhbkxlbmd0aCA9IHNjYW5CeXRlcy5sZW5ndGggLSBzaWduYXR1cmVMZW5ndGg7CiAgaWYgKHNjYW5MZW5ndGggPD0gMCkgewogICAgcmV0dXJuIGZhbHNlOwogIH0KICBpZiAoYmFja3dhcmRzKSB7CiAgICBjb25zdCBzaWduYXR1cmVFbmQgPSBzaWduYXR1cmVMZW5ndGggLSAxOwogICAgbGV0IHBvcyA9IHNjYW5CeXRlcy5sZW5ndGggLSAxOwogICAgd2hpbGUgKHBvcyA+PSBzaWduYXR1cmVFbmQpIHsKICAgICAgbGV0IGogPSAwOwogICAgICB3aGlsZSAoaiA8IHNpZ25hdHVyZUxlbmd0aCAmJiBzY2FuQnl0ZXNbcG9zIC0gal0gPT09IHNpZ25hdHVyZVtzaWduYXR1cmVFbmQgLSBqXSkgewogICAgICAgIGorKzsKICAgICAgfQogICAgICBpZiAoaiA+PSBzaWduYXR1cmVMZW5ndGgpIHsKICAgICAgICBzdHJlYW0ucG9zICs9IHBvcyAtIHNpZ25hdHVyZUVuZDsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBwb3MtLTsKICAgIH0KICB9IGVsc2UgewogICAgbGV0IHBvcyA9IDA7CiAgICB3aGlsZSAocG9zIDw9IHNjYW5MZW5ndGgpIHsKICAgICAgbGV0IGogPSAwOwogICAgICB3aGlsZSAoaiA8IHNpZ25hdHVyZUxlbmd0aCAmJiBzY2FuQnl0ZXNbcG9zICsgal0gPT09IHNpZ25hdHVyZVtqXSkgewogICAgICAgIGorKzsKICAgICAgfQogICAgICBpZiAoaiA+PSBzaWduYXR1cmVMZW5ndGgpIHsKICAgICAgICBzdHJlYW0ucG9zICs9IHBvczsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgICBwb3MrKzsKICAgIH0KICB9CiAgcmV0dXJuIGZhbHNlOwp9CmNsYXNzIFBERkRvY3VtZW50IHsKICAjcGFnZVByb21pc2VzID0gbmV3IE1hcCgpOwogICN2ZXJzaW9uID0gbnVsbDsKICBjb25zdHJ1Y3RvcihwZGZNYW5hZ2VyLCBzdHJlYW0pIHsKICAgIGlmIChzdHJlYW0ubGVuZ3RoIDw9IDApIHsKICAgICAgdGhyb3cgbmV3IEludmFsaWRQREZFeGNlcHRpb24oIlRoZSBQREYgZmlsZSBpcyBlbXB0eSwgaS5lLiBpdHMgc2l6ZSBpcyB6ZXJvIGJ5dGVzLiIpOwogICAgfQogICAgdGhpcy5wZGZNYW5hZ2VyID0gcGRmTWFuYWdlcjsKICAgIHRoaXMuc3RyZWFtID0gc3RyZWFtOwogICAgdGhpcy54cmVmID0gbmV3IFhSZWYoc3RyZWFtLCBwZGZNYW5hZ2VyKTsKICAgIGNvbnN0IGlkQ291bnRlcnMgPSB7CiAgICAgIGZvbnQ6IDAKICAgIH07CiAgICB0aGlzLl9nbG9iYWxJZEZhY3RvcnkgPSBjbGFzcyB7CiAgICAgIHN0YXRpYyBnZXREb2NJZCgpIHsKICAgICAgICByZXR1cm4gYGdfJHtwZGZNYW5hZ2VyLmRvY0lkfWA7CiAgICAgIH0KICAgICAgc3RhdGljIGNyZWF0ZUZvbnRJZCgpIHsKICAgICAgICByZXR1cm4gYGYkeysraWRDb3VudGVycy5mb250fWA7CiAgICAgIH0KICAgICAgc3RhdGljIGNyZWF0ZU9iaklkKCkgewogICAgICAgIHVucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYGNyZWF0ZU9iaklkYCBjYWxsZWQuIik7CiAgICAgIH0KICAgICAgc3RhdGljIGdldFBhZ2VPYmpJZCgpIHsKICAgICAgICB1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGBnZXRQYWdlT2JqSWRgIGNhbGxlZC4iKTsKICAgICAgfQogICAgfTsKICB9CiAgcGFyc2UocmVjb3ZlcnlNb2RlKSB7CiAgICB0aGlzLnhyZWYucGFyc2UocmVjb3ZlcnlNb2RlKTsKICAgIHRoaXMuY2F0YWxvZyA9IG5ldyBDYXRhbG9nKHRoaXMucGRmTWFuYWdlciwgdGhpcy54cmVmKTsKICB9CiAgZ2V0IGxpbmVhcml6YXRpb24oKSB7CiAgICBsZXQgbGluZWFyaXphdGlvbiA9IG51bGw7CiAgICB0cnkgewogICAgICBsaW5lYXJpemF0aW9uID0gTGluZWFyaXphdGlvbi5jcmVhdGUodGhpcy5zdHJlYW0pOwogICAgfSBjYXRjaCAoZXJyKSB7CiAgICAgIGlmIChlcnIgaW5zdGFuY2VvZiBNaXNzaW5nRGF0YUV4Y2VwdGlvbikgewogICAgICAgIHRocm93IGVycjsKICAgICAgfQogICAgICBpbmZvKGVycik7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJsaW5lYXJpemF0aW9uIiwgbGluZWFyaXphdGlvbik7CiAgfQogIGdldCBzdGFydFhSZWYoKSB7CiAgICBjb25zdCBzdHJlYW0gPSB0aGlzLnN0cmVhbTsKICAgIGxldCBzdGFydFhSZWYgPSAwOwogICAgaWYgKHRoaXMubGluZWFyaXphdGlvbikgewogICAgICBzdHJlYW0ucmVzZXQoKTsKICAgICAgaWYgKGZpbmQoc3RyZWFtLCBFTkRPQkpfU0lHTkFUVVJFKSkgewogICAgICAgIHN0cmVhbS5za2lwKDYpOwogICAgICAgIGxldCBjaCA9IHN0cmVhbS5wZWVrQnl0ZSgpOwogICAgICAgIHdoaWxlIChpc1doaXRlU3BhY2UoY2gpKSB7CiAgICAgICAgICBzdHJlYW0ucG9zKys7CiAgICAgICAgICBjaCA9IHN0cmVhbS5wZWVrQnl0ZSgpOwogICAgICAgIH0KICAgICAgICBzdGFydFhSZWYgPSBzdHJlYW0ucG9zIC0gc3RyZWFtLnN0YXJ0OwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBjb25zdCBzdGVwID0gMTAyNDsKICAgICAgY29uc3Qgc3RhcnRYUmVmTGVuZ3RoID0gU1RBUlRYUkVGX1NJR05BVFVSRS5sZW5ndGg7CiAgICAgIGxldCBmb3VuZCA9IGZhbHNlLAogICAgICAgIHBvcyA9IHN0cmVhbS5lbmQ7CiAgICAgIHdoaWxlICghZm91bmQgJiYgcG9zID4gMCkgewogICAgICAgIHBvcyAtPSBzdGVwIC0gc3RhcnRYUmVmTGVuZ3RoOwogICAgICAgIGlmIChwb3MgPCAwKSB7CiAgICAgICAgICBwb3MgPSAwOwogICAgICAgIH0KICAgICAgICBzdHJlYW0ucG9zID0gcG9zOwogICAgICAgIGZvdW5kID0gZmluZChzdHJlYW0sIFNUQVJUWFJFRl9TSUdOQVRVUkUsIHN0ZXAsIHRydWUpOwogICAgICB9CiAgICAgIGlmIChmb3VuZCkgewogICAgICAgIHN0cmVhbS5za2lwKDkpOwogICAgICAgIGxldCBjaDsKICAgICAgICBkbyB7CiAgICAgICAgICBjaCA9IHN0cmVhbS5nZXRCeXRlKCk7CiAgICAgICAgfSB3aGlsZSAoaXNXaGl0ZVNwYWNlKGNoKSk7CiAgICAgICAgbGV0IHN0ciA9ICIiOwogICAgICAgIHdoaWxlIChjaCA+PSAweDIwICYmIGNoIDw9IDB4MzkpIHsKICAgICAgICAgIHN0ciArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKTsKICAgICAgICAgIGNoID0gc3RyZWFtLmdldEJ5dGUoKTsKICAgICAgICB9CiAgICAgICAgc3RhcnRYUmVmID0gcGFyc2VJbnQoc3RyLCAxMCk7CiAgICAgICAgaWYgKGlzTmFOKHN0YXJ0WFJlZikpIHsKICAgICAgICAgIHN0YXJ0WFJlZiA9IDA7CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJzdGFydFhSZWYiLCBzdGFydFhSZWYpOwogIH0KICBjaGVja0hlYWRlcigpIHsKICAgIGNvbnN0IHN0cmVhbSA9IHRoaXMuc3RyZWFtOwogICAgc3RyZWFtLnJlc2V0KCk7CiAgICBpZiAoIWZpbmQoc3RyZWFtLCBQREZfSEVBREVSX1NJR05BVFVSRSkpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgc3RyZWFtLm1vdmVTdGFydCgpOwogICAgc3RyZWFtLnNraXAoUERGX0hFQURFUl9TSUdOQVRVUkUubGVuZ3RoKTsKICAgIGxldCB2ZXJzaW9uID0gIiIsCiAgICAgIGNoOwogICAgd2hpbGUgKChjaCA9IHN0cmVhbS5nZXRCeXRlKCkpID4gMHgyMCAmJiB2ZXJzaW9uLmxlbmd0aCA8IDcpIHsKICAgICAgdmVyc2lvbiArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoKTsKICAgIH0KICAgIGlmIChQREZfVkVSU0lPTl9SRUdFWFAudGVzdCh2ZXJzaW9uKSkgewogICAgICB0aGlzLiN2ZXJzaW9uID0gdmVyc2lvbjsKICAgIH0gZWxzZSB7CiAgICAgIHdhcm4oYEludmFsaWQgUERGIGhlYWRlciB2ZXJzaW9uOiAke3ZlcnNpb259YCk7CiAgICB9CiAgfQogIHBhcnNlU3RhcnRYUmVmKCkgewogICAgdGhpcy54cmVmLnNldFN0YXJ0WFJlZih0aGlzLnN0YXJ0WFJlZik7CiAgfQogIGdldCBudW1QYWdlcygpIHsKICAgIGxldCBudW0gPSAwOwogICAgaWYgKHRoaXMuY2F0YWxvZy5oYXNBY3R1YWxOdW1QYWdlcykgewogICAgICBudW0gPSB0aGlzLmNhdGFsb2cubnVtUGFnZXM7CiAgICB9IGVsc2UgaWYgKHRoaXMueGZhRmFjdG9yeSkgewogICAgICBudW0gPSB0aGlzLnhmYUZhY3RvcnkuZ2V0TnVtUGFnZXMoKTsKICAgIH0gZWxzZSBpZiAodGhpcy5saW5lYXJpemF0aW9uKSB7CiAgICAgIG51bSA9IHRoaXMubGluZWFyaXphdGlvbi5udW1QYWdlczsKICAgIH0gZWxzZSB7CiAgICAgIG51bSA9IHRoaXMuY2F0YWxvZy5udW1QYWdlczsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgIm51bVBhZ2VzIiwgbnVtKTsKICB9CiAgI2hhc09ubHlEb2N1bWVudFNpZ25hdHVyZXMoZmllbGRzLCByZWN1cnNpb25EZXB0aCA9IDApIHsKICAgIGNvbnN0IFJFQ1VSU0lPTl9MSU1JVCA9IDEwOwogICAgaWYgKCFBcnJheS5pc0FycmF5KGZpZWxkcykpIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogICAgcmV0dXJuIGZpZWxkcy5ldmVyeShmaWVsZCA9PiB7CiAgICAgIGZpZWxkID0gdGhpcy54cmVmLmZldGNoSWZSZWYoZmllbGQpOwogICAgICBpZiAoIShmaWVsZCBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICB9CiAgICAgIGlmIChmaWVsZC5oYXMoIktpZHMiKSkgewogICAgICAgIGlmICgrK3JlY3Vyc2lvbkRlcHRoID4gUkVDVVJTSU9OX0xJTUlUKSB7CiAgICAgICAgICB3YXJuKCIjaGFzT25seURvY3VtZW50U2lnbmF0dXJlczogbWF4aW11bSByZWN1cnNpb24gZGVwdGggcmVhY2hlZCIpOwogICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgIH0KICAgICAgICByZXR1cm4gdGhpcy4jaGFzT25seURvY3VtZW50U2lnbmF0dXJlcyhmaWVsZC5nZXQoIktpZHMiKSwgcmVjdXJzaW9uRGVwdGgpOwogICAgICB9CiAgICAgIGNvbnN0IGlzU2lnbmF0dXJlID0gaXNOYW1lKGZpZWxkLmdldCgiRlQiKSwgIlNpZyIpOwogICAgICBjb25zdCByZWN0YW5nbGUgPSBmaWVsZC5nZXQoIlJlY3QiKTsKICAgICAgY29uc3QgaXNJbnZpc2libGUgPSBBcnJheS5pc0FycmF5KHJlY3RhbmdsZSkgJiYgcmVjdGFuZ2xlLmV2ZXJ5KHZhbHVlID0+IHZhbHVlID09PSAwKTsKICAgICAgcmV0dXJuIGlzU2lnbmF0dXJlICYmIGlzSW52aXNpYmxlOwogICAgfSk7CiAgfQogICNjb2xsZWN0U2lnbmF0dXJlQ2VydGlmaWNhdGVzKGZpZWxkcywgY29sbGVjdGVkU2lnbmF0dXJlQ2VydGlmaWNhdGVzLCB2aXNpdGVkID0gbmV3IFJlZlNldCgpKSB7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZmllbGRzKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBmb3IgKGxldCBmaWVsZCBvZiBmaWVsZHMpIHsKICAgICAgaWYgKGZpZWxkIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgaWYgKHZpc2l0ZWQuaGFzKGZpZWxkKSkgewogICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIHZpc2l0ZWQucHV0KGZpZWxkKTsKICAgICAgfQogICAgICBmaWVsZCA9IHRoaXMueHJlZi5mZXRjaElmUmVmKGZpZWxkKTsKICAgICAgaWYgKCEoZmllbGQgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGlmIChmaWVsZC5oYXMoIktpZHMiKSkgewogICAgICAgIHRoaXMuI2NvbGxlY3RTaWduYXR1cmVDZXJ0aWZpY2F0ZXMoZmllbGQuZ2V0KCJLaWRzIiksIGNvbGxlY3RlZFNpZ25hdHVyZUNlcnRpZmljYXRlcywgdmlzaXRlZCk7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3QgaXNTaWduYXR1cmUgPSBpc05hbWUoZmllbGQuZ2V0KCJGVCIpLCAiU2lnIik7CiAgICAgIGlmICghaXNTaWduYXR1cmUpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb25zdCB2YWx1ZSA9IGZpZWxkLmdldCgiViIpOwogICAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgY29uc3Qgc3ViRmlsdGVyID0gdmFsdWUuZ2V0KCJTdWJGaWx0ZXIiKTsKICAgICAgaWYgKCEoc3ViRmlsdGVyIGluc3RhbmNlb2YgTmFtZSkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBjb2xsZWN0ZWRTaWduYXR1cmVDZXJ0aWZpY2F0ZXMuYWRkKHN1YkZpbHRlci5uYW1lKTsKICAgIH0KICB9CiAgZ2V0IF94ZmFTdHJlYW1zKCkgewogICAgY29uc3QgewogICAgICBhY3JvRm9ybQogICAgfSA9IHRoaXMuY2F0YWxvZzsKICAgIGlmICghYWNyb0Zvcm0pIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBjb25zdCB4ZmEgPSBhY3JvRm9ybS5nZXQoIlhGQSIpOwogICAgY29uc3QgZW50cmllcyA9IG5ldyBNYXAoWyJ4ZHA6eGRwIiwgInRlbXBsYXRlIiwgImRhdGFzZXRzIiwgImNvbmZpZyIsICJjb25uZWN0aW9uU2V0IiwgImxvY2FsZVNldCIsICJzdHlsZXNoZWV0IiwgIi94ZHA6eGRwIl0ubWFwKGUgPT4gW2UsIG51bGxdKSk7CiAgICBpZiAoeGZhIGluc3RhbmNlb2YgQmFzZVN0cmVhbSAmJiAheGZhLmlzRW1wdHkpIHsKICAgICAgZW50cmllcy5zZXQoInhkcDp4ZHAiLCB4ZmEpOwogICAgICByZXR1cm4gZW50cmllczsKICAgIH0KICAgIGlmICghQXJyYXkuaXNBcnJheSh4ZmEpIHx8IHhmYS5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIG51bGw7CiAgICB9CiAgICBmb3IgKGxldCBpID0gMCwgaWkgPSB4ZmEubGVuZ3RoOyBpIDwgaWk7IGkgKz0gMikgewogICAgICBsZXQgbmFtZTsKICAgICAgaWYgKGkgPT09IDApIHsKICAgICAgICBuYW1lID0gInhkcDp4ZHAiOwogICAgICB9IGVsc2UgaWYgKGkgPT09IGlpIC0gMikgewogICAgICAgIG5hbWUgPSAiL3hkcDp4ZHAiOwogICAgICB9IGVsc2UgewogICAgICAgIG5hbWUgPSB4ZmFbaV07CiAgICAgIH0KICAgICAgaWYgKCFlbnRyaWVzLmhhcyhuYW1lKSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLnhyZWYuZmV0Y2hJZlJlZih4ZmFbaSArIDFdKTsKICAgICAgaWYgKCEoZGF0YSBpbnN0YW5jZW9mIEJhc2VTdHJlYW0pIHx8IGRhdGEuaXNFbXB0eSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIGVudHJpZXMuc2V0KG5hbWUsIGRhdGEpOwogICAgfQogICAgcmV0dXJuIGVudHJpZXM7CiAgfQogIGdldCB4ZmFEYXRhc2V0cygpIHsKICAgIGNvbnN0IHN0cmVhbXMgPSB0aGlzLl94ZmFTdHJlYW1zOwogICAgaWYgKCFzdHJlYW1zKSB7CiAgICAgIHJldHVybiBzaGFkb3codGhpcywgInhmYURhdGFzZXRzIiwgbnVsbCk7CiAgICB9CiAgICBmb3IgKGNvbnN0IGtleSBvZiBbImRhdGFzZXRzIiwgInhkcDp4ZHAiXSkgewogICAgICBjb25zdCBzdHJlYW0gPSBzdHJlYW1zLmdldChrZXkpOwogICAgICBpZiAoIXN0cmVhbSkgewogICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHRyeSB7CiAgICAgICAgY29uc3Qgc3RyID0gc3RyaW5nVG9VVEY4U3RyaW5nKHN0cmVhbS5nZXRTdHJpbmcoKSk7CiAgICAgICAgY29uc3QgZGF0YSA9IHsKICAgICAgICAgIFtrZXldOiBzdHIKICAgICAgICB9OwogICAgICAgIHJldHVybiBzaGFkb3codGhpcywgInhmYURhdGFzZXRzIiwgbmV3IERhdGFzZXRSZWFkZXIoZGF0YSkpOwogICAgICB9IGNhdGNoIHsKICAgICAgICB3YXJuKCJYRkEgLSBJbnZhbGlkIHV0Zi04IHN0cmluZy4iKTsKICAgICAgICBicmVhazsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAieGZhRGF0YXNldHMiLCBudWxsKTsKICB9CiAgZ2V0IHhmYURhdGEoKSB7CiAgICBjb25zdCBzdHJlYW1zID0gdGhpcy5feGZhU3RyZWFtczsKICAgIGlmICghc3RyZWFtcykgewogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICAgIGNvbnN0IGRhdGEgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgZm9yIChjb25zdCBba2V5LCBzdHJlYW1dIG9mIHN0cmVhbXMpIHsKICAgICAgaWYgKCFzdHJlYW0pIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICB0cnkgewogICAgICAgIGRhdGFba2V5XSA9IHN0cmluZ1RvVVRGOFN0cmluZyhzdHJlYW0uZ2V0U3RyaW5nKCkpOwogICAgICB9IGNhdGNoIHsKICAgICAgICB3YXJuKCJYRkEgLSBJbnZhbGlkIHV0Zi04IHN0cmluZy4iKTsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgfQogICAgcmV0dXJuIGRhdGE7CiAgfQogIGdldCB4ZmFGYWN0b3J5KCkgewogICAgbGV0IGRhdGE7CiAgICBpZiAodGhpcy5wZGZNYW5hZ2VyLmVuYWJsZVhmYSAmJiB0aGlzLmNhdGFsb2cubmVlZHNSZW5kZXJpbmcgJiYgdGhpcy5mb3JtSW5mby5oYXNYZmEgJiYgIXRoaXMuZm9ybUluZm8uaGFzQWNyb0Zvcm0pIHsKICAgICAgZGF0YSA9IHRoaXMueGZhRGF0YTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgInhmYUZhY3RvcnkiLCBkYXRhID8gbmV3IFhGQUZhY3RvcnkoZGF0YSkgOiBudWxsKTsKICB9CiAgZ2V0IGlzUHVyZVhmYSgpIHsKICAgIHJldHVybiB0aGlzLnhmYUZhY3RvcnkgPyB0aGlzLnhmYUZhY3RvcnkuaXNWYWxpZCgpIDogZmFsc2U7CiAgfQogIGdldCBodG1sRm9yWGZhKCkgewogICAgcmV0dXJuIHRoaXMueGZhRmFjdG9yeSA/IHRoaXMueGZhRmFjdG9yeS5nZXRQYWdlcygpIDogbnVsbDsKICB9CiAgYXN5bmMgI2xvYWRYZmFJbWFnZXMoKSB7CiAgICBjb25zdCB4ZmFJbWFnZXMgPSBhd2FpdCB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygieGZhSW1hZ2VzIik7CiAgICBpZiAoIXhmYUltYWdlcykgewogICAgICByZXR1cm47CiAgICB9CiAgICB0aGlzLnhmYUZhY3Rvcnkuc2V0SW1hZ2VzKHhmYUltYWdlcyk7CiAgfQogIGFzeW5jICNsb2FkWGZhRm9udHMoaGFuZGxlciwgdGFzaykgewogICAgY29uc3QgYWNyb0Zvcm0gPSBhd2FpdCB0aGlzLnBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiYWNyb0Zvcm0iKTsKICAgIGlmICghYWNyb0Zvcm0pIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgcmVzb3VyY2VzID0gYXdhaXQgYWNyb0Zvcm0uZ2V0QXN5bmMoIkRSIik7CiAgICBpZiAoIShyZXNvdXJjZXMgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBhd2FpdCBPYmplY3RMb2FkZXIubG9hZChyZXNvdXJjZXMsIFsiRm9udCJdLCB0aGlzLnhyZWYpOwogICAgY29uc3QgZm9udFJlcyA9IHJlc291cmNlcy5nZXQoIkZvbnQiKTsKICAgIGlmICghKGZvbnRSZXMgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBjb25zdCBvcHRpb25zID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG51bGwpLCB0aGlzLnBkZk1hbmFnZXIuZXZhbHVhdG9yT3B0aW9ucywgewogICAgICB1c2VTeXN0ZW1Gb250czogZmFsc2UKICAgIH0pOwogICAgY29uc3QgewogICAgICBidWlsdEluQ01hcENhY2hlLAogICAgICBmb250Q2FjaGUsCiAgICAgIHN0YW5kYXJkRm9udERhdGFDYWNoZQogICAgfSA9IHRoaXMuY2F0YWxvZzsKICAgIGNvbnN0IHBhcnRpYWxFdmFsdWF0b3IgPSBuZXcgUGFydGlhbEV2YWx1YXRvcih7CiAgICAgIHhyZWY6IHRoaXMueHJlZiwKICAgICAgaGFuZGxlciwKICAgICAgcGFnZUluZGV4OiAtMSwKICAgICAgaWRGYWN0b3J5OiB0aGlzLl9nbG9iYWxJZEZhY3RvcnksCiAgICAgIGZvbnRDYWNoZSwKICAgICAgYnVpbHRJbkNNYXBDYWNoZSwKICAgICAgc3RhbmRhcmRGb250RGF0YUNhY2hlLAogICAgICBvcHRpb25zCiAgICB9KTsKICAgIGNvbnN0IG9wZXJhdG9yTGlzdCA9IG5ldyBPcGVyYXRvckxpc3QoKTsKICAgIGNvbnN0IHBkZkZvbnRzID0gW107CiAgICBjb25zdCBpbml0aWFsU3RhdGUgPSB7CiAgICAgIGdldCBmb250KCkgewogICAgICAgIHJldHVybiBwZGZGb250cy5hdCgtMSk7CiAgICAgIH0sCiAgICAgIHNldCBmb250KGZvbnQpIHsKICAgICAgICBwZGZGb250cy5wdXNoKGZvbnQpOwogICAgICB9LAogICAgICBjbG9uZSgpIHsKICAgICAgICByZXR1cm4gdGhpczsKICAgICAgfQogICAgfTsKICAgIGNvbnN0IHBhcnNlRm9udCA9IChmb250TmFtZSwgZmFsbGJhY2tGb250RGljdCwgY3NzRm9udEluZm8pID0+IHBhcnRpYWxFdmFsdWF0b3IuaGFuZGxlU2V0Rm9udChyZXNvdXJjZXMsIFtOYW1lLmdldChmb250TmFtZSksIDFdLCBudWxsLCBvcGVyYXRvckxpc3QsIHRhc2ssIGluaXRpYWxTdGF0ZSwgZmFsbGJhY2tGb250RGljdCwgY3NzRm9udEluZm8pLmNhdGNoKHJlYXNvbiA9PiB7CiAgICAgIHdhcm4oYGxvYWRYZmFGb250czogIiR7cmVhc29ufSIuYCk7CiAgICAgIHJldHVybiBudWxsOwogICAgfSk7CiAgICBjb25zdCBwcm9taXNlcyA9IFtdOwogICAgZm9yIChjb25zdCBbZm9udE5hbWUsIGZvbnRdIG9mIGZvbnRSZXMpIHsKICAgICAgY29uc3QgZGVzY3JpcHRvciA9IGZvbnQuZ2V0KCJGb250RGVzY3JpcHRvciIpOwogICAgICBpZiAoIShkZXNjcmlwdG9yIGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBsZXQgZm9udEZhbWlseSA9IGRlc2NyaXB0b3IuZ2V0KCJGb250RmFtaWx5Iik7CiAgICAgIGZvbnRGYW1pbHkgPSBmb250RmFtaWx5LnJlcGxhY2VBbGwoL1sgXSsoXGQpL2csICIkMSIpOwogICAgICBjb25zdCBmb250V2VpZ2h0ID0gZGVzY3JpcHRvci5nZXQoIkZvbnRXZWlnaHQiKTsKICAgICAgY29uc3QgaXRhbGljQW5nbGUgPSAtZGVzY3JpcHRvci5nZXQoIkl0YWxpY0FuZ2xlIik7CiAgICAgIGNvbnN0IGNzc0ZvbnRJbmZvID0gewogICAgICAgIGZvbnRGYW1pbHksCiAgICAgICAgZm9udFdlaWdodCwKICAgICAgICBpdGFsaWNBbmdsZQogICAgICB9OwogICAgICBpZiAoIXZhbGlkYXRlQ1NTRm9udChjc3NGb250SW5mbykpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQogICAgICBwcm9taXNlcy5wdXNoKHBhcnNlRm9udChmb250TmFtZSwgbnVsbCwgY3NzRm9udEluZm8pKTsKICAgIH0KICAgIGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTsKICAgIGNvbnN0IG1pc3NpbmdGb250cyA9IHRoaXMueGZhRmFjdG9yeS5zZXRGb250cyhwZGZGb250cyk7CiAgICBpZiAoIW1pc3NpbmdGb250cykgewogICAgICByZXR1cm47CiAgICB9CiAgICBvcHRpb25zLmlnbm9yZUVycm9ycyA9IHRydWU7CiAgICBwcm9taXNlcy5sZW5ndGggPSAwOwogICAgcGRmRm9udHMubGVuZ3RoID0gMDsKICAgIGNvbnN0IHJlYWxseU1pc3NpbmdGb250cyA9IG5ldyBTZXQoKTsKICAgIGZvciAoY29uc3QgbWlzc2luZyBvZiBtaXNzaW5nRm9udHMpIHsKICAgICAgaWYgKCFnZXRYZmFGb250TmFtZShgJHttaXNzaW5nfS1SZWd1bGFyYCkpIHsKICAgICAgICByZWFsbHlNaXNzaW5nRm9udHMuYWRkKG1pc3NpbmcpOwogICAgICB9CiAgICB9CiAgICBpZiAocmVhbGx5TWlzc2luZ0ZvbnRzLnNpemUpIHsKICAgICAgbWlzc2luZ0ZvbnRzLnB1c2goIlBkZkpTLUZhbGxiYWNrIik7CiAgICB9CiAgICBmb3IgKGNvbnN0IG1pc3Npbmcgb2YgbWlzc2luZ0ZvbnRzKSB7CiAgICAgIGlmIChyZWFsbHlNaXNzaW5nRm9udHMuaGFzKG1pc3NpbmcpKSB7CiAgICAgICAgY29udGludWU7CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBmb250SW5mbyBvZiBbewogICAgICAgIG5hbWU6ICJSZWd1bGFyIiwKICAgICAgICBmb250V2VpZ2h0OiA0MDAsCiAgICAgICAgaXRhbGljQW5nbGU6IDAKICAgICAgfSwgewogICAgICAgIG5hbWU6ICJCb2xkIiwKICAgICAgICBmb250V2VpZ2h0OiA3MDAsCiAgICAgICAgaXRhbGljQW5nbGU6IDAKICAgICAgfSwgewogICAgICAgIG5hbWU6ICJJdGFsaWMiLAogICAgICAgIGZvbnRXZWlnaHQ6IDQwMCwKICAgICAgICBpdGFsaWNBbmdsZTogMTIKICAgICAgfSwgewogICAgICAgIG5hbWU6ICJCb2xkSXRhbGljIiwKICAgICAgICBmb250V2VpZ2h0OiA3MDAsCiAgICAgICAgaXRhbGljQW5nbGU6IDEyCiAgICAgIH1dKSB7CiAgICAgICAgY29uc3QgbmFtZSA9IGAke21pc3Npbmd9LSR7Zm9udEluZm8ubmFtZX1gOwogICAgICAgIHByb21pc2VzLnB1c2gocGFyc2VGb250KG5hbWUsIGdldFhmYUZvbnREaWN0KG5hbWUpLCB7CiAgICAgICAgICBmb250RmFtaWx5OiBtaXNzaW5nLAogICAgICAgICAgZm9udFdlaWdodDogZm9udEluZm8uZm9udFdlaWdodCwKICAgICAgICAgIGl0YWxpY0FuZ2xlOiBmb250SW5mby5pdGFsaWNBbmdsZQogICAgICAgIH0pKTsKICAgICAgfQogICAgfQogICAgYXdhaXQgUHJvbWlzZS5hbGwocHJvbWlzZXMpOwogICAgdGhpcy54ZmFGYWN0b3J5LmFwcGVuZEZvbnRzKHBkZkZvbnRzLCByZWFsbHlNaXNzaW5nRm9udHMpOwogIH0KICBsb2FkWGZhUmVzb3VyY2VzKGhhbmRsZXIsIHRhc2spIHsKICAgIHJldHVybiBQcm9taXNlLmFsbChbdGhpcy4jbG9hZFhmYUZvbnRzKGhhbmRsZXIsIHRhc2spLmNhdGNoKCgpID0+IHt9KSwgdGhpcy4jbG9hZFhmYUltYWdlcygpXSk7CiAgfQogIHNlcmlhbGl6ZVhmYURhdGEoYW5ub3RhdGlvblN0b3JhZ2UpIHsKICAgIHJldHVybiB0aGlzLnhmYUZhY3RvcnkgPyB0aGlzLnhmYUZhY3Rvcnkuc2VyaWFsaXplRGF0YShhbm5vdGF0aW9uU3RvcmFnZSkgOiBudWxsOwogIH0KICBnZXQgdmVyc2lvbigpIHsKICAgIHJldHVybiB0aGlzLmNhdGFsb2cudmVyc2lvbiB8fCB0aGlzLiN2ZXJzaW9uOwogIH0KICBnZXQgZm9ybUluZm8oKSB7CiAgICBjb25zdCBmb3JtSW5mbyA9IHsKICAgICAgaGFzRmllbGRzOiBmYWxzZSwKICAgICAgaGFzQWNyb0Zvcm06IGZhbHNlLAogICAgICBoYXNYZmE6IGZhbHNlLAogICAgICBoYXNTaWduYXR1cmVzOiBmYWxzZQogICAgfTsKICAgIGNvbnN0IHsKICAgICAgYWNyb0Zvcm0KICAgIH0gPSB0aGlzLmNhdGFsb2c7CiAgICBpZiAoIWFjcm9Gb3JtKSB7CiAgICAgIHJldHVybiBzaGFkb3codGhpcywgImZvcm1JbmZvIiwgZm9ybUluZm8pOwogICAgfQogICAgdHJ5IHsKICAgICAgY29uc3QgZmllbGRzID0gYWNyb0Zvcm0uZ2V0KCJGaWVsZHMiKTsKICAgICAgY29uc3QgaGFzRmllbGRzID0gQXJyYXkuaXNBcnJheShmaWVsZHMpICYmIGZpZWxkcy5sZW5ndGggPiAwOwogICAgICBmb3JtSW5mby5oYXNGaWVsZHMgPSBoYXNGaWVsZHM7CiAgICAgIGNvbnN0IHhmYSA9IGFjcm9Gb3JtLmdldCgiWEZBIik7CiAgICAgIGZvcm1JbmZvLmhhc1hmYSA9IEFycmF5LmlzQXJyYXkoeGZhKSAmJiB4ZmEubGVuZ3RoID4gMCB8fCB4ZmEgaW5zdGFuY2VvZiBCYXNlU3RyZWFtICYmICF4ZmEuaXNFbXB0eTsKICAgICAgY29uc3Qgc2lnRmxhZ3MgPSBhY3JvRm9ybS5nZXQoIlNpZ0ZsYWdzIik7CiAgICAgIGNvbnN0IGhhc1NpZ25hdHVyZXMgPSAhIShzaWdGbGFncyAmIDB4MSk7CiAgICAgIGNvbnN0IGhhc09ubHlEb2N1bWVudFNpZ25hdHVyZXMgPSBoYXNTaWduYXR1cmVzICYmIHRoaXMuI2hhc09ubHlEb2N1bWVudFNpZ25hdHVyZXMoZmllbGRzKTsKICAgICAgZm9ybUluZm8uaGFzQWNyb0Zvcm0gPSBoYXNGaWVsZHMgJiYgIWhhc09ubHlEb2N1bWVudFNpZ25hdHVyZXM7CiAgICAgIGZvcm1JbmZvLmhhc1NpZ25hdHVyZXMgPSBoYXNTaWduYXR1cmVzOwogICAgfSBjYXRjaCAoZXgpIHsKICAgICAgaWYgKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBleDsKICAgICAgfQogICAgICB3YXJuKGBDYW5ub3QgZmV0Y2ggZm9ybSBpbmZvcm1hdGlvbjogIiR7ZXh9Ii5gKTsKICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgImZvcm1JbmZvIiwgZm9ybUluZm8pOwogIH0KICBnZXQgZG9jdW1lbnRJbmZvKCkgewogICAgY29uc3QgewogICAgICBjYXRhbG9nLAogICAgICBmb3JtSW5mbywKICAgICAgeHJlZgogICAgfSA9IHRoaXM7CiAgICBjb25zdCBkb2NJbmZvID0gewogICAgICBQREZGb3JtYXRWZXJzaW9uOiB0aGlzLnZlcnNpb24sCiAgICAgIExhbmd1YWdlOiBjYXRhbG9nLmxhbmcsCiAgICAgIEVuY3J5cHRGaWx0ZXJOYW1lOiB4cmVmLmVuY3J5cHQ/LmZpbHRlck5hbWUgPz8gbnVsbCwKICAgICAgSXNMaW5lYXJpemVkOiAhIXRoaXMubGluZWFyaXphdGlvbiwKICAgICAgSXNBY3JvRm9ybVByZXNlbnQ6IGZvcm1JbmZvLmhhc0Fjcm9Gb3JtLAogICAgICBJc1hGQVByZXNlbnQ6IGZvcm1JbmZvLmhhc1hmYSwKICAgICAgSXNDb2xsZWN0aW9uUHJlc2VudDogISFjYXRhbG9nLmNvbGxlY3Rpb24sCiAgICAgIElzU2lnbmF0dXJlc1ByZXNlbnQ6IGZvcm1JbmZvLmhhc1NpZ25hdHVyZXMKICAgIH07CiAgICBsZXQgaW5mb0RpY3Q7CiAgICB0cnkgewogICAgICBpbmZvRGljdCA9IHhyZWYudHJhaWxlci5nZXQoIkluZm8iKTsKICAgIH0gY2F0Y2ggKGVycikgewogICAgICBpZiAoZXJyIGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pIHsKICAgICAgICB0aHJvdyBlcnI7CiAgICAgIH0KICAgICAgaW5mbygiVGhlIGRvY3VtZW50IGluZm9ybWF0aW9uIGRpY3Rpb25hcnkgaXMgaW52YWxpZC4iKTsKICAgIH0KICAgIGlmICghKGluZm9EaWN0IGluc3RhbmNlb2YgRGljdCkpIHsKICAgICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiZG9jdW1lbnRJbmZvIiwgZG9jSW5mbyk7CiAgICB9CiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBpbmZvRGljdCkgewogICAgICBzd2l0Y2ggKGtleSkgewogICAgICAgIGNhc2UgIlRpdGxlIjoKICAgICAgICBjYXNlICJBdXRob3IiOgogICAgICAgIGNhc2UgIlN1YmplY3QiOgogICAgICAgIGNhc2UgIktleXdvcmRzIjoKICAgICAgICBjYXNlICJDcmVhdG9yIjoKICAgICAgICBjYXNlICJQcm9kdWNlciI6CiAgICAgICAgY2FzZSAiQ3JlYXRpb25EYXRlIjoKICAgICAgICBjYXNlICJNb2REYXRlIjoKICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJzdHJpbmciKSB7CiAgICAgICAgICAgIGRvY0luZm9ba2V5XSA9IHN0cmluZ1RvUERGU3RyaW5nKHZhbHVlKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlICJUcmFwcGVkIjoKICAgICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIE5hbWUpIHsKICAgICAgICAgICAgZG9jSW5mb1trZXldID0gdmFsdWU7CiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgICAgfQogICAgICAgICAgYnJlYWs7CiAgICAgICAgZGVmYXVsdDoKICAgICAgICAgIGxldCBjdXN0b21WYWx1ZTsKICAgICAgICAgIHN3aXRjaCAodHlwZW9mIHZhbHVlKSB7CiAgICAgICAgICAgIGNhc2UgInN0cmluZyI6CiAgICAgICAgICAgICAgY3VzdG9tVmFsdWUgPSBzdHJpbmdUb1BERlN0cmluZyh2YWx1ZSk7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgIm51bWJlciI6CiAgICAgICAgICAgIGNhc2UgImJvb2xlYW4iOgogICAgICAgICAgICAgIGN1c3RvbVZhbHVlID0gdmFsdWU7CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgTmFtZSkgewogICAgICAgICAgICAgICAgY3VzdG9tVmFsdWUgPSB2YWx1ZTsKICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgICBpZiAoY3VzdG9tVmFsdWUgPT09IHVuZGVmaW5lZCkgewogICAgICAgICAgICB3YXJuKGBCYWQgdmFsdWUsIGZvciBjdXN0b20ga2V5ICIke2tleX0iLCBpbiBJbmZvOiAke3ZhbHVlfS5gKTsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICB9CiAgICAgICAgICBkb2NJbmZvLkN1c3RvbSA/Pz0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgICAgIGRvY0luZm8uQ3VzdG9tW2tleV0gPSBjdXN0b21WYWx1ZTsKICAgICAgICAgIGNvbnRpbnVlOwogICAgICB9CiAgICAgIHdhcm4oYEJhZCB2YWx1ZSwgZm9yIGtleSAiJHtrZXl9IiwgaW4gSW5mbzogJHt2YWx1ZX0uYCk7CiAgICB9CiAgICByZXR1cm4gc2hhZG93KHRoaXMsICJkb2N1bWVudEluZm8iLCBkb2NJbmZvKTsKICB9CiAgZ2V0IGZpbmdlcnByaW50cygpIHsKICAgIGNvbnN0IEZJTkdFUlBSSU5UX0ZJUlNUX0JZVEVTID0gMTAyNDsKICAgIGNvbnN0IEVNUFRZX0ZJTkdFUlBSSU5UID0gIlx4MDAiLnJlcGVhdCgxNik7CiAgICBmdW5jdGlvbiB2YWxpZGF0ZShkYXRhKSB7CiAgICAgIHJldHVybiB0eXBlb2YgZGF0YSA9PT0gInN0cmluZyIgJiYgZGF0YS5sZW5ndGggPT09IDE2ICYmIGRhdGEgIT09IEVNUFRZX0ZJTkdFUlBSSU5UOwogICAgfQogICAgY29uc3QgaWQgPSB0aGlzLnhyZWYudHJhaWxlci5nZXQoIklEIik7CiAgICBsZXQgaGFzaE9yaWdpbmFsLCBoYXNoTW9kaWZpZWQ7CiAgICBpZiAoQXJyYXkuaXNBcnJheShpZCkgJiYgdmFsaWRhdGUoaWRbMF0pKSB7CiAgICAgIGhhc2hPcmlnaW5hbCA9IHN0cmluZ1RvQnl0ZXMoaWRbMF0pOwogICAgICBpZiAoaWRbMV0gIT09IGlkWzBdICYmIHZhbGlkYXRlKGlkWzFdKSkgewogICAgICAgIGhhc2hNb2RpZmllZCA9IHN0cmluZ1RvQnl0ZXMoaWRbMV0pOwogICAgICB9CiAgICB9IGVsc2UgewogICAgICBoYXNoT3JpZ2luYWwgPSBjYWxjdWxhdGVNRDUodGhpcy5zdHJlYW0uZ2V0Qnl0ZVJhbmdlKDAsIEZJTkdFUlBSSU5UX0ZJUlNUX0JZVEVTKSwgMCwgRklOR0VSUFJJTlRfRklSU1RfQllURVMpOwogICAgfQogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiZmluZ2VycHJpbnRzIiwgW3RvSGV4VXRpbChoYXNoT3JpZ2luYWwpLCBoYXNoTW9kaWZpZWQgPyB0b0hleFV0aWwoaGFzaE1vZGlmaWVkKSA6IG51bGxdKTsKICB9CiAgYXN5bmMgI2dldExpbmVhcml6YXRpb25QYWdlKHBhZ2VJbmRleCkgewogICAgY29uc3QgewogICAgICBjYXRhbG9nLAogICAgICBsaW5lYXJpemF0aW9uLAogICAgICB4cmVmCiAgICB9ID0gdGhpczsKICAgIGNvbnN0IHJlZiA9IFJlZi5nZXQobGluZWFyaXphdGlvbi5vYmplY3ROdW1iZXJGaXJzdCwgMCk7CiAgICB0cnkgewogICAgICBjb25zdCBvYmogPSBhd2FpdCB4cmVmLmZldGNoQXN5bmMocmVmKTsKICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIERpY3QpIHsKICAgICAgICBsZXQgdHlwZSA9IG9iai5nZXRSYXcoIlR5cGUiKTsKICAgICAgICBpZiAodHlwZSBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgdHlwZSA9IGF3YWl0IHhyZWYuZmV0Y2hBc3luYyh0eXBlKTsKICAgICAgICB9CiAgICAgICAgaWYgKGlzTmFtZSh0eXBlLCAiUGFnZSIpIHx8ICFvYmouaGFzKCJUeXBlIikgJiYgIW9iai5oYXMoIktpZHMiKSAmJiBvYmouaGFzKCJDb250ZW50cyIpKSB7CiAgICAgICAgICBpZiAoIWNhdGFsb2cucGFnZUtpZHNDb3VudENhY2hlLmhhcyhyZWYpKSB7CiAgICAgICAgICAgIGNhdGFsb2cucGFnZUtpZHNDb3VudENhY2hlLnB1dChyZWYsIDEpOwogICAgICAgICAgfQogICAgICAgICAgaWYgKCFjYXRhbG9nLnBhZ2VJbmRleENhY2hlLmhhcyhyZWYpKSB7CiAgICAgICAgICAgIGNhdGFsb2cucGFnZUluZGV4Q2FjaGUucHV0KHJlZiwgMCk7CiAgICAgICAgICB9CiAgICAgICAgICByZXR1cm4gW29iaiwgcmVmXTsKICAgICAgICB9CiAgICAgIH0KICAgICAgdGhyb3cgbmV3IEZvcm1hdEVycm9yKCJUaGUgTGluZWFyaXphdGlvbiBkaWN0aW9uYXJ5IGRvZXNuJ3QgcG9pbnQgdG8gYSB2YWxpZCBQYWdlIGRpY3Rpb25hcnkuIik7CiAgICB9IGNhdGNoIChyZWFzb24pIHsKICAgICAgd2FybihgX2dldExpbmVhcml6YXRpb25QYWdlOiAiJHtyZWFzb24ubWVzc2FnZX0iLmApOwogICAgICByZXR1cm4gY2F0YWxvZy5nZXRQYWdlRGljdChwYWdlSW5kZXgpOwogICAgfQogIH0KICBnZXRQYWdlKHBhZ2VJbmRleCkgewogICAgY29uc3QgY2FjaGVkUHJvbWlzZSA9IHRoaXMuI3BhZ2VQcm9taXNlcy5nZXQocGFnZUluZGV4KTsKICAgIGlmIChjYWNoZWRQcm9taXNlKSB7CiAgICAgIHJldHVybiBjYWNoZWRQcm9taXNlOwogICAgfQogICAgY29uc3QgewogICAgICBjYXRhbG9nLAogICAgICBsaW5lYXJpemF0aW9uLAogICAgICB4ZmFGYWN0b3J5CiAgICB9ID0gdGhpczsKICAgIGxldCBwcm9taXNlOwogICAgaWYgKHhmYUZhY3RvcnkpIHsKICAgICAgcHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZShbRGljdC5lbXB0eSwgbnVsbF0pOwogICAgfSBlbHNlIGlmIChsaW5lYXJpemF0aW9uPy5wYWdlRmlyc3QgPT09IHBhZ2VJbmRleCkgewogICAgICBwcm9taXNlID0gdGhpcy4jZ2V0TGluZWFyaXphdGlvblBhZ2UocGFnZUluZGV4KTsKICAgIH0gZWxzZSB7CiAgICAgIHByb21pc2UgPSBjYXRhbG9nLmdldFBhZ2VEaWN0KHBhZ2VJbmRleCk7CiAgICB9CiAgICBwcm9taXNlID0gcHJvbWlzZS50aGVuKChbcGFnZURpY3QsIHJlZl0pID0+IG5ldyBQYWdlKHsKICAgICAgcGRmTWFuYWdlcjogdGhpcy5wZGZNYW5hZ2VyLAogICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgIHBhZ2VJbmRleCwKICAgICAgcGFnZURpY3QsCiAgICAgIHJlZiwKICAgICAgZ2xvYmFsSWRGYWN0b3J5OiB0aGlzLl9nbG9iYWxJZEZhY3RvcnksCiAgICAgIGZvbnRDYWNoZTogY2F0YWxvZy5mb250Q2FjaGUsCiAgICAgIGJ1aWx0SW5DTWFwQ2FjaGU6IGNhdGFsb2cuYnVpbHRJbkNNYXBDYWNoZSwKICAgICAgc3RhbmRhcmRGb250RGF0YUNhY2hlOiBjYXRhbG9nLnN0YW5kYXJkRm9udERhdGFDYWNoZSwKICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOiBjYXRhbG9nLmdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgICAgZ2xvYmFsSW1hZ2VDYWNoZTogY2F0YWxvZy5nbG9iYWxJbWFnZUNhY2hlLAogICAgICBzeXN0ZW1Gb250Q2FjaGU6IGNhdGFsb2cuc3lzdGVtRm9udENhY2hlLAogICAgICBub25CbGVuZE1vZGVzU2V0OiBjYXRhbG9nLm5vbkJsZW5kTW9kZXNTZXQsCiAgICAgIHhmYUZhY3RvcnkKICAgIH0pKTsKICAgIHRoaXMuI3BhZ2VQcm9taXNlcy5zZXQocGFnZUluZGV4LCBwcm9taXNlKTsKICAgIHJldHVybiBwcm9taXNlOwogIH0KICBhc3luYyBjaGVja0ZpcnN0UGFnZShyZWNvdmVyeU1vZGUgPSBmYWxzZSkgewogICAgaWYgKHJlY292ZXJ5TW9kZSkgewogICAgICByZXR1cm47CiAgICB9CiAgICB0cnkgewogICAgICBhd2FpdCB0aGlzLmdldFBhZ2UoMCk7CiAgICB9IGNhdGNoIChyZWFzb24pIHsKICAgICAgaWYgKHJlYXNvbiBpbnN0YW5jZW9mIFhSZWZFbnRyeUV4Y2VwdGlvbikgewogICAgICAgIHRoaXMuI3BhZ2VQcm9taXNlcy5kZWxldGUoMCk7CiAgICAgICAgYXdhaXQgdGhpcy5jbGVhbnVwKCk7CiAgICAgICAgdGhyb3cgbmV3IFhSZWZQYXJzZUV4Y2VwdGlvbigpOwogICAgICB9CiAgICB9CiAgfQogIGFzeW5jIGNoZWNrTGFzdFBhZ2UocmVjb3ZlcnlNb2RlID0gZmFsc2UpIHsKICAgIGNvbnN0IHsKICAgICAgY2F0YWxvZywKICAgICAgcGRmTWFuYWdlcgogICAgfSA9IHRoaXM7CiAgICBjYXRhbG9nLnNldEFjdHVhbE51bVBhZ2VzKCk7CiAgICBsZXQgbnVtUGFnZXM7CiAgICB0cnkgewogICAgICBhd2FpdCBQcm9taXNlLmFsbChbcGRmTWFuYWdlci5lbnN1cmVEb2MoInhmYUZhY3RvcnkiKSwgcGRmTWFuYWdlci5lbnN1cmVEb2MoImxpbmVhcml6YXRpb24iKSwgcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJudW1QYWdlcyIpXSk7CiAgICAgIGlmICh0aGlzLnhmYUZhY3RvcnkpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0gZWxzZSBpZiAodGhpcy5saW5lYXJpemF0aW9uKSB7CiAgICAgICAgbnVtUGFnZXMgPSB0aGlzLmxpbmVhcml6YXRpb24ubnVtUGFnZXM7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgbnVtUGFnZXMgPSBjYXRhbG9nLm51bVBhZ2VzOwogICAgICB9CiAgICAgIGlmICghTnVtYmVyLmlzSW50ZWdlcihudW1QYWdlcykpIHsKICAgICAgICB0aHJvdyBuZXcgRm9ybWF0RXJyb3IoIlBhZ2UgY291bnQgaXMgbm90IGFuIGludGVnZXIuIik7CiAgICAgIH0gZWxzZSBpZiAobnVtUGFnZXMgPD0gMSkgewogICAgICAgIHJldHVybjsKICAgICAgfQogICAgICBhd2FpdCB0aGlzLmdldFBhZ2UobnVtUGFnZXMgLSAxKTsKICAgIH0gY2F0Y2ggKHJlYXNvbikgewogICAgICB0aGlzLiNwYWdlUHJvbWlzZXMuZGVsZXRlKG51bVBhZ2VzIC0gMSk7CiAgICAgIGF3YWl0IHRoaXMuY2xlYW51cCgpOwogICAgICBpZiAocmVhc29uIGluc3RhbmNlb2YgWFJlZkVudHJ5RXhjZXB0aW9uICYmICFyZWNvdmVyeU1vZGUpIHsKICAgICAgICB0aHJvdyBuZXcgWFJlZlBhcnNlRXhjZXB0aW9uKCk7CiAgICAgIH0KICAgICAgd2FybihgY2hlY2tMYXN0UGFnZSAtIGludmFsaWQgL1BhZ2VzIHRyZWUgL0NvdW50OiAke251bVBhZ2VzfS5gKTsKICAgICAgbGV0IHBhZ2VzVHJlZTsKICAgICAgdHJ5IHsKICAgICAgICBwYWdlc1RyZWUgPSBhd2FpdCBjYXRhbG9nLmdldEFsbFBhZ2VEaWN0cyhyZWNvdmVyeU1vZGUpOwogICAgICB9IGNhdGNoIChyZWFzb25BbGwpIHsKICAgICAgICBpZiAocmVhc29uQWxsIGluc3RhbmNlb2YgWFJlZkVudHJ5RXhjZXB0aW9uICYmICFyZWNvdmVyeU1vZGUpIHsKICAgICAgICAgIHRocm93IG5ldyBYUmVmUGFyc2VFeGNlcHRpb24oKTsKICAgICAgICB9CiAgICAgICAgY2F0YWxvZy5zZXRBY3R1YWxOdW1QYWdlcygxKTsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgZm9yIChjb25zdCBbcGFnZUluZGV4LCBbcGFnZURpY3QsIHJlZl1dIG9mIHBhZ2VzVHJlZSkgewogICAgICAgIGxldCBwcm9taXNlOwogICAgICAgIGlmIChwYWdlRGljdCBpbnN0YW5jZW9mIEVycm9yKSB7CiAgICAgICAgICBwcm9taXNlID0gUHJvbWlzZS5yZWplY3QocGFnZURpY3QpOwogICAgICAgICAgcHJvbWlzZS5jYXRjaCgoKSA9PiB7fSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHByb21pc2UgPSBQcm9taXNlLnJlc29sdmUobmV3IFBhZ2UoewogICAgICAgICAgICBwZGZNYW5hZ2VyLAogICAgICAgICAgICB4cmVmOiB0aGlzLnhyZWYsCiAgICAgICAgICAgIHBhZ2VJbmRleCwKICAgICAgICAgICAgcGFnZURpY3QsCiAgICAgICAgICAgIHJlZiwKICAgICAgICAgICAgZ2xvYmFsSWRGYWN0b3J5OiB0aGlzLl9nbG9iYWxJZEZhY3RvcnksCiAgICAgICAgICAgIGZvbnRDYWNoZTogY2F0YWxvZy5mb250Q2FjaGUsCiAgICAgICAgICAgIGJ1aWx0SW5DTWFwQ2FjaGU6IGNhdGFsb2cuYnVpbHRJbkNNYXBDYWNoZSwKICAgICAgICAgICAgc3RhbmRhcmRGb250RGF0YUNhY2hlOiBjYXRhbG9nLnN0YW5kYXJkRm9udERhdGFDYWNoZSwKICAgICAgICAgICAgZ2xvYmFsQ29sb3JTcGFjZUNhY2hlOiB0aGlzLmdsb2JhbENvbG9yU3BhY2VDYWNoZSwKICAgICAgICAgICAgZ2xvYmFsSW1hZ2VDYWNoZTogY2F0YWxvZy5nbG9iYWxJbWFnZUNhY2hlLAogICAgICAgICAgICBzeXN0ZW1Gb250Q2FjaGU6IGNhdGFsb2cuc3lzdGVtRm9udENhY2hlLAogICAgICAgICAgICBub25CbGVuZE1vZGVzU2V0OiBjYXRhbG9nLm5vbkJsZW5kTW9kZXNTZXQsCiAgICAgICAgICAgIHhmYUZhY3Rvcnk6IG51bGwKICAgICAgICAgIH0pKTsKICAgICAgICB9CiAgICAgICAgdGhpcy4jcGFnZVByb21pc2VzLnNldChwYWdlSW5kZXgsIHByb21pc2UpOwogICAgICB9CiAgICAgIGNhdGFsb2cuc2V0QWN0dWFsTnVtUGFnZXMocGFnZXNUcmVlLnNpemUpOwogICAgfQogIH0KICBhc3luYyBmb250RmFsbGJhY2soaWQsIGhhbmRsZXIpIHsKICAgIGNvbnN0IHsKICAgICAgY2F0YWxvZywKICAgICAgcGRmTWFuYWdlcgogICAgfSA9IHRoaXM7CiAgICBmb3IgKGNvbnN0IHRyYW5zbGF0ZWRGb250IG9mIGF3YWl0IFByb21pc2UuYWxsKGNhdGFsb2cuZm9udENhY2hlKSkgewogICAgICBpZiAodHJhbnNsYXRlZEZvbnQubG9hZGVkTmFtZSA9PT0gaWQpIHsKICAgICAgICB0cmFuc2xhdGVkRm9udC5mYWxsYmFjayhoYW5kbGVyLCBwZGZNYW5hZ2VyLmV2YWx1YXRvck9wdGlvbnMpOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgfQogIH0KICBhc3luYyBjbGVhbnVwKG1hbnVhbGx5VHJpZ2dlcmVkID0gZmFsc2UpIHsKICAgIHJldHVybiB0aGlzLmNhdGFsb2cgPyB0aGlzLmNhdGFsb2cuY2xlYW51cChtYW51YWxseVRyaWdnZXJlZCkgOiBjbGVhckdsb2JhbENhY2hlcygpOwogIH0KICBhc3luYyAjY29sbGVjdEZpZWxkT2JqZWN0cyhuYW1lLCBwYXJlbnRSZWYsIGZpZWxkUmVmLCBwcm9taXNlcywgYW5ub3RhdGlvbkdsb2JhbHMsIHZpc2l0ZWRSZWZzLCBvcnBoYW5GaWVsZHMpIHsKICAgIGNvbnN0IHsKICAgICAgeHJlZgogICAgfSA9IHRoaXM7CiAgICBpZiAoIShmaWVsZFJlZiBpbnN0YW5jZW9mIFJlZikgfHwgdmlzaXRlZFJlZnMuaGFzKGZpZWxkUmVmKSkgewogICAgICByZXR1cm47CiAgICB9CiAgICB2aXNpdGVkUmVmcy5wdXQoZmllbGRSZWYpOwogICAgY29uc3QgZmllbGQgPSBhd2FpdCB4cmVmLmZldGNoQXN5bmMoZmllbGRSZWYpOwogICAgaWYgKCEoZmllbGQgaW5zdGFuY2VvZiBEaWN0KSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBsZXQgc3VidHlwZSA9IGF3YWl0IGZpZWxkLmdldEFzeW5jKCJTdWJ0eXBlIik7CiAgICBzdWJ0eXBlID0gc3VidHlwZSBpbnN0YW5jZW9mIE5hbWUgPyBzdWJ0eXBlLm5hbWUgOiBudWxsOwogICAgc3dpdGNoIChzdWJ0eXBlKSB7CiAgICAgIGNhc2UgIkxpbmsiOgogICAgICAgIHJldHVybjsKICAgIH0KICAgIGlmIChmaWVsZC5oYXMoIlQiKSkgewogICAgICBjb25zdCBwYXJ0TmFtZSA9IHN0cmluZ1RvUERGU3RyaW5nKGF3YWl0IGZpZWxkLmdldEFzeW5jKCJUIikpOwogICAgICBuYW1lID0gbmFtZSA9PT0gIiIgPyBwYXJ0TmFtZSA6IGAke25hbWV9LiR7cGFydE5hbWV9YDsKICAgIH0gZWxzZSB7CiAgICAgIGxldCBvYmogPSBmaWVsZDsKICAgICAgd2hpbGUgKHRydWUpIHsKICAgICAgICBvYmogPSBvYmouZ2V0UmF3KCJQYXJlbnQiKSB8fCBwYXJlbnRSZWY7CiAgICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIFJlZikgewogICAgICAgICAgaWYgKHZpc2l0ZWRSZWZzLmhhcyhvYmopKSB7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgICAgb2JqID0gYXdhaXQgeHJlZi5mZXRjaEFzeW5jKG9iaik7CiAgICAgICAgfQogICAgICAgIGlmICghKG9iaiBpbnN0YW5jZW9mIERpY3QpKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgaWYgKG9iai5oYXMoIlQiKSkgewogICAgICAgICAgY29uc3QgcGFydE5hbWUgPSBzdHJpbmdUb1BERlN0cmluZyhhd2FpdCBvYmouZ2V0QXN5bmMoIlQiKSk7CiAgICAgICAgICBuYW1lID0gbmFtZSA9PT0gIiIgPyBwYXJ0TmFtZSA6IGAke25hbWV9LiR7cGFydE5hbWV9YDsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgfQogICAgaWYgKHBhcmVudFJlZiAmJiAhZmllbGQuaGFzKCJQYXJlbnQiKSAmJiBpc05hbWUoZmllbGQuZ2V0KCJTdWJ0eXBlIiksICJXaWRnZXQiKSkgewogICAgICBvcnBoYW5GaWVsZHMucHV0KGZpZWxkUmVmLCBwYXJlbnRSZWYpOwogICAgfQogICAgaWYgKCFwcm9taXNlcy5oYXMobmFtZSkpIHsKICAgICAgcHJvbWlzZXMuc2V0KG5hbWUsIFtdKTsKICAgIH0KICAgIHByb21pc2VzLmdldChuYW1lKS5wdXNoKEFubm90YXRpb25GYWN0b3J5LmNyZWF0ZSh4cmVmLCBmaWVsZFJlZiwgYW5ub3RhdGlvbkdsb2JhbHMsIG51bGwsIHRydWUsIG9ycGhhbkZpZWxkcywgbnVsbCwgbnVsbCkudGhlbihhbm5vdGF0aW9uID0+IGFubm90YXRpb24/LmdldEZpZWxkT2JqZWN0KCkpLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgd2FybihgI2NvbGxlY3RGaWVsZE9iamVjdHM6ICIke3JlYXNvbn0iLmApOwogICAgICByZXR1cm4gbnVsbDsKICAgIH0pKTsKICAgIGlmICghZmllbGQuaGFzKCJLaWRzIikpIHsKICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3Qga2lkcyA9IGF3YWl0IGZpZWxkLmdldEFzeW5jKCJLaWRzIik7CiAgICBpZiAoQXJyYXkuaXNBcnJheShraWRzKSkgewogICAgICBmb3IgKGNvbnN0IGtpZCBvZiBraWRzKSB7CiAgICAgICAgYXdhaXQgdGhpcy4jY29sbGVjdEZpZWxkT2JqZWN0cyhuYW1lLCBmaWVsZFJlZiwga2lkLCBwcm9taXNlcywgYW5ub3RhdGlvbkdsb2JhbHMsIHZpc2l0ZWRSZWZzLCBvcnBoYW5GaWVsZHMpOwogICAgICB9CiAgICB9CiAgfQogIGdldCBmaWVsZE9iamVjdHMoKSB7CiAgICBjb25zdCBwcm9taXNlID0gdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZURvYygiZm9ybUluZm8iKS50aGVuKGFzeW5jIGZvcm1JbmZvID0+IHsKICAgICAgaWYgKCFmb3JtSW5mby5oYXNGaWVsZHMpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBjb25zdCBhbm5vdGF0aW9uR2xvYmFscyA9IGF3YWl0IHRoaXMuYW5ub3RhdGlvbkdsb2JhbHM7CiAgICAgIGlmICghYW5ub3RhdGlvbkdsb2JhbHMpIHsKICAgICAgICByZXR1cm4gbnVsbDsKICAgICAgfQogICAgICBjb25zdCB7CiAgICAgICAgYWNyb0Zvcm0KICAgICAgfSA9IGFubm90YXRpb25HbG9iYWxzOwogICAgICBjb25zdCB2aXNpdGVkUmVmcyA9IG5ldyBSZWZTZXQoKTsKICAgICAgY29uc3QgYWxsRmllbGRzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgICAgY29uc3QgZmllbGRQcm9taXNlcyA9IG5ldyBNYXAoKTsKICAgICAgY29uc3Qgb3JwaGFuRmllbGRzID0gbmV3IFJlZlNldENhY2hlKCk7CiAgICAgIGZvciAoY29uc3QgZmllbGRSZWYgb2YgYWNyb0Zvcm0uZ2V0KCJGaWVsZHMiKSkgewogICAgICAgIGF3YWl0IHRoaXMuI2NvbGxlY3RGaWVsZE9iamVjdHMoIiIsIG51bGwsIGZpZWxkUmVmLCBmaWVsZFByb21pc2VzLCBhbm5vdGF0aW9uR2xvYmFscywgdmlzaXRlZFJlZnMsIG9ycGhhbkZpZWxkcyk7CiAgICAgIH0KICAgICAgY29uc3QgYWxsUHJvbWlzZXMgPSBbXTsKICAgICAgZm9yIChjb25zdCBbbmFtZSwgcHJvbWlzZXNdIG9mIGZpZWxkUHJvbWlzZXMpIHsKICAgICAgICBhbGxQcm9taXNlcy5wdXNoKFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKGZpZWxkcyA9PiB7CiAgICAgICAgICBmaWVsZHMgPSBmaWVsZHMuZmlsdGVyKGZpZWxkID0+ICEhZmllbGQpOwogICAgICAgICAgaWYgKGZpZWxkcy5sZW5ndGggPiAwKSB7CiAgICAgICAgICAgIGFsbEZpZWxkc1tuYW1lXSA9IGZpZWxkczsKICAgICAgICAgIH0KICAgICAgICB9KSk7CiAgICAgIH0KICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoYWxsUHJvbWlzZXMpOwogICAgICByZXR1cm4gewogICAgICAgIGFsbEZpZWxkczogb2JqZWN0U2l6ZShhbGxGaWVsZHMpID4gMCA/IGFsbEZpZWxkcyA6IG51bGwsCiAgICAgICAgb3JwaGFuRmllbGRzCiAgICAgIH07CiAgICB9KTsKICAgIHJldHVybiBzaGFkb3codGhpcywgImZpZWxkT2JqZWN0cyIsIHByb21pc2UpOwogIH0KICBnZXQgaGFzSlNBY3Rpb25zKCkgewogICAgY29uc3QgcHJvbWlzZSA9IHRoaXMucGRmTWFuYWdlci5lbnN1cmVEb2MoIl9wYXJzZUhhc0pTQWN0aW9ucyIpOwogICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiaGFzSlNBY3Rpb25zIiwgcHJvbWlzZSk7CiAgfQogIGFzeW5jIF9wYXJzZUhhc0pTQWN0aW9ucygpIHsKICAgIGNvbnN0IFtjYXRhbG9nSnNBY3Rpb25zLCBmaWVsZE9iamVjdHNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW3RoaXMucGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJqc0FjdGlvbnMiKSwgdGhpcy5wZGZNYW5hZ2VyLmVuc3VyZURvYygiZmllbGRPYmplY3RzIildKTsKICAgIGlmIChjYXRhbG9nSnNBY3Rpb25zKSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogICAgaWYgKGZpZWxkT2JqZWN0cz8uYWxsRmllbGRzKSB7CiAgICAgIHJldHVybiBPYmplY3QudmFsdWVzKGZpZWxkT2JqZWN0cy5hbGxGaWVsZHMpLnNvbWUoZmllbGRPYmplY3QgPT4gZmllbGRPYmplY3Quc29tZShvYmplY3QgPT4gb2JqZWN0LmFjdGlvbnMgIT09IG51bGwpKTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKICB9CiAgZ2V0IGNhbGN1bGF0aW9uT3JkZXJJZHMoKSB7CiAgICBjb25zdCBjYWxjdWxhdGlvbk9yZGVyID0gdGhpcy5jYXRhbG9nLmFjcm9Gb3JtPy5nZXQoIkNPIik7CiAgICBpZiAoIUFycmF5LmlzQXJyYXkoY2FsY3VsYXRpb25PcmRlcikgfHwgY2FsY3VsYXRpb25PcmRlci5sZW5ndGggPT09IDApIHsKICAgICAgcmV0dXJuIHNoYWRvdyh0aGlzLCAiY2FsY3VsYXRpb25PcmRlcklkcyIsIG51bGwpOwogICAgfQogICAgY29uc3QgaWRzID0gW107CiAgICBmb3IgKGNvbnN0IGlkIG9mIGNhbGN1bGF0aW9uT3JkZXIpIHsKICAgICAgaWYgKGlkIGluc3RhbmNlb2YgUmVmKSB7CiAgICAgICAgaWRzLnB1c2goaWQudG9TdHJpbmcoKSk7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBzaGFkb3codGhpcywgImNhbGN1bGF0aW9uT3JkZXJJZHMiLCBpZHMubGVuZ3RoID8gaWRzIDogbnVsbCk7CiAgfQogIGdldCBhbm5vdGF0aW9uR2xvYmFscygpIHsKICAgIHJldHVybiBzaGFkb3codGhpcywgImFubm90YXRpb25HbG9iYWxzIiwgQW5ub3RhdGlvbkZhY3RvcnkuY3JlYXRlR2xvYmFscyh0aGlzLnBkZk1hbmFnZXIpKTsKICB9Cn0KCjsvLyAuL3NyYy9jb3JlL3BkZl9tYW5hZ2VyLmpzCgoKCgoKCgoKCgpmdW5jdGlvbiBwYXJzZURvY0Jhc2VVcmwodXJsKSB7CiAgaWYgKHVybCkgewogICAgY29uc3QgYWJzb2x1dGVVcmwgPSBjcmVhdGVWYWxpZEFic29sdXRlVXJsKHVybCk7CiAgICBpZiAoYWJzb2x1dGVVcmwpIHsKICAgICAgcmV0dXJuIGFic29sdXRlVXJsLmhyZWY7CiAgICB9CiAgICB3YXJuKGBJbnZhbGlkIGFic29sdXRlIGRvY0Jhc2VVcmw6ICIke3VybH0iLmApOwogIH0KICByZXR1cm4gbnVsbDsKfQpjbGFzcyBCYXNlUGRmTWFuYWdlciB7CiAgY29uc3RydWN0b3IoewogICAgZG9jQmFzZVVybCwKICAgIGRvY0lkLAogICAgZW5hYmxlWGZhLAogICAgZXZhbHVhdG9yT3B0aW9ucywKICAgIGhhbmRsZXIsCiAgICBwYXNzd29yZAogIH0pIHsKICAgIHRoaXMuX2RvY0Jhc2VVcmwgPSBwYXJzZURvY0Jhc2VVcmwoZG9jQmFzZVVybCk7CiAgICB0aGlzLl9kb2NJZCA9IGRvY0lkOwogICAgdGhpcy5fcGFzc3dvcmQgPSBwYXNzd29yZDsKICAgIHRoaXMuZW5hYmxlWGZhID0gZW5hYmxlWGZhOwogICAgZXZhbHVhdG9yT3B0aW9ucy5pc09mZnNjcmVlbkNhbnZhc1N1cHBvcnRlZCAmJj0gRmVhdHVyZVRlc3QuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQ7CiAgICBldmFsdWF0b3JPcHRpb25zLmlzSW1hZ2VEZWNvZGVyU3VwcG9ydGVkICYmPSBGZWF0dXJlVGVzdC5pc0ltYWdlRGVjb2RlclN1cHBvcnRlZDsKICAgIHRoaXMuZXZhbHVhdG9yT3B0aW9ucyA9IE9iamVjdC5mcmVlemUoZXZhbHVhdG9yT3B0aW9ucyk7CiAgICBJbWFnZVJlc2l6ZXIuc2V0T3B0aW9ucyhldmFsdWF0b3JPcHRpb25zKTsKICAgIEpwZWdTdHJlYW0uc2V0T3B0aW9ucyhldmFsdWF0b3JPcHRpb25zKTsKICAgIE9wZXJhdG9yTGlzdC5zZXRPcHRpb25zKGV2YWx1YXRvck9wdGlvbnMpOwogICAgY29uc3Qgb3B0aW9ucyA9IHsKICAgICAgLi4uZXZhbHVhdG9yT3B0aW9ucywKICAgICAgaGFuZGxlcgogICAgfTsKICAgIEpweEltYWdlLnNldE9wdGlvbnMob3B0aW9ucyk7CiAgICBJY2NDb2xvclNwYWNlLnNldE9wdGlvbnMob3B0aW9ucyk7CiAgICBDbXlrSUNDQmFzZWRDUy5zZXRPcHRpb25zKG9wdGlvbnMpOwogIH0KICBnZXQgZG9jSWQoKSB7CiAgICByZXR1cm4gdGhpcy5fZG9jSWQ7CiAgfQogIGdldCBwYXNzd29yZCgpIHsKICAgIHJldHVybiB0aGlzLl9wYXNzd29yZDsKICB9CiAgZ2V0IGRvY0Jhc2VVcmwoKSB7CiAgICByZXR1cm4gdGhpcy5fZG9jQmFzZVVybDsKICB9CiAgZW5zdXJlRG9jKHByb3AsIGFyZ3MpIHsKICAgIHJldHVybiB0aGlzLmVuc3VyZSh0aGlzLnBkZkRvY3VtZW50LCBwcm9wLCBhcmdzKTsKICB9CiAgZW5zdXJlWFJlZihwcm9wLCBhcmdzKSB7CiAgICByZXR1cm4gdGhpcy5lbnN1cmUodGhpcy5wZGZEb2N1bWVudC54cmVmLCBwcm9wLCBhcmdzKTsKICB9CiAgZW5zdXJlQ2F0YWxvZyhwcm9wLCBhcmdzKSB7CiAgICByZXR1cm4gdGhpcy5lbnN1cmUodGhpcy5wZGZEb2N1bWVudC5jYXRhbG9nLCBwcm9wLCBhcmdzKTsKICB9CiAgZ2V0UGFnZShwYWdlSW5kZXgpIHsKICAgIHJldHVybiB0aGlzLnBkZkRvY3VtZW50LmdldFBhZ2UocGFnZUluZGV4KTsKICB9CiAgZm9udEZhbGxiYWNrKGlkLCBoYW5kbGVyKSB7CiAgICByZXR1cm4gdGhpcy5wZGZEb2N1bWVudC5mb250RmFsbGJhY2soaWQsIGhhbmRsZXIpOwogIH0KICBjbGVhbnVwKG1hbnVhbGx5VHJpZ2dlcmVkID0gZmFsc2UpIHsKICAgIHJldHVybiB0aGlzLnBkZkRvY3VtZW50LmNsZWFudXAobWFudWFsbHlUcmlnZ2VyZWQpOwogIH0KICBhc3luYyBlbnN1cmUob2JqLCBwcm9wLCBhcmdzKSB7CiAgICB1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGBlbnN1cmVgIGNhbGxlZCIpOwogIH0KICByZXF1ZXN0UmFuZ2UoYmVnaW4sIGVuZCkgewogICAgdW5yZWFjaGFibGUoIkFic3RyYWN0IG1ldGhvZCBgcmVxdWVzdFJhbmdlYCBjYWxsZWQiKTsKICB9CiAgcmVxdWVzdExvYWRlZFN0cmVhbShub0ZldGNoID0gZmFsc2UpIHsKICAgIHVucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYHJlcXVlc3RMb2FkZWRTdHJlYW1gIGNhbGxlZCIpOwogIH0KICBzZW5kUHJvZ3Jlc3NpdmVEYXRhKGNodW5rKSB7CiAgICB1bnJlYWNoYWJsZSgiQWJzdHJhY3QgbWV0aG9kIGBzZW5kUHJvZ3Jlc3NpdmVEYXRhYCBjYWxsZWQiKTsKICB9CiAgdXBkYXRlUGFzc3dvcmQocGFzc3dvcmQpIHsKICAgIHRoaXMuX3Bhc3N3b3JkID0gcGFzc3dvcmQ7CiAgfQogIHRlcm1pbmF0ZShyZWFzb24pIHsKICAgIHVucmVhY2hhYmxlKCJBYnN0cmFjdCBtZXRob2QgYHRlcm1pbmF0ZWAgY2FsbGVkIik7CiAgfQp9CmNsYXNzIExvY2FsUGRmTWFuYWdlciBleHRlbmRzIEJhc2VQZGZNYW5hZ2VyIHsKICBjb25zdHJ1Y3RvcihhcmdzKSB7CiAgICBzdXBlcihhcmdzKTsKICAgIGNvbnN0IHN0cmVhbSA9IG5ldyBTdHJlYW0oYXJncy5zb3VyY2UpOwogICAgdGhpcy5wZGZEb2N1bWVudCA9IG5ldyBQREZEb2N1bWVudCh0aGlzLCBzdHJlYW0pOwogICAgdGhpcy5fbG9hZGVkU3RyZWFtUHJvbWlzZSA9IFByb21pc2UucmVzb2x2ZShzdHJlYW0pOwogIH0KICBhc3luYyBlbnN1cmUob2JqLCBwcm9wLCBhcmdzKSB7CiAgICBjb25zdCB2YWx1ZSA9IG9ialtwcm9wXTsKICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICJmdW5jdGlvbiIpIHsKICAgICAgcmV0dXJuIHZhbHVlLmFwcGx5KG9iaiwgYXJncyk7CiAgICB9CiAgICByZXR1cm4gdmFsdWU7CiAgfQogIHJlcXVlc3RSYW5nZShiZWdpbiwgZW5kKSB7CiAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7CiAgfQogIHJlcXVlc3RMb2FkZWRTdHJlYW0obm9GZXRjaCA9IGZhbHNlKSB7CiAgICByZXR1cm4gdGhpcy5fbG9hZGVkU3RyZWFtUHJvbWlzZTsKICB9CiAgdGVybWluYXRlKHJlYXNvbikge30KfQpjbGFzcyBOZXR3b3JrUGRmTWFuYWdlciBleHRlbmRzIEJhc2VQZGZNYW5hZ2VyIHsKICBjb25zdHJ1Y3RvcihhcmdzKSB7CiAgICBzdXBlcihhcmdzKTsKICAgIHRoaXMuc3RyZWFtTWFuYWdlciA9IG5ldyBDaHVua2VkU3RyZWFtTWFuYWdlcihhcmdzLnNvdXJjZSwgewogICAgICBtc2dIYW5kbGVyOiBhcmdzLmhhbmRsZXIsCiAgICAgIGxlbmd0aDogYXJncy5sZW5ndGgsCiAgICAgIGRpc2FibGVBdXRvRmV0Y2g6IGFyZ3MuZGlzYWJsZUF1dG9GZXRjaCwKICAgICAgcmFuZ2VDaHVua1NpemU6IGFyZ3MucmFuZ2VDaHVua1NpemUKICAgIH0pOwogICAgdGhpcy5wZGZEb2N1bWVudCA9IG5ldyBQREZEb2N1bWVudCh0aGlzLCB0aGlzLnN0cmVhbU1hbmFnZXIuZ2V0U3RyZWFtKCkpOwogIH0KICBhc3luYyBlbnN1cmUob2JqLCBwcm9wLCBhcmdzKSB7CiAgICB0cnkgewogICAgICBjb25zdCB2YWx1ZSA9IG9ialtwcm9wXTsKICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gImZ1bmN0aW9uIikgewogICAgICAgIHJldHVybiB2YWx1ZS5hcHBseShvYmosIGFyZ3MpOwogICAgICB9CiAgICAgIHJldHVybiB2YWx1ZTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGlmICghKGV4IGluc3RhbmNlb2YgTWlzc2luZ0RhdGFFeGNlcHRpb24pKSB7CiAgICAgICAgdGhyb3cgZXg7CiAgICAgIH0KICAgICAgYXdhaXQgdGhpcy5yZXF1ZXN0UmFuZ2UoZXguYmVnaW4sIGV4LmVuZCk7CiAgICAgIHJldHVybiB0aGlzLmVuc3VyZShvYmosIHByb3AsIGFyZ3MpOwogICAgfQogIH0KICByZXF1ZXN0UmFuZ2UoYmVnaW4sIGVuZCkgewogICAgcmV0dXJuIHRoaXMuc3RyZWFtTWFuYWdlci5yZXF1ZXN0UmFuZ2UoYmVnaW4sIGVuZCk7CiAgfQogIHJlcXVlc3RMb2FkZWRTdHJlYW0obm9GZXRjaCA9IGZhbHNlKSB7CiAgICByZXR1cm4gdGhpcy5zdHJlYW1NYW5hZ2VyLnJlcXVlc3RBbGxDaHVua3Mobm9GZXRjaCk7CiAgfQogIHNlbmRQcm9ncmVzc2l2ZURhdGEoY2h1bmspIHsKICAgIHRoaXMuc3RyZWFtTWFuYWdlci5vblJlY2VpdmVEYXRhKHsKICAgICAgY2h1bmsKICAgIH0pOwogIH0KICB0ZXJtaW5hdGUocmVhc29uKSB7CiAgICB0aGlzLnN0cmVhbU1hbmFnZXIuYWJvcnQocmVhc29uKTsKICB9Cn0KCjsvLyAuL3NyYy9zaGFyZWQvbWVzc2FnZV9oYW5kbGVyLmpzCgoKCmNvbnN0IENhbGxiYWNrS2luZCA9IHsKICBEQVRBOiAxLAogIEVSUk9SOiAyCn07CmNvbnN0IFN0cmVhbUtpbmQgPSB7CiAgQ0FOQ0VMOiAxLAogIENBTkNFTF9DT01QTEVURTogMiwKICBDTE9TRTogMywKICBFTlFVRVVFOiA0LAogIEVSUk9SOiA1LAogIFBVTEw6IDYsCiAgUFVMTF9DT01QTEVURTogNywKICBTVEFSVF9DT01QTEVURTogOAp9OwpmdW5jdGlvbiBvbkZuKCkge30KZnVuY3Rpb24gd3JhcFJlYXNvbihleCkgewogIGlmIChleCBpbnN0YW5jZW9mIEFib3J0RXhjZXB0aW9uIHx8IGV4IGluc3RhbmNlb2YgSW52YWxpZFBERkV4Y2VwdGlvbiB8fCBleCBpbnN0YW5jZW9mIFBhc3N3b3JkRXhjZXB0aW9uIHx8IGV4IGluc3RhbmNlb2YgUmVzcG9uc2VFeGNlcHRpb24gfHwgZXggaW5zdGFuY2VvZiBVbmtub3duRXJyb3JFeGNlcHRpb24pIHsKICAgIHJldHVybiBleDsKICB9CiAgaWYgKCEoZXggaW5zdGFuY2VvZiBFcnJvciB8fCB0eXBlb2YgZXggPT09ICJvYmplY3QiICYmIGV4ICE9PSBudWxsKSkgewogICAgdW5yZWFjaGFibGUoJ3dyYXBSZWFzb246IEV4cGVjdGVkICJyZWFzb24iIHRvIGJlIGEgKHBvc3NpYmx5IGNsb25lZCkgRXJyb3IuJyk7CiAgfQogIHN3aXRjaCAoZXgubmFtZSkgewogICAgY2FzZSAiQWJvcnRFeGNlcHRpb24iOgogICAgICByZXR1cm4gbmV3IEFib3J0RXhjZXB0aW9uKGV4Lm1lc3NhZ2UpOwogICAgY2FzZSAiSW52YWxpZFBERkV4Y2VwdGlvbiI6CiAgICAgIHJldHVybiBuZXcgSW52YWxpZFBERkV4Y2VwdGlvbihleC5tZXNzYWdlKTsKICAgIGNhc2UgIlBhc3N3b3JkRXhjZXB0aW9uIjoKICAgICAgcmV0dXJuIG5ldyBQYXNzd29yZEV4Y2VwdGlvbihleC5tZXNzYWdlLCBleC5jb2RlKTsKICAgIGNhc2UgIlJlc3BvbnNlRXhjZXB0aW9uIjoKICAgICAgcmV0dXJuIG5ldyBSZXNwb25zZUV4Y2VwdGlvbihleC5tZXNzYWdlLCBleC5zdGF0dXMsIGV4Lm1pc3NpbmcpOwogICAgY2FzZSAiVW5rbm93bkVycm9yRXhjZXB0aW9uIjoKICAgICAgcmV0dXJuIG5ldyBVbmtub3duRXJyb3JFeGNlcHRpb24oZXgubWVzc2FnZSwgZXguZGV0YWlscyk7CiAgfQogIHJldHVybiBuZXcgVW5rbm93bkVycm9yRXhjZXB0aW9uKGV4Lm1lc3NhZ2UsIGV4LnRvU3RyaW5nKCkpOwp9CmNsYXNzIE1lc3NhZ2VIYW5kbGVyIHsKICAjbWVzc2FnZUFDID0gbmV3IEFib3J0Q29udHJvbGxlcigpOwogIGNvbnN0cnVjdG9yKHNvdXJjZU5hbWUsIHRhcmdldE5hbWUsIGNvbU9iaikgewogICAgdGhpcy5zb3VyY2VOYW1lID0gc291cmNlTmFtZTsKICAgIHRoaXMudGFyZ2V0TmFtZSA9IHRhcmdldE5hbWU7CiAgICB0aGlzLmNvbU9iaiA9IGNvbU9iajsKICAgIHRoaXMuY2FsbGJhY2tJZCA9IDE7CiAgICB0aGlzLnN0cmVhbUlkID0gMTsKICAgIHRoaXMuc3RyZWFtU2lua3MgPSBPYmplY3QuY3JlYXRlKG51bGwpOwogICAgdGhpcy5zdHJlYW1Db250cm9sbGVycyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICB0aGlzLmNhbGxiYWNrQ2FwYWJpbGl0aWVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsKICAgIHRoaXMuYWN0aW9uSGFuZGxlciA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICBjb21PYmouYWRkRXZlbnRMaXN0ZW5lcigibWVzc2FnZSIsIHRoaXMuI29uTWVzc2FnZS5iaW5kKHRoaXMpLCB7CiAgICAgIHNpZ25hbDogdGhpcy4jbWVzc2FnZUFDLnNpZ25hbAogICAgfSk7CiAgfQogICNvbk1lc3NhZ2UoewogICAgZGF0YQogIH0pIHsKICAgIGlmIChkYXRhLnRhcmdldE5hbWUgIT09IHRoaXMuc291cmNlTmFtZSkgewogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoZGF0YS5zdHJlYW0pIHsKICAgICAgdGhpcy4jcHJvY2Vzc1N0cmVhbU1lc3NhZ2UoZGF0YSk7CiAgICAgIHJldHVybjsKICAgIH0KICAgIGlmIChkYXRhLmNhbGxiYWNrKSB7CiAgICAgIGNvbnN0IGNhbGxiYWNrSWQgPSBkYXRhLmNhbGxiYWNrSWQ7CiAgICAgIGNvbnN0IGNhcGFiaWxpdHkgPSB0aGlzLmNhbGxiYWNrQ2FwYWJpbGl0aWVzW2NhbGxiYWNrSWRdOwogICAgICBpZiAoIWNhcGFiaWxpdHkpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXNvbHZlIGNhbGxiYWNrICR7Y2FsbGJhY2tJZH1gKTsKICAgICAgfQogICAgICBkZWxldGUgdGhpcy5jYWxsYmFja0NhcGFiaWxpdGllc1tjYWxsYmFja0lkXTsKICAgICAgaWYgKGRhdGEuY2FsbGJhY2sgPT09IENhbGxiYWNrS2luZC5EQVRBKSB7CiAgICAgICAgY2FwYWJpbGl0eS5yZXNvbHZlKGRhdGEuZGF0YSk7CiAgICAgIH0gZWxzZSBpZiAoZGF0YS5jYWxsYmFjayA9PT0gQ2FsbGJhY2tLaW5kLkVSUk9SKSB7CiAgICAgICAgY2FwYWJpbGl0eS5yZWplY3Qod3JhcFJlYXNvbihkYXRhLnJlYXNvbikpOwogICAgICB9IGVsc2UgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiVW5leHBlY3RlZCBjYWxsYmFjayBjYXNlIik7CiAgICAgIH0KICAgICAgcmV0dXJuOwogICAgfQogICAgY29uc3QgYWN0aW9uID0gdGhpcy5hY3Rpb25IYW5kbGVyW2RhdGEuYWN0aW9uXTsKICAgIGlmICghYWN0aW9uKSB7CiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBhY3Rpb24gZnJvbSB3b3JrZXI6ICR7ZGF0YS5hY3Rpb259YCk7CiAgICB9CiAgICBpZiAoZGF0YS5jYWxsYmFja0lkKSB7CiAgICAgIGNvbnN0IHNvdXJjZU5hbWUgPSB0aGlzLnNvdXJjZU5hbWUsCiAgICAgICAgdGFyZ2V0TmFtZSA9IGRhdGEuc291cmNlTmFtZSwKICAgICAgICBjb21PYmogPSB0aGlzLmNvbU9iajsKICAgICAgUHJvbWlzZS50cnkoYWN0aW9uLCBkYXRhLmRhdGEpLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkgewogICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgIGNhbGxiYWNrOiBDYWxsYmFja0tpbmQuREFUQSwKICAgICAgICAgIGNhbGxiYWNrSWQ6IGRhdGEuY2FsbGJhY2tJZCwKICAgICAgICAgIGRhdGE6IHJlc3VsdAogICAgICAgIH0pOwogICAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgY2FsbGJhY2s6IENhbGxiYWNrS2luZC5FUlJPUiwKICAgICAgICAgIGNhbGxiYWNrSWQ6IGRhdGEuY2FsbGJhY2tJZCwKICAgICAgICAgIHJlYXNvbjogd3JhcFJlYXNvbihyZWFzb24pCiAgICAgICAgfSk7CiAgICAgIH0pOwogICAgICByZXR1cm47CiAgICB9CiAgICBpZiAoZGF0YS5zdHJlYW1JZCkgewogICAgICB0aGlzLiNjcmVhdGVTdHJlYW1TaW5rKGRhdGEpOwogICAgICByZXR1cm47CiAgICB9CiAgICBhY3Rpb24oZGF0YS5kYXRhKTsKICB9CiAgb24oYWN0aW9uTmFtZSwgaGFuZGxlcikgewogICAgY29uc3QgYWggPSB0aGlzLmFjdGlvbkhhbmRsZXI7CiAgICBpZiAoYWhbYWN0aW9uTmFtZV0pIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGVyZSBpcyBhbHJlYWR5IGFuIGFjdGlvbk5hbWUgY2FsbGVkICIke2FjdGlvbk5hbWV9ImApOwogICAgfQogICAgYWhbYWN0aW9uTmFtZV0gPSBoYW5kbGVyOwogIH0KICBzZW5kKGFjdGlvbk5hbWUsIGRhdGEsIHRyYW5zZmVycykgewogICAgdGhpcy5jb21PYmoucG9zdE1lc3NhZ2UoewogICAgICBzb3VyY2VOYW1lOiB0aGlzLnNvdXJjZU5hbWUsCiAgICAgIHRhcmdldE5hbWU6IHRoaXMudGFyZ2V0TmFtZSwKICAgICAgYWN0aW9uOiBhY3Rpb25OYW1lLAogICAgICBkYXRhCiAgICB9LCB0cmFuc2ZlcnMpOwogIH0KICBzZW5kV2l0aFByb21pc2UoYWN0aW9uTmFtZSwgZGF0YSwgdHJhbnNmZXJzKSB7CiAgICBjb25zdCBjYWxsYmFja0lkID0gdGhpcy5jYWxsYmFja0lkKys7CiAgICBjb25zdCBjYXBhYmlsaXR5ID0gUHJvbWlzZS53aXRoUmVzb2x2ZXJzKCk7CiAgICB0aGlzLmNhbGxiYWNrQ2FwYWJpbGl0aWVzW2NhbGxiYWNrSWRdID0gY2FwYWJpbGl0eTsKICAgIHRyeSB7CiAgICAgIHRoaXMuY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICBzb3VyY2VOYW1lOiB0aGlzLnNvdXJjZU5hbWUsCiAgICAgICAgdGFyZ2V0TmFtZTogdGhpcy50YXJnZXROYW1lLAogICAgICAgIGFjdGlvbjogYWN0aW9uTmFtZSwKICAgICAgICBjYWxsYmFja0lkLAogICAgICAgIGRhdGEKICAgICAgfSwgdHJhbnNmZXJzKTsKICAgIH0gY2F0Y2ggKGV4KSB7CiAgICAgIGNhcGFiaWxpdHkucmVqZWN0KGV4KTsKICAgIH0KICAgIHJldHVybiBjYXBhYmlsaXR5LnByb21pc2U7CiAgfQogIHNlbmRXaXRoU3RyZWFtKGFjdGlvbk5hbWUsIGRhdGEsIHF1ZXVlaW5nU3RyYXRlZ3ksIHRyYW5zZmVycykgewogICAgY29uc3Qgc3RyZWFtSWQgPSB0aGlzLnN0cmVhbUlkKyssCiAgICAgIHNvdXJjZU5hbWUgPSB0aGlzLnNvdXJjZU5hbWUsCiAgICAgIHRhcmdldE5hbWUgPSB0aGlzLnRhcmdldE5hbWUsCiAgICAgIGNvbU9iaiA9IHRoaXMuY29tT2JqOwogICAgcmV0dXJuIG5ldyBSZWFkYWJsZVN0cmVhbSh7CiAgICAgIHN0YXJ0OiBjb250cm9sbGVyID0+IHsKICAgICAgICBjb25zdCBzdGFydENhcGFiaWxpdHkgPSBQcm9taXNlLndpdGhSZXNvbHZlcnMoKTsKICAgICAgICB0aGlzLnN0cmVhbUNvbnRyb2xsZXJzW3N0cmVhbUlkXSA9IHsKICAgICAgICAgIGNvbnRyb2xsZXIsCiAgICAgICAgICBzdGFydENhbGw6IHN0YXJ0Q2FwYWJpbGl0eSwKICAgICAgICAgIHB1bGxDYWxsOiBudWxsLAogICAgICAgICAgY2FuY2VsQ2FsbDogbnVsbCwKICAgICAgICAgIGlzQ2xvc2VkOiBmYWxzZQogICAgICAgIH07CiAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgYWN0aW9uOiBhY3Rpb25OYW1lLAogICAgICAgICAgc3RyZWFtSWQsCiAgICAgICAgICBkYXRhLAogICAgICAgICAgZGVzaXJlZFNpemU6IGNvbnRyb2xsZXIuZGVzaXJlZFNpemUKICAgICAgICB9LCB0cmFuc2ZlcnMpOwogICAgICAgIHJldHVybiBzdGFydENhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgfSwKICAgICAgcHVsbDogY29udHJvbGxlciA9PiB7CiAgICAgICAgY29uc3QgcHVsbENhcGFiaWxpdHkgPSBQcm9taXNlLndpdGhSZXNvbHZlcnMoKTsKICAgICAgICB0aGlzLnN0cmVhbUNvbnRyb2xsZXJzW3N0cmVhbUlkXS5wdWxsQ2FsbCA9IHB1bGxDYXBhYmlsaXR5OwogICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5QVUxMLAogICAgICAgICAgc3RyZWFtSWQsCiAgICAgICAgICBkZXNpcmVkU2l6ZTogY29udHJvbGxlci5kZXNpcmVkU2l6ZQogICAgICAgIH0pOwogICAgICAgIHJldHVybiBwdWxsQ2FwYWJpbGl0eS5wcm9taXNlOwogICAgICB9LAogICAgICBjYW5jZWw6IHJlYXNvbiA9PiB7CiAgICAgICAgYXNzZXJ0KHJlYXNvbiBpbnN0YW5jZW9mIEVycm9yLCAiY2FuY2VsIG11c3QgaGF2ZSBhIHZhbGlkIHJlYXNvbiIpOwogICAgICAgIGNvbnN0IGNhbmNlbENhcGFiaWxpdHkgPSBQcm9taXNlLndpdGhSZXNvbHZlcnMoKTsKICAgICAgICB0aGlzLnN0cmVhbUNvbnRyb2xsZXJzW3N0cmVhbUlkXS5jYW5jZWxDYWxsID0gY2FuY2VsQ2FwYWJpbGl0eTsKICAgICAgICB0aGlzLnN0cmVhbUNvbnRyb2xsZXJzW3N0cmVhbUlkXS5pc0Nsb3NlZCA9IHRydWU7CiAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLkNBTkNFTCwKICAgICAgICAgIHN0cmVhbUlkLAogICAgICAgICAgcmVhc29uOiB3cmFwUmVhc29uKHJlYXNvbikKICAgICAgICB9KTsKICAgICAgICByZXR1cm4gY2FuY2VsQ2FwYWJpbGl0eS5wcm9taXNlOwogICAgICB9CiAgICB9LCBxdWV1ZWluZ1N0cmF0ZWd5KTsKICB9CiAgI2NyZWF0ZVN0cmVhbVNpbmsoZGF0YSkgewogICAgY29uc3Qgc3RyZWFtSWQgPSBkYXRhLnN0cmVhbUlkLAogICAgICBzb3VyY2VOYW1lID0gdGhpcy5zb3VyY2VOYW1lLAogICAgICB0YXJnZXROYW1lID0gZGF0YS5zb3VyY2VOYW1lLAogICAgICBjb21PYmogPSB0aGlzLmNvbU9iajsKICAgIGNvbnN0IHNlbGYgPSB0aGlzLAogICAgICBhY3Rpb24gPSB0aGlzLmFjdGlvbkhhbmRsZXJbZGF0YS5hY3Rpb25dOwogICAgY29uc3Qgc3RyZWFtU2luayA9IHsKICAgICAgZW5xdWV1ZShjaHVuaywgc2l6ZSA9IDEsIHRyYW5zZmVycykgewogICAgICAgIGlmICh0aGlzLmlzQ2FuY2VsbGVkKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIGNvbnN0IGxhc3REZXNpcmVkU2l6ZSA9IHRoaXMuZGVzaXJlZFNpemU7CiAgICAgICAgdGhpcy5kZXNpcmVkU2l6ZSAtPSBzaXplOwogICAgICAgIGlmIChsYXN0RGVzaXJlZFNpemUgPiAwICYmIHRoaXMuZGVzaXJlZFNpemUgPD0gMCkgewogICAgICAgICAgdGhpcy5zaW5rQ2FwYWJpbGl0eSA9IFByb21pc2Uud2l0aFJlc29sdmVycygpOwogICAgICAgICAgdGhpcy5yZWFkeSA9IHRoaXMuc2lua0NhcGFiaWxpdHkucHJvbWlzZTsKICAgICAgICB9CiAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLkVOUVVFVUUsCiAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgIGNodW5rCiAgICAgICAgfSwgdHJhbnNmZXJzKTsKICAgICAgfSwKICAgICAgY2xvc2UoKSB7CiAgICAgICAgaWYgKHRoaXMuaXNDYW5jZWxsZWQpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgdGhpcy5pc0NhbmNlbGxlZCA9IHRydWU7CiAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLkNMT1NFLAogICAgICAgICAgc3RyZWFtSWQKICAgICAgICB9KTsKICAgICAgICBkZWxldGUgc2VsZi5zdHJlYW1TaW5rc1tzdHJlYW1JZF07CiAgICAgIH0sCiAgICAgIGVycm9yKHJlYXNvbikgewogICAgICAgIGFzc2VydChyZWFzb24gaW5zdGFuY2VvZiBFcnJvciwgImVycm9yIG11c3QgaGF2ZSBhIHZhbGlkIHJlYXNvbiIpOwogICAgICAgIGlmICh0aGlzLmlzQ2FuY2VsbGVkKSB7CiAgICAgICAgICByZXR1cm47CiAgICAgICAgfQogICAgICAgIHRoaXMuaXNDYW5jZWxsZWQgPSB0cnVlOwogICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5FUlJPUiwKICAgICAgICAgIHN0cmVhbUlkLAogICAgICAgICAgcmVhc29uOiB3cmFwUmVhc29uKHJlYXNvbikKICAgICAgICB9KTsKICAgICAgfSwKICAgICAgc2lua0NhcGFiaWxpdHk6IFByb21pc2Uud2l0aFJlc29sdmVycygpLAogICAgICBvblB1bGw6IG51bGwsCiAgICAgIG9uQ2FuY2VsOiBudWxsLAogICAgICBpc0NhbmNlbGxlZDogZmFsc2UsCiAgICAgIGRlc2lyZWRTaXplOiBkYXRhLmRlc2lyZWRTaXplLAogICAgICByZWFkeTogbnVsbAogICAgfTsKICAgIHN0cmVhbVNpbmsuc2lua0NhcGFiaWxpdHkucmVzb2x2ZSgpOwogICAgc3RyZWFtU2luay5yZWFkeSA9IHN0cmVhbVNpbmsuc2lua0NhcGFiaWxpdHkucHJvbWlzZTsKICAgIHRoaXMuc3RyZWFtU2lua3Nbc3RyZWFtSWRdID0gc3RyZWFtU2luazsKICAgIFByb21pc2UudHJ5KGFjdGlvbiwgZGF0YS5kYXRhLCBzdHJlYW1TaW5rKS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLlNUQVJUX0NPTVBMRVRFLAogICAgICAgIHN0cmVhbUlkLAogICAgICAgIHN1Y2Nlc3M6IHRydWUKICAgICAgfSk7CiAgICB9LCBmdW5jdGlvbiAocmVhc29uKSB7CiAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgc291cmNlTmFtZSwKICAgICAgICB0YXJnZXROYW1lLAogICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5TVEFSVF9DT01QTEVURSwKICAgICAgICBzdHJlYW1JZCwKICAgICAgICByZWFzb246IHdyYXBSZWFzb24ocmVhc29uKQogICAgICB9KTsKICAgIH0pOwogIH0KICAjcHJvY2Vzc1N0cmVhbU1lc3NhZ2UoZGF0YSkgewogICAgY29uc3Qgc3RyZWFtSWQgPSBkYXRhLnN0cmVhbUlkLAogICAgICBzb3VyY2VOYW1lID0gdGhpcy5zb3VyY2VOYW1lLAogICAgICB0YXJnZXROYW1lID0gZGF0YS5zb3VyY2VOYW1lLAogICAgICBjb21PYmogPSB0aGlzLmNvbU9iajsKICAgIGNvbnN0IHN0cmVhbUNvbnRyb2xsZXIgPSB0aGlzLnN0cmVhbUNvbnRyb2xsZXJzW3N0cmVhbUlkXSwKICAgICAgc3RyZWFtU2luayA9IHRoaXMuc3RyZWFtU2lua3Nbc3RyZWFtSWRdOwogICAgc3dpdGNoIChkYXRhLnN0cmVhbSkgewogICAgICBjYXNlIFN0cmVhbUtpbmQuU1RBUlRfQ09NUExFVEU6CiAgICAgICAgaWYgKGRhdGEuc3VjY2VzcykgewogICAgICAgICAgc3RyZWFtQ29udHJvbGxlci5zdGFydENhbGwucmVzb2x2ZSgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdHJlYW1Db250cm9sbGVyLnN0YXJ0Q2FsbC5yZWplY3Qod3JhcFJlYXNvbihkYXRhLnJlYXNvbikpOwogICAgICAgIH0KICAgICAgICBicmVhazsKICAgICAgY2FzZSBTdHJlYW1LaW5kLlBVTExfQ09NUExFVEU6CiAgICAgICAgaWYgKGRhdGEuc3VjY2VzcykgewogICAgICAgICAgc3RyZWFtQ29udHJvbGxlci5wdWxsQ2FsbC5yZXNvbHZlKCk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIHN0cmVhbUNvbnRyb2xsZXIucHVsbENhbGwucmVqZWN0KHdyYXBSZWFzb24oZGF0YS5yZWFzb24pKTsKICAgICAgICB9CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgU3RyZWFtS2luZC5QVUxMOgogICAgICAgIGlmICghc3RyZWFtU2luaykgewogICAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLlBVTExfQ09NUExFVEUsCiAgICAgICAgICAgIHN0cmVhbUlkLAogICAgICAgICAgICBzdWNjZXNzOiB0cnVlCiAgICAgICAgICB9KTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgICBpZiAoc3RyZWFtU2luay5kZXNpcmVkU2l6ZSA8PSAwICYmIGRhdGEuZGVzaXJlZFNpemUgPiAwKSB7CiAgICAgICAgICBzdHJlYW1TaW5rLnNpbmtDYXBhYmlsaXR5LnJlc29sdmUoKTsKICAgICAgICB9CiAgICAgICAgc3RyZWFtU2luay5kZXNpcmVkU2l6ZSA9IGRhdGEuZGVzaXJlZFNpemU7CiAgICAgICAgUHJvbWlzZS50cnkoc3RyZWFtU2luay5vblB1bGwgfHwgb25GbikudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuUFVMTF9DT01QTEVURSwKICAgICAgICAgICAgc3RyZWFtSWQsCiAgICAgICAgICAgIHN1Y2Nlc3M6IHRydWUKICAgICAgICAgIH0pOwogICAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgIGNvbU9iai5wb3N0TWVzc2FnZSh7CiAgICAgICAgICAgIHNvdXJjZU5hbWUsCiAgICAgICAgICAgIHRhcmdldE5hbWUsCiAgICAgICAgICAgIHN0cmVhbTogU3RyZWFtS2luZC5QVUxMX0NPTVBMRVRFLAogICAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgICAgcmVhc29uOiB3cmFwUmVhc29uKHJlYXNvbikKICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFN0cmVhbUtpbmQuRU5RVUVVRToKICAgICAgICBhc3NlcnQoc3RyZWFtQ29udHJvbGxlciwgImVucXVldWUgc2hvdWxkIGhhdmUgc3RyZWFtIGNvbnRyb2xsZXIiKTsKICAgICAgICBpZiAoc3RyZWFtQ29udHJvbGxlci5pc0Nsb3NlZCkgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgICAgIHN0cmVhbUNvbnRyb2xsZXIuY29udHJvbGxlci5lbnF1ZXVlKGRhdGEuY2h1bmspOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIFN0cmVhbUtpbmQuQ0xPU0U6CiAgICAgICAgYXNzZXJ0KHN0cmVhbUNvbnRyb2xsZXIsICJjbG9zZSBzaG91bGQgaGF2ZSBzdHJlYW0gY29udHJvbGxlciIpOwogICAgICAgIGlmIChzdHJlYW1Db250cm9sbGVyLmlzQ2xvc2VkKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgc3RyZWFtQ29udHJvbGxlci5pc0Nsb3NlZCA9IHRydWU7CiAgICAgICAgc3RyZWFtQ29udHJvbGxlci5jb250cm9sbGVyLmNsb3NlKCk7CiAgICAgICAgdGhpcy4jZGVsZXRlU3RyZWFtQ29udHJvbGxlcihzdHJlYW1Db250cm9sbGVyLCBzdHJlYW1JZCk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgU3RyZWFtS2luZC5FUlJPUjoKICAgICAgICBhc3NlcnQoc3RyZWFtQ29udHJvbGxlciwgImVycm9yIHNob3VsZCBoYXZlIHN0cmVhbSBjb250cm9sbGVyIik7CiAgICAgICAgc3RyZWFtQ29udHJvbGxlci5jb250cm9sbGVyLmVycm9yKHdyYXBSZWFzb24oZGF0YS5yZWFzb24pKTsKICAgICAgICB0aGlzLiNkZWxldGVTdHJlYW1Db250cm9sbGVyKHN0cmVhbUNvbnRyb2xsZXIsIHN0cmVhbUlkKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBTdHJlYW1LaW5kLkNBTkNFTF9DT01QTEVURToKICAgICAgICBpZiAoZGF0YS5zdWNjZXNzKSB7CiAgICAgICAgICBzdHJlYW1Db250cm9sbGVyLmNhbmNlbENhbGwucmVzb2x2ZSgpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBzdHJlYW1Db250cm9sbGVyLmNhbmNlbENhbGwucmVqZWN0KHdyYXBSZWFzb24oZGF0YS5yZWFzb24pKTsKICAgICAgICB9CiAgICAgICAgdGhpcy4jZGVsZXRlU3RyZWFtQ29udHJvbGxlcihzdHJlYW1Db250cm9sbGVyLCBzdHJlYW1JZCk7CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgU3RyZWFtS2luZC5DQU5DRUw6CiAgICAgICAgaWYgKCFzdHJlYW1TaW5rKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgY29uc3QgZGF0YVJlYXNvbiA9IHdyYXBSZWFzb24oZGF0YS5yZWFzb24pOwogICAgICAgIFByb21pc2UudHJ5KHN0cmVhbVNpbmsub25DYW5jZWwgfHwgb25GbiwgZGF0YVJlYXNvbikudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgICBjb21PYmoucG9zdE1lc3NhZ2UoewogICAgICAgICAgICBzb3VyY2VOYW1lLAogICAgICAgICAgICB0YXJnZXROYW1lLAogICAgICAgICAgICBzdHJlYW06IFN0cmVhbUtpbmQuQ0FOQ0VMX0NPTVBMRVRFLAogICAgICAgICAgICBzdHJlYW1JZCwKICAgICAgICAgICAgc3VjY2VzczogdHJ1ZQogICAgICAgICAgfSk7CiAgICAgICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgY29tT2JqLnBvc3RNZXNzYWdlKHsKICAgICAgICAgICAgc291cmNlTmFtZSwKICAgICAgICAgICAgdGFyZ2V0TmFtZSwKICAgICAgICAgICAgc3RyZWFtOiBTdHJlYW1LaW5kLkNBTkNFTF9DT01QTEVURSwKICAgICAgICAgICAgc3RyZWFtSWQsCiAgICAgICAgICAgIHJlYXNvbjogd3JhcFJlYXNvbihyZWFzb24pCiAgICAgICAgICB9KTsKICAgICAgICB9KTsKICAgICAgICBzdHJlYW1TaW5rLnNpbmtDYXBhYmlsaXR5LnJlamVjdChkYXRhUmVhc29uKTsKICAgICAgICBzdHJlYW1TaW5rLmlzQ2FuY2VsbGVkID0gdHJ1ZTsKICAgICAgICBkZWxldGUgdGhpcy5zdHJlYW1TaW5rc1tzdHJlYW1JZF07CiAgICAgICAgYnJlYWs7CiAgICAgIGRlZmF1bHQ6CiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCJVbmV4cGVjdGVkIHN0cmVhbSBjYXNlIik7CiAgICB9CiAgfQogIGFzeW5jICNkZWxldGVTdHJlYW1Db250cm9sbGVyKHN0cmVhbUNvbnRyb2xsZXIsIHN0cmVhbUlkKSB7CiAgICBhd2FpdCBQcm9taXNlLmFsbFNldHRsZWQoW3N0cmVhbUNvbnRyb2xsZXIuc3RhcnRDYWxsPy5wcm9taXNlLCBzdHJlYW1Db250cm9sbGVyLnB1bGxDYWxsPy5wcm9taXNlLCBzdHJlYW1Db250cm9sbGVyLmNhbmNlbENhbGw/LnByb21pc2VdKTsKICAgIGRlbGV0ZSB0aGlzLnN0cmVhbUNvbnRyb2xsZXJzW3N0cmVhbUlkXTsKICB9CiAgZGVzdHJveSgpIHsKICAgIHRoaXMuI21lc3NhZ2VBQz8uYWJvcnQoKTsKICAgIHRoaXMuI21lc3NhZ2VBQyA9IG51bGw7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS93cml0ZXIuanMKCgoKCgoKCgoKCgoKCgoKCgoKCmFzeW5jIGZ1bmN0aW9uIHdyaXRlT2JqZWN0KHJlZiwgb2JqLCBidWZmZXIsIHsKICBlbmNyeXB0ID0gbnVsbAp9KSB7CiAgY29uc3QgdHJhbnNmb3JtID0gZW5jcnlwdD8uY3JlYXRlQ2lwaGVyVHJhbnNmb3JtKHJlZi5udW0sIHJlZi5nZW4pOwogIGJ1ZmZlci5wdXNoKGAke3JlZi5udW19ICR7cmVmLmdlbn0gb2JqXG5gKTsKICBpZiAob2JqIGluc3RhbmNlb2YgRGljdCkgewogICAgYXdhaXQgd3JpdGVEaWN0KG9iaiwgYnVmZmVyLCB0cmFuc2Zvcm0pOwogIH0gZWxzZSBpZiAob2JqIGluc3RhbmNlb2YgQmFzZVN0cmVhbSkgewogICAgYXdhaXQgd3JpdGVTdHJlYW0ob2JqLCBidWZmZXIsIHRyYW5zZm9ybSk7CiAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KG9iaikgfHwgQXJyYXlCdWZmZXIuaXNWaWV3KG9iaikpIHsKICAgIGF3YWl0IHdyaXRlQXJyYXkob2JqLCBidWZmZXIsIHRyYW5zZm9ybSk7CiAgfQogIGJ1ZmZlci5wdXNoKCJcbmVuZG9ialxuIik7Cn0KYXN5bmMgZnVuY3Rpb24gd3JpdGVEaWN0KGRpY3QsIGJ1ZmZlciwgdHJhbnNmb3JtKSB7CiAgYnVmZmVyLnB1c2goIjw8Iik7CiAgZm9yIChjb25zdCBrZXkgb2YgZGljdC5nZXRLZXlzKCkpIHsKICAgIGJ1ZmZlci5wdXNoKGAgLyR7ZXNjYXBlUERGTmFtZShrZXkpfSBgKTsKICAgIGF3YWl0IHdyaXRlVmFsdWUoZGljdC5nZXRSYXcoa2V5KSwgYnVmZmVyLCB0cmFuc2Zvcm0pOwogIH0KICBidWZmZXIucHVzaCgiPj4iKTsKfQphc3luYyBmdW5jdGlvbiB3cml0ZVN0cmVhbShzdHJlYW0sIGJ1ZmZlciwgdHJhbnNmb3JtKSB7CiAgbGV0IGJ5dGVzID0gc3RyZWFtLmdldEJ5dGVzKCk7CiAgY29uc3QgewogICAgZGljdAogIH0gPSBzdHJlYW07CiAgY29uc3QgW2ZpbHRlciwgcGFyYW1zXSA9IGF3YWl0IFByb21pc2UuYWxsKFtkaWN0LmdldEFzeW5jKCJGaWx0ZXIiKSwgZGljdC5nZXRBc3luYygiRGVjb2RlUGFybXMiKV0pOwogIGNvbnN0IGZpbHRlclplcm8gPSBBcnJheS5pc0FycmF5KGZpbHRlcikgPyBhd2FpdCBkaWN0LnhyZWYuZmV0Y2hJZlJlZkFzeW5jKGZpbHRlclswXSkgOiBmaWx0ZXI7CiAgY29uc3QgaXNGaWx0ZXJaZXJvRmxhdGVEZWNvZGUgPSBpc05hbWUoZmlsdGVyWmVybywgIkZsYXRlRGVjb2RlIik7CiAgY29uc3QgTUlOX0xFTkdUSF9GT1JfQ09NUFJFU1NJTkcgPSAyNTY7CiAgaWYgKGJ5dGVzLmxlbmd0aCA+PSBNSU5fTEVOR1RIX0ZPUl9DT01QUkVTU0lORyB8fCBpc0ZpbHRlclplcm9GbGF0ZURlY29kZSkgewogICAgdHJ5IHsKICAgICAgY29uc3QgY3MgPSBuZXcgQ29tcHJlc3Npb25TdHJlYW0oImRlZmxhdGUiKTsKICAgICAgY29uc3Qgd3JpdGVyID0gY3Mud3JpdGFibGUuZ2V0V3JpdGVyKCk7CiAgICAgIGF3YWl0IHdyaXRlci5yZWFkeTsKICAgICAgd3JpdGVyLndyaXRlKGJ5dGVzKS50aGVuKGFzeW5jICgpID0+IHsKICAgICAgICBhd2FpdCB3cml0ZXIucmVhZHk7CiAgICAgICAgYXdhaXQgd3JpdGVyLmNsb3NlKCk7CiAgICAgIH0pLmNhdGNoKCgpID0+IHt9KTsKICAgICAgY29uc3QgYnVmID0gYXdhaXQgbmV3IFJlc3BvbnNlKGNzLnJlYWRhYmxlKS5hcnJheUJ1ZmZlcigpOwogICAgICBieXRlcyA9IG5ldyBVaW50OEFycmF5KGJ1Zik7CiAgICAgIGxldCBuZXdGaWx0ZXIsIG5ld1BhcmFtczsKICAgICAgaWYgKCFmaWx0ZXIpIHsKICAgICAgICBuZXdGaWx0ZXIgPSBOYW1lLmdldCgiRmxhdGVEZWNvZGUiKTsKICAgICAgfSBlbHNlIGlmICghaXNGaWx0ZXJaZXJvRmxhdGVEZWNvZGUpIHsKICAgICAgICBuZXdGaWx0ZXIgPSBBcnJheS5pc0FycmF5KGZpbHRlcikgPyBbTmFtZS5nZXQoIkZsYXRlRGVjb2RlIiksIC4uLmZpbHRlcl0gOiBbTmFtZS5nZXQoIkZsYXRlRGVjb2RlIiksIGZpbHRlcl07CiAgICAgICAgaWYgKHBhcmFtcykgewogICAgICAgICAgbmV3UGFyYW1zID0gQXJyYXkuaXNBcnJheShwYXJhbXMpID8gW251bGwsIC4uLnBhcmFtc10gOiBbbnVsbCwgcGFyYW1zXTsKICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKG5ld0ZpbHRlcikgewogICAgICAgIGRpY3Quc2V0KCJGaWx0ZXIiLCBuZXdGaWx0ZXIpOwogICAgICB9CiAgICAgIGlmIChuZXdQYXJhbXMpIHsKICAgICAgICBkaWN0LnNldCgiRGVjb2RlUGFybXMiLCBuZXdQYXJhbXMpOwogICAgICB9CiAgICB9IGNhdGNoIChleCkgewogICAgICBpbmZvKGB3cml0ZVN0cmVhbSAtIGNhbm5vdCBjb21wcmVzcyBkYXRhOiAiJHtleH0iLmApOwogICAgfQogIH0KICBsZXQgc3RyaW5nID0gYnl0ZXNUb1N0cmluZyhieXRlcyk7CiAgaWYgKHRyYW5zZm9ybSkgewogICAgc3RyaW5nID0gdHJhbnNmb3JtLmVuY3J5cHRTdHJpbmcoc3RyaW5nKTsKICB9CiAgZGljdC5zZXQoIkxlbmd0aCIsIHN0cmluZy5sZW5ndGgpOwogIGF3YWl0IHdyaXRlRGljdChkaWN0LCBidWZmZXIsIHRyYW5zZm9ybSk7CiAgYnVmZmVyLnB1c2goIiBzdHJlYW1cbiIsIHN0cmluZywgIlxuZW5kc3RyZWFtIik7Cn0KYXN5bmMgZnVuY3Rpb24gd3JpdGVBcnJheShhcnJheSwgYnVmZmVyLCB0cmFuc2Zvcm0pIHsKICBidWZmZXIucHVzaCgiWyIpOwogIGxldCBmaXJzdCA9IHRydWU7CiAgZm9yIChjb25zdCB2YWwgb2YgYXJyYXkpIHsKICAgIGlmICghZmlyc3QpIHsKICAgICAgYnVmZmVyLnB1c2goIiAiKTsKICAgIH0gZWxzZSB7CiAgICAgIGZpcnN0ID0gZmFsc2U7CiAgICB9CiAgICBhd2FpdCB3cml0ZVZhbHVlKHZhbCwgYnVmZmVyLCB0cmFuc2Zvcm0pOwogIH0KICBidWZmZXIucHVzaCgiXSIpOwp9CmFzeW5jIGZ1bmN0aW9uIHdyaXRlVmFsdWUodmFsdWUsIGJ1ZmZlciwgdHJhbnNmb3JtKSB7CiAgaWYgKHZhbHVlIGluc3RhbmNlb2YgTmFtZSkgewogICAgYnVmZmVyLnB1c2goYC8ke2VzY2FwZVBERk5hbWUodmFsdWUubmFtZSl9YCk7CiAgfSBlbHNlIGlmICh2YWx1ZSBpbnN0YW5jZW9mIFJlZikgewogICAgYnVmZmVyLnB1c2goYCR7dmFsdWUubnVtfSAke3ZhbHVlLmdlbn0gUmApOwogIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkgfHwgQXJyYXlCdWZmZXIuaXNWaWV3KHZhbHVlKSkgewogICAgYXdhaXQgd3JpdGVBcnJheSh2YWx1ZSwgYnVmZmVyLCB0cmFuc2Zvcm0pOwogIH0gZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAic3RyaW5nIikgewogICAgaWYgKHRyYW5zZm9ybSkgewogICAgICB2YWx1ZSA9IHRyYW5zZm9ybS5lbmNyeXB0U3RyaW5nKHZhbHVlKTsKICAgIH0KICAgIGJ1ZmZlci5wdXNoKGAoJHtlc2NhcGVTdHJpbmcodmFsdWUpfSlgKTsKICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gIm51bWJlciIpIHsKICAgIGJ1ZmZlci5wdXNoKG51bWJlclRvU3RyaW5nKHZhbHVlKSk7CiAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICJib29sZWFuIikgewogICAgYnVmZmVyLnB1c2godmFsdWUudG9TdHJpbmcoKSk7CiAgfSBlbHNlIGlmICh2YWx1ZSBpbnN0YW5jZW9mIERpY3QpIHsKICAgIGF3YWl0IHdyaXRlRGljdCh2YWx1ZSwgYnVmZmVyLCB0cmFuc2Zvcm0pOwogIH0gZWxzZSBpZiAodmFsdWUgaW5zdGFuY2VvZiBCYXNlU3RyZWFtKSB7CiAgICBhd2FpdCB3cml0ZVN0cmVhbSh2YWx1ZSwgYnVmZmVyLCB0cmFuc2Zvcm0pOwogIH0gZWxzZSBpZiAodmFsdWUgPT09IG51bGwpIHsKICAgIGJ1ZmZlci5wdXNoKCJudWxsIik7CiAgfSBlbHNlIHsKICAgIHdhcm4oYFVuaGFuZGxlZCB2YWx1ZSBpbiB3cml0ZXI6ICR7dHlwZW9mIHZhbHVlfSwgcGxlYXNlIGZpbGUgYSBidWcuYCk7CiAgfQp9CmZ1bmN0aW9uIHdyaXRlSW50KG51bWJlciwgc2l6ZSwgb2Zmc2V0LCBidWZmZXIpIHsKICBmb3IgKGxldCBpID0gc2l6ZSArIG9mZnNldCAtIDE7IGkgPiBvZmZzZXQgLSAxOyBpLS0pIHsKICAgIGJ1ZmZlcltpXSA9IG51bWJlciAmIDB4ZmY7CiAgICBudW1iZXIgPj49IDg7CiAgfQogIHJldHVybiBvZmZzZXQgKyBzaXplOwp9CmZ1bmN0aW9uIHdyaXRlU3RyaW5nKHN0cmluZywgb2Zmc2V0LCBidWZmZXIpIHsKICBjb25zdCBpaSA9IHN0cmluZy5sZW5ndGg7CiAgZm9yIChsZXQgaSA9IDA7IGkgPCBpaTsgaSsrKSB7CiAgICBidWZmZXJbb2Zmc2V0ICsgaV0gPSBzdHJpbmcuY2hhckNvZGVBdChpKSAmIDB4ZmY7CiAgfQogIHJldHVybiBvZmZzZXQgKyBpaTsKfQpmdW5jdGlvbiBjb21wdXRlTUQ1KGZpbGVzaXplLCB4cmVmSW5mbykgewogIGNvbnN0IHRpbWUgPSBNYXRoLmZsb29yKERhdGUubm93KCkgLyAxMDAwKTsKICBjb25zdCBmaWxlbmFtZSA9IHhyZWZJbmZvLmZpbGVuYW1lIHx8ICIiOwogIGNvbnN0IG1kNUJ1ZmZlciA9IFt0aW1lLnRvU3RyaW5nKCksIGZpbGVuYW1lLCBmaWxlc2l6ZS50b1N0cmluZygpLCAuLi54cmVmSW5mby5pbmZvTWFwLnZhbHVlcygpXTsKICBjb25zdCBtZDVCdWZmZXJMZW4gPSBNYXRoLnN1bVByZWNpc2UobWQ1QnVmZmVyLm1hcChzdHIgPT4gc3RyLmxlbmd0aCkpOwogIGNvbnN0IGFycmF5ID0gbmV3IFVpbnQ4QXJyYXkobWQ1QnVmZmVyTGVuKTsKICBsZXQgb2Zmc2V0ID0gMDsKICBmb3IgKGNvbnN0IHN0ciBvZiBtZDVCdWZmZXIpIHsKICAgIG9mZnNldCA9IHdyaXRlU3RyaW5nKHN0ciwgb2Zmc2V0LCBhcnJheSk7CiAgfQogIHJldHVybiBieXRlc1RvU3RyaW5nKGNhbGN1bGF0ZU1ENShhcnJheSwgMCwgYXJyYXkubGVuZ3RoKSk7Cn0KZnVuY3Rpb24gd3JpdGVYRkFEYXRhRm9yQWNyb2Zvcm0oc3RyLCBjaGFuZ2VzKSB7CiAgY29uc3QgeG1sID0gbmV3IFNpbXBsZVhNTFBhcnNlcih7CiAgICBoYXNBdHRyaWJ1dGVzOiB0cnVlCiAgfSkucGFyc2VGcm9tU3RyaW5nKHN0cik7CiAgZm9yIChjb25zdCB7CiAgICB4ZmEKICB9IG9mIGNoYW5nZXMpIHsKICAgIGlmICgheGZhKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQogICAgY29uc3QgewogICAgICBwYXRoLAogICAgICB2YWx1ZQogICAgfSA9IHhmYTsKICAgIGlmICghcGF0aCkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIGNvbnN0IG5vZGVQYXRoID0gcGFyc2VYRkFQYXRoKHBhdGgpOwogICAgbGV0IG5vZGUgPSB4bWwuZG9jdW1lbnRFbGVtZW50LnNlYXJjaE5vZGUobm9kZVBhdGgsIDApOwogICAgaWYgKCFub2RlICYmIG5vZGVQYXRoLmxlbmd0aCA+IDEpIHsKICAgICAgbm9kZSA9IHhtbC5kb2N1bWVudEVsZW1lbnQuc2VhcmNoTm9kZShbbm9kZVBhdGguYXQoLTEpXSwgMCk7CiAgICB9CiAgICBpZiAobm9kZSkgewogICAgICBub2RlLmNoaWxkTm9kZXMgPSBBcnJheS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlLm1hcCh2YWwgPT4gbmV3IFNpbXBsZURPTU5vZGUoInZhbHVlIiwgdmFsKSkgOiBbbmV3IFNpbXBsZURPTU5vZGUoIiN0ZXh0IiwgdmFsdWUpXTsKICAgIH0gZWxzZSB7CiAgICAgIHdhcm4oYE5vZGUgbm90IGZvdW5kIGZvciBwYXRoOiAke3BhdGh9YCk7CiAgICB9CiAgfQogIGNvbnN0IGJ1ZmZlciA9IFtdOwogIHhtbC5kb2N1bWVudEVsZW1lbnQuZHVtcChidWZmZXIpOwogIHJldHVybiBidWZmZXIuam9pbigiIik7Cn0KYXN5bmMgZnVuY3Rpb24gdXBkYXRlQWNyb2Zvcm0oewogIHhyZWYsCiAgYWNyb0Zvcm0sCiAgYWNyb0Zvcm1SZWYsCiAgaGFzWGZhLAogIGhhc1hmYURhdGFzZXRzRW50cnksCiAgeGZhRGF0YXNldHNSZWYsCiAgbmVlZEFwcGVhcmFuY2VzLAogIGNoYW5nZXMKfSkgewogIGlmIChoYXNYZmEgJiYgIWhhc1hmYURhdGFzZXRzRW50cnkgJiYgIXhmYURhdGFzZXRzUmVmKSB7CiAgICB3YXJuKCJYRkEgLSBDYW5ub3Qgc2F2ZSBpdCIpOwogIH0KICBpZiAoIW5lZWRBcHBlYXJhbmNlcyAmJiAoIWhhc1hmYSB8fCAheGZhRGF0YXNldHNSZWYgfHwgaGFzWGZhRGF0YXNldHNFbnRyeSkpIHsKICAgIHJldHVybjsKICB9CiAgY29uc3QgZGljdCA9IGFjcm9Gb3JtLmNsb25lKCk7CiAgaWYgKGhhc1hmYSAmJiAhaGFzWGZhRGF0YXNldHNFbnRyeSkgewogICAgY29uc3QgbmV3WGZhID0gYWNyb0Zvcm0uZ2V0KCJYRkEiKS5zbGljZSgpOwogICAgbmV3WGZhLnNwbGljZSgyLCAwLCAiZGF0YXNldHMiKTsKICAgIG5ld1hmYS5zcGxpY2UoMywgMCwgeGZhRGF0YXNldHNSZWYpOwogICAgZGljdC5zZXQoIlhGQSIsIG5ld1hmYSk7CiAgfQogIGlmIChuZWVkQXBwZWFyYW5jZXMpIHsKICAgIGRpY3Quc2V0KCJOZWVkQXBwZWFyYW5jZXMiLCB0cnVlKTsKICB9CiAgY2hhbmdlcy5wdXQoYWNyb0Zvcm1SZWYsIHsKICAgIGRhdGE6IGRpY3QKICB9KTsKfQpmdW5jdGlvbiB1cGRhdGVYRkEoewogIHhmYURhdGEsCiAgeGZhRGF0YXNldHNSZWYsCiAgY2hhbmdlcywKICB4cmVmCn0pIHsKICBpZiAoeGZhRGF0YSA9PT0gbnVsbCkgewogICAgY29uc3QgZGF0YXNldHMgPSB4cmVmLmZldGNoSWZSZWYoeGZhRGF0YXNldHNSZWYpOwogICAgeGZhRGF0YSA9IHdyaXRlWEZBRGF0YUZvckFjcm9mb3JtKGRhdGFzZXRzLmdldFN0cmluZygpLCBjaGFuZ2VzKTsKICB9CiAgY29uc3QgeGZhRGF0YVN0cmVhbSA9IG5ldyBTdHJpbmdTdHJlYW0oeGZhRGF0YSk7CiAgeGZhRGF0YVN0cmVhbS5kaWN0ID0gbmV3IERpY3QoeHJlZik7CiAgeGZhRGF0YVN0cmVhbS5kaWN0LnNldElmTmFtZSgiVHlwZSIsICJFbWJlZGRlZEZpbGUiKTsKICBjaGFuZ2VzLnB1dCh4ZmFEYXRhc2V0c1JlZiwgewogICAgZGF0YTogeGZhRGF0YVN0cmVhbQogIH0pOwp9CmFzeW5jIGZ1bmN0aW9uIGdldFhSZWZUYWJsZSh4cmVmSW5mbywgYmFzZU9mZnNldCwgbmV3UmVmcywgbmV3WHJlZiwgYnVmZmVyKSB7CiAgYnVmZmVyLnB1c2goInhyZWZcbiIpOwogIGNvbnN0IGluZGV4ZXMgPSBnZXRJbmRleGVzKG5ld1JlZnMpOwogIGxldCBpbmRleGVzUG9zaXRpb24gPSAwOwogIGZvciAoY29uc3QgewogICAgcmVmLAogICAgZGF0YQogIH0gb2YgbmV3UmVmcykgewogICAgaWYgKHJlZi5udW0gPT09IGluZGV4ZXNbaW5kZXhlc1Bvc2l0aW9uXSkgewogICAgICBidWZmZXIucHVzaChgJHtpbmRleGVzW2luZGV4ZXNQb3NpdGlvbl19ICR7aW5kZXhlc1tpbmRleGVzUG9zaXRpb24gKyAxXX1cbmApOwogICAgICBpbmRleGVzUG9zaXRpb24gKz0gMjsKICAgIH0KICAgIGlmIChkYXRhICE9PSBudWxsKSB7CiAgICAgIGJ1ZmZlci5wdXNoKGAke2Jhc2VPZmZzZXQudG9TdHJpbmcoKS5wYWRTdGFydCgxMCwgIjAiKX0gJHtNYXRoLm1pbihyZWYuZ2VuLCAweGZmZmYpLnRvU3RyaW5nKCkucGFkU3RhcnQoNSwgIjAiKX0gblxyXG5gKTsKICAgICAgYmFzZU9mZnNldCArPSBkYXRhLmxlbmd0aDsKICAgIH0gZWxzZSB7CiAgICAgIGJ1ZmZlci5wdXNoKGAwMDAwMDAwMDAwICR7TWF0aC5taW4ocmVmLmdlbiArIDEsIDB4ZmZmZikudG9TdHJpbmcoKS5wYWRTdGFydCg1LCAiMCIpfSBmXHJcbmApOwogICAgfQogIH0KICBjb21wdXRlSURzKGJhc2VPZmZzZXQsIHhyZWZJbmZvLCBuZXdYcmVmKTsKICBidWZmZXIucHVzaCgidHJhaWxlclxuIik7CiAgYXdhaXQgd3JpdGVEaWN0KG5ld1hyZWYsIGJ1ZmZlcik7CiAgYnVmZmVyLnB1c2goIlxuc3RhcnR4cmVmXG4iLCBiYXNlT2Zmc2V0LnRvU3RyaW5nKCksICJcbiUlRU9GXG4iKTsKfQpmdW5jdGlvbiBnZXRJbmRleGVzKG5ld1JlZnMpIHsKICBjb25zdCBpbmRleGVzID0gW107CiAgZm9yIChjb25zdCB7CiAgICByZWYKICB9IG9mIG5ld1JlZnMpIHsKICAgIGlmIChyZWYubnVtID09PSBpbmRleGVzLmF0KC0yKSArIGluZGV4ZXMuYXQoLTEpKSB7CiAgICAgIGluZGV4ZXNbaW5kZXhlcy5sZW5ndGggLSAxXSArPSAxOwogICAgfSBlbHNlIHsKICAgICAgaW5kZXhlcy5wdXNoKHJlZi5udW0sIDEpOwogICAgfQogIH0KICByZXR1cm4gaW5kZXhlczsKfQphc3luYyBmdW5jdGlvbiBnZXRYUmVmU3RyZWFtVGFibGUoeHJlZkluZm8sIGJhc2VPZmZzZXQsIG5ld1JlZnMsIG5ld1hyZWYsIGJ1ZmZlcikgewogIGNvbnN0IHhyZWZUYWJsZURhdGEgPSBbXTsKICBsZXQgbWF4T2Zmc2V0ID0gMDsKICBsZXQgbWF4R2VuID0gMDsKICBmb3IgKGNvbnN0IHsKICAgIHJlZiwKICAgIGRhdGEKICB9IG9mIG5ld1JlZnMpIHsKICAgIGxldCBnZW47CiAgICBtYXhPZmZzZXQgPSBNYXRoLm1heChtYXhPZmZzZXQsIGJhc2VPZmZzZXQpOwogICAgaWYgKGRhdGEgIT09IG51bGwpIHsKICAgICAgZ2VuID0gTWF0aC5taW4ocmVmLmdlbiwgMHhmZmZmKTsKICAgICAgeHJlZlRhYmxlRGF0YS5wdXNoKFsxLCBiYXNlT2Zmc2V0LCBnZW5dKTsKICAgICAgYmFzZU9mZnNldCArPSBkYXRhLmxlbmd0aDsKICAgIH0gZWxzZSB7CiAgICAgIGdlbiA9IE1hdGgubWluKHJlZi5nZW4gKyAxLCAweGZmZmYpOwogICAgICB4cmVmVGFibGVEYXRhLnB1c2goWzAsIDAsIGdlbl0pOwogICAgfQogICAgbWF4R2VuID0gTWF0aC5tYXgobWF4R2VuLCBnZW4pOwogIH0KICBuZXdYcmVmLnNldCgiSW5kZXgiLCBnZXRJbmRleGVzKG5ld1JlZnMpKTsKICBjb25zdCBvZmZzZXRTaXplID0gZ2V0U2l6ZUluQnl0ZXMobWF4T2Zmc2V0KTsKICBjb25zdCBtYXhHZW5TaXplID0gZ2V0U2l6ZUluQnl0ZXMobWF4R2VuKTsKICBjb25zdCBzaXplcyA9IFsxLCBvZmZzZXRTaXplLCBtYXhHZW5TaXplXTsKICBuZXdYcmVmLnNldCgiVyIsIHNpemVzKTsKICBjb21wdXRlSURzKGJhc2VPZmZzZXQsIHhyZWZJbmZvLCBuZXdYcmVmKTsKICBjb25zdCBzdHJ1Y3RTaXplID0gTWF0aC5zdW1QcmVjaXNlKHNpemVzKTsKICBjb25zdCBkYXRhID0gbmV3IFVpbnQ4QXJyYXkoc3RydWN0U2l6ZSAqIHhyZWZUYWJsZURhdGEubGVuZ3RoKTsKICBjb25zdCBzdHJlYW0gPSBuZXcgU3RyZWFtKGRhdGEpOwogIHN0cmVhbS5kaWN0ID0gbmV3WHJlZjsKICBsZXQgb2Zmc2V0ID0gMDsKICBmb3IgKGNvbnN0IFt0eXBlLCBvYmpPZmZzZXQsIGdlbl0gb2YgeHJlZlRhYmxlRGF0YSkgewogICAgb2Zmc2V0ID0gd3JpdGVJbnQodHlwZSwgc2l6ZXNbMF0sIG9mZnNldCwgZGF0YSk7CiAgICBvZmZzZXQgPSB3cml0ZUludChvYmpPZmZzZXQsIHNpemVzWzFdLCBvZmZzZXQsIGRhdGEpOwogICAgb2Zmc2V0ID0gd3JpdGVJbnQoZ2VuLCBzaXplc1syXSwgb2Zmc2V0LCBkYXRhKTsKICB9CiAgYXdhaXQgd3JpdGVPYmplY3QoeHJlZkluZm8ubmV3UmVmLCBzdHJlYW0sIGJ1ZmZlciwge30pOwogIGJ1ZmZlci5wdXNoKCJzdGFydHhyZWZcbiIsIGJhc2VPZmZzZXQudG9TdHJpbmcoKSwgIlxuJSVFT0ZcbiIpOwp9CmZ1bmN0aW9uIGNvbXB1dGVJRHMoYmFzZU9mZnNldCwgeHJlZkluZm8sIG5ld1hyZWYpIHsKICBpZiAoQXJyYXkuaXNBcnJheSh4cmVmSW5mby5maWxlSWRzKSAmJiB4cmVmSW5mby5maWxlSWRzLmxlbmd0aCA+IDApIHsKICAgIGNvbnN0IG1kNSA9IGNvbXB1dGVNRDUoYmFzZU9mZnNldCwgeHJlZkluZm8pOwogICAgbmV3WHJlZi5zZXQoIklEIiwgW3hyZWZJbmZvLmZpbGVJZHNbMF0sIG1kNV0pOwogIH0KfQpmdW5jdGlvbiBnZXRUcmFpbGVyRGljdCh4cmVmSW5mbywgY2hhbmdlcywgdXNlWHJlZlN0cmVhbSkgewogIGNvbnN0IG5ld1hyZWYgPSBuZXcgRGljdChudWxsKTsKICBuZXdYcmVmLnNldCgiUHJldiIsIHhyZWZJbmZvLnN0YXJ0WFJlZik7CiAgY29uc3QgcmVmRm9yWHJlZlRhYmxlID0geHJlZkluZm8ubmV3UmVmOwogIGlmICh1c2VYcmVmU3RyZWFtKSB7CiAgICBjaGFuZ2VzLnB1dChyZWZGb3JYcmVmVGFibGUsIHsKICAgICAgZGF0YTogIiIKICAgIH0pOwogICAgbmV3WHJlZi5zZXQoIlNpemUiLCByZWZGb3JYcmVmVGFibGUubnVtICsgMSk7CiAgICBuZXdYcmVmLnNldElmTmFtZSgiVHlwZSIsICJYUmVmIik7CiAgfSBlbHNlIHsKICAgIG5ld1hyZWYuc2V0KCJTaXplIiwgcmVmRm9yWHJlZlRhYmxlLm51bSk7CiAgfQogIGlmICh4cmVmSW5mby5yb290UmVmICE9PSBudWxsKSB7CiAgICBuZXdYcmVmLnNldCgiUm9vdCIsIHhyZWZJbmZvLnJvb3RSZWYpOwogIH0KICBpZiAoeHJlZkluZm8uaW5mb1JlZiAhPT0gbnVsbCkgewogICAgbmV3WHJlZi5zZXQoIkluZm8iLCB4cmVmSW5mby5pbmZvUmVmKTsKICB9CiAgaWYgKHhyZWZJbmZvLmVuY3J5cHRSZWYgIT09IG51bGwpIHsKICAgIG5ld1hyZWYuc2V0KCJFbmNyeXB0IiwgeHJlZkluZm8uZW5jcnlwdFJlZik7CiAgfQogIHJldHVybiBuZXdYcmVmOwp9CmFzeW5jIGZ1bmN0aW9uIHdyaXRlQ2hhbmdlcyhjaGFuZ2VzLCB4cmVmLCBidWZmZXIgPSBbXSkgewogIGNvbnN0IG5ld1JlZnMgPSBbXTsKICBmb3IgKGNvbnN0IFtyZWYsIHsKICAgIGRhdGEKICB9XSBvZiBjaGFuZ2VzLml0ZW1zKCkpIHsKICAgIGlmIChkYXRhID09PSBudWxsIHx8IHR5cGVvZiBkYXRhID09PSAic3RyaW5nIikgewogICAgICBuZXdSZWZzLnB1c2goewogICAgICAgIHJlZiwKICAgICAgICBkYXRhCiAgICAgIH0pOwogICAgICBjb250aW51ZTsKICAgIH0KICAgIGF3YWl0IHdyaXRlT2JqZWN0KHJlZiwgZGF0YSwgYnVmZmVyLCB4cmVmKTsKICAgIG5ld1JlZnMucHVzaCh7CiAgICAgIHJlZiwKICAgICAgZGF0YTogYnVmZmVyLmpvaW4oIiIpCiAgICB9KTsKICAgIGJ1ZmZlci5sZW5ndGggPSAwOwogIH0KICByZXR1cm4gbmV3UmVmcy5zb3J0KChhLCBiKSA9PiBhLnJlZi5udW0gLSBiLnJlZi5udW0pOwp9CmFzeW5jIGZ1bmN0aW9uIGluY3JlbWVudGFsVXBkYXRlKHsKICBvcmlnaW5hbERhdGEsCiAgeHJlZkluZm8sCiAgY2hhbmdlcywKICB4cmVmID0gbnVsbCwKICBoYXNYZmEgPSBmYWxzZSwKICB4ZmFEYXRhc2V0c1JlZiA9IG51bGwsCiAgaGFzWGZhRGF0YXNldHNFbnRyeSA9IGZhbHNlLAogIG5lZWRBcHBlYXJhbmNlcywKICBhY3JvRm9ybVJlZiA9IG51bGwsCiAgYWNyb0Zvcm0gPSBudWxsLAogIHhmYURhdGEgPSBudWxsLAogIHVzZVhyZWZTdHJlYW0gPSBmYWxzZQp9KSB7CiAgYXdhaXQgdXBkYXRlQWNyb2Zvcm0oewogICAgeHJlZiwKICAgIGFjcm9Gb3JtLAogICAgYWNyb0Zvcm1SZWYsCiAgICBoYXNYZmEsCiAgICBoYXNYZmFEYXRhc2V0c0VudHJ5LAogICAgeGZhRGF0YXNldHNSZWYsCiAgICBuZWVkQXBwZWFyYW5jZXMsCiAgICBjaGFuZ2VzCiAgfSk7CiAgaWYgKGhhc1hmYSkgewogICAgdXBkYXRlWEZBKHsKICAgICAgeGZhRGF0YSwKICAgICAgeGZhRGF0YXNldHNSZWYsCiAgICAgIGNoYW5nZXMsCiAgICAgIHhyZWYKICAgIH0pOwogIH0KICBjb25zdCBuZXdYcmVmID0gZ2V0VHJhaWxlckRpY3QoeHJlZkluZm8sIGNoYW5nZXMsIHVzZVhyZWZTdHJlYW0pOwogIGNvbnN0IGJ1ZmZlciA9IFtdOwogIGNvbnN0IG5ld1JlZnMgPSBhd2FpdCB3cml0ZUNoYW5nZXMoY2hhbmdlcywgeHJlZiwgYnVmZmVyKTsKICBsZXQgYmFzZU9mZnNldCA9IG9yaWdpbmFsRGF0YS5sZW5ndGg7CiAgY29uc3QgbGFzdEJ5dGUgPSBvcmlnaW5hbERhdGEuYXQoLTEpOwogIGlmIChsYXN0Qnl0ZSAhPT0gMHgwYSAmJiBsYXN0Qnl0ZSAhPT0gMHgwZCkgewogICAgYnVmZmVyLnB1c2goIlxuIik7CiAgICBiYXNlT2Zmc2V0ICs9IDE7CiAgfQogIGZvciAoY29uc3QgewogICAgZGF0YQogIH0gb2YgbmV3UmVmcykgewogICAgaWYgKGRhdGEgIT09IG51bGwpIHsKICAgICAgYnVmZmVyLnB1c2goZGF0YSk7CiAgICB9CiAgfQogIGF3YWl0ICh1c2VYcmVmU3RyZWFtID8gZ2V0WFJlZlN0cmVhbVRhYmxlKHhyZWZJbmZvLCBiYXNlT2Zmc2V0LCBuZXdSZWZzLCBuZXdYcmVmLCBidWZmZXIpIDogZ2V0WFJlZlRhYmxlKHhyZWZJbmZvLCBiYXNlT2Zmc2V0LCBuZXdSZWZzLCBuZXdYcmVmLCBidWZmZXIpKTsKICBjb25zdCB0b3RhbExlbmd0aCA9IG9yaWdpbmFsRGF0YS5sZW5ndGggKyBNYXRoLnN1bVByZWNpc2UoYnVmZmVyLm1hcChzdHIgPT4gc3RyLmxlbmd0aCkpOwogIGNvbnN0IGFycmF5ID0gbmV3IFVpbnQ4QXJyYXkodG90YWxMZW5ndGgpOwogIGFycmF5LnNldChvcmlnaW5hbERhdGEpOwogIGxldCBvZmZzZXQgPSBvcmlnaW5hbERhdGEubGVuZ3RoOwogIGZvciAoY29uc3Qgc3RyIG9mIGJ1ZmZlcikgewogICAgb2Zmc2V0ID0gd3JpdGVTdHJpbmcoc3RyLCBvZmZzZXQsIGFycmF5KTsKICB9CiAgcmV0dXJuIGFycmF5Owp9Cgo7Ly8gLi9zcmMvY29yZS93b3JrZXJfc3RyZWFtLmpzCgoKY2xhc3MgUERGV29ya2VyU3RyZWFtIHsKICBjb25zdHJ1Y3Rvcihtc2dIYW5kbGVyKSB7CiAgICB0aGlzLl9tc2dIYW5kbGVyID0gbXNnSGFuZGxlcjsKICAgIHRoaXMuX2NvbnRlbnRMZW5ndGggPSBudWxsOwogICAgdGhpcy5fZnVsbFJlcXVlc3RSZWFkZXIgPSBudWxsOwogICAgdGhpcy5fcmFuZ2VSZXF1ZXN0UmVhZGVycyA9IFtdOwogIH0KICBnZXRGdWxsUmVhZGVyKCkgewogICAgYXNzZXJ0KCF0aGlzLl9mdWxsUmVxdWVzdFJlYWRlciwgIlBERldvcmtlclN0cmVhbS5nZXRGdWxsUmVhZGVyIGNhbiBvbmx5IGJlIGNhbGxlZCBvbmNlLiIpOwogICAgdGhpcy5fZnVsbFJlcXVlc3RSZWFkZXIgPSBuZXcgUERGV29ya2VyU3RyZWFtUmVhZGVyKHRoaXMuX21zZ0hhbmRsZXIpOwogICAgcmV0dXJuIHRoaXMuX2Z1bGxSZXF1ZXN0UmVhZGVyOwogIH0KICBnZXRSYW5nZVJlYWRlcihiZWdpbiwgZW5kKSB7CiAgICBjb25zdCByZWFkZXIgPSBuZXcgUERGV29ya2VyU3RyZWFtUmFuZ2VSZWFkZXIoYmVnaW4sIGVuZCwgdGhpcy5fbXNnSGFuZGxlcik7CiAgICB0aGlzLl9yYW5nZVJlcXVlc3RSZWFkZXJzLnB1c2gocmVhZGVyKTsKICAgIHJldHVybiByZWFkZXI7CiAgfQogIGNhbmNlbEFsbFJlcXVlc3RzKHJlYXNvbikgewogICAgdGhpcy5fZnVsbFJlcXVlc3RSZWFkZXI/LmNhbmNlbChyZWFzb24pOwogICAgZm9yIChjb25zdCByZWFkZXIgb2YgdGhpcy5fcmFuZ2VSZXF1ZXN0UmVhZGVycy5zbGljZSgwKSkgewogICAgICByZWFkZXIuY2FuY2VsKHJlYXNvbik7CiAgICB9CiAgfQp9CmNsYXNzIFBERldvcmtlclN0cmVhbVJlYWRlciB7CiAgY29uc3RydWN0b3IobXNnSGFuZGxlcikgewogICAgdGhpcy5fbXNnSGFuZGxlciA9IG1zZ0hhbmRsZXI7CiAgICB0aGlzLm9uUHJvZ3Jlc3MgPSBudWxsOwogICAgdGhpcy5fY29udGVudExlbmd0aCA9IG51bGw7CiAgICB0aGlzLl9pc1JhbmdlU3VwcG9ydGVkID0gZmFsc2U7CiAgICB0aGlzLl9pc1N0cmVhbWluZ1N1cHBvcnRlZCA9IGZhbHNlOwogICAgY29uc3QgcmVhZGFibGVTdHJlYW0gPSB0aGlzLl9tc2dIYW5kbGVyLnNlbmRXaXRoU3RyZWFtKCJHZXRSZWFkZXIiKTsKICAgIHRoaXMuX3JlYWRlciA9IHJlYWRhYmxlU3RyZWFtLmdldFJlYWRlcigpOwogICAgdGhpcy5faGVhZGVyc1JlYWR5ID0gdGhpcy5fbXNnSGFuZGxlci5zZW5kV2l0aFByb21pc2UoIlJlYWRlckhlYWRlcnNSZWFkeSIpLnRoZW4oZGF0YSA9PiB7CiAgICAgIHRoaXMuX2lzU3RyZWFtaW5nU3VwcG9ydGVkID0gZGF0YS5pc1N0cmVhbWluZ1N1cHBvcnRlZDsKICAgICAgdGhpcy5faXNSYW5nZVN1cHBvcnRlZCA9IGRhdGEuaXNSYW5nZVN1cHBvcnRlZDsKICAgICAgdGhpcy5fY29udGVudExlbmd0aCA9IGRhdGEuY29udGVudExlbmd0aDsKICAgIH0pOwogIH0KICBnZXQgaGVhZGVyc1JlYWR5KCkgewogICAgcmV0dXJuIHRoaXMuX2hlYWRlcnNSZWFkeTsKICB9CiAgZ2V0IGNvbnRlbnRMZW5ndGgoKSB7CiAgICByZXR1cm4gdGhpcy5fY29udGVudExlbmd0aDsKICB9CiAgZ2V0IGlzU3RyZWFtaW5nU3VwcG9ydGVkKCkgewogICAgcmV0dXJuIHRoaXMuX2lzU3RyZWFtaW5nU3VwcG9ydGVkOwogIH0KICBnZXQgaXNSYW5nZVN1cHBvcnRlZCgpIHsKICAgIHJldHVybiB0aGlzLl9pc1JhbmdlU3VwcG9ydGVkOwogIH0KICBhc3luYyByZWFkKCkgewogICAgY29uc3QgewogICAgICB2YWx1ZSwKICAgICAgZG9uZQogICAgfSA9IGF3YWl0IHRoaXMuX3JlYWRlci5yZWFkKCk7CiAgICBpZiAoZG9uZSkgewogICAgICByZXR1cm4gewogICAgICAgIHZhbHVlOiB1bmRlZmluZWQsCiAgICAgICAgZG9uZTogdHJ1ZQogICAgICB9OwogICAgfQogICAgcmV0dXJuIHsKICAgICAgdmFsdWU6IHZhbHVlLmJ1ZmZlciwKICAgICAgZG9uZTogZmFsc2UKICAgIH07CiAgfQogIGNhbmNlbChyZWFzb24pIHsKICAgIHRoaXMuX3JlYWRlci5jYW5jZWwocmVhc29uKTsKICB9Cn0KY2xhc3MgUERGV29ya2VyU3RyZWFtUmFuZ2VSZWFkZXIgewogIGNvbnN0cnVjdG9yKGJlZ2luLCBlbmQsIG1zZ0hhbmRsZXIpIHsKICAgIHRoaXMuX21zZ0hhbmRsZXIgPSBtc2dIYW5kbGVyOwogICAgdGhpcy5vblByb2dyZXNzID0gbnVsbDsKICAgIGNvbnN0IHJlYWRhYmxlU3RyZWFtID0gdGhpcy5fbXNnSGFuZGxlci5zZW5kV2l0aFN0cmVhbSgiR2V0UmFuZ2VSZWFkZXIiLCB7CiAgICAgIGJlZ2luLAogICAgICBlbmQKICAgIH0pOwogICAgdGhpcy5fcmVhZGVyID0gcmVhZGFibGVTdHJlYW0uZ2V0UmVhZGVyKCk7CiAgfQogIGdldCBpc1N0cmVhbWluZ1N1cHBvcnRlZCgpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CiAgYXN5bmMgcmVhZCgpIHsKICAgIGNvbnN0IHsKICAgICAgdmFsdWUsCiAgICAgIGRvbmUKICAgIH0gPSBhd2FpdCB0aGlzLl9yZWFkZXIucmVhZCgpOwogICAgaWYgKGRvbmUpIHsKICAgICAgcmV0dXJuIHsKICAgICAgICB2YWx1ZTogdW5kZWZpbmVkLAogICAgICAgIGRvbmU6IHRydWUKICAgICAgfTsKICAgIH0KICAgIHJldHVybiB7CiAgICAgIHZhbHVlOiB2YWx1ZS5idWZmZXIsCiAgICAgIGRvbmU6IGZhbHNlCiAgICB9OwogIH0KICBjYW5jZWwocmVhc29uKSB7CiAgICB0aGlzLl9yZWFkZXIuY2FuY2VsKHJlYXNvbik7CiAgfQp9Cgo7Ly8gLi9zcmMvY29yZS93b3JrZXIuanMKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgpjbGFzcyBXb3JrZXJUYXNrIHsKICBjb25zdHJ1Y3RvcihuYW1lKSB7CiAgICB0aGlzLm5hbWUgPSBuYW1lOwogICAgdGhpcy50ZXJtaW5hdGVkID0gZmFsc2U7CiAgICB0aGlzLl9jYXBhYmlsaXR5ID0gUHJvbWlzZS53aXRoUmVzb2x2ZXJzKCk7CiAgfQogIGdldCBmaW5pc2hlZCgpIHsKICAgIHJldHVybiB0aGlzLl9jYXBhYmlsaXR5LnByb21pc2U7CiAgfQogIGZpbmlzaCgpIHsKICAgIHRoaXMuX2NhcGFiaWxpdHkucmVzb2x2ZSgpOwogIH0KICB0ZXJtaW5hdGUoKSB7CiAgICB0aGlzLnRlcm1pbmF0ZWQgPSB0cnVlOwogIH0KICBlbnN1cmVOb3RUZXJtaW5hdGVkKCkgewogICAgaWYgKHRoaXMudGVybWluYXRlZCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoIldvcmtlciB0YXNrIHdhcyB0ZXJtaW5hdGVkIik7CiAgICB9CiAgfQp9CmNsYXNzIFdvcmtlck1lc3NhZ2VIYW5kbGVyIHsKICBzdGF0aWMgewogICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICJ1bmRlZmluZWQiICYmICFpc05vZGVKUyAmJiB0eXBlb2Ygc2VsZiAhPT0gInVuZGVmaW5lZCIgJiYgdHlwZW9mIHNlbGYucG9zdE1lc3NhZ2UgPT09ICJmdW5jdGlvbiIgJiYgIm9ubWVzc2FnZSIgaW4gc2VsZikgewogICAgICB0aGlzLmluaXRpYWxpemVGcm9tUG9ydChzZWxmKTsKICAgIH0KICB9CiAgc3RhdGljIHNldHVwKGhhbmRsZXIsIHBvcnQpIHsKICAgIGxldCB0ZXN0TWVzc2FnZVByb2Nlc3NlZCA9IGZhbHNlOwogICAgaGFuZGxlci5vbigidGVzdCIsIGRhdGEgPT4gewogICAgICBpZiAodGVzdE1lc3NhZ2VQcm9jZXNzZWQpIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KICAgICAgdGVzdE1lc3NhZ2VQcm9jZXNzZWQgPSB0cnVlOwogICAgICBoYW5kbGVyLnNlbmQoInRlc3QiLCBkYXRhIGluc3RhbmNlb2YgVWludDhBcnJheSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oImNvbmZpZ3VyZSIsIGRhdGEgPT4gewogICAgICBzZXRWZXJib3NpdHlMZXZlbChkYXRhLnZlcmJvc2l0eSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldERvY1JlcXVlc3QiLCBkYXRhID0+IHRoaXMuY3JlYXRlRG9jdW1lbnRIYW5kbGVyKGRhdGEsIHBvcnQpKTsKICB9CiAgc3RhdGljIGNyZWF0ZURvY3VtZW50SGFuZGxlcihkb2NQYXJhbXMsIHBvcnQpIHsKICAgIGxldCBwZGZNYW5hZ2VyOwogICAgbGV0IHRlcm1pbmF0ZWQgPSBmYWxzZTsKICAgIGxldCBjYW5jZWxYSFJzID0gbnVsbDsKICAgIGNvbnN0IFdvcmtlclRhc2tzID0gbmV3IFNldCgpOwogICAgY29uc3QgdmVyYm9zaXR5ID0gZ2V0VmVyYm9zaXR5TGV2ZWwoKTsKICAgIGNvbnN0IHsKICAgICAgZG9jSWQsCiAgICAgIGFwaVZlcnNpb24KICAgIH0gPSBkb2NQYXJhbXM7CiAgICBjb25zdCB3b3JrZXJWZXJzaW9uID0gIjUuNC4yOTYiOwogICAgaWYgKGFwaVZlcnNpb24gIT09IHdvcmtlclZlcnNpb24pIHsKICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgQVBJIHZlcnNpb24gIiR7YXBpVmVyc2lvbn0iIGRvZXMgbm90IG1hdGNoIGAgKyBgdGhlIFdvcmtlciB2ZXJzaW9uICIke3dvcmtlclZlcnNpb259Ii5gKTsKICAgIH0KICAgIGNvbnN0IGJ1aWxkTXNnID0gKHR5cGUsIHByb3ApID0+IGBUaGUgXGAke3R5cGV9LnByb3RvdHlwZVxgIGNvbnRhaW5zIHVuZXhwZWN0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0eSBgICsgYCIke3Byb3B9IiwgdGh1cyBicmVha2luZyBlLmcuIFxgZm9yLi4uaW5cYCBpdGVyYXRpb24gb2YgJHt0eXBlfXMuYDsKICAgIGZvciAoY29uc3QgcHJvcCBpbiB7fSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoYnVpbGRNc2coIk9iamVjdCIsIHByb3ApKTsKICAgIH0KICAgIGZvciAoY29uc3QgcHJvcCBpbiBbXSkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoYnVpbGRNc2coIkFycmF5IiwgcHJvcCkpOwogICAgfQogICAgY29uc3Qgd29ya2VySGFuZGxlck5hbWUgPSBkb2NJZCArICJfd29ya2VyIjsKICAgIGxldCBoYW5kbGVyID0gbmV3IE1lc3NhZ2VIYW5kbGVyKHdvcmtlckhhbmRsZXJOYW1lLCBkb2NJZCwgcG9ydCk7CiAgICBmdW5jdGlvbiBlbnN1cmVOb3RUZXJtaW5hdGVkKCkgewogICAgICBpZiAodGVybWluYXRlZCkgewogICAgICAgIHRocm93IG5ldyBFcnJvcigiV29ya2VyIHdhcyB0ZXJtaW5hdGVkIik7CiAgICAgIH0KICAgIH0KICAgIGZ1bmN0aW9uIHN0YXJ0V29ya2VyVGFzayh0YXNrKSB7CiAgICAgIFdvcmtlclRhc2tzLmFkZCh0YXNrKTsKICAgIH0KICAgIGZ1bmN0aW9uIGZpbmlzaFdvcmtlclRhc2sodGFzaykgewogICAgICB0YXNrLmZpbmlzaCgpOwogICAgICBXb3JrZXJUYXNrcy5kZWxldGUodGFzayk7CiAgICB9CiAgICBhc3luYyBmdW5jdGlvbiBsb2FkRG9jdW1lbnQocmVjb3ZlcnlNb2RlKSB7CiAgICAgIGF3YWl0IHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJjaGVja0hlYWRlciIpOwogICAgICBhd2FpdCBwZGZNYW5hZ2VyLmVuc3VyZURvYygicGFyc2VTdGFydFhSZWYiKTsKICAgICAgYXdhaXQgcGRmTWFuYWdlci5lbnN1cmVEb2MoInBhcnNlIiwgW3JlY292ZXJ5TW9kZV0pOwogICAgICBhd2FpdCBwZGZNYW5hZ2VyLmVuc3VyZURvYygiY2hlY2tGaXJzdFBhZ2UiLCBbcmVjb3ZlcnlNb2RlXSk7CiAgICAgIGF3YWl0IHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJjaGVja0xhc3RQYWdlIiwgW3JlY292ZXJ5TW9kZV0pOwogICAgICBjb25zdCBpc1B1cmVYZmEgPSBhd2FpdCBwZGZNYW5hZ2VyLmVuc3VyZURvYygiaXNQdXJlWGZhIik7CiAgICAgIGlmIChpc1B1cmVYZmEpIHsKICAgICAgICBjb25zdCB0YXNrID0gbmV3IFdvcmtlclRhc2soImxvYWRYZmFSZXNvdXJjZXMiKTsKICAgICAgICBzdGFydFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgYXdhaXQgcGRmTWFuYWdlci5lbnN1cmVEb2MoImxvYWRYZmFSZXNvdXJjZXMiLCBbaGFuZGxlciwgdGFza10pOwogICAgICAgIGZpbmlzaFdvcmtlclRhc2sodGFzayk7CiAgICAgIH0KICAgICAgY29uc3QgW251bVBhZ2VzLCBmaW5nZXJwcmludHNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW3BkZk1hbmFnZXIuZW5zdXJlRG9jKCJudW1QYWdlcyIpLCBwZGZNYW5hZ2VyLmVuc3VyZURvYygiZmluZ2VycHJpbnRzIildKTsKICAgICAgY29uc3QgaHRtbEZvclhmYSA9IGlzUHVyZVhmYSA/IGF3YWl0IHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJodG1sRm9yWGZhIikgOiBudWxsOwogICAgICByZXR1cm4gewogICAgICAgIG51bVBhZ2VzLAogICAgICAgIGZpbmdlcnByaW50cywKICAgICAgICBodG1sRm9yWGZhCiAgICAgIH07CiAgICB9CiAgICBhc3luYyBmdW5jdGlvbiBnZXRQZGZNYW5hZ2VyKHsKICAgICAgZGF0YSwKICAgICAgcGFzc3dvcmQsCiAgICAgIGRpc2FibGVBdXRvRmV0Y2gsCiAgICAgIHJhbmdlQ2h1bmtTaXplLAogICAgICBsZW5ndGgsCiAgICAgIGRvY0Jhc2VVcmwsCiAgICAgIGVuYWJsZVhmYSwKICAgICAgZXZhbHVhdG9yT3B0aW9ucwogICAgfSkgewogICAgICBjb25zdCBwZGZNYW5hZ2VyQXJncyA9IHsKICAgICAgICBzb3VyY2U6IG51bGwsCiAgICAgICAgZGlzYWJsZUF1dG9GZXRjaCwKICAgICAgICBkb2NCYXNlVXJsLAogICAgICAgIGRvY0lkLAogICAgICAgIGVuYWJsZVhmYSwKICAgICAgICBldmFsdWF0b3JPcHRpb25zLAogICAgICAgIGhhbmRsZXIsCiAgICAgICAgbGVuZ3RoLAogICAgICAgIHBhc3N3b3JkLAogICAgICAgIHJhbmdlQ2h1bmtTaXplCiAgICAgIH07CiAgICAgIGlmIChkYXRhKSB7CiAgICAgICAgcGRmTWFuYWdlckFyZ3Muc291cmNlID0gZGF0YTsKICAgICAgICByZXR1cm4gbmV3IExvY2FsUGRmTWFuYWdlcihwZGZNYW5hZ2VyQXJncyk7CiAgICAgIH0KICAgICAgY29uc3QgcGRmU3RyZWFtID0gbmV3IFBERldvcmtlclN0cmVhbShoYW5kbGVyKSwKICAgICAgICBmdWxsUmVxdWVzdCA9IHBkZlN0cmVhbS5nZXRGdWxsUmVhZGVyKCk7CiAgICAgIGNvbnN0IHBkZk1hbmFnZXJDYXBhYmlsaXR5ID0gUHJvbWlzZS53aXRoUmVzb2x2ZXJzKCk7CiAgICAgIGxldCBuZXdQZGZNYW5hZ2VyLAogICAgICAgIGNhY2hlZENodW5rcyA9IFtdLAogICAgICAgIGxvYWRlZCA9IDA7CiAgICAgIGZ1bGxSZXF1ZXN0LmhlYWRlcnNSZWFkeS50aGVuKGZ1bmN0aW9uICgpIHsKICAgICAgICBpZiAoIWZ1bGxSZXF1ZXN0LmlzUmFuZ2VTdXBwb3J0ZWQpIHsKICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICAgICAgcGRmTWFuYWdlckFyZ3Muc291cmNlID0gcGRmU3RyZWFtOwogICAgICAgIHBkZk1hbmFnZXJBcmdzLmxlbmd0aCA9IGZ1bGxSZXF1ZXN0LmNvbnRlbnRMZW5ndGg7CiAgICAgICAgcGRmTWFuYWdlckFyZ3MuZGlzYWJsZUF1dG9GZXRjaCB8fD0gZnVsbFJlcXVlc3QuaXNTdHJlYW1pbmdTdXBwb3J0ZWQ7CiAgICAgICAgbmV3UGRmTWFuYWdlciA9IG5ldyBOZXR3b3JrUGRmTWFuYWdlcihwZGZNYW5hZ2VyQXJncyk7CiAgICAgICAgZm9yIChjb25zdCBjaHVuayBvZiBjYWNoZWRDaHVua3MpIHsKICAgICAgICAgIG5ld1BkZk1hbmFnZXIuc2VuZFByb2dyZXNzaXZlRGF0YShjaHVuayk7CiAgICAgICAgfQogICAgICAgIGNhY2hlZENodW5rcyA9IFtdOwogICAgICAgIHBkZk1hbmFnZXJDYXBhYmlsaXR5LnJlc29sdmUobmV3UGRmTWFuYWdlcik7CiAgICAgICAgY2FuY2VsWEhScyA9IG51bGw7CiAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICBwZGZNYW5hZ2VyQ2FwYWJpbGl0eS5yZWplY3QocmVhc29uKTsKICAgICAgICBjYW5jZWxYSFJzID0gbnVsbDsKICAgICAgfSk7CiAgICAgIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsKICAgICAgICBjb25zdCByZWFkQ2h1bmsgPSBmdW5jdGlvbiAoewogICAgICAgICAgdmFsdWUsCiAgICAgICAgICBkb25lCiAgICAgICAgfSkgewogICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgZW5zdXJlTm90VGVybWluYXRlZCgpOwogICAgICAgICAgICBpZiAoZG9uZSkgewogICAgICAgICAgICAgIGlmICghbmV3UGRmTWFuYWdlcikgewogICAgICAgICAgICAgICAgY29uc3QgcGRmRmlsZSA9IGFycmF5QnVmZmVyc1RvQnl0ZXMoY2FjaGVkQ2h1bmtzKTsKICAgICAgICAgICAgICAgIGNhY2hlZENodW5rcyA9IFtdOwogICAgICAgICAgICAgICAgaWYgKGxlbmd0aCAmJiBwZGZGaWxlLmxlbmd0aCAhPT0gbGVuZ3RoKSB7CiAgICAgICAgICAgICAgICAgIHdhcm4oInJlcG9ydGVkIEhUVFAgbGVuZ3RoIGlzIGRpZmZlcmVudCBmcm9tIGFjdHVhbCIpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgcGRmTWFuYWdlckFyZ3Muc291cmNlID0gcGRmRmlsZTsKICAgICAgICAgICAgICAgIG5ld1BkZk1hbmFnZXIgPSBuZXcgTG9jYWxQZGZNYW5hZ2VyKHBkZk1hbmFnZXJBcmdzKTsKICAgICAgICAgICAgICAgIHBkZk1hbmFnZXJDYXBhYmlsaXR5LnJlc29sdmUobmV3UGRmTWFuYWdlcik7CiAgICAgICAgICAgICAgfQogICAgICAgICAgICAgIGNhbmNlbFhIUnMgPSBudWxsOwogICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgICAgICBsb2FkZWQgKz0gdmFsdWUuYnl0ZUxlbmd0aDsKICAgICAgICAgICAgaWYgKCFmdWxsUmVxdWVzdC5pc1N0cmVhbWluZ1N1cHBvcnRlZCkgewogICAgICAgICAgICAgIGhhbmRsZXIuc2VuZCgiRG9jUHJvZ3Jlc3MiLCB7CiAgICAgICAgICAgICAgICBsb2FkZWQsCiAgICAgICAgICAgICAgICB0b3RhbDogTWF0aC5tYXgobG9hZGVkLCBmdWxsUmVxdWVzdC5jb250ZW50TGVuZ3RoIHx8IDApCiAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKG5ld1BkZk1hbmFnZXIpIHsKICAgICAgICAgICAgICBuZXdQZGZNYW5hZ2VyLnNlbmRQcm9ncmVzc2l2ZURhdGEodmFsdWUpOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgIGNhY2hlZENodW5rcy5wdXNoKHZhbHVlKTsKICAgICAgICAgICAgfQogICAgICAgICAgICBmdWxsUmVxdWVzdC5yZWFkKCkudGhlbihyZWFkQ2h1bmssIHJlamVjdCk7CiAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgIHJlamVjdChlKTsKICAgICAgICAgIH0KICAgICAgICB9OwogICAgICAgIGZ1bGxSZXF1ZXN0LnJlYWQoKS50aGVuKHJlYWRDaHVuaywgcmVqZWN0KTsKICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGUpIHsKICAgICAgICBwZGZNYW5hZ2VyQ2FwYWJpbGl0eS5yZWplY3QoZSk7CiAgICAgICAgY2FuY2VsWEhScyA9IG51bGw7CiAgICAgIH0pOwogICAgICBjYW5jZWxYSFJzID0gcmVhc29uID0+IHsKICAgICAgICBwZGZTdHJlYW0uY2FuY2VsQWxsUmVxdWVzdHMocmVhc29uKTsKICAgICAgfTsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXJDYXBhYmlsaXR5LnByb21pc2U7CiAgICB9CiAgICBmdW5jdGlvbiBzZXR1cERvYyhkYXRhKSB7CiAgICAgIGZ1bmN0aW9uIG9uU3VjY2Vzcyhkb2MpIHsKICAgICAgICBlbnN1cmVOb3RUZXJtaW5hdGVkKCk7CiAgICAgICAgaGFuZGxlci5zZW5kKCJHZXREb2MiLCB7CiAgICAgICAgICBwZGZJbmZvOiBkb2MKICAgICAgICB9KTsKICAgICAgfQogICAgICBmdW5jdGlvbiBvbkZhaWx1cmUoZXgpIHsKICAgICAgICBlbnN1cmVOb3RUZXJtaW5hdGVkKCk7CiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGFzc3dvcmRFeGNlcHRpb24pIHsKICAgICAgICAgIGNvbnN0IHRhc2sgPSBuZXcgV29ya2VyVGFzayhgUGFzc3dvcmRFeGNlcHRpb246IHJlc3BvbnNlICR7ZXguY29kZX1gKTsKICAgICAgICAgIHN0YXJ0V29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgIGhhbmRsZXIuc2VuZFdpdGhQcm9taXNlKCJQYXNzd29yZFJlcXVlc3QiLCBleCkudGhlbihmdW5jdGlvbiAoewogICAgICAgICAgICBwYXNzd29yZAogICAgICAgICAgfSkgewogICAgICAgICAgICBmaW5pc2hXb3JrZXJUYXNrKHRhc2spOwogICAgICAgICAgICBwZGZNYW5hZ2VyLnVwZGF0ZVBhc3N3b3JkKHBhc3N3b3JkKTsKICAgICAgICAgICAgcGRmTWFuYWdlclJlYWR5KCk7CiAgICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAoKSB7CiAgICAgICAgICAgIGZpbmlzaFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgICAgIGhhbmRsZXIuc2VuZCgiRG9jRXhjZXB0aW9uIiwgZXgpOwogICAgICAgICAgfSk7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgIGhhbmRsZXIuc2VuZCgiRG9jRXhjZXB0aW9uIiwgd3JhcFJlYXNvbihleCkpOwogICAgICAgIH0KICAgICAgfQogICAgICBmdW5jdGlvbiBwZGZNYW5hZ2VyUmVhZHkoKSB7CiAgICAgICAgZW5zdXJlTm90VGVybWluYXRlZCgpOwogICAgICAgIGxvYWREb2N1bWVudChmYWxzZSkudGhlbihvblN1Y2Nlc3MsIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgIGVuc3VyZU5vdFRlcm1pbmF0ZWQoKTsKICAgICAgICAgIGlmICghKHJlYXNvbiBpbnN0YW5jZW9mIFhSZWZQYXJzZUV4Y2VwdGlvbikpIHsKICAgICAgICAgICAgb25GYWlsdXJlKHJlYXNvbik7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KICAgICAgICAgIHBkZk1hbmFnZXIucmVxdWVzdExvYWRlZFN0cmVhbSgpLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgICBlbnN1cmVOb3RUZXJtaW5hdGVkKCk7CiAgICAgICAgICAgIGxvYWREb2N1bWVudCh0cnVlKS50aGVuKG9uU3VjY2Vzcywgb25GYWlsdXJlKTsKICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICB9CiAgICAgIGVuc3VyZU5vdFRlcm1pbmF0ZWQoKTsKICAgICAgZ2V0UGRmTWFuYWdlcihkYXRhKS50aGVuKGZ1bmN0aW9uIChuZXdQZGZNYW5hZ2VyKSB7CiAgICAgICAgaWYgKHRlcm1pbmF0ZWQpIHsKICAgICAgICAgIG5ld1BkZk1hbmFnZXIudGVybWluYXRlKG5ldyBBYm9ydEV4Y2VwdGlvbigiV29ya2VyIHdhcyB0ZXJtaW5hdGVkLiIpKTsKICAgICAgICAgIHRocm93IG5ldyBFcnJvcigiV29ya2VyIHdhcyB0ZXJtaW5hdGVkIik7CiAgICAgICAgfQogICAgICAgIHBkZk1hbmFnZXIgPSBuZXdQZGZNYW5hZ2VyOwogICAgICAgIHBkZk1hbmFnZXIucmVxdWVzdExvYWRlZFN0cmVhbSh0cnVlKS50aGVuKHN0cmVhbSA9PiB7CiAgICAgICAgICBoYW5kbGVyLnNlbmQoIkRhdGFMb2FkZWQiLCB7CiAgICAgICAgICAgIGxlbmd0aDogc3RyZWFtLmJ5dGVzLmJ5dGVMZW5ndGgKICAgICAgICAgIH0pOwogICAgICAgIH0pOwogICAgICB9KS50aGVuKHBkZk1hbmFnZXJSZWFkeSwgb25GYWlsdXJlKTsKICAgIH0KICAgIGhhbmRsZXIub24oIkdldFBhZ2UiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5nZXRQYWdlKGRhdGEucGFnZUluZGV4KS50aGVuKGZ1bmN0aW9uIChwYWdlKSB7CiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFtwZGZNYW5hZ2VyLmVuc3VyZShwYWdlLCAicm90YXRlIiksIHBkZk1hbmFnZXIuZW5zdXJlKHBhZ2UsICJyZWYiKSwgcGRmTWFuYWdlci5lbnN1cmUocGFnZSwgInVzZXJVbml0IiksIHBkZk1hbmFnZXIuZW5zdXJlKHBhZ2UsICJ2aWV3IildKS50aGVuKGZ1bmN0aW9uIChbcm90YXRlLCByZWYsIHVzZXJVbml0LCB2aWV3XSkgewogICAgICAgICAgcmV0dXJuIHsKICAgICAgICAgICAgcm90YXRlLAogICAgICAgICAgICByZWYsCiAgICAgICAgICAgIHJlZlN0cjogcmVmPy50b1N0cmluZygpID8/IG51bGwsCiAgICAgICAgICAgIHVzZXJVbml0LAogICAgICAgICAgICB2aWV3CiAgICAgICAgICB9OwogICAgICAgIH0pOwogICAgICB9KTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0UGFnZUluZGV4IiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgY29uc3QgcGFnZVJlZiA9IFJlZi5nZXQoZGF0YS5udW0sIGRhdGEuZ2VuKTsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiZ2V0UGFnZUluZGV4IiwgW3BhZ2VSZWZdKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0RGVzdGluYXRpb25zIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiZGVzdGluYXRpb25zIik7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldERlc3RpbmF0aW9uIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiZ2V0RGVzdGluYXRpb24iLCBbZGF0YS5pZF0pOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRQYWdlTGFiZWxzIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygicGFnZUxhYmVscyIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRQYWdlTGF5b3V0IiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygicGFnZUxheW91dCIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRQYWdlTW9kZSIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coInBhZ2VNb2RlIik7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldFZpZXdlclByZWZlcmVuY2VzIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygidmlld2VyUHJlZmVyZW5jZXMiKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0T3BlbkFjdGlvbiIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coIm9wZW5BY3Rpb24iKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0QXR0YWNobWVudHMiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJhdHRhY2htZW50cyIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXREb2NKU0FjdGlvbnMiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJqc0FjdGlvbnMiKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0UGFnZUpTQWN0aW9ucyIsIGZ1bmN0aW9uICh7CiAgICAgIHBhZ2VJbmRleAogICAgfSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5nZXRQYWdlKHBhZ2VJbmRleCkudGhlbihwYWdlID0+IHBkZk1hbmFnZXIuZW5zdXJlKHBhZ2UsICJqc0FjdGlvbnMiKSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldEFubm90YXRpb25zQnlUeXBlIiwgYXN5bmMgZnVuY3Rpb24gKHsKICAgICAgdHlwZXMsCiAgICAgIHBhZ2VJbmRleGVzVG9Ta2lwCiAgICB9KSB7CiAgICAgIGNvbnN0IFtudW1QYWdlcywgYW5ub3RhdGlvbkdsb2JhbHNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW3BkZk1hbmFnZXIuZW5zdXJlRG9jKCJudW1QYWdlcyIpLCBwZGZNYW5hZ2VyLmVuc3VyZURvYygiYW5ub3RhdGlvbkdsb2JhbHMiKV0pOwogICAgICBpZiAoIWFubm90YXRpb25HbG9iYWxzKSB7CiAgICAgICAgcmV0dXJuIG51bGw7CiAgICAgIH0KICAgICAgY29uc3QgcGFnZVByb21pc2VzID0gW107CiAgICAgIGNvbnN0IGFubm90YXRpb25Qcm9taXNlcyA9IFtdOwogICAgICBsZXQgdGFzayA9IG51bGw7CiAgICAgIHRyeSB7CiAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0gbnVtUGFnZXM7IGkgPCBpaTsgaSsrKSB7CiAgICAgICAgICBpZiAocGFnZUluZGV4ZXNUb1NraXA/LmhhcyhpKSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICAgIH0KICAgICAgICAgIGlmICghdGFzaykgewogICAgICAgICAgICB0YXNrID0gbmV3IFdvcmtlclRhc2soIkdldEFubm90YXRpb25zQnlUeXBlIik7CiAgICAgICAgICAgIHN0YXJ0V29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgIH0KICAgICAgICAgIHBhZ2VQcm9taXNlcy5wdXNoKHBkZk1hbmFnZXIuZ2V0UGFnZShpKS50aGVuKGFzeW5jIHBhZ2UgPT4gewogICAgICAgICAgICBpZiAoIXBhZ2UpIHsKICAgICAgICAgICAgICByZXR1cm4gW107CiAgICAgICAgICAgIH0KICAgICAgICAgICAgcmV0dXJuIHBhZ2UuY29sbGVjdEFubm90YXRpb25zQnlUeXBlKGhhbmRsZXIsIHRhc2ssIHR5cGVzLCBhbm5vdGF0aW9uUHJvbWlzZXMsIGFubm90YXRpb25HbG9iYWxzKSB8fCBbXTsKICAgICAgICAgIH0pKTsKICAgICAgICB9CiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwocGFnZVByb21pc2VzKTsKICAgICAgICBjb25zdCBhbm5vdGF0aW9ucyA9IGF3YWl0IFByb21pc2UuYWxsKGFubm90YXRpb25Qcm9taXNlcyk7CiAgICAgICAgcmV0dXJuIGFubm90YXRpb25zLmZpbHRlcihhID0+ICEhYSk7CiAgICAgIH0gZmluYWxseSB7CiAgICAgICAgaWYgKHRhc2spIHsKICAgICAgICAgIGZpbmlzaFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgfQogICAgICB9CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldE91dGxpbmUiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJkb2N1bWVudE91dGxpbmUiKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0T3B0aW9uYWxDb250ZW50Q29uZmlnIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygib3B0aW9uYWxDb250ZW50Q29uZmlnIik7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldFBlcm1pc3Npb25zIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygicGVybWlzc2lvbnMiKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0TWV0YWRhdGEiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gUHJvbWlzZS5hbGwoW3BkZk1hbmFnZXIuZW5zdXJlRG9jKCJkb2N1bWVudEluZm8iKSwgcGRmTWFuYWdlci5lbnN1cmVDYXRhbG9nKCJtZXRhZGF0YSIpXSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldE1hcmtJbmZvIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygibWFya0luZm8iKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0RGF0YSIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLnJlcXVlc3RMb2FkZWRTdHJlYW0oKS50aGVuKHN0cmVhbSA9PiBzdHJlYW0uYnl0ZXMpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJHZXRBbm5vdGF0aW9ucyIsIGZ1bmN0aW9uICh7CiAgICAgIHBhZ2VJbmRleCwKICAgICAgaW50ZW50CiAgICB9KSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmdldFBhZ2UocGFnZUluZGV4KS50aGVuKGZ1bmN0aW9uIChwYWdlKSB7CiAgICAgICAgY29uc3QgdGFzayA9IG5ldyBXb3JrZXJUYXNrKGBHZXRBbm5vdGF0aW9uczogcGFnZSAke3BhZ2VJbmRleH1gKTsKICAgICAgICBzdGFydFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgcmV0dXJuIHBhZ2UuZ2V0QW5ub3RhdGlvbnNEYXRhKGhhbmRsZXIsIHRhc2ssIGludGVudCkudGhlbihkYXRhID0+IHsKICAgICAgICAgIGZpbmlzaFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgICByZXR1cm4gZGF0YTsKICAgICAgICB9LCByZWFzb24gPT4gewogICAgICAgICAgZmluaXNoV29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgIHRocm93IHJlYXNvbjsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldEZpZWxkT2JqZWN0cyIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZURvYygiZmllbGRPYmplY3RzIikudGhlbihmaWVsZE9iamVjdHMgPT4gZmllbGRPYmplY3RzPy5hbGxGaWVsZHMgfHwgbnVsbCk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkhhc0pTQWN0aW9ucyIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmVuc3VyZURvYygiaGFzSlNBY3Rpb25zIik7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldENhbGN1bGF0aW9uT3JkZXJJZHMiLCBmdW5jdGlvbiAoZGF0YSkgewogICAgICByZXR1cm4gcGRmTWFuYWdlci5lbnN1cmVEb2MoImNhbGN1bGF0aW9uT3JkZXJJZHMiKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiU2F2ZURvY3VtZW50IiwgYXN5bmMgZnVuY3Rpb24gKHsKICAgICAgaXNQdXJlWGZhLAogICAgICBudW1QYWdlcywKICAgICAgYW5ub3RhdGlvblN0b3JhZ2UsCiAgICAgIGZpbGVuYW1lCiAgICB9KSB7CiAgICAgIGNvbnN0IGdsb2JhbFByb21pc2VzID0gW3BkZk1hbmFnZXIucmVxdWVzdExvYWRlZFN0cmVhbSgpLCBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coImFjcm9Gb3JtIiksIHBkZk1hbmFnZXIuZW5zdXJlQ2F0YWxvZygiYWNyb0Zvcm1SZWYiKSwgcGRmTWFuYWdlci5lbnN1cmVEb2MoInN0YXJ0WFJlZiIpLCBwZGZNYW5hZ2VyLmVuc3VyZURvYygieHJlZiIpLCBwZGZNYW5hZ2VyLmVuc3VyZUNhdGFsb2coInN0cnVjdFRyZWVSb290IildOwogICAgICBjb25zdCBjaGFuZ2VzID0gbmV3IFJlZlNldENhY2hlKCk7CiAgICAgIGNvbnN0IHByb21pc2VzID0gW107CiAgICAgIGNvbnN0IG5ld0Fubm90YXRpb25zQnlQYWdlID0gIWlzUHVyZVhmYSA/IGdldE5ld0Fubm90YXRpb25zTWFwKGFubm90YXRpb25TdG9yYWdlKSA6IG51bGw7CiAgICAgIGNvbnN0IFtzdHJlYW0sIGFjcm9Gb3JtLCBhY3JvRm9ybVJlZiwgc3RhcnRYUmVmLCB4cmVmLCBfc3RydWN0VHJlZVJvb3RdID0gYXdhaXQgUHJvbWlzZS5hbGwoZ2xvYmFsUHJvbWlzZXMpOwogICAgICBjb25zdCBjYXRhbG9nUmVmID0geHJlZi50cmFpbGVyLmdldFJhdygiUm9vdCIpIHx8IG51bGw7CiAgICAgIGxldCBzdHJ1Y3RUcmVlUm9vdDsKICAgICAgaWYgKG5ld0Fubm90YXRpb25zQnlQYWdlKSB7CiAgICAgICAgaWYgKCFfc3RydWN0VHJlZVJvb3QpIHsKICAgICAgICAgIGlmIChhd2FpdCBTdHJ1Y3RUcmVlUm9vdC5jYW5DcmVhdGVTdHJ1Y3R1cmVUcmVlKHsKICAgICAgICAgICAgY2F0YWxvZ1JlZiwKICAgICAgICAgICAgcGRmTWFuYWdlciwKICAgICAgICAgICAgbmV3QW5ub3RhdGlvbnNCeVBhZ2UKICAgICAgICAgIH0pKSB7CiAgICAgICAgICAgIHN0cnVjdFRyZWVSb290ID0gbnVsbDsKICAgICAgICAgIH0KICAgICAgICB9IGVsc2UgaWYgKGF3YWl0IF9zdHJ1Y3RUcmVlUm9vdC5jYW5VcGRhdGVTdHJ1Y3RUcmVlKHsKICAgICAgICAgIHBkZk1hbmFnZXIsCiAgICAgICAgICBuZXdBbm5vdGF0aW9uc0J5UGFnZQogICAgICAgIH0pKSB7CiAgICAgICAgICBzdHJ1Y3RUcmVlUm9vdCA9IF9zdHJ1Y3RUcmVlUm9vdDsKICAgICAgICB9CiAgICAgICAgY29uc3QgaW1hZ2VQcm9taXNlcyA9IEFubm90YXRpb25GYWN0b3J5LmdlbmVyYXRlSW1hZ2VzKGFubm90YXRpb25TdG9yYWdlLnZhbHVlcygpLCB4cmVmLCBwZGZNYW5hZ2VyLmV2YWx1YXRvck9wdGlvbnMuaXNPZmZzY3JlZW5DYW52YXNTdXBwb3J0ZWQpOwogICAgICAgIGNvbnN0IG5ld0Fubm90YXRpb25Qcm9taXNlcyA9IHN0cnVjdFRyZWVSb290ID09PSB1bmRlZmluZWQgPyBwcm9taXNlcyA6IFtdOwogICAgICAgIGZvciAoY29uc3QgW3BhZ2VJbmRleCwgYW5ub3RhdGlvbnNdIG9mIG5ld0Fubm90YXRpb25zQnlQYWdlKSB7CiAgICAgICAgICBuZXdBbm5vdGF0aW9uUHJvbWlzZXMucHVzaChwZGZNYW5hZ2VyLmdldFBhZ2UocGFnZUluZGV4KS50aGVuKHBhZ2UgPT4gewogICAgICAgICAgICBjb25zdCB0YXNrID0gbmV3IFdvcmtlclRhc2soYFNhdmUgKGVkaXRvcik6IHBhZ2UgJHtwYWdlSW5kZXh9YCk7CiAgICAgICAgICAgIHN0YXJ0V29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgICAgcmV0dXJuIHBhZ2Uuc2F2ZU5ld0Fubm90YXRpb25zKGhhbmRsZXIsIHRhc2ssIGFubm90YXRpb25zLCBpbWFnZVByb21pc2VzLCBjaGFuZ2VzKS5maW5hbGx5KGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICBmaW5pc2hXb3JrZXJUYXNrKHRhc2spOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0pKTsKICAgICAgICB9CiAgICAgICAgaWYgKHN0cnVjdFRyZWVSb290ID09PSBudWxsKSB7CiAgICAgICAgICBwcm9taXNlcy5wdXNoKFByb21pc2UuYWxsKG5ld0Fubm90YXRpb25Qcm9taXNlcykudGhlbihhc3luYyAoKSA9PiB7CiAgICAgICAgICAgIGF3YWl0IFN0cnVjdFRyZWVSb290LmNyZWF0ZVN0cnVjdHVyZVRyZWUoewogICAgICAgICAgICAgIG5ld0Fubm90YXRpb25zQnlQYWdlLAogICAgICAgICAgICAgIHhyZWYsCiAgICAgICAgICAgICAgY2F0YWxvZ1JlZiwKICAgICAgICAgICAgICBwZGZNYW5hZ2VyLAogICAgICAgICAgICAgIGNoYW5nZXMKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KSk7CiAgICAgICAgfSBlbHNlIGlmIChzdHJ1Y3RUcmVlUm9vdCkgewogICAgICAgICAgcHJvbWlzZXMucHVzaChQcm9taXNlLmFsbChuZXdBbm5vdGF0aW9uUHJvbWlzZXMpLnRoZW4oYXN5bmMgKCkgPT4gewogICAgICAgICAgICBhd2FpdCBzdHJ1Y3RUcmVlUm9vdC51cGRhdGVTdHJ1Y3R1cmVUcmVlKHsKICAgICAgICAgICAgICBuZXdBbm5vdGF0aW9uc0J5UGFnZSwKICAgICAgICAgICAgICBwZGZNYW5hZ2VyLAogICAgICAgICAgICAgIGNoYW5nZXMKICAgICAgICAgICAgfSk7CiAgICAgICAgICB9KSk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGlmIChpc1B1cmVYZmEpIHsKICAgICAgICBwcm9taXNlcy5wdXNoKHBkZk1hbmFnZXIuZW5zdXJlRG9jKCJzZXJpYWxpemVYZmFEYXRhIiwgW2Fubm90YXRpb25TdG9yYWdlXSkpOwogICAgICB9IGVsc2UgewogICAgICAgIGZvciAobGV0IHBhZ2VJbmRleCA9IDA7IHBhZ2VJbmRleCA8IG51bVBhZ2VzOyBwYWdlSW5kZXgrKykgewogICAgICAgICAgcHJvbWlzZXMucHVzaChwZGZNYW5hZ2VyLmdldFBhZ2UocGFnZUluZGV4KS50aGVuKGZ1bmN0aW9uIChwYWdlKSB7CiAgICAgICAgICAgIGNvbnN0IHRhc2sgPSBuZXcgV29ya2VyVGFzayhgU2F2ZTogcGFnZSAke3BhZ2VJbmRleH1gKTsKICAgICAgICAgICAgc3RhcnRXb3JrZXJUYXNrKHRhc2spOwogICAgICAgICAgICByZXR1cm4gcGFnZS5zYXZlKGhhbmRsZXIsIHRhc2ssIGFubm90YXRpb25TdG9yYWdlLCBjaGFuZ2VzKS5maW5hbGx5KGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgICBmaW5pc2hXb3JrZXJUYXNrKHRhc2spOwogICAgICAgICAgICB9KTsKICAgICAgICAgIH0pKTsKICAgICAgICB9CiAgICAgIH0KICAgICAgY29uc3QgcmVmcyA9IGF3YWl0IFByb21pc2UuYWxsKHByb21pc2VzKTsKICAgICAgbGV0IHhmYURhdGEgPSBudWxsOwogICAgICBpZiAoaXNQdXJlWGZhKSB7CiAgICAgICAgeGZhRGF0YSA9IHJlZnNbMF07CiAgICAgICAgaWYgKCF4ZmFEYXRhKSB7CiAgICAgICAgICByZXR1cm4gc3RyZWFtLmJ5dGVzOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmIChjaGFuZ2VzLnNpemUgPT09IDApIHsKICAgICAgICByZXR1cm4gc3RyZWFtLmJ5dGVzOwogICAgICB9CiAgICAgIGNvbnN0IG5lZWRBcHBlYXJhbmNlcyA9IGFjcm9Gb3JtUmVmICYmIGFjcm9Gb3JtIGluc3RhbmNlb2YgRGljdCAmJiBjaGFuZ2VzLnZhbHVlcygpLnNvbWUocmVmID0+IHJlZi5uZWVkQXBwZWFyYW5jZXMpOwogICAgICBjb25zdCB4ZmEgPSBhY3JvRm9ybSBpbnN0YW5jZW9mIERpY3QgJiYgYWNyb0Zvcm0uZ2V0KCJYRkEiKSB8fCBudWxsOwogICAgICBsZXQgeGZhRGF0YXNldHNSZWYgPSBudWxsOwogICAgICBsZXQgaGFzWGZhRGF0YXNldHNFbnRyeSA9IGZhbHNlOwogICAgICBpZiAoQXJyYXkuaXNBcnJheSh4ZmEpKSB7CiAgICAgICAgZm9yIChsZXQgaSA9IDAsIGlpID0geGZhLmxlbmd0aDsgaSA8IGlpOyBpICs9IDIpIHsKICAgICAgICAgIGlmICh4ZmFbaV0gPT09ICJkYXRhc2V0cyIpIHsKICAgICAgICAgICAgeGZhRGF0YXNldHNSZWYgPSB4ZmFbaSArIDFdOwogICAgICAgICAgICBoYXNYZmFEYXRhc2V0c0VudHJ5ID0gdHJ1ZTsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgaWYgKHhmYURhdGFzZXRzUmVmID09PSBudWxsKSB7CiAgICAgICAgICB4ZmFEYXRhc2V0c1JlZiA9IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCk7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKHhmYSkgewogICAgICAgIHdhcm4oIlVuc3VwcG9ydGVkIFhGQSB0eXBlLiIpOwogICAgICB9CiAgICAgIGxldCBuZXdYcmVmSW5mbyA9IE9iamVjdC5jcmVhdGUobnVsbCk7CiAgICAgIGlmICh4cmVmLnRyYWlsZXIpIHsKICAgICAgICBjb25zdCBpbmZvTWFwID0gbmV3IE1hcCgpOwogICAgICAgIGNvbnN0IHhyZWZJbmZvID0geHJlZi50cmFpbGVyLmdldCgiSW5mbyIpIHx8IG51bGw7CiAgICAgICAgaWYgKHhyZWZJbmZvIGluc3RhbmNlb2YgRGljdCkgewogICAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgeHJlZkluZm8pIHsKICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gInN0cmluZyIpIHsKICAgICAgICAgICAgICBpbmZvTWFwLnNldChrZXksIHN0cmluZ1RvUERGU3RyaW5nKHZhbHVlKSk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgbmV3WHJlZkluZm8gPSB7CiAgICAgICAgICByb290UmVmOiBjYXRhbG9nUmVmLAogICAgICAgICAgZW5jcnlwdFJlZjogeHJlZi50cmFpbGVyLmdldFJhdygiRW5jcnlwdCIpIHx8IG51bGwsCiAgICAgICAgICBuZXdSZWY6IHhyZWYuZ2V0TmV3VGVtcG9yYXJ5UmVmKCksCiAgICAgICAgICBpbmZvUmVmOiB4cmVmLnRyYWlsZXIuZ2V0UmF3KCJJbmZvIikgfHwgbnVsbCwKICAgICAgICAgIGluZm9NYXAsCiAgICAgICAgICBmaWxlSWRzOiB4cmVmLnRyYWlsZXIuZ2V0KCJJRCIpIHx8IG51bGwsCiAgICAgICAgICBzdGFydFhSZWYsCiAgICAgICAgICBmaWxlbmFtZQogICAgICAgIH07CiAgICAgIH0KICAgICAgcmV0dXJuIGluY3JlbWVudGFsVXBkYXRlKHsKICAgICAgICBvcmlnaW5hbERhdGE6IHN0cmVhbS5ieXRlcywKICAgICAgICB4cmVmSW5mbzogbmV3WHJlZkluZm8sCiAgICAgICAgY2hhbmdlcywKICAgICAgICB4cmVmLAogICAgICAgIGhhc1hmYTogISF4ZmEsCiAgICAgICAgeGZhRGF0YXNldHNSZWYsCiAgICAgICAgaGFzWGZhRGF0YXNldHNFbnRyeSwKICAgICAgICBuZWVkQXBwZWFyYW5jZXMsCiAgICAgICAgYWNyb0Zvcm1SZWYsCiAgICAgICAgYWNyb0Zvcm0sCiAgICAgICAgeGZhRGF0YSwKICAgICAgICB1c2VYcmVmU3RyZWFtOiBpc0RpY3QoeHJlZi50b3BEaWN0LCAiWFJlZiIpCiAgICAgIH0pLmZpbmFsbHkoKCkgPT4gewogICAgICAgIHhyZWYucmVzZXROZXdUZW1wb3JhcnlSZWYoKTsKICAgICAgfSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldE9wZXJhdG9yTGlzdCIsIGZ1bmN0aW9uIChkYXRhLCBzaW5rKSB7CiAgICAgIGNvbnN0IHBhZ2VJbmRleCA9IGRhdGEucGFnZUluZGV4OwogICAgICBwZGZNYW5hZ2VyLmdldFBhZ2UocGFnZUluZGV4KS50aGVuKGZ1bmN0aW9uIChwYWdlKSB7CiAgICAgICAgY29uc3QgdGFzayA9IG5ldyBXb3JrZXJUYXNrKGBHZXRPcGVyYXRvckxpc3Q6IHBhZ2UgJHtwYWdlSW5kZXh9YCk7CiAgICAgICAgc3RhcnRXb3JrZXJUYXNrKHRhc2spOwogICAgICAgIGNvbnN0IHN0YXJ0ID0gdmVyYm9zaXR5ID49IFZlcmJvc2l0eUxldmVsLklORk9TID8gRGF0ZS5ub3coKSA6IDA7CiAgICAgICAgcGFnZS5nZXRPcGVyYXRvckxpc3QoewogICAgICAgICAgaGFuZGxlciwKICAgICAgICAgIHNpbmssCiAgICAgICAgICB0YXNrLAogICAgICAgICAgaW50ZW50OiBkYXRhLmludGVudCwKICAgICAgICAgIGNhY2hlS2V5OiBkYXRhLmNhY2hlS2V5LAogICAgICAgICAgYW5ub3RhdGlvblN0b3JhZ2U6IGRhdGEuYW5ub3RhdGlvblN0b3JhZ2UsCiAgICAgICAgICBtb2RpZmllZElkczogZGF0YS5tb2RpZmllZElkcwogICAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKG9wZXJhdG9yTGlzdEluZm8pIHsKICAgICAgICAgIGZpbmlzaFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgICBpZiAoc3RhcnQpIHsKICAgICAgICAgICAgaW5mbyhgcGFnZT0ke3BhZ2VJbmRleCArIDF9IC0gZ2V0T3BlcmF0b3JMaXN0OiB0aW1lPWAgKyBgJHtEYXRlLm5vdygpIC0gc3RhcnR9bXMsIGxlbj0ke29wZXJhdG9yTGlzdEluZm8ubGVuZ3RofWApOwogICAgICAgICAgfQogICAgICAgICAgc2luay5jbG9zZSgpOwogICAgICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHsKICAgICAgICAgIGZpbmlzaFdvcmtlclRhc2sodGFzayk7CiAgICAgICAgICBpZiAodGFzay50ZXJtaW5hdGVkKSB7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgIH0KICAgICAgICAgIHNpbmsuZXJyb3IocmVhc29uKTsKICAgICAgICB9KTsKICAgICAgfSk7CiAgICB9KTsKICAgIGhhbmRsZXIub24oIkdldFRleHRDb250ZW50IiwgZnVuY3Rpb24gKGRhdGEsIHNpbmspIHsKICAgICAgY29uc3QgewogICAgICAgIHBhZ2VJbmRleCwKICAgICAgICBpbmNsdWRlTWFya2VkQ29udGVudCwKICAgICAgICBkaXNhYmxlTm9ybWFsaXphdGlvbgogICAgICB9ID0gZGF0YTsKICAgICAgcGRmTWFuYWdlci5nZXRQYWdlKHBhZ2VJbmRleCkudGhlbihmdW5jdGlvbiAocGFnZSkgewogICAgICAgIGNvbnN0IHRhc2sgPSBuZXcgV29ya2VyVGFzaygiR2V0VGV4dENvbnRlbnQ6IHBhZ2UgIiArIHBhZ2VJbmRleCk7CiAgICAgICAgc3RhcnRXb3JrZXJUYXNrKHRhc2spOwogICAgICAgIGNvbnN0IHN0YXJ0ID0gdmVyYm9zaXR5ID49IFZlcmJvc2l0eUxldmVsLklORk9TID8gRGF0ZS5ub3coKSA6IDA7CiAgICAgICAgcGFnZS5leHRyYWN0VGV4dENvbnRlbnQoewogICAgICAgICAgaGFuZGxlciwKICAgICAgICAgIHRhc2ssCiAgICAgICAgICBzaW5rLAogICAgICAgICAgaW5jbHVkZU1hcmtlZENvbnRlbnQsCiAgICAgICAgICBkaXNhYmxlTm9ybWFsaXphdGlvbgogICAgICAgIH0pLnRoZW4oZnVuY3Rpb24gKCkgewogICAgICAgICAgZmluaXNoV29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgIGlmIChzdGFydCkgewogICAgICAgICAgICBpbmZvKGBwYWdlPSR7cGFnZUluZGV4ICsgMX0gLSBnZXRUZXh0Q29udGVudDogdGltZT1gICsgYCR7RGF0ZS5ub3coKSAtIHN0YXJ0fW1zYCk7CiAgICAgICAgICB9CiAgICAgICAgICBzaW5rLmNsb3NlKCk7CiAgICAgICAgfSwgZnVuY3Rpb24gKHJlYXNvbikgewogICAgICAgICAgZmluaXNoV29ya2VyVGFzayh0YXNrKTsKICAgICAgICAgIGlmICh0YXNrLnRlcm1pbmF0ZWQpIHsKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgfQogICAgICAgICAgc2luay5lcnJvcihyZWFzb24pOwogICAgICAgIH0pOwogICAgICB9KTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiR2V0U3RydWN0VHJlZSIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHJldHVybiBwZGZNYW5hZ2VyLmdldFBhZ2UoZGF0YS5wYWdlSW5kZXgpLnRoZW4ocGFnZSA9PiBwZGZNYW5hZ2VyLmVuc3VyZShwYWdlLCAiZ2V0U3RydWN0VHJlZSIpKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiRm9udEZhbGxiYWNrIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuZm9udEZhbGxiYWNrKGRhdGEuaWQsIGhhbmRsZXIpOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJDbGVhbnVwIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgcmV0dXJuIHBkZk1hbmFnZXIuY2xlYW51cCh0cnVlKTsKICAgIH0pOwogICAgaGFuZGxlci5vbigiVGVybWluYXRlIiwgZnVuY3Rpb24gKGRhdGEpIHsKICAgICAgdGVybWluYXRlZCA9IHRydWU7CiAgICAgIGNvbnN0IHdhaXRPbiA9IFtdOwogICAgICBpZiAocGRmTWFuYWdlcikgewogICAgICAgIHBkZk1hbmFnZXIudGVybWluYXRlKG5ldyBBYm9ydEV4Y2VwdGlvbigiV29ya2VyIHdhcyB0ZXJtaW5hdGVkLiIpKTsKICAgICAgICBjb25zdCBjbGVhbnVwUHJvbWlzZSA9IHBkZk1hbmFnZXIuY2xlYW51cCgpOwogICAgICAgIHdhaXRPbi5wdXNoKGNsZWFudXBQcm9taXNlKTsKICAgICAgICBwZGZNYW5hZ2VyID0gbnVsbDsKICAgICAgfSBlbHNlIHsKICAgICAgICBjbGVhckdsb2JhbENhY2hlcygpOwogICAgICB9CiAgICAgIGNhbmNlbFhIUnM/LihuZXcgQWJvcnRFeGNlcHRpb24oIldvcmtlciB3YXMgdGVybWluYXRlZC4iKSk7CiAgICAgIGZvciAoY29uc3QgdGFzayBvZiBXb3JrZXJUYXNrcykgewogICAgICAgIHdhaXRPbi5wdXNoKHRhc2suZmluaXNoZWQpOwogICAgICAgIHRhc2sudGVybWluYXRlKCk7CiAgICAgIH0KICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHdhaXRPbikudGhlbihmdW5jdGlvbiAoKSB7CiAgICAgICAgaGFuZGxlci5kZXN0cm95KCk7CiAgICAgICAgaGFuZGxlciA9IG51bGw7CiAgICAgIH0pOwogICAgfSk7CiAgICBoYW5kbGVyLm9uKCJSZWFkeSIsIGZ1bmN0aW9uIChkYXRhKSB7CiAgICAgIHNldHVwRG9jKGRvY1BhcmFtcyk7CiAgICAgIGRvY1BhcmFtcyA9IG51bGw7CiAgICB9KTsKICAgIHJldHVybiB3b3JrZXJIYW5kbGVyTmFtZTsKICB9CiAgc3RhdGljIGluaXRpYWxpemVGcm9tUG9ydChwb3J0KSB7CiAgICBjb25zdCBoYW5kbGVyID0gbmV3IE1lc3NhZ2VIYW5kbGVyKCJ3b3JrZXIiLCAibWFpbiIsIHBvcnQpOwogICAgdGhpcy5zZXR1cChoYW5kbGVyLCBwb3J0KTsKICAgIGhhbmRsZXIuc2VuZCgicmVhZHkiLCBudWxsKTsKICB9Cn0KCjsvLyAuL3NyYy9wZGYud29ya2VyLmpzCgpnbG9iYWxUaGlzLnBkZmpzV29ya2VyID0gewogIFdvcmtlck1lc3NhZ2VIYW5kbGVyOiBXb3JrZXJNZXNzYWdlSGFuZGxlcgp9OwoKZXhwb3J0IHsgV29ya2VyTWVzc2FnZUhhbmRsZXIgfTsKCi8vIyBzb3VyY2VNYXBwaW5nVVJMPXBkZi53b3JrZXIubWpzLm1hcA=="; +class Shape { + static tolerance = 2; + static applyTransform(p, m) { + const xt = p[0] * m[0] + p[1] * m[2] + m[4]; + const yt = p[0] * m[1] + p[1] * m[3] + m[5]; + return [xt, yt]; + } +} +class Point extends Shape { + x; + y; + constructor(x, y) { + super(); + this.x = x; + this.y = y; + } + equal(point) { + return point.x === this.x && point.y === this.y; + } + transform(matrix) { + const p = Shape.applyTransform([this.x, this.y], matrix); + this.x = p[0]; + this.y = p[1]; + return this; + } +} +var LineDirection = /* @__PURE__ */ ((LineDirection2) => { + LineDirection2[LineDirection2["None"] = 0] = "None"; + LineDirection2[LineDirection2["Horizontal"] = 1] = "Horizontal"; + LineDirection2[LineDirection2["Vertical"] = 2] = "Vertical"; + return LineDirection2; +})(LineDirection || {}); +class Line extends Shape { + from; + to; + direction = 0; + length = 0; + intersections = []; + gaps = []; + constructor(from, to) { + super(); + this.from = from; + this.to = to; + this.init(); + } + init() { + let from = this.from; + let to = this.to; + if (Math.abs(from.y - to.y) < Shape.tolerance) { + this.direction = 1; + to.y = from.y; + if (from.x > to.x) { + const temp = from; + from = to; + to = temp; + } + this.length = to.x - from.x; + } else if (Math.abs(from.x - to.x) < Shape.tolerance) { + this.direction = 2; + to.x = from.x; + if (from.y > to.y) { + const temp = from; + from = to; + to = temp; + } + this.length = to.y - from.y; + } + this.from = from; + this.to = to; + } + _valid = void 0; + get valid() { + if (this._valid === void 0) { + this._valid = this.direction !== 0 && this.length > Shape.tolerance; + } + return this._valid; + } + get normalized() { + if (this.direction === 1) { + return new Line(new Point(this.from.x - Shape.tolerance, this.from.y), new Point(this.to.x + Shape.tolerance, this.from.y)); + } else if (this.direction === 2) { + return new Line(new Point(this.from.x, this.from.y - Shape.tolerance), new Point(this.from.x, this.to.y + Shape.tolerance)); + } + return this; + } + addGap(line) { + this.gaps.push(line); + } + containsPoint(p) { + if (this.direction === 2) { + return this.from.x === p.x && p.y >= this.from.y && p.y <= this.to.y; + } else if (this.direction === 1) { + return this.from.y === p.y && p.x >= this.from.x && p.x <= this.to.x; + } + return false; + } + // // todo implement + // public containsLine(l:Line):boolean{ + // if(this.direction === LineDirection.Vertical && l.direction === LineDirection.Vertical){ + // return this.from.x === l.from.x + // } + // else if(this.direction === LineDirection.Horizontal && l.direction === LineDirection.Horizontal){ + // return this.from.y === l.from.y + // } + // return false + // } + addIntersectionPoint(point) { + for (const intPoint of this.intersections) { + if (intPoint.equal(point)) return; + } + this.intersections.push(point); + } + intersection(line) { + let result; + if (!this.valid || !line.valid) { + return result; + } + const thisNormalized = this.normalized; + const lineNormalized = line.normalized; + if (this.direction === 1 && line.direction === 2) { + const x = lineNormalized.from.x; + const y = thisNormalized.from.y; + const isOk = x > thisNormalized.from.x && x < thisNormalized.to.x && y > lineNormalized.from.y && y < lineNormalized.to.y; + if (isOk) { + const intPoint = new Point(x, y); + this.addIntersectionPoint(intPoint); + line.addIntersectionPoint(intPoint); + result = intPoint; + } + } else if (this.direction === 2 && line.direction === 1) { + const x = thisNormalized.from.x; + const y = lineNormalized.from.y; + const isOk = x > lineNormalized.from.x && x < lineNormalized.to.x && y > thisNormalized.from.y && y < thisNormalized.to.y; + if (isOk) { + const intPoint = new Point(x, y); + this.addIntersectionPoint(intPoint); + line.addIntersectionPoint(intPoint); + result = intPoint; + } + } + return result; + } + transform(matrix) { + const p1 = this.from.transform(matrix); + const p2 = this.to.transform(matrix); + const x = Math.min(p1.x, p2.x); + const y = Math.min(p1.y, p2.y); + const width = Math.abs(p1.x - p2.x); + const height = Math.abs(p1.y - p2.y); + this.from = new Point(x, y); + this.to = new Point(x + width, y + height); + this.init(); + return this; + } +} +class TableData { + minXY; + maxXY; + rows; + rowPivots; + colPivots; + constructor(minXY, maxXY, rowPivots, colPivots) { + this.minXY = minXY; + this.maxXY = maxXY; + this.rows = []; + this.rowPivots = rowPivots; + this.colPivots = colPivots; + } + findCell(x, y) { + if (x >= this.minXY.x && y >= this.minXY.y && x <= this.maxXY.x && y <= this.maxXY.y) { + for (const row of this.rows) { + for (const cell of row) { + if (cell.minXY.x <= x && cell.minXY.y <= y && cell.maxXY.x >= x && cell.maxXY.y >= y) { + return cell; + } + } + } + } + return void 0; + } + get cellCount() { + return this.rows.reduce((acc, row) => acc + row.length, 0); + } + get rowCount() { + return this.rows.length; + } + check() { + const virtualCellCount = (this.colPivots.length - 1) * (this.rowPivots.length - 1); + let allCellCount = 0; + for (const row of this.rows) { + for (const cell of row) { + const count = (cell.colspan || 1) * (cell.rowspan || 1); + allCellCount += count; + } + } + if (virtualCellCount !== allCellCount) { + return false; + } + return true; + } + toArray() { + const tableArr = []; + for (const row of this.rows) { + const rowArr = []; + for (const cell of row) { + let text = cell.text.join(""); + text = text.replace(/^[\s]+|[\s]+$/g, ""); + text = text.trim(); + rowArr.push(text); + } + tableArr.push(rowArr); + } + return tableArr; + } +} +class Table { + hLines = []; + vLines = []; + constructor(line) { + if (line.direction === LineDirection.Horizontal) { + this.hLines.push(line); + } else if (line.direction === LineDirection.Vertical) { + this.vLines.push(line); + } + } + get isValid() { + return this.hLines.length + this.vLines.length > 4; + } + get rowPivots() { + const rowSet = /* @__PURE__ */ new Set(); + for (const line of this.hLines) { + rowSet.add(line.from.y); + } + return [...rowSet].sort((a, b) => a - b); + } + get colPivots() { + const colSet = /* @__PURE__ */ new Set(); + for (const line of this.vLines) { + colSet.add(line.from.x); + } + return [...colSet].sort((a, b) => a - b); + } + add(line) { + const hasIntersection = this.intersection(line); + if (hasIntersection) { + if (line.direction === LineDirection.Horizontal) { + this.hLines.push(line); + return true; + } else if (line.direction === LineDirection.Vertical) { + this.vLines.push(line); + return true; + } + } + return false; + } + intersection(line) { + let flag = false; + if (!line.valid) return flag; + if (line.direction === LineDirection.Horizontal) { + for (const vLine of this.vLines) { + const p = line.intersection(vLine); + if (p) { + flag = true; + } + } + } else if (line.direction === LineDirection.Vertical) { + for (const hLine of this.hLines) { + const p = line.intersection(hLine); + if (p) { + flag = true; + } + } + } + return flag; + } + getSameHorizontal(line) { + const same = [line]; + const other = []; + while (this.hLines.length > 0) { + const hLine = this.hLines.shift(); + if (!hLine) continue; + if (hLine.from.y === line.from.y) { + same.push(hLine); + } else { + other.push(hLine); + } + } + this.hLines = other; + return same; + } + getSameVertical(line) { + const same = [line]; + const other = []; + while (this.vLines.length > 0) { + const vLine = this.vLines.shift(); + if (!vLine) continue; + if (vLine.from.x === line.from.x) { + same.push(vLine); + } else { + other.push(vLine); + } + } + this.vLines = other; + return same; + } + mergeHorizontalLines(lines) { + lines.sort((l1, l2) => l1.from.x - l2.from.x); + const minX = lines[0].from.x; + const maxX = lines[lines.length - 1].to.x; + const resultLine = new Line(new Point(minX, lines[0].from.y), new Point(maxX, lines[0].from.y)); + for (let i = 1; i < lines.length; i++) { + const prevLine = lines[i - 1]; + const currLine = lines[i]; + if (Math.abs(prevLine.to.x - currLine.from.x) > Shape.tolerance) { + const gapLine = new Line(new Point(prevLine.to.x, prevLine.from.y), new Point(currLine.from.x, currLine.from.y)); + resultLine.addGap(gapLine); + } + } + return resultLine; + } + mergeVerticalLines(lines) { + lines.sort((l1, l2) => l1.from.y - l2.from.y); + const minY = lines[0].from.y; + const maxY = lines[lines.length - 1].to.y; + const resultLine = new Line(new Point(lines[0].from.x, minY), new Point(lines[0].from.x, maxY)); + for (let i = 1; i < lines.length; i++) { + const prevLine = lines[i - 1]; + const currLine = lines[i]; + if (Math.abs(prevLine.to.y - currLine.from.y) > Shape.tolerance) { + const gapLine = new Line(new Point(prevLine.to.x, prevLine.to.y), new Point(prevLine.to.x, currLine.from.y)); + resultLine.addGap(gapLine); + } + } + return resultLine; + } + normalize() { + this.hLines = this.hLines.filter((l) => l.intersections.length > 1); + this.vLines = this.vLines.filter((l) => l.intersections.length > 1); + this.hLines.sort((l1, l2) => l1.from.y - l2.from.y); + this.vLines.sort((l1, l2) => l1.from.x - l2.from.x); + const newHLines = []; + while (this.hLines.length > 0) { + const line = this.hLines.shift(); + if (!line) continue; + const lines = this.getSameHorizontal(line); + const merged = this.mergeHorizontalLines(lines); + newHLines.push(merged); + } + this.hLines = newHLines; + const newVLines = []; + while (this.vLines.length > 0) { + const line = this.vLines.shift(); + if (!line) continue; + const lines = this.getSameVertical(line); + const merged = this.mergeVerticalLines(lines); + newVLines.push(merged); + } + this.vLines = newVLines; + } + verticalExists(line, y1, y2) { + if (line.direction !== LineDirection.Vertical) { + throw new Error("Line is not vertical"); + } + if (y1 >= y2) { + throw new Error("y1 must be less than y2"); + } + if (line.from.y <= y1 && line.to.y >= y2) { + for (const gap of line.gaps) { + if (gap.from.y <= y1 && gap.to.y >= y2) { + return false; + } + } + return true; + } + return false; + } + horizontalExists(line, x1, x2) { + if (line.direction !== LineDirection.Horizontal) { + throw new Error("Line is not horizontal"); + } + if (x1 >= x2) { + throw new Error("x1 must be less than x2"); + } + if (line.from.x <= x1 && line.to.x >= x2) { + for (const gap of line.gaps) { + if (gap.from.x <= x1 && gap.to.x >= x2) { + return false; + } + } + return true; + } + return false; + } + findBottomLineIndex(h2Index, xMiddle) { + for (let i = h2Index; i < this.hLines.length; i++) { + const hLine = this.hLines[i]; + if (hLine.from.x <= xMiddle && hLine.to.x >= xMiddle) { + return i; + } + } + return -1; + } + findVerticalLineIndexs(topHLine, yMiddle) { + const result = []; + for (let i = 0; i < this.vLines.length; i++) { + const vLine = this.vLines[i]; + if (vLine.from.y <= yMiddle && vLine.to.y >= yMiddle && topHLine.intersection(vLine)) { + result.push(i); + } + } + return result; + } + getRow(h1Index, h2Index, yMiddle) { + const tableRow = []; + const topHLine = this.hLines[h1Index]; + const vLineIndexes = this.findVerticalLineIndexs(topHLine, yMiddle); + for (let i = 1; i < vLineIndexes.length; i++) { + const leftVLine = this.vLines[vLineIndexes[i - 1]]; + const rightVLine = this.vLines[vLineIndexes[i]]; + const xMiddle = (leftVLine.from.x + rightVLine.from.x) / 2; + const bottomHLineIndex = this.findBottomLineIndex(h2Index, xMiddle); + const bottomHLine = this.hLines[bottomHLineIndex]; + const tableCell = { + minXY: new Point(leftVLine.from.x, topHLine.from.y), + maxXY: new Point(rightVLine.from.x, bottomHLine.from.y), + width: rightVLine.from.x - leftVLine.from.x, + height: bottomHLine.from.y - topHLine.from.y, + text: [] + }; + const colSpan = vLineIndexes[i] - vLineIndexes[i - 1]; + const rowSpan = bottomHLineIndex - h1Index; + if (colSpan > 1) { + tableCell.colspan = colSpan; + } + if (rowSpan > 1) { + tableCell.rowspan = rowSpan; + } + tableRow.push(tableCell); + } + return tableRow; + } + toData() { + const rowPivots = this.rowPivots; + const colPivots = this.colPivots; + const minXY = new Point(colPivots[0], rowPivots[0]); + const maxXY = new Point(colPivots[colPivots.length - 1], rowPivots[rowPivots.length - 1]); + const result = new TableData(minXY, maxXY, rowPivots, colPivots); + for (let h1 = 1; h1 < this.hLines.length; h1++) { + const prevHLine = this.hLines[h1 - 1]; + const currHLine = this.hLines[h1]; + const YMiddle = (prevHLine.from.y + currHLine.from.y) / 2; + const rowData = this.getRow(h1 - 1, h1, YMiddle); + result.rows.push(rowData); + } + return result; + } +} +class LineStore { + hLines = []; + vLines = []; + add(line) { + if (line.valid) { + if (line.direction === LineDirection.Horizontal) { + this.hLines.push(line); + } else if (line.direction === LineDirection.Vertical) { + this.vLines.push(line); + } + } + } + addRectangle(rect) { + for (const line of rect.getLines()) { + this.add(line); + } + } + getTableData() { + const result = []; + const tables = this.getTables(); + for (const table of tables) { + const data = table.toData(); + if (data) { + result.push(data); + } + } + return result; + } + getTables() { + const result = []; + while (this.hLines.length !== 0) { + const hLine = this.hLines.shift(); + if (!hLine) continue; + const filled = this.tryFill(result, hLine); + if (filled) continue; + const table = new Table(hLine); + this.fillTable(table); + result.push(table); + } + while (this.vLines.length !== 0) { + const vLine = this.vLines.shift(); + if (!vLine) continue; + const filled = this.tryFill(result, vLine); + if (filled) continue; + const table = new Table(vLine); + this.fillTable(table); + result.push(table); + } + const validTables = result.filter((t) => t.isValid); + for (const table of validTables) { + table.normalize(); + } + return validTables; + } + normalize() { + this.normalizeHorizontal(); + this.normalizeVertical(); + } + normalizeHorizontal() { + this.hLines.sort((l1, l2) => l1.from.y - l2.from.y); + const newLines = []; + let sameY = []; + for (const line of this.hLines) { + if (sameY.length === 0) { + sameY.push(line); + } else if (Math.abs(sameY[0]?.from.y - line.from.y) < Shape.tolerance) { + sameY.push(line); + } else { + const merged = this.margeHorizontalLines(sameY); + newLines.push(...merged); + sameY = [line]; + } + } + if (sameY.length > 0) { + const merged = this.margeHorizontalLines(sameY); + newLines.push(...merged); + } + this.hLines = newLines; + } + normalizeVertical() { + this.vLines.sort((l1, l2) => l1.from.x - l2.from.x); + const newLines = []; + let sameX = []; + for (const line of this.vLines) { + if (sameX.length === 0) { + sameX.push(line); + } else if (Math.abs(sameX[0]?.from.x - line.from.x) < Shape.tolerance) { + sameX.push(line); + } else { + const merged = this.margeVerticalLines(sameX); + newLines.push(...merged); + sameX = [line]; + } + } + if (sameX.length > 0) { + const merged = this.margeVerticalLines(sameX); + newLines.push(...merged); + } + this.vLines = newLines; + } + fillTable(table) { + const newVLines = []; + const newHLines = []; + for (const vLine of this.vLines) { + if (!table.add(vLine)) { + newVLines.push(vLine); + } + } + for (const hLine of this.hLines) { + if (!table.add(hLine)) { + newHLines.push(hLine); + } + } + this.hLines = newHLines; + this.vLines = newVLines; + } + tryFill(tables, line) { + for (const table of tables) { + if (table.add(line)) { + this.fillTable(table); + return true; + } + } + return false; + } + margeHorizontalLines(sameYLines) { + const result = []; + sameYLines.sort((l1, l2) => l1.from.x - l2.from.x); + const sameY = sameYLines[0]?.from.y; + if (sameY === void 0) return result; + let minX = Number.MAX_SAFE_INTEGER; + let maxX = Number.MIN_SAFE_INTEGER; + for (const line of sameYLines) { + if (line.from.x - maxX < Shape.tolerance) { + if (line.from.x < minX) { + minX = line.from.x; + } + if (line.to.x > maxX) { + maxX = line.to.x; + } + } else { + if (maxX > minX) { + result.push(new Line(new Point(minX, sameY), new Point(maxX, sameY))); + } + minX = line.from.x; + maxX = line.to.x; + } + } + const last = result[result.length - 1]; + if (last) { + if (last.from.x !== minX && last.to.x !== maxX) { + result.push(new Line(new Point(minX, sameY), new Point(maxX, sameY))); + } + } else { + result.push(new Line(new Point(minX, sameY), new Point(maxX, sameY))); + } + return result; + } + margeVerticalLines(sameXLines) { + const result = []; + sameXLines.sort((l1, l2) => l1.from.y - l2.from.y); + const sameX = sameXLines[0]?.from.x; + if (sameX === void 0) return result; + let minY = Number.MAX_SAFE_INTEGER; + let maxY = Number.MIN_SAFE_INTEGER; + for (const line of sameXLines) { + if (line.from.y - maxY < Shape.tolerance) { + if (line.from.y < minY) { + minY = line.from.y; + } + if (line.to.y > maxY) { + maxY = line.to.y; + } + } else { + if (maxY > minY) { + result.push(new Line(new Point(sameX, minY), new Point(sameX, maxY))); + } + minY = line.from.y; + maxY = line.to.y; + } + } + const last = result[result.length - 1]; + if (last) { + if (last.from.y !== minY && last.to.y !== maxY) { + result.push(new Line(new Point(sameX, minY), new Point(sameX, maxY))); + } + } else { + result.push(new Line(new Point(sameX, minY), new Point(sameX, maxY))); + } + return result; + } +} +class Rectangle extends Shape { + from; + width; + height; + constructor(from, width, height) { + super(); + this.from = from; + this.width = width; + this.height = height; + } + get to() { + return new Point(this.from.x + this.width, this.from.y + this.height); + } + getLines() { + const to = this.to; + const lines = [ + new Line(this.from, new Point(to.x, this.from.y)), + new Line(this.from, new Point(this.from.x, to.y)), + new Line(new Point(to.x, this.from.y), to), + new Line(new Point(this.from.x, to.y), to) + ]; + return lines.filter((l) => l.valid); + } + transform(matrix) { + const p1 = Shape.applyTransform([this.from.x, this.from.y], matrix); + const p2 = Shape.applyTransform([this.from.x + this.width, this.from.y + this.height], matrix); + const x = Math.min(p1[0], p2[0]); + const y = Math.min(p1[1], p2[1]); + const width = Math.abs(p1[0] - p2[0]); + const height = Math.abs(p1[1] - p2[1]); + this.from = new Point(x, y); + this.width = width; + this.height = height; + return this; + } +} +class ImageResult { + pages = []; + total = 0; + info; + metadata; + getPageImage(num, name) { + for (const pageData of this.pages) { + if (pageData.pageNumber === num) { + for (const img of pageData.images) { + if (img.fileName === name) { + return img; + } + } + } + } + return null; + } + constructor(info2) { + Object.assign(this, info2); + } +} +class PageToImageResult { + pages = []; + total = 0; + info; + metadata; + constructor(info2) { + Object.assign(this, info2); + } +} +var PathGeometry = /* @__PURE__ */ ((PathGeometry2) => { + PathGeometry2[PathGeometry2["undefined"] = 0] = "undefined"; + PathGeometry2[PathGeometry2["hline"] = 1] = "hline"; + PathGeometry2[PathGeometry2["vline"] = 2] = "vline"; + PathGeometry2[PathGeometry2["rectangle"] = 3] = "rectangle"; + return PathGeometry2; +})(PathGeometry || {}); +class TableResult { + pages = []; + mergedTables = []; + total = 0; + info; + metadata; + constructor(info2) { + Object.assign(this, info2); + } +} +class TextResult { + pages = []; + text = ""; + total = 0; + info; + metadata; + getPageText(num) { + for (const pageData of this.pages) { + if (pageData.num === num) return pageData.text; + } + return ""; + } + constructor(info2) { + Object.assign(this, info2); + } +} +initPDFJS(); +class PDFParse { + options; + doc; + constructor(options) { + options.verbosity = VerbosityLevel.ERRORS; + this.options = options; + } + enviroment() { + const isBrowser = typeof window !== "undefined" && typeof document !== "undefined"; + const isCJS = typeof require !== "undefined" && typeof module !== "undefined" && typeof module.exports !== "undefined"; + const isESM = typeof window === "undefined" && typeof require === "undefined"; + return { isBrowser, isCJS, isESM }; + } + async getText(params = {}) { + const info2 = await this.load(); + const result = new TextResult(info2); + if (this.doc === void 0) { + throw new Error("PDF document not loaded"); + } + for (let i = 1; i <= result.total; i++) { + if (this.shouldParse(i, result.total, params)) { + const pageProxy = await this.doc.getPage(i); + const text = await this.getPageText(pageProxy, params); + result.pages.push({ + text, + num: i + }); + pageProxy.cleanup(); + } + } + await this.doc.destroy(); + this.doc = void 0; + for (const page of result.pages) { + result.text += `${page.text} + +`; + } + return result; + } + async load() { + const opts = { ...this.options }; + if (typeof this.options.data === "object" && "buffer" in this.options.data) { + opts.data = new Uint8Array(this.options.data); + } + const loadingTask = getDocument(opts); + this.doc = await loadingTask.promise; + const data = await this.doc.getMetadata(); + return { + total: this.doc.numPages, + info: data.info, + metadata: data.metadata + }; + } + shouldParse(currentPage, totalPage, params) { + params.partial = params?.partial ?? []; + params.first = params?.first ?? 0; + params.last = params?.last ?? 0; + if (params.partial.length > 0) { + if (params.partial.includes(currentPage)) { + return true; + } + return false; + } + if (params.first > 0 && params.last > 0) { + if (currentPage >= params.first && currentPage <= params.last) { + return true; + } + return false; + } + if (params.first > 0) { + if (currentPage <= params.first) { + return true; + } + return false; + } + if (params.last > 0) { + if (currentPage > totalPage - params.last) { + return true; + } + return false; + } + return true; + } + async getPageText(page, params) { + const viewport = page.getViewport({ scale: 1 }); + const textContent = await page.getTextContent({ + includeMarkedContent: !!params.includeMarkedContent, + disableNormalization: !!params.disableNormalization + }); + let links = /* @__PURE__ */ new Map(); + if (params.parseHyperlinks) { + links = await this.getHyperlinks(page, viewport); + } + const strBuf = []; + for (const item of textContent.items) { + if (!("str" in item)) continue; + if (params.parseHyperlinks) { + const tm = item.transform ?? item.transform; + const [x, y] = viewport.convertToViewportPoint(tm[4], tm[5]); + const posArr = links.get(item.str) || []; + const hit = posArr.find((l) => x >= l.rect.left && x <= l.rect.right && y >= l.rect.top && y <= l.rect.bottom); + if (hit) { + strBuf.push(`[${item.str}](${hit.url})`); + } else { + strBuf.push(item.str); + } + } else { + strBuf.push(item.str); + } + if (item.hasEOL) { + strBuf.push("\n"); + } + } + return strBuf.join(""); + } + async getHyperlinks(page, viewport) { + const result = /* @__PURE__ */ new Map(); + const annotations = await page.getAnnotations({ intent: "display" }) || []; + for (const i of annotations) { + if (i.subtype !== "Link") continue; + const url = i.url ?? i.unsafeUrl; + if (!url) continue; + const text = i.overlaidText; + if (!text) continue; + const rectVp = viewport.convertToViewportRectangle(i.rect); + const left = Math.min(rectVp[0], rectVp[2]) - 0.5; + const top = Math.min(rectVp[1], rectVp[3]) - 0.5; + const right = Math.max(rectVp[0], rectVp[2]) + 0.5; + const bottom = Math.max(rectVp[1], rectVp[3]) + 0.5; + const pos = { rect: { left, top, right, bottom }, url, text, used: false }; + const el = result.get(text); + if (el) { + el.push(pos); + } else { + result.set(text, [pos]); + } + } + return result; + } + async getImage(params = {}) { + const info2 = await this.load(); + const result = new ImageResult(info2); + if (this.doc === void 0) { + throw new Error("PDF document not loaded"); + } + for (let i = 1; i <= result.total; i++) { + if (this.shouldParse(i, result.total, params)) { + const page = await this.doc.getPage(i); + const ops = await page.getOperatorList(); + const pageImages = { pageNumber: i, images: [] }; + result.pages.push(pageImages); + for (let j = 0; j < ops.fnArray.length; j++) { + if (ops.fnArray[j] === OPS.paintInlineImageXObject || ops.fnArray[j] === OPS.paintImageXObject) { + const name = ops.argsArray[j][0]; + const isCommon = page.commonObjs.has(name); + const imgPromise = isCommon ? this.resolveEmbeddedImage(page.commonObjs, name) : this.resolveEmbeddedImage(page.objs, name); + const { width, height, kind, data } = await imgPromise; + const canvasFactory = this.doc.canvasFactory; + const canvasAndContext = canvasFactory.create(width, height); + const context = canvasAndContext.context; + let imgData = null; + if (kind === util_ImageKind.RGBA_32BPP) { + imgData = context.createImageData(width, height); + imgData.data.set(data); + } else { + imgData = context.createImageData(width, height); + this.convertToRGBA({ + src: data, + dest: new Uint32Array(imgData.data.buffer), + width, + height, + kind + }); + } + context.putImageData(imgData, 0, 0); + let buff; + let dataUrl; + if (typeof canvasAndContext.canvas.toBuffer === "function") { + const nodeBuffer = canvasAndContext.canvas.toBuffer("image/png"); + buff = new Uint8Array(nodeBuffer); + const base64 = nodeBuffer.toString("base64"); + dataUrl = `data:image/png;base64,${base64}`; + } else { + dataUrl = canvasAndContext.canvas.toDataURL("image/png"); + const base64 = dataUrl.split(",")[1]; + const binaryString = atob(base64); + buff = new Uint8Array(binaryString.length); + for (let i2 = 0; i2 < binaryString.length; i2++) { + buff[i2] = binaryString.charCodeAt(i2); + } + } + pageImages.images.push({ + data: buff, + dataUrl, + fileName: name, + height, + width, + kind + }); + } + } + } + } + await this.doc.destroy(); + this.doc = void 0; + return result; + } + convertToRGBA({ src, dest, width, height, kind }) { + if (kind === util_ImageKind.RGB_24BPP) { + for (let i = 0, j = 0; i < src.length; i += 3, j++) { + const r = src[i]; + const g = src[i + 1]; + const b = src[i + 2]; + dest[j] = 255 << 24 | b << 16 | g << 8 | r; + } + } else if (kind === util_ImageKind.GRAYSCALE_1BPP) { + let pixelIndex = 0; + for (let i = 0; i < src.length; i++) { + const byte = src[i]; + for (let bit = 7; bit >= 0; bit--) { + if (pixelIndex >= width * height) break; + const isWhite = (byte >> bit & 1) === 1; + const gray = isWhite ? 255 : 0; + dest[pixelIndex++] = 255 << 24 | gray << 16 | gray << 8 | gray; + } + } + } else if (kind === void 0 || kind === null) { + const bytesPerPixel = src.length / (width * height); + if (Math.abs(bytesPerPixel - 3) < 0.1) { + for (let i = 0, j = 0; i < src.length; i += 3, j++) { + const r = src[i]; + const g = src[i + 1]; + const b = src[i + 2]; + dest[j] = 255 << 24 | b << 16 | g << 8 | r; + } + } else if (Math.abs(bytesPerPixel - 4) < 0.1) { + for (let i = 0, j = 0; i < src.length; i += 4, j++) { + const r = src[i]; + const g = src[i + 1]; + const b = src[i + 2]; + const a = src[i + 3]; + dest[j] = a << 24 | b << 16 | g << 8 | r; + } + } else if (Math.abs(bytesPerPixel - 1) < 0.1) { + for (let i = 0; i < src.length; i++) { + const gray = src[i]; + dest[i] = 255 << 24 | gray << 16 | gray << 8 | gray; + } + } else { + throw new Error(`convertToRGBA: Cannot infer image format. kind: ${kind}, bytesPerPixel: ${bytesPerPixel}, width: ${width}, height: ${height}, dataLength: ${src.length}`); + } + } else { + throw new Error( + `convertToRGBA: Unsupported image kind: ${kind}. Available kinds: GRAYSCALE_1BPP=${util_ImageKind.GRAYSCALE_1BPP}, RGB_24BPP=${util_ImageKind.RGB_24BPP}, RGBA_32BPP=${util_ImageKind.RGBA_32BPP}` + ); + } + } + resolveEmbeddedImage(pdfObjects, name) { + return new Promise((resolve, reject) => { + pdfObjects.get(name, (imgData) => { + if (imgData) { + let dataBuff; + if (imgData.data instanceof Uint8Array) { + dataBuff = imgData.data; + } else if (imgData.data instanceof Uint8ClampedArray) { + dataBuff = new Uint8Array(imgData.data); + } else if (imgData.data?.buffer) { + dataBuff = new Uint8Array(imgData.data.buffer); + } else if (imgData.bitmap) { + const canvasFactory = this.doc.canvasFactory; + const canvasAndContext = canvasFactory.create(imgData.bitmap.width, imgData.bitmap.height); + canvasAndContext.context.drawImage(imgData.bitmap, 0, 0); + const imageData = canvasAndContext.context.getImageData(0, 0, imgData.bitmap.width, imgData.bitmap.height); + dataBuff = new Uint8Array(imageData.data.buffer); + } else if (ArrayBuffer.isView(imgData.data)) { + dataBuff = new Uint8Array(imgData.data.buffer, imgData.data.byteOffset, imgData.data.byteLength); + } + if (!dataBuff) { + reject(new Error(`Image object ${name}: data field is empty or invalid. Available fields: ${Object.keys(imgData).join(", ")}`)); + return; + } + if (dataBuff.length === 0) { + reject(new Error(`Image object ${name}: data buffer is empty (length: 0)`)); + return; + } + resolve({ width: imgData.width, height: imgData.height, kind: imgData.kind, data: dataBuff }); + } else { + reject(new Error(`Image object ${name} not found`)); + } + }); + }); + } + async pageToImage(params = {}) { + const info2 = await this.load(); + const result = new PageToImageResult(info2); + if (this.doc === void 0) { + throw new Error("PDF document not loaded"); + } + for (let i = 1; i <= result.total; i++) { + if (this.shouldParse(i, result.total, params)) { + const page = await this.doc.getPage(i); + const canvasFactory = this.doc.canvasFactory; + const viewport = page.getViewport({ scale: 1 }); + const canvasAndContext = canvasFactory.create(viewport.width, viewport.height); + const renderContext = { + canvasContext: canvasAndContext.context, + viewport, + canvas: canvasAndContext.canvas + }; + const renderTask = page.render(renderContext); + await renderTask.promise; + let data; + let dataUrl; + if (typeof canvasAndContext.canvas.toBuffer === "function") { + const nodeBuffer = canvasAndContext.canvas.toBuffer("image/png"); + data = new Uint8Array(nodeBuffer); + const base64 = nodeBuffer.toString("base64"); + dataUrl = `data:image/png;base64,${base64}`; + } else { + dataUrl = canvasAndContext.canvas.toDataURL("image/png"); + const base64 = dataUrl.split(",")[1]; + const binaryString = atob(base64); + data = new Uint8Array(binaryString.length); + for (let i2 = 0; i2 < binaryString.length; i2++) { + data[i2] = binaryString.charCodeAt(i2); + } + } + result.pages.push({ + data, + dataUrl, + pageNumber: i + }); + page.cleanup(); + } + } + await this.doc.destroy(); + this.doc = void 0; + return result; + } + async getTable(params = {}) { + const info2 = await this.load(); + const result = new TableResult(info2); + if (this.doc === void 0) { + throw new Error("PDF document not loaded"); + } + for (let i = 1; i <= result.total; i++) { + if (this.shouldParse(i, result.total, params)) { + const page = await this.doc.getPage(i); + const store = await this.getPageTables(page); + store.normalize(); + const tableDataArr = store.getTableData(); + await this.fillPageTables(page, tableDataArr); + for (const table of tableDataArr) { + const pageTableResult = { num: i, tables: table.toArray() }; + result.pages.push(pageTableResult); + } + page.cleanup(); + } + } + await this.doc.destroy(); + return result; + } + getPathGeometry(mm) { + const width = mm[2] - mm[0]; + const height = mm[3] - mm[1]; + if (mm[0] === Infinity) { + return PathGeometry.undefined; + } + if (width > 5 && height > 5) { + return PathGeometry.rectangle; + } else if (width > 5 && height === 0) { + return PathGeometry.hline; + } else if (width === 0 && height > 5) { + return PathGeometry.vline; + } + return PathGeometry.undefined; + } + async getPageTables(page) { + const lineStore = new LineStore(); + const viewport = page.getViewport({ scale: 1 }); + let transformMatrix = [1, 0, 0, 1, 0, 0]; + const transformStack = []; + const opList = await page.getOperatorList(); + for (let i = 0; i < opList.fnArray.length; i++) { + const fn = opList.fnArray[i]; + const args = opList.argsArray[i]; + const op = args?.[0] ?? 0; + const mm = args?.[2] ?? [Infinity, Infinity, -Infinity, -Infinity]; + if (fn === OPS.constructPath) { + if (op === OPS.fill) ; + if (op !== OPS.stroke) { + continue; + } + const pg = this.getPathGeometry(mm); + if (pg === PathGeometry.rectangle) { + const rect = new Rectangle(new Point(mm[0], mm[1]), mm[2] - mm[0], mm[3] - mm[1]); + rect.transform(transformMatrix); + rect.transform(viewport.transform); + lineStore.addRectangle(rect); + } else if (pg === PathGeometry.hline || pg === PathGeometry.vline) { + const from = new Point(mm[0], mm[1]); + const to = new Point(mm[2], mm[3]); + const line = new Line(from, to); + line.transform(transformMatrix); + line.transform(viewport.transform); + lineStore.add(line); + } else ; + } else if (fn === OPS.setLineWidth) ; + else if (fn === OPS.save) { + transformStack.push(transformMatrix); + } else if (fn === OPS.restore) { + const restoredMatrix = transformStack.pop(); + if (restoredMatrix) { + transformMatrix = restoredMatrix; + } + } else if (fn === OPS.transform) { + transformMatrix = Util.transform(transformMatrix, args); + } + } + return lineStore; + } + // private async getPageGeometry(page: PDFPageProxy): Promise { + // const lineStore: LineStore = new LineStore(); + // const opList = await page.getOperatorList(); + // const viewport = page.getViewport({ scale: 1 }); + // let transformMatrix = [1, 0, 0, 1, 0, 0]; + // const transformStack: Array> = []; + // let current_x: number = 0; + // let current_y: number = 0; + // for (let j = 0; j < opList.fnArray.length; j++) { + // const fn = opList.fnArray[j]; + // const args = opList.argsArray[j]; + // if (fn === pdfjs.OPS.constructPath) { + // while (args[0].length) { + // const op = args[0].shift(); + // const combinedMatrix = pdfjs.Util.transform(viewport.transform, transformMatrix); + // if (op === pdfjs.OPS.rectangle) { + // const x = args[1].shift(); + // const y = args[1].shift(); + // const width = args[1].shift(); + // const height = args[1].shift(); + // if (Math.min(width, height) <= 2) { + // // TODO remove + // debugger; + // } + // const rect = new Rectangle(new Point(x, y), width, height); + // rect.transform(combinedMatrix); + // //rect.transform(viewport.transform); + // lineStore.addRectangle(rect); + // } else if (op === pdfjs.OPS.moveTo) { + // current_x = args[1].shift(); + // current_y = args[1].shift(); + // } else if (op === pdfjs.OPS.lineTo) { + // const x = args[1].shift(); + // const y = args[1].shift(); + // //default trasform + // const from = new Point(current_x, current_y); + // const to = new Point(x, y); + // const line = new Line(from, to); + // line.transform(combinedMatrix); + // //line.transform(viewport.transform); + // // // viewport transform + // // const _from = viewport.convertToViewportPoint(line.from.x, line.from.y) + // // const _to = viewport.convertToViewportPoint(line.to.x, line.to.y) + // // + // // const transformedLine = new Line(new Point(_from[0], _from[1]), new Point(_to[0], _to[1])) + // lineStore.add(line); + // current_x = x; + // current_y = y; + // } + // } + // } else if (fn === pdfjs.OPS.save) { + // transformStack.push(transformMatrix); + // } else if (fn === pdfjs.OPS.restore) { + // const restoredMatrix = transformStack.pop(); + // if (restoredMatrix) { + // transformMatrix = restoredMatrix; + // } + // } else if (fn === pdfjs.OPS.transform) { + // //transformMatrix = this.transform_fn(transformMatrix, args); + // transformMatrix = pdfjs.Util.transform(transformMatrix, args); + // } + // } + // return lineStore; + // } + async fillPageTables(page, pageTables) { + const viewport = page.getViewport({ scale: 1 }); + const textContent = await page.getTextContent({ + includeMarkedContent: false, + disableNormalization: false + }); + for (const textItem of textContent.items) { + if (!("str" in textItem)) continue; + const tx = Util.transform(Util.transform(viewport.transform, textItem.transform), [1, 0, 0, -1, 0, 0]); + for (const pageTable of pageTables) { + const cell = pageTable.findCell(tx[4], tx[5]); + if (cell) { + cell.text.push(textItem.str); + if (textItem.hasEOL) { + cell.text.push("\n"); + } + break; + } + } + } + } +} +function initPDFJS(workerSrc = void 0) { + if (typeof globalThis.pdfjs === "undefined") { + globalThis.pdfjs = pdfjs; + } + const worker = pdf_worker; + if (GlobalWorkerOptions === null) return; + if (workerSrc !== void 0) { + GlobalWorkerOptions.workerSrc = workerSrc; + return; + } + const isNodeJS2 = typeof process === "object" && `${process}` === "[object process]" && !process.versions.nw && // biome-ignore lint/suspicious/noExplicitAny: + !(process.versions.electron && typeof process.type !== "undefined" && process.type !== "browser"); + if (!isNodeJS2) { + GlobalWorkerOptions.workerSrc = worker; + } +} +async function pdf(data) { + let parser; + if (data instanceof URL) { + parser = new PDFParse({ url: data }); + } else { + parser = new PDFParse({ data }); + } + const text = await parser.getText(); + return text; +} +export { + PDFParse, + initPDFJS, + pdf +}; +//# sourceMappingURL=pdf-parse.es.js.map diff --git a/apps/client/next.lock/lock.json b/apps/client/next.lock/lock.json new file mode 100644 index 00000000..e24b6f94 --- /dev/null +++ b/apps/client/next.lock/lock.json @@ -0,0 +1,4 @@ +{ + "https://cdn.jsdelivr.net/npm/pdf-parse@latest/dist/browser/pdf-parse.es.js": { "integrity": "sha512-2eTbeGze7jo0qJ4BU89ApQzHDlfvhToUH+uhXbRS9q1ypPIm1RHOAZvrdO70S+IwigD8HClaKXiYqJ1DwkYGZw==", "contentType": "application/javascript; charset=utf-8" }, + "version": 1 +} diff --git a/apps/client/package.json b/apps/client/package.json index b2e89db1..cd0bff42 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -24,11 +24,13 @@ "@tanstack/react-query": "^5.80.6", "@woowa-babble/random-nickname": "^1.0.2", "axios": "^1.9.0", + "chart.js": "^4.5.0", "lucide-react": "^0.511.0", "motion": "^12.23.12", "next": "15.3.2", "posthog-js": "^1.257.0", "react": "^19.0.0", + "react-chartjs-2": "^5.3.0", "react-dom": "^19.0.0", "react-hook-form": "^7.59.0", "zod": "^3.25.74" diff --git a/apps/client/public/kokomenReport.png b/apps/client/public/kokomenReport.png new file mode 100644 index 00000000..bbba3566 Binary files /dev/null and b/apps/client/public/kokomenReport.png differ diff --git a/apps/client/src/domains/resume/api/index.ts b/apps/client/src/domains/resume/api/index.ts new file mode 100644 index 00000000..b8d7b3df --- /dev/null +++ b/apps/client/src/domains/resume/api/index.ts @@ -0,0 +1,17 @@ +import { mapToCamelCase } from "@/utils/convertConvention"; +import { ResumeInput, ResumeOutput } from "@kokomen/types"; +import axios from "axios"; + +const resumeServerInstance = axios.create({ + baseURL: process.env.NEXT_PUBLIC_V3_API_BASE_URL + "/resume", + withCredentials: true +}); + +function submitResumeEvaluation(data: ResumeInput) { + return resumeServerInstance + .post("/evaluation", data) + .then((res) => res.data) + .then(mapToCamelCase); +} + +export { submitResumeEvaluation }; diff --git a/apps/client/src/domains/resume/components/index.ts b/apps/client/src/domains/resume/components/index.ts new file mode 100644 index 00000000..a12a663f --- /dev/null +++ b/apps/client/src/domains/resume/components/index.ts @@ -0,0 +1,3 @@ +export { default as ResumeSelectMenu3d } from "./resumeSelectMenu3d"; +export { default as ResumeSelectMenuNormal } from "./resumeSelectMenuNormal"; +export { default as ResumeEvaluationResult } from "./resumeEvaluationResult"; diff --git a/apps/client/src/domains/resume/components/resumeEvaluationForm.tsx b/apps/client/src/domains/resume/components/resumeEvaluationForm.tsx new file mode 100644 index 00000000..a849ed62 --- /dev/null +++ b/apps/client/src/domains/resume/components/resumeEvaluationForm.tsx @@ -0,0 +1,218 @@ +import { submitResumeEvaluation } from "@/domains/resume/api"; +import { withApiErrorCapture } from "@/utils/error"; +import { parsePdf } from "@/utils/pdf"; +import { standardSchemaResolver } from "@hookform/resolvers/standard-schema"; +import { + CamelCasedProperties, + ResumeInput, + ResumeOutput +} from "@kokomen/types"; +import { Button, FileField, Input, useToast } from "@kokomen/ui"; +import { useMutation } from "@tanstack/react-query"; +import { isAxiosError } from "axios"; +import Image from "next/image"; +import { useRouter } from "next/navigation"; +import { Dispatch, SetStateAction, useState } from "react"; +import { useForm } from "react-hook-form"; +import z from "zod"; + +const ResumeEvaluationLoading = () => ( +
+ kokomenReport +
+

보고서를 생성하는 중이에요. 잠시만 기다려주세요.

+

최대 1분까지 소요될 수 있어요

+
+
+); + +const jobCareers = ["0-1년", "1-3년", "3-5년", "5-10년", "10년 이상"]; +const resumeEvalFormFields = z.object({ + resume: z.instanceof(FileList).refine((fileList) => fileList.length > 0, { + message: "이력서를 업로드해주세요" + }), + portfolio: z.instanceof(FileList).optional(), + job_position: z.string().nonempty({ message: "지원 직무를 입력해주세요" }), + job_description: z.string().optional(), + job_career: z.enum(jobCareers as [string, ...string[]]).default("0-1년") +}); +type ResumeEvalFormFields = z.infer; + +export default function ResumeEvaluationForm({ + setResult +}: { + setResult: Dispatch< + SetStateAction | null> + >; +}) { + const { toast } = useToast(); + const form = useForm({ + resolver: standardSchemaResolver(resumeEvalFormFields), + defaultValues: { + job_career: "0-1년" + } + }); + const router = useRouter(); + const mutation = useMutation< + CamelCasedProperties, + Error, + ResumeInput + >({ + mutationFn: (data) => submitResumeEvaluation(data), + onSuccess: (data) => setResult(data), + onError: withApiErrorCapture((error) => { + if (isAxiosError(error) && error.response?.status === 401) { + router.replace("/login?redirectTo=/resume/eval"); + return; + } else { + toast({ + title: "이력서 분석 실패", + description: + "이력서 분석 중 오류가 발생했어요. 잠시 후 다시 시도해주세요", + variant: "error" + }); + } + }) + }); + const [isParsing, setIsParsing] = useState(false); + + async function onSubmit(data: ResumeEvalFormFields) { + try { + setIsParsing(true); + let resume = ""; + let portfolio = ""; + if (data.portfolio && data.portfolio?.length > 0) { + const parsedFiles = await parsePdf([ + data.resume[0], + data.portfolio[0] + ] as File[]); + resume = parsedFiles[0]; + portfolio = parsedFiles[1]; + } else { + resume = await parsePdf(data.resume[0] as File); + } + + mutation.mutate({ + resume: resume, + portfolio: portfolio, + job_position: data.job_position, + job_description: data.job_description || "", + job_career: data.job_career + }); + } catch (error) { + console.log(error); + } finally { + setIsParsing(false); + } + } + + const isPending = isParsing || mutation.isPending; + + return ( +
+
+
+

이력서 평가

+

+ 이력서와 포트폴리오를 업로드하고, 지원하려는 직무 정보를 + 입력해주세요. +

+
+ +
+
+ + + + +
+ + + {form.formState.errors.job_position && ( +

+ {form.formState.errors.job_position.message} +

+ )} +
+ +
+ +
+ {jobCareers.map((career) => ( + + ))} +
+
+ +
+ +